"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.onAfterBuild = exports.onBeforeBuild = exports.throwError = void 0; /** * 构建进程(独立 worker)加载的钩子脚本;custom-builder 的 configs.*.hooks 指向本文件。 * custom-builder.ts 会 re-export 本文件的钩子,供编辑器校验通过。 */ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const lz4js_1 = __importDefault(require("lz4js")); const terser_1 = require("terser"); const MembershipSet_1 = require("./MembershipSet"); exports.throwError = true; function readJson(filePath) { const raw = fs_1.default.readFileSync(filePath, 'utf8'); return JSON.parse(raw); } function resolveConfigNameVersion(projectPath) { var _a, _b, _c, _d, _e, _f; const sdkConfigPath = path_1.default.join(projectPath, 'assets', 'script', 'sdk', 'sdkConfig.ts'); const sdkConfigContent = fs_1.default.readFileSync(sdkConfigPath, 'utf8'); const importRegex = /import\s+\{\s*(\w+)\s*\}\s+from\s+["']\.\/config\/([^"']+)["'];?/g; const importMap = new Map(); let m = null; while ((m = importRegex.exec(sdkConfigContent))) { importMap.set(m[1], m[2]); } const configAssign = sdkConfigContent.match(/static\s+readonly\s+config\s*:\s*IConfigData\s*=\s*(\w+)\s*;/); const symbol = (_a = configAssign === null || configAssign === void 0 ? void 0 : configAssign[1]) !== null && _a !== void 0 ? _a : 'DefaultConfig'; const relConfig = (_b = importMap.get(symbol)) !== null && _b !== void 0 ? _b : 'DefaultConfig'; const configPath = path_1.default.join(projectPath, 'assets', 'script', 'sdk', 'config', `${relConfig}.ts`); const configContent = fs_1.default.readFileSync(configPath, 'utf8'); const name = (_d = (_c = configContent.match(/name\s*:\s*["']([^"']+)["']/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : 'config'; const vsion = (_f = (_e = configContent.match(/vsion\s*:\s*["']([^"']+)["']/)) === null || _e === void 0 ? void 0 : _e[1]) !== null && _f !== void 0 ? _f : '0.0.0'; return { name, vsion }; } function encodeForRuntime(jsonObj) { const jsonString = JSON.stringify(jsonObj); const uint8 = new TextEncoder().encode(jsonString); const compressed = Uint8Array.from(lz4js_1.default.compress(uint8)); const binary = Buffer.from(compressed).toString('latin1'); const base64 = Buffer.from(binary, 'latin1').toString('base64'); return Buffer.from(base64, 'latin1'); } const HOT_UPDATE_TABLE_FILES = [ { tableKey: 'Monster', fileName: 'Monster.json' }, { tableKey: 'Const', fileName: 'Const.json' }, { tableKey: 'Rank', fileName: 'Rank.json' }, { tableKey: 'Item', fileName: 'Item.json' }, { tableKey: 'Level', fileName: 'Level.json' }, { tableKey: 'Skill', fileName: 'Skill.json' }, { tableKey: 'Battlebuff', fileName: 'Battlebuff.json' }, { tableKey: 'Weapon', fileName: 'Weapon.json' }, { tableKey: 'Text', fileName: 'Text.json' }, { tableKey: 'Hero', fileName: 'Hero.json' }, { tableKey: 'Headicon', fileName: 'Headicon.json' }, ]; function generateConfigBin() { const projectPath = Editor.Project.path; const configDir = path_1.default.join(projectPath, 'assets', 'bundles', 'first', 'config'); const mergeJson = {}; for (const { tableKey, fileName } of HOT_UPDATE_TABLE_FILES) { const fp = path_1.default.join(configDir, fileName); if (!fs_1.default.existsSync(fp)) { console.warn(`[tools] skip bin generate: missing ${fileName}`); return; } mergeJson[tableKey] = readJson(fp); } const { name, vsion } = resolveConfigNameVersion(projectPath); const safeName = `${name}${vsion}`.replace(/[<>:"/\\|?*]+/g, '_'); const outDir = path_1.default.join(projectPath, 'bin'); const outFile = path_1.default.join(outDir, `${safeName}.bin`); fs_1.default.mkdirSync(outDir, { recursive: true }); fs_1.default.writeFileSync(outFile, encodeForRuntime(mergeJson)); console.log(`[tools] generated config bin: ${outFile}`); } function collectJsFiles(dir, acc) { if (!fs_1.default.existsSync(dir)) return; const st = fs_1.default.statSync(dir); if (!st.isDirectory()) return; const entries = fs_1.default.readdirSync(dir, { withFileTypes: true }); for (const e of entries) { const full = path_1.default.join(dir, e.name); if (e.isDirectory()) { collectJsFiles(full, acc); } else if (e.isFile() && e.name.endsWith('.js')) { acc.push(full); } } } function collectStripRoots(options, result) { var _a, _b, _c, _d; const roots = (0, MembershipSet_1.createMembershipSet)(); const add = (p) => { if (p == null || p === '') return; const s = path_1.default.normalize(String(p).replace(/\//g, path_1.default.sep)); try { if (fs_1.default.existsSync(s)) { const st = fs_1.default.statSync(s); if (st.isDirectory()) (0, MembershipSet_1.membershipAdd)(roots, s); } } catch (_a) { /* ignore */ } }; add(result === null || result === void 0 ? void 0 : result.dest); add((_a = result === null || result === void 0 ? void 0 : result.paths) === null || _a === void 0 ? void 0 : _a.dir); add((_b = result === null || result === void 0 ? void 0 : result.paths) === null || _b === void 0 ? void 0 : _b.assets); add((_c = result === null || result === void 0 ? void 0 : result.paths) === null || _c === void 0 ? void 0 : _c.bundleScripts); add((_d = result === null || result === void 0 ? void 0 : result.paths) === null || _d === void 0 ? void 0 : _d.subpackages); const projectPath = Editor.Project.path; if (projectPath && (options === null || options === void 0 ? void 0 : options.buildPath) && (options === null || options === void 0 ? void 0 : options.outputName)) { let bp = String(options.buildPath); if (bp.includes('project:')) { bp = path_1.default.join(projectPath, bp.replace(/^project:\/\//, '').replace(/^project:/, '')); } add(path_1.default.join(bp, options.outputName)); } return (0, MembershipSet_1.membershipToArray)(roots); } function collectAllJsFiles(roots) { const files = (0, MembershipSet_1.createMembershipSet)(); for (const root of roots) { const acc = []; collectJsFiles(root, acc); for (const f of acc) (0, MembershipSet_1.membershipAdd)(files, path_1.default.normalize(f)); } return (0, MembershipSet_1.membershipToArray)(files); } async function minifyStripConsole(src) { const base = { compress: { drop_console: true, drop_debugger: true, passes: 2, }, mangle: false, format: { comments: 'some' }, ecma: 2020, }; let out = await (0, terser_1.minify)(src, base); if (out.code != null) return out.code; out = await (0, terser_1.minify)(src, Object.assign(Object.assign({}, base), { module: true })); if (out.code != null) return out.code; throw new Error('terser returned empty'); } async function stripConsoleFromBuildOutput(roots) { const files = collectAllJsFiles(roots); if (files.length === 0) { console.warn('[tools] stripConsole: no .js under roots', roots); return; } let ok = 0; let fail = 0; for (const file of files) { try { const src = fs_1.default.readFileSync(file, 'utf8'); const code = await minifyStripConsole(src); fs_1.default.writeFileSync(file, code, 'utf8'); ok++; } catch (err) { fail++; console.warn(`[tools] stripConsole skip (terser error): ${file}`, err); } } console.log(`[tools] stripConsole done: ok=${ok}, fail=${fail}, roots=${roots.join('; ')}`); } function shouldStripConsole(options) { var _a, _b; const v = (_b = (_a = options === null || options === void 0 ? void 0 : options.packages) === null || _a === void 0 ? void 0 : _a.tools) === null || _b === void 0 ? void 0 : _b.stripConsole; if (v === true) return true; if (v === 'true' || v === 1) return true; return false; } /** Cocos engine-adapter 中 tt.createOffscreenVideo 鸿蒙暂不支持,构建后替换为带环境判断的调用 */ function patchEngineAdapterHarmony(engineAdapterPath) { if (!fs_1.default.existsSync(engineAdapterPath)) { return; } const needle = 'tt.createOffscreenVideo()'; let src = fs_1.default.readFileSync(engineAdapterPath, 'utf8'); if (!src.includes(needle)) { console.warn(`[tools] harmony patch skip: ${needle} not found in ${engineAdapterPath}`); return; } const replacement = '(function(t){try{var i=t.getSystemInfoSync(),p=String(i.platform||"").toLowerCase(),s=String(i.system||"").toLowerCase();' + 'if(p==="openharmony"||s.indexOf("openharmony")>=0)return null;var f=t["create"+"Offscreen"+"Video"];' + 'return typeof f==="function"?f.call(t):null}catch(e){return null}})(tt)'; src = src.replace(needle, replacement); fs_1.default.writeFileSync(engineAdapterPath, src, 'utf8'); console.log(`[tools] harmony patch applied: ${engineAdapterPath}`); } function patchHarmonyEngineAdapter(roots) { for (const root of roots) { patchEngineAdapterHarmony(path_1.default.join(root, 'engine-adapter.js')); } } const WECHAT_ONLY_FALLBACK_FILES = ['Sdk30rWechat.ts', 'Sdk30rWechat.ts.meta']; function getBuildPlatform(options) { var _a, _b; return String((_b = (_a = options === null || options === void 0 ? void 0 : options.platform) !== null && _a !== void 0 ? _a : options === null || options === void 0 ? void 0 : options.buildPlatform) !== null && _b !== void 0 ? _b : ''); } function wechatOnlySdkPaths(projectPath) { const srcDir = path_1.default.join(projectPath, 'tools', 'wechat-only'); const destDir = path_1.default.join(projectPath, 'assets', 'script', 'sdk'); return { srcDir, destDir }; } function listWechatOnlyFiles(srcDir) { if (!fs_1.default.existsSync(srcDir)) return []; const names = fs_1.default.readdirSync(srcDir); const out = []; for (let i = 0; i < names.length; i++) { const name = names[i]; if (name.endsWith('.md')) continue; const full = path_1.default.join(srcDir, name); if (fs_1.default.statSync(full).isFile()) out.push(name); } return out; } function removeWechatOnlySdkFromAssets(srcDir, destDir, platform) { const names = listWechatOnlyFiles(srcDir); for (let i = 0; i < WECHAT_ONLY_FALLBACK_FILES.length; i++) { const n = WECHAT_ONLY_FALLBACK_FILES[i]; if (names.indexOf(n) < 0) names.push(n); } let removed = 0; for (let i = 0; i < names.length; i++) { const dest = path_1.default.join(destDir, names[i]); if (fs_1.default.existsSync(dest)) { fs_1.default.unlinkSync(dest); removed++; } } if (removed > 0) { console.log(`[tools] removed wechat-only 30r sdk from assets (${platform || 'unknown platform'})`); } } function syncWechatOnlySdk(options, mode) { const projectPath = Editor.Project.path; if (!projectPath) return; const { srcDir, destDir } = wechatOnlySdkPaths(projectPath); const platform = getBuildPlatform(options); const isWechat = platform === 'wechatgame'; const isBiliGame = !!(options && options.packages && options.packages['biligame-builder'] && options.packages['biligame-builder'].isBiliGame); if (mode === 'after' || !isWechat || isBiliGame) { removeWechatOnlySdkFromAssets(srcDir, destDir, isBiliGame ? 'biligame' : platform); return; } const files = listWechatOnlyFiles(srcDir); if (files.length === 0) { console.warn('[tools] wechat-only sdk missing:', srcDir); return; } fs_1.default.mkdirSync(destDir, { recursive: true }); for (let i = 0; i < files.length; i++) { const name = files[i]; fs_1.default.copyFileSync(path_1.default.join(srcDir, name), path_1.default.join(destDir, name)); } console.log('[tools] copied wechat-only 30r sdk into assets/script/sdk'); } function onBeforeBuild(options, _result) { try { syncWechatOnlySdk(options, 'before'); } catch (err) { console.error('[tools] onBeforeBuild syncWechatOnlySdk failed:', err); } try { console.log('[tools] onBeforeBuild: generate config bin'); generateConfigBin(); } catch (err) { console.error('[tools] onBeforeBuild generate config bin failed:', err); } return true; } exports.onBeforeBuild = onBeforeBuild; async function onAfterBuild(options, result) { try { syncWechatOnlySdk(options, 'after'); } catch (err) { console.error('[tools] onAfterBuild syncWechatOnlySdk failed:', err); } try { if (shouldStripConsole(options)) { const roots = collectStripRoots(options, result); if (roots.length === 0) { console.warn('[tools] stripConsole 已勾选但未能解析构建输出目录(检查 result.dest / paths / buildPath+outputName)'); } else { console.log('[tools] onAfterBuild stripConsole →', roots.join(' | ')); await stripConsoleFromBuildOutput(roots); } } } catch (err) { console.error('[tools] onAfterBuild stripConsole failed:', err); } try { if (getBuildPlatform(options) === 'bytedance-mini-game') { const roots = collectStripRoots(options, result); patchHarmonyEngineAdapter(roots); } } catch (err) { console.error('[tools] onAfterBuild harmony patch failed:', err); } try { console.log('[tools] onAfterBuild: generate config bin'); generateConfigBin(); } catch (err) { console.error('[tools] onAfterBuild generate config bin failed:', err); } return true; } exports.onAfterBuild = onAfterBuild; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQtaG9va3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zb3VyY2UvYnVpbGQtaG9va3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7OztHQUdHO0FBQ0gsNENBQW9CO0FBQ3BCLGdEQUF3QjtBQUN4QixrREFBd0I7QUFDeEIsbUNBQWdDO0FBQ2hDLG1EQUl5QjtBQUVaLFFBQUEsVUFBVSxHQUFHLElBQUksQ0FBQztBQUUvQixTQUFTLFFBQVEsQ0FBQyxRQUFnQjtJQUM5QixNQUFNLEdBQUcsR0FBRyxZQUFFLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM5QyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDM0IsQ0FBQztBQUVELFNBQVMsd0JBQXdCLENBQUMsV0FBbUI7O0lBQ2pELE1BQU0sYUFBYSxHQUFHLGNBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBQ3hGLE1BQU0sZ0JBQWdCLEdBQUcsWUFBRSxDQUFDLFlBQVksQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7SUFFaEUsTUFBTSxXQUFXLEdBQUcsbUVBQW1FLENBQUM7SUFDeEYsTUFBTSxTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFDNUMsSUFBSSxDQUFDLEdBQTJCLElBQUksQ0FBQztJQUNyQyxPQUFPLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxFQUFFO1FBQzdDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQzdCO0lBRUQsTUFBTSxZQUFZLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLDhEQUE4RCxDQUFDLENBQUM7SUFDNUcsTUFB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QUFHLENBQUMsQ0FBQztLQUNwRTtJQUNELElBQUk7UUFDQSxPQUFPLENBQUMsR0FBRyxDQUFDLDJDQUEyQyxDQUFDLENBQUM7UUFDekQsaUJBQWlCLEVBQUUsQ0FBQztLQUN2QjtJQUFDLE9BQU8sR0FBRyxFQUFFO1FBQ1YsT0FBTyxDQUFDLEtBQUssQ0FBQyxrREFBa0QsRUFBRSxHQUFHLENBQUMsQ0FBQztLQUMxRTtJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2hCLENBQUM7QUF0Q0Qsb0NBc0NDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiDmnoTlu7rov5vnqIvvvIjni6znq4sgd29ya2Vy77yJ5Yqg6L2955qE6ZKp5a2Q6ISa5pys77ybY3VzdG9tLWJ1aWxkZXIg55qEIGNvbmZpZ3MuKi5ob29rcyDmjIflkJHmnKzmlofku7bjgIJcbiAqIGN1c3RvbS1idWlsZGVyLnRzIOS8miByZS1leHBvcnQg5pys5paH5Lu255qE6ZKp5a2Q77yM5L6b57yW6L6R5Zmo5qCh6aqM6YCa6L+H44CCXG4gKi9cbmltcG9ydCBmcyBmcm9tICdmcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCBsejQgZnJvbSAnbHo0anMnO1xuaW1wb3J0IHsgbWluaWZ5IH0gZnJvbSAndGVyc2VyJztcbmltcG9ydCB7XG4gICAgY3JlYXRlTWVtYmVyc2hpcFNldCxcbiAgICBtZW1iZXJzaGlwQWRkLFxuICAgIG1lbWJlcnNoaXBUb0FycmF5LFxufSBmcm9tICcuL01lbWJlcnNoaXBTZXQnO1xuXG5leHBvcnQgY29uc3QgdGhyb3dFcnJvciA9IHRydWU7XG5cbmZ1bmN0aW9uIHJlYWRKc29uKGZpbGVQYXRoOiBzdHJpbmcpIHtcbiAgICBjb25zdCByYXcgPSBmcy5yZWFkRmlsZVN5bmMoZmlsZVBhdGgsICd1dGY4Jyk7XG4gICAgcmV0dXJuIEpTT04ucGFyc2UocmF3KTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNvbmZpZ05hbWVWZXJzaW9uKHByb2plY3RQYXRoOiBzdHJpbmcpIHtcbiAgICBjb25zdCBzZGtDb25maWdQYXRoID0gcGF0aC5qb2luKHByb2plY3RQYXRoLCAnYXNzZXRzJywgJ3NjcmlwdCcsICdzZGsnLCAnc2RrQ29uZmlnLnRzJyk7XG4gICAgY29uc3Qgc2RrQ29uZmlnQ29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhzZGtDb25maWdQYXRoLCAndXRmOCcpO1xuXG4gICAgY29uc3QgaW1wb3J0UmVnZXggPSAvaW1wb3J0XFxzK1xce1xccyooXFx3KylcXHMqXFx9XFxzK2Zyb21cXHMrW1wiJ11cXC5cXC9jb25maWdcXC8oW15cIiddKylbXCInXTs/L2c7XG4gICAgY29uc3QgaW1wb3J0TWFwID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgICBsZXQgbTogUmVnRXhwRXhlY0FycmF5IHwgbnVsbCA9IG51bGw7XG4gICAgd2hpbGUgKChtID0gaW1wb3J0UmVnZXguZXhlYyhzZGtDb25maWdDb250ZW50KSkpIHtcbiAgICAgICAgaW1wb3J0TWFwLnNldChtWzFdLCBtWzJdKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb25maWdBc3NpZ24gPSBzZGtDb25maWdDb250ZW50Lm1hdGNoKC9zdGF0aWNcXHMrcmVhZG9ubHlcXHMrY29uZmlnXFxzKjpcXHMqSUNvbmZpZ0RhdGFcXHMqPVxccyooXFx3KylcXHMqOy8pO1xuICAgIGNvbnN0IHN5bWJvbCA9IGNvbmZpZ0Fzc2lnbj8uWzFdID8/ICdEZWZhdWx0Q29uZmlnJztcbiAgICBjb25zdCByZWxDb25maWcgPSBpbXBvcnRNYXAuZ2V0KHN5bWJvbCkgPz8gJ0RlZmF1bHRDb25maWcnO1xuICAgIGNvbnN0IGNvbmZpZ1BhdGggPSBwYXRoLmpvaW4ocHJvamVjdFBhdGgsICdhc3NldHMnLCAnc2NyaXB0JywgJ3NkaycsICdjb25maWcnLCBgJHtyZWxDb25maWd9LnRzYCk7XG4gICAgY29uc3QgY29uZmlnQ29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhjb25maWdQYXRoLCAndXRmOCcpO1xuXG4gICAgY29uc3QgbmFtZSA9IGNvbmZpZ0NvbnRlbnQubWF0Y2goL25hbWVcXHMqOlxccypbXCInXShbXlwiJ10rKVtcIiddLyk/LlsxXSA/PyAnY29uZmlnJztcbiAgICBjb25zdCB2c2lvbiA9IGNvbmZpZ0NvbnRlbnQubWF0Y2goL3ZzaW9uXFxzKjpcXHMqW1wiJ10oW15cIiddKylbXCInXS8pPy5bMV0gPz8gJzAuMC4wJztcbiAgICByZXR1cm4geyBuYW1lLCB2c2lvbiB9O1xufVxuXG5mdW5jdGlvbiBlbmNvZGVGb3JSdW50aW1lKGpzb25PYmo6IGFueSkge1xuICAgIGNvbnN0IGpzb25TdHJpbmcgPSBKU09OLnN0cmluZ2lmeShqc29uT2JqKTtcbiAgICBjb25zdCB1aW50OCA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShqc29uU3RyaW5nKTtcbiAgICBjb25zdCBjb21wcmVzc2VkID0gVWludDhBcnJheS5mcm9tKGx6NC5jb21wcmVzcyh1aW50OCkpO1xuXG4gICAgY29uc3QgYmluYXJ5ID0gQnVmZmVyLmZyb20oY29tcHJlc3NlZCkudG9TdHJpbmcoJ2xhdGluMScpO1xuICAgIGNvbnN0IGJhc2U2NCA9IEJ1ZmZlci5mcm9tKGJpbmFyeSwgJ2xhdGluMScpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICByZXR1cm4gQnVmZmVyLmZyb20oYmFzZTY0LCAnbGF0aW4xJyk7XG59XG5cbmNvbnN0IEhPVF9VUERBVEVfVEFCTEVfRklMRVM6IHsgdGFibGVLZXk6IHN0cmluZzsgZmlsZU5hbWU6IHN0cmluZyB9W10gPSBbXG4gICAgeyB0YWJsZUtleTogJ0NoYXB0ZXInLCBmaWxlTmFtZTogJ0NoYXB0ZXIuanNvbicgfSxcbiAgICB7IHRhYmxlS2V5OiAnQ29uc3Rfd2VpZ2h0JywgZmlsZU5hbWU6ICdDb25zdF93ZWlnaHQuanNvbicgfSwgXG4gICAgeyB0YWJsZUtleTogJ01vbnN0ZXInLCBmaWxlTmFtZTogJ01vbnN0ZXIuanNvbicgfSxcbiAgICB7IHRhYmxlS2V5OiAnYm94X3dlYXBvbicsIGZpbGVOYW1lOiAnYm94X3dlYXBvbi5qc29uJyB9LFxuICAgIHsgdGFibGVLZXk6ICdTa2lsbF9wb29sJywgZmlsZU5hbWU6ICdTa2lsbF9wb29sLmpzb24nIH0sXG4gICAgeyB0YWJsZUtleTogJ01vbnN0ZXIyJywgZmlsZU5hbWU6ICdNb25zdGVyMi5qc29uJyB9LFxuXTtcblxuZnVuY3Rpb24gZ2VuZXJhdGVDb25maWdCaW4oKSB7XG4gICAgY29uc3QgcHJvamVjdFBhdGggPSBFZGl0b3IuUHJvamVjdC5wYXRoO1xuICAgIGNvbnN0IGNvbmZpZ0RpciA9IHBhdGguam9pbihwcm9qZWN0UGF0aCwgJ2Fzc2V0cycsICdidW5kbGVzJywgJ2ZpcnN0JywgJ2NvbmZpZycpO1xuXG4gICAgY29uc3QgbWVyZ2VKc29uOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuICAgIGZvciAoY29uc3QgeyB0YWJsZUtleSwgZmlsZU5hbWUgfSBvZiBIT1RfVVBEQVRFX1RBQkxFX0ZJTEVTKSB7XG4gICAgICAgIGNvbnN0IGZwID0gcGF0aC5qb2luKGNvbmZpZ0RpciwgZmlsZU5hbWUpO1xuICAgICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZnApKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYFt0b29sc10gc2tpcCBiaW4gZ2VuZXJhdGU6IG1pc3NpbmcgJHtmaWxlTmFtZX1gKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBtZXJnZUpzb25bdGFibGVLZXldID0gcmVhZEpzb24oZnApO1xuICAgIH1cblxuICAgIGNvbnN0IHsgbmFtZSwgdnNpb24gfSA9IHJlc29sdmVDb25maWdOYW1lVmVyc2lvbihwcm9qZWN0UGF0aCk7XG4gICAgY29uc3Qgc2FmZU5hbWUgPSBgJHtuYW1lfSR7dnNpb259YC5yZXBsYWNlKC9bPD46XCIvXFxcXHw/Kl0rL2csICdfJyk7XG4gICAgY29uc3Qgb3V0RGlyID0gcGF0aC5qb2luKHByb2plY3RQYXRoLCAnYmluJyk7XG4gICAgY29uc3Qgb3V0RmlsZSA9IHBhdGguam9pbihvdXREaXIsIGAke3NhZmVOYW1lfS5iaW5gKTtcbiAgICBmcy5ta2RpclN5bmMob3V0RGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICBmcy53cml0ZUZpbGVTeW5jKG91dEZpbGUsIGVuY29kZUZvclJ1bnRpbWUobWVyZ2VKc29uKSk7XG4gICAgY29uc29sZS5sb2coYFt0b29sc10gZ2VuZXJhdGVkIGNvbmZpZyBiaW46ICR7b3V0RmlsZX1gKTtcbn1cblxuZnVuY3Rpb24gY29sbGVjdEpzRmlsZXMoZGlyOiBzdHJpbmcsIGFjYzogc3RyaW5nW10pIHtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZGlyKSkgcmV0dXJuO1xuICAgIGNvbnN0IHN0ID0gZnMuc3RhdFN5bmMoZGlyKTtcbiAgICBpZiAoIXN0LmlzRGlyZWN0b3J5KCkpIHJldHVybjtcbiAgICBjb25zdCBlbnRyaWVzID0gZnMucmVhZGRpclN5bmMoZGlyLCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSk7XG4gICAgZm9yIChjb25zdCBlIG9mIGVudHJpZXMpIHtcbiAgICAgICAgY29uc3QgZnVsbCA9IHBhdGguam9pbihkaXIsIGUubmFtZSk7XG4gICAgICAgIGlmIChlLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgICAgIGNvbGxlY3RKc0ZpbGVzKGZ1bGwsIGFjYyk7XG4gICAgICAgIH0gZWxzZSBpZiAoZS5pc0ZpbGUoKSAmJiBlLm5hbWUuZW5kc1dpdGgoJy5qcycpKSB7XG4gICAgICAgICAgICBhY2MucHVzaChmdWxsKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gY29sbGVjdFN0cmlwUm9vdHMob3B0aW9uczogYW55LCByZXN1bHQ6IGFueSk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCByb290cyA9IGNyZWF0ZU1lbWJlcnNoaXBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IGFkZCA9IChwOiB1bmtub3duKSA9PiB7XG4gICAgICAgIGlmIChwID09IG51bGwgfHwgcCA9PT0gJycpIHJldHVybjtcbiAgICAgICAgY29uc3QgcyA9IHBhdGgubm9ybWFsaXplKFN0cmluZyhwKS5yZXBsYWNlKC9cXC8vZywgcGF0aC5zZXApKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmcy5leGlzdHNTeW5jKHMpKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3QgPSBmcy5zdGF0U3luYyhzKTtcbiAgICAgICAgICAgICAgICBpZiAoc3QuaXNEaXJlY3RvcnkoKSkgbWVtYmVyc2hpcEFkZChyb290cywgcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgICAgLyogaWdub3JlICovXG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgYWRkKHJlc3VsdD8uZGVzdCk7XG4gICAgYWRkKHJlc3VsdD8ucGF0aHM/LmRpcik7XG4gICAgYWRkKHJlc3VsdD8ucGF0aHM/LmFzc2V0cyk7XG4gICAgYWRkKHJlc3VsdD8ucGF0aHM/LmJ1bmRsZVNjcmlwdHMpO1xuICAgIGFkZChyZXN1bHQ/LnBhdGhzPy5zdWJwYWNrYWdlcyk7XG5cbiAgICBjb25zdCBwcm9qZWN0UGF0aCA9IEVkaXRvci5Qcm9qZWN0LnBhdGg7XG4gICAgaWYgKHByb2plY3RQYXRoICYmIG9wdGlvbnM/LmJ1aWxkUGF0aCAmJiBvcHRpb25zPy5vdXRwdXROYW1lKSB7XG4gICAgICAgIGxldCBicCA9IFN0cmluZyhvcHRpb25zLmJ1aWxkUGF0aCk7XG4gICAgICAgIGlmIChicC5pbmNsdWRlcygncHJvamVjdDonKSkge1xuICAgICAgICAgICAgYnAgPSBwYXRoLmpvaW4ocHJvamVjdFBhdGgsIGJwLnJlcGxhY2UoL15wcm9qZWN0OlxcL1xcLy8sICcnKS5yZXBsYWNlKC9ecHJvamVjdDovLCAnJykpO1xuICAgICAgICB9XG4gICAgICAgIGFkZChwYXRoLmpvaW4oYnAsIG9wdGlvbnMub3V0cHV0TmFtZSkpO1xuICAgIH1cblxuICAgIHJldHVybiBtZW1iZXJzaGlwVG9BcnJheShyb290cyk7XG59XG5cbmZ1bmN0aW9uIGNvbGxlY3RBbGxKc0ZpbGVzKHJvb3RzOiBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBmaWxlcyA9IGNyZWF0ZU1lbWJlcnNoaXBTZXQ8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3Qgcm9vdCBvZiByb290cykge1xuICAgICAgICBjb25zdCBhY2M6IHN0cmluZ1tdID0gW107XG4gICAgICAgIGNvbGxlY3RKc0ZpbGVzKHJvb3QsIGFjYyk7XG4gICAgICAgIGZvciAoY29uc3QgZiBvZiBhY2MpIG1lbWJlcnNoaXBBZGQoZmlsZXMsIHBhdGgubm9ybWFsaXplKGYpKTtcbiAgICB9XG4gICAgcmV0dXJuIG1lbWJlcnNoaXBUb0FycmF5KGZpbGVzKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbWluaWZ5U3RyaXBDb25zb2xlKHNyYzogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBiYXNlID0ge1xuICAgICAgICBjb21wcmVzczoge1xuICAgICAgICAgICAgZHJvcF9jb25zb2xlOiB0cnVlLFxuICAgICAgICAgICAgZHJvcF9kZWJ1Z2dlcjogdHJ1ZSxcbiAgICAgICAgICAgIHBhc3NlczogMixcbiAgICAgICAgfSxcbiAgICAgICAgbWFuZ2xlOiBmYWxzZSxcbiAgICAgICAgZm9ybWF0OiB7IGNvbW1lbnRzOiAnc29tZScgYXMgY29uc3QgfSxcbiAgICAgICAgZWNtYTogMjAyMCBhcyBjb25zdCxcbiAgICB9O1xuICAgIGxldCBvdXQgPSBhd2FpdCBtaW5pZnkoc3JjLCBiYXNlKTtcbiAgICBpZiAob3V0LmNvZGUgIT0gbnVsbCkgcmV0dXJuIG91dC5jb2RlO1xuICAgIG91dCA9IGF3YWl0IG1pbmlmeShzcmMsIHsgLi4uYmFzZSwgbW9kdWxlOiB0cnVlIH0pO1xuICAgIGlmIChvdXQuY29kZSAhPSBudWxsKSByZXR1cm4gb3V0LmNvZGU7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd0ZXJzZXIgcmV0dXJuZWQgZW1wdHknKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc3RyaXBDb25zb2xlRnJvbUJ1aWxkT3V0cHV0KHJvb3RzOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IGZpbGVzID0gY29sbGVjdEFsbEpzRmlsZXMocm9vdHMpO1xuICAgIGlmIChmaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdbdG9vbHNdIHN0cmlwQ29uc29sZTogbm8gLmpzIHVuZGVyIHJvb3RzJywgcm9vdHMpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxldCBvayA9IDA7XG4gICAgbGV0IGZhaWwgPSAwO1xuICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qgc3JjID0gZnMucmVhZEZpbGVTeW5jKGZpbGUsICd1dGY4Jyk7XG4gICAgICAgICAgICBjb25zdCBjb2RlID0gYXdhaXQgbWluaWZ5U3RyaXBDb25zb2xlKHNyYyk7XG4gICAgICAgICAgICBmcy53cml0ZUZpbGVTeW5jKGZpbGUsIGNvZGUsICd1dGY4Jyk7XG4gICAgICAgICAgICBvaysrO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGZhaWwrKztcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgW3Rvb2xzXSBzdHJpcENvbnNvbGUgc2tpcCAodGVyc2VyIGVycm9yKTogJHtmaWxlfWAsIGVycik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgY29uc29sZS5sb2coYFt0b29sc10gc3RyaXBDb25zb2xlIGRvbmU6IG9rPSR7b2t9LCBmYWlsPSR7ZmFpbH0sIHJvb3RzPSR7cm9vdHMuam9pbignOyAnKX1gKTtcbn1cblxuZnVuY3Rpb24gc2hvdWxkU3RyaXBDb25zb2xlKG9wdGlvbnM6IGFueSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHYgPSBvcHRpb25zPy5wYWNrYWdlcz8udG9vbHM/LnN0cmlwQ29uc29sZTtcbiAgICBpZiAodiA9PT0gdHJ1ZSkgcmV0dXJuIHRydWU7XG4gICAgaWYgKHYgPT09ICd0cnVlJyB8fCB2ID09PSAxKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKiBDb2NvcyBlbmdpbmUtYWRhcHRlciDkuK0gdHQuY3JlYXRlT2Zmc2NyZWVuVmlkZW8g6bi/6JKZ5pqC5LiN5pSv5oyB77yM5p6E5bu65ZCO5pu/5o2i5Li65bim546v5aKD5Yik5pat55qE6LCD55SoICovXG5mdW5jdGlvbiBwYXRjaEVuZ2luZUFkYXB0ZXJIYXJtb255KGVuZ2luZUFkYXB0ZXJQYXRoOiBzdHJpbmcpIHtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZW5naW5lQWRhcHRlclBhdGgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbmVlZGxlID0gJ3R0LmNyZWF0ZU9mZnNjcmVlblZpZGVvKCknO1xuICAgIGxldCBzcmMgPSBmcy5yZWFkRmlsZVN5bmMoZW5naW5lQWRhcHRlclBhdGgsICd1dGY4Jyk7XG4gICAgaWYgKCFzcmMuaW5jbHVkZXMobmVlZGxlKSkge1xuICAgICAgICBjb25zb2xlLndhcm4oYFt0b29sc10gaGFybW9ueSBwYXRjaCBza2lwOiAke25lZWRsZX0gbm90IGZvdW5kIGluICR7ZW5naW5lQWRhcHRlclBhdGh9YCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcmVwbGFjZW1lbnQgPVxuICAgICAgICAnKGZ1bmN0aW9uKHQpe3RyeXt2YXIgaT10LmdldFN5c3RlbUluZm9TeW5jKCkscD1TdHJpbmcoaS5wbGF0Zm9ybXx8XCJcIikudG9Mb3dlckNhc2UoKSxzPVN0cmluZyhpLnN5c3RlbXx8XCJcIikudG9Mb3dlckNhc2UoKTsnXG4gICAgICAgICsgJ2lmKHA9PT1cIm9wZW5oYXJtb255XCJ8fHMuaW5kZXhPZihcIm9wZW5oYXJtb255XCIpPj0wKXJldHVybiBudWxsO3ZhciBmPXRbXCJjcmVhdGVcIitcIk9mZnNjcmVlblwiK1wiVmlkZW9cIl07J1xuICAgICAgICArICdyZXR1cm4gdHlwZW9mIGY9PT1cImZ1bmN0aW9uXCI/Zi5jYWxsKHQpOm51bGx9Y2F0Y2goZSl7cmV0dXJuIG51bGx9fSkodHQpJztcbiAgICBzcmMgPSBzcmMucmVwbGFjZShuZWVkbGUsIHJlcGxhY2VtZW50KTtcbiAgICBmcy53cml0ZUZpbGVTeW5jKGVuZ2luZUFkYXB0ZXJQYXRoLCBzcmMsICd1dGY4Jyk7XG4gICAgY29uc29sZS5sb2coYFt0b29sc10gaGFybW9ueSBwYXRjaCBhcHBsaWVkOiAke2VuZ2luZUFkYXB0ZXJQYXRofWApO1xufVxuXG5mdW5jdGlvbiBwYXRjaEhhcm1vbnlFbmdpbmVBZGFwdGVyKHJvb3RzOiBzdHJpbmdbXSkge1xuICAgIGZvciAoY29uc3Qgcm9vdCBvZiByb290cykge1xuICAgICAgICBwYXRjaEVuZ2luZUFkYXB0ZXJIYXJtb255KHBhdGguam9pbihyb290LCAnZW5naW5lLWFkYXB0ZXIuanMnKSk7XG4gICAgfVxufVxuXG5jb25zdCBXRUNIQVRfT05MWV9TREtfRklMRVMgPSBbJ1NkazMwcldlY2hhdC50cycsICdTZGszMHJXZWNoYXQudHMubWV0YSddO1xuXG5mdW5jdGlvbiBnZXRCdWlsZFBsYXRmb3JtKG9wdGlvbnM6IGFueSk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFN0cmluZyhvcHRpb25zPy5wbGF0Zm9ybSA/PyBvcHRpb25zPy5idWlsZFBsYXRmb3JtID8/ICcnKTtcbn1cblxuZnVuY3Rpb24gd2VjaGF0T25seVNka1BhdGhzKHByb2plY3RQYXRoOiBzdHJpbmcpIHtcbiAgICBjb25zdCBzcmNEaXIgPSBwYXRoLmpvaW4ocHJvamVjdFBhdGgsICd0b29scycsICd3ZWNoYXQtb25seScpO1xuICAgIGNvbnN0IGRlc3REaXIgPSBwYXRoLmpvaW4ocHJvamVjdFBhdGgsICdhc3NldHMnLCAnc2NyaXB0JywgJ3NkaycpO1xuICAgIHJldHVybiB7IHNyY0RpciwgZGVzdERpciB9O1xufVxuXG4vKiogMzByIFNESyDlkKsgQGRuLXNka++8jOS4jeiDveeVmeWcqCBhc3NldHMg5ZCm5YiZ5oqW6Z+z562J5YWo5bmz5Y+w5p6E5bu66YO95Lya5omT6L+b5YyFICovXG5mdW5jdGlvbiBzeW5jV2VjaGF0T25seVNkayhvcHRpb25zOiBhbnkpIHtcbiAgICBjb25zdCBwcm9qZWN0UGF0aCA9IEVkaXRvci5Qcm9qZWN0LnBhdGg7XG4gICAgaWYgKCFwcm9qZWN0UGF0aCkgcmV0dXJuO1xuXG4gICAgY29uc3QgeyBzcmNEaXIsIGRlc3REaXIgfSA9IHdlY2hhdE9ubHlTZGtQYXRocyhwcm9qZWN0UGF0aCk7XG4gICAgY29uc3QgcGxhdGZvcm0gPSBnZXRCdWlsZFBsYXRmb3JtKG9wdGlvbnMpO1xuICAgIGNvbnN0IGlzV2VjaGF0ID0gcGxhdGZvcm0gPT09ICd3ZWNoYXRnYW1lJztcblxuICAgIGlmIChpc1dlY2hhdCkge1xuICAgICAgICBmcy5ta2RpclN5bmMoZGVzdERpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBXRUNIQVRfT05MWV9TREtfRklMRVMpIHtcbiAgICAgICAgICAgIGNvbnN0IHNyYyA9IHBhdGguam9pbihzcmNEaXIsIG5hbWUpO1xuICAgICAgICAgICAgY29uc3QgZGVzdCA9IHBhdGguam9pbihkZXN0RGlyLCBuYW1lKTtcbiAgICAgICAgICAgIGlmICghZnMuZXhpc3RzU3luYyhzcmMpKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKGBbdG9vbHNdIHdlY2hhdC1vbmx5IHNkayBtaXNzaW5nOiAke3NyY31gKTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZzLmNvcHlGaWxlU3luYyhzcmMsIGRlc3QpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnNvbGUubG9nKCdbdG9vbHNdIGNvcGllZCB3ZWNoYXQtb25seSAzMHIgc2RrIGludG8gYXNzZXRzL3NjcmlwdC9zZGsnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCByZW1vdmVkID0gMDtcbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgV0VDSEFUX09OTFlfU0RLX0ZJTEVTKSB7XG4gICAgICAgIGNvbnN0IGRlc3QgPSBwYXRoLmpvaW4oZGVzdERpciwgbmFtZSk7XG4gICAgICAgIGlmIChmcy5leGlzdHNTeW5jKGRlc3QpKSB7XG4gICAgICAgICAgICBmcy51bmxpbmtTeW5jKGRlc3QpO1xuICAgICAgICAgICAgcmVtb3ZlZCsrO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChyZW1vdmVkID4gMCkge1xuICAgICAgICBjb25zb2xlLmxvZyhgW3Rvb2xzXSByZW1vdmVkIHdlY2hhdC1vbmx5IDMwciBzZGsgZnJvbSBhc3NldHMgKCR7cGxhdGZvcm0gfHwgJ3Vua25vd24gcGxhdGZvcm0nfSlgKTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvbkJlZm9yZUJ1aWxkKG9wdGlvbnM6IGFueSwgX3Jlc3VsdDogYW55KSB7XG4gICAgdHJ5IHtcbiAgICAgICAgc3luY1dlY2hhdE9ubHlTZGsob3B0aW9ucyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ1t0b29sc10gb25CZWZvcmVCdWlsZCBzeW5jV2VjaGF0T25seVNkayBmYWlsZWQ6JywgZXJyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgY29uc29sZS5sb2coJ1t0b29sc10gb25CZWZvcmVCdWlsZDogZ2VuZXJhdGUgY29uZmlnIGJpbicpO1xuICAgICAgICBnZW5lcmF0ZUNvbmZpZ0JpbigpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdbdG9vbHNdIG9uQmVmb3JlQnVpbGQgZ2VuZXJhdGUgY29uZmlnIGJpbiBmYWlsZWQ6JywgZXJyKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBvbkFmdGVyQnVpbGQob3B0aW9uczogYW55LCByZXN1bHQ6IGFueSkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmIChnZXRCdWlsZFBsYXRmb3JtKG9wdGlvbnMpICE9PSAnd2VjaGF0Z2FtZScpIHtcbiAgICAgICAgICAgIHN5bmNXZWNoYXRPbmx5U2RrKG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ1t0b29sc10gb25BZnRlckJ1aWxkIHN5bmNXZWNoYXRPbmx5U2RrIGZhaWxlZDonLCBlcnIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBpZiAoc2hvdWxkU3RyaXBDb25zb2xlKG9wdGlvbnMpKSB7XG4gICAgICAgICAgICBjb25zdCByb290cyA9IGNvbGxlY3RTdHJpcFJvb3RzKG9wdGlvbnMsIHJlc3VsdCk7XG4gICAgICAgICAgICBpZiAocm9vdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICAgICAgICAnW3Rvb2xzXSBzdHJpcENvbnNvbGUg5bey5Yu+6YCJ5L2G5pyq6IO96Kej5p6Q5p6E5bu66L6T5Ye655uu5b2V77yI5qOA5p+lIHJlc3VsdC5kZXN0IC8gcGF0aHMgLyBidWlsZFBhdGgrb3V0cHV0TmFtZe+8iScsXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1t0b29sc10gb25BZnRlckJ1aWxkIHN0cmlwQ29uc29sZSDihpInLCByb290cy5qb2luKCcgfCAnKSk7XG4gICAgICAgICAgICAgICAgYXdhaXQgc3RyaXBDb25zb2xlRnJvbUJ1aWxkT3V0cHV0KHJvb3RzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdbdG9vbHNdIG9uQWZ0ZXJCdWlsZCBzdHJpcENvbnNvbGUgZmFpbGVkOicsIGVycik7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmIChnZXRCdWlsZFBsYXRmb3JtKG9wdGlvbnMpID09PSAnYnl0ZWRhbmNlLW1pbmktZ2FtZScpIHtcbiAgICAgICAgICAgIGNvbnN0IHJvb3RzID0gY29sbGVjdFN0cmlwUm9vdHMob3B0aW9ucywgcmVzdWx0KTtcbiAgICAgICAgICAgIHBhdGNoSGFybW9ueUVuZ2luZUFkYXB0ZXIocm9vdHMpO1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ1t0b29sc10gb25BZnRlckJ1aWxkIGhhcm1vbnkgcGF0Y2ggZmFpbGVkOicsIGVycik7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdbdG9vbHNdIG9uQWZ0ZXJCdWlsZDogZ2VuZXJhdGUgY29uZmlnIGJpbicpO1xuICAgICAgICBnZW5lcmF0ZUNvbmZpZ0JpbigpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdbdG9vbHNdIG9uQWZ0ZXJCdWlsZCBnZW5lcmF0ZSBjb25maWcgYmluIGZhaWxlZDonLCBlcnIpO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cbiJdfQ==