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