@riddance/deploy
Version:
162 lines • 24 kB
JavaScript
import { thrownHasStatus } from '@riddance/fetch';
import { SignatureV4 } from '@smithy/signature-v4';
import { createHash, createHmac } from 'node:crypto';
import { readFile } from 'node:fs/promises';
import { homedir } from 'node:os';
import { join } from 'node:path';
import { setTimeout } from 'node:timers/promises';
let cachedConfigLines;
export async function localAwsEnv(region, profile) {
let { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN } = {
AWS_REGION: region ?? process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION,
AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY,
AWS_SESSION_TOKEN: process.env.AWS_SESSION_TOKEN,
};
if (AWS_REGION && AWS_ACCESS_KEY_ID && AWS_SECRET_ACCESS_KEY) {
return { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY };
}
const configLines = cachedConfigLines ??
(await readFile(process.env.AWS_SHARED_CREDENTIALS_FILE ?? join(homedir(), '.aws', 'credentials'), 'ascii'))
.split('\n')
.map(line => line.trim())
.filter(line => !!line && !line.startsWith('#'));
// eslint-disable-next-line require-atomic-updates
cachedConfigLines = configLines;
let sectionBeginIx = -1;
const section = `[${profile}]`;
sectionBeginIx = configLines.indexOf(section);
if (sectionBeginIx === -1) {
sectionBeginIx = configLines.indexOf('[default]');
}
if (sectionBeginIx === -1) {
throw new Error('Section not found.');
}
const sectionEndIx = configLines.findIndex((line, ix) => ix > sectionBeginIx && line.startsWith('['));
const sectionLines = configLines
.slice(sectionBeginIx + 1, sectionEndIx === -1 ? undefined : sectionEndIx)
.map(line => line.split('='))
.map(([k, v]) => [k?.trim(), v?.trim()]);
AWS_REGION ??= sectionLines.find(([k]) => k === 'region')?.[1];
AWS_ACCESS_KEY_ID = sectionLines.find(([k]) => k === 'aws_access_key_id')?.[1];
AWS_SECRET_ACCESS_KEY = sectionLines.find(([k]) => k === 'aws_secret_access_key')?.[1];
AWS_SESSION_TOKEN = sectionLines.find(([k]) => k === 'aws_session_token')?.[1];
if (!AWS_REGION || !AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {
throw new Error('Incomplete AWS credentials file.');
}
return { AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN };
}
export function awsRequest(env, method, service, path, body) {
return awsStringRequest(env, method, service, path, body ? JSON.stringify(body) : '', 'application/json');
}
export function awsFormRequest(env, method, service, path, body) {
return awsStringRequest(env, method, service, path, body.toString(), 'application/x-www-form-urlencoded');
}
async function awsStringRequest(env, method, service, path, body, contentType) {
const signer = new SignatureV4({
service,
region: service === 'iam' ? 'us-east-1' : env.AWS_REGION,
sha256: AwsHash,
credentials: {
accessKeyId: env.AWS_ACCESS_KEY_ID,
secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
sessionToken: env.AWS_SESSION_TOKEN,
},
});
const uri = new URL(`https://${subdomain(service, env.AWS_REGION)}.amazonaws.com${path}`);
const query = {};
uri.searchParams.forEach((value, key) => {
query[key] = value;
});
const { headers } = await signer.sign({
method,
protocol: 'https:',
hostname: uri.hostname,
path: uri.pathname,
query,
headers: {
host: uri.hostname,
'content-type': contentType,
accept: 'application/json',
},
body,
});
return await fetch(uri.toString(), {
method,
headers,
body: body || undefined,
});
}
function subdomain(service, region) {
switch (service) {
case 'iam':
return 'iam';
default:
return `${service}.${region}`;
}
}
export async function retry(request, when) {
for (let attempts = 0;; ++attempts) {
const response = await request();
const maxRetries = when(response);
if (maxRetries === undefined || maxRetries <= attempts) {
return response;
}
console.log(`retrying #${attempts + 1}... (${response.url} -> ${await response.text()})`);
await setTimeout(500);
}
}
export function isNotFound(e) {
return thrownHasStatus(e, 404);
}
export function isConflict(e) {
return thrownHasStatus(e, 409);
}
export async function retryConflict(fn) {
const deadline = new Date();
deadline.setUTCSeconds(deadline.getUTCSeconds() + 30);
for (;;) {
try {
return await fn();
}
catch (e) {
if (!isConflict(e) || new Date() > deadline) {
throw e;
}
await setTimeout(((Math.random() + 0.5) * 500) / 2);
}
}
}
class AwsHash {
#secret;
#hash;
constructor(secret) {
this.#secret = secret;
this.#hash = makeHash(this.#secret);
}
digest() {
return Promise.resolve(this.#hash.digest());
}
reset() {
this.#hash = makeHash(this.#secret);
}
update(chunk) {
this.#hash.update(new Uint8Array(Buffer.from(chunk)));
}
}
function makeHash(secret) {
return secret ? createHmac('sha256', castSourceData(secret)) : createHash('sha256');
}
function castSourceData(data) {
if (Buffer.isBuffer(data)) {
return data;
}
if (typeof data === 'string') {
return Buffer.from(data);
}
if (ArrayBuffer.isView(data)) {
return Buffer.from(data.buffer, data.byteOffset, data.byteLength);
}
return Buffer.from(data);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGl0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImxpdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQ2pELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQTtBQUNsRCxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUNwRCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDM0MsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUNqQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQ2hDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQTtBQVNqRCxJQUFJLGlCQUF1QyxDQUFBO0FBRTNDLE1BQU0sQ0FBQyxLQUFLLFVBQVUsV0FBVyxDQUFDLE1BQTBCLEVBQUUsT0FBZTtJQUN6RSxJQUFJLEVBQUUsVUFBVSxFQUFFLGlCQUFpQixFQUFFLHFCQUFxQixFQUFFLGlCQUFpQixFQUFFLEdBQUc7UUFDOUUsVUFBVSxFQUFFLE1BQU0sSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQjtRQUM5RSxpQkFBaUIsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQjtRQUNoRCxxQkFBcUIsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLHFCQUFxQjtRQUN4RCxpQkFBaUIsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQjtLQUNuRCxDQUFBO0lBQ0QsSUFBSSxVQUFVLElBQUksaUJBQWlCLElBQUkscUJBQXFCLEVBQUUsQ0FBQztRQUMzRCxPQUFPLEVBQUUsVUFBVSxFQUFFLGlCQUFpQixFQUFFLHFCQUFxQixFQUFFLENBQUE7SUFDbkUsQ0FBQztJQUNELE1BQU0sV0FBVyxHQUNi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QUFXLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDM0IsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDckUsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQUM1QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdGhyb3duSGFzU3RhdHVzIH0gZnJvbSAnQHJpZGRhbmNlL2ZldGNoJ1xuaW1wb3J0IHsgU2lnbmF0dXJlVjQgfSBmcm9tICdAc21pdGh5L3NpZ25hdHVyZS12NCdcbmltcG9ydCB7IGNyZWF0ZUhhc2gsIGNyZWF0ZUhtYWMgfSBmcm9tICdub2RlOmNyeXB0bydcbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcydcbmltcG9ydCB7IGhvbWVkaXIgfSBmcm9tICdub2RlOm9zJ1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ25vZGU6cGF0aCdcbmltcG9ydCB7IHNldFRpbWVvdXQgfSBmcm9tICdub2RlOnRpbWVycy9wcm9taXNlcydcblxuZXhwb3J0IHR5cGUgTG9jYWxFbnYgPSB7XG4gICAgQVdTX1JFR0lPTjogc3RyaW5nXG4gICAgQVdTX0FDQ0VTU19LRVlfSUQ6IHN0cmluZ1xuICAgIEFXU19TRUNSRVRfQUNDRVNTX0tFWTogc3RyaW5nXG4gICAgQVdTX1NFU1NJT05fVE9LRU4/OiBzdHJpbmdcbn1cblxubGV0IGNhY2hlZENvbmZpZ0xpbmVzOiBzdHJpbmdbXSB8IHVuZGVmaW5lZFxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbG9jYWxBd3NFbnYocmVnaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQsIHByb2ZpbGU6IHN0cmluZyk6IFByb21pc2U8TG9jYWxFbnY+IHtcbiAgICBsZXQgeyBBV1NfUkVHSU9OLCBBV1NfQUNDRVNTX0tFWV9JRCwgQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZLCBBV1NfU0VTU0lPTl9UT0tFTiB9ID0ge1xuICAgICAgICBBV1NfUkVHSU9OOiByZWdpb24gPz8gcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTiA/PyBwcm9jZXNzLmVudi5BV1NfREVGQVVMVF9SRUdJT04sXG4gICAgICAgIEFXU19BQ0NFU1NfS0VZX0lEOiBwcm9jZXNzLmVudi5BV1NfQUNDRVNTX0tFWV9JRCxcbiAgICAgICAgQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZOiBwcm9jZXNzLmVudi5BV1NfU0VDUkVUX0FDQ0VTU19LRVksXG4gICAgICAgIEFXU19TRVNTSU9OX1RPS0VOOiBwcm9jZXNzLmVudi5BV1NfU0VTU0lPTl9UT0tFTixcbiAgICB9XG4gICAgaWYgKEFXU19SRUdJT04gJiYgQVdTX0FDQ0VTU19LRVlfSUQgJiYgQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZKSB7XG4gICAgICAgIHJldHVybiB7IEFXU19SRUdJT04sIEFXU19BQ0NFU1NfS0VZX0lELCBBV1NfU0VDUkVUX0FDQ0VTU19LRVkgfVxuICAgIH1cbiAgICBjb25zdCBjb25maWdMaW5lcyA9XG4gICAgICAgIGNhY2hlZENvbmZpZ0xpbmVzID8/XG4gICAgICAgIChcbiAgICAgICAgICAgIGF3YWl0IHJlYWRGaWxlKFxuICAgICAgICAgICAgICAgIHByb2Nlc3MuZW52LkFXU19TSEFSRURfQ1JFREVOVElBTFNfRklMRSA/PyBqb2luKGhvbWVkaXIoKSwgJy5hd3MnLCAnY3JlZGVudGlhbHMnKSxcbiAgICAgICAgICAgICAgICAnYXNjaWknLFxuICAgICAgICAgICAgKVxuICAgICAgICApXG4gICAgICAgICAgICAuc3BsaXQoJ1xcbicpXG4gICAgICAgICAgICAubWFwKGxpbmUgPT4gbGluZS50cmltKCkpXG4gICAgICAgICAgICAuZmlsdGVyKGxpbmUgPT4gISFsaW5lICYmICFsaW5lLnN0YXJ0c1dpdGgoJyMnKSlcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVxdWlyZS1hdG9taWMtdXBkYXRlc1xuICAgIGNhY2hlZENvbmZpZ0xpbmVzID0gY29uZmlnTGluZXNcblxuICAgIGxldCBzZWN0aW9uQmVnaW5JeCA9IC0xXG4gICAgY29uc3Qgc2VjdGlvbiA9IGBbJHtwcm9maWxlfV1gXG4gICAgc2VjdGlvbkJlZ2luSXggPSBjb25maWdMaW5lcy5pbmRleE9mKHNlY3Rpb24pXG4gICAgaWYgKHNlY3Rpb25CZWdpbkl4ID09PSAtMSkge1xuICAgICAgICBzZWN0aW9uQmVnaW5JeCA9IGNvbmZpZ0xpbmVzLmluZGV4T2YoJ1tkZWZhdWx0XScpXG4gICAgfVxuICAgIGlmIChzZWN0aW9uQmVnaW5JeCA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTZWN0aW9uIG5vdCBmb3VuZC4nKVxuICAgIH1cbiAgICBjb25zdCBzZWN0aW9uRW5kSXggPSBjb25maWdMaW5lcy5maW5kSW5kZXgoXG4gICAgICAgIChsaW5lLCBpeCkgPT4gaXggPiBzZWN0aW9uQmVnaW5JeCAmJiBsaW5lLnN0YXJ0c1dpdGgoJ1snKSxcbiAgICApXG4gICAgY29uc3Qgc2VjdGlvbkxpbmVzID0gY29uZmlnTGluZXNcbiAgICAgICAgLnNsaWNlKHNlY3Rpb25CZWdpbkl4ICsgMSwgc2VjdGlvbkVuZEl4ID09PSAtMSA/IHVuZGVmaW5lZCA6IHNlY3Rpb25FbmRJeClcbiAgICAgICAgLm1hcChsaW5lID0+IGxpbmUuc3BsaXQoJz0nKSlcbiAgICAgICAgLm1hcCgoW2ssIHZdKSA9PiBbaz8udHJpbSgpLCB2Py50cmltKCldKVxuICAgIEFXU19SRUdJT04gPz89IHNlY3Rpb25MaW5lcy5maW5kKChba10pID0+IGsgPT09ICdyZWdpb24nKT8uWzFdXG4gICAgQVdTX0FDQ0VTU19LRVlfSUQgPSBzZWN0aW9uTGluZXMuZmluZCgoW2tdKSA9PiBrID09PSAnYXdzX2FjY2Vzc19rZXlfaWQnKT8uWzFdXG4gICAgQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZID0gc2VjdGlvbkxpbmVzLmZpbmQoKFtrXSkgPT4gayA9PT0gJ2F3c19zZWNyZXRfYWNjZXNzX2tleScpPy5bMV1cbiAgICBBV1NfU0VTU0lPTl9UT0tFTiA9IHNlY3Rpb25MaW5lcy5maW5kKChba10pID0+IGsgPT09ICdhd3Nfc2Vzc2lvbl90b2tlbicpPy5bMV1cbiAgICBpZiAoIUFXU19SRUdJT04gfHwgIUFXU19BQ0NFU1NfS0VZX0lEIHx8ICFBV1NfU0VDUkVUX0FDQ0VTU19LRVkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbmNvbXBsZXRlIEFXUyBjcmVkZW50aWFscyBmaWxlLicpXG4gICAgfVxuICAgIHJldHVybiB7IEFXU19SRUdJT04sIEFXU19BQ0NFU1NfS0VZX0lELCBBV1NfU0VDUkVUX0FDQ0VTU19LRVksIEFXU19TRVNTSU9OX1RPS0VOIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGF3c1JlcXVlc3QoXG4gICAgZW52OiBMb2NhbEVudixcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICBzZXJ2aWNlOiBzdHJpbmcsXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIGJvZHk/OiB1bmtub3duLFxuKSB7XG4gICAgcmV0dXJuIGF3c1N0cmluZ1JlcXVlc3QoXG4gICAgICAgIGVudixcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICBzZXJ2aWNlLFxuICAgICAgICBwYXRoLFxuICAgICAgICBib2R5ID8gSlNPTi5zdHJpbmdpZnkoYm9keSkgOiAnJyxcbiAgICAgICAgJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgIClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGF3c0Zvcm1SZXF1ZXN0KFxuICAgIGVudjogTG9jYWxFbnYsXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgc2VydmljZTogc3RyaW5nLFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBib2R5OiBVUkxTZWFyY2hQYXJhbXMsXG4pIHtcbiAgICByZXR1cm4gYXdzU3RyaW5nUmVxdWVzdChcbiAgICAgICAgZW52LFxuICAgICAgICBtZXRob2QsXG4gICAgICAgIHNlcnZpY2UsXG4gICAgICAgIHBhdGgsXG4gICAgICAgIGJvZHkudG9TdHJpbmcoKSxcbiAgICAgICAgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcsXG4gICAgKVxufVxuXG5hc3luYyBmdW5jdGlvbiBhd3NTdHJpbmdSZXF1ZXN0KFxuICAgIGVudjogTG9jYWxFbnYsXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgc2VydmljZTogc3RyaW5nLFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBib2R5OiBzdHJpbmcsXG4gICAgY29udGVudFR5cGU6IHN0cmluZyxcbikge1xuICAgIGNvbnN0IHNpZ25lciA9IG5ldyBTaWduYXR1cmVWNCh7XG4gICAgICAgIHNlcnZpY2UsXG4gICAgICAgIHJlZ2lvbjogc2VydmljZSA9PT0gJ2lhbScgPyAndXMtZWFzdC0xJyA6IGVudi5BV1NfUkVHSU9OLFxuICAgICAgICBzaGEyNTY6IEF3c0hhc2gsXG4gICAgICAgIGNyZWRlbnRpYWxzOiB7XG4gICAgICAgICAgICBhY2Nlc3NLZXlJZDogZW52LkFXU19BQ0NFU1NfS0VZX0lELFxuICAgICAgICAgICAgc2VjcmV0QWNjZXNzS2V5OiBlbnYuQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZLFxuICAgICAgICAgICAgc2Vzc2lvblRva2VuOiBlbnYuQVdTX1NFU1NJT05fVE9LRU4sXG4gICAgICAgIH0sXG4gICAgfSlcbiAgICBjb25zdCB1cmkgPSBuZXcgVVJMKGBodHRwczovLyR7c3ViZG9tYWluKHNlcnZpY2UsIGVudi5BV1NfUkVHSU9OKX0uYW1hem9uYXdzLmNvbSR7cGF0aH1gKVxuICAgIGNvbnN0IHF1ZXJ5OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge31cbiAgICB1cmkuc2VhcmNoUGFyYW1zLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgcXVlcnlba2V5XSA9IHZhbHVlXG4gICAgfSlcbiAgICBjb25zdCB7IGhlYWRlcnMgfSA9IGF3YWl0IHNpZ25lci5zaWduKHtcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICBwcm90b2NvbDogJ2h0dHBzOicsXG4gICAgICAgIGhvc3RuYW1lOiB1cmkuaG9zdG5hbWUsXG4gICAgICAgIHBhdGg6IHVyaS5wYXRobmFtZSxcbiAgICAgICAgcXVlcnksXG4gICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgIGhvc3Q6IHVyaS5ob3N0bmFtZSxcbiAgICAgICAgICAgICdjb250ZW50LXR5cGUnOiBjb250ZW50VHlwZSxcbiAgICAgICAgICAgIGFjY2VwdDogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICB9LFxuICAgICAgICBib2R5LFxuICAgIH0pXG4gICAgcmV0dXJuIGF3YWl0IGZldGNoKHVyaS50b1N0cmluZygpLCB7XG4gICAgICAgIG1ldGhvZCxcbiAgICAgICAgaGVhZGVycyxcbiAgICAgICAgYm9keTogYm9keSB8fCB1bmRlZmluZWQsXG4gICAgfSlcbn1cblxuZnVuY3Rpb24gc3ViZG9tYWluKHNlcnZpY2U6IHN0cmluZywgcmVnaW9uOiBzdHJpbmcpIHtcbiAgICBzd2l0Y2ggKHNlcnZpY2UpIHtcbiAgICAgICAgY2FzZSAnaWFtJzpcbiAgICAgICAgICAgIHJldHVybiAnaWFtJ1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIGAke3NlcnZpY2V9LiR7cmVnaW9ufWBcbiAgICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXRyeTxUIGV4dGVuZHMgeyB1cmw6IHN0cmluZzsgdGV4dDogKCkgPT4gUHJvbWlzZTxzdHJpbmc+IH0+KFxuICAgIHJlcXVlc3Q6ICgpID0+IFByb21pc2U8VD4sXG4gICAgd2hlbjogKHJlc3BvbnNlOiBUKSA9PiBudW1iZXIgfCB1bmRlZmluZWQsXG4pIHtcbiAgICBmb3IgKGxldCBhdHRlbXB0cyA9IDA7IDsgKythdHRlbXB0cykge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3QoKVxuICAgICAgICBjb25zdCBtYXhSZXRyaWVzID0gd2hlbihyZXNwb25zZSlcbiAgICAgICAgaWYgKG1heFJldHJpZXMgPT09IHVuZGVmaW5lZCB8fCBtYXhSZXRyaWVzIDw9IGF0dGVtcHRzKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2VcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZyhgcmV0cnlpbmcgIyR7YXR0ZW1wdHMgKyAxfS4uLiAoJHtyZXNwb25zZS51cmx9IC0+ICR7YXdhaXQgcmVzcG9uc2UudGV4dCgpfSlgKVxuICAgICAgICBhd2FpdCBzZXRUaW1lb3V0KDUwMClcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc05vdEZvdW5kKGU6IHVua25vd24pIHtcbiAgICByZXR1cm4gdGhyb3duSGFzU3RhdHVzKGUsIDQwNClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ29uZmxpY3QoZTogdW5rbm93bikge1xuICAgIHJldHVybiB0aHJvd25IYXNTdGF0dXMoZSwgNDA5KVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmV0cnlDb25mbGljdDxUPihmbjogKCkgPT4gUHJvbWlzZTxUPik6IFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGRlYWRsaW5lID0gbmV3IERhdGUoKVxuICAgIGRlYWRsaW5lLnNldFVUQ1NlY29uZHMoZGVhZGxpbmUuZ2V0VVRDU2Vjb25kcygpICsgMzApXG4gICAgZm9yICg7Oykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGZuKClcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgaWYgKCFpc0NvbmZsaWN0KGUpIHx8IG5ldyBEYXRlKCkgPiBkZWFkbGluZSkge1xuICAgICAgICAgICAgICAgIHRocm93IGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IHNldFRpbWVvdXQoKChNYXRoLnJhbmRvbSgpICsgMC41KSAqIDUwMCkgLyAyKVxuICAgICAgICB9XG4gICAgfVxufVxuXG50eXBlIFNvdXJjZURhdGEgPSBzdHJpbmcgfCBBcnJheUJ1ZmZlciB8IEFycmF5QnVmZmVyVmlld1xuXG5jbGFzcyBBd3NIYXNoIHtcbiAgICByZWFkb25seSAjc2VjcmV0PzogU291cmNlRGF0YVxuICAgICNoYXNoOiBSZXR1cm5UeXBlPHR5cGVvZiBjcmVhdGVIYXNoPiB8IFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZUhtYWM+XG5cbiAgICBjb25zdHJ1Y3RvcihzZWNyZXQ/OiBTb3VyY2VEYXRhKSB7XG4gICAgICAgIHRoaXMuI3NlY3JldCA9IHNlY3JldFxuICAgICAgICB0aGlzLiNoYXNoID0gbWFrZUhhc2godGhpcy4jc2VjcmV0KVxuICAgIH1cblxuICAgIGRpZ2VzdCgpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLiNoYXNoLmRpZ2VzdCgpKVxuICAgIH1cblxuICAgIHJlc2V0KCkge1xuICAgICAgICB0aGlzLiNoYXNoID0gbWFrZUhhc2godGhpcy4jc2VjcmV0KVxuICAgIH1cblxuICAgIHVwZGF0ZShjaHVuazogVWludDhBcnJheSkge1xuICAgICAgICB0aGlzLiNoYXNoLnVwZGF0ZShuZXcgVWludDhBcnJheShCdWZmZXIuZnJvbShjaHVuaykpKVxuICAgIH1cbn1cblxuZnVuY3Rpb24gbWFrZUhhc2goc2VjcmV0PzogU291cmNlRGF0YSkge1xuICAgIHJldHVybiBzZWNyZXQgPyBjcmVhdGVIbWFjKCdzaGEyNTYnLCBjYXN0U291cmNlRGF0YShzZWNyZXQpKSA6IGNyZWF0ZUhhc2goJ3NoYTI1NicpXG59XG5cbmZ1bmN0aW9uIGNhc3RTb3VyY2VEYXRhKGRhdGE6IFNvdXJjZURhdGEpIHtcbiAgICBpZiAoQnVmZmVyLmlzQnVmZmVyKGRhdGEpKSB7XG4gICAgICAgIHJldHVybiBkYXRhXG4gICAgfVxuICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEpXG4gICAgfVxuICAgIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoZGF0YSkpIHtcbiAgICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQsIGRhdGEuYnl0ZUxlbmd0aClcbiAgICB9XG4gICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGRhdGEpXG59XG4iXX0=