@eventcatalog/core 2.47.1 → 2.48.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.
@@ -37,7 +37,7 @@ var import_axios = __toESM(require("axios"), 1);
37
37
  var import_os = __toESM(require("os"), 1);
38
38
 
39
39
  // package.json
40
- var version = "2.47.1";
40
+ var version = "2.48.0";
41
41
 
42
42
  // src/constants.ts
43
43
  var VERSION = version;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "../chunk-QWDFTW7H.js";
4
- import "../chunk-WWYOMQLW.js";
3
+ } from "../chunk-LK6C3F6Q.js";
4
+ import "../chunk-I755G24S.js";
5
5
  export {
6
6
  raiseEvent
7
7
  };
@@ -106,7 +106,7 @@ var import_axios = __toESM(require("axios"), 1);
106
106
  var import_os = __toESM(require("os"), 1);
107
107
 
108
108
  // package.json
109
- var version = "2.47.1";
109
+ var version = "2.48.0";
110
110
 
111
111
  // src/constants.ts
112
112
  var VERSION = version;
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  log_build_default
3
- } from "../chunk-YJYT2E6S.js";
4
- import "../chunk-QWDFTW7H.js";
5
- import "../chunk-WWYOMQLW.js";
3
+ } from "../chunk-RW4O4UUQ.js";
4
+ import "../chunk-LK6C3F6Q.js";
5
+ import "../chunk-I755G24S.js";
6
6
  import "../chunk-E7TXTI7G.js";
7
7
  export {
8
8
  log_build_default as default
@@ -153,6 +153,8 @@ function isCatalogRelated(filePath) {
153
153
  // custom styles file at root
154
154
  "components",
155
155
  // custom components
156
+ "snippets",
157
+ // custom snippets
156
158
  "public",
157
159
  // public assets
158
160
  ".env",
@@ -175,6 +177,9 @@ function getBaseTargetPaths(filePath) {
175
177
  if (filePathArr[0] == "components") {
176
178
  return [import_node_path2.default.join("src", "custom-defined-components")];
177
179
  }
180
+ if (filePathArr[0] == "snippets") {
181
+ return [import_node_path2.default.join("src")];
182
+ }
178
183
  if (filePathArr[0] == "public") {
179
184
  return [import_node_path2.default.join("public")];
180
185
  }
@@ -185,10 +190,14 @@ function getRelativeTargetPath(filePath) {
185
190
  if (filePathArr[0] == "public" || filePathArr[0] == "components") {
186
191
  filePathArr.shift();
187
192
  }
193
+ if (filePathArr[0] == "snippets") {
194
+ console.log("SNIPPETS", filePathArr);
195
+ return import_node_path2.default.join("snippets", ...filePathArr.slice(1));
196
+ }
188
197
  const relativePath = [];
189
198
  for (let i = filePathArr.length - 1; i >= 0; i--) {
190
199
  relativePath.unshift(filePathArr[i]);
191
- if (isCollectionKey(filePathArr[i])) break;
200
+ if (isCollectionKey(filePathArr[i]) && filePathArr[i] != "snippets") break;
192
201
  }
193
202
  return import_node_path2.default.join(...relativePath);
194
203
  }
@@ -202,6 +211,13 @@ var copyFiles = async (source, target) => {
202
211
  windowsPathsNoEscape: import_node_os.default.platform() == "win32",
203
212
  ignore: ["node_modules/**", "**/dist/**", "**/teams", "**/users", "**/*.mdx", "**/*.md", "**/package.json", "**/Dockerfile"]
204
213
  });
214
+ const snippets = await (0, import_glob.glob)(path3.join(source, "snippets/**/*.mdx"), {
215
+ nodir: true,
216
+ windowsPathsNoEscape: import_node_os.default.platform() == "win32"
217
+ });
218
+ if (snippets.length > 0) {
219
+ files.push(...snippets);
220
+ }
205
221
  if (import_fs.default.existsSync(path3.join(source, ".env"))) {
206
222
  files.push(path3.join(source, ".env"));
207
223
  }
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  catalogToAstro,
3
3
  checkAndConvertMdToMdx
4
- } from "./chunk-SFA7F3CQ.js";
5
- import "./chunk-EXAALOQA.js";
4
+ } from "./chunk-B53UJPGW.js";
5
+ import "./chunk-WDTWWPPX.js";
6
6
  import "./chunk-E7TXTI7G.js";
7
7
  export {
8
8
  catalogToAstro,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mapCatalogToAstro
3
- } from "./chunk-EXAALOQA.js";
3
+ } from "./chunk-WDTWWPPX.js";
4
4
  import {
5
5
  verifyRequiredFieldsAreInCatalogConfigFile
6
6
  } from "./chunk-E7TXTI7G.js";
@@ -19,6 +19,13 @@ var copyFiles = async (source, target) => {
19
19
  windowsPathsNoEscape: os.platform() == "win32",
20
20
  ignore: ["node_modules/**", "**/dist/**", "**/teams", "**/users", "**/*.mdx", "**/*.md", "**/package.json", "**/Dockerfile"]
21
21
  });
22
+ const snippets = await glob(path.join(source, "snippets/**/*.mdx"), {
23
+ nodir: true,
24
+ windowsPathsNoEscape: os.platform() == "win32"
25
+ });
26
+ if (snippets.length > 0) {
27
+ files.push(...snippets);
28
+ }
22
29
  if (fs.existsSync(path.join(source, ".env"))) {
23
30
  files.push(path.join(source, ".env"));
24
31
  }
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "2.47.1";
2
+ var version = "2.48.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-WWYOMQLW.js";
3
+ } from "./chunk-I755G24S.js";
4
4
 
5
5
  // src/analytics/analytics.js
6
6
  import axios from "axios";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mapCatalogToAstro
3
- } from "./chunk-EXAALOQA.js";
3
+ } from "./chunk-WDTWWPPX.js";
4
4
 
5
5
  // src/watcher.js
6
6
  import watcher from "@parcel/watcher";
@@ -21,7 +21,7 @@ async function watch(projectDirectory, catalogDirectory, callback = void 0) {
21
21
  }
22
22
  for (let event of events) {
23
23
  const { path: filePath, type } = event;
24
- if (filePath.endsWith(".mdx") || filePath.endsWith(".md")) {
24
+ if ((filePath.endsWith(".mdx") || filePath.endsWith(".md")) && !filePath.includes("snippets")) {
25
25
  continue;
26
26
  }
27
27
  const astroPaths = mapCatalogToAstro({
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  raiseEvent
3
- } from "./chunk-QWDFTW7H.js";
3
+ } from "./chunk-LK6C3F6Q.js";
4
4
  import {
5
5
  getEventCatalogConfigFile,
6
6
  verifyRequiredFieldsAreInCatalogConfigFile
@@ -38,6 +38,8 @@ function isCatalogRelated(filePath) {
38
38
  // custom styles file at root
39
39
  "components",
40
40
  // custom components
41
+ "snippets",
42
+ // custom snippets
41
43
  "public",
42
44
  // public assets
43
45
  ".env",
@@ -60,6 +62,9 @@ function getBaseTargetPaths(filePath) {
60
62
  if (filePathArr[0] == "components") {
61
63
  return [path.join("src", "custom-defined-components")];
62
64
  }
65
+ if (filePathArr[0] == "snippets") {
66
+ return [path.join("src")];
67
+ }
63
68
  if (filePathArr[0] == "public") {
64
69
  return [path.join("public")];
65
70
  }
@@ -70,10 +75,14 @@ function getRelativeTargetPath(filePath) {
70
75
  if (filePathArr[0] == "public" || filePathArr[0] == "components") {
71
76
  filePathArr.shift();
72
77
  }
78
+ if (filePathArr[0] == "snippets") {
79
+ console.log("SNIPPETS", filePathArr);
80
+ return path.join("snippets", ...filePathArr.slice(1));
81
+ }
73
82
  const relativePath = [];
74
83
  for (let i = filePathArr.length - 1; i >= 0; i--) {
75
84
  relativePath.unshift(filePathArr[i]);
76
- if (isCollectionKey(filePathArr[i])) break;
85
+ if (isCollectionKey(filePathArr[i]) && filePathArr[i] != "snippets") break;
77
86
  }
78
87
  return path.join(...relativePath);
79
88
  }
@@ -25,7 +25,7 @@ __export(constants_exports, {
25
25
  module.exports = __toCommonJS(constants_exports);
26
26
 
27
27
  // package.json
28
- var version = "2.47.1";
28
+ var version = "2.48.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-WWYOMQLW.js";
3
+ } from "./chunk-I755G24S.js";
4
4
  export {
5
5
  VERSION
6
6
  };
@@ -29,9 +29,9 @@ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
29
29
  // src/eventcatalog.ts
30
30
  var import_commander = require("commander");
31
31
  var import_node_child_process = require("child_process");
32
- var import_node_path7 = require("path");
32
+ var import_node_path6 = require("path");
33
33
  var import_fs2 = __toESM(require("fs"), 1);
34
- var import_node_path8 = __toESM(require("path"), 1);
34
+ var import_node_path7 = __toESM(require("path"), 1);
35
35
  var import_node_url = require("url");
36
36
  var import_concurrently = __toESM(require("concurrently"), 1);
37
37
 
@@ -157,7 +157,7 @@ var import_axios = __toESM(require("axios"), 1);
157
157
  var import_os = __toESM(require("os"), 1);
158
158
 
159
159
  // package.json
160
- var version = "2.47.1";
160
+ var version = "2.48.0";
161
161
 
162
162
  // src/constants.ts
163
163
  var VERSION = version;
@@ -268,6 +268,8 @@ function isCatalogRelated(filePath) {
268
268
  // custom styles file at root
269
269
  "components",
270
270
  // custom components
271
+ "snippets",
272
+ // custom snippets
271
273
  "public",
272
274
  // public assets
273
275
  ".env",
@@ -290,6 +292,9 @@ function getBaseTargetPaths(filePath) {
290
292
  if (filePathArr[0] == "components") {
291
293
  return [import_node_path3.default.join("src", "custom-defined-components")];
292
294
  }
295
+ if (filePathArr[0] == "snippets") {
296
+ return [import_node_path3.default.join("src")];
297
+ }
293
298
  if (filePathArr[0] == "public") {
294
299
  return [import_node_path3.default.join("public")];
295
300
  }
@@ -300,17 +305,20 @@ function getRelativeTargetPath(filePath) {
300
305
  if (filePathArr[0] == "public" || filePathArr[0] == "components") {
301
306
  filePathArr.shift();
302
307
  }
308
+ if (filePathArr[0] == "snippets") {
309
+ console.log("SNIPPETS", filePathArr);
310
+ return import_node_path3.default.join("snippets", ...filePathArr.slice(1));
311
+ }
303
312
  const relativePath = [];
304
313
  for (let i = filePathArr.length - 1; i >= 0; i--) {
305
314
  relativePath.unshift(filePathArr[i]);
306
- if (isCollectionKey(filePathArr[i])) break;
315
+ if (isCollectionKey(filePathArr[i]) && filePathArr[i] != "snippets") break;
307
316
  }
308
317
  return import_node_path3.default.join(...relativePath);
309
318
  }
310
319
 
311
320
  // src/watcher.js
312
321
  var import_rimraf = require("rimraf");
313
- var import_node_path4 = __toESM(require("path"), 1);
314
322
  async function watch(projectDirectory, catalogDirectory, callback = void 0) {
315
323
  const subscription = await import_watcher.default.subscribe(
316
324
  projectDirectory,
@@ -326,7 +334,7 @@ async function watch(projectDirectory, catalogDirectory, callback = void 0) {
326
334
  }
327
335
  for (let event of events) {
328
336
  const { path: filePath, type } = event;
329
- if (filePath.endsWith(".mdx") || filePath.endsWith(".md")) {
337
+ if ((filePath.endsWith(".mdx") || filePath.endsWith(".md")) && !filePath.includes("snippets")) {
330
338
  continue;
331
339
  }
332
340
  const astroPaths = mapCatalogToAstro({
@@ -391,20 +399,27 @@ function retryEPERM(fn) {
391
399
 
392
400
  // src/catalog-to-astro-content-directory.js
393
401
  var import_glob = require("glob");
394
- var path5 = __toESM(require("path"), 1);
402
+ var path4 = __toESM(require("path"), 1);
395
403
  var import_fs = __toESM(require("fs"), 1);
396
404
  var import_url2 = require("url");
397
405
  var import_node_os = __toESM(require("os"), 1);
398
406
  var __filename2 = (0, import_url2.fileURLToPath)(importMetaUrl);
399
- var rootPkg = path5.resolve(path5.dirname(__filename2), "../");
407
+ var rootPkg = path4.resolve(path4.dirname(__filename2), "../");
400
408
  var copyFiles = async (source, target) => {
401
- const files = await (0, import_glob.glob)(path5.join(source, "**"), {
409
+ const files = await (0, import_glob.glob)(path4.join(source, "**"), {
402
410
  nodir: true,
403
411
  windowsPathsNoEscape: import_node_os.default.platform() == "win32",
404
412
  ignore: ["node_modules/**", "**/dist/**", "**/teams", "**/users", "**/*.mdx", "**/*.md", "**/package.json", "**/Dockerfile"]
405
413
  });
406
- if (import_fs.default.existsSync(path5.join(source, ".env"))) {
407
- files.push(path5.join(source, ".env"));
414
+ const snippets = await (0, import_glob.glob)(path4.join(source, "snippets/**/*.mdx"), {
415
+ nodir: true,
416
+ windowsPathsNoEscape: import_node_os.default.platform() == "win32"
417
+ });
418
+ if (snippets.length > 0) {
419
+ files.push(...snippets);
420
+ }
421
+ if (import_fs.default.existsSync(path4.join(source, ".env"))) {
422
+ files.push(path4.join(source, ".env"));
408
423
  }
409
424
  for (const file of files) {
410
425
  mapCatalogToAstro({
@@ -418,17 +433,17 @@ var copyFiles = async (source, target) => {
418
433
  }
419
434
  };
420
435
  var catalogToAstro = async (source, astroDir) => {
421
- const astroContentDir = path5.join(astroDir, "src/content/");
436
+ const astroContentDir = path4.join(astroDir, "src/content/");
422
437
  if (import_fs.default.existsSync(astroContentDir)) import_fs.default.rmSync(astroContentDir, { recursive: true });
423
438
  import_fs.default.mkdirSync(astroContentDir);
424
439
  await verifyRequiredFieldsAreInCatalogConfigFile(source);
425
- if (!import_fs.default.existsSync(path5.join(source, "eventcatalog.styles.css"))) {
426
- import_fs.default.writeFileSync(path5.join(source, "eventcatalog.styles.css"), "");
440
+ if (!import_fs.default.existsSync(path4.join(source, "eventcatalog.styles.css"))) {
441
+ import_fs.default.writeFileSync(path4.join(source, "eventcatalog.styles.css"), "");
427
442
  }
428
443
  await copyFiles(source, astroDir);
429
444
  };
430
445
  var checkAndConvertMdToMdx = async (source, astroDir) => {
431
- const files = await (0, import_glob.glob)(path5.join(source, "**"), {
446
+ const files = await (0, import_glob.glob)(path4.join(source, "**"), {
432
447
  nodir: true,
433
448
  windowsPathsNoEscape: import_node_os.default.platform() == "win32",
434
449
  ignore: ["node_modules/**", "**/dist/**", "**/README.md"]
@@ -444,7 +459,7 @@ var checkAndConvertMdToMdx = async (source, astroDir) => {
444
459
  };
445
460
 
446
461
  // src/resolve-catalog-dependencies.js
447
- var import_node_path5 = __toESM(require("path"), 1);
462
+ var import_node_path4 = __toESM(require("path"), 1);
448
463
  var import_node_fs3 = __toESM(require("fs"), 1);
449
464
  var import_gray_matter2 = __toESM(require("gray-matter"), 1);
450
465
  var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
@@ -453,7 +468,7 @@ var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
453
468
  if (!dependencies) {
454
469
  return;
455
470
  }
456
- const dependenciesDir = import_node_path5.default.join(catalogDir, "dependencies");
471
+ const dependenciesDir = import_node_path4.default.join(catalogDir, "dependencies");
457
472
  if (import_node_fs3.default.existsSync(dependenciesDir)) {
458
473
  import_node_fs3.default.rmSync(dependenciesDir, { recursive: true, force: true });
459
474
  }
@@ -477,8 +492,8 @@ var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
477
492
  },
478
493
  frontmatter
479
494
  );
480
- const resourceFile = import_node_path5.default.join(dependenciesDir, resourceType, dependency.id, `index.md`);
481
- import_node_fs3.default.mkdirSync(import_node_path5.default.dirname(resourceFile), { recursive: true });
495
+ const resourceFile = import_node_path4.default.join(dependenciesDir, resourceType, dependency.id, `index.md`);
496
+ import_node_fs3.default.mkdirSync(import_node_path4.default.dirname(resourceFile), { recursive: true });
482
497
  import_node_fs3.default.writeFileSync(resourceFile, markdown);
483
498
  }
484
499
  }
@@ -490,7 +505,7 @@ var import_boxen2 = __toESM(require("boxen"), 1);
490
505
 
491
506
  // src/features.ts
492
507
  var import_boxen = __toESM(require("boxen"), 1);
493
- var import_node_path6 = require("path");
508
+ var import_node_path5 = require("path");
494
509
  var import_node_fs4 = __toESM(require("fs"), 1);
495
510
  var isOutputServer = async () => {
496
511
  const config = await getEventCatalogConfigFile(process.env.PROJECT_DIR || "");
@@ -498,7 +513,7 @@ var isOutputServer = async () => {
498
513
  };
499
514
  var isAuthEnabled = async () => {
500
515
  const directory = process.env.PROJECT_DIR || process.cwd();
501
- const hasAuthConfig = import_node_fs4.default.existsSync((0, import_node_path6.join)(directory, "eventcatalog.auth.js"));
516
+ const hasAuthConfig = import_node_fs4.default.existsSync((0, import_node_path5.join)(directory, "eventcatalog.auth.js"));
502
517
  return hasAuthConfig;
503
518
  };
504
519
  var isBackstagePluginEnabled = async (licenseKey) => {
@@ -632,14 +647,14 @@ var isEventCatalogStarterEnabled = async (licenseKey) => {
632
647
  // src/eventcatalog.ts
633
648
  var import_update_notifier = __toESM(require("update-notifier"), 1);
634
649
  var import_dotenv = __toESM(require("dotenv"), 1);
635
- var currentDir = import_node_path8.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
650
+ var currentDir = import_node_path7.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
636
651
  var program = new import_commander.Command().version(VERSION);
637
- var dir = import_node_path8.default.resolve(process.env.PROJECT_DIR || process.cwd());
638
- var core = import_node_path8.default.resolve(process.env.CATALOG_DIR || (0, import_node_path7.join)(dir, ".eventcatalog-core"));
639
- var eventCatalogDir = import_node_path8.default.resolve((0, import_node_path7.join)(currentDir, "../eventcatalog/"));
652
+ var dir = import_node_path7.default.resolve(process.env.PROJECT_DIR || process.cwd());
653
+ var core = import_node_path7.default.resolve(process.env.CATALOG_DIR || (0, import_node_path6.join)(dir, ".eventcatalog-core"));
654
+ var eventCatalogDir = import_node_path7.default.resolve((0, import_node_path6.join)(currentDir, "../eventcatalog/"));
640
655
  var getInstalledEventCatalogVersion = () => {
641
656
  try {
642
- const pkg = import_fs2.default.readFileSync((0, import_node_path7.join)(dir, "package.json"), "utf8");
657
+ const pkg = import_fs2.default.readFileSync((0, import_node_path6.join)(dir, "package.json"), "utf8");
643
658
  const json = JSON.parse(pkg);
644
659
  return json.dependencies["@eventcatalog/core"];
645
660
  } catch (error) {
@@ -666,13 +681,13 @@ var copyCore = () => {
666
681
  };
667
682
  var copyServerFiles = async () => {
668
683
  const isServerOutput = await isOutputServer();
669
- if (import_fs2.default.existsSync((0, import_node_path7.join)(core, "src/pages/api/server"))) {
670
- import_fs2.default.rmSync((0, import_node_path7.join)(core, "src/pages/api/server"), { recursive: true });
684
+ if (import_fs2.default.existsSync((0, import_node_path6.join)(core, "src/pages/api/server"))) {
685
+ import_fs2.default.rmSync((0, import_node_path6.join)(core, "src/pages/api/server"), { recursive: true });
671
686
  }
672
687
  if (!isServerOutput) {
673
688
  return;
674
689
  }
675
- import_fs2.default.cpSync((0, import_node_path7.join)(eventCatalogDir, "src/enterprise/eventcatalog-chat/pages/api"), (0, import_node_path7.join)(core, "src/pages/api/server"), {
690
+ import_fs2.default.cpSync((0, import_node_path6.join)(eventCatalogDir, "src/enterprise/eventcatalog-chat/pages/api"), (0, import_node_path6.join)(core, "src/pages/api/server"), {
676
691
  recursive: true
677
692
  });
678
693
  };
@@ -683,7 +698,7 @@ var createAuthFileIfNotExists = async (hasRequiredLicense) => {
683
698
  if (authEnabled && hasRequiredLicense && isSRR) {
684
699
  console.log("Creating auth file");
685
700
  import_fs2.default.writeFileSync(
686
- (0, import_node_path7.join)(core, "src/pages/api/[...auth].ts"),
701
+ (0, import_node_path6.join)(core, "src/pages/api/[...auth].ts"),
687
702
  `import { AstroAuth } from 'auth-astro/server';
688
703
  export const prerender = false;
689
704
  export const { GET, POST } = AstroAuth();
@@ -726,8 +741,8 @@ Run npm i @eventcatalog/core to update`;
726
741
  };
727
742
  program.command("dev").description("Run development server of EventCatalog").option("-d, --debug", "Output EventCatalog application information into your terminal").option("--force-recreate", "Recreate the eventcatalog-core directory", false).action(async (options, command) => {
728
743
  console.log("Setting up EventCatalog....");
729
- if (import_fs2.default.existsSync(import_node_path8.default.join(dir, ".env"))) {
730
- import_dotenv.default.config({ path: import_node_path8.default.join(dir, ".env") });
744
+ if (import_fs2.default.existsSync(import_node_path7.default.join(dir, ".env"))) {
745
+ import_dotenv.default.config({ path: import_node_path7.default.join(dir, ".env") });
731
746
  }
732
747
  if (options.debug) {
733
748
  console.log("Debug mode enabled");
@@ -777,8 +792,8 @@ program.command("dev").description("Run development server of EventCatalog").opt
777
792
  });
778
793
  program.command("build").description("Run build of EventCatalog").action(async (options, command) => {
779
794
  console.log("Building EventCatalog...");
780
- if (import_fs2.default.existsSync(import_node_path8.default.join(dir, ".env"))) {
781
- import_dotenv.default.config({ path: import_node_path8.default.join(dir, ".env") });
795
+ if (import_fs2.default.existsSync(import_node_path7.default.join(dir, ".env"))) {
796
+ import_dotenv.default.config({ path: import_node_path7.default.join(dir, ".env") });
782
797
  }
783
798
  copyCore();
784
799
  await copyServerFiles();
@@ -836,8 +851,8 @@ var startServerCatalog = ({
836
851
  };
837
852
  program.command("preview").description("Serves the contents of your eventcatalog build directory").action(async (options, command) => {
838
853
  console.log("Starting preview of your build...");
839
- if (import_fs2.default.existsSync(import_node_path8.default.join(dir, ".env"))) {
840
- import_dotenv.default.config({ path: import_node_path8.default.join(dir, ".env") });
854
+ if (import_fs2.default.existsSync(import_node_path7.default.join(dir, ".env"))) {
855
+ import_dotenv.default.config({ path: import_node_path7.default.join(dir, ".env") });
841
856
  }
842
857
  const canEmbedPages = await isBackstagePluginEnabled();
843
858
  const isEventCatalogStarter = await isEventCatalogStarterEnabled();
@@ -848,8 +863,8 @@ program.command("preview").description("Serves the contents of your eventcatalog
848
863
  });
849
864
  program.command("start").description("Serves the contents of your eventcatalog build directory").action(async (options, command) => {
850
865
  console.log("Starting preview of your build...");
851
- if (import_fs2.default.existsSync(import_node_path8.default.join(dir, ".env"))) {
852
- import_dotenv.default.config({ path: import_node_path8.default.join(dir, ".env") });
866
+ if (import_fs2.default.existsSync(import_node_path7.default.join(dir, ".env"))) {
867
+ import_dotenv.default.config({ path: import_node_path7.default.join(dir, ".env") });
853
868
  }
854
869
  const canEmbedPages = await isBackstagePluginEnabled();
855
870
  const isEventCatalogStarter = await isEventCatalogStarterEnabled();
@@ -862,8 +877,8 @@ program.command("start").description("Serves the contents of your eventcatalog b
862
877
  }
863
878
  });
864
879
  program.command("generate [siteDir]").description("Start the generator scripts.").action(async () => {
865
- if (import_fs2.default.existsSync(import_node_path8.default.join(dir, ".env"))) {
866
- import_dotenv.default.config({ path: import_node_path8.default.join(dir, ".env") });
880
+ if (import_fs2.default.existsSync(import_node_path7.default.join(dir, ".env"))) {
881
+ import_dotenv.default.config({ path: import_node_path7.default.join(dir, ".env") });
867
882
  }
868
883
  await generate(dir);
869
884
  });
@@ -3,19 +3,19 @@ import {
3
3
  } from "./chunk-BLDONK5J.js";
4
4
  import {
5
5
  watch
6
- } from "./chunk-DCLTVJDP.js";
6
+ } from "./chunk-MDWGYIVH.js";
7
7
  import {
8
8
  log_build_default
9
- } from "./chunk-YJYT2E6S.js";
10
- import "./chunk-QWDFTW7H.js";
9
+ } from "./chunk-RW4O4UUQ.js";
10
+ import "./chunk-LK6C3F6Q.js";
11
11
  import {
12
12
  catalogToAstro,
13
13
  checkAndConvertMdToMdx
14
- } from "./chunk-SFA7F3CQ.js";
15
- import "./chunk-EXAALOQA.js";
14
+ } from "./chunk-B53UJPGW.js";
15
+ import "./chunk-WDTWWPPX.js";
16
16
  import {
17
17
  VERSION
18
- } from "./chunk-WWYOMQLW.js";
18
+ } from "./chunk-I755G24S.js";
19
19
  import {
20
20
  isAuthEnabled,
21
21
  isBackstagePluginEnabled,
@@ -72,6 +72,8 @@ function isCatalogRelated(filePath) {
72
72
  // custom styles file at root
73
73
  "components",
74
74
  // custom components
75
+ "snippets",
76
+ // custom snippets
75
77
  "public",
76
78
  // public assets
77
79
  ".env",
@@ -94,6 +96,9 @@ function getBaseTargetPaths(filePath) {
94
96
  if (filePathArr[0] == "components") {
95
97
  return [import_node_path.default.join("src", "custom-defined-components")];
96
98
  }
99
+ if (filePathArr[0] == "snippets") {
100
+ return [import_node_path.default.join("src")];
101
+ }
97
102
  if (filePathArr[0] == "public") {
98
103
  return [import_node_path.default.join("public")];
99
104
  }
@@ -104,10 +109,14 @@ function getRelativeTargetPath(filePath) {
104
109
  if (filePathArr[0] == "public" || filePathArr[0] == "components") {
105
110
  filePathArr.shift();
106
111
  }
112
+ if (filePathArr[0] == "snippets") {
113
+ console.log("SNIPPETS", filePathArr);
114
+ return import_node_path.default.join("snippets", ...filePathArr.slice(1));
115
+ }
107
116
  const relativePath = [];
108
117
  for (let i = filePathArr.length - 1; i >= 0; i--) {
109
118
  relativePath.unshift(filePathArr[i]);
110
- if (isCollectionKey(filePathArr[i])) break;
119
+ if (isCollectionKey(filePathArr[i]) && filePathArr[i] != "snippets") break;
111
120
  }
112
121
  return import_node_path.default.join(...relativePath);
113
122
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mapCatalogToAstro
3
- } from "./chunk-EXAALOQA.js";
3
+ } from "./chunk-WDTWWPPX.js";
4
4
  export {
5
5
  mapCatalogToAstro
6
6
  };
package/dist/watcher.cjs CHANGED
@@ -34,7 +34,7 @@ __export(watcher_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(watcher_exports);
36
36
  var import_watcher = __toESM(require("@parcel/watcher"), 1);
37
- var import_node_fs2 = __toESM(require("fs"), 1);
37
+ 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);
@@ -76,6 +76,8 @@ function isCatalogRelated(filePath) {
76
76
  // custom styles file at root
77
77
  "components",
78
78
  // custom components
79
+ "snippets",
80
+ // custom snippets
79
81
  "public",
80
82
  // public assets
81
83
  ".env",
@@ -98,6 +100,9 @@ function getBaseTargetPaths(filePath) {
98
100
  if (filePathArr[0] == "components") {
99
101
  return [import_node_path.default.join("src", "custom-defined-components")];
100
102
  }
103
+ if (filePathArr[0] == "snippets") {
104
+ return [import_node_path.default.join("src")];
105
+ }
101
106
  if (filePathArr[0] == "public") {
102
107
  return [import_node_path.default.join("public")];
103
108
  }
@@ -108,27 +113,20 @@ function getRelativeTargetPath(filePath) {
108
113
  if (filePathArr[0] == "public" || filePathArr[0] == "components") {
109
114
  filePathArr.shift();
110
115
  }
116
+ if (filePathArr[0] == "snippets") {
117
+ console.log("SNIPPETS", filePathArr);
118
+ return import_node_path.default.join("snippets", ...filePathArr.slice(1));
119
+ }
111
120
  const relativePath = [];
112
121
  for (let i = filePathArr.length - 1; i >= 0; i--) {
113
122
  relativePath.unshift(filePathArr[i]);
114
- if (isCollectionKey(filePathArr[i])) break;
123
+ if (isCollectionKey(filePathArr[i]) && filePathArr[i] != "snippets") break;
115
124
  }
116
125
  return import_node_path.default.join(...relativePath);
117
126
  }
118
127
 
119
128
  // src/watcher.js
120
129
  var import_rimraf = require("rimraf");
121
-
122
- // src/eventcatalog-config-file-utils.js
123
- var import_promises = require("fs/promises");
124
- var import_node_fs = require("fs");
125
- var import_promises2 = require("fs/promises");
126
- var import_node_path2 = __toESM(require("path"), 1);
127
- var import_uuid = require("uuid");
128
- var import_gray_matter = __toESM(require("gray-matter"), 1);
129
-
130
- // src/watcher.js
131
- var import_node_path3 = __toESM(require("path"), 1);
132
130
  async function watch(projectDirectory, catalogDirectory, callback = void 0) {
133
131
  const subscription = await import_watcher.default.subscribe(
134
132
  projectDirectory,
@@ -144,7 +142,7 @@ async function watch(projectDirectory, catalogDirectory, callback = void 0) {
144
142
  }
145
143
  for (let event of events) {
146
144
  const { path: filePath, type } = event;
147
- if (filePath.endsWith(".mdx") || filePath.endsWith(".md")) {
145
+ if ((filePath.endsWith(".mdx") || filePath.endsWith(".md")) && !filePath.includes("snippets")) {
148
146
  continue;
149
147
  }
150
148
  const astroPaths = mapCatalogToAstro({
@@ -156,10 +154,10 @@ async function watch(projectDirectory, catalogDirectory, callback = void 0) {
156
154
  switch (type) {
157
155
  case "create":
158
156
  case "update":
159
- if (import_node_fs2.default.statSync(filePath).isDirectory()) {
160
- import_node_fs2.default.mkdirSync(astroPath, { recursive: true });
157
+ if (import_node_fs.default.statSync(filePath).isDirectory()) {
158
+ import_node_fs.default.mkdirSync(astroPath, { recursive: true });
161
159
  } else {
162
- retryEPERM(import_node_fs2.default.cpSync)(filePath, astroPath);
160
+ retryEPERM(import_node_fs.default.cpSync)(filePath, astroPath);
163
161
  }
164
162
  break;
165
163
  case "delete":
package/dist/watcher.js CHANGED
@@ -1,8 +1,7 @@
1
1
  import {
2
2
  watch
3
- } from "./chunk-DCLTVJDP.js";
4
- import "./chunk-EXAALOQA.js";
5
- import "./chunk-E7TXTI7G.js";
3
+ } from "./chunk-MDWGYIVH.js";
4
+ import "./chunk-WDTWWPPX.js";
6
5
  export {
7
6
  watch
8
7
  };
@@ -1,10 +1,11 @@
1
1
  import React, { useState, useEffect, useRef, useMemo, useCallback } from 'react';
2
- import { ChevronDownIcon } from '@heroicons/react/24/outline';
2
+ import { ChevronDownIcon, ChevronDoubleDownIcon, ChevronDoubleUpIcon, XMarkIcon } from '@heroicons/react/24/outline';
3
3
  import { buildUrl, buildUrlWithParams } from '@utils/url-builder';
4
4
  import CollapsibleGroup from './components/CollapsibleGroup';
5
5
  import MessageList from './components/MessageList';
6
6
  import SpecificationsList from './components/SpecificationList';
7
7
  import type { MessageItem, ServiceItem, ListViewSideBarProps, DomainItem, FlowItem, Resources } from './types';
8
+ import { PanelLeft } from 'lucide-react';
8
9
  const STORAGE_KEY = 'EventCatalog:catalogSidebarCollapsedGroups';
9
10
  const DEBOUNCE_DELAY = 300; // 300ms debounce delay
10
11
 
@@ -204,6 +205,7 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
204
205
  const [searchTerm, setSearchTerm] = useState('');
205
206
  const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
206
207
  const [isInitialized, setIsInitialized] = useState(false);
208
+ const [isExpanded, setIsExpanded] = useState(true);
207
209
  const [collapsedGroups, setCollapsedGroups] = useState<{ [key: string]: boolean }>(() => {
208
210
  if (typeof window !== 'undefined') {
209
211
  const saved = window.localStorage.getItem(STORAGE_KEY);
@@ -241,9 +243,55 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
241
243
  );
242
244
  };
243
245
 
246
+ // Enhanced domain filtering that considers parent-subdomain relationships
247
+ const filterDomains = (domains: any[]) => {
248
+ const filteredDomains: any[] = [];
249
+
250
+ domains.forEach((domain: any) => {
251
+ const domainMatches = filterItem(domain);
252
+
253
+ // Check if this domain is a subdomain of another domain
254
+ const isSubdomain = domains.some((parentDomain: any) => {
255
+ const subdomains = parentDomain.domains || [];
256
+ return subdomains.some((subdomain: any) => subdomain.data.id === domain.id);
257
+ });
258
+
259
+ // If this is a parent domain, check if any of its subdomains match
260
+ let hasMatchingSubdomains = false;
261
+ if (!isSubdomain) {
262
+ const subdomains = domain.domains || [];
263
+ hasMatchingSubdomains = domains.some((potentialSubdomain: any) =>
264
+ subdomains.some((subdomain: any) => subdomain.data.id === potentialSubdomain.id && filterItem(potentialSubdomain))
265
+ );
266
+ }
267
+
268
+ // Include domain if:
269
+ // 1. The domain itself matches the search
270
+ // 2. It's a parent domain and has matching subdomains
271
+ // 3. It's a subdomain and matches the search
272
+ if (domainMatches || hasMatchingSubdomains || (isSubdomain && domainMatches)) {
273
+ filteredDomains.push(domain);
274
+ }
275
+
276
+ // If this is a subdomain that matches, also include its parent domain
277
+ if (isSubdomain && domainMatches) {
278
+ const parentDomain = domains.find((parentDomain: any) => {
279
+ const subdomains = parentDomain.domains || [];
280
+ return subdomains.some((subdomain: any) => subdomain.data.id === domain.id);
281
+ });
282
+
283
+ if (parentDomain && !filteredDomains.some((d: any) => d.id === parentDomain.id)) {
284
+ filteredDomains.push(parentDomain);
285
+ }
286
+ }
287
+ });
288
+
289
+ return filteredDomains;
290
+ };
291
+
244
292
  return {
245
293
  'context-map': data['context-map']?.filter(filterItem) || [],
246
- domains: data.domains?.filter(filterItem) || [],
294
+ domains: data.domains ? filterDomains(data.domains) : [],
247
295
  services:
248
296
  data.services
249
297
  ?.map((service: ServiceItem) => ({
@@ -310,6 +358,65 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
310
358
  setSearchTerm(e.target.value);
311
359
  }, []);
312
360
 
361
+ const collapseAll = useCallback(() => {
362
+ const newCollapsedState: { [key: string]: boolean } = {};
363
+
364
+ // Collapse all domains
365
+ filteredData.domains?.forEach((domain: any) => {
366
+ newCollapsedState[domain.href] = true;
367
+ newCollapsedState[`${domain.href}-entities`] = true;
368
+ newCollapsedState[`${domain.href}-subdomains`] = true;
369
+ });
370
+
371
+ // Collapse all services
372
+ filteredData.services?.forEach((service: any) => {
373
+ newCollapsedState[service.href] = true;
374
+ newCollapsedState[`${service.href}-specifications`] = true;
375
+ newCollapsedState[`${service.href}-receives`] = true;
376
+ newCollapsedState[`${service.href}-sends`] = true;
377
+ newCollapsedState[`${service.href}-entities`] = true;
378
+ });
379
+
380
+ setCollapsedGroups(newCollapsedState);
381
+ setIsExpanded(false);
382
+ }, [filteredData]);
383
+
384
+ const expandAll = useCallback(() => {
385
+ const newCollapsedState: { [key: string]: boolean } = {};
386
+
387
+ // Expand all domains
388
+ filteredData.domains?.forEach((domain: any) => {
389
+ newCollapsedState[domain.href] = false;
390
+ newCollapsedState[`${domain.href}-entities`] = false;
391
+ newCollapsedState[`${domain.href}-subdomains`] = false;
392
+ });
393
+
394
+ // Expand all services
395
+ filteredData.services?.forEach((service: any) => {
396
+ newCollapsedState[service.href] = false;
397
+ newCollapsedState[`${service.href}-specifications`] = false;
398
+ newCollapsedState[`${service.href}-receives`] = false;
399
+ newCollapsedState[`${service.href}-sends`] = false;
400
+ newCollapsedState[`${service.href}-entities`] = false;
401
+ });
402
+
403
+ setCollapsedGroups(newCollapsedState);
404
+ setIsExpanded(true);
405
+ }, [filteredData]);
406
+
407
+ const toggleExpandCollapse = useCallback(() => {
408
+ if (isExpanded) {
409
+ collapseAll();
410
+ } else {
411
+ expandAll();
412
+ }
413
+ }, [isExpanded, collapseAll, expandAll]);
414
+
415
+ const hideSidebar = useCallback(() => {
416
+ // Dispatch custom event that the Astro layout will listen for
417
+ window.dispatchEvent(new CustomEvent('sidebarToggle', { detail: { action: 'hide' } }));
418
+ }, []);
419
+
313
420
  const isDomainSubDomain = useMemo(() => {
314
421
  return (domain: any) => {
315
422
  const domains = data.domains || [];
@@ -320,6 +427,125 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
320
427
  };
321
428
  }, [data.domains]);
322
429
 
430
+ // Helper function to get parent domains (domains that are not subdomains)
431
+ const getParentDomains = useMemo(() => {
432
+ return (domains: any[]) => {
433
+ return domains.filter((domain: any) => !isDomainSubDomain(domain));
434
+ };
435
+ }, [isDomainSubDomain]);
436
+
437
+ // Helper function to get subdomains for a specific parent domain
438
+ const getSubdomainsForParent = useMemo(() => {
439
+ return (parentDomain: any, allDomains: any[]) => {
440
+ const subdomains = parentDomain.domains || [];
441
+ return allDomains.filter((domain: any) => subdomains.some((subdomain: any) => subdomain.data.id === domain.id));
442
+ };
443
+ }, []);
444
+
445
+ // Component to render a single domain item
446
+ const DomainItem = React.memo(
447
+ ({ item, isSubdomain = false, nestingLevel = 0 }: { item: any; isSubdomain?: boolean; nestingLevel?: number }) => {
448
+ const marginLeft = nestingLevel > 0 ? `ml-${nestingLevel * 4}` : '';
449
+
450
+ return (
451
+ <div className={`flex items-center ${marginLeft}`}>
452
+ <button
453
+ onClick={(e) => {
454
+ e.stopPropagation();
455
+ toggleGroupCollapse(item.href);
456
+ }}
457
+ className="p-1 hover:bg-gray-100 rounded-md"
458
+ >
459
+ <div className={`transition-transform duration-150 ${collapsedGroups[item.href] ? '' : 'rotate-180'}`}>
460
+ <ChevronDownIcon className="h-3 w-3 text-gray-500" />
461
+ </div>
462
+ </button>
463
+ <button
464
+ onClick={(e) => {
465
+ e.stopPropagation();
466
+ toggleGroupCollapse(item.href);
467
+ }}
468
+ className={`flex-grow flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md ${
469
+ decodedCurrentPath === item.href ? 'bg-purple-100' : 'hover:bg-purple-100'
470
+ }`}
471
+ >
472
+ <span className="truncate">
473
+ <HighlightedText text={item.label} searchTerm={debouncedSearchTerm} />
474
+ </span>
475
+ <span className="text-yellow-600 ml-2 text-[10px] font-medium bg-yellow-50 px-2 py-0.5 rounded">
476
+ {isSubdomain ? 'SUBDOMAIN' : 'DOMAIN'}
477
+ </span>
478
+ </button>
479
+ </div>
480
+ );
481
+ }
482
+ );
483
+
484
+ // Component to render domain content (Overview, Architecture, etc.)
485
+ const DomainContent = React.memo(({ item, nestingLevel = 0 }: { item: any; nestingLevel?: number }) => {
486
+ const marginLeft = nestingLevel > 0 ? `ml-${nestingLevel * 4}` : '';
487
+
488
+ return (
489
+ <div
490
+ className={`overflow-hidden transition-[height] duration-150 ease-out ${collapsedGroups[item.href] ? 'h-0' : 'h-auto'}`}
491
+ >
492
+ <div className={`space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-1 ${marginLeft}`}>
493
+ <a
494
+ href={`${item.href}`}
495
+ className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
496
+ decodedCurrentPath === item.href ? 'bg-purple-100 ' : 'hover:bg-purple-100'
497
+ }`}
498
+ >
499
+ <span className="truncate">Overview</span>
500
+ </a>
501
+ {!isVisualizer && (
502
+ <a
503
+ href={buildUrlWithParams('/architecture/docs/services', {
504
+ serviceIds: item.services.map((service: any) => service.data.id).join(','),
505
+ domainId: item.id,
506
+ domainName: item.name,
507
+ })}
508
+ className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
509
+ window.location.href.includes(`domainId=${item.id}`) ? 'bg-purple-100 ' : 'hover:bg-purple-100'
510
+ }`}
511
+ >
512
+ <span className="truncate">Architecture</span>
513
+ </a>
514
+ )}
515
+ {!isVisualizer && (
516
+ <a
517
+ href={buildUrl(`/docs/domains/${item.id}/language`)}
518
+ className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
519
+ decodedCurrentPath.includes(`/docs/domains/${item.id}/language`) ? 'bg-purple-100 ' : 'hover:bg-purple-100'
520
+ }`}
521
+ >
522
+ <span className="truncate">Ubiquitous Language</span>
523
+ </a>
524
+ )}
525
+ {item.entities.length > 0 && !isVisualizer && (
526
+ <CollapsibleGroup
527
+ isCollapsed={collapsedGroups[`${item.href}-entities`]}
528
+ onToggle={() => toggleGroupCollapse(`${item.href}-entities`)}
529
+ title={
530
+ <button
531
+ onClick={(e) => {
532
+ e.stopPropagation();
533
+ toggleGroupCollapse(`${item.href}-entities`);
534
+ }}
535
+ className="truncate underline ml-2 text-xs mb-1 py-1"
536
+ >
537
+ Entities ({item.entities.length})
538
+ </button>
539
+ }
540
+ >
541
+ <MessageList messages={item.entities} decodedCurrentPath={decodedCurrentPath} searchTerm={debouncedSearchTerm} />
542
+ </CollapsibleGroup>
543
+ )}
544
+ </div>
545
+ </div>
546
+ );
547
+ });
548
+
323
549
  if (!isInitialized) return null;
324
550
 
325
551
  const hasNoResults =
@@ -332,13 +558,35 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
332
558
 
333
559
  return (
334
560
  <nav ref={navRef} className="space-y-4 text-gray-800 px-3 py-4">
335
- <input
336
- type="text"
337
- value={searchTerm}
338
- onChange={handleSearchChange}
339
- placeholder="Quick search..."
340
- className="w-full p-2 text-sm rounded-md border border-gray-200 h-[30px]"
341
- />
561
+ <div className="flex gap-2">
562
+ <input
563
+ type="text"
564
+ value={searchTerm}
565
+ onChange={handleSearchChange}
566
+ placeholder="Quick search..."
567
+ className="flex-1 p-2 text-sm rounded-md border border-gray-200 h-[30px]"
568
+ />
569
+ <div className="flex gap-1">
570
+ <button
571
+ onClick={toggleExpandCollapse}
572
+ title={isExpanded ? 'Collapse All' : 'Expand All'}
573
+ className="px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md border border-gray-200 h-[30px] flex items-center justify-center"
574
+ >
575
+ {isExpanded ? (
576
+ <ChevronDoubleUpIcon className="h-4 w-4 text-gray-600" />
577
+ ) : (
578
+ <ChevronDoubleDownIcon className="h-4 w-4 text-gray-600" />
579
+ )}
580
+ </button>
581
+ <button
582
+ onClick={hideSidebar}
583
+ title="Hide Sidebar"
584
+ className="px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md border border-gray-200 h-[30px] flex items-center justify-center"
585
+ >
586
+ <PanelLeft className="h-4 w-4 text-gray-600" />
587
+ </button>
588
+ </div>
589
+ </div>
342
590
  <div className="space-y-2 divide-y divide-gray-200/80">
343
591
  {hasNoResults ? (
344
592
  <NoResultsFound searchTerm={debouncedSearchTerm} />
@@ -372,104 +620,50 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
372
620
  {filteredData['domains'] && (
373
621
  <div className={`${isVisualizer ? 'pt-4 pb-2' : 'p-0'}`}>
374
622
  <ul className="space-y-2">
375
- {filteredData['domains'].map((item: any) => (
376
- <li key={item.href} className="space-y-0" data-active={decodedCurrentPath === item.href}>
377
- <div className="flex items-center">
378
- <button
379
- onClick={(e) => {
380
- e.stopPropagation();
381
- toggleGroupCollapse(item.href);
382
- }}
383
- className="p-1 hover:bg-gray-100 rounded-md"
384
- >
385
- <div className={`transition-transform duration-150 ${collapsedGroups[item.href] ? '' : 'rotate-180'}`}>
386
- <ChevronDownIcon className="h-3 w-3 text-gray-500" />
387
- </div>
388
- </button>
389
- <button
390
- onClick={(e) => {
391
- e.stopPropagation();
392
- toggleGroupCollapse(item.href);
393
- }}
394
- className={`flex-grow flex items-center justify-between px-2 py-0.5 text-xs font-bold rounded-md ${
395
- decodedCurrentPath === item.href
396
- }`}
397
- >
398
- <span className="truncate">
399
- <HighlightedText text={item.label} searchTerm={debouncedSearchTerm} />
400
- </span>
401
- <span className="text-yellow-600 ml-2 text-[10px] font-medium bg-yellow-50 px-2 py-0.5 rounded">
402
- {isDomainSubDomain(item) ? 'SUBDOMAIN' : 'DOMAIN'}
403
- </span>
404
- </button>
405
- </div>
406
- <div
407
- className={`overflow-hidden transition-[height] duration-150 ease-out ${
408
- collapsedGroups[item.href] ? 'h-0' : 'h-auto'
409
- }`}
410
- >
411
- <div className="space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-1">
412
- <a
413
- href={`${item.href}`}
414
- className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
415
- decodedCurrentPath === item.href ? 'bg-purple-100 ' : 'hover:bg-purple-100'
416
- }`}
417
- >
418
- <span className="truncate">Overview</span>
419
- </a>
420
- {!isVisualizer && (
421
- <a
422
- href={buildUrlWithParams('/architecture/docs/services', {
423
- serviceIds: item.services.map((service: any) => service.data.id).join(','),
424
- domainId: item.id,
425
- domainName: item.name,
426
- })}
427
- className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
428
- window.location.href.includes(`domainId=${item.id}`) ? 'bg-purple-100 ' : 'hover:bg-purple-100'
429
- }`}
430
- >
431
- <span className="truncate">Architecture</span>
432
- </a>
433
- )}
434
- {!isVisualizer && (
435
- <a
436
- href={buildUrl(`/docs/domains/${item.id}/language`)}
437
- className={`flex items-center px-2 py-1.5 text-xs text-gray-600 hover:bg-purple-100 rounded-md ${
438
- decodedCurrentPath.includes(`/docs/domains/${item.id}/language`)
439
- ? 'bg-purple-100 '
440
- : 'hover:bg-purple-100'
441
- }`}
442
- >
443
- <span className="truncate">Ubiquitous Language</span>
444
- </a>
445
- )}
446
- {item.entities.length > 0 && !isVisualizer && (
623
+ {getParentDomains(filteredData['domains'] || []).map((parentDomain: any) => {
624
+ const subdomains = getSubdomainsForParent(parentDomain, filteredData['domains'] || []);
625
+
626
+ return (
627
+ <li key={parentDomain.href} className="space-y-0" data-active={decodedCurrentPath === parentDomain.href}>
628
+ <DomainItem item={parentDomain} isSubdomain={false} />
629
+ <DomainContent item={parentDomain} />
630
+
631
+ {/* Render nested subdomains */}
632
+ {subdomains.length > 0 && !collapsedGroups[parentDomain.href] && (
633
+ <div className="space-y-0.5 border-gray-200/80 border-l pl-4 ml-[9px] mt-2">
447
634
  <CollapsibleGroup
448
- isCollapsed={collapsedGroups[`${item.href}-entities`]}
449
- onToggle={() => toggleGroupCollapse(`${item.href}-entities`)}
635
+ isCollapsed={collapsedGroups[`${parentDomain.href}-subdomains`]}
636
+ onToggle={() => toggleGroupCollapse(`${parentDomain.href}-subdomains`)}
450
637
  title={
451
638
  <button
452
639
  onClick={(e) => {
453
640
  e.stopPropagation();
454
- toggleGroupCollapse(`${item.href}-entities`);
641
+ toggleGroupCollapse(`${parentDomain.href}-subdomains`);
455
642
  }}
456
643
  className="truncate underline ml-2 text-xs mb-1 py-1"
457
644
  >
458
- Entities ({item.entities.length})
645
+ Subdomains ({subdomains.length})
459
646
  </button>
460
647
  }
461
648
  >
462
- <MessageList
463
- messages={item.entities}
464
- decodedCurrentPath={decodedCurrentPath}
465
- searchTerm={debouncedSearchTerm}
466
- />
649
+ <div className="space-y-2">
650
+ {subdomains.map((subdomain: any) => (
651
+ <div
652
+ key={subdomain.href}
653
+ className="space-y-0"
654
+ data-active={decodedCurrentPath === subdomain.href}
655
+ >
656
+ <DomainItem item={subdomain} isSubdomain={true} nestingLevel={1} />
657
+ <DomainContent item={subdomain} nestingLevel={1} />
658
+ </div>
659
+ ))}
660
+ </div>
467
661
  </CollapsibleGroup>
468
- )}
469
- </div>
470
- </div>
471
- </li>
472
- ))}
662
+ </div>
663
+ )}
664
+ </li>
665
+ );
666
+ })}
473
667
  </ul>
474
668
  </div>
475
669
  )}
@@ -492,7 +686,7 @@ const ListViewSideBar: React.FC<ListViewSideBarProps> = ({ resources, currentPat
492
686
  </div>
493
687
  )}
494
688
 
495
- {filteredData['messagesNotInService'] && (
689
+ {filteredData['messagesNotInService'] && filteredData['messagesNotInService'].length > 0 && (
496
690
  <div className="pt-4 pb-2">
497
691
  <ul className="space-y-4">
498
692
  {filteredData['messagesNotInService'].map((item: any) => (
@@ -1,4 +1,5 @@
1
1
  import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
2
+ import { ChevronDoubleDownIcon, ChevronDoubleUpIcon } from '@heroicons/react/24/outline';
2
3
  import { buildUrl } from '@utils/url-builder';
3
4
  import type { CustomDocsNavProps, SidebarSection, SidebarItem } from './types';
4
5
  import NestedItem from './components/NestedItem';
@@ -12,6 +13,7 @@ const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems }) => {
12
13
  const [searchTerm, setSearchTerm] = useState('');
13
14
  const [debouncedSearchTerm, setDebouncedSearchTerm] = useState('');
14
15
  const [isInitialized, setIsInitialized] = useState(false);
16
+ const [isExpanded, setIsExpanded] = useState(true);
15
17
  const [collapsedGroups, setCollapsedGroups] = useState<{ [key: string]: boolean }>(() => {
16
18
  if (typeof window !== 'undefined') {
17
19
  const saved = window.localStorage.getItem(STORAGE_KEY);
@@ -126,6 +128,70 @@ const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems }) => {
126
128
  setSearchTerm(e.target.value);
127
129
  }, []);
128
130
 
131
+ const collapseAll = useCallback(() => {
132
+ const newCollapsedState: { [key: string]: boolean } = {};
133
+
134
+ // Collapse all sections
135
+ filteredSidebarItems.forEach((section, index) => {
136
+ const sectionKey = `section-${index}`;
137
+ newCollapsedState[sectionKey] = true;
138
+
139
+ // Collapse all nested items in the section
140
+ const collapseNestedItems = (items: SidebarItem[], parentId: string) => {
141
+ items.forEach((item, itemIndex) => {
142
+ if (item.items && item.items.length > 0) {
143
+ const itemKey = `${parentId}-${itemIndex}`;
144
+ newCollapsedState[itemKey] = true;
145
+ collapseNestedItems(item.items, itemKey);
146
+ }
147
+ });
148
+ };
149
+
150
+ if (section.items) {
151
+ collapseNestedItems(section.items, sectionKey);
152
+ }
153
+ });
154
+
155
+ setCollapsedGroups(newCollapsedState);
156
+ setIsExpanded(false);
157
+ }, [filteredSidebarItems]);
158
+
159
+ const expandAll = useCallback(() => {
160
+ const newCollapsedState: { [key: string]: boolean } = {};
161
+
162
+ // Expand all sections
163
+ filteredSidebarItems.forEach((section, index) => {
164
+ const sectionKey = `section-${index}`;
165
+ newCollapsedState[sectionKey] = false;
166
+
167
+ // Expand all nested items in the section
168
+ const expandNestedItems = (items: SidebarItem[], parentId: string) => {
169
+ items.forEach((item, itemIndex) => {
170
+ if (item.items && item.items.length > 0) {
171
+ const itemKey = `${parentId}-${itemIndex}`;
172
+ newCollapsedState[itemKey] = false;
173
+ expandNestedItems(item.items, itemKey);
174
+ }
175
+ });
176
+ };
177
+
178
+ if (section.items) {
179
+ expandNestedItems(section.items, sectionKey);
180
+ }
181
+ });
182
+
183
+ setCollapsedGroups(newCollapsedState);
184
+ setIsExpanded(true);
185
+ }, [filteredSidebarItems]);
186
+
187
+ const toggleExpandCollapse = useCallback(() => {
188
+ if (isExpanded) {
189
+ collapseAll();
190
+ } else {
191
+ expandAll();
192
+ }
193
+ }, [isExpanded, collapseAll, expandAll]);
194
+
129
195
  if (!isInitialized) return null;
130
196
 
131
197
  const hasNoResults = debouncedSearchTerm && filteredSidebarItems.length === 0;
@@ -133,13 +199,26 @@ const CustomDocsNav: React.FC<CustomDocsNavProps> = ({ sidebarItems }) => {
133
199
  return (
134
200
  <nav ref={navRef} className="h-full text-gray-800 pt-4 overflow-y-auto">
135
201
  <div className="mb-2 px-3 bg-white z-10">
136
- <input
137
- type="text"
138
- value={searchTerm}
139
- onChange={handleSearchChange}
140
- placeholder="Quick search..."
141
- className="w-full p-2 px-2 text-sm rounded-md border border-gray-200 h-[30px]"
142
- />
202
+ <div className="flex gap-2">
203
+ <input
204
+ type="text"
205
+ value={searchTerm}
206
+ onChange={handleSearchChange}
207
+ placeholder="Quick search..."
208
+ className="flex-1 p-2 px-2 text-sm rounded-md border border-gray-200 h-[30px]"
209
+ />
210
+ <button
211
+ onClick={toggleExpandCollapse}
212
+ title={isExpanded ? 'Collapse All' : 'Expand All'}
213
+ className="px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md border border-gray-200 h-[30px] flex items-center justify-center"
214
+ >
215
+ {isExpanded ? (
216
+ <ChevronDoubleUpIcon className="h-4 w-4 text-gray-600" />
217
+ ) : (
218
+ <ChevronDoubleDownIcon className="h-4 w-4 text-gray-600" />
219
+ )}
220
+ </button>
221
+ </div>
143
222
  </div>
144
223
 
145
224
  <div className="space-y-2 divide-y divide-gray-100/40 pb-4">
@@ -454,5 +454,15 @@ const canPageBeEmbedded = process.env.ENABLE_EMBED === 'true';
454
454
  }
455
455
  });
456
456
  }
457
+
458
+ // Listen for custom sidebar toggle event from React components
459
+ window.addEventListener('sidebarToggle', (event) => {
460
+ const { action } = event.detail;
461
+ if (action === 'hide') {
462
+ hideSidebar();
463
+ } else if (action === 'show') {
464
+ showSidebar();
465
+ }
466
+ });
457
467
  });
458
468
  </script>
@@ -9,6 +9,7 @@
9
9
  "@icons/*": ["src/icons/*"],
10
10
  "@components/*": ["src/components/*"],
11
11
  "@catalog/components/*": ["src/custom-defined-components/*"],
12
+ "@catalog/snippets/*": ["src/snippets/*"],
12
13
  "@types": ["src/types/index.ts"],
13
14
  "@utils/*": ["src/utils/*"],
14
15
  "@layouts/*": ["src/layouts/*"],
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "url": "https://github.com/event-catalog/eventcatalog.git"
7
7
  },
8
8
  "type": "module",
9
- "version": "2.47.1",
9
+ "version": "2.48.0",
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },