@eventcatalog/core 5.0.0-beta.10 → 5.0.0-beta.12

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 (61) hide show
  1. package/README.md +5 -5
  2. package/dist/analytics/analytics.cjs +1 -1
  3. package/dist/analytics/analytics.js +2 -2
  4. package/dist/analytics/log-build.cjs +1 -1
  5. package/dist/analytics/log-build.js +3 -3
  6. package/dist/{chunk-CRKJBDN7.js → chunk-BWC4YKW3.js} +1 -1
  7. package/dist/{chunk-LJMXOEEC.js → chunk-CX2VB7AI.js} +1 -1
  8. package/dist/{chunk-IONYKKOY.js → chunk-FY6MSP6J.js} +1 -1
  9. package/dist/{chunk-2LBDRHE4.js → chunk-QB7X34OD.js} +1 -1
  10. package/dist/{chunk-EM36OL6A.js → chunk-TSY5CC27.js} +1 -1
  11. package/dist/constants.cjs +1 -1
  12. package/dist/constants.js +1 -1
  13. package/dist/eventcatalog.cjs +1 -1
  14. package/dist/eventcatalog.js +5 -5
  15. package/dist/generate.cjs +1 -1
  16. package/dist/generate.js +3 -3
  17. package/dist/utils/cli-logger.cjs +1 -1
  18. package/dist/utils/cli-logger.js +2 -2
  19. package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +2 -0
  20. package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +34 -3
  21. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +5 -1
  22. package/eventcatalog/src/components/NavigationProgress.astro +7 -0
  23. package/eventcatalog/src/features/mcp/apps/architecture-diagram/node-chat.tsx +6 -45
  24. package/eventcatalog/src/features/mcp/apps/generated/canvas.html +67 -67
  25. package/eventcatalog/src/features/mcp/apps/generated/viewer.html +69 -69
  26. package/eventcatalog/src/features/studio/agent-choreography.ts +8 -6
  27. package/eventcatalog/src/features/studio/api/canvases-api.ts +64 -15
  28. package/eventcatalog/src/features/studio/api/client.ts +6 -1
  29. package/eventcatalog/src/features/studio/canvas-actions.ts +140 -22
  30. package/eventcatalog/src/features/studio/canvas-doc.ts +165 -10
  31. package/eventcatalog/src/features/studio/catalog.ts +15 -10
  32. package/eventcatalog/src/features/studio/components/CanvasControls.tsx +54 -89
  33. package/eventcatalog/src/features/studio/components/CanvasHeader.tsx +43 -26
  34. package/eventcatalog/src/features/studio/components/CanvasStatusMenu.tsx +8 -11
  35. package/eventcatalog/src/features/studio/components/Comments.tsx +15 -8
  36. package/eventcatalog/src/features/studio/components/DeleteCanvasDialog.tsx +27 -43
  37. package/eventcatalog/src/features/studio/components/Dialog.tsx +60 -0
  38. package/eventcatalog/src/features/studio/components/LeftPanel.tsx +32 -4
  39. package/eventcatalog/src/features/studio/components/OpenInStudioDialog.tsx +79 -0
  40. package/eventcatalog/src/features/studio/components/Presence.tsx +47 -38
  41. package/eventcatalog/src/features/studio/components/StudioDesigner.tsx +323 -99
  42. package/eventcatalog/src/features/studio/components/canvas-nodes.tsx +33 -17
  43. package/eventcatalog/src/features/studio/flow-state.ts +29 -0
  44. package/eventcatalog/src/features/studio/from-visualiser.ts +138 -0
  45. package/eventcatalog/src/features/studio/grouping.ts +4 -0
  46. package/eventcatalog/src/features/studio/hooks/use-canvas-webmcp.ts +1 -1
  47. package/eventcatalog/src/features/studio/hooks/use-counter-scale.ts +20 -0
  48. package/eventcatalog/src/features/studio/hooks/use-follow-camera.ts +8 -3
  49. package/eventcatalog/src/features/studio/hooks/use-studio-flow.ts +67 -13
  50. package/eventcatalog/src/features/studio/layout.ts +29 -15
  51. package/eventcatalog/src/features/studio/level-layout.ts +145 -0
  52. package/eventcatalog/src/features/studio/levels.ts +82 -27
  53. package/eventcatalog/src/features/studio/limits.ts +2 -0
  54. package/eventcatalog/src/features/studio/node-types.ts +44 -4
  55. package/eventcatalog/src/features/studio/pages/index.astro +2 -1
  56. package/eventcatalog/src/features/studio/server/canvas-mcp.ts +1 -1
  57. package/eventcatalog/src/features/studio/server/runtime.ts +12 -4
  58. package/eventcatalog/src/utils/node-graphs/domain-levels-node-graph.ts +3 -3
  59. package/eventcatalog/src/utils/node-graphs/node-resource.ts +67 -0
  60. package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +1 -1
  61. package/package.json +3 -3
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <div align="center">
2
2
 
3
3
  <!-- <h1>📖 EventCatalog</h1> -->
4
- <!-- <h3>The open source tool to help you discover and document your event-driven architectures</h3> -->
4
+ <!-- <h3>The source-available tool to help you discover and document your event-driven architectures</h3> -->
5
5
 
6
6
 
7
7
 
@@ -35,7 +35,7 @@
35
35
  <div align="center">
36
36
 
37
37
  [![main](https://github.com/event-catalog/eventcatalog/actions/workflows/verify-build.yml/badge.svg)](https://github.com/event-catalog/eventcatalog/actions/workflows/verify-build.yml)
38
- [![License](https://img.shields.io/badge/License-MIT%20%2B%20Commercial-blue.svg)](./LICENSE)
38
+ [![License: BSL 1.1](https://img.shields.io/badge/License-BSL%201.1-blue.svg)](https://github.com/event-catalog/eventcatalog/blob/main/LICENSE)
39
39
  [![npm version](https://badge.fury.io/js/@eventcatalog%2Fcore.svg)](https://badge.fury.io/js/@eventcatalog/core)
40
40
 
41
41
  </div>
@@ -205,6 +205,6 @@ This project follows the [all-contributors](https://github.com/all-contributors/
205
205
 
206
206
  # License
207
207
 
208
- `@eventcatalog/core` 5.0.0 (including its pre-releases) and later is licensed under the
209
- [Business Source License 1.1](./LICENSE). Releases up to and including 4.x remain available under the MIT
210
- License (see [NOTICE](./NOTICE)).
208
+ EventCatalog is source-available under the [Business Source License 1.1](https://github.com/event-catalog/eventcatalog/blob/main/LICENSE). It is free for eligible organisations (under USD 10M revenue and under USD 10M funding). Otherwise it is covered by a subscription. See [pricing](https://www.eventcatalog.dev/pricing).
209
+
210
+ `@eventcatalog/core` version 5.0.0 (including its pre-releases) and later is covered by that licence. Releases up to and including 4.x remain available under the MIT License (see [NOTICE](./NOTICE)).
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(analytics_exports);
36
36
  var import_os = __toESM(require("os"), 1);
37
37
 
38
38
  // package.json
39
- var version = "5.0.0-beta.10";
39
+ var version = "5.0.0-beta.12";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-LJMXOEEC.js";
3
+ } from "../chunk-CX2VB7AI.js";
4
4
  import "../chunk-CPW6G62V.js";
5
- import "../chunk-IONYKKOY.js";
5
+ import "../chunk-FY6MSP6J.js";
6
6
  export {
7
7
  raiseEvent
8
8
  };
@@ -176,7 +176,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
176
176
  var import_os = __toESM(require("os"), 1);
177
177
 
178
178
  // package.json
179
- var version = "5.0.0-beta.10";
179
+ var version = "5.0.0-beta.12";
180
180
 
181
181
  // src/constants.ts
182
182
  var VERSION = version;
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-CRKJBDN7.js";
3
+ } from "../chunk-BWC4YKW3.js";
4
4
  import "../chunk-AWOO63ME.js";
5
5
  import "../chunk-ZAZHAVKB.js";
6
- import "../chunk-LJMXOEEC.js";
6
+ import "../chunk-CX2VB7AI.js";
7
7
  import "../chunk-CPW6G62V.js";
8
- import "../chunk-IONYKKOY.js";
8
+ import "../chunk-FY6MSP6J.js";
9
9
  import "../chunk-RFIXKATC.js";
10
10
  export {
11
11
  log_build_default as default
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-ZAZHAVKB.js";
9
9
  import {
10
10
  raiseEvent
11
- } from "./chunk-LJMXOEEC.js";
11
+ } from "./chunk-CX2VB7AI.js";
12
12
  import {
13
13
  TELEMETRY_REQUEST_TIMEOUT_MS,
14
14
  isTelemetryDisabled
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-CPW6G62V.js";
5
5
  import {
6
6
  VERSION
7
- } from "./chunk-IONYKKOY.js";
7
+ } from "./chunk-FY6MSP6J.js";
8
8
 
9
9
  // src/analytics/analytics.js
10
10
  import os from "os";
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "5.0.0-beta.10";
2
+ var version = "5.0.0-beta.12";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-IONYKKOY.js";
3
+ } from "./chunk-FY6MSP6J.js";
4
4
 
5
5
  // src/utils/cli-logger.ts
6
6
  import pc from "picocolors";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-2LBDRHE4.js";
3
+ } from "./chunk-QB7X34OD.js";
4
4
  import {
5
5
  cleanup,
6
6
  getEventCatalogConfigFile
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "5.0.0-beta.10";
28
+ var version = "5.0.0-beta.12";
29
29
 
30
30
  // src/constants.ts
31
31
  var VERSION = version;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-IONYKKOY.js";
3
+ } from "./chunk-FY6MSP6J.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -181,7 +181,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
181
181
  var import_picocolors = __toESM(require("picocolors"), 1);
182
182
 
183
183
  // package.json
184
- var version = "5.0.0-beta.10";
184
+ var version = "5.0.0-beta.12";
185
185
 
186
186
  // src/constants.ts
187
187
  var VERSION = version;
@@ -4,7 +4,7 @@ import {
4
4
  import "./chunk-CA4U2JP7.js";
5
5
  import {
6
6
  log_build_default
7
- } from "./chunk-CRKJBDN7.js";
7
+ } from "./chunk-BWC4YKW3.js";
8
8
  import {
9
9
  getLicenseStatus,
10
10
  printLicenseStatus
@@ -33,10 +33,10 @@ import {
33
33
  } from "./chunk-MDWB5HLO.js";
34
34
  import {
35
35
  generate
36
- } from "./chunk-EM36OL6A.js";
36
+ } from "./chunk-TSY5CC27.js";
37
37
  import {
38
38
  logger
39
- } from "./chunk-2LBDRHE4.js";
39
+ } from "./chunk-QB7X34OD.js";
40
40
  import {
41
41
  resolve_catalog_dependencies_default
42
42
  } from "./chunk-36RYTYT5.js";
@@ -50,7 +50,7 @@ import {
50
50
  import {
51
51
  watch
52
52
  } from "./chunk-U63GDPPY.js";
53
- import "./chunk-LJMXOEEC.js";
53
+ import "./chunk-CX2VB7AI.js";
54
54
  import "./chunk-CPW6G62V.js";
55
55
  import {
56
56
  getAstroConfigPath
@@ -67,7 +67,7 @@ import {
67
67
  } from "./chunk-LFQJXLHG.js";
68
68
  import {
69
69
  VERSION
70
- } from "./chunk-IONYKKOY.js";
70
+ } from "./chunk-FY6MSP6J.js";
71
71
  import {
72
72
  getEventCatalogConfigFile,
73
73
  verifyRequiredFieldsAreInCatalogConfigFile
package/dist/generate.cjs CHANGED
@@ -112,7 +112,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
112
112
  var import_picocolors = __toESM(require("picocolors"), 1);
113
113
 
114
114
  // package.json
115
- var version = "5.0.0-beta.10";
115
+ var version = "5.0.0-beta.12";
116
116
 
117
117
  // src/constants.ts
118
118
  var VERSION = version;
package/dist/generate.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  generate
3
- } from "./chunk-EM36OL6A.js";
4
- import "./chunk-2LBDRHE4.js";
5
- import "./chunk-IONYKKOY.js";
3
+ } from "./chunk-TSY5CC27.js";
4
+ import "./chunk-QB7X34OD.js";
5
+ import "./chunk-FY6MSP6J.js";
6
6
  import "./chunk-RFIXKATC.js";
7
7
  export {
8
8
  generate
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(cli_logger_exports);
36
36
  var import_picocolors = __toESM(require("picocolors"), 1);
37
37
 
38
38
  // package.json
39
- var version = "5.0.0-beta.10";
39
+ var version = "5.0.0-beta.12";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  logger
3
- } from "../chunk-2LBDRHE4.js";
4
- import "../chunk-IONYKKOY.js";
3
+ } from "../chunk-QB7X34OD.js";
4
+ import "../chunk-FY6MSP6J.js";
5
5
  export {
6
6
  logger
7
7
  };
@@ -29,6 +29,8 @@ const CHAT_PANEL_STYLES = `
29
29
  }
30
30
  .ec-chat-surface { font-weight: 400; }
31
31
  .ec-chat-avatar { background: rgb(var(--ec-accent) / .06); animation: ec-chat-breathe 5s ease-in-out infinite; }
32
+ /* The closed panel stays on the page (off screen): a running animation there still costs every frame */
33
+ .ec-chat-surface[aria-hidden='true'] .ec-chat-avatar { animation-play-state: paused; }
32
34
  .ec-chat-suggestion { width: fit-content; max-width: 100%; transition: background 180ms, transform 180ms; }
33
35
  .ec-chat-suggestion:hover { transform: translateX(3px); }
34
36
  .ec-chat-message { animation: fadeInUp 280ms ease-out both; }
@@ -12,10 +12,14 @@
12
12
  * CSS ships in the page head and survives ClientRouter navigations (see NodeGraph.astro).
13
13
  */
14
14
 
15
- import { useCallback, lazy, Suspense } from 'react';
15
+ import { useCallback, useState, lazy, Suspense } from 'react';
16
16
  import type { Node, Edge } from '@xyflow/react';
17
- import type { FlowGroupBy } from '@eventcatalog/visualiser';
17
+ import type { FlowGroupBy, OpenInStudioRequest } from '@eventcatalog/visualiser';
18
18
  import { buildUrl } from '@utils/url-builder';
19
+ import { createCanvasThroughApi } from '@features/studio/api/client';
20
+ import { canvasFromVisualiser } from '@features/studio/from-visualiser';
21
+ import { getStoredName } from '@features/studio/identity';
22
+ import OpenInStudioDialog from '@features/studio/components/OpenInStudioDialog';
19
23
 
20
24
  const NodeGraph = lazy(() =>
21
25
  import('@eventcatalog/visualiser').then((module) => ({ default: module.NodeGraph }))
@@ -57,9 +61,11 @@ interface AstroNodeGraphProps {
57
61
  preferenceScope?: string;
58
62
  // Group a flow's steps into swimlanes to start with
59
63
  swimlanes?: FlowGroupBy;
64
+ // The Studio API's address, when Studio is on: the menu can then start a canvas from the diagram
65
+ studioApiUrl?: string;
60
66
  }
61
67
 
62
- const AstroNodeGraph = ({ isDevMode = false, resourceKey, ...otherProps }: AstroNodeGraphProps) => {
68
+ const AstroNodeGraph = ({ isDevMode = false, resourceKey, studioApiUrl, ...otherProps }: AstroNodeGraphProps) => {
63
69
  // Astro-specific navigation handler
64
70
  const handleNavigate = useCallback((url: string) => {
65
71
  // Use window.location for navigation since we can't import astro:transitions/client in a React component
@@ -108,6 +114,29 @@ const AstroNodeGraph = ({ isDevMode = false, resourceKey, ...otherProps }: Astro
108
114
  }
109
115
  }, []);
110
116
 
117
+ // Opening the diagram in Studio: asks what to call the canvas, then makes it with what the diagram shows and opens
118
+ // it (in this tab) at the level shown. What it shows is only taken once it's named (laying a level out can take a
119
+ // moment), and anything that goes wrong is shown in the dialog.
120
+ const [toOpen, setToOpen] = useState<OpenInStudioRequest | null>(null);
121
+ const closeOpenInStudio = useCallback(() => setToOpen(null), []);
122
+ const openInStudio = useCallback(
123
+ async (title: string | undefined) => {
124
+ if (!studioApiUrl || !toOpen) return;
125
+ const snapshot = await toOpen.getSnapshot();
126
+ const { nodes, edges, levels } = canvasFromVisualiser(snapshot);
127
+ if (nodes.length === 0) throw new Error('Nothing on this diagram can go on a canvas yet');
128
+ const canvas = await createCanvasThroughApi(studioApiUrl, {
129
+ title,
130
+ createdBy: getStoredName() ?? undefined,
131
+ nodes,
132
+ edges,
133
+ levels,
134
+ });
135
+ window.location.assign(snapshot.level === 3 ? canvas.url : `${canvas.url}?level=${snapshot.level}`);
136
+ },
137
+ [studioApiUrl, toOpen]
138
+ );
139
+
111
140
  return (
112
141
  <Suspense fallback={<div>Loading graph...</div>}>
113
142
  <NodeGraph
@@ -118,7 +147,9 @@ const AstroNodeGraph = ({ isDevMode = false, resourceKey, ...otherProps }: Astro
118
147
  onBuildUrl={handleBuildUrl}
119
148
  onSaveLayout={handleSaveLayout}
120
149
  onResetLayout={handleResetLayout}
150
+ onOpenInStudio={studioApiUrl ? setToOpen : undefined}
121
151
  />
152
+ {toOpen && <OpenInStudioDialog title={toOpen.title} onOpen={openInStudio} onClose={closeOpenInStudio} />}
122
153
  </Suspense>
123
154
  );
124
155
  };
@@ -31,11 +31,14 @@ import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
31
31
  import { getNodesAndEdges as getNodesAndEdgesForContainer } from '@utils/node-graphs/container-node-graph';
32
32
  import { getNodesAndEdges as getNodesAndEdgesForChannel } from '@utils/node-graphs/channel-node-graph';
33
33
  import config from '@config';
34
- import { isEventCatalogChatVisible, isDevMode } from '@utils/feature';
34
+ import { isEventCatalogChatVisible, isDevMode, isCanvasEnabled } from '@utils/feature';
35
+ import { CANVASES_API_PATH } from '@features/studio/api/canvases-api';
35
36
  import { loadSavedLayout, applyLayoutToNodes, buildResourceKey } from '@utils/node-graphs/layout-persistence';
36
37
  import { compactVisualiserGraph } from '@utils/node-graphs/compact-visualiser-graph';
37
38
 
38
39
  const isChatEnabled = isEventCatalogChatVisible();
40
+ // With Studio on, the menu can start a canvas from the diagram
41
+ const studioApiUrl = isCanvasEnabled() ? buildUrl(CANVASES_API_PATH, true) : undefined;
39
42
 
40
43
  interface Props {
41
44
  id: string;
@@ -257,6 +260,7 @@ if (overview && levelsOverview) {
257
260
  hiddenMessagesGraph={hiddenMessagesGraph}
258
261
  preferenceScope={collection}
259
262
  swimlanes={lanes}
263
+ studioApiUrl={studioApiUrl}
260
264
  />
261
265
  </div>
262
266
 
@@ -22,12 +22,19 @@
22
22
  opacity: 1;
23
23
  }
24
24
 
25
+ /* On every page, hidden until a navigation takes a while: paused until then (a running animation costs a style
26
+ recalc and paint on every frame, even when it can't be seen) */
25
27
  .navigation-progress__bar {
26
28
  width: 35%;
27
29
  height: 100%;
28
30
  background: rgb(var(--ec-accent));
29
31
  box-shadow: 0 0 10px rgb(var(--ec-accent) / 0.55);
30
32
  animation: navigation-progress 1.1s ease-in-out infinite;
33
+ animation-play-state: paused;
34
+ }
35
+
36
+ #navigation-progress[data-visible='true'] .navigation-progress__bar {
37
+ animation-play-state: running;
31
38
  }
32
39
 
33
40
  :global([data-navigation-pending='true']) {
@@ -6,7 +6,8 @@
6
6
  import { useEffect, useRef, useState, type FormEvent, type KeyboardEvent, type RefObject } from 'react';
7
7
  import type { Node } from '@xyflow/react';
8
8
  import { Check, Network, SendHorizontal, X } from 'lucide-react';
9
- import type { ArchitectureDiagramCollection } from '@utils/node-graphs/architecture-diagram-types';
9
+ import { isArchitectureDiagramCollection } from '@utils/node-graphs/architecture-diagram-types';
10
+ import { getNodeCatalogResource, getNodeResourceDetails } from '@utils/node-graphs/node-resource';
10
11
  import type { DiagramLink } from './links';
11
12
  import { RESOURCE_TYPE_LABELS } from '../shared/resource-types';
12
13
 
@@ -36,53 +37,13 @@ const NODE_TYPE_LABELS: Record<string, string> = {
36
37
  externalSystem: 'External system',
37
38
  };
38
39
 
39
- // Where each node type keeps the resource it shows
40
- const RESOURCE_DATA_KEYS = [
41
- 'service',
42
- 'agent',
43
- 'message',
44
- 'channel',
45
- 'data',
46
- 'dataProduct',
47
- 'flow',
48
- 'entity',
49
- 'domain',
50
- 'system',
51
- 'custom',
52
- ];
53
-
54
- // The collection of each node type the architecture diagram tool can draw a diagram for
55
- const DIAGRAM_COLLECTIONS: Record<string, ArchitectureDiagramCollection> = {
56
- services: 'services',
57
- agents: 'agents',
58
- events: 'events',
59
- commands: 'commands',
60
- queries: 'queries',
61
- flows: 'flows',
62
- data: 'containers',
63
- containers: 'containers',
64
- 'data-products': 'data-products',
65
- domains: 'domains',
66
- 'context-domain': 'domains',
67
- 'domain-group': 'domains',
68
- systems: 'systems',
69
- 'system-group': 'systems',
70
- };
71
-
72
- // Domain and system boundaries only have their catalog id in the node id: {kind}-group-{id}-{version}
73
- const catalogIdOfGroup = (node: Node, version?: string) => {
74
- const match = node.id.match(/^(?:domain|system)-group-(.+)$/);
75
- if (!match) return undefined;
76
- return version && match[1].endsWith(`-${version}`) ? match[1].slice(0, -(version.length + 1)) : match[1];
77
- };
78
-
79
40
  export function describeNode(node: Node): SelectedNode {
80
41
  const data = (node.data ?? {}) as Record<string, any>;
81
- const resource = RESOURCE_DATA_KEYS.map((key) => data[key]).find(Boolean) ?? data;
82
- const details = resource?.data ?? resource;
42
+ const details = (getNodeResourceDetails(node) ?? data) as Record<string, any>;
83
43
  const version: string | undefined = details?.version;
84
- const id: string = details?.id ?? catalogIdOfGroup(node, version) ?? node.id;
85
- const collection = DIAGRAM_COLLECTIONS[node.type ?? ''];
44
+ const id: string = details?.id ?? node.id;
45
+ const resource = getNodeCatalogResource(node);
46
+ const collection = resource && isArchitectureDiagramCollection(resource.collection) ? resource.collection : undefined;
86
47
 
87
48
  return {
88
49
  nodeId: node.id,