@qodalis/cli-server-logs
Version:
An Angular CLI extension for server logs.
152 lines • 21.3 kB
JavaScript
import { Injectable } from '@angular/core';
import * as signalR from '@microsoft/signalr';
import { DefaultLibraryAuthor, highlightTextWithBg, toQueryString, } from '@qodalis/cli-core';
import * as i0 from "@angular/core";
const levels = ['verbose', 'debug', 'information', 'warning', 'error', 'fatal'];
export class CliLogsCommandProcessor {
constructor() {
this.command = 'server-logs';
this.description = 'Show live logs';
this.processors = [];
this.metadata = {
requireServer: true,
};
this.parameters = [
{
name: 'pattern',
type: 'string',
description: 'The regex pattern to search for in the logs',
required: false,
validator: (value) => {
const isValid = this.isValidRegex(value);
return {
valid: isValid,
message: isValid
? undefined
: 'Invalid regex pattern provided',
};
},
},
{
name: 'level',
type: 'string',
description: 'The log level to filter by, e.g. ' + levels.join(', '),
required: false,
validator: (value) => {
const isValid = levels.includes(value);
return {
valid: isValid,
message: isValid
? undefined
: 'Invalid log level provided, must be one of: ' +
levels.join(', '),
};
},
},
{
name: 'server',
type: 'string',
description: 'The server to connect to, e.g. "http://localhost:5000"',
required: false,
},
{
name: 'hub',
type: 'string',
description: 'The hub to connect to, e.g. "loghub" (default) or "loghub2"',
required: false,
},
{
name: 'file',
type: 'boolean',
description: 'Export logs to a file',
required: false,
},
];
this.author = DefaultLibraryAuthor;
this.processors?.push({
command: 'live',
description: this.description,
parameters: this.parameters,
processCommand: this.processCommand.bind(this),
writeDescription: this.writeDescription.bind(this),
});
}
async processCommand(command, context) {
let qs = '?';
const args = this.excludeKeys(command.args, ['server', 'hub', 'file']);
if (Object.keys(args).length > 0) {
qs += toQueryString(args);
}
const hub = command.args['hub'] || 'loghub';
let server = command.args['server'] || '';
server = server.replace(/\/+$/, '');
const url = `${server}/${hub}${qs}`;
console.log('Connecting to:', url);
this.hubConnection = new signalR.HubConnectionBuilder()
.withUrl(url)
.build();
const buffer = [];
await this.hubConnection
.start()
.then(() => {
console.log('SignalR connection started');
context.writer.writeWarning('Connected to live logs');
if (qs.length) {
Object.keys(args).forEach((key) => {
context.writer.writeWarning(`Filtering logs by: ${key}=${command.args[key]}`);
});
}
let firstLog = true;
let index = 0;
this.hubConnection.on('log', (log) => {
if (firstLog) {
context.writer.writeln('');
}
buffer.push(log);
context.writer.writeln(`\x1b[33m${++index}\x1b[0m. ` +
(command.args['pattern']
? highlightTextWithBg(log, new RegExp(command.args['pattern'], 'g'))
: log));
firstLog = false;
});
const subscription = context.onAbort.subscribe(() => {
this.hubConnection.stop();
context.writer.writeWarning('Disconnected from live logs');
if (command.args['file']) {
const filename = `logs-${new Date().toISOString()}.txt`;
context.writer.writeToFile(filename, buffer.join('\n'));
}
subscription.unsubscribe();
});
})
.catch((err) => {
console.error('Error starting SignalR connection:', err);
context.writer.writeError('Failed to connect to live logs');
context.writer.writeError(err?.toString());
});
}
writeDescription(context) {
context.writer.writeln('Show live logs');
}
excludeKeys(record, keysToExclude) {
return Object.fromEntries(Object.entries(record).filter(([key]) => !keysToExclude.includes(key)));
}
isValidRegex(pattern) {
try {
new RegExp(pattern);
return true;
}
catch (e) {
return false;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliLogsCommandProcessor, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliLogsCommandProcessor, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: CliLogsCommandProcessor, decorators: [{
type: Injectable,
args: [{
providedIn: 'root',
}]
}], ctorParameters: function () { return []; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLWxvZ3MtY29tbWFuZC1wcm9jZXNzb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zZXJ2ZXItbG9ncy9zcmMvbGliL3Byb2Nlc3NvcnMvY2xpLWxvZ3MtY29tbWFuZC1wcm9jZXNzb3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEtBQUssT0FBTyxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFHSCxvQkFBb0IsRUFDcEIsbUJBQW1CLEVBS25CLGFBQWEsR0FDaEIsTUFBTSxtQkFBbUIsQ0FBQzs7QUFFM0IsTUFBTSxNQUFNLEdBQUcsQ0FBQyxTQUFTLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBS2hGLE1BQU0sT0FBTyx1QkFBdUI7SUF1RWhDO1FBdEVBLFlBQU8sR0FBRyxhQUFhLENBQUM7UUFFeEIsZ0JBQVcsR0FBd0IsZ0JBQWdCLENBQUM7UUFFcEQsZUFBVSxHQUF3QyxFQUFFLENBQUM7UUFFckQsYUFBUSxHQUFzQztZQUMxQyxhQUFhLEVBQUUsSUFBSTtTQUN0QixDQUFDO1FBRUYsZUFBVSxHQUFrRDtZQUN4RDtnQkFDSSxJQUFJLEVBQUUsU0FBUztnQkFDZixJQUFJLEVBQUUsUUFBUTtnQkFDZCxXQUFXLEVBQUUsNkNBQTZDO2dCQUMxRCxRQUFRLEVBQUUsS0FBSztnQkFDZixTQUFTLEVBQUUsQ0FBQyxLQUFhLEVBQUUsRUFBRTtvQkFDekIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDekMsT0FBTzt3QkFDSCxLQUFLLEVBQUUsT0FBTzt3QkFDZCxPQUFPLEVBQUUsT0FBTzs0QkFDWixDQUFDLENBQUMsU0FBUzs0QkFDWCxDQUFDLENBQUMsZ0NBQWdDO3FCQUN6QyxD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SUFDcEIsQ0FBQztJQUVPLFlBQVksQ0FBQyxPQUFlO1FBQ2hDLElBQUk7WUFDQSxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNwQixPQUFPLElBQUksQ0FBQztTQUNmO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDUixPQUFPLEtBQUssQ0FBQztTQUNoQjtJQUNMLENBQUM7K0dBekxRLHVCQUF1QjttSEFBdkIsdUJBQXVCLGNBRnBCLE1BQU07OzRGQUVULHVCQUF1QjtrQkFIbkMsVUFBVTttQkFBQztvQkFDUixVQUFVLEVBQUUsTUFBTTtpQkFDckIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgKiBhcyBzaWduYWxSIGZyb20gJ0BtaWNyb3NvZnQvc2lnbmFscic7XG5pbXBvcnQge1xuICAgIENsaVByb2Nlc3NDb21tYW5kLFxuICAgIENsaVByb2Nlc3Nvck1ldGFkYXRhLFxuICAgIERlZmF1bHRMaWJyYXJ5QXV0aG9yLFxuICAgIGhpZ2hsaWdodFRleHRXaXRoQmcsXG4gICAgSUNsaUNvbW1hbmRBdXRob3IsXG4gICAgSUNsaUNvbW1hbmRQYXJhbWV0ZXJEZXNjcmlwdG9yLFxuICAgIElDbGlDb21tYW5kUHJvY2Vzc29yLFxuICAgIElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgIHRvUXVlcnlTdHJpbmcsXG59IGZyb20gJ0Bxb2RhbGlzL2NsaS1jb3JlJztcblxuY29uc3QgbGV2ZWxzID0gWyd2ZXJib3NlJywgJ2RlYnVnJywgJ2luZm9ybWF0aW9uJywgJ3dhcm5pbmcnLCAnZXJyb3InLCAnZmF0YWwnXTtcblxuQEluamVjdGFibGUoe1xuICAgIHByb3ZpZGVkSW46ICdyb290Jyxcbn0pXG5leHBvcnQgY2xhc3MgQ2xpTG9nc0NvbW1hbmRQcm9jZXNzb3IgaW1wbGVtZW50cyBJQ2xpQ29tbWFuZFByb2Nlc3NvciB7XG4gICAgY29tbWFuZCA9ICdzZXJ2ZXItbG9ncyc7XG5cbiAgICBkZXNjcmlwdGlvbj86IHN0cmluZyB8IHVuZGVmaW5lZCA9ICdTaG93IGxpdmUgbG9ncyc7XG5cbiAgICBwcm9jZXNzb3JzPzogSUNsaUNvbW1hbmRQcm9jZXNzb3JbXSB8IHVuZGVmaW5lZCA9IFtdO1xuXG4gICAgbWV0YWRhdGE/OiBDbGlQcm9jZXNzb3JNZXRhZGF0YSB8IHVuZGVmaW5lZCA9IHtcbiAgICAgICAgcmVxdWlyZVNlcnZlcjogdHJ1ZSxcbiAgICB9O1xuXG4gICAgcGFyYW1ldGVycz86IElDbGlDb21tYW5kUGFyYW1ldGVyRGVzY3JpcHRvcltdIHwgdW5kZWZpbmVkID0gW1xuICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAncGF0dGVybicsXG4gICAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVGhlIHJlZ2V4IHBhdHRlcm4gdG8gc2VhcmNoIGZvciBpbiB0aGUgbG9ncycsXG4gICAgICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgICAgICB2YWxpZGF0b3I6ICh2YWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgaXNWYWxpZCA9IHRoaXMuaXNWYWxpZFJlZ2V4KHZhbHVlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZDogaXNWYWxpZCxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogaXNWYWxpZFxuICAgICAgICAgICAgICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIDogJ0ludmFsaWQgcmVnZXggcGF0dGVybiBwcm92aWRlZCcsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdsZXZlbCcsXG4gICAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICdUaGUgbG9nIGxldmVsIHRvIGZpbHRlciBieSwgZS5nLiAnICsgbGV2ZWxzLmpvaW4oJywgJyksXG4gICAgICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgICAgICB2YWxpZGF0b3I6ICh2YWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgaXNWYWxpZCA9IGxldmVscy5pbmNsdWRlcyh2YWx1ZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICB2YWxpZDogaXNWYWxpZCxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogaXNWYWxpZFxuICAgICAgICAgICAgICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIDogJ0ludmFsaWQgbG9nIGxldmVsIHByb3ZpZGVkLCBtdXN0IGJlIG9uZSBvZjogJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscy5qb2luKCcsICcpLFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAnc2VydmVyJyxcbiAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgICAgICAgJ1RoZSBzZXJ2ZXIgdG8gY29ubmVjdCB0bywgZS5nLiBcImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMFwiJyxcbiAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ2h1YicsXG4gICAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICdUaGUgaHViIHRvIGNvbm5lY3QgdG8sIGUuZy4gXCJsb2dodWJcIiAoZGVmYXVsdCkgb3IgXCJsb2dodWIyXCInLFxuICAgICAgICAgICAgcmVxdWlyZWQ6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAnZmlsZScsXG4gICAgICAgICAgICB0eXBlOiAnYm9vbGVhbicsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogJ0V4cG9ydCBsb2dzIHRvIGEgZmlsZScsXG4gICAgICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgXTtcblxuICAgIGF1dGhvcj86IElDbGlDb21tYW5kQXV0aG9yIHwgdW5kZWZpbmVkID0gRGVmYXVsdExpYnJhcnlBdXRob3I7XG5cbiAgICBwcml2YXRlIGh1YkNvbm5lY3Rpb24hOiBzaWduYWxSLkh1YkNvbm5lY3Rpb247XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5wcm9jZXNzb3JzPy5wdXNoKHtcbiAgICAgICAgICAgIGNvbW1hbmQ6ICdsaXZlJyxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiB0aGlzLmRlc2NyaXB0aW9uLFxuICAgICAgICAgICAgcGFyYW1ldGVyczogdGhpcy5wYXJhbWV0ZXJzLFxuICAgICAgICAgICAgcHJvY2Vzc0NvbW1hbmQ6IHRoaXMucHJvY2Vzc0NvbW1hbmQuYmluZCh0aGlzKSxcbiAgICAgICAgICAgIHdyaXRlRGVzY3JpcHRpb246IHRoaXMud3JpdGVEZXNjcmlwdGlvbi5iaW5kKHRoaXMpLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBwcm9jZXNzQ29tbWFuZChcbiAgICAgICAgY29tbWFuZDogQ2xpUHJvY2Vzc0NvbW1hbmQsXG4gICAgICAgIGNvbnRleHQ6IElDbGlFeGVjdXRpb25Db250ZXh0LFxuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBsZXQgcXMgPSAnPyc7XG5cbiAgICAgICAgY29uc3QgYXJncyA9IHRoaXMuZXhjbHVkZUtleXMoY29tbWFuZC5hcmdzLCBbJ3NlcnZlcicsICdodWInLCAnZmlsZSddKTtcblxuICAgICAgICBpZiAoT2JqZWN0LmtleXMoYXJncykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcXMgKz0gdG9RdWVyeVN0cmluZyhhcmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGh1YiA9IGNvbW1hbmQuYXJnc1snaHViJ10gfHwgJ2xvZ2h1Yic7XG5cbiAgICAgICAgbGV0IHNlcnZlciA9IGNvbW1hbmQuYXJnc1snc2VydmVyJ10gfHwgJyc7XG4gICAgICAgIHNlcnZlciA9IHNlcnZlci5yZXBsYWNlKC9cXC8rJC8sICcnKTtcblxuICAgICAgICBjb25zdCB1cmwgPSBgJHtzZXJ2ZXJ9LyR7aHVifSR7cXN9YDtcblxuICAgICAgICBjb25zb2xlLmxvZygnQ29ubmVjdGluZyB0bzonLCB1cmwpO1xuXG4gICAgICAgIHRoaXMuaHViQ29ubmVjdGlvbiA9IG5ldyBzaWduYWxSLkh1YkNvbm5lY3Rpb25CdWlsZGVyKClcbiAgICAgICAgICAgIC53aXRoVXJsKHVybClcbiAgICAgICAgICAgIC5idWlsZCgpO1xuXG4gICAgICAgIGNvbnN0IGJ1ZmZlcjogc3RyaW5nW10gPSBbXTtcblxuICAgICAgICBhd2FpdCB0aGlzLmh1YkNvbm5lY3Rpb25cbiAgICAgICAgICAgIC5zdGFydCgpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1NpZ25hbFIgY29ubmVjdGlvbiBzdGFydGVkJyk7XG5cbiAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZVdhcm5pbmcoJ0Nvbm5lY3RlZCB0byBsaXZlIGxvZ3MnKTtcbiAgICAgICAgICAgICAgICBpZiAocXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKGFyZ3MpLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVXYXJuaW5nKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBGaWx0ZXJpbmcgbG9ncyBieTogJHtrZXl9PSR7Y29tbWFuZC5hcmdzW2tleV19YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCBmaXJzdExvZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgbGV0IGluZGV4ID0gMDtcblxuICAgICAgICAgICAgICAgIHRoaXMuaHViQ29ubmVjdGlvbi5vbignbG9nJywgKGxvZzogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaXJzdExvZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVsbignJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBidWZmZXIucHVzaChsb2cpO1xuXG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQud3JpdGVyLndyaXRlbG4oXG4gICAgICAgICAgICAgICAgICAgICAgICBgXFx4MWJbMzNtJHsrK2luZGV4fVxceDFiWzBtLiBgICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY29tbWFuZC5hcmdzWydwYXR0ZXJuJ11cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBoaWdobGlnaHRUZXh0V2l0aEJnKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2csXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBSZWdFeHAoY29tbWFuZC5hcmdzWydwYXR0ZXJuJ10sICdnJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IGxvZyksXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIGZpcnN0TG9nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBzdWJzY3JpcHRpb24gPSBjb250ZXh0Lm9uQWJvcnQuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5odWJDb25uZWN0aW9uLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVXYXJuaW5nKCdEaXNjb25uZWN0ZWQgZnJvbSBsaXZlIGxvZ3MnKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY29tbWFuZC5hcmdzWydmaWxlJ10pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZpbGVuYW1lID0gYGxvZ3MtJHtuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCl9LnR4dGA7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZVRvRmlsZShmaWxlbmFtZSwgYnVmZmVyLmpvaW4oJ1xcbicpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3Igc3RhcnRpbmcgU2lnbmFsUiBjb25uZWN0aW9uOicsIGVycik7XG4gICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVFcnJvcignRmFpbGVkIHRvIGNvbm5lY3QgdG8gbGl2ZSBsb2dzJyk7XG4gICAgICAgICAgICAgICAgY29udGV4dC53cml0ZXIud3JpdGVFcnJvcihlcnI/LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgd3JpdGVEZXNjcmlwdGlvbihjb250ZXh0OiBJQ2xpRXhlY3V0aW9uQ29udGV4dCk6IHZvaWQge1xuICAgICAgICBjb250ZXh0LndyaXRlci53cml0ZWxuKCdTaG93IGxpdmUgbG9ncycpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZXhjbHVkZUtleXM8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4+KFxuICAgICAgICByZWNvcmQ6IFQsXG4gICAgICAgIGtleXNUb0V4Y2x1ZGU6IHN0cmluZ1tdLFxuICAgICk6IFBhcnRpYWw8VD4ge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMocmVjb3JkKS5maWx0ZXIoXG4gICAgICAgICAgICAgICAgKFtrZXldKSA9PiAha2V5c1RvRXhjbHVkZS5pbmNsdWRlcyhrZXkpLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgKSBhcyBQYXJ0aWFsPFQ+O1xuICAgIH1cblxuICAgIHByaXZhdGUgaXNWYWxpZFJlZ2V4KHBhdHRlcm46IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbmV3IFJlZ0V4cChwYXR0ZXJuKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=