UNPKG

redis-smq-rest-api

Version:
122 lines 4.39 kB
import { writeFile } from 'fs/promises'; import { resolve } from 'path'; import { constants } from '../../config/constants.js'; import { EControllerRequestPayload } from '../controller/types/index.js'; import { SchemaGenerator } from '../validator/schema-generator.js'; import { getOpenApiRoutes } from './adaptor.js'; async function toOpenAPISchema(schema) { const { default: toOpenApiSchema } = await import('@openapi-contrib/json-schema-to-openapi-schema'); return toOpenApiSchema(schema); } async function getRequestParameters(schema, payloadSource) { if (schema.$ref) { const def = (schema.definitions || {})[schema.$ref]; if (typeof def !== 'object') throw new Error(`Schema ${schema.$ref} not found.`); schema = def; } if (schema.definitions) delete schema.definitions; if (payloadSource === EControllerRequestPayload.PATH || payloadSource === EControllerRequestPayload.QUERY) { const parameters = []; for (const property in schema.properties) { const prop = schema.properties[property]; if (typeof prop !== 'boolean') { const { description = '', ...propSchema } = prop; const param = { name: property, in: payloadSource === EControllerRequestPayload.PATH ? 'path' : 'query', required: schema.required?.includes(property) || false, schema: await toOpenAPISchema(propSchema), description, }; parameters.push(param); } } return parameters; } return []; } async function getRequestBody(schema, payloadSource, contentType = 'application/json') { if (payloadSource === EControllerRequestPayload.BODY && schema.properties && Object.keys(schema.properties).length) { if (schema.definitions) delete schema.definitions; return { required: true, content: { [contentType]: { schema: await toOpenAPISchema(schema) }, }, }; } return null; } async function getResponses(schemaMap) { const responses = {}; for (const [status, schema] of schemaMap) { if (schema.definitions) delete schema.definitions; responses[status] = { description: '', content: { 'application/json': { schema: await toOpenAPISchema(schema), }, }, }; } return responses; } async function buildOpenApiDocument(routes, basePath = '/') { const spec = { openapi: '3.0.0', info: { title: 'RedisSMQ HTTP API specification', version: '8.0.0', }, components: { schemas: {} }, servers: [ { url: basePath, }, ], paths: {}, }; for (const route of routes) { const { path, method, description, tags } = route; const operation = { responses: {}, description, tags, }; operation.parameters = []; for (const [payloadSource, schema] of route.requestParamsSchemas) { operation.parameters.push(...(await getRequestParameters(schema, payloadSource))); const requestBody = await getRequestBody(schema, payloadSource); if (requestBody) operation.requestBody = requestBody; } if (!operation.parameters.length) delete operation.parameters; operation.responses = await getResponses(route.response); spec.paths[path] = { ...spec.paths[path], [method]: operation, }; } return spec; } export async function generateOpenApiDocument(routingMap, basePath = '/') { const schema = SchemaGenerator(); const openApiRoutes = await getOpenApiRoutes(routingMap, schema); return buildOpenApiDocument(openApiRoutes, basePath); } export async function saveOpenApiDocument(spec, dir) { const { openApiDocumentFilename } = constants; const openApiDocumentPath = resolve(dir, openApiDocumentFilename); await writeFile(openApiDocumentPath, JSON.stringify(spec)); return openApiDocumentPath; } //# sourceMappingURL=builder.js.map