@nexical/cli-core 0.1.0 → 0.1.1

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.
Files changed (49) hide show
  1. package/README.md +195 -0
  2. package/cli.ts +9 -0
  3. package/dist/chunk-2NZ4H42M.js +255 -0
  4. package/dist/chunk-2NZ4H42M.js.map +1 -0
  5. package/dist/chunk-5YGASH25.js +48 -0
  6. package/dist/chunk-5YGASH25.js.map +1 -0
  7. package/dist/chunk-6LSNSDTL.js +67 -0
  8. package/dist/chunk-6LSNSDTL.js.map +1 -0
  9. package/dist/chunk-C4IL52NB.js +2 -0
  10. package/dist/chunk-C4IL52NB.js.map +1 -0
  11. package/dist/chunk-HETFF3FQ.js +20 -0
  12. package/dist/chunk-HETFF3FQ.js.map +1 -0
  13. package/dist/chunk-PFEYDXIW.js +69 -0
  14. package/dist/chunk-PFEYDXIW.js.map +1 -0
  15. package/dist/cli.d.ts +1 -0
  16. package/dist/cli.js +15 -0
  17. package/dist/cli.js.map +1 -0
  18. package/dist/index.d.ts +4 -0
  19. package/dist/index.js +16 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/src/BaseCommand.d.ts +21 -0
  22. package/dist/src/BaseCommand.js +10 -0
  23. package/dist/src/BaseCommand.js.map +1 -0
  24. package/dist/src/CLI.d.ts +23 -0
  25. package/dist/src/CLI.js +10 -0
  26. package/dist/src/CLI.js.map +1 -0
  27. package/dist/src/CommandInterface.d.ts +21 -0
  28. package/dist/src/CommandInterface.js +3 -0
  29. package/dist/src/CommandInterface.js.map +1 -0
  30. package/dist/src/CommandLoader.d.ts +20 -0
  31. package/dist/src/CommandLoader.js +9 -0
  32. package/dist/src/CommandLoader.js.map +1 -0
  33. package/dist/src/commands/help.d.ts +19 -0
  34. package/dist/src/commands/help.js +134 -0
  35. package/dist/src/commands/help.js.map +1 -0
  36. package/dist/src/utils/config.d.ts +7 -0
  37. package/dist/src/utils/config.js +13 -0
  38. package/dist/src/utils/config.js.map +1 -0
  39. package/dist/src/utils/logger.d.ts +6 -0
  40. package/dist/src/utils/logger.js +10 -0
  41. package/dist/src/utils/logger.js.map +1 -0
  42. package/dist/src/utils/shell.d.ts +3 -0
  43. package/dist/src/utils/shell.js +28 -0
  44. package/dist/src/utils/shell.js.map +1 -0
  45. package/index.ts +3 -9
  46. package/package.json +7 -2
  47. package/test/utils/integration-helpers.ts +1 -1
  48. package/tsconfig.json +2 -2
  49. package/tsup.config.ts +1 -1
@@ -0,0 +1,69 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ logger
4
+ } from "./chunk-HETFF3FQ.js";
5
+
6
+ // src/CommandLoader.ts
7
+ import fs from "fs";
8
+ import path from "path";
9
+ var CommandLoader = class {
10
+ cli = null;
11
+ commands = [];
12
+ importer;
13
+ constructor(cli, importer = (p) => import(p)) {
14
+ this.cli = cli;
15
+ this.importer = importer;
16
+ }
17
+ getCommands() {
18
+ return this.commands;
19
+ }
20
+ async load(commandsDir) {
21
+ logger.debug(`Loading commands from: ${commandsDir}`);
22
+ if (!fs.existsSync(commandsDir)) {
23
+ logger.debug(`Commands directory not found: ${commandsDir}`);
24
+ return [];
25
+ }
26
+ await this.scan(commandsDir, []);
27
+ return this.commands;
28
+ }
29
+ async scan(dir, prefix) {
30
+ const files = fs.readdirSync(dir);
31
+ for (const file of files) {
32
+ const fullPath = path.join(dir, file);
33
+ const stat = fs.statSync(fullPath);
34
+ if (stat.isDirectory()) {
35
+ await this.scan(fullPath, [...prefix, file]);
36
+ } else if ((file.endsWith(".ts") || file.endsWith(".js")) && !file.endsWith(".d.ts")) {
37
+ logger.debug(`Found potential command file: ${fullPath}`);
38
+ const name = path.basename(file, path.extname(file));
39
+ const commandParts = [...prefix];
40
+ if (name !== "index") {
41
+ commandParts.push(name);
42
+ } else if (commandParts.length === 0) {
43
+ continue;
44
+ }
45
+ try {
46
+ const module = await this.importer(fullPath);
47
+ const CommandClass = module.default;
48
+ if (CommandClass) {
49
+ const commandName = commandParts.join(" ");
50
+ logger.debug(`Registered command: ${commandName}`);
51
+ this.commands.push({
52
+ command: commandName,
53
+ path: fullPath,
54
+ instance: new CommandClass(this.cli),
55
+ class: CommandClass
56
+ });
57
+ }
58
+ } catch (e) {
59
+ logger.error(`Failed to load command at ${fullPath}`, e);
60
+ }
61
+ }
62
+ }
63
+ }
64
+ };
65
+
66
+ export {
67
+ CommandLoader
68
+ };
69
+ //# sourceMappingURL=chunk-PFEYDXIW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/CommandLoader.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { BaseCommand } from './BaseCommand.js';\nimport { logger } from './utils/logger.js';\n\nexport interface LoadedCommand {\n command: string;\n path: string;\n instance: BaseCommand;\n class: any;\n}\n\nexport class CommandLoader {\n private cli: any = null;\n private commands: LoadedCommand[] = [];\n private importer: (path: string) => Promise<any>;\n\n constructor(cli: any, importer: (path: string) => Promise<any> = (p) => import(p)) {\n this.cli = cli;\n this.importer = importer;\n }\n\n getCommands(): LoadedCommand[] {\n return this.commands;\n }\n\n async load(commandsDir: string): Promise<LoadedCommand[]> {\n logger.debug(`Loading commands from: ${commandsDir}`);\n if (!fs.existsSync(commandsDir)) {\n logger.debug(`Commands directory not found: ${commandsDir}`);\n return [];\n }\n\n await this.scan(commandsDir, []);\n return this.commands;\n }\n\n private async scan(dir: string, prefix: string[]) {\n const files = fs.readdirSync(dir);\n\n for (const file of files) {\n const fullPath = path.join(dir, file);\n const stat = fs.statSync(fullPath);\n\n if (stat.isDirectory()) {\n await this.scan(fullPath, [...prefix, file]);\n } else if ((file.endsWith('.ts') || file.endsWith('.js')) && !file.endsWith('.d.ts')) {\n // Ignore index files or non-command files if needed, but for now scan all.\n // Assuming \"index.ts\" might be the command for the directory path itself if we supported that,\n // but let's stick to \"create.ts\" -> \"create\"\n logger.debug(`Found potential command file: ${fullPath}`);\n\n const name = path.basename(file, path.extname(file));\n const commandParts = [...prefix];\n if (name !== 'index') {\n commandParts.push(name);\n } else if (commandParts.length === 0) {\n continue; // skip src/commands/index.ts if it exists and doesn't map to anything specific\n }\n\n // Import\n try {\n const module = await this.importer(fullPath);\n // Assume default export is the command class\n const CommandClass = module.default;\n\n if (CommandClass) { // Loose check for now to debug\n const commandName = commandParts.join(' ');\n logger.debug(`Registered command: ${commandName}`);\n this.commands.push({\n command: commandName,\n path: fullPath,\n instance: new CommandClass(this.cli),\n class: CommandClass\n });\n }\n } catch (e) {\n logger.error(`Failed to load command at ${fullPath}`, e);\n }\n }\n }\n }\n}\n"],"mappings":";;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AAWV,IAAM,gBAAN,MAAoB;AAAA,EACf,MAAW;AAAA,EACX,WAA4B,CAAC;AAAA,EAC7B;AAAA,EAER,YAAY,KAAU,WAA2C,CAAC,MAAM,OAAO,IAAI;AAC/E,SAAK,MAAM;AACX,SAAK,WAAW;AAAA,EACpB;AAAA,EAEA,cAA+B;AAC3B,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAM,KAAK,aAA+C;AACtD,WAAO,MAAM,0BAA0B,WAAW,EAAE;AACpD,QAAI,CAAC,GAAG,WAAW,WAAW,GAAG;AAC7B,aAAO,MAAM,iCAAiC,WAAW,EAAE;AAC3D,aAAO,CAAC;AAAA,IACZ;AAEA,UAAM,KAAK,KAAK,aAAa,CAAC,CAAC;AAC/B,WAAO,KAAK;AAAA,EAChB;AAAA,EAEA,MAAc,KAAK,KAAa,QAAkB;AAC9C,UAAM,QAAQ,GAAG,YAAY,GAAG;AAEhC,eAAW,QAAQ,OAAO;AACtB,YAAM,WAAW,KAAK,KAAK,KAAK,IAAI;AACpC,YAAM,OAAO,GAAG,SAAS,QAAQ;AAEjC,UAAI,KAAK,YAAY,GAAG;AACpB,cAAM,KAAK,KAAK,UAAU,CAAC,GAAG,QAAQ,IAAI,CAAC;AAAA,MAC/C,YAAY,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,GAAG;AAIlF,eAAO,MAAM,iCAAiC,QAAQ,EAAE;AAExD,cAAM,OAAO,KAAK,SAAS,MAAM,KAAK,QAAQ,IAAI,CAAC;AACnD,cAAM,eAAe,CAAC,GAAG,MAAM;AAC/B,YAAI,SAAS,SAAS;AAClB,uBAAa,KAAK,IAAI;AAAA,QAC1B,WAAW,aAAa,WAAW,GAAG;AAClC;AAAA,QACJ;AAGA,YAAI;AACA,gBAAM,SAAS,MAAM,KAAK,SAAS,QAAQ;AAE3C,gBAAM,eAAe,OAAO;AAE5B,cAAI,cAAc;AACd,kBAAM,cAAc,aAAa,KAAK,GAAG;AACzC,mBAAO,MAAM,uBAAuB,WAAW,EAAE;AACjD,iBAAK,SAAS,KAAK;AAAA,cACf,SAAS;AAAA,cACT,MAAM;AAAA,cACN,UAAU,IAAI,aAAa,KAAK,GAAG;AAAA,cACnC,OAAO;AAAA,YACX,CAAC;AAAA,UACL;AAAA,QACJ,SAAS,GAAG;AACR,iBAAO,MAAM,6BAA6B,QAAQ,IAAI,CAAC;AAAA,QAC3D;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AACJ;","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-2NZ4H42M.js";
6
+ import "./chunk-PFEYDXIW.js";
7
+ import {
8
+ logger
9
+ } from "./chunk-HETFF3FQ.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
@@ -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":[]}
@@ -0,0 +1,4 @@
1
+ export { CLI, CLIConfig } from './src/CLI.js';
2
+ export { BaseCommand } from './src/BaseCommand.js';
3
+ export { CommandArg, CommandDefinition, CommandInterface, CommandOption } from './src/CommandInterface.js';
4
+ import 'cac';
package/dist/index.js ADDED
@@ -0,0 +1,16 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ CLI
4
+ } from "./chunk-2NZ4H42M.js";
5
+ import "./chunk-C4IL52NB.js";
6
+ import "./chunk-PFEYDXIW.js";
7
+ import {
8
+ BaseCommand
9
+ } from "./chunk-6LSNSDTL.js";
10
+ import "./chunk-5YGASH25.js";
11
+ import "./chunk-HETFF3FQ.js";
12
+ export {
13
+ BaseCommand,
14
+ CLI
15
+ };
16
+ //# 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-6LSNSDTL.js";
5
+ import "../chunk-5YGASH25.js";
6
+ import "../chunk-HETFF3FQ.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 };
@@ -0,0 +1,10 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ CLI
4
+ } from "../chunk-2NZ4H42M.js";
5
+ import "../chunk-PFEYDXIW.js";
6
+ import "../chunk-HETFF3FQ.js";
7
+ export {
8
+ CLI
9
+ };
10
+ //# sourceMappingURL=CLI.js.map
@@ -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,3 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import "../chunk-C4IL52NB.js";
3
+ //# sourceMappingURL=CommandInterface.js.map
@@ -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,9 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ CommandLoader
4
+ } from "../chunk-PFEYDXIW.js";
5
+ import "../chunk-HETFF3FQ.js";
6
+ export {
7
+ CommandLoader
8
+ };
9
+ //# sourceMappingURL=CommandLoader.js.map
@@ -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-6LSNSDTL.js";
5
+ import "../../chunk-5YGASH25.js";
6
+ import "../../chunk-HETFF3FQ.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
@@ -0,0 +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":[]}
@@ -0,0 +1,7 @@
1
+ import { Loader } from 'lilconfig';
2
+
3
+ declare const loadYaml: Loader;
4
+ declare function findProjectRoot(commandName: string, startDir: string): Promise<string | null>;
5
+ declare function loadConfig(commandName: string, rootDir: string): Promise<any>;
6
+
7
+ export { findProjectRoot, loadConfig, loadYaml };
@@ -0,0 +1,13 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ findProjectRoot,
4
+ loadConfig,
5
+ loadYaml
6
+ } from "../../chunk-5YGASH25.js";
7
+ import "../../chunk-HETFF3FQ.js";
8
+ export {
9
+ findProjectRoot,
10
+ loadConfig,
11
+ loadYaml
12
+ };
13
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,6 @@
1
+ import * as consola from 'consola';
2
+
3
+ declare const logger: consola.ConsolaInstance;
4
+ declare function setDebugMode(enabled: boolean): void;
5
+
6
+ export { logger, setDebugMode };
@@ -0,0 +1,10 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ logger,
4
+ setDebugMode
5
+ } from "../../chunk-HETFF3FQ.js";
6
+ export {
7
+ logger,
8
+ setDebugMode
9
+ };
10
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,3 @@
1
+ declare function runCommand(command: string, cwd?: string): Promise<void>;
2
+
3
+ export { runCommand };
@@ -0,0 +1,28 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ logger
4
+ } from "../../chunk-HETFF3FQ.js";
5
+
6
+ // src/utils/shell.ts
7
+ import { exec } from "child_process";
8
+ import { promisify } from "util";
9
+ var execAsync = promisify(exec);
10
+ async function runCommand(command, cwd) {
11
+ try {
12
+ logger.debug(`Executing command: ${command} in ${cwd || process.cwd()}`);
13
+ const { stdout } = await execAsync(command, { cwd });
14
+ if (stdout) {
15
+ console.log(stdout);
16
+ }
17
+ } catch (error) {
18
+ logger.error(`Command failed: ${command}`);
19
+ if (error.stderr) {
20
+ logger.error(error.stderr);
21
+ }
22
+ throw new Error(`Command failed: ${command}`);
23
+ }
24
+ }
25
+ export {
26
+ runCommand
27
+ };
28
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/shell.ts"],"sourcesContent":["import { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { logger } from './logger.js';\n\nconst execAsync = promisify(exec);\n\nexport async function runCommand(command: string, cwd?: string): Promise<void> {\n try {\n logger.debug(`Executing command: ${command} in ${cwd || process.cwd()}`);\n const { stdout } = await execAsync(command, { cwd });\n if (stdout) {\n console.log(stdout);\n }\n } catch (error: any) {\n logger.error(`Command failed: ${command}`);\n if (error.stderr) {\n logger.error(error.stderr);\n }\n throw new Error(`Command failed: ${command}`);\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAG1B,IAAM,YAAY,UAAU,IAAI;AAEhC,eAAsB,WAAW,SAAiB,KAA6B;AAC3E,MAAI;AACA,WAAO,MAAM,sBAAsB,OAAO,OAAO,OAAO,QAAQ,IAAI,CAAC,EAAE;AACvE,UAAM,EAAE,OAAO,IAAI,MAAM,UAAU,SAAS,EAAE,IAAI,CAAC;AACnD,QAAI,QAAQ;AACR,cAAQ,IAAI,MAAM;AAAA,IACtB;AAAA,EACJ,SAAS,OAAY;AACjB,WAAO,MAAM,mBAAmB,OAAO,EAAE;AACzC,QAAI,MAAM,QAAQ;AACd,aAAO,MAAM,MAAM,MAAM;AAAA,IAC7B;AACA,UAAM,IAAI,MAAM,mBAAmB,OAAO,EAAE;AAAA,EAChD;AACJ;","names":[]}
package/index.ts CHANGED
@@ -1,9 +1,3 @@
1
- #!/usr/bin/env node
2
- import { CLI } from './src/CLI.js';
3
-
4
- import { logger } from './src/utils/logger.js';
5
-
6
- logger.debug('CLI ENTRY POINT HIT', process.argv);
7
-
8
- const app = new CLI();
9
- app.start();
1
+ export { CLI, CLIConfig } from './src/CLI.js';
2
+ export { BaseCommand } from './src/BaseCommand.js';
3
+ export * from './src/CommandInterface.js';
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "@nexical/cli-core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": "./dist/index.js"
9
+ },
5
10
  "scripts": {
6
11
  "build": "tsup",
7
12
  "dev": "tsup --watch",
8
- "cli": "node dist/index.js",
13
+ "cli": "node dist/cli.js",
9
14
  "test": "npm run test:unit && npm run test:integration && npm run test:e2e",
10
15
  "test:unit": "vitest run --config vitest.config.ts --coverage",
11
16
  "test:integration": "vitest run --config vitest.integration.config.ts",
@@ -4,7 +4,7 @@ import { fileURLToPath } from 'node:url';
4
4
 
5
5
  // Constants
6
6
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
7
- export const CLI_BIN = path.resolve(__dirname, '../../dist/index.js');
7
+ export const CLI_BIN = path.resolve(__dirname, '../../dist/cli.js');
8
8
 
9
9
  /**
10
10
  * Runs the CLI command against the compiled binary (E2E style)
package/tsconfig.json CHANGED
@@ -14,9 +14,9 @@
14
14
  "outDir": "./dist"
15
15
  },
16
16
  "include": [
17
+ "cli.ts",
17
18
  "src/**/*",
18
- "test/**/*",
19
- "../utils/environment.ts"
19
+ "test/**/*"
20
20
  ],
21
21
  "exclude": [
22
22
  "node_modules",
package/tsup.config.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { Options } from 'tsup';
2
2
 
3
3
  export default <Options>{
4
- entry: ['index.ts', 'src/**/*.ts'],
4
+ entry: ['index.ts', 'cli.ts', 'src/**/*.ts'],
5
5
  format: ['esm'],
6
6
  target: 'node18',
7
7
  clean: true,