@eventcatalog/core 4.6.1 → 4.6.3
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-352FGP6W.js +123 -0
- package/dist/{chunk-N3YKQTGX.js → chunk-4BBXOL6K.js} +1 -1
- package/dist/{chunk-Y7JJ2B3L.js → chunk-54KFOI6Z.js} +3 -3
- package/dist/chunk-5EPNFDT5.js +133 -0
- package/dist/{chunk-MTXVQ4VP.js → chunk-FZJDCQZE.js} +1 -1
- package/dist/{chunk-X7XI7NEP.js → chunk-LB5VXS6X.js} +1 -1
- package/dist/{chunk-U6VOVEVZ.js → chunk-PWY4SP6L.js} +1 -1
- package/dist/chunk-R7Z5ALYI.js +44 -0
- package/dist/chunk-ZR6AH5Z2.js +204 -0
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/eventcatalog.cjs +651 -51
- package/dist/eventcatalog.config.d.cts +18 -1
- package/dist/eventcatalog.config.d.ts +18 -1
- package/dist/eventcatalog.js +134 -7
- package/dist/federation/content-cache.cjs +78 -0
- package/dist/federation/content-cache.d.cts +9 -0
- package/dist/federation/content-cache.d.ts +9 -0
- package/dist/federation/content-cache.js +6 -0
- package/dist/federation/federate.cjs +588 -0
- package/dist/federation/federate.d.cts +81 -0
- package/dist/federation/federate.d.ts +81 -0
- package/dist/federation/federate.js +12 -0
- package/dist/federation/github-source-provider.cjs +157 -0
- package/dist/federation/github-source-provider.d.cts +24 -0
- package/dist/federation/github-source-provider.d.ts +24 -0
- package/dist/federation/github-source-provider.js +6 -0
- package/dist/federation/public-assets.cjs +167 -0
- package/dist/federation/public-assets.d.cts +24 -0
- package/dist/federation/public-assets.d.ts +24 -0
- package/dist/federation/public-assets.js +6 -0
- package/dist/federation/types.cjs +18 -0
- package/dist/federation/types.d.cts +19 -0
- package/dist/federation/types.d.ts +19 -0
- package/dist/federation/types.js +0 -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 +8 -8
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ResolvedGraph, HydrateResult, Conflict } from '@eventcatalog/sdk';
|
|
2
|
+
import { FederationSourceConfig } from '../eventcatalog.config.js';
|
|
3
|
+
import { PublicAssetCompositionResult } from './public-assets.js';
|
|
4
|
+
import { FederationSourceProvider } from './types.js';
|
|
5
|
+
|
|
6
|
+
type FederationProgressEvent = {
|
|
7
|
+
type: 'configured';
|
|
8
|
+
sources: number;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'cleanup:complete';
|
|
11
|
+
federated: boolean;
|
|
12
|
+
publicFiles: number;
|
|
13
|
+
lock: boolean;
|
|
14
|
+
} | {
|
|
15
|
+
type: 'cache:disabled';
|
|
16
|
+
} | {
|
|
17
|
+
type: 'source:start';
|
|
18
|
+
source: FederationSourceConfig;
|
|
19
|
+
current: number;
|
|
20
|
+
total: number;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'source:complete';
|
|
23
|
+
source: FederationSourceConfig;
|
|
24
|
+
current: number;
|
|
25
|
+
total: number;
|
|
26
|
+
commit: string;
|
|
27
|
+
resources: number;
|
|
28
|
+
generated: boolean;
|
|
29
|
+
} | {
|
|
30
|
+
type: 'local:start';
|
|
31
|
+
} | {
|
|
32
|
+
type: 'local:complete';
|
|
33
|
+
resources: number;
|
|
34
|
+
} | {
|
|
35
|
+
type: 'resolving';
|
|
36
|
+
resources: number;
|
|
37
|
+
localResources: number;
|
|
38
|
+
} | {
|
|
39
|
+
type: 'resolved';
|
|
40
|
+
graph: ResolvedGraph;
|
|
41
|
+
} | {
|
|
42
|
+
type: 'hydrating';
|
|
43
|
+
outDir: string;
|
|
44
|
+
} | {
|
|
45
|
+
type: 'hydrate:cache';
|
|
46
|
+
files: number;
|
|
47
|
+
} | {
|
|
48
|
+
type: 'hydrate:file';
|
|
49
|
+
files: number;
|
|
50
|
+
source: string;
|
|
51
|
+
path: string;
|
|
52
|
+
} | {
|
|
53
|
+
type: 'public:complete';
|
|
54
|
+
result: PublicAssetCompositionResult;
|
|
55
|
+
} | {
|
|
56
|
+
type: 'complete';
|
|
57
|
+
result: FederateCatalogResult;
|
|
58
|
+
};
|
|
59
|
+
type FederateCatalogResult = {
|
|
60
|
+
sources: number;
|
|
61
|
+
resources: number;
|
|
62
|
+
graph: ResolvedGraph;
|
|
63
|
+
hydrate: HydrateResult;
|
|
64
|
+
public: PublicAssetCompositionResult;
|
|
65
|
+
outDir: string;
|
|
66
|
+
lockPath: string;
|
|
67
|
+
};
|
|
68
|
+
type FederateCatalogOptions = {
|
|
69
|
+
provider?: FederationSourceProvider;
|
|
70
|
+
onProgress?: (event: FederationProgressEvent) => void;
|
|
71
|
+
now?: () => Date;
|
|
72
|
+
useCache?: boolean;
|
|
73
|
+
isFederationEnabled?: () => Promise<boolean>;
|
|
74
|
+
};
|
|
75
|
+
declare class FederationConflictError extends Error {
|
|
76
|
+
conflicts: Conflict[];
|
|
77
|
+
constructor(conflicts: Conflict[]);
|
|
78
|
+
}
|
|
79
|
+
declare const federateCatalog: (projectDirectory: string, options?: FederateCatalogOptions) => Promise<FederateCatalogResult | null>;
|
|
80
|
+
|
|
81
|
+
export { type FederateCatalogResult, FederationConflictError, type FederationProgressEvent, federateCatalog };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FederationConflictError,
|
|
3
|
+
federateCatalog
|
|
4
|
+
} from "../chunk-ZR6AH5Z2.js";
|
|
5
|
+
import "../chunk-R7Z5ALYI.js";
|
|
6
|
+
import "../chunk-352FGP6W.js";
|
|
7
|
+
import "../chunk-5EPNFDT5.js";
|
|
8
|
+
import "../chunk-6QENHZZP.js";
|
|
9
|
+
export {
|
|
10
|
+
FederationConflictError,
|
|
11
|
+
federateCatalog
|
|
12
|
+
};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/federation/github-source-provider.ts
|
|
31
|
+
var github_source_provider_exports = {};
|
|
32
|
+
__export(github_source_provider_exports, {
|
|
33
|
+
createGitHubSourceProvider: () => createGitHubSourceProvider
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(github_source_provider_exports);
|
|
36
|
+
var import_node_child_process = require("child_process");
|
|
37
|
+
var import_promises = __toESM(require("fs/promises"), 1);
|
|
38
|
+
var import_node_os = __toESM(require("os"), 1);
|
|
39
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
40
|
+
var import_node_util = require("util");
|
|
41
|
+
var import_sdk = __toESM(require("@eventcatalog/sdk"), 1);
|
|
42
|
+
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
43
|
+
var parseGitHubSource = (source) => {
|
|
44
|
+
const match = /^github:([^/]+)\/(.+)$/.exec(source.source);
|
|
45
|
+
if (!match) throw new Error(`Unsupported federation source "${source.source}". Expected github:owner/repository.`);
|
|
46
|
+
return { owner: match[1], repository: match[2] };
|
|
47
|
+
};
|
|
48
|
+
var assertSafeCatalogPath = (source) => {
|
|
49
|
+
const catalogPath = source.path ?? ".";
|
|
50
|
+
const normalized = import_node_path.default.posix.normalize(catalogPath.replaceAll("\\", "/"));
|
|
51
|
+
if (catalogPath.includes("\\") || import_node_path.default.posix.isAbsolute(normalized) || normalized === ".." || normalized.startsWith("../")) {
|
|
52
|
+
throw new Error(`Catalog path "${catalogPath}" escapes source "${source.id}"`);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var encodePath = (value) => value.split("/").filter(Boolean).map(encodeURIComponent).join("/");
|
|
56
|
+
var rawUrl = (source, ref, filePath) => {
|
|
57
|
+
const { owner, repository } = parseGitHubSource(source);
|
|
58
|
+
return `https://raw.githubusercontent.com/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/${encodeURIComponent(
|
|
59
|
+
ref
|
|
60
|
+
)}/${encodePath(filePath)}`;
|
|
61
|
+
};
|
|
62
|
+
var contentsApiUrl = (source, ref, filePath) => {
|
|
63
|
+
const { owner, repository } = parseGitHubSource(source);
|
|
64
|
+
return `https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repository)}/contents/${encodePath(
|
|
65
|
+
filePath
|
|
66
|
+
)}?ref=${encodeURIComponent(ref)}`;
|
|
67
|
+
};
|
|
68
|
+
var fetchBytes = async (source, ref, filePath, fetcher, token) => {
|
|
69
|
+
const url = token ? contentsApiUrl(source, ref, filePath) : rawUrl(source, ref, filePath);
|
|
70
|
+
const response = token ? await fetcher(url, {
|
|
71
|
+
headers: {
|
|
72
|
+
Accept: "application/vnd.github.raw+json",
|
|
73
|
+
Authorization: `Bearer ${token}`,
|
|
74
|
+
"X-GitHub-Api-Version": "2026-03-10"
|
|
75
|
+
}
|
|
76
|
+
}) : await fetcher(url);
|
|
77
|
+
if (response.status === 404) return void 0;
|
|
78
|
+
if (!response.ok) throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
|
|
79
|
+
return Buffer.from(await response.arrayBuffer());
|
|
80
|
+
};
|
|
81
|
+
var getGitEnvironment = (token) => {
|
|
82
|
+
if (!token) return process.env;
|
|
83
|
+
const inheritedCount = Number.parseInt(process.env.GIT_CONFIG_COUNT ?? "0", 10);
|
|
84
|
+
const configIndex = Number.isInteger(inheritedCount) && inheritedCount >= 0 ? inheritedCount : 0;
|
|
85
|
+
return {
|
|
86
|
+
...process.env,
|
|
87
|
+
GIT_CONFIG_COUNT: String(configIndex + 1),
|
|
88
|
+
[`GIT_CONFIG_KEY_${configIndex}`]: "http.https://github.com/.extraheader",
|
|
89
|
+
[`GIT_CONFIG_VALUE_${configIndex}`]: `AUTHORIZATION: basic ${Buffer.from(`x-access-token:${token}`).toString("base64")}`
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
var createCheckout = (executeFile, token) => async (source, ref, callback) => {
|
|
93
|
+
const { owner, repository } = parseGitHubSource(source);
|
|
94
|
+
const catalogPath = import_node_path.default.posix.normalize(source.path ?? ".");
|
|
95
|
+
const directory = await import_promises.default.mkdtemp(import_node_path.default.join(import_node_os.default.tmpdir(), "eventcatalog-federation-"));
|
|
96
|
+
const env = getGitEnvironment(token);
|
|
97
|
+
try {
|
|
98
|
+
const git = (args) => executeFile("git", args, { cwd: directory, env, encoding: "utf8" });
|
|
99
|
+
await git(["init", "--quiet"]);
|
|
100
|
+
await git(["remote", "add", "origin", `https://github.com/${owner}/${repository}.git`]);
|
|
101
|
+
if (catalogPath !== ".") {
|
|
102
|
+
await git(["sparse-checkout", "init", "--cone"]);
|
|
103
|
+
await git(["sparse-checkout", "set", catalogPath]);
|
|
104
|
+
}
|
|
105
|
+
await git(["fetch", "--quiet", "--depth", "1", "origin", ref]);
|
|
106
|
+
await git(["checkout", "--quiet", "--detach", "FETCH_HEAD"]);
|
|
107
|
+
return await callback(directory);
|
|
108
|
+
} finally {
|
|
109
|
+
await import_promises.default.rm(directory, { recursive: true, force: true });
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
var generateIndex = async (source, ref, checkout, executeFile) => checkout(source, ref, async (directory) => {
|
|
113
|
+
const { stdout } = await executeFile("git", ["rev-parse", "HEAD"], { cwd: directory, encoding: "utf8" });
|
|
114
|
+
const commit = stdout.trim();
|
|
115
|
+
const catalogDirectory = import_node_path.default.resolve(directory, source.path ?? ".");
|
|
116
|
+
const relativeCatalogDirectory = import_node_path.default.relative(directory, catalogDirectory);
|
|
117
|
+
if (relativeCatalogDirectory.startsWith("..") || import_node_path.default.isAbsolute(relativeCatalogDirectory)) {
|
|
118
|
+
throw new Error(`Catalog path "${source.path}" escapes source "${source.id}"`);
|
|
119
|
+
}
|
|
120
|
+
const index = await (0, import_sdk.default)(catalogDirectory).buildIndex({ source: source.id, commit });
|
|
121
|
+
return { bytes: Buffer.from(JSON.stringify(index)), index, commit, generated: true };
|
|
122
|
+
});
|
|
123
|
+
var fetchPublishedIndex = async (source, ref, fetcher, token) => {
|
|
124
|
+
const indexPath = import_node_path.default.posix.join(source.path ?? ".", "catalog.index.json");
|
|
125
|
+
const bytes = await fetchBytes(source, ref, indexPath, fetcher, token);
|
|
126
|
+
if (!bytes) return void 0;
|
|
127
|
+
const index = (0, import_sdk.parseIndex)(JSON.parse(bytes.toString("utf8")));
|
|
128
|
+
if (index.source !== source.id) {
|
|
129
|
+
throw new Error(`Published index source "${index.source}" does not match configured id "${source.id}"`);
|
|
130
|
+
}
|
|
131
|
+
return { bytes, index, commit: index.commit, generated: false };
|
|
132
|
+
};
|
|
133
|
+
var createGitHubSourceProvider = (options = {}) => {
|
|
134
|
+
const fetcher = options.fetch ?? ((url, init) => fetch(url, init));
|
|
135
|
+
const executeFile = options.execFile ?? ((file, args, execOptions) => execFileAsync(file, args, execOptions));
|
|
136
|
+
const configuredToken = options.token ?? process.env.EVENTCATALOG_GITHUB_TOKEN ?? process.env.GITHUB_TOKEN;
|
|
137
|
+
const token = configuredToken?.trim() || void 0;
|
|
138
|
+
const checkout = options.checkout ?? createCheckout(executeFile, token);
|
|
139
|
+
return {
|
|
140
|
+
async resolve(source) {
|
|
141
|
+
assertSafeCatalogPath(source);
|
|
142
|
+
const ref = source.ref ?? "main";
|
|
143
|
+
return await fetchPublishedIndex(source, ref, fetcher, token) ?? generateIndex(source, ref, checkout, executeFile);
|
|
144
|
+
},
|
|
145
|
+
async fetchContent({ source, commit, path: artifactPath }) {
|
|
146
|
+
assertSafeCatalogPath(source);
|
|
147
|
+
const catalogPath = import_node_path.default.posix.join(source.path ?? ".", artifactPath);
|
|
148
|
+
const content = await fetchBytes(source, commit, catalogPath, fetcher, token);
|
|
149
|
+
if (!content) throw new Error(`Federated artifact not found for "${source.id}": ${artifactPath}`);
|
|
150
|
+
return content;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
155
|
+
0 && (module.exports = {
|
|
156
|
+
createGitHubSourceProvider
|
|
157
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FederationSourceConfig } from '../eventcatalog.config.cjs';
|
|
2
|
+
import { FederationSourceProvider } from './types.cjs';
|
|
3
|
+
import '@eventcatalog/sdk';
|
|
4
|
+
|
|
5
|
+
type FetchResponse = Pick<Response, 'status' | 'statusText' | 'ok' | 'arrayBuffer'>;
|
|
6
|
+
type FetchFunction = (url: string, init?: RequestInit) => Promise<FetchResponse>;
|
|
7
|
+
type ExecFileFunction = (file: string, args: string[], options: {
|
|
8
|
+
cwd: string;
|
|
9
|
+
env?: NodeJS.ProcessEnv;
|
|
10
|
+
encoding: 'utf8';
|
|
11
|
+
}) => Promise<{
|
|
12
|
+
stdout: string;
|
|
13
|
+
stderr: string;
|
|
14
|
+
}>;
|
|
15
|
+
type CheckoutFunction = <T>(source: FederationSourceConfig, ref: string, callback: (directory: string) => Promise<T>) => Promise<T>;
|
|
16
|
+
type GitHubSourceProviderOptions = {
|
|
17
|
+
fetch?: FetchFunction;
|
|
18
|
+
checkout?: CheckoutFunction;
|
|
19
|
+
execFile?: ExecFileFunction;
|
|
20
|
+
token?: string;
|
|
21
|
+
};
|
|
22
|
+
declare const createGitHubSourceProvider: (options?: GitHubSourceProviderOptions) => FederationSourceProvider;
|
|
23
|
+
|
|
24
|
+
export { type GitHubSourceProviderOptions, createGitHubSourceProvider };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { FederationSourceConfig } from '../eventcatalog.config.js';
|
|
2
|
+
import { FederationSourceProvider } from './types.js';
|
|
3
|
+
import '@eventcatalog/sdk';
|
|
4
|
+
|
|
5
|
+
type FetchResponse = Pick<Response, 'status' | 'statusText' | 'ok' | 'arrayBuffer'>;
|
|
6
|
+
type FetchFunction = (url: string, init?: RequestInit) => Promise<FetchResponse>;
|
|
7
|
+
type ExecFileFunction = (file: string, args: string[], options: {
|
|
8
|
+
cwd: string;
|
|
9
|
+
env?: NodeJS.ProcessEnv;
|
|
10
|
+
encoding: 'utf8';
|
|
11
|
+
}) => Promise<{
|
|
12
|
+
stdout: string;
|
|
13
|
+
stderr: string;
|
|
14
|
+
}>;
|
|
15
|
+
type CheckoutFunction = <T>(source: FederationSourceConfig, ref: string, callback: (directory: string) => Promise<T>) => Promise<T>;
|
|
16
|
+
type GitHubSourceProviderOptions = {
|
|
17
|
+
fetch?: FetchFunction;
|
|
18
|
+
checkout?: CheckoutFunction;
|
|
19
|
+
execFile?: ExecFileFunction;
|
|
20
|
+
token?: string;
|
|
21
|
+
};
|
|
22
|
+
declare const createGitHubSourceProvider: (options?: GitHubSourceProviderOptions) => FederationSourceProvider;
|
|
23
|
+
|
|
24
|
+
export { type GitHubSourceProviderOptions, createGitHubSourceProvider };
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/federation/public-assets.ts
|
|
31
|
+
var public_assets_exports = {};
|
|
32
|
+
__export(public_assets_exports, {
|
|
33
|
+
composePublicAssets: () => composePublicAssets
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(public_assets_exports);
|
|
36
|
+
var import_node_crypto = require("crypto");
|
|
37
|
+
var import_promises = __toESM(require("fs/promises"), 1);
|
|
38
|
+
var import_node_path = __toESM(require("path"), 1);
|
|
39
|
+
var getContentHash = (content) => `sha256:${(0, import_node_crypto.createHash)("sha256").update(content).digest("hex")}`;
|
|
40
|
+
var getFileHash = async (filePath) => {
|
|
41
|
+
try {
|
|
42
|
+
const stat = await import_promises.default.lstat(filePath);
|
|
43
|
+
return stat.isFile() ? getContentHash(await import_promises.default.readFile(filePath)) : void 0;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (error.code === "ENOENT") return void 0;
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var getSafePath = (directory, relativePath) => {
|
|
50
|
+
const normalizedPath = import_node_path.default.posix.normalize(relativePath);
|
|
51
|
+
const unsafe = relativePath.length === 0 || relativePath.includes("\0") || relativePath.includes("\\") || import_node_path.default.posix.isAbsolute(relativePath) || /^[a-zA-Z]:\//.test(relativePath) || normalizedPath !== relativePath || normalizedPath === ".." || normalizedPath.startsWith("../");
|
|
52
|
+
if (unsafe) return void 0;
|
|
53
|
+
const resolvedDirectory = import_node_path.default.resolve(directory);
|
|
54
|
+
const resolvedPath = import_node_path.default.resolve(resolvedDirectory, relativePath);
|
|
55
|
+
const relativeResolvedPath = import_node_path.default.relative(resolvedDirectory, resolvedPath);
|
|
56
|
+
if (relativeResolvedPath === "" || relativeResolvedPath === ".." || relativeResolvedPath.startsWith(`..${import_node_path.default.sep}`) || import_node_path.default.isAbsolute(relativeResolvedPath)) {
|
|
57
|
+
return void 0;
|
|
58
|
+
}
|
|
59
|
+
return resolvedPath;
|
|
60
|
+
};
|
|
61
|
+
var listFiles = async (directory, relativeDirectory = "") => {
|
|
62
|
+
let entries;
|
|
63
|
+
try {
|
|
64
|
+
entries = await import_promises.default.readdir(import_node_path.default.join(directory, relativeDirectory), { withFileTypes: true });
|
|
65
|
+
} catch (error) {
|
|
66
|
+
if (error.code === "ENOENT") return [];
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
const files = await Promise.all(
|
|
70
|
+
entries.map(async (entry) => {
|
|
71
|
+
const relativePath = import_node_path.default.join(relativeDirectory, entry.name);
|
|
72
|
+
if (entry.isDirectory()) return listFiles(directory, relativePath);
|
|
73
|
+
return entry.isFile() ? [relativePath.split(import_node_path.default.sep).join("/")] : [];
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
return files.flat().sort();
|
|
77
|
+
};
|
|
78
|
+
var pathExists = async (filePath) => {
|
|
79
|
+
try {
|
|
80
|
+
await import_promises.default.lstat(filePath);
|
|
81
|
+
return true;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
if (error.code === "ENOENT") return false;
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var hasBlockingParent = async (publicDirectory, destinationPath) => {
|
|
88
|
+
let currentPath = import_node_path.default.dirname(destinationPath);
|
|
89
|
+
while (currentPath !== publicDirectory) {
|
|
90
|
+
try {
|
|
91
|
+
if (!(await import_promises.default.lstat(currentPath)).isDirectory()) return true;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
if (error.code !== "ENOENT") throw error;
|
|
94
|
+
}
|
|
95
|
+
currentPath = import_node_path.default.dirname(currentPath);
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
};
|
|
99
|
+
var pruneEmptyDirectories = async (publicDirectory, filePath) => {
|
|
100
|
+
let currentPath = import_node_path.default.dirname(filePath);
|
|
101
|
+
while (currentPath !== publicDirectory) {
|
|
102
|
+
try {
|
|
103
|
+
await import_promises.default.rmdir(currentPath);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
if (!["ENOENT", "ENOTEMPTY"].includes(error.code ?? "")) throw error;
|
|
106
|
+
if (error.code === "ENOTEMPTY") return;
|
|
107
|
+
}
|
|
108
|
+
currentPath = import_node_path.default.dirname(currentPath);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var composePublicAssets = async ({
|
|
112
|
+
projectDirectory,
|
|
113
|
+
federatedDirectory,
|
|
114
|
+
assets,
|
|
115
|
+
previousFiles = {},
|
|
116
|
+
collisionPaths = /* @__PURE__ */ new Set()
|
|
117
|
+
}) => {
|
|
118
|
+
const publicDirectory = import_node_path.default.resolve(projectDirectory, "public");
|
|
119
|
+
const federatedPublicDirectory = import_node_path.default.resolve(federatedDirectory, "public");
|
|
120
|
+
const sourceFiles = await listFiles(federatedPublicDirectory);
|
|
121
|
+
const sourceFileSet = new Set(sourceFiles);
|
|
122
|
+
const managedFiles = /* @__PURE__ */ new Set();
|
|
123
|
+
for (const [relativePath, previousFile] of Object.entries(previousFiles)) {
|
|
124
|
+
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
125
|
+
if (destinationPath && await getFileHash(destinationPath) === previousFile.hash) managedFiles.add(relativePath);
|
|
126
|
+
}
|
|
127
|
+
let removed = 0;
|
|
128
|
+
for (const relativePath of managedFiles) {
|
|
129
|
+
if (sourceFileSet.has(relativePath)) continue;
|
|
130
|
+
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
131
|
+
if (!destinationPath) continue;
|
|
132
|
+
await import_promises.default.rm(destinationPath, { force: true });
|
|
133
|
+
await pruneEmptyDirectories(publicDirectory, destinationPath);
|
|
134
|
+
removed += 1;
|
|
135
|
+
}
|
|
136
|
+
const publicAssetsByPath = new Map(
|
|
137
|
+
assets.filter((asset) => asset.path.startsWith("public/")).map((asset) => [asset.path.slice("public/".length), asset])
|
|
138
|
+
);
|
|
139
|
+
const files = {};
|
|
140
|
+
let copied = 0;
|
|
141
|
+
let skipped = 0;
|
|
142
|
+
let overwritten = 0;
|
|
143
|
+
for (const relativePath of sourceFiles) {
|
|
144
|
+
const sourcePath = getSafePath(federatedPublicDirectory, relativePath);
|
|
145
|
+
const destinationPath = getSafePath(publicDirectory, relativePath);
|
|
146
|
+
if (!sourcePath || !destinationPath) throw new Error(`Unsafe federated public asset path "${relativePath}"`);
|
|
147
|
+
const mainCatalogOwnsPath = await pathExists(destinationPath) && !managedFiles.has(relativePath) || await hasBlockingParent(publicDirectory, destinationPath);
|
|
148
|
+
if (mainCatalogOwnsPath) {
|
|
149
|
+
skipped += 1;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const asset = publicAssetsByPath.get(relativePath);
|
|
153
|
+
if (!asset) throw new Error(`Cannot identify the source of federated public asset "${relativePath}"`);
|
|
154
|
+
const content = await import_promises.default.readFile(sourcePath);
|
|
155
|
+
await import_promises.default.mkdir(import_node_path.default.dirname(destinationPath), { recursive: true });
|
|
156
|
+
await import_promises.default.writeFile(destinationPath, content);
|
|
157
|
+
files[relativePath] = { source: asset.resolvedFrom.source, hash: getContentHash(content) };
|
|
158
|
+
copied += 1;
|
|
159
|
+
if (collisionPaths.has(`public/${relativePath}`)) overwritten += 1;
|
|
160
|
+
}
|
|
161
|
+
await import_promises.default.rm(federatedPublicDirectory, { recursive: true, force: true });
|
|
162
|
+
return { files, copied, skipped, overwritten, removed };
|
|
163
|
+
};
|
|
164
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
165
|
+
0 && (module.exports = {
|
|
166
|
+
composePublicAssets
|
|
167
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ResolvedAsset } from '@eventcatalog/sdk';
|
|
2
|
+
|
|
3
|
+
type FederatedPublicFile = {
|
|
4
|
+
source: string;
|
|
5
|
+
hash: string;
|
|
6
|
+
};
|
|
7
|
+
type FederatedPublicFiles = Record<string, FederatedPublicFile>;
|
|
8
|
+
type PublicAssetCompositionResult = {
|
|
9
|
+
files: FederatedPublicFiles;
|
|
10
|
+
copied: number;
|
|
11
|
+
skipped: number;
|
|
12
|
+
overwritten: number;
|
|
13
|
+
removed: number;
|
|
14
|
+
};
|
|
15
|
+
type ComposePublicAssetsOptions = {
|
|
16
|
+
projectDirectory: string;
|
|
17
|
+
federatedDirectory: string;
|
|
18
|
+
assets: ResolvedAsset[];
|
|
19
|
+
previousFiles?: FederatedPublicFiles;
|
|
20
|
+
collisionPaths?: Set<string>;
|
|
21
|
+
};
|
|
22
|
+
declare const composePublicAssets: ({ projectDirectory, federatedDirectory, assets, previousFiles, collisionPaths, }: ComposePublicAssetsOptions) => Promise<PublicAssetCompositionResult>;
|
|
23
|
+
|
|
24
|
+
export { type FederatedPublicFile, type FederatedPublicFiles, type PublicAssetCompositionResult, composePublicAssets };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ResolvedAsset } from '@eventcatalog/sdk';
|
|
2
|
+
|
|
3
|
+
type FederatedPublicFile = {
|
|
4
|
+
source: string;
|
|
5
|
+
hash: string;
|
|
6
|
+
};
|
|
7
|
+
type FederatedPublicFiles = Record<string, FederatedPublicFile>;
|
|
8
|
+
type PublicAssetCompositionResult = {
|
|
9
|
+
files: FederatedPublicFiles;
|
|
10
|
+
copied: number;
|
|
11
|
+
skipped: number;
|
|
12
|
+
overwritten: number;
|
|
13
|
+
removed: number;
|
|
14
|
+
};
|
|
15
|
+
type ComposePublicAssetsOptions = {
|
|
16
|
+
projectDirectory: string;
|
|
17
|
+
federatedDirectory: string;
|
|
18
|
+
assets: ResolvedAsset[];
|
|
19
|
+
previousFiles?: FederatedPublicFiles;
|
|
20
|
+
collisionPaths?: Set<string>;
|
|
21
|
+
};
|
|
22
|
+
declare const composePublicAssets: ({ projectDirectory, federatedDirectory, assets, previousFiles, collisionPaths, }: ComposePublicAssetsOptions) => Promise<PublicAssetCompositionResult>;
|
|
23
|
+
|
|
24
|
+
export { type FederatedPublicFile, type FederatedPublicFiles, type PublicAssetCompositionResult, composePublicAssets };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
|
|
16
|
+
// src/federation/types.ts
|
|
17
|
+
var types_exports = {};
|
|
18
|
+
module.exports = __toCommonJS(types_exports);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Index } from '@eventcatalog/sdk';
|
|
2
|
+
import { FederationSourceConfig } from '../eventcatalog.config.cjs';
|
|
3
|
+
|
|
4
|
+
type ResolvedFederationSource = {
|
|
5
|
+
bytes: Buffer;
|
|
6
|
+
index: Index;
|
|
7
|
+
commit: string;
|
|
8
|
+
generated: boolean;
|
|
9
|
+
};
|
|
10
|
+
type FederationSourceProvider = {
|
|
11
|
+
resolve(source: FederationSourceConfig): Promise<ResolvedFederationSource>;
|
|
12
|
+
fetchContent(request: {
|
|
13
|
+
source: FederationSourceConfig;
|
|
14
|
+
commit: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}): Promise<Buffer>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type { FederationSourceProvider, ResolvedFederationSource };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Index } from '@eventcatalog/sdk';
|
|
2
|
+
import { FederationSourceConfig } from '../eventcatalog.config.js';
|
|
3
|
+
|
|
4
|
+
type ResolvedFederationSource = {
|
|
5
|
+
bytes: Buffer;
|
|
6
|
+
index: Index;
|
|
7
|
+
commit: string;
|
|
8
|
+
generated: boolean;
|
|
9
|
+
};
|
|
10
|
+
type FederationSourceProvider = {
|
|
11
|
+
resolve(source: FederationSourceConfig): Promise<ResolvedFederationSource>;
|
|
12
|
+
fetchContent(request: {
|
|
13
|
+
source: FederationSourceConfig;
|
|
14
|
+
commit: string;
|
|
15
|
+
path: string;
|
|
16
|
+
}): Promise<Buffer>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type { FederationSourceProvider, ResolvedFederationSource };
|
|
File without changes
|
package/dist/generate.cjs
CHANGED
|
@@ -108,7 +108,7 @@ var getEventCatalogConfigFile = async (projectDirectory) => {
|
|
|
108
108
|
var import_picocolors = __toESM(require("picocolors"), 1);
|
|
109
109
|
|
|
110
110
|
// package.json
|
|
111
|
-
var version = "4.6.
|
|
111
|
+
var version = "4.6.3";
|
|
112
112
|
|
|
113
113
|
// src/constants.ts
|
|
114
114
|
var VERSION = version;
|
package/dist/generate.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generate
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-4BBXOL6K.js";
|
|
4
|
+
import "./chunk-FZJDCQZE.js";
|
|
5
|
+
import "./chunk-LB5VXS6X.js";
|
|
6
6
|
import "./chunk-6QENHZZP.js";
|
|
7
7
|
export {
|
|
8
8
|
generate
|