tubeless 0.2.6 → 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/project/project-compiler.js +1 -1
- package/dist/project/project-compiler.js.map +1 -1
- package/docs/agent-guide.md +9 -7
- package/docs/api-reference.md +4 -4
- package/docs/api-report.json +4 -4
- package/docs/child-pipeline-composition.md +24 -19
- package/docs/concepts.md +13 -11
- package/docs/getting-started.md +3 -3
- package/docs/recipes.md +5 -5
- 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 +2 -0
- package/examples/child-pipeline.ts +4 -4
- package/examples/cli-job.ts +1 -1
- package/examples/conditional-step.ts +2 -2
- 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 +1 -1
- 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/package.json +1 -1
- package/skills/tubeless/SKILL.md +6 -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"]}
|
|
@@ -34,7 +34,7 @@ export function compilePipelineDocument(document, registry) {
|
|
|
34
34
|
for (const [id, definition] of Object.entries(parsed.pipelines)) {
|
|
35
35
|
const path = `$.pipelines[${JSON.stringify(id)}]`;
|
|
36
36
|
const optionsSchema = schema(registry.optionsSchemas, definition.optionsSchema, `${path}.optionsSchema`);
|
|
37
|
-
const step = optionsSchema ? createSteps(optionsSchema) : createSteps();
|
|
37
|
+
const { step } = optionsSchema ? createSteps(optionsSchema) : createSteps();
|
|
38
38
|
const entries = definition.steps.map((definition, index) => {
|
|
39
39
|
const stepPath = `${path}.steps[${index}]`;
|
|
40
40
|
// Populate these arrays after all steps exist, allowing forward references
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-compiler.js","sourceRoot":"","sources":["../../src/project/project-compiler.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createSteps,\n definePipeline,\n requireOutputs,\n type AnyStep,\n type Pipeline,\n type PipelineExecutionContext,\n type PipelineStepContext,\n type StandardSchemaV1,\n} from \"../core/pipeline.js\";\nimport { validatePipelineDocument, PipelineDocumentError } from \"./project-document.js\";\n\nexport { PipelineDocumentError };\nexport type {\n PipelineDocument,\n PipelineDocumentDefinition,\n PipelineDocumentStep,\n} from \"./project-document.js\";\n\n/** Dependency values are checked at runtime rather than inferred from a project document. */\nexport type PipelineDocumentHandler = (\n inputs: Record<string, unknown>,\n context: PipelineStepContext<object>\n) => unknown;\n\nexport type PipelineDocumentFinalizer = (\n outputs: Record<string, unknown>,\n context: PipelineExecutionContext<object>\n) => unknown;\n\n/** Only explicitly registered functions and schemas can be referenced by a document. */\nexport interface PipelineDocumentRegistry {\n steps: Readonly<Record<string, PipelineDocumentHandler>>;\n finalizers: Readonly<Record<string, PipelineDocumentFinalizer>>;\n optionsSchemas?: Readonly<Record<string, StandardSchemaV1<object, object>>>;\n schemas?: Readonly<Record<string, StandardSchemaV1>>;\n}\n\nfunction resolve<T>(\n registry: Readonly<Record<string, T>> | undefined,\n name: string,\n path: string\n): T {\n if (!registry || !Object.hasOwn(registry, name)) {\n throw new PipelineDocumentError(path, `Unknown registered name ${JSON.stringify(name)}`);\n }\n return registry[name];\n}\n\nfunction handler<T extends PipelineDocumentHandler | PipelineDocumentFinalizer>(\n registry: Readonly<Record<string, T>>,\n name: string,\n path: string\n): T {\n const value = resolve(registry, name, path);\n if (typeof value !== \"function\")\n throw new PipelineDocumentError(path, \"Expected a registered function\");\n return value;\n}\n\nfunction schema<T extends StandardSchemaV1>(\n registry: Readonly<Record<string, T>> | undefined,\n name: string | undefined,\n path: string\n): T | undefined {\n if (name === undefined) return undefined;\n const value = resolve(registry, name, path);\n if (\n !value ||\n value[\"~standard\"]?.version !== 1 ||\n typeof value[\"~standard\"].validate !== \"function\"\n ) {\n throw new PipelineDocumentError(path, \"Expected a Standard Schema v1 schema\");\n }\n return value;\n}\n\n/**\n * Compile parsed YAML or JSON into ordinary pipelines. Does not load modules,\n * invoke handlers or schemas, or perform I/O. Graph validation belongs to core.\n */\nexport function compilePipelineDocument(\n document: unknown,\n registry: PipelineDocumentRegistry\n): ReadonlyMap<string, Pipeline<object, unknown>> {\n const parsed = validatePipelineDocument(document);\n const pipelines = new Map<string, Pipeline<object, unknown>>();\n for (const [id, definition] of Object.entries(parsed.pipelines)) {\n const path = `$.pipelines[${JSON.stringify(id)}]`;\n const optionsSchema = schema(\n registry.optionsSchemas,\n definition.optionsSchema,\n `${path}.optionsSchema`\n );\n const step = optionsSchema ? createSteps(optionsSchema) : createSteps<object>();\n const entries = definition.steps.map((definition, index) => {\n const stepPath = `${path}.steps[${index}]`;\n // Populate these arrays after all steps exist, allowing forward references\n // and leaving cycle detection to the existing definition validator.\n const dependsOn: AnyStep[] = [];\n const optionalDependsOn: AnyStep[] = [];\n const skipAfterFailureOf: AnyStep[] = [];\n const dryRun =\n definition.dryRun === undefined || definition.dryRun === \"skip\"\n ? definition.dryRun\n : handler(registry.steps, definition.dryRun.run, `${stepPath}.dryRun.run`);\n const outputSchema = schema(\n registry.schemas,\n definition.outputSchema,\n `${stepPath}.outputSchema`\n );\n const config = {\n name: definition.name,\n description: definition.description,\n run: handler(registry.steps, definition.run, `${stepPath}.run`),\n dryRun,\n dependsOn,\n optionalDependsOn,\n skipAfterFailureOf,\n };\n return {\n definition,\n path: stepPath,\n dependsOn,\n optionalDependsOn,\n skipAfterFailureOf,\n step: outputSchema\n ? step(definition.id, { ...config, outputSchema })\n : step(definition.id, config),\n };\n });\n const byId = new Map(entries.map((entry) => [entry.step.id, entry.step]));\n const resolveSteps = (ids: readonly string[] = [], fieldPath: string): AnyStep[] =>\n ids.map((stepId, index) => {\n const found = byId.get(stepId);\n if (!found)\n throw new PipelineDocumentError(\n `${fieldPath}[${index}]`,\n `Unknown step ${JSON.stringify(stepId)}`\n );\n return found;\n });\n for (const entry of entries) {\n for (const field of [\"dependsOn\", \"optionalDependsOn\", \"skipAfterFailureOf\"] as const) {\n entry[field].push(...resolveSteps(entry.definition[field], `${entry.path}.${field}`));\n }\n }\n const finalize = handler(registry.finalizers, definition.finalize.run, `${path}.finalize.run`);\n pipelines.set(\n id,\n definePipeline({\n id,\n steps: entries.map((entry) => entry.step),\n targets: resolveSteps(definition.targets, `${path}.targets`),\n resultSchema: schema(registry.schemas, definition.resultSchema, `${path}.resultSchema`),\n finalize:\n definition.finalize.requireOutputs === undefined\n ? finalize\n : requireOutputs(\n resolveSteps(definition.finalize.requireOutputs, `${path}.finalize.requireOutputs`),\n finalize\n ),\n })\n );\n }\n return pipelines;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"project-compiler.js","sourceRoot":"","sources":["../../src/project/project-compiler.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createSteps,\n definePipeline,\n requireOutputs,\n type AnyStep,\n type Pipeline,\n type PipelineExecutionContext,\n type PipelineStepContext,\n type StandardSchemaV1,\n} from \"../core/pipeline.js\";\nimport { validatePipelineDocument, PipelineDocumentError } from \"./project-document.js\";\n\nexport { PipelineDocumentError };\nexport type {\n PipelineDocument,\n PipelineDocumentDefinition,\n PipelineDocumentStep,\n} from \"./project-document.js\";\n\n/** Dependency values are checked at runtime rather than inferred from a project document. */\nexport type PipelineDocumentHandler = (\n inputs: Record<string, unknown>,\n context: PipelineStepContext<object>\n) => unknown;\n\nexport type PipelineDocumentFinalizer = (\n outputs: Record<string, unknown>,\n context: PipelineExecutionContext<object>\n) => unknown;\n\n/** Only explicitly registered functions and schemas can be referenced by a document. */\nexport interface PipelineDocumentRegistry {\n steps: Readonly<Record<string, PipelineDocumentHandler>>;\n finalizers: Readonly<Record<string, PipelineDocumentFinalizer>>;\n optionsSchemas?: Readonly<Record<string, StandardSchemaV1<object, object>>>;\n schemas?: Readonly<Record<string, StandardSchemaV1>>;\n}\n\nfunction resolve<T>(\n registry: Readonly<Record<string, T>> | undefined,\n name: string,\n path: string\n): T {\n if (!registry || !Object.hasOwn(registry, name)) {\n throw new PipelineDocumentError(path, `Unknown registered name ${JSON.stringify(name)}`);\n }\n return registry[name];\n}\n\nfunction handler<T extends PipelineDocumentHandler | PipelineDocumentFinalizer>(\n registry: Readonly<Record<string, T>>,\n name: string,\n path: string\n): T {\n const value = resolve(registry, name, path);\n if (typeof value !== \"function\")\n throw new PipelineDocumentError(path, \"Expected a registered function\");\n return value;\n}\n\nfunction schema<T extends StandardSchemaV1>(\n registry: Readonly<Record<string, T>> | undefined,\n name: string | undefined,\n path: string\n): T | undefined {\n if (name === undefined) return undefined;\n const value = resolve(registry, name, path);\n if (\n !value ||\n value[\"~standard\"]?.version !== 1 ||\n typeof value[\"~standard\"].validate !== \"function\"\n ) {\n throw new PipelineDocumentError(path, \"Expected a Standard Schema v1 schema\");\n }\n return value;\n}\n\n/**\n * Compile parsed YAML or JSON into ordinary pipelines. Does not load modules,\n * invoke handlers or schemas, or perform I/O. Graph validation belongs to core.\n */\nexport function compilePipelineDocument(\n document: unknown,\n registry: PipelineDocumentRegistry\n): ReadonlyMap<string, Pipeline<object, unknown>> {\n const parsed = validatePipelineDocument(document);\n const pipelines = new Map<string, Pipeline<object, unknown>>();\n for (const [id, definition] of Object.entries(parsed.pipelines)) {\n const path = `$.pipelines[${JSON.stringify(id)}]`;\n const optionsSchema = schema(\n registry.optionsSchemas,\n definition.optionsSchema,\n `${path}.optionsSchema`\n );\n const { step } = optionsSchema ? createSteps(optionsSchema) : createSteps<object>();\n const entries = definition.steps.map((definition, index) => {\n const stepPath = `${path}.steps[${index}]`;\n // Populate these arrays after all steps exist, allowing forward references\n // and leaving cycle detection to the existing definition validator.\n const dependsOn: AnyStep[] = [];\n const optionalDependsOn: AnyStep[] = [];\n const skipAfterFailureOf: AnyStep[] = [];\n const dryRun =\n definition.dryRun === undefined || definition.dryRun === \"skip\"\n ? definition.dryRun\n : handler(registry.steps, definition.dryRun.run, `${stepPath}.dryRun.run`);\n const outputSchema = schema(\n registry.schemas,\n definition.outputSchema,\n `${stepPath}.outputSchema`\n );\n const config = {\n name: definition.name,\n description: definition.description,\n run: handler(registry.steps, definition.run, `${stepPath}.run`),\n dryRun,\n dependsOn,\n optionalDependsOn,\n skipAfterFailureOf,\n };\n return {\n definition,\n path: stepPath,\n dependsOn,\n optionalDependsOn,\n skipAfterFailureOf,\n step: outputSchema\n ? step(definition.id, { ...config, outputSchema })\n : step(definition.id, config),\n };\n });\n const byId = new Map(entries.map((entry) => [entry.step.id, entry.step]));\n const resolveSteps = (ids: readonly string[] = [], fieldPath: string): AnyStep[] =>\n ids.map((stepId, index) => {\n const found = byId.get(stepId);\n if (!found)\n throw new PipelineDocumentError(\n `${fieldPath}[${index}]`,\n `Unknown step ${JSON.stringify(stepId)}`\n );\n return found;\n });\n for (const entry of entries) {\n for (const field of [\"dependsOn\", \"optionalDependsOn\", \"skipAfterFailureOf\"] as const) {\n entry[field].push(...resolveSteps(entry.definition[field], `${entry.path}.${field}`));\n }\n }\n const finalize = handler(registry.finalizers, definition.finalize.run, `${path}.finalize.run`);\n pipelines.set(\n id,\n definePipeline({\n id,\n steps: entries.map((entry) => entry.step),\n targets: resolveSteps(definition.targets, `${path}.targets`),\n resultSchema: schema(registry.schemas, definition.resultSchema, `${path}.resultSchema`),\n finalize:\n definition.finalize.requireOutputs === undefined\n ? finalize\n : requireOutputs(\n resolveSteps(definition.finalize.requireOutputs, `${path}.finalize.requireOutputs`),\n finalize\n ),\n })\n );\n }\n return pipelines;\n}\n"]}
|
package/docs/agent-guide.md
CHANGED
|
@@ -37,8 +37,10 @@ dry runs with fake I/O. The general `tubeless` skill supports ongoing authoring.
|
|
|
37
37
|
editor or agent validation. Optional document metadata is descriptive only.
|
|
38
38
|
`inspect` or `plan` on a compiled command still checks graph semantics.
|
|
39
39
|
|
|
40
|
-
- Use `createSteps<TDomainOptions>()` once per pipeline and
|
|
41
|
-
|
|
40
|
+
- Use `createSteps<TDomainOptions>()` once per pipeline and destructure every
|
|
41
|
+
constructor that pipeline uses: `step`, `fromPipeline`, `fromRemote`, and/or
|
|
42
|
+
`forEachPipeline`. Use `definePipeline` once after declaring the steps. Domain
|
|
43
|
+
option types contain domain input only;
|
|
42
44
|
callers pass those options and optional built-in controls to
|
|
43
45
|
`run(options, controls?)`, while `plan(controls)` accepts controls alone.
|
|
44
46
|
- Treat a `PipelineDefinitionError` during module loading as an authoring bug;
|
|
@@ -53,12 +55,12 @@ dry runs with fake I/O. The general `tubeless` skill supports ongoing authoring.
|
|
|
53
55
|
- Set `dryRun: "skip"` on filesystem writes, database mutations, publication,
|
|
54
56
|
email, and other steps whose normal `run` must not execute in a dry run. Use a
|
|
55
57
|
typed `dryRun` handler when the step should produce a preview value instead.
|
|
56
|
-
-
|
|
57
|
-
resulting `T | undefined` output type explicitly.
|
|
58
|
+
- Add `skip` to a step definition only for an intentional successful outcome.
|
|
59
|
+
Handle its resulting `T | undefined` output type explicitly.
|
|
58
60
|
- Use `fromPipeline` for one independently useful child workflow and
|
|
59
61
|
`forEachPipeline` for runtime fan-out with stable keys and bounded concurrency.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
+
Add `skip` only when the whole fan-out may be intentionally omitted; handle
|
|
63
|
+
its `readonly T[] | undefined` output explicitly.
|
|
62
64
|
Async `fromPipeline` result mappings publish resolved values; use that resolved
|
|
63
65
|
shape for dependent inputs and policy-skip values.
|
|
64
66
|
Parent plans show one wrapper step and expose `nestedPipeline` with the child
|
|
@@ -221,7 +223,7 @@ dry runs with fake I/O. The general `tubeless` skill supports ongoing authoring.
|
|
|
221
223
|
|
|
222
224
|
## Failure and safety rules
|
|
223
225
|
|
|
224
|
-
- Do not use `
|
|
226
|
+
- Do not use `skip` to swallow an exception.
|
|
225
227
|
- Do not treat dry run as rollback; external side effects require
|
|
226
228
|
`dryRun: "skip"` or a side-effect-free custom `dryRun` handler.
|
|
227
229
|
- Do not publish after a failed or cancelled validation step. Make validation
|
package/docs/api-reference.md
CHANGED
|
@@ -8,14 +8,14 @@ Package: `tubeless`
|
|
|
8
8
|
|
|
9
9
|
| Entrypoint | Declaration | Surface hash | Exported symbols |
|
|
10
10
|
| --------------------- | ---------------------------------- | ------------------------------------------------------------------ | ---------------: |
|
|
11
|
-
| `tubeless` | `./dist/core/pipeline.d.ts` | `
|
|
12
|
-
| `tubeless/cli` | `./dist/cli/cli.d.ts` | `
|
|
11
|
+
| `tubeless` | `./dist/core/pipeline.d.ts` | `84b22a259773f3dcfeb91a3bae96ccef79e4279664946faa25d0219778ef6fd2` | 65 |
|
|
12
|
+
| `tubeless/cli` | `./dist/cli/cli.d.ts` | `fe37491a52df175b666ebffc497f8afea9ad94aa2bb97841b5e7f22e1b71a04c` | 33 |
|
|
13
13
|
| `tubeless/batch` | `./dist/utilities/batch.d.ts` | `6b7fe7d6eec6532cc835505517c3481e4290a2a606c2fddf6c80367f5c76c5f5` | 7 |
|
|
14
14
|
| `tubeless/node` | `./dist/node/node.d.ts` | `06411eb43b8d1b5aca5d51d70e68553cb9065447b250c29382e6036ad9eac52c` | 8 |
|
|
15
15
|
| `tubeless/rate-limit` | `./dist/utilities/rate-limit.d.ts` | `5cd093bb780a19e44b087b01e2b38e06f07e7233c9920988ba399036e319c368` | 1 |
|
|
16
16
|
| `tubeless/retry` | `./dist/utilities/retry.d.ts` | `f91f83f8e31e3e629ed90d1b04656110572ea970187a92369f0908cd75ae8f00` | 4 |
|
|
17
|
-
| `tubeless/project` | `./dist/project/project.d.ts` | `
|
|
18
|
-
| `tubeless/testing` | `./dist/testing/testing.d.ts` | `
|
|
17
|
+
| `tubeless/project` | `./dist/project/project.d.ts` | `316af8da2ed6a5708004ed3d52fb2311a81e19789796bdc926a5902764472a72` | 14 |
|
|
18
|
+
| `tubeless/testing` | `./dist/testing/testing.d.ts` | `6eb6f55eaa2bb1b75a1085dafd5e136dc5d76566dfe405a60b40942a5e40b958` | 7 |
|
|
19
19
|
| `tubeless/tracing` | `./dist/tracing/tracing.d.ts` | `c272c955aab09dcd8cc334ffcea3af5cfda420cecc2881a01e3316e3a38801dd` | 3 |
|
|
20
20
|
|
|
21
21
|
## Symbols
|