UNPKG

vulcain-corejs

Version:
353 lines 14.1 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 __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; Object.defineProperty(exports, "__esModule", { value: true }); const annotations_1 = require("../../di/annotations"); const domain_1 = require("../../schemas/domain"); const conventions_1 = require("../../utils/conventions"); const index_1 = require("../../index"); let SwaggerServiceDescriptor = class SwaggerServiceDescriptor { constructor(container, domain) { this.container = container; this.domain = domain; } async getDescriptions(serviceDescription) { let descriptions = this.initialize(); descriptions.info.version = serviceDescription.serviceVersion; descriptions.info.title = serviceDescription.serviceName; descriptions.tags = this.computeTags(serviceDescription.services); descriptions.definitions = this.computeDefinitions(serviceDescription.schemas); descriptions.paths = this.computePaths(serviceDescription); descriptions.host = this.context.hostName; descriptions.basePath = conventions_1.Conventions.instance.defaultUrlprefix; return descriptions; } initialize() { return { swagger: '2.0', info: { 'version': '1.0.0', 'title': index_1.Service.fullServiceName }, schemes: [ 'http' ], basePath: conventions_1.Conventions.instance.defaultUrlprefix, paths: {}, definitions: {} }; } /** * Getting all endpoint Handler (only the first word) * Example : {verb : "customer.myAction" } it's `customer` who is kept * @param services * @return string[] */ computeTags(services) { let tags = []; let tagsSet = new Set(); services.forEach((service) => { //service.verb = 'customer.myAction' // with split we kept only 'customer' //split for getting first word let parts = service.verb.split('.'); if (parts.length === 2) tagsSet.add(parts[0]); }); let allTags = [...tagsSet]; tags = allTags.map((tag) => { return { name: tag, description: '' }; }); return tags; } /** * Format the path to swagger json format. * See the documentation here : http://swagger.io/specification/#pathsObject * @param services */ computePaths(serviceDescription) { let paths = {}; serviceDescription.services.forEach((service) => { if (service.name.startsWith("_")) return; let operationObject = {}; operationObject.tags = [service.verb.split('.')[0]]; operationObject.summary = service.description; operationObject.description = service.description; if (service.inputSchema) operationObject.consumes = ['application/json']; operationObject.produces = ['application/json']; operationObject.parameters = this.computeParameters(serviceDescription.schemas, service); this.computeResponses(service, operationObject); paths[`/${service.verb}`] = { [service.kind === 'action' ? 'post' : 'get']: operationObject }; }); return paths; } createResponseDefinition(listResponse, payload) { let res = { type: 'object', properties: { meta: { type: "object", properties: { correlationId: { type: 'string' } } } } }; if (listResponse) { res.properties.meta.properties.totalCount = { type: 'number' }; res.properties.meta.properties.pageSize = { type: 'number' }; res.properties.meta.properties.page = { type: 'number' }; } if (payload) res.properties = Object.assign(res.properties, payload); return res; } computeResponses(service, operationObject) { operationObject.responses = {}; operationObject.responses['400'] = { description: 'Invalid input', schema: { type: 'object', properties: { meta: { type: "object", properties: { correlationId: { type: 'string' } } }, error: { type: "object", properties: { message: { type: 'string' }, errors: { type: "object", additionalProperties: { type: 'string' }, example: { firstName: "FirstName is required", lastName: "lastName must be in upper case" } } } } } } }; if (service.scope !== '?') { operationObject.responses['401'] = { description: 'Not authentified' }; operationObject.responses['403'] = { description: 'Not authorized' }; } operationObject.responses['500'] = { description: 'Invalid input', schema: { type: 'object', properties: { meta: { type: "object", properties: { correlationId: { type: 'string' } } }, error: { type: "object", properties: { message: { type: 'string' } } } } } }; if (service.async) { operationObject.responses['200'] = { description: 'Processing task', schema: this.createResponseDefinition(false, { meta: { type: "object", properties: { status: { type: "string" }, taskId: { type: "string" } } } }) }; } else { operationObject.responses['200'] = { description: 'Successful operation', schema: this.createResponseDefinition(service.kind === "query" && service.name === "all") }; if (service.outputSchema) { operationObject.responses['200'].schema.properties.value = {}; this.setReferenceDefinition(operationObject.responses['200'].schema.properties.value, service.outputSchema, service.outputCardinality); } } } /** * Format the json parameters object for swagger * See the documentation here: http://swagger.io/specification/#parameterObject * @param service */ computeParameters(schemas, service) { if (service.kind === 'get') { let params = [ { name: 'id', description: "Unique id", in: 'path', type: 'string', required: true } ]; return params; } else if (service.kind === 'query') { let parms = []; if (service.inputSchema) { let schema = schemas.find(sch => sch.name === service.inputSchema); if (schema) { schema.properties.forEach((property) => { let param = {}; param.name = property.name; param.description = property.description || property.typeDescription; param['in'] = 'query'; param.required = property.required; param['schema'] = { type: property.type, description: property.typeDescription }; parms.push(param); }); } } return parms.concat([ { name: '$query', in: 'query', description: "Filter query", type: 'string', required: false }, { name: '$page', in: 'query', description: "Skip to page", type: 'number', required: false }, { name: '$pageSize', in: 'query', description: "Max items by page", type: 'number', required: false } ]); } else if (service.inputSchema) { let parameters = {}; parameters.name = 'args'; parameters['in'] = 'body'; parameters.required = true; parameters.description = "Argument"; parameters['schema'] = {}; this.setReferenceDefinition(parameters['schema'], service.inputSchema); return [parameters]; } return []; } /** * Format the json definitions for swagger type * See the documentation here : http://swagger.io/specification/#definitionsObject * @param schemas * @return DefinitionObject */ computeDefinitions(schemas) { let definitions = {}; let currentDef = {}; schemas.forEach((schema) => { currentDef[schema.name] = Object.assign({ type: SwaggerServiceDescriptor.defaultDefinitionType }, this.createDefinition(schema)); }); return currentDef; } createDefinition(schema) { let jsonSchema = { properties: {} }; let required = []; schema.properties.forEach((property) => { jsonSchema.properties[property.name] = { type: property.type, description: property.typeDescription }; if (property.definition.cardinality === 'one' || property.definition.cardinality === 'many') { this.setReferenceDefinition(jsonSchema.properties[property.name], property.type, property.definition.cardinality); } if (property.description) { jsonSchema.properties[property.name].description = property.description; } if (property.required) { required.push(property.name); } }); if (required.length) jsonSchema.required = required; return jsonSchema; } setReferenceDefinition(desc, definitionName, propertyReference = 'one') { if (propertyReference === 'one') { if (definitionName !== 'any') { if (this.isFundamentalObject(definitionName)) { desc['type'] = definitionName; } else { desc['$ref'] = `#/definitions/${definitionName}`; } } } else { // is a 'many' output cardinality desc['type'] = 'array'; let def = definitionName; let pos = def.indexOf('[]'); if (pos > 0) def = def.substr(0, pos); // remove final [] if (def !== 'any') { let items = desc['items'] = {}; if (this.isFundamentalObject(def)) { items['type'] = def; } else { items['$ref'] = `#/definitions/${def}`; } } else { desc.items = { type: 'object' }; } } } isFundamentalObject(inputSchema) { let type = this.domain.getType(inputSchema); if (!type) return false; return this.domain.getScalarTypeOf(type); } }; SwaggerServiceDescriptor.defaultDefinitionType = "object"; SwaggerServiceDescriptor = __decorate([ __param(0, annotations_1.Inject(annotations_1.DefaultServiceNames.Container)), __param(1, annotations_1.Inject(annotations_1.DefaultServiceNames.Domain)), __metadata("design:paramtypes", [Object, domain_1.Domain]) ], SwaggerServiceDescriptor); exports.SwaggerServiceDescriptor = SwaggerServiceDescriptor; //# sourceMappingURL=swaggerServiceDescriptions.js.map