From dacb6c0998f0fbc7bd0a361f6cca3063cea6aab9 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 6 Jan 2025 17:17:25 +0000 Subject: [PATCH] feat(subcommand): add subcommand support (#644) --- src/commands/build-module.ts | 63 ------------------------------------ src/commands/index.ts | 35 ++++++++++---------- src/main.ts | 30 +++++++++++++++++ 3 files changed, 47 insertions(+), 81 deletions(-) delete mode 100644 src/commands/build-module.ts diff --git a/src/commands/build-module.ts b/src/commands/build-module.ts deleted file mode 100644 index 3a870d1d..00000000 --- a/src/commands/build-module.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { defineCommand } from 'citty' -import { resolve } from 'pathe' -import { readPackageJSON } from 'pkg-types' -import { x } from 'tinyexec' - -import { logger } from '../utils/logger' -import { cwdArgs, legacyRootDirArgs, logLevelArgs } from './_shared' - -const MODULE_BUILDER_PKG = '@nuxt/module-builder' - -export default defineCommand({ - meta: { - name: 'build-module', - description: `Helper command for using ${MODULE_BUILDER_PKG}`, - }, - args: { - ...cwdArgs, - ...logLevelArgs, - ...legacyRootDirArgs, - stub: { - type: 'boolean', - description: 'Stub dist instead of actually building it for development', - }, - sourcemap: { - type: 'boolean', - description: 'Generate sourcemaps', - }, - prepare: { - type: 'boolean', - description: 'Prepare module for local development', - }, - }, - async run(ctx) { - // Find local installed version - const cwd = resolve(ctx.args.cwd || ctx.args.rootDir) - - const hasLocal = await readPackageJSON(MODULE_BUILDER_PKG, { url: cwd }).catch(() => false) - - const execArgs = Object.entries({ - '--stub': ctx.args.stub, - '--sourcemap': ctx.args.sourcemap, - '--prepare': ctx.args.prepare, - }) - .filter(([, value]) => value) - .map(([key]) => key) - - let cmd = 'nuxt-module-build' - if (!hasLocal) { - logger.warn( - `Cannot find locally installed version of \`${MODULE_BUILDER_PKG}\` (>=0.2.0). Falling back to \`npx ${MODULE_BUILDER_PKG}\``, - ) - cmd = 'npx' - execArgs.unshift(MODULE_BUILDER_PKG) - } - - await x(cmd, execArgs, { - nodeOptions: { - cwd, - stdio: 'inherit', - }, - }) - }, -}) diff --git a/src/commands/index.ts b/src/commands/index.ts index a3462443..416196fe 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -3,22 +3,21 @@ import type { CommandDef } from 'citty' const _rDefault = (r: any) => (r.default || r) as Promise export const commands = { - 'add': () => import('./add').then(_rDefault), - 'analyze': () => import('./analyze').then(_rDefault), - 'build-module': () => import('./build-module').then(_rDefault), - 'build': () => import('./build').then(_rDefault), - 'cleanup': () => import('./cleanup').then(_rDefault), - '_dev': () => import('./dev-child').then(_rDefault), - 'dev': () => import('./dev').then(_rDefault), - 'devtools': () => import('./devtools').then(_rDefault), - 'generate': () => import('./generate').then(_rDefault), - 'info': () => import('./info').then(_rDefault), - 'init': () => import('./init').then(_rDefault), - 'module': () => import('./module').then(_rDefault), - 'prepare': () => import('./prepare').then(_rDefault), - 'preview': () => import('./preview').then(_rDefault), - 'start': () => import('./preview').then(_rDefault), - 'test': () => import('./test').then(_rDefault), - 'typecheck': () => import('./typecheck').then(_rDefault), - 'upgrade': () => import('./upgrade').then(_rDefault), + add: () => import('./add').then(_rDefault), + analyze: () => import('./analyze').then(_rDefault), + build: () => import('./build').then(_rDefault), + cleanup: () => import('./cleanup').then(_rDefault), + _dev: () => import('./dev-child').then(_rDefault), + dev: () => import('./dev').then(_rDefault), + devtools: () => import('./devtools').then(_rDefault), + generate: () => import('./generate').then(_rDefault), + info: () => import('./info').then(_rDefault), + init: () => import('./init').then(_rDefault), + module: () => import('./module').then(_rDefault), + prepare: () => import('./prepare').then(_rDefault), + preview: () => import('./preview').then(_rDefault), + start: () => import('./preview').then(_rDefault), + test: () => import('./test').then(_rDefault), + typecheck: () => import('./typecheck').then(_rDefault), + upgrade: () => import('./upgrade').then(_rDefault), } as const diff --git a/src/main.ts b/src/main.ts index 2919737c..20b1c7eb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,7 +1,12 @@ +import { resolve } from 'node:path' +import process from 'node:process' + import { defineCommand } from 'citty' import { provider } from 'std-env' + import nuxiPkg from '../package.json' assert { type: 'json' } import { commands } from './commands' +import { cwdArgs } from './commands/_shared' import { setupGlobalConsole } from './utils/console' import { checkEngines } from './utils/engines' import { logger } from './utils/logger' @@ -12,6 +17,12 @@ export const main = defineCommand({ version: nuxiPkg.version, description: nuxiPkg.description, }, + args: { + ...cwdArgs, + command: { + type: 'positional', + }, + }, subCommands: commands, async setup(ctx) { const command = ctx.args._[0] @@ -30,5 +41,24 @@ export const main = defineCommand({ if (command === 'init') { await backgroundTasks } + + // allow running arbitrary commands if there's a locally registered binary with `nuxt-` prefix + if (ctx.args.command && !(ctx.args.command in commands)) { + const cwd = resolve(ctx.args.cwd) + try { + const { x } = await import('tinyexec') + // `tinyexec` will resolve command from local binaries + await x(`nuxt-${ctx.args.command}`, ctx.args._.slice(1), { + nodeOptions: { stdio: 'inherit', cwd }, + throwOnError: true, + }) + } + catch (err) { + if (err instanceof Error && 'code' in err && err.code === 'ENOENT') { + return + } + } + process.exit() + } }, })