@alauda/doom
Version:
Doctor Doom making docs.
148 lines (147 loc) • 8.62 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { usePage } from '@rspress/core/runtime';
import { Badge } from '@rspress/core/theme-original';
import BananaSlug from '@rspress/shared/github-slugger';
import openapisMap from 'doom-@api-openapisMap';
import virtual from 'doom-@api-virtual';
import { OpenAPIV3 } from 'openapi-types';
import { Fragment, useMemo } from 'react';
import { omitRoutePathRefs, resolveRef } from '../utils.js';
import { Markdown } from './Markdown.js';
import { OpenAPIProperties, OpenAPIProperty, OpenAPIRef } from './OpenAPIRef.js';
import { HeadingTitle } from './_HeadingTitle.js';
import { RefLink } from './_RefLink.js';
import { X } from './_X.js';
export const OpenAPIParameters = ({ parameters, openapi, }) => {
return (_jsx(X.ul, { children: parameters.map((param, index) => {
const paramObj = '$ref' in param
? resolveRef(openapi, param.$ref)
: param;
const type = paramObj.schema &&
('$ref' in paramObj.schema ? paramObj.schema : paramObj.schema.type);
let typeNode;
if (typeof type === 'string') {
typeNode = _jsx("code", { children: type });
}
else if (type) {
typeNode = _jsx(RefLink, { "$ref": type.$ref });
}
return (_jsxs(X.li, { children: [_jsx("code", { children: paramObj.name }), " (", _jsxs("em", { children: ["in ", paramObj.in] }), "): ", typeNode, paramObj.required && (_jsxs(_Fragment, { children: [' ', _jsx(Badge, { children: "required" })] })), _jsxs(_Fragment, { children: [' ', _jsx(Markdown, { children: paramObj.description })] })] }, index));
}) }));
};
export const OpenAPIResponses = ({ responses, openapi, }) => {
return (_jsx(X.ul, { children: Object.entries(responses).map(([code, response]) => {
const responseObj = '$ref' in response
? resolveRef(openapi, response.$ref)
: response;
const responseContent = responseObj.content;
const schema = (responseContent?.['application/json'] ?? responseContent?.['*/*'])?.schema;
const type = schema && ('$ref' in schema ? schema : schema.type);
let typeNode;
let extraNode;
if (typeof type === 'string') {
typeNode = _jsx("code", { children: type });
if (type === 'object' &&
'properties' in schema &&
schema.properties) {
extraNode = (_jsxs("div", { className: "my-4", children: [_jsx("em", { children: "Properties:" }), _jsx(OpenAPIProperties, { properties: schema.properties, openapi: openapi })] }));
}
else if (type === 'array' && 'items' in schema && schema.items) {
extraNode = (_jsxs("div", { className: "my-4", children: [_jsx("em", { children: "Items:" }), _jsx(OpenAPIProperty, { property: schema.items, openapi: openapi })] }));
}
}
else if (type && '$ref' in type) {
typeNode = _jsx(RefLink, { "$ref": type.$ref });
}
return (_jsxs(X.li, { children: [_jsx("code", { children: code }), " ", typeNode, ": ", responseObj.description, extraNode] }, code));
}) }));
};
const setRefsForPath = (openapi, path, knownRefs, refs) => {
const pathSchema = openapi.paths?.[path];
if (!pathSchema) {
return;
}
const collectRefs = (schema) => {
if ('$ref' in schema && typeof schema.$ref === 'string') {
const ref = schema.$ref.replace(/^#\/components\/[^/]+\//, '');
if (!knownRefs[ref]) {
refs.add(ref);
schema = resolveRef(openapi, schema.$ref);
}
}
for (const value of Object.values(schema)) {
if (value && typeof value === 'object') {
collectRefs(value);
}
}
};
for (const method of Object.values(OpenAPIV3.HttpMethods)) {
if (pathSchema[method]?.requestBody) {
collectRefs(pathSchema[method].requestBody);
}
if (pathSchema[method]?.responses) {
for (const response in pathSchema[method].responses) {
collectRefs(pathSchema[method].responses[response]);
}
}
}
};
const OpenAPIPathBase = ({ path, pathItem, openapi, pathPrefix: pathPrefix_, slugger, }) => {
const pathPrefix = pathPrefix_ ?? (virtual.pathPrefix || '');
if (!pathItem || !openapi) {
console.error(`No OpenAPI path definition found for ${path}`);
return null;
}
return (_jsxs(_Fragment, { children: [_jsxs(HeadingTitle, { slugger: slugger, level: 2, children: [pathPrefix, path] }), pathItem.parameters && (_jsxs(_Fragment, { children: [_jsx(HeadingTitle, { slugger: slugger, level: 3, children: "Common Parameters" }), _jsx(OpenAPIParameters, { parameters: pathItem.parameters, openapi: openapi })] })), Object.values(OpenAPIV3.HttpMethods).map((method) => {
if (!pathItem[method]) {
return null;
}
const { description, parameters, requestBody, responses, summary } = pathItem[method];
const requestBodyRef = requestBody &&
('$ref' in requestBody
? requestBody.$ref
: /* eslint-disable @typescript-eslint/no-unnecessary-condition */
(requestBody.content['application/json'] ||
requestBody.content['application/json-patch+json'] ||
requestBody.content['*/*'])?.schema?.$ref);
/* eslint-enable @typescript-eslint/no-unnecessary-condition */
const requestBodySchema = requestBodyRef
? resolveRef(openapi, requestBodyRef)
: undefined;
return (_jsxs(Fragment, { children: [_jsxs(HeadingTitle, { slugger: slugger, level: 3, children: [_jsx("code", { children: method }), " ", summary] }), _jsx(Markdown, { children: description }), parameters && (_jsxs(_Fragment, { children: [_jsx(HeadingTitle, { slugger: slugger, level: 4, children: "Parameters" }), _jsx(OpenAPIParameters, { parameters: parameters, openapi: openapi })] })), requestBodySchema && (_jsxs(_Fragment, { children: [_jsx(HeadingTitle, { slugger: slugger, level: 4, children: "Request Body" }), _jsxs(X.p, { children: [_jsx(RefLink, { "$ref": requestBodyRef }), requestBodySchema.required && _jsx(Badge, { children: "required" })] })] })), responses && (_jsxs(_Fragment, { children: [_jsx(HeadingTitle, { slugger: slugger, level: 4, children: "Response" }), _jsx(OpenAPIResponses, { responses: responses, openapi: openapi })] }))] }, method));
})] }));
};
export const OpenAPIPath = ({ path, openapiPath, pathPrefix, }) => {
const { page } = usePage();
const { paths, pathMap, refMap } = useMemo(() => {
const paths = Array.isArray(path) ? path : [path];
const pathMap = new Map();
const refMap = new Map();
for (const [pathname, openapi] of Object.entries(openapisMap)) {
if (openapiPath && pathname !== openapiPath) {
continue;
}
for (const path of paths) {
const pathItem = openapi.paths?.[path];
if (pathItem) {
pathMap.set(path, {
pathItem,
openapi,
});
if (!refMap.has(pathname)) {
refMap.set(pathname, new Set());
}
const refs = refMap.get(pathname);
setRefsForPath(openapi, path, omitRoutePathRefs(page.routePath), refs);
}
}
}
return { paths, pathMap, refMap };
}, [openapiPath, page.routePath, path]);
const slugger = useMemo(() => new BananaSlug(), []);
return (_jsxs(_Fragment, { children: [paths.map((path) => {
const p = pathMap.get(path);
return (_jsx(OpenAPIPathBase, { path: path, pathItem: p?.pathItem, openapi: p?.openapi, pathPrefix: pathPrefix, slugger: slugger }, path));
}), [...refMap.entries()].map(([openapiPath, refs]) => (_jsx(Fragment, { children: [...refs].map((ref) => (_jsx(OpenAPIRef, { schema: ref, openapiPath: openapiPath, collectRefs: false }, ref))) }, openapiPath)))] }));
};
export default OpenAPIPath;