@eventcatalog/core 4.7.3 → 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.
- package/dist/analytics/analytics.cjs +1 -1
- package/dist/analytics/analytics.js +2 -2
- package/dist/analytics/log-build.cjs +1 -1
- package/dist/analytics/log-build.js +3 -3
- package/dist/{chunk-XXJX3WWF.js → chunk-7QTCSRAC.js} +1 -1
- package/dist/chunk-A2RZR3U4.js +29 -0
- package/dist/{chunk-SMDTRRED.js → chunk-FDXJIZ74.js} +1 -1
- package/dist/{chunk-ZR6AH5Z2.js → chunk-RIUHZZRA.js} +4 -4
- package/dist/chunk-SDZQJTJW.js +90 -0
- package/dist/{chunk-V4FAVGI7.js → chunk-TLWM7WRZ.js} +1 -1
- package/dist/{chunk-GINIJSFI.js → chunk-ZIABX6SP.js} +1 -1
- package/dist/{chunk-IALEXWSE.js → chunk-ZXVQXBTT.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +315 -209
- package/dist/eventcatalog.config.d.cts +3 -3
- package/dist/eventcatalog.config.d.ts +3 -3
- package/dist/eventcatalog.js +11 -9
- package/dist/federation/federate.cjs +269 -163
- package/dist/federation/federate.js +3 -1
- package/dist/federation/filesystem-source-provider.cjs +124 -0
- package/dist/federation/filesystem-source-provider.d.cts +7 -0
- package/dist/federation/filesystem-source-provider.d.ts +7 -0
- package/dist/federation/filesystem-source-provider.js +6 -0
- package/dist/federation/source-provider.cjs +265 -0
- package/dist/federation/source-provider.d.cts +11 -0
- package/dist/federation/source-provider.d.ts +11 -0
- package/dist/federation/source-provider.js +8 -0
- 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/package.json +3 -3
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_path16 = 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_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.
|
|
147
|
+
var version = "4.7.4";
|
|
148
148
|
|
|
149
149
|
// src/constants.ts
|
|
150
150
|
var VERSION = version;
|
|
@@ -1310,22 +1310,22 @@ function getAvroTypeName(type) {
|
|
|
1310
1310
|
function walkAvroRecord(schema, prefix, fields) {
|
|
1311
1311
|
if (!schema.fields || !Array.isArray(schema.fields)) return;
|
|
1312
1312
|
for (const field of schema.fields) {
|
|
1313
|
-
const
|
|
1313
|
+
const path17 = prefix ? `${prefix}.${field.name}` : field.name;
|
|
1314
1314
|
const isOptional = Array.isArray(field.type) && field.type.includes("null");
|
|
1315
1315
|
const typeName = getAvroTypeName(field.type);
|
|
1316
1316
|
fields.push({
|
|
1317
|
-
path:
|
|
1317
|
+
path: path17,
|
|
1318
1318
|
type: typeName,
|
|
1319
1319
|
description: field.doc || "",
|
|
1320
1320
|
required: !isOptional
|
|
1321
1321
|
});
|
|
1322
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;
|
|
1323
1323
|
if (innerType) {
|
|
1324
|
-
walkAvroRecord(innerType,
|
|
1324
|
+
walkAvroRecord(innerType, path17, fields);
|
|
1325
1325
|
}
|
|
1326
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;
|
|
1327
1327
|
if (arrayType && typeof arrayType.items === "object" && arrayType.items.type === "record") {
|
|
1328
|
-
walkAvroRecord(arrayType.items, `${
|
|
1328
|
+
walkAvroRecord(arrayType.items, `${path17}[]`, fields);
|
|
1329
1329
|
}
|
|
1330
1330
|
}
|
|
1331
1331
|
}
|
|
@@ -1356,32 +1356,32 @@ function walkJsonSchema(node, prefix, requiredList, rootSchema, fields) {
|
|
|
1356
1356
|
}
|
|
1357
1357
|
if (!node.properties) return;
|
|
1358
1358
|
for (const [name, prop] of Object.entries(node.properties)) {
|
|
1359
|
-
const
|
|
1359
|
+
const path17 = prefix ? `${prefix}.${name}` : name;
|
|
1360
1360
|
const isRequired = requiredList.includes(name);
|
|
1361
1361
|
if (prop.$ref) {
|
|
1362
1362
|
const resolved = resolveLocalRef(prop.$ref, rootSchema);
|
|
1363
1363
|
if (resolved) {
|
|
1364
1364
|
const rawRefType = resolved.type || "object";
|
|
1365
1365
|
const type2 = Array.isArray(rawRefType) ? [...rawRefType].sort().join(" | ") : rawRefType;
|
|
1366
|
-
fields.push({ path:
|
|
1366
|
+
fields.push({ path: path17, type: type2, description: resolved.description || "", required: isRequired });
|
|
1367
1367
|
if (resolved.properties) {
|
|
1368
|
-
walkJsonSchema(resolved,
|
|
1368
|
+
walkJsonSchema(resolved, path17, resolved.required || [], rootSchema, fields);
|
|
1369
1369
|
}
|
|
1370
1370
|
} else {
|
|
1371
|
-
fields.push({ path:
|
|
1371
|
+
fields.push({ path: path17, type: "$ref", description: "", required: isRequired });
|
|
1372
1372
|
}
|
|
1373
1373
|
continue;
|
|
1374
1374
|
}
|
|
1375
1375
|
const rawType = prop.type || (prop.enum ? "enum" : prop.$ref ? "$ref" : "object");
|
|
1376
1376
|
const typeList = Array.isArray(rawType) ? rawType : [rawType];
|
|
1377
1377
|
const type = Array.isArray(rawType) ? [...rawType].sort().join(" | ") : rawType;
|
|
1378
|
-
fields.push({ path:
|
|
1378
|
+
fields.push({ path: path17, type, description: prop.description || "", required: isRequired });
|
|
1379
1379
|
if (typeList.includes("object") && prop.properties) {
|
|
1380
|
-
walkJsonSchema(prop,
|
|
1380
|
+
walkJsonSchema(prop, path17, prop.required || [], rootSchema, fields);
|
|
1381
1381
|
}
|
|
1382
1382
|
if (typeList.includes("array") && prop.items) {
|
|
1383
1383
|
if (prop.items.type === "object" && prop.items.properties) {
|
|
1384
|
-
walkJsonSchema(prop.items, `${
|
|
1384
|
+
walkJsonSchema(prop.items, `${path17}[]`, prop.items.required || [], rootSchema, fields);
|
|
1385
1385
|
}
|
|
1386
1386
|
}
|
|
1387
1387
|
}
|
|
@@ -1900,10 +1900,10 @@ var createAstroDevLineFilter = () => {
|
|
|
1900
1900
|
};
|
|
1901
1901
|
|
|
1902
1902
|
// src/federation/federate.ts
|
|
1903
|
-
var
|
|
1904
|
-
var
|
|
1905
|
-
var
|
|
1906
|
-
var
|
|
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);
|
|
1907
1907
|
|
|
1908
1908
|
// src/federation/content-cache.ts
|
|
1909
1909
|
var import_node_crypto = require("crypto");
|
|
@@ -1946,13 +1946,230 @@ var createFederationContentCache = (projectDirectory, options = {}) => {
|
|
|
1946
1946
|
};
|
|
1947
1947
|
};
|
|
1948
1948
|
|
|
1949
|
+
// src/federation/public-assets.ts
|
|
1950
|
+
var import_node_crypto2 = require("crypto");
|
|
1951
|
+
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
1952
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
1953
|
+
var getContentHash2 = (content) => `sha256:${(0, import_node_crypto2.createHash)("sha256").update(content).digest("hex")}`;
|
|
1954
|
+
var getFileHash = async (filePath) => {
|
|
1955
|
+
try {
|
|
1956
|
+
const stat = await import_promises5.default.lstat(filePath);
|
|
1957
|
+
return stat.isFile() ? getContentHash2(await import_promises5.default.readFile(filePath)) : void 0;
|
|
1958
|
+
} catch (error) {
|
|
1959
|
+
if (error.code === "ENOENT") return void 0;
|
|
1960
|
+
throw error;
|
|
1961
|
+
}
|
|
1962
|
+
};
|
|
1963
|
+
var getSafePath = (directory, relativePath) => {
|
|
1964
|
+
const normalizedPath = import_node_path12.default.posix.normalize(relativePath);
|
|
1965
|
+
const unsafe = relativePath.length === 0 || relativePath.includes("\0") || relativePath.includes("\\") || import_node_path12.default.posix.isAbsolute(relativePath) || /^[a-zA-Z]:\//.test(relativePath) || normalizedPath !== relativePath || normalizedPath === ".." || normalizedPath.startsWith("../");
|
|
1966
|
+
if (unsafe) return void 0;
|
|
1967
|
+
const resolvedDirectory = import_node_path12.default.resolve(directory);
|
|
1968
|
+
const resolvedPath = import_node_path12.default.resolve(resolvedDirectory, relativePath);
|
|
1969
|
+
const relativeResolvedPath = import_node_path12.default.relative(resolvedDirectory, resolvedPath);
|
|
1970
|
+
if (relativeResolvedPath === "" || relativeResolvedPath === ".." || relativeResolvedPath.startsWith(`..${import_node_path12.default.sep}`) || import_node_path12.default.isAbsolute(relativeResolvedPath)) {
|
|
1971
|
+
return void 0;
|
|
1972
|
+
}
|
|
1973
|
+
return resolvedPath;
|
|
1974
|
+
};
|
|
1975
|
+
var listFiles = async (directory, relativeDirectory = "") => {
|
|
1976
|
+
let entries;
|
|
1977
|
+
try {
|
|
1978
|
+
entries = await import_promises5.default.readdir(import_node_path12.default.join(directory, relativeDirectory), { withFileTypes: true });
|
|
1979
|
+
} catch (error) {
|
|
1980
|
+
if (error.code === "ENOENT") return [];
|
|
1981
|
+
throw error;
|
|
1982
|
+
}
|
|
1983
|
+
const files = await Promise.all(
|
|
1984
|
+
entries.map(async (entry) => {
|
|
1985
|
+
const relativePath = import_node_path12.default.join(relativeDirectory, entry.name);
|
|
1986
|
+
if (entry.isDirectory()) return listFiles(directory, relativePath);
|
|
1987
|
+
return entry.isFile() ? [relativePath.split(import_node_path12.default.sep).join("/")] : [];
|
|
1988
|
+
})
|
|
1989
|
+
);
|
|
1990
|
+
return files.flat().sort();
|
|
1991
|
+
};
|
|
1992
|
+
var pathExists = async (filePath) => {
|
|
1993
|
+
try {
|
|
1994
|
+
await import_promises5.default.lstat(filePath);
|
|
1995
|
+
return true;
|
|
1996
|
+
} catch (error) {
|
|
1997
|
+
if (error.code === "ENOENT") return false;
|
|
1998
|
+
throw error;
|
|
1999
|
+
}
|
|
2000
|
+
};
|
|
2001
|
+
var hasBlockingParent = async (publicDirectory, destinationPath) => {
|
|
2002
|
+
let currentPath = import_node_path12.default.dirname(destinationPath);
|
|
2003
|
+
while (currentPath !== publicDirectory) {
|
|
2004
|
+
try {
|
|
2005
|
+
if (!(await import_promises5.default.lstat(currentPath)).isDirectory()) return true;
|
|
2006
|
+
} catch (error) {
|
|
2007
|
+
if (error.code !== "ENOENT") throw error;
|
|
2008
|
+
}
|
|
2009
|
+
currentPath = import_node_path12.default.dirname(currentPath);
|
|
2010
|
+
}
|
|
2011
|
+
return false;
|
|
2012
|
+
};
|
|
2013
|
+
var pruneEmptyDirectories = async (publicDirectory, filePath) => {
|
|
2014
|
+
let currentPath = import_node_path12.default.dirname(filePath);
|
|
2015
|
+
while (currentPath !== publicDirectory) {
|
|
2016
|
+
try {
|
|
2017
|
+
await import_promises5.default.rmdir(currentPath);
|
|
2018
|
+
} catch (error) {
|
|
2019
|
+
if (!["ENOENT", "ENOTEMPTY"].includes(error.code ?? "")) throw error;
|
|
2020
|
+
if (error.code === "ENOTEMPTY") return;
|
|
2021
|
+
}
|
|
2022
|
+
currentPath = import_node_path12.default.dirname(currentPath);
|
|
2023
|
+
}
|
|
2024
|
+
};
|
|
2025
|
+
var composePublicAssets = async ({
|
|
2026
|
+
projectDirectory,
|
|
2027
|
+
federatedDirectory,
|
|
2028
|
+
assets,
|
|
2029
|
+
previousFiles = {},
|
|
2030
|
+
collisionPaths = /* @__PURE__ */ new Set()
|
|
2031
|
+
}) => {
|
|
2032
|
+
const publicDirectory = import_node_path12.default.resolve(projectDirectory, "public");
|
|
2033
|
+
const federatedPublicDirectory = import_node_path12.default.resolve(federatedDirectory, "public");
|
|
2034
|
+
const sourceFiles = await listFiles(federatedPublicDirectory);
|
|
2035
|
+
const sourceFileSet = new Set(sourceFiles);
|
|
2036
|
+
const managedFiles = /* @__PURE__ */ new Set();
|
|
2037
|
+
for (const [relativePath, previousFile] of Object.entries(previousFiles)) {
|
|
2038
|
+
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
2039
|
+
if (destinationPath && await getFileHash(destinationPath) === previousFile.hash) managedFiles.add(relativePath);
|
|
2040
|
+
}
|
|
2041
|
+
let removed = 0;
|
|
2042
|
+
for (const relativePath of managedFiles) {
|
|
2043
|
+
if (sourceFileSet.has(relativePath)) continue;
|
|
2044
|
+
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
2045
|
+
if (!destinationPath) continue;
|
|
2046
|
+
await import_promises5.default.rm(destinationPath, { force: true });
|
|
2047
|
+
await pruneEmptyDirectories(publicDirectory, destinationPath);
|
|
2048
|
+
removed += 1;
|
|
2049
|
+
}
|
|
2050
|
+
const publicAssetsByPath = new Map(
|
|
2051
|
+
assets.filter((asset) => asset.path.startsWith("public/")).map((asset) => [asset.path.slice("public/".length), asset])
|
|
2052
|
+
);
|
|
2053
|
+
const files = {};
|
|
2054
|
+
let copied = 0;
|
|
2055
|
+
let skipped = 0;
|
|
2056
|
+
let overwritten = 0;
|
|
2057
|
+
for (const relativePath of sourceFiles) {
|
|
2058
|
+
const sourcePath = getSafePath(federatedPublicDirectory, relativePath);
|
|
2059
|
+
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
2060
|
+
if (!sourcePath || !destinationPath) throw new Error(`Unsafe federated public asset path "${relativePath}"`);
|
|
2061
|
+
const mainCatalogOwnsPath = await pathExists(destinationPath) && !managedFiles.has(relativePath) || await hasBlockingParent(publicDirectory, destinationPath);
|
|
2062
|
+
if (mainCatalogOwnsPath) {
|
|
2063
|
+
skipped += 1;
|
|
2064
|
+
continue;
|
|
2065
|
+
}
|
|
2066
|
+
const asset = publicAssetsByPath.get(relativePath);
|
|
2067
|
+
if (!asset) throw new Error(`Cannot identify the source of federated public asset "${relativePath}"`);
|
|
2068
|
+
const content = await import_promises5.default.readFile(sourcePath);
|
|
2069
|
+
await import_promises5.default.mkdir(import_node_path12.default.dirname(destinationPath), { recursive: true });
|
|
2070
|
+
await import_promises5.default.writeFile(destinationPath, content);
|
|
2071
|
+
files[relativePath] = { source: asset.resolvedFrom.source, hash: getContentHash2(content) };
|
|
2072
|
+
copied += 1;
|
|
2073
|
+
if (collisionPaths.has(`public/${relativePath}`)) overwritten += 1;
|
|
2074
|
+
}
|
|
2075
|
+
await import_promises5.default.rm(federatedPublicDirectory, { recursive: true, force: true });
|
|
2076
|
+
return { files, copied, skipped, overwritten, removed };
|
|
2077
|
+
};
|
|
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
|
+
|
|
1949
2166
|
// src/federation/github-source-provider.ts
|
|
1950
2167
|
var import_node_child_process = require("child_process");
|
|
1951
|
-
var
|
|
2168
|
+
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
1952
2169
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
1953
|
-
var
|
|
2170
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
1954
2171
|
var import_node_util = require("util");
|
|
1955
|
-
var
|
|
2172
|
+
var import_sdk2 = __toESM(require("@eventcatalog/sdk"), 1);
|
|
1956
2173
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
1957
2174
|
var parseGitHubSource = (source) => {
|
|
1958
2175
|
const match = /^github:([^/]+)\/(.+)$/.exec(source.source);
|
|
@@ -1961,8 +2178,8 @@ var parseGitHubSource = (source) => {
|
|
|
1961
2178
|
};
|
|
1962
2179
|
var assertSafeCatalogPath = (source) => {
|
|
1963
2180
|
const catalogPath = source.path ?? ".";
|
|
1964
|
-
const normalized =
|
|
1965
|
-
if (catalogPath.includes("\\") ||
|
|
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("../")) {
|
|
1966
2183
|
throw new Error(`Catalog path "${catalogPath}" escapes source "${source.id}"`);
|
|
1967
2184
|
}
|
|
1968
2185
|
};
|
|
@@ -2005,8 +2222,8 @@ var getGitEnvironment = (token) => {
|
|
|
2005
2222
|
};
|
|
2006
2223
|
var createCheckout = (executeFile, token) => async (source, ref, callback) => {
|
|
2007
2224
|
const { owner, repository } = parseGitHubSource(source);
|
|
2008
|
-
const catalogPath =
|
|
2009
|
-
const directory = await
|
|
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-"));
|
|
2010
2227
|
const env = getGitEnvironment(token);
|
|
2011
2228
|
try {
|
|
2012
2229
|
const git = (args) => executeFile("git", args, { cwd: directory, env, encoding: "utf8" });
|
|
@@ -2020,25 +2237,25 @@ var createCheckout = (executeFile, token) => async (source, ref, callback) => {
|
|
|
2020
2237
|
await git(["checkout", "--quiet", "--detach", "FETCH_HEAD"]);
|
|
2021
2238
|
return await callback(directory);
|
|
2022
2239
|
} finally {
|
|
2023
|
-
await
|
|
2240
|
+
await import_promises7.default.rm(directory, { recursive: true, force: true });
|
|
2024
2241
|
}
|
|
2025
2242
|
};
|
|
2026
2243
|
var generateIndex = async (source, ref, checkout, executeFile) => checkout(source, ref, async (directory) => {
|
|
2027
2244
|
const { stdout } = await executeFile("git", ["rev-parse", "HEAD"], { cwd: directory, encoding: "utf8" });
|
|
2028
2245
|
const commit = stdout.trim();
|
|
2029
|
-
const catalogDirectory =
|
|
2030
|
-
const relativeCatalogDirectory =
|
|
2031
|
-
if (relativeCatalogDirectory.startsWith("..") ||
|
|
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)) {
|
|
2032
2249
|
throw new Error(`Catalog path "${source.path}" escapes source "${source.id}"`);
|
|
2033
2250
|
}
|
|
2034
|
-
const index = await (0,
|
|
2251
|
+
const index = await (0, import_sdk2.default)(catalogDirectory).buildIndex({ source: source.id, commit });
|
|
2035
2252
|
return { bytes: Buffer.from(JSON.stringify(index)), index, commit, generated: true };
|
|
2036
2253
|
});
|
|
2037
2254
|
var fetchPublishedIndex = async (source, ref, fetcher, token) => {
|
|
2038
|
-
const indexPath =
|
|
2255
|
+
const indexPath = import_node_path14.default.posix.join(source.path ?? ".", "catalog.index.json");
|
|
2039
2256
|
const bytes = await fetchBytes(source, ref, indexPath, fetcher, token);
|
|
2040
2257
|
if (!bytes) return void 0;
|
|
2041
|
-
const index = (0,
|
|
2258
|
+
const index = (0, import_sdk2.parseIndex)(JSON.parse(bytes.toString("utf8")));
|
|
2042
2259
|
if (index.source !== source.id) {
|
|
2043
2260
|
throw new Error(`Published index source "${index.source}" does not match configured id "${source.id}"`);
|
|
2044
2261
|
}
|
|
@@ -2058,7 +2275,7 @@ var createGitHubSourceProvider = (options = {}) => {
|
|
|
2058
2275
|
},
|
|
2059
2276
|
async fetchContent({ source, commit, path: artifactPath }) {
|
|
2060
2277
|
assertSafeCatalogPath(source);
|
|
2061
|
-
const catalogPath =
|
|
2278
|
+
const catalogPath = import_node_path14.default.posix.join(source.path ?? ".", artifactPath);
|
|
2062
2279
|
const content = await fetchBytes(source, commit, catalogPath, fetcher, token);
|
|
2063
2280
|
if (!content) throw new Error(`Federated artifact not found for "${source.id}": ${artifactPath}`);
|
|
2064
2281
|
return content;
|
|
@@ -2066,134 +2283,23 @@ var createGitHubSourceProvider = (options = {}) => {
|
|
|
2066
2283
|
};
|
|
2067
2284
|
};
|
|
2068
2285
|
|
|
2069
|
-
// src/federation/
|
|
2070
|
-
var
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
const normalizedPath = import_node_path13.default.posix.normalize(relativePath);
|
|
2085
|
-
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("../");
|
|
2086
|
-
if (unsafe) return void 0;
|
|
2087
|
-
const resolvedDirectory = import_node_path13.default.resolve(directory);
|
|
2088
|
-
const resolvedPath = import_node_path13.default.resolve(resolvedDirectory, relativePath);
|
|
2089
|
-
const relativeResolvedPath = import_node_path13.default.relative(resolvedDirectory, resolvedPath);
|
|
2090
|
-
if (relativeResolvedPath === "" || relativeResolvedPath === ".." || relativeResolvedPath.startsWith(`..${import_node_path13.default.sep}`) || import_node_path13.default.isAbsolute(relativeResolvedPath)) {
|
|
2091
|
-
return void 0;
|
|
2092
|
-
}
|
|
2093
|
-
return resolvedPath;
|
|
2094
|
-
};
|
|
2095
|
-
var listFiles = async (directory, relativeDirectory = "") => {
|
|
2096
|
-
let entries;
|
|
2097
|
-
try {
|
|
2098
|
-
entries = await import_promises6.default.readdir(import_node_path13.default.join(directory, relativeDirectory), { withFileTypes: true });
|
|
2099
|
-
} catch (error) {
|
|
2100
|
-
if (error.code === "ENOENT") return [];
|
|
2101
|
-
throw error;
|
|
2102
|
-
}
|
|
2103
|
-
const files = await Promise.all(
|
|
2104
|
-
entries.map(async (entry) => {
|
|
2105
|
-
const relativePath = import_node_path13.default.join(relativeDirectory, entry.name);
|
|
2106
|
-
if (entry.isDirectory()) return listFiles(directory, relativePath);
|
|
2107
|
-
return entry.isFile() ? [relativePath.split(import_node_path13.default.sep).join("/")] : [];
|
|
2108
|
-
})
|
|
2109
|
-
);
|
|
2110
|
-
return files.flat().sort();
|
|
2111
|
-
};
|
|
2112
|
-
var pathExists = async (filePath) => {
|
|
2113
|
-
try {
|
|
2114
|
-
await import_promises6.default.lstat(filePath);
|
|
2115
|
-
return true;
|
|
2116
|
-
} catch (error) {
|
|
2117
|
-
if (error.code === "ENOENT") return false;
|
|
2118
|
-
throw error;
|
|
2119
|
-
}
|
|
2120
|
-
};
|
|
2121
|
-
var hasBlockingParent = async (publicDirectory, destinationPath) => {
|
|
2122
|
-
let currentPath = import_node_path13.default.dirname(destinationPath);
|
|
2123
|
-
while (currentPath !== publicDirectory) {
|
|
2124
|
-
try {
|
|
2125
|
-
if (!(await import_promises6.default.lstat(currentPath)).isDirectory()) return true;
|
|
2126
|
-
} catch (error) {
|
|
2127
|
-
if (error.code !== "ENOENT") throw error;
|
|
2128
|
-
}
|
|
2129
|
-
currentPath = import_node_path13.default.dirname(currentPath);
|
|
2130
|
-
}
|
|
2131
|
-
return false;
|
|
2132
|
-
};
|
|
2133
|
-
var pruneEmptyDirectories = async (publicDirectory, filePath) => {
|
|
2134
|
-
let currentPath = import_node_path13.default.dirname(filePath);
|
|
2135
|
-
while (currentPath !== publicDirectory) {
|
|
2136
|
-
try {
|
|
2137
|
-
await import_promises6.default.rmdir(currentPath);
|
|
2138
|
-
} catch (error) {
|
|
2139
|
-
if (!["ENOENT", "ENOTEMPTY"].includes(error.code ?? "")) throw error;
|
|
2140
|
-
if (error.code === "ENOTEMPTY") return;
|
|
2141
|
-
}
|
|
2142
|
-
currentPath = import_node_path13.default.dirname(currentPath);
|
|
2143
|
-
}
|
|
2144
|
-
};
|
|
2145
|
-
var composePublicAssets = async ({
|
|
2146
|
-
projectDirectory,
|
|
2147
|
-
federatedDirectory,
|
|
2148
|
-
assets,
|
|
2149
|
-
previousFiles = {},
|
|
2150
|
-
collisionPaths = /* @__PURE__ */ new Set()
|
|
2151
|
-
}) => {
|
|
2152
|
-
const publicDirectory = import_node_path13.default.resolve(projectDirectory, "public");
|
|
2153
|
-
const federatedPublicDirectory = import_node_path13.default.resolve(federatedDirectory, "public");
|
|
2154
|
-
const sourceFiles = await listFiles(federatedPublicDirectory);
|
|
2155
|
-
const sourceFileSet = new Set(sourceFiles);
|
|
2156
|
-
const managedFiles = /* @__PURE__ */ new Set();
|
|
2157
|
-
for (const [relativePath, previousFile] of Object.entries(previousFiles)) {
|
|
2158
|
-
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
2159
|
-
if (destinationPath && await getFileHash(destinationPath) === previousFile.hash) managedFiles.add(relativePath);
|
|
2160
|
-
}
|
|
2161
|
-
let removed = 0;
|
|
2162
|
-
for (const relativePath of managedFiles) {
|
|
2163
|
-
if (sourceFileSet.has(relativePath)) continue;
|
|
2164
|
-
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
2165
|
-
if (!destinationPath) continue;
|
|
2166
|
-
await import_promises6.default.rm(destinationPath, { force: true });
|
|
2167
|
-
await pruneEmptyDirectories(publicDirectory, destinationPath);
|
|
2168
|
-
removed += 1;
|
|
2169
|
-
}
|
|
2170
|
-
const publicAssetsByPath = new Map(
|
|
2171
|
-
assets.filter((asset) => asset.path.startsWith("public/")).map((asset) => [asset.path.slice("public/".length), asset])
|
|
2172
|
-
);
|
|
2173
|
-
const files = {};
|
|
2174
|
-
let copied = 0;
|
|
2175
|
-
let skipped = 0;
|
|
2176
|
-
let overwritten = 0;
|
|
2177
|
-
for (const relativePath of sourceFiles) {
|
|
2178
|
-
const sourcePath = getSafePath(federatedPublicDirectory, relativePath);
|
|
2179
|
-
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
2180
|
-
if (!sourcePath || !destinationPath) throw new Error(`Unsafe federated public asset path "${relativePath}"`);
|
|
2181
|
-
const mainCatalogOwnsPath = await pathExists(destinationPath) && !managedFiles.has(relativePath) || await hasBlockingParent(publicDirectory, destinationPath);
|
|
2182
|
-
if (mainCatalogOwnsPath) {
|
|
2183
|
-
skipped += 1;
|
|
2184
|
-
continue;
|
|
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);
|
|
2185
2301
|
}
|
|
2186
|
-
|
|
2187
|
-
if (!asset) throw new Error(`Cannot identify the source of federated public asset "${relativePath}"`);
|
|
2188
|
-
const content = await import_promises6.default.readFile(sourcePath);
|
|
2189
|
-
await import_promises6.default.mkdir(import_node_path13.default.dirname(destinationPath), { recursive: true });
|
|
2190
|
-
await import_promises6.default.writeFile(destinationPath, content);
|
|
2191
|
-
files[relativePath] = { source: asset.resolvedFrom.source, hash: getContentHash2(content) };
|
|
2192
|
-
copied += 1;
|
|
2193
|
-
if (collisionPaths.has(`public/${relativePath}`)) overwritten += 1;
|
|
2194
|
-
}
|
|
2195
|
-
await import_promises6.default.rm(federatedPublicDirectory, { recursive: true, force: true });
|
|
2196
|
-
return { files, copied, skipped, overwritten, removed };
|
|
2302
|
+
};
|
|
2197
2303
|
};
|
|
2198
2304
|
|
|
2199
2305
|
// src/federation/federate.ts
|
|
@@ -2218,16 +2324,16 @@ var validateSources = (sources) => {
|
|
|
2218
2324
|
var writeLock = async (lockPath, lock) => {
|
|
2219
2325
|
const temporaryPath = `${lockPath}.tmp-${process.pid}`;
|
|
2220
2326
|
try {
|
|
2221
|
-
await
|
|
2327
|
+
await import_promises8.default.writeFile(temporaryPath, `${JSON.stringify(lock, null, 2)}
|
|
2222
2328
|
`, "utf8");
|
|
2223
|
-
await
|
|
2329
|
+
await import_promises8.default.rename(temporaryPath, lockPath);
|
|
2224
2330
|
} finally {
|
|
2225
|
-
await
|
|
2331
|
+
await import_promises8.default.rm(temporaryPath, { force: true });
|
|
2226
2332
|
}
|
|
2227
2333
|
};
|
|
2228
2334
|
var readLock = async (lockPath) => {
|
|
2229
2335
|
try {
|
|
2230
|
-
return JSON.parse(await
|
|
2336
|
+
return JSON.parse(await import_promises8.default.readFile(lockPath, "utf8"));
|
|
2231
2337
|
} catch (error) {
|
|
2232
2338
|
if (error.code === "ENOENT") return void 0;
|
|
2233
2339
|
throw new Error(`Cannot read federation lock at "${lockPath}"`, { cause: error });
|
|
@@ -2235,7 +2341,7 @@ var readLock = async (lockPath) => {
|
|
|
2235
2341
|
};
|
|
2236
2342
|
var pathExists2 = async (filePath) => {
|
|
2237
2343
|
try {
|
|
2238
|
-
await
|
|
2344
|
+
await import_promises8.default.access(filePath);
|
|
2239
2345
|
return true;
|
|
2240
2346
|
} catch (error) {
|
|
2241
2347
|
if (error.code === "ENOENT") return false;
|
|
@@ -2243,20 +2349,20 @@ var pathExists2 = async (filePath) => {
|
|
|
2243
2349
|
}
|
|
2244
2350
|
};
|
|
2245
2351
|
var cleanupPreviousFederation = async (projectDirectory, onProgress) => {
|
|
2246
|
-
const outDir =
|
|
2247
|
-
const lockPath =
|
|
2352
|
+
const outDir = import_node_path15.default.join(projectDirectory, "federated");
|
|
2353
|
+
const lockPath = import_node_path15.default.join(projectDirectory, "eventcatalog.lock");
|
|
2248
2354
|
const previousLock = await readLock(lockPath);
|
|
2249
2355
|
const hadFederatedOutput = await pathExists2(outDir);
|
|
2250
2356
|
const hadLock = previousLock !== void 0;
|
|
2251
2357
|
if (!hadFederatedOutput && !hadLock) return;
|
|
2252
|
-
await
|
|
2358
|
+
await import_promises8.default.rm(outDir, { recursive: true, force: true });
|
|
2253
2359
|
const publicResult = await composePublicAssets({
|
|
2254
2360
|
projectDirectory,
|
|
2255
2361
|
federatedDirectory: outDir,
|
|
2256
2362
|
assets: [],
|
|
2257
2363
|
previousFiles: previousLock?.publicFiles
|
|
2258
2364
|
});
|
|
2259
|
-
await
|
|
2365
|
+
await import_promises8.default.rm(lockPath, { force: true });
|
|
2260
2366
|
onProgress?.({
|
|
2261
2367
|
type: "cleanup:complete",
|
|
2262
2368
|
federated: hadFederatedOutput,
|
|
@@ -2279,7 +2385,7 @@ var federateCatalog = async (projectDirectory, options = {}) => {
|
|
|
2279
2385
|
}
|
|
2280
2386
|
validateSources(sources);
|
|
2281
2387
|
if (options.useCache === false) options.onProgress?.({ type: "cache:disabled" });
|
|
2282
|
-
const provider = options.provider ??
|
|
2388
|
+
const provider = options.provider ?? createFederationSourceProvider(projectDirectory);
|
|
2283
2389
|
const resolvedSources = [];
|
|
2284
2390
|
for (const [index, source] of sources.entries()) {
|
|
2285
2391
|
const current = index + 1;
|
|
@@ -2301,13 +2407,13 @@ var federateCatalog = async (projectDirectory, options = {}) => {
|
|
|
2301
2407
|
throw new Error(`Failed to federate source "${source.id}": ${message}`, { cause: error });
|
|
2302
2408
|
}
|
|
2303
2409
|
}
|
|
2304
|
-
const outDir =
|
|
2305
|
-
const lockPath =
|
|
2410
|
+
const outDir = import_node_path15.default.join(projectDirectory, "federated");
|
|
2411
|
+
const lockPath = import_node_path15.default.join(projectDirectory, "eventcatalog.lock");
|
|
2306
2412
|
const previousLock = await readLock(lockPath);
|
|
2307
2413
|
const resources = resolvedSources.reduce((total, source) => total + source.resolved.index.resources.length, 0);
|
|
2308
2414
|
const remoteIndexes = resolvedSources.map(({ resolved }) => resolved.index);
|
|
2309
2415
|
options.onProgress?.({ type: "local:start" });
|
|
2310
|
-
const localIndex = await (0,
|
|
2416
|
+
const localIndex = await (0, import_sdk3.default)(projectDirectory).buildIndex({
|
|
2311
2417
|
source: config.cId,
|
|
2312
2418
|
commit: "local",
|
|
2313
2419
|
hashContent: false,
|
|
@@ -2315,18 +2421,18 @@ var federateCatalog = async (projectDirectory, options = {}) => {
|
|
|
2315
2421
|
});
|
|
2316
2422
|
options.onProgress?.({ type: "local:complete", resources: localIndex.resources.length });
|
|
2317
2423
|
options.onProgress?.({ type: "resolving", resources, localResources: localIndex.resources.length });
|
|
2318
|
-
const ownershipGraph = (0,
|
|
2424
|
+
const ownershipGraph = (0, import_sdk3.resolve)([localIndex, ...remoteIndexes]);
|
|
2319
2425
|
if (ownershipGraph.conflicts.length > 0) {
|
|
2320
2426
|
options.onProgress?.({ type: "resolved", graph: ownershipGraph });
|
|
2321
2427
|
throw new FederationConflictError(ownershipGraph.conflicts);
|
|
2322
2428
|
}
|
|
2323
|
-
const graph = (0,
|
|
2429
|
+
const graph = (0, import_sdk3.resolve)(remoteIndexes);
|
|
2324
2430
|
options.onProgress?.({ type: "resolved", graph });
|
|
2325
2431
|
const sourcesById = new Map(sources.map((source) => [source.id, source]));
|
|
2326
2432
|
options.onProgress?.({ type: "hydrating", outDir });
|
|
2327
2433
|
let hydratedFiles = 0;
|
|
2328
2434
|
let cachedFiles = 0;
|
|
2329
|
-
const hydrateResult = await (0,
|
|
2435
|
+
const hydrateResult = await (0, import_sdk3.hydrate)(graph, {
|
|
2330
2436
|
outDir,
|
|
2331
2437
|
cache: createFederationContentCache(projectDirectory, {
|
|
2332
2438
|
read: options.useCache !== false,
|
|
@@ -2360,7 +2466,7 @@ var federateCatalog = async (projectDirectory, options = {}) => {
|
|
|
2360
2466
|
lockVersion: 1,
|
|
2361
2467
|
sources: resolvedSources.map(({ config: source, resolved }) => ({
|
|
2362
2468
|
id: source.id,
|
|
2363
|
-
digest: `sha256:${(0,
|
|
2469
|
+
digest: `sha256:${(0, import_node_crypto4.createHash)("sha256").update(resolved.bytes).digest("hex")}`,
|
|
2364
2470
|
commit: resolved.commit,
|
|
2365
2471
|
resolvedAt
|
|
2366
2472
|
})).sort((left, right) => left.id.localeCompare(right.id)),
|
|
@@ -2381,14 +2487,14 @@ var federateCatalog = async (projectDirectory, options = {}) => {
|
|
|
2381
2487
|
|
|
2382
2488
|
// src/eventcatalog.ts
|
|
2383
2489
|
var import_license = require("@eventcatalog/license");
|
|
2384
|
-
var currentDir =
|
|
2490
|
+
var currentDir = import_node_path17.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
2385
2491
|
var program = new import_commander.Command().version(VERSION);
|
|
2386
|
-
var dir =
|
|
2387
|
-
var core =
|
|
2388
|
-
var eventCatalogDir =
|
|
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/"));
|
|
2389
2495
|
var getInstalledEventCatalogVersion = () => {
|
|
2390
2496
|
try {
|
|
2391
|
-
const pkg = import_fs3.default.readFileSync((0,
|
|
2497
|
+
const pkg = import_fs3.default.readFileSync((0, import_node_path16.join)(dir, "package.json"), "utf8");
|
|
2392
2498
|
const json = JSON.parse(pkg);
|
|
2393
2499
|
return json.dependencies["@eventcatalog/core"];
|
|
2394
2500
|
} catch (error) {
|
|
@@ -2454,12 +2560,12 @@ var startDevPrewarm = ({
|
|
|
2454
2560
|
var buildDevSearchIndex = async ({ config }) => {
|
|
2455
2561
|
const result = await buildSearchIndex({
|
|
2456
2562
|
projectDir: dir,
|
|
2457
|
-
outDir:
|
|
2458
|
-
searchOutputPath:
|
|
2563
|
+
outDir: import_node_path17.default.join(core, "public"),
|
|
2564
|
+
searchOutputPath: import_node_path17.default.join(core, "public", "pagefind"),
|
|
2459
2565
|
config,
|
|
2460
2566
|
isServer: false
|
|
2461
2567
|
});
|
|
2462
|
-
logger.info(`Indexed ${result.records} page(s) into ${
|
|
2568
|
+
logger.info(`Indexed ${result.records} page(s) into ${import_node_path17.default.relative(core, result.outputPath)}`, "search");
|
|
2463
2569
|
};
|
|
2464
2570
|
var warnIfIndexedSearchUsesAuth = async () => {
|
|
2465
2571
|
if (!await isAuthEnabled()) {
|
|
@@ -2574,12 +2680,12 @@ var copyCore = () => {
|
|
|
2574
2680
|
import_fs3.default.cpSync(eventCatalogDir, core, {
|
|
2575
2681
|
recursive: true,
|
|
2576
2682
|
filter: (src) => {
|
|
2577
|
-
const relativePath =
|
|
2578
|
-
const pathParts = relativePath.split(
|
|
2683
|
+
const relativePath = import_node_path17.default.relative(eventCatalogDir, src);
|
|
2684
|
+
const pathParts = relativePath.split(import_node_path17.default.sep);
|
|
2579
2685
|
return !pathParts.some((part) => [".astro", "dist", "node_modules"].includes(part));
|
|
2580
2686
|
}
|
|
2581
2687
|
});
|
|
2582
|
-
const coreNodeModules =
|
|
2688
|
+
const coreNodeModules = import_node_path17.default.join(core, "node_modules");
|
|
2583
2689
|
const installedCoreNodeModules = resolveInstalledCoreNodeModules(currentDir);
|
|
2584
2690
|
linkCoreNodeModules({ coreNodeModules, installedCoreNodeModules });
|
|
2585
2691
|
};
|
|
@@ -2638,8 +2744,8 @@ program.command("dev").description("Run development server of EventCatalog").opt
|
|
|
2638
2744
|
logger.info("Setting up EventCatalog...", "eventcatalog");
|
|
2639
2745
|
const isServer = await isOutputServer();
|
|
2640
2746
|
logger.info(isServer ? "EventCatalog is running in Server Mode" : "EventCatalog is running in Static Mode", "config");
|
|
2641
|
-
if (import_fs3.default.existsSync(
|
|
2642
|
-
import_dotenv.default.config({ path:
|
|
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") });
|
|
2643
2749
|
}
|
|
2644
2750
|
if (options.debug) {
|
|
2645
2751
|
logger.info("Debug mode enabled", "debug");
|
|
@@ -2719,8 +2825,8 @@ program.command("build").description("Run build of EventCatalog").action(async (
|
|
|
2719
2825
|
logger.info("Building EventCatalog...", "build");
|
|
2720
2826
|
const isServer = await isOutputServer();
|
|
2721
2827
|
logger.info(isServer ? "EventCatalog is running in Server Mode" : "EventCatalog is running in Static Mode", "config");
|
|
2722
|
-
if (import_fs3.default.existsSync(
|
|
2723
|
-
import_dotenv.default.config({ path:
|
|
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") });
|
|
2724
2830
|
}
|
|
2725
2831
|
await verifyRequiredFieldsAreInCatalogConfigFile(dir);
|
|
2726
2832
|
copyCore();
|
|
@@ -2770,7 +2876,7 @@ program.command("build").description("Run build of EventCatalog").action(async (
|
|
|
2770
2876
|
if (await isIndexedSearchEnabled()) {
|
|
2771
2877
|
await warnIfIndexedSearchUsesAuth();
|
|
2772
2878
|
const config = await getEventCatalogConfigFile(dir);
|
|
2773
|
-
const outDir =
|
|
2879
|
+
const outDir = import_node_path17.default.resolve(dir, await getProjectOutDir());
|
|
2774
2880
|
logger.info("Building indexed search...", "search");
|
|
2775
2881
|
const result = await buildSearchIndex({
|
|
2776
2882
|
projectDir: dir,
|
|
@@ -2778,7 +2884,7 @@ program.command("build").description("Run build of EventCatalog").action(async (
|
|
|
2778
2884
|
config,
|
|
2779
2885
|
isServer
|
|
2780
2886
|
});
|
|
2781
|
-
logger.info(`Indexed ${result.records} page(s) into ${
|
|
2887
|
+
logger.info(`Indexed ${result.records} page(s) into ${import_node_path17.default.relative(dir, result.outputPath)}`, "search");
|
|
2782
2888
|
}
|
|
2783
2889
|
});
|
|
2784
2890
|
var previewCatalog = async ({
|
|
@@ -2805,7 +2911,7 @@ var startServerCatalog = async ({
|
|
|
2805
2911
|
isEventCatalogStarter = false,
|
|
2806
2912
|
isEventCatalogScale = false
|
|
2807
2913
|
}) => {
|
|
2808
|
-
const serverEntryPath =
|
|
2914
|
+
const serverEntryPath = import_node_path17.default.join(dir, "dist", "server", "entry.mjs");
|
|
2809
2915
|
await runCommandWithFilteredOutput({
|
|
2810
2916
|
command: `node "${serverEntryPath}"`,
|
|
2811
2917
|
cwd: core,
|
|
@@ -2822,8 +2928,8 @@ var startServerCatalog = async ({
|
|
|
2822
2928
|
program.command("preview").description("Serves the contents of your eventcatalog build directory").action(async (options, command) => {
|
|
2823
2929
|
logger.welcome();
|
|
2824
2930
|
logger.info("Starting preview of your build...", "preview");
|
|
2825
|
-
if (import_fs3.default.existsSync(
|
|
2826
|
-
import_dotenv.default.config({ path:
|
|
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") });
|
|
2827
2933
|
}
|
|
2828
2934
|
const canEmbedPages = await (0, import_license.isFeatureEnabled)(
|
|
2829
2935
|
"@eventcatalog/backstage-plugin-eventcatalog",
|
|
@@ -2841,8 +2947,8 @@ program.command("preview").description("Serves the contents of your eventcatalog
|
|
|
2841
2947
|
program.command("start").description("Serves the contents of your eventcatalog build directory").action(async (options, command) => {
|
|
2842
2948
|
logger.welcome();
|
|
2843
2949
|
logger.info("Starting preview of your build...", "preview");
|
|
2844
|
-
if (import_fs3.default.existsSync(
|
|
2845
|
-
import_dotenv.default.config({ path:
|
|
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") });
|
|
2846
2952
|
}
|
|
2847
2953
|
const canEmbedPages = await (0, import_license.isFeatureEnabled)(
|
|
2848
2954
|
"@eventcatalog/backstage-plugin-eventcatalog",
|
|
@@ -2869,22 +2975,22 @@ program.command("start").description("Serves the contents of your eventcatalog b
|
|
|
2869
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) => {
|
|
2870
2976
|
logger.welcome();
|
|
2871
2977
|
logger.info("Exporting EventCatalog...", "export");
|
|
2872
|
-
if (import_fs3.default.existsSync(
|
|
2873
|
-
import_dotenv.default.config({ path:
|
|
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") });
|
|
2874
2980
|
}
|
|
2875
2981
|
const { default: initSDK } = await import("@eventcatalog/sdk");
|
|
2876
2982
|
const sdk = initSDK(dir);
|
|
2877
2983
|
const catalog = await sdk.dumpCatalog({ includeMarkdown: options.includeMarkdown });
|
|
2878
|
-
const exportsDir =
|
|
2984
|
+
const exportsDir = import_node_path17.default.join(dir, "exports");
|
|
2879
2985
|
ensureDir(exportsDir);
|
|
2880
2986
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
2881
|
-
const exportFile =
|
|
2987
|
+
const exportFile = import_node_path17.default.join(exportsDir, `catalog-${date}.json`);
|
|
2882
2988
|
import_fs3.default.writeFileSync(exportFile, JSON.stringify(catalog, null, 2), "utf-8");
|
|
2883
2989
|
logger.info(`Catalog exported to ${exportFile}`, "export");
|
|
2884
2990
|
});
|
|
2885
2991
|
program.command("generate [siteDir]").description("Start the generator scripts.").action(async () => {
|
|
2886
|
-
if (import_fs3.default.existsSync(
|
|
2887
|
-
import_dotenv.default.config({ path:
|
|
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") });
|
|
2888
2994
|
}
|
|
2889
2995
|
await generate(dir);
|
|
2890
2996
|
});
|
|
@@ -2959,7 +3065,7 @@ var reportFederationProgress = (event) => {
|
|
|
2959
3065
|
}
|
|
2960
3066
|
return;
|
|
2961
3067
|
case "hydrating":
|
|
2962
|
-
logger.info(`Hydrating federated content into ${
|
|
3068
|
+
logger.info(`Hydrating federated content into ${import_node_path17.default.relative(dir, event.outDir)}/...`, "federation");
|
|
2963
3069
|
return;
|
|
2964
3070
|
case "hydrate:cache":
|
|
2965
3071
|
if (event.files === 1 || event.files % 25 === 0) {
|
|
@@ -2988,13 +3094,13 @@ var reportFederationProgress = (event) => {
|
|
|
2988
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)`,
|
|
2989
3095
|
"federation"
|
|
2990
3096
|
);
|
|
2991
|
-
logger.info(`Pinned source commits in ${
|
|
3097
|
+
logger.info(`Pinned source commits in ${import_node_path17.default.relative(dir, event.result.lockPath)}`, "federation");
|
|
2992
3098
|
}
|
|
2993
3099
|
};
|
|
2994
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) => {
|
|
2995
3101
|
logger.welcome();
|
|
2996
|
-
if (import_fs3.default.existsSync(
|
|
2997
|
-
import_dotenv.default.config({ path:
|
|
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") });
|
|
2998
3104
|
}
|
|
2999
3105
|
logger.info("Starting federation...", "federation");
|
|
3000
3106
|
let cleanedPreviousOutput = false;
|