@farming-labs/docs 0.2.120 → 0.2.122

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.
Files changed (188) hide show
  1. package/README.md +8 -0
  2. package/dist/access.d.mts +13 -0
  3. package/dist/access.mjs +56 -0
  4. package/dist/agent-conformance.d.mts +60 -0
  5. package/dist/agent-conformance.mjs +538 -0
  6. package/dist/agent-contract.d.mts +47 -0
  7. package/dist/agent-contract.mjs +645 -0
  8. package/dist/agent-detection.d.mts +6 -0
  9. package/dist/agent-detection.mjs +83 -0
  10. package/dist/agent-evals.d.mts +224 -0
  11. package/dist/{agent-evals-BLNLvXbG.mjs → agent-evals.mjs} +7 -565
  12. package/dist/agent-feedback-evaluations-node.mjs +38 -0
  13. package/dist/agent-feedback-evaluations.d.mts +91 -0
  14. package/dist/{agent-feedback-evaluations-CcMGlgsO.mjs → agent-feedback-evaluations.mjs} +2 -2
  15. package/dist/agent-feedback-loop.d.mts +45 -0
  16. package/dist/{agent-feedback-loop-CcZL_sb1.mjs → agent-feedback-loop.mjs} +1 -1
  17. package/dist/agent-maintenance.d.mts +71 -0
  18. package/dist/{agent-maintenance-CuZ7iAKq.mjs → agent-maintenance.mjs} +1 -1
  19. package/dist/agent-provenance.d.mts +23 -0
  20. package/dist/agent-provenance.mjs +77 -0
  21. package/dist/agent-scope.mjs +321 -0
  22. package/dist/agent-skills-archive.mjs +86 -0
  23. package/dist/agent-skills-bundle.d.mts +1 -1
  24. package/dist/{agent-skills-progressive-disclosure-PjPtTYL-.mjs → agent-skills-progressive-disclosure.mjs} +2 -2
  25. package/dist/{agent-skills-server-D5IuvwM7.d.mts → agent-skills-server.d.mts} +3 -3
  26. package/dist/{agent-skills-server-BC7md56k.mjs → agent-skills-server.mjs} +2 -2
  27. package/dist/agent-skills-vite.d.mts +3 -3
  28. package/dist/agent-skills-vite.mjs +1 -2
  29. package/dist/agent-surface-drift.mjs +236 -0
  30. package/dist/{golden-evaluations-CLUViycJ.mjs → agent-usefulness.mjs} +5 -290
  31. package/dist/{content-change-hydration-wqXIZHp6.d.mts → agent.d.mts} +10 -411
  32. package/dist/agent.mjs +2729 -0
  33. package/dist/{analytics-w3FDOksr.d.mts → analytics.d.mts} +2 -2
  34. package/dist/{analytics-p8Vhhu2P.mjs → analytics.mjs} +2 -2
  35. package/dist/{sitemap-server-BUdPBcGs.d.mts → api-reference.d.mts} +2 -6
  36. package/dist/api-reference.mjs +1481 -0
  37. package/dist/{audience-exposure-DBrFWULA.d.mts → audience-exposure.d.mts} +1 -1
  38. package/dist/audience-exposure.mjs +8 -0
  39. package/dist/audience.d.mts +44 -0
  40. package/dist/audience.mjs +1654 -0
  41. package/dist/authoring-mcp.d.mts +44 -0
  42. package/dist/{authoring-mcp-CiCUQe3o.mjs → authoring-mcp.mjs} +3 -3
  43. package/dist/browser.d.mts +6 -4
  44. package/dist/browser.mjs +6 -7
  45. package/dist/build.d.mts +8 -0
  46. package/dist/build.mjs +8 -0
  47. package/dist/changelog.d.mts +20 -0
  48. package/dist/changelog.mjs +39 -0
  49. package/dist/{agent-export-CA6IUQ7T.mjs → cli/agent-export.mjs} +19 -45
  50. package/dist/{agent-CYk2DxY7.mjs → cli/agent.mjs} +6 -35
  51. package/dist/{agents-BUiVmj8i.mjs → cli/agents.mjs} +5 -18
  52. package/dist/cli/api-doctor.mjs +206 -0
  53. package/dist/{authoring-C2ymvYWl.mjs → cli/authoring.mjs} +2 -8
  54. package/dist/{cloud-6eKrlmKd.mjs → cli/cloud.mjs} +3 -3
  55. package/dist/{codeblocks-CHpgAwY-.mjs → cli/codeblocks.mjs} +2 -2
  56. package/dist/cli/config.d.mts +11 -0
  57. package/dist/{config-BZnKAj_Y.mjs → cli/config.mjs} +1 -1
  58. package/dist/cli/dev-banner.mjs +58 -0
  59. package/dist/{dev-Bnn-NUNa.mjs → cli/dev.mjs} +3 -57
  60. package/dist/{doctor-Bfkrkzad.mjs → cli/doctor.mjs} +41 -226
  61. package/dist/{downgrade-CHMta85e.mjs → cli/downgrade.mjs} +2 -2
  62. package/dist/cli/errors.d.mts +4 -0
  63. package/dist/{errors-BtnVLhNF.mjs → cli/errors.mjs} +1 -1
  64. package/dist/{feedback-evals-DMilg9pY.mjs → cli/feedback-evals.mjs} +3 -36
  65. package/dist/{feedback-DL4T5oIO.mjs → cli/feedback.mjs} +1 -1
  66. package/dist/cli/git-dates.mjs +35 -0
  67. package/dist/cli/golden-evaluations.mjs +52 -0
  68. package/dist/cli/index.d.mts +2 -3
  69. package/dist/cli/index.mjs +38 -38
  70. package/dist/{init-K0LmXDZ5.mjs → cli/init.mjs} +3 -3
  71. package/dist/{mcp-iLCmnPJI.mjs → cli/mcp.mjs} +7 -19
  72. package/dist/{openapi-diff-HcpUNjA-.mjs → cli/openapi-diff.mjs} +2 -7
  73. package/dist/{openapi-sdk-BQKC6H-_.mjs → cli/openapi-sdk.mjs} +2 -7
  74. package/dist/{openapi-source-DK6ts_Bk.mjs → cli/openapi-source.mjs} +2 -2
  75. package/dist/{package-version-HJhYeq4M.mjs → cli/package-version.mjs} +2 -2
  76. package/dist/{propose-JmUv_BTt.mjs → cli/propose.mjs} +1 -1
  77. package/dist/{review-C6EmbV0l.mjs → cli/review.mjs} +16 -15
  78. package/dist/{robots-DteZB8vl.mjs → cli/robots.mjs} +3 -7
  79. package/dist/{search-Bhuv_YsL.mjs → cli/search.mjs} +7 -20
  80. package/dist/{sitemap-DW5LDKDa.mjs → cli/sitemap.mjs} +7 -42
  81. package/dist/{skills-BAPQLSCm.mjs → cli/skills.mjs} +5 -19
  82. package/dist/{templates-BuQ8YsGv.mjs → cli/templates.mjs} +1 -1
  83. package/dist/{upgrade-DlQMOFV1.mjs → cli/upgrade.mjs} +2 -2
  84. package/dist/{utils-C7KDrPpA.mjs → cli/utils.mjs} +1 -1
  85. package/dist/client/react.d.mts +2 -18
  86. package/dist/client/react.mjs +1 -157
  87. package/dist/{cloud-analytics-D14HplI7.mjs → cloud-analytics.mjs} +1 -1
  88. package/dist/{cloud-ask-ai-BrsTXQf6.d.mts → cloud-ask-ai.d.mts} +2 -2
  89. package/dist/{cloud-ask-ai-BqKhjpS5.mjs → cloud-ask-ai.mjs} +3 -3
  90. package/dist/code-blocks.d.mts +51 -0
  91. package/dist/{code-blocks-GYdvS3BH.mjs → code-blocks.mjs} +2 -2
  92. package/dist/code-group-mdx.d.mts +11 -0
  93. package/dist/code-group-mdx.mjs +57 -0
  94. package/dist/content-change-hydration.d.mts +87 -0
  95. package/dist/{openapi-mcp-BIOTLiA7.mjs → content-change-hydration.mjs} +5 -210
  96. package/dist/content-changes.d.mts +47 -0
  97. package/dist/content-changes.mjs +216 -0
  98. package/dist/create-theme.d.mts +48 -0
  99. package/dist/create-theme.mjs +57 -0
  100. package/dist/date.d.mts +5 -0
  101. package/dist/date.mjs +17 -0
  102. package/dist/define-docs.d.mts +9 -0
  103. package/dist/define-docs.mjs +46 -0
  104. package/dist/docs-cloud-client.d.mts +18 -0
  105. package/dist/docs-cloud-client.mjs +161 -0
  106. package/dist/docs-cloud-server.d.mts +2 -2
  107. package/dist/docs-cloud-server.mjs +2 -3
  108. package/dist/heading-toc.d.mts +10 -0
  109. package/dist/heading-toc.mjs +23 -0
  110. package/dist/http-body.d.mts +14 -0
  111. package/dist/{http-body-DkAPk6D5.mjs → http-body.mjs} +1 -1
  112. package/dist/http-cache.d.mts +25 -0
  113. package/dist/http-cache.mjs +140 -0
  114. package/dist/http-link.mjs +81 -0
  115. package/dist/i18n.d.mts +18 -0
  116. package/dist/{i18n-B1gJ9EW0.mjs → i18n.mjs} +1 -1
  117. package/dist/index.d.mts +42 -674
  118. package/dist/index.mjs +40 -14
  119. package/dist/markdown-rendering.mjs +1 -1
  120. package/dist/markdown-section-cache.mjs +49 -0
  121. package/dist/markdown-sections.d.mts +47 -0
  122. package/dist/{markdown-sections-9Oxr33b-.mjs → markdown-sections.mjs} +29 -703
  123. package/dist/mcp-auth.d.mts +14 -0
  124. package/dist/mcp-auth.mjs +99 -0
  125. package/dist/mcp.d.mts +5 -3
  126. package/dist/mcp.mjs +21 -9
  127. package/dist/mdx.d.mts +6 -0
  128. package/dist/mdx.mjs +7 -0
  129. package/dist/metadata.d.mts +60 -0
  130. package/dist/{metadata-BOHn0Y5K.mjs → metadata.mjs} +2 -2
  131. package/dist/native-api-reference.mjs +968 -0
  132. package/dist/okf.d.mts +42 -0
  133. package/dist/okf.mjs +145 -0
  134. package/dist/openapi-contract.mjs +154 -0
  135. package/dist/{openapi-mcp-node-C4jUpZG6.mjs → openapi-mcp-node.mjs} +1 -1
  136. package/dist/openapi-mcp.d.mts +26 -0
  137. package/dist/openapi-mcp.mjs +132 -0
  138. package/dist/openapi-operations.d.mts +71 -0
  139. package/dist/{openapi-operations-DFpaqOqA.mjs → openapi-operations.mjs} +1 -1
  140. package/dist/openapi-overlays.mjs +221 -0
  141. package/dist/openapi-references.mjs +233 -0
  142. package/dist/pagination.d.mts +7 -0
  143. package/dist/pagination.mjs +100 -0
  144. package/dist/prompt-references.d.mts +12 -0
  145. package/dist/prompt-references.mjs +132 -0
  146. package/dist/prompt-utils.d.mts +36 -0
  147. package/dist/{prompt-utils-B5g-bv7o.mjs → prompt-utils.mjs} +1 -57
  148. package/dist/reading-time.d.mts +23 -0
  149. package/dist/reading-time.mjs +58 -0
  150. package/dist/related.d.mts +7 -0
  151. package/dist/related.mjs +50 -0
  152. package/dist/retrieval-digest.d.mts +16 -0
  153. package/dist/{retrieval-digest-CT-eIEcp.mjs → retrieval-digest.mjs} +1 -1
  154. package/dist/review.d.mts +69 -0
  155. package/dist/review.mjs +562 -0
  156. package/dist/robots.d.mts +54 -0
  157. package/dist/{robots-BYJAVeI6.mjs → robots.mjs} +5 -3
  158. package/dist/runtime.d.mts +3 -3
  159. package/dist/runtime.mjs +3 -9
  160. package/dist/search.d.mts +210 -0
  161. package/dist/search.mjs +3401 -0
  162. package/dist/server.d.mts +22 -198
  163. package/dist/server.mjs +21 -19
  164. package/dist/sidebar.d.mts +15 -0
  165. package/dist/sidebar.mjs +73 -0
  166. package/dist/sitemap-server.d.mts +7 -0
  167. package/dist/{sitemap-server-Lg3YhUx4.mjs → sitemap-server.mjs} +2 -2
  168. package/dist/{sitemap-Cl8vrixd.d.mts → sitemap.d.mts} +3 -3
  169. package/dist/sitemap.mjs +254 -0
  170. package/dist/{standards-discovery-BHPc7YIX.d.mts → standards-discovery.d.mts} +2 -2
  171. package/dist/{standards-discovery-sSEojU80.mjs → standards-discovery.mjs} +3 -139
  172. package/dist/telemetry-runtime.d.mts +42 -0
  173. package/dist/telemetry-runtime.mjs +238 -0
  174. package/dist/telemetry.d.mts +15 -0
  175. package/dist/telemetry.mjs +117 -0
  176. package/dist/{types-BJFeMXWZ.d.mts → types.d.mts} +3 -2
  177. package/dist/urls.d.mts +7 -0
  178. package/dist/urls.mjs +21 -0
  179. package/dist/utils.d.mts +8 -0
  180. package/dist/utils.mjs +22 -0
  181. package/package.json +21 -3
  182. package/dist/agent-DkAidqtV.mjs +0 -9026
  183. package/dist/api-reference-BYee4zMo.mjs +0 -3046
  184. package/dist/prompt-references-DMgbu_dz.mjs +0 -1082
  185. package/dist/retrieval-digest-AOx2-LbC.d.mts +0 -367
  186. package/dist/sidebar-CFHBj29f.mjs +0 -421
  187. package/dist/sidebar-CMPbVfGP.d.mts +0 -63
  188. /package/dist/{openapi-CfCzX_a1.mjs → cli/openapi.mjs} +0 -0
@@ -0,0 +1,47 @@
1
+ import { DocsAgentContentChangesConfig, DocsContentChangesResponse, DocsSearchConfig, DocsSearchSourcePage } from "./types.mjs";
2
+ import { BuildDocsContentSnapshotOptions } from "./search.mjs";
3
+
4
+ //#region src/content-changes.d.ts
5
+ declare const DOCS_CONTENT_CHANGES_FORMAT = "docs-content-changes.v1";
6
+ declare const DOCS_CONTENT_SNAPSHOT_FORMAT = "docs-content-snapshot.v1";
7
+ declare const DOCS_CONTENT_CHANGES_RESPONSE_VALUE = "changes";
8
+ /** Whether a value is a valid content-index generation identifier. */
9
+ declare function isDocsContentChangeGeneration(value: string): boolean;
10
+ interface DocsContentChangesRequest {
11
+ audience: "human" | "agent";
12
+ since?: string;
13
+ }
14
+ interface DocsResolvedContentChangesConfig {
15
+ enabled: boolean;
16
+ maxSnapshots: number;
17
+ loadSnapshot?: DocsAgentContentChangesConfig["loadSnapshot"];
18
+ saveSnapshot?: DocsAgentContentChangesConfig["saveSnapshot"];
19
+ }
20
+ interface ResolveDocsContentChangesOptions extends Omit<BuildDocsContentSnapshotOptions, "pages"> {
21
+ pages: readonly DocsSearchSourcePage[];
22
+ since?: string;
23
+ request?: Request;
24
+ }
25
+ interface DocsContentChangeFeed {
26
+ resolve(options: ResolveDocsContentChangesOptions): Promise<DocsContentChangesResponse>;
27
+ }
28
+ declare class DocsContentChangesRequestError extends Error {
29
+ readonly code = "invalid_content_changes_request";
30
+ constructor(message: string);
31
+ }
32
+ declare function resolveDocsContentChangesConfig(input?: boolean | DocsAgentContentChangesConfig, options?: {
33
+ staticExport?: boolean;
34
+ }): DocsResolvedContentChangesConfig;
35
+ declare function isDocsContentChangesRequest(url: URL): boolean;
36
+ declare function resolveDocsContentChangesRequest(url: URL): DocsContentChangesRequest;
37
+ declare function createDocsContentChangeFeed(input?: boolean | DocsAgentContentChangesConfig): DocsContentChangeFeed;
38
+ declare function createDocsContentChangesHttpResponse(options: {
39
+ request: Request;
40
+ feed: DocsContentChangeFeed;
41
+ pages: readonly DocsSearchSourcePage[];
42
+ search?: boolean | DocsSearchConfig;
43
+ locale?: string;
44
+ baseUrl?: string;
45
+ }): Promise<Response>;
46
+ //#endregion
47
+ export { DOCS_CONTENT_CHANGES_FORMAT, DOCS_CONTENT_CHANGES_RESPONSE_VALUE, DOCS_CONTENT_SNAPSHOT_FORMAT, DocsContentChangeFeed, DocsContentChangesRequest, DocsContentChangesRequestError, DocsResolvedContentChangesConfig, ResolveDocsContentChangesOptions, createDocsContentChangeFeed, createDocsContentChangesHttpResponse, isDocsContentChangeGeneration, isDocsContentChangesRequest, resolveDocsContentChangesConfig, resolveDocsContentChangesRequest };
@@ -0,0 +1,216 @@
1
+ import { digestDocsRetrievalContent, isDocsRetrievalCanonicalUrl } from "./retrieval-digest.mjs";
2
+ import { buildDocsContentSnapshot } from "./search.mjs";
3
+
4
+ //#region src/content-changes.ts
5
+ const DOCS_CONTENT_CHANGES_FORMAT = "docs-content-changes.v1";
6
+ const DOCS_CONTENT_SNAPSHOT_FORMAT = "docs-content-snapshot.v1";
7
+ const DOCS_CONTENT_CHANGES_RESPONSE_VALUE = "changes";
8
+ const DEFAULT_DOCS_CONTENT_CHANGE_SNAPSHOTS = 8;
9
+ const MAX_DOCS_CONTENT_CHANGE_SNAPSHOTS = 64;
10
+ const DOCS_RETRIEVAL_DIGEST_PATTERN = /^sha256:[a-f\d]{64}$/u;
11
+ /** Whether a value is a valid content-index generation identifier. */
12
+ function isDocsContentChangeGeneration(value) {
13
+ return DOCS_RETRIEVAL_DIGEST_PATTERN.test(value);
14
+ }
15
+ var DocsContentChangesRequestError = class extends Error {
16
+ code = "invalid_content_changes_request";
17
+ constructor(message) {
18
+ super(message);
19
+ this.name = "DocsContentChangesRequestError";
20
+ }
21
+ };
22
+ function resolveDocsContentChangesConfig(input, options = {}) {
23
+ const configured = input && typeof input === "object" ? input : void 0;
24
+ const enabled = !options.staticExport && input !== false && configured?.enabled !== false;
25
+ const requestedMax = configured?.maxSnapshots ?? DEFAULT_DOCS_CONTENT_CHANGE_SNAPSHOTS;
26
+ return {
27
+ enabled,
28
+ maxSnapshots: Number.isSafeInteger(requestedMax) && requestedMax >= 1 && requestedMax <= MAX_DOCS_CONTENT_CHANGE_SNAPSHOTS ? requestedMax : DEFAULT_DOCS_CONTENT_CHANGE_SNAPSHOTS,
29
+ ...configured?.loadSnapshot ? { loadSnapshot: configured.loadSnapshot } : {},
30
+ ...configured?.saveSnapshot ? { saveSnapshot: configured.saveSnapshot } : {}
31
+ };
32
+ }
33
+ function isDocsContentChangesRequest(url) {
34
+ return url.searchParams.get("response") === DOCS_CONTENT_CHANGES_RESPONSE_VALUE;
35
+ }
36
+ function resolveDocsContentChangesRequest(url) {
37
+ if (!isDocsContentChangesRequest(url)) throw new DocsContentChangesRequestError("Content changes require `response=changes`.");
38
+ const rawAudience = url.searchParams.get("audience");
39
+ if (rawAudience !== null && rawAudience !== "human" && rawAudience !== "agent") throw new DocsContentChangesRequestError("Content-change audience must be `human` or `agent`.");
40
+ const since = url.searchParams.get("since") ?? void 0;
41
+ if (since !== void 0 && !isDocsContentChangeGeneration(since)) throw new DocsContentChangesRequestError("Content-change `since` must be a SHA-256 index generation.");
42
+ return {
43
+ audience: rawAudience ?? "agent",
44
+ ...since ? { since } : {}
45
+ };
46
+ }
47
+ function snapshotScope(snapshot) {
48
+ return JSON.stringify({
49
+ audience: snapshot.audience,
50
+ locale: snapshot.locale,
51
+ baseUrl: snapshot.baseUrl
52
+ });
53
+ }
54
+ function snapshotKey(snapshot) {
55
+ return `${snapshotScope(snapshot)}\0${snapshot.indexGeneration}`;
56
+ }
57
+ function snapshotContext(snapshot, request) {
58
+ return {
59
+ audience: snapshot.audience,
60
+ ...snapshot.locale ? { locale: snapshot.locale } : {},
61
+ ...snapshot.baseUrl ? { baseUrl: snapshot.baseUrl } : {},
62
+ ...request ? { request } : {}
63
+ };
64
+ }
65
+ function isSnapshotDocument(value) {
66
+ if (!value || typeof value !== "object") return false;
67
+ const document = value;
68
+ return typeof document.url === "string" && document.url.length > 0 && typeof document.canonicalUrl === "string" && isDocsRetrievalCanonicalUrl(document.canonicalUrl) && typeof document.digest === "string" && DOCS_RETRIEVAL_DIGEST_PATTERN.test(document.digest) && (document.lastModified === void 0 || typeof document.lastModified === "string" && Number.isFinite(Date.parse(document.lastModified)));
69
+ }
70
+ function validateLoadedSnapshot(value, generation, current) {
71
+ if (value.format !== DOCS_CONTENT_SNAPSHOT_FORMAT || value.indexGeneration !== generation || !DOCS_RETRIEVAL_DIGEST_PATTERN.test(value.indexGeneration) || snapshotScope(value) !== snapshotScope(current) || !Array.isArray(value.documents) || !value.documents.every(isSnapshotDocument)) throw new TypeError("Content-change snapshot storage returned an invalid snapshot.");
72
+ const documents = value.documents.map((document) => ({ ...document }));
73
+ documents.sort((left, right) => left.canonicalUrl === right.canonicalUrl ? left.url.localeCompare(right.url) : left.canonicalUrl.localeCompare(right.canonicalUrl));
74
+ if (documents.some((document, index) => index > 0 && documents[index - 1]?.canonicalUrl === document.canonicalUrl)) throw new TypeError("Content-change snapshot storage returned duplicate canonical URLs.");
75
+ return {
76
+ ...value,
77
+ documents
78
+ };
79
+ }
80
+ function asChangeDocument(document) {
81
+ return { ...document };
82
+ }
83
+ function buildDelta(current, previous, since) {
84
+ const currentByUrl = new Map(current.documents.map((document) => [document.canonicalUrl, document]));
85
+ const previousByUrl = new Map(previous?.documents.map((document) => [document.canonicalUrl, document]) ?? []);
86
+ const added = [];
87
+ const changed = [];
88
+ const deleted = [];
89
+ if (!since || !previous) added.push(...current.documents.map(asChangeDocument));
90
+ else {
91
+ for (const document of current.documents) {
92
+ const old = previousByUrl.get(document.canonicalUrl);
93
+ if (!old) added.push(asChangeDocument(document));
94
+ else if (old.digest !== document.digest || old.lastModified !== document.lastModified || old.url !== document.url) changed.push({
95
+ ...asChangeDocument(document),
96
+ previousDigest: old.digest,
97
+ ...old.lastModified ? { previousLastModified: old.lastModified } : {}
98
+ });
99
+ }
100
+ for (const document of previous.documents) if (!currentByUrl.has(document.canonicalUrl)) deleted.push(asChangeDocument(document));
101
+ }
102
+ const mode = !since ? "snapshot" : previous ? "delta" : "reset";
103
+ return {
104
+ format: DOCS_CONTENT_CHANGES_FORMAT,
105
+ audience: current.audience,
106
+ ...current.locale ? { locale: current.locale } : {},
107
+ since: since ?? null,
108
+ indexGeneration: current.indexGeneration,
109
+ mode,
110
+ resetRequired: mode === "reset",
111
+ documentCount: current.documents.length,
112
+ counts: {
113
+ added: added.length,
114
+ changed: changed.length,
115
+ deleted: deleted.length
116
+ },
117
+ added,
118
+ changed,
119
+ deleted
120
+ };
121
+ }
122
+ function createDocsContentChangeFeed(input) {
123
+ const config = resolveDocsContentChangesConfig(input);
124
+ const snapshots = /* @__PURE__ */ new Map();
125
+ const saved = /* @__PURE__ */ new Set();
126
+ const remember = (snapshot) => {
127
+ const key = snapshotKey(snapshot);
128
+ snapshots.delete(key);
129
+ snapshots.set(key, snapshot);
130
+ while (snapshots.size > config.maxSnapshots) {
131
+ const oldest = snapshots.keys().next().value;
132
+ if (!oldest) break;
133
+ snapshots.delete(oldest);
134
+ saved.delete(oldest);
135
+ }
136
+ };
137
+ return { async resolve(options) {
138
+ if (!config.enabled) throw new DocsContentChangesRequestError("Content changes are disabled.");
139
+ const current = await buildDocsContentSnapshot(options);
140
+ const currentKey = snapshotKey(current);
141
+ let previous;
142
+ if (options.since === current.indexGeneration) previous = current;
143
+ else if (options.since) {
144
+ const scopedKey = `${snapshotScope(current)}\0${options.since}`;
145
+ previous = snapshots.get(scopedKey);
146
+ if (!previous && config.loadSnapshot) {
147
+ const loaded = await config.loadSnapshot(options.since, snapshotContext(current, options.request));
148
+ if (loaded) {
149
+ previous = validateLoadedSnapshot(loaded, options.since, current);
150
+ remember(previous);
151
+ }
152
+ }
153
+ }
154
+ remember(current);
155
+ if (config.saveSnapshot && !saved.has(currentKey)) {
156
+ await config.saveSnapshot({
157
+ ...current,
158
+ documents: current.documents.map((document) => ({ ...document }))
159
+ }, snapshotContext(current, options.request));
160
+ saved.add(currentKey);
161
+ }
162
+ return buildDelta(current, previous, options.since);
163
+ } };
164
+ }
165
+ function contentChangesEtag(response) {
166
+ return `"${digestDocsRetrievalContent(JSON.stringify([
167
+ response.format,
168
+ response.audience,
169
+ response.locale ?? null,
170
+ response.since,
171
+ response.indexGeneration,
172
+ response.mode
173
+ ]))}"`;
174
+ }
175
+ function requestMatchesEtag(request, etag) {
176
+ const header = request.headers.get("if-none-match");
177
+ if (!header) return false;
178
+ return header.split(",").map((value) => value.trim().replace(/^W\//u, "")).some((value) => value === "*" || value === etag);
179
+ }
180
+ async function createDocsContentChangesHttpResponse(options) {
181
+ let resolved;
182
+ try {
183
+ resolved = resolveDocsContentChangesRequest(new URL(options.request.url));
184
+ } catch (error) {
185
+ if (!(error instanceof DocsContentChangesRequestError)) throw error;
186
+ return Response.json({ error: {
187
+ code: error.code,
188
+ message: error.message
189
+ } }, { status: 400 });
190
+ }
191
+ const response = await options.feed.resolve({
192
+ pages: options.pages,
193
+ search: options.search,
194
+ audience: resolved.audience,
195
+ locale: options.locale,
196
+ baseUrl: options.baseUrl,
197
+ since: resolved.since,
198
+ request: options.request
199
+ });
200
+ const etag = contentChangesEtag(response);
201
+ const headers = {
202
+ "Cache-Control": "public, max-age=0, s-maxage=60, stale-while-revalidate=300",
203
+ ETag: etag,
204
+ "X-Docs-Index-Generation": response.indexGeneration,
205
+ "X-Robots-Tag": "noindex"
206
+ };
207
+ if (requestMatchesEtag(options.request, etag)) return new Response(null, {
208
+ status: 304,
209
+ headers
210
+ });
211
+ if (options.request.method.toUpperCase() === "HEAD") return new Response(null, { headers });
212
+ return Response.json(response, { headers });
213
+ }
214
+
215
+ //#endregion
216
+ export { DOCS_CONTENT_CHANGES_FORMAT, DOCS_CONTENT_CHANGES_RESPONSE_VALUE, DOCS_CONTENT_SNAPSHOT_FORMAT, DocsContentChangesRequestError, createDocsContentChangeFeed, createDocsContentChangesHttpResponse, isDocsContentChangeGeneration, isDocsContentChangesRequest, resolveDocsContentChangesConfig, resolveDocsContentChangesRequest };
@@ -0,0 +1,48 @@
1
+ import { DocsTheme } from "./types.mjs";
2
+
3
+ //#region src/create-theme.d.ts
4
+ /**
5
+ * Create a theme preset factory.
6
+ *
7
+ * Returns a function that accepts optional overrides and deep-merges them
8
+ * with the base theme defaults. This is the same pattern used by the
9
+ * built-in `fumadocs()`, `darksharp()`, and `pixelBorder()` presets.
10
+ *
11
+ * @param baseTheme - The default theme configuration
12
+ * @returns A factory function `(overrides?) => DocsTheme`
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { createTheme } from "@farming-labs/docs";
17
+ *
18
+ * export const myTheme = createTheme({
19
+ * name: "my-theme",
20
+ * ui: {
21
+ * colors: { primary: "#6366f1" },
22
+ * layout: { contentWidth: 800 },
23
+ * },
24
+ * });
25
+ * ```
26
+ */
27
+ declare function createTheme(baseTheme: DocsTheme): (overrides?: Partial<DocsTheme>) => DocsTheme;
28
+ /**
29
+ * Extend an existing theme preset with additional defaults.
30
+ *
31
+ * Useful when you want to build on top of an existing theme (e.g. fumadocs)
32
+ * rather than starting from scratch.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * import { extendTheme } from "@farming-labs/docs";
37
+ * import { fumadocs } from "@farming-labs/theme/default";
38
+ *
39
+ * // Start with fumadocs defaults, override some values
40
+ * export const myTheme = extendTheme(fumadocs(), {
41
+ * name: "my-custom-fumadocs",
42
+ * ui: { colors: { primary: "#22c55e" } },
43
+ * });
44
+ * ```
45
+ */
46
+ declare function extendTheme(baseTheme: DocsTheme, extensions: Partial<DocsTheme>): DocsTheme;
47
+ //#endregion
48
+ export { createTheme, extendTheme };
@@ -0,0 +1,57 @@
1
+ import { deepMerge } from "./utils.mjs";
2
+
3
+ //#region src/create-theme.ts
4
+ /**
5
+ * Create a theme preset factory.
6
+ *
7
+ * Returns a function that accepts optional overrides and deep-merges them
8
+ * with the base theme defaults. This is the same pattern used by the
9
+ * built-in `fumadocs()`, `darksharp()`, and `pixelBorder()` presets.
10
+ *
11
+ * @param baseTheme - The default theme configuration
12
+ * @returns A factory function `(overrides?) => DocsTheme`
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * import { createTheme } from "@farming-labs/docs";
17
+ *
18
+ * export const myTheme = createTheme({
19
+ * name: "my-theme",
20
+ * ui: {
21
+ * colors: { primary: "#6366f1" },
22
+ * layout: { contentWidth: 800 },
23
+ * },
24
+ * });
25
+ * ```
26
+ */
27
+ function createTheme(baseTheme) {
28
+ return function themeFactory(overrides = {}) {
29
+ const merged = deepMerge(baseTheme, overrides);
30
+ if (overrides.ui?.colors) merged._userColorOverrides = { ...overrides.ui.colors };
31
+ return merged;
32
+ };
33
+ }
34
+ /**
35
+ * Extend an existing theme preset with additional defaults.
36
+ *
37
+ * Useful when you want to build on top of an existing theme (e.g. fumadocs)
38
+ * rather than starting from scratch.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { extendTheme } from "@farming-labs/docs";
43
+ * import { fumadocs } from "@farming-labs/theme/default";
44
+ *
45
+ * // Start with fumadocs defaults, override some values
46
+ * export const myTheme = extendTheme(fumadocs(), {
47
+ * name: "my-custom-fumadocs",
48
+ * ui: { colors: { primary: "#22c55e" } },
49
+ * });
50
+ * ```
51
+ */
52
+ function extendTheme(baseTheme, extensions) {
53
+ return deepMerge(baseTheme, extensions);
54
+ }
55
+
56
+ //#endregion
57
+ export { createTheme, extendTheme };
@@ -0,0 +1,5 @@
1
+ //#region src/date.d.ts
2
+ /** Formats docs timestamps without allowing the deployment timezone to change the calendar day. */
3
+ declare function formatDocsLastModifiedDate(value: string | Date): string | undefined;
4
+ //#endregion
5
+ export { formatDocsLastModifiedDate };
package/dist/date.mjs ADDED
@@ -0,0 +1,17 @@
1
+ //#region src/date.ts
2
+ const DATE_ONLY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
3
+ /** Formats docs timestamps without allowing the deployment timezone to change the calendar day. */
4
+ function formatDocsLastModifiedDate(value) {
5
+ const normalized = typeof value === "string" && DATE_ONLY_PATTERN.test(value) ? `${value}T00:00:00.000Z` : value;
6
+ const date = normalized instanceof Date ? normalized : new Date(normalized);
7
+ if (Number.isNaN(date.getTime())) return void 0;
8
+ return date.toLocaleDateString("en-US", {
9
+ year: "numeric",
10
+ month: "long",
11
+ day: "numeric",
12
+ timeZone: "UTC"
13
+ });
14
+ }
15
+
16
+ //#endregion
17
+ export { formatDocsLastModifiedDate };
@@ -0,0 +1,9 @@
1
+ import { DocsConfig } from "./types.mjs";
2
+
3
+ //#region src/define-docs.d.ts
4
+ /**
5
+ * Define docs configuration. Validates and returns the config.
6
+ */
7
+ declare function defineDocs(config: DocsConfig): DocsConfig;
8
+ //#endregion
9
+ export { defineDocs };
@@ -0,0 +1,46 @@
1
+ //#region src/define-docs.ts
2
+ /**
3
+ * Define docs configuration. Validates and returns the config.
4
+ */
5
+ function defineDocs(config) {
6
+ return {
7
+ entry: config.entry ?? "docs",
8
+ docsPath: config.docsPath,
9
+ contentDir: config.contentDir,
10
+ i18n: config.i18n,
11
+ theme: config.theme,
12
+ nav: config.nav,
13
+ github: config.github,
14
+ themeToggle: config.themeToggle,
15
+ breadcrumb: config.breadcrumb,
16
+ sidebar: config.sidebar,
17
+ components: config.components,
18
+ analytics: config.analytics,
19
+ telemetry: config.telemetry,
20
+ cloud: config.cloud,
21
+ observability: config.observability,
22
+ onCopyClick: config.onCopyClick,
23
+ codeBlocks: config.codeBlocks,
24
+ feedback: config.feedback,
25
+ search: config.search,
26
+ mcp: config.mcp,
27
+ icons: config.icons,
28
+ pageActions: config.pageActions,
29
+ lastUpdated: config.lastUpdated,
30
+ readingTime: config.readingTime,
31
+ llmsTxt: config.llmsTxt,
32
+ sitemap: config.sitemap,
33
+ robots: config.robots,
34
+ ai: config.ai,
35
+ ordering: config.ordering,
36
+ metadata: config.metadata,
37
+ og: config.og,
38
+ changelog: config.changelog,
39
+ apiReference: config.apiReference,
40
+ agent: config.agent,
41
+ review: config.review
42
+ };
43
+ }
44
+
45
+ //#endregion
46
+ export { defineDocs };
@@ -0,0 +1,18 @@
1
+ //#region src/docs-cloud-client.d.ts
2
+ type DocsCloudClientRuntimeValue<T = string> = T | undefined | null | (() => T | undefined | null);
3
+ type DocsCloudClientRuntimeEnv = Record<string, string | undefined> | (() => Record<string, string | undefined>);
4
+ interface DocsCloudClientOptions {
5
+ projectId?: DocsCloudClientRuntimeValue;
6
+ endpoint?: DocsCloudClientRuntimeValue;
7
+ analyticsEndpoint?: DocsCloudClientRuntimeValue;
8
+ apiBaseUrl?: DocsCloudClientRuntimeValue;
9
+ analyticsKey?: DocsCloudClientRuntimeValue;
10
+ enabled?: DocsCloudClientRuntimeValue<boolean | string>;
11
+ includeInputs?: DocsCloudClientRuntimeValue<boolean>;
12
+ env?: DocsCloudClientRuntimeEnv;
13
+ fetch?: typeof fetch;
14
+ metadata?: Record<string, unknown>;
15
+ properties?: Record<string, unknown>;
16
+ }
17
+ //#endregion
18
+ export { DocsCloudClientOptions, DocsCloudClientRuntimeValue };
@@ -0,0 +1,161 @@
1
+ "use client";
2
+
3
+ import { sendDocsCloudAnalyticsEvent } from "./cloud-analytics.mjs";
4
+
5
+ //#region src/docs-cloud-client.ts
6
+ const DEFAULT_DOCS_CLOUD_API_BASE_URL = "https://api.farming-labs.dev";
7
+ const DOCS_CLOUD_PROJECT_ID_ENVS = [
8
+ "NEXT_PUBLIC_DOCS_CLOUD_PROJECT_ID",
9
+ "PUBLIC_DOCS_CLOUD_PROJECT_ID",
10
+ "DOCS_CLOUD_PROJECT_ID"
11
+ ];
12
+ const DOCS_CLOUD_API_BASE_URL_ENVS = [
13
+ "NEXT_PUBLIC_DOCS_CLOUD_URL",
14
+ "PUBLIC_DOCS_CLOUD_URL",
15
+ "DOCS_CLOUD_API_BASE_URL",
16
+ "DOCS_CLOUD_API_URL"
17
+ ];
18
+ const DOCS_CLOUD_ANALYTICS_ENDPOINT_ENVS = [
19
+ "NEXT_PUBLIC_DOCS_CLOUD_ANALYTICS_ENDPOINT",
20
+ "PUBLIC_DOCS_CLOUD_ANALYTICS_ENDPOINT",
21
+ "DOCS_CLOUD_ANALYTICS_ENDPOINT"
22
+ ];
23
+ const DOCS_CLOUD_ANALYTICS_ENABLED_ENVS = [
24
+ "NEXT_PUBLIC_DOCS_CLOUD_ANALYTICS_ENABLED",
25
+ "PUBLIC_DOCS_CLOUD_ANALYTICS_ENABLED",
26
+ "DOCS_CLOUD_ANALYTICS_ENABLED"
27
+ ];
28
+ const DOCS_CLOUD_ANALYTICS_KEY_ENVS = [
29
+ "NEXT_PUBLIC_DOCS_CLOUD_ANALYTICS_KEY",
30
+ "PUBLIC_DOCS_CLOUD_ANALYTICS_KEY",
31
+ "DOCS_CLOUD_ANALYTICS_KEY"
32
+ ];
33
+ function normalizeRuntimeString(value) {
34
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
35
+ }
36
+ function resolveRuntimeValue(value) {
37
+ return (typeof value === "function" ? value() : value) ?? void 0;
38
+ }
39
+ function resolveRuntimeString(value) {
40
+ return normalizeRuntimeString(resolveRuntimeValue(value));
41
+ }
42
+ function resolveRuntimeEnv(env) {
43
+ return typeof env === "function" ? env() : env ?? {};
44
+ }
45
+ function readProcessEnv(name) {
46
+ if (typeof process === "undefined") return void 0;
47
+ if (!process.env) return void 0;
48
+ switch (name) {
49
+ case "NEXT_PUBLIC_DOCS_CLOUD_PROJECT_ID": return normalizeRuntimeString(process.env.NEXT_PUBLIC_DOCS_CLOUD_PROJECT_ID);
50
+ case "NEXT_PUBLIC_DOCS_CLOUD_URL": return normalizeRuntimeString(process.env.NEXT_PUBLIC_DOCS_CLOUD_URL);
51
+ case "NEXT_PUBLIC_DOCS_CLOUD_ANALYTICS_ENDPOINT": return normalizeRuntimeString(process.env.NEXT_PUBLIC_DOCS_CLOUD_ANALYTICS_ENDPOINT);
52
+ case "NEXT_PUBLIC_DOCS_CLOUD_ANALYTICS_ENABLED": return normalizeRuntimeString(process.env.NEXT_PUBLIC_DOCS_CLOUD_ANALYTICS_ENABLED);
53
+ case "NEXT_PUBLIC_DOCS_CLOUD_ANALYTICS_KEY": return normalizeRuntimeString(process.env.NEXT_PUBLIC_DOCS_CLOUD_ANALYTICS_KEY);
54
+ default: return;
55
+ }
56
+ }
57
+ function readEnv(name, env) {
58
+ return normalizeRuntimeString(env[name]) ?? readProcessEnv(name);
59
+ }
60
+ function readFirstEnv(names, env) {
61
+ for (const name of names) {
62
+ const value = readEnv(name, env);
63
+ if (value) return value;
64
+ }
65
+ }
66
+ function isFalsy(value) {
67
+ if (value === false) return true;
68
+ if (typeof value !== "string") return false;
69
+ return /^(0|false|no|off)$/i.test(value.trim());
70
+ }
71
+ function stripTrailingSlash(value) {
72
+ return value.replace(/\/+$/, "");
73
+ }
74
+ function mergeRecords(...records) {
75
+ const merged = {};
76
+ for (const record of records) {
77
+ if (!record) continue;
78
+ Object.assign(merged, record);
79
+ }
80
+ return Object.keys(merged).length > 0 ? merged : void 0;
81
+ }
82
+ function getBrowserLocation() {
83
+ return typeof window !== "undefined" ? window.location : void 0;
84
+ }
85
+ function getBrowserReferrer() {
86
+ if (typeof document === "undefined") return void 0;
87
+ return document.referrer || void 0;
88
+ }
89
+ function createDocsCloudClient(options = {}) {
90
+ function env() {
91
+ return resolveRuntimeEnv(options.env);
92
+ }
93
+ function projectId() {
94
+ const runtimeEnv = env();
95
+ return resolveRuntimeString(options.projectId) ?? readFirstEnv(DOCS_CLOUD_PROJECT_ID_ENVS, runtimeEnv);
96
+ }
97
+ function apiBaseUrl() {
98
+ const runtimeEnv = env();
99
+ return stripTrailingSlash(resolveRuntimeString(options.apiBaseUrl) ?? readFirstEnv(DOCS_CLOUD_API_BASE_URL_ENVS, runtimeEnv) ?? DEFAULT_DOCS_CLOUD_API_BASE_URL);
100
+ }
101
+ function endpoint() {
102
+ const runtimeEnv = env();
103
+ return resolveRuntimeString(options.endpoint) ?? resolveRuntimeString(options.analyticsEndpoint) ?? readFirstEnv(DOCS_CLOUD_ANALYTICS_ENDPOINT_ENVS, runtimeEnv) ?? `${apiBaseUrl()}/v1/analytics/events`;
104
+ }
105
+ function analyticsKey() {
106
+ const runtimeEnv = env();
107
+ return resolveRuntimeString(options.analyticsKey) ?? readFirstEnv(DOCS_CLOUD_ANALYTICS_KEY_ENVS, runtimeEnv);
108
+ }
109
+ function enabled() {
110
+ const runtimeEnv = env();
111
+ return !isFalsy(resolveRuntimeValue(options.enabled) ?? readFirstEnv(DOCS_CLOUD_ANALYTICS_ENABLED_ENVS, runtimeEnv));
112
+ }
113
+ function includeInputs() {
114
+ return resolveRuntimeValue(options.includeInputs) === true;
115
+ }
116
+ function getConfig() {
117
+ const id = projectId();
118
+ return {
119
+ enabled: enabled(),
120
+ configured: Boolean(id),
121
+ ...id ? { projectId: id } : {},
122
+ endpoint: endpoint()
123
+ };
124
+ }
125
+ async function trackEvent(event, trackOptions = {}) {
126
+ const config = getConfig();
127
+ if (!config.enabled || !config.projectId) return false;
128
+ const location = getBrowserLocation();
129
+ const normalized = {
130
+ ...event,
131
+ source: event.source ?? "client",
132
+ timestamp: event.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
133
+ url: event.url ?? location?.href,
134
+ path: event.path ?? location?.pathname,
135
+ referrer: event.referrer ?? getBrowserReferrer(),
136
+ locale: event.locale ?? trackOptions.locale,
137
+ metadata: mergeRecords(options.metadata, trackOptions.metadata, event.metadata),
138
+ properties: mergeRecords(options.properties, trackOptions.properties, event.properties)
139
+ };
140
+ if (!includeInputs()) delete normalized.input;
141
+ await sendDocsCloudAnalyticsEvent({
142
+ endpoint: config.endpoint,
143
+ projectId: config.projectId,
144
+ apiKey: analyticsKey(),
145
+ fetch: options.fetch
146
+ }, normalized);
147
+ return true;
148
+ }
149
+ return {
150
+ analytics: { track: trackEvent },
151
+ trackEvent,
152
+ getConfig,
153
+ isConfigured() {
154
+ const config = getConfig();
155
+ return config.enabled && config.configured;
156
+ }
157
+ };
158
+ }
159
+
160
+ //#endregion
161
+ export { createDocsCloudClient };
@@ -1,5 +1,5 @@
1
- import { bt as DocsAnalyticsEventInput, vt as DocsAnalyticsConfig, yt as DocsAnalyticsEvent } from "./types-BJFeMXWZ.mjs";
2
- import { n as DocsCloudAskAIResponseOptions, t as DocsCloudAskAIConfig } from "./cloud-ask-ai-BrsTXQf6.mjs";
1
+ import { DocsAnalyticsConfig, DocsAnalyticsEvent, DocsAnalyticsEventInput } from "./types.mjs";
2
+ import { DocsCloudAskAIConfig, DocsCloudAskAIResponseOptions } from "./cloud-ask-ai.mjs";
3
3
 
4
4
  //#region src/docs-cloud-server.d.ts
5
5
  type DocsCloudRuntimeValue<T = string> = T | undefined | null | (() => T | undefined | null);
@@ -1,6 +1,5 @@
1
- import "./http-body-DkAPk6D5.mjs";
2
- import { n as sendDocsCloudAnalyticsEvent } from "./cloud-analytics-D14HplI7.mjs";
3
- import { t as createDocsCloudAskAIResponse } from "./cloud-ask-ai-BqKhjpS5.mjs";
1
+ import { sendDocsCloudAnalyticsEvent } from "./cloud-analytics.mjs";
2
+ import { createDocsCloudAskAIResponse } from "./cloud-ask-ai.mjs";
4
3
 
5
4
  //#region src/docs-cloud-server.ts
6
5
  const DEFAULT_DOCS_CLOUD_API_BASE_URL = "https://api.farming-labs.dev";
@@ -0,0 +1,10 @@
1
+ //#region src/heading-toc.d.ts
2
+ /**
3
+ * Encode heading fragments emitted by a renderer's nested table of contents.
4
+ *
5
+ * Fumadocs stores fragment URLs as raw DOM ids. Encoding the fragment after its
6
+ * heading visitor runs keeps links valid without changing path prefixes.
7
+ */
8
+ declare function encodeDocsHeadingTocUrls(value: unknown): void;
9
+ //#endregion
10
+ export { encodeDocsHeadingTocUrls };