@nexical/cli-core 0.1.12 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-Z3YJLRUV.js → chunk-3OQ5T2ZX.js} +2 -1
- package/dist/chunk-3OQ5T2ZX.js.map +1 -0
- package/dist/{chunk-TCK2GYT7.js → chunk-BZD5CM3C.js} +2 -2
- package/dist/{chunk-TCK2GYT7.js.map → chunk-BZD5CM3C.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.js +2 -2
- package/dist/src/BaseCommand.d.ts +1 -0
- package/dist/src/BaseCommand.js +1 -1
- package/dist/src/CLI.js +1 -1
- package/dist/src/commands/help.js +5 -1
- package/dist/src/commands/help.js.map +1 -1
- package/package.json +2 -2
- package/src/BaseCommand.ts +1 -0
- package/src/commands/help.ts +5 -0
- package/test/unit/commands/help.test.ts +25 -0
- package/dist/chunk-Z3YJLRUV.js.map +0 -1
|
@@ -14,6 +14,7 @@ import { consola } from "consola";
|
|
|
14
14
|
var BaseCommand = class {
|
|
15
15
|
static usage = "";
|
|
16
16
|
static description = "";
|
|
17
|
+
static help = "";
|
|
17
18
|
static args = {};
|
|
18
19
|
// Configurable flags
|
|
19
20
|
static requiresProject = false;
|
|
@@ -80,4 +81,4 @@ var BaseCommand = class {
|
|
|
80
81
|
export {
|
|
81
82
|
BaseCommand
|
|
82
83
|
};
|
|
83
|
-
//# sourceMappingURL=chunk-
|
|
84
|
+
//# sourceMappingURL=chunk-3OQ5T2ZX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/BaseCommand.ts"],"sourcesContent":["import { logger } from './utils/logger.js';\nimport { CommandDefinition, CommandInterface } from './CommandInterface.js';\nimport { findProjectRoot, loadConfig } from './utils/config.js';\nimport process from 'node:process';\nimport pc from 'picocolors';\nimport { consola } from 'consola';\n\nexport abstract class BaseCommand implements CommandInterface {\n static usage = '';\n static description = '';\n static help = '';\n static args: CommandDefinition = {};\n\n // Configurable flags\n static requiresProject = false;\n\n protected projectRoot: string | null = null;\n protected config: any = {};\n protected globalOptions: any = {};\n protected cli: any = null;\n\n\n constructor(cli: any, globalOptions: any = {}) {\n this.globalOptions = globalOptions;\n this.cli = cli;\n }\n\n async init() {\n // 1. Root detection strategy\n if (this.globalOptions.rootDir) {\n this.projectRoot = this.globalOptions.rootDir;\n } else {\n this.projectRoot = await findProjectRoot(this.cli.name, process.cwd());\n }\n\n if (this.projectRoot) {\n this.config = await loadConfig(this.cli.name, this.projectRoot);\n logger.debug(`Loaded config from ${this.projectRoot}`);\n }\n }\n\n async runInit(options: any): Promise<void> {\n const requiresProject = (this.constructor as any).requiresProject;\n if (requiresProject && !this.projectRoot) {\n this.error(`This command requires to be run within an app project (${this.cli.name}.yml not found).`, 1);\n return;\n }\n await this.run(options);\n }\n\n abstract run(options: any): Promise<void>;\n\n // Helpers\n success(msg: string) {\n console.log(pc.green('✔ ' + msg));\n }\n\n notice(msg: string) {\n console.log(pc.blue('📢 ' + msg));\n }\n\n input(msg: string) {\n console.log(pc.cyan('? ' + msg));\n }\n\n info(msg: string) {\n console.log(msg);\n }\n\n warn(msg: string) {\n console.log(pc.yellow('⚠ ' + msg));\n }\n\n error(msg: string | Error, code = 1) {\n if (msg instanceof Error) {\n console.log(pc.red('✖ ' + msg.message));\n if (this.globalOptions.debug) {\n logger.error(msg.stack);\n }\n } else {\n console.log(pc.red('✖ ' + msg));\n }\n process.exit(code);\n }\n\n async prompt(msg: string): Promise<string> {\n const response = await consola.prompt(msg, { type: 'text' });\n return response as string;\n }\n}\n"],"mappings":";;;;;;;;;;AAGA,OAAO,aAAa;AACpB,OAAO,QAAQ;AACf,SAAS,eAAe;AAEjB,IAAe,cAAf,MAAuD;AAAA,EAC1D,OAAO,QAAQ;AAAA,EACf,OAAO,cAAc;AAAA,EACrB,OAAO,OAAO;AAAA,EACd,OAAO,OAA0B,CAAC;AAAA;AAAA,EAGlC,OAAO,kBAAkB;AAAA,EAEf,cAA6B;AAAA,EAC7B,SAAc,CAAC;AAAA,EACf,gBAAqB,CAAC;AAAA,EACtB,MAAW;AAAA,EAGrB,YAAY,KAAU,gBAAqB,CAAC,GAAG;AAC3C,SAAK,gBAAgB;AACrB,SAAK,MAAM;AAAA,EACf;AAAA,EAEA,MAAM,OAAO;AAET,QAAI,KAAK,cAAc,SAAS;AAC5B,WAAK,cAAc,KAAK,cAAc;AAAA,IAC1C,OAAO;AACH,WAAK,cAAc,MAAM,gBAAgB,KAAK,IAAI,MAAM,QAAQ,IAAI,CAAC;AAAA,IACzE;AAEA,QAAI,KAAK,aAAa;AAClB,WAAK,SAAS,MAAM,WAAW,KAAK,IAAI,MAAM,KAAK,WAAW;AAC9D,aAAO,MAAM,sBAAsB,KAAK,WAAW,EAAE;AAAA,IACzD;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ,SAA6B;AACvC,UAAM,kBAAmB,KAAK,YAAoB;AAClD,QAAI,mBAAmB,CAAC,KAAK,aAAa;AACtC,WAAK,MAAM,0DAA0D,KAAK,IAAI,IAAI,oBAAoB,CAAC;AACvG;AAAA,IACJ;AACA,UAAM,KAAK,IAAI,OAAO;AAAA,EAC1B;AAAA;AAAA,EAKA,QAAQ,KAAa;AACjB,YAAQ,IAAI,GAAG,MAAM,YAAO,GAAG,CAAC;AAAA,EACpC;AAAA,EAEA,OAAO,KAAa;AAChB,YAAQ,IAAI,GAAG,KAAK,eAAQ,GAAG,CAAC;AAAA,EACpC;AAAA,EAEA,MAAM,KAAa;AACf,YAAQ,IAAI,GAAG,KAAK,OAAO,GAAG,CAAC;AAAA,EACnC;AAAA,EAEA,KAAK,KAAa;AACd,YAAQ,IAAI,GAAG;AAAA,EACnB;AAAA,EAEA,KAAK,KAAa;AACd,YAAQ,IAAI,GAAG,OAAO,YAAO,GAAG,CAAC;AAAA,EACrC;AAAA,EAEA,MAAM,KAAqB,OAAO,GAAG;AACjC,QAAI,eAAe,OAAO;AACtB,cAAQ,IAAI,GAAG,IAAI,YAAO,IAAI,OAAO,CAAC;AACtC,UAAI,KAAK,cAAc,OAAO;AAC1B,eAAO,MAAM,IAAI,KAAK;AAAA,MAC1B;AAAA,IACJ,OAAO;AACH,cAAQ,IAAI,GAAG,IAAI,YAAO,GAAG,CAAC;AAAA,IAClC;AACA,YAAQ,KAAK,IAAI;AAAA,EACrB;AAAA,EAEA,MAAM,OAAO,KAA8B;AACvC,UAAM,WAAW,MAAM,QAAQ,OAAO,KAAK,EAAE,MAAM,OAAO,CAAC;AAC3D,WAAO;AAAA,EACX;AACJ;","names":[]}
|
|
@@ -17,7 +17,7 @@ import pc from "picocolors";
|
|
|
17
17
|
// package.json
|
|
18
18
|
var package_default = {
|
|
19
19
|
name: "@nexical/cli-core",
|
|
20
|
-
version: "0.1.
|
|
20
|
+
version: "0.1.13",
|
|
21
21
|
type: "module",
|
|
22
22
|
main: "dist/index.js",
|
|
23
23
|
types: "dist/index.d.ts",
|
|
@@ -272,4 +272,4 @@ var CLI = class {
|
|
|
272
272
|
export {
|
|
273
273
|
CLI
|
|
274
274
|
};
|
|
275
|
-
//# sourceMappingURL=chunk-
|
|
275
|
+
//# sourceMappingURL=chunk-BZD5CM3C.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/CLI.ts","../package.json"],"sourcesContent":["import { cac } from 'cac';\nimport { CommandLoader } from './CommandLoader.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport pc from 'picocolors';\nimport pkg from '../package.json';\nimport { logger, setDebugMode } from './utils/logger.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface CLIConfig {\n version?: string;\n commandName?: string;\n searchDirectories?: string[];\n}\n\nexport class CLI {\n public name: string;\n public version: string;\n private cli: ReturnType<typeof cac>;\n private loader: CommandLoader;\n private HelpCommandClass: any;\n private config: CLIConfig;\n\n constructor(config: CLIConfig = {}) {\n this.config = config;\n this.name = this.config.commandName || 'app';\n this.version = this.config.version || pkg.version;\n this.cli = cac(this.name);\n this.loader = new CommandLoader(this);\n }\n\n private loadedCommands: any[] = [];\n\n getCommands() {\n return this.loadedCommands;\n }\n\n getRawCLI() {\n return this.cli;\n }\n\n async start() {\n if (process.argv.includes('--debug')) {\n setDebugMode(true);\n logger.debug('Debug mode enabled via --debug flag');\n }\n\n let commandsDirs: string[] = [];\n\n if (this.config.searchDirectories && this.config.searchDirectories.length > 0) {\n commandsDirs = [...this.config.searchDirectories];\n } else {\n const possibleDirs = [\n path.resolve(__dirname, './src/commands'),\n path.resolve(process.cwd(), 'commands') // Fallback relative to cwd\n ];\n\n for (const dir of possibleDirs) {\n if (fs.existsSync(dir)) {\n commandsDirs.push(dir);\n }\n }\n }\n\n // Always add core commands directory (where help command lives)\n const coreCommandsDir = path.resolve(__dirname, './commands');\n const coreCommandsDirSrc = path.resolve(__dirname, './src/commands');\n\n if (fs.existsSync(coreCommandsDir)) {\n commandsDirs.push(coreCommandsDir);\n } else if (fs.existsSync(coreCommandsDirSrc)) {\n // Fallback for tsup chunking which puts CLI in dist/ but keeps src/commands in dist/src/commands\n commandsDirs.push(coreCommandsDirSrc);\n }\n\n // Fallback or error\n if (commandsDirs.length === 0) {\n logger.debug(\"No commands directory found.\");\n }\n\n for (const dir of commandsDirs) {\n // Loader accumulates commands\n await this.loader.load(dir);\n }\n this.loadedCommands = this.loader.getCommands();\n\n // Group commands by root command name\n const commandGroups: Record<string, any[]> = {};\n // Locate HelpCommand for fallback usage\n const helpCmd = this.loadedCommands.find(c => c.command === 'help');\n if (helpCmd) {\n this.HelpCommandClass = helpCmd.class;\n }\n\n for (const cmd of this.loadedCommands) {\n const root = cmd.command.split(' ')[0];\n if (!commandGroups[root]) commandGroups[root] = [];\n commandGroups[root].push(cmd);\n }\n\n for (const [root, cmds] of Object.entries(commandGroups)) {\n // Case 1: Single command, no subcommands (e.g. 'init')\n if (cmds.length === 1 && cmds[0].command === root) {\n const cmd = cmds[0];\n const CommandClass = cmd.class;\n // Original logic for single command\n let commandName = cmd.command;\n const argsDef = CommandClass.args || {};\n if (argsDef.args) {\n argsDef.args.forEach((arg: any) => {\n const isVariadic = arg.name.endsWith('...');\n const cleanName = isVariadic ? arg.name.slice(0, -3) : arg.name;\n // Always use optional brackets [] for CAC to allow --help to pass validation\n // We will enforce 'required' manually in the action handler\n commandName += isVariadic ? ` [...${cleanName}]` : ` [${cleanName}]`;\n });\n }\n const cacCommand = this.cli.command(commandName, CommandClass.description || '');\n\n // Register options\n if (argsDef.options) {\n argsDef.options.forEach((opt: any) => {\n cacCommand.option(opt.name, opt.description, { default: opt.default });\n });\n }\n this.registerGlobalOptions(cacCommand);\n\n cacCommand.action(async (...args: any[]) => {\n const options = args.pop();\n\n if (options.help) {\n await this.runHelp([cmd.command]);\n return;\n }\n\n const positionalArgs = args;\n\n if (argsDef.args) {\n argsDef.args.forEach((arg: any, index: number) => {\n const isVariadic = arg.name.endsWith('...');\n const name = isVariadic ? arg.name.slice(0, -3) : arg.name;\n const val = positionalArgs[index];\n\n if (val !== undefined) {\n options[name] = val;\n } else if (arg.required) {\n console.error(pc.red(`Missing required argument: ${name}`));\n this.runHelp([cmd.command]).then(() => process.exit(1));\n return;\n }\n });\n }\n await this.runCommand(CommandClass, options, [cmd.command]);\n });\n } else {\n // Case 2: Command with subcommands (e.g. 'module add')\n // Register 'module <subcommand>' catch-all\n const commandName = `${root} [subcommand] [...args]`;\n const cacCommand = this.cli.command(commandName, `Manage ${root} commands`);\n\n cacCommand.allowUnknownOptions(); // Pass options to subcommand\n this.registerGlobalOptions(cacCommand);\n\n cacCommand.action(async (subcommand: string, ...args: any[]) => {\n const options = args.pop(); // last is options\n\n if (!subcommand || options.help) {\n await this.runHelp([root, subcommand].filter(Boolean));\n return;\n }\n\n\n // Find matching command\n // Match against \"root subcommand\"\n const fullCommandName = `${root} ${subcommand}`;\n const cmd = cmds.find(c => c.command === fullCommandName);\n\n if (!cmd) {\n console.error(pc.red(`Unknown subcommand '${subcommand}' for '${root}'`));\n process.exit(1);\n }\n\n const CommandClass = cmd.class;\n const argsDef = CommandClass.args || {};\n const positionalArgs = (args.length > 0 && Array.isArray(args[0])) ? args[0] : args;\n\n const childOptions = { ...options }; // Copy options\n\n const cmdParts = [root, subcommand];\n\n if (argsDef.args) {\n argsDef.args.forEach((arg: any, index: number) => {\n const isVariadic = arg.name.endsWith('...');\n const name = isVariadic ? arg.name.slice(0, -3) : arg.name;\n const val = positionalArgs[index];\n\n if (val !== undefined) {\n if (isVariadic) {\n childOptions[name] = positionalArgs.slice(index);\n } else {\n childOptions[name] = val;\n }\n } else if (arg.required) {\n console.error(pc.red(`Missing required argument: ${name}`));\n this.runHelp(cmdParts).then(() => process.exit(1));\n return;\n }\n });\n }\n\n if (argsDef.options) {\n argsDef.options.forEach((opt: any) => {\n const name = opt.name.replace(/^-+/, ''); // remove leading dashes\n const camelName = name.split(' ')[0].replace(/-([a-z])/g, (g: string) => g[1].toUpperCase());\n\n // Check both raw name and camelCase name\n // CAC usually provides camelCase options\n if (childOptions[camelName] === undefined && opt.default !== undefined) {\n childOptions[camelName] = opt.default;\n }\n });\n }\n\n await this.runCommand(CommandClass, childOptions, cmdParts);\n });\n }\n }\n\n // Manually register global help to ensure it's allowed\n this.cli.option('--help, -h', 'Display help');\n\n this.cli.version(this.version);\n\n if (process.argv.includes('--help') || process.argv.includes('-h')) {\n // Inspect non-option args to see if there's a command?\n const args = process.argv.slice(2).filter(a => !a.startsWith('-'));\n if (args.length === 0) {\n await this.runHelp([]);\n process.exit(0);\n }\n }\n\n try {\n this.cli.parse();\n } catch (e: any) {\n console.error(pc.red(e.message));\n\n // Try to provide helpful context\n console.log('');\n // Simple heuristic: find first non-flag arg as command\n const args = process.argv.slice(2);\n const potentialCommand = args.find(a => !a.startsWith('-'));\n const helpArgs = potentialCommand ? [potentialCommand] : [];\n await this.runHelp(helpArgs);\n\n process.exit(1);\n }\n }\n\n private registerGlobalOptions(cacCommand: any) {\n cacCommand.option('--root-dir <path>', 'Override project root');\n cacCommand.option('--debug', 'Enable debug mode');\n cacCommand.option('--help, -h', 'Display help message');\n }\n\n private async runHelp(commandParts: string[]) {\n if (this.HelpCommandClass) {\n const helpInstance = new this.HelpCommandClass(this);\n await helpInstance.run({ command: commandParts });\n } else {\n // Fallback if HelpCommand not loaded (shouldn't happen)\n this.cli.outputHelp();\n }\n }\n\n private async runCommand(CommandClass: any, options: any, commandParts: string[] = []) {\n try {\n const instance = new CommandClass(this, options);\n await instance.init();\n await instance.runInit(options);\n } catch (e: any) {\n console.error(pc.red(e.message));\n if (options.debug) console.error(e.stack);\n\n console.log(''); // spacer\n await this.runHelp(commandParts);\n\n process.exit(1);\n }\n }\n}\n","{\n \"name\": \"@nexical/cli-core\",\n \"version\": \"0.1.12\",\n \"type\": \"module\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"cli\": \"node dist/cli.js\",\n \"test\": \"npm run test:unit && npm run test:integration && npm run test:e2e\",\n \"test:unit\": \"vitest run --config vitest.config.ts --coverage\",\n \"test:integration\": \"vitest run --config vitest.integration.config.ts\",\n \"test:e2e\": \"npm run build && vitest run --config vitest.e2e.config.ts\",\n \"test:watch\": \"vitest\"\n },\n \"dependencies\": {\n \"cac\": \"^6.7.14\",\n \"consola\": \"^3.4.2\",\n \"lilconfig\": \"^3.1.3\",\n \"picocolors\": \"^1.1.1\",\n \"yaml\": \"^2.8.2\",\n \"zod\": \"^3.22.4\"\n },\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/node\": \"^20.10.0\",\n \"@vitest/coverage-v8\": \"^4.0.15\",\n \"execa\": \"^9.6.1\",\n \"fs-extra\": \"^11.3.2\",\n \"tsup\": \"^8.0.1\",\n \"typescript\": \"^5.3.3\",\n \"vitest\": \"^4.0.15\"\n }\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/CLI.ts","../package.json"],"sourcesContent":["import { cac } from 'cac';\nimport { CommandLoader } from './CommandLoader.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { fileURLToPath } from 'node:url';\nimport pc from 'picocolors';\nimport pkg from '../package.json';\nimport { logger, setDebugMode } from './utils/logger.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface CLIConfig {\n version?: string;\n commandName?: string;\n searchDirectories?: string[];\n}\n\nexport class CLI {\n public name: string;\n public version: string;\n private cli: ReturnType<typeof cac>;\n private loader: CommandLoader;\n private HelpCommandClass: any;\n private config: CLIConfig;\n\n constructor(config: CLIConfig = {}) {\n this.config = config;\n this.name = this.config.commandName || 'app';\n this.version = this.config.version || pkg.version;\n this.cli = cac(this.name);\n this.loader = new CommandLoader(this);\n }\n\n private loadedCommands: any[] = [];\n\n getCommands() {\n return this.loadedCommands;\n }\n\n getRawCLI() {\n return this.cli;\n }\n\n async start() {\n if (process.argv.includes('--debug')) {\n setDebugMode(true);\n logger.debug('Debug mode enabled via --debug flag');\n }\n\n let commandsDirs: string[] = [];\n\n if (this.config.searchDirectories && this.config.searchDirectories.length > 0) {\n commandsDirs = [...this.config.searchDirectories];\n } else {\n const possibleDirs = [\n path.resolve(__dirname, './src/commands'),\n path.resolve(process.cwd(), 'commands') // Fallback relative to cwd\n ];\n\n for (const dir of possibleDirs) {\n if (fs.existsSync(dir)) {\n commandsDirs.push(dir);\n }\n }\n }\n\n // Always add core commands directory (where help command lives)\n const coreCommandsDir = path.resolve(__dirname, './commands');\n const coreCommandsDirSrc = path.resolve(__dirname, './src/commands');\n\n if (fs.existsSync(coreCommandsDir)) {\n commandsDirs.push(coreCommandsDir);\n } else if (fs.existsSync(coreCommandsDirSrc)) {\n // Fallback for tsup chunking which puts CLI in dist/ but keeps src/commands in dist/src/commands\n commandsDirs.push(coreCommandsDirSrc);\n }\n\n // Fallback or error\n if (commandsDirs.length === 0) {\n logger.debug(\"No commands directory found.\");\n }\n\n for (const dir of commandsDirs) {\n // Loader accumulates commands\n await this.loader.load(dir);\n }\n this.loadedCommands = this.loader.getCommands();\n\n // Group commands by root command name\n const commandGroups: Record<string, any[]> = {};\n // Locate HelpCommand for fallback usage\n const helpCmd = this.loadedCommands.find(c => c.command === 'help');\n if (helpCmd) {\n this.HelpCommandClass = helpCmd.class;\n }\n\n for (const cmd of this.loadedCommands) {\n const root = cmd.command.split(' ')[0];\n if (!commandGroups[root]) commandGroups[root] = [];\n commandGroups[root].push(cmd);\n }\n\n for (const [root, cmds] of Object.entries(commandGroups)) {\n // Case 1: Single command, no subcommands (e.g. 'init')\n if (cmds.length === 1 && cmds[0].command === root) {\n const cmd = cmds[0];\n const CommandClass = cmd.class;\n // Original logic for single command\n let commandName = cmd.command;\n const argsDef = CommandClass.args || {};\n if (argsDef.args) {\n argsDef.args.forEach((arg: any) => {\n const isVariadic = arg.name.endsWith('...');\n const cleanName = isVariadic ? arg.name.slice(0, -3) : arg.name;\n // Always use optional brackets [] for CAC to allow --help to pass validation\n // We will enforce 'required' manually in the action handler\n commandName += isVariadic ? ` [...${cleanName}]` : ` [${cleanName}]`;\n });\n }\n const cacCommand = this.cli.command(commandName, CommandClass.description || '');\n\n // Register options\n if (argsDef.options) {\n argsDef.options.forEach((opt: any) => {\n cacCommand.option(opt.name, opt.description, { default: opt.default });\n });\n }\n this.registerGlobalOptions(cacCommand);\n\n cacCommand.action(async (...args: any[]) => {\n const options = args.pop();\n\n if (options.help) {\n await this.runHelp([cmd.command]);\n return;\n }\n\n const positionalArgs = args;\n\n if (argsDef.args) {\n argsDef.args.forEach((arg: any, index: number) => {\n const isVariadic = arg.name.endsWith('...');\n const name = isVariadic ? arg.name.slice(0, -3) : arg.name;\n const val = positionalArgs[index];\n\n if (val !== undefined) {\n options[name] = val;\n } else if (arg.required) {\n console.error(pc.red(`Missing required argument: ${name}`));\n this.runHelp([cmd.command]).then(() => process.exit(1));\n return;\n }\n });\n }\n await this.runCommand(CommandClass, options, [cmd.command]);\n });\n } else {\n // Case 2: Command with subcommands (e.g. 'module add')\n // Register 'module <subcommand>' catch-all\n const commandName = `${root} [subcommand] [...args]`;\n const cacCommand = this.cli.command(commandName, `Manage ${root} commands`);\n\n cacCommand.allowUnknownOptions(); // Pass options to subcommand\n this.registerGlobalOptions(cacCommand);\n\n cacCommand.action(async (subcommand: string, ...args: any[]) => {\n const options = args.pop(); // last is options\n\n if (!subcommand || options.help) {\n await this.runHelp([root, subcommand].filter(Boolean));\n return;\n }\n\n\n // Find matching command\n // Match against \"root subcommand\"\n const fullCommandName = `${root} ${subcommand}`;\n const cmd = cmds.find(c => c.command === fullCommandName);\n\n if (!cmd) {\n console.error(pc.red(`Unknown subcommand '${subcommand}' for '${root}'`));\n process.exit(1);\n }\n\n const CommandClass = cmd.class;\n const argsDef = CommandClass.args || {};\n const positionalArgs = (args.length > 0 && Array.isArray(args[0])) ? args[0] : args;\n\n const childOptions = { ...options }; // Copy options\n\n const cmdParts = [root, subcommand];\n\n if (argsDef.args) {\n argsDef.args.forEach((arg: any, index: number) => {\n const isVariadic = arg.name.endsWith('...');\n const name = isVariadic ? arg.name.slice(0, -3) : arg.name;\n const val = positionalArgs[index];\n\n if (val !== undefined) {\n if (isVariadic) {\n childOptions[name] = positionalArgs.slice(index);\n } else {\n childOptions[name] = val;\n }\n } else if (arg.required) {\n console.error(pc.red(`Missing required argument: ${name}`));\n this.runHelp(cmdParts).then(() => process.exit(1));\n return;\n }\n });\n }\n\n if (argsDef.options) {\n argsDef.options.forEach((opt: any) => {\n const name = opt.name.replace(/^-+/, ''); // remove leading dashes\n const camelName = name.split(' ')[0].replace(/-([a-z])/g, (g: string) => g[1].toUpperCase());\n\n // Check both raw name and camelCase name\n // CAC usually provides camelCase options\n if (childOptions[camelName] === undefined && opt.default !== undefined) {\n childOptions[camelName] = opt.default;\n }\n });\n }\n\n await this.runCommand(CommandClass, childOptions, cmdParts);\n });\n }\n }\n\n // Manually register global help to ensure it's allowed\n this.cli.option('--help, -h', 'Display help');\n\n this.cli.version(this.version);\n\n if (process.argv.includes('--help') || process.argv.includes('-h')) {\n // Inspect non-option args to see if there's a command?\n const args = process.argv.slice(2).filter(a => !a.startsWith('-'));\n if (args.length === 0) {\n await this.runHelp([]);\n process.exit(0);\n }\n }\n\n try {\n this.cli.parse();\n } catch (e: any) {\n console.error(pc.red(e.message));\n\n // Try to provide helpful context\n console.log('');\n // Simple heuristic: find first non-flag arg as command\n const args = process.argv.slice(2);\n const potentialCommand = args.find(a => !a.startsWith('-'));\n const helpArgs = potentialCommand ? [potentialCommand] : [];\n await this.runHelp(helpArgs);\n\n process.exit(1);\n }\n }\n\n private registerGlobalOptions(cacCommand: any) {\n cacCommand.option('--root-dir <path>', 'Override project root');\n cacCommand.option('--debug', 'Enable debug mode');\n cacCommand.option('--help, -h', 'Display help message');\n }\n\n private async runHelp(commandParts: string[]) {\n if (this.HelpCommandClass) {\n const helpInstance = new this.HelpCommandClass(this);\n await helpInstance.run({ command: commandParts });\n } else {\n // Fallback if HelpCommand not loaded (shouldn't happen)\n this.cli.outputHelp();\n }\n }\n\n private async runCommand(CommandClass: any, options: any, commandParts: string[] = []) {\n try {\n const instance = new CommandClass(this, options);\n await instance.init();\n await instance.runInit(options);\n } catch (e: any) {\n console.error(pc.red(e.message));\n if (options.debug) console.error(e.stack);\n\n console.log(''); // spacer\n await this.runHelp(commandParts);\n\n process.exit(1);\n }\n }\n}\n","{\n \"name\": \"@nexical/cli-core\",\n \"version\": \"0.1.13\",\n \"type\": \"module\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"cli\": \"node dist/cli.js\",\n \"test\": \"npm run test:unit && npm run test:integration && npm run test:e2e\",\n \"test:unit\": \"vitest run --config vitest.config.ts --coverage\",\n \"test:integration\": \"vitest run --config vitest.integration.config.ts\",\n \"test:e2e\": \"npm run build && vitest run --config vitest.e2e.config.ts\",\n \"test:watch\": \"vitest\"\n },\n \"dependencies\": {\n \"cac\": \"^6.7.14\",\n \"consola\": \"^3.4.2\",\n \"lilconfig\": \"^3.1.3\",\n \"picocolors\": \"^1.1.1\",\n \"yaml\": \"^2.8.2\",\n \"zod\": \"^3.22.4\"\n },\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/node\": \"^20.10.0\",\n \"@vitest/coverage-v8\": \"^4.0.15\",\n \"execa\": \"^9.6.1\",\n \"fs-extra\": \"^11.3.2\",\n \"tsup\": \"^8.0.1\",\n \"typescript\": \"^5.3.3\",\n \"vitest\": \"^4.0.15\"\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -4,12 +4,12 @@ import {
|
|
|
4
4
|
} from "./chunk-SNTKHUTX.js";
|
|
5
5
|
import {
|
|
6
6
|
CLI
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-BZD5CM3C.js";
|
|
8
8
|
import "./chunk-C4IL52NB.js";
|
|
9
9
|
import "./chunk-LLXEFSKN.js";
|
|
10
10
|
import {
|
|
11
11
|
BaseCommand
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-3OQ5T2ZX.js";
|
|
13
13
|
import {
|
|
14
14
|
findProjectRoot,
|
|
15
15
|
loadConfig
|
|
@@ -3,6 +3,7 @@ import { CommandInterface, CommandDefinition } from './CommandInterface.js';
|
|
|
3
3
|
declare abstract class BaseCommand implements CommandInterface {
|
|
4
4
|
static usage: string;
|
|
5
5
|
static description: string;
|
|
6
|
+
static help: string;
|
|
6
7
|
static args: CommandDefinition;
|
|
7
8
|
static requiresProject: boolean;
|
|
8
9
|
protected projectRoot: string | null;
|
package/dist/src/BaseCommand.js
CHANGED
package/dist/src/CLI.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
BaseCommand
|
|
4
|
-
} from "../../chunk-
|
|
4
|
+
} from "../../chunk-3OQ5T2ZX.js";
|
|
5
5
|
import "../../chunk-IIOHHU2E.js";
|
|
6
6
|
import "../../chunk-2HJDWSDA.js";
|
|
7
7
|
|
|
@@ -87,6 +87,10 @@ var HelpCommand = class extends BaseCommand {
|
|
|
87
87
|
const description = CommandClass.description || cacCmd && cacCmd.description || "";
|
|
88
88
|
console.log(` ${description}`);
|
|
89
89
|
console.log("");
|
|
90
|
+
if (CommandClass.help) {
|
|
91
|
+
console.log(CommandClass.help);
|
|
92
|
+
console.log("");
|
|
93
|
+
}
|
|
90
94
|
const argsDef = CommandClass.args?.args;
|
|
91
95
|
if (argsDef && Array.isArray(argsDef) && argsDef.length > 0) {
|
|
92
96
|
console.log(" Arguments:");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/help.ts"],"sourcesContent":["import { BaseCommand } from '../BaseCommand.js';\nimport pc from 'picocolors';\n\nexport default class HelpCommand extends BaseCommand {\n static description = 'Display help for commands.';\n\n static args = {\n args: [\n { name: 'command...', required: false, description: 'Command name to get help for' }\n ],\n options: []\n };\n\n async run(options: any) {\n const commandParts = options.command || [];\n const query = commandParts.join(' ');\n\n if (!query) {\n // General help\n this.printGlobalHelp();\n return;\n }\n\n // Search for specific command or namespace\n const commands = this.cli.getCommands();\n\n // Exact match?\n const exactMatch = commands.find((c: any) => c.command === query);\n if (exactMatch) {\n // Try to find CAC command if it exists (e.g. top-level commands like 'init')\n // For subcommands (e.g. 'module add'), CAC might only have 'module <subcommand>', \n // so cacCmd will be undefined for the exact query.\n const cacCmd = this.cli.getRawCLI().commands.find((c: any) => c.name === query);\n\n this.printCommandHelp(exactMatch, cacCmd);\n return;\n }\n\n // Namespace match? (e.g. \"module\" matches \"module add\", \"module remove\")\n const namespaceMatches = commands.filter((c: any) => c.command.startsWith(query + ' '));\n\n if (namespaceMatches.length > 0) {\n console.log(`\\n Commands for ${pc.bold(query)}:\\n`);\n for (const cmd of namespaceMatches) {\n const name = cmd.command;\n const desc = cmd.class.description || '';\n console.log(` ${pc.cyan(name.padEnd(20))} ${desc}`);\n }\n console.log('');\n return;\n }\n\n this.error(`Unknown command: ${query}`);\n }\n\n private printGlobalHelp() {\n const commands = this.cli.getCommands();\n const bin = this.cli.name;\n\n console.log('');\n console.log(` Usage: ${pc.cyan(bin)} <command> [options]`);\n console.log('');\n console.log(' Commands:');\n console.log('');\n\n for (const cmd of commands) {\n const name = cmd.command;\n const desc = cmd.class.description || '';\n console.log(` ${pc.cyan(name.padEnd(25))} ${desc}`);\n }\n\n console.log('');\n console.log(' Options:');\n console.log('');\n console.log(` ${pc.yellow('--help'.padEnd(25))} Display this message`);\n console.log(` ${pc.yellow('--version'.padEnd(25))} Display version number`);\n console.log(` ${pc.yellow('--root-dir <path>'.padEnd(25))} Override project root`);\n console.log(` ${pc.yellow('--debug'.padEnd(25))} Enable debug mode`);\n console.log('');\n }\n\n private printCommandHelp(loadedCommand: any, cacCmd?: any) {\n const CommandClass = loadedCommand.class;\n\n let usage = CommandClass.usage;\n if (!usage && cacCmd) usage = cacCmd.rawName;\n\n // Fallback: construct usage from args definition if usage is missing\n if (!usage) {\n let tempUsage = loadedCommand.command;\n const args = CommandClass.args?.args || [];\n args.forEach((arg: any) => {\n const isVariadic = arg.name.endsWith('...');\n const cleanName = isVariadic ? arg.name.slice(0, -3) : arg.name;\n if (arg.required) tempUsage += isVariadic ? ` <...${cleanName}>` : ` <${cleanName}>`;\n else tempUsage += isVariadic ? ` [...${cleanName}]` : ` [${cleanName}]`;\n });\n usage = tempUsage;\n }\n\n console.log('');\n console.log(` Usage: ${pc.cyan(usage)}`);\n console.log('');\n\n const description = CommandClass.description || (cacCmd && cacCmd.description) || '';\n console.log(` ${description}`);\n console.log('');\n\n // Arguments\n // Prefer class definition (or cacCmd definition if we wanted, but class is source of truth for our commands)\n const argsDef = CommandClass.args?.args;\n if (argsDef && Array.isArray(argsDef) && argsDef.length > 0) {\n console.log(' Arguments:');\n for (const arg of argsDef) {\n const name = arg.name;\n const desc = arg.description || '';\n const required = arg.required ? ' (required)' : '';\n console.log(` ${pc.cyan(name.padEnd(25))} ${desc}${pc.dim(required)}`);\n }\n console.log('');\n }\n\n // Options\n const optionsList = [];\n\n if (cacCmd) {\n // If CAC command exists, use its parsed options (includes globals)\n optionsList.push(...cacCmd.options);\n } else {\n // Reconstruct options from Class + Globals\n const classOptions = CommandClass.args?.options || [];\n\n for (const opt of classOptions) {\n optionsList.push({\n rawName: opt.name, // e.g. '--repo <url>'\n description: opt.description,\n config: { default: opt.default }\n });\n }\n\n // Append Global Options manually since they are always available\n optionsList.push({ rawName: '--help', description: 'Display this message', config: {} });\n optionsList.push({ rawName: '--version', description: 'Display version number', config: {} });\n optionsList.push({ rawName: '--root-dir <path>', description: 'Override project root', config: {} });\n optionsList.push({ rawName: '--debug', description: 'Enable debug mode', config: {} });\n }\n\n if (optionsList.length > 0) {\n console.log(' Options:');\n for (const opt of optionsList) {\n const flags = opt.rawName.padEnd(25);\n const desc = opt.description || '';\n const def = opt.config?.default ? ` (default: ${opt.config.default})` : '';\n console.log(` ${pc.yellow(flags)} ${desc}${pc.dim(def)}`);\n }\n console.log('');\n }\n }\n}\n"],"mappings":";;;;;;;;AACA,OAAO,QAAQ;AAEf,IAAqB,cAArB,cAAyC,YAAY;AAAA,EACjD,OAAO,cAAc;AAAA,EAErB,OAAO,OAAO;AAAA,IACV,MAAM;AAAA,MACF,EAAE,MAAM,cAAc,UAAU,OAAO,aAAa,+BAA+B;AAAA,IACvF;AAAA,IACA,SAAS,CAAC;AAAA,EACd;AAAA,EAEA,MAAM,IAAI,SAAc;AACpB,UAAM,eAAe,QAAQ,WAAW,CAAC;AACzC,UAAM,QAAQ,aAAa,KAAK,GAAG;AAEnC,QAAI,CAAC,OAAO;AAER,WAAK,gBAAgB;AACrB;AAAA,IACJ;AAGA,UAAM,WAAW,KAAK,IAAI,YAAY;AAGtC,UAAM,aAAa,SAAS,KAAK,CAAC,MAAW,EAAE,YAAY,KAAK;AAChE,QAAI,YAAY;AAIZ,YAAM,SAAS,KAAK,IAAI,UAAU,EAAE,SAAS,KAAK,CAAC,MAAW,EAAE,SAAS,KAAK;AAE9E,WAAK,iBAAiB,YAAY,MAAM;AACxC;AAAA,IACJ;AAGA,UAAM,mBAAmB,SAAS,OAAO,CAAC,MAAW,EAAE,QAAQ,WAAW,QAAQ,GAAG,CAAC;AAEtF,QAAI,iBAAiB,SAAS,GAAG;AAC7B,cAAQ,IAAI;AAAA,iBAAoB,GAAG,KAAK,KAAK,CAAC;AAAA,CAAK;AACnD,iBAAW,OAAO,kBAAkB;AAChC,cAAM,OAAO,IAAI;AACjB,cAAM,OAAO,IAAI,MAAM,eAAe;AACtC,gBAAQ,IAAI,KAAK,GAAG,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;AAAA,MACvD;AACA,cAAQ,IAAI,EAAE;AACd;AAAA,IACJ;AAEA,SAAK,MAAM,oBAAoB,KAAK,EAAE;AAAA,EAC1C;AAAA,EAEQ,kBAAkB;AACtB,UAAM,WAAW,KAAK,IAAI,YAAY;AACtC,UAAM,MAAM,KAAK,IAAI;AAErB,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,YAAY,GAAG,KAAK,GAAG,CAAC,sBAAsB;AAC1D,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,aAAa;AACzB,YAAQ,IAAI,EAAE;AAEd,eAAW,OAAO,UAAU;AACxB,YAAM,OAAO,IAAI;AACjB,YAAM,OAAO,IAAI,MAAM,eAAe;AACtC,cAAQ,IAAI,OAAO,GAAG,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE;AAAA,IACzD;AAEA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,YAAY;AACxB,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,OAAO,GAAG,OAAO,SAAS,OAAO,EAAE,CAAC,CAAC,uBAAuB;AACxE,YAAQ,IAAI,OAAO,GAAG,OAAO,YAAY,OAAO,EAAE,CAAC,CAAC,yBAAyB;AAC7E,YAAQ,IAAI,OAAO,GAAG,OAAO,oBAAoB,OAAO,EAAE,CAAC,CAAC,wBAAwB;AACpF,YAAQ,IAAI,OAAO,GAAG,OAAO,UAAU,OAAO,EAAE,CAAC,CAAC,oBAAoB;AACtE,YAAQ,IAAI,EAAE;AAAA,EAClB;AAAA,EAEQ,iBAAiB,eAAoB,QAAc;AACvD,UAAM,eAAe,cAAc;AAEnC,QAAI,QAAQ,aAAa;AACzB,QAAI,CAAC,SAAS,OAAQ,SAAQ,OAAO;AAGrC,QAAI,CAAC,OAAO;AACR,UAAI,YAAY,cAAc;AAC9B,YAAM,OAAO,aAAa,MAAM,QAAQ,CAAC;AACzC,WAAK,QAAQ,CAAC,QAAa;AACvB,cAAM,aAAa,IAAI,KAAK,SAAS,KAAK;AAC1C,cAAM,YAAY,aAAa,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,IAAI;AAC3D,YAAI,IAAI,SAAU,cAAa,aAAa,QAAQ,SAAS,MAAM,KAAK,SAAS;AAAA,YAC5E,cAAa,aAAa,QAAQ,SAAS,MAAM,KAAK,SAAS;AAAA,MACxE,CAAC;AACD,cAAQ;AAAA,IACZ;AAEA,YAAQ,IAAI,EAAE;AACd,YAAQ,IAAI,YAAY,GAAG,KAAK,KAAK,CAAC,EAAE;AACxC,YAAQ,IAAI,EAAE;AAEd,UAAM,cAAc,aAAa,eAAgB,UAAU,OAAO,eAAgB;AAClF,YAAQ,IAAI,KAAK,WAAW,EAAE;AAC9B,YAAQ,IAAI,EAAE;AAId,UAAM,UAAU,aAAa,MAAM;AACnC,QAAI,WAAW,MAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,GAAG;AACzD,cAAQ,IAAI,cAAc;AAC1B,iBAAW,OAAO,SAAS;AACvB,cAAM,OAAO,IAAI;AACjB,cAAM,OAAO,IAAI,eAAe;AAChC,cAAM,WAAW,IAAI,WAAW,gBAAgB;AAChD,gBAAQ,IAAI,OAAO,GAAG,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,GAAG,GAAG,IAAI,QAAQ,CAAC,EAAE;AAAA,MAC5E;AACA,cAAQ,IAAI,EAAE;AAAA,IAClB;AAGA,UAAM,cAAc,CAAC;AAErB,QAAI,QAAQ;AAER,kBAAY,KAAK,GAAG,OAAO,OAAO;AAAA,IACtC,OAAO;AAEH,YAAM,eAAe,aAAa,MAAM,WAAW,CAAC;AAEpD,iBAAW,OAAO,cAAc;AAC5B,oBAAY,KAAK;AAAA,UACb,SAAS,IAAI;AAAA;AAAA,UACb,aAAa,IAAI;AAAA,UACjB,QAAQ,EAAE,SAAS,IAAI,QAAQ;AAAA,QACnC,CAAC;AAAA,MACL;AAGA,kBAAY,KAAK,EAAE,SAAS,UAAU,aAAa,wBAAwB,QAAQ,CAAC,EAAE,CAAC;AACvF,kBAAY,KAAK,EAAE,SAAS,aAAa,aAAa,0BAA0B,QAAQ,CAAC,EAAE,CAAC;AAC5F,kBAAY,KAAK,EAAE,SAAS,qBAAqB,aAAa,yBAAyB,QAAQ,CAAC,EAAE,CAAC;AACnG,kBAAY,KAAK,EAAE,SAAS,WAAW,aAAa,qBAAqB,QAAQ,CAAC,EAAE,CAAC;AAAA,IACzF;AAEA,QAAI,YAAY,SAAS,GAAG;AACxB,cAAQ,IAAI,YAAY;AACxB,iBAAW,OAAO,aAAa;AAC3B,cAAM,QAAQ,IAAI,QAAQ,OAAO,EAAE;AACnC,cAAM,OAAO,IAAI,eAAe;AAChC,cAAM,MAAM,IAAI,QAAQ,UAAU,cAAc,IAAI,OAAO,OAAO,MAAM;AACxE,gBAAQ,IAAI,OAAO,GAAG,OAAO,KAAK,CAAC,IAAI,IAAI,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE;AAAA,MAC/D;AACA,cAAQ,IAAI,EAAE;AAAA,IAClB;AAAA,EACJ;AACJ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/help.ts"],"sourcesContent":["import { BaseCommand } from '../BaseCommand.js';\nimport pc from 'picocolors';\n\nexport default class HelpCommand extends BaseCommand {\n static description = 'Display help for commands.';\n\n static args = {\n args: [\n { name: 'command...', required: false, description: 'Command name to get help for' }\n ],\n options: []\n };\n\n async run(options: any) {\n const commandParts = options.command || [];\n const query = commandParts.join(' ');\n\n if (!query) {\n // General help\n this.printGlobalHelp();\n return;\n }\n\n // Search for specific command or namespace\n const commands = this.cli.getCommands();\n\n // Exact match?\n const exactMatch = commands.find((c: any) => c.command === query);\n if (exactMatch) {\n // Try to find CAC command if it exists (e.g. top-level commands like 'init')\n // For subcommands (e.g. 'module add'), CAC might only have 'module <subcommand>', \n // so cacCmd will be undefined for the exact query.\n const cacCmd = this.cli.getRawCLI().commands.find((c: any) => c.name === query);\n\n this.printCommandHelp(exactMatch, cacCmd);\n return;\n }\n\n // Namespace match? (e.g. \"module\" matches \"module add\", \"module remove\")\n const namespaceMatches = commands.filter((c: any) => c.command.startsWith(query + ' '));\n\n if (namespaceMatches.length > 0) {\n console.log(`\\n Commands for ${pc.bold(query)}:\\n`);\n for (const cmd of namespaceMatches) {\n const name = cmd.command;\n const desc = cmd.class.description || '';\n console.log(` ${pc.cyan(name.padEnd(20))} ${desc}`);\n }\n console.log('');\n return;\n }\n\n this.error(`Unknown command: ${query}`);\n }\n\n private printGlobalHelp() {\n const commands = this.cli.getCommands();\n const bin = this.cli.name;\n\n console.log('');\n console.log(` Usage: ${pc.cyan(bin)} <command> [options]`);\n console.log('');\n console.log(' Commands:');\n console.log('');\n\n for (const cmd of commands) {\n const name = cmd.command;\n const desc = cmd.class.description || '';\n console.log(` ${pc.cyan(name.padEnd(25))} ${desc}`);\n }\n\n console.log('');\n console.log(' Options:');\n console.log('');\n console.log(` ${pc.yellow('--help'.padEnd(25))} Display this message`);\n console.log(` ${pc.yellow('--version'.padEnd(25))} Display version number`);\n console.log(` ${pc.yellow('--root-dir <path>'.padEnd(25))} Override project root`);\n console.log(` ${pc.yellow('--debug'.padEnd(25))} Enable debug mode`);\n console.log('');\n }\n\n private printCommandHelp(loadedCommand: any, cacCmd?: any) {\n const CommandClass = loadedCommand.class;\n\n let usage = CommandClass.usage;\n if (!usage && cacCmd) usage = cacCmd.rawName;\n\n // Fallback: construct usage from args definition if usage is missing\n if (!usage) {\n let tempUsage = loadedCommand.command;\n const args = CommandClass.args?.args || [];\n args.forEach((arg: any) => {\n const isVariadic = arg.name.endsWith('...');\n const cleanName = isVariadic ? arg.name.slice(0, -3) : arg.name;\n if (arg.required) tempUsage += isVariadic ? ` <...${cleanName}>` : ` <${cleanName}>`;\n else tempUsage += isVariadic ? ` [...${cleanName}]` : ` [${cleanName}]`;\n });\n usage = tempUsage;\n }\n\n console.log('');\n console.log(` Usage: ${pc.cyan(usage)}`);\n console.log('');\n\n const description = CommandClass.description || (cacCmd && cacCmd.description) || '';\n console.log(` ${description}`);\n console.log('');\n\n if (CommandClass.help) {\n console.log(CommandClass.help);\n console.log('');\n }\n\n // Arguments\n // Prefer class definition (or cacCmd definition if we wanted, but class is source of truth for our commands)\n const argsDef = CommandClass.args?.args;\n if (argsDef && Array.isArray(argsDef) && argsDef.length > 0) {\n console.log(' Arguments:');\n for (const arg of argsDef) {\n const name = arg.name;\n const desc = arg.description || '';\n const required = arg.required ? ' (required)' : '';\n console.log(` ${pc.cyan(name.padEnd(25))} ${desc}${pc.dim(required)}`);\n }\n console.log('');\n }\n\n // Options\n const optionsList = [];\n\n if (cacCmd) {\n // If CAC command exists, use its parsed options (includes globals)\n optionsList.push(...cacCmd.options);\n } else {\n // Reconstruct options from Class + Globals\n const classOptions = CommandClass.args?.options || [];\n\n for (const opt of classOptions) {\n optionsList.push({\n rawName: opt.name, // e.g. '--repo <url>'\n description: opt.description,\n config: { default: opt.default }\n });\n }\n\n // Append Global Options manually since they are always available\n optionsList.push({ rawName: '--help', description: 'Display this message', config: {} });\n optionsList.push({ rawName: '--version', description: 'Display version number', config: {} });\n optionsList.push({ rawName: '--root-dir <path>', description: 'Override project root', config: {} });\n optionsList.push({ rawName: '--debug', description: 'Enable debug mode', config: {} });\n }\n\n if (optionsList.length > 0) {\n console.log(' Options:');\n for (const opt of optionsList) {\n const flags = opt.rawName.padEnd(25);\n const desc = opt.description || '';\n const def = opt.config?.default ? ` (default: ${opt.config.default})` : '';\n console.log(` ${pc.yellow(flags)} ${desc}${pc.dim(def)}`);\n }\n console.log('');\n }\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
package/src/BaseCommand.ts
CHANGED
package/src/commands/help.ts
CHANGED
|
@@ -106,6 +106,11 @@ export default class HelpCommand extends BaseCommand {
|
|
|
106
106
|
console.log(` ${description}`);
|
|
107
107
|
console.log('');
|
|
108
108
|
|
|
109
|
+
if (CommandClass.help) {
|
|
110
|
+
console.log(CommandClass.help);
|
|
111
|
+
console.log('');
|
|
112
|
+
}
|
|
113
|
+
|
|
109
114
|
// Arguments
|
|
110
115
|
// Prefer class definition (or cacCmd definition if we wanted, but class is source of truth for our commands)
|
|
111
116
|
const argsDef = CommandClass.args?.args;
|
|
@@ -128,6 +128,31 @@ describe('HelpCommand', () => {
|
|
|
128
128
|
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('--force'));
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
+
it('should display detailed command help (help property) if present', async () => {
|
|
132
|
+
const cmd = new HelpCommand(mockCli);
|
|
133
|
+
|
|
134
|
+
// Mock loaded commands with help definition
|
|
135
|
+
mockCli.getCommands.mockReturnValue([
|
|
136
|
+
{
|
|
137
|
+
command: 'detailed',
|
|
138
|
+
class: {
|
|
139
|
+
description: 'Detailed command',
|
|
140
|
+
help: 'Multi-line detailed help text.\nSecond line.',
|
|
141
|
+
args: {}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
]);
|
|
145
|
+
mockRawCli.commands = [];
|
|
146
|
+
|
|
147
|
+
await cmd.run({ command: ['detailed'] });
|
|
148
|
+
|
|
149
|
+
// Should print description
|
|
150
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('Detailed command'));
|
|
151
|
+
// Should print help
|
|
152
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('Multi-line detailed help text.'));
|
|
153
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining('Second line.'));
|
|
154
|
+
});
|
|
155
|
+
|
|
131
156
|
it('should display subcommand help when CAC command is missing (fallback to LoadedCommand)', async () => {
|
|
132
157
|
const cmd = new HelpCommand(mockCli);
|
|
133
158
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/BaseCommand.ts"],"sourcesContent":["import { logger } from './utils/logger.js';\nimport { CommandDefinition, CommandInterface } from './CommandInterface.js';\nimport { findProjectRoot, loadConfig } from './utils/config.js';\nimport process from 'node:process';\nimport pc from 'picocolors';\nimport { consola } from 'consola';\n\nexport abstract class BaseCommand implements CommandInterface {\n static usage = '';\n static description = '';\n static args: CommandDefinition = {};\n\n // Configurable flags\n static requiresProject = false;\n\n protected projectRoot: string | null = null;\n protected config: any = {};\n protected globalOptions: any = {};\n protected cli: any = null;\n\n\n constructor(cli: any, globalOptions: any = {}) {\n this.globalOptions = globalOptions;\n this.cli = cli;\n }\n\n async init() {\n // 1. Root detection strategy\n if (this.globalOptions.rootDir) {\n this.projectRoot = this.globalOptions.rootDir;\n } else {\n this.projectRoot = await findProjectRoot(this.cli.name, process.cwd());\n }\n\n if (this.projectRoot) {\n this.config = await loadConfig(this.cli.name, this.projectRoot);\n logger.debug(`Loaded config from ${this.projectRoot}`);\n }\n }\n\n async runInit(options: any): Promise<void> {\n const requiresProject = (this.constructor as any).requiresProject;\n if (requiresProject && !this.projectRoot) {\n this.error(`This command requires to be run within an app project (${this.cli.name}.yml not found).`, 1);\n return;\n }\n await this.run(options);\n }\n\n abstract run(options: any): Promise<void>;\n\n // Helpers\n success(msg: string) {\n console.log(pc.green('✔ ' + msg));\n }\n\n notice(msg: string) {\n console.log(pc.blue('📢 ' + msg));\n }\n\n input(msg: string) {\n console.log(pc.cyan('? ' + msg));\n }\n\n info(msg: string) {\n console.log(msg);\n }\n\n warn(msg: string) {\n console.log(pc.yellow('⚠ ' + msg));\n }\n\n error(msg: string | Error, code = 1) {\n if (msg instanceof Error) {\n console.log(pc.red('✖ ' + msg.message));\n if (this.globalOptions.debug) {\n logger.error(msg.stack);\n }\n } else {\n console.log(pc.red('✖ ' + msg));\n }\n process.exit(code);\n }\n\n async prompt(msg: string): Promise<string> {\n const response = await consola.prompt(msg, { type: 'text' });\n return response as string;\n }\n}\n"],"mappings":";;;;;;;;;;AAGA,OAAO,aAAa;AACpB,OAAO,QAAQ;AACf,SAAS,eAAe;AAEjB,IAAe,cAAf,MAAuD;AAAA,EAC1D,OAAO,QAAQ;AAAA,EACf,OAAO,cAAc;AAAA,EACrB,OAAO,OAA0B,CAAC;AAAA;AAAA,EAGlC,OAAO,kBAAkB;AAAA,EAEf,cAA6B;AAAA,EAC7B,SAAc,CAAC;AAAA,EACf,gBAAqB,CAAC;AAAA,EACtB,MAAW;AAAA,EAGrB,YAAY,KAAU,gBAAqB,CAAC,GAAG;AAC3C,SAAK,gBAAgB;AACrB,SAAK,MAAM;AAAA,EACf;AAAA,EAEA,MAAM,OAAO;AAET,QAAI,KAAK,cAAc,SAAS;AAC5B,WAAK,cAAc,KAAK,cAAc;AAAA,IAC1C,OAAO;AACH,WAAK,cAAc,MAAM,gBAAgB,KAAK,IAAI,MAAM,QAAQ,IAAI,CAAC;AAAA,IACzE;AAEA,QAAI,KAAK,aAAa;AAClB,WAAK,SAAS,MAAM,WAAW,KAAK,IAAI,MAAM,KAAK,WAAW;AAC9D,aAAO,MAAM,sBAAsB,KAAK,WAAW,EAAE;AAAA,IACzD;AAAA,EACJ;AAAA,EAEA,MAAM,QAAQ,SAA6B;AACvC,UAAM,kBAAmB,KAAK,YAAoB;AAClD,QAAI,mBAAmB,CAAC,KAAK,aAAa;AACtC,WAAK,MAAM,0DAA0D,KAAK,IAAI,IAAI,oBAAoB,CAAC;AACvG;AAAA,IACJ;AACA,UAAM,KAAK,IAAI,OAAO;AAAA,EAC1B;AAAA;AAAA,EAKA,QAAQ,KAAa;AACjB,YAAQ,IAAI,GAAG,MAAM,YAAO,GAAG,CAAC;AAAA,EACpC;AAAA,EAEA,OAAO,KAAa;AAChB,YAAQ,IAAI,GAAG,KAAK,eAAQ,GAAG,CAAC;AAAA,EACpC;AAAA,EAEA,MAAM,KAAa;AACf,YAAQ,IAAI,GAAG,KAAK,OAAO,GAAG,CAAC;AAAA,EACnC;AAAA,EAEA,KAAK,KAAa;AACd,YAAQ,IAAI,GAAG;AAAA,EACnB;AAAA,EAEA,KAAK,KAAa;AACd,YAAQ,IAAI,GAAG,OAAO,YAAO,GAAG,CAAC;AAAA,EACrC;AAAA,EAEA,MAAM,KAAqB,OAAO,GAAG;AACjC,QAAI,eAAe,OAAO;AACtB,cAAQ,IAAI,GAAG,IAAI,YAAO,IAAI,OAAO,CAAC;AACtC,UAAI,KAAK,cAAc,OAAO;AAC1B,eAAO,MAAM,IAAI,KAAK;AAAA,MAC1B;AAAA,IACJ,OAAO;AACH,cAAQ,IAAI,GAAG,IAAI,YAAO,GAAG,CAAC;AAAA,IAClC;AACA,YAAQ,KAAK,IAAI;AAAA,EACrB;AAAA,EAEA,MAAM,OAAO,KAA8B;AACvC,UAAM,WAAW,MAAM,QAAQ,OAAO,KAAK,EAAE,MAAM,OAAO,CAAC;AAC3D,WAAO;AAAA,EACX;AACJ;","names":[]}
|