@farming-labs/next 0.1.3 → 0.1.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/dist/api.d.mts +23 -2
- package/dist/api.mjs +65 -2
- package/dist/config.mjs +57 -1
- package/package.json +3 -3
package/dist/api.d.mts
CHANGED
|
@@ -1,2 +1,23 @@
|
|
|
1
|
-
import { createDocsAPI, createDocsMCPAPI } from "@farming-labs/theme/api";
|
|
2
|
-
|
|
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
CHANGED
|
@@ -1,3 +1,66 @@
|
|
|
1
|
-
import
|
|
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";
|
|
2
4
|
|
|
3
|
-
|
|
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") {
|
|
20
|
+
const serverParent = path.dirname(parent);
|
|
21
|
+
if (path.basename(serverParent) === "dev") return path.dirname(path.dirname(serverParent));
|
|
22
|
+
return path.dirname(serverParent);
|
|
23
|
+
}
|
|
24
|
+
return parent;
|
|
25
|
+
}
|
|
26
|
+
if (parent === current) return process.cwd();
|
|
27
|
+
current = parent;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function isNextRouteFile(filePath) {
|
|
31
|
+
const normalized = filePath.replaceAll("\\", "/");
|
|
32
|
+
return /\/(?:src\/)?app\/api\/.+\/route\.[cm]?[jt]sx?$/.test(normalized);
|
|
33
|
+
}
|
|
34
|
+
function inferNextProjectRootFromCaller() {
|
|
35
|
+
const previousPrepareStackTrace = Error.prepareStackTrace;
|
|
36
|
+
try {
|
|
37
|
+
Error.prepareStackTrace = (_error, stack) => stack;
|
|
38
|
+
const error = /* @__PURE__ */ new Error();
|
|
39
|
+
Error.captureStackTrace?.(error, inferNextProjectRootFromCaller);
|
|
40
|
+
const stack = error.stack;
|
|
41
|
+
for (const frame of stack ?? []) {
|
|
42
|
+
const fileName = frame.getFileName?.();
|
|
43
|
+
if (!fileName || !isNextRouteFile(fileName)) continue;
|
|
44
|
+
return resolveNextProjectRoot(pathToFileURL(fileName).href);
|
|
45
|
+
}
|
|
46
|
+
} catch {} finally {
|
|
47
|
+
Error.prepareStackTrace = previousPrepareStackTrace;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function createDocsAPI(options = {}) {
|
|
51
|
+
const rootDir = options.rootDir ?? inferNextProjectRootFromCaller();
|
|
52
|
+
return createDocsAPI$1(rootDir ? {
|
|
53
|
+
...options,
|
|
54
|
+
rootDir
|
|
55
|
+
} : options);
|
|
56
|
+
}
|
|
57
|
+
function createDocsMCPAPI(options = {}) {
|
|
58
|
+
const rootDir = options.rootDir ?? inferNextProjectRootFromCaller();
|
|
59
|
+
return createDocsMCPAPI$1(rootDir ? {
|
|
60
|
+
...options,
|
|
61
|
+
rootDir
|
|
62
|
+
} : options);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
//#endregion
|
|
66
|
+
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
|
|
@@ -70,6 +70,7 @@ 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,
|
|
74
75
|
search: docsConfig.search,
|
|
75
76
|
ai: docsConfig.ai,
|
|
@@ -109,6 +110,39 @@ const FILE_EXTS = [
|
|
|
109
110
|
"js"
|
|
110
111
|
];
|
|
111
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
|
+
}
|
|
112
146
|
function hasFile(root, baseName) {
|
|
113
147
|
return FILE_EXTS.some((ext) => existsSync(join(root, `${baseName}.${ext}`)));
|
|
114
148
|
}
|
|
@@ -131,6 +165,16 @@ function readDocsEntry(root) {
|
|
|
131
165
|
}
|
|
132
166
|
return "docs";
|
|
133
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
|
+
}
|
|
134
178
|
function readDocsConfigPath(root) {
|
|
135
179
|
for (const ext of FILE_EXTS) {
|
|
136
180
|
const relativePath = `docs.config.${ext}`;
|
|
@@ -245,12 +289,15 @@ function normalizeRoutePath(route) {
|
|
|
245
289
|
}
|
|
246
290
|
function withDocs(nextConfig = {}) {
|
|
247
291
|
const root = process.cwd();
|
|
292
|
+
const workspaceRoot = findDocsWorkspaceRoot(root);
|
|
248
293
|
const docsConfigPath = readDocsConfigPath(root);
|
|
249
294
|
const docsConfigAbsolutePath = join(root, docsConfigPath);
|
|
250
295
|
const docsConfigRelativeAlias = docsConfigPath.startsWith("./") || docsConfigPath.startsWith("../") ? docsConfigPath : `./${docsConfigPath}`;
|
|
251
296
|
if (!hasFile(root, "mdx-components")) writeFileSync(join(root, "mdx-components.tsx"), MDX_COMPONENTS_TEMPLATE);
|
|
252
297
|
const entry = readDocsEntry(root);
|
|
298
|
+
const configuredContentDir = readDocsContentDir(root);
|
|
253
299
|
const appDir = getNextAppDir(root);
|
|
300
|
+
const docsContentDir = configuredContentDir ?? join(appDir, entry);
|
|
254
301
|
const layoutDir = join(root, appDir, entry);
|
|
255
302
|
if (!existsSync(layoutDir)) mkdirSync(layoutDir, { recursive: true });
|
|
256
303
|
const docsLayoutPath = join(layoutDir, "layout.tsx");
|
|
@@ -305,7 +352,9 @@ function withDocs(nextConfig = {}) {
|
|
|
305
352
|
const existingResolveAlias = existingTurbopack.resolveAlias ?? {};
|
|
306
353
|
nextConfig.turbopack = {
|
|
307
354
|
...existingTurbopack,
|
|
355
|
+
...workspaceRoot && !existingTurbopack.root ? { root: workspaceRoot } : {},
|
|
308
356
|
resolveAlias: {
|
|
357
|
+
...workspaceRoot ? createDocsWorkspaceAliases() : {},
|
|
309
358
|
...existingResolveAlias,
|
|
310
359
|
[INTERNAL_DOCS_CONFIG_ALIAS]: docsConfigRelativeAlias
|
|
311
360
|
}
|
|
@@ -318,6 +367,13 @@ function withDocs(nextConfig = {}) {
|
|
|
318
367
|
resolvedConfig.resolve.alias[INTERNAL_DOCS_CONFIG_ALIAS] = docsConfigAbsolutePath;
|
|
319
368
|
return resolvedConfig;
|
|
320
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
|
+
};
|
|
321
377
|
return withMDX(nextConfig);
|
|
322
378
|
}
|
|
323
379
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/next",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"tsdown": "^0.20.3",
|
|
85
85
|
"typescript": "^5.9.3",
|
|
86
86
|
"vitest": "^3.2.4",
|
|
87
|
-
"@farming-labs/
|
|
88
|
-
"@farming-labs/
|
|
87
|
+
"@farming-labs/theme": "0.1.5",
|
|
88
|
+
"@farming-labs/docs": "0.1.5"
|
|
89
89
|
},
|
|
90
90
|
"peerDependencies": {
|
|
91
91
|
"@farming-labs/docs": ">=0.0.1",
|