@eventcatalog/core 3.7.2 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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-O6SRHGZ7.js → chunk-4EJDLNIX.js} +1 -1
- package/dist/{chunk-WAX3S32H.js → chunk-EG36OTR7.js} +1 -1
- package/dist/{chunk-GQZVIS3Z.js → chunk-GITARDPK.js} +1 -1
- package/dist/{chunk-7CTNGTBB.js → chunk-IEEU454Z.js} +1 -1
- package/dist/{chunk-M7EPRGHR.js → chunk-ZIG6J4R2.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/ChatPanel/ChatPanel.tsx +13 -1
- package/eventcatalog/src/components/Grids/DomainGrid.tsx +109 -6
- package/eventcatalog/src/components/Grids/utils.tsx +10 -1
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +2 -0
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.tsx +4 -0
- package/eventcatalog/src/components/MDX/NodeGraph/Nodes/DataProduct.tsx +132 -0
- package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +29 -2
- package/eventcatalog/src/components/SchemaExplorer/types.ts +5 -1
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +3 -0
- package/eventcatalog/src/components/SideNav/NestedSideBar/utils.ts +1 -0
- package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +23 -1
- package/eventcatalog/src/components/Tables/Discover/columns.tsx +62 -0
- package/eventcatalog/src/content.config.ts +34 -0
- package/eventcatalog/src/enterprise/ai/chat-api.ts +26 -0
- package/eventcatalog/src/enterprise/custom-documentation/utils/custom-docs.ts +1 -1
- package/eventcatalog/src/enterprise/tools/catalog-tools.ts +169 -2
- package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -1
- package/eventcatalog/src/pages/discover/[type]/index.astro +57 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +5 -1
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/_index.data.ts +27 -3
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +74 -25
- package/eventcatalog/src/pages/schemas/explorer/_index.data.ts +55 -1
- package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/_index.data.ts +10 -1
- package/eventcatalog/src/stores/sidebar-store/builders/container.ts +23 -16
- package/eventcatalog/src/stores/sidebar-store/builders/data-product.ts +130 -0
- package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +11 -0
- package/eventcatalog/src/stores/sidebar-store/state.ts +68 -13
- package/eventcatalog/src/styles/theme.css +4 -0
- package/eventcatalog/src/styles/themes/forest.css +4 -0
- package/eventcatalog/src/styles/themes/ocean.css +4 -0
- package/eventcatalog/src/styles/themes/sapphire.css +4 -0
- package/eventcatalog/src/styles/themes/sunset.css +4 -0
- package/eventcatalog/src/types/index.ts +4 -2
- package/eventcatalog/src/utils/collections/commands.ts +11 -29
- package/eventcatalog/src/utils/collections/containers.ts +25 -1
- package/eventcatalog/src/utils/collections/data-products.ts +85 -0
- package/eventcatalog/src/utils/collections/domains.ts +28 -10
- package/eventcatalog/src/utils/collections/events.ts +11 -29
- package/eventcatalog/src/utils/collections/icons.ts +5 -0
- package/eventcatalog/src/utils/collections/messages.ts +68 -0
- package/eventcatalog/src/utils/collections/queries.ts +11 -29
- package/eventcatalog/src/utils/collections/util.ts +11 -2
- package/eventcatalog/src/utils/node-graphs/container-node-graph.ts +91 -3
- package/eventcatalog/src/utils/node-graphs/data-products-node-graph.ts +225 -0
- package/eventcatalog/src/utils/node-graphs/domains-node-graph.ts +28 -2
- package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +74 -20
- package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
- package/package.json +2 -2
|
@@ -7,6 +7,7 @@ import { getFlows } from '@utils/collections/flows';
|
|
|
7
7
|
import { getUsers } from '@utils/collections/users';
|
|
8
8
|
import { getTeams } from '@utils/collections/teams';
|
|
9
9
|
import { getDiagrams } from '@utils/collections/diagrams';
|
|
10
|
+
import { getDataProducts } from '@utils/collections/data-products';
|
|
10
11
|
import { buildUrl } from '@utils/url-builder';
|
|
11
12
|
import type { NavigationData, NavNode, ChildRef } from './builders/shared';
|
|
12
13
|
import { buildDomainNode } from './builders/domain';
|
|
@@ -14,6 +15,7 @@ import { buildServiceNode } from './builders/service';
|
|
|
14
15
|
import { buildMessageNode } from './builders/message';
|
|
15
16
|
import { buildContainerNode } from './builders/container';
|
|
16
17
|
import { buildFlowNode } from './builders/flow';
|
|
18
|
+
import { buildDataProductNode } from './builders/data-product';
|
|
17
19
|
import config from '@config';
|
|
18
20
|
import { getDesigns } from '@utils/collections/designs';
|
|
19
21
|
import { getChannels } from '@utils/collections/channels';
|
|
@@ -31,19 +33,31 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
31
33
|
return memoryCache;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
const [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
const [
|
|
37
|
+
domains,
|
|
38
|
+
services,
|
|
39
|
+
{ events, commands, queries },
|
|
40
|
+
containers,
|
|
41
|
+
flows,
|
|
42
|
+
users,
|
|
43
|
+
teams,
|
|
44
|
+
designs,
|
|
45
|
+
channels,
|
|
46
|
+
diagrams,
|
|
47
|
+
dataProducts,
|
|
48
|
+
] = await Promise.all([
|
|
49
|
+
getDomains({ getAllVersions: false, includeServicesInSubdomains: false }),
|
|
50
|
+
getServices({ getAllVersions: false }),
|
|
51
|
+
getMessages({ getAllVersions: false }),
|
|
52
|
+
getContainers({ getAllVersions: false }),
|
|
53
|
+
getFlows({ getAllVersions: false }),
|
|
54
|
+
getUsers(),
|
|
55
|
+
getTeams(),
|
|
56
|
+
getDesigns(),
|
|
57
|
+
getChannels({ getAllVersions: false }),
|
|
58
|
+
getDiagrams({ getAllVersions: false }),
|
|
59
|
+
getDataProducts({ getAllVersions: false }),
|
|
60
|
+
]);
|
|
47
61
|
|
|
48
62
|
// Calculate derived lists to avoid extra fetches
|
|
49
63
|
const allSubDomainIds = new Set(domains.flatMap((d) => (d.data.domains || []).map((sd: any) => sd.data.id)));
|
|
@@ -60,6 +74,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
60
74
|
flows,
|
|
61
75
|
containers,
|
|
62
76
|
diagrams,
|
|
77
|
+
dataProducts,
|
|
63
78
|
};
|
|
64
79
|
|
|
65
80
|
// Process all domains with their owners first (async)
|
|
@@ -166,6 +181,35 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
166
181
|
{} as Record<string, NavNode | string>
|
|
167
182
|
);
|
|
168
183
|
|
|
184
|
+
// Get owners for data products
|
|
185
|
+
const dataProductWithOwners = await Promise.all(
|
|
186
|
+
dataProducts.map(async (dataProduct) => {
|
|
187
|
+
const owners = await Promise.all((dataProduct.data.owners || []).map((owner) => getOwner(owner)));
|
|
188
|
+
return { dataProduct, owners: owners.filter((o) => o !== undefined) };
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
const dataProductContext = {
|
|
193
|
+
events,
|
|
194
|
+
commands,
|
|
195
|
+
queries,
|
|
196
|
+
services,
|
|
197
|
+
containers,
|
|
198
|
+
channels,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const dataProductNodes = dataProductWithOwners.reduce(
|
|
202
|
+
(acc, { dataProduct, owners }) => {
|
|
203
|
+
const versionedKey = `data-product:${dataProduct.data.id}:${dataProduct.data.version}`;
|
|
204
|
+
acc[versionedKey] = buildDataProductNode(dataProduct, owners, dataProductContext);
|
|
205
|
+
if (dataProduct.data.latestVersion === dataProduct.data.version) {
|
|
206
|
+
acc[`data-product:${dataProduct.data.id}`] = versionedKey;
|
|
207
|
+
}
|
|
208
|
+
return acc;
|
|
209
|
+
},
|
|
210
|
+
{} as Record<string, NavNode | string>
|
|
211
|
+
);
|
|
212
|
+
|
|
169
213
|
const designNodes = designs.reduce(
|
|
170
214
|
(acc, design) => {
|
|
171
215
|
acc[`design:${design.data.id}`] = {
|
|
@@ -285,6 +329,13 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
285
329
|
pages: containers.map((container) => `container:${container.data.id}:${container.data.version}`),
|
|
286
330
|
});
|
|
287
331
|
|
|
332
|
+
const dataProductsList = createLeaf(dataProducts, {
|
|
333
|
+
type: 'item',
|
|
334
|
+
title: 'Data Products',
|
|
335
|
+
icon: 'Package',
|
|
336
|
+
pages: dataProducts.map((dataProduct) => `data-product:${dataProduct.data.id}:${dataProduct.data.version}`),
|
|
337
|
+
});
|
|
338
|
+
|
|
288
339
|
const designsList = createLeaf(designs, {
|
|
289
340
|
type: 'item',
|
|
290
341
|
title: 'Designs',
|
|
@@ -346,6 +397,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
346
397
|
'list:channels',
|
|
347
398
|
'list:flows',
|
|
348
399
|
'list:containers',
|
|
400
|
+
'list:data-products',
|
|
349
401
|
'list:designs',
|
|
350
402
|
'list:people',
|
|
351
403
|
];
|
|
@@ -356,6 +408,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
356
408
|
channelList,
|
|
357
409
|
flowsList,
|
|
358
410
|
containersList,
|
|
411
|
+
dataProductsList,
|
|
359
412
|
designsList,
|
|
360
413
|
peopleList,
|
|
361
414
|
];
|
|
@@ -381,6 +434,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
381
434
|
...(messagesList ? { 'list:messages': messagesList as NavNode } : {}),
|
|
382
435
|
...(flowsList ? { 'list:flows': flowsList } : {}),
|
|
383
436
|
...(containersList ? { 'list:containers': containersList } : {}),
|
|
437
|
+
...(dataProductsList ? { 'list:data-products': dataProductsList } : {}),
|
|
384
438
|
...(designsList ? { 'list:designs': designsList } : {}),
|
|
385
439
|
...(teamsList ? { 'list:teams': teamsList } : {}),
|
|
386
440
|
...(usersList ? { 'list:users': usersList } : {}),
|
|
@@ -415,6 +469,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
415
469
|
...messageNodes,
|
|
416
470
|
...channelNodes,
|
|
417
471
|
...containerNodes,
|
|
472
|
+
...dataProductNodes,
|
|
418
473
|
...flowNodes,
|
|
419
474
|
...userNodes,
|
|
420
475
|
...teamNodes,
|
|
@@ -103,6 +103,8 @@
|
|
|
103
103
|
--ec-badge-design-text: 15 118 110; /* teal-700 */
|
|
104
104
|
--ec-badge-channel-bg: 224 231 255; /* indigo-100 */
|
|
105
105
|
--ec-badge-channel-text: 67 56 202; /* indigo-700 */
|
|
106
|
+
--ec-badge-data-product-bg: 219 234 254; /* blue-100 */
|
|
107
|
+
--ec-badge-data-product-text: 30 64 175; /* blue-800 */
|
|
106
108
|
--ec-badge-default-bg: 243 244 246; /* gray-100 */
|
|
107
109
|
--ec-badge-default-text: 75 85 99; /* gray-600 */
|
|
108
110
|
}
|
|
@@ -199,6 +201,8 @@
|
|
|
199
201
|
--ec-badge-design-text: 94 234 212; /* teal-300 */
|
|
200
202
|
--ec-badge-channel-bg: 49 46 129 / 0.3; /* indigo-900/30 */
|
|
201
203
|
--ec-badge-channel-text: 165 180 252; /* indigo-300 */
|
|
204
|
+
--ec-badge-data-product-bg: 30 64 175 / 0.3; /* blue-800/30 */
|
|
205
|
+
--ec-badge-data-product-text: 147 197 253; /* blue-300 */
|
|
202
206
|
--ec-badge-default-bg: 63 63 70 / 0.3; /* zinc-700/30 */
|
|
203
207
|
--ec-badge-default-text: 212 212 216; /* zinc-300 */
|
|
204
208
|
}
|
|
@@ -97,6 +97,8 @@
|
|
|
97
97
|
--ec-badge-design-text: 22 101 52; /* green-800 */
|
|
98
98
|
--ec-badge-channel-bg: 224 231 255; /* indigo-100 */
|
|
99
99
|
--ec-badge-channel-text: 67 56 202; /* indigo-700 */
|
|
100
|
+
--ec-badge-data-product-bg: 219 234 254; /* blue-100 */
|
|
101
|
+
--ec-badge-data-product-text: 30 64 175; /* blue-800 */
|
|
100
102
|
--ec-badge-default-bg: 240 253 244; /* green-50 */
|
|
101
103
|
--ec-badge-default-text: 75 85 99; /* gray-600 */
|
|
102
104
|
}
|
|
@@ -188,6 +190,8 @@
|
|
|
188
190
|
--ec-badge-design-text: 134 239 172; /* green-300 */
|
|
189
191
|
--ec-badge-channel-bg: 49 46 129 / 0.3; /* indigo-900/30 */
|
|
190
192
|
--ec-badge-channel-text: 165 180 252; /* indigo-300 */
|
|
193
|
+
--ec-badge-data-product-bg: 30 64 175 / 0.3; /* blue-800/30 */
|
|
194
|
+
--ec-badge-data-product-text: 147 197 253; /* blue-300 */
|
|
191
195
|
--ec-badge-default-bg: 55 65 81 / 0.3; /* gray-700/30 */
|
|
192
196
|
--ec-badge-default-text: 209 213 219; /* gray-300 */
|
|
193
197
|
}
|
|
@@ -97,6 +97,8 @@
|
|
|
97
97
|
--ec-badge-design-text: 15 118 110; /* teal-700 */
|
|
98
98
|
--ec-badge-channel-bg: 224 231 255; /* indigo-100 */
|
|
99
99
|
--ec-badge-channel-text: 67 56 202; /* indigo-700 */
|
|
100
|
+
--ec-badge-data-product-bg: 219 234 254; /* blue-100 */
|
|
101
|
+
--ec-badge-data-product-text: 30 64 175; /* blue-800 */
|
|
100
102
|
--ec-badge-default-bg: 240 253 250; /* teal-50 */
|
|
101
103
|
--ec-badge-default-text: 71 85 105; /* slate-600 */
|
|
102
104
|
}
|
|
@@ -193,6 +195,8 @@
|
|
|
193
195
|
--ec-badge-design-text: 94 234 212; /* teal-300 */
|
|
194
196
|
--ec-badge-channel-bg: 49 46 129 / 0.3; /* indigo-900/30 */
|
|
195
197
|
--ec-badge-channel-text: 165 180 252; /* indigo-300 */
|
|
198
|
+
--ec-badge-data-product-bg: 30 64 175 / 0.3; /* blue-800/30 */
|
|
199
|
+
--ec-badge-data-product-text: 147 197 253; /* blue-300 */
|
|
196
200
|
--ec-badge-default-bg: 51 65 85 / 0.3; /* slate-700/30 */
|
|
197
201
|
--ec-badge-default-text: 203 213 225; /* slate-300 */
|
|
198
202
|
}
|
|
@@ -97,6 +97,8 @@
|
|
|
97
97
|
--ec-badge-design-text: 37 99 235; /* blue-600 */
|
|
98
98
|
--ec-badge-channel-bg: 224 231 255; /* indigo-100 */
|
|
99
99
|
--ec-badge-channel-text: 67 56 202; /* indigo-700 */
|
|
100
|
+
--ec-badge-data-product-bg: 219 234 254; /* blue-100 */
|
|
101
|
+
--ec-badge-data-product-text: 30 64 175; /* blue-800 */
|
|
100
102
|
--ec-badge-default-bg: 239 246 255; /* blue-50 */
|
|
101
103
|
--ec-badge-default-text: 71 85 105; /* slate-600 */
|
|
102
104
|
}
|
|
@@ -188,6 +190,8 @@
|
|
|
188
190
|
--ec-badge-design-text: 147 197 253; /* blue-300 */
|
|
189
191
|
--ec-badge-channel-bg: 49 46 129 / 0.3; /* indigo-900/30 */
|
|
190
192
|
--ec-badge-channel-text: 165 180 252; /* indigo-300 */
|
|
193
|
+
--ec-badge-data-product-bg: 30 64 175 / 0.3; /* blue-800/30 */
|
|
194
|
+
--ec-badge-data-product-text: 147 197 253; /* blue-300 */
|
|
191
195
|
--ec-badge-default-bg: 51 65 85 / 0.3; /* slate-700/30 */
|
|
192
196
|
--ec-badge-default-text: 203 213 225; /* slate-300 */
|
|
193
197
|
}
|
|
@@ -97,6 +97,8 @@
|
|
|
97
97
|
--ec-badge-design-text: 234 88 12; /* orange-600 */
|
|
98
98
|
--ec-badge-channel-bg: 224 231 255; /* indigo-100 */
|
|
99
99
|
--ec-badge-channel-text: 67 56 202; /* indigo-700 */
|
|
100
|
+
--ec-badge-data-product-bg: 219 234 254; /* blue-100 */
|
|
101
|
+
--ec-badge-data-product-text: 30 64 175; /* blue-800 */
|
|
100
102
|
--ec-badge-default-bg: 255 247 237; /* orange-50 */
|
|
101
103
|
--ec-badge-default-text: 82 82 82; /* neutral-600 */
|
|
102
104
|
}
|
|
@@ -188,6 +190,8 @@
|
|
|
188
190
|
--ec-badge-design-text: 253 186 116; /* orange-300 */
|
|
189
191
|
--ec-badge-channel-bg: 49 46 129 / 0.3; /* indigo-900/30 */
|
|
190
192
|
--ec-badge-channel-text: 165 180 252; /* indigo-300 */
|
|
193
|
+
--ec-badge-data-product-bg: 30 64 175 / 0.3; /* blue-800/30 */
|
|
194
|
+
--ec-badge-data-product-text: 147 197 253; /* blue-300 */
|
|
191
195
|
--ec-badge-default-bg: 64 64 64 / 0.3; /* neutral-700/30 */
|
|
192
196
|
--ec-badge-default-text: 212 212 212; /* neutral-300 */
|
|
193
197
|
}
|
|
@@ -8,7 +8,8 @@ export type CollectionTypes =
|
|
|
8
8
|
| 'channels'
|
|
9
9
|
| 'entities'
|
|
10
10
|
| 'containers'
|
|
11
|
-
| 'diagrams'
|
|
11
|
+
| 'diagrams'
|
|
12
|
+
| 'data-products';
|
|
12
13
|
export type CollectionMessageTypes = 'commands' | 'events' | 'queries';
|
|
13
14
|
export type CollectionUserTypes = 'users';
|
|
14
15
|
export type PageTypes =
|
|
@@ -21,7 +22,8 @@ export type PageTypes =
|
|
|
21
22
|
| 'flows'
|
|
22
23
|
| 'entities'
|
|
23
24
|
| 'containers'
|
|
24
|
-
| 'diagrams'
|
|
25
|
+
| 'diagrams'
|
|
26
|
+
| 'data-products';
|
|
25
27
|
|
|
26
28
|
export type TableConfiguration = {
|
|
27
29
|
columns: {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { getCollection } from 'astro:content';
|
|
2
2
|
import type { CollectionEntry } from 'astro:content';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
import { createVersionedMap
|
|
4
|
+
import { createVersionedMap } from './util';
|
|
5
|
+
import { hydrateProducersAndConsumers } from './messages';
|
|
5
6
|
import utils from '@eventcatalog/sdk';
|
|
6
7
|
|
|
7
8
|
const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd();
|
|
@@ -35,10 +36,11 @@ export const getCommands = async ({ getAllVersions = true, hydrateServices = tru
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
// 1. Fetch collections in parallel
|
|
38
|
-
const [allCommands, allServices, allChannels] = await Promise.all([
|
|
39
|
+
const [allCommands, allServices, allChannels, allDataProducts] = await Promise.all([
|
|
39
40
|
getCollection('commands'),
|
|
40
41
|
getCollection('services'),
|
|
41
42
|
getCollection('channels'),
|
|
43
|
+
getCollection('data-products'),
|
|
42
44
|
]);
|
|
43
45
|
|
|
44
46
|
// 2. Build optimized maps
|
|
@@ -61,33 +63,13 @@ export const getCommands = async ({ getAllVersions = true, hydrateServices = tru
|
|
|
61
63
|
const latestVersion = commandVersions[0]?.data.version || command.data.version;
|
|
62
64
|
const versions = commandVersions.map((e) => e.data.version);
|
|
63
65
|
|
|
64
|
-
// Find
|
|
65
|
-
const producers =
|
|
66
|
-
.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
})
|
|
72
|
-
)
|
|
73
|
-
.map((service) => {
|
|
74
|
-
if (!hydrateServices) return { id: service.data.id, version: service.data.version };
|
|
75
|
-
return service;
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// Find Consumers (Services that receive this command)
|
|
79
|
-
const consumers = allServices
|
|
80
|
-
.filter((service) =>
|
|
81
|
-
service.data.receives?.some((item) => {
|
|
82
|
-
if (item.id !== command.data.id) return false;
|
|
83
|
-
if (item.version === 'latest' || item.version === undefined) return command.data.version === latestVersion;
|
|
84
|
-
return satisfies(command.data.version, item.version);
|
|
85
|
-
})
|
|
86
|
-
)
|
|
87
|
-
.map((service) => {
|
|
88
|
-
if (!hydrateServices) return { id: service.data.id, version: service.data.version };
|
|
89
|
-
return service;
|
|
90
|
-
});
|
|
66
|
+
// Find producers and consumers (services + data products)
|
|
67
|
+
const { producers, consumers } = hydrateProducersAndConsumers({
|
|
68
|
+
message: { data: { ...command.data, latestVersion } },
|
|
69
|
+
services: allServices,
|
|
70
|
+
dataProducts: allDataProducts,
|
|
71
|
+
hydrate: hydrateServices,
|
|
72
|
+
});
|
|
91
73
|
|
|
92
74
|
// Find Channels
|
|
93
75
|
const messageChannels = command.data.channels || [];
|
|
@@ -32,7 +32,11 @@ export const getContainers = async ({ getAllVersions = true }: Props = {}): Prom
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// 1. Fetch collections in parallel
|
|
35
|
-
const [allContainers, allServices] = await Promise.all([
|
|
35
|
+
const [allContainers, allServices, allDataProducts] = await Promise.all([
|
|
36
|
+
getCollection('containers'),
|
|
37
|
+
getCollection('services'),
|
|
38
|
+
getCollection('data-products'),
|
|
39
|
+
]);
|
|
36
40
|
|
|
37
41
|
// 2. Build optimized maps
|
|
38
42
|
const containerMap = createVersionedMap(allContainers);
|
|
@@ -72,6 +76,24 @@ export const getContainers = async ({ getAllVersions = true }: Props = {}): Prom
|
|
|
72
76
|
});
|
|
73
77
|
});
|
|
74
78
|
|
|
79
|
+
// Find Data Products that write to this container (have it in outputs)
|
|
80
|
+
const dataProductsThatWriteToContainer = allDataProducts.filter((dataProduct) => {
|
|
81
|
+
return dataProduct.data?.outputs?.some((item) => {
|
|
82
|
+
if (item.id !== container.data.id) return false;
|
|
83
|
+
if (item.version === 'latest' || item.version === undefined) return container.data.version === latestVersion;
|
|
84
|
+
return satisfies(container.data.version, item.version);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Find Data Products that read from this container (have it in inputs)
|
|
89
|
+
const dataProductsThatReadFromContainer = allDataProducts.filter((dataProduct) => {
|
|
90
|
+
return dataProduct.data?.inputs?.some((item) => {
|
|
91
|
+
if (item.id !== container.data.id) return false;
|
|
92
|
+
if (item.version === 'latest' || item.version === undefined) return container.data.version === latestVersion;
|
|
93
|
+
return satisfies(container.data.version, item.version);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
75
97
|
// Combine references
|
|
76
98
|
const servicesThatReferenceContainer = [...new Set([...servicesThatWriteToContainer, ...servicesThatReadFromContainer])];
|
|
77
99
|
|
|
@@ -91,6 +113,8 @@ export const getContainers = async ({ getAllVersions = true }: Props = {}): Prom
|
|
|
91
113
|
services: servicesThatReferenceContainer,
|
|
92
114
|
servicesThatWriteToContainer,
|
|
93
115
|
servicesThatReadFromContainer,
|
|
116
|
+
dataProductsThatWriteToContainer,
|
|
117
|
+
dataProductsThatReadFromContainer,
|
|
94
118
|
},
|
|
95
119
|
catalog: {
|
|
96
120
|
path: path.join(container.collection, container.id.replace('/index.mdx', '')),
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { getCollection } from 'astro:content';
|
|
2
|
+
import type { CollectionEntry } from 'astro:content';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { createVersionedMap, satisfies } from './util';
|
|
5
|
+
|
|
6
|
+
const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd();
|
|
7
|
+
|
|
8
|
+
export type DataProduct = CollectionEntry<'data-products'> & {
|
|
9
|
+
catalog: {
|
|
10
|
+
path: string;
|
|
11
|
+
filePath: string;
|
|
12
|
+
type: string;
|
|
13
|
+
publicPath: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
interface Props {
|
|
18
|
+
getAllVersions?: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// cache for build time
|
|
22
|
+
let memoryCache: Record<string, DataProduct[]> = {};
|
|
23
|
+
|
|
24
|
+
export const getDataProducts = async ({ getAllVersions = true }: Props = {}): Promise<DataProduct[]> => {
|
|
25
|
+
// console.time('✅ New getEntities');
|
|
26
|
+
const cacheKey = getAllVersions ? 'allVersions' : 'currentVersions';
|
|
27
|
+
|
|
28
|
+
if (memoryCache[cacheKey] && memoryCache[cacheKey].length > 0) {
|
|
29
|
+
// console.timeEnd('✅ New getEntities');
|
|
30
|
+
return memoryCache[cacheKey];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 1. Fetch collections in parallel
|
|
34
|
+
const [allDataProducts, allDomains] = await Promise.all([getCollection('data-products'), getCollection('domains')]);
|
|
35
|
+
|
|
36
|
+
// 2. Build optimized maps
|
|
37
|
+
const dataProductMap = createVersionedMap(allDataProducts);
|
|
38
|
+
|
|
39
|
+
// 3. Enrich data products
|
|
40
|
+
const processedDataProducts = await Promise.all(
|
|
41
|
+
allDataProducts.map(async (dataProduct) => {
|
|
42
|
+
// Version info
|
|
43
|
+
const dataProductVersions = dataProductMap.get(dataProduct.data.id) || [];
|
|
44
|
+
const latestVersion = dataProductVersions[0]?.data.version || dataProduct.data.version;
|
|
45
|
+
const versions = dataProductVersions.map((e) => e.data.version);
|
|
46
|
+
|
|
47
|
+
// Find Domains that reference this data product
|
|
48
|
+
const domainsThatReferenceDataProduct = allDomains.filter((domain) =>
|
|
49
|
+
domain.data['data-products']?.some((item) => {
|
|
50
|
+
if (item.id !== dataProduct.data.id) return false;
|
|
51
|
+
if (item.version === 'latest' || item.version === undefined) return dataProduct.data.version === latestVersion;
|
|
52
|
+
return satisfies(dataProduct.data.version, item.version);
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const dataProductFolderName = dataProduct.id.replace('/index.mdx', '');
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
...dataProduct,
|
|
60
|
+
data: {
|
|
61
|
+
...dataProduct.data,
|
|
62
|
+
versions,
|
|
63
|
+
latestVersion,
|
|
64
|
+
domains: domainsThatReferenceDataProduct,
|
|
65
|
+
},
|
|
66
|
+
catalog: {
|
|
67
|
+
path: path.join(dataProduct.collection, dataProductFolderName),
|
|
68
|
+
filePath: path.join(process.cwd(), 'src', 'catalog-files', dataProduct.collection, dataProductFolderName),
|
|
69
|
+
publicPath: path.join('/generated', dataProduct.collection, dataProductFolderName),
|
|
70
|
+
type: 'dataProduct',
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// order them by the name of the data product
|
|
77
|
+
processedDataProducts.sort((a, b) => {
|
|
78
|
+
return (a.data.name || a.data.id).localeCompare(b.data.name || b.data.id);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
memoryCache[cacheKey] = processedDataProducts;
|
|
82
|
+
// console.timeEnd('✅ New getDataProducts');
|
|
83
|
+
|
|
84
|
+
return processedDataProducts as DataProduct[];
|
|
85
|
+
};
|
|
@@ -80,16 +80,18 @@ export const getDomains = async ({
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// 1. Fetch collections (always fetch messages to hydrate domain-level sends/receives)
|
|
83
|
-
const [allDomains, allServices, allEntities, allFlows, allEvents, allCommands, allQueries, allContainers] =
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
83
|
+
const [allDomains, allServices, allEntities, allFlows, allEvents, allCommands, allQueries, allContainers, allDataProducts] =
|
|
84
|
+
await Promise.all([
|
|
85
|
+
getCollection('domains'),
|
|
86
|
+
getCollection('services'),
|
|
87
|
+
getCollection('entities'),
|
|
88
|
+
getCollection('flows'),
|
|
89
|
+
getCollection('events'),
|
|
90
|
+
getCollection('commands'),
|
|
91
|
+
getCollection('queries'),
|
|
92
|
+
getCollection('containers'),
|
|
93
|
+
getCollection('data-products'),
|
|
94
|
+
]);
|
|
93
95
|
|
|
94
96
|
const allMessages = [...allEvents, ...allCommands, ...allQueries];
|
|
95
97
|
const messageMap = createVersionedMap(allMessages);
|
|
@@ -100,6 +102,7 @@ export const getDomains = async ({
|
|
|
100
102
|
const serviceMap = createVersionedMap(allServices);
|
|
101
103
|
const entityMap = createVersionedMap(allEntities);
|
|
102
104
|
const flowMap = createVersionedMap(allFlows);
|
|
105
|
+
const dataProductMap = createVersionedMap(allDataProducts);
|
|
103
106
|
|
|
104
107
|
// 3. Filter the domains we actually want to process/return
|
|
105
108
|
const targetDomains = allDomains.filter((domain: Domain) => {
|
|
@@ -137,11 +140,17 @@ export const getDomains = async ({
|
|
|
137
140
|
.filter((s: any) => !!s);
|
|
138
141
|
}
|
|
139
142
|
|
|
143
|
+
// Hydrate data products for the subdomain
|
|
144
|
+
const subdomainDataProducts = (subDomain.data['data-products'] || [])
|
|
145
|
+
.map((dp: { id: string; version: string | undefined }) => findInMap(dataProductMap, dp.id, dp.version))
|
|
146
|
+
.filter((dp: any) => !!dp);
|
|
147
|
+
|
|
140
148
|
return {
|
|
141
149
|
...subDomain,
|
|
142
150
|
data: {
|
|
143
151
|
...subDomain.data,
|
|
144
152
|
services: hydratedServices as any,
|
|
153
|
+
'data-products': subdomainDataProducts as any,
|
|
145
154
|
},
|
|
146
155
|
};
|
|
147
156
|
});
|
|
@@ -158,6 +167,14 @@ export const getDomains = async ({
|
|
|
158
167
|
.map((flow: { id: string; version: string | undefined }) => findInMap(flowMap, flow.id, flow.version))
|
|
159
168
|
.filter((f): f is CollectionEntry<'flows'> => !!f);
|
|
160
169
|
|
|
170
|
+
// Resolve Data Products
|
|
171
|
+
const dataProductsInDomain = domain.data['data-products'] || [];
|
|
172
|
+
const dataProducts = dataProductsInDomain
|
|
173
|
+
.map((dataProduct: { id: string; version: string | undefined }) =>
|
|
174
|
+
findInMap(dataProductMap, dataProduct.id, dataProduct.version)
|
|
175
|
+
)
|
|
176
|
+
.filter((dp): dp is CollectionEntry<'data-products'> => !!dp);
|
|
177
|
+
|
|
161
178
|
// Resolve Services for Main Domain
|
|
162
179
|
const servicesInDomain = domain.data.services || [];
|
|
163
180
|
|
|
@@ -203,6 +220,7 @@ export const getDomains = async ({
|
|
|
203
220
|
domains: subDomains as any,
|
|
204
221
|
entities: entities as any,
|
|
205
222
|
flows: flows as any,
|
|
223
|
+
'data-products': dataProducts as any,
|
|
206
224
|
sends: domainSends as any,
|
|
207
225
|
receives: domainReceives as any,
|
|
208
226
|
latestVersion,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { getCollection } from 'astro:content';
|
|
2
2
|
import type { CollectionEntry } from 'astro:content';
|
|
3
3
|
import path from 'path';
|
|
4
|
-
import { createVersionedMap
|
|
4
|
+
import { createVersionedMap } from './util';
|
|
5
|
+
import { hydrateProducersAndConsumers } from './messages';
|
|
5
6
|
import utils from '@eventcatalog/sdk';
|
|
6
7
|
|
|
7
8
|
const PROJECT_DIR = process.env.PROJECT_DIR || process.cwd();
|
|
@@ -35,10 +36,11 @@ export const getEvents = async ({ getAllVersions = true, hydrateServices = true
|
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
// 1. Fetch collections in parallel
|
|
38
|
-
const [allEvents, allServices, allChannels] = await Promise.all([
|
|
39
|
+
const [allEvents, allServices, allChannels, allDataProducts] = await Promise.all([
|
|
39
40
|
getCollection('events'),
|
|
40
41
|
getCollection('services'),
|
|
41
42
|
getCollection('channels'),
|
|
43
|
+
getCollection('data-products'),
|
|
42
44
|
]);
|
|
43
45
|
|
|
44
46
|
// 2. Build optimized maps
|
|
@@ -64,33 +66,13 @@ export const getEvents = async ({ getAllVersions = true, hydrateServices = true
|
|
|
64
66
|
const latestVersion = eventVersions[0]?.data.version || event.data.version;
|
|
65
67
|
const versions = eventVersions.map((e) => e.data.version);
|
|
66
68
|
|
|
67
|
-
// Find
|
|
68
|
-
const producers =
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
})
|
|
75
|
-
)
|
|
76
|
-
.map((service) => {
|
|
77
|
-
if (!hydrateServices) return { id: service.data.id, version: service.data.version };
|
|
78
|
-
return service;
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// Find Consumers (Services that receive this event)
|
|
82
|
-
const consumers = allServices
|
|
83
|
-
.filter((service) =>
|
|
84
|
-
service.data.receives?.some((item) => {
|
|
85
|
-
if (item.id !== event.data.id) return false;
|
|
86
|
-
if (item.version === 'latest' || item.version === undefined) return event.data.version === latestVersion;
|
|
87
|
-
return satisfies(event.data.version, item.version);
|
|
88
|
-
})
|
|
89
|
-
)
|
|
90
|
-
.map((service) => {
|
|
91
|
-
if (!hydrateServices) return { id: service.data.id, version: service.data.version };
|
|
92
|
-
return service;
|
|
93
|
-
});
|
|
69
|
+
// Find producers and consumers (services + data products)
|
|
70
|
+
const { producers, consumers } = hydrateProducersAndConsumers({
|
|
71
|
+
message: { data: { ...event.data, latestVersion } },
|
|
72
|
+
services: allServices,
|
|
73
|
+
dataProducts: allDataProducts,
|
|
74
|
+
hydrate: hydrateServices,
|
|
75
|
+
});
|
|
94
76
|
|
|
95
77
|
// Find Channels
|
|
96
78
|
const messageChannels = event.data.channels || [];
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
ArrowsRightLeftIcon,
|
|
11
11
|
VariableIcon,
|
|
12
12
|
MapIcon,
|
|
13
|
+
CubeIcon,
|
|
13
14
|
} from '@heroicons/react/24/outline';
|
|
14
15
|
import { BookText, Box, DatabaseIcon } from 'lucide-react';
|
|
15
16
|
|
|
@@ -43,6 +44,8 @@ export const getIconForCollection = (collection: string) => {
|
|
|
43
44
|
return Box;
|
|
44
45
|
case 'containers':
|
|
45
46
|
return DatabaseIcon;
|
|
47
|
+
case 'data-products':
|
|
48
|
+
return CubeIcon;
|
|
46
49
|
default:
|
|
47
50
|
return ServerIcon;
|
|
48
51
|
}
|
|
@@ -74,6 +77,8 @@ export const getColorAndIconForCollection = (collection: string) => {
|
|
|
74
77
|
return { color: 'yellow', Icon: icon };
|
|
75
78
|
case 'services':
|
|
76
79
|
return { color: 'pink', Icon: icon };
|
|
80
|
+
case 'data-products':
|
|
81
|
+
return { color: 'cyan', Icon: icon };
|
|
77
82
|
default:
|
|
78
83
|
return { color: 'gray', Icon: icon };
|
|
79
84
|
}
|