tubeless 0.2.5 → 0.2.7
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 +3 -3
- package/dist/core/pipeline-steps.d.ts +61 -77
- package/dist/core/pipeline-steps.js +25 -44
- package/dist/core/pipeline-steps.js.map +1 -1
- package/dist/node/atomic-text.js +3 -2
- package/dist/node/atomic-text.js.map +1 -1
- package/dist/node/env.d.ts +1 -0
- package/dist/node/env.js +8 -0
- package/dist/node/env.js.map +1 -0
- package/dist/node/file-utils.d.ts +3 -0
- package/dist/node/file-utils.js +21 -0
- package/dist/node/file-utils.js.map +1 -0
- package/dist/node/node.d.ts +3 -0
- package/dist/node/node.js +3 -0
- package/dist/node/node.js.map +1 -1
- package/dist/node/paths.d.ts +10 -0
- package/dist/node/paths.js +19 -0
- package/dist/node/paths.js.map +1 -0
- package/dist/project/project-compiler.d.ts +19 -0
- package/dist/project/project-compiler.js +94 -0
- package/dist/project/project-compiler.js.map +1 -0
- package/dist/project/project-document.d.ts +47 -0
- package/dist/project/project-document.js +136 -0
- package/dist/project/project-document.js.map +1 -0
- package/dist/project/project.d.ts +2 -0
- package/dist/project/project.js +2 -0
- package/dist/project/project.js.map +1 -1
- package/dist/workbench/workbench-validate.d.ts +2 -0
- package/dist/workbench/workbench-validate.js +76 -0
- package/dist/workbench/workbench-validate.js.map +1 -0
- package/dist/workbench/workbench.js +4 -0
- package/dist/workbench/workbench.js.map +1 -1
- package/docs/README.md +7 -4
- package/docs/agent-guide.md +33 -9
- package/docs/api-reference.md +20 -5
- package/docs/api-report.json +26 -7
- package/docs/child-pipeline-composition.md +24 -19
- package/docs/cli.md +18 -11
- package/docs/concepts.md +13 -11
- package/docs/declarative-pipelines.md +247 -0
- package/docs/getting-started.md +3 -3
- package/docs/llms.txt +4 -0
- package/docs/pipeline-document.schema.json +93 -0
- package/docs/recipes.md +57 -25
- package/docs/remote-step-composition.md +4 -3
- package/examples/best-effort.ts +1 -1
- package/examples/cancellation-and-testing.ts +1 -1
- package/examples/catalog/pipelines/enrich.ts +3 -3
- package/examples/catalog/pipelines/import.ts +2 -2
- package/examples/catalog/pipelines/normalize.ts +1 -1
- package/examples/catalog/pipelines/publish.ts +1 -1
- package/examples/catalog/tubeless.project.ts +23 -0
- package/examples/child-pipeline.ts +4 -4
- package/examples/cli-job.ts +1 -1
- package/examples/conditional-step.ts +2 -2
- package/examples/declarative/handlers.ts +44 -0
- package/examples/declarative/peloton-handlers.ts +231 -0
- package/examples/declarative/peloton.yaml +65 -0
- package/examples/declarative/pipelines.yaml +33 -0
- package/examples/declarative/yaml.d.ts +5 -0
- package/examples/fan-out-progress.ts +3 -3
- package/examples/host-embedding.ts +1 -1
- package/examples/live-tui.ts +1 -1
- package/examples/node-artifacts.ts +28 -0
- package/examples/peloton.ts +9 -6
- package/examples/publish-with-gates.ts +1 -1
- package/examples/remote-steps.ts +2 -2
- package/examples/resumable-enrichment.ts +1 -1
- package/examples/tracing.ts +1 -1
- package/examples/typed-import.ts +1 -1
- package/examples/validated-boundaries.ts +1 -1
- package/examples/yaml-peloton.ts +49 -0
- package/examples/yaml-pipelines.ts +26 -0
- package/package.json +3 -1
- package/skills/tubeless/SKILL.md +22 -4
- package/skills/tubeless-make-pipeline/SKILL.md +5 -4
package/README.md
CHANGED
|
@@ -36,8 +36,8 @@ Tubeless is pre-1.0, so the public API may change between releases.
|
|
|
36
36
|
|
|
37
37
|
## Quick start
|
|
38
38
|
|
|
39
|
-
This pipeline loads
|
|
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
41
|
|
|
42
42
|
```ts
|
|
43
43
|
import { createSteps, definePipeline, requireOutputs } from "tubeless";
|
|
@@ -46,7 +46,7 @@ interface ImportOptions {
|
|
|
46
46
|
lines: readonly string[];
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
const step = createSteps<ImportOptions>();
|
|
49
|
+
const { step } = createSteps<ImportOptions>();
|
|
50
50
|
|
|
51
51
|
const load = step("load", {
|
|
52
52
|
run: (_inputs, context) => context.options.lines,
|
|
@@ -117,67 +117,6 @@ type PlainStepFields<TOptions extends object, TDeps extends readonly AnyStep<TOp
|
|
|
117
117
|
type SchemaStepFields<TOptions extends object, TDeps extends readonly AnyStep<TOptions>[], TOptionalDeps extends readonly AnyStep<TOptions>[], TSchema extends StandardSchemaV1> = Omit<PlainStepFields<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>, "outputSchema"> & {
|
|
118
118
|
outputSchema: TSchema;
|
|
119
119
|
};
|
|
120
|
-
interface StepConstructor<TOptions extends object, TInputOptions extends object = TOptions> {
|
|
121
|
-
/** Ordinary steps never policy-skip, so dependents receive their full output. */
|
|
122
|
-
<TId extends string, TSchema extends StandardSchemaV1, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: SchemaStepFields<TOptions, TDeps, TOptionalDeps, TSchema> & {
|
|
123
|
-
skip?: never;
|
|
124
|
-
}): Step<TId, InferSchemaOutput<TSchema>, TOptions, TInputOptions, InferSchemaInput<TSchema>>;
|
|
125
|
-
<TId extends string, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = [], TOut = unknown>(id: TId, definition: PlainStepFields<TOptions, TDeps, TOptionalDeps, TOut> & {
|
|
126
|
-
skip?: never;
|
|
127
|
-
}): Step<TId, TOut, TOptions, TInputOptions>;
|
|
128
|
-
/** Explicit policy-skip constructor; dependents receive `TOut | undefined`. */
|
|
129
|
-
skippable: SkippableStepConstructor<TOptions, TInputOptions>;
|
|
130
|
-
}
|
|
131
|
-
interface SkippableStepConstructor<TOptions extends object, TInputOptions extends object = TOptions> {
|
|
132
|
-
<TId extends string, TSchema extends StandardSchemaV1, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: SchemaStepFields<TOptions, TDeps, TOptionalDeps, TSchema> & {
|
|
133
|
-
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>> | undefined;
|
|
134
|
-
}): Step<TId, InferSchemaOutput<TSchema> | undefined, TOptions, TInputOptions, InferSchemaInput<TSchema>>;
|
|
135
|
-
<TId extends string, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = [], TOut = unknown>(id: TId, definition: PlainStepFields<TOptions, TDeps, TOptionalDeps, TOut> & {
|
|
136
|
-
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, TOut> | undefined;
|
|
137
|
-
}): Step<TId, TOut | undefined, TOptions, TInputOptions>;
|
|
138
|
-
}
|
|
139
|
-
interface FromPipelineConstructor<TOptions extends object, TInputOptions extends object = TOptions> {
|
|
140
|
-
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: ChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {
|
|
141
|
-
skip?: never;
|
|
142
|
-
mapResult?: undefined;
|
|
143
|
-
}): Step<TId, PipelineResultOf<TChildPipeline>, TOptions, TInputOptions>;
|
|
144
|
-
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TOut, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {
|
|
145
|
-
skip?: never;
|
|
146
|
-
mapResult(value: PipelineResultOf<TChildPipeline>, result: PipelineRun<PipelineResultOf<TChildPipeline>>, context: PipelineStepContext<TOptions>): TOut;
|
|
147
|
-
}): Step<TId, Awaited<TOut>, TOptions, TInputOptions>;
|
|
148
|
-
skippable: SkippableFromPipelineConstructor<TOptions, TInputOptions>;
|
|
149
|
-
}
|
|
150
|
-
interface SkippableFromPipelineConstructor<TOptions extends object, TInputOptions extends object = TOptions> {
|
|
151
|
-
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {
|
|
152
|
-
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, PipelineResultOf<TChildPipeline>> | undefined;
|
|
153
|
-
mapResult?: undefined;
|
|
154
|
-
}): Step<TId, PipelineResultOf<TChildPipeline> | undefined, TOptions, TInputOptions>;
|
|
155
|
-
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TOut, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {
|
|
156
|
-
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, NoInfer<Awaited<TOut>>> | undefined;
|
|
157
|
-
mapResult(value: PipelineResultOf<TChildPipeline>, result: PipelineRun<PipelineResultOf<TChildPipeline>>, context: PipelineStepContext<TOptions>): TOut;
|
|
158
|
-
}): Step<TId, Awaited<TOut> | undefined, TOptions, TInputOptions>;
|
|
159
|
-
}
|
|
160
|
-
interface ForEachPipelineConstructor<TOptions extends object, TInputOptions extends object = TOptions> {
|
|
161
|
-
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TItem, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: MappedChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline, TItem> & {
|
|
162
|
-
skip?: never;
|
|
163
|
-
mapResult?: undefined;
|
|
164
|
-
}): Step<TId, readonly PipelineResultOf<TChildPipeline>[], TOptions, TInputOptions>;
|
|
165
|
-
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TItem, TOut, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: MappedChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline, TItem> & {
|
|
166
|
-
skip?: never;
|
|
167
|
-
mapResult(value: PipelineResultOf<TChildPipeline>, result: PipelineRun<PipelineResultOf<TChildPipeline>>, item: TItem, index: number, context: PipelineStepContext<TOptions>): TOut;
|
|
168
|
-
}): Step<TId, readonly TOut[], TOptions, TInputOptions>;
|
|
169
|
-
skippable: SkippableForEachPipelineConstructor<TOptions, TInputOptions>;
|
|
170
|
-
}
|
|
171
|
-
interface SkippableForEachPipelineConstructor<TOptions extends object, TInputOptions extends object = TOptions> {
|
|
172
|
-
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TItem, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: MappedChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline, TItem> & {
|
|
173
|
-
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, readonly PipelineResultOf<TChildPipeline>[]> | undefined;
|
|
174
|
-
mapResult?: undefined;
|
|
175
|
-
}): Step<TId, readonly PipelineResultOf<TChildPipeline>[] | undefined, TOptions, TInputOptions>;
|
|
176
|
-
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TItem, TOut, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: MappedChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline, TItem> & {
|
|
177
|
-
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, NoInfer<readonly TOut[]>> | undefined;
|
|
178
|
-
mapResult(value: PipelineResultOf<TChildPipeline>, result: PipelineRun<PipelineResultOf<TChildPipeline>>, item: TItem, index: number, context: PipelineStepContext<TOptions>): TOut;
|
|
179
|
-
}): Step<TId, readonly TOut[] | undefined, TOptions, TInputOptions>;
|
|
180
|
-
}
|
|
181
120
|
type RemoteStepDefinitionBase<TParentOptions extends object, TDeps extends readonly AnyStep<TParentOptions>[], TOptionalDeps extends readonly AnyStep<TParentOptions>[], TPayload, TSchema extends StandardSchemaV1> = {
|
|
182
121
|
adapter: RemoteStepAdapter<TParentOptions, TPayload, InferSchemaInput<TSchema>>;
|
|
183
122
|
mapInput(inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>, context: PipelineStepContext<TParentOptions>): TPayload;
|
|
@@ -189,22 +128,7 @@ type RemoteStepDefinitionBase<TParentOptions extends object, TDeps extends reado
|
|
|
189
128
|
description?: string;
|
|
190
129
|
dryRun?: StepDryRunPolicy<TParentOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>;
|
|
191
130
|
};
|
|
192
|
-
|
|
193
|
-
<TId extends string, TSchema extends StandardSchemaV1, TPayload, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: RemoteStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TPayload, TSchema> & {
|
|
194
|
-
skip?: never;
|
|
195
|
-
}): Step<TId, InferSchemaOutput<TSchema>, TOptions, TInputOptions, InferSchemaInput<TSchema>>;
|
|
196
|
-
skippable: SkippableFromRemoteConstructor<TOptions, TInputOptions>;
|
|
197
|
-
}
|
|
198
|
-
interface SkippableFromRemoteConstructor<TOptions extends object, TInputOptions extends object = TOptions> {
|
|
199
|
-
<TId extends string, TSchema extends StandardSchemaV1, TPayload, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: RemoteStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TPayload, TSchema> & {
|
|
200
|
-
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>> | undefined;
|
|
201
|
-
}): Step<TId, InferSchemaOutput<TSchema> | undefined, TOptions, TInputOptions, InferSchemaInput<TSchema>>;
|
|
202
|
-
}
|
|
203
|
-
export interface StepFactory<TOptions extends object, TInputOptions extends object = TOptions> extends StepConstructor<TOptions, TInputOptions> {
|
|
204
|
-
fromPipeline: FromPipelineConstructor<TOptions, TInputOptions>;
|
|
205
|
-
fromRemote: FromRemoteConstructor<TOptions, TInputOptions>;
|
|
206
|
-
forEachPipeline: ForEachPipelineConstructor<TOptions, TInputOptions>;
|
|
207
|
-
}
|
|
131
|
+
export type StepFactory<TOptions extends object, TInputOptions extends object = TOptions> = ReturnType<typeof createStepFactory<TOptions, TInputOptions>>;
|
|
208
132
|
/**
|
|
209
133
|
* Returns a step factory scoped to one pipeline's domain options. Pass built-in
|
|
210
134
|
* run controls as the second argument to `run` / `runOrThrow`. Child
|
|
@@ -212,4 +136,64 @@ export interface StepFactory<TOptions extends object, TInputOptions extends obje
|
|
|
212
136
|
*/
|
|
213
137
|
export declare function createSteps<TOptions extends object = {}>(): StepFactory<TOptions>;
|
|
214
138
|
export declare function createSteps<const TSchema extends StandardSchemaV1<object, object>>(optionsSchema: TSchema): StepFactory<InferSchemaOutput<TSchema>, InferSchemaInput<TSchema>>;
|
|
139
|
+
declare function createStepFactory<TOptions extends object, TInputOptions extends object = TOptions>(optionsSchema?: StandardSchemaV1): {
|
|
140
|
+
step: {
|
|
141
|
+
<TId extends string, TSchema extends StandardSchemaV1, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: SchemaStepFields<TOptions, TDeps, TOptionalDeps, TSchema> & {
|
|
142
|
+
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>> | undefined;
|
|
143
|
+
}): Step<TId, InferSchemaOutput<TSchema> | undefined, TOptions, TInputOptions, InferSchemaInput<TSchema>>;
|
|
144
|
+
<TId extends string, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = [], TOut = unknown>(id: TId, definition: PlainStepFields<TOptions, TDeps, TOptionalDeps, TOut> & {
|
|
145
|
+
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, TOut> | undefined;
|
|
146
|
+
}): Step<TId, TOut | undefined, TOptions, TInputOptions>;
|
|
147
|
+
<TId extends string, TSchema extends StandardSchemaV1, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: SchemaStepFields<TOptions, TDeps, TOptionalDeps, TSchema> & {
|
|
148
|
+
skip?: never;
|
|
149
|
+
}): Step<TId, InferSchemaOutput<TSchema>, TOptions, TInputOptions, InferSchemaInput<TSchema>>;
|
|
150
|
+
<TId extends string, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = [], TOut = unknown>(id: TId, definition: PlainStepFields<TOptions, TDeps, TOptionalDeps, TOut> & {
|
|
151
|
+
skip?: never;
|
|
152
|
+
}): Step<TId, TOut, TOptions, TInputOptions>;
|
|
153
|
+
};
|
|
154
|
+
fromPipeline: {
|
|
155
|
+
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: ChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {
|
|
156
|
+
skip?: never;
|
|
157
|
+
mapResult?: undefined;
|
|
158
|
+
}): Step<TId, PipelineResultOf<TChildPipeline>, TOptions, TInputOptions>;
|
|
159
|
+
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TOut, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {
|
|
160
|
+
skip?: never;
|
|
161
|
+
mapResult(value: PipelineResultOf<TChildPipeline>, result: PipelineRun<PipelineResultOf<TChildPipeline>>, context: PipelineStepContext<TOptions>): TOut;
|
|
162
|
+
}): Step<TId, Awaited<TOut>, TOptions, TInputOptions>;
|
|
163
|
+
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {
|
|
164
|
+
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, PipelineResultOf<TChildPipeline>> | undefined;
|
|
165
|
+
mapResult?: undefined;
|
|
166
|
+
}): Step<TId, PipelineResultOf<TChildPipeline> | undefined, TOptions, TInputOptions>;
|
|
167
|
+
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TOut, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {
|
|
168
|
+
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, NoInfer<Awaited<TOut>>> | undefined;
|
|
169
|
+
mapResult(value: PipelineResultOf<TChildPipeline>, result: PipelineRun<PipelineResultOf<TChildPipeline>>, context: PipelineStepContext<TOptions>): TOut;
|
|
170
|
+
}): Step<TId, Awaited<TOut> | undefined, TOptions, TInputOptions>;
|
|
171
|
+
};
|
|
172
|
+
fromRemote: {
|
|
173
|
+
<TId extends string, TSchema extends StandardSchemaV1, TPayload, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: RemoteStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TPayload, TSchema> & {
|
|
174
|
+
skip?: never;
|
|
175
|
+
}): Step<TId, InferSchemaOutput<TSchema>, TOptions, TInputOptions, InferSchemaInput<TSchema>>;
|
|
176
|
+
<TId extends string, TSchema extends StandardSchemaV1, TPayload, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: RemoteStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TPayload, TSchema> & {
|
|
177
|
+
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>> | undefined;
|
|
178
|
+
}): Step<TId, InferSchemaOutput<TSchema> | undefined, TOptions, TInputOptions, InferSchemaInput<TSchema>>;
|
|
179
|
+
};
|
|
180
|
+
forEachPipeline: {
|
|
181
|
+
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TItem, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: MappedChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline, TItem> & {
|
|
182
|
+
skip?: never;
|
|
183
|
+
mapResult?: undefined;
|
|
184
|
+
}): Step<TId, readonly PipelineResultOf<TChildPipeline>[], TOptions, TInputOptions>;
|
|
185
|
+
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TItem, TOut, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: MappedChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline, TItem> & {
|
|
186
|
+
skip?: never;
|
|
187
|
+
mapResult(value: PipelineResultOf<TChildPipeline>, result: PipelineRun<PipelineResultOf<TChildPipeline>>, item: TItem, index: number, context: PipelineStepContext<TOptions>): TOut;
|
|
188
|
+
}): Step<TId, readonly TOut[], TOptions, TInputOptions>;
|
|
189
|
+
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TItem, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: MappedChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline, TItem> & {
|
|
190
|
+
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, readonly PipelineResultOf<TChildPipeline>[]> | undefined;
|
|
191
|
+
mapResult?: undefined;
|
|
192
|
+
}): Step<TId, readonly PipelineResultOf<TChildPipeline>[] | undefined, TOptions, TInputOptions>;
|
|
193
|
+
<TId extends string, TChildPipeline extends Pipeline<object, unknown>, TItem, TOut, const TDeps extends readonly AnyStep<TOptions>[] = [], const TOptionalDeps extends readonly AnyStep<TOptions>[] = []>(id: TId, definition: MappedChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline, TItem> & {
|
|
194
|
+
skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, NoInfer<readonly TOut[]>> | undefined;
|
|
195
|
+
mapResult(value: PipelineResultOf<TChildPipeline>, result: PipelineRun<PipelineResultOf<TChildPipeline>>, item: TItem, index: number, context: PipelineStepContext<TOptions>): TOut;
|
|
196
|
+
}): Step<TId, readonly TOut[] | undefined, TOptions, TInputOptions>;
|
|
197
|
+
};
|
|
198
|
+
};
|
|
215
199
|
export {};
|
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
import { createMappedChildRunner, createSingleChildRunner
|
|
1
|
+
import { createMappedChildRunner, createSingleChildRunner } from "./child-execution.js";
|
|
2
2
|
import { isPipelineCancellation, PipelineExecutionError } from "./pipeline-execute.js";
|
|
3
3
|
import { STEP_NESTED_PIPELINE, STEP_OPTIONS_SCHEMA, STEP_REMOTE, } from "./pipeline-step-metadata.js";
|
|
4
4
|
export function createSteps(optionsSchema) {
|
|
5
5
|
return createStepFactory(optionsSchema);
|
|
6
6
|
}
|
|
7
7
|
function createStepFactory(optionsSchema) {
|
|
8
|
-
// Runtime construction is deliberately simple; the public factory owns the
|
|
9
|
-
// distinction between ordinary and explicitly skippable constructors.
|
|
10
8
|
const buildStep = (id, definition) => {
|
|
11
|
-
// SAFETY: `definition` carries the step's own fields; spreading it onto the
|
|
12
|
-
// id-bearing shell yields a value whose shape matches `AnyStep<TOptions>`.
|
|
13
9
|
const built = { id, ...definition };
|
|
14
10
|
if (optionsSchema) {
|
|
15
11
|
Object.defineProperty(built, STEP_OPTIONS_SCHEMA, { value: optionsSchema });
|
|
16
12
|
}
|
|
17
13
|
return built;
|
|
18
14
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
function step(id, definition) {
|
|
16
|
+
return buildStep(id, definition);
|
|
17
|
+
}
|
|
18
|
+
const buildPipelineStep = (id, config) => {
|
|
22
19
|
const definition = {
|
|
23
20
|
[STEP_NESTED_PIPELINE]: {
|
|
24
21
|
mode: "single",
|
|
@@ -31,9 +28,6 @@ function createStepFactory(optionsSchema) {
|
|
|
31
28
|
name: config.name,
|
|
32
29
|
description: config.description,
|
|
33
30
|
dryRun: config.dryRun,
|
|
34
|
-
// SAFETY: the config carries `pipeline` and `mapResult`; the runner
|
|
35
|
-
// derives `mapOptions` from the same fields, so the config is a valid
|
|
36
|
-
// single-child execution config at runtime.
|
|
37
31
|
run: createSingleChildRunner(config, {
|
|
38
32
|
createExecutionError: (result, message) => new PipelineExecutionError(result, message),
|
|
39
33
|
isCancellation: (error, childContext) => isPipelineCancellation(error, childContext),
|
|
@@ -41,14 +35,14 @@ function createStepFactory(optionsSchema) {
|
|
|
41
35
|
};
|
|
42
36
|
const skip = config.skip;
|
|
43
37
|
if (skip !== undefined) {
|
|
44
|
-
|
|
45
|
-
definition.skip = (inputs, context) => skip(inputs, context);
|
|
38
|
+
definition.skip = skip;
|
|
46
39
|
}
|
|
47
40
|
return buildStep(id, definition);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
};
|
|
42
|
+
function fromPipeline(id, definition) {
|
|
43
|
+
return buildPipelineStep(id, definition);
|
|
44
|
+
}
|
|
45
|
+
const buildRemoteStep = (id, config) => {
|
|
52
46
|
const remote = { engine: config.adapter.engine };
|
|
53
47
|
if (config.adapter.target !== undefined)
|
|
54
48
|
remote.target = config.adapter.target;
|
|
@@ -65,14 +59,14 @@ function createStepFactory(optionsSchema) {
|
|
|
65
59
|
};
|
|
66
60
|
const skip = config.skip;
|
|
67
61
|
if (skip !== undefined) {
|
|
68
|
-
|
|
69
|
-
definition.skip = (inputs, context) => skip(inputs, context);
|
|
62
|
+
definition.skip = skip;
|
|
70
63
|
}
|
|
71
64
|
return buildStep(id, definition);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
65
|
+
};
|
|
66
|
+
function fromRemote(id, definition) {
|
|
67
|
+
return buildRemoteStep(id, definition);
|
|
68
|
+
}
|
|
69
|
+
const buildMappedPipelineStep = (id, config) => {
|
|
76
70
|
const definition = {
|
|
77
71
|
[STEP_NESTED_PIPELINE]: {
|
|
78
72
|
mode: "for-each",
|
|
@@ -85,9 +79,6 @@ function createStepFactory(optionsSchema) {
|
|
|
85
79
|
name: config.name,
|
|
86
80
|
description: config.description,
|
|
87
81
|
dryRun: config.dryRun,
|
|
88
|
-
// SAFETY: the config carries `pipeline`, `items`, `key`, and `mapResult`;
|
|
89
|
-
// the runner derives the rest from those fields, so the config is a valid
|
|
90
|
-
// mapped-child execution config at runtime.
|
|
91
82
|
run: createMappedChildRunner(config, {
|
|
92
83
|
createExecutionError: (result, message) => new PipelineExecutionError(result, message),
|
|
93
84
|
isCancellation: (error, childContext) => isPipelineCancellation(error, childContext),
|
|
@@ -95,29 +86,19 @@ function createStepFactory(optionsSchema) {
|
|
|
95
86
|
};
|
|
96
87
|
const skip = config.skip;
|
|
97
88
|
if (skip !== undefined) {
|
|
98
|
-
|
|
99
|
-
definition.skip = (inputs, context) => skip(inputs, context);
|
|
89
|
+
definition.skip = skip;
|
|
100
90
|
}
|
|
101
91
|
return buildStep(id, definition);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const factory =
|
|
107
|
-
|
|
92
|
+
};
|
|
93
|
+
function forEachPipeline(id, definition) {
|
|
94
|
+
return buildMappedPipelineStep(id, definition);
|
|
95
|
+
}
|
|
96
|
+
const factory = {
|
|
97
|
+
step,
|
|
108
98
|
fromPipeline,
|
|
109
99
|
fromRemote,
|
|
110
100
|
forEachPipeline,
|
|
111
|
-
}
|
|
112
|
-
// SAFETY: `fromPipeline` is the same callable as `factory.fromPipeline`; it
|
|
113
|
-
// carries the skippable variant, so the assignment is sound.
|
|
114
|
-
factory.fromPipeline.skippable = fromPipeline;
|
|
115
|
-
// SAFETY: `fromRemote` is the same callable as `factory.fromRemote`; it
|
|
116
|
-
// carries the skippable variant, so the assignment is sound.
|
|
117
|
-
factory.fromRemote.skippable = fromRemote;
|
|
118
|
-
// SAFETY: `forEachPipeline` is the same callable as `factory.forEachPipeline`;
|
|
119
|
-
// it carries the skippable variant, so the assignment is sound.
|
|
120
|
-
factory.forEachPipeline.skippable = forEachPipeline;
|
|
101
|
+
};
|
|
121
102
|
return factory;
|
|
122
103
|
}
|
|
123
104
|
//# sourceMappingURL=pipeline-steps.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline-steps.js","sourceRoot":"","sources":["../../src/core/pipeline-steps.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createMappedChildRunner,\n createSingleChildRunner,\n type MappedChildExecutionConfig,\n type SingleChildExecutionConfig,\n} from \"./child-execution.js\";\nimport type { ToMappedChildStepProgressOptions } from \"./mapped-child-progress.js\";\nimport { isPipelineCancellation, PipelineExecutionError } from \"./pipeline-execute.js\";\nimport {\n STEP_NESTED_PIPELINE,\n STEP_OPTIONS_SCHEMA,\n STEP_REMOTE,\n} from \"./pipeline-step-metadata.js\";\nimport type {\n InferSchemaInput,\n InferSchemaOutput,\n Pipeline,\n PipelineExecutionContext,\n PipelinePlanStep,\n PipelineRun,\n PipelineRunOptions,\n PipelineStepContext,\n RemoteStepAdapter,\n StandardSchemaV1,\n StepSkipDecision,\n} from \"./pipeline-types.js\";\n\n/**\n * A step's dependencies are references to the dependency's own step object, not string ids\n * into a hand-maintained output-type map. This buys two things no amount of extra generics\n * on a string-keyed design could:\n * - a step used before its dependency exists is a compile error (JS temporal dead zone on\n * `const`), so out-of-order and self/cyclic dependencies are caught by the language, not\n * a bespoke runtime check\n * - each step only ever states its own id/deps; the output-type map is derived, never\n * restated, and callers of `definePipeline`/`createSteps` never write out its generics\n */\ntype AnyStepDryRunHandler<TOptions extends object> = {\n bivarianceHack(\n inputs: Record<string, unknown>,\n context: PipelineStepContext<TOptions>\n ): unknown | Promise<unknown>;\n}[\"bivarianceHack\"];\n\nexport interface AnyStep<TOptions extends object = object> {\n readonly [STEP_NESTED_PIPELINE]?: NonNullable<PipelinePlanStep[\"nestedPipeline\"]>;\n readonly [STEP_REMOTE]?: NonNullable<PipelinePlanStep[\"remote\"]>;\n readonly [STEP_OPTIONS_SCHEMA]?: StandardSchemaV1;\n readonly id: string;\n readonly dependsOn?: readonly AnyStep<TOptions>[];\n readonly optionalDependsOn?: readonly AnyStep<TOptions>[];\n readonly skipAfterFailureOf?: readonly AnyStep<TOptions>[];\n /** Optional human-facing display name. Stable machine identity remains `id`. */\n readonly name?: string;\n readonly description?: string;\n /**\n * Dry-run policy. Omitted runs the normal handler, `\"skip\"` structurally\n * skips it, and a handler substitutes for `run` while preserving its output.\n */\n readonly dryRun?: \"skip\" | AnyStepDryRunHandler<TOptions>;\n /** Optional Standard Schema for values published by this step. */\n readonly outputSchema?: StandardSchemaV1;\n /**\n * Optional runtime skip. Return a non-empty reason (or `{ reason, value }`) to\n * skip without calling `run`. Policy skips unlock dependents; structural skips\n * (dry-run, filtered, …) do not use this hook.\n */\n skip?(\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<TOptions>\n ): StepSkipDecision | Promise<StepSkipDecision>;\n run(inputs: Record<string, unknown>, context: PipelineStepContext<TOptions>): unknown;\n}\n\n/** The step fields that `buildStep` merges onto the id-bearing shell. */\ntype StepDefinitionBody<TOptions extends object> = Omit<AnyStep<TOptions>, \"id\">;\n\nexport interface Step<\n TId extends string,\n TOut,\n TOptions extends object,\n TInputOptions extends object = TOptions,\n TRunOut = TOut,\n> extends AnyStep<TOptions> {\n readonly id: TId;\n run(\n inputs: Record<string, unknown>,\n context: PipelineStepContext<TOptions>\n ): TRunOut | Promise<TRunOut>;\n /** Type-only: carries this step's output type for sibling inference. Never set at runtime. */\n readonly __outputType?: TOut;\n /** Type-only: carries pre-validation run options for pipeline call-site inference. */\n readonly __inputOptionsType?: TInputOptions;\n}\n\n/**\n * Extract a step's output type for dependency typing.\n * Prefer matching `Step<…, TOut, …>` over `{ __outputType?: infer T }`: optional-property\n * inference collapses `TOut | undefined` to `TOut`, which hides policy-skip widening.\n */\nexport type StepOutput<S> =\n S extends Step<string, infer TOut, infer _TOptions, infer _TInputOptions, infer _TRunOut>\n ? TOut\n : never;\n\ninterface StepToken {\n readonly id: string;\n readonly __outputType?: unknown;\n}\n\ntype RequiredInputs<TDeps extends readonly StepToken[]> = {\n [S in TDeps[number] as S[\"id\"]]: StepOutput<S>;\n};\n\ntype OptionalInputs<TDeps extends readonly StepToken[]> = {\n [S in TDeps[number] as S[\"id\"]]?: StepOutput<S>;\n};\n\ntype PipelineResultOf<TPipeline> =\n TPipeline extends Pipeline<object, infer TResult, infer _TStepId, infer _TTargetId>\n ? TResult\n : never;\n\ntype PipelineRunOptionsOf<TPipeline> =\n TPipeline extends Pipeline<infer TOptions, unknown, infer TStepId, infer TTargetId>\n ? PipelineRunOptions<TOptions, TStepId, TTargetId>\n : never;\n\ntype ChildPipelineStepDefinitionBase<\n TParentOptions extends object,\n TDeps extends readonly AnyStep<TParentOptions>[],\n TOptionalDeps extends readonly AnyStep<TParentOptions>[],\n TChildPipeline extends Pipeline<object, unknown>,\n> = {\n pipeline: TChildPipeline;\n dependsOn?: TDeps;\n optionalDependsOn?: TOptionalDeps;\n skipAfterFailureOf?: readonly AnyStep<TParentOptions>[];\n name?: string;\n description?: string;\n dryRun?: \"skip\";\n mapOptions(\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TParentOptions>\n ): PipelineRunOptionsOf<TChildPipeline>;\n};\n\n/** Child step without policy skip (dependents see the full child result type). */\ntype ChildPipelineStepDefinition<\n TParentOptions extends object,\n TDeps extends readonly AnyStep<TParentOptions>[],\n TOptionalDeps extends readonly AnyStep<TParentOptions>[],\n TChildPipeline extends Pipeline<object, unknown>,\n> = ChildPipelineStepDefinitionBase<TParentOptions, TDeps, TOptionalDeps, TChildPipeline>;\n\n/**\n * Presentation options for opaque `forEachPipeline` progress.\n * Defaults are domain-neutral (`N/M items · K running · key/step`).\n * Override `formatMessage` when a domain wants its own noun (images, shards, …).\n */\nexport type MappedChildProgressOptions = ToMappedChildStepProgressOptions;\n\ntype MappedChildPipelineStepDefinition<\n TParentOptions extends object,\n TDeps extends readonly AnyStep<TParentOptions>[],\n TOptionalDeps extends readonly AnyStep<TParentOptions>[],\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n> = {\n pipeline: TChildPipeline;\n dependsOn?: TDeps;\n optionalDependsOn?: TOptionalDeps;\n skipAfterFailureOf?: readonly AnyStep<TParentOptions>[];\n name?: string;\n description?: string;\n dryRun?: \"skip\";\n items(\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TParentOptions>\n ): readonly TItem[] | Promise<readonly TItem[]>;\n key(item: TItem, index: number): string;\n concurrency?:\n | number\n | ((\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TParentOptions>\n ) => number);\n /**\n * How the opaque parent step reports live fan-out progress.\n * Purely presentational — does not change scheduling or results.\n */\n progress?: MappedChildProgressOptions;\n mapOptions(\n item: TItem,\n index: number,\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TParentOptions>\n ): PipelineRunOptionsOf<TChildPipeline>;\n};\n\ntype StepSkipPredicate<\n TOptions extends object,\n TDeps extends readonly AnyStep<TOptions>[],\n TOptionalDeps extends readonly AnyStep<TOptions>[],\n TOut,\n> = (\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TOptions>\n) => StepSkipDecision<TOut> | Promise<StepSkipDecision<TOut>>;\n\ntype StepDryRunPolicy<\n TOptions extends object,\n TDeps extends readonly AnyStep<TOptions>[],\n TOptionalDeps extends readonly AnyStep<TOptions>[],\n TOut,\n> =\n | \"skip\"\n | ((\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineStepContext<TOptions>\n ) => TOut | Promise<TOut>);\n\ntype PlainStepFields<\n TOptions extends object,\n TDeps extends readonly AnyStep<TOptions>[],\n TOptionalDeps extends readonly AnyStep<TOptions>[],\n TOut,\n> = {\n dependsOn?: TDeps;\n optionalDependsOn?: TOptionalDeps;\n skipAfterFailureOf?: readonly AnyStep<TOptions>[];\n name?: string;\n description?: string;\n dryRun?: StepDryRunPolicy<TOptions, TDeps, TOptionalDeps, TOut>;\n outputSchema?: never;\n run(\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineStepContext<TOptions>\n ): TOut | Promise<TOut>;\n};\n\ntype SchemaStepFields<\n TOptions extends object,\n TDeps extends readonly AnyStep<TOptions>[],\n TOptionalDeps extends readonly AnyStep<TOptions>[],\n TSchema extends StandardSchemaV1,\n> = Omit<\n PlainStepFields<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>,\n \"outputSchema\"\n> & {\n outputSchema: TSchema;\n};\n\ninterface StepConstructor<TOptions extends object, TInputOptions extends object = TOptions> {\n /** Ordinary steps never policy-skip, so dependents receive their full output. */\n <\n TId extends string,\n TSchema extends StandardSchemaV1,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: SchemaStepFields<TOptions, TDeps, TOptionalDeps, TSchema> & { skip?: never }\n ): Step<TId, InferSchemaOutput<TSchema>, TOptions, TInputOptions, InferSchemaInput<TSchema>>;\n\n <\n TId extends string,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n TOut = unknown,\n >(\n id: TId,\n definition: PlainStepFields<TOptions, TDeps, TOptionalDeps, TOut> & { skip?: never }\n ): Step<TId, TOut, TOptions, TInputOptions>;\n\n /** Explicit policy-skip constructor; dependents receive `TOut | undefined`. */\n skippable: SkippableStepConstructor<TOptions, TInputOptions>;\n}\n\ninterface SkippableStepConstructor<\n TOptions extends object,\n TInputOptions extends object = TOptions,\n> {\n <\n TId extends string,\n TSchema extends StandardSchemaV1,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: SchemaStepFields<TOptions, TDeps, TOptionalDeps, TSchema> & {\n skip:\n | StepSkipPredicate<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>\n | undefined;\n }\n ): Step<\n TId,\n InferSchemaOutput<TSchema> | undefined,\n TOptions,\n TInputOptions,\n InferSchemaInput<TSchema>\n >;\n\n <\n TId extends string,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n TOut = unknown,\n >(\n id: TId,\n definition: PlainStepFields<TOptions, TDeps, TOptionalDeps, TOut> & {\n skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, TOut> | undefined;\n }\n ): Step<TId, TOut | undefined, TOptions, TInputOptions>;\n}\n\ninterface FromPipelineConstructor<\n TOptions extends object,\n TInputOptions extends object = TOptions,\n> {\n <\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: ChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {\n skip?: never;\n mapResult?: undefined;\n }\n ): Step<TId, PipelineResultOf<TChildPipeline>, TOptions, TInputOptions>;\n\n <\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TOut,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {\n skip?: never;\n mapResult(\n value: PipelineResultOf<TChildPipeline>,\n result: PipelineRun<PipelineResultOf<TChildPipeline>>,\n context: PipelineStepContext<TOptions>\n ): TOut;\n }\n ): Step<TId, Awaited<TOut>, TOptions, TInputOptions>;\n\n skippable: SkippableFromPipelineConstructor<TOptions, TInputOptions>;\n}\n\ninterface SkippableFromPipelineConstructor<\n TOptions extends object,\n TInputOptions extends object = TOptions,\n> {\n <\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {\n skip:\n | StepSkipPredicate<TOptions, TDeps, TOptionalDeps, PipelineResultOf<TChildPipeline>>\n | undefined;\n mapResult?: undefined;\n }\n ): Step<TId, PipelineResultOf<TChildPipeline> | undefined, TOptions, TInputOptions>;\n\n <\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TOut,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {\n skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, NoInfer<Awaited<TOut>>> | undefined;\n mapResult(\n value: PipelineResultOf<TChildPipeline>,\n result: PipelineRun<PipelineResultOf<TChildPipeline>>,\n context: PipelineStepContext<TOptions>\n ): TOut;\n }\n ): Step<TId, Awaited<TOut> | undefined, TOptions, TInputOptions>;\n}\n\ninterface ForEachPipelineConstructor<\n TOptions extends object,\n TInputOptions extends object = TOptions,\n> {\n <\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: MappedChildPipelineStepDefinition<\n TOptions,\n TDeps,\n TOptionalDeps,\n TChildPipeline,\n TItem\n > & {\n skip?: never;\n mapResult?: undefined;\n }\n ): Step<TId, readonly PipelineResultOf<TChildPipeline>[], TOptions, TInputOptions>;\n\n <\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n TOut,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: MappedChildPipelineStepDefinition<\n TOptions,\n TDeps,\n TOptionalDeps,\n TChildPipeline,\n TItem\n > & {\n skip?: never;\n mapResult(\n value: PipelineResultOf<TChildPipeline>,\n result: PipelineRun<PipelineResultOf<TChildPipeline>>,\n item: TItem,\n index: number,\n context: PipelineStepContext<TOptions>\n ): TOut;\n }\n ): Step<TId, readonly TOut[], TOptions, TInputOptions>;\n\n skippable: SkippableForEachPipelineConstructor<TOptions, TInputOptions>;\n}\n\ninterface SkippableForEachPipelineConstructor<\n TOptions extends object,\n TInputOptions extends object = TOptions,\n> {\n <\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: MappedChildPipelineStepDefinition<\n TOptions,\n TDeps,\n TOptionalDeps,\n TChildPipeline,\n TItem\n > & {\n skip:\n | StepSkipPredicate<\n TOptions,\n TDeps,\n TOptionalDeps,\n readonly PipelineResultOf<TChildPipeline>[]\n >\n | undefined;\n mapResult?: undefined;\n }\n ): Step<TId, readonly PipelineResultOf<TChildPipeline>[] | undefined, TOptions, TInputOptions>;\n\n <\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n TOut,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: MappedChildPipelineStepDefinition<\n TOptions,\n TDeps,\n TOptionalDeps,\n TChildPipeline,\n TItem\n > & {\n skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, NoInfer<readonly TOut[]>> | undefined;\n mapResult(\n value: PipelineResultOf<TChildPipeline>,\n result: PipelineRun<PipelineResultOf<TChildPipeline>>,\n item: TItem,\n index: number,\n context: PipelineStepContext<TOptions>\n ): TOut;\n }\n ): Step<TId, readonly TOut[] | undefined, TOptions, TInputOptions>;\n}\n\ntype RemoteStepDefinitionBase<\n TParentOptions extends object,\n TDeps extends readonly AnyStep<TParentOptions>[],\n TOptionalDeps extends readonly AnyStep<TParentOptions>[],\n TPayload,\n TSchema extends StandardSchemaV1,\n> = {\n adapter: RemoteStepAdapter<TParentOptions, TPayload, InferSchemaInput<TSchema>>;\n mapInput(\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineStepContext<TParentOptions>\n ): TPayload;\n outputSchema: TSchema;\n dependsOn?: TDeps;\n optionalDependsOn?: TOptionalDeps;\n skipAfterFailureOf?: readonly AnyStep<TParentOptions>[];\n name?: string;\n description?: string;\n dryRun?: StepDryRunPolicy<TParentOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>;\n};\n\ninterface FromRemoteConstructor<TOptions extends object, TInputOptions extends object = TOptions> {\n <\n TId extends string,\n TSchema extends StandardSchemaV1,\n TPayload,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: RemoteStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TPayload, TSchema> & {\n skip?: never;\n }\n ): Step<TId, InferSchemaOutput<TSchema>, TOptions, TInputOptions, InferSchemaInput<TSchema>>;\n\n skippable: SkippableFromRemoteConstructor<TOptions, TInputOptions>;\n}\n\ninterface SkippableFromRemoteConstructor<\n TOptions extends object,\n TInputOptions extends object = TOptions,\n> {\n <\n TId extends string,\n TSchema extends StandardSchemaV1,\n TPayload,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: RemoteStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TPayload, TSchema> & {\n skip:\n | StepSkipPredicate<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>\n | undefined;\n }\n ): Step<\n TId,\n InferSchemaOutput<TSchema> | undefined,\n TOptions,\n TInputOptions,\n InferSchemaInput<TSchema>\n >;\n}\n\nexport interface StepFactory<\n TOptions extends object,\n TInputOptions extends object = TOptions,\n> extends StepConstructor<TOptions, TInputOptions> {\n fromPipeline: FromPipelineConstructor<TOptions, TInputOptions>;\n fromRemote: FromRemoteConstructor<TOptions, TInputOptions>;\n forEachPipeline: ForEachPipelineConstructor<TOptions, TInputOptions>;\n}\n\n/**\n * Returns a step factory scoped to one pipeline's domain options. Pass built-in\n * run controls as the second argument to `run` / `runOrThrow`. Child\n * `mapOptions` may still return domain options plus those controls.\n */\nexport function createSteps<TOptions extends object = {}>(): StepFactory<TOptions>;\nexport function createSteps<const TSchema extends StandardSchemaV1<object, object>>(\n optionsSchema: TSchema\n): StepFactory<InferSchemaOutput<TSchema>, InferSchemaInput<TSchema>>;\nexport function createSteps(optionsSchema?: StandardSchemaV1<object, object>): StepFactory<object> {\n return createStepFactory<object>(optionsSchema);\n}\n\nfunction createStepFactory<TOptions extends object, TInputOptions extends object = TOptions>(\n optionsSchema?: StandardSchemaV1\n): StepFactory<TOptions, TInputOptions> {\n // Runtime construction is deliberately simple; the public factory owns the\n // distinction between ordinary and explicitly skippable constructors.\n const buildStep = (id: string, definition: StepDefinitionBody<TOptions>): AnyStep<TOptions> => {\n // SAFETY: `definition` carries the step's own fields; spreading it onto the\n // id-bearing shell yields a value whose shape matches `AnyStep<TOptions>`.\n const built = { id, ...definition } as AnyStep<TOptions>;\n if (optionsSchema) {\n Object.defineProperty(built, STEP_OPTIONS_SCHEMA, { value: optionsSchema });\n }\n return built;\n };\n\n // SAFETY: the closure's parameter and return shapes match the\n // `fromPipeline` constructor signature it is assigned to.\n const fromPipeline = ((\n id: string,\n config: ChildPipelineStepDefinitionBase<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n Pipeline<object, unknown>\n > & {\n skip?: StepSkipPredicate<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n unknown\n >;\n mapResult?: (\n value: unknown,\n result: PipelineRun<unknown>,\n context: PipelineStepContext<TOptions>\n ) => unknown;\n }\n ) => {\n const definition: StepDefinitionBody<TOptions> = {\n [STEP_NESTED_PIPELINE]: {\n mode: \"single\" as const,\n pipelineId: config.pipeline.id,\n stepIds: config.pipeline.stepIds,\n },\n dependsOn: config.dependsOn,\n optionalDependsOn: config.optionalDependsOn,\n skipAfterFailureOf: config.skipAfterFailureOf,\n name: config.name,\n description: config.description,\n dryRun: config.dryRun,\n // SAFETY: the config carries `pipeline` and `mapResult`; the runner\n // derives `mapOptions` from the same fields, so the config is a valid\n // single-child execution config at runtime.\n run: createSingleChildRunner(config as SingleChildExecutionConfig<TOptions>, {\n createExecutionError: (result, message) => new PipelineExecutionError(result, message),\n isCancellation: (error, childContext) => isPipelineCancellation(error, childContext),\n }),\n };\n\n const skip = config.skip;\n if (skip !== undefined) {\n // SAFETY: each constructor preserves the skip predicate's dependency inputs and context.\n definition.skip = (inputs, context) => skip(inputs as never, context);\n }\n return buildStep(id, definition);\n }) as StepFactory<TOptions, TInputOptions>[\"fromPipeline\"];\n\n // SAFETY: the closure's parameter and return shapes match the\n // `fromRemote` constructor signature it is assigned to.\n const fromRemote = ((\n id: string,\n config: {\n adapter: RemoteStepAdapter<object, unknown, unknown>;\n mapInput: (\n inputs: Record<string, unknown>,\n context: PipelineStepContext<TOptions>\n ) => unknown;\n outputSchema: StandardSchemaV1;\n dependsOn?: readonly AnyStep<TOptions>[];\n optionalDependsOn?: readonly AnyStep<TOptions>[];\n skipAfterFailureOf?: readonly AnyStep<TOptions>[];\n name?: string;\n description?: string;\n dryRun?: \"skip\" | AnyStepDryRunHandler<TOptions>;\n skip?: StepSkipPredicate<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n unknown\n >;\n }\n ) => {\n const remote: NonNullable<PipelinePlanStep[\"remote\"]> = { engine: config.adapter.engine };\n if (config.adapter.target !== undefined) remote.target = config.adapter.target;\n const definition: StepDefinitionBody<TOptions> = {\n [STEP_REMOTE]: remote,\n dependsOn: config.dependsOn,\n optionalDependsOn: config.optionalDependsOn,\n skipAfterFailureOf: config.skipAfterFailureOf,\n name: config.name,\n description: config.description,\n dryRun: config.dryRun,\n outputSchema: config.outputSchema,\n run: (inputs: Record<string, unknown>, context: PipelineStepContext<TOptions>) =>\n config.adapter.invoke(config.mapInput(inputs, context), context),\n };\n const skip = config.skip;\n if (skip !== undefined) {\n // SAFETY: each constructor preserves the skip predicate's dependency inputs and context.\n definition.skip = (inputs, context) => skip(inputs as never, context);\n }\n return buildStep(id, definition);\n }) as StepFactory<TOptions, TInputOptions>[\"fromRemote\"];\n\n // SAFETY: the closure's parameter and return shapes match the\n // `forEachPipeline` constructor signature it is assigned to.\n const forEachPipeline = ((\n id: string,\n config: MappedChildPipelineStepDefinition<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n Pipeline<object, unknown>,\n unknown\n > & {\n mapResult?: (\n value: unknown,\n result: PipelineRun<unknown>,\n item: unknown,\n index: number,\n context: PipelineStepContext<TOptions>\n ) => unknown;\n skip?: StepSkipPredicate<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n unknown\n >;\n }\n ) => {\n const definition: StepDefinitionBody<TOptions> = {\n [STEP_NESTED_PIPELINE]: {\n mode: \"for-each\" as const,\n pipelineId: config.pipeline.id,\n stepIds: config.pipeline.stepIds,\n },\n dependsOn: config.dependsOn,\n optionalDependsOn: config.optionalDependsOn,\n skipAfterFailureOf: config.skipAfterFailureOf,\n name: config.name,\n description: config.description,\n dryRun: config.dryRun,\n // SAFETY: the config carries `pipeline`, `items`, `key`, and `mapResult`;\n // the runner derives the rest from those fields, so the config is a valid\n // mapped-child execution config at runtime.\n run: createMappedChildRunner(config as MappedChildExecutionConfig<TOptions>, {\n createExecutionError: (result, message) => new PipelineExecutionError(result, message),\n isCancellation: (error, childContext) => isPipelineCancellation(error, childContext),\n }),\n };\n\n const skip = config.skip;\n if (skip !== undefined) {\n // SAFETY: each constructor preserves the skip predicate's dependency inputs and context.\n definition.skip = (inputs, context) => skip(inputs as never, context);\n }\n return buildStep(id, definition);\n }) as StepFactory<TOptions, TInputOptions>[\"forEachPipeline\"];\n\n // SAFETY: `buildStep` is a callable; attaching the constructor properties\n // yields exactly the `StepFactory` surface (call + skippable + fromPipeline +\n // forEachPipeline), so the single assertion is sound.\n const factory = Object.assign(buildStep, {\n skippable: buildStep,\n fromPipeline,\n fromRemote,\n forEachPipeline,\n }) as StepFactory<TOptions, TInputOptions>;\n // SAFETY: `fromPipeline` is the same callable as `factory.fromPipeline`; it\n // carries the skippable variant, so the assignment is sound.\n factory.fromPipeline.skippable = fromPipeline as StepFactory<\n TOptions,\n TInputOptions\n >[\"fromPipeline\"][\"skippable\"];\n // SAFETY: `fromRemote` is the same callable as `factory.fromRemote`; it\n // carries the skippable variant, so the assignment is sound.\n factory.fromRemote.skippable = fromRemote as StepFactory<\n TOptions,\n TInputOptions\n >[\"fromRemote\"][\"skippable\"];\n // SAFETY: `forEachPipeline` is the same callable as `factory.forEachPipeline`;\n // it carries the skippable variant, so the assignment is sound.\n factory.forEachPipeline.skippable = forEachPipeline as StepFactory<\n TOptions,\n TInputOptions\n >[\"forEachPipeline\"][\"skippable\"];\n\n return factory;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pipeline-steps.js","sourceRoot":"","sources":["../../src/core/pipeline-steps.ts"],"names":[],"mappings":"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","sourcesContent":["import { createMappedChildRunner, createSingleChildRunner } from \"./child-execution.js\";\nimport type { ToMappedChildStepProgressOptions } from \"./mapped-child-progress.js\";\nimport { isPipelineCancellation, PipelineExecutionError } from \"./pipeline-execute.js\";\nimport {\n STEP_NESTED_PIPELINE,\n STEP_OPTIONS_SCHEMA,\n STEP_REMOTE,\n} from \"./pipeline-step-metadata.js\";\nimport type {\n InferSchemaInput,\n InferSchemaOutput,\n Pipeline,\n PipelineExecutionContext,\n PipelinePlanStep,\n PipelineRun,\n PipelineRunOptions,\n PipelineStepContext,\n RemoteStepAdapter,\n StandardSchemaV1,\n StepSkipDecision,\n} from \"./pipeline-types.js\";\n\n/**\n * A step's dependencies are references to the dependency's own step object, not string ids\n * into a hand-maintained output-type map. This buys two things no amount of extra generics\n * on a string-keyed design could:\n * - a step used before its dependency exists is a compile error (JS temporal dead zone on\n * `const`), so out-of-order and self/cyclic dependencies are caught by the language, not\n * a bespoke runtime check\n * - each step only ever states its own id/deps; the output-type map is derived, never\n * restated, and callers of `definePipeline`/`createSteps` never write out its generics\n */\ntype AnyStepDryRunHandler<TOptions extends object> = {\n bivarianceHack(\n inputs: Record<string, unknown>,\n context: PipelineStepContext<TOptions>\n ): unknown | Promise<unknown>;\n}[\"bivarianceHack\"];\n\nexport interface AnyStep<TOptions extends object = object> {\n readonly [STEP_NESTED_PIPELINE]?: NonNullable<PipelinePlanStep[\"nestedPipeline\"]>;\n readonly [STEP_REMOTE]?: NonNullable<PipelinePlanStep[\"remote\"]>;\n readonly [STEP_OPTIONS_SCHEMA]?: StandardSchemaV1;\n readonly id: string;\n readonly dependsOn?: readonly AnyStep<TOptions>[];\n readonly optionalDependsOn?: readonly AnyStep<TOptions>[];\n readonly skipAfterFailureOf?: readonly AnyStep<TOptions>[];\n /** Optional human-facing display name. Stable machine identity remains `id`. */\n readonly name?: string;\n readonly description?: string;\n /**\n * Dry-run policy. Omitted runs the normal handler, `\"skip\"` structurally\n * skips it, and a handler substitutes for `run` while preserving its output.\n */\n readonly dryRun?: \"skip\" | AnyStepDryRunHandler<TOptions>;\n /** Optional Standard Schema for values published by this step. */\n readonly outputSchema?: StandardSchemaV1;\n /**\n * Optional runtime skip. Return a non-empty reason (or `{ reason, value }`) to\n * skip without calling `run`. Policy skips unlock dependents; structural skips\n * (dry-run, filtered, …) do not use this hook.\n */\n skip?(\n inputs: Record<string, unknown>,\n context: PipelineExecutionContext<TOptions>\n ): StepSkipDecision | Promise<StepSkipDecision>;\n run(inputs: Record<string, unknown>, context: PipelineStepContext<TOptions>): unknown;\n}\n\n/** The step fields that `buildStep` merges onto the id-bearing shell. */\ntype StepDefinitionBody<TOptions extends object> = Omit<AnyStep<TOptions>, \"id\">;\n\nexport interface Step<\n TId extends string,\n TOut,\n TOptions extends object,\n TInputOptions extends object = TOptions,\n TRunOut = TOut,\n> extends AnyStep<TOptions> {\n readonly id: TId;\n run(\n inputs: Record<string, unknown>,\n context: PipelineStepContext<TOptions>\n ): TRunOut | Promise<TRunOut>;\n /** Type-only: carries this step's output type for sibling inference. Never set at runtime. */\n readonly __outputType?: TOut;\n /** Type-only: carries pre-validation run options for pipeline call-site inference. */\n readonly __inputOptionsType?: TInputOptions;\n}\n\n/**\n * Extract a step's output type for dependency typing.\n * Prefer matching `Step<…, TOut, …>` over `{ __outputType?: infer T }`: optional-property\n * inference collapses `TOut | undefined` to `TOut`, which hides policy-skip widening.\n */\nexport type StepOutput<S> =\n S extends Step<string, infer TOut, infer _TOptions, infer _TInputOptions, infer _TRunOut>\n ? TOut\n : never;\n\ninterface StepToken {\n readonly id: string;\n readonly __outputType?: unknown;\n}\n\ntype RequiredInputs<TDeps extends readonly StepToken[]> = {\n [S in TDeps[number] as S[\"id\"]]: StepOutput<S>;\n};\n\ntype OptionalInputs<TDeps extends readonly StepToken[]> = {\n [S in TDeps[number] as S[\"id\"]]?: StepOutput<S>;\n};\n\ntype PipelineResultOf<TPipeline> =\n TPipeline extends Pipeline<object, infer TResult, infer _TStepId, infer _TTargetId>\n ? TResult\n : never;\n\ntype PipelineRunOptionsOf<TPipeline> =\n TPipeline extends Pipeline<infer TOptions, unknown, infer TStepId, infer TTargetId>\n ? PipelineRunOptions<TOptions, TStepId, TTargetId>\n : never;\n\ntype ChildPipelineStepDefinitionBase<\n TParentOptions extends object,\n TDeps extends readonly AnyStep<TParentOptions>[],\n TOptionalDeps extends readonly AnyStep<TParentOptions>[],\n TChildPipeline extends Pipeline<object, unknown>,\n> = {\n pipeline: TChildPipeline;\n dependsOn?: TDeps;\n optionalDependsOn?: TOptionalDeps;\n skipAfterFailureOf?: readonly AnyStep<TParentOptions>[];\n name?: string;\n description?: string;\n dryRun?: \"skip\";\n mapOptions(\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TParentOptions>\n ): PipelineRunOptionsOf<TChildPipeline>;\n};\n\n/** Child step without policy skip (dependents see the full child result type). */\ntype ChildPipelineStepDefinition<\n TParentOptions extends object,\n TDeps extends readonly AnyStep<TParentOptions>[],\n TOptionalDeps extends readonly AnyStep<TParentOptions>[],\n TChildPipeline extends Pipeline<object, unknown>,\n> = ChildPipelineStepDefinitionBase<TParentOptions, TDeps, TOptionalDeps, TChildPipeline>;\n\n/**\n * Presentation options for opaque `forEachPipeline` progress.\n * Defaults are domain-neutral (`N/M items · K running · key/step`).\n * Override `formatMessage` when a domain wants its own noun (images, shards, …).\n */\nexport type MappedChildProgressOptions = ToMappedChildStepProgressOptions;\n\ntype MappedChildPipelineStepDefinition<\n TParentOptions extends object,\n TDeps extends readonly AnyStep<TParentOptions>[],\n TOptionalDeps extends readonly AnyStep<TParentOptions>[],\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n> = {\n pipeline: TChildPipeline;\n dependsOn?: TDeps;\n optionalDependsOn?: TOptionalDeps;\n skipAfterFailureOf?: readonly AnyStep<TParentOptions>[];\n name?: string;\n description?: string;\n dryRun?: \"skip\";\n items(\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TParentOptions>\n ): readonly TItem[] | Promise<readonly TItem[]>;\n key(item: TItem, index: number): string;\n concurrency?:\n | number\n | ((\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TParentOptions>\n ) => number);\n /**\n * How the opaque parent step reports live fan-out progress.\n * Purely presentational — does not change scheduling or results.\n */\n progress?: MappedChildProgressOptions;\n mapOptions(\n item: TItem,\n index: number,\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TParentOptions>\n ): PipelineRunOptionsOf<TChildPipeline>;\n};\n\ntype StepSkipPredicate<\n TOptions extends object,\n TDeps extends readonly AnyStep<TOptions>[],\n TOptionalDeps extends readonly AnyStep<TOptions>[],\n TOut,\n> = (\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineExecutionContext<TOptions>\n) => StepSkipDecision<TOut> | Promise<StepSkipDecision<TOut>>;\n\ntype StepDryRunPolicy<\n TOptions extends object,\n TDeps extends readonly AnyStep<TOptions>[],\n TOptionalDeps extends readonly AnyStep<TOptions>[],\n TOut,\n> =\n | \"skip\"\n | ((\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineStepContext<TOptions>\n ) => TOut | Promise<TOut>);\n\ntype PlainStepFields<\n TOptions extends object,\n TDeps extends readonly AnyStep<TOptions>[],\n TOptionalDeps extends readonly AnyStep<TOptions>[],\n TOut,\n> = {\n dependsOn?: TDeps;\n optionalDependsOn?: TOptionalDeps;\n skipAfterFailureOf?: readonly AnyStep<TOptions>[];\n name?: string;\n description?: string;\n dryRun?: StepDryRunPolicy<TOptions, TDeps, TOptionalDeps, TOut>;\n outputSchema?: never;\n run(\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineStepContext<TOptions>\n ): TOut | Promise<TOut>;\n};\n\ntype SchemaStepFields<\n TOptions extends object,\n TDeps extends readonly AnyStep<TOptions>[],\n TOptionalDeps extends readonly AnyStep<TOptions>[],\n TSchema extends StandardSchemaV1,\n> = Omit<\n PlainStepFields<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>,\n \"outputSchema\"\n> & {\n outputSchema: TSchema;\n};\n\ntype RemoteStepDefinitionBase<\n TParentOptions extends object,\n TDeps extends readonly AnyStep<TParentOptions>[],\n TOptionalDeps extends readonly AnyStep<TParentOptions>[],\n TPayload,\n TSchema extends StandardSchemaV1,\n> = {\n adapter: RemoteStepAdapter<TParentOptions, TPayload, InferSchemaInput<TSchema>>;\n mapInput(\n inputs: RequiredInputs<TDeps> & OptionalInputs<TOptionalDeps>,\n context: PipelineStepContext<TParentOptions>\n ): TPayload;\n outputSchema: TSchema;\n dependsOn?: TDeps;\n optionalDependsOn?: TOptionalDeps;\n skipAfterFailureOf?: readonly AnyStep<TParentOptions>[];\n name?: string;\n description?: string;\n dryRun?: StepDryRunPolicy<TParentOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>;\n};\n\nexport type StepFactory<\n TOptions extends object,\n TInputOptions extends object = TOptions,\n> = ReturnType<typeof createStepFactory<TOptions, TInputOptions>>;\n\n/**\n * Returns a step factory scoped to one pipeline's domain options. Pass built-in\n * run controls as the second argument to `run` / `runOrThrow`. Child\n * `mapOptions` may still return domain options plus those controls.\n */\nexport function createSteps<TOptions extends object = {}>(): StepFactory<TOptions>;\nexport function createSteps<const TSchema extends StandardSchemaV1<object, object>>(\n optionsSchema: TSchema\n): StepFactory<InferSchemaOutput<TSchema>, InferSchemaInput<TSchema>>;\nexport function createSteps(optionsSchema?: StandardSchemaV1<object, object>): StepFactory<object> {\n return createStepFactory<object>(optionsSchema);\n}\n\nfunction createStepFactory<TOptions extends object, TInputOptions extends object = TOptions>(\n optionsSchema?: StandardSchemaV1\n) {\n const buildStep = (id: string, definition: StepDefinitionBody<TOptions>): AnyStep<TOptions> => {\n const built: AnyStep<TOptions> = { id, ...definition };\n if (optionsSchema) {\n Object.defineProperty(built, STEP_OPTIONS_SCHEMA, { value: optionsSchema });\n }\n return built;\n };\n\n function step<\n TId extends string,\n TSchema extends StandardSchemaV1,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: SchemaStepFields<TOptions, TDeps, TOptionalDeps, TSchema> & {\n skip:\n | StepSkipPredicate<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>\n | undefined;\n }\n ): Step<\n TId,\n InferSchemaOutput<TSchema> | undefined,\n TOptions,\n TInputOptions,\n InferSchemaInput<TSchema>\n >;\n function step<\n TId extends string,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n TOut = unknown,\n >(\n id: TId,\n definition: PlainStepFields<TOptions, TDeps, TOptionalDeps, TOut> & {\n skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, TOut> | undefined;\n }\n ): Step<TId, TOut | undefined, TOptions, TInputOptions>;\n function step<\n TId extends string,\n TSchema extends StandardSchemaV1,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: SchemaStepFields<TOptions, TDeps, TOptionalDeps, TSchema> & { skip?: never }\n ): Step<TId, InferSchemaOutput<TSchema>, TOptions, TInputOptions, InferSchemaInput<TSchema>>;\n function step<\n TId extends string,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n TOut = unknown,\n >(\n id: TId,\n definition: PlainStepFields<TOptions, TDeps, TOptionalDeps, TOut> & { skip?: never }\n ): Step<TId, TOut, TOptions, TInputOptions>;\n function step(id: string, definition: StepDefinitionBody<TOptions>): AnyStep<TOptions> {\n return buildStep(id, definition);\n }\n\n const buildPipelineStep = (\n id: string,\n config: ChildPipelineStepDefinitionBase<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n Pipeline<object, unknown>\n > & {\n skip?: StepSkipPredicate<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n unknown\n >;\n mapResult?: (\n value: unknown,\n result: PipelineRun<unknown>,\n context: PipelineStepContext<TOptions>\n ) => unknown;\n }\n ) => {\n const definition: StepDefinitionBody<TOptions> = {\n [STEP_NESTED_PIPELINE]: {\n mode: \"single\" as const,\n pipelineId: config.pipeline.id,\n stepIds: config.pipeline.stepIds,\n },\n dependsOn: config.dependsOn,\n optionalDependsOn: config.optionalDependsOn,\n skipAfterFailureOf: config.skipAfterFailureOf,\n name: config.name,\n description: config.description,\n dryRun: config.dryRun,\n run: createSingleChildRunner(config, {\n createExecutionError: (result, message) => new PipelineExecutionError(result, message),\n isCancellation: (error, childContext) => isPipelineCancellation(error, childContext),\n }),\n };\n\n const skip = config.skip;\n if (skip !== undefined) {\n definition.skip = skip;\n }\n return buildStep(id, definition);\n };\n\n function fromPipeline<\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: ChildPipelineStepDefinition<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {\n skip?: never;\n mapResult?: undefined;\n }\n ): Step<TId, PipelineResultOf<TChildPipeline>, TOptions, TInputOptions>;\n function fromPipeline<\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TOut,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {\n skip?: never;\n mapResult(\n value: PipelineResultOf<TChildPipeline>,\n result: PipelineRun<PipelineResultOf<TChildPipeline>>,\n context: PipelineStepContext<TOptions>\n ): TOut;\n }\n ): Step<TId, Awaited<TOut>, TOptions, TInputOptions>;\n function fromPipeline<\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {\n skip:\n | StepSkipPredicate<TOptions, TDeps, TOptionalDeps, PipelineResultOf<TChildPipeline>>\n | undefined;\n mapResult?: undefined;\n }\n ): Step<TId, PipelineResultOf<TChildPipeline> | undefined, TOptions, TInputOptions>;\n function fromPipeline<\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TOut,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: ChildPipelineStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TChildPipeline> & {\n skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, NoInfer<Awaited<TOut>>> | undefined;\n mapResult(\n value: PipelineResultOf<TChildPipeline>,\n result: PipelineRun<PipelineResultOf<TChildPipeline>>,\n context: PipelineStepContext<TOptions>\n ): TOut;\n }\n ): Step<TId, Awaited<TOut> | undefined, TOptions, TInputOptions>;\n function fromPipeline(\n id: string,\n definition: Parameters<typeof buildPipelineStep>[1]\n ): AnyStep<TOptions> {\n return buildPipelineStep(id, definition);\n }\n\n const buildRemoteStep = (\n id: string,\n config: {\n adapter: RemoteStepAdapter<object, unknown, unknown>;\n mapInput(inputs: Record<string, unknown>, context: PipelineStepContext<TOptions>): unknown;\n outputSchema: StandardSchemaV1;\n dependsOn?: readonly AnyStep<TOptions>[];\n optionalDependsOn?: readonly AnyStep<TOptions>[];\n skipAfterFailureOf?: readonly AnyStep<TOptions>[];\n name?: string;\n description?: string;\n dryRun?: \"skip\" | AnyStepDryRunHandler<TOptions>;\n skip?: StepSkipPredicate<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n unknown\n >;\n }\n ) => {\n const remote: NonNullable<PipelinePlanStep[\"remote\"]> = { engine: config.adapter.engine };\n if (config.adapter.target !== undefined) remote.target = config.adapter.target;\n const definition: StepDefinitionBody<TOptions> = {\n [STEP_REMOTE]: remote,\n dependsOn: config.dependsOn,\n optionalDependsOn: config.optionalDependsOn,\n skipAfterFailureOf: config.skipAfterFailureOf,\n name: config.name,\n description: config.description,\n dryRun: config.dryRun,\n outputSchema: config.outputSchema,\n run: (inputs: Record<string, unknown>, context: PipelineStepContext<TOptions>) =>\n config.adapter.invoke(config.mapInput(inputs, context), context),\n };\n const skip = config.skip;\n if (skip !== undefined) {\n definition.skip = skip;\n }\n return buildStep(id, definition);\n };\n\n function fromRemote<\n TId extends string,\n TSchema extends StandardSchemaV1,\n TPayload,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: RemoteStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TPayload, TSchema> & {\n skip?: never;\n }\n ): Step<TId, InferSchemaOutput<TSchema>, TOptions, TInputOptions, InferSchemaInput<TSchema>>;\n function fromRemote<\n TId extends string,\n TSchema extends StandardSchemaV1,\n TPayload,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: RemoteStepDefinitionBase<TOptions, TDeps, TOptionalDeps, TPayload, TSchema> & {\n skip:\n | StepSkipPredicate<TOptions, TDeps, TOptionalDeps, InferSchemaInput<TSchema>>\n | undefined;\n }\n ): Step<\n TId,\n InferSchemaOutput<TSchema> | undefined,\n TOptions,\n TInputOptions,\n InferSchemaInput<TSchema>\n >;\n function fromRemote(\n id: string,\n definition: Parameters<typeof buildRemoteStep>[1]\n ): AnyStep<TOptions> {\n return buildRemoteStep(id, definition);\n }\n\n const buildMappedPipelineStep = (\n id: string,\n config: MappedChildPipelineStepDefinition<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n Pipeline<object, unknown>,\n unknown\n > & {\n mapResult?: (\n value: unknown,\n result: PipelineRun<unknown>,\n item: unknown,\n index: number,\n context: PipelineStepContext<TOptions>\n ) => unknown;\n skip?: StepSkipPredicate<\n TOptions,\n readonly AnyStep<TOptions>[],\n readonly AnyStep<TOptions>[],\n unknown\n >;\n }\n ) => {\n const definition: StepDefinitionBody<TOptions> = {\n [STEP_NESTED_PIPELINE]: {\n mode: \"for-each\" as const,\n pipelineId: config.pipeline.id,\n stepIds: config.pipeline.stepIds,\n },\n dependsOn: config.dependsOn,\n optionalDependsOn: config.optionalDependsOn,\n skipAfterFailureOf: config.skipAfterFailureOf,\n name: config.name,\n description: config.description,\n dryRun: config.dryRun,\n run: createMappedChildRunner(config, {\n createExecutionError: (result, message) => new PipelineExecutionError(result, message),\n isCancellation: (error, childContext) => isPipelineCancellation(error, childContext),\n }),\n };\n\n const skip = config.skip;\n if (skip !== undefined) {\n definition.skip = skip;\n }\n return buildStep(id, definition);\n };\n\n function forEachPipeline<\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: MappedChildPipelineStepDefinition<\n TOptions,\n TDeps,\n TOptionalDeps,\n TChildPipeline,\n TItem\n > & {\n skip?: never;\n mapResult?: undefined;\n }\n ): Step<TId, readonly PipelineResultOf<TChildPipeline>[], TOptions, TInputOptions>;\n function forEachPipeline<\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n TOut,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: MappedChildPipelineStepDefinition<\n TOptions,\n TDeps,\n TOptionalDeps,\n TChildPipeline,\n TItem\n > & {\n skip?: never;\n mapResult(\n value: PipelineResultOf<TChildPipeline>,\n result: PipelineRun<PipelineResultOf<TChildPipeline>>,\n item: TItem,\n index: number,\n context: PipelineStepContext<TOptions>\n ): TOut;\n }\n ): Step<TId, readonly TOut[], TOptions, TInputOptions>;\n function forEachPipeline<\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: MappedChildPipelineStepDefinition<\n TOptions,\n TDeps,\n TOptionalDeps,\n TChildPipeline,\n TItem\n > & {\n skip:\n | StepSkipPredicate<\n TOptions,\n TDeps,\n TOptionalDeps,\n readonly PipelineResultOf<TChildPipeline>[]\n >\n | undefined;\n mapResult?: undefined;\n }\n ): Step<TId, readonly PipelineResultOf<TChildPipeline>[] | undefined, TOptions, TInputOptions>;\n function forEachPipeline<\n TId extends string,\n TChildPipeline extends Pipeline<object, unknown>,\n TItem,\n TOut,\n const TDeps extends readonly AnyStep<TOptions>[] = [],\n const TOptionalDeps extends readonly AnyStep<TOptions>[] = [],\n >(\n id: TId,\n definition: MappedChildPipelineStepDefinition<\n TOptions,\n TDeps,\n TOptionalDeps,\n TChildPipeline,\n TItem\n > & {\n skip: StepSkipPredicate<TOptions, TDeps, TOptionalDeps, NoInfer<readonly TOut[]>> | undefined;\n mapResult(\n value: PipelineResultOf<TChildPipeline>,\n result: PipelineRun<PipelineResultOf<TChildPipeline>>,\n item: TItem,\n index: number,\n context: PipelineStepContext<TOptions>\n ): TOut;\n }\n ): Step<TId, readonly TOut[] | undefined, TOptions, TInputOptions>;\n function forEachPipeline(\n id: string,\n definition: Parameters<typeof buildMappedPipelineStep>[1]\n ): AnyStep<TOptions> {\n return buildMappedPipelineStep(id, definition);\n }\n\n const factory = {\n step,\n fromPipeline,\n fromRemote,\n forEachPipeline,\n };\n\n return factory;\n}\n"]}
|
package/dist/node/atomic-text.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
3
4
|
export function writeAtomicText(filePath, text) {
|
|
4
5
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
5
|
-
//
|
|
6
|
-
const tmpPath = `${filePath}.tmp-${process.pid}`;
|
|
6
|
+
// Each call owns its sibling temp file, including writers on same-PID workers.
|
|
7
|
+
const tmpPath = `${filePath}.tmp-${process.pid}-${randomUUID()}`;
|
|
7
8
|
try {
|
|
8
9
|
fs.writeFileSync(tmpPath, text);
|
|
9
10
|
fs.renameSync(tmpPath, filePath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomic-text.js","sourceRoot":"","sources":["../../src/node/atomic-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"atomic-text.js","sourceRoot":"","sources":["../../src/node/atomic-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAY;IAC5D,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,+EAA+E;IAC/E,MAAM,OAAO,GAAG,GAAG,QAAQ,QAAQ,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,EAAE,CAAC;IACjE,IAAI,CAAC;QACH,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAChC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YACH,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,gEAAgE;QAClE,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\nimport { randomUUID } from \"node:crypto\";\n\nexport function writeAtomicText(filePath: string, text: string): void {\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n // Each call owns its sibling temp file, including writers on same-PID workers.\n const tmpPath = `${filePath}.tmp-${process.pid}-${randomUUID()}`;\n try {\n fs.writeFileSync(tmpPath, text);\n fs.renameSync(tmpPath, filePath);\n } catch (error) {\n try {\n fs.rmSync(tmpPath, { force: true });\n } catch {\n // Best-effort cleanup; surface the original write/rename error.\n }\n throw error;\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function requireEnv(varName: string, usedBy: string): string;
|
package/dist/node/env.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/node/env.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,MAAc;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,oBAAoB,MAAM,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["export function requireEnv(varName: string, usedBy: string): string {\n const value = process.env[varName];\n if (!value) {\n throw new Error(`${varName} is required for ${usedBy}`);\n }\n return value;\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import { writeAtomicText } from "./atomic-text.js";
|
|
3
|
+
export function writeJson(filePath, value) {
|
|
4
|
+
const serialized = JSON.stringify(value, null, 2);
|
|
5
|
+
if (serialized === undefined) {
|
|
6
|
+
throw new TypeError("Value cannot be serialized as JSON");
|
|
7
|
+
}
|
|
8
|
+
writeAtomicText(filePath, `${serialized}\n`);
|
|
9
|
+
}
|
|
10
|
+
export function readJson(filePath) {
|
|
11
|
+
// SAFETY: the caller's type parameter T is the contract for the file's
|
|
12
|
+
// contents; the file is expected to hold JSON matching T (files written by
|
|
13
|
+
// writeJson round-trip). JSON.parse returns `any`, so the assertion only
|
|
14
|
+
// documents the caller's guarantee — it performs no runtime narrowing.
|
|
15
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
16
|
+
}
|
|
17
|
+
export function resetDir(dirPath) {
|
|
18
|
+
fs.rmSync(dirPath, { recursive: true, force: true });
|
|
19
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=file-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../src/node/file-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,KAAc;IACxD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAClD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,SAAS,CAAC,oCAAoC,CAAC,CAAC;IAC5D,CAAC;IACD,eAAe,CAAC,QAAQ,EAAE,GAAG,UAAU,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,QAAgB;IAC1C,uEAAuE;IACvE,2EAA2E;IAC3E,yEAAyE;IACzE,uEAAuE;IACvE,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAM,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAe;IACtC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrD,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC7C,CAAC","sourcesContent":["import * as fs from \"fs\";\nimport { writeAtomicText } from \"./atomic-text.js\";\n\nexport function writeJson(filePath: string, value: unknown): void {\n const serialized = JSON.stringify(value, null, 2);\n if (serialized === undefined) {\n throw new TypeError(\"Value cannot be serialized as JSON\");\n }\n writeAtomicText(filePath, `${serialized}\\n`);\n}\n\nexport function readJson<T>(filePath: string): T {\n // SAFETY: the caller's type parameter T is the contract for the file's\n // contents; the file is expected to hold JSON matching T (files written by\n // writeJson round-trip). JSON.parse returns `any`, so the assertion only\n // documents the caller's guarantee — it performs no runtime narrowing.\n return JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as T;\n}\n\nexport function resetDir(dirPath: string): void {\n fs.rmSync(dirPath, { recursive: true, force: true });\n fs.mkdirSync(dirPath, { recursive: true });\n}\n"]}
|
package/dist/node/node.d.ts
CHANGED
package/dist/node/node.js
CHANGED
package/dist/node/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAwB,MAAM,iBAAiB,CAAC","sourcesContent":["export { openCheckpoint, withCheckpointedBatch, type CheckpointStore } from \"./checkpoint.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAwB,MAAM,iBAAiB,CAAC;AAC9F,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export { openCheckpoint, withCheckpointedBatch, type CheckpointStore } from \"./checkpoint.js\";\nexport { requireEnv } from \"./env.js\";\nexport { readJson, resetDir, writeJson } from \"./file-utils.js\";\nexport { definePaths } from \"./paths.js\";\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declares a set of workspace-relative default paths as one factory instead of one
|
|
3
|
+
* `function defaultXDir(cwd) { return path.join(cwd, "...") }` per path. The returned
|
|
4
|
+
* function re-resolves against `cwd` on every call — nothing is computed or cached at
|
|
5
|
+
* module-load time, so a frozen-`process.cwd()` bug cannot be reintroduced by
|
|
6
|
+
* construction.
|
|
7
|
+
*/
|
|
8
|
+
export declare function definePaths<T extends Record<string, string>>(relativePaths: T): (cwd: string) => {
|
|
9
|
+
[K in keyof T]: string;
|
|
10
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
/**
|
|
3
|
+
* Declares a set of workspace-relative default paths as one factory instead of one
|
|
4
|
+
* `function defaultXDir(cwd) { return path.join(cwd, "...") }` per path. The returned
|
|
5
|
+
* function re-resolves against `cwd` on every call — nothing is computed or cached at
|
|
6
|
+
* module-load time, so a frozen-`process.cwd()` bug cannot be reintroduced by
|
|
7
|
+
* construction.
|
|
8
|
+
*/
|
|
9
|
+
export function definePaths(relativePaths) {
|
|
10
|
+
return (cwd) =>
|
|
11
|
+
// SAFETY: Object.entries(relativePaths) yields exactly T's keys, and every
|
|
12
|
+
// value is a resolved string, so the result preserves T's keys while widening
|
|
13
|
+
// relative path literals to string.
|
|
14
|
+
Object.fromEntries(Object.entries(relativePaths).map(([key, relativePath]) => [
|
|
15
|
+
key,
|
|
16
|
+
path.join(cwd, relativePath),
|
|
17
|
+
]));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/node/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,aAAgB;IAEhB,OAAO,CAAC,GAAW,EAAE,EAAE;IACrB,2EAA2E;IAC3E,8EAA8E;IAC9E,oCAAoC;IACpC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,EAAE,CAAC;QACzD,GAAG;QACH,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC;KAC7B,CAAC,CAC2B,CAAC;AACpC,CAAC","sourcesContent":["import * as path from \"path\";\n\n/**\n * Declares a set of workspace-relative default paths as one factory instead of one\n * `function defaultXDir(cwd) { return path.join(cwd, \"...\") }` per path. The returned\n * function re-resolves against `cwd` on every call — nothing is computed or cached at\n * module-load time, so a frozen-`process.cwd()` bug cannot be reintroduced by\n * construction.\n */\nexport function definePaths<T extends Record<string, string>>(\n relativePaths: T\n): (cwd: string) => { [K in keyof T]: string } {\n return (cwd: string) =>\n // SAFETY: Object.entries(relativePaths) yields exactly T's keys, and every\n // value is a resolved string, so the result preserves T's keys while widening\n // relative path literals to string.\n Object.fromEntries(\n Object.entries(relativePaths).map(([key, relativePath]) => [\n key,\n path.join(cwd, relativePath),\n ])\n ) as { [K in keyof T]: string };\n}\n"]}
|