@eventcatalog/core 2.58.2 → 2.59.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/{chunk-PV4MP6U4.js → chunk-5GNBQGFW.js} +1 -1
- package/dist/{chunk-WK6GQM5P.js → chunk-AREJNU2F.js} +1 -1
- package/dist/{chunk-ZBPULBAC.js → chunk-LAI5QQUI.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 +3 -3
- package/eventcatalog/src/components/Grids/DomainGrid.tsx +67 -2
- package/eventcatalog/src/components/Grids/MessageGrid.tsx +157 -41
- package/eventcatalog/src/components/Grids/ServiceGrid.tsx +78 -14
- package/eventcatalog/src/components/MDX/NodeGraph/Edges/MultilineEdgeLabel.tsx +52 -0
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +13 -0
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.tsx +4 -1
- package/eventcatalog/src/components/MDX/NodeGraph/Nodes/Data.tsx +55 -16
- package/eventcatalog/src/components/SideBars/ContainerSideBar.astro +180 -0
- package/eventcatalog/src/components/SideBars/ServiceSideBar.astro +41 -0
- package/eventcatalog/src/components/SideNav/ListViewSideBar/components/MessageList.tsx +1 -1
- package/eventcatalog/src/components/SideNav/ListViewSideBar/index.tsx +250 -59
- package/eventcatalog/src/components/SideNav/ListViewSideBar/types.ts +3 -0
- package/eventcatalog/src/components/SideNav/ListViewSideBar/utils.ts +35 -1
- package/eventcatalog/src/components/SideNav/TreeView/getTreeView.ts +2 -2
- package/eventcatalog/src/components/Tables/Table.tsx +22 -2
- package/eventcatalog/src/components/Tables/columns/ContainersTableColumns.tsx +152 -0
- package/eventcatalog/src/components/Tables/columns/index.tsx +3 -0
- package/eventcatalog/src/content.config.ts +57 -1
- package/eventcatalog/src/layouts/DiscoverLayout.astro +11 -1
- package/eventcatalog/src/pages/architecture/architecture.astro +9 -1
- package/eventcatalog/src/pages/discover/[type]/_index.data.ts +1 -1
- package/eventcatalog/src/pages/discover/[type]/index.astro +11 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +11 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/_index.data.ts +1 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +4 -6
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +50 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version].md.ts +2 -0
- package/eventcatalog/src/pages/docs/llm/llms-full.txt.ts +4 -1
- package/eventcatalog/src/pages/docs/llm/llms-services.txt.ts +19 -1
- package/eventcatalog/src/pages/docs/llm/llms.txt.ts +3 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +1 -1
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/_index.data.ts +80 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/data/index.astro +52 -0
- package/eventcatalog/src/pages/visualiser/[type]/[id]/index.astro +9 -2
- package/eventcatalog/src/types/index.ts +20 -2
- package/eventcatalog/src/utils/collections/containers.ts +94 -0
- package/eventcatalog/src/utils/collections/icons.ts +3 -1
- package/eventcatalog/src/utils/collections/services.ts +15 -1
- package/eventcatalog/src/utils/collections/util.ts +4 -2
- package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +155 -0
- package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +188 -82
- package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ import { columns as ServiceTableColumns } from './ServiceTableColumns';
|
|
|
4
4
|
import { columns as DomainTableColumns } from './DomainTableColumns';
|
|
5
5
|
import { columns as FlowTableColumns } from './FlowTableColumns';
|
|
6
6
|
import { columns as TeamsTableColumns } from './TeamsTableColumns';
|
|
7
|
+
import { columns as ContainerTableColumns } from './ContainersTableColumns';
|
|
7
8
|
export const getColumnsByCollection = (collection: string): any => {
|
|
8
9
|
switch (collection) {
|
|
9
10
|
case 'events':
|
|
@@ -20,6 +21,8 @@ export const getColumnsByCollection = (collection: string): any => {
|
|
|
20
21
|
return UserTableColumns();
|
|
21
22
|
case 'teams':
|
|
22
23
|
return TeamsTableColumns();
|
|
24
|
+
case 'containers':
|
|
25
|
+
return ContainerTableColumns();
|
|
23
26
|
default:
|
|
24
27
|
return [];
|
|
25
28
|
}
|
|
@@ -47,7 +47,7 @@ const channelPointer = z
|
|
|
47
47
|
const resourcePointer = z.object({
|
|
48
48
|
id: z.string(),
|
|
49
49
|
version: z.string().optional().default('latest'),
|
|
50
|
-
type: z.enum(['service', 'event', 'command', 'query', 'flow', 'channel', 'domain', 'user', 'team']),
|
|
50
|
+
type: z.enum(['service', 'event', 'command', 'query', 'flow', 'channel', 'domain', 'user', 'team', 'container']),
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
const changelogs = defineCollection({
|
|
@@ -361,6 +361,8 @@ const services = defineCollection({
|
|
|
361
361
|
sends: z.array(pointer).optional(),
|
|
362
362
|
receives: z.array(pointer).optional(),
|
|
363
363
|
entities: z.array(pointer).optional(),
|
|
364
|
+
writesTo: z.array(pointer).optional(),
|
|
365
|
+
readsFrom: z.array(pointer).optional(),
|
|
364
366
|
detailsPanel: z
|
|
365
367
|
.object({
|
|
366
368
|
domains: detailPanelPropertySchema.optional(),
|
|
@@ -371,12 +373,65 @@ const services = defineCollection({
|
|
|
371
373
|
repository: detailPanelPropertySchema.optional(),
|
|
372
374
|
owners: detailPanelPropertySchema.optional(),
|
|
373
375
|
changelog: detailPanelPropertySchema.optional(),
|
|
376
|
+
containers: detailPanelPropertySchema.optional(),
|
|
374
377
|
})
|
|
375
378
|
.optional(),
|
|
376
379
|
})
|
|
377
380
|
.merge(baseSchema),
|
|
378
381
|
});
|
|
379
382
|
|
|
383
|
+
// 1) Put this near your other enums/utilities
|
|
384
|
+
const containerTypeEnum = z.enum([
|
|
385
|
+
// Core
|
|
386
|
+
'database',
|
|
387
|
+
'cache',
|
|
388
|
+
'objectStore',
|
|
389
|
+
'searchIndex',
|
|
390
|
+
'dataWarehouse',
|
|
391
|
+
'dataLake',
|
|
392
|
+
'externalSaaS',
|
|
393
|
+
// Fallback
|
|
394
|
+
'other',
|
|
395
|
+
]);
|
|
396
|
+
|
|
397
|
+
const accessModeEnum = z.enum(['read', 'write', 'readWrite', 'appendOnly']);
|
|
398
|
+
const dataClassificationEnum = z.enum(['public', 'internal', 'confidential', 'regulated']);
|
|
399
|
+
|
|
400
|
+
const containers = defineCollection({
|
|
401
|
+
loader: glob({
|
|
402
|
+
pattern: ['**/containers/*/index.(md|mdx)', '**/containers/*/versioned/*/index.(md|mdx)'],
|
|
403
|
+
base: projectDirBase,
|
|
404
|
+
generateId: ({ data }) => {
|
|
405
|
+
return `${data.id}-${data.version}`;
|
|
406
|
+
},
|
|
407
|
+
}),
|
|
408
|
+
schema: z
|
|
409
|
+
.object({
|
|
410
|
+
container_type: containerTypeEnum, // <— the important discriminator inside DataContainer
|
|
411
|
+
technology: z.string().optional(), // e.g. "postgres@14", "kafka", "s3"
|
|
412
|
+
authoritative: z.boolean().optional().default(false),
|
|
413
|
+
access_mode: accessModeEnum.optional(), // read/write/readWrite/appendOnly
|
|
414
|
+
classification: dataClassificationEnum.optional(),
|
|
415
|
+
residency: z.string().optional(),
|
|
416
|
+
retention: z.string().optional(),
|
|
417
|
+
// details panel toggles (aligns with your pattern)
|
|
418
|
+
detailsPanel: z
|
|
419
|
+
.object({
|
|
420
|
+
versions: detailPanelPropertySchema.optional(),
|
|
421
|
+
repository: detailPanelPropertySchema.optional(),
|
|
422
|
+
owners: detailPanelPropertySchema.optional(),
|
|
423
|
+
changelog: detailPanelPropertySchema.optional(),
|
|
424
|
+
attachments: detailPanelPropertySchema.optional(),
|
|
425
|
+
})
|
|
426
|
+
.optional(),
|
|
427
|
+
services: z.array(reference('services')).optional(),
|
|
428
|
+
|
|
429
|
+
servicesThatWriteToContainer: z.array(reference('services')).optional(),
|
|
430
|
+
servicesThatReadFromContainer: z.array(reference('services')).optional(),
|
|
431
|
+
})
|
|
432
|
+
.merge(baseSchema),
|
|
433
|
+
});
|
|
434
|
+
|
|
380
435
|
const customPages = defineCollection({
|
|
381
436
|
loader: glob({
|
|
382
437
|
// any number of child folders
|
|
@@ -628,6 +683,7 @@ export const collections = {
|
|
|
628
683
|
flows,
|
|
629
684
|
pages,
|
|
630
685
|
changelogs,
|
|
686
|
+
containers,
|
|
631
687
|
|
|
632
688
|
// DDD Collections
|
|
633
689
|
ubiquitousLanguages,
|
|
@@ -9,6 +9,8 @@ import { getEvents } from '@utils/events';
|
|
|
9
9
|
import { getServices } from '@utils/collections/services';
|
|
10
10
|
import { buildUrl } from '@utils/url-builder';
|
|
11
11
|
import { getQueries } from '@utils/queries';
|
|
12
|
+
import { getContainers } from '@utils/collections/containers';
|
|
13
|
+
import { DatabaseIcon } from 'lucide-react';
|
|
12
14
|
import { MagnifyingGlassIcon } from '@heroicons/react/20/solid';
|
|
13
15
|
import VerticalSideBarLayout from './VerticalSideBarLayout.astro';
|
|
14
16
|
import Checkbox from '@components/Checkbox.astro';
|
|
@@ -19,7 +21,7 @@ const commands = await getCommands();
|
|
|
19
21
|
const services = await getServices();
|
|
20
22
|
const domains = await getDomains();
|
|
21
23
|
const flows = await getFlows();
|
|
22
|
-
|
|
24
|
+
const containers = await getContainers();
|
|
23
25
|
export interface Props<T extends TCollectionTypes> {
|
|
24
26
|
title: string;
|
|
25
27
|
subtitle: string;
|
|
@@ -74,6 +76,14 @@ const tabs = [
|
|
|
74
76
|
activeColor: 'yellow',
|
|
75
77
|
enabled: domains.length > 0,
|
|
76
78
|
},
|
|
79
|
+
{
|
|
80
|
+
label: `Data (${containers.length})`,
|
|
81
|
+
href: buildUrl('/discover/containers'),
|
|
82
|
+
isActive: currentPath === '/discover/containers',
|
|
83
|
+
icon: DatabaseIcon,
|
|
84
|
+
activeColor: 'blue',
|
|
85
|
+
enabled: containers.length > 0,
|
|
86
|
+
},
|
|
77
87
|
{
|
|
78
88
|
label: `Flows (${flows.length})`,
|
|
79
89
|
href: buildUrl('/discover/flows'),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { getDomains, getMessagesForDomain } from '@utils/collections/domains';
|
|
3
3
|
import { getServices } from '@utils/collections/services';
|
|
4
|
+
import { getContainers } from '@utils/collections/containers';
|
|
4
5
|
import { getMessages } from '@utils/messages';
|
|
5
6
|
import type { ExtendedDomain } from '@components/Grids/DomainGrid';
|
|
6
7
|
import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
|
|
@@ -27,6 +28,7 @@ const { type, embeded = false } = Astro.props as { type: ValidType; embeded: boo
|
|
|
27
28
|
// Get data based on type
|
|
28
29
|
let items: Service[] | CollectionEntry<'commands'>[] | CollectionEntry<CollectionMessageTypes>[] = [];
|
|
29
30
|
let domains: ExtendedDomain[] = [];
|
|
31
|
+
let containers: CollectionEntry<'containers'>[] = [];
|
|
30
32
|
|
|
31
33
|
const getDomainsForArchitecturePages = async () => {
|
|
32
34
|
const domains = await getDomains({ getAllVersions: false });
|
|
@@ -68,6 +70,7 @@ if (type === 'services') {
|
|
|
68
70
|
const { events, commands, queries } = await getMessages({ getAllVersions: false, hydrateServices: false });
|
|
69
71
|
const messages = [...events, ...commands, ...queries];
|
|
70
72
|
items = removeContentFromCollection(messages) as unknown as CollectionEntry<CollectionMessageTypes>[];
|
|
73
|
+
containers = await getContainers({ getAllVersions: false });
|
|
71
74
|
}
|
|
72
75
|
---
|
|
73
76
|
|
|
@@ -83,7 +86,12 @@ if (type === 'services') {
|
|
|
83
86
|
}
|
|
84
87
|
{
|
|
85
88
|
type === 'messages' && (
|
|
86
|
-
<MessageGrid
|
|
89
|
+
<MessageGrid
|
|
90
|
+
messages={items as CollectionEntry<CollectionMessageTypes>[]}
|
|
91
|
+
embeded={embeded}
|
|
92
|
+
containers={containers}
|
|
93
|
+
client:load
|
|
94
|
+
/>
|
|
87
95
|
)
|
|
88
96
|
}
|
|
89
97
|
</div>
|
|
@@ -16,7 +16,7 @@ export class Page extends HybridPage {
|
|
|
16
16
|
flows: getFlows,
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
const itemTypes = ['events', 'commands', 'queries', 'services', 'domains', 'flows'] as const;
|
|
19
|
+
const itemTypes = ['events', 'commands', 'queries', 'services', 'domains', 'flows', 'containers'] as const;
|
|
20
20
|
const allItems = await Promise.all(itemTypes.map((type) => loaders[type]()));
|
|
21
21
|
|
|
22
22
|
return allItems.flatMap((items, index) => ({
|
|
@@ -9,6 +9,12 @@ export const getStaticPaths = Page.getStaticPaths;
|
|
|
9
9
|
|
|
10
10
|
const { type, data } = await Page.getData(Astro);
|
|
11
11
|
|
|
12
|
+
let title = `${type} (${data.length})`;
|
|
13
|
+
|
|
14
|
+
if (type === 'containers') {
|
|
15
|
+
title = `Data (${data.length})`;
|
|
16
|
+
}
|
|
17
|
+
|
|
12
18
|
function mapToItem(i: any) {
|
|
13
19
|
return {
|
|
14
20
|
collection: i.collection,
|
|
@@ -22,7 +28,7 @@ function mapToItem(i: any) {
|
|
|
22
28
|
---
|
|
23
29
|
|
|
24
30
|
<DiscoverLayout
|
|
25
|
-
title={
|
|
31
|
+
title={title}
|
|
26
32
|
subtitle={`Find, filter and search for any ${type} in your system.`}
|
|
27
33
|
data={data.map(
|
|
28
34
|
(d: CollectionEntry<CollectionTypes>) =>
|
|
@@ -46,6 +52,10 @@ function mapToItem(i: any) {
|
|
|
46
52
|
sends: d.data?.sends?.map(mapToItem) ?? [],
|
|
47
53
|
// @ts-ignore
|
|
48
54
|
services: d.data?.services?.map(mapToItem) ?? [],
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
servicesThatWriteToContainer: d.data?.servicesThatWriteToContainer?.map(mapToItem) ?? [],
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
servicesThatReadFromContainer: d.data?.servicesThatReadFromContainer?.map(mapToItem) ?? [],
|
|
49
59
|
},
|
|
50
60
|
}) as DiscoverLayoutProps<typeof type>['data'][0]
|
|
51
61
|
)}
|
|
@@ -12,7 +12,17 @@ export class Page extends HybridPage {
|
|
|
12
12
|
return [];
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const itemTypes: PageTypes[] = [
|
|
15
|
+
const itemTypes: PageTypes[] = [
|
|
16
|
+
'events',
|
|
17
|
+
'commands',
|
|
18
|
+
'queries',
|
|
19
|
+
'services',
|
|
20
|
+
'domains',
|
|
21
|
+
'flows',
|
|
22
|
+
'channels',
|
|
23
|
+
'entities',
|
|
24
|
+
'containers',
|
|
25
|
+
];
|
|
16
26
|
const allItems = await Promise.all(itemTypes.map((type) => pageDataLoader[type]()));
|
|
17
27
|
|
|
18
28
|
return allItems.flatMap((items, index) =>
|
|
@@ -14,7 +14,7 @@ export class Page extends HybridPage {
|
|
|
14
14
|
|
|
15
15
|
const { pageDataLoader } = await import('@utils/page-loaders/page-data-loader');
|
|
16
16
|
|
|
17
|
-
const itemTypes: PageTypes[] = ['events', 'commands', 'queries', 'services', 'domains', 'flows'];
|
|
17
|
+
const itemTypes: PageTypes[] = ['events', 'commands', 'queries', 'services', 'domains', 'flows', 'containers'];
|
|
18
18
|
const allItems = await Promise.all(itemTypes.map((type) => pageDataLoader[type]()));
|
|
19
19
|
|
|
20
20
|
return allItems.flatMap((items, index) =>
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
MagnifyingGlassIcon,
|
|
10
10
|
QueueListIcon,
|
|
11
11
|
} from '@heroicons/react/24/outline';
|
|
12
|
+
import { DatabaseIcon } from 'lucide-react';
|
|
12
13
|
import { render, getEntry } from 'astro:content';
|
|
13
14
|
import mdxComponents from '@components/MDX/components';
|
|
14
15
|
import 'diff2html/bundles/css/diff2html.min.css';
|
|
@@ -96,18 +97,15 @@ const getBadge = () => {
|
|
|
96
97
|
class: 'text-yellow-400',
|
|
97
98
|
};
|
|
98
99
|
}
|
|
100
|
+
if (props.collection === 'containers') {
|
|
101
|
+
return { backgroundColor: 'blue', textColor: 'blue', content: 'Container', icon: DatabaseIcon, class: 'text-blue-400' };
|
|
102
|
+
}
|
|
99
103
|
if (props.collection === 'flows') {
|
|
100
104
|
return { backgroundColor: 'teal', textColor: 'teal', content: 'Flow', icon: QueueListIcon, class: 'text-teal-400' };
|
|
101
105
|
}
|
|
102
106
|
};
|
|
103
107
|
|
|
104
108
|
const badges = [getBadge()];
|
|
105
|
-
import { HomeIcon } from '@heroicons/react/20/solid';
|
|
106
|
-
|
|
107
|
-
const pages = [
|
|
108
|
-
{ name: 'Projects', href: '#', current: false },
|
|
109
|
-
{ name: 'Project Nero', href: '#', current: true },
|
|
110
|
-
];
|
|
111
109
|
---
|
|
112
110
|
|
|
113
111
|
<VerticalSideBarLayout title="ChangeLog">
|
|
@@ -19,6 +19,7 @@ import DomainSideBar from '@components/SideBars/DomainSideBar.astro';
|
|
|
19
19
|
import ChannelSideBar from '@components/SideBars/ChannelSideBar.astro';
|
|
20
20
|
import FlowSideBar from '@components/SideBars/FlowSideBar.astro';
|
|
21
21
|
import EntitySideBar from '@components/SideBars/EntitySideBar.astro';
|
|
22
|
+
import ContainerSideBar from '@components/SideBars/ContainerSideBar.astro';
|
|
22
23
|
import CopyAsMarkdown from '@components/CopyAsMarkdown';
|
|
23
24
|
|
|
24
25
|
import {
|
|
@@ -28,9 +29,11 @@ import {
|
|
|
28
29
|
BoltIcon,
|
|
29
30
|
ChatBubbleLeftIcon,
|
|
30
31
|
MagnifyingGlassIcon,
|
|
32
|
+
MapIcon,
|
|
33
|
+
ClockIcon,
|
|
31
34
|
} from '@heroicons/react/24/outline';
|
|
32
35
|
import { ArrowsRightLeftIcon } from '@heroicons/react/20/solid';
|
|
33
|
-
import { Box, Boxes, SquarePenIcon } from 'lucide-react';
|
|
36
|
+
import { Box, Boxes, SquarePenIcon, DatabaseIcon, DatabaseZapIcon, ShieldCheckIcon } from 'lucide-react';
|
|
34
37
|
import type { CollectionTypes } from '@types';
|
|
35
38
|
|
|
36
39
|
import { render } from 'astro:content';
|
|
@@ -101,6 +104,51 @@ const getBadge = () => {
|
|
|
101
104
|
return [{ backgroundColor: 'teal', textColor: 'teal', content: 'Channel', icon: ArrowsRightLeftIcon, class: 'text-gray' }];
|
|
102
105
|
}
|
|
103
106
|
|
|
107
|
+
if (props.collection === 'containers') {
|
|
108
|
+
const badges = [];
|
|
109
|
+
const content = props.data.container_type?.charAt(0).toUpperCase() + props.data.container_type?.slice(1) || 'Database';
|
|
110
|
+
|
|
111
|
+
badges.push({ backgroundColor: 'blue', textColor: 'blue', content: content, icon: DatabaseIcon, class: 'text-gray' });
|
|
112
|
+
|
|
113
|
+
if (props.data?.technology) {
|
|
114
|
+
badges.push({
|
|
115
|
+
backgroundColor: 'indigo',
|
|
116
|
+
textColor: 'indigo',
|
|
117
|
+
content: `${props.data.technology}`,
|
|
118
|
+
icon: DatabaseZapIcon,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (props.data?.residency) {
|
|
123
|
+
badges.push({
|
|
124
|
+
backgroundColor: 'red',
|
|
125
|
+
textColor: 'red',
|
|
126
|
+
content: `Residency: ${props.data.residency}`,
|
|
127
|
+
icon: MapIcon,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (props.data?.retention) {
|
|
132
|
+
badges.push({
|
|
133
|
+
backgroundColor: 'green',
|
|
134
|
+
textColor: 'green',
|
|
135
|
+
content: `Retention: ${props.data.retention}`,
|
|
136
|
+
icon: ClockIcon,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (props.data?.access_mode) {
|
|
141
|
+
badges.push({
|
|
142
|
+
backgroundColor: 'green',
|
|
143
|
+
textColor: 'green',
|
|
144
|
+
content: `Access Mode: ${props.data.access_mode}`,
|
|
145
|
+
icon: ShieldCheckIcon,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return badges;
|
|
150
|
+
}
|
|
151
|
+
|
|
104
152
|
if (props.collection === 'entities') {
|
|
105
153
|
const entityBadges = [{ backgroundColor: 'purple', textColor: 'purple', content: 'Entity', icon: Box, class: 'text-gray' }];
|
|
106
154
|
if (props.data.aggregateRoot) {
|
|
@@ -435,6 +483,7 @@ nodeGraphs.push({
|
|
|
435
483
|
{props?.collection === 'channels' && <ChannelSideBar channel={props} />}
|
|
436
484
|
{props?.collection === 'flows' && <FlowSideBar flow={props} />}
|
|
437
485
|
{props?.collection === 'entities' && <EntitySideBar entity={props} />}
|
|
486
|
+
{props?.collection === 'containers' && <ContainerSideBar container={props} />}
|
|
438
487
|
</aside>
|
|
439
488
|
</div>
|
|
440
489
|
</main>
|
|
@@ -15,6 +15,7 @@ const services = await getCollection('services');
|
|
|
15
15
|
const domains = await getCollection('domains');
|
|
16
16
|
const flows = await getCollection('flows');
|
|
17
17
|
const channels = await getCollection('channels');
|
|
18
|
+
const containers = await getCollection('containers');
|
|
18
19
|
const entities = await getEntities();
|
|
19
20
|
export async function getStaticPaths() {
|
|
20
21
|
// Just return empty array if LLMs are not enabled
|
|
@@ -30,6 +31,7 @@ export async function getStaticPaths() {
|
|
|
30
31
|
domains,
|
|
31
32
|
flows,
|
|
32
33
|
channels,
|
|
34
|
+
containers,
|
|
33
35
|
entities,
|
|
34
36
|
};
|
|
35
37
|
const paths = Object.keys(collections).map((type) => {
|
|
@@ -16,7 +16,8 @@ type AllowedCollections =
|
|
|
16
16
|
| 'customPages'
|
|
17
17
|
| 'channels'
|
|
18
18
|
| 'entities'
|
|
19
|
-
| 'flows'
|
|
19
|
+
| 'flows'
|
|
20
|
+
| 'containers';
|
|
20
21
|
|
|
21
22
|
const events = await getCollection('events');
|
|
22
23
|
const commands = await getCollection('commands');
|
|
@@ -28,6 +29,7 @@ const users = await getCollection('users');
|
|
|
28
29
|
const entities = await getCollection('entities');
|
|
29
30
|
const channels = await getCollection('channels');
|
|
30
31
|
const flows = await getCollection('flows');
|
|
32
|
+
const containers = await getCollection('containers');
|
|
31
33
|
|
|
32
34
|
const customDocs = await getCollection('customPages');
|
|
33
35
|
|
|
@@ -46,6 +48,7 @@ export const GET: APIRoute = async ({ params, request }) => {
|
|
|
46
48
|
...users,
|
|
47
49
|
...entities,
|
|
48
50
|
...channels,
|
|
51
|
+
...containers,
|
|
49
52
|
...flows,
|
|
50
53
|
];
|
|
51
54
|
|
|
@@ -12,6 +12,8 @@ export const GET: APIRoute = async ({ params, request }) => {
|
|
|
12
12
|
const formatServiceWithLinks = (service: CollectionEntry<'services'>) => {
|
|
13
13
|
const sends = service.data.sends as unknown as CollectionEntry<'events'>[];
|
|
14
14
|
const receives = service.data.receives as unknown as CollectionEntry<'events'>[];
|
|
15
|
+
const writesTo = service.data.writesTo as unknown as CollectionEntry<'containers'>[];
|
|
16
|
+
const readsFrom = service.data.readsFrom as unknown as CollectionEntry<'containers'>[];
|
|
15
17
|
|
|
16
18
|
const sendsList =
|
|
17
19
|
sends
|
|
@@ -29,7 +31,23 @@ export const GET: APIRoute = async ({ params, request }) => {
|
|
|
29
31
|
)
|
|
30
32
|
.join('') || ' - Does not receive any messages';
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
const writesToList =
|
|
35
|
+
writesTo
|
|
36
|
+
.map(
|
|
37
|
+
(write) =>
|
|
38
|
+
` - [${write.data.name} - ${write.data.version}](${baseUrl}/docs/containers/${write.data.id}/${write.data.version}.mdx) - ${write.data.summary}`
|
|
39
|
+
)
|
|
40
|
+
.join('') || ' - Does not write to any containers';
|
|
41
|
+
|
|
42
|
+
const readsFromList =
|
|
43
|
+
readsFrom
|
|
44
|
+
.map(
|
|
45
|
+
(read) =>
|
|
46
|
+
` - [${read.data.name} - ${read.data.version}](${baseUrl}/docs/containers/${read.data.id}/${read.data.version}.mdx) - ${read.data.summary}`
|
|
47
|
+
)
|
|
48
|
+
.join('') || ' - Does not read from any containers';
|
|
49
|
+
|
|
50
|
+
return `## [${service.data.name} - ${service.data.version}](${baseUrl}/docs/services/${service.data.id}/${service.data.version}.mdx) - ${service.data.summary}\n ## Sends\n${sendsList}\n ## Receives\n${receivesList}\n ## Writes to\n${writesToList}\n ## Reads from\n${readsFromList} \n`;
|
|
33
51
|
};
|
|
34
52
|
|
|
35
53
|
const content = ['# Services \n\n', services.map((item) => formatServiceWithLinks(item)).join('\n')].join('\n');
|
|
@@ -17,6 +17,7 @@ const users = await getCollection('users');
|
|
|
17
17
|
|
|
18
18
|
const flows = await getCollection('flows');
|
|
19
19
|
const channels = await getCollection('channels');
|
|
20
|
+
const containers = await getCollection('containers');
|
|
20
21
|
|
|
21
22
|
const entities = await getCollection('entities');
|
|
22
23
|
|
|
@@ -115,6 +116,8 @@ export const GET: APIRoute = async ({ params, request }) => {
|
|
|
115
116
|
)
|
|
116
117
|
.join(''),
|
|
117
118
|
...(Object.keys(ubiquitousLanguages).length > 0 ? ['## Ubiquitous Language', renderUbiquitousLanguages(baseUrl)] : []),
|
|
119
|
+
'\n## Containers (Databases, External Systems)',
|
|
120
|
+
containers.map((item) => formatVersionedItem(item, 'containers')).join('\n'),
|
|
118
121
|
'\n## Entities',
|
|
119
122
|
renderEntities(baseUrl),
|
|
120
123
|
'\n## Teams',
|
|
@@ -19,7 +19,7 @@ export class Page extends HybridPage {
|
|
|
19
19
|
flows: getFlows,
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
const itemTypes: PageTypesWithFlows[] = ['events', 'commands', 'queries', 'services', 'domains', 'flows'];
|
|
22
|
+
const itemTypes: PageTypesWithFlows[] = ['events', 'commands', 'queries', 'services', 'domains', 'flows', 'containers'];
|
|
23
23
|
const allItems = await Promise.all(itemTypes.map((type) => loaders[type]()));
|
|
24
24
|
|
|
25
25
|
return allItems.flatMap((items, index) =>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { HybridPage } from '@utils/page-loaders/hybrid-page';
|
|
2
|
+
import { isAuthEnabled } from '@utils/feature';
|
|
3
|
+
import { getServices, type Service } from '@utils/collections/services';
|
|
4
|
+
|
|
5
|
+
const serviceHasData = (service: Service) => {
|
|
6
|
+
return service.data.writesTo?.length || 0 > 0 || service.data.readsFrom?.length || 0 > 0;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export class Page extends HybridPage {
|
|
10
|
+
static async getStaticPaths(): Promise<Array<{ params: any; props: any }>> {
|
|
11
|
+
if (isAuthEnabled()) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const services = await getServices();
|
|
16
|
+
const servicesWithData = services.filter((service) => serviceHasData(service));
|
|
17
|
+
|
|
18
|
+
return servicesWithData.flatMap((service) => {
|
|
19
|
+
return {
|
|
20
|
+
params: {
|
|
21
|
+
type: 'services',
|
|
22
|
+
id: service.data.id,
|
|
23
|
+
version: service.data.version,
|
|
24
|
+
},
|
|
25
|
+
props: {
|
|
26
|
+
type: 'service',
|
|
27
|
+
...service,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
protected static async fetchData(params: any) {
|
|
34
|
+
const { id, version } = params;
|
|
35
|
+
|
|
36
|
+
if (!id || !version) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Get all items of the specified type
|
|
41
|
+
const items = await getServices();
|
|
42
|
+
|
|
43
|
+
// Find the specific item by id and version, and only if it has entities
|
|
44
|
+
const item = items.find((i) => i.data.id === id && i.data.version === version && serviceHasData(i));
|
|
45
|
+
|
|
46
|
+
if (!item) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return item;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
protected static createNotFoundResponse(): Response {
|
|
54
|
+
return new Response(null, {
|
|
55
|
+
status: 404,
|
|
56
|
+
statusText: 'Service data page not found',
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static get clientAuthScript(): string {
|
|
61
|
+
if (!isAuthEnabled()) {
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return `
|
|
66
|
+
if (typeof window !== 'undefined' && !import.meta.env.SSR) {
|
|
67
|
+
fetch('/api/auth/session')
|
|
68
|
+
.then(res => res.json())
|
|
69
|
+
.then(session => {
|
|
70
|
+
if (!session?.user) {
|
|
71
|
+
window.location.href = '/auth/login?callbackUrl=' + encodeURIComponent(window.location.pathname);
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
.catch(() => {
|
|
75
|
+
window.location.href = '/auth/login?callbackUrl=' + encodeURIComponent(window.location.pathname);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
import NodeGraph from '@components/MDX/NodeGraph/NodeGraph.astro';
|
|
3
|
+
import VisualiserLayout from '@layouts/VisualiserLayout.astro';
|
|
4
|
+
import { buildUrl } from '@utils/url-builder';
|
|
5
|
+
import { ClientRouter } from 'astro:transitions';
|
|
6
|
+
|
|
7
|
+
import { Page } from './_index.data';
|
|
8
|
+
|
|
9
|
+
export const prerender = Page.prerender;
|
|
10
|
+
export const getStaticPaths = Page.getStaticPaths;
|
|
11
|
+
|
|
12
|
+
// Get data
|
|
13
|
+
const props = await Page.getData(Astro);
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
data: { id },
|
|
17
|
+
collection,
|
|
18
|
+
} = props;
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
<VisualiserLayout title={`Visualiser | ${props.data.name} (${props.collection})`} description={props.data.summary}>
|
|
22
|
+
<div class="bg-gray-100/50 m-4">
|
|
23
|
+
<div class="h-[calc(100vh-130px)] w-full relative border border-gray-200" id={`${id}-portal`} transition:animate="fade"></div>
|
|
24
|
+
<NodeGraph
|
|
25
|
+
id={id}
|
|
26
|
+
collection={`${collection}-containers`}
|
|
27
|
+
title={`${props.data.name} (v${props.data.version}) - Data`}
|
|
28
|
+
mode="full"
|
|
29
|
+
linkTo="visualiser"
|
|
30
|
+
version={props.data.version}
|
|
31
|
+
linksToVisualiser={false}
|
|
32
|
+
href={{
|
|
33
|
+
label: `Open documentation for ${props.data.name} v${props.data.version}`,
|
|
34
|
+
url: buildUrl(`/docs/${props.collection}/${props.data.id}/${props.data.version}`),
|
|
35
|
+
}}
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
<ClientRouter />
|
|
39
|
+
</VisualiserLayout>
|
|
40
|
+
|
|
41
|
+
<script define:vars={{ id }}>
|
|
42
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
43
|
+
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
44
|
+
const params = Object.fromEntries(urlSearchParams.entries());
|
|
45
|
+
const embeded = params.embed === 'true' ? true : false;
|
|
46
|
+
const viewport = document.getElementById(`${id}-portal`);
|
|
47
|
+
|
|
48
|
+
if (embeded) {
|
|
49
|
+
viewport.style.height = 'calc(100vh - 30px)';
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
</script>
|
|
@@ -5,13 +5,20 @@ import { getEvents } from '@utils/events';
|
|
|
5
5
|
import { getCommands } from '@utils/commands';
|
|
6
6
|
import { getServices } from '@utils/collections/services';
|
|
7
7
|
import { getDomains } from '@utils/collections/domains';
|
|
8
|
+
import { getContainers } from '@utils/collections/containers';
|
|
8
9
|
import type { CollectionEntry } from 'astro:content';
|
|
9
10
|
import type { CollectionTypes } from '@types';
|
|
10
11
|
|
|
11
12
|
export async function getStaticPaths() {
|
|
12
|
-
const [events, commands, services, domains] = await Promise.all([
|
|
13
|
+
const [events, commands, services, domains, containers] = await Promise.all([
|
|
14
|
+
getEvents(),
|
|
15
|
+
getCommands(),
|
|
16
|
+
getServices(),
|
|
17
|
+
getDomains(),
|
|
18
|
+
getContainers(),
|
|
19
|
+
]);
|
|
13
20
|
|
|
14
|
-
const resources = [...domains, ...events, ...services, ...commands];
|
|
21
|
+
const resources = [...domains, ...events, ...services, ...commands, ...containers];
|
|
15
22
|
const resourcesWithVisualiserEnabled = resources.filter((resource) => resource.data.visualiser !== false);
|
|
16
23
|
|
|
17
24
|
const buildPages = (collection: CollectionEntry<CollectionTypes>[]) => {
|
|
@@ -1,4 +1,22 @@
|
|
|
1
|
-
export type CollectionTypes =
|
|
1
|
+
export type CollectionTypes =
|
|
2
|
+
| 'commands'
|
|
3
|
+
| 'events'
|
|
4
|
+
| 'queries'
|
|
5
|
+
| 'domains'
|
|
6
|
+
| 'services'
|
|
7
|
+
| 'flows'
|
|
8
|
+
| 'channels'
|
|
9
|
+
| 'entities'
|
|
10
|
+
| 'containers';
|
|
2
11
|
export type CollectionMessageTypes = 'commands' | 'events' | 'queries';
|
|
3
12
|
export type CollectionUserTypes = 'users';
|
|
4
|
-
export type PageTypes =
|
|
13
|
+
export type PageTypes =
|
|
14
|
+
| 'events'
|
|
15
|
+
| 'commands'
|
|
16
|
+
| 'queries'
|
|
17
|
+
| 'services'
|
|
18
|
+
| 'domains'
|
|
19
|
+
| 'channels'
|
|
20
|
+
| 'flows'
|
|
21
|
+
| 'entities'
|
|
22
|
+
| 'containers';
|