@eventcatalog/core 4.7.2 → 4.7.4

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 (41) 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 +65 -13
  6. package/dist/catalog-to-astro-content-directory.js +2 -1
  7. package/dist/{chunk-FTNXTYFU.js → chunk-7QTCSRAC.js} +1 -1
  8. package/dist/chunk-A2RZR3U4.js +29 -0
  9. package/dist/{chunk-CWVGSEON.js → chunk-FDXJIZ74.js} +1 -1
  10. package/dist/{chunk-ZR6AH5Z2.js → chunk-RIUHZZRA.js} +4 -4
  11. package/dist/chunk-SDZQJTJW.js +90 -0
  12. package/dist/{chunk-W3SAPOZU.js → chunk-T4RVWPIQ.js} +6 -0
  13. package/dist/chunk-T5IUG523.js +54 -0
  14. package/dist/{chunk-YTT25224.js → chunk-TLWM7WRZ.js} +1 -1
  15. package/dist/{chunk-5QOWJT54.js → chunk-ZIABX6SP.js} +3 -3
  16. package/dist/{chunk-2ERJ2Z5B.js → chunk-ZXVQXBTT.js} +1 -1
  17. package/dist/constants.cjs +1 -1
  18. package/dist/constants.js +1 -1
  19. package/dist/custom-components.cjs +89 -0
  20. package/dist/custom-components.d.cts +4 -0
  21. package/dist/custom-components.d.ts +4 -0
  22. package/dist/custom-components.js +8 -0
  23. package/dist/eventcatalog.cjs +401 -241
  24. package/dist/eventcatalog.config.d.cts +3 -3
  25. package/dist/eventcatalog.config.d.ts +3 -3
  26. package/dist/eventcatalog.js +14 -11
  27. package/dist/federation/federate.cjs +269 -163
  28. package/dist/federation/federate.js +3 -1
  29. package/dist/federation/filesystem-source-provider.cjs +124 -0
  30. package/dist/federation/filesystem-source-provider.d.cts +7 -0
  31. package/dist/federation/filesystem-source-provider.d.ts +7 -0
  32. package/dist/federation/filesystem-source-provider.js +6 -0
  33. package/dist/federation/source-provider.cjs +265 -0
  34. package/dist/federation/source-provider.d.cts +11 -0
  35. package/dist/federation/source-provider.d.ts +11 -0
  36. package/dist/federation/source-provider.js +8 -0
  37. package/dist/generate.cjs +1 -1
  38. package/dist/generate.js +3 -3
  39. package/dist/utils/cli-logger.cjs +1 -1
  40. package/dist/utils/cli-logger.js +2 -2
  41. package/package.json +3 -3
@@ -29,10 +29,10 @@ var importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
29
29
  // src/eventcatalog.ts
30
30
  var import_commander = require("commander");
31
31
  var import_node_child_process2 = require("child_process");
32
- var import_node_path14 = require("path");
32
+ var import_node_path16 = require("path");
33
33
  var import_node_http = __toESM(require("http"), 1);
34
34
  var import_fs3 = __toESM(require("fs"), 1);
35
- var import_node_path15 = __toESM(require("path"), 1);
35
+ var import_node_path17 = __toESM(require("path"), 1);
36
36
  var import_node_url = require("url");
37
37
 
38
38
  // src/generate.js
@@ -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.7.2";
147
+ var version = "4.7.4";
148
148
 
149
149
  // src/constants.ts
150
150
  var VERSION = version;
@@ -632,29 +632,82 @@ function retryEPERM(fn) {
632
632
 
633
633
  // src/catalog-to-astro-content-directory.js
634
634
  var import_glob2 = require("glob");
635
- var path4 = __toESM(require("path"), 1);
635
+ var path5 = __toESM(require("path"), 1);
636
636
  var import_fs = __toESM(require("fs"), 1);
637
637
  var import_url2 = require("url");
638
638
  var import_node_os2 = __toESM(require("os"), 1);
639
+
640
+ // src/custom-components.js
641
+ var import_promises2 = __toESM(require("fs/promises"), 1);
642
+ var import_node_path4 = __toESM(require("path"), 1);
643
+ var isCustomComponentPath = (projectDirectory, filePath) => {
644
+ const [rootDirectory, childDirectory] = import_node_path4.default.relative(projectDirectory, filePath).split(import_node_path4.default.sep);
645
+ return rootDirectory === "components" || rootDirectory === "federated" && childDirectory === "components";
646
+ };
647
+ var readDirectory = async (directory) => {
648
+ try {
649
+ return await import_promises2.default.readdir(directory, { withFileTypes: true });
650
+ } catch (error) {
651
+ if (error.code === "ENOENT") return [];
652
+ throw error;
653
+ }
654
+ };
655
+ var mergeDirectory = async (sourceDirectory, destinationDirectory) => {
656
+ for (const entry of await readDirectory(sourceDirectory)) {
657
+ const sourcePath = import_node_path4.default.join(sourceDirectory, entry.name);
658
+ const destinationPath = import_node_path4.default.join(destinationDirectory, entry.name);
659
+ if (entry.isDirectory()) {
660
+ const destinationEntry = await import_promises2.default.stat(destinationPath).catch((error) => {
661
+ if (error.code === "ENOENT") return void 0;
662
+ throw error;
663
+ });
664
+ if (destinationEntry && !destinationEntry.isDirectory()) {
665
+ await import_promises2.default.rm(destinationPath, { recursive: true, force: true });
666
+ }
667
+ await import_promises2.default.mkdir(destinationPath, { recursive: true });
668
+ await mergeDirectory(sourcePath, destinationPath);
669
+ continue;
670
+ }
671
+ await import_promises2.default.rm(destinationPath, { recursive: true, force: true });
672
+ await import_promises2.default.copyFile(sourcePath, destinationPath);
673
+ }
674
+ };
675
+ var syncCustomComponents = async (projectDirectory, catalogDirectory) => {
676
+ const destinationDirectory = import_node_path4.default.join(catalogDirectory, "src", "custom-defined-components");
677
+ const destinationParent = import_node_path4.default.dirname(destinationDirectory);
678
+ await import_promises2.default.mkdir(destinationParent, { recursive: true });
679
+ const stagingDirectory = await import_promises2.default.mkdtemp(import_node_path4.default.join(destinationParent, ".custom-defined-components.staging-"));
680
+ try {
681
+ await mergeDirectory(import_node_path4.default.join(projectDirectory, "federated", "components"), stagingDirectory);
682
+ await mergeDirectory(import_node_path4.default.join(projectDirectory, "components"), stagingDirectory);
683
+ await import_promises2.default.rm(destinationDirectory, { recursive: true, force: true });
684
+ await import_promises2.default.rename(stagingDirectory, destinationDirectory);
685
+ } finally {
686
+ await import_promises2.default.rm(stagingDirectory, { recursive: true, force: true });
687
+ }
688
+ };
689
+
690
+ // src/catalog-to-astro-content-directory.js
639
691
  var __filename2 = (0, import_url2.fileURLToPath)(importMetaUrl);
640
- var rootPkg = path4.resolve(path4.dirname(__filename2), "../");
692
+ var rootPkg = path5.resolve(path5.dirname(__filename2), "../");
641
693
  var copyFiles = async (source, target) => {
642
- const files = await (0, import_glob2.glob)(path4.join(source, "**"), {
694
+ const files = await (0, import_glob2.glob)(path5.join(source, "**"), {
643
695
  nodir: true,
644
696
  windowsPathsNoEscape: import_node_os2.default.platform() == "win32",
645
697
  ignore: ["node_modules/**", "**/dist/**", "**/teams", "**/users", "**/*.mdx", "**/*.md", "**/package.json", "**/Dockerfile"]
646
698
  });
647
- const snippets = await (0, import_glob2.glob)(path4.join(source, "snippets/**/*.mdx"), {
699
+ const snippets = await (0, import_glob2.glob)(path5.join(source, "snippets/**/*.mdx"), {
648
700
  nodir: true,
649
701
  windowsPathsNoEscape: import_node_os2.default.platform() == "win32"
650
702
  });
651
703
  if (snippets.length > 0) {
652
704
  files.push(...snippets);
653
705
  }
654
- if (import_fs.default.existsSync(path4.join(source, ".env"))) {
655
- files.push(path4.join(source, ".env"));
706
+ if (import_fs.default.existsSync(path5.join(source, ".env"))) {
707
+ files.push(path5.join(source, ".env"));
656
708
  }
657
709
  for (const file of files) {
710
+ if (isCustomComponentPath(source, file)) continue;
658
711
  mapCatalogToAstro({
659
712
  filePath: file,
660
713
  astroDir: target,
@@ -666,9 +719,9 @@ var copyFiles = async (source, target) => {
666
719
  }
667
720
  };
668
721
  var clearCustomPages = async (target) => {
669
- const customPagesDir = path4.join(target, "src", "custom-pages");
722
+ const customPagesDir = path5.join(target, "src", "custom-pages");
670
723
  if (import_fs.default.existsSync(customPagesDir)) import_fs.default.rmSync(customPagesDir, { recursive: true });
671
- const staleCodeFiles = await (0, import_glob2.glob)(path4.join(target, "public", "generated", "pages", "**/*.{astro,ts,js,mjs}"), {
724
+ const staleCodeFiles = await (0, import_glob2.glob)(path5.join(target, "public", "generated", "pages", "**/*.{astro,ts,js,mjs}"), {
672
725
  nodir: true,
673
726
  windowsPathsNoEscape: import_node_os2.default.platform() == "win32"
674
727
  });
@@ -677,8 +730,8 @@ var clearCustomPages = async (target) => {
677
730
  }
678
731
  };
679
732
  var removeGeneratedLikeC4Sources = async (target) => {
680
- const generatedDir = path4.join(target, "public", "generated");
681
- const files = await (0, import_glob2.glob)(path4.join(generatedDir, "**/*.{c4,likec4}"), {
733
+ const generatedDir = path5.join(target, "public", "generated");
734
+ const files = await (0, import_glob2.glob)(path5.join(generatedDir, "**/*.{c4,likec4}"), {
682
735
  nodir: true,
683
736
  windowsPathsNoEscape: import_node_os2.default.platform() == "win32"
684
737
  });
@@ -687,20 +740,21 @@ var removeGeneratedLikeC4Sources = async (target) => {
687
740
  }
688
741
  };
689
742
  var catalogToAstro = async (source, astroDir) => {
690
- const astroContentDir = path4.join(astroDir, "src/content/");
743
+ const astroContentDir = path5.join(astroDir, "src/content/");
691
744
  if (import_fs.default.existsSync(astroContentDir)) import_fs.default.rmSync(astroContentDir, { recursive: true });
692
745
  import_fs.default.mkdirSync(astroContentDir);
693
746
  await verifyRequiredFieldsAreInCatalogConfigFile(source);
694
- if (!import_fs.default.existsSync(path4.join(source, "eventcatalog.styles.css"))) {
695
- import_fs.default.writeFileSync(path4.join(source, "eventcatalog.styles.css"), "");
747
+ if (!import_fs.default.existsSync(path5.join(source, "eventcatalog.styles.css"))) {
748
+ import_fs.default.writeFileSync(path5.join(source, "eventcatalog.styles.css"), "");
696
749
  }
697
750
  await clearCustomPages(astroDir);
698
751
  await removeGeneratedLikeC4Sources(astroDir);
752
+ await syncCustomComponents(source, astroDir);
699
753
  await copyFiles(source, astroDir);
700
754
  };
701
755
 
702
756
  // src/resolve-catalog-dependencies.js
703
- var import_node_path4 = __toESM(require("path"), 1);
757
+ var import_node_path5 = __toESM(require("path"), 1);
704
758
  var import_node_fs3 = __toESM(require("fs"), 1);
705
759
  var import_gray_matter2 = __toESM(require("gray-matter"), 1);
706
760
  var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
@@ -709,7 +763,7 @@ var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
709
763
  if (!dependencies) {
710
764
  return;
711
765
  }
712
- const dependenciesDir = import_node_path4.default.join(catalogDir, "dependencies");
766
+ const dependenciesDir = import_node_path5.default.join(catalogDir, "dependencies");
713
767
  if (import_node_fs3.default.existsSync(dependenciesDir)) {
714
768
  import_node_fs3.default.rmSync(dependenciesDir, { recursive: true, force: true });
715
769
  }
@@ -733,8 +787,8 @@ var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
733
787
  },
734
788
  frontmatter
735
789
  );
736
- const resourceFile = import_node_path4.default.join(dependenciesDir, resourceType, dependency.id, `index.md`);
737
- import_node_fs3.default.mkdirSync(import_node_path4.default.dirname(resourceFile), { recursive: true });
790
+ const resourceFile = import_node_path5.default.join(dependenciesDir, resourceType, dependency.id, `index.md`);
791
+ import_node_fs3.default.mkdirSync(import_node_path5.default.dirname(resourceFile), { recursive: true });
738
792
  import_node_fs3.default.writeFileSync(resourceFile, markdown);
739
793
  }
740
794
  }
@@ -745,7 +799,7 @@ var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
745
799
  var import_boxen = __toESM(require("boxen"), 1);
746
800
 
747
801
  // src/features.ts
748
- var import_node_path5 = require("path");
802
+ var import_node_path6 = require("path");
749
803
  var import_node_fs4 = __toESM(require("fs"), 1);
750
804
  var getProjectOutDir = async () => {
751
805
  const config = await getEventCatalogConfigFile(process.env.PROJECT_DIR || "");
@@ -761,7 +815,7 @@ var isIndexedSearchEnabled = async () => {
761
815
  };
762
816
  var isAuthEnabled = async () => {
763
817
  const directory = process.env.PROJECT_DIR || process.cwd();
764
- const hasAuthConfig = import_node_fs4.default.existsSync((0, import_node_path5.join)(directory, "eventcatalog.auth.js"));
818
+ const hasAuthConfig = import_node_fs4.default.existsSync((0, import_node_path6.join)(directory, "eventcatalog.auth.js"));
765
819
  return hasAuthConfig;
766
820
  };
767
821
 
@@ -774,7 +828,7 @@ var import_node_fs5 = __toESM(require("fs"), 1);
774
828
  var import_glob3 = require("glob");
775
829
  var import_node_os3 = __toESM(require("os"), 1);
776
830
  var import_gray_matter3 = __toESM(require("gray-matter"), 1);
777
- var import_node_path6 = __toESM(require("path"), 1);
831
+ var import_node_path7 = __toESM(require("path"), 1);
778
832
  var DISABLE_CHANNEL_MIGRATION_ENV = "EVENTCATALOG_DISABLE_CHANNEL_MIGRATION";
779
833
  var isChannelMigrationDisabled = () => {
780
834
  return ["true", "1", "yes"].includes((process.env[DISABLE_CHANNEL_MIGRATION_ENV] ?? "").toLowerCase());
@@ -783,7 +837,7 @@ var message_channels_to_service_channels_default = async (dir2) => {
783
837
  if (isChannelMigrationDisabled()) {
784
838
  return { status: "skipped", message: `Channel migration disabled by ${DISABLE_CHANNEL_MIGRATION_ENV}` };
785
839
  }
786
- const PROJECT_DIR = import_node_path6.default.join(dir2 || process.env.PROJECT_DIR);
840
+ const PROJECT_DIR = import_node_path7.default.join(dir2 || process.env.PROJECT_DIR);
787
841
  const messages = await (0, import_glob3.glob)(
788
842
  [
789
843
  "**/events/*/index.mdx",
@@ -890,7 +944,7 @@ var runMigrations = async (dir2) => {
890
944
  };
891
945
 
892
946
  // eventcatalog/src/enterprise/fields/field-indexer.ts
893
- var import_node_path7 = __toESM(require("path"), 1);
947
+ var import_node_path8 = __toESM(require("path"), 1);
894
948
  var import_node_fs7 = __toESM(require("fs"), 1);
895
949
 
896
950
  // eventcatalog/src/enterprise/fields/fields-db.ts
@@ -1256,22 +1310,22 @@ function getAvroTypeName(type) {
1256
1310
  function walkAvroRecord(schema, prefix, fields) {
1257
1311
  if (!schema.fields || !Array.isArray(schema.fields)) return;
1258
1312
  for (const field of schema.fields) {
1259
- const path15 = prefix ? `${prefix}.${field.name}` : field.name;
1313
+ const path17 = prefix ? `${prefix}.${field.name}` : field.name;
1260
1314
  const isOptional = Array.isArray(field.type) && field.type.includes("null");
1261
1315
  const typeName = getAvroTypeName(field.type);
1262
1316
  fields.push({
1263
- path: path15,
1317
+ path: path17,
1264
1318
  type: typeName,
1265
1319
  description: field.doc || "",
1266
1320
  required: !isOptional
1267
1321
  });
1268
1322
  const innerType = Array.isArray(field.type) ? field.type.find((t) => typeof t === "object" && t.type === "record") : typeof field.type === "object" && field.type.type === "record" ? field.type : null;
1269
1323
  if (innerType) {
1270
- walkAvroRecord(innerType, path15, fields);
1324
+ walkAvroRecord(innerType, path17, fields);
1271
1325
  }
1272
1326
  const arrayType = Array.isArray(field.type) ? field.type.find((t) => typeof t === "object" && t.type === "array") : typeof field.type === "object" && field.type.type === "array" ? field.type : null;
1273
1327
  if (arrayType && typeof arrayType.items === "object" && arrayType.items.type === "record") {
1274
- walkAvroRecord(arrayType.items, `${path15}[]`, fields);
1328
+ walkAvroRecord(arrayType.items, `${path17}[]`, fields);
1275
1329
  }
1276
1330
  }
1277
1331
  }
@@ -1302,32 +1356,32 @@ function walkJsonSchema(node, prefix, requiredList, rootSchema, fields) {
1302
1356
  }
1303
1357
  if (!node.properties) return;
1304
1358
  for (const [name, prop] of Object.entries(node.properties)) {
1305
- const path15 = prefix ? `${prefix}.${name}` : name;
1359
+ const path17 = prefix ? `${prefix}.${name}` : name;
1306
1360
  const isRequired = requiredList.includes(name);
1307
1361
  if (prop.$ref) {
1308
1362
  const resolved = resolveLocalRef(prop.$ref, rootSchema);
1309
1363
  if (resolved) {
1310
1364
  const rawRefType = resolved.type || "object";
1311
1365
  const type2 = Array.isArray(rawRefType) ? [...rawRefType].sort().join(" | ") : rawRefType;
1312
- fields.push({ path: path15, type: type2, description: resolved.description || "", required: isRequired });
1366
+ fields.push({ path: path17, type: type2, description: resolved.description || "", required: isRequired });
1313
1367
  if (resolved.properties) {
1314
- walkJsonSchema(resolved, path15, resolved.required || [], rootSchema, fields);
1368
+ walkJsonSchema(resolved, path17, resolved.required || [], rootSchema, fields);
1315
1369
  }
1316
1370
  } else {
1317
- fields.push({ path: path15, type: "$ref", description: "", required: isRequired });
1371
+ fields.push({ path: path17, type: "$ref", description: "", required: isRequired });
1318
1372
  }
1319
1373
  continue;
1320
1374
  }
1321
1375
  const rawType = prop.type || (prop.enum ? "enum" : prop.$ref ? "$ref" : "object");
1322
1376
  const typeList = Array.isArray(rawType) ? rawType : [rawType];
1323
1377
  const type = Array.isArray(rawType) ? [...rawType].sort().join(" | ") : rawType;
1324
- fields.push({ path: path15, type, description: prop.description || "", required: isRequired });
1378
+ fields.push({ path: path17, type, description: prop.description || "", required: isRequired });
1325
1379
  if (typeList.includes("object") && prop.properties) {
1326
- walkJsonSchema(prop, path15, prop.required || [], rootSchema, fields);
1380
+ walkJsonSchema(prop, path17, prop.required || [], rootSchema, fields);
1327
1381
  }
1328
1382
  if (typeList.includes("array") && prop.items) {
1329
1383
  if (prop.items.type === "object" && prop.items.properties) {
1330
- walkJsonSchema(prop.items, `${path15}[]`, prop.items.required || [], rootSchema, fields);
1384
+ walkJsonSchema(prop.items, `${path17}[]`, prop.items.required || [], rootSchema, fields);
1331
1385
  }
1332
1386
  }
1333
1387
  }
@@ -1345,7 +1399,7 @@ function resolveLocalRef(ref, rootSchema) {
1345
1399
 
1346
1400
  // eventcatalog/src/enterprise/fields/field-indexer.ts
1347
1401
  function detectFormat(fileName) {
1348
- const ext = import_node_path7.default.extname(fileName).toLowerCase();
1402
+ const ext = import_node_path8.default.extname(fileName).toLowerCase();
1349
1403
  if (ext === ".proto") return "proto";
1350
1404
  if (ext === ".avro" || ext === ".avsc") return "avro";
1351
1405
  return "json-schema";
@@ -1353,8 +1407,8 @@ function detectFormat(fileName) {
1353
1407
  async function buildFieldsIndex(catalogDir, outputDir) {
1354
1408
  const sdkModule = await import("@eventcatalog/sdk");
1355
1409
  const sdk = sdkModule.default(catalogDir);
1356
- const dbDir = import_node_path7.default.join(outputDir || catalogDir, ".eventcatalog");
1357
- const dbPath = import_node_path7.default.join(dbDir, "fields.db");
1410
+ const dbDir = import_node_path8.default.join(outputDir || catalogDir, ".eventcatalog");
1411
+ const dbPath = import_node_path8.default.join(dbDir, "fields.db");
1358
1412
  if (!import_node_fs7.default.existsSync(dbDir)) {
1359
1413
  import_node_fs7.default.mkdirSync(dbDir, { recursive: true });
1360
1414
  }
@@ -1439,8 +1493,8 @@ async function buildFieldsIndex(catalogDir, outputDir) {
1439
1493
  }
1440
1494
 
1441
1495
  // src/search-indexer.ts
1442
- var import_promises2 = __toESM(require("fs/promises"), 1);
1443
- var import_node_path8 = __toESM(require("path"), 1);
1496
+ var import_promises3 = __toESM(require("fs/promises"), 1);
1497
+ var import_node_path9 = __toESM(require("path"), 1);
1444
1498
  var import_glob4 = require("glob");
1445
1499
  var import_gray_matter4 = __toESM(require("gray-matter"), 1);
1446
1500
  var RESOURCE_COLLECTIONS = {
@@ -1499,9 +1553,9 @@ var markdownToSearchText = (content) => {
1499
1553
  };
1500
1554
  var inferDocIdFromFile = (relativePath, frontmatterId) => {
1501
1555
  if (frontmatterId) return frontmatterId;
1502
- const fileName = import_node_path8.default.posix.basename(removeExtension(relativePath));
1556
+ const fileName = import_node_path9.default.posix.basename(removeExtension(relativePath));
1503
1557
  if (fileName.toLowerCase() === "index") {
1504
- return import_node_path8.default.posix.basename(import_node_path8.default.posix.dirname(relativePath));
1558
+ return import_node_path9.default.posix.basename(import_node_path9.default.posix.dirname(relativePath));
1505
1559
  }
1506
1560
  return stripNumericPrefix(fileName);
1507
1561
  };
@@ -1519,10 +1573,10 @@ var findResourceSegment = (segments) => {
1519
1573
  return match;
1520
1574
  };
1521
1575
  var readResourceFrontmatter = async (projectDir, resourcePath) => {
1522
- const candidates = [import_node_path8.default.join(projectDir, resourcePath, "index.mdx"), import_node_path8.default.join(projectDir, resourcePath, "index.md")];
1576
+ const candidates = [import_node_path9.default.join(projectDir, resourcePath, "index.mdx"), import_node_path9.default.join(projectDir, resourcePath, "index.md")];
1523
1577
  for (const candidate of candidates) {
1524
1578
  try {
1525
- const file = await import_promises2.default.readFile(candidate, "utf8");
1579
+ const file = await import_promises3.default.readFile(candidate, "utf8");
1526
1580
  return (0, import_gray_matter4.default)(file).data;
1527
1581
  } catch {
1528
1582
  }
@@ -1544,7 +1598,7 @@ var deriveRecordFromPath = async ({
1544
1598
  }
1545
1599
  if (segments[0] === "docs") {
1546
1600
  const customPath = normalizeUrlPath(removeExtension(segments.slice(1).join("/")));
1547
- const title = data.title || data.label || import_node_path8.default.posix.basename(customPath) || "Custom docs";
1601
+ const title = data.title || data.label || import_node_path9.default.posix.basename(customPath) || "Custom docs";
1548
1602
  return {
1549
1603
  url: buildUrl(`/docs/custom/${customPath}`, config),
1550
1604
  title,
@@ -1660,9 +1714,9 @@ var collectSearchRecords = async ({
1660
1714
  });
1661
1715
  const records = await Promise.all(
1662
1716
  files.map(async (file) => {
1663
- const raw = await import_promises2.default.readFile(file, "utf8");
1717
+ const raw = await import_promises3.default.readFile(file, "utf8");
1664
1718
  const parsed = (0, import_gray_matter4.default)(raw);
1665
- const relativePath = normalizePath(import_node_path8.default.relative(projectDir, file));
1719
+ const relativePath = normalizePath(import_node_path9.default.relative(projectDir, file));
1666
1720
  const baseRecord = await deriveRecordFromPath({
1667
1721
  projectDir,
1668
1722
  relativePath,
@@ -1709,7 +1763,7 @@ var getSearchOutputPath = ({
1709
1763
  if (searchOutputPath) {
1710
1764
  return searchOutputPath;
1711
1765
  }
1712
- return import_node_path8.default.join(outDir, isServer ? "client" : "", "pagefind");
1766
+ return import_node_path9.default.join(outDir, isServer ? "client" : "", "pagefind");
1713
1767
  };
1714
1768
  var buildSearchIndex = async ({ projectDir, outDir, config, isServer, searchOutputPath }) => {
1715
1769
  const records = await collectSearchRecords({ projectDir, config });
@@ -1745,7 +1799,7 @@ var buildSearchIndex = async ({ projectDir, outDir, config, isServer, searchOutp
1745
1799
  }
1746
1800
  }
1747
1801
  const outputPath = getSearchOutputPath({ outDir, isServer, searchOutputPath });
1748
- await import_promises2.default.rm(outputPath, { recursive: true, force: true });
1802
+ await import_promises3.default.rm(outputPath, { recursive: true, force: true });
1749
1803
  const writeResult = await index.writeFiles({ outputPath });
1750
1804
  if (writeResult.errors?.length) {
1751
1805
  errors.push(...writeResult.errors.map((error) => error.message || String(error)));
@@ -1764,7 +1818,7 @@ ${errors.join("\n")}`);
1764
1818
 
1765
1819
  // src/core-node-modules.ts
1766
1820
  var import_fs2 = __toESM(require("fs"), 1);
1767
- var import_node_path9 = __toESM(require("path"), 1);
1821
+ var import_node_path10 = __toESM(require("path"), 1);
1768
1822
  var isDirectory = (directory) => {
1769
1823
  try {
1770
1824
  return import_fs2.default.statSync(directory).isDirectory();
@@ -1774,7 +1828,7 @@ var isDirectory = (directory) => {
1774
1828
  };
1775
1829
  var hasAstroDependency = (nodeModulesDirectory) => {
1776
1830
  const astroBin = process.platform === "win32" ? "astro.cmd" : "astro";
1777
- return import_fs2.default.existsSync(import_node_path9.default.join(nodeModulesDirectory, "astro", "package.json")) || import_fs2.default.existsSync(import_node_path9.default.join(nodeModulesDirectory, ".bin", astroBin));
1831
+ return import_fs2.default.existsSync(import_node_path10.default.join(nodeModulesDirectory, "astro", "package.json")) || import_fs2.default.existsSync(import_node_path10.default.join(nodeModulesDirectory, ".bin", astroBin));
1778
1832
  };
1779
1833
  var isSymbolicLink = (targetPath) => {
1780
1834
  try {
@@ -1794,20 +1848,20 @@ var resolveInstalledCoreNodeModules = (currentDir2) => {
1794
1848
  const candidates = [];
1795
1849
  const seen = /* @__PURE__ */ new Set();
1796
1850
  const addCandidate = (candidate) => {
1797
- const resolvedCandidate = import_node_path9.default.resolve(candidate);
1851
+ const resolvedCandidate = import_node_path10.default.resolve(candidate);
1798
1852
  if (!seen.has(resolvedCandidate)) {
1799
1853
  candidates.push(resolvedCandidate);
1800
1854
  seen.add(resolvedCandidate);
1801
1855
  }
1802
1856
  };
1803
- addCandidate(import_node_path9.default.resolve(currentDir2, "..", "node_modules"));
1804
- let directory = import_node_path9.default.resolve(currentDir2);
1857
+ addCandidate(import_node_path10.default.resolve(currentDir2, "..", "node_modules"));
1858
+ let directory = import_node_path10.default.resolve(currentDir2);
1805
1859
  while (true) {
1806
- if (import_node_path9.default.basename(directory) === "node_modules") {
1860
+ if (import_node_path10.default.basename(directory) === "node_modules") {
1807
1861
  addCandidate(directory);
1808
1862
  }
1809
- addCandidate(import_node_path9.default.join(directory, "node_modules"));
1810
- const parentDirectory = import_node_path9.default.dirname(directory);
1863
+ addCandidate(import_node_path10.default.join(directory, "node_modules"));
1864
+ const parentDirectory = import_node_path10.default.dirname(directory);
1811
1865
  if (parentDirectory === directory) {
1812
1866
  break;
1813
1867
  }
@@ -1846,28 +1900,28 @@ var createAstroDevLineFilter = () => {
1846
1900
  };
1847
1901
 
1848
1902
  // src/federation/federate.ts
1849
- var import_node_crypto3 = require("crypto");
1850
- var import_promises6 = __toESM(require("fs/promises"), 1);
1851
- var import_node_path13 = __toESM(require("path"), 1);
1852
- var import_sdk2 = __toESM(require("@eventcatalog/sdk"), 1);
1903
+ var import_node_crypto4 = require("crypto");
1904
+ var import_promises8 = __toESM(require("fs/promises"), 1);
1905
+ var import_node_path15 = __toESM(require("path"), 1);
1906
+ var import_sdk3 = __toESM(require("@eventcatalog/sdk"), 1);
1853
1907
 
1854
1908
  // src/federation/content-cache.ts
1855
1909
  var import_node_crypto = require("crypto");
1856
- var import_promises3 = __toESM(require("fs/promises"), 1);
1857
- var import_node_path10 = __toESM(require("path"), 1);
1910
+ var import_promises4 = __toESM(require("fs/promises"), 1);
1911
+ var import_node_path11 = __toESM(require("path"), 1);
1858
1912
  var getContentHash = (content) => `sha256:${(0, import_node_crypto.createHash)("sha256").update(content).digest("hex")}`;
1859
1913
  var isContentHash = (key) => /^sha256:[a-f0-9]{64}$/i.test(key);
1860
1914
  var createFederationContentCache = (projectDirectory, options = {}) => {
1861
- const cacheDirectory = import_node_path10.default.join(projectDirectory, ".eventcatalog-cache", "federation", "content");
1862
- const getCachePath = (key) => import_node_path10.default.join(cacheDirectory, encodeURIComponent(key));
1915
+ const cacheDirectory = import_node_path11.default.join(projectDirectory, ".eventcatalog-cache", "federation", "content");
1916
+ const getCachePath = (key) => import_node_path11.default.join(cacheDirectory, encodeURIComponent(key));
1863
1917
  return {
1864
1918
  async get(key) {
1865
1919
  if (options.read === false || !isContentHash(key)) return void 0;
1866
1920
  const cachePath = getCachePath(key);
1867
1921
  try {
1868
- const content = await import_promises3.default.readFile(cachePath);
1922
+ const content = await import_promises4.default.readFile(cachePath);
1869
1923
  if (getContentHash(content) !== key) {
1870
- await import_promises3.default.rm(cachePath, { force: true });
1924
+ await import_promises4.default.rm(cachePath, { force: true });
1871
1925
  return void 0;
1872
1926
  }
1873
1927
  options.onHit?.(key);
@@ -1879,139 +1933,19 @@ var createFederationContentCache = (projectDirectory, options = {}) => {
1879
1933
  },
1880
1934
  async set(key, content) {
1881
1935
  if (!isContentHash(key) || getContentHash(content) !== key) return;
1882
- await import_promises3.default.mkdir(cacheDirectory, { recursive: true });
1936
+ await import_promises4.default.mkdir(cacheDirectory, { recursive: true });
1883
1937
  const cachePath = getCachePath(key);
1884
1938
  const temporaryPath = `${cachePath}.tmp-${process.pid}-${(0, import_node_crypto.randomUUID)()}`;
1885
1939
  try {
1886
- await import_promises3.default.writeFile(temporaryPath, content);
1887
- await import_promises3.default.rename(temporaryPath, cachePath);
1940
+ await import_promises4.default.writeFile(temporaryPath, content);
1941
+ await import_promises4.default.rename(temporaryPath, cachePath);
1888
1942
  } finally {
1889
- await import_promises3.default.rm(temporaryPath, { force: true });
1943
+ await import_promises4.default.rm(temporaryPath, { force: true });
1890
1944
  }
1891
1945
  }
1892
1946
  };
1893
1947
  };
1894
1948
 
1895
- // src/federation/github-source-provider.ts
1896
- var import_node_child_process = require("child_process");
1897
- var import_promises4 = __toESM(require("fs/promises"), 1);
1898
- var import_node_os4 = __toESM(require("os"), 1);
1899
- var import_node_path11 = __toESM(require("path"), 1);
1900
- var import_node_util = require("util");
1901
- var import_sdk = __toESM(require("@eventcatalog/sdk"), 1);
1902
- var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
1903
- var parseGitHubSource = (source) => {
1904
- const match = /^github:([^/]+)\/(.+)$/.exec(source.source);
1905
- if (!match) throw new Error(`Unsupported federation source "${source.source}". Expected github:owner/repository.`);
1906
- return { owner: match[1], repository: match[2] };
1907
- };
1908
- var assertSafeCatalogPath = (source) => {
1909
- const catalogPath = source.path ?? ".";
1910
- const normalized = import_node_path11.default.posix.normalize(catalogPath.replaceAll("\\", "/"));
1911
- if (catalogPath.includes("\\") || import_node_path11.default.posix.isAbsolute(normalized) || normalized === ".." || normalized.startsWith("../")) {
1912
- throw new Error(`Catalog path "${catalogPath}" escapes source "${source.id}"`);
1913
- }
1914
- };
1915
- var encodePath = (value) => value.split("/").filter(Boolean).map(encodeURIComponent).join("/");
1916
- var rawUrl = (source, ref, filePath) => {
1917
- const { owner, repository } = parseGitHubSource(source);
1918
- return `https://raw.githubusercontent.com/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/${encodeURIComponent(
1919
- ref
1920
- )}/${encodePath(filePath)}`;
1921
- };
1922
- var contentsApiUrl = (source, ref, filePath) => {
1923
- const { owner, repository } = parseGitHubSource(source);
1924
- return `https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/contents/${encodePath(
1925
- filePath
1926
- )}?ref=${encodeURIComponent(ref)}`;
1927
- };
1928
- var fetchBytes = async (source, ref, filePath, fetcher, token) => {
1929
- const url = token ? contentsApiUrl(source, ref, filePath) : rawUrl(source, ref, filePath);
1930
- const response = token ? await fetcher(url, {
1931
- headers: {
1932
- Accept: "application/vnd.github.raw+json",
1933
- Authorization: `Bearer ${token}`,
1934
- "X-GitHub-Api-Version": "2026-03-10"
1935
- }
1936
- }) : await fetcher(url);
1937
- if (response.status === 404) return void 0;
1938
- if (!response.ok) throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
1939
- return Buffer.from(await response.arrayBuffer());
1940
- };
1941
- var getGitEnvironment = (token) => {
1942
- if (!token) return process.env;
1943
- const inheritedCount = Number.parseInt(process.env.GIT_CONFIG_COUNT ?? "0", 10);
1944
- const configIndex = Number.isInteger(inheritedCount) && inheritedCount >= 0 ? inheritedCount : 0;
1945
- return {
1946
- ...process.env,
1947
- GIT_CONFIG_COUNT: String(configIndex + 1),
1948
- [`GIT_CONFIG_KEY_${configIndex}`]: "http.https://github.com/.extraheader",
1949
- [`GIT_CONFIG_VALUE_${configIndex}`]: `AUTHORIZATION: basic ${Buffer.from(`x-access-token:${token}`).toString("base64")}`
1950
- };
1951
- };
1952
- var createCheckout = (executeFile, token) => async (source, ref, callback) => {
1953
- const { owner, repository } = parseGitHubSource(source);
1954
- const catalogPath = import_node_path11.default.posix.normalize(source.path ?? ".");
1955
- const directory = await import_promises4.default.mkdtemp(import_node_path11.default.join(import_node_os4.default.tmpdir(), "eventcatalog-federation-"));
1956
- const env = getGitEnvironment(token);
1957
- try {
1958
- const git = (args) => executeFile("git", args, { cwd: directory, env, encoding: "utf8" });
1959
- await git(["init", "--quiet"]);
1960
- await git(["remote", "add", "origin", `https://github.com/${owner}/${repository}.git`]);
1961
- if (catalogPath !== ".") {
1962
- await git(["sparse-checkout", "init", "--cone"]);
1963
- await git(["sparse-checkout", "set", catalogPath]);
1964
- }
1965
- await git(["fetch", "--quiet", "--depth", "1", "origin", ref]);
1966
- await git(["checkout", "--quiet", "--detach", "FETCH_HEAD"]);
1967
- return await callback(directory);
1968
- } finally {
1969
- await import_promises4.default.rm(directory, { recursive: true, force: true });
1970
- }
1971
- };
1972
- var generateIndex = async (source, ref, checkout, executeFile) => checkout(source, ref, async (directory) => {
1973
- const { stdout } = await executeFile("git", ["rev-parse", "HEAD"], { cwd: directory, encoding: "utf8" });
1974
- const commit = stdout.trim();
1975
- const catalogDirectory = import_node_path11.default.resolve(directory, source.path ?? ".");
1976
- const relativeCatalogDirectory = import_node_path11.default.relative(directory, catalogDirectory);
1977
- if (relativeCatalogDirectory.startsWith("..") || import_node_path11.default.isAbsolute(relativeCatalogDirectory)) {
1978
- throw new Error(`Catalog path "${source.path}" escapes source "${source.id}"`);
1979
- }
1980
- const index = await (0, import_sdk.default)(catalogDirectory).buildIndex({ source: source.id, commit });
1981
- return { bytes: Buffer.from(JSON.stringify(index)), index, commit, generated: true };
1982
- });
1983
- var fetchPublishedIndex = async (source, ref, fetcher, token) => {
1984
- const indexPath = import_node_path11.default.posix.join(source.path ?? ".", "catalog.index.json");
1985
- const bytes = await fetchBytes(source, ref, indexPath, fetcher, token);
1986
- if (!bytes) return void 0;
1987
- const index = (0, import_sdk.parseIndex)(JSON.parse(bytes.toString("utf8")));
1988
- if (index.source !== source.id) {
1989
- throw new Error(`Published index source "${index.source}" does not match configured id "${source.id}"`);
1990
- }
1991
- return { bytes, index, commit: index.commit, generated: false };
1992
- };
1993
- var createGitHubSourceProvider = (options = {}) => {
1994
- const fetcher = options.fetch ?? ((url, init) => fetch(url, init));
1995
- const executeFile = options.execFile ?? ((file, args, execOptions) => execFileAsync(file, args, execOptions));
1996
- const configuredToken = options.token ?? process.env.EVENTCATALOG_GITHUB_TOKEN ?? process.env.GITHUB_TOKEN;
1997
- const token = configuredToken?.trim() || void 0;
1998
- const checkout = options.checkout ?? createCheckout(executeFile, token);
1999
- return {
2000
- async resolve(source) {
2001
- assertSafeCatalogPath(source);
2002
- const ref = source.ref ?? "main";
2003
- return await fetchPublishedIndex(source, ref, fetcher, token) ?? generateIndex(source, ref, checkout, executeFile);
2004
- },
2005
- async fetchContent({ source, commit, path: artifactPath }) {
2006
- assertSafeCatalogPath(source);
2007
- const catalogPath = import_node_path11.default.posix.join(source.path ?? ".", artifactPath);
2008
- const content = await fetchBytes(source, commit, catalogPath, fetcher, token);
2009
- if (!content) throw new Error(`Federated artifact not found for "${source.id}": ${artifactPath}`);
2010
- return content;
2011
- }
2012
- };
2013
- };
2014
-
2015
1949
  // src/federation/public-assets.ts
2016
1950
  var import_node_crypto2 = require("crypto");
2017
1951
  var import_promises5 = __toESM(require("fs/promises"), 1);
@@ -2142,6 +2076,232 @@ var composePublicAssets = async ({
2142
2076
  return { files, copied, skipped, overwritten, removed };
2143
2077
  };
2144
2078
 
2079
+ // src/federation/filesystem-source-provider.ts
2080
+ var import_node_crypto3 = require("crypto");
2081
+ var import_promises6 = __toESM(require("fs/promises"), 1);
2082
+ var import_node_path13 = __toESM(require("path"), 1);
2083
+ var import_sdk = __toESM(require("@eventcatalog/sdk"), 1);
2084
+ var FILESYSTEM_SOURCE_PREFIX = "file:";
2085
+ var isWithinDirectory = (directory, target) => {
2086
+ const relativePath = import_node_path13.default.relative(directory, target);
2087
+ return relativePath === "" || !relativePath.startsWith(`..${import_node_path13.default.sep}`) && relativePath !== ".." && !import_node_path13.default.isAbsolute(relativePath);
2088
+ };
2089
+ var assertPortableRelativePath = (filePath, label, allowRoot = true) => {
2090
+ const portablePath = filePath.replaceAll("\\", "/");
2091
+ const normalizedPath = import_node_path13.default.posix.normalize(portablePath);
2092
+ const isUnsafe = filePath.includes("\\") || filePath.includes("\0") || import_node_path13.default.posix.isAbsolute(normalizedPath) || /^[a-zA-Z]:\//.test(normalizedPath) || normalizedPath === ".." || normalizedPath.startsWith("../") || !allowRoot && (normalizedPath === "." || normalizedPath === "");
2093
+ if (isUnsafe) throw new Error(`${label} "${filePath}" escapes its filesystem source`);
2094
+ return normalizedPath;
2095
+ };
2096
+ var getSourceRoot = (projectDirectory, source) => {
2097
+ if (!source.source.startsWith(FILESYSTEM_SOURCE_PREFIX)) {
2098
+ throw new Error(`Unsupported federation source "${source.source}". Expected file:path/to/catalog.`);
2099
+ }
2100
+ const locator = source.source.slice(FILESYSTEM_SOURCE_PREFIX.length);
2101
+ if (!locator.trim()) throw new Error(`Filesystem federation source "${source.id}" requires a path after "file:".`);
2102
+ return import_node_path13.default.resolve(projectDirectory, locator);
2103
+ };
2104
+ var getCatalogDirectory = async (projectDirectory, source) => {
2105
+ if (source.ref) throw new Error(`Filesystem federation source "${source.id}" does not support "ref".`);
2106
+ const sourceRoot = getSourceRoot(projectDirectory, source);
2107
+ const catalogPath = assertPortableRelativePath(source.path ?? ".", "Catalog path");
2108
+ const catalogDirectory = import_node_path13.default.resolve(sourceRoot, ...catalogPath.split("/"));
2109
+ if (!isWithinDirectory(sourceRoot, catalogDirectory)) {
2110
+ throw new Error(`Catalog path "${source.path}" escapes source "${source.id}"`);
2111
+ }
2112
+ try {
2113
+ const [realSourceRoot, realCatalogDirectory] = await Promise.all([import_promises6.default.realpath(sourceRoot), import_promises6.default.realpath(catalogDirectory)]);
2114
+ if (!isWithinDirectory(realSourceRoot, realCatalogDirectory)) {
2115
+ throw new Error(`Catalog path "${source.path}" escapes source "${source.id}"`);
2116
+ }
2117
+ if (!(await import_promises6.default.stat(realCatalogDirectory)).isDirectory()) {
2118
+ throw new Error(`Filesystem federation source "${source.id}" is not a directory: ${catalogDirectory}`);
2119
+ }
2120
+ return realCatalogDirectory;
2121
+ } catch (error) {
2122
+ if (error.code === "ENOENT") {
2123
+ throw new Error(`Filesystem federation source "${source.id}" does not exist: ${catalogDirectory}`, { cause: error });
2124
+ }
2125
+ throw error;
2126
+ }
2127
+ };
2128
+ var getArtifactPath = async (catalogDirectory, source, artifactPath) => {
2129
+ const normalizedPath = assertPortableRelativePath(artifactPath, "Federated artifact path", false);
2130
+ const filePath = import_node_path13.default.resolve(catalogDirectory, ...normalizedPath.split("/"));
2131
+ if (!isWithinDirectory(catalogDirectory, filePath)) {
2132
+ throw new Error(`Federated artifact path "${artifactPath}" escapes source "${source.id}"`);
2133
+ }
2134
+ try {
2135
+ const realFilePath = await import_promises6.default.realpath(filePath);
2136
+ if (!isWithinDirectory(catalogDirectory, realFilePath)) {
2137
+ throw new Error(`Federated artifact path "${artifactPath}" escapes source "${source.id}"`);
2138
+ }
2139
+ return realFilePath;
2140
+ } catch (error) {
2141
+ if (error.code === "ENOENT") {
2142
+ throw new Error(`Federated artifact not found for "${source.id}": ${artifactPath}`, { cause: error });
2143
+ }
2144
+ throw error;
2145
+ }
2146
+ };
2147
+ var createFileSystemSourceProvider = (projectDirectory) => ({
2148
+ async resolve(source) {
2149
+ const catalogDirectory = await getCatalogDirectory(projectDirectory, source);
2150
+ const localIndex = await (0, import_sdk.default)(catalogDirectory).buildIndex({
2151
+ source: source.id,
2152
+ commit: "local",
2153
+ includeFederated: false
2154
+ });
2155
+ const snapshot = (0, import_node_crypto3.createHash)("sha256").update(JSON.stringify(localIndex)).digest("hex").slice(0, 12);
2156
+ const index = { ...localIndex, commit: `local:${snapshot}` };
2157
+ const bytes = Buffer.from(JSON.stringify(index));
2158
+ return { bytes, index, commit: index.commit, generated: true };
2159
+ },
2160
+ async fetchContent({ source, path: artifactPath }) {
2161
+ const catalogDirectory = await getCatalogDirectory(projectDirectory, source);
2162
+ return import_promises6.default.readFile(await getArtifactPath(catalogDirectory, source, artifactPath));
2163
+ }
2164
+ });
2165
+
2166
+ // src/federation/github-source-provider.ts
2167
+ var import_node_child_process = require("child_process");
2168
+ var import_promises7 = __toESM(require("fs/promises"), 1);
2169
+ var import_node_os4 = __toESM(require("os"), 1);
2170
+ var import_node_path14 = __toESM(require("path"), 1);
2171
+ var import_node_util = require("util");
2172
+ var import_sdk2 = __toESM(require("@eventcatalog/sdk"), 1);
2173
+ var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
2174
+ var parseGitHubSource = (source) => {
2175
+ const match = /^github:([^/]+)\/(.+)$/.exec(source.source);
2176
+ if (!match) throw new Error(`Unsupported federation source "${source.source}". Expected github:owner/repository.`);
2177
+ return { owner: match[1], repository: match[2] };
2178
+ };
2179
+ var assertSafeCatalogPath = (source) => {
2180
+ const catalogPath = source.path ?? ".";
2181
+ const normalized = import_node_path14.default.posix.normalize(catalogPath.replaceAll("\\", "/"));
2182
+ if (catalogPath.includes("\\") || import_node_path14.default.posix.isAbsolute(normalized) || normalized === ".." || normalized.startsWith("../")) {
2183
+ throw new Error(`Catalog path "${catalogPath}" escapes source "${source.id}"`);
2184
+ }
2185
+ };
2186
+ var encodePath = (value) => value.split("/").filter(Boolean).map(encodeURIComponent).join("/");
2187
+ var rawUrl = (source, ref, filePath) => {
2188
+ const { owner, repository } = parseGitHubSource(source);
2189
+ return `https://raw.githubusercontent.com/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/${encodeURIComponent(
2190
+ ref
2191
+ )}/${encodePath(filePath)}`;
2192
+ };
2193
+ var contentsApiUrl = (source, ref, filePath) => {
2194
+ const { owner, repository } = parseGitHubSource(source);
2195
+ return `https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/contents/${encodePath(
2196
+ filePath
2197
+ )}?ref=${encodeURIComponent(ref)}`;
2198
+ };
2199
+ var fetchBytes = async (source, ref, filePath, fetcher, token) => {
2200
+ const url = token ? contentsApiUrl(source, ref, filePath) : rawUrl(source, ref, filePath);
2201
+ const response = token ? await fetcher(url, {
2202
+ headers: {
2203
+ Accept: "application/vnd.github.raw+json",
2204
+ Authorization: `Bearer ${token}`,
2205
+ "X-GitHub-Api-Version": "2026-03-10"
2206
+ }
2207
+ }) : await fetcher(url);
2208
+ if (response.status === 404) return void 0;
2209
+ if (!response.ok) throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
2210
+ return Buffer.from(await response.arrayBuffer());
2211
+ };
2212
+ var getGitEnvironment = (token) => {
2213
+ if (!token) return process.env;
2214
+ const inheritedCount = Number.parseInt(process.env.GIT_CONFIG_COUNT ?? "0", 10);
2215
+ const configIndex = Number.isInteger(inheritedCount) && inheritedCount >= 0 ? inheritedCount : 0;
2216
+ return {
2217
+ ...process.env,
2218
+ GIT_CONFIG_COUNT: String(configIndex + 1),
2219
+ [`GIT_CONFIG_KEY_${configIndex}`]: "http.https://github.com/.extraheader",
2220
+ [`GIT_CONFIG_VALUE_${configIndex}`]: `AUTHORIZATION: basic ${Buffer.from(`x-access-token:${token}`).toString("base64")}`
2221
+ };
2222
+ };
2223
+ var createCheckout = (executeFile, token) => async (source, ref, callback) => {
2224
+ const { owner, repository } = parseGitHubSource(source);
2225
+ const catalogPath = import_node_path14.default.posix.normalize(source.path ?? ".");
2226
+ const directory = await import_promises7.default.mkdtemp(import_node_path14.default.join(import_node_os4.default.tmpdir(), "eventcatalog-federation-"));
2227
+ const env = getGitEnvironment(token);
2228
+ try {
2229
+ const git = (args) => executeFile("git", args, { cwd: directory, env, encoding: "utf8" });
2230
+ await git(["init", "--quiet"]);
2231
+ await git(["remote", "add", "origin", `https://github.com/${owner}/${repository}.git`]);
2232
+ if (catalogPath !== ".") {
2233
+ await git(["sparse-checkout", "init", "--cone"]);
2234
+ await git(["sparse-checkout", "set", catalogPath]);
2235
+ }
2236
+ await git(["fetch", "--quiet", "--depth", "1", "origin", ref]);
2237
+ await git(["checkout", "--quiet", "--detach", "FETCH_HEAD"]);
2238
+ return await callback(directory);
2239
+ } finally {
2240
+ await import_promises7.default.rm(directory, { recursive: true, force: true });
2241
+ }
2242
+ };
2243
+ var generateIndex = async (source, ref, checkout, executeFile) => checkout(source, ref, async (directory) => {
2244
+ const { stdout } = await executeFile("git", ["rev-parse", "HEAD"], { cwd: directory, encoding: "utf8" });
2245
+ const commit = stdout.trim();
2246
+ const catalogDirectory = import_node_path14.default.resolve(directory, source.path ?? ".");
2247
+ const relativeCatalogDirectory = import_node_path14.default.relative(directory, catalogDirectory);
2248
+ if (relativeCatalogDirectory.startsWith("..") || import_node_path14.default.isAbsolute(relativeCatalogDirectory)) {
2249
+ throw new Error(`Catalog path "${source.path}" escapes source "${source.id}"`);
2250
+ }
2251
+ const index = await (0, import_sdk2.default)(catalogDirectory).buildIndex({ source: source.id, commit });
2252
+ return { bytes: Buffer.from(JSON.stringify(index)), index, commit, generated: true };
2253
+ });
2254
+ var fetchPublishedIndex = async (source, ref, fetcher, token) => {
2255
+ const indexPath = import_node_path14.default.posix.join(source.path ?? ".", "catalog.index.json");
2256
+ const bytes = await fetchBytes(source, ref, indexPath, fetcher, token);
2257
+ if (!bytes) return void 0;
2258
+ const index = (0, import_sdk2.parseIndex)(JSON.parse(bytes.toString("utf8")));
2259
+ if (index.source !== source.id) {
2260
+ throw new Error(`Published index source "${index.source}" does not match configured id "${source.id}"`);
2261
+ }
2262
+ return { bytes, index, commit: index.commit, generated: false };
2263
+ };
2264
+ var createGitHubSourceProvider = (options = {}) => {
2265
+ const fetcher = options.fetch ?? ((url, init) => fetch(url, init));
2266
+ const executeFile = options.execFile ?? ((file, args, execOptions) => execFileAsync(file, args, execOptions));
2267
+ const configuredToken = options.token ?? process.env.EVENTCATALOG_GITHUB_TOKEN ?? process.env.GITHUB_TOKEN;
2268
+ const token = configuredToken?.trim() || void 0;
2269
+ const checkout = options.checkout ?? createCheckout(executeFile, token);
2270
+ return {
2271
+ async resolve(source) {
2272
+ assertSafeCatalogPath(source);
2273
+ const ref = source.ref ?? "main";
2274
+ return await fetchPublishedIndex(source, ref, fetcher, token) ?? generateIndex(source, ref, checkout, executeFile);
2275
+ },
2276
+ async fetchContent({ source, commit, path: artifactPath }) {
2277
+ assertSafeCatalogPath(source);
2278
+ const catalogPath = import_node_path14.default.posix.join(source.path ?? ".", artifactPath);
2279
+ const content = await fetchBytes(source, commit, catalogPath, fetcher, token);
2280
+ if (!content) throw new Error(`Federated artifact not found for "${source.id}": ${artifactPath}`);
2281
+ return content;
2282
+ }
2283
+ };
2284
+ };
2285
+
2286
+ // src/federation/source-provider.ts
2287
+ var createFederationSourceProvider = (projectDirectory, providers = {}) => {
2288
+ const github = providers.github ?? createGitHubSourceProvider();
2289
+ const filesystem = providers.filesystem ?? createFileSystemSourceProvider(projectDirectory);
2290
+ const getProvider = (source) => {
2291
+ if (source.source.startsWith("github:")) return github;
2292
+ if (source.source.startsWith("file:")) return filesystem;
2293
+ throw new Error(`Unsupported federation source "${source.source}" for "${source.id}". Supported protocols: github:, file:.`);
2294
+ };
2295
+ return {
2296
+ async resolve(source) {
2297
+ return getProvider(source).resolve(source);
2298
+ },
2299
+ async fetchContent(request) {
2300
+ return getProvider(request.source).fetchContent(request);
2301
+ }
2302
+ };
2303
+ };
2304
+
2145
2305
  // src/federation/federate.ts
2146
2306
  var FederationConflictError = class extends Error {
2147
2307
  conflicts;
@@ -2164,16 +2324,16 @@ var validateSources = (sources) => {
2164
2324
  var writeLock = async (lockPath, lock) => {
2165
2325
  const temporaryPath = `${lockPath}.tmp-${process.pid}`;
2166
2326
  try {
2167
- await import_promises6.default.writeFile(temporaryPath, `${JSON.stringify(lock, null, 2)}
2327
+ await import_promises8.default.writeFile(temporaryPath, `${JSON.stringify(lock, null, 2)}
2168
2328
  `, "utf8");
2169
- await import_promises6.default.rename(temporaryPath, lockPath);
2329
+ await import_promises8.default.rename(temporaryPath, lockPath);
2170
2330
  } finally {
2171
- await import_promises6.default.rm(temporaryPath, { force: true });
2331
+ await import_promises8.default.rm(temporaryPath, { force: true });
2172
2332
  }
2173
2333
  };
2174
2334
  var readLock = async (lockPath) => {
2175
2335
  try {
2176
- return JSON.parse(await import_promises6.default.readFile(lockPath, "utf8"));
2336
+ return JSON.parse(await import_promises8.default.readFile(lockPath, "utf8"));
2177
2337
  } catch (error) {
2178
2338
  if (error.code === "ENOENT") return void 0;
2179
2339
  throw new Error(`Cannot read federation lock at "${lockPath}"`, { cause: error });
@@ -2181,7 +2341,7 @@ var readLock = async (lockPath) => {
2181
2341
  };
2182
2342
  var pathExists2 = async (filePath) => {
2183
2343
  try {
2184
- await import_promises6.default.access(filePath);
2344
+ await import_promises8.default.access(filePath);
2185
2345
  return true;
2186
2346
  } catch (error) {
2187
2347
  if (error.code === "ENOENT") return false;
@@ -2189,20 +2349,20 @@ var pathExists2 = async (filePath) => {
2189
2349
  }
2190
2350
  };
2191
2351
  var cleanupPreviousFederation = async (projectDirectory, onProgress) => {
2192
- const outDir = import_node_path13.default.join(projectDirectory, "federated");
2193
- const lockPath = import_node_path13.default.join(projectDirectory, "eventcatalog.lock");
2352
+ const outDir = import_node_path15.default.join(projectDirectory, "federated");
2353
+ const lockPath = import_node_path15.default.join(projectDirectory, "eventcatalog.lock");
2194
2354
  const previousLock = await readLock(lockPath);
2195
2355
  const hadFederatedOutput = await pathExists2(outDir);
2196
2356
  const hadLock = previousLock !== void 0;
2197
2357
  if (!hadFederatedOutput && !hadLock) return;
2198
- await import_promises6.default.rm(outDir, { recursive: true, force: true });
2358
+ await import_promises8.default.rm(outDir, { recursive: true, force: true });
2199
2359
  const publicResult = await composePublicAssets({
2200
2360
  projectDirectory,
2201
2361
  federatedDirectory: outDir,
2202
2362
  assets: [],
2203
2363
  previousFiles: previousLock?.publicFiles
2204
2364
  });
2205
- await import_promises6.default.rm(lockPath, { force: true });
2365
+ await import_promises8.default.rm(lockPath, { force: true });
2206
2366
  onProgress?.({
2207
2367
  type: "cleanup:complete",
2208
2368
  federated: hadFederatedOutput,
@@ -2225,7 +2385,7 @@ var federateCatalog = async (projectDirectory, options = {}) => {
2225
2385
  }
2226
2386
  validateSources(sources);
2227
2387
  if (options.useCache === false) options.onProgress?.({ type: "cache:disabled" });
2228
- const provider = options.provider ?? createGitHubSourceProvider();
2388
+ const provider = options.provider ?? createFederationSourceProvider(projectDirectory);
2229
2389
  const resolvedSources = [];
2230
2390
  for (const [index, source] of sources.entries()) {
2231
2391
  const current = index + 1;
@@ -2247,13 +2407,13 @@ var federateCatalog = async (projectDirectory, options = {}) => {
2247
2407
  throw new Error(`Failed to federate source "${source.id}": ${message}`, { cause: error });
2248
2408
  }
2249
2409
  }
2250
- const outDir = import_node_path13.default.join(projectDirectory, "federated");
2251
- const lockPath = import_node_path13.default.join(projectDirectory, "eventcatalog.lock");
2410
+ const outDir = import_node_path15.default.join(projectDirectory, "federated");
2411
+ const lockPath = import_node_path15.default.join(projectDirectory, "eventcatalog.lock");
2252
2412
  const previousLock = await readLock(lockPath);
2253
2413
  const resources = resolvedSources.reduce((total, source) => total + source.resolved.index.resources.length, 0);
2254
2414
  const remoteIndexes = resolvedSources.map(({ resolved }) => resolved.index);
2255
2415
  options.onProgress?.({ type: "local:start" });
2256
- const localIndex = await (0, import_sdk2.default)(projectDirectory).buildIndex({
2416
+ const localIndex = await (0, import_sdk3.default)(projectDirectory).buildIndex({
2257
2417
  source: config.cId,
2258
2418
  commit: "local",
2259
2419
  hashContent: false,
@@ -2261,18 +2421,18 @@ var federateCatalog = async (projectDirectory, options = {}) => {
2261
2421
  });
2262
2422
  options.onProgress?.({ type: "local:complete", resources: localIndex.resources.length });
2263
2423
  options.onProgress?.({ type: "resolving", resources, localResources: localIndex.resources.length });
2264
- const ownershipGraph = (0, import_sdk2.resolve)([localIndex, ...remoteIndexes]);
2424
+ const ownershipGraph = (0, import_sdk3.resolve)([localIndex, ...remoteIndexes]);
2265
2425
  if (ownershipGraph.conflicts.length > 0) {
2266
2426
  options.onProgress?.({ type: "resolved", graph: ownershipGraph });
2267
2427
  throw new FederationConflictError(ownershipGraph.conflicts);
2268
2428
  }
2269
- const graph = (0, import_sdk2.resolve)(remoteIndexes);
2429
+ const graph = (0, import_sdk3.resolve)(remoteIndexes);
2270
2430
  options.onProgress?.({ type: "resolved", graph });
2271
2431
  const sourcesById = new Map(sources.map((source) => [source.id, source]));
2272
2432
  options.onProgress?.({ type: "hydrating", outDir });
2273
2433
  let hydratedFiles = 0;
2274
2434
  let cachedFiles = 0;
2275
- const hydrateResult = await (0, import_sdk2.hydrate)(graph, {
2435
+ const hydrateResult = await (0, import_sdk3.hydrate)(graph, {
2276
2436
  outDir,
2277
2437
  cache: createFederationContentCache(projectDirectory, {
2278
2438
  read: options.useCache !== false,
@@ -2306,7 +2466,7 @@ var federateCatalog = async (projectDirectory, options = {}) => {
2306
2466
  lockVersion: 1,
2307
2467
  sources: resolvedSources.map(({ config: source, resolved }) => ({
2308
2468
  id: source.id,
2309
- digest: `sha256:${(0, import_node_crypto3.createHash)("sha256").update(resolved.bytes).digest("hex")}`,
2469
+ digest: `sha256:${(0, import_node_crypto4.createHash)("sha256").update(resolved.bytes).digest("hex")}`,
2310
2470
  commit: resolved.commit,
2311
2471
  resolvedAt
2312
2472
  })).sort((left, right) => left.id.localeCompare(right.id)),
@@ -2327,14 +2487,14 @@ var federateCatalog = async (projectDirectory, options = {}) => {
2327
2487
 
2328
2488
  // src/eventcatalog.ts
2329
2489
  var import_license = require("@eventcatalog/license");
2330
- var currentDir = import_node_path15.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
2490
+ var currentDir = import_node_path17.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
2331
2491
  var program = new import_commander.Command().version(VERSION);
2332
- var dir = import_node_path15.default.resolve(process.env.PROJECT_DIR || process.cwd());
2333
- var core = import_node_path15.default.resolve(process.env.CATALOG_DIR || (0, import_node_path14.join)(dir, ".eventcatalog-core"));
2334
- var eventCatalogDir = import_node_path15.default.resolve((0, import_node_path14.join)(currentDir, "../eventcatalog/"));
2492
+ var dir = import_node_path17.default.resolve(process.env.PROJECT_DIR || process.cwd());
2493
+ var core = import_node_path17.default.resolve(process.env.CATALOG_DIR || (0, import_node_path16.join)(dir, ".eventcatalog-core"));
2494
+ var eventCatalogDir = import_node_path17.default.resolve((0, import_node_path16.join)(currentDir, "../eventcatalog/"));
2335
2495
  var getInstalledEventCatalogVersion = () => {
2336
2496
  try {
2337
- const pkg = import_fs3.default.readFileSync((0, import_node_path14.join)(dir, "package.json"), "utf8");
2497
+ const pkg = import_fs3.default.readFileSync((0, import_node_path16.join)(dir, "package.json"), "utf8");
2338
2498
  const json = JSON.parse(pkg);
2339
2499
  return json.dependencies["@eventcatalog/core"];
2340
2500
  } catch (error) {
@@ -2400,12 +2560,12 @@ var startDevPrewarm = ({
2400
2560
  var buildDevSearchIndex = async ({ config }) => {
2401
2561
  const result = await buildSearchIndex({
2402
2562
  projectDir: dir,
2403
- outDir: import_node_path15.default.join(core, "public"),
2404
- searchOutputPath: import_node_path15.default.join(core, "public", "pagefind"),
2563
+ outDir: import_node_path17.default.join(core, "public"),
2564
+ searchOutputPath: import_node_path17.default.join(core, "public", "pagefind"),
2405
2565
  config,
2406
2566
  isServer: false
2407
2567
  });
2408
- logger.info(`Indexed ${result.records} page(s) into ${import_node_path15.default.relative(core, result.outputPath)}`, "search");
2568
+ logger.info(`Indexed ${result.records} page(s) into ${import_node_path17.default.relative(core, result.outputPath)}`, "search");
2409
2569
  };
2410
2570
  var warnIfIndexedSearchUsesAuth = async () => {
2411
2571
  if (!await isAuthEnabled()) {
@@ -2520,12 +2680,12 @@ var copyCore = () => {
2520
2680
  import_fs3.default.cpSync(eventCatalogDir, core, {
2521
2681
  recursive: true,
2522
2682
  filter: (src) => {
2523
- const relativePath = import_node_path15.default.relative(eventCatalogDir, src);
2524
- const pathParts = relativePath.split(import_node_path15.default.sep);
2683
+ const relativePath = import_node_path17.default.relative(eventCatalogDir, src);
2684
+ const pathParts = relativePath.split(import_node_path17.default.sep);
2525
2685
  return !pathParts.some((part) => [".astro", "dist", "node_modules"].includes(part));
2526
2686
  }
2527
2687
  });
2528
- const coreNodeModules = import_node_path15.default.join(core, "node_modules");
2688
+ const coreNodeModules = import_node_path17.default.join(core, "node_modules");
2529
2689
  const installedCoreNodeModules = resolveInstalledCoreNodeModules(currentDir);
2530
2690
  linkCoreNodeModules({ coreNodeModules, installedCoreNodeModules });
2531
2691
  };
@@ -2584,8 +2744,8 @@ program.command("dev").description("Run development server of EventCatalog").opt
2584
2744
  logger.info("Setting up EventCatalog...", "eventcatalog");
2585
2745
  const isServer = await isOutputServer();
2586
2746
  logger.info(isServer ? "EventCatalog is running in Server Mode" : "EventCatalog is running in Static Mode", "config");
2587
- if (import_fs3.default.existsSync(import_node_path15.default.join(dir, ".env"))) {
2588
- import_dotenv.default.config({ path: import_node_path15.default.join(dir, ".env") });
2747
+ if (import_fs3.default.existsSync(import_node_path17.default.join(dir, ".env"))) {
2748
+ import_dotenv.default.config({ path: import_node_path17.default.join(dir, ".env") });
2589
2749
  }
2590
2750
  if (options.debug) {
2591
2751
  logger.info("Debug mode enabled", "debug");
@@ -2665,8 +2825,8 @@ program.command("build").description("Run build of EventCatalog").action(async (
2665
2825
  logger.info("Building EventCatalog...", "build");
2666
2826
  const isServer = await isOutputServer();
2667
2827
  logger.info(isServer ? "EventCatalog is running in Server Mode" : "EventCatalog is running in Static Mode", "config");
2668
- if (import_fs3.default.existsSync(import_node_path15.default.join(dir, ".env"))) {
2669
- import_dotenv.default.config({ path: import_node_path15.default.join(dir, ".env") });
2828
+ if (import_fs3.default.existsSync(import_node_path17.default.join(dir, ".env"))) {
2829
+ import_dotenv.default.config({ path: import_node_path17.default.join(dir, ".env") });
2670
2830
  }
2671
2831
  await verifyRequiredFieldsAreInCatalogConfigFile(dir);
2672
2832
  copyCore();
@@ -2716,7 +2876,7 @@ program.command("build").description("Run build of EventCatalog").action(async (
2716
2876
  if (await isIndexedSearchEnabled()) {
2717
2877
  await warnIfIndexedSearchUsesAuth();
2718
2878
  const config = await getEventCatalogConfigFile(dir);
2719
- const outDir = import_node_path15.default.resolve(dir, await getProjectOutDir());
2879
+ const outDir = import_node_path17.default.resolve(dir, await getProjectOutDir());
2720
2880
  logger.info("Building indexed search...", "search");
2721
2881
  const result = await buildSearchIndex({
2722
2882
  projectDir: dir,
@@ -2724,7 +2884,7 @@ program.command("build").description("Run build of EventCatalog").action(async (
2724
2884
  config,
2725
2885
  isServer
2726
2886
  });
2727
- logger.info(`Indexed ${result.records} page(s) into ${import_node_path15.default.relative(dir, result.outputPath)}`, "search");
2887
+ logger.info(`Indexed ${result.records} page(s) into ${import_node_path17.default.relative(dir, result.outputPath)}`, "search");
2728
2888
  }
2729
2889
  });
2730
2890
  var previewCatalog = async ({
@@ -2751,7 +2911,7 @@ var startServerCatalog = async ({
2751
2911
  isEventCatalogStarter = false,
2752
2912
  isEventCatalogScale = false
2753
2913
  }) => {
2754
- const serverEntryPath = import_node_path15.default.join(dir, "dist", "server", "entry.mjs");
2914
+ const serverEntryPath = import_node_path17.default.join(dir, "dist", "server", "entry.mjs");
2755
2915
  await runCommandWithFilteredOutput({
2756
2916
  command: `node "${serverEntryPath}"`,
2757
2917
  cwd: core,
@@ -2768,8 +2928,8 @@ var startServerCatalog = async ({
2768
2928
  program.command("preview").description("Serves the contents of your eventcatalog build directory").action(async (options, command) => {
2769
2929
  logger.welcome();
2770
2930
  logger.info("Starting preview of your build...", "preview");
2771
- if (import_fs3.default.existsSync(import_node_path15.default.join(dir, ".env"))) {
2772
- import_dotenv.default.config({ path: import_node_path15.default.join(dir, ".env") });
2931
+ if (import_fs3.default.existsSync(import_node_path17.default.join(dir, ".env"))) {
2932
+ import_dotenv.default.config({ path: import_node_path17.default.join(dir, ".env") });
2773
2933
  }
2774
2934
  const canEmbedPages = await (0, import_license.isFeatureEnabled)(
2775
2935
  "@eventcatalog/backstage-plugin-eventcatalog",
@@ -2787,8 +2947,8 @@ program.command("preview").description("Serves the contents of your eventcatalog
2787
2947
  program.command("start").description("Serves the contents of your eventcatalog build directory").action(async (options, command) => {
2788
2948
  logger.welcome();
2789
2949
  logger.info("Starting preview of your build...", "preview");
2790
- if (import_fs3.default.existsSync(import_node_path15.default.join(dir, ".env"))) {
2791
- import_dotenv.default.config({ path: import_node_path15.default.join(dir, ".env") });
2950
+ if (import_fs3.default.existsSync(import_node_path17.default.join(dir, ".env"))) {
2951
+ import_dotenv.default.config({ path: import_node_path17.default.join(dir, ".env") });
2792
2952
  }
2793
2953
  const canEmbedPages = await (0, import_license.isFeatureEnabled)(
2794
2954
  "@eventcatalog/backstage-plugin-eventcatalog",
@@ -2815,22 +2975,22 @@ program.command("start").description("Serves the contents of your eventcatalog b
2815
2975
  program.command("export").description("Export your EventCatalog using the SDK dumpCatalog function").option("--include-markdown", "Include markdown content in the export", false).action(async (options) => {
2816
2976
  logger.welcome();
2817
2977
  logger.info("Exporting EventCatalog...", "export");
2818
- if (import_fs3.default.existsSync(import_node_path15.default.join(dir, ".env"))) {
2819
- import_dotenv.default.config({ path: import_node_path15.default.join(dir, ".env") });
2978
+ if (import_fs3.default.existsSync(import_node_path17.default.join(dir, ".env"))) {
2979
+ import_dotenv.default.config({ path: import_node_path17.default.join(dir, ".env") });
2820
2980
  }
2821
2981
  const { default: initSDK } = await import("@eventcatalog/sdk");
2822
2982
  const sdk = initSDK(dir);
2823
2983
  const catalog = await sdk.dumpCatalog({ includeMarkdown: options.includeMarkdown });
2824
- const exportsDir = import_node_path15.default.join(dir, "exports");
2984
+ const exportsDir = import_node_path17.default.join(dir, "exports");
2825
2985
  ensureDir(exportsDir);
2826
2986
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
2827
- const exportFile = import_node_path15.default.join(exportsDir, `catalog-${date}.json`);
2987
+ const exportFile = import_node_path17.default.join(exportsDir, `catalog-${date}.json`);
2828
2988
  import_fs3.default.writeFileSync(exportFile, JSON.stringify(catalog, null, 2), "utf-8");
2829
2989
  logger.info(`Catalog exported to ${exportFile}`, "export");
2830
2990
  });
2831
2991
  program.command("generate [siteDir]").description("Start the generator scripts.").action(async () => {
2832
- if (import_fs3.default.existsSync(import_node_path15.default.join(dir, ".env"))) {
2833
- import_dotenv.default.config({ path: import_node_path15.default.join(dir, ".env") });
2992
+ if (import_fs3.default.existsSync(import_node_path17.default.join(dir, ".env"))) {
2993
+ import_dotenv.default.config({ path: import_node_path17.default.join(dir, ".env") });
2834
2994
  }
2835
2995
  await generate(dir);
2836
2996
  });
@@ -2905,7 +3065,7 @@ var reportFederationProgress = (event) => {
2905
3065
  }
2906
3066
  return;
2907
3067
  case "hydrating":
2908
- logger.info(`Hydrating federated content into ${import_node_path15.default.relative(dir, event.outDir)}/...`, "federation");
3068
+ logger.info(`Hydrating federated content into ${import_node_path17.default.relative(dir, event.outDir)}/...`, "federation");
2909
3069
  return;
2910
3070
  case "hydrate:cache":
2911
3071
  if (event.files === 1 || event.files % 25 === 0) {
@@ -2934,13 +3094,13 @@ var reportFederationProgress = (event) => {
2934
3094
  `Federation complete: ${event.result.sources} sources, ${event.result.resources} remote resources, ${event.result.hydrate.written} files written (${event.result.hydrate.fetched} downloaded, ${event.result.hydrate.written - event.result.hydrate.fetched} cached)`,
2935
3095
  "federation"
2936
3096
  );
2937
- logger.info(`Pinned source commits in ${import_node_path15.default.relative(dir, event.result.lockPath)}`, "federation");
3097
+ logger.info(`Pinned source commits in ${import_node_path17.default.relative(dir, event.result.lockPath)}`, "federation");
2938
3098
  }
2939
3099
  };
2940
3100
  program.command("federate").description("Fetch, resolve, and hydrate the catalogs configured in federation.sources.").option("--no-cache", "Download all federation content and refresh the cache.").action(async (commandOptions) => {
2941
3101
  logger.welcome();
2942
- if (import_fs3.default.existsSync(import_node_path15.default.join(dir, ".env"))) {
2943
- import_dotenv.default.config({ path: import_node_path15.default.join(dir, ".env") });
3102
+ if (import_fs3.default.existsSync(import_node_path17.default.join(dir, ".env"))) {
3103
+ import_dotenv.default.config({ path: import_node_path17.default.join(dir, ".env") });
2944
3104
  }
2945
3105
  logger.info("Starting federation...", "federation");
2946
3106
  let cleanedPreviousOutput = false;