@eventcatalog/core 3.44.2 → 3.46.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 (39) 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/{chunk-THDZCUFV.js → chunk-DOHA5HNJ.js} +1 -1
  6. package/dist/{chunk-BLJ5FRR3.js → chunk-FNOYJEUK.js} +1 -1
  7. package/dist/{chunk-LIIOK6SZ.js → chunk-JS6IYB55.js} +1 -1
  8. package/dist/{chunk-IU3D7JRW.js → chunk-TLLUDBO4.js} +1 -1
  9. package/dist/{chunk-RUACTEJR.js → chunk-X4AESI6E.js} +1 -1
  10. package/dist/constants.cjs +1 -1
  11. package/dist/constants.js +1 -1
  12. package/dist/eventcatalog.cjs +1 -1
  13. package/dist/eventcatalog.config.d.cts +29 -0
  14. package/dist/eventcatalog.config.d.ts +29 -0
  15. package/dist/eventcatalog.js +10 -10
  16. package/dist/generate.cjs +1 -1
  17. package/dist/generate.js +3 -3
  18. package/dist/utils/cli-logger.cjs +1 -1
  19. package/dist/utils/cli-logger.js +2 -2
  20. package/eventcatalog/astro.config.mjs +7 -10
  21. package/eventcatalog/ec.config.mjs +20 -0
  22. package/eventcatalog/src/components/MDX/SchemaViewer/SchemaViewerPortal.tsx +1 -1
  23. package/eventcatalog/src/components/MDX/SchemaViewer/SchemaViewerRoot.astro +19 -47
  24. package/eventcatalog/src/components/MDX/SchemaViewer/schema-viewer-utils.spec.ts +53 -0
  25. package/eventcatalog/src/components/MDX/SchemaViewer/schema-viewer-utils.ts +133 -0
  26. package/eventcatalog/src/content.config.ts +65 -0
  27. package/eventcatalog/src/enterprise/api/schemas/[collection]/[id]/[version]/index.ts +42 -50
  28. package/eventcatalog/src/enterprise/tools/catalog-tools.ts +23 -0
  29. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +1 -1
  30. package/eventcatalog/src/pages/docs/llm/schemas.txt.ts +25 -17
  31. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/_index.data.ts +33 -16
  32. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +18 -8
  33. package/eventcatalog/src/pages/schemas/explorer/_index.data.ts +45 -21
  34. package/eventcatalog/src/stores/sidebar-store/builders/message.ts +25 -2
  35. package/eventcatalog/src/stores/sidebar-store/builders/shared.ts +1 -0
  36. package/eventcatalog/src/stores/sidebar-store/state.ts +3 -0
  37. package/eventcatalog/src/utils/collections/schema-loader.ts +523 -0
  38. package/eventcatalog/src/utils/files.ts +1 -1
  39. package/package.json +4 -4
@@ -67,6 +67,7 @@ export type ResourceGroupContext = {
67
67
  entities?: CollectionEntry<'entities'>[];
68
68
  dataProducts: CollectionEntry<'data-products'>[];
69
69
  diagrams: CollectionEntry<'diagrams'>[];
70
+ schemas?: CollectionEntry<'schemas'>[];
70
71
  adrs: Adr[];
71
72
  users?: CollectionEntry<'users'>[];
72
73
  teams?: CollectionEntry<'teams'>[];
@@ -292,6 +292,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
292
292
  dataProducts,
293
293
  entities,
294
294
  adrs,
295
+ schemas,
295
296
  resourceDocs,
296
297
  resourceDocCategories,
297
298
  ] = await Promise.all([
@@ -309,6 +310,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
309
310
  getDataProducts({ getAllVersions: false }),
310
311
  getEntities({ getAllVersions: false }),
311
312
  getAdrs({ getAllVersions: false }),
313
+ getCollection('schemas'),
312
314
  getResourceDocs(),
313
315
  getResourceDocCategories(),
314
316
  ]);
@@ -330,6 +332,7 @@ export const getNestedSideBarData = async (): Promise<NavigationData> => {
330
332
  containers,
331
333
  channels,
332
334
  diagrams,
335
+ schemas,
333
336
  dataProducts,
334
337
  entities,
335
338
  adrs,
@@ -0,0 +1,523 @@
1
+ import type { Loader } from 'astro/loaders';
2
+ import { glob } from 'glob';
3
+ import matter from 'gray-matter';
4
+ import fs from 'node:fs/promises';
5
+ import fsSync from 'node:fs';
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import pc from 'picocolors';
9
+ import { isEventCatalogScaleEnabled } from '../feature';
10
+ import { sortVersioned } from './util';
11
+
12
+ const colors = pc.createColors(true);
13
+
14
+ type MessageCollection = 'events' | 'commands' | 'queries';
15
+
16
+ type SchemaReference = {
17
+ id?: string;
18
+ ref?: string;
19
+ file?: string;
20
+ path?: string;
21
+ name?: string;
22
+ format?: string;
23
+ environments?: string[];
24
+ default?: boolean;
25
+ };
26
+
27
+ type SchemaSourceEntry = {
28
+ provider: string;
29
+ id?: string;
30
+ path?: string;
31
+ url?: string;
32
+ ref?: string;
33
+ [key: string]: unknown;
34
+ };
35
+
36
+ type SchemaSource = {
37
+ type: 'schemas';
38
+ name: string;
39
+ canResolve: (ref: string) => boolean;
40
+ resolve: (
41
+ ref: string,
42
+ context?: { messageFilePath?: string }
43
+ ) => Promise<
44
+ | {
45
+ id: string;
46
+ name?: string;
47
+ format?: string;
48
+ content: string;
49
+ source: SchemaSourceEntry;
50
+ }
51
+ | undefined
52
+ >;
53
+ };
54
+
55
+ type MessageFrontmatter = {
56
+ id?: string;
57
+ name?: string;
58
+ version?: string;
59
+ summary?: string;
60
+ owners?: string[];
61
+ schemaPath?: string;
62
+ schemas?: SchemaReference[];
63
+ };
64
+
65
+ export type MessageSchemaResource = {
66
+ id: string;
67
+ schemaId?: string;
68
+ ref?: string;
69
+ name?: string;
70
+ version?: string;
71
+ format: string;
72
+ content?: string;
73
+ file?: string;
74
+ filePath?: string;
75
+ environments?: string[];
76
+ default?: boolean;
77
+ latest?: boolean;
78
+ message: {
79
+ collection: MessageCollection;
80
+ id: string;
81
+ name?: string;
82
+ version: string;
83
+ summary?: string;
84
+ owners?: string[];
85
+ };
86
+ source: {
87
+ provider: string;
88
+ id?: string;
89
+ path?: string;
90
+ url?: string;
91
+ ref?: string;
92
+ [key: string]: unknown;
93
+ };
94
+ readOnly?: boolean;
95
+ };
96
+
97
+ type InternalMessageSchemaResource = MessageSchemaResource & {
98
+ _context?: {
99
+ messageFilePath?: string;
100
+ };
101
+ };
102
+
103
+ type SchemaLoaderOptions = {
104
+ messages: {
105
+ pattern: string[];
106
+ base?: string;
107
+ };
108
+ sources?: SchemaSource[];
109
+ };
110
+
111
+ type LoaderContext = Parameters<Loader['load']>[0];
112
+
113
+ const MESSAGE_COLLECTIONS: MessageCollection[] = ['events', 'commands', 'queries'];
114
+ const FILE_SCHEMA_REF_PREFIX = 'file://';
115
+
116
+ const normalizePath = (value: string) => value.replace(/\\/g, '/');
117
+
118
+ const getMessageCollectionFromPath = (filePath: string): MessageCollection | undefined => {
119
+ const parts = normalizePath(filePath).split('/');
120
+ return MESSAGE_COLLECTIONS.find((collection) => parts.includes(collection));
121
+ };
122
+
123
+ const getSchemaFormat = (schemaPath: string) => {
124
+ const extension = path.extname(schemaPath).replace('.', '').toLowerCase();
125
+
126
+ if (extension === 'avsc' || extension === 'avro') return 'avro';
127
+ if (extension === 'proto') return 'protobuf';
128
+ if (extension === 'json') return 'jsonschema';
129
+ if (extension === 'yaml' || extension === 'yml') return 'yaml';
130
+
131
+ return extension || 'unknown';
132
+ };
133
+
134
+ const buildGeneratedSchemaId = (message: { collection: MessageCollection; id: string; version: string }, schemaPath: string) =>
135
+ `schema:${message.collection}:${message.id}:${message.version}:${schemaPath}`;
136
+
137
+ const getSchemaCollectionId = ({
138
+ message,
139
+ reference,
140
+ schemaRef,
141
+ schemaFile,
142
+ }: {
143
+ message: { collection: MessageCollection; id: string; version: string };
144
+ reference: SchemaReference;
145
+ schemaRef?: string;
146
+ schemaFile?: string;
147
+ }) => {
148
+ if (schemaRef) return buildGeneratedSchemaId(message, schemaRef);
149
+ if (reference.id) return buildGeneratedSchemaId(message, reference.id);
150
+ return buildGeneratedSchemaId(message, schemaFile as string);
151
+ };
152
+
153
+ const getSchemaFile = (reference: SchemaReference) => reference.file ?? reference.path;
154
+
155
+ const getSchemaRef = (reference: SchemaReference) => {
156
+ if (reference.ref) return reference.ref;
157
+ if (!getSchemaFile(reference)) return reference.id;
158
+ return undefined;
159
+ };
160
+
161
+ const getSchemaDisplayName = ({
162
+ referenceName,
163
+ resolvedName,
164
+ schemaFile,
165
+ filePath,
166
+ schemaRef,
167
+ sourcePath,
168
+ schemaId,
169
+ messageName,
170
+ }: {
171
+ referenceName?: string;
172
+ resolvedName?: string;
173
+ schemaFile?: string;
174
+ filePath?: string;
175
+ schemaRef?: string;
176
+ sourcePath?: string;
177
+ schemaId: string;
178
+ messageName?: string;
179
+ }) => {
180
+ const pathLikeName = schemaFile ?? filePath ?? sourcePath ?? schemaRef ?? schemaId;
181
+ return referenceName ?? resolvedName ?? path.basename(pathLikeName) ?? messageName ?? 'Schema';
182
+ };
183
+
184
+ const schemaFileExists = (schema: MessageSchemaResource): schema is MessageSchemaResource & { filePath: string } =>
185
+ Boolean(schema.filePath && fsSync.existsSync(schema.filePath));
186
+
187
+ const getSchemaProvider = (id: string) => {
188
+ try {
189
+ const url = new URL(id);
190
+ return url.protocol.replace(':', '') || 'external';
191
+ } catch {
192
+ return 'external';
193
+ }
194
+ };
195
+
196
+ const isFileSchemaRef = (ref?: string) => ref?.startsWith(FILE_SCHEMA_REF_PREFIX);
197
+
198
+ const getFileSchemaRefPath = (ref: string, messageFilePath: string) => {
199
+ if (ref.startsWith('file:///') || ref.startsWith('file://localhost/')) {
200
+ try {
201
+ const filePath = fileURLToPath(ref);
202
+ return {
203
+ filePath,
204
+ sourcePath: filePath,
205
+ };
206
+ } catch {
207
+ throw new Error(`Invalid file schema ref "${ref}". Expected file://<relative-path> or file:///absolute/path.`);
208
+ }
209
+ }
210
+
211
+ const sourcePath = decodeURIComponent(ref.slice(FILE_SCHEMA_REF_PREFIX.length));
212
+ if (!sourcePath) {
213
+ throw new Error(`Invalid file schema ref "${ref}". Expected file://<relative-path> or file:///absolute/path.`);
214
+ }
215
+
216
+ return {
217
+ filePath: path.resolve(path.dirname(messageFilePath), sourcePath),
218
+ sourcePath,
219
+ };
220
+ };
221
+
222
+ const getTimestamp = () => {
223
+ const now = new Date();
224
+ return now.toLocaleTimeString('en-US', { hour12: false });
225
+ };
226
+
227
+ const logSchemaInfo = (message: string) => {
228
+ console.log(`${colors.dim(getTimestamp())} ${colors.blue('[schemas]')} ${message}`);
229
+ };
230
+
231
+ const getMessageTypeLabel = (collection: MessageCollection) => {
232
+ if (collection === 'events') return 'event';
233
+ if (collection === 'commands') return 'command';
234
+ return 'query';
235
+ };
236
+
237
+ const getErrorMessage = (error: unknown) => {
238
+ return error instanceof Error ? error.message : String(error);
239
+ };
240
+
241
+ const getSchemaResolveRef = (schema: MessageSchemaResource) => schema.ref ?? schema.id;
242
+
243
+ const buildSchemaSourceErrorMessage = ({
244
+ schema,
245
+ source,
246
+ error,
247
+ }: {
248
+ schema: MessageSchemaResource;
249
+ source: SchemaSource;
250
+ error: unknown;
251
+ }) => {
252
+ const messageType = getMessageTypeLabel(schema.message.collection);
253
+
254
+ return [
255
+ '',
256
+ colors.red(colors.bold('[schemas] Failed to resolve schema')),
257
+ '',
258
+ ` Message: ${messageType} "${schema.message.id}" version "${schema.message.version}"`,
259
+ ` Schema: ${getSchemaResolveRef(schema)}`,
260
+ ` Source: ${source.name}`,
261
+ '',
262
+ colors.bold('Reason:'),
263
+ ` ${getErrorMessage(error)}`,
264
+ '',
265
+ ].join('\n');
266
+ };
267
+
268
+ const addLatestMetadata = (schemas: MessageSchemaResource[]) => {
269
+ const schemasByMessage = schemas.reduce(
270
+ (acc, schema) => {
271
+ const key = `${schema.message.collection}:${schema.message.id}`;
272
+ acc[key] = [...(acc[key] ?? []), schema];
273
+ return acc;
274
+ },
275
+ {} as Record<string, MessageSchemaResource[]>
276
+ );
277
+
278
+ const latestVersionsByMessage = Object.entries(schemasByMessage).reduce(
279
+ (acc, [key, messageSchemas]) => {
280
+ acc[key] = sortVersioned(messageSchemas, (schema) => schema.message.version)[0]?.message.version;
281
+ return acc;
282
+ },
283
+ {} as Record<string, string | undefined>
284
+ );
285
+
286
+ return schemas.map((schema) => {
287
+ const key = `${schema.message.collection}:${schema.message.id}`;
288
+ return {
289
+ ...schema,
290
+ latest: schema.message.version === latestVersionsByMessage[key],
291
+ };
292
+ });
293
+ };
294
+
295
+ export const getMessageSchemasFromFrontmatter = ({
296
+ data,
297
+ collection,
298
+ messageFilePath,
299
+ }: {
300
+ data: MessageFrontmatter;
301
+ collection: MessageCollection;
302
+ messageFilePath: string;
303
+ }): MessageSchemaResource[] => {
304
+ if (!data.id || !data.version) return [];
305
+
306
+ const message = {
307
+ collection,
308
+ id: data.id,
309
+ name: data.name,
310
+ version: data.version,
311
+ summary: data.summary,
312
+ owners: data.owners,
313
+ };
314
+
315
+ const schemaReferences =
316
+ data.schemas?.filter((schema) => getSchemaRef(schema) || getSchemaFile(schema)) ??
317
+ (data.schemaPath
318
+ ? [
319
+ {
320
+ file: data.schemaPath,
321
+ name: 'Schema',
322
+ default: true,
323
+ },
324
+ ]
325
+ : []);
326
+
327
+ return schemaReferences.map((reference) => {
328
+ const schemaFile = getSchemaFile(reference);
329
+ const schemaRef = getSchemaRef(reference);
330
+ const fileSchemaRef = isFileSchemaRef(schemaRef) ? getFileSchemaRefPath(schemaRef as string, messageFilePath) : undefined;
331
+ const schemaFilePath = schemaFile ? path.resolve(path.dirname(messageFilePath), schemaFile) : fileSchemaRef?.filePath;
332
+ const schemaId = getSchemaCollectionId({ message, reference, schemaRef, schemaFile });
333
+ const schemaPathForFormat = schemaFile ?? fileSchemaRef?.filePath;
334
+
335
+ return {
336
+ id: schemaId,
337
+ ...(reference.id && !schemaRef ? { schemaId: reference.id } : {}),
338
+ ...(schemaRef ? { ref: schemaRef } : {}),
339
+ name: getSchemaDisplayName({
340
+ referenceName: reference.name,
341
+ schemaFile,
342
+ filePath: fileSchemaRef?.filePath,
343
+ schemaRef,
344
+ schemaId,
345
+ messageName: data.name,
346
+ }),
347
+ version: data.version,
348
+ format: reference.format ?? (schemaPathForFormat ? getSchemaFormat(schemaPathForFormat) : 'unknown'),
349
+ file: schemaFile,
350
+ filePath: schemaFilePath,
351
+ environments: reference.environments,
352
+ default: reference.default,
353
+ message,
354
+ source: {
355
+ provider: schemaFile || fileSchemaRef ? 'file' : getSchemaProvider(schemaRef ?? schemaId),
356
+ path: schemaFile ?? fileSchemaRef?.sourcePath,
357
+ },
358
+ };
359
+ });
360
+ };
361
+
362
+ const resolveSchemaSource = async (
363
+ schema: InternalMessageSchemaResource,
364
+ source: SchemaSource
365
+ ): Promise<InternalMessageSchemaResource | undefined> => {
366
+ if (schemaFileExists(schema)) return schema;
367
+ if (schema.filePath) return undefined;
368
+
369
+ let resolvedSchema: Awaited<ReturnType<SchemaSource['resolve']>>;
370
+ const schemaResolveRef = getSchemaResolveRef(schema);
371
+
372
+ try {
373
+ resolvedSchema = await source.resolve(schemaResolveRef, schema._context);
374
+ } catch (error) {
375
+ throw new Error(buildSchemaSourceErrorMessage({ schema, source, error }));
376
+ }
377
+
378
+ if (!resolvedSchema) return undefined;
379
+
380
+ const resolvedMessageSchema: InternalMessageSchemaResource = {
381
+ ...schema,
382
+ format: schema.format !== 'unknown' ? schema.format : (resolvedSchema.format ?? 'unknown'),
383
+ content: resolvedSchema.content,
384
+ source: resolvedSchema.source,
385
+ readOnly: true,
386
+ };
387
+
388
+ resolvedMessageSchema.name = getSchemaDisplayName({
389
+ referenceName: schema.name,
390
+ resolvedName: resolvedSchema.name,
391
+ schemaRef: schema.ref,
392
+ sourcePath: resolvedSchema.source.path,
393
+ schemaId: schema.id,
394
+ messageName: schema.message.name,
395
+ });
396
+
397
+ return resolvedMessageSchema;
398
+ };
399
+
400
+ const resolveSchemaSources = async (schemas: InternalMessageSchemaResource[], sources: SchemaSource[] = []) => {
401
+ if (sources.length > 0 && !isEventCatalogScaleEnabled()) {
402
+ throw new Error('Schema sources require EventCatalog Scale.');
403
+ }
404
+
405
+ const localSchemas = schemas.filter(schemaFileExists);
406
+ const externalSchemas = schemas.filter((schema) => !schema.filePath);
407
+ const resolvedExternalSchemas: InternalMessageSchemaResource[] = [];
408
+ const resolvedExternalSchemaIds = new Set<string>();
409
+
410
+ for (const source of sources) {
411
+ const sourceSchemas = externalSchemas.filter((schema) => source.canResolve(getSchemaResolveRef(schema)));
412
+ if (sourceSchemas.length === 0) continue;
413
+
414
+ logSchemaInfo(
415
+ `Loading ${sourceSchemas.length} schema${sourceSchemas.length === 1 ? '' : 's'} from schema source "${source.name}"`
416
+ );
417
+
418
+ const resolvedSchemas = await Promise.all(sourceSchemas.map((schema) => resolveSchemaSource(schema, source)));
419
+ const syncedSchemas = resolvedSchemas.filter((schema): schema is InternalMessageSchemaResource => schema !== undefined);
420
+
421
+ for (const schema of syncedSchemas) {
422
+ resolvedExternalSchemaIds.add(schema.id);
423
+ resolvedExternalSchemas.push(schema);
424
+ }
425
+
426
+ const skippedSchemas = sourceSchemas.length - syncedSchemas.length;
427
+ logSchemaInfo(
428
+ `Synced ${syncedSchemas.length} schema${syncedSchemas.length === 1 ? '' : 's'} from schema source "${source.name}"${
429
+ skippedSchemas > 0 ? ` (${skippedSchemas} skipped)` : ''
430
+ }`
431
+ );
432
+ }
433
+
434
+ return [
435
+ ...localSchemas,
436
+ ...resolvedExternalSchemas,
437
+ ...schemas.filter((schema) => schema.filePath && !schemaFileExists(schema)),
438
+ ].filter((schema) => {
439
+ if (schema.filePath) return schemaFileExists(schema);
440
+ return resolvedExternalSchemaIds.has(schema.id);
441
+ });
442
+ };
443
+
444
+ const loadMessageSchemaResources = async ({ pattern, base }: SchemaLoaderOptions['messages']) => {
445
+ if (!base) return [];
446
+
447
+ const files = await glob(pattern, {
448
+ cwd: base,
449
+ absolute: true,
450
+ nodir: true,
451
+ ignore: ['dist/**', '**/dist/**'],
452
+ });
453
+
454
+ const schemas = await Promise.all(
455
+ files.map(async (file) => {
456
+ const collection = getMessageCollectionFromPath(file);
457
+ if (!collection) return [];
458
+
459
+ const { data } = matter.read(file) as { data: MessageFrontmatter };
460
+ return getMessageSchemasFromFrontmatter({ data, collection, messageFilePath: file }).map((schema) => ({
461
+ ...schema,
462
+ _context: {
463
+ messageFilePath: file,
464
+ },
465
+ }));
466
+ })
467
+ );
468
+
469
+ return schemas.flat();
470
+ };
471
+
472
+ const stripSchemaLoaderContext = (schema: InternalMessageSchemaResource): MessageSchemaResource => {
473
+ const { _context, ...publicSchema } = schema;
474
+ return publicSchema;
475
+ };
476
+
477
+ export const loadMessageSchemas = async (messages: SchemaLoaderOptions['messages'], sources: SchemaSource[] = []) => {
478
+ const schemas = await loadMessageSchemaResources(messages);
479
+ const resolvedSchemas = await resolveSchemaSources(schemas, sources);
480
+
481
+ return addLatestMetadata(resolvedSchemas.map(stripSchemaLoaderContext));
482
+ };
483
+
484
+ const getSchemaBody = async (schema: MessageSchemaResource) => {
485
+ if (schema.content !== undefined) return schema.content;
486
+ if (!schemaFileExists(schema)) return undefined;
487
+ return fs.readFile(schema.filePath, 'utf8');
488
+ };
489
+
490
+ const setSchema = async (context: LoaderContext, schema: MessageSchemaResource) => {
491
+ const body = await getSchemaBody(schema);
492
+ if (body === undefined) return;
493
+
494
+ const schemaWithContent = {
495
+ ...schema,
496
+ content: body,
497
+ };
498
+ const parsedData = await context.parseData({
499
+ id: schema.id,
500
+ data: schemaWithContent,
501
+ });
502
+
503
+ context.store.set({
504
+ id: schema.id,
505
+ data: parsedData,
506
+ body,
507
+ digest: context.generateDigest(schemaWithContent),
508
+ });
509
+ };
510
+
511
+ export const schemaLoader = ({ messages, sources = [] }: SchemaLoaderOptions): Loader => {
512
+ return {
513
+ name: 'eventcatalog-schema-loader',
514
+ load: async (context) => {
515
+ context.store.clear();
516
+ const schemas = await loadMessageSchemas(messages, sources);
517
+
518
+ for (const schema of schemas) {
519
+ await setSchema(context, schema);
520
+ }
521
+ },
522
+ };
523
+ };
@@ -1,4 +1,4 @@
1
- import path from 'node:path';
1
+ import * as path from 'node:path';
2
2
 
3
3
  /**
4
4
  * Resolves a file path relative to PROJECT_DIR, handling ../ paths correctly
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "license": "SEE LICENSE IN LICENSE",
9
9
  "type": "module",
10
- "version": "3.44.2",
10
+ "version": "3.46.0",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -74,7 +74,7 @@
74
74
  "elkjs": "^0.10.0",
75
75
  "glob": "^13.0.6",
76
76
  "gray-matter": "^4.0.3",
77
- "hono": "4.12.18",
77
+ "hono": "4.12.21",
78
78
  "html-to-image": "^1.11.11",
79
79
  "js-yaml": "^4.1.1",
80
80
  "jsonpath-plus": "^10.4.0",
@@ -112,9 +112,9 @@
112
112
  "update-notifier": "^7.3.1",
113
113
  "uuid": "^10.0.0",
114
114
  "zod": "^4.3.6",
115
+ "@eventcatalog/linter": "1.0.29",
115
116
  "@eventcatalog/sdk": "2.24.1",
116
- "@eventcatalog/visualiser": "^3.22.1",
117
- "@eventcatalog/linter": "1.0.29"
117
+ "@eventcatalog/visualiser": "^3.22.1"
118
118
  },
119
119
  "devDependencies": {
120
120
  "@astrojs/check": "^0.9.9",