Skip to content

Commit bfa1dd4

Browse files
committed
feat: auto-install validation library deps
1 parent 46307d8 commit bfa1dd4

File tree

1 file changed

+42
-3
lines changed

1 file changed

+42
-3
lines changed

src/wizard/shelve-setup.ts

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import type { Nuxt } from '@nuxt/schema'
22
import type { ConsolaInstance } from 'consola'
3+
import { exec } from 'node:child_process'
34
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
45
import { homedir } from 'node:os'
56
import { join, resolve } from 'node:path'
67
import process from 'node:process'
8+
import { promisify } from 'node:util'
79
import { consola } from 'consola'
810
import { builders, loadFile, writeFile } from 'magicast'
911
import { getDefaultExportOptions } from 'magicast/helpers'
1012
import { $fetch } from 'ofetch'
1113
import { getPrefix, toCamelCase } from '../utils/transform'
1214

15+
const execAsync = promisify(exec)
16+
1317
const SHELVE_RC_PATH = join(homedir(), '.shelve')
1418
const DEFAULT_URL = 'https://app.shelve.cloud'
1519

@@ -86,6 +90,34 @@ function detectValidationLibrary(rootDir: string): ValidationLibrary | null {
8690
catch { return null }
8791
}
8892

93+
function detectPackageManager(rootDir: string): 'pnpm' | 'yarn' | 'npm' {
94+
if (existsSync(join(rootDir, 'pnpm-lock.yaml')))
95+
return 'pnpm'
96+
if (existsSync(join(rootDir, 'yarn.lock')))
97+
return 'yarn'
98+
return 'npm'
99+
}
100+
101+
async function installValidationLibrary(rootDir: string, library: ValidationLibrary, logger: ConsolaInstance): Promise<void> {
102+
const pm = detectPackageManager(rootDir)
103+
const packages = library === 'valibot'
104+
? ['valibot', '@valibot/to-json-schema']
105+
: ['zod']
106+
107+
const cmd = pm === 'npm'
108+
? `npm install ${packages.join(' ')}`
109+
: `${pm} add ${packages.join(' ')}`
110+
111+
logger.info(`Installing ${packages.join(', ')}...`)
112+
try {
113+
await execAsync(cmd, { cwd: rootDir })
114+
logger.success(`Installed ${library} dependencies`)
115+
}
116+
catch (error) {
117+
logger.error(`Failed to install dependencies: ${error}`)
118+
}
119+
}
120+
89121
function countPrefixes(keys: string[]): Map<string, number> {
90122
const counts = new Map<string, number>()
91123
for (const key of keys) {
@@ -377,6 +409,7 @@ export async function runShelveWizard(nuxt: Nuxt): Promise<void> {
377409

378410
// 1. Detect or ask for validation library
379411
let library: ValidationLibrary | null = detectValidationLibrary(nuxt.options.rootDir)
412+
let needsInstall = false
380413
if (library) {
381414
logger.info(`Detected ${library} for schema validation`)
382415
}
@@ -394,6 +427,7 @@ export async function runShelveWizard(nuxt: Nuxt): Promise<void> {
394427
}
395428
else {
396429
library = choice as ValidationLibrary
430+
needsInstall = true
397431
}
398432
}
399433

@@ -431,14 +465,19 @@ export async function runShelveWizard(nuxt: Nuxt): Promise<void> {
431465
}
432466
}
433467

434-
// 3. Generate schema (only if library selected)
435-
let schemaCode: { imports: string, schema: string } | null = null
468+
// 3. Install validation library if needed
469+
if (library && needsInstall) {
470+
await installValidationLibrary(nuxt.options.rootDir, library, logger)
471+
}
472+
473+
// 4. Generate schema (only if library selected)
474+
let schemaCode: { imports: string, schemaExpr: string } | null = null
436475
if (library) {
437476
const keys = variables.length > 0 ? variables.map(v => v.key) : null
438477
schemaCode = generateSchemaCode(keys, library)
439478
}
440479

441-
// 4. Only update config if we have something to add
480+
// 5. Only update config if we have something to add
442481
if (!schemaCode && !shelveConfig) {
443482
logger.info('No configuration changes needed')
444483
return

0 commit comments

Comments
 (0)