UNPKG

@micro.ts/core

Version:

Microservice framework with Typescript

243 lines (242 loc) 9.79 kB
"use strict"; 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;