@eventcatalog/core 2.65.0 → 3.0.0-beta.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.
Files changed (130) hide show
  1. package/README.md +1 -26
  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-NK6OYMRD.js → chunk-JB4YT5JY.js} +1 -1
  7. package/dist/{chunk-BMDTX5IN.js → chunk-TQ4HZREX.js} +1 -1
  8. package/dist/{chunk-IJRFYF4B.js → chunk-X4W4YC3U.js} +1 -1
  9. package/dist/constants.cjs +1 -1
  10. package/dist/constants.js +1 -1
  11. package/dist/eventcatalog.cjs +1 -21
  12. package/dist/eventcatalog.config.d.cts +10 -0
  13. package/dist/eventcatalog.config.d.ts +10 -0
  14. package/dist/eventcatalog.js +3 -20
  15. package/eventcatalog/src/components/CopyAsMarkdown.tsx +19 -1
  16. package/eventcatalog/src/components/FavoriteButton.tsx +54 -0
  17. package/eventcatalog/src/components/Grids/DomainGrid.tsx +386 -362
  18. package/eventcatalog/src/components/Grids/MessageGrid.tsx +166 -518
  19. package/eventcatalog/src/components/Header.astro +48 -23
  20. package/eventcatalog/src/components/Lists/VersionList.astro +2 -2
  21. package/eventcatalog/src/components/MDX/Design/Design.astro +4 -1
  22. package/eventcatalog/src/components/MDX/Flow/Flow.astro +2 -1
  23. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +3 -3
  24. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +8 -2
  25. package/eventcatalog/src/components/SchemaExplorer/SchemaPageViewer.tsx +37 -0
  26. package/eventcatalog/src/components/Search/Search.astro +48 -28
  27. package/eventcatalog/src/components/Search/SearchModal.tsx +393 -702
  28. package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +298 -0
  29. package/eventcatalog/src/components/SideNav/NestedSideBar/builders/container.ts +66 -0
  30. package/eventcatalog/src/components/SideNav/NestedSideBar/builders/domain.ts +101 -0
  31. package/eventcatalog/src/components/SideNav/NestedSideBar/builders/flow.ts +29 -0
  32. package/eventcatalog/src/components/SideNav/NestedSideBar/builders/message.ts +84 -0
  33. package/eventcatalog/src/components/SideNav/NestedSideBar/builders/service.ts +147 -0
  34. package/eventcatalog/src/components/SideNav/NestedSideBar/builders/shared.ts +146 -0
  35. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +1073 -0
  36. package/eventcatalog/src/components/SideNav/NestedSideBar/sidebar-builder.ts +365 -0
  37. package/eventcatalog/src/components/SideNav/NestedSideBar/storage.ts +90 -0
  38. package/eventcatalog/src/components/SideNav/SideNav.astro +18 -28
  39. package/eventcatalog/src/content.config.ts +2 -0
  40. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +10 -4
  41. package/eventcatalog/src/enterprise/eventcatalog-chat/pages/chat/index.astro +3 -3
  42. package/eventcatalog/src/layouts/DirectoryLayout.astro +2 -2
  43. package/eventcatalog/src/layouts/DiscoverLayout.astro +3 -3
  44. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +85 -63
  45. package/eventcatalog/src/layouts/VisualiserLayout.astro +3 -3
  46. package/eventcatalog/src/pages/_index.astro +530 -110
  47. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +64 -0
  48. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +29 -0
  49. package/eventcatalog/src/pages/directory/[type]/_index.data.ts +4 -4
  50. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -4
  51. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +3 -3
  52. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +1 -5
  53. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +362 -190
  54. package/eventcatalog/src/pages/docs/[type]/[id]/[version].md.ts +1 -1
  55. package/eventcatalog/src/pages/docs/[type]/[id]/index.astro +4 -4
  56. package/eventcatalog/src/pages/docs/[type]/[id]/language/_index.data.ts +1 -4
  57. package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +3 -27
  58. package/eventcatalog/src/pages/docs/teams/[id]/_index.data.ts +2 -2
  59. package/eventcatalog/src/pages/docs/users/[id]/_index.data.ts +2 -2
  60. package/eventcatalog/src/pages/index.astro +14 -5
  61. package/eventcatalog/src/pages/nav-index.json.ts +30 -0
  62. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/_index.data.ts +77 -0
  63. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +90 -0
  64. package/eventcatalog/src/pages/schemas/{index.astro → explorer/index.astro} +3 -3
  65. package/eventcatalog/src/pages/studio.astro +3 -3
  66. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +4 -3
  67. package/eventcatalog/src/pages/visualiser/[type]/[id]/index.astro +2 -2
  68. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/_index.data.ts +4 -3
  69. package/eventcatalog/src/stores/favorites-store.ts +83 -0
  70. package/eventcatalog/src/stores/sidebar-store.ts +8 -0
  71. package/eventcatalog/src/utils/collections/changelogs.ts +7 -4
  72. package/eventcatalog/src/utils/{channels.ts → collections/channels.ts} +81 -31
  73. package/eventcatalog/src/utils/collections/commands.ts +134 -0
  74. package/eventcatalog/src/utils/collections/containers.ts +44 -33
  75. package/eventcatalog/src/utils/collections/domains.ts +204 -62
  76. package/eventcatalog/src/utils/{entities.ts → collections/entities.ts} +44 -24
  77. package/eventcatalog/src/utils/collections/events.ts +136 -0
  78. package/eventcatalog/src/utils/collections/flows.ts +59 -25
  79. package/eventcatalog/src/utils/{messages.ts → collections/messages.ts} +13 -4
  80. package/eventcatalog/src/utils/{queries.ts → collections/queries.ts} +49 -28
  81. package/eventcatalog/src/utils/collections/services.ts +100 -68
  82. package/eventcatalog/src/utils/collections/teams.ts +94 -0
  83. package/eventcatalog/src/utils/collections/users.ts +122 -0
  84. package/eventcatalog/src/utils/collections/util.ts +57 -1
  85. package/eventcatalog/src/utils/feature.ts +3 -1
  86. package/eventcatalog/src/utils/{collections/file-diffs.ts → file-diffs.ts} +1 -1
  87. package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +2 -0
  88. package/eventcatalog/src/utils/node-graphs/domain-entity-map.ts +16 -6
  89. package/eventcatalog/src/utils/node-graphs/domains-canvas.ts +14 -10
  90. package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +36 -64
  91. package/eventcatalog/src/utils/node-graphs/flows-node-graph.ts +23 -19
  92. package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +36 -49
  93. package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +22 -18
  94. package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +4 -4
  95. package/eventcatalog/tailwind.config.mjs +14 -0
  96. package/eventcatalog/tsconfig.json +2 -1
  97. package/package.json +7 -4
  98. package/eventcatalog/public/logo_old.png +0 -0
  99. package/eventcatalog/src/components/DiscoverInsight.astro +0 -61
  100. package/eventcatalog/src/components/Grids/ServiceGrid.tsx +0 -534
  101. package/eventcatalog/src/components/Lists/CustomSideBarSectionList.astro +0 -55
  102. package/eventcatalog/src/components/Lists/ProtocolList.tsx +0 -74
  103. package/eventcatalog/src/components/Lists/RepositoryList.astro +0 -37
  104. package/eventcatalog/src/components/Lists/SpecificationsList.astro +0 -67
  105. package/eventcatalog/src/components/SideBars/ChannelSideBar.astro +0 -204
  106. package/eventcatalog/src/components/SideBars/ContainerSideBar.astro +0 -180
  107. package/eventcatalog/src/components/SideBars/DomainSideBar.astro +0 -273
  108. package/eventcatalog/src/components/SideBars/EntitySideBar.astro +0 -139
  109. package/eventcatalog/src/components/SideBars/FlowSideBar.astro +0 -128
  110. package/eventcatalog/src/components/SideBars/MessageSideBar.astro +0 -248
  111. package/eventcatalog/src/components/SideBars/ServiceSideBar.astro +0 -294
  112. package/eventcatalog/src/components/SideNav/ListViewSideBar/components/CollapsibleGroup.tsx +0 -46
  113. package/eventcatalog/src/components/SideNav/ListViewSideBar/components/MessageList.tsx +0 -78
  114. package/eventcatalog/src/components/SideNav/ListViewSideBar/components/SpecificationList.tsx +0 -83
  115. package/eventcatalog/src/components/SideNav/ListViewSideBar/index.tsx +0 -1250
  116. package/eventcatalog/src/components/SideNav/ListViewSideBar/types.ts +0 -91
  117. package/eventcatalog/src/components/SideNav/ListViewSideBar/utils.ts +0 -201
  118. package/eventcatalog/src/components/SideNav/TreeView/getTreeView.ts +0 -190
  119. package/eventcatalog/src/components/SideNav/TreeView/index.tsx +0 -94
  120. package/eventcatalog/src/components/TreeView/index.tsx +0 -328
  121. package/eventcatalog/src/components/TreeView/styles.module.css +0 -264
  122. package/eventcatalog/src/components/TreeView/useSlots.ts +0 -95
  123. package/eventcatalog/src/pages/architecture/[type]/index.astro +0 -14
  124. package/eventcatalog/src/pages/architecture/architecture.astro +0 -101
  125. package/eventcatalog/src/pages/architecture/docs/[type]/index.astro +0 -14
  126. package/eventcatalog/src/utils/commands.ts +0 -112
  127. package/eventcatalog/src/utils/events.ts +0 -108
  128. package/eventcatalog/src/utils/generators/index.ts +0 -10
  129. package/eventcatalog/src/utils/teams.ts +0 -72
  130. package/eventcatalog/src/utils/users.ts +0 -72
@@ -0,0 +1,365 @@
1
+ import { getContainers } from '@utils/collections/containers';
2
+ import { getDomains } from '@utils/collections/domains';
3
+ import { getServices } from '@utils/collections/services';
4
+ import { getMessages, pluralizeMessageType } from '@utils/collections/messages';
5
+ import { getOwner } from '@utils/collections/owners';
6
+ import { getFlows } from '@utils/collections/flows';
7
+ import { getUsers } from '@utils/collections/users';
8
+ import { getTeams } from '@utils/collections/teams';
9
+ import { buildUrl } from '@utils/url-builder';
10
+ import type { NavigationData, NavNode, ChildRef } from './builders/shared';
11
+ import { buildDomainNode } from './builders/domain';
12
+ import { buildServiceNode } from './builders/service';
13
+ import { buildMessageNode } from './builders/message';
14
+ import { buildContainerNode } from './builders/container';
15
+ import { buildFlowNode } from './builders/flow';
16
+ import config from '@config';
17
+ import { getDesigns } from '@utils/collections/designs';
18
+
19
+ export type { NavigationData, NavNode, ChildRef };
20
+
21
+ const CACHE_ENABLED = process.env.DISABLE_EVENTCATALOG_CACHE !== 'true';
22
+ let memoryCache: NavigationData | null = null;
23
+
24
+ /**
25
+ * Get the navigation data for the sidebar
26
+ */
27
+ export const getNestedSideBarData = async (): Promise<NavigationData> => {
28
+ if (memoryCache && CACHE_ENABLED) {
29
+ return memoryCache;
30
+ }
31
+
32
+ const [domains, services, { events, commands, queries }, containers, flows, users, teams, designs] = await Promise.all([
33
+ getDomains({ getAllVersions: false, includeServicesInSubdomains: false }),
34
+ getServices({ getAllVersions: false }),
35
+ getMessages({ getAllVersions: false }),
36
+ getContainers({ getAllVersions: false }),
37
+ getFlows({ getAllVersions: false }),
38
+ getUsers(),
39
+ getTeams(),
40
+ getDesigns(),
41
+ ]);
42
+
43
+ // Calculate derived lists to avoid extra fetches
44
+ const allSubDomainIds = new Set(domains.flatMap((d) => (d.data.domains || []).map((sd: any) => sd.data.id)));
45
+ const rootDomains = domains.filter((d) => !allSubDomainIds.has(d.data.id));
46
+
47
+ const messages = [...events, ...commands, ...queries];
48
+
49
+ const context = {
50
+ services,
51
+ domains,
52
+ events,
53
+ commands,
54
+ queries,
55
+ flows,
56
+ containers,
57
+ };
58
+
59
+ // Process all domains with their owners first (async)
60
+ const domainsWithOwners = await Promise.all(
61
+ domains.map(async (domain) => {
62
+ const ownersInDomain = domain.data.owners || [];
63
+ const owners = await Promise.all(ownersInDomain.map((owner) => getOwner(owner)));
64
+ const filteredOwners = owners.filter((o) => o !== undefined) as Array<NonNullable<(typeof owners)[0]>>;
65
+
66
+ return {
67
+ domain,
68
+ owners: filteredOwners,
69
+ };
70
+ })
71
+ );
72
+
73
+ // Services with owners
74
+ const servicesWithOwners = await Promise.all(
75
+ services.map(async (service) => {
76
+ const ownersInService = service.data.owners || [];
77
+ const owners = await Promise.all(ownersInService.map((owner) => getOwner(owner)));
78
+ const filteredOwners = owners.filter((o) => o !== undefined) as Array<NonNullable<(typeof owners)[0]>>;
79
+ return { service, owners: filteredOwners };
80
+ })
81
+ );
82
+
83
+ // Messages with owners
84
+ const messagesWithOwners = await Promise.all(
85
+ messages.map(async (message) => {
86
+ const ownersInMessage = message.data.owners || [];
87
+ const owners = await Promise.all(ownersInMessage.map((owner) => getOwner(owner)));
88
+ const filteredOwners = owners.filter((o) => o !== undefined) as Array<NonNullable<(typeof owners)[0]>>;
89
+ return { message, owners: filteredOwners };
90
+ })
91
+ );
92
+
93
+ const containerWithOwners = await Promise.all(
94
+ containers.map(async (container) => {
95
+ const ownersInContainer = container.data.owners || [];
96
+ const owners = await Promise.all(ownersInContainer.map((owner) => getOwner(owner)));
97
+ const filteredOwners = owners.filter((o) => o !== undefined) as Array<NonNullable<(typeof owners)[0]>>;
98
+ return { container, owners: filteredOwners };
99
+ })
100
+ );
101
+
102
+ const flowNodes = flows.reduce(
103
+ (acc, flow) => {
104
+ acc[`flow:${flow.data.id}:${flow.data.version}`] = buildFlowNode(flow);
105
+ return acc;
106
+ },
107
+ {} as Record<string, NavNode>
108
+ );
109
+
110
+ const domainNodes = domainsWithOwners.reduce(
111
+ (acc, { domain, owners }) => {
112
+ acc[`domain:${domain.data.id}:${domain.data.version}`] = buildDomainNode(domain, owners, context);
113
+ if (domain.data.latestVersion === domain.data.version) {
114
+ acc[`domain:${domain.data.id}`] = buildDomainNode(domain, owners, context);
115
+ }
116
+ return acc;
117
+ },
118
+ {} as Record<string, NavNode>
119
+ );
120
+
121
+ const serviceNodes = servicesWithOwners.reduce(
122
+ (acc, { service, owners }) => {
123
+ acc[`service:${service.data.id}:${service.data.version}`] = buildServiceNode(service, owners, context);
124
+ if (service.data.latestVersion === service.data.version) {
125
+ acc[`service:${service.data.id}`] = buildServiceNode(service, owners, context);
126
+ }
127
+ return acc;
128
+ },
129
+ {} as Record<string, NavNode>
130
+ );
131
+
132
+ const messageNodes = messagesWithOwners.reduce(
133
+ (acc, { message, owners }) => {
134
+ const type = pluralizeMessageType(message as any);
135
+
136
+ acc[`${type}:${message.data.id}:${message.data.version}`] = buildMessageNode(message, owners);
137
+ if (message.data.latestVersion === message.data.version) {
138
+ acc[`${type}:${message.data.id}`] = buildMessageNode(message, owners);
139
+ }
140
+ return acc;
141
+ },
142
+ {} as Record<string, NavNode>
143
+ );
144
+
145
+ const containerNodes = containerWithOwners.reduce(
146
+ (acc, { container, owners }) => {
147
+ acc[`container:${container.data.id}:${container.data.version}`] = buildContainerNode(container, owners);
148
+ if (container.data.latestVersion === container.data.version) {
149
+ acc[`container:${container.data.id}`] = buildContainerNode(container, owners);
150
+ }
151
+ return acc;
152
+ },
153
+ {} as Record<string, NavNode>
154
+ );
155
+
156
+ const designNodes = designs.reduce(
157
+ (acc, design) => {
158
+ acc[`design:${design.data.id}`] = {
159
+ type: 'item',
160
+ title: design.data.name,
161
+ badge: 'Design',
162
+ href: buildUrl(`/visualiser/designs/${design.data.id}`),
163
+ };
164
+ return acc;
165
+ },
166
+ {} as Record<string, NavNode>
167
+ );
168
+
169
+ const userNodes = users.reduce(
170
+ (acc, user) => {
171
+ acc[`user:${user.data.id}`] = {
172
+ type: 'item',
173
+ title: user.data.name,
174
+ href: buildUrl(`/docs/users/${user.data.id}`),
175
+ };
176
+ return acc;
177
+ },
178
+ {} as Record<string, NavNode>
179
+ );
180
+
181
+ const teamNodes = teams.reduce(
182
+ (acc, team) => {
183
+ acc[`team:${team.data.id}`] = {
184
+ type: 'item',
185
+ title: team.data.name,
186
+ href: buildUrl(`/docs/teams/${team.data.id}`),
187
+ };
188
+ return acc;
189
+ },
190
+ {} as Record<string, NavNode>
191
+ );
192
+
193
+ const rootDomainsNodes: Record<string, NavNode> = {};
194
+
195
+ if (rootDomains.length > 0) {
196
+ rootDomainsNodes['list:top-level-domains'] = {
197
+ type: 'group',
198
+ title: 'Domains',
199
+ icon: 'Boxes',
200
+ pages: rootDomains.map((domain) => `domain:${domain.data.id}:${domain.data.version}`),
201
+ };
202
+ }
203
+
204
+ const createLeaf = (items: any[], node: NavNode) => (items.length > 0 ? node : undefined);
205
+
206
+ const domainsList = createLeaf(domains, {
207
+ type: 'item',
208
+ title: 'Domains',
209
+ icon: 'Boxes',
210
+ pages: domains.map((domain) => `domain:${domain.data.id}:${domain.data.version}`),
211
+ });
212
+
213
+ const servicesList = createLeaf(services, {
214
+ type: 'item',
215
+ title: 'Services',
216
+ icon: 'Server',
217
+ pages: services.map((service) => `service:${service.data.id}:${service.data.version}`),
218
+ });
219
+
220
+ const eventsList = createLeaf(events, {
221
+ type: 'group',
222
+ title: 'Events',
223
+ icon: 'Zap',
224
+ pages: events.map((event) => `event:${event.data.id}:${event.data.version}`),
225
+ });
226
+
227
+ const commandsList = createLeaf(commands, {
228
+ type: 'group',
229
+ title: 'Commands',
230
+ icon: 'Terminal',
231
+ pages: commands.map((command) => `command:${command.data.id}:${command.data.version}`),
232
+ });
233
+
234
+ const queriesList = createLeaf(queries, {
235
+ type: 'group',
236
+ title: 'Queries',
237
+ icon: 'Search',
238
+ pages: queries.map((query) => `query:${query.data.id}:${query.data.version}`),
239
+ });
240
+
241
+ const flowsList = createLeaf(flows, {
242
+ type: 'item',
243
+ title: 'Flows',
244
+ icon: 'Waypoints',
245
+ pages: flows.map((flow) => `flow:${flow.data.id}:${flow.data.version}`),
246
+ });
247
+
248
+ const containersList = createLeaf(containers, {
249
+ type: 'item',
250
+ title: 'Data Stores',
251
+ icon: 'Database',
252
+ pages: containers.map((container) => `container:${container.data.id}:${container.data.version}`),
253
+ });
254
+
255
+ const designsList = createLeaf(designs, {
256
+ type: 'item',
257
+ title: 'Designs',
258
+ icon: 'SquareMousePointer',
259
+ pages: designs.map((design) => `design:${design.data.id}`),
260
+ });
261
+
262
+ const teamsList = createLeaf(teams, {
263
+ type: 'group',
264
+ title: 'Teams',
265
+ icon: 'Users',
266
+ pages: teams.map((team) => `team:${team.data.id}`),
267
+ });
268
+
269
+ const usersList = createLeaf(users, {
270
+ type: 'group',
271
+ title: 'Users',
272
+ icon: 'User',
273
+ pages: users.map((user) => `user:${user.data.id}`),
274
+ });
275
+
276
+ const messagesChildren = ['list:events', 'list:commands', 'list:queries'].filter(
277
+ (key, index) => [eventsList, commandsList, queriesList][index] !== undefined
278
+ );
279
+
280
+ let messagesList;
281
+ if (messagesChildren.length > 0) {
282
+ messagesList = {
283
+ type: 'item',
284
+ title: 'Messages',
285
+ icon: 'Mail',
286
+ pages: messagesChildren,
287
+ };
288
+ }
289
+
290
+ const peopleChildren = ['list:teams', 'list:users'].filter((key, index) => [teamsList, usersList][index] !== undefined);
291
+
292
+ let peopleList;
293
+ if (peopleChildren.length > 0) {
294
+ peopleList = {
295
+ type: 'item',
296
+ title: 'Teams & Users',
297
+ icon: 'Users',
298
+ pages: peopleChildren,
299
+ };
300
+ }
301
+
302
+ const allChildrenKeys = [
303
+ 'list:domains',
304
+ 'list:services',
305
+ 'list:messages',
306
+ 'list:flows',
307
+ 'list:containers',
308
+ 'list:designs',
309
+ 'list:people',
310
+ ];
311
+ const allChildrenNodes = [domainsList, servicesList, messagesList, flowsList, containersList, designsList, peopleList];
312
+
313
+ const validAllChildren = allChildrenKeys.filter((_, idx) => allChildrenNodes[idx] !== undefined);
314
+
315
+ let allList;
316
+ if (validAllChildren.length > 0) {
317
+ allList = {
318
+ type: 'group',
319
+ title: 'Browse',
320
+ icon: 'Telescope',
321
+ pages: validAllChildren,
322
+ };
323
+ }
324
+
325
+ const allNodes: Record<string, NavNode> = {
326
+ ...(domainsList ? { 'list:domains': domainsList } : {}),
327
+ ...(servicesList ? { 'list:services': servicesList } : {}),
328
+ ...(eventsList ? { 'list:events': eventsList } : {}),
329
+ ...(commandsList ? { 'list:commands': commandsList } : {}),
330
+ ...(queriesList ? { 'list:queries': queriesList } : {}),
331
+ ...(messagesList ? { 'list:messages': messagesList as NavNode } : {}),
332
+ ...(flowsList ? { 'list:flows': flowsList } : {}),
333
+ ...(containersList ? { 'list:containers': containersList } : {}),
334
+ ...(designsList ? { 'list:designs': designsList } : {}),
335
+ ...(teamsList ? { 'list:teams': teamsList } : {}),
336
+ ...(usersList ? { 'list:users': usersList } : {}),
337
+ ...(peopleList ? { 'list:people': peopleList as NavNode } : {}),
338
+ ...(allList ? { 'list:all': allList as NavNode } : {}),
339
+ };
340
+
341
+ const allGeneratedNodes = {
342
+ ...rootDomainsNodes,
343
+ ...domainNodes,
344
+ ...serviceNodes,
345
+ ...messageNodes,
346
+ ...containerNodes,
347
+ ...flowNodes,
348
+ ...userNodes,
349
+ ...teamNodes,
350
+ ...designNodes,
351
+ ...allNodes,
352
+ };
353
+
354
+ // only filter if child is string
355
+ const rootNavigationConfig = config?.navigation?.pages || ['list:top-level-domains', 'list:all'];
356
+
357
+ const navigationConfig = {
358
+ roots: rootNavigationConfig,
359
+ nodes: allGeneratedNodes,
360
+ };
361
+
362
+ memoryCache = navigationConfig;
363
+
364
+ return navigationConfig;
365
+ };
@@ -0,0 +1,90 @@
1
+ // ============================================
2
+ // Local Storage Persistence
3
+ // ============================================
4
+
5
+ const STORAGE_KEY = 'eventcatalog-sidebar-nav';
6
+ const COLLAPSED_SECTIONS_KEY = 'eventcatalog-sidebar-collapsed';
7
+ const FAVORITES_KEY = 'eventcatalog-sidebar-favorites';
8
+
9
+ // ============================================
10
+ // Types
11
+ // ============================================
12
+
13
+ export type PersistedState = {
14
+ path: string[]; // Array of node keys representing drill-down path
15
+ currentUrl: string; // The URL when this state was saved
16
+ };
17
+
18
+ export type FavoriteItem = {
19
+ nodeKey: string; // The key of the favorited node
20
+ path: string[]; // Path of keys to reach this node
21
+ title: string; // Display title
22
+ badge?: string; // Type badge (Domain, Service, etc.)
23
+ href?: string; // Direct link if it's a leaf item
24
+ };
25
+
26
+ // ============================================
27
+ // Navigation State
28
+ // ============================================
29
+
30
+ export const saveState = (state: PersistedState): void => {
31
+ try {
32
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
33
+ } catch (e) {
34
+ console.warn('Failed to save sidebar state:', e);
35
+ }
36
+ };
37
+
38
+ export const loadState = (): PersistedState | null => {
39
+ try {
40
+ const stored = localStorage.getItem(STORAGE_KEY);
41
+ return stored ? JSON.parse(stored) : null;
42
+ } catch (e) {
43
+ console.warn('Failed to load sidebar state:', e);
44
+ return null;
45
+ }
46
+ };
47
+
48
+ // ============================================
49
+ // Collapsed Sections
50
+ // ============================================
51
+
52
+ export const saveCollapsedSections = (sections: Set<string>): void => {
53
+ try {
54
+ localStorage.setItem(COLLAPSED_SECTIONS_KEY, JSON.stringify([...sections]));
55
+ } catch (e) {
56
+ console.warn('Failed to save collapsed sections:', e);
57
+ }
58
+ };
59
+
60
+ export const loadCollapsedSections = (): Set<string> => {
61
+ try {
62
+ const stored = localStorage.getItem(COLLAPSED_SECTIONS_KEY);
63
+ return stored ? new Set(JSON.parse(stored)) : new Set();
64
+ } catch (e) {
65
+ console.warn('Failed to load collapsed sections:', e);
66
+ return new Set();
67
+ }
68
+ };
69
+
70
+ // ============================================
71
+ // Favorites
72
+ // ============================================
73
+
74
+ export const saveFavorites = (favorites: FavoriteItem[]): void => {
75
+ try {
76
+ localStorage.setItem(FAVORITES_KEY, JSON.stringify(favorites));
77
+ } catch (e) {
78
+ console.warn('Failed to save favorites:', e);
79
+ }
80
+ };
81
+
82
+ export const loadFavorites = (): FavoriteItem[] => {
83
+ try {
84
+ const stored = localStorage.getItem(FAVORITES_KEY);
85
+ return stored ? JSON.parse(stored) : [];
86
+ } catch (e) {
87
+ console.warn('Failed to load favorites:', e);
88
+ return [];
89
+ }
90
+ };
@@ -1,37 +1,27 @@
1
1
  ---
2
2
  import type { HTMLAttributes } from 'astro/types';
3
- import config from '@config';
4
-
5
- // FlatView
6
- import { getResourcesForNavigation as getListViewResources } from './ListViewSideBar/utils';
7
-
8
- // TreeView
9
- import { SideNavTreeView } from './TreeView';
10
- import { getTreeView } from './TreeView/getTreeView';
11
-
12
- import ListViewSideBar from './ListViewSideBar';
13
3
 
14
4
  interface Props extends Omit<HTMLAttributes<'div'>, 'children'> {}
5
+ import { getNestedSideBarData } from './NestedSideBar/sidebar-builder';
6
+ import NestedSideBar from './NestedSideBar';
7
+ import { ClientRouter } from 'astro:transitions';
15
8
 
16
- const currentPath = Astro.url.pathname;
17
-
18
- let props;
19
-
20
- const SIDENAV_TYPE = config?.docs?.sidebar?.type ?? 'LIST_VIEW';
21
- const SHOW_ORPHANED_MESSAGES = config?.docs?.sidebar?.showOrphanedMessages ?? true;
22
-
23
- if (SIDENAV_TYPE === 'LIST_VIEW') {
24
- props = await getListViewResources({ currentPath });
25
- } else if (SIDENAV_TYPE === 'TREE_VIEW') {
26
- props = getTreeView({ projectDir: process.env.PROJECT_DIR!, currentPath });
27
- }
9
+ const props = await getNestedSideBarData();
28
10
  ---
29
11
 
30
12
  <div {...Astro.props}>
31
- {
32
- SIDENAV_TYPE === 'LIST_VIEW' && (
33
- <ListViewSideBar resources={props} currentPath={currentPath} client:only showOrphanedMessages={SHOW_ORPHANED_MESSAGES} />
34
- )
35
- }
36
- {SIDENAV_TYPE === 'TREE_VIEW' && <SideNavTreeView client:only transition:persist tree={props} />}
13
+ <ClientRouter />
14
+ <NestedSideBar client:only="react" />
37
15
  </div>
16
+
17
+ <script is:inline define:vars={{ props }}>
18
+ window.sidebarData = props;
19
+ </script>
20
+
21
+ <script>
22
+ import { setSidebarData } from '@stores/sidebar-store';
23
+ const data = (window as any).sidebarData;
24
+ if (data) {
25
+ setSidebarData(data);
26
+ }
27
+ </script>
@@ -390,6 +390,7 @@ const services = defineCollection({
390
390
  entities: z.array(pointer).optional(),
391
391
  writesTo: z.array(pointer).optional(),
392
392
  readsFrom: z.array(pointer).optional(),
393
+ flows: z.array(pointer).optional(),
393
394
  detailsPanel: z
394
395
  .object({
395
396
  domains: detailPanelPropertySchema.optional(),
@@ -497,6 +498,7 @@ const domains = defineCollection({
497
498
  services: z.array(pointer).optional(),
498
499
  domains: z.array(pointer).optional(),
499
500
  entities: z.array(pointer).optional(),
501
+ flows: z.array(pointer).optional(),
500
502
  detailsPanel: z
501
503
  .object({
502
504
  parentDomains: detailPanelPropertySchema.optional(),
@@ -16,6 +16,8 @@ import { getAdjacentPages } from '@enterprise/custom-documentation/utils/custom-
16
16
  import CustomDocsNav from '@enterprise/custom-documentation/components/CustomDocsNav/CustomDocsNav.astro';
17
17
  import NodeGraph from '@components/MDX/NodeGraph/NodeGraph.astro';
18
18
 
19
+ import { isVisualiserEnabled } from '@utils/feature';
20
+
19
21
  const props = Astro.props;
20
22
  const doc = props.data;
21
23
  const { Content, headings } = await render(props as any);
@@ -132,10 +134,14 @@ const badges = doc?.badges || [];
132
134
  title={nodeGraph.title}
133
135
  mode="simple"
134
136
  linksToVisualiser={true}
135
- href={{
136
- label: 'Open in Visualiser',
137
- url: buildUrl(`/visualiser/${collection}/${nodeGraph.id}/${nodeGraph.version}`),
138
- }}
137
+ href={
138
+ isVisualiserEnabled()
139
+ ? {
140
+ label: 'Open in Visualiser',
141
+ url: buildUrl(`/visualiser/${collection}/${nodeGraph.id}/${nodeGraph.version}`),
142
+ }
143
+ : undefined
144
+ }
139
145
  />
140
146
  );
141
147
  })
@@ -5,10 +5,10 @@ import { getChatPromptsGroupedByCategory } from '@enterprise/eventcatalog-chat/u
5
5
  import config from '@config';
6
6
  import { Code } from 'astro-expressive-code/components';
7
7
  import { getDomains } from '@utils/collections/domains';
8
- import { getEvents } from '@utils/events';
9
- import { getCommands } from '@utils/commands';
8
+ import { getEvents } from '@utils/collections/events';
9
+ import { getCommands } from '@utils/collections/commands';
10
10
  import { getServices } from '@utils/collections/services';
11
- import { getQueries } from '@utils/queries';
11
+ import { getQueries } from '@utils/collections/queries';
12
12
 
13
13
  const isEnabled = config.chat?.enabled || false;
14
14
  const chatConfig = config.chat || {};
@@ -3,8 +3,8 @@ import { Table, type TData, type TCollectionTypes } from '@components/Tables/Tab
3
3
  import { buildUrl } from '@utils/url-builder';
4
4
  import VerticalSideBarLayout from './VerticalSideBarLayout.astro';
5
5
  import { User, Users } from 'lucide-react';
6
- import { getUsers } from '@utils/users';
7
- import { getTeams } from '@utils/teams';
6
+ import { getUsers } from '@utils/collections/users';
7
+ import { getTeams } from '@utils/collections/teams';
8
8
  import config from '@config';
9
9
 
10
10
  const users = await getUsers();
@@ -2,13 +2,13 @@
2
2
  import { Table, type TData, type TCollectionTypes } from '@components/Tables/Table';
3
3
  import { QueueListIcon, RectangleGroupIcon, BoltIcon, ChatBubbleLeftIcon } from '@heroicons/react/24/outline';
4
4
  import ServerIcon from '@heroicons/react/24/outline/ServerIcon';
5
- import { getCommands } from '@utils/commands';
5
+ import { getCommands } from '@utils/collections/commands';
6
6
  import { getDomains } from '@utils/collections/domains';
7
7
  import { getFlows } from '@utils/collections/flows';
8
- import { getEvents } from '@utils/events';
8
+ import { getEvents } from '@utils/collections/events';
9
9
  import { getServices } from '@utils/collections/services';
10
10
  import { buildUrl } from '@utils/url-builder';
11
- import { getQueries } from '@utils/queries';
11
+ import { getQueries } from '@utils/collections/queries';
12
12
  import { getContainers } from '@utils/collections/containers';
13
13
  import { DatabaseIcon } from 'lucide-react';
14
14
  import { MagnifyingGlassIcon } from '@heroicons/react/20/solid';