UNPKG

@neo-one/server

Version:

NEO•ONE Server that NEO•ONE CLI and other clients connect to.

172 lines (170 loc) 31.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const server_client_1 = require("@neo-one/server-client"); const server_plugin_1 = require("@neo-one/server-plugin"); const fs = tslib_1.__importStar(require("fs-extra")); const lodash_1 = tslib_1.__importDefault(require("lodash")); const path = tslib_1.__importStar(require("path")); const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const toposort_1 = tslib_1.__importDefault(require("toposort")); const errors_1 = require("./errors"); const plugins_1 = require("./plugins"); const Ready_1 = require("./Ready"); const ResourcesManager_1 = require("./ResourcesManager"); const MANAGER_PATH = 'manager'; const MASTER_PATH = 'master'; const PLUGINS_READY_PATH = 'ready'; class PluginManager { constructor({ monitor, binary, portAllocator, dataPath, httpServerPort, }) { this.monitor = monitor.at('plugin_manager'); this.binary = binary; this.portAllocator = portAllocator; this.dataPath = dataPath; this.httpServerPort = httpServerPort; this.mutableResourceManagers = {}; this.mutablePlugins = {}; this.plugins$ = new rxjs_1.ReplaySubject(); this.ready = new Ready_1.Ready({ dir: path.resolve(dataPath, PLUGINS_READY_PATH), }); this.update$ = new rxjs_1.Subject(); this.allResources$ = this.update$.pipe(operators_1.switchMap(() => rxjs_1.concat(rxjs_1.of([]), rxjs_1.combineLatest(Object.entries(this.mutableResourceManagers).reduce((acc, [pluginName, pluginResourcesManagers]) => acc.concat(Object.entries(pluginResourcesManagers).map(([resourceType, resourcesManager]) => resourcesManager.resources$.pipe(operators_1.map((resources) => [ server_plugin_1.pluginResourceTypeUtil.make({ plugin: pluginName, resourceType, }), resources, ])))), [])))), operators_1.map((result) => lodash_1.default.fromPairs(result)), operators_1.shareReplay(1)); this.allResources$.subscribe().unsubscribe(); } get plugins() { return Object.keys(this.mutablePlugins); } async init() { await fs.ensureDir(this.ready.dir); const pluginNames = await this.ready.getAll(); await this.registerPlugins([...new Set(pluginNames.concat(plugins_1.plugins.DEFAULT_PLUGINS))]); } async reset() { await Promise.all([ Promise.all(Object.values(this.mutablePlugins).map(async (plugin) => plugin.reset())), Promise.all(Object.values(this.mutableResourceManagers) .reduce((acc, managers) => acc.concat(Object.values(managers)), []) .map(async (manager) => { await manager.reset(); })), ]); } async registerPlugins(pluginNames) { const plugins = pluginNames.map((pluginName) => plugins_1.plugins.getPlugin({ monitor: this.monitor, pluginName, })); const graph = plugins.reduce((acc, plugin) => acc.concat(plugin.dependencies.map((dep) => [plugin.name, dep])), []); const sorted = lodash_1.default.reverse(toposort_1.default(graph)); const pluginNameToPlugin = plugins.reduce((acc, plugin) => (Object.assign({}, acc, { [plugin.name]: plugin })), {}); const noDepPlugins = plugins.filter((plugin) => plugin.dependencies.length === 0); await Promise.all(noDepPlugins.map(async (plugin) => this.registerPlugin(plugin))); for (const pluginName of sorted) { const plugin = pluginNameToPlugin[pluginName]; if (plugin !== undefined) { await this.registerPlugin(pluginNameToPlugin[pluginName]); } } } getPlugin({ plugin: pluginName }) { const plugin = this.mutablePlugins[pluginName]; if (plugin === undefined) { throw new server_client_1.PluginNotInstalledError(pluginName); } return plugin; } getResourcesManager({ plugin: pluginName, resourceType: resourceTypeName, }) { const plugin = this.getPlugin({ plugin: pluginName }); const resourceType = plugin.resourceTypeByName[resourceTypeName]; if (resourceType === undefined) { throw new server_client_1.UnknownPluginResourceType({ plugin: pluginName, resourceType: resourceTypeName, }); } return this.mutableResourceManagers[pluginName][resourceTypeName]; } getDebug() { return [ ['Binary', `${this.binary.cmd} ${this.binary.firstArgs.join(' ')}`], ['Port Allocator', { type: 'describe', table: this.portAllocator.getDebug() }], ['Resources Managers', { type: 'describe', table: this.getResourcesManagersDebug() }], ]; } async registerPlugin(plugin) { plugin.dependencies.forEach((dependency) => { if (this.mutablePlugins[dependency] === undefined) { throw new errors_1.PluginDependencyNotMetError({ plugin: plugin.name, dependency, }); } }); this.mutablePlugins[plugin.name] = plugin; this.mutableResourceManagers[plugin.name] = {}; const resourcesManagers = await Promise.all(plugin.resourceTypes.map(async (resourceType) => { const masterResourceAdapter = await resourceType.createMasterResourceAdapter({ pluginManager: this, dataPath: this.getMasterResourceAdapterDataPath({ plugin: plugin.name, resourceType: resourceType.name, }), binary: this.binary, portAllocator: this.portAllocator, }); const resourcesManager = new ResourcesManager_1.ResourcesManager({ monitor: this.monitor, dataPath: this.getResourcesManagerDataPath({ plugin: plugin.name, resourceType: resourceType.name, }), pluginManager: this, resourceType, masterResourceAdapter, portAllocator: this.portAllocator, }); await resourcesManager.init(); return { resourceType: resourceType.name, resourcesManager }; })); plugin.createHooks.forEach(({ plugin: pluginName, resourceType: resourceTypeName, hook }) => { this.getResourcesManager({ plugin: pluginName, resourceType: resourceTypeName, }).addCreateHook(hook); }); await this.ready.write(plugin.name); resourcesManagers.forEach(({ resourceType, resourcesManager }) => { this.mutableResourceManagers[plugin.name][resourceType] = resourcesManager; }); this.plugins$.next(plugin.name); this.update$.next(); } getResourcesManagerDataPath(options) { return path.resolve(this.getPluginPath(options), MANAGER_PATH); } getMasterResourceAdapterDataPath(options) { return path.resolve(this.getPluginPath(options), MASTER_PATH); } getPluginPath({ plugin, resourceType }) { return path.resolve(this.dataPath, plugins_1.plugins.cleanPluginName({ pluginName: plugin }), resourceType); } getResourcesManagersDebug() { return Object.entries(this.mutableResourceManagers).map(([pluginName, resourceTypeManagers]) => [ pluginName.slice('@neo-one/server-plugin-'.length), { type: 'describe', table: Object.entries(resourceTypeManagers).map(([resourceType, resourcesManager]) => [resourceType, { type: 'describe', table: resourcesManager.getDebug() }]), }, ]); } } exports.PluginManager = PluginManager; //# sourceMappingURL=data:application/json;charset=utf8;base64,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QU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ2pFLENBQUM7SUFFTyxnQ0FBZ0MsQ0FBQyxPQUd4QztRQUNDLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFTyxhQUFhLENBQUMsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUE4RDtRQUN4RyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxpQkFBVyxDQUFDLGVBQWUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ3hHLENBQUM7SUFFTyx5QkFBeUI7UUFDL0IsT0FBTyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLEdBQUcsQ0FDckQsQ0FBQyxDQUFDLFVBQVUsRUFBRSxvQkFBb0IsQ0FBQyxFQUFFLEVBQUUsQ0FDckM7WUFDRSxVQUFVLENBQUMsS0FBSyxDQUFDLHlCQUF5QixDQUFDLE1BQU0sQ0FBQztZQUNsRDtnQkFDRSxJQUFJLEVBQUUsVUFBVTtnQkFDaEIsS0FBSyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxHQUFHLENBQzdDLENBQUMsQ0FBQyxZQUFZLEVBQUUsZ0JBQWdCLENBQUMsRUFBRSxFQUFFLENBQ25DLENBQUMsWUFBWSxFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQW1CLEVBQUUsS0FBSyxFQUFFLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxFQUFFLENBQVUsQ0FDN0Y7YUFDRjtTQUNPLENBQ2IsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQWpRRCxzQ0FpUUMiLCJmaWxlIjoibmVvLW9uZS1zZXJ2ZXIvc3JjL1BsdWdpbk1hbmFnZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNb25pdG9yIH0gZnJvbSAnQG5lby1vbmUvbW9uaXRvcic7XG5pbXBvcnQgeyBQbHVnaW5Ob3RJbnN0YWxsZWRFcnJvciwgVW5rbm93blBsdWdpblJlc291cmNlVHlwZSB9IGZyb20gJ0BuZW8tb25lL3NlcnZlci1jbGllbnQnO1xuaW1wb3J0IHtcbiAgQWxsUmVzb3VyY2VzLFxuICBCYXNlUmVzb3VyY2UsXG4gIEJpbmFyeSxcbiAgRGVzY3JpYmVUYWJsZSxcbiAgUGx1Z2luLFxuICBwbHVnaW5SZXNvdXJjZVR5cGVVdGlsLFxuICBSZXNvdXJjZVR5cGUsXG4gIFN1YkRlc2NyaWJlVGFibGUsXG59IGZyb20gJ0BuZW8tb25lL3NlcnZlci1wbHVnaW4nO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBjb21iaW5lTGF0ZXN0LCBjb25jYXQsIE9ic2VydmFibGUsIG9mIGFzIF9vZiwgUmVwbGF5U3ViamVjdCwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCBzaGFyZVJlcGxheSwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHRvcG9zb3J0IGZyb20gJ3RvcG9zb3J0JztcbmltcG9ydCB7IFBsdWdpbkRlcGVuZGVuY3lOb3RNZXRFcnJvciB9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7IHBsdWdpbnMgYXMgcGx1Z2luc1V0aWwgfSBmcm9tICcuL3BsdWdpbnMnO1xuaW1wb3J0IHsgUG9ydEFsbG9jYXRvciB9IGZyb20gJy4vUG9ydEFsbG9jYXRvcic7XG5pbXBvcnQgeyBSZWFkeSB9IGZyb20gJy4vUmVhZHknO1xuaW1wb3J0IHsgUmVzb3VyY2VzTWFuYWdlciB9IGZyb20gJy4vUmVzb3VyY2VzTWFuYWdlcic7XG5cbmNvbnN0IE1BTkFHRVJfUEFUSCA9ICdtYW5hZ2VyJztcbmNvbnN0IE1BU1RFUl9QQVRIID0gJ21hc3Rlcic7XG5jb25zdCBQTFVHSU5TX1JFQURZX1BBVEggPSAncmVhZHknO1xuXG5pbnRlcmZhY2UgUmVzb3VyY2VzTWFuYWdlcnMge1xuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgcmVhZG9ubHkta2V5d29yZFxuICBbcGx1Z2luOiBzdHJpbmddOiB7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIHJlYWRvbmx5LWtleXdvcmRcbiAgICBbcmVzb3VyY2VUeXBlOiBzdHJpbmddOiBSZXNvdXJjZXNNYW5hZ2VyO1xuICB9O1xufVxuXG5pbnRlcmZhY2UgUGx1Z2lucyB7XG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZSByZWFkb25seS1rZXl3b3JkXG4gIFtwbHVnaW46IHN0cmluZ106IFBsdWdpbjtcbn1cblxuZXhwb3J0IGNsYXNzIFBsdWdpbk1hbmFnZXIge1xuICBwdWJsaWMgcmVhZG9ubHkgaHR0cFNlcnZlclBvcnQ6IG51bWJlcjtcbiAgcHVibGljIHJlYWRvbmx5IGFsbFJlc291cmNlcyQ6IE9ic2VydmFibGU8QWxsUmVzb3VyY2VzPjtcbiAgcHVibGljIG11dGFibGVQbHVnaW5zOiBQbHVnaW5zO1xuICBwdWJsaWMgcmVhZG9ubHkgcGx1Z2lucyQ6IFJlcGxheVN1YmplY3Q8c3RyaW5nPjtcbiAgcHJpdmF0ZSByZWFkb25seSBtb25pdG9yOiBNb25pdG9yO1xuICBwcml2YXRlIHJlYWRvbmx5IGJpbmFyeTogQmluYXJ5O1xuICBwcml2YXRlIHJlYWRvbmx5IHBvcnRBbGxvY2F0b3I6IFBvcnRBbGxvY2F0b3I7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGF0YVBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBtdXRhYmxlUmVzb3VyY2VNYW5hZ2VyczogUmVzb3VyY2VzTWFuYWdlcnM7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVhZHk6IFJlYWR5O1xuICBwcml2YXRlIHJlYWRvbmx5IHVwZGF0ZSQ6IFN1YmplY3Q8dm9pZD47XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHtcbiAgICBtb25pdG9yLFxuICAgIGJpbmFyeSxcbiAgICBwb3J0QWxsb2NhdG9yLFxuICAgIGRhdGFQYXRoLFxuICAgIGh0dHBTZXJ2ZXJQb3J0LFxuICB9OiB7XG4gICAgcmVhZG9ubHkgbW9uaXRvcjogTW9uaXRvcjtcbiAgICByZWFkb25seSBiaW5hcnk6IEJpbmFyeTtcbiAgICByZWFkb25seSBwb3J0QWxsb2NhdG9yOiBQb3J0QWxsb2NhdG9yO1xuICAgIHJlYWRvbmx5IGRhdGFQYXRoOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgaHR0cFNlcnZlclBvcnQ6IG51bWJlcjtcbiAgfSkge1xuICAgIHRoaXMubW9uaXRvciA9IG1vbml0b3IuYXQoJ3BsdWdpbl9tYW5hZ2VyJyk7XG4gICAgdGhpcy5iaW5hcnkgPSBiaW5hcnk7XG4gICAgdGhpcy5wb3J0QWxsb2NhdG9yID0gcG9ydEFsbG9jYXRvcjtcbiAgICB0aGlzLmRhdGFQYXRoID0gZGF0YVBhdGg7XG4gICAgdGhpcy5odHRwU2VydmVyUG9ydCA9IGh0dHBTZXJ2ZXJQb3J0O1xuXG4gICAgdGhpcy5tdXRhYmxlUmVzb3VyY2VNYW5hZ2VycyA9IHt9O1xuICAgIHRoaXMubXV0YWJsZVBsdWdpbnMgPSB7fTtcbiAgICB0aGlzLnBsdWdpbnMkID0gbmV3IFJlcGxheVN1YmplY3QoKTtcbiAgICB0aGlzLnJlYWR5ID0gbmV3IFJlYWR5KHtcbiAgICAgIGRpcjogcGF0aC5yZXNvbHZlKGRhdGFQYXRoLCBQTFVHSU5TX1JFQURZX1BBVEgpLFxuICAgIH0pO1xuXG4gICAgdGhpcy51cGRhdGUkID0gbmV3IFN1YmplY3QoKTtcbiAgICB0aGlzLmFsbFJlc291cmNlcyQgPSB0aGlzLnVwZGF0ZSQucGlwZShcbiAgICAgIHN3aXRjaE1hcCgoKSA9PlxuICAgICAgICBjb25jYXQoXG4gICAgICAgICAgX29mKFtdKSxcbiAgICAgICAgICBjb21iaW5lTGF0ZXN0KFxuICAgICAgICAgICAgT2JqZWN0LmVudHJpZXModGhpcy5tdXRhYmxlUmVzb3VyY2VNYW5hZ2VycykucmVkdWNlPEFycmF5PE9ic2VydmFibGU8W3N0cmluZywgcmVhZG9ubHkgQmFzZVJlc291cmNlW11dPj4+KFxuICAgICAgICAgICAgICAoYWNjLCBbcGx1Z2luTmFtZSwgcGx1Z2luUmVzb3VyY2VzTWFuYWdlcnNdKSA9PlxuICAgICAgICAgICAgICAgIGFjYy5jb25jYXQoXG4gICAgICAgICAgICAgICAgICBPYmplY3QuZW50cmllcyhwbHVnaW5SZXNvdXJjZXNNYW5hZ2VycykubWFwKChbcmVzb3VyY2VUeXBlLCByZXNvdXJjZXNNYW5hZ2VyXSkgPT5cbiAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2VzTWFuYWdlci5yZXNvdXJjZXMkLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgbWFwPHJlYWRvbmx5IEJhc2VSZXNvdXJjZVtdLCBbc3RyaW5nLCByZWFkb25seSBCYXNlUmVzb3VyY2VbXV0+KChyZXNvdXJjZXMpID0+IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBsdWdpblJlc291cmNlVHlwZVV0aWwubWFrZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHBsdWdpbjogcGx1Z2luTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2VUeXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSksXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc291cmNlcyxcbiAgICAgICAgICAgICAgICAgICAgICBdKSxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgKSxcblxuICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgICksXG4gICAgICAgICAgKSxcbiAgICAgICAgKSxcbiAgICAgICksXG4gICAgICBtYXAoKHJlc3VsdCkgPT4gXy5mcm9tUGFpcnMocmVzdWx0KSksXG4gICAgICBzaGFyZVJlcGxheSgxKSxcbiAgICApO1xuXG4gICAgdGhpcy5hbGxSZXNvdXJjZXMkLnN1YnNjcmliZSgpLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHBsdWdpbnMoKTogcmVhZG9ubHkgc3RyaW5nW10ge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLm11dGFibGVQbHVnaW5zKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBpbml0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IGZzLmVuc3VyZURpcih0aGlzLnJlYWR5LmRpcik7XG4gICAgY29uc3QgcGx1Z2luTmFtZXMgPSBhd2FpdCB0aGlzLnJlYWR5LmdldEFsbCgpO1xuICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJQbHVnaW5zKFsuLi5uZXcgU2V0KHBsdWdpbk5hbWVzLmNvbmNhdChwbHVnaW5zVXRpbC5ERUZBVUxUX1BMVUdJTlMpKV0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHJlc2V0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIFByb21pc2UuYWxsKE9iamVjdC52YWx1ZXModGhpcy5tdXRhYmxlUGx1Z2lucykubWFwKGFzeW5jIChwbHVnaW4pID0+IHBsdWdpbi5yZXNldCgpKSksXG4gICAgICBQcm9taXNlLmFsbChcbiAgICAgICAgT2JqZWN0LnZhbHVlcyh0aGlzLm11dGFibGVSZXNvdXJjZU1hbmFnZXJzKVxuICAgICAgICAgIC5yZWR1Y2UoKGFjYzogcmVhZG9ubHkgUmVzb3VyY2VzTWFuYWdlcltdLCBtYW5hZ2VycykgPT4gYWNjLmNvbmNhdChPYmplY3QudmFsdWVzKG1hbmFnZXJzKSksIFtdKVxuICAgICAgICAgIC5tYXAoYXN5bmMgKG1hbmFnZXI6IFJlc291cmNlc01hbmFnZXIpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IG1hbmFnZXIucmVzZXQoKTtcbiAgICAgICAgICB9KSxcbiAgICAgICksXG4gICAgXSk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgcmVnaXN0ZXJQbHVnaW5zKHBsdWdpbk5hbWVzOiByZWFkb25seSBzdHJpbmdbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHBsdWdpbnMgPSBwbHVnaW5OYW1lcy5tYXAoKHBsdWdpbk5hbWUpID0+XG4gICAgICBwbHVnaW5zVXRpbC5nZXRQbHVnaW4oe1xuICAgICAgICBtb25pdG9yOiB0aGlzLm1vbml0b3IsXG4gICAgICAgIHBsdWdpbk5hbWUsXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgY29uc3QgZ3JhcGggPSBwbHVnaW5zLnJlZHVjZTxSZWFkb25seUFycmF5PFtzdHJpbmcsIHN0cmluZ10+PihcbiAgICAgIChhY2MsIHBsdWdpbikgPT4gYWNjLmNvbmNhdChwbHVnaW4uZGVwZW5kZW5jaWVzLm1hcDxbc3RyaW5nLCBzdHJpbmddPigoZGVwKSA9PiBbcGx1Z2luLm5hbWUsIGRlcF0pKSxcbiAgICAgIFtdLFxuICAgICk7XG5cbiAgICBjb25zdCBzb3J0ZWQgPSBfLnJldmVyc2UodG9wb3NvcnQoZ3JhcGgpKTtcbiAgICBjb25zdCBwbHVnaW5OYW1lVG9QbHVnaW4gPSBwbHVnaW5zLnJlZHVjZTx7IFtwbHVnaW5OYW1lOiBzdHJpbmddOiBQbHVnaW4gfT4oXG4gICAgICAoYWNjLCBwbHVnaW4pID0+ICh7XG4gICAgICAgIC4uLmFjYyxcbiAgICAgICAgW3BsdWdpbi5uYW1lXTogcGx1Z2luLFxuICAgICAgfSksXG4gICAgICB7fSxcbiAgICApO1xuICAgIGNvbnN0IG5vRGVwUGx1Z2lucyA9IHBsdWdpbnMuZmlsdGVyKChwbHVnaW4pID0+IHBsdWdpbi5kZXBlbmRlbmNpZXMubGVuZ3RoID09PSAwKTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsKG5vRGVwUGx1Z2lucy5tYXAoYXN5bmMgKHBsdWdpbikgPT4gdGhpcy5yZWdpc3RlclBsdWdpbihwbHVnaW4pKSk7XG5cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tbG9vcC1zdGF0ZW1lbnRcbiAgICBmb3IgKGNvbnN0IHBsdWdpbk5hbWUgb2Ygc29ydGVkKSB7XG4gICAgICBjb25zdCBwbHVnaW4gPSBwbHVnaW5OYW1lVG9QbHVnaW5bcGx1Z2luTmFtZV0gYXMgUGx1Z2luIHwgdW5kZWZpbmVkO1xuICAgICAgLy8gVGhlIGxhdGVyIHBsdWdpbnMgd2lsbCBmYWlsIHdpdGggbWlzc2luZyBkZXBlbmRlbmN5XG4gICAgICBpZiAocGx1Z2luICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5yZWdpc3RlclBsdWdpbihwbHVnaW5OYW1lVG9QbHVnaW5bcGx1Z2luTmFtZV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRQbHVnaW4oeyBwbHVnaW46IHBsdWdpbk5hbWUgfTogeyByZWFkb25seSBwbHVnaW46IHN0cmluZyB9KTogUGx1Z2luIHtcbiAgICBjb25zdCBwbHVnaW4gPSB0aGlzLm11dGFibGVQbHVnaW5zW3BsdWdpbk5hbWVdIGFzIFBsdWdpbiB8IHVuZGVmaW5lZDtcbiAgICBpZiAocGx1Z2luID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBQbHVnaW5Ob3RJbnN0YWxsZWRFcnJvcihwbHVnaW5OYW1lKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGx1Z2luO1xuICB9XG5cbiAgcHVibGljIGdldFJlc291cmNlc01hbmFnZXIoe1xuICAgIHBsdWdpbjogcGx1Z2luTmFtZSxcbiAgICByZXNvdXJjZVR5cGU6IHJlc291cmNlVHlwZU5hbWUsXG4gIH06IHtcbiAgICByZWFkb25seSBwbHVnaW46IHN0cmluZztcbiAgICByZWFkb25seSByZXNvdXJjZVR5cGU6IHN0cmluZztcbiAgfSk6IFJlc291cmNlc01hbmFnZXIge1xuICAgIGNvbnN0IHBsdWdpbiA9IHRoaXMuZ2V0UGx1Z2luKHsgcGx1Z2luOiBwbHVnaW5OYW1lIH0pO1xuICAgIGNvbnN0IHJlc291cmNlVHlwZSA9IHBsdWdpbi5yZXNvdXJjZVR5cGVCeU5hbWVbcmVzb3VyY2VUeXBlTmFtZV0gYXMgUmVzb3VyY2VUeXBlIHwgdW5kZWZpbmVkO1xuICAgIGlmIChyZXNvdXJjZVR5cGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IFVua25vd25QbHVnaW5SZXNvdXJjZVR5cGUoe1xuICAgICAgICBwbHVnaW46IHBsdWdpbk5hbWUsXG4gICAgICAgIHJlc291cmNlVHlwZTogcmVzb3VyY2VUeXBlTmFtZSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm11dGFibGVSZXNvdXJjZU1hbmFnZXJzW3BsdWdpbk5hbWVdW3Jlc291cmNlVHlwZU5hbWVdO1xuICB9XG5cbiAgcHVibGljIGdldERlYnVnKCk6IERlc2NyaWJlVGFibGUge1xuICAgIHJldHVybiBbXG4gICAgICBbJ0JpbmFyeScsIGAke3RoaXMuYmluYXJ5LmNtZH0gJHt0aGlzLmJpbmFyeS5maXJzdEFyZ3Muam9pbignICcpfWBdIGFzIGNvbnN0LFxuICAgICAgWydQb3J0IEFsbG9jYXRvcicsIHsgdHlwZTogJ2Rlc2NyaWJlJywgdGFibGU6IHRoaXMucG9ydEFsbG9jYXRvci5nZXREZWJ1ZygpIH1dIGFzIGNvbnN0LFxuICAgICAgWydSZXNvdXJjZXMgTWFuYWdlcnMnLCB7IHR5cGU6ICdkZXNjcmliZScsIHRhYmxlOiB0aGlzLmdldFJlc291cmNlc01hbmFnZXJzRGVidWcoKSB9XSBhcyBjb25zdCxcbiAgICBdO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWdpc3RlclBsdWdpbihwbHVnaW46IFBsdWdpbik6IFByb21pc2U8dm9pZD4ge1xuICAgIHBsdWdpbi5kZXBlbmRlbmNpZXMuZm9yRWFjaCgoZGVwZW5kZW5jeSkgPT4ge1xuICAgICAgaWYgKCh0aGlzLm11dGFibGVQbHVnaW5zW2RlcGVuZGVuY3ldIGFzIFBsdWdpbiB8IHVuZGVmaW5lZCkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgUGx1Z2luRGVwZW5kZW5jeU5vdE1ldEVycm9yKHtcbiAgICAgICAgICBwbHVnaW46IHBsdWdpbi5uYW1lLFxuICAgICAgICAgIGRlcGVuZGVuY3ksXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5tdXRhYmxlUGx1Z2luc1twbHVnaW4ubmFtZV0gPSBwbHVnaW47XG4gICAgdGhpcy5tdXRhYmxlUmVzb3VyY2VNYW5hZ2Vyc1twbHVnaW4ubmFtZV0gPSB7fTtcbiAgICBjb25zdCByZXNvdXJjZXNNYW5hZ2VycyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgcGx1Z2luLnJlc291cmNlVHlwZXMubWFwKGFzeW5jIChyZXNvdXJjZVR5cGUpID0+IHtcbiAgICAgICAgY29uc3QgbWFzdGVyUmVzb3VyY2VBZGFwdGVyID0gYXdhaXQgcmVzb3VyY2VUeXBlLmNyZWF0ZU1hc3RlclJlc291cmNlQWRhcHRlcih7XG4gICAgICAgICAgcGx1Z2luTWFuYWdlcjogdGhpcyxcbiAgICAgICAgICBkYXRhUGF0aDogdGhpcy5nZXRNYXN0ZXJSZXNvdXJjZUFkYXB0ZXJEYXRhUGF0aCh7XG4gICAgICAgICAgICBwbHVnaW46IHBsdWdpbi5uYW1lLFxuICAgICAgICAgICAgcmVzb3VyY2VUeXBlOiByZXNvdXJjZVR5cGUubmFtZSxcbiAgICAgICAgICB9KSxcblxuICAgICAgICAgIGJpbmFyeTogdGhpcy5iaW5hcnksXG4gICAgICAgICAgcG9ydEFsbG9jYXRvcjogdGhpcy5wb3J0QWxsb2NhdG9yLFxuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCByZXNvdXJjZXNNYW5hZ2VyID0gbmV3IFJlc291cmNlc01hbmFnZXIoe1xuICAgICAgICAgIG1vbml0b3I6IHRoaXMubW9uaXRvcixcbiAgICAgICAgICBkYXRhUGF0aDogdGhpcy5nZXRSZXNvdXJjZXNNYW5hZ2VyRGF0YVBhdGgoe1xuICAgICAgICAgICAgcGx1Z2luOiBwbHVnaW4ubmFtZSxcbiAgICAgICAgICAgIHJlc291cmNlVHlwZTogcmVzb3VyY2VUeXBlLm5hbWUsXG4gICAgICAgICAgfSksXG5cbiAgICAgICAgICBwbHVnaW5NYW5hZ2VyOiB0aGlzLFxuICAgICAgICAgIHJlc291cmNlVHlwZSxcbiAgICAgICAgICBtYXN0ZXJSZXNvdXJjZUFkYXB0ZXIsXG4gICAgICAgICAgcG9ydEFsbG9jYXRvcjogdGhpcy5wb3J0QWxsb2NhdG9yLFxuICAgICAgICB9KTtcblxuICAgICAgICBhd2FpdCByZXNvdXJjZXNNYW5hZ2VyLmluaXQoKTtcblxuICAgICAgICByZXR1cm4geyByZXNvdXJjZVR5cGU6IHJlc291cmNlVHlwZS5uYW1lLCByZXNvdXJjZXNNYW5hZ2VyIH07XG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgcGx1Z2luLmNyZWF0ZUhvb2tzLmZvckVhY2goKHsgcGx1Z2luOiBwbHVnaW5OYW1lLCByZXNvdXJjZVR5cGU6IHJlc291cmNlVHlwZU5hbWUsIGhvb2sgfSkgPT4ge1xuICAgICAgdGhpcy5nZXRSZXNvdXJjZXNNYW5hZ2VyKHtcbiAgICAgICAgcGx1Z2luOiBwbHVnaW5OYW1lLFxuICAgICAgICByZXNvdXJjZVR5cGU6IHJlc291cmNlVHlwZU5hbWUsXG4gICAgICB9KS5hZGRDcmVhdGVIb29rKGhvb2spO1xuICAgIH0pO1xuXG4gICAgYXdhaXQgdGhpcy5yZWFkeS53cml0ZShwbHVnaW4ubmFtZSk7XG4gICAgcmVzb3VyY2VzTWFuYWdlcnMuZm9yRWFjaCgoeyByZXNvdXJjZVR5cGUsIHJlc291cmNlc01hbmFnZXIgfSkgPT4ge1xuICAgICAgdGhpcy5tdXRhYmxlUmVzb3VyY2VNYW5hZ2Vyc1twbHVnaW4ubmFtZV1bcmVzb3VyY2VUeXBlXSA9IHJlc291cmNlc01hbmFnZXI7XG4gICAgfSk7XG4gICAgdGhpcy5wbHVnaW5zJC5uZXh0KHBsdWdpbi5uYW1lKTtcbiAgICB0aGlzLnVwZGF0ZSQubmV4dCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRSZXNvdXJjZXNNYW5hZ2VyRGF0YVBhdGgob3B0aW9uczogeyByZWFkb25seSBwbHVnaW46IHN0cmluZzsgcmVhZG9ubHkgcmVzb3VyY2VUeXBlOiBzdHJpbmcgfSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHBhdGgucmVzb2x2ZSh0aGlzLmdldFBsdWdpblBhdGgob3B0aW9ucyksIE1BTkFHRVJfUEFUSCk7XG4gIH1cblxuICBwcml2YXRlIGdldE1hc3RlclJlc291cmNlQWRhcHRlckRhdGFQYXRoKG9wdGlvbnM6IHtcbiAgICByZWFkb25seSBwbHVnaW46IHN0cmluZztcbiAgICByZWFkb25seSByZXNvdXJjZVR5cGU6IHN0cmluZztcbiAgfSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHBhdGgucmVzb2x2ZSh0aGlzLmdldFBsdWdpblBhdGgob3B0aW9ucyksIE1BU1RFUl9QQVRIKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UGx1Z2luUGF0aCh7IHBsdWdpbiwgcmVzb3VyY2VUeXBlIH06IHsgcmVhZG9ubHkgcGx1Z2luOiBzdHJpbmc7IHJlYWRvbmx5IHJlc291cmNlVHlwZTogc3RyaW5nIH0pOiBzdHJpbmcge1xuICAgIHJldHVybiBwYXRoLnJlc29sdmUodGhpcy5kYXRhUGF0aCwgcGx1Z2luc1V0aWwuY2xlYW5QbHVnaW5OYW1lKHsgcGx1Z2luTmFtZTogcGx1Z2luIH0pLCByZXNvdXJjZVR5cGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRSZXNvdXJjZXNNYW5hZ2Vyc0RlYnVnKCk6IERlc2NyaWJlVGFibGUge1xuICAgIHJldHVybiBPYmplY3QuZW50cmllcyh0aGlzLm11dGFibGVSZXNvdXJjZU1hbmFnZXJzKS5tYXA8cmVhZG9ubHkgW3N0cmluZywgU3ViRGVzY3JpYmVUYWJsZV0+KFxuICAgICAgKFtwbHVnaW5OYW1lLCByZXNvdXJjZVR5cGVNYW5hZ2Vyc10pID0+XG4gICAgICAgIFtcbiAgICAgICAgICBwbHVnaW5OYW1lLnNsaWNlKCdAbmVvLW9uZS9zZXJ2ZXItcGx1Z2luLScubGVuZ3RoKSxcbiAgICAgICAgICB7XG4gICAgICAgICAgICB0eXBlOiAnZGVzY3JpYmUnLFxuICAgICAgICAgICAgdGFibGU6IE9iamVjdC5lbnRyaWVzKHJlc291cmNlVHlwZU1hbmFnZXJzKS5tYXA8cmVhZG9ubHkgW3N0cmluZywgU3ViRGVzY3JpYmVUYWJsZV0+KFxuICAgICAgICAgICAgICAoW3Jlc291cmNlVHlwZSwgcmVzb3VyY2VzTWFuYWdlcl0pID0+XG4gICAgICAgICAgICAgICAgW3Jlc291cmNlVHlwZSwgeyB0eXBlOiAnZGVzY3JpYmUnIGFzIGNvbnN0LCB0YWJsZTogcmVzb3VyY2VzTWFuYWdlci5nZXREZWJ1ZygpIH1dIGFzIGNvbnN0LFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICB9LFxuICAgICAgICBdIGFzIGNvbnN0LFxuICAgICk7XG4gIH1cbn1cbiJdfQ==