tubeless 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -20
- package/dist/cli/cli-command.d.ts +1 -0
- package/dist/cli/cli-command.js +2 -0
- package/dist/cli/cli-command.js.map +1 -1
- package/dist/cli/cli-pipeline-command.d.ts +24 -6
- package/dist/cli/cli-pipeline-command.js +32 -12
- package/dist/cli/cli-pipeline-command.js.map +1 -1
- package/dist/cli/cli-schema.d.ts +25 -0
- package/dist/cli/cli-schema.js +129 -0
- package/dist/cli/cli-schema.js.map +1 -0
- package/dist/cli/cli-types.d.ts +18 -0
- package/dist/cli/cli-types.js +2 -0
- package/dist/cli/cli-types.js.map +1 -1
- package/dist/cli/cli.d.ts +2 -2
- package/dist/cli/cli.js.map +1 -1
- package/dist/core/child-execution.d.ts +3 -7
- package/dist/core/child-execution.js +34 -185
- package/dist/core/child-execution.js.map +1 -1
- package/dist/core/child-progress.d.ts +15 -5
- package/dist/core/child-progress.js +252 -9
- package/dist/core/child-progress.js.map +1 -1
- package/dist/core/mapped-child-progress.d.ts +4 -20
- package/dist/core/mapped-child-progress.js +2 -34
- package/dist/core/mapped-child-progress.js.map +1 -1
- package/dist/core/pipeline-compiler.d.ts +3 -2
- package/dist/core/pipeline-compiler.js +22 -5
- package/dist/core/pipeline-compiler.js.map +1 -1
- package/dist/core/pipeline-definition-identity.d.ts +14 -0
- package/dist/core/pipeline-definition-identity.js +141 -0
- package/dist/core/pipeline-definition-identity.js.map +1 -0
- package/dist/core/pipeline-definition-validation.js +13 -5
- package/dist/core/pipeline-definition-validation.js.map +1 -1
- package/dist/core/pipeline-definition.d.ts +26 -4
- package/dist/core/pipeline-definition.js.map +1 -1
- package/dist/core/pipeline-execute.d.ts +1 -2
- package/dist/core/pipeline-execute.js +80 -73
- package/dist/core/pipeline-execute.js.map +1 -1
- package/dist/core/pipeline-finalizer.d.ts +1 -1
- package/dist/core/pipeline-finalizer.js +1 -1
- package/dist/core/pipeline-finalizer.js.map +1 -1
- package/dist/core/pipeline-ids.js +1 -6
- package/dist/core/pipeline-ids.js.map +1 -1
- package/dist/core/pipeline-plan.js +2 -0
- package/dist/core/pipeline-plan.js.map +1 -1
- package/dist/core/pipeline-run-state.js +22 -4
- package/dist/core/pipeline-run-state.js.map +1 -1
- package/dist/core/pipeline-scheduler.d.ts +10 -0
- package/dist/core/pipeline-scheduler.js +54 -0
- package/dist/core/pipeline-scheduler.js.map +1 -0
- package/dist/core/pipeline-steps.d.ts +23 -18
- package/dist/core/pipeline-steps.js +5 -9
- package/dist/core/pipeline-steps.js.map +1 -1
- package/dist/core/pipeline-types.d.ts +71 -9
- package/dist/core/pipeline-types.js.map +1 -1
- package/dist/core/pipeline.d.ts +17 -6
- package/dist/core/pipeline.js +14 -3
- package/dist/core/pipeline.js.map +1 -1
- package/dist/node/checkpoint.d.ts +2 -0
- package/dist/node/checkpoint.js +1 -0
- package/dist/node/checkpoint.js.map +1 -1
- package/dist/node/env.d.ts +1 -0
- package/dist/node/env.js +1 -0
- package/dist/node/env.js.map +1 -1
- package/dist/node/file-utils.d.ts +3 -0
- package/dist/node/file-utils.js +3 -0
- package/dist/node/file-utils.js.map +1 -1
- package/dist/node/node.d.ts +2 -0
- package/dist/node/node.js +1 -0
- package/dist/node/node.js.map +1 -1
- package/dist/node/paths.d.ts +2 -1
- package/dist/node/paths.js +2 -1
- package/dist/node/paths.js.map +1 -1
- package/dist/node/worker-thread-adapter.d.ts +19 -0
- package/dist/node/worker-thread-adapter.js +194 -0
- package/dist/node/worker-thread-adapter.js.map +1 -0
- package/dist/node/worker-thread-protocol.d.ts +57 -0
- package/dist/node/worker-thread-protocol.js +26 -0
- package/dist/node/worker-thread-protocol.js.map +1 -0
- package/dist/node/worker-thread-runtime.d.ts +1 -0
- package/dist/node/worker-thread-runtime.js +53 -0
- package/dist/node/worker-thread-runtime.js.map +1 -0
- package/dist/project/pipeline-project.d.ts +37 -0
- package/dist/project/pipeline-project.js +90 -0
- package/dist/project/pipeline-project.js.map +1 -0
- package/dist/project/project-compiler.d.ts +5 -3
- package/dist/project/project-compiler.js +6 -3
- package/dist/project/project-compiler.js.map +1 -1
- package/dist/project/project.d.ts +2 -3
- package/dist/project/project.js +2 -3
- package/dist/project/project.js.map +1 -1
- package/dist/render/render.d.ts +3 -7
- package/dist/render/render.js +5 -2
- package/dist/render/render.js.map +1 -1
- package/dist/reporter/interactive-reporter.d.ts +5 -0
- package/dist/reporter/interactive-reporter.js +39 -32
- package/dist/reporter/interactive-reporter.js.map +1 -1
- package/dist/reporter/live-ticker-worker.js +17 -14
- package/dist/reporter/live-ticker-worker.js.map +1 -1
- package/dist/reporter/live-ticker.d.ts +6 -6
- package/dist/reporter/live-ticker.js +117 -44
- package/dist/reporter/live-ticker.js.map +1 -1
- package/dist/reporter/reporter.d.ts +5 -0
- package/dist/reporter/reporter.js +27 -17
- package/dist/reporter/reporter.js.map +1 -1
- package/dist/reporter/terminal-text.d.ts +2 -0
- package/dist/reporter/terminal-text.js +20 -0
- package/dist/reporter/terminal-text.js.map +1 -0
- package/dist/run-store/definition-diff.d.ts +9 -0
- package/dist/run-store/definition-diff.js +39 -0
- package/dist/run-store/definition-diff.js.map +1 -0
- package/dist/run-store/run-store-codec.d.ts +2 -2
- package/dist/run-store/run-store-codec.js +14 -14
- package/dist/run-store/run-store-codec.js.map +1 -1
- package/dist/run-store/run-store-event-decoder.d.ts +3 -0
- package/dist/run-store/run-store-event-decoder.js +18 -0
- package/dist/run-store/run-store-event-decoder.js.map +1 -0
- package/dist/run-store/run-store-ndjson.js +2 -2
- package/dist/run-store/run-store-ndjson.js.map +1 -1
- package/dist/run-store/run-store-sqlite.js +3 -3
- package/dist/run-store/run-store-sqlite.js.map +1 -1
- package/dist/run-store/run-store.d.ts +4 -1
- package/dist/run-store/run-store.js +23 -9
- package/dist/run-store/run-store.js.map +1 -1
- package/dist/studio/run-store-ui-client-browser.js +2 -2
- package/dist/studio/run-store-ui-client-transport.d.ts +7 -1
- package/dist/studio/run-store-ui-client-transport.js +9 -6
- package/dist/studio/run-store-ui-client-transport.js.map +1 -1
- package/dist/studio/run-store-ui-client.d.ts +68 -1
- package/dist/studio/run-store-ui-client.js +764 -3
- package/dist/studio/run-store-ui-client.js.map +1 -1
- package/dist/studio/run-store-ui-data-controller.d.ts +24 -0
- package/dist/studio/run-store-ui-data-controller.js +238 -0
- package/dist/studio/run-store-ui-data-controller.js.map +1 -0
- package/dist/studio/run-store-ui-definitions.d.ts +6 -0
- package/dist/studio/run-store-ui-definitions.js +29 -0
- package/dist/studio/run-store-ui-definitions.js.map +1 -0
- package/dist/studio/run-store-ui-page.d.ts +1 -1
- package/dist/studio/run-store-ui-page.js +6 -1
- package/dist/studio/run-store-ui-page.js.map +1 -1
- package/dist/studio/run-store-ui.js +1 -1
- package/dist/studio/run-store-ui.js.map +1 -1
- package/dist/testing/testing.d.ts +2 -0
- package/dist/testing/testing.js.map +1 -1
- package/dist/tracing/tracing-internal.js +18 -3
- package/dist/tracing/tracing-internal.js.map +1 -1
- package/dist/tracing/tracing-schema.d.ts +167 -12
- package/dist/tracing/tracing-schema.js +57 -1
- package/dist/tracing/tracing-schema.js.map +1 -1
- package/dist/utilities/batch.d.ts +4 -1
- package/dist/utilities/batch.js +3 -1
- package/dist/utilities/batch.js.map +1 -1
- package/dist/utilities/pipeline-command-marker.d.ts +4 -0
- package/dist/utilities/pipeline-command-marker.js +16 -0
- package/dist/utilities/pipeline-command-marker.js.map +1 -0
- package/dist/utilities/rate-limit.d.ts +1 -0
- package/dist/utilities/rate-limit.js +1 -0
- package/dist/utilities/rate-limit.js.map +1 -1
- package/dist/utilities/retry.d.ts +3 -1
- package/dist/utilities/retry.js +1 -0
- package/dist/utilities/retry.js.map +1 -1
- package/dist/workbench/pipeline-module.d.ts +1 -0
- package/dist/workbench/pipeline-module.js +5 -5
- package/dist/workbench/pipeline-module.js.map +1 -1
- package/dist/workbench/workbench-commands.d.ts +6 -0
- package/dist/workbench/workbench-commands.js +288 -0
- package/dist/workbench/workbench-commands.js.map +1 -0
- package/dist/workbench/workbench-history.js +1 -1
- package/dist/workbench/workbench-history.js.map +1 -1
- package/dist/workbench/workbench-launch-session.d.ts +25 -0
- package/dist/workbench/workbench-launch-session.js +91 -0
- package/dist/workbench/workbench-launch-session.js.map +1 -0
- package/dist/workbench/workbench-project-loader.d.ts +28 -26
- package/dist/workbench/workbench-project-loader.js +94 -86
- package/dist/workbench/workbench-project-loader.js.map +1 -1
- package/dist/workbench/workbench-run.js +7 -4
- package/dist/workbench/workbench-run.js.map +1 -1
- package/dist/workbench/workbench-shared.d.ts +3 -0
- package/dist/workbench/workbench-shared.js +2 -1
- package/dist/workbench/workbench-shared.js.map +1 -1
- package/dist/workbench/workbench-ui.js +45 -145
- package/dist/workbench/workbench-ui.js.map +1 -1
- package/dist/workbench/workbench.d.ts +1 -1
- package/dist/workbench/workbench.js +4 -8
- package/dist/workbench/workbench.js.map +1 -1
- package/docs/README.md +12 -11
- package/docs/agent-guide.md +101 -27
- package/docs/agent-skills.md +1 -1
- package/docs/api-reference.md +156 -145
- package/docs/api-report.json +20 -29
- package/docs/assets/social.svg +192 -56
- package/docs/child-pipeline-composition.md +17 -12
- package/docs/cli.md +239 -75
- package/docs/comparison.md +21 -29
- package/docs/concepts.md +112 -17
- package/docs/declarative-pipelines.md +57 -28
- package/docs/getting-started.md +95 -17
- package/docs/llms.txt +8 -4
- package/docs/recipes.md +65 -36
- package/docs/remote-step-composition.md +81 -1
- package/docs/studio.md +115 -31
- package/examples/automatic-cli.ts +12 -0
- package/examples/child-pipeline.ts +0 -9
- package/examples/cli-job.ts +2 -14
- package/examples/declarative/handlers.ts +2 -2
- package/examples/declarative/peloton-handlers.ts +2 -2
- package/examples/live-tui.ts +4 -1
- package/examples/minimal-pipeline.ts +24 -0
- package/examples/parallel-dag.ts +46 -0
- package/examples/prime-worker.ts +22 -0
- package/examples/{catalog → project}/pipelines/enrich.ts +2 -2
- package/examples/{catalog → project}/scripts/enrich.ts +1 -0
- package/examples/{catalog → project}/scripts/import.ts +1 -0
- package/examples/{catalog → project}/scripts/publish.ts +1 -0
- package/examples/project/tubeless.project.ts +47 -0
- package/examples/tracing.ts +3 -0
- package/examples/tubeless.project.ts +9 -0
- package/examples/typed-import.ts +0 -10
- package/examples/validated-boundaries.ts +8 -12
- package/examples/worker-threads.ts +50 -0
- package/examples/yaml-peloton.ts +3 -3
- package/examples/yaml-pipelines.ts +7 -5
- package/package.json +5 -7
- package/skills/tubeless/SKILL.md +51 -13
- package/skills/tubeless-make-pipeline/SKILL.md +1 -1
- package/dist/cli/pipeline-command-marker.d.ts +0 -4
- package/dist/cli/pipeline-command-marker.js +0 -21
- package/dist/cli/pipeline-command-marker.js.map +0 -1
- package/dist/project/project-manifest.d.ts +0 -27
- package/dist/project/project-manifest.js +0 -66
- package/dist/project/project-manifest.js.map +0 -1
- package/dist/studio/run-store-ui-client-app.d.ts +0 -12
- package/dist/studio/run-store-ui-client-app.js +0 -224
- package/dist/studio/run-store-ui-client-app.js.map +0 -1
- package/dist/studio/run-store-ui-client-commands.d.ts +0 -18
- package/dist/studio/run-store-ui-client-commands.js +0 -98
- package/dist/studio/run-store-ui-client-commands.js.map +0 -1
- package/dist/studio/run-store-ui-client-form.d.ts +0 -11
- package/dist/studio/run-store-ui-client-form.js +0 -54
- package/dist/studio/run-store-ui-client-form.js.map +0 -1
- package/dist/studio/run-store-ui-client-modals.d.ts +0 -20
- package/dist/studio/run-store-ui-client-modals.js +0 -154
- package/dist/studio/run-store-ui-client-modals.js.map +0 -1
- package/dist/studio/run-store-ui-client-model.d.ts +0 -19
- package/dist/studio/run-store-ui-client-model.js +0 -189
- package/dist/studio/run-store-ui-client-model.js.map +0 -1
- package/dist/studio/run-store-ui-client-runs.d.ts +0 -24
- package/dist/studio/run-store-ui-client-runs.js +0 -78
- package/dist/studio/run-store-ui-client-runs.js.map +0 -1
- package/dist/studio/run-store-ui-client-shared.d.ts +0 -22
- package/dist/studio/run-store-ui-client-shared.js +0 -63
- package/dist/studio/run-store-ui-client-shared.js.map +0 -1
- package/dist/workbench/workbench-graph.d.ts +0 -2
- package/dist/workbench/workbench-graph.js +0 -64
- package/dist/workbench/workbench-graph.js.map +0 -1
- package/dist/workbench/workbench-inspect.d.ts +0 -2
- package/dist/workbench/workbench-inspect.js +0 -70
- package/dist/workbench/workbench-inspect.js.map +0 -1
- package/dist/workbench/workbench-list.d.ts +0 -2
- package/dist/workbench/workbench-list.js +0 -53
- package/dist/workbench/workbench-list.js.map +0 -1
- package/dist/workbench/workbench-plan.d.ts +0 -2
- package/dist/workbench/workbench-plan.js +0 -67
- package/dist/workbench/workbench-plan.js.map +0 -1
- package/dist/workbench/workbench-validate.d.ts +0 -2
- package/dist/workbench/workbench-validate.js +0 -76
- package/dist/workbench/workbench-validate.js.map +0 -1
- package/examples/catalog/tubeless.project.ts +0 -76
- /package/examples/{catalog → project}/pipelines/import.ts +0 -0
- /package/examples/{catalog → project}/pipelines/normalize.ts +0 -0
- /package/examples/{catalog → project}/pipelines/publish.ts +0 -0
package/README.md
CHANGED
|
@@ -11,11 +11,13 @@
|
|
|
11
11
|
<a href="https://www.npmjs.com/package/tubeless"><img alt="npm" src="https://img.shields.io/npm/v/tubeless?style=flat-square&labelColor=121212&color=c4a046"></a>
|
|
12
12
|
<a href="https://github.com/chetmancini/tubeless/actions/workflows/check.yml"><img alt="check" src="https://img.shields.io/github/actions/workflow/status/chetmancini/tubeless/check.yml?style=flat-square&label=check&labelColor=121212&color=2f6f4a"></a>
|
|
13
13
|
<a href="./LICENSE"><img alt="MIT" src="https://img.shields.io/npm/l/tubeless?style=flat-square&labelColor=121212&color=c4c0b4"></a>
|
|
14
|
+
<a href="./docs/getting-started.md#install"><img alt="Node" src="https://img.shields.io/node/v/tubeless?style=flat-square&labelColor=121212&color=c4c0b4"></a> <a href="https://www.npmjs.com/package/tubeless"><img alt="provenance" src="https://img.shields.io/badge/provenance-npm-2f6f4a?style=flat-square&labelColor=121212"></a>
|
|
14
15
|
</p>
|
|
15
16
|
|
|
16
17
|
Tubeless is a TypeScript toolkit for work that unfolds in steps. It fits data
|
|
17
18
|
pipelines, multi-step application workflows, and AI workloads—anywhere you want
|
|
18
|
-
explicit dependencies, typed handoffs, and inspectable execution.
|
|
19
|
+
explicit dependencies, typed handoffs, and inspectable execution. The name is the
|
|
20
|
+
cycling kind of tubeless: no inner tube, and no extra runtime to keep the work rolling.
|
|
19
21
|
|
|
20
22
|
Pipelines run in your process with no runtime dependencies. You can preview
|
|
21
23
|
execution, select a target and its dependencies, compose child pipelines, and
|
|
@@ -36,11 +38,10 @@ Tubeless is pre-1.0, so the public API may change between releases.
|
|
|
36
38
|
|
|
37
39
|
## Quick start
|
|
38
40
|
|
|
39
|
-
This pipeline loads and normalizes strings. `step` creates a step; dependencies give typed
|
|
40
|
-
inputs. Adding `skip` makes it skippable and widens its output to include `undefined`.
|
|
41
|
+
This pipeline loads and normalizes strings. `step` creates a step; dependencies give typed inputs.
|
|
41
42
|
|
|
42
43
|
```ts
|
|
43
|
-
import { createSteps, definePipeline
|
|
44
|
+
import { createSteps, definePipeline } from "tubeless";
|
|
44
45
|
|
|
45
46
|
interface ImportOptions {
|
|
46
47
|
lines: readonly string[];
|
|
@@ -60,33 +61,33 @@ const normalize = step("normalize", {
|
|
|
60
61
|
export const ImportPipeline = definePipeline({
|
|
61
62
|
id: "import",
|
|
62
63
|
steps: [load, normalize],
|
|
63
|
-
targets: [normalize],
|
|
64
|
-
finalize: requireOutputs([normalize], ({ normalize }) => normalize),
|
|
65
64
|
});
|
|
66
65
|
|
|
67
66
|
const rows = await ImportPipeline.runOrThrow({ lines: [" Alpha ", "", "Beta"] });
|
|
68
67
|
// ["alpha", "beta"]
|
|
69
68
|
```
|
|
70
69
|
|
|
71
|
-
`
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
Omitted `targets` and `finalize` use the last step in execution order: `normalize`.
|
|
71
|
+
Missing output returns `undefined`; use `requireOutputs` when absence should fail.
|
|
72
|
+
|
|
73
|
+
`runOrThrow` returns the result or throws on failure. Use `run` for reports, `plan`
|
|
74
|
+
for previews, and `toMermaid` for diagrams. See [getting started](./docs/getting-started.md).
|
|
74
75
|
|
|
75
76
|
## Use the CLI
|
|
76
77
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
Projects made with `defineProject(id, pipelines)` are directly usable by the CLI;
|
|
79
|
+
schema-backed pipelines get inferred flags automatically. See the [CLI guide](./docs/cli.md)
|
|
80
|
+
for direct project usage and advanced custom command adapters. From this repository:
|
|
80
81
|
|
|
81
82
|
```sh
|
|
82
|
-
bunx tubeless list
|
|
83
|
-
bunx tubeless inspect import
|
|
84
|
-
bunx tubeless run import
|
|
83
|
+
bunx tubeless list --project examples/tubeless.project.ts
|
|
84
|
+
bunx tubeless inspect --project examples/tubeless.project.ts validated-import
|
|
85
|
+
bunx tubeless run --project examples/tubeless.project.ts validated-import -- --source rows.txt
|
|
85
86
|
```
|
|
86
87
|
|
|
87
|
-
|
|
88
|
-
Record runs with `--store` or
|
|
89
|
-
|
|
88
|
+
In your app, add `tubeless.project.ts` and omit `--project`. Pass application
|
|
89
|
+
flags after `--`. Record runs with `--store` or `--trace`, then inspect them with
|
|
90
|
+
`tubeless history` or the [local studio](./docs/studio.md).
|
|
90
91
|
|
|
91
92
|
## Find your route
|
|
92
93
|
|
|
@@ -94,8 +95,7 @@ them with `tubeless history` or the [local studio](./docs/studio.md).
|
|
|
94
95
|
[dry runs and write gates](./examples/publish-with-gates.ts) to a publishing job.
|
|
95
96
|
- Build a larger workflow with [child pipelines](./examples/child-pipeline.ts)
|
|
96
97
|
and [fan-out](./examples/fan-out-progress.ts).
|
|
97
|
-
-
|
|
98
|
-
workflow that brings several pipeline features together.
|
|
98
|
+
- Optional: the [peloton example](./examples/peloton.ts) is a cycling-themed kitchen sink for the live TUI.
|
|
99
99
|
|
|
100
100
|
The [recipe index](./docs/recipes.md) covers validation, retries, tracing, testing,
|
|
101
101
|
and more. For help authoring pipelines with a coding agent, install the
|
|
@@ -2,4 +2,5 @@ import { type CliCommand, type CliCommandConfig, type CliParamsSchema } from "./
|
|
|
2
2
|
export declare function createCommand<const TSchema extends CliParamsSchema, TResult = void>(config: CliCommandConfig<TSchema, TResult>, mainExits?: {
|
|
3
3
|
validation?: number;
|
|
4
4
|
}): CliCommand<TSchema, TResult>;
|
|
5
|
+
/** Create a typed command from a declarative parameter schema and run handler. */
|
|
5
6
|
export declare function defineCommand<const TSchema extends CliParamsSchema, TResult = void>(config: CliCommandConfig<TSchema, TResult>): CliCommand<TSchema, TResult>;
|
package/dist/cli/cli-command.js
CHANGED
|
@@ -8,6 +8,7 @@ function resolveContext(overrides) {
|
|
|
8
8
|
cwd: overrides?.cwd ?? process.cwd(),
|
|
9
9
|
env: overrides?.env ?? process.env,
|
|
10
10
|
log: overrides?.log ?? console,
|
|
11
|
+
reporterOutput: overrides?.reporterOutput,
|
|
11
12
|
pipelineContext: overrides?.pipelineContext,
|
|
12
13
|
signal: overrides?.signal,
|
|
13
14
|
checkpoint: overrides?.checkpoint,
|
|
@@ -291,6 +292,7 @@ function normalizeStructuredValue(key, param, value, errors) {
|
|
|
291
292
|
}
|
|
292
293
|
return value;
|
|
293
294
|
}
|
|
295
|
+
/** Create a typed command from a declarative parameter schema and run handler. */
|
|
294
296
|
export function defineCommand(config) {
|
|
295
297
|
return createCommand(config);
|
|
296
298
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-command.js","sourceRoot":"","sources":["../../src/cli/cli-command.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from \"path\";\nimport { openCheckpoint, type CheckpointStore } from \"../node/checkpoint.js\";\nimport {\n assertNoDuplicateFlags,\n assertValidEnvironmentFallbacks,\n assertValidMultipleParams,\n assertValidPositionals,\n buildEffectiveSchema,\n commandDescriptor,\n renderHelp,\n resolveParam,\n tokenize,\n type ResolvedParamValue,\n} from \"./cli-parser.js\";\nimport {\n CliHelpRequested,\n CliValidationError,\n type CliCommand,\n type CliCommandConfig,\n type CliContext,\n type CliParams,\n type CliParamsSchema,\n type CliParseResult,\n} from \"./cli-types.js\";\nimport { isCliValidationError, isPipelineExecutionError, toExitCode } from \"./cli-exit.js\";\n\nfunction resolveContext(overrides?: Partial<CliContext>): CliContext {\n return {\n cwd: overrides?.cwd ?? process.cwd(),\n env: overrides?.env ?? process.env,\n log: overrides?.log ?? console,\n pipelineContext: overrides?.pipelineContext,\n signal: overrides?.signal,\n checkpoint: overrides?.checkpoint,\n };\n}\n\ninterface ManagedMainSignal {\n context: CliContext;\n wasInterrupted(): boolean;\n cleanup(): void;\n}\n\nconst SIGINT_EXIT_CODE = 130;\n\n/**\n * Give real CLI entrypoints graceful cancellation without making `run()` or\n * `parse()` mutate process-global signal handlers. Embedded callers can pass\n * their own signal through the context instead.\n */\nfunction manageMainSignal(context: CliContext): ManagedMainSignal {\n if (context.signal) {\n return { context, wasInterrupted: () => false, cleanup: () => {} };\n }\n\n const controller = new AbortController();\n let interrupted = false;\n const onSigint = (): void => {\n interrupted = true;\n context.log.warn(\"SIGINT received; cancelling pipeline work.\");\n controller.abort();\n };\n process.once(\"SIGINT\", onSigint);\n\n return {\n context: { ...context, signal: controller.signal },\n wasInterrupted: () => interrupted,\n cleanup: () => process.removeListener(\"SIGINT\", onSigint),\n };\n}\n\n/**\n * An in-memory-only `CheckpointStore` seeded from `seed`: reads and `record()` behave\n * exactly like a real store for the rest of this run, but `flush()`/`clear()` never touch\n * disk. Every dry-run path hands `run` one of these instead of the real store — the\n * managed-checkpoint contract is that a dry run never writes to the checkpoint file, no\n * matter what `run` does with `context.checkpoint` (`record`/`flush`/`clear`, directly or\n * via `withCheckpointedBatch`).\n */\nfunction inMemoryCheckpointView(seed: ReadonlyMap<string, unknown>): CheckpointStore {\n const entries = new Map(seed);\n return {\n has: (key) => entries.has(key),\n record: (key, meta) => {\n entries.set(key, meta);\n },\n entries: () => entries,\n flush: () => {},\n clear: () => {\n entries.clear();\n },\n };\n}\n\nexport function createCommand<const TSchema extends CliParamsSchema, TResult = void>(\n config: CliCommandConfig<TSchema, TResult>,\n mainExits?: { validation?: number }\n): CliCommand<TSchema, TResult> {\n const effectiveParams = buildEffectiveSchema(config.params, config.checkpoint);\n assertNoDuplicateFlags(effectiveParams);\n assertValidMultipleParams(effectiveParams);\n assertValidEnvironmentFallbacks(effectiveParams);\n const positionals = [...(config.positionals ?? [])];\n assertValidPositionals(positionals, effectiveParams);\n const descriptor = commandDescriptor(config, effectiveParams, positionals);\n\n function resolveValues(\n readValue: (\n key: string,\n param: CliParamsSchema[string]\n ) => string | boolean | string[] | undefined,\n context: CliContext,\n errors: string[],\n helpText: string\n ): CliParseResult<TSchema> {\n const values: Record<string, ResolvedParamValue> = {};\n for (const [key, param] of Object.entries(effectiveParams)) {\n const errorCount = errors.length;\n const raw = readValue(key, param);\n if (errors.length > errorCount) continue;\n const envValue = raw === undefined && param.env ? context.env?.[param.env] : undefined;\n values[key] = resolveParam(\n key,\n param,\n raw ?? envValue,\n context.cwd,\n errors,\n raw !== undefined ? \"argv\" : envValue !== undefined ? \"env\" : \"default\"\n );\n }\n if (errors.length > 0) return { kind: \"error\", errors, helpText };\n // SAFETY: resolveParam populated every effective schema key and all input checks passed.\n const typedValues = values as CliParams<TSchema>;\n const validationErrors = config.validate?.(typedValues, context) ?? [];\n return validationErrors.length > 0\n ? { kind: \"error\", errors: validationErrors, helpText }\n : { kind: \"values\", values: typedValues };\n }\n\n function parseWithContext(argv: readonly string[], context: CliContext): CliParseResult<TSchema> {\n const helpText = renderHelp(\n descriptor.name,\n descriptor.description,\n effectiveParams,\n positionals\n );\n const tokenized = tokenize(argv, effectiveParams, positionals);\n if (tokenized.help) return { kind: \"help\", helpText };\n return resolveValues(\n (key) => tokenized.values.get(key),\n context,\n [...tokenized.errors],\n helpText\n );\n }\n\n function parse(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): CliParseResult<TSchema> {\n return parseWithContext(argv, resolveContext(contextOverrides));\n }\n\n function parseStructuredWithContext(\n structuredValues: Record<string, unknown>,\n context: CliContext\n ): CliParseResult<TSchema> {\n const helpText = renderHelp(\n descriptor.name,\n descriptor.description,\n effectiveParams,\n positionals\n );\n const errors: string[] = [];\n for (const key of Object.keys(structuredValues)) {\n if (!Object.prototype.hasOwnProperty.call(effectiveParams, key)) {\n errors.push(`Unknown parameter: ${key}`);\n }\n }\n return resolveValues(\n (key, param) => normalizeStructuredValue(key, param, structuredValues[key], errors),\n context,\n errors,\n helpText\n );\n }\n\n /**\n * No-op unless `config.checkpoint` is set. Respects a caller-provided `context.checkpoint`\n * override (e.g. a stub in tests) instead of opening the real file. Otherwise opens (or\n * clears, if not resuming) the checkpoint before `run` is called — never on the `--help`/\n * error paths, since those return before this is reached.\n */\n function attachCheckpoint(context: CliContext, values: CliParams<TSchema>): CliContext {\n const checkpointConfig = config.checkpoint;\n if (!checkpointConfig) {\n return context;\n }\n const resolvedPath = path.isAbsolute(checkpointConfig.path)\n ? checkpointConfig.path\n : path.join(context.cwd, checkpointConfig.path);\n // A caller-provided context.checkpoint (e.g. a stub in tests) is used as the\n // underlying store instead of opening the real file, but every rule below — fresh\n // clearing, dry-run wrapping, resume detection/logging — still applies to it; only\n // the \"where does the store come from\" step is skipped.\n const store = context.checkpoint ?? openCheckpoint(resolvedPath);\n const hadExisting = store.entries().size > 0;\n\n if (values.resume) {\n if (hadExisting) {\n context.log.log(\n `Resuming from checkpoint: ${store.entries().size} item(s) already recorded.`\n );\n } else {\n // Without this, --resume against a missing/wrong-path/already-cleared checkpoint\n // silently starts fresh — the exact failure mode that's dangerous for\n // clearOnSuccess: false workflows, where \"fresh\" quietly means \"reprocess\n // everything already done\".\n context.log.warn(\n `--resume was passed, but no checkpoint was found at ${resolvedPath}; starting fresh.`\n );\n }\n // A dry run must never write to the checkpoint file, even while resuming — an\n // in-memory view seeded with the real entries previews it accurately without risk.\n return {\n ...context,\n checkpoint: values.dryRun ? inMemoryCheckpointView(store.entries()) : store,\n };\n }\n\n if (!hadExisting) {\n return {\n ...context,\n checkpoint: values.dryRun ? inMemoryCheckpointView(store.entries()) : store,\n };\n }\n\n if (values.dryRun) {\n // Dry run must not touch the file — neither clearing it nor writing new progress —\n // but the preview should still reflect what a real fresh run would see: an empty\n // \"done\" set, not the stale entries a --resume invocation would use.\n context.log.log(\"Dry run: leaving existing checkpoint untouched (would start fresh).\");\n return { ...context, checkpoint: inMemoryCheckpointView(new Map()) };\n }\n\n store.clear();\n context.log.log(\"Starting fresh — cleared existing checkpoint.\");\n return { ...context, checkpoint: store };\n }\n\n /**\n * No-op unless `config.checkpoint` is set, a store is attached, and the run completed\n * without a dry run or caller cancellation.\n */\n function finalizeCheckpoint(context: CliContext, values: CliParams<TSchema>): void {\n const checkpointConfig = config.checkpoint;\n if (!checkpointConfig || !context.checkpoint || values.dryRun || context.signal?.aborted) {\n return;\n }\n if (checkpointConfig.clearOnSuccess === false) {\n return;\n }\n context.checkpoint.clear();\n }\n\n async function executeValues(values: CliParams<TSchema>, context: CliContext): Promise<TResult> {\n const runContext = attachCheckpoint(context, values);\n const value = await config.run(values, runContext);\n finalizeCheckpoint(runContext, values);\n return value;\n }\n\n function parseValues(\n values: Record<string, unknown>,\n contextOverrides?: Partial<CliContext>\n ): CliParseResult<TSchema> {\n const context = resolveContext(contextOverrides);\n return parseStructuredWithContext(values, context);\n }\n\n async function execute(\n values: CliParams<TSchema>,\n contextOverrides?: Partial<CliContext>\n ): Promise<TResult> {\n return executeValues(values, resolveContext(contextOverrides));\n }\n\n async function run(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): Promise<TResult> {\n const context = resolveContext(contextOverrides);\n const result = parseWithContext(argv, context);\n if (result.kind === \"help\") throw new CliHelpRequested(result.helpText);\n if (result.kind === \"error\") throw new CliValidationError(result.errors, result.helpText);\n return executeValues(result.values, context);\n }\n\n async function main(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): Promise<void> {\n const context = resolveContext(contextOverrides);\n let result: CliParseResult<TSchema>;\n try {\n result = parseWithContext(argv, context);\n } catch (error) {\n context.log.error(error instanceof Error ? (error.stack ?? error.message) : String(error));\n process.exitCode =\n mainExits || isCliValidationError(error) || isPipelineExecutionError(error)\n ? toExitCode(error)\n : 1;\n return;\n }\n if (result.kind === \"help\") {\n context.log.log(result.helpText);\n process.exitCode = 0;\n return;\n }\n if (result.kind === \"error\") {\n for (const error of result.errors) {\n context.log.error(`Error: ${error}`);\n }\n context.log.error(\"\");\n context.log.error(result.helpText);\n process.exitCode = mainExits?.validation ?? 1;\n return;\n }\n const managedSignal = manageMainSignal(context);\n try {\n const runContext = attachCheckpoint(managedSignal.context, result.values);\n await config.run(result.values, runContext);\n if (!managedSignal.wasInterrupted()) {\n finalizeCheckpoint(runContext, result.values);\n }\n } catch (error) {\n context.log.error(error instanceof Error ? (error.stack ?? error.message) : String(error));\n process.exitCode = managedSignal.wasInterrupted()\n ? SIGINT_EXIT_CODE\n : mainExits || isCliValidationError(error) || isPipelineExecutionError(error)\n ? toExitCode(error)\n : 1;\n } finally {\n if (managedSignal.wasInterrupted()) {\n process.exitCode = SIGINT_EXIT_CODE;\n }\n managedSignal.cleanup();\n }\n }\n\n return { descriptor, execute, parse, parseValues, run, main };\n}\n\nfunction normalizeStructuredValue(\n key: string,\n param: CliParamsSchema[string],\n value: unknown,\n errors: string[]\n): string | boolean | string[] | undefined {\n if (value === undefined) return undefined;\n const label = `--${param.flag ?? key}`;\n if (param.type === \"boolean\") {\n if (typeof value === \"boolean\") return value;\n errors.push(`${label} must be a boolean value.`);\n return undefined;\n }\n if ((param.type === \"number\" || param.type === \"string\") && param.multiple === true) {\n if (!Array.isArray(value)) {\n errors.push(`${label} must be an array.`);\n return undefined;\n }\n if (param.type === \"number\") {\n if (!value.every((item) => typeof item === \"number\" && Number.isFinite(item))) {\n errors.push(`${label} must contain only finite numbers.`);\n return undefined;\n }\n return value.map(String);\n }\n if (!value.every((item) => typeof item === \"string\")) {\n errors.push(`${label} must contain only strings.`);\n return undefined;\n }\n return [...value];\n }\n if (param.type === \"number\") {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n errors.push(`${label} must be a finite number.`);\n return undefined;\n }\n return String(value);\n }\n if (typeof value !== \"string\") {\n errors.push(`${label} must be a string value.`);\n return undefined;\n }\n return value;\n}\n\nexport function defineCommand<const TSchema extends CliParamsSchema, TResult = void>(\n config: CliCommandConfig<TSchema, TResult>\n): CliCommand<TSchema, TResult> {\n return createCommand(config);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cli-command.js","sourceRoot":"","sources":["../../src/cli/cli-command.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from \"path\";\nimport { openCheckpoint, type CheckpointStore } from \"../node/checkpoint.js\";\nimport {\n assertNoDuplicateFlags,\n assertValidEnvironmentFallbacks,\n assertValidMultipleParams,\n assertValidPositionals,\n buildEffectiveSchema,\n commandDescriptor,\n renderHelp,\n resolveParam,\n tokenize,\n type ResolvedParamValue,\n} from \"./cli-parser.js\";\nimport {\n CliHelpRequested,\n CliValidationError,\n type CliCommand,\n type CliCommandConfig,\n type CliContext,\n type CliParams,\n type CliParamsSchema,\n type CliParseResult,\n} from \"./cli-types.js\";\nimport { isCliValidationError, isPipelineExecutionError, toExitCode } from \"./cli-exit.js\";\n\nfunction resolveContext(overrides?: Partial<CliContext>): CliContext {\n return {\n cwd: overrides?.cwd ?? process.cwd(),\n env: overrides?.env ?? process.env,\n log: overrides?.log ?? console,\n reporterOutput: overrides?.reporterOutput,\n pipelineContext: overrides?.pipelineContext,\n signal: overrides?.signal,\n checkpoint: overrides?.checkpoint,\n };\n}\n\ninterface ManagedMainSignal {\n context: CliContext;\n wasInterrupted(): boolean;\n cleanup(): void;\n}\n\nconst SIGINT_EXIT_CODE = 130;\n\n/**\n * Give real CLI entrypoints graceful cancellation without making `run()` or\n * `parse()` mutate process-global signal handlers. Embedded callers can pass\n * their own signal through the context instead.\n */\nfunction manageMainSignal(context: CliContext): ManagedMainSignal {\n if (context.signal) {\n return { context, wasInterrupted: () => false, cleanup: () => {} };\n }\n\n const controller = new AbortController();\n let interrupted = false;\n const onSigint = (): void => {\n interrupted = true;\n context.log.warn(\"SIGINT received; cancelling pipeline work.\");\n controller.abort();\n };\n process.once(\"SIGINT\", onSigint);\n\n return {\n context: { ...context, signal: controller.signal },\n wasInterrupted: () => interrupted,\n cleanup: () => process.removeListener(\"SIGINT\", onSigint),\n };\n}\n\n/**\n * An in-memory-only `CheckpointStore` seeded from `seed`: reads and `record()` behave\n * exactly like a real store for the rest of this run, but `flush()`/`clear()` never touch\n * disk. Every dry-run path hands `run` one of these instead of the real store — the\n * managed-checkpoint contract is that a dry run never writes to the checkpoint file, no\n * matter what `run` does with `context.checkpoint` (`record`/`flush`/`clear`, directly or\n * via `withCheckpointedBatch`).\n */\nfunction inMemoryCheckpointView(seed: ReadonlyMap<string, unknown>): CheckpointStore {\n const entries = new Map(seed);\n return {\n has: (key) => entries.has(key),\n record: (key, meta) => {\n entries.set(key, meta);\n },\n entries: () => entries,\n flush: () => {},\n clear: () => {\n entries.clear();\n },\n };\n}\n\nexport function createCommand<const TSchema extends CliParamsSchema, TResult = void>(\n config: CliCommandConfig<TSchema, TResult>,\n mainExits?: { validation?: number }\n): CliCommand<TSchema, TResult> {\n const effectiveParams = buildEffectiveSchema(config.params, config.checkpoint);\n assertNoDuplicateFlags(effectiveParams);\n assertValidMultipleParams(effectiveParams);\n assertValidEnvironmentFallbacks(effectiveParams);\n const positionals = [...(config.positionals ?? [])];\n assertValidPositionals(positionals, effectiveParams);\n const descriptor = commandDescriptor(config, effectiveParams, positionals);\n\n function resolveValues(\n readValue: (\n key: string,\n param: CliParamsSchema[string]\n ) => string | boolean | string[] | undefined,\n context: CliContext,\n errors: string[],\n helpText: string\n ): CliParseResult<TSchema> {\n const values: Record<string, ResolvedParamValue> = {};\n for (const [key, param] of Object.entries(effectiveParams)) {\n const errorCount = errors.length;\n const raw = readValue(key, param);\n if (errors.length > errorCount) continue;\n const envValue = raw === undefined && param.env ? context.env?.[param.env] : undefined;\n values[key] = resolveParam(\n key,\n param,\n raw ?? envValue,\n context.cwd,\n errors,\n raw !== undefined ? \"argv\" : envValue !== undefined ? \"env\" : \"default\"\n );\n }\n if (errors.length > 0) return { kind: \"error\", errors, helpText };\n // SAFETY: resolveParam populated every effective schema key and all input checks passed.\n const typedValues = values as CliParams<TSchema>;\n const validationErrors = config.validate?.(typedValues, context) ?? [];\n return validationErrors.length > 0\n ? { kind: \"error\", errors: validationErrors, helpText }\n : { kind: \"values\", values: typedValues };\n }\n\n function parseWithContext(argv: readonly string[], context: CliContext): CliParseResult<TSchema> {\n const helpText = renderHelp(\n descriptor.name,\n descriptor.description,\n effectiveParams,\n positionals\n );\n const tokenized = tokenize(argv, effectiveParams, positionals);\n if (tokenized.help) return { kind: \"help\", helpText };\n return resolveValues(\n (key) => tokenized.values.get(key),\n context,\n [...tokenized.errors],\n helpText\n );\n }\n\n function parse(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): CliParseResult<TSchema> {\n return parseWithContext(argv, resolveContext(contextOverrides));\n }\n\n function parseStructuredWithContext(\n structuredValues: Record<string, unknown>,\n context: CliContext\n ): CliParseResult<TSchema> {\n const helpText = renderHelp(\n descriptor.name,\n descriptor.description,\n effectiveParams,\n positionals\n );\n const errors: string[] = [];\n for (const key of Object.keys(structuredValues)) {\n if (!Object.prototype.hasOwnProperty.call(effectiveParams, key)) {\n errors.push(`Unknown parameter: ${key}`);\n }\n }\n return resolveValues(\n (key, param) => normalizeStructuredValue(key, param, structuredValues[key], errors),\n context,\n errors,\n helpText\n );\n }\n\n /**\n * No-op unless `config.checkpoint` is set. Respects a caller-provided `context.checkpoint`\n * override (e.g. a stub in tests) instead of opening the real file. Otherwise opens (or\n * clears, if not resuming) the checkpoint before `run` is called — never on the `--help`/\n * error paths, since those return before this is reached.\n */\n function attachCheckpoint(context: CliContext, values: CliParams<TSchema>): CliContext {\n const checkpointConfig = config.checkpoint;\n if (!checkpointConfig) {\n return context;\n }\n const resolvedPath = path.isAbsolute(checkpointConfig.path)\n ? checkpointConfig.path\n : path.join(context.cwd, checkpointConfig.path);\n // A caller-provided context.checkpoint (e.g. a stub in tests) is used as the\n // underlying store instead of opening the real file, but every rule below — fresh\n // clearing, dry-run wrapping, resume detection/logging — still applies to it; only\n // the \"where does the store come from\" step is skipped.\n const store = context.checkpoint ?? openCheckpoint(resolvedPath);\n const hadExisting = store.entries().size > 0;\n\n if (values.resume) {\n if (hadExisting) {\n context.log.log(\n `Resuming from checkpoint: ${store.entries().size} item(s) already recorded.`\n );\n } else {\n // Without this, --resume against a missing/wrong-path/already-cleared checkpoint\n // silently starts fresh — the exact failure mode that's dangerous for\n // clearOnSuccess: false workflows, where \"fresh\" quietly means \"reprocess\n // everything already done\".\n context.log.warn(\n `--resume was passed, but no checkpoint was found at ${resolvedPath}; starting fresh.`\n );\n }\n // A dry run must never write to the checkpoint file, even while resuming — an\n // in-memory view seeded with the real entries previews it accurately without risk.\n return {\n ...context,\n checkpoint: values.dryRun ? inMemoryCheckpointView(store.entries()) : store,\n };\n }\n\n if (!hadExisting) {\n return {\n ...context,\n checkpoint: values.dryRun ? inMemoryCheckpointView(store.entries()) : store,\n };\n }\n\n if (values.dryRun) {\n // Dry run must not touch the file — neither clearing it nor writing new progress —\n // but the preview should still reflect what a real fresh run would see: an empty\n // \"done\" set, not the stale entries a --resume invocation would use.\n context.log.log(\"Dry run: leaving existing checkpoint untouched (would start fresh).\");\n return { ...context, checkpoint: inMemoryCheckpointView(new Map()) };\n }\n\n store.clear();\n context.log.log(\"Starting fresh — cleared existing checkpoint.\");\n return { ...context, checkpoint: store };\n }\n\n /**\n * No-op unless `config.checkpoint` is set, a store is attached, and the run completed\n * without a dry run or caller cancellation.\n */\n function finalizeCheckpoint(context: CliContext, values: CliParams<TSchema>): void {\n const checkpointConfig = config.checkpoint;\n if (!checkpointConfig || !context.checkpoint || values.dryRun || context.signal?.aborted) {\n return;\n }\n if (checkpointConfig.clearOnSuccess === false) {\n return;\n }\n context.checkpoint.clear();\n }\n\n async function executeValues(values: CliParams<TSchema>, context: CliContext): Promise<TResult> {\n const runContext = attachCheckpoint(context, values);\n const value = await config.run(values, runContext);\n finalizeCheckpoint(runContext, values);\n return value;\n }\n\n function parseValues(\n values: Record<string, unknown>,\n contextOverrides?: Partial<CliContext>\n ): CliParseResult<TSchema> {\n const context = resolveContext(contextOverrides);\n return parseStructuredWithContext(values, context);\n }\n\n async function execute(\n values: CliParams<TSchema>,\n contextOverrides?: Partial<CliContext>\n ): Promise<TResult> {\n return executeValues(values, resolveContext(contextOverrides));\n }\n\n async function run(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): Promise<TResult> {\n const context = resolveContext(contextOverrides);\n const result = parseWithContext(argv, context);\n if (result.kind === \"help\") throw new CliHelpRequested(result.helpText);\n if (result.kind === \"error\") throw new CliValidationError(result.errors, result.helpText);\n return executeValues(result.values, context);\n }\n\n async function main(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): Promise<void> {\n const context = resolveContext(contextOverrides);\n let result: CliParseResult<TSchema>;\n try {\n result = parseWithContext(argv, context);\n } catch (error) {\n context.log.error(error instanceof Error ? (error.stack ?? error.message) : String(error));\n process.exitCode =\n mainExits || isCliValidationError(error) || isPipelineExecutionError(error)\n ? toExitCode(error)\n : 1;\n return;\n }\n if (result.kind === \"help\") {\n context.log.log(result.helpText);\n process.exitCode = 0;\n return;\n }\n if (result.kind === \"error\") {\n for (const error of result.errors) {\n context.log.error(`Error: ${error}`);\n }\n context.log.error(\"\");\n context.log.error(result.helpText);\n process.exitCode = mainExits?.validation ?? 1;\n return;\n }\n const managedSignal = manageMainSignal(context);\n try {\n const runContext = attachCheckpoint(managedSignal.context, result.values);\n await config.run(result.values, runContext);\n if (!managedSignal.wasInterrupted()) {\n finalizeCheckpoint(runContext, result.values);\n }\n } catch (error) {\n context.log.error(error instanceof Error ? (error.stack ?? error.message) : String(error));\n process.exitCode = managedSignal.wasInterrupted()\n ? SIGINT_EXIT_CODE\n : mainExits || isCliValidationError(error) || isPipelineExecutionError(error)\n ? toExitCode(error)\n : 1;\n } finally {\n if (managedSignal.wasInterrupted()) {\n process.exitCode = SIGINT_EXIT_CODE;\n }\n managedSignal.cleanup();\n }\n }\n\n return { descriptor, execute, parse, parseValues, run, main };\n}\n\nfunction normalizeStructuredValue(\n key: string,\n param: CliParamsSchema[string],\n value: unknown,\n errors: string[]\n): string | boolean | string[] | undefined {\n if (value === undefined) return undefined;\n const label = `--${param.flag ?? key}`;\n if (param.type === \"boolean\") {\n if (typeof value === \"boolean\") return value;\n errors.push(`${label} must be a boolean value.`);\n return undefined;\n }\n if ((param.type === \"number\" || param.type === \"string\") && param.multiple === true) {\n if (!Array.isArray(value)) {\n errors.push(`${label} must be an array.`);\n return undefined;\n }\n if (param.type === \"number\") {\n if (!value.every((item) => typeof item === \"number\" && Number.isFinite(item))) {\n errors.push(`${label} must contain only finite numbers.`);\n return undefined;\n }\n return value.map(String);\n }\n if (!value.every((item) => typeof item === \"string\")) {\n errors.push(`${label} must contain only strings.`);\n return undefined;\n }\n return [...value];\n }\n if (param.type === \"number\") {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n errors.push(`${label} must be a finite number.`);\n return undefined;\n }\n return String(value);\n }\n if (typeof value !== \"string\") {\n errors.push(`${label} must be a string value.`);\n return undefined;\n }\n return value;\n}\n\n/** Create a typed command from a declarative parameter schema and run handler. */\nexport function defineCommand<const TSchema extends CliParamsSchema, TResult = void>(\n config: CliCommandConfig<TSchema, TResult>\n): CliCommand<TSchema, TResult> {\n return createCommand(config);\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { type InferredCliParams, type InferredFlagOverrides } from "./cli-schema.js";
|
|
2
|
+
import type { CliBooleanParam, CliCheckpointConfig, CliCommandDescriptor, CliContext, CliNumberParam, CliParams, CliParamsSchema, CliStringParam } from "./cli-types.js";
|
|
3
|
+
import { type Pipeline, type PipelineHooks, type PipelineMermaidOptions, type PipelinePlan, type PipelineRunControls, type StandardSchemaV1 } from "../core/pipeline.js";
|
|
3
4
|
import { type PipelineReporterConfig } from "../reporter/reporter-entry.js";
|
|
4
5
|
export type PipelineCliBuiltins = {
|
|
5
6
|
stepIds: CliStringParam & {
|
|
@@ -9,12 +10,16 @@ export type PipelineCliBuiltins = {
|
|
|
9
10
|
multiple: true;
|
|
10
11
|
};
|
|
11
12
|
continueOnError: CliBooleanParam;
|
|
13
|
+
maxConcurrency: CliNumberParam;
|
|
12
14
|
};
|
|
15
|
+
/** Validated domain parameters plus the built-in pipeline execution controls. */
|
|
13
16
|
export type PipelineCliValues<TSchema extends CliParamsSchema> = CliParams<TSchema> & {
|
|
14
17
|
stepIds: readonly string[];
|
|
15
18
|
targets: readonly string[];
|
|
16
19
|
continueOnError: boolean;
|
|
20
|
+
maxConcurrency: number;
|
|
17
21
|
};
|
|
22
|
+
/** Parse result returned by commands created with `definePipelineCommand`. */
|
|
18
23
|
export type PipelineCliParseResult<TSchema extends CliParamsSchema> = {
|
|
19
24
|
kind: "values";
|
|
20
25
|
values: PipelineCliValues<TSchema>;
|
|
@@ -26,6 +31,7 @@ export type PipelineCliParseResult<TSchema extends CliParamsSchema> = {
|
|
|
26
31
|
errors: readonly string[];
|
|
27
32
|
helpText: string;
|
|
28
33
|
};
|
|
34
|
+
/** Typed CLI facade over a pipeline with planning and graph helpers. */
|
|
29
35
|
export interface PipelineCommand<TSchema extends CliParamsSchema, TResult> {
|
|
30
36
|
readonly descriptor: CliCommandDescriptor;
|
|
31
37
|
/** Stable identity of the wrapped pipeline. */
|
|
@@ -46,20 +52,23 @@ export interface PipelineCommand<TSchema extends CliParamsSchema, TResult> {
|
|
|
46
52
|
run(argv?: readonly string[], context?: Partial<CliContext>): Promise<TResult>;
|
|
47
53
|
main(argv?: readonly string[], context?: Partial<CliContext>): Promise<void>;
|
|
48
54
|
}
|
|
55
|
+
/** Parsed values and CLI services passed to a pipeline hook factory. */
|
|
49
56
|
export interface PipelineCommandHookContext<TSchema extends CliParamsSchema> {
|
|
50
57
|
context: CliContext;
|
|
51
58
|
values: PipelineCliValues<TSchema>;
|
|
52
59
|
}
|
|
53
|
-
|
|
60
|
+
/** One lifecycle hook set or an ordered collection of hook sets. */
|
|
61
|
+
type PipelineCommandHookSets<TResult> = PipelineHooks<TResult> | readonly PipelineHooks<TResult>[];
|
|
62
|
+
/** Static or lazily constructed lifecycle hooks for a pipeline command. */
|
|
54
63
|
export type PipelineCommandHookConfig<TResult, TSchema extends CliParamsSchema> = PipelineCommandHookSets<TResult> | ((input: PipelineCommandHookContext<TSchema>) => PipelineCommandHookSets<TResult> | undefined);
|
|
55
64
|
type PipelineCommandMapOptions<TOptions extends object, TSchema extends CliParamsSchema> = (values: PipelineCliValues<TSchema>, context: CliContext) => TOptions | Promise<TOptions>;
|
|
56
|
-
type DefaultPipelineCommandOptions<TSchema extends CliParamsSchema> = Omit<PipelineCliValues<TSchema>, "continueOnError" | "dryRun" | "resume" | "stepIds" | "targets">;
|
|
65
|
+
type DefaultPipelineCommandOptions<TSchema extends CliParamsSchema> = Omit<PipelineCliValues<TSchema>, "continueOnError" | "maxConcurrency" | "dryRun" | "resume" | "stepIds" | "targets">;
|
|
57
66
|
type CanDefaultPipelineCommandOptions<TOptions extends object, TSchema extends CliParamsSchema> = DefaultPipelineCommandOptions<TSchema> extends TOptions ? Exclude<keyof TSchema, keyof TOptions> extends never ? true : false : false;
|
|
58
67
|
interface DefinePipelineCommandConfigBase<TResult, TSchema extends CliParamsSchema> {
|
|
59
68
|
/** Defaults to pipeline.id. */
|
|
60
69
|
name?: string;
|
|
61
70
|
description?: string;
|
|
62
|
-
/**
|
|
71
|
+
/** Advanced: replace inferred flags for type-only pipelines or custom CLI inputs. */
|
|
63
72
|
params?: TSchema;
|
|
64
73
|
/** Extra parameter keys accepted in positional order. */
|
|
65
74
|
positionals?: readonly (keyof TSchema & string)[];
|
|
@@ -80,6 +89,15 @@ export type DefinePipelineCommandConfig<TOptions extends object, TResult, TSchem
|
|
|
80
89
|
/** Required when parsed flags do not already satisfy the pipeline's domain options. */
|
|
81
90
|
mapOptions: PipelineCommandMapOptions<TOptions, TSchema>;
|
|
82
91
|
});
|
|
83
|
-
/** Turn a
|
|
92
|
+
/** Turn a pipeline into a CLI; infer domain flags from its Standard JSON Schema input. */
|
|
93
|
+
export declare function definePipelineCommand<TOptions extends object, TResult>(pipeline: Pipeline<TOptions, TResult> & (keyof TOptions extends never ? unknown : {
|
|
94
|
+
readonly optionsSchema: StandardSchemaV1;
|
|
95
|
+
}), config?: Omit<DefinePipelineCommandConfigBase<TResult, InferredCliParams<NoInfer<TOptions>>>, "params"> & {
|
|
96
|
+
params?: never;
|
|
97
|
+
mapOptions?: never;
|
|
98
|
+
/** Advanced: customize flag spelling, aliases, help or environment fallbacks. */
|
|
99
|
+
overrides?: InferredFlagOverrides<NoInfer<TOptions>>;
|
|
100
|
+
}): PipelineCommand<InferredCliParams<TOptions>, TResult>;
|
|
101
|
+
/** Advanced: declare CLI inputs explicitly, mapping them only when their shape differs. */
|
|
84
102
|
export declare function definePipelineCommand<TOptions extends object, TResult, const TSchema extends CliParamsSchema = {}>(pipeline: Pipeline<TOptions, TResult>, config: DefinePipelineCommandConfig<NoInfer<TOptions>, TResult, TSchema>): PipelineCommand<TSchema, TResult>;
|
|
85
103
|
export {};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { createCommand } from "./cli-command.js";
|
|
2
2
|
import { flagName } from "./cli-parser.js";
|
|
3
|
-
import {
|
|
3
|
+
import { inferCliParams, } from "./cli-schema.js";
|
|
4
|
+
import { markPipelineCommand } from "../utilities/pipeline-command-marker.js";
|
|
4
5
|
import {} from "../core/pipeline.js";
|
|
5
6
|
import { createPipelineReporter } from "../reporter/reporter-entry.js";
|
|
6
7
|
import { TUBELESS_WORKBENCH_EXIT_CODE } from "./cli-exit.js";
|
|
7
|
-
const PIPELINE_COMMAND_KEYS = new Set(["continueOnError", "stepIds", "targets"]);
|
|
8
|
-
const PIPELINE_COMMAND_FLAGS = new Set(["continue-on-error", "step", "target"]);
|
|
8
|
+
const PIPELINE_COMMAND_KEYS = new Set(["continueOnError", "maxConcurrency", "stepIds", "targets"]);
|
|
9
|
+
const PIPELINE_COMMAND_FLAGS = new Set(["continue-on-error", "max-concurrency", "step", "target"]);
|
|
9
10
|
function assertNoPipelineCommandConflicts(params) {
|
|
10
11
|
for (const [key, param] of Object.entries(params)) {
|
|
11
12
|
if (PIPELINE_COMMAND_KEYS.has(key)) {
|
|
@@ -19,7 +20,7 @@ function assertNoPipelineCommandConflicts(params) {
|
|
|
19
20
|
}
|
|
20
21
|
function normalizePipelineCliValues(values) {
|
|
21
22
|
// SAFETY: `PipelineCliValues<TSchema>` is `CliParams<TSchema>` plus the builtin
|
|
22
|
-
// `stepIds`/`targets`/`continueOnError` keys,
|
|
23
|
+
// `stepIds`/`targets`/`continueOnError`/`maxConcurrency` keys, which `CliParams<PipelineCliBuiltins & TSchema>`
|
|
23
24
|
// already provides, so the runtime shape matches the target type.
|
|
24
25
|
const pipelineValues = values;
|
|
25
26
|
const { continueOnError, stepIds, targets } = pipelineValues;
|
|
@@ -34,6 +35,7 @@ function pipelineRunControlsFromCliValues(values) {
|
|
|
34
35
|
const controls = {
|
|
35
36
|
dryRun: values.dryRun,
|
|
36
37
|
continueOnError: values.continueOnError,
|
|
38
|
+
maxConcurrency: values.maxConcurrency,
|
|
37
39
|
};
|
|
38
40
|
if (values.stepIds.length > 0)
|
|
39
41
|
controls.stepIds = values.stepIds;
|
|
@@ -51,14 +53,19 @@ function isHookConfigFunction(config) {
|
|
|
51
53
|
return typeof config === "function";
|
|
52
54
|
}
|
|
53
55
|
function defaultPipelineCommandOptions(values) {
|
|
54
|
-
const { continueOnError: _continueOnError, dryRun: _dryRun, resume: _resume, stepIds: _stepIds, targets: _targets, ...domainValues } = values;
|
|
56
|
+
const { continueOnError: _continueOnError, maxConcurrency: _maxConcurrency, dryRun: _dryRun, resume: _resume, stepIds: _stepIds, targets: _targets, ...domainValues } = values;
|
|
55
57
|
return domainValues;
|
|
56
58
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
export function definePipelineCommand(pipeline, config = {}) {
|
|
60
|
+
// SAFETY: explicit params retain TSchema; the inferred overload derives its schema
|
|
61
|
+
// from the same pipeline input type. Type-only pipelines have no runtime fields.
|
|
62
|
+
const userParams = (config.params ??
|
|
63
|
+
(pipeline.optionsSchema && !config.mapOptions
|
|
64
|
+
? inferCliParams(pipeline.optionsSchema, config.overrides)
|
|
65
|
+
: {}));
|
|
66
|
+
if (config.overrides && (config.params || config.mapOptions || !pipeline.optionsSchema)) {
|
|
67
|
+
throw new Error("Flag overrides require inferred pipeline flags; use params for an explicit CLI.");
|
|
68
|
+
}
|
|
62
69
|
assertNoPipelineCommandConflicts(userParams);
|
|
63
70
|
const targetFlagEnabled = pipeline.targetIds.length > 0;
|
|
64
71
|
const bridgeParams = {
|
|
@@ -76,6 +83,14 @@ export function definePipelineCommand(pipeline, config) {
|
|
|
76
83
|
group: "execution",
|
|
77
84
|
description: "Continue independent work after a step fails.",
|
|
78
85
|
},
|
|
86
|
+
maxConcurrency: {
|
|
87
|
+
type: "number",
|
|
88
|
+
group: "execution",
|
|
89
|
+
default: 1,
|
|
90
|
+
integer: true,
|
|
91
|
+
min: 1,
|
|
92
|
+
description: "Maximum simultaneous steps in this run.",
|
|
93
|
+
},
|
|
79
94
|
};
|
|
80
95
|
if (targetFlagEnabled) {
|
|
81
96
|
bridgeParams.targets = {
|
|
@@ -119,12 +134,17 @@ export function definePipelineCommand(pipeline, config) {
|
|
|
119
134
|
const controls = pipelineRunControlsFromCliValues({
|
|
120
135
|
dryRun: values.dryRun,
|
|
121
136
|
continueOnError: pipelineValues.continueOnError,
|
|
137
|
+
maxConcurrency: pipelineValues.maxConcurrency,
|
|
122
138
|
stepIds: pipelineValues.stepIds,
|
|
123
139
|
targets: targetFlagEnabled ? pipelineValues.targets : [],
|
|
124
140
|
});
|
|
125
141
|
const reporter = config.reporter === false
|
|
126
142
|
? undefined
|
|
127
|
-
: createPipelineReporter({
|
|
143
|
+
: createPipelineReporter({
|
|
144
|
+
log: cliContext.log,
|
|
145
|
+
...(config.reporter ?? {}),
|
|
146
|
+
...(cliContext.reporterOutput ? { output: cliContext.reporterOutput } : {}),
|
|
147
|
+
});
|
|
128
148
|
const runtimeContext = reporter ? { ...cliContext, log: reporter.log } : cliContext;
|
|
129
149
|
let result;
|
|
130
150
|
try {
|
|
@@ -186,6 +206,6 @@ export function definePipelineCommand(pipeline, config) {
|
|
|
186
206
|
toMermaid: (options) => pipeline.toMermaid(options),
|
|
187
207
|
run: command.run,
|
|
188
208
|
main: command.main,
|
|
189
|
-
});
|
|
209
|
+
}, pipeline);
|
|
190
210
|
}
|
|
191
211
|
//# sourceMappingURL=cli-pipeline-command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-pipeline-command.js","sourceRoot":"","sources":["../../src/cli/cli-pipeline-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCommand } from \"./cli-command.js\";\nimport { flagName } from \"./cli-parser.js\";\nimport type {\n CliBooleanParam,\n CliCheckpointConfig,\n CliCommandConfig,\n CliCommandDescriptor,\n CliContext,\n CliParams,\n CliParamsSchema,\n CliStringParam,\n} from \"./cli-types.js\";\nimport { markPipelineCommand } from \"./pipeline-command-marker.js\";\nimport {\n type Pipeline,\n type PipelineHooks,\n type PipelineMermaidOptions,\n type PipelinePlan,\n type PipelineRunControls,\n} from \"../core/pipeline.js\";\nimport { createPipelineReporter, type PipelineReporterConfig } from \"../reporter/reporter-entry.js\";\nimport { TUBELESS_WORKBENCH_EXIT_CODE } from \"./cli-exit.js\";\n\nexport type PipelineCliBuiltins = {\n stepIds: CliStringParam & { multiple: true };\n targets: CliStringParam & { multiple: true };\n continueOnError: CliBooleanParam;\n};\n\nexport type PipelineCliValues<TSchema extends CliParamsSchema> = CliParams<TSchema> & {\n stepIds: readonly string[];\n targets: readonly string[];\n continueOnError: boolean;\n};\n\nexport type PipelineCliParseResult<TSchema extends CliParamsSchema> =\n | { kind: \"values\"; values: PipelineCliValues<TSchema> }\n | { kind: \"help\"; helpText: string }\n | { kind: \"error\"; errors: readonly string[]; helpText: string };\n\nexport interface PipelineCommand<TSchema extends CliParamsSchema, TResult> {\n readonly descriptor: CliCommandDescriptor;\n /** Stable identity of the wrapped pipeline. */\n readonly id: string;\n /** Stable definition-order step ids for discovery surfaces such as CLI help. */\n readonly stepIds: readonly string[];\n /** Stable declared goal ids that support dependency-aware target execution. */\n readonly targetIds: readonly string[];\n /** Plan without parsing or requiring domain parameters. */\n plan(controls?: PipelineRunControls): PipelinePlan;\n /** Generate a static Mermaid flowchart without running or planning the pipeline. */\n toMermaid(options?: PipelineMermaidOptions): string;\n parse(argv?: readonly string[], context?: Partial<CliContext>): PipelineCliParseResult<TSchema>;\n /** Validate structured form values without tokenizing argv. */\n parseValues(\n values: Record<string, unknown>,\n context?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema>;\n /** Execute already validated form values. */\n execute(values: PipelineCliValues<TSchema>, context?: Partial<CliContext>): Promise<TResult>;\n run(argv?: readonly string[], context?: Partial<CliContext>): Promise<TResult>;\n main(argv?: readonly string[], context?: Partial<CliContext>): Promise<void>;\n}\n\nexport interface PipelineCommandHookContext<TSchema extends CliParamsSchema> {\n context: CliContext;\n values: PipelineCliValues<TSchema>;\n}\n\nexport type PipelineCommandHookSets<TResult> =\n | PipelineHooks<TResult>\n | readonly PipelineHooks<TResult>[];\n\nexport type PipelineCommandHookConfig<TResult, TSchema extends CliParamsSchema> =\n | PipelineCommandHookSets<TResult>\n | ((input: PipelineCommandHookContext<TSchema>) => PipelineCommandHookSets<TResult> | undefined);\n\ntype PipelineCommandMapOptions<TOptions extends object, TSchema extends CliParamsSchema> = (\n values: PipelineCliValues<TSchema>,\n context: CliContext\n) => TOptions | Promise<TOptions>;\n\ntype DefaultPipelineCommandOptions<TSchema extends CliParamsSchema> = Omit<\n PipelineCliValues<TSchema>,\n \"continueOnError\" | \"dryRun\" | \"resume\" | \"stepIds\" | \"targets\"\n>;\n\ntype CanDefaultPipelineCommandOptions<TOptions extends object, TSchema extends CliParamsSchema> =\n DefaultPipelineCommandOptions<TSchema> extends TOptions\n ? Exclude<keyof TSchema, keyof TOptions> extends never\n ? true\n : false\n : false;\n\ninterface DefinePipelineCommandConfigBase<TResult, TSchema extends CliParamsSchema> {\n /** Defaults to pipeline.id. */\n name?: string;\n description?: string;\n /** Extra flags beyond the command and pipeline built-ins. */\n params?: TSchema;\n /** Extra parameter keys accepted in positional order. */\n positionals?: readonly (keyof TSchema & string)[];\n checkpoint?: CliCheckpointConfig;\n /** Additional lifecycle hooks, or a factory resolved from parsed values and CLI context. */\n hooks?: PipelineCommandHookConfig<TResult, TSchema>;\n /** Configure plain/interactive reporting, or disable it. Defaults to automatic mode. */\n reporter?: false | PipelineReporterConfig;\n /** Print domain-specific result lines after a successful run. */\n summarize?(\n result: TResult,\n values: PipelineCliValues<TSchema>,\n context: CliContext\n ): readonly string[] | void;\n validate?(values: PipelineCliValues<TSchema>, context: CliContext): string[] | void;\n}\n\n/** Configuration for a typed pipeline command. Mapping is optional only for compatible flags. */\nexport type DefinePipelineCommandConfig<\n TOptions extends object,\n TResult,\n TSchema extends CliParamsSchema,\n> = DefinePipelineCommandConfigBase<TResult, TSchema> &\n (CanDefaultPipelineCommandOptions<TOptions, TSchema> extends true\n ? {\n /** Override the default same-name flag-to-option mapping. */\n mapOptions?: PipelineCommandMapOptions<TOptions, TSchema>;\n }\n : {\n /** Required when parsed flags do not already satisfy the pipeline's domain options. */\n mapOptions: PipelineCommandMapOptions<TOptions, TSchema>;\n });\n\nconst PIPELINE_COMMAND_KEYS = new Set([\"continueOnError\", \"stepIds\", \"targets\"]);\nconst PIPELINE_COMMAND_FLAGS = new Set([\"continue-on-error\", \"step\", \"target\"]);\n\nfunction assertNoPipelineCommandConflicts(params: CliParamsSchema): void {\n for (const [key, param] of Object.entries(params)) {\n if (PIPELINE_COMMAND_KEYS.has(key)) {\n throw new Error(\n `\"${key}\" is a reserved parameter provided automatically by pipeline commands; remove it from params.`\n );\n }\n const flag = flagName(key, param);\n if (PIPELINE_COMMAND_FLAGS.has(flag)) {\n throw new Error(\n `--${flag} is a reserved flag provided automatically by pipeline commands; remove \"${key}\" from params or give it a different flag name.`\n );\n }\n }\n}\n\nfunction normalizePipelineCliValues<TSchema extends CliParamsSchema>(\n values: CliParams<PipelineCliBuiltins & TSchema>\n): PipelineCliValues<TSchema> {\n // SAFETY: `PipelineCliValues<TSchema>` is `CliParams<TSchema>` plus the builtin\n // `stepIds`/`targets`/`continueOnError` keys, all of which `CliParams<PipelineCliBuiltins & TSchema>`\n // already provides, so the runtime shape matches the target type.\n const pipelineValues = values as PipelineCliValues<TSchema>;\n const { continueOnError, stepIds, targets } = pipelineValues;\n return {\n ...pipelineValues,\n continueOnError,\n stepIds,\n targets: targets ?? [],\n };\n}\n\nfunction pipelineRunControlsFromCliValues(values: {\n continueOnError: boolean;\n dryRun: boolean;\n stepIds: readonly string[];\n targets: readonly string[];\n}): PipelineRunControls {\n const controls: PipelineRunControls = {\n dryRun: values.dryRun,\n continueOnError: values.continueOnError,\n };\n if (values.stepIds.length > 0) controls.stepIds = values.stepIds;\n if (values.targets.length > 0) controls.targets = values.targets;\n return controls;\n}\n\nfunction normalizePipelineHookSets<TResult>(\n hooks: PipelineCommandHookSets<TResult> | undefined\n): PipelineHooks<TResult>[] {\n if (!hooks) return [];\n // SAFETY: a non-array `PipelineCommandHookSets` is always a single `PipelineHooks`.\n return Array.isArray(hooks) ? [...hooks] : [hooks as PipelineHooks<TResult>];\n}\n\nfunction isHookConfigFunction<TResult, TSchema extends CliParamsSchema>(\n config: PipelineCommandHookConfig<TResult, TSchema> | undefined\n): config is (\n input: PipelineCommandHookContext<TSchema>\n) => PipelineCommandHookSets<TResult> | undefined {\n return typeof config === \"function\";\n}\n\nfunction defaultPipelineCommandOptions<TSchema extends CliParamsSchema>(\n values: PipelineCliValues<TSchema>\n): DefaultPipelineCommandOptions<TSchema> {\n const {\n continueOnError: _continueOnError,\n dryRun: _dryRun,\n resume: _resume,\n stepIds: _stepIds,\n targets: _targets,\n ...domainValues\n } = values;\n return domainValues;\n}\n\n/** Turn a typed pipeline into a command with selection, plan, and reporting defaults. */\nexport function definePipelineCommand<\n TOptions extends object,\n TResult,\n const TSchema extends CliParamsSchema = {},\n>(\n pipeline: Pipeline<TOptions, TResult>,\n config: DefinePipelineCommandConfig<NoInfer<TOptions>, TResult, TSchema>\n): PipelineCommand<TSchema, TResult> {\n // SAFETY: `config.params` is declared as `TSchema`; the empty-object fallback is only\n // reached when the caller omits `params`, which is exactly the `{}` schema case.\n const userParams = config.params ?? ({} as TSchema);\n assertNoPipelineCommandConflicts(userParams);\n\n const targetFlagEnabled = pipeline.targetIds.length > 0;\n const bridgeParams: CliParamsSchema = {\n stepIds: {\n type: \"string\",\n multiple: true,\n flag: \"step\",\n group: \"execution\",\n exclusive: true,\n choices: pipeline.stepIds,\n description: `Run exactly this step. Steps: ${pipeline.stepIds.join(\", \")}`,\n },\n continueOnError: {\n type: \"boolean\",\n group: \"execution\",\n description: \"Continue independent work after a step fails.\",\n },\n };\n if (targetFlagEnabled) {\n bridgeParams.targets = {\n type: \"string\",\n multiple: true,\n flag: \"target\",\n group: \"execution\",\n exclusive: true,\n choices: pipeline.targetIds,\n description: `Run this declared target and its prerequisites. Targets: ${pipeline.targetIds.join(\", \")}`,\n };\n }\n\n // SAFETY: `bridgeParams` supplies the `PipelineCliBuiltins` keys and `userParams` is\n // `TSchema`, so the merged object satisfies `PipelineCliBuiltins & TSchema`.\n const params = { ...bridgeParams, ...userParams } as PipelineCliBuiltins & TSchema;\n\n const commandConfig = {\n name: config.name ?? pipeline.id,\n description: config.description,\n params,\n positionals: config.positionals,\n checkpoint: config.checkpoint,\n validate: (values, context) => {\n const pipelineValues = normalizePipelineCliValues<TSchema>(values);\n const errors = config.validate?.(pipelineValues, context) ?? [];\n if (pipelineValues.stepIds.length > 0 && pipelineValues.targets.length > 0) {\n return [\"--step and --target cannot be used together.\", ...errors];\n }\n return errors.length > 0 ? errors : undefined;\n },\n run: async (values, cliContext) => {\n const pipelineValues = normalizePipelineCliValues<TSchema>(values);\n let mapped: TOptions;\n if (config.mapOptions) {\n mapped = await config.mapOptions(pipelineValues, cliContext);\n } else {\n // SAFETY: `defaultPipelineCommandOptions` returns exactly the domain options the\n // `CanDefaultPipelineCommandOptions` constraint guarantees map to `TOptions`.\n mapped = defaultPipelineCommandOptions(pipelineValues) as TOptions;\n }\n const controls = pipelineRunControlsFromCliValues({\n dryRun: values.dryRun,\n continueOnError: pipelineValues.continueOnError,\n stepIds: pipelineValues.stepIds,\n targets: targetFlagEnabled ? pipelineValues.targets : [],\n });\n\n const reporter =\n config.reporter === false\n ? undefined\n : createPipelineReporter<TResult>({ log: cliContext.log, ...(config.reporter ?? {}) });\n const runtimeContext = reporter ? { ...cliContext, log: reporter.log } : cliContext;\n let result: TResult;\n try {\n const configuredHooks = isHookConfigFunction(config.hooks)\n ? config.hooks({ context: runtimeContext, values: pipelineValues })\n : config.hooks;\n const hooks: PipelineHooks<TResult>[] = [\n ...normalizePipelineHookSets(cliContext.pipelineContext?.hooks),\n ...(reporter ? [reporter.hooks] : []),\n ...normalizePipelineHookSets(configuredHooks),\n ];\n\n result = await pipeline.runOrThrow(mapped, controls, {\n ...cliContext.pipelineContext,\n cwd: runtimeContext.cwd,\n log: runtimeContext.log,\n hooks: hooks.length > 0 ? hooks : undefined,\n signal: runtimeContext.signal,\n });\n } finally {\n reporter?.dispose();\n }\n for (const line of config.summarize?.(result, pipelineValues, cliContext) ?? []) {\n cliContext.log.log(line);\n }\n return result;\n },\n } satisfies CliCommandConfig<PipelineCliBuiltins & TSchema, TResult>;\n\n const command = createCommand(commandConfig, {\n validation: TUBELESS_WORKBENCH_EXIT_CODE.validation,\n });\n\n function parse(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema> {\n const result = command.parse(argv, contextOverrides);\n return result.kind === \"values\"\n ? { kind: \"values\", values: normalizePipelineCliValues<TSchema>(result.values) }\n : result;\n }\n\n function plan(controls: PipelineRunControls = {}): PipelinePlan {\n return pipeline.plan(controls);\n }\n\n function parseValues(\n values: Record<string, unknown>,\n contextOverrides?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema> {\n const result = command.parseValues(values, contextOverrides);\n return result.kind === \"values\"\n ? { kind: \"values\", values: normalizePipelineCliValues<TSchema>(result.values) }\n : result;\n }\n\n return markPipelineCommand({\n descriptor: command.descriptor,\n id: pipeline.id,\n stepIds: pipeline.stepIds,\n targetIds: pipeline.targetIds,\n execute: (values, contextOverrides) =>\n // SAFETY: `execute` receives `PipelineCliValues<TSchema>` from the public interface,\n // which is a subtype of `CliParams<PipelineCliBuiltins & TSchema>`.\n command.execute(values as CliParams<PipelineCliBuiltins & TSchema>, contextOverrides),\n parse,\n parseValues,\n plan,\n toMermaid: (options) => pipeline.toMermaid(options),\n run: command.run,\n main: command.main,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cli-pipeline-command.js","sourceRoot":"","sources":["../../src/cli/cli-pipeline-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCommand } from \"./cli-command.js\";\nimport { flagName } from \"./cli-parser.js\";\nimport {\n inferCliParams,\n type InferredCliParams,\n type InferredFlagOverrides,\n} from \"./cli-schema.js\";\nimport type {\n CliBooleanParam,\n CliCheckpointConfig,\n CliCommandConfig,\n CliCommandDescriptor,\n CliContext,\n CliNumberParam,\n CliParams,\n CliParamsSchema,\n CliStringParam,\n} from \"./cli-types.js\";\nimport { markPipelineCommand } from \"../utilities/pipeline-command-marker.js\";\nimport {\n type Pipeline,\n type PipelineHooks,\n type PipelineMermaidOptions,\n type PipelinePlan,\n type PipelineRunControls,\n type StandardSchemaV1,\n} from \"../core/pipeline.js\";\nimport { createPipelineReporter, type PipelineReporterConfig } from \"../reporter/reporter-entry.js\";\nimport { TUBELESS_WORKBENCH_EXIT_CODE } from \"./cli-exit.js\";\n\nexport type PipelineCliBuiltins = {\n stepIds: CliStringParam & { multiple: true };\n targets: CliStringParam & { multiple: true };\n continueOnError: CliBooleanParam;\n maxConcurrency: CliNumberParam;\n};\n\n/** Validated domain parameters plus the built-in pipeline execution controls. */\nexport type PipelineCliValues<TSchema extends CliParamsSchema> = CliParams<TSchema> & {\n stepIds: readonly string[];\n targets: readonly string[];\n continueOnError: boolean;\n maxConcurrency: number;\n};\n\n/** Parse result returned by commands created with `definePipelineCommand`. */\nexport type PipelineCliParseResult<TSchema extends CliParamsSchema> =\n | { kind: \"values\"; values: PipelineCliValues<TSchema> }\n | { kind: \"help\"; helpText: string }\n | { kind: \"error\"; errors: readonly string[]; helpText: string };\n\n/** Typed CLI facade over a pipeline with planning and graph helpers. */\nexport interface PipelineCommand<TSchema extends CliParamsSchema, TResult> {\n readonly descriptor: CliCommandDescriptor;\n /** Stable identity of the wrapped pipeline. */\n readonly id: string;\n /** Stable definition-order step ids for discovery surfaces such as CLI help. */\n readonly stepIds: readonly string[];\n /** Stable declared goal ids that support dependency-aware target execution. */\n readonly targetIds: readonly string[];\n /** Plan without parsing or requiring domain parameters. */\n plan(controls?: PipelineRunControls): PipelinePlan;\n /** Generate a static Mermaid flowchart without running or planning the pipeline. */\n toMermaid(options?: PipelineMermaidOptions): string;\n parse(argv?: readonly string[], context?: Partial<CliContext>): PipelineCliParseResult<TSchema>;\n /** Validate structured form values without tokenizing argv. */\n parseValues(\n values: Record<string, unknown>,\n context?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema>;\n /** Execute already validated form values. */\n execute(values: PipelineCliValues<TSchema>, context?: Partial<CliContext>): Promise<TResult>;\n run(argv?: readonly string[], context?: Partial<CliContext>): Promise<TResult>;\n main(argv?: readonly string[], context?: Partial<CliContext>): Promise<void>;\n}\n\n/** Parsed values and CLI services passed to a pipeline hook factory. */\nexport interface PipelineCommandHookContext<TSchema extends CliParamsSchema> {\n context: CliContext;\n values: PipelineCliValues<TSchema>;\n}\n\n/** One lifecycle hook set or an ordered collection of hook sets. */\ntype PipelineCommandHookSets<TResult> = PipelineHooks<TResult> | readonly PipelineHooks<TResult>[];\n\n/** Static or lazily constructed lifecycle hooks for a pipeline command. */\nexport type PipelineCommandHookConfig<TResult, TSchema extends CliParamsSchema> =\n | PipelineCommandHookSets<TResult>\n | ((input: PipelineCommandHookContext<TSchema>) => PipelineCommandHookSets<TResult> | undefined);\n\ntype PipelineCommandMapOptions<TOptions extends object, TSchema extends CliParamsSchema> = (\n values: PipelineCliValues<TSchema>,\n context: CliContext\n) => TOptions | Promise<TOptions>;\n\ntype DefaultPipelineCommandOptions<TSchema extends CliParamsSchema> = Omit<\n PipelineCliValues<TSchema>,\n \"continueOnError\" | \"maxConcurrency\" | \"dryRun\" | \"resume\" | \"stepIds\" | \"targets\"\n>;\n\ntype CanDefaultPipelineCommandOptions<TOptions extends object, TSchema extends CliParamsSchema> =\n DefaultPipelineCommandOptions<TSchema> extends TOptions\n ? Exclude<keyof TSchema, keyof TOptions> extends never\n ? true\n : false\n : false;\n\ninterface DefinePipelineCommandConfigBase<TResult, TSchema extends CliParamsSchema> {\n /** Defaults to pipeline.id. */\n name?: string;\n description?: string;\n /** Advanced: replace inferred flags for type-only pipelines or custom CLI inputs. */\n params?: TSchema;\n /** Extra parameter keys accepted in positional order. */\n positionals?: readonly (keyof TSchema & string)[];\n checkpoint?: CliCheckpointConfig;\n /** Additional lifecycle hooks, or a factory resolved from parsed values and CLI context. */\n hooks?: PipelineCommandHookConfig<TResult, TSchema>;\n /** Configure plain/interactive reporting, or disable it. Defaults to automatic mode. */\n reporter?: false | PipelineReporterConfig;\n /** Print domain-specific result lines after a successful run. */\n summarize?(\n result: TResult,\n values: PipelineCliValues<TSchema>,\n context: CliContext\n ): readonly string[] | void;\n validate?(values: PipelineCliValues<TSchema>, context: CliContext): string[] | void;\n}\n\n/** Configuration for a typed pipeline command. Mapping is optional only for compatible flags. */\nexport type DefinePipelineCommandConfig<\n TOptions extends object,\n TResult,\n TSchema extends CliParamsSchema,\n> = DefinePipelineCommandConfigBase<TResult, TSchema> &\n (CanDefaultPipelineCommandOptions<TOptions, TSchema> extends true\n ? {\n /** Override the default same-name flag-to-option mapping. */\n mapOptions?: PipelineCommandMapOptions<TOptions, TSchema>;\n }\n : {\n /** Required when parsed flags do not already satisfy the pipeline's domain options. */\n mapOptions: PipelineCommandMapOptions<TOptions, TSchema>;\n });\n\nconst PIPELINE_COMMAND_KEYS = new Set([\"continueOnError\", \"maxConcurrency\", \"stepIds\", \"targets\"]);\nconst PIPELINE_COMMAND_FLAGS = new Set([\"continue-on-error\", \"max-concurrency\", \"step\", \"target\"]);\n\nfunction assertNoPipelineCommandConflicts(params: CliParamsSchema): void {\n for (const [key, param] of Object.entries(params)) {\n if (PIPELINE_COMMAND_KEYS.has(key)) {\n throw new Error(\n `\"${key}\" is a reserved parameter provided automatically by pipeline commands; remove it from params.`\n );\n }\n const flag = flagName(key, param);\n if (PIPELINE_COMMAND_FLAGS.has(flag)) {\n throw new Error(\n `--${flag} is a reserved flag provided automatically by pipeline commands; remove \"${key}\" from params or give it a different flag name.`\n );\n }\n }\n}\n\nfunction normalizePipelineCliValues<TSchema extends CliParamsSchema>(\n values: CliParams<PipelineCliBuiltins & TSchema>\n): PipelineCliValues<TSchema> {\n // SAFETY: `PipelineCliValues<TSchema>` is `CliParams<TSchema>` plus the builtin\n // `stepIds`/`targets`/`continueOnError`/`maxConcurrency` keys, which `CliParams<PipelineCliBuiltins & TSchema>`\n // already provides, so the runtime shape matches the target type.\n const pipelineValues = values as PipelineCliValues<TSchema>;\n const { continueOnError, stepIds, targets } = pipelineValues;\n return {\n ...pipelineValues,\n continueOnError,\n stepIds,\n targets: targets ?? [],\n };\n}\n\nfunction pipelineRunControlsFromCliValues(values: {\n continueOnError: boolean;\n maxConcurrency: number;\n dryRun: boolean;\n stepIds: readonly string[];\n targets: readonly string[];\n}): PipelineRunControls {\n const controls: PipelineRunControls = {\n dryRun: values.dryRun,\n continueOnError: values.continueOnError,\n maxConcurrency: values.maxConcurrency,\n };\n if (values.stepIds.length > 0) controls.stepIds = values.stepIds;\n if (values.targets.length > 0) controls.targets = values.targets;\n return controls;\n}\n\nfunction normalizePipelineHookSets<TResult>(\n hooks: PipelineCommandHookSets<TResult> | undefined\n): PipelineHooks<TResult>[] {\n if (!hooks) return [];\n // SAFETY: a non-array `PipelineCommandHookSets` is always a single `PipelineHooks`.\n return Array.isArray(hooks) ? [...hooks] : [hooks as PipelineHooks<TResult>];\n}\n\nfunction isHookConfigFunction<TResult, TSchema extends CliParamsSchema>(\n config: PipelineCommandHookConfig<TResult, TSchema> | undefined\n): config is (\n input: PipelineCommandHookContext<TSchema>\n) => PipelineCommandHookSets<TResult> | undefined {\n return typeof config === \"function\";\n}\n\nfunction defaultPipelineCommandOptions<TSchema extends CliParamsSchema>(\n values: PipelineCliValues<TSchema>\n): DefaultPipelineCommandOptions<TSchema> {\n const {\n continueOnError: _continueOnError,\n maxConcurrency: _maxConcurrency,\n dryRun: _dryRun,\n resume: _resume,\n stepIds: _stepIds,\n targets: _targets,\n ...domainValues\n } = values;\n return domainValues;\n}\n\n/** Turn a pipeline into a CLI; infer domain flags from its Standard JSON Schema input. */\nexport function definePipelineCommand<TOptions extends object, TResult>(\n pipeline: Pipeline<TOptions, TResult> &\n (keyof TOptions extends never ? unknown : { readonly optionsSchema: StandardSchemaV1 }),\n config?: Omit<\n DefinePipelineCommandConfigBase<TResult, InferredCliParams<NoInfer<TOptions>>>,\n \"params\"\n > & {\n params?: never;\n mapOptions?: never;\n /** Advanced: customize flag spelling, aliases, help or environment fallbacks. */\n overrides?: InferredFlagOverrides<NoInfer<TOptions>>;\n }\n): PipelineCommand<InferredCliParams<TOptions>, TResult>;\n/** Advanced: declare CLI inputs explicitly, mapping them only when their shape differs. */\nexport function definePipelineCommand<\n TOptions extends object,\n TResult,\n const TSchema extends CliParamsSchema = {},\n>(\n pipeline: Pipeline<TOptions, TResult>,\n config: DefinePipelineCommandConfig<NoInfer<TOptions>, TResult, TSchema>\n): PipelineCommand<TSchema, TResult>;\nexport function definePipelineCommand<\n TOptions extends object,\n TResult,\n const TSchema extends CliParamsSchema = {},\n>(\n pipeline: Pipeline<TOptions, TResult>,\n config: DefinePipelineCommandConfigBase<TResult, TSchema> & {\n mapOptions?: PipelineCommandMapOptions<TOptions, TSchema>;\n overrides?: InferredFlagOverrides<TOptions>;\n } = {}\n): PipelineCommand<TSchema, TResult> {\n // SAFETY: explicit params retain TSchema; the inferred overload derives its schema\n // from the same pipeline input type. Type-only pipelines have no runtime fields.\n const userParams = (config.params ??\n (pipeline.optionsSchema && !config.mapOptions\n ? inferCliParams(pipeline.optionsSchema, config.overrides)\n : {})) as TSchema;\n if (config.overrides && (config.params || config.mapOptions || !pipeline.optionsSchema)) {\n throw new Error(\n \"Flag overrides require inferred pipeline flags; use params for an explicit CLI.\"\n );\n }\n assertNoPipelineCommandConflicts(userParams);\n\n const targetFlagEnabled = pipeline.targetIds.length > 0;\n const bridgeParams: CliParamsSchema = {\n stepIds: {\n type: \"string\",\n multiple: true,\n flag: \"step\",\n group: \"execution\",\n exclusive: true,\n choices: pipeline.stepIds,\n description: `Run exactly this step. Steps: ${pipeline.stepIds.join(\", \")}`,\n },\n continueOnError: {\n type: \"boolean\",\n group: \"execution\",\n description: \"Continue independent work after a step fails.\",\n },\n maxConcurrency: {\n type: \"number\",\n group: \"execution\",\n default: 1,\n integer: true,\n min: 1,\n description: \"Maximum simultaneous steps in this run.\",\n },\n };\n if (targetFlagEnabled) {\n bridgeParams.targets = {\n type: \"string\",\n multiple: true,\n flag: \"target\",\n group: \"execution\",\n exclusive: true,\n choices: pipeline.targetIds,\n description: `Run this declared target and its prerequisites. Targets: ${pipeline.targetIds.join(\", \")}`,\n };\n }\n\n // SAFETY: `bridgeParams` supplies the `PipelineCliBuiltins` keys and `userParams` is\n // `TSchema`, so the merged object satisfies `PipelineCliBuiltins & TSchema`.\n const params = { ...bridgeParams, ...userParams } as PipelineCliBuiltins & TSchema;\n\n const commandConfig = {\n name: config.name ?? pipeline.id,\n description: config.description,\n params,\n positionals: config.positionals,\n checkpoint: config.checkpoint,\n validate: (values, context) => {\n const pipelineValues = normalizePipelineCliValues<TSchema>(values);\n const errors = config.validate?.(pipelineValues, context) ?? [];\n if (pipelineValues.stepIds.length > 0 && pipelineValues.targets.length > 0) {\n return [\"--step and --target cannot be used together.\", ...errors];\n }\n return errors.length > 0 ? errors : undefined;\n },\n run: async (values, cliContext) => {\n const pipelineValues = normalizePipelineCliValues<TSchema>(values);\n let mapped: TOptions;\n if (config.mapOptions) {\n mapped = await config.mapOptions(pipelineValues, cliContext);\n } else {\n // SAFETY: `defaultPipelineCommandOptions` returns exactly the domain options the\n // `CanDefaultPipelineCommandOptions` constraint guarantees map to `TOptions`.\n mapped = defaultPipelineCommandOptions(pipelineValues) as TOptions;\n }\n const controls = pipelineRunControlsFromCliValues({\n dryRun: values.dryRun,\n continueOnError: pipelineValues.continueOnError,\n maxConcurrency: pipelineValues.maxConcurrency,\n stepIds: pipelineValues.stepIds,\n targets: targetFlagEnabled ? pipelineValues.targets : [],\n });\n\n const reporter =\n config.reporter === false\n ? undefined\n : createPipelineReporter<TResult>({\n log: cliContext.log,\n ...(config.reporter ?? {}),\n ...(cliContext.reporterOutput ? { output: cliContext.reporterOutput } : {}),\n });\n const runtimeContext = reporter ? { ...cliContext, log: reporter.log } : cliContext;\n let result: TResult;\n try {\n const configuredHooks = isHookConfigFunction(config.hooks)\n ? config.hooks({ context: runtimeContext, values: pipelineValues })\n : config.hooks;\n const hooks: PipelineHooks<TResult>[] = [\n ...normalizePipelineHookSets(cliContext.pipelineContext?.hooks),\n ...(reporter ? [reporter.hooks] : []),\n ...normalizePipelineHookSets(configuredHooks),\n ];\n\n result = await pipeline.runOrThrow(mapped, controls, {\n ...cliContext.pipelineContext,\n cwd: runtimeContext.cwd,\n log: runtimeContext.log,\n hooks: hooks.length > 0 ? hooks : undefined,\n signal: runtimeContext.signal,\n });\n } finally {\n reporter?.dispose();\n }\n for (const line of config.summarize?.(result, pipelineValues, cliContext) ?? []) {\n cliContext.log.log(line);\n }\n return result;\n },\n } satisfies CliCommandConfig<PipelineCliBuiltins & TSchema, TResult>;\n\n const command = createCommand(commandConfig, {\n validation: TUBELESS_WORKBENCH_EXIT_CODE.validation,\n });\n\n function parse(\n argv: readonly string[] = process.argv.slice(2),\n contextOverrides?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema> {\n const result = command.parse(argv, contextOverrides);\n return result.kind === \"values\"\n ? { kind: \"values\", values: normalizePipelineCliValues<TSchema>(result.values) }\n : result;\n }\n\n function plan(controls: PipelineRunControls = {}): PipelinePlan {\n return pipeline.plan(controls);\n }\n\n function parseValues(\n values: Record<string, unknown>,\n contextOverrides?: Partial<CliContext>\n ): PipelineCliParseResult<TSchema> {\n const result = command.parseValues(values, contextOverrides);\n return result.kind === \"values\"\n ? { kind: \"values\", values: normalizePipelineCliValues<TSchema>(result.values) }\n : result;\n }\n\n return markPipelineCommand(\n {\n descriptor: command.descriptor,\n id: pipeline.id,\n stepIds: pipeline.stepIds,\n targetIds: pipeline.targetIds,\n execute: (values, contextOverrides) =>\n // SAFETY: `execute` receives `PipelineCliValues<TSchema>` from the public interface,\n // which is a subtype of `CliParams<PipelineCliBuiltins & TSchema>`.\n command.execute(values as CliParams<PipelineCliBuiltins & TSchema>, contextOverrides),\n parse,\n parseValues,\n plan,\n toMermaid: (options) => pipeline.toMermaid(options),\n run: command.run,\n main: command.main,\n },\n pipeline\n );\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "../core/pipeline.js";
|
|
2
|
+
import type { CliParam, CliParamsSchema } from "./cli-types.js";
|
|
3
|
+
type ScalarParam<T> = [T] extends [string] ? {
|
|
4
|
+
type: "string";
|
|
5
|
+
choices: readonly T[];
|
|
6
|
+
} : [T] extends [number] ? {
|
|
7
|
+
type: "number";
|
|
8
|
+
} : [T] extends [boolean] ? {
|
|
9
|
+
type: "boolean";
|
|
10
|
+
} : never;
|
|
11
|
+
/** Input types describe flag values; the runtime schema supplies their metadata. */
|
|
12
|
+
export type InferredCliParams<TOptions extends object> = {
|
|
13
|
+
[K in keyof TOptions]-?: NonNullable<TOptions[K]> extends readonly (infer TItem)[] ? ScalarParam<TItem> & {
|
|
14
|
+
multiple: true;
|
|
15
|
+
} : ScalarParam<NonNullable<TOptions[K]>> & (undefined extends TOptions[K] ? {
|
|
16
|
+
optional: true;
|
|
17
|
+
} : {});
|
|
18
|
+
};
|
|
19
|
+
type FlagOverride = Pick<CliParam, "description" | "flag" | "short" | "env">;
|
|
20
|
+
export type InferredFlagOverrides<TOptions extends object> = {
|
|
21
|
+
[K in keyof TOptions]?: FlagOverride;
|
|
22
|
+
};
|
|
23
|
+
/** Convert metadata only. Domain validation and transformations still belong to the pipeline. */
|
|
24
|
+
export declare function inferCliParams(optionsSchema: StandardSchemaV1, overrides?: Record<string, FlagOverride | undefined>): CliParamsSchema;
|
|
25
|
+
export {};
|