vulcain-corejs
Version:
Vulcain micro-service framework
353 lines • 14.1 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 __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