@riddance/deploy
Version:
250 lines (249 loc) • 35.5 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: (fn) => `
import './${fn}.js'
import { awsHandler } from '@riddance/aws-host/http'
export const handler = awsHandler
`,
patch: (code) => `/*global fetch AbortController*/${code}`,
};
export async function stage(path, implementations, service) {
const stagePath = join(tmpdir(), 'riddance', 'stage', service);
console.log(`stage dir: ${stagePath}`);
console.log('staging...');
const { functions, hashes } = await copyAndPatchProject(path, stagePath, implementations);
console.log('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(aws, path, stagePath, changed)),
...(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(aws, path, stagePath, functions);
await writeFile(join(stagePath, '.hashes.json'), hashesJson);
return code;
}
}
async function copyAndPatchProject(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'));
for (const [pkg, sub] of Object.entries(implementations)) {
if (packageJson.dependencies[pkg]) {
delete packageJson.dependencies[pkg];
packageJson.dependencies[sub.implementation] = sub.version;
}
}
delete packageJson.devDependencies;
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 };
}
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(host, _path, stagePath, functions) {
const minified = [];
let rollupCache;
for (const fn of functions) {
const bundler = await rollup({
input: 'entry',
cache: rollupCache,
treeshake: {
correctVarValueBeforeDeclaration: false,
propertyReadSideEffects: false,
unknownGlobalSideEffects: false,
moduleSideEffects: true,
},
plugins: [
virtual({
entry: aws.entry(fn),
}),
nodeResolve({
exportConditions: ['node'],
rootDir: stagePath,
}),
commonjs(),
json(),
],
onwarn: warning => {
if (warning.code === 'THIS_IS_UNDEFINED') {
return;
}
console.warn(`${warning.code ?? warning.message} [${fn}]`);
if (warning.code === 'CIRCULAR_DEPENDENCY' &&
warning.ids &&
warning.ids.length !== 0) {
console.warn(warning.ids.map(p => relative(stagePath, p)).join(' -> '));
}
},
});
rollupCache = bundler.cache;
const { output } = await bundler.generate({
format: 'cjs',
compact: true,
sourcemap: true,
manualChunks: () => 'entry.js',
generatedCode: {
preset: 'es2015',
arrowFunctions: true,
constBindings: true,
objectShorthand: true,
},
});
if (output.length !== 2) {
console.log(output[2]);
throw new Error('Weird');
}
if (output[1]?.type !== 'asset' || output[1].fileName !== '_virtual_entry.js.map') {
console.log(output[2]);
throw new Error('Weird');
}
const [{ code, map }] = output;
if (!map || map.version !== 3) {
throw new Error('Source map missing.');
}
minified.push(pack(host, stagePath, fn, code, { ...map, version: 3 }));
}
return await Promise.all(minified);
}
async function pack(host, stagePath, fn, source, map) {
console.log(`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;
console.log(`${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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzdGFnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLFFBQVEsTUFBTSx5QkFBeUIsQ0FBQTtBQUM5QyxPQUFPLElBQUksTUFBTSxxQkFBcUIsQ0FBQTtBQUN0QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNkJBQTZCLENBQUE7QUFDekQsT0FBTyxPQUFPLE1BQU0sd0JBQXdCLENBQUE7QUFDNUMsT0FBTyxFQUFFLE1BQU0sRUFBdUMsTUFBTSxtQkFBbUIsQ0FBQTtBQUMvRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQ3hDLE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDNUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUNoQyxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDbkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQzdDLE9BQU8sSUFBSSxNQUFNLFdBQVcsQ0FBQTtBQUM1QixxQ0FBcUM7QUFDckMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLFFBQVEsQ0FBQTtBQUNwQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBT2xDLE1BQU0sR0FBRyxHQUFHO0lBQ1IsS0FBSyxFQUFFLENBQUMsRUFBVSxFQUFFLEVBQUUsQ0FBQztZQUNmLEVBQUU7Ozs7Q0FJYjtJQUNHLEtBQUssRUFBRSxDQUFDLElBQVksRUFBRSxFQUFFLENBQUMsbUNBQW1DLElBQUksRUFBRTtDQUNyRSxDQUFBO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxLQUFLLENBQ3ZCLElBQVksRUFDWixlQUEwRCxFQUMxRCxPQUFlO0lBRWYsTUFBTSxTQUFTLEdB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LFNBQVMsRUFBRSxFQUFFLEdBQUcsZ0JBQWdCLENBQUMsRUFDdEMsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQWlDLENBQUMsQ0FDcEQ7S0FDSixDQUFDLENBQUE7SUFFRixPQUFPLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFBO0FBQ3ZCLENBQUM7QUFFRCxTQUFTLElBQUksQ0FBQyxJQUFxQjtJQUMvQixPQUFPLElBQUksT0FBTyxDQUFTLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1FBQzNDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFO1lBQ3ZDLElBQUksR0FBRyxFQUFFLENBQUM7Z0JBQ04sTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNYLE9BQU07WUFDVixDQUFDO1lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQ2hCLENBQUMsQ0FBQyxDQUFBO0lBQ04sQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNvbW1vbmpzIGZyb20gJ0Byb2xsdXAvcGx1Z2luLWNvbW1vbmpzJ1xuaW1wb3J0IGpzb24gZnJvbSAnQHJvbGx1cC9wbHVnaW4tanNvbidcbmltcG9ydCB7IG5vZGVSZXNvbHZlIH0gZnJvbSAnQHJvbGx1cC9wbHVnaW4tbm9kZS1yZXNvbHZlJ1xuaW1wb3J0IHZpcnR1YWwgZnJvbSAnQHJvbGx1cC9wbHVnaW4tdmlydHVhbCdcbmltcG9ydCB7IHJvbGx1cCwgUm9sbHVwQ2FjaGUsIFNvdXJjZU1hcCwgdHlwZSBQbHVnaW4gfSBmcm9tICdAcm9sbHVwL3dhc20tbm9kZSdcbmltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tICdub2RlOmNyeXB0bydcbmltcG9ydCB7IG1rZGlyLCByZWFkZGlyLCByZWFkRmlsZSwgc3RhdCwgd3JpdGVGaWxlIH0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcydcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gJ25vZGU6b3MnXG5pbXBvcnQgeyBkaXJuYW1lLCBqb2luLCByZWxhdGl2ZSB9IGZyb20gJ25vZGU6cGF0aCdcbmltcG9ydCB7IGlzRGVlcFN0cmljdEVxdWFsIH0gZnJvbSAnbm9kZTp1dGlsJ1xuaW1wb3J0IHpsaWIgZnJvbSAnbm9kZTp6bGliJ1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNhbWVsY2FzZVxuaW1wb3J0IHsgbWluaWZ5X3N5bmMgfSBmcm9tICd0ZXJzZXInXG5pbXBvcnQgeyBpbnN0YWxsIH0gZnJvbSAnLi9ucG0uanMnXG5cbnR5cGUgSW1wbGVtZW50YXRpb24gPSB7XG4gICAgaW1wbGVtZW50YXRpb246IHN0cmluZ1xuICAgIHZlcnNpb246IHN0cmluZ1xufVxuXG5jb25zdCBhd3MgPSB7XG4gICAgZW50cnk6IChmbjogc3RyaW5nKSA9PiBgXG5pbXBvcnQgJy4vJHtmbn0uanMnXG5pbXBvcnQgeyBhd3NIYW5kbGVyIH0gZnJvbSAnQHJpZGRhbmNlL2F3cy1ob3N0L2h0dHAnXG5cbmV4cG9ydCBjb25zdCBoYW5kbGVyID0gYXdzSGFuZGxlclxuYCxcbiAgICBwYXRjaDogKGNvZGU6IHN0cmluZykgPT4gYC8qZ2xvYmFsIGZldGNoIEFib3J0Q29udHJvbGxlciovJHtjb2RlfWAsXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFnZShcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgaW1wbGVtZW50YXRpb25zOiB7IFtmcm9tUGFja2FnZTogc3RyaW5nXTogSW1wbGVtZW50YXRpb24gfSxcbiAgICBzZXJ2aWNlOiBzdHJpbmcsXG4pIHtcbiAgICBjb25zdCBzdGFnZVBhdGggPSBqb2luKHRtcGRpcigpLCAncmlkZGFuY2UnLCAnc3RhZ2UnLCBzZXJ2aWNlKVxuICAgIGNvbnNvbGUubG9nKGBzdGFnZSBkaXI6ICR7c3RhZ2VQYXRofWApXG4gICAgY29uc29sZS5sb2coJ3N0YWdpbmcuLi4nKVxuICAgIGNvbnN0IHsgZnVuY3Rpb25zLCBoYXNoZXMgfSA9IGF3YWl0IGNvcHlBbmRQYXRjaFByb2plY3QocGF0aCwgc3RhZ2VQYXRoLCBpbXBsZW1lbnRhdGlvbnMpXG5cbiAgICBjb25zb2xlLmxvZygnc3luY2luZyBkZXBlbmRlbmNpZXMuLi4nKVxuICAgIGF3YWl0IGluc3RhbGwoc3RhZ2VQYXRoKVxuICAgIGhhc2hlc1sncGFja2FnZS1sb2NrLmpzb24nXSA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpXG4gICAgICAgIC51cGRhdGUoYXdhaXQgcmVhZEZpbGUoam9pbihzdGFnZVBhdGgsICdwYWNrYWdlLWxvY2suanNvbicpKSlcbiAgICAgICAgLmRpZ2VzdCgnYmFzZTY0JylcblxuICAgIGxldCBwcmV2aW91czogeyBbc291cmNlOiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9XG4gICAgdHJ5IHtcbiAgICAgICAgcHJldmlvdXMgPSBKU09OLnBhcnNlKGF3YWl0IHJlYWRGaWxlKGpvaW4oc3RhZ2VQYXRoLCAnLmhhc2hlcy5qc29uJyksICd1dGYtOCcpKSBhcyB7XG4gICAgICAgICAgICBbc291cmNlOiBzdHJpbmddOiBzdHJpbmdcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKChlIGFzIHsgY29kZT86IHN0cmluZyB9KS5jb2RlICE9PSAnRU5PRU5UJykge1xuICAgICAgICAgICAgdGhyb3cgZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcGFja2FnZUNoYW5nZSA9XG4gICAgICAgIHByZXZpb3VzWydwYWNrYWdlLmpzb24nXSAhPT0gaGFzaGVzWydwYWNrYWdlLmpzb24nXSB8fFxuICAgICAgICBwcmV2aW91c1sncGFja2FnZS1sb2NrLmpzb24nXSAhPT0gaGFzaGVzWydwYWNrYWdlLWxvY2suanNvbiddXG5cbiAgICBjb25zdCBoYXNoZXNKc29uID0gSlNPTi5zdHJpbmdpZnkoaGFzaGVzLCB1bmRlZmluZWQsICcgICcpXG4gICAgY29uc3QgY2hhbmdlZCA9IFtdXG4gICAgY29uc3QgdW5jaGFuZ2VkID0gW11cbiAgICBmb3IgKGNvbnN0IGZuIG9mIGZ1bmN0aW9ucykge1xuICAgICAgICBjb25zdCBmaWxlID0gZm4gKyAnLmpzJ1xuICAgICAgICBpZiAocHJldmlvdXNbZmlsZV0gIT09IGhhc2hlc1tmaWxlXSB8fCBwYWNrYWdlQ2hhbmdlKSB7XG4gICAgICAgICAgICBjaGFuZ2VkLnB1c2goZm4pXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1bmNoYW5nZWQucHVzaChmbilcbiAgICAgICAgfVxuICAgICAgICBkZWxldGUgcHJldmlvdXNbZmlsZV1cbiAgICAgICAgZGVsZXRlIGhhc2hlc1tmaWxlXVxuICAgIH1cbiAgICBjb25zdCBub25GdW5jdGlvbkZpbGVzVW5jaGFuZ2VkID0gaXNEZWVwU3RyaWN0RXF1YWwocHJldmlvdXMsIGhhc2hlcylcbiAgICBpZiAobm9uRnVuY3Rpb25GaWxlc1VuY2hhbmdlZCkge1xuICAgICAgICBjb25zdCBjb2RlID0gW1xuICAgICAgICAgICAgLi4uKGF3YWl0IHJvbGx1cEFuZE1pbmlmeShhd3MsIHBhdGgsIHN0YWdlUGF0aCwgY2hhbmdlZCkpLFxuICAgICAgICAgICAgLi4uKGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICAgICAgICAgIHVuY2hhbmdlZC5tYXAoYXN5bmMgZm4gPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgZm4sXG4gICAgICAgICAgICAgICAgICAgIGNvZGU6IGF3YWl0IHJlYWRGaWxlKGpvaW4oc3RhZ2VQYXRoLCBmbiArICcubWluLmpzJyksICd1dGYtOCcpLFxuICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgICkpLFxuICAgICAgICBdXG4gICAgICAgIGF3YWl0IHdyaXRlRmlsZShqb2luKHN0YWdlUGF0aCwgJy5oYXNoZXMuanNvbicpLCBoYXNoZXNKc29uKVxuICAgICAgICByZXR1cm4gY29kZVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IGNvZGUgPSBhd2FpdCByb2xsdXBBbmRNaW5pZnkoYXdzLCBwYXRoLCBzdGFnZVBhdGgsIGZ1bmN0aW9ucylcbiAgICAgICAgYXdhaXQgd3JpdGVGaWxlKGpvaW4oc3RhZ2VQYXRoLCAnLmhhc2hlcy5qc29uJyksIGhhc2hlc0pzb24pXG4gICAgICAgIHJldHVybiBjb2RlXG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBjb3B5QW5kUGF0Y2hQcm9qZWN0KFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICB0YXJnZXQ6IHN0cmluZyxcbiAgICBpbXBsZW1lbnRhdGlvbnM6IHsgW2Zyb21QYWNrYWdlOiBzdHJpbmddOiBJbXBsZW1lbnRhdGlvbiB9LFxuKSB7XG4gICAgY29uc3QgaGFzaGVzOiB7IFtzb3VyY2U6IHN0cmluZ106IHN0cmluZyB9ID0ge31cbiAgICBjb25zdCBzb3VyY2VGaWxlcyA9IChhd2FpdCBmaW5kKHBhdGgpKS5tYXAoZiA9PiBmLnNsaWNlKHBhdGgubGVuZ3RoICsgMSkpXG4gICAgY29uc3Qgc2VydmljZUZpbGVzID0gc291cmNlRmlsZXMuZmlsdGVyKGYgPT4gZi5lbmRzV2l0aCgnLmpzJykgJiYgIWYuaW5jbHVkZXMoJy8nKSlcblxuICAgIGZvciAoY29uc3Qgc2Ygb2Ygc291cmNlRmlsZXMpIHtcbiAgICAgICAgaGFzaGVzW3NmXSA9IGF3YWl0IG1rRGlyQ29weUZpbGUoam9pbihwYXRoLCBzZiksIGpvaW4odGFyZ2V0LCBzZiksIGltcGxlbWVudGF0aW9ucylcbiAgICB9XG5cbiAgICBjb25zdCBwYWNrYWdlRmlsZSA9IGpvaW4odGFyZ2V0LCAncGFja2FnZS5qc29uJylcbiAgICBjb25zdCBwYWNrYWdlSnNvbiA9IEpTT04ucGFyc2UoYXdhaXQgcmVhZEZpbGUocGFja2FnZUZpbGUsICd1dGYtOCcpKSBhcyB7XG4gICAgICAgIG5hbWU6IHN0cmluZ1xuICAgICAgICBjb25maWc/OiB1bmtub3duXG4gICAgICAgIGRlcGVuZGVuY2llczogeyBbcGFja2FnZU5hbWU6IHN0cmluZ106IHN0cmluZyB9XG4gICAgICAgIGRldkRlcGVuZGVuY2llcz86IHVua25vd25cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IFtwa2csIHN1Yl0gb2YgT2JqZWN0LmVudHJpZXMoaW1wbGVtZW50YXRpb25zKSkge1xuICAgICAgICBpZiAocGFja2FnZUpzb24uZGVwZW5kZW5jaWVzW3BrZ10pIHtcbiAgICAgICAgICAgIGRlbGV0ZSBwYWNrYWdlSnNvbi5kZXBlbmRlbmNpZXNbcGtnXVxuICAgICAgICAgICAgcGFja2FnZUpzb24uZGVwZW5kZW5jaWVzW3N1Yi5pbXBsZW1lbnRhdGlvbl0gPSBzdWIudmVyc2lvblxuICAgICAgICB9XG4gICAgfVxuICAgIGRlbGV0ZSBwYWNrYWdlSnNvbi5kZXZEZXBlbmRlbmNpZXNcblxuICAgIGNvbnN0IHVwZGF0ZWQgPSBKU09OLnN0cmluZ2lmeShwYWNrYWdlSnNvbilcbiAgICBoYXNoZXNbJ3BhY2thZ2UuanNvbiddID0gY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKHVwZGF0ZWQpLmRpZ2VzdCgnYmFzZTY0JylcbiAgICBhd2FpdCB3cml0ZUZpbGUocGFja2FnZUZpbGUsIHVwZGF0ZWQpXG5cbiAgICByZXR1cm4geyBmdW5jdGlvbnM6IHNlcnZpY2VGaWxlcy5tYXAoZiA9PiBmLnNsaWNlKDAsIC0zKSksIGhhc2hlcyB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1rRGlyQ29weUZpbGUoXG4gICAgc291cmNlOiBzdHJpbmcsXG4gICAgdGFyZ2V0OiBzdHJpbmcsXG4gICAgaW1wbGVtZW50YXRpb25zOiB7IFtmcm9tUGFja2FnZTogc3RyaW5nXTogSW1wbGVtZW50YXRpb24gfSxcbikge1xuICAgIGxldCBjb2RlID0gYXdhaXQgcmVhZEZpbGUoc291cmNlLCAndXRmLTgnKVxuICAgIGZvciAoY29uc3QgW2Zyb21QYWNrYWdlLCB0b1BhY2thZ2VdIG9mIE9iamVjdC5lbnRyaWVzKGltcGxlbWVudGF0aW9ucykpIHtcbiAgICAgICAgY29kZSA9IGNvZGUucmVwbGFjZUFsbChcbiAgICAgICAgICAgIG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgICAgYGltcG9ydCBcXFxceyAoW159XSspIFxcXFx9IGZyb20gJyR7ZnJvbVBhY2thZ2UucmVwbGFjZUFsbCgnLycsICdcXFxcLycpfSh8L1teJ10rKSc7YCxcbiAgICAgICAgICAgICAgICAnZ3UnLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIGBpbXBvcnQgeyAkMSB9IGZyb20gJyR7dG9QYWNrYWdlLmltcGxlbWVudGF0aW9ufSQyJztgLFxuICAgICAgICApXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHdyaXRlRmlsZSh0YXJnZXQsIGNvZGUpXG4gICAgfSBjYXRjaCB7XG4gICAgICAgIGF3YWl0IG1rZGlyKGRpcm5hbWUodGFyZ2V0KSwgeyByZWN1cnNpdmU6IHRydWUgfSlcbiAgICAgICAgYXdhaXQgd3JpdGVGaWxlKHRhcmdldCwgY29kZSlcbiAgICB9XG4gICAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShjb2RlKS5kaWdlc3QoJ2Jhc2U2NCcpXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbmQoZGlyOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgbGV0IHJlc3VsdHM6IHN0cmluZ1tdID0gW11cbiAgICBsZXQgaSA9IDBcbiAgICBmb3IgKDs7KSB7XG4gICAgICAgIGNvbnN0IGxpc3QgPSAoYXdhaXQgcmVhZGRpcihkaXIpKS5maWx0ZXIoXG4gICAgICAgICAgICBmID0+XG4gICAgICAgICAgICAgICAgIWYuc3RhcnRzV2l0aCgnLicpICYmXG4gICAgICAgICAgICAgICAgIWYuZW5kc1dpdGgoJy50cycpICYmXG4gICAgICAgICAgICAgICAgIWYuZW5kc1dpdGgoJy5neicpICYmXG4gICAgICAgICAgICAgICAgIWYuZW5kc1dpdGgoJy5taW4uanMnKSAmJlxuICAgICAgICAgICAgICAgIGYgIT09ICd0c2NvbmZpZy5qc29uJyAmJlxuICAgICAgICAgICAgICAgIGYgIT09ICdjc3BlbGwuanNvbicgJiZcbiAgICAgICAgICAgICAgICBmICE9PSAnZXNsaW50LmNvbmZpZy5tanMnICYmXG4gICAgICAgICAgICAgICAgZiAhPT0gJ2RpY3Rpb25hcnkudHh0JyAmJlxuICAgICAgICAgICAgICAgIGYgIT09ICdub2RlX21vZHVsZXMnICYmXG4gICAgICAgICAgICAgICAgZiAhPT0gJ3Rlc3QnICYmXG4gICAgICAgICAgICAgICAgZiAhPT0gJ2JpbicsXG4gICAgICAgIClcbiAgICAgICAgbGV0IGZpbGUgPSBsaXN0W2krK11cbiAgICAgICAgaWYgKCFmaWxlKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0c1xuICAgICAgICB9XG4gICAgICAgIGZpbGUgPSBkaXIgKyAnLycgKyBmaWxlXG4gICAgICAgIGNvbnN0IHN0YXRzID0gYXdhaXQgc3RhdChmaWxlKVxuICAgICAgICBpZiAoc3RhdHMuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICAgICAgcmVzdWx0cyA9IFsuLi5yZXN1bHRzLCAuLi4oYXdhaXQgZmluZChmaWxlKSldXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHRzLnB1c2goZmlsZSlcbiAgICAgICAgfVxuICAgIH1cbn1cblxudHlwZSBIb3N0ID0ge1xuICAgIGVudHJ5OiAoZm46IHN0cmluZykgPT4gc3RyaW5nXG4gICAgcGF0Y2g/OiAoYnVuZGxlZDogc3RyaW5nKSA9PiBzdHJpbmdcbn1cblxuYXN5bmMgZnVuY3Rpb24gcm9sbHVwQW5kTWluaWZ5KGhvc3Q6IEhvc3QsIF9wYXRoOiBzdHJpbmcsIHN0YWdlUGF0aDogc3RyaW5nLCBmdW5jdGlvbnM6IHN0cmluZ1tdKSB7XG4gICAgY29uc3QgbWluaWZpZWQgPSBbXVxuICAgIGxldCByb2xsdXBDYWNoZTogUm9sbHVwQ2FjaGUgfCB1bmRlZmluZWRcbiAgICBmb3IgKGNvbnN0IGZuIG9mIGZ1bmN0aW9ucykge1xuICAgICAgICBjb25zdCBidW5kbGVyID0gYXdhaXQgcm9sbHVwKHtcbiAgICAgICAgICAgIGlucHV0OiAnZW50cnknLFxuICAgICAgICAgICAgY2FjaGU6IHJvbGx1cENhY2hlLFxuICAgICAgICAgICAgdHJlZXNoYWtlOiB7XG4gICAgICAgICAgICAgICAgY29ycmVjdFZhclZhbHVlQmVmb3JlRGVjbGFyYXRpb246IGZhbHNlLFxuICAgICAgICAgICAgICAgIHByb3BlcnR5UmVhZFNpZGVFZmZlY3RzOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB1bmtub3duR2xvYmFsU2lkZUVmZmVjdHM6IGZhbHNlLFxuICAgICAgICAgICAgICAgIG1vZHVsZVNpZGVFZmZlY3RzOiB0cnVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBsdWdpbnM6IFtcbiAgICAgICAgICAgICAgICAodmlydHVhbCBhcyB1bmtub3duIGFzIChvcHRpb25zOiB1bmtub3duKSA9PiBQbHVnaW4pKHtcbiAgICAgICAgICAgICAgICAgICAgZW50cnk6IGF3cy5lbnRyeShmbiksXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgbm9kZVJlc29sdmUoe1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRDb25kaXRpb25zOiBbJ25vZGUnXSxcbiAgICAgICAgICAgICAgICAgICAgcm9vdERpcjogc3RhZ2VQYXRoLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIChjb21tb25qcyBhcyB1bmtub3duIGFzICgpID0+IFBsdWdpbikoKSxcbiAgICAgICAgICAgICAgICAoanNvbiBhcyB1bmtub3duIGFzICgpID0+IFBsdWdpbikoKSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBvbndhcm46IHdhcm5pbmcgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh3YXJuaW5nLmNvZGUgPT09ICdUSElTX0lTX1VOREVGSU5FRCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihgJHt3YXJuaW5nLmNvZGUgPz8gd2FybmluZy5tZXNzYWdlfSBbJHtmbn1dYClcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIHdhcm5pbmcuY29kZSA9PT0gJ0NJUkNVTEFSX0RFUEVOREVOQ1knICYmXG4gICAgICAgICAgICAgICAgICAgIHdhcm5pbmcuaWRzICYmXG4gICAgICAgICAgICAgICAgICAgIHdhcm5pbmcuaWRzLmxlbmd0aCAhPT0gMFxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4od2FybmluZy5pZHMubWFwKHAgPT4gcmVsYXRpdmUoc3RhZ2VQYXRoLCBwKSkuam9pbignIC0+ICcpKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pXG4gICAgICAgIHJvbGx1cENhY2hlID0gYnVuZGxlci5jYWNoZVxuICAgICAgICBjb25zdCB7IG91dHB1dCB9ID0gYXdhaXQgYnVuZGxlci5nZW5lcmF0ZSh7XG4gICAgICAgICAgICBmb3JtYXQ6ICdjanMnLFxuICAgICAgICAgICAgY29tcGFjdDogdHJ1ZSxcbiAgICAgICAgICAgIHNvdXJjZW1hcDogdHJ1ZSxcbiAgICAgICAgICAgIG1hbnVhbENodW5rczogKCkgPT4gJ2VudHJ5LmpzJyxcbiAgICAgICAgICAgIGdlbmVyYXRlZENvZGU6IHtcbiAgICAgICAgICAgICAgICBwcmVzZXQ6ICdlczIwMTUnLFxuICAgICAgICAgICAgICAgIGFycm93RnVuY3Rpb25zOiB0cnVlLFxuICAgICAgICAgICAgICAgIGNvbnN0QmluZGluZ3M6IHRydWUsXG4gICAgICAgICAgICAgICAgb2JqZWN0U2hvcnRoYW5kOiB0cnVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKG91dHB1dFsyXSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignV2VpcmQnKVxuICAgICAgICB9XG4gICAgICAgIGlmIChvdXRwdXRbMV0/LnR5cGUgIT09ICdhc3NldCcgfHwgb3V0cHV0WzFdLmZpbGVOYW1lICE9PSAnX3ZpcnR1YWxfZW50cnkuanMubWFwJykge1xuICAgICAgICAgICAgY29uc29sZS5sb2cob3V0cHV0WzJdKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdXZWlyZCcpXG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgW3sgY29kZSwgbWFwIH1dID0gb3V0cHV0XG4gICAgICAgIGlmICghbWFwIHx8IG1hcC52ZXJzaW9uICE9PSAzKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1NvdXJjZSBtYXAgbWlzc2luZy4nKVxuICAgICAgICB9XG4gICAgICAgIG1pbmlmaWVkLnB1c2gocGFjayhob3N0LCBzdGFnZVBhdGgsIGZuLCBjb2RlLCB7IC4uLm1hcCwgdmVyc2lvbjogMyB9KSlcbiAgICB9XG4gICAgcmV0dXJuIGF3YWl0IFByb21pc2UuYWxsKG1pbmlmaWVkKVxufVxuXG5hc3luYyBmdW5jdGlvbiBwYWNrKFxuICAgIGhvc3Q6IEhvc3QsXG4gICAgc3RhZ2VQYXRoOiBzdHJpbmcsXG4gICAgZm46IHN0cmluZyxcbiAgICBzb3VyY2U6IHN0cmluZyxcbiAgICBtYXA6IFNvdXJjZU1hcCAmIHsgdmVyc2lvbjogMyB9LFxuKSB7XG4gICAgY29uc29sZS5sb2coYG1pbmlmeWluZyAke2ZufWApXG4gICAgY29uc3QgbWluID0gbWluaWZ5X3N5bmMoXG4gICAgICAgIHsgW2Ake2ZufS5qc2BdOiBzb3VyY2UgfSxcbiAgICAgICAge1xuICAgICAgICAgICAgY29tcHJlc3M6IHtcbiAgICAgICAgICAgICAgICBtb2R1bGU6IHRydWUsXG4gICAgICAgICAgICAgICAgZWNtYTogMjAyMCxcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2FtZWxjYXNlXG4gICAgICAgICAgICAgICAgaG9pc3RfZnVuczogdHJ1ZSxcbiAgICAgICAgICAgICAgICBwYXNzZXM6IDIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWFuZ2xlOiB7XG4gICAgICAgICAgICAgICAgbW9kdWxlOiB0cnVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNvdXJjZU1hcDoge1xuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IG1hcCxcbiAgICAgICAgICAgICAgICBmaWxlbmFtZTogYCR7Zm59LmpzLm1hcGAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZm9ybWF0OiB7XG4gICAgICAgICAgICAgICAgZWNtYTogMjAyMCxcbiAgICAgICAgICAgICAgICBjb21tZW50czogZmFsc2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgIClcbiAgICBpZiAoIW1pbi5jb2RlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignV2VpcmQnKVxuICAgIH1cbiAgICBjb25zdCBjb2RlID0gaG9zdC5wYXRjaCA/IGhvc3QucGF0Y2gobWluLmNvZGUpIDogbWluLmNvZGVcbiAgICBjb25zb2xlLmxvZyhgJHtmbn0gbWluaWZpZWRgKVxuICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgd3JpdGVGaWxlKGpvaW4oc3RhZ2VQYXRoLCBmbiArICcubWluLmpzJyksIGNvZGUpLFxuICAgICAgICB3cml0ZUZpbGUoXG4gICAgICAgICAgICBqb2luKHN0YWdlUGF0aCwgZm4gKyAnLm1pbi5qcy5tYXAuZ3onKSxcbiAgICAgICAgICAgIGF3YWl0IGd6aXAobWluLm1hcCBhcyB1bmtub3duIGFzIEFycmF5QnVmZmVyTGlrZSksXG4gICAgICAgICksXG4gICAgXSlcblxuICAgIHJldHVybiB7IGZuLCBjb2RlIH1cbn1cblxuZnVuY3Rpb24gZ3ppcChkYXRhOiBBcnJheUJ1ZmZlckxpa2UpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8QnVmZmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHpsaWIuZ3ppcChkYXRhLCB7IGxldmVsOiA5IH0sIChlcnIsIGJ1ZikgPT4ge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpXG4gICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXNvbHZlKGJ1ZilcbiAgICAgICAgfSlcbiAgICB9KVxufVxuIl19