mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 10:55:57 +00:00
132 lines
3.6 KiB
TypeScript
132 lines
3.6 KiB
TypeScript
import Slugger from 'github-slugger';
|
|
import { Operation } from '@/render/operation';
|
|
import type { RenderContext } from '@/types';
|
|
import { createMethod } from '@/server/create-method';
|
|
import { createRenders } from '@/render/renderer';
|
|
import type { OpenAPIV3_1 } from 'openapi-types';
|
|
import {
|
|
processDocumentCached,
|
|
type ProcessedDocument,
|
|
} from '@/utils/process-document';
|
|
import { defaultAdapters } from '@/media/adapter';
|
|
import type { SharedOpenAPIOptions } from '@/server';
|
|
|
|
export interface ApiPageProps extends SharedOpenAPIOptions {
|
|
document: Promise<ProcessedDocument> | string | ProcessedDocument;
|
|
hasHead: boolean;
|
|
|
|
/**
|
|
* An array of operations
|
|
*/
|
|
operations?: OperationItem[];
|
|
|
|
webhooks?: WebhookItem[];
|
|
}
|
|
|
|
export interface WebhookItem {
|
|
name: string;
|
|
method: OpenAPIV3_1.HttpMethods;
|
|
}
|
|
|
|
export interface OperationItem {
|
|
path: string;
|
|
method: OpenAPIV3_1.HttpMethods;
|
|
}
|
|
|
|
export async function APIPage(props: ApiPageProps) {
|
|
const { operations, hasHead = true, webhooks } = props;
|
|
const processed =
|
|
typeof props.document === 'string'
|
|
? await processDocumentCached(props.document)
|
|
: await props.document;
|
|
const ctx = await getContext(processed, props);
|
|
const { dereferenced } = processed;
|
|
|
|
return (
|
|
<ctx.renderer.Root ctx={ctx}>
|
|
{operations?.map((item) => {
|
|
const pathItem = dereferenced.paths?.[item.path];
|
|
if (!pathItem)
|
|
throw new Error(
|
|
`[Fumadocs OpenAPI] Path not found in OpenAPI schema: ${item.path}`,
|
|
);
|
|
|
|
const operation = pathItem[item.method];
|
|
if (!operation)
|
|
throw new Error(
|
|
`[Fumadocs OpenAPI] Method ${item.method} not found in operation: ${item.path}`,
|
|
);
|
|
|
|
const method = createMethod(item.method, pathItem, operation);
|
|
|
|
return (
|
|
<Operation
|
|
key={`${item.path}:${item.method}`}
|
|
method={method}
|
|
path={item.path}
|
|
ctx={ctx}
|
|
hasHead={hasHead}
|
|
/>
|
|
);
|
|
})}
|
|
{webhooks?.map((item) => {
|
|
const webhook = dereferenced.webhooks?.[item.name];
|
|
if (!webhook)
|
|
throw new Error(
|
|
`[Fumadocs OpenAPI] Webhook not found in OpenAPI schema: ${item.name}`,
|
|
);
|
|
|
|
const hook = webhook[item.method];
|
|
if (!hook)
|
|
throw new Error(
|
|
`[Fumadocs OpenAPI] Method ${item.method} not found in webhook: ${item.name}`,
|
|
);
|
|
|
|
const method = createMethod(item.method, webhook, hook);
|
|
|
|
return (
|
|
<Operation
|
|
type="webhook"
|
|
key={`${item.name}:${item.method}`}
|
|
method={method}
|
|
ctx={ctx}
|
|
path={`/${item.name}`}
|
|
hasHead={hasHead}
|
|
/>
|
|
);
|
|
})}
|
|
</ctx.renderer.Root>
|
|
);
|
|
}
|
|
|
|
export async function getContext(
|
|
schema: ProcessedDocument,
|
|
options: SharedOpenAPIOptions = {},
|
|
): Promise<RenderContext> {
|
|
const document = schema.dereferenced;
|
|
const servers =
|
|
document.servers && document.servers.length > 0
|
|
? document.servers
|
|
: [{ url: '/' }];
|
|
|
|
return {
|
|
schema,
|
|
proxyUrl: options.proxyUrl,
|
|
disablePlayground: options.disablePlayground,
|
|
showResponseSchema: options.showResponseSchema,
|
|
renderer: {
|
|
...createRenders(),
|
|
...options.renderer,
|
|
},
|
|
shikiOptions: options.shikiOptions,
|
|
generateTypeScriptSchema: options.generateTypeScriptSchema,
|
|
generateCodeSamples: options.generateCodeSamples,
|
|
servers,
|
|
mediaAdapters: {
|
|
...defaultAdapters,
|
|
...options.mediaAdapters,
|
|
},
|
|
slugger: new Slugger(),
|
|
};
|
|
}
|