@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.
- package/README.md +8 -0
- package/dist/access.d.mts +13 -0
- package/dist/access.mjs +56 -0
- package/dist/agent-conformance.d.mts +60 -0
- package/dist/agent-conformance.mjs +538 -0
- package/dist/agent-contract.d.mts +47 -0
- package/dist/agent-contract.mjs +645 -0
- package/dist/agent-detection.d.mts +6 -0
- package/dist/agent-detection.mjs +83 -0
- package/dist/agent-evals.d.mts +224 -0
- package/dist/{agent-evals-BLNLvXbG.mjs → agent-evals.mjs} +7 -565
- package/dist/agent-feedback-evaluations-node.mjs +38 -0
- package/dist/agent-feedback-evaluations.d.mts +91 -0
- package/dist/{agent-feedback-evaluations-CcMGlgsO.mjs → agent-feedback-evaluations.mjs} +2 -2
- package/dist/agent-feedback-loop.d.mts +45 -0
- package/dist/{agent-feedback-loop-CcZL_sb1.mjs → agent-feedback-loop.mjs} +1 -1
- package/dist/agent-maintenance.d.mts +71 -0
- package/dist/{agent-maintenance-CuZ7iAKq.mjs → agent-maintenance.mjs} +1 -1
- package/dist/agent-provenance.d.mts +23 -0
- package/dist/agent-provenance.mjs +77 -0
- package/dist/agent-scope.mjs +321 -0
- package/dist/agent-skills-archive.mjs +86 -0
- package/dist/agent-skills-bundle.d.mts +1 -1
- package/dist/{agent-skills-progressive-disclosure-PjPtTYL-.mjs → agent-skills-progressive-disclosure.mjs} +2 -2
- package/dist/{agent-skills-server-D5IuvwM7.d.mts → agent-skills-server.d.mts} +3 -3
- package/dist/{agent-skills-server-BC7md56k.mjs → agent-skills-server.mjs} +2 -2
- package/dist/agent-skills-vite.d.mts +3 -3
- package/dist/agent-skills-vite.mjs +1 -2
- package/dist/agent-surface-drift.mjs +236 -0
- package/dist/{golden-evaluations-CLUViycJ.mjs → agent-usefulness.mjs} +5 -290
- package/dist/{content-change-hydration-wqXIZHp6.d.mts → agent.d.mts} +10 -411
- package/dist/agent.mjs +2729 -0
- package/dist/{analytics-w3FDOksr.d.mts → analytics.d.mts} +2 -2
- package/dist/{analytics-p8Vhhu2P.mjs → analytics.mjs} +2 -2
- package/dist/{sitemap-server-BUdPBcGs.d.mts → api-reference.d.mts} +2 -6
- package/dist/api-reference.mjs +1481 -0
- package/dist/{audience-exposure-DBrFWULA.d.mts → audience-exposure.d.mts} +1 -1
- package/dist/audience-exposure.mjs +8 -0
- package/dist/audience.d.mts +44 -0
- package/dist/audience.mjs +1654 -0
- package/dist/authoring-mcp.d.mts +44 -0
- package/dist/{authoring-mcp-CiCUQe3o.mjs → authoring-mcp.mjs} +3 -3
- package/dist/browser.d.mts +6 -4
- package/dist/browser.mjs +6 -7
- package/dist/build.d.mts +8 -0
- package/dist/build.mjs +8 -0
- package/dist/changelog.d.mts +20 -0
- package/dist/changelog.mjs +39 -0
- package/dist/{agent-export-CA6IUQ7T.mjs → cli/agent-export.mjs} +19 -45
- package/dist/{agent-CYk2DxY7.mjs → cli/agent.mjs} +6 -35
- package/dist/{agents-BUiVmj8i.mjs → cli/agents.mjs} +5 -18
- package/dist/cli/api-doctor.mjs +206 -0
- package/dist/{authoring-C2ymvYWl.mjs → cli/authoring.mjs} +2 -8
- package/dist/{cloud-6eKrlmKd.mjs → cli/cloud.mjs} +3 -3
- package/dist/{codeblocks-CHpgAwY-.mjs → cli/codeblocks.mjs} +2 -2
- package/dist/cli/config.d.mts +11 -0
- package/dist/{config-BZnKAj_Y.mjs → cli/config.mjs} +1 -1
- package/dist/cli/dev-banner.mjs +58 -0
- package/dist/{dev-Bnn-NUNa.mjs → cli/dev.mjs} +3 -57
- package/dist/{doctor-Bfkrkzad.mjs → cli/doctor.mjs} +41 -226
- package/dist/{downgrade-CHMta85e.mjs → cli/downgrade.mjs} +2 -2
- package/dist/cli/errors.d.mts +4 -0
- package/dist/{errors-BtnVLhNF.mjs → cli/errors.mjs} +1 -1
- package/dist/{feedback-evals-DMilg9pY.mjs → cli/feedback-evals.mjs} +3 -36
- package/dist/{feedback-DL4T5oIO.mjs → cli/feedback.mjs} +1 -1
- package/dist/cli/git-dates.mjs +35 -0
- package/dist/cli/golden-evaluations.mjs +52 -0
- package/dist/cli/index.d.mts +2 -3
- package/dist/cli/index.mjs +38 -38
- package/dist/{init-K0LmXDZ5.mjs → cli/init.mjs} +3 -3
- package/dist/{mcp-iLCmnPJI.mjs → cli/mcp.mjs} +7 -19
- package/dist/{openapi-diff-HcpUNjA-.mjs → cli/openapi-diff.mjs} +2 -7
- package/dist/{openapi-sdk-BQKC6H-_.mjs → cli/openapi-sdk.mjs} +2 -7
- package/dist/{openapi-source-DK6ts_Bk.mjs → cli/openapi-source.mjs} +2 -2
- package/dist/{package-version-HJhYeq4M.mjs → cli/package-version.mjs} +2 -2
- package/dist/{propose-JmUv_BTt.mjs → cli/propose.mjs} +1 -1
- package/dist/{review-C6EmbV0l.mjs → cli/review.mjs} +16 -15
- package/dist/{robots-DteZB8vl.mjs → cli/robots.mjs} +3 -7
- package/dist/{search-Bhuv_YsL.mjs → cli/search.mjs} +7 -20
- package/dist/{sitemap-DW5LDKDa.mjs → cli/sitemap.mjs} +7 -42
- package/dist/{skills-BAPQLSCm.mjs → cli/skills.mjs} +5 -19
- package/dist/{templates-BuQ8YsGv.mjs → cli/templates.mjs} +1 -1
- package/dist/{upgrade-DlQMOFV1.mjs → cli/upgrade.mjs} +2 -2
- package/dist/{utils-C7KDrPpA.mjs → cli/utils.mjs} +1 -1
- package/dist/client/react.d.mts +2 -18
- package/dist/client/react.mjs +1 -157
- package/dist/{cloud-analytics-D14HplI7.mjs → cloud-analytics.mjs} +1 -1
- package/dist/{cloud-ask-ai-BrsTXQf6.d.mts → cloud-ask-ai.d.mts} +2 -2
- package/dist/{cloud-ask-ai-BqKhjpS5.mjs → cloud-ask-ai.mjs} +3 -3
- package/dist/code-blocks.d.mts +51 -0
- package/dist/{code-blocks-GYdvS3BH.mjs → code-blocks.mjs} +2 -2
- package/dist/code-group-mdx.d.mts +11 -0
- package/dist/code-group-mdx.mjs +57 -0
- package/dist/content-change-hydration.d.mts +87 -0
- package/dist/{openapi-mcp-BIOTLiA7.mjs → content-change-hydration.mjs} +5 -210
- package/dist/content-changes.d.mts +47 -0
- package/dist/content-changes.mjs +216 -0
- package/dist/create-theme.d.mts +48 -0
- package/dist/create-theme.mjs +57 -0
- package/dist/date.d.mts +5 -0
- package/dist/date.mjs +17 -0
- package/dist/define-docs.d.mts +9 -0
- package/dist/define-docs.mjs +46 -0
- package/dist/docs-cloud-client.d.mts +18 -0
- package/dist/docs-cloud-client.mjs +161 -0
- package/dist/docs-cloud-server.d.mts +2 -2
- package/dist/docs-cloud-server.mjs +2 -3
- package/dist/heading-toc.d.mts +10 -0
- package/dist/heading-toc.mjs +23 -0
- package/dist/http-body.d.mts +14 -0
- package/dist/{http-body-DkAPk6D5.mjs → http-body.mjs} +1 -1
- package/dist/http-cache.d.mts +25 -0
- package/dist/http-cache.mjs +140 -0
- package/dist/http-link.mjs +81 -0
- package/dist/i18n.d.mts +18 -0
- package/dist/{i18n-B1gJ9EW0.mjs → i18n.mjs} +1 -1
- package/dist/index.d.mts +42 -674
- package/dist/index.mjs +40 -14
- package/dist/markdown-rendering.mjs +1 -1
- package/dist/markdown-section-cache.mjs +49 -0
- package/dist/markdown-sections.d.mts +47 -0
- package/dist/{markdown-sections-9Oxr33b-.mjs → markdown-sections.mjs} +29 -703
- package/dist/mcp-auth.d.mts +14 -0
- package/dist/mcp-auth.mjs +99 -0
- package/dist/mcp.d.mts +5 -3
- package/dist/mcp.mjs +21 -9
- package/dist/mdx.d.mts +6 -0
- package/dist/mdx.mjs +7 -0
- package/dist/metadata.d.mts +60 -0
- package/dist/{metadata-BOHn0Y5K.mjs → metadata.mjs} +2 -2
- package/dist/native-api-reference.mjs +968 -0
- package/dist/okf.d.mts +42 -0
- package/dist/okf.mjs +145 -0
- package/dist/openapi-contract.mjs +154 -0
- package/dist/{openapi-mcp-node-C4jUpZG6.mjs → openapi-mcp-node.mjs} +1 -1
- package/dist/openapi-mcp.d.mts +26 -0
- package/dist/openapi-mcp.mjs +132 -0
- package/dist/openapi-operations.d.mts +71 -0
- package/dist/{openapi-operations-DFpaqOqA.mjs → openapi-operations.mjs} +1 -1
- package/dist/openapi-overlays.mjs +221 -0
- package/dist/openapi-references.mjs +233 -0
- package/dist/pagination.d.mts +7 -0
- package/dist/pagination.mjs +100 -0
- package/dist/prompt-references.d.mts +12 -0
- package/dist/prompt-references.mjs +132 -0
- package/dist/prompt-utils.d.mts +36 -0
- package/dist/{prompt-utils-B5g-bv7o.mjs → prompt-utils.mjs} +1 -57
- package/dist/reading-time.d.mts +23 -0
- package/dist/reading-time.mjs +58 -0
- package/dist/related.d.mts +7 -0
- package/dist/related.mjs +50 -0
- package/dist/retrieval-digest.d.mts +16 -0
- package/dist/{retrieval-digest-CT-eIEcp.mjs → retrieval-digest.mjs} +1 -1
- package/dist/review.d.mts +69 -0
- package/dist/review.mjs +562 -0
- package/dist/robots.d.mts +54 -0
- package/dist/{robots-BYJAVeI6.mjs → robots.mjs} +5 -3
- package/dist/runtime.d.mts +3 -3
- package/dist/runtime.mjs +3 -9
- package/dist/search.d.mts +210 -0
- package/dist/search.mjs +3401 -0
- package/dist/server.d.mts +22 -198
- package/dist/server.mjs +21 -19
- package/dist/sidebar.d.mts +15 -0
- package/dist/sidebar.mjs +73 -0
- package/dist/sitemap-server.d.mts +7 -0
- package/dist/{sitemap-server-Lg3YhUx4.mjs → sitemap-server.mjs} +2 -2
- package/dist/{sitemap-Cl8vrixd.d.mts → sitemap.d.mts} +3 -3
- package/dist/sitemap.mjs +254 -0
- package/dist/{standards-discovery-BHPc7YIX.d.mts → standards-discovery.d.mts} +2 -2
- package/dist/{standards-discovery-sSEojU80.mjs → standards-discovery.mjs} +3 -139
- package/dist/telemetry-runtime.d.mts +42 -0
- package/dist/telemetry-runtime.mjs +238 -0
- package/dist/telemetry.d.mts +15 -0
- package/dist/telemetry.mjs +117 -0
- package/dist/{types-BJFeMXWZ.d.mts → types.d.mts} +3 -2
- package/dist/urls.d.mts +7 -0
- package/dist/urls.mjs +21 -0
- package/dist/utils.d.mts +8 -0
- package/dist/utils.mjs +22 -0
- package/package.json +21 -3
- package/dist/agent-DkAidqtV.mjs +0 -9026
- package/dist/api-reference-BYee4zMo.mjs +0 -3046
- package/dist/prompt-references-DMgbu_dz.mjs +0 -1082
- package/dist/retrieval-digest-AOx2-LbC.d.mts +0 -367
- package/dist/sidebar-CFHBj29f.mjs +0 -421
- package/dist/sidebar-CMPbVfGP.d.mts +0 -63
- /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 };
|
package/dist/date.d.mts
ADDED
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,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 {
|
|
2
|
-
import {
|
|
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 "./
|
|
2
|
-
import {
|
|
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 };
|