@bian-womp/spark-graph 0.1.15 → 0.1.17

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 (41) hide show
  1. package/lib/cjs/index.cjs +264 -72
  2. package/lib/cjs/index.cjs.map +1 -1
  3. package/lib/cjs/src/builder/GraphBuilder.d.ts.map +1 -1
  4. package/lib/cjs/src/builder/Registry.d.ts +3 -3
  5. package/lib/cjs/src/builder/Registry.d.ts.map +1 -1
  6. package/lib/cjs/src/core/types.d.ts +7 -1
  7. package/lib/cjs/src/core/types.d.ts.map +1 -1
  8. package/lib/cjs/src/examples/async.d.ts.map +1 -1
  9. package/lib/cjs/src/examples/engine.d.ts.map +1 -1
  10. package/lib/cjs/src/examples/progress.d.ts.map +1 -1
  11. package/lib/cjs/src/examples/shared.d.ts +2 -6
  12. package/lib/cjs/src/examples/shared.d.ts.map +1 -1
  13. package/lib/cjs/src/examples/simple.d.ts.map +1 -1
  14. package/lib/cjs/src/index.d.ts +3 -1
  15. package/lib/cjs/src/index.d.ts.map +1 -1
  16. package/lib/cjs/src/misc/base.d.ts +7 -0
  17. package/lib/cjs/src/misc/base.d.ts.map +1 -0
  18. package/lib/cjs/src/plugins/composite.d.ts.map +1 -1
  19. package/lib/cjs/src/runtime/GraphRuntime.d.ts +1 -0
  20. package/lib/cjs/src/runtime/GraphRuntime.d.ts.map +1 -1
  21. package/lib/esm/index.js +263 -73
  22. package/lib/esm/index.js.map +1 -1
  23. package/lib/esm/src/builder/GraphBuilder.d.ts.map +1 -1
  24. package/lib/esm/src/builder/Registry.d.ts +3 -3
  25. package/lib/esm/src/builder/Registry.d.ts.map +1 -1
  26. package/lib/esm/src/core/types.d.ts +7 -1
  27. package/lib/esm/src/core/types.d.ts.map +1 -1
  28. package/lib/esm/src/examples/async.d.ts.map +1 -1
  29. package/lib/esm/src/examples/engine.d.ts.map +1 -1
  30. package/lib/esm/src/examples/progress.d.ts.map +1 -1
  31. package/lib/esm/src/examples/shared.d.ts +2 -6
  32. package/lib/esm/src/examples/shared.d.ts.map +1 -1
  33. package/lib/esm/src/examples/simple.d.ts.map +1 -1
  34. package/lib/esm/src/index.d.ts +3 -1
  35. package/lib/esm/src/index.d.ts.map +1 -1
  36. package/lib/esm/src/misc/base.d.ts +7 -0
  37. package/lib/esm/src/misc/base.d.ts.map +1 -0
  38. package/lib/esm/src/plugins/composite.d.ts.map +1 -1
  39. package/lib/esm/src/runtime/GraphRuntime.d.ts +1 -0
  40. package/lib/esm/src/runtime/GraphRuntime.d.ts.map +1 -1
  41. package/package.json +1 -1
package/lib/cjs/index.cjs CHANGED
@@ -372,6 +372,15 @@ class Registry {
372
372
  }
373
373
  }
374
374
 
375
+ function typed(typeId, value) {
376
+ return { __spark_type: typeId, __spark_value: value };
377
+ }
378
+ function isTypedOutput(v) {
379
+ return (!!v &&
380
+ typeof v === "object" &&
381
+ Object.prototype.hasOwnProperty.call(v, "__spark_type"));
382
+ }
383
+
375
384
  class GraphRuntime {
376
385
  constructor() {
377
386
  this.nodes = new Map();
@@ -435,25 +444,19 @@ class GraphRuntime {
435
444
  srcDeclared = srcDesc.outputs[e.source.handle];
436
445
  }
437
446
  }
438
- if (!effectiveTypeId)
439
- effectiveTypeId = srcDeclared;
447
+ if (!effectiveTypeId) {
448
+ effectiveTypeId = Array.isArray(srcDeclared)
449
+ ? srcDeclared[0]
450
+ : srcDeclared;
451
+ }
440
452
  if (dstNode) {
441
453
  const dstDesc = registry.nodes.get(dstNode.typeId);
442
454
  if (dstDesc) {
443
455
  dstDeclared = dstDesc.inputs[e.target.handle];
444
456
  }
445
457
  }
446
- // Attach convert if source/target differ but coercible
447
- let convert = undefined;
448
- let convertAsync = undefined;
449
- if (srcDeclared && dstDeclared && srcDeclared !== dstDeclared) {
450
- const fn = registry.getCoercion(srcDeclared, dstDeclared);
451
- if (fn)
452
- convert = convert ?? fn;
453
- const afn = registry.getAsyncCoercion(srcDeclared, dstDeclared);
454
- if (afn)
455
- convertAsync = convertAsync ?? afn;
456
- }
458
+ // Attach dynamic convert/convertAsync aware of union sources and typed outputs
459
+ const { convert, convertAsync } = GraphRuntime.buildEdgeConverters(srcDeclared, dstDeclared, registry);
457
460
  return {
458
461
  id: e.id,
459
462
  source: { ...e.source },
@@ -461,6 +464,9 @@ class GraphRuntime {
461
464
  typeId: effectiveTypeId ?? "untyped",
462
465
  convert,
463
466
  convertAsync,
467
+ srcUnionTypes: Array.isArray(srcDeclared)
468
+ ? [...srcDeclared]
469
+ : undefined,
464
470
  stats: { runs: 0, inFlight: false, progress: 0 },
465
471
  };
466
472
  });
@@ -537,6 +543,59 @@ class GraphRuntime {
537
543
  const node = this.nodes.get(nodeId);
538
544
  return node?.outputs[output];
539
545
  }
546
+ static buildEdgeConverters(srcDeclared, dstDeclared, registry) {
547
+ let convert;
548
+ let convertAsync;
549
+ if (dstDeclared && srcDeclared) {
550
+ if (Array.isArray(srcDeclared)) {
551
+ const srcTypes = srcDeclared;
552
+ const anyAsync = srcTypes.some((s) => {
553
+ const res = registry.resolveCoercion(s, dstDeclared);
554
+ return res?.kind === "async";
555
+ });
556
+ if (anyAsync) {
557
+ convertAsync = async (v, signal) => {
558
+ if (!isTypedOutput(v))
559
+ throw new Error(`Typed output required for union source; allowed: ${srcTypes.join("|")}`);
560
+ const typeId = String(v.__spark_type);
561
+ if (!srcTypes.includes(typeId))
562
+ throw new Error(`Invalid typed output ${typeId}; allowed: ${srcTypes.join("|")}`);
563
+ const payload = v.__spark_value;
564
+ const res = registry.resolveCoercion(typeId, dstDeclared);
565
+ if (!res)
566
+ return payload;
567
+ if (res.kind === "async")
568
+ return await res.convertAsync(payload, signal);
569
+ return res.convert(payload);
570
+ };
571
+ }
572
+ else {
573
+ convert = (v) => {
574
+ if (!isTypedOutput(v))
575
+ throw new Error(`Typed output required for union source; allowed: ${srcTypes.join("|")}`);
576
+ const typeId = String(v.__spark_type);
577
+ if (!srcTypes.includes(typeId))
578
+ throw new Error(`Invalid typed output ${typeId}; allowed: ${srcTypes.join("|")}`);
579
+ const payload = v.__spark_value;
580
+ const res = registry.resolveCoercion(typeId, dstDeclared);
581
+ if (!res)
582
+ return payload;
583
+ if (res.kind === "async")
584
+ throw new Error("Async coercion required but convert used");
585
+ return res.convert(payload);
586
+ };
587
+ }
588
+ }
589
+ else {
590
+ const res = registry.resolveCoercion(srcDeclared, dstDeclared);
591
+ if (res?.kind === "async")
592
+ convertAsync = res.convertAsync;
593
+ else if (res?.kind === "sync")
594
+ convert = res.convert;
595
+ }
596
+ }
597
+ return { convert, convertAsync };
598
+ }
540
599
  scheduleInputsChanged(nodeId) {
541
600
  const node = this.nodes.get(nodeId);
542
601
  if (!node)
@@ -708,10 +767,27 @@ class GraphRuntime {
708
767
  handle: srcHandle,
709
768
  value,
710
769
  io: "output",
770
+ runtimeTypeId: isTypedOutput(value)
771
+ ? String(value.__spark_type)
772
+ : undefined,
711
773
  });
712
774
  // fan-out along all edges from this output
713
775
  const outEdges = this.edges.filter((e) => e.source.nodeId === srcNodeId && e.source.handle === srcHandle);
714
776
  for (const e of outEdges) {
777
+ // If source declares a union for this handle, require typed output
778
+ const isUnion = Array.isArray(e.srcUnionTypes);
779
+ const isTyped = isTypedOutput(value);
780
+ if (isUnion && !isTyped) {
781
+ const err = new Error(`Output ${srcNodeId}.${srcHandle} requires typed value for union output (allowed: ${e.srcUnionTypes.join("|")})`);
782
+ this.emit("error", {
783
+ kind: "edge-convert",
784
+ edgeId: e.id,
785
+ source: { nodeId: e.source.nodeId, handle: e.source.handle },
786
+ target: { nodeId: e.target.nodeId, handle: e.target.handle },
787
+ err,
788
+ });
789
+ continue;
790
+ }
715
791
  // Clone per edge to isolate conversions from mutating the shared source value
716
792
  let nextVal = structuredClone(value);
717
793
  const applyToTarget = (v) => {
@@ -725,6 +801,7 @@ class GraphRuntime {
725
801
  handle: e.target.handle,
726
802
  value: v,
727
803
  io: "input",
804
+ runtimeTypeId: isTypedOutput(v) ? String(v.__spark_type) : undefined,
728
805
  });
729
806
  if (!this.paused && this.allInboundHaveValue(e.target.nodeId))
730
807
  this.scheduleInputsChanged(e.target.nodeId);
@@ -743,7 +820,7 @@ class GraphRuntime {
743
820
  e.stats.inFlight = true;
744
821
  e.stats.progress = 0;
745
822
  const sig = controller.signal;
746
- // Fire async conversion
823
+ // Fire async conversion using edge's convertAsync (dynamic union aware)
747
824
  void e
748
825
  .convertAsync(nextVal, sig)
749
826
  .then((v) => {
@@ -1020,24 +1097,18 @@ class GraphRuntime {
1020
1097
  srcDeclared = srcDesc.outputs[e.source.handle];
1021
1098
  }
1022
1099
  }
1023
- if (!effectiveTypeId)
1024
- effectiveTypeId = srcDeclared;
1100
+ if (!effectiveTypeId) {
1101
+ effectiveTypeId = Array.isArray(srcDeclared)
1102
+ ? srcDeclared[0]
1103
+ : srcDeclared;
1104
+ }
1025
1105
  if (dstNode) {
1026
1106
  const dstDesc = registry.nodes.get(dstNode.typeId);
1027
1107
  if (dstDesc) {
1028
1108
  dstDeclared = dstDesc.inputs[e.target.handle];
1029
1109
  }
1030
1110
  }
1031
- let convert = undefined;
1032
- let convertAsync = undefined;
1033
- if (srcDeclared && dstDeclared && srcDeclared !== dstDeclared) {
1034
- const fn = registry.getCoercion(srcDeclared, dstDeclared);
1035
- if (fn)
1036
- convert = convert ?? fn;
1037
- const afn = registry.getAsyncCoercion(srcDeclared, dstDeclared);
1038
- if (afn)
1039
- convertAsync = convertAsync ?? afn;
1040
- }
1111
+ const { convert, convertAsync } = GraphRuntime.buildEdgeConverters(srcDeclared, dstDeclared, registry);
1041
1112
  return {
1042
1113
  id: e.id,
1043
1114
  source: { ...e.source },
@@ -1178,12 +1249,30 @@ class GraphBuilder {
1178
1249
  message: `Edge ${e.id} target node missing`,
1179
1250
  data: { edgeId: e.id },
1180
1251
  });
1181
- // infer edge type from source output if missing
1252
+ // Infer edge type when missing. For union sources, prefer target input type if available.
1182
1253
  let effectiveTypeId = e.typeId;
1183
- if (!effectiveTypeId && srcNode) {
1254
+ let _srcDeclared;
1255
+ let _dstDeclared;
1256
+ if (srcNode) {
1184
1257
  const srcType = this.registry.nodes.get(srcNode.typeId);
1185
- if (srcType) {
1186
- effectiveTypeId = srcType.outputs[e.source.handle];
1258
+ if (srcType)
1259
+ _srcDeclared = srcType.outputs[e.source.handle];
1260
+ }
1261
+ if (dstNode) {
1262
+ const dstType = this.registry.nodes.get(dstNode.typeId);
1263
+ if (dstType)
1264
+ _dstDeclared = dstType.inputs[e.target.handle];
1265
+ }
1266
+ if (!effectiveTypeId) {
1267
+ if (Array.isArray(_srcDeclared) && _dstDeclared) {
1268
+ // When source is a union and target input type is known, adopt the input type
1269
+ // so validation checks are performed against the target, not an arbitrary variant.
1270
+ effectiveTypeId = _dstDeclared;
1271
+ }
1272
+ else if (_srcDeclared) {
1273
+ effectiveTypeId = Array.isArray(_srcDeclared)
1274
+ ? _srcDeclared[0]
1275
+ : _srcDeclared;
1187
1276
  }
1188
1277
  }
1189
1278
  const type = effectiveTypeId
@@ -1213,22 +1302,29 @@ class GraphBuilder {
1213
1302
  }
1214
1303
  if (srcType) {
1215
1304
  const declared = srcType.outputs[e.source.handle];
1216
- if (declared &&
1217
- effectiveTypeId &&
1218
- declared !== effectiveTypeId &&
1219
- !this.registry.canCoerce(declared, effectiveTypeId)) {
1220
- issues.push({
1221
- level: "error",
1222
- code: "TYPE_MISMATCH_OUTPUT",
1223
- message: `Edge ${e.id} type ${effectiveTypeId} mismatches source output ${srcNode.typeId}.${e.source.handle} (${declared}) and no coercion exists`,
1224
- data: {
1225
- edgeId: e.id,
1226
- nodeId: srcNode.nodeId,
1227
- output: e.source.handle,
1228
- declared,
1229
- effectiveTypeId,
1230
- },
1231
- });
1305
+ const declaredArr = Array.isArray(declared)
1306
+ ? declared
1307
+ : declared
1308
+ ? [declared]
1309
+ : [];
1310
+ if (declaredArr.length > 0 && effectiveTypeId) {
1311
+ for (const s of declaredArr) {
1312
+ if (s !== effectiveTypeId &&
1313
+ !this.registry.canCoerce(s, effectiveTypeId)) {
1314
+ issues.push({
1315
+ level: "error",
1316
+ code: "TYPE_MISMATCH_OUTPUT",
1317
+ message: `Edge ${e.id} type ${effectiveTypeId} mismatches source output ${srcNode.typeId}.${e.source.handle} (${s}) and no coercion exists`,
1318
+ data: {
1319
+ edgeId: e.id,
1320
+ nodeId: srcNode.nodeId,
1321
+ output: e.source.handle,
1322
+ declared: s,
1323
+ effectiveTypeId,
1324
+ },
1325
+ });
1326
+ }
1327
+ }
1232
1328
  }
1233
1329
  }
1234
1330
  }
@@ -1247,23 +1343,52 @@ class GraphBuilder {
1247
1343
  });
1248
1344
  }
1249
1345
  if (dstType) {
1250
- const declared = dstType.inputs[e.target.handle];
1251
- if (declared &&
1252
- effectiveTypeId &&
1253
- declared !== effectiveTypeId &&
1254
- !this.registry.canCoerce(effectiveTypeId, declared)) {
1255
- issues.push({
1256
- level: "error",
1257
- code: "TYPE_MISMATCH_INPUT",
1258
- message: `Edge ${e.id} type ${effectiveTypeId} mismatches target input ${dstNode.typeId}.${e.target.handle} (${declared}) and no coercion exists`,
1259
- data: {
1260
- edgeId: e.id,
1261
- nodeId: dstNode.nodeId,
1262
- input: e.target.handle,
1263
- declared,
1264
- effectiveTypeId,
1265
- },
1266
- });
1346
+ const declaredIn = dstType.inputs[e.target.handle];
1347
+ if (declaredIn && effectiveTypeId) {
1348
+ // If source is a union, ensure each variant can reach declaredIn
1349
+ if (srcNode) {
1350
+ const srcType = this.registry.nodes.get(srcNode.typeId);
1351
+ const srcDeclared = srcType?.outputs[e.source.handle];
1352
+ const srcArr = Array.isArray(srcDeclared)
1353
+ ? srcDeclared
1354
+ : srcDeclared
1355
+ ? [srcDeclared]
1356
+ : effectiveTypeId
1357
+ ? [effectiveTypeId]
1358
+ : [];
1359
+ for (const s of srcArr) {
1360
+ if (s !== declaredIn &&
1361
+ !this.registry.canCoerce(s, declaredIn)) {
1362
+ issues.push({
1363
+ level: "error",
1364
+ code: "TYPE_MISMATCH_INPUT",
1365
+ message: `Edge ${e.id} output type ${s} not convertible to target input ${dstNode.typeId}.${e.target.handle} (${declaredIn})`,
1366
+ data: {
1367
+ edgeId: e.id,
1368
+ nodeId: dstNode.nodeId,
1369
+ input: e.target.handle,
1370
+ declared: declaredIn,
1371
+ effectiveTypeId: s,
1372
+ },
1373
+ });
1374
+ }
1375
+ }
1376
+ }
1377
+ else if (declaredIn !== effectiveTypeId &&
1378
+ !this.registry.canCoerce(effectiveTypeId, declaredIn)) {
1379
+ issues.push({
1380
+ level: "error",
1381
+ code: "TYPE_MISMATCH_INPUT",
1382
+ message: `Edge ${e.id} type ${effectiveTypeId} mismatches target input ${dstNode.typeId}.${e.target.handle} (${declaredIn}) and no coercion exists`,
1383
+ data: {
1384
+ edgeId: e.id,
1385
+ nodeId: dstNode.nodeId,
1386
+ input: e.target.handle,
1387
+ declared: declaredIn,
1388
+ effectiveTypeId,
1389
+ },
1390
+ });
1391
+ }
1267
1392
  }
1268
1393
  }
1269
1394
  }
@@ -1304,7 +1429,8 @@ class GraphBuilder {
1304
1429
  ? this.registry.nodes.get(innerNode.typeId)
1305
1430
  : undefined;
1306
1431
  const typeId = innerDesc ? innerDesc.outputs[map.handle] : undefined;
1307
- outputTypes[outerOut] = typeId ?? "untyped";
1432
+ const single = Array.isArray(typeId) ? typeId[0] : typeId;
1433
+ outputTypes[outerOut] = single ?? "untyped";
1308
1434
  }
1309
1435
  return {
1310
1436
  id: nodeTypeId,
@@ -1576,10 +1702,16 @@ const CompositeCategory = (registry) => ({
1576
1702
  onInputsChanged: (inputs, ctx) => {
1577
1703
  if (!inner)
1578
1704
  return;
1579
- // map outer input => inner node input
1705
+ // map outer inputs => batch per inner node to avoid extra runs
1706
+ const grouped = {};
1580
1707
  for (const [inHandle, map] of Object.entries(impl.exposure.inputs)) {
1581
- if (inHandle in inputs)
1582
- inner.setInput(map.nodeId, map.handle, inputs[inHandle]);
1708
+ if (inHandle in inputs) {
1709
+ const nodeMap = (grouped[map.nodeId] = grouped[map.nodeId] || {});
1710
+ nodeMap[map.handle] = inputs[inHandle];
1711
+ }
1712
+ }
1713
+ for (const [nodeId, map] of Object.entries(grouped)) {
1714
+ inner.setInputs(nodeId, map);
1583
1715
  }
1584
1716
  // pull inner exposed outputs and emit
1585
1717
  for (const [outHandle, map] of Object.entries(impl.exposure.outputs)) {
@@ -1622,6 +1754,25 @@ const lcg = (seed) => {
1622
1754
  let s = seed >>> 0 || 1;
1623
1755
  return () => (s = (s * 1664525 + 1013904223) >>> 0) / 0xffffffff;
1624
1756
  };
1757
+ // JSON helpers
1758
+ const isPlainObject = (v) => {
1759
+ if (v === null || typeof v !== "object")
1760
+ return false;
1761
+ const proto = Object.getPrototypeOf(v);
1762
+ return proto === Object.prototype || proto === null;
1763
+ };
1764
+ const isJson = (v) => {
1765
+ if (v === null)
1766
+ return true;
1767
+ const t = typeof v;
1768
+ if (t === "string" || t === "number" || t === "boolean")
1769
+ return true;
1770
+ if (Array.isArray(v))
1771
+ return v.every(isJson);
1772
+ if (isPlainObject(v))
1773
+ return Object.values(v).every(isJson);
1774
+ return false;
1775
+ };
1625
1776
  function setupBasicGraphRegistry() {
1626
1777
  const registry = new Registry();
1627
1778
  registry.categories.register(ComputeCategory);
@@ -1637,6 +1788,11 @@ function setupBasicGraphRegistry() {
1637
1788
  id: "base.string",
1638
1789
  validate: (v) => typeof v === "string",
1639
1790
  }, { withArray: true, arrayPickFirstDefined: true });
1791
+ // Generic object value (JSON-compatible; object/array/primitive/null)
1792
+ registry.registerType({
1793
+ id: "base.object",
1794
+ validate: (v) => isJson(v),
1795
+ }, { withArray: true, arrayPickFirstDefined: true });
1640
1796
  registry.registerType({
1641
1797
  id: "base.vec3",
1642
1798
  validate: (v) => Array.isArray(v) &&
@@ -1647,18 +1803,52 @@ function setupBasicGraphRegistry() {
1647
1803
  registry.registerCoercion("base.float", "base.vec3", (v) => {
1648
1804
  return [Number(v) || 0, 0, 0];
1649
1805
  });
1650
- // Async coercion variant for vec3 -> float (chunked + abortable)
1651
- registry.registerAsyncCoercion("base.vec3", "base.float", async (value, signal) => {
1652
- if (signal.aborted)
1653
- throw new DOMException("Aborted", "AbortError");
1806
+ registry.registerCoercion("base.vec3", "base.float", (value) => {
1654
1807
  const v = value;
1655
- await new Promise((r) => setTimeout(r, 1000));
1656
1808
  return Math.hypot(Number(v[0] ?? 0), Number(v[1] ?? 0), Number(v[2] ?? 0));
1657
1809
  });
1658
1810
  registry.registerCoercion("base.bool", "base.float", (v) => (v ? 1 : 0));
1659
1811
  registry.registerCoercion("base.float", "base.bool", (v) => !!v);
1660
1812
  registry.registerCoercion("base.float", "base.string", (v) => String(v));
1661
1813
  registry.registerCoercion("base.string", "base.float", (v) => Number(v));
1814
+ // Object <-> String
1815
+ registry.registerCoercion("base.string", "base.object", (v) => {
1816
+ try {
1817
+ return JSON.parse(String(v));
1818
+ }
1819
+ catch {
1820
+ return undefined;
1821
+ }
1822
+ });
1823
+ registry.registerCoercion("base.object", "base.string", (v) => {
1824
+ try {
1825
+ return JSON.stringify(v);
1826
+ }
1827
+ catch {
1828
+ return String(v);
1829
+ }
1830
+ });
1831
+ registry.registerCoercion("base.vec3", "base.json", (v) => {
1832
+ try {
1833
+ return v ? JSON.stringify(v) : undefined;
1834
+ }
1835
+ catch {
1836
+ return undefined;
1837
+ }
1838
+ });
1839
+ registry.registerCoercion("base.json", "base.vec3", (v) => {
1840
+ try {
1841
+ const result = JSON.parse(v);
1842
+ if (result.length === 3 &&
1843
+ result.every((x) => typeof x === "number")) {
1844
+ return result;
1845
+ }
1846
+ return undefined;
1847
+ }
1848
+ catch {
1849
+ return undefined;
1850
+ }
1851
+ });
1662
1852
  // Enums: Math Operation
1663
1853
  registry.registerEnum({
1664
1854
  id: "base.enum:math.operation",
@@ -2204,6 +2394,8 @@ exports.createSimpleGraphDef = createSimpleGraphDef;
2204
2394
  exports.createSimpleGraphRegistry = createSimpleGraphRegistry;
2205
2395
  exports.createValidationGraphDef = createValidationGraphDef;
2206
2396
  exports.createValidationGraphRegistry = createValidationGraphRegistry;
2397
+ exports.isTypedOutput = isTypedOutput;
2207
2398
  exports.registerDelayNode = registerDelayNode;
2208
2399
  exports.registerProgressNodes = registerProgressNodes;
2400
+ exports.typed = typed;
2209
2401
  //# sourceMappingURL=index.cjs.map