vulcain-corejs
Version:
Vulcain micro-service framework
264 lines (262 loc) • 10.5 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};
const apiKeyService_1 = require("./defaults/services/apiKeyService");
const preloader_1 = require("./preloader");
const hystrixSSEStream_1 = require("./commands/http/hystrixSSEStream");
const localAdapter_1 = require("./bus/localAdapter");
const Path = require("path");
const schema_1 = require("./schemas/schema");
const containers_1 = require("./di/containers");
const files_1 = require("./utils/files");
const expressAdapter_1 = require("./servers/express/expressAdapter");
require("reflect-metadata");
const annotations_1 = require("./di/annotations");
const conventions_1 = require("./utils/conventions");
const provider_1 = require("./providers/memory/provider");
const requestContext_1 = require("./servers/requestContext");
require("./defaults/serviceExplorer"); // Don't remove (auto register)
require("./defaults/dependencyExplorer"); // Don't remove (auto register)
require("./pipeline/scopeDescriptors"); // Don't remove (auto register)
const system_1 = require("./configurations/globals/system");
const expressAuthentication_1 = require("./servers/express/expressAuthentication");
/**
* 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) {
/**
* Ignore invalid bearer token
*
* @type {boolean}
* @memberOf Application
*/
this.ignoreInvalidBearerToken = false;
domainName = domainName;
if (!domainName) {
throw new Error("Domain name is required.");
}
system_1.System.defaultDomainName = domainName;
system_1.System.log.info(null, "Starting application");
this._executablePath = Path.dirname(module.filename);
this._basePath = this.findBasePath();
// Ensure initializing this first
const test = system_1.System.isDevelopment;
this._container = container || new containers_1.Container();
this._container.injectTransient(provider_1.MemoryProvider, annotations_1.DefaultServiceNames.Provider);
this._container.injectInstance(this, annotations_1.DefaultServiceNames.Application);
this._container.injectSingleton(expressAuthentication_1.ExpressAuthentication, annotations_1.DefaultServiceNames.Authentication);
this._domain = new schema_1.Domain(domainName, this._container);
this._container.injectInstance(this.domain, annotations_1.DefaultServiceNames.Domain);
}
/**
* Enable api key authentication
*
* @param {string} apiKeyServiceName Vulcain service name
* @param {string} [version="1.0"] Service version
*
* @memberOf Application
*/
enableApiKeyAuthentication(apiKeyServiceName, version = "1.0") {
this.container.injectScoped(apiKeyService_1.ApiKeyService, annotations_1.DefaultServiceNames.ApiKeyService, apiKeyServiceName, version);
}
/**
* Set the user to use in local development
*
* @param {UserContext} user
* @returns
*/
setTestUser(user) {
user = user || requestContext_1.RequestContext.TestUser;
if (!user.id || !user.name || !user.scopes) {
throw new Error("Invalid test user - Properties must be set.");
}
if (!system_1.System.isTestEnvironnment) {
system_1.System.log.info(null, "Warning : TestUser ignored");
return;
}
this._container.injectInstance(user, annotations_1.DefaultServiceNames.TestUser);
}
/**
* Called when the server adapter is started
*
* @param {*} server
* @param {*} adapter
*
* @memberOf Application
*/
onServerStarted(server, adapter) { }
/**
* Current component container
* @returns {Container}
*/
get container() { return this._container; }
/**
* Get the current domain model
* @returns {Domain}
*/
get domain() {
return this._domain;
}
findBasePath() {
let parent = module.parent;
while (parent.parent) {
parent = parent.parent;
}
return Path.dirname(parent.filename);
}
startHystrixStream() {
if (!this.enableHystrixStream) {
return;
}
this.adapter.useMiddleware("get", conventions_1.Conventions.instance.defaultHystrixPath, (request, response) => {
response.append('Content-Type', 'text/event-stream;charset=UTF-8');
response.append('Cache-Control', 'no-cache, no-store, max-age=0, must-revalidate');
response.append('Pragma', 'no-cache');
system_1.System.log.info(null, "get hystrix.stream");
let subscription = hystrixSSEStream_1.HystrixSSEStream.toObservable().subscribe(function onNext(sseData) {
response.write('data: ' + sseData + '\n\n');
}, function onError(error) {
system_1.System.log.info(null, "hystrixstream: error");
}, function onComplete() {
system_1.System.log.info(null, "end hystrix.stream");
return response.end();
});
request.on("close", () => {
system_1.System.log.info(null, "close hystrix.stream");
subscription.dispose();
});
return subscription;
});
}
/**
* Define all scopes used in this service
*
* @protected
* @param {ScopesDescriptor} scopes Scope definitions manager - Use scopes.defineScope for each scope
*
* @memberOf Application
*/
defineScopes(scopes) {
}
/**
* Override this method to initialize default containers
*
* @protected
* @param {IContainer} container
*/
initializeDefaultServices(container) {
}
/**
* Override this method to add your custom services
*
* @protected
* @param {IContainer} container
*/
initializeServices(container) {
}
/**
* Called before the server adapter is started
*
* @protected
* @param {AbstractAdapter} abstractAdapter
*/
initializeServerAdapter(abstractAdapter) {
}
/**
* Initialize and start application
*
* @param {number} port
*/
start(port) {
return __awaiter(this, void 0, void 0, function* () {
try {
this.initializeDefaultServices(this.container);
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;
}
yield eventBus.startAsync();
yield commandBus.startAsync();
this.registerComponents();
this.initializeServices(this.container);
preloader_1.Preloader.instance.runPreloads(this.container, this._domain);
let scopes = this.container.get(annotations_1.DefaultServiceNames.ScopesDescriptor);
this.defineScopes(scopes);
let descriptors = this.container.get(annotations_1.DefaultServiceNames.ServiceDescriptors);
descriptors.createHandlersTable();
this.adapter = this.container.get(annotations_1.DefaultServiceNames.ServerAdapter, true);
if (!this.adapter) {
this.adapter = new expressAdapter_1.ExpressAdapter(this.domain.name, this._container, this);
this.container.injectInstance(this.adapter, annotations_1.DefaultServiceNames.ServerAdapter);
this.initializeServerAdapter(this.adapter);
this.adapter.initialize();
}
this.startHystrixStream();
this.adapter.start(port);
}
catch (err) {
system_1.System.log.error(null, err, "ERROR when starting application");
process.exit(2);
}
});
}
registerComponents() {
this.registerRecursive(Path.join(this._executablePath, "defaults/models"));
this.registerRecursive(Path.join(this._executablePath, "defaults/handlers"));
this.registerRecursive(Path.join(this._executablePath, "defaults/services"));
let path = conventions_1.Conventions.instance.defaultApplicationFolder;
this.registerRecursive(Path.join(this._basePath, path));
}
/**
* 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(this._basePath, 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 container
*/
injectFrom(path) {
if (!Path.isAbsolute(path)) {
path = Path.join(this._basePath, path);
}
this._container.injectFrom(path);
return this._container;
}
}
exports.Application = Application;
//# sourceMappingURL=application.js.map