UNPKG

vulcain-corejs

Version:
291 lines (289 loc) 12.8 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); } }; const schema_1 = require('./../schemas/schema'); const annotations_1 = require('../di/annotations'); const annotations_2 = require('./../schemas/annotations'); const runtimeError_1 = require('./../errors/runtimeError'); const system_1 = require('./../configurations/globals/system'); class PropertyDescription { } exports.PropertyDescription = PropertyDescription; class SchemaDescription { } exports.SchemaDescription = SchemaDescription; class ActionDescription { } exports.ActionDescription = ActionDescription; let ServiceDescription = class ServiceDescription { }; ServiceDescription = __decorate([ annotations_2.Model(), __metadata('design:paramtypes', []) ], ServiceDescription); exports.ServiceDescription = ServiceDescription; class ServiceDescriptors { constructor(container, domain) { this.container = container; this.domain = domain; this.handlers = new Array(); this.routes = new Map(); this.monoSchema = true; } getDescriptions() { this.createHandlersTable(); return this.descriptions; } getHandlerInfo(container, schema, action, optional) { this.createHandlersTable(); let a = action && action.toLowerCase(); let item; if (this.monoSchema || !schema) { item = this.routes.get(a); } else { let s = schema && schema.toLowerCase(); item = this.routes.get(s + "." + a); } if (!item) { if (optional) return null; else throw new runtimeError_1.RuntimeError(`no handler method founded for action ${action}, schema ${schema}`); } try { let handler = container && container.resolve(item.handler); return { handler: handler, metadata: item.metadata, method: item.methodName, kind: item.kind }; } catch (e) { system_1.System.log.error(null, e, `Unable to create handler action ${action}, schema ${schema}`); throw new Error(`Unable to create handler for action ${action}, schema ${schema}`); } } createHandlersTable() { if (!this.handlers) return; let scopes = this.container.get(annotations_1.DefaultServiceNames.ScopesDescriptor); let schemas = new Map(); // Check if there is only one Schema let lastSchema; this.handlers.forEach(item => { if (!item.metadata.schema) return; if (!lastSchema) lastSchema = item.metadata.schema; else if (item.metadata.schema !== lastSchema) { this.monoSchema = false; } }); this.descriptions = { services: [], schemas: new Array(), domain: this.domain.name, serviceName: system_1.System.serviceName, serviceVersion: system_1.System.serviceVersion, alternateAddress: null, hasAsyncTasks: false, scopes: scopes.getScopes().map(d => { return { name: d.name, description: d.description }; }) }; for (let item of this.handlers.filter(h => h.kind === "action")) { let schema = this.getSchemaDescription(schemas, item.metadata.schema); let verb = !item.metadata.schema || this.monoSchema ? item.metadata.action : schema + "." + item.metadata.action; verb = verb.toLowerCase(); if (this.routes.has(verb)) throw new Error(`*** Duplicate handler for action ${item.metadata.action} for handler ${item.handler.name}`); system_1.System.log.info(null, "Handler registered for action verb %s", verb); this.routes.set(verb, item); let metadata = item.metadata; metadata.scope = this.checkScopes(scopes, metadata.scope, verb); metadata.inputSchema = this.getSchemaDescription(schemas, metadata.inputSchema, schema); metadata.outputSchema = !metadata.async && this.getSchemaDescription(schemas, metadata.outputSchema, schema); let desc = { schema: schema, kind: "action", async: metadata.async, verb: verb, description: metadata.description, action: metadata.action, scope: metadata.scope, inputSchema: metadata.inputSchema, outputSchema: metadata.outputSchema }; if (metadata.async) this.descriptions.hasAsyncTasks = true; this.descriptions.services.push(desc); } for (let item of this.handlers.filter(h => h.kind === "query")) { let schema = item.metadata.schema && this.getSchemaDescription(schemas, item.metadata.schema); let verb = !item.metadata.schema || this.monoSchema ? item.metadata.action : schema + "." + item.metadata.action; verb = verb.toLowerCase(); if (this.routes.has(verb)) throw new Error(`*** Duplicate handler for query ${item.metadata.action} for handler ${item.handler.name}`); system_1.System.log.info(null, "Handler registered for query verb %s", verb); this.routes.set(verb, item); if (item.metadata.action.startsWith("_service")) continue; let metadata = item.metadata; metadata.inputSchema = this.getSchemaDescription(schemas, metadata.inputSchema); metadata.outputSchema = this.getSchemaDescription(schemas, metadata.outputSchema, schema); metadata.scope = this.checkScopes(scopes, metadata.scope, verb); let desc = { schema: schema, kind: metadata.action === "get" ? "get" : "query", verb: verb, description: metadata.description, action: metadata.action, scope: metadata.scope, async: false, inputSchema: metadata.inputSchema, outputSchema: metadata.outputSchema }; if (desc.action === "get" && !desc.inputSchema) desc.inputSchema = "string"; if (desc.action !== "get") desc.outputSchema = desc.outputSchema; this.descriptions.services.push(desc); } this.sortSchemasDependencies(); this.handlers = null; } checkScopes(scopes, scope, verb) { if (!scope || scope === "?" || scope === "*") return scope; let parts = scope.split(','); let result = []; for (let sc of parts) { sc = system_1.System.domainName + ":" + sc.trim(); if (!scopes.getScopes().find(s => s.name === sc)) throw new Error(`${sc} not found in scopes descriptor for ${verb}. You must define it in (Startup)application.defineScopes.`); result.push(sc); } return result.join(','); } getSchemaDescription(schemas, schemaName, defaultValue) { if (schemaName === "none") return; if (!schemaName) return defaultValue; let schema; if (typeof schemaName === "string") { if (ServiceDescriptors.nativeTypes.indexOf(schemaName) >= 0) return schemaName; let type = this.getPropertyType(schemaName); if (type) return type.name; } schema = this.domain.getSchema(schemaName); if (!schema) throw new Error("Unknow schema " + schemaName); let desc = schemas.get(schema.name); if (desc) return desc.name; desc = { name: schema.name, properties: [], dependencies: new Set() }; schemas.set(schema.name, desc); this.descriptions.schemas.push(desc); for (let k of Object.keys(schema.description.properties)) { const p = schema.description.properties[k]; let type = this.getPropertyType(p.item || p.type); if (type) { let metadata = { type: p.type, item: p.item, values: p.values, required: p.required, description: p.description }; let pdesc = { name: k, type: p.item ? type.name + "[]" : type.name, required: p.required, description: p.description, metadata: metadata }; // Insert required at the beginning if (!pdesc.required) desc.properties.push(pdesc); else desc.properties.unshift(pdesc); } } for (let k of Object.keys(schema.description.references)) { const r = schema.description.references[k]; if (schemas.has(k)) return k; this.getSchemaDescription(schemas, r.item); let metadata = { item: r.item, cardinality: r.cardinality, required: r.required, description: r.description }; let pdesc = { name: k, reference: r.cardinality, type: r.cardinality === "many" ? r.item + "[]" : r.item, required: false, description: r.description, metadata: metadata }; if (r.item !== "any") desc.dependencies.add(r.item); // Insert required at the beginning if (!pdesc.required) desc.properties.push(pdesc); else desc.properties.unshift(pdesc); } return desc.name; } getPropertyType(name) { while (true) { let type = this.domain._findType(name); if (!type) { name = name.toLowerCase(); type = this.domain._findType(name); } if (!type || (!type.type && !type.item)) { if (type) type.name = name; return type; } name = type.type || type.item; } } sortSchemasDependencies() { this.descriptions.schemas = this.descriptions.schemas.sort((a, b) => { if (a.dependencies.has(b.name)) return 1; return -1; }); this.descriptions.schemas.forEach((s) => delete s.dependencies); } register(container, domain, target, actions, handlerMetadata, kind) { handlerMetadata = handlerMetadata || { scope: "*" }; if (handlerMetadata.schema) { // test if exists let tmp = domain.getSchema(handlerMetadata.schema); handlerMetadata.schema = tmp.name; } container.inject(handlerMetadata.serviceName || target.name, target, handlerMetadata.serviceLifeTime || annotations_1.LifeTime.Scoped); for (const action in actions) { let actionMetadata = actions[action]; actionMetadata = actionMetadata || {}; actionMetadata.action = actionMetadata.action || action; // Merge metadata let item = { kind: kind, methodName: action, metadata: Object.assign({}, handlerMetadata, actionMetadata), handler: target }; this.handlers.push(item); } } } ServiceDescriptors.nativeTypes = ["string", "String", "boolean", "Boolean", "number", "Number", "any", "Object"]; ServiceDescriptors = __decorate([ __param(0, annotations_1.Inject(annotations_1.DefaultServiceNames.Container)), __param(1, annotations_1.Inject(annotations_1.DefaultServiceNames.Domain)), __metadata('design:paramtypes', [Object, schema_1.Domain]) ], ServiceDescriptors); exports.ServiceDescriptors = ServiceDescriptors; //# sourceMappingURL=serviceDescriptions.js.map