UNPKG

@alauda/doom

Version:

Doctor Doom making docs.

148 lines (147 loc) 8.62 kB
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;