UNPKG

@riddance/env

Version:

Too much code slows you down, creates risks, increases maintainability burdens, confuses AI. So let's commit less of it.

239 lines 34.5 kB
import { access, constants, copyFile, mkdir, readdir, readFile, rm, stat, unlink, writeFile, } from 'node:fs/promises'; import { EOL, platform } from 'node:os'; import { join } from 'node:path'; import { managedFiles as managedAgentFiles, setupAgents } from './agents.js'; import { dependantPackages } from './dependencies.js'; import { isFileNotFound } from './fs.js'; import { install } from './npm.js'; import { vote } from './siblings.js'; import { setupSpelling } from './spelling.js'; import { writeTestConfig } from './tester.js'; const dirs = ['.vscode', '.zed', '.devcontainer', '.idea/codeStyles/', '.idea/inspectionProfiles/']; const files = [ 'tsconfig.json', '.prettierrc.json', '.editorconfig', '.nvmrc', '.vscode/settings.json', '.vscode/tasks.json', '.vscode/extensions.json', '.zed/settings.json', '.zed/tasks.json', '.devcontainer/Dockerfile', '.devcontainer/devcontainer.json', '.idea/compiler.xml', '.idea/codeStyles/codeStyleConfig.xml', '.idea/inspectionProfiles/Project_Default.xml', ]; const overridableFiles = []; const legacyFiles = [ '.prettierrc', 'Dockerfile.integration', '.eslintrc.json', 'eslint.config.js', ['.gitattributes', '* text=auto eol=lf\n'], ]; const managedFiles = [ '.gitignore', ...files, ...legacyFiles.map(lf => (Array.isArray(lf) ? lf[0] : lf)), 'cspell.json', 'eslint.config.mjs', '.mocharc.json', ...managedAgentFiles, ]; export async function prepare() { await createTemplate(); await makeWindowsNpmPackFriendly('template'); } async function createTemplate() { await rm('template', { recursive: true, force: true }); await mkdir('template'); await Promise.all(dirs.map(dir => mkdir(join('template', dir), { recursive: true }))); await Promise.all([...files, ...overridableFiles.map(f => f[0])].map(file => copyFile(file, join('template', file)))); await writeFile('template/gitignore', [ ...files.map(f => `/${f}`), ...(await readFile('.gitignore', 'utf-8')) .split('\n') .filter(l => !!l && l.trim() !== '/template' && l.trim() !== '!/eslint.config.mjs'), '/eslint.config.mjs', '/.gitignore', '', ].join('\n')); await writeFile('template/eslint.config', (await readFile('eslint.config.mjs', 'utf-8')) .split('\n') .map(l => l .replace(/import \{ [^}]+ \} from '\.\/lib\/eslint-config.js'/u, `import { configuration } from '@riddance/env/lib/eslint-config.js'`) .trim()) .join('\n')); } export async function setup(targetDir, firstInstall, myself) { if (firstInstall && !myself) { // eslint-disable-next-line no-bitwise const mod = constants.R_OK | constants.W_OK; const accessResult = await Promise.allSettled(managedFiles.map(f => access(join(targetDir, f), mod))); const existing = []; accessResult.forEach((r, ix) => { if (r.status === 'fulfilled') { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion existing.push(managedFiles[ix]); } }); if (existing.length !== 0) { return existing; } } await Promise.all(legacyFiles.map(file => ensureUnlinked(targetDir, file))); await Promise.all(dirs.map(dir => mkdir(join(targetDir, dir), { recursive: true }))); const dependencies = dependantPackages(targetDir); await Promise.all([ ...(myself ? [] : [copyFromTemplate(targetDir)]), setupSpelling(targetDir), writeTestConfig(targetDir, dependencies), syncGitUser(targetDir), setupAgents(targetDir, dependencies, myself), makeWindowsNpmPackAndDevcontainerFriendly(targetDir), ensureUnlinked(targetDir, '.timestamps.json'), ]); return []; } async function copyFromTemplate(targetDir) { await Promise.all(files.map(file => copyFile(join('template', file), join(targetDir, file)))); await copyFile('template/gitignore', join(targetDir, '.gitignore')); await copyFile('template/eslint.config', join(targetDir, 'eslint.config.mjs')); for (const [file, belongsHere] of overridableFiles) { try { const existing = await readFile(join(targetDir, file), 'utf-8'); if (!belongsHere(existing)) { continue; } } catch (e) { if (!isFileNotFound(e)) { throw e; } } await copyFile(join('template', file), join(targetDir, file)); } } async function syncGitUser(path) { try { const [ws, core, ...sections] = (await readFile(join(path, '.git/config'), 'utf-8')).split('['); if (!ws || !core || sections[0]?.startsWith('user]')) { return; } const user = await vote(path, '.git/config', content => content .split('[') .filter(section => section.startsWith('user]')) .join('[')); if (!user) { return; } await writeFile(join(path, '.git/config'), [ws, core, user, ...sections].join('['), 'utf-8'); } catch (e) { if (isFileNotFound(e)) { return; } throw e; } } export async function uninstall(reporter, targetDir) { reporter.status('Uninstalling...'); const packageJson = JSON.parse(await readFile(join(targetDir, 'package.json'), 'utf-8')); await ensureUnlinked(targetDir, '.timestamps.json'); await writeFile(join(targetDir, '.gitignore'), `.DS_Store node_modules/ *.js *.js.map *.d.ts `, 'utf-8'); let modified = false; if (packageJson.scripts) { for (const [key, value] of Object.entries(packageJson.scripts)) { if (value.includes('@riddance/') || value.startsWith('riddance-')) { delete packageJson.scripts[key]; modified = true; } } } if (packageJson.devDependencies?.['@riddance/env']) { delete packageJson.devDependencies['@riddance/env']; modified = true; if (Object.keys(packageJson.devDependencies).length === 0) { delete packageJson.devDependencies; } } if (modified) { await writeFile(join(targetDir, 'package.json'), JSON.stringify(packageJson, undefined, ' '), 'utf-8'); await install(reporter, targetDir); } } async function makeWindowsNpmPackAndDevcontainerFriendly(targetDir) { if (platform() !== 'win32') { return; } const path = join(targetDir, '.git', 'info', 'attributes'); if (!(await stat(path).catch(isFileNotFound))) { return; } await mkdir(join(targetDir, '.git', 'info'), { recursive: true }); await writeFile(path, sourceExtensions.map(ext => `*${ext} text=auto eol=lf\n`).join('')); for await (const sourceFile of findFiles(targetDir, isSource)) { await dos2unix(sourceFile); } } async function makeWindowsNpmPackFriendly(targetDir) { if (platform() !== 'win32') { return; } for await (const sourceFile of findFiles(targetDir, () => true)) { await dos2unix(sourceFile); } } async function dos2unix(file) { const dos = await readFile(file, 'utf-8'); const unix = dos.replaceAll(EOL, '\n'); if (unix.length !== dos.length) { await writeFile(file, unix, 'utf-8'); } } const sourceExtensions = ['.ts', '.json', '.txt', '.md']; const otherSources = new Set(['LICENSE', 'eslint.config.mjs']); function isSource(file) { return ((sourceExtensions.some(ext => file.name.endsWith(ext)) && !file.name.endsWith('.d.ts')) || otherSources.has(file.name)); } async function* findFiles(path, predicate) { const entries = await readdir(path, { withFileTypes: true }); for (const entry of entries) { if (entry.isDirectory() && entry.name !== 'node_modules') { yield* findFiles(join(path, entry.name), predicate); } if (entry.isFile() && predicate(entry)) { yield join(path, entry.name); } } } async function ensureUnlinked(dir, file) { try { if (Array.isArray(file)) { const [filename, expectedContents] = file; const path = join(dir, filename); if ((await readFile(path, 'utf-8')) !== expectedContents) { return; } await unlink(join(dir, filename)); } else { await unlink(join(dir, file)); } } catch (e) { if (isFileNotFound(e)) { return; } throw e; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZW52LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFDSCxNQUFNLEVBQ04sU0FBUyxFQUNULFFBQVEsRUFDUixLQUFLLEVBQ0wsT0FBTyxFQUNQLFFBQVEsRUFDUixFQUFFLEVBQ0YsSUFBSSxFQUNKLE1BQU0sRUFDTixTQUFTLEdBQ1osTUFBTSxrQkFBa0IsQ0FBQTtBQUN6QixPQUFPLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxNQUFNLFNBQVMsQ0FBQTtBQUN2QyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFBO0FBQ2hDLE9BQU8sRUFBRSxZQUFZLElBQUksaUJBQWlCLEVBQUUsV0FBVyxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQzVFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ3JELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxTQUFTLENBQUE7QUFDeEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFVBQVUsQ0FBQTtBQUVsQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQ3BDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDN0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGFBQWEsQ0FBQTtBQUU3QyxNQUFNLElBQUksR0FBRyxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsZUFBZSxFQUFFLG1CQUFtQixFQUFFLDJCQUEyQixDQUFDLENBQUE7QUFDbkcsTUFBTSxLQUFLLEdBQUc7SUFDVixlQUFlO0lBQ2Ysa0JBQWtCO0lBQ2xCLGVBQWU7SUFDZixRQUFRO0lBQ1IsdUJBQXVCO0lBQ3ZCLG9CQUFvQjtJQUNwQix5QkFBeUI7SUFDekIsb0JBQW9CO0lBQ3BCLGlCQUFpQjtJQUNqQiwwQkFBMEI7SUFDMUIsaUNBQWlDO0lBQ2pDLG9CQUFvQjtJQUNwQixzQ0FBc0M7SUFDdEMsOENBQThDO0NBQ2pELENBQUE7QUFDRCxNQUFNLGdCQUFnQixHQUE2QyxFQUFFLENBQUE7QUFDckUsTUFBTSxXQUFXLEdBQWtDO0lBQy9DLGFBQWE7SUFDYix3QkFBd0I7SUFDeEIsZ0JBQWdCO0lBQ2hCLGtCQUFrQjtJQUNsQixDQUFDLGdCQUFnQixFQUFFLHNCQUFzQixDQUFDO0NBQzdDLENBQUE7QUFFRCxNQUFNLFlBQVksR0FBRztJQUNqQixZQUFZO0lBQ1osR0FBRyxLQUFLO0lBQ1IsR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQzFELGFBQWE7SUFDYixtQkFBbUI7SUFDbkIsZUFBZTtJQUNmLEdBQUcsaUJBQWlCO0NBQ3ZCLENBQUE7QUFFRCxNQUFNLENBQUMsS0FBSyxVQUFVLE9BQU87SUFDekIsTUFBTSxjQUFjLEVBQUUsQ0FBQTtJQUN0QixNQUFNLDBCQUEwQixDQUFDLFVBQVUsQ0FBQyxDQUFBO0FBQ2hELENBQUM7QUFFRCxLQUFLLFVBQVUsY0FBYztJQUN6QixNQUFNLEVBQUUsQ0FBQyxVQUFVLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFBO0lBQ3RELE1BQU0sS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFBO0lBQ3ZCLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDckYsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUNiLENBQUMsR0FBRyxLQUFLLEVBQUUsR0FBRyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUN0RCxRQUFRLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FDekMsQ0FDSixDQUFBO0lBQ0QsTUFBTSxTQUFTLENBQ1gsb0JBQW9CLEVBQ3BCO1FBQ0ksR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUMxQixHQUFHLENBQUMsTUFBTSxRQUFRLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxDQUFDO2FBQ3JDLEtBQUssQ0FBQyxJQUFJLENBQUM7YUFDWCxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxXQUFXLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLHFCQUFxQixDQUFDO1FBQ3ZGLG9CQUFvQjtRQUNwQixhQUFhO1FBQ2IsRUFBRTtLQUNMLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUNmLENBQUE7SUFDRCxNQUFNLFNBQVMsQ0FDWCx3QkFBd0IsRUFDeEIsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUN6QyxLQUFLLENBQUMsSUFBSSxDQUFDO1NBQ1gsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQ0wsQ0FBQztTQUNJLE9BQU8sQ0FDSixzREFBc0QsRUFDdEQsb0VBQW9FLENBQ3ZFO1NBQ0EsSUFBSSxFQUFFLENBQ2Q7U0FDQSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQ2xCLENBQUE7QUFDTCxDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxLQUFLLENBQUMsU0FBaUIsRUFBRSxZQUFxQixFQUFFLE1BQWU7SUFDakYsSUFBSSxZQUFZLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMxQixzQ0FBc0M7UUFDdEMsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLElBQUksR0FBRyxTQUFTLENBQUMsSUFBSSxDQUFBO1FBQzNDLE1BQU0sWUFBWSxHQUFHLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FDekMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQ3pELENBQUE7UUFDRCxNQUFNLFFBQVEsR0FBYSxFQUFFLENBQUE7UUFDN0IsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUMzQixJQUFJLENBQUMsQ0FBQyxNQUFNLEtBQUssV0FBVyxFQUFFLENBQUM7Z0JBQzNCLG9FQUFvRTtnQkFDcEUsUUFBUSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFFLENBQUMsQ0FBQTtZQUNwQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUE7UUFDRixJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDeEIsT0FBTyxRQUFRLENBQUE7UUFDbkIsQ0FBQztJQUNMLENBQUM7SUFDRCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQzNFLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDcEYsTUFBTSxZQUFZLEdBQUcsaUJBQWlCLENBQUMsU0FBUyxDQUFDLENBQUE7SUFDakQsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDO1FBQ2QsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDaEQsYUFBYSxDQUFDLFNBQVMsQ0FBQztRQUN4QixlQUFlLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQztRQUN4QyxXQUFXLENBQUMsU0FBUyxDQUFDO1FBQ3RCLFdBQVcsQ0FBQyxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sQ0FBQztRQUM1Qyx5Q0FBeUMsQ0FBQyxTQUFTLENBQUM7UUFDcEQsY0FBYyxDQUFDLFNBQVMsRUFBRSxrQkFBa0IsQ0FBQztLQUNoRCxDQUFDLENBQUE7SUFDRixPQUFPLEVBQUUsQ0FBQTtBQUNiLENBQUM7QUFFRCxLQUFLLFVBQVUsZ0JBQWdCLENBQUMsU0FBaUI7SUFDN0MsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQzdGLE1BQU0sUUFBUSxDQUFDLG9CQUFvQixFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQTtJQUNuRSxNQUFNLFFBQVEsQ0FBQyx3QkFBd0IsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLG1CQUFtQixDQUFDLENBQUMsQ0FBQTtJQUM5RSxLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztRQUNqRCxJQUFJLENBQUM7WUFDRCxNQUFNLFFBQVEsR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFBO1lBQy9ELElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztnQkFDekIsU0FBUTtZQUNaLENBQUM7UUFDTCxDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNULElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDckIsTUFBTSxDQUFDLENBQUE7WUFDWCxDQUFDO1FBQ0wsQ0FBQztRQUNELE1BQU0sUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFBO0lBQ2pFLENBQUM7QUFDTCxDQUFDO0FBRUQsS0FBSyxVQUFVLFdBQVcsQ0FBQyxJQUFZO0lBQ25DLElBQUksQ0FBQztRQUNELE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUN0RixHQUFHLENBQ04sQ0FBQTtRQUNELElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxJQUFJLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ25ELE9BQU07UUFDVixDQUFDO1FBQ0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRSxPQUFPLENBQUMsRUFBRSxDQUNuRCxPQUFPO2FBQ0YsS0FBSyxDQUFDLEdBQUcsQ0FBQzthQUNWLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7YUFDOUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUNqQixDQUFBO1FBQ0QsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1IsT0FBTTtRQUNWLENBQUM7UUFDRCxNQUFNLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxRQUFRLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUE7SUFDaEcsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDVCxJQUFJLGNBQWMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3BCLE9BQU07UUFDVixDQUFDO1FBQ0QsTUFBTSxDQUFDLENBQUE7SUFDWCxDQUFDO0FBQ0wsQ0FBQztBQUVELE1BQU0sQ0FBQyxLQUFLLFVBQVUsU0FBUyxDQUFDLFFBQWtCLEVBQUUsU0FBaUI7SUFDakUsUUFBUSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO0lBQ2xDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxjQUFjLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FLdEYsQ0FBQTtJQUVELE1BQU0sY0FBYyxDQUFDLFNBQVMsRUFBRSxrQkFBa0IsQ0FBQyxDQUFBO0lBRW5ELE1BQU0sU0FBUyxDQUNYLElBQUksQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLEVBQzdCOzs7OztDQUtQLEVBQ08sT0FBTyxDQUNWLENBQUE7SUFFRCxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUE7SUFDcEIsSUFBSSxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDdEIsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDN0QsSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztnQkFDaEUsT0FBTyxXQUFXLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUMvQixRQUFRLEdBQUcsSUFBSSxDQUFBO1lBQ25CLENBQUM7UUFDTCxDQUFDO0lBQ0wsQ0FBQztJQUNELElBQUksV0FBVyxDQUFDLGVBQWUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7UUFDakQsT0FBTyxXQUFXLENBQUMsZUFBZSxDQUFDLGVBQWUsQ0FBQyxDQUFBO1FBQ25ELFFBQVEsR0FBRyxJQUFJLENBQUE7UUFDZixJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN4RCxPQUFPLFdBQVcsQ0FBQyxlQUFlLENBQUE7UUFDdEMsQ0FBQztJQUNMLENBQUM7SUFDRCxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQ1gsTUFBTSxTQUFTLENBQ1gsSUFBSSxDQUFDLFNBQVMsRUFBRSxjQUFjLENBQUMsRUFDL0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxFQUM1QyxPQUFPLENBQ1YsQ0FBQTtRQUNELE1BQU0sT0FBTyxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQTtJQUN0QyxDQUFDO0FBQ0wsQ0FBQztBQUVELEtBQUssVUFBVSx5Q0FBeUMsQ0FBQyxTQUFpQjtJQUN0RSxJQUFJLFFBQVEsRUFBRSxLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQ3pCLE9BQU07SUFDVixDQUFDO0lBQ0QsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFBO0lBQzFELElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDNUMsT0FBTTtJQUNWLENBQUM7SUFDRCxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFBO0lBQ2pFLE1BQU0sU0FBUyxDQUFDLElBQUksRUFBRSxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEdBQUcscUJBQXFCLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUN6RixJQUFJLEtBQUssRUFBRSxNQUFNLFVBQVUsSUFBSSxTQUFTLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDNUQsTUFBTSxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUE7SUFDOUIsQ0FBQztBQUNMLENBQUM7QUFFRCxLQUFLLFVBQVUsMEJBQTBCLENBQUMsU0FBaUI7SUFDdkQsSUFBSSxRQUFRLEVBQUUsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUN6QixPQUFNO0lBQ1YsQ0FBQztJQUNELElBQUksS0FBSyxFQUFFLE1BQU0sVUFBVSxJQUFJLFNBQVMsQ0FBQyxTQUFTLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUM5RCxNQUFNLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUM5QixDQUFDO0FBQ0wsQ0FBQztBQUVELEtBQUssVUFBVSxRQUFRLENBQUMsSUFBWTtJQUNoQyxNQUFNLEdBQUcsR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUE7SUFDekMsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUE7SUFDdEMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUM3QixNQUFNLFNBQVMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFBO0lBQ3hDLENBQUM7QUFDTCxDQUFDO0FBRUQsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO0FBQ3hELE1BQU0sWUFBWSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLG1CQUFtQixDQUFDLENBQUMsQ0FBQTtBQUU5RCxTQUFTLFFBQVEsQ0FBQyxJQUFZO0lBQzFCLE9BQU8sQ0FDSCxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2RixZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDOUIsQ0FBQTtBQUNMLENBQUM7QUFFRCxLQUFLLFNBQVMsQ0FBQyxDQUFDLFNBQVMsQ0FDckIsSUFBWSxFQUNaLFNBQXFDO0lBRXJDLE1BQU0sT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLElBQUksRUFBRSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFBO0lBQzVELEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxFQUFFLENBQUM7UUFDMUIsSUFBSSxLQUFLLENBQUMsV0FBVyxFQUFFLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxjQUFjLEVBQUUsQ0FBQztZQUN2RCxLQUFLLENBQUMsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUE7UUFDdkQsQ0FBQztRQUNELElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRSxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3JDLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDaEMsQ0FBQztJQUNMLENBQUM7QUFDTCxDQUFDO0FBRUQsS0FBSyxVQUFVLGNBQWMsQ0FBQyxHQUFXLEVBQUUsSUFBK0I7SUFDdEUsSUFBSSxDQUFDO1FBQ0QsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDdEIsTUFBTSxDQUFDLFFBQVEsRUFBRSxnQkFBZ0IsQ0FBQyxHQUFHLElBQUksQ0FBQTtZQUN6QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFBO1lBQ2hDLElBQUksQ0FBQyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO2dCQUN2RCxPQUFNO1lBQ1YsQ0FBQztZQUNELE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQTtRQUNyQyxDQUFDO2FBQU0sQ0FBQztZQUNKLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUNqQyxDQUFDO0lBQ0wsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDVCxJQUFJLGNBQWMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3BCLE9BQU07UUFDVixDQUFDO1FBQ0QsTUFBTSxDQUFDLENBQUE7SUFDWCxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1yZXN0cmljdGVkLWltcG9ydHNcbmltcG9ydCB7IHR5cGUgRGlyZW50IH0gZnJvbSAnbm9kZTpmcydcbmltcG9ydCB7XG4gICAgYWNjZXNzLFxuICAgIGNvbnN0YW50cyxcbiAgICBjb3B5RmlsZSxcbiAgICBta2RpcixcbiAgICByZWFkZGlyLFxuICAgIHJlYWRGaWxlLFxuICAgIHJtLFxuICAgIHN0YXQsXG4gICAgdW5saW5rLFxuICAgIHdyaXRlRmlsZSxcbn0gZnJvbSAnbm9kZTpmcy9wcm9taXNlcydcbmltcG9ydCB7IEVPTCwgcGxhdGZvcm0gfSBmcm9tICdub2RlOm9zJ1xuaW1wb3J0IHsgam9pbiB9IGZyb20gJ25vZGU6cGF0aCdcbmltcG9ydCB7IG1hbmFnZWRGaWxlcyBhcyBtYW5hZ2VkQWdlbnRGaWxlcywgc2V0dXBBZ2VudHMgfSBmcm9tICcuL2FnZW50cy5qcydcbmltcG9ydCB7IGRlcGVuZGFudFBhY2thZ2VzIH0gZnJvbSAnLi9kZXBlbmRlbmNpZXMuanMnXG5pbXBvcnQgeyBpc0ZpbGVOb3RGb3VuZCB9IGZyb20gJy4vZnMuanMnXG5pbXBvcnQgeyBpbnN0YWxsIH0gZnJvbSAnLi9ucG0uanMnXG5pbXBvcnQgdHlwZSB7IFJlcG9ydGVyIH0gZnJvbSAnLi9yZXBvcnRlci5qcydcbmltcG9ydCB7IHZvdGUgfSBmcm9tICcuL3NpYmxpbmdzLmpzJ1xuaW1wb3J0IHsgc2V0dXBTcGVsbGluZyB9IGZyb20gJy4vc3BlbGxpbmcuanMnXG5pbXBvcnQgeyB3cml0ZVRlc3RDb25maWcgfSBmcm9tICcuL3Rlc3Rlci5qcydcblxuY29uc3QgZGlycyA9IFsnLnZzY29kZScsICcuemVkJywgJy5kZXZjb250YWluZXInLCAnLmlkZWEvY29kZVN0eWxlcy8nLCAnLmlkZWEvaW5zcGVjdGlvblByb2ZpbGVzLyddXG5jb25zdCBmaWxlcyA9IFtcbiAgICAndHNjb25maWcuanNvbicsXG4gICAgJy5wcmV0dGllcnJjLmpzb24nLFxuICAgICcuZWRpdG9yY29uZmlnJyxcbiAgICAnLm52bXJjJyxcbiAgICAnLnZzY29kZS9zZXR0aW5ncy5qc29uJyxcbiAgICAnLnZzY29kZS90YXNrcy5qc29uJyxcbiAgICAnLnZzY29kZS9leHRlbnNpb25zLmpzb24nLFxuICAgICcuemVkL3NldHRpbmdzLmpzb24nLFxuICAgICcuemVkL3Rhc2tzLmpzb24nLFxuICAgICcuZGV2Y29udGFpbmVyL0RvY2tlcmZpbGUnLFxuICAgICcuZGV2Y29udGFpbmVyL2RldmNvbnRhaW5lci5qc29uJyxcbiAgICAnLmlkZWEvY29tcGlsZXIueG1sJyxcbiAgICAnLmlkZWEvY29kZVN0eWxlcy9jb2RlU3R5bGVDb25maWcueG1sJyxcbiAgICAnLmlkZWEvaW5zcGVjdGlvblByb2ZpbGVzL1Byb2plY3RfRGVmYXVsdC54bWwnLFxuXVxuY29uc3Qgb3ZlcnJpZGFibGVGaWxlczogW3N0cmluZywgKGNvbnRlbnQ6IHN0cmluZykgPT4gYm9vbGVhbl1bXSA9IFtdXG5jb25zdCBsZWdhY3lGaWxlczogKHN0cmluZyB8IFtzdHJpbmcsIHN0cmluZ10pW10gPSBbXG4gICAgJy5wcmV0dGllcnJjJyxcbiAgICAnRG9ja2VyZmlsZS5pbnRlZ3JhdGlvbicsXG4gICAgJy5lc2xpbnRyYy5qc29uJyxcbiAgICAnZXNsaW50LmNvbmZpZy5qcycsXG4gICAgWycuZ2l0YXR0cmlidXRlcycsICcqIHRleHQ9YXV0byBlb2w9bGZcXG4nXSxcbl1cblxuY29uc3QgbWFuYWdlZEZpbGVzID0gW1xuICAgICcuZ2l0aWdub3JlJyxcbiAgICAuLi5maWxlcyxcbiAgICAuLi5sZWdhY3lGaWxlcy5tYXAobGYgPT4gKEFycmF5LmlzQXJyYXkobGYpID8gbGZbMF0gOiBsZikpLFxuICAgICdjc3BlbGwuanNvbicsXG4gICAgJ2VzbGludC5jb25maWcubWpzJyxcbiAgICAnLm1vY2hhcmMuanNvbicsXG4gICAgLi4ubWFuYWdlZEFnZW50RmlsZXMsXG5dXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcmVwYXJlKCkge1xuICAgIGF3YWl0IGNyZWF0ZVRlbXBsYXRlKClcbiAgICBhd2FpdCBtYWtlV2luZG93c05wbVBhY2tGcmllbmRseSgndGVtcGxhdGUnKVxufVxuXG5hc3luYyBmdW5jdGlvbiBjcmVhdGVUZW1wbGF0ZSgpIHtcbiAgICBhd2FpdCBybSgndGVtcGxhdGUnLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSlcbiAgICBhd2FpdCBta2RpcigndGVtcGxhdGUnKVxuICAgIGF3YWl0IFByb21pc2UuYWxsKGRpcnMubWFwKGRpciA9PiBta2Rpcihqb2luKCd0ZW1wbGF0ZScsIGRpciksIHsgcmVjdXJzaXZlOiB0cnVlIH0pKSlcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgWy4uLmZpbGVzLCAuLi5vdmVycmlkYWJsZUZpbGVzLm1hcChmID0+IGZbMF0pXS5tYXAoZmlsZSA9PlxuICAgICAgICAgICAgY29weUZpbGUoZmlsZSwgam9pbigndGVtcGxhdGUnLCBmaWxlKSksXG4gICAgICAgICksXG4gICAgKVxuICAgIGF3YWl0IHdyaXRlRmlsZShcbiAgICAgICAgJ3RlbXBsYXRlL2dpdGlnbm9yZScsXG4gICAgICAgIFtcbiAgICAgICAgICAgIC4uLmZpbGVzLm1hcChmID0+IGAvJHtmfWApLFxuICAgICAgICAgICAgLi4uKGF3YWl0IHJlYWRGaWxlKCcuZ2l0aWdub3JlJywgJ3V0Zi04JykpXG4gICAgICAgICAgICAgICAgLnNwbGl0KCdcXG4nKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIobCA9PiAhIWwgJiYgbC50cmltKCkgIT09ICcvdGVtcGxhdGUnICYmIGwudHJpbSgpICE9PSAnIS9lc2xpbnQuY29uZmlnLm1qcycpLFxuICAgICAgICAgICAgJy9lc2xpbnQuY29uZmlnLm1qcycsXG4gICAgICAgICAgICAnLy5naXRpZ25vcmUnLFxuICAgICAgICAgICAgJycsXG4gICAgICAgIF0uam9pbignXFxuJyksXG4gICAgKVxuICAgIGF3YWl0IHdyaXRlRmlsZShcbiAgICAgICAgJ3RlbXBsYXRlL2VzbGludC5jb25maWcnLFxuICAgICAgICAoYXdhaXQgcmVhZEZpbGUoJ2VzbGludC5jb25maWcubWpzJywgJ3V0Zi04JykpXG4gICAgICAgICAgICAuc3BsaXQoJ1xcbicpXG4gICAgICAgICAgICAubWFwKGwgPT5cbiAgICAgICAgICAgICAgICBsXG4gICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKFxuICAgICAgICAgICAgICAgICAgICAgICAgL2ltcG9ydCBcXHsgW159XSsgXFx9IGZyb20gJ1xcLlxcL2xpYlxcL2VzbGludC1jb25maWcuanMnL3UsXG4gICAgICAgICAgICAgICAgICAgICAgICBgaW1wb3J0IHsgY29uZmlndXJhdGlvbiB9IGZyb20gJ0ByaWRkYW5jZS9lbnYvbGliL2VzbGludC1jb25maWcuanMnYCxcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAudHJpbSgpLFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLmpvaW4oJ1xcbicpLFxuICAgIClcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNldHVwKHRhcmdldERpcjogc3RyaW5nLCBmaXJzdEluc3RhbGw6IGJvb2xlYW4sIG15c2VsZjogYm9vbGVhbikge1xuICAgIGlmIChmaXJzdEluc3RhbGwgJiYgIW15c2VsZikge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgICAgICBjb25zdCBtb2QgPSBjb25zdGFudHMuUl9PSyB8IGNvbnN0YW50cy5XX09LXG4gICAgICAgIGNvbnN0IGFjY2Vzc1Jlc3VsdCA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChcbiAgICAgICAgICAgIG1hbmFnZWRGaWxlcy5tYXAoZiA9PiBhY2Nlc3Moam9pbih0YXJnZXREaXIsIGYpLCBtb2QpKSxcbiAgICAgICAgKVxuICAgICAgICBjb25zdCBleGlzdGluZzogc3RyaW5nW10gPSBbXVxuICAgICAgICBhY2Nlc3NSZXN1bHQuZm9yRWFjaCgociwgaXgpID0+IHtcbiAgICAgICAgICAgIGlmIChyLnN0YXR1cyA9PT0gJ2Z1bGZpbGxlZCcpIHtcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvblxuICAgICAgICAgICAgICAgIGV4aXN0aW5nLnB1c2gobWFuYWdlZEZpbGVzW2l4XSEpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIGlmIChleGlzdGluZy5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBleGlzdGluZ1xuICAgICAgICB9XG4gICAgfVxuICAgIGF3YWl0IFByb21pc2UuYWxsKGxlZ2FjeUZpbGVzLm1hcChmaWxlID0+IGVuc3VyZVVubGlua2VkKHRhcmdldERpciwgZmlsZSkpKVxuICAgIGF3YWl0IFByb21pc2UuYWxsKGRpcnMubWFwKGRpciA9PiBta2Rpcihqb2luKHRhcmdldERpciwgZGlyKSwgeyByZWN1cnNpdmU6IHRydWUgfSkpKVxuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IGRlcGVuZGFudFBhY2thZ2VzKHRhcmdldERpcilcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICAgIC4uLihteXNlbGYgPyBbXSA6IFtjb3B5RnJvbVRlbXBsYXRlKHRhcmdldERpcildKSxcbiAgICAgICAgc2V0dXBTcGVsbGluZyh0YXJnZXREaXIpLFxuICAgICAgICB3cml0ZVRlc3RDb25maWcodGFyZ2V0RGlyLCBkZXBlbmRlbmNpZXMpLFxuICAgICAgICBzeW5jR2l0VXNlcih0YXJnZXREaXIpLFxuICAgICAgICBzZXR1cEFnZW50cyh0YXJnZXREaXIsIGRlcGVuZGVuY2llcywgbXlzZWxmKSxcbiAgICAgICAgbWFrZVdpbmRvd3NOcG1QYWNrQW5kRGV2Y29udGFpbmVyRnJpZW5kbHkodGFyZ2V0RGlyKSxcbiAgICAgICAgZW5zdXJlVW5saW5rZWQodGFyZ2V0RGlyLCAnLnRpbWVzdGFtcHMuanNvbicpLFxuICAgIF0pXG4gICAgcmV0dXJuIFtdXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNvcHlGcm9tVGVtcGxhdGUodGFyZ2V0RGlyOiBzdHJpbmcpIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChmaWxlcy5tYXAoZmlsZSA9PiBjb3B5RmlsZShqb2luKCd0ZW1wbGF0ZScsIGZpbGUpLCBqb2luKHRhcmdldERpciwgZmlsZSkpKSlcbiAgICBhd2FpdCBjb3B5RmlsZSgndGVtcGxhdGUvZ2l0aWdub3JlJywgam9pbih0YXJnZXREaXIsICcuZ2l0aWdub3JlJykpXG4gICAgYXdhaXQgY29weUZpbGUoJ3RlbXBsYXRlL2VzbGludC5jb25maWcnLCBqb2luKHRhcmdldERpciwgJ2VzbGludC5jb25maWcubWpzJykpXG4gICAgZm9yIChjb25zdCBbZmlsZSwgYmVsb25nc0hlcmVdIG9mIG92ZXJyaWRhYmxlRmlsZXMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nID0gYXdhaXQgcmVhZEZpbGUoam9pbih0YXJnZXREaXIsIGZpbGUpLCAndXRmLTgnKVxuICAgICAgICAgICAgaWYgKCFiZWxvbmdzSGVyZShleGlzdGluZykpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAoIWlzRmlsZU5vdEZvdW5kKGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGF3YWl0IGNvcHlGaWxlKGpvaW4oJ3RlbXBsYXRlJywgZmlsZSksIGpvaW4odGFyZ2V0RGlyLCBmaWxlKSlcbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHN5bmNHaXRVc2VyKHBhdGg6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IFt3cywgY29yZSwgLi4uc2VjdGlvbnNdID0gKGF3YWl0IHJlYWRGaWxlKGpvaW4ocGF0aCwgJy5naXQvY29uZmlnJyksICd1dGYtOCcpKS5zcGxpdChcbiAgICAgICAgICAgICdbJyxcbiAgICAgICAgKVxuICAgICAgICBpZiAoIXdzIHx8ICFjb3JlIHx8IHNlY3Rpb25zWzBdPy5zdGFydHNXaXRoKCd1c2VyXScpKSB7XG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgdm90ZShwYXRoLCAnLmdpdC9jb25maWcnLCBjb250ZW50ID0+XG4gICAgICAgICAgICBjb250ZW50XG4gICAgICAgICAgICAgICAgLnNwbGl0KCdbJylcbiAgICAgICAgICAgICAgICAuZmlsdGVyKHNlY3Rpb24gPT4gc2VjdGlvbi5zdGFydHNXaXRoKCd1c2VyXScpKVxuICAgICAgICAgICAgICAgIC5qb2luKCdbJyksXG4gICAgICAgIClcbiAgICAgICAgaWYgKCF1c2VyKSB7XG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB3cml0ZUZpbGUoam9pbihwYXRoLCAnLmdpdC9jb25maWcnKSwgW3dzLCBjb3JlLCB1c2VyLCAuLi5zZWN0aW9uc10uam9pbignWycpLCAndXRmLTgnKVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKGlzRmlsZU5vdEZvdW5kKGUpKSB7XG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBlXG4gICAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdW5pbnN0YWxsKHJlcG9ydGVyOiBSZXBvcnRlciwgdGFyZ2V0RGlyOiBzdHJpbmcpIHtcbiAgICByZXBvcnRlci5zdGF0dXMoJ1VuaW5zdGFsbGluZy4uLicpXG4gICAgY29uc3QgcGFja2FnZUpzb24gPSBKU09OLnBhcnNlKGF3YWl0IHJlYWRGaWxlKGpvaW4odGFyZ2V0RGlyLCAncGFja2FnZS5qc29uJyksICd1dGYtOCcpKSBhcyB7XG4gICAgICAgIHNjcmlwdHM/OiB7IFtzOiBzdHJpbmddOiBzdHJpbmcgfVxuICAgICAgICBkZXZEZXBlbmRlbmNpZXM/OiB7XG4gICAgICAgICAgICAnQHJpZGRhbmNlL2Vudic/OiBzdHJpbmdcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGF3YWl0IGVuc3VyZVVubGlua2VkKHRhcmdldERpciwgJy50aW1lc3RhbXBzLmpzb24nKVxuXG4gICAgYXdhaXQgd3JpdGVGaWxlKFxuICAgICAgICBqb2luKHRhcmdldERpciwgJy5naXRpZ25vcmUnKSxcbiAgICAgICAgYC5EU19TdG9yZVxubm9kZV9tb2R1bGVzL1xuKi5qc1xuKi5qcy5tYXBcbiouZC50c1xuYCxcbiAgICAgICAgJ3V0Zi04JyxcbiAgICApXG5cbiAgICBsZXQgbW9kaWZpZWQgPSBmYWxzZVxuICAgIGlmIChwYWNrYWdlSnNvbi5zY3JpcHRzKSB7XG4gICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHBhY2thZ2VKc29uLnNjcmlwdHMpKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUuaW5jbHVkZXMoJ0ByaWRkYW5jZS8nKSB8fCB2YWx1ZS5zdGFydHNXaXRoKCdyaWRkYW5jZS0nKSkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBwYWNrYWdlSnNvbi5zY3JpcHRzW2tleV1cbiAgICAgICAgICAgICAgICBtb2RpZmllZCA9IHRydWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAocGFja2FnZUpzb24uZGV2RGVwZW5kZW5jaWVzPy5bJ0ByaWRkYW5jZS9lbnYnXSkge1xuICAgICAgICBkZWxldGUgcGFja2FnZUpzb24uZGV2RGVwZW5kZW5jaWVzWydAcmlkZGFuY2UvZW52J11cbiAgICAgICAgbW9kaWZpZWQgPSB0cnVlXG4gICAgICAgIGlmIChPYmplY3Qua2V5cyhwYWNrYWdlSnNvbi5kZXZEZXBlbmRlbmNpZXMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgZGVsZXRlIHBhY2thZ2VKc29uLmRldkRlcGVuZGVuY2llc1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmIChtb2RpZmllZCkge1xuICAgICAgICBhd2FpdCB3cml0ZUZpbGUoXG4gICAgICAgICAgICBqb2luKHRhcmdldERpciwgJ3BhY2thZ2UuanNvbicpLFxuICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkocGFja2FnZUpzb24sIHVuZGVmaW5lZCwgJyAgJyksXG4gICAgICAgICAgICAndXRmLTgnLFxuICAgICAgICApXG4gICAgICAgIGF3YWl0IGluc3RhbGwocmVwb3J0ZXIsIHRhcmdldERpcilcbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1ha2VXaW5kb3dzTnBtUGFja0FuZERldmNvbnRhaW5lckZyaWVuZGx5KHRhcmdldERpcjogc3RyaW5nKSB7XG4gICAgaWYgKHBsYXRmb3JtKCkgIT09ICd3aW4zMicpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGNvbnN0IHBhdGggPSBqb2luKHRhcmdldERpciwgJy5naXQnLCAnaW5mbycsICdhdHRyaWJ1dGVzJylcbiAgICBpZiAoIShhd2FpdCBzdGF0KHBhdGgpLmNhdGNoKGlzRmlsZU5vdEZvdW5kKSkpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGF3YWl0IG1rZGlyKGpvaW4odGFyZ2V0RGlyLCAnLmdpdCcsICdpbmZvJyksIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG4gICAgYXdhaXQgd3JpdGVGaWxlKHBhdGgsIHNvdXJjZUV4dGVuc2lvbnMubWFwKGV4dCA9PiBgKiR7ZXh0fSB0ZXh0PWF1dG8gZW9sPWxmXFxuYCkuam9pbignJykpXG4gICAgZm9yIGF3YWl0IChjb25zdCBzb3VyY2VGaWxlIG9mIGZpbmRGaWxlcyh0YXJnZXREaXIsIGlzU291cmNlKSkge1xuICAgICAgICBhd2FpdCBkb3MydW5peChzb3VyY2VGaWxlKVxuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gbWFrZVdpbmRvd3NOcG1QYWNrRnJpZW5kbHkodGFyZ2V0RGlyOiBzdHJpbmcpIHtcbiAgICBpZiAocGxhdGZvcm0oKSAhPT0gJ3dpbjMyJykge1xuICAgICAgICByZXR1cm5cbiAgICB9XG4gICAgZm9yIGF3YWl0IChjb25zdCBzb3VyY2VGaWxlIG9mIGZpbmRGaWxlcyh0YXJnZXREaXIsICgpID0+IHRydWUpKSB7XG4gICAgICAgIGF3YWl0IGRvczJ1bml4KHNvdXJjZUZpbGUpXG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBkb3MydW5peChmaWxlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBkb3MgPSBhd2FpdCByZWFkRmlsZShmaWxlLCAndXRmLTgnKVxuICAgIGNvbnN0IHVuaXggPSBkb3MucmVwbGFjZUFsbChFT0wsICdcXG4nKVxuICAgIGlmICh1bml4Lmxlbmd0aCAhPT0gZG9zLmxlbmd0aCkge1xuICAgICAgICBhd2FpdCB3cml0ZUZpbGUoZmlsZSwgdW5peCwgJ3V0Zi04JylcbiAgICB9XG59XG5cbmNvbnN0IHNvdXJjZUV4dGVuc2lvbnMgPSBbJy50cycsICcuanNvbicsICcudHh0JywgJy5tZCddXG5jb25zdCBvdGhlclNvdXJjZXMgPSBuZXcgU2V0KFsnTElDRU5TRScsICdlc2xpbnQuY29uZmlnLm1qcyddKVxuXG5mdW5jdGlvbiBpc1NvdXJjZShmaWxlOiBEaXJlbnQpIHtcbiAgICByZXR1cm4gKFxuICAgICAgICAoc291cmNlRXh0ZW5zaW9ucy5zb21lKGV4dCA9PiBmaWxlLm5hbWUuZW5kc1dpdGgoZXh0KSkgJiYgIWZpbGUubmFtZS5lbmRzV2l0aCgnLmQudHMnKSkgfHxcbiAgICAgICAgb3RoZXJTb3VyY2VzLmhhcyhmaWxlLm5hbWUpXG4gICAgKVxufVxuXG5hc3luYyBmdW5jdGlvbiogZmluZEZpbGVzKFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBwcmVkaWNhdGU6IChlbnRyeTogRGlyZW50KSA9PiBib29sZWFuLFxuKTogQXN5bmNHZW5lcmF0b3I8c3RyaW5nLCB2b2lkPiB7XG4gICAgY29uc3QgZW50cmllcyA9IGF3YWl0IHJlYWRkaXIocGF0aCwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pXG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiBlbnRyaWVzKSB7XG4gICAgICAgIGlmIChlbnRyeS5pc0RpcmVjdG9yeSgpICYmIGVudHJ5Lm5hbWUgIT09ICdub2RlX21vZHVsZXMnKSB7XG4gICAgICAgICAgICB5aWVsZCogZmluZEZpbGVzKGpvaW4ocGF0aCwgZW50cnkubmFtZSksIHByZWRpY2F0ZSlcbiAgICAgICAgfVxuICAgICAgICBpZiAoZW50cnkuaXNGaWxlKCkgJiYgcHJlZGljYXRlKGVudHJ5KSkge1xuICAgICAgICAgICAgeWllbGQgam9pbihwYXRoLCBlbnRyeS5uYW1lKVxuICAgICAgICB9XG4gICAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBlbnN1cmVVbmxpbmtlZChkaXI6IHN0cmluZywgZmlsZTogc3RyaW5nIHwgW3N0cmluZywgc3RyaW5nXSkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGZpbGUpKSB7XG4gICAgICAgICAgICBjb25zdCBbZmlsZW5hbWUsIGV4cGVjdGVkQ29udGVudHNdID0gZmlsZVxuICAgICAgICAgICAgY29uc3QgcGF0aCA9IGpvaW4oZGlyLCBmaWxlbmFtZSlcbiAgICAgICAgICAgIGlmICgoYXdhaXQgcmVhZEZpbGUocGF0aCwgJ3V0Zi04JykpICE9PSBleHBlY3RlZENvbnRlbnRzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCB1bmxpbmsoam9pbihkaXIsIGZpbGVuYW1lKSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGF3YWl0IHVubGluayhqb2luKGRpciwgZmlsZSkpXG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChpc0ZpbGVOb3RGb3VuZChlKSkge1xuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgZVxuICAgIH1cbn1cbiJdfQ==