UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

428 lines 60.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.InitTemplate = void 0; exports.cliInit = cliInit; exports.availableInitTemplates = availableInitTemplates; exports.availableInitLanguages = availableInitLanguages; exports.printAvailableTemplates = printAvailableTemplates; exports.currentlyRecommendedAwsCdkLibFlags = currentlyRecommendedAwsCdkLibFlags; const childProcess = require("child_process"); const path = require("path"); const chalk = require("chalk"); const fs = require("fs-extra"); const init_hooks_1 = require("./init-hooks"); const logging_1 = require("./logging"); const error_1 = require("./toolkit/error"); const directories_1 = require("./util/directories"); const error_2 = require("./util/error"); const version_range_1 = require("./util/version-range"); /* eslint-disable @typescript-eslint/no-var-requires */ // Packages don't have @types module // eslint-disable-next-line @typescript-eslint/no-require-imports const camelCase = require('camelcase'); // eslint-disable-next-line @typescript-eslint/no-require-imports const decamelize = require('decamelize'); /** * Initialize a CDK package in the current directory */ async function cliInit(options) { const canUseNetwork = options.canUseNetwork ?? true; const generateOnly = options.generateOnly ?? false; const workDir = options.workDir ?? process.cwd(); if (!options.type && !options.language) { await printAvailableTemplates(); return; } const type = options.type || 'default'; // "default" is the default type (and maps to "app") const template = (await availableInitTemplates()).find((t) => t.hasName(type)); if (!template) { await printAvailableTemplates(options.language); throw new error_1.ToolkitError(`Unknown init template: ${type}`); } if (!options.language && template.languages.length === 1) { const language = template.languages[0]; (0, logging_1.warning)(`No --language was provided, but '${type}' supports only '${language}', so defaulting to --language=${language}`); } if (!options.language) { (0, logging_1.info)(`Available languages for ${chalk.green(type)}: ${template.languages.map((l) => chalk.blue(l)).join(', ')}`); throw new error_1.ToolkitError('No language was selected'); } await initializeProject(template, options.language, canUseNetwork, generateOnly, workDir, options.stackName, options.migrate); } /** * Returns the name of the Python executable for this OS */ function pythonExecutable() { let python = 'python3'; if (process.platform === 'win32') { python = 'python'; } return python; } const INFO_DOT_JSON = 'info.json'; class InitTemplate { static async fromName(templatesDir, name) { const basePath = path.join(templatesDir, name); const languages = await listDirectory(basePath); const initInfo = await fs.readJson(path.join(basePath, INFO_DOT_JSON)); return new InitTemplate(basePath, name, languages, initInfo); } constructor(basePath, name, languages, initInfo) { this.basePath = basePath; this.name = name; this.languages = languages; this.aliases = new Set(); this.description = initInfo.description; for (const alias of initInfo.aliases || []) { this.aliases.add(alias); } } /** * @param name the name that is being checked * @returns ``true`` if ``name`` is the name of this template or an alias of it. */ hasName(name) { return name === this.name || this.aliases.has(name); } /** * Creates a new instance of this ``InitTemplate`` for a given language to a specified folder. * * @param language the language to instantiate this template with * @param targetDirectory the directory where the template is to be instantiated into */ async install(language, targetDirectory, stackName) { if (this.languages.indexOf(language) === -1) { (0, logging_1.error)(`The ${chalk.blue(language)} language is not supported for ${chalk.green(this.name)} ` + `(it supports: ${this.languages.map((l) => chalk.blue(l)).join(', ')})`); throw new error_1.ToolkitError(`Unsupported language: ${language}`); } const projectInfo = { name: decamelize(path.basename(path.resolve(targetDirectory))), stackName, versions: await loadInitVersions(), }; const sourceDirectory = path.join(this.basePath, language); await this.installFiles(sourceDirectory, targetDirectory, language, projectInfo); await this.applyFutureFlags(targetDirectory); await (0, init_hooks_1.invokeBuiltinHooks)({ targetDirectory, language, templateName: this.name }, { substitutePlaceholdersIn: async (...fileNames) => { for (const fileName of fileNames) { const fullPath = path.join(targetDirectory, fileName); const template = await fs.readFile(fullPath, { encoding: 'utf-8' }); await fs.writeFile(fullPath, this.expand(template, language, projectInfo)); } }, placeholder: (ph) => this.expand(`%${ph}%`, language, projectInfo), }); } async installFiles(sourceDirectory, targetDirectory, language, project) { for (const file of await fs.readdir(sourceDirectory)) { const fromFile = path.join(sourceDirectory, file); const toFile = path.join(targetDirectory, this.expand(file, language, project)); if ((await fs.stat(fromFile)).isDirectory()) { await fs.mkdir(toFile); await this.installFiles(fromFile, toFile, language, project); continue; } else if (file.match(/^.*\.template\.[^.]+$/)) { await this.installProcessed(fromFile, toFile.replace(/\.template(\.[^.]+)$/, '$1'), language, project); continue; } else if (file.match(/^.*\.hook\.(d.)?[^.]+$/)) { // Ignore continue; } else { await fs.copy(fromFile, toFile); } } } async installProcessed(templatePath, toFile, language, project) { const template = await fs.readFile(templatePath, { encoding: 'utf-8' }); await fs.writeFile(toFile, this.expand(template, language, project)); } expand(template, language, project) { const cdkVersion = project.versions['aws-cdk-lib']; let constructsVersion = project.versions.constructs; switch (language) { case 'java': case 'csharp': case 'fsharp': constructsVersion = (0, version_range_1.rangeFromSemver)(constructsVersion, 'bracket'); break; case 'python': constructsVersion = (0, version_range_1.rangeFromSemver)(constructsVersion, 'pep'); break; } return template .replace(/%name%/g, project.name) .replace(/%stackname%/, project.stackName ?? '%name.PascalCased%Stack') .replace(/%PascalNameSpace%/, project.stackName ? camelCase(project.stackName + 'Stack', { pascalCase: true }) : '%name.PascalCased%') .replace(/%PascalStackProps%/, project.stackName ? camelCase(project.stackName, { pascalCase: true }) + 'StackProps' : 'StackProps') .replace(/%name\.camelCased%/g, camelCase(project.name)) .replace(/%name\.PascalCased%/g, camelCase(project.name, { pascalCase: true })) .replace(/%cdk-version%/g, cdkVersion) .replace(/%constructs-version%/g, constructsVersion) .replace(/%cdk-home%/g, (0, directories_1.cdkHomeDir)()) .replace(/%name\.PythonModule%/g, project.name.replace(/-/g, '_')) .replace(/%python-executable%/g, pythonExecutable()) .replace(/%name\.StackName%/g, project.name.replace(/[^A-Za-z0-9-]/g, '-')); } /** * Adds context variables to `cdk.json` in the generated project directory to * enable future behavior for new projects. */ async applyFutureFlags(projectDir) { const cdkJson = path.join(projectDir, 'cdk.json'); if (!(await fs.pathExists(cdkJson))) { return; } const config = await fs.readJson(cdkJson); config.context = { ...config.context, ...await currentlyRecommendedAwsCdkLibFlags(), }; await fs.writeJson(cdkJson, config, { spaces: 2 }); } async addMigrateContext(projectDir) { const cdkJson = path.join(projectDir, 'cdk.json'); if (!(await fs.pathExists(cdkJson))) { return; } const config = await fs.readJson(cdkJson); config.context = { ...config.context, 'cdk-migrate': true, }; await fs.writeJson(cdkJson, config, { spaces: 2 }); } } exports.InitTemplate = InitTemplate; async function availableInitTemplates() { return new Promise(async (resolve) => { try { const templatesDir = path.join((0, directories_1.rootDir)(), 'lib', 'init-templates'); const templateNames = await listDirectory(templatesDir); const templates = new Array(); for (const templateName of templateNames) { templates.push(await InitTemplate.fromName(templatesDir, templateName)); } resolve(templates); } catch { resolve([]); } }); } async function availableInitLanguages() { return new Promise(async (resolve) => { const templates = await availableInitTemplates(); const result = new Set(); for (const template of templates) { for (const language of template.languages) { result.add(language); } } resolve([...result]); }); } /** * @param dirPath is the directory to be listed. * @returns the list of file or directory names contained in ``dirPath``, excluding any dot-file, and sorted. */ async function listDirectory(dirPath) { return ((await fs.readdir(dirPath)) .filter((p) => !p.startsWith('.')) .filter((p) => !(p === 'LICENSE')) // if, for some reason, the temp folder for the hook doesn't get deleted we don't want to display it in this list .filter((p) => !(p === INFO_DOT_JSON)) .sort()); } async function printAvailableTemplates(language) { (0, logging_1.info)('Available templates:'); for (const template of await availableInitTemplates()) { if (language && template.languages.indexOf(language) === -1) { continue; } (0, logging_1.info)(`* ${chalk.green(template.name)}: ${template.description}`); const languageArg = language ? chalk.bold(language) : template.languages.length > 1 ? `[${template.languages.map((t) => chalk.bold(t)).join('|')}]` : chalk.bold(template.languages[0]); (0, logging_1.info)(` └─ ${chalk.blue(`cdk init ${chalk.bold(template.name)} --language=${languageArg}`)}`); } } async function initializeProject(template, language, canUseNetwork, generateOnly, workDir, stackName, migrate) { await assertIsEmptyDirectory(workDir); (0, logging_1.info)(`Applying project template ${chalk.green(template.name)} for ${chalk.blue(language)}`); await template.install(language, workDir, stackName); if (migrate) { await template.addMigrateContext(workDir); } if (await fs.pathExists(`${workDir}/README.md`)) { const readme = await fs.readFile(`${workDir}/README.md`, { encoding: 'utf-8' }); (0, logging_1.info)(chalk.green(readme)); } if (!generateOnly) { await initializeGitRepository(workDir); await postInstall(language, canUseNetwork, workDir); } (0, logging_1.info)('✅ All done!'); } async function assertIsEmptyDirectory(workDir) { const files = await fs.readdir(workDir); if (files.filter((f) => !f.startsWith('.')).length !== 0) { throw new error_1.ToolkitError('`cdk init` cannot be run in a non-empty directory!'); } } async function initializeGitRepository(workDir) { if (await isInGitRepository(workDir)) { return; } (0, logging_1.info)('Initializing a new git repository...'); try { await execute('git', ['init'], { cwd: workDir }); await execute('git', ['add', '.'], { cwd: workDir }); await execute('git', ['commit', '--message="Initial commit"', '--no-gpg-sign'], { cwd: workDir }); } catch { (0, logging_1.warning)('Unable to initialize git repository for your project.'); } } async function postInstall(language, canUseNetwork, workDir) { switch (language) { case 'javascript': return postInstallJavascript(canUseNetwork, workDir); case 'typescript': return postInstallTypescript(canUseNetwork, workDir); case 'java': return postInstallJava(canUseNetwork, workDir); case 'python': return postInstallPython(workDir); } } async function postInstallJavascript(canUseNetwork, cwd) { return postInstallTypescript(canUseNetwork, cwd); } async function postInstallTypescript(canUseNetwork, cwd) { const command = 'npm'; if (!canUseNetwork) { (0, logging_1.warning)(`Please run '${command} install'!`); return; } (0, logging_1.info)(`Executing ${chalk.green(`${command} install`)}...`); try { await execute(command, ['install'], { cwd }); } catch (e) { (0, logging_1.warning)(`${command} install failed: ` + (0, error_2.formatErrorMessage)(e)); } } async function postInstallJava(canUseNetwork, cwd) { const mvnPackageWarning = "Please run 'mvn package'!"; if (!canUseNetwork) { (0, logging_1.warning)(mvnPackageWarning); return; } (0, logging_1.info)("Executing 'mvn package'"); try { await execute('mvn', ['package'], { cwd }); } catch { (0, logging_1.warning)('Unable to package compiled code as JAR'); (0, logging_1.warning)(mvnPackageWarning); } } async function postInstallPython(cwd) { const python = pythonExecutable(); (0, logging_1.warning)(`Please run '${python} -m venv .venv'!`); (0, logging_1.info)(`Executing ${chalk.green('Creating virtualenv...')}`); try { await execute(python, ['-m venv', '.venv'], { cwd }); } catch { (0, logging_1.warning)('Unable to create virtualenv automatically'); (0, logging_1.warning)(`Please run '${python} -m venv .venv'!`); } } /** * @param dir a directory to be checked * @returns true if ``dir`` is within a git repository. */ async function isInGitRepository(dir) { while (true) { if (await fs.pathExists(path.join(dir, '.git'))) { return true; } if (isRoot(dir)) { return false; } dir = path.dirname(dir); } } /** * @param dir a directory to be checked. * @returns true if ``dir`` is the root of a filesystem. */ function isRoot(dir) { return path.dirname(dir) === dir; } /** * Executes `command`. STDERR is emitted in real-time. * * If command exits with non-zero exit code, an exceprion is thrown and includes * the contents of STDOUT. * * @returns STDOUT (if successful). */ async function execute(cmd, args, { cwd }) { const child = childProcess.spawn(cmd, args, { cwd, shell: true, stdio: ['ignore', 'pipe', 'inherit'], }); let stdout = ''; child.stdout.on('data', (chunk) => (stdout += chunk.toString())); return new Promise((ok, fail) => { child.once('error', (err) => fail(err)); child.once('exit', (status) => { if (status === 0) { return ok(stdout); } else { (0, logging_1.error)(stdout); return fail(new error_1.ToolkitError(`${cmd} exited with status ${status}`)); } }); }); } /** * Return the 'aws-cdk-lib' version we will init * * This has been built into the CLI at build time. */ async function loadInitVersions() { const recommendedFlagsFile = path.join(__dirname, './init-templates/.init-version.json'); const contents = JSON.parse(await fs.readFile(recommendedFlagsFile, { encoding: 'utf-8' })); const ret = { 'aws-cdk-lib': contents['aws-cdk-lib'], 'constructs': contents.constructs, }; for (const [key, value] of Object.entries(ret)) { /* istanbul ignore next */ if (!value) { throw new error_1.ToolkitError(`Missing init version from ${recommendedFlagsFile}: ${key}`); } } return ret; } /** * Return the currently recommended flags for `aws-cdk-lib`. * * These have been built into the CLI at build time. */ async function currentlyRecommendedAwsCdkLibFlags() { const recommendedFlagsFile = path.join(__dirname, './init-templates/.recommended-feature-flags.json'); return JSON.parse(await fs.readFile(recommendedFlagsFile, { encoding: 'utf-8' })); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImluaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBOEJBLDBCQW9DQztBQTRMRCx3REFjQztBQUNELHdEQVdDO0FBaUJELDBEQWNDO0FBc01ELGdGQUdDO0FBaGdCRCw4Q0FBOEM7QUFDOUMsNkJBQTZCO0FBQzdCLCtCQUErQjtBQUMvQiwrQkFBK0I7QUFDL0IsNkNBQWtEO0FBQ2xELHVDQUFpRDtBQUNqRCwyQ0FBK0M7QUFDL0Msb0RBQXlEO0FBQ3pELHdDQUFrRDtBQUNsRCx3REFBdUQ7QUFFdkQsdURBQXVELENBQUMsb0NBQW9DO0FBQzVGLGlFQUFpRTtBQUNqRSxNQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7QUFDdkMsaUVBQWlFO0FBQ2pFLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztBQVl6Qzs7R0FFRztBQUNJLEtBQUssVUFBVSxPQUFPLENBQUMsT0FBdUI7SUFDbkQsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUM7SUFDcEQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksSUFBSSxLQUFLLENBQUM7SUFDbkQsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDakQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDdkMsTUFBTSx1QkFBdUIsRUFBRSxDQUFDO1FBQ2hDLE9BQU87SUFDVCxDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksSUFBSSxTQUFTLENBQUMsQ0FBQyxvREFBb0Q7SUFFNUYsTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUFNLHNCQUFzQixFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxD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QUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFPRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLGdCQUFnQjtJQUM3QixNQUFNLG9CQUFvQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLHFDQUFxQyxDQUFDLENBQUM7SUFDekYsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsb0JBQW9CLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRTVGLE1BQU0sR0FBRyxHQUFHO1FBQ1YsYUFBYSxFQUFFLFFBQVEsQ0FBQyxhQUFhLENBQUM7UUFDdEMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxVQUFVO0tBQ2xDLENBQUM7SUFDRixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQy9DLDBCQUEwQjtRQUMxQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksb0JBQVksQ0FBQyw2QkFBNkIsb0JBQW9CLEtBQUssR0FBRyxFQUFFLENBQUMsQ0FBQztRQUN0RixDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSSxLQUFLLFVBQVUsa0NBQWtDO0lBQ3RELE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsa0RBQWtELENBQUMsQ0FBQztJQUN0RyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLG9CQUFvQixFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNwRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2hpbGRQcm9jZXNzIGZyb20gJ2NoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCB7IGludm9rZUJ1aWx0aW5Ib29rcyB9IGZyb20gJy4vaW5pdC1ob29rcyc7XG5pbXBvcnQgeyBlcnJvciwgaW5mbywgd2FybmluZyB9IGZyb20gJy4vbG9nZ2luZyc7XG5pbXBvcnQgeyBUb29sa2l0RXJyb3IgfSBmcm9tICcuL3Rvb2xraXQvZXJyb3InO1xuaW1wb3J0IHsgY2RrSG9tZURpciwgcm9vdERpciB9IGZyb20gJy4vdXRpbC9kaXJlY3Rvcmllcyc7XG5pbXBvcnQgeyBmb3JtYXRFcnJvck1lc3NhZ2UgfSBmcm9tICcuL3V0aWwvZXJyb3InO1xuaW1wb3J0IHsgcmFuZ2VGcm9tU2VtdmVyIH0gZnJvbSAnLi91dGlsL3ZlcnNpb24tcmFuZ2UnO1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdmFyLXJlcXVpcmVzICovIC8vIFBhY2thZ2VzIGRvbid0IGhhdmUgQHR5cGVzIG1vZHVsZVxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbmNvbnN0IGNhbWVsQ2FzZSA9IHJlcXVpcmUoJ2NhbWVsY2FzZScpO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbmNvbnN0IGRlY2FtZWxpemUgPSByZXF1aXJlKCdkZWNhbWVsaXplJyk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpSW5pdE9wdGlvbnMge1xuICByZWFkb25seSB0eXBlPzogc3RyaW5nO1xuICByZWFkb25seSBsYW5ndWFnZT86IHN0cmluZztcbiAgcmVhZG9ubHkgY2FuVXNlTmV0d29yaz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGdlbmVyYXRlT25seT86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHdvcmtEaXI/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN0YWNrTmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgbWlncmF0ZT86IGJvb2xlYW47XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBhIENESyBwYWNrYWdlIGluIHRoZSBjdXJyZW50IGRpcmVjdG9yeVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2xpSW5pdChvcHRpb25zOiBDbGlJbml0T3B0aW9ucykge1xuICBjb25zdCBjYW5Vc2VOZXR3b3JrID0gb3B0aW9ucy5jYW5Vc2VOZXR3b3JrID8/IHRydWU7XG4gIGNvbnN0IGdlbmVyYXRlT25seSA9IG9wdGlvbnMuZ2VuZXJhdGVPbmx5ID8/IGZhbHNlO1xuICBjb25zdCB3b3JrRGlyID0gb3B0aW9ucy53b3JrRGlyID8/IHByb2Nlc3MuY3dkKCk7XG4gIGlmICghb3B0aW9ucy50eXBlICYmICFvcHRpb25zLmxhbmd1YWdlKSB7XG4gICAgYXdhaXQgcHJpbnRBdmFpbGFibGVUZW1wbGF0ZXMoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCB0eXBlID0gb3B0aW9ucy50eXBlIHx8ICdkZWZhdWx0JzsgLy8gXCJkZWZhdWx0XCIgaXMgdGhlIGRlZmF1bHQgdHlwZSAoYW5kIG1hcHMgdG8gXCJhcHBcIilcblxuICBjb25zdCB0ZW1wbGF0ZSA9IChhd2FpdCBhdmFpbGFibGVJbml0VGVtcGxhdGVzKCkpLmZpbmQoKHQpID0+IHQuaGFzTmFtZSh0eXBlISkpO1xuICBpZiAoIXRlbXBsYXRlKSB7XG4gICAgYXdhaXQgcHJpbnRBdmFpbGFibGVUZW1wbGF0ZXMob3B0aW9ucy5sYW5ndWFnZSk7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihgVW5rbm93biBpbml0IHRlbXBsYXRlOiAke3R5cGV9YCk7XG4gIH1cbiAgaWYgKCFvcHRpb25zLmxhbmd1YWdlICYmIHRlbXBsYXRlLmxhbmd1YWdlcy5sZW5ndGggPT09IDEpIHtcbiAgICBjb25zdCBsYW5ndWFnZSA9IHRlbXBsYXRlLmxhbmd1YWdlc1swXTtcbiAgICB3YXJuaW5nKFxuICAgICAgYE5vIC0tbGFuZ3VhZ2Ugd2FzIHByb3ZpZGVkLCBidXQgJyR7dHlwZX0nIHN1cHBvcnRzIG9ubHkgJyR7bGFuZ3VhZ2V9Jywgc28gZGVmYXVsdGluZyB0byAtLWxhbmd1YWdlPSR7bGFuZ3VhZ2V9YCxcbiAgICApO1xuICB9XG4gIGlmICghb3B0aW9ucy5sYW5ndWFnZSkge1xuICAgIGluZm8oYEF2YWlsYWJsZSBsYW5ndWFnZXMgZm9yICR7Y2hhbGsuZ3JlZW4odHlwZSl9OiAke3RlbXBsYXRlLmxhbmd1YWdlcy5tYXAoKGwpID0+IGNoYWxrLmJsdWUobCkpLmpvaW4oJywgJyl9YCk7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcignTm8gbGFuZ3VhZ2Ugd2FzIHNlbGVjdGVkJyk7XG4gIH1cblxuICBhd2FpdCBpbml0aWFsaXplUHJvamVjdChcbiAgICB0ZW1wbGF0ZSxcbiAgICBvcHRpb25zLmxhbmd1YWdlLFxuICAgIGNhblVzZU5ldHdvcmssXG4gICAgZ2VuZXJhdGVPbmx5LFxuICAgIHdvcmtEaXIsXG4gICAgb3B0aW9ucy5zdGFja05hbWUsXG4gICAgb3B0aW9ucy5taWdyYXRlLFxuICApO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIG5hbWUgb2YgdGhlIFB5dGhvbiBleGVjdXRhYmxlIGZvciB0aGlzIE9TXG4gKi9cbmZ1bmN0aW9uIHB5dGhvbkV4ZWN1dGFibGUoKSB7XG4gIGxldCBweXRob24gPSAncHl0aG9uMyc7XG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSAnd2luMzInKSB7XG4gICAgcHl0aG9uID0gJ3B5dGhvbic7XG4gIH1cbiAgcmV0dXJuIHB5dGhvbjtcbn1cbmNvbnN0IElORk9fRE9UX0pTT04gPSAnaW5mby5qc29uJztcblxuZXhwb3J0IGNsYXNzIEluaXRUZW1wbGF0ZSB7XG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgZnJvbU5hbWUodGVtcGxhdGVzRGlyOiBzdHJpbmcsIG5hbWU6IHN0cmluZykge1xuICAgIGNvbnN0IGJhc2VQYXRoID0gcGF0aC5qb2luKHRlbXBsYXRlc0RpciwgbmFtZSk7XG4gICAgY29uc3QgbGFuZ3VhZ2VzID0gYXdhaXQgbGlzdERpcmVjdG9yeShiYXNlUGF0aCk7XG4gICAgY29uc3QgaW5pdEluZm8gPSBhd2FpdCBmcy5yZWFkSnNvbihwYXRoLmpvaW4oYmFzZVBhdGgsIElORk9fRE9UX0pTT04pKTtcbiAgICByZXR1cm4gbmV3IEluaXRUZW1wbGF0ZShiYXNlUGF0aCwgbmFtZSwgbGFuZ3VhZ2VzLCBpbml0SW5mbyk7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgZGVzY3JpcHRpb246IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IGFsaWFzZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGJhc2VQYXRoOiBzdHJpbmcsXG4gICAgcHVibGljIHJlYWRvbmx5IG5hbWU6IHN0cmluZyxcbiAgICBwdWJsaWMgcmVhZG9ubHkgbGFuZ3VhZ2VzOiBzdHJpbmdbXSxcbiAgICBpbml0SW5mbzogYW55LFxuICApIHtcbiAgICB0aGlzLmRlc2NyaXB0aW9uID0gaW5pdEluZm8uZGVzY3JpcHRpb247XG4gICAgZm9yIChjb25zdCBhbGlhcyBvZiBpbml0SW5mby5hbGlhc2VzIHx8IFtdKSB7XG4gICAgICB0aGlzLmFsaWFzZXMuYWRkKGFsaWFzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIG5hbWUgdGhlIG5hbWUgdGhhdCBpcyBiZWluZyBjaGVja2VkXG4gICAqIEByZXR1cm5zIGBgdHJ1ZWBgIGlmIGBgbmFtZWBgIGlzIHRoZSBuYW1lIG9mIHRoaXMgdGVtcGxhdGUgb3IgYW4gYWxpYXMgb2YgaXQuXG4gICAqL1xuICBwdWJsaWMgaGFzTmFtZShuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gbmFtZSA9PT0gdGhpcy5uYW1lIHx8IHRoaXMuYWxpYXNlcy5oYXMobmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGlzIGBgSW5pdFRlbXBsYXRlYGAgZm9yIGEgZ2l2ZW4gbGFuZ3VhZ2UgdG8gYSBzcGVjaWZpZWQgZm9sZGVyLlxuICAgKlxuICAgKiBAcGFyYW0gbGFuZ3VhZ2UgICAgdGhlIGxhbmd1YWdlIHRvIGluc3RhbnRpYXRlIHRoaXMgdGVtcGxhdGUgd2l0aFxuICAgKiBAcGFyYW0gdGFyZ2V0RGlyZWN0b3J5IHRoZSBkaXJlY3Rvcnkgd2hlcmUgdGhlIHRlbXBsYXRlIGlzIHRvIGJlIGluc3RhbnRpYXRlZCBpbnRvXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgaW5zdGFsbChsYW5ndWFnZTogc3RyaW5nLCB0YXJnZXREaXJlY3Rvcnk6IHN0cmluZywgc3RhY2tOYW1lPzogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMubGFuZ3VhZ2VzLmluZGV4T2YobGFuZ3VhZ2UpID09PSAtMSkge1xuICAgICAgZXJyb3IoXG4gICAgICAgIGBUaGUgJHtjaGFsay5ibHVlKGxhbmd1YWdlKX0gbGFuZ3VhZ2UgaXMgbm90IHN1cHBvcnRlZCBmb3IgJHtjaGFsay5ncmVlbih0aGlzLm5hbWUpfSBgICtcbiAgICAgICAgICBgKGl0IHN1cHBvcnRzOiAke3RoaXMubGFuZ3VhZ2VzLm1hcCgobCkgPT4gY2hhbGsuYmx1ZShsKSkuam9pbignLCAnKX0pYCxcbiAgICAgICk7XG4gICAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKGBVbnN1cHBvcnRlZCBsYW5ndWFnZTogJHtsYW5ndWFnZX1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9qZWN0SW5mbzogUHJvamVjdEluZm8gPSB7XG4gICAgICBuYW1lOiBkZWNhbWVsaXplKHBhdGguYmFzZW5hbWUocGF0aC5yZXNvbHZlKHRhcmdldERpcmVjdG9yeSkpKSxcbiAgICAgIHN0YWNrTmFtZSxcbiAgICAgIHZlcnNpb25zOiBhd2FpdCBsb2FkSW5pdFZlcnNpb25zKCksXG4gICAgfTtcblxuICAgIGNvbnN0IHNvdXJjZURpcmVjdG9yeSA9IHBhdGguam9pbih0aGlzLmJhc2VQYXRoLCBsYW5ndWFnZSk7XG5cbiAgICBhd2FpdCB0aGlzLmluc3RhbGxGaWxlcyhzb3VyY2VEaXJlY3RvcnksIHRhcmdldERpcmVjdG9yeSwgbGFuZ3VhZ2UsIHByb2plY3RJbmZvKTtcbiAgICBhd2FpdCB0aGlzLmFwcGx5RnV0dXJlRmxhZ3ModGFyZ2V0RGlyZWN0b3J5KTtcbiAgICBhd2FpdCBpbnZva2VCdWlsdGluSG9va3MoXG4gICAgICB7IHRhcmdldERpcmVjdG9yeSwgbGFuZ3VhZ2UsIHRlbXBsYXRlTmFtZTogdGhpcy5uYW1lIH0sXG4gICAgICB7XG4gICAgICAgIHN1YnN0aXR1dGVQbGFjZWhvbGRlcnNJbjogYXN5bmMgKC4uLmZpbGVOYW1lczogc3RyaW5nW10pID0+IHtcbiAgICAgICAgICBmb3IgKGNvbnN0IGZpbGVOYW1lIG9mIGZpbGVOYW1lcykge1xuICAgICAgICAgICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4odGFyZ2V0RGlyZWN0b3J5LCBmaWxlTmFtZSk7XG4gICAgICAgICAgICBjb25zdCB0ZW1wbGF0ZSA9IGF3YWl0IGZzLnJlYWRGaWxlKGZ1bGxQYXRoLCB7IGVuY29kaW5nOiAndXRmLTgnIH0pO1xuICAgICAgICAgICAgYXdhaXQgZnMud3JpdGVGaWxlKGZ1bGxQYXRoLCB0aGlzLmV4cGFuZCh0ZW1wbGF0ZSwgbGFuZ3VhZ2UsIHByb2plY3RJbmZvKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBwbGFjZWhvbGRlcjogKHBoOiBzdHJpbmcpID0+IHRoaXMuZXhwYW5kKGAlJHtwaH0lYCwgbGFuZ3VhZ2UsIHByb2plY3RJbmZvKSxcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgaW5zdGFsbEZpbGVzKHNvdXJjZURpcmVjdG9yeTogc3RyaW5nLCB0YXJnZXREaXJlY3Rvcnk6IHN0cmluZywgbGFuZ3VhZ2U6IHN0cmluZywgcHJvamVjdDogUHJvamVjdEluZm8pIHtcbiAgICBmb3IgKGNvbnN0IGZpbGUgb2YgYXdhaXQgZnMucmVhZGRpcihzb3VyY2VEaXJlY3RvcnkpKSB7XG4gICAgICBjb25zdCBmcm9tRmlsZSA9IHBhdGguam9pbihzb3VyY2VEaXJlY3RvcnksIGZpbGUpO1xuICAgICAgY29uc3QgdG9GaWxlID0gcGF0aC5qb2luKHRhcmdldERpcmVjdG9yeSwgdGhpcy5leHBhbmQoZmlsZSwgbGFuZ3VhZ2UsIHByb2plY3QpKTtcbiAgICAgIGlmICgoYXdhaXQgZnMuc3RhdChmcm9tRmlsZSkpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgYXdhaXQgZnMubWtkaXIodG9GaWxlKTtcbiAgICAgICAgYXdhaXQgdGhpcy5pbnN0YWxsRmlsZXMoZnJvbUZpbGUsIHRvRmlsZSwgbGFuZ3VhZ2UsIHByb2plY3QpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH0gZWxzZSBpZiAoZmlsZS5tYXRjaCgvXi4qXFwudGVtcGxhdGVcXC5bXi5dKyQvKSkge1xuICAgICAgICBhd2FpdCB0aGlzLmluc3RhbGxQcm9jZXNzZWQoZnJvbUZpbGUsIHRvRmlsZS5yZXBsYWNlKC9cXC50ZW1wbGF0ZShcXC5bXi5dKykkLywgJyQxJyksIGxhbmd1YWdlLCBwcm9qZWN0KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9IGVsc2UgaWYgKGZpbGUubWF0Y2goL14uKlxcLmhvb2tcXC4oZC4pP1teLl0rJC8pKSB7XG4gICAgICAgIC8vIElnbm9yZVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IGZzLmNvcHkoZnJvbUZpbGUsIHRvRmlsZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbnN0YWxsUHJvY2Vzc2VkKHRlbXBsYXRlUGF0aDogc3RyaW5nLCB0b0ZpbGU6IHN0cmluZywgbGFuZ3VhZ2U6IHN0cmluZywgcHJvamVjdDogUHJvamVjdEluZm8pIHtcbiAgICBjb25zdCB0ZW1wbGF0ZSA9IGF3YWl0IGZzLnJlYWRGaWxlKHRlbXBsYXRlUGF0aCwgeyBlbmNvZGluZzogJ3V0Zi04JyB9KTtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUodG9GaWxlLCB0aGlzLmV4cGFuZCh0ZW1wbGF0ZSwgbGFuZ3VhZ2UsIHByb2plY3QpKTtcbiAgfVxuXG4gIHByaXZhdGUgZXhwYW5kKHRlbXBsYXRlOiBzdHJpbmcsIGxhbmd1YWdlOiBzdHJpbmcsIHByb2plY3Q6IFByb2plY3RJbmZvKSB7XG4gICAgY29uc3QgY2RrVmVyc2lvbiA9IHByb2plY3QudmVyc2lvbnNbJ2F3cy1jZGstbGliJ107XG4gICAgbGV0IGNvbnN0cnVjdHNWZXJzaW9uID0gcHJvamVjdC52ZXJzaW9ucy5jb25zdHJ1Y3RzO1xuXG4gICAgc3dpdGNoIChsYW5ndWFnZSkge1xuICAgICAgY2FzZSAnamF2YSc6XG4gICAgICBjYXNlICdjc2hhcnAnOlxuICAgICAgY2FzZSAnZnNoYXJwJzpcbiAgICAgICAgY29uc3RydWN0c1ZlcnNpb24gPSByYW5nZUZyb21TZW12ZXIoY29uc3RydWN0c1ZlcnNpb24sICdicmFja2V0Jyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncHl0aG9uJzpcbiAgICAgICAgY29uc3RydWN0c1ZlcnNpb24gPSByYW5nZUZyb21TZW12ZXIoY29uc3RydWN0c1ZlcnNpb24sICdwZXAnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiB0ZW1wbGF0ZVxuICAgICAgLnJlcGxhY2UoLyVuYW1lJS9nLCBwcm9qZWN0Lm5hbWUpXG4gICAgICAucmVwbGFjZSgvJXN0YWNrbmFtZSUvLCBwcm9qZWN0LnN0YWNrTmFtZSA/PyAnJW5hbWUuUGFzY2FsQ2FzZWQlU3RhY2snKVxuICAgICAgLnJlcGxhY2UoXG4gICAgICAgIC8lUGFzY2FsTmFtZVNwYWNlJS8sXG4gICAgICAgIHByb2plY3Quc3RhY2tOYW1lID8gY2FtZWxDYXNlKHByb2plY3Quc3RhY2tOYW1lICsgJ1N0YWNrJywgeyBwYXNjYWxDYXNlOiB0cnVlIH0pIDogJyVuYW1lLlBhc2NhbENhc2VkJScsXG4gICAgICApXG4gICAgICAucmVwbGFjZShcbiAgICAgICAgLyVQYXNjYWxTdGFja1Byb3BzJS8sXG4gICAgICAgIHByb2plY3Quc3RhY2tOYW1lID8gY2FtZWxDYXNlKHByb2plY3Quc3RhY2tOYW1lLCB7IHBhc2NhbENhc2U6IHRydWUgfSkgKyAnU3RhY2tQcm9wcycgOiAnU3RhY2tQcm9wcycsXG4gICAgICApXG4gICAgICAucmVwbGFjZSgvJW5hbWVcXC5jYW1lbENhc2VkJS9nLCBjYW1lbENhc2UocHJvamVjdC5uYW1lKSlcbiAgICAgIC5yZXBsYWNlKC8lbmFtZVxcLlBhc2NhbENhc2VkJS9nLCBjYW1lbENhc2UocHJvamVjdC5uYW1lLCB7IHBhc2NhbENhc2U6IHRydWUgfSkpXG4gICAgICAucmVwbGFjZSgvJWNkay12ZXJzaW9uJS9nLCBjZGtWZXJzaW9uKVxuICAgICAgLnJlcGxhY2UoLyVjb25zdHJ1Y3RzLXZlcnNpb24lL2csIGNvbnN0cnVjdHNWZXJzaW9uKVxuICAgICAgLnJlcGxhY2UoLyVjZGstaG9tZSUvZywgY2RrSG9tZURpcigpKVxuICAgICAgLnJlcGxhY2UoLyVuYW1lXFwuUHl0aG9uTW9kdWxlJS9nLCBwcm9qZWN0Lm5hbWUucmVwbGFjZSgvLS9nLCAnXycpKVxuICAgICAgLnJlcGxhY2UoLyVweXRob24tZXhlY3V0YWJsZSUvZywgcHl0aG9uRXhlY3V0YWJsZSgpKVxuICAgICAgLnJlcGxhY2UoLyVuYW1lXFwuU3RhY2tOYW1lJS9nLCBwcm9qZWN0Lm5hbWUucmVwbGFjZSgvW15BLVphLXowLTktXS9nLCAnLScpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGNvbnRleHQgdmFyaWFibGVzIHRvIGBjZGsuanNvbmAgaW4gdGhlIGdlbmVyYXRlZCBwcm9qZWN0IGRpcmVjdG9yeSB0b1xuICAgKiBlbmFibGUgZnV0dXJlIGJlaGF2aW9yIGZvciBuZXcgcHJvamVjdHMuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGFwcGx5RnV0dXJlRmxhZ3MocHJvamVjdERpcjogc3RyaW5nKSB7XG4gICAgY29uc3QgY2RrSnNvbiA9IHBhdGguam9pbihwcm9qZWN0RGlyLCAnY2RrLmpzb24nKTtcbiAgICBpZiAoIShhd2FpdCBmcy5wYXRoRXhpc3RzKGNka0pzb24pKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbmZpZyA9IGF3YWl0IGZzLnJlYWRKc29uKGNka0pzb24pO1xuICAgIGNvbmZpZy5jb250ZXh0ID0ge1xuICAgICAgLi4uY29uZmlnLmNvbnRleHQsXG4gICAgICAuLi5hd2FpdCBjdXJyZW50bHlSZWNvbW1lbmRlZEF3c0Nka0xpYkZsYWdzKCksXG4gICAgfTtcblxuICAgIGF3YWl0IGZzLndyaXRlSnNvbihjZGtKc29uLCBjb25maWcsIHsgc3BhY2VzOiAyIH0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGFkZE1pZ3JhdGVDb250ZXh0KHByb2plY3REaXI6IHN0cmluZykge1xuICAgIGNvbnN0IGNka0pzb24gPSBwYXRoLmpvaW4ocHJvamVjdERpciwgJ2Nkay5qc29uJyk7XG4gICAgaWYgKCEoYXdhaXQgZnMucGF0aEV4aXN0cyhjZGtKc29uKSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjb25maWcgPSBhd2FpdCBmcy5yZWFkSnNvbihjZGtKc29uKTtcbiAgICBjb25maWcuY29udGV4dCA9IHtcbiAgICAgIC4uLmNvbmZpZy5jb250ZXh0LFxuICAgICAgJ2Nkay1taWdyYXRlJzogdHJ1ZSxcbiAgICB9O1xuXG4gICAgYXdhaXQgZnMud3JpdGVKc29uKGNka0pzb24sIGNvbmZpZywgeyBzcGFjZXM6IDIgfSk7XG4gIH1cbn1cblxuaW50ZXJmYWNlIFByb2plY3RJbmZvIHtcbiAgLyoqIFRoZSB2YWx1ZSB1c2VkIGZvciAlbmFtZSUgKi9cbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICByZWFkb25seSBzdGFja05hbWU/OiBzdHJpbmc7XG5cbiAgcmVhZG9ubHkgdmVyc2lvbnM6IFZlcnNpb25zO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXZhaWxhYmxlSW5pdFRlbXBsYXRlcygpOiBQcm9taXNlPEluaXRUZW1wbGF0ZVtdPiB7XG4gIHJldHVyb