@eventcatalog/core 4.10.4 → 4.10.6
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.
- package/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/count-resources.cjs +32 -0
- package/dist/analytics/count-resources.d.cts +9 -1
- package/dist/analytics/count-resources.d.ts +9 -1
- package/dist/analytics/count-resources.js +3 -1
- package/dist/analytics/log-build.cjs +30 -3
- package/dist/analytics/log-build.d.cts +2 -1
- package/dist/analytics/log-build.d.ts +2 -1
- package/dist/analytics/log-build.js +4 -4
- package/dist/{chunk-2SLBVVUZ.js → chunk-EB43LSVE.js} +12 -4
- package/dist/{chunk-T5XTOY52.js → chunk-GMVJ4B2S.js} +1 -1
- package/dist/{chunk-6S2ZIVEV.js → chunk-NECJFWMI.js} +1 -1
- package/dist/{chunk-S3J4N5ZP.js → chunk-XFS3XVP2.js} +1 -1
- package/dist/{chunk-322TAIDG.js → chunk-YSWJHMAX.js} +1 -1
- package/dist/{chunk-K2XIENVT.js → chunk-ZAZHAVKB.js} +21 -0
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +277 -243
- package/dist/eventcatalog.js +14 -7
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/src/components/MDX/MermaidFileLoader/MermaidFileLoader.astro +10 -3
- package/eventcatalog/src/pages/diagrams/[id]/[version]/embed.astro +665 -325
- package/eventcatalog/src/remark-plugins/mermaid.ts +48 -1
- package/eventcatalog/src/utils/mermaid-zoom.ts +781 -404
- package/package.json +6 -7
package/dist/eventcatalog.cjs
CHANGED
|
@@ -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
|
|
32
|
+
var import_node_path18 = require("path");
|
|
33
33
|
var import_node_http = __toESM(require("http"), 1);
|
|
34
34
|
var import_fs3 = __toESM(require("fs"), 1);
|
|
35
|
-
var
|
|
35
|
+
var import_node_path19 = __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.10.
|
|
147
|
+
var version = "4.10.6";
|
|
148
148
|
|
|
149
149
|
// src/constants.ts
|
|
150
150
|
var VERSION = version;
|
|
@@ -299,6 +299,9 @@ async function raiseEvent(eventData) {
|
|
|
299
299
|
|
|
300
300
|
// src/analytics/count-resources.js
|
|
301
301
|
var import_glob = require("glob");
|
|
302
|
+
var import_node_crypto = require("crypto");
|
|
303
|
+
var import_promises2 = require("fs/promises");
|
|
304
|
+
var import_node_path3 = __toESM(require("path"), 1);
|
|
302
305
|
var RESOURCE_PATTERNS = {
|
|
303
306
|
adrs: ["**/adrs/*/index.@(md|mdx)"],
|
|
304
307
|
agents: ["**/agents/*/index.@(md|mdx)"],
|
|
@@ -339,6 +342,23 @@ async function countResources(projectDir) {
|
|
|
339
342
|
}
|
|
340
343
|
return counts;
|
|
341
344
|
}
|
|
345
|
+
async function hashCatalogContent(projectDir) {
|
|
346
|
+
const hash = (0, import_node_crypto.createHash)("sha256");
|
|
347
|
+
const files = /* @__PURE__ */ new Set();
|
|
348
|
+
for (const pattern of Object.values(RESOURCE_PATTERNS).flat()) {
|
|
349
|
+
for (const file of await (0, import_glob.glob)(pattern, { cwd: projectDir, ignore: DEFAULT_IGNORES })) {
|
|
350
|
+
files.add(file);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
for (const file of [...files].sort()) {
|
|
354
|
+
try {
|
|
355
|
+
hash.update(file);
|
|
356
|
+
hash.update(await (0, import_promises2.readFile)(import_node_path3.default.join(projectDir, file)));
|
|
357
|
+
} catch {
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return hash.digest("hex").slice(0, 16);
|
|
361
|
+
}
|
|
342
362
|
function serializeCounts(counts) {
|
|
343
363
|
return Object.entries(counts).map(([k, v]) => `${k}:${v}`).join(",");
|
|
344
364
|
}
|
|
@@ -412,7 +432,7 @@ var reportCloudResourceInventory = async (configFile, resourceCounts) => {
|
|
|
412
432
|
})
|
|
413
433
|
});
|
|
414
434
|
};
|
|
415
|
-
var main = async (projectDir, { isEventCatalogStarterEnabled: isEventCatalogStarterEnabled2, isEventCatalogScaleEnabled: isEventCatalogScaleEnabled2, isBackstagePluginEnabled }) => {
|
|
435
|
+
var main = async (projectDir, { isEventCatalogStarterEnabled: isEventCatalogStarterEnabled2, isEventCatalogScaleEnabled: isEventCatalogScaleEnabled2, isBackstagePluginEnabled, command = "build" }) => {
|
|
416
436
|
try {
|
|
417
437
|
await verifyRequiredFieldsAreInCatalogConfigFile(projectDir);
|
|
418
438
|
const configFile = await getEventCatalogConfigFile(projectDir);
|
|
@@ -429,11 +449,18 @@ var main = async (projectDir, { isEventCatalogStarterEnabled: isEventCatalogStar
|
|
|
429
449
|
}
|
|
430
450
|
const features = await getFeatures(configFile);
|
|
431
451
|
const resourceCounts = await countResources(projectDir);
|
|
452
|
+
const contentHash = await hashCatalogContent(projectDir);
|
|
432
453
|
await reportCloudResourceInventory(configFile, resourceCounts);
|
|
433
454
|
await raiseEvent({
|
|
434
|
-
command
|
|
455
|
+
command,
|
|
435
456
|
org: organizationName,
|
|
436
457
|
cId,
|
|
458
|
+
// CI redeploys and human-run builds are different signals; tag rather than suppress
|
|
459
|
+
ci: process.env.CI ? "true" : "false",
|
|
460
|
+
// The commercial plan, separate from the generators list, so telemetry joins cleanly to licensing
|
|
461
|
+
plan: isEventCatalogScaleEnabled2 ? "scale" : isEventCatalogStarterEnabled2 ? "starter" : "none",
|
|
462
|
+
backstage: isBackstagePluginEnabled ? "true" : "false",
|
|
463
|
+
contentHash,
|
|
437
464
|
generators: generatorNames.toString(),
|
|
438
465
|
features: Object.keys(features).map((feature) => `${feature}:${features[feature]}`).join(","),
|
|
439
466
|
directorySources: serializeDirectorySources(configFile),
|
|
@@ -449,7 +476,7 @@ var import_watcher = __toESM(require("@parcel/watcher"), 1);
|
|
|
449
476
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
450
477
|
|
|
451
478
|
// src/map-catalog-to-astro.js
|
|
452
|
-
var
|
|
479
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
453
480
|
var CUSTOM_PAGE_EXTENSIONS = [".astro", ".ts", ".js", ".mjs"];
|
|
454
481
|
var COLLECTION_KEYS = [
|
|
455
482
|
"agents",
|
|
@@ -479,10 +506,10 @@ function mapCatalogToAstro({ filePath, astroDir, projectDir }) {
|
|
|
479
506
|
}
|
|
480
507
|
const baseTargetPaths = getBaseTargetPaths(relativeFilePath);
|
|
481
508
|
const relativeTargetPath = getRelativeTargetPath(relativeFilePath);
|
|
482
|
-
return baseTargetPaths.map((base) =>
|
|
509
|
+
return baseTargetPaths.map((base) => import_node_path4.default.join(astroDir, base, relativeTargetPath));
|
|
483
510
|
}
|
|
484
511
|
function removeBasePath(fullPath, basePath) {
|
|
485
|
-
const relativePath =
|
|
512
|
+
const relativePath = import_node_path4.default.relative(basePath, fullPath);
|
|
486
513
|
return relativePath.startsWith("..") ? fullPath : relativePath;
|
|
487
514
|
}
|
|
488
515
|
function isCollectionKey(key) {
|
|
@@ -493,21 +520,21 @@ function isLikeC4Source(filePath) {
|
|
|
493
520
|
}
|
|
494
521
|
var hasExtension = (str) => /\.[a-zA-Z0-9]{2,}$/.test(str);
|
|
495
522
|
function getCustomPageTargetPaths(filePath, astroDir) {
|
|
496
|
-
const filePathArr = filePath.split(
|
|
523
|
+
const filePathArr = filePath.split(import_node_path4.default.sep).filter(Boolean);
|
|
497
524
|
if (filePathArr[0] !== "pages") {
|
|
498
525
|
return null;
|
|
499
526
|
}
|
|
500
|
-
const customPagePath =
|
|
501
|
-
if (CUSTOM_PAGE_EXTENSIONS.includes(
|
|
527
|
+
const customPagePath = import_node_path4.default.join(astroDir, "src", "custom-pages", ...filePathArr.slice(1));
|
|
528
|
+
if (CUSTOM_PAGE_EXTENSIONS.includes(import_node_path4.default.extname(filePath).toLowerCase())) {
|
|
502
529
|
return [customPagePath];
|
|
503
530
|
}
|
|
504
531
|
if (!hasExtension(filePath)) {
|
|
505
|
-
return [customPagePath,
|
|
532
|
+
return [customPagePath, import_node_path4.default.join(astroDir, "public", "generated", ...filePathArr)];
|
|
506
533
|
}
|
|
507
|
-
return [
|
|
534
|
+
return [import_node_path4.default.join(astroDir, "public", "generated", ...filePathArr)];
|
|
508
535
|
}
|
|
509
536
|
function isCatalogRelated(filePath) {
|
|
510
|
-
const filePathArr = filePath.split(
|
|
537
|
+
const filePathArr = filePath.split(import_node_path4.default.sep).filter(Boolean);
|
|
511
538
|
if ([
|
|
512
539
|
"eventcatalog.config.js",
|
|
513
540
|
// config file at root
|
|
@@ -528,38 +555,38 @@ function isCatalogRelated(filePath) {
|
|
|
528
555
|
return false;
|
|
529
556
|
}
|
|
530
557
|
function getBaseTargetPaths(filePath) {
|
|
531
|
-
const filePathArr = filePath.split(
|
|
558
|
+
const filePathArr = filePath.split(import_node_path4.default.sep).filter(Boolean);
|
|
532
559
|
if (isCollectionKey(filePathArr[0])) {
|
|
533
560
|
if (hasExtension(filePath)) {
|
|
534
|
-
return [
|
|
561
|
+
return [import_node_path4.default.join("public", "generated")];
|
|
535
562
|
}
|
|
536
|
-
return [
|
|
563
|
+
return [import_node_path4.default.join("public", "generated")];
|
|
537
564
|
}
|
|
538
565
|
if (filePathArr[0] == "components") {
|
|
539
|
-
return [
|
|
566
|
+
return [import_node_path4.default.join("src", "custom-defined-components")];
|
|
540
567
|
}
|
|
541
568
|
if (filePathArr[0] == "snippets") {
|
|
542
|
-
return [
|
|
569
|
+
return [import_node_path4.default.join("src")];
|
|
543
570
|
}
|
|
544
571
|
if (filePathArr[0] == "public") {
|
|
545
|
-
return [
|
|
572
|
+
return [import_node_path4.default.join("public")];
|
|
546
573
|
}
|
|
547
|
-
return [
|
|
574
|
+
return [import_node_path4.default.join("/")];
|
|
548
575
|
}
|
|
549
576
|
function getRelativeTargetPath(filePath) {
|
|
550
|
-
const filePathArr = filePath.split(
|
|
577
|
+
const filePathArr = filePath.split(import_node_path4.default.sep).filter(Boolean);
|
|
551
578
|
if (filePathArr[0] == "public" || filePathArr[0] == "components") {
|
|
552
579
|
filePathArr.shift();
|
|
553
580
|
}
|
|
554
581
|
if (filePathArr[0] == "snippets") {
|
|
555
|
-
return
|
|
582
|
+
return import_node_path4.default.join("snippets", ...filePathArr.slice(1));
|
|
556
583
|
}
|
|
557
584
|
const relativePath = [];
|
|
558
585
|
for (let i = filePathArr.length - 1; i >= 0; i--) {
|
|
559
586
|
relativePath.unshift(filePathArr[i]);
|
|
560
587
|
if (isCollectionKey(filePathArr[i]) && filePathArr[i] != "snippets") break;
|
|
561
588
|
}
|
|
562
|
-
return
|
|
589
|
+
return import_node_path4.default.join(...relativePath);
|
|
563
590
|
}
|
|
564
591
|
|
|
565
592
|
// src/watcher.js
|
|
@@ -656,21 +683,21 @@ function retryEPERM(fn) {
|
|
|
656
683
|
|
|
657
684
|
// src/catalog-to-astro-content-directory.js
|
|
658
685
|
var import_glob2 = require("glob");
|
|
659
|
-
var
|
|
686
|
+
var path6 = __toESM(require("path"), 1);
|
|
660
687
|
var import_fs = __toESM(require("fs"), 1);
|
|
661
688
|
var import_url2 = require("url");
|
|
662
689
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
663
690
|
|
|
664
691
|
// src/custom-components.js
|
|
665
|
-
var
|
|
666
|
-
var
|
|
692
|
+
var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
693
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
667
694
|
var isCustomComponentPath = (projectDirectory, filePath) => {
|
|
668
|
-
const [rootDirectory, childDirectory] =
|
|
695
|
+
const [rootDirectory, childDirectory] = import_node_path5.default.relative(projectDirectory, filePath).split(import_node_path5.default.sep);
|
|
669
696
|
return rootDirectory === "components" || rootDirectory === "federated" && childDirectory === "components";
|
|
670
697
|
};
|
|
671
698
|
var readDirectory = async (directory) => {
|
|
672
699
|
try {
|
|
673
|
-
return await
|
|
700
|
+
return await import_promises3.default.readdir(directory, { withFileTypes: true });
|
|
674
701
|
} catch (error) {
|
|
675
702
|
if (error.code === "ENOENT") return [];
|
|
676
703
|
throw error;
|
|
@@ -678,57 +705,57 @@ var readDirectory = async (directory) => {
|
|
|
678
705
|
};
|
|
679
706
|
var mergeDirectory = async (sourceDirectory, destinationDirectory) => {
|
|
680
707
|
for (const entry of await readDirectory(sourceDirectory)) {
|
|
681
|
-
const sourcePath =
|
|
682
|
-
const destinationPath =
|
|
708
|
+
const sourcePath = import_node_path5.default.join(sourceDirectory, entry.name);
|
|
709
|
+
const destinationPath = import_node_path5.default.join(destinationDirectory, entry.name);
|
|
683
710
|
if (entry.isDirectory()) {
|
|
684
|
-
const destinationEntry = await
|
|
711
|
+
const destinationEntry = await import_promises3.default.stat(destinationPath).catch((error) => {
|
|
685
712
|
if (error.code === "ENOENT") return void 0;
|
|
686
713
|
throw error;
|
|
687
714
|
});
|
|
688
715
|
if (destinationEntry && !destinationEntry.isDirectory()) {
|
|
689
|
-
await
|
|
716
|
+
await import_promises3.default.rm(destinationPath, { recursive: true, force: true });
|
|
690
717
|
}
|
|
691
|
-
await
|
|
718
|
+
await import_promises3.default.mkdir(destinationPath, { recursive: true });
|
|
692
719
|
await mergeDirectory(sourcePath, destinationPath);
|
|
693
720
|
continue;
|
|
694
721
|
}
|
|
695
|
-
await
|
|
696
|
-
await
|
|
722
|
+
await import_promises3.default.rm(destinationPath, { recursive: true, force: true });
|
|
723
|
+
await import_promises3.default.copyFile(sourcePath, destinationPath);
|
|
697
724
|
}
|
|
698
725
|
};
|
|
699
726
|
var syncCustomComponents = async (projectDirectory, catalogDirectory) => {
|
|
700
|
-
const destinationDirectory =
|
|
701
|
-
const destinationParent =
|
|
702
|
-
await
|
|
703
|
-
const stagingDirectory = await
|
|
727
|
+
const destinationDirectory = import_node_path5.default.join(catalogDirectory, "src", "custom-defined-components");
|
|
728
|
+
const destinationParent = import_node_path5.default.dirname(destinationDirectory);
|
|
729
|
+
await import_promises3.default.mkdir(destinationParent, { recursive: true });
|
|
730
|
+
const stagingDirectory = await import_promises3.default.mkdtemp(import_node_path5.default.join(destinationParent, ".custom-defined-components.staging-"));
|
|
704
731
|
try {
|
|
705
|
-
await mergeDirectory(
|
|
706
|
-
await mergeDirectory(
|
|
707
|
-
await
|
|
708
|
-
await
|
|
732
|
+
await mergeDirectory(import_node_path5.default.join(projectDirectory, "federated", "components"), stagingDirectory);
|
|
733
|
+
await mergeDirectory(import_node_path5.default.join(projectDirectory, "components"), stagingDirectory);
|
|
734
|
+
await import_promises3.default.rm(destinationDirectory, { recursive: true, force: true });
|
|
735
|
+
await import_promises3.default.rename(stagingDirectory, destinationDirectory);
|
|
709
736
|
} finally {
|
|
710
|
-
await
|
|
737
|
+
await import_promises3.default.rm(stagingDirectory, { recursive: true, force: true });
|
|
711
738
|
}
|
|
712
739
|
};
|
|
713
740
|
|
|
714
741
|
// src/catalog-to-astro-content-directory.js
|
|
715
742
|
var __filename2 = (0, import_url2.fileURLToPath)(importMetaUrl);
|
|
716
|
-
var rootPkg =
|
|
743
|
+
var rootPkg = path6.resolve(path6.dirname(__filename2), "../");
|
|
717
744
|
var copyFiles = async (source, target) => {
|
|
718
|
-
const files = await (0, import_glob2.glob)(
|
|
745
|
+
const files = await (0, import_glob2.glob)(path6.join(source, "**"), {
|
|
719
746
|
nodir: true,
|
|
720
747
|
windowsPathsNoEscape: import_node_os2.default.platform() == "win32",
|
|
721
748
|
ignore: ["node_modules/**", "**/dist/**", "**/teams", "**/users", "**/*.mdx", "**/*.md", "**/package.json", "**/Dockerfile"]
|
|
722
749
|
});
|
|
723
|
-
const snippets = await (0, import_glob2.glob)(
|
|
750
|
+
const snippets = await (0, import_glob2.glob)(path6.join(source, "snippets/**/*.mdx"), {
|
|
724
751
|
nodir: true,
|
|
725
752
|
windowsPathsNoEscape: import_node_os2.default.platform() == "win32"
|
|
726
753
|
});
|
|
727
754
|
if (snippets.length > 0) {
|
|
728
755
|
files.push(...snippets);
|
|
729
756
|
}
|
|
730
|
-
if (import_fs.default.existsSync(
|
|
731
|
-
files.push(
|
|
757
|
+
if (import_fs.default.existsSync(path6.join(source, ".env"))) {
|
|
758
|
+
files.push(path6.join(source, ".env"));
|
|
732
759
|
}
|
|
733
760
|
for (const file of files) {
|
|
734
761
|
if (isCustomComponentPath(source, file)) continue;
|
|
@@ -743,9 +770,9 @@ var copyFiles = async (source, target) => {
|
|
|
743
770
|
}
|
|
744
771
|
};
|
|
745
772
|
var clearCustomPages = async (target) => {
|
|
746
|
-
const customPagesDir =
|
|
773
|
+
const customPagesDir = path6.join(target, "src", "custom-pages");
|
|
747
774
|
if (import_fs.default.existsSync(customPagesDir)) import_fs.default.rmSync(customPagesDir, { recursive: true });
|
|
748
|
-
const staleCodeFiles = await (0, import_glob2.glob)(
|
|
775
|
+
const staleCodeFiles = await (0, import_glob2.glob)(path6.join(target, "public", "generated", "pages", "**/*.{astro,ts,js,mjs}"), {
|
|
749
776
|
nodir: true,
|
|
750
777
|
windowsPathsNoEscape: import_node_os2.default.platform() == "win32"
|
|
751
778
|
});
|
|
@@ -754,8 +781,8 @@ var clearCustomPages = async (target) => {
|
|
|
754
781
|
}
|
|
755
782
|
};
|
|
756
783
|
var removeGeneratedLikeC4Sources = async (target) => {
|
|
757
|
-
const generatedDir =
|
|
758
|
-
const files = await (0, import_glob2.glob)(
|
|
784
|
+
const generatedDir = path6.join(target, "public", "generated");
|
|
785
|
+
const files = await (0, import_glob2.glob)(path6.join(generatedDir, "**/*.{c4,likec4}"), {
|
|
759
786
|
nodir: true,
|
|
760
787
|
windowsPathsNoEscape: import_node_os2.default.platform() == "win32"
|
|
761
788
|
});
|
|
@@ -764,12 +791,12 @@ var removeGeneratedLikeC4Sources = async (target) => {
|
|
|
764
791
|
}
|
|
765
792
|
};
|
|
766
793
|
var catalogToAstro = async (source, astroDir) => {
|
|
767
|
-
const astroContentDir =
|
|
794
|
+
const astroContentDir = path6.join(astroDir, "src/content/");
|
|
768
795
|
if (import_fs.default.existsSync(astroContentDir)) import_fs.default.rmSync(astroContentDir, { recursive: true });
|
|
769
796
|
import_fs.default.mkdirSync(astroContentDir);
|
|
770
797
|
await verifyRequiredFieldsAreInCatalogConfigFile(source);
|
|
771
|
-
if (!import_fs.default.existsSync(
|
|
772
|
-
import_fs.default.writeFileSync(
|
|
798
|
+
if (!import_fs.default.existsSync(path6.join(source, "eventcatalog.styles.css"))) {
|
|
799
|
+
import_fs.default.writeFileSync(path6.join(source, "eventcatalog.styles.css"), "");
|
|
773
800
|
}
|
|
774
801
|
await clearCustomPages(astroDir);
|
|
775
802
|
await removeGeneratedLikeC4Sources(astroDir);
|
|
@@ -778,7 +805,7 @@ var catalogToAstro = async (source, astroDir) => {
|
|
|
778
805
|
};
|
|
779
806
|
|
|
780
807
|
// src/resolve-catalog-dependencies.js
|
|
781
|
-
var
|
|
808
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
782
809
|
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
783
810
|
var import_gray_matter2 = __toESM(require("gray-matter"), 1);
|
|
784
811
|
var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
|
|
@@ -787,7 +814,7 @@ var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
|
|
|
787
814
|
if (!dependencies) {
|
|
788
815
|
return;
|
|
789
816
|
}
|
|
790
|
-
const dependenciesDir =
|
|
817
|
+
const dependenciesDir = import_node_path6.default.join(catalogDir, "dependencies");
|
|
791
818
|
if (import_node_fs3.default.existsSync(dependenciesDir)) {
|
|
792
819
|
import_node_fs3.default.rmSync(dependenciesDir, { recursive: true, force: true });
|
|
793
820
|
}
|
|
@@ -811,8 +838,8 @@ var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
|
|
|
811
838
|
},
|
|
812
839
|
frontmatter
|
|
813
840
|
);
|
|
814
|
-
const resourceFile =
|
|
815
|
-
import_node_fs3.default.mkdirSync(
|
|
841
|
+
const resourceFile = import_node_path6.default.join(dependenciesDir, resourceType, dependency.id, `index.md`);
|
|
842
|
+
import_node_fs3.default.mkdirSync(import_node_path6.default.dirname(resourceFile), { recursive: true });
|
|
816
843
|
import_node_fs3.default.writeFileSync(resourceFile, markdown);
|
|
817
844
|
}
|
|
818
845
|
}
|
|
@@ -823,7 +850,7 @@ var resolve_catalog_dependencies_default = async (catalogDir, core2) => {
|
|
|
823
850
|
var import_boxen = __toESM(require("boxen"), 1);
|
|
824
851
|
|
|
825
852
|
// src/features.ts
|
|
826
|
-
var
|
|
853
|
+
var import_node_path7 = require("path");
|
|
827
854
|
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
828
855
|
var getProjectOutDir = async () => {
|
|
829
856
|
const config = await getEventCatalogConfigFile(process.env.PROJECT_DIR || "");
|
|
@@ -839,7 +866,7 @@ var isIndexedSearchEnabled = async () => {
|
|
|
839
866
|
};
|
|
840
867
|
var isAuthEnabled = async () => {
|
|
841
868
|
const directory = process.env.PROJECT_DIR || process.cwd();
|
|
842
|
-
const hasAuthConfig = import_node_fs4.default.existsSync((0,
|
|
869
|
+
const hasAuthConfig = import_node_fs4.default.existsSync((0, import_node_path7.join)(directory, "eventcatalog.auth.js"));
|
|
843
870
|
return hasAuthConfig;
|
|
844
871
|
};
|
|
845
872
|
|
|
@@ -852,7 +879,7 @@ var import_node_fs5 = __toESM(require("fs"), 1);
|
|
|
852
879
|
var import_glob3 = require("glob");
|
|
853
880
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
854
881
|
var import_gray_matter3 = __toESM(require("gray-matter"), 1);
|
|
855
|
-
var
|
|
882
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
856
883
|
var DISABLE_CHANNEL_MIGRATION_ENV = "EVENTCATALOG_DISABLE_CHANNEL_MIGRATION";
|
|
857
884
|
var isChannelMigrationDisabled = () => {
|
|
858
885
|
return ["true", "1", "yes"].includes((process.env[DISABLE_CHANNEL_MIGRATION_ENV] ?? "").toLowerCase());
|
|
@@ -861,7 +888,7 @@ var message_channels_to_service_channels_default = async (dir2) => {
|
|
|
861
888
|
if (isChannelMigrationDisabled()) {
|
|
862
889
|
return { status: "skipped", message: `Channel migration disabled by ${DISABLE_CHANNEL_MIGRATION_ENV}` };
|
|
863
890
|
}
|
|
864
|
-
const PROJECT_DIR =
|
|
891
|
+
const PROJECT_DIR = import_node_path8.default.join(dir2 || process.env.PROJECT_DIR);
|
|
865
892
|
const messages = await (0, import_glob3.glob)(
|
|
866
893
|
[
|
|
867
894
|
"**/events/*/index.mdx",
|
|
@@ -968,7 +995,7 @@ var runMigrations = async (dir2) => {
|
|
|
968
995
|
};
|
|
969
996
|
|
|
970
997
|
// eventcatalog/src/enterprise/fields/field-indexer.ts
|
|
971
|
-
var
|
|
998
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
972
999
|
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
973
1000
|
|
|
974
1001
|
// eventcatalog/src/enterprise/fields/fields-db.ts
|
|
@@ -1334,22 +1361,22 @@ function getAvroTypeName(type) {
|
|
|
1334
1361
|
function walkAvroRecord(schema, prefix, fields) {
|
|
1335
1362
|
if (!schema.fields || !Array.isArray(schema.fields)) return;
|
|
1336
1363
|
for (const field of schema.fields) {
|
|
1337
|
-
const
|
|
1364
|
+
const path19 = prefix ? `${prefix}.${field.name}` : field.name;
|
|
1338
1365
|
const isOptional = Array.isArray(field.type) && field.type.includes("null");
|
|
1339
1366
|
const typeName = getAvroTypeName(field.type);
|
|
1340
1367
|
fields.push({
|
|
1341
|
-
path:
|
|
1368
|
+
path: path19,
|
|
1342
1369
|
type: typeName,
|
|
1343
1370
|
description: field.doc || "",
|
|
1344
1371
|
required: !isOptional
|
|
1345
1372
|
});
|
|
1346
1373
|
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;
|
|
1347
1374
|
if (innerType) {
|
|
1348
|
-
walkAvroRecord(innerType,
|
|
1375
|
+
walkAvroRecord(innerType, path19, fields);
|
|
1349
1376
|
}
|
|
1350
1377
|
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;
|
|
1351
1378
|
if (arrayType && typeof arrayType.items === "object" && arrayType.items.type === "record") {
|
|
1352
|
-
walkAvroRecord(arrayType.items, `${
|
|
1379
|
+
walkAvroRecord(arrayType.items, `${path19}[]`, fields);
|
|
1353
1380
|
}
|
|
1354
1381
|
}
|
|
1355
1382
|
}
|
|
@@ -1380,32 +1407,32 @@ function walkJsonSchema(node, prefix, requiredList, rootSchema, fields) {
|
|
|
1380
1407
|
}
|
|
1381
1408
|
if (!node.properties) return;
|
|
1382
1409
|
for (const [name, prop] of Object.entries(node.properties)) {
|
|
1383
|
-
const
|
|
1410
|
+
const path19 = prefix ? `${prefix}.${name}` : name;
|
|
1384
1411
|
const isRequired = requiredList.includes(name);
|
|
1385
1412
|
if (prop.$ref) {
|
|
1386
1413
|
const resolved = resolveLocalRef(prop.$ref, rootSchema);
|
|
1387
1414
|
if (resolved) {
|
|
1388
1415
|
const rawRefType = resolved.type || "object";
|
|
1389
1416
|
const type2 = Array.isArray(rawRefType) ? [...rawRefType].sort().join(" | ") : rawRefType;
|
|
1390
|
-
fields.push({ path:
|
|
1417
|
+
fields.push({ path: path19, type: type2, description: resolved.description || "", required: isRequired });
|
|
1391
1418
|
if (resolved.properties) {
|
|
1392
|
-
walkJsonSchema(resolved,
|
|
1419
|
+
walkJsonSchema(resolved, path19, resolved.required || [], rootSchema, fields);
|
|
1393
1420
|
}
|
|
1394
1421
|
} else {
|
|
1395
|
-
fields.push({ path:
|
|
1422
|
+
fields.push({ path: path19, type: "$ref", description: "", required: isRequired });
|
|
1396
1423
|
}
|
|
1397
1424
|
continue;
|
|
1398
1425
|
}
|
|
1399
1426
|
const rawType = prop.type || (prop.enum ? "enum" : prop.$ref ? "$ref" : "object");
|
|
1400
1427
|
const typeList = Array.isArray(rawType) ? rawType : [rawType];
|
|
1401
1428
|
const type = Array.isArray(rawType) ? [...rawType].sort().join(" | ") : rawType;
|
|
1402
|
-
fields.push({ path:
|
|
1429
|
+
fields.push({ path: path19, type, description: prop.description || "", required: isRequired });
|
|
1403
1430
|
if (typeList.includes("object") && prop.properties) {
|
|
1404
|
-
walkJsonSchema(prop,
|
|
1431
|
+
walkJsonSchema(prop, path19, prop.required || [], rootSchema, fields);
|
|
1405
1432
|
}
|
|
1406
1433
|
if (typeList.includes("array") && prop.items) {
|
|
1407
1434
|
if (prop.items.type === "object" && prop.items.properties) {
|
|
1408
|
-
walkJsonSchema(prop.items, `${
|
|
1435
|
+
walkJsonSchema(prop.items, `${path19}[]`, prop.items.required || [], rootSchema, fields);
|
|
1409
1436
|
}
|
|
1410
1437
|
}
|
|
1411
1438
|
}
|
|
@@ -1423,7 +1450,7 @@ function resolveLocalRef(ref, rootSchema) {
|
|
|
1423
1450
|
|
|
1424
1451
|
// eventcatalog/src/enterprise/fields/field-indexer.ts
|
|
1425
1452
|
function detectFormat(fileName) {
|
|
1426
|
-
const ext =
|
|
1453
|
+
const ext = import_node_path9.default.extname(fileName).toLowerCase();
|
|
1427
1454
|
if (ext === ".proto") return "proto";
|
|
1428
1455
|
if (ext === ".avro" || ext === ".avsc") return "avro";
|
|
1429
1456
|
return "json-schema";
|
|
@@ -1431,8 +1458,8 @@ function detectFormat(fileName) {
|
|
|
1431
1458
|
async function buildFieldsIndex(catalogDir, outputDir) {
|
|
1432
1459
|
const sdkModule = await import("@eventcatalog/sdk");
|
|
1433
1460
|
const sdk = sdkModule.default(catalogDir);
|
|
1434
|
-
const dbDir =
|
|
1435
|
-
const dbPath =
|
|
1461
|
+
const dbDir = import_node_path9.default.join(outputDir || catalogDir, ".eventcatalog");
|
|
1462
|
+
const dbPath = import_node_path9.default.join(dbDir, "fields.db");
|
|
1436
1463
|
if (!import_node_fs7.default.existsSync(dbDir)) {
|
|
1437
1464
|
import_node_fs7.default.mkdirSync(dbDir, { recursive: true });
|
|
1438
1465
|
}
|
|
@@ -1517,8 +1544,8 @@ async function buildFieldsIndex(catalogDir, outputDir) {
|
|
|
1517
1544
|
}
|
|
1518
1545
|
|
|
1519
1546
|
// src/search-indexer.ts
|
|
1520
|
-
var
|
|
1521
|
-
var
|
|
1547
|
+
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
1548
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
1522
1549
|
var import_glob4 = require("glob");
|
|
1523
1550
|
var import_gray_matter4 = __toESM(require("gray-matter"), 1);
|
|
1524
1551
|
var RESOURCE_COLLECTIONS = {
|
|
@@ -1581,9 +1608,9 @@ var markdownToSearchText = (content) => {
|
|
|
1581
1608
|
};
|
|
1582
1609
|
var inferDocIdFromFile = (relativePath, frontmatterId) => {
|
|
1583
1610
|
if (frontmatterId) return frontmatterId;
|
|
1584
|
-
const fileName =
|
|
1611
|
+
const fileName = import_node_path10.default.posix.basename(removeExtension(relativePath));
|
|
1585
1612
|
if (fileName.toLowerCase() === "index") {
|
|
1586
|
-
return
|
|
1613
|
+
return import_node_path10.default.posix.basename(import_node_path10.default.posix.dirname(relativePath));
|
|
1587
1614
|
}
|
|
1588
1615
|
return stripNumericPrefix(fileName);
|
|
1589
1616
|
};
|
|
@@ -1601,10 +1628,10 @@ var findResourceSegment = (segments) => {
|
|
|
1601
1628
|
return match;
|
|
1602
1629
|
};
|
|
1603
1630
|
var readResourceFrontmatter = async (projectDir, resourcePath) => {
|
|
1604
|
-
const candidates = [
|
|
1631
|
+
const candidates = [import_node_path10.default.join(projectDir, resourcePath, "index.mdx"), import_node_path10.default.join(projectDir, resourcePath, "index.md")];
|
|
1605
1632
|
for (const candidate of candidates) {
|
|
1606
1633
|
try {
|
|
1607
|
-
const file = await
|
|
1634
|
+
const file = await import_promises4.default.readFile(candidate, "utf8");
|
|
1608
1635
|
return (0, import_gray_matter4.default)(file).data;
|
|
1609
1636
|
} catch {
|
|
1610
1637
|
}
|
|
@@ -1626,7 +1653,7 @@ var deriveRecordFromPath = async ({
|
|
|
1626
1653
|
}
|
|
1627
1654
|
if (segments[0] === "docs") {
|
|
1628
1655
|
const customPath = normalizeUrlPath(removeExtension(segments.slice(1).join("/")));
|
|
1629
|
-
const title = data.title || data.label ||
|
|
1656
|
+
const title = data.title || data.label || import_node_path10.default.posix.basename(customPath) || "Custom docs";
|
|
1630
1657
|
return {
|
|
1631
1658
|
url: buildUrl(`/docs/custom/${customPath}`, config),
|
|
1632
1659
|
title,
|
|
@@ -1742,9 +1769,9 @@ var collectSearchRecords = async ({
|
|
|
1742
1769
|
});
|
|
1743
1770
|
const records = await Promise.all(
|
|
1744
1771
|
files.map(async (file) => {
|
|
1745
|
-
const raw = await
|
|
1772
|
+
const raw = await import_promises4.default.readFile(file, "utf8");
|
|
1746
1773
|
const parsed = (0, import_gray_matter4.default)(raw);
|
|
1747
|
-
const relativePath = normalizePath(
|
|
1774
|
+
const relativePath = normalizePath(import_node_path10.default.relative(projectDir, file));
|
|
1748
1775
|
const baseRecord = await deriveRecordFromPath({
|
|
1749
1776
|
projectDir,
|
|
1750
1777
|
relativePath,
|
|
@@ -1792,7 +1819,7 @@ var getSearchOutputPath = ({
|
|
|
1792
1819
|
if (searchOutputPath) {
|
|
1793
1820
|
return searchOutputPath;
|
|
1794
1821
|
}
|
|
1795
|
-
return
|
|
1822
|
+
return import_node_path10.default.join(outDir, isServer ? "client" : "", "pagefind");
|
|
1796
1823
|
};
|
|
1797
1824
|
var buildSearchIndex = async ({ projectDir, outDir, config, isServer, searchOutputPath }) => {
|
|
1798
1825
|
const records = await collectSearchRecords({ projectDir, config });
|
|
@@ -1828,7 +1855,7 @@ var buildSearchIndex = async ({ projectDir, outDir, config, isServer, searchOutp
|
|
|
1828
1855
|
}
|
|
1829
1856
|
}
|
|
1830
1857
|
const outputPath = getSearchOutputPath({ outDir, isServer, searchOutputPath });
|
|
1831
|
-
await
|
|
1858
|
+
await import_promises4.default.rm(outputPath, { recursive: true, force: true });
|
|
1832
1859
|
const writeResult = await index.writeFiles({ outputPath });
|
|
1833
1860
|
if (writeResult.errors?.length) {
|
|
1834
1861
|
errors.push(...writeResult.errors.map((error) => error.message || String(error)));
|
|
@@ -1847,7 +1874,7 @@ ${errors.join("\n")}`);
|
|
|
1847
1874
|
|
|
1848
1875
|
// src/core-node-modules.ts
|
|
1849
1876
|
var import_fs2 = __toESM(require("fs"), 1);
|
|
1850
|
-
var
|
|
1877
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
1851
1878
|
var isDirectory = (directory) => {
|
|
1852
1879
|
try {
|
|
1853
1880
|
return import_fs2.default.statSync(directory).isDirectory();
|
|
@@ -1857,7 +1884,7 @@ var isDirectory = (directory) => {
|
|
|
1857
1884
|
};
|
|
1858
1885
|
var hasAstroDependency = (nodeModulesDirectory) => {
|
|
1859
1886
|
const astroBin = process.platform === "win32" ? "astro.cmd" : "astro";
|
|
1860
|
-
return import_fs2.default.existsSync(
|
|
1887
|
+
return import_fs2.default.existsSync(import_node_path11.default.join(nodeModulesDirectory, "astro", "package.json")) || import_fs2.default.existsSync(import_node_path11.default.join(nodeModulesDirectory, ".bin", astroBin));
|
|
1861
1888
|
};
|
|
1862
1889
|
var isSymbolicLink = (targetPath) => {
|
|
1863
1890
|
try {
|
|
@@ -1877,20 +1904,20 @@ var resolveInstalledCoreNodeModules = (currentDir2) => {
|
|
|
1877
1904
|
const candidates = [];
|
|
1878
1905
|
const seen = /* @__PURE__ */ new Set();
|
|
1879
1906
|
const addCandidate = (candidate) => {
|
|
1880
|
-
const resolvedCandidate =
|
|
1907
|
+
const resolvedCandidate = import_node_path11.default.resolve(candidate);
|
|
1881
1908
|
if (!seen.has(resolvedCandidate)) {
|
|
1882
1909
|
candidates.push(resolvedCandidate);
|
|
1883
1910
|
seen.add(resolvedCandidate);
|
|
1884
1911
|
}
|
|
1885
1912
|
};
|
|
1886
|
-
addCandidate(
|
|
1887
|
-
let directory =
|
|
1913
|
+
addCandidate(import_node_path11.default.resolve(currentDir2, "..", "node_modules"));
|
|
1914
|
+
let directory = import_node_path11.default.resolve(currentDir2);
|
|
1888
1915
|
while (true) {
|
|
1889
|
-
if (
|
|
1916
|
+
if (import_node_path11.default.basename(directory) === "node_modules") {
|
|
1890
1917
|
addCandidate(directory);
|
|
1891
1918
|
}
|
|
1892
|
-
addCandidate(
|
|
1893
|
-
const parentDirectory =
|
|
1919
|
+
addCandidate(import_node_path11.default.join(directory, "node_modules"));
|
|
1920
|
+
const parentDirectory = import_node_path11.default.dirname(directory);
|
|
1894
1921
|
if (parentDirectory === directory) {
|
|
1895
1922
|
break;
|
|
1896
1923
|
}
|
|
@@ -1929,28 +1956,28 @@ var createAstroDevLineFilter = () => {
|
|
|
1929
1956
|
};
|
|
1930
1957
|
|
|
1931
1958
|
// src/federation/federate.ts
|
|
1932
|
-
var
|
|
1933
|
-
var
|
|
1934
|
-
var
|
|
1959
|
+
var import_node_crypto5 = require("crypto");
|
|
1960
|
+
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
1961
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
1935
1962
|
var import_sdk3 = __toESM(require("@eventcatalog/sdk"), 1);
|
|
1936
1963
|
|
|
1937
1964
|
// src/federation/content-cache.ts
|
|
1938
|
-
var
|
|
1939
|
-
var
|
|
1940
|
-
var
|
|
1941
|
-
var getContentHash = (content) => `sha256:${(0,
|
|
1965
|
+
var import_node_crypto2 = require("crypto");
|
|
1966
|
+
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
1967
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
1968
|
+
var getContentHash = (content) => `sha256:${(0, import_node_crypto2.createHash)("sha256").update(content).digest("hex")}`;
|
|
1942
1969
|
var isContentHash = (key) => /^sha256:[a-f0-9]{64}$/i.test(key);
|
|
1943
1970
|
var createFederationContentCache = (projectDirectory, options = {}) => {
|
|
1944
|
-
const cacheDirectory =
|
|
1945
|
-
const getCachePath = (key) =>
|
|
1971
|
+
const cacheDirectory = import_node_path12.default.join(projectDirectory, ".eventcatalog-cache", "federation", "content");
|
|
1972
|
+
const getCachePath = (key) => import_node_path12.default.join(cacheDirectory, encodeURIComponent(key));
|
|
1946
1973
|
return {
|
|
1947
1974
|
async get(key) {
|
|
1948
1975
|
if (options.read === false || !isContentHash(key)) return void 0;
|
|
1949
1976
|
const cachePath = getCachePath(key);
|
|
1950
1977
|
try {
|
|
1951
|
-
const content = await
|
|
1978
|
+
const content = await import_promises5.default.readFile(cachePath);
|
|
1952
1979
|
if (getContentHash(content) !== key) {
|
|
1953
|
-
await
|
|
1980
|
+
await import_promises5.default.rm(cachePath, { force: true });
|
|
1954
1981
|
return void 0;
|
|
1955
1982
|
}
|
|
1956
1983
|
options.onHit?.(key);
|
|
@@ -1962,14 +1989,14 @@ var createFederationContentCache = (projectDirectory, options = {}) => {
|
|
|
1962
1989
|
},
|
|
1963
1990
|
async set(key, content) {
|
|
1964
1991
|
if (!isContentHash(key) || getContentHash(content) !== key) return;
|
|
1965
|
-
await
|
|
1992
|
+
await import_promises5.default.mkdir(cacheDirectory, { recursive: true });
|
|
1966
1993
|
const cachePath = getCachePath(key);
|
|
1967
|
-
const temporaryPath = `${cachePath}.tmp-${process.pid}-${(0,
|
|
1994
|
+
const temporaryPath = `${cachePath}.tmp-${process.pid}-${(0, import_node_crypto2.randomUUID)()}`;
|
|
1968
1995
|
try {
|
|
1969
|
-
await
|
|
1970
|
-
await
|
|
1996
|
+
await import_promises5.default.writeFile(temporaryPath, content);
|
|
1997
|
+
await import_promises5.default.rename(temporaryPath, cachePath);
|
|
1971
1998
|
} finally {
|
|
1972
|
-
await
|
|
1999
|
+
await import_promises5.default.rm(temporaryPath, { force: true });
|
|
1973
2000
|
}
|
|
1974
2001
|
}
|
|
1975
2002
|
};
|
|
@@ -2132,21 +2159,21 @@ var import_license = require("@eventcatalog/license");
|
|
|
2132
2159
|
var isFederationEnabled = () => (0, import_license.isEventCatalogEnterpriseEnabled)();
|
|
2133
2160
|
|
|
2134
2161
|
// src/federation/output-transaction.ts
|
|
2135
|
-
var
|
|
2136
|
-
var
|
|
2162
|
+
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
2163
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
2137
2164
|
var getSafePublicPath = (publicDirectory, relativePath) => {
|
|
2138
|
-
const normalizedPath =
|
|
2139
|
-
const unsafe = relativePath.length === 0 || relativePath.includes("\0") || relativePath.includes("\\") ||
|
|
2165
|
+
const normalizedPath = import_node_path13.default.posix.normalize(relativePath);
|
|
2166
|
+
const unsafe = relativePath.length === 0 || relativePath.includes("\0") || relativePath.includes("\\") || import_node_path13.default.posix.isAbsolute(relativePath) || /^[a-zA-Z]:\//.test(relativePath) || normalizedPath !== relativePath || normalizedPath === ".." || normalizedPath.startsWith("../");
|
|
2140
2167
|
if (unsafe) return void 0;
|
|
2141
|
-
const destinationPath =
|
|
2142
|
-
const relativeDestinationPath =
|
|
2143
|
-
return relativeDestinationPath !== "" && relativeDestinationPath !== ".." && !relativeDestinationPath.startsWith(`..${
|
|
2168
|
+
const destinationPath = import_node_path13.default.resolve(publicDirectory, relativePath);
|
|
2169
|
+
const relativeDestinationPath = import_node_path13.default.relative(publicDirectory, destinationPath);
|
|
2170
|
+
return relativeDestinationPath !== "" && relativeDestinationPath !== ".." && !relativeDestinationPath.startsWith(`..${import_node_path13.default.sep}`) && !import_node_path13.default.isAbsolute(relativeDestinationPath) ? destinationPath : void 0;
|
|
2144
2171
|
};
|
|
2145
2172
|
var beginFederationOutputTransaction = async (projectDirectory, outDir, relativePublicPaths) => {
|
|
2146
|
-
const transactionDirectory = await
|
|
2147
|
-
const previousOutDir =
|
|
2148
|
-
const publicBackupDirectory =
|
|
2149
|
-
const publicDirectory =
|
|
2173
|
+
const transactionDirectory = await import_promises6.default.mkdtemp(import_node_path13.default.join(projectDirectory, ".eventcatalog-federation-transaction-"));
|
|
2174
|
+
const previousOutDir = import_node_path13.default.join(transactionDirectory, "federated");
|
|
2175
|
+
const publicBackupDirectory = import_node_path13.default.join(transactionDirectory, "public");
|
|
2176
|
+
const publicDirectory = import_node_path13.default.resolve(projectDirectory, "public");
|
|
2150
2177
|
const publicSnapshots = [];
|
|
2151
2178
|
const missingPublicDirectories = /* @__PURE__ */ new Set();
|
|
2152
2179
|
let hadPreviousOutDir = false;
|
|
@@ -2155,45 +2182,45 @@ var beginFederationOutputTransaction = async (projectDirectory, outDir, relative
|
|
|
2155
2182
|
const destinationPath = getSafePublicPath(publicDirectory, relativePath);
|
|
2156
2183
|
if (!destinationPath) continue;
|
|
2157
2184
|
try {
|
|
2158
|
-
const stat = await
|
|
2185
|
+
const stat = await import_promises6.default.lstat(destinationPath);
|
|
2159
2186
|
if (!stat.isFile()) continue;
|
|
2160
|
-
const backupPath =
|
|
2161
|
-
await
|
|
2162
|
-
await
|
|
2187
|
+
const backupPath = import_node_path13.default.join(publicBackupDirectory, `${publicSnapshots.length}`);
|
|
2188
|
+
await import_promises6.default.mkdir(import_node_path13.default.dirname(backupPath), { recursive: true });
|
|
2189
|
+
await import_promises6.default.copyFile(destinationPath, backupPath);
|
|
2163
2190
|
publicSnapshots.push({ backupPath, destinationPath, state: "file" });
|
|
2164
2191
|
} catch (error) {
|
|
2165
2192
|
const code = error.code;
|
|
2166
2193
|
if (code === "ENOTDIR") continue;
|
|
2167
2194
|
if (code !== "ENOENT") throw error;
|
|
2168
2195
|
publicSnapshots.push({ destinationPath, state: "missing" });
|
|
2169
|
-
let directory =
|
|
2196
|
+
let directory = import_node_path13.default.dirname(destinationPath);
|
|
2170
2197
|
while (directory !== publicDirectory) {
|
|
2171
2198
|
try {
|
|
2172
|
-
await
|
|
2199
|
+
await import_promises6.default.lstat(directory);
|
|
2173
2200
|
break;
|
|
2174
2201
|
} catch (directoryError) {
|
|
2175
2202
|
const directoryCode = directoryError.code;
|
|
2176
2203
|
if (directoryCode === "ENOTDIR") break;
|
|
2177
2204
|
if (directoryCode !== "ENOENT") throw directoryError;
|
|
2178
2205
|
missingPublicDirectories.add(directory);
|
|
2179
|
-
directory =
|
|
2206
|
+
directory = import_node_path13.default.dirname(directory);
|
|
2180
2207
|
}
|
|
2181
2208
|
}
|
|
2182
2209
|
}
|
|
2183
2210
|
}
|
|
2184
2211
|
try {
|
|
2185
|
-
await
|
|
2212
|
+
await import_promises6.default.rename(outDir, previousOutDir);
|
|
2186
2213
|
hadPreviousOutDir = true;
|
|
2187
2214
|
} catch (error) {
|
|
2188
2215
|
if (error.code !== "ENOENT") throw error;
|
|
2189
2216
|
}
|
|
2190
2217
|
} catch (error) {
|
|
2191
|
-
await
|
|
2218
|
+
await import_promises6.default.rm(transactionDirectory, { recursive: true, force: true });
|
|
2192
2219
|
throw error;
|
|
2193
2220
|
}
|
|
2194
2221
|
return {
|
|
2195
2222
|
commit: async () => {
|
|
2196
|
-
await
|
|
2223
|
+
await import_promises6.default.rm(transactionDirectory, { recursive: true, force: true }).catch(() => void 0);
|
|
2197
2224
|
},
|
|
2198
2225
|
rollback: async () => {
|
|
2199
2226
|
const rollbackErrors = [];
|
|
@@ -2204,28 +2231,28 @@ var beginFederationOutputTransaction = async (projectDirectory, outDir, relative
|
|
|
2204
2231
|
rollbackErrors.push(error);
|
|
2205
2232
|
}
|
|
2206
2233
|
};
|
|
2207
|
-
await attempt(() =>
|
|
2208
|
-
if (hadPreviousOutDir) await attempt(() =>
|
|
2234
|
+
await attempt(() => import_promises6.default.rm(outDir, { recursive: true, force: true }));
|
|
2235
|
+
if (hadPreviousOutDir) await attempt(() => import_promises6.default.rename(previousOutDir, outDir));
|
|
2209
2236
|
for (const snapshot of publicSnapshots) {
|
|
2210
2237
|
if (snapshot.state === "missing") {
|
|
2211
|
-
await attempt(() =>
|
|
2238
|
+
await attempt(() => import_promises6.default.rm(snapshot.destinationPath, { force: true }));
|
|
2212
2239
|
continue;
|
|
2213
2240
|
}
|
|
2214
2241
|
await attempt(async () => {
|
|
2215
|
-
await
|
|
2216
|
-
await
|
|
2242
|
+
await import_promises6.default.mkdir(import_node_path13.default.dirname(snapshot.destinationPath), { recursive: true });
|
|
2243
|
+
await import_promises6.default.copyFile(snapshot.backupPath, snapshot.destinationPath);
|
|
2217
2244
|
});
|
|
2218
2245
|
}
|
|
2219
2246
|
for (const directory of [...missingPublicDirectories].sort((left, right) => right.length - left.length)) {
|
|
2220
2247
|
await attempt(async () => {
|
|
2221
2248
|
try {
|
|
2222
|
-
await
|
|
2249
|
+
await import_promises6.default.rmdir(directory);
|
|
2223
2250
|
} catch (error) {
|
|
2224
2251
|
if (!["ENOENT", "ENOTEMPTY"].includes(error.code ?? "")) throw error;
|
|
2225
2252
|
}
|
|
2226
2253
|
});
|
|
2227
2254
|
}
|
|
2228
|
-
await attempt(() =>
|
|
2255
|
+
await attempt(() => import_promises6.default.rm(transactionDirectory, { recursive: true, force: true }));
|
|
2229
2256
|
if (rollbackErrors.length > 0) throw new AggregateError(rollbackErrors, "Failed to restore the previous federation output");
|
|
2230
2257
|
}
|
|
2231
2258
|
};
|
|
@@ -2247,27 +2274,27 @@ var withFederationOutputTransaction = async (projectDirectory, outDir, relativeP
|
|
|
2247
2274
|
};
|
|
2248
2275
|
|
|
2249
2276
|
// src/federation/public-assets.ts
|
|
2250
|
-
var
|
|
2251
|
-
var
|
|
2252
|
-
var
|
|
2253
|
-
var getContentHash2 = (content) => `sha256:${(0,
|
|
2277
|
+
var import_node_crypto3 = require("crypto");
|
|
2278
|
+
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
2279
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
2280
|
+
var getContentHash2 = (content) => `sha256:${(0, import_node_crypto3.createHash)("sha256").update(content).digest("hex")}`;
|
|
2254
2281
|
var getFileHash = async (filePath) => {
|
|
2255
2282
|
try {
|
|
2256
|
-
const stat = await
|
|
2257
|
-
return stat.isFile() ? getContentHash2(await
|
|
2283
|
+
const stat = await import_promises7.default.lstat(filePath);
|
|
2284
|
+
return stat.isFile() ? getContentHash2(await import_promises7.default.readFile(filePath)) : void 0;
|
|
2258
2285
|
} catch (error) {
|
|
2259
2286
|
if (error.code === "ENOENT") return void 0;
|
|
2260
2287
|
throw error;
|
|
2261
2288
|
}
|
|
2262
2289
|
};
|
|
2263
2290
|
var getSafePath = (directory, relativePath) => {
|
|
2264
|
-
const normalizedPath =
|
|
2265
|
-
const unsafe = relativePath.length === 0 || relativePath.includes("\0") || relativePath.includes("\\") ||
|
|
2291
|
+
const normalizedPath = import_node_path14.default.posix.normalize(relativePath);
|
|
2292
|
+
const unsafe = relativePath.length === 0 || relativePath.includes("\0") || relativePath.includes("\\") || import_node_path14.default.posix.isAbsolute(relativePath) || /^[a-zA-Z]:\//.test(relativePath) || normalizedPath !== relativePath || normalizedPath === ".." || normalizedPath.startsWith("../");
|
|
2266
2293
|
if (unsafe) return void 0;
|
|
2267
|
-
const resolvedDirectory =
|
|
2268
|
-
const resolvedPath =
|
|
2269
|
-
const relativeResolvedPath =
|
|
2270
|
-
if (relativeResolvedPath === "" || relativeResolvedPath === ".." || relativeResolvedPath.startsWith(`..${
|
|
2294
|
+
const resolvedDirectory = import_node_path14.default.resolve(directory);
|
|
2295
|
+
const resolvedPath = import_node_path14.default.resolve(resolvedDirectory, relativePath);
|
|
2296
|
+
const relativeResolvedPath = import_node_path14.default.relative(resolvedDirectory, resolvedPath);
|
|
2297
|
+
if (relativeResolvedPath === "" || relativeResolvedPath === ".." || relativeResolvedPath.startsWith(`..${import_node_path14.default.sep}`) || import_node_path14.default.isAbsolute(relativeResolvedPath)) {
|
|
2271
2298
|
return void 0;
|
|
2272
2299
|
}
|
|
2273
2300
|
return resolvedPath;
|
|
@@ -2275,23 +2302,23 @@ var getSafePath = (directory, relativePath) => {
|
|
|
2275
2302
|
var listFiles = async (directory, relativeDirectory = "") => {
|
|
2276
2303
|
let entries;
|
|
2277
2304
|
try {
|
|
2278
|
-
entries = await
|
|
2305
|
+
entries = await import_promises7.default.readdir(import_node_path14.default.join(directory, relativeDirectory), { withFileTypes: true });
|
|
2279
2306
|
} catch (error) {
|
|
2280
2307
|
if (error.code === "ENOENT") return [];
|
|
2281
2308
|
throw error;
|
|
2282
2309
|
}
|
|
2283
2310
|
const files = await Promise.all(
|
|
2284
2311
|
entries.map(async (entry) => {
|
|
2285
|
-
const relativePath =
|
|
2312
|
+
const relativePath = import_node_path14.default.join(relativeDirectory, entry.name);
|
|
2286
2313
|
if (entry.isDirectory()) return listFiles(directory, relativePath);
|
|
2287
|
-
return entry.isFile() ? [relativePath.split(
|
|
2314
|
+
return entry.isFile() ? [relativePath.split(import_node_path14.default.sep).join("/")] : [];
|
|
2288
2315
|
})
|
|
2289
2316
|
);
|
|
2290
2317
|
return files.flat().sort();
|
|
2291
2318
|
};
|
|
2292
2319
|
var pathExists = async (filePath) => {
|
|
2293
2320
|
try {
|
|
2294
|
-
await
|
|
2321
|
+
await import_promises7.default.lstat(filePath);
|
|
2295
2322
|
return true;
|
|
2296
2323
|
} catch (error) {
|
|
2297
2324
|
if (error.code === "ENOENT") return false;
|
|
@@ -2299,27 +2326,27 @@ var pathExists = async (filePath) => {
|
|
|
2299
2326
|
}
|
|
2300
2327
|
};
|
|
2301
2328
|
var hasBlockingParent = async (publicDirectory, destinationPath) => {
|
|
2302
|
-
let currentPath =
|
|
2329
|
+
let currentPath = import_node_path14.default.dirname(destinationPath);
|
|
2303
2330
|
while (currentPath !== publicDirectory) {
|
|
2304
2331
|
try {
|
|
2305
|
-
if (!(await
|
|
2332
|
+
if (!(await import_promises7.default.lstat(currentPath)).isDirectory()) return true;
|
|
2306
2333
|
} catch (error) {
|
|
2307
2334
|
if (error.code !== "ENOENT") throw error;
|
|
2308
2335
|
}
|
|
2309
|
-
currentPath =
|
|
2336
|
+
currentPath = import_node_path14.default.dirname(currentPath);
|
|
2310
2337
|
}
|
|
2311
2338
|
return false;
|
|
2312
2339
|
};
|
|
2313
2340
|
var pruneEmptyDirectories = async (publicDirectory, filePath) => {
|
|
2314
|
-
let currentPath =
|
|
2341
|
+
let currentPath = import_node_path14.default.dirname(filePath);
|
|
2315
2342
|
while (currentPath !== publicDirectory) {
|
|
2316
2343
|
try {
|
|
2317
|
-
await
|
|
2344
|
+
await import_promises7.default.rmdir(currentPath);
|
|
2318
2345
|
} catch (error) {
|
|
2319
2346
|
if (!["ENOENT", "ENOTEMPTY"].includes(error.code ?? "")) throw error;
|
|
2320
2347
|
if (error.code === "ENOTEMPTY") return;
|
|
2321
2348
|
}
|
|
2322
|
-
currentPath =
|
|
2349
|
+
currentPath = import_node_path14.default.dirname(currentPath);
|
|
2323
2350
|
}
|
|
2324
2351
|
};
|
|
2325
2352
|
var composePublicAssets = async ({
|
|
@@ -2329,8 +2356,8 @@ var composePublicAssets = async ({
|
|
|
2329
2356
|
previousFiles = {},
|
|
2330
2357
|
collisionPaths = /* @__PURE__ */ new Set()
|
|
2331
2358
|
}) => {
|
|
2332
|
-
const publicDirectory =
|
|
2333
|
-
const federatedPublicDirectory =
|
|
2359
|
+
const publicDirectory = import_node_path14.default.resolve(projectDirectory, "public");
|
|
2360
|
+
const federatedPublicDirectory = import_node_path14.default.resolve(federatedDirectory, "public");
|
|
2334
2361
|
const sourceFiles = await listFiles(federatedPublicDirectory);
|
|
2335
2362
|
const sourceFileSet = new Set(sourceFiles);
|
|
2336
2363
|
const managedFiles = /* @__PURE__ */ new Set();
|
|
@@ -2343,7 +2370,7 @@ var composePublicAssets = async ({
|
|
|
2343
2370
|
if (sourceFileSet.has(relativePath)) continue;
|
|
2344
2371
|
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
2345
2372
|
if (!destinationPath) continue;
|
|
2346
|
-
await
|
|
2373
|
+
await import_promises7.default.rm(destinationPath, { force: true });
|
|
2347
2374
|
await pruneEmptyDirectories(publicDirectory, destinationPath);
|
|
2348
2375
|
removed += 1;
|
|
2349
2376
|
}
|
|
@@ -2365,31 +2392,31 @@ var composePublicAssets = async ({
|
|
|
2365
2392
|
}
|
|
2366
2393
|
const asset = publicAssetsByPath.get(relativePath);
|
|
2367
2394
|
if (!asset) throw new Error(`Cannot identify the source of federated public asset "${relativePath}"`);
|
|
2368
|
-
const content = await
|
|
2369
|
-
await
|
|
2370
|
-
await
|
|
2395
|
+
const content = await import_promises7.default.readFile(sourcePath);
|
|
2396
|
+
await import_promises7.default.mkdir(import_node_path14.default.dirname(destinationPath), { recursive: true });
|
|
2397
|
+
await import_promises7.default.writeFile(destinationPath, content);
|
|
2371
2398
|
files[relativePath] = { source: asset.resolvedFrom.source, hash: getContentHash2(content) };
|
|
2372
2399
|
copied += 1;
|
|
2373
2400
|
if (collisionPaths.has(`public/${relativePath}`)) overwritten += 1;
|
|
2374
2401
|
}
|
|
2375
|
-
await
|
|
2402
|
+
await import_promises7.default.rm(federatedPublicDirectory, { recursive: true, force: true });
|
|
2376
2403
|
return { files, copied, skipped, overwritten, removed };
|
|
2377
2404
|
};
|
|
2378
2405
|
|
|
2379
2406
|
// src/federation/filesystem-source-provider.ts
|
|
2380
|
-
var
|
|
2381
|
-
var
|
|
2382
|
-
var
|
|
2407
|
+
var import_node_crypto4 = require("crypto");
|
|
2408
|
+
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
2409
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
2383
2410
|
var import_sdk = __toESM(require("@eventcatalog/sdk"), 1);
|
|
2384
2411
|
var FILESYSTEM_SOURCE_PREFIX = "file:";
|
|
2385
2412
|
var isWithinDirectory = (directory, target) => {
|
|
2386
|
-
const relativePath =
|
|
2387
|
-
return relativePath === "" || !relativePath.startsWith(`..${
|
|
2413
|
+
const relativePath = import_node_path15.default.relative(directory, target);
|
|
2414
|
+
return relativePath === "" || !relativePath.startsWith(`..${import_node_path15.default.sep}`) && relativePath !== ".." && !import_node_path15.default.isAbsolute(relativePath);
|
|
2388
2415
|
};
|
|
2389
2416
|
var assertPortableRelativePath = (filePath, label, allowRoot = true) => {
|
|
2390
2417
|
const portablePath = filePath.replaceAll("\\", "/");
|
|
2391
|
-
const normalizedPath =
|
|
2392
|
-
const isUnsafe = filePath.includes("\\") || filePath.includes("\0") ||
|
|
2418
|
+
const normalizedPath = import_node_path15.default.posix.normalize(portablePath);
|
|
2419
|
+
const isUnsafe = filePath.includes("\\") || filePath.includes("\0") || import_node_path15.default.posix.isAbsolute(normalizedPath) || /^[a-zA-Z]:\//.test(normalizedPath) || normalizedPath === ".." || normalizedPath.startsWith("../") || !allowRoot && (normalizedPath === "." || normalizedPath === "");
|
|
2393
2420
|
if (isUnsafe) throw new Error(`${label} "${filePath}" escapes its filesystem source`);
|
|
2394
2421
|
return normalizedPath;
|
|
2395
2422
|
};
|
|
@@ -2399,22 +2426,22 @@ var getSourceRoot = (projectDirectory, source) => {
|
|
|
2399
2426
|
}
|
|
2400
2427
|
const locator = source.source.slice(FILESYSTEM_SOURCE_PREFIX.length);
|
|
2401
2428
|
if (!locator.trim()) throw new Error(`Filesystem federation source "${source.id}" requires a path after "file:".`);
|
|
2402
|
-
return
|
|
2429
|
+
return import_node_path15.default.resolve(projectDirectory, locator);
|
|
2403
2430
|
};
|
|
2404
2431
|
var getCatalogDirectory = async (projectDirectory, source) => {
|
|
2405
2432
|
if (source.ref) throw new Error(`Filesystem federation source "${source.id}" does not support "ref".`);
|
|
2406
2433
|
const sourceRoot = getSourceRoot(projectDirectory, source);
|
|
2407
2434
|
const catalogPath = assertPortableRelativePath(source.path ?? ".", "Catalog path");
|
|
2408
|
-
const catalogDirectory =
|
|
2435
|
+
const catalogDirectory = import_node_path15.default.resolve(sourceRoot, ...catalogPath.split("/"));
|
|
2409
2436
|
if (!isWithinDirectory(sourceRoot, catalogDirectory)) {
|
|
2410
2437
|
throw new Error(`Catalog path "${source.path}" escapes source "${source.id}"`);
|
|
2411
2438
|
}
|
|
2412
2439
|
try {
|
|
2413
|
-
const [realSourceRoot, realCatalogDirectory] = await Promise.all([
|
|
2440
|
+
const [realSourceRoot, realCatalogDirectory] = await Promise.all([import_promises8.default.realpath(sourceRoot), import_promises8.default.realpath(catalogDirectory)]);
|
|
2414
2441
|
if (!isWithinDirectory(realSourceRoot, realCatalogDirectory)) {
|
|
2415
2442
|
throw new Error(`Catalog path "${source.path}" escapes source "${source.id}"`);
|
|
2416
2443
|
}
|
|
2417
|
-
if (!(await
|
|
2444
|
+
if (!(await import_promises8.default.stat(realCatalogDirectory)).isDirectory()) {
|
|
2418
2445
|
throw new Error(`Filesystem federation source "${source.id}" is not a directory: ${catalogDirectory}`);
|
|
2419
2446
|
}
|
|
2420
2447
|
return realCatalogDirectory;
|
|
@@ -2427,12 +2454,12 @@ var getCatalogDirectory = async (projectDirectory, source) => {
|
|
|
2427
2454
|
};
|
|
2428
2455
|
var getArtifactPath = async (catalogDirectory, source, artifactPath) => {
|
|
2429
2456
|
const normalizedPath = assertPortableRelativePath(artifactPath, "Federated artifact path", false);
|
|
2430
|
-
const filePath =
|
|
2457
|
+
const filePath = import_node_path15.default.resolve(catalogDirectory, ...normalizedPath.split("/"));
|
|
2431
2458
|
if (!isWithinDirectory(catalogDirectory, filePath)) {
|
|
2432
2459
|
throw new Error(`Federated artifact path "${artifactPath}" escapes source "${source.id}"`);
|
|
2433
2460
|
}
|
|
2434
2461
|
try {
|
|
2435
|
-
const realFilePath = await
|
|
2462
|
+
const realFilePath = await import_promises8.default.realpath(filePath);
|
|
2436
2463
|
if (!isWithinDirectory(catalogDirectory, realFilePath)) {
|
|
2437
2464
|
throw new Error(`Federated artifact path "${artifactPath}" escapes source "${source.id}"`);
|
|
2438
2465
|
}
|
|
@@ -2452,22 +2479,22 @@ var createFileSystemSourceProvider = (projectDirectory) => ({
|
|
|
2452
2479
|
commit: "local",
|
|
2453
2480
|
includeFederated: false
|
|
2454
2481
|
});
|
|
2455
|
-
const snapshot = (0,
|
|
2482
|
+
const snapshot = (0, import_node_crypto4.createHash)("sha256").update(JSON.stringify(localIndex)).digest("hex").slice(0, 12);
|
|
2456
2483
|
const index = { ...localIndex, commit: `local:${snapshot}` };
|
|
2457
2484
|
const bytes = Buffer.from(JSON.stringify(index));
|
|
2458
2485
|
return { bytes, index, commit: index.commit, generated: true };
|
|
2459
2486
|
},
|
|
2460
2487
|
async fetchContent({ source, path: artifactPath }) {
|
|
2461
2488
|
const catalogDirectory = await getCatalogDirectory(projectDirectory, source);
|
|
2462
|
-
return
|
|
2489
|
+
return import_promises8.default.readFile(await getArtifactPath(catalogDirectory, source, artifactPath));
|
|
2463
2490
|
}
|
|
2464
2491
|
});
|
|
2465
2492
|
|
|
2466
2493
|
// src/federation/github-source-provider.ts
|
|
2467
2494
|
var import_node_child_process = require("child_process");
|
|
2468
|
-
var
|
|
2495
|
+
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
2469
2496
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
2470
|
-
var
|
|
2497
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
2471
2498
|
var import_node_util = require("util");
|
|
2472
2499
|
var import_sdk2 = __toESM(require("@eventcatalog/sdk"), 1);
|
|
2473
2500
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
@@ -2478,8 +2505,8 @@ var parseGitHubSource = (source) => {
|
|
|
2478
2505
|
};
|
|
2479
2506
|
var assertSafeCatalogPath = (source) => {
|
|
2480
2507
|
const catalogPath = source.path ?? ".";
|
|
2481
|
-
const normalized =
|
|
2482
|
-
if (catalogPath.includes("\\") ||
|
|
2508
|
+
const normalized = import_node_path16.default.posix.normalize(catalogPath.replaceAll("\\", "/"));
|
|
2509
|
+
if (catalogPath.includes("\\") || import_node_path16.default.posix.isAbsolute(normalized) || normalized === ".." || normalized.startsWith("../")) {
|
|
2483
2510
|
throw new Error(`Catalog path "${catalogPath}" escapes source "${source.id}"`);
|
|
2484
2511
|
}
|
|
2485
2512
|
};
|
|
@@ -2522,8 +2549,8 @@ var getGitEnvironment = (token) => {
|
|
|
2522
2549
|
};
|
|
2523
2550
|
var createCheckout = (executeFile, token) => async (source, ref, callback) => {
|
|
2524
2551
|
const { owner, repository } = parseGitHubSource(source);
|
|
2525
|
-
const catalogPath =
|
|
2526
|
-
const directory = await
|
|
2552
|
+
const catalogPath = import_node_path16.default.posix.normalize(source.path ?? ".");
|
|
2553
|
+
const directory = await import_promises9.default.mkdtemp(import_node_path16.default.join(import_node_os4.default.tmpdir(), "eventcatalog-federation-"));
|
|
2527
2554
|
const env = getGitEnvironment(token);
|
|
2528
2555
|
try {
|
|
2529
2556
|
const git = (args) => executeFile("git", args, { cwd: directory, env, encoding: "utf8" });
|
|
@@ -2537,22 +2564,22 @@ var createCheckout = (executeFile, token) => async (source, ref, callback) => {
|
|
|
2537
2564
|
await git(["checkout", "--quiet", "--detach", "FETCH_HEAD"]);
|
|
2538
2565
|
return await callback(directory);
|
|
2539
2566
|
} finally {
|
|
2540
|
-
await
|
|
2567
|
+
await import_promises9.default.rm(directory, { recursive: true, force: true });
|
|
2541
2568
|
}
|
|
2542
2569
|
};
|
|
2543
2570
|
var generateIndex = async (source, ref, checkout, executeFile) => checkout(source, ref, async (directory) => {
|
|
2544
2571
|
const { stdout } = await executeFile("git", ["rev-parse", "HEAD"], { cwd: directory, encoding: "utf8" });
|
|
2545
2572
|
const commit = stdout.trim();
|
|
2546
|
-
const catalogDirectory =
|
|
2547
|
-
const relativeCatalogDirectory =
|
|
2548
|
-
if (relativeCatalogDirectory.startsWith("..") ||
|
|
2573
|
+
const catalogDirectory = import_node_path16.default.resolve(directory, source.path ?? ".");
|
|
2574
|
+
const relativeCatalogDirectory = import_node_path16.default.relative(directory, catalogDirectory);
|
|
2575
|
+
if (relativeCatalogDirectory.startsWith("..") || import_node_path16.default.isAbsolute(relativeCatalogDirectory)) {
|
|
2549
2576
|
throw new Error(`Catalog path "${source.path}" escapes source "${source.id}"`);
|
|
2550
2577
|
}
|
|
2551
2578
|
const index = await (0, import_sdk2.default)(catalogDirectory).buildIndex({ source: source.id, commit });
|
|
2552
2579
|
return { bytes: Buffer.from(JSON.stringify(index)), index, commit, generated: true };
|
|
2553
2580
|
});
|
|
2554
2581
|
var fetchPublishedIndex = async (source, ref, fetcher, token) => {
|
|
2555
|
-
const indexPath =
|
|
2582
|
+
const indexPath = import_node_path16.default.posix.join(source.path ?? ".", "catalog.index.json");
|
|
2556
2583
|
const bytes = await fetchBytes(source, ref, indexPath, fetcher, token);
|
|
2557
2584
|
if (!bytes) return void 0;
|
|
2558
2585
|
const index = (0, import_sdk2.parseIndex)(JSON.parse(bytes.toString("utf8")));
|
|
@@ -2575,7 +2602,7 @@ var createGitHubSourceProvider = (options = {}) => {
|
|
|
2575
2602
|
},
|
|
2576
2603
|
async fetchContent({ source, commit, path: artifactPath }) {
|
|
2577
2604
|
assertSafeCatalogPath(source);
|
|
2578
|
-
const catalogPath =
|
|
2605
|
+
const catalogPath = import_node_path16.default.posix.join(source.path ?? ".", artifactPath);
|
|
2579
2606
|
const content = await fetchBytes(source, commit, catalogPath, fetcher, token);
|
|
2580
2607
|
if (!content) throw new Error(`Federated artifact not found for "${source.id}": ${artifactPath}`);
|
|
2581
2608
|
return content;
|
|
@@ -2661,16 +2688,16 @@ var createDiagnosticGraph = (graph, ownershipGraph, remoteSourceIds, localSource
|
|
|
2661
2688
|
var writeLock = async (lockPath, lock) => {
|
|
2662
2689
|
const temporaryPath = `${lockPath}.tmp-${process.pid}`;
|
|
2663
2690
|
try {
|
|
2664
|
-
await
|
|
2691
|
+
await import_promises10.default.writeFile(temporaryPath, `${JSON.stringify(lock, null, 2)}
|
|
2665
2692
|
`, "utf8");
|
|
2666
|
-
await
|
|
2693
|
+
await import_promises10.default.rename(temporaryPath, lockPath);
|
|
2667
2694
|
} finally {
|
|
2668
|
-
await
|
|
2695
|
+
await import_promises10.default.rm(temporaryPath, { force: true });
|
|
2669
2696
|
}
|
|
2670
2697
|
};
|
|
2671
2698
|
var readLock = async (lockPath) => {
|
|
2672
2699
|
try {
|
|
2673
|
-
return JSON.parse(await
|
|
2700
|
+
return JSON.parse(await import_promises10.default.readFile(lockPath, "utf8"));
|
|
2674
2701
|
} catch (error) {
|
|
2675
2702
|
if (error.code === "ENOENT") return void 0;
|
|
2676
2703
|
throw new Error(`Cannot read federation lock at "${lockPath}"`, { cause: error });
|
|
@@ -2678,7 +2705,7 @@ var readLock = async (lockPath) => {
|
|
|
2678
2705
|
};
|
|
2679
2706
|
var pathExists2 = async (filePath) => {
|
|
2680
2707
|
try {
|
|
2681
|
-
await
|
|
2708
|
+
await import_promises10.default.access(filePath);
|
|
2682
2709
|
return true;
|
|
2683
2710
|
} catch (error) {
|
|
2684
2711
|
if (error.code === "ENOENT") return false;
|
|
@@ -2686,8 +2713,8 @@ var pathExists2 = async (filePath) => {
|
|
|
2686
2713
|
}
|
|
2687
2714
|
};
|
|
2688
2715
|
var cleanupPreviousFederation = async (projectDirectory, onProgress) => {
|
|
2689
|
-
const outDir =
|
|
2690
|
-
const lockPath =
|
|
2716
|
+
const outDir = import_node_path17.default.join(projectDirectory, "federated");
|
|
2717
|
+
const lockPath = import_node_path17.default.join(projectDirectory, "eventcatalog.lock");
|
|
2691
2718
|
const previousLock = await readLock(lockPath);
|
|
2692
2719
|
const hadFederatedOutput = await pathExists2(outDir);
|
|
2693
2720
|
const hadLock = previousLock !== void 0;
|
|
@@ -2703,7 +2730,7 @@ var cleanupPreviousFederation = async (projectDirectory, onProgress) => {
|
|
|
2703
2730
|
assets: [],
|
|
2704
2731
|
previousFiles: previousLock?.publicFiles
|
|
2705
2732
|
});
|
|
2706
|
-
await
|
|
2733
|
+
await import_promises10.default.rm(lockPath, { force: true });
|
|
2707
2734
|
return result;
|
|
2708
2735
|
}
|
|
2709
2736
|
);
|
|
@@ -2752,8 +2779,8 @@ var federateCatalog = async (projectDirectory, options = {}) => {
|
|
|
2752
2779
|
throw new Error(`Failed to federate source "${source.id}": ${message}`, { cause: error });
|
|
2753
2780
|
}
|
|
2754
2781
|
}
|
|
2755
|
-
const outDir =
|
|
2756
|
-
const lockPath =
|
|
2782
|
+
const outDir = import_node_path17.default.join(projectDirectory, "federated");
|
|
2783
|
+
const lockPath = import_node_path17.default.join(projectDirectory, "eventcatalog.lock");
|
|
2757
2784
|
const previousLock = await readLock(lockPath);
|
|
2758
2785
|
const resources = resolvedSources.reduce((total, source) => total + source.resolved.index.resources.length, 0);
|
|
2759
2786
|
const remoteIndexes = resolvedSources.map(({ resolved }) => resolved.index);
|
|
@@ -2826,7 +2853,7 @@ var federateCatalog = async (projectDirectory, options = {}) => {
|
|
|
2826
2853
|
lockVersion: 1,
|
|
2827
2854
|
sources: resolvedSources.map(({ config: source, resolved }) => ({
|
|
2828
2855
|
id: source.id,
|
|
2829
|
-
digest: `sha256:${(0,
|
|
2856
|
+
digest: `sha256:${(0, import_node_crypto5.createHash)("sha256").update(resolved.bytes).digest("hex")}`,
|
|
2830
2857
|
commit: resolved.commit,
|
|
2831
2858
|
resolvedAt
|
|
2832
2859
|
})).sort((left, right) => left.id.localeCompare(right.id)),
|
|
@@ -2851,14 +2878,14 @@ var federateCatalog = async (projectDirectory, options = {}) => {
|
|
|
2851
2878
|
|
|
2852
2879
|
// src/eventcatalog.ts
|
|
2853
2880
|
var import_license2 = require("@eventcatalog/license");
|
|
2854
|
-
var currentDir =
|
|
2881
|
+
var currentDir = import_node_path19.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
2855
2882
|
var program = new import_commander.Command().version(VERSION);
|
|
2856
|
-
var dir =
|
|
2857
|
-
var core =
|
|
2858
|
-
var eventCatalogDir =
|
|
2883
|
+
var dir = import_node_path19.default.resolve(process.env.PROJECT_DIR || process.cwd());
|
|
2884
|
+
var core = import_node_path19.default.resolve(process.env.CATALOG_DIR || (0, import_node_path18.join)(dir, ".eventcatalog-core"));
|
|
2885
|
+
var eventCatalogDir = import_node_path19.default.resolve((0, import_node_path18.join)(currentDir, "../eventcatalog/"));
|
|
2859
2886
|
var getInstalledEventCatalogVersion = () => {
|
|
2860
2887
|
try {
|
|
2861
|
-
const pkg = import_fs3.default.readFileSync((0,
|
|
2888
|
+
const pkg = import_fs3.default.readFileSync((0, import_node_path18.join)(dir, "package.json"), "utf8");
|
|
2862
2889
|
const json = JSON.parse(pkg);
|
|
2863
2890
|
return json.dependencies["@eventcatalog/core"];
|
|
2864
2891
|
} catch (error) {
|
|
@@ -2924,12 +2951,12 @@ var startDevPrewarm = ({
|
|
|
2924
2951
|
var buildDevSearchIndex = async ({ config }) => {
|
|
2925
2952
|
const result = await buildSearchIndex({
|
|
2926
2953
|
projectDir: dir,
|
|
2927
|
-
outDir:
|
|
2928
|
-
searchOutputPath:
|
|
2954
|
+
outDir: import_node_path19.default.join(core, "public"),
|
|
2955
|
+
searchOutputPath: import_node_path19.default.join(core, "public", "pagefind"),
|
|
2929
2956
|
config,
|
|
2930
2957
|
isServer: false
|
|
2931
2958
|
});
|
|
2932
|
-
logger.info(`Indexed ${result.records} page(s) into ${
|
|
2959
|
+
logger.info(`Indexed ${result.records} page(s) into ${import_node_path19.default.relative(core, result.outputPath)}`, "search");
|
|
2933
2960
|
};
|
|
2934
2961
|
var warnIfIndexedSearchUsesAuth = async () => {
|
|
2935
2962
|
if (!await isAuthEnabled()) {
|
|
@@ -3044,12 +3071,12 @@ var copyCore = () => {
|
|
|
3044
3071
|
import_fs3.default.cpSync(eventCatalogDir, core, {
|
|
3045
3072
|
recursive: true,
|
|
3046
3073
|
filter: (src) => {
|
|
3047
|
-
const relativePath =
|
|
3048
|
-
const pathParts = relativePath.split(
|
|
3074
|
+
const relativePath = import_node_path19.default.relative(eventCatalogDir, src);
|
|
3075
|
+
const pathParts = relativePath.split(import_node_path19.default.sep);
|
|
3049
3076
|
return !pathParts.some((part) => [".astro", "dist", "node_modules"].includes(part));
|
|
3050
3077
|
}
|
|
3051
3078
|
});
|
|
3052
|
-
const coreNodeModules =
|
|
3079
|
+
const coreNodeModules = import_node_path19.default.join(core, "node_modules");
|
|
3053
3080
|
const installedCoreNodeModules = resolveInstalledCoreNodeModules(currentDir);
|
|
3054
3081
|
linkCoreNodeModules({ coreNodeModules, installedCoreNodeModules });
|
|
3055
3082
|
};
|
|
@@ -3108,8 +3135,8 @@ program.command("dev").description("Run development server of EventCatalog").opt
|
|
|
3108
3135
|
logger.info("Setting up EventCatalog...", "eventcatalog");
|
|
3109
3136
|
const isServer = await isOutputServer();
|
|
3110
3137
|
logger.info(isServer ? "EventCatalog is running in Server Mode" : "EventCatalog is running in Static Mode", "config");
|
|
3111
|
-
if (import_fs3.default.existsSync(
|
|
3112
|
-
import_dotenv.default.config({ path:
|
|
3138
|
+
if (import_fs3.default.existsSync(import_node_path19.default.join(dir, ".env"))) {
|
|
3139
|
+
import_dotenv.default.config({ path: import_node_path19.default.join(dir, ".env") });
|
|
3113
3140
|
}
|
|
3114
3141
|
if (options.debug) {
|
|
3115
3142
|
logger.info("Debug mode enabled", "debug");
|
|
@@ -3129,6 +3156,12 @@ program.command("dev").description("Run development server of EventCatalog").opt
|
|
|
3129
3156
|
);
|
|
3130
3157
|
const isEventCatalogStarter = await (0, import_license2.isEventCatalogStarterEnabled)();
|
|
3131
3158
|
const isEventCatalogScale = await (0, import_license2.isEventCatalogScaleEnabled)();
|
|
3159
|
+
void log_build_default(dir, {
|
|
3160
|
+
isEventCatalogStarterEnabled: isEventCatalogStarter,
|
|
3161
|
+
isEventCatalogScaleEnabled: isEventCatalogScale,
|
|
3162
|
+
isBackstagePluginEnabled: canEmbedPages || isEventCatalogScale,
|
|
3163
|
+
command: "dev"
|
|
3164
|
+
});
|
|
3132
3165
|
if (isServer) {
|
|
3133
3166
|
try {
|
|
3134
3167
|
logger.info("Building fields index...", "fields");
|
|
@@ -3189,8 +3222,8 @@ program.command("build").description("Run build of EventCatalog").action(async (
|
|
|
3189
3222
|
logger.info("Building EventCatalog...", "build");
|
|
3190
3223
|
const isServer = await isOutputServer();
|
|
3191
3224
|
logger.info(isServer ? "EventCatalog is running in Server Mode" : "EventCatalog is running in Static Mode", "config");
|
|
3192
|
-
if (import_fs3.default.existsSync(
|
|
3193
|
-
import_dotenv.default.config({ path:
|
|
3225
|
+
if (import_fs3.default.existsSync(import_node_path19.default.join(dir, ".env"))) {
|
|
3226
|
+
import_dotenv.default.config({ path: import_node_path19.default.join(dir, ".env") });
|
|
3194
3227
|
}
|
|
3195
3228
|
await verifyRequiredFieldsAreInCatalogConfigFile(dir);
|
|
3196
3229
|
copyCore();
|
|
@@ -3204,7 +3237,8 @@ program.command("build").description("Run build of EventCatalog").action(async (
|
|
|
3204
3237
|
await log_build_default(dir, {
|
|
3205
3238
|
isEventCatalogStarterEnabled: isEventCatalogStarter,
|
|
3206
3239
|
isEventCatalogScaleEnabled: isEventCatalogScale,
|
|
3207
|
-
isBackstagePluginEnabled: canEmbedPages || isEventCatalogScale
|
|
3240
|
+
isBackstagePluginEnabled: canEmbedPages || isEventCatalogScale,
|
|
3241
|
+
command: "build"
|
|
3208
3242
|
});
|
|
3209
3243
|
await resolve_catalog_dependencies_default(dir, core);
|
|
3210
3244
|
await runMigrations(dir);
|
|
@@ -3240,7 +3274,7 @@ program.command("build").description("Run build of EventCatalog").action(async (
|
|
|
3240
3274
|
if (await isIndexedSearchEnabled()) {
|
|
3241
3275
|
await warnIfIndexedSearchUsesAuth();
|
|
3242
3276
|
const config = await getEventCatalogConfigFile(dir);
|
|
3243
|
-
const outDir =
|
|
3277
|
+
const outDir = import_node_path19.default.resolve(dir, await getProjectOutDir());
|
|
3244
3278
|
logger.info("Building indexed search...", "search");
|
|
3245
3279
|
const result = await buildSearchIndex({
|
|
3246
3280
|
projectDir: dir,
|
|
@@ -3248,7 +3282,7 @@ program.command("build").description("Run build of EventCatalog").action(async (
|
|
|
3248
3282
|
config,
|
|
3249
3283
|
isServer
|
|
3250
3284
|
});
|
|
3251
|
-
logger.info(`Indexed ${result.records} page(s) into ${
|
|
3285
|
+
logger.info(`Indexed ${result.records} page(s) into ${import_node_path19.default.relative(dir, result.outputPath)}`, "search");
|
|
3252
3286
|
}
|
|
3253
3287
|
});
|
|
3254
3288
|
var previewCatalog = async ({
|
|
@@ -3275,7 +3309,7 @@ var startServerCatalog = async ({
|
|
|
3275
3309
|
isEventCatalogStarter = false,
|
|
3276
3310
|
isEventCatalogScale = false
|
|
3277
3311
|
}) => {
|
|
3278
|
-
const serverEntryPath =
|
|
3312
|
+
const serverEntryPath = import_node_path19.default.join(dir, "dist", "server", "entry.mjs");
|
|
3279
3313
|
await runCommandWithFilteredOutput({
|
|
3280
3314
|
command: `node "${serverEntryPath}"`,
|
|
3281
3315
|
cwd: core,
|
|
@@ -3292,8 +3326,8 @@ var startServerCatalog = async ({
|
|
|
3292
3326
|
program.command("preview").description("Serves the contents of your eventcatalog build directory").action(async (options, command) => {
|
|
3293
3327
|
logger.welcome();
|
|
3294
3328
|
logger.info("Starting preview of your build...", "preview");
|
|
3295
|
-
if (import_fs3.default.existsSync(
|
|
3296
|
-
import_dotenv.default.config({ path:
|
|
3329
|
+
if (import_fs3.default.existsSync(import_node_path19.default.join(dir, ".env"))) {
|
|
3330
|
+
import_dotenv.default.config({ path: import_node_path19.default.join(dir, ".env") });
|
|
3297
3331
|
}
|
|
3298
3332
|
const canEmbedPages = await (0, import_license2.isFeatureEnabled)(
|
|
3299
3333
|
"@eventcatalog/backstage-plugin-eventcatalog",
|
|
@@ -3311,8 +3345,8 @@ program.command("preview").description("Serves the contents of your eventcatalog
|
|
|
3311
3345
|
program.command("start").description("Serves the contents of your eventcatalog build directory").action(async (options, command) => {
|
|
3312
3346
|
logger.welcome();
|
|
3313
3347
|
logger.info("Starting preview of your build...", "preview");
|
|
3314
|
-
if (import_fs3.default.existsSync(
|
|
3315
|
-
import_dotenv.default.config({ path:
|
|
3348
|
+
if (import_fs3.default.existsSync(import_node_path19.default.join(dir, ".env"))) {
|
|
3349
|
+
import_dotenv.default.config({ path: import_node_path19.default.join(dir, ".env") });
|
|
3316
3350
|
}
|
|
3317
3351
|
const canEmbedPages = await (0, import_license2.isFeatureEnabled)(
|
|
3318
3352
|
"@eventcatalog/backstage-plugin-eventcatalog",
|
|
@@ -3339,22 +3373,22 @@ program.command("start").description("Serves the contents of your eventcatalog b
|
|
|
3339
3373
|
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) => {
|
|
3340
3374
|
logger.welcome();
|
|
3341
3375
|
logger.info("Exporting EventCatalog...", "export");
|
|
3342
|
-
if (import_fs3.default.existsSync(
|
|
3343
|
-
import_dotenv.default.config({ path:
|
|
3376
|
+
if (import_fs3.default.existsSync(import_node_path19.default.join(dir, ".env"))) {
|
|
3377
|
+
import_dotenv.default.config({ path: import_node_path19.default.join(dir, ".env") });
|
|
3344
3378
|
}
|
|
3345
3379
|
const { default: initSDK } = await import("@eventcatalog/sdk");
|
|
3346
3380
|
const sdk = initSDK(dir);
|
|
3347
3381
|
const catalog = await sdk.dumpCatalog({ includeMarkdown: options.includeMarkdown });
|
|
3348
|
-
const exportsDir =
|
|
3382
|
+
const exportsDir = import_node_path19.default.join(dir, "exports");
|
|
3349
3383
|
ensureDir(exportsDir);
|
|
3350
3384
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
3351
|
-
const exportFile =
|
|
3385
|
+
const exportFile = import_node_path19.default.join(exportsDir, `catalog-${date}.json`);
|
|
3352
3386
|
import_fs3.default.writeFileSync(exportFile, JSON.stringify(catalog, null, 2), "utf-8");
|
|
3353
3387
|
logger.info(`Catalog exported to ${exportFile}`, "export");
|
|
3354
3388
|
});
|
|
3355
3389
|
program.command("generate [siteDir]").description("Start the generator scripts.").action(async () => {
|
|
3356
|
-
if (import_fs3.default.existsSync(
|
|
3357
|
-
import_dotenv.default.config({ path:
|
|
3390
|
+
if (import_fs3.default.existsSync(import_node_path19.default.join(dir, ".env"))) {
|
|
3391
|
+
import_dotenv.default.config({ path: import_node_path19.default.join(dir, ".env") });
|
|
3358
3392
|
}
|
|
3359
3393
|
await generate(dir);
|
|
3360
3394
|
});
|
|
@@ -3427,7 +3461,7 @@ var reportFederationProgress = (event, verbose = false) => {
|
|
|
3427
3461
|
}
|
|
3428
3462
|
return;
|
|
3429
3463
|
case "hydrating":
|
|
3430
|
-
logger.info(`Hydrating federated content into ${
|
|
3464
|
+
logger.info(`Hydrating federated content into ${import_node_path19.default.relative(dir, event.outDir)}/...`, "federation");
|
|
3431
3465
|
return;
|
|
3432
3466
|
case "hydrate:cache":
|
|
3433
3467
|
if (event.files === 1 || event.files % 25 === 0) {
|
|
@@ -3450,13 +3484,13 @@ var reportFederationProgress = (event, verbose = false) => {
|
|
|
3450
3484
|
`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)`,
|
|
3451
3485
|
"federation"
|
|
3452
3486
|
);
|
|
3453
|
-
logger.info(`Recorded resolved source state in ${
|
|
3487
|
+
logger.info(`Recorded resolved source state in ${import_node_path19.default.relative(dir, event.result.lockPath)}`, "federation");
|
|
3454
3488
|
}
|
|
3455
3489
|
};
|
|
3456
3490
|
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.").option("-v, --verbose", "Show detailed federation diagnostics.").action(async (commandOptions) => {
|
|
3457
3491
|
logger.welcome();
|
|
3458
|
-
if (import_fs3.default.existsSync(
|
|
3459
|
-
import_dotenv.default.config({ path:
|
|
3492
|
+
if (import_fs3.default.existsSync(import_node_path19.default.join(dir, ".env"))) {
|
|
3493
|
+
import_dotenv.default.config({ path: import_node_path19.default.join(dir, ".env") });
|
|
3460
3494
|
}
|
|
3461
3495
|
logger.info("Starting federation...", "federation");
|
|
3462
3496
|
let cleanedPreviousOutput = false;
|