faastjs
Version:
Serverless batch computing made simple.
240 lines • 38.1 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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Q0FBQztRQUNoRSxRQUFRLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1FBQ3RELFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUIsQ0FBQyxDQUFDLENBQUM7SUFDSCxPQUFPLEtBQUssQ0FBQztBQUNqQixDQUFDO0FBZEQsZ0NBY0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgYXJjaGl2ZXIsIHsgQXJjaGl2ZXIgfSBmcm9tIFwiYXJjaGl2ZXJcIjtcbmltcG9ydCB7XG4gICAgY3JlYXRlV3JpdGVTdHJlYW0sXG4gICAgZW5zdXJlRGlyLFxuICAgIG1rZGlycCxcbiAgICBwYXRoRXhpc3RzLFxuICAgIHJlYWRGaWxlLFxuICAgIHN0YXRcbn0gZnJvbSBcImZzLWV4dHJhXCI7XG5pbXBvcnQgTWVtb3J5RmlsZVN5c3RlbSBmcm9tIFwibWVtb3J5LWZzXCI7XG5pbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgeyBQYXNzVGhyb3VnaCwgUmVhZGFibGUgfSBmcm9tIFwic3RyZWFtXCI7XG5pbXBvcnQgd2VicGFjayBmcm9tIFwid2VicGFja1wiO1xuaW1wb3J0IHsgbWVyZ2UgfSBmcm9tIFwid2VicGFjay1tZXJnZVwiO1xuaW1wb3J0IHlhdXpsIGZyb20gXCJ5YXV6bFwiO1xuaW1wb3J0IHsgRmFhc3RFcnJvciB9IGZyb20gXCIuL2Vycm9yXCI7XG5pbXBvcnQgeyBMb2FkZXJPcHRpb25zIH0gZnJvbSBcIi4vbG9hZGVyXCI7XG5pbXBvcnQgeyBsb2cgfSBmcm9tIFwiLi9sb2dcIjtcbmltcG9ydCB7IGNvbW1vbkRlZmF1bHRzLCBDb21tb25PcHRpb25zLCBJbmNsdWRlT3B0aW9uIH0gZnJvbSBcIi4vcHJvdmlkZXJcIjtcbmltcG9ydCB7IGtleXNPZiwgc3RyZWFtVG9CdWZmZXIgfSBmcm9tIFwiLi9zaGFyZWRcIjtcbmltcG9ydCB7IFRyYW1wb2xpbmVGYWN0b3J5LCBXcmFwcGVyT3B0aW9uRGVmYXVsdHMsIFdyYXBwZXJPcHRpb25zIH0gZnJvbSBcIi4vd3JhcHBlclwiO1xuXG50eXBlIFppcEZpbGUgPSB5YXV6bC5aaXBGaWxlO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBhY2tlclJlc3VsdCB7XG4gICAgYXJjaGl2ZTogTm9kZUpTLlJlYWRhYmxlU3RyZWFtO1xufVxuXG5mdW5jdGlvbiBnZXRVcmxFbmNvZGVkUXVlcnlQYXJhbWV0ZXJzKG9wdGlvbnM6IExvYWRlck9wdGlvbnMpIHtcbiAgICByZXR1cm4ga2V5c09mKG9wdGlvbnMpXG4gICAgICAgIC5maWx0ZXIoa2V5ID0+IG9wdGlvbnNba2V5XSlcbiAgICAgICAgLm1hcChrZXkgPT4gYCR7a2V5fT0ke2VuY29kZVVSSUNvbXBvbmVudChKU09OLnN0cmluZ2lmeShvcHRpb25zW2tleV0pKX1gKVxuICAgICAgICAuam9pbihgJmApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcGFja2VyKFxuICAgIHRyYW1wb2xpbmVGYWN0b3J5OiBUcmFtcG9saW5lRmFjdG9yeSxcbiAgICBmdW5jdGlvbk1vZHVsZTogc3RyaW5nLFxuICAgIHVzZXJPcHRpb25zOiBDb21tb25PcHRpb25zLFxuICAgIHVzZXJXcmFwcGVyT3B0aW9uczogV3JhcHBlck9wdGlvbnMsXG4gICAgRnVuY3Rpb25OYW1lOiBzdHJpbmdcbik6IFByb21pc2U8UGFja2VyUmVzdWx0PiB7XG4gICAgY29uc3Qgb3B0aW9ucyA9IHsgLi4uY29tbW9uRGVmYXVsdHMsIC4uLnVzZXJPcHRpb25zIH07XG4gICAgY29uc3Qgd3JhcHBlck9wdGlvbnMgPSB7IC4uLldyYXBwZXJPcHRpb25EZWZhdWx0cywgLi4udXNlcldyYXBwZXJPcHRpb25zIH07XG4gICAgY29uc3QgeyB3ZWJwYWNrT3B0aW9ucywgcGFja2FnZUpzb24gfSA9IG9wdGlvbnM7XG5cbiAgICBsb2cuaW5mbyhgUnVubmluZyB3ZWJwYWNrYCk7XG4gICAgY29uc3QgbWZzID0gbmV3IE1lbW9yeUZpbGVTeXN0ZW0oKTtcblxuICAgIGZ1bmN0aW9uIGFkZFRvQXJjaGl2ZShyb290OiBzdHJpbmcsIGFyY2hpdmU6IEFyY2hpdmVyKSB7XG4gICAgICAgIGZ1bmN0aW9uIGFkZEVudHJ5KGVudHJ5OiBzdHJpbmcpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRFbnRyeSA9IG1mcy5zdGF0U3luYyhlbnRyeSk7XG4gICAgICAgICAgICBpZiAoc3RhdEVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHN1YkVudHJ5IG9mIG1mcy5yZWFkZGlyU3luYyhlbnRyeSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3ViRW50cnlQYXRoID0gcGF0aC5qb2luKGVudHJ5LCBzdWJFbnRyeSk7XG4gICAgICAgICAgICAgICAgICAgIGFkZEVudHJ5KHN1YkVudHJ5UGF0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChzdGF0RW50cnkuaXNGaWxlKCkpIHtcbiAgICAgICAgICAgICAgICBsb2cuaW5mbyhgQWRkaW5nIGZpbGU6ICR7ZW50cnl9YCk7XG4gICAgICAgICAgICAgICAgYXJjaGl2ZS5hcHBlbmQoKG1mcyBhcyBhbnkpLmNyZWF0ZVJlYWRTdHJlYW0oZW50cnkpLCB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IHBhdGgucmVsYXRpdmUocm9vdCwgZW50cnkpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYWRkRW50cnkocm9vdCk7XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gYWRkUGFja2FnZUpzb24ocGFja2FnZUpzb25GaWxlOiBzdHJpbmcgfCBvYmplY3QpIHtcbiAgICAgICAgY29uc3QgcGFyc2VkUGFja2FnZUpzb24gPVxuICAgICAgICAgICAgdHlwZW9mIHBhY2thZ2VKc29uRmlsZSA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICAgID8gSlNPTi5wYXJzZShcbiAgICAgICAgICAgICAgICAgICAgICAoYXdhaXQgcmVhZEZpbGUoYXdhaXQgcmVzb2x2ZVBhdGgocGFja2FnZUpzb25GaWxlKSkpLnRvU3RyaW5nKClcbiAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICA6IHsgLi4ucGFja2FnZUpzb25GaWxlIH07XG4gICAgICAgIHBhcnNlZFBhY2thZ2VKc29uLm1haW4gPSBcImluZGV4LmpzXCI7XG4gICAgICAgIG1mcy53cml0ZUZpbGVTeW5jKFxuICAgICAgICAgICAgXCIvcGFja2FnZS5qc29uXCIsXG4gICAgICAgICAgICBKU09OLnN0cmluZ2lmeShwYXJzZWRQYWNrYWdlSnNvbiwgdW5kZWZpbmVkLCAyKVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMocGFyc2VkUGFja2FnZUpzb24uZGVwZW5kZW5jaWVzIHx8IHt9KTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiByZXNvbHZlUGF0aChwYXRoTmFtZTogc3RyaW5nKSB7XG4gICAgICAgIGlmIChhd2FpdCBwYXRoRXhpc3RzKHBhdGhOYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuIHBhdGhOYW1lO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBGYWFzdEVycm9yKGBDb3VsZCBub3QgZmluZCBcIiR7cGF0aE5hbWV9XCJgKTtcbiAgICB9XG5cbiAgICBhc3luYyBmdW5jdGlvbiBwcm9jZXNzSW5jbHVkZUV4Y2x1ZGUoXG4gICAgICAgIGFyY2hpdmU6IEFyY2hpdmVyLFxuICAgICAgICBpbmNsdWRlOiAoc3RyaW5nIHwgSW5jbHVkZU9wdGlvbilbXSxcbiAgICAgICAgZXhjbHVkZTogc3RyaW5nW11cbiAgICApIHtcbiAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIGluY2x1ZGUpIHtcbiAgICAgICAgICAgIGxldCBjd2QgPSBcIi5cIjtcbiAgICAgICAgICAgIGxldCBlbnRyeTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIGVudHJ5ID0gbmFtZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY3dkID0gbmFtZS5jd2QgfHwgXCIuXCI7XG4gICAgICAgICAgICAgICAgZW50cnkgPSBuYW1lLnBhdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc29sdmVkUGF0aCA9IHBhdGgucmVzb2x2ZShjd2QsIGVudHJ5KTtcbiAgICAgICAgICAgICAgICBjb25zdCBlbnRyeVN0YXQgPSBhd2FpdCBzdGF0KHJlc29sdmVkUGF0aCk7XG4gICAgICAgICAgICAgICAgaWYgKGVudHJ5U3RhdC5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVudHJ5ID0gam9pbihlbnRyeSwgXCIvKiovKlwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIHt9XG4gICAgICAgICAgICBhcmNoaXZlLmdsb2IoZW50cnksIHsgaWdub3JlOiBleGNsdWRlIGFzIGFueSwgY3dkIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgZnVuY3Rpb24gcHJlcGFyZVppcEFyY2hpdmUoKTogUHJvbWlzZTxQYWNrZXJSZXN1bHQ+IHtcbiAgICAgICAgY29uc3QgYXJjaGl2ZSA9IGFyY2hpdmVyKFwiemlwXCIsIHsgemxpYjogeyBsZXZlbDogOCB9IH0pO1xuICAgICAgICBhcmNoaXZlLm9uKFwiZXJyb3JcIiwgZXJyID0+IGxvZy53YXJuKGVycikpO1xuICAgICAgICBhcmNoaXZlLm9uKFwid2FybmluZ1wiLCBlcnIgPT4gbG9nLndhcm4oZXJyKSk7XG4gICAgICAgIGFkZFRvQXJjaGl2ZShcIi9cIiwgYXJjaGl2ZSk7XG4gICAgICAgIGNvbnN0IHsgaW5jbHVkZSwgZXhjbHVkZSB9ID0gb3B0aW9ucztcbiAgICAgICAgYXdhaXQgcHJvY2Vzc0luY2x1ZGVFeGNsdWRlKGFyY2hpdmUsIGluY2x1ZGUsIGV4Y2x1ZGUpO1xuICAgICAgICBhcmNoaXZlLmZpbmFsaXplKCk7XG4gICAgICAgIHJldHVybiB7IGFyY2hpdmUgfTtcbiAgICB9XG5cbiAgICBjb25zdCBkZXBlbmRlbmNpZXMgPSAocGFja2FnZUpzb24gJiYgKGF3YWl0IGFkZFBhY2thZ2VKc29uKHBhY2thZ2VKc29uKSkpIHx8IFtdO1xuXG4gICAgZnVuY3Rpb24gcnVuV2VicGFjayhlbnRyeTogc3RyaW5nLCBlbnRyeU5hbWU6IHN0cmluZykge1xuICAgICAgICBjb25zdCBjb3JlQ29uZmlnOiB3ZWJwYWNrLkNvbmZpZ3VyYXRpb24gPSB7XG4gICAgICAgICAgICBlbnRyeTogeyBbZW50cnlOYW1lXTogZW50cnkgfSxcbiAgICAgICAgICAgIG1vZGU6IFwiZGV2ZWxvcG1lbnRcIixcbiAgICAgICAgICAgIG91dHB1dDoge1xuICAgICAgICAgICAgICAgIHBhdGg6IFwiL1wiLFxuICAgICAgICAgICAgICAgIGZpbGVuYW1lOiBcIltuYW1lXS5qc1wiLFxuICAgICAgICAgICAgICAgIGxpYnJhcnlUYXJnZXQ6IFwiY29tbW9uanMyXCJcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0YXJnZXQ6IFwibm9kZVwiLFxuICAgICAgICAgICAgcmVzb2x2ZUxvYWRlcjogeyBtb2R1bGVzOiBbX19kaXJuYW1lLCBgJHtfX2Rpcm5hbWV9L2Rpc3RgXSB9LFxuICAgICAgICAgICAgbm9kZTogeyBnbG9iYWw6IHRydWUsIF9fZGlybmFtZTogZmFsc2UsIF9fZmlsZW5hbWU6IGZhbHNlIH1cbiAgICAgICAgfTtcbiAgICAgICAgY29uc3QgZGVwZW5kZW5jeUV4dGVybmFscyA9IHtcbiAgICAgICAgICAgIGV4dGVybmFsczogWy4uLmRlcGVuZGVuY2llcywgLi4uZGVwZW5kZW5jaWVzLm1hcChkID0+IG5ldyBSZWdFeHAoYF4ke2R9Ly4qYCkpXVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBjb25maWcgPSBtZXJnZShjb3JlQ29uZmlnLCBkZXBlbmRlbmN5RXh0ZXJuYWxzLCB3ZWJwYWNrT3B0aW9ucyk7XG4gICAgICAgIGxvZy53ZWJwYWNrKGB3ZWJwYWNrIGNvbmZpZzogJU9gLCBjb25maWcpO1xuICAgICAgICBjb25zdCBjb21waWxlciA9IHdlYnBhY2soY29uZmlnKTtcbiAgICAgICAgY29tcGlsZXIub3V0cHV0RmlsZVN5c3RlbSA9IG1mcyBhcyBhbnk7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PlxuICAgICAgICAgICAgY29tcGlsZXIucnVuKChlcnIsIHN0YXRzKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc3RhdHM/Lmhhc0Vycm9ycygpIHx8IHN0YXRzPy5oYXNXYXJuaW5ncygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjID0gc3RhdHMuY29tcGlsYXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXNzYWdlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGMud2FybmluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VzLnB1c2goYCR7Yy53YXJuaW5ncy5sZW5ndGh9IHdhcm5pbmcocylgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjLmVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZXMucHVzaChgJHtjLmVycm9ycy5sZW5ndGh9IGVycm9yKHMpYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2cud2Fybihgd2VicGFjayBoYWQgJHttZXNzYWdlcy5qb2luKFwiIGFuZCBcIil9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2cud2FybihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBgc2V0IGVudmlyb25tZW50IHZhcmlhYmxlIERFQlVHPWZhYXN0OndlYnBhY2sgZm9yIGRldGFpbHNgXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nLndhcm4oXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYHNlZSBodHRwczovL2ZhYXN0anMub3JnL2RvY3MvYXBpL2ZhYXN0anMuY29tbW9ub3B0aW9ucy5wYWNrYWdlanNvbmBcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxvZy53ZWJwYWNrLmVuYWJsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy53ZWJwYWNrKHN0YXRzPy50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxvZy53ZWJwYWNrKGBNZW1vcnkgZmlsZXN5c3RlbTogYCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgT2JqZWN0LmtleXMobWZzLmRhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nLndlYnBhY2soYCAgJHtmaWxlfTogJHttZnMuZGF0YVtmaWxlXS5sZW5ndGh9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgeyBjaGlsZFByb2Nlc3MsIHZhbGlkYXRlU2VyaWFsaXphdGlvbiB9ID0gb3B0aW9ucztcbiAgICBjb25zdCB7XG4gICAgICAgIHdyYXBwZXJWZXJib3NlLFxuICAgICAgICBjaGlsZFByb2Nlc3M6IF9vbmx5VXNlZEZvckxvY2FsUHJvdmlkZXJEaXJlY3RXcmFwcGVySW5zdGFudGlhdGlvbixcbiAgICAgICAgY2hpbGREaXIsXG4gICAgICAgIGNoaWxkUHJvY2Vzc01lbW9yeUxpbWl0TWIsXG4gICAgICAgIGNoaWxkUHJvY2Vzc1RpbWVvdXRNcyxcbiAgICAgICAgY2hpbGRQcm9jZXNzRW52aXJvbm1lbnQ6IF9vbmx5VXNlZEZvckxvY2FsUHJvdmlkZXJEaXJlY3RXcmFwcGVySW5zdGFudGlhdGlvbjIsXG4gICAgICAgIHdyYXBwZXJMb2c6IF9vbmx5VXNlZEZvckxvY2FsUHJvdmlkZXJEaXJlY3RXcmFwcGVySW5zdGFudGlhdGlvbjMsXG4gICAgICAgIHZhbGlkYXRlU2VyaWFsaXphdGlvbjogX2lnbm9yZWRJbkZhdm9yT2ZDb21tb25PcHRpb25zU2V0dGluZyxcbiAgICAgICAgLi4ucmVzdFxuICAgIH0gPSB3cmFwcGVyT3B0aW9ucztcbiAgICBjb25zdCBfZXhoYXVzdGl2ZUNoZWNrMjogUmVxdWlyZWQ8dHlwZW9mIHJlc3Q+ID0ge307XG4gICAgY29uc3QgaXNWZXJib3NlID0gd3JhcHBlclZlcmJvc2UgfHwgbG9nLnByb3ZpZGVyLmVuYWJsZWQ7XG5cbiAgICBjb25zdCBsb2FkZXIgPSBgbG9hZGVyPyR7Z2V0VXJsRW5jb2RlZFF1ZXJ5UGFyYW1ldGVycyh7XG4gICAgICAgIHRyYW1wb2xpbmVGYWN0b3J5TW9kdWxlOiB0cmFtcG9saW5lRmFjdG9yeS5maWxlbmFtZSxcbiAgICAgICAgd3JhcHBlck9wdGlvbnM6IHtcbiAgICAgICAgICAgIHdyYXBwZXJWZXJib3NlOiBpc1ZlcmJvc2UsXG4gICAgICAgICAgICBjaGlsZFByb2Nlc3MsXG4gICAgICAgICAgICBjaGlsZERpcixcbiAgICAgICAgICAgIGNoaWxkUHJvY2Vzc01lbW9yeUxpbWl0TWIsXG4gICAgICAgICAgICBjaGlsZFByb2Nlc3NUaW1lb3V0TXMsXG4gICAgICAgICAgICB2YWxpZGF0ZVNlcmlhbGl6YXRpb25cbiAgICAgICAgfSxcbiAgICAgICAgZnVuY3Rpb25Nb2R1bGVcbiAgICB9KX0hYDtcbiAgICB0cnkge1xuICAgICAgICBhd2FpdCBydW5XZWJwYWNrKGxvYWRlciwgXCJpbmRleFwiKTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICB0aHJvdyBuZXcgRmFhc3RFcnJvcihlcnIsIFwiZmFpbGVkIHJ1bm5pbmcgd2VicGFja1wiKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgbGV0IHsgYXJjaGl2ZSB9ID0gYXdhaXQgcHJlcGFyZVppcEFyY2hpdmUoKTtcbiAgICAgICAgY29uc3QgcGFja2FnZURpciA9IHByb2Nlc3MuZW52W1wiRkFBU1RfUEFDS0FHRV9ESVJcIl07XG4gICAgICAgIGlmIChwYWNrYWdlRGlyKSB7XG4gICAgICAgICAgICBsb2cud2VicGFjayhgRkFBU1RfUEFDS0FHRV9ESVI6ICR7cGFja2FnZURpcn1gKTtcbiAgICAgICAgICAgIGNvbnN0IHBhY2thZ2VGaWxlID0gam9pbihwYWNrYWdlRGlyLCBGdW5jdGlvbk5hbWUpICsgXCIuemlwXCI7XG4gICAgICAgICAgICBhd2FpdCBlbnN1cmVEaXIocGFja2FnZURpcik7XG4gICAgICAgICAgICBjb25zdCB3cml0ZVN0cmVhbSA9IGNyZWF0ZVdyaXRlU3RyZWFtKHBhY2thZ2VGaWxlKTtcbiAgICAgICAgICAgIGNvbnN0IHBhc3NUaHJvdWdoID0gYXJjaGl2ZS5waXBlKG5ldyBQYXNzVGhyb3VnaCgpKTtcbiAgICAgICAgICAgIGFyY2hpdmUgPSBhcmNoaXZlLnBpcGUobmV3IFBhc3NUaHJvdWdoKCkpO1xuICAgICAgICAgICAgcGFzc1Rocm91Z2gucGlwZSh3cml0ZVN0cmVhbSk7XG4gICAgICAgICAgICB3cml0ZVN0cmVhbS5vbihcImNsb3NlXCIsICgpID0+IHtcbiAgICAgICAgICAgICAgICBsb2cuaW5mbyhgV3JvdGUgJHtwYWNrYWdlRmlsZX1gKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IGFyY2hpdmUgfTtcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xuICAgICAgICB0aHJvdyBuZXcgRmFhc3RFcnJvcihlcnIsIFwiZmFpbGVkIGNyZWF0aW5nIHppcCBhcmNoaXZlXCIpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBAcGFyYW0ge05vZGVKUy5SZWFkYWJsZVN0cmVhbSB8IHN0cmluZ30gYXJjaGl2ZSBBIHppcCBhcmNoaXZlIGFzIGEgc3RyZWFtIG9yIGEgZmlsZW5hbWVcbiAqIEBwYXJhbSB7KGZpbGVuYW1lOiBzdHJpbmcsIGNvbnRlbnRzOiBSZWFkYWJsZSkgPT4gdm9pZH0gcHJvY2Vzc0VudHJ5IEV2ZXJ5XG4gKiBlbnRyeSdzIGNvbnRlbnRzIG11c3QgYmUgY29uc3VtZWQsIG90aGVyd2lzZSB0aGUgbmV4dCBlbnRyeSB3b24ndCBiZSByZWFkLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJvY2Vzc1ppcChcbiAgICBhcmNoaXZlOiBOb2RlSlMuUmVhZGFibGVTdHJlYW0gfCBzdHJpbmcsXG4gICAgcHJvY2Vzc0VudHJ5OiAoZmlsZW5hbWU6IHN0cmluZywgY29udGVudHM6IFJlYWRhYmxlLCBtb2RlOiBudW1iZXIpID0+IHZvaWRcbikge1xuICAgIGxldCB6aXA6IFppcEZpbGU7XG4gICAgaWYgKHR5cGVvZiBhcmNoaXZlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHppcCA9IGF3YWl0IG5ldyBQcm9taXNlPFppcEZpbGU+KChyZXNvbHZlLCByZWplY3QpID0+XG4gICAgICAgICAgICB5YXV6bC5vcGVuKGFyY2hpdmUsIHsgbGF6eUVudHJpZXM6IHRydWUgfSwgKGVyciwgemlwZmlsZSkgPT5cbiAgICAgICAgICAgICAgICBlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUoemlwZmlsZSEpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgYnVmID0gYXdhaXQgc3RyZWFtVG9CdWZmZXIoYXJjaGl2ZSk7XG4gICAgICAgIHppcCA9IGF3YWl0IG5ldyBQcm9taXNlPFppcEZpbGU+KChyZXNvbHZlLCByZWplY3QpID0+XG4gICAgICAgICAgICB5YXV6bC5mcm9tQnVmZmVyKGJ1ZiwgeyBsYXp5RW50cmllczogdHJ1ZSB9LCAoZXJyLCB6aXBmaWxlKSA9PlxuICAgICAgICAgICAgICAgIGVyciA/IHJlamVjdChlcnIpIDogcmVzb2x2ZSh6aXBmaWxlISlcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB6aXAucmVhZEVudHJ5KCk7XG4gICAgICAgIHppcC5vbihcImVudHJ5XCIsIChlbnRyeTogeWF1emwuRW50cnkpID0+IHtcbiAgICAgICAgICAgIGlmICgvXFwvJC8udGVzdChlbnRyeS5maWxlTmFtZSkpIHtcbiAgICAgICAgICAgICAgICB6aXAucmVhZEVudHJ5KCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHppcC5vcGVuUmVhZFN0cmVhbShlbnRyeSwgKGVyciwgcmVhZFN0cmVhbSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZWFkU3RyZWFtIS5vbihcImVuZFwiLCAoKSA9PiB6aXAucmVhZEVudHJ5KCkpO1xuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzRW50cnkoXG4gICAgICAgICAgICAgICAgICAgICAgICBlbnRyeS5maWxlTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWRTdHJlYW0hLFxuICAgICAgICAgICAgICAgICAgICAgICAgZW50cnkuZXh0ZXJuYWxGaWxlQXR0cmlidXRlcyA+Pj4gMTZcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHppcC5vbihcImVuZFwiLCByZXNvbHZlKTtcbiAgICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVuemlwSW5EaXIoZGlyOiBzdHJpbmcsIGFyY2hpdmU6IE5vZGVKUy5SZWFkYWJsZVN0cmVhbSkge1xuICAgIGF3YWl0IG1rZGlycChkaXIpO1xuICAgIGxldCB0b3RhbCA9IDA7XG4gICAgYXdhaXQgcHJvY2Vzc1ppcChhcmNoaXZlLCBhc3luYyAoZmlsZW5hbWUsIGNvbnRlbnRzLCBtb2RlKSA9PiB7XG4gICAgICAgIGNvbnN0IGRlc3RpbmF0aW9uRmlsZW5hbWUgPSBwYXRoLmpvaW4oZGlyLCBmaWxlbmFtZSk7XG4gICAgICAgIGNvbnN0IHsgZGlyOiBvdXRwdXREaXIgfSA9IHBhdGgucGFyc2UoZGVzdGluYXRpb25GaWxlbmFtZSk7XG4gICAgICAgIGlmICghKGF3YWl0IHBhdGhFeGlzdHMob3V0cHV0RGlyKSkpIHtcbiAgICAgICAgICAgIGF3YWl0IG1rZGlycChvdXRwdXREaXIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0cmVhbSA9IGNyZWF0ZVdyaXRlU3RyZWFtKGRlc3RpbmF0aW9uRmlsZW5hbWUsIHsgbW9kZSB9KTtcbiAgICAgICAgY29udGVudHMub24oXCJkYXRhXCIsIGNodW5rID0+ICh0b3RhbCArPSBjaHVuay5sZW5ndGgpKTtcbiAgICAgICAgY29udGVudHMucGlwZShzdHJlYW0pO1xuICAgIH0pO1xuICAgIHJldHVybiB0b3RhbDtcbn1cbiJdfQ==
;