@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
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  import Seo from '@components/Seo.astro';
3
3
  import { buildUrl } from '@utils/url-builder';
4
- import { getEvents } from '@utils/events';
5
- import { getEntities } from '@utils/entities';
6
- import { getCommands } from '@utils/commands';
4
+ import { getEvents } from '@utils/collections/events';
5
+ import { getEntities } from '@utils/collections/entities';
6
+ import { getCommands } from '@utils/collections/commands';
7
7
  import { getServices } from '@utils/collections/services';
8
8
  import { getDomains } from '@utils/collections/domains';
9
9
  import type { CollectionEntry } from 'astro:content';
10
10
  import type { CollectionTypes } from '@types';
11
- import { getChannels } from '@utils/channels';
11
+ import { getChannels } from '@utils/collections/channels';
12
12
 
13
13
  export async function getStaticPaths() {
14
14
  const [events, commands, services, domains, channels, entities] = await Promise.all([
@@ -18,10 +18,7 @@ export class Page extends HybridPage {
18
18
  type: item.collection,
19
19
  id: item.data.id,
20
20
  },
21
- props: {
22
- type: item.collection,
23
- ...item,
24
- },
21
+ props: {},
25
22
  }));
26
23
  }
27
24
 
@@ -25,36 +25,12 @@ const { subdomains, duplicateTerms } = ubiquitousLanguageData;
25
25
  <main class="flex sm:px-6 docs-layout h-full" data-pagefind-body data-pagefind-meta={`title:${pageTitle}`}>
26
26
  <div class="flex docs-layout w-full">
27
27
  <div class="w-full lg:mr-2 pr-8 overflow-y-auto pt-6 pb-8 min-h-[50em]">
28
- {/* Breadcrumb */}
29
- <nav class="mb-4 flex items-center space-x-2 text-sm text-gray-500" aria-label="Breadcrumb">
30
- <a
31
- href={buildUrl(`/docs/${props.type}/${props.data.id}/${props.data.latestVersion}`)}
32
- class="hover:text-gray-700 hover:underline flex items-center gap-2"
33
- >
34
- <RectangleGroupIcon className="h-4 w-4" />
35
- {props.data.name}
36
- </a>
37
- <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
38
- <path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"></path>
39
- </svg>
40
- <span class="text-gray-900 flex items-center gap-2">
41
- {
42
- (() => {
43
- const BookOpen = LucideIcons.BookOpen;
44
- //@ts-ignore
45
- return <BookOpen className="h-4 w-4" />;
46
- })()
47
- }
48
- Ubiquitous Language Explorer
49
- </span>
50
- </nav>
51
-
52
28
  {/* Title Section */}
53
29
  <div class="relative border-b border-gray-200 mb-4 pb-4">
54
30
  <div class="xl:flex xl:items-start xl:justify-between">
55
31
  <div class="min-w-0 flex-1">
56
32
  <div class="flex items-center gap-2">
57
- <h1 class="text-xl font-bold leading-7 text-gray-900 sm:text-2xl xl:text-3xl">Ubiquitous Language Explorer</h1>
33
+ <h1 class="text-xl font-bold leading-7 text-gray-900 sm:text-2xl xl:text-3xl">Ubiquitous Language</h1>
58
34
  </div>
59
35
  <p class="mt-2 text-sm text-gray-500">
60
36
  Browse and discover ubiquitous language terms in the {props.data.name} domain{
@@ -145,7 +121,7 @@ const { subdomains, duplicateTerms } = ubiquitousLanguageData;
145
121
  {term.description && (
146
122
  <div class="prose prose-sm prose-p:my-3">
147
123
  <a
148
- href={buildUrl(`/docs/${props.type}/${props.data.id}/language/${term.id}`)}
124
+ href={buildUrl(`/docs/${props.collection}/${props.data.id}/language/${term.id}`)}
149
125
  class="show-more-text text-sm text-primary font-medium hover:underline"
150
126
  >
151
127
  Read more
@@ -213,7 +189,7 @@ const { subdomains, duplicateTerms } = ubiquitousLanguageData;
213
189
  {term.description && (
214
190
  <div class="prose prose-sm prose-p:my-3">
215
191
  <a
216
- href={buildUrl(`/docs/${props.type}/${subdomain.data.id}/language/${term.id}`)}
192
+ href={buildUrl(`/docs/${props.collection}/${subdomain.data.id}/language/${term.id}`)}
217
193
  class="show-more-text text-sm text-primary font-medium hover:underline"
218
194
  >
219
195
  Read more
@@ -12,7 +12,7 @@ export class Page extends HybridPage {
12
12
  return [];
13
13
  }
14
14
 
15
- const { getTeams } = await import('@utils/teams');
15
+ const { getTeams } = await import('@utils/collections/teams');
16
16
  const teams = await getTeams();
17
17
 
18
18
  return teams.map((team) => ({
@@ -28,7 +28,7 @@ export class Page extends HybridPage {
28
28
  return null;
29
29
  }
30
30
 
31
- const { getTeams } = await import('@utils/teams');
31
+ const { getTeams } = await import('@utils/collections/teams');
32
32
  const teams = await getTeams();
33
33
 
34
34
  // Find the specific team by id
@@ -12,7 +12,7 @@ export class Page extends HybridPage {
12
12
  return [];
13
13
  }
14
14
 
15
- const { getUsers } = await import('@utils/users');
15
+ const { getUsers } = await import('@utils/collections/users');
16
16
  const users = await getUsers();
17
17
 
18
18
  return users.map((user) => ({
@@ -28,7 +28,7 @@ export class Page extends HybridPage {
28
28
  return null;
29
29
  }
30
30
 
31
- const { getUsers } = await import('@utils/users');
31
+ const { getUsers } = await import('@utils/collections/users');
32
32
  const users = await getUsers();
33
33
 
34
34
  // Find the specific team by id
@@ -7,8 +7,9 @@ import NodeGraph from '@components/MDX/NodeGraph/NodeGraph.astro';
7
7
  import { getMDXComponentsByName } from '@utils/markdown';
8
8
  import { resourceToCollectionMap } from '@utils/collections/util';
9
9
  import { buildUrl } from '@utils/url-builder';
10
- import { isCustomLandingPageEnabled } from '@utils/feature';
10
+ import { isCustomLandingPageEnabled, isVisualiserEnabled } from '@utils/feature';
11
11
  import DefaultAstroLandingPage from './_index.astro';
12
+ import config from '@config';
12
13
 
13
14
  let nodeGraphs: any[] = [];
14
15
  let CustomContent = null;
@@ -28,6 +29,10 @@ if (existsSync(pathToUserDefinedLandingPage) && isCustomLandingPageEnabled()) {
28
29
  const rawContent = readFileSync(pathToUserDefinedLandingPage, 'utf-8');
29
30
  nodeGraphs = getMDXComponentsByName(rawContent, 'NodeGraph') || [];
30
31
  }
32
+
33
+ if (config.landingPage) {
34
+ return Astro.redirect(buildUrl(config.landingPage));
35
+ }
31
36
  ---
32
37
 
33
38
  {
@@ -53,10 +58,14 @@ if (existsSync(pathToUserDefinedLandingPage) && isCustomLandingPageEnabled()) {
53
58
  title={nodeGraph.title}
54
59
  mode="simple"
55
60
  linksToVisualiser={true}
56
- href={{
57
- label: 'Open in Visualiser',
58
- url: buildUrl(`/visualiser/${collection}/${nodeGraph.id}/${nodeGraph.version}`),
59
- }}
61
+ href={
62
+ isVisualiserEnabled()
63
+ ? {
64
+ label: 'Open in Visualiser',
65
+ url: buildUrl(`/visualiser/${collection}/${nodeGraph.id}/${nodeGraph.version}`),
66
+ }
67
+ : undefined
68
+ }
60
69
  />
61
70
  );
62
71
  })}
@@ -0,0 +1,30 @@
1
+ // src/pages/nav-index.json.ts
2
+ import { getCollection } from 'astro:content';
3
+
4
+ export const prerender = true;
5
+
6
+ export async function GET() {
7
+ // const services = await getCollection('services');
8
+ // const domains = await getCollection('domains');
9
+ // // ...other collections
10
+
11
+ // const index = buildNavIndex({ services, domains }); // your map logic
12
+
13
+ const index = [
14
+ {
15
+ type: 'group',
16
+ title: 'Domains',
17
+ pages: [
18
+ {
19
+ type: 'item',
20
+ title: 'Inventory Domain',
21
+ icon: 'ServerIcon',
22
+ },
23
+ ],
24
+ },
25
+ ];
26
+
27
+ return new Response(JSON.stringify(index), {
28
+ headers: { 'Content-Type': 'application/json' },
29
+ });
30
+ }
@@ -0,0 +1,77 @@
1
+ import { isSSR } from '@utils/feature';
2
+ import { HybridPage } from '@utils/page-loaders/hybrid-page';
3
+ import type { PageTypes } from '@types';
4
+ import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
5
+
6
+ /**
7
+ * Documentation page class for all collection types with versioning
8
+ */
9
+ export class Page extends HybridPage {
10
+ static async getStaticPaths() {
11
+ if (isSSR()) {
12
+ return [];
13
+ }
14
+
15
+ const itemTypes: PageTypes[] = [
16
+ 'events',
17
+ 'commands',
18
+ 'queries',
19
+ // 'services',
20
+ // 'domains',
21
+ // 'flows',
22
+ // 'channels',
23
+ // 'entities',
24
+ // 'containers',
25
+ ];
26
+ const allItems = await Promise.all(itemTypes.map((type) => pageDataLoader[type]()));
27
+
28
+ // We only care about any item that has data.schemaPath
29
+ const itemsWithSchema = allItems.flatMap((items) => items.filter((item) => item.data.schemaPath));
30
+
31
+ // return allItems.flatMap((items, index) =>
32
+ return itemsWithSchema.map((item, index) => ({
33
+ params: {
34
+ type: item.collection,
35
+ id: item.data.id,
36
+ version: item.data.version,
37
+ },
38
+ props: {
39
+ type: item.collection,
40
+ ...item,
41
+ // Not everything needs the body of the page itself.
42
+ body: undefined,
43
+ },
44
+ }));
45
+ // );
46
+ }
47
+
48
+ protected static async fetchData(params: any) {
49
+ const { type, id, version } = params;
50
+
51
+ if (!type || !id || !version) {
52
+ return null;
53
+ }
54
+
55
+ // Get all items of the specified type
56
+ const items = await pageDataLoader[type as PageTypes]();
57
+
58
+ // Find the specific item by id and version
59
+ const item = items.find((i) => i.data.id === id && i.data.version === version);
60
+
61
+ if (!item) {
62
+ return null;
63
+ }
64
+
65
+ return {
66
+ type,
67
+ ...item,
68
+ };
69
+ }
70
+
71
+ protected static createNotFoundResponse(): Response {
72
+ return new Response(null, {
73
+ status: 404,
74
+ statusText: 'Documentation not found',
75
+ });
76
+ }
77
+ }
@@ -0,0 +1,90 @@
1
+ ---
2
+ import type { PageTypes } from '@types';
3
+ import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
4
+ import { Page } from './_index.data';
5
+ import SchemaPageViewer from '@components/SchemaExplorer/SchemaPageViewer';
6
+ import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
7
+ import { sortVersioned } from '@utils/collections/util';
8
+ import { isEventCatalogScaleEnabled } from '@utils/feature';
9
+ import fs from 'fs';
10
+ import path from 'path';
11
+ import type { SchemaItem } from '@components/SchemaExplorer/types';
12
+
13
+ export const prerender = Page.prerender;
14
+ export const getStaticPaths = Page.getStaticPaths;
15
+
16
+ // Get data
17
+ const props = await Page.getData(Astro);
18
+ const { type, data } = props as { type: PageTypes; data: any };
19
+ const pageTitle = `${type} | ${data.name}`.replace(/^\w/, (c) => c.toUpperCase());
20
+
21
+ const allItems = await pageDataLoader[type]();
22
+ const versions = allItems.filter((item) => item.data.id === data.id);
23
+
24
+ // Transform to SchemaItems
25
+ const availableVersions = await Promise.all(
26
+ versions
27
+ .filter((message) => message.data.schemaPath)
28
+ .filter((message) => fs.existsSync(path.join(path.dirname(message.filePath ?? ''), message.data.schemaPath ?? '')))
29
+ .map(async (message) => {
30
+ try {
31
+ const schemaPath = message.data.schemaPath;
32
+ const fullSchemaPath = path.join(path.dirname(message.filePath ?? ''), schemaPath ?? '');
33
+
34
+ let schemaContent = '';
35
+ if (fs.existsSync(fullSchemaPath)) {
36
+ schemaContent = fs.readFileSync(fullSchemaPath, 'utf-8');
37
+ }
38
+
39
+ const schemaExtension = path.extname(schemaPath ?? '').slice(1);
40
+
41
+ return {
42
+ collection: message.collection,
43
+ data: {
44
+ id: message.data.id,
45
+ name: message.data.name,
46
+ version: message.data.version,
47
+ summary: message.data.summary,
48
+ schemaPath: message.data.schemaPath,
49
+ // @ts-ignore
50
+ producers: message.data.producers || [],
51
+ // @ts-ignore
52
+ consumers: message.data.consumers || [],
53
+ },
54
+ schemaContent,
55
+ schemaExtension,
56
+ } as SchemaItem;
57
+ } catch (error) {
58
+ console.error(`Error reading schema for ${message.data.id}:`, error);
59
+ return null;
60
+ }
61
+ })
62
+ );
63
+
64
+ const validVersions = availableVersions.filter((v): v is SchemaItem => v !== null);
65
+
66
+ // Sort versions descending (newest first)
67
+ const sortedVersions = sortVersioned(validVersions, (item) => item.data.version);
68
+
69
+ const currentMessage = sortedVersions.find((v) => v.data.version === data.version);
70
+ const apiAccessEnabled = isEventCatalogScaleEnabled();
71
+ ---
72
+
73
+ <VerticalSideBarLayout title={pageTitle}>
74
+ <div class="h-[calc(100vh-4rem)] w-full overflow-hidden flex flex-col">
75
+ {
76
+ currentMessage ? (
77
+ <SchemaPageViewer
78
+ client:load
79
+ message={currentMessage}
80
+ availableVersions={sortedVersions}
81
+ apiAccessEnabled={apiAccessEnabled}
82
+ showOwners={false}
83
+ showProducersConsumers={false}
84
+ />
85
+ ) : (
86
+ <div class="p-8 flex items-center justify-center h-full text-gray-500">Schema not found or could not be loaded.</div>
87
+ )
88
+ }
89
+ </div>
90
+ </VerticalSideBarLayout>
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
3
- import { getEvents } from '@utils/events';
4
- import { getCommands } from '@utils/commands';
5
- import { getQueries } from '@utils/queries';
3
+ import { getEvents } from '@utils/collections/events';
4
+ import { getCommands } from '@utils/collections/commands';
5
+ import { getQueries } from '@utils/collections/queries';
6
6
  import { getServices, getSpecificationsForService } from '@utils/collections/services';
7
7
  import SchemaExplorer from '@components/SchemaExplorer/SchemaExplorer';
8
8
  import { isEventCatalogScaleEnabled } from '@utils/feature';
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
3
- import { getEvents } from '@utils/events';
4
- import { getCommands } from '@utils/commands';
3
+ import { getEvents } from '@utils/collections/events';
4
+ import { getCommands } from '@utils/collections/commands';
5
5
  import { getServices } from '@utils/collections/services';
6
6
  import { BoltIcon, ServerIcon, RectangleGroupIcon } from '@heroicons/react/24/outline';
7
7
  import { SquareDashedMousePointerIcon, ArrowLeftRightIcon } from 'lucide-react';
8
8
  import StudioPageModal from '@components/Studio/StudioPageModal';
9
- import { getChannels } from '@utils/channels';
9
+ import { getChannels } from '@utils/collections/channels';
10
10
 
11
11
  const [events, commands, services, channels] = await Promise.all([
12
12
  getEvents().catch(() => []),
@@ -3,12 +3,13 @@ import { HybridPage } from '@utils/page-loaders/hybrid-page';
3
3
  import { isAuthEnabled } from '@utils/feature';
4
4
  import type { PageTypes } from '@types';
5
5
  import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
6
+ import { isVisualiserEnabled } from '@utils/feature';
6
7
 
7
8
  type PageTypesWithFlows = PageTypes | 'flows';
8
9
 
9
10
  export class Page extends HybridPage {
10
11
  static async getStaticPaths(): Promise<Array<{ params: any; props: any }>> {
11
- if (isAuthEnabled()) {
12
+ if (isAuthEnabled() || !isVisualiserEnabled()) {
12
13
  return [];
13
14
  }
14
15
 
@@ -42,7 +43,7 @@ export class Page extends HybridPage {
42
43
  protected static async fetchData(params: any) {
43
44
  const { type, id, version } = params;
44
45
 
45
- if (!type || !id || !version) {
46
+ if (!type || !id || !version || !isVisualiserEnabled()) {
46
47
  return null;
47
48
  }
48
49
 
@@ -77,7 +78,7 @@ export class Page extends HybridPage {
77
78
  }
78
79
 
79
80
  static get clientAuthScript(): string {
80
- if (!isAuthEnabled()) {
81
+ if (!isAuthEnabled() || !isVisualiserEnabled()) {
81
82
  return '';
82
83
  }
83
84
 
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  import Seo from '@components/Seo.astro';
3
3
  import { buildUrl } from '@utils/url-builder';
4
- import { getEvents } from '@utils/events';
5
- import { getCommands } from '@utils/commands';
4
+ import { getEvents } from '@utils/collections/events';
5
+ import { getCommands } from '@utils/collections/commands';
6
6
  import { getServices } from '@utils/collections/services';
7
7
  import { getDomains } from '@utils/collections/domains';
8
8
  import { getContainers } from '@utils/collections/containers';
@@ -1,10 +1,11 @@
1
1
  import { HybridPage } from '@utils/page-loaders/hybrid-page';
2
2
  import { isAuthEnabled } from '@utils/feature';
3
3
  import { domainHasEntities, getDomains, type Domain } from '@utils/collections/domains';
4
+ import { isVisualiserEnabled } from '@utils/feature';
4
5
 
5
6
  export class Page extends HybridPage {
6
7
  static async getStaticPaths(): Promise<Array<{ params: any; props: any }>> {
7
- if (isAuthEnabled()) {
8
+ if (isAuthEnabled() || !isVisualiserEnabled()) {
8
9
  return [];
9
10
  }
10
11
 
@@ -29,7 +30,7 @@ export class Page extends HybridPage {
29
30
  protected static async fetchData(params: any) {
30
31
  const { id, version } = params;
31
32
 
32
- if (!id || !version) {
33
+ if (!id || !version || !isVisualiserEnabled()) {
33
34
  return null;
34
35
  }
35
36
 
@@ -54,7 +55,7 @@ export class Page extends HybridPage {
54
55
  }
55
56
 
56
57
  static get clientAuthScript(): string {
57
- if (!isAuthEnabled()) {
58
+ if (!isAuthEnabled() || !isVisualiserEnabled()) {
58
59
  return '';
59
60
  }
60
61
 
@@ -0,0 +1,83 @@
1
+ import { atom } from 'nanostores';
2
+
3
+ const FAVORITES_KEY = 'eventcatalog-sidebar-favorites';
4
+
5
+ export type FavoriteItem = {
6
+ nodeKey: string; // The key of the favorited node
7
+ path: string[]; // Path of keys to reach this node
8
+ title: string; // Display title
9
+ badge?: string; // Type badge (Domain, Service, etc.)
10
+ href?: string; // Direct link if it's a leaf item
11
+ };
12
+
13
+ export const favoritesStore = atom<FavoriteItem[]>([]);
14
+
15
+ // Initialize store from localStorage on client side
16
+ const initStore = () => {
17
+ if (typeof window !== 'undefined') {
18
+ try {
19
+ const stored = localStorage.getItem(FAVORITES_KEY);
20
+ if (stored) {
21
+ const parsed = JSON.parse(stored);
22
+ if (JSON.stringify(favoritesStore.get()) !== stored) {
23
+ favoritesStore.set(parsed);
24
+ }
25
+ }
26
+ } catch (e) {
27
+ console.warn('Failed to load favorites:', e);
28
+ }
29
+ }
30
+ };
31
+
32
+ if (typeof window !== 'undefined') {
33
+ initStore();
34
+
35
+ // Listen for storage events (cross-tab sync)
36
+ window.addEventListener('storage', (e) => {
37
+ if (e.key === FAVORITES_KEY) {
38
+ initStore();
39
+ }
40
+ });
41
+
42
+ // Listen for custom events (same-tab sync between instances)
43
+ window.addEventListener('favorites-updated', () => {
44
+ initStore();
45
+ });
46
+ }
47
+
48
+ export const saveFavorites = (favorites: FavoriteItem[]) => {
49
+ favoritesStore.set(favorites);
50
+ if (typeof window !== 'undefined') {
51
+ try {
52
+ localStorage.setItem(FAVORITES_KEY, JSON.stringify(favorites));
53
+ // Dispatch event to notify other store instances/components
54
+ window.dispatchEvent(new CustomEvent('favorites-updated'));
55
+ } catch (e) {
56
+ console.warn('Failed to save favorites:', e);
57
+ }
58
+ }
59
+ };
60
+
61
+ export const addFavorite = (item: FavoriteItem) => {
62
+ const current = favoritesStore.get();
63
+ const exists = current.some((fav) => fav.nodeKey === item.nodeKey);
64
+ if (!exists) {
65
+ saveFavorites([...current, item]);
66
+ }
67
+ };
68
+
69
+ export const removeFavorite = (nodeKey: string) => {
70
+ const current = favoritesStore.get();
71
+ saveFavorites(current.filter((fav) => fav.nodeKey !== nodeKey));
72
+ };
73
+
74
+ export const toggleFavorite = (item: FavoriteItem) => {
75
+ const current = favoritesStore.get();
76
+ const exists = current.some((fav) => fav.nodeKey === item.nodeKey);
77
+
78
+ if (exists) {
79
+ removeFavorite(item.nodeKey);
80
+ } else {
81
+ addFavorite(item);
82
+ }
83
+ };
@@ -0,0 +1,8 @@
1
+ import { atom } from 'nanostores';
2
+ import type { NavigationData } from '../components/SideNav/NestedSideBar/sidebar-builder';
3
+
4
+ export const sidebarStore = atom<NavigationData | null>(null);
5
+
6
+ export const setSidebarData = (data: NavigationData) => {
7
+ sidebarStore.set(data);
8
+ };
@@ -7,12 +7,15 @@ export type ChangeLog = CollectionEntry<'changelogs'>;
7
7
  export const getChangeLogs = async (item: CollectionEntry<CollectionTypes>): Promise<ChangeLog[]> => {
8
8
  const { collection, data, filePath } = item;
9
9
 
10
+ const collectionDirectory = path.dirname(item?.filePath || '');
11
+ // Ensure the path follows <collectionDirectory>/versioned/<version>/changelog.mdx
12
+ // Pre-compile regex
13
+ const versionedPathPattern = new RegExp(`${collectionDirectory}/versioned/[^/]+/changelog\\.mdx$`);
14
+ const rootChangeLogPath = path.join(collectionDirectory, 'changelog.mdx');
15
+
10
16
  // Get all logs for collection type and filter by given collection
11
17
  const logs = await getCollection('changelogs', (log) => {
12
- const collectionDirectory = path.dirname(item?.filePath || '');
13
- const isRootChangeLog = path.join(collectionDirectory, 'changelog.mdx') === log.filePath;
14
- // Ensure the path follows <collectionDirectory>/versioned/<version>/changelog.mdx
15
- const versionedPathPattern = new RegExp(`${collectionDirectory}/versioned/[^/]+/changelog\\.mdx$`);
18
+ const isRootChangeLog = rootChangeLogPath === log.filePath;
16
19
  const isVersionedChangeLog = versionedPathPattern.test(log.filePath!);
17
20
  return log.id.includes(`${collection}/`) && (isRootChangeLog || isVersionedChangeLog);
18
21
  });