modarb-be / src /lib /swagger /swagger.ts
moahmedwafy's picture
update: swagger
2228807
raw
history blame
5.33 kB
import { config } from "@configs/config";
/**
* Swagger registry class.
*/
class SwaggerRegistry {
public controllersRegistry = new Map<
any,
{
routes: {
propertyKey: string;
path?: string;
method?: "get" | "post" | "put" | "patch" | "delete";
request?: any;
response?: any;
queryParams?: any;
description?: string;
summary?: string;
tags?: string[];
}[];
prefix: string;
tags?: string[];
}
>();
public schemasRegistry = new Map<
any,
{
properties: {
[key: string]: any;
};
propertiesToExclude: string[];
}
>();
public initSchemaIfNotExists(schema: any) {
if (!this.schemasRegistry.has(schema)) {
this.schemasRegistry.set(schema, {
properties: {},
propertiesToExclude: [],
});
}
}
public updateSchemaProperty(props: {
schema: any;
property: string;
newName?: string;
type: any;
}) {
this.initSchemaIfNotExists(props.schema);
const data = this.schemasRegistry.get(props.schema);
data.properties[props.newName || props.property] = { type: props.type };
if (props.newName) {
data.propertiesToExclude.push(props.property);
}
this.schemasRegistry.set(props.schema, data);
}
public initControllerIfNotExists(controller: any, prefix: string = "") {
if (!this.controllersRegistry.has(controller)) {
this.controllersRegistry.set(controller, {
routes: [],
prefix,
});
}
}
public setControllerPrefix(controller: any, prefix: string) {
this.initControllerIfNotExists(controller);
const data = this.controllersRegistry.get(controller);
data.prefix = prefix;
this.controllersRegistry.set(controller, data);
}
public updateRoute(
controller: any,
params: {
propertyKey: string;
path?: string;
method?: "get" | "post" | "put" | "patch" | "delete";
request?: any;
response?: any;
queryParams?: any;
description?: string;
summary?: string;
tags?: string[];
}
) {
this.initControllerIfNotExists(controller);
const data = this.controllersRegistry.get(controller);
// delete undefined keys
Object.keys(params).forEach(
(key) => params[key] === undefined && delete params[key]
);
const route = data.routes.find(
(route) => route.propertyKey === params.propertyKey
);
if (route) {
Object.assign(route, params);
} else {
data.routes.push(params);
}
this.controllersRegistry.set(controller, data);
}
public setControllerTags(controller: any, tags: string[]) {
this.initControllerIfNotExists(controller);
const data = this.controllersRegistry.get(controller);
data.tags = tags;
this.controllersRegistry.set(controller, data);
}
public generateSwaggerDocument() {
const paths: any = {};
this.controllersRegistry.forEach((value) => {
const controllerData = value;
controllerData.routes.forEach((route) => {
route.path = `/api/v1${controllerData.prefix}${route.path}`;
// convert :param to {param}
route.path = route.path.replace(/:(\w+)/g, "{$1}");
const params = route.path.match(/{(\w+)}/g);
if (!paths[route.path]) {
paths[route.path] = {};
}
paths[route.path][route.method] = {
security: [
{
bearerAuth: [],
},
],
tags: [...(controllerData.tags || []), ...(route.tags || [])],
summary: route.summary,
description: route.description,
parameters: [
...((params &&
params.map((param) => {
return {
name: param.replace(/{|}/g, ""),
in: "path",
required: true,
schema: {
type: "string",
},
};
})) ||
[]),
...(route.queryParams || []),
],
responses: {
200: {
description: "Success",
content: {
"application/json": {
schema: route.response,
},
},
},
},
};
if (route.request) {
paths[route.path][route.method].requestBody = {
content: {
"application/json": {
schema: route.request,
},
},
};
}
});
});
const document = {
openapi: "3.0.0",
info: {
title: "Modarb API Documentation",
version: "1.0.0",
description: "Look! Docs!",
},
servers: [
{
url: config.swaggerServer || `${config.host}:${config.port}`,
},
],
security: [
{
bearerAuth: [],
},
],
paths,
components: {
securitySchemes: {
bearerAuth: {
type: "http",
scheme: "bearer",
bearerFormat: "JWT",
},
},
},
};
//console.log(JSON.stringify(document, null, 2));
return document;
}
}
export const swaggerRegistry = new SwaggerRegistry();