@farming-labs/docs 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.
@@ -0,0 +1,99 @@
1
+ import { n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, t as buildDocsSearchDocuments } from "./search-BS6C5N1i.mjs";
2
+ import "./api-reference-DlfH-Y9c.mjs";
3
+ import { createFilesystemDocsMcpSource } from "./mcp.mjs";
4
+ import "./server.mjs";
5
+ import { a as readStringProperty, n as loadProjectEnv, o as resolveDocsConfigPath, s as resolveDocsContentDir } from "./config-CSywk3ou.mjs";
6
+ import { readFileSync } from "node:fs";
7
+ import pc from "picocolors";
8
+
9
+ //#region src/cli/search.ts
10
+ function getEnvValue(loadedEnv, key) {
11
+ return process.env[key] ?? loadedEnv[key];
12
+ }
13
+ function resolveSearchSyncProvider(options, loadedEnv) {
14
+ if (options.typesense && options.algolia) throw new Error("Use only one provider flag: --typesense or --algolia.");
15
+ if (options.typesense) return "typesense";
16
+ if (options.algolia) return "algolia";
17
+ if (options.provider === "typesense" || options.provider === "algolia") return options.provider;
18
+ if (options.provider) throw new Error(`Unsupported search provider: ${options.provider}.`);
19
+ if (options.baseUrl || getEnvValue(loadedEnv, "TYPESENSE_URL")) return "typesense";
20
+ if (options.appId || getEnvValue(loadedEnv, "ALGOLIA_APP_ID")) return "algolia";
21
+ throw new Error("Could not determine a search provider. Use --typesense, --algolia, or --provider <name>.");
22
+ }
23
+ function resolveTypesenseSyncConfig(options, loadedEnv) {
24
+ const baseUrl = options.baseUrl ?? getEnvValue(loadedEnv, "TYPESENSE_URL") ?? getEnvValue(loadedEnv, "TYPESENSE_BASE_URL");
25
+ const collection = options.collection ?? getEnvValue(loadedEnv, "TYPESENSE_COLLECTION") ?? "docs";
26
+ const apiKey = options.apiKey ?? getEnvValue(loadedEnv, "TYPESENSE_SEARCH_API_KEY") ?? getEnvValue(loadedEnv, "TYPESENSE_API_KEY");
27
+ const adminApiKey = options.adminApiKey ?? getEnvValue(loadedEnv, "TYPESENSE_ADMIN_API_KEY") ?? getEnvValue(loadedEnv, "TYPESENSE_API_KEY");
28
+ const mode = options.mode === "hybrid" ? "hybrid" : "keyword";
29
+ const ollamaModel = options.ollamaModel ?? getEnvValue(loadedEnv, "TYPESENSE_OLLAMA_MODEL");
30
+ const ollamaBaseUrl = options.ollamaBaseUrl ?? getEnvValue(loadedEnv, "TYPESENSE_OLLAMA_BASE_URL");
31
+ if (!baseUrl) throw new Error("Missing Typesense base URL. Set TYPESENSE_URL or pass --base-url.");
32
+ if (!apiKey) throw new Error("Missing Typesense API key. Set TYPESENSE_API_KEY or pass --api-key.");
33
+ if (!adminApiKey) throw new Error("Missing Typesense admin-capable key for sync. Set TYPESENSE_ADMIN_API_KEY or pass --admin-api-key.");
34
+ return {
35
+ provider: "typesense",
36
+ baseUrl,
37
+ collection,
38
+ apiKey,
39
+ adminApiKey,
40
+ mode,
41
+ ...mode === "hybrid" ? ollamaModel ? { embeddings: {
42
+ provider: "ollama",
43
+ model: ollamaModel,
44
+ baseUrl: ollamaBaseUrl
45
+ } } : (() => {
46
+ throw new Error("Typesense hybrid sync needs an embeddings model. Set TYPESENSE_OLLAMA_MODEL or pass --ollama-model.");
47
+ })() : {}
48
+ };
49
+ }
50
+ function resolveAlgoliaSyncConfig(options, loadedEnv) {
51
+ const appId = options.appId ?? getEnvValue(loadedEnv, "ALGOLIA_APP_ID");
52
+ const indexName = options.indexName ?? getEnvValue(loadedEnv, "ALGOLIA_INDEX_NAME") ?? "docs";
53
+ const adminApiKey = options.adminApiKey ?? getEnvValue(loadedEnv, "ALGOLIA_ADMIN_API_KEY");
54
+ const searchApiKey = options.searchApiKey ?? getEnvValue(loadedEnv, "ALGOLIA_SEARCH_API_KEY") ?? adminApiKey;
55
+ if (!appId) throw new Error("Missing Algolia app id. Set ALGOLIA_APP_ID or pass --app-id.");
56
+ if (!adminApiKey) throw new Error("Missing Algolia admin API key for sync. Set ALGOLIA_ADMIN_API_KEY or pass --admin-api-key.");
57
+ if (!searchApiKey) throw new Error("Missing Algolia search API key. Set ALGOLIA_SEARCH_API_KEY or pass --search-api-key.");
58
+ return {
59
+ provider: "algolia",
60
+ appId,
61
+ indexName,
62
+ searchApiKey,
63
+ adminApiKey
64
+ };
65
+ }
66
+ async function syncSearch(options = {}) {
67
+ const rootDir = process.cwd();
68
+ const configContent = readFileSync(resolveDocsConfigPath(rootDir, options.configPath), "utf-8");
69
+ const loadedEnv = loadProjectEnv(rootDir);
70
+ const provider = resolveSearchSyncProvider(options, loadedEnv);
71
+ const entry = readStringProperty(configContent, "entry") ?? "docs";
72
+ const contentDir = resolveDocsContentDir(rootDir, configContent, entry);
73
+ const source = createFilesystemDocsMcpSource({
74
+ rootDir,
75
+ entry,
76
+ contentDir,
77
+ siteTitle: "Documentation"
78
+ });
79
+ const pages = await source.getPages();
80
+ const documents = buildDocsSearchDocuments(pages);
81
+ const context = {
82
+ pages,
83
+ documents,
84
+ siteTitle: source.siteTitle
85
+ };
86
+ if (documents.length === 0) throw new Error(`No docs content was found under ${contentDir}.`);
87
+ if (provider === "typesense") {
88
+ const config = resolveTypesenseSyncConfig(options, loadedEnv);
89
+ await createTypesenseSearchAdapter(config).index?.(context);
90
+ console.log(pc.green(`Synced ${documents.length} docs search documents to Typesense collection "${config.collection}".`));
91
+ return;
92
+ }
93
+ const config = resolveAlgoliaSyncConfig(options, loadedEnv);
94
+ await createAlgoliaSearchAdapter(config).index?.(context);
95
+ console.log(pc.green(`Synced ${documents.length} docs search documents to Algolia index "${config.indexName}".`));
96
+ }
97
+
98
+ //#endregion
99
+ export { syncSearch };
@@ -0,0 +1,21 @@
1
+ import { E as DocsSearchSourcePage, N as McpDocsSearchConfig, Z as TypesenseDocsSearchConfig, b as DocsSearchConfig, g as DocsSearchAdapter, n as AlgoliaDocsSearchConfig, s as CustomDocsSearchConfig, v as DocsSearchAdapterFactory, w as DocsSearchResult, x as DocsSearchDocument, y as DocsSearchChunkingConfig } from "./types-BAulrjlV.mjs";
2
+
3
+ //#region src/search.d.ts
4
+ declare function buildDocsSearchDocuments(pages: DocsSearchSourcePage[], chunking?: DocsSearchChunkingConfig): DocsSearchDocument[];
5
+ declare function createSimpleSearchAdapter(): DocsSearchAdapter;
6
+ declare function createTypesenseSearchAdapter(config: TypesenseDocsSearchConfig): DocsSearchAdapter;
7
+ declare function resolveSearchRequestConfig(search: boolean | DocsSearchConfig | undefined, requestUrl?: string): boolean | DocsSearchConfig | undefined;
8
+ declare function createMcpSearchAdapter(config: McpDocsSearchConfig): DocsSearchAdapter;
9
+ declare function createAlgoliaSearchAdapter(config: AlgoliaDocsSearchConfig): DocsSearchAdapter;
10
+ declare function performDocsSearch(options: {
11
+ pages: DocsSearchSourcePage[];
12
+ query: string;
13
+ search?: boolean | DocsSearchConfig;
14
+ locale?: string;
15
+ pathname?: string;
16
+ siteTitle?: string;
17
+ limit?: number;
18
+ }): Promise<DocsSearchResult[]>;
19
+ declare function createCustomSearchAdapter(adapter: DocsSearchAdapter | DocsSearchAdapterFactory): CustomDocsSearchConfig;
20
+ //#endregion
21
+ export { createSimpleSearchAdapter as a, resolveSearchRequestConfig as c, createMcpSearchAdapter as i, createAlgoliaSearchAdapter as n, createTypesenseSearchAdapter as o, createCustomSearchAdapter as r, performDocsSearch as s, buildDocsSearchDocuments as t };
package/dist/server.d.mts CHANGED
@@ -1,4 +1,5 @@
1
- import { o as DocsConfig } from "./types-dqnMXLdw.mjs";
1
+ import { C as DocsSearchQuery, E as DocsSearchSourcePage, N as McpDocsSearchConfig, _ as DocsSearchAdapterContext, b as DocsSearchConfig, c as DocsConfig, g as DocsSearchAdapter, v as DocsSearchAdapterFactory, w as DocsSearchResult, x as DocsSearchDocument } from "./types-BAulrjlV.mjs";
2
+ import { a as createSimpleSearchAdapter, c as resolveSearchRequestConfig, i as createMcpSearchAdapter, n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, r as createCustomSearchAdapter, s as performDocsSearch, t as buildDocsSearchDocuments } from "./search-KzREATdM.mjs";
2
3
  import { DocsMcpHttpHandlers, DocsMcpNavigationNode, DocsMcpNavigationTree, DocsMcpPage, DocsMcpResolvedConfig, DocsMcpSource, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
3
4
 
4
5
  //#region src/api-reference.d.ts
@@ -36,4 +37,4 @@ declare function buildApiReferenceOpenApiDocumentAsync(config: DocsConfig, optio
36
37
  declare function buildApiReferenceHtmlDocument(config: DocsConfig, options: BuildApiReferenceHtmlOptions): string;
37
38
  declare function buildApiReferenceHtmlDocumentAsync(config: DocsConfig, options: BuildApiReferenceHtmlOptions): Promise<string>;
38
39
  //#endregion
39
- export { type ApiReferenceFramework, type ApiReferenceRoute, type DocsMcpHttpHandlers, type DocsMcpNavigationNode, type DocsMcpNavigationTree, type DocsMcpPage, type DocsMcpResolvedConfig, type DocsMcpSource, type ResolvedApiReferenceConfig, buildApiReferenceHtmlDocument, buildApiReferenceHtmlDocumentAsync, buildApiReferenceOpenApiDocument, buildApiReferenceOpenApiDocumentAsync, buildApiReferencePageTitle, buildApiReferenceScalarCss, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveApiReferenceConfig, resolveDocsMcpConfig, runDocsMcpStdio };
40
+ export { type ApiReferenceFramework, type ApiReferenceRoute, type DocsMcpHttpHandlers, type DocsMcpNavigationNode, type DocsMcpNavigationTree, type DocsMcpPage, type DocsMcpResolvedConfig, type DocsMcpSource, type DocsSearchAdapter, type DocsSearchAdapterContext, type DocsSearchAdapterFactory, type DocsSearchConfig, type DocsSearchDocument, type DocsSearchQuery, type DocsSearchResult, type DocsSearchSourcePage, type McpDocsSearchConfig, type ResolvedApiReferenceConfig, buildApiReferenceHtmlDocument, buildApiReferenceHtmlDocumentAsync, buildApiReferenceOpenApiDocument, buildApiReferenceOpenApiDocumentAsync, buildApiReferencePageTitle, buildApiReferenceScalarCss, buildDocsSearchDocuments, createAlgoliaSearchAdapter, createCustomSearchAdapter, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, createMcpSearchAdapter, createSimpleSearchAdapter, createTypesenseSearchAdapter, normalizeDocsMcpRoute, performDocsSearch, resolveApiReferenceConfig, resolveDocsMcpConfig, resolveSearchRequestConfig, runDocsMcpStdio };
package/dist/server.mjs CHANGED
@@ -1,4 +1,5 @@
1
- import { a as buildApiReferencePageTitle, i as buildApiReferenceOpenApiDocumentAsync, n as buildApiReferenceHtmlDocumentAsync, o as buildApiReferenceScalarCss, r as buildApiReferenceOpenApiDocument, s as resolveApiReferenceConfig, t as buildApiReferenceHtmlDocument } from "./api-reference-wh4_pwG8.mjs";
1
+ import { a as createSimpleSearchAdapter, c as resolveSearchRequestConfig, i as createMcpSearchAdapter, n as createAlgoliaSearchAdapter, o as createTypesenseSearchAdapter, r as createCustomSearchAdapter, s as performDocsSearch, t as buildDocsSearchDocuments } from "./search-BS6C5N1i.mjs";
2
+ import { a as buildApiReferencePageTitle, i as buildApiReferenceOpenApiDocumentAsync, n as buildApiReferenceHtmlDocumentAsync, o as buildApiReferenceScalarCss, r as buildApiReferenceOpenApiDocument, s as resolveApiReferenceConfig, t as buildApiReferenceHtmlDocument } from "./api-reference-DlfH-Y9c.mjs";
2
3
  import { createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveDocsMcpConfig, runDocsMcpStdio } from "./mcp.mjs";
3
4
 
4
- export { buildApiReferenceHtmlDocument, buildApiReferenceHtmlDocumentAsync, buildApiReferenceOpenApiDocument, buildApiReferenceOpenApiDocumentAsync, buildApiReferencePageTitle, buildApiReferenceScalarCss, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, normalizeDocsMcpRoute, resolveApiReferenceConfig, resolveDocsMcpConfig, runDocsMcpStdio };
5
+ export { buildApiReferenceHtmlDocument, buildApiReferenceHtmlDocumentAsync, buildApiReferenceOpenApiDocument, buildApiReferenceOpenApiDocumentAsync, buildApiReferencePageTitle, buildApiReferenceScalarCss, buildDocsSearchDocuments, createAlgoliaSearchAdapter, createCustomSearchAdapter, createDocsMcpHttpHandler, createDocsMcpServer, createFilesystemDocsMcpSource, createMcpSearchAdapter, createSimpleSearchAdapter, createTypesenseSearchAdapter, normalizeDocsMcpRoute, performDocsSearch, resolveApiReferenceConfig, resolveDocsMcpConfig, resolveSearchRequestConfig, runDocsMcpStdio };
@@ -614,6 +614,144 @@ interface DocsMcpConfig {
614
614
  /** Fine-grained tool toggles. Omitted tools stay enabled. */
615
615
  tools?: DocsMcpToolsConfig;
616
616
  }
617
+ type DocsSearchResultType = "page" | "heading" | "text";
618
+ interface DocsSearchSourcePage {
619
+ title: string;
620
+ url: string;
621
+ content: string;
622
+ description?: string;
623
+ rawContent?: string;
624
+ type?: "page" | "api" | "code" | "changelog";
625
+ locale?: string;
626
+ framework?: string;
627
+ version?: string;
628
+ tags?: string[];
629
+ }
630
+ interface DocsSearchDocument {
631
+ id: string;
632
+ url: string;
633
+ title: string;
634
+ content: string;
635
+ description?: string;
636
+ section?: string;
637
+ type: DocsSearchResultType;
638
+ locale?: string;
639
+ framework?: string;
640
+ version?: string;
641
+ tags?: string[];
642
+ }
643
+ interface DocsSearchResult {
644
+ id: string;
645
+ url: string;
646
+ content: string;
647
+ description?: string;
648
+ type: DocsSearchResultType;
649
+ score?: number;
650
+ section?: string;
651
+ }
652
+ interface DocsSearchQuery {
653
+ query: string;
654
+ limit?: number;
655
+ locale?: string;
656
+ pathname?: string;
657
+ }
658
+ interface DocsSearchAdapterContext {
659
+ pages: DocsSearchSourcePage[];
660
+ documents: DocsSearchDocument[];
661
+ locale?: string;
662
+ pathname?: string;
663
+ siteTitle?: string;
664
+ }
665
+ interface DocsSearchAdapter {
666
+ name: string;
667
+ index?(context: DocsSearchAdapterContext): Promise<void>;
668
+ search(query: DocsSearchQuery, context: DocsSearchAdapterContext): Promise<DocsSearchResult[]>;
669
+ }
670
+ type DocsSearchAdapterFactory = (context: DocsSearchAdapterContext) => DocsSearchAdapter | Promise<DocsSearchAdapter>;
671
+ interface DocsSearchChunkingConfig {
672
+ /**
673
+ * How docs content should be chunked before searching.
674
+ *
675
+ * - `"page"` keeps one search document per page
676
+ * - `"section"` splits pages by headings and improves precision
677
+ *
678
+ * @default "section"
679
+ */
680
+ strategy?: "page" | "section";
681
+ }
682
+ interface DocsSearchEmbeddingsConfig {
683
+ /**
684
+ * Embeddings provider used for hybrid / semantic search.
685
+ * The initial built-in provider is Ollama for local or self-hosted setups.
686
+ */
687
+ provider: "ollama";
688
+ /** Embedding model id, e.g. `embeddinggemma`. */
689
+ model: string;
690
+ /** Base URL of the embedding API. @default "http://127.0.0.1:11434" */
691
+ baseUrl?: string;
692
+ }
693
+ interface SimpleDocsSearchConfig {
694
+ provider?: "simple";
695
+ enabled?: boolean;
696
+ maxResults?: number;
697
+ chunking?: DocsSearchChunkingConfig;
698
+ }
699
+ interface AlgoliaDocsSearchConfig {
700
+ provider: "algolia";
701
+ enabled?: boolean;
702
+ appId: string;
703
+ indexName: string;
704
+ searchApiKey: string;
705
+ adminApiKey?: string;
706
+ maxResults?: number;
707
+ syncOnSearch?: boolean;
708
+ chunking?: DocsSearchChunkingConfig;
709
+ }
710
+ interface TypesenseDocsSearchConfig {
711
+ provider: "typesense";
712
+ enabled?: boolean;
713
+ baseUrl: string;
714
+ collection: string;
715
+ apiKey: string;
716
+ adminApiKey?: string;
717
+ maxResults?: number;
718
+ syncOnSearch?: boolean;
719
+ queryBy?: string[];
720
+ mode?: "keyword" | "hybrid";
721
+ embeddings?: DocsSearchEmbeddingsConfig;
722
+ chunking?: DocsSearchChunkingConfig;
723
+ }
724
+ interface McpDocsSearchConfig {
725
+ provider: "mcp";
726
+ enabled?: boolean;
727
+ /**
728
+ * Streamable HTTP MCP endpoint. Relative paths like `/api/docs/mcp` are resolved
729
+ * against the current docs API request URL.
730
+ */
731
+ endpoint: string;
732
+ /**
733
+ * Optional extra headers passed to the MCP endpoint on initialize/tool calls.
734
+ */
735
+ headers?: Record<string, string>;
736
+ /**
737
+ * MCP tool name used for search. Defaults to `search_docs`.
738
+ */
739
+ toolName?: string;
740
+ /**
741
+ * Override the MCP protocol version header when needed.
742
+ */
743
+ protocolVersion?: string;
744
+ maxResults?: number;
745
+ chunking?: DocsSearchChunkingConfig;
746
+ }
747
+ interface CustomDocsSearchConfig {
748
+ provider: "custom";
749
+ enabled?: boolean;
750
+ adapter: DocsSearchAdapter | DocsSearchAdapterFactory;
751
+ maxResults?: number;
752
+ chunking?: DocsSearchChunkingConfig;
753
+ }
754
+ type DocsSearchConfig = SimpleDocsSearchConfig | AlgoliaDocsSearchConfig | McpDocsSearchConfig | TypesenseDocsSearchConfig | CustomDocsSearchConfig;
617
755
  interface LastUpdatedConfig {
618
756
  /**
619
757
  * Whether to show the "Last updated" date.
@@ -1353,6 +1491,16 @@ interface DocsConfig {
1353
1491
  * ```
1354
1492
  */
1355
1493
  pageActions?: PageActionsConfig;
1494
+ /**
1495
+ * Built-in docs search configuration.
1496
+ *
1497
+ * - `true` or omitted → use the built-in simple search
1498
+ * - `{ provider: "typesense", ... }` → use Typesense
1499
+ * - `{ provider: "algolia", ... }` → use Algolia
1500
+ * - `{ provider: "custom", adapter }` → use a custom adapter
1501
+ * - `false` → disable docs search
1502
+ */
1503
+ search?: boolean | DocsSearchConfig;
1356
1504
  /**
1357
1505
  * Configuration for the "Last updated" date display.
1358
1506
  *
@@ -1481,4 +1629,4 @@ interface DocsConfig {
1481
1629
  og?: OGConfig;
1482
1630
  }
1483
1631
  //#endregion
1484
- export { SidebarConfig as A, OpenGraphImage as C, PageOpenGraph as D, PageFrontmatter as E, ThemeToggleConfig as F, TypographyConfig as I, UIConfig as L, SidebarNode as M, SidebarPageNode as N, PageTwitter as O, SidebarTree as P, OpenDocsProvider as S, PageActionsConfig as T, GithubConfig as _, CopyMarkdownConfig as a, OGConfig as b, DocsFeedbackValue as c, DocsMcpToolsConfig as d, DocsMetadata as f, FontStyle as g, FeedbackConfig as h, CodeBlockCopyData as i, SidebarFolderNode as j, SidebarComponentProps as k, DocsI18nConfig as l, DocsTheme as m, ApiReferenceConfig as n, DocsConfig as o, DocsNav as p, BreadcrumbConfig as r, DocsFeedbackData as s, AIConfig as t, DocsMcpConfig as u, LastUpdatedConfig as v, OrderingItem as w, OpenDocsConfig as x, LlmsTxtConfig as y };
1632
+ export { UIConfig as $, GithubConfig as A, PageFrontmatter as B, DocsSearchQuery as C, DocsTheme as D, DocsSearchSourcePage as E, OpenDocsConfig as F, SidebarFolderNode as G, PageTwitter as H, OpenDocsProvider as I, SidebarTree as J, SidebarNode as K, OpenGraphImage as L, LlmsTxtConfig as M, McpDocsSearchConfig as N, FeedbackConfig as O, OGConfig as P, TypographyConfig as Q, OrderingItem as R, DocsSearchEmbeddingsConfig as S, DocsSearchResultType as T, SidebarComponentProps as U, PageOpenGraph as V, SidebarConfig as W, ThemeToggleConfig as X, SimpleDocsSearchConfig as Y, TypesenseDocsSearchConfig as Z, DocsSearchAdapterContext as _, CodeBlockCopyData as a, DocsSearchConfig as b, DocsConfig as c, DocsI18nConfig as d, DocsMcpConfig as f, DocsSearchAdapter as g, DocsNav as h, BreadcrumbConfig as i, LastUpdatedConfig as j, FontStyle as k, DocsFeedbackData as l, DocsMetadata as m, AlgoliaDocsSearchConfig as n, CopyMarkdownConfig as o, DocsMcpToolsConfig as p, SidebarPageNode as q, ApiReferenceConfig as r, CustomDocsSearchConfig as s, AIConfig as t, DocsFeedbackValue as u, DocsSearchAdapterFactory as v, DocsSearchResult as w, DocsSearchDocument as x, DocsSearchChunkingConfig as y, PageActionsConfig as z };
@@ -1,4 +1,4 @@
1
- import { c as installCommand, i as detectPackageManagerFromLockfile, o as exec, s as fileExists, t as detectFramework } from "./utils-D5Wn7Q5E.mjs";
1
+ import { c as installCommand, i as detectPackageManagerFromLockfile, o as exec, s as fileExists, t as detectFramework } from "./utils-CRhME2g-.mjs";
2
2
  import path from "node:path";
3
3
  import pc from "picocolors";
4
4
  import * as p from "@clack/prompts";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farming-labs/docs",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Modern, flexible MDX-based docs framework — core types, config, and CLI",
5
5
  "keywords": [
6
6
  "docs",
@@ -1,93 +0,0 @@
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 };
File without changes