UNPKG

aws-cdk

Version:

CDK Toolkit, the command line tool for CDK apps

272 lines 38.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.execProgram = execProgram; exports.createAssembly = createAssembly; exports.prepareDefaultEnvironment = prepareDefaultEnvironment; exports.prepareContext = prepareContext; exports.guessExecutable = guessExecutable; exports.spaceAvailableForContext = spaceAvailableForContext; const childProcess = require("child_process"); const os = require("os"); const path = require("path"); const cxschema = require("@aws-cdk/cloud-assembly-schema"); const cxapi = require("@aws-cdk/cx-api"); const fs = require("fs-extra"); const semver = require("semver"); const user_configuration_1 = require("../../cli/user-configuration"); const version_1 = require("../../cli/version"); const logging_1 = require("../../logging"); const error_1 = require("../../toolkit/error"); const tree_1 = require("../../tree"); const objects_1 = require("../../util/objects"); const rwlock_1 = require("../util/rwlock"); /** Invokes the cloud executable and returns JSON output */ async function execProgram(aws, config) { const env = await prepareDefaultEnvironment(aws); const context = await prepareContext(config.settings, config.context.all, env); const build = config.settings.get(['build']); if (build) { await exec(build); } const app = config.settings.get(['app']); if (!app) { throw new error_1.ToolkitError(`--app is required either in command-line, in ${user_configuration_1.PROJECT_CONFIG} or in ${user_configuration_1.USER_DEFAULTS}`); } // bypass "synth" if app points to a cloud assembly if (await fs.pathExists(app) && (await fs.stat(app)).isDirectory()) { (0, logging_1.debug)('--app points to a cloud assembly, so we bypass synth'); // Acquire a read lock on this directory const lock = await new rwlock_1.RWLock(app).acquireRead(); return { assembly: createAssembly(app), lock }; } const commandLine = await guessExecutable(app); const outdir = config.settings.get(['output']); if (!outdir) { throw new error_1.ToolkitError('unexpected: --output is required'); } if (typeof outdir !== 'string') { throw new error_1.ToolkitError(`--output takes a string, got ${JSON.stringify(outdir)}`); } try { await fs.mkdirp(outdir); } catch (error) { throw new error_1.ToolkitError(`Could not create output directory ${outdir} (${error.message})`); } (0, logging_1.debug)('outdir:', outdir); env[cxapi.OUTDIR_ENV] = outdir; // Acquire a lock on the output directory const writerLock = await new rwlock_1.RWLock(outdir).acquireWrite(); try { // Send version information env[cxapi.CLI_ASM_VERSION_ENV] = cxschema.Manifest.version(); env[cxapi.CLI_VERSION_ENV] = (0, version_1.versionNumber)(); (0, logging_1.debug)('env:', env); const envVariableSizeLimit = os.platform() === 'win32' ? 32760 : 131072; const [smallContext, overflow] = (0, objects_1.splitBySize)(context, spaceAvailableForContext(env, envVariableSizeLimit)); // Store the safe part in the environment variable env[cxapi.CONTEXT_ENV] = JSON.stringify(smallContext); // If there was any overflow, write it to a temporary file let contextOverflowLocation; if (Object.keys(overflow ?? {}).length > 0) { const contextDir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-context')); contextOverflowLocation = path.join(contextDir, 'context-overflow.json'); fs.writeJSONSync(contextOverflowLocation, overflow); env[cxapi.CONTEXT_OVERFLOW_LOCATION_ENV] = contextOverflowLocation; } await exec(commandLine.join(' ')); const assembly = createAssembly(outdir); contextOverflowCleanup(contextOverflowLocation, assembly); return { assembly, lock: await writerLock.convertToReaderLock() }; } catch (e) { await writerLock.release(); throw e; } async function exec(commandAndArgs) { return new Promise((ok, fail) => { // We use a slightly lower-level interface to: // // - Pass arguments in an array instead of a string, to get around a // number of quoting issues introduced by the intermediate shell layer // (which would be different between Linux and Windows). // // - Inherit stderr from controlling terminal. We don't use the captured value // anyway, and if the subprocess is printing to it for debugging purposes the // user gets to see it sooner. Plus, capturing doesn't interact nicely with some // processes like Maven. const proc = childProcess.spawn(commandAndArgs, { stdio: ['ignore', 'inherit', 'inherit'], detached: false, shell: true, env: { ...process.env, ...env, }, }); proc.on('error', fail); proc.on('exit', code => { if (code === 0) { return ok(); } else { (0, logging_1.debug)('failed command:', commandAndArgs); return fail(new error_1.ToolkitError(`Subprocess exited with error ${code}`)); } }); }); } } /** * Creates an assembly with error handling */ function createAssembly(appDir) { try { return new cxapi.CloudAssembly(appDir, { // We sort as we deploy topoSort: false, }); } catch (error) { if (error.message.includes(cxschema.VERSION_MISMATCH)) { // this means the CLI version is too old. // we instruct the user to upgrade. throw new error_1.ToolkitError(`This CDK CLI is not compatible with the CDK library used by your application. Please upgrade the CLI to the latest version.\n(${error.message})`); } throw error; } } /** * If we don't have region/account defined in context, we fall back to the default SDK behavior * where region is retrieved from ~/.aws/config and account is based on default credentials provider * chain and then STS is queried. * * This is done opportunistically: for example, if we can't access STS for some reason or the region * is not configured, the context value will be 'null' and there could failures down the line. In * some cases, synthesis does not require region/account information at all, so that might be perfectly * fine in certain scenarios. * * @param context The context key/value bash. */ async function prepareDefaultEnvironment(aws, logFn = logging_1.debug) { const env = {}; env[cxapi.DEFAULT_REGION_ENV] = aws.defaultRegion; await logFn(`Setting "${cxapi.DEFAULT_REGION_ENV}" environment variable to`, env[cxapi.DEFAULT_REGION_ENV]); const accountId = (await aws.defaultAccount())?.accountId; if (accountId) { env[cxapi.DEFAULT_ACCOUNT_ENV] = accountId; await logFn(`Setting "${cxapi.DEFAULT_ACCOUNT_ENV}" environment variable to`, env[cxapi.DEFAULT_ACCOUNT_ENV]); } return env; } /** * Settings related to synthesis are read from context. * The merging of various configuration sources like cli args or cdk.json has already happened. * We now need to set the final values to the context. */ async function prepareContext(settings, context, env) { const debugMode = settings.get(['debug']) ?? true; if (debugMode) { env.CDK_DEBUG = 'true'; } const pathMetadata = settings.get(['pathMetadata']) ?? true; if (pathMetadata) { context[cxapi.PATH_METADATA_ENABLE_CONTEXT] = true; } const assetMetadata = settings.get(['assetMetadata']) ?? true; if (assetMetadata) { context[cxapi.ASSET_RESOURCE_METADATA_ENABLED_CONTEXT] = true; } const versionReporting = settings.get(['versionReporting']) ?? true; if (versionReporting) { context[cxapi.ANALYTICS_REPORTING_ENABLED_CONTEXT] = true; } // We need to keep on doing this for framework version from before this flag was deprecated. if (!versionReporting) { context['aws:cdk:disable-version-reporting'] = true; } const stagingEnabled = settings.get(['staging']) ?? true; if (!stagingEnabled) { context[cxapi.DISABLE_ASSET_STAGING_CONTEXT] = true; } const bundlingStacks = settings.get(['bundlingStacks']) ?? ['**']; context[cxapi.BUNDLING_STACKS] = bundlingStacks; (0, logging_1.debug)('context:', context); return context; } /** * Make sure the 'app' is an array * * If it's a string, split on spaces as a trivial way of tokenizing the command line. */ function appToArray(app) { return typeof app === 'string' ? app.split(' ') : app; } /** * Execute the given file with the same 'node' process as is running the current process */ function executeNode(scriptFile) { return [process.execPath, scriptFile]; } /** * Mapping of extensions to command-line generators */ const EXTENSION_MAP = new Map([ ['.js', executeNode], ]); /** * Guess the executable from the command-line argument * * Only do this if the file is NOT marked as executable. If it is, * we'll defer to the shebang inside the file itself. * * If we're on Windows, we ALWAYS take the handler, since it's hard to * verify if registry associations have or have not been set up for this * file type, so we'll assume the worst and take control. */ async function guessExecutable(app) { const commandLine = appToArray(app); if (commandLine.length === 1) { let fstat; try { fstat = await fs.stat(commandLine[0]); } catch { (0, logging_1.debug)(`Not a file: '${commandLine[0]}'. Using '${commandLine}' as command-line`); return commandLine; } // eslint-disable-next-line no-bitwise const isExecutable = (fstat.mode & fs.constants.X_OK) !== 0; const isWindows = process.platform === 'win32'; const handler = EXTENSION_MAP.get(path.extname(commandLine[0])); if (handler && (!isExecutable || isWindows)) { return handler(commandLine[0]); } } return commandLine; } function contextOverflowCleanup(location, assembly) { if (location) { fs.removeSync(path.dirname(location)); const tree = (0, tree_1.loadTree)(assembly); const frameworkDoesNotSupportContextOverflow = (0, tree_1.some)(tree, node => { const fqn = node.constructInfo?.fqn; const version = node.constructInfo?.version; return (fqn === 'aws-cdk-lib.App' && version != null && semver.lte(version, '2.38.0')) || fqn === '@aws-cdk/core.App'; // v1 }); // We're dealing with an old version of the framework here. It is unaware of the temporary // file, which means that it will ignore the context overflow. if (frameworkDoesNotSupportContextOverflow) { (0, logging_1.warning)('Part of the context could not be sent to the application. Please update the AWS CDK library to the latest version.'); } } } function spaceAvailableForContext(env, limit) { const size = (value) => value != null ? Buffer.byteLength(value) : 0; const usedSpace = Object.entries(env) .map(([k, v]) => k === cxapi.CONTEXT_ENV ? size(k) : size(k) + size(v)) .reduce((a, b) => a + b, 0); return Math.max(0, limit - usedSpace); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImV4ZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUF1QkEsa0NBaUhDO0FBS0Qsd0NBY0M7QUFjRCw4REFnQkM7QUFPRCx3Q0FnQ0M7QUFxQ0QsMENBc0JDO0FBc0JELDREQVFDO0FBelRELDhDQUE4QztBQUM5Qyx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLDJEQUEyRDtBQUMzRCx5Q0FBeUM7QUFDekMsK0JBQStCO0FBQy9CLGlDQUFpQztBQUNqQyxxRUFBNEY7QUFDNUYsK0NBQWtEO0FBQ2xELDJDQUErQztBQUMvQywrQ0FBbUQ7QUFDbkQscUNBQTRDO0FBQzVDLGdEQUFpRDtBQUdqRCwyQ0FBK0M7QUFPL0MsMkRBQTJEO0FBQ3BELEtBQUssVUFBVSxXQUFXLENBQUMsR0FBZ0IsRUFBRSxNQUFxQjtJQUN2RSxNQUFNLEdBQUcsR0FBRyxNQUFNLHlCQUF5QixDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ2pELE1BQU0sT0FBTyxHQUFHLE1BQU0sY0FBYyxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFFL0UsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQzdDLElBQUksS0FBSyxFQUFFLENBQUM7UUFDVixNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNwQixDQUFDO0lBRUQsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3pDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNULE1BQU0sSUFBSSxvQkFBWSxDQUFDLGdEQUFnRCxtQ0FBYyxVQUFVLGtDQUFhLEVBQUUsQ0FBQyxDQUFDO0lBQ2xILENBQUM7SUFFRCxtREFBbUQ7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TyxDQUFDLEdBQUcsQ0FBQztTQUNsQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN0RSxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRTlCLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsS0FBSyxHQUFHLFNBQVMsQ0FBQyxDQUFDO0FBQ3hDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjaGlsZFByb2Nlc3MgZnJvbSAnY2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgY3hzY2hlbWEgZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktc2NoZW1hJztcbmltcG9ydCAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgKiBhcyBzZW12ZXIgZnJvbSAnc2VtdmVyJztcbmltcG9ydCB7IENvbmZpZ3VyYXRpb24sIFBST0pFQ1RfQ09ORklHLCBVU0VSX0RFRkFVTFRTIH0gZnJvbSAnLi4vLi4vY2xpL3VzZXItY29uZmlndXJhdGlvbic7XG5pbXBvcnQgeyB2ZXJzaW9uTnVtYmVyIH0gZnJvbSAnLi4vLi4vY2xpL3ZlcnNpb24nO1xuaW1wb3J0IHsgZGVidWcsIHdhcm5pbmcgfSBmcm9tICcuLi8uLi9sb2dnaW5nJztcbmltcG9ydCB7IFRvb2xraXRFcnJvciB9IGZyb20gJy4uLy4uL3Rvb2xraXQvZXJyb3InO1xuaW1wb3J0IHsgbG9hZFRyZWUsIHNvbWUgfSBmcm9tICcuLi8uLi90cmVlJztcbmltcG9ydCB7IHNwbGl0QnlTaXplIH0gZnJvbSAnLi4vLi4vdXRpbC9vYmplY3RzJztcbmltcG9ydCB7IFNka1Byb3ZpZGVyIH0gZnJvbSAnLi4vYXdzLWF1dGgnO1xuaW1wb3J0IHsgU2V0dGluZ3MgfSBmcm9tICcuLi9zZXR0aW5ncyc7XG5pbXBvcnQgeyBSV0xvY2ssIElMb2NrIH0gZnJvbSAnLi4vdXRpbC9yd2xvY2snO1xuXG5leHBvcnQgaW50ZXJmYWNlIEV4ZWNQcm9ncmFtUmVzdWx0IHtcbiAgcmVhZG9ubHkgYXNzZW1ibHk6IGN4YXBpLkNsb3VkQXNzZW1ibHk7XG4gIHJlYWRvbmx5IGxvY2s6IElMb2NrO1xufVxuXG4vKiogSW52b2tlcyB0aGUgY2xvdWQgZXhlY3V0YWJsZSBhbmQgcmV0dXJucyBKU09OIG91dHB1dCAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGV4ZWNQcm9ncmFtKGF3czogU2RrUHJvdmlkZXIsIGNvbmZpZzogQ29uZmlndXJhdGlvbik6IFByb21pc2U8RXhlY1Byb2dyYW1SZXN1bHQ+IHtcbiAgY29uc3QgZW52ID0gYXdhaXQgcHJlcGFyZURlZmF1bHRFbnZpcm9ubWVudChhd3MpO1xuICBjb25zdCBjb250ZXh0ID0gYXdhaXQgcHJlcGFyZUNvbnRleHQoY29uZmlnLnNldHRpbmdzLCBjb25maWcuY29udGV4dC5hbGwsIGVudik7XG5cbiAgY29uc3QgYnVpbGQgPSBjb25maWcuc2V0dGluZ3MuZ2V0KFsnYnVpbGQnXSk7XG4gIGlmIChidWlsZCkge1xuICAgIGF3YWl0IGV4ZWMoYnVpbGQpO1xuICB9XG5cbiAgY29uc3QgYXBwID0gY29uZmlnLnNldHRpbmdzLmdldChbJ2FwcCddKTtcbiAgaWYgKCFhcHApIHtcbiAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKGAtLWFwcCBpcyByZXF1aXJlZCBlaXRoZXIgaW4gY29tbWFuZC1saW5lLCBpbiAke1BST0pFQ1RfQ09ORklHfSBvciBpbiAke1VTRVJfREVGQVVMVFN9YCk7XG4gIH1cblxuICAvLyBieXBhc3MgXCJzeW50aFwiIGlmIGFwcCBwb2ludHMgdG8gYSBjbG91ZCBhc3NlbWJseVxuICBpZiAoYXdhaXQgZnMucGF0aEV4aXN0cyhhcHApICYmIChhd2FpdCBmcy5zdGF0KGFwcCkpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICBkZWJ1ZygnLS1hcHAgcG9pbnRzIHRvIGEgY2xvdWQgYXNzZW1ibHksIHNvIHdlIGJ5cGFzcyBzeW50aCcpO1xuXG4gICAgLy8gQWNxdWlyZSBhIHJlYWQgbG9jayBvbiB0aGlzIGRpcmVjdG9yeVxuICAgIGNvbnN0IGxvY2sgPSBhd2FpdCBuZXcgUldMb2NrKGFwcCkuYWNxdWlyZVJlYWQoKTtcblxuICAgIHJldHVybiB7IGFzc2VtYmx5OiBjcmVhdGVBc3NlbWJseShhcHApLCBsb2NrIH07XG4gIH1cblxuICBjb25zdCBjb21tYW5kTGluZSA9IGF3YWl0IGd1ZXNzRXhlY3V0YWJsZShhcHApO1xuXG4gIGNvbnN0IG91dGRpciA9IGNvbmZpZy5zZXR0aW5ncy5nZXQoWydvdXRwdXQnXSk7XG4gIGlmICghb3V0ZGlyKSB7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcigndW5leHBlY3RlZDogLS1vdXRwdXQgaXMgcmVxdWlyZWQnKTtcbiAgfVxuICBpZiAodHlwZW9mIG91dGRpciAhPT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgVG9vbGtpdEVycm9yKGAtLW91dHB1dCB0YWtlcyBhIHN0cmluZywgZ290ICR7SlNPTi5zdHJpbmdpZnkob3V0ZGlyKX1gKTtcbiAgfVxuICB0cnkge1xuICAgIGF3YWl0IGZzLm1rZGlycChvdXRkaXIpO1xuICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihgQ291bGQgbm90IGNyZWF0ZSBvdXRwdXQgZGlyZWN0b3J5ICR7b3V0ZGlyfSAoJHtlcnJvci5tZXNzYWdlfSlgKTtcbiAgfVxuXG4gIGRlYnVnKCdvdXRkaXI6Jywgb3V0ZGlyKTtcbiAgZW52W2N4YXBpLk9VVERJUl9FTlZdID0gb3V0ZGlyO1xuXG4gIC8vIEFjcXVpcmUgYSBsb2NrIG9uIHRoZSBvdXRwdXQgZGlyZWN0b3J5XG4gIGNvbnN0IHdyaXRlckxvY2sgPSBhd2FpdCBuZXcgUldMb2NrKG91dGRpcikuYWNxdWlyZVdyaXRlKCk7XG5cbiAgdHJ5IHtcbiAgICAvLyBTZW5kIHZlcnNpb24gaW5mb3JtYXRpb25cbiAgICBlbnZbY3hhcGkuQ0xJX0FTTV9WRVJTSU9OX0VOVl0gPSBjeHNjaGVtYS5NYW5pZmVzdC52ZXJzaW9uKCk7XG4gICAgZW52W2N4YXBpLkNMSV9WRVJTSU9OX0VOVl0gPSB2ZXJzaW9uTnVtYmVyKCk7XG5cbiAgICBkZWJ1ZygnZW52OicsIGVudik7XG5cbiAgICBjb25zdCBlbnZWYXJpYWJsZVNpemVMaW1pdCA9IG9zLnBsYXRmb3JtKCkgPT09ICd3aW4zMicgPyAzMjc2MCA6IDEzMTA3MjtcbiAgICBjb25zdCBbc21hbGxDb250ZXh0LCBvdmVyZmxvd10gPSBzcGxpdEJ5U2l6ZShjb250ZXh0LCBzcGFjZUF2YWlsYWJsZUZvckNvbnRleHQoZW52LCBlbnZWYXJpYWJsZVNpemVMaW1pdCkpO1xuXG4gICAgLy8gU3RvcmUgdGhlIHNhZmUgcGFydCBpbiB0aGUgZW52aXJvbm1lbnQgdmFyaWFibGVcbiAgICBlbnZbY3hhcGkuQ09OVEVYVF9FTlZdID0gSlNPTi5zdHJpbmdpZnkoc21hbGxDb250ZXh0KTtcblxuICAgIC8vIElmIHRoZXJlIHdhcyBhbnkgb3ZlcmZsb3csIHdyaXRlIGl0IHRvIGEgdGVtcG9yYXJ5IGZpbGVcbiAgICBsZXQgY29udGV4dE92ZXJmbG93TG9jYXRpb247XG4gICAgaWYgKE9iamVjdC5rZXlzKG92ZXJmbG93ID8/IHt9KS5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBjb250ZXh0RGlyID0gYXdhaXQgZnMubWtkdGVtcChwYXRoLmpvaW4ob3MudG1wZGlyKCksICdjZGstY29udGV4dCcpKTtcbiAgICAgIGNvbnRleHRPdmVyZmxvd0xvY2F0aW9uID0gcGF0aC5qb2luKGNvbnRleHREaXIsICdjb250ZXh0LW92ZXJmbG93Lmpzb24nKTtcbiAgICAgIGZzLndyaXRlSlNPTlN5bmMoY29udGV4dE92ZXJmbG93TG9jYXRpb24sIG92ZXJmbG93KTtcbiAgICAgIGVudltjeGFwaS5DT05URVhUX09WRVJGTE9XX0xPQ0FUSU9OX0VOVl0gPSBjb250ZXh0T3ZlcmZsb3dMb2NhdGlvbjtcbiAgICB9XG5cbiAgICBhd2FpdCBleGVjKGNvbW1hbmRMaW5lLmpvaW4oJyAnKSk7XG5cbiAgICBjb25zdCBhc3NlbWJseSA9IGNyZWF0ZUFzc2VtYmx5KG91dGRpcik7XG5cbiAgICBjb250ZXh0T3ZlcmZsb3dDbGVhbnVwKGNvbnRleHRPdmVyZmxvd0xvY2F0aW9uLCBhc3NlbWJseSk7XG5cbiAgICByZXR1cm4geyBhc3NlbWJseSwgbG9jazogYXdhaXQgd3JpdGVyTG9jay5jb252ZXJ0VG9SZWFkZXJMb2NrKCkgfTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGF3YWl0IHdyaXRlckxvY2sucmVsZWFzZSgpO1xuICAgIHRocm93IGU7XG4gIH1cblxuICBhc3luYyBmdW5jdGlvbiBleGVjKGNvbW1hbmRBbmRBcmdzOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKG9rLCBmYWlsKSA9PiB7XG4gICAgICAvLyBXZSB1c2UgYSBzbGlnaHRseSBsb3dlci1sZXZlbCBpbnRlcmZhY2UgdG86XG4gICAgICAvL1xuICAgICAgLy8gLSBQYXNzIGFyZ3VtZW50cyBpbiBhbiBhcnJheSBpbnN0ZWFkIG9mIGEgc3RyaW5nLCB0byBnZXQgYXJvdW5kIGFcbiAgICAgIC8vICAgbnVtYmVyIG9mIHF1b3RpbmcgaXNzdWVzIGludHJvZHVjZWQgYnkgdGhlIGludGVybWVkaWF0ZSBzaGVsbCBsYXllclxuICAgICAgLy8gICAod2hpY2ggd291bGQgYmUgZGlmZmVyZW50IGJldHdlZW4gTGludXggYW5kIFdpbmRvd3MpLlxuICAgICAgLy9cbiAgICAgIC8vIC0gSW5oZXJpdCBzdGRlcnIgZnJvbSBjb250cm9sbGluZyB0ZXJtaW5hbC4gV2UgZG9uJ3QgdXNlIHRoZSBjYXB0dXJlZCB2YWx1ZVxuICAgICAgLy8gICBhbnl3YXksIGFuZCBpZiB0aGUgc3VicHJvY2VzcyBpcyBwcmludGluZyB0byBpdCBmb3IgZGVidWdnaW5nIHB1cnBvc2VzIHRoZVxuICAgICAgLy8gICB1c2VyIGdldHMgdG8gc2VlIGl0IHNvb25lci4gUGx1cywgY2FwdHVyaW5nIGRvZXNuJ3QgaW50ZXJhY3QgbmljZWx5IHdpdGggc29tZVxuICAgICAgLy8gICBwcm9jZXNzZXMgbGlrZSBNYXZlbi5cbiAgICAgIGNvbnN0IHByb2MgPSBjaGlsZFByb2Nlc3Muc3Bhd24oY29tbWFuZEFuZEFyZ3MsIHtcbiAgICAgICAgc3RkaW86IFsnaWdub3JlJywgJ2luaGVyaXQnLCAnaW5oZXJpdCddLFxuICAgICAgICBkZXRhY2hlZDogZmFsc2UsXG4gICAgICAgIHNoZWxsOiB0cnVlLFxuICAgICAgICBlbnY6IHtcbiAgICAgICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgICAgICAuLi5lbnYsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgcHJvYy5vbignZXJyb3InLCBmYWlsKTtcblxuICAgICAgcHJvYy5vbignZXhpdCcsIGNvZGUgPT4ge1xuICAgICAgICBpZiAoY29kZSA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBvaygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRlYnVnKCdmYWlsZWQgY29tbWFuZDonLCBjb21tYW5kQW5kQXJncyk7XG4gICAgICAgICAgcmV0dXJuIGZhaWwobmV3IFRvb2xraXRFcnJvcihgU3VicHJvY2VzcyBleGl0ZWQgd2l0aCBlcnJvciAke2NvZGV9YCkpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXNzZW1ibHkgd2l0aCBlcnJvciBoYW5kbGluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQXNzZW1ibHkoYXBwRGlyOiBzdHJpbmcpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbmV3IGN4YXBpLkNsb3VkQXNzZW1ibHkoYXBwRGlyLCB7XG4gICAgICAvLyBXZSBzb3J0IGFzIHdlIGRlcGxveVxuICAgICAgdG9wb1NvcnQ6IGZhbHNlLFxuICAgIH0pO1xuICB9IGNhdGNoIChlcnJvcjogYW55KSB7XG4gICAgaWYgKGVycm9yLm1lc3NhZ2UuaW5jbHVkZXMoY3hzY2hlbWEuVkVSU0lPTl9NSVNNQVRDSCkpIHtcbiAgICAgIC8vIHRoaXMgbWVhbnMgdGhlIENMSSB2ZXJzaW9uIGlzIHRvbyBvbGQuXG4gICAgICAvLyB3ZSBpbnN0cnVjdCB0aGUgdXNlciB0byB1cGdyYWRlLlxuICAgICAgdGhyb3cgbmV3IFRvb2xraXRFcnJvcihgVGhpcyBDREsgQ0xJIGlzIG5vdCBjb21wYXRpYmxlIHdpdGggdGhlIENESyBsaWJyYXJ5IHVzZWQgYnkgeW91ciBhcHBsaWNhdGlvbi4gUGxlYXNlIHVwZ3JhZGUgdGhlIENMSSB0byB0aGUgbGF0ZXN0IHZlcnNpb24uXFxuKCR7ZXJyb3IubWVzc2FnZX0pYCk7XG4gICAgfVxuICAgIHRocm93IGVycm9yO1xuICB9XG59XG5cbi8qKlxuICogSWYgd2UgZG9uJ3QgaGF2ZSByZWdpb24vYWNjb3VudCBkZWZpbmVkIGluIGNvbnRleHQsIHdlIGZhbGwgYmFjayB0byB0aGUgZGVmYXVsdCBTREsgYmVoYXZpb3JcbiAqIHdoZXJlIHJlZ2lvbiBpcyByZXRyaWV2ZWQgZnJvbSB+Ly5hd3MvY29uZmlnIGFuZCBhY2NvdW50IGlzIGJhc2VkIG9uIGRlZmF1bHQgY3JlZGVudGlhbHMgcHJvdmlkZXJcbiAqIGNoYWluIGFuZCB0aGVuIFNUUyBpcyBxdWVyaWVkLlxuICpcbiAqIFRoaXMgaXMgZG9uZSBvcHBvcnR1bmlzdGljYWxseTogZm9yIGV4YW1wbGUsIGlmIHdlIGNhbid0IGFjY2VzcyBTVFMgZm9yIHNvbWUgcmVhc29uIG9yIHRoZSByZWdpb25cbiAqIGlzIG5vdCBjb25maWd1cmVkLCB0aGUgY29udGV4dCB2YWx1ZSB3aWxsIGJlICdudWxsJyBhbmQgdGhlcmUgY291bGQgZmFpbHVyZXMgZG93biB0aGUgbGluZS4gSW5cbiAqIHNvbWUgY2FzZXMsIHN5bnRoZXNpcyBkb2VzIG5vdCByZXF1aXJlIHJlZ2lvbi9hY2NvdW50IGluZm9ybWF0aW9uIGF0IGFsbCwgc28gdGhhdCBtaWdodCBiZSBwZXJmZWN0bHlcbiAqIGZpbmUgaW4gY2VydGFpbiBzY2VuYXJpb3MuXG4gKlxuICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQga2V5L3ZhbHVlIGJhc2guXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcmVwYXJlRGVmYXVsdEVudmlyb25tZW50KFxuICBhd3M6IFNka1Byb3ZpZGVyLFxuICBsb2dGbjogKG1zZzogc3RyaW5nLCAuLi5hcmdzOiBhbnkpID0+IGFueSA9IGRlYnVnLFxuKTogUHJvbWlzZTx7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9PiB7XG4gIGNvbnN0IGVudjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHsgfTtcblxuICBlbnZbY3hhcGkuREVGQVVMVF9SRUdJT05fRU5WXSA9IGF3cy5kZWZhdWx0UmVnaW9uO1xuICBhd2FpdCBsb2dGbihgU2V0dGluZyBcIiR7Y3hhcGkuREVGQVVMVF9SRUdJT05fRU5WfVwiIGVudmlyb25tZW50IHZhcmlhYmxlIHRvYCwgZW52W2N4YXBpLkRFRkFVTFRfUkVHSU9OX0VOVl0pO1xuXG4gIGNvbnN0IGFjY291bnRJZCA9IChhd2FpdCBhd3MuZGVmYXVsdEFjY291bnQoKSk/LmFjY291bnRJZDtcbiAgaWYgKGFjY291bnRJZCkge1xuICAgIGVudltjeGFwaS5ERUZBVUxUX0FDQ09VTlRfRU5WXSA9IGFjY291bnRJZDtcbiAgICBhd2FpdCBsb2dGbihgU2V0dGluZyBcIiR7Y3hhcGkuREVGQVVMVF9BQ0NPVU5UX0VOVn1cIiBlbnZpcm9ubWVudCB2YXJpYWJsZSB0b2AsIGVudltjeGFwaS5ERUZBVUxUX0FDQ09VTlRfRU5WXSk7XG4gIH1cblxuICByZXR1cm4gZW52O1xufVxuXG4vKipcbiAqIFNldHRpbmdzIHJlbGF0ZWQgdG8gc3ludGhlc2lzIGFyZSByZWFkIGZyb20gY29udGV4dC5cbiAqIFRoZSBtZXJnaW5nIG9mIHZhcmlvdXMgY29uZmlndXJhdGlvbiBzb3VyY2VzIGxpa2UgY2xpIGFyZ3Mgb3IgY2RrLmpzb24gaGFzIGFscmVhZHkgaGFwcGVuZWQuXG4gKiBXZSBub3cgbmVlZCB0byBzZXQgdGhlIGZpbmFsIHZhbHVlcyB0byB0aGUgY29udGV4dC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByZXBhcmVDb250ZXh0KHNldHRpbmdzOiBTZXR0aW5ncywgY29udGV4dDoge1trZXk6IHN0cmluZ106IGFueX0sIGVudjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCB1bmRlZmluZWR9KSB7XG4gIGNvbnN0IGRlYnVnTW9kZTogYm9vbGVhbiA9IHNldHRpbmdzLmdldChbJ2RlYnVnJ10pID8/IHRydWU7XG4gIGlmIChkZWJ1Z01vZGUpIHtcbiAgICBlbnYuQ0RLX0RFQlVHID0gJ3RydWUnO1xuICB9XG5cbiAgY29uc3QgcGF0aE1ldGFkYXRhOiBib29sZWFuID0gc2V0dGluZ3MuZ2V0KFsncGF0aE1ldGFkYXRhJ10pID8/IHRydWU7XG4gIGlmIChwYXRoTWV0YWRhdGEpIHtcbiAgICBjb250ZXh0W2N4YXBpLlBBVEhfTUVUQURBVEFfRU5BQkxFX0NPTlRFWFRdID0gdHJ1ZTtcbiAgfVxuXG4gIGNvbnN0IGFzc2V0TWV0YWRhdGE6IGJvb2xlYW4gPSBzZXR0aW5ncy5nZXQoWydhc3NldE1ldGFkYXRhJ10pID8/IHRydWU7XG4gIGlmIChhc3NldE1ldGFkYXRhKSB7XG4gICAgY29udGV4dFtjeGFwaS5BU1NFVF9SRVNPVVJDRV9NRVRBREFUQV9FTkFCTEVEX0NPTlRFWFRdID0gdHJ1ZTtcbiAgfVxuXG4gIGNvbnN0IHZlcnNpb25SZXBvcnRpbmc6IGJvb2xlYW4gPSBzZXR0aW5ncy5nZXQoWyd2ZXJzaW9uUmVwb3J0aW5nJ10pID8/IHRydWU7XG4gIGlmICh2ZXJzaW9uUmVwb3J0aW5nKSB7IGNvbnRleHRbY3hhcGkuQU5BTFlUSUNTX1JFUE9SVElOR19FTkFCTEVEX0NPTlRFWFRdID0gdHJ1ZTsgfVxuICAvLyBXZSBuZWVkIHRvIGtlZXAgb24gZG9pbmcgdGhpcyBmb3IgZnJhbWV3b3JrIHZlcnNpb24gZnJvbSBiZWZvcmUgdGhpcyBmbGFnIHdhcyBkZXByZWNhdGVkLlxuICBpZiAoIXZlcnNpb25SZXBvcnRpbmcpIHsgY29udGV4dFsnYXdzOmNkazpkaXNhYmxlLXZlcnNpb24tcmVwb3J0aW5nJ10gPSB0cnVlOyB9XG5cbiAgY29uc3Qgc3RhZ2luZ0VuYWJsZWQgPSBzZXR0aW5ncy5nZXQoWydzdGFnaW5nJ10pID8/IHRydWU7XG4gIGlmICghc3RhZ2luZ0VuYWJsZWQpIHtcbiAgICBjb250ZXh0W2N4YXBpLkRJU0FCTEVfQVNTRVRfU1RBR0lOR19DT05URVhUXSA9IHRydWU7XG4gIH1cblxuICBjb25zdCBidW5kbGluZ1N0YWNrcyA9IHNldHRpbmdzLmdldChbJ2J1bmRsaW5nU3RhY2tzJ10pID8/IFsnKionXTtcbiAgY29udGV4dFtjeGFwaS5CVU5ETElOR19TVEFDS1NdID0gYnVuZGxpbmdTdGFja3M7XG5cbiAgZGVidWcoJ2NvbnRleHQ6JywgY29udGV4dCk7XG5cbiAgcmV0dXJuIGNvbnRleHQ7XG59XG5cbi8qKlxuICogTWFrZSBzdXJlIHRoZSAnYXBwJyBpcyBhbiBhcnJheVxuICpcbiAqIElmIGl0J3MgYSBzdHJpbmcsIHNwbGl0IG9uIHNwYWNlcyBhcyBhIHRyaXZpYWwgd2F5IG9mIHRva2VuaXppbmcgdGhlIGNvbW1hbmQgbGluZS5cbiAqL1xuZnVuY3Rpb24gYXBwVG9BcnJheShhcHA6IGFueSkge1xuICByZXR1cm4gdHlwZW9mIGFwcCA9PT0gJ3N0cmluZycgPyBhcHAuc3BsaXQoJyAnKSA6IGFwcDtcbn1cblxudHlwZSBDb21tYW5kR2VuZXJhdG9yID0gKGZpbGU6IHN0cmluZykgPT4gc3RyaW5nW107XG5cbi8qKlxuICogRXhlY3V0ZSB0aGUgZ2l2ZW4gZmlsZSB3aXRoIHRoZSBzYW1lICdub2RlJyBwcm9jZXNzIGFzIGlzIHJ1bm5pbmcgdGhlIGN1cnJlbnQgcHJvY2Vzc1xuICovXG5mdW5jdGlvbiBleGVjdXRlTm9kZShzY3JpcHRGaWxlOiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBbcHJvY2Vzcy5leGVjUGF0aCwgc2NyaXB0RmlsZV07XG59XG5cbi8qKlxuICogTWFwcGluZyBvZiBleHRlbnNpb25zIHRvIGNvbW1hbmQtbGluZSBnZW5lcmF0b3JzXG4gKi9cbmNvbnN0IEVYVEVOU0lPTl9NQVAgPSBuZXcgTWFwPHN0cmluZywgQ29tbWFuZEdlbmVyYXRvcj4oW1xuICBbJy5qcycsIGV4ZWN1dGVOb2RlXSxcbl0pO1xuXG4vKipcbiAqIEd1ZXNzIHRoZSBleGVjdXRhYmxlIGZyb20gdGhlIGNvbW1hbmQtbGluZSBhcmd1bWVudFxuICpcbiAqIE9ubHkgZG8gdGhpcyBpZiB0aGUgZmlsZSBpcyBOT1QgbWFya2VkIGFzIGV4ZWN1dGFibGUuIElmIGl0IGlzLFxuICogd2UnbGwgZGVmZXIgdG8gdGhlIHNoZWJhbmcgaW5zaWRlIHRoZSBmaWxlIGl0c2VsZi5cbiAqXG4gKiBJZiB3ZSdyZSBvbiBXaW5kb3dzLCB3ZSBBTFdBWVMgdGFrZSB0aGUgaGFuZGxlciwgc2luY2UgaXQncyBoYXJkIHRvXG4gKiB2ZXJpZnkgaWYgcmVnaXN0cnkgYXNzb2NpYXRpb25zIGhhdmUgb3IgaGF2ZSBub3QgYmVlbiBzZXQgdXAgZm9yIHRoaXNcbiAqIGZpbGUgdHlwZSwgc28gd2UnbGwgYXNzdW1lIHRoZSB3b3JzdCBhbmQgdGFrZSBjb250cm9sLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ3Vlc3NFeGVjdXRhYmxlKGFwcDogc3RyaW5nKSB7XG4gIGNvbnN0IGNvbW1hbmRMaW5lID0gYXBwVG9BcnJheShhcHApO1xuICBpZiAoY29tbWFuZExpbmUubGVuZ3RoID09PSAxKSB7XG4gICAgbGV0IGZzdGF0O1xuXG4gICAgdHJ5IHtcbiAgICAgIGZzdGF0ID0gYXdhaXQgZnMuc3RhdChjb21tYW5kTGluZVswXSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBkZWJ1ZyhgTm90IGEgZmlsZTogJyR7Y29tbWFuZExpbmVbMF19Jy4gVXNpbmcgJyR7Y29tbWFuZExpbmV9JyBhcyBjb21tYW5kLWxpbmVgKTtcbiAgICAgIHJldHVybiBjb21tYW5kTGluZTtcbiAgICB9XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgIGNvbnN0IGlzRXhlY3V0YWJsZSA9IChmc3RhdC5tb2RlICYgZnMuY29uc3RhbnRzLlhfT0spICE9PSAwO1xuICAgIGNvbnN0IGlzV2luZG93cyA9IHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMic7XG5cbiAgICBjb25zdCBoYW5kbGVyID0gRVhURU5TSU9OX01BUC5nZXQocGF0aC5leHRuYW1lKGNvbW1hbmRMaW5lWzBdKSk7XG4gICAgaWYgKGhhbmRsZXIgJiYgKCFpc0V4ZWN1dGFibGUgfHwgaXNXaW5kb3dzKSkge1xuICAgICAgcmV0dXJuIGhhbmRsZXIoY29tbWFuZExpbmVbMF0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gY29tbWFuZExpbmU7XG59XG5cbmZ1bmN0aW9uIGNvbnRleHRPdmVyZmxvd0NsZWFudXAobG9jYXRpb246IHN0cmluZyB8IHVuZGVmaW5lZCwgYXNzZW1ibHk6IGN4YXBpLkNsb3VkQXNzZW1ibHkpIHtcbiAgaWYgKGxvY2F0aW9uKSB7XG4gICAgZnMucmVtb3ZlU3luYyhwYXRoLmRpcm5hbWUobG9jYXRpb24pKTtcblxuICAgIGNvbnN0IHRyZWUgPSBsb2FkVHJlZShhc3NlbWJseSk7XG4gICAgY29uc3QgZnJhbWV3b3JrRG9lc05vdFN1cHBvcnRDb250ZXh0T3ZlcmZsb3cgPSBzb21lKHRyZWUsIG5vZGUgPT4ge1xuICAgICAgY29uc3QgZnFuID0gbm9kZS5jb25zdHJ1Y3RJbmZvPy5mcW47XG4gICAgICBjb25zdCB2ZXJzaW9uID0gbm9kZS5jb25zdHJ1Y3RJbmZvPy52ZXJzaW9uO1xuICAgICAgcmV0dXJuIChmcW4gPT09ICdhd3MtY2RrLWxpYi5BcHAnICYmIHZlcnNpb24gIT0gbnVsbCAmJiBzZW12ZXIubHRlKHZlcnNpb24sICcyLjM4LjAnKSlcbiAgICAgICAgfHwgZnFuID09PSAnQGF3cy1jZGsvY29yZS5BcHAnOyAvLyB2MVxuICAgIH0pO1xuXG4gICAgLy8gV2UncmUgZGVhbGluZyB3aXRoIGFuIG9sZCB2ZXJzaW9uIG9mIHRoZSBmcmFtZXdvcmsgaGVyZS4gSXQgaXMgdW5hd2FyZSBvZiB0aGUgdGVtcG9yYXJ5XG4gICAgLy8gZmlsZSwgd2hpY2ggbWVhbnMgdGhhdCBpdCB3aWxsIGlnbm9yZSB0aGUgY29udGV4dCBvdmVyZmxvdy5cbiAgICBpZiAoZnJhbWV3b3JrRG9lc05vdFN1cHBvcnRDb250ZXh0T3ZlcmZsb3cpIHtcbiAgICAgIHdhcm5pbmcoJ1BhcnQgb2YgdGhlIGNvbnRleHQgY291bGQgbm90IGJlIHNlbnQgdG8gdGhlIGFwcGxpY2F0aW9uLiBQbGVhc2UgdXBkYXRlIHRoZSBBV1MgQ0RLIGxpYnJhcnkgdG8gdGhlIGxhdGVzdCB2ZXJzaW9uLicpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc3BhY2VBdmFpbGFibGVGb3JDb250ZXh0KGVudjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSwgbGltaXQ6IG51bWJlcikge1xuICBjb25zdCBzaXplID0gKHZhbHVlOiBzdHJpbmcpID0+IHZhbHVlICE9IG51bGwgPyBCdWZmZXIuYnl0ZUxlbmd0aCh2YWx1ZSkgOiAwO1xuXG4gIGNvbnN0IHVzZWRTcGFjZSA9IE9iamVjdC5lbnRyaWVzKGVudilcbiAgICAubWFwKChbaywgdl0pID0+IGsgPT09IGN4YXBpLkNPTlRFWFRfRU5WID8gc2l6ZShrKSA6IHNpemUoaykgKyBzaXplKHYpKVxuICAgIC5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTtcblxuICByZXR1cm4gTWF0aC5tYXgoMCwgbGltaXQgLSB1c2VkU3BhY2UpO1xufVxuIl19