settings.js
1 "use strict"; 2 Object.defineProperty(exports, "__esModule", { value: true }); 3 exports.Settings = exports.Context = exports.Configuration = exports.Command = exports.TRANSIENT_CONTEXT_KEY = exports.USER_DEFAULTS = exports.PROJECT_CONTEXT = exports.PROJECT_CONFIG = void 0; 4 const os = require("os"); 5 const fs_path = require("path"); 6 const fs = require("fs-extra"); 7 const logging_1 = require("./logging"); 8 const util = require("./util"); 9 exports.PROJECT_CONFIG = 'cdk.json'; 10 exports.PROJECT_CONTEXT = 'cdk.context.json'; 11 exports.USER_DEFAULTS = '~/.cdk.json'; 12 /** 13 * If a context value is an object with this key set to a truthy value, it won't be saved to cdk.context.json 14 */ 15 exports.TRANSIENT_CONTEXT_KEY = '$dontSaveContext'; 16 const CONTEXT_KEY = 'context'; 17 var Command; 18 (function (Command) { 19 Command["LS"] = "ls"; 20 Command["LIST"] = "list"; 21 Command["DIFF"] = "diff"; 22 Command["BOOTSTRAP"] = "bootstrap"; 23 Command["DEPLOY"] = "deploy"; 24 Command["DESTROY"] = "destroy"; 25 Command["SYNTHESIZE"] = "synthesize"; 26 Command["SYNTH"] = "synth"; 27 Command["METADATA"] = "metadata"; 28 Command["INIT"] = "init"; 29 Command["VERSION"] = "version"; 30 })(Command = exports.Command || (exports.Command = {})); 31 const BUNDLING_COMMANDS = [ 32 Command.DEPLOY, 33 Command.DIFF, 34 Command.SYNTH, 35 Command.SYNTHESIZE, 36 ]; 37 /** 38 * All sources of settings combined 39 */ 40 class Configuration { 41 constructor(props = {}) { 42 this.props = props; 43 this.settings = new Settings(); 44 this.context = new Context(); 45 this.defaultConfig = new Settings({ 46 versionReporting: true, 47 pathMetadata: true, 48 output: 'cdk.out', 49 }); 50 this.loaded = false; 51 this.commandLineArguments = props.commandLineArguments 52 ? Settings.fromCommandLineArguments(props.commandLineArguments) 53 : new Settings(); 54 this.commandLineContext = this.commandLineArguments.subSettings([CONTEXT_KEY]).makeReadOnly(); 55 } 56 get projectConfig() { 57 if (!this._projectConfig) { 58 throw new Error('#load has not been called yet!'); 59 } 60 return this._projectConfig; 61 } 62 get projectContext() { 63 if (!this._projectContext) { 64 throw new Error('#load has not been called yet!'); 65 } 66 return this._projectContext; 67 } 68 /** 69 * Load all config 70 */ 71 async load() { 72 var _a; 73 const userConfig = await loadAndLog(exports.USER_DEFAULTS); 74 this._projectConfig = await loadAndLog(exports.PROJECT_CONFIG); 75 this._projectContext = await loadAndLog(exports.PROJECT_CONTEXT); 76 const readUserContext = (_a = this.props.readUserContext) !== null && _a !== void 0 ? _a : true; 77 const contextSources = [ 78 this.commandLineContext, 79 this.projectConfig.subSettings([CONTEXT_KEY]).makeReadOnly(), 80 this.projectContext, 81 ]; 82 if (readUserContext) { 83 contextSources.push(userConfig.subSettings([CONTEXT_KEY]).makeReadOnly()); 84 } 85 this.context = new Context(...contextSources); 86 // Build settings from what's left 87 this.settings = this.defaultConfig 88 .merge(userConfig) 89 .merge(this.projectConfig) 90 .merge(this.commandLineArguments) 91 .makeReadOnly(); 92 logging_1.debug('merged settings:', this.settings.all); 93 this.loaded = true; 94 return this; 95 } 96 /** 97 * Save the project context 98 */ 99 async saveContext() { 100 if (!this.loaded) { 101 return this; 102 } // Avoid overwriting files with nothing 103 await this.projectContext.save(exports.PROJECT_CONTEXT); 104 return this; 105 } 106 } 107 exports.Configuration = Configuration; 108 async function loadAndLog(fileName) { 109 const ret = new Settings(); 110 await ret.load(fileName); 111 if (!ret.empty) { 112 logging_1.debug(fileName + ':', JSON.stringify(ret.all, undefined, 2)); 113 } 114 return ret; 115 } 116 /** 117 * Class that supports overlaying property bags 118 * 119 * Reads come from the first property bag that can has the given key, 120 * writes go to the first property bag that is not readonly. A write 121 * will remove the value from all property bags after the first 122 * writable one. 123 */ 124 class Context { 125 constructor(...bags) { 126 this.bags = bags.length > 0 ? bags : [new Settings()]; 127 } 128 get keys() { 129 return Object.keys(this.all); 130 } 131 has(key) { 132 return this.keys.indexOf(key) > -1; 133 } 134 get all() { 135 let ret = new Settings(); 136 // In reverse order so keys to the left overwrite keys to the right of them 137 for (const bag of [...this.bags].reverse()) { 138 ret = ret.merge(bag); 139 } 140 return ret.all; 141 } 142 get(key) { 143 for (const bag of this.bags) { 144 const v = bag.get([key]); 145 if (v !== undefined) { 146 return v; 147 } 148 } 149 return undefined; 150 } 151 set(key, value) { 152 for (const bag of this.bags) { 153 if (bag.readOnly) { 154 continue; 155 } 156 // All bags past the first one have the value erased 157 bag.set([key], value); 158 value = undefined; 159 } 160 } 161 unset(key) { 162 this.set(key, undefined); 163 } 164 clear() { 165 for (const key of this.keys) { 166 this.unset(key); 167 } 168 } 169 } 170 exports.Context = Context; 171 /** 172 * A single bag of settings 173 */ 174 class Settings { 175 constructor(settings = {}, readOnly = false) { 176 this.settings = settings; 177 this.readOnly = readOnly; 178 } 179 /** 180 * Parse Settings out of CLI arguments. 181 * 182 * CLI arguments in must be accessed in the CLI code via 183 * `configuration.settings.get(['argName'])` instead of via `args.argName`. 184 * 185 * The advantage is that they can be configured via `cdk.json` and 186 * `$HOME/.cdk.json`. Arguments not listed below and accessed via this object 187 * can only be specified on the command line. 188 * 189 * @param argv the received CLI arguments. 190 * @returns a new Settings object. 191 */ 192 static fromCommandLineArguments(argv) { 193 var _a; 194 const context = this.parseStringContextListToObject(argv); 195 const tags = this.parseStringTagsListToObject(expectStringList(argv.tags)); 196 // Determine bundling stacks 197 let bundlingStacks; 198 if (BUNDLING_COMMANDS.includes(argv._[0])) { 199 // If we deploy, diff or synth a list of stacks exclusively we skip 200 // bundling for all other stacks. 201 bundlingStacks = argv.exclusively 202 ? (_a = argv.STACKS) !== null && _a !== void 0 ? _a : ['*'] : ['*']; 203 } 204 else { // Skip bundling for all stacks 205 bundlingStacks = []; 206 } 207 return new Settings({ 208 app: argv.app, 209 browser: argv.browser, 210 context, 211 debug: argv.debug, 212 tags, 213 language: argv.language, 214 pathMetadata: argv.pathMetadata, 215 assetMetadata: argv.assetMetadata, 216 profile: argv.profile, 217 plugin: argv.plugin, 218 requireApproval: argv.requireApproval, 219 toolkitStackName: argv.toolkitStackName, 220 toolkitBucket: { 221 bucketName: argv.bootstrapBucketName, 222 kmsKeyId: argv.bootstrapKmsKeyId, 223 }, 224 versionReporting: argv.versionReporting, 225 staging: argv.staging, 226 output: argv.output, 227 outputsFile: argv.outputsFile, 228 progress: argv.progress, 229 bundlingStacks, 230 lookups: argv.lookups, 231 rollback: argv.rollback, 232 }); 233 } 234 static mergeAll(...settings) { 235 let ret = new Settings(); 236 for (const setting of settings) { 237 ret = ret.merge(setting); 238 } 239 return ret; 240 } 241 static parseStringContextListToObject(argv) { 242 const context = {}; 243 for (const assignment of (argv.context || [])) { 244 const parts = assignment.split(/=(.*)/, 2); 245 if (parts.length === 2) { 246 logging_1.debug('CLI argument context: %s=%s', parts[0], parts[1]); 247 if (parts[0].match(/^aws:.+/)) { 248 throw new Error(`User-provided context cannot use keys prefixed with 'aws:', but ${parts[0]} was provided.`); 249 } 250 context[parts[0]] = parts[1]; 251 } 252 else { 253 logging_1.warning('Context argument is not an assignment (key=value): %s', assignment); 254 } 255 } 256 return context; 257 } 258 /** 259 * Parse tags out of arguments 260 * 261 * Return undefined if no tags were provided, return an empty array if only empty 262 * strings were provided 263 */ 264 static parseStringTagsListToObject(argTags) { 265 if (argTags === undefined) { 266 return undefined; 267 } 268 if (argTags.length === 0) { 269 return undefined; 270 } 271 const nonEmptyTags = argTags.filter(t => t !== ''); 272 if (nonEmptyTags.length === 0) { 273 return []; 274 } 275 const tags = []; 276 for (const assignment of nonEmptyTags) { 277 const parts = assignment.split('=', 2); 278 if (parts.length === 2) { 279 logging_1.debug('CLI argument tags: %s=%s', parts[0], parts[1]); 280 tags.push({ 281 Key: parts[0], 282 Value: parts[1], 283 }); 284 } 285 else { 286 logging_1.warning('Tags argument is not an assignment (key=value): %s', assignment); 287 } 288 } 289 return tags.length > 0 ? tags : undefined; 290 } 291 async load(fileName) { 292 if (this.readOnly) { 293 throw new Error(`Can't load ${fileName}: settings object is readonly`); 294 } 295 this.settings = {}; 296 const expanded = expandHomeDir(fileName); 297 if (await fs.pathExists(expanded)) { 298 this.settings = await fs.readJson(expanded); 299 } 300 // See https://github.com/aws/aws-cdk/issues/59 301 this.prohibitContextKey('default-account', fileName); 302 this.prohibitContextKey('default-region', fileName); 303 this.warnAboutContextKey('aws:', fileName); 304 return this; 305 } 306 async save(fileName) { 307 const expanded = expandHomeDir(fileName); 308 await fs.writeJson(expanded, stripTransientValues(this.settings), { spaces: 2 }); 309 return this; 310 } 311 get all() { 312 return this.get([]); 313 } 314 merge(other) { 315 return new Settings(util.deepMerge(this.settings, other.settings)); 316 } 317 subSettings(keyPrefix) { 318 return new Settings(this.get(keyPrefix) || {}, false); 319 } 320 makeReadOnly() { 321 return new Settings(this.settings, true); 322 } 323 clear() { 324 if (this.readOnly) { 325 throw new Error('Cannot clear(): settings are readonly'); 326 } 327 this.settings = {}; 328 } 329 get empty() { 330 return Object.keys(this.settings).length === 0; 331 } 332 get(path) { 333 return util.deepClone(util.deepGet(this.settings, path)); 334 } 335 set(path, value) { 336 if (this.readOnly) { 337 throw new Error(`Can't set ${path}: settings object is readonly`); 338 } 339 if (path.length === 0) { 340 // deepSet can't handle this case 341 this.settings = value; 342 } 343 else { 344 util.deepSet(this.settings, path, value); 345 } 346 return this; 347 } 348 unset(path) { 349 this.set(path, undefined); 350 } 351 prohibitContextKey(key, fileName) { 352 if (!this.settings.context) { 353 return; 354 } 355 if (key in this.settings.context) { 356 // eslint-disable-next-line max-len 357 throw new Error(`The 'context.${key}' key was found in ${fs_path.resolve(fileName)}, but it is no longer supported. Please remove it.`); 358 } 359 } 360 warnAboutContextKey(prefix, fileName) { 361 if (!this.settings.context) { 362 return; 363 } 364 for (const contextKey of Object.keys(this.settings.context)) { 365 if (contextKey.startsWith(prefix)) { 366 // eslint-disable-next-line max-len 367 logging_1.warning(`A reserved context key ('context.${prefix}') key was found in ${fs_path.resolve(fileName)}, it might cause surprising behavior and should be removed.`); 368 } 369 } 370 } 371 } 372 exports.Settings = Settings; 373 function expandHomeDir(x) { 374 if (x.startsWith('~')) { 375 return fs_path.join(os.homedir(), x.substr(1)); 376 } 377 return x; 378 } 379 /** 380 * Return all context value that are not transient context values 381 */ 382 function stripTransientValues(obj) { 383 const ret = {}; 384 for (const [key, value] of Object.entries(obj)) { 385 if (!isTransientValue(value)) { 386 ret[key] = value; 387 } 388 } 389 return ret; 390 } 391 /** 392 * Return whether the given value is a transient context value 393 * 394 * Values that are objects with a magic key set to a truthy value are considered transient. 395 */ 396 function isTransientValue(value) { 397 return typeof value === 'object' && value !== null && value[exports.TRANSIENT_CONTEXT_KEY]; 398 } 399 function expectStringList(x) { 400 if (x === undefined) { 401 return undefined; 402 } 403 if (!Array.isArray(x)) { 404 throw new Error(`Expected array, got '${x}'`); 405 } 406 const nonStrings = x.filter(e => typeof e !== 'string'); 407 if (nonStrings.length > 0) { 408 throw new Error(`Expected list of strings, found ${nonStrings}`); 409 } 410 return x; 411 } 412 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0dGluZ3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5QkFBeUI7QUFDekIsZ0NBQWdDO0FBQ2hDLCtCQUErQjtBQUUvQix1Q0FBMkM7QUFDM0MsK0JBQStCO0FBSWxCLFFBQUEsY0FBYyxHQUFHLFVBQVUsQ0FBQztBQUM1QixRQUFBLGVBQWUsR0FBRyxrQkFBa0IsQ0FBQztBQUNyQyxRQUFBLGFBQWEsR0FBRyxhQUFhLENBQUM7QUFFM0M7O0dBRUc7QUFDVSxRQUFBLHFCQUFxQixHQUFHLGtCQUFrQixDQUFDO0FBRXhELE1BQU0sV0FBVyxHQUFHLFNBQVMsQ0FBQztBQUU5QixJQUFZLE9BWVg7QUFaRCxXQUFZLE9BQU87SUFDakIsb0JBQVMsQ0FBQTtJQUNULHdCQUFhLENBQUE7SUFDYix3QkFBYSxDQUFBO0lBQ2Isa0NBQXVCLENBQUE7SUFDdkIsNEJBQWlCLENBQUE7SUFDakIsOEJBQW1CLENBQUE7SUFDbkIsb0NBQXlCLENBQUE7SUFDekIsMEJBQWUsQ0FBQTtJQUNmLGdDQUFxQixDQUFBO0lBQ3JCLHdCQUFhLENBQUE7SUFDYiw4QkFBbUIsQ0FBQTtBQUNyQixDQUFDLEVBWlcsT0FBTyxHQUFQLGVBQU8sS0FBUCxlQUFPLFFBWWxCO0FBRUQsTUFBTSxpQkFBaUIsR0FBRztJQUN4QixPQUFPLENBQUMsTUFBTTtJQUNkLE9BQU8sQ0FBQyxJQUFJO0lBQ1osT0FBTyxDQUFDLEtBQUs7SUFDYixPQUFPLENBQUMsVUFBVTtDQUNuQixDQUFDO0FBMEJGOztHQUVHO0FBQ0gsTUFBYSxhQUFhO0lBZ0J4QixZQUE2QixRQUE0QixFQUFFO1FBQTlCLFVBQUssR0FBTCxLQUFLLENBQXlCO1FBZnBELGFBQVEsR0FBRyxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQzFCLFlBQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBRWYsa0JBQWEsR0FBRyxJQUFJLFFBQVEsQ0FBQztZ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LCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgKiBhcyBmc19wYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuaW1wb3J0IHsgVGFnIH0gZnJvbSAnLi9jZGstdG9vbGtpdCc7XG5pbXBvcnQgeyBkZWJ1Zywgd2FybmluZyB9IGZyb20gJy4vbG9nZ2luZyc7XG5pbXBvcnQgKiBhcyB1dGlsIGZyb20gJy4vdXRpbCc7XG5cbmV4cG9ydCB0eXBlIFNldHRpbmdzTWFwID0ge1trZXk6IHN0cmluZ106IGFueX07XG5cbmV4cG9ydCBjb25zdCBQUk9KRUNUX0NPTkZJRyA9ICdjZGsuanNvbic7XG5leHBvcnQgY29uc3QgUFJPSkVDVF9DT05URVhUID0gJ2Nkay5jb250ZXh0Lmpzb24nO1xuZXhwb3J0IGNvbnN0IFVTRVJfREVGQVVMVFMgPSAnfi8uY2RrLmpzb24nO1xuXG4vKipcbiAqIElmIGEgY29udGV4dCB2YWx1ZSBpcyBhbiBvYmplY3Qgd2l0aCB0aGlzIGtleSBzZXQgdG8gYSB0cnV0aHkgdmFsdWUsIGl0IHdvbid0IGJlIHNhdmVkIHRvIGNkay5jb250ZXh0Lmpzb25cbiAqL1xuZXhwb3J0IGNvbnN0IFRSQU5TSUVOVF9DT05URVhUX0tFWSA9ICckZG9udFNhdmVDb250ZXh0JztcblxuY29uc3QgQ09OVEVYVF9LRVkgPSAnY29udGV4dCc7XG5cbmV4cG9ydCBlbnVtIENvbW1hbmQge1xuICBMUyA9ICdscycsXG4gIExJU1QgPSAnbGlzdCcsXG4gIERJRkYgPSAnZGlmZicsXG4gIEJPT1RTVFJBUCA9ICdib290c3RyYXAnLFxuICBERVBMT1kgPSAnZGVwbG95JyxcbiAgREVTVFJPWSA9ICdkZXN0cm95JyxcbiAgU1lOVEhFU0laRSA9ICdzeW50aGVzaXplJyxcbiAgU1lOVEggPSAnc3ludGgnLFxuICBNRVRBREFUQSA9ICdtZXRhZGF0YScsXG4gIElOSVQgPSAnaW5pdCcsXG4gIFZFUlNJT04gPSAndmVyc2lvbicsXG59XG5cbmNvbnN0IEJVTkRMSU5HX0NPTU1BTkRTID0gW1xuICBDb21tYW5kLkRFUExPWSxcbiAgQ29tbWFuZC5ESUZGLFxuICBDb21tYW5kLlNZTlRILFxuICBDb21tYW5kLlNZTlRIRVNJWkUsXG5dO1xuXG5leHBvcnQgdHlwZSBBcmd1bWVudHMgPSB7XG4gIHJlYWRvbmx5IF86IFtDb21tYW5kLCAuLi5zdHJpbmdbXV07XG4gIHJlYWRvbmx5IGV4Y2x1c2l2ZWx5PzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgU1RBQ0tTPzogc3RyaW5nW107XG4gIHJlYWRvbmx5IGxvb2t1cHM/OiBib29sZWFuO1xuICByZWFkb25seSBbbmFtZTogc3RyaW5nXTogdW5rbm93bjtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29uZmlndXJhdGlvblByb3BzIHtcbiAgLyoqXG4gICAqIENvbmZpZ3VyYXRpb24gcGFzc2VkIHZpYSBjb21tYW5kIGxpbmUgYXJndW1lbnRzXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm90aGluZyBwYXNzZWRcbiAgICovXG4gIHJlYWRvbmx5IGNvbW1hbmRMaW5lQXJndW1lbnRzPzogQXJndW1lbnRzO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIG9yIG5vdCB0byB1c2UgY29udGV4dCBmcm9tIGAuY2RrLmpzb25gIGluIHVzZXIgaG9tZSBkaXJlY3RvcnlcbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVhZFVzZXJDb250ZXh0PzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBbGwgc291cmNlcyBvZiBzZXR0aW5ncyBjb21iaW5lZFxuICovXG5leHBvcnQgY2xhc3MgQ29uZmlndXJhdGlvbiB7XG4gIHB1YmxpYyBzZXR0aW5ncyA9IG5ldyBTZXR0aW5ncygpO1xuICBwdWJsaWMgY29udGV4dCA9IG5ldyBDb250ZXh0KCk7XG5cbiAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRDb25maWcgPSBuZXcgU2V0dGluZ3Moe1xuICAgIHZlcnNpb25SZXBvcnRpbmc6IHRydWUsXG4gICAgcGF0aE1ldGFkYXRhOiB0cnVlLFxuICAgIG91dHB1dDogJ2Nkay5vdXQnLFxuICB9KTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNvbW1hbmRMaW5lQXJndW1lbnRzOiBTZXR0aW5ncztcbiAgcHJpdmF0ZSByZWFkb25seSBjb21tYW5kTGluZUNvbnRleHQ6IFNldHRpbmdzO1xuICBwcml2YXRlIF9wcm9qZWN0Q29uZmlnPzogU2V0dGluZ3M7XG4gIHByaXZhdGUgX3Byb2plY3RDb250ZXh0PzogU2V0dGluZ3M7XG4gIHByaXZhdGUgbG9hZGVkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBwcm9wczogQ29uZmlndXJhdGlvblByb3BzID0ge30pIHtcbiAgICB0aGlzLmNvbW1hbmRMaW5lQXJndW1lbnRzID0gcHJvcHMuY29tbWFuZExpbmVBcmd1bWVudHNcbiAgICAgID8gU2V0dGluZ3MuZnJvbUNvbW1hbmRMaW5lQXJndW1lbnRzKHByb3BzLmNvbW1hbmRMaW5lQXJndW1lbnRzKVxuICAgICAgOiBuZXcgU2V0dGluZ3MoKTtcbiAgICB0aGlzLmNvbW1hbmRMaW5lQ29udGV4dCA9IHRoaXMuY29tbWFuZExpbmVBcmd1bWVudHMuc3ViU2V0dGluZ3MoW0NPTlRFWFRfS0VZXSkubWFrZVJlYWRPbmx5KCk7XG4gIH1cblxuICBwcml2YXRlIGdldCBwcm9qZWN0Q29uZmlnKCkge1xuICAgIGlmICghdGhpcy5fcHJvamVjdENvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCcjbG9hZCBoYXMgbm90IGJlZW4gY2FsbGVkIHlldCEnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3Byb2plY3RDb25maWc7XG4gIH1cblxuICBwcml2YXRlIGdldCBwcm9qZWN0Q29udGV4dCgpIHtcbiAgICBpZiAoIXRoaXMuX3Byb2plY3RDb250ZXh0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJyNsb2FkIGhhcyBub3QgYmVlbiBjYWxsZWQgeWV0IScpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fcHJvamVjdENvbnRleHQ7XG4gIH1cblxuICAvKipcbiAgICogTG9hZCBhbGwgY29uZmlnXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgbG9hZCgpOiBQcm9taXNlPHRoaXM+IHtcbiAgICBjb25zdCB1c2VyQ29uZmlnID0gYXdhaXQgbG9hZEFuZExvZyhVU0VSX0RFRkFVTFRTKTtcbiAgICB0aGlzLl9wcm9qZWN0Q29uZmlnID0gYXdhaXQgbG9hZEFuZExvZyhQUk9KRUNUX0NPTkZJRyk7XG4gICAgdGhpcy5fcHJvamVjdENvbnRleHQgPSBhd2FpdCBsb2FkQW5kTG9nKFBST0pFQ1RfQ09OVEVYVCk7XG5cbiAgICBjb25zdCByZWFkVXNlckNvbnRleHQgPSB0aGlzLnByb3BzLnJlYWRVc2VyQ29udGV4dCA/PyB0cnVlO1xuXG4gICAgY29uc3QgY29udGV4dFNvdXJjZXMgPSBbXG4gICAgICB0aGlzLmNvbW1hbmRMaW5lQ29udGV4dCxcbiAgICAgIHRoaXMucHJvamVjdENvbmZpZy5zdWJTZXR0aW5ncyhbQ09OVEVYVF9LRVldKS5tYWtlUmVhZE9ubHkoKSxcbiAgICAgIHRoaXMucHJvamVjdENvbnRleHQsXG4gICAgXTtcbiAgICBpZiAocmVhZFVzZXJDb250ZXh0KSB7XG4gICAgICBjb250ZXh0U291cmNlcy5wdXNoKHVzZXJDb25maWcuc3ViU2V0dGluZ3MoW0NPTlRFWFRfS0VZXSkubWFrZVJlYWRPbmx5KCkpO1xuICAgIH1cblxuICAgIHRoaXMuY29udGV4dCA9IG5ldyBDb250ZXh0KC4uLmNvbnRleHRTb3VyY2VzKTtcblxuICAgIC8vIEJ1aWxkIHNldHRpbmdzIGZyb20gd2hhdCdzIGxlZnRcbiAgICB0aGlzLnNldHRpbmdzID0gdGhpcy5kZWZhdWx0Q29uZmlnXG4gICAgICAubWVyZ2UodXNlckNvbmZpZylcbiAgICAgIC5tZXJnZSh0aGlzLnByb2plY3RDb25maWcpXG4gICAgICAubWVyZ2UodGhpcy5jb21tYW5kTGluZUFyZ3VtZW50cylcbiAgICAgIC5tYWtlUmVhZE9ubHkoKTtcblxuICAgIGRlYnVnKCdtZXJnZWQgc2V0dGluZ3M6JywgdGhpcy5zZXR0aW5ncy5hbGwpO1xuXG4gICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSB0aGUgcHJvamVjdCBjb250ZXh0XG4gICAqL1xuICBwdWJsaWMgYXN5bmMgc2F2ZUNvbnRleHQoKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgaWYgKCF0aGlzLmxvYWRlZCkgeyByZXR1cm4gdGhpczsgfSAvLyBBdm9pZCBvdmVyd3JpdGluZyBmaWxlcyB3aXRoIG5vdGhpbmdcblxuICAgIGF3YWl0IHRoaXMucHJvamVjdENvbnRleHQuc2F2ZShQUk9KRUNUX0NPTlRFWFQpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZEFuZExvZyhmaWxlTmFtZTogc3RyaW5nKTogUHJvbWlzZTxTZXR0aW5ncz4ge1xuICBjb25zdCByZXQgPSBuZXcgU2V0dGluZ3MoKTtcbiAgYXdhaXQgcmV0LmxvYWQoZmlsZU5hbWUpO1xuICBpZiAoIXJldC5lbXB0eSkge1xuICAgIGRlYnVnKGZpbGVOYW1lICsgJzonLCBKU09OLnN0cmluZ2lmeShyZXQuYWxsLCB1bmRlZmluZWQsIDIpKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIENsYXNzIHRoYXQgc3VwcG9ydHMgb3ZlcmxheWluZyBwcm9wZXJ0eSBiYWdzXG4gKlxuICogUmVhZHMgY29tZSBmcm9tIHRoZSBmaXJzdCBwcm9wZXJ0eSBiYWcgdGhhdCBjYW4gaGFzIHRoZSBnaXZlbiBrZXksXG4gKiB3cml0ZXMgZ28gdG8gdGhlIGZpcnN0IHByb3BlcnR5IGJhZyB0aGF0IGlzIG5vdCByZWFkb25seS4gQSB3cml0ZVxuICogd2lsbCByZW1vdmUgdGhlIHZhbHVlIGZyb20gYWxsIHByb3BlcnR5IGJhZ3MgYWZ0ZXIgdGhlIGZpcnN0XG4gKiB3cml0YWJsZSBvbmUuXG4gKi9cbmV4cG9ydCBjbGFzcyBDb250ZXh0IHtcbiAgcHJpdmF0ZSByZWFkb25seSBiYWdzOiBTZXR0aW5nc1tdO1xuXG4gIGNvbnN0cnVjdG9yKC4uLmJhZ3M6IFNldHRpbmdzW10pIHtcbiAgICB0aGlzLmJhZ3MgPSBiYWdzLmxlbmd0aCA+IDAgPyBiYWdzIDogW25ldyBTZXR0aW5ncygpXTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQga2V5cygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuYWxsKTtcbiAgfVxuXG4gIHB1YmxpYyBoYXMoa2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5rZXlzLmluZGV4T2Yoa2V5KSA+IC0xO1xuICB9XG5cbiAgcHVibGljIGdldCBhbGwoKToge1trZXk6IHN0cmluZ106IGFueX0ge1xuICAgIGxldCByZXQgPSBuZXcgU2V0dGluZ3MoKTtcblxuICAgIC8vIEluIHJldmVyc2Ugb3JkZXIgc28ga2V5cyB0byB0aGUgbGVmdCBvdmVyd3JpdGUga2V5cyB0byB0aGUgcmlnaHQgb2YgdGhlbVxuICAgIGZvciAoY29uc3QgYmFnIG9mIFsuLi50aGlzLmJhZ3NdLnJldmVyc2UoKSkge1xuICAgICAgcmV0ID0gcmV0Lm1lcmdlKGJhZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldC5hbGw7XG4gIH1cblxuICBwdWJsaWMgZ2V0KGtleTogc3RyaW5nKTogYW55IHtcbiAgICBmb3IgKGNvbnN0IGJhZyBvZiB0aGlzLmJhZ3MpIHtcbiAgICAgIGNvbnN0IHYgPSBiYWcuZ2V0KFtrZXldKTtcbiAgICAgIGlmICh2ICE9PSB1bmRlZmluZWQpIHsgcmV0dXJuIHY7IH1cbiAgICB9XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHB1YmxpYyBzZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgICBmb3IgKGNvbnN0IGJhZyBvZiB0aGlzLmJhZ3MpIHtcbiAgICAgIGlmIChiYWcucmVhZE9ubHkpIHsgY29udGludWU7IH1cblxuICAgICAgLy8gQWxsIGJhZ3MgcGFzdCB0aGUgZmlyc3Qgb25lIGhhdmUgdGhlIHZhbHVlIGVyYXNlZFxuICAgICAgYmFnLnNldChba2V5XSwgdmFsdWUpO1xuICAgICAgdmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHVuc2V0KGtleTogc3RyaW5nKSB7XG4gICAgdGhpcy5zZXQoa2V5LCB1bmRlZmluZWQpO1xuICB9XG5cbiAgcHVibGljIGNsZWFyKCkge1xuICAgIGZvciAoY29uc3Qga2V5IG9mIHRoaXMua2V5cykge1xuICAgICAgdGhpcy51bnNldChrZXkpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEEgc2luZ2xlIGJhZyBvZiBzZXR0aW5nc1xuICovXG5leHBvcnQgY2xhc3MgU2V0dGluZ3Mge1xuXG4gIC8qKlxuICAgKiBQYXJzZSBTZXR0aW5ncyBvdXQgb2YgQ0xJIGFyZ3VtZW50cy5cbiAgICpcbiAgICogQ0xJIGFyZ3VtZW50cyBpbiBtdXN0IGJlIGFjY2Vzc2VkIGluIHRoZSBDTEkgY29kZSB2aWFcbiAgICogYGNvbmZpZ3VyYXRpb24uc2V0dGluZ3MuZ2V0KFsnYXJnTmFtZSddKWAgaW5zdGVhZCBvZiB2aWEgYGFyZ3MuYXJnTmFtZWAuXG4gICAqXG4gICAqIFRoZSBhZHZhbnRhZ2UgaXMgdGhhdCB0aGV5IGNhbiBiZSBjb25maWd1cmVkIHZpYSBgY2RrLmpzb25gIGFuZFxuICAgKiBgJEhPTUUvLmNkay5qc29uYC4gQXJndW1lbnRzIG5vdCBsaXN0ZWQgYmVsb3cgYW5kIGFjY2Vzc2VkIHZpYSB0aGlzIG9iamVjdFxuICAgKiBjYW4gb25seSBiZSBzcGVjaWZpZWQgb24gdGhlIGNvbW1hbmQgbGluZS5cbiAgICpcbiAgICogQHBhcmFtIGFyZ3YgdGhlIHJlY2VpdmVkIENMSSBhcmd1bWVudHMuXG4gICAqIEByZXR1cm5zIGEgbmV3IFNldHRpbmdzIG9iamVjdC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUNvbW1hbmRMaW5lQXJndW1lbnRzKGFyZ3Y6IEFyZ3VtZW50cyk6IFNldHRpbmdzIHtcbiAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5wYXJzZVN0cmluZ0NvbnRleHRMaXN0VG9PYmplY3QoYXJndik7XG4gICAgY29uc3QgdGFncyA9IHRoaXMucGFyc2VTdHJpbmdUYWdzTGlzdFRvT2JqZWN0KGV4cGVjdFN0cmluZ0xpc3QoYXJndi50YWdzKSk7XG5cbiAgICAvLyBEZXRlcm1pbmUgYnVuZGxpbmcgc3RhY2tzXG4gICAgbGV0IGJ1bmRsaW5nU3RhY2tzOiBzdHJpbmdbXTtcbiAgICBpZiAoQlVORExJTkdfQ09NTUFORFMuaW5jbHVkZXMoYXJndi5fWzBdKSkge1xuICAgIC8vIElmIHdlIGRlcGxveSwgZGlmZiBvciBzeW50aCBhIGxpc3Qgb2Ygc3RhY2tzIGV4Y2x1c2l2ZWx5IHdlIHNraXBcbiAgICAvLyBidW5kbGluZyBmb3IgYWxsIG90aGVyIHN0YWNrcy5cbiAgICAgIGJ1bmRsaW5nU3RhY2tzID0gYXJndi5leGNsdXNpdmVseVxuICAgICAgICA/IGFyZ3YuU1RBQ0tTID8/IFsnKiddXG4gICAgICAgIDogWycqJ107XG4gICAgfSBlbHNlIHsgLy8gU2tpcCBidW5kbGluZyBmb3IgYWxsIHN0YWNrc1xuICAgICAgYnVuZGxpbmdTdGFja3MgPSBbXTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFNldHRpbmdzKHtcbiAgICAgIGFwcDogYXJndi5hcHAsXG4gICAgICBicm93c2VyOiBhcmd2LmJyb3dzZXIsXG4gICAgICBjb250ZXh0LFxuICAgICAgZGVidWc6IGFyZ3YuZGVidWcsXG4gICAgICB0YWdzLFxuICAgICAgbGFuZ3VhZ2U6IGFyZ3YubGFuZ3VhZ2UsXG4gICAgICBwYXRoTWV0YWRhdGE6IGFyZ3YucGF0aE1ldGFkYXRhLFxuICAgICAgYXNzZXRNZXRhZGF0YTogYXJndi5hc3NldE1ldGFkYXRhLFxuICAgICAgcHJvZmlsZTogYXJndi5wcm9maWxlLFxuICAgICAgcGx1Z2luOiBhcmd2LnBsdWdpbixcbiAgICAgIHJlcXVpcmVBcHByb3ZhbDogYXJndi5yZXF1aXJlQXBwcm92YWwsXG4gICAgICB0b29sa2l0U3RhY2tOYW1lOiBhcmd2LnRvb2xraXRTdGFja05hbWUsXG4gICAgICB0b29sa2l0QnVja2V0OiB7XG4gICAgICAgIGJ1Y2tldE5hbWU6IGFyZ3YuYm9vdHN0cmFwQnVja2V0TmFtZSxcbiAgICAgICAga21zS2V5SWQ6IGFyZ3YuYm9vdHN0cmFwS21zS2V5SWQsXG4gICAgICB9LFxuICAgICAgdmVyc2lvblJlcG9ydGluZzogYXJndi52ZXJzaW9uUmVwb3J0aW5nLFxuICAgICAgc3RhZ2luZzogYXJndi5zdGFnaW5nLFxuICAgICAgb3V0cHV0OiBhcmd2Lm91dHB1dCxcbiAgICAgIG91dHB1dHNGaWxlOiBhcmd2Lm91dHB1dHNGaWxlLFxuICAgICAgcHJvZ3Jlc3M6IGFyZ3YucHJvZ3Jlc3MsXG4gICAgICBidW5kbGluZ1N0YWNrcyxcbiAgICAgIGxvb2t1cHM6IGFyZ3YubG9va3VwcyxcbiAgICAgIHJvbGxiYWNrOiBhcmd2LnJvbGxiYWNrLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBtZXJnZUFsbCguLi5zZXR0aW5nczogU2V0dGluZ3NbXSk6IFNldHRpbmdzIHtcbiAgICBsZXQgcmV0ID0gbmV3IFNldHRpbmdzKCk7XG4gICAgZm9yIChjb25zdCBzZXR0aW5nIG9mIHNldHRpbmdzKSB7XG4gICAgICByZXQgPSByZXQubWVyZ2Uoc2V0dGluZyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBwYXJzZVN0cmluZ0NvbnRleHRMaXN0VG9PYmplY3QoYXJndjogQXJndW1lbnRzKTogYW55IHtcbiAgICBjb25zdCBjb250ZXh0OiBhbnkgPSB7fTtcblxuICAgIGZvciAoY29uc3QgYXNzaWdubWVudCBvZiAoKGFyZ3YgYXMgYW55KS5jb250ZXh0IHx8IFtdKSkge1xuICAgICAgY29uc3QgcGFydHMgPSBhc3NpZ25tZW50LnNwbGl0KC89KC4qKS8sIDIpO1xuICAgICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMikge1xuICAgICAgICBkZWJ1ZygnQ0xJIGFyZ3VtZW50IGNvbnRleHQ6ICVzPSVzJywgcGFydHNbMF0sIHBhcnRzWzFdKTtcbiAgICAgICAgaWYgKHBhcnRzWzBdLm1hdGNoKC9eYXdzOi4rLykpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVzZXItcHJvdmlkZWQgY29udGV4dCBjYW5ub3QgdXNlIGtleXMgcHJlZml4ZWQgd2l0aCAnYXdzOicsIGJ1dCAke3BhcnRzWzBdfSB3YXMgcHJvdmlkZWQuYCk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGV4dFtwYXJ0c1swXV0gPSBwYXJ0c1sxXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHdhcm5pbmcoJ0NvbnRleHQgYXJndW1lbnQgaXMgbm90IGFuIGFzc2lnbm1lbnQgKGtleT12YWx1ZSk6ICVzJywgYXNzaWdubWVudCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjb250ZXh0O1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlIHRhZ3Mgb3V0IG9mIGFyZ3VtZW50c1xuICAgKlxuICAgKiBSZXR1cm4gdW5kZWZpbmVkIGlmIG5vIHRhZ3Mgd2VyZSBwcm92aWRlZCwgcmV0dXJuIGFuIGVtcHR5IGFycmF5IGlmIG9ubHkgZW1wdHlcbiAgICogc3RyaW5ncyB3ZXJlIHByb3ZpZGVkXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBwYXJzZVN0cmluZ1RhZ3NMaXN0VG9PYmplY3QoYXJnVGFnczogc3RyaW5nW10gfCB1bmRlZmluZWQpOiBUYWdbXSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKGFyZ1RhZ3MgPT09IHVuZGVmaW5lZCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9XG4gICAgaWYgKGFyZ1RhZ3MubGVuZ3RoID09PSAwKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cbiAgICBjb25zdCBub25FbXB0eVRhZ3MgPSBhcmdUYWdzLmZpbHRlcih0ID0+IHQgIT09ICcnKTtcbiAgICBpZiAobm9uRW1wdHlUYWdzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gW107IH1cblxuICAgIGNvbnN0IHRhZ3M6IFRhZ1tdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGFzc2lnbm1lbnQgb2Ygbm9uRW1wdHlUYWdzKSB7XG4gICAgICBjb25zdCBwYXJ0cyA9IGFzc2lnbm1lbnQuc3BsaXQoJz0nLCAyKTtcbiAgICAgIGlmIChwYXJ0cy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgZGVidWcoJ0NMSSBhcmd1bWVudCB0YWdzOiAlcz0lcycsIHBhcnRzWzBdLCBwYXJ0c1sxXSk7XG4gICAgICAgIHRhZ3MucHVzaCh7XG4gICAgICAgICAgS2V5OiBwYXJ0c1swXSxcbiAgICAgICAgICBWYWx1ZTogcGFydHNbMV0sXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2FybmluZygnVGFncyBhcmd1bWVudCBpcyBub3QgYW4gYXNzaWdubWVudCAoa2V5PXZhbHVlKTogJXMnLCBhc3NpZ25tZW50KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRhZ3MubGVuZ3RoID4gMCA/IHRhZ3MgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNldHRpbmdzOiBTZXR0aW5nc01hcCA9IHt9LCBwdWJsaWMgcmVhZG9ubHkgcmVhZE9ubHkgPSBmYWxzZSkge31cblxuICBwdWJsaWMgYXN5bmMgbG9hZChmaWxlTmFtZTogc3RyaW5nKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3QgbG9hZCAke2ZpbGVOYW1lfTogc2V0dGluZ3Mgb2JqZWN0IGlzIHJlYWRvbmx5YCk7XG4gICAgfVxuICAgIHRoaXMuc2V0dGluZ3MgPSB7fTtcblxuICAgIGNvbnN0IGV4cGFuZGVkID0gZXhwYW5kSG9tZURpcihmaWxlTmFtZSk7XG4gICAgaWYgKGF3YWl0IGZzLnBhdGhFeGlzdHMoZXhwYW5kZWQpKSB7XG4gICAgICB0aGlzLnNldHRpbmdzID0gYXdhaXQgZnMucmVhZEpzb24oZXhwYW5kZWQpO1xuICAgIH1cblxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvaXNzdWVzLzU5XG4gICAgdGhpcy5wcm9oaWJpdENvbnRleHRLZXkoJ2RlZmF1bHQtYWNjb3VudCcsIGZpbGVOYW1lKTtcbiAgICB0aGlzLnByb2hpYml0Q29udGV4dEtleSgnZGVmYXVsdC1yZWdpb24nLCBmaWxlTmFtZSk7XG4gICAgdGhpcy53YXJuQWJvdXRDb250ZXh0S2V5KCdhd3M6JywgZmlsZU5hbWUpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgc2F2ZShmaWxlTmFtZTogc3RyaW5nKTogUHJvbWlzZTx0aGlzPiB7XG4gICAgY29uc3QgZXhwYW5kZWQgPSBleHBhbmRIb21lRGlyKGZpbGVOYW1lKTtcbiAgICBhd2FpdCBmcy53cml0ZUpzb24oZXhwYW5kZWQsIHN0cmlwVHJhbnNpZW50VmFsdWVzKHRoaXMuc2V0dGluZ3MpLCB7IHNwYWNlczogMiB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYWxsKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KFtdKTtcbiAgfVxuXG4gIHB1YmxpYyBtZXJnZShvdGhlcjogU2V0dGluZ3MpOiBTZXR0aW5ncyB7XG4gICAgcmV0dXJuIG5ldyBTZXR0aW5ncyh1dGlsLmRlZXBNZXJnZSh0aGlzLnNldHRpbmdzLCBvdGhlci5zZXR0aW5ncykpO1xuICB9XG5cbiAgcHVibGljIHN1YlNldHRpbmdzKGtleVByZWZpeDogc3RyaW5nW10pIHtcbiAgICByZXR1cm4gbmV3IFNldHRpbmdzKHRoaXMuZ2V0KGtleVByZWZpeCkgfHwge30sIGZhbHNlKTtcbiAgfVxuXG4gIHB1YmxpYyBtYWtlUmVhZE9ubHkoKTogU2V0dGluZ3Mge1xuICAgIHJldHVybiBuZXcgU2V0dGluZ3ModGhpcy5zZXR0aW5ncywgdHJ1ZSk7XG4gIH1cblxuICBwdWJsaWMgY2xlYXIoKSB7XG4gICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGNsZWFyKCk6IHNldHRpbmdzIGFyZSByZWFkb25seScpO1xuICAgIH1cbiAgICB0aGlzLnNldHRpbmdzID0ge307XG4gIH1cblxuICBwdWJsaWMgZ2V0IGVtcHR5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLnNldHRpbmdzKS5sZW5ndGggPT09IDA7XG4gIH1cblxuICBwdWJsaWMgZ2V0KHBhdGg6IHN0cmluZ1tdKTogYW55IHtcbiAgICByZXR1cm4gdXRpbC5kZWVwQ2xvbmUodXRpbC5kZWVwR2V0KHRoaXMuc2V0dGluZ3MsIHBhdGgpKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXQocGF0aDogc3RyaW5nW10sIHZhbHVlOiBhbnkpOiBTZXR0aW5ncyB7XG4gICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3Qgc2V0ICR7cGF0aH06IHNldHRpbmdzIG9iamVjdCBpcyByZWFkb25seWApO1xuICAgIH1cbiAgICBpZiAocGF0aC5sZW5ndGggPT09IDApIHtcbiAgICAgIC8vIGRlZXBTZXQgY2FuJ3QgaGFuZGxlIHRoaXMgY2FzZVxuICAgICAgdGhpcy5zZXR0aW5ncyA9IHZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB1dGlsLmRlZXBTZXQodGhpcy5zZXR0aW5ncywgcGF0aCwgdmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyB1bnNldChwYXRoOiBzdHJpbmdbXSkge1xuICAgIHRoaXMuc2V0KHBhdGgsIHVuZGVmaW5lZCk7XG4gIH1cblxuICBwcml2YXRlIHByb2hpYml0Q29udGV4dEtleShrZXk6IHN0cmluZywgZmlsZU5hbWU6IHN0cmluZykge1xuICAgIGlmICghdGhpcy5zZXR0aW5ncy5jb250ZXh0KSB7IHJldHVybjsgfVxuICAgIGlmIChrZXkgaW4gdGhpcy5zZXR0aW5ncy5jb250ZXh0KSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgJ2NvbnRleHQuJHtrZXl9JyBrZXkgd2FzIGZvdW5kIGluICR7ZnNfcGF0aC5yZXNvbHZlKGZpbGVOYW1lKX0sIGJ1dCBpdCBpcyBubyBsb25nZXIgc3VwcG9ydGVkLiBQbGVhc2UgcmVtb3ZlIGl0LmApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgd2FybkFib3V0Q29udGV4dEtleShwcmVmaXg6IHN0cmluZywgZmlsZU5hbWU6IHN0cmluZykge1xuICAgIGlmICghdGhpcy5zZXR0aW5ncy5jb250ZXh0KSB7IHJldHVybjsgfVxuICAgIGZvciAoY29uc3QgY29udGV4dEtleSBvZiBPYmplY3Qua2V5cyh0aGlzLnNldHRpbmdzLmNvbnRleHQpKSB7XG4gICAgICBpZiAoY29udGV4dEtleS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICAgICAgd2FybmluZyhgQSByZXNlcnZlZCBjb250ZXh0IGtleSAoJ2NvbnRleHQuJHtwcmVmaXh9Jykga2V5IHdhcyBmb3VuZCBpbiAke2ZzX3BhdGgucmVzb2x2ZShmaWxlTmFtZSl9LCBpdCBtaWdodCBjYXVzZSBzdXJwcmlzaW5nIGJlaGF2aW9yIGFuZCBzaG91bGQgYmUgcmVtb3ZlZC5gKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZXhwYW5kSG9tZURpcih4OiBzdHJpbmcpIHtcbiAgaWYgKHguc3RhcnRzV2l0aCgnficpKSB7XG4gICAgcmV0dXJuIGZzX3BhdGguam9pbihvcy5ob21lZGlyKCksIHguc3Vic3RyKDEpKTtcbiAgfVxuICByZXR1cm4geDtcbn1cblxuLyoqXG4gKiBSZXR1cm4gYWxsIGNvbnRleHQgdmFsdWUgdGhhdCBhcmUgbm90IHRyYW5zaWVudCBjb250ZXh0IHZhbHVlc1xuICovXG5mdW5jdGlvbiBzdHJpcFRyYW5zaWVudFZhbHVlcyhvYmo6IHtba2V5OiBzdHJpbmddOiBhbnl9KSB7XG4gIGNvbnN0IHJldDogYW55ID0ge307XG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKG9iaikpIHtcbiAgICBpZiAoIWlzVHJhbnNpZW50VmFsdWUodmFsdWUpKSB7XG4gICAgICByZXRba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG4vKipcbiAqIFJldHVybiB3aGV0aGVyIHRoZSBnaXZlbiB2YWx1ZSBpcyBhIHRyYW5zaWVudCBjb250ZXh0IHZhbHVlXG4gKlxuICogVmFsdWVzIHRoYXQgYXJlIG9iamVjdHMgd2l0aCBhIG1hZ2ljIGtleSBzZXQgdG8gYSB0cnV0aHkgdmFsdWUgYXJlIGNvbnNpZGVyZWQgdHJhbnNpZW50LlxuICovXG5mdW5jdGlvbiBpc1RyYW5zaWVudFZhbHVlKHZhbHVlOiBhbnkpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwgJiYgKHZhbHVlIGFzIGFueSlbVFJBTlNJRU5UX0NPTlRFWFRfS0VZXTtcbn1cblxuZnVuY3Rpb24gZXhwZWN0U3RyaW5nTGlzdCh4OiB1bmtub3duKTogc3RyaW5nW10gfCB1bmRlZmluZWQge1xuICBpZiAoeCA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cbiAgaWYgKCFBcnJheS5pc0FycmF5KHgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBhcnJheSwgZ290ICcke3h9J2ApO1xuICB9XG4gIGNvbnN0IG5vblN0cmluZ3MgPSB4LmZpbHRlcihlID0+IHR5cGVvZiBlICE9PSAnc3RyaW5nJyk7XG4gIGlmIChub25TdHJpbmdzLmxlbmd0aCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIGxpc3Qgb2Ygc3RyaW5ncywgZm91bmQgJHtub25TdHJpbmdzfWApO1xuICB9XG4gIHJldHVybiB4O1xufVxuIl19