@clarify-labs/cli 0.11.3 → 0.11.5
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/output/cli.cjs +9 -17
- package/output/cli.cjs.map +1 -1
- package/output/cli.js +9 -17
- package/output/cli.js.map +1 -1
- package/output/core/adapters.d.ts +1 -1
- package/output/core/engine/engine.d.ts +2 -1
- package/output/core/plugin/hooks.d.ts +2 -2
- package/output/core/routing/route-analysis.d.ts +11 -0
- package/output/core/routing/route-resolution.d.ts +8 -0
- package/output/core/runtime/module-ids.d.ts +5 -0
- package/output/core/runtime/virtual-modules.d.ts +2 -1
- package/output/{engine-CrYRJRZT.js → engine-DuiJVdO8.js} +454 -243
- package/output/engine-DuiJVdO8.js.map +1 -0
- package/output/{engine-6WmOk7xk.cjs → engine-VgAP_Ms6.cjs} +459 -242
- package/output/engine-VgAP_Ms6.cjs.map +1 -0
- package/output/index.cjs +1 -1
- package/output/index.js +1 -1
- package/output/parsers/content/content.d.ts +1 -1
- package/output/parsers/markdown/markdown.d.ts +34 -0
- package/output/parsers/markdown/mdx.d.ts +18 -10
- package/output/parsers/routes/routes.d.ts +4 -5
- package/output/parsers/routes/routes.test-utils.d.ts +5 -3
- package/output/plugins/openapi/parser.d.ts +2 -2
- package/output/plugins/openapi/routes.d.ts +3 -0
- package/output/plugins/openapi/state.d.ts +7 -0
- package/output/types.d.ts +24 -9
- package/package.json +3 -3
- package/output/engine-6WmOk7xk.cjs.map +0 -1
- package/output/engine-CrYRJRZT.js.map +0 -1
|
@@ -112,11 +112,11 @@ var rehypePlugins = [
|
|
|
112
112
|
];
|
|
113
113
|
function createContentCompileDiagnostic(options) {
|
|
114
114
|
const { format, phase, error, filePath, projectRoot } = options;
|
|
115
|
-
const label = format === "
|
|
115
|
+
const label = format === "markdown+jsx" ? "MDX" : "Markdown";
|
|
116
116
|
return createContentDiagnostic({
|
|
117
117
|
kind: format,
|
|
118
118
|
title: `${label} ${phase} error`,
|
|
119
|
-
message: phase === "syntax" ?
|
|
119
|
+
message: phase === "syntax" ? `This page could not be compiled. Fix the ${label} syntax or component usage above, then reload the route.` : `This page could not be compiled. Fix the ${label} syntax or plugin error below, then reload the route.`,
|
|
120
120
|
error,
|
|
121
121
|
filePath,
|
|
122
122
|
projectRoot,
|
|
@@ -129,19 +129,24 @@ function createContentCompileDiagnostic(options) {
|
|
|
129
129
|
*
|
|
130
130
|
* `rehypePlugins` includes `rehypeShiki`, which loads grammar/WASM assets and
|
|
131
131
|
* is expensive. The real highlighting happens at Vite build time via the
|
|
132
|
-
* `@mdx-js/rollup`
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
* "不应在 core 中执行代码高亮".
|
|
132
|
+
* `@mdx-js/rollup` plugin (see `createContentCompilerPlugin` in
|
|
133
|
+
* `core/adapters.ts`), which runs the full remark + rehype pipeline.
|
|
134
|
+
* Re-running it here, during route discovery (Phase 3), would compile every
|
|
135
|
+
* `.mdx` file twice and invoke Shiki once per file per `engine.refresh()` -
|
|
136
|
+
* see ARCHITECTURE.md §2.2 which states "不应在 core 中执行代码高亮".
|
|
138
137
|
*
|
|
139
138
|
* The remark pipeline still runs (shared with the Vite plugin via
|
|
140
|
-
* `remarkPlugins`), so MDX/JSX syntax errors
|
|
141
|
-
* diagnostic is meant to surface ahead of the Vite build
|
|
139
|
+
* `remarkPlugins`), so MDX/JSX syntax errors - the only class of error this
|
|
140
|
+
* diagnostic is meant to surface ahead of the Vite build - are caught. The
|
|
142
141
|
* output is discarded; only the thrown error is used.
|
|
142
|
+
*
|
|
143
|
+
* `.md` files are handled by `compileMarkdownContent` in `markdown.ts`, which
|
|
144
|
+
* mirrors the adapter's markdown compiler semantics (`format: 'md'`, raw HTML
|
|
145
|
+
* allowed). Keep the two compilers separate so each format can evolve its own
|
|
146
|
+
* diagnostic rules without contaminating the other.
|
|
143
147
|
*/
|
|
144
|
-
async function compileMdxContent(content,
|
|
148
|
+
async function compileMdxContent(content, options = {}) {
|
|
149
|
+
const { filePath, projectRoot } = options;
|
|
145
150
|
try {
|
|
146
151
|
await (0, _mdx_js_mdx.compile)(content, {
|
|
147
152
|
jsx: true,
|
|
@@ -153,7 +158,7 @@ async function compileMdxContent(content, filePath, projectRoot) {
|
|
|
153
158
|
return {
|
|
154
159
|
ok: false,
|
|
155
160
|
diagnostic: createContentCompileDiagnostic({
|
|
156
|
-
format: "
|
|
161
|
+
format: "markdown+jsx",
|
|
157
162
|
phase: "syntax",
|
|
158
163
|
error,
|
|
159
164
|
filePath,
|
|
@@ -163,6 +168,21 @@ async function compileMdxContent(content, filePath, projectRoot) {
|
|
|
163
168
|
}
|
|
164
169
|
}
|
|
165
170
|
//#endregion
|
|
171
|
+
//#region source/core/runtime/module-ids.ts
|
|
172
|
+
var PAGE_PREFIX = "virtual:clarify-page/";
|
|
173
|
+
var CONTENT_PREFIX = "virtual:clarify-content/";
|
|
174
|
+
function pageVirtualModuleId(path) {
|
|
175
|
+
return `${PAGE_PREFIX}${path.replace(/^\/+/, "").replace(/\/index$/, "").replace(/\/+/g, "/") || "index"}`;
|
|
176
|
+
}
|
|
177
|
+
function pageVirtualModuleIdFromRef(ref) {
|
|
178
|
+
return pageVirtualModuleId(ref.replace(/\.mdx?$/, "").replace(/\.openapi\.(json|yaml|yml)$/, ""));
|
|
179
|
+
}
|
|
180
|
+
function contentVirtualModuleId(filePath, contentRoot) {
|
|
181
|
+
const sourcePath = (0, node_path.relative)(contentRoot, filePath).replace(/\\/g, "/");
|
|
182
|
+
if (!sourcePath || sourcePath.startsWith("../") || (0, node_path.isAbsolute)(sourcePath)) throw new Error(`Content source must be inside the content root: ${filePath}`);
|
|
183
|
+
return `${CONTENT_PREFIX}${sourcePath}`;
|
|
184
|
+
}
|
|
185
|
+
//#endregion
|
|
166
186
|
//#region source/core/plugin/hooks.ts
|
|
167
187
|
async function runHooks(plugins, hookName, input, ctx) {
|
|
168
188
|
let result = input;
|
|
@@ -178,32 +198,43 @@ async function runHooks(plugins, hookName, input, ctx) {
|
|
|
178
198
|
return result;
|
|
179
199
|
}
|
|
180
200
|
async function runDevConfigureServerHooks(plugins, server, ctx) {
|
|
201
|
+
const postHooks = [];
|
|
181
202
|
for (const plugin of plugins) {
|
|
182
203
|
const hook = plugin.hooks?.["dev:configureServer"];
|
|
183
204
|
if (!hook) continue;
|
|
184
205
|
try {
|
|
185
|
-
await hook(server, ctx);
|
|
206
|
+
const postHook = await hook(server, ctx);
|
|
207
|
+
if (postHook) postHooks.push(postHook);
|
|
186
208
|
} catch (err) {
|
|
187
209
|
throw new Error(`[clarify] plugin "${plugin.name}" hook "dev:configureServer" failed: ${err}`, { cause: err });
|
|
188
210
|
}
|
|
189
211
|
}
|
|
212
|
+
return postHooks;
|
|
190
213
|
}
|
|
191
|
-
async function
|
|
192
|
-
const
|
|
214
|
+
async function runBuildAssetsHooks(plugins, ctx) {
|
|
215
|
+
const assets = [];
|
|
216
|
+
const producerByFileName = /* @__PURE__ */ new Map();
|
|
193
217
|
for (const plugin of plugins) {
|
|
194
|
-
const hook = plugin.hooks?.[
|
|
218
|
+
const hook = plugin.hooks?.["build:assets"];
|
|
195
219
|
if (!hook) continue;
|
|
220
|
+
let pluginAssets;
|
|
196
221
|
try {
|
|
197
|
-
|
|
198
|
-
results.push(...pluginResults);
|
|
222
|
+
pluginAssets = await hook(ctx);
|
|
199
223
|
} catch (err) {
|
|
200
|
-
throw new Error(`[clarify] plugin "${plugin.name}" hook "
|
|
224
|
+
throw new Error(`[clarify] plugin "${plugin.name}" hook "build:assets" failed: ${err}`, { cause: err });
|
|
225
|
+
}
|
|
226
|
+
for (const asset of pluginAssets) {
|
|
227
|
+
const fileName = asset.fileName.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
228
|
+
const previousProducer = producerByFileName.get(fileName);
|
|
229
|
+
if (previousProducer) throw new Error(`[clarify] build asset "${fileName}" is emitted by both plugin "${previousProducer}" and plugin "${plugin.name}"`);
|
|
230
|
+
producerByFileName.set(fileName, plugin.name);
|
|
231
|
+
assets.push({
|
|
232
|
+
...asset,
|
|
233
|
+
fileName
|
|
234
|
+
});
|
|
201
235
|
}
|
|
202
236
|
}
|
|
203
|
-
return
|
|
204
|
-
}
|
|
205
|
-
async function runBuildAssetsHooks(plugins, ctx) {
|
|
206
|
-
return runCollectorHooks(plugins, "build:assets", ctx);
|
|
237
|
+
return assets;
|
|
207
238
|
}
|
|
208
239
|
async function runBuildDoneHooks(plugins, ctx) {
|
|
209
240
|
for (const plugin of plugins) {
|
|
@@ -238,7 +269,7 @@ function createContentProcessor(transform) {
|
|
|
238
269
|
async processMdx(source, filePath) {
|
|
239
270
|
const { frontmatter, content } = parseFrontmatter(source);
|
|
240
271
|
const transformed = await transformContent(transform, {
|
|
241
|
-
kind: "
|
|
272
|
+
kind: "markdown+jsx",
|
|
242
273
|
source,
|
|
243
274
|
filePath,
|
|
244
275
|
frontmatter,
|
|
@@ -272,6 +303,54 @@ function createProjectContentProcessor(plugins, ctx) {
|
|
|
272
303
|
return createContentProcessor((input) => runHooks(plugins, "content:transform", input, ctx));
|
|
273
304
|
}
|
|
274
305
|
//#endregion
|
|
306
|
+
//#region source/parsers/markdown/markdown.ts
|
|
307
|
+
/**
|
|
308
|
+
* Validate Markdown content for diagnostics WITHOUT running the build-time
|
|
309
|
+
* rehype pipeline (Shiki highlighting, slug injection, code-block parsing).
|
|
310
|
+
*
|
|
311
|
+
* `rehypePlugins` includes `rehypeShiki`, which loads grammar/WASM assets and
|
|
312
|
+
* is expensive. The real highlighting happens at Vite build time via the
|
|
313
|
+
* `@mdx-js/rollup` plugin (see `createContentCompilerPlugin` in
|
|
314
|
+
* `core/adapters.ts`), which runs the full remark + rehype pipeline.
|
|
315
|
+
* Re-running it here, during route discovery (Phase 3), would compile every
|
|
316
|
+
* `.md` file twice and invoke Shiki once per file per `engine.refresh()` -
|
|
317
|
+
* see ARCHITECTURE.md §2.2 which states "不应在 core 中执行代码高亮".
|
|
318
|
+
*
|
|
319
|
+
* `format: 'md'` mirrors the adapter's markdown compiler semantics (no JSX,
|
|
320
|
+
* raw HTML allowed via `remarkRehypeOptions`), so the same class of syntax
|
|
321
|
+
* errors that would break the Vite build is surfaced as a diagnostic here
|
|
322
|
+
* instead of leaking out as an opaque
|
|
323
|
+
* `Failed to fetch dynamically imported module` at runtime.
|
|
324
|
+
*
|
|
325
|
+
* MDX files are handled by `compileMdxContent` in `mdx.ts`. Keep the two
|
|
326
|
+
* compilers separate so each format can evolve its own diagnostic rules
|
|
327
|
+
* without contaminating the other.
|
|
328
|
+
*/
|
|
329
|
+
async function compileMarkdownContent(content, options = {}) {
|
|
330
|
+
const { filePath, projectRoot } = options;
|
|
331
|
+
try {
|
|
332
|
+
await (0, _mdx_js_mdx.compile)(content, {
|
|
333
|
+
format: "md",
|
|
334
|
+
jsx: true,
|
|
335
|
+
providerImportSource: "@clarify-labs/renderer",
|
|
336
|
+
remarkPlugins,
|
|
337
|
+
remarkRehypeOptions: { allowDangerousHtml: true }
|
|
338
|
+
});
|
|
339
|
+
return { ok: true };
|
|
340
|
+
} catch (error) {
|
|
341
|
+
return {
|
|
342
|
+
ok: false,
|
|
343
|
+
diagnostic: createContentCompileDiagnostic({
|
|
344
|
+
format: "markdown",
|
|
345
|
+
phase: "syntax",
|
|
346
|
+
error,
|
|
347
|
+
filePath,
|
|
348
|
+
projectRoot
|
|
349
|
+
})
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
//#endregion
|
|
275
354
|
//#region source/parsers/routes/routes.ts
|
|
276
355
|
function kebabToTitle(str) {
|
|
277
356
|
return str.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
@@ -280,8 +359,10 @@ function parseMdxTree(content) {
|
|
|
280
359
|
return remark.remark.parse(content);
|
|
281
360
|
}
|
|
282
361
|
async function compileRouteDiagnostic(content, filePath, baseDir) {
|
|
283
|
-
|
|
284
|
-
|
|
362
|
+
const result = await ((0, node_path.extname)(filePath).toLowerCase() === ".md" ? compileMarkdownContent : compileMdxContent)(content, {
|
|
363
|
+
filePath,
|
|
364
|
+
projectRoot: baseDir
|
|
365
|
+
});
|
|
285
366
|
return result.ok ? void 0 : result.diagnostic;
|
|
286
367
|
}
|
|
287
368
|
/** 从内容中提取第一个 H1 标题 */
|
|
@@ -340,9 +421,6 @@ function openAPIPagePathFromRef(ref, tagFilter, explicitPath) {
|
|
|
340
421
|
function routePathFromRef(ref, explicitPath) {
|
|
341
422
|
return explicitPath ? normalizePath(explicitPath) : basePathFromRef(ref);
|
|
342
423
|
}
|
|
343
|
-
function virtualModuleIdFromRef(ref) {
|
|
344
|
-
return "virtual:clarify-page/" + ref.replace(/\.mdx?$/, "").replace(/\.openapi\.(json|yaml|yml)$/, "").replace(/\/+/g, "/");
|
|
345
|
-
}
|
|
346
424
|
function localizedRoutePath(basePath, locale, _i18n) {
|
|
347
425
|
const normalizedBasePath = normalizePath(basePath);
|
|
348
426
|
const prefix = normalizePath(locale);
|
|
@@ -385,7 +463,7 @@ async function findContentRoutes(dir, base = dir, options = {}) {
|
|
|
385
463
|
title = kebabToTitle(lastPart === "index" ? pathParts.length >= 2 ? pathParts[pathParts.length - 2] : extractH1(page.content) : lastPart) || "Untitled";
|
|
386
464
|
}
|
|
387
465
|
routes.push({
|
|
388
|
-
kind: "mdx",
|
|
466
|
+
kind: entry.name.toLowerCase().endsWith(".mdx") ? "markdown+jsx" : "markdown",
|
|
389
467
|
path: cleanPath,
|
|
390
468
|
basePath: cleanPath,
|
|
391
469
|
meta: {
|
|
@@ -394,7 +472,10 @@ async function findContentRoutes(dir, base = dir, options = {}) {
|
|
|
394
472
|
keywords: frontmatterKeywords(page.frontmatter),
|
|
395
473
|
sections: extractMdxSections(page.content)
|
|
396
474
|
},
|
|
397
|
-
module: {
|
|
475
|
+
module: {
|
|
476
|
+
pageVirtualModuleId: pageVirtualModuleId(relativePath.replace(/\.mdx?$/, "")),
|
|
477
|
+
contentVirtualModuleId: contentVirtualModuleId(fullPath, base)
|
|
478
|
+
},
|
|
398
479
|
source: {
|
|
399
480
|
filePath: fullPath,
|
|
400
481
|
frontmatter: page.frontmatter,
|
|
@@ -406,14 +487,24 @@ async function findContentRoutes(dir, base = dir, options = {}) {
|
|
|
406
487
|
}
|
|
407
488
|
return routes;
|
|
408
489
|
}
|
|
409
|
-
function
|
|
410
|
-
return
|
|
490
|
+
function pageVirtualModuleIdForLocalizedRoute(contentRoot, filePath) {
|
|
491
|
+
return pageVirtualModuleIdFromRef((0, node_path.relative)(contentRoot, filePath));
|
|
411
492
|
}
|
|
412
493
|
function frontmatterKeywords(frontmatter) {
|
|
413
494
|
const value = frontmatter.keywords ?? frontmatter.keyword ?? frontmatter.tags;
|
|
414
495
|
const keywords = Array.isArray(value) ? value.filter((item) => typeof item === "string") : typeof value === "string" ? value.split(",").map((keyword) => keyword.trim()).filter(Boolean) : [];
|
|
415
496
|
return keywords.length > 0 ? keywords : void 0;
|
|
416
497
|
}
|
|
498
|
+
function withPageIdentity(route, path) {
|
|
499
|
+
return {
|
|
500
|
+
...route,
|
|
501
|
+
path,
|
|
502
|
+
module: {
|
|
503
|
+
...route.module,
|
|
504
|
+
pageVirtualModuleId: pageVirtualModuleId(path)
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
}
|
|
417
508
|
function withAlternates(route, routes, locales) {
|
|
418
509
|
const basePath = route.basePath ?? route.path;
|
|
419
510
|
const routeByLocaleAndBase = new Map(routes.filter((r) => !r.locale || r.path === `/${r.locale}` || r.path.startsWith(`/${r.locale}/`)).map((r) => [`${r.locale ?? ""}:${r.basePath ?? r.path}`, r]));
|
|
@@ -439,8 +530,7 @@ function generateBareAliases(routes, locales) {
|
|
|
439
530
|
if (bp === route.path || seenBare.has(bp)) continue;
|
|
440
531
|
seenBare.add(bp);
|
|
441
532
|
bareRoutes.push({
|
|
442
|
-
...route,
|
|
443
|
-
path: bp,
|
|
533
|
+
...withPageIdentity(route, bp),
|
|
444
534
|
isBareAlias: true
|
|
445
535
|
});
|
|
446
536
|
}
|
|
@@ -459,7 +549,11 @@ async function findLocalizedContentRoutes(contentRoot, locales, options = {}) {
|
|
|
459
549
|
path: localizedRoutePath(basePath, locale.code, locales),
|
|
460
550
|
basePath,
|
|
461
551
|
locale: locale.code,
|
|
462
|
-
module: {
|
|
552
|
+
module: {
|
|
553
|
+
...route.module,
|
|
554
|
+
pageVirtualModuleId: pageVirtualModuleIdForLocalizedRoute(contentRoot, route.source.filePath),
|
|
555
|
+
contentVirtualModuleId: contentVirtualModuleId(route.source.filePath, contentRoot)
|
|
556
|
+
}
|
|
463
557
|
});
|
|
464
558
|
}
|
|
465
559
|
}
|
|
@@ -471,9 +565,9 @@ async function findLocalizedContentRoutes(contentRoot, locales, options = {}) {
|
|
|
471
565
|
for (const locale of locales.locales) {
|
|
472
566
|
const key = `${locale.code}:${basePath}`;
|
|
473
567
|
if (routeByLocaleAndBase.has(key)) continue;
|
|
568
|
+
const path = localizedRoutePath(basePath, locale.code, locales);
|
|
474
569
|
localizedRoutes.push({
|
|
475
|
-
...sourceRoute,
|
|
476
|
-
path: localizedRoutePath(basePath, locale.code, locales),
|
|
570
|
+
...withPageIdentity(sourceRoute, path),
|
|
477
571
|
locale: locale.code,
|
|
478
572
|
isFallback: true
|
|
479
573
|
});
|
|
@@ -568,13 +662,13 @@ function applyConfiguredPageRoutePaths(routes, tabs, locales) {
|
|
|
568
662
|
const targetBasePath = routePathFromRef(intent.ref, intent.path);
|
|
569
663
|
if (sourceBasePath === targetBasePath) continue;
|
|
570
664
|
for (const route of routes) {
|
|
571
|
-
if (route.kind
|
|
665
|
+
if (route.kind === "openapi" || (route.basePath ?? route.path) !== sourceBasePath) continue;
|
|
572
666
|
const key = `${route.locale ?? ""}:${targetBasePath}`;
|
|
573
667
|
if (existingKeys.has(key)) continue;
|
|
574
668
|
existingKeys.add(key);
|
|
669
|
+
const path = route.locale && locales ? localizedRoutePath(targetBasePath, route.locale, locales) : targetBasePath;
|
|
575
670
|
additions.push({
|
|
576
|
-
...route,
|
|
577
|
-
path: route.locale && locales ? localizedRoutePath(targetBasePath, route.locale, locales) : targetBasePath,
|
|
671
|
+
...withPageIdentity(route, path),
|
|
578
672
|
basePath: targetBasePath
|
|
579
673
|
});
|
|
580
674
|
}
|
|
@@ -582,7 +676,8 @@ function applyConfiguredPageRoutePaths(routes, tabs, locales) {
|
|
|
582
676
|
const nextRoutes = [...routes, ...additions];
|
|
583
677
|
const routesWithAlternates = locales ? nextRoutes.map((route) => withAlternates(route, nextRoutes, locales)) : nextRoutes;
|
|
584
678
|
if (!locales) return routesWithAlternates;
|
|
585
|
-
|
|
679
|
+
const markdownRoutes = routesWithAlternates.filter((route) => route.kind !== "openapi");
|
|
680
|
+
return [...routesWithAlternates, ...generateBareAliases(markdownRoutes, locales)];
|
|
586
681
|
}
|
|
587
682
|
function buildNavigationFromPagesConfig(routes, config) {
|
|
588
683
|
if (!config || config === "FileTree") return buildNavigation(routes);
|
|
@@ -776,7 +871,7 @@ function inferRouteForFile(filePath, contentRoot, defaultLocale) {
|
|
|
776
871
|
filePath,
|
|
777
872
|
locale: fileLocale,
|
|
778
873
|
basePath: normalizePath(basePath),
|
|
779
|
-
kind: isMdx ? "
|
|
874
|
+
kind: isMdx ? "markdown+jsx" : "openapi",
|
|
780
875
|
title,
|
|
781
876
|
inferred: true
|
|
782
877
|
};
|
|
@@ -986,18 +1081,16 @@ var clarifyThemeConfigSchema = zod.z.object({
|
|
|
986
1081
|
tokens: clarifyThemeTokensConfigSchema.optional(),
|
|
987
1082
|
layout: clarifyThemeLayoutConfigSchema.optional()
|
|
988
1083
|
}).strict();
|
|
989
|
-
function featureSchema(shape, defaults) {
|
|
1084
|
+
function featureSchema(shape, defaults, enabledByDefault = true) {
|
|
1085
|
+
const resolvedDefaults = {
|
|
1086
|
+
enabled: enabledByDefault,
|
|
1087
|
+
...defaults
|
|
1088
|
+
};
|
|
990
1089
|
const objectSchema = zod.z.object({
|
|
991
|
-
enabled: zod.z.boolean().default(
|
|
1090
|
+
enabled: zod.z.boolean().default(enabledByDefault),
|
|
992
1091
|
...shape
|
|
993
|
-
}).strict().default(
|
|
994
|
-
|
|
995
|
-
...defaults
|
|
996
|
-
});
|
|
997
|
-
return zod.z.union([zod.z.boolean(), objectSchema]).default({
|
|
998
|
-
enabled: true,
|
|
999
|
-
...defaults
|
|
1000
|
-
}).transform((value) => typeof value === "boolean" ? {
|
|
1092
|
+
}).strict().default(resolvedDefaults);
|
|
1093
|
+
return zod.z.union([zod.z.boolean(), objectSchema]).default(resolvedDefaults).transform((value) => typeof value === "boolean" ? {
|
|
1001
1094
|
enabled: value,
|
|
1002
1095
|
...defaults
|
|
1003
1096
|
} : value);
|
|
@@ -1005,7 +1098,7 @@ function featureSchema(shape, defaults) {
|
|
|
1005
1098
|
var clarifyFeaturesConfigSchema = zod.z.object({
|
|
1006
1099
|
search: featureSchema({ mcp: zod.z.boolean().default(true) }, { mcp: true }),
|
|
1007
1100
|
repository: featureSchema(clarifyRepositoryConfigSchema.shape, {}),
|
|
1008
|
-
themeEditor: featureSchema({}, {}),
|
|
1101
|
+
themeEditor: featureSchema({}, {}, false),
|
|
1009
1102
|
openapi: featureSchema({ playground: zod.z.boolean().default(true) }, { playground: true })
|
|
1010
1103
|
}).strict();
|
|
1011
1104
|
var clarifyProjectConfigSchema = zod.z.object({
|
|
@@ -1197,6 +1290,9 @@ function resolveVirtualId(id) {
|
|
|
1197
1290
|
function stripVirtualPrefix(id) {
|
|
1198
1291
|
return id.startsWith("\0") ? id.slice(1) : id;
|
|
1199
1292
|
}
|
|
1293
|
+
function virtualContentModuleId(route) {
|
|
1294
|
+
return route.module.contentVirtualModuleId;
|
|
1295
|
+
}
|
|
1200
1296
|
/**
|
|
1201
1297
|
* Fixed virtual module IDs (excluding the client entry, which has a special
|
|
1202
1298
|
* resolved form). Used to avoid hardcoding the constant list in every
|
|
@@ -1224,8 +1320,10 @@ function resolveVirtualModuleId(id, modules, routes) {
|
|
|
1224
1320
|
for (const virtualId of FIXED_VIRTUAL_IDS) if (id === virtualId || id === resolveVirtualId(virtualId)) return resolveVirtualId(virtualId);
|
|
1225
1321
|
const moduleId = stripVirtualPrefix(id);
|
|
1226
1322
|
if (modules.has(moduleId)) return resolveVirtualId(moduleId);
|
|
1227
|
-
const
|
|
1228
|
-
if (
|
|
1323
|
+
const contentRoute = routes.find((route) => (route.kind === "markdown" || route.kind === "markdown+jsx") && route.module.contentVirtualModuleId === moduleId);
|
|
1324
|
+
if (contentRoute) return contentRoute.source.filePath;
|
|
1325
|
+
const route = routes.find((route) => route.module.pageVirtualModuleId === id || route.module.pageVirtualModuleId === moduleId);
|
|
1326
|
+
if (route) return resolveVirtualId(route.module.pageVirtualModuleId);
|
|
1229
1327
|
return null;
|
|
1230
1328
|
}
|
|
1231
1329
|
function generateConfigModule(projectConfig, version) {
|
|
@@ -1279,8 +1377,8 @@ function routeToRuntimeManifestEntry(route, component, mode) {
|
|
|
1279
1377
|
return entry;
|
|
1280
1378
|
}
|
|
1281
1379
|
function generateRoutesModule(routes, navigation, mode = "client") {
|
|
1282
|
-
return `${mode === "server" ? routes.map((r, i) => `import Page${i} from ${moduleSpecifier(r.module.
|
|
1283
|
-
const component = mode === "server" ? `Page${i}` : `() => import(${moduleSpecifier(r.module.
|
|
1380
|
+
return `${mode === "server" ? routes.map((r, i) => `import Page${i} from ${moduleSpecifier(r.module.pageVirtualModuleId)};`).join("\n") : `import { createContentDiagnosticComponent } from '@clarify-labs/renderer';`}\n\nexport const routes = [\n${routes.map((r, i) => {
|
|
1381
|
+
const component = mode === "server" ? `Page${i}` : `() => import(${moduleSpecifier(r.module.pageVirtualModuleId)}).catch((error) => Promise.resolve({ default: createContentDiagnosticComponent({ kind: 'route-load', title: 'This page could not be loaded', message: error instanceof Error ? error.message : String(error), details: error instanceof Error ? error.stack : undefined }) }))`;
|
|
1284
1382
|
const placeholder = `__COMPONENT_${i}__`;
|
|
1285
1383
|
const manifestEntry = routeToRuntimeManifestEntry(r, placeholder, mode);
|
|
1286
1384
|
return ` ${JSON.stringify(manifestEntry, null, 0).replace(`"${placeholder}"`, component).replace(/"([A-Za-z_$][\w$]*)":/g, "$1: ")}`;
|
|
@@ -1352,13 +1450,14 @@ function buildVirtualModules(args) {
|
|
|
1352
1450
|
modules.set(VIRTUAL_ROUTES, generateRoutesModule(args.routes, args.navigation, "client"));
|
|
1353
1451
|
modules.set(VIRTUAL_SERVER_ROUTES, generateRoutesModule(args.routes, args.navigation, "server"));
|
|
1354
1452
|
modules.set(VIRTUAL_SLOTS, createRuntimeSlotsModule(allPlugins, args.generateOptions.projectRoot));
|
|
1355
|
-
modules.set(VIRTUAL_OPENAPI, "export const openApiSpecs = {};");
|
|
1356
1453
|
modules.set(VIRTUAL_SLOT, "export { useSlot } from '@clarify-labs/renderer';\n");
|
|
1357
|
-
modules.set(
|
|
1454
|
+
modules.set(VIRTUAL_OPENAPI, "export const openApiSpecs = {};");
|
|
1358
1455
|
modules.set(RESOLVED_CLIENT_ENTRY, clientEntryModule);
|
|
1456
|
+
modules.set(VIRTUAL_CLIENT_ENTRY, clientEntryModule);
|
|
1359
1457
|
for (const route of args.routes) {
|
|
1360
|
-
const moduleContent = route.diagnostic ? generateContentDiagnosticModule(route.diagnostic) : `export { default } from ${moduleSpecifier(route
|
|
1361
|
-
|
|
1458
|
+
const moduleContent = route.diagnostic ? generateContentDiagnosticModule(route.diagnostic) : route.kind === "markdown" || route.kind === "markdown+jsx" ? `export { default } from ${moduleSpecifier(virtualContentModuleId(route))};` : null;
|
|
1459
|
+
if (moduleContent === null) continue;
|
|
1460
|
+
modules.set(route.module.pageVirtualModuleId, moduleContent);
|
|
1362
1461
|
}
|
|
1363
1462
|
return modules;
|
|
1364
1463
|
}
|
|
@@ -1399,7 +1498,7 @@ function createNormalizedContentPlugin(engine) {
|
|
|
1399
1498
|
transform(_code, id) {
|
|
1400
1499
|
if (!/\.mdx?(?:\?|$)/.test(id)) return null;
|
|
1401
1500
|
const filePath = id.replace(/\?.*$/, "");
|
|
1402
|
-
const route = engine.routes.find((route) => route.kind === "
|
|
1501
|
+
const route = engine.routes.find((route) => (route.kind === "markdown+jsx" || route.kind === "markdown") && route.source.filePath === filePath);
|
|
1403
1502
|
if (!route || route.source.content === void 0) return null;
|
|
1404
1503
|
return {
|
|
1405
1504
|
code: route.source.content,
|
|
@@ -1514,7 +1613,10 @@ function createClarifyViteCorePlugin(engine, normalizedContentPlugin, markdown,
|
|
|
1514
1613
|
};
|
|
1515
1614
|
server.watcher.on("add", handleContentTreeChange);
|
|
1516
1615
|
server.watcher.on("unlink", handleContentTreeChange);
|
|
1517
|
-
await engine.configureDevServer(server);
|
|
1616
|
+
const postHooks = await engine.configureDevServer(server);
|
|
1617
|
+
if (postHooks.length > 0) return () => {
|
|
1618
|
+
for (const postHook of postHooks) postHook();
|
|
1619
|
+
};
|
|
1518
1620
|
},
|
|
1519
1621
|
transformIndexHtml: {
|
|
1520
1622
|
order: "pre",
|
|
@@ -1569,7 +1671,7 @@ function createViteAdapter(engine) {
|
|
|
1569
1671
|
const errorPolicy = () => contentCompileErrorPolicy;
|
|
1570
1672
|
const normalizedContentPlugin = createNormalizedContentPlugin(engine);
|
|
1571
1673
|
const markdown = createContentCompilerPlugin("markdown", engine.root, errorPolicy);
|
|
1572
|
-
const mdx = createContentCompilerPlugin("
|
|
1674
|
+
const mdx = createContentCompilerPlugin("markdown+jsx", engine.root, errorPolicy);
|
|
1573
1675
|
const compilePolicyPlugin = {
|
|
1574
1676
|
name: "clarify:content-compile-policy",
|
|
1575
1677
|
configResolved(config) {
|
|
@@ -1589,7 +1691,7 @@ function createViteAdapter(engine) {
|
|
|
1589
1691
|
}
|
|
1590
1692
|
var cliPackageVersion = {
|
|
1591
1693
|
name: "@clarify-labs/cli",
|
|
1592
|
-
version: "0.11.
|
|
1694
|
+
version: "0.11.5",
|
|
1593
1695
|
license: "AGPL-3.0-only",
|
|
1594
1696
|
type: "module",
|
|
1595
1697
|
repository: {
|
|
@@ -1689,7 +1791,7 @@ function withUtf8Signature(content) {
|
|
|
1689
1791
|
return `${UTF8_SIGNATURE}${content}`;
|
|
1690
1792
|
}
|
|
1691
1793
|
function shouldUseUtf8Signature(route) {
|
|
1692
|
-
if (route.kind === "
|
|
1794
|
+
if (route.kind === "markdown+jsx" || route.kind === "markdown") return true;
|
|
1693
1795
|
return false;
|
|
1694
1796
|
}
|
|
1695
1797
|
function routeToMarkdownArtifactUrl(routePath) {
|
|
@@ -1761,9 +1863,9 @@ function createLlmsTxt(routes, projectConfig) {
|
|
|
1761
1863
|
const lines = [`# ${projectConfig.title}`, ""];
|
|
1762
1864
|
if (projectConfig.description) lines.push(`> ${projectConfig.description}`, "");
|
|
1763
1865
|
lines.push("This file lists the source-ready Markdown and OpenAPI artifacts for this documentation site.", "");
|
|
1764
|
-
const
|
|
1765
|
-
if (
|
|
1766
|
-
const localizedGroups = groupLlmsTxtRoutesByLocale(
|
|
1866
|
+
const markdownRoutes = routes.filter((route) => (route.kind === "markdown+jsx" || route.kind === "markdown") && isLlmsTxtRoute(route) && !route.isBareAlias);
|
|
1867
|
+
if (markdownRoutes.length > 0) {
|
|
1868
|
+
const localizedGroups = groupLlmsTxtRoutesByLocale(markdownRoutes, projectConfig);
|
|
1767
1869
|
for (const [locale, localeRoutes] of localizedGroups) {
|
|
1768
1870
|
lines.push(`## ${llmsTxtDocsSectionTitle(locale, localizedGroups.size, projectConfig)}`);
|
|
1769
1871
|
for (const route of localeRoutes) {
|
|
@@ -1840,10 +1942,12 @@ function createContentArtifactsPlugin() {
|
|
|
1840
1942
|
return input;
|
|
1841
1943
|
},
|
|
1842
1944
|
"dev:configureServer": (server, ctx) => {
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1945
|
+
return () => {
|
|
1946
|
+
server.middlewares.use((req, res, next) => {
|
|
1947
|
+
if (serveContentArtifacts(req, res, ctx.projectConfig, ctx.routes)) return;
|
|
1948
|
+
next();
|
|
1949
|
+
});
|
|
1950
|
+
};
|
|
1847
1951
|
},
|
|
1848
1952
|
"build:assets": (ctx) => {
|
|
1849
1953
|
const assets = [];
|
|
@@ -2334,7 +2438,7 @@ function findOpenAPIRoutes(dir, base = dir) {
|
|
|
2334
2438
|
basePath: cleanPath,
|
|
2335
2439
|
kind: "openapi",
|
|
2336
2440
|
meta: { title: kebabToTitle(cleanPath.split("/").pop() ?? "API") },
|
|
2337
|
-
module: {
|
|
2441
|
+
module: { pageVirtualModuleId: pageVirtualModuleIdFromRef(ref) },
|
|
2338
2442
|
source: { filePath: fullPath }
|
|
2339
2443
|
});
|
|
2340
2444
|
}
|
|
@@ -2458,34 +2562,7 @@ async function readOpenAPISpec(filePath, contentProcessor, projectRoot) {
|
|
|
2458
2562
|
}
|
|
2459
2563
|
}
|
|
2460
2564
|
//#endregion
|
|
2461
|
-
//#region source/plugins/openapi/
|
|
2462
|
-
var openApiRegistryModuleId = VIRTUAL_OPENAPI;
|
|
2463
|
-
var openApiServerRegistryModuleId = VIRTUAL_OPENAPI_SERVER;
|
|
2464
|
-
var OPENAPI_SPEC_PREFIX = "virtual:clarify/openapi-spec/";
|
|
2465
|
-
function specVirtualModuleId(specKey) {
|
|
2466
|
-
return `${OPENAPI_SPEC_PREFIX}${specKey}`;
|
|
2467
|
-
}
|
|
2468
|
-
function generateOpenAPIRegistryModule(openApiSpecs) {
|
|
2469
|
-
return `export const openApiSpecs = {\n${Object.entries(openApiSpecs).map(([key, moduleId]) => ` ${JSON.stringify(key)}: () => import(${JSON.stringify(moduleId)}),`).join("\n")}\n};`;
|
|
2470
|
-
}
|
|
2471
|
-
function generateOpenAPIServerRegistryModule(openApiSpecs) {
|
|
2472
|
-
return `export const openApiSpecs = ${JSON.stringify(openApiSpecs)};`;
|
|
2473
|
-
}
|
|
2474
|
-
/** Generate a virtual module that exports a single spec as default. */
|
|
2475
|
-
function generateOpenAPISpecModule(spec) {
|
|
2476
|
-
return `export default ${JSON.stringify(spec)};`;
|
|
2477
|
-
}
|
|
2478
|
-
function generateOpenAPIPageModule(opts) {
|
|
2479
|
-
return `import { createOpenApiRouteComponent } from '@clarify-labs/renderer';
|
|
2480
|
-
import spec from ${JSON.stringify(opts.specModuleId)};
|
|
2481
|
-
|
|
2482
|
-
export const routeData = {};
|
|
2483
|
-
|
|
2484
|
-
export default createOpenApiRouteComponent({ ...routeData, spec });
|
|
2485
|
-
`;
|
|
2486
|
-
}
|
|
2487
|
-
//#endregion
|
|
2488
|
-
//#region source/plugins/openapi/index.ts
|
|
2565
|
+
//#region source/plugins/openapi/routes.ts
|
|
2489
2566
|
function collectOpenAPIPageIntents(config) {
|
|
2490
2567
|
const intents = [];
|
|
2491
2568
|
function visitItems(items) {
|
|
@@ -2505,9 +2582,6 @@ function collectOpenAPIPageIntents(config) {
|
|
|
2505
2582
|
for (const tab of config.navigation?.tabs ?? []) visitPages(tab.pages);
|
|
2506
2583
|
return intents;
|
|
2507
2584
|
}
|
|
2508
|
-
function virtualModuleIdFromPath(path) {
|
|
2509
|
-
return `virtual:clarify-page/${path.replace(/^\/+/, "") || "index"}`;
|
|
2510
|
-
}
|
|
2511
2585
|
function cloneOpenAPIRoute(route, overrides = {}) {
|
|
2512
2586
|
return {
|
|
2513
2587
|
...route,
|
|
@@ -2525,7 +2599,7 @@ function cloneOpenAPIRoute(route, overrides = {}) {
|
|
|
2525
2599
|
...overrides
|
|
2526
2600
|
};
|
|
2527
2601
|
}
|
|
2528
|
-
function
|
|
2602
|
+
function discoverOpenAPIRoutes(contentRoot, locales) {
|
|
2529
2603
|
if (!locales) return findOpenAPIRoutes(contentRoot);
|
|
2530
2604
|
const localizedRoutes = [];
|
|
2531
2605
|
for (const locale of locales.locales) {
|
|
@@ -2538,31 +2612,30 @@ function findOpenAPIRoutesForContentRoot(contentRoot, locales) {
|
|
|
2538
2612
|
path,
|
|
2539
2613
|
basePath,
|
|
2540
2614
|
locale: locale.code,
|
|
2541
|
-
module: {
|
|
2615
|
+
module: { pageVirtualModuleId: pageVirtualModuleId(path) }
|
|
2542
2616
|
});
|
|
2543
2617
|
}
|
|
2544
2618
|
}
|
|
2545
|
-
if (locales.missing
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
}
|
|
2619
|
+
if (locales.missing !== "fallback") return localizedRoutes;
|
|
2620
|
+
const routeByLocaleAndBase = new Map(localizedRoutes.map((route) => [`${route.locale ?? ""}:${route.basePath ?? route.path}`, route]));
|
|
2621
|
+
const defaultRoutes = localizedRoutes.filter((route) => route.locale === locales.default);
|
|
2622
|
+
for (const sourceRoute of defaultRoutes) {
|
|
2623
|
+
const basePath = sourceRoute.basePath ?? sourceRoute.path;
|
|
2624
|
+
for (const locale of locales.locales) {
|
|
2625
|
+
const key = `${locale.code}:${basePath}`;
|
|
2626
|
+
if (routeByLocaleAndBase.has(key)) continue;
|
|
2627
|
+
const path = localizedRoutePath(basePath, locale.code, locales);
|
|
2628
|
+
localizedRoutes.push(cloneOpenAPIRoute(sourceRoute, {
|
|
2629
|
+
path,
|
|
2630
|
+
locale: locale.code,
|
|
2631
|
+
module: { pageVirtualModuleId: pageVirtualModuleId(path) },
|
|
2632
|
+
isFallback: true
|
|
2633
|
+
}));
|
|
2561
2634
|
}
|
|
2562
2635
|
}
|
|
2563
2636
|
return localizedRoutes;
|
|
2564
2637
|
}
|
|
2565
|
-
function
|
|
2638
|
+
function expandConfiguredOpenAPIRoutes(routes, config) {
|
|
2566
2639
|
const openAPIIntents = collectOpenAPIPageIntents(config);
|
|
2567
2640
|
if (!openAPIIntents.length) return routes;
|
|
2568
2641
|
const additions = [];
|
|
@@ -2581,7 +2654,7 @@ function createConfiguredOpenAPIRoutes(routes, config) {
|
|
|
2581
2654
|
additions.push(cloneOpenAPIRoute(route, {
|
|
2582
2655
|
path,
|
|
2583
2656
|
basePath: targetBasePath,
|
|
2584
|
-
module: {
|
|
2657
|
+
module: { pageVirtualModuleId: pageVirtualModuleId(path) },
|
|
2585
2658
|
openapi: {
|
|
2586
2659
|
...route.openapi,
|
|
2587
2660
|
tagFilter: tagFilter?.length ? tagFilter : void 0
|
|
@@ -2595,19 +2668,47 @@ function createConfiguredOpenAPIRoutes(routes, config) {
|
|
|
2595
2668
|
const bareAliases = [];
|
|
2596
2669
|
const seenBare = new Set(routesWithAlternates.map((route) => route.path));
|
|
2597
2670
|
for (const route of routesWithAlternates) {
|
|
2598
|
-
if (route.locale !== config.locales.default) continue;
|
|
2671
|
+
if (route.kind !== "openapi" || route.locale !== config.locales.default) continue;
|
|
2599
2672
|
const basePath = route.basePath ?? route.path;
|
|
2600
2673
|
if (basePath === route.path || seenBare.has(basePath)) continue;
|
|
2601
2674
|
seenBare.add(basePath);
|
|
2602
2675
|
bareAliases.push(cloneOpenAPIRoute(route, {
|
|
2603
2676
|
path: basePath,
|
|
2604
|
-
module: {
|
|
2677
|
+
module: { pageVirtualModuleId: pageVirtualModuleId(basePath) },
|
|
2605
2678
|
isBareAlias: true
|
|
2606
2679
|
}));
|
|
2607
2680
|
}
|
|
2608
2681
|
return [...routesWithAlternates, ...bareAliases];
|
|
2609
2682
|
}
|
|
2610
|
-
|
|
2683
|
+
//#endregion
|
|
2684
|
+
//#region source/plugins/openapi/virtual-modules.ts
|
|
2685
|
+
var openApiRegistryModuleId = VIRTUAL_OPENAPI;
|
|
2686
|
+
var openApiServerRegistryModuleId = VIRTUAL_OPENAPI_SERVER;
|
|
2687
|
+
var OPENAPI_SPEC_PREFIX = "virtual:clarify/openapi-spec/";
|
|
2688
|
+
function specVirtualModuleId(specKey) {
|
|
2689
|
+
return `${OPENAPI_SPEC_PREFIX}${specKey}`;
|
|
2690
|
+
}
|
|
2691
|
+
function generateOpenAPIRegistryModule(openApiSpecs) {
|
|
2692
|
+
return `export const openApiSpecs = {\n${Object.entries(openApiSpecs).map(([key, moduleId]) => ` ${JSON.stringify(key)}: () => import(${JSON.stringify(moduleId)}),`).join("\n")}\n};`;
|
|
2693
|
+
}
|
|
2694
|
+
function generateOpenAPIServerRegistryModule(openApiSpecs) {
|
|
2695
|
+
return `export const openApiSpecs = ${JSON.stringify(openApiSpecs)};`;
|
|
2696
|
+
}
|
|
2697
|
+
/** Generate a virtual module that exports a single spec as default. */
|
|
2698
|
+
function generateOpenAPISpecModule(spec) {
|
|
2699
|
+
return `export default ${JSON.stringify(spec)};`;
|
|
2700
|
+
}
|
|
2701
|
+
function generateOpenAPIPageModule(opts) {
|
|
2702
|
+
return `import { createOpenApiRouteComponent } from '@clarify-labs/renderer';
|
|
2703
|
+
import spec from ${JSON.stringify(opts.specModuleId)};
|
|
2704
|
+
|
|
2705
|
+
export const routeData = {};
|
|
2706
|
+
|
|
2707
|
+
export default createOpenApiRouteComponent({ ...routeData, spec });
|
|
2708
|
+
`;
|
|
2709
|
+
}
|
|
2710
|
+
//#endregion
|
|
2711
|
+
//#region source/plugins/openapi/state.ts
|
|
2611
2712
|
function sourceSpecIdFromPath(filePath, projectRoot) {
|
|
2612
2713
|
return (0, node_path.relative)(projectRoot, filePath).replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
2613
2714
|
}
|
|
@@ -2619,90 +2720,94 @@ function openAPIRegistryKeys(route) {
|
|
|
2619
2720
|
const keys = /* @__PURE__ */ new Set();
|
|
2620
2721
|
const path = (route.path || "/").replace(/^\//, "");
|
|
2621
2722
|
const base = (route.basePath ?? route.path).replace(/^\//, "");
|
|
2622
|
-
if (route.locale) keys.add(
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
if (!route.locale && base) keys.add(`virtual:clarify-page/${base}`);
|
|
2723
|
+
if (route.locale) keys.add(pageVirtualModuleId(`${route.locale}/${base}`));
|
|
2724
|
+
keys.add(pageVirtualModuleId(path));
|
|
2725
|
+
if (!route.locale && base) keys.add(pageVirtualModuleId(base));
|
|
2626
2726
|
return [...keys];
|
|
2627
2727
|
}
|
|
2728
|
+
var OpenAPIPluginState = class {
|
|
2729
|
+
specModules = /* @__PURE__ */ new Map();
|
|
2730
|
+
async enrichRoutes(routes, ctx) {
|
|
2731
|
+
this.specModules.clear();
|
|
2732
|
+
const specByFilePath = /* @__PURE__ */ new Map();
|
|
2733
|
+
for (const route of routes) {
|
|
2734
|
+
if (route.kind !== "openapi") continue;
|
|
2735
|
+
const specFromCache = specByFilePath.get(route.source.filePath);
|
|
2736
|
+
const processor = createProjectContentProcessor(ctx.plugins, ctx);
|
|
2737
|
+
const result = specFromCache ? {
|
|
2738
|
+
ok: true,
|
|
2739
|
+
spec: specFromCache
|
|
2740
|
+
} : await readOpenAPISpec(route.source.filePath, processor, ctx.generateOptions.projectRoot);
|
|
2741
|
+
if (!result.ok) {
|
|
2742
|
+
route.diagnostic = result.diagnostic;
|
|
2743
|
+
route.meta.title = route.meta.title || "OpenAPI parse error";
|
|
2744
|
+
route.meta.sections = [];
|
|
2745
|
+
continue;
|
|
2746
|
+
}
|
|
2747
|
+
const spec = normalizeOpenAPISpecSectionIds(result.spec);
|
|
2748
|
+
specByFilePath.set(route.source.filePath, spec);
|
|
2749
|
+
const sourceSpecId = sourceSpecIdFromPath(route.source.filePath, ctx.generateOptions.projectRoot);
|
|
2750
|
+
route.openapi = {
|
|
2751
|
+
...route.openapi,
|
|
2752
|
+
sourceSpecId
|
|
2753
|
+
};
|
|
2754
|
+
route.meta.title = spec.info?.title ?? route.meta.title;
|
|
2755
|
+
route.meta.description = spec.info?.description ?? route.meta.description;
|
|
2756
|
+
route.meta.sections = extractOpenAPISections(spec, route.openapi.tagFilter);
|
|
2757
|
+
const pageSpec = route.openapi.tagFilter?.length ? filterSpecByTags(spec, route.openapi.tagFilter) : spec;
|
|
2758
|
+
const routeSpecModuleId = routeSpecModuleIdFromSourceSpecId(sourceSpecId, route.openapi.tagFilter);
|
|
2759
|
+
route.openapi.routeSpecModuleId = routeSpecModuleId;
|
|
2760
|
+
this.specModules.set(routeSpecModuleId, pageSpec);
|
|
2761
|
+
route.source.content = JSON.stringify(pageSpec);
|
|
2762
|
+
}
|
|
2763
|
+
return routes;
|
|
2764
|
+
}
|
|
2765
|
+
contributeModules(modules, routes) {
|
|
2766
|
+
const registryEntries = {};
|
|
2767
|
+
const serverRegistryEntries = {};
|
|
2768
|
+
for (const route of routes) {
|
|
2769
|
+
if (route.kind !== "openapi" || !route.openapi?.sourceSpecId) continue;
|
|
2770
|
+
const routeSpecModuleId = route.openapi.routeSpecModuleId ?? route.openapi.sourceSpecId;
|
|
2771
|
+
const spec = this.specModules.get(routeSpecModuleId);
|
|
2772
|
+
if (!spec) continue;
|
|
2773
|
+
for (const registryKey of openAPIRegistryKeys(route)) {
|
|
2774
|
+
registryEntries[registryKey] = specVirtualModuleId(routeSpecModuleId);
|
|
2775
|
+
serverRegistryEntries[registryKey] = spec;
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
modules.set(openApiRegistryModuleId, generateOpenAPIRegistryModule(registryEntries));
|
|
2779
|
+
modules.set(openApiServerRegistryModuleId, generateOpenAPIServerRegistryModule(serverRegistryEntries));
|
|
2780
|
+
for (const [routeSpecModuleId, spec] of this.specModules) modules.set(specVirtualModuleId(routeSpecModuleId), generateOpenAPISpecModule(spec));
|
|
2781
|
+
for (const route of routes) {
|
|
2782
|
+
if (route.kind !== "openapi") continue;
|
|
2783
|
+
if (route.diagnostic) {
|
|
2784
|
+
modules.set(route.module.pageVirtualModuleId, generateContentDiagnosticModule(route.diagnostic));
|
|
2785
|
+
continue;
|
|
2786
|
+
}
|
|
2787
|
+
if (!route.openapi?.sourceSpecId) continue;
|
|
2788
|
+
const routeSpecModuleId = route.openapi.routeSpecModuleId ?? route.openapi.sourceSpecId;
|
|
2789
|
+
if (!this.specModules.has(routeSpecModuleId)) continue;
|
|
2790
|
+
modules.set(route.module.pageVirtualModuleId, generateOpenAPIPageModule({ specModuleId: specVirtualModuleId(routeSpecModuleId) }));
|
|
2791
|
+
}
|
|
2792
|
+
return modules;
|
|
2793
|
+
}
|
|
2794
|
+
};
|
|
2795
|
+
//#endregion
|
|
2796
|
+
//#region source/plugins/openapi/index.ts
|
|
2628
2797
|
function createOpenAPIPlugin() {
|
|
2629
|
-
|
|
2630
|
-
const specs = /* @__PURE__ */ new Map();
|
|
2631
|
-
const specModules = /* @__PURE__ */ new Map();
|
|
2798
|
+
const state = new OpenAPIPluginState();
|
|
2632
2799
|
return {
|
|
2633
2800
|
name: "clarify:openapi",
|
|
2634
2801
|
hooks: {
|
|
2635
2802
|
"routes:discover": (input, ctx) => ({
|
|
2636
2803
|
...input,
|
|
2637
|
-
routes: [...input.routes, ...
|
|
2804
|
+
routes: [...input.routes, ...discoverOpenAPIRoutes(input.contentRoot, ctx.projectConfig.locales)]
|
|
2638
2805
|
}),
|
|
2639
2806
|
"routes:discovered": async (routes, ctx) => {
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
const nextRoutes = createConfiguredOpenAPIRoutes(routes, ctx.projectConfig);
|
|
2643
|
-
const specByFilePath = /* @__PURE__ */ new Map();
|
|
2644
|
-
for (const route of nextRoutes.filter((route) => route.kind === "openapi")) {
|
|
2645
|
-
const specFromCache = specByFilePath.get(route.source.filePath);
|
|
2646
|
-
const processor = createProjectContentProcessor(ctx.plugins, ctx);
|
|
2647
|
-
const result = specFromCache ? {
|
|
2648
|
-
ok: true,
|
|
2649
|
-
spec: specFromCache
|
|
2650
|
-
} : await readOpenAPISpec(route.source.filePath, processor, ctx.generateOptions.projectRoot);
|
|
2651
|
-
if (!result.ok) {
|
|
2652
|
-
route.diagnostic = result.diagnostic;
|
|
2653
|
-
route.meta.title = route.meta.title || "OpenAPI parse error";
|
|
2654
|
-
route.meta.sections = [];
|
|
2655
|
-
continue;
|
|
2656
|
-
}
|
|
2657
|
-
const spec = normalizeOpenAPISpecSectionIds(result.spec);
|
|
2658
|
-
specByFilePath.set(route.source.filePath, spec);
|
|
2659
|
-
const sourceSpecId = sourceSpecIdFromPath(route.source.filePath, ctx.generateOptions.projectRoot);
|
|
2660
|
-
route.openapi = {
|
|
2661
|
-
...route.openapi,
|
|
2662
|
-
sourceSpecId
|
|
2663
|
-
};
|
|
2664
|
-
specs.set(sourceSpecId, {
|
|
2665
|
-
spec,
|
|
2666
|
-
filePath: route.source.filePath
|
|
2667
|
-
});
|
|
2668
|
-
route.meta.title = spec.info?.title ?? route.meta.title;
|
|
2669
|
-
route.meta.description = spec.info?.description ?? route.meta.description;
|
|
2670
|
-
route.meta.sections = extractOpenAPISections(spec, route.openapi?.tagFilter);
|
|
2671
|
-
const pageSpec = route.openapi?.tagFilter?.length ? filterSpecByTags(spec, route.openapi.tagFilter) : spec;
|
|
2672
|
-
const routeSpecModuleId = routeSpecModuleIdFromSourceSpecId(sourceSpecId, route.openapi?.tagFilter);
|
|
2673
|
-
route.openapi.routeSpecModuleId = routeSpecModuleId;
|
|
2674
|
-
specModules.set(routeSpecModuleId, pageSpec);
|
|
2675
|
-
route.source.content = JSON.stringify(pageSpec);
|
|
2676
|
-
}
|
|
2677
|
-
return nextRoutes;
|
|
2807
|
+
const expandedRoutes = expandConfiguredOpenAPIRoutes(routes, ctx.projectConfig);
|
|
2808
|
+
return state.enrichRoutes(expandedRoutes, ctx);
|
|
2678
2809
|
},
|
|
2679
|
-
"modules:before": (modules, ctx) =>
|
|
2680
|
-
const registryEntries = {};
|
|
2681
|
-
const serverRegistryEntries = {};
|
|
2682
|
-
for (const route of ctx.routes) {
|
|
2683
|
-
if (route.kind !== "openapi" || !route.openapi?.sourceSpecId) continue;
|
|
2684
|
-
const routeSpecModuleId = route.openapi.routeSpecModuleId ?? route.openapi.sourceSpecId;
|
|
2685
|
-
const spec = specModules.get(routeSpecModuleId) ?? specs.get(route.openapi.sourceSpecId)?.spec;
|
|
2686
|
-
if (!spec) continue;
|
|
2687
|
-
for (const registryKey of openAPIRegistryKeys(route)) {
|
|
2688
|
-
registryEntries[registryKey] = specVirtualModuleId(routeSpecModuleId);
|
|
2689
|
-
serverRegistryEntries[registryKey] = spec;
|
|
2690
|
-
}
|
|
2691
|
-
}
|
|
2692
|
-
modules.set(openApiRegistryModuleId, generateOpenAPIRegistryModule(registryEntries));
|
|
2693
|
-
modules.set(openApiServerRegistryModuleId, generateOpenAPIServerRegistryModule(serverRegistryEntries));
|
|
2694
|
-
for (const [routeSpecModuleId, spec] of specModules) modules.set(specVirtualModuleId(routeSpecModuleId), generateOpenAPISpecModule(spec));
|
|
2695
|
-
for (const route of ctx.routes) {
|
|
2696
|
-
if (route.kind !== "openapi") continue;
|
|
2697
|
-
if (route.diagnostic) modules.set(route.module.virtualModuleId, generateContentDiagnosticModule(route.diagnostic));
|
|
2698
|
-
else if (route.openapi?.sourceSpecId) {
|
|
2699
|
-
const routeSpecModuleId = route.openapi.routeSpecModuleId ?? route.openapi.sourceSpecId;
|
|
2700
|
-
if (!specModules.has(routeSpecModuleId)) continue;
|
|
2701
|
-
modules.set(route.module.virtualModuleId, generateOpenAPIPageModule({ specModuleId: specVirtualModuleId(routeSpecModuleId) }));
|
|
2702
|
-
}
|
|
2703
|
-
}
|
|
2704
|
-
return modules;
|
|
2705
|
-
}
|
|
2810
|
+
"modules:before": (modules, ctx) => state.contributeModules(modules, ctx.routes)
|
|
2706
2811
|
}
|
|
2707
2812
|
};
|
|
2708
2813
|
}
|
|
@@ -3111,6 +3216,145 @@ async function resolveProjectContext(options = {}, env = {
|
|
|
3111
3216
|
};
|
|
3112
3217
|
}
|
|
3113
3218
|
//#endregion
|
|
3219
|
+
//#region source/core/routing/route-analysis.ts
|
|
3220
|
+
function routeDescription(route) {
|
|
3221
|
+
return `${route.kind} ${route.source.filePath}`;
|
|
3222
|
+
}
|
|
3223
|
+
function collectConflicts(routes, keyOf) {
|
|
3224
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
3225
|
+
for (const route of routes) {
|
|
3226
|
+
const key = keyOf(route);
|
|
3227
|
+
grouped.set(key, [...grouped.get(key) ?? [], route]);
|
|
3228
|
+
}
|
|
3229
|
+
return grouped;
|
|
3230
|
+
}
|
|
3231
|
+
function describeRouteConflict(route) {
|
|
3232
|
+
return routeDescription(route);
|
|
3233
|
+
}
|
|
3234
|
+
function findRouteConflicts(routes) {
|
|
3235
|
+
const conflicts = [];
|
|
3236
|
+
for (const [path, pathRoutes] of collectConflicts(routes, (route) => route.path)) {
|
|
3237
|
+
if (pathRoutes.length < 2) continue;
|
|
3238
|
+
conflicts.push({
|
|
3239
|
+
kind: "path",
|
|
3240
|
+
key: path,
|
|
3241
|
+
label: `path ${path}`,
|
|
3242
|
+
routes: pathRoutes
|
|
3243
|
+
});
|
|
3244
|
+
}
|
|
3245
|
+
for (const [pageModuleId, moduleRoutes] of collectConflicts(routes, (route) => route.module.pageVirtualModuleId)) {
|
|
3246
|
+
if (moduleRoutes.length < 2) continue;
|
|
3247
|
+
if (moduleRoutes.every((route) => route.path === moduleRoutes[0].path)) continue;
|
|
3248
|
+
conflicts.push({
|
|
3249
|
+
kind: "page-module",
|
|
3250
|
+
key: pageModuleId,
|
|
3251
|
+
label: `page module ${pageModuleId}`,
|
|
3252
|
+
routes: moduleRoutes
|
|
3253
|
+
});
|
|
3254
|
+
}
|
|
3255
|
+
return conflicts;
|
|
3256
|
+
}
|
|
3257
|
+
function formatRouteConflicts(conflicts) {
|
|
3258
|
+
return conflicts.map((conflict) => `- ${conflict.label}: ${conflict.routes.map(describeRouteConflict).join(", ")}`).join("\n");
|
|
3259
|
+
}
|
|
3260
|
+
//#endregion
|
|
3261
|
+
//#region source/core/routing/route-resolution.ts
|
|
3262
|
+
async function resolveRoutePages(routes, plugins, ctx) {
|
|
3263
|
+
const routeToken = Symbol("clarifyRouteToken");
|
|
3264
|
+
const resolvedPages = await runHooks(plugins, "pages:resolved", routes.map((route, routeIndex) => ({
|
|
3265
|
+
path: route.path,
|
|
3266
|
+
filePath: route.source.filePath,
|
|
3267
|
+
frontmatter: route.source.frontmatter ?? {},
|
|
3268
|
+
content: route.source.content ?? "",
|
|
3269
|
+
[routeToken]: routeIndex
|
|
3270
|
+
})), ctx);
|
|
3271
|
+
const pageByRouteIndex = /* @__PURE__ */ new Map();
|
|
3272
|
+
for (const page of resolvedPages) {
|
|
3273
|
+
const routeIndex = page[routeToken];
|
|
3274
|
+
if (!Number.isInteger(routeIndex) || routeIndex < 0 || routeIndex >= routes.length) throw new Error("[clarify] pages:resolved hooks must preserve each page route identity");
|
|
3275
|
+
if (pageByRouteIndex.has(routeIndex)) throw new Error("[clarify] pages:resolved hooks returned the same page route identity more than once");
|
|
3276
|
+
pageByRouteIndex.set(routeIndex, page);
|
|
3277
|
+
}
|
|
3278
|
+
if (pageByRouteIndex.size !== routes.length) throw new Error("[clarify] pages:resolved hooks must return exactly one page for each route");
|
|
3279
|
+
return routes.map((route, routeIndex) => {
|
|
3280
|
+
const page = pageByRouteIndex.get(routeIndex);
|
|
3281
|
+
return {
|
|
3282
|
+
...route,
|
|
3283
|
+
source: {
|
|
3284
|
+
...route.source,
|
|
3285
|
+
frontmatter: page.frontmatter,
|
|
3286
|
+
content: page.content
|
|
3287
|
+
}
|
|
3288
|
+
};
|
|
3289
|
+
});
|
|
3290
|
+
}
|
|
3291
|
+
function buildNavigationTree(routes, ctx) {
|
|
3292
|
+
const tabs = ctx.projectConfig.navigation?.tabs;
|
|
3293
|
+
if (!tabs) return {
|
|
3294
|
+
kind: "flat",
|
|
3295
|
+
nodes: buildNavigation(routes)
|
|
3296
|
+
};
|
|
3297
|
+
if (!ctx.projectConfig.locales) return buildNavigationFromTabsConfig(routes, tabs);
|
|
3298
|
+
return buildLocalizedNavigationFromTabsConfig(routes, tabs, ctx.projectConfig.locales) ?? {
|
|
3299
|
+
kind: "localized-tabbed",
|
|
3300
|
+
locales: {}
|
|
3301
|
+
};
|
|
3302
|
+
}
|
|
3303
|
+
function assertNoRouteConflicts(routes) {
|
|
3304
|
+
const conflicts = findRouteConflicts(routes);
|
|
3305
|
+
if (conflicts.length > 0) throw new Error(`[clarify] Route conflicts prevent the site from being built:\n${formatRouteConflicts(conflicts)}`);
|
|
3306
|
+
}
|
|
3307
|
+
function createRouteConflictDiagnostic(label, routes) {
|
|
3308
|
+
return {
|
|
3309
|
+
kind: "route-load",
|
|
3310
|
+
title: "Route conflict",
|
|
3311
|
+
message: `This page cannot be rendered because ${label} is used by multiple routes.`,
|
|
3312
|
+
details: routes.map(describeRouteConflict).join("\n")
|
|
3313
|
+
};
|
|
3314
|
+
}
|
|
3315
|
+
function createDevRouteConflictRoutes(routes) {
|
|
3316
|
+
const conflicts = findRouteConflicts(routes);
|
|
3317
|
+
if (conflicts.length === 0) return routes;
|
|
3318
|
+
const conflictedRoutes = /* @__PURE__ */ new Map();
|
|
3319
|
+
for (const conflict of conflicts) for (const route of conflict.routes) conflictedRoutes.set(route, conflict);
|
|
3320
|
+
function createConflictRoute(route, conflict) {
|
|
3321
|
+
return {
|
|
3322
|
+
...route,
|
|
3323
|
+
module: {
|
|
3324
|
+
...route.module,
|
|
3325
|
+
pageVirtualModuleId: `${route.module.pageVirtualModuleId}__conflict`
|
|
3326
|
+
},
|
|
3327
|
+
diagnostic: createRouteConflictDiagnostic(conflict.label, conflict.routes)
|
|
3328
|
+
};
|
|
3329
|
+
}
|
|
3330
|
+
const usedPaths = /* @__PURE__ */ new Set();
|
|
3331
|
+
return routes.flatMap((route) => {
|
|
3332
|
+
const conflict = conflictedRoutes.get(route);
|
|
3333
|
+
if (!conflict) return [route];
|
|
3334
|
+
if (usedPaths.has(route.path)) return [];
|
|
3335
|
+
usedPaths.add(route.path);
|
|
3336
|
+
return [createConflictRoute(route, conflict)];
|
|
3337
|
+
});
|
|
3338
|
+
}
|
|
3339
|
+
function handleRouteConflicts(routes, development) {
|
|
3340
|
+
if (development) return createDevRouteConflictRoutes(routes);
|
|
3341
|
+
assertNoRouteConflicts(routes);
|
|
3342
|
+
return routes;
|
|
3343
|
+
}
|
|
3344
|
+
async function resolveRouteState(routes, plugins, ctx, development) {
|
|
3345
|
+
const tabs = ctx.projectConfig.navigation?.tabs;
|
|
3346
|
+
const configuredRoutes = applyConfiguredPageRoutePaths(routes, tabs, ctx.projectConfig.locales);
|
|
3347
|
+
const resolved = await runHooks(plugins, "routes:resolved", {
|
|
3348
|
+
routes: configuredRoutes,
|
|
3349
|
+
navigation: buildNavigationTree(configuredRoutes, ctx)
|
|
3350
|
+
}, ctx);
|
|
3351
|
+
const finalRoutes = handleRouteConflicts(resolved.routes, development);
|
|
3352
|
+
return {
|
|
3353
|
+
routes: finalRoutes,
|
|
3354
|
+
navigation: finalRoutes === resolved.routes ? resolved.navigation : buildNavigationTree(finalRoutes, ctx)
|
|
3355
|
+
};
|
|
3356
|
+
}
|
|
3357
|
+
//#endregion
|
|
3114
3358
|
//#region source/core/runtime/env-types.ts
|
|
3115
3359
|
var GENERATED_FILE_NAME = "clarify-env.d.ts";
|
|
3116
3360
|
/**
|
|
@@ -3651,7 +3895,7 @@ var ClarifyEngine = class {
|
|
|
3651
3895
|
async discoverSite() {
|
|
3652
3896
|
const plugins = this.ctx.plugins;
|
|
3653
3897
|
const contentRoot = this.ctx.contentRoot;
|
|
3654
|
-
const { locales
|
|
3898
|
+
const { locales } = this.ctx.projectConfig;
|
|
3655
3899
|
let routes = await runPhase(plugins, "site:discover", this.ctx, async () => {
|
|
3656
3900
|
const options = { contentProcessor: createProjectContentProcessor(plugins, this.ctx) };
|
|
3657
3901
|
const discovered = locales ? await findLocalizedContentRoutes(contentRoot, locales, options) : await findContentRoutes(contentRoot, contentRoot, options);
|
|
@@ -3659,43 +3903,10 @@ var ClarifyEngine = class {
|
|
|
3659
3903
|
contentRoot,
|
|
3660
3904
|
routes: discovered
|
|
3661
3905
|
}, this.ctx);
|
|
3662
|
-
return runHooks(plugins, "routes:discovered", result.routes, this.ctx);
|
|
3663
|
-
});
|
|
3664
|
-
routes = await runPhase(plugins, "content:process", this.ctx, async () => {
|
|
3665
|
-
const pages = routes.map((route) => ({
|
|
3666
|
-
path: route.path,
|
|
3667
|
-
filePath: route.source.filePath,
|
|
3668
|
-
frontmatter: route.source.frontmatter ?? {},
|
|
3669
|
-
content: route.source.content ?? ""
|
|
3670
|
-
}));
|
|
3671
|
-
const resolvedPages = await runHooks(plugins, "pages:resolved", pages, this.ctx);
|
|
3672
|
-
const pageByPath = new Map(resolvedPages.map((p) => [p.path, p]));
|
|
3673
|
-
return routes.map((route) => {
|
|
3674
|
-
const page = pageByPath.get(route.path);
|
|
3675
|
-
if (!page) return route;
|
|
3676
|
-
return {
|
|
3677
|
-
...route,
|
|
3678
|
-
source: {
|
|
3679
|
-
...route.source,
|
|
3680
|
-
frontmatter: page.frontmatter,
|
|
3681
|
-
content: page.content
|
|
3682
|
-
}
|
|
3683
|
-
};
|
|
3684
|
-
});
|
|
3906
|
+
return await runHooks(plugins, "routes:discovered", result.routes, this.ctx);
|
|
3685
3907
|
});
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
const navigation = tabs ? locales ? buildLocalizedNavigationFromTabsConfig(routes, tabs, locales) ?? {
|
|
3689
|
-
kind: "localized-tabbed",
|
|
3690
|
-
locales: {}
|
|
3691
|
-
} : buildNavigationFromTabsConfig(routes, tabs) : {
|
|
3692
|
-
kind: "flat",
|
|
3693
|
-
nodes: buildNavigation(routes)
|
|
3694
|
-
};
|
|
3695
|
-
const resolved = await runHooks(plugins, "routes:resolved", {
|
|
3696
|
-
routes,
|
|
3697
|
-
navigation
|
|
3698
|
-
}, this.ctx);
|
|
3908
|
+
routes = await runPhase(plugins, "content:process", this.ctx, () => resolveRoutePages(routes, plugins, this.ctx));
|
|
3909
|
+
const resolved = await resolveRouteState(routes, plugins, this.ctx, this.runtime.command === "serve");
|
|
3699
3910
|
this.ctx.routes = resolved.routes;
|
|
3700
3911
|
this.ctx.navigation = resolved.navigation;
|
|
3701
3912
|
}
|
|
@@ -3745,8 +3956,8 @@ var ClarifyEngine = class {
|
|
|
3745
3956
|
return this.buildEnabled;
|
|
3746
3957
|
}
|
|
3747
3958
|
async configureDevServer(server) {
|
|
3748
|
-
|
|
3749
|
-
|
|
3959
|
+
return runPhase(this.plugins, "dev:server", this.ctx, () => {
|
|
3960
|
+
return runDevConfigureServerHooks(this.plugins, server, this.ctx);
|
|
3750
3961
|
});
|
|
3751
3962
|
}
|
|
3752
3963
|
async runBuildDone() {
|
|
@@ -3871,6 +4082,12 @@ Object.defineProperty(exports, "deserializeSearchIndex", {
|
|
|
3871
4082
|
return deserializeSearchIndex;
|
|
3872
4083
|
}
|
|
3873
4084
|
});
|
|
4085
|
+
Object.defineProperty(exports, "findRouteConflicts", {
|
|
4086
|
+
enumerable: true,
|
|
4087
|
+
get: function() {
|
|
4088
|
+
return findRouteConflicts;
|
|
4089
|
+
}
|
|
4090
|
+
});
|
|
3874
4091
|
Object.defineProperty(exports, "searchMcpIndex", {
|
|
3875
4092
|
enumerable: true,
|
|
3876
4093
|
get: function() {
|
|
@@ -3878,4 +4095,4 @@ Object.defineProperty(exports, "searchMcpIndex", {
|
|
|
3878
4095
|
}
|
|
3879
4096
|
});
|
|
3880
4097
|
|
|
3881
|
-
//# sourceMappingURL=engine-
|
|
4098
|
+
//# sourceMappingURL=engine-VgAP_Ms6.cjs.map
|