@eventcatalog/core 4.0.6 → 4.1.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 (44) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/catalog-to-astro-content-directory.cjs +32 -1
  6. package/dist/catalog-to-astro-content-directory.js +2 -2
  7. package/dist/{chunk-7443A7LZ.js → chunk-2PPDVKNK.js} +1 -1
  8. package/dist/{chunk-ZYWUN3T3.js → chunk-2T6ESD3L.js} +1 -1
  9. package/dist/{chunk-O3Y2G6CY.js → chunk-CAJUIMDJ.js} +1 -1
  10. package/dist/{chunk-Z7BGWB5J.js → chunk-OQ36RUHT.js} +1 -1
  11. package/dist/{chunk-FHVBLKWN.js → chunk-PL4YZUAA.js} +1 -1
  12. package/dist/{chunk-ZXAF4JO7.js → chunk-RXZKZGDC.js} +1 -1
  13. package/dist/{chunk-WQNKHIDM.js → chunk-W3SAPOZU.js} +13 -1
  14. package/dist/{chunk-VC6VUJIX.js → chunk-W5JQON7Z.js} +20 -1
  15. package/dist/constants.cjs +1 -1
  16. package/dist/constants.js +1 -1
  17. package/dist/eventcatalog.cjs +33 -2
  18. package/dist/eventcatalog.config.d.cts +8 -0
  19. package/dist/eventcatalog.config.d.ts +8 -0
  20. package/dist/eventcatalog.js +8 -8
  21. package/dist/generate.cjs +1 -1
  22. package/dist/generate.js +3 -3
  23. package/dist/map-catalog-to-astro.cjs +20 -1
  24. package/dist/map-catalog-to-astro.js +1 -1
  25. package/dist/utils/cli-logger.cjs +1 -1
  26. package/dist/utils/cli-logger.js +2 -2
  27. package/dist/watcher.cjs +20 -1
  28. package/dist/watcher.js +2 -2
  29. package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +6 -2
  30. package/eventcatalog/src/components/MDX/RemoteFile.astro +5 -0
  31. package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +7 -9
  32. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +127 -41
  33. package/eventcatalog/src/components/SchemaExplorer/VersionHistoryModal.tsx +2 -2
  34. package/eventcatalog/src/components/SchemaExplorer/types.ts +4 -4
  35. package/eventcatalog/src/enterprise/custom-pages/routes.ts +142 -0
  36. package/eventcatalog/src/enterprise/feature.ts +3 -0
  37. package/eventcatalog/src/enterprise/integrations/eventcatalog-features.ts +84 -1
  38. package/eventcatalog/src/pages/index.astro +1 -1
  39. package/eventcatalog/src/toolkit/layouts/Layout.astro +25 -0
  40. package/eventcatalog/src/toolkit/utils/index.ts +26 -0
  41. package/eventcatalog/src/utils/feature.ts +1 -0
  42. package/eventcatalog/src/utils/json-schema-refs.ts +158 -0
  43. package/eventcatalog/tsconfig.json +5 -1
  44. package/package.json +3 -3
@@ -0,0 +1,158 @@
1
+ type Fetcher = (input: string | URL, init?: RequestInit) => Promise<Response>;
2
+
3
+ type ResolveSchemaRefsOptions = {
4
+ baseUrl: string;
5
+ headers?: HeadersInit;
6
+ fetcher?: Fetcher;
7
+ maxDepth?: number;
8
+ };
9
+
10
+ type ResolveContext = Required<Pick<ResolveSchemaRefsOptions, 'baseUrl' | 'fetcher' | 'maxDepth'>> & {
11
+ headers?: HeadersInit;
12
+ cache: Map<string, unknown>;
13
+ };
14
+
15
+ type RefTarget = {
16
+ schema: unknown;
17
+ root: unknown;
18
+ baseUrl: string;
19
+ refKey: string;
20
+ };
21
+
22
+ const isObject = (value: unknown): value is Record<string, unknown> =>
23
+ typeof value === 'object' && value !== null && !Array.isArray(value);
24
+
25
+ const decodeJsonPointerSegment = (segment: string) => decodeURIComponent(segment).replace(/~1/g, '/').replace(/~0/g, '~');
26
+
27
+ const resolveJsonPointer = (document: unknown, pointer: string): unknown => {
28
+ if (!pointer || pointer === '#') return document;
29
+
30
+ const path = pointer.startsWith('#') ? pointer.slice(1) : pointer;
31
+ if (!path) return document;
32
+ if (!path.startsWith('/')) return undefined;
33
+
34
+ return path
35
+ .slice(1)
36
+ .split('/')
37
+ .map(decodeJsonPointerSegment)
38
+ .reduce<unknown>((current, segment) => {
39
+ if (current === undefined || current === null) return undefined;
40
+ if (Array.isArray(current)) return current[Number(segment)];
41
+ if (isObject(current)) return current[segment];
42
+ return undefined;
43
+ }, document);
44
+ };
45
+
46
+ const splitRef = (ref: string, baseUrl: string) => {
47
+ const [urlPart = '', fragmentPart = ''] = ref.split('#');
48
+ const url = urlPart ? new URL(urlPart, baseUrl).toString() : baseUrl;
49
+ return {
50
+ url,
51
+ fragment: `#${fragmentPart}`,
52
+ refKey: `${url}#${fragmentPart}`,
53
+ };
54
+ };
55
+
56
+ const loadRemoteDocument = async (url: string, context: ResolveContext) => {
57
+ if (context.cache.has(url)) return context.cache.get(url);
58
+
59
+ const response = await context.fetcher(url, {
60
+ headers: context.headers,
61
+ });
62
+
63
+ if (!response.ok) {
64
+ throw new Error(`Failed to fetch referenced schema: ${response.status} ${response.statusText}`);
65
+ }
66
+
67
+ const document = await response.json();
68
+ context.cache.set(url, document);
69
+ return document;
70
+ };
71
+
72
+ const resolveRef = async (
73
+ ref: string,
74
+ root: unknown,
75
+ currentBaseUrl: string,
76
+ context: ResolveContext
77
+ ): Promise<RefTarget | undefined> => {
78
+ const { url, fragment, refKey } = splitRef(ref, currentBaseUrl);
79
+ const isCurrentDocument = url === currentBaseUrl;
80
+ const document = isCurrentDocument ? root : await loadRemoteDocument(url, context);
81
+ const schema = resolveJsonPointer(document, fragment);
82
+
83
+ if (schema === undefined) return undefined;
84
+
85
+ return {
86
+ schema,
87
+ root: document,
88
+ baseUrl: url,
89
+ refKey,
90
+ };
91
+ };
92
+
93
+ const resolveNode = async (
94
+ node: unknown,
95
+ root: unknown,
96
+ currentBaseUrl: string,
97
+ context: ResolveContext,
98
+ seenRefs: Set<string>,
99
+ depth: number
100
+ ): Promise<unknown> => {
101
+ if (depth > context.maxDepth) return node;
102
+
103
+ if (Array.isArray(node)) {
104
+ return Promise.all(node.map((item) => resolveNode(item, root, currentBaseUrl, context, seenRefs, depth)));
105
+ }
106
+
107
+ if (!isObject(node)) return node;
108
+
109
+ const ref = typeof node.$ref === 'string' ? node.$ref : undefined;
110
+ if (ref) {
111
+ const target = await resolveRef(ref, root, currentBaseUrl, context);
112
+ if (!target || seenRefs.has(target.refKey)) return { ...node };
113
+
114
+ const nextSeenRefs = new Set(seenRefs);
115
+ nextSeenRefs.add(target.refKey);
116
+
117
+ const resolvedSchema = await resolveNode(target.schema, target.root, target.baseUrl, context, nextSeenRefs, depth + 1);
118
+ const siblingEntries = Object.entries(node).filter(([key]) => key !== '$ref');
119
+ const resolvedSiblings = Object.fromEntries(
120
+ await Promise.all(
121
+ siblingEntries.map(async ([key, value]) => [
122
+ key,
123
+ await resolveNode(value, root, currentBaseUrl, context, seenRefs, depth),
124
+ ])
125
+ )
126
+ );
127
+
128
+ if (isObject(resolvedSchema)) {
129
+ return {
130
+ ...resolvedSchema,
131
+ ...resolvedSiblings,
132
+ };
133
+ }
134
+
135
+ return Object.keys(resolvedSiblings).length > 0 ? resolvedSiblings : resolvedSchema;
136
+ }
137
+
138
+ return Object.fromEntries(
139
+ await Promise.all(
140
+ Object.entries(node).map(async ([key, value]) => [
141
+ key,
142
+ await resolveNode(value, root, currentBaseUrl, context, seenRefs, depth),
143
+ ])
144
+ )
145
+ );
146
+ };
147
+
148
+ export const resolveSchemaRefs = async (schema: unknown, options: ResolveSchemaRefsOptions): Promise<unknown> => {
149
+ const context: ResolveContext = {
150
+ baseUrl: options.baseUrl,
151
+ headers: options.headers,
152
+ fetcher: options.fetcher ?? fetch,
153
+ maxDepth: options.maxDepth ?? 25,
154
+ cache: new Map([[options.baseUrl, schema]]),
155
+ };
156
+
157
+ return resolveNode(schema, schema, options.baseUrl, context, new Set(), 0);
158
+ };
@@ -9,6 +9,9 @@
9
9
  "@icons/*": ["src/icons/*"],
10
10
  "@components/*": ["src/components/*"],
11
11
  "@catalog/components/*": ["src/custom-defined-components/*"],
12
+ "@catalog/layouts/*": ["src/toolkit/layouts/*"],
13
+ "@catalog/utils": ["src/toolkit/utils/index.ts"],
14
+ "@catalog/utils/*": ["src/toolkit/utils/*"],
12
15
  "@catalog/snippets/*": ["src/snippets/*"],
13
16
  "@types": ["src/types/index.ts"],
14
17
  "@utils/*": ["src/utils/*"],
@@ -22,5 +25,6 @@
22
25
  "jsxImportSource": "react",
23
26
  "types": ["vitest/globals"]
24
27
  },
25
- "include": ["src/**/*", "*.config.*"]
28
+ "include": ["src/**/*", "*.config.*"],
29
+ "exclude": ["src/custom-pages"]
26
30
  }
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "SEE LICENSE IN LICENSE",
9
9
  "type": "module",
10
- "version": "4.0.6",
10
+ "version": "4.1.0",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -117,8 +117,8 @@
117
117
  "uuid": "^10.0.0",
118
118
  "zod": "^4.3.6",
119
119
  "@eventcatalog/sdk": "2.25.0",
120
- "@eventcatalog/visualiser": "^4.0.0",
121
- "@eventcatalog/linter": "1.1.3"
120
+ "@eventcatalog/visualiser": "^4.0.1",
121
+ "@eventcatalog/linter": "1.1.4"
122
122
  },
123
123
  "devDependencies": {
124
124
  "@astrojs/check": "^0.9.9",