@nocobase/server 2.0.0-beta.9 → 2.0.0
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/lib/aes-encryptor.d.ts +1 -0
- package/lib/aes-encryptor.js +8 -5
- package/lib/ai/create-docs-index.d.ts +13 -0
- package/lib/ai/create-docs-index.js +892 -0
- package/lib/app-supervisor/app-options-factory.d.ts +80 -0
- package/lib/app-supervisor/app-options-factory.js +91 -0
- package/lib/app-supervisor/condition-registry.d.ts +18 -0
- package/lib/app-supervisor/condition-registry.js +60 -0
- package/lib/app-supervisor/db-creator.d.ts +16 -0
- package/lib/app-supervisor/db-creator.js +163 -0
- package/lib/app-supervisor/db-drivers.d.ts +11 -0
- package/lib/app-supervisor/db-drivers.js +52 -0
- package/lib/app-supervisor/index.d.ts +161 -0
- package/lib/app-supervisor/index.js +690 -0
- package/lib/app-supervisor/main-only-adapter.d.ts +37 -0
- package/lib/app-supervisor/main-only-adapter.js +156 -0
- package/lib/app-supervisor/types.d.ts +161 -0
- package/lib/app-supervisor/types.js +24 -0
- package/lib/application.d.ts +3 -1
- package/lib/application.js +10 -6
- package/lib/commands/ai.d.ts +11 -0
- package/lib/commands/ai.js +40 -0
- package/lib/commands/console.js +1 -1
- package/lib/commands/index.js +2 -0
- package/lib/commands/install.js +2 -0
- package/lib/commands/start.js +3 -0
- package/lib/commands/upgrade.js +2 -0
- package/lib/gateway/errors.js +1 -1
- package/lib/gateway/index.js +64 -15
- package/lib/gateway/ipc-socket-server.js +1 -1
- package/lib/gateway/ws-server.js +3 -2
- package/lib/helper.js +20 -3
- package/lib/plugin-manager/deps.js +1 -1
- package/lib/plugin-manager/plugin-manager.js +2 -0
- package/lib/plugin.d.ts +5 -0
- package/lib/plugin.js +25 -0
- package/lib/redis-connection-manager.d.ts +15 -5
- package/lib/redis-connection-manager.js +117 -24
- package/package.json +18 -17
- package/lib/app-supervisor.d.ts +0 -74
- package/lib/app-supervisor.js +0 -338
|
@@ -0,0 +1,892 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __create = Object.create;
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
15
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
17
|
+
var __export = (target, all) => {
|
|
18
|
+
for (var name in all)
|
|
19
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
20
|
+
};
|
|
21
|
+
var __copyProps = (to, from, except, desc) => {
|
|
22
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
23
|
+
for (let key of __getOwnPropNames(from))
|
|
24
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
25
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
26
|
+
}
|
|
27
|
+
return to;
|
|
28
|
+
};
|
|
29
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
30
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
31
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
32
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
33
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
34
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
35
|
+
mod
|
|
36
|
+
));
|
|
37
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
|
+
var create_docs_index_exports = {};
|
|
39
|
+
__export(create_docs_index_exports, {
|
|
40
|
+
createDocsIndex: () => createDocsIndex
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(create_docs_index_exports);
|
|
43
|
+
var import_fast_glob = __toESM(require("fast-glob"));
|
|
44
|
+
var import_fs_extra = __toESM(require("fs-extra"));
|
|
45
|
+
var import_path = __toESM(require("path"));
|
|
46
|
+
var import_ai = require("@nocobase/ai");
|
|
47
|
+
var import_findPackageNames = require("../plugin-manager/findPackageNames");
|
|
48
|
+
var import_plugin_manager = require("../plugin-manager");
|
|
49
|
+
const DOCS_STORAGE_DIR = import_path.default.resolve(process.cwd(), "storage/ai/docs");
|
|
50
|
+
const REFERENCE_START = "<!-- docs:references:start -->";
|
|
51
|
+
const REFERENCE_END = "<!-- docs:references:end -->";
|
|
52
|
+
const SPLIT_REFERENCE_START = "<!-- docs:splits:start -->";
|
|
53
|
+
const SPLIT_REFERENCE_END = "<!-- docs:splits:end -->";
|
|
54
|
+
const SPLIT_MAX_LENGTH = 5e3;
|
|
55
|
+
const SPLIT_MAX_CODE_BLOCKS = 3;
|
|
56
|
+
const CREATE_INDEX_RETRY_MAX = 3;
|
|
57
|
+
const CREATE_INDEX_RETRY_DELAY_MS = 200;
|
|
58
|
+
function normalizeMetaEntries(meta, fallbackModule) {
|
|
59
|
+
if (Array.isArray(meta)) {
|
|
60
|
+
return meta.filter((item) => item && typeof item.module === "string").map((item) => ({
|
|
61
|
+
module: item.module.trim(),
|
|
62
|
+
description: typeof item.description === "string" ? item.description.trim() : "",
|
|
63
|
+
source: typeof item.source === "string" ? item.source.trim() : ""
|
|
64
|
+
})).filter((item) => item.module);
|
|
65
|
+
}
|
|
66
|
+
if (meta && typeof meta.module === "string") {
|
|
67
|
+
return [
|
|
68
|
+
{
|
|
69
|
+
module: meta.module.trim() || fallbackModule,
|
|
70
|
+
description: typeof meta.description === "string" ? meta.description.trim() : "",
|
|
71
|
+
source: typeof meta.source === "string" ? meta.source.trim() : ""
|
|
72
|
+
}
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
return [
|
|
76
|
+
{
|
|
77
|
+
module: fallbackModule,
|
|
78
|
+
description: "",
|
|
79
|
+
source: ""
|
|
80
|
+
}
|
|
81
|
+
];
|
|
82
|
+
}
|
|
83
|
+
__name(normalizeMetaEntries, "normalizeMetaEntries");
|
|
84
|
+
async function resolvePkgs(pkg) {
|
|
85
|
+
if (!pkg) {
|
|
86
|
+
return await (0, import_findPackageNames.findAllPlugins)();
|
|
87
|
+
}
|
|
88
|
+
const scopes = (Array.isArray(pkg) ? pkg : pkg.split(",")).map((item) => item.trim()).filter(Boolean);
|
|
89
|
+
return Array.from(new Set(scopes));
|
|
90
|
+
}
|
|
91
|
+
__name(resolvePkgs, "resolvePkgs");
|
|
92
|
+
function buildDirectoryChildren(files, docsDir) {
|
|
93
|
+
const map = /* @__PURE__ */ new Map();
|
|
94
|
+
const ensureDir = /* @__PURE__ */ __name((dir) => {
|
|
95
|
+
if (!map.has(dir)) {
|
|
96
|
+
map.set(dir, { files: [], directories: [] });
|
|
97
|
+
}
|
|
98
|
+
}, "ensureDir");
|
|
99
|
+
ensureDir(docsDir);
|
|
100
|
+
files.forEach((file) => {
|
|
101
|
+
var _a;
|
|
102
|
+
const dir = import_path.default.dirname(file);
|
|
103
|
+
ensureDir(dir);
|
|
104
|
+
(_a = map.get(dir)) == null ? void 0 : _a.files.push(file);
|
|
105
|
+
});
|
|
106
|
+
files.forEach((file) => {
|
|
107
|
+
let current = import_path.default.dirname(file);
|
|
108
|
+
while (current && current.startsWith(docsDir)) {
|
|
109
|
+
const parent = import_path.default.dirname(current);
|
|
110
|
+
if (parent && parent.startsWith(docsDir)) {
|
|
111
|
+
ensureDir(parent);
|
|
112
|
+
const list = map.get(parent);
|
|
113
|
+
if (list && !list.directories.includes(current)) {
|
|
114
|
+
list.directories.push(current);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (current === docsDir) break;
|
|
118
|
+
current = import_path.default.dirname(current);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return map;
|
|
122
|
+
}
|
|
123
|
+
__name(buildDirectoryChildren, "buildDirectoryChildren");
|
|
124
|
+
async function resolveSourcePath(source, metaFile) {
|
|
125
|
+
if (!source) return "";
|
|
126
|
+
if (import_path.default.isAbsolute(source)) {
|
|
127
|
+
return await import_fs_extra.default.pathExists(source) ? source : "";
|
|
128
|
+
}
|
|
129
|
+
const fromRepo = import_path.default.resolve(process.cwd(), source);
|
|
130
|
+
if (await import_fs_extra.default.pathExists(fromRepo)) {
|
|
131
|
+
return fromRepo;
|
|
132
|
+
}
|
|
133
|
+
const fromMeta = import_path.default.resolve(import_path.default.dirname(metaFile), source);
|
|
134
|
+
if (await import_fs_extra.default.pathExists(fromMeta)) {
|
|
135
|
+
return fromMeta;
|
|
136
|
+
}
|
|
137
|
+
return "";
|
|
138
|
+
}
|
|
139
|
+
__name(resolveSourcePath, "resolveSourcePath");
|
|
140
|
+
function errorToString(error) {
|
|
141
|
+
if (error instanceof Error) {
|
|
142
|
+
return error.stack || error.message;
|
|
143
|
+
}
|
|
144
|
+
return String(error);
|
|
145
|
+
}
|
|
146
|
+
__name(errorToString, "errorToString");
|
|
147
|
+
async function collectModuleGroups(packageName) {
|
|
148
|
+
const packageJsonPath = require.resolve(`${packageName}/package.json`);
|
|
149
|
+
const packageDir = import_path.default.dirname(packageJsonPath);
|
|
150
|
+
const distDocsDir = import_path.default.join(packageDir, "dist", "ai", "docs");
|
|
151
|
+
const srcDocsDir = import_path.default.join(packageDir, "src", "ai", "docs");
|
|
152
|
+
const preferSrc = process.env.APP_ENV !== "production";
|
|
153
|
+
const preferredDocsDir = preferSrc ? srcDocsDir : distDocsDir;
|
|
154
|
+
const fallbackDocsDir = preferSrc ? distDocsDir : srcDocsDir;
|
|
155
|
+
const docsDir = await import_fs_extra.default.pathExists(preferredDocsDir) ? preferredDocsDir : fallbackDocsDir;
|
|
156
|
+
if (!await import_fs_extra.default.pathExists(docsDir)) {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
const rootMetaPath = import_path.default.join(docsDir, "meta.json");
|
|
160
|
+
let metaEntries = [];
|
|
161
|
+
if (await import_fs_extra.default.pathExists(rootMetaPath)) {
|
|
162
|
+
try {
|
|
163
|
+
const rootMeta = await import_fs_extra.default.readJson(rootMetaPath);
|
|
164
|
+
metaEntries = normalizeMetaEntries(rootMeta, import_path.default.basename(docsDir));
|
|
165
|
+
} catch {
|
|
166
|
+
metaEntries = [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const moduleMetaFiles = metaEntries.length === 0 ? await (0, import_fast_glob.default)(["*/meta.json"], {
|
|
170
|
+
cwd: docsDir,
|
|
171
|
+
onlyFiles: true,
|
|
172
|
+
absolute: true
|
|
173
|
+
}) : [];
|
|
174
|
+
if (!metaEntries.length && !moduleMetaFiles.length) {
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
moduleMetaFiles.sort();
|
|
178
|
+
const moduleRoots = moduleMetaFiles.map((metaPath) => import_path.default.dirname(metaPath));
|
|
179
|
+
const groups = [];
|
|
180
|
+
const entriesToProcess = metaEntries.length > 0 ? metaEntries.map((entry) => ({ metaFile: rootMetaPath, entry })) : moduleMetaFiles.map((metaFile) => ({ metaFile, entry: void 0 }));
|
|
181
|
+
for (const item of entriesToProcess) {
|
|
182
|
+
const metaFile = item.metaFile;
|
|
183
|
+
const moduleRoot = import_path.default.dirname(metaFile);
|
|
184
|
+
const moduleDirName = import_path.default.basename(moduleRoot);
|
|
185
|
+
let perFileEntries = [];
|
|
186
|
+
if (item.entry) {
|
|
187
|
+
perFileEntries = [item.entry];
|
|
188
|
+
} else {
|
|
189
|
+
try {
|
|
190
|
+
const meta = await import_fs_extra.default.readJson(metaFile);
|
|
191
|
+
perFileEntries = normalizeMetaEntries(meta, moduleDirName);
|
|
192
|
+
} catch {
|
|
193
|
+
perFileEntries = normalizeMetaEntries(null, moduleDirName);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
for (const metaEntry of perFileEntries) {
|
|
197
|
+
const moduleName = metaEntry.module || moduleDirName;
|
|
198
|
+
const description = metaEntry.description || "";
|
|
199
|
+
const source = metaEntry.source || "";
|
|
200
|
+
const defaultModuleRoot = import_path.default.join(docsDir, moduleName);
|
|
201
|
+
let effectiveModuleRoot = defaultModuleRoot;
|
|
202
|
+
if (source && preferSrc) {
|
|
203
|
+
const resolvedSource = await resolveSourcePath(source, metaFile);
|
|
204
|
+
if (resolvedSource) {
|
|
205
|
+
effectiveModuleRoot = resolvedSource;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (!await import_fs_extra.default.pathExists(effectiveModuleRoot)) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const ignore = [];
|
|
212
|
+
if (moduleRoot === docsDir && effectiveModuleRoot === moduleRoot) {
|
|
213
|
+
for (const otherRoot of moduleRoots) {
|
|
214
|
+
if (otherRoot === moduleRoot) continue;
|
|
215
|
+
const rel = import_path.default.relative(moduleRoot, otherRoot).split(import_path.default.sep).join("/");
|
|
216
|
+
if (rel && !rel.startsWith("..")) {
|
|
217
|
+
ignore.push(`${rel}/**`);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const files = await (0, import_fast_glob.default)(["**/*.{md,mdx}"], {
|
|
222
|
+
cwd: effectiveModuleRoot,
|
|
223
|
+
onlyFiles: true,
|
|
224
|
+
absolute: true,
|
|
225
|
+
ignore
|
|
226
|
+
});
|
|
227
|
+
if (!files.length) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
files.sort();
|
|
231
|
+
const directoryChildren = buildDirectoryChildren(files, effectiveModuleRoot);
|
|
232
|
+
const docEntries = await Promise.all(
|
|
233
|
+
files.map(async (file) => {
|
|
234
|
+
const relativePath = import_path.default.relative(effectiveModuleRoot, file);
|
|
235
|
+
const normalizedRelativePath = relativePath.split(import_path.default.sep).join("/");
|
|
236
|
+
const canonicalPath = import_path.default.posix.join(moduleName, normalizedRelativePath);
|
|
237
|
+
const content = await import_fs_extra.default.readFile(file, "utf8");
|
|
238
|
+
const meta = extractDocMetadata(content, file);
|
|
239
|
+
return {
|
|
240
|
+
absolutePath: file,
|
|
241
|
+
relativePath,
|
|
242
|
+
canonicalPath,
|
|
243
|
+
content,
|
|
244
|
+
moduleName,
|
|
245
|
+
moduleRoot,
|
|
246
|
+
packageName,
|
|
247
|
+
...meta
|
|
248
|
+
};
|
|
249
|
+
})
|
|
250
|
+
);
|
|
251
|
+
const docMap = new Map(docEntries.map((entry) => [entry.absolutePath, entry]));
|
|
252
|
+
groups.push({
|
|
253
|
+
moduleName,
|
|
254
|
+
description,
|
|
255
|
+
moduleRoot,
|
|
256
|
+
packageName,
|
|
257
|
+
entries: docEntries,
|
|
258
|
+
directoryChildren,
|
|
259
|
+
docMap
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return groups;
|
|
264
|
+
}
|
|
265
|
+
__name(collectModuleGroups, "collectModuleGroups");
|
|
266
|
+
async function buildDocsIndexForPackages(packageNames) {
|
|
267
|
+
const moduleGroups = /* @__PURE__ */ new Map();
|
|
268
|
+
const moduleDescriptions = /* @__PURE__ */ new Map();
|
|
269
|
+
const conflicts = /* @__PURE__ */ new Map();
|
|
270
|
+
for (const packageName of packageNames) {
|
|
271
|
+
const groups = await collectModuleGroups(packageName);
|
|
272
|
+
for (const group of groups) {
|
|
273
|
+
const existing = moduleGroups.get(group.moduleName);
|
|
274
|
+
if (existing) {
|
|
275
|
+
existing.push(group);
|
|
276
|
+
} else {
|
|
277
|
+
moduleGroups.set(group.moduleName, [group]);
|
|
278
|
+
}
|
|
279
|
+
if (group.description) {
|
|
280
|
+
const existingDesc = moduleDescriptions.get(group.moduleName);
|
|
281
|
+
if (existingDesc && existingDesc !== group.description) {
|
|
282
|
+
const list = conflicts.get(group.moduleName) || [];
|
|
283
|
+
list.push(
|
|
284
|
+
`${group.packageName}: description mismatch (existing="${existingDesc}", new="${group.description}")`
|
|
285
|
+
);
|
|
286
|
+
conflicts.set(group.moduleName, list);
|
|
287
|
+
} else if (!existingDesc) {
|
|
288
|
+
moduleDescriptions.set(group.moduleName, group.description);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
const results = /* @__PURE__ */ new Map();
|
|
294
|
+
for (const [moduleName, groups] of moduleGroups.entries()) {
|
|
295
|
+
const outputDir = import_path.default.join(DOCS_STORAGE_DIR, moduleName);
|
|
296
|
+
if (!groups.length) {
|
|
297
|
+
results.set(moduleName, { created: false, reason: "no doc files found" });
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
const docsOutputDir = outputDir;
|
|
301
|
+
const index = new import_ai.FlexSearchIndex();
|
|
302
|
+
const fileMap = {};
|
|
303
|
+
let currentId = 1;
|
|
304
|
+
let indexedDocs = 0;
|
|
305
|
+
const markdownExt = /* @__PURE__ */ new Set([".md", ".mdx"]);
|
|
306
|
+
const storagePathMap = /* @__PURE__ */ new Map();
|
|
307
|
+
const moduleConflicts = [];
|
|
308
|
+
await import_fs_extra.default.remove(outputDir);
|
|
309
|
+
await import_fs_extra.default.ensureDir(docsOutputDir);
|
|
310
|
+
const sortedGroups = groups.slice().sort((a, b) => {
|
|
311
|
+
if (a.packageName !== b.packageName) {
|
|
312
|
+
return a.packageName.localeCompare(b.packageName);
|
|
313
|
+
}
|
|
314
|
+
return a.moduleRoot.localeCompare(b.moduleRoot);
|
|
315
|
+
});
|
|
316
|
+
for (const group of sortedGroups) {
|
|
317
|
+
for (const entry of group.entries) {
|
|
318
|
+
const storageDocPath = import_path.default.join(docsOutputDir, entry.relativePath);
|
|
319
|
+
const existing = storagePathMap.get(storageDocPath);
|
|
320
|
+
if (existing) {
|
|
321
|
+
moduleConflicts.push(
|
|
322
|
+
`Duplicate path "${entry.relativePath}" from ${entry.packageName} and ${existing.packageName}`
|
|
323
|
+
);
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
storagePathMap.set(storageDocPath, entry);
|
|
327
|
+
await import_fs_extra.default.ensureDir(import_path.default.dirname(storageDocPath));
|
|
328
|
+
let processedContent = rewriteRelativeLinks(entry.content, entry);
|
|
329
|
+
const splitResult = splitMarkdownIfNeeded(processedContent, entry);
|
|
330
|
+
const splitRefs = splitResult.splits.map((split, index2) => {
|
|
331
|
+
const splitRelativePath = entry.relativePath.replace(/\.mdx?$/i, "") + split.suffix;
|
|
332
|
+
const splitCanonicalPath = import_path.default.posix.join(entry.moduleName, splitRelativePath.split(import_path.default.sep).join("/"));
|
|
333
|
+
return {
|
|
334
|
+
index: index2,
|
|
335
|
+
splitRelativePath,
|
|
336
|
+
splitCanonicalPath,
|
|
337
|
+
...split
|
|
338
|
+
};
|
|
339
|
+
});
|
|
340
|
+
processedContent = splitResult.content;
|
|
341
|
+
if (entry.isIndex) {
|
|
342
|
+
processedContent = applyReferencesToIndex(
|
|
343
|
+
processedContent,
|
|
344
|
+
entry.absolutePath,
|
|
345
|
+
group.directoryChildren,
|
|
346
|
+
group.docMap
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
if (splitRefs.length) {
|
|
350
|
+
processedContent = applySplitReferences(
|
|
351
|
+
processedContent,
|
|
352
|
+
splitRefs.map((split) => ({
|
|
353
|
+
pathRef: split.splitCanonicalPath,
|
|
354
|
+
title: split.title,
|
|
355
|
+
description: split.description
|
|
356
|
+
}))
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
if (!entry.hasFrontMatter) {
|
|
360
|
+
processedContent = injectFrontMatter(processedContent, entry);
|
|
361
|
+
}
|
|
362
|
+
await import_fs_extra.default.writeFile(storageDocPath, processedContent, "utf8");
|
|
363
|
+
for (const split of splitRefs) {
|
|
364
|
+
const splitStoragePath = import_path.default.join(docsOutputDir, split.splitRelativePath);
|
|
365
|
+
if (storagePathMap.has(splitStoragePath)) {
|
|
366
|
+
moduleConflicts.push(`Duplicate split path "${split.splitRelativePath}" in ${entry.packageName}`);
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
storagePathMap.set(splitStoragePath, entry);
|
|
370
|
+
await import_fs_extra.default.ensureDir(import_path.default.dirname(splitStoragePath));
|
|
371
|
+
let splitContent = split.content;
|
|
372
|
+
splitContent = injectFrontMatter(splitContent, {
|
|
373
|
+
title: split.title,
|
|
374
|
+
description: split.description
|
|
375
|
+
});
|
|
376
|
+
await import_fs_extra.default.writeFile(splitStoragePath, splitContent, "utf8");
|
|
377
|
+
}
|
|
378
|
+
const ext = import_path.default.extname(entry.absolutePath).toLowerCase();
|
|
379
|
+
if (!markdownExt.has(ext)) {
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
const content = processedContent.trim();
|
|
383
|
+
if (!content) {
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
const docId = currentId++;
|
|
387
|
+
await index.addAsync(docId, processedContent);
|
|
388
|
+
fileMap[docId] = entry.canonicalPath;
|
|
389
|
+
indexedDocs++;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (!indexedDocs) {
|
|
393
|
+
await import_fs_extra.default.remove(outputDir);
|
|
394
|
+
results.set(moduleName, { created: false, reason: "no markdown doc content to index" });
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
const indexData = {};
|
|
398
|
+
index.export((key, data) => {
|
|
399
|
+
indexData[key] = data;
|
|
400
|
+
});
|
|
401
|
+
await import_fs_extra.default.ensureDir(outputDir);
|
|
402
|
+
await import_fs_extra.default.writeJSON(import_path.default.join(outputDir, "index.json"), indexData, { spaces: 2 });
|
|
403
|
+
await import_fs_extra.default.writeJSON(import_path.default.join(outputDir, "files.json"), fileMap, { spaces: 2 });
|
|
404
|
+
const allConflicts = [...conflicts.get(moduleName) || [], ...moduleConflicts];
|
|
405
|
+
if (allConflicts.length) {
|
|
406
|
+
results.set(moduleName, { created: true, conflicts: allConflicts });
|
|
407
|
+
} else {
|
|
408
|
+
results.set(moduleName, { created: true });
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (moduleGroups.size) {
|
|
412
|
+
const metaOutput = {};
|
|
413
|
+
for (const moduleName of moduleGroups.keys()) {
|
|
414
|
+
metaOutput[moduleName] = {
|
|
415
|
+
description: moduleDescriptions.get(moduleName) || ""
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
await import_fs_extra.default.ensureDir(DOCS_STORAGE_DIR);
|
|
419
|
+
await import_fs_extra.default.writeJSON(import_path.default.join(DOCS_STORAGE_DIR, "meta.json"), metaOutput, { spaces: 2 });
|
|
420
|
+
}
|
|
421
|
+
return results;
|
|
422
|
+
}
|
|
423
|
+
__name(buildDocsIndexForPackages, "buildDocsIndexForPackages");
|
|
424
|
+
function extractDocMetadata(content, filePath) {
|
|
425
|
+
const normalized = content.replace(/\r\n/g, "\n");
|
|
426
|
+
const hasFrontMatter = normalized.startsWith("---\n") && normalized.indexOf("\n---", 4) !== -1;
|
|
427
|
+
let searchStart = 0;
|
|
428
|
+
if (hasFrontMatter) {
|
|
429
|
+
const closingIndex = normalized.indexOf("\n---", 4);
|
|
430
|
+
if (closingIndex !== -1) {
|
|
431
|
+
const closingLineEnd = normalized.indexOf("\n", closingIndex + 4);
|
|
432
|
+
searchStart = closingLineEnd === -1 ? normalized.length : closingLineEnd + 1;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
let title = "";
|
|
436
|
+
let description = "";
|
|
437
|
+
const lines = normalized.slice(searchStart).split("\n");
|
|
438
|
+
for (let i = 0; i < lines.length; i++) {
|
|
439
|
+
const line = lines[i].trim();
|
|
440
|
+
if (line.startsWith("# ")) {
|
|
441
|
+
title = line.replace(/^#\s+/, "").trim();
|
|
442
|
+
let j = i + 1;
|
|
443
|
+
const descParts = [];
|
|
444
|
+
while (j < lines.length) {
|
|
445
|
+
const descLine = lines[j].trim();
|
|
446
|
+
if (!descLine) {
|
|
447
|
+
if (descParts.length) break;
|
|
448
|
+
j++;
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
if (descLine.startsWith("#")) break;
|
|
452
|
+
descParts.push(descLine);
|
|
453
|
+
if (descParts.join(" ").length > 160) break;
|
|
454
|
+
j++;
|
|
455
|
+
}
|
|
456
|
+
description = descParts.join(" ");
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (!title) {
|
|
461
|
+
const base = import_path.default.basename(filePath, import_path.default.extname(filePath));
|
|
462
|
+
title = base.split(/[-_]/).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join(" ");
|
|
463
|
+
}
|
|
464
|
+
if (!description) {
|
|
465
|
+
description = `Reference snippet for ${title}`;
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
title,
|
|
469
|
+
description,
|
|
470
|
+
hasFrontMatter,
|
|
471
|
+
isIndex: import_path.default.basename(filePath).toLowerCase() === "index.md"
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
__name(extractDocMetadata, "extractDocMetadata");
|
|
475
|
+
function injectFrontMatter(content, meta) {
|
|
476
|
+
const trimmed = content.replace(/^\uFEFF/, "");
|
|
477
|
+
const fmLines = [
|
|
478
|
+
"---",
|
|
479
|
+
`title: ${JSON.stringify(meta.title)}`,
|
|
480
|
+
`description: ${JSON.stringify(meta.description)}`,
|
|
481
|
+
"---"
|
|
482
|
+
];
|
|
483
|
+
const frontMatter = `${fmLines.join("\n")}
|
|
484
|
+
`;
|
|
485
|
+
const separator = trimmed.startsWith("\n") ? "" : "\n";
|
|
486
|
+
return `${frontMatter}${separator}${trimmed}`;
|
|
487
|
+
}
|
|
488
|
+
__name(injectFrontMatter, "injectFrontMatter");
|
|
489
|
+
function splitFrontMatter(content) {
|
|
490
|
+
const normalized = content.replace(/\r\n/g, "\n");
|
|
491
|
+
if (!normalized.startsWith("---\n")) {
|
|
492
|
+
return { frontMatter: "", body: normalized, hasFrontMatter: false };
|
|
493
|
+
}
|
|
494
|
+
const closingIndex = normalized.indexOf("\n---", 4);
|
|
495
|
+
if (closingIndex === -1) {
|
|
496
|
+
return { frontMatter: "", body: normalized, hasFrontMatter: false };
|
|
497
|
+
}
|
|
498
|
+
const closingLineEnd = normalized.indexOf("\n", closingIndex + 4);
|
|
499
|
+
const bodyStart = closingLineEnd === -1 ? normalized.length : closingLineEnd + 1;
|
|
500
|
+
return {
|
|
501
|
+
frontMatter: normalized.slice(0, bodyStart),
|
|
502
|
+
body: normalized.slice(bodyStart),
|
|
503
|
+
hasFrontMatter: true
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
__name(splitFrontMatter, "splitFrontMatter");
|
|
507
|
+
function getPrimaryHeading(body) {
|
|
508
|
+
var _a;
|
|
509
|
+
const match = body.match(/^#\s+(.+)$/m);
|
|
510
|
+
return ((_a = match == null ? void 0 : match[1]) == null ? void 0 : _a.trim()) || "";
|
|
511
|
+
}
|
|
512
|
+
__name(getPrimaryHeading, "getPrimaryHeading");
|
|
513
|
+
function countCodeBlocks(content) {
|
|
514
|
+
return (content.match(/```[\s\S]*?```/g) || []).length;
|
|
515
|
+
}
|
|
516
|
+
__name(countCodeBlocks, "countCodeBlocks");
|
|
517
|
+
function normalizeHeadingText(text) {
|
|
518
|
+
return text.replace(/^#+\s+/, "").trim();
|
|
519
|
+
}
|
|
520
|
+
__name(normalizeHeadingText, "normalizeHeadingText");
|
|
521
|
+
function splitByHeadings(body) {
|
|
522
|
+
const lines = body.split("\n");
|
|
523
|
+
const sections = [];
|
|
524
|
+
let current = null;
|
|
525
|
+
for (const line of lines) {
|
|
526
|
+
const headingMatch = line.match(/^(#{2,3})\s+(.+)$/);
|
|
527
|
+
if (headingMatch) {
|
|
528
|
+
if (current) {
|
|
529
|
+
sections.push(current);
|
|
530
|
+
}
|
|
531
|
+
current = {
|
|
532
|
+
level: headingMatch[1].length,
|
|
533
|
+
heading: normalizeHeadingText(headingMatch[0]),
|
|
534
|
+
content: []
|
|
535
|
+
};
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
if (current) {
|
|
539
|
+
current.content.push(line);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (current) {
|
|
543
|
+
sections.push(current);
|
|
544
|
+
}
|
|
545
|
+
return sections.filter((section) => section.content.join("\n").trim().length > 0);
|
|
546
|
+
}
|
|
547
|
+
__name(splitByHeadings, "splitByHeadings");
|
|
548
|
+
function splitExamples(body) {
|
|
549
|
+
var _a;
|
|
550
|
+
const codeRegex = /```[\s\S]*?```/g;
|
|
551
|
+
const headingRegex = /^(#{2,3})\s+(.+)$/gm;
|
|
552
|
+
const headings = [];
|
|
553
|
+
for (const match of body.matchAll(headingRegex)) {
|
|
554
|
+
const raw = normalizeHeadingText(match[0]);
|
|
555
|
+
const key = raw.toLowerCase();
|
|
556
|
+
headings.push({
|
|
557
|
+
index: match.index ?? 0,
|
|
558
|
+
level: match[1].length,
|
|
559
|
+
text: raw,
|
|
560
|
+
key
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
const examples = [];
|
|
564
|
+
const excludeKeys = /* @__PURE__ */ new Set([
|
|
565
|
+
"type definition",
|
|
566
|
+
"type definition (simplified)",
|
|
567
|
+
"parameters",
|
|
568
|
+
"return value",
|
|
569
|
+
"\u7C7B\u578B\u5B9A\u4E49",
|
|
570
|
+
"\u53C2\u6570",
|
|
571
|
+
"\u8FD4\u56DE\u503C"
|
|
572
|
+
]);
|
|
573
|
+
const codeMatches = Array.from(body.matchAll(codeRegex));
|
|
574
|
+
const exampleCodeRanges = [];
|
|
575
|
+
const exampleSectionRanges = [];
|
|
576
|
+
for (const match of codeMatches) {
|
|
577
|
+
const code = match[0];
|
|
578
|
+
const index = match.index ?? 0;
|
|
579
|
+
const priorHeadings = headings.filter((item) => item.index < index);
|
|
580
|
+
const currentH2 = priorHeadings.filter((item) => item.level === 2).slice(-1)[0];
|
|
581
|
+
const currentH3 = priorHeadings.filter((item) => item.level === 3).slice(-1)[0];
|
|
582
|
+
const h2Key = (currentH2 == null ? void 0 : currentH2.key) || "";
|
|
583
|
+
const h3Key = (currentH3 == null ? void 0 : currentH3.key) || "";
|
|
584
|
+
if (excludeKeys.has(h2Key) || excludeKeys.has(h3Key)) {
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
const heading = (currentH3 == null ? void 0 : currentH3.text) || (currentH2 == null ? void 0 : currentH2.text) || "";
|
|
588
|
+
examples.push({ heading, content: code });
|
|
589
|
+
exampleCodeRanges.push({ start: index, end: index + code.length });
|
|
590
|
+
if (currentH3 || currentH2) {
|
|
591
|
+
const anchor = currentH3 || currentH2;
|
|
592
|
+
const nextHeadingIndex = ((_a = headings.filter((item) => item.index > anchor.index && item.level <= anchor.level).slice(0, 1)[0]) == null ? void 0 : _a.index) ?? body.length;
|
|
593
|
+
exampleSectionRanges.push({ start: anchor.index, end: nextHeadingIndex });
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
let cleanedBody = body;
|
|
597
|
+
if (exampleSectionRanges.length) {
|
|
598
|
+
const ranges = exampleSectionRanges.sort((a, b) => a.start - b.start).filter((range, index, list) => index === 0 || range.start >= list[index - 1].end);
|
|
599
|
+
let result = "";
|
|
600
|
+
let last = 0;
|
|
601
|
+
for (const range of ranges) {
|
|
602
|
+
result += body.slice(last, range.start);
|
|
603
|
+
last = range.end;
|
|
604
|
+
}
|
|
605
|
+
result += body.slice(last);
|
|
606
|
+
cleanedBody = result;
|
|
607
|
+
} else if (exampleCodeRanges.length) {
|
|
608
|
+
const ranges = exampleCodeRanges.sort((a, b) => a.start - b.start).filter((range, index, list) => index === 0 || range.start >= list[index - 1].end);
|
|
609
|
+
let result = "";
|
|
610
|
+
let last = 0;
|
|
611
|
+
for (const range of ranges) {
|
|
612
|
+
result += body.slice(last, range.start);
|
|
613
|
+
last = range.end;
|
|
614
|
+
}
|
|
615
|
+
result += body.slice(last);
|
|
616
|
+
cleanedBody = result;
|
|
617
|
+
}
|
|
618
|
+
return { examples, cleanedBody };
|
|
619
|
+
}
|
|
620
|
+
__name(splitExamples, "splitExamples");
|
|
621
|
+
function splitMarkdownIfNeeded(content, entry) {
|
|
622
|
+
const { body, frontMatter, hasFrontMatter } = splitFrontMatter(content);
|
|
623
|
+
const bodyLength = body.trim().length;
|
|
624
|
+
const codeBlocks = countCodeBlocks(body);
|
|
625
|
+
const shouldSplitByLength = bodyLength > SPLIT_MAX_LENGTH;
|
|
626
|
+
const shouldSplitByExamples = codeBlocks > SPLIT_MAX_CODE_BLOCKS;
|
|
627
|
+
if (!shouldSplitByLength && !shouldSplitByExamples) {
|
|
628
|
+
return {
|
|
629
|
+
splits: [],
|
|
630
|
+
content
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
const h1 = getPrimaryHeading(body) || entry.title;
|
|
634
|
+
const splits = [];
|
|
635
|
+
let nextBody = body;
|
|
636
|
+
let didSplitByExamples = false;
|
|
637
|
+
if (shouldSplitByExamples) {
|
|
638
|
+
const { examples, cleanedBody } = splitExamples(body);
|
|
639
|
+
if (examples.length) {
|
|
640
|
+
didSplitByExamples = true;
|
|
641
|
+
nextBody = cleanedBody;
|
|
642
|
+
examples.forEach((example, index) => {
|
|
643
|
+
const headingLine = example.heading ? `## ${example.heading}
|
|
644
|
+
|
|
645
|
+
` : "";
|
|
646
|
+
const exampleContent = `# ${h1}
|
|
647
|
+
|
|
648
|
+
${headingLine}${example.content}
|
|
649
|
+
`;
|
|
650
|
+
const title = example.heading ? `${example.heading} Example` : `${h1} Example ${index + 1}`;
|
|
651
|
+
splits.push({
|
|
652
|
+
suffix: `__example-${index + 1}.md`,
|
|
653
|
+
title,
|
|
654
|
+
description: `Extracted example from ${entry.title}`,
|
|
655
|
+
content: exampleContent
|
|
656
|
+
});
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
if (shouldSplitByLength && !didSplitByExamples) {
|
|
661
|
+
const sections = splitByHeadings(body);
|
|
662
|
+
sections.forEach((section, index) => {
|
|
663
|
+
const headingLine = `${"#".repeat(section.level)} ${section.heading}`;
|
|
664
|
+
const sectionBody = section.content.join("\n").trim();
|
|
665
|
+
const chunkContent = `# ${h1}
|
|
666
|
+
|
|
667
|
+
${headingLine}
|
|
668
|
+
${sectionBody}
|
|
669
|
+
`;
|
|
670
|
+
const title = section.heading || `${h1} Chunk ${index + 1}`;
|
|
671
|
+
splits.push({
|
|
672
|
+
suffix: `__chunk-${index + 1}.md`,
|
|
673
|
+
title,
|
|
674
|
+
description: `Extracted section from ${entry.title}`,
|
|
675
|
+
content: chunkContent
|
|
676
|
+
});
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
const rebuilt = hasFrontMatter ? `${frontMatter}${nextBody}` : nextBody;
|
|
680
|
+
return { splits, content: rebuilt };
|
|
681
|
+
}
|
|
682
|
+
__name(splitMarkdownIfNeeded, "splitMarkdownIfNeeded");
|
|
683
|
+
function applySplitReferences(content, splits) {
|
|
684
|
+
if (!splits.length) return content;
|
|
685
|
+
const refLines = splits.map((split) => referenceLine(split.title, split.description, split.pathRef));
|
|
686
|
+
const baseContent = stripSplitReferenceBlock(content).trimEnd();
|
|
687
|
+
const block = `${SPLIT_REFERENCE_START}
|
|
688
|
+
|
|
689
|
+
## Extracted references
|
|
690
|
+
|
|
691
|
+
${refLines.join(
|
|
692
|
+
"\n"
|
|
693
|
+
)}
|
|
694
|
+
|
|
695
|
+
${SPLIT_REFERENCE_END}`;
|
|
696
|
+
if (!baseContent) {
|
|
697
|
+
return `${block}
|
|
698
|
+
`;
|
|
699
|
+
}
|
|
700
|
+
return `${baseContent}
|
|
701
|
+
|
|
702
|
+
${block}
|
|
703
|
+
`;
|
|
704
|
+
}
|
|
705
|
+
__name(applySplitReferences, "applySplitReferences");
|
|
706
|
+
function stripSplitReferenceBlock(content) {
|
|
707
|
+
const start = content.indexOf(SPLIT_REFERENCE_START);
|
|
708
|
+
if (start === -1) return content;
|
|
709
|
+
const end = content.indexOf(SPLIT_REFERENCE_END, start + SPLIT_REFERENCE_START.length);
|
|
710
|
+
if (end === -1) return content;
|
|
711
|
+
const before = content.slice(0, start).trimEnd();
|
|
712
|
+
const after = content.slice(end + SPLIT_REFERENCE_END.length).trimStart();
|
|
713
|
+
if (!before) return after;
|
|
714
|
+
if (!after) return `${before}
|
|
715
|
+
`;
|
|
716
|
+
return `${before}
|
|
717
|
+
|
|
718
|
+
${after}`;
|
|
719
|
+
}
|
|
720
|
+
__name(stripSplitReferenceBlock, "stripSplitReferenceBlock");
|
|
721
|
+
function rewriteRelativeLinks(content, entry) {
|
|
722
|
+
const { body, frontMatter, hasFrontMatter } = splitFrontMatter(content);
|
|
723
|
+
const segments = [];
|
|
724
|
+
const codeRegex = /```[\s\S]*?```/g;
|
|
725
|
+
let lastIndex = 0;
|
|
726
|
+
for (const match of body.matchAll(codeRegex)) {
|
|
727
|
+
const index = match.index ?? 0;
|
|
728
|
+
if (index > lastIndex) {
|
|
729
|
+
segments.push({ type: "text", content: body.slice(lastIndex, index) });
|
|
730
|
+
}
|
|
731
|
+
segments.push({ type: "code", content: match[0] });
|
|
732
|
+
lastIndex = index + match[0].length;
|
|
733
|
+
}
|
|
734
|
+
if (lastIndex < body.length) {
|
|
735
|
+
segments.push({ type: "text", content: body.slice(lastIndex) });
|
|
736
|
+
}
|
|
737
|
+
const dir = import_path.default.posix.dirname(entry.relativePath.split(import_path.default.sep).join("/"));
|
|
738
|
+
const rewritten = segments.map((segment) => {
|
|
739
|
+
if (segment.type === "code") return segment.content;
|
|
740
|
+
return segment.content.replace(/(!?)\[[^\]]+]\(([^)]+)\)/g, (match, bang, link) => {
|
|
741
|
+
if (bang) return match;
|
|
742
|
+
const trimmed = link.trim();
|
|
743
|
+
if (trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("/") || trimmed.startsWith("#") || trimmed.startsWith("mailto:") || trimmed.startsWith("tel:")) {
|
|
744
|
+
return match;
|
|
745
|
+
}
|
|
746
|
+
const hashIndex = trimmed.indexOf("#");
|
|
747
|
+
const hash = hashIndex >= 0 ? trimmed.slice(hashIndex) : "";
|
|
748
|
+
const beforeHash = hashIndex >= 0 ? trimmed.slice(0, hashIndex) : trimmed;
|
|
749
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
750
|
+
const query = queryIndex >= 0 ? beforeHash.slice(queryIndex) : "";
|
|
751
|
+
const pathPart = queryIndex >= 0 ? beforeHash.slice(0, queryIndex) : beforeHash;
|
|
752
|
+
const resolved = import_path.default.posix.normalize(import_path.default.posix.join(dir, pathPart));
|
|
753
|
+
const normalized = resolved.startsWith(".") ? resolved.replace(/^(\.\.\/?)+/, "") : resolved;
|
|
754
|
+
const absolutePath = import_path.default.posix.join("/", entry.moduleName, normalized);
|
|
755
|
+
const nextLink = `${absolutePath}${query}${hash}`;
|
|
756
|
+
return match.replace(link, nextLink);
|
|
757
|
+
});
|
|
758
|
+
}).join("");
|
|
759
|
+
if (!hasFrontMatter) {
|
|
760
|
+
return rewritten;
|
|
761
|
+
}
|
|
762
|
+
return `${frontMatter}${rewritten}`;
|
|
763
|
+
}
|
|
764
|
+
__name(rewriteRelativeLinks, "rewriteRelativeLinks");
|
|
765
|
+
function applyReferencesToIndex(content, filePath, directoryChildren, docMap) {
|
|
766
|
+
const dir = import_path.default.dirname(filePath);
|
|
767
|
+
const entry = directoryChildren.get(dir);
|
|
768
|
+
if (!entry) {
|
|
769
|
+
return stripExistingReferenceBlock(content);
|
|
770
|
+
}
|
|
771
|
+
const refLines = [];
|
|
772
|
+
const refs = /* @__PURE__ */ new Set();
|
|
773
|
+
const childFiles = entry.files.filter((file) => file !== import_path.default.join(dir, "index.md"));
|
|
774
|
+
for (const child of childFiles.sort()) {
|
|
775
|
+
const meta = docMap.get(child);
|
|
776
|
+
if (!meta) continue;
|
|
777
|
+
const refPath = meta.canonicalPath;
|
|
778
|
+
if (refs.has(refPath)) continue;
|
|
779
|
+
refs.add(refPath);
|
|
780
|
+
refLines.push(referenceLine(meta.title, meta.description, refPath));
|
|
781
|
+
}
|
|
782
|
+
for (const subDir of entry.directories.sort()) {
|
|
783
|
+
const indexFile = import_path.default.join(subDir, "index.md");
|
|
784
|
+
const meta = docMap.get(indexFile);
|
|
785
|
+
if (!meta) continue;
|
|
786
|
+
const refPath = meta.canonicalPath;
|
|
787
|
+
if (refs.has(refPath)) continue;
|
|
788
|
+
refs.add(refPath);
|
|
789
|
+
refLines.push(referenceLine(meta.title, meta.description, refPath));
|
|
790
|
+
}
|
|
791
|
+
if (!refLines.length) {
|
|
792
|
+
return stripExistingReferenceBlock(content);
|
|
793
|
+
}
|
|
794
|
+
const baseContent = stripExistingReferenceBlock(content).trimEnd();
|
|
795
|
+
const block = `${REFERENCE_START}
|
|
796
|
+
|
|
797
|
+
## References
|
|
798
|
+
|
|
799
|
+
${refLines.join("\n")}
|
|
800
|
+
|
|
801
|
+
${REFERENCE_END}`;
|
|
802
|
+
if (!baseContent) {
|
|
803
|
+
return `${block}
|
|
804
|
+
`;
|
|
805
|
+
}
|
|
806
|
+
return `${baseContent}
|
|
807
|
+
|
|
808
|
+
${block}
|
|
809
|
+
`;
|
|
810
|
+
}
|
|
811
|
+
__name(applyReferencesToIndex, "applyReferencesToIndex");
|
|
812
|
+
function referenceLine(title, description, pathRef) {
|
|
813
|
+
const summary = description.length > 200 ? `${description.slice(0, 197)}...` : description;
|
|
814
|
+
const descText = summary ? ` - ${summary}` : "";
|
|
815
|
+
return `- **${title}** (\`${pathRef}\`)${descText}`;
|
|
816
|
+
}
|
|
817
|
+
__name(referenceLine, "referenceLine");
|
|
818
|
+
function stripExistingReferenceBlock(content) {
|
|
819
|
+
const start = content.indexOf(REFERENCE_START);
|
|
820
|
+
if (start === -1) return content;
|
|
821
|
+
const end = content.indexOf(REFERENCE_END, start + REFERENCE_START.length);
|
|
822
|
+
if (end === -1) return content;
|
|
823
|
+
const before = content.slice(0, start).trimEnd();
|
|
824
|
+
const after = content.slice(end + REFERENCE_END.length).trimStart();
|
|
825
|
+
if (!before) return after;
|
|
826
|
+
if (!after) return `${before}
|
|
827
|
+
`;
|
|
828
|
+
return `${before}
|
|
829
|
+
|
|
830
|
+
${after}`;
|
|
831
|
+
}
|
|
832
|
+
__name(stripExistingReferenceBlock, "stripExistingReferenceBlock");
|
|
833
|
+
async function createDocsIndex(app, options = {}) {
|
|
834
|
+
var _a;
|
|
835
|
+
const pkgs = await resolvePkgs(options.pkg);
|
|
836
|
+
if (!pkgs.length) {
|
|
837
|
+
app.log.info("No plugin packages detected for docs index generation");
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
const packageNames = [];
|
|
841
|
+
for (const pkg of pkgs) {
|
|
842
|
+
try {
|
|
843
|
+
const { packageName } = await import_plugin_manager.PluginManager.parseName(pkg);
|
|
844
|
+
packageNames.push(packageName);
|
|
845
|
+
} catch (error) {
|
|
846
|
+
app.log.error(error, { pkg });
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
if (!packageNames.length) {
|
|
850
|
+
app.log.info("No plugin packages resolved for docs index generation");
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
let results = null;
|
|
854
|
+
let lastError;
|
|
855
|
+
for (let attempt = 0; attempt < CREATE_INDEX_RETRY_MAX; attempt++) {
|
|
856
|
+
try {
|
|
857
|
+
results = await buildDocsIndexForPackages(packageNames);
|
|
858
|
+
break;
|
|
859
|
+
} catch (error) {
|
|
860
|
+
lastError = error;
|
|
861
|
+
if (attempt === CREATE_INDEX_RETRY_MAX - 1) {
|
|
862
|
+
break;
|
|
863
|
+
}
|
|
864
|
+
app.log.warn(`Docs index build failed, retrying (${attempt + 1}/${CREATE_INDEX_RETRY_MAX})`);
|
|
865
|
+
await new Promise((resolve) => setTimeout(resolve, CREATE_INDEX_RETRY_DELAY_MS * (attempt + 1)));
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
if (!results) {
|
|
869
|
+
const message = lastError ? errorToString(lastError) : "Docs index build failed";
|
|
870
|
+
app.log.error(message);
|
|
871
|
+
return;
|
|
872
|
+
}
|
|
873
|
+
if (!results.size) {
|
|
874
|
+
app.log.info("No module docs found to index");
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
for (const [moduleName, result] of results.entries()) {
|
|
878
|
+
if (result.created) {
|
|
879
|
+
app.log.info(`Docs index generated for module "${moduleName}"`);
|
|
880
|
+
if ((_a = result.conflicts) == null ? void 0 : _a.length) {
|
|
881
|
+
app.log.warn(`Module "${moduleName}" has conflicts: ${result.conflicts.join("; ")}`);
|
|
882
|
+
}
|
|
883
|
+
} else {
|
|
884
|
+
app.log.info(`Skipped docs index for module "${moduleName}": ${result.reason}`);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
__name(createDocsIndex, "createDocsIndex");
|
|
889
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
890
|
+
0 && (module.exports = {
|
|
891
|
+
createDocsIndex
|
|
892
|
+
});
|