@fluidgrids/workflows 2026.1027.0 → 2026.1027.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.
Files changed (52) hide show
  1. package/README.md +26 -5
  2. package/dist/{assemble-DMOuaxRI.d.ts → assemble-CrpUyd_3.d.ts} +20 -2
  3. package/dist/{assemble-BJo9TECS.d.cts → assemble-DEf3znGD.d.cts} +20 -2
  4. package/dist/chunk-3M34AUIY.cjs +27 -0
  5. package/dist/chunk-5AW745OG.js +25 -0
  6. package/dist/{chunk-RRQ5HOBF.cjs → chunk-6AIAC2FP.cjs} +4 -4
  7. package/dist/{chunk-GO34UHSY.js → chunk-6BEW4QD6.js} +3 -3
  8. package/dist/{chunk-SS4LT2IP.js → chunk-6U446SKY.js} +5 -10
  9. package/dist/{chunk-AU3YW7FZ.cjs → chunk-7YR7DI7B.cjs} +46 -51
  10. package/dist/{chunk-27HASETB.cjs → chunk-CSYBNN3V.cjs} +3 -1
  11. package/dist/{chunk-LRM6JXJA.cjs → chunk-E3APHA6O.cjs} +19 -1
  12. package/dist/{chunk-BWSLWF2E.js → chunk-EEAIM35V.js} +38 -12
  13. package/dist/{chunk-X4HKU3MX.js → chunk-IHKXLG6I.js} +3 -1
  14. package/dist/chunk-MBBKGD7K.js +440 -0
  15. package/dist/{chunk-LSKSBVL4.cjs → chunk-OSPTJCDI.cjs} +6 -6
  16. package/dist/{chunk-KUTMY2IO.cjs → chunk-TQF7MYEN.cjs} +101 -75
  17. package/dist/{chunk-BYJ7QTLY.cjs → chunk-TWOYB4Y7.cjs} +13 -13
  18. package/dist/{chunk-PL73GJR4.js → chunk-UB2BHU2M.js} +1 -1
  19. package/dist/{chunk-REV7ZOA4.js → chunk-UJNHTS6D.js} +13 -2
  20. package/dist/{chunk-IZQNUNSU.cjs → chunk-UWQWD7BP.cjs} +17 -17
  21. package/dist/{chunk-4DPEGDPW.js → chunk-W32BSO3M.js} +4 -4
  22. package/dist/{chunk-LMX35GNQ.js → chunk-XBIID5DY.js} +4 -4
  23. package/dist/chunk-Y7NWR3WH.cjs +450 -0
  24. package/dist/codegen/index.cjs +7 -7
  25. package/dist/codegen/index.js +5 -5
  26. package/dist/index.cjs +30 -30
  27. package/dist/index.d.cts +3 -3
  28. package/dist/index.d.ts +3 -3
  29. package/dist/index.js +3 -3
  30. package/dist/ir/index.cjs +118 -116
  31. package/dist/ir/index.d.cts +18 -8
  32. package/dist/ir/index.d.ts +18 -8
  33. package/dist/ir/index.js +21 -19
  34. package/dist/{lower-Dw5grNrI.d.ts → lower-CXggJTIo.d.ts} +20 -2
  35. package/dist/{lower-DcOY8ux0.d.cts → lower-DAzvsJCo.d.cts} +20 -2
  36. package/dist/node-evaluator-CH3XCJND.cjs +17 -0
  37. package/dist/node-evaluator-TULXA3WE.js +8 -0
  38. package/dist/quickjs/index.cjs +32 -78
  39. package/dist/quickjs/index.d.cts +4 -4
  40. package/dist/quickjs/index.d.ts +4 -4
  41. package/dist/quickjs/index.js +32 -78
  42. package/dist/roundtrip/index.cjs +201 -128
  43. package/dist/roundtrip/index.d.cts +7 -4
  44. package/dist/roundtrip/index.d.ts +7 -4
  45. package/dist/roundtrip/index.js +87 -18
  46. package/package.json +44 -18
  47. package/dist/chunk-265J2FCH.cjs +0 -33
  48. package/dist/chunk-LUXCXFOE.cjs +0 -269
  49. package/dist/chunk-S34NJE3A.js +0 -262
  50. package/dist/chunk-SRQRLWOS.js +0 -31
  51. package/dist/node-evaluator-2GTUZVPK.cjs +0 -17
  52. package/dist/node-evaluator-RMYEWCXZ.js +0 -8
package/README.md CHANGED
@@ -79,8 +79,16 @@ calls, so the same source always gives the same IR.
79
79
  becomes `{{ $json.x }}`. Comparisons (`gte`, `eq`, `contains`, `isEmpty`, …,
80
80
  `and`, `or`) become the condition tree `internal:if` evaluates.
81
81
  - `connection: 'name'` resolves to a connection id when the workflow is pushed.
82
+ - Lowering must not read the clock or a random source while the workflow is
83
+ defined: `Date.now()`, `new Date()` / `Date()` without arguments,
84
+ `Math.random()`, `crypto.getRandomValues()` / `crypto.randomUUID()` and an
85
+ argument-less `Intl.DateTimeFormat` `format()` throw a `DeterminismViolation`
86
+ error in both evaluators. Use `wf.now` and other references for run-time values.
82
87
  - Positions come from the layout sidecar `workflows/<key>.layout.json`, or the
83
88
  automatic layout the AI draft generator uses.
89
+ - An edge without an explicit `id` gets `e-<source>-<target>[-<sourceHandle>][-<targetHandle>]`.
90
+ Ids may contain `-`, so two edges can share that default; the later ones get
91
+ `-2`, `-3`, … in declaration order. Only a repeated explicit id is an error.
84
92
  - `edge(source, { id, type, targetHandle, label, mapping, extra })`,
85
93
  `wf.connect`, `wf.edgeOrderIs` and the `extra` option on every node keep any
86
94
  stored definition expressible exactly.
@@ -116,14 +124,23 @@ const { buildId, workflows } = await lower(files, { connections });
116
124
  evaluates the bundle in an isolate. `buildId` is the SHA-256 of the bundle; it
117
125
  is identical with `esbuild` and `esbuild-wasm` of the same version, so the CLI
118
126
  and the service agree. Workflow code may import project files and
119
- `@fluidgrids/workflows` only.
127
+ `@fluidgrids/workflows` only. The sources are limited to `maxSourceBytes`
128
+ (default 1 MiB) before esbuild runs and the bundle to `maxBundleBytes`
129
+ (default 1.5 MiB) before it is evaluated; a `LowerError` with
130
+ `reason: 'too-large'` reports either.
120
131
  - **Evaluators**: the default is a fresh Node `vm` context (for the CLI, which
121
132
  runs the developer's own code). Services use `createQuickJSEvaluator()` from
122
133
  `@fluidgrids/workflows/quickjs` (quickjs-emscripten 0.32.0, the engine the
123
- workers use), which bounds memory and time.
134
+ workers use), which bounds memory exactly. Both evaluate in a worker thread
135
+ that is terminated at `timeoutMs`, so the budget covers parsing and compiling
136
+ the bundle, promise jobs and anything the code leaves behind, and the calling
137
+ process never runs or inspects a value from the isolate. Failures are
138
+ `LowerError`s with a `reason` (`timeout`, `determinism`, `out-of-memory`, …).
124
139
  - **Fidelity** is `lossless` when `irHash(lower(lift(ir))) == irHash(ir)`. Items
125
140
  report what is kept as plain strings or exact forms: `expression-verbatim`,
126
- `legacy-syntax`, `unknown-node`, `connection-id-only`, `raw-node`, `key-added`;
141
+ `legacy-syntax`, `unknown-node`, `connection-id-only`, `connection-ambiguous`
142
+ (a connection name that more than one connection id has, so the id is kept),
143
+ `raw-node`, `key-added`;
127
144
  `layout-omitted`, `pinned-data-omitted`, `roundtrip-mismatch` and
128
145
  `lowering-failed` make an export lossy.
129
146
 
@@ -133,8 +150,12 @@ const { buildId, workflows } = await lower(files, { connections });
133
150
  `config` on internal nodes) into the canonical node fields following the
134
151
  executor's own reading order, so no executor-visible value changes
135
152
  (`executorView` computes what the executor reads, for checking). It is pure
136
- and idempotent. The one mirror it keeps is `data.executionSettings.runOn`,
137
- because today's executor reads `runOn` only there.
153
+ and idempotent. It keeps the mirrors some executor path reads from the data
154
+ bag only: `data.executionSettings.runOn`, `data.operation_name` (the agent tool
155
+ binding) and an external node's `data.version` (node-state rows). It does not
156
+ promote an external node's `data.state`, which the sub-node paths do not read;
157
+ `validate --strict` reports it. Keys named `__proto__` are ordinary keys
158
+ everywhere (copies, hashes, lift and lower).
138
159
  - `irHash` is `sha256:` + the SHA-256 of the RFC 8785 canonical JSON of the
139
160
  normalised definition without `authoring`.
140
161
  - `validate(definition, { strict, isTaskQueueKnown })` applies the service's
@@ -270,7 +270,11 @@ interface CompareRef extends NodeRef {
270
270
  }
271
271
  /** Options of an explicit edge, made with {@link edge}. */
272
272
  interface EdgeOptions {
273
- /** Edge id. Default: `e-<source>-<target>[-<sourceHandle>][-<targetHandle>]`; `false` writes none. */
273
+ /**
274
+ * Edge id. Default: `e-<source>-<target>[-<sourceHandle>][-<targetHandle>]`, with
275
+ * `-2`, `-3`, … added in declaration order when that id is already taken;
276
+ * `false` writes none.
277
+ */
274
278
  id?: string | false;
275
279
  /** Edge type. Default `deletable` (what the canvas writes); `false` writes none. */
276
280
  type?: string | false;
@@ -387,7 +391,11 @@ interface Tier1Workflow {
387
391
  }
388
392
  /** True for a value returned by {@link defineWorkflow}. */
389
393
  declare function isTier1Workflow(value: unknown): value is Tier1Workflow;
390
- /** Default edge id, the scheme the AI draft generator uses. */
394
+ /**
395
+ * Default edge id, the scheme the AI draft generator uses. Ids may contain `-`,
396
+ * so two edges can share a default id (`a` to `b-c` and `a-b` to `c`); the
397
+ * builder then gives the later edges `-2`, `-3`, … in declaration order.
398
+ */
391
399
  declare function defaultEdgeId(source: string, target: string, sourceHandle?: string, targetHandle?: string): string;
392
400
  /** Options of `wf.if`. */
393
401
  interface IfOptions extends NodeOptions {
@@ -447,7 +455,10 @@ declare class WorkflowBuilder {
447
455
  private readonly edges;
448
456
  private readonly notes;
449
457
  private readonly ids;
458
+ /** Ids given explicitly; a second edge with the same explicit id is an error. */
450
459
  private readonly edgeIds;
460
+ /** Edges whose id is the default, as indices into `edges`, with the unsuffixed default id. */
461
+ private readonly defaultIds;
451
462
  private edgeOrder;
452
463
  constructor(autoIds: boolean);
453
464
  /** A reference to a node by id, for nodes declared later in the source. */
@@ -525,6 +536,13 @@ declare class WorkflowBuilder {
525
536
  finish(key: string, document: JsonObject): Tier1Recording;
526
537
  private claimId;
527
538
  private resolveId;
539
+ /**
540
+ * Give every edge declared without an id its default id. Explicit ids are
541
+ * claimed first, so a default never takes an id the code names; a default that
542
+ * is taken gets `-2`, `-3`, … in declaration order. The result depends only on
543
+ * the builder calls.
544
+ */
545
+ private assignDefaultEdgeIds;
528
546
  private addEdge;
529
547
  private add;
530
548
  }
@@ -270,7 +270,11 @@ interface CompareRef extends NodeRef {
270
270
  }
271
271
  /** Options of an explicit edge, made with {@link edge}. */
272
272
  interface EdgeOptions {
273
- /** Edge id. Default: `e-<source>-<target>[-<sourceHandle>][-<targetHandle>]`; `false` writes none. */
273
+ /**
274
+ * Edge id. Default: `e-<source>-<target>[-<sourceHandle>][-<targetHandle>]`, with
275
+ * `-2`, `-3`, … added in declaration order when that id is already taken;
276
+ * `false` writes none.
277
+ */
274
278
  id?: string | false;
275
279
  /** Edge type. Default `deletable` (what the canvas writes); `false` writes none. */
276
280
  type?: string | false;
@@ -387,7 +391,11 @@ interface Tier1Workflow {
387
391
  }
388
392
  /** True for a value returned by {@link defineWorkflow}. */
389
393
  declare function isTier1Workflow(value: unknown): value is Tier1Workflow;
390
- /** Default edge id, the scheme the AI draft generator uses. */
394
+ /**
395
+ * Default edge id, the scheme the AI draft generator uses. Ids may contain `-`,
396
+ * so two edges can share a default id (`a` to `b-c` and `a-b` to `c`); the
397
+ * builder then gives the later edges `-2`, `-3`, … in declaration order.
398
+ */
391
399
  declare function defaultEdgeId(source: string, target: string, sourceHandle?: string, targetHandle?: string): string;
392
400
  /** Options of `wf.if`. */
393
401
  interface IfOptions extends NodeOptions {
@@ -447,7 +455,10 @@ declare class WorkflowBuilder {
447
455
  private readonly edges;
448
456
  private readonly notes;
449
457
  private readonly ids;
458
+ /** Ids given explicitly; a second edge with the same explicit id is an error. */
450
459
  private readonly edgeIds;
460
+ /** Edges whose id is the default, as indices into `edges`, with the unsuffixed default id. */
461
+ private readonly defaultIds;
451
462
  private edgeOrder;
452
463
  constructor(autoIds: boolean);
453
464
  /** A reference to a node by id, for nodes declared later in the source. */
@@ -525,6 +536,13 @@ declare class WorkflowBuilder {
525
536
  finish(key: string, document: JsonObject): Tier1Recording;
526
537
  private claimId;
527
538
  private resolveId;
539
+ /**
540
+ * Give every edge declared without an id its default id. Explicit ids are
541
+ * claimed first, so a default never takes an id the code names; a default that
542
+ * is taken gets `-2`, `-3`, … in declaration order. The result depends only on
543
+ * the builder calls.
544
+ */
545
+ private assignDefaultEdgeIds;
528
546
  private addEdge;
529
547
  private add;
530
548
  }
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ var chunkY7NWR3WH_cjs = require('./chunk-Y7NWR3WH.cjs');
4
+
5
+ // src/generated/vm-worker-source.ts
6
+ var VM_WORKER_SOURCE = '"use strict";\n\nvar import_node_worker_threads = require("node:worker_threads");\n\nfunction isRecord(value) {\n return typeof value === "object" && value !== null && !Array.isArray(value);\n}\n\nvar DETERMINISM_VIOLATION = "DeterminismViolation";\nvar DETERMINISM_PRELUDE = `(() => {\n const NAME = ${JSON.stringify(DETERMINISM_VIOLATION)};\n const fail = (what) => {\n const error = new Error(\n what + " is not allowed in workflow code: lowering must give the same IR on every build. Read times and random values at run time instead (for example wf.now)."\n );\n error.name = NAME;\n throw error;\n };\n const lock = (target, key, value) =>\n Object.defineProperty(target, key, { value, writable: false, enumerable: false, configurable: false });\n const RealDate = Date;\n const LockedDate = function Date(...args) {\n if (new.target === undefined) return fail("Date()");\n if (args.length === 0) return fail("new Date()");\n return Reflect.construct(RealDate, args, new.target);\n };\n lock(LockedDate, "prototype", RealDate.prototype);\n lock(RealDate.prototype, "constructor", LockedDate);\n lock(LockedDate, "now", function now() { return fail("Date.now()"); });\n lock(LockedDate, "parse", RealDate.parse);\n lock(LockedDate, "UTC", RealDate.UTC);\n lock(globalThis, "Date", LockedDate);\n lock(Math, "random", function random() { return fail("Math.random()"); });\n const crypto = globalThis.crypto;\n if (crypto !== null && typeof crypto === "object") {\n for (const name of ["getRandomValues", "randomUUID"]) {\n if (typeof crypto[name] === "function") lock(crypto, name, function () { return fail("crypto." + name + "()"); });\n }\n }\n const DateTimeFormat = typeof Intl === "object" && Intl !== null ? Intl.DateTimeFormat : undefined;\n if (typeof DateTimeFormat === "function") {\n const proto = DateTimeFormat.prototype;\n const format = Object.getOwnPropertyDescriptor(proto, "format");\n if (format && typeof format.get === "function") {\n const get = format.get;\n Object.defineProperty(proto, "format", {\n get() {\n const bound = get.call(this);\n return (date) => (date === undefined ? fail("Intl.DateTimeFormat format()") : bound(date));\n },\n enumerable: false,\n configurable: false,\n });\n }\n const formatToParts = proto.formatToParts;\n if (typeof formatToParts === "function") {\n lock(proto, "formatToParts", function (date) {\n return date === undefined ? fail("Intl.DateTimeFormat formatToParts()") : formatToParts.call(this, date);\n });\n }\n }\n})();\n`;\nfunction failure(kind, message) {\n return { ok: false, failure: kind, message };\n}\n\nvar import_node_vm = require("node:vm");\nvar import_node_util = require("node:util");\nvar BUNDLE_GLOBAL = "__fluidgridsBundle";\nfunction wrap(code) {\n return `(function () {\n const describe = (error) => {\n let name = "Error";\n let message = "";\n try {\n if (error !== null && (typeof error === "object" || typeof error === "function")) {\n const n = error.name;\n if (typeof n === "string") name = n;\n const m = error.message;\n message = typeof m === "string" ? m : m === undefined ? "" + error : "" + m;\n } else {\n message = "" + error;\n }\n } catch (_) {\n message = "a value whose message cannot be read was thrown";\n }\n return (name === ${JSON.stringify(DETERMINISM_VIOLATION)} ? "D" : "E") + message;\n };\n try {\n${code}\n;const __fluidgridsValue = ${BUNDLE_GLOBAL}.__fluidgrids;\n return typeof __fluidgridsValue === "string" ? "R" + __fluidgridsValue : "N";\n } catch (error) {\n try {\n return describe(error);\n } catch (_) {\n return "Ean error that cannot be described was thrown";\n }\n }\n})()`;\n}\nfunction hostErrorFields(error) {\n if (!import_node_util.types.isNativeError(error)) return {};\n const code = Object.getOwnPropertyDescriptor(error, "code")?.value;\n const message = Object.getOwnPropertyDescriptor(error, "message")?.value;\n return {\n ...typeof code === "string" ? { code } : {},\n ...typeof message === "string" ? { message } : {}\n };\n}\nfunction decode(result) {\n const tag = result.charAt(0);\n const rest = result.slice(1);\n if (tag === "R") return { ok: true, value: rest };\n if (tag === "N")\n return failure("no-collection", "The bundle did not export a workflow collection");\n if (tag === "D") return failure("determinism", rest);\n return failure("error", rest);\n}\nfunction runInVmContext(code, timeoutMs) {\n const context = (0, import_node_vm.createContext)(/* @__PURE__ */ Object.create(null), {\n codeGeneration: { strings: false, wasm: false },\n microtaskMode: "afterEvaluate",\n name: "fluidgrids-workflow-lowering"\n });\n const refuseImport = () => {\n throw new Error("Workflow code may not import modules at run time");\n };\n const deadline = Date.now() + timeoutMs;\n const run = (source, filename) => new import_node_vm.Script(source, { filename, importModuleDynamically: refuseImport }).runInContext(context, {\n timeout: Math.max(1, deadline - Date.now()),\n breakOnSigint: true\n });\n try {\n run(DETERMINISM_PRELUDE, "determinism-prelude.js");\n const result = run(wrap(code), "workflow-bundle.js");\n return typeof result === "string" ? decode(result) : failure("no-collection", "The bundle did not export a workflow collection");\n } catch (error) {\n const fields = hostErrorFields(error);\n if (fields.code === "ERR_SCRIPT_EXECUTION_TIMEOUT" || fields.message !== void 0 && /^Script execution timed out/.test(fields.message)) {\n return failure("timeout", `Evaluating the workflow code timed out after ${timeoutMs} ms`);\n }\n return failure("error", fields.message ?? "The workflow code could not be evaluated");\n }\n}\n\nprocess.on("unhandledRejection", () => void 0);\nvar input = import_node_worker_threads.workerData;\nimport_node_worker_threads.parentPort?.postMessage(\n isRecord(input) && typeof input["code"] === "string" && typeof input["timeoutMs"] === "number" ? runInVmContext(input["code"], input["timeoutMs"]) : failure("crashed", "The evaluation worker received no bundle")\n);\n';
7
+
8
+ // src/roundtrip/node-evaluator.ts
9
+ var MIB = 1024 * 1024;
10
+ function createNodeVmEvaluator(options = {}) {
11
+ const timeoutMs = options.timeoutMs ?? 5e3;
12
+ const memoryLimitBytes = options.memoryLimitBytes ?? 512 * MIB;
13
+ return {
14
+ format: "iife",
15
+ async evaluate(code) {
16
+ const outcome = await chunkY7NWR3WH_cjs.runIsolateWorker({
17
+ source: VM_WORKER_SOURCE,
18
+ workerData: { code, timeoutMs },
19
+ timeoutMs,
20
+ resourceLimits: { maxOldGenerationSizeMb: Math.max(16, Math.ceil(memoryLimitBytes / MIB)) }
21
+ });
22
+ return chunkY7NWR3WH_cjs.outcomeToCollection(outcome);
23
+ }
24
+ };
25
+ }
26
+
27
+ exports.createNodeVmEvaluator = createNodeVmEvaluator;
@@ -0,0 +1,25 @@
1
+ import { runIsolateWorker, outcomeToCollection } from './chunk-MBBKGD7K.js';
2
+
3
+ // src/generated/vm-worker-source.ts
4
+ var VM_WORKER_SOURCE = '"use strict";\n\nvar import_node_worker_threads = require("node:worker_threads");\n\nfunction isRecord(value) {\n return typeof value === "object" && value !== null && !Array.isArray(value);\n}\n\nvar DETERMINISM_VIOLATION = "DeterminismViolation";\nvar DETERMINISM_PRELUDE = `(() => {\n const NAME = ${JSON.stringify(DETERMINISM_VIOLATION)};\n const fail = (what) => {\n const error = new Error(\n what + " is not allowed in workflow code: lowering must give the same IR on every build. Read times and random values at run time instead (for example wf.now)."\n );\n error.name = NAME;\n throw error;\n };\n const lock = (target, key, value) =>\n Object.defineProperty(target, key, { value, writable: false, enumerable: false, configurable: false });\n const RealDate = Date;\n const LockedDate = function Date(...args) {\n if (new.target === undefined) return fail("Date()");\n if (args.length === 0) return fail("new Date()");\n return Reflect.construct(RealDate, args, new.target);\n };\n lock(LockedDate, "prototype", RealDate.prototype);\n lock(RealDate.prototype, "constructor", LockedDate);\n lock(LockedDate, "now", function now() { return fail("Date.now()"); });\n lock(LockedDate, "parse", RealDate.parse);\n lock(LockedDate, "UTC", RealDate.UTC);\n lock(globalThis, "Date", LockedDate);\n lock(Math, "random", function random() { return fail("Math.random()"); });\n const crypto = globalThis.crypto;\n if (crypto !== null && typeof crypto === "object") {\n for (const name of ["getRandomValues", "randomUUID"]) {\n if (typeof crypto[name] === "function") lock(crypto, name, function () { return fail("crypto." + name + "()"); });\n }\n }\n const DateTimeFormat = typeof Intl === "object" && Intl !== null ? Intl.DateTimeFormat : undefined;\n if (typeof DateTimeFormat === "function") {\n const proto = DateTimeFormat.prototype;\n const format = Object.getOwnPropertyDescriptor(proto, "format");\n if (format && typeof format.get === "function") {\n const get = format.get;\n Object.defineProperty(proto, "format", {\n get() {\n const bound = get.call(this);\n return (date) => (date === undefined ? fail("Intl.DateTimeFormat format()") : bound(date));\n },\n enumerable: false,\n configurable: false,\n });\n }\n const formatToParts = proto.formatToParts;\n if (typeof formatToParts === "function") {\n lock(proto, "formatToParts", function (date) {\n return date === undefined ? fail("Intl.DateTimeFormat formatToParts()") : formatToParts.call(this, date);\n });\n }\n }\n})();\n`;\nfunction failure(kind, message) {\n return { ok: false, failure: kind, message };\n}\n\nvar import_node_vm = require("node:vm");\nvar import_node_util = require("node:util");\nvar BUNDLE_GLOBAL = "__fluidgridsBundle";\nfunction wrap(code) {\n return `(function () {\n const describe = (error) => {\n let name = "Error";\n let message = "";\n try {\n if (error !== null && (typeof error === "object" || typeof error === "function")) {\n const n = error.name;\n if (typeof n === "string") name = n;\n const m = error.message;\n message = typeof m === "string" ? m : m === undefined ? "" + error : "" + m;\n } else {\n message = "" + error;\n }\n } catch (_) {\n message = "a value whose message cannot be read was thrown";\n }\n return (name === ${JSON.stringify(DETERMINISM_VIOLATION)} ? "D" : "E") + message;\n };\n try {\n${code}\n;const __fluidgridsValue = ${BUNDLE_GLOBAL}.__fluidgrids;\n return typeof __fluidgridsValue === "string" ? "R" + __fluidgridsValue : "N";\n } catch (error) {\n try {\n return describe(error);\n } catch (_) {\n return "Ean error that cannot be described was thrown";\n }\n }\n})()`;\n}\nfunction hostErrorFields(error) {\n if (!import_node_util.types.isNativeError(error)) return {};\n const code = Object.getOwnPropertyDescriptor(error, "code")?.value;\n const message = Object.getOwnPropertyDescriptor(error, "message")?.value;\n return {\n ...typeof code === "string" ? { code } : {},\n ...typeof message === "string" ? { message } : {}\n };\n}\nfunction decode(result) {\n const tag = result.charAt(0);\n const rest = result.slice(1);\n if (tag === "R") return { ok: true, value: rest };\n if (tag === "N")\n return failure("no-collection", "The bundle did not export a workflow collection");\n if (tag === "D") return failure("determinism", rest);\n return failure("error", rest);\n}\nfunction runInVmContext(code, timeoutMs) {\n const context = (0, import_node_vm.createContext)(/* @__PURE__ */ Object.create(null), {\n codeGeneration: { strings: false, wasm: false },\n microtaskMode: "afterEvaluate",\n name: "fluidgrids-workflow-lowering"\n });\n const refuseImport = () => {\n throw new Error("Workflow code may not import modules at run time");\n };\n const deadline = Date.now() + timeoutMs;\n const run = (source, filename) => new import_node_vm.Script(source, { filename, importModuleDynamically: refuseImport }).runInContext(context, {\n timeout: Math.max(1, deadline - Date.now()),\n breakOnSigint: true\n });\n try {\n run(DETERMINISM_PRELUDE, "determinism-prelude.js");\n const result = run(wrap(code), "workflow-bundle.js");\n return typeof result === "string" ? decode(result) : failure("no-collection", "The bundle did not export a workflow collection");\n } catch (error) {\n const fields = hostErrorFields(error);\n if (fields.code === "ERR_SCRIPT_EXECUTION_TIMEOUT" || fields.message !== void 0 && /^Script execution timed out/.test(fields.message)) {\n return failure("timeout", `Evaluating the workflow code timed out after ${timeoutMs} ms`);\n }\n return failure("error", fields.message ?? "The workflow code could not be evaluated");\n }\n}\n\nprocess.on("unhandledRejection", () => void 0);\nvar input = import_node_worker_threads.workerData;\nimport_node_worker_threads.parentPort?.postMessage(\n isRecord(input) && typeof input["code"] === "string" && typeof input["timeoutMs"] === "number" ? runInVmContext(input["code"], input["timeoutMs"]) : failure("crashed", "The evaluation worker received no bundle")\n);\n';
5
+
6
+ // src/roundtrip/node-evaluator.ts
7
+ var MIB = 1024 * 1024;
8
+ function createNodeVmEvaluator(options = {}) {
9
+ const timeoutMs = options.timeoutMs ?? 5e3;
10
+ const memoryLimitBytes = options.memoryLimitBytes ?? 512 * MIB;
11
+ return {
12
+ format: "iife",
13
+ async evaluate(code) {
14
+ const outcome = await runIsolateWorker({
15
+ source: VM_WORKER_SOURCE,
16
+ workerData: { code, timeoutMs },
17
+ timeoutMs,
18
+ resourceLimits: { maxOldGenerationSizeMb: Math.max(16, Math.ceil(memoryLimitBytes / MIB)) }
19
+ });
20
+ return outcomeToCollection(outcome);
21
+ }
22
+ };
23
+ }
24
+
25
+ export { createNodeVmEvaluator };
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkLRM6JXJA_cjs = require('./chunk-LRM6JXJA.cjs');
3
+ var chunkE3APHA6O_cjs = require('./chunk-E3APHA6O.cjs');
4
4
 
5
5
  // src/builder/refs.ts
6
6
  var REF_MODEL = /* @__PURE__ */ Symbol.for("fluidgrids.workflows.ref");
@@ -101,7 +101,7 @@ function callOnRef(model, args) {
101
101
  }
102
102
  function makeRef(root, path = []) {
103
103
  const model = { root, path };
104
- const render = () => chunkLRM6JXJA_cjs.formatRefTemplate(model);
104
+ const render = () => chunkE3APHA6O_cjs.formatRefTemplate(model);
105
105
  const target = function fluidgridsRef() {
106
106
  return void 0;
107
107
  };
@@ -112,7 +112,7 @@ function makeRef(root, path = []) {
112
112
  if (typeof property === "symbol") return void 0;
113
113
  if (property === "then") return void 0;
114
114
  if (property === "toJSON" || property === "toString" || property === "valueOf") return render;
115
- return makeRef(root, [...path, chunkLRM6JXJA_cjs.segmentFromKey(property)]);
115
+ return makeRef(root, [...path, chunkE3APHA6O_cjs.segmentFromKey(property)]);
116
116
  },
117
117
  apply(_target, _thisArg, args) {
118
118
  return callOnRef(model, args);
@@ -162,7 +162,7 @@ function expr(strings, ...values) {
162
162
  let out = strings[0] ?? "";
163
163
  values.forEach((value, index) => {
164
164
  const model = refModelOf(value);
165
- if (model) out += chunkLRM6JXJA_cjs.formatRefTemplate(model);
165
+ if (model) out += chunkE3APHA6O_cjs.formatRefTemplate(model);
166
166
  else if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
167
167
  out += String(value);
168
168
  } else {
@@ -1,4 +1,4 @@
1
- import { isRecord } from './chunk-REV7ZOA4.js';
1
+ import { isRecord, setOwn } from './chunk-UJNHTS6D.js';
2
2
 
3
3
  // src/ir/manifest.ts
4
4
  function operationsOf(manifest) {
@@ -50,7 +50,7 @@ function fieldSchema(value) {
50
50
  if (isRecord(field.properties)) {
51
51
  const properties = {};
52
52
  for (const [name, child] of Object.entries(field.properties))
53
- properties[name] = fieldSchema(child);
53
+ setOwn(properties, name, fieldSchema(child));
54
54
  return { type: "object", properties, ...description };
55
55
  }
56
56
  return { type: "object", ...description };
@@ -63,7 +63,7 @@ function fieldsSchema(fields) {
63
63
  const properties = {};
64
64
  const required = [];
65
65
  for (const [name, field] of Object.entries(fields ?? {})) {
66
- properties[name] = fieldSchema(field);
66
+ setOwn(properties, name, fieldSchema(field));
67
67
  if (fieldOf(field).required === true) required.push(name);
68
68
  }
69
69
  return {
@@ -1,6 +1,6 @@
1
1
  import { autoLayout } from './chunk-5LUIDMF4.js';
2
- import { sha256Tagged, canonicalJson } from './chunk-X4HKU3MX.js';
3
- import { isRecord, cloneJson, deepEqual } from './chunk-REV7ZOA4.js';
2
+ import { sha256Tagged, canonicalJson } from './chunk-IHKXLG6I.js';
3
+ import { isRecord, cloneJson, deepEqual, setOwn } from './chunk-UJNHTS6D.js';
4
4
 
5
5
  // src/ir/node-types.ts
6
6
  var EXECUTOR_INTERNAL_TYPES = /* @__PURE__ */ new Set([
@@ -97,16 +97,11 @@ function normalizeOperation(node, data) {
97
97
  if (!isNonEmptyString(node["operation_name"]) && isNonEmptyString(data["operation_name"])) {
98
98
  node["operation_name"] = data["operation_name"];
99
99
  }
100
- if (data["operation_name"] !== void 0 && deepEqual(data["operation_name"], node["operation_name"])) {
101
- delete data["operation_name"];
102
- }
103
100
  }
104
101
  function normalizeVersion(node, data, merged) {
105
102
  if (merged) return;
106
103
  const effective = firstTruthy(data["version"], node["version"]);
107
104
  if (typeof effective === "string") node["version"] = effective;
108
- if (data["version"] !== void 0 && deepEqual(data["version"], node["version"]))
109
- delete data["version"];
110
105
  if (data["nodeVersion"] !== void 0 && deepEqual(data["nodeVersion"], node["version"])) {
111
106
  delete data["nodeVersion"];
112
107
  }
@@ -114,7 +109,7 @@ function normalizeVersion(node, data, merged) {
114
109
  function normalizeExternalState(node, data) {
115
110
  const args = isRecord(node["args"]) ? node["args"] : void 0;
116
111
  const dataArgs = isRecord(data["args"]) ? data["args"] : void 0;
117
- const effective = firstTruthy(args?.["state"], dataArgs?.["state"], data["state"]);
112
+ const effective = firstTruthy(args?.["state"], dataArgs?.["state"]);
118
113
  if (effective !== void 0 && args?.["state"] === void 0) {
119
114
  const nextArgs = args ?? {};
120
115
  nextArgs["state"] = effective;
@@ -124,7 +119,6 @@ function normalizeExternalState(node, data) {
124
119
  if (dataArgs && dataArgs["state"] !== void 0 && deepEqual(dataArgs["state"], rootState)) {
125
120
  delete dataArgs["state"];
126
121
  }
127
- if (data["state"] !== void 0 && deepEqual(data["state"], rootState)) delete data["state"];
128
122
  }
129
123
  function normalizeMergedState(node, data) {
130
124
  const args = isRecord(node["args"]) ? node["args"] : {};
@@ -163,6 +157,7 @@ function normalizeErrorConfig(node, data) {
163
157
  const dataState = isRecord(dataArgs?.["state"]) ? dataArgs["state"] : void 0;
164
158
  const effective = node["errorConfig"] ?? data["errorConfig"] ?? dataState?.["errorConfig"];
165
159
  if (effective !== void 0 && effective !== null) node["errorConfig"] = effective;
160
+ else if (node["errorConfig"] === null) delete node["errorConfig"];
166
161
  if (data["errorConfig"] !== void 0 && deepEqual(data["errorConfig"], node["errorConfig"])) {
167
162
  delete data["errorConfig"];
168
163
  }
@@ -173,7 +168,7 @@ function normalizeExecutionSettings(node, data) {
173
168
  if (!root && !mirror) return;
174
169
  const merged = { ...root };
175
170
  for (const [key, value] of Object.entries(mirror ?? {}))
176
- if (!Object.hasOwn(merged, key)) merged[key] = value;
171
+ if (!Object.hasOwn(merged, key)) setOwn(merged, key, value);
177
172
  if (root?.["executeOnce"] === true || mirror?.["executeOnce"] === true)
178
173
  merged["executeOnce"] = true;
179
174
  if (mirror && Object.hasOwn(mirror, "runOn")) {
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkG4UEPUGO_cjs = require('./chunk-G4UEPUGO.cjs');
4
- var chunk27HASETB_cjs = require('./chunk-27HASETB.cjs');
5
- var chunkLRM6JXJA_cjs = require('./chunk-LRM6JXJA.cjs');
4
+ var chunkCSYBNN3V_cjs = require('./chunk-CSYBNN3V.cjs');
5
+ var chunkE3APHA6O_cjs = require('./chunk-E3APHA6O.cjs');
6
6
 
7
7
  // src/ir/node-types.ts
8
8
  var EXECUTOR_INTERNAL_TYPES = /* @__PURE__ */ new Set([
@@ -82,58 +82,52 @@ function firstTruthy(...values) {
82
82
  return void 0;
83
83
  }
84
84
  function readPosition(value) {
85
- if (!chunkLRM6JXJA_cjs.isRecord(value)) return void 0;
85
+ if (!chunkE3APHA6O_cjs.isRecord(value)) return void 0;
86
86
  const { x, y } = value;
87
87
  return typeof x === "number" && typeof y === "number" && Number.isFinite(x) && Number.isFinite(y) ? { x, y } : void 0;
88
88
  }
89
89
  function removeIfEmpty(parent, key) {
90
90
  const value = parent[key];
91
- if (chunkLRM6JXJA_cjs.isRecord(value) && Object.keys(value).length === 0) delete parent[key];
91
+ if (chunkE3APHA6O_cjs.isRecord(value) && Object.keys(value).length === 0) delete parent[key];
92
92
  }
93
93
  function normalizeLabel(node, data) {
94
94
  if (node["label"] === void 0 && typeof data["label"] === "string")
95
95
  node["label"] = data["label"];
96
- if (data["label"] !== void 0 && chunkLRM6JXJA_cjs.deepEqual(data["label"], node["label"])) delete data["label"];
96
+ if (data["label"] !== void 0 && chunkE3APHA6O_cjs.deepEqual(data["label"], node["label"])) delete data["label"];
97
97
  }
98
98
  function normalizeOperation(node, data) {
99
99
  if (!isNonEmptyString(node["operation_name"]) && isNonEmptyString(data["operation_name"])) {
100
100
  node["operation_name"] = data["operation_name"];
101
101
  }
102
- if (data["operation_name"] !== void 0 && chunkLRM6JXJA_cjs.deepEqual(data["operation_name"], node["operation_name"])) {
103
- delete data["operation_name"];
104
- }
105
102
  }
106
103
  function normalizeVersion(node, data, merged) {
107
104
  if (merged) return;
108
105
  const effective = firstTruthy(data["version"], node["version"]);
109
106
  if (typeof effective === "string") node["version"] = effective;
110
- if (data["version"] !== void 0 && chunkLRM6JXJA_cjs.deepEqual(data["version"], node["version"]))
111
- delete data["version"];
112
- if (data["nodeVersion"] !== void 0 && chunkLRM6JXJA_cjs.deepEqual(data["nodeVersion"], node["version"])) {
107
+ if (data["nodeVersion"] !== void 0 && chunkE3APHA6O_cjs.deepEqual(data["nodeVersion"], node["version"])) {
113
108
  delete data["nodeVersion"];
114
109
  }
115
110
  }
116
111
  function normalizeExternalState(node, data) {
117
- const args = chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"] : void 0;
118
- const dataArgs = chunkLRM6JXJA_cjs.isRecord(data["args"]) ? data["args"] : void 0;
119
- const effective = firstTruthy(args?.["state"], dataArgs?.["state"], data["state"]);
112
+ const args = chunkE3APHA6O_cjs.isRecord(node["args"]) ? node["args"] : void 0;
113
+ const dataArgs = chunkE3APHA6O_cjs.isRecord(data["args"]) ? data["args"] : void 0;
114
+ const effective = firstTruthy(args?.["state"], dataArgs?.["state"]);
120
115
  if (effective !== void 0 && args?.["state"] === void 0) {
121
116
  const nextArgs = args ?? {};
122
117
  nextArgs["state"] = effective;
123
118
  node["args"] = nextArgs;
124
119
  }
125
- const rootState = chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"]["state"] : void 0;
126
- if (dataArgs && dataArgs["state"] !== void 0 && chunkLRM6JXJA_cjs.deepEqual(dataArgs["state"], rootState)) {
120
+ const rootState = chunkE3APHA6O_cjs.isRecord(node["args"]) ? node["args"]["state"] : void 0;
121
+ if (dataArgs && dataArgs["state"] !== void 0 && chunkE3APHA6O_cjs.deepEqual(dataArgs["state"], rootState)) {
127
122
  delete dataArgs["state"];
128
123
  }
129
- if (data["state"] !== void 0 && chunkLRM6JXJA_cjs.deepEqual(data["state"], rootState)) delete data["state"];
130
124
  }
131
125
  function normalizeMergedState(node, data) {
132
- const args = chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"] : {};
133
- const dataArgs = chunkLRM6JXJA_cjs.isRecord(data["args"]) ? data["args"] : void 0;
134
- const config = chunkLRM6JXJA_cjs.isRecord(node["config"]) ? node["config"] : void 0;
135
- const dataState = chunkLRM6JXJA_cjs.isRecord(dataArgs?.["state"]) ? dataArgs["state"] : void 0;
136
- const rootState = chunkLRM6JXJA_cjs.isRecord(args["state"]) ? args["state"] : void 0;
126
+ const args = chunkE3APHA6O_cjs.isRecord(node["args"]) ? node["args"] : {};
127
+ const dataArgs = chunkE3APHA6O_cjs.isRecord(data["args"]) ? data["args"] : void 0;
128
+ const config = chunkE3APHA6O_cjs.isRecord(node["config"]) ? node["config"] : void 0;
129
+ const dataState = chunkE3APHA6O_cjs.isRecord(dataArgs?.["state"]) ? dataArgs["state"] : void 0;
130
+ const rootState = chunkE3APHA6O_cjs.isRecord(args["state"]) ? args["state"] : void 0;
137
131
  if (config === void 0 && dataState === void 0) return;
138
132
  args["state"] = { ...config, ...dataState, ...rootState };
139
133
  node["args"] = args;
@@ -141,41 +135,42 @@ function normalizeMergedState(node, data) {
141
135
  if (dataArgs && dataState !== void 0) delete dataArgs["state"];
142
136
  }
143
137
  function normalizeConnections(node, data) {
144
- const dataArgs = chunkLRM6JXJA_cjs.isRecord(data["args"]) ? data["args"] : void 0;
138
+ const dataArgs = chunkE3APHA6O_cjs.isRecord(data["args"]) ? data["args"] : void 0;
145
139
  if (!dataArgs) return;
146
140
  for (const key of ["connections", "credentials"]) {
147
- const args = chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"] : void 0;
141
+ const args = chunkE3APHA6O_cjs.isRecord(node["args"]) ? node["args"] : void 0;
148
142
  if (!args?.[key] && dataArgs[key]) {
149
143
  const nextArgs = args ?? {};
150
144
  nextArgs[key] = dataArgs[key];
151
145
  node["args"] = nextArgs;
152
146
  }
153
- const rootValue = chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"][key] : void 0;
154
- if (dataArgs[key] !== void 0 && chunkLRM6JXJA_cjs.deepEqual(dataArgs[key], rootValue)) delete dataArgs[key];
147
+ const rootValue = chunkE3APHA6O_cjs.isRecord(node["args"]) ? node["args"][key] : void 0;
148
+ if (dataArgs[key] !== void 0 && chunkE3APHA6O_cjs.deepEqual(dataArgs[key], rootValue)) delete dataArgs[key];
155
149
  }
156
150
  }
157
151
  function normalizeContext(node, data) {
158
- const dataArgs = chunkLRM6JXJA_cjs.isRecord(data["args"]) ? data["args"] : void 0;
159
- const args = chunkLRM6JXJA_cjs.isRecord(node["args"]) ? node["args"] : void 0;
152
+ const dataArgs = chunkE3APHA6O_cjs.isRecord(data["args"]) ? data["args"] : void 0;
153
+ const args = chunkE3APHA6O_cjs.isRecord(node["args"]) ? node["args"] : void 0;
160
154
  if (!dataArgs || dataArgs["context"] === void 0) return;
161
- if (args && chunkLRM6JXJA_cjs.deepEqual(dataArgs["context"], args["context"])) delete dataArgs["context"];
155
+ if (args && chunkE3APHA6O_cjs.deepEqual(dataArgs["context"], args["context"])) delete dataArgs["context"];
162
156
  }
163
157
  function normalizeErrorConfig(node, data) {
164
- const dataArgs = chunkLRM6JXJA_cjs.isRecord(data["args"]) ? data["args"] : void 0;
165
- const dataState = chunkLRM6JXJA_cjs.isRecord(dataArgs?.["state"]) ? dataArgs["state"] : void 0;
158
+ const dataArgs = chunkE3APHA6O_cjs.isRecord(data["args"]) ? data["args"] : void 0;
159
+ const dataState = chunkE3APHA6O_cjs.isRecord(dataArgs?.["state"]) ? dataArgs["state"] : void 0;
166
160
  const effective = node["errorConfig"] ?? data["errorConfig"] ?? dataState?.["errorConfig"];
167
161
  if (effective !== void 0 && effective !== null) node["errorConfig"] = effective;
168
- if (data["errorConfig"] !== void 0 && chunkLRM6JXJA_cjs.deepEqual(data["errorConfig"], node["errorConfig"])) {
162
+ else if (node["errorConfig"] === null) delete node["errorConfig"];
163
+ if (data["errorConfig"] !== void 0 && chunkE3APHA6O_cjs.deepEqual(data["errorConfig"], node["errorConfig"])) {
169
164
  delete data["errorConfig"];
170
165
  }
171
166
  }
172
167
  function normalizeExecutionSettings(node, data) {
173
- const root = chunkLRM6JXJA_cjs.isRecord(node["executionSettings"]) ? node["executionSettings"] : void 0;
174
- const mirror = chunkLRM6JXJA_cjs.isRecord(data["executionSettings"]) ? data["executionSettings"] : void 0;
168
+ const root = chunkE3APHA6O_cjs.isRecord(node["executionSettings"]) ? node["executionSettings"] : void 0;
169
+ const mirror = chunkE3APHA6O_cjs.isRecord(data["executionSettings"]) ? data["executionSettings"] : void 0;
175
170
  if (!root && !mirror) return;
176
171
  const merged = { ...root };
177
172
  for (const [key, value] of Object.entries(mirror ?? {}))
178
- if (!Object.hasOwn(merged, key)) merged[key] = value;
173
+ if (!Object.hasOwn(merged, key)) chunkE3APHA6O_cjs.setOwn(merged, key, value);
179
174
  if (root?.["executeOnce"] === true || mirror?.["executeOnce"] === true)
180
175
  merged["executeOnce"] = true;
181
176
  if (mirror && Object.hasOwn(mirror, "runOn")) {
@@ -191,11 +186,11 @@ function normalizeDisabled(node, data) {
191
186
  delete data["disabled"];
192
187
  }
193
188
  function normalizeNode(raw) {
194
- if (!chunkLRM6JXJA_cjs.isRecord(raw)) return raw;
195
- const node = chunkLRM6JXJA_cjs.cloneJson(raw);
189
+ if (!chunkE3APHA6O_cjs.isRecord(raw)) return raw;
190
+ const node = chunkE3APHA6O_cjs.cloneJson(raw);
196
191
  const type = typeof node["type"] === "string" ? node["type"] : "";
197
192
  const merged = usesMergedParameters(type);
198
- const data = chunkLRM6JXJA_cjs.isRecord(node["data"]) ? node["data"] : {};
193
+ const data = chunkE3APHA6O_cjs.isRecord(node["data"]) ? node["data"] : {};
199
194
  normalizeLabel(node, data);
200
195
  normalizeOperation(node, data);
201
196
  normalizeVersion(node, data, merged);
@@ -206,28 +201,28 @@ function normalizeNode(raw) {
206
201
  normalizeContext(node, data);
207
202
  normalizeExecutionSettings(node, data);
208
203
  normalizeDisabled(node, data);
209
- if (chunkLRM6JXJA_cjs.isRecord(data["args"])) removeIfEmpty(data, "args");
204
+ if (chunkE3APHA6O_cjs.isRecord(data["args"])) removeIfEmpty(data, "args");
210
205
  if (Object.keys(data).length === 0) delete node["data"];
211
206
  else node["data"] = data;
212
207
  return node;
213
208
  }
214
209
  function normalizeDefinition(definition) {
215
- if (!chunkLRM6JXJA_cjs.isRecord(definition) || !chunkLRM6JXJA_cjs.isRecord(definition["data"])) return definition;
216
- const doc = chunkLRM6JXJA_cjs.cloneJson(definition);
210
+ if (!chunkE3APHA6O_cjs.isRecord(definition) || !chunkE3APHA6O_cjs.isRecord(definition["data"])) return definition;
211
+ const doc = chunkE3APHA6O_cjs.cloneJson(definition);
217
212
  const data = doc["data"];
218
213
  const rawNodes = Array.isArray(data["nodes"]) ? data["nodes"] : [];
219
214
  const nodes = rawNodes.map(normalizeNode);
220
215
  data["nodes"] = nodes;
221
- const edges = Array.isArray(data["edges"]) ? data["edges"].filter(chunkLRM6JXJA_cjs.isRecord) : [];
216
+ const edges = Array.isArray(data["edges"]) ? data["edges"].filter(chunkE3APHA6O_cjs.isRecord) : [];
222
217
  const ids = nodes.flatMap(
223
- (node) => chunkLRM6JXJA_cjs.isRecord(node) && typeof node["id"] === "string" ? [node["id"]] : []
218
+ (node) => chunkE3APHA6O_cjs.isRecord(node) && typeof node["id"] === "string" ? [node["id"]] : []
224
219
  );
225
220
  const missing = nodes.some(
226
- (node) => chunkLRM6JXJA_cjs.isRecord(node) && readPosition(node["position"]) === void 0
221
+ (node) => chunkE3APHA6O_cjs.isRecord(node) && readPosition(node["position"]) === void 0
227
222
  );
228
223
  if (missing) {
229
- const meta = chunkLRM6JXJA_cjs.isRecord(doc["meta"]) ? doc["meta"] : void 0;
230
- const metaLayout = chunkLRM6JXJA_cjs.isRecord(meta?.["layout"]) ? meta["layout"] : void 0;
224
+ const meta = chunkE3APHA6O_cjs.isRecord(doc["meta"]) ? doc["meta"] : void 0;
225
+ const metaLayout = chunkE3APHA6O_cjs.isRecord(meta?.["layout"]) ? meta["layout"] : void 0;
231
226
  const computed = chunkG4UEPUGO_cjs.autoLayout(
232
227
  ids,
233
228
  edges.flatMap(
@@ -235,7 +230,7 @@ function normalizeDefinition(definition) {
235
230
  )
236
231
  );
237
232
  for (const node of nodes) {
238
- if (!chunkLRM6JXJA_cjs.isRecord(node) || typeof node["id"] !== "string") continue;
233
+ if (!chunkE3APHA6O_cjs.isRecord(node) || typeof node["id"] !== "string") continue;
239
234
  if (readPosition(node["position"]) !== void 0) continue;
240
235
  const fromMeta = readPosition(metaLayout?.[node["id"]]);
241
236
  const position = fromMeta ?? computed.get(node["id"]);
@@ -249,22 +244,22 @@ function normalizeDefinition(definition) {
249
244
  // src/ir/hash.ts
250
245
  function hashedProjection(definition) {
251
246
  const normalized = normalizeDefinition(definition);
252
- if (!chunkLRM6JXJA_cjs.isRecord(normalized)) return normalized;
247
+ if (!chunkE3APHA6O_cjs.isRecord(normalized)) return normalized;
253
248
  const copy = { ...normalized };
254
249
  delete copy["authoring"];
255
250
  return copy;
256
251
  }
257
252
  function irHash(definition) {
258
- return chunk27HASETB_cjs.sha256Tagged(chunk27HASETB_cjs.canonicalJson(hashedProjection(definition)));
253
+ return chunkCSYBNN3V_cjs.sha256Tagged(chunkCSYBNN3V_cjs.canonicalJson(hashedProjection(definition)));
259
254
  }
260
255
  function sourceHash(files) {
261
256
  const entries = [...files].sort(
262
257
  (a, b) => a.path === b.path ? a.content < b.content ? -1 : a.content > b.content ? 1 : 0 : a.path < b.path ? -1 : 1
263
258
  ).map((file) => [file.path, file.content]);
264
- return chunk27HASETB_cjs.sha256Tagged(chunk27HASETB_cjs.canonicalJson(entries));
259
+ return chunkCSYBNN3V_cjs.sha256Tagged(chunkCSYBNN3V_cjs.canonicalJson(entries));
265
260
  }
266
261
  function buildIdOf(bundle) {
267
- return chunk27HASETB_cjs.sha256Tagged(bundle);
262
+ return chunkCSYBNN3V_cjs.sha256Tagged(bundle);
268
263
  }
269
264
 
270
265
  exports.CODE_WORKFLOW_NODE_TYPE = CODE_WORKFLOW_NODE_TYPE;
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var chunkE3APHA6O_cjs = require('./chunk-E3APHA6O.cjs');
4
+
3
5
  // src/ir/canonical-json.ts
4
6
  var CanonicalJsonError = class extends Error {
5
7
  constructor(message) {
@@ -70,7 +72,7 @@ function sortKeysDeep(value) {
70
72
  const record = value;
71
73
  const sorted = {};
72
74
  for (const key of Object.keys(record).sort()) {
73
- if (record[key] !== void 0) sorted[key] = sortKeysDeep(record[key]);
75
+ if (record[key] !== void 0) chunkE3APHA6O_cjs.setOwn(sorted, key, sortKeysDeep(record[key]));
74
76
  }
75
77
  return sorted;
76
78
  }