@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.
@@ -804,6 +804,7 @@ type EditorEvents = {
804
804
  "catalog:change": {
805
805
  catalog?: ServiceCatalogState;
806
806
  reason: string;
807
+ snapshot: EditorSnapshot;
807
808
  };
808
809
  "catalog:active-change": {
809
810
  activeNodeId?: string;
@@ -804,6 +804,7 @@ type EditorEvents = {
804
804
  "catalog:change": {
805
805
  catalog?: ServiceCatalogState;
806
806
  reason: string;
807
+ snapshot: EditorSnapshot;
807
808
  };
808
809
  "catalog:active-change": {
809
810
  activeNodeId?: string;
@@ -1367,7 +1367,6 @@ function useLivePolling(params) {
1367
1367
  live,
1368
1368
  workspaceId,
1369
1369
  actor,
1370
- hasAnyData,
1371
1370
  getCurrentBranchId,
1372
1371
  refreshAll,
1373
1372
  refreshBranchContext,
@@ -1474,11 +1473,6 @@ function useLivePolling(params) {
1474
1473
  disconnect2();
1475
1474
  if (live.mode === "off") {
1476
1475
  setStatus({ connected: false });
1477
- if (!hasAnyData) {
1478
- void (async () => {
1479
- await refreshAll({ strict: false });
1480
- })();
1481
- }
1482
1476
  return;
1483
1477
  }
1484
1478
  const adapter = resolveAdapter();
@@ -1514,7 +1508,6 @@ function useLivePolling(params) {
1514
1508
  }, [
1515
1509
  disconnect2,
1516
1510
  live.mode,
1517
- hasAnyData,
1518
1511
  refreshAll,
1519
1512
  resolveAdapter,
1520
1513
  ctx,
@@ -9120,6 +9113,7 @@ var Editor = class {
9120
9113
  "catalog:change",
9121
9114
  {
9122
9115
  catalog: (0, import_lodash_es4.cloneDeep)(this.catalog),
9116
+ snapshot: this.makeSnapshot(reason),
9123
9117
  reason
9124
9118
  }
9125
9119
  );
@@ -9911,8 +9905,8 @@ function CanvasProviderOwned({
9911
9905
  canvasOpts,
9912
9906
  builderOpts
9913
9907
  );
9914
- useHydrateEditorSnapshot(api, initialSnapshot);
9915
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Ctx.Provider, { value: api, children });
9908
+ const hydrationReady = useHydrateEditorSnapshot(api, initialSnapshot);
9909
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Ctx.Provider, { value: api, children: hydrationReady ? children : null });
9916
9910
  }
9917
9911
  function useCanvasAPI() {
9918
9912
  const api = (0, import_react2.useContext)(Ctx);
@@ -9940,42 +9934,71 @@ function useCanvasFromBuilder(builder, opts) {
9940
9934
  function useCanvasFromExisting(api) {
9941
9935
  return api;
9942
9936
  }
9937
+ var NO_SNAPSHOT_HYDRATION_KEY = "__no_snapshot__";
9943
9938
  function useHydrateEditorSnapshot(api, snapshot) {
9944
- const hydratedRef = (0, import_react2.useRef)(null);
9945
- (0, import_react2.useEffect)(() => {
9946
- if (!(snapshot == null ? void 0 : snapshot.props)) return;
9947
- const hydrationKey = getSnapshotHydrationKey(snapshot);
9948
- if (hydratedRef.current === hydrationKey) return;
9949
- hydratedRef.current = hydrationKey;
9950
- hydrateEditorFromSnapshot(api, snapshot);
9951
- }, [api, snapshot]);
9939
+ const targetHydrationKey = (0, import_react2.useMemo)(() => {
9940
+ if (!(snapshot == null ? void 0 : snapshot.props)) return NO_SNAPSHOT_HYDRATION_KEY;
9941
+ return getSnapshotHydrationKey(snapshot);
9942
+ }, [snapshot]);
9943
+ const [hydratedKey, setHydratedKey] = (0, import_react2.useState)(
9944
+ NO_SNAPSHOT_HYDRATION_KEY
9945
+ );
9946
+ (0, import_react2.useLayoutEffect)(() => {
9947
+ if (hydratedKey === targetHydrationKey) return;
9948
+ if (snapshot == null ? void 0 : snapshot.props) {
9949
+ hydrateEditorFromSnapshot(api, snapshot);
9950
+ }
9951
+ setHydratedKey(targetHydrationKey);
9952
+ }, [api, hydratedKey, snapshot, targetHydrationKey]);
9953
+ return hydratedKey === targetHydrationKey;
9952
9954
  }
9953
9955
  function getSnapshotHydrationKey(snapshot) {
9954
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
9956
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
9955
9957
  const meta = snapshot.meta;
9956
- 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;
9957
- if (preferred != null) {
9958
- return String(preferred);
9959
- }
9960
- const layout = (_f = snapshot.layout) == null ? void 0 : _f.canvas;
9958
+ const metaKey = [
9959
+ (_b = (_a = meta == null ? void 0 : meta.snapshot_id) != null ? _a : meta == null ? void 0 : meta.snapshotId) != null ? _b : "",
9960
+ (_d = (_c = meta == null ? void 0 : meta.version_id) != null ? _c : meta == null ? void 0 : meta.versionId) != null ? _d : "",
9961
+ (_f = (_e = meta == null ? void 0 : meta.branch_id) != null ? _e : meta == null ? void 0 : meta.branchId) != null ? _f : ""
9962
+ ].join("|");
9963
+ const layout = (_g = snapshot.layout) == null ? void 0 : _g.canvas;
9961
9964
  const positionKeys = (layout == null ? void 0 : layout.positions) ? Object.keys(layout.positions).sort().join("|") : "";
9962
9965
  const viewport = (layout == null ? void 0 : layout.viewport) ? `${layout.viewport.x}:${layout.viewport.y}:${layout.viewport.zoom}` : "";
9963
9966
  const selection = (layout == null ? void 0 : layout.selection) ? Array.from(layout.selection).sort().join("|") : "";
9964
- const catalogKey = snapshot.catalog ? JSON.stringify({
9965
- opened: (_g = snapshot.catalog.opened) != null ? _g : null,
9966
- mode: (_h = snapshot.catalog.mode) != null ? _h : null,
9967
- tab: (_i = snapshot.catalog.tab) != null ? _i : null,
9968
- query: (_j = snapshot.catalog.query) != null ? _j : null
9969
- }) : "";
9967
+ const catalogKey = serializeForHydration(snapshot.catalog);
9970
9968
  return [
9971
- String(((_l = (_k = snapshot.props) == null ? void 0 : _k.fields) != null ? _l : []).length),
9972
- String(((_n = (_m = snapshot.props) == null ? void 0 : _m.filters) != null ? _n : []).length),
9969
+ metaKey,
9970
+ String(((_i = (_h = snapshot.props) == null ? void 0 : _h.fields) != null ? _i : []).length),
9971
+ String(((_k = (_j = snapshot.props) == null ? void 0 : _j.filters) != null ? _k : []).length),
9973
9972
  positionKeys,
9974
9973
  viewport,
9975
9974
  selection,
9976
9975
  catalogKey
9977
9976
  ].join("::");
9978
9977
  }
9978
+ function serializeForHydration(value) {
9979
+ if (value == null) return "";
9980
+ try {
9981
+ return JSON.stringify(sortForHydration(value));
9982
+ } catch {
9983
+ return "__unserializable__";
9984
+ }
9985
+ }
9986
+ function sortForHydration(value) {
9987
+ if (Array.isArray(value)) {
9988
+ return value.map((entry) => sortForHydration(entry));
9989
+ }
9990
+ if (value && typeof value === "object") {
9991
+ const entries = Object.entries(value).sort(
9992
+ ([a], [b]) => a.localeCompare(b)
9993
+ );
9994
+ const next = {};
9995
+ for (const [key, entry] of entries) {
9996
+ next[key] = sortForHydration(entry);
9997
+ }
9998
+ return next;
9999
+ }
10000
+ return value;
10001
+ }
9979
10002
  function hydrateEditorFromSnapshot(api, snapshot) {
9980
10003
  var _a;
9981
10004
  api.refreshGraph();
@@ -9990,30 +10013,66 @@ function hydrateCatalog(api, snapshot) {
9990
10013
  api.editor.clearCatalog();
9991
10014
  }
9992
10015
  function hydrateCanvasLayout(api, canvas) {
10016
+ var _a;
9993
10017
  if (!canvas) return;
9994
- if (canvas.positions) {
10018
+ const current = api.snapshot();
10019
+ if (canvas.positions && hasPositionDelta(canvas.positions, current.positions)) {
9995
10020
  api.setPositions(canvas.positions);
9996
10021
  }
9997
- if (canvas.viewport) {
10022
+ if (canvas.viewport && !sameViewport(canvas.viewport, current.viewport)) {
9998
10023
  api.setViewport(canvas.viewport);
9999
10024
  }
10025
+ const currentSelection = api.getSelection().map(String);
10000
10026
  if (canvas.selection) {
10001
10027
  const ids = Array.isArray(canvas.selection) ? canvas.selection : Array.from(canvas.selection);
10002
10028
  if (ids.length > 0) {
10003
- api.select(ids);
10004
- } else {
10029
+ if (!sameIdSet(ids.map(String), currentSelection)) {
10030
+ api.select(ids.map(String));
10031
+ }
10032
+ } else if (currentSelection.length > 0) {
10005
10033
  api.clearSelection();
10006
10034
  }
10007
- } else {
10035
+ } else if (currentSelection.length > 0) {
10008
10036
  api.clearSelection();
10009
10037
  }
10010
- if (canvas.highlighted) {
10011
- const ids = Array.isArray(canvas.highlighted) ? canvas.highlighted : Array.from(canvas.highlighted);
10012
- api.setHighlighted(ids);
10038
+ if ("highlighted" in canvas) {
10039
+ const highlighted = canvas.highlighted;
10040
+ const ids = highlighted ? Array.isArray(highlighted) ? highlighted : Array.from(highlighted) : [];
10041
+ const currentIds = Array.from((_a = current.highlighted) != null ? _a : []).map(String);
10042
+ const nextIds = ids.map(String);
10043
+ if (!sameIdSet(nextIds, currentIds)) {
10044
+ api.setHighlighted(nextIds);
10045
+ }
10013
10046
  }
10014
10047
  if ("hoverId" in canvas) {
10015
- api.setHover(canvas.hoverId);
10048
+ const nextHoverId = canvas.hoverId;
10049
+ if (current.hoverId !== nextHoverId) {
10050
+ api.setHover(nextHoverId);
10051
+ }
10052
+ }
10053
+ }
10054
+ function hasPositionDelta(next, current) {
10055
+ for (const id of Object.keys(next)) {
10056
+ const nextPos = next[id];
10057
+ const currentPos = current[id];
10058
+ if (!currentPos || currentPos.x !== nextPos.x || currentPos.y !== nextPos.y) {
10059
+ return true;
10060
+ }
10061
+ }
10062
+ return false;
10063
+ }
10064
+ function sameViewport(a, b) {
10065
+ if (!a && !b) return true;
10066
+ if (!a || !b) return false;
10067
+ return a.x === b.x && a.y === b.y && a.zoom === b.zoom;
10068
+ }
10069
+ function sameIdSet(a, b) {
10070
+ if (a.length !== b.length) return false;
10071
+ const set = new Set(a);
10072
+ for (const id of b) {
10073
+ if (!set.has(id)) return false;
10016
10074
  }
10075
+ return true;
10017
10076
  }
10018
10077
  function WorkspaceBootScreen({
10019
10078
  boot
@@ -12028,7 +12087,7 @@ function rafThrottle(fn, minMs = 80) {
12028
12087
  });
12029
12088
  }
12030
12089
  var isCommentId = (id) => id.startsWith("c::");
12031
- function sameIdSet(a, b) {
12090
+ function sameIdSet2(a, b) {
12032
12091
  if (a.length !== b.length) return false;
12033
12092
  const s = new Set(a);
12034
12093
  for (const id of b) if (!s.has(id)) return false;
@@ -12217,7 +12276,7 @@ function useReactFlowAdapter(api, options = {}) {
12217
12276
  const next = Array.from(keep);
12218
12277
  const currRaw = api.getSelection();
12219
12278
  const curr = Array.isArray(currRaw) ? currRaw : Array.from(currRaw);
12220
- if (!sameIdSet(next, curr)) {
12279
+ if (!sameIdSet2(next, curr)) {
12221
12280
  api.select(keep);
12222
12281
  }
12223
12282
  }
@@ -12335,7 +12394,7 @@ function useReactFlowAdapter(api, options = {}) {
12335
12394
  const next = nodes.map((n) => n.id);
12336
12395
  const currRaw = api.getSelection();
12337
12396
  const curr = Array.isArray(currRaw) ? currRaw : Array.from(currRaw);
12338
- if (sameIdSet(next, curr)) return;
12397
+ if (sameIdSet2(next, curr)) return;
12339
12398
  api.select(next);
12340
12399
  },
12341
12400
  [api]