UNPKG

@qodalis/angular-cli

Version:

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

335 lines 48.5 kB
import { Component, Inject, Input, ViewEncapsulation, } from '@angular/core'; import { CliForegroundColor, colorFirstWord, } from '@qodalis/cli-core'; import { ICliUserSessionService_TOKEN } from './tokens'; import { CliExecutionContext } from './context'; import { CliBoot } from './services/system/cli-boot'; import { CliWelcomeMessageService } from './services/system/cli-welcome-message.service'; import { BehaviorSubject, combineLatest, filter } from 'rxjs'; import { themes } from './processors/theme/types'; import * as i0 from "@angular/core"; import * as i1 from "./services"; import * as i2 from "./storage/cli-key-value-store"; import * as i3 from "../cli-terminal/cli-terminal.component"; export class CliComponent { constructor(injector, userManagementService, commandExecutor, commandHistoryService, store) { this.injector = injector; this.userManagementService = userManagementService; this.commandExecutor = commandExecutor; this.commandHistoryService = commandHistoryService; this.store = store; this.currentLine = ''; this.minDepsInitialized = new BehaviorSubject(false); this.terminalInitialized = new BehaviorSubject(false); this.selectionStart = null; this.selectionEnd = null; this.historyIndex = 0; this.cursorPosition = 0; this.userManagementService.getUserSession().subscribe((session) => { this.currentUserSession = session; this.executionContext?.setSession(session); if (this.terminal) { this.printPrompt({ reset: true, }); } }); } ngOnInit() { combineLatest([this.minDepsInitialized, this.terminalInitialized]) .pipe(filter(([x, y]) => x && y)) .subscribe(() => { this.initialize(); }); this.terminalOptions = { cursorBlink: true, allowProposedApi: true, fontSize: 20, theme: themes.default, convertEol: true, ...(this.options?.terminalOptions ?? {}), }; this.store.initialize().then(() => { this.minDepsInitialized.next(true); }); } onTerminalReady(terminal) { this.terminal = terminal; this.terminalInitialized.next(true); } initialize() { this.commandHistoryService.initialize().then(() => { this.historyIndex = this.commandHistoryService.getLastIndex(); }); this.addTerminalEventListeners(); this.executionContext = new CliExecutionContext(this.injector, this.terminal, this.commandExecutor, (o) => this.printPrompt(o), { ...(this.options ?? {}), terminalOptions: this.terminalOptions, }); this.executionContext.setSession(this.currentUserSession); this.injector .get(CliBoot) .boot(this.executionContext) .then(() => { this.injector .get(CliWelcomeMessageService) .displayWelcomeMessage(this.executionContext); }); } getTerminalCursorPosition() { const x = this.terminal._core.buffer.x; const y = this.terminal._core.buffer.y; return { x, y, }; } addTerminalEventListeners() { // Handle user input this.terminal.onData(async (data) => await this.handleInput(data)); this.terminal.onKey(async (event) => { }); this.terminal.attachCustomKeyEventHandler((event) => { if (event.type === 'keydown') { if (event.code === 'KeyC' && event.ctrlKey) { // Handle Ctrl+C this.executionContext?.abort(); this.executionContext?.setContextProcessor(undefined); this.terminal.writeln('Ctrl+C'); this.printPrompt(); return false; } if (event.code === 'Escape') { // Handle Escape this.executionContext?.abort(); this.printPrompt({ newLine: true, }); return false; } if (event.code === 'KeyV' && event.ctrlKey) { //Handle Ctrl+V return false; } if (event.code === 'KeyL' && event.ctrlKey) { // Prevent the browser's default action (e.g., focusing the address bar) event.preventDefault(); this.clearCurrentLine(); // Clear the terminal screen this.terminal.clear(); return false; } if (event.shiftKey && (event.code === 'ArrowLeft' || event.code === 'ArrowRight')) { if (!this.selectionStart) { this.selectionStart = this.getTerminalCursorPosition(); } switch (event.code) { case 'ArrowLeft': this.moveCursorLeft(); break; case 'ArrowRight': this.moveCursorRight(); break; } this.selectionEnd = this.getTerminalCursorPosition(); this.updateSelection(); return false; } else { this.selectionStart = null; } } return true; }); } updateSelection() { if (this.selectionStart && this.selectionEnd) { const startRow = Math.min(this.selectionStart.y, this.selectionEnd.y); const endRow = Math.max(this.selectionStart.y, this.selectionEnd.y); if (startRow === endRow) { const startCol = Math.min(this.selectionStart.x, this.selectionEnd.x); const endCol = Math.max(this.selectionStart.x, this.selectionEnd.x); // Select text on the same line this.terminal.select(startCol, startRow, Math.abs(endCol - startCol)); } else { // Select multiple lines this.terminal.selectLines(startRow, endRow); } } } printPrompt(options) { const { reset, newLine, keepCurrentLine } = options || {}; if (reset) { this.terminal.write('\x1b[2K\r'); } if (newLine) { this.terminal.write('\r\n'); } if (!keepCurrentLine) { this.currentLine = ''; this.cursorPosition = 0; } let promtStartMessage = this.options?.usersModule?.hideUserName || !this.options?.usersModule?.enabled ? '' : `\x1b[32m${this.currentUserSession?.user.email}\x1b[0m:`; if (this.executionContext?.contextProcessor) { promtStartMessage = `${this.executionContext.contextProcessor.command}`; } const promtEndMessage = '\x1b[34m~\x1b[0m$ '; const prompt = `${promtStartMessage}${promtEndMessage}`; this.terminal.write(prompt); } async handleInput(data) { if (this.executionContext?.isProgressRunning()) { return; } if (data === '\r') { // Enter key: Process the current command this.terminal.write('\r\n'); // Move to the next line if (this.currentLine) { await this.commandHistoryService.addCommand(this.currentLine); this.historyIndex = this.commandHistoryService.getLastIndex(); //reset cursor position this.cursorPosition = 0; await this.commandExecutor.executeCommand(this.currentLine, this.executionContext); //check if the command has subscribed to the onAbort event if (this.executionContext?.onAbort.observed) { this.terminal.writeln('\x1b[33m' + 'Press Ctrl+C to cancel' + '\x1b[0m'); } } this.printPrompt(); } else if (data === '\u001B[A') { // Arrow Up this.showPreviousCommand(); } else if (data === '\u001B[B') { // Arrow Down this.showNextCommand(); } else if (data === '\u001B[D') { // Left Arrow this.moveCursorLeft(data); } else if (data === '\u001B[C') { // Right Arrow this.moveCursorRight(data); } else if (data === '\u007F') { // Backspace key this.handleBackspace(); } else { // Append character at cursor position this.handleInputText(data); } } normalizeText(text) { //handle tab if (text === '\u0009') { return ' '; } return text.replace(/[\r\n]+/g, ''); } handleInputText(text) { text = this.normalizeText(text); this.currentLine = this.currentLine.slice(0, this.cursorPosition) + text + this.currentLine.slice(this.cursorPosition); this.cursorPosition += text.length; this.refreshCurrentLine(); } refreshCurrentLine() { this.terminal.write('\x1b[2K'); // Clear the current line this.terminal.write('\r'); // Move the cursor to the start this.printPrompt({ keepCurrentLine: true, }); // Redraw the prompt this.writeCurrentLine(); // Move cursor to the correct position const cursorOffset = this.currentLine.length - this.cursorPosition; if (cursorOffset > 0) { this.terminal.write(`\x1b[${cursorOffset}D`); } } writeCurrentLine() { this.terminal.write(colorFirstWord(this.currentLine, (word) => this.executionContext?.writer.wrapInColor(word, CliForegroundColor.Yellow) ?? this.currentLine)); } showPreviousCommand() { if (this.historyIndex > 0) { this.historyIndex--; this.displayCommandFromHistory(); } } showNextCommand() { if (this.historyIndex < this.commandHistoryService.getLastIndex() - 1) { this.historyIndex++; this.displayCommandFromHistory(); } else { this.historyIndex = this.commandHistoryService.getLastIndex(); this.clearCurrentLine(); } } displayCommandFromHistory() { this.clearCurrentLine(); this.currentLine = this.commandHistoryService.getCommand(this.historyIndex) || ''; this.writeCurrentLine(); this.cursorPosition = this.currentLine.length; } clearCurrentLine() { const wrappedLines = Math.ceil(this.currentLine.length / this.terminal.cols); for (let i = 0; i < wrappedLines; i++) { this.terminal.write('\x1b[2K'); // Clear the current line this.terminal.write('\r'); // Move the cursor to the start of the line if (i < wrappedLines - 1) { this.terminal.write('\x1b[F'); // Move the cursor up for all but the last line } if (i === wrappedLines - 1) { this.terminal.write('\r'); this.printPrompt(); } } this.currentLine = ''; this.cursorPosition = 0; } moveCursorLeft(key = '\x1b[D') { if (this.cursorPosition > 0) { this.cursorPosition--; this.terminal.write(key); } } moveCursorRight(key = '\x1b[C') { if (this.cursorPosition < this.currentLine.length) { this.cursorPosition++; this.terminal.write(key); } } handleBackspace() { if (this.cursorPosition > 0) { this.currentLine = this.currentLine.slice(0, this.cursorPosition - 1) + this.currentLine.slice(this.cursorPosition); this.cursorPosition--; this.refreshCurrentLine(); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliComponent, deps: [{ token: i0.Injector }, { token: ICliUserSessionService_TOKEN }, { token: i1.CliCommandExecutorService }, { token: i1.CliCommandHistoryService }, { token: i2.CliKeyValueStore }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: CliComponent, selector: "cli", inputs: { options: "options", height: "height" }, ngImport: i0, template: "<cli-terminal\n [options]=\"terminalOptions\"\n [height]=\"height\"\n (onTerminalReady)=\"onTerminalReady($event)\"\n/>\n", styles: [""], dependencies: [{ kind: "component", type: i3.CliTerminalComponent, selector: "cli-terminal", inputs: ["options", "height"], outputs: ["onTerminalReady"] }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliComponent, decorators: [{ type: Component, args: [{ selector: 'cli', encapsulation: ViewEncapsulation.None, template: "<cli-terminal\n [options]=\"terminalOptions\"\n [height]=\"height\"\n (onTerminalReady)=\"onTerminalReady($event)\"\n/>\n" }] }], ctorParameters: function () { return [{ type: i0.Injector }, { type: undefined, decorators: [{ type: Inject, args: [ICliUserSessionService_TOKEN] }] }, { type: i1.CliCommandExecutorService }, { type: i1.CliCommandHistoryService }, { type: i2.CliKeyValueStore }]; }, propDecorators: { options: [{ type: Input }], height: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NsaS9zcmMvbGliL2NsaS9jbGkuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpL3NyYy9saWIvY2xpL2NsaS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0gsU0FBUyxFQUNULE1BQU0sRUFFTixLQUFLLEVBRUwsaUJBQWlCLEdBQ3BCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDSCxrQkFBa0IsRUFFbEIsY0FBYyxHQUdqQixNQUFNLG1CQUFtQixDQUFDO0FBVzNCLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUN4RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDaEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3JELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxlQUFlLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM5RCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7Ozs7O0FBU2xELE1BQU0sT0FBTyxZQUFZO0lBZXJCLFlBQ1ksUUFBa0IsRUFFVCxxQkFBNkMsRUFDdEQsZUFBMEMsRUFDakMscUJBQStDLEVBQy9DLEtBQXVCO1FBTGhDLGFBQVEsR0FBUixRQUFRLENBQVU7UUFFVCwwQkFBcUIsR0FBckIscUJBQXFCLENBQXdCO1FBQ3RELG9CQUFlLEdBQWYsZUFBZSxDQUEyQjtRQUNqQywwQkFBcUIsR0FBckIscUJBQXFCLENBQTBCO1FBQy9DLFVBQUssR0FBTCxLQUFLLENBQWtCO1FBYnBDLGdCQUFXLEdBQUcsRUFBRSxDQUFDO1FBSWYsdUJBQWtCLEdBQUcsSUFB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ICBJbmplY3QsXG4gICAgSW5qZWN0b3IsXG4gICAgSW5wdXQsXG4gICAgT25Jbml0LFxuICAgIFZpZXdFbmNhcHN1bGF0aW9uLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gICAgQ2xpRm9yZWdyb3VuZENvbG9yLFxuICAgIENsaU9wdGlvbnMsXG4gICAgY29sb3JGaXJzdFdvcmQsXG4gICAgSUNsaVVzZXJTZXNzaW9uLFxuICAgIElDbGlVc2VyU2Vzc2lvblNlcnZpY2UsXG59IGZyb20gJ0Bxb2RhbGlzL2NsaS1jb3JlJztcbmltcG9ydCB7XG4gICAgQ2xpQ29tbWFuZEV4ZWN1dG9yU2VydmljZSxcbiAgICBDbGlDb21tYW5kSGlzdG9yeVNlcnZpY2UsXG59IGZyb20gJy4vc2VydmljZXMnO1xuaW1wb3J0IHsgQ2xpS2V5VmFsdWVTdG9yZSB9IGZyb20gJy4vc3RvcmFnZS9jbGkta2V5LXZhbHVlLXN0b3JlJztcbmltcG9ydCB7XG4gICAgSVRlcm1pbmFsSW5pdE9ubHlPcHRpb25zLFxuICAgIElUZXJtaW5hbE9wdGlvbnMsXG4gICAgVGVybWluYWwsXG59IGZyb20gJ0B4dGVybS94dGVybSc7XG5pbXBvcnQgeyBJQ2xpVXNlclNlc3Npb25TZXJ2aWNlX1RPS0VOIH0gZnJvbSAnLi90b2tlbnMnO1xuaW1wb3J0IHsgQ2xpRXhlY3V0aW9uQ29udGV4dCB9IGZyb20gJy4vY29udGV4dCc7XG5pbXBvcnQgeyBDbGlCb290IH0gZnJvbSAnLi9zZXJ2aWNlcy9zeXN0ZW0vY2xpLWJvb3QnO1xuaW1wb3J0IHsgQ2xpV2VsY29tZU1lc3NhZ2VTZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9zeXN0ZW0vY2xpLXdlbGNvbWUtbWVzc2FnZS5zZXJ2aWNlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdCwgZmlsdGVyIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0aGVtZXMgfSBmcm9tICcuL3Byb2Nlc3NvcnMvdGhlbWUvdHlwZXMnO1xuaW1wb3J0IHsgQ29udGFpbmVyU2l6ZSB9IGZyb20gJy4uL2NsaS10ZXJtaW5hbC9jbGktdGVybWluYWwuY29tcG9uZW50JztcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdjbGknLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9jbGkuY29tcG9uZW50Lmh0bWwnLFxuICAgIHN0eWxlVXJsczogWycuL2NsaS5jb21wb25lbnQuc2FzcyddLFxuICAgIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG59KVxuZXhwb3J0IGNsYXNzIENsaUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gICAgQElucHV0KCkgb3B0aW9ucz86IENsaU9wdGlvbnM7XG5cbiAgICBASW5wdXQoKSBoZWlnaHQ/OiBDb250YWluZXJTaXplO1xuXG4gICAgcHJvdGVjdGVkIHRlcm1pbmFsT3B0aW9ucyE6IElUZXJtaW5hbE9wdGlvbnMgJiBJVGVybWluYWxJbml0T25seU9wdGlvbnM7XG4gICAgcHJpdmF0ZSB0ZXJtaW5hbCE6IFRlcm1pbmFsO1xuXG4gICAgcHJpdmF0ZSBjdXJyZW50TGluZSA9ICcnO1xuICAgIHByaXZhdGUgZXhlY3V0aW9uQ29udGV4dD86IENsaUV4ZWN1dGlvbkNvbnRleHQ7XG4gICAgcHJpdmF0ZSBjdXJyZW50VXNlclNlc3Npb246IElDbGlVc2VyU2Vzc2lvbiB8IHVuZGVmaW5lZDtcblxuICAgIHByb3RlY3RlZCBtaW5EZXBzSW5pdGlhbGl6ZWQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgICBwcm90ZWN0ZWQgdGVybWluYWxJbml0aWFsaXplZCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgICAgICBASW5qZWN0KElDbGlVc2VyU2Vzc2lvblNlcnZpY2VfVE9LRU4pXG4gICAgICAgIHByaXZhdGUgcmVhZG9ubHkgdXNlck1hbmFnZW1lbnRTZXJ2aWNlOiBJQ2xpVXNlclNlc3Npb25TZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIGNvbW1hbmRFeGVjdXRvcjogQ2xpQ29tbWFuZEV4ZWN1dG9yU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBjb21tYW5kSGlzdG9yeVNlcnZpY2U6IENsaUNvbW1hbmRIaXN0b3J5U2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSByZWFkb25seSBzdG9yZTogQ2xpS2V5VmFsdWVTdG9yZSxcbiAgICApIHtcbiAgICAgICAgdGhpcy51c2VyTWFuYWdlbWVudFNlcnZpY2UuZ2V0VXNlclNlc3Npb24oKS5zdWJzY3JpYmUoKHNlc3Npb24pID0+IHtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFVzZXJTZXNzaW9uID0gc2Vzc2lvbjtcbiAgICAgICAgICAgIHRoaXMuZXhlY3V0aW9uQ29udGV4dD8uc2V0U2Vzc2lvbihzZXNzaW9uISk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnRlcm1pbmFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wcmludFByb21wdCh7XG4gICAgICAgICAgICAgICAgICAgIHJlc2V0OiB0cnVlLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgY29tYmluZUxhdGVzdChbdGhpcy5taW5EZXBzSW5pdGlhbGl6ZWQsIHRoaXMudGVybWluYWxJbml0aWFsaXplZF0pXG4gICAgICAgICAgICAucGlwZShmaWx0ZXIoKFt4LCB5XSkgPT4geCAmJiB5KSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZSgpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy50ZXJtaW5hbE9wdGlvbnMgPSB7XG4gICAgICAgICAgICBjdXJzb3JCbGluazogdHJ1ZSxcbiAgICAgICAgICAgIGFsbG93UHJvcG9zZWRBcGk6IHRydWUsXG4gICAgICAgICAgICBmb250U2l6ZTogMjAsXG4gICAgICAgICAgICB0aGVtZTogdGhlbWVzLmRlZmF1bHQsXG4gICAgICAgICAgICBjb252ZXJ0RW9sOiB0cnVlLFxuICAgICAgICAgICAgLi4uKHRoaXMub3B0aW9ucz8udGVybWluYWxPcHRpb25zID8/IHt9KSxcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnN0b3JlLmluaXRpYWxpemUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMubWluRGVwc0luaXRpYWxpemVkLm5leHQodHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBvblRlcm1pbmFsUmVhZHkodGVybWluYWw6IFRlcm1pbmFsKTogdm9pZCB7XG4gICAgICAgIHRoaXMudGVybWluYWwgPSB0ZXJtaW5hbDtcblxuICAgICAgICB0aGlzLnRlcm1pbmFsSW5pdGlhbGl6ZWQubmV4dCh0cnVlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGluaXRpYWxpemUoKSB7XG4gICAgICAgIHRoaXMuY29tbWFuZEhpc3RvcnlTZXJ2aWNlLmluaXRpYWxpemUoKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuaGlzdG9yeUluZGV4ID0gdGhpcy5jb21tYW5kSGlzdG9yeVNlcnZpY2UuZ2V0TGFzdEluZGV4KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuYWRkVGVybWluYWxFdmVudExpc3RlbmVycygpO1xuXG4gICAgICAgIHRoaXMuZXhlY3V0aW9uQ29udGV4dCA9IG5ldyBDbGlFeGVjdXRpb25Db250ZXh0KFxuICAgICAgICAgICAgdGhpcy5pbmplY3RvcixcbiAgICAgICAgICAgIHRoaXMudGVybWluYWwsXG4gICAgICAgICAgICB0aGlzLmNvbW1hbmRFeGVjdXRvcixcbiAgICAgICAgICAgIChvKSA9PiB0aGlzLnByaW50UHJvbXB0KG8pLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIC4uLih0aGlzLm9wdGlvbnMgPz8ge30pLFxuICAgICAgICAgICAgICAgIHRlcm1pbmFsT3B0aW9uczogdGhpcy50ZXJtaW5hbE9wdGlvbnMsXG4gICAgICAgICAgICB9LFxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZXhlY3V0aW9uQ29udGV4dC5zZXRTZXNzaW9uKHRoaXMuY3VycmVudFVzZXJTZXNzaW9uISk7XG5cbiAgICAgICAgdGhpcy5pbmplY3RvclxuICAgICAgICAgICAgLmdldChDbGlCb290KVxuICAgICAgICAgICAgLmJvb3QodGhpcy5leGVjdXRpb25Db250ZXh0KVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5qZWN0b3JcbiAgICAgICAgICAgICAgICAgICAgLmdldChDbGlXZWxjb21lTWVzc2FnZVNlcnZpY2UpXG4gICAgICAgICAgICAgICAgICAgIC5kaXNwbGF5V2VsY29tZU1lc3NhZ2UodGhpcy5leGVjdXRpb25Db250ZXh0ISk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFRlcm1pbmFsQ3Vyc29yUG9zaXRpb24oKSB7XG4gICAgICAgIGNvbnN0IHg6IG51bWJlciA9ICh0aGlzLnRlcm1pbmFsIGFzIGFueSkuX2NvcmUuYnVmZmVyLng7XG4gICAgICAgIGNvbnN0IHk6IG51bWJlciA9ICh0aGlzLnRlcm1pbmFsIGFzIGFueSkuX2NvcmUuYnVmZmVyLnk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHgsXG4gICAgICAgICAgICB5LFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgc2VsZWN0aW9uU3RhcnQ6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgc2VsZWN0aW9uRW5kOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0gfCBudWxsID0gbnVsbDtcblxuICAgIHByaXZhdGUgYWRkVGVybWluYWxFdmVudExpc3RlbmVycygpOiB2b2lkIHtcbiAgICAgICAgLy8gSGFuZGxlIHVzZXIgaW5wdXRcbiAgICAgICAgdGhpcy50ZXJtaW5hbC5vbkRhdGEoYXN5bmMgKGRhdGEpID0+IGF3YWl0IHRoaXMuaGFuZGxlSW5wdXQoZGF0YSkpO1xuXG4gICAgICAgIHRoaXMudGVybWluYWwub25LZXkoYXN5bmMgKGV2ZW50KSA9PiB7fSk7XG5cbiAgICAgICAgdGhpcy50ZXJtaW5hbC5hdHRhY2hDdXN0b21LZXlFdmVudEhhbmRsZXIoKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBpZiAoZXZlbnQudHlwZSA9PT0gJ2tleWRvd24nKSB7XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50LmNvZGUgPT09ICdLZXlDJyAmJiBldmVudC5jdHJsS2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEhhbmRsZSBDdHJsK0NcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5leGVjdXRpb25Db250ZXh0Py5hYm9ydCgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV4ZWN1dGlvbkNvbnRleHQ/LnNldENvbnRleHRQcm9jZXNzb3IodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXJtaW5hbC53cml0ZWxuKCdDdHJsK0MnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcmludFByb21wdCgpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZXZlbnQuY29kZSA9PT0gJ0VzY2FwZScpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIEVzY2FwZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmV4ZWN1dGlvbkNvbnRleHQ/LmFib3J0KCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJpbnRQcm9tcHQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3TGluZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChldmVudC5jb2RlID09PSAnS2V5VicgJiYgZXZlbnQuY3RybEtleSkge1xuICAgICAgICAgICAgICAgICAgICAvL0hhbmRsZSBDdHJsK1ZcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChldmVudC5jb2RlID09PSAnS2V5TCcgJiYgZXZlbnQuY3RybEtleSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQcmV2ZW50IHRoZSBicm93c2VyJ3MgZGVmYXVsdCBhY3Rpb24gKGUuZy4sIGZvY3VzaW5nIHRoZSBhZGRyZXNzIGJhcilcbiAgICAgICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyQ3VycmVudExpbmUoKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBDbGVhciB0aGUgdGVybWluYWwgc2NyZWVuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMudGVybWluYWwuY2xlYXIoKTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICBldmVudC5zaGlmdEtleSAmJlxuICAgICAgICAgICAgICAgICAgICAoZXZlbnQuY29kZSA9PT0gJ0Fycm93TGVmdCcgfHwgZXZlbnQuY29kZSA9PT0gJ0Fycm93UmlnaHQnKVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc2VsZWN0aW9uU3RhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uU3RhcnQgPSB0aGlzLmdldFRlcm1pbmFsQ3Vyc29yUG9zaXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZXZlbnQuY29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnQXJyb3dMZWZ0JzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1vdmVDdXJzb3JMZWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdBcnJvd1JpZ2h0JzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1vdmVDdXJzb3JSaWdodCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25FbmQgPSB0aGlzLmdldFRlcm1pbmFsQ3Vyc29yUG9zaXRpb24oKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25TdGFydCA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGVTZWxlY3Rpb24oKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnNlbGVjdGlvblN0YXJ0ICYmIHRoaXMuc2VsZWN0aW9uRW5kKSB7XG4gICAgICAgICAgICBjb25zdCBzdGFydFJvdyA9IE1hdGgubWluKFxuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uU3RhcnQueSxcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGlvbkVuZC55LFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGVuZFJvdyA9IE1hdGgubWF4KHRoaXMuc2VsZWN0aW9uU3RhcnQueSwgdGhpcy5zZWxlY3Rpb25FbmQueSk7XG5cbiAgICAgICAgICAgIGlmIChzdGFydFJvdyA9PT0gZW5kUm93KSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RhcnRDb2wgPSBNYXRoLm1pbihcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25TdGFydC54LFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGlvbkVuZC54LFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29uc3QgZW5kQ29sID0gTWF0aC5tYXgoXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uU3RhcnQueCxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25FbmQueCxcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgLy8gU2VsZWN0IHRleHQgb24gdGhlIHNhbWUgbGluZVxuICAgICAgICAgICAgICAgIHRoaXMudGVybWluYWwuc2VsZWN0KFxuICAgICAgICAgICAgICAgICAgICBzdGFydENvbCxcbiAgICAgICAgICAgICAgICAgICAgc3RhcnRSb3csXG4gICAgICAgICAgICAgICAgICAgIE1hdGguYWJzKGVuZENvbCAtIHN0YXJ0Q29sKSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBTZWxlY3QgbXVsdGlwbGUgbGluZXNcbiAgICAgICAgICAgICAgICB0aGlzLnRlcm1pbmFsLnNlbGVjdExpbmVzKHN0YXJ0Um93LCBlbmRSb3cpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwcmludFByb21wdChvcHRpb25zPzoge1xuICAgICAgICByZXNldD86IGJvb2xlYW47XG4gICAgICAgIG5ld0xpbmU/OiBib29sZWFuO1xuICAgICAgICBrZWVwQ3VycmVudExpbmU/OiBib29sZWFuO1xuICAgIH0pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgeyByZXNldCwgbmV3TGluZSwga2VlcEN1cnJlbnRMaW5lIH0gPSBvcHRpb25zIHx8IHt9O1xuXG4gICAgICAgIGlmIChyZXNldCkge1xuICAgICAgICAgICAgdGhpcy50ZXJtaW5hbC53cml0ZSgnXFx4MWJbMktcXHInKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChuZXdMaW5lKSB7XG4gICAgICAgICAgICB0aGlzLnRlcm1pbmFsLndyaXRlKCdcXHJcXG4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgha2VlcEN1cnJlbnRMaW5lKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRMaW5lID0gJyc7XG4gICAgICAgICAgICB0aGlzLmN1cnNvclBvc2l0aW9uID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBwcm9tdFN0YXJ0TWVzc2FnZSA9XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnM/LnVzZXJzTW9kdWxlPy5oaWRlVXNlck5hbWUgfHxcbiAgICAgICAgICAgICF0aGlzLm9wdGlvbnM/LnVzZXJzTW9kdWxlPy5lbmFibGVkXG4gICAgICAgICAgICAgICAgPyAnJ1xuICAgICAgICAgICAgICAgIDogYFxceDFiWzMybSR7dGhpcy5jdXJyZW50VXNlclNlc3Npb24/LnVzZXIuZW1haWx9XFx4MWJbMG06YDtcblxuICAgICAgICBpZiAodGhpcy5leGVjdXRpb25Db250ZXh0Py5jb250ZXh0UHJvY2Vzc29yKSB7XG4gICAgICAgICAgICBwcm9tdFN0YXJ0TWVzc2FnZSA9IGAke3RoaXMuZXhlY3V0aW9uQ29udGV4dC5jb250ZXh0UHJvY2Vzc29yLmNvbW1hbmR9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHByb210RW5kTWVzc2FnZSA9ICdcXHgxYlszNG1+XFx4MWJbMG0kICc7XG5cbiAgICAgICAgY29uc3QgcHJvbXB0ID0gYCR7cHJvbXRTdGFydE1lc3NhZ2V9JHtwcm9tdEVuZE1lc3NhZ2V9YDtcblxuICAgICAgICB0aGlzLnRlcm1pbmFsLndyaXRlKHByb21wdCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBoaXN0b3J5SW5kZXg6IG51bWJlciA9IDA7XG4gICAgcHJpdmF0ZSBjdXJzb3JQb3NpdGlvbjogbnVtYmVyID0gMDtcblxuICAgIHByaXZhdGUgYXN5bmMgaGFuZGxlSW5wdXQoZGF0YTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGlmICh0aGlzLmV4ZWN1dGlvbkNvbnRleHQ/LmlzUHJvZ3Jlc3NSdW5uaW5nKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkYXRhID09PSAnXFxyJykge1xuICAgICAgICAgICAgLy8gRW50ZXIga2V5OiBQcm9jZXNzIHRoZSBjdXJyZW50IGNvbW1hbmRcbiAgICAgICAgICAgIHRoaXMudGVybWluYWwud3JpdGUoJ1xcclxcbicpOyAvLyBNb3ZlIHRvIHRoZSBuZXh0IGxpbmVcblxuICAgICAgICAgICAgaWYgKHRoaXMuY3VycmVudExpbmUpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmNvbW1hbmRIaXN0b3J5U2VydmljZS5hZGRDb21tYW5kKHRoaXMuY3VycmVudExpbmUpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5oaXN0b3J5SW5kZXggPSB0aGlzLmNvbW1hbmRIaXN0b3J5U2VydmljZS5nZXRMYXN0SW5kZXgoKTtcblxuICAgICAgICAgICAgICAgIC8vcmVzZXQgY3Vyc29yIHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJzb3JQb3NpdGlvbiA9IDA7XG5cbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmNvbW1hbmRFeGVjdXRvci5leGVjdXRlQ29tbWFuZChcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50TGluZSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5leGVjdXRpb25Db250ZXh0ISxcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgLy9jaGVjayBpZiB0aGUgY29tbWFuZCBoYXMgc3Vic2NyaWJlZCB0byB0aGUgb25BYm9ydCBldmVudFxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmV4ZWN1dGlvbkNvbnRleHQ/Lm9uQWJvcnQub2JzZXJ2ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50ZXJtaW5hbC53cml0ZWxuKFxuICAgICAgICAgICAgICAgICAgICAgICAgJ1xceDFiWzMzbScgKyAnUHJlc3MgQ3RybCtDIHRvIGNhbmNlbCcgKyAnXFx4MWJbMG0nLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5wcmludFByb21wdCgpO1xuICAgICAgICB9IGVsc2UgaWYgKGRhdGEgPT09ICdcXHUwMDFCW0EnKSB7XG4gICAgICAgICAgICAvLyBBcnJvdyBVcFxuICAgICAgICAgICAgdGhpcy5zaG93UHJldmlvdXNDb21tYW5kKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YSA9PT0gJ1xcdTAwMUJbQicpIHtcbiAgICAgICAgICAgIC8vIEFycm93IERvd25cbiAgICAgICAgICAgIHRoaXMuc2hvd05leHRDb21tYW5kKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YSA9PT0gJ1xcdTAwMUJbRCcpIHtcbiAgICAgICAgICAgIC8vIExlZnQgQXJyb3dcbiAgICAgICAgICAgIHRoaXMubW92ZUN1cnNvckxlZnQoZGF0YSk7XG4gICAgICAgIH0gZWxzZSBpZiAoZGF0YSA9PT0gJ1xcdTAwMUJbQycpIHtcbiAgICAgICAgICAgIC8vIFJpZ2h0IEFycm93XG4gICAgICAgICAgICB0aGlzLm1vdmVDdXJzb3JSaWdodChkYXRhKTtcbiAgICAgICAgfSBlbHNlIGlmIChkYXRhID09PSAnXFx1MDA3RicpIHtcbiAgICAgICAgICAgIC8vIEJhY2tzcGFjZSBrZXlcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlQmFja3NwYWNlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBBcHBlbmQgY2hhcmFjdGVyIGF0IGN1cnNvciBwb3NpdGlvblxuICAgICAgICAgICAgdGhpcy5oYW5kbGVJbnB1dFRleHQoZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG5vcm1hbGl6ZVRleHQodGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgLy9oYW5kbGUgdGFiXG4gICAgICAgIGlmICh0ZXh0ID09PSAnXFx1MDAwOScpIHtcbiAgICAgICAgICAgIHJldHVybiAnICAgICc7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGV4dC5yZXBsYWNlKC9bXFxyXFxuXSsvZywgJycpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaGFuZGxlSW5wdXRUZXh0KHRleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0ZXh0ID0gdGhpcy5ub3JtYWxpemVUZXh0KHRleHQpO1xuXG4gICAgICAgIHRoaXMuY3VycmVudExpbmUgPVxuICAgICAgICAgICAgdGhpcy5jdXJyZW50TGluZS5zbGljZSgwLCB0aGlzLmN1cnNvclBvc2l0aW9uKSArXG4gICAgICAgICAgICB0ZXh0ICtcbiAgICAgICAgICAgIHRoaXMuY3VycmVudExpbmUuc2xpY2UodGhpcy5jdXJzb3JQb3NpdGlvbik7XG5cbiAgICAgICAgdGhpcy5jdXJzb3JQb3NpdGlvbiArPSB0ZXh0Lmxlbmd0aDtcblxuICAgICAgICB0aGlzLnJlZnJlc2hDdXJyZW50TGluZSgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVmcmVzaEN1cnJlbnRMaW5lKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnRlcm1pbmFsLndyaXRlKCdcXHgxYlsySycpOyAvLyBDbGVhciB0aGUgY3VycmVudCBsaW5lXG4gICAgICAgIHRoaXMudGVybWluYWwud3JpdGUoJ1xccicpOyAvLyBNb3ZlIHRoZSBjdXJzb3IgdG8gdGhlIHN0YXJ0XG5cbiAgICAgICAgdGhpcy5wcmludFByb21wdCh7XG4gICAgICAgICAgICBrZWVwQ3VycmVudExpbmU6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFJlZHJhdyB0aGUgcHJvbXB0XG4gICAgICAgIHRoaXMud3JpdGVDdXJyZW50TGluZSgpO1xuXG4gICAgICAgIC8vIE1vdmUgY3Vyc29yIHRvIHRoZSBjb3JyZWN0IHBvc2l0aW9uXG4gICAgICAgIGNvbnN0IGN1cnNvck9mZnNldCA9IHRoaXMuY3VycmVudExpbmUubGVuZ3RoIC0gdGhpcy5jdXJzb3JQb3NpdGlvbjtcbiAgICAgICAgaWYgKGN1cnNvck9mZnNldCA+IDApIHtcbiAgICAgICAgICAgIHRoaXMudGVybWluYWwud3JpdGUoYFxceDFiWyR7Y3Vyc29yT2Zmc2V0fURgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgd3JpdGVDdXJyZW50TGluZSgpIHtcbiAgICAgICAgdGhpcy50ZXJtaW5hbC53cml0ZShcbiAgICAgICAgICAgIGNvbG9yRmlyc3RXb3JkKFxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudExpbmUsXG4gICAgICAgICAgICAgICAgKHdvcmQpID0+XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXhlY3V0aW9uQ29udGV4dD8ud3JpdGVyLndyYXBJbkNvbG9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgd29yZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIENsaUZvcmVncm91bmRDb2xvci5ZZWxsb3csXG4gICAgICAgICAgICAgICAgICAgICkgPz8gdGhpcy5jdXJyZW50TGluZSxcbiAgICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzaG93UHJldmlvdXNDb21tYW5kKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5oaXN0b3J5SW5kZXggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmhpc3RvcnlJbmRleC0tO1xuICAgICAgICAgICAgdGhpcy5kaXNwbGF5Q29tbWFuZEZyb21IaXN0b3J5KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHNob3dOZXh0Q29tbWFuZCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaGlzdG9yeUluZGV4IDwgdGhpcy5jb21tYW5kSGlzdG9yeVNlcnZpY2UuZ2V0TGFzdEluZGV4KCkgLSAxKSB7XG4gICAgICAgICAgICB0aGlzLmhpc3RvcnlJbmRleCsrO1xuICAgICAgICAgICAgdGhpcy5kaXNwbGF5Q29tbWFuZEZyb21IaXN0b3J5KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmhpc3RvcnlJbmRleCA9IHRoaXMuY29tbWFuZEhpc3RvcnlTZXJ2aWNlLmdldExhc3RJbmRleCgpO1xuICAgICAgICAgICAgdGhpcy5jbGVhckN1cnJlbnRMaW5lKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGRpc3BsYXlDb21tYW5kRnJvbUhpc3RvcnkoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY2xlYXJDdXJyZW50TGluZSgpO1xuICAgICAgICB0aGlzLmN1cnJlbnRMaW5lID1cbiAgICAgICAgICAgIHRoaXMuY29tbWFuZEhpc3RvcnlTZXJ2aWNlLmdldENvbW1hbmQodGhpcy5oaXN0b3J5SW5kZXgpIHx8ICcnO1xuICAgICAgICB0aGlzLndyaXRlQ3VycmVudExpbmUoKTtcbiAgICAgICAgdGhpcy5jdXJzb3JQb3NpdGlvbiA9IHRoaXMuY3VycmVudExpbmUubGVuZ3RoO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2xlYXJDdXJyZW50TGluZSgpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgd3JhcHBlZExpbmVzID0gTWF0aC5jZWlsKFxuICAgICAgICAgICAgdGhpcy5jdXJyZW50TGluZS5sZW5ndGggLyB0aGlzLnRlcm1pbmFsLmNvbHMsXG4gICAgICAgICk7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB3cmFwcGVkTGluZXM7IGkrKykge1xuICAgICAgICAgICAgdGhpcy50ZXJtaW5hbC53cml0ZSgnXFx4MWJbMksnKTsgLy8gQ2xlYXIgdGhlIGN1cnJlbnQgbGluZVxuICAgICAgICAgICAgdGhpcy50ZXJtaW5hbC53cml0ZSgnXFxyJyk7IC8vIE1vdmUgdGhlIGN1cnNvciB0byB0aGUgc3RhcnQgb2YgdGhlIGxpbmVcbiAgICAgICAgICAgIGlmIChpIDwgd3JhcHBlZExpbmVzIC0gMSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGVybWluYWwud3JpdGUoJ1xceDFiW0YnKTsgLy8gTW92ZSB0aGUgY3Vyc29yIHVwIGZvciBhbGwgYnV0IHRoZSBsYXN0IGxpbmVcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGkgPT09IHdyYXBwZWRMaW5lcyAtIDEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRlcm1pbmFsLndyaXRlKCdcXHInKTtcbiAgICAgICAgICAgICAgICB0aGlzLnByaW50UHJvbXB0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmN1cnJlbnRMaW5lID0gJyc7XG4gICAgICAgIHRoaXMuY3Vyc29yUG9zaXRpb24gPSAwO1xuICAgIH1cblxuICAgIHByaXZhdGUgbW92ZUN1cnNvckxlZnQoa2V5OiBzdHJpbmcgPSAnXFx4MWJbRCcpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuY3Vyc29yUG9zaXRpb24gPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnNvclBvc2l0aW9uLS07XG4gICAgICAgICAgICB0aGlzLnRlcm1pbmFsLndyaXRlKGtleSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG1vdmVDdXJzb3JSaWdodChrZXk6IHN0cmluZyA9ICdcXHgxYltDJyk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5jdXJzb3JQb3NpdGlvbiA8IHRoaXMuY3VycmVudExpbmUubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnNvclBvc2l0aW9uKys7XG4gICAgICAgICAgICB0aGlzLnRlcm1pbmFsLndyaXRlKGtleSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGhhbmRsZUJhY2tzcGFjZSgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuY3Vyc29yUG9zaXRpb24gPiAwKSB7XG4gICAgICAgICAgICB0aGlzLmN1cnJlbnRMaW5lID1cbiAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRMaW5lLnNsaWNlKDAsIHRoaXMuY3Vyc29yUG9zaXRpb24gLSAxKSArXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50TGluZS5zbGljZSh0aGlzLmN1cnNvclBvc2l0aW9uKTtcbiAgICAgICAgICAgIHRoaXMuY3Vyc29yUG9zaXRpb24tLTtcblxuICAgICAgICAgICAgdGhpcy5yZWZyZXNoQ3VycmVudExpbmUoKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIjxjbGktdGVybWluYWxcbiAgW29wdGlvbnNdPVwidGVybWluYWxPcHRpb25zXCJcbiAgW2hlaWdodF09XCJoZWlnaHRcIlxuICAob25UZXJtaW5hbFJlYWR5KT1cIm9uVGVybWluYWxSZWFkeSgkZXZlbnQpXCJcbi8+XG4iXX0=