@apifn/docsfn 0.0.2 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.cjs ADDED
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/react/ApifnApiReference.tsx
21
+ var ApifnApiReference_exports = {};
22
+ __export(ApifnApiReference_exports, {
23
+ ApifnApiReference: () => ApifnApiReference
24
+ });
25
+ module.exports = __toCommonJS(ApifnApiReference_exports);
26
+ var import_react = require("react");
27
+ var import_react2 = require("@apifn/react");
28
+ var import_jsx_runtime = require("react/jsx-runtime");
29
+ var METHOD_COLORS = {
30
+ get: { bg: "#065f46", text: "#6ee7b7" },
31
+ post: { bg: "#1e3a5f", text: "#93c5fd" },
32
+ put: { bg: "#78350f", text: "#fcd34d" },
33
+ patch: { bg: "#5b21b6", text: "#c4b5fd" },
34
+ delete: { bg: "#7f1d1d", text: "#fca5a5" },
35
+ head: { bg: "#1f2937", text: "#9ca3af" },
36
+ options: { bg: "#1f2937", text: "#9ca3af" }
37
+ };
38
+ function getThemeStyle(theme) {
39
+ const dark = `
40
+ --apifn-bg:#0f1117;--apifn-bg-surface:#1a1d2e;--apifn-bg-surface-hover:#252840;
41
+ --apifn-border:#2d3748;--apifn-text:#e2e8f0;--apifn-text-muted:#64748b;
42
+ --apifn-accent:#7c3aed;--apifn-accent-text:#c4b5fd;--apifn-green:#6ee7b7;
43
+ --apifn-blue:#93c5fd;--apifn-yellow:#fcd34d;--apifn-red:#fca5a5;
44
+ --apifn-radius:6px;--apifn-font-mono:'JetBrains Mono',monospace;--apifn-font-sans:-apple-system,sans-serif
45
+ `;
46
+ const light = `
47
+ --apifn-bg:#ffffff;--apifn-bg-surface:#f8fafc;--apifn-bg-surface-hover:#f1f5f9;
48
+ --apifn-border:#e2e8f0;--apifn-text:#0f172a;--apifn-text-muted:#64748b;
49
+ --apifn-accent:#7c3aed;--apifn-accent-text:#6d28d9;--apifn-green:#059669;
50
+ --apifn-blue:#2563eb;--apifn-yellow:#d97706;--apifn-red:#dc2626;
51
+ --apifn-radius:6px;--apifn-font-mono:'JetBrains Mono',monospace;--apifn-font-sans:-apple-system,sans-serif
52
+ `;
53
+ if (theme === "dark") return `.apifn-root{${dark}}`;
54
+ if (theme === "light") return `.apifn-root{${light}}`;
55
+ return `.apifn-root{${light}}@media(prefers-color-scheme:dark){.apifn-root{${dark}}}`;
56
+ }
57
+ var s = {
58
+ root: {
59
+ fontFamily: "var(--apifn-font-sans)",
60
+ color: "var(--apifn-text)",
61
+ background: "var(--apifn-bg)",
62
+ maxWidth: "960px",
63
+ margin: "0 auto",
64
+ padding: "0 24px 48px"
65
+ },
66
+ pageTitle: { fontSize: "28px", fontWeight: 800, marginBottom: "8px" },
67
+ pageSubtitle: { fontSize: "14px", color: "var(--apifn-text-muted)", marginBottom: "40px" },
68
+ card: {
69
+ border: "1px solid var(--apifn-border)",
70
+ borderRadius: "var(--apifn-radius)",
71
+ marginBottom: "24px",
72
+ overflow: "hidden",
73
+ background: "var(--apifn-bg-surface)"
74
+ },
75
+ cardHeader: {
76
+ width: "100%",
77
+ border: "none",
78
+ background: "none",
79
+ color: "inherit",
80
+ font: "inherit",
81
+ textAlign: "left",
82
+ display: "flex",
83
+ alignItems: "center",
84
+ gap: "12px",
85
+ padding: "14px 20px",
86
+ cursor: "pointer",
87
+ borderBottom: "1px solid var(--apifn-border)"
88
+ },
89
+ badge: (method) => {
90
+ const c = METHOD_COLORS[method.toLowerCase()] ?? { bg: "#2d3748", text: "#9ca3af" };
91
+ return { padding: "3px 10px", borderRadius: "3px", background: c.bg, color: c.text, fontWeight: 700, fontSize: "12px", fontFamily: "var(--apifn-font-mono)", textTransform: "uppercase" };
92
+ },
93
+ cardPath: { fontFamily: "var(--apifn-font-mono)", fontSize: "14px", fontWeight: 600, flex: 1 },
94
+ cardSummary: { fontSize: "13px", color: "var(--apifn-text-muted)" },
95
+ tabs: {
96
+ display: "flex",
97
+ borderBottom: "1px solid var(--apifn-border)",
98
+ padding: "0 20px"
99
+ },
100
+ tab: (active) => ({
101
+ padding: "10px 14px",
102
+ fontSize: "13px",
103
+ fontWeight: active ? 600 : 400,
104
+ color: active ? "var(--apifn-text)" : "var(--apifn-text-muted)",
105
+ border: "none",
106
+ borderBottomWidth: "2px",
107
+ borderBottomStyle: "solid",
108
+ borderBottomColor: active ? "var(--apifn-accent)" : "transparent",
109
+ background: "none",
110
+ cursor: "pointer"
111
+ })
112
+ };
113
+ function EndpointCard({
114
+ path,
115
+ method,
116
+ operation,
117
+ tryIt,
118
+ baseUrl,
119
+ performanceMetrics
120
+ }) {
121
+ const [open, setOpen] = (0, import_react.useState)(false);
122
+ const [tab, setTab] = (0, import_react.useState)("docs");
123
+ const perfKey = `${method.toUpperCase()} ${path}`;
124
+ const rawMetrics = performanceMetrics?.[perfKey];
125
+ const anchorId = `${method.toLowerCase()}-${path.replace(/[^a-z0-9]/gi, "-")}`;
126
+ const perfMetrics = rawMetrics ? { endpoint: path, method, lastUpdated: (/* @__PURE__ */ new Date()).toISOString(), ...rawMetrics } : void 0;
127
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { id: anchorId, style: s.card, children: [
128
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { type: "button", style: s.cardHeader, "aria-expanded": open, onClick: () => setOpen((o) => !o), children: [
129
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: s.badge(method), children: method.toUpperCase() }),
130
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: s.cardPath, children: path }),
131
+ operation.summary && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: s.cardSummary, children: operation.summary }),
132
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", style: { color: "var(--apifn-text-muted)", fontSize: "12px", transform: open ? "rotate(180deg)" : "none", transition: "transform .15s" }, children: "\u25BC" })
133
+ ] }),
134
+ open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
135
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: s.tabs, children: [
136
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: s.tab(tab === "docs"), onClick: () => setTab("docs"), children: "Docs" }),
137
+ tryIt && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: s.tab(tab === "tryit"), onClick: () => setTab("tryit"), children: "Try It" }),
138
+ perfMetrics && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: s.tab(tab === "perf"), onClick: () => setTab("perf"), children: "Performance" })
139
+ ] }),
140
+ tab === "docs" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react2.EndpointViewer, { path, method, operation }),
141
+ tab === "tryit" && tryIt && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react2.TryIt, { path, method, operation, baseUrl }),
142
+ tab === "perf" && perfMetrics && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "20px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react2.PerformanceOverlay, { metrics: perfMetrics }) })
143
+ ] })
144
+ ] });
145
+ }
146
+ function ApifnApiReference({
147
+ entry,
148
+ tryIt = false,
149
+ baseUrl,
150
+ theme = "auto",
151
+ performanceMetrics
152
+ }) {
153
+ const themeStyle = getThemeStyle(theme);
154
+ const effectiveBaseUrl = baseUrl ?? entry.baseUrl ?? entry.spec.servers?.[0]?.url ?? "https://api.example.com";
155
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "apifn-root", children: [
156
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: themeStyle }),
157
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: s.root, children: [
158
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { style: s.pageTitle, children: entry.title }),
159
+ entry.tag && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: s.pageSubtitle, children: [
160
+ "Tag: ",
161
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { style: { fontFamily: "var(--apifn-font-mono)" }, children: entry.tag }),
162
+ " \u2014 ",
163
+ entry.endpoints.length,
164
+ " endpoint",
165
+ entry.endpoints.length !== 1 ? "s" : ""
166
+ ] }),
167
+ entry.endpoints.map((ep) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
168
+ EndpointCard,
169
+ {
170
+ path: ep.path,
171
+ method: ep.method,
172
+ operation: ep.operation,
173
+ tryIt,
174
+ baseUrl: effectiveBaseUrl,
175
+ performanceMetrics
176
+ },
177
+ `${ep.method}-${ep.path}`
178
+ ))
179
+ ] })
180
+ ] });
181
+ }
182
+ // Annotate the CommonJS export names for ESM import in node:
183
+ 0 && (module.exports = {
184
+ ApifnApiReference
185
+ });
186
+ //# sourceMappingURL=react.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/ApifnApiReference.tsx"],"sourcesContent":["/**\n * ApifnApiReference (React) — renders a docsfn RawContentEntry as an API reference page (DOCS-002, DOCS-005).\n */\n\nimport React, { useState } from \"react\";\nimport { EndpointViewer, TryIt, PerformanceOverlay } from \"@apifn/react\";\nimport type { ApifnApiReferenceProps, PerformanceMetrics } from \"../types.js\";\nimport type { OperationObject } from \"@apifn/core\";\n\nexport type { ApifnApiReferenceProps };\n\n// Inline method colors — avoids importing internal @apifn/react paths\nconst METHOD_COLORS: Record<string, { bg: string; text: string }> = {\n get: { bg: \"#065f46\", text: \"#6ee7b7\" },\n post: { bg: \"#1e3a5f\", text: \"#93c5fd\" },\n put: { bg: \"#78350f\", text: \"#fcd34d\" },\n patch: { bg: \"#5b21b6\", text: \"#c4b5fd\" },\n delete: { bg: \"#7f1d1d\", text: \"#fca5a5\" },\n head: { bg: \"#1f2937\", text: \"#9ca3af\" },\n options: { bg: \"#1f2937\", text: \"#9ca3af\" },\n};\n\nfunction getThemeStyle(theme: \"light\" | \"dark\" | \"auto\"): string {\n const dark = `\n --apifn-bg:#0f1117;--apifn-bg-surface:#1a1d2e;--apifn-bg-surface-hover:#252840;\n --apifn-border:#2d3748;--apifn-text:#e2e8f0;--apifn-text-muted:#64748b;\n --apifn-accent:#7c3aed;--apifn-accent-text:#c4b5fd;--apifn-green:#6ee7b7;\n --apifn-blue:#93c5fd;--apifn-yellow:#fcd34d;--apifn-red:#fca5a5;\n --apifn-radius:6px;--apifn-font-mono:'JetBrains Mono',monospace;--apifn-font-sans:-apple-system,sans-serif\n `;\n const light = `\n --apifn-bg:#ffffff;--apifn-bg-surface:#f8fafc;--apifn-bg-surface-hover:#f1f5f9;\n --apifn-border:#e2e8f0;--apifn-text:#0f172a;--apifn-text-muted:#64748b;\n --apifn-accent:#7c3aed;--apifn-accent-text:#6d28d9;--apifn-green:#059669;\n --apifn-blue:#2563eb;--apifn-yellow:#d97706;--apifn-red:#dc2626;\n --apifn-radius:6px;--apifn-font-mono:'JetBrains Mono',monospace;--apifn-font-sans:-apple-system,sans-serif\n `;\n if (theme === \"dark\") return `.apifn-root{${dark}}`;\n if (theme === \"light\") return `.apifn-root{${light}}`;\n return `.apifn-root{${light}}@media(prefers-color-scheme:dark){.apifn-root{${dark}}}`;\n}\n\nconst s = {\n root: {\n fontFamily: \"var(--apifn-font-sans)\",\n color: \"var(--apifn-text)\",\n background: \"var(--apifn-bg)\",\n maxWidth: \"960px\",\n margin: \"0 auto\",\n padding: \"0 24px 48px\",\n } as React.CSSProperties,\n pageTitle: { fontSize: \"28px\", fontWeight: 800, marginBottom: \"8px\" } as React.CSSProperties,\n pageSubtitle: { fontSize: \"14px\", color: \"var(--apifn-text-muted)\", marginBottom: \"40px\" } as React.CSSProperties,\n card: {\n border: \"1px solid var(--apifn-border)\",\n borderRadius: \"var(--apifn-radius)\",\n marginBottom: \"24px\",\n overflow: \"hidden\",\n background: \"var(--apifn-bg-surface)\",\n } as React.CSSProperties,\n cardHeader: {\n width: \"100%\", border: \"none\", background: \"none\",\n color: \"inherit\", font: \"inherit\", textAlign: \"left\",\n display: \"flex\", alignItems: \"center\", gap: \"12px\",\n padding: \"14px 20px\", cursor: \"pointer\",\n borderBottom: \"1px solid var(--apifn-border)\",\n } as React.CSSProperties,\n badge: (method: string): React.CSSProperties => {\n const c = METHOD_COLORS[method.toLowerCase()] ?? { bg: \"#2d3748\", text: \"#9ca3af\" };\n return { padding: \"3px 10px\", borderRadius: \"3px\", background: c.bg, color: c.text, fontWeight: 700, fontSize: \"12px\", fontFamily: \"var(--apifn-font-mono)\", textTransform: \"uppercase\" };\n },\n cardPath: { fontFamily: \"var(--apifn-font-mono)\", fontSize: \"14px\", fontWeight: 600, flex: 1 } as React.CSSProperties,\n cardSummary: { fontSize: \"13px\", color: \"var(--apifn-text-muted)\" } as React.CSSProperties,\n tabs: {\n display: \"flex\", borderBottom: \"1px solid var(--apifn-border)\", padding: \"0 20px\",\n } as React.CSSProperties,\n tab: (active: boolean): React.CSSProperties => ({\n padding: \"10px 14px\", fontSize: \"13px\",\n fontWeight: active ? 600 : 400,\n color: active ? \"var(--apifn-text)\" : \"var(--apifn-text-muted)\",\n border: \"none\", borderBottomWidth: \"2px\", borderBottomStyle: \"solid\",\n borderBottomColor: active ? \"var(--apifn-accent)\" : \"transparent\",\n background: \"none\", cursor: \"pointer\",\n }),\n};\n\nfunction EndpointCard({\n path, method, operation, tryIt, baseUrl, performanceMetrics,\n}: Readonly<{\n path: string;\n method: string;\n operation: OperationObject;\n tryIt: boolean;\n baseUrl: string;\n performanceMetrics?: ApifnApiReferenceProps[\"performanceMetrics\"];\n}>) {\n const [open, setOpen] = useState(false);\n const [tab, setTab] = useState<\"docs\" | \"tryit\" | \"perf\">(\"docs\");\n\n const perfKey = `${method.toUpperCase()} ${path}`;\n const rawMetrics = performanceMetrics?.[perfKey];\n const anchorId = `${method.toLowerCase()}-${path.replace(/[^a-z0-9]/gi, \"-\")}`;\n\n const perfMetrics: PerformanceMetrics | undefined = rawMetrics\n ? { endpoint: path, method, lastUpdated: new Date().toISOString(), ...rawMetrics }\n : undefined;\n\n return (\n <div id={anchorId} style={s.card}>\n <button type=\"button\" style={s.cardHeader} aria-expanded={open} onClick={() => setOpen((o) => !o)}>\n <span style={s.badge(method)}>{method.toUpperCase()}</span>\n <span style={s.cardPath}>{path}</span>\n {operation.summary && <span style={s.cardSummary}>{operation.summary as string}</span>}\n <span aria-hidden=\"true\" style={{ color: \"var(--apifn-text-muted)\", fontSize: \"12px\", transform: open ? \"rotate(180deg)\" : \"none\", transition: \"transform .15s\" }}>▼</span>\n </button>\n\n {open && (\n <>\n <div style={s.tabs}>\n <button style={s.tab(tab === \"docs\")} onClick={() => setTab(\"docs\")}>Docs</button>\n {tryIt && <button style={s.tab(tab === \"tryit\")} onClick={() => setTab(\"tryit\")}>Try It</button>}\n {perfMetrics && <button style={s.tab(tab === \"perf\")} onClick={() => setTab(\"perf\")}>Performance</button>}\n </div>\n {tab === \"docs\" && <EndpointViewer path={path} method={method} operation={operation} />}\n {tab === \"tryit\" && tryIt && <TryIt path={path} method={method} operation={operation} baseUrl={baseUrl} />}\n {tab === \"perf\" && perfMetrics && (\n <div style={{ padding: \"20px\" }}>\n <PerformanceOverlay metrics={perfMetrics} />\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n\nexport function ApifnApiReference({\n entry, tryIt = false, baseUrl, theme = \"auto\", performanceMetrics,\n}: Readonly<ApifnApiReferenceProps>): React.ReactElement {\n const themeStyle = getThemeStyle(theme);\n const effectiveBaseUrl =\n baseUrl\n ?? entry.baseUrl\n ?? (entry.spec as { servers?: Array<{ url: string }> }).servers?.[0]?.url\n ?? \"https://api.example.com\";\n\n return (\n <div className=\"apifn-root\">\n <style>{themeStyle}</style>\n <div style={s.root}>\n <h1 style={s.pageTitle}>{entry.title}</h1>\n {entry.tag && (\n <div style={s.pageSubtitle}>\n Tag: <code style={{ fontFamily: \"var(--apifn-font-mono)\" }}>{entry.tag}</code>\n {\" — \"}\n {entry.endpoints.length} endpoint{entry.endpoints.length !== 1 ? \"s\" : \"\"}\n </div>\n )}\n {entry.endpoints.map((ep) => (\n <EndpointCard\n key={`${ep.method}-${ep.path}`}\n path={ep.path}\n method={ep.method}\n operation={ep.operation}\n tryIt={tryIt}\n baseUrl={effectiveBaseUrl}\n performanceMetrics={performanceMetrics}\n />\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["import_react"]}
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { a as ApifnApiReferenceProps } from './types-D4LTWU9V.cjs';
3
+ import '@apifn/core';
4
+
5
+ /**
6
+ * ApifnApiReference (React) — renders a docsfn RawContentEntry as an API reference page (DOCS-002, DOCS-005).
7
+ */
8
+
9
+ declare function ApifnApiReference({ entry, tryIt, baseUrl, theme, performanceMetrics, }: Readonly<ApifnApiReferenceProps>): React.ReactElement;
10
+
11
+ export { ApifnApiReference, ApifnApiReferenceProps };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { a as ApifnApiReferenceProps } from './types-D4LTWU9V.js';
3
+ import '@apifn/core';
4
+
5
+ /**
6
+ * ApifnApiReference (React) — renders a docsfn RawContentEntry as an API reference page (DOCS-002, DOCS-005).
7
+ */
8
+
9
+ declare function ApifnApiReference({ entry, tryIt, baseUrl, theme, performanceMetrics, }: Readonly<ApifnApiReferenceProps>): React.ReactElement;
10
+
11
+ export { ApifnApiReference, ApifnApiReferenceProps };
package/dist/react.js ADDED
@@ -0,0 +1,161 @@
1
+ // src/react/ApifnApiReference.tsx
2
+ import { useState } from "react";
3
+ import { EndpointViewer, TryIt, PerformanceOverlay } from "@apifn/react";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ var METHOD_COLORS = {
6
+ get: { bg: "#065f46", text: "#6ee7b7" },
7
+ post: { bg: "#1e3a5f", text: "#93c5fd" },
8
+ put: { bg: "#78350f", text: "#fcd34d" },
9
+ patch: { bg: "#5b21b6", text: "#c4b5fd" },
10
+ delete: { bg: "#7f1d1d", text: "#fca5a5" },
11
+ head: { bg: "#1f2937", text: "#9ca3af" },
12
+ options: { bg: "#1f2937", text: "#9ca3af" }
13
+ };
14
+ function getThemeStyle(theme) {
15
+ const dark = `
16
+ --apifn-bg:#0f1117;--apifn-bg-surface:#1a1d2e;--apifn-bg-surface-hover:#252840;
17
+ --apifn-border:#2d3748;--apifn-text:#e2e8f0;--apifn-text-muted:#64748b;
18
+ --apifn-accent:#7c3aed;--apifn-accent-text:#c4b5fd;--apifn-green:#6ee7b7;
19
+ --apifn-blue:#93c5fd;--apifn-yellow:#fcd34d;--apifn-red:#fca5a5;
20
+ --apifn-radius:6px;--apifn-font-mono:'JetBrains Mono',monospace;--apifn-font-sans:-apple-system,sans-serif
21
+ `;
22
+ const light = `
23
+ --apifn-bg:#ffffff;--apifn-bg-surface:#f8fafc;--apifn-bg-surface-hover:#f1f5f9;
24
+ --apifn-border:#e2e8f0;--apifn-text:#0f172a;--apifn-text-muted:#64748b;
25
+ --apifn-accent:#7c3aed;--apifn-accent-text:#6d28d9;--apifn-green:#059669;
26
+ --apifn-blue:#2563eb;--apifn-yellow:#d97706;--apifn-red:#dc2626;
27
+ --apifn-radius:6px;--apifn-font-mono:'JetBrains Mono',monospace;--apifn-font-sans:-apple-system,sans-serif
28
+ `;
29
+ if (theme === "dark") return `.apifn-root{${dark}}`;
30
+ if (theme === "light") return `.apifn-root{${light}}`;
31
+ return `.apifn-root{${light}}@media(prefers-color-scheme:dark){.apifn-root{${dark}}}`;
32
+ }
33
+ var s = {
34
+ root: {
35
+ fontFamily: "var(--apifn-font-sans)",
36
+ color: "var(--apifn-text)",
37
+ background: "var(--apifn-bg)",
38
+ maxWidth: "960px",
39
+ margin: "0 auto",
40
+ padding: "0 24px 48px"
41
+ },
42
+ pageTitle: { fontSize: "28px", fontWeight: 800, marginBottom: "8px" },
43
+ pageSubtitle: { fontSize: "14px", color: "var(--apifn-text-muted)", marginBottom: "40px" },
44
+ card: {
45
+ border: "1px solid var(--apifn-border)",
46
+ borderRadius: "var(--apifn-radius)",
47
+ marginBottom: "24px",
48
+ overflow: "hidden",
49
+ background: "var(--apifn-bg-surface)"
50
+ },
51
+ cardHeader: {
52
+ width: "100%",
53
+ border: "none",
54
+ background: "none",
55
+ color: "inherit",
56
+ font: "inherit",
57
+ textAlign: "left",
58
+ display: "flex",
59
+ alignItems: "center",
60
+ gap: "12px",
61
+ padding: "14px 20px",
62
+ cursor: "pointer",
63
+ borderBottom: "1px solid var(--apifn-border)"
64
+ },
65
+ badge: (method) => {
66
+ const c = METHOD_COLORS[method.toLowerCase()] ?? { bg: "#2d3748", text: "#9ca3af" };
67
+ return { padding: "3px 10px", borderRadius: "3px", background: c.bg, color: c.text, fontWeight: 700, fontSize: "12px", fontFamily: "var(--apifn-font-mono)", textTransform: "uppercase" };
68
+ },
69
+ cardPath: { fontFamily: "var(--apifn-font-mono)", fontSize: "14px", fontWeight: 600, flex: 1 },
70
+ cardSummary: { fontSize: "13px", color: "var(--apifn-text-muted)" },
71
+ tabs: {
72
+ display: "flex",
73
+ borderBottom: "1px solid var(--apifn-border)",
74
+ padding: "0 20px"
75
+ },
76
+ tab: (active) => ({
77
+ padding: "10px 14px",
78
+ fontSize: "13px",
79
+ fontWeight: active ? 600 : 400,
80
+ color: active ? "var(--apifn-text)" : "var(--apifn-text-muted)",
81
+ border: "none",
82
+ borderBottomWidth: "2px",
83
+ borderBottomStyle: "solid",
84
+ borderBottomColor: active ? "var(--apifn-accent)" : "transparent",
85
+ background: "none",
86
+ cursor: "pointer"
87
+ })
88
+ };
89
+ function EndpointCard({
90
+ path,
91
+ method,
92
+ operation,
93
+ tryIt,
94
+ baseUrl,
95
+ performanceMetrics
96
+ }) {
97
+ const [open, setOpen] = useState(false);
98
+ const [tab, setTab] = useState("docs");
99
+ const perfKey = `${method.toUpperCase()} ${path}`;
100
+ const rawMetrics = performanceMetrics?.[perfKey];
101
+ const anchorId = `${method.toLowerCase()}-${path.replace(/[^a-z0-9]/gi, "-")}`;
102
+ const perfMetrics = rawMetrics ? { endpoint: path, method, lastUpdated: (/* @__PURE__ */ new Date()).toISOString(), ...rawMetrics } : void 0;
103
+ return /* @__PURE__ */ jsxs("div", { id: anchorId, style: s.card, children: [
104
+ /* @__PURE__ */ jsxs("button", { type: "button", style: s.cardHeader, "aria-expanded": open, onClick: () => setOpen((o) => !o), children: [
105
+ /* @__PURE__ */ jsx("span", { style: s.badge(method), children: method.toUpperCase() }),
106
+ /* @__PURE__ */ jsx("span", { style: s.cardPath, children: path }),
107
+ operation.summary && /* @__PURE__ */ jsx("span", { style: s.cardSummary, children: operation.summary }),
108
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { color: "var(--apifn-text-muted)", fontSize: "12px", transform: open ? "rotate(180deg)" : "none", transition: "transform .15s" }, children: "\u25BC" })
109
+ ] }),
110
+ open && /* @__PURE__ */ jsxs(Fragment, { children: [
111
+ /* @__PURE__ */ jsxs("div", { style: s.tabs, children: [
112
+ /* @__PURE__ */ jsx("button", { style: s.tab(tab === "docs"), onClick: () => setTab("docs"), children: "Docs" }),
113
+ tryIt && /* @__PURE__ */ jsx("button", { style: s.tab(tab === "tryit"), onClick: () => setTab("tryit"), children: "Try It" }),
114
+ perfMetrics && /* @__PURE__ */ jsx("button", { style: s.tab(tab === "perf"), onClick: () => setTab("perf"), children: "Performance" })
115
+ ] }),
116
+ tab === "docs" && /* @__PURE__ */ jsx(EndpointViewer, { path, method, operation }),
117
+ tab === "tryit" && tryIt && /* @__PURE__ */ jsx(TryIt, { path, method, operation, baseUrl }),
118
+ tab === "perf" && perfMetrics && /* @__PURE__ */ jsx("div", { style: { padding: "20px" }, children: /* @__PURE__ */ jsx(PerformanceOverlay, { metrics: perfMetrics }) })
119
+ ] })
120
+ ] });
121
+ }
122
+ function ApifnApiReference({
123
+ entry,
124
+ tryIt = false,
125
+ baseUrl,
126
+ theme = "auto",
127
+ performanceMetrics
128
+ }) {
129
+ const themeStyle = getThemeStyle(theme);
130
+ const effectiveBaseUrl = baseUrl ?? entry.baseUrl ?? entry.spec.servers?.[0]?.url ?? "https://api.example.com";
131
+ return /* @__PURE__ */ jsxs("div", { className: "apifn-root", children: [
132
+ /* @__PURE__ */ jsx("style", { children: themeStyle }),
133
+ /* @__PURE__ */ jsxs("div", { style: s.root, children: [
134
+ /* @__PURE__ */ jsx("h1", { style: s.pageTitle, children: entry.title }),
135
+ entry.tag && /* @__PURE__ */ jsxs("div", { style: s.pageSubtitle, children: [
136
+ "Tag: ",
137
+ /* @__PURE__ */ jsx("code", { style: { fontFamily: "var(--apifn-font-mono)" }, children: entry.tag }),
138
+ " \u2014 ",
139
+ entry.endpoints.length,
140
+ " endpoint",
141
+ entry.endpoints.length !== 1 ? "s" : ""
142
+ ] }),
143
+ entry.endpoints.map((ep) => /* @__PURE__ */ jsx(
144
+ EndpointCard,
145
+ {
146
+ path: ep.path,
147
+ method: ep.method,
148
+ operation: ep.operation,
149
+ tryIt,
150
+ baseUrl: effectiveBaseUrl,
151
+ performanceMetrics
152
+ },
153
+ `${ep.method}-${ep.path}`
154
+ ))
155
+ ] })
156
+ ] });
157
+ }
158
+ export {
159
+ ApifnApiReference
160
+ };
161
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react/ApifnApiReference.tsx"],"sourcesContent":["/**\n * ApifnApiReference (React) — renders a docsfn RawContentEntry as an API reference page (DOCS-002, DOCS-005).\n */\n\nimport React, { useState } from \"react\";\nimport { EndpointViewer, TryIt, PerformanceOverlay } from \"@apifn/react\";\nimport type { ApifnApiReferenceProps, PerformanceMetrics } from \"../types.js\";\nimport type { OperationObject } from \"@apifn/core\";\n\nexport type { ApifnApiReferenceProps };\n\n// Inline method colors — avoids importing internal @apifn/react paths\nconst METHOD_COLORS: Record<string, { bg: string; text: string }> = {\n get: { bg: \"#065f46\", text: \"#6ee7b7\" },\n post: { bg: \"#1e3a5f\", text: \"#93c5fd\" },\n put: { bg: \"#78350f\", text: \"#fcd34d\" },\n patch: { bg: \"#5b21b6\", text: \"#c4b5fd\" },\n delete: { bg: \"#7f1d1d\", text: \"#fca5a5\" },\n head: { bg: \"#1f2937\", text: \"#9ca3af\" },\n options: { bg: \"#1f2937\", text: \"#9ca3af\" },\n};\n\nfunction getThemeStyle(theme: \"light\" | \"dark\" | \"auto\"): string {\n const dark = `\n --apifn-bg:#0f1117;--apifn-bg-surface:#1a1d2e;--apifn-bg-surface-hover:#252840;\n --apifn-border:#2d3748;--apifn-text:#e2e8f0;--apifn-text-muted:#64748b;\n --apifn-accent:#7c3aed;--apifn-accent-text:#c4b5fd;--apifn-green:#6ee7b7;\n --apifn-blue:#93c5fd;--apifn-yellow:#fcd34d;--apifn-red:#fca5a5;\n --apifn-radius:6px;--apifn-font-mono:'JetBrains Mono',monospace;--apifn-font-sans:-apple-system,sans-serif\n `;\n const light = `\n --apifn-bg:#ffffff;--apifn-bg-surface:#f8fafc;--apifn-bg-surface-hover:#f1f5f9;\n --apifn-border:#e2e8f0;--apifn-text:#0f172a;--apifn-text-muted:#64748b;\n --apifn-accent:#7c3aed;--apifn-accent-text:#6d28d9;--apifn-green:#059669;\n --apifn-blue:#2563eb;--apifn-yellow:#d97706;--apifn-red:#dc2626;\n --apifn-radius:6px;--apifn-font-mono:'JetBrains Mono',monospace;--apifn-font-sans:-apple-system,sans-serif\n `;\n if (theme === \"dark\") return `.apifn-root{${dark}}`;\n if (theme === \"light\") return `.apifn-root{${light}}`;\n return `.apifn-root{${light}}@media(prefers-color-scheme:dark){.apifn-root{${dark}}}`;\n}\n\nconst s = {\n root: {\n fontFamily: \"var(--apifn-font-sans)\",\n color: \"var(--apifn-text)\",\n background: \"var(--apifn-bg)\",\n maxWidth: \"960px\",\n margin: \"0 auto\",\n padding: \"0 24px 48px\",\n } as React.CSSProperties,\n pageTitle: { fontSize: \"28px\", fontWeight: 800, marginBottom: \"8px\" } as React.CSSProperties,\n pageSubtitle: { fontSize: \"14px\", color: \"var(--apifn-text-muted)\", marginBottom: \"40px\" } as React.CSSProperties,\n card: {\n border: \"1px solid var(--apifn-border)\",\n borderRadius: \"var(--apifn-radius)\",\n marginBottom: \"24px\",\n overflow: \"hidden\",\n background: \"var(--apifn-bg-surface)\",\n } as React.CSSProperties,\n cardHeader: {\n width: \"100%\", border: \"none\", background: \"none\",\n color: \"inherit\", font: \"inherit\", textAlign: \"left\",\n display: \"flex\", alignItems: \"center\", gap: \"12px\",\n padding: \"14px 20px\", cursor: \"pointer\",\n borderBottom: \"1px solid var(--apifn-border)\",\n } as React.CSSProperties,\n badge: (method: string): React.CSSProperties => {\n const c = METHOD_COLORS[method.toLowerCase()] ?? { bg: \"#2d3748\", text: \"#9ca3af\" };\n return { padding: \"3px 10px\", borderRadius: \"3px\", background: c.bg, color: c.text, fontWeight: 700, fontSize: \"12px\", fontFamily: \"var(--apifn-font-mono)\", textTransform: \"uppercase\" };\n },\n cardPath: { fontFamily: \"var(--apifn-font-mono)\", fontSize: \"14px\", fontWeight: 600, flex: 1 } as React.CSSProperties,\n cardSummary: { fontSize: \"13px\", color: \"var(--apifn-text-muted)\" } as React.CSSProperties,\n tabs: {\n display: \"flex\", borderBottom: \"1px solid var(--apifn-border)\", padding: \"0 20px\",\n } as React.CSSProperties,\n tab: (active: boolean): React.CSSProperties => ({\n padding: \"10px 14px\", fontSize: \"13px\",\n fontWeight: active ? 600 : 400,\n color: active ? \"var(--apifn-text)\" : \"var(--apifn-text-muted)\",\n border: \"none\", borderBottomWidth: \"2px\", borderBottomStyle: \"solid\",\n borderBottomColor: active ? \"var(--apifn-accent)\" : \"transparent\",\n background: \"none\", cursor: \"pointer\",\n }),\n};\n\nfunction EndpointCard({\n path, method, operation, tryIt, baseUrl, performanceMetrics,\n}: Readonly<{\n path: string;\n method: string;\n operation: OperationObject;\n tryIt: boolean;\n baseUrl: string;\n performanceMetrics?: ApifnApiReferenceProps[\"performanceMetrics\"];\n}>) {\n const [open, setOpen] = useState(false);\n const [tab, setTab] = useState<\"docs\" | \"tryit\" | \"perf\">(\"docs\");\n\n const perfKey = `${method.toUpperCase()} ${path}`;\n const rawMetrics = performanceMetrics?.[perfKey];\n const anchorId = `${method.toLowerCase()}-${path.replace(/[^a-z0-9]/gi, \"-\")}`;\n\n const perfMetrics: PerformanceMetrics | undefined = rawMetrics\n ? { endpoint: path, method, lastUpdated: new Date().toISOString(), ...rawMetrics }\n : undefined;\n\n return (\n <div id={anchorId} style={s.card}>\n <button type=\"button\" style={s.cardHeader} aria-expanded={open} onClick={() => setOpen((o) => !o)}>\n <span style={s.badge(method)}>{method.toUpperCase()}</span>\n <span style={s.cardPath}>{path}</span>\n {operation.summary && <span style={s.cardSummary}>{operation.summary as string}</span>}\n <span aria-hidden=\"true\" style={{ color: \"var(--apifn-text-muted)\", fontSize: \"12px\", transform: open ? \"rotate(180deg)\" : \"none\", transition: \"transform .15s\" }}>▼</span>\n </button>\n\n {open && (\n <>\n <div style={s.tabs}>\n <button style={s.tab(tab === \"docs\")} onClick={() => setTab(\"docs\")}>Docs</button>\n {tryIt && <button style={s.tab(tab === \"tryit\")} onClick={() => setTab(\"tryit\")}>Try It</button>}\n {perfMetrics && <button style={s.tab(tab === \"perf\")} onClick={() => setTab(\"perf\")}>Performance</button>}\n </div>\n {tab === \"docs\" && <EndpointViewer path={path} method={method} operation={operation} />}\n {tab === \"tryit\" && tryIt && <TryIt path={path} method={method} operation={operation} baseUrl={baseUrl} />}\n {tab === \"perf\" && perfMetrics && (\n <div style={{ padding: \"20px\" }}>\n <PerformanceOverlay metrics={perfMetrics} />\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n\nexport function ApifnApiReference({\n entry, tryIt = false, baseUrl, theme = \"auto\", performanceMetrics,\n}: Readonly<ApifnApiReferenceProps>): React.ReactElement {\n const themeStyle = getThemeStyle(theme);\n const effectiveBaseUrl =\n baseUrl\n ?? entry.baseUrl\n ?? (entry.spec as { servers?: Array<{ url: string }> }).servers?.[0]?.url\n ?? \"https://api.example.com\";\n\n return (\n <div className=\"apifn-root\">\n <style>{themeStyle}</style>\n <div style={s.root}>\n <h1 style={s.pageTitle}>{entry.title}</h1>\n {entry.tag && (\n <div style={s.pageSubtitle}>\n Tag: <code style={{ fontFamily: \"var(--apifn-font-mono)\" }}>{entry.tag}</code>\n {\" — \"}\n {entry.endpoints.length} endpoint{entry.endpoints.length !== 1 ? \"s\" : \"\"}\n </div>\n )}\n {entry.endpoints.map((ep) => (\n <EndpointCard\n key={`${ep.method}-${ep.path}`}\n path={ep.path}\n method={ep.method}\n operation={ep.operation}\n tryIt={tryIt}\n baseUrl={effectiveBaseUrl}\n performanceMetrics={performanceMetrics}\n />\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,97 @@
1
+ import { OperationObject, OpenAPIDocument } from '@apifn/core';
2
+
3
+ /**
4
+ * docsfn integration types for @apifn/docsfn.
5
+ *
6
+ * docsfn is an optional peer dependency that may not be installed.
7
+ * We define the minimal interfaces needed for our provider here so
8
+ * consumers get correct types even without the full docsfn package.
9
+ */
10
+
11
+ /** Sidebar leaf link. */
12
+ interface SidebarLink {
13
+ type: "link";
14
+ label: string;
15
+ href: string;
16
+ }
17
+ /** Sidebar group containing links. */
18
+ interface SidebarGroup {
19
+ type: "group";
20
+ label: string;
21
+ items: Array<SidebarLink | SidebarGroup>;
22
+ }
23
+ type SidebarItem = SidebarLink | SidebarGroup;
24
+ /** A processed endpoint grouped in a docsfn page. */
25
+ interface ApiEndpoint {
26
+ path: string;
27
+ method: string;
28
+ operation: OperationObject;
29
+ tag: string;
30
+ }
31
+ /**
32
+ * A single raw content entry produced by a DocsContentProvider.
33
+ * `kind: "api"` signals to docsfn that this is an API reference page.
34
+ */
35
+ interface RawContentEntry {
36
+ kind: "api";
37
+ /** URL slug for this page (e.g. "/api/users") */
38
+ slug: string;
39
+ /** Human-readable page title */
40
+ title: string;
41
+ /** Tag name when split by tag */
42
+ tag?: string;
43
+ /** Endpoint list for this page */
44
+ endpoints: ApiEndpoint[];
45
+ /** Sidebar items generated for this entry */
46
+ sidebar: SidebarGroup;
47
+ /** Full OpenAPI spec (so renderers can look up $refs etc.) */
48
+ spec: OpenAPIDocument;
49
+ /** Optional Try-It base URL supplied by the provider */
50
+ baseUrl?: string;
51
+ }
52
+ /** A DocsContentProvider is a callable that returns RawContentEntry[]. */
53
+ interface DocsContentProvider {
54
+ (): Promise<RawContentEntry[]>;
55
+ entries: RawContentEntry[];
56
+ }
57
+ interface CreateApifnProviderOptions {
58
+ /** OpenAPI document (object) */
59
+ spec?: OpenAPIDocument;
60
+ /** File path to a JSON or YAML OpenAPI spec */
61
+ specPath?: string;
62
+ /** Base path prefix for slug generation (default: "/api") */
63
+ basePath?: string;
64
+ /**
65
+ * Split the spec into one page per tag.
66
+ * - `true` → one RawContentEntry per tag
67
+ * - `false` → one RawContentEntry with all endpoints
68
+ * @default true
69
+ */
70
+ splitByTag?: boolean;
71
+ /** Optional base URL to embed in entries (for TryIt) */
72
+ baseUrl?: string;
73
+ }
74
+ interface PerformanceMetrics {
75
+ endpoint: string;
76
+ method: string;
77
+ p50Ms: number;
78
+ p95Ms: number;
79
+ p99Ms: number;
80
+ errorRatePct: number;
81
+ requestsPerMinute: number;
82
+ lastUpdated: string;
83
+ }
84
+ interface ApifnApiReferenceProps {
85
+ /** Single content entry from createApifnProvider */
86
+ entry: RawContentEntry;
87
+ /** Show embedded Try-It console per endpoint (DOCS-005) */
88
+ tryIt?: boolean;
89
+ /** Base URL for Try-It requests */
90
+ baseUrl?: string;
91
+ /** Theme for the embedded components */
92
+ theme?: "light" | "dark" | "auto";
93
+ /** Optional watchfn metrics per endpoint key ("METHOD /path") */
94
+ performanceMetrics?: Record<string, Omit<PerformanceMetrics, "endpoint" | "method" | "lastUpdated">>;
95
+ }
96
+
97
+ export type { ApiEndpoint as A, CreateApifnProviderOptions as C, DocsContentProvider as D, RawContentEntry as R, SidebarGroup as S, ApifnApiReferenceProps as a, SidebarItem as b, SidebarLink as c };
@@ -0,0 +1,97 @@
1
+ import { OperationObject, OpenAPIDocument } from '@apifn/core';
2
+
3
+ /**
4
+ * docsfn integration types for @apifn/docsfn.
5
+ *
6
+ * docsfn is an optional peer dependency that may not be installed.
7
+ * We define the minimal interfaces needed for our provider here so
8
+ * consumers get correct types even without the full docsfn package.
9
+ */
10
+
11
+ /** Sidebar leaf link. */
12
+ interface SidebarLink {
13
+ type: "link";
14
+ label: string;
15
+ href: string;
16
+ }
17
+ /** Sidebar group containing links. */
18
+ interface SidebarGroup {
19
+ type: "group";
20
+ label: string;
21
+ items: Array<SidebarLink | SidebarGroup>;
22
+ }
23
+ type SidebarItem = SidebarLink | SidebarGroup;
24
+ /** A processed endpoint grouped in a docsfn page. */
25
+ interface ApiEndpoint {
26
+ path: string;
27
+ method: string;
28
+ operation: OperationObject;
29
+ tag: string;
30
+ }
31
+ /**
32
+ * A single raw content entry produced by a DocsContentProvider.
33
+ * `kind: "api"` signals to docsfn that this is an API reference page.
34
+ */
35
+ interface RawContentEntry {
36
+ kind: "api";
37
+ /** URL slug for this page (e.g. "/api/users") */
38
+ slug: string;
39
+ /** Human-readable page title */
40
+ title: string;
41
+ /** Tag name when split by tag */
42
+ tag?: string;
43
+ /** Endpoint list for this page */
44
+ endpoints: ApiEndpoint[];
45
+ /** Sidebar items generated for this entry */
46
+ sidebar: SidebarGroup;
47
+ /** Full OpenAPI spec (so renderers can look up $refs etc.) */
48
+ spec: OpenAPIDocument;
49
+ /** Optional Try-It base URL supplied by the provider */
50
+ baseUrl?: string;
51
+ }
52
+ /** A DocsContentProvider is a callable that returns RawContentEntry[]. */
53
+ interface DocsContentProvider {
54
+ (): Promise<RawContentEntry[]>;
55
+ entries: RawContentEntry[];
56
+ }
57
+ interface CreateApifnProviderOptions {
58
+ /** OpenAPI document (object) */
59
+ spec?: OpenAPIDocument;
60
+ /** File path to a JSON or YAML OpenAPI spec */
61
+ specPath?: string;
62
+ /** Base path prefix for slug generation (default: "/api") */
63
+ basePath?: string;
64
+ /**
65
+ * Split the spec into one page per tag.
66
+ * - `true` → one RawContentEntry per tag
67
+ * - `false` → one RawContentEntry with all endpoints
68
+ * @default true
69
+ */
70
+ splitByTag?: boolean;
71
+ /** Optional base URL to embed in entries (for TryIt) */
72
+ baseUrl?: string;
73
+ }
74
+ interface PerformanceMetrics {
75
+ endpoint: string;
76
+ method: string;
77
+ p50Ms: number;
78
+ p95Ms: number;
79
+ p99Ms: number;
80
+ errorRatePct: number;
81
+ requestsPerMinute: number;
82
+ lastUpdated: string;
83
+ }
84
+ interface ApifnApiReferenceProps {
85
+ /** Single content entry from createApifnProvider */
86
+ entry: RawContentEntry;
87
+ /** Show embedded Try-It console per endpoint (DOCS-005) */
88
+ tryIt?: boolean;
89
+ /** Base URL for Try-It requests */
90
+ baseUrl?: string;
91
+ /** Theme for the embedded components */
92
+ theme?: "light" | "dark" | "auto";
93
+ /** Optional watchfn metrics per endpoint key ("METHOD /path") */
94
+ performanceMetrics?: Record<string, Omit<PerformanceMetrics, "endpoint" | "method" | "lastUpdated">>;
95
+ }
96
+
97
+ export type { ApiEndpoint as A, CreateApifnProviderOptions as C, DocsContentProvider as D, RawContentEntry as R, SidebarGroup as S, ApifnApiReferenceProps as a, SidebarItem as b, SidebarLink as c };