UNPKG

@riddance/env

Version:

189 lines 26.6 kB
import { spawn } from 'node:child_process'; import { readFile, rm, stat, writeFile } from 'node:fs/promises'; import { dirname, extname, join, resolve } from 'node:path'; import { formatted } from '../lib/formatter.js'; import { lint, makeCache } from '../lib/linter.js'; import { install } from '../lib/npm.js'; import { spelling } from '../lib/spelling.js'; import { isTest, test, writeTestConfig } from '../lib/tester.js'; export function getSource(input) { return input.filter(f => extname(f) === '.ts' && !f.endsWith('.d.ts') && !dirname(f).includes('node_modules')); } export async function load(path) { return new Changes(path, await loadMyVersion(path), await loadTimestamps(path)); } export class Changes { #path; #myVersion; #timestamps; #lintCache; constructor(path, myVersion, timestamps) { this.#path = path; this.#myVersion = myVersion; this.#timestamps = timestamps; this.#lintCache = makeCache(path); } async preCompile(reporter, path) { if (await this.shouldInstall()) { await install(reporter, path); this.#timestamps.stages = {}; await this.stageComplete('install'); await this.#restartIfUpdated(reporter); await writeTestConfig(path); } } async postCompile(reporter, path, inputFiles, compileResult, abort) { const source = getSource(inputFiles); const result = (await Promise.all([ compileResult, this.#ifChanged('formatting', source, s => formatted(reporter, path, s, abort)), this.#ifChanged('spelling', source, s => spelling(reporter, path, s, abort)), this.#ifChanged('linting', source, s => lint(reporter, path, s, this.#lintCache)), this.#ifChanged('tests', source, async (s) => { const outputFiles = await compileResult; if (abort.aborted) { return false; } if (!outputFiles) { return false; } const tests = outputFiles.filter(f => isTest(f) && !f.endsWith('.d.ts')); return await test(reporter, path, tests, s, abort); }), ])).every(r => !!r); await this.#setOutputs(await compileResult); await this.#saveTimestamps(); return result; } async shouldInstall() { const oldestStage = Object.values(this.#timestamps.stages) .map(d => new Date(d).getTime()) .sort() .at(0) ?? -1; const latestPackage = (await Promise.all([ 'package.json', 'package-lock.json', 'example/package.json', 'example/package-lock.json', ].map(async (f) => { try { return await stat(resolve(this.#path, f)); } catch (e) { if (isFileNotFound(e)) { return { ctimeMs: 0 }; } throw e; } }))) .map(s => s.ctimeMs) .sort() .at(-1) ?? 0; return oldestStage < latestPackage; } async #restartIfUpdated(reporter) { if (this.#myVersion === (await loadMyVersion(this.#path))) { return; } reporter.status('Restarting...'); const [cmd, ...argv] = process.argv; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const proc = spawn(cmd, argv, { stdio: [process.stdin, process.stdout, process.stderr, 'pipe'], }); // eslint-disable-next-line promise/param-names return new Promise(exit => { proc.addListener('exit', exit); }); } async stageComplete(stage) { this.#timestamps.stages[stage] = new Date().toISOString(); await this.#saveTimestamps(); } async clearStages() { this.#timestamps.stages = {}; this.#lintCache = makeCache(this.#path); await this.#saveTimestamps(); } async #ifChanged(stage, source, fn) { const { stages } = this.#timestamps; if (stages[stage]) { const lastSuccess = new Date(this.#timestamps.stages[stage] ?? 0).getTime(); const stats = await Promise.all(source.map(async (s) => { try { return await stat(s); } catch (e) { if (isFileNotFound(e)) { return { mtimeMs: 0 }; } throw e; } })); source = source .map((s, ix) => ((stats[ix]?.mtimeMs ?? Number.MAX_VALUE) > lastSuccess ? s : '')) .filter(s => !!s); } if (await fn(source)) { stages[stage] = new Date().toISOString(); return true; } return false; } async #setOutputs(outputs) { for (const old of this.#timestamps.outputs) { if (!outputs?.includes(old)) { try { await rm(old); } catch (e) { if (isFileNotFound(e)) { continue; } throw e; } } } this.#timestamps.outputs = outputs ?? []; } async #saveTimestamps() { await writeFile(join(this.#path, '.timestamps.json'), JSON.stringify(this.#timestamps, undefined, ' ')); } } async function loadTimestamps(path) { try { return JSON.parse(await readFile(join(path, '.timestamps.json'), 'utf-8')); } catch (e) { if (isFileNotFound(e)) { return { outputs: [], stages: {}, }; } throw e; } } async function loadMyVersion(path, reporter) { try { const { dependencies = {}, devDependencies = {} } = JSON.parse(await readFile(join(path, 'package.json'), 'utf-8')); const myVersion = devDependencies['@riddance/env']; if (!myVersion) { if (dependencies['@riddance/env']) { reporter?.error('@riddance/env should be added to package.json as a devDependency, not a dependency.'); } return; } return myVersion; } catch (e) { if (isFileNotFound(e)) { return; } throw e; } } function isFileNotFound(e) { return e.code === 'ENOENT'; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhbmdlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNoYW5nZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQzFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQTtBQUNoRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQzNELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ2xELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDdkMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFBO0FBQzdDLE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBR2hFLE1BQU0sVUFBVSxTQUFTLENBQUMsS0FBZTtJQUNyQyxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQ2YsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLENBQzVGLENBQUE7QUFDTCxDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxJQUFJLENBQUMsSUFBWTtJQUNuQyxPQUFPLElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLGFBQWEsQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFBO0FBQ25G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LENBQUM7WUFDcEIsT0FBTztnQkFDSCxPQUFPLEVBQUUsRUFBRTtnQkFDWCxNQUFNLEVBQUUsRUFBRTthQUNiLENBQUE7UUFDTCxDQUFDO1FBQ0QsTUFBTSxDQUFDLENBQUE7SUFDWCxDQUFDO0FBQ0wsQ0FBQztBQUVELEtBQUssVUFBVSxhQUFhLENBQUMsSUFBWSxFQUFFLFFBQW1CO0lBQzFELElBQUksQ0FBQztRQUNELE1BQU0sRUFBRSxZQUFZLEdBQUcsRUFBRSxFQUFFLGVBQWUsR0FBRyxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUMxRCxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLGNBQWMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUl0RCxDQUFBO1FBQ0QsTUFBTSxTQUFTLEdBQUcsZUFBZSxDQUFDLGVBQWUsQ0FBQyxDQUFBO1FBQ2xELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNiLElBQUksWUFBWSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hDLFFBQVEsRUFBRSxLQUFLLENBQ1gscUZBQXFGLENBQ3hGLENBQUE7WUFDTCxDQUFDO1lBQ0QsT0FBTTtRQUNWLENBQUM7UUFDRCxPQUFPLFNBQVMsQ0FBQTtJQUNwQixDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNULElBQUksY0FBYyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDcEIsT0FBTTtRQUNWLENBQUM7UUFDRCxNQUFNLENBQUMsQ0FBQTtJQUNYLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxjQUFjLENBQUMsQ0FBVTtJQUM5QixPQUFRLENBQXVCLENBQUMsSUFBSSxLQUFLLFFBQVEsQ0FBQTtBQUNyRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgc3Bhd24gfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnXG5pbXBvcnQgeyByZWFkRmlsZSwgcm0sIHN0YXQsIHdyaXRlRmlsZSB9IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnXG5pbXBvcnQgeyBkaXJuYW1lLCBleHRuYW1lLCBqb2luLCByZXNvbHZlIH0gZnJvbSAnbm9kZTpwYXRoJ1xuaW1wb3J0IHsgZm9ybWF0dGVkIH0gZnJvbSAnLi4vbGliL2Zvcm1hdHRlci5qcydcbmltcG9ydCB7IGxpbnQsIG1ha2VDYWNoZSB9IGZyb20gJy4uL2xpYi9saW50ZXIuanMnXG5pbXBvcnQgeyBpbnN0YWxsIH0gZnJvbSAnLi4vbGliL25wbS5qcydcbmltcG9ydCB7IHNwZWxsaW5nIH0gZnJvbSAnLi4vbGliL3NwZWxsaW5nLmpzJ1xuaW1wb3J0IHsgaXNUZXN0LCB0ZXN0LCB3cml0ZVRlc3RDb25maWcgfSBmcm9tICcuLi9saWIvdGVzdGVyLmpzJ1xuaW1wb3J0IHsgUmVwb3J0ZXIgfSBmcm9tICcuL3JlcG9ydGVyLmpzJ1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U291cmNlKGlucHV0OiBzdHJpbmdbXSkge1xuICAgIHJldHVybiBpbnB1dC5maWx0ZXIoXG4gICAgICAgIGYgPT4gZXh0bmFtZShmKSA9PT0gJy50cycgJiYgIWYuZW5kc1dpdGgoJy5kLnRzJykgJiYgIWRpcm5hbWUoZikuaW5jbHVkZXMoJ25vZGVfbW9kdWxlcycpLFxuICAgIClcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxvYWQocGF0aDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIG5ldyBDaGFuZ2VzKHBhdGgsIGF3YWl0IGxvYWRNeVZlcnNpb24ocGF0aCksIGF3YWl0IGxvYWRUaW1lc3RhbXBzKHBhdGgpKVxufVxuXG5leHBvcnQgY2xhc3MgQ2hhbmdlcyB7XG4gICAgcmVhZG9ubHkgI3BhdGhcbiAgICByZWFkb25seSAjbXlWZXJzaW9uOiBzdHJpbmcgfCB1bmRlZmluZWRcbiAgICByZWFkb25seSAjdGltZXN0YW1wczogVGltZXN0YW1wc1xuICAgICNsaW50Q2FjaGVcblxuICAgIGNvbnN0cnVjdG9yKHBhdGg6IHN0cmluZywgbXlWZXJzaW9uOiBzdHJpbmcgfCB1bmRlZmluZWQsIHRpbWVzdGFtcHM6IFRpbWVzdGFtcHMpIHtcbiAgICAgICAgdGhpcy4jcGF0aCA9IHBhdGhcbiAgICAgICAgdGhpcy4jbXlWZXJzaW9uID0gbXlWZXJzaW9uXG4gICAgICAgIHRoaXMuI3RpbWVzdGFtcHMgPSB0aW1lc3RhbXBzXG4gICAgICAgIHRoaXMuI2xpbnRDYWNoZSA9IG1ha2VDYWNoZShwYXRoKVxuICAgIH1cblxuICAgIGFzeW5jIHByZUNvbXBpbGUocmVwb3J0ZXI6IFJlcG9ydGVyLCBwYXRoOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKGF3YWl0IHRoaXMuc2hvdWxkSW5zdGFsbCgpKSB7XG4gICAgICAgICAgICBhd2FpdCBpbnN0YWxsKHJlcG9ydGVyLCBwYXRoKVxuICAgICAgICAgICAgdGhpcy4jdGltZXN0YW1wcy5zdGFnZXMgPSB7fVxuICAgICAgICAgICAgYXdhaXQgdGhpcy5zdGFnZUNvbXBsZXRlKCdpbnN0YWxsJylcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuI3Jlc3RhcnRJZlVwZGF0ZWQocmVwb3J0ZXIpXG4gICAgICAgICAgICBhd2FpdCB3cml0ZVRlc3RDb25maWcocGF0aClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGFzeW5jIHBvc3RDb21waWxlKFxuICAgICAgICByZXBvcnRlcjogUmVwb3J0ZXIsXG4gICAgICAgIHBhdGg6IHN0cmluZyxcbiAgICAgICAgaW5wdXRGaWxlczogc3RyaW5nW10sXG4gICAgICAgIGNvbXBpbGVSZXN1bHQ6IFByb21pc2U8c3RyaW5nW10gfCB1bmRlZmluZWQ+LFxuICAgICAgICBhYm9ydDogQWJvcnRTaWduYWwsXG4gICAgKSB7XG4gICAgICAgIGNvbnN0IHNvdXJjZSA9IGdldFNvdXJjZShpbnB1dEZpbGVzKVxuICAgICAgICBjb25zdCByZXN1bHQgPSAoXG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgY29tcGlsZVJlc3VsdCxcbiAgICAgICAgICAgICAgICB0aGlzLiNpZkNoYW5nZWQoJ2Zvcm1hdHRpbmcnLCBzb3VyY2UsIHMgPT4gZm9ybWF0dGVkKHJlcG9ydGVyLCBwYXRoLCBzLCBhYm9ydCkpLFxuICAgICAgICAgICAgICAgIHRoaXMuI2lmQ2hhbmdlZCgnc3BlbGxpbmcnLCBzb3VyY2UsIHMgPT4gc3BlbGxpbmcocmVwb3J0ZXIsIHBhdGgsIHMsIGFib3J0KSksXG4gICAgICAgICAgICAgICAgdGhpcy4jaWZDaGFuZ2VkKCdsaW50aW5nJywgc291cmNlLCBzID0+IGxpbnQocmVwb3J0ZXIsIHBhdGgsIHMsIHRoaXMuI2xpbnRDYWNoZSkpLFxuICAgICAgICAgICAgICAgIHRoaXMuI2lmQ2hhbmdlZCgndGVzdHMnLCBzb3VyY2UsIGFzeW5jIHMgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvdXRwdXRGaWxlcyA9IGF3YWl0IGNvbXBpbGVSZXN1bHRcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFib3J0LmFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghb3V0cHV0RmlsZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRlc3RzID0gb3V0cHV0RmlsZXMuZmlsdGVyKGYgPT4gaXNUZXN0KGYpICYmICFmLmVuZHNXaXRoKCcuZC50cycpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGVzdChyZXBvcnRlciwgcGF0aCwgdGVzdHMsIHMsIGFib3J0KVxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgXSlcbiAgICAgICAgKS5ldmVyeShyID0+ICEhcilcbiAgICAgICAgYXdhaXQgdGhpcy4jc2V0T3V0cHV0cyhhd2FpdCBjb21waWxlUmVzdWx0KVxuICAgICAgICBhd2FpdCB0aGlzLiNzYXZlVGltZXN0YW1wcygpXG4gICAgICAgIHJldHVybiByZXN1bHRcbiAgICB9XG5cbiAgICBhc3luYyBzaG91bGRJbnN0YWxsKCkge1xuICAgICAgICBjb25zdCBvbGRlc3RTdGFnZSA9XG4gICAgICAgICAgICBPYmplY3QudmFsdWVzKHRoaXMuI3RpbWVzdGFtcHMuc3RhZ2VzKVxuICAgICAgICAgICAgICAgIC5tYXAoZCA9PiBuZXcgRGF0ZShkKS5nZXRUaW1lKCkpXG4gICAgICAgICAgICAgICAgLnNvcnQoKVxuICAgICAgICAgICAgICAgIC5hdCgwKSA/PyAtMVxuICAgICAgICBjb25zdCBsYXRlc3RQYWNrYWdlID1cbiAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgICAgICAgICAgJ3BhY2thZ2UuanNvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICAncGFja2FnZS1sb2NrLmpzb24nLFxuICAgICAgICAgICAgICAgICAgICAgICAgJ2V4YW1wbGUvcGFja2FnZS5qc29uJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICdleGFtcGxlL3BhY2thZ2UtbG9jay5qc29uJyxcbiAgICAgICAgICAgICAgICAgICAgXS5tYXAoYXN5bmMgZiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhd2FpdCBzdGF0KHJlc29sdmUodGhpcy4jcGF0aCwgZikpXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRmlsZU5vdEZvdW5kKGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGN0aW1lTXM6IDAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAubWFwKHMgPT4gcy5jdGltZU1zKVxuICAgICAgICAgICAgICAgIC5zb3J0KClcbiAgICAgICAgICAgICAgICAuYXQoLTEpID8/IDBcbiAgICAgICAgcmV0dXJuIG9sZGVzdFN0YWdlIDwgbGF0ZXN0UGFja2FnZVxuICAgIH1cblxuICAgIGFzeW5jICNyZXN0YXJ0SWZVcGRhdGVkKHJlcG9ydGVyOiBSZXBvcnRlcikge1xuICAgICAgICBpZiAodGhpcy4jbXlWZXJzaW9uID09PSAoYXdhaXQgbG9hZE15VmVyc2lvbih0aGlzLiNwYXRoKSkpIHtcbiAgICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICAgIHJlcG9ydGVyLnN0YXR1cygnUmVzdGFydGluZy4uLicpXG4gICAgICAgIGNvbnN0IFtjbWQsIC4uLmFyZ3ZdID0gcHJvY2Vzcy5hcmd2XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICAgIGNvbnN0IHByb2MgPSBzcGF3bihjbWQhLCBhcmd2LCB7XG4gICAgICAgICAgICBzdGRpbzogW3Byb2Nlc3Muc3RkaW4sIHByb2Nlc3Muc3Rkb3V0LCBwcm9jZXNzLnN0ZGVyciwgJ3BpcGUnXSxcbiAgICAgICAgfSlcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHByb21pc2UvcGFyYW0tbmFtZXNcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGV4aXQgPT4ge1xuICAgICAgICAgICAgcHJvYy5hZGRMaXN0ZW5lcignZXhpdCcsIGV4aXQpXG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgYXN5bmMgc3RhZ2VDb21wbGV0ZShzdGFnZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuI3RpbWVzdGFtcHMuc3RhZ2VzW3N0YWdlXSA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKVxuICAgICAgICBhd2FpdCB0aGlzLiNzYXZlVGltZXN0YW1wcygpXG4gICAgfVxuICAgIGFzeW5jIGNsZWFyU3RhZ2VzKCkge1xuICAgICAgICB0aGlzLiN0aW1lc3RhbXBzLnN0YWdlcyA9IHt9XG4gICAgICAgIHRoaXMuI2xpbnRDYWNoZSA9IG1ha2VDYWNoZSh0aGlzLiNwYXRoKVxuICAgICAgICBhd2FpdCB0aGlzLiNzYXZlVGltZXN0YW1wcygpXG4gICAgfVxuXG4gICAgYXN5bmMgI2lmQ2hhbmdlZChzdGFnZTogc3RyaW5nLCBzb3VyY2U6IHN0cmluZ1tdLCBmbjogKHNyYzogc3RyaW5nW10pID0+IFByb21pc2U8Ym9vbGVhbj4pIHtcbiAgICAgICAgY29uc3QgeyBzdGFnZXMgfSA9IHRoaXMuI3RpbWVzdGFtcHNcbiAgICAgICAgaWYgKHN0YWdlc1tzdGFnZV0pIHtcbiAgICAgICAgICAgIGNvbnN0IGxhc3RTdWNjZXNzID0gbmV3IERhdGUodGhpcy4jdGltZXN0YW1wcy5zdGFnZXNbc3RhZ2VdID8/IDApLmdldFRpbWUoKVxuICAgICAgICAgICAgY29uc3Qgc3RhdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgICAgICAgICBzb3VyY2UubWFwKGFzeW5jIHMgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHN0YXQocylcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzRmlsZU5vdEZvdW5kKGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgbXRpbWVNczogMCB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIHNvdXJjZSA9IHNvdXJjZVxuICAgICAgICAgICAgICAgIC5tYXAoKHMsIGl4KSA9PiAoKHN0YXRzW2l4XT8ubXRpbWVNcyA/PyBOdW1iZXIuTUFYX1ZBTFVFKSA+IGxhc3RTdWNjZXNzID8gcyA6ICcnKSlcbiAgICAgICAgICAgICAgICAuZmlsdGVyKHMgPT4gISFzKVxuICAgICAgICB9XG4gICAgICAgIGlmIChhd2FpdCBmbihzb3VyY2UpKSB7XG4gICAgICAgICAgICBzdGFnZXNbc3RhZ2VdID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIGFzeW5jICNzZXRPdXRwdXRzKG91dHB1dHM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkKSB7XG4gICAgICAgIGZvciAoY29uc3Qgb2xkIG9mIHRoaXMuI3RpbWVzdGFtcHMub3V0cHV0cykge1xuICAgICAgICAgICAgaWYgKCFvdXRwdXRzPy5pbmNsdWRlcyhvbGQpKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgcm0ob2xkKVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzRmlsZU5vdEZvdW5kKGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRocm93IGVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy4jdGltZXN0YW1wcy5vdXRwdXRzID0gb3V0cHV0cyA/PyBbXVxuICAgIH1cblxuICAgIGFzeW5jICNzYXZlVGltZXN0YW1wcygpIHtcbiAgICAgICAgYXdhaXQgd3JpdGVGaWxlKFxuICAgICAgICAgICAgam9pbih0aGlzLiNwYXRoLCAnLnRpbWVzdGFtcHMuanNvbicpLFxuICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkodGhpcy4jdGltZXN0YW1wcywgdW5kZWZpbmVkLCAnICAnKSxcbiAgICAgICAgKVxuICAgIH1cbn1cblxudHlwZSBUaW1lc3RhbXBzID0ge1xuICAgIG91dHB1dHM6IHN0cmluZ1tdXG4gICAgc3RhZ2VzOiB7IFtzdGFnZTogc3RyaW5nXTogc3RyaW5nIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZFRpbWVzdGFtcHMocGF0aDogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoYXdhaXQgcmVhZEZpbGUoam9pbihwYXRoLCAnLnRpbWVzdGFtcHMuanNvbicpLCAndXRmLTgnKSkgYXMgVGltZXN0YW1wc1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGlzRmlsZU5vdEZvdW5kKGUpKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG91dHB1dHM6IFtdLFxuICAgICAgICAgICAgICAgIHN0YWdlczoge30sXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZVxuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZE15VmVyc2lvbihwYXRoOiBzdHJpbmcsIHJlcG9ydGVyPzogUmVwb3J0ZXIpIHtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCB7IGRlcGVuZGVuY2llcyA9IHt9LCBkZXZEZXBlbmRlbmNpZXMgPSB7fSB9ID0gSlNPTi5wYXJzZShcbiAgICAgICAgICAgIGF3YWl0IHJlYWRGaWxlKGpvaW4ocGF0aCwgJ3BhY2thZ2UuanNvbicpLCAndXRmLTgnKSxcbiAgICAgICAgKSBhcyB7XG4gICAgICAgICAgICBkZXBlbmRlbmNpZXM/OiB7IFtwOiBzdHJpbmddOiBzdHJpbmcgfVxuICAgICAgICAgICAgZGV2RGVwZW5kZW5jaWVzPzogeyBbcDogc3RyaW5nXTogc3RyaW5nIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBteVZlcnNpb24gPSBkZXZEZXBlbmRlbmNpZXNbJ0ByaWRkYW5jZS9lbnYnXVxuICAgICAgICBpZiAoIW15VmVyc2lvbikge1xuICAgICAgICAgICAgaWYgKGRlcGVuZGVuY2llc1snQHJpZGRhbmNlL2VudiddKSB7XG4gICAgICAgICAgICAgICAgcmVwb3J0ZXI/LmVycm9yKFxuICAgICAgICAgICAgICAgICAgICAnQHJpZGRhbmNlL2VudiBzaG91bGQgYmUgYWRkZWQgdG8gcGFja2FnZS5qc29uIGFzIGEgZGV2RGVwZW5kZW5jeSwgbm90IGEgZGVwZW5kZW5jeS4nLFxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBteVZlcnNpb25cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChpc0ZpbGVOb3RGb3VuZChlKSkge1xuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZVxuICAgIH1cbn1cblxuZnVuY3Rpb24gaXNGaWxlTm90Rm91bmQoZTogdW5rbm93bikge1xuICAgIHJldHVybiAoZSBhcyB7IGNvZGU6IHVua25vd24gfSkuY29kZSA9PT0gJ0VOT0VOVCdcbn1cbiJdfQ==