@bian-womp/spark-workbench 0.2.23 → 0.2.25

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 (55) hide show
  1. package/lib/cjs/index.cjs +63 -18
  2. package/lib/cjs/index.cjs.map +1 -1
  3. package/lib/cjs/src/adapters/cli/index.d.ts +1 -1
  4. package/lib/cjs/src/adapters/cli/index.d.ts.map +1 -1
  5. package/lib/cjs/src/core/AbstractWorkbench.d.ts +3 -3
  6. package/lib/cjs/src/core/AbstractWorkbench.d.ts.map +1 -1
  7. package/lib/cjs/src/core/InMemoryWorkbench.d.ts +4 -3
  8. package/lib/cjs/src/core/InMemoryWorkbench.d.ts.map +1 -1
  9. package/lib/cjs/src/core/contracts.d.ts +4 -3
  10. package/lib/cjs/src/core/contracts.d.ts.map +1 -1
  11. package/lib/cjs/src/misc/WorkbenchStudio.d.ts +12 -2
  12. package/lib/cjs/src/misc/WorkbenchStudio.d.ts.map +1 -1
  13. package/lib/cjs/src/misc/context/WorkbenchContext.d.ts +2 -1
  14. package/lib/cjs/src/misc/context/WorkbenchContext.d.ts.map +1 -1
  15. package/lib/cjs/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
  16. package/lib/cjs/src/misc/layout.d.ts +5 -5
  17. package/lib/cjs/src/misc/layout.d.ts.map +1 -1
  18. package/lib/cjs/src/misc/mapping.d.ts +2 -1
  19. package/lib/cjs/src/misc/mapping.d.ts.map +1 -1
  20. package/lib/cjs/src/runtime/AbstractGraphRunner.d.ts +2 -2
  21. package/lib/cjs/src/runtime/AbstractGraphRunner.d.ts.map +1 -1
  22. package/lib/cjs/src/runtime/IGraphRunner.d.ts +7 -3
  23. package/lib/cjs/src/runtime/IGraphRunner.d.ts.map +1 -1
  24. package/lib/cjs/src/runtime/LocalGraphRunner.d.ts +2 -2
  25. package/lib/cjs/src/runtime/LocalGraphRunner.d.ts.map +1 -1
  26. package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts +2 -2
  27. package/lib/cjs/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
  28. package/lib/esm/index.js +63 -18
  29. package/lib/esm/index.js.map +1 -1
  30. package/lib/esm/src/adapters/cli/index.d.ts +1 -1
  31. package/lib/esm/src/adapters/cli/index.d.ts.map +1 -1
  32. package/lib/esm/src/core/AbstractWorkbench.d.ts +3 -3
  33. package/lib/esm/src/core/AbstractWorkbench.d.ts.map +1 -1
  34. package/lib/esm/src/core/InMemoryWorkbench.d.ts +4 -3
  35. package/lib/esm/src/core/InMemoryWorkbench.d.ts.map +1 -1
  36. package/lib/esm/src/core/contracts.d.ts +4 -3
  37. package/lib/esm/src/core/contracts.d.ts.map +1 -1
  38. package/lib/esm/src/misc/WorkbenchStudio.d.ts +12 -2
  39. package/lib/esm/src/misc/WorkbenchStudio.d.ts.map +1 -1
  40. package/lib/esm/src/misc/context/WorkbenchContext.d.ts +2 -1
  41. package/lib/esm/src/misc/context/WorkbenchContext.d.ts.map +1 -1
  42. package/lib/esm/src/misc/context/WorkbenchContext.provider.d.ts.map +1 -1
  43. package/lib/esm/src/misc/layout.d.ts +5 -5
  44. package/lib/esm/src/misc/layout.d.ts.map +1 -1
  45. package/lib/esm/src/misc/mapping.d.ts +2 -1
  46. package/lib/esm/src/misc/mapping.d.ts.map +1 -1
  47. package/lib/esm/src/runtime/AbstractGraphRunner.d.ts +2 -2
  48. package/lib/esm/src/runtime/AbstractGraphRunner.d.ts.map +1 -1
  49. package/lib/esm/src/runtime/IGraphRunner.d.ts +7 -3
  50. package/lib/esm/src/runtime/IGraphRunner.d.ts.map +1 -1
  51. package/lib/esm/src/runtime/LocalGraphRunner.d.ts +2 -2
  52. package/lib/esm/src/runtime/LocalGraphRunner.d.ts.map +1 -1
  53. package/lib/esm/src/runtime/RemoteGraphRunner.d.ts +2 -2
  54. package/lib/esm/src/runtime/RemoteGraphRunner.d.ts.map +1 -1
  55. package/package.json +4 -4
package/lib/cjs/index.cjs CHANGED
@@ -817,22 +817,39 @@ class RemoteGraphRunner extends AbstractGraphRunner {
817
817
  return this.runner;
818
818
  let transport;
819
819
  const kind = this.backend.kind;
820
+ const backend = this.backend;
821
+ const connectOptions = backend.connectOptions;
820
822
  this.emit("transport", { state: "connecting", kind });
821
- if (this.backend.kind === "remote-http") {
823
+ if (backend.kind === "remote-http") {
822
824
  if (!sparkRemote.HttpPollingTransport)
823
825
  throw new Error("HttpPollingTransport not available");
824
- transport = new sparkRemote.HttpPollingTransport(this.backend.baseUrl);
825
- await transport.connect();
826
+ transport = new sparkRemote.HttpPollingTransport(backend.baseUrl);
827
+ await transport.connect(connectOptions);
826
828
  }
827
- else if (this.backend.kind === "remote-ws") {
829
+ else if (backend.kind === "remote-ws") {
828
830
  if (!sparkRemote.WebSocketTransport)
829
831
  throw new Error("WebSocketTransport not available");
830
- transport = new sparkRemote.WebSocketTransport(this.backend.url);
831
- await transport.connect();
832
+ transport = new sparkRemote.WebSocketTransport(backend.url);
833
+ await transport.connect(connectOptions);
832
834
  }
833
835
  else {
834
836
  throw new Error("Remote backend not configured");
835
837
  }
838
+ // Subscribe to custom events if handler provided
839
+ if (backend.onCustomEvent) {
840
+ transport.subscribe((event) => {
841
+ // Filter out standard runtime events, pass others to custom handler
842
+ const msg = event.message;
843
+ if (msg && typeof msg === "object" && "type" in msg) {
844
+ const type = msg.type;
845
+ // Standard runtime events: stats, value, error, invalidate
846
+ // Custom events are anything else (e.g., flow-opened, flow-latest)
847
+ if (!["stats", "value", "error", "invalidate"].includes(type)) {
848
+ backend.onCustomEvent?.(event);
849
+ }
850
+ }
851
+ });
852
+ }
836
853
  const runner = new sparkRemote.RemoteRunner(transport);
837
854
  this.runner = runner;
838
855
  this.transport = transport;
@@ -2837,7 +2854,7 @@ const WorkbenchCanvas = React.forwardRef(({ showValues, toString, toElement, get
2837
2854
  })
2838
2855
  .map((n) => n.id);
2839
2856
  // Detect handle updates (ids/length changes) for targeted debug
2840
- const toIds = (arr) => Array.isArray(arr) ? arr.map((h) => h?.id) : [];
2857
+ const toIds = (arr) => Array.isArray(arr) ? arr.map((h) => (h && typeof h === "object" && "id" in h ? String(h.id) : "")).filter(Boolean) : [];
2841
2858
  const handlesEqual = (a, b) => {
2842
2859
  const aIds = toIds(a);
2843
2860
  const bIds = toIds(b);
@@ -3109,7 +3126,8 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3109
3126
  URL.revokeObjectURL(url);
3110
3127
  }
3111
3128
  catch (err) {
3112
- alert(String(err?.message ?? err));
3129
+ const message = err instanceof Error ? err.message : String(err);
3130
+ alert(message);
3113
3131
  }
3114
3132
  }, [wb, runner]);
3115
3133
  const onUploadPicked = React.useCallback(async (e) => {
@@ -3167,7 +3185,8 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3167
3185
  runAutoLayout();
3168
3186
  }
3169
3187
  catch (err) {
3170
- alert(String(err?.message ?? err));
3188
+ const message = err instanceof Error ? err.message : String(err);
3189
+ alert(message);
3171
3190
  }
3172
3191
  finally {
3173
3192
  // reset input so same file can be picked again
@@ -3417,8 +3436,11 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3417
3436
  return pre;
3418
3437
  if (typeof value === "object" &&
3419
3438
  value !== null &&
3439
+ "url" in value &&
3420
3440
  typeof value.url === "string") {
3421
- const title = value.title || "";
3441
+ const title = "title" in value && typeof value.title === "string"
3442
+ ? value.title
3443
+ : "";
3422
3444
  const url = String(value.url || "");
3423
3445
  // value.ts handles data URL formatting
3424
3446
  return title || url.slice(0, 32) + (url.length > 32 ? "…" : "");
@@ -3431,7 +3453,11 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3431
3453
  const round4 = (n) => Math.round(Number(n) * 10000) / 10000;
3432
3454
  if (typeId === "base.vec3" && Array.isArray(value)) {
3433
3455
  const a = value;
3434
- return [round4(a[0] ?? 0), round4(a[1] ?? 0), round4(a[2] ?? 0)].join(",");
3456
+ return [
3457
+ round4(Number(a[0] ?? 0)),
3458
+ round4(Number(a[1] ?? 0)),
3459
+ round4(Number(a[2] ?? 0)),
3460
+ ].join(",");
3435
3461
  }
3436
3462
  const stringifyRounded = (v) => {
3437
3463
  try {
@@ -3482,7 +3508,8 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3482
3508
  runner.launch(wb.export(), { engine: kind });
3483
3509
  }
3484
3510
  catch (err) {
3485
- alert(String(err?.message ?? err));
3511
+ const message = err instanceof Error ? err.message : String(err);
3512
+ alert(message);
3486
3513
  }
3487
3514
  }, disabled: !engine, title: engine ? "Start engine" : "Select an engine first", children: [jsxRuntime.jsx(react$1.PlayIcon, { size: 14, weight: "fill" }), jsxRuntime.jsx("span", { className: "font-medium ml-1", children: "Start" })] })), jsxRuntime.jsx("button", { className: "border border-gray-300 rounded px-2 py-1.5", onClick: runAutoLayout, children: "Auto Layout" }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: () => canvasRef.current?.fitView?.(), title: "Fit View", children: "Fit View" }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: downloadGraph, children: "Download Graph" }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: async () => {
3488
3515
  try {
@@ -3510,25 +3537,43 @@ function WorkbenchStudioCanvas({ setRegistry, autoScroll, onAutoScrollChange, ex
3510
3537
  URL.revokeObjectURL(url);
3511
3538
  }
3512
3539
  catch (err) {
3513
- alert(String(err?.message ?? err));
3540
+ const message = err instanceof Error ? err.message : String(err);
3541
+ alert(message);
3514
3542
  }
3515
3543
  }, children: "Download Snapshot" }), jsxRuntime.jsx("input", { ref: uploadInputRef, type: "file", accept: "application/json,.json", className: "hidden", onChange: onUploadPicked }), jsxRuntime.jsx("button", { className: "ml-2 border border-gray-300 rounded px-2 py-1.5", onClick: triggerUpload, children: "Upload Graph/Snapshot" }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: debug, onChange: (e) => onDebugChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Debug events" })] }), jsxRuntime.jsxs("label", { className: "ml-2 flex items-center gap-1", children: [jsxRuntime.jsx("input", { type: "checkbox", checked: showValues, onChange: (e) => onShowValuesChange(e.target.checked) }), jsxRuntime.jsx("span", { children: "Show values in nodes" })] })] }), jsxRuntime.jsxs("div", { className: "flex flex-1 min-h-0", children: [jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: jsxRuntime.jsx(WorkbenchCanvas, { ref: canvasRef, showValues: showValues, toString: toString, toElement: toElement, getDefaultNodeSize: overrides?.getDefaultNodeSize }) }), jsxRuntime.jsx(Inspector, { setInput: setInput, debug: debug, autoScroll: autoScroll, hideWorkbench: hideWorkbench, onAutoScrollChange: onAutoScrollChange, onHideWorkbenchChange: onHideWorkbenchChange, toString: toString, toElement: toElement, contextPanel: overrides?.contextPanel })] })] }));
3516
3544
  }
3517
- function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, overrides, onInit, onChange, }) {
3545
+ function WorkbenchStudio({ engine, onEngineChange, example, onExampleChange, backendKind, onBackendKindChange, httpBaseUrl, onHttpBaseUrlChange, wsUrl, onWsUrlChange, debug, onDebugChange, showValues, onShowValuesChange, hideWorkbench, onHideWorkbenchChange, autoScroll, onAutoScrollChange, backendOptions, overrides, onInit, onChange, }) {
3518
3546
  const [registry, setRegistry] = React.useState(sparkGraph.createSimpleGraphRegistry());
3519
3547
  const [wb] = React.useState(() => new InMemoryWorkbench({ ui: new DefaultUIExtensionRegistry() }));
3520
3548
  const runner = React.useMemo(() => {
3521
3549
  if (backendKind === "remote-http") {
3522
- return new RemoteGraphRunner(registry, {
3550
+ const backend = {
3523
3551
  kind: "remote-http",
3524
3552
  baseUrl: httpBaseUrl,
3525
- });
3553
+ ...(backendOptions?.connectOptions && {
3554
+ connectOptions: backendOptions.connectOptions,
3555
+ }),
3556
+ ...(backendOptions?.onCustomEvent && {
3557
+ onCustomEvent: backendOptions.onCustomEvent,
3558
+ }),
3559
+ };
3560
+ return new RemoteGraphRunner(registry, backend);
3526
3561
  }
3527
3562
  if (backendKind === "remote-ws") {
3528
- return new RemoteGraphRunner(registry, { kind: "remote-ws", url: wsUrl });
3563
+ const backend = {
3564
+ kind: "remote-ws",
3565
+ url: wsUrl,
3566
+ ...(backendOptions?.connectOptions && {
3567
+ connectOptions: backendOptions.connectOptions,
3568
+ }),
3569
+ ...(backendOptions?.onCustomEvent && {
3570
+ onCustomEvent: backendOptions.onCustomEvent,
3571
+ }),
3572
+ };
3573
+ return new RemoteGraphRunner(registry, backend);
3529
3574
  }
3530
3575
  return new LocalGraphRunner(registry);
3531
- }, [registry, backendKind, httpBaseUrl, wsUrl]);
3576
+ }, [registry, backendKind, httpBaseUrl, wsUrl, backendOptions]);
3532
3577
  // Allow external UI registration (e.g., node renderers) with access to wb
3533
3578
  React.useEffect(() => {
3534
3579
  const baseRegisterUI = (_wb) => { };