@ontrails/cli 1.0.0-beta.2 → 1.0.0-beta.4
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/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +44 -0
- package/README.md +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +7 -8
- package/dist/build.js.map +1 -1
- package/dist/command.d.ts +1 -2
- package/dist/command.d.ts.map +1 -1
- package/dist/commander/blaze.d.ts +1 -1
- package/dist/commander/blaze.d.ts.map +1 -1
- package/dist/commander/blaze.js +2 -2
- package/dist/commander/blaze.js.map +1 -1
- package/dist/commander/to-commander.d.ts.map +1 -1
- package/dist/commander/to-commander.js +25 -7
- package/dist/commander/to-commander.js.map +1 -1
- package/dist/flags.d.ts.map +1 -1
- package/dist/flags.js +2 -0
- package/dist/flags.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/blaze.test.ts +13 -4
- package/src/__tests__/build.test.ts +16 -18
- package/src/__tests__/layers.test.ts +5 -7
- package/src/__tests__/to-commander.test.ts +170 -7
- package/src/build.ts +7 -8
- package/src/command.ts +1 -2
- package/src/commander/blaze.ts +5 -2
- package/src/commander/to-commander.ts +30 -7
- package/src/flags.ts +2 -0
package/.turbo/turbo-lint.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# @ontrails/cli
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.4
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- API simplification: unified trail model, intent enum, run, metadata.
|
|
8
|
+
|
|
9
|
+
**BREAKING CHANGES:**
|
|
10
|
+
|
|
11
|
+
- `hike()` removed — use `trail()` with optional `follow: [...]` field
|
|
12
|
+
- `follows` renamed to `follow` (singular, matching `ctx.follow()`)
|
|
13
|
+
- `topo.hikes` removed — single `topo.trails` map
|
|
14
|
+
- `kind: 'hike'` removed — everything is `kind: 'trail'`
|
|
15
|
+
- `readOnly`/`destructive` booleans replaced by `intent: 'read' | 'write' | 'destroy'`
|
|
16
|
+
- `implementation` field renamed to `run`
|
|
17
|
+
- `markers` field renamed to `metadata`
|
|
18
|
+
- `testHike` renamed to `testFollows`, `HikeScenario` to `FollowScenario`
|
|
19
|
+
- `blaze()` now returns the surface handle (`Command` for CLI, `Server` for MCP)
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
- @ontrails/core@1.0.0-beta.4
|
|
25
|
+
|
|
26
|
+
## 1.0.0-beta.3
|
|
27
|
+
|
|
28
|
+
### Minor Changes
|
|
29
|
+
|
|
30
|
+
- Bug fixes across all surface packages found via parallel Codex review.
|
|
31
|
+
|
|
32
|
+
**core**: Fix Result.toJson false circular detection on DAGs, deserializeError subclass round-trip, topo cross-kind ID collisions, validateTopo multi-node cycle detection, error example input validation bypass, and deriveFields array type collapse.
|
|
33
|
+
|
|
34
|
+
**cli**: Switch blaze to parseAsync for proper async error handling, add boolean flag negation (--no-flag), and strict number parsing that rejects partial input.
|
|
35
|
+
|
|
36
|
+
**mcp**: Align BlobRef with core (including ReadableStream support) and detect tool-name collisions after normalization.
|
|
37
|
+
|
|
38
|
+
**testing**: Include hikes in testContracts validation, with follow-context awareness.
|
|
39
|
+
|
|
40
|
+
**warden**: Collect hike detour targets, validate detour refs in hike specs, and stop implementation-returns-result from walking into nested function bodies.
|
|
41
|
+
|
|
42
|
+
### Patch Changes
|
|
43
|
+
|
|
44
|
+
- Updated dependencies
|
|
45
|
+
- @ontrails/core@1.0.0-beta.3
|
|
46
|
+
|
|
3
47
|
## 1.0.0-beta.2
|
|
4
48
|
|
|
5
49
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ import { z } from 'zod';
|
|
|
11
11
|
|
|
12
12
|
const greet = trail('greet', {
|
|
13
13
|
input: z.object({ name: z.string().describe('Who to greet') }),
|
|
14
|
-
|
|
14
|
+
run: (input) => Result.ok(`Hello, ${input.name}!`),
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
const app = topo('myapp', { greet });
|
package/dist/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAS,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EACL,MAAM,EAKP,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED,oCAAoC;AACpC,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC;IACzE,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,GAAG,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC1C;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAS,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EACL,MAAM,EAKP,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,+CAA+C;AAC/C,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B;AAED,oCAAoC;AACpC,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC;IACzE,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IAC7B,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,GAAG,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;CAC1C;AAgND,eAAO,MAAM,gBAAgB,GAC3B,KAAK,IAAI,EACT,UAAU,uBAAuB,KAChC,UAAU,EAiBZ,CAAC"}
|
package/dist/build.js
CHANGED
|
@@ -90,7 +90,7 @@ const reportResult = async (options, ctx) => {
|
|
|
90
90
|
const executeTrail = async (t, validatedInput, ctxOverrides, options) => {
|
|
91
91
|
const ctx = await resolveContext(ctxOverrides, options);
|
|
92
92
|
const layers = options?.layers ?? [];
|
|
93
|
-
const impl = composeLayers(layers, t, t.
|
|
93
|
+
const impl = composeLayers(layers, t, t.run);
|
|
94
94
|
return impl(validatedInput, ctx);
|
|
95
95
|
};
|
|
96
96
|
/** Create the execute function for a CLI command. */
|
|
@@ -120,12 +120,12 @@ const createExecute = (t, fields, _flags, options) => async (parsedArgs, parsedF
|
|
|
120
120
|
return result;
|
|
121
121
|
};
|
|
122
122
|
/** Derive and merge flags for a trail. */
|
|
123
|
-
const buildFlags = (fields,
|
|
123
|
+
const buildFlags = (fields, intent, options) => {
|
|
124
124
|
let flags = toFlags(fields);
|
|
125
125
|
if (options?.presets) {
|
|
126
126
|
flags = mergeFlags(options.presets.flat(), flags);
|
|
127
127
|
}
|
|
128
|
-
if (
|
|
128
|
+
if (intent === 'destroy') {
|
|
129
129
|
flags = mergeFlags(dryRunPreset(), flags);
|
|
130
130
|
}
|
|
131
131
|
return flags;
|
|
@@ -134,30 +134,29 @@ const buildFlags = (fields, destructive, options) => {
|
|
|
134
134
|
const toCliCommand = (t, options) => {
|
|
135
135
|
const { group, name } = parseTrailId(t.id);
|
|
136
136
|
const fields = deriveFields(t.input, t.fields);
|
|
137
|
-
const flags = buildFlags(fields, t.
|
|
137
|
+
const flags = buildFlags(fields, t.intent, options);
|
|
138
138
|
return {
|
|
139
139
|
args: [],
|
|
140
140
|
description: t.description,
|
|
141
|
-
destructive: t.destructive,
|
|
142
141
|
execute: createExecute(t, fields, flags, options),
|
|
143
142
|
flags,
|
|
144
143
|
group,
|
|
145
144
|
idempotent: t.idempotent,
|
|
145
|
+
intent: t.intent,
|
|
146
146
|
layers: options?.layers,
|
|
147
147
|
name,
|
|
148
|
-
readOnly: t.readOnly,
|
|
149
148
|
trail: t,
|
|
150
149
|
};
|
|
151
150
|
};
|
|
152
151
|
export const buildCliCommands = (app, options) => {
|
|
153
152
|
const commands = [];
|
|
154
153
|
for (const item of app.list()) {
|
|
155
|
-
if (item.kind !== 'trail'
|
|
154
|
+
if (item.kind !== 'trail') {
|
|
156
155
|
continue;
|
|
157
156
|
}
|
|
158
157
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
159
158
|
const t = item;
|
|
160
|
-
if (t.
|
|
159
|
+
if (t.metadata?.['internal'] === true) {
|
|
161
160
|
continue;
|
|
162
161
|
}
|
|
163
162
|
commands.push(toCliCommand(t, options));
|
package/dist/build.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
package/dist/command.d.ts
CHANGED
|
@@ -39,8 +39,7 @@ export interface CliCommand {
|
|
|
39
39
|
readonly args: CliArg[];
|
|
40
40
|
readonly trail: AnyTrail;
|
|
41
41
|
readonly layers?: Layer[] | undefined;
|
|
42
|
-
readonly
|
|
43
|
-
readonly destructive?: boolean | undefined;
|
|
42
|
+
readonly intent: 'read' | 'write' | 'destroy';
|
|
44
43
|
readonly idempotent?: boolean | undefined;
|
|
45
44
|
execute(parsedArgs: Record<string, unknown>, parsedFlags: Record<string, unknown>, ctx?: Partial<TrailContext>): Promise<Result<unknown, Error>>;
|
|
46
45
|
}
|
package/dist/command.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAMzE;;;;GAIG;AAEH,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAMvC,mEAAmE;AACnE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IACzE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAMD,iCAAiC;AACjC,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAMD,4DAA4D;AAC5D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAMzE;;;;GAIG;AAEH,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAMvC,mEAAmE;AACnE,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IACzE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAMD,iCAAiC;AACjC,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAMD,4DAA4D;AAC5D,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE1C,OAAO,CACL,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAC1B,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;CACpC"}
|
|
@@ -27,5 +27,5 @@ export interface BlazeCliOptions {
|
|
|
27
27
|
* blaze(app);
|
|
28
28
|
* ```
|
|
29
29
|
*/
|
|
30
|
-
export declare const blaze: (app: Topo, options?: BlazeCliOptions) => void
|
|
30
|
+
export declare const blaze: (app: Topo, options?: BlazeCliOptions) => Promise<void>;
|
|
31
31
|
//# sourceMappingURL=blaze.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blaze.d.ts","sourceRoot":"","sources":["../../src/commander/blaze.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAQlD,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,EAAE,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC;IACzE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,GAAG,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAMD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK,
|
|
1
|
+
{"version":3,"file":"blaze.d.ts","sourceRoot":"","sources":["../../src/commander/blaze.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAQlD,MAAM,WAAW,eAAe;IAC9B,aAAa,CAAC,EAAE,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,GAAG,SAAS,CAAC;IACzE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IACrE,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,GAAG,SAAS,CAAC;IAClC,YAAY,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACzC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAMD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK,GAChB,KAAK,IAAI,EACT,UAAS,eAAoB,KAC5B,OAAO,CAAC,IAAI,CAqBd,CAAC"}
|
package/dist/commander/blaze.js
CHANGED
|
@@ -19,7 +19,7 @@ import { toCommander } from './to-commander.js';
|
|
|
19
19
|
* blaze(app);
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
|
-
export const blaze = (app, options = {}) => {
|
|
22
|
+
export const blaze = async (app, options = {}) => {
|
|
23
23
|
const commands = buildCliCommands(app, {
|
|
24
24
|
createContext: options.createContext,
|
|
25
25
|
layers: options.layers,
|
|
@@ -37,6 +37,6 @@ export const blaze = (app, options = {}) => {
|
|
|
37
37
|
commanderOpts.description = options.description;
|
|
38
38
|
}
|
|
39
39
|
const program = toCommander(commands, commanderOpts);
|
|
40
|
-
program.
|
|
40
|
+
await program.parseAsync();
|
|
41
41
|
};
|
|
42
42
|
//# sourceMappingURL=blaze.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blaze.js","sourceRoot":"","sources":["../../src/commander/blaze.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAiBhD,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"blaze.js","sourceRoot":"","sources":["../../src/commander/blaze.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAiBhD,8EAA8E;AAC9E,QAAQ;AACR,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EACxB,GAAS,EACT,UAA2B,EAAE,EACd,EAAE;IACjB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,EAAE;QACrC,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,eAAe;QAC7C,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAuB;QACxC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI;KAC/B,CAAC;IACF,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAClC,aAAa,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAC1C,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACtC,aAAa,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAClD,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACrD,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;AAC7B,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-commander.d.ts","sourceRoot":"","sources":["../../src/commander/to-commander.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"to-commander.d.ts","sourceRoot":"","sources":["../../src/commander/to-commander.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,OAAO,EAAgC,MAAM,WAAW,CAAC;AAElE,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,eAAe,CAAC;AAMzD,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAiLD,eAAO,MAAM,WAAW,GACtB,UAAU,UAAU,EAAE,EACtB,UAAU,kBAAkB,KAC3B,OAWF,CAAC"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Adapt framework-agnostic CliCommand[] to a Commander program.
|
|
3
3
|
*/
|
|
4
4
|
import { exitCodeMap, isTrailsError } from '@ontrails/core';
|
|
5
|
-
import { Command, Option } from 'commander';
|
|
5
|
+
import { Command, InvalidArgumentError, Option } from 'commander';
|
|
6
6
|
// ---------------------------------------------------------------------------
|
|
7
7
|
// Helpers
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
@@ -22,9 +22,16 @@ const buildFlagString = (flag) => {
|
|
|
22
22
|
const argPart = buildFlagArgument(flag);
|
|
23
23
|
return short ? `${short}, ${long} ${argPart}` : `${long} ${argPart}`;
|
|
24
24
|
};
|
|
25
|
-
/**
|
|
26
|
-
const
|
|
27
|
-
const
|
|
25
|
+
/** Strict number parser that rejects partial parses and non-finite values. */
|
|
26
|
+
const strictParseNumber = (value) => {
|
|
27
|
+
const n = Number(value);
|
|
28
|
+
if (Number.isNaN(n) || !Number.isFinite(n)) {
|
|
29
|
+
throw new InvalidArgumentError(`"${value}" is not a valid number`);
|
|
30
|
+
}
|
|
31
|
+
return n;
|
|
32
|
+
};
|
|
33
|
+
/** Apply common modifiers (choices, default, arg parser) to a Commander Option. */
|
|
34
|
+
const applyOptionModifiers = (opt, flag) => {
|
|
28
35
|
if (flag.choices) {
|
|
29
36
|
opt.choices(flag.choices);
|
|
30
37
|
}
|
|
@@ -32,9 +39,18 @@ const buildOption = (flag) => {
|
|
|
32
39
|
opt.default(flag.default);
|
|
33
40
|
}
|
|
34
41
|
if (flag.type === 'number' || flag.type === 'number[]') {
|
|
35
|
-
opt.argParser(
|
|
42
|
+
opt.argParser(strictParseNumber);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/** Build Commander Option(s) from a CliFlag. Returns one or two options. */
|
|
46
|
+
const buildOptions = (flag) => {
|
|
47
|
+
const opt = new Option(buildFlagString(flag), flag.description);
|
|
48
|
+
applyOptionModifiers(opt, flag);
|
|
49
|
+
if (flag.type === 'boolean') {
|
|
50
|
+
const negation = new Option(`--no-${flag.name}`, flag.description ? `Negate ${flag.description}` : undefined);
|
|
51
|
+
return [opt, negation];
|
|
36
52
|
}
|
|
37
|
-
return opt;
|
|
53
|
+
return [opt];
|
|
38
54
|
};
|
|
39
55
|
/** Add positional args to a Commander subcommand. */
|
|
40
56
|
const buildArgTemplate = (arg) => {
|
|
@@ -129,7 +145,9 @@ const buildSubcommand = (cmd) => {
|
|
|
129
145
|
sub.description(cmd.description);
|
|
130
146
|
}
|
|
131
147
|
for (const flag of cmd.flags) {
|
|
132
|
-
|
|
148
|
+
for (const opt of buildOptions(flag)) {
|
|
149
|
+
sub.addOption(opt);
|
|
150
|
+
}
|
|
133
151
|
}
|
|
134
152
|
addArgs(sub, cmd);
|
|
135
153
|
wireAction(sub, cmd);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"to-commander.js","sourceRoot":"","sources":["../../src/commander/to-commander.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"to-commander.js","sourceRoot":"","sources":["../../src/commander/to-commander.ts"],"names":[],"mappings":"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"}
|
package/dist/flags.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAmD5C,2CAA2C;AAC3C,eAAO,MAAM,OAAO,GAAI,QAAQ,SAAS,KAAK,EAAE,KAAG,OAAO,EACnC,CAAC;AA2HxB,gDAAgD;AAChD,eAAO,MAAM,WAAW,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAAO,EAYtD,CAAC;AAMF,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,QAAO,OAAO,EAyB1C,CAAC;AAEF,iDAAiD;AACjD,eAAO,MAAM,SAAS,QAAO,OAAO,EAQnC,CAAC;AAEF,uCAAuC;AACvC,eAAO,MAAM,YAAY,QAAO,OAAO,EAStC,CAAC"}
|
package/dist/flags.js
CHANGED
|
@@ -11,7 +11,9 @@ const fieldTypeToCliFlag = {
|
|
|
11
11
|
enum: { type: 'string', variadic: false },
|
|
12
12
|
multiselect: { type: 'string[]', variadic: true },
|
|
13
13
|
number: { type: 'number', variadic: false },
|
|
14
|
+
'number[]': { type: 'number[]', variadic: true },
|
|
14
15
|
string: { type: 'string', variadic: false },
|
|
16
|
+
'string[]': { type: 'string[]', variadic: true },
|
|
15
17
|
};
|
|
16
18
|
/** Convert a derived field into a CLI flag descriptor. */
|
|
17
19
|
const toCliFlag = (field) => {
|
package/dist/flags.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,uCAAuC;AACvC,MAAM,OAAO,GAAG,CAAC,GAAW,EAAU,EAAE,CACtC,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;AAe3D,MAAM,kBAAkB,GAAwC;IAC9D,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE;IAC7C,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE;IACzC,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE;IACjD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE;IAC3C,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE;
|
|
1
|
+
{"version":3,"file":"flags.js","sourceRoot":"","sources":["../src/flags.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import { Result, trail, topo } from '@ontrails/core';
|
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
|
|
6
6
|
import { buildCliCommands } from '../build.js';
|
|
7
|
+
import { blaze } from '../commander/blaze.js';
|
|
7
8
|
import { toCommander } from '../commander/to-commander.js';
|
|
8
9
|
import { defaultOnResult } from '../on-result.js';
|
|
9
10
|
|
|
@@ -14,8 +15,8 @@ import { defaultOnResult } from '../on-result.js';
|
|
|
14
15
|
describe('blaze', () => {
|
|
15
16
|
test('smoke test: buildCliCommands + toCommander wiring does not throw', () => {
|
|
16
17
|
const t = trail('ping', {
|
|
17
|
-
implementation: () => Result.ok('pong'),
|
|
18
18
|
input: z.object({}),
|
|
19
|
+
run: () => Result.ok('pong'),
|
|
19
20
|
});
|
|
20
21
|
const app = topo('smoke-test', { ping: t });
|
|
21
22
|
|
|
@@ -32,8 +33,8 @@ describe('blaze', () => {
|
|
|
32
33
|
|
|
33
34
|
test('uses defaultOnResult when none provided', () => {
|
|
34
35
|
const t = trail('echo', {
|
|
35
|
-
implementation: (input: { msg: string }) => Result.ok(input.msg),
|
|
36
36
|
input: z.object({ msg: z.string() }),
|
|
37
|
+
run: (input: { msg: string }) => Result.ok(input.msg),
|
|
37
38
|
});
|
|
38
39
|
const app = topo('default-on-result', { echo: t });
|
|
39
40
|
|
|
@@ -47,6 +48,15 @@ describe('blaze', () => {
|
|
|
47
48
|
expect(program.commands[0]?.name()).toBe('echo');
|
|
48
49
|
});
|
|
49
50
|
|
|
51
|
+
test('blaze returns a Promise (async signature)', () => {
|
|
52
|
+
// Verify blaze's return type is a Promise by checking its constructor name.
|
|
53
|
+
// We don't call blaze() here because it invokes parseAsync on real argv.
|
|
54
|
+
expect(blaze).toBeDefined();
|
|
55
|
+
// The function is async, so calling it returns a Promise.
|
|
56
|
+
// We verify the type signature indirectly: async functions have AsyncFunction constructor.
|
|
57
|
+
expect(blaze.constructor.name).toBe('AsyncFunction');
|
|
58
|
+
});
|
|
59
|
+
|
|
50
60
|
test('end-to-end: define trail, build commands, execute, verify output', async () => {
|
|
51
61
|
const written: string[] = [];
|
|
52
62
|
const originalWrite = process.stdout.write;
|
|
@@ -57,9 +67,8 @@ describe('blaze', () => {
|
|
|
57
67
|
|
|
58
68
|
try {
|
|
59
69
|
const t = trail('greet', {
|
|
60
|
-
implementation: (input: { name: string }) =>
|
|
61
|
-
Result.ok(`Hello, ${input.name}!`),
|
|
62
70
|
input: z.object({ name: z.string() }),
|
|
71
|
+
run: (input: { name: string }) => Result.ok(`Hello, ${input.name}!`),
|
|
63
72
|
});
|
|
64
73
|
const app = topo('e2e-test', { greet: t });
|
|
65
74
|
|
|
@@ -36,9 +36,8 @@ const requireCommand = (commands: ReturnType<typeof buildCliCommands>) => {
|
|
|
36
36
|
describe('buildCliCommands', () => {
|
|
37
37
|
test('builds commands from a simple app with one trail', () => {
|
|
38
38
|
const t = trail('greet', {
|
|
39
|
-
implementation: (input: { name: string }) =>
|
|
40
|
-
Result.ok(`Hello, ${input.name}`),
|
|
41
39
|
input: z.object({ name: z.string() }),
|
|
40
|
+
run: (input: { name: string }) => Result.ok(`Hello, ${input.name}`),
|
|
42
41
|
});
|
|
43
42
|
const app = makeApp(t);
|
|
44
43
|
const commands = buildCliCommands(app);
|
|
@@ -49,13 +48,12 @@ describe('buildCliCommands', () => {
|
|
|
49
48
|
|
|
50
49
|
test('builds grouped subcommands from dotted trail IDs', () => {
|
|
51
50
|
const show = trail('entity.show', {
|
|
52
|
-
implementation: (input: { id: string }) => Result.ok({ id: input.id }),
|
|
53
51
|
input: z.object({ id: z.string() }),
|
|
52
|
+
run: (input: { id: string }) => Result.ok({ id: input.id }),
|
|
54
53
|
});
|
|
55
54
|
const add = trail('entity.add', {
|
|
56
|
-
implementation: (input: { name: string }) =>
|
|
57
|
-
Result.ok({ name: input.name }),
|
|
58
55
|
input: z.object({ name: z.string() }),
|
|
56
|
+
run: (input: { name: string }) => Result.ok({ name: input.name }),
|
|
59
57
|
});
|
|
60
58
|
const app = makeApp(show, add);
|
|
61
59
|
const commands = buildCliCommands(app);
|
|
@@ -68,11 +66,11 @@ describe('buildCliCommands', () => {
|
|
|
68
66
|
|
|
69
67
|
test('derives flags from input schema', () => {
|
|
70
68
|
const t = trail('search', {
|
|
71
|
-
implementation: () => Result.ok([]),
|
|
72
69
|
input: z.object({
|
|
73
70
|
limit: z.number().optional(),
|
|
74
71
|
query: z.string(),
|
|
75
72
|
}),
|
|
73
|
+
run: () => Result.ok([]),
|
|
76
74
|
});
|
|
77
75
|
const app = makeApp(t);
|
|
78
76
|
const { flags } = requireCommand(buildCliCommands(app));
|
|
@@ -84,11 +82,11 @@ describe('buildCliCommands', () => {
|
|
|
84
82
|
expect(limitFlag?.required).toBe(false);
|
|
85
83
|
});
|
|
86
84
|
|
|
87
|
-
test('adds --dry-run for
|
|
85
|
+
test('adds --dry-run for destroy intent trails', () => {
|
|
88
86
|
const t = trail('entity.delete', {
|
|
89
|
-
destructive: true,
|
|
90
|
-
implementation: () => Result.ok(),
|
|
91
87
|
input: z.object({ id: z.string() }),
|
|
88
|
+
intent: 'destroy',
|
|
89
|
+
run: () => Result.ok(),
|
|
92
90
|
});
|
|
93
91
|
const app = makeApp(t);
|
|
94
92
|
const commands = buildCliCommands(app);
|
|
@@ -100,8 +98,8 @@ describe('buildCliCommands', () => {
|
|
|
100
98
|
test('calls onResult with correct context', async () => {
|
|
101
99
|
let captured: ActionResultContext | undefined;
|
|
102
100
|
const t = trail('ping', {
|
|
103
|
-
implementation: (input: { msg: string }) => Result.ok(input.msg),
|
|
104
101
|
input: z.object({ msg: z.string() }),
|
|
102
|
+
run: (input: { msg: string }) => Result.ok(input.msg),
|
|
105
103
|
});
|
|
106
104
|
const app = makeApp(t);
|
|
107
105
|
const commands = buildCliCommands(app, {
|
|
@@ -122,11 +120,11 @@ describe('buildCliCommands', () => {
|
|
|
122
120
|
test('validates input before calling implementation', async () => {
|
|
123
121
|
let implCalled = false;
|
|
124
122
|
const t = trail('strict', {
|
|
125
|
-
|
|
123
|
+
input: z.object({ name: z.string() }),
|
|
124
|
+
run: () => {
|
|
126
125
|
implCalled = true;
|
|
127
126
|
return Result.ok('done');
|
|
128
127
|
},
|
|
129
|
-
input: z.object({ name: z.string() }),
|
|
130
128
|
});
|
|
131
129
|
const app = makeApp(t);
|
|
132
130
|
const commands = buildCliCommands(app);
|
|
@@ -143,11 +141,11 @@ describe('buildCliCommands', () => {
|
|
|
143
141
|
test('applies layers in order', async () => {
|
|
144
142
|
const order: string[] = [];
|
|
145
143
|
const t = trail('layered', {
|
|
146
|
-
|
|
144
|
+
input: z.object({ x: z.string() }),
|
|
145
|
+
run: (input: { x: string }) => {
|
|
147
146
|
order.push('impl');
|
|
148
147
|
return Result.ok(input.x);
|
|
149
148
|
},
|
|
150
|
-
input: z.object({ x: z.string() }),
|
|
151
149
|
});
|
|
152
150
|
const app = makeApp(t);
|
|
153
151
|
const commands = buildCliCommands(app, {
|
|
@@ -186,11 +184,11 @@ describe('buildCliCommands', () => {
|
|
|
186
184
|
test('uses provided createContext factory', async () => {
|
|
187
185
|
let usedRequestId: string | undefined;
|
|
188
186
|
const t = trail('ctx-test', {
|
|
189
|
-
|
|
187
|
+
input: z.object({}),
|
|
188
|
+
run: (_input: Record<string, never>, ctx: TrailContext) => {
|
|
190
189
|
usedRequestId = ctx.requestId;
|
|
191
190
|
return Result.ok('ok');
|
|
192
191
|
},
|
|
193
|
-
input: z.object({}),
|
|
194
192
|
});
|
|
195
193
|
const app = makeApp(t);
|
|
196
194
|
const commands = buildCliCommands(app, {
|
|
@@ -204,11 +202,11 @@ describe('buildCliCommands', () => {
|
|
|
204
202
|
test('converts kebab-case flags back to camelCase for input', async () => {
|
|
205
203
|
let receivedInput: unknown;
|
|
206
204
|
const t = trail('camel', {
|
|
207
|
-
|
|
205
|
+
input: z.object({ sortOrder: z.string() }),
|
|
206
|
+
run: (input) => {
|
|
208
207
|
receivedInput = input;
|
|
209
208
|
return Result.ok('ok');
|
|
210
209
|
},
|
|
211
|
-
input: z.object({ sortOrder: z.string() }),
|
|
212
210
|
});
|
|
213
211
|
const app = makeApp(t);
|
|
214
212
|
const commands = buildCliCommands(app);
|
|
@@ -48,7 +48,6 @@ const expectSameDate = (value: string | undefined, expected: Date) => {
|
|
|
48
48
|
|
|
49
49
|
describe('autoIterateLayer', () => {
|
|
50
50
|
const paginatedTrail = trail('list-items', {
|
|
51
|
-
implementation: () => Result.ok({ hasMore: false, items: [] }),
|
|
52
51
|
input: z.object({
|
|
53
52
|
all: z.boolean().optional(),
|
|
54
53
|
cursor: z.string().optional(),
|
|
@@ -58,6 +57,7 @@ describe('autoIterateLayer', () => {
|
|
|
58
57
|
items: z.array(z.string()),
|
|
59
58
|
nextCursor: z.string().optional(),
|
|
60
59
|
}),
|
|
60
|
+
run: () => Result.ok({ hasMore: false, items: [] }),
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
test('collects paginated results with --all flag', async () => {
|
|
@@ -112,8 +112,8 @@ describe('autoIterateLayer', () => {
|
|
|
112
112
|
|
|
113
113
|
test('ignores non-paginated trails', () => {
|
|
114
114
|
const simpleTrail = trail('simple', {
|
|
115
|
-
implementation: (input: { name: string }) => Result.ok(input.name),
|
|
116
115
|
input: z.object({ name: z.string() }),
|
|
116
|
+
run: (input: { name: string }) => Result.ok(input.name),
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
const impl: Implementation<{ name: string }, string> = async (input) =>
|
|
@@ -132,14 +132,12 @@ describe('autoIterateLayer', () => {
|
|
|
132
132
|
|
|
133
133
|
describe('dateShortcutsLayer', () => {
|
|
134
134
|
const dateTrail = trail('events', {
|
|
135
|
-
implementation: (input: {
|
|
136
|
-
since?: string | undefined;
|
|
137
|
-
until?: string | undefined;
|
|
138
|
-
}) => Result.ok(input),
|
|
139
135
|
input: z.object({
|
|
140
136
|
since: z.string().optional(),
|
|
141
137
|
until: z.string().optional(),
|
|
142
138
|
}),
|
|
139
|
+
run: (input: { since?: string | undefined; until?: string | undefined }) =>
|
|
140
|
+
Result.ok(input),
|
|
143
141
|
});
|
|
144
142
|
|
|
145
143
|
test("expands 'today' to correct date", async () => {
|
|
@@ -180,8 +178,8 @@ describe('dateShortcutsLayer', () => {
|
|
|
180
178
|
|
|
181
179
|
test('ignores trails without date range fields', () => {
|
|
182
180
|
const noDateTrail = trail('no-dates', {
|
|
183
|
-
implementation: (input: { name: string }) => Result.ok(input.name),
|
|
184
181
|
input: z.object({ name: z.string() }),
|
|
182
|
+
run: (input: { name: string }) => Result.ok(input.name),
|
|
185
183
|
});
|
|
186
184
|
|
|
187
185
|
const impl: Implementation<{ name: string }, string> = async (input) =>
|
|
@@ -11,6 +11,11 @@ import { toCommander } from '../commander/to-commander.js';
|
|
|
11
11
|
// Helpers
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
13
|
|
|
14
|
+
// oxlint-disable-next-line no-empty-function, require-await -- intentional noop for callback type
|
|
15
|
+
const noopResult = async () => {};
|
|
16
|
+
// oxlint-disable-next-line no-empty-function -- intentional noop for callback type
|
|
17
|
+
const noopWrite = () => {};
|
|
18
|
+
|
|
14
19
|
const makeApp = (...trails: AnyTrail[]) => {
|
|
15
20
|
const mod: Record<string, unknown> = {};
|
|
16
21
|
for (const t of trails) {
|
|
@@ -19,6 +24,25 @@ const makeApp = (...trails: AnyTrail[]) => {
|
|
|
19
24
|
return topo('test-app', mod);
|
|
20
25
|
};
|
|
21
26
|
|
|
27
|
+
/** Intercept a command's execute to capture parsed opts. */
|
|
28
|
+
const interceptOpts = (commands: ReturnType<typeof buildCliCommands>) => {
|
|
29
|
+
let received: Record<string, unknown> = {};
|
|
30
|
+
const [cmd] = commands;
|
|
31
|
+
if (!cmd) {
|
|
32
|
+
throw new Error('No commands built');
|
|
33
|
+
}
|
|
34
|
+
const original = cmd.execute;
|
|
35
|
+
cmd.execute = (args, opts) => {
|
|
36
|
+
received = opts;
|
|
37
|
+
return original(args, opts);
|
|
38
|
+
};
|
|
39
|
+
return {
|
|
40
|
+
get received() {
|
|
41
|
+
return received;
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
22
46
|
const requireCommand = (
|
|
23
47
|
program: ReturnType<typeof toCommander>,
|
|
24
48
|
name: string
|
|
@@ -38,9 +62,8 @@ const requireCommand = (
|
|
|
38
62
|
describe('toCommander', () => {
|
|
39
63
|
test('creates a Commander program with correct commands', () => {
|
|
40
64
|
const t = trail('greet', {
|
|
41
|
-
implementation: (input: { name: string }) =>
|
|
42
|
-
Result.ok(`Hello, ${input.name}`),
|
|
43
65
|
input: z.object({ name: z.string() }),
|
|
66
|
+
run: (input: { name: string }) => Result.ok(`Hello, ${input.name}`),
|
|
44
67
|
});
|
|
45
68
|
const app = makeApp(t);
|
|
46
69
|
const commands = buildCliCommands(app);
|
|
@@ -54,12 +77,12 @@ describe('toCommander', () => {
|
|
|
54
77
|
|
|
55
78
|
test('grouped commands create parent/subcommand structure', () => {
|
|
56
79
|
const show = trail('entity.show', {
|
|
57
|
-
implementation: () => Result.ok({}),
|
|
58
80
|
input: z.object({ id: z.string() }),
|
|
81
|
+
run: () => Result.ok({}),
|
|
59
82
|
});
|
|
60
83
|
const add = trail('entity.add', {
|
|
61
|
-
implementation: () => Result.ok({}),
|
|
62
84
|
input: z.object({ name: z.string() }),
|
|
85
|
+
run: () => Result.ok({}),
|
|
63
86
|
});
|
|
64
87
|
const app = makeApp(show, add);
|
|
65
88
|
const commands = buildCliCommands(app);
|
|
@@ -76,7 +99,6 @@ describe('toCommander', () => {
|
|
|
76
99
|
|
|
77
100
|
test('flag types map correctly to Commander options', () => {
|
|
78
101
|
const t = trail('search', {
|
|
79
|
-
implementation: () => Result.ok([]),
|
|
80
102
|
input: z.object({
|
|
81
103
|
format: z.enum(['json', 'text']).optional(),
|
|
82
104
|
limit: z.number().optional(),
|
|
@@ -84,12 +106,14 @@ describe('toCommander', () => {
|
|
|
84
106
|
tags: z.array(z.string()).optional(),
|
|
85
107
|
verbose: z.boolean().optional(),
|
|
86
108
|
}),
|
|
109
|
+
run: () => Result.ok([]),
|
|
87
110
|
});
|
|
88
111
|
const app = makeApp(t);
|
|
89
112
|
const commands = buildCliCommands(app);
|
|
90
113
|
const program = toCommander(commands);
|
|
91
114
|
|
|
92
115
|
const opts = requireCommand(program, 'search').options;
|
|
116
|
+
// 5 flags + negation options for boolean flags
|
|
93
117
|
expect(opts.length).toBeGreaterThanOrEqual(5);
|
|
94
118
|
|
|
95
119
|
const formatOpt = opts.find((entry) => entry.long === '--format');
|
|
@@ -97,10 +121,149 @@ describe('toCommander', () => {
|
|
|
97
121
|
expect(formatOpt?.argChoices).toEqual(['json', 'text']);
|
|
98
122
|
});
|
|
99
123
|
|
|
124
|
+
describe('boolean flag negation', () => {
|
|
125
|
+
test('boolean flags get --no-<name> negation options', () => {
|
|
126
|
+
const t = trail('check', {
|
|
127
|
+
input: z.object({ strict: z.boolean() }),
|
|
128
|
+
run: () => Result.ok('ok'),
|
|
129
|
+
});
|
|
130
|
+
const app = makeApp(t);
|
|
131
|
+
const commands = buildCliCommands(app);
|
|
132
|
+
const program = toCommander(commands);
|
|
133
|
+
|
|
134
|
+
const cmd = requireCommand(program, 'check');
|
|
135
|
+
const strictOpt = cmd.options.find((o) => o.long === '--strict');
|
|
136
|
+
const noStrictOpt = cmd.options.find((o) => o.long === '--no-strict');
|
|
137
|
+
|
|
138
|
+
expect(strictOpt).toBeDefined();
|
|
139
|
+
expect(noStrictOpt).toBeDefined();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('--no-<flag> sets value to false via parseAsync', async () => {
|
|
143
|
+
const t = trail('check', {
|
|
144
|
+
input: z.object({ strict: z.boolean().default(true) }),
|
|
145
|
+
run: () => Result.ok('ok'),
|
|
146
|
+
});
|
|
147
|
+
const app = makeApp(t);
|
|
148
|
+
const commands = buildCliCommands(app, { onResult: noopResult });
|
|
149
|
+
const spy = interceptOpts(commands);
|
|
150
|
+
const program = toCommander(commands, { name: 'test' });
|
|
151
|
+
program.exitOverride();
|
|
152
|
+
|
|
153
|
+
await program.parseAsync(['node', 'test', 'check', '--no-strict']);
|
|
154
|
+
expect(spy.received['strict']).toBe(false);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test('--flag sets boolean value to true via parseAsync', async () => {
|
|
158
|
+
const t = trail('check', {
|
|
159
|
+
input: z.object({ strict: z.boolean().default(false) }),
|
|
160
|
+
run: () => Result.ok('ok'),
|
|
161
|
+
});
|
|
162
|
+
const app = makeApp(t);
|
|
163
|
+
const commands = buildCliCommands(app, { onResult: noopResult });
|
|
164
|
+
const spy = interceptOpts(commands);
|
|
165
|
+
const program = toCommander(commands, { name: 'test' });
|
|
166
|
+
program.exitOverride();
|
|
167
|
+
|
|
168
|
+
await program.parseAsync(['node', 'test', 'check', '--strict']);
|
|
169
|
+
expect(spy.received['strict']).toBe(true);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('strict number parsing', () => {
|
|
174
|
+
const buildNumberProgram = () => {
|
|
175
|
+
const t = trail('count', {
|
|
176
|
+
input: z.object({ limit: z.number() }),
|
|
177
|
+
run: () => Result.ok('ok'),
|
|
178
|
+
});
|
|
179
|
+
const app = makeApp(t);
|
|
180
|
+
const commands = buildCliCommands(app);
|
|
181
|
+
const program = toCommander(commands, { name: 'test' });
|
|
182
|
+
program.exitOverride();
|
|
183
|
+
program.configureOutput({
|
|
184
|
+
writeErr: noopWrite,
|
|
185
|
+
writeOut: noopWrite,
|
|
186
|
+
});
|
|
187
|
+
// Also configure on the subcommand directly
|
|
188
|
+
for (const sub of program.commands) {
|
|
189
|
+
sub.exitOverride();
|
|
190
|
+
sub.configureOutput({
|
|
191
|
+
writeErr: noopWrite,
|
|
192
|
+
writeOut: noopWrite,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
return program;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
test('rejects partial number like "123abc"', async () => {
|
|
199
|
+
const program = buildNumberProgram();
|
|
200
|
+
let threw = false;
|
|
201
|
+
try {
|
|
202
|
+
await program.parseAsync([
|
|
203
|
+
'node',
|
|
204
|
+
'test',
|
|
205
|
+
'count',
|
|
206
|
+
'--limit',
|
|
207
|
+
'123abc',
|
|
208
|
+
]);
|
|
209
|
+
} catch {
|
|
210
|
+
threw = true;
|
|
211
|
+
}
|
|
212
|
+
expect(threw).toBe(true);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
test('rejects Infinity', async () => {
|
|
216
|
+
const program = buildNumberProgram();
|
|
217
|
+
let threw = false;
|
|
218
|
+
try {
|
|
219
|
+
await program.parseAsync([
|
|
220
|
+
'node',
|
|
221
|
+
'test',
|
|
222
|
+
'count',
|
|
223
|
+
'--limit',
|
|
224
|
+
'Infinity',
|
|
225
|
+
]);
|
|
226
|
+
} catch {
|
|
227
|
+
threw = true;
|
|
228
|
+
}
|
|
229
|
+
expect(threw).toBe(true);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test('rejects NaN', async () => {
|
|
233
|
+
const program = buildNumberProgram();
|
|
234
|
+
let threw = false;
|
|
235
|
+
try {
|
|
236
|
+
await program.parseAsync(['node', 'test', 'count', '--limit', 'abc']);
|
|
237
|
+
} catch {
|
|
238
|
+
threw = true;
|
|
239
|
+
}
|
|
240
|
+
expect(threw).toBe(true);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test.each([
|
|
244
|
+
{ expected: 42, input: '42' },
|
|
245
|
+
{ expected: 3.14, input: '3.14' },
|
|
246
|
+
{ expected: -5, input: '-5' },
|
|
247
|
+
])('accepts valid number "$input"', async ({ expected, input }) => {
|
|
248
|
+
const t = trail('count', {
|
|
249
|
+
input: z.object({ limit: z.number() }),
|
|
250
|
+
run: () => Result.ok('ok'),
|
|
251
|
+
});
|
|
252
|
+
const app = makeApp(t);
|
|
253
|
+
const commands = buildCliCommands(app, { onResult: noopResult });
|
|
254
|
+
const spy = interceptOpts(commands);
|
|
255
|
+
const program = toCommander(commands, { name: 'test' });
|
|
256
|
+
program.exitOverride();
|
|
257
|
+
|
|
258
|
+
await program.parseAsync(['node', 'test', 'count', '--limit', input]);
|
|
259
|
+
expect(spy.received['limit']).toBe(expected);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
100
263
|
test('sets version when provided', () => {
|
|
101
264
|
const t = trail('ping', {
|
|
102
|
-
implementation: () => Result.ok('pong'),
|
|
103
265
|
input: z.object({}),
|
|
266
|
+
run: () => Result.ok('pong'),
|
|
104
267
|
});
|
|
105
268
|
const app = makeApp(t);
|
|
106
269
|
const commands = buildCliCommands(app);
|
|
@@ -119,8 +282,8 @@ describe('toCommander', () => {
|
|
|
119
282
|
// This test verifies the error handling structure exists.
|
|
120
283
|
// Full integration would need process.exit mocking.
|
|
121
284
|
const t = trail('fail', {
|
|
122
|
-
implementation: () => Result.ok('ok'),
|
|
123
285
|
input: z.object({}),
|
|
286
|
+
run: () => Result.ok('ok'),
|
|
124
287
|
});
|
|
125
288
|
const app = makeApp(t);
|
|
126
289
|
const commands = buildCliCommands(app);
|
package/src/build.ts
CHANGED
|
@@ -155,7 +155,7 @@ const executeTrail = async (
|
|
|
155
155
|
): Promise<Result<unknown, Error>> => {
|
|
156
156
|
const ctx = await resolveContext(ctxOverrides, options);
|
|
157
157
|
const layers = options?.layers ?? [];
|
|
158
|
-
const impl = composeLayers(layers, t, t.
|
|
158
|
+
const impl = composeLayers(layers, t, t.run);
|
|
159
159
|
return impl(validatedInput, ctx);
|
|
160
160
|
};
|
|
161
161
|
|
|
@@ -207,14 +207,14 @@ const createExecute =
|
|
|
207
207
|
/** Derive and merge flags for a trail. */
|
|
208
208
|
const buildFlags = (
|
|
209
209
|
fields: readonly Field[],
|
|
210
|
-
|
|
210
|
+
intent: 'read' | 'write' | 'destroy',
|
|
211
211
|
options?: BuildCliCommandsOptions
|
|
212
212
|
): CliFlag[] => {
|
|
213
213
|
let flags = toFlags(fields);
|
|
214
214
|
if (options?.presets) {
|
|
215
215
|
flags = mergeFlags(options.presets.flat(), flags);
|
|
216
216
|
}
|
|
217
|
-
if (
|
|
217
|
+
if (intent === 'destroy') {
|
|
218
218
|
flags = mergeFlags(dryRunPreset(), flags);
|
|
219
219
|
}
|
|
220
220
|
return flags;
|
|
@@ -227,19 +227,18 @@ const toCliCommand = (
|
|
|
227
227
|
): CliCommand => {
|
|
228
228
|
const { group, name } = parseTrailId(t.id);
|
|
229
229
|
const fields = deriveFields(t.input, t.fields);
|
|
230
|
-
const flags = buildFlags(fields, t.
|
|
230
|
+
const flags = buildFlags(fields, t.intent, options);
|
|
231
231
|
|
|
232
232
|
return {
|
|
233
233
|
args: [],
|
|
234
234
|
description: t.description,
|
|
235
|
-
destructive: t.destructive,
|
|
236
235
|
execute: createExecute(t, fields, flags, options),
|
|
237
236
|
flags,
|
|
238
237
|
group,
|
|
239
238
|
idempotent: t.idempotent,
|
|
239
|
+
intent: t.intent,
|
|
240
240
|
layers: options?.layers,
|
|
241
241
|
name,
|
|
242
|
-
readOnly: t.readOnly,
|
|
243
242
|
trail: t,
|
|
244
243
|
};
|
|
245
244
|
};
|
|
@@ -251,13 +250,13 @@ export const buildCliCommands = (
|
|
|
251
250
|
const commands: CliCommand[] = [];
|
|
252
251
|
|
|
253
252
|
for (const item of app.list()) {
|
|
254
|
-
if (item.kind !== 'trail'
|
|
253
|
+
if (item.kind !== 'trail') {
|
|
255
254
|
continue;
|
|
256
255
|
}
|
|
257
256
|
|
|
258
257
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
259
258
|
const t = item as AnyTrail;
|
|
260
|
-
if (t.
|
|
259
|
+
if (t.metadata?.['internal'] === true) {
|
|
261
260
|
continue;
|
|
262
261
|
}
|
|
263
262
|
commands.push(toCliCommand(t, options));
|
package/src/command.ts
CHANGED
|
@@ -61,8 +61,7 @@ export interface CliCommand {
|
|
|
61
61
|
readonly args: CliArg[];
|
|
62
62
|
readonly trail: AnyTrail;
|
|
63
63
|
readonly layers?: Layer[] | undefined;
|
|
64
|
-
readonly
|
|
65
|
-
readonly destructive?: boolean | undefined;
|
|
64
|
+
readonly intent: 'read' | 'write' | 'destroy';
|
|
66
65
|
readonly idempotent?: boolean | undefined;
|
|
67
66
|
|
|
68
67
|
execute(
|
package/src/commander/blaze.ts
CHANGED
|
@@ -43,7 +43,10 @@ export interface BlazeCliOptions {
|
|
|
43
43
|
* blaze(app);
|
|
44
44
|
* ```
|
|
45
45
|
*/
|
|
46
|
-
export const blaze = (
|
|
46
|
+
export const blaze = async (
|
|
47
|
+
app: Topo,
|
|
48
|
+
options: BlazeCliOptions = {}
|
|
49
|
+
): Promise<void> => {
|
|
47
50
|
const commands = buildCliCommands(app, {
|
|
48
51
|
createContext: options.createContext,
|
|
49
52
|
layers: options.layers,
|
|
@@ -63,5 +66,5 @@ export const blaze = (app: Topo, options: BlazeCliOptions = {}): void => {
|
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
const program = toCommander(commands, commanderOpts);
|
|
66
|
-
program.
|
|
69
|
+
await program.parseAsync();
|
|
67
70
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { exitCodeMap, isTrailsError } from '@ontrails/core';
|
|
6
|
-
import { Command, Option } from 'commander';
|
|
6
|
+
import { Command, InvalidArgumentError, Option } from 'commander';
|
|
7
7
|
|
|
8
8
|
import type { CliCommand, CliFlag } from '../command.js';
|
|
9
9
|
|
|
@@ -41,9 +41,17 @@ const buildFlagString = (flag: CliFlag): string => {
|
|
|
41
41
|
return short ? `${short}, ${long} ${argPart}` : `${long} ${argPart}`;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
/**
|
|
45
|
-
const
|
|
46
|
-
const
|
|
44
|
+
/** Strict number parser that rejects partial parses and non-finite values. */
|
|
45
|
+
const strictParseNumber = (value: string): number => {
|
|
46
|
+
const n = Number(value);
|
|
47
|
+
if (Number.isNaN(n) || !Number.isFinite(n)) {
|
|
48
|
+
throw new InvalidArgumentError(`"${value}" is not a valid number`);
|
|
49
|
+
}
|
|
50
|
+
return n;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** Apply common modifiers (choices, default, arg parser) to a Commander Option. */
|
|
54
|
+
const applyOptionModifiers = (opt: Option, flag: CliFlag): void => {
|
|
47
55
|
if (flag.choices) {
|
|
48
56
|
opt.choices(flag.choices);
|
|
49
57
|
}
|
|
@@ -51,9 +59,22 @@ const buildOption = (flag: CliFlag): Option => {
|
|
|
51
59
|
opt.default(flag.default);
|
|
52
60
|
}
|
|
53
61
|
if (flag.type === 'number' || flag.type === 'number[]') {
|
|
54
|
-
opt.argParser(
|
|
62
|
+
opt.argParser(strictParseNumber);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** Build Commander Option(s) from a CliFlag. Returns one or two options. */
|
|
67
|
+
const buildOptions = (flag: CliFlag): Option[] => {
|
|
68
|
+
const opt = new Option(buildFlagString(flag), flag.description);
|
|
69
|
+
applyOptionModifiers(opt, flag);
|
|
70
|
+
if (flag.type === 'boolean') {
|
|
71
|
+
const negation = new Option(
|
|
72
|
+
`--no-${flag.name}`,
|
|
73
|
+
flag.description ? `Negate ${flag.description}` : undefined
|
|
74
|
+
);
|
|
75
|
+
return [opt, negation];
|
|
55
76
|
}
|
|
56
|
-
return opt;
|
|
77
|
+
return [opt];
|
|
57
78
|
};
|
|
58
79
|
|
|
59
80
|
/** Add positional args to a Commander subcommand. */
|
|
@@ -162,7 +183,9 @@ const buildSubcommand = (cmd: CliCommand): Command => {
|
|
|
162
183
|
sub.description(cmd.description);
|
|
163
184
|
}
|
|
164
185
|
for (const flag of cmd.flags) {
|
|
165
|
-
|
|
186
|
+
for (const opt of buildOptions(flag)) {
|
|
187
|
+
sub.addOption(opt);
|
|
188
|
+
}
|
|
166
189
|
}
|
|
167
190
|
addArgs(sub, cmd);
|
|
168
191
|
wireAction(sub, cmd);
|
package/src/flags.ts
CHANGED
|
@@ -33,7 +33,9 @@ const fieldTypeToCliFlag: Record<Field['type'], CliFlagShape> = {
|
|
|
33
33
|
enum: { type: 'string', variadic: false },
|
|
34
34
|
multiselect: { type: 'string[]', variadic: true },
|
|
35
35
|
number: { type: 'number', variadic: false },
|
|
36
|
+
'number[]': { type: 'number[]', variadic: true },
|
|
36
37
|
string: { type: 'string', variadic: false },
|
|
38
|
+
'string[]': { type: 'string[]', variadic: true },
|
|
37
39
|
};
|
|
38
40
|
|
|
39
41
|
/** Convert a derived field into a CLI flag descriptor. */
|