UNPKG

fets

Version:

TypeScript HTTP Framework focusing on e2e type-safety, easy setup, performance & great developer experience

163 lines (162 loc) 7.65 kB
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, }; } } }, }; }