@eventcatalog/core 3.41.4 → 3.43.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/count-resources.cjs +1 -0
- package/dist/analytics/count-resources.js +1 -1
- package/dist/analytics/log-build.cjs +3 -1
- package/dist/analytics/log-build.js +4 -4
- package/dist/{chunk-VQLDZRHC.js → chunk-2EI3M7OO.js} +1 -1
- package/dist/{chunk-COPXPOV2.js → chunk-7M5IQL3J.js} +1 -1
- package/dist/{chunk-3DVHEVHQ.js → chunk-DAOXTQVS.js} +1 -0
- package/dist/{chunk-OH2U6UEJ.js → chunk-KY74BE42.js} +1 -1
- package/dist/{chunk-LYRAK5LI.js → chunk-QV2PKXZM.js} +3 -2
- package/dist/{chunk-QMORF42U.js → chunk-ZONBICNH.js} +8 -0
- package/dist/{chunk-YWG7CCN7.js → chunk-ZQHBDPIY.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/docs/development/developer-tools/api-catalog.md +114 -0
- package/dist/eventcatalog.cjs +11 -1
- package/dist/eventcatalog.js +7 -7
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/search-indexer.cjs +8 -0
- package/dist/search-indexer.js +1 -1
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/src/components/MDX/Attachments.astro +3 -3
- package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +11 -2
- package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +100 -2
- package/eventcatalog/src/components/Tables/Discover/columns.tsx +53 -1
- package/eventcatalog/src/content.config.ts +61 -0
- package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +19 -0
- package/eventcatalog/src/layouts/DiscoverLayout.astro +12 -1
- package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +98 -46
- package/eventcatalog/src/pages/.well-known/api-catalog.ts +191 -0
- package/eventcatalog/src/pages/api-catalog/specifications/[collection]/[id]/[version]/[specification].ts +109 -0
- package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -0
- package/eventcatalog/src/pages/discover/[type]/index.astro +17 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -0
- package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +68 -2
- package/eventcatalog/src/pages/docs/llm/llms-full.txt.ts +1 -0
- package/eventcatalog/src/pages/docs/teams/[id]/index.astro +26 -1
- package/eventcatalog/src/pages/docs/users/[id]/index.astro +26 -1
- package/eventcatalog/src/stores/sidebar-store/builders/adr.ts +150 -0
- package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +2 -0
- package/eventcatalog/src/stores/sidebar-store/builders/shared.ts +50 -0
- package/eventcatalog/src/stores/sidebar-store/state.ts +209 -68
- package/eventcatalog/src/types/index.ts +2 -0
- package/eventcatalog/src/utils/collection-colors.ts +2 -0
- package/eventcatalog/src/utils/collections/adr-constants.ts +53 -0
- package/eventcatalog/src/utils/collections/adrs.ts +146 -0
- package/eventcatalog/src/utils/collections/icons.ts +2 -0
- package/eventcatalog/src/utils/collections/teams.ts +6 -1
- package/eventcatalog/src/utils/collections/users.ts +17 -10
- package/eventcatalog/src/utils/collections/util.ts +2 -0
- package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
- package/package.json +1 -1
|
@@ -6,10 +6,12 @@ import {
|
|
|
6
6
|
getFacetedUniqueValues,
|
|
7
7
|
getFilteredRowModel,
|
|
8
8
|
getPaginationRowModel,
|
|
9
|
+
getSortedRowModel,
|
|
9
10
|
useReactTable,
|
|
10
11
|
type ColumnFiltersState,
|
|
12
|
+
type SortingState,
|
|
11
13
|
} from '@tanstack/react-table';
|
|
12
|
-
import { ChevronLeft, ChevronRight, SearchX, X, Search, Users } from 'lucide-react';
|
|
14
|
+
import { ArrowDown, ArrowUp, ArrowUpDown, ChevronLeft, ChevronRight, SearchX, X, Search, Users } from 'lucide-react';
|
|
13
15
|
import { UserIcon } from '@heroicons/react/24/outline';
|
|
14
16
|
import { useEffect, useMemo, useState } from 'react';
|
|
15
17
|
import type { TableConfiguration } from '@types';
|
|
@@ -17,12 +19,14 @@ import { isSameVersion } from '@utils/collections/version-compare';
|
|
|
17
19
|
import { resolveIconUrl } from '@utils/icon';
|
|
18
20
|
import { FilterDropdown, CheckboxItem } from './FilterComponents';
|
|
19
21
|
import { getDiscoverColumns } from './columns';
|
|
22
|
+
import { formatAdrStatus, type AdrStatus } from '@utils/collections/adr-constants';
|
|
20
23
|
|
|
21
24
|
export type CollectionType =
|
|
22
25
|
| 'agents'
|
|
23
26
|
| 'events'
|
|
24
27
|
| 'commands'
|
|
25
28
|
| 'queries'
|
|
29
|
+
| 'adrs'
|
|
26
30
|
| 'services'
|
|
27
31
|
| 'external-systems'
|
|
28
32
|
| 'domains'
|
|
@@ -41,6 +45,8 @@ export interface DiscoverTableData {
|
|
|
41
45
|
hasDataDependencies?: boolean;
|
|
42
46
|
hasTools?: boolean;
|
|
43
47
|
hasModel?: boolean;
|
|
48
|
+
hasAppliesTo?: boolean;
|
|
49
|
+
hasDecisionMakers?: boolean;
|
|
44
50
|
hasInputs?: boolean;
|
|
45
51
|
hasOutputs?: boolean;
|
|
46
52
|
data: {
|
|
@@ -58,6 +64,13 @@ export interface DiscoverTableData {
|
|
|
58
64
|
textColor?: string;
|
|
59
65
|
url?: string;
|
|
60
66
|
}>;
|
|
67
|
+
status?: string;
|
|
68
|
+
date?: string | Date;
|
|
69
|
+
statusBadge?: {
|
|
70
|
+
content: string;
|
|
71
|
+
backgroundColor?: string;
|
|
72
|
+
textColor?: string;
|
|
73
|
+
};
|
|
61
74
|
producers?: Array<any>;
|
|
62
75
|
consumers?: Array<any>;
|
|
63
76
|
receives?: Array<any>;
|
|
@@ -159,6 +172,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
159
172
|
[collectionType, tableConfiguration]
|
|
160
173
|
);
|
|
161
174
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
|
175
|
+
const [sorting, setSorting] = useState<SortingState>([]);
|
|
162
176
|
const [tableFilter, setTableFilter] = useState('');
|
|
163
177
|
const PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
|
|
164
178
|
const PAGE_SIZE_STORAGE_KEY = 'eventcatalog-discover-page-size';
|
|
@@ -182,6 +196,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
182
196
|
const [selectedAgentModels, setSelectedAgentModels] = useState<string[]>([]);
|
|
183
197
|
const [selectedBadges, setSelectedBadges] = useState<string[]>([]);
|
|
184
198
|
const [selectedProperties, setSelectedProperties] = useState<string[]>([]);
|
|
199
|
+
const [selectedStatuses, setSelectedStatuses] = useState<string[]>([]);
|
|
185
200
|
|
|
186
201
|
// Collect unique badges from all items
|
|
187
202
|
const allBadges = useMemo(() => {
|
|
@@ -286,6 +301,14 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
286
301
|
}
|
|
287
302
|
}
|
|
288
303
|
|
|
304
|
+
// ADR status filter
|
|
305
|
+
if (selectedStatuses.length > 0) {
|
|
306
|
+
const status = row.data.status;
|
|
307
|
+
if (!status || !selectedStatuses.includes(status)) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
289
312
|
// Property filters
|
|
290
313
|
if (selectedProperties.length > 0) {
|
|
291
314
|
for (const prop of selectedProperties) {
|
|
@@ -364,6 +387,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
364
387
|
selectedAgentProviders,
|
|
365
388
|
selectedAgentModels,
|
|
366
389
|
selectedBadges,
|
|
390
|
+
selectedStatuses,
|
|
367
391
|
selectedProperties,
|
|
368
392
|
tableFilter,
|
|
369
393
|
]);
|
|
@@ -378,14 +402,17 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
378
402
|
data: filteredData,
|
|
379
403
|
columns,
|
|
380
404
|
onColumnFiltersChange: setColumnFilters,
|
|
405
|
+
onSortingChange: setSorting,
|
|
381
406
|
getCoreRowModel: getCoreRowModel(),
|
|
382
407
|
getFilteredRowModel: getFilteredRowModel(),
|
|
408
|
+
getSortedRowModel: getSortedRowModel(),
|
|
383
409
|
getFacetedRowModel: getFacetedRowModel(),
|
|
384
410
|
getFacetedUniqueValues: getFacetedUniqueValues(),
|
|
385
411
|
getFacetedMinMaxValues: getFacetedMinMaxValues(),
|
|
386
412
|
getPaginationRowModel: getPaginationRowModel(),
|
|
387
413
|
state: {
|
|
388
414
|
columnFilters,
|
|
415
|
+
sorting,
|
|
389
416
|
columnVisibility,
|
|
390
417
|
},
|
|
391
418
|
initialState: {
|
|
@@ -468,6 +495,27 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
468
495
|
return counts;
|
|
469
496
|
}, [initialData]);
|
|
470
497
|
|
|
498
|
+
const statusCounts = useMemo(() => {
|
|
499
|
+
const counts: Record<string, number> = {};
|
|
500
|
+
initialData.forEach((item) => {
|
|
501
|
+
const status = item.data.status;
|
|
502
|
+
if (status) counts[status] = (counts[status] || 0) + 1;
|
|
503
|
+
});
|
|
504
|
+
return counts;
|
|
505
|
+
}, [initialData]);
|
|
506
|
+
|
|
507
|
+
const statusOptions = useMemo(
|
|
508
|
+
() =>
|
|
509
|
+
Object.keys(statusCounts)
|
|
510
|
+
.map((status) => ({
|
|
511
|
+
id: status,
|
|
512
|
+
name: formatAdrStatus(status as AdrStatus),
|
|
513
|
+
count: statusCounts[status],
|
|
514
|
+
}))
|
|
515
|
+
.sort((a, b) => a.name.localeCompare(b.name)),
|
|
516
|
+
[statusCounts]
|
|
517
|
+
);
|
|
518
|
+
|
|
471
519
|
const toggleDomain = (domainId: string) => {
|
|
472
520
|
setSelectedDomains((prev) => (prev.includes(domainId) ? prev.filter((id) => id !== domainId) : [...prev, domainId]));
|
|
473
521
|
};
|
|
@@ -498,6 +546,10 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
498
546
|
setSelectedBadges((prev) => (prev.includes(badgeContent) ? prev.filter((b) => b !== badgeContent) : [...prev, badgeContent]));
|
|
499
547
|
};
|
|
500
548
|
|
|
549
|
+
const toggleStatus = (status: string) => {
|
|
550
|
+
setSelectedStatuses((prev) => (prev.includes(status) ? prev.filter((item) => item !== status) : [...prev, status]));
|
|
551
|
+
};
|
|
552
|
+
|
|
501
553
|
const toggleProperty = (propertyId: string) => {
|
|
502
554
|
setSelectedProperties((prev) => (prev.includes(propertyId) ? prev.filter((p) => p !== propertyId) : [...prev, propertyId]));
|
|
503
555
|
};
|
|
@@ -510,6 +562,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
510
562
|
setSelectedAgentProviders([]);
|
|
511
563
|
setSelectedAgentModels([]);
|
|
512
564
|
setSelectedBadges([]);
|
|
565
|
+
setSelectedStatuses([]);
|
|
513
566
|
setSelectedProperties([]);
|
|
514
567
|
setShowOnlyLatest(true);
|
|
515
568
|
setOnlyShowDrafts(false);
|
|
@@ -525,6 +578,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
525
578
|
selectedAgentProviders.length +
|
|
526
579
|
selectedAgentModels.length +
|
|
527
580
|
selectedBadges.length +
|
|
581
|
+
selectedStatuses.length +
|
|
528
582
|
selectedProperties.length +
|
|
529
583
|
(!showOnlyLatest ? 1 : 0) +
|
|
530
584
|
(onlyShowDrafts ? 1 : 0);
|
|
@@ -545,6 +599,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
545
599
|
(id) => agentProviders.find((provider) => provider.id === id)?.name || id
|
|
546
600
|
);
|
|
547
601
|
const selectedAgentModelNames = selectedAgentModels.map((id) => agentModels.find((model) => model.id === id)?.name || id);
|
|
602
|
+
const selectedStatusNames = selectedStatuses.map((id) => statusOptions.find((status) => status.id === id)?.name || id);
|
|
548
603
|
|
|
549
604
|
// Filter producers/consumers to only show those with count > 0
|
|
550
605
|
const filteredProducers = producers.filter((p) => (producerCounts[p.id] || 0) > 0);
|
|
@@ -767,6 +822,32 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
767
822
|
</div>
|
|
768
823
|
)}
|
|
769
824
|
|
|
825
|
+
{/* ADR Status Filter */}
|
|
826
|
+
{collectionType === 'adrs' && statusOptions.length > 0 && (
|
|
827
|
+
<div>
|
|
828
|
+
<label className="block text-xs font-medium text-[rgb(var(--ec-page-text)/0.8)] mb-1.5">Status</label>
|
|
829
|
+
<FilterDropdown
|
|
830
|
+
label="Select statuses..."
|
|
831
|
+
selectedItems={selectedStatusNames}
|
|
832
|
+
onClear={() => setSelectedStatuses([])}
|
|
833
|
+
onRemoveItem={(name) => {
|
|
834
|
+
const status = statusOptions.find((item) => item.name === name);
|
|
835
|
+
if (status) toggleStatus(status.id);
|
|
836
|
+
}}
|
|
837
|
+
>
|
|
838
|
+
{statusOptions.map((status) => (
|
|
839
|
+
<CheckboxItem
|
|
840
|
+
key={status.id}
|
|
841
|
+
label={status.name}
|
|
842
|
+
checked={selectedStatuses.includes(status.id)}
|
|
843
|
+
onChange={() => toggleStatus(status.id)}
|
|
844
|
+
count={status.count}
|
|
845
|
+
/>
|
|
846
|
+
))}
|
|
847
|
+
</FilterDropdown>
|
|
848
|
+
</div>
|
|
849
|
+
)}
|
|
850
|
+
|
|
770
851
|
{/* Badges Filter */}
|
|
771
852
|
{allBadges.length > 0 && (
|
|
772
853
|
<div>
|
|
@@ -899,7 +980,24 @@ export function DiscoverTable<T extends DiscoverTableData>({
|
|
|
899
980
|
key={`${header.id}`}
|
|
900
981
|
className="px-4 py-2.5 text-left text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))] uppercase tracking-wider"
|
|
901
982
|
>
|
|
902
|
-
{header.isPlaceholder ? null :
|
|
983
|
+
{header.isPlaceholder ? null : header.column.id === 'date' && header.column.getCanSort() ? (
|
|
984
|
+
<button
|
|
985
|
+
type="button"
|
|
986
|
+
onClick={header.column.getToggleSortingHandler()}
|
|
987
|
+
className="flex items-center gap-1.5 rounded-sm text-left uppercase tracking-wider hover:text-[rgb(var(--ec-page-text))] focus:outline-none focus:ring-2 focus:ring-[rgb(var(--ec-accent))]"
|
|
988
|
+
>
|
|
989
|
+
{flexRender(header.column.columnDef.header, header.getContext())}
|
|
990
|
+
{header.column.getIsSorted() === 'asc' ? (
|
|
991
|
+
<ArrowUp className="h-3.5 w-3.5" />
|
|
992
|
+
) : header.column.getIsSorted() === 'desc' ? (
|
|
993
|
+
<ArrowDown className="h-3.5 w-3.5" />
|
|
994
|
+
) : (
|
|
995
|
+
<ArrowUpDown className="h-3.5 w-3.5 opacity-40" />
|
|
996
|
+
)}
|
|
997
|
+
</button>
|
|
998
|
+
) : (
|
|
999
|
+
flexRender(header.column.columnDef.header, header.getContext())
|
|
1000
|
+
)}
|
|
903
1001
|
</th>
|
|
904
1002
|
))}
|
|
905
1003
|
</tr>
|
|
@@ -17,6 +17,7 @@ import { useStore } from '@nanostores/react';
|
|
|
17
17
|
import { favoritesStore, toggleFavorite, type FavoriteItem } from '../../../stores/favorites-store';
|
|
18
18
|
import type { DiscoverTableData, CollectionType } from './DiscoverTable';
|
|
19
19
|
import type { TableConfiguration } from '@types';
|
|
20
|
+
import { formatAdrDate, isAdrCollection } from '@utils/collections/adr-constants';
|
|
20
21
|
|
|
21
22
|
const columnHelper = createColumnHelper<DiscoverTableData>();
|
|
22
23
|
|
|
@@ -107,6 +108,7 @@ const createBadgesColumn = (tableConfiguration: TableConfiguration) =>
|
|
|
107
108
|
columnHelper.accessor((row) => row.data.badges, {
|
|
108
109
|
id: 'badges',
|
|
109
110
|
header: () => <span>{tableConfiguration?.columns?.badges?.label || 'Badges'}</span>,
|
|
111
|
+
enableSorting: false,
|
|
110
112
|
cell: (info) => <BadgesCell badges={info.getValue() || []} />,
|
|
111
113
|
meta: {
|
|
112
114
|
showFilter: false,
|
|
@@ -143,7 +145,7 @@ const RowActionsMenu = ({ item, collectionType }: { item: DiscoverTableData; col
|
|
|
143
145
|
const favorites = useStore(favoritesStore);
|
|
144
146
|
const href = buildUrl(`/docs/${item.collection}/${item.data.id}/${item.data.version}`);
|
|
145
147
|
const visualiserHref = buildUrl(`/visualiser/${item.collection}/${item.data.id}/${item.data.version}`);
|
|
146
|
-
const hasVisualiser =
|
|
148
|
+
const hasVisualiser = !isAdrCollection(item.collection);
|
|
147
149
|
const nodeKey = `${item.collection}-${item.data.id}-${item.data.version}`;
|
|
148
150
|
const badgeLabel =
|
|
149
151
|
collectionType === 'external-systems'
|
|
@@ -234,6 +236,7 @@ const createActionsColumn = (collectionType: CollectionType, tableConfiguration:
|
|
|
234
236
|
columnHelper.accessor('data.name', {
|
|
235
237
|
id: 'actions',
|
|
236
238
|
header: () => <span></span>,
|
|
239
|
+
enableSorting: false,
|
|
237
240
|
cell: (info) => {
|
|
238
241
|
const item = info.row.original;
|
|
239
242
|
return <RowActionsMenu item={item} collectionType={collectionType} />;
|
|
@@ -392,6 +395,53 @@ export const getAgentColumns = (tableConfiguration: TableConfiguration) => [
|
|
|
392
395
|
createActionsColumn('agents', tableConfiguration),
|
|
393
396
|
];
|
|
394
397
|
|
|
398
|
+
// ============================================================================
|
|
399
|
+
// ADR COLUMNS
|
|
400
|
+
// ============================================================================
|
|
401
|
+
export const getAdrColumns = (tableConfiguration: TableConfiguration) => [
|
|
402
|
+
columnHelper.accessor('data.name', {
|
|
403
|
+
id: 'name',
|
|
404
|
+
header: () => <span>{tableConfiguration?.columns?.name?.label || 'Decision record'}</span>,
|
|
405
|
+
cell: (info) => <ResourceNameCell item={info.row.original} />,
|
|
406
|
+
meta: {
|
|
407
|
+
filterVariant: 'name',
|
|
408
|
+
},
|
|
409
|
+
}),
|
|
410
|
+
createSummaryColumn(tableConfiguration),
|
|
411
|
+
columnHelper.accessor('data.statusBadge', {
|
|
412
|
+
id: 'status',
|
|
413
|
+
header: () => <span>{tableConfiguration?.columns?.status?.label || 'Status'}</span>,
|
|
414
|
+
enableSorting: false,
|
|
415
|
+
cell: (info) => {
|
|
416
|
+
const badge = info.getValue();
|
|
417
|
+
if (!badge) return <span className="text-xs text-[rgb(var(--ec-icon-color))]">-</span>;
|
|
418
|
+
return <BadgesCell badges={[badge]} />;
|
|
419
|
+
},
|
|
420
|
+
meta: {
|
|
421
|
+
showFilter: false,
|
|
422
|
+
},
|
|
423
|
+
}),
|
|
424
|
+
columnHelper.accessor('data.date', {
|
|
425
|
+
id: 'date',
|
|
426
|
+
header: () => <span>{tableConfiguration?.columns?.date?.label || 'Date'}</span>,
|
|
427
|
+
sortingFn: (rowA, rowB) => {
|
|
428
|
+
const left = rowA.original.data.date ? new Date(rowA.original.data.date).getTime() : 0;
|
|
429
|
+
const right = rowB.original.data.date ? new Date(rowB.original.data.date).getTime() : 0;
|
|
430
|
+
return left - right;
|
|
431
|
+
},
|
|
432
|
+
cell: (info) => {
|
|
433
|
+
const date = info.getValue();
|
|
434
|
+
if (!date) return <span className="text-xs text-[rgb(var(--ec-icon-color))]">-</span>;
|
|
435
|
+
return <span className="text-[0.8rem] text-[rgb(var(--ec-page-text))]">{formatAdrDate(new Date(date))}</span>;
|
|
436
|
+
},
|
|
437
|
+
meta: {
|
|
438
|
+
showFilter: false,
|
|
439
|
+
},
|
|
440
|
+
}),
|
|
441
|
+
createBadgesColumn(tableConfiguration),
|
|
442
|
+
createActionsColumn('adrs', tableConfiguration),
|
|
443
|
+
];
|
|
444
|
+
|
|
395
445
|
// ============================================================================
|
|
396
446
|
// EVENT COLUMNS
|
|
397
447
|
// ============================================================================
|
|
@@ -677,6 +727,8 @@ export const getDiscoverColumns = (collectionType: CollectionType, tableConfigur
|
|
|
677
727
|
switch (collectionType) {
|
|
678
728
|
case 'agents':
|
|
679
729
|
return getAgentColumns(tableConfiguration);
|
|
730
|
+
case 'adrs':
|
|
731
|
+
return getAdrColumns(tableConfiguration);
|
|
680
732
|
case 'events':
|
|
681
733
|
return getEventColumns(tableConfiguration);
|
|
682
734
|
case 'commands':
|
|
@@ -4,6 +4,7 @@ import { glob } from 'astro/loaders';
|
|
|
4
4
|
import { glob as globPackage } from 'glob';
|
|
5
5
|
import { v4 as uuidv4 } from 'uuid';
|
|
6
6
|
import { badge, ownerReference } from './content.config-shared-collections';
|
|
7
|
+
import { ADR_STATUS_VALUES } from './utils/collections/adr-constants';
|
|
7
8
|
import fs from 'fs';
|
|
8
9
|
import path from 'path';
|
|
9
10
|
|
|
@@ -550,6 +551,65 @@ const agents = defineCollection({
|
|
|
550
551
|
.extend(baseSchema.shape),
|
|
551
552
|
});
|
|
552
553
|
|
|
554
|
+
const adrStatus = z.enum(ADR_STATUS_VALUES);
|
|
555
|
+
|
|
556
|
+
const adrPointer = z.object({
|
|
557
|
+
id: z.string(),
|
|
558
|
+
version: z.string().optional().default('latest'),
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
const adrResourcePointer = adrPointer.extend({
|
|
562
|
+
type: z.enum([
|
|
563
|
+
'agent',
|
|
564
|
+
'service',
|
|
565
|
+
'event',
|
|
566
|
+
'command',
|
|
567
|
+
'query',
|
|
568
|
+
'flow',
|
|
569
|
+
'channel',
|
|
570
|
+
'domain',
|
|
571
|
+
'user',
|
|
572
|
+
'team',
|
|
573
|
+
'container',
|
|
574
|
+
'entity',
|
|
575
|
+
'diagram',
|
|
576
|
+
'data-product',
|
|
577
|
+
]),
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
const adrs = defineCollection({
|
|
581
|
+
loader: glob({
|
|
582
|
+
pattern: withIgnoredBuildArtifacts(['**/adrs/*/index.(md|mdx)', '**/adrs/*/versioned/*/index.(md|mdx)']),
|
|
583
|
+
base: projectDirBase,
|
|
584
|
+
generateId: ({ data }) => `${data.id}-${data.version}`,
|
|
585
|
+
}),
|
|
586
|
+
schema: z
|
|
587
|
+
.object({
|
|
588
|
+
status: adrStatus,
|
|
589
|
+
date: z.coerce.date(),
|
|
590
|
+
decisionMakers: z.array(ownerReference).optional(),
|
|
591
|
+
appliesTo: z.array(adrResourcePointer).optional(),
|
|
592
|
+
supersedes: z.array(adrPointer).optional(),
|
|
593
|
+
supersededBy: z.array(adrPointer).optional(),
|
|
594
|
+
amends: z.array(adrPointer).optional(),
|
|
595
|
+
amendedBy: z.array(adrPointer).optional(),
|
|
596
|
+
related: z.array(adrPointer).optional(),
|
|
597
|
+
detailsPanel: z
|
|
598
|
+
.object({
|
|
599
|
+
status: detailPanelPropertySchema.optional(),
|
|
600
|
+
date: detailPanelPropertySchema.optional(),
|
|
601
|
+
decisionMakers: detailPanelPropertySchema.optional(),
|
|
602
|
+
appliesTo: detailPanelPropertySchema.optional(),
|
|
603
|
+
relationships: detailPanelPropertySchema.optional(),
|
|
604
|
+
owners: detailPanelPropertySchema.optional(),
|
|
605
|
+
repository: detailPanelPropertySchema.optional(),
|
|
606
|
+
changelog: detailPanelPropertySchema.optional(),
|
|
607
|
+
})
|
|
608
|
+
.optional(),
|
|
609
|
+
})
|
|
610
|
+
.extend(baseSchema.shape),
|
|
611
|
+
});
|
|
612
|
+
|
|
553
613
|
// 1) Put this near your other enums/utilities
|
|
554
614
|
const containerTypeEnum = z.enum([
|
|
555
615
|
// Core
|
|
@@ -915,6 +975,7 @@ export const collections = {
|
|
|
915
975
|
queries,
|
|
916
976
|
services,
|
|
917
977
|
agents,
|
|
978
|
+
adrs,
|
|
918
979
|
channels,
|
|
919
980
|
users,
|
|
920
981
|
teams,
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { getCollection, type CollectionEntry } from 'astro:content';
|
|
7
|
+
import fs from 'node:fs';
|
|
7
8
|
import path from 'node:path';
|
|
8
9
|
import { coerce, rcompare } from 'semver';
|
|
9
10
|
import { sortVersioned } from '../../utils/collections/util';
|
|
@@ -77,6 +78,16 @@ let memoryResourceLookupPromise: Promise<Record<ResourceCollection, ResourceLook
|
|
|
77
78
|
const normalizePath = (value: string) => value.replace(/\\/g, '/').replace(/^\.\//, '');
|
|
78
79
|
const normalizeTypeName = (value: string) => value.trim().toLowerCase();
|
|
79
80
|
|
|
81
|
+
const isMissingGeneratedContentFile = (filePath: string) => {
|
|
82
|
+
const normalizedPath = normalizePath(filePath);
|
|
83
|
+
|
|
84
|
+
if (!path.isAbsolute(filePath) && !normalizedPath.startsWith('../')) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return !fs.existsSync(filePath);
|
|
89
|
+
};
|
|
90
|
+
|
|
80
91
|
const inferOrderFromFilePath = (filePath: string): number | undefined => {
|
|
81
92
|
const normalizedPath = normalizePath(filePath);
|
|
82
93
|
const fileName = normalizedPath.split('/').pop();
|
|
@@ -373,6 +384,10 @@ export const getResourceDocs = async (): Promise<ResourceDocEntry[]> => {
|
|
|
373
384
|
return null;
|
|
374
385
|
}
|
|
375
386
|
|
|
387
|
+
if (isMissingGeneratedContentFile(doc.filePath)) {
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
|
|
376
391
|
const resolvedResource = resolveResourceFromPath(doc.filePath, lookups);
|
|
377
392
|
if (!resolvedResource) {
|
|
378
393
|
return null;
|
|
@@ -483,6 +498,10 @@ export const getResourceDocCategories = async (): Promise<ResourceDocCategoryEnt
|
|
|
483
498
|
continue;
|
|
484
499
|
}
|
|
485
500
|
|
|
501
|
+
if (isMissingGeneratedContentFile(category.filePath)) {
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
|
|
486
505
|
const resolvedResource = resolveResourceFromPath(category.filePath, lookups);
|
|
487
506
|
if (!resolvedResource) {
|
|
488
507
|
continue;
|
|
@@ -10,7 +10,8 @@ import { getServices } from '@utils/collections/services';
|
|
|
10
10
|
import { buildUrl } from '@utils/url-builder';
|
|
11
11
|
import { getQueries } from '@utils/collections/queries';
|
|
12
12
|
import { getContainers } from '@utils/collections/containers';
|
|
13
|
-
import { DatabaseIcon } from 'lucide-react';
|
|
13
|
+
import { BookText, DatabaseIcon } from 'lucide-react';
|
|
14
|
+
import { getAdrs } from '@utils/collections/adrs';
|
|
14
15
|
import { MagnifyingGlassIcon } from '@heroicons/react/20/solid';
|
|
15
16
|
import VerticalSideBarLayout from './VerticalSideBarLayout.astro';
|
|
16
17
|
import Checkbox from '@components/Checkbox.astro';
|
|
@@ -23,6 +24,7 @@ const services = await getServices();
|
|
|
23
24
|
const domains = await getDomains();
|
|
24
25
|
const flows = await getFlows();
|
|
25
26
|
const containers = await getContainers();
|
|
27
|
+
const adrs = await getAdrs();
|
|
26
28
|
export interface Props<T extends TCollectionTypes> {
|
|
27
29
|
title: string;
|
|
28
30
|
subtitle: string;
|
|
@@ -85,6 +87,15 @@ const tabs = [
|
|
|
85
87
|
enabled: domains.length > 0,
|
|
86
88
|
visible: domains.length > 0,
|
|
87
89
|
},
|
|
90
|
+
{
|
|
91
|
+
label: `Decision Records (${adrs.length})`,
|
|
92
|
+
href: buildUrl('/discover/adrs'),
|
|
93
|
+
isActive: currentPath === '/discover/adrs',
|
|
94
|
+
icon: BookText,
|
|
95
|
+
activeColor: 'purple',
|
|
96
|
+
enabled: adrs.length > 0,
|
|
97
|
+
visible: adrs.length > 0,
|
|
98
|
+
},
|
|
88
99
|
{
|
|
89
100
|
label: `Data (${containers.length})`,
|
|
90
101
|
href: buildUrl('/discover/containers'),
|