@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 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/theme/api";
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/theme/api";
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.2",
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.2",
83
- "@farming-labs/theme": "0.1.2"
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",