@nexical/cli 0.11.15 → 0.11.16
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/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/src/commands/init.js +6 -6
- package/dist/src/commands/module/add.js +3 -3
- package/package.json +1 -1
- package/GEMINI.md +0 -199
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\nimport { CLI, findProjectRoot } from '@nexical/cli-core';\nimport { fileURLToPath } from 'node:url';\nimport { discoverCommandDirectories } from './src/utils/discovery.js';\nimport pkg from './package.json';\nimport path from 'node:path';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst commandName = 'nexical';\nconst projectRoot = (await findProjectRoot(commandName, process.cwd())) || process.cwd();\nconst coreCommandsDir = path.resolve(__dirname, './src/commands');\nconst additionalCommands = discoverCommandDirectories(projectRoot);\n\n// Filter out duplicate core commands and source versions\nconst filteredAdditional = additionalCommands.filter((dir) => {\n const resolvedDir = path.resolve(dir);\n const resolvedCore = path.resolve(coreCommandsDir);\n\n if (resolvedDir === resolvedCore) return false;\n\n // Check if this is another instance of the core CLI commands (by checking path suffix)\n const coreSuffix = path.join('@nexical', 'cli', 'dist', 'src', 'commands');\n const coreSuffixSrc = path.join('packages', 'cli', 'dist', 'src', 'commands');\n const coreSuffixRawSrc = path.join('packages', 'cli', 'src', 'commands');\n\n if (\n resolvedDir.endsWith(coreSuffix) ||\n resolvedDir.endsWith(coreSuffixSrc) ||\n resolvedDir.endsWith(coreSuffixRawSrc)\n ) {\n return false;\n }\n\n // Handle mismatch between dist/src and src/\n if (resolvedCore.includes(path.join(path.sep, 'dist', 'src', 'commands'))) {\n const srcVersion = resolvedCore.replace(\n path.join(path.sep, 'dist', 'src', 'commands'),\n path.join(path.sep, 'src', 'commands'),\n );\n if (resolvedDir === srcVersion) return false;\n }\n\n return true;\n});\n\nconst app = new CLI({\n version: pkg.version,\n commandName: commandName,\n searchDirectories: [...new Set([coreCommandsDir, ...filteredAdditional])],\n});\napp.start();\n","{\n \"name\": \"@nexical/cli\",\n \"version\": \"0.11.
|
|
1
|
+
{"version":3,"sources":["../index.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\nimport { CLI, findProjectRoot } from '@nexical/cli-core';\nimport { fileURLToPath } from 'node:url';\nimport { discoverCommandDirectories } from './src/utils/discovery.js';\nimport pkg from './package.json';\nimport path from 'node:path';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst commandName = 'nexical';\nconst projectRoot = (await findProjectRoot(commandName, process.cwd())) || process.cwd();\nconst coreCommandsDir = path.resolve(__dirname, './src/commands');\nconst additionalCommands = discoverCommandDirectories(projectRoot);\n\n// Filter out duplicate core commands and source versions\nconst filteredAdditional = additionalCommands.filter((dir) => {\n const resolvedDir = path.resolve(dir);\n const resolvedCore = path.resolve(coreCommandsDir);\n\n if (resolvedDir === resolvedCore) return false;\n\n // Check if this is another instance of the core CLI commands (by checking path suffix)\n const coreSuffix = path.join('@nexical', 'cli', 'dist', 'src', 'commands');\n const coreSuffixSrc = path.join('packages', 'cli', 'dist', 'src', 'commands');\n const coreSuffixRawSrc = path.join('packages', 'cli', 'src', 'commands');\n\n if (\n resolvedDir.endsWith(coreSuffix) ||\n resolvedDir.endsWith(coreSuffixSrc) ||\n resolvedDir.endsWith(coreSuffixRawSrc)\n ) {\n return false;\n }\n\n // Handle mismatch between dist/src and src/\n if (resolvedCore.includes(path.join(path.sep, 'dist', 'src', 'commands'))) {\n const srcVersion = resolvedCore.replace(\n path.join(path.sep, 'dist', 'src', 'commands'),\n path.join(path.sep, 'src', 'commands'),\n );\n if (resolvedDir === srcVersion) return false;\n }\n\n return true;\n});\n\nconst app = new CLI({\n version: pkg.version,\n commandName: commandName,\n searchDirectories: [...new Set([coreCommandsDir, ...filteredAdditional])],\n});\napp.start();\n","{\n \"name\": \"@nexical/cli\",\n \"version\": \"0.11.16\",\n \"license\": \"Apache-2.0\",\n \"type\": \"module\",\n \"bin\": {\n \"nexical\": \"./dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"start\": \"node dist/index.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 \"format\": \"prettier --write .\",\n \"lint\": \"eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"prepare\": \"husky\"\n },\n \"lint-staged\": {\n \"**/*\": [\n \"prettier --write --ignore-unknown\"\n ],\n \"**/*.{js,jsx,ts,tsx,astro}\": [\n \"eslint --fix\"\n ]\n },\n \"dependencies\": {\n \"@nexical/cli-core\": \"^0.1.16\",\n \"dotenv\": \"^17.3.1\",\n \"fast-glob\": \"^3.3.3\",\n \"glob\": \"^13.0.5\",\n \"jiti\": \"^2.6.1\",\n \"yaml\": \"^2.8.2\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.2\",\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/node\": \"^25.3.0\",\n \"@vitest/coverage-v8\": \"^4.0.18\",\n \"eslint\": \"^9.39.2\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-astro\": \"^1.6.0\",\n \"eslint-plugin-jsx-a11y\": \"^6.10.2\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"eslint-plugin-react-hooks\": \"^7.0.1\",\n \"execa\": \"^9.6.1\",\n \"fs-extra\": \"^11.3.3\",\n \"globals\": \"^17.3.0\",\n \"husky\": \"^9.1.7\",\n \"lint-staged\": \"^16.2.7\",\n \"prettier\": \"^3.8.1\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^5.9.3\",\n \"typescript-eslint\": \"^8.56.0\",\n \"vitest\": \"^4.0.18\"\n }\n}\n"],"mappings":";;;;;;;;;;AAAA;AACA,SAAS,KAAK,uBAAuB;AACrC,SAAS,qBAAqB;;;ACF9B;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,SAAW;AAAA,EACX,MAAQ;AAAA,EACR,KAAO;AAAA,IACL,SAAW;AAAA,EACb;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,QAAU;AAAA,IACV,MAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAW;AAAA,EACb;AAAA,EACA,eAAe;AAAA,IACb,QAAQ;AAAA,MACN;AAAA,IACF;AAAA,IACA,8BAA8B;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA,EACA,cAAgB;AAAA,IACd,qBAAqB;AAAA,IACrB,QAAU;AAAA,IACV,aAAa;AAAA,IACb,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,MAAQ;AAAA,EACV;AAAA,EACA,iBAAmB;AAAA,IACjB,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,uBAAuB;AAAA,IACvB,QAAU;AAAA,IACV,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,6BAA6B;AAAA,IAC7B,OAAS;AAAA,IACT,YAAY;AAAA,IACZ,SAAW;AAAA,IACX,OAAS;AAAA,IACT,eAAe;AAAA,IACf,UAAY;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,YAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,QAAU;AAAA,EACZ;AACF;;;ADxDA,OAAO,UAAU;AAEjB,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE7D,IAAM,cAAc;AACpB,IAAM,cAAe,MAAM,gBAAgB,aAAa,QAAQ,IAAI,CAAC,KAAM,QAAQ,IAAI;AACvF,IAAM,kBAAkB,KAAK,QAAQ,WAAW,gBAAgB;AAChE,IAAM,qBAAqB,2BAA2B,WAAW;AAGjE,IAAM,qBAAqB,mBAAmB,OAAO,CAAC,QAAQ;AAC5D,QAAM,cAAc,KAAK,QAAQ,GAAG;AACpC,QAAM,eAAe,KAAK,QAAQ,eAAe;AAEjD,MAAI,gBAAgB,aAAc,QAAO;AAGzC,QAAM,aAAa,KAAK,KAAK,YAAY,OAAO,QAAQ,OAAO,UAAU;AACzE,QAAM,gBAAgB,KAAK,KAAK,YAAY,OAAO,QAAQ,OAAO,UAAU;AAC5E,QAAM,mBAAmB,KAAK,KAAK,YAAY,OAAO,OAAO,UAAU;AAEvE,MACE,YAAY,SAAS,UAAU,KAC/B,YAAY,SAAS,aAAa,KAClC,YAAY,SAAS,gBAAgB,GACrC;AACA,WAAO;AAAA,EACT;AAGA,MAAI,aAAa,SAAS,KAAK,KAAK,KAAK,KAAK,QAAQ,OAAO,UAAU,CAAC,GAAG;AACzE,UAAM,aAAa,aAAa;AAAA,MAC9B,KAAK,KAAK,KAAK,KAAK,QAAQ,OAAO,UAAU;AAAA,MAC7C,KAAK,KAAK,KAAK,KAAK,OAAO,UAAU;AAAA,IACvC;AACA,QAAI,gBAAgB,WAAY,QAAO;AAAA,EACzC;AAEA,SAAO;AACT,CAAC;AAED,IAAM,MAAM,IAAI,IAAI;AAAA,EAClB,SAAS,gBAAI;AAAA,EACb;AAAA,EACA,mBAAmB,CAAC,GAAG,oBAAI,IAAI,CAAC,iBAAiB,GAAG,kBAAkB,CAAC,CAAC;AAC1E,CAAC;AACD,IAAI,MAAM;","names":[]}
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
SetupCommand
|
|
4
|
-
} from "../../chunk-GUUPSHWC.js";
|
|
5
|
-
import {
|
|
6
|
-
require_lib
|
|
7
|
-
} from "../../chunk-OUGA4CB4.js";
|
|
8
2
|
import {
|
|
9
3
|
addAll,
|
|
10
4
|
clone,
|
|
@@ -15,6 +9,12 @@ import {
|
|
|
15
9
|
import {
|
|
16
10
|
resolveGitUrl
|
|
17
11
|
} from "../../chunk-PJIOCW2A.js";
|
|
12
|
+
import {
|
|
13
|
+
SetupCommand
|
|
14
|
+
} from "../../chunk-GUUPSHWC.js";
|
|
15
|
+
import {
|
|
16
|
+
require_lib
|
|
17
|
+
} from "../../chunk-OUGA4CB4.js";
|
|
18
18
|
import {
|
|
19
19
|
__toESM,
|
|
20
20
|
init_esm_shims
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
require_lib
|
|
4
|
-
} from "../../../chunk-OUGA4CB4.js";
|
|
5
2
|
import {
|
|
6
3
|
addSubmodule,
|
|
7
4
|
clone,
|
|
@@ -10,6 +7,9 @@ import {
|
|
|
10
7
|
import {
|
|
11
8
|
resolveGitUrl
|
|
12
9
|
} from "../../../chunk-PJIOCW2A.js";
|
|
10
|
+
import {
|
|
11
|
+
require_lib
|
|
12
|
+
} from "../../../chunk-OUGA4CB4.js";
|
|
13
13
|
import {
|
|
14
14
|
__toESM,
|
|
15
15
|
init_esm_shims
|
package/package.json
CHANGED
package/GEMINI.md
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
# Nexical CLI Core Development Guide
|
|
2
|
-
|
|
3
|
-
This guide details how to build command libraries and CLIs using the `@nexical/cli-core` framework within this project.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The project is configured to use `@nexical/cli-core` as its CLI framework. usage entails:
|
|
8
|
-
|
|
9
|
-
1. **Entry Point**: `index.ts` initializes the `CLI` instance.
|
|
10
|
-
2. **Command Discovery**: The CLI automatically scans `src/commands` for command files.
|
|
11
|
-
3. **Command Implementation**: Commands are TypeScript classes extending `BaseCommand`.
|
|
12
|
-
|
|
13
|
-
## Directory Structure
|
|
14
|
-
|
|
15
|
-
Commands are defined in `src/commands`. The file structure directly maps to the command hierarchy.
|
|
16
|
-
|
|
17
|
-
| File Path | Command | Description |
|
|
18
|
-
| :---------------------------- | :---------------- | :-------------------------------- |
|
|
19
|
-
| `src/commands/init.ts` | `app init` | Root level command |
|
|
20
|
-
| `src/commands/user/create.ts` | `app user create` | Subcommand |
|
|
21
|
-
| `src/commands/user/index.ts` | `app user` | Parent command handler (optional) |
|
|
22
|
-
|
|
23
|
-
> **Note**: The CLI name (`app`) is configured in `index.ts`.
|
|
24
|
-
|
|
25
|
-
## Creating a New Command
|
|
26
|
-
|
|
27
|
-
To create a new command, add a `.ts` file in `src/commands`.
|
|
28
|
-
|
|
29
|
-
### 1. Basic Command Template
|
|
30
|
-
|
|
31
|
-
Create `src/commands/hello.ts`:
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
35
|
-
|
|
36
|
-
export default class HelloCommand extends BaseCommand {
|
|
37
|
-
// Description displayed in help menus
|
|
38
|
-
static description = 'Prints a hello message';
|
|
39
|
-
|
|
40
|
-
// The main execution method
|
|
41
|
-
async run(options: any) {
|
|
42
|
-
this.success('Hello World!');
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
**Run it:**
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
npm run cli hello
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### 2. Arguments and Options
|
|
54
|
-
|
|
55
|
-
Use the static `args` property to define inputs.
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
59
|
-
|
|
60
|
-
export default class GreetCommand extends BaseCommand {
|
|
61
|
-
static description = 'Greets a user';
|
|
62
|
-
|
|
63
|
-
static args = {
|
|
64
|
-
// Positional Arguments
|
|
65
|
-
args: [
|
|
66
|
-
{
|
|
67
|
-
name: 'name',
|
|
68
|
-
description: 'Name of the user',
|
|
69
|
-
required: true,
|
|
70
|
-
},
|
|
71
|
-
],
|
|
72
|
-
// Options (Flags)
|
|
73
|
-
options: [
|
|
74
|
-
{
|
|
75
|
-
name: '--loud',
|
|
76
|
-
description: 'Print in uppercase',
|
|
77
|
-
default: false,
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
name: '-c, --count <n>',
|
|
81
|
-
description: 'Number of times to greet',
|
|
82
|
-
default: 1,
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
async run(options: any) {
|
|
88
|
-
// 'name' is mapped from args
|
|
89
|
-
// 'loud' and 'count' are mapped from options
|
|
90
|
-
const { name, loud, count } = options;
|
|
91
|
-
|
|
92
|
-
let message = `Hello, ${name}`;
|
|
93
|
-
if (loud) message = message.toUpperCase();
|
|
94
|
-
|
|
95
|
-
for (let i = 0; i < count; i++) {
|
|
96
|
-
this.info(message);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
**Run it:**
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
npm run cli greet Adrian --loud --count 3
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
### 3. User Input & Prompts
|
|
109
|
-
|
|
110
|
-
`BaseCommand` provides built-in methods for interactivity.
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
export default class InteractiveCommand extends BaseCommand {
|
|
114
|
-
async run() {
|
|
115
|
-
// Simple confirmation or input
|
|
116
|
-
const name = await this.prompt('What is your name?');
|
|
117
|
-
|
|
118
|
-
this.success(`Nice to meet you, ${name}`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### 4. Output Helpers
|
|
124
|
-
|
|
125
|
-
Use the built-in helper methods for consistent logging:
|
|
126
|
-
|
|
127
|
-
- `this.success(msg)`: Green checkmark (✔ Success)
|
|
128
|
-
- `this.error(msg)`: Red cross (✖ Error) - **Exits process**
|
|
129
|
-
- `this.warn(msg)`: Yellow warning (⚠ Warning)
|
|
130
|
-
- `this.info(msg)`: Standard log
|
|
131
|
-
- `this.notice(msg)`: Blue notice (📢 Note)
|
|
132
|
-
- `this.input(msg)`: Cyan input prompt (? Question)
|
|
133
|
-
|
|
134
|
-
## Subcommands
|
|
135
|
-
|
|
136
|
-
To create grouped commands (e.g., `user create`, `user list`), use directories.
|
|
137
|
-
|
|
138
|
-
1. **Create Directory**: `src/commands/user/`
|
|
139
|
-
2. **Add Commands**:
|
|
140
|
-
- `src/commands/user/create.ts` -> `app user create`
|
|
141
|
-
- `src/commands/user/list.ts` -> `app user list`
|
|
142
|
-
|
|
143
|
-
### Index Commands (Container Commands)
|
|
144
|
-
|
|
145
|
-
If you need the parent command `app user` to do something (or just provide a description for the group), create `src/commands/user/index.ts`.
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
// src/commands/user/index.ts
|
|
149
|
-
import { BaseCommand } from '@nexical/cli-core';
|
|
150
|
-
|
|
151
|
-
export default class UserCommand extends BaseCommand {
|
|
152
|
-
static description = 'Manage users';
|
|
153
|
-
|
|
154
|
-
async run() {
|
|
155
|
-
// This runs when user types 'app user' without a subcommand
|
|
156
|
-
// Often used to show help
|
|
157
|
-
this.cli.getRawCLI().outputHelp();
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
## Internal API Reference
|
|
163
|
-
|
|
164
|
-
### `BaseCommand`
|
|
165
|
-
|
|
166
|
-
All commands inherit from `BaseCommand`.
|
|
167
|
-
|
|
168
|
-
**Properties:**
|
|
169
|
-
|
|
170
|
-
- `cli`: Access to the main `CLI` instance.
|
|
171
|
-
- `projectRoot`: Path to the project root (if detected).
|
|
172
|
-
- `config`: Loaded configuration from `{cliName}.yml`.
|
|
173
|
-
- `globalOptions`: Global flags passed to the CLI (e.g., `--debug`).
|
|
174
|
-
|
|
175
|
-
**Methods:**
|
|
176
|
-
|
|
177
|
-
- `init()`: Called before `run()`. Useful for setup.
|
|
178
|
-
- `run(options)`: Abstract method. Must be implemented.
|
|
179
|
-
- `prompt(message)`: Async, returns string.
|
|
180
|
-
|
|
181
|
-
**Static Properties:**
|
|
182
|
-
|
|
183
|
-
- `description`: String. Shown in help.
|
|
184
|
-
- `args`: Object. Defines arguments and options.
|
|
185
|
-
- `args`: Array of `{ name, description, required, default }`.
|
|
186
|
-
- `options`: Array of `{ name, description, default }`.
|
|
187
|
-
- `requiresProject`: Boolean. If true, command fails if not run inside a project with a config file.
|
|
188
|
-
|
|
189
|
-
## Best Practices
|
|
190
|
-
|
|
191
|
-
1. **Type Safety**: While `options` is `any` in `run()`, validate inputs early.
|
|
192
|
-
2. **Error Handling**: Use `this.error()` for fatal errors to ensure proper exit codes.
|
|
193
|
-
3. **Clean Output**: Use the helper methods (`success`, `info`, etc.) instead of `console.log` for a consistent UI.
|
|
194
|
-
4. **Async**: The `run` method is async. Always `await` asynchronous operations.
|
|
195
|
-
|
|
196
|
-
## Troubleshooting
|
|
197
|
-
|
|
198
|
-
- **Command not found**: Ensure the file exports a class leveraging `export default` and extends `BaseCommand`.
|
|
199
|
-
- **Changes not reflected**: If using `tsup`, ensure you are building or running in dev mode (`npm run dev`). For `npm run cli` using `ts-node` (via `cli.ts` or similar), changes should be instant.
|