@eventcatalog/core 3.42.0 → 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.
Files changed (52) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/count-resources.cjs +1 -0
  4. package/dist/analytics/count-resources.js +1 -1
  5. package/dist/analytics/log-build.cjs +3 -1
  6. package/dist/analytics/log-build.js +4 -4
  7. package/dist/{chunk-6FAGUEM4.js → chunk-2EI3M7OO.js} +1 -1
  8. package/dist/{chunk-UQIDXF2V.js → chunk-7M5IQL3J.js} +1 -1
  9. package/dist/{chunk-3DVHEVHQ.js → chunk-DAOXTQVS.js} +1 -0
  10. package/dist/{chunk-VPZ77Y6E.js → chunk-KY74BE42.js} +1 -1
  11. package/dist/{chunk-L66TCSM7.js → chunk-QV2PKXZM.js} +3 -2
  12. package/dist/{chunk-QMORF42U.js → chunk-ZONBICNH.js} +8 -0
  13. package/dist/{chunk-KE6YTTLB.js → chunk-ZQHBDPIY.js} +1 -1
  14. package/dist/constants.cjs +1 -1
  15. package/dist/constants.js +1 -1
  16. package/dist/eventcatalog.cjs +11 -1
  17. package/dist/eventcatalog.js +7 -7
  18. package/dist/generate.cjs +1 -1
  19. package/dist/generate.js +3 -3
  20. package/dist/search-indexer.cjs +8 -0
  21. package/dist/search-indexer.js +1 -1
  22. package/dist/utils/cli-logger.cjs +1 -1
  23. package/dist/utils/cli-logger.js +2 -2
  24. package/eventcatalog/src/components/MDX/Attachments.astro +3 -3
  25. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +11 -2
  26. package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +100 -2
  27. package/eventcatalog/src/components/Tables/Discover/columns.tsx +53 -1
  28. package/eventcatalog/src/content.config.ts +61 -0
  29. package/eventcatalog/src/enterprise/collections/resource-docs-utils.ts +19 -0
  30. package/eventcatalog/src/layouts/DiscoverLayout.astro +12 -1
  31. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +98 -46
  32. package/eventcatalog/src/pages/discover/[type]/_index.data.ts +5 -0
  33. package/eventcatalog/src/pages/discover/[type]/index.astro +17 -0
  34. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/_index.data.ts +1 -0
  35. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +68 -2
  36. package/eventcatalog/src/pages/docs/llm/llms-full.txt.ts +1 -0
  37. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +26 -1
  38. package/eventcatalog/src/pages/docs/users/[id]/index.astro +26 -1
  39. package/eventcatalog/src/stores/sidebar-store/builders/adr.ts +150 -0
  40. package/eventcatalog/src/stores/sidebar-store/builders/domain.ts +2 -0
  41. package/eventcatalog/src/stores/sidebar-store/builders/shared.ts +50 -0
  42. package/eventcatalog/src/stores/sidebar-store/state.ts +209 -68
  43. package/eventcatalog/src/types/index.ts +2 -0
  44. package/eventcatalog/src/utils/collection-colors.ts +2 -0
  45. package/eventcatalog/src/utils/collections/adr-constants.ts +53 -0
  46. package/eventcatalog/src/utils/collections/adrs.ts +146 -0
  47. package/eventcatalog/src/utils/collections/icons.ts +2 -0
  48. package/eventcatalog/src/utils/collections/teams.ts +6 -1
  49. package/eventcatalog/src/utils/collections/users.ts +17 -10
  50. package/eventcatalog/src/utils/collections/util.ts +2 -0
  51. package/eventcatalog/src/utils/page-loaders/page-data-loader.ts +2 -0
  52. package/package.json +3 -3
@@ -0,0 +1,146 @@
1
+ import { getCollection, type CollectionEntry } from 'astro:content';
2
+ import type { CollectionTypes, CollectionUserTypes } from '@types';
3
+ import { collectionToResourceMap, createVersionedMap, findInMap, versionMatches } from '@utils/collections/util';
4
+ export {
5
+ ADR_STATUS,
6
+ adrStatusBadgeColor,
7
+ createAdrStatusBadge,
8
+ formatAdrDate,
9
+ formatAdrStatus,
10
+ hasAdrStatus,
11
+ isAdrCollection,
12
+ isDeprecatedAdr,
13
+ isSupersededAdr,
14
+ type AdrStatus,
15
+ } from './adr-constants';
16
+
17
+ const CACHE_ENABLED = process.env.DISABLE_EVENTCATALOG_CACHE !== 'true';
18
+
19
+ export type Adr = CollectionEntry<'adrs'>;
20
+ export type AdrResourceType = NonNullable<Adr['data']['appliesTo']>[number]['type'];
21
+ export type AdrPointer = { id: string; version?: string };
22
+ export type AdrResource = CollectionEntry<CollectionTypes> | CollectionEntry<CollectionUserTypes>;
23
+
24
+ interface Props {
25
+ getAllVersions?: boolean;
26
+ returnBody?: boolean;
27
+ }
28
+
29
+ let memoryCache: Record<string, Adr[]> = {};
30
+
31
+ export const getAdrs = async ({ getAllVersions = true, returnBody = false }: Props = {}): Promise<Adr[]> => {
32
+ const cacheKey = `${getAllVersions ? 'allVersions' : 'currentVersions'}-${returnBody ? 'withBody' : 'noBody'}`;
33
+
34
+ if (memoryCache[cacheKey] && memoryCache[cacheKey].length > 0 && CACHE_ENABLED) {
35
+ return memoryCache[cacheKey];
36
+ }
37
+
38
+ const allAdrs = await getCollection('adrs');
39
+ const adrMap = createVersionedMap(allAdrs);
40
+
41
+ const targetAdrs = allAdrs.filter((adr) => {
42
+ if (adr.data.hidden === true) return false;
43
+ if (!getAllVersions && adr.filePath?.includes('versioned')) return false;
44
+ return true;
45
+ });
46
+
47
+ const processedAdrs = targetAdrs.map((adr) => {
48
+ const adrVersions = adrMap.get(adr.data.id) || [];
49
+ const latestVersion = adrVersions[0]?.data.version || adr.data.version;
50
+ const versions = adrVersions.map((entry) => entry.data.version);
51
+
52
+ return {
53
+ ...adr,
54
+ data: {
55
+ ...adr.data,
56
+ versions,
57
+ latestVersion,
58
+ },
59
+ body: returnBody ? adr.body : undefined,
60
+ };
61
+ });
62
+
63
+ processedAdrs.sort((a, b) => {
64
+ const dateCompare = Number(b.data.date) - Number(a.data.date);
65
+ if (dateCompare !== 0) return dateCompare;
66
+ return (a.data.name || a.data.id).localeCompare(b.data.name || b.data.id);
67
+ });
68
+
69
+ memoryCache[cacheKey] = processedAdrs;
70
+
71
+ return processedAdrs;
72
+ };
73
+
74
+ export const getAdrNodeKey = (adr: Adr) => `adr:${adr.data.id}:${adr.data.version}`;
75
+
76
+ export const getAdrAliasNodeKey = (adr: Adr) => `adr:${adr.data.id}`;
77
+
78
+ export const getAdrResourceNodeKey = (resource: AdrResource) => {
79
+ const resourceType = collectionToResourceMap[resource.collection as keyof typeof collectionToResourceMap];
80
+ if (!resourceType) return undefined;
81
+ if (resource.collection === 'users' || resource.collection === 'teams') return `${resourceType}:${resource.data.id}`;
82
+ return `${resourceType}:${resource.data.id}:${(resource.data as any).version}`;
83
+ };
84
+
85
+ const isResourcePointerMatch = (resource: AdrResource, pointer: NonNullable<Adr['data']['appliesTo']>[number]) => {
86
+ const resourceType = collectionToResourceMap[resource.collection as keyof typeof collectionToResourceMap];
87
+ if (pointer.type !== resourceType || pointer.id !== resource.data.id) return false;
88
+
89
+ const resourceVersion = (resource.data as any).version;
90
+ if (!resourceVersion) return true;
91
+ if (!pointer.version || pointer.version === 'latest') return true;
92
+
93
+ return versionMatches(resourceVersion, pointer.version);
94
+ };
95
+
96
+ export const getAdrsForResource = (resource: AdrResource, adrs: Adr[]) => {
97
+ return adrs.filter((adr) => (adr.data.appliesTo || []).some((pointer) => isResourcePointerMatch(resource, pointer)));
98
+ };
99
+
100
+ export const resolveAdrPointers = (pointers: AdrPointer[] | undefined, adrs: Adr[]) => {
101
+ if (!pointers || pointers.length === 0) return [];
102
+
103
+ const adrMap = createVersionedMap(adrs);
104
+ return pointers.map((pointer) => findInMap(adrMap, pointer.id, pointer.version)).filter((adr): adr is Adr => !!adr);
105
+ };
106
+
107
+ export const getAdrRelationships = (adr: Adr, adrs: Adr[]) => {
108
+ const supersedes = resolveAdrPointers(adr.data.supersedes, adrs);
109
+ const explicitSupersededBy = resolveAdrPointers(adr.data.supersededBy, adrs);
110
+ const derivedSupersededBy = adrs.filter((candidate) =>
111
+ (candidate.data.supersedes || []).some((pointer) => {
112
+ if (pointer.id !== adr.data.id) return false;
113
+ return !pointer.version || pointer.version === 'latest' || versionMatches(adr.data.version, pointer.version);
114
+ })
115
+ );
116
+
117
+ const amends = resolveAdrPointers(adr.data.amends, adrs);
118
+ const explicitAmendedBy = resolveAdrPointers(adr.data.amendedBy, adrs);
119
+ const derivedAmendedBy = adrs.filter((candidate) =>
120
+ (candidate.data.amends || []).some((pointer) => {
121
+ if (pointer.id !== adr.data.id) return false;
122
+ return !pointer.version || pointer.version === 'latest' || versionMatches(adr.data.version, pointer.version);
123
+ })
124
+ );
125
+
126
+ return {
127
+ supersedes,
128
+ supersededBy: uniqueAdrs([...explicitSupersededBy, ...derivedSupersededBy], adr),
129
+ amends,
130
+ amendedBy: uniqueAdrs([...explicitAmendedBy, ...derivedAmendedBy], adr),
131
+ related: resolveAdrPointers(adr.data.related, adrs),
132
+ };
133
+ };
134
+
135
+ const uniqueAdrs = (adrs: Adr[], currentAdr?: Adr) => {
136
+ const seen = new Set<string>();
137
+
138
+ return adrs.filter((adr) => {
139
+ if (currentAdr && adr.data.id === currentAdr.data.id && adr.data.version === currentAdr.data.version) return false;
140
+
141
+ const key = `${adr.data.id}:${adr.data.version}`;
142
+ if (seen.has(key)) return false;
143
+ seen.add(key);
144
+ return true;
145
+ });
146
+ };
@@ -21,6 +21,8 @@ export const getIconForCollection = (collection: string) => {
21
21
  return RectangleGroupIcon;
22
22
  case 'agents':
23
23
  return Bot;
24
+ case 'adrs':
25
+ return BookText;
24
26
  case 'services':
25
27
  return ServerIcon;
26
28
  case 'events':
@@ -1,6 +1,7 @@
1
1
  import type { CollectionTypes } from '@types';
2
2
  import { getCollection } from 'astro:content';
3
3
  import type { CollectionEntry } from 'astro:content';
4
+ import { getAdrs } from './adrs';
4
5
 
5
6
  export type Team = CollectionEntry<'teams'>;
6
7
  const CACHE_ENABLED = process.env.DISABLE_EVENTCATALOG_CACHE !== 'true';
@@ -15,7 +16,7 @@ export const getTeams = async (): Promise<Team[]> => {
15
16
  }
16
17
 
17
18
  // 1. Fetch all collections in parallel
18
- const [allTeams, allAgents, allDomains, allServices, allEvents, allCommands, allQueries] = await Promise.all([
19
+ const [allTeams, allAgents, allDomains, allServices, allEvents, allCommands, allQueries, allAdrs] = await Promise.all([
19
20
  getCollection('teams'),
20
21
  getCollection('agents'),
21
22
  getCollection('domains'),
@@ -23,6 +24,7 @@ export const getTeams = async (): Promise<Team[]> => {
23
24
  getCollection('events'),
24
25
  getCollection('commands'),
25
26
  getCollection('queries'),
27
+ getAdrs({ getAllVersions: false }),
26
28
  ]);
27
29
 
28
30
  // 2. Filter teams
@@ -52,6 +54,7 @@ export const getTeams = async (): Promise<Team[]> => {
52
54
  addToIndex(allEvents);
53
55
  addToIndex(allCommands);
54
56
  addToIndex(allQueries);
57
+ addToIndex(allAdrs);
55
58
 
56
59
  // 4. Enrich teams using the ownership index
57
60
  const processedTeams = targetTeams.map((team) => {
@@ -65,6 +68,7 @@ export const getTeams = async (): Promise<Team[]> => {
65
68
  const ownedEvents = ownedItems.filter((i) => i.collection === 'events') as CollectionEntry<'events'>[];
66
69
  const ownedCommands = ownedItems.filter((i) => i.collection === 'commands') as CollectionEntry<'commands'>[];
67
70
  const ownedQueries = ownedItems.filter((i) => i.collection === 'queries') as CollectionEntry<'queries'>[];
71
+ const ownedAdrs = ownedItems.filter((i) => i.collection === 'adrs') as CollectionEntry<'adrs'>[];
68
72
 
69
73
  return {
70
74
  ...team,
@@ -76,6 +80,7 @@ export const getTeams = async (): Promise<Team[]> => {
76
80
  ownedCommands,
77
81
  ownedQueries,
78
82
  ownedEvents,
83
+ ownedAdrs,
79
84
  },
80
85
  };
81
86
  });
@@ -1,6 +1,7 @@
1
1
  import type { CollectionTypes } from '@types';
2
2
  import { getCollection } from 'astro:content';
3
3
  import type { CollectionEntry } from 'astro:content';
4
+ import { getAdrs } from './adrs';
4
5
 
5
6
  export type User = CollectionEntry<'users'>;
6
7
 
@@ -16,16 +17,19 @@ export const getUsers = async (): Promise<User[]> => {
16
17
  }
17
18
 
18
19
  // 1. Fetch all collections in parallel
19
- const [allUsers, allAgents, allDomains, allServices, allEvents, allCommands, allQueries, allTeams] = await Promise.all([
20
- getCollection('users'),
21
- getCollection('agents'),
22
- getCollection('domains'),
23
- getCollection('services'),
24
- getCollection('events'),
25
- getCollection('commands'),
26
- getCollection('queries'),
27
- getCollection('teams'),
28
- ]);
20
+ const [allUsers, allAgents, allDomains, allServices, allEvents, allCommands, allQueries, allTeams, allAdrs] = await Promise.all(
21
+ [
22
+ getCollection('users'),
23
+ getCollection('agents'),
24
+ getCollection('domains'),
25
+ getCollection('services'),
26
+ getCollection('events'),
27
+ getCollection('commands'),
28
+ getCollection('queries'),
29
+ getCollection('teams'),
30
+ getAdrs({ getAllVersions: false }),
31
+ ]
32
+ );
29
33
 
30
34
  // 2. Filter users
31
35
  const targetUsers = allUsers.filter((user) => user.data.hidden !== true);
@@ -59,6 +63,7 @@ export const getUsers = async (): Promise<User[]> => {
59
63
  addToIndex(allEvents);
60
64
  addToIndex(allCommands);
61
65
  addToIndex(allQueries);
66
+ addToIndex(allAdrs);
62
67
 
63
68
  // Team Membership Index: Map<UserID, Team[]>
64
69
  const teamMembershipMap = new Map<string, typeof visibleTeams>();
@@ -92,6 +97,7 @@ export const getUsers = async (): Promise<User[]> => {
92
97
  const ownedEvents = allOwnedItems.filter((i) => i.collection === 'events') as CollectionEntry<'events'>[];
93
98
  const ownedCommands = allOwnedItems.filter((i) => i.collection === 'commands') as CollectionEntry<'commands'>[];
94
99
  const ownedQueries = allOwnedItems.filter((i) => i.collection === 'queries') as CollectionEntry<'queries'>[];
100
+ const ownedAdrs = allOwnedItems.filter((i) => i.collection === 'adrs') as CollectionEntry<'adrs'>[];
95
101
 
96
102
  return {
97
103
  ...user,
@@ -103,6 +109,7 @@ export const getUsers = async (): Promise<User[]> => {
103
109
  ownedEvents,
104
110
  ownedCommands,
105
111
  ownedQueries,
112
+ ownedAdrs,
106
113
  associatedTeams,
107
114
  },
108
115
  };
@@ -173,6 +173,7 @@ export const findMatchingNodes = (
173
173
  };
174
174
 
175
175
  export const resourceToCollectionMap = {
176
+ adr: 'adrs',
176
177
  agent: 'agents',
177
178
  service: 'services',
178
179
  event: 'events',
@@ -190,6 +191,7 @@ export const resourceToCollectionMap = {
190
191
  } as const;
191
192
 
192
193
  export const collectionToResourceMap = {
194
+ adrs: 'adr',
193
195
  agents: 'agent',
194
196
  services: 'service',
195
197
  events: 'event',
@@ -11,12 +11,14 @@ import { getContainers } from '@utils/collections/containers';
11
11
  import { getDiagrams } from '@utils/collections/diagrams';
12
12
  import type { CollectionEntry } from 'astro:content';
13
13
  import { getDataProducts } from '@utils/collections/data-products';
14
+ import { getAdrs } from '@utils/collections/adrs';
14
15
 
15
16
  type PageDataLoaderOptions = { getAllVersions?: boolean };
16
17
 
17
18
  export const pageDataLoader: Record<PageTypes, (options?: PageDataLoaderOptions) => Promise<CollectionEntry<CollectionTypes>[]>> =
18
19
  {
19
20
  agents: getAgents,
21
+ adrs: getAdrs,
20
22
  events: getEvents,
21
23
  commands: getCommands,
22
24
  queries: getQueries,
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "SEE LICENSE IN LICENSE",
9
9
  "type": "module",
10
- "version": "3.42.0",
10
+ "version": "3.43.0",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -113,8 +113,8 @@
113
113
  "uuid": "^10.0.0",
114
114
  "zod": "^4.3.6",
115
115
  "@eventcatalog/sdk": "2.23.0",
116
- "@eventcatalog/linter": "1.0.26",
117
- "@eventcatalog/visualiser": "^3.22.1"
116
+ "@eventcatalog/visualiser": "^3.22.1",
117
+ "@eventcatalog/linter": "1.0.26"
118
118
  },
119
119
  "devDependencies": {
120
120
  "@astrojs/check": "^0.9.9",