@tsclean/core
Version:
Plugin for API Rest Full development, based on Clean Architecture, IoC and Dependency Injection.
207 lines • 30.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Application = void 0;
const os_1 = require("os");
const core_1 = require("../core");
const constants_1 = require("./constants");
const middleware_1 = require("../middleware");
const application_context_1 = require("./application-context");
const utils_1 = require("../utils");
const services_1 = require("../services");
const routes_resolver_1 = require("../router/routes-resolver");
const helpers_1 = require("../helpers");
const { SocketModule } = (0, helpers_1.optionalRequire)('../websockets/socket-module', () => require('../websockets/socket-module'));
class Application extends application_context_1.ApplicationContext {
constructor(container, httpAdapter, config, graphInspector, appOptions = {}) {
super(container, appOptions);
this.httpAdapter = httpAdapter;
this.config = config;
this.graphInspector = graphInspector;
this.logger = new services_1.Logger(null, { timestamp: true });
this.middlewareModule = new middleware_1.MiddlewareModule();
this.middlewareContainer = new middleware_1.MiddlewareContainer(this.container);
this.socketModule = SocketModule && new SocketModule();
this.isListening = false;
this.selectContextModule();
this.registerHttpServer();
this.middlewareModule = new middleware_1.MiddlewareModule();
this.injector = new core_1.Injector({ preview: this.appOptions.preview });
this.routesResolver = new routes_resolver_1.RoutesResolver(this.container, this.config, this.injector, this.graphInspector);
}
async dispose() {
this.socketModule && (await this.socketModule.close());
this.httpAdapter && (await this.httpAdapter.close());
}
getHttpAdapter() {
return this.httpAdapter;
}
registerHttpServer() {
this.httpServer = this.createServer();
}
getUnderlyingHttpServer() {
return this.httpAdapter.getHttpServer();
}
applyOptions() {
if (!this.appOptions || !this.appOptions.cors)
return undefined;
const passCustomOptions = (0, utils_1.isObject)(this.appOptions.cors) ||
typeof this.appOptions.cors === 'function';
if (!passCustomOptions)
return this.enableCors();
return this.enableCors(this.appOptions.cors);
}
createServer() {
this.httpAdapter.initHttpServer(this.appOptions);
return this.httpAdapter.getHttpServer();
}
async registerModules() {
this.registerWsModule();
await this.middlewareModule.register(this.middlewareContainer, this.container, this.config, this.injector, this.httpAdapter, this.graphInspector, this.appOptions);
}
registerWsModule() {
if (!this.socketModule) {
return;
}
this.socketModule.register(this.container, this.config, this.graphInspector, this.appOptions, this.httpServer);
}
async init() {
var _a;
this.applyOptions();
await ((_a = this.httpAdapter) === null || _a === void 0 ? void 0 : _a.init());
const useBodyParser = this.appOptions && this.appOptions.bodyParser !== false;
useBodyParser && this.registerParserMiddleware();
await this.registerModules();
await this.registerRouter();
await this.registerRouterHooks();
this.isInitialized = true;
this.logger.log(constants_1.MESSAGES.APPLICATION_READY);
return this;
}
registerParserMiddleware() {
this.httpAdapter.registerParserMiddleware();
}
async registerRouter() {
await this.registerMiddleware(this.httpAdapter);
const prefix = this.config.getGlobalPrefix();
const basePath = (0, utils_1.addLeadingSlash)(prefix);
this.routesResolver.resolve(this.httpAdapter, basePath);
}
async registerRouterHooks() {
this.routesResolver.registerNotFoundHandler();
this.routesResolver.registerExceptionHandler();
}
getHttpServer() {
return this.httpServer;
}
use(...args) {
this.httpAdapter.use(...args);
return this;
}
enableCors(options) {
this.httpAdapter.enableCors(options);
}
async listen(port, ...args) {
!this.isInitialized && (await this.init());
return new Promise((resolve, reject) => {
const errorHandler = (e) => {
var _a;
this.logger.error((_a = e === null || e === void 0 ? void 0 : e.toString) === null || _a === void 0 ? void 0 : _a.call(e));
reject(e);
};
this.httpServer.once('error', errorHandler);
const isCallbackInOriginalArgs = (0, utils_1.isFunction)(args[args.length - 1]);
const listenFnArgs = isCallbackInOriginalArgs
? args.slice(0, args.length - 1)
: args;
this.httpAdapter.listen(port, ...listenFnArgs, (...originalCallbackArgs) => {
if (originalCallbackArgs[0] instanceof Error) {
return reject(originalCallbackArgs[0]);
}
const address = this.httpServer.address();
if (address) {
this.httpServer.removeListener('error', errorHandler);
this.isListening = true;
resolve(this.httpServer);
}
if (isCallbackInOriginalArgs) {
args[args.length - 1](...originalCallbackArgs);
}
});
});
}
async getUrl() {
return new Promise((resolve, reject) => {
if (!this.isListening) {
this.logger.error(constants_1.MESSAGES.CALL_LISTEN_FIRST);
reject(constants_1.MESSAGES.CALL_LISTEN_FIRST);
}
const address = this.httpServer.address();
resolve(this.formatAddress(address));
});
}
formatAddress(address) {
if (typeof address === 'string') {
if ((0, os_1.platform)() === 'win32')
return address;
const basePath = encodeURIComponent(address);
return `${this.getProtocol()}+unix://${basePath}`;
}
let host = this.host();
if (address && address.family === 'IPv6') {
if (host === '::') {
host = '[::1]';
}
else {
host = `[${host}]`;
}
}
else if (host === '0.0.0.0') {
host = '127.0.0.1';
}
return `${this.getProtocol()}://${host}:${address.port}`;
}
setGlobalPrefix(prefix, options) {
this.config.setGlobalPrefix(prefix);
if (options) {
const exclude = (options === null || options === void 0 ? void 0 : options.exclude)
? (0, middleware_1.mapToExcludeRoute)(options.exclude.filter((item) => typeof item !== 'string'))
: [];
this.config.setGlobalPrefixOptions(Object.assign(Object.assign({}, options), { exclude }));
}
return this;
}
useWebSocketAdapter(adapter) {
this.config.setIoAdapter(adapter);
return this;
}
useGlobalFilters(...filters) {
this.config.useGlobalFilters(...filters);
return this;
}
useGlobalHandler(...handlers) {
this.config.useGlobalHandlers(...handlers);
return this;
}
useGlobalInterceptors(...interceptors) {
this.config.useGlobalInterceptors(...interceptors);
return this;
}
useGlobalAccessResources(...guards) {
this.config.useGlobalAccessResource(...guards);
return this;
}
host() {
const address = this.httpServer.address();
if (typeof address === 'string')
return undefined;
return address && address.address;
}
getProtocol() {
return this.appOptions && this.appOptions.httpsOptions ? 'https' : 'http';
}
async registerMiddleware(instance) {
await this.middlewareModule.registerMiddleware(this.middlewareContainer, instance);
}
}
exports.Application = Application;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBwL2FwcGxpY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJCQUE2QjtBQUU3QixrQ0FBcUU7QUFFckUsMkNBQXNDO0FBQ3RDLDhDQUF3RjtBQUN4RiwrREFBMEQ7QUFpQjFELG9DQUEwRTtBQUMxRSwwQ0FBb0M7QUFFcEMsK0RBQTBEO0FBQzFELHdDQUE0QztBQUc1QyxNQUFNLEVBQUUsWUFBWSxFQUFFLEdBQUcsSUFBQSx5QkFBZSxFQUN0Qyw2QkFBNkIsRUFDN0IsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLDZCQUE2QixDQUFDLENBQzdDLENBQUM7QUFFRixNQUFhLFdBQ1gsU0FBUSx3Q0FBK0M7SUFXdkQsWUFDRSxTQUF1QixFQUNOLFdBQXVCLEVBQ3ZCLE1BQXlCLEVBQ3pCLGNBQThCLEVBQy9DLGFBQTBDLEVBQUU7UUFFNUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsQ0FBQTtRQUxYLGdCQUFXLEdBQVgsV0FBVyxDQUFZO1FBQ3ZCLFdBQU0sR0FBTixNQUFNLENBQW1CO1FBQ3pCLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQVo5QixXQUFNLEdBQUcsSUFBSSxpQkFBTSxDQUFDLElBQUksRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFBO1FBQ2hELHFCQUFnQixHQUFHLElBQUksNkJBQWdCLEVBQUUsQ0FBQTtRQUN6Qyx3QkFBbUIsR0FBRyxJQUFJLGdDQUFtQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQTtRQUM3RCxpQkFBWSxHQUFHLFlBQVksSUFBSSxJQUFJLFlBQVksRUFBRSxDQUFDO1FBRzNELGdCQUFXLEdBQUcsS0FBSyxDQUFBO1FBV3pCLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFBO1FBQzFCLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFBO1FBQ3pCLElBQUksQ0FBQyxn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Q0FBQyxDQUFDLENBQUMsTUFBTSxDQUFBO0lBQzNFLENBQUM7SUFFTyxLQUFLLENBQUMsa0JBQWtCLENBQUUsUUFBYTtRQUM3QyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsQ0FDNUMsSUFBSSxDQUFDLG1CQUFtQixFQUN4QixRQUFRLENBQ1QsQ0FBQTtJQUNILENBQUM7Q0FDRjtBQW5SRCxrQ0FtUkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBwbGF0Zm9ybSB9IGZyb20gJ29zJ1xuaW1wb3J0IHBhdGhUb1JlZ2V4cCBmcm9tICdwYXRoLXRvLXJlZ2V4cCdcbmltcG9ydCB7IEFic3RyYWN0SHR0cEFkYXB0ZXIsIENvbnRhaW5lcklvQywgSW5qZWN0b3IgfSBmcm9tICcuLi9jb3JlJ1xuaW1wb3J0IHsgQXBwbGljYXRpb25Db25maWcgfSBmcm9tICcuL2FwcGxpY2F0aW9uLWNvbmZpZydcbmltcG9ydCB7IE1FU1NBR0VTIH0gZnJvbSAnLi9jb25zdGFudHMnXG5pbXBvcnQgeyBtYXBUb0V4Y2x1ZGVSb3V0ZSwgTWlkZGxld2FyZUNvbnRhaW5lciwgTWlkZGxld2FyZU1vZHVsZSB9IGZyb20gJy4uL21pZGRsZXdhcmUnXG5pbXBvcnQgeyBBcHBsaWNhdGlvbkNvbnRleHQgfSBmcm9tICcuL2FwcGxpY2F0aW9uLWNvbnRleHQnXG5pbXBvcnQge1xuICBBY2Nlc3NSZXNvdXJjZUludGVyZmFjZSxcbiAgRXhjZXB0aW9uRmlsdGVySW50ZXJmYWNlLFxuICBIdHRwU2VydmVyLFxuICBBcHBsaWNhdGlvbkludGVyZmFjZSxcbiAgQXBwbGljYXRpb25PcHRpb25zSW50ZXJmYWNlLFxuICBJbnRlcmNlcHRvckludGVyZmFjZSxcbiAgR2xvYmFsUHJlZml4T3B0aW9uc0ludGVyZmFjZSxcbiAgUm91dGVJbmZvLFxuICBSZXNvbHZlckludGVyZmFjZSxcbiAgRXhjbHVkZVJvdXRlTWV0YWRhdGFJbnRlcmZhY2UsXG4gIENvcnNPcHRpb25zLFxuICBDb3JzT3B0aW9uc0RlbGVnYXRlLFxuICBIYW5kbGVyVHJhbnNmb3JtLFxuICBXZWJTb2NrZXRBZGFwdGVyXG59IGZyb20gJy4uL2NvbnRyYWN0cydcbmltcG9ydCB7IGFkZExlYWRpbmdTbGFzaCwgaXNGdW5jdGlvbiwgaXNPYmplY3QsIGlzU3RyaW5nIH0gZnJvbSAnLi4vdXRpbHMnXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9zZXJ2aWNlcydcbmltcG9ydCB7IFJlcXVlc3RNZXRob2QgfSBmcm9tICcuLi9lbnVtcydcbmltcG9ydCB7IFJvdXRlc1Jlc29sdmVyIH0gZnJvbSAnLi4vcm91dGVyL3JvdXRlcy1yZXNvbHZlcidcbmltcG9ydCB7IG9wdGlvbmFsUmVxdWlyZSB9IGZyb20gJy4uL2hlbHBlcnMnXG5pbXBvcnQgeyBHcmFwaEluc3BlY3RvciB9IGZyb20gJy4uL2luc3BlY3RvcidcblxuY29uc3QgeyBTb2NrZXRNb2R1bGUgfSA9IG9wdGlvbmFsUmVxdWlyZShcbiAgJy4uL3dlYnNvY2tldHMvc29ja2V0LW1vZHVsZScsXG4gICgpID0+IHJlcXVpcmUoJy4uL3dlYnNvY2tldHMvc29ja2V0LW1vZHVsZScpLFxuKTtcblxuZXhwb3J0IGNsYXNzIEFwcGxpY2F0aW9uXG4gIGV4dGVuZHMgQXBwbGljYXRpb25Db250ZXh0PEFwcGxpY2F0aW9uT3B0aW9uc0ludGVyZmFjZT5cbiAgaW1wbGVtZW50cyBBcHBsaWNhdGlvbkludGVyZmFjZVxue1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgbG9nZ2VyID0gbmV3IExvZ2dlcihudWxsLCB7IHRpbWVzdGFtcDogdHJ1ZSB9KVxuICBwcml2YXRlIHJlYWRvbmx5IG1pZGRsZXdhcmVNb2R1bGUgPSBuZXcgTWlkZGxld2FyZU1vZHVsZSgpXG4gIHByaXZhdGUgcmVhZG9ubHkgbWlkZGxld2FyZUNvbnRhaW5lciA9IG5ldyBNaWRkbGV3YXJlQ29udGFpbmVyKHRoaXMuY29udGFpbmVyKVxuICBwcml2YXRlIHJlYWRvbmx5IHNvY2tldE1vZHVsZSA9IFNvY2tldE1vZHVsZSAmJiBuZXcgU29ja2V0TW9kdWxlKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcm91dGVzUmVzb2x2ZXI6IFJlc29sdmVySW50ZXJmYWNlXG4gIHByaXZhdGUgaHR0cFNlcnZlcjogYW55XG4gIHByaXZhdGUgaXNMaXN0ZW5pbmcgPSBmYWxzZVxuXG4gIGNvbnN0cnVjdG9yIChcbiAgICBjb250YWluZXI6IENvbnRhaW5lcklvQyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGh0dHBBZGFwdGVyOiBIdHRwU2VydmVyLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBBcHBsaWNhdGlvbkNvbmZpZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGdyYXBoSW5zcGVjdG9yOiBHcmFwaEluc3BlY3RvcixcbiAgICBhcHBPcHRpb25zOiBBcHBsaWNhdGlvbk9wdGlvbnNJbnRlcmZhY2UgPSB7fVxuICApIHtcbiAgICBzdXBlcihjb250YWluZXIsIGFwcE9wdGlvbnMpXG5cbiAgICB0aGlzLnNlbGVjdENvbnRleHRNb2R1bGUoKVxuICAgIHRoaXMucmVnaXN0ZXJIdHRwU2VydmVyKClcbiAgICB0aGlzLm1pZGRsZXdhcmVNb2R1bGUgPSBuZXcgTWlkZGxld2FyZU1vZHVsZSgpO1xuICAgIHRoaXMuaW5qZWN0b3IgPSBuZXcgSW5qZWN0b3IoeyBwcmV2aWV3OiB0aGlzLmFwcE9wdGlvbnMucHJldmlldyB9KTtcbiAgICBcbiAgICB0aGlzLnJvdXRlc1Jlc29sdmVyID0gbmV3IFJvdXRlc1Jlc29sdmVyKFxuICAgICAgdGhpcy5jb250YWluZXIsXG4gICAgICB0aGlzLmNvbmZpZyxcbiAgICAgIHRoaXMuaW5qZWN0b3IsXG4gICAgICB0aGlzLmdyYXBoSW5zcGVjdG9yLFxuICAgIClcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBkaXNwb3NlICgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLnNvY2tldE1vZHVsZSAmJiAoYXdhaXQgdGhpcy5zb2NrZXRNb2R1bGUuY2xvc2UoKSk7XG4gICAgdGhpcy5odHRwQWRhcHRlciAmJiAoYXdhaXQgdGhpcy5odHRwQWRhcHRlci5jbG9zZSgpKVxuICB9XG5cbiAgcHVibGljIGdldEh0dHBBZGFwdGVyICgpOiBBYnN0cmFjdEh0dHBBZGFwdGVyIHtcbiAgICByZXR1cm4gdGhpcy5odHRwQWRhcHRlciBhcyBBYnN0cmFjdEh0dHBBZGFwdGVyXG4gIH1cblxuICBwdWJsaWMgcmVnaXN0ZXJIdHRwU2VydmVyICgpIHtcbiAgICB0aGlzLmh0dHBTZXJ2ZXIgPSB0aGlzLmNyZWF0ZVNlcnZlcigpXG4gIH1cblxuICBwdWJsaWMgZ2V0VW5kZXJseWluZ0h0dHBTZXJ2ZXI8VD4gKCk6IFQge1xuICAgIHJldHVybiB0aGlzLmh0dHBBZGFwdGVyLmdldEh0dHBTZXJ2ZXIoKVxuICB9XG5cbiAgcHVibGljIGFwcGx5T3B0aW9ucyAoKSB7XG4gICAgaWYgKCF0aGlzLmFwcE9wdGlvbnMgfHwgIXRoaXMuYXBwT3B0aW9ucy5jb3JzKSByZXR1cm4gdW5kZWZpbmVkXG5cbiAgICBjb25zdCBwYXNzQ3VzdG9tT3B0aW9ucyA9XG4gICAgICBpc09iamVjdCh0aGlzLmFwcE9wdGlvbnMuY29ycykgfHxcbiAgICAgIHR5cGVvZiB0aGlzLmFwcE9wdGlvbnMuY29ycyA9PT0gJ2Z1bmN0aW9uJ1xuICAgIGlmICghcGFzc0N1c3RvbU9wdGlvbnMpIHJldHVybiB0aGlzLmVuYWJsZUNvcnMoKVxuXG4gICAgcmV0dXJuIHRoaXMuZW5hYmxlQ29ycyhcbiAgICAgIHRoaXMuYXBwT3B0aW9ucy5jb3JzIGFzIENvcnNPcHRpb25zIHwgQ29yc09wdGlvbnNEZWxlZ2F0ZTxhbnk+XG4gICAgKVxuICB9XG5cbiAgcHVibGljIGNyZWF0ZVNlcnZlcjxUID0gYW55PiAoKTogVCB7XG4gICAgdGhpcy5odHRwQWRhcHRlci5pbml0SHR0cFNlcnZlcih0aGlzLmFwcE9wdGlvbnMpXG4gICAgcmV0dXJuIHRoaXMuaHR0cEFkYXB0ZXIuZ2V0SHR0cFNlcnZlcigpIGFzIFRcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyByZWdpc3Rlck1vZHVsZXMgKCkge1xuICAgIHRoaXMucmVnaXN0ZXJXc01vZHVsZSgpO1xuXG4gICAgYXdhaXQgdGhpcy5taWRkbGV3YXJlTW9kdWxlLnJlZ2lzdGVyKFxuICAgICAgdGhpcy5taWRkbGV3YXJlQ29udGFpbmVyLFxuICAgICAgdGhpcy5jb250YWluZXIsXG4gICAgICB0aGlzLmNvbmZpZyxcbiAgICAgIHRoaXMuaW5qZWN0b3IsXG4gICAgICB0aGlzLmh0dHBBZGFwdGVyLFxuICAgICAgdGhpcy5ncmFwaEluc3BlY3RvcixcbiAgICAgIHRoaXMuYXBwT3B0aW9ucyxcbiAgICApXG4gIH1cblxuICBwdWJsaWMgcmVnaXN0ZXJXc01vZHVsZSgpIHtcbiAgICBpZiAoIXRoaXMuc29ja2V0TW9kdWxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuc29ja2V0TW9kdWxlLnJlZ2lzdGVyKFxuICAgICAgdGhpcy5jb250YWluZXIsXG4gICAgICB0aGlzLmNvbmZpZyxcbiAgICAgIHRoaXMuZ3JhcGhJbnNwZWN0b3IsXG4gICAgICB0aGlzLmFwcE9wdGlvbnMsXG4gICAgICB0aGlzLmh0dHBTZXJ2ZXIsXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBpbml0ICgpOiBQcm9taXNlPHRoaXM+IHtcbiAgICB0aGlzLmFwcGx5T3B0aW9ucygpXG4gICAgYXdhaXQgdGhpcy5odHRwQWRhcHRlcj8uaW5pdCgpXG5cbiAgICBjb25zdCB1c2VCb2R5UGFyc2VyID1cbiAgICAgIHRoaXMuYXBwT3B0aW9ucyAmJiB0aGlzLmFwcE9wdGlvbnMuYm9keVBhcnNlciAhPT0gZmFsc2VcbiAgICB1c2VCb2R5UGFyc2VyICYmIHRoaXMucmVnaXN0ZXJQYXJzZXJNaWRkbGV3YXJlKClcblxuICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJNb2R1bGVzKClcbiAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyUm91dGVyKClcbiAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyUm91dGVySG9va3MoKVxuXG4gICAgdGhpcy5pc0luaXRpYWxpemVkID0gdHJ1ZVxuICAgIHRoaXMubG9nZ2VyLmxvZyhNRVNTQUdFUy5BUFBMSUNBVElPTl9SRUFEWSlcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgcHVibGljIHJlZ2lzdGVyUGFyc2VyTWlkZGxld2FyZSAoKSB7XG4gICAgdGhpcy5odHRwQWRhcHRlci5yZWdpc3RlclBhcnNlck1pZGRsZXdhcmUoKVxuICB9XG5cbiAgcHVibGljIGFzeW5jIHJlZ2lzdGVyUm91dGVyICgpIHtcbiAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyTWlkZGxld2FyZSh0aGlzLmh0dHBBZGFwdGVyKVxuXG4gICAgY29uc3QgcHJlZml4ID0gdGhpcy5jb25maWcuZ2V0R2xvYmFsUHJlZml4KClcbiAgICBjb25zdCBiYXNlUGF0aCA9IGFkZExlYWRpbmdTbGFzaChwcmVmaXgpXG4gICAgdGhpcy5yb3V0ZXNSZXNvbHZlci5yZXNvbHZlKHRoaXMuaHR0cEFkYXB0ZXIsIGJhc2VQYXRoKVxuICB9XG5cbiAgcHVibGljIGFzeW5jIHJlZ2lzdGVyUm91dGVySG9va3MgKCkge1xuICAgIHRoaXMucm91dGVzUmVzb2x2ZXIucmVnaXN0ZXJOb3RGb3VuZEhhbmRsZXIoKVxuICAgIHRoaXMucm91dGVzUmVzb2x2ZXIucmVnaXN0ZXJFeGNlcHRpb25IYW5kbGVyKClcbiAgfVxuXG4gIHB1YmxpYyBnZXRIdHRwU2VydmVyICgpIHtcbiAgICByZXR1cm4gdGhpcy5odHRwU2VydmVyXG4gIH1cblxuICBwdWJsaWMgdXNlICguLi5hcmdzOiBbYW55LCBhbnk/XSk6IHRoaXMge1xuICAgIHRoaXMuaHR0cEFkYXB0ZXIudXNlKC4uLmFyZ3MpXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHB1YmxpYyBlbmFibGVDb3JzIChvcHRpb25zPzogQ29yc09wdGlvbnMgfCBDb3JzT3B0aW9uc0RlbGVnYXRlPGFueT4pOiB2b2lkIHtcbiAgICB0aGlzLmh0dHBBZGFwdGVyLmVuYWJsZUNvcnMob3B0aW9ucylcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBsaXN0ZW4ocG9ydDogbnVtYmVyIHwgc3RyaW5nKTogUHJvbWlzZTxhbnk+XG5cbiAgcHVibGljIGFzeW5jIGxpc3Rlbihwb3J0OiBudW1iZXIgfCBzdHJpbmcsIGhvc3RuYW1lOiBzdHJpbmcpOiBQcm9taXNlPGFueT5cblxuICBwdWJsaWMgYXN5bmMgbGlzdGVuIChwb3J0OiBudW1iZXIgfCBzdHJpbmcsIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxhbnk+IHtcbiAgICAhdGhpcy5pc0luaXRpYWxpemVkICYmIChhd2FpdCB0aGlzLmluaXQoKSlcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb25zdCBlcnJvckhhbmRsZXIgPSAoZTogYW55KSA9PiB7XG4gICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKGU/LnRvU3RyaW5nPy4oKSlcbiAgICAgICAgcmVqZWN0KGUpXG4gICAgICB9XG4gICAgICB0aGlzLmh0dHBTZXJ2ZXIub25jZSgnZXJyb3InLCBlcnJvckhhbmRsZXIpXG5cbiAgICAgIGNvbnN0IGlzQ2FsbGJhY2tJbk9yaWdpbmFsQXJncyA9IGlzRnVuY3Rpb24oYXJnc1thcmdzLmxlbmd0aCAtIDFdKVxuICAgICAgY29uc3QgbGlzdGVuRm5BcmdzID0gaXNDYWxsYmFja0luT3JpZ2luYWxBcmdzXG4gICAgICAgID8gYXJncy5zbGljZSgwLCBhcmdzLmxlbmd0aCAtIDEpXG4gICAgICAgIDogYXJnc1xuXG4gICAgICB0aGlzLmh0dHBBZGFwdGVyLmxpc3RlbihcbiAgICAgICAgcG9ydCxcbiAgICAgICAgLi4ubGlzdGVuRm5BcmdzLFxuICAgICAgICAoLi4ub3JpZ2luYWxDYWxsYmFja0FyZ3M6IHVua25vd25bXSkgPT4ge1xuICAgICAgICAgIGlmIChvcmlnaW5hbENhbGxiYWNrQXJnc1swXSBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KG9yaWdpbmFsQ2FsbGJhY2tBcmdzWzBdKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGFkZHJlc3MgPSB0aGlzLmh0dHBTZXJ2ZXIuYWRkcmVzcygpXG4gICAgICAgICAgaWYgKGFkZHJlc3MpIHtcbiAgICAgICAgICAgIHRoaXMuaHR0cFNlcnZlci5yZW1vdmVMaXN0ZW5lcignZXJyb3InLCBlcnJvckhhbmRsZXIpXG4gICAgICAgICAgICB0aGlzLmlzTGlzdGVuaW5nID0gdHJ1ZVxuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmh0dHBTZXJ2ZXIpXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChpc0NhbGxiYWNrSW5PcmlnaW5hbEFyZ3MpIHtcbiAgICAgICAgICAgIGFyZ3NbYXJncy5sZW5ndGggLSAxXSguLi5vcmlnaW5hbENhbGxiYWNrQXJncylcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIClcbiAgICB9KVxuICB9XG5cbiAgcHVibGljIGFzeW5jIGdldFVybCAoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLmlzTGlzdGVuaW5nKSB7XG4gICAgICAgIHRoaXMubG9nZ2VyLmVycm9yKE1FU1NBR0VTLkNBTExfTElTVEVOX0ZJUlNUKVxuICAgICAgICByZWplY3QoTUVTU0FHRVMuQ0FMTF9MSVNURU5fRklSU1QpXG4gICAgICB9XG4gICAgICBjb25zdCBhZGRyZXNzID0gdGhpcy5odHRwU2VydmVyLmFkZHJlc3MoKVxuICAgICAgcmVzb2x2ZSh0aGlzLmZvcm1hdEFkZHJlc3MoYWRkcmVzcykpXG4gICAgfSlcbiAgfVxuXG4gIHByaXZhdGUgZm9ybWF0QWRkcmVzcyAoYWRkcmVzczogYW55KTogc3RyaW5nIHtcbiAgICBpZiAodHlwZW9mIGFkZHJlc3MgPT09ICdzdHJpbmcnKSB7XG4gICAgICBpZiAocGxhdGZvcm0oKSA9PT0gJ3dpbjMyJykgcmV0dXJuIGFkZHJlc3NcblxuICAgICAgY29uc3QgYmFzZVBhdGggPSBlbmNvZGVVUklDb21wb25lbnQoYWRkcmVzcylcbiAgICAgIHJldHVybiBgJHt0aGlzLmdldFByb3RvY29sKCl9K3VuaXg6Ly8ke2Jhc2VQYXRofWBcbiAgICB9XG4gICAgbGV0IGhvc3QgPSB0aGlzLmhvc3QoKVxuICAgIGlmIChhZGRyZXNzICYmIGFkZHJlc3MuZmFtaWx5ID09PSAnSVB2NicpIHtcbiAgICAgIGlmIChob3N0ID09PSAnOjonKSB7XG4gICAgICAgIGhvc3QgPSAnWzo6MV0nXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBob3N0ID0gYFske2hvc3R9XWBcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGhvc3QgPT09ICcwLjAuMC4wJykge1xuICAgICAgaG9zdCA9ICcxMjcuMC4wLjEnXG4gICAgfVxuXG4gICAgcmV0dXJuIGAke3RoaXMuZ2V0UHJvdG9jb2woKX06Ly8ke2hvc3R9OiR7YWRkcmVzcy5wb3J0fWBcbiAgfVxuXG4gIHB1YmxpYyBzZXRHbG9iYWxQcmVmaXggKFxuICAgIHByZWZpeDogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBHbG9iYWxQcmVmaXhPcHRpb25zSW50ZXJmYWNlXG4gICk6IHRoaXMge1xuICAgIHRoaXMuY29uZmlnLnNldEdsb2JhbFByZWZpeChwcmVmaXgpO1xuICAgIGlmIChvcHRpb25zKSB7XG4gICAgICBjb25zdCBleGNsdWRlID0gb3B0aW9ucz8uZXhjbHVkZVxuICAgICAgICA/IG1hcFRvRXhjbHVkZVJvdXRlKG9wdGlvbnMuZXhjbHVkZS5maWx0ZXIoKGl0ZW0pOiBpdGVtIGlzIFJvdXRlSW5mbyA9PiB0eXBlb2YgaXRlbSAhPT0gJ3N0cmluZycpKVxuICAgICAgICA6IFtdO1xuICAgICAgdGhpcy5jb25maWcuc2V0R2xvYmFsUHJlZml4T3B0aW9ucyh7XG4gICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgIGV4Y2x1ZGUsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBwdWJsaWMgdXNlV2ViU29ja2V0QWRhcHRlcihhZGFwdGVyOiBXZWJTb2NrZXRBZGFwdGVyKTogdGhpcyB7XG4gICAgdGhpcy5jb25maWcuc2V0SW9BZGFwdGVyKGFkYXB0ZXIpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgcHVibGljIHVzZUdsb2JhbEZpbHRlcnMgKC4uLmZpbHRlcnM6IEV4Y2VwdGlvbkZpbHRlckludGVyZmFjZVtdKTogdGhpcyB7XG4gICAgdGhpcy5jb25maWcudXNlR2xvYmFsRmlsdGVycyguLi5maWx0ZXJzKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBwdWJsaWMgdXNlR2xvYmFsSGFuZGxlciAoLi4uaGFuZGxlcnM6IEhhbmRsZXJUcmFuc2Zvcm08YW55PltdKTogdGhpcyB7XG4gICAgdGhpcy5jb25maWcudXNlR2xvYmFsSGFuZGxlcnMoLi4uaGFuZGxlcnMpXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHB1YmxpYyB1c2VHbG9iYWxJbnRlcmNlcHRvcnMgKC4uLmludGVyY2VwdG9yczogSW50ZXJjZXB0b3JJbnRlcmZhY2VbXSk6IHRoaXMge1xuICAgIHRoaXMuY29uZmlnLnVzZUdsb2JhbEludGVyY2VwdG9ycyguLi5pbnRlcmNlcHRvcnMpXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHB1YmxpYyB1c2VHbG9iYWxBY2Nlc3NSZXNvdXJjZXMgKC4uLmd1YXJkczogQWNjZXNzUmVzb3VyY2VJbnRlcmZhY2VbXSk6IHRoaXMge1xuICAgIHRoaXMuY29uZmlnLnVzZUdsb2JhbEFjY2Vzc1Jlc291cmNlKC4uLmd1YXJkcylcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgcHJpdmF0ZSBob3N0ICgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGFkZHJlc3MgPSB0aGlzLmh0dHBTZXJ2ZXIuYWRkcmVzcygpXG4gICAgaWYgKHR5cGVvZiBhZGRyZXNzID09PSAnc3RyaW5nJykgcmV0dXJuIHVuZGVmaW5lZFxuXG4gICAgcmV0dXJuIGFkZHJlc3MgJiYgYWRkcmVzcy5hZGRyZXNzXG4gIH1cblxuICBwcml2YXRlIGdldFByb3RvY29sICgpOiAnaHR0cCcgfCAnaHR0cHMnIHtcbiAgICByZXR1cm4gdGhpcy5hcHBPcHRpb25zICYmIHRoaXMuYXBwT3B0aW9ucy5odHRwc09wdGlvbnMgPyAnaHR0cHMnIDogJ2h0dHAnXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZ2lzdGVyTWlkZGxld2FyZSAoaW5zdGFuY2U6IGFueSkge1xuICAgIGF3YWl0IHRoaXMubWlkZGxld2FyZU1vZHVsZS5yZWdpc3Rlck1pZGRsZXdhcmUoXG4gICAgICB0aGlzLm1pZGRsZXdhcmVDb250YWluZXIsXG4gICAgICBpbnN0YW5jZVxuICAgIClcbiAgfVxufVxuIl19