@eventcatalog/core 3.48.4 → 4.0.0-beta.1
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/catalog-to-astro-content-directory.cjs +1 -1
- package/dist/chunk-BWN544LB.js +73 -0
- package/dist/{chunk-XNVSSL4W.js → chunk-JTZT2SDF.js} +1 -1
- package/dist/{chunk-JY4H7A4S.js → chunk-M2ZRT7KQ.js} +1 -1
- package/dist/{chunk-SY4XL6OQ.js → chunk-MBVTS76Q.js} +1 -1
- package/dist/{chunk-KDLSBQRP.js → chunk-TZTPGQGL.js} +1 -1
- package/dist/{chunk-FNDSHOV2.js → chunk-U5OTNDVQ.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/core-node-modules.cjs +108 -0
- package/dist/core-node-modules.d.cts +7 -0
- package/dist/core-node-modules.d.ts +7 -0
- package/dist/core-node-modules.js +8 -0
- package/dist/docs/development/components/components/15-prompt.md +5 -1
- package/dist/eventcatalog.cjs +124 -48
- package/dist/eventcatalog.js +26 -15
- 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/astro.config.mjs +27 -23
- package/eventcatalog/public/icons/languages/java.svg +1 -0
- package/eventcatalog/public/icons/payments/stripe.svg +1 -0
- package/eventcatalog/src/components/Badge.astro +10 -10
- package/eventcatalog/src/components/CopyAsMarkdown.tsx +154 -0
- package/eventcatalog/src/components/Grids/DomainGrid.tsx +207 -44
- package/eventcatalog/src/components/Grids/MessageGrid.tsx +0 -20
- package/eventcatalog/src/components/Grids/SystemGrid.tsx +185 -0
- package/eventcatalog/src/components/MDX/ADRTable/ADRTable.astro +99 -0
- package/eventcatalog/src/components/MDX/ADRTable/ADRTable.client.tsx +400 -0
- package/eventcatalog/src/components/MDX/ContextDiagram/ContextDiagramPortal.tsx +21 -0
- package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +1 -0
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +42 -6
- package/eventcatalog/src/components/MDX/Prompt/Prompt.astro +62 -9
- package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +8 -1
- package/eventcatalog/src/components/MDX/SystemContextMap/SystemContextMapPortal.tsx +22 -0
- package/eventcatalog/src/components/MDX/components.tsx +7 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +1 -1
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +67 -37
- package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +47 -0
- package/eventcatalog/src/components/Tables/Discover/FilterComponents.tsx +10 -2
- package/eventcatalog/src/components/Tables/Discover/columns.tsx +115 -27
- package/eventcatalog/src/components/Tables/Discover/index.ts +7 -1
- package/eventcatalog/src/components/Tables/SystemResources/SystemResourcesTable.tsx +267 -0
- package/eventcatalog/src/content.config.ts +96 -8
- package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +4 -1
- package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +12 -13
- package/eventcatalog/src/enterprise/custom-documentation/utils/custom-docs.ts +6 -0
- package/eventcatalog/src/enterprise/feature.ts +3 -1
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +96 -140
- package/eventcatalog/src/layouts/VisualiserLayout.astro +66 -0
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +4 -2
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +2 -0
- package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +15 -15
- package/eventcatalog/src/pages/discover/[type]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/discover/[type]/index.astro +47 -2
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +15 -14
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +13 -14
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +11 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +81 -26
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/_index.data.ts +89 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/index.astro +85 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version].md.ts +2 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version].mdx.ts +2 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +24 -1
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +24 -1
- package/eventcatalog/src/pages/index.astro +30 -7
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +1 -1
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version].mermaid.ts +3 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/_index.data.ts +94 -0
- package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/index.astro +51 -0
- package/eventcatalog/src/pages/visualiser/system-context-map/index.astro +41 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/_index.data.ts +91 -0
- package/eventcatalog/src/pages/visualiser/systems/[id]/[version]/context/index.astro +51 -0
- package/eventcatalog/src/stores/sidebar-store/builders/adr.ts +3 -1
- package/eventcatalog/src/stores/sidebar-store/builders/agent.ts +3 -1
- package/eventcatalog/src/stores/sidebar-store/builders/container.ts +1 -1
- package/eventcatalog/src/stores/sidebar-store/builders/data-product.ts +1 -1
- package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +127 -49
- package/eventcatalog/src/stores/sidebar-store/builders/message.ts +1 -1
- package/eventcatalog/src/stores/sidebar-store/builders/service.ts +4 -2
- package/eventcatalog/src/stores/sidebar-store/builders/shared.ts +2 -1
- package/eventcatalog/src/stores/sidebar-store/builders/system.ts +166 -0
- package/eventcatalog/src/stores/sidebar-store/state.ts +99 -6
- package/eventcatalog/src/types/index.ts +2 -0
- package/eventcatalog/src/utils/collection-colors.ts +6 -1
- package/eventcatalog/src/utils/collections/domains.ts +35 -0
- package/eventcatalog/src/utils/collections/icons.ts +4 -5
- package/eventcatalog/src/utils/collections/systems.ts +110 -0
- package/eventcatalog/src/utils/collections/teams.ts +15 -10
- package/eventcatalog/src/utils/collections/users.ts +7 -4
- package/eventcatalog/src/utils/collections/util.ts +2 -0
- package/eventcatalog/src/utils/icon-map.ts +20 -0
- package/eventcatalog/src/utils/icon.ts +11 -0
- package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +12 -2
- package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +0 -170
- package/eventcatalog/src/utils/node-graphs/system-context-node-graph.ts +400 -0
- package/eventcatalog/src/utils/node-graphs/systems-node-graph.ts +208 -0
- package/eventcatalog/src/utils/node-graphs/utils/utils.ts +12 -0
- package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
- package/package.json +17 -14
- package/eventcatalog/src/pages/visualiser/context-map/index.astro +0 -30
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Footer from '@layouts/Footer.astro';
|
|
3
|
+
import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
|
|
4
|
+
import { buildUrl } from '@utils/url-builder';
|
|
5
|
+
import {
|
|
6
|
+
SystemResourcesTable,
|
|
7
|
+
type SystemResourceItem,
|
|
8
|
+
type SystemResourceCollection,
|
|
9
|
+
} from '@components/Tables/SystemResources/SystemResourcesTable';
|
|
10
|
+
|
|
11
|
+
import { Page } from './_index.data';
|
|
12
|
+
|
|
13
|
+
export const prerender = Page.prerender;
|
|
14
|
+
export const getStaticPaths = Page.getStaticPaths;
|
|
15
|
+
|
|
16
|
+
const resourceOwner = await Page.getData(Astro);
|
|
17
|
+
const { data } = resourceOwner;
|
|
18
|
+
const ownerCollection = resourceOwner.collection as 'systems' | 'domains';
|
|
19
|
+
|
|
20
|
+
// Domain-level messages come from the domain's own `sends` (Domain Events) and
|
|
21
|
+
// `receives` (External Events). Each resolved entry already carries its own
|
|
22
|
+
// collection (events / commands / queries). Dedupe across sends + receives.
|
|
23
|
+
const messageEntries = (() => {
|
|
24
|
+
const seen = new Map<string, any>();
|
|
25
|
+
for (const message of [...(data.sends || []), ...(data.receives || [])]) {
|
|
26
|
+
if (!message?.data?.id || !message?.collection) continue;
|
|
27
|
+
seen.set(`${message.collection}:${message.data.id}:${message.data.version}`, message);
|
|
28
|
+
}
|
|
29
|
+
return Array.from(seen.values());
|
|
30
|
+
})();
|
|
31
|
+
|
|
32
|
+
const messagesByCollection = (collection: SystemResourceCollection) =>
|
|
33
|
+
messageEntries.filter((message: any) => message.collection === collection);
|
|
34
|
+
|
|
35
|
+
// Only show resources that are directly attached to the system/domain — not resources
|
|
36
|
+
// nested further downstream. Domains can't hold containers directly, so a domain's
|
|
37
|
+
// Resources page shows services, flows, entities and its own messages.
|
|
38
|
+
const resourceGroups: Array<{ collection: SystemResourceCollection; items: any[] }> = [
|
|
39
|
+
{ collection: 'services', items: data.services || [] },
|
|
40
|
+
{ collection: 'flows', items: data.flows || [] },
|
|
41
|
+
{ collection: 'entities', items: data.entities || [] },
|
|
42
|
+
{ collection: 'containers', items: data.containers || [] },
|
|
43
|
+
{ collection: 'events', items: messagesByCollection('events') },
|
|
44
|
+
{ collection: 'commands', items: messagesByCollection('commands') },
|
|
45
|
+
{ collection: 'queries', items: messagesByCollection('queries') },
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const hrefForResource = (collection: SystemResourceCollection, id: string, version: string) => {
|
|
49
|
+
if (collection === 'entities') {
|
|
50
|
+
return buildUrl(`/docs/entities/${id}/${version}`);
|
|
51
|
+
}
|
|
52
|
+
return buildUrl(`/docs/${collection}/${id}/${version}`);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const resources: SystemResourceItem[] = resourceGroups.flatMap(({ collection, items }) =>
|
|
56
|
+
items.map((item: any) => ({
|
|
57
|
+
collection,
|
|
58
|
+
id: item.data.id,
|
|
59
|
+
name: item.data.name || item.data.id,
|
|
60
|
+
version: item.data.version,
|
|
61
|
+
summary: item.data.summary,
|
|
62
|
+
icon: item.data?.styles?.icon,
|
|
63
|
+
href: hrefForResource(collection, item.data.id, item.data.version),
|
|
64
|
+
}))
|
|
65
|
+
);
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
<VerticalSideBarLayout title={`${data.name} | Resources`}>
|
|
69
|
+
<main class="flex docs-layout min-h-full bg-[rgb(var(--ec-page-bg))]">
|
|
70
|
+
<div class="flex docs-layout w-full">
|
|
71
|
+
<div class="w-full lg:mr-2 pr-24 py-8 bg-[rgb(var(--ec-page-bg))]">
|
|
72
|
+
<div class="border-b border-[rgb(var(--ec-page-border))] pb-4">
|
|
73
|
+
<h2 class="text-2xl md:text-4xl font-bold text-[rgb(var(--ec-page-text))]">{data.name} Resources</h2>
|
|
74
|
+
<h2 class="text-lg pt-2 text-[rgb(var(--ec-page-text-muted))] font-light">
|
|
75
|
+
A group of resources that are mapped to the {data.name} {ownerCollection === 'domains' ? 'domain' : 'system'}.
|
|
76
|
+
</h2>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div class="py-8 w-full">
|
|
80
|
+
<SystemResourcesTable resources={resources} client:only="react" />
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
</main>
|
|
85
|
+
</VerticalSideBarLayout>
|
|
@@ -17,6 +17,7 @@ const queries = await getCollection('queries');
|
|
|
17
17
|
const services = await getCollection('services');
|
|
18
18
|
const dataProducts = await getCollection('data-products');
|
|
19
19
|
const domains = await getCollection('domains');
|
|
20
|
+
const systems = await getCollection('systems');
|
|
20
21
|
const flows = await getCollection('flows');
|
|
21
22
|
const channels = await getCollection('channels');
|
|
22
23
|
const containers = await getCollection('containers');
|
|
@@ -30,6 +31,7 @@ const collections = {
|
|
|
30
31
|
services,
|
|
31
32
|
'data-products': dataProducts,
|
|
32
33
|
domains,
|
|
34
|
+
systems,
|
|
33
35
|
flows,
|
|
34
36
|
channels,
|
|
35
37
|
containers,
|
|
@@ -15,6 +15,7 @@ const queries = await getCollection('queries');
|
|
|
15
15
|
const services = await getCollection('services');
|
|
16
16
|
const dataProducts = await getCollection('data-products');
|
|
17
17
|
const domains = await getCollection('domains');
|
|
18
|
+
const systems = await getCollection('systems');
|
|
18
19
|
const flows = await getCollection('flows');
|
|
19
20
|
const channels = await getCollection('channels');
|
|
20
21
|
const containers = await getCollection('containers');
|
|
@@ -30,6 +31,7 @@ const collections = {
|
|
|
30
31
|
services,
|
|
31
32
|
'data-products': dataProducts,
|
|
32
33
|
domains,
|
|
34
|
+
systems,
|
|
33
35
|
flows,
|
|
34
36
|
channels,
|
|
35
37
|
containers,
|
|
@@ -25,6 +25,7 @@ const membersRaw = props.data.members || [];
|
|
|
25
25
|
const members = (await Promise.all(membersRaw.map((m: CollectionEntry<'teams'>) => getEntry(m)))).filter(Boolean);
|
|
26
26
|
|
|
27
27
|
const domains = props.data.ownedDomains as CollectionEntry<'domains'>[];
|
|
28
|
+
const systems = props.data.ownedSystems as CollectionEntry<'systems'>[];
|
|
28
29
|
const agents = props.data.ownedAgents as CollectionEntry<'agents'>[];
|
|
29
30
|
const services = props.data.ownedServices as CollectionEntry<'services'>[];
|
|
30
31
|
const events = props.data.ownedEvents as CollectionEntry<'events'>[];
|
|
@@ -48,6 +49,13 @@ const ownedDomainsList = domains.map((p) => ({
|
|
|
48
49
|
tag: `v${p.data.version}`,
|
|
49
50
|
}));
|
|
50
51
|
|
|
52
|
+
const ownedSystemsList = systems.map((p) => ({
|
|
53
|
+
label: `${p.data.name}`,
|
|
54
|
+
collection: p.collection,
|
|
55
|
+
href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
|
|
56
|
+
tag: `v${p.data.version}`,
|
|
57
|
+
}));
|
|
58
|
+
|
|
51
59
|
const ownedServicesList = services.map((p) => ({
|
|
52
60
|
label: `${p.data.name}`,
|
|
53
61
|
href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
|
|
@@ -175,11 +183,15 @@ const sourceTitle = sourceLabel ? `Synced from ${sourceLabel}` : undefined;
|
|
|
175
183
|
</div>
|
|
176
184
|
</div>
|
|
177
185
|
<div class="border-b border-[rgb(var(--ec-page-border))] py-4" data-pagefind-ignore>
|
|
178
|
-
<dl class="grid grid-cols-2 gap-3 sm:grid-cols-
|
|
186
|
+
<dl class="grid grid-cols-2 gap-3 sm:grid-cols-7">
|
|
179
187
|
<div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
|
|
180
188
|
<dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Domains</dt>
|
|
181
189
|
<dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedDomainsList.length}</dd>
|
|
182
190
|
</div>
|
|
191
|
+
<div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
|
|
192
|
+
<dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Systems</dt>
|
|
193
|
+
<dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedSystemsList.length}</dd>
|
|
194
|
+
</div>
|
|
183
195
|
<div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
|
|
184
196
|
<dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Services</dt>
|
|
185
197
|
<dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedServicesList.length}</dd>
|
|
@@ -222,6 +234,17 @@ const sourceTitle = sourceLabel ? `Synced from ${sourceLabel}` : undefined;
|
|
|
222
234
|
/>
|
|
223
235
|
)
|
|
224
236
|
}
|
|
237
|
+
{
|
|
238
|
+
ownedSystemsList.length > 0 && (
|
|
239
|
+
<PillListFlat
|
|
240
|
+
color="pink"
|
|
241
|
+
title={`Owned systems (${ownedSystemsList.length})`}
|
|
242
|
+
pills={ownedSystemsList}
|
|
243
|
+
emptyMessage={`${props.data.name} does not own any systems.`}
|
|
244
|
+
client:load
|
|
245
|
+
/>
|
|
246
|
+
)
|
|
247
|
+
}
|
|
225
248
|
{
|
|
226
249
|
ownedServicesList.length > 0 && (
|
|
227
250
|
<PillListFlat
|
|
@@ -22,6 +22,7 @@ const props = await Page.getData(Astro);
|
|
|
22
22
|
const { Content } = await render(props);
|
|
23
23
|
|
|
24
24
|
const domains = props.data.ownedDomains as CollectionEntry<'domains'>[];
|
|
25
|
+
const systems = props.data.ownedSystems as CollectionEntry<'systems'>[];
|
|
25
26
|
const agents = props.data.ownedAgents as CollectionEntry<'agents'>[];
|
|
26
27
|
const services = props.data.ownedServices as CollectionEntry<'services'>[];
|
|
27
28
|
const events = props.data.ownedEvents as CollectionEntry<'events'>[];
|
|
@@ -37,6 +38,13 @@ const ownedDomainsList = domains.map((p) => ({
|
|
|
37
38
|
tag: `v${p.data.version}`,
|
|
38
39
|
}));
|
|
39
40
|
|
|
41
|
+
const ownedSystemsList = systems.map((p) => ({
|
|
42
|
+
label: `${p.data.name}`,
|
|
43
|
+
href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
|
|
44
|
+
collection: p.collection,
|
|
45
|
+
tag: `v${p.data.version}`,
|
|
46
|
+
}));
|
|
47
|
+
|
|
40
48
|
const ownedServicesList = services.map((p) => ({
|
|
41
49
|
label: `${p.data.name}`,
|
|
42
50
|
href: buildUrl(`/docs/${p.collection}/${p.data.id}/${p.data.version}`),
|
|
@@ -181,11 +189,15 @@ const sourceTitle = sourceLabel ? `Synced from ${sourceLabel}` : undefined;
|
|
|
181
189
|
</div>
|
|
182
190
|
</div>
|
|
183
191
|
<div class="border-b border-[rgb(var(--ec-page-border))] py-4" data-pagefind-ignore>
|
|
184
|
-
<dl class="grid grid-cols-2 gap-3 sm:grid-cols-
|
|
192
|
+
<dl class="grid grid-cols-2 gap-3 sm:grid-cols-7">
|
|
185
193
|
<div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
|
|
186
194
|
<dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Domains</dt>
|
|
187
195
|
<dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedDomainsList.length}</dd>
|
|
188
196
|
</div>
|
|
197
|
+
<div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
|
|
198
|
+
<dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Systems</dt>
|
|
199
|
+
<dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedSystemsList.length}</dd>
|
|
200
|
+
</div>
|
|
189
201
|
<div class="flex flex-col p-4 bg-[rgb(var(--ec-content-hover))] rounded-lg">
|
|
190
202
|
<dt class="text-xs font-medium text-[rgb(var(--ec-page-text-muted))]">Services</dt>
|
|
191
203
|
<dd class="text-2xl font-semibold text-[rgb(var(--ec-page-text))] mt-1">{ownedServicesList.length}</dd>
|
|
@@ -228,6 +240,17 @@ const sourceTitle = sourceLabel ? `Synced from ${sourceLabel}` : undefined;
|
|
|
228
240
|
/>
|
|
229
241
|
)
|
|
230
242
|
}
|
|
243
|
+
{
|
|
244
|
+
ownedSystemsList.length > 0 && (
|
|
245
|
+
<PillListFlat
|
|
246
|
+
color="pink"
|
|
247
|
+
title={`Owned systems (${ownedSystemsList.length})`}
|
|
248
|
+
pills={ownedSystemsList}
|
|
249
|
+
emptyMessage={`${props.data.name} does not own any systems.`}
|
|
250
|
+
client:load
|
|
251
|
+
/>
|
|
252
|
+
)
|
|
253
|
+
}
|
|
231
254
|
{
|
|
232
255
|
ownedServicesList.length > 0 && (
|
|
233
256
|
<PillListFlat
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
---
|
|
2
|
-
import Footer from '@layouts/Footer.astro';
|
|
3
2
|
import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
|
|
4
3
|
import { getMDXComponentsByName } from '@utils/markdown';
|
|
5
4
|
import { resourceToCollectionMap } from '@utils/collections/util';
|
|
@@ -9,6 +8,7 @@ import DefaultAstroLandingPage from './_index.astro';
|
|
|
9
8
|
import config from '@config';
|
|
10
9
|
|
|
11
10
|
let nodeGraphs: any[] = [];
|
|
11
|
+
let systemContextMaps: any[] = [];
|
|
12
12
|
let CustomContent = null;
|
|
13
13
|
let NodeGraph = null;
|
|
14
14
|
let customHomepageComponents: Record<string, any> = {};
|
|
@@ -34,9 +34,12 @@ if (existsSync(pathToUserDefinedLandingPage) && isCustomLandingPageEnabled()) {
|
|
|
34
34
|
const rawContent = readFileSync(pathToUserDefinedLandingPage, 'utf-8');
|
|
35
35
|
nodeGraphs = getMDXComponentsByName(rawContent, 'NodeGraph') || [];
|
|
36
36
|
|
|
37
|
+
// The homepage can also embed the global System Context Map via <SystemContextMap />.
|
|
38
|
+
systemContextMaps = getMDXComponentsByName(rawContent, 'SystemContextMap') || [];
|
|
39
|
+
|
|
37
40
|
// Avoid pulling visualizer CSS into the default homepage bundle.
|
|
38
|
-
// Only load the NodeGraph component when the custom homepage actually uses
|
|
39
|
-
if (nodeGraphs.length > 0) {
|
|
41
|
+
// Only load the NodeGraph component when the custom homepage actually uses a graph.
|
|
42
|
+
if (nodeGraphs.length > 0 || systemContextMaps.length > 0) {
|
|
40
43
|
NodeGraph = (await import('@components/MDX/NodeGraph/NodeGraph.astro')).default;
|
|
41
44
|
}
|
|
42
45
|
}
|
|
@@ -48,14 +51,13 @@ if (config.landingPage) {
|
|
|
48
51
|
|
|
49
52
|
{
|
|
50
53
|
CustomContent ? (
|
|
51
|
-
<VerticalSideBarLayout title="EventCatalog">
|
|
52
|
-
<main class="flex
|
|
54
|
+
<VerticalSideBarLayout title="EventCatalog" reducedContentPadding>
|
|
55
|
+
<main class="flex docs-layout h-full">
|
|
53
56
|
<div class="flex docs-layout w-full">
|
|
54
|
-
<div class="w-full
|
|
57
|
+
<div class="w-full overflow-y-auto py-8">
|
|
55
58
|
<div class="w-full max-w-none!">
|
|
56
59
|
<CustomContent components={customHomepageComponents} />
|
|
57
60
|
</div>
|
|
58
|
-
<Footer />
|
|
59
61
|
</div>
|
|
60
62
|
</div>
|
|
61
63
|
{NodeGraph &&
|
|
@@ -81,6 +83,27 @@ if (config.landingPage) {
|
|
|
81
83
|
/>
|
|
82
84
|
);
|
|
83
85
|
})}
|
|
86
|
+
{NodeGraph &&
|
|
87
|
+
systemContextMaps.length > 0 &&
|
|
88
|
+
systemContextMaps.map(() => (
|
|
89
|
+
<NodeGraph
|
|
90
|
+
id="system-context-map"
|
|
91
|
+
version="1.0.0"
|
|
92
|
+
collection="system-context-map"
|
|
93
|
+
title="System context map"
|
|
94
|
+
mode="simple"
|
|
95
|
+
linksToVisualiser={true}
|
|
96
|
+
portalId="system-context-map-portal"
|
|
97
|
+
href={
|
|
98
|
+
isVisualiserEnabled()
|
|
99
|
+
? {
|
|
100
|
+
label: 'Open in Visualiser',
|
|
101
|
+
url: buildUrl('/visualiser/system-context-map'),
|
|
102
|
+
}
|
|
103
|
+
: undefined
|
|
104
|
+
}
|
|
105
|
+
/>
|
|
106
|
+
))}
|
|
84
107
|
</main>
|
|
85
108
|
</VerticalSideBarLayout>
|
|
86
109
|
) : (
|
|
@@ -18,6 +18,7 @@ import { getNodesAndEdges as getNodesAndEdgesForDomain } from '@utils/node-graph
|
|
|
18
18
|
import { getNodesAndEdges as getNodesAndEdgesForFlows } from '@utils/node-graphs/flows-node-graph';
|
|
19
19
|
import { getNodesAndEdges as getNodesAndEdgesForDataProduct } from '@utils/node-graphs/data-products-node-graph';
|
|
20
20
|
import { getNodesAndEdges as getNodesAndEdgesForContainer } from '@utils/node-graphs/container-node-graph';
|
|
21
|
+
import { getNodesAndEdges as getNodesAndEdgesForSystem } from '@utils/node-graphs/systems-node-graph';
|
|
21
22
|
import { convertToMermaid } from '@utils/node-graphs/export-mermaid';
|
|
22
23
|
import config from '@config';
|
|
23
24
|
import type { PageTypes } from '@types';
|
|
@@ -36,6 +37,7 @@ const getNodesAndEdgesFunctions = {
|
|
|
36
37
|
flows: getNodesAndEdgesForFlows,
|
|
37
38
|
containers: getNodesAndEdgesForContainer,
|
|
38
39
|
'data-products': getNodesAndEdgesForDataProduct,
|
|
40
|
+
systems: getNodesAndEdgesForSystem,
|
|
39
41
|
};
|
|
40
42
|
|
|
41
43
|
export const getStaticPaths: GetStaticPaths = async () => {
|
|
@@ -59,6 +61,7 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
|
|
59
61
|
'flows',
|
|
60
62
|
'containers',
|
|
61
63
|
'data-products',
|
|
64
|
+
'systems',
|
|
62
65
|
];
|
|
63
66
|
|
|
64
67
|
const allItems = await Promise.all(itemTypes.map((type) => loaders[type]()));
|
package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/systems-context/_index.data.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { HybridPage } from '@utils/page-loaders/hybrid-page';
|
|
2
|
+
import { isAuthEnabled, isVisualiserEnabled } from '@utils/feature';
|
|
3
|
+
import { getDomains } from '@utils/collections/domains';
|
|
4
|
+
import { getSystems } from '@utils/collections/systems';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A domain gets a System Diagram when it has systems and at least one of those
|
|
8
|
+
* systems takes part in a context graph — i.e. it declares relationships or actors. A
|
|
9
|
+
* domain whose systems have neither has nothing to show, so we don't generate a page.
|
|
10
|
+
*/
|
|
11
|
+
const domainHasSystemContext = (
|
|
12
|
+
domain: Awaited<ReturnType<typeof getDomains>>[number],
|
|
13
|
+
systemMap: Map<string, { data: { relationships?: unknown[]; actors?: unknown[] } }>
|
|
14
|
+
) => {
|
|
15
|
+
const systemRefs = (domain.data.systems || []) as { id: string }[];
|
|
16
|
+
if (systemRefs.length === 0) return false;
|
|
17
|
+
|
|
18
|
+
return systemRefs.some((ref) => {
|
|
19
|
+
const system = systemMap.get(ref.id);
|
|
20
|
+
if (!system) return false;
|
|
21
|
+
const relationships = (system.data.relationships || []) as unknown[];
|
|
22
|
+
const actors = (system.data.actors || []) as unknown[];
|
|
23
|
+
return relationships.length > 0 || actors.length > 0;
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export class Page extends HybridPage {
|
|
28
|
+
static async getStaticPaths(): Promise<Array<{ params: any; props: any }>> {
|
|
29
|
+
if (isAuthEnabled() || !isVisualiserEnabled()) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const [domains, systems] = await Promise.all([getDomains({ getAllVersions: false }), getSystems()]);
|
|
34
|
+
const systemMap = new Map(systems.map((system) => [system.data.id, system]));
|
|
35
|
+
|
|
36
|
+
return domains
|
|
37
|
+
.filter((domain) => domainHasSystemContext(domain, systemMap))
|
|
38
|
+
.map((domain) => ({
|
|
39
|
+
params: {
|
|
40
|
+
id: domain.data.id,
|
|
41
|
+
version: domain.data.version,
|
|
42
|
+
},
|
|
43
|
+
props: {
|
|
44
|
+
type: 'domains',
|
|
45
|
+
...domain,
|
|
46
|
+
},
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
protected static async fetchData(params: any) {
|
|
51
|
+
const { id, version } = params;
|
|
52
|
+
|
|
53
|
+
if (!id || !version || !isVisualiserEnabled()) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const domains = await getDomains({ getAllVersions: false });
|
|
58
|
+
const item = domains.find((i) => i.data.id === id && i.data.version === version);
|
|
59
|
+
|
|
60
|
+
if (!item) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return item;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
protected static createNotFoundResponse(): Response {
|
|
68
|
+
return new Response(null, {
|
|
69
|
+
status: 404,
|
|
70
|
+
statusText: 'Domain System Diagram page not found',
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static get clientAuthScript(): string {
|
|
75
|
+
if (!isAuthEnabled() || !isVisualiserEnabled()) {
|
|
76
|
+
return '';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return `
|
|
80
|
+
if (typeof window !== 'undefined' && !import.meta.env.SSR) {
|
|
81
|
+
fetch('/api/auth/session')
|
|
82
|
+
.then(res => res.json())
|
|
83
|
+
.then(session => {
|
|
84
|
+
if (!session?.user) {
|
|
85
|
+
window.location.href = '/auth/login?callbackUrl=' + encodeURIComponent(window.location.pathname);
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
.catch(() => {
|
|
89
|
+
window.location.href = '/auth/login?callbackUrl=' + encodeURIComponent(window.location.pathname);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
import NodeGraph from '@components/MDX/NodeGraph/NodeGraph.astro';
|
|
3
|
+
import VisualiserLayout from '@layouts/VisualiserLayout.astro';
|
|
4
|
+
import { ClientRouter } from 'astro:transitions';
|
|
5
|
+
|
|
6
|
+
import { Page } from './_index.data';
|
|
7
|
+
|
|
8
|
+
export const prerender = Page.prerender;
|
|
9
|
+
export const getStaticPaths = Page.getStaticPaths;
|
|
10
|
+
|
|
11
|
+
// Get data
|
|
12
|
+
const props = await Page.getData(Astro);
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
data: { id },
|
|
16
|
+
} = props;
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<VisualiserLayout title={`Visualiser | ${props.data.name} - System Context`} description={props.data.summary}>
|
|
20
|
+
<div class="p-2">
|
|
21
|
+
<div
|
|
22
|
+
class="h-[calc(100vh-5rem)] w-full relative border border-[rgb(var(--ec-page-border))]"
|
|
23
|
+
id={`${id}-portal`}
|
|
24
|
+
transition:name="visualiser-graph"
|
|
25
|
+
>
|
|
26
|
+
</div>
|
|
27
|
+
<NodeGraph
|
|
28
|
+
id={id}
|
|
29
|
+
collection="domains-systems-context"
|
|
30
|
+
title={`${props.data.name} (v${props.data.version}) - System Context`}
|
|
31
|
+
mode="full"
|
|
32
|
+
linkTo="visualiser"
|
|
33
|
+
version={props.data.version}
|
|
34
|
+
linksToVisualiser={false}
|
|
35
|
+
/>
|
|
36
|
+
</div>
|
|
37
|
+
<ClientRouter />
|
|
38
|
+
</VisualiserLayout>
|
|
39
|
+
|
|
40
|
+
<script define:vars={{ id }}>
|
|
41
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
42
|
+
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
43
|
+
const params = Object.fromEntries(urlSearchParams.entries());
|
|
44
|
+
const embeded = params.embed === 'true' ? true : false;
|
|
45
|
+
const viewport = document.getElementById(`${id}-portal`);
|
|
46
|
+
|
|
47
|
+
if (embeded) {
|
|
48
|
+
viewport.style.height = 'calc(100vh - 30px)';
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
</script>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
import NodeGraph from '@components/MDX/NodeGraph/NodeGraph.astro';
|
|
3
|
+
import VisualiserLayout from '@layouts/VisualiserLayout.astro';
|
|
4
|
+
import { ClientRouter } from 'astro:transitions';
|
|
5
|
+
|
|
6
|
+
const id = 'system-context-map';
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<VisualiserLayout title={`Visualiser | System context map`}>
|
|
10
|
+
<div class="p-2">
|
|
11
|
+
<div
|
|
12
|
+
class="h-[calc(100vh-5rem)] w-full relative border border-[rgb(var(--ec-page-border))]"
|
|
13
|
+
id={`${id}-portal`}
|
|
14
|
+
transition:name="visualiser-graph"
|
|
15
|
+
>
|
|
16
|
+
</div>
|
|
17
|
+
<NodeGraph
|
|
18
|
+
id={id}
|
|
19
|
+
collection="system-context-map"
|
|
20
|
+
title="System context map"
|
|
21
|
+
mode="full"
|
|
22
|
+
linkTo="visualiser"
|
|
23
|
+
version="1.0.0"
|
|
24
|
+
linksToVisualiser={false}
|
|
25
|
+
/>
|
|
26
|
+
</div>
|
|
27
|
+
<ClientRouter />
|
|
28
|
+
</VisualiserLayout>
|
|
29
|
+
|
|
30
|
+
<script define:vars={{ id }}>
|
|
31
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
32
|
+
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
33
|
+
const params = Object.fromEntries(urlSearchParams.entries());
|
|
34
|
+
const embeded = params.embed === 'true' ? true : false;
|
|
35
|
+
const viewport = document.getElementById(`${id}-portal`);
|
|
36
|
+
|
|
37
|
+
if (embeded && viewport) {
|
|
38
|
+
viewport.style.height = 'calc(100vh - 30px)';
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
</script>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { HybridPage } from '@utils/page-loaders/hybrid-page';
|
|
2
|
+
import { isAuthEnabled, isVisualiserEnabled } from '@utils/feature';
|
|
3
|
+
import { getSystems } from '@utils/collections/systems';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A system participates in the System Diagram if it declares relationships
|
|
7
|
+
* (to other systems) or actors, or if another system declares a relationship
|
|
8
|
+
* pointing at it. Systems with nothing on any side have nothing to show, so we
|
|
9
|
+
* don't generate a page for them.
|
|
10
|
+
*/
|
|
11
|
+
const buildSystemsInContextGraph = (systems: Awaited<ReturnType<typeof getSystems>>) => {
|
|
12
|
+
const referenced = new Set<string>();
|
|
13
|
+
|
|
14
|
+
for (const system of systems) {
|
|
15
|
+
const relationships = (system.data.relationships || []) as { id: string }[];
|
|
16
|
+
const actors = (system.data.actors || []) as { id: string }[];
|
|
17
|
+
if (relationships.length > 0 || actors.length > 0) referenced.add(system.data.id);
|
|
18
|
+
for (const relationship of relationships) {
|
|
19
|
+
referenced.add(relationship.id);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return systems.filter((system) => referenced.has(system.data.id));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export class Page extends HybridPage {
|
|
27
|
+
static async getStaticPaths(): Promise<Array<{ params: any; props: any }>> {
|
|
28
|
+
if (isAuthEnabled() || !isVisualiserEnabled()) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const systems = await getSystems();
|
|
33
|
+
const systemsInContext = buildSystemsInContextGraph(systems);
|
|
34
|
+
|
|
35
|
+
return systemsInContext.map((system) => ({
|
|
36
|
+
params: {
|
|
37
|
+
id: system.data.id,
|
|
38
|
+
version: system.data.version,
|
|
39
|
+
},
|
|
40
|
+
props: {
|
|
41
|
+
type: 'systems',
|
|
42
|
+
...system,
|
|
43
|
+
},
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
protected static async fetchData(params: any) {
|
|
48
|
+
const { id, version } = params;
|
|
49
|
+
|
|
50
|
+
if (!id || !version || !isVisualiserEnabled()) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const systems = await getSystems();
|
|
55
|
+
const item = systems.find((i) => i.data.id === id && i.data.version === version);
|
|
56
|
+
|
|
57
|
+
if (!item) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return item;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
protected static createNotFoundResponse(): Response {
|
|
65
|
+
return new Response(null, {
|
|
66
|
+
status: 404,
|
|
67
|
+
statusText: 'System Diagram page not found',
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static get clientAuthScript(): string {
|
|
72
|
+
if (!isAuthEnabled() || !isVisualiserEnabled()) {
|
|
73
|
+
return '';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return `
|
|
77
|
+
if (typeof window !== 'undefined' && !import.meta.env.SSR) {
|
|
78
|
+
fetch('/api/auth/session')
|
|
79
|
+
.then(res => res.json())
|
|
80
|
+
.then(session => {
|
|
81
|
+
if (!session?.user) {
|
|
82
|
+
window.location.href = '/auth/login?callbackUrl=' + encodeURIComponent(window.location.pathname);
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
.catch(() => {
|
|
86
|
+
window.location.href = '/auth/login?callbackUrl=' + encodeURIComponent(window.location.pathname);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
`;
|
|
90
|
+
}
|
|
91
|
+
}
|