faastjs
Version:
Serverless batch computing made simple.
240 lines • 37.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.unzipInDir = exports.processZip = exports.packer = void 0;
const tslib_1 = require("tslib");
const archiver_1 = tslib_1.__importDefault(require("archiver"));
const fs_extra_1 = require("fs-extra");
const memory_fs_1 = tslib_1.__importDefault(require("memory-fs"));
const path_1 = tslib_1.__importDefault(require("path"));
const path_2 = require("path");
const stream_1 = require("stream");
const webpack_1 = tslib_1.__importDefault(require("webpack"));
const webpack_merge_1 = require("webpack-merge");
const yauzl_1 = tslib_1.__importDefault(require("yauzl"));
const error_1 = require("./error");
const log_1 = require("./log");
const provider_1 = require("./provider");
const shared_1 = require("./shared");
const wrapper_1 = require("./wrapper");
function getUrlEncodedQueryParameters(options) {
return (0, shared_1.keysOf)(options)
.filter(key => options[key])
.map(key => `${key}=${encodeURIComponent(JSON.stringify(options[key]))}`)
.join(`&`);
}
async function packer(trampolineFactory, functionModule, userOptions, userWrapperOptions, FunctionName) {
const options = { ...provider_1.commonDefaults, ...userOptions };
const wrapperOptions = { ...wrapper_1.WrapperOptionDefaults, ...userWrapperOptions };
const { webpackOptions, packageJson } = options;
log_1.log.info(`Running webpack`);
const mfs = new memory_fs_1.default();
function addToArchive(root, archive) {
function addEntry(entry) {
const statEntry = mfs.statSync(entry);
if (statEntry.isDirectory()) {
for (const subEntry of mfs.readdirSync(entry)) {
const subEntryPath = path_1.default.join(entry, subEntry);
addEntry(subEntryPath);
}
}
else if (statEntry.isFile()) {
log_1.log.info(`Adding file: ${entry}`);
archive.append(mfs.createReadStream(entry), {
name: path_1.default.relative(root, entry)
});
}
}
addEntry(root);
}
async function addPackageJson(packageJsonFile) {
const parsedPackageJson = typeof packageJsonFile === "string"
? JSON.parse((await (0, fs_extra_1.readFile)(await resolvePath(packageJsonFile))).toString())
: { ...packageJsonFile };
parsedPackageJson.main = "index.js";
mfs.writeFileSync("/package.json", JSON.stringify(parsedPackageJson, undefined, 2));
return Object.keys(parsedPackageJson.dependencies || {});
}
async function resolvePath(pathName) {
if (await (0, fs_extra_1.pathExists)(pathName)) {
return pathName;
}
throw new error_1.FaastError(`Could not find "${pathName}"`);
}
async function processIncludeExclude(archive, include, exclude) {
for (const name of include) {
let cwd = ".";
let entry;
if (typeof name === "string") {
entry = name;
}
else {
cwd = name.cwd || ".";
entry = name.path;
}
try {
const resolvedPath = path_1.default.resolve(cwd, entry);
const entryStat = await (0, fs_extra_1.stat)(resolvedPath);
if (entryStat.isDirectory()) {
entry = (0, path_2.join)(entry, "/**/*");
}
}
catch { }
archive.glob(entry, { ignore: exclude, cwd });
}
}
async function prepareZipArchive() {
const archive = (0, archiver_1.default)("zip", { zlib: { level: 8 } });
archive.on("error", err => log_1.log.warn(err));
archive.on("warning", err => log_1.log.warn(err));
addToArchive("/", archive);
const { include, exclude } = options;
await processIncludeExclude(archive, include, exclude);
archive.finalize();
return { archive };
}
const dependencies = (packageJson && (await addPackageJson(packageJson))) || [];
function runWebpack(entry, entryName) {
const coreConfig = {
entry: { [entryName]: entry },
mode: "development",
output: {
path: "/",
filename: "[name].js",
libraryTarget: "commonjs2"
},
target: "node",
resolveLoader: { modules: [__dirname, `${__dirname}/dist`] },
node: { global: true, __dirname: false, __filename: false }
};
const dependencyExternals = {
externals: [...dependencies, ...dependencies.map(d => new RegExp(`^${d}/.*`))]
};
const config = (0, webpack_merge_1.merge)(coreConfig, dependencyExternals, webpackOptions);
log_1.log.webpack(`webpack config: %O`, config);
const compiler = (0, webpack_1.default)(config);
compiler.outputFileSystem = mfs;
return new Promise((resolve, reject) => compiler.run((err, stats) => {
if (err) {
reject(err);
}
else {
if (stats?.hasErrors() || stats?.hasWarnings()) {
const c = stats.compilation;
const messages = [];
if (c.warnings.length > 0) {
messages.push(`${c.warnings.length} warning(s)`);
}
if (c.errors.length > 0) {
messages.push(`${c.errors.length} error(s)`);
}
log_1.log.warn(`webpack had ${messages.join(" and ")}`);
log_1.log.warn(`set environment variable DEBUG=faast:webpack for details`);
log_1.log.warn(`see https://faastjs.org/docs/api/faastjs.commonoptions.packagejson`);
}
if (log_1.log.webpack.enabled) {
log_1.log.webpack(stats?.toString());
log_1.log.webpack(`Memory filesystem: `);
for (const file of Object.keys(mfs.data)) {
log_1.log.webpack(` ${file}: ${mfs.data[file].length}`);
}
}
resolve();
}
}));
}
const { childProcess, validateSerialization } = options;
const { wrapperVerbose, childProcess: _onlyUsedForLocalProviderDirectWrapperInstantiation, childDir, childProcessMemoryLimitMb, childProcessTimeoutMs, childProcessEnvironment: _onlyUsedForLocalProviderDirectWrapperInstantiation2, wrapperLog: _onlyUsedForLocalProviderDirectWrapperInstantiation3, validateSerialization: _ignoredInFavorOfCommonOptionsSetting, ...rest } = wrapperOptions;
const _exhaustiveCheck2 = {};
const isVerbose = wrapperVerbose || log_1.log.provider.enabled;
const loader = `loader?${getUrlEncodedQueryParameters({
trampolineFactoryModule: trampolineFactory.filename,
wrapperOptions: {
wrapperVerbose: isVerbose,
childProcess,
childDir,
childProcessMemoryLimitMb,
childProcessTimeoutMs,
validateSerialization
},
functionModule
})}!`;
try {
await runWebpack(loader, "index");
}
catch (err) {
throw new error_1.FaastError(err, "failed running webpack");
}
try {
let { archive } = await prepareZipArchive();
const packageDir = process.env["FAAST_PACKAGE_DIR"];
if (packageDir) {
log_1.log.webpack(`FAAST_PACKAGE_DIR: ${packageDir}`);
const packageFile = (0, path_2.join)(packageDir, FunctionName) + ".zip";
await (0, fs_extra_1.ensureDir)(packageDir);
const writeStream = (0, fs_extra_1.createWriteStream)(packageFile);
const passThrough = archive.pipe(new stream_1.PassThrough());
archive = archive.pipe(new stream_1.PassThrough());
passThrough.pipe(writeStream);
writeStream.on("close", () => {
log_1.log.info(`Wrote ${packageFile}`);
});
}
return { archive };
}
catch (err) {
throw new error_1.FaastError(err, "failed creating zip archive");
}
}
exports.packer = packer;
/**
* @param {NodeJS.ReadableStream | string} archive A zip archive as a stream or a filename
* @param {(filename: string, contents: Readable) => void} processEntry Every
* entry's contents must be consumed, otherwise the next entry won't be read.
*/
async function processZip(archive, processEntry) {
let zip;
if (typeof archive === "string") {
zip = await new Promise((resolve, reject) => yauzl_1.default.open(archive, { lazyEntries: true }, (err, zipfile) => err ? reject(err) : resolve(zipfile)));
}
else {
const buf = await (0, shared_1.streamToBuffer)(archive);
zip = await new Promise((resolve, reject) => yauzl_1.default.fromBuffer(buf, { lazyEntries: true }, (err, zipfile) => err ? reject(err) : resolve(zipfile)));
}
return new Promise((resolve, reject) => {
zip.readEntry();
zip.on("entry", (entry) => {
if (/\/$/.test(entry.fileName)) {
zip.readEntry();
}
else {
zip.openReadStream(entry, (err, readStream) => {
if (err) {
reject(err);
return;
}
readStream.on("end", () => zip.readEntry());
processEntry(entry.fileName, readStream, entry.externalFileAttributes >>> 16);
});
}
});
zip.on("end", resolve);
});
}
exports.processZip = processZip;
async function unzipInDir(dir, archive) {
await (0, fs_extra_1.mkdirp)(dir);
let total = 0;
await processZip(archive, async (filename, contents, mode) => {
const destinationFilename = path_1.default.join(dir, filename);
const { dir: outputDir } = path_1.default.parse(destinationFilename);
if (!(await (0, fs_extra_1.pathExists)(outputDir))) {
await (0, fs_extra_1.mkdirp)(outputDir);
}
const stream = (0, fs_extra_1.createWriteStream)(destinationFilename, { mode });
contents.on("data", chunk => (total += chunk.length));
contents.pipe(stream);
});
return total;
}
exports.unzipInDir = unzipInDir;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFja2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BhY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsZ0VBQThDO0FBQzlDLHVDQU9rQjtBQUNsQixrRUFBeUM7QUFDekMsd0RBQXdCO0FBQ3hCLCtCQUE0QjtBQUM1QixtQ0FBK0M7QUFDL0MsOERBQThCO0FBQzlCLGlEQUFzQztBQUN0QywwREFBMEI7QUFDMUIsbUNBQXFDO0FBRXJDLCtCQUE0QjtBQUM1Qix5Q0FBMEU7QUFDMUUscUNBQWtEO0FBQ2xELHVDQUFxRjtBQVFyRixTQUFTLDRCQUE0QixDQUFDLE9BQXNCO0lBQ3hELE9BQU8sSUFBQSxlQUFNLEVBQUMsT0FBTyxDQUFDO1NBQ2pCLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUMzQixHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsSUFBSSxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztTQUN4RSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDbkIsQ0FBQztBQUVNLEtBQUssVUFBVSxNQUFNLENBQ3hCLGlCQUFvQyxFQUNwQyxjQUFzQixFQUN0QixXQUEwQixFQUMxQixrQkFBa0MsRUFDbEMsWUFBb0I7SUFFcEIsTUFBTSxPQUFPLEdBQUcsRUFBRSxHQUFHLHlCQUFjLEVBQUUsR0FBRyxXQUFXLEVBQUUsQ0FBQztJQUN0RCxNQUFNLGNBQWMsR0FBRyxFQUFFLEdBQUcsK0JBQXFCLEVBQUUsR0FBRyxrQkFBa0IsRUFBRSxDQUFDO0lBQzNFLE1BQU0sRUFBRSxjQUFjLEVBQUUsV0FBVyxFQUFFLEdBQUcsT0FBTyxDQUFDO0lBRWhELFNBQUcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUM1QixNQUFNLEdBQUcs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QUFDLENBQUM7UUFDSCxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztJQUMzQixDQUFDLENBQUMsQ0FBQztBQUNQLENBQUM7QUExQ0QsZ0NBMENDO0FBRU0sS0FBSyxVQUFVLFVBQVUsQ0FBQyxHQUFXLEVBQUUsT0FBOEI7SUFDeEUsTUFBTSxJQUFBLGlCQUFNLEVBQUMsR0FBRyxDQUFDLENBQUM7SUFDbEIsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQ2QsTUFBTSxVQUFVLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFO1FBQ3pELE1BQU0sbUJBQW1CLEdBQUcsY0FBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDckQsTUFBTSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxjQUFJLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDM0QsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFBLHFCQUFVLEVBQUMsU0FBUyxDQUFDLENBQUMsRUFBRTtZQUNoQyxNQUFNLElBQUEsaUJBQU0sRUFBQyxTQUFTLENBQUMsQ0FBQztTQUMzQjtRQUNELE1BQU0sTUFBTSxHQUFHLElBQUEsNEJBQWlCLEVBQUMsbUJBQW1CLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLFFBQVEsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDdEQsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMxQixDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sS0FBSyxDQUFDO0FBQ2pCLENBQUM7QUFkRCxnQ0FjQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBhcmNoaXZlciwgeyBBcmNoaXZlciB9IGZyb20gXCJhcmNoaXZlclwiO1xuaW1wb3J0IHtcbiAgICBjcmVhdGVXcml0ZVN0cmVhbSxcbiAgICBlbnN1cmVEaXIsXG4gICAgbWtkaXJwLFxuICAgIHBhdGhFeGlzdHMsXG4gICAgcmVhZEZpbGUsXG4gICAgc3RhdFxufSBmcm9tIFwiZnMtZXh0cmFcIjtcbmltcG9ydCBNZW1vcnlGaWxlU3lzdGVtIGZyb20gXCJtZW1vcnktZnNcIjtcbmltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcInBhdGhcIjtcbmltcG9ydCB7IFBhc3NUaHJvdWdoLCBSZWFkYWJsZSB9IGZyb20gXCJzdHJlYW1cIjtcbmltcG9ydCB3ZWJwYWNrIGZyb20gXCJ3ZWJwYWNrXCI7XG5pbXBvcnQgeyBtZXJnZSB9IGZyb20gXCJ3ZWJwYWNrLW1lcmdlXCI7XG5pbXBvcnQgeWF1emwgZnJvbSBcInlhdXpsXCI7XG5pbXBvcnQgeyBGYWFzdEVycm9yIH0gZnJvbSBcIi4vZXJyb3JcIjtcbmltcG9ydCB7IExvYWRlck9wdGlvbnMgfSBmcm9tIFwiLi9sb2FkZXJcIjtcbmltcG9ydCB7IGxvZyB9IGZyb20gXCIuL2xvZ1wiO1xuaW1wb3J0IHsgY29tbW9uRGVmYXVsdHMsIENvbW1vbk9wdGlvbnMsIEluY2x1ZGVPcHRpb24gfSBmcm9tIFwiLi9wcm92aWRlclwiO1xuaW1wb3J0IHsga2V5c09mLCBzdHJlYW1Ub0J1ZmZlciB9IGZyb20gXCIuL3NoYXJlZFwiO1xuaW1wb3J0IHsgVHJhbXBvbGluZUZhY3RvcnksIFdyYXBwZXJPcHRpb25EZWZhdWx0cywgV3JhcHBlck9wdGlvbnMgfSBmcm9tIFwiLi93cmFwcGVyXCI7XG5cbnR5cGUgWmlwRmlsZSA9IHlhdXpsLlppcEZpbGU7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFja2VyUmVzdWx0IHtcbiAgICBhcmNoaXZlOiBOb2RlSlMuUmVhZGFibGVTdHJlYW07XG59XG5cbmZ1bmN0aW9uIGdldFVybEVuY29kZWRRdWVyeVBhcmFtZXRlcnMob3B0aW9uczogTG9hZGVyT3B0aW9ucykge1xuICAgIHJldHVybiBrZXlzT2Yob3B0aW9ucylcbiAgICAgICAgLmZpbHRlcihrZXkgPT4gb3B0aW9uc1trZXldKVxuICAgICAgICAubWFwKGtleSA9PiBgJHtrZXl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KEpTT04uc3RyaW5naWZ5KG9wdGlvbnNba2V5XSkpfWApXG4gICAgICAgIC5qb2luKGAmYCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwYWNrZXIoXG4gICAgdHJhbXBvbGluZUZhY3Rvcnk6IFRyYW1wb2xpbmVGYWN0b3J5LFxuICAgIGZ1bmN0aW9uTW9kdWxlOiBzdHJpbmcsXG4gICAgdXNlck9wdGlvbnM6IENvbW1vbk9wdGlvbnMsXG4gICAgdXNlcldyYXBwZXJPcHRpb25zOiBXcmFwcGVyT3B0aW9ucyxcbiAgICBGdW5jdGlvbk5hbWU6IHN0cmluZ1xuKTogUHJvbWlzZTxQYWNrZXJSZXN1bHQ+IHtcbiAgICBjb25zdCBvcHRpb25zID0geyAuLi5jb21tb25EZWZhdWx0cywgLi4udXNlck9wdGlvbnMgfTtcbiAgICBjb25zdCB3cmFwcGVyT3B0aW9ucyA9IHsgLi4uV3JhcHBlck9wdGlvbkRlZmF1bHRzLCAuLi51c2VyV3JhcHBlck9wdGlvbnMgfTtcbiAgICBjb25zdCB7IHdlYnBhY2tPcHRpb25zLCBwYWNrYWdlSnNvbiB9ID0gb3B0aW9ucztcblxuICAgIGxvZy5pbmZvKGBSdW5uaW5nIHdlYnBhY2tgKTtcbiAgICBjb25zdCBtZnMgPSBuZXcgTWVtb3J5RmlsZVN5c3RlbSgpO1xuXG4gICAgZnVuY3Rpb24gYWRkVG9BcmNoaXZlKHJvb3Q6IHN0cmluZywgYXJjaGl2ZTogQXJjaGl2ZXIpIHtcbiAgICAgICAgZnVuY3Rpb24gYWRkRW50cnkoZW50cnk6IHN0cmluZykge1xuICAgICAgICAgICAgY29uc3Qgc3RhdEVudHJ5ID0gbWZzLnN0YXRTeW5jKGVudHJ5KTtcbiAgICAgICAgICAgIGlmIChzdGF0RW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgc3ViRW50cnkgb2YgbWZzLnJlYWRkaXJTeW5jKGVudHJ5KSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdWJFbnRyeVBhdGggPSBwYXRoLmpvaW4oZW50cnksIHN1YkVudHJ5KTtcbiAgICAgICAgICAgICAgICAgICAgYWRkRW50cnkoc3ViRW50cnlQYXRoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHN0YXRFbnRyeS5pc0ZpbGUoKSkge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKGBBZGRpbmcgZmlsZTogJHtlbnRyeX1gKTtcbiAgICAgICAgICAgICAgICBhcmNoaXZlLmFwcGVuZCgobWZzIGFzIGFueSkuY3JlYXRlUmVhZFN0cmVhbShlbnRyeSksIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogcGF0aC5yZWxhdGl2ZShyb290LCBlbnRyeSlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhZGRFbnRyeShyb290KTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBhZGRQYWNrYWdlSnNvbihwYWNrYWdlSnNvbkZpbGU6IHN0cmluZyB8IG9iamVjdCkge1xuICAgICAgICBjb25zdCBwYXJzZWRQYWNrYWdlSnNvbiA9XG4gICAgICAgICAgICB0eXBlb2YgcGFja2FnZUpzb25GaWxlID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgPyBKU09OLnBhcnNlKFxuICAgICAgICAgICAgICAgICAgICAgIChhd2FpdCByZWFkRmlsZShhd2FpdCByZXNvbHZlUGF0aChwYWNrYWdlSnNvbkZpbGUpKSkudG9TdHJpbmcoKVxuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIDogeyAuLi5wYWNrYWdlSnNvbkZpbGUgfTtcbiAgICAgICAgcGFyc2VkUGFja2FnZUpzb24ubWFpbiA9IFwiaW5kZXguanNcIjtcbiAgICAgICAgbWZzLndyaXRlRmlsZVN5bmMoXG4gICAgICAgICAgICBcIi9wYWNrYWdlLmpzb25cIixcbiAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHBhcnNlZFBhY2thZ2VKc29uLCB1bmRlZmluZWQsIDIpXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhwYXJzZWRQYWNrYWdlSnNvbi5kZXBlbmRlbmNpZXMgfHwge30pO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVQYXRoKHBhdGhOYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKGF3YWl0IHBhdGhFeGlzdHMocGF0aE5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gcGF0aE5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgbmV3IEZhYXN0RXJyb3IoYENvdWxkIG5vdCBmaW5kIFwiJHtwYXRoTmFtZX1cImApO1xuICAgIH1cblxuICAgIGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NJbmNsdWRlRXhjbHVkZShcbiAgICAgICAgYXJjaGl2ZTogQXJjaGl2ZXIsXG4gICAgICAgIGluY2x1ZGU6IChzdHJpbmcgfCBJbmNsdWRlT3B0aW9uKVtdLFxuICAgICAgICBleGNsdWRlOiBzdHJpbmdbXVxuICAgICkge1xuICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgaW5jbHVkZSkge1xuICAgICAgICAgICAgbGV0IGN3ZCA9IFwiLlwiO1xuICAgICAgICAgICAgbGV0IGVudHJ5O1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgZW50cnkgPSBuYW1lO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjd2QgPSBuYW1lLmN3ZCB8fCBcIi5cIjtcbiAgICAgICAgICAgICAgICBlbnRyeSA9IG5hbWUucGF0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzb2x2ZWRQYXRoID0gcGF0aC5yZXNvbHZlKGN3ZCwgZW50cnkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGVudHJ5U3RhdCA9IGF3YWl0IHN0YXQocmVzb2x2ZWRQYXRoKTtcbiAgICAgICAgICAgICAgICBpZiAoZW50cnlTdGF0LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZW50cnkgPSBqb2luKGVudHJ5LCBcIi8qKi8qXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2gge31cbiAgICAgICAgICAgIGFyY2hpdmUuZ2xvYihlbnRyeSwgeyBpZ25vcmU6IGV4Y2x1ZGUgYXMgYW55LCBjd2QgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBwcmVwYXJlWmlwQXJjaGl2ZSgpOiBQcm9taXNlPFBhY2tlclJlc3VsdD4ge1xuICAgICAgICBjb25zdCBhcmNoaXZlID0gYXJjaGl2ZXIoXCJ6aXBcIiwgeyB6bGliOiB7IGxldmVsOiA4IH0gfSk7XG4gICAgICAgIGFyY2hpdmUub24oXCJlcnJvclwiLCBlcnIgPT4gbG9nLndhcm4oZXJyKSk7XG4gICAgICAgIGFyY2hpdmUub24oXCJ3YXJuaW5nXCIsIGVyciA9PiBsb2cud2FybihlcnIpKTtcbiAgICAgICAgYWRkVG9BcmNoaXZlKFwiL1wiLCBhcmNoaXZlKTtcbiAgICAgICAgY29uc3QgeyBpbmNsdWRlLCBleGNsdWRlIH0gPSBvcHRpb25zO1xuICAgICAgICBhd2FpdCBwcm9jZXNzSW5jbHVkZUV4Y2x1ZGUoYXJjaGl2ZSwgaW5jbHVkZSwgZXhjbHVkZSk7XG4gICAgICAgIGFyY2hpdmUuZmluYWxpemUoKTtcbiAgICAgICAgcmV0dXJuIHsgYXJjaGl2ZSB9O1xuICAgIH1cblxuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IChwYWNrYWdlSnNvbiAmJiAoYXdhaXQgYWRkUGFja2FnZUpzb24ocGFja2FnZUpzb24pKSkgfHwgW107XG5cbiAgICBmdW5jdGlvbiBydW5XZWJwYWNrKGVudHJ5OiBzdHJpbmcsIGVudHJ5TmFtZTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IGNvcmVDb25maWc6IHdlYnBhY2suQ29uZmlndXJhdGlvbiA9IHtcbiAgICAgICAgICAgIGVudHJ5OiB7IFtlbnRyeU5hbWVdOiBlbnRyeSB9LFxuICAgICAgICAgICAgbW9kZTogXCJkZXZlbG9wbWVudFwiLFxuICAgICAgICAgICAgb3V0cHV0OiB7XG4gICAgICAgICAgICAgICAgcGF0aDogXCIvXCIsXG4gICAgICAgICAgICAgICAgZmlsZW5hbWU6IFwiW25hbWVdLmpzXCIsXG4gICAgICAgICAgICAgICAgbGlicmFyeVRhcmdldDogXCJjb21tb25qczJcIlxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRhcmdldDogXCJub2RlXCIsXG4gICAgICAgICAgICByZXNvbHZlTG9hZGVyOiB7IG1vZHVsZXM6IFtfX2Rpcm5hbWUsIGAke19fZGlybmFtZX0vZGlzdGBdIH0sXG4gICAgICAgICAgICBub2RlOiB7IGdsb2JhbDogdHJ1ZSwgX19kaXJuYW1lOiBmYWxzZSwgX19maWxlbmFtZTogZmFsc2UgfVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBkZXBlbmRlbmN5RXh0ZXJuYWxzID0ge1xuICAgICAgICAgICAgZXh0ZXJuYWxzOiBbLi4uZGVwZW5kZW5jaWVzLCAuLi5kZXBlbmRlbmNpZXMubWFwKGQgPT4gbmV3IFJlZ0V4cChgXiR7ZH0vLipgKSldXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IG1lcmdlKGNvcmVDb25maWcsIGRlcGVuZGVuY3lFeHRlcm5hbHMsIHdlYnBhY2tPcHRpb25zKTtcbiAgICAgICAgbG9nLndlYnBhY2soYHdlYnBhY2sgY29uZmlnOiAlT2AsIGNvbmZpZyk7XG4gICAgICAgIGNvbnN0IGNvbXBpbGVyID0gd2VicGFjayhjb25maWcpO1xuICAgICAgICBjb21waWxlci5vdXRwdXRGaWxlU3lzdGVtID0gbWZzIGFzIGFueTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlLCByZWplY3QpID0+XG4gICAgICAgICAgICBjb21waWxlci5ydW4oKGVyciwgc3RhdHMpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzdGF0cz8uaGFzRXJyb3JzKCkgfHwgc3RhdHM/Lmhhc1dhcm5pbmdzKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGMgPSBzdGF0cy5jb21waWxhdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYy53YXJuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZXMucHVzaChgJHtjLndhcm5pbmdzLmxlbmd0aH0gd2FybmluZyhzKWApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGMuZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlcy5wdXNoKGAke2MuZXJyb3JzLmxlbmd0aH0gZXJyb3IocylgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy53YXJuKGB3ZWJwYWNrIGhhZCAke21lc3NhZ2VzLmpvaW4oXCIgYW5kIFwiKX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy53YXJuKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBzZXQgZW52aXJvbm1lbnQgdmFyaWFibGUgREVCVUc9ZmFhc3Q6d2VicGFjayBmb3IgZGV0YWlsc2BcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2cud2FybihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgc2VlIGh0dHBzOi8vZmFhc3Rqcy5vcmcvZG9jcy9hcGkvZmFhc3Rqcy5jb21tb25vcHRpb25zLnBhY2thZ2Vqc29uYFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobG9nLndlYnBhY2suZW5hYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nLndlYnBhY2soc3RhdHM/LnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nLndlYnBhY2soYE1lbW9yeSBmaWxlc3lzdGVtOiBgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBPYmplY3Qua2V5cyhtZnMuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2cud2VicGFjayhgICAke2ZpbGV9OiAke21mcy5kYXRhW2ZpbGVdLmxlbmd0aH1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCB7IGNoaWxkUHJvY2VzcywgdmFsaWRhdGVTZXJpYWxpemF0aW9uIH0gPSBvcHRpb25zO1xuICAgIGNvbnN0IHtcbiAgICAgICAgd3JhcHBlclZlcmJvc2UsXG4gICAgICAgIGNoaWxkUHJvY2VzczogX29ubHlVc2VkRm9yTG9jYWxQcm92aWRlckRpcmVjdFdyYXBwZXJJbnN0YW50aWF0aW9uLFxuICAgICAgICBjaGlsZERpcixcbiAgICAgICAgY2hpbGRQcm9jZXNzTWVtb3J5TGltaXRNYixcbiAgICAgICAgY2hpbGRQcm9jZXNzVGltZW91dE1zLFxuICAgICAgICBjaGlsZFByb2Nlc3NFbnZpcm9ubWVudDogX29ubHlVc2VkRm9yTG9jYWxQcm92aWRlckRpcmVjdFdyYXBwZXJJbnN0YW50aWF0aW9uMixcbiAgICAgICAgd3JhcHBlckxvZzogX29ubHlVc2VkRm9yTG9jYWxQcm92aWRlckRpcmVjdFdyYXBwZXJJbnN0YW50aWF0aW9uMyxcbiAgICAgICAgdmFsaWRhdGVTZXJpYWxpemF0aW9uOiBfaWdub3JlZEluRmF2b3JPZkNvbW1vbk9wdGlvbnNTZXR0aW5nLFxuICAgICAgICAuLi5yZXN0XG4gICAgfSA9IHdyYXBwZXJPcHRpb25zO1xuICAgIGNvbnN0IF9leGhhdXN0aXZlQ2hlY2syOiBSZXF1aXJlZDx0eXBlb2YgcmVzdD4gPSB7fTtcbiAgICBjb25zdCBpc1ZlcmJvc2UgPSB3cmFwcGVyVmVyYm9zZSB8fCBsb2cucHJvdmlkZXIuZW5hYmxlZDtcblxuICAgIGNvbnN0IGxvYWRlciA9IGBsb2FkZXI/JHtnZXRVcmxFbmNvZGVkUXVlcnlQYXJhbWV0ZXJzKHtcbiAgICAgICAgdHJhbXBvbGluZUZhY3RvcnlNb2R1bGU6IHRyYW1wb2xpbmVGYWN0b3J5LmZpbGVuYW1lLFxuICAgICAgICB3cmFwcGVyT3B0aW9uczoge1xuICAgICAgICAgICAgd3JhcHBlclZlcmJvc2U6IGlzVmVyYm9zZSxcbiAgICAgICAgICAgIGNoaWxkUHJvY2VzcyxcbiAgICAgICAgICAgIGNoaWxkRGlyLFxuICAgICAgICAgICAgY2hpbGRQcm9jZXNzTWVtb3J5TGltaXRNYixcbiAgICAgICAgICAgIGNoaWxkUHJvY2Vzc1RpbWVvdXRNcyxcbiAgICAgICAgICAgIHZhbGlkYXRlU2VyaWFsaXphdGlvblxuICAgICAgICB9LFxuICAgICAgICBmdW5jdGlvbk1vZHVsZVxuICAgIH0pfSFgO1xuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHJ1bldlYnBhY2sobG9hZGVyLCBcImluZGV4XCIpO1xuICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgIHRocm93IG5ldyBGYWFzdEVycm9yKGVyciwgXCJmYWlsZWQgcnVubmluZyB3ZWJwYWNrXCIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBsZXQgeyBhcmNoaXZlIH0gPSBhd2FpdCBwcmVwYXJlWmlwQXJjaGl2ZSgpO1xuICAgICAgICBjb25zdCBwYWNrYWdlRGlyID0gcHJvY2Vzcy5lbnZbXCJGQUFTVF9QQUNLQUdFX0RJUlwiXTtcbiAgICAgICAgaWYgKHBhY2thZ2VEaXIpIHtcbiAgICAgICAgICAgIGxvZy53ZWJwYWNrKGBGQUFTVF9QQUNLQUdFX0RJUjogJHtwYWNrYWdlRGlyfWApO1xuICAgICAgICAgICAgY29uc3QgcGFja2FnZUZpbGUgPSBqb2luKHBhY2thZ2VEaXIsIEZ1bmN0aW9uTmFtZSkgKyBcIi56aXBcIjtcbiAgICAgICAgICAgIGF3YWl0IGVuc3VyZURpcihwYWNrYWdlRGlyKTtcbiAgICAgICAgICAgIGNvbnN0IHdyaXRlU3RyZWFtID0gY3JlYXRlV3JpdGVTdHJlYW0ocGFja2FnZUZpbGUpO1xuICAgICAgICAgICAgY29uc3QgcGFzc1Rocm91Z2ggPSBhcmNoaXZlLnBpcGUobmV3IFBhc3NUaHJvdWdoKCkpO1xuICAgICAgICAgICAgYXJjaGl2ZSA9IGFyY2hpdmUucGlwZShuZXcgUGFzc1Rocm91Z2goKSk7XG4gICAgICAgICAgICBwYXNzVGhyb3VnaC5waXBlKHdyaXRlU3RyZWFtKTtcbiAgICAgICAgICAgIHdyaXRlU3RyZWFtLm9uKFwiY2xvc2VcIiwgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxvZy5pbmZvKGBXcm90ZSAke3BhY2thZ2VGaWxlfWApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgYXJjaGl2ZSB9O1xuICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgIHRocm93IG5ldyBGYWFzdEVycm9yKGVyciwgXCJmYWlsZWQgY3JlYXRpbmcgemlwIGFyY2hpdmVcIik7XG4gICAgfVxufVxuXG4vKipcbiAqIEBwYXJhbSB7Tm9kZUpTLlJlYWRhYmxlU3RyZWFtIHwgc3RyaW5nfSBhcmNoaXZlIEEgemlwIGFyY2hpdmUgYXMgYSBzdHJlYW0gb3IgYSBmaWxlbmFtZVxuICogQHBhcmFtIHsoZmlsZW5hbWU6IHN0cmluZywgY29udGVudHM6IFJlYWRhYmxlKSA9PiB2b2lkfSBwcm9jZXNzRW50cnkgRXZlcnlcbiAqIGVudHJ5J3MgY29udGVudHMgbXVzdCBiZSBjb25zdW1lZCwgb3RoZXJ3aXNlIHRoZSBuZXh0IGVudHJ5IHdvbid0IGJlIHJlYWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcm9jZXNzWmlwKFxuICAgIGFyY2hpdmU6IE5vZGVKUy5SZWFkYWJsZVN0cmVhbSB8IHN0cmluZyxcbiAgICBwcm9jZXNzRW50cnk6IChmaWxlbmFtZTogc3RyaW5nLCBjb250ZW50czogUmVhZGFibGUsIG1vZGU6IG51bWJlcikgPT4gdm9pZFxuKSB7XG4gICAgbGV0IHppcDogWmlwRmlsZTtcbiAgICBpZiAodHlwZW9mIGFyY2hpdmUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgemlwID0gYXdhaXQgbmV3IFByb21pc2U8WmlwRmlsZT4oKHJlc29sdmUsIHJlamVjdCkgPT5cbiAgICAgICAgICAgIHlhdXpsLm9wZW4oYXJjaGl2ZSwgeyBsYXp5RW50cmllczogdHJ1ZSB9LCAoZXJyLCB6aXBmaWxlKSA9PlxuICAgICAgICAgICAgICAgIGVyciA/IHJlamVjdChlcnIpIDogcmVzb2x2ZSh6aXBmaWxlISlcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBidWYgPSBhd2FpdCBzdHJlYW1Ub0J1ZmZlcihhcmNoaXZlKTtcbiAgICAgICAgemlwID0gYXdhaXQgbmV3IFByb21pc2U8WmlwRmlsZT4oKHJlc29sdmUsIHJlamVjdCkgPT5cbiAgICAgICAgICAgIHlhdXpsLmZyb21CdWZmZXIoYnVmLCB7IGxhenlFbnRyaWVzOiB0cnVlIH0sIChlcnIsIHppcGZpbGUpID0+XG4gICAgICAgICAgICAgICAgZXJyID8gcmVqZWN0KGVycikgOiByZXNvbHZlKHppcGZpbGUhKVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHppcC5yZWFkRW50cnkoKTtcbiAgICAgICAgemlwLm9uKFwiZW50cnlcIiwgKGVudHJ5OiB5YXV6bC5FbnRyeSkgPT4ge1xuICAgICAgICAgICAgaWYgKC9cXC8kLy50ZXN0KGVudHJ5LmZpbGVOYW1lKSkge1xuICAgICAgICAgICAgICAgIHppcC5yZWFkRW50cnkoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgemlwLm9wZW5SZWFkU3RyZWFtKGVudHJ5LCAoZXJyLCByZWFkU3RyZWFtKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlYWRTdHJlYW0hLm9uKFwiZW5kXCIsICgpID0+IHppcC5yZWFkRW50cnkoKSk7XG4gICAgICAgICAgICAgICAgICAgIHByb2Nlc3NFbnRyeShcbiAgICAgICAgICAgICAgICAgICAgICAgIGVudHJ5LmZpbGVOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhZFN0cmVhbSEsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbnRyeS5leHRlcm5hbEZpbGVBdHRyaWJ1dGVzID4+PiAxNlxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgemlwLm9uKFwiZW5kXCIsIHJlc29sdmUpO1xuICAgIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdW56aXBJbkRpcihkaXI6IHN0cmluZywgYXJjaGl2ZTogTm9kZUpTLlJlYWRhYmxlU3RyZWFtKSB7XG4gICAgYXdhaXQgbWtkaXJwKGRpcik7XG4gICAgbGV0IHRvdGFsID0gMDtcbiAgICBhd2FpdCBwcm9jZXNzWmlwKGFyY2hpdmUsIGFzeW5jIChmaWxlbmFtZSwgY29udGVudHMsIG1vZGUpID0+IHtcbiAgICAgICAgY29uc3QgZGVzdGluYXRpb25GaWxlbmFtZSA9IHBhdGguam9pbihkaXIsIGZpbGVuYW1lKTtcbiAgICAgICAgY29uc3QgeyBkaXI6IG91dHB1dERpciB9ID0gcGF0aC5wYXJzZShkZXN0aW5hdGlvbkZpbGVuYW1lKTtcbiAgICAgICAgaWYgKCEoYXdhaXQgcGF0aEV4aXN0cyhvdXRwdXREaXIpKSkge1xuICAgICAgICAgICAgYXdhaXQgbWtkaXJwKG91dHB1dERpcik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3RyZWFtID0gY3JlYXRlV3JpdGVTdHJlYW0oZGVzdGluYXRpb25GaWxlbmFtZSwgeyBtb2RlIH0pO1xuICAgICAgICBjb250ZW50cy5vbihcImRhdGFcIiwgY2h1bmsgPT4gKHRvdGFsICs9IGNodW5rLmxlbmd0aCkpO1xuICAgICAgICBjb250ZW50cy5waXBlKHN0cmVhbSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRvdGFsO1xufVxuIl19