@ontrails/cli 1.0.0-beta.3 → 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 +23 -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/package.json +1 -1
- package/src/__tests__/blaze.test.ts +3 -4
- package/src/__tests__/build.test.ts +16 -18
- package/src/__tests__/layers.test.ts +5 -7
- package/src/__tests__/to-commander.test.ts +11 -12
- package/src/build.ts +7 -8
- package/src/command.ts +1 -2
package/.turbo/turbo-lint.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
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
|
+
|
|
3
26
|
## 1.0.0-beta.3
|
|
4
27
|
|
|
5
28
|
### Minor 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"}
|
package/package.json
CHANGED
|
@@ -15,8 +15,8 @@ import { defaultOnResult } from '../on-result.js';
|
|
|
15
15
|
describe('blaze', () => {
|
|
16
16
|
test('smoke test: buildCliCommands + toCommander wiring does not throw', () => {
|
|
17
17
|
const t = trail('ping', {
|
|
18
|
-
implementation: () => Result.ok('pong'),
|
|
19
18
|
input: z.object({}),
|
|
19
|
+
run: () => Result.ok('pong'),
|
|
20
20
|
});
|
|
21
21
|
const app = topo('smoke-test', { ping: t });
|
|
22
22
|
|
|
@@ -33,8 +33,8 @@ describe('blaze', () => {
|
|
|
33
33
|
|
|
34
34
|
test('uses defaultOnResult when none provided', () => {
|
|
35
35
|
const t = trail('echo', {
|
|
36
|
-
implementation: (input: { msg: string }) => Result.ok(input.msg),
|
|
37
36
|
input: z.object({ msg: z.string() }),
|
|
37
|
+
run: (input: { msg: string }) => Result.ok(input.msg),
|
|
38
38
|
});
|
|
39
39
|
const app = topo('default-on-result', { echo: t });
|
|
40
40
|
|
|
@@ -67,9 +67,8 @@ describe('blaze', () => {
|
|
|
67
67
|
|
|
68
68
|
try {
|
|
69
69
|
const t = trail('greet', {
|
|
70
|
-
implementation: (input: { name: string }) =>
|
|
71
|
-
Result.ok(`Hello, ${input.name}!`),
|
|
72
70
|
input: z.object({ name: z.string() }),
|
|
71
|
+
run: (input: { name: string }) => Result.ok(`Hello, ${input.name}!`),
|
|
73
72
|
});
|
|
74
73
|
const app = topo('e2e-test', { greet: t });
|
|
75
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) =>
|
|
@@ -62,9 +62,8 @@ const requireCommand = (
|
|
|
62
62
|
describe('toCommander', () => {
|
|
63
63
|
test('creates a Commander program with correct commands', () => {
|
|
64
64
|
const t = trail('greet', {
|
|
65
|
-
implementation: (input: { name: string }) =>
|
|
66
|
-
Result.ok(`Hello, ${input.name}`),
|
|
67
65
|
input: z.object({ name: z.string() }),
|
|
66
|
+
run: (input: { name: string }) => Result.ok(`Hello, ${input.name}`),
|
|
68
67
|
});
|
|
69
68
|
const app = makeApp(t);
|
|
70
69
|
const commands = buildCliCommands(app);
|
|
@@ -78,12 +77,12 @@ describe('toCommander', () => {
|
|
|
78
77
|
|
|
79
78
|
test('grouped commands create parent/subcommand structure', () => {
|
|
80
79
|
const show = trail('entity.show', {
|
|
81
|
-
implementation: () => Result.ok({}),
|
|
82
80
|
input: z.object({ id: z.string() }),
|
|
81
|
+
run: () => Result.ok({}),
|
|
83
82
|
});
|
|
84
83
|
const add = trail('entity.add', {
|
|
85
|
-
implementation: () => Result.ok({}),
|
|
86
84
|
input: z.object({ name: z.string() }),
|
|
85
|
+
run: () => Result.ok({}),
|
|
87
86
|
});
|
|
88
87
|
const app = makeApp(show, add);
|
|
89
88
|
const commands = buildCliCommands(app);
|
|
@@ -100,7 +99,6 @@ describe('toCommander', () => {
|
|
|
100
99
|
|
|
101
100
|
test('flag types map correctly to Commander options', () => {
|
|
102
101
|
const t = trail('search', {
|
|
103
|
-
implementation: () => Result.ok([]),
|
|
104
102
|
input: z.object({
|
|
105
103
|
format: z.enum(['json', 'text']).optional(),
|
|
106
104
|
limit: z.number().optional(),
|
|
@@ -108,6 +106,7 @@ describe('toCommander', () => {
|
|
|
108
106
|
tags: z.array(z.string()).optional(),
|
|
109
107
|
verbose: z.boolean().optional(),
|
|
110
108
|
}),
|
|
109
|
+
run: () => Result.ok([]),
|
|
111
110
|
});
|
|
112
111
|
const app = makeApp(t);
|
|
113
112
|
const commands = buildCliCommands(app);
|
|
@@ -125,8 +124,8 @@ describe('toCommander', () => {
|
|
|
125
124
|
describe('boolean flag negation', () => {
|
|
126
125
|
test('boolean flags get --no-<name> negation options', () => {
|
|
127
126
|
const t = trail('check', {
|
|
128
|
-
implementation: () => Result.ok('ok'),
|
|
129
127
|
input: z.object({ strict: z.boolean() }),
|
|
128
|
+
run: () => Result.ok('ok'),
|
|
130
129
|
});
|
|
131
130
|
const app = makeApp(t);
|
|
132
131
|
const commands = buildCliCommands(app);
|
|
@@ -142,8 +141,8 @@ describe('toCommander', () => {
|
|
|
142
141
|
|
|
143
142
|
test('--no-<flag> sets value to false via parseAsync', async () => {
|
|
144
143
|
const t = trail('check', {
|
|
145
|
-
implementation: () => Result.ok('ok'),
|
|
146
144
|
input: z.object({ strict: z.boolean().default(true) }),
|
|
145
|
+
run: () => Result.ok('ok'),
|
|
147
146
|
});
|
|
148
147
|
const app = makeApp(t);
|
|
149
148
|
const commands = buildCliCommands(app, { onResult: noopResult });
|
|
@@ -157,8 +156,8 @@ describe('toCommander', () => {
|
|
|
157
156
|
|
|
158
157
|
test('--flag sets boolean value to true via parseAsync', async () => {
|
|
159
158
|
const t = trail('check', {
|
|
160
|
-
implementation: () => Result.ok('ok'),
|
|
161
159
|
input: z.object({ strict: z.boolean().default(false) }),
|
|
160
|
+
run: () => Result.ok('ok'),
|
|
162
161
|
});
|
|
163
162
|
const app = makeApp(t);
|
|
164
163
|
const commands = buildCliCommands(app, { onResult: noopResult });
|
|
@@ -174,8 +173,8 @@ describe('toCommander', () => {
|
|
|
174
173
|
describe('strict number parsing', () => {
|
|
175
174
|
const buildNumberProgram = () => {
|
|
176
175
|
const t = trail('count', {
|
|
177
|
-
implementation: () => Result.ok('ok'),
|
|
178
176
|
input: z.object({ limit: z.number() }),
|
|
177
|
+
run: () => Result.ok('ok'),
|
|
179
178
|
});
|
|
180
179
|
const app = makeApp(t);
|
|
181
180
|
const commands = buildCliCommands(app);
|
|
@@ -247,8 +246,8 @@ describe('toCommander', () => {
|
|
|
247
246
|
{ expected: -5, input: '-5' },
|
|
248
247
|
])('accepts valid number "$input"', async ({ expected, input }) => {
|
|
249
248
|
const t = trail('count', {
|
|
250
|
-
implementation: () => Result.ok('ok'),
|
|
251
249
|
input: z.object({ limit: z.number() }),
|
|
250
|
+
run: () => Result.ok('ok'),
|
|
252
251
|
});
|
|
253
252
|
const app = makeApp(t);
|
|
254
253
|
const commands = buildCliCommands(app, { onResult: noopResult });
|
|
@@ -263,8 +262,8 @@ describe('toCommander', () => {
|
|
|
263
262
|
|
|
264
263
|
test('sets version when provided', () => {
|
|
265
264
|
const t = trail('ping', {
|
|
266
|
-
implementation: () => Result.ok('pong'),
|
|
267
265
|
input: z.object({}),
|
|
266
|
+
run: () => Result.ok('pong'),
|
|
268
267
|
});
|
|
269
268
|
const app = makeApp(t);
|
|
270
269
|
const commands = buildCliCommands(app);
|
|
@@ -283,8 +282,8 @@ describe('toCommander', () => {
|
|
|
283
282
|
// This test verifies the error handling structure exists.
|
|
284
283
|
// Full integration would need process.exit mocking.
|
|
285
284
|
const t = trail('fail', {
|
|
286
|
-
implementation: () => Result.ok('ok'),
|
|
287
285
|
input: z.object({}),
|
|
286
|
+
run: () => Result.ok('ok'),
|
|
288
287
|
});
|
|
289
288
|
const app = makeApp(t);
|
|
290
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(
|