UNPKG

aws-cdk

Version:

AWS CDK CLI, the command line tool for CDK apps

511 lines 77.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FlagOperations = void 0; exports.isEffectiveValueEqualToRecommended = isEffectiveValueEqualToRecommended; const os = __importStar(require("os")); const path = __importStar(require("path")); const cloudformation_diff_1 = require("@aws-cdk/cloudformation-diff"); const toolkit_lib_1 = require("@aws-cdk/toolkit-lib"); const chalk_1 = __importDefault(require("chalk")); const fs = __importStar(require("fs-extra")); const p_queue_1 = __importDefault(require("p-queue")); const obsolete_flags_1 = require("./obsolete-flags"); const api_1 = require("../../api"); class FlagOperations { flags; toolkit; ioHelper; cliContextValues; /** * Returns only those feature flags that need configuration * * That is those flags: * - That are unconfigured * - That are not obsolete * - Whose default value is different from the recommended value * * The default value being equal to the recommended value sounds odd, but * crops up in a number of situtations: * * - Security-related fixes that we want to force on people, but want to * give them a flag to back out of the changes if they really need to. * - Flags that changed their default value in the most recent major * version. * - Flags that we've introduced at some point in the past, but have gone * back on. */ static filterNeedsAttention(flags) { return flags .filter(flag => !obsolete_flags_1.OBSOLETE_FLAGS.includes(flag.name)) .filter(flag => flag.userValue === undefined) .filter(flag => defaultValue(flag) !== flag.recommendedValue); } app; baseContextValues; allStacks; queue; baselineTempDir; constructor(flags, toolkit, ioHelper, cliContextValues = {}) { this.flags = flags; this.toolkit = toolkit; this.ioHelper = ioHelper; this.cliContextValues = cliContextValues; this.app = ''; this.baseContextValues = {}; this.allStacks = []; this.queue = new p_queue_1.default({ concurrency: 4 }); } /** Main entry point that routes to either flag setting or display operations */ async execute(params) { if (params.set) { if (params.FLAGNAME && params.value) { await this.setFlag(params); } else { await this.setMultipleFlags(params); } } else { await this.displayFlags(params); } } /** Sets a single specific flag with validation and user confirmation */ async setFlag(params) { const flagName = params.FLAGNAME[0]; const flag = this.flags.find(f => f.name === flagName); if (!flag) { await this.ioHelper.defaults.error('Flag not found.'); return; } if (!this.isBooleanFlag(flag)) { await this.ioHelper.defaults.error(`Flag '${flagName}' is not a boolean flag. Only boolean flags are currently supported.`); return; } const prototypeSuccess = await this.prototypeChanges([flagName], params); if (prototypeSuccess) { await this.handleUserResponse([flagName], params); } } /** Sets multiple flags (all or unconfigured) with validation and user confirmation */ async setMultipleFlags(params) { if (params.default && !this.flags.some(f => f.unconfiguredBehavesLike)) { await this.ioHelper.defaults.error('The --default options are not compatible with the AWS CDK library used by your application. Please upgrade to 2.212.0 or above.'); return; } const flagsToSet = this.getFlagsToSet(params); const prototypeSuccess = await this.prototypeChanges(flagsToSet, params); if (prototypeSuccess) { await this.handleUserResponse(flagsToSet, params); } } /** Determines which flags should be set based on the provided parameters */ getFlagsToSet(params) { if (params.all && params.default) { return this.flags .filter(flag => this.isBooleanFlag(flag)) .map(flag => flag.name); } else if (params.all) { return this.flags .filter(flag => flag.userValue === undefined || !isEffectiveValueEqualToRecommended(flag)) .filter(flag => this.isBooleanFlag(flag)) .map(flag => flag.name); } else { return this.flags .filter(flag => flag.userValue === undefined) .filter(flag => this.isBooleanFlag(flag)) .map(flag => flag.name); } } /** Sets flags that don't cause template changes */ async setSafeFlags(params) { const cdkJson = await JSON.parse(await fs.readFile(path.join(process.cwd(), 'cdk.json'), 'utf-8')); this.app = params.app || cdkJson.app; const isUsingTsNode = this.app.includes('ts-node'); if (isUsingTsNode && !this.app.includes('-T') && !this.app.includes('--transpileOnly')) { await this.ioHelper.defaults.info('Repeated synths with ts-node will type-check the application on every synth. Add --transpileOnly to cdk.json\'s "app" command to make this operation faster.'); } const unconfiguredFlags = this.flags.filter(flag => flag.userValue === undefined && this.isBooleanFlag(flag)); if (unconfiguredFlags.length === 0) { await this.ioHelper.defaults.info('All feature flags are configured.'); return; } await this.initializeSafetyCheck(); const safeFlags = await this.batchTestFlags(unconfiguredFlags); await this.cleanupSafetyCheck(); if (safeFlags.length > 0) { await this.ioHelper.defaults.info('Flags that can be set without template changes:'); for (const flag of safeFlags) { await this.ioHelper.defaults.info(`- ${flag.name} -> ${flag.recommendedValue}`); } await this.handleUserResponse(safeFlags.map(flag => flag.name), { ...params, recommended: true }); } else { await this.ioHelper.defaults.info('No more flags can be set without causing template changes.'); } } /** Initializes the safety check by reading context and synthesizing baseline templates */ async initializeSafetyCheck() { const baseContext = new toolkit_lib_1.CdkAppMultiContext(process.cwd()); this.baseContextValues = { ...await baseContext.read(), ...this.cliContextValues }; this.baselineTempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-baseline-')); const mergedContext = new toolkit_lib_1.MemoryContext(this.baseContextValues); const baseSource = await this.toolkit.fromCdkApp(this.app, { contextStore: mergedContext, outdir: this.baselineTempDir, }); const baseCx = await this.toolkit.synth(baseSource); const baseAssembly = baseCx.cloudAssembly; this.allStacks = baseAssembly.stacksRecursively; this.queue = new p_queue_1.default({ concurrency: 4 }); } /** Cleans up temporary directories created during safety checks */ async cleanupSafetyCheck() { if (this.baselineTempDir) { await fs.remove(this.baselineTempDir); this.baselineTempDir = undefined; } } /** Tests multiple flags together and isolates unsafe ones using binary search */ async batchTestFlags(flags) { if (flags.length === 0) return []; const allFlagsContext = { ...this.baseContextValues }; flags.forEach(flag => { allFlagsContext[flag.name] = flag.recommendedValue; }); const allSafe = await this.testBatch(allFlagsContext); if (allSafe) return flags; return this.isolateUnsafeFlags(flags); } /** Tests if a set of context values causes template changes by synthesizing and diffing */ async testBatch(contextValues) { const testContext = new toolkit_lib_1.MemoryContext(contextValues); const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-test-')); const testSource = await this.toolkit.fromCdkApp(this.app, { contextStore: testContext, outdir: tempDir, }); const testCx = await this.toolkit.synth(testSource); try { for (const stack of this.allStacks) { const templatePath = stack.templateFullPath; const diff = await this.toolkit.diff(testCx, { method: toolkit_lib_1.DiffMethod.LocalFile(templatePath), stacks: { strategy: api_1.StackSelectionStrategy.PATTERN_MUST_MATCH_SINGLE, patterns: [stack.hierarchicalId], }, }); for (const stackDiff of Object.values(diff)) { if (stackDiff.differenceCount > 0) { return false; } } } return true; } finally { await fs.remove(tempDir); } } /** Uses binary search to isolate which flags are safe to set without template changes */ async isolateUnsafeFlags(flags) { const safeFlags = []; const processBatch = async (batch, contextValues) => { if (batch.length === 1) { const isSafe = await this.testBatch({ ...contextValues, [batch[0].name]: batch[0].recommendedValue }); if (isSafe) safeFlags.push(batch[0]); return; } const batchContext = { ...contextValues }; batch.forEach(flag => { batchContext[flag.name] = flag.recommendedValue; }); const isSafeBatch = await this.testBatch(batchContext); if (isSafeBatch) { safeFlags.push(...batch); return; } const mid = Math.floor(batch.length / 2); const left = batch.slice(0, mid); const right = batch.slice(mid); void this.queue.add(() => processBatch(left, contextValues)); void this.queue.add(() => processBatch(right, contextValues)); }; void this.queue.add(() => processBatch(flags, this.baseContextValues)); await this.queue.onIdle(); return safeFlags; } /** Prototypes flag changes by synthesizing templates and showing diffs to the user */ async prototypeChanges(flagNames, params) { const baseContext = new toolkit_lib_1.CdkAppMultiContext(process.cwd()); const baseContextValues = { ...await baseContext.read(), ...this.cliContextValues }; 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 this.toolkit.fromCdkApp(app, { contextStore: memoryContext, outdir: fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-original-')), }); const updateObj = await this.buildUpdateObject(flagNames, params, baseContextValues); if (!updateObj) return false; await memoryContext.update(updateObj); const cx = await this.toolkit.synth(source); const assembly = cx.cloudAssembly; const modifiedSource = await this.toolkit.fromCdkApp(app, { contextStore: memoryContext, outdir: fs.mkdtempSync(path.join(os.tmpdir(), 'cdk-temp-')), }); const modifiedCx = await this.toolkit.synth(modifiedSource); const allStacks = assembly.stacksRecursively; for (const stack of allStacks) { const templatePath = stack.templateFullPath; await this.toolkit.diff(modifiedCx, { method: toolkit_lib_1.DiffMethod.LocalFile(templatePath), stacks: { strategy: api_1.StackSelectionStrategy.PATTERN_MUST_MATCH_SINGLE, patterns: [stack.hierarchicalId], }, }); } await this.displayFlagChanges(updateObj, baseContextValues); return true; } /** Displays a summary of flag changes showing old and new values */ async displayFlagChanges(updateObj, baseContextValues) { await this.ioHelper.defaults.info('\nFlag changes:'); for (const [flagName, newValue] of Object.entries(updateObj)) { const currentValue = baseContextValues[flagName]; const currentDisplay = currentValue === undefined ? '<unset>' : String(currentValue); await this.ioHelper.defaults.info(` ${flagName}: ${currentDisplay} → ${newValue}`); } } /** Builds the update object with new flag values based on parameters and current context */ async buildUpdateObject(flagNames, params, baseContextValues) { const updateObj = {}; if (flagNames.length === 1 && params.value !== undefined) { const flagName = flagNames[0]; const boolValue = params.value === 'true'; if (baseContextValues[flagName] === boolValue) { await this.ioHelper.defaults.info('Flag is already set to the specified value. No changes needed.'); return null; } updateObj[flagName] = boolValue; } else { for (const flagName of flagNames) { const flag = this.flags.find(f => f.name === flagName); if (!flag) { await this.ioHelper.defaults.error(`Flag ${flagName} not found.`); return null; } const newValue = params.recommended ? flag.recommendedValue : String(defaultValue(flag)) === 'true'; updateObj[flagName] = newValue; } } return updateObj; } /** Prompts user for confirmation and applies changes if accepted */ async handleUserResponse(flagNames, params) { const userAccepted = await this.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 this.cleanupTempDirectories(); throw new toolkit_lib_1.AbortError('FlagsAborted', 'Flag update cancelled'); } await this.modifyValues(flagNames, params); await this.ioHelper.defaults.info('Flag value(s) updated successfully.'); await this.cleanupTempDirectories(); } /** Removes temporary directories created during flag operations */ async cleanupTempDirectories() { const originalDir = path.join(process.cwd(), 'original'); const tempDir = path.join(process.cwd(), 'temp'); await fs.remove(originalDir); await fs.remove(tempDir); } /** Actually modifies the cdk.json file with the new flag values */ async modifyValues(flagNames, 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 && !params.safe && !params.all) { const boolValue = params.value === 'true'; cdkJson.context[String(flagNames[0])] = boolValue; await this.ioHelper.defaults.info(`Setting flag '${flagNames}' to: ${boolValue}`); } else { for (const flagName of flagNames) { const flag = this.flags.find(f => f.name === flagName); const newValue = params.recommended || params.safe ? flag.recommendedValue : String(defaultValue(flag)) === 'true'; cdkJson.context[flagName] = newValue; } } await fs.writeFile(cdkJsonPath, JSON.stringify(cdkJson, null, 2), 'utf-8'); } /** Displays flags in a table format, either specific flags or filtered by criteria */ async displayFlags(params) { const { FLAGNAME, all } = params; if (FLAGNAME && FLAGNAME.length > 0) { await this.displaySpecificFlags(FLAGNAME); return; } const [flagsToDisplay, header] = all ? [this.flags, 'All feature flags'] : [FlagOperations.filterNeedsAttention(this.flags), 'Unconfigured feature flags']; await this.ioHelper.defaults.info(header); await this.displayFlagTable(flagsToDisplay); // Add helpful message after empty table when not using --all if (!all && flagsToDisplay.length === 0) { await this.ioHelper.defaults.info(''); await this.ioHelper.defaults.info('✅ All feature flags are already set to their recommended values.'); await this.ioHelper.defaults.info('Use \'cdk flags --all --unstable=flags\' to see all flags and their current values.'); } } /** Displays detailed information for specific flags matching the given names */ async displaySpecificFlags(flagNames) { const matchingFlags = this.flags.filter(f => flagNames.some(searchTerm => f.name.toLowerCase().includes(searchTerm.toLowerCase()))); if (matchingFlags.length === 0) { await this.ioHelper.defaults.error(`Flag matching "${flagNames.join(', ')}" not found.`); return; } if (matchingFlags.length === 1) { const flag = matchingFlags[0]; await this.ioHelper.defaults.info(`Flag name: ${flag.name}`); await this.ioHelper.defaults.info(`Description: ${flag.explanation}`); await this.ioHelper.defaults.info(`Recommended value: ${flag.recommendedValue}`); await this.ioHelper.defaults.info(`Default value: ${defaultValue(flag)}`); await this.ioHelper.defaults.info(`User value: ${flag.userValue}`); await this.ioHelper.defaults.info(`Effective value: ${effectiveValue(flag)}`); return; } await this.ioHelper.defaults.info(`Found ${matchingFlags.length} flags matching "${flagNames.join(', ')}"`); await this.displayFlagTable(matchingFlags); } /** Returns sort order for flags */ getFlagSortOrder(flag) { if (flag.userValue === undefined) return 3; if (isEffectiveValueEqualToRecommended(flag)) return 1; return 2; } /** Displays flags in a formatted table grouped by module and sorted */ async displayFlagTable(flags) { const sortedFlags = [...flags].sort((a, b) => { const orderA = this.getFlagSortOrder(a); const orderB = this.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 = [['Feature Flag', 'Recommended', 'User', 'Effective']]; let currentModule = ''; sortedFlags.forEach((flag) => { if (flag.module !== currentModule) { rows.push([chalk_1.default.bold(`Module: ${flag.module}`), '', '', '']); currentModule = flag.module; } rows.push([ ` ${flag.name}`, String(flag.recommendedValue), flag.userValue === undefined ? '<unset>' : String(flag.userValue), String(effectiveValue(flag)), ]); }); const formattedTable = (0, cloudformation_diff_1.formatTable)(rows, undefined, true); await this.ioHelper.defaults.info(formattedTable); } /** Checks if a flag has a boolean recommended value */ isBooleanFlag(flag) { const recommended = flag.recommendedValue; return typeof recommended === 'boolean' || recommended === 'true' || recommended === 'false'; } /** Shows helpful usage examples and available command options */ async displayHelpMessage() { await this.ioHelper.defaults.info('\n' + chalk_1.default.bold('Available options:')); await this.ioHelper.defaults.info(' cdk flags --interactive # Interactive menu to manage flags'); await this.ioHelper.defaults.info(' cdk flags --all # Show all flags (including configured ones)'); await this.ioHelper.defaults.info(' cdk flags --set --all --recommended # Set all flags to recommended values'); await this.ioHelper.defaults.info(' cdk flags --set --all --default # Set all flags to default values'); await this.ioHelper.defaults.info(' cdk flags --set --unconfigured --recommended # Set unconfigured flags to recommended'); await this.ioHelper.defaults.info(' cdk flags --set <flag-name> --value <true|false> # Set specific flag'); await this.ioHelper.defaults.info(' cdk flags --safe # Safely set flags that don\'t change templates'); } } exports.FlagOperations = FlagOperations; /** Checks if the flags current effective value matches the recommended value */ function isEffectiveValueEqualToRecommended(flag) { return String(effectiveValue(flag)) === String(flag.recommendedValue); } /** * Return the effective value of a flag (user value or default) */ function effectiveValue(flag) { return flag.userValue ?? defaultValue(flag); } /** * Return the default value for a flag, assume it's `false` if not given */ function defaultValue(flag) { return flag.unconfiguredBehavesLike?.v2 ?? false; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlcmF0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm9wZXJhdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBcWdCQSxnRkFFQztBQXZnQkQsdUNBQXlCO0FBQ3pCLDJDQUE2QjtBQUU3QixzRUFBMkQ7QUFFM0Qsc0RBQWlHO0FBQ2pHLGtEQUEwQjtBQUMxQiw2Q0FBK0I7QUFDL0Isc0RBQTZCO0FBQzdCLHFEQUFrRDtBQUVsRCxtQ0FBbUQ7QUFHbkQsTUFBYSxjQUFjO0lBaUNOO0lBQ0E7SUFDQTtJQUNBO0lBbkNuQjs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FpQkc7SUFDSSxNQUFNLENBQUMsb0JBQW9CLENBQUMsS0FBb0I7UUFDckQsT0FBTyxLQUFLO2FBQ1QsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQywrQkFBYyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDbkQsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUM7YUFDNUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFFTyxHQUFHLENBQVM7SUFDWixpQkFBaUIsQ0FBc0I7SUFDdkMsU0FBUyxDQUFnQztJQUN6QyxLQUFLLENBQVM7SUFDZCxlQUFlLENBQVU7SUFFakMsWUFDbUIsS0FBb0IsRUFDcEIsT0FBZ0IsRUFDaEIsUUFBa0IsRUFDbEIsbUJBQXdDLEVBQUU7UUFIMUMsVUFBSyxHQUFMLEtBQUssQ0FBZTtRQUNwQixZQUFPLEdBQVAsT0FBTyxDQUFTO1FBQ2hCLGFBQVEsR0FBUixRQUFRLENBQVU7UUFDbEIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUEwQjtRQUUzRCxJQUFJ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UUFDN0gsTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMseUVBQXlFLENBQUMsQ0FBQztRQUM3RyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQywrRUFBK0UsQ0FBQyxDQUFDO0lBQ3JILENBQUM7Q0FDRjtBQXBmRCx3Q0FvZkM7QUFFRCxnRkFBZ0Y7QUFDaEYsU0FBZ0Isa0NBQWtDLENBQUMsSUFBaUI7SUFDbEUsT0FBTyxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBQ3hFLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsY0FBYyxDQUFDLElBQWlCO0lBQ3ZDLE9BQU8sSUFBSSxDQUFDLFNBQVMsSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDOUMsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxZQUFZLENBQUMsSUFBaUI7SUFDckMsT0FBTyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsRUFBRSxJQUFJLEtBQUssQ0FBQztBQUNuRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB0eXBlIHsgQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0IH0gZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktYXBpJztcbmltcG9ydCB7IGZvcm1hdFRhYmxlIH0gZnJvbSAnQGF3cy1jZGsvY2xvdWRmb3JtYXRpb24tZGlmZic7XG5pbXBvcnQgdHlwZSB7IEZlYXR1cmVGbGFnLCBUb29sa2l0IH0gZnJvbSAnQGF3cy1jZGsvdG9vbGtpdC1saWInO1xuaW1wb3J0IHsgQ2RrQXBwTXVsdGlDb250ZXh0LCBNZW1vcnlDb250ZXh0LCBEaWZmTWV0aG9kLCBBYm9ydEVycm9yIH0gZnJvbSAnQGF3cy1jZGsvdG9vbGtpdC1saWInO1xuaW1wb3J0IGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCBQUXVldWUgZnJvbSAncC1xdWV1ZSc7XG5pbXBvcnQgeyBPQlNPTEVURV9GTEFHUyB9IGZyb20gJy4vb2Jzb2xldGUtZmxhZ3MnO1xuaW1wb3J0IHR5cGUgeyBGbGFnT3BlcmF0aW9uc1BhcmFtcyB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgU3RhY2tTZWxlY3Rpb25TdHJhdGVneSB9IGZyb20gJy4uLy4uL2FwaSc7XG5pbXBvcnQgdHlwZSB7IElvSGVscGVyIH0gZnJvbSAnLi4vLi4vYXBpLXByaXZhdGUnO1xuXG5leHBvcnQgY2xhc3MgRmxhZ09wZXJhdGlvbnMge1xuICAvKipcbiAgICogUmV0dXJucyBvbmx5IHRob3NlIGZlYXR1cmUgZmxhZ3MgdGhhdCBuZWVkIGNvbmZpZ3VyYXRpb25cbiAgICpcbiAgICogVGhhdCBpcyB0aG9zZSBmbGFnczpcbiAgICogLSBUaGF0IGFyZSB1bmNvbmZpZ3VyZWRcbiAgICogLSBUaGF0IGFyZSBub3Qgb2Jzb2xldGVcbiAgICogLSBXaG9zZSBkZWZhdWx0IHZhbHVlIGlzIGRpZmZlcmVudCBmcm9tIHRoZSByZWNvbW1lbmRlZCB2YWx1ZVxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCB2YWx1ZSBiZWluZyBlcXVhbCB0byB0aGUgcmVjb21tZW5kZWQgdmFsdWUgc291bmRzIG9kZCwgYnV0XG4gICAqIGNyb3BzIHVwIGluIGEgbnVtYmVyIG9mIHNpdHV0YXRpb25zOlxuICAgKlxuICAgKiAtIFNlY3VyaXR5LXJlbGF0ZWQgZml4ZXMgdGhhdCB3ZSB3YW50IHRvIGZvcmNlIG9uIHBlb3BsZSwgYnV0IHdhbnQgdG9cbiAgICogICBnaXZlIHRoZW