@riddance/env
Version:
Too much code slows you down, creates risks, increases maintainability burdens, confuses AI. So let's commit less of it.
138 lines • 21.6 kB
JavaScript
import { spawn } from 'node:child_process';
import { access, constants, writeFile } from 'node:fs/promises';
import { findPackageJSON } from 'node:module';
import { basename, dirname, join, relative } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
const exampleTestDir = join('example', 'test');
export function isTest(file) {
const dirName = dirname(file);
return ((dirName === 'test' || dirName === exampleTestDir) &&
(file.endsWith('.js') || (file.endsWith('.ts') && !file.endsWith('.d.ts'))));
}
export function isTestData(file) {
return (file === 'test/env.txt' ||
file === 'example/test/env.txt' ||
file.startsWith('test/data/') ||
file.startsWith('example/test/data/'));
}
export async function test(reporter, path, testFiles, changed, signal) {
if (changed.length === 0) {
return true;
}
if (process.env.RIDDANCE_TESTS === 'skip') {
reporter.error('⚠️ Tests skipped ⚠️');
return true;
}
const runOnlyChangedTests = changed.every(isTest);
if (runOnlyChangedTests) {
testFiles = testFiles.filter(file => changed.includes(join(dirname(file), basename(file, '.js') + '.ts')));
}
const success = (await testDirectory(path, 'test', testFiles, signal)) &&
(await testSubProjectDirectory(path, exampleTestDir, testFiles, signal));
return success;
}
async function testDirectory(path, directory, testFiles, signal) {
testFiles = testFiles.filter(file => dirname(file) === directory);
if (testFiles.length === 0) {
return true;
}
return await runTests(path, directory, testFiles, signal);
}
async function testSubProjectDirectory(path, directory, testFiles, signal) {
testFiles = testFiles.filter(file => dirname(file) === directory);
if (testFiles.length === 0) {
return true;
}
return await runTests(path, directory, testFiles, signal);
}
async function runTests(path, directory, testFiles, signal) {
const cwd = join(path, directory, '..');
const mochaPackageJsonPath = findPackageJSON('mocha', `${pathToFileURL(cwd).href}/`);
const exitCode = await spawnNode([
relative(cwd, join(mochaPackageJsonPath
? dirname(mochaPackageJsonPath)
: join(path, 'node_modules'), 'bin/mocha.js')),
'--config',
'.mocharc.json',
...testFiles.map(f => relative(cwd, join(path, f))),
], {
detached: true,
cwd,
env: {
PROJECT_DIRECTORY: process.cwd(),
...process.env,
RIDDANCE_SUB_PROJECT_URL: pathToFileURL(cwd).href,
},
}, signal);
return exitCode === 0;
}
export async function writeTestConfig(path, dependencies, resolver) {
const [sourceMapModule, hooks] = await Promise.all([sourceMapSupport(), getHooks(dependencies)]);
await writeFile(join(path, '.mocharc.json'), JSON.stringify({
parallel: true,
'node-option': ['trace-warnings', 'unhandled-rejections=strict'],
require: [sourceMapModule, ...(resolver ? hooks.map(resolver) : hooks)],
}, undefined, ' '), 'utf-8');
const subProjectDirectory = join(path, 'example');
try {
await access(subProjectDirectory, constants.W_OK);
}
catch {
return;
}
const script = relative(subProjectDirectory, fileURLToPath(import.meta.resolve('./sub-project-tests.js')));
await spawnNode(['--experimental-import-meta-resolve', script], { cwd: subProjectDirectory }, new AbortController().signal);
}
async function sourceMapSupport() {
try {
await access('./lib/source-map-support.ts', constants.R_OK);
return './lib/source-map-support.js';
}
catch {
return '@riddance/env/lib/source-map-support.js';
}
}
async function getHooks(dependencies) {
return Object.entries((await dependencies).dependencies)
.map(([dependency, { packageJson }]) => {
const { mock } = packageJson;
if (typeof mock !== 'string') {
return undefined;
}
return `${dependency}/${mock}`;
})
.filter(h => h !== undefined);
}
function spawnNode(args, options, signal) {
return new Promise((resolve, reject) => {
const proc = spawn('node', args, {
...options,
stdio: [process.stdin, process.stdout, process.stderr, 'pipe'],
});
const killer = () => {
const { pid } = proc;
if (pid) {
process.kill(-pid, 'SIGTERM');
}
else {
proc.kill('SIGTERM');
}
};
signal.addEventListener('abort', killer);
const onError = (error) => {
reject(error);
proc.removeListener('error', onError);
proc.removeListener('exit', onExit);
signal.removeEventListener('abort', killer);
};
const onExit = (code) => {
resolve(code);
proc.removeListener('error', onError);
proc.removeListener('exit', onExit);
signal.removeEventListener('abort', killer);
};
proc.addListener('error', onError);
proc.addListener('exit', onExit);
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidGVzdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQWdCLE1BQU0sb0JBQW9CLENBQUE7QUFDeEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sa0JBQWtCLENBQUE7QUFDL0QsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUM3QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQzdELE9BQU8sRUFBRSxhQUFhLEVBQUUsYUFBYSxFQUFFLE1BQU0sVUFBVSxDQUFBO0FBR3ZELE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUE7QUFFOUMsTUFBTSxVQUFVLE1BQU0sQ0FBQyxJQUFZO0lBQy9CLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUM3QixPQUFPLENBQ0gsQ0FBQyxPQUFPLEtBQUssTUFBTSxJQUFJLE9BQU8sS0FBSyxjQUFjLENBQUM7UUFDbEQsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUM5RSxDQUFBO0FBQ0wsQ0FBQztBQUVELE1BQU0sVUFBVSxVQUFVLENBQUMsSUFBWTtJQUNuQyxPQUFPLENBQ0gsSUFBSSxLQUFLLGNBQWM7UUFDdkIsSUFBSSxLQUFLLHNCQUFzQjtRQUMvQixJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQztRQUM3QixJQUFJLENBQUMsVUFBVSxDQUFDLG9CQUFvQixDQUFDLENBQ3hDLENBQUE7QUFDTCxDQUFDO0FBRUQsTUFBTSxD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TUFBTSxHQUFHLENBQUMsSUFBbUIsRUFBRSxFQUFFO1lBQ25DLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUNiLElBQUksQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFBO1lBQ3JDLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1lBQ25DLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUE7UUFDL0MsQ0FBQyxDQUFBO1FBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDbEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFDcEMsQ0FBQyxDQUFDLENBQUE7QUFDTixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgc3Bhd24sIFNwYXduT3B0aW9ucyB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2VzcydcbmltcG9ydCB7IGFjY2VzcywgY29uc3RhbnRzLCB3cml0ZUZpbGUgfSBmcm9tICdub2RlOmZzL3Byb21pc2VzJ1xuaW1wb3J0IHsgZmluZFBhY2thZ2VKU09OIH0gZnJvbSAnbm9kZTptb2R1bGUnXG5pbXBvcnQgeyBiYXNlbmFtZSwgZGlybmFtZSwgam9pbiwgcmVsYXRpdmUgfSBmcm9tICdub2RlOnBhdGgnXG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoLCBwYXRoVG9GaWxlVVJMIH0gZnJvbSAnbm9kZTp1cmwnXG5pbXBvcnQgeyBSZXBvcnRlciB9IGZyb20gJy4vcmVwb3J0ZXIuanMnXG5cbmNvbnN0IGV4YW1wbGVUZXN0RGlyID0gam9pbignZXhhbXBsZScsICd0ZXN0JylcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVGVzdChmaWxlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBkaXJOYW1lID0gZGlybmFtZShmaWxlKVxuICAgIHJldHVybiAoXG4gICAgICAgIChkaXJOYW1lID09PSAndGVzdCcgfHwgZGlyTmFtZSA9PT0gZXhhbXBsZVRlc3REaXIpICYmXG4gICAgICAgIChmaWxlLmVuZHNXaXRoKCcuanMnKSB8fCAoZmlsZS5lbmRzV2l0aCgnLnRzJykgJiYgIWZpbGUuZW5kc1dpdGgoJy5kLnRzJykpKVxuICAgIClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVGVzdERhdGEoZmlsZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIChcbiAgICAgICAgZmlsZSA9PT0gJ3Rlc3QvZW52LnR4dCcgfHxcbiAgICAgICAgZmlsZSA9PT0gJ2V4YW1wbGUvdGVzdC9lbnYudHh0JyB8fFxuICAgICAgICBmaWxlLnN0YXJ0c1dpdGgoJ3Rlc3QvZGF0YS8nKSB8fFxuICAgICAgICBmaWxlLnN0YXJ0c1dpdGgoJ2V4YW1wbGUvdGVzdC9kYXRhLycpXG4gICAgKVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdGVzdChcbiAgICByZXBvcnRlcjogUmVwb3J0ZXIsXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIHRlc3RGaWxlczogc3RyaW5nW10sXG4gICAgY2hhbmdlZDogc3RyaW5nW10sXG4gICAgc2lnbmFsOiBBYm9ydFNpZ25hbCxcbikge1xuICAgIGlmIChjaGFuZ2VkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgICBpZiAocHJvY2Vzcy5lbnYuUklEREFOQ0VfVEVTVFMgPT09ICdza2lwJykge1xuICAgICAgICByZXBvcnRlci5lcnJvcign4pqg77iPICBUZXN0cyBza2lwcGVkIOKaoO+4jycpXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIGNvbnN0IHJ1bk9ubHlDaGFuZ2VkVGVzdHMgPSBjaGFuZ2VkLmV2ZXJ5KGlzVGVzdClcbiAgICBpZiAocnVuT25seUNoYW5nZWRUZXN0cykge1xuICAgICAgICB0ZXN0RmlsZXMgPSB0ZXN0RmlsZXMuZmlsdGVyKGZpbGUgPT5cbiAgICAgICAgICAgIGNoYW5nZWQuaW5jbHVkZXMoam9pbihkaXJuYW1lKGZpbGUpLCBiYXNlbmFtZShmaWxlLCAnLmpzJykgKyAnLnRzJykpLFxuICAgICAgICApXG4gICAgfVxuICAgIGNvbnN0IHN1Y2Nlc3MgPVxuICAgICAgICAoYXdhaXQgdGVzdERpcmVjdG9yeShwYXRoLCAndGVzdCcsIHRlc3RGaWxlcywgc2lnbmFsKSkgJiZcbiAgICAgICAgKGF3YWl0IHRlc3RTdWJQcm9qZWN0RGlyZWN0b3J5KHBhdGgsIGV4YW1wbGVUZXN0RGlyLCB0ZXN0RmlsZXMsIHNpZ25hbCkpXG5cbiAgICByZXR1cm4gc3VjY2Vzc1xufVxuXG5hc3luYyBmdW5jdGlvbiB0ZXN0RGlyZWN0b3J5KFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBkaXJlY3Rvcnk6IHN0cmluZyxcbiAgICB0ZXN0RmlsZXM6IHN0cmluZ1tdLFxuICAgIHNpZ25hbDogQWJvcnRTaWduYWwsXG4pIHtcbiAgICB0ZXN0RmlsZXMgPSB0ZXN0RmlsZXMuZmlsdGVyKGZpbGUgPT4gZGlybmFtZShmaWxlKSA9PT0gZGlyZWN0b3J5KVxuICAgIGlmICh0ZXN0RmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBhd2FpdCBydW5UZXN0cyhwYXRoLCBkaXJlY3RvcnksIHRlc3RGaWxlcywgc2lnbmFsKVxufVxuXG5hc3luYyBmdW5jdGlvbiB0ZXN0U3ViUHJvamVjdERpcmVjdG9yeShcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgZGlyZWN0b3J5OiBzdHJpbmcsXG4gICAgdGVzdEZpbGVzOiBzdHJpbmdbXSxcbiAgICBzaWduYWw6IEFib3J0U2lnbmFsLFxuKSB7XG4gICAgdGVzdEZpbGVzID0gdGVzdEZpbGVzLmZpbHRlcihmaWxlID0+IGRpcm5hbWUoZmlsZSkgPT09IGRpcmVjdG9yeSlcbiAgICBpZiAodGVzdEZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cbiAgICByZXR1cm4gYXdhaXQgcnVuVGVzdHMocGF0aCwgZGlyZWN0b3J5LCB0ZXN0RmlsZXMsIHNpZ25hbClcbn1cblxuYXN5bmMgZnVuY3Rpb24gcnVuVGVzdHMocGF0aDogc3RyaW5nLCBkaXJlY3Rvcnk6IHN0cmluZywgdGVzdEZpbGVzOiBzdHJpbmdbXSwgc2lnbmFsOiBBYm9ydFNpZ25hbCkge1xuICAgIGNvbnN0IGN3ZCA9IGpvaW4ocGF0aCwgZGlyZWN0b3J5LCAnLi4nKVxuICAgIGNvbnN0IG1vY2hhUGFja2FnZUpzb25QYXRoID0gZmluZFBhY2thZ2VKU09OKCdtb2NoYScsIGAke3BhdGhUb0ZpbGVVUkwoY3dkKS5ocmVmfS9gKVxuICAgIGNvbnN0IGV4aXRDb2RlID0gYXdhaXQgc3Bhd25Ob2RlKFxuICAgICAgICBbXG4gICAgICAgICAgICByZWxhdGl2ZShcbiAgICAgICAgICAgICAgICBjd2QsXG4gICAgICAgICAgICAgICAgam9pbihcbiAgICAgICAgICAgICAgICAgICAgbW9jaGFQYWNrYWdlSnNvblBhdGhcbiAgICAgICAgICAgICAgICAgICAgICAgID8gZGlybmFtZShtb2NoYVBhY2thZ2VKc29uUGF0aClcbiAgICAgICAgICAgICAgICAgICAgICAgIDogam9pbihwYXRoLCAnbm9kZV9tb2R1bGVzJyksXG4gICAgICAgICAgICAgICAgICAgICdiaW4vbW9jaGEuanMnLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgJy0tY29uZmlnJyxcbiAgICAgICAgICAgICcubW9jaGFyYy5qc29uJyxcbiAgICAgICAgICAgIC4uLnRlc3RGaWxlcy5tYXAoZiA9PiByZWxhdGl2ZShjd2QsIGpvaW4ocGF0aCwgZikpKSxcbiAgICAgICAgXSxcbiAgICAgICAge1xuICAgICAgICAgICAgZGV0YWNoZWQ6IHRydWUsXG4gICAgICAgICAgICBjd2QsXG4gICAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgICAgICBQUk9KRUNUX0RJUkVDVE9SWTogcHJvY2Vzcy5jd2QoKSxcbiAgICAgICAgICAgICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgICAgICAgICAgICBSSUREQU5DRV9TVUJfUFJPSkVDVF9VUkw6IHBhdGhUb0ZpbGVVUkwoY3dkKS5ocmVmLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgc2lnbmFsLFxuICAgIClcbiAgICByZXR1cm4gZXhpdENvZGUgPT09IDBcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlVGVzdENvbmZpZyhcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgZGVwZW5kZW5jaWVzOiBQcm9taXNlPHsgZGVwZW5kZW5jaWVzOiB7IFtkZXBlbmRlbmN5OiBzdHJpbmddOiB7IHBhY2thZ2VKc29uOiB1bmtub3duIH0gfSB9PixcbiAgICByZXNvbHZlcj86IChkZXBlbmRlbmN5OiBzdHJpbmcpID0+IHN0cmluZyxcbikge1xuICAgIGNvbnN0IFtzb3VyY2VNYXBNb2R1bGUsIGhvb2tzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtzb3VyY2VNYXBTdXBwb3J0KCksIGdldEhvb2tzKGRlcGVuZGVuY2llcyldKVxuICAgIGF3YWl0IHdyaXRlRmlsZShcbiAgICAgICAgam9pbihwYXRoLCAnLm1vY2hhcmMuanNvbicpLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBwYXJhbGxlbDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAnbm9kZS1vcHRpb24nOiBbJ3RyYWNlLXdhcm5pbmdzJywgJ3VuaGFuZGxlZC1yZWplY3Rpb25zPXN0cmljdCddLFxuICAgICAgICAgICAgICAgIHJlcXVpcmU6IFtzb3VyY2VNYXBNb2R1bGUsIC4uLihyZXNvbHZlciA/IGhvb2tzLm1hcChyZXNvbHZlcikgOiBob29rcyldLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICcgICcsXG4gICAgICAgICksXG4gICAgICAgICd1dGYtOCcsXG4gICAgKVxuXG4gICAgY29uc3Qgc3ViUHJvamVjdERpcmVjdG9yeSA9IGpvaW4ocGF0aCwgJ2V4YW1wbGUnKVxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGFjY2VzcyhzdWJQcm9qZWN0RGlyZWN0b3J5LCBjb25zdGFudHMuV19PSylcbiAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGNvbnN0IHNjcmlwdCA9IHJlbGF0aXZlKFxuICAgICAgICBzdWJQcm9qZWN0RGlyZWN0b3J5LFxuICAgICAgICBmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnJlc29sdmUoJy4vc3ViLXByb2plY3QtdGVzdHMuanMnKSksXG4gICAgKVxuICAgIGF3YWl0IHNwYXduTm9kZShcbiAgICAgICAgWyctLWV4cGVyaW1lbnRhbC1pbXBvcnQtbWV0YS1yZXNvbHZlJywgc2NyaXB0XSxcbiAgICAgICAgeyBjd2Q6IHN1YlByb2plY3REaXJlY3RvcnkgfSxcbiAgICAgICAgbmV3IEFib3J0Q29udHJvbGxlcigpLnNpZ25hbCxcbiAgICApXG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNvdXJjZU1hcFN1cHBvcnQoKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgYWNjZXNzKCcuL2xpYi9zb3VyY2UtbWFwLXN1cHBvcnQudHMnLCBjb25zdGFudHMuUl9PSylcbiAgICAgICAgcmV0dXJuICcuL2xpYi9zb3VyY2UtbWFwLXN1cHBvcnQuanMnXG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiAnQHJpZGRhbmNlL2Vudi9saWIvc291cmNlLW1hcC1zdXBwb3J0LmpzJ1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0SG9va3MoXG4gICAgZGVwZW5kZW5jaWVzOiBQcm9taXNlPHsgZGVwZW5kZW5jaWVzOiB7IFtkZXBlbmRlbmN5OiBzdHJpbmddOiB7IHBhY2thZ2VKc29uOiB1bmtub3duIH0gfSB9Pixcbikge1xuICAgIHJldHVybiBPYmplY3QuZW50cmllcygoYXdhaXQgZGVwZW5kZW5jaWVzKS5kZXBlbmRlbmNpZXMpXG4gICAgICAgIC5tYXAoKFtkZXBlbmRlbmN5LCB7IHBhY2thZ2VKc29uIH1dKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IG1vY2sgfSA9IHBhY2thZ2VKc29uIGFzIHsgbW9jaz86IHVua25vd24gfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtb2NrICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBgJHtkZXBlbmRlbmN5fS8ke21vY2t9YFxuICAgICAgICB9KVxuICAgICAgICAuZmlsdGVyKGggPT4gaCAhPT0gdW5kZWZpbmVkKVxufVxuXG5mdW5jdGlvbiBzcGF3bk5vZGUoYXJnczogcmVhZG9ubHkgc3RyaW5nW10sIG9wdGlvbnM6IFNwYXduT3B0aW9ucywgc2lnbmFsOiBBYm9ydFNpZ25hbCkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxudW1iZXIgfCBudWxsPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHByb2MgPSBzcGF3bignbm9kZScsIGFyZ3MsIHtcbiAgICAgICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgICAgICBzdGRpbzogW3Byb2Nlc3Muc3RkaW4sIHByb2Nlc3Muc3Rkb3V0LCBwcm9jZXNzLnN0ZGVyciwgJ3BpcGUnXSxcbiAgICAgICAgfSlcbiAgICAgICAgY29uc3Qga2lsbGVyID0gKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgeyBwaWQgfSA9IHByb2NcbiAgICAgICAgICAgIGlmIChwaWQpIHtcbiAgICAgICAgICAgICAgICBwcm9jZXNzLmtpbGwoLXBpZCwgJ1NJR1RFUk0nKVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcm9jLmtpbGwoJ1NJR1RFUk0nKVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsIGtpbGxlcilcbiAgICAgICAgY29uc3Qgb25FcnJvciA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcilcbiAgICAgICAgICAgIHByb2MucmVtb3ZlTGlzdGVuZXIoJ2Vycm9yJywgb25FcnJvcilcbiAgICAgICAgICAgIHByb2MucmVtb3ZlTGlzdGVuZXIoJ2V4aXQnLCBvbkV4aXQpXG4gICAgICAgICAgICBzaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBraWxsZXIpXG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgb25FeGl0ID0gKGNvZGU6IG51bWJlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUoY29kZSlcbiAgICAgICAgICAgIHByb2MucmVtb3ZlTGlzdGVuZXIoJ2Vycm9yJywgb25FcnJvcilcbiAgICAgICAgICAgIHByb2MucmVtb3ZlTGlzdGVuZXIoJ2V4aXQnLCBvbkV4aXQpXG4gICAgICAgICAgICBzaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBraWxsZXIpXG4gICAgICAgIH1cbiAgICAgICAgcHJvYy5hZGRMaXN0ZW5lcignZXJyb3InLCBvbkVycm9yKVxuICAgICAgICBwcm9jLmFkZExpc3RlbmVyKCdleGl0Jywgb25FeGl0KVxuICAgIH0pXG59XG4iXX0=