@eventcatalog/core 3.48.3 → 4.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 (109) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/catalog-to-astro-content-directory.cjs +1 -1
  6. package/dist/{chunk-4BRGEUVO.js → chunk-7PMNFOIL.js} +1 -1
  7. package/dist/chunk-BWN544LB.js +73 -0
  8. package/dist/{chunk-X7GMZVB3.js → chunk-D3MI3OFO.js} +1 -1
  9. package/dist/{chunk-EE5Q6MJZ.js → chunk-HN45LKSL.js} +1 -1
  10. package/dist/{chunk-PWBFBCJ4.js → chunk-JMADW4J7.js} +1 -1
  11. package/dist/{chunk-XEUW7PEQ.js → chunk-NAOHQDLC.js} +1 -1
  12. package/dist/constants.cjs +1 -1
  13. package/dist/constants.js +1 -1
  14. package/dist/core-node-modules.cjs +108 -0
  15. package/dist/core-node-modules.d.cts +7 -0
  16. package/dist/core-node-modules.d.ts +7 -0
  17. package/dist/core-node-modules.js +8 -0
  18. package/dist/docs/development/components/components/15-prompt.md +5 -1
  19. package/dist/eventcatalog.cjs +124 -48
  20. package/dist/eventcatalog.js +26 -15
  21. package/dist/generate.cjs +1 -1
  22. package/dist/generate.js +3 -3
  23. package/dist/utils/cli-logger.cjs +1 -1
  24. package/dist/utils/cli-logger.js +2 -2
  25. package/eventcatalog/astro.config.mjs +27 -23
  26. package/eventcatalog/public/icons/languages/java.svg +1 -0
  27. package/eventcatalog/public/icons/payments/stripe.svg +1 -0
  28. package/eventcatalog/src/components/Badge.astro +10 -10
  29. package/eventcatalog/src/components/CopyAsMarkdown.tsx +154 -0
  30. package/eventcatalog/src/components/Grids/DomainGrid.tsx +207 -44
  31. package/eventcatalog/src/components/Grids/MessageGrid.tsx +0 -20
  32. package/eventcatalog/src/components/Grids/SystemGrid.tsx +185 -0
  33. package/eventcatalog/src/components/MDX/ADRTable/ADRTable.astro +99 -0
  34. package/eventcatalog/src/components/MDX/ADRTable/ADRTable.client.tsx +400 -0
  35. package/eventcatalog/src/components/MDX/ContextDiagram/ContextDiagramPortal.tsx +21 -0
  36. package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +1 -0
  37. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +42 -6
  38. package/eventcatalog/src/components/MDX/Prompt/Prompt.astro +62 -9
  39. package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +8 -1
  40. package/eventcatalog/src/components/MDX/SystemContextMap/SystemContextMapPortal.tsx +22 -0
  41. package/eventcatalog/src/components/MDX/components.tsx +7 -0
  42. package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +1 -1
  43. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +67 -37
  44. package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +47 -0
  45. package/eventcatalog/src/components/Tables/Discover/FilterComponents.tsx +10 -2
  46. package/eventcatalog/src/components/Tables/Discover/columns.tsx +115 -27
  47. package/eventcatalog/src/components/Tables/Discover/index.ts +7 -1
  48. package/eventcatalog/src/components/Tables/SystemResources/SystemResourcesTable.tsx +267 -0
  49. package/eventcatalog/src/content.config.ts +94 -8
  50. package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +4 -1
  51. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +12 -13
  52. package/eventcatalog/src/enterprise/custom-documentation/utils/custom-docs.ts +6 -0
  53. package/eventcatalog/src/enterprise/feature.ts +3 -1
  54. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +85 -129
  55. package/eventcatalog/src/layouts/VisualiserLayout.astro +66 -0
  56. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +4 -2
  57. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +2 -0
  58. package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +15 -15
  59. package/eventcatalog/src/pages/discover/[type]/_index.data.ts +1 -0
  60. package/eventcatalog/src/pages/discover/[type]/index.astro +47 -2
  61. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +15 -14
  62. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +13 -14
  63. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -0
  64. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +11 -1
  65. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +81 -26
  66. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.ts +89 -0
  67. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/index.astro +85 -0
  68. package/eventcatalog/src/pages/docs/[type]/[id]/[version].md.ts +2 -0
  69. package/eventcatalog/src/pages/docs/[type]/[id]/[version].mdx.ts +2 -0
  70. package/eventcatalog/src/pages/docs/[type]/[id]/_index.data.ts +1 -0
  71. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +24 -1
  72. package/eventcatalog/src/pages/docs/users/[id]/index.astro +24 -1
  73. package/eventcatalog/src/pages/index.astro +30 -7
  74. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +1 -0
  75. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +1 -1
  76. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version].mermaid.ts +3 -0
  77. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/_index.data.ts +94 -0
  78. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/index.astro +51 -0
  79. package/eventcatalog/src/pages/visualiser/system-context-map/index.astro +41 -0
  80. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/_index.data.ts +91 -0
  81. package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/index.astro +51 -0
  82. package/eventcatalog/src/stores/sidebar-store/builders/adr.ts +3 -1
  83. package/eventcatalog/src/stores/sidebar-store/builders/agent.ts +3 -1
  84. package/eventcatalog/src/stores/sidebar-store/builders/container.ts +1 -1
  85. package/eventcatalog/src/stores/sidebar-store/builders/data-product.ts +1 -1
  86. package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +127 -49
  87. package/eventcatalog/src/stores/sidebar-store/builders/message.ts +1 -1
  88. package/eventcatalog/src/stores/sidebar-store/builders/service.ts +4 -2
  89. package/eventcatalog/src/stores/sidebar-store/builders/shared.ts +2 -1
  90. package/eventcatalog/src/stores/sidebar-store/builders/system.ts +166 -0
  91. package/eventcatalog/src/stores/sidebar-store/state.ts +99 -6
  92. package/eventcatalog/src/types/index.ts +2 -0
  93. package/eventcatalog/src/utils/collection-colors.ts +6 -1
  94. package/eventcatalog/src/utils/collections/domains.ts +35 -0
  95. package/eventcatalog/src/utils/collections/icons.ts +4 -5
  96. package/eventcatalog/src/utils/collections/systems.ts +110 -0
  97. package/eventcatalog/src/utils/collections/teams.ts +15 -10
  98. package/eventcatalog/src/utils/collections/users.ts +7 -4
  99. package/eventcatalog/src/utils/collections/util.ts +2 -0
  100. package/eventcatalog/src/utils/icon-map.ts +20 -0
  101. package/eventcatalog/src/utils/icon.ts +11 -0
  102. package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +12 -2
  103. package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +0 -170
  104. package/eventcatalog/src/utils/node-graphs/system-context-node-graph.ts +400 -0
  105. package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +208 -0
  106. package/eventcatalog/src/utils/node-graphs/utils/utils.ts +12 -0
  107. package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
  108. package/package.json +17 -14
  109. package/eventcatalog/src/pages/visualiser/context-map/index.astro +0 -30
@@ -490,6 +490,10 @@ const services = defineCollection({
490
490
  'domains/*/subdomains/*/services/*/index.(md|mdx)',
491
491
  'domains/*/subdomains/*/services/*/versioned/*/index.(md|mdx)',
492
492
 
493
+ // Capture services inside systems
494
+ 'domains/*/systems/*/services/*/index.(md|mdx)',
495
+ 'domains/*/systems/*/services/*/versioned/*/index.(md|mdx)',
496
+
493
497
  // Capture services in the root
494
498
  'services/*/index.(md|mdx)', // ✅ Capture only services markdown files
495
499
  'services/*/versioned/*/index.(md|mdx)', // ✅ Capture versioned files inside services
@@ -591,6 +595,7 @@ const adrResourcePointer = adrPointer.extend({
591
595
  'flow',
592
596
  'channel',
593
597
  'domain',
598
+ 'system',
594
599
  'user',
595
600
  'team',
596
601
  'container',
@@ -703,10 +708,10 @@ const resourceDocs = defineCollection({
703
708
  // Resource-level docs are restricted to known resource paths.
704
709
  // This avoids scanning external docs such as node_modules/**/docs.
705
710
  pattern: withIgnoredBuildArtifacts([
706
- '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products}/**/docs/**/*.@(md|mdx)',
707
- '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products}/**/docs/*.@(md|mdx)',
708
- '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products}/**/versioned/*/docs/**/*.@(md|mdx)',
709
- '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products}/**/versioned/*/docs/*.@(md|mdx)',
711
+ '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products,systems}/**/docs/**/*.@(md|mdx)',
712
+ '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products,systems}/**/docs/*.@(md|mdx)',
713
+ '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products,systems}/**/versioned/*/docs/**/*.@(md|mdx)',
714
+ '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products,systems}/**/versioned/*/docs/*.@(md|mdx)',
710
715
  'domains/**/docs/**/*.@(md|mdx)',
711
716
  'domains/**/docs/*.@(md|mdx)',
712
717
  ]),
@@ -718,10 +723,10 @@ const resourceDocs = defineCollection({
718
723
  const resourceDocCategories = defineCollection({
719
724
  loader: glob({
720
725
  pattern: withIgnoredBuildArtifacts([
721
- '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products}/**/docs/**/category.json',
722
- '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products}/**/docs/**/_category_.json',
723
- '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products}/**/versioned/*/docs/**/category.json',
724
- '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products}/**/versioned/*/docs/**/_category_.json',
726
+ '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products,systems}/**/docs/**/category.json',
727
+ '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products,systems}/**/docs/**/_category_.json',
728
+ '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products,systems}/**/versioned/*/docs/**/category.json',
729
+ '{agents,events,commands,queries,services,flows,containers,channels,entities,data-products,systems}/**/versioned/*/docs/**/_category_.json',
725
730
  'domains/**/docs/**/category.json',
726
731
  'domains/**/docs/**/_category_.json',
727
732
  'domains/**/docs/category.json',
@@ -753,6 +758,7 @@ const domains = defineCollection({
753
758
  services: z.array(pointer).optional(),
754
759
  agents: z.array(pointer).optional(),
755
760
  domains: z.array(pointer).optional(),
761
+ systems: z.array(pointer).optional(),
756
762
  entities: z.array(pointer).optional(),
757
763
  'data-products': z.array(pointer).optional(),
758
764
  flows: z.array(pointer).optional(),
@@ -762,6 +768,7 @@ const domains = defineCollection({
762
768
  .object({
763
769
  parentDomains: detailPanelPropertySchema.optional(),
764
770
  subdomains: detailPanelPropertySchema.optional(),
771
+ systems: detailPanelPropertySchema.optional(),
765
772
  services: detailPanelPropertySchema.optional(),
766
773
  entities: detailPanelPropertySchema.optional(),
767
774
  messages: detailPanelPropertySchema.optional(),
@@ -777,6 +784,84 @@ const domains = defineCollection({
777
784
  .extend(baseSchema.shape),
778
785
  });
779
786
 
787
+ // A relationship from one system to another, used by the System Diagram.
788
+ // Source-declared and one-directional. The `label` describes the edge; a relationship
789
+ // without a label is treated as having no edge (it is skipped when drawing the diagram).
790
+ const systemRelationshipPointer = z.object({
791
+ id: z.string(),
792
+ version: z.string().optional().default('latest'),
793
+ label: z.string().optional(),
794
+ });
795
+
796
+ // An actor (a person/role) that interacts with a system on the Context Diagram.
797
+ // Actors are inline (not a collection) — `id` is the actor's node id, used to
798
+ // de-duplicate the same actor referenced from multiple systems.
799
+ // `direction` controls the edge arrow: `inbound` = actor -> system (e.g. "logs into"),
800
+ // `outbound` = system -> actor (e.g. "sends email to"). Defaults to inbound.
801
+ const systemActorRelationship = z.object({
802
+ id: z.string(),
803
+ name: z.string().optional(),
804
+ label: z.string().optional(),
805
+ direction: z.enum(['inbound', 'outbound']).optional().default('inbound'),
806
+ });
807
+
808
+ const systems = defineCollection({
809
+ loader: glob({
810
+ pattern: withIgnoredBuildArtifacts([
811
+ '**/systems/**/index.(md|mdx)',
812
+ '**/systems/**/versioned/*/index.(md|mdx)',
813
+ // Systems can contain nested resource folders (containers, diagrams, services, etc.).
814
+ // Those nested resources are loaded by their own collections — exclude their index files
815
+ // here so they are not mistaken for systems. Nested `systems/` folders are still allowed.
816
+ '!**/systems/**/agents/**',
817
+ '!**/systems/**/services/**',
818
+ '!**/systems/**/events/**',
819
+ '!**/systems/**/commands/**',
820
+ '!**/systems/**/queries/**',
821
+ '!**/systems/**/flows/**',
822
+ '!**/systems/**/channels/**',
823
+ '!**/systems/**/entities/**',
824
+ '!**/systems/**/containers/**',
825
+ '!**/systems/**/diagrams/**',
826
+ '!**/systems/**/data-products/**',
827
+ '!**/systems/**/adrs/**',
828
+ '!**/systems/**/docs/**',
829
+ ]),
830
+ base: projectDirBase,
831
+ generateId: ({ data }) => {
832
+ return `${data.id}-${data.version}`;
833
+ },
834
+ }),
835
+ schema: z
836
+ .object({
837
+ // Whether the system belongs to your organisation (`internal`) or is a
838
+ // third-party/SaaS system you integrate with (`external`, e.g. "Resend",
839
+ // "Stripe"). External systems are shaded in the node-graph. Defaults to internal.
840
+ scope: z.enum(['internal', 'external']).optional().default('internal'),
841
+ services: z.array(pointer).optional(),
842
+ flows: z.array(pointer).optional(),
843
+ entities: z.array(pointer).optional(),
844
+ containers: z.array(pointer).optional(),
845
+ relationships: z.array(systemRelationshipPointer).optional(),
846
+ actors: z.array(systemActorRelationship).optional(),
847
+ detailsPanel: z
848
+ .object({
849
+ versions: detailPanelPropertySchema.optional(),
850
+ repository: detailPanelPropertySchema.optional(),
851
+ owners: detailPanelPropertySchema.optional(),
852
+ changelog: detailPanelPropertySchema.optional(),
853
+ attachments: detailPanelPropertySchema.optional(),
854
+ services: detailPanelPropertySchema.optional(),
855
+ flows: detailPanelPropertySchema.optional(),
856
+ entities: detailPanelPropertySchema.optional(),
857
+ containers: detailPanelPropertySchema.optional(),
858
+ diagrams: detailPanelPropertySchema.optional(),
859
+ })
860
+ .optional(),
861
+ })
862
+ .extend(baseSchema.shape),
863
+ });
864
+
780
865
  const channels = defineCollection({
781
866
  loader: glob({
782
867
  pattern: withIgnoredBuildArtifacts(['**/channels/**/index.(md|mdx)', '**/channels/**/versioned/*/index.(md|mdx)']),
@@ -1064,6 +1149,7 @@ export const collections = {
1064
1149
  users,
1065
1150
  teams,
1066
1151
  domains,
1152
+ systems,
1067
1153
  flows,
1068
1154
  pages,
1069
1155
  changelogs,
@@ -15,6 +15,7 @@ const CACHE_ENABLED = process.env.DISABLE_EVENTCATALOG_CACHE !== 'true';
15
15
  export type ResourceCollection =
16
16
  | 'agents'
17
17
  | 'domains'
18
+ | 'systems'
18
19
  | 'services'
19
20
  | 'events'
20
21
  | 'commands'
@@ -283,10 +284,11 @@ const getResourceLookups = async (): Promise<Record<ResourceCollection, Resource
283
284
  }
284
285
 
285
286
  const lookupPromise = (async () => {
286
- const [agents, domains, services, events, commands, queries, flows, containers, channels, entities, dataProducts] =
287
+ const [agents, domains, systems, services, events, commands, queries, flows, containers, channels, entities, dataProducts] =
287
288
  await Promise.all([
288
289
  getCollection('agents'),
289
290
  getCollection('domains'),
291
+ getCollection('systems'),
290
292
  getCollection('services'),
291
293
  getCollection('events'),
292
294
  getCollection('commands'),
@@ -301,6 +303,7 @@ const getResourceLookups = async (): Promise<Record<ResourceCollection, Resource
301
303
  return {
302
304
  agents: buildLookup(agents),
303
305
  domains: buildLookup(domains),
306
+ systems: buildLookup(systems),
304
307
  services: buildLookup(services),
305
308
  events: buildLookup(events),
306
309
  commands: buildLookup(commands),
@@ -97,32 +97,31 @@ const editUrl =
97
97
  <span class="text-xs md:text-sm font-semibold text-[rgb(var(--ec-accent))] capitalize">{sectionLabel}</span>
98
98
  )
99
99
  }
100
- <div class="flex justify-between items-center gap-4">
100
+ <div class="flex items-center gap-4">
101
101
  <h2 id="doc-page-header" class="text-2xl md:text-4xl font-bold text-[rgb(var(--ec-page-text))]">
102
102
  {doc.title}
103
103
  </h2>
104
- <div class="hidden lg:block shrink-0">
105
- <CopyAsMarkdown
106
- client:only="react"
107
- schemas={[]}
108
- chatEnabled={isEventCatalogChatEnabled()}
109
- markdownDownloadEnabled={isMarkdownDownloadEnabled()}
110
- rssFeedEnabled={isRSSEnabled()}
111
- editUrl={editUrl}
112
- preferChatAsDefault={isEventCatalogChatEnabled()}
113
- />
114
- </div>
115
104
  </div>
116
105
  <p class="text-base text-[rgb(var(--ec-page-text-muted))] font-light">{doc.summary}</p>
117
106
  {
118
107
  badges && badges.length > 0 && (
119
- <div class="flex flex-wrap gap-3 py-2">
108
+ <div class="flex flex-wrap gap-1.5 py-1">
120
109
  {badges.map((badge: any) => {
121
110
  return <Badge badge={badge} />;
122
111
  })}
123
112
  </div>
124
113
  )
125
114
  }
115
+ <CopyAsMarkdown
116
+ client:only="react"
117
+ variant="toolbar"
118
+ schemas={[]}
119
+ chatEnabled={isEventCatalogChatEnabled()}
120
+ markdownDownloadEnabled={isMarkdownDownloadEnabled()}
121
+ rssFeedEnabled={isRSSEnabled()}
122
+ editUrl={editUrl}
123
+ preferChatAsDefault={isEventCatalogChatEnabled()}
124
+ />
126
125
  </div>
127
126
  </div>
128
127
  <div class="prose prose-md max-w-none py-4 w-full text-[15px]">
@@ -269,3 +269,9 @@ export const getNavigationItems = async (): Promise<SidebarItem[]> => {
269
269
  const configuredSidebar = config.customDocs?.sidebar || [];
270
270
  return processSidebarItems(configuredSidebar as SideBarConfigurationItem[]);
271
271
  };
272
+
273
+ export const getFirstNavigationPage = async (): Promise<AdjacentPage | null> => {
274
+ const navigationItems = await getNavigationItems();
275
+ const flatPages = flattenNavigationItems(navigationItems);
276
+ return flatPages[0] || null;
277
+ };
@@ -49,7 +49,9 @@ export const isEventCatalogChatEnabled = () => {
49
49
  };
50
50
 
51
51
  export const isEventCatalogUpgradeEnabled = () => !isEventCatalogStarterEnabled() && !isEventCatalogScaleEnabled();
52
- export const isCustomLandingPageEnabled = () => isEventCatalogStarterEnabled() || isEventCatalogScaleEnabled();
52
+
53
+ // Custom landing pages are always enabled now.
54
+ export const isCustomLandingPageEnabled = () => true;
53
55
 
54
56
  export const isAuthEnabled = () => {
55
57
  const isAuthEnabledInCatalog = config?.auth?.enabled ?? false;
@@ -5,33 +5,23 @@ interface Props {
5
5
  description?: string;
6
6
  showNestedSideBar?: boolean;
7
7
  showHeader?: boolean;
8
+ // When true, the main content uses a reduced horizontal padding instead of the
9
+ // default 5rem. Used by wide pages such as the custom landing page.
10
+ reducedContentPadding?: boolean;
8
11
  }
9
12
 
10
13
  import {
11
14
  TableProperties,
12
- BotMessageSquare,
13
- BookOpen,
14
- BookText,
15
+ House,
15
16
  FileText,
16
17
  SquareDashedMousePointerIcon,
17
18
  FileCode,
18
19
  Waypoints,
19
20
  PanelLeftClose,
20
- Database,
21
21
  UserRound,
22
22
  UsersRound,
23
23
  Settings,
24
24
  } from 'lucide-react';
25
- import {
26
- RectangleGroupIcon,
27
- GlobeAltIcon,
28
- CubeIcon,
29
- BoltIcon,
30
- ChatBubbleLeftIcon,
31
- MagnifyingGlassIcon,
32
- QueueListIcon,
33
- } from '@heroicons/react/24/outline';
34
- import ServerIcon from '@heroicons/react/24/outline/ServerIcon';
35
25
  import BaseLayout from './BaseLayout.astro';
36
26
  import Header from '../components/Header.astro';
37
27
  import SideNav from '../components/SideNav/SideNav.astro';
@@ -58,6 +48,7 @@ import { ClientRouter } from 'astro:transitions';
58
48
 
59
49
  import { getCommands } from '@utils/collections/commands';
60
50
  import { getDomains } from '@utils/collections/domains';
51
+ import { getSystems } from '@utils/collections/systems';
61
52
  import { getEvents } from '@utils/collections/events';
62
53
  import { getServices } from '@utils/collections/services';
63
54
  import { getAgents } from '@utils/collections/agents';
@@ -69,10 +60,12 @@ import { isCollectionVisibleInCatalog } from '@eventcatalog';
69
60
  import { buildUrl } from '@utils/url-builder';
70
61
  import { getQueries } from '@utils/collections/queries';
71
62
  import { filterSidebarItems } from '@utils/sidebar-visibility';
63
+ import { getFirstNavigationPage } from '@enterprise/custom-documentation/utils/custom-docs';
72
64
 
73
65
  import { isEmbedEnabled, isCustomStylesEnabled, isEventCatalogScaleEnabled, isCustomDocsEnabled, isSSR } from '@utils/feature';
74
66
 
75
67
  const customDocs = await getCollection('customPages');
68
+ const firstCustomDocsPage = isCustomDocsEnabled() && customDocs.length > 0 ? await getFirstNavigationPage() : null;
76
69
 
77
70
  let events: any[] = [];
78
71
  let commands: any[] = [];
@@ -81,11 +74,12 @@ let services: any[] = [];
81
74
  let agents: any[] = [];
82
75
  let adrs: any[] = [];
83
76
  let domains: any[] = [];
77
+ let systems: any[] = [];
84
78
  let flows: any[] = [];
85
79
  let containers: any[] = [];
86
80
  let dataProducts: any[] = [];
87
81
 
88
- [events, commands, queries, services, agents, adrs, domains, flows, containers, dataProducts] = await Promise.all([
82
+ [events, commands, queries, services, agents, adrs, domains, systems, flows, containers, dataProducts] = await Promise.all([
89
83
  getEvents({ getAllVersions: false, hydrateServices: false }),
90
84
  getCommands({ getAllVersions: false, hydrateServices: false }),
91
85
  getQueries({ getAllVersions: false, hydrateServices: false }),
@@ -93,6 +87,7 @@ let dataProducts: any[] = [];
93
87
  getAgents({ getAllVersions: false }),
94
88
  getAdrs({ getAllVersions: false }),
95
89
  getDomains({ getAllVersions: false }),
90
+ getSystems({ getAllVersions: false }),
96
91
  getFlows({ getAllVersions: false }),
97
92
  getContainers({ getAllVersions: false }),
98
93
  getDataProducts({ getAllVersions: false }),
@@ -109,7 +104,7 @@ const currentPath = Astro.url.pathname;
109
104
 
110
105
  const getDefaultUrl = (route: string, defaultValue: string) => {
111
106
  if (route === 'docs/custom') {
112
- return customDocs.length > 0 ? buildUrl(`/${route}/${customDocs[0].id.replace('docs', '')}`) : buildUrl(defaultValue);
107
+ return firstCustomDocsPage ? buildUrl(`/${route}/${firstCustomDocsPage.slug}`) : buildUrl(defaultValue);
113
108
  }
114
109
 
115
110
  const collections = [
@@ -143,8 +138,8 @@ const navigationItems = filterSidebarItems(
143
138
  [
144
139
  {
145
140
  id: '/',
146
- label: 'Catalog',
147
- icon: BookOpen,
141
+ label: 'Home',
142
+ icon: House,
148
143
  href: buildUrl(config.landingPage || '/'),
149
144
  current:
150
145
  currentPath === '/' ||
@@ -165,13 +160,6 @@ const navigationItems = filterSidebarItems(
165
160
  isPremium: true,
166
161
  visible: isCustomDocsEnabled() && customDocs.length > 0,
167
162
  },
168
- {
169
- id: '/schemas/explorer',
170
- label: 'Schemas',
171
- icon: FileCode,
172
- href: buildUrl('/schemas/explorer'),
173
- current: currentPath.includes('/schemas/explorer') && !currentPath.includes('/schemas/fields'),
174
- },
175
163
  ...(isSSR()
176
164
  ? [
177
165
  {
@@ -211,113 +199,58 @@ const premiumFeatures: Array<{
211
199
 
212
200
  const internalServices = services.filter((service) => !service.data.externalSystem);
213
201
  const externalSystems = services.filter((service) => service.data.externalSystem);
202
+ const discoverTargets = [
203
+ { id: '/discover/domains', aliases: ['/discover'], href: buildUrl('/discover/domains'), count: domains.length },
204
+ { id: '/discover/systems', aliases: ['/discover'], href: buildUrl('/discover/systems'), count: systems.length },
205
+ {
206
+ id: '/discover/services',
207
+ aliases: ['/discover'],
208
+ href: buildUrl('/discover/services'),
209
+ count: internalServices.length,
210
+ },
211
+ {
212
+ id: '/discover/external-systems',
213
+ aliases: ['/discover'],
214
+ href: buildUrl('/discover/external-systems'),
215
+ count: externalSystems.length,
216
+ },
217
+ { id: '/discover/agents', aliases: ['/discover'], href: buildUrl('/discover/agents'), count: agents.length },
218
+ { id: '/discover/adrs', aliases: ['/discover'], href: buildUrl('/discover/adrs'), count: adrs.length },
219
+ {
220
+ id: '/discover/data-products',
221
+ aliases: ['/discover'],
222
+ href: buildUrl('/discover/data-products'),
223
+ count: dataProducts.length,
224
+ },
225
+ { id: '/discover/containers', aliases: ['/discover'], href: buildUrl('/discover/containers'), count: containers.length },
226
+ { id: '/discover/events', aliases: ['/discover'], href: buildUrl('/discover/events'), count: events.length },
227
+ { id: '/discover/commands', aliases: ['/discover'], href: buildUrl('/discover/commands'), count: commands.length },
228
+ { id: '/discover/queries', aliases: ['/discover'], href: buildUrl('/discover/queries'), count: queries.length },
229
+ { id: '/discover/flows', aliases: ['/discover'], href: buildUrl('/discover/flows'), count: flows.length },
230
+ ];
231
+ const defaultDiscoverTarget = filterSidebarItems(discoverTargets, userSideBarConfiguration).find((target) => target.count > 0);
214
232
 
215
233
  const browseItems = filterSidebarItems(
216
234
  [
217
235
  {
218
- id: '/discover/agents',
219
- aliases: ['/discover'],
220
- label: 'Agents',
221
- icon: BotMessageSquare,
222
- href: buildUrl('/discover/agents'),
223
- current: currentPath === buildUrl('/discover/agents'),
224
- visible: agents.length > 0,
225
- },
226
- {
227
- id: '/discover/adrs',
228
- aliases: ['/discover'],
229
- label: 'Decision Records',
230
- icon: BookText,
231
- href: buildUrl('/discover/adrs'),
232
- current: currentPath === buildUrl('/discover/adrs'),
233
- visible: adrs.length > 0,
234
- },
235
- {
236
- id: '/discover/data-products',
237
- aliases: ['/discover'],
238
- label: 'Data Products',
239
- icon: CubeIcon,
240
- href: buildUrl('/discover/data-products'),
241
- current: currentPath === buildUrl('/discover/data-products'),
242
- visible: dataProducts.length > 0,
243
- },
244
- {
245
- id: '/discover/containers',
246
- aliases: ['/discover'],
247
- label: 'Data Stores',
248
- icon: Database,
249
- href: buildUrl('/discover/containers'),
250
- current: currentPath === buildUrl('/discover/containers'),
251
- visible: containers.length > 0,
252
- },
253
- {
254
- id: '/discover/domains',
255
- aliases: ['/discover'],
256
- label: 'Domains',
257
- icon: RectangleGroupIcon,
258
- href: buildUrl('/discover/domains'),
259
- current: currentPath === buildUrl('/discover/domains'),
260
- visible: domains.length > 0,
261
- },
262
- {
263
- id: '/discover/services',
264
- aliases: ['/discover'],
265
- label: 'Services',
266
- icon: ServerIcon,
267
- href: buildUrl('/discover/services'),
268
- current: currentPath === buildUrl('/discover/services'),
269
- visible: internalServices.length > 0,
270
- },
271
- {
272
- id: '/discover/external-systems',
236
+ id: '/discover',
273
237
  aliases: ['/discover'],
274
- label: 'External Systems',
275
- icon: GlobeAltIcon,
276
- href: buildUrl('/discover/external-systems'),
277
- current: currentPath === buildUrl('/discover/external-systems'),
278
- visible: externalSystems.length > 0,
238
+ label: 'Resources',
239
+ icon: TableProperties,
240
+ href: defaultDiscoverTarget?.href ?? buildUrl('/discover/domains'),
241
+ current: currentPath === buildUrl('/discover') || currentPath.startsWith(buildUrl('/discover/', true)),
242
+ visible: Boolean(defaultDiscoverTarget),
279
243
  },
280
244
  {
281
- id: '/discover/events',
282
- aliases: ['/discover'],
283
- label: 'Events',
284
- icon: BoltIcon,
285
- href: buildUrl('/discover/events'),
286
- current: currentPath === buildUrl('/discover/events'),
287
- visible: events.length > 0,
288
- },
289
- {
290
- id: '/discover/commands',
291
- aliases: ['/discover'],
292
- label: 'Commands',
293
- icon: ChatBubbleLeftIcon,
294
- href: buildUrl('/discover/commands'),
295
- current: currentPath === buildUrl('/discover/commands'),
296
- visible: commands.length > 0,
297
- },
298
- {
299
- id: '/discover/queries',
300
- aliases: ['/discover'],
301
- label: 'Queries',
302
- icon: MagnifyingGlassIcon,
303
- href: buildUrl('/discover/queries'),
304
- current: currentPath === buildUrl('/discover/queries'),
305
- visible: queries.length > 0,
306
- },
307
- {
308
- id: '/discover/flows',
309
- aliases: ['/discover'],
310
- label: 'Flows',
311
- icon: QueueListIcon,
312
- href: buildUrl('/discover/flows'),
313
- current: currentPath === buildUrl('/discover/flows'),
314
- visible: flows.length > 0,
245
+ id: '/schemas/explorer',
246
+ label: 'Schemas',
247
+ icon: FileCode,
248
+ href: buildUrl('/schemas/explorer'),
249
+ current: currentPath.includes('/schemas/explorer') && !currentPath.includes('/schemas/fields'),
315
250
  },
316
251
  ],
317
252
  userSideBarConfiguration
318
- )
319
- .filter((item) => item.visible !== false)
320
- .sort((a, b) => a.label.localeCompare(b.label));
253
+ ).filter((item) => item.visible !== false);
321
254
 
322
255
  const organizationItems = filterSidebarItems(
323
256
  [
@@ -356,7 +289,7 @@ const settingsItems = filterSidebarItems(
356
289
  );
357
290
 
358
291
  const currentNavigationItem = [...navigationItems, ...studioNavigationItem, ...premiumFeatures].find((item) => item.current);
359
- const { title, description, showNestedSideBar = true, showHeader = true } = Astro.props;
292
+ const { title, description, showNestedSideBar = true, showHeader = true, reducedContentPadding = false } = Astro.props;
360
293
 
361
294
  const canPageBeEmbedded = isEmbedEnabled();
362
295
  const verticalNavAutoCollapsePaths = [buildUrl('/discover', true), buildUrl('/docs', true)];
@@ -420,6 +353,10 @@ const verticalNavAutoCollapsePaths = [buildUrl('/discover', true), buildUrl('/do
420
353
  padding-left: var(--ec-app-content-padding-left);
421
354
  padding-right: var(--ec-app-content-padding-right);
422
355
  }
356
+ .app-content-wrapper--reduced-padding {
357
+ --ec-app-content-padding-left: 2rem;
358
+ --ec-app-content-padding-right: 2rem;
359
+ }
423
360
  .app-shell {
424
361
  min-height: calc(100vh - 4rem);
425
362
  flex: 1;
@@ -458,8 +395,9 @@ const verticalNavAutoCollapsePaths = [buildUrl('/discover', true), buildUrl('/do
458
395
  .vertical-nav-rail[data-collapsed='true'] .nav-secondary-item,
459
396
  .vertical-nav-rail[data-collapsed='true'] #vertical-nav-toggle {
460
397
  justify-content: center;
461
- padding-left: 0.25rem;
462
- padding-right: 0.25rem;
398
+ width: 2.5rem;
399
+ height: 2.5rem;
400
+ padding: 0;
463
401
  }
464
402
  :root[data-vertical-nav-collapsed='true'] .vertical-nav-rail .nav-brand-link,
465
403
  .vertical-nav-rail[data-collapsed='true'] .nav-brand-link {
@@ -468,13 +406,26 @@ const verticalNavAutoCollapsePaths = [buildUrl('/discover', true), buildUrl('/do
468
406
  }
469
407
  :root[data-vertical-nav-collapsed='true'] .vertical-nav-rail nav,
470
408
  .vertical-nav-rail[data-collapsed='true'] nav {
409
+ align-items: center;
410
+ gap: 0.75rem;
471
411
  padding-left: 0.25rem;
472
412
  padding-right: 0.25rem;
473
413
  }
474
414
  :root[data-vertical-nav-collapsed='true'] .vertical-nav-rail .rail-divider,
475
415
  .vertical-nav-rail[data-collapsed='true'] .rail-divider {
476
- margin-left: 0.25rem;
477
- margin-right: 0.25rem;
416
+ display: none;
417
+ }
418
+ :root[data-vertical-nav-collapsed='true'] .vertical-nav-rail nav > .mt-auto,
419
+ .vertical-nav-rail[data-collapsed='true'] nav > .mt-auto {
420
+ margin-top: auto !important;
421
+ padding-top: 0;
422
+ }
423
+ :root[data-vertical-nav-collapsed='true'] .vertical-nav-rail nav + div,
424
+ .vertical-nav-rail[data-collapsed='true'] nav + div {
425
+ border-top: 0;
426
+ display: flex;
427
+ justify-content: center;
428
+ padding: 0.75rem 0.25rem;
478
429
  }
479
430
  :root[data-vertical-nav-collapsed='true'] .vertical-nav-rail .nav-premium-icon,
480
431
  .vertical-nav-rail[data-collapsed='true'] .nav-premium-icon {
@@ -745,7 +696,7 @@ const verticalNavAutoCollapsePaths = [buildUrl('/discover', true), buildUrl('/do
745
696
  Astro.slots.has('sidebar-content') ? (
746
697
  <slot />
747
698
  ) : (
748
- <div class="app-content-wrapper">
699
+ <div class={`app-content-wrapper ${reducedContentPadding ? 'app-content-wrapper--reduced-padding' : ''}`}>
749
700
  <slot />
750
701
  </div>
751
702
  )
@@ -814,6 +765,10 @@ const verticalNavAutoCollapsePaths = [buildUrl('/discover', true), buildUrl('/do
814
765
  return pathname.includes('/schemas/fields');
815
766
  }
816
767
 
768
+ if (id === '/discover') {
769
+ return pathname === '/discover' || pathname.includes('/discover/');
770
+ }
771
+
817
772
  if (id === '/studio') {
818
773
  return pathname.includes('/studio');
819
774
  }
@@ -844,9 +799,10 @@ const verticalNavAutoCollapsePaths = [buildUrl('/discover', true), buildUrl('/do
844
799
  });
845
800
 
846
801
  secondaryNavItems.forEach((item) => {
802
+ const id = item.getAttribute('id');
847
803
  const href = item.getAttribute('href');
848
804
  const targetPath = href ? new URL(href, window.location.origin).pathname : null;
849
- const isCurrent = targetPath ? pathname === targetPath : false;
805
+ const isCurrent = id === '/discover' ? isNavItemCurrent(id, pathname) : targetPath ? pathname === targetPath : false;
850
806
 
851
807
  if (isCurrent) {
852
808
  item.classList.remove(...INACTIVE_NAV_CLASSES);