@farming-labs/next 0.2.114 → 0.2.116
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-reference.d.mts +7 -2
- package/dist/api-reference.mjs +48 -15
- package/dist/api.mjs +5 -3
- package/dist/config.mjs +145 -44
- package/package.json +3 -3
package/dist/api-reference.d.mts
CHANGED
|
@@ -34,8 +34,13 @@ declare function createNextApiReferencePage(config: DocsConfig): (props?: {
|
|
|
34
34
|
}) => Promise<react_jsx_runtime0.JSX.Element>;
|
|
35
35
|
declare function createNextApiReferenceLayout(config: DocsConfig): (props: {
|
|
36
36
|
children: React.ReactNode;
|
|
37
|
+
params?: Promise<{
|
|
38
|
+
slug?: string[];
|
|
39
|
+
}> | {
|
|
40
|
+
slug?: string[];
|
|
41
|
+
};
|
|
37
42
|
}) => Promise<react_jsx_runtime0.JSX.Element>;
|
|
38
|
-
declare function getNextApiReferenceSourceState(config: DocsConfig): Promise<NextApiReferenceSourceState>;
|
|
39
|
-
declare function getNextApiReferenceMode(config: DocsConfig): "fumadocs" | "scalar";
|
|
43
|
+
declare function getNextApiReferenceSourceState(config: DocsConfig, versionId?: string): Promise<NextApiReferenceSourceState>;
|
|
44
|
+
declare function getNextApiReferenceMode(config: DocsConfig): "farming-labs" | "fumadocs" | "scalar";
|
|
40
45
|
//#endregion
|
|
41
46
|
export { NextApiReferenceSourceState, buildNextOpenApiDocument, createNextApiReference, createNextApiReferenceLayout, createNextApiReferencePage, flattenApiReferencePageTreeForSidebar, getNextApiReferenceMode, getNextApiReferenceSourceState, resolveApiReferenceConfig, withNextApiReferenceBanner };
|
package/dist/api-reference.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import DocsClientCallbacks from "./client-callbacks.mjs";
|
|
2
2
|
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
3
|
import { join, relative } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { resolveDocsMetadataBaseUrl } from "@farming-labs/docs";
|
|
5
|
+
import { buildApiReferenceHtmlDocumentAsync, buildApiReferenceOpenApiDocumentAsync, buildApiReferencePageTitle, buildApiReferenceScalarCss, createApiReferenceOperationMarkdownResponse, resolveApiReferenceConfig, resolveApiReferenceRenderer, resolveApiReferenceVersion, resolveApiReferenceVersionFromPathname } from "@farming-labs/docs/server";
|
|
5
6
|
import { ApiReference } from "@scalar/nextjs-api-reference";
|
|
6
7
|
import { SidebarTabsDropdown } from "fumadocs-ui/components/sidebar/tabs/dropdown";
|
|
7
8
|
import Link from "next/link";
|
|
@@ -235,11 +236,12 @@ function buildOpenApiPaths(routes) {
|
|
|
235
236
|
return paths;
|
|
236
237
|
}
|
|
237
238
|
function buildNextOpenApiDocument(config) {
|
|
238
|
-
|
|
239
|
+
const apiReference = resolveApiReferenceConfig(config.apiReference);
|
|
240
|
+
if (apiReference.specUrl || apiReference.versions.length > 0) return {
|
|
239
241
|
openapi: "3.1.0",
|
|
240
242
|
info: {
|
|
241
243
|
title: "API Reference",
|
|
242
|
-
description: "
|
|
244
|
+
description: "Configured OpenAPI specs are resolved at request time through the Next.js API reference renderer.",
|
|
243
245
|
version: "0.0.0"
|
|
244
246
|
},
|
|
245
247
|
servers: [{ url: "/" }],
|
|
@@ -552,14 +554,39 @@ function createNextApiReference(config) {
|
|
|
552
554
|
const apiReference = resolveApiReferenceConfig(config.apiReference);
|
|
553
555
|
return async (request) => {
|
|
554
556
|
if (!apiReference.enabled) return new Response("Not Found", { status: 404 });
|
|
557
|
+
const requestUrl = request ? new URL(request.url) : void 0;
|
|
558
|
+
if (request && requestUrl) {
|
|
559
|
+
const markdownResponse = await createApiReferenceOperationMarkdownResponse(config, {
|
|
560
|
+
request,
|
|
561
|
+
framework: "next",
|
|
562
|
+
rootDir: process.cwd(),
|
|
563
|
+
baseUrl: getOriginFromRequest(request),
|
|
564
|
+
origin: resolveDocsMetadataBaseUrl(config) || getOriginFromRequest(request),
|
|
565
|
+
sitemap: config.sitemap,
|
|
566
|
+
okf: config.agent?.okf
|
|
567
|
+
});
|
|
568
|
+
if (markdownResponse) return markdownResponse;
|
|
569
|
+
}
|
|
570
|
+
const version = (requestUrl ? resolveApiReferenceVersionFromPathname(config.apiReference, requestUrl.pathname) : void 0) ?? resolveApiReferenceVersion(apiReference);
|
|
571
|
+
if (resolveApiReferenceRenderer(config.apiReference, "next") === "farming-labs") {
|
|
572
|
+
const html = await buildApiReferenceHtmlDocumentAsync(config, {
|
|
573
|
+
framework: "next",
|
|
574
|
+
rootDir: process.cwd(),
|
|
575
|
+
baseUrl: getOriginFromRequest(request),
|
|
576
|
+
version: version?.id
|
|
577
|
+
});
|
|
578
|
+
return new Response(html, { headers: { "Content-Type": "text/html; charset=utf-8" } });
|
|
579
|
+
}
|
|
555
580
|
const document = await buildApiReferenceOpenApiDocumentAsync(config, {
|
|
556
581
|
framework: "next",
|
|
557
582
|
rootDir: process.cwd(),
|
|
558
|
-
baseUrl: getOriginFromRequest(request)
|
|
583
|
+
baseUrl: getOriginFromRequest(request),
|
|
584
|
+
version: version?.id
|
|
559
585
|
});
|
|
586
|
+
const basePath = `/${apiReference.path}${version ? `/${encodeURIComponent(version.id)}` : ""}`;
|
|
560
587
|
return ApiReference({
|
|
561
|
-
pageTitle: buildApiReferencePageTitle(config, "API Reference"),
|
|
562
|
-
title: "API Reference",
|
|
588
|
+
pageTitle: buildApiReferencePageTitle(config, version ? `API Reference – ${version.label}` : "API Reference"),
|
|
589
|
+
title: version ? `API Reference – ${version.label}` : "API Reference",
|
|
563
590
|
content: document,
|
|
564
591
|
theme: "deepSpace",
|
|
565
592
|
layout: "modern",
|
|
@@ -567,7 +594,7 @@ function createNextApiReference(config) {
|
|
|
567
594
|
forceDarkModeState: getForcedMode(config),
|
|
568
595
|
hideDarkModeToggle: isThemeToggleHidden(config),
|
|
569
596
|
customCss: buildApiReferenceScalarCss(config),
|
|
570
|
-
pathRouting: { basePath
|
|
597
|
+
pathRouting: { basePath },
|
|
571
598
|
showSidebar: true,
|
|
572
599
|
defaultOpenFirstTag: true,
|
|
573
600
|
tagsSorter: "alpha",
|
|
@@ -591,8 +618,10 @@ function getOpenApiInfo(document) {
|
|
|
591
618
|
function createNextApiReferencePage(config) {
|
|
592
619
|
return async function NextApiReferencePage(props) {
|
|
593
620
|
const [{ createAPIPage }, { DocsDescription, DocsPage, DocsTitle }] = await Promise.all([import("fumadocs-openapi/ui"), import("fumadocs-ui/layouts/notebook/page")]);
|
|
594
|
-
const { info, pages, server, source } = await getNextApiReferenceSourceState(config);
|
|
595
621
|
const slug = (props?.params ? await props.params : void 0)?.slug ?? [];
|
|
622
|
+
const version = resolveApiReferenceVersion(resolveApiReferenceConfig(config.apiReference), slug[0]);
|
|
623
|
+
const pageSlug = version ? slug.slice(1) : slug;
|
|
624
|
+
const { info, pages, server, source } = await getNextApiReferenceSourceState(config, version?.id);
|
|
596
625
|
if (pages.length === 0) return /* @__PURE__ */ jsxs(DocsPage, {
|
|
597
626
|
full: true,
|
|
598
627
|
children: [
|
|
@@ -607,10 +636,10 @@ function createNextApiReferencePage(config) {
|
|
|
607
636
|
})
|
|
608
637
|
]
|
|
609
638
|
});
|
|
610
|
-
const page =
|
|
639
|
+
const page = pageSlug.length === 0 ? pages[0] : source.getPage(pageSlug);
|
|
611
640
|
if (!page || typeof page.data?.getAPIPageProps !== "function") notFound();
|
|
612
641
|
const APIPage = createAPIPage(server, { content: { renderOperationLayout: renderApiReferenceOperationLayout } });
|
|
613
|
-
const currentPageIndex =
|
|
642
|
+
const currentPageIndex = pageSlug.length === 0 ? 0 : pages.findIndex((entry) => entry.url === page.url);
|
|
614
643
|
const previousPage = currentPageIndex > 0 ? pages[currentPageIndex - 1] : void 0;
|
|
615
644
|
const nextPage = currentPageIndex >= 0 && currentPageIndex < pages.length - 1 ? pages[currentPageIndex + 1] : void 0;
|
|
616
645
|
return /* @__PURE__ */ jsxs(DocsPage, {
|
|
@@ -681,10 +710,12 @@ function createNextApiReferencePage(config) {
|
|
|
681
710
|
function createNextApiReferenceLayout(config) {
|
|
682
711
|
return async function NextApiReferenceLayout(props) {
|
|
683
712
|
const { DocsLayout } = await import("fumadocs-ui/layouts/notebook");
|
|
684
|
-
const
|
|
713
|
+
const resolvedParams = props.params ? await props.params : void 0;
|
|
714
|
+
const version = resolveApiReferenceVersion(resolveApiReferenceConfig(config.apiReference), resolvedParams?.slug?.[0]);
|
|
715
|
+
const { apiReference, primaryServerUrl, source } = await getNextApiReferenceSourceState(config, version?.id);
|
|
685
716
|
const sidebarTree = flattenApiReferencePageTreeForSidebar(source.getPageTree());
|
|
686
717
|
const docsUrl = getDocsUrl(config);
|
|
687
|
-
const apiUrl = `/${apiReference.path}`;
|
|
718
|
+
const apiUrl = `/${apiReference.path}${version ? `/${encodeURIComponent(version.id)}` : ""}`;
|
|
688
719
|
const themeSwitch = resolveApiReferenceThemeSwitch(config.themeToggle);
|
|
689
720
|
const themeStyle = resolveApiReferenceThemeStyle(config);
|
|
690
721
|
const banner = mergeBanner(getExistingSidebarBanner(config), /* @__PURE__ */ jsx(ApiReferenceSwitcher, {
|
|
@@ -714,14 +745,16 @@ function createNextApiReferenceLayout(config) {
|
|
|
714
745
|
});
|
|
715
746
|
};
|
|
716
747
|
}
|
|
717
|
-
async function getNextApiReferenceSourceState(config) {
|
|
748
|
+
async function getNextApiReferenceSourceState(config, versionId) {
|
|
718
749
|
const apiReference = resolveApiReferenceConfig(config.apiReference);
|
|
750
|
+
const version = resolveApiReferenceVersion(apiReference, versionId);
|
|
719
751
|
const [{ createOpenAPI, openapiPlugin, openapiSource }, { loader }] = await Promise.all([import("fumadocs-openapi/server"), import("fumadocs-core/source")]);
|
|
720
752
|
const baseUrl = await getOriginFromNextHeaders();
|
|
721
753
|
const document = await buildApiReferenceOpenApiDocumentAsync(config, {
|
|
722
754
|
framework: "next",
|
|
723
755
|
rootDir: process.cwd(),
|
|
724
|
-
baseUrl
|
|
756
|
+
baseUrl,
|
|
757
|
+
version: version?.id
|
|
725
758
|
});
|
|
726
759
|
const server = createOpenAPI({ input: async () => ({ main: document }) });
|
|
727
760
|
const info = getOpenApiInfo(document);
|
|
@@ -734,7 +767,7 @@ async function getNextApiReferenceSourceState(config) {
|
|
|
734
767
|
return slugifyApiReferencePageName(typeof operation?.summary === "string" && operation.summary.trim() ? operation.summary : typeof operation?.operationId === "string" && operation.operationId.trim() ? operation.operationId : `${output.item.method} ${output.item.path}`);
|
|
735
768
|
}
|
|
736
769
|
}), {
|
|
737
|
-
baseUrl: `/${apiReference.path}`,
|
|
770
|
+
baseUrl: `/${apiReference.path}${version ? `/${encodeURIComponent(version.id)}` : ""}`,
|
|
738
771
|
plugins: [openapiPlugin()]
|
|
739
772
|
});
|
|
740
773
|
return {
|
package/dist/api.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
3
|
import { createDocsAPI as createDocsAPI$1, createDocsMCPAPI as createDocsMCPAPI$1 } from "@farming-labs/theme/api";
|
|
4
|
-
import { bundledAgentSkills } from "@farming-labs/docs/agent-skills-bundle";
|
|
4
|
+
import { bundledAgentSkills, bundledRootDocuments } from "@farming-labs/docs/agent-skills-bundle";
|
|
5
5
|
import { createDocsCloudRouteHandler } from "@farming-labs/docs/cloud/server";
|
|
6
6
|
|
|
7
7
|
//#region src/api.ts
|
|
@@ -117,7 +117,8 @@ function createDocsAPI(options = {}, cloudIntegration) {
|
|
|
117
117
|
const handlers = createDocsAPI$1({
|
|
118
118
|
...options,
|
|
119
119
|
...rootDir ? { rootDir } : {},
|
|
120
|
-
_preloadedAgentSkills: options._preloadedAgentSkills ?? bundledAgentSkills
|
|
120
|
+
_preloadedAgentSkills: options._preloadedAgentSkills ?? bundledAgentSkills,
|
|
121
|
+
_preloadedRootDocuments: options._preloadedRootDocuments ?? bundledRootDocuments
|
|
121
122
|
});
|
|
122
123
|
const integration = resolveDocsCloudIntegration(cloudIntegration);
|
|
123
124
|
if (!integration) return handlers;
|
|
@@ -146,7 +147,8 @@ function createDocsMCPAPI(options = {}) {
|
|
|
146
147
|
return createDocsMCPAPI$1({
|
|
147
148
|
...options,
|
|
148
149
|
...rootDir ? { rootDir } : {},
|
|
149
|
-
_preloadedAgentSkills: options._preloadedAgentSkills ?? bundledAgentSkills
|
|
150
|
+
_preloadedAgentSkills: options._preloadedAgentSkills ?? bundledAgentSkills,
|
|
151
|
+
_preloadedRootDocuments: options._preloadedRootDocuments ?? bundledRootDocuments
|
|
150
152
|
});
|
|
151
153
|
}
|
|
152
154
|
|
package/dist/config.mjs
CHANGED
|
@@ -669,11 +669,33 @@ function readAgentSkillPaths(root, configPath) {
|
|
|
669
669
|
if (!configured) throw new Error("withDocs could not statically bundle agent.skills. Use a literal path, a literal path array, or { paths: [...] } so configured skills are included in production.");
|
|
670
670
|
return configured;
|
|
671
671
|
}
|
|
672
|
+
const ROOT_DOCUMENT_FILES = [
|
|
673
|
+
"skill.md",
|
|
674
|
+
"AGENTS.md",
|
|
675
|
+
"AGENT.md"
|
|
676
|
+
];
|
|
677
|
+
/**
|
|
678
|
+
* Snapshot the project-root agent documents into the skills bundle. Tracing
|
|
679
|
+
* them by bare filename is not an option: Turbopack matches such globs at any
|
|
680
|
+
* depth, which drags `node_modules/next/AGENTS.md` into the trace through the
|
|
681
|
+
* pnpm workspace symlink and breaks Vercel output materialization.
|
|
682
|
+
*/
|
|
683
|
+
function readRootDocumentsSnapshot(root) {
|
|
684
|
+
const documents = {};
|
|
685
|
+
for (const fileName of ROOT_DOCUMENT_FILES) {
|
|
686
|
+
const filePath = join(root, fileName);
|
|
687
|
+
if (!existsSync(filePath)) continue;
|
|
688
|
+
try {
|
|
689
|
+
documents[fileName] = readFileSync(filePath, "utf8");
|
|
690
|
+
} catch {}
|
|
691
|
+
}
|
|
692
|
+
return Object.keys(documents).length > 0 ? documents : void 0;
|
|
693
|
+
}
|
|
672
694
|
function writeAgentSkillsBundle(root, configuredSkills) {
|
|
673
695
|
const bundlePath = join(root, AGENT_SKILLS_BUNDLE_PATH);
|
|
674
|
-
const source = `${GENERATED_BANNER}${renderDocsAgentSkillsBundle(resolveConfiguredAgentSkillsSync(configuredSkills, { rootDir: root }))}`;
|
|
675
|
-
|
|
676
|
-
if (!existsSync(bundlePath) || readFileSync(bundlePath, "utf8") !== source)
|
|
696
|
+
const source = `${GENERATED_BANNER}${renderDocsAgentSkillsBundle(resolveConfiguredAgentSkillsSync(configuredSkills, { rootDir: root }), readRootDocumentsSnapshot(root))}`;
|
|
697
|
+
makeGeneratedDir(dirname(bundlePath));
|
|
698
|
+
if (!existsSync(bundlePath) || readFileSync(bundlePath, "utf8") !== source) writeGeneratedFile(bundlePath, source);
|
|
677
699
|
return bundlePath;
|
|
678
700
|
}
|
|
679
701
|
/** Read the OG endpoint from docs.config.ts[x] (returns undefined if not set). */
|
|
@@ -695,32 +717,32 @@ function readApiReferenceConfig(root) {
|
|
|
695
717
|
if (content.match(/apiReference\s*:\s*false/)) return {
|
|
696
718
|
enabled: false,
|
|
697
719
|
path: "api-reference",
|
|
698
|
-
renderer: "
|
|
720
|
+
renderer: "farming-labs",
|
|
699
721
|
routeRoot: "api"
|
|
700
722
|
};
|
|
701
723
|
if (content.match(/apiReference\s*:\s*true/)) return {
|
|
702
724
|
enabled: true,
|
|
703
725
|
path: "api-reference",
|
|
704
|
-
renderer: "
|
|
726
|
+
renderer: "farming-labs",
|
|
705
727
|
routeRoot: "api"
|
|
706
728
|
};
|
|
707
729
|
const block = extractObjectLiteral(content, "apiReference");
|
|
708
730
|
if (!block) continue;
|
|
709
731
|
const enabledMatch = block.match(/enabled\s*:\s*(true|false)/);
|
|
710
732
|
const pathMatch = block.match(/path\s*:\s*["']([^"']+)["']/);
|
|
711
|
-
const rendererMatch = block.match(/renderer\s*:\s*["'](fumadocs|scalar)["']/);
|
|
733
|
+
const rendererMatch = block.match(/renderer\s*:\s*["'](farming-labs|fumadocs|scalar)["']/);
|
|
712
734
|
const routeRootMatch = block.match(/routeRoot\s*:\s*["']([^"']+)["']/);
|
|
713
735
|
return {
|
|
714
736
|
enabled: enabledMatch ? enabledMatch[1] !== "false" : true,
|
|
715
737
|
path: pathMatch?.[1]?.replace(/^\/+|\/+$/g, "") || "api-reference",
|
|
716
|
-
renderer: rendererMatch?.[1] ?? "
|
|
738
|
+
renderer: rendererMatch?.[1] ?? "farming-labs",
|
|
717
739
|
routeRoot: routeRootMatch?.[1]?.replace(/^\/+|\/+$/g, "") || "api"
|
|
718
740
|
};
|
|
719
741
|
} catch {
|
|
720
742
|
return {
|
|
721
743
|
enabled: false,
|
|
722
744
|
path: "api-reference",
|
|
723
|
-
renderer: "
|
|
745
|
+
renderer: "farming-labs",
|
|
724
746
|
routeRoot: "api"
|
|
725
747
|
};
|
|
726
748
|
}
|
|
@@ -728,7 +750,7 @@ function readApiReferenceConfig(root) {
|
|
|
728
750
|
return {
|
|
729
751
|
enabled: false,
|
|
730
752
|
path: "api-reference",
|
|
731
|
-
renderer: "
|
|
753
|
+
renderer: "farming-labs",
|
|
732
754
|
routeRoot: "api"
|
|
733
755
|
};
|
|
734
756
|
}
|
|
@@ -1155,7 +1177,29 @@ function resolveManagedChangelogSourceLayoutPath(root, appDir, entry, changelogC
|
|
|
1155
1177
|
return join(contentRoot, "layout.tsx");
|
|
1156
1178
|
}
|
|
1157
1179
|
function removeManagedFile(filePath) {
|
|
1158
|
-
if (isManagedGeneratedFile(filePath)) rmSync(filePath, { force: true });
|
|
1180
|
+
if (isManagedGeneratedFile(filePath)) withReadOnlyFsGuard(filePath, () => rmSync(filePath, { force: true }));
|
|
1181
|
+
}
|
|
1182
|
+
const READ_ONLY_FS_CODES = new Set([
|
|
1183
|
+
"EROFS",
|
|
1184
|
+
"EACCES",
|
|
1185
|
+
"EPERM"
|
|
1186
|
+
]);
|
|
1187
|
+
/** Generation must not take down config evaluation on read-only filesystems; the build already shipped these files. */
|
|
1188
|
+
function withReadOnlyFsGuard(target, mutate) {
|
|
1189
|
+
try {
|
|
1190
|
+
return mutate();
|
|
1191
|
+
} catch (error) {
|
|
1192
|
+
const code = error?.code;
|
|
1193
|
+
if (!code || !READ_ONLY_FS_CODES.has(code)) throw error;
|
|
1194
|
+
console.warn(`[docs] Skipped generating ${target} (${code}): filesystem is read-only; using existing files.`);
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
function makeGeneratedDir(dirPath) {
|
|
1199
|
+
withReadOnlyFsGuard(dirPath, () => mkdirSync(dirPath, { recursive: true }));
|
|
1200
|
+
}
|
|
1201
|
+
function writeGeneratedFile(filePath, content) {
|
|
1202
|
+
withReadOnlyFsGuard(filePath, () => writeFileSync(filePath, content, "utf8"));
|
|
1159
1203
|
}
|
|
1160
1204
|
function resolveMcpConfig(mcp) {
|
|
1161
1205
|
if (mcp === false) return {
|
|
@@ -1557,6 +1601,72 @@ function buildDocsMarkdownRewrites(entry, docsPath) {
|
|
|
1557
1601
|
}
|
|
1558
1602
|
];
|
|
1559
1603
|
}
|
|
1604
|
+
function buildApiReferenceMarkdownRewrites(apiReference) {
|
|
1605
|
+
if (!apiReference.enabled) return [];
|
|
1606
|
+
const basePath = `/${apiReference.path}`;
|
|
1607
|
+
const markdownAcceptHeader = {
|
|
1608
|
+
type: "header",
|
|
1609
|
+
key: "accept",
|
|
1610
|
+
value: MARKDOWN_ACCEPT_HEADER_VALUE
|
|
1611
|
+
};
|
|
1612
|
+
const markdownSignatureAgentHeader = {
|
|
1613
|
+
type: "header",
|
|
1614
|
+
key: "signature-agent",
|
|
1615
|
+
value: ".+"
|
|
1616
|
+
};
|
|
1617
|
+
const markdownAgentUserAgentHeader = {
|
|
1618
|
+
type: "header",
|
|
1619
|
+
key: "user-agent",
|
|
1620
|
+
value: DOCS_AI_AGENT_USER_AGENT_HEADER_PATTERN
|
|
1621
|
+
};
|
|
1622
|
+
const markdownBotLikeUserAgentHeader = {
|
|
1623
|
+
type: "header",
|
|
1624
|
+
key: "user-agent",
|
|
1625
|
+
value: DOCS_BOT_LIKE_USER_AGENT_HEADER_PATTERN
|
|
1626
|
+
};
|
|
1627
|
+
const markdownTraditionalBotUserAgentHeader = {
|
|
1628
|
+
type: "header",
|
|
1629
|
+
key: "user-agent",
|
|
1630
|
+
value: DOCS_TRADITIONAL_BOT_USER_AGENT_HEADER_PATTERN
|
|
1631
|
+
};
|
|
1632
|
+
const markdownSecFetchModeHeader = {
|
|
1633
|
+
type: "header",
|
|
1634
|
+
key: "sec-fetch-mode"
|
|
1635
|
+
};
|
|
1636
|
+
return [{
|
|
1637
|
+
source: `${basePath}/operations/:operation`,
|
|
1638
|
+
path: `${apiReference.path}/operations/:operation`
|
|
1639
|
+
}, {
|
|
1640
|
+
source: `${basePath}/:version/operations/:operation`,
|
|
1641
|
+
path: `${apiReference.path}/:version/operations/:operation`
|
|
1642
|
+
}].flatMap((route) => [
|
|
1643
|
+
{
|
|
1644
|
+
source: `${route.source}.md`,
|
|
1645
|
+
destination: `/api/docs?format=markdown&path=${route.path}`
|
|
1646
|
+
},
|
|
1647
|
+
{
|
|
1648
|
+
source: route.source,
|
|
1649
|
+
has: [markdownAcceptHeader],
|
|
1650
|
+
destination: `/api/docs?format=markdown&path=${route.path}`
|
|
1651
|
+
},
|
|
1652
|
+
{
|
|
1653
|
+
source: route.source,
|
|
1654
|
+
has: [markdownSignatureAgentHeader],
|
|
1655
|
+
destination: `/api/docs?format=markdown&path=${route.path}`
|
|
1656
|
+
},
|
|
1657
|
+
{
|
|
1658
|
+
source: route.source,
|
|
1659
|
+
has: [markdownAgentUserAgentHeader],
|
|
1660
|
+
destination: `/api/docs?format=markdown&path=${route.path}`
|
|
1661
|
+
},
|
|
1662
|
+
{
|
|
1663
|
+
source: route.source,
|
|
1664
|
+
has: [markdownBotLikeUserAgentHeader],
|
|
1665
|
+
missing: [markdownTraditionalBotUserAgentHeader, markdownSecFetchModeHeader],
|
|
1666
|
+
destination: `/api/docs?format=markdown&path=${route.path}`
|
|
1667
|
+
}
|
|
1668
|
+
]);
|
|
1669
|
+
}
|
|
1560
1670
|
function buildAgentSpecRewrites() {
|
|
1561
1671
|
return [
|
|
1562
1672
|
{
|
|
@@ -1863,7 +1973,7 @@ function buildHiddenFolderRedirects(docsDir, docsPath) {
|
|
|
1863
1973
|
scan(docsDir, []);
|
|
1864
1974
|
return dedupeRedirects(redirects);
|
|
1865
1975
|
}
|
|
1866
|
-
function mergeDocsMarkdownRewrites(entry, docsPath, mcp, sitemap, agentFeedback, robots, result) {
|
|
1976
|
+
function mergeDocsMarkdownRewrites(entry, docsPath, apiReference, mcp, sitemap, agentFeedback, robots, result) {
|
|
1867
1977
|
const autoBeforeFilesRewrites = [
|
|
1868
1978
|
...buildAgentSpecRewrites(),
|
|
1869
1979
|
...buildStandardsDiscoveryRewrites(),
|
|
@@ -1873,6 +1983,7 @@ function mergeDocsMarkdownRewrites(entry, docsPath, mcp, sitemap, agentFeedback,
|
|
|
1873
1983
|
...buildSitemapRewrites(sitemap),
|
|
1874
1984
|
...buildRobotsRewrites(robots),
|
|
1875
1985
|
...buildDocsMarkdownRewrites(entry, docsPath),
|
|
1986
|
+
...buildApiReferenceMarkdownRewrites(apiReference),
|
|
1876
1987
|
...buildDocsPathRewrites(entry, docsPath),
|
|
1877
1988
|
...buildAgentFeedbackRewrites(agentFeedback)
|
|
1878
1989
|
];
|
|
@@ -1910,36 +2021,36 @@ function withDocs(nextConfig = {}, docsConfig) {
|
|
|
1910
2021
|
const agentSkillsBundlePath = writeAgentSkillsBundle(root, docsConfig === void 0 || !Object.hasOwn(docsConfig, "agent") ? readAgentSkillPaths(root, docsConfigPath) : docsConfig.agent?.skills);
|
|
1911
2022
|
const agentFeedback = readAgentFeedbackConfig(root);
|
|
1912
2023
|
const docsConfigRelativeAlias = docsConfigPath.startsWith("./") || docsConfigPath.startsWith("../") ? docsConfigPath : `./${docsConfigPath}`;
|
|
1913
|
-
ensureDocsReviewWorkflow({
|
|
2024
|
+
withReadOnlyFsGuard(".github/workflows/docs-review.yml", () => ensureDocsReviewWorkflow({
|
|
1914
2025
|
rootDir: root,
|
|
1915
2026
|
configPath: docsConfigPath,
|
|
1916
2027
|
configContent: existsSync(docsConfigAbsolutePath) ? readFileSync(docsConfigAbsolutePath, "utf-8") : void 0,
|
|
1917
2028
|
log: process.env.NODE_ENV === "test" ? void 0 : (message) => console.log(message)
|
|
1918
|
-
});
|
|
1919
|
-
if (!hasFile(root, "mdx-components"))
|
|
2029
|
+
}));
|
|
2030
|
+
if (!hasFile(root, "mdx-components")) writeGeneratedFile(join(root, "mdx-components.tsx"), MDX_COMPONENTS_TEMPLATE);
|
|
1920
2031
|
const entry = readDocsEntry(root);
|
|
1921
2032
|
const docsPath = normalizeDocsPath(readDocsPath(root), entry);
|
|
1922
2033
|
const configuredContentDir = readDocsContentDir(root);
|
|
1923
2034
|
const appDir = getNextAppDir(root);
|
|
1924
2035
|
const docsContentDir = configuredContentDir ?? join(appDir, entry);
|
|
1925
2036
|
const layoutDir = join(root, appDir, entry);
|
|
1926
|
-
if (!existsSync(layoutDir))
|
|
2037
|
+
if (!existsSync(layoutDir)) makeGeneratedDir(layoutDir);
|
|
1927
2038
|
const docsLayoutPath = join(layoutDir, "layout.tsx");
|
|
1928
|
-
if (!hasFile(layoutDir, "layout") || isManagedGeneratedFile(docsLayoutPath))
|
|
2039
|
+
if (!hasFile(layoutDir, "layout") || isManagedGeneratedFile(docsLayoutPath)) writeGeneratedFile(join(layoutDir, "layout.tsx"), DOCS_LAYOUT_TEMPLATE);
|
|
1929
2040
|
const isStaticExport = nextConfig.output === "export";
|
|
1930
2041
|
const docsApiRouteDir = join(root, appDir, "api", "docs");
|
|
1931
2042
|
const existingDocsApiRoutePath = FILE_EXTS.map((ext) => join(docsApiRouteDir, `route.${ext}`)).find((filePath) => existsSync(filePath));
|
|
1932
2043
|
const docsApiRoutePath = existingDocsApiRoutePath ?? join(docsApiRouteDir, "route.ts");
|
|
1933
2044
|
if (!isStaticExport && (!existingDocsApiRoutePath || isManagedGeneratedFile(existingDocsApiRoutePath))) {
|
|
1934
|
-
|
|
1935
|
-
|
|
2045
|
+
makeGeneratedDir(docsApiRouteDir);
|
|
2046
|
+
writeGeneratedFile(docsApiRoutePath, DOCS_API_ROUTE_TEMPLATE);
|
|
1936
2047
|
}
|
|
1937
2048
|
const sitemap = readSitemapConfig(root);
|
|
1938
2049
|
const robots = readRobotsConfig(root);
|
|
1939
2050
|
const docsMcpRouteDir = join(root, appDir, "api", "docs", "mcp");
|
|
1940
2051
|
if (mcp.enabled && mcp.route === DEFAULT_MCP_ROUTE && !isStaticExport && !hasFile(docsMcpRouteDir, "route")) {
|
|
1941
|
-
|
|
1942
|
-
|
|
2052
|
+
makeGeneratedDir(docsMcpRouteDir);
|
|
2053
|
+
writeGeneratedFile(join(docsMcpRouteDir, "route.ts"), DOCS_MCP_ROUTE_TEMPLATE);
|
|
1943
2054
|
}
|
|
1944
2055
|
const apiReference = readApiReferenceConfig(root);
|
|
1945
2056
|
if (apiReference.enabled && !isStaticExport) {
|
|
@@ -1954,19 +2065,19 @@ function withDocs(nextConfig = {}, docsConfig) {
|
|
|
1954
2065
|
removeManagedFile(apiReferenceRoutePath);
|
|
1955
2066
|
removeManagedFile(legacyApiReferencePagePath);
|
|
1956
2067
|
if (!hasFile(apiReferenceBaseDir, "layout") || isManagedGeneratedFile(apiReferenceLayoutPath)) {
|
|
1957
|
-
|
|
1958
|
-
|
|
2068
|
+
makeGeneratedDir(apiReferenceBaseDir);
|
|
2069
|
+
writeGeneratedFile(apiReferenceLayoutPath, API_REFERENCE_LAYOUT_TEMPLATE);
|
|
1959
2070
|
}
|
|
1960
2071
|
if (!hasFile(apiReferencePageDir, "page") || isManagedGeneratedFile(apiReferencePagePath)) {
|
|
1961
|
-
|
|
1962
|
-
|
|
2072
|
+
makeGeneratedDir(apiReferencePageDir);
|
|
2073
|
+
writeGeneratedFile(apiReferencePagePath, API_REFERENCE_PAGE_TEMPLATE);
|
|
1963
2074
|
}
|
|
1964
2075
|
} else {
|
|
1965
2076
|
removeManagedFile(apiReferenceLayoutPath);
|
|
1966
2077
|
removeManagedFile(apiReferencePagePath);
|
|
1967
2078
|
if (!hasFile(apiReferenceRouteDir, "route") || isManagedGeneratedFile(apiReferenceRoutePath)) {
|
|
1968
|
-
|
|
1969
|
-
|
|
2079
|
+
makeGeneratedDir(apiReferenceRouteDir);
|
|
2080
|
+
writeGeneratedFile(apiReferenceRoutePath, API_REFERENCE_ROUTE_TEMPLATE);
|
|
1970
2081
|
}
|
|
1971
2082
|
}
|
|
1972
2083
|
}
|
|
@@ -1987,22 +2098,22 @@ function withDocs(nextConfig = {}, docsConfig) {
|
|
|
1987
2098
|
removeManagedFile(join(legacyChangelogBaseDir, "page.tsx"));
|
|
1988
2099
|
removeManagedFile(join(legacyChangelogBaseDir, "__changelog.generated.tsx"));
|
|
1989
2100
|
}
|
|
1990
|
-
|
|
2101
|
+
makeGeneratedDir(changelogBaseDir);
|
|
1991
2102
|
removeManagedFile(join(changelogBaseDir, "__changelog.generated.tsx"));
|
|
1992
|
-
if (!hasFile(changelogBaseDir, "page") || isManagedGeneratedFile(changelogIndexPath))
|
|
2103
|
+
if (!hasFile(changelogBaseDir, "page") || isManagedGeneratedFile(changelogIndexPath)) writeGeneratedFile(changelogIndexPath, buildChangelogIndexPageSource(root, changelogIndexPath, entry, changelog.path, changelogEntries));
|
|
1993
2104
|
if (changelogUsesSourcePagesAsDetails) {
|
|
1994
2105
|
removeManagedFile(changelogEntryPath);
|
|
1995
2106
|
if (changelogSourceLayoutPath) removeManagedFile(changelogSourceLayoutPath);
|
|
1996
2107
|
} else {
|
|
1997
2108
|
if (!hasFile(changelogEntryDir, "page") || isManagedGeneratedFile(changelogEntryPath)) {
|
|
1998
|
-
|
|
1999
|
-
|
|
2109
|
+
makeGeneratedDir(changelogEntryDir);
|
|
2110
|
+
writeGeneratedFile(changelogEntryPath, buildChangelogEntryPageSource(root, changelogEntryPath, entry, changelog.path, changelogEntries));
|
|
2000
2111
|
}
|
|
2001
2112
|
if (changelogSourceLayoutPath) {
|
|
2002
2113
|
const changelogSourceLayoutDir = dirname(changelogSourceLayoutPath);
|
|
2003
2114
|
if (!hasFile(changelogSourceLayoutDir, "layout") || isManagedGeneratedFile(changelogSourceLayoutPath)) {
|
|
2004
|
-
|
|
2005
|
-
|
|
2115
|
+
makeGeneratedDir(changelogSourceLayoutDir);
|
|
2116
|
+
writeGeneratedFile(changelogSourceLayoutPath, CHANGELOG_SOURCE_LAYOUT_TEMPLATE);
|
|
2006
2117
|
}
|
|
2007
2118
|
}
|
|
2008
2119
|
}
|
|
@@ -2098,15 +2209,12 @@ function withDocs(nextConfig = {}, docsConfig) {
|
|
|
2098
2209
|
};
|
|
2099
2210
|
const existingTracingIncludes = nextConfig.outputFileTracingIncludes ?? {};
|
|
2100
2211
|
const docsTraceGlob = docsContentDir.replace(/\\/g, "/").replace(/^\.?\//, "") + "/**/*";
|
|
2101
|
-
const skillTraceFile = "skill.md";
|
|
2102
|
-
const agentsTraceFile = "AGENTS.md";
|
|
2103
|
-
const agentTraceFile = "AGENT.md";
|
|
2104
2212
|
const sitemapManifestTraceFile = DEFAULT_SITEMAP_MANIFEST_PATH;
|
|
2105
2213
|
const docsContentRoot = isAbsolute(docsContentDir) ? docsContentDir : join(root, docsContentDir);
|
|
2106
2214
|
if (!isStaticExport) {
|
|
2107
2215
|
const existingRewrites = nextConfig.rewrites;
|
|
2108
2216
|
nextConfig.rewrites = async () => {
|
|
2109
|
-
return mergeDocsMarkdownRewrites(entry, docsPath, mcp, sitemap, agentFeedback, robots, typeof existingRewrites === "function" ? await existingRewrites() : existingRewrites);
|
|
2217
|
+
return mergeDocsMarkdownRewrites(entry, docsPath, apiReference, mcp, sitemap, agentFeedback, robots, typeof existingRewrites === "function" ? await existingRewrites() : existingRewrites);
|
|
2110
2218
|
};
|
|
2111
2219
|
const autoRedirects = buildHiddenFolderRedirects(docsContentRoot, docsPath);
|
|
2112
2220
|
if (autoRedirects.length > 0) {
|
|
@@ -2121,16 +2229,9 @@ function withDocs(nextConfig = {}, docsConfig) {
|
|
|
2121
2229
|
"/api/docs": [...new Set([
|
|
2122
2230
|
...existingTracingIncludes["/api/docs"] ?? [],
|
|
2123
2231
|
docsTraceGlob,
|
|
2124
|
-
skillTraceFile,
|
|
2125
|
-
agentsTraceFile,
|
|
2126
|
-
agentTraceFile,
|
|
2127
2232
|
sitemapManifestTraceFile
|
|
2128
2233
|
])],
|
|
2129
|
-
[DEFAULT_MCP_ROUTE]: [...new Set([
|
|
2130
|
-
...existingTracingIncludes[DEFAULT_MCP_ROUTE] ?? [],
|
|
2131
|
-
docsTraceGlob,
|
|
2132
|
-
skillTraceFile
|
|
2133
|
-
])]
|
|
2234
|
+
[DEFAULT_MCP_ROUTE]: [...new Set([...existingTracingIncludes[DEFAULT_MCP_ROUTE] ?? [], docsTraceGlob])]
|
|
2134
2235
|
};
|
|
2135
2236
|
return withMDX(nextConfig);
|
|
2136
2237
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/next",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.116",
|
|
4
4
|
"description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -109,8 +109,8 @@
|
|
|
109
109
|
"tsdown": "^0.20.3",
|
|
110
110
|
"typescript": "^5.9.3",
|
|
111
111
|
"vitest": "^4.1.8",
|
|
112
|
-
"@farming-labs/docs": "0.2.
|
|
113
|
-
"@farming-labs/theme": "0.2.
|
|
112
|
+
"@farming-labs/docs": "0.2.116",
|
|
113
|
+
"@farming-labs/theme": "0.2.116"
|
|
114
114
|
},
|
|
115
115
|
"peerDependencies": {
|
|
116
116
|
"@farming-labs/docs": ">=0.2.73",
|