@farming-labs/next 0.1.2 → 0.1.4
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.d.mts +23 -0
- package/dist/api.mjs +62 -0
- package/dist/config.mjs +62 -3
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +2 -1
- package/package.json +8 -3
package/dist/api.d.mts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createDocsAPI as createDocsAPI$1, createDocsMCPAPI as createDocsMCPAPI$1 } from "@farming-labs/theme/api";
|
|
2
|
+
|
|
3
|
+
//#region src/api.d.ts
|
|
4
|
+
type DocsAPIOptions = NonNullable<Parameters<typeof createDocsAPI$1>[0]>;
|
|
5
|
+
type DocsMCPAPIOptions = NonNullable<Parameters<typeof createDocsMCPAPI$1>[0]>;
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the app project root for a Next route module.
|
|
8
|
+
*
|
|
9
|
+
* This handles source routes (`app/...` or `src/app/...`) and built production
|
|
10
|
+
* output (`.next/server/app/...` or custom-dist-dir `/server/app/...`).
|
|
11
|
+
*/
|
|
12
|
+
declare function resolveNextProjectRoot(metaUrl: string): string;
|
|
13
|
+
declare function createDocsAPI(options?: DocsAPIOptions): {
|
|
14
|
+
GET(request: Request): Promise<Response>;
|
|
15
|
+
POST(request: Request): Promise<Response>;
|
|
16
|
+
};
|
|
17
|
+
declare function createDocsMCPAPI(options?: DocsMCPAPIOptions): {
|
|
18
|
+
GET(request: Request): Promise<Response>;
|
|
19
|
+
POST(request: Request): Promise<Response>;
|
|
20
|
+
DELETE(request: Request): Promise<Response>;
|
|
21
|
+
};
|
|
22
|
+
//#endregion
|
|
23
|
+
export { createDocsAPI, createDocsMCPAPI, resolveNextProjectRoot };
|
package/dist/api.mjs
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
|
+
import { createDocsAPI as createDocsAPI$1, createDocsMCPAPI as createDocsMCPAPI$1 } from "@farming-labs/theme/api";
|
|
4
|
+
|
|
5
|
+
//#region src/api.ts
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the app project root for a Next route module.
|
|
8
|
+
*
|
|
9
|
+
* This handles source routes (`app/...` or `src/app/...`) and built production
|
|
10
|
+
* output (`.next/server/app/...` or custom-dist-dir `/server/app/...`).
|
|
11
|
+
*/
|
|
12
|
+
function resolveNextProjectRoot(metaUrl) {
|
|
13
|
+
const filePath = fileURLToPath(metaUrl);
|
|
14
|
+
let current = path.dirname(filePath);
|
|
15
|
+
while (true) {
|
|
16
|
+
const parent = path.dirname(current);
|
|
17
|
+
if (path.basename(current) === "app") {
|
|
18
|
+
if (path.basename(parent) === "src") return path.dirname(parent);
|
|
19
|
+
if (path.basename(parent) === "server") return path.dirname(path.dirname(parent));
|
|
20
|
+
return parent;
|
|
21
|
+
}
|
|
22
|
+
if (parent === current) return process.cwd();
|
|
23
|
+
current = parent;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function isNextRouteFile(filePath) {
|
|
27
|
+
const normalized = filePath.replaceAll("\\", "/");
|
|
28
|
+
return /\/(?:src\/)?app\/api\/.+\/route\.[cm]?[jt]sx?$/.test(normalized);
|
|
29
|
+
}
|
|
30
|
+
function inferNextProjectRootFromCaller() {
|
|
31
|
+
const previousPrepareStackTrace = Error.prepareStackTrace;
|
|
32
|
+
try {
|
|
33
|
+
Error.prepareStackTrace = (_error, stack) => stack;
|
|
34
|
+
const error = /* @__PURE__ */ new Error();
|
|
35
|
+
Error.captureStackTrace?.(error, inferNextProjectRootFromCaller);
|
|
36
|
+
const stack = error.stack;
|
|
37
|
+
for (const frame of stack ?? []) {
|
|
38
|
+
const fileName = frame.getFileName?.();
|
|
39
|
+
if (!fileName || !isNextRouteFile(fileName)) continue;
|
|
40
|
+
return resolveNextProjectRoot(pathToFileURL(fileName).href);
|
|
41
|
+
}
|
|
42
|
+
} catch {} finally {
|
|
43
|
+
Error.prepareStackTrace = previousPrepareStackTrace;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function createDocsAPI(options = {}) {
|
|
47
|
+
const rootDir = options.rootDir ?? inferNextProjectRootFromCaller();
|
|
48
|
+
return createDocsAPI$1(rootDir ? {
|
|
49
|
+
...options,
|
|
50
|
+
rootDir
|
|
51
|
+
} : options);
|
|
52
|
+
}
|
|
53
|
+
function createDocsMCPAPI(options = {}) {
|
|
54
|
+
const rootDir = options.rootDir ?? inferNextProjectRootFromCaller();
|
|
55
|
+
return createDocsMCPAPI$1(rootDir ? {
|
|
56
|
+
...options,
|
|
57
|
+
rootDir
|
|
58
|
+
} : options);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
export { createDocsAPI, createDocsMCPAPI, resolveNextProjectRoot };
|
package/dist/config.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
3
|
import createMDX from "@next/mdx";
|
|
4
4
|
|
|
5
5
|
//#region src/config.ts
|
|
@@ -66,11 +66,14 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
|
|
66
66
|
const DOCS_API_ROUTE_TEMPLATE = `\
|
|
67
67
|
${GENERATED_BANNER}
|
|
68
68
|
import docsConfig from "@/docs.config";
|
|
69
|
-
import { createDocsAPI } from "@farming-labs/
|
|
69
|
+
import { createDocsAPI } from "@farming-labs/next/api";
|
|
70
70
|
|
|
71
71
|
export const { GET, POST } = createDocsAPI({
|
|
72
72
|
entry: docsConfig.entry,
|
|
73
|
+
contentDir: docsConfig.contentDir,
|
|
73
74
|
i18n: docsConfig.i18n,
|
|
75
|
+
search: docsConfig.search,
|
|
76
|
+
ai: docsConfig.ai,
|
|
74
77
|
});
|
|
75
78
|
|
|
76
79
|
export const revalidate = false;
|
|
@@ -78,13 +81,14 @@ export const revalidate = false;
|
|
|
78
81
|
const DOCS_MCP_ROUTE_TEMPLATE = `\
|
|
79
82
|
${GENERATED_BANNER}
|
|
80
83
|
import docsConfig from "@/docs.config";
|
|
81
|
-
import { createDocsMCPAPI } from "@farming-labs/
|
|
84
|
+
import { createDocsMCPAPI } from "@farming-labs/next/api";
|
|
82
85
|
|
|
83
86
|
export const { GET, POST, DELETE } = createDocsMCPAPI({
|
|
84
87
|
entry: docsConfig.entry,
|
|
85
88
|
contentDir: docsConfig.contentDir,
|
|
86
89
|
nav: docsConfig.nav,
|
|
87
90
|
ordering: docsConfig.ordering,
|
|
91
|
+
search: docsConfig.search,
|
|
88
92
|
mcp: docsConfig.mcp,
|
|
89
93
|
});
|
|
90
94
|
|
|
@@ -106,6 +110,39 @@ const FILE_EXTS = [
|
|
|
106
110
|
"js"
|
|
107
111
|
];
|
|
108
112
|
const INTERNAL_DOCS_CONFIG_ALIAS = "@farming-labs/next-internal-docs-config";
|
|
113
|
+
function isDocsWorkspaceRoot(root) {
|
|
114
|
+
return existsSync(join(root, "packages", "docs", "src", "index.ts")) && existsSync(join(root, "packages", "fumadocs", "src", "index.ts")) && existsSync(join(root, "packages", "next", "src", "config.ts"));
|
|
115
|
+
}
|
|
116
|
+
function findDocsWorkspaceRoot(start) {
|
|
117
|
+
let current = start;
|
|
118
|
+
while (true) {
|
|
119
|
+
if (isDocsWorkspaceRoot(current)) return current;
|
|
120
|
+
const parent = dirname(current);
|
|
121
|
+
if (parent === current) return void 0;
|
|
122
|
+
current = parent;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function createDocsWorkspaceAliases() {
|
|
126
|
+
return {
|
|
127
|
+
"@farming-labs/docs": "./packages/docs/src/index.ts",
|
|
128
|
+
"@farming-labs/docs/server": "./packages/docs/src/server.ts",
|
|
129
|
+
"@farming-labs/next": "./packages/next/src/index.ts",
|
|
130
|
+
"@farming-labs/next/api": "./packages/next/src/api.ts",
|
|
131
|
+
"@farming-labs/next/client-callbacks": "./packages/next/src/client-callbacks.tsx",
|
|
132
|
+
"@farming-labs/next/layout": "./packages/next/src/layout.tsx",
|
|
133
|
+
"@farming-labs/next/mdx-plugins/rehype-code": "./packages/next/src/mdx-plugins/rehype-code.ts",
|
|
134
|
+
"@farming-labs/next/mdx-plugins/rehype-toc": "./packages/next/src/mdx-plugins/rehype-toc.ts",
|
|
135
|
+
"@farming-labs/next/mdx-plugins/remark-heading": "./packages/next/src/mdx-plugins/remark-heading.ts",
|
|
136
|
+
"@farming-labs/next/mdx-plugins/remark-og": "./packages/next/src/mdx-plugins/remark-og.ts",
|
|
137
|
+
"@farming-labs/theme": "./packages/fumadocs/src/index.ts",
|
|
138
|
+
"@farming-labs/theme/api": "./packages/fumadocs/src/docs-api.ts",
|
|
139
|
+
"@farming-labs/theme/client-hooks": "./packages/fumadocs/src/docs-client-hooks.tsx",
|
|
140
|
+
"@farming-labs/theme/concrete": "./packages/fumadocs/src/concrete/index.ts",
|
|
141
|
+
"@farming-labs/theme/hardline": "./packages/fumadocs/src/hardline/index.ts",
|
|
142
|
+
"@farming-labs/theme/mdx": "./packages/fumadocs/src/mdx.ts",
|
|
143
|
+
"@farming-labs/theme/search": "./packages/fumadocs/src/search.ts"
|
|
144
|
+
};
|
|
145
|
+
}
|
|
109
146
|
function hasFile(root, baseName) {
|
|
110
147
|
return FILE_EXTS.some((ext) => existsSync(join(root, `${baseName}.${ext}`)));
|
|
111
148
|
}
|
|
@@ -128,6 +165,16 @@ function readDocsEntry(root) {
|
|
|
128
165
|
}
|
|
129
166
|
return "docs";
|
|
130
167
|
}
|
|
168
|
+
function readDocsContentDir(root) {
|
|
169
|
+
for (const ext of FILE_EXTS) {
|
|
170
|
+
const configPath = join(root, `docs.config.${ext}`);
|
|
171
|
+
if (!existsSync(configPath)) continue;
|
|
172
|
+
try {
|
|
173
|
+
const match = readFileSync(configPath, "utf-8").match(/contentDir\s*:\s*["']([^"']+)["']/);
|
|
174
|
+
if (match?.[1]) return match[1];
|
|
175
|
+
} catch {}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
131
178
|
function readDocsConfigPath(root) {
|
|
132
179
|
for (const ext of FILE_EXTS) {
|
|
133
180
|
const relativePath = `docs.config.${ext}`;
|
|
@@ -242,12 +289,15 @@ function normalizeRoutePath(route) {
|
|
|
242
289
|
}
|
|
243
290
|
function withDocs(nextConfig = {}) {
|
|
244
291
|
const root = process.cwd();
|
|
292
|
+
const workspaceRoot = findDocsWorkspaceRoot(root);
|
|
245
293
|
const docsConfigPath = readDocsConfigPath(root);
|
|
246
294
|
const docsConfigAbsolutePath = join(root, docsConfigPath);
|
|
247
295
|
const docsConfigRelativeAlias = docsConfigPath.startsWith("./") || docsConfigPath.startsWith("../") ? docsConfigPath : `./${docsConfigPath}`;
|
|
248
296
|
if (!hasFile(root, "mdx-components")) writeFileSync(join(root, "mdx-components.tsx"), MDX_COMPONENTS_TEMPLATE);
|
|
249
297
|
const entry = readDocsEntry(root);
|
|
298
|
+
const configuredContentDir = readDocsContentDir(root);
|
|
250
299
|
const appDir = getNextAppDir(root);
|
|
300
|
+
const docsContentDir = configuredContentDir ?? join(appDir, entry);
|
|
251
301
|
const layoutDir = join(root, appDir, entry);
|
|
252
302
|
if (!existsSync(layoutDir)) mkdirSync(layoutDir, { recursive: true });
|
|
253
303
|
const docsLayoutPath = join(layoutDir, "layout.tsx");
|
|
@@ -302,7 +352,9 @@ function withDocs(nextConfig = {}) {
|
|
|
302
352
|
const existingResolveAlias = existingTurbopack.resolveAlias ?? {};
|
|
303
353
|
nextConfig.turbopack = {
|
|
304
354
|
...existingTurbopack,
|
|
355
|
+
...workspaceRoot && !existingTurbopack.root ? { root: workspaceRoot } : {},
|
|
305
356
|
resolveAlias: {
|
|
357
|
+
...workspaceRoot ? createDocsWorkspaceAliases() : {},
|
|
306
358
|
...existingResolveAlias,
|
|
307
359
|
[INTERNAL_DOCS_CONFIG_ALIAS]: docsConfigRelativeAlias
|
|
308
360
|
}
|
|
@@ -315,6 +367,13 @@ function withDocs(nextConfig = {}) {
|
|
|
315
367
|
resolvedConfig.resolve.alias[INTERNAL_DOCS_CONFIG_ALIAS] = docsConfigAbsolutePath;
|
|
316
368
|
return resolvedConfig;
|
|
317
369
|
};
|
|
370
|
+
const existingTracingIncludes = nextConfig.outputFileTracingIncludes ?? {};
|
|
371
|
+
const docsTraceGlob = docsContentDir.replace(/\\/g, "/").replace(/^\.?\//, "") + "/**/*";
|
|
372
|
+
nextConfig.outputFileTracingIncludes = {
|
|
373
|
+
...existingTracingIncludes,
|
|
374
|
+
"/api/docs": [...new Set([...existingTracingIncludes["/api/docs"] ?? [], docsTraceGlob])],
|
|
375
|
+
"/api/docs/mcp": [...new Set([...existingTracingIncludes["/api/docs/mcp"] ?? [], docsTraceGlob])]
|
|
376
|
+
};
|
|
318
377
|
return withMDX(nextConfig);
|
|
319
378
|
}
|
|
320
379
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { buildNextOpenApiDocument, createNextApiReference, resolveApiReferenceConfig, withNextApiReferenceBanner } from "./api-reference.mjs";
|
|
2
|
+
import { createDocsAPI, createDocsMCPAPI } from "./api.mjs";
|
|
2
3
|
import { withDocs } from "./config.mjs";
|
|
3
|
-
export { buildNextOpenApiDocument, createNextApiReference, resolveApiReferenceConfig, withDocs, withNextApiReferenceBanner };
|
|
4
|
+
export { buildNextOpenApiDocument, createDocsAPI, createDocsMCPAPI, createNextApiReference, resolveApiReferenceConfig, withDocs, withNextApiReferenceBanner };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { withDocs } from "./config.mjs";
|
|
2
|
+
import { createDocsAPI, createDocsMCPAPI } from "./api.mjs";
|
|
2
3
|
import { buildNextOpenApiDocument, createNextApiReference, resolveApiReferenceConfig, withNextApiReferenceBanner } from "./api-reference.mjs";
|
|
3
4
|
|
|
4
|
-
export { buildNextOpenApiDocument, createNextApiReference, resolveApiReferenceConfig, withDocs, withNextApiReferenceBanner };
|
|
5
|
+
export { buildNextOpenApiDocument, createDocsAPI, createDocsMCPAPI, createNextApiReference, resolveApiReferenceConfig, withDocs, withNextApiReferenceBanner };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/next",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -27,6 +27,11 @@
|
|
|
27
27
|
"import": "./dist/api-reference.mjs",
|
|
28
28
|
"default": "./dist/api-reference.mjs"
|
|
29
29
|
},
|
|
30
|
+
"./api": {
|
|
31
|
+
"types": "./dist/api.d.mts",
|
|
32
|
+
"import": "./dist/api.mjs",
|
|
33
|
+
"default": "./dist/api.mjs"
|
|
34
|
+
},
|
|
30
35
|
"./client-callbacks": {
|
|
31
36
|
"types": "./dist/client-callbacks.d.mts",
|
|
32
37
|
"import": "./dist/client-callbacks.mjs",
|
|
@@ -79,8 +84,8 @@
|
|
|
79
84
|
"tsdown": "^0.20.3",
|
|
80
85
|
"typescript": "^5.9.3",
|
|
81
86
|
"vitest": "^3.2.4",
|
|
82
|
-
"@farming-labs/docs": "0.1.
|
|
83
|
-
"@farming-labs/theme": "0.1.
|
|
87
|
+
"@farming-labs/docs": "0.1.4",
|
|
88
|
+
"@farming-labs/theme": "0.1.4"
|
|
84
89
|
},
|
|
85
90
|
"peerDependencies": {
|
|
86
91
|
"@farming-labs/docs": ">=0.0.1",
|