@eventcatalog/core 4.10.10 → 4.10.11

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.
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(analytics_exports);
36
36
  var import_os = __toESM(require("os"), 1);
37
37
 
38
38
  // package.json
39
- var version = "4.10.10";
39
+ var version = "4.10.11";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-QXANW76J.js";
4
- import "../chunk-PR77FB54.js";
3
+ } from "../chunk-TWZKZIRW.js";
4
+ import "../chunk-3XTFNVGA.js";
5
5
  export {
6
6
  raiseEvent
7
7
  };
@@ -140,7 +140,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
140
140
  var import_os = __toESM(require("os"), 1);
141
141
 
142
142
  // package.json
143
- var version = "4.10.10";
143
+ var version = "4.10.11";
144
144
 
145
145
  // src/constants.ts
146
146
  var VERSION = version;
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-K45ABG6N.js";
4
- import "../chunk-QXANW76J.js";
3
+ } from "../chunk-N6U5CNT7.js";
4
+ import "../chunk-TWZKZIRW.js";
5
5
  import "../chunk-ZAZHAVKB.js";
6
- import "../chunk-PR77FB54.js";
6
+ import "../chunk-3XTFNVGA.js";
7
7
  import "../chunk-6QENHZZP.js";
8
8
  export {
9
9
  log_build_default as default
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "4.10.10";
2
+ var version = "4.10.11";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-QXANW76J.js";
3
+ } from "./chunk-TWZKZIRW.js";
4
4
  import {
5
5
  countResources,
6
6
  hashCatalogContent,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-PR77FB54.js";
3
+ } from "./chunk-3XTFNVGA.js";
4
4
 
5
5
  // src/utils/cli-logger.ts
6
6
  import pc from "picocolors";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-PR77FB54.js";
3
+ } from "./chunk-3XTFNVGA.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import os from "os";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-U6R6BFJ5.js";
3
+ } from "./chunk-RLGMIZSH.js";
4
4
  import {
5
5
  cleanup,
6
6
  getEventCatalogConfigFile
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "4.10.10";
28
+ var version = "4.10.11";
29
29
 
30
30
  // src/constants.ts
31
31
  var VERSION = version;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-PR77FB54.js";
3
+ } from "./chunk-3XTFNVGA.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -144,7 +144,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
144
144
  var import_picocolors = __toESM(require("picocolors"), 1);
145
145
 
146
146
  // package.json
147
- var version = "4.10.10";
147
+ var version = "4.10.11";
148
148
 
149
149
  // src/constants.ts
150
150
  var VERSION = version;
@@ -4,8 +4,8 @@ import {
4
4
  import "./chunk-CA4U2JP7.js";
5
5
  import {
6
6
  log_build_default
7
- } from "./chunk-K45ABG6N.js";
8
- import "./chunk-QXANW76J.js";
7
+ } from "./chunk-N6U5CNT7.js";
8
+ import "./chunk-TWZKZIRW.js";
9
9
  import "./chunk-ZAZHAVKB.js";
10
10
  import {
11
11
  FederationConflictError,
@@ -31,10 +31,10 @@ import {
31
31
  } from "./chunk-B7HCX5HM.js";
32
32
  import {
33
33
  generate
34
- } from "./chunk-Y6VX2CGL.js";
34
+ } from "./chunk-VFRR3M72.js";
35
35
  import {
36
36
  logger
37
- } from "./chunk-U6R6BFJ5.js";
37
+ } from "./chunk-RLGMIZSH.js";
38
38
  import {
39
39
  resolve_catalog_dependencies_default
40
40
  } from "./chunk-LHR4G2UO.js";
@@ -54,7 +54,7 @@ import {
54
54
  import "./chunk-W5JQON7Z.js";
55
55
  import {
56
56
  VERSION
57
- } from "./chunk-PR77FB54.js";
57
+ } from "./chunk-3XTFNVGA.js";
58
58
  import {
59
59
  linkCoreNodeModules,
60
60
  resolveInstalledCoreNodeModules
package/dist/generate.cjs CHANGED
@@ -108,7 +108,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
108
108
  var import_picocolors = __toESM(require("picocolors"), 1);
109
109
 
110
110
  // package.json
111
- var version = "4.10.10";
111
+ var version = "4.10.11";
112
112
 
113
113
  // src/constants.ts
114
114
  var VERSION = version;
package/dist/generate.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  generate
3
- } from "./chunk-Y6VX2CGL.js";
4
- import "./chunk-U6R6BFJ5.js";
5
- import "./chunk-PR77FB54.js";
3
+ } from "./chunk-VFRR3M72.js";
4
+ import "./chunk-RLGMIZSH.js";
5
+ import "./chunk-3XTFNVGA.js";
6
6
  import "./chunk-6QENHZZP.js";
7
7
  export {
8
8
  generate
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(cli_logger_exports);
36
36
  var import_picocolors = __toESM(require("picocolors"), 1);
37
37
 
38
38
  // package.json
39
- var version = "4.10.10";
39
+ var version = "4.10.11";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  logger
3
- } from "../chunk-U6R6BFJ5.js";
4
- import "../chunk-PR77FB54.js";
3
+ } from "../chunk-RLGMIZSH.js";
4
+ import "../chunk-3XTFNVGA.js";
5
5
  export {
6
6
  logger
7
7
  };
@@ -17,6 +17,7 @@ import {
17
17
  import { buildUrl } from '@utils/url-builder';
18
18
  import { BoxIcon, Group as GroupIcon } from 'lucide-react';
19
19
  import { getSpecUrl, getSpecIcon, getSpecLabel, getServiceSpecifications } from './specification-utils';
20
+ import { getMessageLinkProps } from './message-link';
20
21
 
21
22
  // ============================================
22
23
  // Types
@@ -64,12 +65,8 @@ export const EntityBadge = memo(({ entity }: { entity: any }) => {
64
65
  });
65
66
 
66
67
  const MessageLink = memo(({ message }: { message: any }) => {
67
- const data = message?.data || message;
68
- const collection = message?.collection || 'events';
69
- const { Icon, color } = getMessageIcon(collection);
70
- const id = data?.id || message?.id;
71
- const name = data?.name || data?.id || id;
72
- const version = data?.version || message?.data?.version || 'latest';
68
+ const { collection, name, version, href } = getMessageLinkProps(message);
69
+ const { Icon, color } = getMessageIcon(collection || '');
73
70
 
74
71
  const iconStyles: Record<string, string> = {
75
72
  orange: 'text-orange-500',
@@ -78,14 +75,25 @@ const MessageLink = memo(({ message }: { message: any }) => {
78
75
  gray: 'text-gray-500',
79
76
  };
80
77
 
81
- return (
82
- <a
83
- href={buildUrl(`/docs/${collection}/${id}/${version}`)}
84
- className="flex items-center gap-2 py-1.5 text-sm text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))] transition-colors group"
85
- >
78
+ const content = (
79
+ <>
86
80
  <Icon className={`h-4 w-4 flex-shrink-0 ${iconStyles[color]}`} />
87
- <span className="group-hover:underline">{name}</span>
81
+ <span className={href ? 'group-hover:underline' : undefined}>{name}</span>
88
82
  <span className="text-xs text-[rgb(var(--ec-icon-color))]">v{version}</span>
83
+ </>
84
+ );
85
+
86
+ const className =
87
+ 'flex items-center gap-2 py-1.5 text-sm text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))] transition-colors group';
88
+
89
+ // Missing collection means an unhydrated pointer — do not guess `/docs/events/...`.
90
+ if (!href) {
91
+ return <span className={className}>{content}</span>;
92
+ }
93
+
94
+ return (
95
+ <a href={buildUrl(href)} className={className}>
96
+ {content}
89
97
  </a>
90
98
  );
91
99
  });
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { getMessageLinkProps } from './message-link';
3
+
4
+ describe('getMessageLinkProps', () => {
5
+ it('builds a command docs url and prefers the resource name over the id', () => {
6
+ expect(
7
+ getMessageLinkProps({
8
+ collection: 'commands',
9
+ data: { id: 'order-create', name: 'Create Order', version: '0.0.1' },
10
+ })
11
+ ).toEqual({
12
+ collection: 'commands',
13
+ id: 'order-create',
14
+ name: 'Create Order',
15
+ version: '0.0.1',
16
+ href: '/docs/commands/order-create/0.0.1',
17
+ });
18
+ });
19
+
20
+ it('builds a query docs url from a hydrated collection entry', () => {
21
+ expect(
22
+ getMessageLinkProps({
23
+ collection: 'queries',
24
+ data: { id: 'get-stock-level', name: 'Get Stock Level', version: '1.0.0' },
25
+ })
26
+ ).toEqual({
27
+ collection: 'queries',
28
+ id: 'get-stock-level',
29
+ name: 'Get Stock Level',
30
+ version: '1.0.0',
31
+ href: '/docs/queries/get-stock-level/1.0.0',
32
+ });
33
+ });
34
+
35
+ it('does not default a missing collection to events', () => {
36
+ expect(getMessageLinkProps({ id: 'order-create', version: '0.0.1' })).toEqual({
37
+ collection: undefined,
38
+ id: 'order-create',
39
+ name: 'order-create',
40
+ version: '0.0.1',
41
+ href: undefined,
42
+ });
43
+ });
44
+
45
+ it('ignores unknown collection values instead of linking to events', () => {
46
+ expect(
47
+ getMessageLinkProps({
48
+ collection: 'services',
49
+ data: { id: 'order-service', name: 'Order Service', version: '1.0.0' },
50
+ })
51
+ ).toEqual({
52
+ collection: undefined,
53
+ id: 'order-service',
54
+ name: 'Order Service',
55
+ version: '1.0.0',
56
+ href: undefined,
57
+ });
58
+ });
59
+ });
@@ -0,0 +1,38 @@
1
+ import type { CollectionMessageTypes } from '@types';
2
+
3
+ export const MESSAGE_COLLECTIONS: readonly CollectionMessageTypes[] = ['events', 'commands', 'queries'];
4
+
5
+ export function isMessageCollection(value: unknown): value is CollectionMessageTypes {
6
+ return value === 'events' || value === 'commands' || value === 'queries';
7
+ }
8
+
9
+ export interface MessageLinkProps {
10
+ collection?: CollectionMessageTypes;
11
+ id?: string;
12
+ name?: string;
13
+ version: string;
14
+ href?: string;
15
+ }
16
+
17
+ /**
18
+ * Resolve a DomainGrid/SystemGrid receives/sends item into a docs link.
19
+ *
20
+ * Hydrated collection entries carry `collection` + `data.name`. Bare `{id, version}`
21
+ * pointers do not — never guess `events` for those, or commands/queries get the wrong URL.
22
+ */
23
+ export function getMessageLinkProps(message: any): MessageLinkProps {
24
+ const data = message?.data ?? message;
25
+ const collectionCandidate = message?.collection ?? data?.collection;
26
+ const collection = isMessageCollection(collectionCandidate) ? collectionCandidate : undefined;
27
+ const id = data?.id ?? message?.id;
28
+ const name = data?.name || message?.name || id;
29
+ const version = data?.version ?? message?.version ?? 'latest';
30
+
31
+ return {
32
+ collection,
33
+ id,
34
+ name,
35
+ version,
36
+ href: collection && id ? `/docs/${collection}/${id}/${version}` : undefined,
37
+ };
38
+ }
@@ -0,0 +1,88 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { loadArchitectureItems, Page } from './_index.data';
3
+
4
+ const collectionMocks = vi.hoisted(() => ({
5
+ getDomains: vi.fn(),
6
+ getServices: vi.fn(),
7
+ getSystems: vi.fn(),
8
+ }));
9
+
10
+ vi.mock('@utils/feature', () => ({
11
+ isSSR: () => false,
12
+ }));
13
+
14
+ vi.mock('@utils/collections/domains', () => ({ getDomains: collectionMocks.getDomains }));
15
+ vi.mock('@utils/collections/systems', () => ({ getSystems: collectionMocks.getSystems }));
16
+ vi.mock('@utils/page-loaders/page-data-loader', () => ({
17
+ pageDataLoader: {
18
+ services: (...args: unknown[]) => collectionMocks.getServices(...args),
19
+ domains: (...args: unknown[]) => collectionMocks.getDomains(...args),
20
+ systems: (...args: unknown[]) => collectionMocks.getSystems(...args),
21
+ },
22
+ }));
23
+
24
+ const domain = {
25
+ collection: 'domains',
26
+ data: { id: 'ordering', name: 'Ordering', version: '1.0.0' },
27
+ };
28
+
29
+ const service = {
30
+ collection: 'services',
31
+ data: { id: 'order-service', name: 'Order Service', version: '1.0.0' },
32
+ };
33
+
34
+ const system = {
35
+ collection: 'systems',
36
+ data: { id: 'order-management-system', name: 'Order Management', version: '1.0.0' },
37
+ };
38
+
39
+ describe('architecture page data', () => {
40
+ beforeEach(() => {
41
+ collectionMocks.getDomains.mockReset().mockResolvedValue([domain]);
42
+ collectionMocks.getServices.mockReset().mockResolvedValue([service]);
43
+ collectionMocks.getSystems.mockReset().mockResolvedValue([system]);
44
+ });
45
+
46
+ it('hydrates domain and system services for static architecture paths', async () => {
47
+ const paths = await Page.getStaticPaths();
48
+
49
+ expect(collectionMocks.getDomains).toHaveBeenCalledWith({ enrichServices: true });
50
+ expect(collectionMocks.getSystems).toHaveBeenCalledWith({ enrichServices: true });
51
+ expect(paths).toEqual(
52
+ expect.arrayContaining([
53
+ expect.objectContaining({
54
+ params: { type: 'domains', id: 'ordering', version: '1.0.0' },
55
+ }),
56
+ expect.objectContaining({
57
+ params: { type: 'systems', id: 'order-management-system', version: '1.0.0' },
58
+ }),
59
+ expect.objectContaining({
60
+ params: { type: 'services', id: 'order-service', version: '1.0.0' },
61
+ }),
62
+ ])
63
+ );
64
+ });
65
+
66
+ it('hydrates domain services when architecture pages are fetched in SSR', async () => {
67
+ await Page.getData({
68
+ props: {},
69
+ params: { type: 'domains', id: 'ordering', version: '1.0.0' },
70
+ } as any);
71
+
72
+ expect(collectionMocks.getDomains).toHaveBeenCalledWith({ enrichServices: true });
73
+ });
74
+
75
+ it('hydrates system services when architecture pages are fetched in SSR', async () => {
76
+ await Page.getData({
77
+ props: {},
78
+ params: { type: 'systems', id: 'order-management-system', version: '1.0.0' },
79
+ } as any);
80
+
81
+ expect(collectionMocks.getSystems).toHaveBeenCalledWith({ enrichServices: true });
82
+ });
83
+
84
+ it('loads domains with enrichServices so DomainGrid command links keep their collection', async () => {
85
+ await loadArchitectureItems('domains');
86
+ expect(collectionMocks.getDomains).toHaveBeenCalledWith({ enrichServices: true });
87
+ });
88
+ });
@@ -3,11 +3,27 @@ import { HybridPage } from '@utils/page-loaders/hybrid-page';
3
3
  import type { PageTypes } from '@types';
4
4
  import { pageDataLoader } from '@utils/page-loaders/page-data-loader';
5
5
  import { getDomains } from '@utils/collections/domains';
6
- import { getServices } from '@utils/collections/services';
7
6
  import { getSystems } from '@utils/collections/systems';
8
7
 
9
8
  const architecturePageTypes: PageTypes[] = ['services', 'domains', 'systems'];
10
9
 
10
+ /**
11
+ * Architecture grids render service sends/receives as docs links, so domains and
12
+ * systems must hydrate those messages (collection + name). `pageDataLoader`
13
+ * uses the cheaper unenriched path used by docs/sidebar.
14
+ */
15
+ export const loadArchitectureItems = (type: PageTypes) => {
16
+ if (type === 'domains') {
17
+ return getDomains({ enrichServices: true });
18
+ }
19
+
20
+ if (type === 'systems') {
21
+ return getSystems({ enrichServices: true });
22
+ }
23
+
24
+ return pageDataLoader[type as PageTypes]();
25
+ };
26
+
11
27
  /**
12
28
  * Documentation page class for all collection types with versioning
13
29
  */
@@ -17,11 +33,7 @@ export class Page extends HybridPage {
17
33
  return [];
18
34
  }
19
35
 
20
- const domains = await getDomains({ enrichServices: true });
21
- const services = await getServices();
22
- const systems = await getSystems();
23
-
24
- const pageData = [services, domains, systems];
36
+ const pageData = await Promise.all(architecturePageTypes.map((type) => loadArchitectureItems(type)));
25
37
 
26
38
  return pageData.flatMap((items, index) =>
27
39
  items.map((item) => ({
@@ -47,8 +59,7 @@ export class Page extends HybridPage {
47
59
  return null;
48
60
  }
49
61
 
50
- // Get all items of the specified type
51
- const items = await pageDataLoader[type as PageTypes]();
62
+ const items = await loadArchitectureItems(type as PageTypes);
52
63
 
53
64
  // Find the specific item by id and version
54
65
  const item = items.find((i) => i.data.id === id && i.data.version === version);
@@ -4,6 +4,7 @@ import path from 'path';
4
4
  import type { CollectionMessageTypes } from '@types';
5
5
  import type { Agent, Service } from './types';
6
6
  import { createVersionedMap, findInMap, processSpecifications } from '@utils/collections/util';
7
+ import { hydrateAgents, hydrateServices } from '@utils/collections/hydrate-services';
7
8
 
8
9
  const CACHE_ENABLED = process.env.DISABLE_EVENTCATALOG_CACHE !== 'true';
9
10
 
@@ -19,86 +20,6 @@ interface Props {
19
20
  // Simple in-memory cache variable
20
21
  let memoryCache: Record<string, Domain[]> = {};
21
22
 
22
- // Helper to hydrate services
23
- const hydrateServices = (
24
- servicesList: any[],
25
- serviceMap: Map<string, any[]>,
26
- messageMap: Map<string, any[]>,
27
- containerMap: Map<string, any[]>
28
- ) => {
29
- return servicesList
30
- .map((service: { id: string; version: string | undefined }) => findInMap(serviceMap, service.id, service.version))
31
- .filter((s) => !!s)
32
- .map((service) => {
33
- // Hydrate service messages and containers
34
- const sends = (service.data.sends || [])
35
- .map((msg: any) => findInMap(messageMap, msg.id, msg.version))
36
- .filter((m: any) => !!m);
37
-
38
- const receives = (service.data.receives || [])
39
- .map((msg: any) => findInMap(messageMap, msg.id, msg.version))
40
- .filter((m: any) => !!m);
41
-
42
- const readsFrom = (service.data.readsFrom || [])
43
- .map((c: any) => findInMap(containerMap, c.id, c.version))
44
- .filter((c: any) => !!c);
45
-
46
- const writesTo = (service.data.writesTo || [])
47
- .map((c: any) => findInMap(containerMap, c.id, c.version))
48
- .filter((c: any) => !!c);
49
-
50
- return {
51
- ...service,
52
- data: {
53
- ...service.data,
54
- sends: sends as any,
55
- receives: receives as any,
56
- readsFrom: readsFrom as any,
57
- writesTo: writesTo as any,
58
- },
59
- };
60
- });
61
- };
62
-
63
- const hydrateAgents = (
64
- agentsList: any[],
65
- agentMap: Map<string, any[]>,
66
- messageMap: Map<string, any[]>,
67
- containerMap: Map<string, any[]>
68
- ) => {
69
- return agentsList
70
- .map((agent: { id: string; version: string | undefined }) => findInMap(agentMap, agent.id, agent.version))
71
- .filter((a) => !!a)
72
- .map((agent) => {
73
- const sends = (agent.data.sends || [])
74
- .map((msg: any) => findInMap(messageMap, msg.id, msg.version))
75
- .filter((m: any) => !!m);
76
-
77
- const receives = (agent.data.receives || [])
78
- .map((msg: any) => findInMap(messageMap, msg.id, msg.version))
79
- .filter((m: any) => !!m);
80
-
81
- const readsFrom = (agent.data.readsFrom || [])
82
- .map((c: any) => findInMap(containerMap, c.id, c.version))
83
- .filter((c: any) => !!c);
84
-
85
- const writesTo = (agent.data.writesTo || [])
86
- .map((c: any) => findInMap(containerMap, c.id, c.version))
87
- .filter((c: any) => !!c);
88
-
89
- return {
90
- ...agent,
91
- data: {
92
- ...agent.data,
93
- sends: sends as any,
94
- receives: receives as any,
95
- readsFrom: readsFrom as any,
96
- writesTo: writesTo as any,
97
- },
98
- };
99
- });
100
- };
101
-
102
23
  // --- MAIN FUNCTION ---
103
24
 
104
25
  export const getDomains = async ({
@@ -0,0 +1,51 @@
1
+ import { findInMap } from '@utils/collections/util';
2
+
3
+ /**
4
+ * Resolve service/agent pointers to collection entries and hydrate their
5
+ * sends/receives/readsFrom/writesTo relationships.
6
+ */
7
+ export const hydrateServices = (
8
+ servicesList: any[],
9
+ serviceMap: Map<string, any[]>,
10
+ messageMap: Map<string, any[]>,
11
+ containerMap: Map<string, any[]>
12
+ ) => {
13
+ return servicesList
14
+ .map((service: { id: string; version: string | undefined }) => findInMap(serviceMap, service.id, service.version))
15
+ .filter((s) => !!s)
16
+ .map((service) => {
17
+ const sends = (service.data.sends || [])
18
+ .map((msg: any) => findInMap(messageMap, msg.id, msg.version))
19
+ .filter((m: any) => !!m);
20
+
21
+ const receives = (service.data.receives || [])
22
+ .map((msg: any) => findInMap(messageMap, msg.id, msg.version))
23
+ .filter((m: any) => !!m);
24
+
25
+ const readsFrom = (service.data.readsFrom || [])
26
+ .map((c: any) => findInMap(containerMap, c.id, c.version))
27
+ .filter((c: any) => !!c);
28
+
29
+ const writesTo = (service.data.writesTo || [])
30
+ .map((c: any) => findInMap(containerMap, c.id, c.version))
31
+ .filter((c: any) => !!c);
32
+
33
+ return {
34
+ ...service,
35
+ data: {
36
+ ...service.data,
37
+ sends: sends as any,
38
+ receives: receives as any,
39
+ readsFrom: readsFrom as any,
40
+ writesTo: writesTo as any,
41
+ },
42
+ };
43
+ });
44
+ };
45
+
46
+ export const hydrateAgents = (
47
+ agentsList: any[],
48
+ agentMap: Map<string, any[]>,
49
+ messageMap: Map<string, any[]>,
50
+ containerMap: Map<string, any[]>
51
+ ) => hydrateServices(agentsList, agentMap, messageMap, containerMap);
@@ -1,5 +1,6 @@
1
1
  import { getCollection } from 'astro:content';
2
2
  import type { CollectionEntry } from 'astro:content';
3
+ import { hydrateServices } from '@utils/collections/hydrate-services';
3
4
  import { createVersionedMap, findInMap } from './util';
4
5
 
5
6
  const CACHE_ENABLED = process.env.DISABLE_EVENTCATALOG_CACHE !== 'true';
@@ -7,24 +8,28 @@ export type System = CollectionEntry<'systems'>;
7
8
 
8
9
  interface Props {
9
10
  getAllVersions?: boolean;
11
+ enrichServices?: boolean;
10
12
  }
11
13
 
12
14
  // cache for build time
13
15
  let memoryCache: Record<string, System[]> = {};
14
16
 
15
- export const getSystems = async ({ getAllVersions = true }: Props = {}): Promise<System[]> => {
16
- const cacheKey = getAllVersions ? 'allVersions' : 'currentVersions';
17
+ export const getSystems = async ({ getAllVersions = true, enrichServices = false }: Props = {}): Promise<System[]> => {
18
+ const cacheKey = `${getAllVersions ? 'allVersions' : 'currentVersions'}-${enrichServices ? 'enriched' : 'simple'}`;
17
19
 
18
20
  if (memoryCache[cacheKey] && memoryCache[cacheKey].length > 0 && CACHE_ENABLED) {
19
21
  return memoryCache[cacheKey];
20
22
  }
21
23
 
22
- const [allSystems, allServices, allFlows, allEntities, allContainers] = await Promise.all([
24
+ const [allSystems, allServices, allFlows, allEntities, allContainers, allEvents, allCommands, allQueries] = await Promise.all([
23
25
  getCollection('systems'),
24
26
  getCollection('services'),
25
27
  getCollection('flows'),
26
28
  getCollection('entities'),
27
29
  getCollection('containers'),
30
+ enrichServices ? getCollection('events') : Promise.resolve([]),
31
+ enrichServices ? getCollection('commands') : Promise.resolve([]),
32
+ enrichServices ? getCollection('queries') : Promise.resolve([]),
28
33
  ]);
29
34
 
30
35
  // Build optimized map of id -> versions (sorted latest first)
@@ -33,6 +38,7 @@ export const getSystems = async ({ getAllVersions = true }: Props = {}): Promise
33
38
  const flowMap = createVersionedMap(allFlows);
34
39
  const entityMap = createVersionedMap(allEntities);
35
40
  const containerMap = createVersionedMap(allContainers);
41
+ const messageMap = createVersionedMap([...allEvents, ...allCommands, ...allQueries]);
36
42
 
37
43
  // Filter systems
38
44
  const targetSystems = allSystems.filter((system) => {
@@ -47,10 +53,14 @@ export const getSystems = async ({ getAllVersions = true }: Props = {}): Promise
47
53
  const latestVersion = systemVersions[0]?.data.version || system.data.version;
48
54
  const versions = systemVersions.map((s) => s.data.version);
49
55
 
50
- // Resolve service pointers to their full collection entries
51
- const services = (system.data.services || [])
52
- .map((service: { id: string; version?: string }) => findInMap(serviceMap, service.id, service.version))
53
- .filter((s): s is NonNullable<typeof s> => !!s);
56
+ // Resolve service pointers to their full collection entries.
57
+ // Architecture grids need sends/receives hydrated so command/query links
58
+ // keep the correct collection instead of falling back to events.
59
+ const services = enrichServices
60
+ ? hydrateServices(system.data.services || [], serviceMap, messageMap, containerMap)
61
+ : (system.data.services || [])
62
+ .map((service: { id: string; version?: string }) => findInMap(serviceMap, service.id, service.version))
63
+ .filter((s): s is NonNullable<typeof s> => !!s);
54
64
 
55
65
  // Resolve flow pointers to their full collection entries
56
66
  const flows = (system.data.flows || [])
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "SEE LICENSE IN LICENSE",
9
9
  "type": "module",
10
- "version": "4.10.10",
10
+ "version": "4.10.11",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -118,9 +118,9 @@
118
118
  "update-notifier": "^7.3.1",
119
119
  "uuid": "^11.1.1",
120
120
  "zod": "^4.3.6",
121
+ "@eventcatalog/linter": "1.1.18",
121
122
  "@eventcatalog/sdk": "2.29.0",
122
- "@eventcatalog/visualiser": "^4.1.4",
123
- "@eventcatalog/linter": "1.1.18"
123
+ "@eventcatalog/visualiser": "^4.1.4"
124
124
  },
125
125
  "devDependencies": {
126
126
  "@astrojs/check": "^0.9.10",