fumadocs-openapi
Version:
Generate MDX docs for your OpenAPI spec
104 lines (103 loc) • 4.99 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Markdown } from '../../render/markdown.js';
import { CodeBlock } from '../../render/codeblock.js';
import { CodeExample, CodeExampleProvider } from '../../ui/lazy.js';
import { getPreferredType } from '../../utils/schema.js';
import { getRequestData } from '../../render/operation/get-request-data.js';
import { sample } from 'openapi-sampler';
import { encodeRequestData, } from '../../requests/_shared.js';
import { defaultSamples } from '../../requests/index.js';
export function APIExampleProvider({ examples, method, children, route, }) {
const exclusiveSampleKey = method['x-exclusiveCodeSample'];
return (_jsx(CodeExampleProvider, { initialKey: exclusiveSampleKey, route: route, examples: examples, children: children }));
}
export function getAPIExamples(path, method, ctx) {
const media = method.requestBody
? getPreferredType(method.requestBody.content)
: null;
const bodyOfType = media ? method.requestBody?.content[media] : null;
if (bodyOfType?.examples) {
const result = [];
for (const [key, value] of Object.entries(bodyOfType.examples)) {
const data = getRequestData(path, method, key, ctx);
result.push({
key,
name: value.summary ?? key,
description: value.description,
data,
encoded: encodeRequestData(data, ctx.mediaAdapters, method.parameters ?? []),
});
}
if (result.length > 0)
return result;
}
const data = getRequestData(path, method, null, ctx);
return [
{
key: '_default',
name: 'Default',
description: bodyOfType?.schema?.description,
data,
encoded: encodeRequestData(data, ctx.mediaAdapters, method.parameters ?? []),
},
];
}
export async function APIExample({ method, examples, ctx, }) {
const renderer = ctx.renderer;
const generators = dedupe([
...defaultSamples,
...(ctx.generateCodeSamples ? await ctx.generateCodeSamples(method) : []),
...(method['x-codeSamples'] ?? []),
]).filter((generator) => generator.source !== false);
const exclusiveSampleKey = method['x-exclusiveCodeSample'];
return (_jsxs(renderer.APIExample, { children: [examples.length > 1 && !exclusiveSampleKey && (_jsx(renderer.CodeExampleSelector, { items: examples.map((sample) => ({
title: sample.name,
description: sample.description ? (_jsx(Markdown, { text: sample.description })) : null,
value: sample.key,
})) })), generators.length > 0 && (_jsx(renderer.Requests, { items: generators.map((s) => s.label ?? s.lang), children: generators.map((generator, i) => (_jsx(renderer.Request, { name: generator.label ?? generator.lang, children: _jsx(CodeExample, { ...generator }) }, i))) })), _jsx(ResponseTabs, { operation: method, ctx: ctx })] }));
}
/**
* Remove duplicated labels
*/
function dedupe(samples) {
const set = new Set();
const out = [];
for (let i = samples.length - 1; i >= 0; i--) {
const item = samples[i];
if (item.label) {
if (set.has(item.label))
continue;
set.add(item.label);
}
out.unshift(item);
}
return out;
}
function ResponseTabs({ operation, ctx, }) {
const { renderer } = ctx;
if (!operation.responses)
return null;
async function renderResponse(code) {
const response = operation.responses?.[code];
const media = response?.content ? getPreferredType(response.content) : null;
const responseOfType = media ? response?.content?.[media] : null;
let slot = 'Empty';
if (responseOfType?.examples) {
const values = [];
const children = Object.entries(responseOfType.examples).map(([key, sample]) => {
const title = sample?.summary ?? `Example ${key}`;
values.push(title);
return (_jsxs(renderer.ResponseType, { label: title, children: [sample?.description && _jsx(Markdown, { text: sample.description }), _jsx(CodeBlock, { lang: "json", code: JSON.stringify(sample.value, null, 2), ctx: ctx })] }, key));
});
slot = (_jsx(renderer.ResponseTypes, { defaultValue: values[0], children: children }));
}
else if (responseOfType?.example || responseOfType?.schema) {
slot = (_jsx(CodeBlock, { lang: "json", code: JSON.stringify(responseOfType.example ?? sample(responseOfType.schema), null, 2), ctx: ctx }));
}
return _jsx(renderer.Response, { value: code, children: slot });
}
const codes = Object.keys(operation.responses);
if (codes.length === 0)
return null;
return (_jsx(renderer.Responses, { items: codes, children: codes.map((code) => renderResponse(code)) }));
}