UNPKG

@riddance/env

Version:

It slows you down, creates risks, increases maintainability burdens. So let's commit less of it.

122 lines 19.1 kB
import { spawn } from 'node:child_process'; import { access, constants, readFile, writeFile } from 'node:fs/promises'; 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; } export async function test(reporter, path, testFiles, changed, signal) { if (changed.length === 0) { 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)); reporter.done(); 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 exitCode = await spawnNode([ relative(cwd, join(path, 'node_modules/mocha/bin/mocha.js')), '--config', '.mocharc.json', ...testFiles.map(f => relative(cwd, join(path, f))), ], { cwd, env: { PROJECT_DIRECTORY: process.cwd(), ...process.env, RIDDANCE_SUB_PROJECT_URL: pathToFileURL(cwd).href, }, }, signal); return exitCode === 0; } export async function writeTestConfig(path, resolver) { const sourceMapModule = await sourceMapSupport(); const hooks = await getHooks(path); await writeFile(join(path, '.mocharc.json'), JSON.stringify({ parallel: true, jobs: 128, '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(path) { const { dependencies } = JSON.parse(await readFile(join(path, 'package.json'), 'utf-8')); if (!dependencies) { return []; } const hooks = await Promise.all(Object.keys(dependencies).map(async (dependency) => { const { mock } = JSON.parse(await readFile(join(path, 'node_modules', dependency, 'package.json'), 'utf-8')); if (!mock) { return ''; } return `${dependency}/${mock}`; })); return hooks.filter(h => !!h); } 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 = () => { 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidGVzdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLEVBQWdCLE1BQU0sb0JBQW9CLENBQUE7QUFDeEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ3pFLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxXQUFXLENBQUE7QUFDN0QsT0FBTyxFQUFFLGFBQWEsRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUE7QUFHdkQsTUFBTSxjQUFjLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQTtBQUU5QyxNQUFNLFVBQVUsTUFBTSxDQUFDLElBQVk7SUFDL0IsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQzdCLE9BQU8sT0FBTyxLQUFLLE1BQU0sSUFBSSxPQUFPLEtBQUssY0FBYyxDQUFBO0FBQzNELENBQUM7QUFFRCxNQUFNLENBQUMsS0FBSyxVQUFVLElBQUksQ0FDdEIsUUFBa0IsRUFDbEIsSUFBWSxFQUNaLFNBQW1CLEVBQ25CLE9BQWlCLEVBQ2pCLE1BQW1CO0lBRW5CLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN2QixPQUFPLElBQUksQ0FBQTtJQUNmLENBQUM7SUFDRCxNQUFNLG1CQUFtQixHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDakQsSUFBSSxtQkFBbUIsRUFBRSxDQUFDO1FBQ3RCLFNBQVMsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQ2hDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxRQUFRLENBQUMs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QUksQ0FBQyxTQUFTLENBQUMsQ0FBQTtRQUN4QixDQUFDLENBQUE7UUFDRCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQ3hDLE1BQU0sT0FBTyxHQUFHLENBQUMsS0FBWSxFQUFFLEVBQUU7WUFDN0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ2IsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUE7WUFDckMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUE7WUFDbkMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQTtRQUMvQyxDQUFDLENBQUE7UUFDRCxNQUFNLE1BQU0sR0FBRyxDQUFDLElBQW1CLEVBQUUsRUFBRTtZQUNuQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUE7WUFDYixJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQTtZQUNyQyxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQTtZQUNuQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQy9DLENBQUMsQ0FBQTtRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFBO1FBQ2xDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBQ3BDLENBQUMsQ0FBQyxDQUFBO0FBQ04sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNwYXduLCBTcGF3bk9wdGlvbnMgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnXG5pbXBvcnQgeyBhY2Nlc3MsIGNvbnN0YW50cywgcmVhZEZpbGUsIHdyaXRlRmlsZSB9IGZyb20gJ25vZGU6ZnMvcHJvbWlzZXMnXG5pbXBvcnQgeyBiYXNlbmFtZSwgZGlybmFtZSwgam9pbiwgcmVsYXRpdmUgfSBmcm9tICdub2RlOnBhdGgnXG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoLCBwYXRoVG9GaWxlVVJMIH0gZnJvbSAnbm9kZTp1cmwnXG5pbXBvcnQgeyBSZXBvcnRlciB9IGZyb20gJy4vcmVwb3J0ZXIuanMnXG5cbmNvbnN0IGV4YW1wbGVUZXN0RGlyID0gam9pbignZXhhbXBsZScsICd0ZXN0JylcblxuZXhwb3J0IGZ1bmN0aW9uIGlzVGVzdChmaWxlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBkaXJOYW1lID0gZGlybmFtZShmaWxlKVxuICAgIHJldHVybiBkaXJOYW1lID09PSAndGVzdCcgfHwgZGlyTmFtZSA9PT0gZXhhbXBsZVRlc3REaXJcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3QoXG4gICAgcmVwb3J0ZXI6IFJlcG9ydGVyLFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICB0ZXN0RmlsZXM6IHN0cmluZ1tdLFxuICAgIGNoYW5nZWQ6IHN0cmluZ1tdLFxuICAgIHNpZ25hbDogQWJvcnRTaWduYWwsXG4pIHtcbiAgICBpZiAoY2hhbmdlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gICAgY29uc3QgcnVuT25seUNoYW5nZWRUZXN0cyA9IGNoYW5nZWQuZXZlcnkoaXNUZXN0KVxuICAgIGlmIChydW5Pbmx5Q2hhbmdlZFRlc3RzKSB7XG4gICAgICAgIHRlc3RGaWxlcyA9IHRlc3RGaWxlcy5maWx0ZXIoZmlsZSA9PlxuICAgICAgICAgICAgY2hhbmdlZC5pbmNsdWRlcyhqb2luKGRpcm5hbWUoZmlsZSksIGJhc2VuYW1lKGZpbGUsICcuanMnKSArICcudHMnKSksXG4gICAgICAgIClcbiAgICB9XG4gICAgY29uc3Qgc3VjY2VzcyA9XG4gICAgICAgIChhd2FpdCB0ZXN0RGlyZWN0b3J5KHBhdGgsICd0ZXN0JywgdGVzdEZpbGVzLCBzaWduYWwpKSAmJlxuICAgICAgICAoYXdhaXQgdGVzdFN1YlByb2plY3REaXJlY3RvcnkocGF0aCwgZXhhbXBsZVRlc3REaXIsIHRlc3RGaWxlcywgc2lnbmFsKSlcblxuICAgIHJlcG9ydGVyLmRvbmUoKVxuICAgIHJldHVybiBzdWNjZXNzXG59XG5cbmFzeW5jIGZ1bmN0aW9uIHRlc3REaXJlY3RvcnkoXG4gICAgcGF0aDogc3RyaW5nLFxuICAgIGRpcmVjdG9yeTogc3RyaW5nLFxuICAgIHRlc3RGaWxlczogc3RyaW5nW10sXG4gICAgc2lnbmFsOiBBYm9ydFNpZ25hbCxcbikge1xuICAgIHRlc3RGaWxlcyA9IHRlc3RGaWxlcy5maWx0ZXIoZmlsZSA9PiBkaXJuYW1lKGZpbGUpID09PSBkaXJlY3RvcnkpXG4gICAgaWYgKHRlc3RGaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gICAgcmV0dXJuIGF3YWl0IHJ1blRlc3RzKHBhdGgsIGRpcmVjdG9yeSwgdGVzdEZpbGVzLCBzaWduYWwpXG59XG5cbmFzeW5jIGZ1bmN0aW9uIHRlc3RTdWJQcm9qZWN0RGlyZWN0b3J5KFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBkaXJlY3Rvcnk6IHN0cmluZyxcbiAgICB0ZXN0RmlsZXM6IHN0cmluZ1tdLFxuICAgIHNpZ25hbDogQWJvcnRTaWduYWwsXG4pIHtcbiAgICB0ZXN0RmlsZXMgPSB0ZXN0RmlsZXMuZmlsdGVyKGZpbGUgPT4gZGlybmFtZShmaWxlKSA9PT0gZGlyZWN0b3J5KVxuICAgIGlmICh0ZXN0RmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuICAgIHJldHVybiBhd2FpdCBydW5UZXN0cyhwYXRoLCBkaXJlY3RvcnksIHRlc3RGaWxlcywgc2lnbmFsKVxufVxuXG5hc3luYyBmdW5jdGlvbiBydW5UZXN0cyhwYXRoOiBzdHJpbmcsIGRpcmVjdG9yeTogc3RyaW5nLCB0ZXN0RmlsZXM6IHN0cmluZ1tdLCBzaWduYWw6IEFib3J0U2lnbmFsKSB7XG4gICAgY29uc3QgY3dkID0gam9pbihwYXRoLCBkaXJlY3RvcnksICcuLicpXG4gICAgY29uc3QgZXhpdENvZGUgPSBhd2FpdCBzcGF3bk5vZGUoXG4gICAgICAgIFtcbiAgICAgICAgICAgIHJlbGF0aXZlKGN3ZCwgam9pbihwYXRoLCAnbm9kZV9tb2R1bGVzL21vY2hhL2Jpbi9tb2NoYS5qcycpKSxcbiAgICAgICAgICAgICctLWNvbmZpZycsXG4gICAgICAgICAgICAnLm1vY2hhcmMuanNvbicsXG4gICAgICAgICAgICAuLi50ZXN0RmlsZXMubWFwKGYgPT4gcmVsYXRpdmUoY3dkLCBqb2luKHBhdGgsIGYpKSksXG4gICAgICAgIF0sXG4gICAgICAgIHtcbiAgICAgICAgICAgIGN3ZCxcbiAgICAgICAgICAgIGVudjoge1xuICAgICAgICAgICAgICAgIFBST0pFQ1RfRElSRUNUT1JZOiBwcm9jZXNzLmN3ZCgpLFxuICAgICAgICAgICAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgICAgICAgICAgIFJJRERBTkNFX1NVQl9QUk9KRUNUX1VSTDogcGF0aFRvRmlsZVVSTChjd2QpLmhyZWYsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBzaWduYWwsXG4gICAgKVxuICAgIHJldHVybiBleGl0Q29kZSA9PT0gMFxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVUZXN0Q29uZmlnKHBhdGg6IHN0cmluZywgcmVzb2x2ZXI/OiAoZGVwZW5kZW5jeTogc3RyaW5nKSA9PiBzdHJpbmcpIHtcbiAgICBjb25zdCBzb3VyY2VNYXBNb2R1bGUgPSBhd2FpdCBzb3VyY2VNYXBTdXBwb3J0KClcbiAgICBjb25zdCBob29rcyA9IGF3YWl0IGdldEhvb2tzKHBhdGgpXG4gICAgYXdhaXQgd3JpdGVGaWxlKFxuICAgICAgICBqb2luKHBhdGgsICcubW9jaGFyYy5qc29uJyksXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHBhcmFsbGVsOiB0cnVlLFxuICAgICAgICAgICAgICAgIGpvYnM6IDEyOCxcbiAgICAgICAgICAgICAgICAnbm9kZS1vcHRpb24nOiBbJ3RyYWNlLXdhcm5pbmdzJywgJ3VuaGFuZGxlZC1yZWplY3Rpb25zPXN0cmljdCddLFxuICAgICAgICAgICAgICAgIHJlcXVpcmU6IFtzb3VyY2VNYXBNb2R1bGUsIC4uLihyZXNvbHZlciA/IGhvb2tzLm1hcChyZXNvbHZlcikgOiBob29rcyldLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICcgICcsXG4gICAgICAgICksXG4gICAgICAgICd1dGYtOCcsXG4gICAgKVxuXG4gICAgY29uc3Qgc3ViUHJvamVjdERpcmVjdG9yeSA9IGpvaW4ocGF0aCwgJ2V4YW1wbGUnKVxuICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGFjY2VzcyhzdWJQcm9qZWN0RGlyZWN0b3J5LCBjb25zdGFudHMuV19PSylcbiAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGNvbnN0IHNjcmlwdCA9IHJlbGF0aXZlKFxuICAgICAgICBzdWJQcm9qZWN0RGlyZWN0b3J5LFxuICAgICAgICBmaWxlVVJMVG9QYXRoKGltcG9ydC5tZXRhLnJlc29sdmUoJy4vc3ViLXByb2plY3QtdGVzdHMuanMnKSksXG4gICAgKVxuICAgIGF3YWl0IHNwYXduTm9kZShcbiAgICAgICAgWyctLWV4cGVyaW1lbnRhbC1pbXBvcnQtbWV0YS1yZXNvbHZlJywgc2NyaXB0XSxcbiAgICAgICAgeyBjd2Q6IHN1YlByb2plY3REaXJlY3RvcnkgfSxcbiAgICAgICAgbmV3IEFib3J0Q29udHJvbGxlcigpLnNpZ25hbCxcbiAgICApXG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNvdXJjZU1hcFN1cHBvcnQoKSB7XG4gICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgYWNjZXNzKCcuL2xpYi9zb3VyY2UtbWFwLXN1cHBvcnQudHMnLCBjb25zdGFudHMuUl9PSylcbiAgICAgICAgcmV0dXJuICcuL2xpYi9zb3VyY2UtbWFwLXN1cHBvcnQuanMnXG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiAnQHJpZGRhbmNlL2Vudi9saWIvc291cmNlLW1hcC1zdXBwb3J0LmpzJ1xuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0SG9va3MocGF0aDogc3RyaW5nKSB7XG4gICAgY29uc3QgeyBkZXBlbmRlbmNpZXMgfSA9IEpTT04ucGFyc2UoYXdhaXQgcmVhZEZpbGUoam9pbihwYXRoLCAncGFja2FnZS5qc29uJyksICd1dGYtOCcpKSBhcyB7XG4gICAgICAgIGRlcGVuZGVuY2llcz86IHsgW3A6IHN0cmluZ106IHVua25vd24gfVxuICAgIH1cbiAgICBpZiAoIWRlcGVuZGVuY2llcykge1xuICAgICAgICByZXR1cm4gW11cbiAgICB9XG4gICAgY29uc3QgaG9va3MgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgT2JqZWN0LmtleXMoZGVwZW5kZW5jaWVzKS5tYXAoYXN5bmMgZGVwZW5kZW5jeSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IG1vY2sgfSA9IEpTT04ucGFyc2UoXG4gICAgICAgICAgICAgICAgYXdhaXQgcmVhZEZpbGUoam9pbihwYXRoLCAnbm9kZV9tb2R1bGVzJywgZGVwZW5kZW5jeSwgJ3BhY2thZ2UuanNvbicpLCAndXRmLTgnKSxcbiAgICAgICAgICAgICkgYXMge1xuICAgICAgICAgICAgICAgIG1vY2s6IHN0cmluZ1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtb2NrKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICcnXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYCR7ZGVwZW5kZW5jeX0vJHttb2NrfWBcbiAgICAgICAgfSksXG4gICAgKVxuICAgIHJldHVybiBob29rcy5maWx0ZXIoaCA9PiAhIWgpXG59XG5cbmZ1bmN0aW9uIHNwYXduTm9kZShhcmdzOiByZWFkb25seSBzdHJpbmdbXSwgb3B0aW9uczogU3Bhd25PcHRpb25zLCBzaWduYWw6IEFib3J0U2lnbmFsKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPG51bWJlciB8IG51bGw+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgcHJvYyA9IHNwYXduKCdub2RlJywgYXJncywge1xuICAgICAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgICAgIHN0ZGlvOiBbcHJvY2Vzcy5zdGRpbiwgcHJvY2Vzcy5zdGRvdXQsIHByb2Nlc3Muc3RkZXJyLCAncGlwZSddLFxuICAgICAgICB9KVxuICAgICAgICBjb25zdCBraWxsZXIgPSAoKSA9PiB7XG4gICAgICAgICAgICBwcm9jLmtpbGwoJ1NJR1RFUk0nKVxuICAgICAgICB9XG4gICAgICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsIGtpbGxlcilcbiAgICAgICAgY29uc3Qgb25FcnJvciA9IChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgIHJlamVjdChlcnJvcilcbiAgICAgICAgICAgIHByb2MucmVtb3ZlTGlzdGVuZXIoJ2Vycm9yJywgb25FcnJvcilcbiAgICAgICAgICAgIHByb2MucmVtb3ZlTGlzdGVuZXIoJ2V4aXQnLCBvbkV4aXQpXG4gICAgICAgICAgICBzaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBraWxsZXIpXG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgb25FeGl0ID0gKGNvZGU6IG51bWJlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUoY29kZSlcbiAgICAgICAgICAgIHByb2MucmVtb3ZlTGlzdGVuZXIoJ2Vycm9yJywgb25FcnJvcilcbiAgICAgICAgICAgIHByb2MucmVtb3ZlTGlzdGVuZXIoJ2V4aXQnLCBvbkV4aXQpXG4gICAgICAgICAgICBzaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBraWxsZXIpXG4gICAgICAgIH1cbiAgICAgICAgcHJvYy5hZGRMaXN0ZW5lcignZXJyb3InLCBvbkVycm9yKVxuICAgICAgICBwcm9jLmFkZExpc3RlbmVyKCdleGl0Jywgb25FeGl0KVxuICAgIH0pXG59XG4iXX0=