@ucdjs/pipelines-core 0.0.1-beta.7 → 0.0.1-beta.8

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/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { n as resolveMultipleSourceFiles, r as resolveSourceFiles, t as definePipelineSource } from "./source-EtWCktj_.mjs";
2
- import { n as definePipelineTransform, t as applyTransforms } from "./transform-BGOswbNk.mjs";
1
+ import { n as normalizeRouteOutputs, t as filesystemSink } from "./types-BxE_sFho.mjs";
2
+ import { a as resolveSourceFiles, i as resolveMultipleSourceFiles, n as isPipelineOutputSource, r as pipelineOutputSource, t as definePipelineSource } from "./source-UYQsDb7S.mjs";
3
+ import { n as definePipelineTransform, t as applyTransforms } from "./transform-C7y-ZJKs.mjs";
3
4
  import picomatch from "picomatch";
4
-
5
5
  //#region src/dependencies.ts
6
6
  function parseDependency(dep) {
7
7
  if (dep.startsWith("route:")) {
@@ -12,37 +12,19 @@ function parseDependency(dep) {
12
12
  routeId
13
13
  };
14
14
  }
15
- if (dep.startsWith("artifact:")) {
16
- const rest = dep.slice(9);
17
- const sepIndex = rest.indexOf(":");
18
- if (sepIndex <= 0 || sepIndex >= rest.length - 1) throw new Error(`Invalid dependency format: ${dep}. Expected "route:<id>" or "artifact:<routeId>:<artifactName>"`);
19
- return {
20
- type: "artifact",
21
- routeId: rest.slice(0, sepIndex),
22
- artifactName: rest.slice(sepIndex + 1)
23
- };
24
- }
25
- throw new Error(`Invalid dependency format: ${dep}. Expected "route:<id>" or "artifact:<routeId>:<artifactName>"`);
15
+ throw new Error(`Invalid dependency format: ${dep}. Expected "route:<id>"`);
26
16
  }
27
17
  function isRouteDependency(dep) {
28
18
  return dep.startsWith("route:");
29
19
  }
30
- function isArtifactDependency(dep) {
31
- return dep.startsWith("artifact:");
32
- }
33
20
  function createRouteDependency(routeId) {
34
21
  return `route:${routeId}`;
35
22
  }
36
- function createArtifactDependency(routeId, artifactName) {
37
- return `artifact:${routeId}:${artifactName}`;
38
- }
39
-
40
23
  //#endregion
41
24
  //#region src/dag.ts
42
25
  function buildDAG(routes) {
43
26
  const errors = [];
44
27
  const nodes = /* @__PURE__ */ new Map();
45
- const artifactsByRoute = /* @__PURE__ */ new Map();
46
28
  const seenIds = /* @__PURE__ */ new Map();
47
29
  for (let i = 0; i < routes.length; i++) {
48
30
  const route = routes[i];
@@ -60,65 +42,29 @@ function buildDAG(routes) {
60
42
  errors
61
43
  };
62
44
  const routeIds = new Set(routes.map((r) => r.id));
63
- for (const route of routes) {
64
- const emittedArtifacts = /* @__PURE__ */ new Set();
65
- if (route.emits) for (const artifactName of Object.keys(route.emits)) emittedArtifacts.add(`${route.id}:${artifactName}`);
66
- artifactsByRoute.set(route.id, emittedArtifacts);
67
- nodes.set(route.id, {
68
- id: route.id,
69
- dependencies: /* @__PURE__ */ new Set(),
70
- dependents: /* @__PURE__ */ new Set(),
71
- emittedArtifacts
72
- });
73
- }
45
+ for (const route of routes) nodes.set(route.id, {
46
+ id: route.id,
47
+ dependencies: /* @__PURE__ */ new Set(),
48
+ dependents: /* @__PURE__ */ new Set()
49
+ });
74
50
  for (const route of routes) {
75
51
  const node = nodes.get(route.id);
76
52
  if (!route.depends) continue;
77
53
  for (const dep of route.depends) {
78
54
  const parsed = parseDependency(dep);
79
- if (isRouteDependency(dep)) {
80
- if (!routeIds.has(parsed.routeId)) {
81
- errors.push({
82
- type: "missing-route",
83
- message: `Route "${route.id}" depends on non-existent route "${parsed.routeId}"`,
84
- details: {
85
- routeId: route.id,
86
- dependencyId: parsed.routeId
87
- }
88
- });
89
- continue;
90
- }
91
- node.dependencies.add(parsed.routeId);
92
- nodes.get(parsed.routeId).dependents.add(route.id);
93
- } else if (isArtifactDependency(dep)) {
94
- if (parsed.type !== "artifact") continue;
95
- if (!routeIds.has(parsed.routeId)) {
96
- errors.push({
97
- type: "missing-route",
98
- message: `Route "${route.id}" depends on artifact from non-existent route "${parsed.routeId}"`,
99
- details: {
100
- routeId: route.id,
101
- dependencyId: parsed.routeId
102
- }
103
- });
104
- continue;
105
- }
106
- const routeArtifacts = artifactsByRoute.get(parsed.routeId);
107
- const artifactKey = `${parsed.routeId}:${parsed.artifactName}`;
108
- if (!routeArtifacts?.has(artifactKey)) {
109
- errors.push({
110
- type: "missing-artifact",
111
- message: `Route "${route.id}" depends on non-existent artifact "${parsed.artifactName}" from route "${parsed.routeId}"`,
112
- details: {
113
- routeId: route.id,
114
- dependencyId: artifactKey
115
- }
116
- });
117
- continue;
118
- }
119
- node.dependencies.add(parsed.routeId);
120
- nodes.get(parsed.routeId).dependents.add(route.id);
55
+ if (!routeIds.has(parsed.routeId)) {
56
+ errors.push({
57
+ type: "missing-route",
58
+ message: `Route "${route.id}" depends on non-existent route "${parsed.routeId}"`,
59
+ details: {
60
+ routeId: route.id,
61
+ dependencyId: parsed.routeId
62
+ }
63
+ });
64
+ continue;
121
65
  }
66
+ node.dependencies.add(parsed.routeId);
67
+ nodes.get(parsed.routeId).dependents.add(route.id);
122
68
  }
123
69
  }
124
70
  const cycleResult = detectCycle(nodes);
@@ -201,52 +147,110 @@ function getExecutionLayers(dag) {
201
147
  }
202
148
  return layers;
203
149
  }
204
-
205
150
  //#endregion
206
151
  //#region src/filters.ts
152
+ const FILTER_NODE = Symbol.for("ucdjs.filter-node");
153
+ function setFilterNode(filter, node) {
154
+ Object.defineProperty(filter, FILTER_NODE, {
155
+ value: node,
156
+ enumerable: false,
157
+ configurable: false,
158
+ writable: false
159
+ });
160
+ return filter;
161
+ }
162
+ function getFilterNode(filter) {
163
+ return filter[FILTER_NODE];
164
+ }
165
+ function createPipelineFilter(caller, args, filter) {
166
+ return setFilterNode(filter, {
167
+ type: "filter",
168
+ name: caller.name,
169
+ args
170
+ });
171
+ }
172
+ function serializeNode(filter, insideCombinator = false) {
173
+ const node = getFilterNode(filter);
174
+ if (!node) return "<custom>";
175
+ switch (node.type) {
176
+ case "filter": {
177
+ const args = node.args.map(formatArg).join(", ");
178
+ return `${node.name}(${args})`;
179
+ }
180
+ case "and": {
181
+ const description = node.filters.map((filter) => serializeNode(filter, true)).join(" AND ");
182
+ return insideCombinator ? `(${description})` : description;
183
+ }
184
+ case "or": {
185
+ const description = node.filters.map((filter) => serializeNode(filter, true)).join(" OR ");
186
+ return insideCombinator ? `(${description})` : description;
187
+ }
188
+ case "not": return `NOT ${serializeNode(node.filter, true)}`;
189
+ }
190
+ }
191
+ function formatArg(arg) {
192
+ if (typeof arg === "string") return JSON.stringify(arg);
193
+ if (arg instanceof RegExp) return String(arg);
194
+ if (Array.isArray(arg)) return JSON.stringify(arg);
195
+ return String(arg);
196
+ }
197
+ function getFilterDescription(filter) {
198
+ if (!getFilterNode(filter)) return;
199
+ return serializeNode(filter);
200
+ }
207
201
  function byName(name) {
208
- return (ctx) => ctx.file.name === name;
202
+ return createPipelineFilter(byName, [name], (context) => context.file.name === name);
209
203
  }
210
204
  function byDir(dir) {
211
- return (ctx) => ctx.file.dir === dir;
205
+ return createPipelineFilter(byDir, [dir], (context) => context.file.dir === dir);
212
206
  }
213
207
  function byExt(ext) {
214
- if (ext === "") return (ctx) => ctx.file.ext === "";
215
- const normalizedExt = ext.startsWith(".") ? ext : `.${ext}`;
216
- return (ctx) => ctx.file.ext === normalizedExt;
208
+ const normalizedExt = ext === "" ? "" : ext.startsWith(".") ? ext : `.${ext}`;
209
+ return createPipelineFilter(byExt, [normalizedExt], (context) => context.file.ext === normalizedExt);
217
210
  }
218
211
  function byGlob(pattern) {
219
- const matcher = picomatch(pattern);
220
- return (ctx) => matcher(ctx.file.path);
212
+ const matches = picomatch(pattern);
213
+ return createPipelineFilter(byGlob, [pattern], (context) => matches(context.file.path));
221
214
  }
222
215
  function byPath(pathPattern) {
223
- if (typeof pathPattern === "string") return (ctx) => ctx.file.path === pathPattern;
224
- return (ctx) => pathPattern.test(ctx.file.path);
216
+ if (typeof pathPattern === "string") return createPipelineFilter(byPath, [pathPattern], (context) => context.file.path === pathPattern);
217
+ return createPipelineFilter(byPath, [pathPattern], (context) => pathPattern.test(context.file.path));
225
218
  }
226
219
  function byProp(pattern) {
227
- if (typeof pattern === "string") return (ctx) => ctx.row?.property === pattern;
228
- return (ctx) => !!ctx.row?.property && pattern.test(ctx.row.property);
220
+ if (typeof pattern === "string") return createPipelineFilter(byProp, [pattern], (context) => context.row?.property === pattern);
221
+ return createPipelineFilter(byProp, [pattern], (context) => {
222
+ const property = context.row?.property;
223
+ return property != null && pattern.test(property);
224
+ });
229
225
  }
230
226
  function bySource(sourceIds) {
231
227
  const ids = Array.isArray(sourceIds) ? sourceIds : [sourceIds];
232
- return (ctx) => ctx.source != null && ids.includes(ctx.source.id);
228
+ return createPipelineFilter(bySource, [ids.length === 1 ? ids[0] : ids], (context) => context.source != null && ids.includes(context.source.id));
233
229
  }
234
230
  function and(...filters) {
235
- return (ctx) => filters.every((f) => f(ctx));
231
+ return setFilterNode((context) => filters.every((filter) => filter(context)), {
232
+ type: "and",
233
+ filters
234
+ });
236
235
  }
237
236
  function or(...filters) {
238
- return (ctx) => filters.some((f) => f(ctx));
237
+ return setFilterNode((context) => filters.some((filter) => filter(context)), {
238
+ type: "or",
239
+ filters
240
+ });
239
241
  }
240
242
  function not(filter) {
241
- return (ctx) => !filter(ctx);
243
+ return setFilterNode((context) => !filter(context), {
244
+ type: "not",
245
+ filter
246
+ });
242
247
  }
243
248
  function always() {
244
- return () => true;
249
+ return createPipelineFilter(always, [], () => true);
245
250
  }
246
251
  function never() {
247
- return () => false;
252
+ return createPipelineFilter(never, [], () => false);
248
253
  }
249
-
250
254
  //#endregion
251
255
  //#region src/pipeline.ts
252
256
  /**
@@ -288,7 +292,6 @@ function definePipeline(options) {
288
292
  strict: options.strict ?? false,
289
293
  concurrency: options.concurrency ?? 4,
290
294
  fallback: options.fallback,
291
- onEvent: options.onEvent,
292
295
  dag: dagResult.dag,
293
296
  tags: options.tags ?? []
294
297
  };
@@ -302,13 +305,11 @@ function getPipelineRouteIds(pipeline) {
302
305
  function getPipelineSourceIds(pipeline) {
303
306
  return pipeline.inputs.map((source) => source.id);
304
307
  }
305
-
306
308
  //#endregion
307
309
  //#region src/route.ts
308
310
  function definePipelineRoute(definition) {
309
311
  return definition;
310
312
  }
311
-
312
313
  //#endregion
313
314
  //#region src/utils/arrays.ts
314
315
  /**
@@ -333,6 +334,5 @@ function splitMinFields(line, delimiter, minFields) {
333
334
  const parts = line.split(delimiter);
334
335
  return parts.length >= minFields ? parts : null;
335
336
  }
336
-
337
337
  //#endregion
338
- export { always, and, applyTransforms, buildDAG, byDir, byExt, byGlob, byName, byPath, byProp, bySource, createArtifactDependency, createRouteDependency, definePipeline, definePipelineRoute, definePipelineSource, definePipelineTransform, getExecutionLayers, getPipelineRouteIds, getPipelineSourceIds, isArtifactDependency, isPipelineDefinition, isRouteDependency, never, not, or, parseDependency, resolveMultipleSourceFiles, resolveSourceFiles, splitMinFields, splitTwoFields };
338
+ export { FILTER_NODE, always, and, applyTransforms, buildDAG, byDir, byExt, byGlob, byName, byPath, byProp, bySource, createPipelineFilter, createRouteDependency, definePipeline, definePipelineRoute, definePipelineSource, definePipelineTransform, filesystemSink, getExecutionLayers, getFilterDescription, getPipelineRouteIds, getPipelineSourceIds, isPipelineDefinition, isPipelineOutputSource, isRouteDependency, never, normalizeRouteOutputs, not, or, parseDependency, pipelineOutputSource, resolveMultipleSourceFiles, resolveSourceFiles, splitMinFields, splitTwoFields };
@@ -0,0 +1,17 @@
1
+ import { c as FilesystemOutputSinkDefinition, d as RouteOutputDefinition, f as RouteOutputPathContext, h as normalizeRouteOutputs, l as NormalizedRouteOutputDefinition, m as filesystemSink, p as RouteOutputPathResolver, u as OutputSinkDefinition } from "../route-BT-OXkF-.mjs";
2
+
3
+ //#region src/outputs/resolve.d.ts
4
+ interface ResolvedOutputDestination {
5
+ locator: string;
6
+ displayLocator: string;
7
+ }
8
+ declare const DEFAULT_FALLBACK_OUTPUTS: readonly NormalizedRouteOutputDefinition[];
9
+ declare function getOutputProperty(output: unknown): string | undefined;
10
+ declare function resolveOutputDestination(definition: NormalizedRouteOutputDefinition, ctx: RouteOutputPathContext, resolvePath?: (base: string, relative: string) => string): ResolvedOutputDestination;
11
+ declare function renderOutputPathTemplate(template: string, ctx: RouteOutputPathContext): string;
12
+ declare function propertyToKebab(value: string): string;
13
+ //#endregion
14
+ //#region src/outputs/serialize.d.ts
15
+ declare function serializeOutputValue(value: unknown, format: "json" | "text"): string;
16
+ //#endregion
17
+ export { DEFAULT_FALLBACK_OUTPUTS, type FilesystemOutputSinkDefinition, type NormalizedRouteOutputDefinition, type OutputSinkDefinition, type ResolvedOutputDestination, type RouteOutputDefinition, type RouteOutputPathContext, type RouteOutputPathResolver, filesystemSink, getOutputProperty, normalizeRouteOutputs, propertyToKebab, renderOutputPathTemplate, resolveOutputDestination, serializeOutputValue };
@@ -0,0 +1,73 @@
1
+ import { n as normalizeRouteOutputs, t as filesystemSink } from "../types-BxE_sFho.mjs";
2
+ //#region src/outputs/resolve.ts
3
+ const DEFAULT_FALLBACK_OUTPUTS = [{
4
+ id: "fallback-output",
5
+ format: "json"
6
+ }];
7
+ const KEBAB_WORD_RE = /[a-z0-9]+/g;
8
+ const LEADING_SLASHES_RE = /^\/+/;
9
+ const TEMPLATE_TOKEN_RE = /\{([^{}]+)\}/g;
10
+ function getOutputProperty(output) {
11
+ if (typeof output !== "object" || output == null) return;
12
+ if ("property" in output && typeof output.property === "string") return output.property;
13
+ }
14
+ function resolveOutputDestination(definition, ctx, resolvePath) {
15
+ if (definition.path) {
16
+ const relativeLocator = typeof definition.path === "function" ? definition.path(ctx) : renderOutputPathTemplate(definition.path, ctx);
17
+ return createDestination(definition.sink, relativeLocator, resolvePath);
18
+ }
19
+ const property = ctx.property ?? "output";
20
+ const defaultRelative = `${ctx.routeId}/${propertyToKebab(property)}-${ctx.outputIndex}.${definition.format === "text" ? "txt" : "json"}`;
21
+ return createDestination(definition.sink, defaultRelative, resolvePath);
22
+ }
23
+ function createDestination(sink, relativeLocator, resolvePath) {
24
+ const normalizedRelative = relativeLocator.replaceAll("\\", "/");
25
+ if (normalizedRelative.startsWith("/") || normalizedRelative.split("/").includes("..")) throw new Error(`Output path must stay within the configured sink: "${relativeLocator}"`);
26
+ if (sink?.type === "filesystem") {
27
+ const resolved = sink.baseDir ? resolvePath?.(sink.baseDir, normalizedRelative) ?? `${sink.baseDir}/${normalizedRelative}` : resolvePath?.("", normalizedRelative) ?? normalizedRelative;
28
+ return {
29
+ locator: resolved,
30
+ displayLocator: resolved
31
+ };
32
+ }
33
+ const stripped = normalizedRelative.replace(LEADING_SLASHES_RE, "");
34
+ return {
35
+ locator: `memory://${stripped}`,
36
+ displayLocator: `memory://${stripped}`
37
+ };
38
+ }
39
+ function renderOutputPathTemplate(template, ctx) {
40
+ return template.replaceAll(TEMPLATE_TOKEN_RE, (_match, token) => {
41
+ const [rawKey = "", transform] = String(token).split(":");
42
+ const value = resolveTemplateValue(rawKey, ctx);
43
+ if (value == null) return "";
44
+ const stringValue = String(value);
45
+ switch (transform) {
46
+ case "lower": return stringValue.toLowerCase();
47
+ case "kebab": return propertyToKebab(stringValue);
48
+ default: return stringValue;
49
+ }
50
+ });
51
+ }
52
+ function resolveTemplateValue(key, ctx) {
53
+ switch (key) {
54
+ case "version": return ctx.version;
55
+ case "routeId": return ctx.routeId;
56
+ case "property": return ctx.property;
57
+ case "outputIndex": return ctx.outputIndex;
58
+ case "file.name": return ctx.file.name;
59
+ case "file.path": return ctx.file.path;
60
+ default: return;
61
+ }
62
+ }
63
+ function propertyToKebab(value) {
64
+ return (value.toLowerCase().match(KEBAB_WORD_RE) ?? []).join("-");
65
+ }
66
+ //#endregion
67
+ //#region src/outputs/serialize.ts
68
+ function serializeOutputValue(value, format) {
69
+ if (format === "text") return typeof value === "string" ? value : JSON.stringify(value, null, 2) ?? "null";
70
+ return JSON.stringify(value, null, 2) ?? "null";
71
+ }
72
+ //#endregion
73
+ export { DEFAULT_FALLBACK_OUTPUTS, filesystemSink, getOutputProperty, normalizeRouteOutputs, propertyToKebab, renderOutputPathTemplate, resolveOutputDestination, serializeOutputValue };
@@ -0,0 +1,96 @@
1
+ import { a as ParsedRow, d as ResolvedEntry, l as PipelineLogger, n as FileContext, o as ParserFn, s as PipelineFilter, u as PropertyJson } from "./types-B_R0NiDI.mjs";
2
+ import { a as PipelineTransformDefinition, n as ChainTransforms, t as AnyPipelineTransformDefinition } from "./transform-BkBLzZAP.mjs";
3
+
4
+ //#region src/dependencies.d.ts
5
+ type RouteDependency = `route:${string}`;
6
+ type PipelineDependency = RouteDependency;
7
+ interface ParsedRouteDependency {
8
+ type: "route";
9
+ routeId: string;
10
+ }
11
+ type ParsedDependency = ParsedRouteDependency;
12
+ type ParseDependencyType<T extends string> = T extends `route:${infer RouteId}` ? {
13
+ type: "route";
14
+ routeId: RouteId;
15
+ } : never;
16
+ type ExtractRouteDependencies<T extends readonly PipelineDependency[]> = { [K in keyof T]: T[K] extends `route:${infer RouteId}` ? RouteId : never }[number];
17
+ declare function parseDependency(dep: PipelineDependency): ParsedDependency;
18
+ declare function isRouteDependency(dep: PipelineDependency): dep is RouteDependency;
19
+ declare function createRouteDependency(routeId: string): RouteDependency;
20
+ //#endregion
21
+ //#region src/outputs/types.d.ts
22
+ interface FilesystemOutputSinkDefinition {
23
+ type: "filesystem";
24
+ baseDir?: string;
25
+ }
26
+ type OutputSinkDefinition = FilesystemOutputSinkDefinition;
27
+ interface RouteOutputPathContext {
28
+ version: string;
29
+ routeId: string;
30
+ file: FileContext;
31
+ output: unknown;
32
+ property?: string;
33
+ outputIndex: number;
34
+ }
35
+ type RouteOutputPathResolver = (ctx: RouteOutputPathContext) => string;
36
+ interface RouteOutputDefinition {
37
+ /**
38
+ * Stable identifier for this output destination within the route.
39
+ */
40
+ id?: string;
41
+ /**
42
+ * Destination sink to use when the output should be persisted.
43
+ * When omitted, the output remains available for the run only.
44
+ */
45
+ sink?: OutputSinkDefinition;
46
+ /**
47
+ * Output format used by built-in sinks.
48
+ * @default "json"
49
+ */
50
+ format?: "json" | "text";
51
+ /**
52
+ * Preferred explicit path for the output.
53
+ */
54
+ path?: string | RouteOutputPathResolver;
55
+ }
56
+ declare function filesystemSink(options?: Omit<FilesystemOutputSinkDefinition, "type">): FilesystemOutputSinkDefinition;
57
+ interface NormalizedRouteOutputDefinition {
58
+ id: string;
59
+ sink?: OutputSinkDefinition;
60
+ format: "json" | "text";
61
+ path?: RouteOutputDefinition["path"];
62
+ }
63
+ declare function normalizeRouteOutputs(route: PipelineRouteDefinition): NormalizedRouteOutputDefinition[];
64
+ //#endregion
65
+ //#region src/route.d.ts
66
+ interface ResolveContext<TDepends extends readonly PipelineDependency[] = readonly PipelineDependency[]> {
67
+ version: string;
68
+ file: FileContext;
69
+ logger: PipelineLogger;
70
+ getRouteData: <T = unknown>(routeId: ExtractRouteDependencies<TDepends>) => readonly T[];
71
+ normalizeEntries: (entries: ResolvedEntry[]) => ResolvedEntry[];
72
+ now: () => string;
73
+ }
74
+ type ResolverFn<TOutput = PropertyJson[], TDepends extends readonly PipelineDependency[] = readonly PipelineDependency[]> = (ctx: ResolveContext<TDepends>, rows: AsyncIterable<ParsedRow>) => Promise<TOutput>;
75
+ type PipelineRouteResolver<TDepends extends readonly PipelineDependency[], TTransforms extends readonly AnyPipelineTransformDefinition[], TOutput> = (ctx: ResolveContext<TDepends>, rows: AsyncIterable<TTransforms extends readonly [] ? ParsedRow : ChainTransforms<ParsedRow, TTransforms>>) => Promise<TOutput>;
76
+ interface PipelineRouteDefinition<TId extends string = string, TDepends extends readonly PipelineDependency[] = readonly PipelineDependency[], TTransforms extends readonly AnyPipelineTransformDefinition[] = readonly [], TOutput = PropertyJson[]> {
77
+ id: TId;
78
+ filter: PipelineFilter;
79
+ depends?: TDepends;
80
+ parser: ParserFn;
81
+ transforms?: TTransforms;
82
+ resolver: PipelineRouteResolver<TDepends, TTransforms, TOutput>;
83
+ outputs?: RouteOutputDefinition[];
84
+ cache?: boolean;
85
+ }
86
+ type AnyPipelineRouteDefinition = PipelineRouteDefinition<any, any, any, any>;
87
+ declare function definePipelineRoute<const TId extends string, const TDepends extends readonly PipelineDependency[] = readonly [], const TTransforms extends readonly AnyPipelineTransformDefinition[] = readonly [], TOutput = PropertyJson[]>(definition: PipelineRouteDefinition<TId, TDepends, TTransforms, TOutput>): PipelineRouteDefinition<TId, TDepends, TTransforms, TOutput>;
88
+ type InferRoute<T> = T extends PipelineRouteDefinition<infer TId, infer TDepends, infer TTransforms extends readonly PipelineTransformDefinition<any, any>[], infer TOutput> ? {
89
+ id: TId;
90
+ depends: TDepends;
91
+ transforms: TTransforms;
92
+ output: TOutput;
93
+ } : never;
94
+ type InferRoutesOutput<T extends readonly AnyPipelineRouteDefinition[]> = T[number] extends PipelineRouteDefinition<any, any, any, infer TOutput> ? TOutput extends unknown[] ? TOutput[number] : TOutput : never;
95
+ //#endregion
96
+ export { parseDependency as C, isRouteDependency as S, ParseDependencyType as _, ResolveContext as a, PipelineDependency as b, FilesystemOutputSinkDefinition as c, RouteOutputDefinition as d, RouteOutputPathContext as f, ExtractRouteDependencies as g, normalizeRouteOutputs as h, PipelineRouteDefinition as i, NormalizedRouteOutputDefinition as l, filesystemSink as m, InferRoute as n, ResolverFn as o, RouteOutputPathResolver as p, InferRoutesOutput as r, definePipelineRoute as s, AnyPipelineRouteDefinition as t, OutputSinkDefinition as u, ParsedDependency as v, createRouteDependency as x, ParsedRouteDependency as y };
@@ -1,4 +1,4 @@
1
- import { n as FileContext, s as PipelineFilter } from "./types-T24cxilU.mjs";
1
+ import { l as PipelineLogger, n as FileContext, s as PipelineFilter } from "./types-B_R0NiDI.mjs";
2
2
 
3
3
  //#region src/source.d.ts
4
4
  interface StreamOptions {
@@ -22,16 +22,33 @@ interface PipelineSourceDefinition<TId extends string = string> {
22
22
  backend: SourceBackend;
23
23
  includes?: PipelineFilter;
24
24
  excludes?: PipelineFilter;
25
+ kind?: "standard" | "pipeline-output";
26
+ }
27
+ interface PipelineOutputSourceDefinition<TId extends string = string> extends PipelineSourceDefinition<TId> {
28
+ kind: "pipeline-output";
29
+ pipelineId: string;
30
+ outputId?: string;
25
31
  }
26
32
  interface SourceFileContext extends FileContext {
27
33
  source: {
28
34
  id: string;
29
35
  };
30
36
  }
37
+ interface ResolveSourceContext {
38
+ logger: PipelineLogger;
39
+ }
31
40
  declare function definePipelineSource<const TId extends string>(definition: PipelineSourceDefinition<TId>): PipelineSourceDefinition<TId>;
32
- declare function resolveSourceFiles(source: PipelineSourceDefinition, version: string): Promise<SourceFileContext[]>;
33
- declare function resolveMultipleSourceFiles(sources: PipelineSourceDefinition[] | readonly PipelineSourceDefinition[], version: string): Promise<SourceFileContext[]>;
41
+ declare function pipelineOutputSource<const TId extends string = string>(options: {
42
+ id?: TId;
43
+ pipelineId: string;
44
+ outputId?: string;
45
+ }): PipelineOutputSourceDefinition<TId>;
46
+ declare function isPipelineOutputSource(source: PipelineSourceDefinition): source is PipelineOutputSourceDefinition;
47
+ declare function resolveSourceFiles(source: PipelineSourceDefinition, version: string, {
48
+ logger
49
+ }: ResolveSourceContext): Promise<SourceFileContext[]>;
50
+ declare function resolveMultipleSourceFiles(sources: PipelineSourceDefinition[] | readonly PipelineSourceDefinition[], version: string, context: ResolveSourceContext): Promise<SourceFileContext[]>;
34
51
  type InferSourceId<T> = T extends PipelineSourceDefinition<infer TId> ? TId : never;
35
52
  type InferSourceIds<T extends readonly PipelineSourceDefinition[]> = { [K in keyof T]: InferSourceId<T[K]> }[number];
36
53
  //#endregion
37
- export { SourceBackend as a, definePipelineSource as c, PipelineSourceDefinition as i, resolveMultipleSourceFiles as l, InferSourceId as n, SourceFileContext as o, InferSourceIds as r, StreamOptions as s, FileMetadata as t, resolveSourceFiles as u };
54
+ export { PipelineSourceDefinition as a, SourceFileContext as c, isPipelineOutputSource as d, pipelineOutputSource as f, PipelineOutputSourceDefinition as i, StreamOptions as l, resolveSourceFiles as m, InferSourceId as n, ResolveSourceContext as o, resolveMultipleSourceFiles as p, InferSourceIds as r, SourceBackend as s, FileMetadata as t, definePipelineSource as u };
@@ -0,0 +1,49 @@
1
+ //#region src/source.ts
2
+ function definePipelineSource(definition) {
3
+ return definition;
4
+ }
5
+ const unsupportedPipelineOutputBackend = {
6
+ listFiles: async () => {
7
+ throw new Error("Pipeline output sources are resolved by the executor and cannot be listed directly.");
8
+ },
9
+ readFile: async () => {
10
+ throw new Error("Pipeline output sources are resolved by the executor and cannot be read directly.");
11
+ }
12
+ };
13
+ function pipelineOutputSource(options) {
14
+ return {
15
+ id: options.id ?? `pipeline:${options.pipelineId}${options.outputId ? `:${options.outputId}` : ""}`,
16
+ kind: "pipeline-output",
17
+ pipelineId: options.pipelineId,
18
+ outputId: options.outputId,
19
+ backend: unsupportedPipelineOutputBackend
20
+ };
21
+ }
22
+ function isPipelineOutputSource(source) {
23
+ return source.kind === "pipeline-output";
24
+ }
25
+ async function resolveSourceFiles(source, version, { logger }) {
26
+ if (isPipelineOutputSource(source)) return [];
27
+ return (await source.backend.listFiles(version)).filter((file) => {
28
+ const ctx = {
29
+ file,
30
+ logger
31
+ };
32
+ if (source.includes && !source.includes(ctx)) return false;
33
+ if (source.excludes && source.excludes(ctx)) return false;
34
+ return true;
35
+ }).map((file) => ({
36
+ ...file,
37
+ source: { id: source.id }
38
+ }));
39
+ }
40
+ async function resolveMultipleSourceFiles(sources, version, context) {
41
+ const filesByPath = /* @__PURE__ */ new Map();
42
+ for (const source of sources) {
43
+ const files = await resolveSourceFiles(source, version, context);
44
+ for (const file of files) filesByPath.set(file.path, file);
45
+ }
46
+ return [...filesByPath.values()];
47
+ }
48
+ //#endregion
49
+ export { resolveSourceFiles as a, resolveMultipleSourceFiles as i, isPipelineOutputSource as n, pipelineOutputSource as r, definePipelineSource as t };
@@ -1,5 +1,5 @@
1
- import { n as FileContext } from "../types-T24cxilU.mjs";
2
- import { a as SourceBackend, i as PipelineSourceDefinition } from "../source-Bnjgl99T.mjs";
1
+ import { n as FileContext } from "../types-B_R0NiDI.mjs";
2
+ import { a as PipelineSourceDefinition, s as SourceBackend } from "../source-Bw_42mA2.mjs";
3
3
 
4
4
  //#region src/sources/http.d.ts
5
5
  interface HttpBackendOptions {
@@ -1,5 +1,4 @@
1
- import { t as definePipelineSource } from "../source-EtWCktj_.mjs";
2
-
1
+ import { t as definePipelineSource } from "../source-UYQsDb7S.mjs";
3
2
  //#region src/sources/http.ts
4
3
  const UNICODE_ORG_BASE_URL = "https://www.unicode.org/Public/";
5
4
  function createHttpBackend(options) {
@@ -60,13 +59,12 @@ function createUnicodeOrgSource(id) {
60
59
  });
61
60
  }
62
61
  const unicodeOrgSource = createUnicodeOrgSource();
63
-
64
62
  //#endregion
65
63
  //#region src/sources/memory.ts
66
64
  function getFileContext(version, file) {
67
65
  const path = file.path;
68
66
  const parts = path.split("/");
69
- const name = parts[parts.length - 1];
67
+ const name = parts.at(-1);
70
68
  if (!name) throw new Error(`Invalid file path: ${file.path}`);
71
69
  const extIndex = name.lastIndexOf(".");
72
70
  const ext = extIndex >= 0 ? name.slice(extIndex) : "";
@@ -108,6 +106,5 @@ function createMemorySource(options) {
108
106
  backend: createMemoryBackend({ files: options?.files ?? {} })
109
107
  });
110
108
  }
111
-
112
109
  //#endregion
113
- export { UNICODE_ORG_BASE_URL, createHttpBackend, createHttpSource, createMemoryBackend, createMemorySource, createUnicodeOrgSource, unicodeOrgSource };
110
+ export { UNICODE_ORG_BASE_URL, createHttpBackend, createHttpSource, createMemoryBackend, createMemorySource, createUnicodeOrgSource, unicodeOrgSource };