@fluidgrids/workflows 0.0.0-stage → 2026.1027.0
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 +9 -0
- package/README.md +187 -2
- package/dist/assemble-BJo9TECS.d.cts +569 -0
- package/dist/assemble-DMOuaxRI.d.ts +569 -0
- package/dist/chunk-265J2FCH.cjs +33 -0
- package/dist/chunk-27HASETB.cjs +250 -0
- package/dist/chunk-4DPEGDPW.js +74 -0
- package/dist/chunk-5LUIDMF4.js +42 -0
- package/dist/chunk-AU3YW7FZ.cjs +279 -0
- package/dist/chunk-BWSLWF2E.js +722 -0
- package/dist/chunk-BYJ7QTLY.cjs +76 -0
- package/dist/chunk-G4UEPUGO.cjs +46 -0
- package/dist/chunk-GO34UHSY.js +95 -0
- package/dist/chunk-IZQNUNSU.cjs +931 -0
- package/dist/chunk-KUTMY2IO.cjs +745 -0
- package/dist/chunk-LMX35GNQ.js +893 -0
- package/dist/chunk-LRM6JXJA.cjs +181 -0
- package/dist/chunk-LSKSBVL4.cjs +102 -0
- package/dist/chunk-LUXCXFOE.cjs +269 -0
- package/dist/chunk-PL73GJR4.js +174 -0
- package/dist/chunk-REV7ZOA4.js +170 -0
- package/dist/chunk-RRQ5HOBF.cjs +185 -0
- package/dist/chunk-S34NJE3A.js +262 -0
- package/dist/chunk-SRQRLWOS.js +31 -0
- package/dist/chunk-SS4LT2IP.js +268 -0
- package/dist/chunk-X4HKU3MX.js +244 -0
- package/dist/codegen/index.cjs +18 -0
- package/dist/codegen/index.d.cts +15 -0
- package/dist/codegen/index.d.ts +15 -0
- package/dist/codegen/index.js +5 -0
- package/dist/expressions-DhHaqyar.d.cts +62 -0
- package/dist/expressions-DhHaqyar.d.ts +62 -0
- package/dist/hash-CZkTXPCX.d.cts +15 -0
- package/dist/hash-CZkTXPCX.d.ts +15 -0
- package/dist/index.cjs +117 -0
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +4 -0
- package/dist/ir/index.cjs +1244 -0
- package/dist/ir/index.d.cts +828 -0
- package/dist/ir/index.d.ts +828 -0
- package/dist/ir/index.js +1120 -0
- package/dist/lower-DcOY8ux0.d.cts +49 -0
- package/dist/lower-Dw5grNrI.d.ts +49 -0
- package/dist/manifest-Bp9ZJlav.d.ts +60 -0
- package/dist/manifest-Duf-gHdO.d.cts +60 -0
- package/dist/node-evaluator-2GTUZVPK.cjs +17 -0
- package/dist/node-evaluator-RMYEWCXZ.js +8 -0
- package/dist/quickjs/index.cjs +92 -0
- package/dist/quickjs/index.d.cts +18 -0
- package/dist/quickjs/index.d.ts +18 -0
- package/dist/quickjs/index.js +90 -0
- package/dist/roundtrip/index.cjs +1375 -0
- package/dist/roundtrip/index.d.cts +287 -0
- package/dist/roundtrip/index.d.ts +287 -0
- package/dist/roundtrip/index.js +1328 -0
- package/dist/types-Dr2Fn1Ax.d.cts +225 -0
- package/dist/types-Dr2Fn1Ax.d.ts +225 -0
- package/package.json +117 -4
- package/schema/ir-v2.schema.json +655 -0
|
@@ -0,0 +1,1375 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkBYJ7QTLY_cjs = require('../chunk-BYJ7QTLY.cjs');
|
|
4
|
+
var chunkIZQNUNSU_cjs = require('../chunk-IZQNUNSU.cjs');
|
|
5
|
+
var chunkLSKSBVL4_cjs = require('../chunk-LSKSBVL4.cjs');
|
|
6
|
+
var chunk265J2FCH_cjs = require('../chunk-265J2FCH.cjs');
|
|
7
|
+
var chunkLUXCXFOE_cjs = require('../chunk-LUXCXFOE.cjs');
|
|
8
|
+
var chunkKUTMY2IO_cjs = require('../chunk-KUTMY2IO.cjs');
|
|
9
|
+
var chunkAU3YW7FZ_cjs = require('../chunk-AU3YW7FZ.cjs');
|
|
10
|
+
require('../chunk-G4UEPUGO.cjs');
|
|
11
|
+
var chunkRRQ5HOBF_cjs = require('../chunk-RRQ5HOBF.cjs');
|
|
12
|
+
var chunk27HASETB_cjs = require('../chunk-27HASETB.cjs');
|
|
13
|
+
var chunkLRM6JXJA_cjs = require('../chunk-LRM6JXJA.cjs');
|
|
14
|
+
|
|
15
|
+
// src/roundtrip/plan.ts
|
|
16
|
+
var TYPED_HANDLES = {
|
|
17
|
+
if: ["true", "false"],
|
|
18
|
+
loop: ["loop", "done"],
|
|
19
|
+
validate: ["valid", "invalid"],
|
|
20
|
+
sendAndWait: ["approved", "declined", "timedOut"],
|
|
21
|
+
waitForSignal: ["received", "timedOut"],
|
|
22
|
+
compareDatasets: ["inAOnly", "inBOnly", "same", "different"],
|
|
23
|
+
switch: ["default"]
|
|
24
|
+
};
|
|
25
|
+
var HANDLE_PROPERTY = {
|
|
26
|
+
loop: { loop: "body", done: "done" }
|
|
27
|
+
};
|
|
28
|
+
var HELPER_METHODS = {
|
|
29
|
+
"internal:if": "if",
|
|
30
|
+
"internal:switch": "switch",
|
|
31
|
+
"internal:loop": "loop",
|
|
32
|
+
"internal:merge": "merge",
|
|
33
|
+
"internal:wait": "wait",
|
|
34
|
+
"internal:wait-for-signal": "waitForSignal",
|
|
35
|
+
"internal:send-and-wait": "sendAndWait",
|
|
36
|
+
"internal:subworkflow": "subworkflow",
|
|
37
|
+
"internal:validate": "validate",
|
|
38
|
+
"internal:compare-datasets": "compareDatasets",
|
|
39
|
+
"internal:set": "set",
|
|
40
|
+
"internal:filter": "filter",
|
|
41
|
+
"internal:aggregate": "aggregate",
|
|
42
|
+
"internal:split-out": "splitOut",
|
|
43
|
+
"internal:limit": "limit",
|
|
44
|
+
"internal:dedupe": "dedupe",
|
|
45
|
+
"internal:sort": "sort",
|
|
46
|
+
"internal:datatable": "dataTable",
|
|
47
|
+
"internal:http": "http",
|
|
48
|
+
"internal:code": "code",
|
|
49
|
+
"internal:transform": "transform",
|
|
50
|
+
"internal:log": "log",
|
|
51
|
+
"internal:respond-to-webhook": "respondToWebhook",
|
|
52
|
+
"internal:error": "stopAndError",
|
|
53
|
+
"internal:noop": "noop"
|
|
54
|
+
};
|
|
55
|
+
var INTERNAL_DESCRIPTOR_NAMES = {
|
|
56
|
+
"internal:code-workflow": "codeWorkflow"
|
|
57
|
+
};
|
|
58
|
+
var TRIGGER_NAMES = {
|
|
59
|
+
"internal:api": "api",
|
|
60
|
+
"internal:schedule": "schedule",
|
|
61
|
+
"internal:webhook": "webhook",
|
|
62
|
+
"internal:form": "form",
|
|
63
|
+
"internal:error-trigger": "errorTrigger",
|
|
64
|
+
"internal:workflow-call": "workflowCall",
|
|
65
|
+
"internal:rss-feed": "rssFeed",
|
|
66
|
+
"internal:http-poll": "httpPoll",
|
|
67
|
+
"internal:database-poll": "databasePoll",
|
|
68
|
+
"internal:email-imap": "emailImap",
|
|
69
|
+
"internal:file-upload": "fileUpload",
|
|
70
|
+
"internal:record-change": "recordChange",
|
|
71
|
+
"internal:state-change": "stateChange"
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// src/roundtrip/build-plan.ts
|
|
75
|
+
var LiftError = class extends Error {
|
|
76
|
+
constructor(message) {
|
|
77
|
+
super(message);
|
|
78
|
+
this.name = "LiftError";
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
var RULE_METHOD_BY_OPERATOR = new Map(
|
|
82
|
+
Object.entries(chunkRRQ5HOBF_cjs.PREDICATE_OPERATORS).map(([method, spec]) => [
|
|
83
|
+
spec.operator,
|
|
84
|
+
{ method, unary: spec.unary }
|
|
85
|
+
])
|
|
86
|
+
);
|
|
87
|
+
function literalOrStructure(value2) {
|
|
88
|
+
if (Array.isArray(value2)) return { k: "array", items: value2.map(literalOrStructure) };
|
|
89
|
+
if (chunkLRM6JXJA_cjs.isRecord(value2))
|
|
90
|
+
return {
|
|
91
|
+
k: "object",
|
|
92
|
+
entries: Object.entries(value2).map(([key, child]) => [key, literalOrStructure(child)])
|
|
93
|
+
};
|
|
94
|
+
if (value2 === null || typeof value2 === "string" || typeof value2 === "number" || typeof value2 === "boolean") {
|
|
95
|
+
return { k: "literal", value: value2 };
|
|
96
|
+
}
|
|
97
|
+
throw new LiftError(`A ${typeof value2} cannot appear in a workflow definition`);
|
|
98
|
+
}
|
|
99
|
+
function expressible(ref) {
|
|
100
|
+
return ref.path.every(
|
|
101
|
+
(segment) => segment.kind === "index" || !chunkRRQ5HOBF_cjs.RESERVED_REF_KEYS.has(segment.key)
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
function toPlanRef(ref) {
|
|
105
|
+
const target = ref.root.kind === "node" ? { kind: "node", nodeId: ref.root.nodeId } : { kind: ref.root.kind };
|
|
106
|
+
return { target, path: ref.path };
|
|
107
|
+
}
|
|
108
|
+
function liftValue(value2, path, nodeId, items) {
|
|
109
|
+
if (typeof value2 === "string") {
|
|
110
|
+
const parts = chunkLRM6JXJA_cjs.parseTemplate(value2);
|
|
111
|
+
if (parts && parts.every((part) => part.kind === "text" || expressible(part.ref))) {
|
|
112
|
+
const [only] = parts;
|
|
113
|
+
if (parts.length === 1 && only?.kind === "ref") return { k: "ref", ref: toPlanRef(only.ref) };
|
|
114
|
+
return {
|
|
115
|
+
k: "template",
|
|
116
|
+
parts: parts.map(
|
|
117
|
+
(part) => part.kind === "text" ? { text: part.text } : { ref: toPlanRef(part.ref) }
|
|
118
|
+
)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (/\{\{[\s\S]*?\}\}/.test(value2)) {
|
|
122
|
+
items.push({
|
|
123
|
+
nodeId,
|
|
124
|
+
path,
|
|
125
|
+
kind: "expression-verbatim",
|
|
126
|
+
detail: `${value2.slice(0, 120)} kept as a string; not statically typed`
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (/\$\{[\s\S]*?\}/.test(value2)) {
|
|
130
|
+
items.push({ nodeId, path, kind: "legacy-syntax", detail: "${\u2026} template kept verbatim" });
|
|
131
|
+
}
|
|
132
|
+
return { k: "literal", value: value2 };
|
|
133
|
+
}
|
|
134
|
+
if (Array.isArray(value2))
|
|
135
|
+
return {
|
|
136
|
+
k: "array",
|
|
137
|
+
items: value2.map((item, index) => liftValue(item, `${path}[${index}]`, nodeId, items))
|
|
138
|
+
};
|
|
139
|
+
if (chunkLRM6JXJA_cjs.isRecord(value2)) {
|
|
140
|
+
return {
|
|
141
|
+
k: "object",
|
|
142
|
+
entries: Object.entries(value2).map(([key, child]) => [
|
|
143
|
+
key,
|
|
144
|
+
liftValue(child, `${path}.${key}`, nodeId, items)
|
|
145
|
+
])
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
return literalOrStructure(value2);
|
|
149
|
+
}
|
|
150
|
+
function liftState(type, state, nodeId, items) {
|
|
151
|
+
if (type !== "internal:code" || typeof state["code"] !== "string")
|
|
152
|
+
return liftValue(state, "args.state", nodeId, items);
|
|
153
|
+
return {
|
|
154
|
+
k: "object",
|
|
155
|
+
entries: Object.entries(state).map(([key, child]) => [
|
|
156
|
+
key,
|
|
157
|
+
key === "code" ? literalOrStructure(child) : liftValue(child, `args.state.${key}`, nodeId, items)
|
|
158
|
+
])
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function fieldRef(field, nodeIds) {
|
|
162
|
+
const segments = field.split(".");
|
|
163
|
+
const toPath = (parts) => {
|
|
164
|
+
if (parts.some((part) => part === "")) return void 0;
|
|
165
|
+
return parts.map(
|
|
166
|
+
(part) => /^(0|[1-9][0-9]{0,8})$/.test(part) ? { kind: "index", index: Number(part) } : { kind: "key", key: part }
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
if (segments[0] === "WorkflowState" && segments.length >= 2) {
|
|
170
|
+
const nodeId = segments[1] ?? "";
|
|
171
|
+
if (!nodeIds.has(nodeId)) return void 0;
|
|
172
|
+
const path = toPath(segments.slice(2));
|
|
173
|
+
return path ? { target: { kind: "node", nodeId }, path } : void 0;
|
|
174
|
+
}
|
|
175
|
+
if (segments[0] === "output") {
|
|
176
|
+
const path = toPath(segments.slice(1));
|
|
177
|
+
return path ? { target: { kind: "json" }, path } : void 0;
|
|
178
|
+
}
|
|
179
|
+
return void 0;
|
|
180
|
+
}
|
|
181
|
+
function liftRule(rule, nodeIds) {
|
|
182
|
+
const keys = Object.keys(rule).sort();
|
|
183
|
+
const allowed = ["field", "operator", "type", "value"];
|
|
184
|
+
if (!keys.every((key) => allowed.includes(key)) || rule["type"] !== "rule") return void 0;
|
|
185
|
+
if (typeof rule["field"] !== "string" || typeof rule["operator"] !== "string" || rule["operator"] === "")
|
|
186
|
+
return void 0;
|
|
187
|
+
const ref = fieldRef(rule["field"], nodeIds);
|
|
188
|
+
if (!ref || !ref.path.every((segment) => segment.kind === "index" || !chunkRRQ5HOBF_cjs.RESERVED_REF_KEYS.has(segment.key))) {
|
|
189
|
+
return void 0;
|
|
190
|
+
}
|
|
191
|
+
const hasValue = Object.hasOwn(rule, "value");
|
|
192
|
+
const value2 = rule["value"];
|
|
193
|
+
if (hasValue && !(value2 === null || ["string", "number", "boolean"].includes(typeof value2)))
|
|
194
|
+
return void 0;
|
|
195
|
+
const known = RULE_METHOD_BY_OPERATOR.get(rule["operator"]);
|
|
196
|
+
const method = known && known.unary === !hasValue ? known.method : "is";
|
|
197
|
+
return {
|
|
198
|
+
k: "rule",
|
|
199
|
+
ref,
|
|
200
|
+
method,
|
|
201
|
+
operator: rule["operator"],
|
|
202
|
+
hasValue,
|
|
203
|
+
...hasValue ? { value: value2 } : {}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function liftCondition(tree, nodeIds, top) {
|
|
207
|
+
if (!chunkLRM6JXJA_cjs.isRecord(tree)) return void 0;
|
|
208
|
+
if (tree["type"] === "rule") return top ? void 0 : liftRule(tree, nodeIds);
|
|
209
|
+
if (tree["type"] !== "group") return void 0;
|
|
210
|
+
const keys = Object.keys(tree).sort();
|
|
211
|
+
if (keys.join(",") !== "children,combinator,type") return void 0;
|
|
212
|
+
const combinator = tree["combinator"];
|
|
213
|
+
if (combinator !== "AND" && combinator !== "OR") return void 0;
|
|
214
|
+
const children = tree["children"];
|
|
215
|
+
if (!Array.isArray(children) || children.length === 0) return void 0;
|
|
216
|
+
const plan = children.map((child) => liftCondition(child, nodeIds, false));
|
|
217
|
+
if (!plan.every((child) => child !== void 0)) return void 0;
|
|
218
|
+
if (top && combinator === "AND" && plan.length === 1 && plan[0]?.k === "rule") return plan[0];
|
|
219
|
+
return { k: "group", combinator: combinator === "AND" ? "and" : "or", children: plan };
|
|
220
|
+
}
|
|
221
|
+
function handleAccessor(method, handle) {
|
|
222
|
+
if (method && TYPED_HANDLES[method]?.includes(handle)) {
|
|
223
|
+
return { kind: "property", name: HANDLE_PROPERTY[method]?.[handle] ?? handle };
|
|
224
|
+
}
|
|
225
|
+
if (method === "switch") return { kind: "case" };
|
|
226
|
+
return { kind: "generic" };
|
|
227
|
+
}
|
|
228
|
+
function edgeSourceExpr(edge2, info) {
|
|
229
|
+
const source = String(edge2["source"]);
|
|
230
|
+
if (typeof edge2["sourceHandle"] === "string") {
|
|
231
|
+
return {
|
|
232
|
+
k: "handle",
|
|
233
|
+
nodeId: source,
|
|
234
|
+
handle: edge2["sourceHandle"],
|
|
235
|
+
accessor: handleAccessor(info.get(source)?.method, edge2["sourceHandle"])
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return { k: "node", nodeId: source };
|
|
239
|
+
}
|
|
240
|
+
function richEdge(edge2, info, items) {
|
|
241
|
+
const source = String(edge2["source"]);
|
|
242
|
+
const target = String(edge2["target"]);
|
|
243
|
+
const sourceHandle = typeof edge2["sourceHandle"] === "string" ? edge2["sourceHandle"] : void 0;
|
|
244
|
+
const targetHandle = typeof edge2["targetHandle"] === "string" ? edge2["targetHandle"] : void 0;
|
|
245
|
+
const options2 = [];
|
|
246
|
+
const extra = [];
|
|
247
|
+
if (edge2["id"] === void 0) options2.push(["id", { k: "literal", value: false }]);
|
|
248
|
+
else if (edge2["id"] !== chunkKUTMY2IO_cjs.defaultEdgeId(source, target, sourceHandle, targetHandle))
|
|
249
|
+
options2.push(["id", literalOrStructure(edge2["id"])]);
|
|
250
|
+
if (edge2["type"] === void 0) options2.push(["type", { k: "literal", value: false }]);
|
|
251
|
+
else if (edge2["type"] !== "deletable") options2.push(["type", literalOrStructure(edge2["type"])]);
|
|
252
|
+
if (targetHandle !== void 0)
|
|
253
|
+
options2.push(["targetHandle", { k: "literal", value: targetHandle }]);
|
|
254
|
+
for (const [key, value2] of Object.entries(edge2)) {
|
|
255
|
+
if (["id", "source", "target", "sourceHandle", "targetHandle", "type"].includes(key)) {
|
|
256
|
+
if ((key === "sourceHandle" || key === "targetHandle") && typeof value2 !== "string")
|
|
257
|
+
extra.push([key, literalOrStructure(value2)]);
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (key === "label" && typeof value2 === "string")
|
|
261
|
+
options2.push(["label", { k: "literal", value: value2 }]);
|
|
262
|
+
else if ((key === "data" || key === "mapping") && chunkLRM6JXJA_cjs.isRecord(value2)) {
|
|
263
|
+
options2.push([key, literalOrStructure(value2)]);
|
|
264
|
+
if (key === "mapping") {
|
|
265
|
+
items.push({
|
|
266
|
+
nodeId: target,
|
|
267
|
+
path: `edges[${String(edge2["id"] ?? `${source}->${target}`)}].mapping`,
|
|
268
|
+
kind: "legacy-syntax",
|
|
269
|
+
detail: "Edge mapping kept verbatim"
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
} else extra.push([key, literalOrStructure(value2)]);
|
|
273
|
+
}
|
|
274
|
+
if (extra.length > 0) options2.push(["extra", { k: "object", entries: extra }]);
|
|
275
|
+
const from = edgeSourceExpr(edge2, info);
|
|
276
|
+
return options2.length === 0 ? from : { k: "edge", from, options: options2 };
|
|
277
|
+
}
|
|
278
|
+
function rawEdge(edge2) {
|
|
279
|
+
const options2 = [
|
|
280
|
+
[
|
|
281
|
+
"id",
|
|
282
|
+
edge2["id"] === void 0 ? { k: "literal", value: false } : literalOrStructure(edge2["id"])
|
|
283
|
+
]
|
|
284
|
+
];
|
|
285
|
+
if (typeof edge2["type"] === "string")
|
|
286
|
+
options2.push(["type", { k: "literal", value: edge2["type"] }]);
|
|
287
|
+
else options2.push(["type", { k: "literal", value: false }]);
|
|
288
|
+
const extra = [];
|
|
289
|
+
for (const [key, value2] of Object.entries(edge2)) {
|
|
290
|
+
if (key === "id" || key === "source" || key === "target" || key === "type") continue;
|
|
291
|
+
if (key === "sourceHandle" && typeof value2 === "string") continue;
|
|
292
|
+
extra.push([key, literalOrStructure(value2)]);
|
|
293
|
+
}
|
|
294
|
+
if (extra.length > 0) options2.push(["extra", { k: "object", entries: extra }]);
|
|
295
|
+
const source = String(edge2["source"]);
|
|
296
|
+
const from = typeof edge2["sourceHandle"] === "string" ? { k: "handle", nodeId: source, handle: edge2["sourceHandle"], accessor: { kind: "generic" } } : { k: "node", nodeId: source };
|
|
297
|
+
return { k: "edge", from, options: options2 };
|
|
298
|
+
}
|
|
299
|
+
function chooseOperation(node, hasIncoming, clients, manifests, items) {
|
|
300
|
+
const type = String(node["type"]);
|
|
301
|
+
const operationName = typeof node["operation_name"] === "string" ? node["operation_name"] : void 0;
|
|
302
|
+
const version = typeof node["version"] === "string" ? node["version"] : void 0;
|
|
303
|
+
const helper = HELPER_METHODS[type];
|
|
304
|
+
if (helper) return { method: helper };
|
|
305
|
+
const internalName = INTERNAL_DESCRIPTOR_NAMES[type];
|
|
306
|
+
if (internalName)
|
|
307
|
+
return { method: "step", operation: { kind: "internal", name: internalName, nodeType: type } };
|
|
308
|
+
const triggerName = TRIGGER_NAMES[type];
|
|
309
|
+
if (triggerName)
|
|
310
|
+
return { method: "trigger", operation: { kind: "trigger", name: triggerName, nodeType: type } };
|
|
311
|
+
const client = clients.get(type);
|
|
312
|
+
const manifest = manifests?.find(
|
|
313
|
+
(candidate) => candidate.nodeType === type && candidate.nodeVersion === client?.version
|
|
314
|
+
);
|
|
315
|
+
const operation = operationName && manifest ? chunkLSKSBVL4_cjs.operationsOf(manifest).find((candidate) => candidate.name === operationName) : void 0;
|
|
316
|
+
const operationKey = operationName ? client?.operations.get(operationName) : void 0;
|
|
317
|
+
if (client && operation && operationKey) {
|
|
318
|
+
const isTrigger = chunkLSKSBVL4_cjs.isTriggerOperation(operation);
|
|
319
|
+
return {
|
|
320
|
+
method: isTrigger && !hasIncoming ? "trigger" : "step",
|
|
321
|
+
operation: {
|
|
322
|
+
kind: "client",
|
|
323
|
+
group: client.ts,
|
|
324
|
+
operationKey: operationKey.ts,
|
|
325
|
+
nodeType: type,
|
|
326
|
+
operation: operation.name,
|
|
327
|
+
...client.version !== void 0 ? { version: client.version } : {},
|
|
328
|
+
...isTrigger ? { role: "trigger" } : {}
|
|
329
|
+
},
|
|
330
|
+
writesOperation: operation.name,
|
|
331
|
+
...client.version !== void 0 ? { writesVersion: client.version } : {}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
if (!type.startsWith("internal:")) {
|
|
335
|
+
items.push({
|
|
336
|
+
nodeId: String(node["id"]),
|
|
337
|
+
kind: "unknown-node",
|
|
338
|
+
detail: client ? `${type} has no operation "${operationName ?? ""}" in the registry snapshot; emitted as nodes.custom()` : `${type} is not in the registry snapshot; emitted as nodes.custom()`
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
method: hasIncoming ? "step" : "trigger",
|
|
343
|
+
operation: {
|
|
344
|
+
kind: "custom",
|
|
345
|
+
nodeType: type,
|
|
346
|
+
...operationName !== void 0 ? { operation: operationName } : {},
|
|
347
|
+
...version !== void 0 ? { version } : {}
|
|
348
|
+
},
|
|
349
|
+
...operationName !== void 0 ? { writesOperation: operationName } : {},
|
|
350
|
+
...version !== void 0 ? { writesVersion: version } : {}
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
var ERROR_CONFIG_KEYS = /* @__PURE__ */ new Set(["onError", "errorBranchId", "retryConfig", "timeout"]);
|
|
354
|
+
function errorConfigOptions(errorConfig) {
|
|
355
|
+
if (!chunkLRM6JXJA_cjs.isRecord(errorConfig) || Object.keys(errorConfig).length === 0) return void 0;
|
|
356
|
+
if (!Object.keys(errorConfig).every((key) => ERROR_CONFIG_KEYS.has(key))) return void 0;
|
|
357
|
+
const options2 = [];
|
|
358
|
+
const onError = errorConfig["onError"];
|
|
359
|
+
const branch = errorConfig["errorBranchId"];
|
|
360
|
+
if (onError === "branch") {
|
|
361
|
+
if (typeof branch !== "string") return void 0;
|
|
362
|
+
options2.push([
|
|
363
|
+
"onError",
|
|
364
|
+
{ k: "object", entries: [["branch", { k: "literal", value: branch }]] }
|
|
365
|
+
]);
|
|
366
|
+
} else {
|
|
367
|
+
if (branch !== void 0) return void 0;
|
|
368
|
+
if (onError === "stop" || onError === "continue")
|
|
369
|
+
options2.push(["onError", { k: "literal", value: onError }]);
|
|
370
|
+
else if (onError !== void 0) return void 0;
|
|
371
|
+
}
|
|
372
|
+
if (errorConfig["retryConfig"] !== void 0) {
|
|
373
|
+
if (!chunkLRM6JXJA_cjs.isRecord(errorConfig["retryConfig"])) return void 0;
|
|
374
|
+
options2.push(["retry", literalOrStructure(errorConfig["retryConfig"])]);
|
|
375
|
+
}
|
|
376
|
+
if (errorConfig["timeout"] !== void 0) {
|
|
377
|
+
if (!chunkLRM6JXJA_cjs.isRecord(errorConfig["timeout"])) return void 0;
|
|
378
|
+
options2.push(["timeout", literalOrStructure(errorConfig["timeout"])]);
|
|
379
|
+
}
|
|
380
|
+
return options2;
|
|
381
|
+
}
|
|
382
|
+
function connectionOptions(value2, names, nodeId, items) {
|
|
383
|
+
if (Array.isArray(value2) && value2.length > 0 && names) {
|
|
384
|
+
const resolved = value2.map((ref) => {
|
|
385
|
+
if (!chunkLRM6JXJA_cjs.isRecord(ref) || Object.keys(ref).sort().join(",") !== "adapter,connectionId")
|
|
386
|
+
return void 0;
|
|
387
|
+
const id = ref["connectionId"];
|
|
388
|
+
return typeof id === "string" && Object.hasOwn(names, id) ? names[id] : void 0;
|
|
389
|
+
});
|
|
390
|
+
if (resolved.every((name) => typeof name === "string")) {
|
|
391
|
+
return resolved.length === 1 ? ["connection", { k: "literal", value: resolved[0] ?? "" }] : [
|
|
392
|
+
"connection",
|
|
393
|
+
{ k: "array", items: resolved.map((name) => ({ k: "literal", value: name })) }
|
|
394
|
+
];
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
if (Array.isArray(value2) && value2.length > 0) {
|
|
398
|
+
items.push({
|
|
399
|
+
nodeId,
|
|
400
|
+
path: "args.connections",
|
|
401
|
+
kind: "connection-id-only",
|
|
402
|
+
detail: "No connection name resolves; the connection id is kept"
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
return ["connections", literalOrStructure(value2)];
|
|
406
|
+
}
|
|
407
|
+
function richNode(node, choice, incoming, nodeIds, options2, items) {
|
|
408
|
+
const id = String(node["id"]);
|
|
409
|
+
const out = [["id", { k: "literal", value: id }]];
|
|
410
|
+
const extra = [];
|
|
411
|
+
const operationName = node["operation_name"];
|
|
412
|
+
const version = node["version"];
|
|
413
|
+
if (node["label"] !== void 0) {
|
|
414
|
+
if (typeof node["label"] === "string")
|
|
415
|
+
out.push(["label", { k: "literal", value: node["label"] }]);
|
|
416
|
+
else extra.push(["label", literalOrStructure(node["label"])]);
|
|
417
|
+
}
|
|
418
|
+
if (incoming.length === 1 && incoming[0]) out.push(["after", incoming[0]]);
|
|
419
|
+
else if (incoming.length > 1) out.push(["after", { k: "array", items: incoming }]);
|
|
420
|
+
if (operationName !== choice.writesOperation) {
|
|
421
|
+
if (operationName === void 0) out.push(["operation", { k: "literal", value: false }]);
|
|
422
|
+
else if (typeof operationName === "string")
|
|
423
|
+
out.push(["operation", { k: "literal", value: operationName }]);
|
|
424
|
+
else {
|
|
425
|
+
out.push(["operation", { k: "literal", value: false }]);
|
|
426
|
+
extra.push(["operation_name", literalOrStructure(operationName)]);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
if (version !== choice.writesVersion) {
|
|
430
|
+
if (version === void 0) out.push(["version", { k: "literal", value: false }]);
|
|
431
|
+
else if (typeof version === "string") out.push(["version", { k: "literal", value: version }]);
|
|
432
|
+
else {
|
|
433
|
+
out.push(["version", { k: "literal", value: false }]);
|
|
434
|
+
extra.push(["version", literalOrStructure(version)]);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
const args = chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"] : void 0;
|
|
438
|
+
if (node["args"] !== void 0 && !args) extra.push(["args", literalOrStructure(node["args"])]);
|
|
439
|
+
if (args) {
|
|
440
|
+
const argsExtra = [];
|
|
441
|
+
let state = args["state"];
|
|
442
|
+
if (choice.method === "if" && chunkLRM6JXJA_cjs.isRecord(state) && state["conditionTree"] !== void 0) {
|
|
443
|
+
const condition = liftCondition(state["conditionTree"], nodeIds, true);
|
|
444
|
+
if (condition) {
|
|
445
|
+
out.push(["condition", condition]);
|
|
446
|
+
const rest = { ...state };
|
|
447
|
+
delete rest["conditionTree"];
|
|
448
|
+
state = Object.keys(rest).length > 0 ? rest : void 0;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (state !== void 0) {
|
|
452
|
+
if (chunkLRM6JXJA_cjs.isRecord(state)) out.push(["args", liftState(String(node["type"]), state, id, items)]);
|
|
453
|
+
else argsExtra.push(["state", literalOrStructure(state)]);
|
|
454
|
+
}
|
|
455
|
+
for (const [key, value2] of Object.entries(args)) {
|
|
456
|
+
if (key === "state") continue;
|
|
457
|
+
if (key === "connections")
|
|
458
|
+
out.push(connectionOptions(value2, options2.connectionNames, id, items));
|
|
459
|
+
else if (key === "credentials" && Array.isArray(value2)) {
|
|
460
|
+
out.push(["credentials", literalOrStructure(value2)]);
|
|
461
|
+
items.push({
|
|
462
|
+
nodeId: id,
|
|
463
|
+
path: "args.credentials",
|
|
464
|
+
kind: "legacy-syntax",
|
|
465
|
+
detail: "Legacy credential references kept verbatim"
|
|
466
|
+
});
|
|
467
|
+
} else if (key === "context" && chunkLRM6JXJA_cjs.isRecord(value2))
|
|
468
|
+
out.push(["context", literalOrStructure(value2)]);
|
|
469
|
+
else argsExtra.push([key, literalOrStructure(value2)]);
|
|
470
|
+
}
|
|
471
|
+
if (argsExtra.length > 0 || Object.keys(args).length === 0 && args["state"] === void 0) {
|
|
472
|
+
extra.push(["args", { k: "object", entries: argsExtra }]);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
if (node["errorConfig"] !== void 0) {
|
|
476
|
+
const sugar = errorConfigOptions(node["errorConfig"]);
|
|
477
|
+
if (sugar) out.push(...sugar);
|
|
478
|
+
else out.push(["errorConfig", literalOrStructure(node["errorConfig"])]);
|
|
479
|
+
}
|
|
480
|
+
const data = chunkLRM6JXJA_cjs.isRecord(node["data"]) ? { ...node["data"] } : void 0;
|
|
481
|
+
if (node["executionSettings"] !== void 0) {
|
|
482
|
+
const settings = node["executionSettings"];
|
|
483
|
+
if (chunkLRM6JXJA_cjs.isRecord(settings)) {
|
|
484
|
+
const mirror = chunkLRM6JXJA_cjs.isRecord(data?.["executionSettings"]) ? data["executionSettings"] : void 0;
|
|
485
|
+
const mirrored = settings["runOn"] !== void 0 && mirror !== void 0 && Object.keys(mirror).length === 1 && chunkLRM6JXJA_cjs.deepEqual(mirror["runOn"], settings["runOn"]);
|
|
486
|
+
if (settings["runOn"] === void 0 || mirrored) {
|
|
487
|
+
out.push(["executionSettings", literalOrStructure(settings)]);
|
|
488
|
+
if (mirrored && data) delete data["executionSettings"];
|
|
489
|
+
} else {
|
|
490
|
+
const withoutRunOn = { ...settings };
|
|
491
|
+
delete withoutRunOn["runOn"];
|
|
492
|
+
out.push(["executionSettings", literalOrStructure(withoutRunOn)]);
|
|
493
|
+
extra.push([
|
|
494
|
+
"executionSettings",
|
|
495
|
+
{ k: "object", entries: [["runOn", literalOrStructure(settings["runOn"])]] }
|
|
496
|
+
]);
|
|
497
|
+
}
|
|
498
|
+
} else extra.push(["executionSettings", literalOrStructure(settings)]);
|
|
499
|
+
}
|
|
500
|
+
if (node["disabled"] !== void 0) {
|
|
501
|
+
if (typeof node["disabled"] === "boolean")
|
|
502
|
+
out.push(["disabled", { k: "literal", value: node["disabled"] }]);
|
|
503
|
+
else extra.push(["disabled", literalOrStructure(node["disabled"])]);
|
|
504
|
+
}
|
|
505
|
+
if (data && Object.keys(data).length > 0) extra.push(["data", literalOrStructure(data)]);
|
|
506
|
+
else if (node["data"] !== void 0 && !chunkLRM6JXJA_cjs.isRecord(node["data"]))
|
|
507
|
+
extra.push(["data", literalOrStructure(node["data"])]);
|
|
508
|
+
else if (chunkLRM6JXJA_cjs.isRecord(node["data"]) && Object.keys(node["data"]).length === 0)
|
|
509
|
+
extra.push(["data", { k: "object", entries: [] }]);
|
|
510
|
+
for (const [key, value2] of Object.entries(node)) {
|
|
511
|
+
if ([
|
|
512
|
+
"id",
|
|
513
|
+
"type",
|
|
514
|
+
"label",
|
|
515
|
+
"position",
|
|
516
|
+
"operation_name",
|
|
517
|
+
"version",
|
|
518
|
+
"args",
|
|
519
|
+
"errorConfig",
|
|
520
|
+
"executionSettings",
|
|
521
|
+
"disabled",
|
|
522
|
+
"data"
|
|
523
|
+
].includes(key)) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
extra.push([key, literalOrStructure(value2)]);
|
|
527
|
+
}
|
|
528
|
+
if (extra.length > 0) out.push(["extra", { k: "object", entries: extra }]);
|
|
529
|
+
return {
|
|
530
|
+
kind: "node",
|
|
531
|
+
nodeId: id,
|
|
532
|
+
method: choice.method,
|
|
533
|
+
...choice.operation ? { operation: choice.operation } : {},
|
|
534
|
+
options: out
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
function rawNode(node, incoming, method) {
|
|
538
|
+
const id = String(node["id"]);
|
|
539
|
+
const type = String(node["type"]);
|
|
540
|
+
const operation = typeof node["operation_name"] === "string" ? node["operation_name"] : void 0;
|
|
541
|
+
const version = typeof node["version"] === "string" ? node["version"] : void 0;
|
|
542
|
+
const options2 = [["id", { k: "literal", value: id }]];
|
|
543
|
+
if (incoming.length === 1 && incoming[0]) options2.push(["after", incoming[0]]);
|
|
544
|
+
else if (incoming.length > 1) options2.push(["after", { k: "array", items: incoming }]);
|
|
545
|
+
const extra = [];
|
|
546
|
+
for (const [key, value2] of Object.entries(node)) {
|
|
547
|
+
if (key === "id" || key === "type" || key === "position") continue;
|
|
548
|
+
if (key === "operation_name" && operation !== void 0) continue;
|
|
549
|
+
if (key === "version" && version !== void 0) continue;
|
|
550
|
+
extra.push([key, literalOrStructure(value2)]);
|
|
551
|
+
}
|
|
552
|
+
if (extra.length > 0) options2.push(["extra", { k: "object", entries: extra }]);
|
|
553
|
+
return {
|
|
554
|
+
kind: "node",
|
|
555
|
+
nodeId: id,
|
|
556
|
+
method,
|
|
557
|
+
operation: {
|
|
558
|
+
kind: "custom",
|
|
559
|
+
nodeType: type,
|
|
560
|
+
...operation !== void 0 ? { operation } : {},
|
|
561
|
+
...version !== void 0 ? { version } : {}
|
|
562
|
+
},
|
|
563
|
+
options: options2
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
var WORKFLOW_OPTION_KEYS = ["name", "description", "config", "interface", "code", "tags", "meta"];
|
|
567
|
+
function workflowOptions(definition, key) {
|
|
568
|
+
const out = [["key", { k: "literal", value: key }]];
|
|
569
|
+
const extra = [];
|
|
570
|
+
for (const option of WORKFLOW_OPTION_KEYS) {
|
|
571
|
+
const value2 = definition[option];
|
|
572
|
+
if (value2 === void 0) continue;
|
|
573
|
+
if (option === "meta" && chunkLRM6JXJA_cjs.isRecord(value2)) {
|
|
574
|
+
const meta = { ...value2 };
|
|
575
|
+
delete meta["layout"];
|
|
576
|
+
if (Object.keys(meta).length > 0) out.push(["meta", literalOrStructure(meta)]);
|
|
577
|
+
continue;
|
|
578
|
+
}
|
|
579
|
+
const typed = (option === "name" || option === "description") && typeof value2 === "string" || option === "tags" && Array.isArray(value2) || ["config", "interface", "code"].includes(option) && chunkLRM6JXJA_cjs.isRecord(value2);
|
|
580
|
+
if (typed) out.push([option, literalOrStructure(value2)]);
|
|
581
|
+
else extra.push([option, literalOrStructure(value2)]);
|
|
582
|
+
}
|
|
583
|
+
const data = chunkLRM6JXJA_cjs.isRecord(definition["data"]) ? definition["data"] : {};
|
|
584
|
+
const dataExtra = Object.entries(data).filter(
|
|
585
|
+
([dataKey]) => !["nodes", "edges", "stickyNotes"].includes(dataKey)
|
|
586
|
+
);
|
|
587
|
+
if (dataExtra.length > 0)
|
|
588
|
+
extra.push([
|
|
589
|
+
"data",
|
|
590
|
+
{ k: "object", entries: dataExtra.map(([k, v]) => [k, literalOrStructure(v)]) }
|
|
591
|
+
]);
|
|
592
|
+
for (const [docKey, value2] of Object.entries(definition)) {
|
|
593
|
+
if (["schemaVersion", "key", "authoring", "data", "pinnedData", ...WORKFLOW_OPTION_KEYS].includes(
|
|
594
|
+
docKey
|
|
595
|
+
))
|
|
596
|
+
continue;
|
|
597
|
+
extra.push([docKey, literalOrStructure(value2)]);
|
|
598
|
+
}
|
|
599
|
+
if (extra.length > 0) out.push(["extra", { k: "object", entries: extra }]);
|
|
600
|
+
return out;
|
|
601
|
+
}
|
|
602
|
+
function buildPlan(normalized, options2, rawNodeIds = /* @__PURE__ */ new Set(), rawEdgeIndices = /* @__PURE__ */ new Set()) {
|
|
603
|
+
const items = [];
|
|
604
|
+
const data = chunkLRM6JXJA_cjs.isRecord(normalized["data"]) ? normalized["data"] : {};
|
|
605
|
+
const nodes2 = Array.isArray(data["nodes"]) ? data["nodes"] : [];
|
|
606
|
+
const edges = Array.isArray(data["edges"]) ? data["edges"] : [];
|
|
607
|
+
const key = typeof normalized["key"] === "string" && normalized["key"] ? normalized["key"] : options2.workflowKey;
|
|
608
|
+
if (!key) throw new LiftError("The definition has no key; pass workflowKey");
|
|
609
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
610
|
+
for (const node of nodes2) {
|
|
611
|
+
if (!chunkLRM6JXJA_cjs.isRecord(node) || typeof node["id"] !== "string" || node["id"] === "" || typeof node["type"] !== "string") {
|
|
612
|
+
throw new LiftError("Every node needs a string id and type to be lifted");
|
|
613
|
+
}
|
|
614
|
+
if (nodeIds.has(node["id"])) throw new LiftError(`Node id "${node["id"]}" is used twice`);
|
|
615
|
+
nodeIds.add(node["id"]);
|
|
616
|
+
}
|
|
617
|
+
const edgeIds = /* @__PURE__ */ new Set();
|
|
618
|
+
for (const edge2 of edges) {
|
|
619
|
+
if (!chunkLRM6JXJA_cjs.isRecord(edge2) || typeof edge2["source"] !== "string" || typeof edge2["target"] !== "string") {
|
|
620
|
+
throw new LiftError("Every edge needs a string source and target to be lifted");
|
|
621
|
+
}
|
|
622
|
+
if (edge2["id"] === void 0) continue;
|
|
623
|
+
if (typeof edge2["id"] !== "string") throw new LiftError("Edge ids must be strings");
|
|
624
|
+
if (edgeIds.has(edge2["id"])) throw new LiftError(`Edge id "${edge2["id"]}" is used twice`);
|
|
625
|
+
edgeIds.add(edge2["id"]);
|
|
626
|
+
}
|
|
627
|
+
const nodeRecords = nodes2.filter(chunkLRM6JXJA_cjs.isRecord);
|
|
628
|
+
const edgeRecords = edges.filter(chunkLRM6JXJA_cjs.isRecord);
|
|
629
|
+
const clients = options2.registry ? chunkIZQNUNSU_cjs.clientNames(options2.registry) : /* @__PURE__ */ new Map();
|
|
630
|
+
const edgeIndex = /* @__PURE__ */ new Map();
|
|
631
|
+
edgeRecords.forEach((edge2, index) => edgeIndex.set(edge2, index));
|
|
632
|
+
const incomingByTarget = /* @__PURE__ */ new Map();
|
|
633
|
+
for (const edge2 of edgeRecords) {
|
|
634
|
+
const target = String(edge2["target"]);
|
|
635
|
+
if (nodeIds.has(target))
|
|
636
|
+
incomingByTarget.set(target, [...incomingByTarget.get(target) ?? [], edge2]);
|
|
637
|
+
}
|
|
638
|
+
const info = /* @__PURE__ */ new Map();
|
|
639
|
+
const choices = /* @__PURE__ */ new Map();
|
|
640
|
+
for (const node of nodeRecords) {
|
|
641
|
+
const id = String(node["id"]);
|
|
642
|
+
const raw = rawNodeIds.has(id);
|
|
643
|
+
const choice = raw ? { method: (incomingByTarget.get(id)?.length ?? 0) > 0 ? "step" : "trigger" } : chooseOperation(
|
|
644
|
+
node,
|
|
645
|
+
(incomingByTarget.get(id)?.length ?? 0) > 0,
|
|
646
|
+
clients,
|
|
647
|
+
options2.registry,
|
|
648
|
+
items
|
|
649
|
+
);
|
|
650
|
+
choices.set(id, choice);
|
|
651
|
+
info.set(id, { id, method: raw ? void 0 : choice.method });
|
|
652
|
+
}
|
|
653
|
+
const edgeExpr = (edge2) => rawEdgeIndices.has(edgeIndex.get(edge2) ?? -1) ? rawEdge(edge2) : richEdge(edge2, info, items);
|
|
654
|
+
const statements = [];
|
|
655
|
+
for (const node of nodeRecords) {
|
|
656
|
+
const id = String(node["id"]);
|
|
657
|
+
const incoming = (incomingByTarget.get(id) ?? []).map(edgeExpr);
|
|
658
|
+
const choice = choices.get(id) ?? { method: "step" };
|
|
659
|
+
if (rawNodeIds.has(id)) {
|
|
660
|
+
items.push({
|
|
661
|
+
nodeId: id,
|
|
662
|
+
kind: "raw-node",
|
|
663
|
+
detail: "Written as nodes.custom() with extra so it round-trips exactly"
|
|
664
|
+
});
|
|
665
|
+
statements.push(rawNode(node, incoming, choice.method === "trigger" ? "trigger" : "step"));
|
|
666
|
+
} else {
|
|
667
|
+
statements.push(richNode(node, choice, incoming, nodeIds, options2, items));
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
const declared = [];
|
|
671
|
+
for (const node of nodeRecords) {
|
|
672
|
+
for (const edge2 of incomingByTarget.get(String(node["id"])) ?? [])
|
|
673
|
+
declared.push(edgeIndex.get(edge2) ?? -1);
|
|
674
|
+
}
|
|
675
|
+
for (const edge2 of edgeRecords) {
|
|
676
|
+
if (nodeIds.has(String(edge2["target"]))) continue;
|
|
677
|
+
const expr2 = edgeExpr(edge2);
|
|
678
|
+
const fromExpr = expr2.k === "edge" ? expr2.from : expr2;
|
|
679
|
+
const edgeOptions = expr2.k === "edge" ? expr2.options : [];
|
|
680
|
+
statements.push({
|
|
681
|
+
kind: "connect",
|
|
682
|
+
from: fromExpr,
|
|
683
|
+
to: String(edge2["target"]),
|
|
684
|
+
options: edgeOptions
|
|
685
|
+
});
|
|
686
|
+
declared.push(edgeIndex.get(edge2) ?? -1);
|
|
687
|
+
}
|
|
688
|
+
if (declared.some((index, position) => index !== position)) {
|
|
689
|
+
const order = edgeRecords.map(
|
|
690
|
+
(edge2, index) => typeof edge2["id"] === "string" ? edge2["id"] : declared.indexOf(index)
|
|
691
|
+
);
|
|
692
|
+
statements.push({ kind: "edgeOrder", ids: order });
|
|
693
|
+
}
|
|
694
|
+
return {
|
|
695
|
+
plan: { key, workflowOptions: workflowOptions(normalized, key), statements },
|
|
696
|
+
items,
|
|
697
|
+
clients
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
function connectionsByName(connectionNames, definition) {
|
|
701
|
+
const out = {};
|
|
702
|
+
const data = chunkLRM6JXJA_cjs.isRecord(definition["data"]) ? definition["data"] : {};
|
|
703
|
+
for (const node of Array.isArray(data["nodes"]) ? data["nodes"] : []) {
|
|
704
|
+
const args = chunkLRM6JXJA_cjs.isRecord(node) && chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"] : void 0;
|
|
705
|
+
for (const ref of Array.isArray(args?.["connections"]) ? args["connections"] : []) {
|
|
706
|
+
if (!chunkLRM6JXJA_cjs.isRecord(ref) || typeof ref["connectionId"] !== "string" || typeof ref["adapter"] !== "string")
|
|
707
|
+
continue;
|
|
708
|
+
const name = connectionNames[ref["connectionId"]];
|
|
709
|
+
if (name !== void 0)
|
|
710
|
+
out[name] = { connectionId: ref["connectionId"], adapter: ref["adapter"] };
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return out;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// src/roundtrip/interpret.ts
|
|
717
|
+
function descriptor(operation) {
|
|
718
|
+
switch (operation.kind) {
|
|
719
|
+
case "trigger": {
|
|
720
|
+
const value2 = chunkKUTMY2IO_cjs.triggers[operation.name];
|
|
721
|
+
if (!value2) throw new LiftError(`Unknown trigger ${operation.name}`);
|
|
722
|
+
return value2;
|
|
723
|
+
}
|
|
724
|
+
case "internal": {
|
|
725
|
+
const value2 = chunkKUTMY2IO_cjs.internalNodes[operation.name];
|
|
726
|
+
if (!value2) throw new LiftError(`Unknown internal node ${operation.name}`);
|
|
727
|
+
return value2;
|
|
728
|
+
}
|
|
729
|
+
case "client":
|
|
730
|
+
return operation.role === "trigger" ? chunkKUTMY2IO_cjs.trigger(operation.nodeType, operation.version, operation.operation) : chunkKUTMY2IO_cjs.op(operation.nodeType, operation.version, operation.operation);
|
|
731
|
+
case "custom":
|
|
732
|
+
return chunkKUTMY2IO_cjs.nodes.custom(operation.nodeType, operation.operation, operation.version);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
function refValue(ref, wf, runtime) {
|
|
736
|
+
let current;
|
|
737
|
+
if (ref.target.kind === "node")
|
|
738
|
+
current = (runtime.get(ref.target.nodeId) ?? wf.ref(ref.target.nodeId)).output;
|
|
739
|
+
else current = wf[ref.target.kind];
|
|
740
|
+
for (const segment of ref.path) {
|
|
741
|
+
current = current[segment.kind === "index" ? String(segment.index) : segment.key];
|
|
742
|
+
}
|
|
743
|
+
return current;
|
|
744
|
+
}
|
|
745
|
+
function value(expression2, wf, runtime) {
|
|
746
|
+
switch (expression2.k) {
|
|
747
|
+
case "literal":
|
|
748
|
+
return expression2.value;
|
|
749
|
+
case "object":
|
|
750
|
+
return Object.fromEntries(
|
|
751
|
+
expression2.entries.map(([key, child]) => [key, value(child, wf, runtime)])
|
|
752
|
+
);
|
|
753
|
+
case "array":
|
|
754
|
+
return expression2.items.map((item) => value(item, wf, runtime));
|
|
755
|
+
case "ref":
|
|
756
|
+
return refValue(expression2.ref, wf, runtime);
|
|
757
|
+
case "template": {
|
|
758
|
+
const strings = [""];
|
|
759
|
+
const values = [];
|
|
760
|
+
for (const part of expression2.parts) {
|
|
761
|
+
if ("text" in part) strings[strings.length - 1] += part.text;
|
|
762
|
+
else {
|
|
763
|
+
values.push(refValue(part.ref, wf, runtime));
|
|
764
|
+
strings.push("");
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
return chunkRRQ5HOBF_cjs.expr(Object.assign([...strings], { raw: [...strings] }), ...values);
|
|
768
|
+
}
|
|
769
|
+
case "rule": {
|
|
770
|
+
const target = refValue(expression2.ref, wf, runtime);
|
|
771
|
+
if (expression2.method === "is") {
|
|
772
|
+
return expression2.hasValue ? target.is(expression2.operator, expression2.value) : target.is(expression2.operator);
|
|
773
|
+
}
|
|
774
|
+
const method = target[expression2.method];
|
|
775
|
+
return expression2.hasValue ? method(expression2.value) : method();
|
|
776
|
+
}
|
|
777
|
+
case "group": {
|
|
778
|
+
const children = expression2.children.map((child) => value(child, wf, runtime));
|
|
779
|
+
return expression2.combinator === "and" ? chunkRRQ5HOBF_cjs.and(...children) : chunkRRQ5HOBF_cjs.or(...children);
|
|
780
|
+
}
|
|
781
|
+
case "node":
|
|
782
|
+
return runtime.get(expression2.nodeId) ?? wf.ref(expression2.nodeId);
|
|
783
|
+
case "handle": {
|
|
784
|
+
const declared = runtime.get(expression2.nodeId);
|
|
785
|
+
if (declared && expression2.accessor.kind === "property")
|
|
786
|
+
return declared[expression2.accessor.name];
|
|
787
|
+
return (declared ?? wf.ref(expression2.nodeId)).handle(expression2.handle);
|
|
788
|
+
}
|
|
789
|
+
case "edge":
|
|
790
|
+
return chunkKUTMY2IO_cjs.edge(
|
|
791
|
+
value(expression2.from, wf, runtime),
|
|
792
|
+
value({ k: "object", entries: expression2.options }, wf, runtime)
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
function literalValue(expression2) {
|
|
797
|
+
switch (expression2.k) {
|
|
798
|
+
case "literal":
|
|
799
|
+
return expression2.value;
|
|
800
|
+
case "object":
|
|
801
|
+
return Object.fromEntries(
|
|
802
|
+
expression2.entries.map(([key, child]) => [key, literalValue(child)])
|
|
803
|
+
);
|
|
804
|
+
case "array":
|
|
805
|
+
return expression2.items.map(literalValue);
|
|
806
|
+
default:
|
|
807
|
+
throw new LiftError("Workflow options hold JSON only");
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
function options(entries, wf, runtime) {
|
|
811
|
+
return value({ k: "object", entries }, wf, runtime);
|
|
812
|
+
}
|
|
813
|
+
function interpretPlan(plan) {
|
|
814
|
+
const workflowOptions2 = literalValue({
|
|
815
|
+
k: "object",
|
|
816
|
+
entries: plan.workflowOptions
|
|
817
|
+
});
|
|
818
|
+
const workflow = chunkKUTMY2IO_cjs.defineWorkflow(workflowOptions2, (wf) => {
|
|
819
|
+
const runtime = /* @__PURE__ */ new Map();
|
|
820
|
+
for (const statement of plan.statements) {
|
|
821
|
+
if (statement.kind === "node") {
|
|
822
|
+
const nodeOptions = options(statement.options, wf, runtime);
|
|
823
|
+
const method = wf[statement.method];
|
|
824
|
+
if (typeof method !== "function")
|
|
825
|
+
throw new LiftError(`Unknown builder method ${statement.method}`);
|
|
826
|
+
const result = statement.operation ? method.call(wf, descriptor(statement.operation), nodeOptions) : method.call(wf, nodeOptions);
|
|
827
|
+
runtime.set(statement.nodeId, result);
|
|
828
|
+
} else if (statement.kind === "connect") {
|
|
829
|
+
wf.connect(
|
|
830
|
+
value(statement.from, wf, runtime),
|
|
831
|
+
statement.to,
|
|
832
|
+
options(statement.options, wf, runtime)
|
|
833
|
+
);
|
|
834
|
+
} else {
|
|
835
|
+
wf.edgeOrderIs(statement.ids);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
});
|
|
839
|
+
return workflow.recording;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// src/roundtrip/render-py.ts
|
|
843
|
+
var PY_SDK_MODULE = "fluidgrids_workflows";
|
|
844
|
+
var PY_PROJECT_MODULE = "fluidgrids_workflows.project";
|
|
845
|
+
var PY_REF_METHODS = /* @__PURE__ */ new Set([
|
|
846
|
+
"eq",
|
|
847
|
+
"neq",
|
|
848
|
+
"gt",
|
|
849
|
+
"gte",
|
|
850
|
+
"lt",
|
|
851
|
+
"lte",
|
|
852
|
+
"contains",
|
|
853
|
+
"not_contains",
|
|
854
|
+
"starts_with",
|
|
855
|
+
"ends_with",
|
|
856
|
+
"matches",
|
|
857
|
+
"has_property",
|
|
858
|
+
"is_empty",
|
|
859
|
+
"is_not_empty",
|
|
860
|
+
"is_null",
|
|
861
|
+
"is_not_null",
|
|
862
|
+
"is_true",
|
|
863
|
+
"is_false",
|
|
864
|
+
"is_"
|
|
865
|
+
]);
|
|
866
|
+
var COMPARISON_OPERATORS = {
|
|
867
|
+
eq: "==",
|
|
868
|
+
neq: "!=",
|
|
869
|
+
gt: ">",
|
|
870
|
+
gte: ">=",
|
|
871
|
+
lt: "<",
|
|
872
|
+
lte: "<="
|
|
873
|
+
};
|
|
874
|
+
var BUILDER_METHODS = {
|
|
875
|
+
if: "if_",
|
|
876
|
+
waitForSignal: "wait_for_signal",
|
|
877
|
+
sendAndWait: "send_and_wait",
|
|
878
|
+
compareDatasets: "compare_datasets",
|
|
879
|
+
splitOut: "split_out",
|
|
880
|
+
dataTable: "data_table",
|
|
881
|
+
respondToWebhook: "respond_to_webhook",
|
|
882
|
+
stopAndError: "stop_and_error",
|
|
883
|
+
edgeOrderIs: "edge_order_is"
|
|
884
|
+
};
|
|
885
|
+
var atom = (text) => ({ t: "atom", text });
|
|
886
|
+
function isPyIdentifier(name) {
|
|
887
|
+
return /^[A-Za-z][A-Za-z0-9_]*$/.test(name) && !chunkIZQNUNSU_cjs.PY_KEYWORDS.has(name);
|
|
888
|
+
}
|
|
889
|
+
function nodeSource(nodeId, ctx) {
|
|
890
|
+
const name = ctx.vars.get(nodeId);
|
|
891
|
+
if (name !== void 0 && ctx.declared.has(nodeId)) return atom(name);
|
|
892
|
+
return {
|
|
893
|
+
t: "call",
|
|
894
|
+
func: atom("wf.ref"),
|
|
895
|
+
args: [{ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(nodeId)) }]
|
|
896
|
+
};
|
|
897
|
+
}
|
|
898
|
+
function refExpr(ref, ctx) {
|
|
899
|
+
let current = ref.target.kind === "node" ? { t: "attr", base: nodeSource(ref.target.nodeId, ctx), name: "output" } : atom(`wf.${ref.target.kind}`);
|
|
900
|
+
for (const segment of ref.path) {
|
|
901
|
+
if (segment.kind === "index")
|
|
902
|
+
current = { t: "subscript", base: current, indices: [atom(String(segment.index))] };
|
|
903
|
+
else if (isPyIdentifier(segment.key) && !PY_REF_METHODS.has(segment.key))
|
|
904
|
+
current = { t: "attr", base: current, name: segment.key };
|
|
905
|
+
else current = { t: "subscript", base: current, indices: [atom(chunkIZQNUNSU_cjs.pyString(segment.key))] };
|
|
906
|
+
}
|
|
907
|
+
return current;
|
|
908
|
+
}
|
|
909
|
+
function literal(value2) {
|
|
910
|
+
if (value2 === null) return atom("None");
|
|
911
|
+
if (typeof value2 === "boolean") return atom(value2 ? "True" : "False");
|
|
912
|
+
if (typeof value2 === "number") return atom(chunkIZQNUNSU_cjs.pyNumber(value2));
|
|
913
|
+
return atom(chunkIZQNUNSU_cjs.pyString(value2));
|
|
914
|
+
}
|
|
915
|
+
function call(func, args) {
|
|
916
|
+
return { t: "call", func: atom(func), args };
|
|
917
|
+
}
|
|
918
|
+
function keywordName(option) {
|
|
919
|
+
return chunkIZQNUNSU_cjs.snakeCase(option);
|
|
920
|
+
}
|
|
921
|
+
function expression(planExpr, ctx) {
|
|
922
|
+
switch (planExpr.k) {
|
|
923
|
+
case "literal":
|
|
924
|
+
return literal(planExpr.value);
|
|
925
|
+
case "object":
|
|
926
|
+
return {
|
|
927
|
+
t: "dict",
|
|
928
|
+
entries: planExpr.entries.map(([key, child]) => [
|
|
929
|
+
atom(chunkIZQNUNSU_cjs.pyString(key)),
|
|
930
|
+
expression(child, ctx)
|
|
931
|
+
])
|
|
932
|
+
};
|
|
933
|
+
case "array":
|
|
934
|
+
return { t: "list", items: planExpr.items.map((item) => expression(item, ctx)) };
|
|
935
|
+
case "ref":
|
|
936
|
+
return refExpr(planExpr.ref, ctx);
|
|
937
|
+
case "template":
|
|
938
|
+
ctx.used.add("expr");
|
|
939
|
+
return call(
|
|
940
|
+
"expr",
|
|
941
|
+
planExpr.parts.map((part) => ({
|
|
942
|
+
kind: "positional",
|
|
943
|
+
value: "text" in part ? atom(chunkIZQNUNSU_cjs.pyString(part.text)) : refExpr(part.ref, ctx)
|
|
944
|
+
}))
|
|
945
|
+
);
|
|
946
|
+
case "rule": {
|
|
947
|
+
const target = refExpr(planExpr.ref, ctx);
|
|
948
|
+
const comparison = COMPARISON_OPERATORS[planExpr.method];
|
|
949
|
+
if (comparison && planExpr.hasValue) {
|
|
950
|
+
return {
|
|
951
|
+
t: "compare",
|
|
952
|
+
left: target,
|
|
953
|
+
op: comparison,
|
|
954
|
+
right: literal(planExpr.value ?? null)
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
const method = planExpr.method === "is" ? "is_" : chunkIZQNUNSU_cjs.snakeCase(planExpr.method);
|
|
958
|
+
const args = [];
|
|
959
|
+
if (planExpr.method === "is")
|
|
960
|
+
args.push({ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(planExpr.operator)) });
|
|
961
|
+
if (planExpr.hasValue)
|
|
962
|
+
args.push({ kind: "positional", value: literal(planExpr.value ?? null) });
|
|
963
|
+
return { t: "call", func: { t: "attr", base: target, name: method }, args };
|
|
964
|
+
}
|
|
965
|
+
case "group": {
|
|
966
|
+
const name = planExpr.combinator === "and" ? "and_" : "or_";
|
|
967
|
+
ctx.used.add(name);
|
|
968
|
+
return call(
|
|
969
|
+
name,
|
|
970
|
+
planExpr.children.map((child) => ({ kind: "positional", value: expression(child, ctx) }))
|
|
971
|
+
);
|
|
972
|
+
}
|
|
973
|
+
case "node":
|
|
974
|
+
return nodeSource(planExpr.nodeId, ctx);
|
|
975
|
+
case "handle": {
|
|
976
|
+
const source = nodeSource(planExpr.nodeId, ctx);
|
|
977
|
+
const declared = ctx.declared.has(planExpr.nodeId) && ctx.vars.has(planExpr.nodeId);
|
|
978
|
+
if (declared && planExpr.accessor.kind === "property")
|
|
979
|
+
return { t: "attr", base: source, name: chunkIZQNUNSU_cjs.snakeCase(planExpr.accessor.name) };
|
|
980
|
+
const method = declared && planExpr.accessor.kind === "case" ? "case" : "handle";
|
|
981
|
+
return {
|
|
982
|
+
t: "call",
|
|
983
|
+
func: { t: "attr", base: source, name: method },
|
|
984
|
+
args: [{ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(planExpr.handle)) }]
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
case "edge":
|
|
988
|
+
ctx.used.add("edge");
|
|
989
|
+
return call("edge", [
|
|
990
|
+
{ kind: "positional", value: expression(planExpr.from, ctx) },
|
|
991
|
+
...keywords(planExpr.options, ctx)
|
|
992
|
+
]);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
function keywords(options2, ctx) {
|
|
996
|
+
return options2.map(([name, value2]) => ({
|
|
997
|
+
kind: "keyword",
|
|
998
|
+
name: keywordName(name),
|
|
999
|
+
value: expression(value2, ctx)
|
|
1000
|
+
}));
|
|
1001
|
+
}
|
|
1002
|
+
function operationExpr(operation, ctx, clientPy) {
|
|
1003
|
+
switch (operation.kind) {
|
|
1004
|
+
case "trigger":
|
|
1005
|
+
ctx.used.add("triggers");
|
|
1006
|
+
return atom(`triggers.${chunkIZQNUNSU_cjs.snakeCase(operation.name)}`);
|
|
1007
|
+
case "internal":
|
|
1008
|
+
ctx.used.add("nodes");
|
|
1009
|
+
return atom(`nodes.internal.${chunkIZQNUNSU_cjs.snakeCase(operation.name)}`);
|
|
1010
|
+
case "client":
|
|
1011
|
+
ctx.used.add("n");
|
|
1012
|
+
return atom(clientPy(operation.nodeType, operation.operation));
|
|
1013
|
+
case "custom": {
|
|
1014
|
+
ctx.used.add("nodes");
|
|
1015
|
+
const args = [{ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(operation.nodeType)) }];
|
|
1016
|
+
if (operation.operation !== void 0)
|
|
1017
|
+
args.push({ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(operation.operation)) });
|
|
1018
|
+
if (operation.version !== void 0) {
|
|
1019
|
+
args.push(
|
|
1020
|
+
operation.operation !== void 0 ? { kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(operation.version)) } : { kind: "keyword", name: "version", value: atom(chunkIZQNUNSU_cjs.pyString(operation.version)) }
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
return call("nodes.custom", args);
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
function statementLines(statement, ctx, clientPy) {
|
|
1028
|
+
if (statement.kind === "edgeOrder") {
|
|
1029
|
+
return chunkIZQNUNSU_cjs.formatLines(
|
|
1030
|
+
"",
|
|
1031
|
+
call("wf.edge_order_is", [
|
|
1032
|
+
{ kind: "positional", value: { t: "list", items: statement.ids.map((id) => literal(id)) } }
|
|
1033
|
+
]),
|
|
1034
|
+
"",
|
|
1035
|
+
1
|
|
1036
|
+
);
|
|
1037
|
+
}
|
|
1038
|
+
if (statement.kind === "connect") {
|
|
1039
|
+
const args2 = [
|
|
1040
|
+
{ kind: "positional", value: expression(statement.from, ctx) },
|
|
1041
|
+
{ kind: "positional", value: atom(chunkIZQNUNSU_cjs.pyString(statement.to)) },
|
|
1042
|
+
...keywords(statement.options, ctx)
|
|
1043
|
+
];
|
|
1044
|
+
return chunkIZQNUNSU_cjs.formatLines("", call("wf.connect", args2), "", 1);
|
|
1045
|
+
}
|
|
1046
|
+
const args = [
|
|
1047
|
+
...statement.operation ? [{ kind: "positional", value: operationExpr(statement.operation, ctx, clientPy) }] : [],
|
|
1048
|
+
...keywords(statement.options, ctx)
|
|
1049
|
+
];
|
|
1050
|
+
const method = BUILDER_METHODS[statement.method] ?? chunkIZQNUNSU_cjs.snakeCase(statement.method);
|
|
1051
|
+
const callExpr = call(`wf.${method}`, args);
|
|
1052
|
+
ctx.declared.add(statement.nodeId);
|
|
1053
|
+
const name = ctx.vars.get(statement.nodeId);
|
|
1054
|
+
return chunkIZQNUNSU_cjs.formatLines(name !== void 0 ? `${name} = ` : "", callExpr, "", 1);
|
|
1055
|
+
}
|
|
1056
|
+
function renderPython(plan, clientPy, header = []) {
|
|
1057
|
+
const allocator = new chunkIZQNUNSU_cjs.NameAllocator("py");
|
|
1058
|
+
const vars = /* @__PURE__ */ new Map();
|
|
1059
|
+
for (const nodeId of chunkIZQNUNSU_cjs.referencedLater(plan)) vars.set(nodeId, allocator.forNode(nodeId));
|
|
1060
|
+
const ctx = { vars, declared: /* @__PURE__ */ new Set(), used: /* @__PURE__ */ new Set() };
|
|
1061
|
+
const body = plan.statements.flatMap((statement) => statementLines(statement, ctx, clientPy));
|
|
1062
|
+
const decorator = chunkIZQNUNSU_cjs.formatLines(
|
|
1063
|
+
"@",
|
|
1064
|
+
call("define_workflow", keywords(plan.workflowOptions, ctx)),
|
|
1065
|
+
"",
|
|
1066
|
+
0
|
|
1067
|
+
);
|
|
1068
|
+
const sdkNames = ["and_", "define_workflow", "edge", "expr", "nodes", "or_", "triggers"].filter(
|
|
1069
|
+
(name) => name === "define_workflow" || ctx.used.has(name)
|
|
1070
|
+
);
|
|
1071
|
+
const lines = [
|
|
1072
|
+
...header.map((line) => `# ${line}`),
|
|
1073
|
+
...header.length > 0 ? [""] : [],
|
|
1074
|
+
...chunkIZQNUNSU_cjs.formatImport(PY_SDK_MODULE, sdkNames),
|
|
1075
|
+
...ctx.used.has("n") ? chunkIZQNUNSU_cjs.formatImport(PY_PROJECT_MODULE, ["nodes as n"]) : [],
|
|
1076
|
+
"",
|
|
1077
|
+
"",
|
|
1078
|
+
...decorator,
|
|
1079
|
+
`def ${chunkIZQNUNSU_cjs.pyWorkflowName(plan.key)}(wf):`,
|
|
1080
|
+
...body.length > 0 ? body : [" pass"],
|
|
1081
|
+
""
|
|
1082
|
+
];
|
|
1083
|
+
return lines.join("\n");
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// src/roundtrip/lift.ts
|
|
1087
|
+
function layoutOf(reference) {
|
|
1088
|
+
const data = chunkLRM6JXJA_cjs.isRecord(reference["data"]) ? reference["data"] : {};
|
|
1089
|
+
const positions = {};
|
|
1090
|
+
for (const node of Array.isArray(data["nodes"]) ? data["nodes"] : []) {
|
|
1091
|
+
if (!chunkLRM6JXJA_cjs.isRecord(node) || typeof node["id"] !== "string" || !chunkLRM6JXJA_cjs.isRecord(node["position"])) continue;
|
|
1092
|
+
const { x, y } = node["position"];
|
|
1093
|
+
if (typeof x === "number" && typeof y === "number") positions[node["id"]] = { x, y };
|
|
1094
|
+
}
|
|
1095
|
+
const sidecar = {
|
|
1096
|
+
format: chunkKUTMY2IO_cjs.LAYOUT_FORMAT,
|
|
1097
|
+
formatVersion: chunkKUTMY2IO_cjs.LAYOUT_FORMAT_VERSION,
|
|
1098
|
+
positions
|
|
1099
|
+
};
|
|
1100
|
+
if (Array.isArray(data["stickyNotes"])) sidecar.stickyNotes = data["stickyNotes"];
|
|
1101
|
+
const meta = chunkLRM6JXJA_cjs.isRecord(reference["meta"]) ? reference["meta"] : void 0;
|
|
1102
|
+
if (chunkLRM6JXJA_cjs.isRecord(meta?.["layout"])) sidecar.metaLayout = meta["layout"];
|
|
1103
|
+
return sidecar;
|
|
1104
|
+
}
|
|
1105
|
+
function mismatches(reference, candidate) {
|
|
1106
|
+
const refData = chunkLRM6JXJA_cjs.isRecord(reference["data"]) ? reference["data"] : {};
|
|
1107
|
+
const candData = chunkLRM6JXJA_cjs.isRecord(candidate["data"]) ? candidate["data"] : {};
|
|
1108
|
+
const byId = (items) => new Map(
|
|
1109
|
+
(Array.isArray(items) ? items : []).filter(chunkLRM6JXJA_cjs.isRecord).map((item) => [String(item["id"]), item])
|
|
1110
|
+
);
|
|
1111
|
+
const nodes2 = /* @__PURE__ */ new Set();
|
|
1112
|
+
const candNodes = byId(candData["nodes"]);
|
|
1113
|
+
for (const [id, node] of byId(refData["nodes"]))
|
|
1114
|
+
if (!chunkLRM6JXJA_cjs.deepEqual(node, candNodes.get(id))) nodes2.add(id);
|
|
1115
|
+
const edges = /* @__PURE__ */ new Set();
|
|
1116
|
+
const refEdges = Array.isArray(refData["edges"]) ? refData["edges"] : [];
|
|
1117
|
+
const candEdges = Array.isArray(candData["edges"]) ? candData["edges"] : [];
|
|
1118
|
+
refEdges.forEach((edge2, index) => {
|
|
1119
|
+
if (!chunkLRM6JXJA_cjs.deepEqual(edge2, candEdges[index])) edges.add(index);
|
|
1120
|
+
});
|
|
1121
|
+
const strip = (doc) => {
|
|
1122
|
+
const copy = { ...doc };
|
|
1123
|
+
delete copy["authoring"];
|
|
1124
|
+
const data = chunkLRM6JXJA_cjs.isRecord(copy["data"]) ? { ...copy["data"] } : {};
|
|
1125
|
+
delete data["nodes"];
|
|
1126
|
+
delete data["edges"];
|
|
1127
|
+
copy["data"] = data;
|
|
1128
|
+
return copy;
|
|
1129
|
+
};
|
|
1130
|
+
return { nodes: nodes2, edges, document: !chunkLRM6JXJA_cjs.deepEqual(strip(reference), strip(candidate)) };
|
|
1131
|
+
}
|
|
1132
|
+
function prepareLift(definition, options2 = {}) {
|
|
1133
|
+
const normalized = chunkAU3YW7FZ_cjs.normalizeDefinition(definition);
|
|
1134
|
+
if (!chunkLRM6JXJA_cjs.isRecord(normalized) || !chunkLRM6JXJA_cjs.isRecord(normalized["data"]))
|
|
1135
|
+
throw new TypeError("A workflow definition must be an object with data");
|
|
1136
|
+
const reference = { ...normalized };
|
|
1137
|
+
const items = [];
|
|
1138
|
+
if (typeof reference["key"] !== "string" || reference["key"] === "") {
|
|
1139
|
+
if (!options2.workflowKey) throw new TypeError("The definition has no key; pass workflowKey");
|
|
1140
|
+
reference["key"] = options2.workflowKey;
|
|
1141
|
+
items.push({
|
|
1142
|
+
kind: "key-added",
|
|
1143
|
+
detail: `The definition has no key; the workflow key "${options2.workflowKey}" is written`
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
delete reference["authoring"];
|
|
1147
|
+
const includeLayout = options2.includeLayout !== false;
|
|
1148
|
+
const layout = layoutOf(reference);
|
|
1149
|
+
if (!includeLayout)
|
|
1150
|
+
items.push({
|
|
1151
|
+
kind: "layout-omitted",
|
|
1152
|
+
detail: "Node positions, sticky notes and meta.layout are not exported"
|
|
1153
|
+
});
|
|
1154
|
+
const pinned = chunkLRM6JXJA_cjs.isRecord(reference["pinnedData"]) ? (
|
|
1155
|
+
// Checked to be a record; carried verbatim.
|
|
1156
|
+
reference["pinnedData"]
|
|
1157
|
+
) : void 0;
|
|
1158
|
+
if (pinned && !options2.includePinnedData)
|
|
1159
|
+
items.push({ kind: "pinned-data-omitted", detail: "Pinned TEST data is not exported" });
|
|
1160
|
+
const connections = options2.connectionNames ? connectionsByName(options2.connectionNames, reference) : void 0;
|
|
1161
|
+
const run = (rawNodes, rawEdges) => {
|
|
1162
|
+
const build = buildPlan(reference, options2, rawNodes, rawEdges);
|
|
1163
|
+
const recording = interpretPlan(build.plan);
|
|
1164
|
+
const candidate = chunkKUTMY2IO_cjs.assembleRecording(recording, {
|
|
1165
|
+
layout,
|
|
1166
|
+
...connections ? { connections } : {},
|
|
1167
|
+
...pinned ? { pinnedData: pinned } : {}
|
|
1168
|
+
});
|
|
1169
|
+
return { build, candidate: chunkAU3YW7FZ_cjs.normalizeDefinition(candidate) };
|
|
1170
|
+
};
|
|
1171
|
+
let attempt = run(/* @__PURE__ */ new Set(), /* @__PURE__ */ new Set());
|
|
1172
|
+
const first = mismatches(reference, attempt.candidate);
|
|
1173
|
+
if (first.nodes.size > 0 || first.edges.size > 0) attempt = run(first.nodes, first.edges);
|
|
1174
|
+
const residual = mismatches(reference, attempt.candidate);
|
|
1175
|
+
for (const id of residual.nodes)
|
|
1176
|
+
items.push({
|
|
1177
|
+
nodeId: id,
|
|
1178
|
+
kind: "roundtrip-mismatch",
|
|
1179
|
+
detail: "This node does not lower back unchanged"
|
|
1180
|
+
});
|
|
1181
|
+
for (const index of residual.edges) {
|
|
1182
|
+
items.push({
|
|
1183
|
+
path: `data.edges[${index}]`,
|
|
1184
|
+
kind: "roundtrip-mismatch",
|
|
1185
|
+
detail: "This edge does not lower back unchanged"
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
if (residual.document)
|
|
1189
|
+
items.push({
|
|
1190
|
+
kind: "roundtrip-mismatch",
|
|
1191
|
+
detail: "Workflow-level fields do not lower back unchanged"
|
|
1192
|
+
});
|
|
1193
|
+
const clients = attempt.build.clients;
|
|
1194
|
+
const usesClients = attempt.build.plan.statements.some(
|
|
1195
|
+
(statement) => statement.kind === "node" && statement.operation?.kind === "client"
|
|
1196
|
+
);
|
|
1197
|
+
return {
|
|
1198
|
+
// The normalised input with its key: a definition by construction.
|
|
1199
|
+
reference,
|
|
1200
|
+
plan: attempt.build.plan,
|
|
1201
|
+
items: [...items, ...attempt.build.items],
|
|
1202
|
+
...includeLayout ? { layout } : {},
|
|
1203
|
+
...pinned && options2.includePinnedData ? { pinnedData: pinned } : {},
|
|
1204
|
+
registry: options2.registry ?? [],
|
|
1205
|
+
clientPy: (nodeType, operation) => {
|
|
1206
|
+
const client = clients.get(nodeType);
|
|
1207
|
+
const names = client?.operations.get(operation);
|
|
1208
|
+
return client && names ? `n.${client.py}.${names.py}` : `nodes.custom(${JSON.stringify(nodeType)})`;
|
|
1209
|
+
},
|
|
1210
|
+
usesClients
|
|
1211
|
+
};
|
|
1212
|
+
}
|
|
1213
|
+
function headerLines(header) {
|
|
1214
|
+
if (!header) return [];
|
|
1215
|
+
const parts = [];
|
|
1216
|
+
if (header.workflowKey)
|
|
1217
|
+
parts.push(`Generated from ${header.workflowKey}${header.version ? ` ${header.version}` : ""}`);
|
|
1218
|
+
if (header.irHash) parts.push(`irHash ${header.irHash}`);
|
|
1219
|
+
if (header.exportedAt) parts.push(`exported ${header.exportedAt}`);
|
|
1220
|
+
const lines = parts.length > 0 ? [`${parts.join(", ")}. Edit freely and run \`fluidgrids push\`.`] : [];
|
|
1221
|
+
if (header.registrySnapshot) lines.push(`Node registry snapshot ${header.registrySnapshot}.`);
|
|
1222
|
+
return lines;
|
|
1223
|
+
}
|
|
1224
|
+
function sidecarFiles(prepared) {
|
|
1225
|
+
const key = prepared.plan.key;
|
|
1226
|
+
const files = [];
|
|
1227
|
+
if (prepared.layout) {
|
|
1228
|
+
files.push({
|
|
1229
|
+
path: `workflows/${key}.layout.json`,
|
|
1230
|
+
contentType: "application/json",
|
|
1231
|
+
content: chunk27HASETB_cjs.stableStringify(prepared.layout)
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
if (prepared.pinnedData) {
|
|
1235
|
+
files.push({
|
|
1236
|
+
path: `workflows/${key}.pinned.json`,
|
|
1237
|
+
contentType: "application/json",
|
|
1238
|
+
content: chunk27HASETB_cjs.stableStringify(prepared.pinnedData)
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
return files;
|
|
1242
|
+
}
|
|
1243
|
+
async function liftToTypeScript(definition, options2 = {}) {
|
|
1244
|
+
const prepared = prepareLift(definition, options2);
|
|
1245
|
+
const source = await chunkIZQNUNSU_cjs.renderTypeScript(prepared.plan, headerLines(options2.header));
|
|
1246
|
+
const files = [
|
|
1247
|
+
{ path: `workflows/${prepared.plan.key}.ts`, contentType: "text/typescript", content: source },
|
|
1248
|
+
...sidecarFiles(prepared)
|
|
1249
|
+
];
|
|
1250
|
+
if (prepared.usesClients) {
|
|
1251
|
+
const clients = await chunkIZQNUNSU_cjs.generateNodeClients(prepared.registry, "ts");
|
|
1252
|
+
files.push({ path: clients.path, contentType: "text/typescript", content: clients.content });
|
|
1253
|
+
}
|
|
1254
|
+
return { files, items: prepared.items, reference: prepared.reference };
|
|
1255
|
+
}
|
|
1256
|
+
async function liftToPython(definition, options2 = {}) {
|
|
1257
|
+
const prepared = prepareLift(definition, options2);
|
|
1258
|
+
const source = renderPython(prepared.plan, prepared.clientPy, headerLines(options2.header));
|
|
1259
|
+
const files = [
|
|
1260
|
+
{
|
|
1261
|
+
path: `workflows/${chunkIZQNUNSU_cjs.pyWorkflowName(prepared.plan.key)}.py`,
|
|
1262
|
+
contentType: "text/x-python",
|
|
1263
|
+
content: source
|
|
1264
|
+
},
|
|
1265
|
+
...sidecarFiles(prepared)
|
|
1266
|
+
];
|
|
1267
|
+
if (prepared.usesClients) {
|
|
1268
|
+
const clients = await chunkIZQNUNSU_cjs.generateNodeClients(prepared.registry, "py");
|
|
1269
|
+
files.push({ path: clients.path, contentType: "text/x-python", content: clients.content });
|
|
1270
|
+
}
|
|
1271
|
+
return { files, items: prepared.items, reference: prepared.reference };
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
// src/roundtrip/fidelity.ts
|
|
1275
|
+
var LOSSY_KINDS = /* @__PURE__ */ new Set([
|
|
1276
|
+
"layout-omitted",
|
|
1277
|
+
"pinned-data-omitted",
|
|
1278
|
+
"roundtrip-mismatch",
|
|
1279
|
+
"lowering-failed"
|
|
1280
|
+
]);
|
|
1281
|
+
async function checkFidelity(files, reference, items, options2 = {}) {
|
|
1282
|
+
const all = [...items];
|
|
1283
|
+
const connections = options2.connectionNames && chunkLRM6JXJA_cjs.isRecord(reference) ? connectionsByName(options2.connectionNames, reference) : void 0;
|
|
1284
|
+
try {
|
|
1285
|
+
const result = await chunkLUXCXFOE_cjs.lower(
|
|
1286
|
+
files.map((file) => ({ path: file.path, content: file.content })),
|
|
1287
|
+
{
|
|
1288
|
+
...options2.esbuild ? { esbuild: options2.esbuild } : {},
|
|
1289
|
+
...options2.evaluator ? { evaluator: options2.evaluator } : {},
|
|
1290
|
+
...connections ? { connections } : {}
|
|
1291
|
+
}
|
|
1292
|
+
);
|
|
1293
|
+
const lowered = result.workflows[0]?.definition;
|
|
1294
|
+
if (result.workflows.length !== 1 || !lowered) {
|
|
1295
|
+
all.push({
|
|
1296
|
+
kind: "lowering-failed",
|
|
1297
|
+
detail: `Lowering produced ${result.workflows.length} workflows instead of one`
|
|
1298
|
+
});
|
|
1299
|
+
} else if (chunkAU3YW7FZ_cjs.irHash(lowered) !== chunkAU3YW7FZ_cjs.irHash(reference)) {
|
|
1300
|
+
for (const change of chunkBYJ7QTLY_cjs.diffDefinitions(reference, lowered)) {
|
|
1301
|
+
all.push({
|
|
1302
|
+
path: change.path,
|
|
1303
|
+
kind: "roundtrip-mismatch",
|
|
1304
|
+
detail: `Lowering the code ${change.kind} this value`
|
|
1305
|
+
});
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
} catch (error) {
|
|
1309
|
+
all.push({
|
|
1310
|
+
kind: "lowering-failed",
|
|
1311
|
+
detail: error instanceof Error ? error.message : String(error)
|
|
1312
|
+
});
|
|
1313
|
+
}
|
|
1314
|
+
const level = all.some((item) => LOSSY_KINDS.has(item.kind)) ? "lossy" : "lossless";
|
|
1315
|
+
return { level, items: all };
|
|
1316
|
+
}
|
|
1317
|
+
async function exportWorkflowCode(definition, options2) {
|
|
1318
|
+
const ts = await liftToTypeScript(definition, options2);
|
|
1319
|
+
const fidelity = await checkFidelity(ts.files, ts.reference, ts.items, {
|
|
1320
|
+
...options2.esbuild ? { esbuild: options2.esbuild } : {},
|
|
1321
|
+
...options2.evaluator ? { evaluator: options2.evaluator } : {},
|
|
1322
|
+
...options2.connectionNames ? { connectionNames: options2.connectionNames } : {}
|
|
1323
|
+
});
|
|
1324
|
+
const files = options2.format === "PYTHON" ? (await liftToPython(definition, options2)).files : ts.files;
|
|
1325
|
+
return { format: options2.format, files, fidelity, irHash: chunkAU3YW7FZ_cjs.irHash(definition) };
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
Object.defineProperty(exports, "PY_LINE_LENGTH", {
|
|
1329
|
+
enumerable: true,
|
|
1330
|
+
get: function () { return chunkIZQNUNSU_cjs.PY_LINE_LENGTH; }
|
|
1331
|
+
});
|
|
1332
|
+
Object.defineProperty(exports, "TS_FORMAT_OPTIONS", {
|
|
1333
|
+
enumerable: true,
|
|
1334
|
+
get: function () { return chunkIZQNUNSU_cjs.TS_FORMAT_OPTIONS; }
|
|
1335
|
+
});
|
|
1336
|
+
Object.defineProperty(exports, "TS_NODES_IMPORT", {
|
|
1337
|
+
enumerable: true,
|
|
1338
|
+
get: function () { return chunkIZQNUNSU_cjs.TS_NODES_IMPORT; }
|
|
1339
|
+
});
|
|
1340
|
+
Object.defineProperty(exports, "createNodeVmEvaluator", {
|
|
1341
|
+
enumerable: true,
|
|
1342
|
+
get: function () { return chunk265J2FCH_cjs.createNodeVmEvaluator; }
|
|
1343
|
+
});
|
|
1344
|
+
Object.defineProperty(exports, "ESBUILD_VERSION", {
|
|
1345
|
+
enumerable: true,
|
|
1346
|
+
get: function () { return chunkLUXCXFOE_cjs.ESBUILD_VERSION; }
|
|
1347
|
+
});
|
|
1348
|
+
Object.defineProperty(exports, "EVALUATION_GLOBAL", {
|
|
1349
|
+
enumerable: true,
|
|
1350
|
+
get: function () { return chunkLUXCXFOE_cjs.EVALUATION_GLOBAL; }
|
|
1351
|
+
});
|
|
1352
|
+
Object.defineProperty(exports, "LowerError", {
|
|
1353
|
+
enumerable: true,
|
|
1354
|
+
get: function () { return chunkLUXCXFOE_cjs.LowerError; }
|
|
1355
|
+
});
|
|
1356
|
+
Object.defineProperty(exports, "bundleProject", {
|
|
1357
|
+
enumerable: true,
|
|
1358
|
+
get: function () { return chunkLUXCXFOE_cjs.bundleProject; }
|
|
1359
|
+
});
|
|
1360
|
+
Object.defineProperty(exports, "defaultEntries", {
|
|
1361
|
+
enumerable: true,
|
|
1362
|
+
get: function () { return chunkLUXCXFOE_cjs.defaultEntries; }
|
|
1363
|
+
});
|
|
1364
|
+
Object.defineProperty(exports, "lower", {
|
|
1365
|
+
enumerable: true,
|
|
1366
|
+
get: function () { return chunkLUXCXFOE_cjs.lower; }
|
|
1367
|
+
});
|
|
1368
|
+
exports.LiftError = LiftError;
|
|
1369
|
+
exports.PY_PROJECT_MODULE = PY_PROJECT_MODULE;
|
|
1370
|
+
exports.PY_SDK_MODULE = PY_SDK_MODULE;
|
|
1371
|
+
exports.checkFidelity = checkFidelity;
|
|
1372
|
+
exports.exportWorkflowCode = exportWorkflowCode;
|
|
1373
|
+
exports.liftToPython = liftToPython;
|
|
1374
|
+
exports.liftToTypeScript = liftToTypeScript;
|
|
1375
|
+
exports.prepareLift = prepareLift;
|