@nexical/cli-core 0.1.0 → 0.1.2
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/README.md +195 -0
- package/cli.ts +9 -0
- package/dist/chunk-2HJDWSDA.js +19 -0
- package/dist/chunk-2HJDWSDA.js.map +1 -0
- package/dist/chunk-C4IL52NB.js +2 -0
- package/dist/chunk-C4IL52NB.js.map +1 -0
- package/dist/chunk-CKAS75E6.js +67 -0
- package/dist/chunk-CKAS75E6.js.map +1 -0
- package/dist/chunk-IIOHHU2E.js +48 -0
- package/dist/chunk-IIOHHU2E.js.map +1 -0
- package/dist/chunk-LLXEFSKN.js +69 -0
- package/dist/chunk-LLXEFSKN.js.map +1 -0
- package/dist/chunk-SNTKHUTX.js +29 -0
- package/dist/chunk-SNTKHUTX.js.map +1 -0
- package/dist/chunk-Z4RQIDDY.js +255 -0
- package/dist/chunk-Z4RQIDDY.js.map +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +15 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/src/BaseCommand.d.ts +21 -0
- package/dist/src/BaseCommand.js +10 -0
- package/dist/src/BaseCommand.js.map +1 -0
- package/dist/src/CLI.d.ts +23 -0
- package/dist/src/CLI.js +10 -0
- package/dist/src/CLI.js.map +1 -0
- package/dist/src/CommandInterface.d.ts +21 -0
- package/dist/src/CommandInterface.js +3 -0
- package/dist/src/CommandInterface.js.map +1 -0
- package/dist/src/CommandLoader.d.ts +20 -0
- package/dist/src/CommandLoader.js +9 -0
- package/dist/src/CommandLoader.js.map +1 -0
- package/dist/src/commands/help.d.ts +19 -0
- package/dist/src/commands/help.js +134 -0
- package/dist/src/commands/help.js.map +1 -0
- package/dist/src/utils/config.d.ts +7 -0
- package/dist/src/utils/config.js +13 -0
- package/dist/src/utils/config.js.map +1 -0
- package/dist/src/utils/logger.d.ts +6 -0
- package/dist/src/utils/logger.js +10 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/shell.d.ts +3 -0
- package/dist/src/utils/shell.js +9 -0
- package/dist/src/utils/shell.js.map +1 -0
- package/index.ts +5 -7
- package/package.json +7 -2
- package/src/utils/logger.ts +2 -2
- package/test/utils/integration-helpers.ts +1 -1
- package/tsconfig.json +2 -2
- package/tsup.config.ts +1 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
CommandLoader
|
|
4
|
+
} from "./chunk-LLXEFSKN.js";
|
|
5
|
+
import {
|
|
6
|
+
logger,
|
|
7
|
+
setDebugMode
|
|
8
|
+
} from "./chunk-2HJDWSDA.js";
|
|
9
|
+
|
|
10
|
+
// src/CLI.ts
|
|
11
|
+
import { cac } from "cac";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
import { fileURLToPath } from "url";
|
|
15
|
+
import pc from "picocolors";
|
|
16
|
+
|
|
17
|
+
// package.json
|
|
18
|
+
var package_default = {
|
|
19
|
+
name: "@nexical/cli-core",
|
|
20
|
+
version: "0.1.2",
|
|
21
|
+
type: "module",
|
|
22
|
+
main: "dist/index.js",
|
|
23
|
+
types: "dist/index.d.ts",
|
|
24
|
+
exports: {
|
|
25
|
+
".": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
scripts: {
|
|
28
|
+
build: "tsup",
|
|
29
|
+
dev: "tsup --watch",
|
|
30
|
+
cli: "node dist/cli.js",
|
|
31
|
+
test: "npm run test:unit && npm run test:integration && npm run test:e2e",
|
|
32
|
+
"test:unit": "vitest run --config vitest.config.ts --coverage",
|
|
33
|
+
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
34
|
+
"test:e2e": "npm run build && vitest run --config vitest.e2e.config.ts",
|
|
35
|
+
"test:watch": "vitest"
|
|
36
|
+
},
|
|
37
|
+
dependencies: {
|
|
38
|
+
cac: "^6.7.14",
|
|
39
|
+
consola: "^3.4.2",
|
|
40
|
+
lilconfig: "^3.1.3",
|
|
41
|
+
picocolors: "^1.1.1",
|
|
42
|
+
yaml: "^2.8.2",
|
|
43
|
+
zod: "^3.22.4"
|
|
44
|
+
},
|
|
45
|
+
devDependencies: {
|
|
46
|
+
"@types/fs-extra": "^11.0.4",
|
|
47
|
+
"@types/node": "^20.10.0",
|
|
48
|
+
"@vitest/coverage-v8": "^4.0.15",
|
|
49
|
+
execa: "^9.6.1",
|
|
50
|
+
"fs-extra": "^11.3.2",
|
|
51
|
+
tsup: "^8.0.1",
|
|
52
|
+
typescript: "^5.3.3",
|
|
53
|
+
vitest: "^4.0.15"
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// src/CLI.ts
|
|
58
|
+
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
59
|
+
var CLI = class {
|
|
60
|
+
name;
|
|
61
|
+
cli;
|
|
62
|
+
loader;
|
|
63
|
+
HelpCommandClass;
|
|
64
|
+
config;
|
|
65
|
+
constructor(config = {}) {
|
|
66
|
+
this.config = config;
|
|
67
|
+
this.name = this.config.commandName || "app";
|
|
68
|
+
this.cli = cac(this.name);
|
|
69
|
+
this.loader = new CommandLoader(this);
|
|
70
|
+
}
|
|
71
|
+
loadedCommands = [];
|
|
72
|
+
getCommands() {
|
|
73
|
+
return this.loadedCommands;
|
|
74
|
+
}
|
|
75
|
+
getRawCLI() {
|
|
76
|
+
return this.cli;
|
|
77
|
+
}
|
|
78
|
+
async start() {
|
|
79
|
+
if (process.argv.includes("--debug")) {
|
|
80
|
+
setDebugMode(true);
|
|
81
|
+
logger.debug("Debug mode enabled via --debug flag");
|
|
82
|
+
}
|
|
83
|
+
let commandsDirs = [];
|
|
84
|
+
if (this.config.searchDirectories && this.config.searchDirectories.length > 0) {
|
|
85
|
+
commandsDirs = this.config.searchDirectories;
|
|
86
|
+
} else {
|
|
87
|
+
const possibleDirs = [
|
|
88
|
+
path.resolve(__dirname, "./src/commands"),
|
|
89
|
+
path.resolve(process.cwd(), "commands")
|
|
90
|
+
// Fallback relative to cwd?
|
|
91
|
+
];
|
|
92
|
+
for (const dir of possibleDirs) {
|
|
93
|
+
if (fs.existsSync(dir)) {
|
|
94
|
+
commandsDirs.push(dir);
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (commandsDirs.length === 0) {
|
|
100
|
+
logger.debug("No commands directory found.");
|
|
101
|
+
}
|
|
102
|
+
for (const dir of commandsDirs) {
|
|
103
|
+
await this.loader.load(dir);
|
|
104
|
+
}
|
|
105
|
+
this.loadedCommands = this.loader.getCommands();
|
|
106
|
+
const commandGroups = {};
|
|
107
|
+
const helpCmd = this.loadedCommands.find((c) => c.command === "help");
|
|
108
|
+
if (helpCmd) {
|
|
109
|
+
this.HelpCommandClass = helpCmd.class;
|
|
110
|
+
}
|
|
111
|
+
for (const cmd of this.loadedCommands) {
|
|
112
|
+
const root = cmd.command.split(" ")[0];
|
|
113
|
+
if (!commandGroups[root]) commandGroups[root] = [];
|
|
114
|
+
commandGroups[root].push(cmd);
|
|
115
|
+
}
|
|
116
|
+
for (const [root, cmds] of Object.entries(commandGroups)) {
|
|
117
|
+
if (cmds.length === 1 && cmds[0].command === root) {
|
|
118
|
+
const cmd = cmds[0];
|
|
119
|
+
const CommandClass = cmd.class;
|
|
120
|
+
let commandName = cmd.command;
|
|
121
|
+
const argsDef = CommandClass.args || {};
|
|
122
|
+
if (argsDef.args) {
|
|
123
|
+
argsDef.args.forEach((arg) => {
|
|
124
|
+
const isVariadic = arg.name.endsWith("...");
|
|
125
|
+
const cleanName = isVariadic ? arg.name.slice(0, -3) : arg.name;
|
|
126
|
+
commandName += isVariadic ? ` [...${cleanName}]` : ` [${cleanName}]`;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const cacCommand = this.cli.command(commandName, CommandClass.description || "");
|
|
130
|
+
if (argsDef.options) {
|
|
131
|
+
argsDef.options.forEach((opt) => {
|
|
132
|
+
cacCommand.option(opt.name, opt.description, { default: opt.default });
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
this.registerGlobalOptions(cacCommand);
|
|
136
|
+
cacCommand.action(async (...args) => {
|
|
137
|
+
const options = args.pop();
|
|
138
|
+
if (options.help) {
|
|
139
|
+
await this.runHelp([cmd.command]);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const positionalArgs = args;
|
|
143
|
+
if (argsDef.args) {
|
|
144
|
+
argsDef.args.forEach((arg, index) => {
|
|
145
|
+
const isVariadic = arg.name.endsWith("...");
|
|
146
|
+
const name = isVariadic ? arg.name.slice(0, -3) : arg.name;
|
|
147
|
+
const val = positionalArgs[index];
|
|
148
|
+
if (val !== void 0) {
|
|
149
|
+
options[name] = val;
|
|
150
|
+
} else if (arg.required) {
|
|
151
|
+
console.error(pc.red(`Missing required argument: ${name}`));
|
|
152
|
+
this.runHelp([cmd.command]).then(() => process.exit(1));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
await this.runCommand(CommandClass, options, [cmd.command]);
|
|
158
|
+
});
|
|
159
|
+
} else {
|
|
160
|
+
const commandName = `${root} [subcommand] [...args]`;
|
|
161
|
+
const cacCommand = this.cli.command(commandName, `Manage ${root} commands`);
|
|
162
|
+
cacCommand.allowUnknownOptions();
|
|
163
|
+
this.registerGlobalOptions(cacCommand);
|
|
164
|
+
cacCommand.action(async (subcommand, ...args) => {
|
|
165
|
+
const options = args.pop();
|
|
166
|
+
if (!subcommand || options.help) {
|
|
167
|
+
await this.runHelp([root, subcommand].filter(Boolean));
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const fullCommandName = `${root} ${subcommand}`;
|
|
171
|
+
const cmd = cmds.find((c) => c.command === fullCommandName);
|
|
172
|
+
if (!cmd) {
|
|
173
|
+
console.error(pc.red(`Unknown subcommand '${subcommand}' for '${root}'`));
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
const CommandClass = cmd.class;
|
|
177
|
+
const argsDef = CommandClass.args || {};
|
|
178
|
+
const positionalArgs = args.length > 0 && Array.isArray(args[0]) ? args[0] : args;
|
|
179
|
+
const childOptions = { ...options };
|
|
180
|
+
const cmdParts = [root, subcommand];
|
|
181
|
+
if (argsDef.args) {
|
|
182
|
+
argsDef.args.forEach((arg, index) => {
|
|
183
|
+
const isVariadic = arg.name.endsWith("...");
|
|
184
|
+
const name = isVariadic ? arg.name.slice(0, -3) : arg.name;
|
|
185
|
+
const val = positionalArgs[index];
|
|
186
|
+
if (val !== void 0) {
|
|
187
|
+
if (isVariadic) {
|
|
188
|
+
childOptions[name] = positionalArgs.slice(index);
|
|
189
|
+
} else {
|
|
190
|
+
childOptions[name] = val;
|
|
191
|
+
}
|
|
192
|
+
} else if (arg.required) {
|
|
193
|
+
console.error(pc.red(`Missing required argument: ${name}`));
|
|
194
|
+
this.runHelp(cmdParts).then(() => process.exit(1));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
await this.runCommand(CommandClass, childOptions, cmdParts);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
this.cli.option("--help, -h", "Display help");
|
|
204
|
+
this.cli.version(package_default.version);
|
|
205
|
+
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
206
|
+
const args = process.argv.slice(2).filter((a) => !a.startsWith("-"));
|
|
207
|
+
if (args.length === 0) {
|
|
208
|
+
await this.runHelp([]);
|
|
209
|
+
process.exit(0);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
this.cli.parse();
|
|
214
|
+
} catch (e) {
|
|
215
|
+
console.error(pc.red(e.message));
|
|
216
|
+
console.log("");
|
|
217
|
+
const args = process.argv.slice(2);
|
|
218
|
+
const potentialCommand = args.find((a) => !a.startsWith("-"));
|
|
219
|
+
const helpArgs = potentialCommand ? [potentialCommand] : [];
|
|
220
|
+
await this.runHelp(helpArgs);
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
registerGlobalOptions(cacCommand) {
|
|
225
|
+
cacCommand.option("--root-dir <path>", "Override project root");
|
|
226
|
+
cacCommand.option("--debug", "Enable debug mode");
|
|
227
|
+
cacCommand.option("--help, -h", "Display help message");
|
|
228
|
+
}
|
|
229
|
+
async runHelp(commandParts) {
|
|
230
|
+
if (this.HelpCommandClass) {
|
|
231
|
+
const helpInstance = new this.HelpCommandClass(this);
|
|
232
|
+
await helpInstance.run({ command: commandParts });
|
|
233
|
+
} else {
|
|
234
|
+
this.cli.outputHelp();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
async runCommand(CommandClass, options, commandParts = []) {
|
|
238
|
+
try {
|
|
239
|
+
const instance = new CommandClass(this, options);
|
|
240
|
+
await instance.init();
|
|
241
|
+
await instance.run(options);
|
|
242
|
+
} catch (e) {
|
|
243
|
+
console.error(pc.red(e.message));
|
|
244
|
+
if (options.debug) console.error(e.stack);
|
|
245
|
+
console.log("");
|
|
246
|
+
await this.runHelp(commandParts);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
export {
|
|
253
|
+
CLI
|
|
254
|
+
};
|
|
255
|
+
//# sourceMappingURL=chunk-Z4RQIDDY.js.map
|
|
@@ -0,0 +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 commandName?: string;\n searchDirectories?: string[];\n}\n\nexport class CLI {\n public name: 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.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 // In built version, we are in dist/index.js (from cli/index.ts) -> core bundled? or just imported.\n // The core logic is now in src/cli/core/src/CLI.ts or dist/core/src/CLI.js\n\n // Check for debug flag early\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 // We assume the standard structure:\n // cli/\n // index.js\n // commands/\n // core/\n // src/\n // CLI.ts\n\n // When running from source (ts-node src/cli/index.ts), specific commands are in src/cli/commands.\n // core is in src/cli/core/src.\n // Relative path from CLI.ts to commands: ../../../commands\n\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 break; // Keep existing behavior: verify if we want multiple or just first found\n }\n }\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 // If --help is passed to 'module --help', subcommand might be caught as 'module' if args parsing is weird? \n // ACTUALLY: cac parses 'module add --help' as subcommand=\"add\".\n // 'module --help' might trigger the command itself? No, 'module <subcommand>' expects a subcommand.\n // If I run 'module --help', it might fail validation or parse 'help' as subcommand if unlucky, \n // but likely it just prints help if we didn't override.\n\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 // Map remaining args? \n // The args array contains positional args AFTER subcommand.\n // But we didn't define them in CAC, so they are just strings.\n // We need to map them manually to the Target Command's args definition.\n // argsDef.args usually starts after the command.\n // For 'module add <url>', <url> is the first arg after 'add'.\n // So 'args' here corresponds to <url>.\n\n const argsDef = CommandClass.args || {};\n // If using [...args], the variadic args are collected into the first argument array\n // args here is what remains after popping options.\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 await this.runCommand(CommandClass, childOptions, cmdParts);\n });\n }\n }\n // Disable default help\n // this.cli.help(); \n\n // Manually register global help to ensure it's allowed\n this.cli.option('--help, -h', 'Display help');\n\n this.cli.version(pkg.version);\n\n // Global help interception for root command\n // If we run `app --help`, we need to catch it.\n // CAC doesn't expose a clean global action without a command content.\n // However, if we parse and no command matches, it usually errors or shows help.\n // If we have default logic, we can put it here?\n // Let's rely on standard parsing but maybe inspect raw args first?\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 // If it matches a loaded command root, show help for it\n // Otherwise show global help\n\n // We need to match 'module add' etc?\n // Just pass the potential command parts to runHelp. \n // runHelp handles filtering itself? No, runHelp takes commandParts to pass to HelpCommand.\n // HelpCommand expects `command` array.\n\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.run(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.2\",\n \"type\": \"module\",\n \"main\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": \"./dist/index.js\"\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":[]}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
CLI
|
|
5
|
+
} from "./chunk-Z4RQIDDY.js";
|
|
6
|
+
import "./chunk-LLXEFSKN.js";
|
|
7
|
+
import {
|
|
8
|
+
logger
|
|
9
|
+
} from "./chunk-2HJDWSDA.js";
|
|
10
|
+
|
|
11
|
+
// cli.ts
|
|
12
|
+
logger.debug("CLI ENTRY POINT HIT", process.argv);
|
|
13
|
+
var app = new CLI();
|
|
14
|
+
app.start();
|
|
15
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { CLI } from './src/CLI.js';\n\nimport { logger } from './src/utils/logger.js';\n\nlogger.debug('CLI ENTRY POINT HIT', process.argv);\n\nconst app = new CLI();\napp.start();\n"],"mappings":";;;;;;;;;;;AAKA,OAAO,MAAM,uBAAuB,QAAQ,IAAI;AAEhD,IAAM,MAAM,IAAI,IAAI;AACpB,IAAI,MAAM;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { CLI, CLIConfig } from './src/CLI.js';
|
|
2
|
+
export { BaseCommand } from './src/BaseCommand.js';
|
|
3
|
+
export { logger, setDebugMode } from './src/utils/logger.js';
|
|
4
|
+
export { runCommand } from './src/utils/shell.js';
|
|
5
|
+
export { CommandArg, CommandDefinition, CommandInterface, CommandOption } from './src/CommandInterface.js';
|
|
6
|
+
import 'cac';
|
|
7
|
+
import 'consola';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
runCommand
|
|
4
|
+
} from "./chunk-SNTKHUTX.js";
|
|
5
|
+
import {
|
|
6
|
+
CLI
|
|
7
|
+
} from "./chunk-Z4RQIDDY.js";
|
|
8
|
+
import "./chunk-C4IL52NB.js";
|
|
9
|
+
import "./chunk-LLXEFSKN.js";
|
|
10
|
+
import {
|
|
11
|
+
BaseCommand
|
|
12
|
+
} from "./chunk-CKAS75E6.js";
|
|
13
|
+
import "./chunk-IIOHHU2E.js";
|
|
14
|
+
import {
|
|
15
|
+
logger,
|
|
16
|
+
setDebugMode
|
|
17
|
+
} from "./chunk-2HJDWSDA.js";
|
|
18
|
+
export {
|
|
19
|
+
BaseCommand,
|
|
20
|
+
CLI,
|
|
21
|
+
logger,
|
|
22
|
+
runCommand,
|
|
23
|
+
setDebugMode
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CommandInterface, CommandDefinition } from './CommandInterface.js';
|
|
2
|
+
|
|
3
|
+
declare abstract class BaseCommand implements CommandInterface {
|
|
4
|
+
static usage: string;
|
|
5
|
+
static description: string;
|
|
6
|
+
static args: CommandDefinition;
|
|
7
|
+
static requiresProject: boolean;
|
|
8
|
+
protected projectRoot: string | null;
|
|
9
|
+
protected config: any;
|
|
10
|
+
protected globalOptions: any;
|
|
11
|
+
protected cli: any;
|
|
12
|
+
constructor(cli: any, globalOptions?: any);
|
|
13
|
+
init(): Promise<void>;
|
|
14
|
+
abstract run(options: any): Promise<void>;
|
|
15
|
+
success(msg: string): void;
|
|
16
|
+
info(msg: string): void;
|
|
17
|
+
warn(msg: string): void;
|
|
18
|
+
error(msg: string | Error, code?: number): void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { BaseCommand };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
BaseCommand
|
|
4
|
+
} from "../chunk-CKAS75E6.js";
|
|
5
|
+
import "../chunk-IIOHHU2E.js";
|
|
6
|
+
import "../chunk-2HJDWSDA.js";
|
|
7
|
+
export {
|
|
8
|
+
BaseCommand
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=BaseCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as cac from 'cac';
|
|
2
|
+
|
|
3
|
+
interface CLIConfig {
|
|
4
|
+
commandName?: string;
|
|
5
|
+
searchDirectories?: string[];
|
|
6
|
+
}
|
|
7
|
+
declare class CLI {
|
|
8
|
+
name: string;
|
|
9
|
+
private cli;
|
|
10
|
+
private loader;
|
|
11
|
+
private HelpCommandClass;
|
|
12
|
+
private config;
|
|
13
|
+
constructor(config?: CLIConfig);
|
|
14
|
+
private loadedCommands;
|
|
15
|
+
getCommands(): any[];
|
|
16
|
+
getRawCLI(): cac.CAC;
|
|
17
|
+
start(): Promise<void>;
|
|
18
|
+
private registerGlobalOptions;
|
|
19
|
+
private runHelp;
|
|
20
|
+
private runCommand;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { CLI, type CLIConfig };
|
package/dist/src/CLI.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface CommandArg {
|
|
2
|
+
name: string;
|
|
3
|
+
required?: boolean;
|
|
4
|
+
description?: string;
|
|
5
|
+
default?: any;
|
|
6
|
+
}
|
|
7
|
+
interface CommandOption {
|
|
8
|
+
name: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
default?: any;
|
|
11
|
+
type?: any[];
|
|
12
|
+
}
|
|
13
|
+
interface CommandDefinition {
|
|
14
|
+
args?: CommandArg[];
|
|
15
|
+
options?: CommandOption[];
|
|
16
|
+
}
|
|
17
|
+
interface CommandInterface {
|
|
18
|
+
run(options: any): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type { CommandArg, CommandDefinition, CommandInterface, CommandOption };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BaseCommand } from './BaseCommand.js';
|
|
2
|
+
import './CommandInterface.js';
|
|
3
|
+
|
|
4
|
+
interface LoadedCommand {
|
|
5
|
+
command: string;
|
|
6
|
+
path: string;
|
|
7
|
+
instance: BaseCommand;
|
|
8
|
+
class: any;
|
|
9
|
+
}
|
|
10
|
+
declare class CommandLoader {
|
|
11
|
+
private cli;
|
|
12
|
+
private commands;
|
|
13
|
+
private importer;
|
|
14
|
+
constructor(cli: any, importer?: (path: string) => Promise<any>);
|
|
15
|
+
getCommands(): LoadedCommand[];
|
|
16
|
+
load(commandsDir: string): Promise<LoadedCommand[]>;
|
|
17
|
+
private scan;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { CommandLoader, type LoadedCommand };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BaseCommand } from '../BaseCommand.js';
|
|
2
|
+
import '../CommandInterface.js';
|
|
3
|
+
|
|
4
|
+
declare class HelpCommand extends BaseCommand {
|
|
5
|
+
static description: string;
|
|
6
|
+
static args: {
|
|
7
|
+
args: {
|
|
8
|
+
name: string;
|
|
9
|
+
required: boolean;
|
|
10
|
+
description: string;
|
|
11
|
+
}[];
|
|
12
|
+
options: never[];
|
|
13
|
+
};
|
|
14
|
+
run(options: any): Promise<void>;
|
|
15
|
+
private printGlobalHelp;
|
|
16
|
+
private printCommandHelp;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { HelpCommand as default };
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
BaseCommand
|
|
4
|
+
} from "../../chunk-CKAS75E6.js";
|
|
5
|
+
import "../../chunk-IIOHHU2E.js";
|
|
6
|
+
import "../../chunk-2HJDWSDA.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/help.ts
|
|
9
|
+
import pc from "picocolors";
|
|
10
|
+
var HelpCommand = class extends BaseCommand {
|
|
11
|
+
static description = "Display help for commands.";
|
|
12
|
+
static args = {
|
|
13
|
+
args: [
|
|
14
|
+
{ name: "command...", required: false, description: "Command name to get help for" }
|
|
15
|
+
],
|
|
16
|
+
options: []
|
|
17
|
+
};
|
|
18
|
+
async run(options) {
|
|
19
|
+
const commandParts = options.command || [];
|
|
20
|
+
const query = commandParts.join(" ");
|
|
21
|
+
if (!query) {
|
|
22
|
+
this.printGlobalHelp();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const commands = this.cli.getCommands();
|
|
26
|
+
const exactMatch = commands.find((c) => c.command === query);
|
|
27
|
+
if (exactMatch) {
|
|
28
|
+
const cacCmd = this.cli.getRawCLI().commands.find((c) => c.name === query);
|
|
29
|
+
this.printCommandHelp(exactMatch, cacCmd);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const namespaceMatches = commands.filter((c) => c.command.startsWith(query + " "));
|
|
33
|
+
if (namespaceMatches.length > 0) {
|
|
34
|
+
console.log(`
|
|
35
|
+
Commands for ${pc.bold(query)}:
|
|
36
|
+
`);
|
|
37
|
+
for (const cmd of namespaceMatches) {
|
|
38
|
+
const name = cmd.command;
|
|
39
|
+
const desc = cmd.class.description || "";
|
|
40
|
+
console.log(` ${pc.cyan(name.padEnd(20))} ${desc}`);
|
|
41
|
+
}
|
|
42
|
+
console.log("");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
this.error(`Unknown command: ${query}`);
|
|
46
|
+
}
|
|
47
|
+
printGlobalHelp() {
|
|
48
|
+
const commands = this.cli.getCommands();
|
|
49
|
+
const bin = this.cli.name;
|
|
50
|
+
console.log("");
|
|
51
|
+
console.log(` Usage: ${pc.cyan(bin)} <command> [options]`);
|
|
52
|
+
console.log("");
|
|
53
|
+
console.log(" Commands:");
|
|
54
|
+
console.log("");
|
|
55
|
+
for (const cmd of commands) {
|
|
56
|
+
const name = cmd.command;
|
|
57
|
+
const desc = cmd.class.description || "";
|
|
58
|
+
console.log(` ${pc.cyan(name.padEnd(25))} ${desc}`);
|
|
59
|
+
}
|
|
60
|
+
console.log("");
|
|
61
|
+
console.log(" Options:");
|
|
62
|
+
console.log("");
|
|
63
|
+
console.log(` ${pc.yellow("--help".padEnd(25))} Display this message`);
|
|
64
|
+
console.log(` ${pc.yellow("--version".padEnd(25))} Display version number`);
|
|
65
|
+
console.log(` ${pc.yellow("--root-dir <path>".padEnd(25))} Override project root`);
|
|
66
|
+
console.log(` ${pc.yellow("--debug".padEnd(25))} Enable debug mode`);
|
|
67
|
+
console.log("");
|
|
68
|
+
}
|
|
69
|
+
printCommandHelp(loadedCommand, cacCmd) {
|
|
70
|
+
const CommandClass = loadedCommand.class;
|
|
71
|
+
let usage = CommandClass.usage;
|
|
72
|
+
if (!usage && cacCmd) usage = cacCmd.rawName;
|
|
73
|
+
if (!usage) {
|
|
74
|
+
let tempUsage = loadedCommand.command;
|
|
75
|
+
const args = CommandClass.args?.args || [];
|
|
76
|
+
args.forEach((arg) => {
|
|
77
|
+
const isVariadic = arg.name.endsWith("...");
|
|
78
|
+
const cleanName = isVariadic ? arg.name.slice(0, -3) : arg.name;
|
|
79
|
+
if (arg.required) tempUsage += isVariadic ? ` <...${cleanName}>` : ` <${cleanName}>`;
|
|
80
|
+
else tempUsage += isVariadic ? ` [...${cleanName}]` : ` [${cleanName}]`;
|
|
81
|
+
});
|
|
82
|
+
usage = tempUsage;
|
|
83
|
+
}
|
|
84
|
+
console.log("");
|
|
85
|
+
console.log(` Usage: ${pc.cyan(usage)}`);
|
|
86
|
+
console.log("");
|
|
87
|
+
const description = CommandClass.description || cacCmd && cacCmd.description || "";
|
|
88
|
+
console.log(` ${description}`);
|
|
89
|
+
console.log("");
|
|
90
|
+
const argsDef = CommandClass.args?.args;
|
|
91
|
+
if (argsDef && Array.isArray(argsDef) && argsDef.length > 0) {
|
|
92
|
+
console.log(" Arguments:");
|
|
93
|
+
for (const arg of argsDef) {
|
|
94
|
+
const name = arg.name;
|
|
95
|
+
const desc = arg.description || "";
|
|
96
|
+
const required = arg.required ? " (required)" : "";
|
|
97
|
+
console.log(` ${pc.cyan(name.padEnd(25))} ${desc}${pc.dim(required)}`);
|
|
98
|
+
}
|
|
99
|
+
console.log("");
|
|
100
|
+
}
|
|
101
|
+
const optionsList = [];
|
|
102
|
+
if (cacCmd) {
|
|
103
|
+
optionsList.push(...cacCmd.options);
|
|
104
|
+
} else {
|
|
105
|
+
const classOptions = CommandClass.args?.options || [];
|
|
106
|
+
for (const opt of classOptions) {
|
|
107
|
+
optionsList.push({
|
|
108
|
+
rawName: opt.name,
|
|
109
|
+
// e.g. '--repo <url>'
|
|
110
|
+
description: opt.description,
|
|
111
|
+
config: { default: opt.default }
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
optionsList.push({ rawName: "--help", description: "Display this message", config: {} });
|
|
115
|
+
optionsList.push({ rawName: "--version", description: "Display version number", config: {} });
|
|
116
|
+
optionsList.push({ rawName: "--root-dir <path>", description: "Override project root", config: {} });
|
|
117
|
+
optionsList.push({ rawName: "--debug", description: "Enable debug mode", config: {} });
|
|
118
|
+
}
|
|
119
|
+
if (optionsList.length > 0) {
|
|
120
|
+
console.log(" Options:");
|
|
121
|
+
for (const opt of optionsList) {
|
|
122
|
+
const flags = opt.rawName.padEnd(25);
|
|
123
|
+
const desc = opt.description || "";
|
|
124
|
+
const def = opt.config?.default ? ` (default: ${opt.config.default})` : "";
|
|
125
|
+
console.log(` ${pc.yellow(flags)} ${desc}${pc.dim(def)}`);
|
|
126
|
+
}
|
|
127
|
+
console.log("");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
export {
|
|
132
|
+
HelpCommand as default
|
|
133
|
+
};
|
|
134
|
+
//# sourceMappingURL=help.js.map
|