UNPKG

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