@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.
- package/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/{chunk-PR77FB54.js → chunk-3XTFNVGA.js} +1 -1
- package/dist/{chunk-K45ABG6N.js → chunk-N6U5CNT7.js} +1 -1
- package/dist/{chunk-U6R6BFJ5.js → chunk-RLGMIZSH.js} +1 -1
- package/dist/{chunk-QXANW76J.js → chunk-TWZKZIRW.js} +1 -1
- package/dist/{chunk-Y6VX2CGL.js → chunk-VFRR3M72.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +1 -1
- package/dist/eventcatalog.js +5 -5
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/src/components/Grids/DomainGrid.tsx +20 -12
- package/eventcatalog/src/components/Grids/message-link.spec.ts +59 -0
- package/eventcatalog/src/components/Grids/message-link.ts +38 -0
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.spec.ts +88 -0
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +19 -8
- package/eventcatalog/src/utils/collections/domains.ts +1 -80
- package/eventcatalog/src/utils/collections/hydrate-services.ts +51 -0
- package/eventcatalog/src/utils/collections/systems.ts +17 -7
- package/package.json +3 -3
|
@@ -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.
|
|
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-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-N6U5CNT7.js";
|
|
4
|
+
import "../chunk-TWZKZIRW.js";
|
|
5
5
|
import "../chunk-ZAZHAVKB.js";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-3XTFNVGA.js";
|
|
7
7
|
import "../chunk-6QENHZZP.js";
|
|
8
8
|
export {
|
|
9
9
|
log_build_default as default
|
package/dist/constants.cjs
CHANGED
package/dist/constants.js
CHANGED
package/dist/eventcatalog.cjs
CHANGED
|
@@ -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.
|
|
147
|
+
var version = "4.10.11";
|
|
148
148
|
|
|
149
149
|
// src/constants.ts
|
|
150
150
|
var VERSION = version;
|
package/dist/eventcatalog.js
CHANGED
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
import "./chunk-CA4U2JP7.js";
|
|
5
5
|
import {
|
|
6
6
|
log_build_default
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
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-
|
|
34
|
+
} from "./chunk-VFRR3M72.js";
|
|
35
35
|
import {
|
|
36
36
|
logger
|
|
37
|
-
} from "./chunk-
|
|
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-
|
|
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.
|
|
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-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
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
|
package/dist/utils/cli-logger.js
CHANGED
|
@@ -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
|
|
68
|
-
const
|
|
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
|
-
|
|
82
|
-
|
|
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=
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
+
"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",
|