@riddance/deploy
Version:
289 lines (287 loc) • 43.1 kB
JavaScript
import commonjs from '@rollup/plugin-commonjs';
import json from '@rollup/plugin-json';
import { nodeResolve } from '@rollup/plugin-node-resolve';
import virtual from '@rollup/plugin-virtual';
import { rollup } from '@rollup/wasm-node';
import { createHash } from 'node:crypto';
import { mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { dirname, join, relative } from 'node:path';
import { isDeepStrictEqual } from 'node:util';
import zlib from 'node:zlib';
// eslint-disable-next-line camelcase
import { minify_sync } from 'terser';
import { install } from './npm.js';
const aws = {
entry: (type, service, fn, revision, config) => `
import { awsHandler } from '@riddance/aws-host/${type}'
import * as host from '@riddance/aws-host/${type}'
if('setMeta' in host) {
host.setMeta(${[
`'${service.replaceAll("'", "\\'")}'`,
`'${fn}'`,
revision ? `'${revision}'` : undefined,
JSON.stringify(config),
].join(',')})
}
import('./${fn}.js')
export const handler = awsHandler
`,
patch: (code) => `/*global fetch AbortController*/${code}`,
};
export async function stage(log, stagePath, path, revision, implementations, service, types) {
stagePath = stagePath ?? join(tmpdir(), 'riddance', 'stage', service);
log.trace(`stage dir: ${stagePath}`);
log.trace('staging...');
const { functions, hashes, config } = await copyAndPatchProject(log, path, stagePath, implementations);
log.trace('syncing dependencies...');
await install(stagePath);
hashes['package-lock.json'] = createHash('sha256')
.update(await readFile(join(stagePath, 'package-lock.json')))
.digest('base64');
let previous = {};
try {
previous = JSON.parse(await readFile(join(stagePath, '.hashes.json'), 'utf-8'));
}
catch (e) {
if (e.code !== 'ENOENT') {
throw e;
}
}
const packageChange = previous['package.json'] !== hashes['package.json'] ||
previous['package-lock.json'] !== hashes['package-lock.json'];
const hashesJson = JSON.stringify(hashes, undefined, ' ');
const changed = [];
const unchanged = [];
for (const fn of functions) {
const file = fn + '.js';
if (previous[file] !== hashes[file] || packageChange) {
changed.push(fn);
}
else {
unchanged.push(fn);
}
delete previous[file];
delete hashes[file];
}
const nonFunctionFilesUnchanged = isDeepStrictEqual(previous, hashes);
if (nonFunctionFilesUnchanged) {
const code = [
...(await rollupAndMinify(log, aws, path, stagePath, service, revision, config, changed, types)),
...(await Promise.all(unchanged.map(async (fn) => ({
fn,
code: await readFile(join(stagePath, fn + '.min.js'), 'utf-8'),
})))),
];
await writeFile(join(stagePath, '.hashes.json'), hashesJson);
return code;
}
else {
const code = await rollupAndMinify(log, aws, path, stagePath, service, revision, config, functions, types);
await writeFile(join(stagePath, '.hashes.json'), hashesJson);
return code;
}
}
async function copyAndPatchProject(log, path, target, implementations) {
const hashes = {};
const sourceFiles = (await find(path)).map(f => f.slice(path.length + 1));
const serviceFiles = sourceFiles.filter(f => f.endsWith('.js') && !f.includes('/'));
for (const sf of sourceFiles) {
hashes[sf] = await mkDirCopyFile(join(path, sf), join(target, sf), implementations);
}
const packageFile = join(target, 'package.json');
const packageJson = JSON.parse(await readFile(packageFile, 'utf-8'));
const substitutions = [];
for (const [pkg, sub] of Object.entries(implementations)) {
if (packageJson.dependencies[pkg]) {
delete packageJson.dependencies[pkg];
packageJson.dependencies[sub.implementation] = sub.version;
substitutions.push(` ${pkg} -> ${sub.implementation} ${sub.version}`);
}
}
delete packageJson.devDependencies;
if (substitutions.length !== 0) {
log.trace('substituting');
for (const s of substitutions) {
log.trace(s);
}
}
const updated = JSON.stringify(packageJson);
hashes['package.json'] = createHash('sha256').update(updated).digest('base64');
await writeFile(packageFile, updated);
return { functions: serviceFiles.map(f => f.slice(0, -3)), hashes, config: packageJson.config };
}
async function mkDirCopyFile(source, target, implementations) {
let code = await readFile(source, 'utf-8');
for (const [fromPackage, toPackage] of Object.entries(implementations)) {
code = code.replaceAll(new RegExp(`import \\{ ([^}]+) \\} from '${fromPackage.replaceAll('/', '\\/')}(|/[^']+)';`, 'gu'), `import { $1 } from '${toPackage.implementation}$2';`);
}
try {
await writeFile(target, code);
}
catch {
await mkdir(dirname(target), { recursive: true });
await writeFile(target, code);
}
return createHash('sha256').update(code).digest('base64');
}
async function find(dir) {
let results = [];
let i = 0;
for (;;) {
const list = (await readdir(dir)).filter(f => !f.startsWith('.') &&
!f.endsWith('.ts') &&
!f.endsWith('.gz') &&
!f.endsWith('.min.js') &&
f !== 'tsconfig.json' &&
f !== 'cspell.json' &&
f !== 'eslint.config.mjs' &&
f !== 'dictionary.txt' &&
f !== 'node_modules' &&
f !== 'test' &&
f !== 'bin');
let file = list[i++];
if (!file) {
return results;
}
file = dir + '/' + file;
const stats = await stat(file);
if (stats.isDirectory()) {
results = [...results, ...(await find(file))];
}
else {
results.push(file);
}
}
}
async function rollupAndMinify(log, host, _path, stagePath, service, revision, config, functions, types) {
const minified = [];
let rollupCache;
for (const fn of functions) {
const functionType = types[fn];
if (!functionType) {
throw new Error(`Type of function ${fn} not determined.`);
}
let seriousWarnings = false;
const bundler = await rollup({
input: 'entry',
cache: rollupCache,
treeshake: {
correctVarValueBeforeDeclaration: false,
propertyReadSideEffects: false,
unknownGlobalSideEffects: false,
moduleSideEffects: true,
},
plugins: [
virtual({
entry: aws.entry(functionType, service, fn, revision, config),
}),
nodeResolve({
exportConditions: ['node'],
rootDir: stagePath,
}),
commonjs(),
json(),
],
onwarn: warning => {
if (warning.code === 'THIS_IS_UNDEFINED') {
return;
}
if (warning.code === 'MISSING_EXPORT' &&
warning.id === '\u0000virtual:entry' &&
warning.binding === 'setMeta') {
return;
}
log.warn(`${warning.code ?? warning.message} [${fn}]`);
if (warning.code === 'CIRCULAR_DEPENDENCY' &&
warning.ids &&
warning.ids.length !== 0) {
log.warn(warning.ids.map(p => relative(stagePath, p)).join(' -> '));
}
else {
if (warning.code) {
log.warn(warning.message);
}
if (warning.frame) {
log.warn(warning.frame);
}
}
if (warning.code === 'UNRESOLVED_IMPORT') {
seriousWarnings = true;
}
},
});
rollupCache = bundler.cache;
const { output: [{ code, map }, virtualEntry, more], } = await bundler.generate({
format: 'cjs',
compact: true,
sourcemap: true,
manualChunks: () => 'entry.js',
generatedCode: {
preset: 'es2015',
arrowFunctions: true,
constBindings: true,
objectShorthand: true,
},
});
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (seriousWarnings) {
throw new Error('Suspicious bundler warnings.');
}
const { type, fileName } = virtualEntry ?? {};
if (type !== 'asset' || fileName !== '_virtual_entry.js.map') {
log.error(JSON.stringify(more));
throw new Error('Weird');
}
if (map?.version !== 3) {
throw new Error('Source map missing.');
}
minified.push(pack(log, host, stagePath, fn, code, { ...map, version: 3 }));
}
return await Promise.all(minified);
}
async function pack(log, host, stagePath, fn, source, map) {
log.trace(`minifying ${fn}`);
const min = minify_sync({ [`${fn}.js`]: source }, {
compress: {
module: true,
ecma: 2020,
// eslint-disable-next-line camelcase
hoist_funs: true,
passes: 2,
},
mangle: {
module: true,
},
sourceMap: {
content: map,
filename: `${fn}.js.map`,
},
format: {
ecma: 2020,
comments: false,
},
});
if (!min.code) {
throw new Error('Weird');
}
const code = host.patch ? host.patch(min.code) : min.code;
log.trace(`${fn} minified`);
await Promise.all([
writeFile(join(stagePath, fn + '.min.js'), code),
writeFile(join(stagePath, fn + '.min.js.map.gz'), await gzip(min.map)),
]);
return { fn, code };
}
function gzip(data) {
return new Promise((resolve, reject) => {
zlib.gzip(data, { level: 9 }, (err, buf) => {
if (err) {
reject(err);
return;
}
resolve(buf);
});
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzdGFnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLFFBQVEsTUFBTSx5QkFBeUIsQ0FBQTtBQUM5QyxPQUFPLElBQUksTUFBTSxxQkFBcUIsQ0FBQTtBQUN0QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNkJBQTZCLENBQUE7QUFDekQsT0FBTyxPQUFPLE1BQU0sd0JBQXdCLENBQUE7QUFDNUMsT0FBTyxFQUFFLE1BQU0sRUFBdUMsTUFBTSxtQkFBbUIsQ0FBQTtBQUMvRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQ3hDLE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDNUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUNoQyxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDbkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQzdDLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQTtBQUM1QixxQ0FBcUM7QUFDckMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFFBQVEsQ0FBQTtBQUNwQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBT2xDLE1BQU0sR0FBRyxHQUFHO0lBQ1IsS0FBSyxFQUFFLENBQ0gsSUFBWSxFQUNaLE9BQWUsRUFDZixFQUFVLEVBQ1YsUUFBNEIsRUFDNUIsTUFBZSxFQUNqQixFQUFFLENBQUM7aURBQ3dDLElBQUk7NENBQ1QsSUFBSTs7bUJBRTdCO1FBQ1gsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRztRQUNyQyxJQUFJLEVBQUUsR0FBRztRQUNULFFBQVEsQ0FBQyxD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QUFFLEVBQUU7WUFDdkMsSUFBSSxHQUFHLEVBQUUsQ0FBQztnQkFDTixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7Z0JBQ1gsT0FBTTtZQUNWLENBQUM7WUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDaEIsQ0FBQyxDQUFDLENBQUE7SUFDTixDQUFDLENBQUMsQ0FBQTtBQUNOLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY29tbW9uanMgZnJvbSAnQHJvbGx1cC9wbHVnaW4tY29tbW9uanMnXG5pbXBvcnQganNvbiBmcm9tICdAcm9sbHVwL3BsdWdpbi1qc29uJ1xuaW1wb3J0IHsgbm9kZVJlc29sdmUgfSBmcm9tICdAcm9sbHVwL3BsdWdpbi1ub2RlLXJlc29sdmUnXG5pbXBvcnQgdmlydHVhbCBmcm9tICdAcm9sbHVwL3BsdWdpbi12aXJ0dWFsJ1xuaW1wb3J0IHsgcm9sbHVwLCBSb2xsdXBDYWNoZSwgU291cmNlTWFwLCB0eXBlIFBsdWdpbiB9IGZyb20gJ0Byb2xsdXAvd2FzbS1ub2RlJ1xuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gJ25vZGU6Y3J5cHRvJ1xuaW1wb3J0IHsgbWtkaXIsIHJlYWRkaXIsIHJlYWRGaWxlLCBzdGF0LCB3cml0ZUZpbGUgfSBmcm9tICdub2RlOmZzL3Byb21pc2VzJ1xuaW1wb3J0IHsgdG1wZGlyIH0gZnJvbSAnbm9kZTpvcydcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4sIHJlbGF0aXZlIH0gZnJvbSAnbm9kZTpwYXRoJ1xuaW1wb3J0IHsgaXNEZWVwU3RyaWN0RXF1YWwgfSBmcm9tICdub2RlOnV0aWwnXG5pbXBvcnQgemxpYiBmcm9tICdub2RlOnpsaWInXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2FtZWxjYXNlXG5pbXBvcnQgeyBtaW5pZnlfc3luYyB9IGZyb20gJ3RlcnNlcidcbmltcG9ydCB7IGluc3RhbGwgfSBmcm9tICcuL25wbS5qcydcblxudHlwZSBJbXBsZW1lbnRhdGlvbiA9IHtcbiAgICBpbXBsZW1lbnRhdGlvbjogc3RyaW5nXG4gICAgdmVyc2lvbjogc3RyaW5nXG59XG5cbmNvbnN0IGF3cyA9IHtcbiAgICBlbnRyeTogKFxuICAgICAgICB0eXBlOiBzdHJpbmcsXG4gICAgICAgIHNlcnZpY2U6IHN0cmluZyxcbiAgICAgICAgZm46IHN0cmluZyxcbiAgICAgICAgcmV2aXNpb246IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICAgICAgY29uZmlnOiB1bmtub3duLFxuICAgICkgPT4gYFxuaW1wb3J0IHsgYXdzSGFuZGxlciB9IGZyb20gJ0ByaWRkYW5jZS9hd3MtaG9zdC8ke3R5cGV9J1xuaW1wb3J0ICogYXMgaG9zdCBmcm9tICdAcmlkZGFuY2UvYXdzLWhvc3QvJHt0eXBlfSdcbmlmKCdzZXRNZXRhJyBpbiBob3N0KSB7XG4gICAgaG9zdC5zZXRNZXRhKCR7W1xuICAgICAgICBgJyR7c2VydmljZS5yZXBsYWNlQWxsKFwiJ1wiLCBcIlxcXFwnXCIpfSdgLFxuICAgICAgICBgJyR7Zm59J2AsXG4gICAgICAgIHJldmlzaW9uID8gYCcke3JldmlzaW9ufSdgIDogdW5kZWZpbmVkLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShjb25maWcpLFxuICAgIF0uam9pbignLCcpfSlcbn1cblxuaW1wb3J0KCcuLyR7Zm59LmpzJylcblxuZXhwb3J0IGNvbnN0IGhhbmRsZXIgPSBhd3NIYW5kbGVyXG5gLFxuICAgIHBhdGNoOiAoY29kZTogc3RyaW5nKSA9PiBgLypnbG9iYWwgZmV0Y2ggQWJvcnRDb250cm9sbGVyKi8ke2NvZGV9YCxcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YWdlKFxuICAgIGxvZzoge1xuICAgICAgICB0cmFjZTogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZFxuICAgICAgICB3YXJuOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkXG4gICAgICAgIGVycm9yOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkXG4gICAgfSxcbiAgICBzdGFnZVBhdGg6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgcmV2aXNpb246IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgICBpbXBsZW1lbnRhdGlvbnM6IHsgW2Zyb21QYWNrYWdlOiBzdHJpbmddOiBJbXBsZW1lbnRhdGlvbiB9LFxuICAgIHNlcnZpY2U6IHN0cmluZyxcbiAgICB0eXBlczogeyBbbmFtZTogc3RyaW5nXTogJ2h0dHAnIHwgJ3RpbWVyJyB8ICdldmVudCcgfSxcbikge1xuICAgIHN0YWdlUGF0aCA9IHN0YWdlUGF0aCA/PyBqb2luKHRtcGRpcigpLCAncmlkZGFuY2UnLCAnc3RhZ2UnLCBzZXJ2aWNlKVxuICAgIGxvZy50cmFjZShgc3RhZ2UgZGlyOiAke3N0YWdlUGF0aH1gKVxuICAgIGxvZy50cmFjZSgnc3RhZ2luZy4uLicpXG4gICAgY29uc3QgeyBmdW5jdGlvbnMsIGhhc2hlcywgY29uZmlnIH0gPSBhd2FpdCBjb3B5QW5kUGF0Y2hQcm9qZWN0KFxuICAgICAgICBsb2csXG4gICAgICAgIHBhdGgsXG4gICAgICAgIHN0YWdlUGF0aCxcbiAgICAgICAgaW1wbGVtZW50YXRpb25zLFxuICAgIClcblxuICAgIGxvZy50cmFjZSgnc3luY2luZyBkZXBlbmRlbmNpZXMuLi4nKVxuICAgIGF3YWl0IGluc3RhbGwoc3RhZ2VQYXRoKVxuICAgIGhhc2hlc1sncGFja2FnZS1sb2NrLmpzb24nXSA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpXG4gICAgICAgIC51cGRhdGUoYXdhaXQgcmVhZEZpbGUoam9pbihzdGFnZVBhdGgsICdwYWNrYWdlLWxvY2suanNvbicpKSlcbiAgICAgICAgLmRpZ2VzdCgnYmFzZTY0JylcblxuICAgIGxldCBwcmV2aW91czogeyBbc291cmNlOiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9XG4gICAgdHJ5IHtcbiAgICAgICAgcHJldmlvdXMgPSBKU09OLnBhcnNlKGF3YWl0IHJlYWRGaWxlKGpvaW4oc3RhZ2VQYXRoLCAnLmhhc2hlcy5qc29uJyksICd1dGYtOCcpKSBhcyB7XG4gICAgICAgICAgICBbc291cmNlOiBzdHJpbmddOiBzdHJpbmdcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKChlIGFzIHsgY29kZT86IHN0cmluZyB9KS5jb2RlICE9PSAnRU5PRU5UJykge1xuICAgICAgICAgICAgdGhyb3cgZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcGFja2FnZUNoYW5nZSA9XG4gICAgICAgIHByZXZpb3VzWydwYWNrYWdlLmpzb24nXSAhPT0gaGFzaGVzWydwYWNrYWdlLmpzb24nXSB8fFxuICAgICAgICBwcmV2aW91c1sncGFja2FnZS1sb2NrLmpzb24nXSAhPT0gaGFzaGVzWydwYWNrYWdlLWxvY2suanNvbiddXG5cbiAgICBjb25zdCBoYXNoZXNKc29uID0gSlNPTi5zdHJpbmdpZnkoaGFzaGVzLCB1bmRlZmluZWQsICcgICcpXG4gICAgY29uc3QgY2hhbmdlZCA9IFtdXG4gICAgY29uc3QgdW5jaGFuZ2VkID0gW11cbiAgICBmb3IgKGNvbnN0IGZuIG9mIGZ1bmN0aW9ucykge1xuICAgICAgICBjb25zdCBmaWxlID0gZm4gKyAnLmpzJ1xuICAgICAgICBpZiAocHJldmlvdXNbZmlsZV0gIT09IGhhc2hlc1tmaWxlXSB8fCBwYWNrYWdlQ2hhbmdlKSB7XG4gICAgICAgICAgICBjaGFuZ2VkLnB1c2goZm4pXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1bmNoYW5nZWQucHVzaChmbilcbiAgICAgICAgfVxuICAgICAgICBkZWxldGUgcHJldmlvdXNbZmlsZV1cbiAgICAgICAgZGVsZXRlIGhhc2hlc1tmaWxlXVxuICAgIH1cbiAgICBjb25zdCBub25GdW5jdGlvbkZpbGVzVW5jaGFuZ2VkID0gaXNEZWVwU3RyaWN0RXF1YWwocHJldmlvdXMsIGhhc2hlcylcbiAgICBpZiAobm9uRnVuY3Rpb25GaWxlc1VuY2hhbmdlZCkge1xuICAgICAgICBjb25zdCBjb2RlID0gW1xuICAgICAgICAgICAgLi4uKGF3YWl0IHJvbGx1cEFuZE1pbmlmeShcbiAgICAgICAgICAgICAgICBsb2csXG4gICAgICAgICAgICAgICAgYXdzLFxuICAgICAgICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgICAgICAgc3RhZ2VQYXRoLFxuICAgICAgICAgICAgICAgIHNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcmV2aXNpb24sXG4gICAgICAgICAgICAgICAgY29uZmlnLFxuICAgICAgICAgICAgICAgIGNoYW5nZWQsXG4gICAgICAgICAgICAgICAgdHlwZXMsXG4gICAgICAgICAgICApKSxcbiAgICAgICAgICAgIC4uLihhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICB1bmNoYW5nZWQubWFwKGFzeW5jIGZuID0+ICh7XG4gICAgICAgICAgICAgICAgICAgIGZuLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiBhd2FpdCByZWFkRmlsZShqb2luKHN0YWdlUGF0aCwgZm4gKyAnLm1pbi5qcycpLCAndXRmLTgnKSxcbiAgICAgICAgICAgICAgICB9KSksXG4gICAgICAgICAgICApKSxcbiAgICAgICAgXVxuICAgICAgICBhd2FpdCB3cml0ZUZpbGUoam9pbihzdGFnZVBhdGgsICcuaGFzaGVzLmpzb24nKSwgaGFzaGVzSnNvbilcbiAgICAgICAgcmV0dXJuIGNvZGVcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBjb2RlID0gYXdhaXQgcm9sbHVwQW5kTWluaWZ5KFxuICAgICAgICAgICAgbG9nLFxuICAgICAgICAgICAgYXdzLFxuICAgICAgICAgICAgcGF0aCxcbiAgICAgICAgICAgIHN0YWdlUGF0aCxcbiAgICAgICAgICAgIHNlcnZpY2UsXG4gICAgICAgICAgICByZXZpc2lvbixcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIGZ1bmN0aW9ucyxcbiAgICAgICAgICAgIHR5cGVzLFxuICAgICAgICApXG4gICAgICAgIGF3YWl0IHdyaXRlRmlsZShqb2luKHN0YWdlUGF0aCwgJy5oYXNoZXMuanNvbicpLCBoYXNoZXNKc29uKVxuICAgICAgICByZXR1cm4gY29kZVxuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gY29weUFuZFBhdGNoUHJvamVjdChcbiAgICBsb2c6IHsgdHJhY2U6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQgfSxcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgdGFyZ2V0OiBzdHJpbmcsXG4gICAgaW1wbGVtZW50YXRpb25zOiB7IFtmcm9tUGFja2FnZTogc3RyaW5nXTogSW1wbGVtZW50YXRpb24gfSxcbikge1xuICAgIGNvbnN0IGhhc2hlczogeyBbc291cmNlOiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9XG4gICAgY29uc3Qgc291cmNlRmlsZXMgPSAoYXdhaXQgZmluZChwYXRoKSkubWFwKGYgPT4gZi5zbGljZShwYXRoLmxlbmd0aCArIDEpKVxuICAgIGNvbnN0IHNlcnZpY2VGaWxlcyA9IHNvdXJjZUZpbGVzLmZpbHRlcihmID0+IGYuZW5kc1dpdGgoJy5qcycpICYmICFmLmluY2x1ZGVzKCcvJykpXG5cbiAgICBmb3IgKGNvbnN0IHNmIG9mIHNvdXJjZUZpbGVzKSB7XG4gICAgICAgIGhhc2hlc1tzZl0gPSBhd2FpdCBta0RpckNvcHlGaWxlKGpvaW4ocGF0aCwgc2YpLCBqb2luKHRhcmdldCwgc2YpLCBpbXBsZW1lbnRhdGlvbnMpXG4gICAgfVxuXG4gICAgY29uc3QgcGFja2FnZUZpbGUgPSBqb2luKHRhcmdldCwgJ3BhY2thZ2UuanNvbicpXG4gICAgY29uc3QgcGFja2FnZUpzb24gPSBKU09OLnBhcnNlKGF3YWl0IHJlYWRGaWxlKHBhY2thZ2VGaWxlLCAndXRmLTgnKSkgYXMge1xuICAgICAgICBuYW1lOiBzdHJpbmdcbiAgICAgICAgY29uZmlnPzogdW5rbm93blxuICAgICAgICBkZXBlbmRlbmNpZXM6IHsgW3BhY2thZ2VOYW1lOiBzdHJpbmddOiBzdHJpbmcgfVxuICAgICAgICBkZXZEZXBlbmRlbmNpZXM/OiB1bmtub3duXG4gICAgfVxuXG4gICAgY29uc3Qgc3Vic3RpdHV0aW9ucyA9IFtdXG4gICAgZm9yIChjb25zdCBbcGtnLCBzdWJdIG9mIE9iamVjdC5lbnRyaWVzKGltcGxlbWVudGF0aW9ucykpIHtcbiAgICAgICAgaWYgKHBhY2thZ2VKc29uLmRlcGVuZGVuY2llc1twa2ddKSB7XG4gICAgICAgICAgICBkZWxldGUgcGFja2FnZUpzb24uZGVwZW5kZW5jaWVzW3BrZ11cbiAgICAgICAgICAgIHBhY2thZ2VKc29uLmRlcGVuZGVuY2llc1tzdWIuaW1wbGVtZW50YXRpb25dID0gc3ViLnZlcnNpb25cbiAgICAgICAgICAgIHN1YnN0aXR1dGlvbnMucHVzaChgICAke3BrZ30gLT4gJHtzdWIuaW1wbGVtZW50YXRpb259ICR7c3ViLnZlcnNpb259YClcbiAgICAgICAgfVxuICAgIH1cbiAgICBkZWxldGUgcGFja2FnZUpzb24uZGV2RGVwZW5kZW5jaWVzXG4gICAgaWYgKHN1YnN0aXR1dGlvbnMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxvZy50cmFjZSgnc3Vic3RpdHV0aW5nJylcbiAgICAgICAgZm9yIChjb25zdCBzIG9mIHN1YnN0aXR1dGlvbnMpIHtcbiAgICAgICAgICAgIGxvZy50cmFjZShzKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdXBkYXRlZCA9IEpTT04uc3RyaW5naWZ5KHBhY2thZ2VKc29uKVxuICAgIGhhc2hlc1sncGFja2FnZS5qc29uJ10gPSBjcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUodXBkYXRlZCkuZGlnZXN0KCdiYXNlNjQnKVxuICAgIGF3YWl0IHdyaXRlRmlsZShwYWNrYWdlRmlsZSwgdXBkYXRlZClcblxuICAgIHJldHVybiB7IGZ1bmN0aW9uczogc2VydmljZUZpbGVzLm1hcChmID0+IGYuc2xpY2UoMCwgLTMpKSwgaGFzaGVzLCBjb25maWc6IHBhY2thZ2VKc29uLmNvbmZpZyB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1rRGlyQ29weUZpbGUoXG4gICAgc291cmNlOiBzdHJpbmcsXG4gICAgdGFyZ2V0OiBzdHJpbmcsXG4gICAgaW1wbGVtZW50YXRpb25zOiB7IFtmcm9tUGFja2FnZTogc3RyaW5nXTogSW1wbGVtZW50YXRpb24gfSxcbikge1xuICAgIGxldCBjb2RlID0gYXdhaXQgcmVhZEZpbGUoc291cmNlLCAndXRmLTgnKVxuICAgIGZvciAoY29uc3QgW2Zyb21QYWNrYWdlLCB0b1BhY2thZ2VdIG9mIE9iamVjdC5lbnRyaWVzKGltcGxlbWVudGF0aW9ucykpIHtcbiAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZUFsbChcbiAgICAgICAgICAgIG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgICAgYGltcG9ydCBcXFxceyAoW159XSspIFxcXFx9IGZyb20gJyR7ZnJvbVBhY2thZ2UucmVwbGFjZUFsbCgnLycsICdcXFxcLycpfSh8L1teJ10rKSc7YCxcbiAgICAgICAgICAgICAgICAnZ3UnLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGBpbXBvcnQgeyAkMSB9IGZyb20gJyR7dG9QYWNrYWdlLmltcGxlbWVudGF0aW9ufSQyJztgLFxuICAgICAgICApXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHdyaXRlRmlsZSh0YXJnZXQsIGNvZGUpXG4gICAgfSBjYXRjaCB7XG4gICAgICAgIGF3YWl0IG1rZGlyKGRpcm5hbWUodGFyZ2V0KSwgeyByZWN1cnNpdmU6IHRydWUgfSlcbiAgICAgICAgYXdhaXQgd3JpdGVGaWxlKHRhcmdldCwgY29kZSlcbiAgICB9XG4gICAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShjb2RlKS5kaWdlc3QoJ2Jhc2U2NCcpXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmQoZGlyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgbGV0IHJlc3VsdHM6IHN0cmluZ1tdID0gW11cbiAgICBsZXQgaSA9IDBcbiAgICBmb3IgKDs7KSB7XG4gICAgICAgIGNvbnN0IGxpc3QgPSAoYXdhaXQgcmVhZGRpcihkaXIpKS5maWx0ZXIoXG4gICAgICAgICAgICBmID0+XG4gICAgICAgICAgICAgICAgIWYuc3RhcnRzV2l0aCgnLicpICYmXG4gICAgICAgICAgICAgICAgIWYuZW5kc1dpdGgoJy50cycpICYmXG4gICAgICAgICAgICAgICAgIWYuZW5kc1dpdGgoJy5neicpICYmXG4gICAgICAgICAgICAgICAgIWYuZW5kc1dpdGgoJy5taW4uanMnKSAmJlxuICAgICAgICAgICAgICAgIGYgIT09ICd0c2NvbmZpZy5qc29uJyAmJlxuICAgICAgICAgICAgICAgIGYgIT09ICdjc3BlbGwuanNvbicgJiZcbiAgICAgICAgICAgICAgICBmICE9PSAnZXNsaW50LmNvbmZpZy5tanMnICYmXG4gICAgICAgICAgICAgICAgZiAhPT0gJ2RpY3Rpb25hcnkudHh0JyAmJlxuICAgICAgICAgICAgICAgIGYgIT09ICdub2RlX21vZHVsZXMnICYmXG4gICAgICAgICAgICAgICAgZiAhPT0gJ3Rlc3QnICYmXG4gICAgICAgICAgICAgICAgZiAhPT0gJ2JpbicsXG4gICAgICAgIClcbiAgICAgICAgbGV0IGZpbGUgPSBsaXN0W2krK11cbiAgICAgICAgaWYgKCFmaWxlKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0c1xuICAgICAgICB9XG4gICAgICAgIGZpbGUgPSBkaXIgKyAnLycgKyBmaWxlXG4gICAgICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgc3RhdChmaWxlKVxuICAgICAgICBpZiAoc3RhdHMuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgICAgcmVzdWx0cyA9IFsuLi5yZXN1bHRzLCAuLi4oYXdhaXQgZmluZChmaWxlKSldXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHRzLnB1c2goZmlsZSlcbiAgICAgICAgfVxuICAgIH1cbn1cblxudHlwZSBIb3N0ID0ge1xuICAgIGVudHJ5OiAoXG4gICAgICAgIHR5cGU6IHN0cmluZyxcbiAgICAgICAgc2VydmljZTogc3RyaW5nLFxuICAgICAgICBuYW1lOiBzdHJpbmcsXG4gICAgICAgIHJldmlzaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgICAgIGNvbmZpZzogb2JqZWN0IHwgdW5kZWZpbmVkLFxuICAgICkgPT4gc3RyaW5nXG4gICAgcGF0Y2g/OiAoYnVuZGxlZDogc3RyaW5nKSA9PiBzdHJpbmdcbn1cblxuYXN5bmMgZnVuY3Rpb24gcm9sbHVwQW5kTWluaWZ5KFxuICAgIGxvZzoge1xuICAgICAgICB0cmFjZTogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZFxuICAgICAgICB3YXJuOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkXG4gICAgICAgIGVycm9yOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkXG4gICAgfSxcbiAgICBob3N0OiBIb3N0LFxuICAgIF9wYXRoOiBzdHJpbmcsXG4gICAgc3RhZ2VQYXRoOiBzdHJpbmcsXG4gICAgc2VydmljZTogc3RyaW5nLFxuICAgIHJldmlzaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQsXG4gICAgY29uZmlnOiB1bmtub3duLFxuICAgIGZ1bmN0aW9uczogc3RyaW5nW10sXG4gICAgdHlwZXM6IHsgW25hbWU6IHN0cmluZ106ICdodHRwJyB8ICd0aW1lcicgfCAnZXZlbnQnIH0sXG4pIHtcbiAgICBjb25zdCBtaW5pZmllZCA9IFtdXG4gICAgbGV0IHJvbGx1cENhY2hlOiBSb2xsdXBDYWNoZSB8IHVuZGVmaW5lZFxuICAgIGZvciAoY29uc3QgZm4gb2YgZnVuY3Rpb25zKSB7XG4gICAgICAgIGNvbnN0IGZ1bmN0aW9uVHlwZSA9IHR5cGVzW2ZuXVxuICAgICAgICBpZiAoIWZ1bmN0aW9uVHlwZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUeXBlIG9mIGZ1bmN0aW9uICR7Zm59IG5vdCBkZXRlcm1pbmVkLmApXG4gICAgICAgIH1cbiAgICAgICAgbGV0IHNlcmlvdXNXYXJuaW5ncyA9IGZhbHNlXG4gICAgICAgIGNvbnN0IGJ1bmRsZXIgPSBhd2FpdCByb2xsdXAoe1xuICAgICAgICAgICAgaW5wdXQ6ICdlbnRyeScsXG4gICAgICAgICAgICBjYWNoZTogcm9sbHVwQ2FjaGUsXG4gICAgICAgICAgICB0cmVlc2hha2U6IHtcbiAgICAgICAgICAgICAgICBjb3JyZWN0VmFyVmFsdWVCZWZvcmVEZWNsYXJhdGlvbjogZmFsc2UsXG4gICAgICAgICAgICAgICAgcHJvcGVydHlSZWFkU2lkZUVmZmVjdHM6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHVua25vd25HbG9iYWxTaWRlRWZmZWN0czogZmFsc2UsXG4gICAgICAgICAgICAgICAgbW9kdWxlU2lkZUVmZmVjdHM6IHRydWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcGx1Z2luczogW1xuICAgICAgICAgICAgICAgICh2aXJ0dWFsIGFzIHVua25vd24gYXMgKG9wdGlvbnM6IHVua25vd24pID0+IFBsdWdpbikoe1xuICAgICAgICAgICAgICAgICAgICBlbnRyeTogYXdzLmVudHJ5KGZ1bmN0aW9uVHlwZSwgc2VydmljZSwgZm4sIHJldmlzaW9uLCBjb25maWcpLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIG5vZGVSZXNvbHZlKHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0Q29uZGl0aW9uczogWydub2RlJ10sXG4gICAgICAgICAgICAgICAgICAgIHJvb3REaXI6IHN0YWdlUGF0aCxcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAoY29tbW9uanMgYXMgdW5rbm93biBhcyAoKSA9PiBQbHVnaW4pKCksXG4gICAgICAgICAgICAgICAgKGpzb24gYXMgdW5rbm93biBhcyAoKSA9PiBQbHVnaW4pKCksXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgb253YXJuOiB3YXJuaW5nID0+IHtcbiAgICAgICAgICAgICAgICBpZiAod2FybmluZy5jb2RlID09PSAnVEhJU19JU19VTkRFRklORUQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIHdhcm5pbmcuY29kZSA9PT0gJ01JU1NJTkdfRVhQT1JUJyAmJlxuICAgICAgICAgICAgICAgICAgICB3YXJuaW5nLmlkID09PSAnXFx1MDAwMHZpcnR1YWw6ZW50cnknICYmXG4gICAgICAgICAgICAgICAgICAgIHdhcm5pbmcuYmluZGluZyA9PT0gJ3NldE1ldGEnXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsb2cud2FybihgJHt3YXJuaW5nLmNvZGUgPz8gd2FybmluZy5tZXNzYWdlfSBbJHtmbn1dYClcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIHdhcm5pbmcuY29kZSA9PT0gJ0NJUkNVTEFSX0RFUEVOREVOQ1knICYmXG4gICAgICAgICAgICAgICAgICAgIHdhcm5pbmcuaWRzICYmXG4gICAgICAgICAgICAgICAgICAgIHdhcm5pbmcuaWRzLmxlbmd0aCAhPT0gMFxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBsb2cud2Fybih3YXJuaW5nLmlkcy5tYXAocCA9PiByZWxhdGl2ZShzdGFnZVBhdGgsIHApKS5qb2luKCcgLT4gJykpXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm5pbmcuY29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9nLndhcm4od2FybmluZy5tZXNzYWdlKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuaW5nLmZyYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsb2cud2Fybih3YXJuaW5nLmZyYW1lKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh3YXJuaW5nLmNvZGUgPT09ICdVTlJFU09MVkVEX0lNUE9SVCcpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VyaW91c1dhcm5pbmdzID0gdHJ1ZVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIHJvbGx1cENhY2hlID0gYnVuZGxlci5jYWNoZVxuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICBvdXRwdXQ6IFt7IGNvZGUsIG1hcCB9LCB2aXJ0dWFsRW50cnksIG1vcmVdLFxuICAgICAgICB9ID0gYXdhaXQgYnVuZGxlci5nZW5lcmF0ZSh7XG4gICAgICAgICAgICBmb3JtYXQ6ICdjanMnLFxuICAgICAgICAgICAgY29tcGFjdDogdHJ1ZSxcbiAgICAgICAgICAgIHNvdXJjZW1hcDogdHJ1ZSxcbiAgICAgICAgICAgIG1hbnVhbENodW5rczogKCkgPT4gJ2VudHJ5LmpzJyxcbiAgICAgICAgICAgIGdlbmVyYXRlZENvZGU6IHtcbiAgICAgICAgICAgICAgICBwcmVzZXQ6ICdlczIwMTUnLFxuICAgICAgICAgICAgICAgIGFycm93RnVuY3Rpb25zOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNvbnN0QmluZGluZ3M6IHRydWUsXG4gICAgICAgICAgICAgICAgb2JqZWN0U2hvcnRoYW5kOiB0cnVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bm5lY2Vzc2FyeS1jb25kaXRpb25cbiAgICAgICAgaWYgKHNlcmlvdXNXYXJuaW5ncykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTdXNwaWNpb3VzIGJ1bmRsZXIgd2FybmluZ3MuJylcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB7IHR5cGUsIGZpbGVOYW1lIH0gPSB2aXJ0dWFsRW50cnkgPz8ge31cbiAgICAgICAgaWYgKHR5cGUgIT09ICdhc3NldCcgfHwgZmlsZU5hbWUgIT09ICdfdmlydHVhbF9lbnRyeS5qcy5tYXAnKSB7XG4gICAgICAgICAgICBsb2cuZXJyb3IoSlNPTi5zdHJpbmdpZnkobW9yZSkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlaXJkJylcbiAgICAgICAgfVxuICAgICAgICBpZiAobWFwPy52ZXJzaW9uICE9PSAzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1NvdXJjZSBtYXAgbWlzc2luZy4nKVxuICAgICAgICB9XG4gICAgICAgIG1pbmlmaWVkLnB1c2gocGFjayhsb2csIGhvc3QsIHN0YWdlUGF0aCwgZm4sIGNvZGUsIHsgLi4ubWFwLCB2ZXJzaW9uOiAzIH0pKVxuICAgIH1cbiAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwobWluaWZpZWQpXG59XG5cbmFzeW5jIGZ1bmN0aW9uIHBhY2soXG4gICAgbG9nOiB7IHRyYWNlOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkIH0sXG4gICAgaG9zdDogSG9zdCxcbiAgICBzdGFnZVBhdGg6IHN0cmluZyxcbiAgICBmbjogc3RyaW5nLFxuICAgIHNvdXJjZTogc3RyaW5nLFxuICAgIG1hcDogU291cmNlTWFwICYgeyB2ZXJzaW9uOiAzIH0sXG4pIHtcbiAgICBsb2cudHJhY2UoYG1pbmlmeWluZyAke2ZufWApXG4gICAgY29uc3QgbWluID0gbWluaWZ5X3N5bmMoXG4gICAgICAgIHsgW2Ake2ZufS5qc2BdOiBzb3VyY2UgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgY29tcHJlc3M6IHtcbiAgICAgICAgICAgICAgICBtb2R1bGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZWNtYTogMjAyMCxcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2FtZWxjYXNlXG4gICAgICAgICAgICAgICAgaG9pc3RfZnVuczogdHJ1ZSxcbiAgICAgICAgICAgICAgICBwYXNzZXM6IDIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWFuZ2xlOiB7XG4gICAgICAgICAgICAgICAgbW9kdWxlOiB0cnVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNvdXJjZU1hcDoge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IG1hcCxcbiAgICAgICAgICAgICAgICBmaWxlbmFtZTogYCR7Zm59LmpzLm1hcGAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZm9ybWF0OiB7XG4gICAgICAgICAgICAgICAgZWNtYTogMjAyMCxcbiAgICAgICAgICAgICAgICBjb21tZW50czogZmFsc2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgIClcbiAgICBpZiAoIW1pbi5jb2RlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignV2VpcmQnKVxuICAgIH1cbiAgICBjb25zdCBjb2RlID0gaG9zdC5wYXRjaCA/IGhvc3QucGF0Y2gobWluLmNvZGUpIDogbWluLmNvZGVcbiAgICBsb2cudHJhY2UoYCR7Zm59IG1pbmlmaWVkYClcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgIHdyaXRlRmlsZShqb2luKHN0YWdlUGF0aCwgZm4gKyAnLm1pbi5qcycpLCBjb2RlKSxcbiAgICAgICAgd3JpdGVGaWxlKFxuICAgICAgICAgICAgam9pbihzdGFnZVBhdGgsIGZuICsgJy5taW4uanMubWFwLmd6JyksXG4gICAgICAgICAgICBhd2FpdCBnemlwKG1pbi5tYXAgYXMgdW5rbm93biBhcyBBcnJheUJ1ZmZlciksXG4gICAgICAgICksXG4gICAgXSlcblxuICAgIHJldHVybiB7IGZuLCBjb2RlIH1cbn1cblxuZnVuY3Rpb24gZ3ppcChkYXRhOiBBcnJheUJ1ZmZlcikge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxCdWZmZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgemxpYi5nemlwKGRhdGEsIHsgbGV2ZWw6IDkgfSwgKGVyciwgYnVmKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgcmVqZWN0KGVycilcbiAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc29sdmUoYnVmKVxuICAgICAgICB9KVxuICAgIH0pXG59XG4iXX0=