UNPKG

37.5 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.unzipInDir = exports.processZip = exports.packer = void 0;
4const fs_extra_1 = require("fs-extra");
5const path = require("path");
6const path_1 = require("path");
7const stream_1 = require("stream");
8const webpack = require("webpack");
9const yauzl = require("yauzl");
10const error_1 = require("./error");
11const log_1 = require("./log");
12const provider_1 = require("./provider");
13const shared_1 = require("./shared");
14const wrapper_1 = require("./wrapper");
15const webpack_merge_1 = require("webpack-merge");
16const MemoryFileSystem = require("memory-fs");
17const archiver = require("archiver");
18function 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}
24async 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}
187exports.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 */
193async 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}
222exports.processZip = processZip;
223async 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}
238exports.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