@farming-labs/docs 0.1.1 → 0.1.2

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.
@@ -0,0 +1,93 @@
1
+ import "./api-reference-wh4_pwG8.mjs";
2
+ import { createFilesystemDocsMcpSource, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
3
+ import "./server.mjs";
4
+ import { existsSync, readFileSync } from "node:fs";
5
+ import { join, resolve } from "node:path";
6
+
7
+ //#region src/cli/mcp.ts
8
+ const FILE_EXTS = [
9
+ "tsx",
10
+ "ts",
11
+ "jsx",
12
+ "js"
13
+ ];
14
+ async function runMcp(options = {}) {
15
+ const rootDir = process.cwd();
16
+ const content = readFileSync(resolveDocsConfigPath(rootDir, options.configPath), "utf-8");
17
+ const entry = readStringProperty(content, "entry") ?? "docs";
18
+ const contentDir = readStringProperty(content, "contentDir") ?? entry;
19
+ const navTitle = readNavTitle(content);
20
+ const mcp = readMcpConfig(content);
21
+ await runDocsMcpStdio({
22
+ source: createFilesystemDocsMcpSource({
23
+ rootDir,
24
+ entry,
25
+ contentDir,
26
+ siteTitle: navTitle ?? "Documentation"
27
+ }),
28
+ mcp: resolveDocsMcpConfig(mcp ?? true, { defaultName: navTitle ?? "@farming-labs/docs" }),
29
+ defaultName: navTitle ?? "@farming-labs/docs"
30
+ });
31
+ }
32
+ function resolveDocsConfigPath(rootDir, explicitPath) {
33
+ if (explicitPath) {
34
+ const resolvedPath = resolve(rootDir, explicitPath);
35
+ if (!existsSync(resolvedPath)) throw new Error(`Could not find docs config at ${explicitPath}.`);
36
+ return resolvedPath;
37
+ }
38
+ for (const ext of FILE_EXTS) {
39
+ const configPath = join(rootDir, `docs.config.${ext}`);
40
+ if (existsSync(configPath)) return configPath;
41
+ }
42
+ throw new Error("Could not find docs.config.ts or docs.config.tsx in the current project. Use --config to point at a custom path.");
43
+ }
44
+ function readStringProperty(content, key) {
45
+ return content.match(new RegExp(`${key}\\s*:\\s*["']([^"']+)["']`))?.[1];
46
+ }
47
+ function readNavTitle(content) {
48
+ const block = extractObjectLiteral(content, "nav");
49
+ if (!block) return void 0;
50
+ return readStringProperty(block, "title");
51
+ }
52
+ function readMcpConfig(content) {
53
+ if (content.match(/mcp\s*:\s*false/)) return false;
54
+ if (content.match(/mcp\s*:\s*true/)) return true;
55
+ const block = extractObjectLiteral(content, "mcp");
56
+ if (!block) return void 0;
57
+ return {
58
+ enabled: readBooleanProperty(block, "enabled"),
59
+ route: readStringProperty(block, "route"),
60
+ name: readStringProperty(block, "name"),
61
+ version: readStringProperty(block, "version"),
62
+ tools: {
63
+ listPages: readBooleanProperty(block, "listPages"),
64
+ readPage: readBooleanProperty(block, "readPage"),
65
+ searchDocs: readBooleanProperty(block, "searchDocs"),
66
+ getNavigation: readBooleanProperty(block, "getNavigation")
67
+ }
68
+ };
69
+ }
70
+ function readBooleanProperty(content, key) {
71
+ const match = content.match(new RegExp(`${key}\\s*:\\s*(true|false)`));
72
+ return match ? match[1] === "true" : void 0;
73
+ }
74
+ function extractObjectLiteral(content, key) {
75
+ const keyIndex = content.search(new RegExp(`${key}\\s*:\\s*\\{`));
76
+ if (keyIndex === -1) return void 0;
77
+ const braceStart = content.indexOf("{", keyIndex);
78
+ if (braceStart === -1) return void 0;
79
+ let depth = 0;
80
+ for (let index = braceStart; index < content.length; index += 1) {
81
+ const char = content[index];
82
+ if (char === "{") {
83
+ depth += 1;
84
+ continue;
85
+ }
86
+ if (char !== "}") continue;
87
+ depth -= 1;
88
+ if (depth === 0) return content.slice(braceStart + 1, index);
89
+ }
90
+ }
91
+
92
+ //#endregion
93
+ export { runMcp };
package/dist/mcp.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { u as DocsMcpConfig, w as OrderingItem } from "./types-Bd3kyFF1.mjs";
2
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp";
1
+ import { u as DocsMcpConfig, w as OrderingItem } from "./types-dqnMXLdw.mjs";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
 
4
4
  //#region src/mcp.d.ts
5
5
  interface DocsMcpPage {
package/dist/mcp.mjs CHANGED
@@ -2,10 +2,10 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import matter from "gray-matter";
5
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp";
6
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio";
7
- import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp";
8
- import { isInitializeRequest } from "@modelcontextprotocol/sdk/types";
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
+ import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
8
+ import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
9
9
  import * as z from "zod/v4";
10
10
 
11
11
  //#region src/mcp.ts
package/dist/server.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { o as DocsConfig } from "./types-Bd3kyFF1.mjs";
1
+ import { o as DocsConfig } from "./types-dqnMXLdw.mjs";
2
2
  import { DocsMcpHttpHandlers, DocsMcpNavigationNode, DocsMcpNavigationTree, DocsMcpPage, DocsMcpResolvedConfig, DocsMcpSource, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
3
3
 
4
4
  //#region src/api-reference.d.ts
@@ -0,0 +1,138 @@
1
+ import { c as installCommand, i as detectPackageManagerFromLockfile, o as exec, s as fileExists, t as detectFramework } from "./utils-D5Wn7Q5E.mjs";
2
+ import path from "node:path";
3
+ import pc from "picocolors";
4
+ import * as p from "@clack/prompts";
5
+
6
+ //#region src/cli/upgrade.ts
7
+ /**
8
+ * Upgrade @farming-labs/* packages to latest.
9
+ * Detects framework from package.json by default, or use --framework (next, tanstack-start, nuxt, sveltekit, astro).
10
+ */
11
+ const PRESETS = [
12
+ "next",
13
+ "tanstack-start",
14
+ "nuxt",
15
+ "sveltekit",
16
+ "astro"
17
+ ];
18
+ const PACKAGES_BY_FRAMEWORK = {
19
+ nextjs: [
20
+ "@farming-labs/docs",
21
+ "@farming-labs/theme",
22
+ "@farming-labs/next"
23
+ ],
24
+ "tanstack-start": [
25
+ "@farming-labs/docs",
26
+ "@farming-labs/theme",
27
+ "@farming-labs/tanstack-start"
28
+ ],
29
+ nuxt: [
30
+ "@farming-labs/docs",
31
+ "@farming-labs/nuxt",
32
+ "@farming-labs/nuxt-theme"
33
+ ],
34
+ sveltekit: [
35
+ "@farming-labs/docs",
36
+ "@farming-labs/svelte",
37
+ "@farming-labs/svelte-theme"
38
+ ],
39
+ astro: [
40
+ "@farming-labs/docs",
41
+ "@farming-labs/astro",
42
+ "@farming-labs/astro-theme"
43
+ ]
44
+ };
45
+ function presetFromFramework(fw) {
46
+ return fw === "nextjs" ? "next" : fw;
47
+ }
48
+ function frameworkFromPreset(preset) {
49
+ return preset === "next" ? "nextjs" : preset;
50
+ }
51
+ /** Return package list for a framework (for testing and CLI). */
52
+ function getPackagesForFramework(framework) {
53
+ return PACKAGES_BY_FRAMEWORK[framework];
54
+ }
55
+ /** Build the install command for upgrade (for testing). */
56
+ function buildUpgradeCommand(framework, tag, pm) {
57
+ const packagesWithTag = PACKAGES_BY_FRAMEWORK[framework].map((name) => `${name}@${tag}`);
58
+ return `${installCommand(pm)} ${packagesWithTag.join(" ")}`;
59
+ }
60
+ async function upgrade(options = {}) {
61
+ const cwd = process.cwd();
62
+ const tag = options.tag ?? "latest";
63
+ p.intro(pc.bgCyan(pc.black(" @farming-labs/docs upgrade ")));
64
+ if (!fileExists(path.join(cwd, "package.json"))) {
65
+ p.log.error("No package.json found in the current directory. Run this from your project root.");
66
+ process.exit(1);
67
+ }
68
+ let framework = null;
69
+ let preset;
70
+ if (options.framework) {
71
+ const raw = options.framework.toLowerCase().trim();
72
+ const normalized = raw === "nextjs" ? "next" : raw;
73
+ if (!PRESETS.includes(normalized)) {
74
+ p.log.error(`Invalid framework ${pc.cyan(options.framework)}. Use one of: ${PRESETS.map((t) => pc.cyan(t)).join(", ")}`);
75
+ process.exit(1);
76
+ }
77
+ preset = normalized;
78
+ framework = frameworkFromPreset(preset);
79
+ } else {
80
+ const detected = detectFramework(cwd);
81
+ if (!detected) {
82
+ p.log.error("Could not detect a supported framework (Next.js, TanStack Start, Nuxt, SvelteKit, Astro). Use " + pc.cyan("--framework <next|tanstack-start|nuxt|sveltekit|astro>") + " to specify.");
83
+ process.exit(1);
84
+ }
85
+ framework = detected;
86
+ preset = presetFromFramework(framework);
87
+ }
88
+ let pm = detectPackageManagerFromLockfile(cwd);
89
+ if (pm) p.log.info(`Detected ${pc.cyan(pm)} from lockfile`);
90
+ else {
91
+ const pmAnswer = await p.select({
92
+ message: "Which package manager do you want to use for this upgrade?",
93
+ options: [
94
+ {
95
+ value: "pnpm",
96
+ label: "pnpm",
97
+ hint: "Use pnpm add"
98
+ },
99
+ {
100
+ value: "npm",
101
+ label: "npm",
102
+ hint: "Use npm add"
103
+ },
104
+ {
105
+ value: "yarn",
106
+ label: "yarn",
107
+ hint: "Use yarn add"
108
+ },
109
+ {
110
+ value: "bun",
111
+ label: "bun",
112
+ hint: "Use bun add"
113
+ }
114
+ ]
115
+ });
116
+ if (p.isCancel(pmAnswer)) {
117
+ p.outro(pc.red("Upgrade cancelled."));
118
+ process.exit(0);
119
+ }
120
+ pm = pmAnswer;
121
+ p.log.info(`Using ${pc.cyan(pm)} as package manager`);
122
+ }
123
+ const cmd = buildUpgradeCommand(framework, tag, pm);
124
+ const packages = getPackagesForFramework(framework);
125
+ p.log.step(`Upgrading ${preset} docs packages to ${tag}...`);
126
+ p.log.message(pc.dim(packages.join(", ")));
127
+ try {
128
+ exec(cmd, cwd);
129
+ p.log.success(`Packages upgraded to ${tag}.`);
130
+ p.outro(pc.green("Done. Run your dev server to confirm everything works."));
131
+ } catch {
132
+ p.log.error("Upgrade failed. Try running manually:\n " + pc.cyan(cmd));
133
+ process.exit(1);
134
+ }
135
+ }
136
+
137
+ //#endregion
138
+ export { upgrade };
@@ -0,0 +1,145 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { execSync, spawn } from "node:child_process";
4
+
5
+ //#region src/cli/utils.ts
6
+ function detectFramework(cwd) {
7
+ const pkgPath = path.join(cwd, "package.json");
8
+ if (!fs.existsSync(pkgPath)) return null;
9
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
10
+ const allDeps = {
11
+ ...pkg.dependencies,
12
+ ...pkg.devDependencies
13
+ };
14
+ if (allDeps["next"]) return "nextjs";
15
+ if (allDeps["@tanstack/react-start"]) return "tanstack-start";
16
+ if (allDeps["@sveltejs/kit"]) return "sveltekit";
17
+ if (allDeps["astro"]) return "astro";
18
+ if (allDeps["nuxt"]) return "nuxt";
19
+ return null;
20
+ }
21
+ function detectPackageManagerFromLockfile(cwd) {
22
+ if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
23
+ if (fs.existsSync(path.join(cwd, "bun.lockb")) || fs.existsSync(path.join(cwd, "bun.lock"))) return "bun";
24
+ if (fs.existsSync(path.join(cwd, "yarn.lock"))) return "yarn";
25
+ if (fs.existsSync(path.join(cwd, "package-lock.json"))) return "npm";
26
+ return null;
27
+ }
28
+ function installCommand(pm) {
29
+ return pm === "yarn" ? "yarn add" : `${pm} add`;
30
+ }
31
+ function devInstallCommand(pm) {
32
+ if (pm === "yarn") return "yarn add -D";
33
+ if (pm === "npm") return "npm install -D";
34
+ return `${pm} add -D`;
35
+ }
36
+ /**
37
+ * Write a file, creating parent directories as needed.
38
+ * Returns true if the file was written, false if it already existed and was skipped.
39
+ */
40
+ function writeFileSafe(filePath, content, overwrite = false) {
41
+ if (fs.existsSync(filePath) && !overwrite) return false;
42
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
43
+ fs.writeFileSync(filePath, content, "utf-8");
44
+ return true;
45
+ }
46
+ /**
47
+ * Check if a file exists.
48
+ */
49
+ function fileExists(filePath) {
50
+ return fs.existsSync(filePath);
51
+ }
52
+ /**
53
+ * Read a file, returning null if it does not exist.
54
+ */
55
+ function readFileSafe(filePath) {
56
+ if (!fs.existsSync(filePath)) return null;
57
+ return fs.readFileSync(filePath, "utf-8");
58
+ }
59
+ /** Common locations where global CSS files live in Next.js / SvelteKit projects. */
60
+ const GLOBAL_CSS_CANDIDATES = [
61
+ "app/globals.css",
62
+ "app/global.css",
63
+ "src/app/globals.css",
64
+ "src/app/global.css",
65
+ "src/app.css",
66
+ "src/styles/app.css",
67
+ "styles/globals.css",
68
+ "styles/global.css",
69
+ "src/styles/globals.css",
70
+ "src/styles/global.css",
71
+ "assets/css/main.css",
72
+ "assets/main.css"
73
+ ];
74
+ /**
75
+ * Find existing global CSS files in the project.
76
+ * Returns relative paths that exist.
77
+ */
78
+ function detectGlobalCssFiles(cwd) {
79
+ return GLOBAL_CSS_CANDIDATES.filter((rel) => fs.existsSync(path.join(cwd, rel)));
80
+ }
81
+ /**
82
+ * Detect whether the Next.js project uses `app` or `src/app` for the App Router.
83
+ * Returns the directory that exists; if both exist, prefers src/app; if neither, returns null.
84
+ */
85
+ function detectNextAppDir(cwd) {
86
+ const hasSrcApp = fs.existsSync(path.join(cwd, "src", "app"));
87
+ const hasApp = fs.existsSync(path.join(cwd, "app"));
88
+ if (hasSrcApp) return "src/app";
89
+ if (hasApp) return "app";
90
+ return null;
91
+ }
92
+ /**
93
+ * Run a shell command synchronously, inheriting stdio.
94
+ */
95
+ function exec(command, cwd) {
96
+ execSync(command, {
97
+ cwd,
98
+ stdio: "inherit"
99
+ });
100
+ }
101
+ /**
102
+ * Spawn a process and wait for a specific string in stdout,
103
+ * then resolve with the child process (still running).
104
+ */
105
+ function spawnAndWaitFor(command, args, cwd, waitFor, timeoutMs = 6e4) {
106
+ return new Promise((resolve, reject) => {
107
+ const child = spawn(command, args, {
108
+ cwd,
109
+ stdio: [
110
+ "ignore",
111
+ "pipe",
112
+ "pipe"
113
+ ],
114
+ shell: true
115
+ });
116
+ let output = "";
117
+ const timer = setTimeout(() => {
118
+ child.kill();
119
+ reject(/* @__PURE__ */ new Error(`Timed out waiting for "${waitFor}" after ${timeoutMs}ms`));
120
+ }, timeoutMs);
121
+ child.stdout?.on("data", (data) => {
122
+ const text = data.toString();
123
+ output += text;
124
+ process.stdout.write(text);
125
+ if (output.includes(waitFor)) {
126
+ clearTimeout(timer);
127
+ resolve(child);
128
+ }
129
+ });
130
+ child.stderr?.on("data", (data) => {
131
+ process.stderr.write(data.toString());
132
+ });
133
+ child.on("error", (err) => {
134
+ clearTimeout(timer);
135
+ reject(err);
136
+ });
137
+ child.on("close", (code) => {
138
+ clearTimeout(timer);
139
+ if (!output.includes(waitFor)) reject(/* @__PURE__ */ new Error(`Process exited with code ${code} before "${waitFor}" appeared`));
140
+ });
141
+ });
142
+ }
143
+
144
+ //#endregion
145
+ export { devInstallCommand as a, installCommand as c, writeFileSafe as d, detectPackageManagerFromLockfile as i, readFileSafe as l, detectGlobalCssFiles as n, exec as o, detectNextAppDir as r, fileExists as s, detectFramework as t, spawnAndWaitFor as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/docs",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Modern, flexible MDX-based docs framework — core types, config, and CLI",
5
5
  "keywords": [
6
6
  "docs",