@timeax/digital-service-engine 0.0.8 → 0.1.0

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.
@@ -651,6 +651,7 @@ type EditorEvents = {
651
651
  "catalog:change": {
652
652
  catalog?: ServiceCatalogState;
653
653
  reason: string;
654
+ snapshot: EditorSnapshot;
654
655
  };
655
656
  "catalog:active-change": {
656
657
  activeNodeId?: string;
@@ -651,6 +651,7 @@ type EditorEvents = {
651
651
  "catalog:change": {
652
652
  catalog?: ServiceCatalogState;
653
653
  reason: string;
654
+ snapshot: EditorSnapshot;
654
655
  };
655
656
  "catalog:active-change": {
656
657
  activeNodeId?: string;
@@ -1316,7 +1316,6 @@ function useLivePolling(params) {
1316
1316
  live,
1317
1317
  workspaceId,
1318
1318
  actor,
1319
- hasAnyData,
1320
1319
  getCurrentBranchId,
1321
1320
  refreshAll,
1322
1321
  refreshBranchContext,
@@ -1423,11 +1422,6 @@ function useLivePolling(params) {
1423
1422
  disconnect2();
1424
1423
  if (live.mode === "off") {
1425
1424
  setStatus({ connected: false });
1426
- if (!hasAnyData) {
1427
- void (async () => {
1428
- await refreshAll({ strict: false });
1429
- })();
1430
- }
1431
1425
  return;
1432
1426
  }
1433
1427
  const adapter = resolveAdapter();
@@ -1463,7 +1457,6 @@ function useLivePolling(params) {
1463
1457
  }, [
1464
1458
  disconnect2,
1465
1459
  live.mode,
1466
- hasAnyData,
1467
1460
  refreshAll,
1468
1461
  resolveAdapter,
1469
1462
  ctx,
@@ -2817,8 +2810,10 @@ import {
2817
2810
  createContext as createContext2,
2818
2811
  useContext as useContext2,
2819
2812
  useEffect as useEffect7,
2813
+ useLayoutEffect,
2820
2814
  useMemo as useMemo13,
2821
- useRef as useRef6
2815
+ useRef as useRef6,
2816
+ useState as useState11
2822
2817
  } from "react";
2823
2818
 
2824
2819
  // src/react/canvas/events.ts
@@ -9075,6 +9070,7 @@ var Editor = class {
9075
9070
  "catalog:change",
9076
9071
  {
9077
9072
  catalog: cloneDeep4(this.catalog),
9073
+ snapshot: this.makeSnapshot(reason),
9078
9074
  reason
9079
9075
  }
9080
9076
  );
@@ -9866,8 +9862,8 @@ function CanvasProviderOwned({
9866
9862
  canvasOpts,
9867
9863
  builderOpts
9868
9864
  );
9869
- useHydrateEditorSnapshot(api, initialSnapshot);
9870
- return /* @__PURE__ */ jsx2(Ctx.Provider, { value: api, children });
9865
+ const hydrationReady = useHydrateEditorSnapshot(api, initialSnapshot);
9866
+ return /* @__PURE__ */ jsx2(Ctx.Provider, { value: api, children: hydrationReady ? children : null });
9871
9867
  }
9872
9868
  function useCanvasAPI() {
9873
9869
  const api = useContext2(Ctx);
@@ -9895,42 +9891,71 @@ function useCanvasFromBuilder(builder, opts) {
9895
9891
  function useCanvasFromExisting(api) {
9896
9892
  return api;
9897
9893
  }
9894
+ var NO_SNAPSHOT_HYDRATION_KEY = "__no_snapshot__";
9898
9895
  function useHydrateEditorSnapshot(api, snapshot) {
9899
- const hydratedRef = useRef6(null);
9900
- useEffect7(() => {
9901
- if (!(snapshot == null ? void 0 : snapshot.props)) return;
9902
- const hydrationKey = getSnapshotHydrationKey(snapshot);
9903
- if (hydratedRef.current === hydrationKey) return;
9904
- hydratedRef.current = hydrationKey;
9905
- hydrateEditorFromSnapshot(api, snapshot);
9906
- }, [api, snapshot]);
9896
+ const targetHydrationKey = useMemo13(() => {
9897
+ if (!(snapshot == null ? void 0 : snapshot.props)) return NO_SNAPSHOT_HYDRATION_KEY;
9898
+ return getSnapshotHydrationKey(snapshot);
9899
+ }, [snapshot]);
9900
+ const [hydratedKey, setHydratedKey] = useState11(
9901
+ NO_SNAPSHOT_HYDRATION_KEY
9902
+ );
9903
+ useLayoutEffect(() => {
9904
+ if (hydratedKey === targetHydrationKey) return;
9905
+ if (snapshot == null ? void 0 : snapshot.props) {
9906
+ hydrateEditorFromSnapshot(api, snapshot);
9907
+ }
9908
+ setHydratedKey(targetHydrationKey);
9909
+ }, [api, hydratedKey, snapshot, targetHydrationKey]);
9910
+ return hydratedKey === targetHydrationKey;
9907
9911
  }
9908
9912
  function getSnapshotHydrationKey(snapshot) {
9909
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
9913
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
9910
9914
  const meta = snapshot.meta;
9911
- const preferred = (_e = (_d = (_c = (_b = (_a = meta == null ? void 0 : meta.snapshot_id) != null ? _a : meta == null ? void 0 : meta.snapshotId) != null ? _b : meta == null ? void 0 : meta.version_id) != null ? _c : meta == null ? void 0 : meta.versionId) != null ? _d : meta == null ? void 0 : meta.branch_id) != null ? _e : meta == null ? void 0 : meta.branchId;
9912
- if (preferred != null) {
9913
- return String(preferred);
9914
- }
9915
- const layout = (_f = snapshot.layout) == null ? void 0 : _f.canvas;
9915
+ const metaKey = [
9916
+ (_b = (_a = meta == null ? void 0 : meta.snapshot_id) != null ? _a : meta == null ? void 0 : meta.snapshotId) != null ? _b : "",
9917
+ (_d = (_c = meta == null ? void 0 : meta.version_id) != null ? _c : meta == null ? void 0 : meta.versionId) != null ? _d : "",
9918
+ (_f = (_e = meta == null ? void 0 : meta.branch_id) != null ? _e : meta == null ? void 0 : meta.branchId) != null ? _f : ""
9919
+ ].join("|");
9920
+ const layout = (_g = snapshot.layout) == null ? void 0 : _g.canvas;
9916
9921
  const positionKeys = (layout == null ? void 0 : layout.positions) ? Object.keys(layout.positions).sort().join("|") : "";
9917
9922
  const viewport = (layout == null ? void 0 : layout.viewport) ? `${layout.viewport.x}:${layout.viewport.y}:${layout.viewport.zoom}` : "";
9918
9923
  const selection = (layout == null ? void 0 : layout.selection) ? Array.from(layout.selection).sort().join("|") : "";
9919
- const catalogKey = snapshot.catalog ? JSON.stringify({
9920
- opened: (_g = snapshot.catalog.opened) != null ? _g : null,
9921
- mode: (_h = snapshot.catalog.mode) != null ? _h : null,
9922
- tab: (_i = snapshot.catalog.tab) != null ? _i : null,
9923
- query: (_j = snapshot.catalog.query) != null ? _j : null
9924
- }) : "";
9924
+ const catalogKey = serializeForHydration(snapshot.catalog);
9925
9925
  return [
9926
- String(((_l = (_k = snapshot.props) == null ? void 0 : _k.fields) != null ? _l : []).length),
9927
- String(((_n = (_m = snapshot.props) == null ? void 0 : _m.filters) != null ? _n : []).length),
9926
+ metaKey,
9927
+ String(((_i = (_h = snapshot.props) == null ? void 0 : _h.fields) != null ? _i : []).length),
9928
+ String(((_k = (_j = snapshot.props) == null ? void 0 : _j.filters) != null ? _k : []).length),
9928
9929
  positionKeys,
9929
9930
  viewport,
9930
9931
  selection,
9931
9932
  catalogKey
9932
9933
  ].join("::");
9933
9934
  }
9935
+ function serializeForHydration(value) {
9936
+ if (value == null) return "";
9937
+ try {
9938
+ return JSON.stringify(sortForHydration(value));
9939
+ } catch {
9940
+ return "__unserializable__";
9941
+ }
9942
+ }
9943
+ function sortForHydration(value) {
9944
+ if (Array.isArray(value)) {
9945
+ return value.map((entry) => sortForHydration(entry));
9946
+ }
9947
+ if (value && typeof value === "object") {
9948
+ const entries = Object.entries(value).sort(
9949
+ ([a], [b]) => a.localeCompare(b)
9950
+ );
9951
+ const next = {};
9952
+ for (const [key, entry] of entries) {
9953
+ next[key] = sortForHydration(entry);
9954
+ }
9955
+ return next;
9956
+ }
9957
+ return value;
9958
+ }
9934
9959
  function hydrateEditorFromSnapshot(api, snapshot) {
9935
9960
  var _a;
9936
9961
  api.refreshGraph();
@@ -9945,30 +9970,66 @@ function hydrateCatalog(api, snapshot) {
9945
9970
  api.editor.clearCatalog();
9946
9971
  }
9947
9972
  function hydrateCanvasLayout(api, canvas) {
9973
+ var _a;
9948
9974
  if (!canvas) return;
9949
- if (canvas.positions) {
9975
+ const current = api.snapshot();
9976
+ if (canvas.positions && hasPositionDelta(canvas.positions, current.positions)) {
9950
9977
  api.setPositions(canvas.positions);
9951
9978
  }
9952
- if (canvas.viewport) {
9979
+ if (canvas.viewport && !sameViewport(canvas.viewport, current.viewport)) {
9953
9980
  api.setViewport(canvas.viewport);
9954
9981
  }
9982
+ const currentSelection = api.getSelection().map(String);
9955
9983
  if (canvas.selection) {
9956
9984
  const ids = Array.isArray(canvas.selection) ? canvas.selection : Array.from(canvas.selection);
9957
9985
  if (ids.length > 0) {
9958
- api.select(ids);
9959
- } else {
9986
+ if (!sameIdSet(ids.map(String), currentSelection)) {
9987
+ api.select(ids.map(String));
9988
+ }
9989
+ } else if (currentSelection.length > 0) {
9960
9990
  api.clearSelection();
9961
9991
  }
9962
- } else {
9992
+ } else if (currentSelection.length > 0) {
9963
9993
  api.clearSelection();
9964
9994
  }
9965
- if (canvas.highlighted) {
9966
- const ids = Array.isArray(canvas.highlighted) ? canvas.highlighted : Array.from(canvas.highlighted);
9967
- api.setHighlighted(ids);
9995
+ if ("highlighted" in canvas) {
9996
+ const highlighted = canvas.highlighted;
9997
+ const ids = highlighted ? Array.isArray(highlighted) ? highlighted : Array.from(highlighted) : [];
9998
+ const currentIds = Array.from((_a = current.highlighted) != null ? _a : []).map(String);
9999
+ const nextIds = ids.map(String);
10000
+ if (!sameIdSet(nextIds, currentIds)) {
10001
+ api.setHighlighted(nextIds);
10002
+ }
9968
10003
  }
9969
10004
  if ("hoverId" in canvas) {
9970
- api.setHover(canvas.hoverId);
10005
+ const nextHoverId = canvas.hoverId;
10006
+ if (current.hoverId !== nextHoverId) {
10007
+ api.setHover(nextHoverId);
10008
+ }
10009
+ }
10010
+ }
10011
+ function hasPositionDelta(next, current) {
10012
+ for (const id of Object.keys(next)) {
10013
+ const nextPos = next[id];
10014
+ const currentPos = current[id];
10015
+ if (!currentPos || currentPos.x !== nextPos.x || currentPos.y !== nextPos.y) {
10016
+ return true;
10017
+ }
10018
+ }
10019
+ return false;
10020
+ }
10021
+ function sameViewport(a, b) {
10022
+ if (!a && !b) return true;
10023
+ if (!a || !b) return false;
10024
+ return a.x === b.x && a.y === b.y && a.zoom === b.zoom;
10025
+ }
10026
+ function sameIdSet(a, b) {
10027
+ if (a.length !== b.length) return false;
10028
+ const set = new Set(a);
10029
+ for (const id of b) {
10030
+ if (!set.has(id)) return false;
9971
10031
  }
10032
+ return true;
9972
10033
  }
9973
10034
  function WorkspaceBootScreen({
9974
10035
  boot
@@ -11952,12 +12013,12 @@ function Workspace(props) {
11952
12013
  }
11953
12014
 
11954
12015
  // src/react/workspace/components/canvas.tsx
11955
- import { useMemo as useMemo19, useState as useState15 } from "react";
12016
+ import { useMemo as useMemo19, useState as useState16 } from "react";
11956
12017
  import { Background, ConnectionMode, MiniMap, ReactFlow } from "@xyflow/react";
11957
12018
  import "@xyflow/react/dist/style.css";
11958
12019
 
11959
12020
  // src/react/workspace/adapters/reactflow/adapter.ts
11960
- import { useCallback as useCallback16, useEffect as useEffect10, useMemo as useMemo17, useRef as useRef9, useState as useState13 } from "react";
12021
+ import { useCallback as useCallback16, useEffect as useEffect10, useMemo as useMemo17, useRef as useRef9, useState as useState14 } from "react";
11961
12022
  import { applyNodeChanges, applyEdgeChanges } from "@xyflow/react";
11962
12023
  function rafThrottle(fn, minMs = 80) {
11963
12024
  let frame = 0;
@@ -11983,7 +12044,7 @@ function rafThrottle(fn, minMs = 80) {
11983
12044
  });
11984
12045
  }
11985
12046
  var isCommentId = (id) => id.startsWith("c::");
11986
- function sameIdSet(a, b) {
12047
+ function sameIdSet2(a, b) {
11987
12048
  if (a.length !== b.length) return false;
11988
12049
  const s = new Set(a);
11989
12050
  for (const id of b) if (!s.has(id)) return false;
@@ -12061,7 +12122,7 @@ function useReactFlowAdapter(api, options = {}) {
12061
12122
  useEffect10(() => {
12062
12123
  afterConnectRef.current = options.afterConnect;
12063
12124
  }, [options.afterConnect]);
12064
- const [rf, setRF] = useState13(
12125
+ const [rf, setRF] = useState14(
12065
12126
  () => toRF(api.snapshot(), api, { nodeDecorators, edgeDecorators })
12066
12127
  );
12067
12128
  const relRef = useRef9(api.getEdgeRel());
@@ -12172,7 +12233,7 @@ function useReactFlowAdapter(api, options = {}) {
12172
12233
  const next = Array.from(keep);
12173
12234
  const currRaw = api.getSelection();
12174
12235
  const curr = Array.isArray(currRaw) ? currRaw : Array.from(currRaw);
12175
- if (!sameIdSet(next, curr)) {
12236
+ if (!sameIdSet2(next, curr)) {
12176
12237
  api.select(keep);
12177
12238
  }
12178
12239
  }
@@ -12290,7 +12351,7 @@ function useReactFlowAdapter(api, options = {}) {
12290
12351
  const next = nodes.map((n) => n.id);
12291
12352
  const currRaw = api.getSelection();
12292
12353
  const curr = Array.isArray(currRaw) ? currRaw : Array.from(currRaw);
12293
- if (sameIdSet(next, curr)) return;
12354
+ if (sameIdSet2(next, curr)) return;
12294
12355
  api.select(next);
12295
12356
  },
12296
12357
  [api]
@@ -12311,7 +12372,7 @@ function useReactFlowAdapter(api, options = {}) {
12311
12372
  }
12312
12373
 
12313
12374
  // src/react/workspace/adapters/reactflow/toolbar.tsx
12314
- import { useMemo as useMemo18, useState as useState14, useCallback as useCallback17 } from "react";
12375
+ import { useMemo as useMemo18, useState as useState15, useCallback as useCallback17 } from "react";
12315
12376
  import { useReactFlow } from "@xyflow/react";
12316
12377
 
12317
12378
  // src/react/workspace/adapters/reactflow/toolbar/merge.ts
@@ -12416,7 +12477,7 @@ function Toolbar({
12416
12477
  renderButton
12417
12478
  }) {
12418
12479
  const rf = useReactFlow();
12419
- const [openMenuId, setOpenMenuId] = useState14(null);
12480
+ const [openMenuId, setOpenMenuId] = useState15(null);
12420
12481
  const selectionCount = api.getSelection().length;
12421
12482
  const relation = api.getEdgeRel();
12422
12483
  const canUndo = true;
@@ -12947,8 +13008,8 @@ function Canvas({
12947
13008
  toolbarPositionClassName = "left-2 top-2",
12948
13009
  children
12949
13010
  }) {
12950
- const [showGrid, setShowGrid] = useState15(initialShowGrid);
12951
- const [showMiniMap, setShowMiniMap] = useState15(initialShowMiniMap);
13011
+ const [showGrid, setShowGrid] = useState16(initialShowGrid);
13012
+ const [showMiniMap, setShowMiniMap] = useState16(initialShowMiniMap);
12952
13013
  const {
12953
13014
  nodes,
12954
13015
  edges,