UNPKG

29.2 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const assert_1 = __importDefault(require("assert"));
7const demurgos_foreground_child_1 = require("demurgos-foreground-child");
8const find_up_1 = __importDefault(require("find-up"));
9const fs_1 = __importDefault(require("fs"));
10const furi_1 = require("furi");
11const path_1 = __importDefault(require("path"));
12const test_exclude_1 = __importDefault(require("test-exclude"));
13const vinyl_fs_1 = __importDefault(require("vinyl-fs"));
14const yargs_1 = __importDefault(require("yargs"));
15const async_done_promise_1 = require("./async-done-promise");
16const filter_1 = require("./filter");
17const get_text_1 = require("./get-text");
18const report_1 = require("./report");
19const reporter_registry_1 = require("./reporter-registry");
20const spawn_inspected_1 = require("./spawn-inspected");
21const to_istanbul_1 = require("./to-istanbul");
22const version_1 = require("./version");
23const DEFAULT_GLOBS = test_exclude_1.default.defaultExclude.map((pattern) => `!${pattern}`);
24const DEFAULT_WATERMARKS = Object.freeze({
25 lines: [80, 95],
26 functions: [80, 95],
27 branches: [80, 95],
28 statements: [80, 95],
29});
30// TODO: Fix yargs type definition
31const ARG_PARSER = yargs_1.default();
32ARG_PARSER
33 .scriptName("c88")
34 .version(version_1.VERSION)
35 .usage("$0 [opts] [script] [opts]")
36 .locale("en")
37 .option("reporter", {
38 alias: "r",
39 describe: "coverage reporter(s) to use",
40 default: "text",
41})
42 .option("match", {
43 alias: "m",
44 default: DEFAULT_GLOBS,
45 // tslint:disable-next-line:max-line-length
46 describe: "a list of specific files and directories that should be matched, glob patterns are supported.",
47})
48 .option("coverage-directory", {
49 default: "coverage",
50 describe: "directory to output coverage JSON and reports",
51})
52 .pkgConf("c88")
53 .demandCommand(1)
54 .epilog("visit https://git.io/vHysA for list of available reporters");
55// tslint:disable:whitespace
56/**
57 * Executes the c88 CLI
58 *
59 * @param args CLI arguments
60 * @param cwd Current working directory
61 * @param proc Current process
62 */
63async function execCli(args, cwd, proc) {
64 const action = await getAction(args, cwd);
65 switch (action.action) {
66 case "message":
67 process.stderr.write(Buffer.from(action.message));
68 return action.error === undefined ? 0 : 1;
69 case "run":
70 return execRunAction(action, cwd, proc);
71 default:
72 throw new Error(`AssertionError: Unexpected \`action\`: ${action.action}`);
73 }
74}
75exports.execCli = execCli;
76function resolveConfig(fileConfig, cliConfig) {
77 return {
78 command: cliConfig.command,
79 reporters: cliConfig.reporters !== undefined ? cliConfig.reporters : ["text"],
80 globs: cliConfig.globs !== undefined ? cliConfig.globs : DEFAULT_GLOBS,
81 waterMarks: fileConfig.waterMarks !== undefined ? fileConfig.waterMarks : DEFAULT_WATERMARKS,
82 coverageDir: cliConfig.coverageDir !== undefined ? cliConfig.coverageDir : "coverage",
83 };
84}
85async function execRunAction({ config }, cwd, proc) {
86 const file = config.command[0];
87 const args = config.command.slice(1);
88 const filter = filter_1.fromGlob({ patterns: config.globs, base: furi_1.fromSysPath(cwd) });
89 const subProcessExit = deferPromise();
90 async function onRootProcess(inspectedProc) {
91 const closeFn = await demurgos_foreground_child_1.proxy(proc, inspectedProc);
92 if (closeFn.signal !== null) {
93 subProcessExit.reject(new Error(`Process killed by signal: ${closeFn.signal}`));
94 }
95 else {
96 subProcessExit.resolve(closeFn.code);
97 }
98 }
99 let processCovs;
100 try {
101 processCovs = await spawn_inspected_1.spawnInspected(file, args, { filter, onRootProcess });
102 }
103 catch (err) {
104 proc.stderr.write(Buffer.from(`${err.toString()}\n`));
105 return 1;
106 }
107 const exitCode = await subProcessExit.promise;
108 try {
109 const reporter = report_1.createReporter(reporter_registry_1.DEFAULT_REGISTRY, config.reporters, { waterMarks: config.waterMarks });
110 const resolvedCoverageDir = path_1.default.join(cwd, config.coverageDir);
111 const coverageDir = furi_1.fromSysPath(resolvedCoverageDir);
112 await report(reporter, processCovs, proc.stdout, coverageDir);
113 return exitCode;
114 }
115 catch (err) {
116 proc.stderr.write(Buffer.from(err.toString() + "\n"));
117 return Math.max(1, exitCode);
118 }
119}
120async function report(reporter, processCovs, outStream, outDir, getText = get_text_1.getText) {
121 const { coverageMap, sources } = await to_istanbul_1.processCovsToIstanbul(processCovs, getText);
122 const getSourcesSync = get_text_1.getTextSyncFromSourceStore(sources);
123 const tasks = [];
124 if (reporter.reportStream !== undefined) {
125 const stream = report_1.reportStream(reporter, coverageMap, getSourcesSync);
126 tasks.push(pipeData(stream, outStream));
127 }
128 if (reporter.reportVinyl !== undefined) {
129 const stream = report_1.reportVinyl(reporter, coverageMap, getSourcesSync)
130 .pipe(vinyl_fs_1.default.dest(furi_1.toSysPath(outDir.href)));
131 tasks.push(async_done_promise_1.asyncDonePromise(() => stream));
132 }
133 await Promise.all(tasks);
134}
135exports.report = report;
136async function getAction(args, cwd) {
137 const parsed = parseArgs(args);
138 if (parsed.action !== "run") {
139 return parsed;
140 }
141 const fileConfig = await readConfigFile(cwd);
142 return {
143 action: "run",
144 config: resolveConfig(fileConfig, parsed.config),
145 };
146}
147exports.getAction = getAction;
148function parseArgs(args) {
149 // The yargs pure API is kinda strange to use (apart from requiring a callback):
150 // The error can either be defined, `undefined` or `null`.
151 // If it is defined or `null`, then `output` should be a non-empty string
152 // intended to be written to stderr. `parsed` is defined but it should be
153 // ignored in this case.
154 // If `err` is `undefined`, then `output` is an empty string and `parsed`
155 // contains the succesfully parsed args.
156 // tslint:disable:variable-name
157 let _err;
158 let _parsed;
159 let _output;
160 let isParsed = false;
161 ARG_PARSER.parse(args, (err, parsed, output) => {
162 _err = err;
163 _parsed = parsed;
164 _output = output;
165 isParsed = true;
166 });
167 assert_1.default(isParsed);
168 const err = _err;
169 const parsed = _parsed;
170 const output = _output;
171 if (err === null) {
172 // Successfully parsed
173 return {
174 action: "run",
175 config: {
176 command: parsed._,
177 reporters: Array.isArray(parsed.reporter) ? parsed.reporter : [parsed.reporter],
178 globs: parsed.match,
179 },
180 };
181 }
182 else {
183 return { action: "message", message: output, error: err };
184 }
185}
186exports.parseArgs = parseArgs;
187async function readConfigFile(cwd) {
188 const configPath = find_up_1.default.sync([".c88rc", ".c88rc.json"]);
189 if (configPath === null) {
190 return Object.create(null);
191 }
192 return JSON.parse(fs_1.default.readFileSync(configPath, "UTF-8"));
193}
194function deferPromise() {
195 let resolve;
196 let reject;
197 const promise = new Promise((res, rej) => {
198 resolve = res;
199 reject = rej;
200 });
201 return { resolve: resolve, reject: reject, promise };
202}
203function pipeData(src, dest) {
204 return new Promise((resolve, reject) => {
205 src.on("data", chunk => dest.write(chunk));
206 src.on("error", reject);
207 src.on("end", resolve);
208 });
209}
210
211//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIl9zcmMvY2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsb0RBQTRCO0FBRTVCLHlFQUF3RjtBQUN4RixzREFBNkI7QUFDN0IsNENBQW9CO0FBQ3BCLCtCQUE4QztBQUM5QyxnREFBMkI7QUFDM0IsZ0VBQW1DO0FBRW5DLHdEQUErQjtBQUMvQixrREFBMEI7QUFDMUIsNkRBQXdEO0FBQ3hELHFDQUFvRDtBQUNwRCx5Q0FBeUc7QUFDekcscUNBQXFFO0FBRXJFLDJEQUF1RDtBQUN2RCx1REFBbUU7QUFDbkUsK0NBQXNEO0FBQ3RELHVDQUFvQztBQUVwQyxNQUFNLGFBQWEsR0FBMEIsc0JBQU8sQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBZSxFQUFFLEVBQUUsQ0FBQyxJQUFJLE9BQU8sRUFBRSxDQUFDLENBQUM7QUE4QzVHLE1BQU0sa0JBQWtCLEdBQWUsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUNuRCxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFxQjtJQUNuQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFxQjtJQUN2QyxRQUFRLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFxQjtJQUN0QyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFxQjtDQUN6QyxDQUFDLENBQUM7QUFFSCxrQ0FBa0M7QUFDbEMsTUFBTSxVQUFVLEdBQWUsZUFBSyxFQUFTLENBQUM7QUFFOUMsVUFBVTtLQUNQLFVBQVUsQ0FBQyxLQUFLLENBQUM7S0FDakIsT0FBTyxDQUFDLGlCQUFPLENBQUM7S0FDaEIsS0FBSyxDQUFDLDJCQUEyQixDQUFDO0tBQ2xDLE1BQU0sQ0FBQyxJQUFJLENBQUM7S0FDWixNQUFNLENBQUMsVUFBVSxFQUFFO0lBQ2xCLEtBQUssRUFBRSxHQUFHO0lBQ1YsUUFBUSxFQUFFLDZCQUE2QjtJQUN2QyxPQUFPLEVBQUUsTUFBTTtDQUNoQixDQUFDO0tBQ0QsTUFBTSxDQUFDLE9BQU8sRUFBRTtJQUNmLEtBQUssRUFBRSxHQUFHO0lBQ1YsT0FBTyxFQUFFLGFBQWE7SUFDdEIsMkNBQTJDO0lBQzNDLFFBQVEsRUFBRSwrRkFBK0Y7Q0FDMUcsQ0FBQztLQUNELE1BQU0sQ0FBQyxvQkFBb0IsRUFBRTtJQUM1QixPQUFPLEVBQUUsVUFBVTtJQUNuQixRQUFRLEVBQUUsK0NBQStDO0NBQzFELENBQUM7S0FDRCxPQUFPLENBQUMsS0FBSyxDQUFDO0tBQ2QsYUFBYSxDQUFDLENBQUMsQ0FBQztLQUNoQixNQUFNLENBQUMsNERBQTRELENBQUMsQ0FBQztBQUV4RSw0QkFBNEI7QUFFNUI7Ozs7OztHQU1HO0FBQ0ksS0FBSyxrQkFBa0IsSUFBYyxFQUFFLEdBQVcsRUFBRSxJQUFvQjtJQUM3RSxNQUFNLE1BQU0sR0FBYyxNQUFNLFNBQVMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFFckQsUUFBUSxNQUFNLENBQUMsTUFBTSxFQUFFO1FBQ3JCLEtBQUssU0FBUztZQUNaLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDbEQsT0FBTyxNQUFNLENBQUMsS0FBSyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDNUMsS0FBSyxLQUFLO1lBQ1IsT0FBTyxhQUFhLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMxQztZQUNFLE1BQU0sSUFBSSxLQUFLLENBQUMsMENBQTJDLE1BQWMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0tBQ3ZGO0FBQ0gsQ0FBQztBQVpELDBCQVlDO0FBRUQsdUJBQXVCLFVBQXNCLEVBQUUsU0FBb0I7SUFDakUsT0FBTztRQUNMLE9BQU8sRUFBRSxTQUFTLENBQUMsT0FBTztRQUMxQixTQUFTLEVBQUUsU0FBUyxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQzdFLEtBQUssRUFBRSxTQUFTLENBQUMsS0FBSyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsYUFBYTtRQUN0RSxVQUFVLEVBQUUsVUFBVSxDQUFDLFVBQVUsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLGtCQUFrQjtRQUM1RixXQUFXLEVBQUUsU0FBUyxDQUFDLFdBQVcsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFVBQVU7S0FDdEYsQ0FBQztBQUNKLENBQUM7QUFFRCxLQUFLLHdCQUF3QixFQUFDLE1BQU0sRUFBWSxFQUFFLEdBQVcsRUFBRSxJQUFvQjtJQUNqRixNQUFNLElBQUksR0FBVyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sSUFBSSxHQUFhLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sTUFBTSxHQUFtQixpQkFBUSxDQUFDLEVBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLGtCQUFXLENBQUMsR0FBRyxDQUFDLEVBQUMsQ0FBQyxDQUFDO0lBRTFGLE1BQU0sY0FBYyxHQUE0QixZQUFZLEVBQUUsQ0FBQztJQUUvRCxLQUFLLHdCQUF3QixhQUE4QjtRQUN6RCxNQUFNLE9BQU8sR0FBYyxNQUFNLGlDQUFZLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQ25FLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxJQUFJLEVBQUU7WUFDM0IsY0FBYyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztTQUNqRjthQUFNO1lBQ0wsY0FBYyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSyxDQUFDLENBQUM7U0FDdkM7SUFDSCxDQUFDO0lBRUQsSUFBSSxXQUE2QixDQUFDO0lBQ2xDLElBQUk7UUFDRixXQUFXLEdBQUcsTUFBTSxnQ0FBYyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsRUFBQyxNQUFNLEVBQUUsYUFBYSxFQUFDLENBQUMsQ0FBQztLQUN6RTtJQUFDLE9BQU8sR0FBRyxFQUFFO1FBQ1osSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN0RCxPQUFPLENBQUMsQ0FBQztLQUNWO0lBQ0QsTUFBTSxRQUFRLEdBQVcsTUFBTSxjQUFjLENBQUMsT0FBTyxDQUFDO0lBRXRELElBQUk7UUFDRixNQUFNLFFBQVEsR0FBYSx1QkFBYyxDQUFDLG9DQUFnQixFQUFFLE1BQU0sQ0FBQyxTQUFTLEVBQUUsRUFBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBQyxDQUFDLENBQUM7UUFDL0csTUFBTSxtQkFBbUIsR0FBVyxjQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDMUUsTUFBTSxXQUFXLEdBQWUsa0JBQVcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ2pFLE1BQU0sTUFBTSxDQUFDLFFBQVEsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxXQUFXLENBQUMsQ0FBQztRQUM5RCxPQUFPLFFBQVEsQ0FBQztLQUNqQjtJQUFDLE9BQU8sR0FBRyxFQUFFO1FBQ1osSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN0RCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0tBQzlCO0FBQ0gsQ0FBQztBQUVNLEtBQUssaUJBQ1YsUUFBa0IsRUFDbEIsV0FBMEMsRUFDMUMsU0FBZ0MsRUFDaEMsTUFBNEIsRUFDNUIsVUFBbUIsa0JBQWM7SUFFakMsTUFBTSxFQUFDLFdBQVcsRUFBRSxPQUFPLEVBQUMsR0FBRyxNQUFNLG1DQUFxQixDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNqRixNQUFNLGNBQWMsR0FBZ0IscUNBQTBCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFFeEUsTUFBTSxLQUFLLEdBQW9CLEVBQUUsQ0FBQztJQUNsQyxJQUFJLFFBQVEsQ0FBQyxZQUFZLEtBQUssU0FBUyxFQUFFO1FBQ3ZDLE1BQU0sTUFBTSxHQUEwQixxQkFBWSxDQUFDLFFBQTBCLEVBQUUsV0FBVyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1FBQzVHLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO0tBQ3pDO0lBQ0QsSUFBSSxRQUFRLENBQUMsV0FBVyxLQUFLLFNBQVMsRUFBRTtRQUN0QyxNQUFNLE1BQU0sR0FBMEIsb0JBQVcsQ0FBQyxRQUF5QixFQUFFLFdBQVcsRUFBRSxjQUFjLENBQUM7YUFDdEcsSUFBSSxDQUFDLGtCQUFPLENBQUMsSUFBSSxDQUFDLGdCQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QyxLQUFLLENBQUMsSUFBSSxDQUFDLHFDQUFnQixDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7S0FDNUM7SUFFRCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDM0IsQ0FBQztBQXRCRCx3QkFzQkM7QUFFTSxLQUFLLG9CQUFvQixJQUFjLEVBQUUsR0FBVztJQUN6RCxNQUFNLE1BQU0sR0FBb0IsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hELElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxLQUFLLEVBQUU7UUFDM0IsT0FBTyxNQUFNLENBQUM7S0FDZjtJQUNELE1BQU0sVUFBVSxHQUFlLE1BQU0sY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3pELE9BQU87UUFDTCxNQUFNLEVBQUUsS0FBSztRQUNiLE1BQU0sRUFBRSxhQUFhLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUM7S0FDakQsQ0FBQztBQUNKLENBQUM7QUFWRCw4QkFVQztBQUVELG1CQUEwQixJQUFjO0lBQ3RDLGdGQUFnRjtJQUNoRiwwREFBMEQ7SUFDMUQseUVBQXlFO0lBQ3pFLHlFQUF5RTtJQUN6RSx3QkFBd0I7SUFDeEIseUVBQXlFO0lBQ3pFLHdDQUF3QztJQUN4QywrQkFBK0I7SUFDL0IsSUFBSSxJQUE4QixDQUFDO0lBQ25DLElBQUksT0FBWSxDQUFDO0lBQ2pCLElBQUksT0FBZSxDQUFDO0lBQ3BCLElBQUksUUFBUSxHQUFZLEtBQUssQ0FBQztJQUM5QixVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLEdBQTZCLEVBQUUsTUFBVyxFQUFFLE1BQWMsRUFBUSxFQUFFO1FBQzFGLElBQUksR0FBRyxHQUFHLENBQUM7UUFDWCxPQUFPLEdBQUcsTUFBTSxDQUFDO1FBQ2pCLE9BQU8sR0FBRyxNQUFNLENBQUM7UUFDakIsUUFBUSxHQUFHLElBQUksQ0FBQztJQUNsQixDQUFDLENBQUMsQ0FBQztJQUNILGdCQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDakIsTUFBTSxHQUFHLEdBQTZCLElBQUssQ0FBQztJQUM1QyxNQUFNLE1BQU0sR0FBUSxPQUFRLENBQUM7SUFDN0IsTUFBTSxNQUFNLEdBQVcsT0FBUSxDQUFDO0lBQ2hDLElBQUksR0FBRyxLQUFLLElBQUksRUFBRTtRQUNoQixzQkFBc0I7UUFDdEIsT0FBTztZQUNMLE1BQU0sRUFBRSxLQUFLO1lBQ2IsTUFBTSxFQUFFO2dCQUNOLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztnQkFDakIsU0FBUyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7Z0JBQy9FLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSzthQUNwQjtTQUNGLENBQUM7S0FDSDtTQUFNO1FBQ0wsT0FBTyxFQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFDLENBQUM7S0FDekQ7QUFDSCxDQUFDO0FBcENELDhCQW9DQztBQUVELEtBQUsseUJBQXlCLEdBQVc7SUFDdkMsTUFBTSxVQUFVLEdBQWtCLGlCQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDekUsSUFBSSxVQUFVLEtBQUssSUFBSSxFQUFFO1FBQ3ZCLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztLQUM1QjtJQUNELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFFLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFVRDtJQUNFLElBQUksT0FBMkIsQ0FBQztJQUNoQyxJQUFJLE1BQTZCLENBQUM7SUFDbEMsTUFBTSxPQUFPLEdBQWUsSUFBSSxPQUFPLENBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUU7UUFDdEQsT0FBTyxHQUFHLEdBQUcsQ0FBQztRQUNkLE1BQU0sR0FBRyxHQUFHLENBQUM7SUFDZixDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sRUFBQyxPQUFPLEVBQUUsT0FBUSxFQUFFLE1BQU0sRUFBRSxNQUFPLEVBQUUsT0FBTyxFQUFDLENBQUM7QUFDdkQsQ0FBQztBQUVELGtCQUFrQixHQUEwQixFQUFFLElBQTJCO0lBQ3ZFLE9BQU8sSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDM0MsR0FBRyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDM0MsR0FBRyxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDeEIsR0FBRyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDekIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDIiwiZmlsZSI6ImNsaS5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhc3NlcnQgZnJvbSBcImFzc2VydFwiO1xuaW1wb3J0IGNwIGZyb20gXCJjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgeyBDbG9zZUZuIGFzIEZnQ2xvc2VGbiwgcHJveHkgYXMgZmdDaGlsZFByb3h5IH0gZnJvbSBcImRlbXVyZ29zLWZvcmVncm91bmQtY2hpbGRcIjtcbmltcG9ydCBmaW5kVXAgZnJvbSBcImZpbmQtdXBcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IGZyb21TeXNQYXRoLCB0b1N5c1BhdGggfSBmcm9tIFwiZnVyaVwiO1xuaW1wb3J0IHN5c1BhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCBFeGNsdWRlIGZyb20gXCJ0ZXN0LWV4Y2x1ZGVcIjtcbmltcG9ydCB1cmxNb2QgZnJvbSBcInVybFwiO1xuaW1wb3J0IHZpbnlsRnMgZnJvbSBcInZpbnlsLWZzXCI7XG5pbXBvcnQgeWFyZ3MgZnJvbSBcInlhcmdzXCI7XG5pbXBvcnQgeyBhc3luY0RvbmVQcm9taXNlIH0gZnJvbSBcIi4vYXN5bmMtZG9uZS1wcm9taXNlXCI7XG5pbXBvcnQgeyBDb3ZlcmFnZUZpbHRlciwgZnJvbUdsb2IgfSBmcm9tIFwiLi9maWx0ZXJcIjtcbmltcG9ydCB7IEdldFRleHQsIGdldFRleHQgYXMgZGVmYXVsdEdldFRleHQsIEdldFRleHRTeW5jLCBnZXRUZXh0U3luY0Zyb21Tb3VyY2VTdG9yZSB9IGZyb20gXCIuL2dldC10ZXh0XCI7XG5pbXBvcnQgeyBjcmVhdGVSZXBvcnRlciwgcmVwb3J0U3RyZWFtLCByZXBvcnRWaW55bCB9IGZyb20gXCIuL3JlcG9ydFwiO1xuaW1wb3J0IHsgUmVwb3J0ZXIsIFN0cmVhbVJlcG9ydGVyLCBWaW55bFJlcG9ydGVyIH0gZnJvbSBcIi4vcmVwb3J0ZXJcIjtcbmltcG9ydCB7IERFRkFVTFRfUkVHSVNUUlkgfSBmcm9tIFwiLi9yZXBvcnRlci1yZWdpc3RyeVwiO1xuaW1wb3J0IHsgUmljaFByb2Nlc3NDb3YsIHNwYXduSW5zcGVjdGVkIH0gZnJvbSBcIi4vc3Bhd24taW5zcGVjdGVkXCI7XG5pbXBvcnQgeyBwcm9jZXNzQ292c1RvSXN0YW5idWwgfSBmcm9tIFwiLi90by1pc3RhbmJ1bFwiO1xuaW1wb3J0IHsgVkVSU0lPTiB9IGZyb20gXCIuL3ZlcnNpb25cIjtcblxuY29uc3QgREVGQVVMVF9HTE9CUzogUmVhZG9ubHlBcnJheTxzdHJpbmc+ID0gRXhjbHVkZS5kZWZhdWx0RXhjbHVkZS5tYXAoKHBhdHRlcm46IHN0cmluZykgPT4gYCEke3BhdHRlcm59YCk7XG5cbmludGVyZmFjZSBXYXRlcm1hcmtzIHtcbiAgbGluZXM6IFtudW1iZXIsIG51bWJlcl07XG4gIGZ1bmN0aW9uczogW251bWJlciwgbnVtYmVyXTtcbiAgYnJhbmNoZXM6IFtudW1iZXIsIG51bWJlcl07XG4gIHN0YXRlbWVudHM6IFtudW1iZXIsIG51bWJlcl07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmlsZUNvbmZpZyB7XG4gIHJlcG9ydGVycz86IFJlYWRvbmx5QXJyYXk8c3RyaW5nPjtcbiAgZ2xvYnM/OiBSZWFkb25seUFycmF5PHN0cmluZz47XG4gIGNvdmVyYWdlRGlyPzogc3RyaW5nO1xuICB3YXRlck1hcmtzPzogV2F0ZXJtYXJrcztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDbGlDb25maWcge1xuICByZXBvcnRlcnM/OiBSZWFkb25seUFycmF5PHN0cmluZz47XG4gIGdsb2JzPzogUmVhZG9ubHlBcnJheTxzdHJpbmc+O1xuICBjb3ZlcmFnZURpcj86IHN0cmluZztcbiAgY29tbWFuZDogUmVhZG9ubHlBcnJheTxzdHJpbmc+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlc29sdmVkQ29uZmlnIHtcbiAgcmVwb3J0ZXJzOiBSZWFkb25seUFycmF5PHN0cmluZz47XG4gIGdsb2JzOiBSZWFkb25seUFycmF5PHN0cmluZz47XG4gIGNvdmVyYWdlRGlyOiBzdHJpbmc7XG4gIHdhdGVyTWFya3M6IFdhdGVybWFya3M7XG4gIGNvbW1hbmQ6IFJlYWRvbmx5QXJyYXk8c3RyaW5nPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZXNzYWdlQWN0aW9uIHtcbiAgYWN0aW9uOiBcIm1lc3NhZ2VcIjtcbiAgbWVzc2FnZTogc3RyaW5nO1xuICBlcnJvcj86IEVycm9yO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJ1bkFjdGlvbiB7XG4gIGFjdGlvbjogXCJydW5cIjtcbiAgY29uZmlnOiBSZXNvbHZlZENvbmZpZztcbn1cblxuZXhwb3J0IHR5cGUgQ2xpQWN0aW9uID0gTWVzc2FnZUFjdGlvbiB8IFJ1bkFjdGlvbjtcblxuZXhwb3J0IHR5cGUgUGFyc2VBcmdzUmVzdWx0ID0gTWVzc2FnZUFjdGlvbiB8IHthY3Rpb246IFwicnVuXCI7IGNvbmZpZzogQ2xpQ29uZmlnfTtcblxuY29uc3QgREVGQVVMVF9XQVRFUk1BUktTOiBXYXRlcm1hcmtzID0gT2JqZWN0LmZyZWV6ZSh7XG4gIGxpbmVzOiBbODAsIDk1XSBhcyBbbnVtYmVyLCBudW1iZXJdLFxuICBmdW5jdGlvbnM6IFs4MCwgOTVdIGFzIFtudW1iZXIsIG51bWJlcl0sXG4gIGJyYW5jaGVzOiBbODAsIDk1XSBhcyBbbnVtYmVyLCBudW1iZXJdLFxuICBzdGF0ZW1lbnRzOiBbODAsIDk1XSBhcyBbbnVtYmVyLCBudW1iZXJdLFxufSk7XG5cbi8vIFRPRE86IEZpeCB5YXJncyB0eXBlIGRlZmluaXRpb25cbmNvbnN0IEFSR19QQVJTRVI6IHlhcmdzLkFyZ3YgPSB5YXJncygpIGFzIGFueTtcblxuQVJHX1BBUlNFUlxuICAuc2NyaXB0TmFtZShcImM4OFwiKVxuICAudmVyc2lvbihWRVJTSU9OKVxuICAudXNhZ2UoXCIkMCBbb3B0c10gW3NjcmlwdF0gW29wdHNdXCIpXG4gIC5sb2NhbGUoXCJlblwiKVxuICAub3B0aW9uKFwicmVwb3J0ZXJcIiwge1xuICAgIGFsaWFzOiBcInJcIixcbiAgICBkZXNjcmliZTogXCJjb3ZlcmFnZSByZXBvcnRlcihzKSB0byB1c2VcIixcbiAgICBkZWZhdWx0OiBcInRleHRcIixcbiAgfSlcbiAgLm9wdGlvbihcIm1hdGNoXCIsIHtcbiAgICBhbGlhczogXCJtXCIsXG4gICAgZGVmYXVsdDogREVGQVVMVF9HTE9CUyxcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bWF4LWxpbmUtbGVuZ3RoXG4gICAgZGVzY3JpYmU6IFwiYSBsaXN0IG9mIHNwZWNpZmljIGZpbGVzIGFuZCBkaXJlY3RvcmllcyB0aGF0IHNob3VsZCBiZSBtYXRjaGVkLCBnbG9iIHBhdHRlcm5zIGFyZSBzdXBwb3J0ZWQuXCIsXG4gIH0pXG4gIC5vcHRpb24oXCJjb3ZlcmFnZS1kaXJlY3RvcnlcIiwge1xuICAgIGRlZmF1bHQ6IFwiY292ZXJhZ2VcIixcbiAgICBkZXNjcmliZTogXCJkaXJlY3RvcnkgdG8gb3V0cHV0IGNvdmVyYWdlIEpTT04gYW5kIHJlcG9ydHNcIixcbiAgfSlcbiAgLnBrZ0NvbmYoXCJjODhcIilcbiAgLmRlbWFuZENvbW1hbmQoMSlcbiAgLmVwaWxvZyhcInZpc2l0IGh0dHBzOi8vZ2l0LmlvL3ZIeXNBIGZvciBsaXN0IG9mIGF2YWlsYWJsZSByZXBvcnRlcnNcIik7XG5cbi8vIHRzbGludDpkaXNhYmxlOndoaXRlc3BhY2VcblxuLyoqXG4gKiBFeGVjdXRlcyB0aGUgYzg4IENMSVxuICpcbiAqIEBwYXJhbSBhcmdzIENMSSBhcmd1bWVudHNcbiAqIEBwYXJhbSBjd2QgQ3VycmVudCB3b3JraW5nIGRpcmVjdG9yeVxuICogQHBhcmFtIHByb2MgQ3VycmVudCBwcm9jZXNzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBleGVjQ2xpKGFyZ3M6IHN0cmluZ1tdLCBjd2Q6IHN0cmluZywgcHJvYzogTm9kZUpTLlByb2Nlc3MpOiBQcm9taXNlPG51bWJlcj4ge1xuICBjb25zdCBhY3Rpb246IENsaUFjdGlvbiA9IGF3YWl0IGdldEFjdGlvbihhcmdzLCBjd2QpO1xuXG4gIHN3aXRjaCAoYWN0aW9uLmFjdGlvbikge1xuICAgIGNhc2UgXCJtZXNzYWdlXCI6XG4gICAgICBwcm9jZXNzLnN0ZGVyci53cml0ZShCdWZmZXIuZnJvbShhY3Rpb24ubWVzc2FnZSkpO1xuICAgICAgcmV0dXJuIGFjdGlvbi5lcnJvciA9PT0gdW5kZWZpbmVkID8gMCA6IDE7XG4gICAgY2FzZSBcInJ1blwiOlxuICAgICAgcmV0dXJuIGV4ZWNSdW5BY3Rpb24oYWN0aW9uLCBjd2QsIHByb2MpO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEFzc2VydGlvbkVycm9yOiBVbmV4cGVjdGVkIFxcYGFjdGlvblxcYDogJHsoYWN0aW9uIGFzIGFueSkuYWN0aW9ufWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDb25maWcoZmlsZUNvbmZpZzogRmlsZUNvbmZpZywgY2xpQ29uZmlnOiBDbGlDb25maWcpOiBSZXNvbHZlZENvbmZpZyB7XG4gIHJldHVybiB7XG4gICAgY29tbWFuZDogY2xpQ29uZmlnLmNvbW1hbmQsXG4gICAgcmVwb3J0ZXJzOiBjbGlDb25maWcucmVwb3J0ZXJzICE9PSB1bmRlZmluZWQgPyBjbGlDb25maWcucmVwb3J0ZXJzIDogW1widGV4dFwiXSxcbiAgICBnbG9iczogY2xpQ29uZmlnLmdsb2JzICE9PSB1bmRlZmluZWQgPyBjbGlDb25maWcuZ2xvYnMgOiBERUZBVUxUX0dMT0JTLFxuICAgIHdhdGVyTWFya3M6IGZpbGVDb25maWcud2F0ZXJNYXJrcyAhPT0gdW5kZWZpbmVkID8gZmlsZUNvbmZpZy53YXRlck1hcmtzIDogREVGQVVMVF9XQVRFUk1BUktTLFxuICAgIGNvdmVyYWdlRGlyOiBjbGlDb25maWcuY292ZXJhZ2VEaXIgIT09IHVuZGVmaW5lZCA/IGNsaUNvbmZpZy5jb3ZlcmFnZURpciA6IFwiY292ZXJhZ2VcIixcbiAgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZXhlY1J1bkFjdGlvbih7Y29uZmlnfTogUnVuQWN0aW9uLCBjd2Q6IHN0cmluZywgcHJvYzogTm9kZUpTLlByb2Nlc3MpOiBQcm9taXNlPG51bWJlcj4ge1xuICBjb25zdCBmaWxlOiBzdHJpbmcgPSBjb25maWcuY29tbWFuZFswXTtcbiAgY29uc3QgYXJnczogc3RyaW5nW10gPSBjb25maWcuY29tbWFuZC5zbGljZSgxKTtcbiAgY29uc3QgZmlsdGVyOiBDb3ZlcmFnZUZpbHRlciA9IGZyb21HbG9iKHtwYXR0ZXJuczogY29uZmlnLmdsb2JzLCBiYXNlOiBmcm9tU3lzUGF0aChjd2QpfSk7XG5cbiAgY29uc3Qgc3ViUHJvY2Vzc0V4aXQ6IERlZmVycmVkUHJvbWlzZTxudW1iZXI+ID0gZGVmZXJQcm9taXNlKCk7XG5cbiAgYXN5bmMgZnVuY3Rpb24gb25Sb290UHJvY2VzcyhpbnNwZWN0ZWRQcm9jOiBjcC5DaGlsZFByb2Nlc3MpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjbG9zZUZuOiBGZ0Nsb3NlRm4gPSBhd2FpdCBmZ0NoaWxkUHJveHkocHJvYywgaW5zcGVjdGVkUHJvYyk7XG4gICAgaWYgKGNsb3NlRm4uc2lnbmFsICE9PSBudWxsKSB7XG4gICAgICBzdWJQcm9jZXNzRXhpdC5yZWplY3QobmV3IEVycm9yKGBQcm9jZXNzIGtpbGxlZCBieSBzaWduYWw6ICR7Y2xvc2VGbi5zaWduYWx9YCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdWJQcm9jZXNzRXhpdC5yZXNvbHZlKGNsb3NlRm4uY29kZSEpO1xuICAgIH1cbiAgfVxuXG4gIGxldCBwcm9jZXNzQ292czogUmljaFByb2Nlc3NDb3ZbXTtcbiAgdHJ5IHtcbiAgICBwcm9jZXNzQ292cyA9IGF3YWl0IHNwYXduSW5zcGVjdGVkKGZpbGUsIGFyZ3MsIHtmaWx0ZXIsIG9uUm9vdFByb2Nlc3N9KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgcHJvYy5zdGRlcnIud3JpdGUoQnVmZmVyLmZyb20oYCR7ZXJyLnRvU3RyaW5nKCl9XFxuYCkpO1xuICAgIHJldHVybiAxO1xuICB9XG4gIGNvbnN0IGV4aXRDb2RlOiBudW1iZXIgPSBhd2FpdCBzdWJQcm9jZXNzRXhpdC5wcm9taXNlO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgcmVwb3J0ZXI6IFJlcG9ydGVyID0gY3JlYXRlUmVwb3J0ZXIoREVGQVVMVF9SRUdJU1RSWSwgY29uZmlnLnJlcG9ydGVycywge3dhdGVyTWFya3M6IGNvbmZpZy53YXRlck1hcmtzfSk7XG4gICAgY29uc3QgcmVzb2x2ZWRDb3ZlcmFnZURpcjogc3RyaW5nID0gc3lzUGF0aC5qb2luKGN3ZCwgY29uZmlnLmNvdmVyYWdlRGlyKTtcbiAgICBjb25zdCBjb3ZlcmFnZURpcjogdXJsTW9kLlVSTCA9IGZyb21TeXNQYXRoKHJlc29sdmVkQ292ZXJhZ2VEaXIpO1xuICAgIGF3YWl0IHJlcG9ydChyZXBvcnRlciwgcHJvY2Vzc0NvdnMsIHByb2Muc3Rkb3V0LCBjb3ZlcmFnZURpcik7XG4gICAgcmV0dXJuIGV4aXRDb2RlO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBwcm9jLnN0ZGVyci53cml0ZShCdWZmZXIuZnJvbShlcnIudG9TdHJpbmcoKSArIFwiXFxuXCIpKTtcbiAgICByZXR1cm4gTWF0aC5tYXgoMSwgZXhpdENvZGUpO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXBvcnQoXG4gIHJlcG9ydGVyOiBSZXBvcnRlcixcbiAgcHJvY2Vzc0NvdnM6IFJlYWRvbmx5QXJyYXk8UmljaFByb2Nlc3NDb3Y+LFxuICBvdXRTdHJlYW06IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSxcbiAgb3V0RGlyOiBSZWFkb25seTx1cmxNb2QuVVJMPixcbiAgZ2V0VGV4dDogR2V0VGV4dCA9IGRlZmF1bHRHZXRUZXh0LFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHtjb3ZlcmFnZU1hcCwgc291cmNlc30gPSBhd2FpdCBwcm9jZXNzQ292c1RvSXN0YW5idWwocHJvY2Vzc0NvdnMsIGdldFRleHQpO1xuICBjb25zdCBnZXRTb3VyY2VzU3luYzogR2V0VGV4dFN5bmMgPSBnZXRUZXh0U3luY0Zyb21Tb3VyY2VTdG9yZShzb3VyY2VzKTtcblxuICBjb25zdCB0YXNrczogUHJvbWlzZTx2b2lkPltdID0gW107XG4gIGlmIChyZXBvcnRlci5yZXBvcnRTdHJlYW0gIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IHN0cmVhbTogTm9kZUpTLlJlYWRhYmxlU3RyZWFtID0gcmVwb3J0U3RyZWFtKHJlcG9ydGVyIGFzIFN0cmVhbVJlcG9ydGVyLCBjb3ZlcmFnZU1hcCwgZ2V0U291cmNlc1N5bmMpO1xuICAgIHRhc2tzLnB1c2gocGlwZURhdGEoc3RyZWFtLCBvdXRTdHJlYW0pKTtcbiAgfVxuICBpZiAocmVwb3J0ZXIucmVwb3J0VmlueWwgIT09IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IHN0cmVhbTogTm9kZUpTLlJlYWRhYmxlU3RyZWFtID0gcmVwb3J0VmlueWwocmVwb3J0ZXIgYXMgVmlueWxSZXBvcnRlciwgY292ZXJhZ2VNYXAsIGdldFNvdXJjZXNTeW5jKVxuICAgICAgLnBpcGUodmlueWxGcy5kZXN0KHRvU3lzUGF0aChvdXREaXIuaHJlZikpKTtcbiAgICB0YXNrcy5wdXNoKGFzeW5jRG9uZVByb21pc2UoKCkgPT4gc3RyZWFtKSk7XG4gIH1cblxuICBhd2FpdCBQcm9taXNlLmFsbCh0YXNrcyk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRBY3Rpb24oYXJnczogc3RyaW5nW10sIGN3ZDogc3RyaW5nKTogUHJvbWlzZTxDbGlBY3Rpb24+IHtcbiAgY29uc3QgcGFyc2VkOiBQYXJzZUFyZ3NSZXN1bHQgPSBwYXJzZUFyZ3MoYXJncyk7XG4gIGlmIChwYXJzZWQuYWN0aW9uICE9PSBcInJ1blwiKSB7XG4gICAgcmV0dXJuIHBhcnNlZDtcbiAgfVxuICBjb25zdCBmaWxlQ29uZmlnOiBGaWxlQ29uZmlnID0gYXdhaXQgcmVhZENvbmZpZ0ZpbGUoY3dkKTtcbiAgcmV0dXJuIHtcbiAgICBhY3Rpb246IFwicnVuXCIsXG4gICAgY29uZmlnOiByZXNvbHZlQ29uZmlnKGZpbGVDb25maWcsIHBhcnNlZC5jb25maWcpLFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VBcmdzKGFyZ3M6IHN0cmluZ1tdKTogUGFyc2VBcmdzUmVzdWx0IHtcbiAgLy8gVGhlIHlhcmdzIHB1cmUgQVBJIGlzIGtpbmRhIHN0cmFuZ2UgdG8gdXNlIChhcGFydCBmcm9tIHJlcXVpcmluZyBhIGNhbGxiYWNrKTpcbiAgLy8gVGhlIGVycm9yIGNhbiBlaXRoZXIgYmUgZGVmaW5lZCwgYHVuZGVmaW5lZGAgb3IgYG51bGxgLlxuICAvLyBJZiBpdCBpcyBkZWZpbmVkIG9yIGBudWxsYCwgdGhlbiBgb3V0cHV0YCBzaG91bGQgYmUgYSBub24tZW1wdHkgc3RyaW5nXG4gIC8vIGludGVuZGVkIHRvIGJlIHdyaXR0ZW4gdG8gc3RkZXJyLiBgcGFyc2VkYCBpcyBkZWZpbmVkIGJ1dCBpdCBzaG91bGQgYmVcbiAgLy8gaWdub3JlZCBpbiB0aGlzIGNhc2UuXG4gIC8vIElmIGBlcnJgIGlzIGB1bmRlZmluZWRgLCB0aGVuIGBvdXRwdXRgIGlzIGFuIGVtcHR5IHN0cmluZyBhbmQgYHBhcnNlZGBcbiAgLy8gY29udGFpbnMgdGhlIHN1Y2Nlc2Z1bGx5IHBhcnNlZCBhcmdzLlxuICAvLyB0c2xpbnQ6ZGlzYWJsZTp2YXJpYWJsZS1uYW1lXG4gIGxldCBfZXJyOiBFcnJvciB8IHVuZGVmaW5lZCB8IG51bGw7XG4gIGxldCBfcGFyc2VkOiBhbnk7XG4gIGxldCBfb3V0cHV0OiBzdHJpbmc7XG4gIGxldCBpc1BhcnNlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBBUkdfUEFSU0VSLnBhcnNlKGFyZ3MsIChlcnI6IEVycm9yIHwgdW5kZWZpbmVkIHwgbnVsbCwgcGFyc2VkOiBhbnksIG91dHB1dDogc3RyaW5nKTogdm9pZCA9PiB7XG4gICAgX2VyciA9IGVycjtcbiAgICBfcGFyc2VkID0gcGFyc2VkO1xuICAgIF9vdXRwdXQgPSBvdXRwdXQ7XG4gICAgaXNQYXJzZWQgPSB0cnVlO1xuICB9KTtcbiAgYXNzZXJ0KGlzUGFyc2VkKTtcbiAgY29uc3QgZXJyOiBFcnJvciB8IHVuZGVmaW5lZCB8IG51bGwgPSBfZXJyITtcbiAgY29uc3QgcGFyc2VkOiBhbnkgPSBfcGFyc2VkITtcbiAgY29uc3Qgb3V0cHV0OiBzdHJpbmcgPSBfb3V0cHV0ITtcbiAgaWYgKGVyciA9PT0gbnVsbCkge1xuICAgIC8vIFN1Y2Nlc3NmdWxseSBwYXJzZWRcbiAgICByZXR1cm4ge1xuICAgICAgYWN0aW9uOiBcInJ1blwiLFxuICAgICAgY29uZmlnOiB7XG4gICAgICAgIGNvbW1hbmQ6IHBhcnNlZC5fLFxuICAgICAgICByZXBvcnRlcnM6IEFycmF5LmlzQXJyYXkocGFyc2VkLnJlcG9ydGVyKSA/IHBhcnNlZC5yZXBvcnRlciA6IFtwYXJzZWQucmVwb3J0ZXJdLFxuICAgICAgICBnbG9iczogcGFyc2VkLm1hdGNoLFxuICAgICAgfSxcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB7YWN0aW9uOiBcIm1lc3NhZ2VcIiwgbWVzc2FnZTogb3V0cHV0LCBlcnJvcjogZXJyfTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZWFkQ29uZmlnRmlsZShjd2Q6IHN0cmluZyk6IFByb21pc2U8RmlsZUNvbmZpZz4ge1xuICBjb25zdCBjb25maWdQYXRoOiBzdHJpbmcgfCBudWxsID0gZmluZFVwLnN5bmMoW1wiLmM4OHJjXCIsIFwiLmM4OHJjLmpzb25cIl0pO1xuICBpZiAoY29uZmlnUGF0aCA9PT0gbnVsbCkge1xuICAgIHJldHVybiBPYmplY3QuY3JlYXRlKG51bGwpO1xuICB9XG4gIHJldHVybiBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhjb25maWdQYXRoLCBcIlVURi04XCIpKTtcbn1cblxuaW50ZXJmYWNlIERlZmVycmVkUHJvbWlzZTxUPiB7XG4gIHByb21pc2U6IFByb21pc2U8VD47XG5cbiAgcmVzb2x2ZSh2YWx1ZTogVCk6IHZvaWQ7XG5cbiAgcmVqZWN0KHJlYXNvbjogYW55KTogdm9pZDtcbn1cblxuZnVuY3Rpb24gZGVmZXJQcm9taXNlPFQ+KCk6IERlZmVycmVkUHJvbWlzZTxUPiB7XG4gIGxldCByZXNvbHZlOiAodmFsdWU6IFQpID0+IHZvaWQ7XG4gIGxldCByZWplY3Q6IChyZWFzb246IGFueSkgPT4gdm9pZDtcbiAgY29uc3QgcHJvbWlzZTogUHJvbWlzZTxUPiA9IG5ldyBQcm9taXNlPFQ+KChyZXMsIHJlaikgPT4ge1xuICAgIHJlc29sdmUgPSByZXM7XG4gICAgcmVqZWN0ID0gcmVqO1xuICB9KTtcbiAgcmV0dXJuIHtyZXNvbHZlOiByZXNvbHZlISwgcmVqZWN0OiByZWplY3QhLCBwcm9taXNlfTtcbn1cblxuZnVuY3Rpb24gcGlwZURhdGEoc3JjOiBOb2RlSlMuUmVhZGFibGVTdHJlYW0sIGRlc3Q6IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSk6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHNyYy5vbihcImRhdGFcIiwgY2h1bmsgPT4gZGVzdC53cml0ZShjaHVuaykpO1xuICAgIHNyYy5vbihcImVycm9yXCIsIHJlamVjdCk7XG4gICAgc3JjLm9uKFwiZW5kXCIsIHJlc29sdmUpO1xuICB9KTtcbn1cbiJdLCJzb3VyY2VSb290IjoiIn0=