@eventcatalog/core 4.0.7 → 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 (37) 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-ZOFYLCPF.js → chunk-2PPDVKNK.js} +1 -1
  8. package/dist/{chunk-ARHL5SPG.js → chunk-2T6ESD3L.js} +1 -1
  9. package/dist/{chunk-O3Y2G6CY.js → chunk-CAJUIMDJ.js} +1 -1
  10. package/dist/{chunk-RBBWHWE4.js → chunk-OQ36RUHT.js} +1 -1
  11. package/dist/{chunk-WDA5QYVD.js → chunk-PL4YZUAA.js} +1 -1
  12. package/dist/{chunk-IMCMPLIJ.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/enterprise/custom-pages/routes.ts +142 -0
  30. package/eventcatalog/src/enterprise/feature.ts +3 -0
  31. package/eventcatalog/src/enterprise/integrations/eventcatalog-features.ts +84 -1
  32. package/eventcatalog/src/pages/index.astro +1 -1
  33. package/eventcatalog/src/toolkit/layouts/Layout.astro +25 -0
  34. package/eventcatalog/src/toolkit/utils/index.ts +26 -0
  35. package/eventcatalog/src/utils/feature.ts +1 -0
  36. package/eventcatalog/tsconfig.json +5 -1
  37. package/package.json +3 -3
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(analytics_exports);
36
36
  var import_os = __toESM(require("os"), 1);
37
37
 
38
38
  // package.json
39
- var version = "4.0.7";
39
+ var version = "4.1.0";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-WDA5QYVD.js";
4
- import "../chunk-RBBWHWE4.js";
3
+ } from "../chunk-PL4YZUAA.js";
4
+ import "../chunk-OQ36RUHT.js";
5
5
  export {
6
6
  raiseEvent
7
7
  };
@@ -140,7 +140,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
140
140
  var import_os = __toESM(require("os"), 1);
141
141
 
142
142
  // package.json
143
- var version = "4.0.7";
143
+ var version = "4.1.0";
144
144
 
145
145
  // src/constants.ts
146
146
  var VERSION = version;
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-ARHL5SPG.js";
4
- import "../chunk-WDA5QYVD.js";
3
+ } from "../chunk-2T6ESD3L.js";
4
+ import "../chunk-PL4YZUAA.js";
5
5
  import "../chunk-DAOXTQVS.js";
6
- import "../chunk-RBBWHWE4.js";
6
+ import "../chunk-OQ36RUHT.js";
7
7
  import "../chunk-6QENHZZP.js";
8
8
  export {
9
9
  log_build_default as default
@@ -149,6 +149,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
149
149
 
150
150
  // src/map-catalog-to-astro.js
151
151
  var import_node_path2 = __toESM(require("path"), 1);
152
+ var CUSTOM_PAGE_EXTENSIONS = [".astro", ".ts", ".js", ".mjs"];
152
153
  var COLLECTION_KEYS = [
153
154
  "agents",
154
155
  "events",
@@ -171,6 +172,10 @@ function mapCatalogToAstro({ filePath, astroDir, projectDir }) {
171
172
  if (!isCatalogRelated(relativeFilePath)) {
172
173
  return [];
173
174
  }
175
+ const customPageTargetPaths = getCustomPageTargetPaths(relativeFilePath, astroDir);
176
+ if (customPageTargetPaths) {
177
+ return customPageTargetPaths;
178
+ }
174
179
  const baseTargetPaths = getBaseTargetPaths(relativeFilePath);
175
180
  const relativeTargetPath = getRelativeTargetPath(relativeFilePath);
176
181
  return baseTargetPaths.map((base) => import_node_path2.default.join(astroDir, base, relativeTargetPath));
@@ -185,6 +190,21 @@ function isCollectionKey(key) {
185
190
  function isLikeC4Source(filePath) {
186
191
  return filePath.endsWith(".c4") || filePath.endsWith(".likec4");
187
192
  }
193
+ var hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
194
+ function getCustomPageTargetPaths(filePath, astroDir) {
195
+ const filePathArr = filePath.split(import_node_path2.default.sep).filter(Boolean);
196
+ if (filePathArr[0] !== "pages") {
197
+ return null;
198
+ }
199
+ const customPagePath = import_node_path2.default.join(astroDir, "src", "custom-pages", ...filePathArr.slice(1));
200
+ if (CUSTOM_PAGE_EXTENSIONS.includes(import_node_path2.default.extname(filePath).toLowerCase())) {
201
+ return [customPagePath];
202
+ }
203
+ if (!hasExtension(filePath)) {
204
+ return [customPagePath, import_node_path2.default.join(astroDir, "public", "generated", ...filePathArr)];
205
+ }
206
+ return [import_node_path2.default.join(astroDir, "public", "generated", ...filePathArr)];
207
+ }
188
208
  function isCatalogRelated(filePath) {
189
209
  const filePathArr = filePath.split(import_node_path2.default.sep).filter(Boolean);
190
210
  if ([
@@ -209,7 +229,6 @@ function isCatalogRelated(filePath) {
209
229
  function getBaseTargetPaths(filePath) {
210
230
  const filePathArr = filePath.split(import_node_path2.default.sep).filter(Boolean);
211
231
  if (isCollectionKey(filePathArr[0])) {
212
- const hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
213
232
  if (hasExtension(filePath)) {
214
233
  return [import_node_path2.default.join("public", "generated")];
215
234
  }
@@ -272,6 +291,17 @@ var copyFiles = async (source, target) => {
272
291
  });
273
292
  }
274
293
  };
294
+ var clearCustomPages = async (target) => {
295
+ const customPagesDir = path3.join(target, "src", "custom-pages");
296
+ if (import_fs.default.existsSync(customPagesDir)) import_fs.default.rmSync(customPagesDir, { recursive: true });
297
+ const staleCodeFiles = await (0, import_glob.glob)(path3.join(target, "public", "generated", "pages", "**/*.{astro,ts,js,mjs}"), {
298
+ nodir: true,
299
+ windowsPathsNoEscape: import_node_os2.default.platform() == "win32"
300
+ });
301
+ for (const file of staleCodeFiles) {
302
+ import_fs.default.rmSync(file);
303
+ }
304
+ };
275
305
  var removeGeneratedLikeC4Sources = async (target) => {
276
306
  const generatedDir = path3.join(target, "public", "generated");
277
307
  const files = await (0, import_glob.glob)(path3.join(generatedDir, "**/*.{c4,likec4}"), {
@@ -290,6 +320,7 @@ var catalogToAstro = async (source, astroDir) => {
290
320
  if (!import_fs.default.existsSync(path3.join(source, "eventcatalog.styles.css"))) {
291
321
  import_fs.default.writeFileSync(path3.join(source, "eventcatalog.styles.css"), "");
292
322
  }
323
+ await clearCustomPages(astroDir);
293
324
  await removeGeneratedLikeC4Sources(astroDir);
294
325
  await copyFiles(source, astroDir);
295
326
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  catalogToAstro
3
- } from "./chunk-WQNKHIDM.js";
4
- import "./chunk-VC6VUJIX.js";
3
+ } from "./chunk-W3SAPOZU.js";
4
+ import "./chunk-W5JQON7Z.js";
5
5
  import "./chunk-6QENHZZP.js";
6
6
  export {
7
7
  catalogToAstro
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-IMCMPLIJ.js";
3
+ } from "./chunk-RXZKZGDC.js";
4
4
  import {
5
5
  cleanup,
6
6
  getEventCatalogConfigFile
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-WDA5QYVD.js";
3
+ } from "./chunk-PL4YZUAA.js";
4
4
  import {
5
5
  countResources,
6
6
  serializeCounts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mapCatalogToAstro
3
- } from "./chunk-VC6VUJIX.js";
3
+ } from "./chunk-W5JQON7Z.js";
4
4
 
5
5
  // src/watcher.js
6
6
  import watcher from "@parcel/watcher";
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "4.0.7";
2
+ var version = "4.1.0";
3
3
 
4
4
  // src/constants.ts
5
5
  var VERSION = version;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-RBBWHWE4.js";
3
+ } from "./chunk-OQ36RUHT.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import os from "os";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-RBBWHWE4.js";
3
+ } from "./chunk-OQ36RUHT.js";
4
4
 
5
5
  // src/utils/cli-logger.ts
6
6
  import pc from "picocolors";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mapCatalogToAstro
3
- } from "./chunk-VC6VUJIX.js";
3
+ } from "./chunk-W5JQON7Z.js";
4
4
  import {
5
5
  verifyRequiredFieldsAreInCatalogConfigFile
6
6
  } from "./chunk-6QENHZZP.js";
@@ -40,6 +40,17 @@ var copyFiles = async (source, target) => {
40
40
  });
41
41
  }
42
42
  };
43
+ var clearCustomPages = async (target) => {
44
+ const customPagesDir = path.join(target, "src", "custom-pages");
45
+ if (fs.existsSync(customPagesDir)) fs.rmSync(customPagesDir, { recursive: true });
46
+ const staleCodeFiles = await glob(path.join(target, "public", "generated", "pages", "**/*.{astro,ts,js,mjs}"), {
47
+ nodir: true,
48
+ windowsPathsNoEscape: os.platform() == "win32"
49
+ });
50
+ for (const file of staleCodeFiles) {
51
+ fs.rmSync(file);
52
+ }
53
+ };
43
54
  var removeGeneratedLikeC4Sources = async (target) => {
44
55
  const generatedDir = path.join(target, "public", "generated");
45
56
  const files = await glob(path.join(generatedDir, "**/*.{c4,likec4}"), {
@@ -58,6 +69,7 @@ var catalogToAstro = async (source, astroDir) => {
58
69
  if (!fs.existsSync(path.join(source, "eventcatalog.styles.css"))) {
59
70
  fs.writeFileSync(path.join(source, "eventcatalog.styles.css"), "");
60
71
  }
72
+ await clearCustomPages(astroDir);
61
73
  await removeGeneratedLikeC4Sources(astroDir);
62
74
  await copyFiles(source, astroDir);
63
75
  };
@@ -1,5 +1,6 @@
1
1
  // src/map-catalog-to-astro.js
2
2
  import path from "path";
3
+ var CUSTOM_PAGE_EXTENSIONS = [".astro", ".ts", ".js", ".mjs"];
3
4
  var COLLECTION_KEYS = [
4
5
  "agents",
5
6
  "events",
@@ -22,6 +23,10 @@ function mapCatalogToAstro({ filePath, astroDir, projectDir }) {
22
23
  if (!isCatalogRelated(relativeFilePath)) {
23
24
  return [];
24
25
  }
26
+ const customPageTargetPaths = getCustomPageTargetPaths(relativeFilePath, astroDir);
27
+ if (customPageTargetPaths) {
28
+ return customPageTargetPaths;
29
+ }
25
30
  const baseTargetPaths = getBaseTargetPaths(relativeFilePath);
26
31
  const relativeTargetPath = getRelativeTargetPath(relativeFilePath);
27
32
  return baseTargetPaths.map((base) => path.join(astroDir, base, relativeTargetPath));
@@ -36,6 +41,21 @@ function isCollectionKey(key) {
36
41
  function isLikeC4Source(filePath) {
37
42
  return filePath.endsWith(".c4") || filePath.endsWith(".likec4");
38
43
  }
44
+ var hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
45
+ function getCustomPageTargetPaths(filePath, astroDir) {
46
+ const filePathArr = filePath.split(path.sep).filter(Boolean);
47
+ if (filePathArr[0] !== "pages") {
48
+ return null;
49
+ }
50
+ const customPagePath = path.join(astroDir, "src", "custom-pages", ...filePathArr.slice(1));
51
+ if (CUSTOM_PAGE_EXTENSIONS.includes(path.extname(filePath).toLowerCase())) {
52
+ return [customPagePath];
53
+ }
54
+ if (!hasExtension(filePath)) {
55
+ return [customPagePath, path.join(astroDir, "public", "generated", ...filePathArr)];
56
+ }
57
+ return [path.join(astroDir, "public", "generated", ...filePathArr)];
58
+ }
39
59
  function isCatalogRelated(filePath) {
40
60
  const filePathArr = filePath.split(path.sep).filter(Boolean);
41
61
  if ([
@@ -60,7 +80,6 @@ function isCatalogRelated(filePath) {
60
80
  function getBaseTargetPaths(filePath) {
61
81
  const filePathArr = filePath.split(path.sep).filter(Boolean);
62
82
  if (isCollectionKey(filePathArr[0])) {
63
- const hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
64
83
  if (hasExtension(filePath)) {
65
84
  return [path.join("public", "generated")];
66
85
  }
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "4.0.7";
28
+ var version = "4.1.0";
29
29
 
30
30
  // src/constants.ts
31
31
  var VERSION = version;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VERSION
3
- } from "./chunk-RBBWHWE4.js";
3
+ } from "./chunk-OQ36RUHT.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -144,7 +144,7 @@ var verifyRequiredFieldsAreInCatalogConfigFile = async (projectDirectory) => {
144
144
  var import_picocolors = __toESM(require("picocolors"), 1);
145
145
 
146
146
  // package.json
147
- var version = "4.0.7";
147
+ var version = "4.1.0";
148
148
 
149
149
  // src/constants.ts
150
150
  var VERSION = version;
@@ -416,6 +416,7 @@ var import_node_fs2 = __toESM(require("fs"), 1);
416
416
 
417
417
  // src/map-catalog-to-astro.js
418
418
  var import_node_path3 = __toESM(require("path"), 1);
419
+ var CUSTOM_PAGE_EXTENSIONS = [".astro", ".ts", ".js", ".mjs"];
419
420
  var COLLECTION_KEYS = [
420
421
  "agents",
421
422
  "events",
@@ -438,6 +439,10 @@ function mapCatalogToAstro({ filePath, astroDir, projectDir }) {
438
439
  if (!isCatalogRelated(relativeFilePath)) {
439
440
  return [];
440
441
  }
442
+ const customPageTargetPaths = getCustomPageTargetPaths(relativeFilePath, astroDir);
443
+ if (customPageTargetPaths) {
444
+ return customPageTargetPaths;
445
+ }
441
446
  const baseTargetPaths = getBaseTargetPaths(relativeFilePath);
442
447
  const relativeTargetPath = getRelativeTargetPath(relativeFilePath);
443
448
  return baseTargetPaths.map((base) => import_node_path3.default.join(astroDir, base, relativeTargetPath));
@@ -452,6 +457,21 @@ function isCollectionKey(key) {
452
457
  function isLikeC4Source(filePath) {
453
458
  return filePath.endsWith(".c4") || filePath.endsWith(".likec4");
454
459
  }
460
+ var hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
461
+ function getCustomPageTargetPaths(filePath, astroDir) {
462
+ const filePathArr = filePath.split(import_node_path3.default.sep).filter(Boolean);
463
+ if (filePathArr[0] !== "pages") {
464
+ return null;
465
+ }
466
+ const customPagePath = import_node_path3.default.join(astroDir, "src", "custom-pages", ...filePathArr.slice(1));
467
+ if (CUSTOM_PAGE_EXTENSIONS.includes(import_node_path3.default.extname(filePath).toLowerCase())) {
468
+ return [customPagePath];
469
+ }
470
+ if (!hasExtension(filePath)) {
471
+ return [customPagePath, import_node_path3.default.join(astroDir, "public", "generated", ...filePathArr)];
472
+ }
473
+ return [import_node_path3.default.join(astroDir, "public", "generated", ...filePathArr)];
474
+ }
455
475
  function isCatalogRelated(filePath) {
456
476
  const filePathArr = filePath.split(import_node_path3.default.sep).filter(Boolean);
457
477
  if ([
@@ -476,7 +496,6 @@ function isCatalogRelated(filePath) {
476
496
  function getBaseTargetPaths(filePath) {
477
497
  const filePathArr = filePath.split(import_node_path3.default.sep).filter(Boolean);
478
498
  if (isCollectionKey(filePathArr[0])) {
479
- const hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
480
499
  if (hasExtension(filePath)) {
481
500
  return [import_node_path3.default.join("public", "generated")];
482
501
  }
@@ -635,6 +654,17 @@ var copyFiles = async (source, target) => {
635
654
  });
636
655
  }
637
656
  };
657
+ var clearCustomPages = async (target) => {
658
+ const customPagesDir = path4.join(target, "src", "custom-pages");
659
+ if (import_fs.default.existsSync(customPagesDir)) import_fs.default.rmSync(customPagesDir, { recursive: true });
660
+ const staleCodeFiles = await (0, import_glob2.glob)(path4.join(target, "public", "generated", "pages", "**/*.{astro,ts,js,mjs}"), {
661
+ nodir: true,
662
+ windowsPathsNoEscape: import_node_os2.default.platform() == "win32"
663
+ });
664
+ for (const file of staleCodeFiles) {
665
+ import_fs.default.rmSync(file);
666
+ }
667
+ };
638
668
  var removeGeneratedLikeC4Sources = async (target) => {
639
669
  const generatedDir = path4.join(target, "public", "generated");
640
670
  const files = await (0, import_glob2.glob)(path4.join(generatedDir, "**/*.{c4,likec4}"), {
@@ -653,6 +683,7 @@ var catalogToAstro = async (source, astroDir) => {
653
683
  if (!import_fs.default.existsSync(path4.join(source, "eventcatalog.styles.css"))) {
654
684
  import_fs.default.writeFileSync(path4.join(source, "eventcatalog.styles.css"), "");
655
685
  }
686
+ await clearCustomPages(astroDir);
656
687
  await removeGeneratedLikeC4Sources(astroDir);
657
688
  await copyFiles(source, astroDir);
658
689
  };
@@ -260,6 +260,14 @@ interface Config {
260
260
  };
261
261
  mdxOptimize?: boolean;
262
262
  compress?: boolean;
263
+ pages?: {
264
+ /**
265
+ * URL prefix that user-defined pages (pages/*.astro, pages/api/*.ts) are served under,
266
+ * e.g. pages/reports.astro is served at /custom/reports.
267
+ * @default 'custom'
268
+ */
269
+ prefix?: string;
270
+ };
263
271
  navigation?: {
264
272
  pages?: NavigationPage[];
265
273
  /**
@@ -260,6 +260,14 @@ interface Config {
260
260
  };
261
261
  mdxOptimize?: boolean;
262
262
  compress?: boolean;
263
+ pages?: {
264
+ /**
265
+ * URL prefix that user-defined pages (pages/*.astro, pages/api/*.ts) are served under,
266
+ * e.g. pages/reports.astro is served at /custom/reports.
267
+ * @default 'custom'
268
+ */
269
+ prefix?: string;
270
+ };
263
271
  navigation?: {
264
272
  pages?: NavigationPage[];
265
273
  /**
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  log_build_default
3
- } from "./chunk-ARHL5SPG.js";
3
+ } from "./chunk-2T6ESD3L.js";
4
4
  import {
5
5
  runMigrations
6
6
  } from "./chunk-XUAF2H54.js";
7
7
  import "./chunk-CA4U2JP7.js";
8
8
  import {
9
9
  generate
10
- } from "./chunk-ZOFYLCPF.js";
10
+ } from "./chunk-2PPDVKNK.js";
11
11
  import {
12
12
  logger
13
- } from "./chunk-IMCMPLIJ.js";
13
+ } from "./chunk-RXZKZGDC.js";
14
14
  import {
15
15
  resolve_catalog_dependencies_default
16
16
  } from "./chunk-LHR4G2UO.js";
@@ -19,16 +19,16 @@ import {
19
19
  } from "./chunk-ZONBICNH.js";
20
20
  import {
21
21
  watch
22
- } from "./chunk-O3Y2G6CY.js";
23
- import "./chunk-WDA5QYVD.js";
22
+ } from "./chunk-CAJUIMDJ.js";
23
+ import "./chunk-PL4YZUAA.js";
24
24
  import "./chunk-DAOXTQVS.js";
25
25
  import {
26
26
  catalogToAstro
27
- } from "./chunk-WQNKHIDM.js";
28
- import "./chunk-VC6VUJIX.js";
27
+ } from "./chunk-W3SAPOZU.js";
28
+ import "./chunk-W5JQON7Z.js";
29
29
  import {
30
30
  VERSION
31
- } from "./chunk-RBBWHWE4.js";
31
+ } from "./chunk-OQ36RUHT.js";
32
32
  import {
33
33
  linkCoreNodeModules,
34
34
  resolveInstalledCoreNodeModules
package/dist/generate.cjs CHANGED
@@ -108,7 +108,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
108
108
  var import_picocolors = __toESM(require("picocolors"), 1);
109
109
 
110
110
  // package.json
111
- var version = "4.0.7";
111
+ var version = "4.1.0";
112
112
 
113
113
  // src/constants.ts
114
114
  var VERSION = version;
package/dist/generate.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  generate
3
- } from "./chunk-ZOFYLCPF.js";
4
- import "./chunk-IMCMPLIJ.js";
5
- import "./chunk-RBBWHWE4.js";
3
+ } from "./chunk-2PPDVKNK.js";
4
+ import "./chunk-RXZKZGDC.js";
5
+ import "./chunk-OQ36RUHT.js";
6
6
  import "./chunk-6QENHZZP.js";
7
7
  export {
8
8
  generate
@@ -34,6 +34,7 @@ __export(map_catalog_to_astro_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(map_catalog_to_astro_exports);
36
36
  var import_node_path = __toESM(require("path"), 1);
37
+ var CUSTOM_PAGE_EXTENSIONS = [".astro", ".ts", ".js", ".mjs"];
37
38
  var COLLECTION_KEYS = [
38
39
  "agents",
39
40
  "events",
@@ -56,6 +57,10 @@ function mapCatalogToAstro({ filePath, astroDir, projectDir }) {
56
57
  if (!isCatalogRelated(relativeFilePath)) {
57
58
  return [];
58
59
  }
60
+ const customPageTargetPaths = getCustomPageTargetPaths(relativeFilePath, astroDir);
61
+ if (customPageTargetPaths) {
62
+ return customPageTargetPaths;
63
+ }
59
64
  const baseTargetPaths = getBaseTargetPaths(relativeFilePath);
60
65
  const relativeTargetPath = getRelativeTargetPath(relativeFilePath);
61
66
  return baseTargetPaths.map((base) => import_node_path.default.join(astroDir, base, relativeTargetPath));
@@ -70,6 +75,21 @@ function isCollectionKey(key) {
70
75
  function isLikeC4Source(filePath) {
71
76
  return filePath.endsWith(".c4") || filePath.endsWith(".likec4");
72
77
  }
78
+ var hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
79
+ function getCustomPageTargetPaths(filePath, astroDir) {
80
+ const filePathArr = filePath.split(import_node_path.default.sep).filter(Boolean);
81
+ if (filePathArr[0] !== "pages") {
82
+ return null;
83
+ }
84
+ const customPagePath = import_node_path.default.join(astroDir, "src", "custom-pages", ...filePathArr.slice(1));
85
+ if (CUSTOM_PAGE_EXTENSIONS.includes(import_node_path.default.extname(filePath).toLowerCase())) {
86
+ return [customPagePath];
87
+ }
88
+ if (!hasExtension(filePath)) {
89
+ return [customPagePath, import_node_path.default.join(astroDir, "public", "generated", ...filePathArr)];
90
+ }
91
+ return [import_node_path.default.join(astroDir, "public", "generated", ...filePathArr)];
92
+ }
73
93
  function isCatalogRelated(filePath) {
74
94
  const filePathArr = filePath.split(import_node_path.default.sep).filter(Boolean);
75
95
  if ([
@@ -94,7 +114,6 @@ function isCatalogRelated(filePath) {
94
114
  function getBaseTargetPaths(filePath) {
95
115
  const filePathArr = filePath.split(import_node_path.default.sep).filter(Boolean);
96
116
  if (isCollectionKey(filePathArr[0])) {
97
- const hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
98
117
  if (hasExtension(filePath)) {
99
118
  return [import_node_path.default.join("public", "generated")];
100
119
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mapCatalogToAstro
3
- } from "./chunk-VC6VUJIX.js";
3
+ } from "./chunk-W5JQON7Z.js";
4
4
  export {
5
5
  mapCatalogToAstro
6
6
  };
@@ -36,7 +36,7 @@ module.exports = __toCommonJS(cli_logger_exports);
36
36
  var import_picocolors = __toESM(require("picocolors"), 1);
37
37
 
38
38
  // package.json
39
- var version = "4.0.7";
39
+ var version = "4.1.0";
40
40
 
41
41
  // src/constants.ts
42
42
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  logger
3
- } from "../chunk-IMCMPLIJ.js";
4
- import "../chunk-RBBWHWE4.js";
3
+ } from "../chunk-RXZKZGDC.js";
4
+ import "../chunk-OQ36RUHT.js";
5
5
  export {
6
6
  logger
7
7
  };
package/dist/watcher.cjs CHANGED
@@ -38,6 +38,7 @@ var import_node_fs = __toESM(require("fs"), 1);
38
38
 
39
39
  // src/map-catalog-to-astro.js
40
40
  var import_node_path = __toESM(require("path"), 1);
41
+ var CUSTOM_PAGE_EXTENSIONS = [".astro", ".ts", ".js", ".mjs"];
41
42
  var COLLECTION_KEYS = [
42
43
  "agents",
43
44
  "events",
@@ -60,6 +61,10 @@ function mapCatalogToAstro({ filePath, astroDir, projectDir }) {
60
61
  if (!isCatalogRelated(relativeFilePath)) {
61
62
  return [];
62
63
  }
64
+ const customPageTargetPaths = getCustomPageTargetPaths(relativeFilePath, astroDir);
65
+ if (customPageTargetPaths) {
66
+ return customPageTargetPaths;
67
+ }
63
68
  const baseTargetPaths = getBaseTargetPaths(relativeFilePath);
64
69
  const relativeTargetPath = getRelativeTargetPath(relativeFilePath);
65
70
  return baseTargetPaths.map((base) => import_node_path.default.join(astroDir, base, relativeTargetPath));
@@ -74,6 +79,21 @@ function isCollectionKey(key) {
74
79
  function isLikeC4Source(filePath) {
75
80
  return filePath.endsWith(".c4") || filePath.endsWith(".likec4");
76
81
  }
82
+ var hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
83
+ function getCustomPageTargetPaths(filePath, astroDir) {
84
+ const filePathArr = filePath.split(import_node_path.default.sep).filter(Boolean);
85
+ if (filePathArr[0] !== "pages") {
86
+ return null;
87
+ }
88
+ const customPagePath = import_node_path.default.join(astroDir, "src", "custom-pages", ...filePathArr.slice(1));
89
+ if (CUSTOM_PAGE_EXTENSIONS.includes(import_node_path.default.extname(filePath).toLowerCase())) {
90
+ return [customPagePath];
91
+ }
92
+ if (!hasExtension(filePath)) {
93
+ return [customPagePath, import_node_path.default.join(astroDir, "public", "generated", ...filePathArr)];
94
+ }
95
+ return [import_node_path.default.join(astroDir, "public", "generated", ...filePathArr)];
96
+ }
77
97
  function isCatalogRelated(filePath) {
78
98
  const filePathArr = filePath.split(import_node_path.default.sep).filter(Boolean);
79
99
  if ([
@@ -98,7 +118,6 @@ function isCatalogRelated(filePath) {
98
118
  function getBaseTargetPaths(filePath) {
99
119
  const filePathArr = filePath.split(import_node_path.default.sep).filter(Boolean);
100
120
  if (isCollectionKey(filePathArr[0])) {
101
- const hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
102
121
  if (hasExtension(filePath)) {
103
122
  return [import_node_path.default.join("public", "generated")];
104
123
  }
package/dist/watcher.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  watch
3
- } from "./chunk-O3Y2G6CY.js";
4
- import "./chunk-VC6VUJIX.js";
3
+ } from "./chunk-CAJUIMDJ.js";
4
+ import "./chunk-W5JQON7Z.js";
5
5
  export {
6
6
  watch
7
7
  };
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Licensed under the EventCatalog Commercial License.
3
+ * See /packages/core/eventcatalog/src/enterprise/LICENSE
4
+ */
5
+
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+
9
+ export interface CustomPageRoute {
10
+ /** Route pattern including the configured prefix, e.g. /custom/reports/[id] */
11
+ pattern: string;
12
+ /** File path relative to the custom pages directory */
13
+ file: string;
14
+ type: 'page' | 'endpoint';
15
+ }
16
+
17
+ export const DEFAULT_CUSTOM_PAGES_PREFIX = 'custom';
18
+
19
+ /**
20
+ * Tracks the routable files during dev so route injection re-runs when files
21
+ * are added or removed. Never a route itself.
22
+ */
23
+ export const CUSTOM_PAGES_MANIFEST_FILENAME = '.routes-manifest.json';
24
+
25
+ const CUSTOM_PAGE_EXTENSIONS = /\.(astro|ts|js|mjs|json)$/i;
26
+
27
+ /**
28
+ * Top-level route segments owned by EventCatalog. The custom pages prefix
29
+ * cannot start with any of these — everything else is collision-free because
30
+ * all user routes live under the prefix.
31
+ */
32
+ const RESERVED_PREFIXES = [
33
+ 'api',
34
+ 'api-catalog',
35
+ 'architecture',
36
+ 'auth',
37
+ 'diagrams',
38
+ 'directory',
39
+ 'discover',
40
+ 'docs',
41
+ 'icepanel',
42
+ 'miro',
43
+ 'rss',
44
+ 'schemas',
45
+ 'settings',
46
+ 'studio',
47
+ 'unauthorized',
48
+ 'visualiser',
49
+ '.well-known',
50
+ ];
51
+
52
+ /**
53
+ * Normalizes and validates the configured prefix (e.g. 'custom', 'internal/tools').
54
+ * Throws when the prefix is empty, contains unsafe characters or shadows a core route.
55
+ */
56
+ export const resolveCustomPagesPrefix = (prefix: string | undefined): string => {
57
+ const normalized = (prefix ?? DEFAULT_CUSTOM_PAGES_PREFIX).replace(/^\/+|\/+$/g, '');
58
+
59
+ if (normalized.length === 0) {
60
+ throw new Error('[EventCatalog] pages.prefix cannot be empty.');
61
+ }
62
+
63
+ if (!/^[a-zA-Z0-9-_]+(\/[a-zA-Z0-9-_]+)*$/.test(normalized)) {
64
+ throw new Error(
65
+ `[EventCatalog] pages.prefix "${prefix}" is invalid. Use URL-safe characters (letters, numbers, - and _), optionally separated by "/".`
66
+ );
67
+ }
68
+
69
+ const firstSegment = normalized.split('/')[0].toLowerCase();
70
+ if (RESERVED_PREFIXES.includes(firstSegment)) {
71
+ throw new Error(`[EventCatalog] pages.prefix "${prefix}" is reserved by EventCatalog. Choose a different prefix.`);
72
+ }
73
+
74
+ return normalized;
75
+ };
76
+
77
+ /**
78
+ * Derives an Astro route pattern from a file path relative to the custom pages
79
+ * directory. Dynamic segments ([id], [...slug]) pass through untouched.
80
+ */
81
+ export const deriveRoutePattern = (relativeFilePath: string, prefix: string): string => {
82
+ const withoutExtension = relativeFilePath.replace(CUSTOM_PAGE_EXTENSIONS, '');
83
+ const segments = withoutExtension.split(/[\\/]/).filter(Boolean);
84
+
85
+ if (segments[segments.length - 1] === 'index') {
86
+ segments.pop();
87
+ }
88
+
89
+ return `/${[prefix, ...segments].join('/')}`;
90
+ };
91
+
92
+ const walkDirectory = (directory: string, relativeTo: string): string[] => {
93
+ const files: string[] = [];
94
+
95
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
96
+ const fullPath = path.join(directory, entry.name);
97
+ if (entry.isDirectory()) {
98
+ files.push(...walkDirectory(fullPath, relativeTo));
99
+ } else if (entry.isFile()) {
100
+ files.push(path.relative(relativeTo, fullPath));
101
+ }
102
+ }
103
+
104
+ return files;
105
+ };
106
+
107
+ /**
108
+ * Lists the routable code files in the custom pages directory (sorted, relative paths).
109
+ * Underscore-prefixed files and directories follow the Astro convention: they are
110
+ * never routable (partials, helpers, colocated components).
111
+ */
112
+ export const listCustomPageFiles = (customPagesDir: string): string[] => {
113
+ if (!fs.existsSync(customPagesDir)) return [];
114
+
115
+ return walkDirectory(customPagesDir, customPagesDir)
116
+ .filter((file) => CUSTOM_PAGE_EXTENSIONS.test(file))
117
+ .filter((file) => file !== CUSTOM_PAGES_MANIFEST_FILENAME)
118
+ .filter((file) => !file.split(path.sep).some((segment) => segment.startsWith('_')))
119
+ .sort();
120
+ };
121
+
122
+ /**
123
+ * Reads the custom pages directory and returns the routes to inject.
124
+ */
125
+ export const getCustomPageRoutes = (customPagesDir: string, prefix: string): CustomPageRoute[] => {
126
+ const routes: CustomPageRoute[] = [];
127
+
128
+ for (const file of listCustomPageFiles(customPagesDir)) {
129
+ // pages/homepage.astro is the custom landing page, rendered by src/pages/index.astro
130
+ if (file === 'homepage.astro') continue;
131
+
132
+ routes.push({
133
+ pattern: deriveRoutePattern(file, prefix),
134
+ file,
135
+ type: file.toLowerCase().endsWith('.astro') ? 'page' : 'endpoint',
136
+ });
137
+ }
138
+
139
+ return routes;
140
+ };
141
+
142
+ export const isApiRoute = (route: CustomPageRoute): boolean => route.file.split(path.sep)[0] === 'api';
@@ -53,6 +53,9 @@ export const isEventCatalogUpgradeEnabled = () => !isEventCatalogStarterEnabled(
53
53
  // Custom landing pages are always enabled now.
54
54
  export const isCustomLandingPageEnabled = () => true;
55
55
 
56
+ // User-defined pages and API routes (pages/*.astro, pages/api/*.ts)
57
+ export const isCustomPagesEnabled = () => isEventCatalogScaleEnabled();
58
+
56
59
  export const isAuthEnabled = () => {
57
60
  const isAuthEnabledInCatalog = config?.auth?.enabled ?? false;
58
61
  const directory = process.env.PROJECT_DIR || process.cwd();
@@ -4,23 +4,80 @@
4
4
  */
5
5
 
6
6
  import type { AstroIntegration } from 'astro';
7
+ import fs from 'node:fs';
7
8
  import path from 'path';
8
9
  import config from '../../../eventcatalog.config.js';
9
10
  import {
10
11
  isEventCatalogChatEnabled,
11
12
  isAuthEnabled,
12
13
  isEventCatalogScaleEnabled,
13
- isEventCatalogStarterEnabled,
14
14
  isEventCatalogMCPEnabled,
15
15
  isEventCatalogMCPAuthEnabled,
16
16
  isFullCatalogAPIEnabled,
17
17
  isDevMode,
18
18
  isIntegrationsEnabled,
19
19
  isCustomDocsEnabled,
20
+ isCustomPagesEnabled,
20
21
  isSSR,
21
22
  } from '../../utils/feature';
23
+ import {
24
+ CUSTOM_PAGES_MANIFEST_FILENAME,
25
+ getCustomPageRoutes,
26
+ isApiRoute,
27
+ listCustomPageFiles,
28
+ resolveCustomPagesPrefix,
29
+ } from '../custom-pages/routes';
22
30
 
23
31
  const catalogDirectory = process.env.CATALOG_DIR || process.cwd();
32
+ const customPagesDirectory = path.join(catalogDirectory, 'src/custom-pages');
33
+
34
+ // Routes are injected at astro:config:setup, so adding or removing a custom page
35
+ // file needs a full Astro restart before its route exists. This manifest is
36
+ // registered via addWatchFile — rewriting it with a changed file list triggers
37
+ // that restart (a Vite-level server.restart() does NOT re-run route injection).
38
+ const customPagesManifest = path.join(customPagesDirectory, CUSTOM_PAGES_MANIFEST_FILENAME);
39
+
40
+ const writeCustomPagesManifest = () => {
41
+ const content = JSON.stringify(listCustomPageFiles(customPagesDirectory));
42
+
43
+ try {
44
+ if (fs.existsSync(customPagesManifest) && fs.readFileSync(customPagesManifest, 'utf-8') === content) {
45
+ return;
46
+ }
47
+
48
+ fs.mkdirSync(customPagesDirectory, { recursive: true });
49
+ fs.writeFileSync(customPagesManifest, content);
50
+ } catch (error: any) {
51
+ console.warn(`[EventCatalog] Could not update the custom pages manifest: ${error.message}`);
52
+ }
53
+ };
54
+
55
+ const configureCustomPages = (params: {
56
+ command: 'dev' | 'build' | 'preview' | 'sync';
57
+ injectRoute: (route: { pattern: string; entrypoint: string }) => void;
58
+ }) => {
59
+ const prefix = resolveCustomPagesPrefix(config.pages?.prefix);
60
+ const routes = getCustomPageRoutes(customPagesDirectory, prefix);
61
+
62
+ const apiRoutes = routes.filter(isApiRoute);
63
+ if (apiRoutes.length > 0 && !isSSR()) {
64
+ const message = `Custom API routes (${apiRoutes.map((route) => `pages/${route.file}`).join(', ')}) require EventCatalog to run in server mode. Set output: 'server' in your eventcatalog.config.js or remove the pages/api directory.`;
65
+
66
+ // The dev server serves endpoints dynamically regardless of output mode,
67
+ // so only fail the build — but warn early during development.
68
+ if (params.command === 'build') {
69
+ throw new Error(`[EventCatalog] ${message}`);
70
+ }
71
+ console.warn(`[EventCatalog] ${message}`);
72
+ }
73
+
74
+ for (const route of routes) {
75
+ params.injectRoute({
76
+ pattern: route.pattern,
77
+ entrypoint: path.join(customPagesDirectory, route.file),
78
+ });
79
+ }
80
+ };
24
81
 
25
82
  const configureAuthentication = (params: {
26
83
  injectRoute: (route: { pattern: string; entrypoint: string }) => void;
@@ -148,6 +205,18 @@ export default function eventCatalogIntegration(): AstroIntegration {
148
205
  });
149
206
  }
150
207
 
208
+ // User-defined pages and API routes (Scale plan)
209
+ if (isCustomPagesEnabled()) {
210
+ configureCustomPages(params);
211
+ } else if (listCustomPageFiles(customPagesDirectory).length > 0) {
212
+ console.warn('[EventCatalog] Custom pages require the Scale plan. The routes for your pages will not be served.');
213
+ }
214
+
215
+ // Keep routes in sync during dev — a manifest change restarts the dev
216
+ // server so injectRoute runs again with the new file list
217
+ writeCustomPagesManifest();
218
+ params.addWatchFile(customPagesManifest);
219
+
151
220
  // Warn if integrations are configured without Scale plan
152
221
  if (config.integrations && !isIntegrationsEnabled()) {
153
222
  console.warn('[EventCatalog] Integrations require the Scale plan. Analytics integrations will not be loaded.');
@@ -165,6 +234,20 @@ export default function eventCatalogIntegration(): AstroIntegration {
165
234
  });
166
235
  }
167
236
  },
237
+ 'astro:server:setup': ({ server }) => {
238
+ // When custom page files appear or disappear, refresh the manifest.
239
+ // A content change restarts the dev server (via addWatchFile above),
240
+ // which re-runs route injection. Unchanged content writes nothing,
241
+ // so events from the watcher's initial scan are no-ops.
242
+ const onCustomPageChange = (file: string) => {
243
+ if (!path.resolve(file).startsWith(customPagesDirectory + path.sep)) return;
244
+ if (!/\.(astro|ts|js|mjs)$/i.test(file)) return;
245
+ writeCustomPagesManifest();
246
+ };
247
+
248
+ server.watcher.on('add', onCustomPageChange);
249
+ server.watcher.on('unlink', onCustomPageChange);
250
+ },
168
251
  },
169
252
  };
170
253
  }
@@ -21,7 +21,7 @@ const props = Astro.props;
21
21
  const pathToUserDefinedLandingPage = path.join(process.env.PROJECT_DIR || '', 'pages/homepage.astro');
22
22
 
23
23
  if (existsSync(pathToUserDefinedLandingPage) && isCustomLandingPageEnabled()) {
24
- const customPages = import.meta.glob('/**/homepage.astro', { eager: true });
24
+ const customPages = import.meta.glob('/src/custom-pages/homepage.astro', { eager: true });
25
25
  // @ts-ignore
26
26
  CustomContent = Object.values(customPages)[0]?.default || null;
27
27
 
@@ -0,0 +1,25 @@
1
+ ---
2
+ /**
3
+ * Public layout shell for user-defined custom pages, imported by catalog
4
+ * authors as `@catalog/layouts/Layout.astro`.
5
+ *
6
+ * The props here are a documented, stable interface — internal layouts can
7
+ * change freely, this contract cannot.
8
+ */
9
+ interface Props {
10
+ title: string;
11
+ description?: string;
12
+ /** Render the resource sidebar (domains, services, messages). Defaults to true. */
13
+ sidebar?: boolean;
14
+ /** Show the EventCatalog header (search, navigation). Defaults to true. */
15
+ showHeader?: boolean;
16
+ }
17
+
18
+ import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
19
+
20
+ const { title, description, sidebar = true, showHeader = true } = Astro.props;
21
+ ---
22
+
23
+ <VerticalSideBarLayout title={title} description={description} showHeader={showHeader} showNestedSideBar={sidebar}>
24
+ <slot />
25
+ </VerticalSideBarLayout>
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Public utilities for user-defined custom pages, imported by catalog
3
+ * authors as `@catalog/utils`.
4
+ *
5
+ * These re-exports are a documented, stable interface — internal utils can
6
+ * change freely, this contract cannot. Getters return hydrated, cached
7
+ * collection entries (pass { getAllVersions: false } for latest versions only).
8
+ */
9
+ export { getDomains } from '@utils/collections/domains';
10
+ export { getServices } from '@utils/collections/services';
11
+ export { getSystems } from '@utils/collections/systems';
12
+ export { getEvents } from '@utils/collections/events';
13
+ export { getCommands } from '@utils/collections/commands';
14
+ export { getQueries } from '@utils/collections/queries';
15
+ export { getFlows } from '@utils/collections/flows';
16
+ export { getChannels } from '@utils/collections/channels';
17
+ export { getEntities } from '@utils/collections/entities';
18
+ export { getAgents } from '@utils/collections/agents';
19
+ export { getContainers } from '@utils/collections/containers';
20
+ export { getDataProducts } from '@utils/collections/data-products';
21
+ export { getAdrs } from '@utils/collections/adrs';
22
+ export { getTeams } from '@utils/collections/teams';
23
+ export { getUsers } from '@utils/collections/users';
24
+
25
+ // Resolve a specific version (semver) or the latest version of items in a collection
26
+ export { getItemsFromCollectionByIdAndSemverOrLatest } from '@utils/collections/util';
@@ -25,6 +25,7 @@ export {
25
25
  isEventCatalogChatEnabled,
26
26
  isEventCatalogUpgradeEnabled,
27
27
  isCustomLandingPageEnabled,
28
+ isCustomPagesEnabled,
28
29
  isAuthEnabled,
29
30
  isCustomStylesEnabled,
30
31
  isEventCatalogMCPEnabled,
@@ -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.7",
10
+ "version": "4.1.0",
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
@@ -116,9 +116,9 @@
116
116
  "update-notifier": "^7.3.1",
117
117
  "uuid": "^10.0.0",
118
118
  "zod": "^4.3.6",
119
- "@eventcatalog/linter": "1.1.4",
120
119
  "@eventcatalog/sdk": "2.25.0",
121
- "@eventcatalog/visualiser": "^4.0.1"
120
+ "@eventcatalog/visualiser": "^4.0.1",
121
+ "@eventcatalog/linter": "1.1.4"
122
122
  },
123
123
  "devDependencies": {
124
124
  "@astrojs/check": "^0.9.9",