@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/README.md +128 -0
- package/dist/index.cjs +9 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -94
- package/dist/index.d.ts +3 -94
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +186 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +11 -0
- package/dist/react.d.ts +11 -0
- package/dist/react.js +161 -0
- package/dist/react.js.map +1 -0
- package/dist/types-D4LTWU9V.d.cts +97 -0
- package/dist/types-D4LTWU9V.d.ts +97 -0
- package/package.json +34 -9
- package/src/svelte/ApifnApiReference.svelte +141 -0
- package/src/svelte/ApifnApiReference.svelte.d.ts +4 -0
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"]}
|
package/dist/react.d.cts
ADDED
|
@@ -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 };
|
package/dist/react.d.ts
ADDED
|
@@ -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 };
|