@pipeline-builder/pipeline-core 0.0.1
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/LICENSE +202 -0
- package/README.md +69 -0
- package/lib/cdk.d.ts +38 -0
- package/lib/cdk.js +44 -0
- package/lib/config/app-config.d.ts +109 -0
- package/lib/config/app-config.js +197 -0
- package/lib/config/aws-config-cdk.d.ts +49 -0
- package/lib/config/aws-config-cdk.js +65 -0
- package/lib/config/billing-config.d.ts +24 -0
- package/lib/config/billing-config.js +497 -0
- package/lib/config/config-types.d.ts +346 -0
- package/lib/config/config-types.js +4 -0
- package/lib/config/entitlements.d.ts +23 -0
- package/lib/config/entitlements.js +46 -0
- package/lib/config/handler-constants.d.ts +10 -0
- package/lib/config/handler-constants.js +39 -0
- package/lib/config/infrastructure-config.d.ts +66 -0
- package/lib/config/infrastructure-config.js +197 -0
- package/lib/config/server-config.d.ts +53 -0
- package/lib/config/server-config.js +175 -0
- package/lib/config/service-client.d.ts +13 -0
- package/lib/config/service-client.js +20 -0
- package/lib/core/artifact-manager.d.ts +62 -0
- package/lib/core/artifact-manager.js +83 -0
- package/lib/core/id-generator.d.ts +50 -0
- package/lib/core/id-generator.js +50 -0
- package/lib/core/metadata-builder.d.ts +48 -0
- package/lib/core/metadata-builder.js +278 -0
- package/lib/core/metadata-helpers.d.ts +31 -0
- package/lib/core/metadata-helpers.js +55 -0
- package/lib/core/network-types.d.ts +200 -0
- package/lib/core/network-types.js +4 -0
- package/lib/core/network.d.ts +33 -0
- package/lib/core/network.js +112 -0
- package/lib/core/pipeline-helpers.d.ts +61 -0
- package/lib/core/pipeline-helpers.js +563 -0
- package/lib/core/pipeline-types.d.ts +118 -0
- package/lib/core/pipeline-types.js +131 -0
- package/lib/core/role-types.d.ts +254 -0
- package/lib/core/role-types.js +4 -0
- package/lib/core/role.d.ts +14 -0
- package/lib/core/role.js +117 -0
- package/lib/core/security-group-types.d.ts +84 -0
- package/lib/core/security-group-types.js +4 -0
- package/lib/core/security-group.d.ts +14 -0
- package/lib/core/security-group.js +33 -0
- package/lib/handlers/plugin-lookup-handler.d.ts +32 -0
- package/lib/handlers/plugin-lookup-handler.js +292 -0
- package/lib/handlers/pnpm-lock.yaml +12 -0
- package/lib/index.d.ts +45 -0
- package/lib/index.js +53 -0
- package/lib/pipeline/pipeline-builder.d.ts +123 -0
- package/lib/pipeline/pipeline-builder.js +476 -0
- package/lib/pipeline/pipeline-configuration.d.ts +81 -0
- package/lib/pipeline/pipeline-configuration.js +214 -0
- package/lib/pipeline/plugin-lookup.d.ts +131 -0
- package/lib/pipeline/plugin-lookup.js +316 -0
- package/lib/pipeline/plugin-spec.d.ts +138 -0
- package/lib/pipeline/plugin-spec.js +4 -0
- package/lib/pipeline/source-builder.d.ts +62 -0
- package/lib/pipeline/source-builder.js +164 -0
- package/lib/pipeline/source-types.d.ts +221 -0
- package/lib/pipeline/source-types.js +4 -0
- package/lib/pipeline/stage-builder.d.ts +78 -0
- package/lib/pipeline/stage-builder.js +129 -0
- package/lib/pipeline/step-types.d.ts +222 -0
- package/lib/pipeline/step-types.js +4 -0
- package/lib/template/evaluator.d.ts +42 -0
- package/lib/template/evaluator.js +164 -0
- package/lib/template/index.d.ts +34 -0
- package/lib/template/index.js +118 -0
- package/lib/template/metrics.d.ts +10 -0
- package/lib/template/metrics.js +43 -0
- package/lib/template/plugin-resolver.d.ts +8 -0
- package/lib/template/plugin-resolver.js +48 -0
- package/lib/template/tokenizer.d.ts +49 -0
- package/lib/template/tokenizer.js +233 -0
- package/lib/template/topo-sort.d.ts +17 -0
- package/lib/template/topo-sort.js +88 -0
- package/lib/template/validate.d.ts +45 -0
- package/lib/template/validate.js +96 -0
- package/lib/template/walker.d.ts +34 -0
- package/lib/template/walker.js +83 -0
- package/package.json +184 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface TopoNode {
|
|
2
|
+
/** Unique key identifying this node (e.g. source field path) */
|
|
3
|
+
key: string;
|
|
4
|
+
/** Dependency keys that must resolve before this node */
|
|
5
|
+
deps: string[];
|
|
6
|
+
}
|
|
7
|
+
export interface TopoResult {
|
|
8
|
+
ordered: string[];
|
|
9
|
+
cycles: string[][];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Topologically sort a set of nodes by their declared dependency keys.
|
|
13
|
+
* Returns `ordered` in resolution order, plus any detected cycles.
|
|
14
|
+
* Nodes whose deps reference keys not in the node set are treated as
|
|
15
|
+
* depending on "external" values and ordered first (no cycle risk).
|
|
16
|
+
*/
|
|
17
|
+
export declare function topoSort(nodes: TopoNode[]): TopoResult;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Topologically sort a set of nodes by their declared dependency keys.
|
|
5
|
+
* Returns `ordered` in resolution order, plus any detected cycles.
|
|
6
|
+
* Nodes whose deps reference keys not in the node set are treated as
|
|
7
|
+
* depending on "external" values and ordered first (no cycle risk).
|
|
8
|
+
*/
|
|
9
|
+
export function topoSort(nodes) {
|
|
10
|
+
const keys = new Set(nodes.map(n => n.key));
|
|
11
|
+
const graph = new Map();
|
|
12
|
+
const inDegree = new Map();
|
|
13
|
+
// Init
|
|
14
|
+
for (const n of nodes) {
|
|
15
|
+
graph.set(n.key, new Set());
|
|
16
|
+
inDegree.set(n.key, 0);
|
|
17
|
+
}
|
|
18
|
+
// Self-loops short-circuit — detected before topo-sort so single-node
|
|
19
|
+
// cycles are reported even when Kahn's would otherwise accept them.
|
|
20
|
+
const selfLoops = [];
|
|
21
|
+
for (const n of nodes) {
|
|
22
|
+
if (n.deps.includes(n.key))
|
|
23
|
+
selfLoops.push([n.key, n.key]);
|
|
24
|
+
}
|
|
25
|
+
// Edges only between internal nodes (external deps resolve before pass starts)
|
|
26
|
+
for (const n of nodes) {
|
|
27
|
+
for (const dep of n.deps) {
|
|
28
|
+
if (!keys.has(dep))
|
|
29
|
+
continue;
|
|
30
|
+
if (dep === n.key)
|
|
31
|
+
continue; // self-dep → already captured above
|
|
32
|
+
// Edge: dep -> n.key (dep must come first)
|
|
33
|
+
if (!graph.get(dep).has(n.key)) {
|
|
34
|
+
graph.get(dep).add(n.key);
|
|
35
|
+
inDegree.set(n.key, (inDegree.get(n.key) ?? 0) + 1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Kahn's algorithm
|
|
40
|
+
const ordered = [];
|
|
41
|
+
const queue = [];
|
|
42
|
+
for (const [k, d] of inDegree)
|
|
43
|
+
if (d === 0)
|
|
44
|
+
queue.push(k);
|
|
45
|
+
while (queue.length) {
|
|
46
|
+
const k = queue.shift();
|
|
47
|
+
ordered.push(k);
|
|
48
|
+
for (const next of graph.get(k) ?? []) {
|
|
49
|
+
const d = (inDegree.get(next) ?? 0) - 1;
|
|
50
|
+
inDegree.set(next, d);
|
|
51
|
+
if (d === 0)
|
|
52
|
+
queue.push(next);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Detect cycles: any node not in `ordered` is part of a cycle
|
|
56
|
+
const cycles = [...selfLoops];
|
|
57
|
+
if (ordered.length < nodes.length) {
|
|
58
|
+
const remaining = new Set(nodes.map(n => n.key).filter(k => !ordered.includes(k)));
|
|
59
|
+
const visited = new Set();
|
|
60
|
+
for (const start of remaining) {
|
|
61
|
+
if (visited.has(start))
|
|
62
|
+
continue;
|
|
63
|
+
const path = [];
|
|
64
|
+
const cycle = findCycle(start, graph, visited, path, remaining);
|
|
65
|
+
if (cycle)
|
|
66
|
+
cycles.push(cycle);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return { ordered, cycles };
|
|
70
|
+
}
|
|
71
|
+
function findCycle(start, graph, visited, path, remaining) {
|
|
72
|
+
if (path.includes(start)) {
|
|
73
|
+
const idx = path.indexOf(start);
|
|
74
|
+
return [...path.slice(idx), start];
|
|
75
|
+
}
|
|
76
|
+
if (visited.has(start) || !remaining.has(start))
|
|
77
|
+
return null;
|
|
78
|
+
visited.add(start);
|
|
79
|
+
path.push(start);
|
|
80
|
+
for (const next of graph.get(start) ?? []) {
|
|
81
|
+
const cycle = findCycle(next, graph, visited, path, remaining);
|
|
82
|
+
if (cycle)
|
|
83
|
+
return cycle;
|
|
84
|
+
}
|
|
85
|
+
path.pop();
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9wby1zb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RlbXBsYXRlL3RvcG8tc29ydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBY3RDOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxLQUFpQjtJQUN4QyxNQUFNLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDNUMsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7SUFDN0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFFM0MsT0FBTztJQUNQLEtBQUssTUFBTSxDQUFDLElBQUksS0FBSyxFQUFFLENBQUM7UUFDdEIsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQztRQUM1QixRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDekIsQ0FBQztJQUVELHNFQUFzRTtJQUN0RSxvRUFBb0U7SUFDcEUsTUFBTSxTQUFTLEdBQWUsRUFBRSxDQUFDO0lBQ2pDLEtBQUssTUFBTSxDQUFDLElBQUksS0FBSyxFQUFFLENBQUM7UUFDdEIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO1lBQUUsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDN0QsQ0FBQztJQUVELCtFQUErRTtJQUMvRSxLQUFLLE1BQU0sQ0FBQyxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ3RCLEtBQUssTUFBTSxHQUFHLElB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Q2IsS0FBK0IsRUFDL0IsT0FBb0IsRUFDcEIsSUFBYyxFQUNkLFNBQXNCO0lBRXRCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEMsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBQ0QsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUM3RCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25CLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDakIsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQzFDLE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDL0QsSUFBSSxLQUFLO1lBQUUsT0FBTyxLQUFLLENBQUM7SUFDMUIsQ0FBQztJQUNELElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUNYLE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5leHBvcnQgaW50ZXJmYWNlIFRvcG9Ob2RlIHtcbiAgLyoqIFVuaXF1ZSBrZXkgaWRlbnRpZnlpbmcgdGhpcyBub2RlIChlLmcuIHNvdXJjZSBmaWVsZCBwYXRoKSAqL1xuICBrZXk6IHN0cmluZztcbiAgLyoqIERlcGVuZGVuY3kga2V5cyB0aGF0IG11c3QgcmVzb2x2ZSBiZWZvcmUgdGhpcyBub2RlICovXG4gIGRlcHM6IHN0cmluZ1tdO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRvcG9SZXN1bHQge1xuICBvcmRlcmVkOiBzdHJpbmdbXTtcbiAgY3ljbGVzOiBzdHJpbmdbXVtdO1xufVxuXG4vKipcbiAqIFRvcG9sb2dpY2FsbHkgc29ydCBhIHNldCBvZiBub2RlcyBieSB0aGVpciBkZWNsYXJlZCBkZXBlbmRlbmN5IGtleXMuXG4gKiBSZXR1cm5zIGBvcmRlcmVkYCBpbiByZXNvbHV0aW9uIG9yZGVyLCBwbHVzIGFueSBkZXRlY3RlZCBjeWNsZXMuXG4gKiBOb2RlcyB3aG9zZSBkZXBzIHJlZmVyZW5jZSBrZXlzIG5vdCBpbiB0aGUgbm9kZSBzZXQgYXJlIHRyZWF0ZWQgYXNcbiAqIGRlcGVuZGluZyBvbiBcImV4dGVybmFsXCIgdmFsdWVzIGFuZCBvcmRlcmVkIGZpcnN0IChubyBjeWNsZSByaXNrKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvcG9Tb3J0KG5vZGVzOiBUb3BvTm9kZVtdKTogVG9wb1Jlc3VsdCB7XG4gIGNvbnN0IGtleXMgPSBuZXcgU2V0KG5vZGVzLm1hcChuID0+IG4ua2V5KSk7XG4gIGNvbnN0IGdyYXBoID0gbmV3IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+PigpO1xuICBjb25zdCBpbkRlZ3JlZSA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG5cbiAgLy8gSW5pdFxuICBmb3IgKGNvbnN0IG4gb2Ygbm9kZXMpIHtcbiAgICBncmFwaC5zZXQobi5rZXksIG5ldyBTZXQoKSk7XG4gICAgaW5EZWdyZWUuc2V0KG4ua2V5LCAwKTtcbiAgfVxuXG4gIC8vIFNlbGYtbG9vcHMgc2hvcnQtY2lyY3VpdCDigJQgZGV0ZWN0ZWQgYmVmb3JlIHRvcG8tc29ydCBzbyBzaW5nbGUtbm9kZVxuICAvLyBjeWNsZXMgYXJlIHJlcG9ydGVkIGV2ZW4gd2hlbiBLYWhuJ3Mgd291bGQgb3RoZXJ3aXNlIGFjY2VwdCB0aGVtLlxuICBjb25zdCBzZWxmTG9vcHM6IHN0cmluZ1tdW10gPSBbXTtcbiAgZm9yIChjb25zdCBuIG9mIG5vZGVzKSB7XG4gICAgaWYgKG4uZGVwcy5pbmNsdWRlcyhuLmtleSkpIHNlbGZMb29wcy5wdXNoKFtuLmtleSwgbi5rZXldKTtcbiAgfVxuXG4gIC8vIEVkZ2VzIG9ubHkgYmV0d2VlbiBpbnRlcm5hbCBub2RlcyAoZXh0ZXJuYWwgZGVwcyByZXNvbHZlIGJlZm9yZSBwYXNzIHN0YXJ0cylcbiAgZm9yIChjb25zdCBuIG9mIG5vZGVzKSB7XG4gICAgZm9yIChjb25zdCBkZXAgb2Ygbi5kZXBzKSB7XG4gICAgICBpZiAoIWtleXMuaGFzKGRlcCkpIGNvbnRpbnVlO1xuICAgICAgaWYgKGRlcCA9PT0gbi5rZXkpIGNvbnRpbnVlOyAvLyBzZWxmLWRlcCDihpIgYWxyZWFkeSBjYXB0dXJlZCBhYm92ZVxuICAgICAgLy8gRWRnZTogZGVwIC0+IG4ua2V5IChkZXAgbXVzdCBjb21lIGZpcnN0KVxuICAgICAgaWYgKCFncmFwaC5nZXQoZGVwKSEuaGFzKG4ua2V5KSkge1xuICAgICAgICBncmFwaC5nZXQoZGVwKSEuYWRkKG4ua2V5KTtcbiAgICAgICAgaW5EZWdyZWUuc2V0KG4ua2V5LCAoaW5EZWdyZWUuZ2V0KG4ua2V5KSA/PyAwKSArIDEpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIEthaG4ncyBhbGdvcml0aG1cbiAgY29uc3Qgb3JkZXJlZDogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgcXVldWU6IHN0cmluZ1tdID0gW107XG4gIGZvciAoY29uc3QgW2ssIGRdIG9mIGluRGVncmVlKSBpZiAoZCA9PT0gMCkgcXVldWUucHVzaChrKTtcbiAgd2hpbGUgKHF1ZXVlLmxlbmd0aCkge1xuICAgIGNvbnN0IGsgPSBxdWV1ZS5zaGlmdCgpITtcbiAgICBvcmRlcmVkLnB1c2goayk7XG4gICAgZm9yIChjb25zdCBuZXh0IG9mIGdyYXBoLmdldChrKSA/PyBbXSkge1xuICAgICAgY29uc3QgZCA9IChpbkRlZ3JlZS5nZXQobmV4dCkgPz8gMCkgLSAxO1xuICAgICAgaW5EZWdyZWUuc2V0KG5leHQsIGQpO1xuICAgICAgaWYgKGQgPT09IDApIHF1ZXVlLnB1c2gobmV4dCk7XG4gICAgfVxuICB9XG5cbiAgLy8gRGV0ZWN0IGN5Y2xlczogYW55IG5vZGUgbm90IGluIGBvcmRlcmVkYCBpcyBwYXJ0IG9mIGEgY3ljbGVcbiAgY29uc3QgY3ljbGVzOiBzdHJpbmdbXVtdID0gWy4uLnNlbGZMb29wc107XG4gIGlmIChvcmRlcmVkLmxlbmd0aCA8IG5vZGVzLmxlbmd0aCkge1xuICAgIGNvbnN0IHJlbWFpbmluZyA9IG5ldyBTZXQobm9kZXMubWFwKG4gPT4gbi5rZXkpLmZpbHRlcihrID0+ICFvcmRlcmVkLmluY2x1ZGVzKGspKSk7XG4gICAgY29uc3QgdmlzaXRlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3Qgc3RhcnQgb2YgcmVtYWluaW5nKSB7XG4gICAgICBpZiAodmlzaXRlZC5oYXMoc3RhcnQpKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IHBhdGg6IHN0cmluZ1tdID0gW107XG4gICAgICBjb25zdCBjeWNsZSA9IGZpbmRDeWNsZShzdGFydCwgZ3JhcGgsIHZpc2l0ZWQsIHBhdGgsIHJlbWFpbmluZyk7XG4gICAgICBpZiAoY3ljbGUpIGN5Y2xlcy5wdXNoKGN5Y2xlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBvcmRlcmVkLCBjeWNsZXMgfTtcbn1cblxuZnVuY3Rpb24gZmluZEN5Y2xlKFxuICBzdGFydDogc3RyaW5nLFxuICBncmFwaDogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+LFxuICB2aXNpdGVkOiBTZXQ8c3RyaW5nPixcbiAgcGF0aDogc3RyaW5nW10sXG4gIHJlbWFpbmluZzogU2V0PHN0cmluZz4sXG4pOiBzdHJpbmdbXSB8IG51bGwge1xuICBpZiAocGF0aC5pbmNsdWRlcyhzdGFydCkpIHtcbiAgICBjb25zdCBpZHggPSBwYXRoLmluZGV4T2Yoc3RhcnQpO1xuICAgIHJldHVybiBbLi4ucGF0aC5zbGljZShpZHgpLCBzdGFydF07XG4gIH1cbiAgaWYgKHZpc2l0ZWQuaGFzKHN0YXJ0KSB8fCAhcmVtYWluaW5nLmhhcyhzdGFydCkpIHJldHVybiBudWxsO1xuICB2aXNpdGVkLmFkZChzdGFydCk7XG4gIHBhdGgucHVzaChzdGFydCk7XG4gIGZvciAoY29uc3QgbmV4dCBvZiBncmFwaC5nZXQoc3RhcnQpID8/IFtdKSB7XG4gICAgY29uc3QgY3ljbGUgPSBmaW5kQ3ljbGUobmV4dCwgZ3JhcGgsIHZpc2l0ZWQsIHBhdGgsIHJlbWFpbmluZyk7XG4gICAgaWYgKGN5Y2xlKSByZXR1cm4gY3ljbGU7XG4gIH1cbiAgcGF0aC5wb3AoKTtcbiAgcmV0dXJuIG51bGw7XG59XG4iXX0=
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ErrorCode } from '@pipeline-builder/api-core';
|
|
2
|
+
import { type FieldPredicate } from './walker.js';
|
|
3
|
+
export interface TemplateError {
|
|
4
|
+
field: string;
|
|
5
|
+
line?: number;
|
|
6
|
+
col?: number;
|
|
7
|
+
code: ErrorCode;
|
|
8
|
+
message: string;
|
|
9
|
+
path?: string;
|
|
10
|
+
cycle?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface ValidationResult {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
errors: TemplateError[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build a predicate that accepts a template path when its root is in the
|
|
18
|
+
* given allow-list. Used by the validator to check that every `{{ path }}`
|
|
19
|
+
* resolves to a known scope root (`pipeline`, `plugin`, `env`, …).
|
|
20
|
+
*
|
|
21
|
+
* Only the root segment is checked — we don't enforce exact nested-key
|
|
22
|
+
* existence here because metadata / vars keys are user-provided per pipeline
|
|
23
|
+
* and not known at plugin upload time.
|
|
24
|
+
*/
|
|
25
|
+
export declare function allowedScopeRoots(roots: string[]): (path: string[]) => boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Validate all template tokens in a document have well-formed paths and
|
|
28
|
+
* point at allowed scope roots. Returns all errors found — does NOT stop
|
|
29
|
+
* on first.
|
|
30
|
+
*
|
|
31
|
+
* Caller supplies `isTemplatable` (the schema allow-list) and
|
|
32
|
+
* `isKnownPath` (the scope-shape predicate). Template text is parsed
|
|
33
|
+
* fresh on each call.
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateTemplates<T extends object>(doc: T, isTemplatable: FieldPredicate, isKnownPath: (path: string[]) => boolean): ValidationResult;
|
|
36
|
+
/**
|
|
37
|
+
* Detect cycles in a self-referencing document. Caller supplies the
|
|
38
|
+
* templatable predicate and a function to extract the scope-path that
|
|
39
|
+
* each template field writes to (same value used as a key in deps).
|
|
40
|
+
*
|
|
41
|
+
* Example for pipeline.json: the field `metadata.env` writes to scope
|
|
42
|
+
* path `metadata.env`; a template `{{ metadata.region }}` in that field
|
|
43
|
+
* declares a dependency on `metadata.region`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function detectCycles<T extends object>(doc: T, isTemplatable: FieldPredicate, fieldToScopePath: (field: string) => string | null): TemplateError[];
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { ErrorCode } from '@pipeline-builder/api-core';
|
|
4
|
+
import { dependencies } from './evaluator.js';
|
|
5
|
+
import { TokenizerError, tokenize } from './tokenizer.js';
|
|
6
|
+
import { topoSort } from './topo-sort.js';
|
|
7
|
+
import { visitStrings, walkAndBind } from './walker.js';
|
|
8
|
+
/**
|
|
9
|
+
* Build a predicate that accepts a template path when its root is in the
|
|
10
|
+
* given allow-list. Used by the validator to check that every `{{ path }}`
|
|
11
|
+
* resolves to a known scope root (`pipeline`, `plugin`, `env`, …).
|
|
12
|
+
*
|
|
13
|
+
* Only the root segment is checked — we don't enforce exact nested-key
|
|
14
|
+
* existence here because metadata / vars keys are user-provided per pipeline
|
|
15
|
+
* and not known at plugin upload time.
|
|
16
|
+
*/
|
|
17
|
+
export function allowedScopeRoots(roots) {
|
|
18
|
+
const allowed = new Set(roots);
|
|
19
|
+
return (path) => {
|
|
20
|
+
const root = path[0];
|
|
21
|
+
return !!root && allowed.has(root);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validate all template tokens in a document have well-formed paths and
|
|
26
|
+
* point at allowed scope roots. Returns all errors found — does NOT stop
|
|
27
|
+
* on first.
|
|
28
|
+
*
|
|
29
|
+
* Caller supplies `isTemplatable` (the schema allow-list) and
|
|
30
|
+
* `isKnownPath` (the scope-shape predicate). Template text is parsed
|
|
31
|
+
* fresh on each call.
|
|
32
|
+
*/
|
|
33
|
+
export function validateTemplates(doc, isTemplatable, isKnownPath) {
|
|
34
|
+
const errors = [];
|
|
35
|
+
const entries = [];
|
|
36
|
+
// Pass 1: parse every templatable field, collecting parse errors instead
|
|
37
|
+
// of throwing on the first one.
|
|
38
|
+
visitStrings(doc, isTemplatable, (field, source) => {
|
|
39
|
+
try {
|
|
40
|
+
entries.push({ field, tokens: tokenize(source) });
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
if (err instanceof TokenizerError) {
|
|
44
|
+
errors.push({ field, line: err.pos.line, col: err.pos.col, code: ErrorCode.TEMPLATE_PARSE_ERROR, message: err.message });
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
errors.push({ field, code: ErrorCode.TEMPLATE_PARSE_ERROR, message: String(err) });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
// Pass 2: validate each expr's path is shape-allowed and not reserved
|
|
52
|
+
for (const { field, tokens } of entries) {
|
|
53
|
+
for (const tok of tokens) {
|
|
54
|
+
if (tok.kind !== 'expr')
|
|
55
|
+
continue;
|
|
56
|
+
if (tok.path[0] === 'secrets') {
|
|
57
|
+
errors.push(mkErr(field, tok.pos, ErrorCode.TEMPLATE_SECRETS_RESERVED, '\'secrets\' is a reserved scope — use the plugin\'s \'secrets:\' field instead', tok.path.join('.')));
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (!isKnownPath(tok.path)) {
|
|
61
|
+
errors.push(mkErr(field, tok.pos, ErrorCode.TEMPLATE_UNKNOWN_PATH, `Template references unknown scope root '${tok.path[0]}'`, tok.path.join('.')));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return { valid: errors.length === 0, errors };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Detect cycles in a self-referencing document. Caller supplies the
|
|
69
|
+
* templatable predicate and a function to extract the scope-path that
|
|
70
|
+
* each template field writes to (same value used as a key in deps).
|
|
71
|
+
*
|
|
72
|
+
* Example for pipeline.json: the field `metadata.env` writes to scope
|
|
73
|
+
* path `metadata.env`; a template `{{ metadata.region }}` in that field
|
|
74
|
+
* declares a dependency on `metadata.region`.
|
|
75
|
+
*/
|
|
76
|
+
export function detectCycles(doc, isTemplatable, fieldToScopePath) {
|
|
77
|
+
const nodes = [];
|
|
78
|
+
for (const entry of walkAndBind(doc, isTemplatable)) {
|
|
79
|
+
const key = fieldToScopePath(entry.field);
|
|
80
|
+
if (!key)
|
|
81
|
+
continue;
|
|
82
|
+
nodes.push({ key, deps: dependencies(entry.tokens) });
|
|
83
|
+
}
|
|
84
|
+
const { cycles } = topoSort(nodes);
|
|
85
|
+
return cycles.map(c => ({
|
|
86
|
+
field: c[0],
|
|
87
|
+
code: ErrorCode.TEMPLATE_CYCLE,
|
|
88
|
+
message: `Template cycle detected: ${c.join(' -> ')}`,
|
|
89
|
+
cycle: c,
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
// -- helpers -----------------------------------------------------------------
|
|
93
|
+
function mkErr(field, pos, code, message, path) {
|
|
94
|
+
return { field, line: pos.line, col: pos.col, code, message, ...(path && { path }) };
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVtcGxhdGUvdmFsaWRhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDdkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBbUMsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNGLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMxQyxPQUFPLEVBQXVCLFlBQVksRUFBRSxXQUFXLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFpQjdFOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLEtBQWU7SUFDL0MsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0IsT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFO1FBQ2QsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3JCLE9BQU8sQ0FBQyxDQUFDLElBQUksSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JDLENBQUMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FDL0IsR0FBTSxFQUNOLGFBQTZCLEVBQzdCLFdBQXdDO0lBRXhDLE1BQU0sTUFBTSxHQUFvQixFQUFFLENBQUM7SUFDbkMsTUFBTSxPQUFPLEdBQXlDLEVBQUUsQ0FBQztJQUV6RCx5RUFBeUU7SUFDekUsZ0NBQWdDO0lBQ2hDLFlBQVksQ0FBQyxHQUFHLEVBQUUsYUFBYSxFQUFFLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQ2pELElBQUksQ0FBQztZQUNILE9B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Q1osSUFBSSxFQUFFLFNBQVMsQ0FBQyxjQUFjO1FBQzlCLE9BQU8sRUFBRSw0QkFBNEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRTtRQUNyRCxLQUFLLEVBQUUsQ0FBQztLQUNULENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQztBQUVELCtFQUErRTtBQUUvRSxTQUFTLEtBQUssQ0FDWixLQUFhLEVBQ2IsR0FBbUIsRUFDbkIsSUFBZSxFQUNmLE9BQWUsRUFDZixJQUFhO0lBRWIsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDdkYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBFcnJvckNvZGUgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5pbXBvcnQgeyBkZXBlbmRlbmNpZXMgfSBmcm9tICcuL2V2YWx1YXRvci5qcyc7XG5pbXBvcnQgeyB0eXBlIFNvdXJjZVBvc2l0aW9uLCB0eXBlIFRva2VuLCBUb2tlbml6ZXJFcnJvciwgdG9rZW5pemUgfSBmcm9tICcuL3Rva2VuaXplci5qcyc7XG5pbXBvcnQgeyB0b3BvU29ydCB9IGZyb20gJy4vdG9wby1zb3J0LmpzJztcbmltcG9ydCB7IHR5cGUgRmllbGRQcmVkaWNhdGUsIHZpc2l0U3RyaW5ncywgd2Fsa0FuZEJpbmQgfSBmcm9tICcuL3dhbGtlci5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVtcGxhdGVFcnJvciB7XG4gIGZpZWxkOiBzdHJpbmc7XG4gIGxpbmU/OiBudW1iZXI7XG4gIGNvbD86IG51bWJlcjtcbiAgY29kZTogRXJyb3JDb2RlO1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIHBhdGg/OiBzdHJpbmc7XG4gIGN5Y2xlPzogc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmFsaWRhdGlvblJlc3VsdCB7XG4gIHZhbGlkOiBib29sZWFuO1xuICBlcnJvcnM6IFRlbXBsYXRlRXJyb3JbXTtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIHByZWRpY2F0ZSB0aGF0IGFjY2VwdHMgYSB0ZW1wbGF0ZSBwYXRoIHdoZW4gaXRzIHJvb3QgaXMgaW4gdGhlXG4gKiBnaXZlbiBhbGxvdy1saXN0LiBVc2VkIGJ5IHRoZSB2YWxpZGF0b3IgdG8gY2hlY2sgdGhhdCBldmVyeSBge3sgcGF0aCB9fWBcbiAqIHJlc29sdmVzIHRvIGEga25vd24gc2NvcGUgcm9vdCAoYHBpcGVsaW5lYCwgYHBsdWdpbmAsIGBlbnZgLCDigKYpLlxuICpcbiAqIE9ubHkgdGhlIHJvb3Qgc2VnbWVudCBpcyBjaGVja2VkIOKAlCB3ZSBkb24ndCBlbmZvcmNlIGV4YWN0IG5lc3RlZC1rZXlcbiAqIGV4aXN0ZW5jZSBoZXJlIGJlY2F1c2UgbWV0YWRhdGEgLyB2YXJzIGtleXMgYXJlIHVzZXItcHJvdmlkZWQgcGVyIHBpcGVsaW5lXG4gKiBhbmQgbm90IGtub3duIGF0IHBsdWdpbiB1cGxvYWQgdGltZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFsbG93ZWRTY29wZVJvb3RzKHJvb3RzOiBzdHJpbmdbXSk6IChwYXRoOiBzdHJpbmdbXSkgPT4gYm9vbGVhbiB7XG4gIGNvbnN0IGFsbG93ZWQgPSBuZXcgU2V0KHJvb3RzKTtcbiAgcmV0dXJuIChwYXRoKSA9PiB7XG4gICAgY29uc3Qgcm9vdCA9IHBhdGhbMF07XG4gICAgcmV0dXJuICEhcm9vdCAmJiBhbGxvd2VkLmhhcyhyb290KTtcbiAgfTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSBhbGwgdGVtcGxhdGUgdG9rZW5zIGluIGEgZG9jdW1lbnQgaGF2ZSB3ZWxsLWZvcm1lZCBwYXRocyBhbmRcbiAqIHBvaW50IGF0IGFsbG93ZWQgc2NvcGUgcm9vdHMuIFJldHVybnMgYWxsIGVycm9ycyBmb3VuZCDigJQgZG9lcyBOT1Qgc3RvcFxuICogb24gZmlyc3QuXG4gKlxuICogQ2FsbGVyIHN1cHBsaWVzIGBpc1RlbXBsYXRhYmxlYCAodGhlIHNjaGVtYSBhbGxvdy1saXN0KSBhbmRcbiAqIGBpc0tub3duUGF0aGAgKHRoZSBzY29wZS1zaGFwZSBwcmVkaWNhdGUpLiBUZW1wbGF0ZSB0ZXh0IGlzIHBhcnNlZFxuICogZnJlc2ggb24gZWFjaCBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVUZW1wbGF0ZXM8VCBleHRlbmRzIG9iamVjdD4oXG4gIGRvYzogVCxcbiAgaXNUZW1wbGF0YWJsZTogRmllbGRQcmVkaWNhdGUsXG4gIGlzS25vd25QYXRoOiAocGF0aDogc3RyaW5nW10pID0+IGJvb2xlYW4sXG4pOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgY29uc3QgZXJyb3JzOiBUZW1wbGF0ZUVycm9yW10gPSBbXTtcbiAgY29uc3QgZW50cmllczogeyBmaWVsZDogc3RyaW5nOyB0b2tlbnM6IFRva2VuW10gfVtdID0gW107XG5cbiAgLy8gUGFzcyAxOiBwYXJzZSBldmVyeSB0ZW1wbGF0YWJsZSBmaWVsZCwgY29sbGVjdGluZyBwYXJzZSBlcnJvcnMgaW5zdGVhZFxuICAvLyBvZiB0aHJvd2luZyBvbiB0aGUgZmlyc3Qgb25lLlxuICB2aXNpdFN0cmluZ3MoZG9jLCBpc1RlbXBsYXRhYmxlLCAoZmllbGQsIHNvdXJjZSkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBlbnRyaWVzLnB1c2goeyBmaWVsZCwgdG9rZW5zOiB0b2tlbml6ZShzb3VyY2UpIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIFRva2VuaXplckVycm9yKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKHsgZmllbGQsIGxpbmU6IGVyci5wb3MubGluZSwgY29sOiBlcnIucG9zLmNvbCwgY29kZTogRXJyb3JDb2RlLlRFTVBMQVRFX1BBUlNFX0VSUk9SLCBtZXNzYWdlOiBlcnIubWVzc2FnZSB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVycm9ycy5wdXNoKHsgZmllbGQsIGNvZGU6IEVycm9yQ29kZS5URU1QTEFURV9QQVJTRV9FUlJPUiwgbWVzc2FnZTogU3RyaW5nKGVycikgfSk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcblxuICAvLyBQYXNzIDI6IHZhbGlkYXRlIGVhY2ggZXhwcidzIHBhdGggaXMgc2hhcGUtYWxsb3dlZCBhbmQgbm90IHJlc2VydmVkXG4gIGZvciAoY29uc3QgeyBmaWVsZCwgdG9rZW5zIH0gb2YgZW50cmllcykge1xuICAgIGZvciAoY29uc3QgdG9rIG9mIHRva2Vucykge1xuICAgICAgaWYgKHRvay5raW5kICE9PSAnZXhwcicpIGNvbnRpbnVlO1xuICAgICAgaWYgKHRvay5wYXRoWzBdID09PSAnc2VjcmV0cycpIHtcbiAgICAgICAgZXJyb3JzLnB1c2gobWtFcnIoZmllbGQsIHRvay5wb3MsIEVycm9yQ29kZS5URU1QTEFURV9TRUNSRVRTX1JFU0VSVkVELFxuICAgICAgICAgICdcXCdzZWNyZXRzXFwnIGlzIGEgcmVzZXJ2ZWQgc2NvcGUg4oCUIHVzZSB0aGUgcGx1Z2luXFwncyBcXCdzZWNyZXRzOlxcJyBmaWVsZCBpbnN0ZWFkJyxcbiAgICAgICAgICB0b2sucGF0aC5qb2luKCcuJykpKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBpZiAoIWlzS25vd25QYXRoKHRvay5wYXRoKSkge1xuICAgICAgICBlcnJvcnMucHVzaChta0VycihmaWVsZCwgdG9rLnBvcywgRXJyb3JDb2RlLlRFTVBMQVRFX1VOS05PV05fUEFUSCxcbiAgICAgICAgICBgVGVtcGxhdGUgcmVmZXJlbmNlcyB1bmtub3duIHNjb3BlIHJvb3QgJyR7dG9rLnBhdGhbMF19J2AsXG4gICAgICAgICAgdG9rLnBhdGguam9pbignLicpKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgdmFsaWQ6IGVycm9ycy5sZW5ndGggPT09IDAsIGVycm9ycyB9O1xufVxuXG4vKipcbiAqIERldGVjdCBjeWNsZXMgaW4gYSBzZWxmLXJlZmVyZW5jaW5nIGRvY3VtZW50LiBDYWxsZXIgc3VwcGxpZXMgdGhlXG4gKiB0ZW1wbGF0YWJsZSBwcmVkaWNhdGUgYW5kIGEgZnVuY3Rpb24gdG8gZXh0cmFjdCB0aGUgc2NvcGUtcGF0aCB0aGF0XG4gKiBlYWNoIHRlbXBsYXRlIGZpZWxkIHdyaXRlcyB0byAoc2FtZSB2YWx1ZSB1c2VkIGFzIGEga2V5IGluIGRlcHMpLlxuICpcbiAqIEV4YW1wbGUgZm9yIHBpcGVsaW5lLmpzb246IHRoZSBmaWVsZCBgbWV0YWRhdGEuZW52YCB3cml0ZXMgdG8gc2NvcGVcbiAqIHBhdGggYG1ldGFkYXRhLmVudmA7IGEgdGVtcGxhdGUgYHt7IG1ldGFkYXRhLnJlZ2lvbiB9fWAgaW4gdGhhdCBmaWVsZFxuICogZGVjbGFyZXMgYSBkZXBlbmRlbmN5IG9uIGBtZXRhZGF0YS5yZWdpb25gLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGV0ZWN0Q3ljbGVzPFQgZXh0ZW5kcyBvYmplY3Q+KFxuICBkb2M6IFQsXG4gIGlzVGVtcGxhdGFibGU6IEZpZWxkUHJlZGljYXRlLFxuICBmaWVsZFRvU2NvcGVQYXRoOiAoZmllbGQ6IHN0cmluZykgPT4gc3RyaW5nIHwgbnVsbCxcbik6IFRlbXBsYXRlRXJyb3JbXSB7XG4gIGNvbnN0IG5vZGVzID0gW107XG4gIGZvciAoY29uc3QgZW50cnkgb2Ygd2Fsa0FuZEJpbmQoZG9jLCBpc1RlbXBsYXRhYmxlKSkge1xuICAgIGNvbnN0IGtleSA9IGZpZWxkVG9TY29wZVBhdGgoZW50cnkuZmllbGQpO1xuICAgIGlmICgha2V5KSBjb250aW51ZTtcbiAgICBub2Rlcy5wdXNoKHsga2V5LCBkZXBzOiBkZXBlbmRlbmNpZXMoZW50cnkudG9rZW5zKSB9KTtcbiAgfVxuICBjb25zdCB7IGN5Y2xlcyB9ID0gdG9wb1NvcnQobm9kZXMpO1xuICByZXR1cm4gY3ljbGVzLm1hcChjID0+ICh7XG4gICAgZmllbGQ6IGNbMF0hLFxuICAgIGNvZGU6IEVycm9yQ29kZS5URU1QTEFURV9DWUNMRSxcbiAgICBtZXNzYWdlOiBgVGVtcGxhdGUgY3ljbGUgZGV0ZWN0ZWQ6ICR7Yy5qb2luKCcgLT4gJyl9YCxcbiAgICBjeWNsZTogYyxcbiAgfSkpO1xufVxuXG4vLyAtLSBoZWxwZXJzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmZ1bmN0aW9uIG1rRXJyKFxuICBmaWVsZDogc3RyaW5nLFxuICBwb3M6IFNvdXJjZVBvc2l0aW9uLFxuICBjb2RlOiBFcnJvckNvZGUsXG4gIG1lc3NhZ2U6IHN0cmluZyxcbiAgcGF0aD86IHN0cmluZyxcbik6IFRlbXBsYXRlRXJyb3Ige1xuICByZXR1cm4geyBmaWVsZCwgbGluZTogcG9zLmxpbmUsIGNvbDogcG9zLmNvbCwgY29kZSwgbWVzc2FnZSwgLi4uKHBhdGggJiYgeyBwYXRoIH0pIH07XG59XG5cbiJdfQ==
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type Token } from './tokenizer.js';
|
|
2
|
+
export interface WalkEntry {
|
|
3
|
+
/** Dotted path to the field inside the document, e.g. 'commands[3]' or 'env.STAGE' */
|
|
4
|
+
field: string;
|
|
5
|
+
/** Raw source string containing template tokens */
|
|
6
|
+
source: string;
|
|
7
|
+
/** Parsed token stream */
|
|
8
|
+
tokens: Token[];
|
|
9
|
+
/** Setter to write back a resolved value into the original `root` object */
|
|
10
|
+
set: (value: unknown) => void;
|
|
11
|
+
}
|
|
12
|
+
export type FieldPredicate = (field: string) => boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Visit every templatable string leaf under `root`. Calls `handler(field, source)`
|
|
15
|
+
* for each string whose field path satisfies `isTemplatable` and contains `{{`.
|
|
16
|
+
* Does NOT tokenize — callers decide whether to throw or collect errors.
|
|
17
|
+
*/
|
|
18
|
+
export declare function visitStrings(root: unknown, isTemplatable: FieldPredicate, handler: (field: string, source: string, keyPath: Array<string | number>) => void): void;
|
|
19
|
+
/**
|
|
20
|
+
* Walk all templatable string fields under `root`, returning one entry per
|
|
21
|
+
* templated field with a bound `set()` that mutates `root` in place.
|
|
22
|
+
* Tokenization happens eagerly here — parse errors throw.
|
|
23
|
+
*
|
|
24
|
+
* By default only fields containing at least one `{{ expr }}` are returned.
|
|
25
|
+
* Pass `includeLiteralOnly` to also return fields whose only template content
|
|
26
|
+
* is a `{{{{` escape sequence — these still need rewriting so the tokenizer's
|
|
27
|
+
* `{{{{` → `{{` unescape actually materializes into the document.
|
|
28
|
+
*
|
|
29
|
+
* The bound `set()` writes back via the exact key path captured during the
|
|
30
|
+
* walk (the real `Object.entries` keys), so document keys containing `.`,
|
|
31
|
+
* `[`, or `]` (e.g. `env["FOO.BAR"]`) are written correctly rather than being
|
|
32
|
+
* silently dropped by re-parsing a flattened dotted field string.
|
|
33
|
+
*/
|
|
34
|
+
export declare function walkAndBind<T extends object>(root: T, isTemplatable: FieldPredicate, includeLiteralOnly?: boolean): WalkEntry[];
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { hasTemplate, tokenize } from './tokenizer.js';
|
|
4
|
+
/**
|
|
5
|
+
* Visit every templatable string leaf under `root`. Calls `handler(field, source)`
|
|
6
|
+
* for each string whose field path satisfies `isTemplatable` and contains `{{`.
|
|
7
|
+
* Does NOT tokenize — callers decide whether to throw or collect errors.
|
|
8
|
+
*/
|
|
9
|
+
export function visitStrings(root, isTemplatable, handler) {
|
|
10
|
+
step(root, '', [], isTemplatable, handler);
|
|
11
|
+
}
|
|
12
|
+
function step(node, field, keyPath, isTemplatable, handler) {
|
|
13
|
+
if (Array.isArray(node)) {
|
|
14
|
+
node.forEach((child, idx) => step(child, `${field}[${idx}]`, [...keyPath, idx], isTemplatable, handler));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (node !== null && typeof node === 'object') {
|
|
18
|
+
for (const [key, child] of Object.entries(node)) {
|
|
19
|
+
step(child, field ? `${field}.${key}` : key, [...keyPath, key], isTemplatable, handler);
|
|
20
|
+
}
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (typeof node === 'string' && isTemplatable(field) && hasTemplate(node)) {
|
|
24
|
+
handler(field, node, keyPath);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Walk all templatable string fields under `root`, returning one entry per
|
|
29
|
+
* templated field with a bound `set()` that mutates `root` in place.
|
|
30
|
+
* Tokenization happens eagerly here — parse errors throw.
|
|
31
|
+
*
|
|
32
|
+
* By default only fields containing at least one `{{ expr }}` are returned.
|
|
33
|
+
* Pass `includeLiteralOnly` to also return fields whose only template content
|
|
34
|
+
* is a `{{{{` escape sequence — these still need rewriting so the tokenizer's
|
|
35
|
+
* `{{{{` → `{{` unescape actually materializes into the document.
|
|
36
|
+
*
|
|
37
|
+
* The bound `set()` writes back via the exact key path captured during the
|
|
38
|
+
* walk (the real `Object.entries` keys), so document keys containing `.`,
|
|
39
|
+
* `[`, or `]` (e.g. `env["FOO.BAR"]`) are written correctly rather than being
|
|
40
|
+
* silently dropped by re-parsing a flattened dotted field string.
|
|
41
|
+
*/
|
|
42
|
+
export function walkAndBind(root, isTemplatable, includeLiteralOnly = false) {
|
|
43
|
+
const entries = [];
|
|
44
|
+
visitStrings(root, isTemplatable, (field, source, keyPath) => {
|
|
45
|
+
const tokens = tokenize(source);
|
|
46
|
+
if (!includeLiteralOnly && !tokens.some(t => t.kind === 'expr'))
|
|
47
|
+
return;
|
|
48
|
+
entries.push({
|
|
49
|
+
field,
|
|
50
|
+
source,
|
|
51
|
+
tokens,
|
|
52
|
+
set: (value) => writeField(root, keyPath, value),
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
return entries;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Keys that must never be walked into or written through: assigning to
|
|
59
|
+
* `__proto__` / `constructor` / `prototype` could retarget an object's
|
|
60
|
+
* prototype. `Object.entries` yields own enumerable keys only, but a JSON
|
|
61
|
+
* document parsed with `JSON.parse` can carry a genuine own enumerable
|
|
62
|
+
* `__proto__` (or `constructor`) key, so a captured keyPath could contain one.
|
|
63
|
+
* Refuse the write in that case rather than mutating the prototype.
|
|
64
|
+
*/
|
|
65
|
+
const UNSAFE_WRITE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
66
|
+
function writeField(root, parts, value) {
|
|
67
|
+
if (parts.length === 0)
|
|
68
|
+
return;
|
|
69
|
+
for (const p of parts) {
|
|
70
|
+
if (typeof p === 'string' && UNSAFE_WRITE_KEYS.has(p))
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
let cur = root;
|
|
74
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
75
|
+
if (cur == null || typeof cur !== 'object')
|
|
76
|
+
return;
|
|
77
|
+
cur = cur[parts[i]];
|
|
78
|
+
}
|
|
79
|
+
if (cur == null || typeof cur !== 'object')
|
|
80
|
+
return;
|
|
81
|
+
cur[parts[parts.length - 1]] = value;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Fsa2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3RlbXBsYXRlL3dhbGtlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFjLE1BQU0sZ0JBQWdCLENBQUM7QUFlbkU7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxZQUFZLENBQzFCLElBQWEsRUFDYixhQUE2QixFQUM3QixPQUFpRjtJQUVqRixJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQzdDLENBQUM7QUFFRCxTQUFTLElBQUksQ0FDWCxJQUFhLEVBQ2IsS0FBYSxFQUNiLE9BQStCLEVBQy9CLGFBQTZCLEVBQzdCLE9BQWlGO0lBRWpGLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsS0FBSyxJQUFJLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxPQUFPLEVBQUUsR0FBRyxDQUFDLEVBQUUsYUFBYSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDekcsT0FBTztJQUNULENBQUM7SUFDRCxJQUFJLElBQUksS0FBSyxJQUFJLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDOUMsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBK0IsQ0FBQyxFQUFFLENBQUM7WUFDM0UsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxJQUFJLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLENBQUMsRUFBRSxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDMUYsQ0FBQztRQUNELE9BQU87SUFDVCxDQUFDO0lBQ0QsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQzFFLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ2hDLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7O0dBY0c7QUFDSCxNQUFNLFVBQVUsV0FBVyxDQUN6QixJQUFPLEVBQ1AsYUFBNkIsRUFDN0Isa0JBQWtCLEdBQUcsS0FBSztJQUUxQixNQUFNLE9BQU8sR0FBZ0IsRUFBRSxDQUFDO0lBQ2hDLFlBQVksQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRTtRQUMzRCxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLGtCQUFrQixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDO1lBQUUsT0FBTztRQUN4RSxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQ1gsS0FBSztZQUNMLE1BQU07WUFDTixNQUFNO1lBQ04sR0FBRyxFQUFFLENBQUMsS0FBYyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUM7U0FDMUQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDSCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxXQUFXLEVBQUUsYUFBYSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7QUFFN0UsU0FBUyxVQUFVLENBQUMsSUFBYSxFQUFFLEtBQTZCLEVBQUUsS0FBYztJQUM5RSxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU87SUFDL0IsS0FBSyxNQUFNLENBQUMsSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUN0QixJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQUUsT0FBTztJQUNoRSxDQUFDO0lBQ0QsSUFBSSxHQUFHLEdBQVksSUFBSSxDQUFDO0lBQ3hCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQzFDLElBQUksR0FBRyxJQUFJLElBQUksSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRO1lBQUUsT0FBTztRQUNuRCxHQUFHLEdBQUksR0FBd0MsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFFLENBQUMsQ0FBQztJQUM3RCxDQUFDO0lBQ0QsSUFBSSxHQUFHLElBQUksSUFBSSxJQUFJLE9BQU8sR0FBRyxLQUFLLFFBQVE7UUFBRSxPQUFPO0lBQ2xELEdBQXdDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFFLENBQUMsR0FBRyxLQUFLLENBQUM7QUFDOUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBoYXNUZW1wbGF0ZSwgdG9rZW5pemUsIHR5cGUgVG9rZW4gfSBmcm9tICcuL3Rva2VuaXplci5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgV2Fsa0VudHJ5IHtcbiAgLyoqIERvdHRlZCBwYXRoIHRvIHRoZSBmaWVsZCBpbnNpZGUgdGhlIGRvY3VtZW50LCBlLmcuICdjb21tYW5kc1szXScgb3IgJ2Vudi5TVEFHRScgKi9cbiAgZmllbGQ6IHN0cmluZztcbiAgLyoqIFJhdyBzb3VyY2Ugc3RyaW5nIGNvbnRhaW5pbmcgdGVtcGxhdGUgdG9rZW5zICovXG4gIHNvdXJjZTogc3RyaW5nO1xuICAvKiogUGFyc2VkIHRva2VuIHN0cmVhbSAqL1xuICB0b2tlbnM6IFRva2VuW107XG4gIC8qKiBTZXR0ZXIgdG8gd3JpdGUgYmFjayBhIHJlc29sdmVkIHZhbHVlIGludG8gdGhlIG9yaWdpbmFsIGByb290YCBvYmplY3QgKi9cbiAgc2V0OiAodmFsdWU6IHVua25vd24pID0+IHZvaWQ7XG59XG5cbmV4cG9ydCB0eXBlIEZpZWxkUHJlZGljYXRlID0gKGZpZWxkOiBzdHJpbmcpID0+IGJvb2xlYW47XG5cbi8qKlxuICogVmlzaXQgZXZlcnkgdGVtcGxhdGFibGUgc3RyaW5nIGxlYWYgdW5kZXIgYHJvb3RgLiBDYWxscyBgaGFuZGxlcihmaWVsZCwgc291cmNlKWBcbiAqIGZvciBlYWNoIHN0cmluZyB3aG9zZSBmaWVsZCBwYXRoIHNhdGlzZmllcyBgaXNUZW1wbGF0YWJsZWAgYW5kIGNvbnRhaW5zIGB7e2AuXG4gKiBEb2VzIE5PVCB0b2tlbml6ZSDigJQgY2FsbGVycyBkZWNpZGUgd2hldGhlciB0byB0aHJvdyBvciBjb2xsZWN0IGVycm9ycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZpc2l0U3RyaW5ncyhcbiAgcm9vdDogdW5rbm93bixcbiAgaXNUZW1wbGF0YWJsZTogRmllbGRQcmVkaWNhdGUsXG4gIGhhbmRsZXI6IChmaWVsZDogc3RyaW5nLCBzb3VyY2U6IHN0cmluZywga2V5UGF0aDogQXJyYXk8c3RyaW5nIHwgbnVtYmVyPikgPT4gdm9pZCxcbik6IHZvaWQge1xuICBzdGVwKHJvb3QsICcnLCBbXSwgaXNUZW1wbGF0YWJsZSwgaGFuZGxlcik7XG59XG5cbmZ1bmN0aW9uIHN0ZXAoXG4gIG5vZGU6IHVua25vd24sXG4gIGZpZWxkOiBzdHJpbmcsXG4gIGtleVBhdGg6IEFycmF5PHN0cmluZyB8IG51bWJlcj4sXG4gIGlzVGVtcGxhdGFibGU6IEZpZWxkUHJlZGljYXRlLFxuICBoYW5kbGVyOiAoZmllbGQ6IHN0cmluZywgc291cmNlOiBzdHJpbmcsIGtleVBhdGg6IEFycmF5PHN0cmluZyB8IG51bWJlcj4pID0+IHZvaWQsXG4pOiB2b2lkIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkobm9kZSkpIHtcbiAgICBub2RlLmZvckVhY2goKGNoaWxkLCBpZHgpID0+IHN0ZXAoY2hpbGQsIGAke2ZpZWxkfVske2lkeH1dYCwgWy4uLmtleVBhdGgsIGlkeF0sIGlzVGVtcGxhdGFibGUsIGhhbmRsZXIpKTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKG5vZGUgIT09IG51bGwgJiYgdHlwZW9mIG5vZGUgPT09ICdvYmplY3QnKSB7XG4gICAgZm9yIChjb25zdCBba2V5LCBjaGlsZF0gb2YgT2JqZWN0LmVudHJpZXMobm9kZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikpIHtcbiAgICAgIHN0ZXAoY2hpbGQsIGZpZWxkID8gYCR7ZmllbGR9LiR7a2V5fWAgOiBrZXksIFsuLi5rZXlQYXRoLCBrZXldLCBpc1RlbXBsYXRhYmxlLCBoYW5kbGVyKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICh0eXBlb2Ygbm9kZSA9PT0gJ3N0cmluZycgJiYgaXNUZW1wbGF0YWJsZShmaWVsZCkgJiYgaGFzVGVtcGxhdGUobm9kZSkpIHtcbiAgICBoYW5kbGVyKGZpZWxkLCBub2RlLCBrZXlQYXRoKTtcbiAgfVxufVxuXG4vKipcbiAqIFdhbGsgYWxsIHRlbXBsYXRhYmxlIHN0cmluZyBmaWVsZHMgdW5kZXIgYHJvb3RgLCByZXR1cm5pbmcgb25lIGVudHJ5IHBlclxuICogdGVtcGxhdGVkIGZpZWxkIHdpdGggYSBib3VuZCBgc2V0KClgIHRoYXQgbXV0YXRlcyBgcm9vdGAgaW4gcGxhY2UuXG4gKiBUb2tlbml6YXRpb24gaGFwcGVucyBlYWdlcmx5IGhlcmUg4oCUIHBhcnNlIGVycm9ycyB0aHJvdy5cbiAqXG4gKiBCeSBkZWZhdWx0IG9ubHkgZmllbGRzIGNvbnRhaW5pbmcgYXQgbGVhc3Qgb25lIGB7eyBleHByIH19YCBhcmUgcmV0dXJuZWQuXG4gKiBQYXNzIGBpbmNsdWRlTGl0ZXJhbE9ubHlgIHRvIGFsc28gcmV0dXJuIGZpZWxkcyB3aG9zZSBvbmx5IHRlbXBsYXRlIGNvbnRlbnRcbiAqIGlzIGEgYHt7e3tgIGVzY2FwZSBzZXF1ZW5jZSDigJQgdGhlc2Ugc3RpbGwgbmVlZCByZXdyaXRpbmcgc28gdGhlIHRva2VuaXplcidzXG4gKiBge3t7e2Ag4oaSIGB7e2AgdW5lc2NhcGUgYWN0dWFsbHkgbWF0ZXJpYWxpemVzIGludG8gdGhlIGRvY3VtZW50LlxuICpcbiAqIFRoZSBib3VuZCBgc2V0KClgIHdyaXRlcyBiYWNrIHZpYSB0aGUgZXhhY3Qga2V5IHBhdGggY2FwdHVyZWQgZHVyaW5nIHRoZVxuICogd2FsayAodGhlIHJlYWwgYE9iamVjdC5lbnRyaWVzYCBrZXlzKSwgc28gZG9jdW1lbnQga2V5cyBjb250YWluaW5nIGAuYCxcbiAqIGBbYCwgb3IgYF1gIChlLmcuIGBlbnZbXCJGT08uQkFSXCJdYCkgYXJlIHdyaXR0ZW4gY29ycmVjdGx5IHJhdGhlciB0aGFuIGJlaW5nXG4gKiBzaWxlbnRseSBkcm9wcGVkIGJ5IHJlLXBhcnNpbmcgYSBmbGF0dGVuZWQgZG90dGVkIGZpZWxkIHN0cmluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdhbGtBbmRCaW5kPFQgZXh0ZW5kcyBvYmplY3Q+KFxuICByb290OiBULFxuICBpc1RlbXBsYXRhYmxlOiBGaWVsZFByZWRpY2F0ZSxcbiAgaW5jbHVkZUxpdGVyYWxPbmx5ID0gZmFsc2UsXG4pOiBXYWxrRW50cnlbXSB7XG4gIGNvbnN0IGVudHJpZXM6IFdhbGtFbnRyeVtdID0gW107XG4gIHZpc2l0U3RyaW5ncyhyb290LCBpc1RlbXBsYXRhYmxlLCAoZmllbGQsIHNvdXJjZSwga2V5UGF0aCkgPT4ge1xuICAgIGNvbnN0IHRva2VucyA9IHRva2VuaXplKHNvdXJjZSk7XG4gICAgaWYgKCFpbmNsdWRlTGl0ZXJhbE9ubHkgJiYgIXRva2Vucy5zb21lKHQgPT4gdC5raW5kID09PSAnZXhwcicpKSByZXR1cm47XG4gICAgZW50cmllcy5wdXNoKHtcbiAgICAgIGZpZWxkLFxuICAgICAgc291cmNlLFxuICAgICAgdG9rZW5zLFxuICAgICAgc2V0OiAodmFsdWU6IHVua25vd24pID0+IHdyaXRlRmllbGQocm9vdCwga2V5UGF0aCwgdmFsdWUpLFxuICAgIH0pO1xuICB9KTtcbiAgcmV0dXJuIGVudHJpZXM7XG59XG5cbi8qKlxuICogS2V5cyB0aGF0IG11c3QgbmV2ZXIgYmUgd2Fsa2VkIGludG8gb3Igd3JpdHRlbiB0aHJvdWdoOiBhc3NpZ25pbmcgdG9cbiAqIGBfX3Byb3RvX19gIC8gYGNvbnN0cnVjdG9yYCAvIGBwcm90b3R5cGVgIGNvdWxkIHJldGFyZ2V0IGFuIG9iamVjdCdzXG4gKiBwcm90b3R5cGUuIGBPYmplY3QuZW50cmllc2AgeWllbGRzIG93biBlbnVtZXJhYmxlIGtleXMgb25seSwgYnV0IGEgSlNPTlxuICogZG9jdW1lbnQgcGFyc2VkIHdpdGggYEpTT04ucGFyc2VgIGNhbiBjYXJyeSBhIGdlbnVpbmUgb3duIGVudW1lcmFibGVcbiAqIGBfX3Byb3RvX19gIChvciBgY29uc3RydWN0b3JgKSBrZXksIHNvIGEgY2FwdHVyZWQga2V5UGF0aCBjb3VsZCBjb250YWluIG9uZS5cbiAqIFJlZnVzZSB0aGUgd3JpdGUgaW4gdGhhdCBjYXNlIHJhdGhlciB0aGFuIG11dGF0aW5nIHRoZSBwcm90b3R5cGUuXG4gKi9cbmNvbnN0IFVOU0FGRV9XUklURV9LRVlTID0gbmV3IFNldChbJ19fcHJvdG9fXycsICdjb25zdHJ1Y3RvcicsICdwcm90b3R5cGUnXSk7XG5cbmZ1bmN0aW9uIHdyaXRlRmllbGQocm9vdDogdW5rbm93biwgcGFydHM6IEFycmF5PHN0cmluZyB8IG51bWJlcj4sIHZhbHVlOiB1bmtub3duKTogdm9pZCB7XG4gIGlmIChwYXJ0cy5sZW5ndGggPT09IDApIHJldHVybjtcbiAgZm9yIChjb25zdCBwIG9mIHBhcnRzKSB7XG4gICAgaWYgKHR5cGVvZiBwID09PSAnc3RyaW5nJyAmJiBVTlNBRkVfV1JJVEVfS0VZUy5oYXMocCkpIHJldHVybjtcbiAgfVxuICBsZXQgY3VyOiB1bmtub3duID0gcm9vdDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGggLSAxOyBpKyspIHtcbiAgICBpZiAoY3VyID09IG51bGwgfHwgdHlwZW9mIGN1ciAhPT0gJ29iamVjdCcpIHJldHVybjtcbiAgICBjdXIgPSAoY3VyIGFzIFJlY29yZDxzdHJpbmcgfCBudW1iZXIsIHVua25vd24+KVtwYXJ0c1tpXSFdO1xuICB9XG4gIGlmIChjdXIgPT0gbnVsbCB8fCB0eXBlb2YgY3VyICE9PSAnb2JqZWN0JykgcmV0dXJuO1xuICAoY3VyIGFzIFJlY29yZDxzdHJpbmcgfCBudW1iZXIsIHVua25vd24+KVtwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSFdID0gdmFsdWU7XG59XG4iXX0=
|
package/package.json
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pipeline-builder/pipeline-core",
|
|
3
|
+
"description": "AWS CDK construct library for Pipeline Builder: the Builder construct that assembles plugin specs into a CodePipeline stack, PluginLookup custom resource, pipeline/plugin domain types, and shared configuration.",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/mwashburn160/pipeline-builder.git"
|
|
7
|
+
},
|
|
8
|
+
"devDependencies": {
|
|
9
|
+
"@aws-sdk/client-secrets-manager": "3.1101.0",
|
|
10
|
+
"@jest/globals": "30.4.1",
|
|
11
|
+
"@stylistic/eslint-plugin": "^2",
|
|
12
|
+
"@types/aws-lambda": "8.10.162",
|
|
13
|
+
"@types/jsonwebtoken": "9.0.10",
|
|
14
|
+
"@types/node": "26.1.2",
|
|
15
|
+
"@typescript-eslint/eslint-plugin": "^8",
|
|
16
|
+
"@typescript-eslint/parser": "^8",
|
|
17
|
+
"@typescript/native": "npm:typescript@^7.0.2",
|
|
18
|
+
"aws-cdk-lib": "2.263.0",
|
|
19
|
+
"constructs": "10.7.0",
|
|
20
|
+
"copyfiles": "2.4.1",
|
|
21
|
+
"eslint": "^9",
|
|
22
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
23
|
+
"eslint-plugin-import": "^2.32.0",
|
|
24
|
+
"jest": "30.4.2",
|
|
25
|
+
"jest-junit": "^17",
|
|
26
|
+
"ts-jest": "29.4.12",
|
|
27
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"aws-cdk-lib": "^2.263.0",
|
|
31
|
+
"constructs": "^10.5.0"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"axios": "1.19.0",
|
|
35
|
+
"jsonwebtoken": "9.0.3",
|
|
36
|
+
"uuid": "14.0.1",
|
|
37
|
+
"@pipeline-builder/api-core": "0.0.1",
|
|
38
|
+
"@pipeline-builder/pipeline-data": "0.0.1"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"ci-cd",
|
|
42
|
+
"cicd",
|
|
43
|
+
"continuous-delivery",
|
|
44
|
+
"devops",
|
|
45
|
+
"self-service",
|
|
46
|
+
"platform-engineering",
|
|
47
|
+
"internal-developer-platform",
|
|
48
|
+
"developer-platform",
|
|
49
|
+
"aws",
|
|
50
|
+
"aws-cdk",
|
|
51
|
+
"cdk",
|
|
52
|
+
"codepipeline",
|
|
53
|
+
"codebuild",
|
|
54
|
+
"cloudformation",
|
|
55
|
+
"pipeline",
|
|
56
|
+
"pipeline-as-code",
|
|
57
|
+
"infrastructure-as-code",
|
|
58
|
+
"iac",
|
|
59
|
+
"compliance",
|
|
60
|
+
"policy-as-code",
|
|
61
|
+
"governance",
|
|
62
|
+
"golden-paths",
|
|
63
|
+
"multi-tenant",
|
|
64
|
+
"rbac",
|
|
65
|
+
"ai",
|
|
66
|
+
"ai-pipeline-generation",
|
|
67
|
+
"llm",
|
|
68
|
+
"bedrock",
|
|
69
|
+
"plugins",
|
|
70
|
+
"plugin-marketplace",
|
|
71
|
+
"containerized",
|
|
72
|
+
"docker",
|
|
73
|
+
"kubernetes",
|
|
74
|
+
"typescript",
|
|
75
|
+
"cli"
|
|
76
|
+
],
|
|
77
|
+
"engines": {
|
|
78
|
+
"node": ">= 24.14.0"
|
|
79
|
+
},
|
|
80
|
+
"devEngines": {
|
|
81
|
+
"packageManager": {
|
|
82
|
+
"name": "pnpm",
|
|
83
|
+
"version": ">=10",
|
|
84
|
+
"onFail": "ignore"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"main": "lib/index.js",
|
|
88
|
+
"license": "Apache-2.0",
|
|
89
|
+
"homepage": "https://mwashburn160.github.io/pipeline-builder/",
|
|
90
|
+
"publishConfig": {
|
|
91
|
+
"access": "public",
|
|
92
|
+
"registry": "https://registry.npmjs.org/"
|
|
93
|
+
},
|
|
94
|
+
"version": "0.0.1",
|
|
95
|
+
"bugs": {
|
|
96
|
+
"url": "https://github.com/mwashburn160/pipeline-builder/issues"
|
|
97
|
+
},
|
|
98
|
+
"jest": {
|
|
99
|
+
"coverageProvider": "v8",
|
|
100
|
+
"testMatch": [
|
|
101
|
+
"<rootDir>/@(src|test)/**/*(*.)@(spec|test).ts?(x)",
|
|
102
|
+
"<rootDir>/@(src|test)/**/__tests__/**/*.ts?(x)"
|
|
103
|
+
],
|
|
104
|
+
"clearMocks": true,
|
|
105
|
+
"collectCoverage": true,
|
|
106
|
+
"coverageReporters": [
|
|
107
|
+
"json",
|
|
108
|
+
"lcov",
|
|
109
|
+
"clover",
|
|
110
|
+
"cobertura",
|
|
111
|
+
"text"
|
|
112
|
+
],
|
|
113
|
+
"coverageDirectory": "coverage",
|
|
114
|
+
"coveragePathIgnorePatterns": [
|
|
115
|
+
"/node_modules/"
|
|
116
|
+
],
|
|
117
|
+
"testPathIgnorePatterns": [
|
|
118
|
+
"/node_modules/"
|
|
119
|
+
],
|
|
120
|
+
"watchPathIgnorePatterns": [
|
|
121
|
+
"/node_modules/"
|
|
122
|
+
],
|
|
123
|
+
"reporters": [
|
|
124
|
+
"default",
|
|
125
|
+
[
|
|
126
|
+
"jest-junit",
|
|
127
|
+
{
|
|
128
|
+
"outputDirectory": "test-reports"
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
],
|
|
132
|
+
"transform": {
|
|
133
|
+
"^.+\\.[t]sx?$": [
|
|
134
|
+
"ts-jest",
|
|
135
|
+
{
|
|
136
|
+
"useESM": true,
|
|
137
|
+
"tsconfig": "tsconfig.dev.json",
|
|
138
|
+
"diagnostics": {
|
|
139
|
+
"ignoreCodes": [
|
|
140
|
+
151002
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
"extensionsToTreatAsEsm": [
|
|
147
|
+
".ts",
|
|
148
|
+
".tsx"
|
|
149
|
+
],
|
|
150
|
+
"moduleNameMapper": {
|
|
151
|
+
"^uuid$": "<rootDir>/../../jest-uuid-stub.js",
|
|
152
|
+
"^(\\.{1,2}/.*)\\.js$": "$1"
|
|
153
|
+
},
|
|
154
|
+
"maxWorkers": 1
|
|
155
|
+
},
|
|
156
|
+
"types": "lib/index.d.ts",
|
|
157
|
+
"type": "module",
|
|
158
|
+
"exports": {
|
|
159
|
+
".": {
|
|
160
|
+
"types": "./lib/index.d.ts",
|
|
161
|
+
"default": "./lib/index.js"
|
|
162
|
+
},
|
|
163
|
+
"./cdk": {
|
|
164
|
+
"types": "./lib/cdk.d.ts",
|
|
165
|
+
"default": "./lib/cdk.js"
|
|
166
|
+
},
|
|
167
|
+
"./lib/*": "./lib/*",
|
|
168
|
+
"./package.json": "./package.json"
|
|
169
|
+
},
|
|
170
|
+
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"pnpm dlx projen\".",
|
|
171
|
+
"scripts": {
|
|
172
|
+
"build": "pnpm dlx projen build",
|
|
173
|
+
"compile": "pnpm dlx projen compile",
|
|
174
|
+
"default": "pnpm dlx projen default",
|
|
175
|
+
"eslint": "pnpm dlx projen eslint",
|
|
176
|
+
"package": "pnpm dlx projen package",
|
|
177
|
+
"post-compile": "pnpm dlx projen post-compile",
|
|
178
|
+
"pre-compile": "pnpm dlx projen pre-compile",
|
|
179
|
+
"test": "pnpm dlx projen test",
|
|
180
|
+
"test:watch": "pnpm dlx projen test:watch",
|
|
181
|
+
"watch": "pnpm dlx projen watch",
|
|
182
|
+
"projen": "pnpm dlx projen"
|
|
183
|
+
}
|
|
184
|
+
}
|