UNPKG

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