aws-cdk
Version:
AWS CDK CLI, the command line tool for CDK apps
418 lines • 58.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.handleFlags = handleFlags;
exports.displayFlags = displayFlags;
const path = require("path");
const toolkit_lib_1 = require("@aws-cdk/toolkit-lib");
const chalk = require("chalk");
// @ts-ignore
const enquirer_1 = require("enquirer");
const fs = require("fs-extra");
const api_1 = require("../api");
const obsolete_flags_1 = require("../obsolete-flags");
var FlagsMenuOptions;
(function (FlagsMenuOptions) {
FlagsMenuOptions["ALL_TO_RECOMMENDED"] = "Set all flags to recommended values";
FlagsMenuOptions["UNCONFIGURED_TO_RECOMMENDED"] = "Set unconfigured flags to recommended values";
FlagsMenuOptions["UNCONFIGURED_TO_DEFAULT"] = "Set unconfigured flags to their implied configuration (record current behavior)";
FlagsMenuOptions["MODIFY_SPECIFIC_FLAG"] = "Modify a specific flag";
FlagsMenuOptions["EXIT"] = "Exit";
})(FlagsMenuOptions || (FlagsMenuOptions = {}));
async function handleFlags(flagData, ioHelper, options, toolkit) {
flagData = flagData.filter(flag => !obsolete_flags_1.OBSOLETE_FLAGS.includes(flag.name));
let params = {
flagData,
toolkit,
ioHelper,
recommended: options.recommended,
all: options.all,
value: options.value,
flagName: options.FLAGNAME,
default: options.default,
unconfigured: options.unconfigured,
};
const interactiveOptions = Object.values(FlagsMenuOptions);
if (options.interactive) {
const prompt = new enquirer_1.Select({
name: 'option',
message: 'Menu',
choices: interactiveOptions,
});
const answer = await prompt.run();
if (answer == FlagsMenuOptions.ALL_TO_RECOMMENDED) {
params = {
...params,
recommended: true,
all: true,
};
await setMultipleFlags(params);
}
else if (answer == FlagsMenuOptions.UNCONFIGURED_TO_RECOMMENDED) {
params = {
...params,
recommended: true,
unconfigured: true,
};
await setMultipleFlags(params);
}
else if (answer == FlagsMenuOptions.UNCONFIGURED_TO_DEFAULT) {
params = {
...params,
default: true,
unconfigured: true,
};
await setMultipleFlags(params);
}
else if (answer == FlagsMenuOptions.MODIFY_SPECIFIC_FLAG) {
await setFlag(params, true);
}
else if (answer == FlagsMenuOptions.EXIT) {
return;
}
return;
}
if (options.FLAGNAME && options.all) {
await ioHelper.defaults.error('Error: Cannot use both --all and a specific flag name. Please use either --all to show all flags or specify a single flag name.');
return;
}
if ((options.value || options.recommended || options.default || options.unconfigured) && !options.set) {
await ioHelper.defaults.error('Error: This option can only be used with --set.');
return;
}
if (options.value && !options.FLAGNAME) {
await ioHelper.defaults.error('Error: --value requires a specific flag name. Please specify a flag name when providing a value.');
return;
}
if (options.recommended && options.default) {
await ioHelper.defaults.error('Error: Cannot use both --recommended and --default. Please choose one option.');
return;
}
if (options.unconfigured && options.all) {
await ioHelper.defaults.error('Error: Cannot use both --unconfigured and --all. Please choose one option.');
return;
}
if (options.unconfigured && options.FLAGNAME) {
await ioHelper.defaults.error('Error: Cannot use --unconfigured with a specific flag name. --unconfigured works on multiple flags.');
return;
}
if (options.set && options.FLAGNAME && !options.value) {
await ioHelper.defaults.error('Error: When setting a specific flag, you must provide a --value.');
return;
}
if (options.set && options.all && !options.recommended && !options.default) {
await ioHelper.defaults.error('Error: When using --set with --all, you must specify either --recommended or --default.');
return;
}
if (options.set && options.unconfigured && !options.recommended && !options.default) {
await ioHelper.defaults.error('Error: When using --set with --unconfigured, you must specify either --recommended or --default.');
return;
}
if (options.FLAGNAME && !options.set && !options.value) {
await displayFlags(params);
return;
}
if (options.all && !options.set) {
await displayFlags(params);
return;
}
if (options.set && options.FLAGNAME && options.value) {
await setFlag(params);
return;
}
if (!options.FLAGNAME && !options.all && !options.set) {
await displayFlags(params);
return;
}
if (options.set && options.all && options.recommended) {
await setMultipleFlags(params);
return;
}
if (options.set && options.all && options.default) {
await setMultipleFlags(params);
return;
}
if (options.set && options.unconfigured && options.recommended) {
await setMultipleFlags(params);
return;
}
if (options.set && options.unconfigured && options.default) {
await setMultipleFlags(params);
return;
}
}
async function setFlag(params, interactive) {
const { flagData, ioHelper, flagName } = params;
let updatedParams = params;
let updatedFlagName = flagName;
if (interactive) {
const allFlagNames = flagData.filter(flag => isBooleanFlag(flag) == true).map(flag => flag.name);
const prompt = new enquirer_1.Select({
name: 'flag',
message: 'Select which flag you would like to modify:',
limit: 100,
choices: allFlagNames,
});
const selectedFlagName = await prompt.run();
updatedFlagName = [selectedFlagName];
const valuePrompt = new enquirer_1.Select({
name: 'value',
message: 'Select a value:',
choices: ['true', 'false'],
});
const updatedValue = await valuePrompt.run();
updatedParams = {
...params,
value: updatedValue,
flagName: updatedFlagName,
};
}
else {
const flag = flagData.find(f => f.name === flagName[0]);
if (!flag) {
await ioHelper.defaults.error('Flag not found.');
return;
}
if (!isBooleanFlag(flag)) {
await ioHelper.defaults.error(`Flag '${flagName}' is not a boolean flag. Only boolean flags are currently supported.`);
return;
}
}
const prototypeSuccess = await prototypeChanges(updatedParams, updatedFlagName);
if (prototypeSuccess) {
await handleUserResponse(updatedParams, updatedFlagName);
}
}
async function prototypeChanges(params, flagNames) {
const { flagData, toolkit, ioHelper, recommended, value } = params;
const baseContext = new toolkit_lib_1.CdkAppMultiContext(process.cwd());
const baseContextValues = await baseContext.read();
const memoryContext = new toolkit_lib_1.MemoryContext(baseContextValues);
const cdkJson = await JSON.parse(await fs.readFile(path.join(process.cwd(), 'cdk.json'), 'utf-8'));
const app = cdkJson.app;
const source = await toolkit.fromCdkApp(app, {
contextStore: baseContext,
outdir: path.join(process.cwd(), 'original'),
});
const updateObj = {};
const boolValue = toBooleanValue(value);
if (flagNames.length === 1 && value !== undefined) {
const flagName = flagNames[0];
if (baseContextValues[flagName] == boolValue) {
await ioHelper.defaults.info('Flag is already set to the specified value. No changes needed.');
return false;
}
updateObj[flagName] = boolValue;
}
else {
for (const flagName of flagNames) {
const flag = flagData.find(f => f.name === flagName);
if (!flag) {
await ioHelper.defaults.error(`Flag ${flagName} not found.`);
return false;
}
const newValue = recommended
? toBooleanValue(flag.recommendedValue)
: String(flag.unconfiguredBehavesLike?.v2) === 'true';
updateObj[flagName] = newValue;
}
}
await memoryContext.update(updateObj);
const cx = await toolkit.synth(source);
const assembly = cx.cloudAssembly;
const modifiedSource = await toolkit.fromCdkApp(app, {
contextStore: memoryContext,
outdir: path.join(process.cwd(), 'temp'),
});
const modifiedCx = await toolkit.synth(modifiedSource);
const allStacks = assembly.stacksRecursively;
for (const stack of allStacks) {
const templatePath = stack.templateFullPath;
await toolkit.diff(modifiedCx, {
method: toolkit_lib_1.DiffMethod.LocalFile(templatePath),
stacks: {
strategy: api_1.StackSelectionStrategy.PATTERN_MUST_MATCH_SINGLE,
patterns: [stack.hierarchicalId],
},
});
}
return true;
}
async function setMultipleFlags(params) {
const { flagData, all } = params;
let flagsToSet;
if (all) {
flagsToSet = flagData.filter(flag => flag.userValue === undefined || !isUserValueEqualToRecommended(flag))
.filter(flag => isBooleanFlag(flag))
.map(flag => flag.name);
}
else {
flagsToSet = flagData.filter(flag => flag.userValue === undefined)
.filter(flag => isBooleanFlag(flag))
.map(flag => flag.name);
}
const prototypeSuccess = await prototypeChanges(params, flagsToSet);
if (prototypeSuccess) {
await handleUserResponse(params, flagsToSet);
}
}
async function handleUserResponse(params, flagNames) {
const { ioHelper } = params;
const userAccepted = await ioHelper.requestResponse({
time: new Date(),
level: 'info',
code: 'CDK_TOOLKIT_I9300',
message: 'Do you want to accept these changes?',
data: {
flagNames,
responseDescription: 'Enter "y" to apply changes or "n" to cancel',
},
defaultResponse: false,
});
if (userAccepted) {
await modifyValues(params, flagNames);
await ioHelper.defaults.info('Flag value(s) updated successfully.');
}
else {
await ioHelper.defaults.info('Operation cancelled');
}
const originalDir = path.join(process.cwd(), 'original');
const tempDir = path.join(process.cwd(), 'temp');
await fs.remove(originalDir);
await fs.remove(tempDir);
}
async function modifyValues(params, flagNames) {
const { flagData, ioHelper, value, recommended } = params;
const cdkJsonPath = path.join(process.cwd(), 'cdk.json');
const cdkJsonContent = await fs.readFile(cdkJsonPath, 'utf-8');
const cdkJson = JSON.parse(cdkJsonContent);
if (flagNames.length == 1) {
const boolValue = toBooleanValue(value);
cdkJson.context[String(flagNames[0])] = boolValue;
await ioHelper.defaults.info(`Setting flag '${flagNames}' to: ${boolValue}`);
}
else {
for (const flagName of flagNames) {
const flag = flagData.find(f => f.name === flagName);
const newValue = recommended
? toBooleanValue(flag.recommendedValue)
: String(flag.unconfiguredBehavesLike?.v2) === 'true';
cdkJson.context[flagName] = newValue;
}
}
await fs.writeFile(cdkJsonPath, JSON.stringify(cdkJson, null, 2), 'utf-8');
}
function formatTable(headers, rows) {
const columnWidths = [
Math.max(headers[0].length, ...rows.map(row => row[0].length)),
Math.max(headers[1].length, ...rows.map(row => row[1].length)),
Math.max(headers[2].length, ...rows.map(row => row[2].length)),
];
const createSeparator = () => {
return '+' + columnWidths.map(width => '-'.repeat(width + 2)).join('+') + '+';
};
const formatRow = (values) => {
return '|' + values.map((value, i) => ` ${value.padEnd(columnWidths[i])} `).join('|') + '|';
};
const separator = createSeparator();
let table = separator + '\n';
table += formatRow(headers) + '\n';
table += separator + '\n';
rows.forEach(row => {
if (row[1] === '' && row[2] === '') {
table += ` ${row[0].padEnd(columnWidths[0])} \n`;
}
else {
table += formatRow(row) + '\n';
}
});
table += separator;
return table;
}
function getFlagSortOrder(flag) {
if (flag.userValue === undefined) {
return 3;
}
else if (isUserValueEqualToRecommended(flag)) {
return 1;
}
else {
return 2;
}
}
async function displayFlagTable(flags, ioHelper) {
const headers = ['Feature Flag Name', 'Recommended Value', 'User Value'];
const sortedFlags = [...flags].sort((a, b) => {
const orderA = getFlagSortOrder(a);
const orderB = getFlagSortOrder(b);
if (orderA !== orderB) {
return orderA - orderB;
}
if (a.module !== b.module) {
return a.module.localeCompare(b.module);
}
return a.name.localeCompare(b.name);
});
const rows = [];
let currentModule = '';
sortedFlags.forEach((flag) => {
if (flag.module !== currentModule) {
rows.push([chalk.bold(`Module: ${flag.module}`), '', '']);
currentModule = flag.module;
}
rows.push([
flag.name,
String(flag.recommendedValue),
flag.userValue === undefined ? '<unset>' : String(flag.userValue),
]);
});
const formattedTable = formatTable(headers, rows);
await ioHelper.defaults.info(formattedTable);
}
async function displayFlags(params) {
const { flagData, ioHelper, flagName, all } = params;
if (flagName && flagName.length > 0) {
const matchingFlags = flagData.filter(f => flagName.some(searchTerm => f.name.toLowerCase().includes(searchTerm.toLowerCase())));
if (matchingFlags.length === 0) {
await ioHelper.defaults.error(`Flag matching "${flagName.join(', ')}" not found.`);
return;
}
if (matchingFlags.length === 1) {
const flag = matchingFlags[0];
await ioHelper.defaults.info(`Flag name: ${flag.name}`);
await ioHelper.defaults.info(`Description: ${flag.explanation}`);
await ioHelper.defaults.info(`Recommended value: ${flag.recommendedValue}`);
await ioHelper.defaults.info(`User value: ${flag.userValue}`);
return;
}
await ioHelper.defaults.info(`Found ${matchingFlags.length} flags matching "${flagName.join(', ')}":`);
await displayFlagTable(matchingFlags, ioHelper);
return;
}
let flagsToDisplay;
if (all) {
flagsToDisplay = flagData;
}
else {
flagsToDisplay = flagData.filter(flag => flag.userValue === undefined || !isUserValueEqualToRecommended(flag));
}
await displayFlagTable(flagsToDisplay, ioHelper);
}
function isUserValueEqualToRecommended(flag) {
return String(flag.userValue) === String(flag.recommendedValue);
}
function toBooleanValue(value) {
if (typeof value === 'boolean') {
return value;
}
if (typeof value === 'string') {
return value.toLowerCase() === 'true';
}
return false;
}
function isBooleanFlag(flag) {
const recommended = flag.recommendedValue;
return typeof recommended === 'boolean' ||
recommended === 'true' ||
recommended === 'false';
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxhZy1vcGVyYXRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZmxhZy1vcGVyYXRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBNENBLGtDQXlJQztBQThRRCxvQ0FxQ0M7QUF4ZUQsNkJBQTZCO0FBRTdCLHNEQUFxRjtBQUNyRiwrQkFBK0I7QUFDL0IsYUFBYTtBQUNiLHVDQUFrQztBQUNsQywrQkFBK0I7QUFDL0IsZ0NBQWdEO0FBR2hELHNEQUFtRDtBQUVuRCxJQUFLLGdCQU1KO0FBTkQsV0FBSyxnQkFBZ0I7SUFDbkIsOEVBQTBELENBQUE7SUFDMUQsZ0dBQTRFLENBQUE7SUFDNUUsK0hBQTJHLENBQUE7SUFDM0csbUVBQStDLENBQUE7SUFDL0MsaUNBQWEsQ0FBQTtBQUNmLENBQUMsRUFOSSxnQkFBZ0IsS0FBaEIsZ0JBQWdCLFFBTXBCO0FBMEJNLEtBQUssVUFBVSxXQUFXLENBQUMsUUFBdUIsRUFBRSxRQUFrQixFQUFFLE9BQXFCLEVBQUUsT0FBZ0I7SUFDcEgsUUFBUSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLCtCQUFjLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLElBQUksTUFBTSxHQUFHO1FBQ1gsUUFBUTtRQUNSLE9BQU87UUFDUCxRQUFRO1FBQ1IsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXO1FBQ2hDLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRztRQUNoQixLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUs7UUFDcEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1FBQzFCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztRQUN4QixZQUFZLEVBQUUsT0FBTyxDQUFDLFlBQVk7S0FDbkMsQ0FBQztJQUVGLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBRTNELElBQUks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Q0FBQztBQUVELFNBQVMsYUFBYSxDQUFDLElBQWlCO0lBQ3RDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztJQUMxQyxPQUFPLE9BQU8sV0FBVyxLQUFLLFNBQVM7UUFDckMsV0FBVyxLQUFLLE1BQU07UUFDdEIsV0FBVyxLQUFLLE9BQU8sQ0FBQztBQUM1QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB0eXBlIHsgRmVhdHVyZUZsYWcsIFRvb2xraXQgfSBmcm9tICdAYXdzLWNkay90b29sa2l0LWxpYic7XG5pbXBvcnQgeyBDZGtBcHBNdWx0aUNvbnRleHQsIE1lbW9yeUNvbnRleHQsIERpZmZNZXRob2QgfSBmcm9tICdAYXdzLWNkay90b29sa2l0LWxpYic7XG5pbXBvcnQgKiBhcyBjaGFsayBmcm9tICdjaGFsayc7XG4vLyBAdHMtaWdub3JlXG5pbXBvcnQgeyBTZWxlY3QgfSBmcm9tICdlbnF1aXJlcic7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgeyBTdGFja1NlbGVjdGlvblN0cmF0ZWd5IH0gZnJvbSAnLi4vYXBpJztcbmltcG9ydCB0eXBlIHsgSW9IZWxwZXIgfSBmcm9tICcuLi9hcGktcHJpdmF0ZSc7XG5pbXBvcnQgdHlwZSB7IEZsYWdzT3B0aW9ucyB9IGZyb20gJy4uL2NsaS91c2VyLWlucHV0JztcbmltcG9ydCB7IE9CU09MRVRFX0ZMQUdTIH0gZnJvbSAnLi4vb2Jzb2xldGUtZmxhZ3MnO1xuXG5lbnVtIEZsYWdzTWVudU9wdGlvbnMge1xuICBBTExfVE9fUkVDT01NRU5ERUQgPSAnU2V0IGFsbCBmbGFncyB0byByZWNvbW1lbmRlZCB2YWx1ZXMnLFxuICBVTkNPTkZJR1VSRURfVE9fUkVDT01NRU5ERUQgPSAnU2V0IHVuY29uZmlndXJlZCBmbGFncyB0byByZWNvbW1lbmRlZCB2YWx1ZXMnLFxuICBVTkNPTkZJR1VSRURfVE9fREVGQVVMVCA9ICdTZXQgdW5jb25maWd1cmVkIGZsYWdzIHRvIHRoZWlyIGltcGxpZWQgY29uZmlndXJhdGlvbiAocmVjb3JkIGN1cnJlbnQgYmVoYXZpb3IpJyxcbiAgTU9ESUZZX1NQRUNJRklDX0ZMQUcgPSAnTW9kaWZ5IGEgc3BlY2lmaWMgZmxhZycsXG4gIEVYSVQgPSAnRXhpdCcsXG59XG5cbmludGVyZmFjZSBGbGFnT3BlcmF0aW9uc1BhcmFtcyB7XG4gIGZsYWdEYXRhOiBGZWF0dXJlRmxhZ1tdO1xuICB0b29sa2l0OiBUb29sa2l0O1xuICBpb0hlbHBlcjogSW9IZWxwZXI7XG5cbiAgLyoqIFVzZXIgcmFuIC0tcmVjb21tZW5kZWQgb3B0aW9uICovXG4gIHJlY29tbWVuZGVkPzogYm9vbGVhbjtcblxuICAvKiogVXNlciByYW4gLS1hbGwgb3B0aW9uICovXG4gIGFsbD86IGJvb2xlYW47XG5cbiAgLyoqIFVzZXIgcHJvdmlkZWQgLS12YWx1ZSBmaWVsZCAqL1xuICB2YWx1ZT86IHN0cmluZztcblxuICAvKiogVXNlciBwcm92aWRlZCBGTEFHTkFNRSBmaWVsZCAqL1xuICBmbGFnTmFtZT86IHN0cmluZ1tdO1xuXG4gIC8qKiBVc2VyIHJhbiAtLWRlZmF1bHQgb3B0aW9uICovXG4gIGRlZmF1bHQ/OiBib29sZWFuO1xuXG4gIC8qKiBVc2VyIHJhbiAtLXVuY29uZmlndXJlZCBvcHRpb24gKi9cbiAgdW5jb25maWd1cmVkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZUZsYWdzKGZsYWdEYXRhOiBGZWF0dXJlRmxhZ1tdLCBpb0hlbHBlcjogSW9IZWxwZXIsIG9wdGlvbnM6IEZsYWdzT3B0aW9ucywgdG9vbGtpdDogVG9vbGtpdCkge1xuICBmbGFnRGF0YSA9IGZsYWdEYXRhLmZpbHRlcihmbGFnID0+ICFPQlNPTEVURV9GTEFHUy5pbmNsdWRlcyhmbGFnLm5hbWUpKTtcbiAgbGV0IHBhcmFtcyA9IHtcbiAgICBmbGFnRGF0YSxcbiAgICB0b29sa2l0LFxuICAgIGlvSGVscGVyLFxuICAgIHJlY29tbWVuZGVkOiBvcHRpb25zLnJlY29tbWVuZGVkLFxuICAgIGFsbDogb3B0aW9ucy5hbGwsXG4gICAgdmFsdWU6IG9wdGlvbnMudmFsdWUsXG4gICAgZmxhZ05hbWU6IG9wdGlvbnMuRkxBR05BTUUsXG4gICAgZGVmYXVsdDogb3B0aW9ucy5kZWZhdWx0LFxuICAgIHVuY29uZmlndXJlZDogb3B0aW9ucy51bmNvbmZpZ3VyZWQsXG4gIH07XG5cbiAgY29uc3QgaW50ZXJhY3RpdmVPcHRpb25zID0gT2JqZWN0LnZhbHVlcyhGbGFnc01lbnVPcHRpb25zKTtcblxuICBpZiAob3B0aW9ucy5pbnRlcmFjdGl2ZSkge1xuICAgIGNvbnN0IHByb21wdCA9IG5ldyBTZWxlY3Qoe1xuICAgICAgbmFtZTogJ29wdGlvbicsXG4gICAgICBtZXNzYWdlOiAnTWVudScsXG4gICAgICBjaG9pY2VzOiBpbnRlcmFjdGl2ZU9wdGlvbnMsXG4gICAgfSk7XG5cbiAgICBjb25zdCBhbnN3ZXIgPSBhd2FpdCBwcm9tcHQucnVuKCk7XG4gICAgaWYgKGFuc3dlciA9PSBGbGFnc01lbnVPcHRpb25zLkFMTF9UT19SRUNPTU1FTkRFRCkge1xuICAgICAgcGFyYW1zID0ge1xuICAgICAgICAuLi5wYXJhbXMsXG4gICAgICAgIHJlY29tbWVuZGVkOiB0cnVlLFxuICAgICAgICBhbGw6IHRydWUsXG4gICAgICB9O1xuICAgICAgYXdhaXQgc2V0TXVsdGlwbGVGbGFncyhwYXJhbXMpO1xuICAgIH0gZWxzZSBpZiAoYW5zd2VyID09IEZsYWdzTWVudU9wdGlvbnMuVU5DT05GSUdVUkVEX1RPX1JFQ09NTUVOREVEKSB7XG4gICAgICBwYXJhbXMgPSB7XG4gICAgICAgIC4uLnBhcmFtcyxcbiAgICAgICAgcmVjb21tZW5kZWQ6IHRydWUsXG4gICAgICAgIHVuY29uZmlndXJlZDogdHJ1ZSxcbiAgICAgIH07XG4gICAgICBhd2FpdCBzZXRNdWx0aXBsZUZsYWdzKHBhcmFtcyk7XG4gICAgfSBlbHNlIGlmIChhbnN3ZXIgPT0gRmxhZ3NNZW51T3B0aW9ucy5VTkNPTkZJR1VSRURfVE9fREVGQVVMVCkge1xuICAgICAgcGFyYW1zID0ge1xuICAgICAgICAuLi5wYXJhbXMsXG4gICAgICAgIGRlZmF1bHQ6IHRydWUsXG4gICAgICAgIHVuY29uZmlndXJlZDogdHJ1ZSxcbiAgICAgIH07XG4gICAgICBhd2FpdCBzZXRNdWx0aXBsZUZsYWdzKHBhcmFtcyk7XG4gICAgfSBlbHNlIGlmIChhbnN3ZXIgPT0gRmxhZ3NNZW51T3B0aW9ucy5NT0RJRllfU1BFQ0lGSUNfRkxBRykge1xuICAgICAgYXdhaXQgc2V0RmxhZyhwYXJhbXMsIHRydWUpO1xuICAgIH0gZWxzZSBpZiAoYW5zd2VyID09IEZsYWdzTWVudU9wdGlvbnMuRVhJVCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAob3B0aW9ucy5GTEFHTkFNRSAmJiBvcHRpb25zLmFsbCkge1xuICAgIGF3YWl0IGlvSGVscGVyLmRlZmF1bHRzLmVycm9yKCdFcnJvcjogQ2Fubm90IHVzZSBib3RoIC0tYWxsIGFuZCBhIHNwZWNpZmljIGZsYWcgbmFtZS4gUGxlYXNlIHVzZSBlaXRoZXIgLS1hbGwgdG8gc2hvdyBhbGwgZmxhZ3Mgb3Igc3BlY2lmeSBhIHNpbmdsZSBmbGFnIG5hbWUuJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKChvcHRpb25zLnZhbHVlIHx8IG9wdGlvbnMucmVjb21tZW5kZWQgfHwgb3B0aW9ucy5kZWZhdWx0IHx8IG9wdGlvbnMudW5jb25maWd1cmVkKSAmJiAhb3B0aW9ucy5zZXQpIHtcbiAgICBhd2FpdCBpb0hlbHBlci5kZWZhdWx0cy5lcnJvcignRXJyb3I6IFRoaXMgb3B0aW9uIGNhbiBvbmx5IGJlIHVzZWQgd2l0aCAtLXNldC4nKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAob3B0aW9ucy52YWx1ZSAmJiAhb3B0aW9ucy5GTEFHTkFNRSkge1xuICAgIGF3YWl0IGlvSGVscGVyLmRlZmF1bHRzLmVycm9yKCdFcnJvcjogLS12YWx1ZSByZXF1aXJlcyBhIHNwZWNpZmljIGZsYWcgbmFtZS4gUGxlYXNlIHNwZWNpZnkgYSBmbGFnIG5hbWUgd2hlbiBwcm92aWRpbmcgYSB2YWx1ZS4nKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAob3B0aW9ucy5yZWNvbW1lbmRlZCAmJiBvcHRpb25zLmRlZmF1bHQpIHtcbiAgICBhd2FpdCBpb0hlbHBlci5kZWZhdWx0cy5lcnJvcignRXJyb3I6IENhbm5vdCB1c2UgYm90aCAtLXJlY29tbWVuZGVkIGFuZCAtLWRlZmF1bHQuIFBsZWFzZSBjaG9vc2Ugb25lIG9wdGlvbi4nKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAob3B0aW9ucy51bmNvbmZpZ3VyZWQgJiYgb3B0aW9ucy5hbGwpIHtcbiAgICBhd2FpdCBpb0hlbHBlci5kZWZhdWx0cy5lcnJvcignRXJyb3I6IENhbm5vdCB1c2UgYm90aCAtLXVuY29uZmlndXJlZCBhbmQgLS1hbGwuIFBsZWFzZSBjaG9vc2Ugb25lIG9wdGlvbi4nKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAob3B0aW9ucy51bmNvbmZpZ3VyZWQgJiYgb3B0aW9ucy5GTEFHTkFNRSkge1xuICAgIGF3YWl0IGlvSGVscGVyLmRlZmF1bHRzLmVycm9yKCdFcnJvcjogQ2Fubm90IHVzZSAtLXVuY29uZmlndXJlZCB3aXRoIGEgc3BlY2lmaWMgZmxhZyBuYW1lLiAtLXVuY29uZmlndXJlZCB3b3JrcyBvbiBtdWx0aXBsZSBmbGFncy4nKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAob3B0aW9ucy5zZXQgJiYgb3B0aW9ucy5GTEFHTkFNRSAmJiAhb3B0aW9ucy52YWx1ZSkge1xuICAgIGF3YWl0IGlvSGVscGVyLmRlZmF1bHRzLmVycm9yKCdFcnJvcjogV2hlbiBzZXR0aW5nIGEgc3BlY2lmaWMgZmxhZywgeW91IG11c3QgcHJvdmlkZSBhIC0tdmFsdWUuJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMuc2V0ICYmIG9wdGlvbnMuYWxsICYmICFvcHRpb25zLnJlY29tbWVuZGVkICYmICFvcHRpb25zLmRlZmF1bHQpIHtcbiAgICBhd2FpdCBpb0hlbHBlci5kZWZhdWx0cy5lcnJvcignRXJyb3I6IFdoZW4gdXNpbmcgLS1zZXQgd2l0aCAtLWFsbCwgeW91IG11c3Qgc3BlY2lmeSBlaXRoZXIgLS1yZWNvbW1lbmRlZCBvciAtLWRlZmF1bHQuJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMuc2V0ICYmIG9wdGlvbnMudW5jb25maWd1cmVkICYmICFvcHRpb25zLnJlY29tbWVuZGVkICYmICFvcHRpb25zLmRlZmF1bHQpIHtcbiAgICBhd2FpdCBpb0hlbHBlci5kZWZhdWx0cy5lcnJvcignRXJyb3I6IFdoZW4gdXNpbmcgLS1zZXQgd2l0aCAtLXVuY29uZmlndXJlZCwgeW91IG11c3Qgc3BlY2lmeSBlaXRoZXIgLS1yZWNvbW1lbmRlZCBvciAtLWRlZmF1bHQuJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMuRkxBR05BTUUgJiYgIW9wdGlvbnMuc2V0ICYmICFvcHRpb25zLnZhbHVlKSB7XG4gICAgYXdhaXQgZGlzcGxheUZsYWdzKHBhcmFtcyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKG9wdGlvbnMuYWxsICYmICFvcHRpb25zLnNldCkge1xuICAgIGF3YWl0IGRpc3BsYXlGbGFncyhwYXJhbXMpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChvcHRpb25zLnNldCAmJiBvcHRpb25zLkZMQUdOQU1FICYmIG9wdGlvbnMudmFsdWUpIHtcbiAgICBhd2FpdCBzZXRGbGFnKHBhcmFtcyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCFvcHRpb25zLkZMQUdOQU1FICYmICFvcHRpb25zLmFsbCAmJiAhb3B0aW9ucy5zZXQpIHtcbiAgICBhd2FpdCBkaXNwbGF5RmxhZ3MocGFyYW1zKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAob3B0aW9ucy5zZXQgJiYgb3B0aW9ucy5hbGwgJiYgb3B0aW9ucy5yZWNvbW1lbmRlZCkge1xuICAgIGF3YWl0IHNldE11bHRpcGxlRmxhZ3MocGFyYW1zKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAob3B0aW9ucy5zZXQgJiYgb3B0aW9ucy5hbGwgJiYgb3B0aW9ucy5kZWZhdWx0KSB7XG4gICAgYXdhaXQgc2V0TXVsdGlwbGVGbGFncyhwYXJhbXMpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChvcHRpb25zLnNldCAmJiBvcHRpb25zLnVuY29uZmlndXJlZCAmJiBvcHRpb25zLnJlY29tbWVuZGVkKSB7XG4gICAgYXdhaXQgc2V0TXVsdGlwbGVGbGFncyhwYXJhbXMpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChvcHRpb25zLnNldCAmJiBvcHRpb25zLnVuY29uZmlndXJlZCAmJiBvcHRpb25zLmRlZmF1bHQpIHtcbiAgICBhd2FpdCBzZXRNdWx0aXBsZUZsYWdzKHBhcmFtcyk7XG4gICAgcmV0dXJuO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHNldEZsYWcocGFyYW1zOiBGbGFnT3BlcmF0aW9uc1BhcmFtcywgaW50ZXJhY3RpdmU/OiBib29sZWFuKSB7XG4gIGNvbnN0IHsgZmxhZ0RhdGEsIGlvSGVscGVyLCBmbGFnTmFtZSB9ID0gcGFyYW1zO1xuICBsZXQgdXBkYXRlZFBhcmFtcyA9IHBhcmFtcztcbiAgbGV0IHVwZGF0ZWRGbGFnTmFtZSA9IGZsYWdOYW1lO1xuXG4gIGlmIChpbnRlcmFjdGl2ZSkge1xuICAgIGNvbnN0IGFsbEZsYWdOYW1lcyA9IGZsYWdEYXRhLmZpbHRlcihmbGFnID0+IGlzQm9vbGVhbkZsYWcoZmxhZykgPT0gdHJ1ZSkubWFwKGZsYWcgPT4gZmxhZy5uYW1lKTtcblxuICAgIGNvbnN0IHByb21wdCA9IG5ldyBTZWxlY3Qoe1xuICAgICAgbmFtZTogJ2ZsYWcnLFxuICAgICAgbWVzc2FnZTogJ1NlbGVjdCB3aGljaCBmbGFnIHlvdSB3b3VsZCBsaWtlIHRvIG1vZGlmeTonLFxuICAgICAgbGltaXQ6IDEwMCxcbiAgICAgIGNob2ljZXM6IGFsbEZsYWdOYW1lcyxcbiAgICB9KTtcblxuICAgIGNvbnN0IHNlbGVjdGVkRmxhZ05hbWUgPSBhd2FpdCBwcm9tcHQucnVuKCk7XG4gICAgdXBkYXRlZEZsYWdOYW1lID0gW3NlbGVjdGVkRmxhZ05hbWVdO1xuXG4gICAgY29uc3QgdmFsdWVQcm9tcHQgPSBuZXcgU2VsZWN0KHtcbiAgICAgIG5hbWU6ICd2YWx1ZScsXG4gICAgICBtZXNzYWdlOiAnU2VsZWN0IGEgdmFsdWU6JyxcbiAgICAgIGNob2ljZXM6IFsndHJ1ZScsICdmYWxzZSddLFxuICAgIH0pO1xuXG4gICAgY29uc3QgdXBkYXRlZFZhbHVlID0gYXdhaXQgdmFsdWVQcm9tcHQucnVuKCk7XG5cbiAgICB1cGRhdGVkUGFyYW1zID0ge1xuICAgICAgLi4ucGFyYW1zLFxuICAgICAgdmFsdWU6IHVwZGF0ZWRWYWx1ZSxcbiAgICAgIGZsYWdOYW1lOiB1cGRhdGVkRmxhZ05hbWUsXG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBmbGFnID0gZmxhZ0RhdGEuZmluZChmID0+IGYubmFtZSA9PT0gZmxhZ05hbWUhWzBdKTtcblxuICAgIGlmICghZmxhZykge1xuICAgICAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuZXJyb3IoJ0ZsYWcgbm90IGZvdW5kLicpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaXNCb29sZWFuRmxhZyhmbGFnKSkge1xuICAgICAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuZXJyb3IoYEZsYWcgJyR7ZmxhZ05hbWV9JyBpcyBub3QgYSBib29sZWFuIGZsYWcuIE9ubHkgYm9vbGVhbiBmbGFncyBhcmUgY3VycmVudGx5IHN1cHBvcnRlZC5gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBjb25zdCBwcm90b3R5cGVTdWNjZXNzID0gYXdhaXQgcHJvdG90eXBlQ2hhbmdlcyh1cGRhdGVkUGFyYW1zLCB1cGRhdGVkRmxhZ05hbWUhKTtcblxuICBpZiAocHJvdG90eXBlU3VjY2Vzcykge1xuICAgIGF3YWl0IGhhbmRsZVVzZXJSZXNwb25zZSh1cGRhdGVkUGFyYW1zLCB1cGRhdGVkRmxhZ05hbWUhKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBwcm90b3R5cGVDaGFuZ2VzKFxuICBwYXJhbXM6IEZsYWdPcGVyYXRpb25zUGFyYW1zLFxuICBmbGFnTmFtZXM6IHN0cmluZ1tdLFxuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IHsgZmxhZ0RhdGEsIHRvb2xraXQsIGlvSGVscGVyLCByZWNvbW1lbmRlZCwgdmFsdWUgfSA9IHBhcmFtcztcbiAgY29uc3QgYmFzZUNvbnRleHQgPSBuZXcgQ2RrQXBwTXVsdGlDb250ZXh0KHByb2Nlc3MuY3dkKCkpO1xuICBjb25zdCBiYXNlQ29udGV4dFZhbHVlcyA9IGF3YWl0IGJhc2VDb250ZXh0LnJlYWQoKTtcbiAgY29uc3QgbWVtb3J5Q29udGV4dCA9IG5ldyBNZW1vcnlDb250ZXh0KGJhc2VDb250ZXh0VmFsdWVzKTtcblxuICBjb25zdCBjZGtKc29uID0gYXdhaXQgSlNPTi5wYXJzZShhd2FpdCBmcy5yZWFkRmlsZShwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgJ2Nkay5qc29uJyksICd1dGYtOCcpKTtcbiAgY29uc3QgYXBwID0gY2RrSnNvbi5hcHA7XG5cbiAgY29uc3Qgc291cmNlID0gYXdhaXQgdG9vbGtpdC5mcm9tQ2RrQXBwKGFwcCwge1xuICAgIGNvbnRleHRTdG9yZTogYmFzZUNvbnRleHQsXG4gICAgb3V0ZGlyOiBwYXRoLmpvaW4ocHJvY2Vzcy5jd2QoKSwgJ29yaWdpbmFsJyksXG4gIH0pO1xuXG4gIGNvbnN0IHVwZGF0ZU9iajogUmVjb3JkPHN0cmluZywgYm9vbGVhbj4gPSB7fTtcbiAgY29uc3QgYm9vbFZhbHVlID0gdG9Cb29sZWFuVmFsdWUodmFsdWUpO1xuICBpZiAoZmxhZ05hbWVzLmxlbmd0aCA9PT0gMSAmJiB2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3QgZmxhZ05hbWUgPSBmbGFnTmFtZXNbMF07XG4gICAgaWYgKGJhc2VDb250ZXh0VmFsdWVzW2ZsYWdOYW1lXSA9PSBib29sVmFsdWUpIHtcbiAgICAgIGF3YWl0IGlvSGVscGVyLmRlZmF1bHRzLmluZm8oJ0ZsYWcgaXMgYWxyZWFkeSBzZXQgdG8gdGhlIHNwZWNpZmllZCB2YWx1ZS4gTm8gY2hhbmdlcyBuZWVkZWQuJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHVwZGF0ZU9ialtmbGFnTmFtZV0gPSBib29sVmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgZm9yIChjb25zdCBmbGFnTmFtZSBvZiBmbGFnTmFtZXMpIHtcbiAgICAgIGNvbnN0IGZsYWcgPSBmbGFnRGF0YS5maW5kKGYgPT4gZi5uYW1lID09PSBmbGFnTmFtZSk7XG4gICAgICBpZiAoIWZsYWcpIHtcbiAgICAgICAgYXdhaXQgaW9IZWxwZXIuZGVmYXVsdHMuZXJyb3IoYEZsYWcgJHtmbGFnTmFtZX0gbm90IGZvdW5kLmApO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBjb25zdCBuZXdWYWx1ZSA9IHJlY29tbWVuZGVkXG4gICAgICAgID8gdG9Cb29sZWFuVmFsdWUoZmxhZy5yZWNvbW1lbmRlZFZhbHVlKVxuICAgICAgICA6IFN0cmluZyhmbGFnLnVuY29uZmlndXJlZEJlaGF2ZXNMaWtlPy52MikgPT09ICd0cnVlJztcbiAgICAgIHVwZGF0ZU9ialtmbGFnTmFtZV0gPSBuZXdWYWx1ZTtcbiAgICB9XG4gIH1cblxuICBhd2FpdCBtZW1vcnlDb250ZXh0LnVwZGF0ZSh1cGRhdGVPYmopO1xuICBjb25zdCBjeCA9IGF3YWl0IHRvb2xraXQuc3ludGgoc291cmNlKTtcbiAgY29uc3QgYXNzZW1ibHkgPSBjeC5jbG91ZEFzc2VtYmx5O1xuXG4gIGNvbnN0IG1vZGlmaWVkU291cmNlID0gYXdhaXQgdG9vbGtpdC5mcm9tQ2RrQXBwKGFwcCwge1xuICAgIGNvbnRleHRTdG9yZTogbWVtb3J5Q29udGV4dCxcbiAgICBvdXRkaXI6IHBhdGguam9pbihwcm9jZXNzLmN3ZCgpLCAndGVtcCcpLFxuICB9KTtcblxuICBjb25zdCBtb2RpZmllZEN4ID0gYXdhaXQgdG9vbGtpdC5zeW50aChtb2RpZmllZFNvdXJjZSk7XG4gIGNvbnN0IGFsbFN0YWNrcyA9IGFzc2VtYmx5LnN0YWNrc1JlY3Vyc2l2ZWx5O1xuXG4gIGZvciAoY29uc3Qgc3RhY2sgb2YgYWxsU3RhY2tzKSB7XG4gICAgY29uc3QgdGVtcGxhdGVQYXRoID0gc3RhY2sudGVtcGxhdGVGdWxsUGF0aDtcbiAgICBhd2FpdCB0b29sa2l0LmRpZmYobW9kaWZpZWRDeCwge1xuICAgICAgbWV0aG9kOiBEaWZmTWV0aG9kLkxvY2FsRmlsZSh0ZW1wbGF0ZVBhdGgpLFxuICAgICAgc3RhY2tzOiB7XG4gICAgICAgIHN0cmF0ZWd5OiBTdGFja1NlbGVjdGlvblN0cmF0ZWd5LlBBVFRFUk5fTVVTVF9NQVRDSF9TSU5HTEUsXG4gICAgICAgIHBhdHRlcm5zOiBbc3RhY2suaGllcmFyY2hpY2FsSWRdLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gc2V0TXVsdGlwbGVGbGFncyhwYXJhbXM6IEZsYWdPcGVyYXRpb25zUGFyYW1zKSB7XG4gIGNvbnN0IHsgZmxhZ0RhdGEsIGFsbCB9ID0gcGFyYW1zO1xuICBsZXQgZmxhZ3NUb1NldDtcbiAgaWYgKGFsbCkge1xuICAgIGZsYWdzVG9TZXQgPSBmbGFnRGF0YS5maWx0ZXIoZmxhZyA9PiBmbGFnLnVzZXJWYWx1ZSA9PT0gdW5kZWZpbmVkIHx8ICFpc1VzZXJWYWx1ZUVxdWFsVG9SZWNvbW1lbmRlZChmbGFnKSlcbiAgICAgIC5maWx0ZXIoZmxhZyA9PiBpc0Jvb2xlYW5GbGFnKGZsYWcpKVxuICAgICAgLm1hcChmbGFnID0+IGZsYWcubmFtZSk7XG4gIH0gZWxzZSB7XG4gICAgZmxhZ3NUb1NldCA9IGZsYWdEYXRhLmZpbHRlcihmbGFnID0+XG4gICAgICBmbGFnLnVzZXJWYWx1ZSA9PT0gdW5kZWZpbmVkKVxuICAgICAgLmZpbHRlcihmbGFnID0+IGlzQm9vbGVhbkZsYWcoZmxhZykpXG4gICAgICAubWFwKGZsYWcgPT4gZmxhZy5uYW1lKTtcbiAgfVxuICBjb25zdCBwcm90b3R5cGVTdWNjZXNzID0gYXdhaXQgcHJvdG90eXBlQ2hhbmdlcyhwYXJhbXMsIGZsYWdzVG9TZXQpO1xuXG4gIGlmIChwcm90b3R5cGVTdWNj