fets
Version:
TypeScript HTTP Framework focusing on e2e type-safety, easy setup, performance & great developer experience
163 lines (162 loc) • 7.65 kB
JavaScript
import { zodToJsonSchema } from 'zod-to-json-schema';
import { Response } from '../Response.js';
import swaggerUiHtml from '../swagger-ui-html.js';
import { isZodSchema } from '../zod/types.js';
export function useOpenAPI({ oasEndpoint, swaggerUIEndpoint, swaggerUIOpts, }) {
let paths;
return {
onRouterInit(router) {
paths = router.openAPIDocument.paths = router.openAPIDocument.paths || {};
if (oasEndpoint) {
router.route({
method: 'GET',
path: oasEndpoint,
handler: () => Response.json(router.openAPIDocument),
});
}
if (swaggerUIEndpoint) {
router.route({
method: 'GET',
path: swaggerUIEndpoint,
handler: () => new Response(swaggerUiHtml.replace('__SWAGGER_UI_OPTIONS__', JSON.stringify({
spec: router.openAPIDocument,
dom_id: '#swagger-ui',
displayOperationId: true,
tryItOutEnabled: true,
requestSnippetsEnabled: true,
displayRequestDuration: true,
defaultModelRendering: 'model',
defaultModelExpandDepth: 3,
defaultModelsExpandDepth: 3,
...swaggerUIOpts,
})), {
headers: {
'Content-Type': 'text/html',
},
}),
});
}
},
onRoute({ method, path, operationId, description, tags, schemas }) {
if (schemas) {
let pathForOAS = path.replace(/:([^/]+)/g, '{$1}');
if (!pathForOAS.startsWith('/')) {
pathForOAS = `/${pathForOAS}`;
}
const pathObj = (paths[pathForOAS] = paths[pathForOAS] || {});
const lowerCasedMethod = method.toLowerCase();
pathObj[lowerCasedMethod] = pathObj[lowerCasedMethod] || {};
const operation = pathObj[lowerCasedMethod];
operation.operationId = operationId;
operation.description = description;
operation.tags = tags;
if (schemas.responses) {
for (const statusCode in schemas.responses) {
let responseSchema = schemas.responses[statusCode];
if (isZodSchema(responseSchema)) {
responseSchema = zodToJsonSchema(responseSchema, {
target: 'openApi3',
});
}
operation.responses = operation.responses || {};
operation.responses[statusCode] = {
description: '',
content: {
'application/json': {
schema: responseSchema,
},
},
};
}
}
else {
operation.responses = {
default: {
description: '',
},
};
}
if (schemas.request?.headers) {
let headersSchema = schemas.request.headers;
if (isZodSchema(headersSchema)) {
headersSchema = zodToJsonSchema(headersSchema, {
target: 'openApi3',
});
}
for (const headerName in headersSchema.properties) {
const headerSchema = headersSchema.properties[headerName];
operation.parameters = operation.parameters || [];
operation.parameters.push({
name: headerName,
in: 'header',
required: headersSchema.required?.includes(headerName),
schema: headerSchema,
});
}
}
if (schemas.request?.params) {
let paramsSchema = schemas.request.params;
if (isZodSchema(paramsSchema)) {
paramsSchema = zodToJsonSchema(paramsSchema, {
target: 'openApi3',
});
}
for (const paramName in paramsSchema.properties) {
const paramSchema = paramsSchema.properties[paramName];
operation.parameters = operation.parameters || [];
operation.parameters.push({
name: paramName,
in: 'path',
required: paramsSchema.required?.includes(paramName),
schema: paramSchema,
});
}
}
if (schemas.request?.query) {
let queriesSchema = schemas.request.query;
if (isZodSchema(queriesSchema)) {
queriesSchema = zodToJsonSchema(queriesSchema, {
target: 'openApi3',
});
}
for (const queryName in queriesSchema.properties) {
const querySchema = queriesSchema.properties[queryName];
operation.parameters = operation.parameters || [];
operation.parameters.push({
name: queryName,
in: 'query',
required: queriesSchema.required?.includes(queryName),
schema: querySchema,
});
}
}
if (schemas.request?.json) {
let requestJsonSchema = schemas.request.json;
if (isZodSchema(requestJsonSchema)) {
requestJsonSchema = zodToJsonSchema(requestJsonSchema, {
target: 'openApi3',
});
}
const requestBody = (operation.requestBody = (operation.requestBody || {}));
const requestBodyContent = (requestBody.content = (requestBody.content || {}));
requestBodyContent['application/json'] = {
schema: requestJsonSchema,
};
}
if (schemas.request?.formData) {
const requestBody = (operation.requestBody = (operation.requestBody || {}));
const requestBodyContent = (requestBody.content = (requestBody.content || {}));
let requestFormDataSchema = schemas.request.formData;
if (isZodSchema(requestFormDataSchema)) {
requestFormDataSchema = zodToJsonSchema(requestFormDataSchema, {
target: 'openApi3',
});
}
requestBodyContent['multipart/form-data'] = {
schema: requestFormDataSchema,
};
}
}
},
};
}