@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
|
@@ -81,11 +81,11 @@ var rehypePlugins = [
|
|
|
81
81
|
];
|
|
82
82
|
function createContentCompileDiagnostic(options) {
|
|
83
83
|
const { format, phase, error, filePath, projectRoot } = options;
|
|
84
|
-
const label = format === "
|
|
84
|
+
const label = format === "markdown+jsx" ? "MDX" : "Markdown";
|
|
85
85
|
return createContentDiagnostic({
|
|
86
86
|
kind: format,
|
|
87
87
|
title: `${label} ${phase} error`,
|
|
88
|
-
message: phase === "syntax" ?
|
|
88
|
+
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.`,
|
|
89
89
|
error,
|
|
90
90
|
filePath,
|
|
91
91
|
projectRoot,
|
|
@@ -98,19 +98,24 @@ function createContentCompileDiagnostic(options) {
|
|
|
98
98
|
*
|
|
99
99
|
* `rehypePlugins` includes `rehypeShiki`, which loads grammar/WASM assets and
|
|
100
100
|
* is expensive. The real highlighting happens at Vite build time via the
|
|
101
|
-
* `@mdx-js/rollup`
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* "不应在 core 中执行代码高亮".
|
|
101
|
+
* `@mdx-js/rollup` plugin (see `createContentCompilerPlugin` in
|
|
102
|
+
* `core/adapters.ts`), which runs the full remark + rehype pipeline.
|
|
103
|
+
* Re-running it here, during route discovery (Phase 3), would compile every
|
|
104
|
+
* `.mdx` file twice and invoke Shiki once per file per `engine.refresh()` -
|
|
105
|
+
* see ARCHITECTURE.md §2.2 which states "不应在 core 中执行代码高亮".
|
|
107
106
|
*
|
|
108
107
|
* The remark pipeline still runs (shared with the Vite plugin via
|
|
109
|
-
* `remarkPlugins`), so MDX/JSX syntax errors
|
|
110
|
-
* diagnostic is meant to surface ahead of the Vite build
|
|
108
|
+
* `remarkPlugins`), so MDX/JSX syntax errors - the only class of error this
|
|
109
|
+
* diagnostic is meant to surface ahead of the Vite build - are caught. The
|
|
111
110
|
* output is discarded; only the thrown error is used.
|
|
111
|
+
*
|
|
112
|
+
* `.md` files are handled by `compileMarkdownContent` in `markdown.ts`, which
|
|
113
|
+
* mirrors the adapter's markdown compiler semantics (`format: 'md'`, raw HTML
|
|
114
|
+
* allowed). Keep the two compilers separate so each format can evolve its own
|
|
115
|
+
* diagnostic rules without contaminating the other.
|
|
112
116
|
*/
|
|
113
|
-
async function compileMdxContent(content,
|
|
117
|
+
async function compileMdxContent(content, options = {}) {
|
|
118
|
+
const { filePath, projectRoot } = options;
|
|
114
119
|
try {
|
|
115
120
|
await compile(content, {
|
|
116
121
|
jsx: true,
|
|
@@ -122,7 +127,7 @@ async function compileMdxContent(content, filePath, projectRoot) {
|
|
|
122
127
|
return {
|
|
123
128
|
ok: false,
|
|
124
129
|
diagnostic: createContentCompileDiagnostic({
|
|
125
|
-
format: "
|
|
130
|
+
format: "markdown+jsx",
|
|
126
131
|
phase: "syntax",
|
|
127
132
|
error,
|
|
128
133
|
filePath,
|
|
@@ -132,6 +137,21 @@ async function compileMdxContent(content, filePath, projectRoot) {
|
|
|
132
137
|
}
|
|
133
138
|
}
|
|
134
139
|
//#endregion
|
|
140
|
+
//#region source/core/runtime/module-ids.ts
|
|
141
|
+
var PAGE_PREFIX = "virtual:clarify-page/";
|
|
142
|
+
var CONTENT_PREFIX = "virtual:clarify-content/";
|
|
143
|
+
function pageVirtualModuleId(path) {
|
|
144
|
+
return `${PAGE_PREFIX}${path.replace(/^\/+/, "").replace(/\/index$/, "").replace(/\/+/g, "/") || "index"}`;
|
|
145
|
+
}
|
|
146
|
+
function pageVirtualModuleIdFromRef(ref) {
|
|
147
|
+
return pageVirtualModuleId(ref.replace(/\.mdx?$/, "").replace(/\.openapi\.(json|yaml|yml)$/, ""));
|
|
148
|
+
}
|
|
149
|
+
function contentVirtualModuleId(filePath, contentRoot) {
|
|
150
|
+
const sourcePath = relative(contentRoot, filePath).replace(/\\/g, "/");
|
|
151
|
+
if (!sourcePath || sourcePath.startsWith("../") || isAbsolute(sourcePath)) throw new Error(`Content source must be inside the content root: ${filePath}`);
|
|
152
|
+
return `${CONTENT_PREFIX}${sourcePath}`;
|
|
153
|
+
}
|
|
154
|
+
//#endregion
|
|
135
155
|
//#region source/core/plugin/hooks.ts
|
|
136
156
|
async function runHooks(plugins, hookName, input, ctx) {
|
|
137
157
|
let result = input;
|
|
@@ -147,32 +167,43 @@ async function runHooks(plugins, hookName, input, ctx) {
|
|
|
147
167
|
return result;
|
|
148
168
|
}
|
|
149
169
|
async function runDevConfigureServerHooks(plugins, server, ctx) {
|
|
170
|
+
const postHooks = [];
|
|
150
171
|
for (const plugin of plugins) {
|
|
151
172
|
const hook = plugin.hooks?.["dev:configureServer"];
|
|
152
173
|
if (!hook) continue;
|
|
153
174
|
try {
|
|
154
|
-
await hook(server, ctx);
|
|
175
|
+
const postHook = await hook(server, ctx);
|
|
176
|
+
if (postHook) postHooks.push(postHook);
|
|
155
177
|
} catch (err) {
|
|
156
178
|
throw new Error(`[clarify] plugin "${plugin.name}" hook "dev:configureServer" failed: ${err}`, { cause: err });
|
|
157
179
|
}
|
|
158
180
|
}
|
|
181
|
+
return postHooks;
|
|
159
182
|
}
|
|
160
|
-
async function
|
|
161
|
-
const
|
|
183
|
+
async function runBuildAssetsHooks(plugins, ctx) {
|
|
184
|
+
const assets = [];
|
|
185
|
+
const producerByFileName = /* @__PURE__ */ new Map();
|
|
162
186
|
for (const plugin of plugins) {
|
|
163
|
-
const hook = plugin.hooks?.[
|
|
187
|
+
const hook = plugin.hooks?.["build:assets"];
|
|
164
188
|
if (!hook) continue;
|
|
189
|
+
let pluginAssets;
|
|
165
190
|
try {
|
|
166
|
-
|
|
167
|
-
results.push(...pluginResults);
|
|
191
|
+
pluginAssets = await hook(ctx);
|
|
168
192
|
} catch (err) {
|
|
169
|
-
throw new Error(`[clarify] plugin "${plugin.name}" hook "
|
|
193
|
+
throw new Error(`[clarify] plugin "${plugin.name}" hook "build:assets" failed: ${err}`, { cause: err });
|
|
194
|
+
}
|
|
195
|
+
for (const asset of pluginAssets) {
|
|
196
|
+
const fileName = asset.fileName.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
197
|
+
const previousProducer = producerByFileName.get(fileName);
|
|
198
|
+
if (previousProducer) throw new Error(`[clarify] build asset "${fileName}" is emitted by both plugin "${previousProducer}" and plugin "${plugin.name}"`);
|
|
199
|
+
producerByFileName.set(fileName, plugin.name);
|
|
200
|
+
assets.push({
|
|
201
|
+
...asset,
|
|
202
|
+
fileName
|
|
203
|
+
});
|
|
170
204
|
}
|
|
171
205
|
}
|
|
172
|
-
return
|
|
173
|
-
}
|
|
174
|
-
async function runBuildAssetsHooks(plugins, ctx) {
|
|
175
|
-
return runCollectorHooks(plugins, "build:assets", ctx);
|
|
206
|
+
return assets;
|
|
176
207
|
}
|
|
177
208
|
async function runBuildDoneHooks(plugins, ctx) {
|
|
178
209
|
for (const plugin of plugins) {
|
|
@@ -207,7 +238,7 @@ function createContentProcessor(transform) {
|
|
|
207
238
|
async processMdx(source, filePath) {
|
|
208
239
|
const { frontmatter, content } = parseFrontmatter(source);
|
|
209
240
|
const transformed = await transformContent(transform, {
|
|
210
|
-
kind: "
|
|
241
|
+
kind: "markdown+jsx",
|
|
211
242
|
source,
|
|
212
243
|
filePath,
|
|
213
244
|
frontmatter,
|
|
@@ -241,6 +272,54 @@ function createProjectContentProcessor(plugins, ctx) {
|
|
|
241
272
|
return createContentProcessor((input) => runHooks(plugins, "content:transform", input, ctx));
|
|
242
273
|
}
|
|
243
274
|
//#endregion
|
|
275
|
+
//#region source/parsers/markdown/markdown.ts
|
|
276
|
+
/**
|
|
277
|
+
* Validate Markdown content for diagnostics WITHOUT running the build-time
|
|
278
|
+
* rehype pipeline (Shiki highlighting, slug injection, code-block parsing).
|
|
279
|
+
*
|
|
280
|
+
* `rehypePlugins` includes `rehypeShiki`, which loads grammar/WASM assets and
|
|
281
|
+
* is expensive. The real highlighting happens at Vite build time via the
|
|
282
|
+
* `@mdx-js/rollup` plugin (see `createContentCompilerPlugin` in
|
|
283
|
+
* `core/adapters.ts`), which runs the full remark + rehype pipeline.
|
|
284
|
+
* Re-running it here, during route discovery (Phase 3), would compile every
|
|
285
|
+
* `.md` file twice and invoke Shiki once per file per `engine.refresh()` -
|
|
286
|
+
* see ARCHITECTURE.md §2.2 which states "不应在 core 中执行代码高亮".
|
|
287
|
+
*
|
|
288
|
+
* `format: 'md'` mirrors the adapter's markdown compiler semantics (no JSX,
|
|
289
|
+
* raw HTML allowed via `remarkRehypeOptions`), so the same class of syntax
|
|
290
|
+
* errors that would break the Vite build is surfaced as a diagnostic here
|
|
291
|
+
* instead of leaking out as an opaque
|
|
292
|
+
* `Failed to fetch dynamically imported module` at runtime.
|
|
293
|
+
*
|
|
294
|
+
* MDX files are handled by `compileMdxContent` in `mdx.ts`. Keep the two
|
|
295
|
+
* compilers separate so each format can evolve its own diagnostic rules
|
|
296
|
+
* without contaminating the other.
|
|
297
|
+
*/
|
|
298
|
+
async function compileMarkdownContent(content, options = {}) {
|
|
299
|
+
const { filePath, projectRoot } = options;
|
|
300
|
+
try {
|
|
301
|
+
await compile(content, {
|
|
302
|
+
format: "md",
|
|
303
|
+
jsx: true,
|
|
304
|
+
providerImportSource: "@clarify-labs/renderer",
|
|
305
|
+
remarkPlugins,
|
|
306
|
+
remarkRehypeOptions: { allowDangerousHtml: true }
|
|
307
|
+
});
|
|
308
|
+
return { ok: true };
|
|
309
|
+
} catch (error) {
|
|
310
|
+
return {
|
|
311
|
+
ok: false,
|
|
312
|
+
diagnostic: createContentCompileDiagnostic({
|
|
313
|
+
format: "markdown",
|
|
314
|
+
phase: "syntax",
|
|
315
|
+
error,
|
|
316
|
+
filePath,
|
|
317
|
+
projectRoot
|
|
318
|
+
})
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
//#endregion
|
|
244
323
|
//#region source/parsers/routes/routes.ts
|
|
245
324
|
function kebabToTitle(str) {
|
|
246
325
|
return str.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
@@ -249,8 +328,10 @@ function parseMdxTree(content) {
|
|
|
249
328
|
return remark.parse(content);
|
|
250
329
|
}
|
|
251
330
|
async function compileRouteDiagnostic(content, filePath, baseDir) {
|
|
252
|
-
|
|
253
|
-
|
|
331
|
+
const result = await (extname(filePath).toLowerCase() === ".md" ? compileMarkdownContent : compileMdxContent)(content, {
|
|
332
|
+
filePath,
|
|
333
|
+
projectRoot: baseDir
|
|
334
|
+
});
|
|
254
335
|
return result.ok ? void 0 : result.diagnostic;
|
|
255
336
|
}
|
|
256
337
|
/** 从内容中提取第一个 H1 标题 */
|
|
@@ -309,9 +390,6 @@ function openAPIPagePathFromRef(ref, tagFilter, explicitPath) {
|
|
|
309
390
|
function routePathFromRef(ref, explicitPath) {
|
|
310
391
|
return explicitPath ? normalizePath(explicitPath) : basePathFromRef(ref);
|
|
311
392
|
}
|
|
312
|
-
function virtualModuleIdFromRef(ref) {
|
|
313
|
-
return "virtual:clarify-page/" + ref.replace(/\.mdx?$/, "").replace(/\.openapi\.(json|yaml|yml)$/, "").replace(/\/+/g, "/");
|
|
314
|
-
}
|
|
315
393
|
function localizedRoutePath(basePath, locale, _i18n) {
|
|
316
394
|
const normalizedBasePath = normalizePath(basePath);
|
|
317
395
|
const prefix = normalizePath(locale);
|
|
@@ -354,7 +432,7 @@ async function findContentRoutes(dir, base = dir, options = {}) {
|
|
|
354
432
|
title = kebabToTitle(lastPart === "index" ? pathParts.length >= 2 ? pathParts[pathParts.length - 2] : extractH1(page.content) : lastPart) || "Untitled";
|
|
355
433
|
}
|
|
356
434
|
routes.push({
|
|
357
|
-
kind: "mdx",
|
|
435
|
+
kind: entry.name.toLowerCase().endsWith(".mdx") ? "markdown+jsx" : "markdown",
|
|
358
436
|
path: cleanPath,
|
|
359
437
|
basePath: cleanPath,
|
|
360
438
|
meta: {
|
|
@@ -363,7 +441,10 @@ async function findContentRoutes(dir, base = dir, options = {}) {
|
|
|
363
441
|
keywords: frontmatterKeywords(page.frontmatter),
|
|
364
442
|
sections: extractMdxSections(page.content)
|
|
365
443
|
},
|
|
366
|
-
module: {
|
|
444
|
+
module: {
|
|
445
|
+
pageVirtualModuleId: pageVirtualModuleId(relativePath.replace(/\.mdx?$/, "")),
|
|
446
|
+
contentVirtualModuleId: contentVirtualModuleId(fullPath, base)
|
|
447
|
+
},
|
|
367
448
|
source: {
|
|
368
449
|
filePath: fullPath,
|
|
369
450
|
frontmatter: page.frontmatter,
|
|
@@ -375,14 +456,24 @@ async function findContentRoutes(dir, base = dir, options = {}) {
|
|
|
375
456
|
}
|
|
376
457
|
return routes;
|
|
377
458
|
}
|
|
378
|
-
function
|
|
379
|
-
return
|
|
459
|
+
function pageVirtualModuleIdForLocalizedRoute(contentRoot, filePath) {
|
|
460
|
+
return pageVirtualModuleIdFromRef(relative(contentRoot, filePath));
|
|
380
461
|
}
|
|
381
462
|
function frontmatterKeywords(frontmatter) {
|
|
382
463
|
const value = frontmatter.keywords ?? frontmatter.keyword ?? frontmatter.tags;
|
|
383
464
|
const keywords = Array.isArray(value) ? value.filter((item) => typeof item === "string") : typeof value === "string" ? value.split(",").map((keyword) => keyword.trim()).filter(Boolean) : [];
|
|
384
465
|
return keywords.length > 0 ? keywords : void 0;
|
|
385
466
|
}
|
|
467
|
+
function withPageIdentity(route, path) {
|
|
468
|
+
return {
|
|
469
|
+
...route,
|
|
470
|
+
path,
|
|
471
|
+
module: {
|
|
472
|
+
...route.module,
|
|
473
|
+
pageVirtualModuleId: pageVirtualModuleId(path)
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
}
|
|
386
477
|
function withAlternates(route, routes, locales) {
|
|
387
478
|
const basePath = route.basePath ?? route.path;
|
|
388
479
|
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]));
|
|
@@ -408,8 +499,7 @@ function generateBareAliases(routes, locales) {
|
|
|
408
499
|
if (bp === route.path || seenBare.has(bp)) continue;
|
|
409
500
|
seenBare.add(bp);
|
|
410
501
|
bareRoutes.push({
|
|
411
|
-
...route,
|
|
412
|
-
path: bp,
|
|
502
|
+
...withPageIdentity(route, bp),
|
|
413
503
|
isBareAlias: true
|
|
414
504
|
});
|
|
415
505
|
}
|
|
@@ -428,7 +518,11 @@ async function findLocalizedContentRoutes(contentRoot, locales, options = {}) {
|
|
|
428
518
|
path: localizedRoutePath(basePath, locale.code, locales),
|
|
429
519
|
basePath,
|
|
430
520
|
locale: locale.code,
|
|
431
|
-
module: {
|
|
521
|
+
module: {
|
|
522
|
+
...route.module,
|
|
523
|
+
pageVirtualModuleId: pageVirtualModuleIdForLocalizedRoute(contentRoot, route.source.filePath),
|
|
524
|
+
contentVirtualModuleId: contentVirtualModuleId(route.source.filePath, contentRoot)
|
|
525
|
+
}
|
|
432
526
|
});
|
|
433
527
|
}
|
|
434
528
|
}
|
|
@@ -440,9 +534,9 @@ async function findLocalizedContentRoutes(contentRoot, locales, options = {}) {
|
|
|
440
534
|
for (const locale of locales.locales) {
|
|
441
535
|
const key = `${locale.code}:${basePath}`;
|
|
442
536
|
if (routeByLocaleAndBase.has(key)) continue;
|
|
537
|
+
const path = localizedRoutePath(basePath, locale.code, locales);
|
|
443
538
|
localizedRoutes.push({
|
|
444
|
-
...sourceRoute,
|
|
445
|
-
path: localizedRoutePath(basePath, locale.code, locales),
|
|
539
|
+
...withPageIdentity(sourceRoute, path),
|
|
446
540
|
locale: locale.code,
|
|
447
541
|
isFallback: true
|
|
448
542
|
});
|
|
@@ -537,13 +631,13 @@ function applyConfiguredPageRoutePaths(routes, tabs, locales) {
|
|
|
537
631
|
const targetBasePath = routePathFromRef(intent.ref, intent.path);
|
|
538
632
|
if (sourceBasePath === targetBasePath) continue;
|
|
539
633
|
for (const route of routes) {
|
|
540
|
-
if (route.kind
|
|
634
|
+
if (route.kind === "openapi" || (route.basePath ?? route.path) !== sourceBasePath) continue;
|
|
541
635
|
const key = `${route.locale ?? ""}:${targetBasePath}`;
|
|
542
636
|
if (existingKeys.has(key)) continue;
|
|
543
637
|
existingKeys.add(key);
|
|
638
|
+
const path = route.locale && locales ? localizedRoutePath(targetBasePath, route.locale, locales) : targetBasePath;
|
|
544
639
|
additions.push({
|
|
545
|
-
...route,
|
|
546
|
-
path: route.locale && locales ? localizedRoutePath(targetBasePath, route.locale, locales) : targetBasePath,
|
|
640
|
+
...withPageIdentity(route, path),
|
|
547
641
|
basePath: targetBasePath
|
|
548
642
|
});
|
|
549
643
|
}
|
|
@@ -551,7 +645,8 @@ function applyConfiguredPageRoutePaths(routes, tabs, locales) {
|
|
|
551
645
|
const nextRoutes = [...routes, ...additions];
|
|
552
646
|
const routesWithAlternates = locales ? nextRoutes.map((route) => withAlternates(route, nextRoutes, locales)) : nextRoutes;
|
|
553
647
|
if (!locales) return routesWithAlternates;
|
|
554
|
-
|
|
648
|
+
const markdownRoutes = routesWithAlternates.filter((route) => route.kind !== "openapi");
|
|
649
|
+
return [...routesWithAlternates, ...generateBareAliases(markdownRoutes, locales)];
|
|
555
650
|
}
|
|
556
651
|
function buildNavigationFromPagesConfig(routes, config) {
|
|
557
652
|
if (!config || config === "FileTree") return buildNavigation(routes);
|
|
@@ -745,7 +840,7 @@ function inferRouteForFile(filePath, contentRoot, defaultLocale) {
|
|
|
745
840
|
filePath,
|
|
746
841
|
locale: fileLocale,
|
|
747
842
|
basePath: normalizePath(basePath),
|
|
748
|
-
kind: isMdx ? "
|
|
843
|
+
kind: isMdx ? "markdown+jsx" : "openapi",
|
|
749
844
|
title,
|
|
750
845
|
inferred: true
|
|
751
846
|
};
|
|
@@ -955,18 +1050,16 @@ var clarifyThemeConfigSchema = z.object({
|
|
|
955
1050
|
tokens: clarifyThemeTokensConfigSchema.optional(),
|
|
956
1051
|
layout: clarifyThemeLayoutConfigSchema.optional()
|
|
957
1052
|
}).strict();
|
|
958
|
-
function featureSchema(shape, defaults) {
|
|
1053
|
+
function featureSchema(shape, defaults, enabledByDefault = true) {
|
|
1054
|
+
const resolvedDefaults = {
|
|
1055
|
+
enabled: enabledByDefault,
|
|
1056
|
+
...defaults
|
|
1057
|
+
};
|
|
959
1058
|
const objectSchema = z.object({
|
|
960
|
-
enabled: z.boolean().default(
|
|
1059
|
+
enabled: z.boolean().default(enabledByDefault),
|
|
961
1060
|
...shape
|
|
962
|
-
}).strict().default(
|
|
963
|
-
|
|
964
|
-
...defaults
|
|
965
|
-
});
|
|
966
|
-
return z.union([z.boolean(), objectSchema]).default({
|
|
967
|
-
enabled: true,
|
|
968
|
-
...defaults
|
|
969
|
-
}).transform((value) => typeof value === "boolean" ? {
|
|
1061
|
+
}).strict().default(resolvedDefaults);
|
|
1062
|
+
return z.union([z.boolean(), objectSchema]).default(resolvedDefaults).transform((value) => typeof value === "boolean" ? {
|
|
970
1063
|
enabled: value,
|
|
971
1064
|
...defaults
|
|
972
1065
|
} : value);
|
|
@@ -974,7 +1067,7 @@ function featureSchema(shape, defaults) {
|
|
|
974
1067
|
var clarifyFeaturesConfigSchema = z.object({
|
|
975
1068
|
search: featureSchema({ mcp: z.boolean().default(true) }, { mcp: true }),
|
|
976
1069
|
repository: featureSchema(clarifyRepositoryConfigSchema.shape, {}),
|
|
977
|
-
themeEditor: featureSchema({}, {}),
|
|
1070
|
+
themeEditor: featureSchema({}, {}, false),
|
|
978
1071
|
openapi: featureSchema({ playground: z.boolean().default(true) }, { playground: true })
|
|
979
1072
|
}).strict();
|
|
980
1073
|
var clarifyProjectConfigSchema = z.object({
|
|
@@ -1166,6 +1259,9 @@ function resolveVirtualId(id) {
|
|
|
1166
1259
|
function stripVirtualPrefix(id) {
|
|
1167
1260
|
return id.startsWith("\0") ? id.slice(1) : id;
|
|
1168
1261
|
}
|
|
1262
|
+
function virtualContentModuleId(route) {
|
|
1263
|
+
return route.module.contentVirtualModuleId;
|
|
1264
|
+
}
|
|
1169
1265
|
/**
|
|
1170
1266
|
* Fixed virtual module IDs (excluding the client entry, which has a special
|
|
1171
1267
|
* resolved form). Used to avoid hardcoding the constant list in every
|
|
@@ -1193,8 +1289,10 @@ function resolveVirtualModuleId(id, modules, routes) {
|
|
|
1193
1289
|
for (const virtualId of FIXED_VIRTUAL_IDS) if (id === virtualId || id === resolveVirtualId(virtualId)) return resolveVirtualId(virtualId);
|
|
1194
1290
|
const moduleId = stripVirtualPrefix(id);
|
|
1195
1291
|
if (modules.has(moduleId)) return resolveVirtualId(moduleId);
|
|
1196
|
-
const
|
|
1197
|
-
if (
|
|
1292
|
+
const contentRoute = routes.find((route) => (route.kind === "markdown" || route.kind === "markdown+jsx") && route.module.contentVirtualModuleId === moduleId);
|
|
1293
|
+
if (contentRoute) return contentRoute.source.filePath;
|
|
1294
|
+
const route = routes.find((route) => route.module.pageVirtualModuleId === id || route.module.pageVirtualModuleId === moduleId);
|
|
1295
|
+
if (route) return resolveVirtualId(route.module.pageVirtualModuleId);
|
|
1198
1296
|
return null;
|
|
1199
1297
|
}
|
|
1200
1298
|
function generateConfigModule(projectConfig, version) {
|
|
@@ -1248,8 +1346,8 @@ function routeToRuntimeManifestEntry(route, component, mode) {
|
|
|
1248
1346
|
return entry;
|
|
1249
1347
|
}
|
|
1250
1348
|
function generateRoutesModule(routes, navigation, mode = "client") {
|
|
1251
|
-
return `${mode === "server" ? routes.map((r, i) => `import Page${i} from ${moduleSpecifier(r.module.
|
|
1252
|
-
const component = mode === "server" ? `Page${i}` : `() => import(${moduleSpecifier(r.module.
|
|
1349
|
+
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) => {
|
|
1350
|
+
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 }) }))`;
|
|
1253
1351
|
const placeholder = `__COMPONENT_${i}__`;
|
|
1254
1352
|
const manifestEntry = routeToRuntimeManifestEntry(r, placeholder, mode);
|
|
1255
1353
|
return ` ${JSON.stringify(manifestEntry, null, 0).replace(`"${placeholder}"`, component).replace(/"([A-Za-z_$][\w$]*)":/g, "$1: ")}`;
|
|
@@ -1321,13 +1419,14 @@ function buildVirtualModules(args) {
|
|
|
1321
1419
|
modules.set(VIRTUAL_ROUTES, generateRoutesModule(args.routes, args.navigation, "client"));
|
|
1322
1420
|
modules.set(VIRTUAL_SERVER_ROUTES, generateRoutesModule(args.routes, args.navigation, "server"));
|
|
1323
1421
|
modules.set(VIRTUAL_SLOTS, createRuntimeSlotsModule(allPlugins, args.generateOptions.projectRoot));
|
|
1324
|
-
modules.set(VIRTUAL_OPENAPI, "export const openApiSpecs = {};");
|
|
1325
1422
|
modules.set(VIRTUAL_SLOT, "export { useSlot } from '@clarify-labs/renderer';\n");
|
|
1326
|
-
modules.set(
|
|
1423
|
+
modules.set(VIRTUAL_OPENAPI, "export const openApiSpecs = {};");
|
|
1327
1424
|
modules.set(RESOLVED_CLIENT_ENTRY, clientEntryModule);
|
|
1425
|
+
modules.set(VIRTUAL_CLIENT_ENTRY, clientEntryModule);
|
|
1328
1426
|
for (const route of args.routes) {
|
|
1329
|
-
const moduleContent = route.diagnostic ? generateContentDiagnosticModule(route.diagnostic) : `export { default } from ${moduleSpecifier(route
|
|
1330
|
-
|
|
1427
|
+
const moduleContent = route.diagnostic ? generateContentDiagnosticModule(route.diagnostic) : route.kind === "markdown" || route.kind === "markdown+jsx" ? `export { default } from ${moduleSpecifier(virtualContentModuleId(route))};` : null;
|
|
1428
|
+
if (moduleContent === null) continue;
|
|
1429
|
+
modules.set(route.module.pageVirtualModuleId, moduleContent);
|
|
1331
1430
|
}
|
|
1332
1431
|
return modules;
|
|
1333
1432
|
}
|
|
@@ -1368,7 +1467,7 @@ function createNormalizedContentPlugin(engine) {
|
|
|
1368
1467
|
transform(_code, id) {
|
|
1369
1468
|
if (!/\.mdx?(?:\?|$)/.test(id)) return null;
|
|
1370
1469
|
const filePath = id.replace(/\?.*$/, "");
|
|
1371
|
-
const route = engine.routes.find((route) => route.kind === "
|
|
1470
|
+
const route = engine.routes.find((route) => (route.kind === "markdown+jsx" || route.kind === "markdown") && route.source.filePath === filePath);
|
|
1372
1471
|
if (!route || route.source.content === void 0) return null;
|
|
1373
1472
|
return {
|
|
1374
1473
|
code: route.source.content,
|
|
@@ -1483,7 +1582,10 @@ function createClarifyViteCorePlugin(engine, normalizedContentPlugin, markdown,
|
|
|
1483
1582
|
};
|
|
1484
1583
|
server.watcher.on("add", handleContentTreeChange);
|
|
1485
1584
|
server.watcher.on("unlink", handleContentTreeChange);
|
|
1486
|
-
await engine.configureDevServer(server);
|
|
1585
|
+
const postHooks = await engine.configureDevServer(server);
|
|
1586
|
+
if (postHooks.length > 0) return () => {
|
|
1587
|
+
for (const postHook of postHooks) postHook();
|
|
1588
|
+
};
|
|
1487
1589
|
},
|
|
1488
1590
|
transformIndexHtml: {
|
|
1489
1591
|
order: "pre",
|
|
@@ -1538,7 +1640,7 @@ function createViteAdapter(engine) {
|
|
|
1538
1640
|
const errorPolicy = () => contentCompileErrorPolicy;
|
|
1539
1641
|
const normalizedContentPlugin = createNormalizedContentPlugin(engine);
|
|
1540
1642
|
const markdown = createContentCompilerPlugin("markdown", engine.root, errorPolicy);
|
|
1541
|
-
const mdx = createContentCompilerPlugin("
|
|
1643
|
+
const mdx = createContentCompilerPlugin("markdown+jsx", engine.root, errorPolicy);
|
|
1542
1644
|
const compilePolicyPlugin = {
|
|
1543
1645
|
name: "clarify:content-compile-policy",
|
|
1544
1646
|
configResolved(config) {
|
|
@@ -1558,7 +1660,7 @@ function createViteAdapter(engine) {
|
|
|
1558
1660
|
}
|
|
1559
1661
|
var cliPackageVersion = {
|
|
1560
1662
|
name: "@clarify-labs/cli",
|
|
1561
|
-
version: "0.11.
|
|
1663
|
+
version: "0.11.5",
|
|
1562
1664
|
license: "AGPL-3.0-only",
|
|
1563
1665
|
type: "module",
|
|
1564
1666
|
repository: {
|
|
@@ -1658,7 +1760,7 @@ function withUtf8Signature(content) {
|
|
|
1658
1760
|
return `${UTF8_SIGNATURE}${content}`;
|
|
1659
1761
|
}
|
|
1660
1762
|
function shouldUseUtf8Signature(route) {
|
|
1661
|
-
if (route.kind === "
|
|
1763
|
+
if (route.kind === "markdown+jsx" || route.kind === "markdown") return true;
|
|
1662
1764
|
return false;
|
|
1663
1765
|
}
|
|
1664
1766
|
function routeToMarkdownArtifactUrl(routePath) {
|
|
@@ -1730,9 +1832,9 @@ function createLlmsTxt(routes, projectConfig) {
|
|
|
1730
1832
|
const lines = [`# ${projectConfig.title}`, ""];
|
|
1731
1833
|
if (projectConfig.description) lines.push(`> ${projectConfig.description}`, "");
|
|
1732
1834
|
lines.push("This file lists the source-ready Markdown and OpenAPI artifacts for this documentation site.", "");
|
|
1733
|
-
const
|
|
1734
|
-
if (
|
|
1735
|
-
const localizedGroups = groupLlmsTxtRoutesByLocale(
|
|
1835
|
+
const markdownRoutes = routes.filter((route) => (route.kind === "markdown+jsx" || route.kind === "markdown") && isLlmsTxtRoute(route) && !route.isBareAlias);
|
|
1836
|
+
if (markdownRoutes.length > 0) {
|
|
1837
|
+
const localizedGroups = groupLlmsTxtRoutesByLocale(markdownRoutes, projectConfig);
|
|
1736
1838
|
for (const [locale, localeRoutes] of localizedGroups) {
|
|
1737
1839
|
lines.push(`## ${llmsTxtDocsSectionTitle(locale, localizedGroups.size, projectConfig)}`);
|
|
1738
1840
|
for (const route of localeRoutes) {
|
|
@@ -1809,10 +1911,12 @@ function createContentArtifactsPlugin() {
|
|
|
1809
1911
|
return input;
|
|
1810
1912
|
},
|
|
1811
1913
|
"dev:configureServer": (server, ctx) => {
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1914
|
+
return () => {
|
|
1915
|
+
server.middlewares.use((req, res, next) => {
|
|
1916
|
+
if (serveContentArtifacts(req, res, ctx.projectConfig, ctx.routes)) return;
|
|
1917
|
+
next();
|
|
1918
|
+
});
|
|
1919
|
+
};
|
|
1816
1920
|
},
|
|
1817
1921
|
"build:assets": (ctx) => {
|
|
1818
1922
|
const assets = [];
|
|
@@ -2303,7 +2407,7 @@ function findOpenAPIRoutes(dir, base = dir) {
|
|
|
2303
2407
|
basePath: cleanPath,
|
|
2304
2408
|
kind: "openapi",
|
|
2305
2409
|
meta: { title: kebabToTitle(cleanPath.split("/").pop() ?? "API") },
|
|
2306
|
-
module: {
|
|
2410
|
+
module: { pageVirtualModuleId: pageVirtualModuleIdFromRef(ref) },
|
|
2307
2411
|
source: { filePath: fullPath }
|
|
2308
2412
|
});
|
|
2309
2413
|
}
|
|
@@ -2427,34 +2531,7 @@ async function readOpenAPISpec(filePath, contentProcessor, projectRoot) {
|
|
|
2427
2531
|
}
|
|
2428
2532
|
}
|
|
2429
2533
|
//#endregion
|
|
2430
|
-
//#region source/plugins/openapi/
|
|
2431
|
-
var openApiRegistryModuleId = VIRTUAL_OPENAPI;
|
|
2432
|
-
var openApiServerRegistryModuleId = VIRTUAL_OPENAPI_SERVER;
|
|
2433
|
-
var OPENAPI_SPEC_PREFIX = "virtual:clarify/openapi-spec/";
|
|
2434
|
-
function specVirtualModuleId(specKey) {
|
|
2435
|
-
return `${OPENAPI_SPEC_PREFIX}${specKey}`;
|
|
2436
|
-
}
|
|
2437
|
-
function generateOpenAPIRegistryModule(openApiSpecs) {
|
|
2438
|
-
return `export const openApiSpecs = {\n${Object.entries(openApiSpecs).map(([key, moduleId]) => ` ${JSON.stringify(key)}: () => import(${JSON.stringify(moduleId)}),`).join("\n")}\n};`;
|
|
2439
|
-
}
|
|
2440
|
-
function generateOpenAPIServerRegistryModule(openApiSpecs) {
|
|
2441
|
-
return `export const openApiSpecs = ${JSON.stringify(openApiSpecs)};`;
|
|
2442
|
-
}
|
|
2443
|
-
/** Generate a virtual module that exports a single spec as default. */
|
|
2444
|
-
function generateOpenAPISpecModule(spec) {
|
|
2445
|
-
return `export default ${JSON.stringify(spec)};`;
|
|
2446
|
-
}
|
|
2447
|
-
function generateOpenAPIPageModule(opts) {
|
|
2448
|
-
return `import { createOpenApiRouteComponent } from '@clarify-labs/renderer';
|
|
2449
|
-
import spec from ${JSON.stringify(opts.specModuleId)};
|
|
2450
|
-
|
|
2451
|
-
export const routeData = {};
|
|
2452
|
-
|
|
2453
|
-
export default createOpenApiRouteComponent({ ...routeData, spec });
|
|
2454
|
-
`;
|
|
2455
|
-
}
|
|
2456
|
-
//#endregion
|
|
2457
|
-
//#region source/plugins/openapi/index.ts
|
|
2534
|
+
//#region source/plugins/openapi/routes.ts
|
|
2458
2535
|
function collectOpenAPIPageIntents(config) {
|
|
2459
2536
|
const intents = [];
|
|
2460
2537
|
function visitItems(items) {
|
|
@@ -2474,9 +2551,6 @@ function collectOpenAPIPageIntents(config) {
|
|
|
2474
2551
|
for (const tab of config.navigation?.tabs ?? []) visitPages(tab.pages);
|
|
2475
2552
|
return intents;
|
|
2476
2553
|
}
|
|
2477
|
-
function virtualModuleIdFromPath(path) {
|
|
2478
|
-
return `virtual:clarify-page/${path.replace(/^\/+/, "") || "index"}`;
|
|
2479
|
-
}
|
|
2480
2554
|
function cloneOpenAPIRoute(route, overrides = {}) {
|
|
2481
2555
|
return {
|
|
2482
2556
|
...route,
|
|
@@ -2494,7 +2568,7 @@ function cloneOpenAPIRoute(route, overrides = {}) {
|
|
|
2494
2568
|
...overrides
|
|
2495
2569
|
};
|
|
2496
2570
|
}
|
|
2497
|
-
function
|
|
2571
|
+
function discoverOpenAPIRoutes(contentRoot, locales) {
|
|
2498
2572
|
if (!locales) return findOpenAPIRoutes(contentRoot);
|
|
2499
2573
|
const localizedRoutes = [];
|
|
2500
2574
|
for (const locale of locales.locales) {
|
|
@@ -2507,31 +2581,30 @@ function findOpenAPIRoutesForContentRoot(contentRoot, locales) {
|
|
|
2507
2581
|
path,
|
|
2508
2582
|
basePath,
|
|
2509
2583
|
locale: locale.code,
|
|
2510
|
-
module: {
|
|
2584
|
+
module: { pageVirtualModuleId: pageVirtualModuleId(path) }
|
|
2511
2585
|
});
|
|
2512
2586
|
}
|
|
2513
2587
|
}
|
|
2514
|
-
if (locales.missing
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
}
|
|
2588
|
+
if (locales.missing !== "fallback") return localizedRoutes;
|
|
2589
|
+
const routeByLocaleAndBase = new Map(localizedRoutes.map((route) => [`${route.locale ?? ""}:${route.basePath ?? route.path}`, route]));
|
|
2590
|
+
const defaultRoutes = localizedRoutes.filter((route) => route.locale === locales.default);
|
|
2591
|
+
for (const sourceRoute of defaultRoutes) {
|
|
2592
|
+
const basePath = sourceRoute.basePath ?? sourceRoute.path;
|
|
2593
|
+
for (const locale of locales.locales) {
|
|
2594
|
+
const key = `${locale.code}:${basePath}`;
|
|
2595
|
+
if (routeByLocaleAndBase.has(key)) continue;
|
|
2596
|
+
const path = localizedRoutePath(basePath, locale.code, locales);
|
|
2597
|
+
localizedRoutes.push(cloneOpenAPIRoute(sourceRoute, {
|
|
2598
|
+
path,
|
|
2599
|
+
locale: locale.code,
|
|
2600
|
+
module: { pageVirtualModuleId: pageVirtualModuleId(path) },
|
|
2601
|
+
isFallback: true
|
|
2602
|
+
}));
|
|
2530
2603
|
}
|
|
2531
2604
|
}
|
|
2532
2605
|
return localizedRoutes;
|
|
2533
2606
|
}
|
|
2534
|
-
function
|
|
2607
|
+
function expandConfiguredOpenAPIRoutes(routes, config) {
|
|
2535
2608
|
const openAPIIntents = collectOpenAPIPageIntents(config);
|
|
2536
2609
|
if (!openAPIIntents.length) return routes;
|
|
2537
2610
|
const additions = [];
|
|
@@ -2550,7 +2623,7 @@ function createConfiguredOpenAPIRoutes(routes, config) {
|
|
|
2550
2623
|
additions.push(cloneOpenAPIRoute(route, {
|
|
2551
2624
|
path,
|
|
2552
2625
|
basePath: targetBasePath,
|
|
2553
|
-
module: {
|
|
2626
|
+
module: { pageVirtualModuleId: pageVirtualModuleId(path) },
|
|
2554
2627
|
openapi: {
|
|
2555
2628
|
...route.openapi,
|
|
2556
2629
|
tagFilter: tagFilter?.length ? tagFilter : void 0
|
|
@@ -2564,19 +2637,47 @@ function createConfiguredOpenAPIRoutes(routes, config) {
|
|
|
2564
2637
|
const bareAliases = [];
|
|
2565
2638
|
const seenBare = new Set(routesWithAlternates.map((route) => route.path));
|
|
2566
2639
|
for (const route of routesWithAlternates) {
|
|
2567
|
-
if (route.locale !== config.locales.default) continue;
|
|
2640
|
+
if (route.kind !== "openapi" || route.locale !== config.locales.default) continue;
|
|
2568
2641
|
const basePath = route.basePath ?? route.path;
|
|
2569
2642
|
if (basePath === route.path || seenBare.has(basePath)) continue;
|
|
2570
2643
|
seenBare.add(basePath);
|
|
2571
2644
|
bareAliases.push(cloneOpenAPIRoute(route, {
|
|
2572
2645
|
path: basePath,
|
|
2573
|
-
module: {
|
|
2646
|
+
module: { pageVirtualModuleId: pageVirtualModuleId(basePath) },
|
|
2574
2647
|
isBareAlias: true
|
|
2575
2648
|
}));
|
|
2576
2649
|
}
|
|
2577
2650
|
return [...routesWithAlternates, ...bareAliases];
|
|
2578
2651
|
}
|
|
2579
|
-
|
|
2652
|
+
//#endregion
|
|
2653
|
+
//#region source/plugins/openapi/virtual-modules.ts
|
|
2654
|
+
var openApiRegistryModuleId = VIRTUAL_OPENAPI;
|
|
2655
|
+
var openApiServerRegistryModuleId = VIRTUAL_OPENAPI_SERVER;
|
|
2656
|
+
var OPENAPI_SPEC_PREFIX = "virtual:clarify/openapi-spec/";
|
|
2657
|
+
function specVirtualModuleId(specKey) {
|
|
2658
|
+
return `${OPENAPI_SPEC_PREFIX}${specKey}`;
|
|
2659
|
+
}
|
|
2660
|
+
function generateOpenAPIRegistryModule(openApiSpecs) {
|
|
2661
|
+
return `export const openApiSpecs = {\n${Object.entries(openApiSpecs).map(([key, moduleId]) => ` ${JSON.stringify(key)}: () => import(${JSON.stringify(moduleId)}),`).join("\n")}\n};`;
|
|
2662
|
+
}
|
|
2663
|
+
function generateOpenAPIServerRegistryModule(openApiSpecs) {
|
|
2664
|
+
return `export const openApiSpecs = ${JSON.stringify(openApiSpecs)};`;
|
|
2665
|
+
}
|
|
2666
|
+
/** Generate a virtual module that exports a single spec as default. */
|
|
2667
|
+
function generateOpenAPISpecModule(spec) {
|
|
2668
|
+
return `export default ${JSON.stringify(spec)};`;
|
|
2669
|
+
}
|
|
2670
|
+
function generateOpenAPIPageModule(opts) {
|
|
2671
|
+
return `import { createOpenApiRouteComponent } from '@clarify-labs/renderer';
|
|
2672
|
+
import spec from ${JSON.stringify(opts.specModuleId)};
|
|
2673
|
+
|
|
2674
|
+
export const routeData = {};
|
|
2675
|
+
|
|
2676
|
+
export default createOpenApiRouteComponent({ ...routeData, spec });
|
|
2677
|
+
`;
|
|
2678
|
+
}
|
|
2679
|
+
//#endregion
|
|
2680
|
+
//#region source/plugins/openapi/state.ts
|
|
2580
2681
|
function sourceSpecIdFromPath(filePath, projectRoot) {
|
|
2581
2682
|
return relative(projectRoot, filePath).replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
2582
2683
|
}
|
|
@@ -2588,90 +2689,94 @@ function openAPIRegistryKeys(route) {
|
|
|
2588
2689
|
const keys = /* @__PURE__ */ new Set();
|
|
2589
2690
|
const path = (route.path || "/").replace(/^\//, "");
|
|
2590
2691
|
const base = (route.basePath ?? route.path).replace(/^\//, "");
|
|
2591
|
-
if (route.locale) keys.add(
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
if (!route.locale && base) keys.add(`virtual:clarify-page/${base}`);
|
|
2692
|
+
if (route.locale) keys.add(pageVirtualModuleId(`${route.locale}/${base}`));
|
|
2693
|
+
keys.add(pageVirtualModuleId(path));
|
|
2694
|
+
if (!route.locale && base) keys.add(pageVirtualModuleId(base));
|
|
2595
2695
|
return [...keys];
|
|
2596
2696
|
}
|
|
2697
|
+
var OpenAPIPluginState = class {
|
|
2698
|
+
specModules = /* @__PURE__ */ new Map();
|
|
2699
|
+
async enrichRoutes(routes, ctx) {
|
|
2700
|
+
this.specModules.clear();
|
|
2701
|
+
const specByFilePath = /* @__PURE__ */ new Map();
|
|
2702
|
+
for (const route of routes) {
|
|
2703
|
+
if (route.kind !== "openapi") continue;
|
|
2704
|
+
const specFromCache = specByFilePath.get(route.source.filePath);
|
|
2705
|
+
const processor = createProjectContentProcessor(ctx.plugins, ctx);
|
|
2706
|
+
const result = specFromCache ? {
|
|
2707
|
+
ok: true,
|
|
2708
|
+
spec: specFromCache
|
|
2709
|
+
} : await readOpenAPISpec(route.source.filePath, processor, ctx.generateOptions.projectRoot);
|
|
2710
|
+
if (!result.ok) {
|
|
2711
|
+
route.diagnostic = result.diagnostic;
|
|
2712
|
+
route.meta.title = route.meta.title || "OpenAPI parse error";
|
|
2713
|
+
route.meta.sections = [];
|
|
2714
|
+
continue;
|
|
2715
|
+
}
|
|
2716
|
+
const spec = normalizeOpenAPISpecSectionIds(result.spec);
|
|
2717
|
+
specByFilePath.set(route.source.filePath, spec);
|
|
2718
|
+
const sourceSpecId = sourceSpecIdFromPath(route.source.filePath, ctx.generateOptions.projectRoot);
|
|
2719
|
+
route.openapi = {
|
|
2720
|
+
...route.openapi,
|
|
2721
|
+
sourceSpecId
|
|
2722
|
+
};
|
|
2723
|
+
route.meta.title = spec.info?.title ?? route.meta.title;
|
|
2724
|
+
route.meta.description = spec.info?.description ?? route.meta.description;
|
|
2725
|
+
route.meta.sections = extractOpenAPISections(spec, route.openapi.tagFilter);
|
|
2726
|
+
const pageSpec = route.openapi.tagFilter?.length ? filterSpecByTags(spec, route.openapi.tagFilter) : spec;
|
|
2727
|
+
const routeSpecModuleId = routeSpecModuleIdFromSourceSpecId(sourceSpecId, route.openapi.tagFilter);
|
|
2728
|
+
route.openapi.routeSpecModuleId = routeSpecModuleId;
|
|
2729
|
+
this.specModules.set(routeSpecModuleId, pageSpec);
|
|
2730
|
+
route.source.content = JSON.stringify(pageSpec);
|
|
2731
|
+
}
|
|
2732
|
+
return routes;
|
|
2733
|
+
}
|
|
2734
|
+
contributeModules(modules, routes) {
|
|
2735
|
+
const registryEntries = {};
|
|
2736
|
+
const serverRegistryEntries = {};
|
|
2737
|
+
for (const route of routes) {
|
|
2738
|
+
if (route.kind !== "openapi" || !route.openapi?.sourceSpecId) continue;
|
|
2739
|
+
const routeSpecModuleId = route.openapi.routeSpecModuleId ?? route.openapi.sourceSpecId;
|
|
2740
|
+
const spec = this.specModules.get(routeSpecModuleId);
|
|
2741
|
+
if (!spec) continue;
|
|
2742
|
+
for (const registryKey of openAPIRegistryKeys(route)) {
|
|
2743
|
+
registryEntries[registryKey] = specVirtualModuleId(routeSpecModuleId);
|
|
2744
|
+
serverRegistryEntries[registryKey] = spec;
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
modules.set(openApiRegistryModuleId, generateOpenAPIRegistryModule(registryEntries));
|
|
2748
|
+
modules.set(openApiServerRegistryModuleId, generateOpenAPIServerRegistryModule(serverRegistryEntries));
|
|
2749
|
+
for (const [routeSpecModuleId, spec] of this.specModules) modules.set(specVirtualModuleId(routeSpecModuleId), generateOpenAPISpecModule(spec));
|
|
2750
|
+
for (const route of routes) {
|
|
2751
|
+
if (route.kind !== "openapi") continue;
|
|
2752
|
+
if (route.diagnostic) {
|
|
2753
|
+
modules.set(route.module.pageVirtualModuleId, generateContentDiagnosticModule(route.diagnostic));
|
|
2754
|
+
continue;
|
|
2755
|
+
}
|
|
2756
|
+
if (!route.openapi?.sourceSpecId) continue;
|
|
2757
|
+
const routeSpecModuleId = route.openapi.routeSpecModuleId ?? route.openapi.sourceSpecId;
|
|
2758
|
+
if (!this.specModules.has(routeSpecModuleId)) continue;
|
|
2759
|
+
modules.set(route.module.pageVirtualModuleId, generateOpenAPIPageModule({ specModuleId: specVirtualModuleId(routeSpecModuleId) }));
|
|
2760
|
+
}
|
|
2761
|
+
return modules;
|
|
2762
|
+
}
|
|
2763
|
+
};
|
|
2764
|
+
//#endregion
|
|
2765
|
+
//#region source/plugins/openapi/index.ts
|
|
2597
2766
|
function createOpenAPIPlugin() {
|
|
2598
|
-
|
|
2599
|
-
const specs = /* @__PURE__ */ new Map();
|
|
2600
|
-
const specModules = /* @__PURE__ */ new Map();
|
|
2767
|
+
const state = new OpenAPIPluginState();
|
|
2601
2768
|
return {
|
|
2602
2769
|
name: "clarify:openapi",
|
|
2603
2770
|
hooks: {
|
|
2604
2771
|
"routes:discover": (input, ctx) => ({
|
|
2605
2772
|
...input,
|
|
2606
|
-
routes: [...input.routes, ...
|
|
2773
|
+
routes: [...input.routes, ...discoverOpenAPIRoutes(input.contentRoot, ctx.projectConfig.locales)]
|
|
2607
2774
|
}),
|
|
2608
2775
|
"routes:discovered": async (routes, ctx) => {
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
const nextRoutes = createConfiguredOpenAPIRoutes(routes, ctx.projectConfig);
|
|
2612
|
-
const specByFilePath = /* @__PURE__ */ new Map();
|
|
2613
|
-
for (const route of nextRoutes.filter((route) => route.kind === "openapi")) {
|
|
2614
|
-
const specFromCache = specByFilePath.get(route.source.filePath);
|
|
2615
|
-
const processor = createProjectContentProcessor(ctx.plugins, ctx);
|
|
2616
|
-
const result = specFromCache ? {
|
|
2617
|
-
ok: true,
|
|
2618
|
-
spec: specFromCache
|
|
2619
|
-
} : await readOpenAPISpec(route.source.filePath, processor, ctx.generateOptions.projectRoot);
|
|
2620
|
-
if (!result.ok) {
|
|
2621
|
-
route.diagnostic = result.diagnostic;
|
|
2622
|
-
route.meta.title = route.meta.title || "OpenAPI parse error";
|
|
2623
|
-
route.meta.sections = [];
|
|
2624
|
-
continue;
|
|
2625
|
-
}
|
|
2626
|
-
const spec = normalizeOpenAPISpecSectionIds(result.spec);
|
|
2627
|
-
specByFilePath.set(route.source.filePath, spec);
|
|
2628
|
-
const sourceSpecId = sourceSpecIdFromPath(route.source.filePath, ctx.generateOptions.projectRoot);
|
|
2629
|
-
route.openapi = {
|
|
2630
|
-
...route.openapi,
|
|
2631
|
-
sourceSpecId
|
|
2632
|
-
};
|
|
2633
|
-
specs.set(sourceSpecId, {
|
|
2634
|
-
spec,
|
|
2635
|
-
filePath: route.source.filePath
|
|
2636
|
-
});
|
|
2637
|
-
route.meta.title = spec.info?.title ?? route.meta.title;
|
|
2638
|
-
route.meta.description = spec.info?.description ?? route.meta.description;
|
|
2639
|
-
route.meta.sections = extractOpenAPISections(spec, route.openapi?.tagFilter);
|
|
2640
|
-
const pageSpec = route.openapi?.tagFilter?.length ? filterSpecByTags(spec, route.openapi.tagFilter) : spec;
|
|
2641
|
-
const routeSpecModuleId = routeSpecModuleIdFromSourceSpecId(sourceSpecId, route.openapi?.tagFilter);
|
|
2642
|
-
route.openapi.routeSpecModuleId = routeSpecModuleId;
|
|
2643
|
-
specModules.set(routeSpecModuleId, pageSpec);
|
|
2644
|
-
route.source.content = JSON.stringify(pageSpec);
|
|
2645
|
-
}
|
|
2646
|
-
return nextRoutes;
|
|
2776
|
+
const expandedRoutes = expandConfiguredOpenAPIRoutes(routes, ctx.projectConfig);
|
|
2777
|
+
return state.enrichRoutes(expandedRoutes, ctx);
|
|
2647
2778
|
},
|
|
2648
|
-
"modules:before": (modules, ctx) =>
|
|
2649
|
-
const registryEntries = {};
|
|
2650
|
-
const serverRegistryEntries = {};
|
|
2651
|
-
for (const route of ctx.routes) {
|
|
2652
|
-
if (route.kind !== "openapi" || !route.openapi?.sourceSpecId) continue;
|
|
2653
|
-
const routeSpecModuleId = route.openapi.routeSpecModuleId ?? route.openapi.sourceSpecId;
|
|
2654
|
-
const spec = specModules.get(routeSpecModuleId) ?? specs.get(route.openapi.sourceSpecId)?.spec;
|
|
2655
|
-
if (!spec) continue;
|
|
2656
|
-
for (const registryKey of openAPIRegistryKeys(route)) {
|
|
2657
|
-
registryEntries[registryKey] = specVirtualModuleId(routeSpecModuleId);
|
|
2658
|
-
serverRegistryEntries[registryKey] = spec;
|
|
2659
|
-
}
|
|
2660
|
-
}
|
|
2661
|
-
modules.set(openApiRegistryModuleId, generateOpenAPIRegistryModule(registryEntries));
|
|
2662
|
-
modules.set(openApiServerRegistryModuleId, generateOpenAPIServerRegistryModule(serverRegistryEntries));
|
|
2663
|
-
for (const [routeSpecModuleId, spec] of specModules) modules.set(specVirtualModuleId(routeSpecModuleId), generateOpenAPISpecModule(spec));
|
|
2664
|
-
for (const route of ctx.routes) {
|
|
2665
|
-
if (route.kind !== "openapi") continue;
|
|
2666
|
-
if (route.diagnostic) modules.set(route.module.virtualModuleId, generateContentDiagnosticModule(route.diagnostic));
|
|
2667
|
-
else if (route.openapi?.sourceSpecId) {
|
|
2668
|
-
const routeSpecModuleId = route.openapi.routeSpecModuleId ?? route.openapi.sourceSpecId;
|
|
2669
|
-
if (!specModules.has(routeSpecModuleId)) continue;
|
|
2670
|
-
modules.set(route.module.virtualModuleId, generateOpenAPIPageModule({ specModuleId: specVirtualModuleId(routeSpecModuleId) }));
|
|
2671
|
-
}
|
|
2672
|
-
}
|
|
2673
|
-
return modules;
|
|
2674
|
-
}
|
|
2779
|
+
"modules:before": (modules, ctx) => state.contributeModules(modules, ctx.routes)
|
|
2675
2780
|
}
|
|
2676
2781
|
};
|
|
2677
2782
|
}
|
|
@@ -3080,6 +3185,145 @@ async function resolveProjectContext(options = {}, env = {
|
|
|
3080
3185
|
};
|
|
3081
3186
|
}
|
|
3082
3187
|
//#endregion
|
|
3188
|
+
//#region source/core/routing/route-analysis.ts
|
|
3189
|
+
function routeDescription(route) {
|
|
3190
|
+
return `${route.kind} ${route.source.filePath}`;
|
|
3191
|
+
}
|
|
3192
|
+
function collectConflicts(routes, keyOf) {
|
|
3193
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
3194
|
+
for (const route of routes) {
|
|
3195
|
+
const key = keyOf(route);
|
|
3196
|
+
grouped.set(key, [...grouped.get(key) ?? [], route]);
|
|
3197
|
+
}
|
|
3198
|
+
return grouped;
|
|
3199
|
+
}
|
|
3200
|
+
function describeRouteConflict(route) {
|
|
3201
|
+
return routeDescription(route);
|
|
3202
|
+
}
|
|
3203
|
+
function findRouteConflicts(routes) {
|
|
3204
|
+
const conflicts = [];
|
|
3205
|
+
for (const [path, pathRoutes] of collectConflicts(routes, (route) => route.path)) {
|
|
3206
|
+
if (pathRoutes.length < 2) continue;
|
|
3207
|
+
conflicts.push({
|
|
3208
|
+
kind: "path",
|
|
3209
|
+
key: path,
|
|
3210
|
+
label: `path ${path}`,
|
|
3211
|
+
routes: pathRoutes
|
|
3212
|
+
});
|
|
3213
|
+
}
|
|
3214
|
+
for (const [pageModuleId, moduleRoutes] of collectConflicts(routes, (route) => route.module.pageVirtualModuleId)) {
|
|
3215
|
+
if (moduleRoutes.length < 2) continue;
|
|
3216
|
+
if (moduleRoutes.every((route) => route.path === moduleRoutes[0].path)) continue;
|
|
3217
|
+
conflicts.push({
|
|
3218
|
+
kind: "page-module",
|
|
3219
|
+
key: pageModuleId,
|
|
3220
|
+
label: `page module ${pageModuleId}`,
|
|
3221
|
+
routes: moduleRoutes
|
|
3222
|
+
});
|
|
3223
|
+
}
|
|
3224
|
+
return conflicts;
|
|
3225
|
+
}
|
|
3226
|
+
function formatRouteConflicts(conflicts) {
|
|
3227
|
+
return conflicts.map((conflict) => `- ${conflict.label}: ${conflict.routes.map(describeRouteConflict).join(", ")}`).join("\n");
|
|
3228
|
+
}
|
|
3229
|
+
//#endregion
|
|
3230
|
+
//#region source/core/routing/route-resolution.ts
|
|
3231
|
+
async function resolveRoutePages(routes, plugins, ctx) {
|
|
3232
|
+
const routeToken = Symbol("clarifyRouteToken");
|
|
3233
|
+
const resolvedPages = await runHooks(plugins, "pages:resolved", routes.map((route, routeIndex) => ({
|
|
3234
|
+
path: route.path,
|
|
3235
|
+
filePath: route.source.filePath,
|
|
3236
|
+
frontmatter: route.source.frontmatter ?? {},
|
|
3237
|
+
content: route.source.content ?? "",
|
|
3238
|
+
[routeToken]: routeIndex
|
|
3239
|
+
})), ctx);
|
|
3240
|
+
const pageByRouteIndex = /* @__PURE__ */ new Map();
|
|
3241
|
+
for (const page of resolvedPages) {
|
|
3242
|
+
const routeIndex = page[routeToken];
|
|
3243
|
+
if (!Number.isInteger(routeIndex) || routeIndex < 0 || routeIndex >= routes.length) throw new Error("[clarify] pages:resolved hooks must preserve each page route identity");
|
|
3244
|
+
if (pageByRouteIndex.has(routeIndex)) throw new Error("[clarify] pages:resolved hooks returned the same page route identity more than once");
|
|
3245
|
+
pageByRouteIndex.set(routeIndex, page);
|
|
3246
|
+
}
|
|
3247
|
+
if (pageByRouteIndex.size !== routes.length) throw new Error("[clarify] pages:resolved hooks must return exactly one page for each route");
|
|
3248
|
+
return routes.map((route, routeIndex) => {
|
|
3249
|
+
const page = pageByRouteIndex.get(routeIndex);
|
|
3250
|
+
return {
|
|
3251
|
+
...route,
|
|
3252
|
+
source: {
|
|
3253
|
+
...route.source,
|
|
3254
|
+
frontmatter: page.frontmatter,
|
|
3255
|
+
content: page.content
|
|
3256
|
+
}
|
|
3257
|
+
};
|
|
3258
|
+
});
|
|
3259
|
+
}
|
|
3260
|
+
function buildNavigationTree(routes, ctx) {
|
|
3261
|
+
const tabs = ctx.projectConfig.navigation?.tabs;
|
|
3262
|
+
if (!tabs) return {
|
|
3263
|
+
kind: "flat",
|
|
3264
|
+
nodes: buildNavigation(routes)
|
|
3265
|
+
};
|
|
3266
|
+
if (!ctx.projectConfig.locales) return buildNavigationFromTabsConfig(routes, tabs);
|
|
3267
|
+
return buildLocalizedNavigationFromTabsConfig(routes, tabs, ctx.projectConfig.locales) ?? {
|
|
3268
|
+
kind: "localized-tabbed",
|
|
3269
|
+
locales: {}
|
|
3270
|
+
};
|
|
3271
|
+
}
|
|
3272
|
+
function assertNoRouteConflicts(routes) {
|
|
3273
|
+
const conflicts = findRouteConflicts(routes);
|
|
3274
|
+
if (conflicts.length > 0) throw new Error(`[clarify] Route conflicts prevent the site from being built:\n${formatRouteConflicts(conflicts)}`);
|
|
3275
|
+
}
|
|
3276
|
+
function createRouteConflictDiagnostic(label, routes) {
|
|
3277
|
+
return {
|
|
3278
|
+
kind: "route-load",
|
|
3279
|
+
title: "Route conflict",
|
|
3280
|
+
message: `This page cannot be rendered because ${label} is used by multiple routes.`,
|
|
3281
|
+
details: routes.map(describeRouteConflict).join("\n")
|
|
3282
|
+
};
|
|
3283
|
+
}
|
|
3284
|
+
function createDevRouteConflictRoutes(routes) {
|
|
3285
|
+
const conflicts = findRouteConflicts(routes);
|
|
3286
|
+
if (conflicts.length === 0) return routes;
|
|
3287
|
+
const conflictedRoutes = /* @__PURE__ */ new Map();
|
|
3288
|
+
for (const conflict of conflicts) for (const route of conflict.routes) conflictedRoutes.set(route, conflict);
|
|
3289
|
+
function createConflictRoute(route, conflict) {
|
|
3290
|
+
return {
|
|
3291
|
+
...route,
|
|
3292
|
+
module: {
|
|
3293
|
+
...route.module,
|
|
3294
|
+
pageVirtualModuleId: `${route.module.pageVirtualModuleId}__conflict`
|
|
3295
|
+
},
|
|
3296
|
+
diagnostic: createRouteConflictDiagnostic(conflict.label, conflict.routes)
|
|
3297
|
+
};
|
|
3298
|
+
}
|
|
3299
|
+
const usedPaths = /* @__PURE__ */ new Set();
|
|
3300
|
+
return routes.flatMap((route) => {
|
|
3301
|
+
const conflict = conflictedRoutes.get(route);
|
|
3302
|
+
if (!conflict) return [route];
|
|
3303
|
+
if (usedPaths.has(route.path)) return [];
|
|
3304
|
+
usedPaths.add(route.path);
|
|
3305
|
+
return [createConflictRoute(route, conflict)];
|
|
3306
|
+
});
|
|
3307
|
+
}
|
|
3308
|
+
function handleRouteConflicts(routes, development) {
|
|
3309
|
+
if (development) return createDevRouteConflictRoutes(routes);
|
|
3310
|
+
assertNoRouteConflicts(routes);
|
|
3311
|
+
return routes;
|
|
3312
|
+
}
|
|
3313
|
+
async function resolveRouteState(routes, plugins, ctx, development) {
|
|
3314
|
+
const tabs = ctx.projectConfig.navigation?.tabs;
|
|
3315
|
+
const configuredRoutes = applyConfiguredPageRoutePaths(routes, tabs, ctx.projectConfig.locales);
|
|
3316
|
+
const resolved = await runHooks(plugins, "routes:resolved", {
|
|
3317
|
+
routes: configuredRoutes,
|
|
3318
|
+
navigation: buildNavigationTree(configuredRoutes, ctx)
|
|
3319
|
+
}, ctx);
|
|
3320
|
+
const finalRoutes = handleRouteConflicts(resolved.routes, development);
|
|
3321
|
+
return {
|
|
3322
|
+
routes: finalRoutes,
|
|
3323
|
+
navigation: finalRoutes === resolved.routes ? resolved.navigation : buildNavigationTree(finalRoutes, ctx)
|
|
3324
|
+
};
|
|
3325
|
+
}
|
|
3326
|
+
//#endregion
|
|
3083
3327
|
//#region source/core/runtime/env-types.ts
|
|
3084
3328
|
var GENERATED_FILE_NAME = "clarify-env.d.ts";
|
|
3085
3329
|
/**
|
|
@@ -3620,7 +3864,7 @@ var ClarifyEngine = class {
|
|
|
3620
3864
|
async discoverSite() {
|
|
3621
3865
|
const plugins = this.ctx.plugins;
|
|
3622
3866
|
const contentRoot = this.ctx.contentRoot;
|
|
3623
|
-
const { locales
|
|
3867
|
+
const { locales } = this.ctx.projectConfig;
|
|
3624
3868
|
let routes = await runPhase(plugins, "site:discover", this.ctx, async () => {
|
|
3625
3869
|
const options = { contentProcessor: createProjectContentProcessor(plugins, this.ctx) };
|
|
3626
3870
|
const discovered = locales ? await findLocalizedContentRoutes(contentRoot, locales, options) : await findContentRoutes(contentRoot, contentRoot, options);
|
|
@@ -3628,43 +3872,10 @@ var ClarifyEngine = class {
|
|
|
3628
3872
|
contentRoot,
|
|
3629
3873
|
routes: discovered
|
|
3630
3874
|
}, this.ctx);
|
|
3631
|
-
return runHooks(plugins, "routes:discovered", result.routes, this.ctx);
|
|
3875
|
+
return await runHooks(plugins, "routes:discovered", result.routes, this.ctx);
|
|
3632
3876
|
});
|
|
3633
|
-
routes = await runPhase(plugins, "content:process", this.ctx,
|
|
3634
|
-
|
|
3635
|
-
path: route.path,
|
|
3636
|
-
filePath: route.source.filePath,
|
|
3637
|
-
frontmatter: route.source.frontmatter ?? {},
|
|
3638
|
-
content: route.source.content ?? ""
|
|
3639
|
-
}));
|
|
3640
|
-
const resolvedPages = await runHooks(plugins, "pages:resolved", pages, this.ctx);
|
|
3641
|
-
const pageByPath = new Map(resolvedPages.map((p) => [p.path, p]));
|
|
3642
|
-
return routes.map((route) => {
|
|
3643
|
-
const page = pageByPath.get(route.path);
|
|
3644
|
-
if (!page) return route;
|
|
3645
|
-
return {
|
|
3646
|
-
...route,
|
|
3647
|
-
source: {
|
|
3648
|
-
...route.source,
|
|
3649
|
-
frontmatter: page.frontmatter,
|
|
3650
|
-
content: page.content
|
|
3651
|
-
}
|
|
3652
|
-
};
|
|
3653
|
-
});
|
|
3654
|
-
});
|
|
3655
|
-
const tabs = navigationConfig?.tabs;
|
|
3656
|
-
routes = applyConfiguredPageRoutePaths(routes, tabs, locales);
|
|
3657
|
-
const navigation = tabs ? locales ? buildLocalizedNavigationFromTabsConfig(routes, tabs, locales) ?? {
|
|
3658
|
-
kind: "localized-tabbed",
|
|
3659
|
-
locales: {}
|
|
3660
|
-
} : buildNavigationFromTabsConfig(routes, tabs) : {
|
|
3661
|
-
kind: "flat",
|
|
3662
|
-
nodes: buildNavigation(routes)
|
|
3663
|
-
};
|
|
3664
|
-
const resolved = await runHooks(plugins, "routes:resolved", {
|
|
3665
|
-
routes,
|
|
3666
|
-
navigation
|
|
3667
|
-
}, this.ctx);
|
|
3877
|
+
routes = await runPhase(plugins, "content:process", this.ctx, () => resolveRoutePages(routes, plugins, this.ctx));
|
|
3878
|
+
const resolved = await resolveRouteState(routes, plugins, this.ctx, this.runtime.command === "serve");
|
|
3668
3879
|
this.ctx.routes = resolved.routes;
|
|
3669
3880
|
this.ctx.navigation = resolved.navigation;
|
|
3670
3881
|
}
|
|
@@ -3714,8 +3925,8 @@ var ClarifyEngine = class {
|
|
|
3714
3925
|
return this.buildEnabled;
|
|
3715
3926
|
}
|
|
3716
3927
|
async configureDevServer(server) {
|
|
3717
|
-
|
|
3718
|
-
|
|
3928
|
+
return runPhase(this.plugins, "dev:server", this.ctx, () => {
|
|
3929
|
+
return runDevConfigureServerHooks(this.plugins, server, this.ctx);
|
|
3719
3930
|
});
|
|
3720
3931
|
}
|
|
3721
3932
|
async runBuildDone() {
|
|
@@ -3786,6 +3997,6 @@ function createClarifyEngine(options = {}) {
|
|
|
3786
3997
|
return new ClarifyEngine(options);
|
|
3787
3998
|
}
|
|
3788
3999
|
//#endregion
|
|
3789
|
-
export {
|
|
4000
|
+
export { createClarifyTempDir as a, cliPackageVersion as c, defineConfig as d, findRouteConflicts as i, cliPackageVersionWithCaret as l, createClarifyEngine as n, deserializeSearchIndex as o, createClarifyRuntimeAliases as r, searchMcpIndex as s, ClarifyEngine as t, createViteAdapter as u };
|
|
3790
4001
|
|
|
3791
|
-
//# sourceMappingURL=engine-
|
|
4002
|
+
//# sourceMappingURL=engine-DuiJVdO8.js.map
|