vulcain-corejs
Version:
Vulcain micro-service framework
196 lines • 8.02 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const Path = require("path");
require("reflect-metadata");
const _1 = require(".");
const localAdapter_1 = require("./bus/localAdapter");
const dynamicConfiguration_1 = require("./configurations/dynamicConfiguration");
require("./defaults/dependencyExplorer"); // Don't remove (auto register)
require("./defaults/serviceExplorer"); // Don't remove (auto register)
const annotations_1 = require("./di/annotations");
const containers_1 = require("./di/containers");
const system_1 = require("./globals/system");
require("./graphql/graphQLHandler");
const graphQLHandler_1 = require("./graphql/graphQLHandler");
const annotations_2 = require("./pipeline/handlers/action/annotations");
const vulcainServer_1 = require("./pipeline/vulcainServer");
const preloader_1 = require("./preloader"); // always on first line
const domain_1 = require("./schemas/domain");
const conventions_1 = require("./utils/conventions");
const files_1 = require("./utils/files");
const hystrixSSEStream_1 = require("./commands/http/hystrixSSEStream");
const vulcainExecutablePath = __dirname;
const applicationPath = Path.dirname(module.parent.parent.filename);
/**
* Application base class
*
* @export
* @abstract
* @class Application
*/
class Application {
/**
* Create new application
* @param path Files base path for components discovery
* @param container Global component container
* @param app (optional)Server adapter
*/
constructor(domainName, _container) {
this.domainName = domainName;
this._container = _container;
this._initialized = false;
if (!this.domainName) {
throw new Error("Domain name is required.");
}
system_1.Service.setDomainName(this.domainName);
this._container = this._container || new containers_1.Container();
}
useMongoProvider(address) {
this.container.useMongoProvider(address);
return this;
}
useMemoryProvider(folder) {
this.container.useMemoryProvider(folder);
return this;
}
useRabbitmqBus(address) {
this.container.useRabbitBusAdapter(address);
return this;
}
useService(name, service, lifeTime) {
this.container.inject(name, service, lifeTime);
return this;
}
enableGraphQL(responseType = "graphql") {
annotations_2.ActionHandler({ async: false, scope: "?", description: "GraphQL action handler" }, { responseType, system: true })(graphQLHandler_1.GraphQLActionHandler);
preloader_1.Preloader.instance.registerHandler((container, domain) => {
let graphQLAdapter = container.get(annotations_1.DefaultServiceNames.GraphQLAdapter);
container.registerSSEEndpoint(conventions_1.Conventions.instance.defaultGraphQLSubscriptionPath, graphQLAdapter.getSubscriptionHandler());
});
return this;
}
/**
* Current component container
* @returns {Container}
*/
get container() { return this._container; }
/**
* Get the current domain model
* @returns {Domain}
*/
get domain() {
return this._domain;
}
/**
* Only use it for testing. Used start instead
*/
async init() {
if (this._initialized)
return;
this._initialized = true;
await dynamicConfiguration_1.DynamicConfiguration.init().startPolling();
system_1.Service.log.info(null, () => "Starting application");
this._container.injectInstance(this, annotations_1.DefaultServiceNames.Application);
this._domain = new domain_1.Domain(this.domainName, this._container);
this._container.injectInstance(this._domain, annotations_1.DefaultServiceNames.Domain);
this.container.registerHTTPEndpoint("GET", conventions_1.Conventions.instance.defaultHystrixPath, hystrixSSEStream_1.HystrixSSEStream.getHandler());
process.on('unhandledRejection', (reason, p) => {
system_1.Service.log.info(null, () => `Unhandled Rejection at ${p} reason ${reason}")`);
});
// Stop to receive inputs
process.once('SIGTERM', () => {
let eventBus = this.container.get(annotations_1.DefaultServiceNames.EventBusAdapter, true);
if (eventBus) {
eventBus.stopReception();
}
let commandBus = this.container.get(annotations_1.DefaultServiceNames.ActionBusAdapter, true);
if (commandBus) {
commandBus.stopReception();
}
this.container.dispose();
});
let local = new localAdapter_1.LocalAdapter();
let eventBus = this.container.get(annotations_1.DefaultServiceNames.EventBusAdapter, true);
if (!eventBus) {
this.container.injectInstance(local, annotations_1.DefaultServiceNames.EventBusAdapter);
eventBus = local;
}
let commandBus = this.container.get(annotations_1.DefaultServiceNames.ActionBusAdapter, true);
if (!commandBus) {
this.container.injectInstance(local, annotations_1.DefaultServiceNames.ActionBusAdapter);
commandBus = local;
}
this.registerComponents();
preloader_1.Preloader.instance.runPreloads(this.container, this._domain);
await eventBus.open();
await commandBus.open();
let scopes = this.container.get(annotations_1.DefaultServiceNames.ScopesDescriptor);
this.defineScopeDescriptions(scopes);
let descriptors = this.container.get(annotations_1.DefaultServiceNames.ServiceDescriptors);
descriptors.getDescriptions(); // ensures handlers table is created
this.container.injectSingleton(_1.HandlerProcessor, annotations_1.DefaultServiceNames.HandlerProcessor);
}
/**
* Define all scopes used in this service
*
* @protected
* @param {ScopesDescriptor} scopes Scope definitions manager - Use scopes.defineScope for each scope
*
* @memberOf Application
*/
defineScopeDescriptions(scopes) {
return this;
}
/**
* Initialize and start application
*
* @param {number} port
*/
async start(port) {
if (!port)
throw new Error("You must provide a port number");
try {
await this.init();
let server = new vulcainServer_1.VulcainServer(this.domain.name, this._container);
server.start(port);
}
catch (err) {
system_1.Service.log.error(null, err, () => "ERROR when starting application");
process.exit(2);
}
}
registerComponents() {
this.registerRecursive(Path.join(vulcainExecutablePath, "defaults"));
//let path = Conventions.instance.defaultApplicationFolder;
//this.registerRecursive(Path.join(applicationPath, path));
this.registerRecursive(applicationPath);
}
/**
* Discover models components
* @param path Where to find models component relative to base path (default=/api/models)
* @returns {Container}
*/
registerRecursive(path) {
if (!Path.isAbsolute(path)) {
path = Path.join(applicationPath, path);
}
files_1.Files.traverse(path);
return this._container;
}
/**
* Inject all components from a specific folder (relative to the current folder)
*
* @protected
* @param {string} path Folder path
* @returns The current application
*/
injectFrom(path) {
if (!Path.isAbsolute(path)) {
path = Path.join(applicationPath, path);
}
this._container.injectFrom(path);
return this;
}
}
exports.Application = Application;
//# sourceMappingURL=application.js.map