@micro.ts/core
Version:
Microservice framework with Typescript
243 lines (242 loc) • 9.79 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SpecBuilder = void 0;
const joi_to_swagger_1 = __importDefault(require("joi-to-swagger"));
const MetadataHelpers_1 = require("joi-typescript-validator/lib/utils/MetadataHelpers");
const HttpBroker_1 = require("../brokers/http/HttpBroker");
const decorators_1 = require("../decorators");
const __1 = require("..");
const joi_typescript_validator_1 = require("joi-typescript-validator");
let SpecBuilder = class SpecBuilder {
constructor() {
this.schemas = new Map();
this.paths = {};
}
getServerPath(server) {
return {
url: "{url}",
description: server.name,
variables: {
url: {
default: server.getFullPath()
}
}
};
}
getSchemaPath(obj) {
if (!this.schemas.has(obj)) {
const joiSchema = (0, joi_typescript_validator_1.getSchema)(obj);
const schema = (0, joi_to_swagger_1.default)(joiSchema);
this.schemas.set(obj, schema["swagger"]);
}
return `#/components/schemas/${obj.name}`;
}
registerRoute(def, brokers, params) {
var _a;
const httpBrokers = brokers
.filter(x => {
return x.constructor.prototype instanceof HttpBroker_1.HttpBroker;
})
.map(x => {
return x;
});
if (httpBrokers.length === 0) {
return;
}
const server = this.getServerPath(httpBrokers[0]);
if (httpBrokers.length > 0) {
server.variables = server.variables || {};
server.variables.url = server.variables.url || { default: "" };
server.variables.url["enum"] = server.variables.url["enum"] || [];
}
for (let i = 0; i < httpBrokers.length; i++) {
server.variables.url.enum.push(httpBrokers[i].getFullPath());
}
const path = this.extractPath(def);
const obj = this.paths[path] || {};
const mappedParams = {
body: [],
header: [],
path: [],
query: []
};
params.forEach(p => {
if (p.options) {
const paramType = p.options.decoratorType;
if (paramType === decorators_1.ParamDecoratorType.Query ||
paramType === decorators_1.ParamDecoratorType.QueryField) {
mappedParams.query.push(p);
}
if (paramType === decorators_1.ParamDecoratorType.Body ||
paramType === decorators_1.ParamDecoratorType.BodyField) {
mappedParams.body.push(p);
}
if (paramType === decorators_1.ParamDecoratorType.Header ||
paramType === decorators_1.ParamDecoratorType.HeaderField) {
mappedParams.header.push(p);
}
if (paramType === decorators_1.ParamDecoratorType.Params ||
paramType === decorators_1.ParamDecoratorType.ParamField) {
mappedParams.path.push(p);
}
}
});
const operation = {
tags: [def.controllerCtor.name],
description: def.handlerName,
parameters: [
...this.buildPathParams(mappedParams.path),
...this.buildHeaderParams(mappedParams.header),
...this.buildQueryParams(mappedParams.query)
],
servers: [server],
responses: {}
};
const verb = (((_a = def.method) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) ||
"get");
if (verb !== "get") {
operation.requestBody = this.buildBodyParams(mappedParams.body);
}
obj[verb] = operation;
this.paths[path] = obj;
}
getDocument() {
return {
paths: this.paths,
components: { schemas: this.getAllSchemas() },
openapi: "3.0.0",
info: { title: "test", version: "1.0.0" }
};
}
buildPathParams(params) {
return this.buildParam(params, "path");
}
buildParam(params, inType) {
return params.reduce((accum, x) => {
var _a, _b, _c, _d;
if ((_a = x.options) === null || _a === void 0 ? void 0 : _a.name) {
accum.push({
name: ((_b = x.options) === null || _b === void 0 ? void 0 : _b.name) || "",
in: inType,
required: inType === 'header' ? !!((_c = x.options.headerParamOptions) === null || _c === void 0 ? void 0 : _c.required) : (inType === 'query' ? !!((_d = x.options.queryParamOptions) === null || _d === void 0 ? void 0 : _d.required) : true),
schema: { type: x.type.name.toLowerCase() }
});
}
else {
const objMetadata = (0, MetadataHelpers_1.getMetadata)(x.type);
if (objMetadata) {
Object.keys(objMetadata).forEach(fieldName => {
const item = {
name: fieldName,
in: inType,
required: !!objMetadata[fieldName].required,
explode: true
};
const obj = objMetadata[fieldName];
item.schema = this.getObjectSchema(obj.designType);
accum.push(item);
});
}
}
return accum;
}, []);
}
buildBodyParams(params) {
let contentSchema = { type: "object" };
params.forEach(param => {
var _a, _b, _c;
if (((_a = param.options) === null || _a === void 0 ? void 0 : _a.decoratorType) === decorators_1.ParamDecoratorType.Body) {
Object.assign(contentSchema, this.getObjectSchema(param.type));
}
else if (((_b = param.options) === null || _b === void 0 ? void 0 : _b.decoratorType) === decorators_1.ParamDecoratorType.BodyField) {
contentSchema.properties = contentSchema.properties || {};
if ((_c = param.options.bodyParamOptions) === null || _c === void 0 ? void 0 : _c.required) {
contentSchema.required = contentSchema.required || [];
if (!contentSchema.required.find(param.options.name)) {
contentSchema.required.push(param.options.name);
}
}
if (!contentSchema.properties[param.options.name]) {
contentSchema.properties[param.options.name] = this.getObjectSchema(param.type);
}
}
});
const result = {
content: {
"application/json": {
schema: contentSchema
}
}
};
return result;
}
buildHeaderParams(params) {
return this.buildParam(params, "header");
}
buildQueryParams(params) {
return this.buildParam(params, "query");
}
getObjectSchema(obj) {
if (!this.schemas.has(obj)) {
const joiSchema = (0, joi_typescript_validator_1.getSchema)(obj);
const schema = (0, joi_to_swagger_1.default)(joiSchema);
this.schemas.set(obj, schema["swagger"]);
}
return { $ref: `#/components/schemas/${obj.name}` };
}
extractPath(def) {
let basePart = def.base;
if (basePart && basePart.indexOf("/") !== 0) {
basePart = `/${basePart}`;
}
let controllerPart = def.controller;
if (controllerPart.indexOf("/") !== 0) {
controllerPart = `/${controllerPart}`;
}
let handlerPart = def.handler;
const params = this.extractParamNames(handlerPart);
handlerPart = params
.map(x => {
if (x.param) {
return `{${x.name}}`;
}
return x.name;
})
.join("/");
if (handlerPart.indexOf("/") !== 0 && handlerPart.length > 0) {
handlerPart = `/${handlerPart}`;
}
return `${basePart}${controllerPart}${handlerPart}`.replace(/\/\//g, "/");
}
extractParamNames(path, separator = "/") {
const spl = path.split(separator);
return spl.map(x => {
const value = { name: x, param: false };
if (x.length > 0 && x[0] === ":") {
value.name = x.substr(1);
value.param = true;
}
return value;
});
}
getAllSchemas() {
const result = {};
this.schemas.forEach((value, key) => {
result[key.name] = value;
});
return result;
}
};
SpecBuilder = __decorate([
(0, __1.Service)()
], SpecBuilder);
exports.SpecBuilder = SpecBuilder;