UNPKG

@qodalis/angular-cli

Version:

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

255 lines 39.2 kB
import { Inject, Injectable } from '@angular/core'; import { getRightOfWord, getParameterValue, CancellablePromise, CliForegroundColor, } from '@qodalis/cli-core'; import { CommandParser } from '../../utils'; import { CliArgsParser } from '../../utils/args-parser'; import { ProcessExitedError } from '../context/errors'; import { CliCommandExecutionContext } from '../context/cli-command-executution-context'; import { CliProcessorsRegistry_TOKEN } from '../tokens'; import * as i0 from "@angular/core"; export class CliCommandExecutorService { constructor(registry) { this.registry = registry; this.commandParser = new CommandParser(); } async executeCommand(command, context) { // Split commands by logical operators const parts = command.split(/(&&|\|\|)/).map((part) => part.trim()); let shouldRunNextCommand = true; // Tracks whether to execute the next command let rootContext; if (context instanceof CliCommandExecutionContext) { rootContext = context.context; } else { rootContext = context; } for (let i = 0; i < parts.length; i++) { const current = parts[i]; // If the current part is a logical operator, adjust the shouldRunNextCommand flag if (current === '&&') { shouldRunNextCommand = shouldRunNextCommand && true; continue; } else if (current === '||') { shouldRunNextCommand = !shouldRunNextCommand; continue; } // Skip execution based on previous command's result and operator if (!shouldRunNextCommand) { shouldRunNextCommand = true; // Reset for next iteration continue; } // Execute the command let commandSuccess = true; try { const data = context.process.data; const command = current; await this.executeSingleCommand(command, data, rootContext); commandSuccess = context.process.exitCode === 0; } catch (e) { commandSuccess = false; context.writer.writeError(`Command ${current} failed: ${e}`); } shouldRunNextCommand = commandSuccess; } } async executeSingleCommand(command, data, context) { const process = context.process; process.start(); const { commandName, args: parsedArgs } = this.commandParser.parse(command); const [mainCommand, ...other] = commandName.split(' '); const chainCommands = other.map((c) => c.toLowerCase()); const searchableProcessors = context.contextProcessor ? (context.contextProcessor.processors ?? []) : this.registry.processors; const processor = this.registry.findProcessorInCollection(mainCommand, chainCommands, searchableProcessors); if (!processor) { const aliases = this.registry.findProcessor('alias', []).aliases ?? {}; if (aliases[mainCommand]) { const alias = aliases[mainCommand]; return await this.executeSingleCommand(alias, data, context); } context.writer.writeError(`Command: ${commandName} not found or not installed`); context.writer.writeln(); context.writer.writeInfo('Type "help" for a list of available commands.'); context.writer.writeInfo('Use packages to install additional commands.'); context.process.exit(-1, { silent: true, }); return; } const args = CliArgsParser.convertToRecord(parsedArgs, processor); const commandToProcess = { command: commandName, chainCommands: chainCommands, rawCommand: command, args: args, data: data, }; if (this.versionRequested(context, processor, args)) { process.end(); return; } if (await this.helpRequested(commandToProcess, context)) { process.end(); return; } if (this.setContextProcessorRequested(context, processor, args)) { process.end(); return; } if (!this.validateBeforeExecution(context, processor, args)) { process.end(); return; } const value = processor.allowUnlistedCommands || processor.valueRequired ? getRightOfWord(commandName, processor.command) : undefined; commandToProcess.value = value; const missingValue = processor.valueRequired && !value; if (missingValue) { context.writer.writeError(`Value required for command: ${commandName} <value>`); context.process.exit(-1); return; } if (processor.validateBeforeExecution) { const validationResult = processor.validateBeforeExecution(commandToProcess, context); if (validationResult.valid === false) { context.writer.writeError(validationResult?.message || 'An error occurred while validating the command.'); context.process.exit(-1); return; } } let cancellable = null; const commandContext = new CliCommandExecutionContext(context, processor); try { const hooks = processor.hooks ?? []; for (const hook of hooks.filter((h) => h.when === 'before')) { await hook.execute(commandContext); } cancellable = new CancellablePromise(async (resolve, reject) => { processor .processCommand(commandToProcess, commandContext) .then(() => { resolve(); }) .catch((e) => { reject(e); }); }); await cancellable.execute(); for (const hook of hooks.filter((h) => h.when === 'after')) { await hook.execute(commandContext); } process.end(); } catch (e) { context.spinner?.hide(); if (e instanceof ProcessExitedError) { cancellable?.cancel(); context?.abort(); if (e.code !== 0) { context.writer.writeError(`Process exited with code ${e.code}`); } else { context.writer.writeInfo('Process exited successfully with code 0'); } } else { context.writer.writeError(`Error executing command: ${e}`); context.process.exit(-1); } } } async showHelp(command, context) { try { await this.executeCommand('help ' + command.rawCommand, context); } catch (e) { context.writer.writeError(`Error executing command: ${e}`); } } versionRequested(context, processor, args) { if (args['v'] || args['version']) { context.writer.writeln(`${context.writer.wrapInColor(processor.version || '1.0.0', CliForegroundColor.Cyan)}`); return true; } return false; } setContextProcessorRequested(context, processor, args) { if (args['context']) { context.setContextProcessor(processor); return true; } return false; } async helpRequested(commandToProcess, context) { if (commandToProcess.command?.startsWith('help')) { return false; } if (commandToProcess.args['h'] || commandToProcess.args['help']) { await this.showHelp(commandToProcess, context); return true; } return false; } /** * Validates the command arguments before execution. * @param context The current CLI execution context. * @param processor The processor to validate. * @param args The command arguments. * @returns True if the arguments are valid, false otherwise. */ validateBeforeExecution(context, processor, args) { // Check for required parameters if (processor.parameters?.some((p) => p.required)) { const missingParams = processor.parameters?.filter((p) => p.required && !args[p.name] && !p.aliases?.some((a) => args[a])); if (missingParams?.length) { context.writer.writeError(`Missing required parameters: ${missingParams .map((p) => p.name) .join(', ')}`); return false; } } // Check for parameter validation const parametersToValidate = processor.parameters ?.filter((x) => x.validator) ?.map((p) => ({ parameter: p, value: getParameterValue(p, args), })) ?.filter((p) => p.value) ?? []; if (parametersToValidate.length > 0) { const invalidParams = parametersToValidate .filter((x) => !x.parameter.validator(x.value).valid) .map((p) => ({ name: p.parameter.name, message: p.parameter.validator(args[p.parameter.name]) .message, })); if (invalidParams?.length) { context.writer.writeError('Invalid parameters:'); invalidParams.forEach((p, index) => { context.writer.writeln(`${index + 1}. Invalid value for ${p.name}: ${args[p.name]} -> ${p.message}`); }); return false; } } return true; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliCommandExecutorService, deps: [{ token: CliProcessorsRegistry_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliCommandExecutorService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliCommandExecutorService, decorators: [{ type: Injectable, args: [{ providedIn: 'root', }] }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Inject, args: [CliProcessorsRegistry_TOKEN] }] }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLWNvbW1hbmQtZXhlY3V0b3Iuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NsaS9zcmMvbGliL2NsaS9zZXJ2aWNlcy9jbGktY29tbWFuZC1leGVjdXRvci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25ELE9BQU8sRUFJSCxjQUFjLEVBQ2QsaUJBQWlCLEVBRWpCLGtCQUFrQixFQUNsQixrQkFBa0IsR0FFckIsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRzVDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQUV4RixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxXQUFXLENBQUM7O0FBS3hELE1BQU0sT0FBTyx5QkFBeUI7SUFHbEMsWUFFcUIsUUFBc0M7UUFBdEMsYUFBUSxHQUFSLFFBQVEsQ0FBOEI7UUFKbkQsa0JBQWEsR0FBa0IsSUFBSSxhQUFhLEVBQUUsQ0FBQztJQUt4RCxDQUFDO0lBRUcsS0FBSyxDQUFDLGNBQWMsQ0FDdkIsT0FBZSxFQUNmLE9BQTZCO1FBRTdCLHNDQUFzQztRQUN0QyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDcEUsSUFBSSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsQ0FBQyw2Q0FBNkM7UUFFOUUsSUFBSSxXQUFnQyxDQUFD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LENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUM7cUJBQ2xELE9BQU87YUFDZixDQUFDLENBQUMsQ0FBQztZQUVSLElBQUksYUFBYSxFQUFFLE1BQU0sRUFBRTtnQkFDdkIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMscUJBQXFCLENBQUMsQ0FBQztnQkFFakQsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRTtvQkFDL0IsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQ2xCLEdBQUcsS0FBSyxHQUFHLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FDdEQsQ0FBQyxDQUFDLE9BQ04sRUFBRSxDQUNMLENBQUM7Z0JBQ04sQ0FBQyxDQUFDLENBQUM7Z0JBRUgsT0FBTyxLQUFLLENBQUM7YUFDaEI7U0FDSjtRQUVELE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7K0dBaFhRLHlCQUF5QixrQkFJdEIsMkJBQTJCO21IQUo5Qix5QkFBeUIsY0FGdEIsTUFBTTs7NEZBRVQseUJBQXlCO2tCQUhyQyxVQUFVO21CQUFDO29CQUNSLFVBQVUsRUFBRSxNQUFNO2lCQUNyQjs7MEJBS1EsTUFBTTsyQkFBQywyQkFBMkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gICAgSUNsaUV4ZWN1dGlvbkNvbnRleHQsXG4gICAgSUNsaUNvbW1hbmRQcm9jZXNzb3IsXG4gICAgQ2xpUHJvY2Vzc0NvbW1hbmQsXG4gICAgZ2V0UmlnaHRPZldvcmQsXG4gICAgZ2V0UGFyYW1ldGVyVmFsdWUsXG4gICAgSUNsaUNvbW1hbmRFeGVjdXRvclNlcnZpY2UsXG4gICAgQ2FuY2VsbGFibGVQcm9taXNlLFxuICAgIENsaUZvcmVncm91bmRDb2xvcixcbiAgICBJQ2xpQ29tbWFuZFByb2Nlc3NvclJlZ2lzdHJ5LFxufSBmcm9tICdAcW9kYWxpcy9jbGktY29yZSc7XG5pbXBvcnQgeyBDb21tYW5kUGFyc2VyIH0gZnJvbSAnLi4vLi4vdXRpbHMnO1xuaW1wb3J0IHsgQ2xpRXhlY3V0aW9uUHJvY2VzcyB9IGZyb20gJy4uL2NvbnRleHQvY2xpLWV4ZWN1dGlvbi1wcm9jZXNzJztcbmltcG9ydCB7IENsaUV4ZWN1dGlvbkNvbnRleHQgfSBmcm9tICcuLi9jb250ZXh0L2NsaS1leGVjdXRpb24tY29udGV4dCc7XG5pbXBvcnQgeyBDbGlBcmdzUGFyc2VyIH0gZnJvbSAnLi4vLi4vdXRpbHMvYXJncy1wYXJzZXInO1xuaW1wb3J0IHsgUHJvY2Vzc0V4aXRlZEVycm9yIH0gZnJvbSAnLi4vY29udGV4dC9lcnJvcnMnO1xuaW1wb3J0IHsgQ2xpQ29tbWFuZEV4ZWN1dGlvbkNvbnRleHQgfSBmcm9tICcuLi9jb250ZXh0L2NsaS1jb21tYW5kLWV4ZWN1dHV0aW9uLWNvbnRleHQnO1xuaW1wb3J0IHsgQ2xpQWxpYXNDb21tYW5kUHJvY2Vzc29yIH0gZnJvbSAnLi4vcHJvY2Vzc29ycyc7XG5pbXBvcnQgeyBDbGlQcm9jZXNzb3JzUmVnaXN0cnlfVE9LRU4gfSBmcm9tICcuLi90b2tlbnMnO1xuXG5ASW5qZWN0YWJsZSh7XG4gICAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxufSlcbmV4cG9ydCBjbGFzcyBDbGlDb21tYW5kRXhlY3V0b3JTZXJ2aWNlIGltcGxlbWVudHMgSUNsaUNvbW1hbmRFeGVjdXRvclNlcnZpY2Uge1xuICAgIHByaXZhdGUgY29tbWFuZFBhcnNlcjogQ29tbWFuZFBhcnNlciA9IG5ldyBDb21tYW5kUGFyc2VyKCk7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgQEluamVjdChDbGlQcm9jZXNzb3JzUmVnaXN0cnlfVE9LRU4pXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgcmVnaXN0cnk6IElDbGlDb21tYW5kUHJvY2Vzc29yUmVnaXN0cnksXG4gICAgKSB7fVxuXG4gICAgcHVibGljIGFzeW5jIGV4ZWN1dGVDb21tYW5kKFxuICAgICAgICBjb21tYW5kOiBzdHJpbmcsXG4gICAgICAgIGNvbnRleHQ6IElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICAvLyBTcGxpdCBjb21tYW5kcyBieSBsb2dpY2FsIG9wZXJhdG9yc1xuICAgICAgICBjb25zdCBwYXJ0cyA9IGNvbW1hbmQuc3BsaXQoLygmJnxcXHxcXHwpLykubWFwKChwYXJ0KSA9PiBwYXJ0LnRyaW0oKSk7XG4gICAgICAgIGxldCBzaG91bGRSdW5OZXh0Q29tbWFuZCA9IHRydWU7IC8vIFRyYWNrcyB3aGV0aGVyIHRvIGV4ZWN1dGUgdGhlIG5leHQgY29tbWFuZFxuXG4gICAgICAgIGxldCByb290Q29udGV4dDogQ2xpRXhlY3V0aW9uQ29udGV4dDtcbiAgICAgICAgaWYgKGNvbnRleHQgaW5zdGFuY2VvZiBDbGlDb21tYW5kRXhlY3V0aW9uQ29udGV4dCkge1xuICAgICAgICAgICAgcm9vdENvbnRleHQgPSBjb250ZXh0LmNvbnRleHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByb290Q29udGV4dCA9IGNvbnRleHQgYXMgQ2xpRXhlY3V0aW9uQ29udGV4dDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnQgPSBwYXJ0c1tpXTtcblxuICAgICAgICAgICAgLy8gSWYgdGhlIGN1cnJlbnQgcGFydCBpcyBhIGxvZ2ljYWwgb3BlcmF0b3IsIGFkanVzdCB0aGUgc2hvdWxkUnVuTmV4dENvbW1hbmQgZmxhZ1xuICAgICAgICAgICAgaWYgKGN1cnJlbnQgPT09ICcmJicpIHtcbiAgICAgICAgICAgICAgICBzaG91bGRSdW5OZXh0Q29tbWFuZCA9IHNob3VsZFJ1bk5leHRDb21tYW5kICYmIHRydWU7XG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnQgPT09ICd8fCcpIHtcbiAgICAgICAgICAgICAgICBzaG91bGRSdW5OZXh0Q29tbWFuZCA9ICFzaG91bGRSdW5OZXh0Q29tbWFuZDtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2tpcCBleGVjdXRpb24gYmFzZWQgb24gcHJldmlvdXMgY29tbWFuZCdzIHJlc3VsdCBhbmQgb3BlcmF0b3JcbiAgICAgICAgICAgIGlmICghc2hvdWxkUnVuTmV4dENvbW1hbmQpIHtcbiAgICAgICAgICAgICAgICBzaG91bGRSdW5OZXh0Q29tbWFuZCA9IHRydWU7IC8vIFJlc2V0IGZvciBuZXh0IGl0ZXJhdGlvblxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIHRoZSBjb21tYW5kXG4gICAgICAgICAgICBsZXQgY29tbWFuZFN1Y2Nlc3MgPSB0cnVlO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gY29udGV4dC5wcm9jZXNzLmRhdGE7XG4gICAgICAgICAgICAgICAgY29uc3QgY29tbWFuZCA9IGN1cnJlbnQ7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmV4ZWN1dGVTaW5nbGVDb21tYW5kKGNvbW1hbmQsIGRhdGEsIHJvb3RDb250ZXh0KTtcblxuICAgICAgICAgICAgICAgIGNvbW1hbmRTdWNjZXNzID0gY29udGV4dC5wcm9jZXNzLmV4aXRDb2RlID09PSAwO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGNvbW1hbmRTdWNjZXNzID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUVycm9yKGBDb21tYW5kICR7Y3VycmVudH0gZmFpbGVkOiAke2V9YCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHNob3VsZFJ1bk5leHRDb21tYW5kID0gY29tbWFuZFN1Y2Nlc3M7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIGV4ZWN1dGVTaW5nbGVDb21tYW5kKFxuICAgICAgICBjb21tYW5kOiBzdHJpbmcsXG4gICAgICAgIGRhdGE6IGFueSB8IHVuZGVmaW5lZCxcbiAgICAgICAgY29udGV4dDogQ2xpRXhlY3V0aW9uQ29udGV4dCxcbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgY29uc3QgcHJvY2VzcyA9IGNvbnRleHQucHJvY2VzcyBhcyBDbGlFeGVjdXRpb25Qcm9jZXNzO1xuXG4gICAgICAgIHByb2Nlc3Muc3RhcnQoKTtcblxuICAgICAgICBjb25zdCB7IGNvbW1hbmROYW1lLCBhcmdzOiBwYXJzZWRBcmdzIH0gPVxuICAgICAgICAgICAgdGhpcy5jb21tYW5kUGFyc2VyLnBhcnNlKGNvbW1hbmQpO1xuXG4gICAgICAgIGNvbnN0IFttYWluQ29tbWFuZCwgLi4ub3RoZXJdID0gY29tbWFuZE5hbWUuc3BsaXQoJyAnKTtcblxuICAgICAgICBjb25zdCBjaGFpbkNvbW1hbmRzID0gb3RoZXIubWFwKChjKSA9PiBjLnRvTG93ZXJDYXNlKCkpO1xuXG4gICAgICAgIGNvbnN0IHNlYXJjaGFibGVQcm9jZXNzb3JzID0gY29udGV4dC5jb250ZXh0UHJvY2Vzc29yXG4gICAgICAgICAgICA/IChjb250ZXh0LmNvbnRleHRQcm9jZXNzb3IucHJvY2Vzc29ycyA/PyBbXSlcbiAgICAgICAgICAgIDogdGhpcy5yZWdpc3RyeS5wcm9jZXNzb3JzO1xuXG4gICAgICAgIGNvbnN0IHByb2Nlc3NvciA9IHRoaXMucmVnaXN0cnkuZmluZFByb2Nlc3NvckluQ29sbGVjdGlvbihcbiAgICAgICAgICAgIG1haW5Db21tYW5kLFxuICAgICAgICAgICAgY2hhaW5Db21tYW5kcyxcbiAgICAgICAgICAgIHNlYXJjaGFibGVQcm9jZXNzb3JzLFxuICAgICAgICApO1xuXG4gICAgICAgIGlmICghcHJvY2Vzc29yKSB7XG4gICAgICAgICAgICBjb25zdCBhbGlhc2VzID1cbiAgICAgICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVnaXN0cnkuZmluZFByb2Nlc3NvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICdhbGlhcycsXG4gICAgICAgICAgICAgICAgICAgICAgICBbXSxcbiAgICAgICAgICAgICAgICAgICAgKSBhcyBDbGlBbGlhc0NvbW1hbmRQcm9jZXNzb3JcbiAgICAgICAgICAgICAgICApLmFsaWFzZXMgPz8ge307XG5cbiAgICAgICAgICAgIGlmIChhbGlhc2VzW21haW5Db21tYW5kXSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFsaWFzID0gYWxpYXNlc1ttYWluQ29tbWFuZF07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZXhlY3V0ZVNpbmdsZUNvbW1hbmQoYWxpYXMsIGRhdGEsIGNvbnRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUVycm9yKFxuICAgICAgICAgICAgICAgIGBDb21tYW5kOiAke2NvbW1hbmROYW1lfSBub3QgZm91bmQgb3Igbm90IGluc3RhbGxlZGAsXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZWxuKCk7XG5cbiAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlSW5mbyhcbiAgICAgICAgICAgICAgICAnVHlwZSBcImhlbHBcIiBmb3IgYSBsaXN0IG9mIGF2YWlsYWJsZSBjb21tYW5kcy4nLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlSW5mbyhcbiAgICAgICAgICAgICAgICAnVXNlIHBhY2thZ2VzIHRvIGluc3RhbGwgYWRkaXRpb25hbCBjb21tYW5kcy4nLFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgY29udGV4dC5wcm9jZXNzLmV4aXQoLTEsIHtcbiAgICAgICAgICAgICAgICBzaWxlbnQ6IHRydWUsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYXJncyA9IENsaUFyZ3NQYXJzZXIuY29udmVydFRvUmVjb3JkKHBhcnNlZEFyZ3MsIHByb2Nlc3Nvcik7XG5cbiAgICAgICAgY29uc3QgY29tbWFuZFRvUHJvY2VzczogQ2xpUHJvY2Vzc0NvbW1hbmQgPSB7XG4gICAgICAgICAgICBjb21tYW5kOiBjb21tYW5kTmFtZSxcbiAgICAgICAgICAgIGNoYWluQ29tbWFuZHM6IGNoYWluQ29tbWFuZHMsXG4gICAgICAgICAgICByYXdDb21tYW5kOiBjb21tYW5kLFxuICAgICAgICAgICAgYXJnczogYXJncyxcbiAgICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHRoaXMudmVyc2lvblJlcXVlc3RlZChjb250ZXh0LCBwcm9jZXNzb3IsIGFyZ3MpKSB7XG4gICAgICAgICAgICBwcm9jZXNzLmVuZCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGF3YWl0IHRoaXMuaGVscFJlcXVlc3RlZChjb21tYW5kVG9Qcm9jZXNzLCBjb250ZXh0KSkge1xuICAgICAgICAgICAgcHJvY2Vzcy5lbmQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNldENvbnRleHRQcm9jZXNzb3JSZXF1ZXN0ZWQoY29udGV4dCwgcHJvY2Vzc29yLCBhcmdzKSkge1xuICAgICAgICAgICAgcHJvY2Vzcy5lbmQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy52YWxpZGF0ZUJlZm9yZUV4ZWN1dGlvbihjb250ZXh0LCBwcm9jZXNzb3IsIGFyZ3MpKSB7XG4gICAgICAgICAgICBwcm9jZXNzLmVuZCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdmFsdWUgPVxuICAgICAgICAgICAgcHJvY2Vzc29yLmFsbG93VW5saXN0ZWRDb21tYW5kcyB8fCBwcm9jZXNzb3IudmFsdWVSZXF1aXJlZFxuICAgICAgICAgICAgICAgID8gZ2V0UmlnaHRPZldvcmQoY29tbWFuZE5hbWUsIHByb2Nlc3Nvci5jb21tYW5kKVxuICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgICAgIGNvbW1hbmRUb1Byb2Nlc3MudmFsdWUgPSB2YWx1ZTtcblxuICAgICAgICBjb25zdCBtaXNzaW5nVmFsdWUgPSBwcm9jZXNzb3IudmFsdWVSZXF1aXJlZCAmJiAhdmFsdWU7XG5cbiAgICAgICAgaWYgKG1pc3NpbmdWYWx1ZSkge1xuICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVFcnJvcihcbiAgICAgICAgICAgICAgICBgVmFsdWUgcmVxdWlyZWQgZm9yIGNvbW1hbmQ6ICR7Y29tbWFuZE5hbWV9IDx2YWx1ZT5gLFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgY29udGV4dC5wcm9jZXNzLmV4aXQoLTEpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocHJvY2Vzc29yLnZhbGlkYXRlQmVmb3JlRXhlY3V0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCB2YWxpZGF0aW9uUmVzdWx0ID0gcHJvY2Vzc29yLnZhbGlkYXRlQmVmb3JlRXhlY3V0aW9uKFxuICAgICAgICAgICAgICAgIGNvbW1hbmRUb1Byb2Nlc3MsXG4gICAgICAgICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGlmICh2YWxpZGF0aW9uUmVzdWx0LnZhbGlkID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb25SZXN1bHQ/Lm1lc3NhZ2UgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICdBbiBlcnJvciBvY2N1cnJlZCB3aGlsZSB2YWxpZGF0aW5nIHRoZSBjb21tYW5kLicsXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIGNvbnRleHQucHJvY2Vzcy5leGl0KC0xKTtcblxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjYW5jZWxsYWJsZTogQ2FuY2VsbGFibGVQcm9taXNlPHZvaWQ+ID0gbnVsbCE7XG5cbiAgICAgICAgY29uc3QgY29tbWFuZENvbnRleHQgPSBuZXcgQ2xpQ29tbWFuZEV4ZWN1dGlvbkNvbnRleHQoXG4gICAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgICAgcHJvY2Vzc29yLFxuICAgICAgICApO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCBob29rcyA9IHByb2Nlc3Nvci5ob29rcyA/PyBbXTtcblxuICAgICAgICAgICAgZm9yIChjb25zdCBob29rIG9mIGhvb2tzLmZpbHRlcigoaCkgPT4gaC53aGVuID09PSAnYmVmb3JlJykpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBob29rLmV4ZWN1dGUoY29tbWFuZENvbnRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjYW5jZWxsYWJsZSA9IG5ldyBDYW5jZWxsYWJsZVByb21pc2U8dm9pZD4oXG4gICAgICAgICAgICAgICAgYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzb3JcbiAgICAgICAgICAgICAgICAgICAgICAgIC5wcm9jZXNzQ29tbWFuZChjb21tYW5kVG9Qcm9jZXNzLCBjb21tYW5kQ29udGV4dClcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGF3YWl0IGNhbmNlbGxhYmxlLmV4ZWN1dGUoKTtcblxuICAgICAgICAgICAgZm9yIChjb25zdCBob29rIG9mIGhvb2tzLmZpbHRlcigoaCkgPT4gaC53aGVuID09PSAnYWZ0ZXInKSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IGhvb2suZXhlY3V0ZShjb21tYW5kQ29udGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHByb2Nlc3MuZW5kKCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnRleHQuc3Bpbm5lcj8uaGlkZSgpO1xuXG4gICAgICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIFByb2Nlc3NFeGl0ZWRFcnJvcikge1xuICAgICAgICAgICAgICAgIGNhbmNlbGxhYmxlPy5jYW5jZWwoKTtcblxuICAgICAgICAgICAgICAgIChjb250ZXh0IGFzIENsaUV4ZWN1dGlvbkNvbnRleHQpPy5hYm9ydCgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGUuY29kZSAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgYFByb2Nlc3MgZXhpdGVkIHdpdGggY29kZSAke2UuY29kZX1gLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlSW5mbyhcbiAgICAgICAgICAgICAgICAgICAgICAgICdQcm9jZXNzIGV4aXRlZCBzdWNjZXNzZnVsbHkgd2l0aCBjb2RlIDAnLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVFcnJvcihgRXJyb3IgZXhlY3V0aW5nIGNvbW1hbmQ6ICR7ZX1gKTtcbiAgICAgICAgICAgICAgICBjb250ZXh0LnByb2Nlc3MuZXhpdCgtMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2hvd0hlbHAoXG4gICAgICAgIGNvbW1hbmQ6IENsaVByb2Nlc3NDb21tYW5kLFxuICAgICAgICBjb250ZXh0OiBJQ2xpRXhlY3V0aW9uQ29udGV4dCxcbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuZXhlY3V0ZUNvbW1hbmQoJ2hlbHAgJyArIGNvbW1hbmQucmF3Q29tbWFuZCwgY29udGV4dCk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlRXJyb3IoYEVycm9yIGV4ZWN1dGluZyBjb21tYW5kOiAke2V9YCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHZlcnNpb25SZXF1ZXN0ZWQoXG4gICAgICAgIGNvbnRleHQ6IElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgICAgICBwcm9jZXNzb3I6IElDbGlDb21tYW5kUHJvY2Vzc29yLFxuICAgICAgICBhcmdzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgICk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoYXJnc1sndiddIHx8IGFyZ3NbJ3ZlcnNpb24nXSkge1xuICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVsbihcbiAgICAgICAgICAgICAgICBgJHtjb250ZXh0LndyaXRlci53cmFwSW5Db2xvcihwcm9jZXNzb3IudmVyc2lvbiB8fCAnMS4wLjAnLCBDbGlGb3JlZ3JvdW5kQ29sb3IuQ3lhbil9YCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldENvbnRleHRQcm9jZXNzb3JSZXF1ZXN0ZWQoXG4gICAgICAgIGNvbnRleHQ6IElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgICAgICBwcm9jZXNzb3I6IElDbGlDb21tYW5kUHJvY2Vzc29yLFxuICAgICAgICBhcmdzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgICk6IGJvb2xlYW4ge1xuICAgICAgICBpZiAoYXJnc1snY29udGV4dCddKSB7XG4gICAgICAgICAgICBjb250ZXh0LnNldENvbnRleHRQcm9jZXNzb3IocHJvY2Vzc29yKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgaGVscFJlcXVlc3RlZChcbiAgICAgICAgY29tbWFuZFRvUHJvY2VzczogQ2xpUHJvY2Vzc0NvbW1hbmQsXG4gICAgICAgIGNvbnRleHQ6IElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgICk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICBpZiAoY29tbWFuZFRvUHJvY2Vzcy5jb21tYW5kPy5zdGFydHNXaXRoKCdoZWxwJykpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb21tYW5kVG9Qcm9jZXNzLmFyZ3NbJ2gnXSB8fCBjb21tYW5kVG9Qcm9jZXNzLmFyZ3NbJ2hlbHAnXSkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5zaG93SGVscChjb21tYW5kVG9Qcm9jZXNzLCBjb250ZXh0KTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVmFsaWRhdGVzIHRoZSBjb21tYW5kIGFyZ3VtZW50cyBiZWZvcmUgZXhlY3V0aW9uLlxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjdXJyZW50IENMSSBleGVjdXRpb24gY29udGV4dC5cbiAgICAgKiBAcGFyYW0gcHJvY2Vzc29yIFRoZSBwcm9jZXNzb3IgdG8gdmFsaWRhdGUuXG4gICAgICogQHBhcmFtIGFyZ3MgVGhlIGNvbW1hbmQgYXJndW1lbnRzLlxuICAgICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGFyZ3VtZW50cyBhcmUgdmFsaWQsIGZhbHNlIG90aGVyd2lzZS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHZhbGlkYXRlQmVmb3JlRXhlY3V0aW9uKFxuICAgICAgICBjb250ZXh0OiBJQ2xpRXhlY3V0aW9uQ29udGV4dCxcbiAgICAgICAgcHJvY2Vzc29yOiBJQ2xpQ29tbWFuZFByb2Nlc3NvcixcbiAgICAgICAgYXJnczogUmVjb3JkPHN0cmluZywgYW55PixcbiAgICApOiBib29sZWFuIHtcbiAgICAgICAgLy8gQ2hlY2sgZm9yIHJlcXVpcmVkIHBhcmFtZXRlcnNcbiAgICAgICAgaWYgKHByb2Nlc3Nvci5wYXJhbWV0ZXJzPy5zb21lKChwKSA9PiBwLnJlcXVpcmVkKSkge1xuICAgICAgICAgICAgY29uc3QgbWlzc2luZ1BhcmFtcyA9IHByb2Nlc3Nvci5wYXJhbWV0ZXJzPy5maWx0ZXIoXG4gICAgICAgICAgICAgICAgKHApID0+XG4gICAgICAgICAgICAgICAgICAgIHAucmVxdWlyZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgIWFyZ3NbcC5uYW1lXSAmJlxuICAgICAgICAgICAgICAgICAgICAhcC5hbGlhc2VzPy5zb21lKChhKSA9PiBhcmdzW2FdKSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGlmIChtaXNzaW5nUGFyYW1zPy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUVycm9yKFxuICAgICAgICAgICAgICAgICAgICBgTWlzc2luZyByZXF1aXJlZCBwYXJhbWV0ZXJzOiAke21pc3NpbmdQYXJhbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoKHApID0+IHAubmFtZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5qb2luKCcsICcpfWAsXG4gICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGZvciBwYXJhbWV0ZXIgdmFsaWRhdGlvblxuICAgICAgICBjb25zdCBwYXJhbWV0ZXJzVG9WYWxpZGF0ZSA9XG4gICAgICAgICAgICBwcm9jZXNzb3IucGFyYW1ldGVyc1xuICAgICAgICAgICAgICAgID8uZmlsdGVyKCh4KSA9PiB4LnZhbGlkYXRvcilcbiAgICAgICAgICAgICAgICA/Lm1hcCgocCkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1ldGVyOiBwLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZ2V0UGFyYW1ldGVyVmFsdWUocCwgYXJncyksXG4gICAgICAgICAgICAgICAgfSkpXG4gICAgICAgICAgICAgICAgPy5maWx0ZXIoKHApID0+IHAudmFsdWUpID8/IFtdO1xuXG4gICAgICAgIGlmIChwYXJhbWV0ZXJzVG9WYWxpZGF0ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBpbnZhbGlkUGFyYW1zID0gcGFyYW1ldGVyc1RvVmFsaWRhdGVcbiAgICAgICAgICAgICAgICAuZmlsdGVyKCh4KSA9PiAheC5wYXJhbWV0ZXIudmFsaWRhdG9yISh4LnZhbHVlKS52YWxpZClcbiAgICAgICAgICAgICAgICAubWFwKChwKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiBwLnBhcmFtZXRlci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBwLnBhcmFtZXRlci52YWxpZGF0b3IhKGFyZ3NbcC5wYXJhbWV0ZXIubmFtZV0pXG4gICAgICAgICAgICAgICAgICAgICAgICAubWVzc2FnZSxcbiAgICAgICAgICAgICAgICB9KSk7XG5cbiAgICAgICAgICAgIGlmIChpbnZhbGlkUGFyYW1zPy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZUVycm9yKCdJbnZhbGlkIHBhcmFtZXRlcnM6Jyk7XG5cbiAgICAgICAgICAgICAgICBpbnZhbGlkUGFyYW1zLmZvckVhY2goKHAsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlbG4oXG4gICAgICAgICAgICAgICAgICAgICAgICBgJHtpbmRleCArIDF9LiBJbnZhbGlkIHZhbHVlIGZvciAke3AubmFtZX06ICR7YXJnc1twLm5hbWVdfSAtPiAke1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAubWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICAgICAgfWAsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG4iXX0=