1 | ;
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.unzipInDir = exports.processZip = exports.packer = void 0;
|
4 | const fs_extra_1 = require("fs-extra");
|
5 | const path = require("path");
|
6 | const path_1 = require("path");
|
7 | const stream_1 = require("stream");
|
8 | const webpack = require("webpack");
|
9 | const yauzl = require("yauzl");
|
10 | const error_1 = require("./error");
|
11 | const log_1 = require("./log");
|
12 | const provider_1 = require("./provider");
|
13 | const shared_1 = require("./shared");
|
14 | const wrapper_1 = require("./wrapper");
|
15 | const webpack_merge_1 = require("webpack-merge");
|
16 | const MemoryFileSystem = require("memory-fs");
|
17 | const archiver = require("archiver");
|
18 | function getUrlEncodedQueryParameters(options) {
|
19 | return (0, shared_1.keysOf)(options)
|
20 | .filter(key => options[key])
|
21 | .map(key => `${key}=${encodeURIComponent(JSON.stringify(options[key]))}`)
|
22 | .join(`&`);
|
23 | }
|
24 | async function packer(trampolineFactory, functionModule, userOptions, userWrapperOptions, FunctionName) {
|
25 | const options = { ...provider_1.commonDefaults, ...userOptions };
|
26 | const wrapperOptions = { ...wrapper_1.WrapperOptionDefaults, ...userWrapperOptions };
|
27 | const { webpackOptions, packageJson } = options;
|
28 | log_1.log.info(`Running webpack`);
|
29 | const mfs = new MemoryFileSystem();
|
30 | function addToArchive(root, archive) {
|
31 | function addEntry(entry) {
|
32 | const statEntry = mfs.statSync(entry);
|
33 | if (statEntry.isDirectory()) {
|
34 | for (const subEntry of mfs.readdirSync(entry)) {
|
35 | const subEntryPath = path.join(entry, subEntry);
|
36 | addEntry(subEntryPath);
|
37 | }
|
38 | }
|
39 | else if (statEntry.isFile()) {
|
40 | log_1.log.info(`Adding file: ${entry}`);
|
41 | archive.append(mfs.createReadStream(entry), {
|
42 | name: path.relative(root, entry)
|
43 | });
|
44 | }
|
45 | }
|
46 | addEntry(root);
|
47 | }
|
48 | async function addPackageJson(packageJsonFile) {
|
49 | const parsedPackageJson = typeof packageJsonFile === "string"
|
50 | ? JSON.parse((await (0, fs_extra_1.readFile)(await resolvePath(packageJsonFile))).toString())
|
51 | : { ...packageJsonFile };
|
52 | parsedPackageJson.main = "index.js";
|
53 | mfs.writeFileSync("/package.json", JSON.stringify(parsedPackageJson, undefined, 2));
|
54 | return Object.keys(parsedPackageJson.dependencies || {});
|
55 | }
|
56 | async function resolvePath(pathName) {
|
57 | if (await (0, fs_extra_1.pathExists)(pathName)) {
|
58 | return pathName;
|
59 | }
|
60 | throw new error_1.FaastError(`Could not find "${pathName}"`);
|
61 | }
|
62 | async function processIncludeExclude(archive, include, exclude) {
|
63 | for (const name of include) {
|
64 | let cwd = ".";
|
65 | let entry;
|
66 | if (typeof name === "string") {
|
67 | entry = name;
|
68 | }
|
69 | else {
|
70 | cwd = name.cwd || ".";
|
71 | entry = name.path;
|
72 | }
|
73 | try {
|
74 | const resolvedPath = path.resolve(cwd, entry);
|
75 | const entryStat = await (0, fs_extra_1.stat)(resolvedPath);
|
76 | if (entryStat.isDirectory()) {
|
77 | entry = (0, path_1.join)(entry, "/**/*");
|
78 | }
|
79 | }
|
80 | catch { }
|
81 | archive.glob(entry, { ignore: exclude, cwd });
|
82 | }
|
83 | }
|
84 | async function prepareZipArchive() {
|
85 | const archive = archiver("zip", { zlib: { level: 8 } });
|
86 | archive.on("error", err => log_1.log.warn(err));
|
87 | archive.on("warning", err => log_1.log.warn(err));
|
88 | addToArchive("/", archive);
|
89 | const { include, exclude } = options;
|
90 | await processIncludeExclude(archive, include, exclude);
|
91 | archive.finalize();
|
92 | return { archive };
|
93 | }
|
94 | const dependencies = (packageJson && (await addPackageJson(packageJson))) || [];
|
95 | function runWebpack(entry, entryName) {
|
96 | const coreConfig = {
|
97 | entry: { [entryName]: entry },
|
98 | mode: "development",
|
99 | output: {
|
100 | path: "/",
|
101 | filename: "[name].js",
|
102 | libraryTarget: "commonjs2"
|
103 | },
|
104 | target: "node",
|
105 | resolveLoader: { modules: [__dirname, `${__dirname}/dist`] },
|
106 | node: { global: true, __dirname: false, __filename: false }
|
107 | };
|
108 | const dependencyExternals = {
|
109 | externals: [...dependencies, ...dependencies.map(d => new RegExp(`^${d}/.*`))]
|
110 | };
|
111 | const config = (0, webpack_merge_1.merge)(coreConfig, dependencyExternals, webpackOptions);
|
112 | log_1.log.webpack(`webpack config: %O`, config);
|
113 | const compiler = webpack(config);
|
114 | compiler.outputFileSystem = mfs;
|
115 | return new Promise((resolve, reject) => compiler.run((err, stats) => {
|
116 | if (err) {
|
117 | reject(err);
|
118 | }
|
119 | else {
|
120 | if (stats?.hasErrors() || stats?.hasWarnings()) {
|
121 | const c = stats.compilation;
|
122 | const messages = [];
|
123 | if (c.warnings.length > 0) {
|
124 | messages.push(`${c.warnings.length} warning(s)`);
|
125 | }
|
126 | if (c.errors.length > 0) {
|
127 | messages.push(`${c.errors.length} error(s)`);
|
128 | }
|
129 | log_1.log.warn(`webpack had ${messages.join(" and ")}`);
|
130 | log_1.log.warn(`set environment variable DEBUG=faast:webpack for details`);
|
131 | log_1.log.warn(`see https://faastjs.org/docs/api/faastjs.commonoptions.packagejson`);
|
132 | }
|
133 | if (log_1.log.webpack.enabled) {
|
134 | log_1.log.webpack(stats?.toString());
|
135 | log_1.log.webpack(`Memory filesystem: `);
|
136 | for (const file of Object.keys(mfs.data)) {
|
137 | log_1.log.webpack(` ${file}: ${mfs.data[file].length}`);
|
138 | }
|
139 | }
|
140 | resolve();
|
141 | }
|
142 | }));
|
143 | }
|
144 | const { childProcess, validateSerialization } = options;
|
145 | const { wrapperVerbose, childProcess: _onlyUsedForLocalProviderDirectWrapperInstantiation, childDir, childProcessMemoryLimitMb, childProcessTimeoutMs, childProcessEnvironment: _onlyUsedForLocalProviderDirectWrapperInstantiation2, wrapperLog: _onlyUsedForLocalProviderDirectWrapperInstantiation3, validateSerialization: _ignoredInFavorOfCommonOptionsSetting, ...rest } = wrapperOptions;
|
146 | const _exhaustiveCheck2 = {};
|
147 | const isVerbose = wrapperVerbose || log_1.log.provider.enabled;
|
148 | const loader = `loader?${getUrlEncodedQueryParameters({
|
149 | trampolineFactoryModule: trampolineFactory.filename,
|
150 | wrapperOptions: {
|
151 | wrapperVerbose: isVerbose,
|
152 | childProcess,
|
153 | childDir,
|
154 | childProcessMemoryLimitMb,
|
155 | childProcessTimeoutMs,
|
156 | validateSerialization
|
157 | },
|
158 | functionModule
|
159 | })}!`;
|
160 | try {
|
161 | await runWebpack(loader, "index");
|
162 | }
|
163 | catch (err) {
|
164 | throw new error_1.FaastError(err, "failed running webpack");
|
165 | }
|
166 | try {
|
167 | let { archive } = await prepareZipArchive();
|
168 | const packageDir = process.env["FAAST_PACKAGE_DIR"];
|
169 | if (packageDir) {
|
170 | log_1.log.webpack(`FAAST_PACKAGE_DIR: ${packageDir}`);
|
171 | const packageFile = (0, path_1.join)(packageDir, FunctionName) + ".zip";
|
172 | await (0, fs_extra_1.ensureDir)(packageDir);
|
173 | const writeStream = (0, fs_extra_1.createWriteStream)(packageFile);
|
174 | const passThrough = archive.pipe(new stream_1.PassThrough());
|
175 | archive = archive.pipe(new stream_1.PassThrough());
|
176 | passThrough.pipe(writeStream);
|
177 | writeStream.on("close", () => {
|
178 | log_1.log.info(`Wrote ${packageFile}`);
|
179 | });
|
180 | }
|
181 | return { archive };
|
182 | }
|
183 | catch (err) {
|
184 | throw new error_1.FaastError(err, "failed creating zip archive");
|
185 | }
|
186 | }
|
187 | exports.packer = packer;
|
188 | /**
|
189 | * @param {NodeJS.ReadableStream | string} archive A zip archive as a stream or a filename
|
190 | * @param {(filename: string, contents: Readable) => void} processEntry Every
|
191 | * entry's contents must be consumed, otherwise the next entry won't be read.
|
192 | */
|
193 | async function processZip(archive, processEntry) {
|
194 | let zip;
|
195 | if (typeof archive === "string") {
|
196 | zip = await new Promise((resolve, reject) => yauzl.open(archive, { lazyEntries: true }, (err, zipfile) => err ? reject(err) : resolve(zipfile)));
|
197 | }
|
198 | else {
|
199 | const buf = await (0, shared_1.streamToBuffer)(archive);
|
200 | zip = await new Promise((resolve, reject) => yauzl.fromBuffer(buf, { lazyEntries: true }, (err, zipfile) => err ? reject(err) : resolve(zipfile)));
|
201 | }
|
202 | return new Promise((resolve, reject) => {
|
203 | zip.readEntry();
|
204 | zip.on("entry", (entry) => {
|
205 | if (/\/$/.test(entry.fileName)) {
|
206 | zip.readEntry();
|
207 | }
|
208 | else {
|
209 | zip.openReadStream(entry, (err, readStream) => {
|
210 | if (err) {
|
211 | reject(err);
|
212 | return;
|
213 | }
|
214 | readStream.on("end", () => zip.readEntry());
|
215 | processEntry(entry.fileName, readStream, entry.externalFileAttributes >>> 16);
|
216 | });
|
217 | }
|
218 | });
|
219 | zip.on("end", resolve);
|
220 | });
|
221 | }
|
222 | exports.processZip = processZip;
|
223 | async function unzipInDir(dir, archive) {
|
224 | await (0, fs_extra_1.mkdirp)(dir);
|
225 | let total = 0;
|
226 | await processZip(archive, async (filename, contents, mode) => {
|
227 | const destinationFilename = path.join(dir, filename);
|
228 | const { dir: outputDir } = path.parse(destinationFilename);
|
229 | if (!(await (0, fs_extra_1.pathExists)(outputDir))) {
|
230 | await (0, fs_extra_1.mkdirp)(outputDir);
|
231 | }
|
232 | const stream = (0, fs_extra_1.createWriteStream)(destinationFilename, { mode });
|
233 | contents.on("data", chunk => (total += chunk.length));
|
234 | contents.pipe(stream);
|
235 | });
|
236 | return total;
|
237 | }
|
238 | exports.unzipInDir = unzipInDir;
|
239 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFja2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BhY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSx1Q0FPa0I7QUFDbEIsNkJBQTZCO0FBQzdCLCtCQUE0QjtBQUM1QixtQ0FBK0M7QUFDL0MsbUNBQW1DO0FBQ25DLCtCQUErQjtBQUMvQixtQ0FBcUM7QUFFckMsK0JBQTRCO0FBQzVCLHlDQUEwRTtBQUMxRSxxQ0FBa0Q7QUFDbEQsdUNBQXFGO0FBQ3JGLGlEQUFzQztBQUl0Qyw4Q0FBK0M7QUFDL0MscUNBQXNDO0FBTXRDLFNBQVMsNEJBQTRCLENBQUMsT0FBc0I7SUFDeEQsT0FBTyxJQUFBLGVBQU0sRUFBQyxPQUFPLENBQUM7U0FDakIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQzNCLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxJQUFJLGtCQUFrQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQ3hFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNuQixDQUFDO0FBRU0sS0FBSyxVQUFVLE1BQU0sQ0FDeEIsaUJBQW9DLEVBQ3BDLGNBQXNCLEVBQ3RCLFdBQTBCLEVBQzFCLGtCQUFrQyxFQUNsQyxZQUFvQjtJQUVwQixNQUFNLE9BQU8sR0FBRyxFQUFFLEdBQUcseUJBQWMsRUFBRSxHQUFHLFdBQVcsRUFBRSxDQUFDO0lBQ3RELE1BQU0sY0FBYyxHQUFHLEVBQUUsR0FBRywrQkFBcUIsRUFBRSxHQUFHLGtCQUFrQixFQUFFLENBQUM7SUFDM0UsTUFBTSxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUUsR0FBRyxPQUFPLENBQUM7SUFFaEQsU0FBRyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQzVCLE1BQU0sR0FBRyxH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LEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzNCLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQTFDRCxnQ0EwQ0M7QUFFTSxLQUFLLFVBQVUsVUFBVSxDQUFDLEdBQVcsRUFBRSxPQUE4QjtJQUN4RSxNQUFNLElBQUEsaUJBQU0sRUFBQyxHQUFHLENBQUMsQ0FBQztJQUNsQixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDZCxNQUFNLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEVBQUU7UUFDekQsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNyRCxNQUFNLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsQ0FBQyxNQUFNLElBQUEscUJBQVUsRUFBQyxTQUFTLENBQUMsQ0FBQyxFQUFFO1lBQ2hDLE1BQU0sSUFBQSxpQkFBTSxFQUFDLFNBQVMsQ0FBQyxDQUFDO1NBQzNCO1FBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBQSw0QkFBaUIsRUFBQyxtQkFBbUIsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDaEUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssSUFBSSxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztRQUN0RCxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFCLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxLQUFLLENBQUM7QUFDakIsQ0FBQztBQWRELGdDQWNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXJjaGl2ZXIgfSBmcm9tIFwiYXJjaGl2ZXJcIjtcbmltcG9ydCB7XG4gICAgY3JlYXRlV3JpdGVTdHJlYW0sXG4gICAgZW5zdXJlRGlyLFxuICAgIG1rZGlycCxcbiAgICBwYXRoRXhpc3RzLFxuICAgIHJlYWRGaWxlLFxuICAgIHN0YXRcbn0gZnJvbSBcImZzLWV4dHJhXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IFBhc3NUaHJvdWdoLCBSZWFkYWJsZSB9IGZyb20gXCJzdHJlYW1cIjtcbmltcG9ydCAqIGFzIHdlYnBhY2sgZnJvbSBcIndlYnBhY2tcIjtcbmltcG9ydCAqIGFzIHlhdXpsIGZyb20gXCJ5YXV6bFwiO1xuaW1wb3J0IHsgRmFhc3RFcnJvciB9IGZyb20gXCIuL2Vycm9yXCI7XG5pbXBvcnQgeyBMb2FkZXJPcHRpb25zIH0gZnJvbSBcIi4vbG9hZGVyXCI7XG5pbXBvcnQgeyBsb2cgfSBmcm9tIFwiLi9sb2dcIjtcbmltcG9ydCB7IGNvbW1vbkRlZmF1bHRzLCBDb21tb25PcHRpb25zLCBJbmNsdWRlT3B0aW9uIH0gZnJvbSBcIi4vcHJvdmlkZXJcIjtcbmltcG9ydCB7IGtleXNPZiwgc3RyZWFtVG9CdWZmZXIgfSBmcm9tIFwiLi9zaGFyZWRcIjtcbmltcG9ydCB7IFRyYW1wb2xpbmVGYWN0b3J5LCBXcmFwcGVyT3B0aW9uRGVmYXVsdHMsIFdyYXBwZXJPcHRpb25zIH0gZnJvbSBcIi4vd3JhcHBlclwiO1xuaW1wb3J0IHsgbWVyZ2UgfSBmcm9tIFwid2VicGFjay1tZXJnZVwiO1xuXG50eXBlIFppcEZpbGUgPSB5YXV6bC5aaXBGaWxlO1xuXG5pbXBvcnQgTWVtb3J5RmlsZVN5c3RlbSA9IHJlcXVpcmUoXCJtZW1vcnktZnNcIik7XG5pbXBvcnQgYXJjaGl2ZXIgPSByZXF1aXJlKFwiYXJjaGl2ZXJcIik7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFja2VyUmVzdWx0IHtcbiAgICBhcmNoaXZlOiBOb2RlSlMuUmVhZGFibGVTdHJlYW07XG59XG5cbmZ1bmN0aW9uIGdldFVybEVuY29kZWRRdWVyeVBhcmFtZXRlcnMob3B0aW9uczogTG9hZGVyT3B0aW9ucykge1xuICAgIHJldHVybiBrZXlzT2Yob3B0aW9ucylcbiAgICAgICAgLmZpbHRlcihrZXkgPT4gb3B0aW9uc1trZXldKVxuICAgICAgICAubWFwKGtleSA9PiBgJHtrZXl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KEpTT04uc3RyaW5naWZ5KG9wdGlvbnNba2V5XSkpfWApXG4gICAgICAgIC5qb2luKGAmYCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwYWNrZXIoXG4gICAgdHJhbXBvbGluZUZhY3Rvcnk6IFRyYW1wb2xpbmVGYWN0b3J5LFxuICAgIGZ1bmN0aW9uTW9kdWxlOiBzdHJpbmcsXG4gICAgdXNlck9wdGlvbnM6IENvbW1vbk9wdGlvbnMsXG4gICAgdXNlcldyYXBwZXJPcHRpb25zOiBXcmFwcGVyT3B0aW9ucyxcbiAgICBGdW5jdGlvbk5hbWU6IHN0cmluZ1xuKTogUHJvbWlzZTxQYWNrZXJSZXN1bHQ+IHtcbiAgICBjb25zdCBvcHRpb25zID0geyAuLi5jb21tb25EZWZhdWx0cywgLi4udXNlck9wdGlvbnMgfTtcbiAgICBjb25zdCB3cmFwcGVyT3B0aW9ucyA9IHsgLi4uV3JhcHBlck9wdGlvbkRlZmF1bHRzLCAuLi51c2VyV3JhcHBlck9wdGlvbnMgfTtcbiAgICBjb25zdCB7IHdlYnBhY2tPcHRpb25zLCBwYWNrYWdlSnNvbiB9ID0gb3B0aW9ucztcblxuICAgIGxvZy5pbmZvKGBSdW5uaW5nIHdlYnBhY2tgKTtcbiAgICBjb25zdCBtZnMgPSBuZXcgTWVtb3J5RmlsZVN5c3RlbSgpO1xuXG4gICAgZnVuY3Rpb24gYWRkVG9BcmNoaXZlKHJvb3Q6IHN0cmluZywgYXJjaGl2ZTogQXJjaGl2ZXIpIHtcbiAgICAgICAgZnVuY3Rpb24gYWRkRW50cnkoZW50cnk6IHN0cmluZykge1xuICAgICAgICAgICAgY29uc3Qgc3RhdEVudHJ5ID0gbWZzLnN0YXRTeW5jKGVudHJ5KTtcbiAgICAgICAgICAgIGlmIChzdGF0RW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc3ViRW50cnkgb2YgbWZzLnJlYWRkaXJTeW5jKGVudHJ5KSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdWJFbnRyeVBhdGggPSBwYXRoLmpvaW4oZW50cnksIHN1YkVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkRW50cnkoc3ViRW50cnlQYXRoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXRFbnRyeS5pc0ZpbGUoKSkge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKGBBZGRpbmcgZmlsZTogJHtlbnRyeX1gKTtcbiAgICAgICAgICAgICAgICBhcmNoaXZlLmFwcGVuZCgobWZzIGFzIGFueSkuY3JlYXRlUmVhZFN0cmVhbShlbnRyeSksIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogcGF0aC5yZWxhdGl2ZShyb290LCBlbnRyeSlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhZGRFbnRyeShyb290KTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBhZGRQYWNrYWdlSnNvbihwYWNrYWdlSnNvbkZpbGU6IHN0cmluZyB8IG9iamVjdCkge1xuICAgICAgICBjb25zdCBwYXJzZWRQYWNrYWdlSnNvbiA9XG4gICAgICAgICAgICB0eXBlb2YgcGFja2FnZUpzb25GaWxlID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBKU09OLnBhcnNlKFxuICAgICAgICAgICAgICAgICAgICAgIChhd2FpdCByZWFkRmlsZShhd2FpdCByZXNvbHZlUGF0aChwYWNrYWdlSnNvbkZpbGUpKSkudG9TdHJpbmcoKVxuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIDogeyAuLi5wYWNrYWdlSnNvbkZpbGUgfTtcbiAgICAgICAgcGFyc2VkUGFja2FnZUpzb24ubWFpbiA9IFwiaW5kZXguanNcIjtcbiAgICAgICAgbWZzLndyaXRlRmlsZVN5bmMoXG4gICAgICAgICAgICBcIi9wYWNrYWdlLmpzb25cIixcbiAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHBhcnNlZFBhY2thZ2VKc29uLCB1bmRlZmluZWQsIDIpXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhwYXJzZWRQYWNrYWdlSnNvbi5kZXBlbmRlbmNpZXMgfHwge30pO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVQYXRoKHBhdGhOYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKGF3YWl0IHBhdGhFeGlzdHMocGF0aE5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gcGF0aE5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEZhYXN0RXJyb3IoYENvdWxkIG5vdCBmaW5kIFwiJHtwYXRoTmFtZX1cImApO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NJbmNsdWRlRXhjbHVkZShcbiAgICAgICAgYXJjaGl2ZTogQXJjaGl2ZXIsXG4gICAgICAgIGluY2x1ZGU6IChzdHJpbmcgfCBJbmNsdWRlT3B0aW9uKVtdLFxuICAgICAgICBleGNsdWRlOiBzdHJpbmdbXVxuICAgICkge1xuICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgaW5jbHVkZSkge1xuICAgICAgICAgICAgbGV0IGN3ZCA9IFwiLlwiO1xuICAgICAgICAgICAgbGV0IGVudHJ5O1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgZW50cnkgPSBuYW1lO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjd2QgPSBuYW1lLmN3ZCB8fCBcIi5cIjtcbiAgICAgICAgICAgICAgICBlbnRyeSA9IG5hbWUucGF0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcGF0aC5yZXNvbHZlKGN3ZCwgZW50cnkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVudHJ5U3RhdCA9IGF3YWl0IHN0YXQocmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgICAgICAgICBpZiAoZW50cnlTdGF0LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZW50cnkgPSBqb2luKGVudHJ5LCBcIi8qKi8qXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2gge31cbiAgICAgICAgICAgIGFyY2hpdmUuZ2xvYihlbnRyeSwgeyBpZ25vcmU6IGV4Y2x1ZGUsIGN3ZCB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByZXBhcmVaaXBBcmNoaXZlKCk6IFByb21pc2U8UGFja2VyUmVzdWx0PiB7XG4gICAgICAgIGNvbnN0IGFyY2hpdmUgPSBhcmNoaXZlcihcInppcFwiLCB7IHpsaWI6IHsgbGV2ZWw6IDggfSB9KTtcbiAgICAgICAgYXJjaGl2ZS5vbihcImVycm9yXCIsIGVyciA9PiBsb2cud2FybihlcnIpKTtcbiAgICAgICAgYXJjaGl2ZS5vbihcIndhcm5pbmdcIiwgZXJyID0+IGxvZy53YXJuKGVycikpO1xuICAgICAgICBhZGRUb0FyY2hpdmUoXCIvXCIsIGFyY2hpdmUpO1xuICAgICAgICBjb25zdCB7IGluY2x1ZGUsIGV4Y2x1ZGUgfSA9IG9wdGlvbnM7XG4gICAgICAgIGF3YWl0IHByb2Nlc3NJbmNsdWRlRXhjbHVkZShhcmNoaXZlLCBpbmNsdWRlLCBleGNsdWRlKTtcbiAgICAgICAgYXJjaGl2ZS5maW5hbGl6ZSgpO1xuICAgICAgICByZXR1cm4geyBhcmNoaXZlIH07XG4gICAgfVxuXG4gICAgY29uc3QgZGVwZW5kZW5jaWVzID0gKHBhY2thZ2VKc29uICYmIChhd2FpdCBhZGRQYWNrYWdlSnNvbihwYWNrYWdlSnNvbikpKSB8fCBbXTtcblxuICAgIGZ1bmN0aW9uIHJ1bldlYnBhY2soZW50cnk6IHN0cmluZywgZW50cnlOYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgY29yZUNvbmZpZzogd2VicGFjay5Db25maWd1cmF0aW9uID0ge1xuICAgICAgICAgICAgZW50cnk6IHsgW2VudHJ5TmFtZV06IGVudHJ5IH0sXG4gICAgICAgICAgICBtb2RlOiBcImRldmVsb3BtZW50XCIsXG4gICAgICAgICAgICBvdXRwdXQ6IHtcbiAgICAgICAgICAgICAgICBwYXRoOiBcIi9cIixcbiAgICAgICAgICAgICAgICBmaWxlbmFtZTogXCJbbmFtZV0uanNcIixcbiAgICAgICAgICAgICAgICBsaWJyYXJ5VGFyZ2V0OiBcImNvbW1vbmpzMlwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGFyZ2V0OiBcIm5vZGVcIixcbiAgICAgICAgICAgIHJlc29sdmVMb2FkZXI6IHsgbW9kdWxlczogW19fZGlybmFtZSwgYCR7X19kaXJuYW1lfS9kaXN0YF0gfSxcbiAgICAgICAgICAgIG5vZGU6IHsgZ2xvYmFsOiB0cnVlLCBfX2Rpcm5hbWU6IGZhbHNlLCBfX2ZpbGVuYW1lOiBmYWxzZSB9XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGRlcGVuZGVuY3lFeHRlcm5hbHMgPSB7XG4gICAgICAgICAgICBleHRlcm5hbHM6IFsuLi5kZXBlbmRlbmNpZXMsIC4uLmRlcGVuZGVuY2llcy5tYXAoZCA9PiBuZXcgUmVnRXhwKGBeJHtkfS8uKmApKV1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgY29uZmlnID0gbWVyZ2UoY29yZUNvbmZpZywgZGVwZW5kZW5jeUV4dGVybmFscywgd2VicGFja09wdGlvbnMpO1xuICAgICAgICBsb2cud2VicGFjayhgd2VicGFjayBjb25maWc6ICVPYCwgY29uZmlnKTtcbiAgICAgICAgY29uc3QgY29tcGlsZXIgPSB3ZWJwYWNrKGNvbmZpZyk7XG4gICAgICAgIGNvbXBpbGVyLm91dHB1dEZpbGVTeXN0ZW0gPSBtZnMgYXMgYW55O1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT5cbiAgICAgICAgICAgIGNvbXBpbGVyLnJ1bigoZXJyLCBzdGF0cykgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRzPy5oYXNFcnJvcnMoKSB8fCBzdGF0cz8uaGFzV2FybmluZ3MoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYyA9IHN0YXRzLmNvbXBpbGF0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZXMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjLndhcm5pbmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlcy5wdXNoKGAke2Mud2FybmluZ3MubGVuZ3RofSB3YXJuaW5nKHMpYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYy5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VzLnB1c2goYCR7Yy5lcnJvcnMubGVuZ3RofSBlcnJvcihzKWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbG9nLndhcm4oYHdlYnBhY2sgaGFkICR7bWVzc2FnZXMuam9pbihcIiBhbmQgXCIpfWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nLndhcm4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYHNldCBlbnZpcm9ubWVudCB2YXJpYWJsZSBERUJVRz1mYWFzdDp3ZWJwYWNrIGZvciBkZXRhaWxzYFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy53YXJuKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBzZWUgaHR0cHM6Ly9mYWFzdGpzLm9yZy9kb2NzL2FwaS9mYWFzdGpzLmNvbW1vbm9wdGlvbnMucGFja2FnZWpzb25gXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsb2cud2VicGFjay5lbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2cud2VicGFjayhzdGF0cz8udG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2cud2VicGFjayhgTWVtb3J5IGZpbGVzeXN0ZW06IGApO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWxlIG9mIE9iamVjdC5rZXlzKG1mcy5kYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZy53ZWJwYWNrKGAgICR7ZmlsZX06ICR7bWZzLmRhdGFbZmlsZV0ubGVuZ3RofWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHsgY2hpbGRQcm9jZXNzLCB2YWxpZGF0ZVNlcmlhbGl6YXRpb24gfSA9IG9wdGlvbnM7XG4gICAgY29uc3Qge1xuICAgICAgICB3cmFwcGVyVmVyYm9zZSxcbiAgICAgICAgY2hpbGRQcm9jZXNzOiBfb25seVVzZWRGb3JMb2NhbFByb3ZpZGVyRGlyZWN0V3JhcHBlckluc3RhbnRpYXRpb24sXG4gICAgICAgIGNoaWxkRGlyLFxuICAgICAgICBjaGlsZFByb2Nlc3NNZW1vcnlMaW1pdE1iLFxuICAgICAgICBjaGlsZFByb2Nlc3NUaW1lb3V0TXMsXG4gICAgICAgIGNoaWxkUHJvY2Vzc0Vudmlyb25tZW50OiBfb25seVVzZWRGb3JMb2NhbFByb3ZpZGVyRGlyZWN0V3JhcHBlckluc3RhbnRpYXRpb24yLFxuICAgICAgICB3cmFwcGVyTG9nOiBfb25seVVzZWRGb3JMb2NhbFByb3ZpZGVyRGlyZWN0V3JhcHBlckluc3RhbnRpYXRpb24zLFxuICAgICAgICB2YWxpZGF0ZVNlcmlhbGl6YXRpb246IF9pZ25vcmVkSW5GYXZvck9mQ29tbW9uT3B0aW9uc1NldHRpbmcsXG4gICAgICAgIC4uLnJlc3RcbiAgICB9ID0gd3JhcHBlck9wdGlvbnM7XG4gICAgY29uc3QgX2V4aGF1c3RpdmVDaGVjazI6IFJlcXVpcmVkPHR5cGVvZiByZXN0PiA9IHt9O1xuICAgIGNvbnN0IGlzVmVyYm9zZSA9IHdyYXBwZXJWZXJib3NlIHx8IGxvZy5wcm92aWRlci5lbmFibGVkO1xuXG4gICAgY29uc3QgbG9hZGVyID0gYGxvYWRlcj8ke2dldFVybEVuY29kZWRRdWVyeVBhcmFtZXRlcnMoe1xuICAgICAgICB0cmFtcG9saW5lRmFjdG9yeU1vZHVsZTogdHJhbXBvbGluZUZhY3RvcnkuZmlsZW5hbWUsXG4gICAgICAgIHdyYXBwZXJPcHRpb25zOiB7XG4gICAgICAgICAgICB3cmFwcGVyVmVyYm9zZTogaXNWZXJib3NlLFxuICAgICAgICAgICAgY2hpbGRQcm9jZXNzLFxuICAgICAgICAgICAgY2hpbGREaXIsXG4gICAgICAgICAgICBjaGlsZFByb2Nlc3NNZW1vcnlMaW1pdE1iLFxuICAgICAgICAgICAgY2hpbGRQcm9jZXNzVGltZW91dE1zLFxuICAgICAgICAgICAgdmFsaWRhdGVTZXJpYWxpemF0aW9uXG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmN0aW9uTW9kdWxlXG4gICAgfSl9IWA7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgcnVuV2VicGFjayhsb2FkZXIsIFwiaW5kZXhcIik7XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEZhYXN0RXJyb3IoZXJyLCBcImZhaWxlZCBydW5uaW5nIHdlYnBhY2tcIik7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGxldCB7IGFyY2hpdmUgfSA9IGF3YWl0IHByZXBhcmVaaXBBcmNoaXZlKCk7XG4gICAgICAgIGNvbnN0IHBhY2thZ2VEaXIgPSBwcm9jZXNzLmVudltcIkZBQVNUX1BBQ0tBR0VfRElSXCJdO1xuICAgICAgICBpZiAocGFja2FnZURpcikge1xuICAgICAgICAgICAgbG9nLndlYnBhY2soYEZBQVNUX1BBQ0tBR0VfRElSOiAke3BhY2thZ2VEaXJ9YCk7XG4gICAgICAgICAgICBjb25zdCBwYWNrYWdlRmlsZSA9IGpvaW4ocGFja2FnZURpciwgRnVuY3Rpb25OYW1lKSArIFwiLnppcFwiO1xuICAgICAgICAgICAgYXdhaXQgZW5zdXJlRGlyKHBhY2thZ2VEaXIpO1xuICAgICAgICAgICAgY29uc3Qgd3JpdGVTdHJlYW0gPSBjcmVhdGVXcml0ZVN0cmVhbShwYWNrYWdlRmlsZSk7XG4gICAgICAgICAgICBjb25zdCBwYXNzVGhyb3VnaCA9IGFyY2hpdmUucGlwZShuZXcgUGFzc1Rocm91Z2goKSk7XG4gICAgICAgICAgICBhcmNoaXZlID0gYXJjaGl2ZS5waXBlKG5ldyBQYXNzVGhyb3VnaCgpKTtcbiAgICAgICAgICAgIHBhc3NUaHJvdWdoLnBpcGUod3JpdGVTdHJlYW0pO1xuICAgICAgICAgICAgd3JpdGVTdHJlYW0ub24oXCJjbG9zZVwiLCAoKSA9PiB7XG4gICAgICAgICAgICAgICAgbG9nLmluZm8oYFdyb3RlICR7cGFja2FnZUZpbGV9YCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBhcmNoaXZlIH07XG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEZhYXN0RXJyb3IoZXJyLCBcImZhaWxlZCBjcmVhdGluZyB6aXAgYXJjaGl2ZVwiKTtcbiAgICB9XG59XG5cbi8qKlxuICogQHBhcmFtIHtOb2RlSlMuUmVhZGFibGVTdHJlYW0gfCBzdHJpbmd9IGFyY2hpdmUgQSB6aXAgYXJjaGl2ZSBhcyBhIHN0cmVhbSBvciBhIGZpbGVuYW1lXG4gKiBAcGFyYW0geyhmaWxlbmFtZTogc3RyaW5nLCBjb250ZW50czogUmVhZGFibGUpID0+IHZvaWR9IHByb2Nlc3NFbnRyeSBFdmVyeVxuICogZW50cnkncyBjb250ZW50cyBtdXN0IGJlIGNvbnN1bWVkLCBvdGhlcndpc2UgdGhlIG5leHQgZW50cnkgd29uJ3QgYmUgcmVhZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NaaXAoXG4gICAgYXJjaGl2ZTogTm9kZUpTLlJlYWRhYmxlU3RyZWFtIHwgc3RyaW5nLFxuICAgIHByb2Nlc3NFbnRyeTogKGZpbGVuYW1lOiBzdHJpbmcsIGNvbnRlbnRzOiBSZWFkYWJsZSwgbW9kZTogbnVtYmVyKSA9PiB2b2lkXG4pIHtcbiAgICBsZXQgemlwOiBaaXBGaWxlO1xuICAgIGlmICh0eXBlb2YgYXJjaGl2ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICB6aXAgPSBhd2FpdCBuZXcgUHJvbWlzZTxaaXBGaWxlPigocmVzb2x2ZSwgcmVqZWN0KSA9PlxuICAgICAgICAgICAgeWF1emwub3BlbihhcmNoaXZlLCB7IGxhenlFbnRyaWVzOiB0cnVlIH0sIChlcnIsIHppcGZpbGUpID0+XG4gICAgICAgICAgICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHppcGZpbGUhKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGJ1ZiA9IGF3YWl0IHN0cmVhbVRvQnVmZmVyKGFyY2hpdmUpO1xuICAgICAgICB6aXAgPSBhd2FpdCBuZXcgUHJvbWlzZTxaaXBGaWxlPigocmVzb2x2ZSwgcmVqZWN0KSA9PlxuICAgICAgICAgICAgeWF1emwuZnJvbUJ1ZmZlcihidWYsIHsgbGF6eUVudHJpZXM6IHRydWUgfSwgKGVyciwgemlwZmlsZSkgPT5cbiAgICAgICAgICAgICAgICBlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUoemlwZmlsZSEpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgemlwLnJlYWRFbnRyeSgpO1xuICAgICAgICB6aXAub24oXCJlbnRyeVwiLCAoZW50cnk6IHlhdXpsLkVudHJ5KSA9PiB7XG4gICAgICAgICAgICBpZiAoL1xcLyQvLnRlc3QoZW50cnkuZmlsZU5hbWUpKSB7XG4gICAgICAgICAgICAgICAgemlwLnJlYWRFbnRyeSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB6aXAub3BlblJlYWRTdHJlYW0oZW50cnksIChlcnIsIHJlYWRTdHJlYW0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVhZFN0cmVhbSEub24oXCJlbmRcIiwgKCkgPT4gemlwLnJlYWRFbnRyeSgpKTtcbiAgICAgICAgICAgICAgICAgICAgcHJvY2Vzc0VudHJ5KFxuICAgICAgICAgICAgICAgICAgICAgICAgZW50cnkuZmlsZU5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICByZWFkU3RyZWFtISxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5LmV4dGVybmFsRmlsZUF0dHJpYnV0ZXMgPj4+IDE2XG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB6aXAub24oXCJlbmRcIiwgcmVzb2x2ZSk7XG4gICAgfSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB1bnppcEluRGlyKGRpcjogc3RyaW5nLCBhcmNoaXZlOiBOb2RlSlMuUmVhZGFibGVTdHJlYW0pIHtcbiAgICBhd2FpdCBta2RpcnAoZGlyKTtcbiAgICBsZXQgdG90YWwgPSAwO1xuICAgIGF3YWl0IHByb2Nlc3NaaXAoYXJjaGl2ZSwgYXN5bmMgKGZpbGVuYW1lLCBjb250ZW50cywgbW9kZSkgPT4ge1xuICAgICAgICBjb25zdCBkZXN0aW5hdGlvbkZpbGVuYW1lID0gcGF0aC5qb2luKGRpciwgZmlsZW5hbWUpO1xuICAgICAgICBjb25zdCB7IGRpcjogb3V0cHV0RGlyIH0gPSBwYXRoLnBhcnNlKGRlc3RpbmF0aW9uRmlsZW5hbWUpO1xuICAgICAgICBpZiAoIShhd2FpdCBwYXRoRXhpc3RzKG91dHB1dERpcikpKSB7XG4gICAgICAgICAgICBhd2FpdCBta2RpcnAob3V0cHV0RGlyKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzdHJlYW0gPSBjcmVhdGVXcml0ZVN0cmVhbShkZXN0aW5hdGlvbkZpbGVuYW1lLCB7IG1vZGUgfSk7XG4gICAgICAgIGNvbnRlbnRzLm9uKFwiZGF0YVwiLCBjaHVuayA9PiAodG90YWwgKz0gY2h1bmsubGVuZ3RoKSk7XG4gICAgICAgIGNvbnRlbnRzLnBpcGUoc3RyZWFtKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdG90YWw7XG59XG4iXX0= |
\ | No newline at end of file |