UNPKG

@qodalis/angular-cli

Version:

A lightweight and flexible command-line interface (CLI) tool designed to streamline workflows and automate tasks for developers.

346 lines 54.5 kB
import { Inject, Injectable } from '@angular/core';
import { CliForegroundColor, DefaultLibraryAuthor, } from '@qodalis/cli-core';
import { CliProcessorsRegistry_TOKEN } from '../../tokens';
import * as i0 from "@angular/core";
import * as i1 from "../../services/script-loader.service";
import * as i2 from "../../services/cli-package-manager.service";
export class CliPackagesCommandProcessor {
    constructor(scriptsLoader, packagesManager, registry) {
        this.scriptsLoader = scriptsLoader;
        this.packagesManager = packagesManager;
        this.registry = registry;
        this.command = 'packages';
        this.description = 'Manage packages in the cli';
        this.author = DefaultLibraryAuthor;
        this.version = '1.0.2';
        this.processors = [];
        this.metadata = {
            sealed: true,
            icon: '📦',
            module: 'system',
        };
        this.registeredDependencies = [];
        const scope = this;
        this.processors = [
            {
                command: 'ls',
                description: 'List all packages in the cli',
                author: DefaultLibraryAuthor,
                async processCommand(_, context) {
                    const packages = await packagesManager.getPackages();
                    context.writer.writeln('Packages:');
                    if (packages.length === 0) {
                        context.writer.writeInfo('No packages installed');
                        context.writer.writeInfo("Use 'packages add <package>' to add a package");
                        return;
                    }
                    packages.forEach((pkg) => {
                        context.writer.writeInfo(`- ${pkg.name}@${pkg.version}`);
                    });
                },
                writeDescription(context) {
                    context.writer.writeln('  packages ls');
                },
            },
            {
                command: 'add',
                description: 'Add a package to the cli, e.g. packages add guid.',
                valueRequired: true,
                async processCommand(command, context) {
                    const packages = command.value.split(' ');
                    for (const pkg of packages) {
                        await scope.addPackage(pkg, context);
                    }
                },
                writeDescription({ writer }) {
                    writer.writeInfo("Supoorts multiple packages, e.g. 'packages add guid server-logs'");
                    writer.writeln('  packages add <package> ' +
                        writer.wrapInColor('# Add a package', CliForegroundColor.Green));
                    writer.writeln('  packages add guid');
                    writer.writeln('  packages add @qodalis/cli-guid');
                    writer.writeln('  packages add @qodalis/cli-server-logs');
                },
            },
            {
                command: 'remove',
                description: 'Remove a package from the cli',
                valueRequired: true,
                async processCommand(command, context) {
                    const packages = command.value.split(' ');
                    for (const pkg of packages) {
                        await scope.removePackage(pkg, context);
                    }
                },
            },
            {
                command: 'update',
                description: 'Update a package in the cli to the latest version or update all packages',
                allowUnlistedCommands: true,
                valueRequired: false,
                async processCommand(command, context) {
                    if (command.value) {
                        await scope.updatePackage(command.value, context);
                    }
                    else {
                        const packages = await packagesManager.getPackages();
                        for (const pkg of packages) {
                            await scope.updatePackage(pkg.name, context);
                        }
                        context.writer.writeSuccess('All packages updated');
                    }
                },
                writeDescription(context) {
                    context.writer.writeln('  packages update <package> ' +
                        context.writer.wrapInColor('# Update a specific package', CliForegroundColor.Green));
                    context.writer.writeln('  packages update ' +
                        context.writer.wrapInColor('# Update all packages', CliForegroundColor.Green));
                },
            },
        ];
    }
    async processCommand(command, context) {
        await context.executor.showHelp(command, context);
    }
    writeDescription({ writer }) {
        writer.writeln(this.description);
        writer.writeInfo('Available packages can be found at https://www.npmjs.com/org/qodalis');
        writer.writeln('  packages ls');
        writer.writeln('  packages add <package>');
    }
    async initialize(context) {
        const packages = await this.packagesManager.getPackages();
        for (const pkg of packages) {
            await this.registerPackageDependencies(pkg, context);
            await this.scriptsLoader.injectScript(pkg.url);
        }
    }
    async removePackage(name, context) {
        context.progressBar.show();
        try {
            const pkg = await this.packagesManager.removePackage(name);
            if (pkg) {
                const module = window[pkg.name];
                if (module) {
                    module.processors?.forEach((processor) => {
                        this.registry.unregisterProcessor(processor);
                    });
                }
            }
            context.progressBar.complete();
            context.writer.writeSuccess(`Package ${pkg.name}@${pkg.version} removed successfully`);
        }
        catch (e) {
            context.progressBar.complete();
            context.writer.writeError(e?.toString() || 'Unknown error');
        }
    }
    async addPackage(name, context) {
        const { progressBar, writer } = context;
        const hasPackage = await this.packagesManager.hasPackage(name);
        if (hasPackage) {
            writer.writeInfo(`Package ${name} already installed`);
            return;
        }
        progressBar.show();
        progressBar.setText(`Fetching package ${name}`);
        try {
            const promises = [
                this.scriptsLoader
                    .getScript(`https://unpkg.com/${name}` + '/package.json')
                    .catch((error) => ({
                    error,
                    content: null,
                    xhr: null,
                }))
                    .finally(() => {
                    progressBar.update(10, {
                        type: 'increment',
                    });
                }),
            ];
            if (!name.startsWith(this.packagesManager.QODALIS_COMMAND_PREFIX)) {
                promises.push(this.scriptsLoader
                    .getScript(`https://unpkg.com/${this.packagesManager.QODALIS_COMMAND_PREFIX}${name}` +
                    '/package.json')
                    .catch((error) => ({
                    error,
                    content: null,
                    xhr: null,
                }))
                    .finally(() => {
                    progressBar.update(10, {
                        type: 'increment',
                    });
                }));
            }
            progressBar.update(10);
            const packages = await Promise.all(promises);
            if (packages.every((p) => p.error)) {
                progressBar.setText('Package not found');
                throw packages[0].error;
            }
            const validResponses = packages
                .filter((p) => p.content)
                .map((p) => JSON.parse(p.content || '{}'));
            progressBar.update(20, {
                type: 'increment',
            });
            progressBar.setText("Checking package's dependencies");
            const packgeInfo = validResponses.some((x) => x.name.startsWith(this.packagesManager.QODALIS_COMMAND_PREFIX))
                ? validResponses.find((x) => x.name.startsWith(this.packagesManager.QODALIS_COMMAND_PREFIX))
                : validResponses[0];
            const response = await this.scriptsLoader.getScript(`https://unpkg.com/${packgeInfo.name}`, {
                onProgress: (progress) => {
                    context.progressBar.update(progress);
                },
            });
            progressBar.update(20, {
                type: 'increment',
            });
            progressBar.setText('Injecting package');
            const pkg = {
                name: packgeInfo.name,
                version: packgeInfo.version || 'latest',
                url: response.xhr.responseURL,
                dependencies: packgeInfo.cliDependencies || [],
            };
            progressBar.update(80);
            progressBar.setText('Registering dependencies');
            await this.registerPackageDependencies(pkg, context);
            progressBar.update(90);
            progressBar.setText('Dependencies registered');
            if (response.content) {
                await this.scriptsLoader.injectBodyScript(response.content);
            }
            progressBar.update(95);
            progressBar.setText('Saving package');
            await this.packagesManager.addPackage(pkg);
            context.progressBar.complete();
            context.writer.writeSuccess(`Package ${packgeInfo.name}@${packgeInfo.version} added successfully`);
        }
        catch (e) {
            context.progressBar.complete();
            context.writer.writeError(e?.toString() || 'Unknown error');
        }
    }
    async updatePackage(name, context) {
        const { progressBar, writer } = context;
        progressBar.show();
        try {
            progressBar.update(10, {
                type: 'increment',
            });
            progressBar.setText(`Updating package ${name}`);
            const currentPackage = await this.packagesManager.getPackage(name);
            if (!currentPackage) {
                progressBar.complete();
                writer.writeError(`Package ${name} not found`);
                return;
            }
            const packageUrl = `https://unpkg.com/${currentPackage.name}`;
            const newPackage = await this.scriptsLoader
                .getScript(packageUrl + '/package.json')
                .then((response) => {
                return JSON.parse(response.content || '{}');
            });
            progressBar.update(20, {
                type: 'increment',
            });
            progressBar.setText(`Checking for updates for package ${currentPackage.name}`);
            if (newPackage.version === currentPackage.version) {
                context.progressBar.complete();
                context.writer.writeInfo(`Package ${currentPackage.name} is already up to date with version ${currentPackage.version}`);
                return;
            }
            const response = await this.scriptsLoader.getScript(packageUrl, {
                onProgress: (progress) => {
                    context.progressBar.update(progress);
                },
            });
            progressBar.update(20, {
                type: 'increment',
            });
            progressBar.setText(`Updating package ${currentPackage.name}`);
            const updatedPkg = {
                name: newPackage.name,
                version: newPackage.version || 'latest',
                url: response.xhr.responseURL,
                dependencies: newPackage.cliDependencies || [],
            };
            await this.registerPackageDependencies(updatedPkg, context);
            progressBar.update(90);
            progressBar.setText(`Injecting package ${currentPackage.name}`);
            if (response.content) {
                await this.scriptsLoader.injectBodyScript(response.content);
            }
            await this.packagesManager.updatePackage(updatedPkg);
            progressBar.setText(`Package ${currentPackage.name} updated successfully`);
            progressBar.complete();
            writer.writeSuccess(`Package ${currentPackage.name} updated successfully to version ${newPackage.version} from ${currentPackage.version}`);
        }
        catch (e) {
            progressBar.complete();
            writer.writeError(e?.toString() || 'Unknown error');
        }
    }
    async registerPackageDependencies(pkg, { logger }) {
        if (pkg.dependencies && pkg.dependencies.length > 0) {
            logger.info(`Injecting package ${pkg.name} dependencies`);
            for (const dependency of pkg.dependencies) {
                if (this.registeredDependencies.includes(dependency.name)) {
                    logger.info(`Dependency ${dependency.globalName} already registered`);
                    continue;
                }
                await this.scriptsLoader.injectScript(dependency.url);
                if (dependency.globalName) {
                    const isAvailable = await this.waitForGlobal(dependency.globalName, 3000);
                    if (!isAvailable) {
                        logger.error(`Dependency ${dependency.globalName} not found in global scope within timeout`);
                        return;
                    }
                    else {
                        logger.info(`Dependency ${dependency.globalName} is available in global scope`);
                    }
                }
                this.registeredDependencies.push(dependency.name);
            }
        }
        else {
            logger.info(`Package ${pkg.name} has no dependencies`);
        }
    }
    /**
     * Waits until a global variable is available on the `window` object.
     * @param globalName {string} The name of the global variable to check.
     * @param timeout {number} The maximum time to wait in milliseconds.
     * @returns {Promise<boolean>} Resolves to `true` if the variable is found, `false` otherwise.
     */
    waitForGlobal(globalName, timeout) {
        return new Promise((resolve) => {
            const interval = 50; // Check every 50ms
            let elapsed = 0;
            const check = () => {
                if (window[globalName]) {
                    resolve(true);
                }
                else if (elapsed >= timeout) {
                    resolve(false);
                }
                else {
                    elapsed += interval;
                    setTimeout(check, interval);
                }
            };
            check();
        });
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliPackagesCommandProcessor, deps: [{ token: i1.ScriptLoaderService }, { token: i2.CliPackageManagerService }, { token: CliProcessorsRegistry_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliPackagesCommandProcessor }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliPackagesCommandProcessor, decorators: [{
            type: Injectable
        }], ctorParameters: function () { return [{ type: i1.ScriptLoaderService }, { type: i2.CliPackageManagerService }, { type: undefined, decorators: [{
                    type: Inject,
                    args: [CliProcessorsRegistry_TOKEN]
                }] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLXBhY2thZ2VzLWNvbW1hbmQtcHJvY2Vzc29yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpL3NyYy9saWIvY2xpL3Byb2Nlc3NvcnMvc3lzdGVtL2NsaS1wYWNrYWdlcy1jb21tYW5kLXByb2Nlc3Nvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQ0gsa0JBQWtCLEVBRWxCLG9CQUFvQixHQUV2QixNQUFNLG1CQUFtQixDQUFDO0FBVTNCLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGNBQWMsQ0FBQzs7OztBQUczRCxNQUFNLE9BQU8sMkJBQTJCO0lBbUJwQyxZQUNxQixhQUFrQyxFQUNsQyxlQUF5QyxFQUV6QyxRQUFzQztRQUh0QyxrQkFBYSxHQUFiLGFBQWEsQ0FBcUI7UUFDbEMsb0JBQWUsR0FBZixlQUFlLENBQTBCO1FBRXpDLGFBQVEsR0FBUixRQUFRLENBQThCO1FBdEJsRCxZQUFPLEdBQUcsVUFBVSxDQUFDO1FBRTlCLGdCQUFXLEdBQUcsNEJBQTRCLENBQUM7UUFFM0MsV0FBTSxHQUFHLG9CQUFvQixDQUFDO1FBRXJCLFlBQU8sR0FBRyxPQUFPLENBQUM7UUFFbEIsZUFBVSxHQUF3QyxFQUFFLENBQUM7UUFFckQsYUFBUSxHQUFzQztZQUNuRCxNQUFNLEVBQUUsSUFBSTtZQUNaLElBQUksRUFBRSxJQUFJO1lBQ1YsTUFBTSxFQUFFLFFBQVE7U0FDbkIsQ0FBQztRQUVNLDJCQUFzQixHQUFhLEVBQUUsQ0FBQztRQVExQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUM7UUFFbkIsSUFBSSxDQUFDLFVBQVUsR0FBRztZQUNkO2dCQUNJLE9BQU8sRUFBRSxJQUFJO2dCQUNiLFdBQVcsRUFBRSw4QkFBOEI7Z0JBQzNDLE1BQU0sRUFBRSxvQkFBb0I7Z0JBQzVC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LENBQUMsSUFBSSxDQUFDLENBQUM7YUFDckQ7U0FDSjthQUFNO1lBQ0gsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxJQUFJLHNCQUFzQixDQUFDLENBQUM7U0FDMUQ7SUFDTCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSyxhQUFhLENBQ2pCLFVBQWtCLEVBQ2xCLE9BQWU7UUFFZixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7WUFDM0IsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDLENBQUMsbUJBQW1CO1lBQ3hDLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQztZQUVoQixNQUFNLEtBQUssR0FBRyxHQUFHLEVBQUU7Z0JBQ2YsSUFBSyxNQUFjLENBQUMsVUFBVSxDQUFDLEVBQUU7b0JBQzdCLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztpQkFDakI7cUJBQU0sSUFBSSxPQUFPLElBQUksT0FBTyxFQUFFO29CQUMzQixPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7aUJBQ2xCO3FCQUFNO29CQUNILE9BQU8sSUFBSSxRQUFRLENBQUM7b0JBQ3BCLFVBQVUsQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7aUJBQy9CO1lBQ0wsQ0FBQyxDQUFDO1lBRUYsS0FBSyxFQUFFLENBQUM7UUFDWixDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7K0dBcmRRLDJCQUEyQiw2RkFzQnhCLDJCQUEyQjttSEF0QjlCLDJCQUEyQjs7NEZBQTNCLDJCQUEyQjtrQkFEdkMsVUFBVTs7MEJBdUJGLE1BQU07MkJBQUMsMkJBQTJCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICAgIENsaUZvcmVncm91bmRDb2xvcixcbiAgICBDbGlQcm9jZXNzb3JNZXRhZGF0YSxcbiAgICBEZWZhdWx0TGlicmFyeUF1dGhvcixcbiAgICBJQ2xpQ29tbWFuZFByb2Nlc3NvclJlZ2lzdHJ5LFxufSBmcm9tICdAcW9kYWxpcy9jbGktY29yZSc7XG5pbXBvcnQge1xuICAgIENsaVByb2Nlc3NDb21tYW5kLFxuICAgIElDbGlDb21tYW5kUHJvY2Vzc29yLFxuICAgIElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgIElDbGlVbWRNb2R1bGUsXG4gICAgUGFja2FnZSxcbn0gZnJvbSAnQHFvZGFsaXMvY2xpLWNvcmUnO1xuaW1wb3J0IHsgU2NyaXB0TG9hZGVyU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3NjcmlwdC1sb2FkZXIuc2VydmljZSc7XG5pbXBvcnQgeyBDbGlQYWNrYWdlTWFuYWdlclNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9jbGktcGFja2FnZS1tYW5hZ2VyLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2xpUHJvY2Vzc29yc1JlZ2lzdHJ5X1RPS0VOIH0gZnJvbSAnLi4vLi4vdG9rZW5zJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIENsaVBhY2thZ2VzQ29tbWFuZFByb2Nlc3NvciBpbXBsZW1lbnRzIElDbGlDb21tYW5kUHJvY2Vzc29yIHtcbiAgICByZWFkb25seSBjb21tYW5kID0gJ3BhY2thZ2VzJztcblxuICAgIGRlc2NyaXB0aW9uID0gJ01hbmFnZSBwYWNrYWdlcyBpbiB0aGUgY2xpJztcblxuICAgIGF1dGhvciA9IERlZmF1bHRMaWJyYXJ5QXV0aG9yO1xuXG4gICAgcmVhZG9ubHkgdmVyc2lvbiA9ICcxLjAuMic7XG5cbiAgICByZWFkb25seSBwcm9jZXNzb3JzPzogSUNsaUNvbW1hbmRQcm9jZXNzb3JbXSB8IHVuZGVmaW5lZCA9IFtdO1xuXG4gICAgcmVhZG9ubHkgbWV0YWRhdGE/OiBDbGlQcm9jZXNzb3JNZXRhZGF0YSB8IHVuZGVmaW5lZCA9IHtcbiAgICAgICAgc2VhbGVkOiB0cnVlLFxuICAgICAgICBpY29uOiAn8J+TpicsXG4gICAgICAgIG1vZHVsZTogJ3N5c3RlbScsXG4gICAgfTtcblxuICAgIHByaXZhdGUgcmVnaXN0ZXJlZERlcGVuZGVuY2llczogc3RyaW5nW10gPSBbXTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IHNjcmlwdHNMb2FkZXI6IFNjcmlwdExvYWRlclNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgcGFja2FnZXNNYW5hZ2VyOiBDbGlQYWNrYWdlTWFuYWdlclNlcnZpY2UsXG4gICAgICAgIEBJbmplY3QoQ2xpUHJvY2Vzc29yc1JlZ2lzdHJ5X1RPS0VOKVxuICAgICAgICBwcml2YXRlIHJlYWRvbmx5IHJlZ2lzdHJ5OiBJQ2xpQ29tbWFuZFByb2Nlc3NvclJlZ2lzdHJ5LFxuICAgICkge1xuICAgICAgICBjb25zdCBzY29wZSA9IHRoaXM7XG5cbiAgICAgICAgdGhpcy5wcm9jZXNzb3JzID0gW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGNvbW1hbmQ6ICdscycsXG4gICAgICAgICAgICAgICAgZGVzY3JpcHRpb246ICdMaXN0IGFsbCBwYWNrYWdlcyBpbiB0aGUgY2xpJyxcbiAgICAgICAgICAgICAgICBhdXRob3I6IERlZmF1bHRMaWJyYXJ5QXV0aG9yLFxuICAgICAgICAgICAgICAgIGFzeW5jIHByb2Nlc3NDb21tYW5kKF8sIGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFja2FnZXMgPSBhd2FpdCBwYWNrYWdlc01hbmFnZXIuZ2V0UGFja2FnZXMoKTtcblxuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZWxuKCdQYWNrYWdlczonKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFja2FnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUluZm8oJ05vIHBhY2thZ2VzIGluc3RhbGxlZCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVJbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiVXNlICdwYWNrYWdlcyBhZGQgPHBhY2thZ2U+JyB0byBhZGQgYSBwYWNrYWdlXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcGFja2FnZXMuZm9yRWFjaCgocGtnKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYC0gJHtwa2cubmFtZX1AJHtwa2cudmVyc2lvbn1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB3cml0ZURlc2NyaXB0aW9uKGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVsbignICBwYWNrYWdlcyBscycpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGNvbW1hbmQ6ICdhZGQnLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICAgICAnQWRkIGEgcGFja2FnZSB0byB0aGUgY2xpLCBlLmcuIHBhY2thZ2VzIGFkZCBndWlkLicsXG4gICAgICAgICAgICAgICAgdmFsdWVSZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhc3luYyBwcm9jZXNzQ29tbWFuZChjb21tYW5kLCBjb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhY2thZ2VzID0gY29tbWFuZC52YWx1ZSEuc3BsaXQoJyAnKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBwa2cgb2YgcGFja2FnZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHNjb3BlLmFkZFBhY2thZ2UocGtnLCBjb250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgd3JpdGVEZXNjcmlwdGlvbih7IHdyaXRlciB9KSB7XG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci53cml0ZUluZm8oXG4gICAgICAgICAgICAgICAgICAgICAgICBcIlN1cG9vcnRzIG11bHRpcGxlIHBhY2thZ2VzLCBlLmcuICdwYWNrYWdlcyBhZGQgZ3VpZCBzZXJ2ZXItbG9ncydcIixcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLndyaXRlbG4oXG4gICAgICAgICAgICAgICAgICAgICAgICAnICBwYWNrYWdlcyBhZGQgPHBhY2thZ2U+ICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyaXRlci53cmFwSW5Db2xvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyMgQWRkIGEgcGFja2FnZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENsaUZvcmVncm91bmRDb2xvci5HcmVlbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB3cml0ZXIud3JpdGVsbignICBwYWNrYWdlcyBhZGQgZ3VpZCcpO1xuICAgICAgICAgICAgICAgICAgICB3cml0ZXIud3JpdGVsbignICBwYWNrYWdlcyBhZGQgQHFvZGFsaXMvY2xpLWd1aWQnKTtcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLndyaXRlbG4oJyAgcGFja2FnZXMgYWRkIEBxb2RhbGlzL2NsaS1zZXJ2ZXItbG9ncycpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGNvbW1hbmQ6ICdyZW1vdmUnLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnUmVtb3ZlIGEgcGFja2FnZSBmcm9tIHRoZSBjbGknLFxuICAgICAgICAgICAgICAgIHZhbHVlUmVxdWlyZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgYXN5bmMgcHJvY2Vzc0NvbW1hbmQoY29tbWFuZCwgY29udGV4dCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWNrYWdlcyA9IGNvbW1hbmQudmFsdWUhLnNwbGl0KCcgJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBwa2cgb2YgcGFja2FnZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHNjb3BlLnJlbW92ZVBhY2thZ2UocGtnLCBjb250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGNvbW1hbmQ6ICd1cGRhdGUnLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICAgICAnVXBkYXRlIGEgcGFja2FnZSBpbiB0aGUgY2xpIHRvIHRoZSBsYXRlc3QgdmVyc2lvbiBvciB1cGRhdGUgYWxsIHBhY2thZ2VzJyxcbiAgICAgICAgICAgICAgICBhbGxvd1VubGlzdGVkQ29tbWFuZHM6IHRydWUsXG4gICAgICAgICAgICAgICAgdmFsdWVSZXF1aXJlZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgYXN5bmMgcHJvY2Vzc0NvbW1hbmQoY29tbWFuZCwgY29udGV4dCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY29tbWFuZC52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXdhaXQgc2NvcGUudXBkYXRlUGFja2FnZShjb21tYW5kLnZhbHVlISwgY29udGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYWNrYWdlcyA9IGF3YWl0IHBhY2thZ2VzTWFuYWdlci5nZXRQYWNrYWdlcygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBwa2cgb2YgcGFja2FnZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCBzY29wZS51cGRhdGVQYWNrYWdlKHBrZy5uYW1lLCBjb250ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVTdWNjZXNzKCdBbGwgcGFja2FnZXMgdXBkYXRlZCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB3cml0ZURlc2NyaXB0aW9uKGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVsbihcbiAgICAgICAgICAgICAgICAgICAgICAgICcgIHBhY2thZ2VzIHVwZGF0ZSA8cGFja2FnZT4gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JhcEluQ29sb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcjIFVwZGF0ZSBhIHNwZWNpZmljIHBhY2thZ2UnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDbGlGb3JlZ3JvdW5kQ29sb3IuR3JlZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVsbihcbiAgICAgICAgICAgICAgICAgICAgICAgICcgIHBhY2thZ2VzIHVwZGF0ZSAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cmFwSW5Db2xvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJyMgVXBkYXRlIGFsbCBwYWNrYWdlcycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENsaUZvcmVncm91bmRDb2xvci5HcmVlbixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuICAgICAgICBdO1xuICAgIH1cblxuICAgIGFzeW5jIHByb2Nlc3NDb21tYW5kKFxuICAgICAgICBjb21tYW5kOiBDbGlQcm9jZXNzQ29tbWFuZCxcbiAgICAgICAgY29udGV4dDogSUNsaUV4ZWN1dGlvbkNvbnRleHQsXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGF3YWl0IGNvbnRleHQuZXhlY3V0b3Iuc2hvd0hlbHAoY29tbWFuZCwgY29udGV4dCk7XG4gICAgfVxuXG4gICAgd3JpdGVEZXNjcmlwdGlvbj8oeyB3cml0ZXIgfTogSUNsaUV4ZWN1dGlvbkNvbnRleHQpOiB2b2lkIHtcbiAgICAgICAgd3JpdGVyLndyaXRlbG4odGhpcy5kZXNjcmlwdGlvbik7XG5cbiAgICAgICAgd3JpdGVyLndyaXRlSW5mbyhcbiAgICAgICAgICAgICdBdmFpbGFibGUgcGFja2FnZXMgY2FuIGJlIGZvdW5kIGF0IGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9vcmcvcW9kYWxpcycsXG4gICAgICAgICk7XG5cbiAgICAgICAgd3JpdGVyLndyaXRlbG4oJyAgcGFja2FnZXMgbHMnKTtcbiAgICAgICAgd3JpdGVyLndyaXRlbG4oJyAgcGFja2FnZXMgYWRkIDxwYWNrYWdlPicpO1xuICAgIH1cblxuICAgIGFzeW5jIGluaXRpYWxpemUoY29udGV4dDogSUNsaUV4ZWN1dGlvbkNvbnRleHQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgcGFja2FnZXMgPSBhd2FpdCB0aGlzLnBhY2thZ2VzTWFuYWdlci5nZXRQYWNrYWdlcygpO1xuXG4gICAgICAgIGZvciAoY29uc3QgcGtnIG9mIHBhY2thZ2VzKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyUGFja2FnZURlcGVuZGVuY2llcyhwa2csIGNvbnRleHQpO1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnNjcmlwdHNMb2FkZXIuaW5qZWN0U2NyaXB0KHBrZy51cmwpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZW1vdmVQYWNrYWdlKG5hbWU6IHN0cmluZywgY29udGV4dDogSUNsaUV4ZWN1dGlvbkNvbnRleHQpIHtcbiAgICAgICAgY29udGV4dC5wcm9ncmVzc0Jhci5zaG93KCk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHBrZyA9IGF3YWl0IHRoaXMucGFja2FnZXNNYW5hZ2VyLnJlbW92ZVBhY2thZ2UobmFtZSk7XG5cbiAgICAgICAgICAgIGlmIChwa2cpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtb2R1bGUgPSAod2luZG93IGFzIGFueSlbcGtnLm5hbWVdIGFzIElDbGlVbWRNb2R1bGU7XG4gICAgICAgICAgICAgICAgaWYgKG1vZHVsZSkge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUucHJvY2Vzc29ycz8uZm9yRWFjaCgocHJvY2Vzc29yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlZ2lzdHJ5LnVucmVnaXN0ZXJQcm9jZXNzb3IocHJvY2Vzc29yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb250ZXh0LnByb2dyZXNzQmFyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZVN1Y2Nlc3MoXG4gICAgICAgICAgICAgICAgYFBhY2thZ2UgJHtwa2cubmFtZX1AJHtwa2cudmVyc2lvbn0gcmVtb3ZlZCBzdWNjZXNzZnVsbHlgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29udGV4dC5wcm9ncmVzc0Jhci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVFcnJvcihlPy50b1N0cmluZygpIHx8ICdVbmtub3duIGVycm9yJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGFkZFBhY2thZ2UobmFtZTogc3RyaW5nLCBjb250ZXh0OiBJQ2xpRXhlY3V0aW9uQ29udGV4dCkge1xuICAgICAgICBjb25zdCB7IHByb2dyZXNzQmFyLCB3cml0ZXIgfSA9IGNvbnRleHQ7XG5cbiAgICAgICAgY29uc3QgaGFzUGFja2FnZSA9IGF3YWl0IHRoaXMucGFja2FnZXNNYW5hZ2VyLmhhc1BhY2thZ2UobmFtZSk7XG4gICAgICAgIGlmIChoYXNQYWNrYWdlKSB7XG4gICAgICAgICAgICB3cml0ZXIud3JpdGVJbmZvKGBQYWNrYWdlICR7bmFtZX0gYWxyZWFkeSBpbnN0YWxsZWRgKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJvZ3Jlc3NCYXIuc2hvdygpO1xuICAgICAgICBwcm9ncmVzc0Jhci5zZXRUZXh0KGBGZXRjaGluZyBwYWNrYWdlICR7bmFtZX1gKTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBbXG4gICAgICAgICAgICAgICAgdGhpcy5zY3JpcHRzTG9hZGVyXG4gICAgICAgICAgICAgICAgICAgIC5nZXRTY3JpcHQoYGh0dHBzOi8vdW5wa2cuY29tLyR7bmFtZX1gICsgJy9wYWNrYWdlLmpzb24nKVxuICAgICAgICAgICAgICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50OiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgeGhyOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICB9KSlcbiAgICAgICAgICAgICAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvZ3Jlc3NCYXIudXBkYXRlKDEwLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2luY3JlbWVudCcsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICBpZiAoIW5hbWUuc3RhcnRzV2l0aCh0aGlzLnBhY2thZ2VzTWFuYWdlci5RT0RBTElTX0NPTU1BTkRfUFJFRklYKSkge1xuICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2NyaXB0c0xvYWRlclxuICAgICAgICAgICAgICAgICAgICAgICAgLmdldFNjcmlwdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgaHR0cHM6Ly91bnBrZy5jb20vJHt0aGlzLnBhY2thZ2VzTWFuYWdlci5RT0RBTElTX0NPTU1BTkRfUFJFRklYfSR7bmFtZX1gICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJy9wYWNrYWdlLmpzb24nLFxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlcnJvcikgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZW50OiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhocjogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2dyZXNzQmFyLnVwZGF0ZSgxMCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnaW5jcmVtZW50JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHByb2dyZXNzQmFyLnVwZGF0ZSgxMCk7XG5cbiAgICAgICAgICAgIGNvbnN0IHBhY2thZ2VzID0gYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuXG4gICAgICAgICAgICBpZiAocGFja2FnZXMuZXZlcnkoKHApID0+IHAuZXJyb3IpKSB7XG4gICAgICAgICAgICAgICAgcHJvZ3Jlc3NCYXIuc2V0VGV4dCgnUGFja2FnZSBub3QgZm91bmQnKTtcbiAgICAgICAgICAgICAgICB0aHJvdyBwYWNrYWdlc1swXS5lcnJvcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgdmFsaWRSZXNwb25zZXMgPSBwYWNrYWdlc1xuICAgICAgICAgICAgICAgIC5maWx0ZXIoKHApID0+IHAuY29udGVudClcbiAgICAgICAgICAgICAgICAubWFwKChwKSA9PiBKU09OLnBhcnNlKHAuY29udGVudCB8fCAne30nKSk7XG5cbiAgICAgICAgICAgIHByb2dyZXNzQmFyLnVwZGF0ZSgyMCwge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdpbmNyZW1lbnQnLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwcm9ncmVzc0Jhci5zZXRUZXh0KFwiQ2hlY2tpbmcgcGFja2FnZSdzIGRlcGVuZGVuY2llc1wiKTtcblxuICAgICAgICAgICAgY29uc3QgcGFja2dlSW5mbyA9IHZhbGlkUmVzcG9uc2VzLnNvbWUoKHgpID0+XG4gICAgICAgICAgICAgICAgeC5uYW1lLnN0YXJ0c1dpdGgodGhpcy5wYWNrYWdlc01hbmFnZXIuUU9EQUxJU19DT01NQU5EX1BSRUZJWCksXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgPyB2YWxpZFJlc3BvbnNlcy5maW5kKCh4KSA9PlxuICAgICAgICAgICAgICAgICAgICAgIHgubmFtZS5zdGFydHNXaXRoKFxuICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBhY2thZ2VzTWFuYWdlci5RT0RBTElTX0NPTU1BTkRfUFJFRklYLFxuICAgICAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgOiB2YWxpZFJlc3BvbnNlc1swXTtcblxuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNjcmlwdHNMb2FkZXIuZ2V0U2NyaXB0KFxuICAgICAgICAgICAgICAgIGBodHRwczovL3VucGtnLmNvbS8ke3BhY2tnZUluZm8ubmFtZX1gLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgb25Qcm9ncmVzczogKHByb2dyZXNzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LnByb2dyZXNzQmFyLnVwZGF0ZShwcm9ncmVzcyk7XG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIHByb2dyZXNzQmFyLnVwZGF0ZSgyMCwge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdpbmNyZW1lbnQnLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwcm9ncmVzc0Jhci5zZXRUZXh0KCdJbmplY3RpbmcgcGFja2FnZScpO1xuXG4gICAgICAgICAgICBjb25zdCBwa2c6IFBhY2thZ2UgPSB7XG4gICAgICAgICAgICAgICAgbmFtZTogcGFja2dlSW5mby5uYW1lLFxuICAgICAgICAgICAgICAgIHZlcnNpb246IHBhY2tnZUluZm8udmVyc2lvbiB8fCAnbGF0ZXN0JyxcbiAgICAgICAgICAgICAgICB1cmw6IHJlc3BvbnNlLnhoci5yZXNwb25zZVVSTCxcbiAgICAgICAgICAgICAgICBkZXBlbmRlbmNpZXM6IHBhY2tnZUluZm8uY2xpRGVwZW5kZW5jaWVzIHx8IFtdLFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcHJvZ3Jlc3NCYXIudXBkYXRlKDgwKTtcbiAgICAgICAgICAgIHByb2dyZXNzQmFyLnNldFRleHQoJ1JlZ2lzdGVyaW5nIGRlcGVuZGVuY2llcycpO1xuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlZ2lzdGVyUGFja2FnZURlcGVuZGVuY2llcyhwa2csIGNvbnRleHQpO1xuXG4gICAgICAgICAgICBwcm9ncmVzc0Jhci51cGRhdGUoOTApO1xuICAgICAgICAgICAgcHJvZ3Jlc3NCYXIuc2V0VGV4dCgnRGVwZW5kZW5jaWVzIHJlZ2lzdGVyZWQnKTtcblxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmNvbnRlbnQpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnNjcmlwdHNMb2FkZXIuaW5qZWN0Qm9keVNjcmlwdChyZXNwb25zZS5jb250ZW50KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcHJvZ3Jlc3NCYXIudXBkYXRlKDk1KTtcbiAgICAgICAgICAgIHByb2dyZXNzQmFyLnNldFRleHQoJ1NhdmluZyBwYWNrYWdlJyk7XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMucGFja2FnZXNNYW5hZ2VyLmFkZFBhY2thZ2UocGtnKTtcblxuICAgICAgICAgICAgY29udGV4dC5wcm9ncmVzc0Jhci5jb21wbGV0ZSgpO1xuXG4gICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZVN1Y2Nlc3MoXG4gICAgICAgICAgICAgICAgYFBhY2thZ2UgJHtwYWNrZ2VJbmZvLm5hbWV9QCR7cGFja2dlSW5mby52ZXJzaW9ufSBhZGRlZCBzdWNjZXNzZnVsbHlgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29udGV4dC5wcm9ncmVzc0Jhci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVFcnJvcihlPy50b1N0cmluZygpIHx8ICdVbmtub3duIGVycm9yJyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHVwZGF0ZVBhY2thZ2UoXG4gICAgICAgIG5hbWU6IHN0cmluZyxcbiAgICAgICAgY29udGV4dDogSUNsaUV4ZWN1dGlvbkNvbnRleHQsXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGNvbnN0IHsgcHJvZ3Jlc3NCYXIsIHdyaXRlciB9ID0gY29udGV4dDtcblxuICAgICAgICBwcm9ncmVzc0Jhci5zaG93KCk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHByb2dyZXNzQmFyLnVwZGF0ZSgxMCwge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdpbmNyZW1lbnQnLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwcm9ncmVzc0Jhci5zZXRUZXh0KGBVcGRhdGluZyBwYWNrYWdlICR7bmFtZX1gKTtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRQYWNrYWdlID0gYXdhaXQgdGhpcy5wYWNrYWdlc01hbmFnZXIuZ2V0UGFja2FnZShuYW1lKTtcblxuICAgICAgICAgICAgaWYgKCFjdXJyZW50UGFja2FnZSkge1xuICAgICAgICAgICAgICAgIHByb2dyZXNzQmFyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgd3JpdGVyLndyaXRlRXJyb3IoYFBhY2thZ2UgJHtuYW1lfSBub3QgZm91bmRgKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHBhY2thZ2VVcmwgPSBgaHR0cHM6Ly91bnBrZy5jb20vJHtjdXJyZW50UGFja2FnZS5uYW1lfWA7XG5cbiAgICAgICAgICAgIGNvbnN0IG5ld1BhY2thZ2UgPSBhd2FpdCB0aGlzLnNjcmlwdHNMb2FkZXJcbiAgICAgICAgICAgICAgICAuZ2V0U2NyaXB0KHBhY2thZ2VVcmwgKyAnL3BhY2thZ2UuanNvbicpXG4gICAgICAgICAgICAgICAgLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKHJlc3BvbnNlLmNvbnRlbnQgfHwgJ3t9Jyk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHByb2dyZXNzQmFyLnVwZGF0ZSgyMCwge1xuICAgICAgICAgICAgICAgIHR5cGU6ICdpbmNyZW1lbnQnLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHByb2dyZXNzQmFyLnNldFRleHQoXG4gICAgICAgICAgICAgICAgYENoZWNraW5nIGZvciB1cGRhdGVzIGZvciBwYWNrYWdlICR7Y3VycmVudFBhY2thZ2UubmFtZX1gLFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgaWYgKG5ld1BhY2thZ2UudmVyc2lvbiA9PT0gY3VycmVudFBhY2thZ2UudmVyc2lvbikge1xuICAgICAgICAgICAgICAgIGNvbnRleHQucHJvZ3Jlc3NCYXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUluZm8oXG4gICAgICAgICAgICAgICAgICAgIGBQYWNrYWdlICR7Y3VycmVudFBhY2thZ2UubmFtZX0gaXMgYWxyZWFkeSB1cCB0byBkYXRlIHdpdGggdmVyc2lvbiAke2N1cnJlbnRQYWNrYWdlLnZlcnNpb259YCxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNjcmlwdHNMb2FkZXIuZ2V0U2NyaXB0KHBhY2thZ2VVcmwsIHtcbiAgICAgICAgICAgICAgICBvblByb2dyZXNzOiAocHJvZ3Jlc3MpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC5wcm9ncmVzc0Jhci51cGRhdGUocHJvZ3Jlc3MpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcHJvZ3Jlc3NCYXIudXBkYXRlKDIwLCB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2luY3JlbWVudCcsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHByb2dyZXNzQmFyLnNldFRleHQoYFVwZGF0aW5nIHBhY2thZ2UgJHtjdXJyZW50UGFja2FnZS5uYW1lfWApO1xuXG4gICAgICAgICAgICBjb25zdCB1cGRhdGVkUGtnOiBQYWNrYWdlID0ge1xuICAgICAgICAgICAgICAgIG5hbWU6IG5ld1BhY2thZ2UubmFtZSxcbiAgICAgICAgICAgICAgICB2ZXJzaW9uOiBuZXdQYWNrYWdlLnZlcnNpb24gfHwgJ2xhdGVzdCcsXG4gICAgICAgICAgICAgICAgdXJsOiByZXNwb25zZS54aHIucmVzcG9uc2VVUkwsXG4gICAgICAgICAgICAgICAgZGVwZW5kZW5jaWVzOiBuZXdQYWNrYWdlLmNsaURlcGVuZGVuY2llcyB8fCBbXSxcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGF3YWl0IHRoaXMucmVnaXN0ZXJQYWNrYWdlRGVwZW5kZW5jaWVzKHVwZGF0ZWRQa2csIGNvbnRleHQpO1xuXG4gICAgICAgICAgICBwcm9ncmVzc0Jhci51cGRhdGUoOTApO1xuICAgICAgICAgICAgcHJvZ3Jlc3NCYXIuc2V0VGV4dChgSW5qZWN0aW5nIHBhY2thZ2UgJHtjdXJyZW50UGFja2FnZS5uYW1lfWApO1xuXG4gICAgICAgICAgICBpZiAocmVzcG9uc2UuY29udGVudCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2NyaXB0c0xvYWRlci5pbmplY3RCb2R5U2NyaXB0KHJlc3BvbnNlLmNvbnRlbnQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnBhY2thZ2VzTWFuYWdlci51cGRhdGVQYWNrYWdlKHVwZGF0ZWRQa2cpO1xuXG4gICAgICAgICAgICBwcm9ncmVzc0Jhci5zZXRUZXh0KFxuICAgICAgICAgICAgICAgIGBQYWNrYWdlICR7Y3VycmVudFBhY2thZ2UubmFtZX0gdXBkYXRlZCBzdWNjZXNzZnVsbHlgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHByb2dyZXNzQmFyLmNvbXBsZXRlKCk7XG5cbiAgICAgICAgICAgIHdyaXRlci53cml0ZVN1Y2Nlc3MoXG4gICAgICAgICAgICAgICAgYFBhY2thZ2UgJHtjdXJyZW50UGFja2FnZS5uYW1lfSB1cGRhdGVkIHN1Y2Nlc3NmdWxseSB0byB2ZXJzaW9uICR7bmV3UGFja2FnZS52ZXJzaW9ufSBmcm9tICR7Y3VycmVudFBhY2thZ2UudmVyc2lvbn1gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcHJvZ3Jlc3NCYXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgIHdyaXRlci53cml0ZUVycm9yKGU/LnRvU3RyaW5nKCkgfHwgJ1Vua25vd24gZXJyb3InKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgcmVnaXN0ZXJQYWNrYWdlRGVwZW5kZW5jaWVzKFxuICAgICAgICBwa2c6IFBhY2thZ2UsXG4gICAgICAgIHsgbG9nZ2VyIH06IElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAocGtnLmRlcGVuZGVuY2llcyAmJiBwa2cuZGVwZW5kZW5jaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGxvZ2dlci5pbmZvKGBJbmplY3RpbmcgcGFja2FnZSAke3BrZy5uYW1lfSBkZXBlbmRlbmNpZXNgKTtcblxuICAgICAgICAgICAgZm9yIChjb25zdCBkZXBlbmRlbmN5IG9mIHBrZy5kZXBlbmRlbmNpZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZWdpc3RlcmVkRGVwZW5kZW5jaWVzLmluY2x1ZGVzKGRlcGVuZGVuY3kubmFtZSEpKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgYERlcGVuZGVuY3kgJHtkZXBlbmRlbmN5Lmdsb2JhbE5hbWV9IGFscmVhZHkgcmVnaXN0ZXJlZGAsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMuc2NyaXB0c0xvYWRlci5pbmplY3RTY3JpcHQoZGVwZW5kZW5jeS51cmwpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRlcGVuZGVuY3kuZ2xvYmFsTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpc0F2YWlsYWJsZSA9IGF3YWl0IHRoaXMud2FpdEZvckdsb2JhbChcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlcGVuZGVuY3kuZ2xvYmFsTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDMwMDAsXG4gICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0F2YWlsYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBEZXBlbmRlbmN5ICR7ZGVwZW5kZW5jeS5nbG9iYWxOYW1lfSBub3QgZm91bmQgaW4gZ2xvYmFsIHNjb3BlIHdpdGhpbiB0aW1lb3V0YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZ2dlci5pbmZvKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBEZXBlbmRlbmN5ICR7ZGVwZW5kZW5jeS5nbG9iYWxOYW1lfSBpcyBhdmFpbGFibGUgaW4gZ2xvYmFsIHNjb3BlYCxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnJlZ2lzdGVyZWREZXBlbmRlbmNpZXMucHVzaChkZXBlbmRlbmN5Lm5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbG9nZ2VyLmluZm8oYFBhY2thZ2UgJHtwa2cubmFtZX0gaGFzIG5vIGRlcGVuZGVuY2llc2ApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2FpdHMgdW50aWwgYSBnbG9iYWwgdmFyaWFibGUgaXMgYXZhaWxhYmxlIG9uIHRoZSBgd2luZG93YCBvYmplY3QuXG4gICAgICogQHBhcmFtIGdsb2JhbE5hbWUge3N0cmluZ30gVGhlIG5hbWUgb2YgdGhlIGdsb2JhbCB2YXJpYWJsZSB0byBjaGVjay5cbiAgICAgKiBAcGFyYW0gdGltZW91dCB7bnVtYmVyfSBUaGUgbWF4aW11bSB0aW1lIHRvIHdhaXQgaW4gbWlsbGlzZWNvbmRzLlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fSBSZXNvbHZlcyB0byBgdHJ1ZWAgaWYgdGhlIHZhcmlhYmxlIGlzIGZvdW5kLCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHdhaXRGb3JHbG9iYWwoXG4gICAgICAgIGdsb2JhbE5hbWU6IHN0cmluZyxcbiAgICAgICAgdGltZW91dDogbnVtYmVyLFxuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGludGVydmFsID0gNTA7IC8vIENoZWNrIGV2ZXJ5IDUwbXNcbiAgICAgICAgICAgIGxldCBlbGFwc2VkID0gMDtcblxuICAgICAgICAgICAgY29uc3QgY2hlY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCh3aW5kb3cgYXMgYW55KVtnbG9iYWxOYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZWxhcHNlZCA+PSB0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVsYXBzZWQgKz0gaW50ZXJ2YWw7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoY2hlY2ssIGludGVydmFsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjaGVjaygpO1xuICAgICAgICB9KTtcbiAgICB9XG59XG4iXX0=