redis-smq-rest-api
Version:
A RESTful API for RedisSMQ
122 lines • 4.39 kB
JavaScript
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