@eventcatalog/core 3.35.1 → 3.36.1
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-4SNN54V4.js → chunk-6D65JSOA.js} +1 -1
- package/dist/{chunk-B7C4DHFE.js → chunk-C7JCOHTI.js} +1 -1
- package/dist/chunk-D6IBLY3O.js +320 -0
- package/dist/{chunk-R4DR3YAH.js → chunk-HDENGAZL.js} +1 -1
- package/dist/{chunk-JEQZWJWP.js → chunk-UJ7DX4SA.js} +3 -3
- package/dist/{chunk-3KXCGYET.js → chunk-ULZYHF3V.js} +5 -0
- package/dist/{chunk-VJ357XOI.js → chunk-V22QY5Q3.js} +1 -1
- package/dist/constants.cjs +1 -1
- package/dist/constants.js +1 -1
- package/dist/docs/api/02-config.md +22 -0
- package/dist/docs/api/_category_.json +1 -1
- package/dist/docs/contributing/_category_.json +1 -1
- package/dist/docs/development/_category_.json +1 -1
- package/dist/docs/development/ask-your-architecture/02-eventcatalog-assistant/_category_.json +1 -1
- package/dist/docs/development/ask-your-architecture/03-mcp-server/_category_.json +1 -1
- package/dist/docs/development/ask-your-architecture/04-skills/_category_.json +1 -1
- package/dist/docs/development/authentication/providers/_category_.json +1 -1
- package/dist/docs/development/bring-your-own-documentation/custom-pages/_category_.json +1 -1
- package/dist/docs/development/customization/01-customize-landing-page.md +1 -1
- package/dist/docs/development/customization/03-search.md +79 -0
- package/dist/docs/development/customization/custom-components/_category_.json +1 -1
- package/dist/docs/development/customization/customize-sidebars/_category_.json +1 -1
- package/dist/docs/development/customization/customize-visualizer/_category_.json +1 -1
- package/dist/docs/development/design/_category_.json +1 -1
- package/dist/docs/development/guides/changelogs/_category_.json +1 -1
- package/dist/docs/development/guides/channels/_category_.json +1 -1
- package/dist/docs/development/guides/channels/ownership-and-components/_category_.json +1 -1
- package/dist/docs/development/guides/channels/versioning-and-lifecycle/_category_.json +1 -1
- package/dist/docs/development/guides/data/_category_.json +1 -1
- package/dist/docs/development/guides/data/ownership-and-components/_category_.json +1 -1
- package/dist/docs/development/guides/data-products/_category_.json +1 -1
- package/dist/docs/development/guides/domains/02-creating-domains/_category_.json +1 -1
- package/dist/docs/development/guides/domains/03-ownership-and-language/_category_.json +1 -1
- package/dist/docs/development/guides/domains/05-entities/_category_.json +1 -1
- package/dist/docs/development/guides/domains/_category_.json +1 -1
- package/dist/docs/development/guides/flows/_category_.json +1 -1
- package/dist/docs/development/guides/messages/_category_.json +1 -1
- package/dist/docs/development/guides/messages/commands/_category_.json +1 -1
- package/dist/docs/development/guides/messages/common/_category_.json +1 -1
- package/dist/docs/development/guides/messages/events/_category_.json +1 -1
- package/dist/docs/development/guides/messages/queries/_category_.json +1 -1
- package/dist/docs/development/guides/owners/_category_.json +1 -1
- package/dist/docs/development/guides/owners/teams/_category_.json +1 -1
- package/dist/docs/development/guides/owners/users/_category_.json +1 -1
- package/dist/docs/development/guides/schemas/_category_.json +1 -1
- package/dist/docs/development/guides/services/_category_.json +1 -1
- package/dist/docs/development/guides/services/adding-to-services/_category_.json +1 -1
- package/dist/docs/development/guides/services/ownership-and-components/_category_.json +1 -1
- package/dist/docs/development/guides/services/versioning-and-lifecycle/_category_.json +1 -1
- package/dist/docs/plugins/_category_.json +1 -1
- package/dist/docs/plugins/amazon-apigateway/_category_.json +1 -1
- package/dist/docs/plugins/asyncapi/_category_.json +1 -1
- package/dist/docs/plugins/aws-glue-registry/_category_.json +1 -1
- package/dist/docs/plugins/backstage/_category_.json +1 -1
- package/dist/docs/plugins/confluent-schema-registry/_category_.json +1 -1
- package/dist/docs/plugins/eventbridge/_category_.json +1 -1
- package/dist/docs/plugins/eventcatalog-federation/_category_.json +1 -1
- package/dist/docs/plugins/github/_category_.json +1 -1
- package/dist/docs/plugins/graphql/_category_.json +1 -1
- package/dist/docs/plugins/hookdeck/_category_.json +1 -1
- package/dist/docs/plugins/openapi/_category_.json +1 -1
- package/dist/eventcatalog.cjs +434 -35
- package/dist/eventcatalog.config.d.cts +8 -0
- package/dist/eventcatalog.config.d.ts +8 -0
- package/dist/eventcatalog.js +87 -10
- package/dist/features.cjs +6 -0
- package/dist/features.d.cts +2 -1
- package/dist/features.d.ts +2 -1
- package/dist/features.js +3 -1
- package/dist/generate.cjs +1 -1
- package/dist/generate.js +3 -3
- package/dist/search-indexer.cjs +356 -0
- package/dist/search-indexer.d.cts +30 -0
- package/dist/search-indexer.d.ts +30 -0
- package/dist/search-indexer.js +10 -0
- package/dist/utils/cli-logger.cjs +1 -1
- package/dist/utils/cli-logger.js +2 -2
- package/eventcatalog/astro.config.mjs +28 -32
- package/eventcatalog/src/components/Search/SearchModal.tsx +248 -148
- package/eventcatalog/src/components/Search/search-utils.spec.ts +138 -1
- package/eventcatalog/src/components/Search/search-utils.ts +271 -0
- package/eventcatalog/src/env.d.ts +1 -0
- package/package.json +3 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
log_build_default
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-VJ357XOI.js";
|
|
3
|
+
} from "../chunk-UJ7DX4SA.js";
|
|
5
4
|
import "../chunk-4UVFXLPI.js";
|
|
6
|
-
import "../chunk-
|
|
5
|
+
import "../chunk-V22QY5Q3.js";
|
|
6
|
+
import "../chunk-C7JCOHTI.js";
|
|
7
7
|
import "../chunk-5T63CXKU.js";
|
|
8
8
|
export {
|
|
9
9
|
log_build_default as default
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
// src/search-indexer.ts
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { glob } from "glob";
|
|
5
|
+
import matter from "gray-matter";
|
|
6
|
+
var RESOURCE_COLLECTIONS = {
|
|
7
|
+
channels: { docsPath: "channels", type: "Channel" },
|
|
8
|
+
commands: { docsPath: "commands", type: "Command" },
|
|
9
|
+
containers: { docsPath: "containers", type: "Container" },
|
|
10
|
+
"data-products": { docsPath: "data-products", type: "Data Product" },
|
|
11
|
+
domains: { docsPath: "domains", type: "Domain" },
|
|
12
|
+
entities: { docsPath: "entities", type: "Entity" },
|
|
13
|
+
events: { docsPath: "events", type: "Event" },
|
|
14
|
+
flows: { docsPath: "flows", type: "Flow" },
|
|
15
|
+
queries: { docsPath: "queries", type: "Query" },
|
|
16
|
+
services: { docsPath: "services", type: "Service" },
|
|
17
|
+
subdomains: { docsPath: "domains", type: "Domain" }
|
|
18
|
+
};
|
|
19
|
+
var IGNORED_GLOBS = [
|
|
20
|
+
"**/.git/**",
|
|
21
|
+
"**/.eventcatalog-core/**",
|
|
22
|
+
"**/dist/**",
|
|
23
|
+
"**/node_modules/**",
|
|
24
|
+
"**/public/**",
|
|
25
|
+
"**/snippets/**",
|
|
26
|
+
"**/chat-prompts/**"
|
|
27
|
+
];
|
|
28
|
+
var trimSlashes = (value) => value.replace(/^\/+|\/+$/g, "");
|
|
29
|
+
var normalizePath = (value) => value.replace(/\\/g, "/");
|
|
30
|
+
var removeExtension = (value) => value.replace(/\.(md|mdx)$/i, "");
|
|
31
|
+
var stripNumericPrefix = (value) => value.replace(/^\d+(?:[-_.\s]+)?/, "") || value;
|
|
32
|
+
var normalizeUrlPath = (value) => {
|
|
33
|
+
const withoutIndex = value.replace(/\/index$/i, "");
|
|
34
|
+
return withoutIndex || "";
|
|
35
|
+
};
|
|
36
|
+
var buildUrl = (pathname, config) => {
|
|
37
|
+
const base = config.base ? `/${trimSlashes(config.base)}` : "";
|
|
38
|
+
const cleanPath = `/${trimSlashes(pathname)}`;
|
|
39
|
+
const url = `${base}${cleanPath}`.replace(/\/{2,}/g, "/");
|
|
40
|
+
if (config.trailingSlash === true && !url.endsWith("/")) {
|
|
41
|
+
return `${url}/`;
|
|
42
|
+
}
|
|
43
|
+
return url || "/";
|
|
44
|
+
};
|
|
45
|
+
var valueToSearchText = (value) => {
|
|
46
|
+
if (value === null || value === void 0) return "";
|
|
47
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return String(value);
|
|
48
|
+
if (Array.isArray(value)) return value.map(valueToSearchText).filter(Boolean).join(" ");
|
|
49
|
+
if (typeof value === "object") return Object.values(value).map(valueToSearchText).filter(Boolean).join(" ");
|
|
50
|
+
return "";
|
|
51
|
+
};
|
|
52
|
+
var markdownToSearchText = (content) => {
|
|
53
|
+
return content.replace(/<!--[\s\S]*?-->/g, " ").replace(/^\s*import\s+.*$/gm, " ").replace(/^\s*export\s+.*$/gm, " ").replace(/```[\s\S]*?```/g, (match) => match.replace(/```[a-zA-Z0-9-]*\n?/g, " ").replace(/```/g, " ")).replace(/<([A-Z][A-Za-z0-9.]*)\b([^>]*)\/?>/g, (_match, _component, attributes) => {
|
|
54
|
+
const quotedValues = [...String(attributes).matchAll(/(?:title|label|description|alt|summary)=["'`]([^"'`]+)["'`]/g)];
|
|
55
|
+
return quotedValues.map((entry) => entry[1]).join(" ");
|
|
56
|
+
}).replace(/<\/?[A-Za-z][^>]*>/g, " ").replace(/\[\[([^|\]]+)\|([^\]]+)\]\]/g, "$2").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/[`*_~>#|{}[\]():]/g, " ").replace(/\s+/g, " ").trim();
|
|
57
|
+
};
|
|
58
|
+
var inferDocIdFromFile = (relativePath, frontmatterId) => {
|
|
59
|
+
if (frontmatterId) return frontmatterId;
|
|
60
|
+
const fileName = path.posix.basename(removeExtension(relativePath));
|
|
61
|
+
if (fileName.toLowerCase() === "index") {
|
|
62
|
+
return path.posix.basename(path.posix.dirname(relativePath));
|
|
63
|
+
}
|
|
64
|
+
return stripNumericPrefix(fileName);
|
|
65
|
+
};
|
|
66
|
+
var findResourceSegment = (segments) => {
|
|
67
|
+
let match = null;
|
|
68
|
+
for (let index = 0; index < segments.length - 1; index++) {
|
|
69
|
+
const segment = segments[index];
|
|
70
|
+
if (RESOURCE_COLLECTIONS[segment] && segments[index + 1]) {
|
|
71
|
+
match = { index, segment };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return match;
|
|
75
|
+
};
|
|
76
|
+
var readResourceFrontmatter = async (projectDir, resourcePath) => {
|
|
77
|
+
const candidates = [path.join(projectDir, resourcePath, "index.mdx"), path.join(projectDir, resourcePath, "index.md")];
|
|
78
|
+
for (const candidate of candidates) {
|
|
79
|
+
try {
|
|
80
|
+
const file = await fs.readFile(candidate, "utf8");
|
|
81
|
+
return matter(file).data;
|
|
82
|
+
} catch {
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return {};
|
|
86
|
+
};
|
|
87
|
+
var deriveRecordFromPath = async ({
|
|
88
|
+
projectDir,
|
|
89
|
+
relativePath,
|
|
90
|
+
data,
|
|
91
|
+
config
|
|
92
|
+
}) => {
|
|
93
|
+
const normalizedRelativePath = normalizePath(relativePath);
|
|
94
|
+
const segments = normalizedRelativePath.split("/").filter(Boolean);
|
|
95
|
+
const fileName = segments[segments.length - 1] || "";
|
|
96
|
+
const fileNameWithoutExtension = removeExtension(fileName);
|
|
97
|
+
if (data.hidden === true || data.draft) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
if (segments[0] === "docs") {
|
|
101
|
+
const customPath = normalizeUrlPath(removeExtension(segments.slice(1).join("/")));
|
|
102
|
+
const title = data.title || data.label || path.posix.basename(customPath) || "Custom docs";
|
|
103
|
+
return {
|
|
104
|
+
url: buildUrl(`/docs/custom/${customPath}`, config),
|
|
105
|
+
title,
|
|
106
|
+
summary: data.summary,
|
|
107
|
+
type: "Custom Doc",
|
|
108
|
+
collection: "custom-docs",
|
|
109
|
+
id: customPath
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (segments[0] === "users" || segments[0] === "teams") {
|
|
113
|
+
const id = data.id || (fileNameWithoutExtension === "index" ? segments[1] : fileNameWithoutExtension);
|
|
114
|
+
const type = segments[0] === "users" ? "User" : "Team";
|
|
115
|
+
return {
|
|
116
|
+
url: buildUrl(`/docs/${segments[0]}/${id}`, config),
|
|
117
|
+
title: data.name || data.title || id,
|
|
118
|
+
summary: data.summary,
|
|
119
|
+
type,
|
|
120
|
+
collection: segments[0],
|
|
121
|
+
id
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
const resourceMatch = findResourceSegment(segments);
|
|
125
|
+
if (!resourceMatch) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
const resourceConfig = RESOURCE_COLLECTIONS[resourceMatch.segment];
|
|
129
|
+
const resourceFolderId = segments[resourceMatch.index + 1];
|
|
130
|
+
const resourcePathSegments = segments.slice(0, resourceMatch.index + 2);
|
|
131
|
+
const versionFromPath = segments[resourceMatch.index + 2] === "versioned" && segments[resourceMatch.index + 3] ? segments[resourceMatch.index + 3] : void 0;
|
|
132
|
+
if (versionFromPath) {
|
|
133
|
+
resourcePathSegments.push("versioned", versionFromPath);
|
|
134
|
+
}
|
|
135
|
+
const resourcePath = resourcePathSegments.join("/");
|
|
136
|
+
const resourceData = fileNameWithoutExtension === "index" ? data : await readResourceFrontmatter(projectDir, resourcePath);
|
|
137
|
+
const resourceId = resourceData.id || data.resourceId || resourceFolderId;
|
|
138
|
+
const resourceVersion = versionFromPath || resourceData.version || data.resourceVersion || data.version;
|
|
139
|
+
if (!resourceVersion) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
if (fileNameWithoutExtension === "index") {
|
|
143
|
+
return {
|
|
144
|
+
url: buildUrl(`/docs/${resourceConfig.docsPath}/${resourceId}/${resourceVersion}`, config),
|
|
145
|
+
title: data.name || data.title || resourceId,
|
|
146
|
+
summary: data.summary,
|
|
147
|
+
type: resourceConfig.type,
|
|
148
|
+
collection: resourceConfig.docsPath,
|
|
149
|
+
id: resourceId,
|
|
150
|
+
version: resourceVersion
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (fileNameWithoutExtension === "ubiquitous-language") {
|
|
154
|
+
return {
|
|
155
|
+
url: buildUrl(`/docs/${resourceConfig.docsPath}/${resourceId}/language`, config),
|
|
156
|
+
title: data.title || `${resourceData.name || resourceId} ubiquitous language`,
|
|
157
|
+
summary: data.summary,
|
|
158
|
+
type: "Language",
|
|
159
|
+
collection: "language",
|
|
160
|
+
id: resourceId,
|
|
161
|
+
version: resourceVersion
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (fileNameWithoutExtension === "changelog") {
|
|
165
|
+
return {
|
|
166
|
+
url: buildUrl(`/docs/${resourceConfig.docsPath}/${resourceId}/${resourceVersion}/changelog`, config),
|
|
167
|
+
title: data.title || `${resourceData.name || resourceId} changelog`,
|
|
168
|
+
summary: data.summary,
|
|
169
|
+
type: "Changelog",
|
|
170
|
+
collection: "changelog",
|
|
171
|
+
id: resourceId,
|
|
172
|
+
version: resourceVersion
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
const docsIndex = segments.indexOf("docs");
|
|
176
|
+
if (docsIndex > resourceMatch.index) {
|
|
177
|
+
const docType = data.type || segments[docsIndex + 1] || "pages";
|
|
178
|
+
const docId = inferDocIdFromFile(normalizedRelativePath, data.id);
|
|
179
|
+
const title = data.title || stripNumericPrefix(removeExtension(fileName));
|
|
180
|
+
return {
|
|
181
|
+
url: buildUrl(`/docs/${resourceConfig.docsPath}/${resourceId}/${resourceVersion}/${docType}/${docId}`, config),
|
|
182
|
+
title,
|
|
183
|
+
summary: data.summary,
|
|
184
|
+
type: "Resource Doc",
|
|
185
|
+
collection: docType,
|
|
186
|
+
id: docId,
|
|
187
|
+
version: data.version || resourceVersion
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
if (segments[0] === "diagrams") {
|
|
191
|
+
const id = data.id || resourceFolderId;
|
|
192
|
+
const version = data.version || resourceVersion;
|
|
193
|
+
return {
|
|
194
|
+
url: buildUrl(`/diagrams/${id}/${version}`, config),
|
|
195
|
+
title: data.name || data.title || id,
|
|
196
|
+
summary: data.summary,
|
|
197
|
+
type: "Design",
|
|
198
|
+
collection: "diagrams",
|
|
199
|
+
id,
|
|
200
|
+
version
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
};
|
|
205
|
+
var collectSearchRecords = async ({
|
|
206
|
+
projectDir,
|
|
207
|
+
config
|
|
208
|
+
}) => {
|
|
209
|
+
const files = await glob("**/*.{md,mdx}", {
|
|
210
|
+
cwd: projectDir,
|
|
211
|
+
absolute: true,
|
|
212
|
+
nodir: true,
|
|
213
|
+
ignore: IGNORED_GLOBS,
|
|
214
|
+
windowsPathsNoEscape: process.platform === "win32"
|
|
215
|
+
});
|
|
216
|
+
const records = await Promise.all(
|
|
217
|
+
files.map(async (file) => {
|
|
218
|
+
const raw = await fs.readFile(file, "utf8");
|
|
219
|
+
const parsed = matter(raw);
|
|
220
|
+
const relativePath = normalizePath(path.relative(projectDir, file));
|
|
221
|
+
const baseRecord = await deriveRecordFromPath({
|
|
222
|
+
projectDir,
|
|
223
|
+
relativePath,
|
|
224
|
+
data: parsed.data,
|
|
225
|
+
config
|
|
226
|
+
});
|
|
227
|
+
if (!baseRecord) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
const frontmatterText = valueToSearchText({
|
|
231
|
+
id: baseRecord.id,
|
|
232
|
+
title: baseRecord.title,
|
|
233
|
+
summary: baseRecord.summary,
|
|
234
|
+
version: baseRecord.version,
|
|
235
|
+
owners: parsed.data.owners,
|
|
236
|
+
badges: parsed.data.badges
|
|
237
|
+
});
|
|
238
|
+
const content = [frontmatterText, markdownToSearchText(parsed.content)].filter(Boolean).join("\n\n");
|
|
239
|
+
if (!content.trim()) {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
...baseRecord,
|
|
244
|
+
content
|
|
245
|
+
};
|
|
246
|
+
})
|
|
247
|
+
);
|
|
248
|
+
const uniqueRecords = /* @__PURE__ */ new Map();
|
|
249
|
+
for (const record of records) {
|
|
250
|
+
if (!record) continue;
|
|
251
|
+
uniqueRecords.set(record.url, record);
|
|
252
|
+
}
|
|
253
|
+
return [...uniqueRecords.values()].sort((a, b) => a.url.localeCompare(b.url));
|
|
254
|
+
};
|
|
255
|
+
var getSearchOutputPath = ({
|
|
256
|
+
outDir,
|
|
257
|
+
isServer,
|
|
258
|
+
searchOutputPath
|
|
259
|
+
}) => {
|
|
260
|
+
if (searchOutputPath) {
|
|
261
|
+
return searchOutputPath;
|
|
262
|
+
}
|
|
263
|
+
return path.join(outDir, isServer ? "client" : "", "pagefind");
|
|
264
|
+
};
|
|
265
|
+
var buildSearchIndex = async ({ projectDir, outDir, config, isServer, searchOutputPath }) => {
|
|
266
|
+
const records = await collectSearchRecords({ projectDir, config });
|
|
267
|
+
if (records.length === 0) {
|
|
268
|
+
throw new Error("No searchable Markdown or MDX content was found.");
|
|
269
|
+
}
|
|
270
|
+
const pagefind = await import("pagefind");
|
|
271
|
+
const { index } = await pagefind.createIndex({
|
|
272
|
+
keepIndexUrl: false,
|
|
273
|
+
writePlayground: false
|
|
274
|
+
});
|
|
275
|
+
const errors = [];
|
|
276
|
+
for (const record of records) {
|
|
277
|
+
const result = await index.addCustomRecord({
|
|
278
|
+
url: record.url,
|
|
279
|
+
content: record.content,
|
|
280
|
+
language: "en",
|
|
281
|
+
meta: {
|
|
282
|
+
title: record.title,
|
|
283
|
+
summary: record.summary || "",
|
|
284
|
+
type: record.type,
|
|
285
|
+
collection: record.collection,
|
|
286
|
+
id: record.id || "",
|
|
287
|
+
version: record.version || ""
|
|
288
|
+
},
|
|
289
|
+
filters: {
|
|
290
|
+
type: [record.type],
|
|
291
|
+
collection: [record.collection]
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
if (result.errors?.length) {
|
|
295
|
+
errors.push(...result.errors.map((error) => `${record.url}: ${error.message || error}`));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
const outputPath = getSearchOutputPath({ outDir, isServer, searchOutputPath });
|
|
299
|
+
await fs.rm(outputPath, { recursive: true, force: true });
|
|
300
|
+
const writeResult = await index.writeFiles({ outputPath });
|
|
301
|
+
if (writeResult.errors?.length) {
|
|
302
|
+
errors.push(...writeResult.errors.map((error) => error.message || String(error)));
|
|
303
|
+
}
|
|
304
|
+
await index.deleteIndex?.();
|
|
305
|
+
await pagefind.close?.();
|
|
306
|
+
if (errors.length > 0) {
|
|
307
|
+
throw new Error(`Failed to build indexed search:
|
|
308
|
+
${errors.join("\n")}`);
|
|
309
|
+
}
|
|
310
|
+
return {
|
|
311
|
+
records: records.length,
|
|
312
|
+
outputPath
|
|
313
|
+
};
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
export {
|
|
317
|
+
markdownToSearchText,
|
|
318
|
+
collectSearchRecords,
|
|
319
|
+
buildSearchIndex
|
|
320
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
raiseEvent
|
|
3
|
-
} from "./chunk-VJ357XOI.js";
|
|
4
1
|
import {
|
|
5
2
|
countResources,
|
|
6
3
|
serializeCounts
|
|
7
4
|
} from "./chunk-4UVFXLPI.js";
|
|
5
|
+
import {
|
|
6
|
+
raiseEvent
|
|
7
|
+
} from "./chunk-V22QY5Q3.js";
|
|
8
8
|
import {
|
|
9
9
|
getEventCatalogConfigFile,
|
|
10
10
|
verifyRequiredFieldsAreInCatalogConfigFile
|
|
@@ -13,6 +13,10 @@ var isOutputServer = async () => {
|
|
|
13
13
|
const config = await getEventCatalogConfigFile(process.env.PROJECT_DIR || "");
|
|
14
14
|
return config?.output === "server";
|
|
15
15
|
};
|
|
16
|
+
var isIndexedSearchEnabled = async () => {
|
|
17
|
+
const config = await getEventCatalogConfigFile(process.env.PROJECT_DIR || "");
|
|
18
|
+
return config?.search?.type === "indexed";
|
|
19
|
+
};
|
|
16
20
|
var isAuthEnabled = async () => {
|
|
17
21
|
const directory = process.env.PROJECT_DIR || process.cwd();
|
|
18
22
|
const hasAuthConfig = fs.existsSync(join(directory, "eventcatalog.auth.js"));
|
|
@@ -22,5 +26,6 @@ var isAuthEnabled = async () => {
|
|
|
22
26
|
export {
|
|
23
27
|
getProjectOutDir,
|
|
24
28
|
isOutputServer,
|
|
29
|
+
isIndexedSearchEnabled,
|
|
25
30
|
isAuthEnabled
|
|
26
31
|
};
|
package/dist/constants.cjs
CHANGED
package/dist/constants.js
CHANGED
|
@@ -400,6 +400,28 @@ module.exports = {
|
|
|
400
400
|
| ------ | ---- | ------- | ----------- |
|
|
401
401
|
| `chat.enabled` | `boolean` | `true` | Enables or disables the AI chat feature. Set to `false` to hide the chat UI and prevent chat requests even when all other prerequisites are met. |
|
|
402
402
|
|
|
403
|
+
### `search` {#search}
|
|
404
|
+
|
|
405
|
+
<AddedIn version="3.36.0" />
|
|
406
|
+
|
|
407
|
+
- Type: `object`
|
|
408
|
+
|
|
409
|
+
Configure the search mode for your catalog.
|
|
410
|
+
|
|
411
|
+
```js title="eventcatalog.config.js"
|
|
412
|
+
module.exports = {
|
|
413
|
+
search: {
|
|
414
|
+
type: 'resource', // default
|
|
415
|
+
},
|
|
416
|
+
};
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
| Option | Type | Default | Description |
|
|
420
|
+
| ------ | ---- | ------- | ----------- |
|
|
421
|
+
| `search.type` | `'resource'` \| `'indexed'` | `'resource'` | `'resource'` searches resource metadata only. `'indexed'` enables full-content search powered by [Pagefind](https://pagefind.app/) and builds a static index at build time. |
|
|
422
|
+
|
|
423
|
+
See the [Search customization](/docs/development/customization/search) guide for details and trade-offs.
|
|
424
|
+
|
|
403
425
|
### `changelog` {#changelog}
|
|
404
426
|
|
|
405
427
|
- Type: `object`
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 1
|
|
3
|
+
keywords:
|
|
4
|
+
- EventCatalog search
|
|
5
|
+
- full-content search
|
|
6
|
+
- indexed search
|
|
7
|
+
- pagefind
|
|
8
|
+
- search configuration
|
|
9
|
+
sidebar_label: Search
|
|
10
|
+
title: Search
|
|
11
|
+
description: Configure resource metadata search or opt-in to full-content indexed search
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
import AddedIn from '@site/src/components/MDX/AddedIn';
|
|
15
|
+
|
|
16
|
+
<AddedIn version="3.36.0" />
|
|
17
|
+
|
|
18
|
+
EventCatalog ships with two search modes. The default is a fast metadata search that works with no extra configuration. An opt-in indexed mode adds full-content search powered by [Pagefind](https://pagefind.app/).
|
|
19
|
+
|
|
20
|
+
## Understand the modes
|
|
21
|
+
|
|
22
|
+
**Resource search (default)** indexes the metadata of every catalog resource — names, summaries, badges, types, and identifiers. It is fast, requires no build step, and works in both `static` and `server` output modes.
|
|
23
|
+
|
|
24
|
+
**Indexed search (opt-in)** builds a static index of the full markdown content of your catalog at build time. It can find matches inside the body of a page, changelogs, custom docs, and resource docs — not just the frontmatter fields.
|
|
25
|
+
|
|
26
|
+
## Enable indexed search
|
|
27
|
+
|
|
28
|
+
Set `search.type` to `'indexed'` in `eventcatalog.config.js`:
|
|
29
|
+
|
|
30
|
+
```js title="eventcatalog.config.js"
|
|
31
|
+
module.exports = {
|
|
32
|
+
search: {
|
|
33
|
+
type: 'indexed',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
No other changes are required. The index is built automatically as part of `eventcatalog build` and also during `eventcatalog dev`.
|
|
39
|
+
|
|
40
|
+
## What gets indexed
|
|
41
|
+
|
|
42
|
+
When indexed search is enabled, the following content is included in the index:
|
|
43
|
+
|
|
44
|
+
- All catalog resources: events, commands, queries, services, domains, subdomains, channels, containers, data products, entities, and flows
|
|
45
|
+
- Custom docs pages
|
|
46
|
+
- Resource docs
|
|
47
|
+
- Changelogs
|
|
48
|
+
|
|
49
|
+
## When the index is built
|
|
50
|
+
|
|
51
|
+
During `eventcatalog build`, the indexer runs after the Astro build and writes the index to `<outDir>/pagefind`.
|
|
52
|
+
|
|
53
|
+
During `eventcatalog dev`, the index is built on startup and rebuilt automatically whenever any `.md` or `.mdx` file changes (debounced to avoid excessive rebuilds). The first build may take a few seconds depending on the size of your catalog. Subsequent incremental rebuilds are faster.
|
|
54
|
+
|
|
55
|
+
## Result ranking
|
|
56
|
+
|
|
57
|
+
Indexed results are ranked by relevance. Matches in the resource title and identifier score highest, followed by matches in the summary and type. Content-body matches score lower than title matches but are still surfaced when no title match is found.
|
|
58
|
+
|
|
59
|
+
## Auth and the `/pagefind` assets
|
|
60
|
+
|
|
61
|
+
:::warning Private catalogs
|
|
62
|
+
If your catalog uses authentication (an `eventcatalog.auth.js` file is present), the generated `/pagefind` directory is served as static client-readable assets. Anyone who can load the page can download the index, which contains the full text of all indexed content.
|
|
63
|
+
|
|
64
|
+
Ensure your deployment platform protects the `/pagefind` path behind the same authentication layer as the rest of your catalog.
|
|
65
|
+
:::
|
|
66
|
+
|
|
67
|
+
## Keep resource search
|
|
68
|
+
|
|
69
|
+
To stay on the default resource search, either omit the `search` key entirely or set the type explicitly:
|
|
70
|
+
|
|
71
|
+
```js title="eventcatalog.config.js"
|
|
72
|
+
module.exports = {
|
|
73
|
+
search: {
|
|
74
|
+
type: 'resource', // default, no index built
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Existing catalogs are not affected by this feature — no changes are needed unless you want to opt in.
|