@eventcatalog/core 3.33.0 → 3.35.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-TDRDRXOZ.js → chunk-B2LDVIVY.js} +1 -1
- package/dist/{chunk-GBSBBBF5.js → chunk-DFLUDECO.js} +1 -1
- package/dist/{chunk-DN6F4AAQ.js → chunk-LUWCWNOR.js} +1 -1
- package/dist/{chunk-YKTTWB2P.js → chunk-NEWQKEP7.js} +1 -1
- package/dist/{chunk-VRXBFCYB.js → chunk-Y5O6SCX3.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 +8 -8
- 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/Search/SearchModal.tsx +23 -34
- package/eventcatalog/src/components/Search/search-utils.spec.ts +36 -0
- package/eventcatalog/src/components/Search/search-utils.ts +34 -0
- package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +7 -1
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +2 -0
- package/eventcatalog/src/enterprise/custom-documentation/utils/custom-docs.ts +26 -8
- package/eventcatalog/src/stores/sidebar-store/builders/flow.ts +77 -0
- package/eventcatalog/src/stores/sidebar-store/builders/message.ts +10 -1
- package/eventcatalog/src/stores/sidebar-store/builders/service.ts +10 -3
- package/eventcatalog/src/stores/sidebar-store/state.ts +126 -2
- package/eventcatalog/src/utils/collections/flows.ts +3 -2
- package/package.json +10 -10
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
log_build_default
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-DFLUDECO.js";
|
|
4
|
+
import "../chunk-B2LDVIVY.js";
|
|
5
5
|
import "../chunk-4UVFXLPI.js";
|
|
6
|
-
import "../chunk-
|
|
6
|
+
import "../chunk-NEWQKEP7.js";
|
|
7
7
|
import "../chunk-5T63CXKU.js";
|
|
8
8
|
export {
|
|
9
9
|
log_build_default as default
|
package/dist/constants.cjs
CHANGED
package/dist/constants.js
CHANGED
package/dist/eventcatalog.cjs
CHANGED
|
@@ -114,7 +114,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
|
|
|
114
114
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
115
115
|
|
|
116
116
|
// package.json
|
|
117
|
-
var version = "3.
|
|
117
|
+
var version = "3.35.0";
|
|
118
118
|
|
|
119
119
|
// src/constants.ts
|
|
120
120
|
var VERSION = version;
|
package/dist/eventcatalog.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
log_build_default
|
|
3
|
-
} from "./chunk-GBSBBBF5.js";
|
|
4
1
|
import {
|
|
5
2
|
resolve_catalog_dependencies_default
|
|
6
3
|
} from "./chunk-WAJIJEI3.js";
|
|
7
4
|
import {
|
|
8
5
|
watch
|
|
9
6
|
} from "./chunk-K3ZVEX2Y.js";
|
|
7
|
+
import {
|
|
8
|
+
log_build_default
|
|
9
|
+
} from "./chunk-DFLUDECO.js";
|
|
10
|
+
import "./chunk-B2LDVIVY.js";
|
|
11
|
+
import "./chunk-4UVFXLPI.js";
|
|
10
12
|
import {
|
|
11
13
|
runMigrations
|
|
12
14
|
} from "./chunk-XUAF2H54.js";
|
|
13
15
|
import "./chunk-CA4U2JP7.js";
|
|
14
|
-
import "./chunk-TDRDRXOZ.js";
|
|
15
|
-
import "./chunk-4UVFXLPI.js";
|
|
16
16
|
import {
|
|
17
17
|
catalogToAstro
|
|
18
18
|
} from "./chunk-YDXB3BD2.js";
|
|
@@ -22,13 +22,13 @@ import {
|
|
|
22
22
|
} from "./chunk-3KXCGYET.js";
|
|
23
23
|
import {
|
|
24
24
|
generate
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-Y5O6SCX3.js";
|
|
26
26
|
import {
|
|
27
27
|
logger
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-LUWCWNOR.js";
|
|
29
29
|
import {
|
|
30
30
|
VERSION
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-NEWQKEP7.js";
|
|
32
32
|
import {
|
|
33
33
|
getEventCatalogConfigFile,
|
|
34
34
|
verifyRequiredFieldsAreInCatalogConfigFile
|
package/dist/generate.cjs
CHANGED
package/dist/generate.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generate
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-Y5O6SCX3.js";
|
|
4
|
+
import "./chunk-LUWCWNOR.js";
|
|
5
|
+
import "./chunk-NEWQKEP7.js";
|
|
6
6
|
import "./chunk-5T63CXKU.js";
|
|
7
7
|
export {
|
|
8
8
|
generate
|
package/dist/utils/cli-logger.js
CHANGED
|
@@ -27,6 +27,7 @@ import { useStore } from '@nanostores/react';
|
|
|
27
27
|
import { favoritesStore, toggleFavorite as toggleFavoriteAction } from '../../stores/favorites-store';
|
|
28
28
|
import { buildUrl } from '@utils/url-builder';
|
|
29
29
|
import { resolveIconUrl } from '@utils/icon';
|
|
30
|
+
import { getUrlForSearchItem } from './search-utils';
|
|
30
31
|
|
|
31
32
|
const typeIcons: any = {
|
|
32
33
|
Domain: RectangleGroupIcon,
|
|
@@ -43,6 +44,8 @@ const typeIcons: any = {
|
|
|
43
44
|
AsyncAPI: DocumentTextIcon,
|
|
44
45
|
Design: Square2StackIcon,
|
|
45
46
|
Container: CircleStackIcon,
|
|
47
|
+
'Data Product': CubeIcon,
|
|
48
|
+
Flow: QueueListIcon,
|
|
46
49
|
default: DocumentTextIcon,
|
|
47
50
|
};
|
|
48
51
|
|
|
@@ -62,6 +65,8 @@ const typeColors: any = {
|
|
|
62
65
|
AsyncAPI: 'text-violet-500 dark:text-violet-400 bg-violet-50 dark:bg-violet-500/10 ring-violet-200 dark:ring-violet-500/30',
|
|
63
66
|
Design: 'text-gray-500 dark:text-gray-400 bg-gray-50 dark:bg-gray-500/10 ring-gray-200 dark:ring-gray-500/30',
|
|
64
67
|
Container: 'text-indigo-500 dark:text-indigo-400 bg-indigo-50 dark:bg-indigo-500/10 ring-indigo-200 dark:ring-indigo-500/30',
|
|
68
|
+
'Data Product': 'text-sky-500 dark:text-sky-400 bg-sky-50 dark:bg-sky-500/10 ring-sky-200 dark:ring-sky-500/30',
|
|
69
|
+
Flow: 'text-fuchsia-500 dark:text-fuchsia-400 bg-fuchsia-50 dark:bg-fuchsia-500/10 ring-fuchsia-200 dark:ring-fuchsia-500/30',
|
|
65
70
|
default: 'text-gray-500 dark:text-gray-400 bg-gray-50 dark:bg-gray-500/10 ring-gray-200 dark:ring-gray-500/30',
|
|
66
71
|
};
|
|
67
72
|
|
|
@@ -69,35 +74,6 @@ function classNames(...classes: (string | boolean | undefined)[]) {
|
|
|
69
74
|
return classes.filter(Boolean).join(' ');
|
|
70
75
|
}
|
|
71
76
|
|
|
72
|
-
// Helper to construct URL from key if href is missing
|
|
73
|
-
const getUrlForItem = (node: any, key: string) => {
|
|
74
|
-
const parts = key.split(':');
|
|
75
|
-
if (parts.length < 2) return null; // Need at least type:id
|
|
76
|
-
|
|
77
|
-
const type = parts[0];
|
|
78
|
-
const id = parts[1];
|
|
79
|
-
const version = parts[2]; // May be undefined
|
|
80
|
-
|
|
81
|
-
// Skip list items and other special keys
|
|
82
|
-
if (type === 'list') return null;
|
|
83
|
-
|
|
84
|
-
// Only show items that have a version to avoid duplicates
|
|
85
|
-
if (!version) return null;
|
|
86
|
-
|
|
87
|
-
// If node has href, use it, otherwise construct from key
|
|
88
|
-
if (node.href) return node.href;
|
|
89
|
-
|
|
90
|
-
// Pluralize type for URL if needed
|
|
91
|
-
let pluralType = type;
|
|
92
|
-
if (['event', 'command', 'domain', 'service', 'flow', 'container', 'channel'].includes(type)) {
|
|
93
|
-
pluralType = type + 's';
|
|
94
|
-
} else if (type === 'query') {
|
|
95
|
-
pluralType = 'queries';
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return buildUrl(`/docs/${pluralType}/${id}/${version}`);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
77
|
interface SearchNode {
|
|
102
78
|
key: string;
|
|
103
79
|
title: string;
|
|
@@ -203,7 +179,7 @@ export default function SearchModal() {
|
|
|
203
179
|
const items = useMemo(() => {
|
|
204
180
|
return searchNodes
|
|
205
181
|
.map((node) => {
|
|
206
|
-
const url =
|
|
182
|
+
const url = getUrlForSearchItem(node as any, node.key);
|
|
207
183
|
if (!url) return null;
|
|
208
184
|
|
|
209
185
|
return {
|
|
@@ -252,8 +228,11 @@ export default function SearchModal() {
|
|
|
252
228
|
Message: 0,
|
|
253
229
|
Team: 0,
|
|
254
230
|
Container: 0,
|
|
231
|
+
Entity: 0,
|
|
255
232
|
Design: 0,
|
|
256
233
|
Channel: 0,
|
|
234
|
+
Flow: 0,
|
|
235
|
+
'Data Product': 0,
|
|
257
236
|
};
|
|
258
237
|
|
|
259
238
|
itemsToCount.forEach((item) => {
|
|
@@ -277,8 +256,12 @@ export default function SearchModal() {
|
|
|
277
256
|
if (counts.Domain > 0) dynamicFilters.push({ id: 'Domain', name: `Domains (${counts.Domain})` });
|
|
278
257
|
if (counts.Service > 0) dynamicFilters.push({ id: 'Service', name: `Services (${counts.Service})` });
|
|
279
258
|
if (counts.Message > 0) dynamicFilters.push({ id: 'Message', name: `Messages (${counts.Message})` });
|
|
280
|
-
if (counts.Container > 0) dynamicFilters.push({ id: 'Container', name: `
|
|
259
|
+
if (counts.Container > 0) dynamicFilters.push({ id: 'Container', name: `Data Stores (${counts.Container})` });
|
|
260
|
+
if (counts.Entity > 0) dynamicFilters.push({ id: 'Entity', name: `Entities (${counts.Entity})` });
|
|
281
261
|
if (counts.Channel > 0) dynamicFilters.push({ id: 'Channel', name: `Channels (${counts.Channel})` });
|
|
262
|
+
if (counts.Flow > 0) dynamicFilters.push({ id: 'Flow', name: `Flows (${counts.Flow})` });
|
|
263
|
+
if (counts['Data Product'] > 0)
|
|
264
|
+
dynamicFilters.push({ id: 'Data Product', name: `Data Products (${counts['Data Product']})` });
|
|
282
265
|
if (counts.Design > 0) dynamicFilters.push({ id: 'Design', name: `Designs (${counts.Design})` });
|
|
283
266
|
if (counts.Team > 0) dynamicFilters.push({ id: 'Team', name: `Teams & Users (${counts.Team})` });
|
|
284
267
|
|
|
@@ -317,7 +300,7 @@ export default function SearchModal() {
|
|
|
317
300
|
.slice(0, 5)
|
|
318
301
|
.map((fav) => {
|
|
319
302
|
const node = searchNodeLookup.get(fav.nodeKey);
|
|
320
|
-
const url = node ?
|
|
303
|
+
const url = node ? getUrlForSearchItem(node as any, fav.nodeKey) : fav.href;
|
|
321
304
|
if (!url) return null;
|
|
322
305
|
|
|
323
306
|
return {
|
|
@@ -411,7 +394,13 @@ export default function SearchModal() {
|
|
|
411
394
|
</div>
|
|
412
395
|
|
|
413
396
|
{/* Filter Tabs */}
|
|
414
|
-
<div
|
|
397
|
+
<div
|
|
398
|
+
className="flex items-center gap-2 px-4 pt-3 pb-3.5 overflow-x-auto overscroll-x-contain border-b border-[rgb(var(--ec-page-border))]"
|
|
399
|
+
style={{
|
|
400
|
+
scrollbarWidth: 'thin',
|
|
401
|
+
scrollbarColor: 'rgb(var(--ec-page-border)) transparent',
|
|
402
|
+
}}
|
|
403
|
+
>
|
|
415
404
|
{filters.map((tab) => (
|
|
416
405
|
<button
|
|
417
406
|
key={tab.id}
|
|
@@ -566,7 +555,7 @@ export default function SearchModal() {
|
|
|
566
555
|
<MagnifyingGlassIcon className="mx-auto h-6 w-6 text-[rgb(var(--ec-icon-color))]" />
|
|
567
556
|
<p className="mt-4 font-semibold text-[rgb(var(--ec-page-text))]">Search for anything</p>
|
|
568
557
|
<p className="mt-2 text-[rgb(var(--ec-page-text-muted))]">
|
|
569
|
-
Search for domains, services, events, commands, queries and more.
|
|
558
|
+
Search for domains, services, events, commands, queries, data stores, data products, flows and more.
|
|
570
559
|
</p>
|
|
571
560
|
</div>
|
|
572
561
|
)}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it, beforeEach } from 'vitest';
|
|
2
|
+
import { getUrlForSearchItem } from './search-utils';
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface Window {
|
|
6
|
+
__EC_TRAILING_SLASH__: boolean;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
describe('getUrlForSearchItem', () => {
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
global.__EC_TRAILING_SLASH__ = false;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it.each([
|
|
17
|
+
['container:OrdersDatabase:1.0.0', '/docs/containers/OrdersDatabase/1.0.0'],
|
|
18
|
+
['data-product:Customer360:1.0.0', '/docs/data-products/Customer360/1.0.0'],
|
|
19
|
+
['entity:Order:1.0.0', '/docs/entities/Order/1.0.0'],
|
|
20
|
+
['flow:CheckoutFlow:1.0.0', '/docs/flows/CheckoutFlow/1.0.0'],
|
|
21
|
+
])('builds a docs URL for %s', (key, expected) => {
|
|
22
|
+
expect(getUrlForSearchItem({}, key)).toBe(expected);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('uses the explicit node href when provided', () => {
|
|
26
|
+
expect(getUrlForSearchItem({ href: '/custom/search-result' }, 'data-product:Customer360:1.0.0')).toBe(
|
|
27
|
+
'/custom/search-result'
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('skips aliases and unsupported keys', () => {
|
|
32
|
+
expect(getUrlForSearchItem({}, 'data-product:Customer360')).toBeNull();
|
|
33
|
+
expect(getUrlForSearchItem({}, 'list:data-products')).toBeNull();
|
|
34
|
+
expect(getUrlForSearchItem({}, 'unknown:Customer360:1.0.0')).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { buildUrl } from '@utils/url-builder';
|
|
2
|
+
|
|
3
|
+
const docsPathByType: Record<string, string> = {
|
|
4
|
+
channel: 'channels',
|
|
5
|
+
command: 'commands',
|
|
6
|
+
container: 'containers',
|
|
7
|
+
'data-product': 'data-products',
|
|
8
|
+
domain: 'domains',
|
|
9
|
+
entity: 'entities',
|
|
10
|
+
event: 'events',
|
|
11
|
+
flow: 'flows',
|
|
12
|
+
query: 'queries',
|
|
13
|
+
service: 'services',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const getUrlForSearchItem = (node: { href?: string }, key: string) => {
|
|
17
|
+
const parts = key.split(':');
|
|
18
|
+
if (parts.length < 2) return null;
|
|
19
|
+
|
|
20
|
+
const type = parts[0];
|
|
21
|
+
const id = parts[1];
|
|
22
|
+
const version = parts[2];
|
|
23
|
+
|
|
24
|
+
if (type === 'list') return null;
|
|
25
|
+
|
|
26
|
+
if (!version) return null;
|
|
27
|
+
|
|
28
|
+
if (node.href) return node.href;
|
|
29
|
+
|
|
30
|
+
const docsPath = docsPathByType[type];
|
|
31
|
+
if (!docsPath) return null;
|
|
32
|
+
|
|
33
|
+
return buildUrl(`/docs/${docsPath}/${id}/${version}`);
|
|
34
|
+
};
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
SquareMousePointer,
|
|
17
17
|
ListOrdered,
|
|
18
18
|
ArrowLeftRight,
|
|
19
|
+
Package,
|
|
20
|
+
Box,
|
|
19
21
|
} from 'lucide-react';
|
|
20
22
|
import type { NavNode } from '@stores/sidebar-store/state';
|
|
21
23
|
import { getBadgeClasses } from './utils';
|
|
@@ -83,8 +85,10 @@ export default function SearchBar({ nodes, onSelectResult, onSearchChange }: Pro
|
|
|
83
85
|
{ key: 'channel', label: 'Channels', badge: 'Channel', icon: ArrowLeftRight },
|
|
84
86
|
{ key: 'command', label: 'Commands', badge: 'Command', icon: MessageSquare },
|
|
85
87
|
{ key: 'container', label: 'Data Stores', badge: 'Container', icon: Database },
|
|
88
|
+
{ key: 'data-product', label: 'Data Products', badge: 'Data Product', icon: Package },
|
|
86
89
|
{ key: 'design', label: 'Designs', badge: 'Design', icon: SquareMousePointer },
|
|
87
90
|
{ key: 'domain', label: 'Domains', badge: 'Domain', icon: Boxes },
|
|
91
|
+
{ key: 'entity', label: 'Entities', badge: 'Entity', icon: Box },
|
|
88
92
|
{ key: 'event', label: 'Events', badge: 'Event', icon: Zap },
|
|
89
93
|
{ key: 'flow', label: 'Flows', badge: 'Flow', icon: Waypoints },
|
|
90
94
|
{ key: 'query', label: 'Queries', badge: 'Query', icon: SearchIcon },
|
|
@@ -116,9 +120,11 @@ export default function SearchBar({ nodes, onSelectResult, onSearchChange }: Pro
|
|
|
116
120
|
Command: 'command',
|
|
117
121
|
Query: 'query',
|
|
118
122
|
Container: 'container',
|
|
123
|
+
'Data Product': 'data-product',
|
|
119
124
|
Flow: 'flow',
|
|
120
125
|
Design: 'design',
|
|
121
126
|
Channel: 'channel',
|
|
127
|
+
Entity: 'entity',
|
|
122
128
|
};
|
|
123
129
|
|
|
124
130
|
// Use the memoized array instead of Object.entries(nodes)
|
|
@@ -135,7 +141,7 @@ export default function SearchBar({ nodes, onSelectResult, onSearchChange }: Pro
|
|
|
135
141
|
|
|
136
142
|
const keyParts = key.split(':');
|
|
137
143
|
if (keyParts.length >= 3) {
|
|
138
|
-
const id = keyParts[
|
|
144
|
+
const id = keyParts[1].toLowerCase();
|
|
139
145
|
if (id.includes(query)) {
|
|
140
146
|
results.push({ nodeKey: key, node, matchType: 'id' });
|
|
141
147
|
}
|
|
@@ -239,6 +239,8 @@ export default function NestedSideBar() {
|
|
|
239
239
|
// Data Products
|
|
240
240
|
{ pattern: /^\/docs\/data-products\/([^/]+)\/([^/]+)/, type: 'data-product' },
|
|
241
241
|
{ pattern: /^\/visualiser\/data-products\/([^/]+)\/([^/]+)/, type: 'data-product' },
|
|
242
|
+
// Entities
|
|
243
|
+
{ pattern: /^\/docs\/entities\/([^/]+)\/([^/]+)/, type: 'entity' },
|
|
242
244
|
];
|
|
243
245
|
|
|
244
246
|
// URL patterns without version (language pages, etc)
|
|
@@ -6,9 +6,20 @@
|
|
|
6
6
|
import config from '@config';
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
import path from 'node:path';
|
|
9
|
-
import {
|
|
9
|
+
import { getCollection } from 'astro:content';
|
|
10
10
|
import matter from 'gray-matter';
|
|
11
11
|
|
|
12
|
+
// Use getCollection (which returns plain entries) instead of getEntry, which installs
|
|
13
|
+
// Astro's `slug` deprecation accessor on every entry it returns. The accessor fires a
|
|
14
|
+
// `console.error` on each access of `entry.data.slug`, even though our schema legitimately
|
|
15
|
+
// defines `slug` as an optional user field. See packages/core/eventcatalog/src/enterprise/collections/custom-pages.ts.
|
|
16
|
+
const getCustomPagesById = async () => {
|
|
17
|
+
const all = await getCollection('customPages');
|
|
18
|
+
const map = new Map<string, (typeof all)[number]>();
|
|
19
|
+
for (const e of all) map.set(e.id, e);
|
|
20
|
+
return map;
|
|
21
|
+
};
|
|
22
|
+
|
|
12
23
|
type Badge = {
|
|
13
24
|
text: string;
|
|
14
25
|
color: string;
|
|
@@ -55,12 +66,16 @@ const DOCS_DIR = 'docs';
|
|
|
55
66
|
* If an index.mdx or index.md file exists in the directory, it will be used as the
|
|
56
67
|
* folder's link target (making the folder clickable) and excluded from the items list.
|
|
57
68
|
*/
|
|
69
|
+
type CustomPagesMap = Awaited<ReturnType<typeof getCustomPagesById>>;
|
|
70
|
+
|
|
58
71
|
const processAutoGeneratedDirectory = async (
|
|
59
72
|
directory: string,
|
|
60
73
|
label: string,
|
|
61
74
|
badge?: Badge,
|
|
62
|
-
collapsed?: boolean
|
|
75
|
+
collapsed?: boolean,
|
|
76
|
+
customPages?: CustomPagesMap
|
|
63
77
|
): Promise<SidebarItem> => {
|
|
78
|
+
customPages ??= await getCustomPagesById();
|
|
64
79
|
// @ts-ignore
|
|
65
80
|
const items = fs.readdirSync(path.join(process.env.PROJECT_DIR || '', DOCS_DIR, directory));
|
|
66
81
|
|
|
@@ -78,7 +93,7 @@ const processAutoGeneratedDirectory = async (
|
|
|
78
93
|
// Normalize path separators for cross-platform compatibility
|
|
79
94
|
// Note: Astro's glob loader strips '/index' from the ID, so docs/foo/index.mdx becomes docs/foo
|
|
80
95
|
const astroId = data.slug || path.join(DOCS_DIR, directory).replace(/\\/g, '/');
|
|
81
|
-
const entry =
|
|
96
|
+
const entry = customPages.get(astroId.toLowerCase());
|
|
82
97
|
|
|
83
98
|
if (entry) {
|
|
84
99
|
// Use the index file's slug as the folder's link target
|
|
@@ -101,7 +116,8 @@ const processAutoGeneratedDirectory = async (
|
|
|
101
116
|
path.join(directory, item),
|
|
102
117
|
item, // Use directory name as label
|
|
103
118
|
undefined, // No badge for subdirectories
|
|
104
|
-
collapsed // Inherit collapsed state
|
|
119
|
+
collapsed, // Inherit collapsed state
|
|
120
|
+
customPages
|
|
105
121
|
);
|
|
106
122
|
// Only add the directory if it contains valid items (mdx/md files) or has a slug (index file)
|
|
107
123
|
if ((subdirResult.items && subdirResult.items.length > 0) || subdirResult.slug) {
|
|
@@ -115,7 +131,7 @@ const processAutoGeneratedDirectory = async (
|
|
|
115
131
|
// Normalize path separators to forward slashes for cross-platform compatibility (Windows uses backslashes)
|
|
116
132
|
const astroId =
|
|
117
133
|
data.slug || path.join(DOCS_DIR, directory, item).replace('.mdx', '').replace('.md', '').replace(/\\/g, '/');
|
|
118
|
-
const entry =
|
|
134
|
+
const entry = customPages.get(astroId.toLowerCase());
|
|
119
135
|
|
|
120
136
|
if (entry) {
|
|
121
137
|
allItems.push({
|
|
@@ -138,7 +154,8 @@ const processAutoGeneratedDirectory = async (
|
|
|
138
154
|
/**
|
|
139
155
|
* Recursively process sidebar items to handle auto-generated content at any nesting level
|
|
140
156
|
*/
|
|
141
|
-
const processSidebarItems = async (items: SideBarConfigurationItem[]): Promise<SidebarItem[]> => {
|
|
157
|
+
const processSidebarItems = async (items: SideBarConfigurationItem[], customPages?: CustomPagesMap): Promise<SidebarItem[]> => {
|
|
158
|
+
customPages ??= await getCustomPagesById();
|
|
142
159
|
const processedItems: SidebarItem[] = [];
|
|
143
160
|
|
|
144
161
|
for (const item of items) {
|
|
@@ -148,13 +165,14 @@ const processSidebarItems = async (items: SideBarConfigurationItem[]): Promise<S
|
|
|
148
165
|
item.autogenerated.directory,
|
|
149
166
|
item.label,
|
|
150
167
|
item.badge,
|
|
151
|
-
item.autogenerated.collapsed !== undefined ? item.autogenerated.collapsed : item.collapsed
|
|
168
|
+
item.autogenerated.collapsed !== undefined ? item.autogenerated.collapsed : item.collapsed,
|
|
169
|
+
customPages
|
|
152
170
|
);
|
|
153
171
|
processedItems.push(processedItem);
|
|
154
172
|
}
|
|
155
173
|
// If item has nested items, process them recursively
|
|
156
174
|
else if (item.items && item.items.length > 0) {
|
|
157
|
-
const processedNestedItems = await processSidebarItems(item.items);
|
|
175
|
+
const processedNestedItems = await processSidebarItems(item.items, customPages);
|
|
158
176
|
processedItems.push({
|
|
159
177
|
label: item.label,
|
|
160
178
|
slug: item.slug,
|
|
@@ -3,6 +3,44 @@ import { buildUrl } from '@utils/url-builder';
|
|
|
3
3
|
import type { NavNode, ChildRef, ResourceGroupContext } from './shared';
|
|
4
4
|
import { buildQuickReferenceSection, buildResourceDocsSection, shouldRenderSideBarSection } from './shared';
|
|
5
5
|
import { isChangelogEnabled } from '@utils/feature';
|
|
6
|
+
import { createVersionedMap, findInMap } from '@utils/collections/util';
|
|
7
|
+
import { pluralizeMessageType } from '@utils/collections/messages';
|
|
8
|
+
|
|
9
|
+
type VersionedEntry = { collection?: string; data: { id: string; version: string } };
|
|
10
|
+
type VersionedEntryMap<T extends VersionedEntry> = Map<string, T[]>;
|
|
11
|
+
|
|
12
|
+
const uniqueRefs = (refs: string[]) => [...new Set(refs)];
|
|
13
|
+
|
|
14
|
+
const resolvePointer = <T extends VersionedEntry>(
|
|
15
|
+
map: VersionedEntryMap<T>,
|
|
16
|
+
pointer: { id: string; version?: string }
|
|
17
|
+
): T | undefined => {
|
|
18
|
+
return findInMap(map, pointer.id, pointer.version);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const resolveMessageStep = (
|
|
22
|
+
step: any,
|
|
23
|
+
maps: {
|
|
24
|
+
eventMap: VersionedEntryMap<CollectionEntry<'events'>>;
|
|
25
|
+
commandMap: VersionedEntryMap<CollectionEntry<'commands'>>;
|
|
26
|
+
queryMap: VersionedEntryMap<CollectionEntry<'queries'>>;
|
|
27
|
+
}
|
|
28
|
+
): string | null => {
|
|
29
|
+
if (!step.message) return null;
|
|
30
|
+
|
|
31
|
+
const hydratedMessage = Array.isArray(step.message) ? step.message[0] : undefined;
|
|
32
|
+
if (hydratedMessage?.collection && hydratedMessage?.data) {
|
|
33
|
+
return `${pluralizeMessageType(hydratedMessage as any)}:${hydratedMessage.data.id}:${hydratedMessage.data.version}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const pointer = Array.isArray(step.message) ? undefined : step.message;
|
|
37
|
+
if (!pointer?.id) return null;
|
|
38
|
+
|
|
39
|
+
const message =
|
|
40
|
+
resolvePointer(maps.eventMap, pointer) || resolvePointer(maps.commandMap, pointer) || resolvePointer(maps.queryMap, pointer);
|
|
41
|
+
|
|
42
|
+
return message ? `${pluralizeMessageType(message as any)}:${message.data.id}:${message.data.version}` : null;
|
|
43
|
+
};
|
|
6
44
|
|
|
7
45
|
export const buildFlowNode = (flow: CollectionEntry<'flows'>, context: ResourceGroupContext): NavNode => {
|
|
8
46
|
const docsSection = buildResourceDocsSection(
|
|
@@ -12,6 +50,27 @@ export const buildFlowNode = (flow: CollectionEntry<'flows'>, context: ResourceG
|
|
|
12
50
|
context.resourceDocs,
|
|
13
51
|
context.resourceDocCategories
|
|
14
52
|
);
|
|
53
|
+
const steps = flow.data.steps || [];
|
|
54
|
+
const eventMap = createVersionedMap(context.events);
|
|
55
|
+
const commandMap = createVersionedMap(context.commands);
|
|
56
|
+
const queryMap = createVersionedMap(context.queries);
|
|
57
|
+
const serviceMap = createVersionedMap(context.services);
|
|
58
|
+
const flowMap = createVersionedMap(context.flows);
|
|
59
|
+
const messageRefs = uniqueRefs(
|
|
60
|
+
steps.map((step) => resolveMessageStep(step, { eventMap, commandMap, queryMap })).filter(Boolean) as string[]
|
|
61
|
+
);
|
|
62
|
+
const serviceRefs = uniqueRefs(
|
|
63
|
+
steps
|
|
64
|
+
.map((step) => (step.service ? resolvePointer(serviceMap, step.service) : undefined))
|
|
65
|
+
.filter(Boolean)
|
|
66
|
+
.map((service) => `service:${service!.data.id}:${service!.data.version}`)
|
|
67
|
+
);
|
|
68
|
+
const flowRefs = uniqueRefs(
|
|
69
|
+
steps
|
|
70
|
+
.map((step) => (step.flow ? resolvePointer(flowMap, step.flow) : undefined))
|
|
71
|
+
.filter(Boolean)
|
|
72
|
+
.map((referencedFlow) => `flow:${referencedFlow!.data.id}:${referencedFlow!.data.version}`)
|
|
73
|
+
);
|
|
15
74
|
|
|
16
75
|
return {
|
|
17
76
|
type: 'item',
|
|
@@ -43,6 +102,24 @@ export const buildFlowNode = (flow: CollectionEntry<'flows'>, context: ResourceG
|
|
|
43
102
|
},
|
|
44
103
|
].filter(Boolean) as ChildRef[],
|
|
45
104
|
},
|
|
105
|
+
messageRefs.length > 0 && {
|
|
106
|
+
type: 'group',
|
|
107
|
+
title: 'Messages',
|
|
108
|
+
icon: 'Mail',
|
|
109
|
+
pages: messageRefs,
|
|
110
|
+
},
|
|
111
|
+
serviceRefs.length > 0 && {
|
|
112
|
+
type: 'group',
|
|
113
|
+
title: 'Services',
|
|
114
|
+
icon: 'Server',
|
|
115
|
+
pages: serviceRefs,
|
|
116
|
+
},
|
|
117
|
+
flowRefs.length > 0 && {
|
|
118
|
+
type: 'group',
|
|
119
|
+
title: 'Subflows',
|
|
120
|
+
icon: 'Waypoints',
|
|
121
|
+
pages: flowRefs,
|
|
122
|
+
},
|
|
46
123
|
].filter(Boolean) as ChildRef[],
|
|
47
124
|
};
|
|
48
125
|
};
|
|
@@ -18,7 +18,8 @@ export const buildMessageNode = (
|
|
|
18
18
|
message: CollectionEntry<'events' | 'commands' | 'queries'>,
|
|
19
19
|
owners: any[],
|
|
20
20
|
context: ResourceGroupContext,
|
|
21
|
-
hasFieldUsage: boolean = false
|
|
21
|
+
hasFieldUsage: boolean = false,
|
|
22
|
+
flowRefs: string[] = []
|
|
22
23
|
): NavNode => {
|
|
23
24
|
const producers = message.data.producers || [];
|
|
24
25
|
const consumers = message.data.consumers || [];
|
|
@@ -26,6 +27,7 @@ export const buildMessageNode = (
|
|
|
26
27
|
|
|
27
28
|
const renderProducers = producers.length > 0 && shouldRenderSideBarSection(message, 'producers');
|
|
28
29
|
const renderConsumers = consumers.length > 0 && shouldRenderSideBarSection(message, 'consumers');
|
|
30
|
+
const renderFlows = flowRefs.length > 0 && shouldRenderSideBarSection(message, 'flows');
|
|
29
31
|
const renderRepository = message.data.repository && shouldRenderSideBarSection(message, 'repository');
|
|
30
32
|
|
|
31
33
|
// Determine badge based on collection type
|
|
@@ -132,6 +134,13 @@ export const buildMessageNode = (
|
|
|
132
134
|
pages: consumers.map((consumer) => `service:${(consumer as any).data.id}:${(consumer as any).data.version}`),
|
|
133
135
|
visible: consumers.length > 0,
|
|
134
136
|
},
|
|
137
|
+
renderFlows && {
|
|
138
|
+
type: 'group',
|
|
139
|
+
title: 'Flows',
|
|
140
|
+
icon: 'Waypoints',
|
|
141
|
+
pages: flowRefs,
|
|
142
|
+
visible: flowRefs.length > 0,
|
|
143
|
+
},
|
|
135
144
|
renderOwners && buildOwnersSection(owners),
|
|
136
145
|
renderRepository && buildRepositorySection(message.data.repository as { url: string; language: string }),
|
|
137
146
|
hasAttachments && buildAttachmentsSection(message.data.attachments as any[]),
|
|
@@ -17,11 +17,14 @@ import { isVisualiserEnabled, isChangelogEnabled } from '@utils/feature';
|
|
|
17
17
|
import { pluralizeMessageType } from '@utils/collections/messages';
|
|
18
18
|
import { iconFieldsForResource } from '@utils/icon';
|
|
19
19
|
|
|
20
|
+
const uniqueRefs = (refs: string[]) => [...new Set(refs)];
|
|
21
|
+
|
|
20
22
|
export const buildServiceNode = (
|
|
21
23
|
service: CollectionEntry<'services'>,
|
|
22
24
|
owners: any[],
|
|
23
25
|
context: ResourceGroupContext,
|
|
24
|
-
serviceChannels: CollectionEntry<'channels'>[] = []
|
|
26
|
+
serviceChannels: CollectionEntry<'channels'>[] = [],
|
|
27
|
+
flowRefs: string[] = []
|
|
25
28
|
): NavNode => {
|
|
26
29
|
const sendsMessages = service.data.sends || [];
|
|
27
30
|
const receivesMessages = service.data.receives || [];
|
|
@@ -36,7 +39,11 @@ export const buildServiceNode = (
|
|
|
36
39
|
const dataStoresInService = uniqueBy([...(service.data.writesTo || []), ...(service.data.readsFrom || [])], 'id');
|
|
37
40
|
|
|
38
41
|
const serviceFlows = service.data.flows || [];
|
|
39
|
-
const
|
|
42
|
+
const serviceFlowRefs = uniqueRefs([
|
|
43
|
+
...serviceFlows.map((flow) => `flow:${(flow as any).data.id}:${(flow as any).data.version}`),
|
|
44
|
+
...flowRefs,
|
|
45
|
+
]);
|
|
46
|
+
const hasFlows = serviceFlowRefs.length > 0;
|
|
40
47
|
|
|
41
48
|
const hasAttachments = service.data.attachments && service.data.attachments.length > 0;
|
|
42
49
|
|
|
@@ -197,7 +204,7 @@ export const buildServiceNode = (
|
|
|
197
204
|
type: 'group',
|
|
198
205
|
title: 'Flows',
|
|
199
206
|
icon: 'Waypoints',
|
|
200
|
-
pages:
|
|
207
|
+
pages: serviceFlowRefs,
|
|
201
208
|
},
|
|
202
209
|
renderOwners && buildOwnersSection(owners),
|
|
203
210
|
renderRepository && buildRepositorySection(service.data.repository as { url: string; language: string }),
|
|
@@ -10,6 +10,7 @@ import { getUsers } from '@utils/collections/users';
|
|
|
10
10
|
import { getTeams } from '@utils/collections/teams';
|
|
11
11
|
import { getDiagrams } from '@utils/collections/diagrams';
|
|
12
12
|
import { getDataProducts } from '@utils/collections/data-products';
|
|
13
|
+
import { getEntities } from '@utils/collections/entities';
|
|
13
14
|
import { getResourceDocCategories, getResourceDocs } from '@utils/collections/resource-docs';
|
|
14
15
|
import { buildUrl } from '@utils/url-builder';
|
|
15
16
|
import type { NavigationData, NavNode, ChildRef } from './builders/shared';
|
|
@@ -32,6 +33,92 @@ export type { NavigationData, NavNode, ChildRef };
|
|
|
32
33
|
const CACHE_ENABLED = process.env.DISABLE_EVENTCATALOG_CACHE !== 'true';
|
|
33
34
|
let memoryCache: NavigationData | null = null;
|
|
34
35
|
|
|
36
|
+
type MessageEntry = CollectionEntry<'events' | 'commands' | 'queries'>;
|
|
37
|
+
type ServiceEntry = CollectionEntry<'services'>;
|
|
38
|
+
|
|
39
|
+
const getMessageNodeKey = (message: MessageEntry) =>
|
|
40
|
+
`${pluralizeMessageType(message)}:${message.data.id}:${message.data.version}`;
|
|
41
|
+
|
|
42
|
+
const uniqueRefs = (refs: string[]) => [...new Set(refs)];
|
|
43
|
+
|
|
44
|
+
const buildFlowReferencesByMessage = ({
|
|
45
|
+
flows,
|
|
46
|
+
events,
|
|
47
|
+
commands,
|
|
48
|
+
queries,
|
|
49
|
+
}: {
|
|
50
|
+
flows: CollectionEntry<'flows'>[];
|
|
51
|
+
events: CollectionEntry<'events'>[];
|
|
52
|
+
commands: CollectionEntry<'commands'>[];
|
|
53
|
+
queries: CollectionEntry<'queries'>[];
|
|
54
|
+
}) => {
|
|
55
|
+
const eventMap = createVersionedMap(events);
|
|
56
|
+
const commandMap = createVersionedMap(commands);
|
|
57
|
+
const queryMap = createVersionedMap(queries);
|
|
58
|
+
const flowRefsByMessage = new Map<string, string[]>();
|
|
59
|
+
|
|
60
|
+
const addFlowRef = (message: MessageEntry, flow: CollectionEntry<'flows'>) => {
|
|
61
|
+
const messageKey = getMessageNodeKey(message);
|
|
62
|
+
const flowKey = `flow:${flow.data.id}:${flow.data.version}`;
|
|
63
|
+
flowRefsByMessage.set(messageKey, uniqueRefs([...(flowRefsByMessage.get(messageKey) || []), flowKey]));
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const resolveMessagePointer = (pointer: { id: string; version?: string }): MessageEntry | undefined => {
|
|
67
|
+
return (
|
|
68
|
+
findInMap(eventMap, pointer.id, pointer.version) ||
|
|
69
|
+
findInMap(commandMap, pointer.id, pointer.version) ||
|
|
70
|
+
findInMap(queryMap, pointer.id, pointer.version)
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
for (const flow of flows) {
|
|
75
|
+
for (const step of flow.data.steps || []) {
|
|
76
|
+
if (!step.message) continue;
|
|
77
|
+
|
|
78
|
+
const hydratedMessage = Array.isArray(step.message) ? step.message[0] : undefined;
|
|
79
|
+
if (hydratedMessage?.collection && hydratedMessage?.data) {
|
|
80
|
+
addFlowRef(hydratedMessage as MessageEntry, flow);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (Array.isArray(step.message)) continue;
|
|
85
|
+
|
|
86
|
+
const message = resolveMessagePointer(step.message);
|
|
87
|
+
if (message) addFlowRef(message, flow);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return flowRefsByMessage;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const buildFlowReferencesByService = ({
|
|
95
|
+
flows,
|
|
96
|
+
services,
|
|
97
|
+
}: {
|
|
98
|
+
flows: CollectionEntry<'flows'>[];
|
|
99
|
+
services: CollectionEntry<'services'>[];
|
|
100
|
+
}) => {
|
|
101
|
+
const serviceMap = createVersionedMap(services);
|
|
102
|
+
const flowRefsByService = new Map<string, string[]>();
|
|
103
|
+
|
|
104
|
+
const addFlowRef = (service: ServiceEntry, flow: CollectionEntry<'flows'>) => {
|
|
105
|
+
const serviceKey = `service:${service.data.id}:${service.data.version}`;
|
|
106
|
+
const flowKey = `flow:${flow.data.id}:${flow.data.version}`;
|
|
107
|
+
flowRefsByService.set(serviceKey, uniqueRefs([...(flowRefsByService.get(serviceKey) || []), flowKey]));
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
for (const flow of flows) {
|
|
111
|
+
for (const step of flow.data.steps || []) {
|
|
112
|
+
if (!step.service) continue;
|
|
113
|
+
|
|
114
|
+
const service = findInMap(serviceMap, step.service.id, step.service.version);
|
|
115
|
+
if (service) addFlowRef(service, flow);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return flowRefsByService;
|
|
120
|
+
};
|
|
121
|
+
|
|
35
122
|
/**
|
|
36
123
|
* Get the navigation data for the sidebar
|
|
37
124
|
*/
|
|
@@ -52,6 +139,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
52
139
|
channels,
|
|
53
140
|
diagrams,
|
|
54
141
|
dataProducts,
|
|
142
|
+
entities,
|
|
55
143
|
resourceDocs,
|
|
56
144
|
resourceDocCategories,
|
|
57
145
|
] = await Promise.all([
|
|
@@ -66,6 +154,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
66
154
|
getChannels({ getAllVersions: false }),
|
|
67
155
|
getDiagrams({ getAllVersions: false }),
|
|
68
156
|
getDataProducts({ getAllVersions: false }),
|
|
157
|
+
getEntities({ getAllVersions: false }),
|
|
69
158
|
getResourceDocs(),
|
|
70
159
|
getResourceDocCategories(),
|
|
71
160
|
]);
|
|
@@ -86,6 +175,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
86
175
|
containers,
|
|
87
176
|
diagrams,
|
|
88
177
|
dataProducts,
|
|
178
|
+
entities,
|
|
89
179
|
resourceDocs,
|
|
90
180
|
resourceDocCategories,
|
|
91
181
|
};
|
|
@@ -190,11 +280,13 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
190
280
|
}
|
|
191
281
|
}
|
|
192
282
|
|
|
283
|
+
const flowRefsByService = buildFlowReferencesByService({ flows, services });
|
|
284
|
+
|
|
193
285
|
const serviceNodes = servicesWithOwners.reduce(
|
|
194
286
|
(acc, { service, owners }) => {
|
|
195
287
|
const versionedKey = `service:${service.data.id}:${service.data.version}`;
|
|
196
288
|
const serviceChannels = serviceChannelsMap.get(`${service.data.id}:${service.data.version}`) || [];
|
|
197
|
-
acc[versionedKey] = buildServiceNode(service, owners, context, serviceChannels);
|
|
289
|
+
acc[versionedKey] = buildServiceNode(service, owners, context, serviceChannels, flowRefsByService.get(versionedKey) || []);
|
|
198
290
|
if (service.data.latestVersion === service.data.version) {
|
|
199
291
|
// Store reference to versioned key instead of duplicating the full node
|
|
200
292
|
acc[`service:${service.data.id}`] = versionedKey;
|
|
@@ -217,12 +309,14 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
217
309
|
}
|
|
218
310
|
}
|
|
219
311
|
|
|
312
|
+
const flowRefsByMessage = buildFlowReferencesByMessage({ flows, events, commands, queries });
|
|
313
|
+
|
|
220
314
|
const messageNodes = messagesWithOwners.reduce(
|
|
221
315
|
(acc, { message, owners }) => {
|
|
222
316
|
const type = pluralizeMessageType(message as any);
|
|
223
317
|
const versionedKey = `${type}:${message.data.id}:${message.data.version}`;
|
|
224
318
|
const hasFieldUsage = messagesWithFieldUsage.has(message.data.id);
|
|
225
|
-
acc[versionedKey] = buildMessageNode(message, owners, context, hasFieldUsage);
|
|
319
|
+
acc[versionedKey] = buildMessageNode(message, owners, context, hasFieldUsage, flowRefsByMessage.get(versionedKey) || []);
|
|
226
320
|
if (message.data.latestVersion === message.data.version) {
|
|
227
321
|
// Store reference to versioned key instead of duplicating the full node
|
|
228
322
|
acc[`${type}:${message.data.id}`] = versionedKey;
|
|
@@ -276,6 +370,25 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
276
370
|
{} as Record<string, NavNode | string>
|
|
277
371
|
);
|
|
278
372
|
|
|
373
|
+
const entityNodes = entities.reduce(
|
|
374
|
+
(acc, entity) => {
|
|
375
|
+
const versionedKey = `entity:${entity.data.id}:${entity.data.version}`;
|
|
376
|
+
acc[versionedKey] = {
|
|
377
|
+
type: 'item',
|
|
378
|
+
title: entity.data.name,
|
|
379
|
+
badge: 'Entity',
|
|
380
|
+
summary: entity.data.summary,
|
|
381
|
+
icon: 'Box',
|
|
382
|
+
href: buildUrl(`/docs/entities/${entity.data.id}/${entity.data.version}`),
|
|
383
|
+
};
|
|
384
|
+
if (entity.data.latestVersion === entity.data.version) {
|
|
385
|
+
acc[`entity:${entity.data.id}`] = versionedKey;
|
|
386
|
+
}
|
|
387
|
+
return acc;
|
|
388
|
+
},
|
|
389
|
+
{} as Record<string, NavNode | string>
|
|
390
|
+
);
|
|
391
|
+
|
|
279
392
|
const designNodes = designs.reduce(
|
|
280
393
|
(acc, design) => {
|
|
281
394
|
acc[`design:${design.data.id}`] = {
|
|
@@ -435,6 +548,13 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
435
548
|
pages: dataProducts.map((dataProduct) => `data-product:${dataProduct.data.id}:${dataProduct.data.version}`),
|
|
436
549
|
});
|
|
437
550
|
|
|
551
|
+
const entitiesList = createLeaf(entities, {
|
|
552
|
+
type: 'item',
|
|
553
|
+
title: 'Entities',
|
|
554
|
+
icon: 'Box',
|
|
555
|
+
pages: entities.map((entity) => `entity:${entity.data.id}:${entity.data.version}`),
|
|
556
|
+
});
|
|
557
|
+
|
|
438
558
|
const designsList = createLeaf(designs, {
|
|
439
559
|
type: 'item',
|
|
440
560
|
title: 'Designs',
|
|
@@ -498,6 +618,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
498
618
|
'list:flows',
|
|
499
619
|
'list:containers',
|
|
500
620
|
'list:data-products',
|
|
621
|
+
'list:entities',
|
|
501
622
|
'list:designs',
|
|
502
623
|
'list:people',
|
|
503
624
|
];
|
|
@@ -510,6 +631,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
510
631
|
flowsList,
|
|
511
632
|
containersList,
|
|
512
633
|
dataProductsList,
|
|
634
|
+
entitiesList,
|
|
513
635
|
designsList,
|
|
514
636
|
peopleList,
|
|
515
637
|
];
|
|
@@ -537,6 +659,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
537
659
|
...(flowsList ? { 'list:flows': flowsList } : {}),
|
|
538
660
|
...(containersList ? { 'list:containers': containersList } : {}),
|
|
539
661
|
...(dataProductsList ? { 'list:data-products': dataProductsList } : {}),
|
|
662
|
+
...(entitiesList ? { 'list:entities': entitiesList } : {}),
|
|
540
663
|
...(designsList ? { 'list:designs': designsList } : {}),
|
|
541
664
|
...(teamsList ? { 'list:teams': teamsList } : {}),
|
|
542
665
|
...(usersList ? { 'list:users': usersList } : {}),
|
|
@@ -572,6 +695,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
|
|
|
572
695
|
...channelNodes,
|
|
573
696
|
...containerNodes,
|
|
574
697
|
...dataProductNodes,
|
|
698
|
+
...entityNodes,
|
|
575
699
|
...flowNodes,
|
|
576
700
|
...userNodes,
|
|
577
701
|
...teamNodes,
|
|
@@ -24,13 +24,14 @@ export const getFlows = async ({ getAllVersions = true }: Props = {}): Promise<F
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// 1. Fetch collections in parallel
|
|
27
|
-
const [allFlows, allEvents, allCommands] = await Promise.all([
|
|
27
|
+
const [allFlows, allEvents, allCommands, allQueries] = await Promise.all([
|
|
28
28
|
getCollection('flows'),
|
|
29
29
|
getCollection('events'),
|
|
30
30
|
getCollection('commands'),
|
|
31
|
+
getCollection('queries'),
|
|
31
32
|
]);
|
|
32
33
|
|
|
33
|
-
const allMessages = [...allEvents, ...allCommands];
|
|
34
|
+
const allMessages = [...allEvents, ...allCommands, ...allQueries];
|
|
34
35
|
|
|
35
36
|
// 2. Build optimized maps
|
|
36
37
|
const flowMap = createVersionedMap(allFlows);
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"license": "SEE LICENSE IN LICENSE",
|
|
9
9
|
"type": "module",
|
|
10
|
-
"version": "3.
|
|
10
|
+
"version": "3.35.0",
|
|
11
11
|
"publishConfig": {
|
|
12
12
|
"access": "public"
|
|
13
13
|
},
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@ai-sdk/react": "^3.0.17",
|
|
25
|
-
"@astrojs/markdown-remark": "^7.
|
|
26
|
-
"@astrojs/mdx": "^5.0.
|
|
27
|
-
"@astrojs/node": "^10.0
|
|
28
|
-
"@astrojs/react": "^5.0.
|
|
25
|
+
"@astrojs/markdown-remark": "^7.1.1",
|
|
26
|
+
"@astrojs/mdx": "^5.0.4",
|
|
27
|
+
"@astrojs/node": "^10.1.0",
|
|
28
|
+
"@astrojs/react": "^5.0.4",
|
|
29
29
|
"@astrojs/rss": "^4.0.18",
|
|
30
30
|
"@asyncapi/avro-schema-parser": "3.0.24",
|
|
31
31
|
"@asyncapi/parser": "^3.6.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@tanstack/react-table": "^8.17.3",
|
|
52
52
|
"@xyflow/react": "^12.3.6",
|
|
53
53
|
"ai": "^6.0.17",
|
|
54
|
-
"astro": "^6.
|
|
54
|
+
"astro": "^6.3.1",
|
|
55
55
|
"astro-compress": "^2.4.0",
|
|
56
56
|
"astro-expressive-code": "^0.41.7",
|
|
57
57
|
"astro-seo": "^0.8.4",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"elkjs": "^0.10.0",
|
|
69
69
|
"glob": "^13.0.6",
|
|
70
70
|
"gray-matter": "^4.0.3",
|
|
71
|
-
"hono": "4.12.
|
|
71
|
+
"hono": "4.12.18",
|
|
72
72
|
"html-to-image": "^1.11.11",
|
|
73
73
|
"js-yaml": "^4.1.1",
|
|
74
74
|
"jsonpath-plus": "^10.4.0",
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
"@eventcatalog/visualiser": "^3.20.0"
|
|
111
111
|
},
|
|
112
112
|
"devDependencies": {
|
|
113
|
-
"@astrojs/check": "^0.9.
|
|
113
|
+
"@astrojs/check": "^0.9.9",
|
|
114
114
|
"@types/dagre": "^0.7.52",
|
|
115
115
|
"@types/diff": "^5.2.2",
|
|
116
116
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -119,8 +119,8 @@
|
|
|
119
119
|
"@types/lodash.merge": "4.6.9",
|
|
120
120
|
"@types/node": "^20.14.2",
|
|
121
121
|
"@types/pako": "^2.0.3",
|
|
122
|
-
"@types/react": "^
|
|
123
|
-
"@types/react-dom": "^
|
|
122
|
+
"@types/react": "^19.2.13",
|
|
123
|
+
"@types/react-dom": "^19.2.3",
|
|
124
124
|
"@types/react-syntax-highlighter": "^15.5.13",
|
|
125
125
|
"@types/semver": "^7.5.8",
|
|
126
126
|
"@types/shelljs": "^0.8.15",
|