@eventcatalog/core 4.8.4 → 4.10.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-EGWBSVND.js → chunk-5XURY2JV.js} +1 -1
- package/dist/{chunk-FQEK3FUI.js → chunk-BDFTJVGN.js} +1 -1
- package/dist/{chunk-QB4W7ZUL.js → chunk-BQXEWQ5J.js} +1 -1
- package/dist/{chunk-Y57SL3H3.js → chunk-HFAQXAG3.js} +1 -1
- package/dist/{chunk-AATZMWL3.js → chunk-IC6XSXJO.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/Badge.astro +3 -1
- package/eventcatalog/src/components/FieldsExplorer/FieldNodeGraph.tsx +0 -5
- package/eventcatalog/src/components/MDX/Design/Design.astro +2 -0
- package/eventcatalog/src/components/MDX/EntityMap/EntityMap.astro +2 -0
- package/eventcatalog/src/components/MDX/Flow/Flow.astro +2 -0
- package/eventcatalog/src/components/MDX/NodeGraph/AstroNodeGraph.tsx +5 -7
- package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.astro +5 -0
- package/eventcatalog/src/components/MDX/SchemaViewer/schema-viewer-utils.spec.ts +3 -3
- package/eventcatalog/src/components/MDX/SchemaViewer/schema-viewer-utils.ts +2 -2
- package/eventcatalog/src/components/SchemaExplorer/useDarkMode.ts +13 -4
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +121 -88
- package/eventcatalog/src/components/SideNav/NestedSideBar/storage.ts +55 -7
- package/eventcatalog/src/components/SideNav/NestedSideBar/utils.spec.ts +59 -15
- package/eventcatalog/src/components/SideNav/NestedSideBar/utils.ts +53 -7
- package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +1 -1
- package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +2 -2
- package/eventcatalog/src/content.config.ts +71 -1
- package/eventcatalog/src/enterprise/api/schemas/[collection]/[id]/[version]/index.ts +3 -3
- package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +19 -0
- package/eventcatalog/src/enterprise/fields/pages/fields.astro +2 -0
- package/eventcatalog/src/enterprise/tools/catalog-tools.ts +1 -1
- package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +1 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +16 -15
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +21 -17
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +1 -1
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +4 -4
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/resources/index.astro +16 -8
- package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +48 -65
- package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +45 -18
- package/eventcatalog/src/pages/docs/llm/schemas.txt.ts +3 -3
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +1 -1
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +1 -1
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/_index.data.ts +6 -4
- package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +6 -2
- package/eventcatalog/src/pages/schemas/explorer/_index.data.ts +2 -2
- package/eventcatalog/src/pages/triggers/[type]/[id]/[version]/index.astro +2 -0
- package/eventcatalog/src/pages/visualiser/designs/[id]/index.astro +2 -0
- package/eventcatalog/src/stores/sidebar-store/builders/adr.ts +96 -34
- package/eventcatalog/src/stores/sidebar-store/builders/agent.ts +167 -75
- package/eventcatalog/src/stores/sidebar-store/builders/container.ts +135 -59
- package/eventcatalog/src/stores/sidebar-store/builders/data-product.ts +144 -58
- package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +306 -188
- package/eventcatalog/src/stores/sidebar-store/builders/entity.ts +108 -39
- package/eventcatalog/src/stores/sidebar-store/builders/flow.ts +147 -63
- package/eventcatalog/src/stores/sidebar-store/builders/message.ts +213 -122
- package/eventcatalog/src/stores/sidebar-store/builders/service.ts +223 -127
- package/eventcatalog/src/stores/sidebar-store/builders/shared.ts +3 -23
- package/eventcatalog/src/stores/sidebar-store/builders/system.ts +187 -97
- package/eventcatalog/src/stores/sidebar-store/custom-sidebar.ts +678 -0
- package/eventcatalog/src/stores/sidebar-store/state.ts +66 -36
- package/eventcatalog/src/stores/theme-store.ts +6 -3
- package/eventcatalog/src/styles/tailwind.css +82 -0
- package/eventcatalog/src/utils/collections/resource-docs.ts +1 -0
- package/eventcatalog/src/utils/collections/schema-loader.ts +10 -8
- package/package.json +3 -2
|
@@ -12,20 +12,70 @@ import {
|
|
|
12
12
|
buildAttachmentsSection,
|
|
13
13
|
buildDiagramNavItems,
|
|
14
14
|
buildResourceDocsSection,
|
|
15
|
+
buildArchitectureDecisionsSection,
|
|
15
16
|
} from './shared';
|
|
16
17
|
import { isVisualiserEnabled, isChangelogEnabled } from '@utils/feature';
|
|
17
18
|
import { pluralizeMessageType } from '@utils/collections/messages';
|
|
18
19
|
import { iconFieldsForResource } from '@utils/icon';
|
|
20
|
+
import { resolveSidebarPages, toCustomSidebarContext, type SidebarSpec } from '../custom-sidebar';
|
|
19
21
|
|
|
20
22
|
const uniqueRefs = (refs: string[]) => [...new Set(refs)];
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Predefined sidebar sections for a service, keyed by the token users reference from
|
|
26
|
+
* `sidebar.json` (e.g. `$quick-reference`). Each token is the kebab-cased title of the
|
|
27
|
+
* section as it appears in the default sidebar.
|
|
28
|
+
*/
|
|
29
|
+
export type ServiceSectionKey =
|
|
30
|
+
| 'quick-reference'
|
|
31
|
+
| 'documentation'
|
|
32
|
+
| 'architecture'
|
|
33
|
+
| 'diagrams'
|
|
34
|
+
| 'api-and-contracts'
|
|
35
|
+
| 'resource-groups'
|
|
36
|
+
| 'state-and-persistence'
|
|
37
|
+
| 'entities'
|
|
38
|
+
| 'outbound-messages'
|
|
39
|
+
| 'inbound-messages'
|
|
40
|
+
| 'channels'
|
|
41
|
+
| 'flows'
|
|
42
|
+
| 'decision-records'
|
|
43
|
+
| 'owners'
|
|
44
|
+
| 'code'
|
|
45
|
+
| 'attachments';
|
|
46
|
+
|
|
47
|
+
export type ServiceSections = Record<ServiceSectionKey, NavNode | NavNode[] | null>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Order of sections in the default (generated) sidebar. `decision-records` is deliberately
|
|
51
|
+
* absent — in default mode it is inserted before Owners by `withArchitectureDecisionsSection`
|
|
52
|
+
* in state.ts, and only becomes a first-class token for custom sidebars.
|
|
53
|
+
*/
|
|
54
|
+
export const DEFAULT_SERVICE_SECTION_ORDER: ServiceSectionKey[] = [
|
|
55
|
+
'quick-reference',
|
|
56
|
+
'documentation',
|
|
57
|
+
'architecture',
|
|
58
|
+
'diagrams',
|
|
59
|
+
'api-and-contracts',
|
|
60
|
+
'resource-groups',
|
|
61
|
+
'state-and-persistence',
|
|
62
|
+
'entities',
|
|
63
|
+
'outbound-messages',
|
|
64
|
+
'inbound-messages',
|
|
65
|
+
'channels',
|
|
66
|
+
'flows',
|
|
67
|
+
'owners',
|
|
68
|
+
'code',
|
|
69
|
+
'attachments',
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
export const buildServiceSections = (
|
|
23
73
|
service: CollectionEntry<'services'>,
|
|
24
74
|
owners: any[],
|
|
25
75
|
context: ResourceGroupContext,
|
|
26
76
|
serviceChannels: CollectionEntry<'channels'>[] = [],
|
|
27
77
|
flowRefs: string[] = []
|
|
28
|
-
):
|
|
78
|
+
): ServiceSections => {
|
|
29
79
|
const sendsMessages = service.data.sends || [];
|
|
30
80
|
const receivesMessages = service.data.receives || [];
|
|
31
81
|
const serviceEntities = service.data.entities || [];
|
|
@@ -72,140 +122,186 @@ export const buildServiceNode = (
|
|
|
72
122
|
const diagramNavItems = buildDiagramNavItems(serviceDiagrams, context.diagrams);
|
|
73
123
|
const hasDiagrams = diagramNavItems.length > 0;
|
|
74
124
|
|
|
75
|
-
const isExternalSystem = !!service.data.externalSystem;
|
|
76
|
-
|
|
77
125
|
return {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
126
|
+
'quick-reference': buildQuickReferenceSection(
|
|
127
|
+
[
|
|
128
|
+
{ title: 'Overview', href: buildUrl(docsBasePath) },
|
|
129
|
+
isChangelogEnabled() &&
|
|
130
|
+
shouldRenderSideBarSection(service, 'changelog') && {
|
|
131
|
+
title: 'Changelog',
|
|
132
|
+
href: buildUrl(`${docsBasePath}/changelog`),
|
|
133
|
+
},
|
|
134
|
+
].filter(Boolean) as { title: string; href: string }[]
|
|
135
|
+
),
|
|
136
|
+
documentation: docsSection,
|
|
137
|
+
architecture: {
|
|
138
|
+
type: 'group',
|
|
139
|
+
title: 'Architecture',
|
|
140
|
+
icon: 'Workflow',
|
|
141
|
+
pages: [
|
|
142
|
+
{
|
|
143
|
+
type: 'item',
|
|
144
|
+
title: 'Overview',
|
|
145
|
+
href: buildUrl(`/architecture/services/${service.data.id}/${service.data.version}`),
|
|
146
|
+
},
|
|
147
|
+
renderVisualiser && {
|
|
148
|
+
type: 'item',
|
|
149
|
+
title: 'Map',
|
|
150
|
+
href: buildUrl(`/visualiser/services/${service.data.id}/${service.data.version}`),
|
|
151
|
+
},
|
|
152
|
+
renderVisualiser &&
|
|
153
|
+
renderEntities && {
|
|
101
154
|
type: 'item',
|
|
102
|
-
title: '
|
|
103
|
-
href: buildUrl(`/
|
|
155
|
+
title: 'Entity Map',
|
|
156
|
+
href: buildUrl(`/visualiser/services/${service.data.id}/${service.data.version}/entity-map`),
|
|
104
157
|
},
|
|
105
|
-
|
|
158
|
+
renderVisualiser &&
|
|
159
|
+
hasDataStores && {
|
|
106
160
|
type: 'item',
|
|
107
|
-
title: '
|
|
108
|
-
href: buildUrl(`/visualiser/services/${service.data.id}/${service.data.version}`),
|
|
161
|
+
title: 'Data Dependency Graph',
|
|
162
|
+
href: buildUrl(`/visualiser/services/${service.data.id}/${service.data.version}/data`),
|
|
109
163
|
},
|
|
110
|
-
|
|
111
|
-
|
|
164
|
+
].filter(Boolean) as ChildRef[],
|
|
165
|
+
},
|
|
166
|
+
diagrams: hasDiagrams
|
|
167
|
+
? {
|
|
168
|
+
type: 'group',
|
|
169
|
+
title: 'Diagrams',
|
|
170
|
+
icon: 'FileImage',
|
|
171
|
+
pages: diagramNavItems,
|
|
172
|
+
}
|
|
173
|
+
: null,
|
|
174
|
+
'api-and-contracts': renderSpecifications
|
|
175
|
+
? {
|
|
176
|
+
type: 'group',
|
|
177
|
+
title: 'API & Contracts',
|
|
178
|
+
icon: 'FileCode',
|
|
179
|
+
pages: [
|
|
180
|
+
...openAPISpecifications.map((specification) => ({
|
|
112
181
|
type: 'item',
|
|
113
|
-
title:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
182
|
+
title: `${specification.name}`,
|
|
183
|
+
leftIcon: '/icons/openapi-black.svg',
|
|
184
|
+
href: buildUrl(`${docsBasePath}/spec/${specification.filenameWithoutExtension}`),
|
|
185
|
+
})),
|
|
186
|
+
...asyncAPISpecifications.map((specification) => ({
|
|
118
187
|
type: 'item',
|
|
119
|
-
title:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
title: `${specification.name}`,
|
|
138
|
-
leftIcon: '/icons/openapi-black.svg',
|
|
139
|
-
href: buildUrl(`${docsBasePath}/spec/${specification.filenameWithoutExtension}`),
|
|
140
|
-
})),
|
|
141
|
-
...asyncAPISpecifications.map((specification) => ({
|
|
142
|
-
type: 'item',
|
|
143
|
-
title: `${specification.name}`,
|
|
144
|
-
leftIcon: '/icons/asyncapi-black.svg',
|
|
145
|
-
href: buildUrl(`${docsBasePath}/asyncapi/${specification.filenameWithoutExtension}`),
|
|
146
|
-
})),
|
|
147
|
-
...graphQLSpecifications.map((specification) => ({
|
|
148
|
-
type: 'item',
|
|
149
|
-
title: `${specification.name}`,
|
|
150
|
-
leftIcon: '/icons/graphql-black.svg',
|
|
151
|
-
href: buildUrl(`${docsBasePath}/graphql/${specification.filenameWithoutExtension}`),
|
|
152
|
-
})),
|
|
153
|
-
],
|
|
154
|
-
},
|
|
155
|
-
renderResourceGroups && buildResourceGroupSections(resourceGroups, context),
|
|
156
|
-
hasDataStores && {
|
|
157
|
-
type: 'group',
|
|
158
|
-
title: 'State and Persistence',
|
|
159
|
-
icon: 'Database',
|
|
160
|
-
pages: dataStoresInService.map(
|
|
161
|
-
(dataStore) => `container:${(dataStore as any).data.id}:${(dataStore as any).data.version}`
|
|
162
|
-
),
|
|
163
|
-
},
|
|
164
|
-
renderEntities && {
|
|
165
|
-
type: 'group',
|
|
166
|
-
title: 'Entities',
|
|
167
|
-
icon: 'Box',
|
|
168
|
-
pages: serviceEntities.map((entity) => ({
|
|
169
|
-
type: 'item',
|
|
170
|
-
title: (entity as any).data?.name || (entity as any).data.id,
|
|
171
|
-
href: buildUrl(`/docs/entities/${(entity as any).data.id}/${(entity as any).data.version}`),
|
|
172
|
-
})),
|
|
173
|
-
},
|
|
174
|
-
sendsMessages.length > 0 &&
|
|
175
|
-
renderMessages && {
|
|
188
|
+
title: `${specification.name}`,
|
|
189
|
+
leftIcon: '/icons/asyncapi-black.svg',
|
|
190
|
+
href: buildUrl(`${docsBasePath}/asyncapi/${specification.filenameWithoutExtension}`),
|
|
191
|
+
})),
|
|
192
|
+
...graphQLSpecifications.map((specification) => ({
|
|
193
|
+
type: 'item',
|
|
194
|
+
title: `${specification.name}`,
|
|
195
|
+
leftIcon: '/icons/graphql-black.svg',
|
|
196
|
+
href: buildUrl(`${docsBasePath}/graphql/${specification.filenameWithoutExtension}`),
|
|
197
|
+
})),
|
|
198
|
+
],
|
|
199
|
+
}
|
|
200
|
+
: null,
|
|
201
|
+
'resource-groups': renderResourceGroups
|
|
202
|
+
? (buildResourceGroupSections(resourceGroups, context).filter(Boolean) as NavNode[])
|
|
203
|
+
: null,
|
|
204
|
+
'state-and-persistence': hasDataStores
|
|
205
|
+
? {
|
|
176
206
|
type: 'group',
|
|
177
|
-
title: '
|
|
178
|
-
icon: '
|
|
179
|
-
pages:
|
|
180
|
-
(
|
|
207
|
+
title: 'State and Persistence',
|
|
208
|
+
icon: 'Database',
|
|
209
|
+
pages: dataStoresInService.map(
|
|
210
|
+
(dataStore) => `container:${(dataStore as any).data.id}:${(dataStore as any).data.version}`
|
|
181
211
|
),
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
|
|
212
|
+
}
|
|
213
|
+
: null,
|
|
214
|
+
entities: renderEntities
|
|
215
|
+
? {
|
|
185
216
|
type: 'group',
|
|
186
|
-
title: '
|
|
187
|
-
icon: '
|
|
188
|
-
pages:
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
217
|
+
title: 'Entities',
|
|
218
|
+
icon: 'Box',
|
|
219
|
+
pages: serviceEntities.map((entity) => ({
|
|
220
|
+
type: 'item',
|
|
221
|
+
title: (entity as any).data?.name || (entity as any).data.id,
|
|
222
|
+
href: buildUrl(`/docs/entities/${(entity as any).data.id}/${(entity as any).data.version}`),
|
|
223
|
+
})),
|
|
224
|
+
}
|
|
225
|
+
: null,
|
|
226
|
+
'outbound-messages':
|
|
227
|
+
sendsMessages.length > 0 && renderMessages
|
|
228
|
+
? {
|
|
229
|
+
type: 'group',
|
|
230
|
+
title: 'Outbound Messages',
|
|
231
|
+
icon: 'Mail',
|
|
232
|
+
pages: sendsMessages.map(
|
|
233
|
+
(message) => `${pluralizeMessageType(message as any)}:${(message as any).data.id}:${(message as any).data.version}`
|
|
234
|
+
),
|
|
235
|
+
}
|
|
236
|
+
: null,
|
|
237
|
+
'inbound-messages':
|
|
238
|
+
receivesMessages.length > 0 && renderMessages
|
|
239
|
+
? {
|
|
240
|
+
type: 'group',
|
|
241
|
+
title: 'Inbound Messages',
|
|
242
|
+
icon: 'Mail',
|
|
243
|
+
pages: receivesMessages.map(
|
|
244
|
+
(receive) => `${pluralizeMessageType(receive as any)}:${(receive as any).data.id}:${(receive as any).data.version}`
|
|
245
|
+
),
|
|
246
|
+
}
|
|
247
|
+
: null,
|
|
248
|
+
channels:
|
|
249
|
+
serviceChannels.length > 0
|
|
250
|
+
? {
|
|
251
|
+
type: 'group',
|
|
252
|
+
title: 'Channels',
|
|
253
|
+
icon: 'ArrowRightLeft',
|
|
254
|
+
pages: serviceChannels.map((channel) => `channel:${(channel as any).data.id}:${(channel as any).data.version}`),
|
|
255
|
+
}
|
|
256
|
+
: null,
|
|
257
|
+
flows: hasFlows
|
|
258
|
+
? {
|
|
259
|
+
type: 'group',
|
|
260
|
+
// If the service declares its own flows it owns them ("Flows"); otherwise it is
|
|
261
|
+
// only referenced as a step in someone else's flow ("Appears in flows").
|
|
262
|
+
title: serviceFlows.length > 0 ? 'Flows' : 'Appears in flows',
|
|
263
|
+
icon: 'Waypoints',
|
|
264
|
+
pages: serviceFlowRefs,
|
|
265
|
+
}
|
|
266
|
+
: null,
|
|
267
|
+
'decision-records': shouldRenderSideBarSection(service, 'architectureDecisions')
|
|
268
|
+
? buildArchitectureDecisionsSection(service, context.adrs || [])
|
|
269
|
+
: null,
|
|
270
|
+
owners: renderOwners ? buildOwnersSection(owners) : null,
|
|
271
|
+
code: renderRepository ? buildRepositorySection(service.data.repository as { url: string; language: string }) : null,
|
|
272
|
+
attachments: hasAttachments ? buildAttachmentsSection(service.data.attachments as any[]) : null,
|
|
273
|
+
};
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
export type BuildServiceNodeOptions = {
|
|
277
|
+
/** A parsed `sidebar.json` for this service. When present it replaces the generated sidebar. */
|
|
278
|
+
sidebar?: SidebarSpec;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export const buildServiceNode = (
|
|
282
|
+
service: CollectionEntry<'services'>,
|
|
283
|
+
owners: any[],
|
|
284
|
+
context: ResourceGroupContext,
|
|
285
|
+
serviceChannels: CollectionEntry<'channels'>[] = [],
|
|
286
|
+
flowRefs: string[] = [],
|
|
287
|
+
options: BuildServiceNodeOptions = {}
|
|
288
|
+
): NavNode => {
|
|
289
|
+
const sections = buildServiceSections(service, owners, context, serviceChannels, flowRefs);
|
|
290
|
+
|
|
291
|
+
const pages = resolveSidebarPages(sections, DEFAULT_SERVICE_SECTION_ORDER, {
|
|
292
|
+
sidebar: options.sidebar,
|
|
293
|
+
resource: { collection: 'services', id: service.data.id, version: service.data.version, entry: service },
|
|
294
|
+
context: toCustomSidebarContext(context),
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const isExternalSystem = !!service.data.externalSystem;
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
type: 'item',
|
|
301
|
+
title: service.data.name,
|
|
302
|
+
badge: isExternalSystem ? 'External System' : 'Service',
|
|
303
|
+
summary: service.data.summary,
|
|
304
|
+
...iconFieldsForResource(service.data, isExternalSystem ? 'Globe' : 'Server'),
|
|
305
|
+
pages,
|
|
210
306
|
};
|
|
211
307
|
};
|
|
@@ -5,6 +5,7 @@ import { getAdrNodeKey, getAdrsForResource, type Adr, type AdrResource } from '@
|
|
|
5
5
|
import { buildUrl } from '@utils/url-builder';
|
|
6
6
|
import {
|
|
7
7
|
getGroupedResourceDocsByType,
|
|
8
|
+
getResourceDocTypeLabel,
|
|
8
9
|
type ResourceCollection,
|
|
9
10
|
type ResourceDocEntry,
|
|
10
11
|
type ResourceDocCategoryEntry,
|
|
@@ -25,6 +26,7 @@ export type NavNode = {
|
|
|
25
26
|
title: string;
|
|
26
27
|
collapseKey?: string; // Stable key used to persist collapse state for inline groups
|
|
27
28
|
collapsible?: boolean; // Set to false to keep a group expanded regardless of its size
|
|
29
|
+
collapsed?: boolean; // Explicit initial collapse state (from sidebar.json). Overrides size/collapsible heuristics.
|
|
28
30
|
icon?: string; // Lucide icon name
|
|
29
31
|
subtle?: boolean; // Render lightweight styling for nested subgroup headers
|
|
30
32
|
leftIcon?: string; // Path to SVG icon shown on the left of the label
|
|
@@ -218,35 +220,13 @@ export const buildResourceDocsSection = (
|
|
|
218
220
|
return null;
|
|
219
221
|
}
|
|
220
222
|
|
|
221
|
-
const typeLabelMap: Record<string, string> = {
|
|
222
|
-
adrs: 'ADR',
|
|
223
|
-
runbooks: 'Runbook',
|
|
224
|
-
contracts: 'Contract',
|
|
225
|
-
troubleshooting: 'Troubleshooting',
|
|
226
|
-
guides: 'Guide',
|
|
227
|
-
};
|
|
228
|
-
|
|
229
|
-
const toTypeLabel = (value: string) => {
|
|
230
|
-
if (typeLabelMap[value]) {
|
|
231
|
-
return typeLabelMap[value];
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const normalized = value
|
|
235
|
-
.split(/[-_\s]+/)
|
|
236
|
-
.filter(Boolean)
|
|
237
|
-
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
238
|
-
.join(' ');
|
|
239
|
-
|
|
240
|
-
return normalized || 'Doc';
|
|
241
|
-
};
|
|
242
|
-
|
|
243
223
|
return {
|
|
244
224
|
type: 'group',
|
|
245
225
|
title: 'Documentation',
|
|
246
226
|
icon: 'BookText',
|
|
247
227
|
pages: groupedDocs.map((group) => ({
|
|
248
228
|
type: 'group',
|
|
249
|
-
title: group.label ||
|
|
229
|
+
title: group.label || getResourceDocTypeLabel(group.type),
|
|
250
230
|
subtle: true,
|
|
251
231
|
pages: group.docs.map((doc) => ({
|
|
252
232
|
type: 'item',
|