@bian-womp/spark-graph 0.3.58 → 0.3.60

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 CHANGED
@@ -919,14 +919,6 @@ class Graph {
919
919
  setResolvedHandles(nodeId, handles) {
920
920
  this.resolvedByNode.set(nodeId, handles);
921
921
  }
922
- /**
923
- * Iterate over resolved handles safely
924
- */
925
- forEachResolvedHandles(callback) {
926
- for (const [nodeId, handles] of this.resolvedByNode.entries()) {
927
- callback(handles, nodeId);
928
- }
929
- }
930
922
  // ==================== Utility Methods ====================
931
923
  /**
932
924
  * Check if all inbound edges for a node have values
@@ -2128,11 +2120,11 @@ function tryHandleResolving(def, registry, environment) {
2128
2120
  }
2129
2121
  return { resolved: out, pending };
2130
2122
  }
2131
- function buildEdges(def, registry, resolvedByNode) {
2123
+ function buildEdges(def, registry, graph) {
2132
2124
  return def.edges.map((e) => {
2133
2125
  const srcNode = def.nodes.find((n) => n.nodeId === e.source.nodeId);
2134
2126
  const dstNode = def.nodes.find((n) => n.nodeId === e.target.nodeId);
2135
- const { srcDeclared, dstDeclared } = extractEdgeTypes(e.source.nodeId, e.source.handle, e.target.nodeId, e.target.handle, resolvedByNode);
2127
+ const { srcDeclared, dstDeclared } = extractEdgeTypes(e.source.nodeId, e.source.handle, e.target.nodeId, e.target.handle, registry, graph);
2136
2128
  const { convert, convertAsync } = buildEdgeConverters(srcDeclared, dstDeclared, registry, `buildEdges: ${srcNode?.typeId || ""}.${e.source.nodeId}.${e.source.handle} -> ${dstNode?.typeId || ""}.${e.target.nodeId}.${e.target.handle}`);
2137
2129
  return {
2138
2130
  id: e.id,
@@ -2152,15 +2144,13 @@ function buildEdges(def, registry, resolvedByNode) {
2152
2144
  * Used by both buildEdges and updateNodeHandles to avoid duplication
2153
2145
  * Now supports union types on both source (output) and destination (input) handles
2154
2146
  */
2155
- function extractEdgeTypes(sourceNodeId, sourceHandle, targetNodeId, targetHandle, resolvedByNode) {
2156
- const srcResolved = resolvedByNode.get(sourceNodeId);
2157
- const dstResolved = resolvedByNode.get(targetNodeId);
2147
+ function extractEdgeTypes(sourceNodeId, sourceHandle, targetNodeId, targetHandle, registry, graph) {
2148
+ const srcResolved = graph.getResolvedHandles(sourceNodeId);
2149
+ const dstResolved = graph.getResolvedHandles(targetNodeId);
2158
2150
  const srcDeclared = srcResolved
2159
2151
  ? srcResolved.outputs[sourceHandle]
2160
- : undefined;
2161
- const dstDeclared = dstResolved
2162
- ? getInputDeclaredTypes(dstResolved.inputs, targetHandle)
2163
- : undefined;
2152
+ : registry.nodes.get(sourceNodeId)?.outputs[sourceHandle];
2153
+ const dstDeclared = getInputDeclaredTypes(dstResolved ? dstResolved.inputs : registry.nodes.get(targetNodeId)?.inputs, targetHandle);
2164
2154
  return {
2165
2155
  srcDeclared,
2166
2156
  dstDeclared,
@@ -2426,10 +2416,6 @@ class HandleResolver {
2426
2416
  if (!node)
2427
2417
  return;
2428
2418
  this.graph.setResolvedHandles(nodeId, handles);
2429
- const resolvedByNode = new Map();
2430
- this.graph.forEachResolvedHandles((handles, nodeId) => {
2431
- resolvedByNode.set(nodeId, handles);
2432
- });
2433
2419
  const registry = this.registry; // Store for use in callback
2434
2420
  this.graph.forEachEdge((e, _index) => {
2435
2421
  // Only update edges that touch the changed node
@@ -2440,7 +2426,7 @@ class HandleResolver {
2440
2426
  const dstNode = this.graph.getNode(e.target.nodeId);
2441
2427
  const oldDstDeclared = e.dstDeclared;
2442
2428
  // Extract edge types using shared helper (handles both source and target updates)
2443
- const { srcDeclared, dstDeclared } = extractEdgeTypes(e.source.nodeId, e.source.handle, e.target.nodeId, e.target.handle, resolvedByNode);
2429
+ const { srcDeclared, dstDeclared } = extractEdgeTypes(e.source.nodeId, e.source.handle, e.target.nodeId, e.target.handle, registry, this.graph);
2444
2430
  // Update converters
2445
2431
  const conv = buildEdgeConverters(srcDeclared, dstDeclared, registry, `updateNodeHandles: ${srcNode?.typeId || ""}.${e.source.nodeId}.${e.source.handle} -> ${dstNode?.typeId || ""}.${e.target.nodeId}.${e.target.handle}`);
2446
2432
  // Update edge properties via Graph
@@ -2573,31 +2559,15 @@ class HandleResolver {
2573
2559
  * EdgePropagator component - handles value propagation through edges
2574
2560
  */
2575
2561
  class EdgePropagator {
2576
- constructor(graph, eventEmitter, runContextManager, handleResolver, nodeExecutor) {
2562
+ constructor(graph, eventEmitter, runContextManager, handleResolver, nodeExecutor, runtime) {
2577
2563
  this.graph = graph;
2578
2564
  this.eventEmitter = eventEmitter;
2579
2565
  this.runContextManager = runContextManager;
2580
2566
  this.handleResolver = handleResolver;
2581
2567
  this.nodeExecutor = nodeExecutor;
2568
+ this.runtime = runtime;
2582
2569
  this.arrayInputBuckets = new Map();
2583
2570
  }
2584
- /**
2585
- * Propagate value through edges
2586
- * @param runContextIds - Optional set of run-context IDs. If provided, propagation is run-context aware.
2587
- * If undefined or empty, behaves like auto mode (always propagates values and execution).
2588
- */
2589
- propagate(srcNodeId, srcHandle, value, runContextIds) {
2590
- // Set source output
2591
- if (!this.setSourceOutput(srcNodeId, srcHandle, value)) {
2592
- return; // Node was removed
2593
- }
2594
- // Find outgoing edges
2595
- const outEdges = this.findOutgoingEdges(srcNodeId, srcHandle);
2596
- // Process each edge
2597
- for (const edge of outEdges) {
2598
- this.propagateToEdge(edge, value, srcNodeId, runContextIds);
2599
- }
2600
- }
2601
2571
  /**
2602
2572
  * Set source output value and emit event
2603
2573
  */
@@ -2686,6 +2656,9 @@ class EdgePropagator {
2686
2656
  if (edge.convert) {
2687
2657
  convertedValue = edge.convert(value);
2688
2658
  }
2659
+ else {
2660
+ console.warn(`No convert function for edge ${edge.id} of type ${edge.source.nodeId}.${edge.source.handle} -> ${edge.target.nodeId}.${edge.target.handle}`);
2661
+ }
2689
2662
  this.applyToTarget(edge, convertedValue, effectiveRunContexts);
2690
2663
  }
2691
2664
  /**
@@ -2906,11 +2879,32 @@ class EdgePropagator {
2906
2879
  this.runContextManager.finishEdgeConversion(id, edgeId);
2907
2880
  }
2908
2881
  }
2882
+ /**
2883
+ * Propagate value through edges
2884
+ * @param runContextIds - Optional set of run-context IDs. If provided, propagation is run-context aware.
2885
+ * If undefined or empty, behaves like auto mode (always propagates values and execution).
2886
+ */
2887
+ propagate(srcNodeId, srcHandle, value, runContextIds) {
2888
+ if (this.runtime.isPaused())
2889
+ return;
2890
+ // Set source output
2891
+ if (!this.setSourceOutput(srcNodeId, srcHandle, value)) {
2892
+ return; // Node was removed
2893
+ }
2894
+ // Find outgoing edges
2895
+ const outEdges = this.findOutgoingEdges(srcNodeId, srcHandle);
2896
+ // Process each edge
2897
+ for (const edge of outEdges) {
2898
+ this.propagateToEdge(edge, value, srcNodeId, runContextIds);
2899
+ }
2900
+ }
2909
2901
  /**
2910
2902
  * Re-emit all outputs from a node (used when graph updates)
2911
2903
  * Only re-emits outputs that are valid according to resolved handles
2912
2904
  */
2913
2905
  invalidateDownstream(nodeId) {
2906
+ if (this.runtime.isPaused())
2907
+ return;
2914
2908
  const node = this.graph.getNode(nodeId);
2915
2909
  if (!node)
2916
2910
  return;
@@ -3653,7 +3647,7 @@ class GraphRuntime {
3653
3647
  this.graph = new Graph(this.eventEmitter);
3654
3648
  this.runContextManager = new RunContextManager(this.graph, "warn");
3655
3649
  this.handleResolver = new HandleResolver(this.graph, this.eventEmitter, this.runContextManager, this);
3656
- this.edgePropagator = new EdgePropagator(this.graph, this.eventEmitter, this.runContextManager, this.handleResolver, this);
3650
+ this.edgePropagator = new EdgePropagator(this.graph, this.eventEmitter, this.runContextManager, this.handleResolver, this, this);
3657
3651
  // Create NodeExecutor with EdgePropagator and HandleResolver
3658
3652
  this.nodeExecutor = new NodeExecutor(this.graph, this.eventEmitter, this.runContextManager, this.handleResolver, this, this);
3659
3653
  // Create RuntimeValidatorManager
@@ -3729,11 +3723,7 @@ class GraphRuntime {
3729
3723
  gr.graph.setNode(n.nodeId, rn);
3730
3724
  }
3731
3725
  // Instantiate edges
3732
- const resolvedByNode = new Map();
3733
- gr.graph.forEachResolvedHandles((handles, nodeId) => {
3734
- resolvedByNode.set(nodeId, handles);
3735
- });
3736
- const edges = buildEdges(def, registry, resolvedByNode);
3726
+ const edges = buildEdges(def, registry, gr.graph);
3737
3727
  gr.graph.setEdges(edges);
3738
3728
  // Schedule async recompute only for nodes that indicated Promise-based resolveHandles
3739
3729
  for (const nodeId of initial.pending) {
@@ -4241,11 +4231,7 @@ class GraphRuntime {
4241
4231
  for (const [nodeId, handles] of result.resolved) {
4242
4232
  this.graph.setResolvedHandles(nodeId, handles);
4243
4233
  }
4244
- const resolvedByNode = new Map();
4245
- this.graph.forEachResolvedHandles((handles, nodeId) => {
4246
- resolvedByNode.set(nodeId, handles);
4247
- });
4248
- const afterEdges = buildEdges(def, registry, resolvedByNode);
4234
+ const afterEdges = buildEdges(def, registry, this.graph);
4249
4235
  this.graph.setEdges(afterEdges);
4250
4236
  for (const nodeId of result.pending) {
4251
4237
  this.handleResolver.scheduleRecomputeHandles(nodeId);