@neo-one/server
Version:
NEO•ONE Server that NEO•ONE CLI and other clients connect to.
183 lines (181 loc) • 30 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const server_plugin_1 = require("@neo-one/server-plugin");
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const operators_1 = require("rxjs/operators");
const createPortAllocatorConfig = ({ dataPath }) => new server_plugin_1.Config({
name: 'port_allocator',
defaultConfig: { ports: {} },
schema: {
type: 'object',
required: ['ports'],
properties: {
ports: {
type: 'object',
patternProperties: {
'^.*$': {
type: 'object',
patternProperties: {
'^.*$': {
type: 'object',
patternProperties: {
'^.*$': {
type: 'object',
patternProperties: {
'^.*$': { type: 'number' },
},
},
},
},
},
},
},
},
},
},
configPath: dataPath,
});
class PortAllocator {
static async create({ monitor, dataPath, portMin, portMax, }) {
const config = createPortAllocatorConfig({ dataPath });
const { ports } = await config.config$.pipe(operators_1.take(1)).toPromise();
return new PortAllocator({
monitor,
config,
ports,
portMin,
portMax,
});
}
constructor({ monitor, ports, portMin, portMax, config, }) {
this.monitor = monitor.at('port_allocator');
let maxPort = -1;
const filteredPorts = {};
const allPorts = new Set();
for (const [plugin, pluginPorts] of Object.entries(ports)) {
const filteredResourceTypePorts = {};
for (const pluginValue of Object.entries(pluginPorts)) {
const [resourceType, resourceTypePorts] = pluginValue;
const filteredResourcePorts = {};
for (const resourceTypeValue of Object.entries(resourceTypePorts)) {
const [resource, resourcePorts] = resourceTypeValue;
const filteredNamePorts = {};
for (const [name, port] of Object.entries(resourcePorts)) {
if (portMin <= port && port <= portMax) {
maxPort = Math.max(maxPort, port);
filteredNamePorts[name] = port;
allPorts.add(port);
}
}
if (!lodash_1.default.isEmpty(filteredNamePorts)) {
filteredResourcePorts[resource] = filteredNamePorts;
}
}
if (!lodash_1.default.isEmpty(filteredResourcePorts)) {
filteredResourceTypePorts[resourceType] = filteredResourcePorts;
}
}
if (!lodash_1.default.isEmpty(filteredResourceTypePorts)) {
filteredPorts[plugin] = filteredResourceTypePorts;
}
}
this.mutablePorts = filteredPorts;
this.mutableCurrentPort = maxPort === -1 ? portMin : maxPort + 1;
this.mutableAvailablePorts = lodash_1.default.range(portMin, this.mutableCurrentPort).filter((port) => !allPorts.has(port));
this.config = config;
this.mutablePersisting = false;
this.mutableShouldPersist = false;
this.persist();
}
releasePort({ plugin, resourceType, resource, name, }) {
if (this.mutablePorts[plugin] !== undefined &&
this.mutablePorts[plugin][resourceType] !== undefined &&
this.mutablePorts[plugin][resourceType][resource] !== undefined &&
(name === undefined ||
this.mutablePorts[plugin][resourceType][resource][name] !== undefined)) {
if (name === undefined) {
const ports = Object.values(this.mutablePorts[plugin][resourceType][resource]);
this.mutableAvailablePorts.push(...ports);
delete this.mutablePorts[plugin][resourceType][resource];
}
else {
const port = this.mutablePorts[plugin][resourceType][resource][name];
this.mutableAvailablePorts.push(port);
delete this.mutablePorts[plugin][resourceType][resource][name];
}
if (lodash_1.default.isEmpty(this.mutablePorts[plugin][resourceType][resource])) {
delete this.mutablePorts[plugin][resourceType][resource];
if (lodash_1.default.isEmpty(this.mutablePorts[plugin][resourceType])) {
delete this.mutablePorts[plugin][resourceType];
if (lodash_1.default.isEmpty(this.mutablePorts[plugin])) {
delete this.mutablePorts[plugin];
}
}
}
this.persist();
}
}
allocatePort({ plugin, resourceType, resource, name, }) {
if (this.mutablePorts[plugin] === undefined) {
this.mutablePorts[plugin] = {};
}
if (this.mutablePorts[plugin][resourceType] === undefined) {
this.mutablePorts[plugin][resourceType] = {};
}
if (this.mutablePorts[plugin][resourceType][resource] === undefined) {
this.mutablePorts[plugin][resourceType][resource] = {};
}
if (this.mutablePorts[plugin][resourceType][resource][name] === undefined) {
this.mutablePorts[plugin][resourceType][resource][name] = this.getNextPort();
this.persist();
}
return this.mutablePorts[plugin][resourceType][resource][name];
}
getDebug() {
return [
['Config Path', this.config.configPath],
['Current Port', `${this.mutableCurrentPort}`],
['Available Ports', JSON.stringify(this.mutableAvailablePorts)],
[
'Ports',
{
type: 'list',
table: [['Plugin', 'Resource Type', 'Resource', 'Name', 'Port']].concat(Object.entries(this.mutablePorts).reduce((acc, [plugin, pluginPorts]) => acc.concat(Object.entries(pluginPorts).reduce((acc1, [resourceType, resourceTypePorts]) => acc1.concat(Object.entries(resourceTypePorts).reduce((acc2, [resource, resourcePorts]) => acc2.concat(Object.entries(resourcePorts).map(([name, port]) => [plugin, resourceType, resource, name, `${port}`])), [])), [])), [])),
},
],
];
}
async persist() {
if (this.mutablePersisting) {
this.mutableShouldPersist = true;
return;
}
this.mutablePersisting = true;
this.mutableShouldPersist = false;
try {
await this.config.update({ config: { ports: this.mutablePorts } });
}
catch (error) {
this.monitor.logError({
name: 'neo_update_config_error',
message: 'Failed to update config',
error,
});
}
this.mutablePersisting = false;
if (this.mutableShouldPersist) {
await this.persist();
}
}
getNextPort() {
if (this.mutableAvailablePorts.length > 0) {
return this.mutableAvailablePorts.shift();
}
const currentPort = this.mutableCurrentPort;
this.mutableCurrentPort += 1;
return currentPort;
}
}
exports.PortAllocator = PortAllocator;
//# sourceMappingURL=data:application/json;charset=utf8;base64,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S0FBSyxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLENBQUM7U0FDcEU7UUFBQyxPQUFPLEtBQUssRUFBRTtZQUNkLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDO2dCQUNwQixJQUFJLEVBQUUseUJBQXlCO2dCQUMvQixPQUFPLEVBQUUseUJBQXlCO2dCQUNsQyxLQUFLO2FBQ04sQ0FBQyxDQUFDO1NBQ0o7UUFFRCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDO1FBQy9CLElBQUksSUFBSSxDQUFDLG9CQUFvQixFQUFFO1lBQzdCLE1BQU0sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1NBQ3RCO0lBQ0gsQ0FBQztJQUVPLFdBQVc7UUFDakIsSUFBSSxJQUFJLENBQUMscUJBQXFCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUN6QyxPQUFPLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxLQUFLLEVBQVksQ0FBQztTQUNyRDtRQUVELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQztRQUM1QyxJQUFJLENBQUMsa0JBQWtCLElBQUksQ0FBQyxDQUFDO1FBRTdCLE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7Q0FDRjtBQWxQRCxzQ0FrUEMiLCJmaWxlIjoibmVvLW9uZS1zZXJ2ZXIvc3JjL1BvcnRBbGxvY2F0b3IuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyB0c2xpbnQ6ZGlzYWJsZSByZWFkb25seS1rZXl3b3JkIG5vLWxvb3Atc3RhdGVtZW50IG5vLW9iamVjdC1tdXRhdGlvbiBuby1keW5hbWljLWRlbGV0ZVxuaW1wb3J0IHsgTW9uaXRvciB9IGZyb20gJ0BuZW8tb25lL21vbml0b3InO1xuaW1wb3J0IHsgQ29uZmlnLCBEZXNjcmliZVRhYmxlLCBQb3J0QWxsb2NhdG9yIGFzIElQb3J0QWxsb2NhdG9yIH0gZnJvbSAnQG5lby1vbmUvc2VydmVyLXBsdWdpbic7XG5pbXBvcnQgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW50ZXJmYWNlIE5hbWVQb3J0cyB7XG4gIFtuYW1lOiBzdHJpbmddOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBSZXNvdXJjZVBvcnRzIHtcbiAgW3Jlc291cmNlOiBzdHJpbmddOiBOYW1lUG9ydHM7XG59XG5cbmludGVyZmFjZSBQbHVnaW5Qb3J0cyB7XG4gIFtyZXNvdXJjZVR5cGU6IHN0cmluZ106IFJlc291cmNlUG9ydHM7XG59XG5cbmludGVyZmFjZSBQb3J0cyB7XG4gIFtwbHVnaW46IHN0cmluZ106IFBsdWdpblBvcnRzO1xufVxuXG5pbnRlcmZhY2UgUG9ydEFsbG9jYXRvckNvbmZpZyB7XG4gIHJlYWRvbmx5IHBvcnRzOiBQb3J0cztcbn1cblxuY29uc3QgY3JlYXRlUG9ydEFsbG9jYXRvckNvbmZpZyA9ICh7IGRhdGFQYXRoIH06IHsgcmVhZG9ubHkgZGF0YVBhdGg6IHN0cmluZyB9KTogQ29uZmlnPFBvcnRBbGxvY2F0b3JDb25maWc+ID0+XG4gIG5ldyBDb25maWcoe1xuICAgIG5hbWU6ICdwb3J0X2FsbG9jYXRvcicsXG4gICAgZGVmYXVsdENvbmZpZzogeyBwb3J0czoge30gfSxcbiAgICBzY2hlbWE6IHtcbiAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgcmVxdWlyZWQ6IFsncG9ydHMnXSxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgcG9ydHM6IHtcbiAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICBwYXR0ZXJuUHJvcGVydGllczoge1xuICAgICAgICAgICAgJ14uKiQnOiB7XG4gICAgICAgICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICAgICAgICBwYXR0ZXJuUHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICdeLiokJzoge1xuICAgICAgICAgICAgICAgICAgdHlwZTogJ29iamVjdCcsXG4gICAgICAgICAgICAgICAgICBwYXR0ZXJuUHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICAnXi4qJCc6IHtcbiAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnb2JqZWN0JyxcbiAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuUHJvcGVydGllczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgJ14uKiQnOiB7IHR5cGU6ICdudW1iZXInIH0sXG4gICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcblxuICAgIGNvbmZpZ1BhdGg6IGRhdGFQYXRoLFxuICB9KTtcblxuZXhwb3J0IGNsYXNzIFBvcnRBbGxvY2F0b3IgaW1wbGVtZW50cyBJUG9ydEFsbG9jYXRvciB7XG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgY3JlYXRlKHtcbiAgICBtb25pdG9yLFxuICAgIGRhdGFQYXRoLFxuICAgIHBvcnRNaW4sXG4gICAgcG9ydE1heCxcbiAgfToge1xuICAgIHJlYWRvbmx5IG1vbml0b3I6IE1vbml0b3I7XG4gICAgcmVhZG9ubHkgZGF0YVBhdGg6IHN0cmluZztcbiAgICByZWFkb25seSBwb3J0TWluOiBudW1iZXI7XG4gICAgcmVhZG9ubHkgcG9ydE1heDogbnVtYmVyO1xuICB9KTogUHJvbWlzZTxQb3J0QWxsb2NhdG9yPiB7XG4gICAgY29uc3QgY29uZmlnID0gY3JlYXRlUG9ydEFsbG9jYXRvckNvbmZpZyh7IGRhdGFQYXRoIH0pO1xuICAgIGNvbnN0IHsgcG9ydHMgfSA9IGF3YWl0IGNvbmZpZy5jb25maWckLnBpcGUodGFrZSgxKSkudG9Qcm9taXNlKCk7XG5cbiAgICByZXR1cm4gbmV3IFBvcnRBbGxvY2F0b3Ioe1xuICAgICAgbW9uaXRvcixcbiAgICAgIGNvbmZpZyxcbiAgICAgIHBvcnRzLFxuICAgICAgcG9ydE1pbixcbiAgICAgIHBvcnRNYXgsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG1vbml0b3I6IE1vbml0b3I7XG4gIHByaXZhdGUgcmVhZG9ubHkgbXV0YWJsZVBvcnRzOiBQb3J0cztcbiAgcHJpdmF0ZSBtdXRhYmxlQ3VycmVudFBvcnQ6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBtdXRhYmxlQXZhaWxhYmxlUG9ydHM6IG51bWJlcltdO1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZzogQ29uZmlnPFBvcnRBbGxvY2F0b3JDb25maWc+O1xuICBwcml2YXRlIG11dGFibGVQZXJzaXN0aW5nOiBib29sZWFuO1xuICBwcml2YXRlIG11dGFibGVTaG91bGRQZXJzaXN0OiBib29sZWFuO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcih7XG4gICAgbW9uaXRvcixcbiAgICBwb3J0cyxcbiAgICBwb3J0TWluLFxuICAgIHBvcnRNYXgsXG4gICAgY29uZmlnLFxuICB9OiB7XG4gICAgcmVhZG9ubHkgbW9uaXRvcjogTW9uaXRvcjtcbiAgICByZWFkb25seSBwb3J0czogUG9ydHM7XG4gICAgcmVhZG9ubHkgcG9ydE1pbjogbnVtYmVyO1xuICAgIHJlYWRvbmx5IHBvcnRNYXg6IG51bWJlcjtcbiAgICByZWFkb25seSBjb25maWc6IENvbmZpZzxQb3J0QWxsb2NhdG9yQ29uZmlnPjtcbiAgfSkge1xuICAgIHRoaXMubW9uaXRvciA9IG1vbml0b3IuYXQoJ3BvcnRfYWxsb2NhdG9yJyk7XG5cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tbGV0XG4gICAgbGV0IG1heFBvcnQgPSAtMTtcbiAgICBjb25zdCBmaWx0ZXJlZFBvcnRzOiBQb3J0cyA9IHt9O1xuICAgIGNvbnN0IGFsbFBvcnRzID0gbmV3IFNldCgpO1xuICAgIGZvciAoY29uc3QgW3BsdWdpbiwgcGx1Z2luUG9ydHNdIG9mIE9iamVjdC5lbnRyaWVzKHBvcnRzKSkge1xuICAgICAgY29uc3QgZmlsdGVyZWRSZXNvdXJjZVR5cGVQb3J0czogUGx1Z2luUG9ydHMgPSB7fTtcbiAgICAgIGZvciAoY29uc3QgcGx1Z2luVmFsdWUgb2YgT2JqZWN0LmVudHJpZXMocGx1Z2luUG9ydHMpKSB7XG4gICAgICAgIGNvbnN0IFtyZXNvdXJjZVR5cGUsIHJlc291cmNlVHlwZVBvcnRzXSA9IHBsdWdpblZhbHVlO1xuICAgICAgICBjb25zdCBmaWx0ZXJlZFJlc291cmNlUG9ydHM6IFJlc291cmNlUG9ydHMgPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCByZXNvdXJjZVR5cGVWYWx1ZSBvZiBPYmplY3QuZW50cmllcyhyZXNvdXJjZVR5cGVQb3J0cykpIHtcbiAgICAgICAgICBjb25zdCBbcmVzb3VyY2UsIHJlc291cmNlUG9ydHNdID0gcmVzb3VyY2VUeXBlVmFsdWU7XG4gICAgICAgICAgY29uc3QgZmlsdGVyZWROYW1lUG9ydHM6IE5hbWVQb3J0cyA9IHt9O1xuICAgICAgICAgIGZvciAoY29uc3QgW25hbWUsIHBvcnRdIG9mIE9iamVjdC5lbnRyaWVzKHJlc291cmNlUG9ydHMpKSB7XG4gICAgICAgICAgICBpZiAocG9ydE1pbiA8PSBwb3J0ICYmIHBvcnQgPD0gcG9ydE1heCkge1xuICAgICAgICAgICAgICBtYXhQb3J0ID0gTWF0aC5tYXgobWF4UG9ydCwgcG9ydCk7XG4gICAgICAgICAgICAgIGZpbHRlcmVkTmFtZVBvcnRzW25hbWVdID0gcG9ydDtcbiAgICAgICAgICAgICAgYWxsUG9ydHMuYWRkKHBvcnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIV8uaXNFbXB0eShmaWx0ZXJlZE5hbWVQb3J0cykpIHtcbiAgICAgICAgICAgIGZpbHRlcmVkUmVzb3VyY2VQb3J0c1tyZXNvdXJjZV0gPSBmaWx0ZXJlZE5hbWVQb3J0cztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFfLmlzRW1wdHkoZmlsdGVyZWRSZXNvdXJjZVBvcnRzKSkge1xuICAgICAgICAgIGZpbHRlcmVkUmVzb3VyY2VUeXBlUG9ydHNbcmVzb3VyY2VUeXBlXSA9IGZpbHRlcmVkUmVzb3VyY2VQb3J0cztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKCFfLmlzRW1wdHkoZmlsdGVyZWRSZXNvdXJjZVR5cGVQb3J0cykpIHtcbiAgICAgICAgZmlsdGVyZWRQb3J0c1twbHVnaW5dID0gZmlsdGVyZWRSZXNvdXJjZVR5cGVQb3J0cztcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLm11dGFibGVQb3J0cyA9IGZpbHRlcmVkUG9ydHM7XG4gICAgdGhpcy5tdXRhYmxlQ3VycmVudFBvcnQgPSBtYXhQb3J0ID09PSAtMSA/IHBvcnRNaW4gOiBtYXhQb3J0ICsgMTtcbiAgICB0aGlzLm11dGFibGVBdmFpbGFibGVQb3J0cyA9IF8ucmFuZ2UocG9ydE1pbiwgdGhpcy5tdXRhYmxlQ3VycmVudFBvcnQpLmZpbHRlcigocG9ydCkgPT4gIWFsbFBvcnRzLmhhcyhwb3J0KSk7XG5cbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcblxuICAgIHRoaXMubXV0YWJsZVBlcnNpc3RpbmcgPSBmYWxzZTtcbiAgICB0aGlzLm11dGFibGVTaG91bGRQZXJzaXN0ID0gZmFsc2U7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWZsb2F0aW5nLXByb21pc2VzXG4gICAgdGhpcy5wZXJzaXN0KCk7XG4gIH1cblxuICBwdWJsaWMgcmVsZWFzZVBvcnQoe1xuICAgIHBsdWdpbixcbiAgICByZXNvdXJjZVR5cGUsXG4gICAgcmVzb3VyY2UsXG4gICAgbmFtZSxcbiAgfToge1xuICAgIHJlYWRvbmx5IHBsdWdpbjogc3RyaW5nO1xuICAgIHJlYWRvbmx5IHJlc291cmNlVHlwZTogc3RyaW5nO1xuICAgIHJlYWRvbmx5IHJlc291cmNlOiBzdHJpbmc7XG4gICAgcmVhZG9ubHkgbmFtZT86IHN0cmluZztcbiAgfSk6IHZvaWQge1xuICAgIGlmIChcbiAgICAgICh0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dIGFzIFBsdWdpblBvcnRzIHwgdW5kZWZpbmVkKSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAodGhpcy5tdXRhYmxlUG9ydHNbcGx1Z2luXVtyZXNvdXJjZVR5cGVdIGFzIFJlc291cmNlUG9ydHMgfCB1bmRlZmluZWQpICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICh0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dW3Jlc291cmNlVHlwZV1bcmVzb3VyY2VdIGFzIE5hbWVQb3J0cyB8IHVuZGVmaW5lZCkgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgKG5hbWUgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAodGhpcy5tdXRhYmxlUG9ydHNbcGx1Z2luXVtyZXNvdXJjZVR5cGVdW3Jlc291cmNlXVtuYW1lXSBhcyBudW1iZXIgfCB1bmRlZmluZWQpICE9PSB1bmRlZmluZWQpXG4gICAgKSB7XG4gICAgICBpZiAobmFtZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnN0IHBvcnRzID0gT2JqZWN0LnZhbHVlcyh0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dW3Jlc291cmNlVHlwZV1bcmVzb3VyY2VdKTtcbiAgICAgICAgdGhpcy5tdXRhYmxlQXZhaWxhYmxlUG9ydHMucHVzaCguLi5wb3J0cyk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dW3Jlc291cmNlVHlwZV1bcmVzb3VyY2VdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcG9ydCA9IHRoaXMubXV0YWJsZVBvcnRzW3BsdWdpbl1bcmVzb3VyY2VUeXBlXVtyZXNvdXJjZV1bbmFtZV07XG4gICAgICAgIHRoaXMubXV0YWJsZUF2YWlsYWJsZVBvcnRzLnB1c2gocG9ydCk7XG4gICAgICAgIGRlbGV0ZSB0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dW3Jlc291cmNlVHlwZV1bcmVzb3VyY2VdW25hbWVdO1xuICAgICAgfVxuICAgICAgaWYgKF8uaXNFbXB0eSh0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dW3Jlc291cmNlVHlwZV1bcmVzb3VyY2VdKSkge1xuICAgICAgICBkZWxldGUgdGhpcy5tdXRhYmxlUG9ydHNbcGx1Z2luXVtyZXNvdXJjZVR5cGVdW3Jlc291cmNlXTtcbiAgICAgICAgaWYgKF8uaXNFbXB0eSh0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dW3Jlc291cmNlVHlwZV0pKSB7XG4gICAgICAgICAgZGVsZXRlIHRoaXMubXV0YWJsZVBvcnRzW3BsdWdpbl1bcmVzb3VyY2VUeXBlXTtcbiAgICAgICAgICBpZiAoXy5pc0VtcHR5KHRoaXMubXV0YWJsZVBvcnRzW3BsdWdpbl0pKSB7XG4gICAgICAgICAgICBkZWxldGUgdGhpcy5tdXRhYmxlUG9ydHNbcGx1Z2luXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lIG5vLWZsb2F0aW5nLXByb21pc2VzXG4gICAgICB0aGlzLnBlcnNpc3QoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYWxsb2NhdGVQb3J0KHtcbiAgICBwbHVnaW4sXG4gICAgcmVzb3VyY2VUeXBlLFxuICAgIHJlc291cmNlLFxuICAgIG5hbWUsXG4gIH06IHtcbiAgICByZWFkb25seSBwbHVnaW46IHN0cmluZztcbiAgICByZWFkb25seSByZXNvdXJjZVR5cGU6IHN0cmluZztcbiAgICByZWFkb25seSByZXNvdXJjZTogc3RyaW5nO1xuICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgfSk6IG51bWJlciB7XG4gICAgaWYgKCh0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dIGFzIFBsdWdpblBvcnRzIHwgdW5kZWZpbmVkKSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dID0ge307XG4gICAgfVxuXG4gICAgaWYgKCh0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dW3Jlc291cmNlVHlwZV0gYXMgUmVzb3VyY2VQb3J0cyB8IHVuZGVmaW5lZCkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5tdXRhYmxlUG9ydHNbcGx1Z2luXVtyZXNvdXJjZVR5cGVdID0ge307XG4gICAgfVxuXG4gICAgaWYgKCh0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dW3Jlc291cmNlVHlwZV1bcmVzb3VyY2VdIGFzIE5hbWVQb3J0cyB8IHVuZGVmaW5lZCkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5tdXRhYmxlUG9ydHNbcGx1Z2luXVtyZXNvdXJjZVR5cGVdW3Jlc291cmNlXSA9IHt9O1xuICAgIH1cblxuICAgIGlmICgodGhpcy5tdXRhYmxlUG9ydHNbcGx1Z2luXVtyZXNvdXJjZVR5cGVdW3Jlc291cmNlXVtuYW1lXSBhcyBudW1iZXIgfCB1bmRlZmluZWQpID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMubXV0YWJsZVBvcnRzW3BsdWdpbl1bcmVzb3VyY2VUeXBlXVtyZXNvdXJjZV1bbmFtZV0gPSB0aGlzLmdldE5leHRQb3J0KCk7XG4gICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmUgbm8tZmxvYXRpbmctcHJvbWlzZXNcbiAgICAgIHRoaXMucGVyc2lzdCgpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm11dGFibGVQb3J0c1twbHVnaW5dW3Jlc291cmNlVHlwZV1bcmVzb3VyY2VdW25hbWVdO1xuICB9XG5cbiAgcHVibGljIGdldERlYnVnKCk6IERlc2NyaWJlVGFibGUge1xuICAgIHJldHVybiBbXG4gICAgICBbJ0NvbmZpZyBQYXRoJywgdGhpcy5jb25maWcuY29uZmlnUGF0aF0gYXMgY29uc3QsXG4gICAgICBbJ0N1cnJlbnQgUG9ydCcsIGAke3RoaXMubXV0YWJsZUN1cnJlbnRQb3J0fWBdIGFzIGNvbnN0LFxuICAgICAgWydBdmFpbGFibGUgUG9ydHMnLCBKU09OLnN0cmluZ2lmeSh0aGlzLm11dGFibGVBdmFpbGFibGVQb3J0cyldIGFzIGNvbnN0LFxuICAgICAgW1xuICAgICAgICAnUG9ydHMnLFxuICAgICAgICB7XG4gICAgICAgICAgdHlwZTogJ2xpc3QnLFxuICAgICAgICAgIHRhYmxlOiBbWydQbHVnaW4nLCAnUmVzb3VyY2UgVHlwZScsICdSZXNvdXJjZScsICdOYW1lJywgJ1BvcnQnXV0uY29uY2F0KFxuICAgICAgICAgICAgT2JqZWN0LmVudHJpZXModGhpcy5tdXRhYmxlUG9ydHMpLnJlZHVjZTxSZWFkb25seUFycmF5PFtzdHJpbmcsIHN0cmluZywgc3RyaW5nLCBzdHJpbmcsIHN0cmluZ10+PihcbiAgICAgICAgICAgICAgKGFjYywgW3BsdWdpbiwgcGx1Z2luUG9ydHNdKSA9PlxuICAgICAgICAgICAgICAgIGFjYy5jb25jYXQoXG4gICAgICAgICAgICAgICAgICBPYmplY3QuZW50cmllcyhwbHVnaW5Qb3J0cykucmVkdWNlPFJlYWRvbmx5QXJyYXk8W3N0cmluZywgc3RyaW5nLCBzdHJpbmcsIHN0cmluZywgc3RyaW5nXT4+KFxuICAgICAgICAgICAgICAgICAgICAoYWNjMSwgW3Jlc291cmNlVHlwZSwgcmVzb3VyY2VUeXBlUG9ydHNdKSA9PlxuICAgICAgICAgICAgICAgICAgICAgIGFjYzEuY29uY2F0KFxuICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMocmVzb3VyY2VUeXBlUG9ydHMpLnJlZHVjZTxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgUmVhZG9ubHlBcnJheTxbc3RyaW5nLCBzdHJpbmcsIHN0cmluZywgc3RyaW5nLCBzdHJpbmddPlxuICAgICAgICAgICAgICAgICAgICAgICAgPihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKGFjYzIsIFtyZXNvdXJjZSwgcmVzb3VyY2VQb3J0c10pID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWNjMi5jb25jYXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBPYmplY3QuZW50cmllcyhyZXNvdXJjZVBvcnRzKS5tYXA8W3N0cmluZywgc3RyaW5nLCBzdHJpbmcsIHN0cmluZywgc3RyaW5nXT4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChbbmFtZSwgcG9ydF0pID0+IFtwbHVnaW4sIHJlc291cmNlVHlwZSwgcmVzb3VyY2UsIG5hbWUsIGAke3BvcnR9YF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICksXG5cbiAgICAgICAgICAgICAgW10sXG4gICAgICAgICAgICApLFxuICAgICAgICAgICksXG4gICAgICAgIH0sXG4gICAgICBdIGFzIGNvbnN0LFxuICAgIF07XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBlcnNpc3QoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMubXV0YWJsZVBlcnNpc3RpbmcpIHtcbiAgICAgIHRoaXMubXV0YWJsZVNob3VsZFBlcnNpc3QgPSB0cnVlO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMubXV0YWJsZVBlcnNpc3RpbmcgPSB0cnVlO1xuICAgIHRoaXMubXV0YWJsZVNob3VsZFBlcnNpc3QgPSBmYWxzZTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmNvbmZpZy51cGRhdGUoeyBjb25maWc6IHsgcG9ydHM6IHRoaXMubXV0YWJsZVBvcnRzIH0gfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMubW9uaXRvci5sb2dFcnJvcih7XG4gICAgICAgIG5hbWU6ICduZW9fdXBkYXRlX2NvbmZpZ19lcnJvcicsXG4gICAgICAgIG1lc3NhZ2U6ICdGYWlsZWQgdG8gdXBkYXRlIGNvbmZpZycsXG4gICAgICAgIGVycm9yLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5tdXRhYmxlUGVyc2lzdGluZyA9IGZhbHNlO1xuICAgIGlmICh0aGlzLm11dGFibGVTaG91bGRQZXJzaXN0KSB7XG4gICAgICBhd2FpdCB0aGlzLnBlcnNpc3QoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldE5leHRQb3J0KCk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMubXV0YWJsZUF2YWlsYWJsZVBvcnRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiB0aGlzLm11dGFibGVBdmFpbGFibGVQb3J0cy5zaGlmdCgpIGFzIG51bWJlcjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50UG9ydCA9IHRoaXMubXV0YWJsZUN1cnJlbnRQb3J0O1xuICAgIHRoaXMubXV0YWJsZUN1cnJlbnRQb3J0ICs9IDE7XG5cbiAgICByZXR1cm4gY3VycmVudFBvcnQ7XG4gIH1cbn1cbiJdfQ==