@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
414 lines • 41.9 kB
JavaScript
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.unionValidator = exports.requireProperty = exports.requiredValidator = exports.propertyValidator = exports.hashValidator = exports.listValidator = exports.validateCfnTag = exports.validateObject = exports.validateDate = exports.validateBoolean = exports.validateNumber = exports.validateString = exports.canInspect = exports.VALIDATION_SUCCESS = exports.ValidationResults = exports.ValidationResult = exports.unionMapper = exports.hashMapper = exports.listMapper = exports.cfnTagToCloudFormation = exports.dateToCloudFormation = exports.numberToCloudFormation = exports.objectToCloudFormation = exports.booleanToCloudFormation = exports.stringToCloudFormation = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
function identity(x) {
return x;
}
exports.stringToCloudFormation = identity;
exports.booleanToCloudFormation = identity;
exports.objectToCloudFormation = identity;
exports.numberToCloudFormation = identity;
/**
* The date needs to be formatted as an ISO date in UTC
*
* Some usage sites require a date, some require a timestamp. We'll
* always output a timestamp and hope the parser on the other end
* is smart enough to ignore the time part... (?)
*/
function dateToCloudFormation(x) {
if (!x) {
return undefined;
}
// eslint-disable-next-line max-len
return `${x.getUTCFullYear()}-${pad(x.getUTCMonth() + 1)}-${pad(x.getUTCDate())}T${pad(x.getUTCHours())}:${pad(x.getUTCMinutes())}:${pad(x.getUTCSeconds())}`;
}
exports.dateToCloudFormation = dateToCloudFormation;
/**
* Pad a number to 2 decimal places
*/
function pad(x) {
if (x < 10) {
return '0' + x.toString();
}
return x.toString();
}
/**
* Turn a tag object into the proper CloudFormation representation
*/
function cfnTagToCloudFormation(x) {
return {
Key: x.key,
Value: x.value,
};
}
exports.cfnTagToCloudFormation = cfnTagToCloudFormation;
function listMapper(elementMapper) {
return (x) => {
if (!canInspect(x)) {
return x;
}
return x.map(elementMapper);
};
}
exports.listMapper = listMapper;
function hashMapper(elementMapper) {
return (x) => {
if (!canInspect(x)) {
return x;
}
const ret = {};
Object.keys(x).forEach((key) => {
ret[key] = elementMapper(x[key]);
});
return ret;
};
}
exports.hashMapper = hashMapper;
/**
* Return a union mapper
*
* Takes a list of validators and a list of mappers, which should correspond pairwise.
*
* The mapper of the first successful validator will be called.
*/
function unionMapper(validators, mappers) {
if (validators.length !== mappers.length) {
throw Error('Not the same amount of validators and mappers passed to unionMapper()');
}
return (x) => {
if (!canInspect(x)) {
return x;
}
for (let i = 0; i < validators.length; i++) {
if (validators[i](x).isSuccess) {
return mappers[i](x);
}
}
// Should not be possible because the union must have passed validation before this function
// will be called, but catch it anyway.
throw new TypeError('No validators matched in the union()');
};
}
exports.unionMapper = unionMapper;
// ----------------------------------------------------------------------
// VALIDATORS
//
// These are used while checking that supplied property bags match the expected schema
//
// We have a couple of datatypes that model validation errors and collections of validation
// errors (together forming a tree of errors so that we can trace validation errors through
// an object graph), and validators.
//
// Validators are simply functions that take a value and return a validation results. Then
// we have some combinators to turn primitive validators into more complex validators.
//
/**
* Representation of validation results
*
* Models a tree of validation errors so that we have as much information as possible
* about the failure that occurred.
*/
class ValidationResult {
constructor(errorMessage = '', results = new ValidationResults()) {
this.errorMessage = errorMessage;
this.results = results;
try {
jsiiDeprecationWarnings._aws_cdk_core_ValidationResults(results);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, ValidationResult);
}
throw error;
}
}
get isSuccess() {
return !this.errorMessage && this.results.isSuccess;
}
/**
* Turn a failed validation into an exception
*/
assertSuccess() {
if (!this.isSuccess) {
let message = this.errorTree();
// The first letter will be lowercase, so uppercase it for a nicer error message
message = message.slice(0, 1).toUpperCase() + message.slice(1);
throw new CfnSynthesisError(message);
}
}
/**
* Return a string rendering of the tree of validation failures
*/
errorTree() {
const childMessages = this.results.errorTreeList();
return this.errorMessage + (childMessages.length ? `\n ${childMessages.replace(/\n/g, '\n ')}` : '');
}
/**
* Wrap this result with an error message, if it concerns an error
*/
prefix(message) {
if (this.isSuccess) {
return this;
}
return new ValidationResult(`${message}: ${this.errorMessage}`, this.results);
}
}
exports.ValidationResult = ValidationResult;
_a = JSII_RTTI_SYMBOL_1;
ValidationResult[_a] = { fqn: "@aws-cdk/core.ValidationResult", version: "1.204.0" };
/**
* A collection of validation results
*/
class ValidationResults {
constructor(results = []) {
this.results = results;
}
collect(result) {
try {
jsiiDeprecationWarnings._aws_cdk_core_ValidationResult(result);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.collect);
}
throw error;
}
// Only collect failures
if (!result.isSuccess) {
this.results.push(result);
}
}
get isSuccess() {
return this.results.every(x => x.isSuccess);
}
errorTreeList() {
return this.results.map(child => child.errorTree()).join('\n');
}
/**
* Wrap up all validation results into a single tree node
*
* If there are failures in the collection, add a message, otherwise
* return a success.
*/
wrap(message) {
if (this.isSuccess) {
return exports.VALIDATION_SUCCESS;
}
return new ValidationResult(message, this);
}
}
exports.ValidationResults = ValidationResults;
_b = JSII_RTTI_SYMBOL_1;
ValidationResults[_b] = { fqn: "@aws-cdk/core.ValidationResults", version: "1.204.0" };
// Singleton object to save on allocations
exports.VALIDATION_SUCCESS = new ValidationResult();
/**
* Return whether this object can be validated at all
*
* True unless it's undefined or a CloudFormation intrinsic
*/
function canInspect(x) {
// Note: using weak equality on purpose, we also want to catch undefined
return (x != null && !isCloudFormationIntrinsic(x) && !isCloudFormationDynamicReference(x));
}
exports.canInspect = canInspect;
// CloudFormation validators for primitive types
function validateString(x) {
if (canInspect(x) && typeof x !== 'string') {
return new ValidationResult(`${JSON.stringify(x)} should be a string`);
}
return exports.VALIDATION_SUCCESS;
}
exports.validateString = validateString;
function validateNumber(x) {
if (canInspect(x) && typeof x !== 'number') {
return new ValidationResult(`${JSON.stringify(x)} should be a number`);
}
return exports.VALIDATION_SUCCESS;
}
exports.validateNumber = validateNumber;
function validateBoolean(x) {
if (canInspect(x) && typeof x !== 'boolean') {
return new ValidationResult(`${JSON.stringify(x)} should be a boolean`);
}
return exports.VALIDATION_SUCCESS;
}
exports.validateBoolean = validateBoolean;
function validateDate(x) {
if (canInspect(x) && !(x instanceof Date)) {
return new ValidationResult(`${JSON.stringify(x)} should be a Date`);
}
if (x !== undefined && isNaN(x.getTime())) {
return new ValidationResult('got an unparseable Date');
}
return exports.VALIDATION_SUCCESS;
}
exports.validateDate = validateDate;
function validateObject(x) {
if (canInspect(x) && typeof x !== 'object') {
return new ValidationResult(`${JSON.stringify(x)} should be an 'object'`);
}
return exports.VALIDATION_SUCCESS;
}
exports.validateObject = validateObject;
function validateCfnTag(x) {
if (!canInspect(x)) {
return exports.VALIDATION_SUCCESS;
}
if (x.key == null || x.value == null) {
return new ValidationResult(`${JSON.stringify(x)} should have a 'key' and a 'value' property`);
}
return exports.VALIDATION_SUCCESS;
}
exports.validateCfnTag = validateCfnTag;
/**
* Return a list validator based on the given element validator
*/
function listValidator(elementValidator) {
return (x) => {
if (!canInspect(x)) {
return exports.VALIDATION_SUCCESS;
}
if (!x.forEach) {
return new ValidationResult(`${JSON.stringify(x)} should be a list`);
}
for (let i = 0; i < x.length; i++) {
const element = x[i];
const result = elementValidator(element);
if (!result.isSuccess) {
return result.prefix(`element ${i}`);
}
}
return exports.VALIDATION_SUCCESS;
};
}
exports.listValidator = listValidator;
/**
* Return a hash validator based on the given element validator
*/
function hashValidator(elementValidator) {
return (x) => {
if (!canInspect(x)) {
return exports.VALIDATION_SUCCESS;
}
for (const key of Object.keys(x)) {
const result = elementValidator(x[key]);
if (!result.isSuccess) {
return result.prefix(`element '${key}'`);
}
}
return exports.VALIDATION_SUCCESS;
};
}
exports.hashValidator = hashValidator;
/**
* Decorate a validator with a message clarifying the property the failure is for.
*/
function propertyValidator(propName, validator) {
return (x) => {
return validator(x).prefix(propName);
};
}
exports.propertyValidator = propertyValidator;
/**
* Return a validator that will fail if the passed property is not present
*
* Does not distinguish between the property actually not being present, vs being present but 'null'
* or 'undefined' (courtesy of JavaScript), which is generally the behavior that we want.
*
* Empty strings are considered "present"--don't know if this agrees with how CloudFormation looks
* at the world.
*/
function requiredValidator(x) {
if (x == null) {
return new ValidationResult('required but missing');
}
return exports.VALIDATION_SUCCESS;
}
exports.requiredValidator = requiredValidator;
/**
* Require a property from a property bag.
*
* @param props the property bag from which a property is required.
* @param name the name of the required property.
* @param typeName the name of the construct type that requires the property
*
* @returns the value of ``props[name]``
*
* @throws if the property ``name`` is not present in ``props``.
*/
function requireProperty(props, name, context) {
const value = props[name];
if (value == null) {
throw new Error(`${context.toString()} is missing required property: ${name}`);
}
// Possibly add type-checking here...
return value;
}
exports.requireProperty = requireProperty;
/**
* Validates if any of the given validators matches
*
* We add either/or words to the front of the error mesages so that they read
* more nicely. Example:
*
* Properties not correct for 'FunctionProps'
* codeUri: not one of the possible types
* either: properties not correct for 'S3LocationProperty'
* bucket: required but missing
* key: required but missing
* version: required but missing
* or: '3' should be a 'string'
*
*/
function unionValidator(...validators) {
return (x) => {
const results = new ValidationResults();
let eitherOr = 'either';
for (const validator of validators) {
const result = validator(x);
if (result.isSuccess) {
return result;
}
results.collect(result.prefix(eitherOr));
eitherOr = 'or';
}
return results.wrap('not one of the possible types');
};
}
exports.unionValidator = unionValidator;
/**
* Return whether the indicated value represents a CloudFormation intrinsic.
*
* CloudFormation intrinsics are modeled as objects with a single key, which
* look like: { "Fn::GetAtt": [...] } or similar.
*/
function isCloudFormationIntrinsic(x) {
if (!(typeof x === 'object')) {
return false;
}
const keys = Object.keys(x);
if (keys.length !== 1) {
return false;
}
return keys[0] === 'Ref' || keys[0].slice(0, 4) === 'Fn::';
}
/**
* Check whether the indicated value is a CloudFormation dynamic reference.
*
* CloudFormation dynamic references take the format: '{{resolve:service-name:reference-key}}'
*/
function isCloudFormationDynamicReference(x) {
return (typeof x === 'string' && x.startsWith('{{resolve:') && x.endsWith('}}'));
}
// Cannot be public because JSII gets confused about es5.d.ts
class CfnSynthesisError extends Error {
constructor() {
super(...arguments);
this.type = 'CfnSynthesisError';
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJ1bnRpbWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBWUEsU0FBUyxRQUFRLENBQUMsQ0FBTTtJQUN0QixPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFWSxRQUFBLHNCQUFzQixHQUFXLFFBQVEsQ0FBQztBQUMxQyxRQUFBLHVCQUF1QixHQUFXLFFBQVEsQ0FBQztBQUMzQyxRQUFBLHNCQUFzQixHQUFXLFFBQVEsQ0FBQztBQUMxQyxRQUFBLHNCQUFzQixHQUFXLFFBQVEsQ0FBQztBQUV2RDs7Ozs7O0dBTUc7QUFDSCxTQUFnQixvQkFBb0IsQ0FBQyxDQUFRO0lBQzNDLElBQUksQ0FBQyxDQUFDLEVBQUU7UUFDTixPQUFPLFNBQVMsQ0FBQztLQUNsQjtJQUVELG1DQUFtQztJQUNuQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLGNBQWMsRUFBRSxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDaEssQ0FBQztBQVBELG9EQU9DO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLEdBQUcsQ0FBQyxDQUFTO0lBQ3BCLElBQUksQ0FBQyxHQUFHLEVBQUUsRUFBRTtRQUNWLE9BQU8sR0FBRyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztLQUMzQjtJQUNELE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ3RCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLHNCQUFzQixDQUFDLENBQU07SUFDM0MsT0FBTztRQUNMLEdBQUcs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O0FBQzdELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxnQ0FBZ0MsQ0FBQyxDQUFNO0lBQzlDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDbkYsQ0FBQztBQUVELDZEQUE2RDtBQUM3RCxNQUFNLGlCQUFrQixTQUFRLEtBQUs7SUFBckM7O1FBQ2tCLFNBQUksR0FBRyxtQkFBbUIsQ0FBQztJQUM3QyxDQUFDO0NBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICcuL2NvbnN0cnVjdC1jb21wYXQnO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBQUk9QRVJUWSBNQVBQRVJTXG4vL1xuLy8gVGhlc2UgYXJlIHVzZWQgd2hpbGUgY29udmVydGluZyBnZW5lcmF0ZWQgY2xhc3Nlcy9wcm9wZXJ0eSBiYWdzIHRvIENsb3VkRm9ybWF0aW9uIHByb3BlcnR5IG9iamVjdHNcbi8vXG4vLyBXZSB1c2UgaWRlbnRpdHkgbWFwcGVycyBmb3IgdGhlIHByaW1pdGl2ZSB0eXBlcy4gVGhlc2UgZG9uJ3QgZG8gYW55dGhpbmcgYnV0IGFyZSB0aGVyZSB0byBtYWtlIHRoZSBjb2RlXG4vLyBnZW5lcmF0aW9uIHdvcmsgb3V0IG5pY2VseSAoc28gdGhlIGNvZGUgZ2VuZXJhdG9yIGRvZXNuJ3QgbmVlZCB0byBlbWl0IGRpZmZlcmVudCBjb2RlIGZvciBwcmltaXRpdmVcbi8vIHZzLiBjb21wbGV4IHR5cGVzKS5cbmV4cG9ydCB0eXBlIE1hcHBlciA9ICh4OiBhbnkpID0+IGFueTtcblxuZnVuY3Rpb24gaWRlbnRpdHkoeDogYW55KSB7XG4gIHJldHVybiB4O1xufVxuXG5leHBvcnQgY29uc3Qgc3RyaW5nVG9DbG91ZEZvcm1hdGlvbjogTWFwcGVyID0gaWRlbnRpdHk7XG5leHBvcnQgY29uc3QgYm9vbGVhblRvQ2xvdWRGb3JtYXRpb246IE1hcHBlciA9IGlkZW50aXR5O1xuZXhwb3J0IGNvbnN0IG9iamVjdFRvQ2xvdWRGb3JtYXRpb246IE1hcHBlciA9IGlkZW50aXR5O1xuZXhwb3J0IGNvbnN0IG51bWJlclRvQ2xvdWRGb3JtYXRpb246IE1hcHBlciA9IGlkZW50aXR5O1xuXG4vKipcbiAqIFRoZSBkYXRlIG5lZWRzIHRvIGJlIGZvcm1hdHRlZCBhcyBhbiBJU08gZGF0ZSBpbiBVVENcbiAqXG4gKiBTb21lIHVzYWdlIHNpdGVzIHJlcXVpcmUgYSBkYXRlLCBzb21lIHJlcXVpcmUgYSB0aW1lc3RhbXAuIFdlJ2xsXG4gKiBhbHdheXMgb3V0cHV0IGEgdGltZXN0YW1wIGFuZCBob3BlIHRoZSBwYXJzZXIgb24gdGhlIG90aGVyIGVuZFxuICogaXMgc21hcnQgZW5vdWdoIHRvIGlnbm9yZSB0aGUgdGltZSBwYXJ0Li4uICg/KVxuICovXG5leHBvcnQgZnVuY3Rpb24gZGF0ZVRvQ2xvdWRGb3JtYXRpb24oeD86IERhdGUpOiBhbnkge1xuICBpZiAoIXgpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgcmV0dXJuIGAke3guZ2V0VVRDRnVsbFllYXIoKX0tJHtwYWQoeC5nZXRVVENNb250aCgpICsgMSl9LSR7cGFkKHguZ2V0VVRDRGF0ZSgpKX1UJHtwYWQoeC5nZXRVVENIb3VycygpKX06JHtwYWQoeC5nZXRVVENNaW51dGVzKCkpfToke3BhZCh4LmdldFVUQ1NlY29uZHMoKSl9YDtcbn1cblxuLyoqXG4gKiBQYWQgYSBudW1iZXIgdG8gMiBkZWNpbWFsIHBsYWNlc1xuICovXG5mdW5jdGlvbiBwYWQoeDogbnVtYmVyKSB7XG4gIGlmICh4IDwgMTApIHtcbiAgICByZXR1cm4gJzAnICsgeC50b1N0cmluZygpO1xuICB9XG4gIHJldHVybiB4LnRvU3RyaW5nKCk7XG59XG5cbi8qKlxuICogVHVybiBhIHRhZyBvYmplY3QgaW50byB0aGUgcHJvcGVyIENsb3VkRm9ybWF0aW9uIHJlcHJlc2VudGF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjZm5UYWdUb0Nsb3VkRm9ybWF0aW9uKHg6IGFueSk6IGFueSB7XG4gIHJldHVybiB7XG4gICAgS2V5OiB4LmtleSxcbiAgICBWYWx1ZTogeC52YWx1ZSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RNYXBwZXIoZWxlbWVudE1hcHBlcjogTWFwcGVyKTogTWFwcGVyIHtcbiAgcmV0dXJuICh4OiBhbnkpID0+IHtcbiAgICBpZiAoIWNhbkluc3BlY3QoeCkpIHsgcmV0dXJuIHg7IH1cbiAgICByZXR1cm4geC5tYXAoZWxlbWVudE1hcHBlcik7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNoTWFwcGVyKGVsZW1lbnRNYXBwZXI6IE1hcHBlcik6IE1hcHBlciB7XG4gIHJldHVybiAoeDogYW55KSA9PiB7XG4gICAgaWYgKCFjYW5JbnNwZWN0KHgpKSB7IHJldHVybiB4OyB9XG5cbiAgICBjb25zdCByZXQ6IGFueSA9IHt9O1xuXG4gICAgT2JqZWN0LmtleXMoeCkuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICByZXRba2V5XSA9IGVsZW1lbnRNYXBwZXIoeFtrZXldKTtcbiAgICB9KTtcblxuICAgIHJldHVybiByZXQ7XG4gIH07XG59XG5cbi8qKlxuICogUmV0dXJuIGEgdW5pb24gbWFwcGVyXG4gKlxuICogVGFrZXMgYSBsaXN0IG9mIHZhbGlkYXRvcnMgYW5kIGEgbGlzdCBvZiBtYXBwZXJzLCB3aGljaCBzaG91bGQgY29ycmVzcG9uZCBwYWlyd2lzZS5cbiAqXG4gKiBUaGUgbWFwcGVyIG9mIHRoZSBmaXJzdCBzdWNjZXNzZnVsIHZhbGlkYXRvciB3aWxsIGJlIGNhbGxlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuaW9uTWFwcGVyKHZhbGlkYXRvcnM6IFZhbGlkYXRvcltdLCBtYXBwZXJzOiBNYXBwZXJbXSk6IE1hcHBlciB7XG4gIGlmICh2YWxpZGF0b3JzLmxlbmd0aCAhPT0gbWFwcGVycy5sZW5ndGgpIHtcbiAgICB0aHJvdyBFcnJvcignTm90IHRoZSBzYW1lIGFtb3VudCBvZiB2YWxpZGF0b3JzIGFuZCBtYXBwZXJzIHBhc3NlZCB0byB1bmlvbk1hcHBlcigpJyk7XG4gIH1cblxuICByZXR1cm4gKHg6IGFueSkgPT4ge1xuICAgIGlmICghY2FuSW5zcGVjdCh4KSkgeyByZXR1cm4geDsgfVxuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWxpZGF0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodmFsaWRhdG9yc1tpXSh4KS5pc1N1Y2Nlc3MpIHtcbiAgICAgICAgcmV0dXJuIG1hcHBlcnNbaV0oeCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gU2hvdWxkIG5vdCBiZSBwb3NzaWJsZSBiZWNhdXNlIHRoZSB1bmlvbiBtdXN0IGhhdmUgcGFzc2VkIHZhbGlkYXRpb24gYmVmb3JlIHRoaXMgZnVuY3Rpb25cbiAgICAvLyB3aWxsIGJlIGNhbGxlZCwgYnV0IGNhdGNoIGl0IGFueXdheS5cbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdObyB2YWxpZGF0b3JzIG1hdGNoZWQgaW4gdGhlIHVuaW9uKCknKTtcbiAgfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gVkFMSURBVE9SU1xuLy9cbi8vIFRoZXNlIGFyZSB1c2VkIHdoaWxlIGNoZWNraW5nIHRoYXQgc3VwcGxpZWQgcHJvcGVydHkgYmFncyBtYXRjaCB0aGUgZXhwZWN0ZWQgc2NoZW1hXG4vL1xuLy8gV2UgaGF2ZSBhIGNvdXBsZSBvZiBkYXRhdHlwZXMgdGhhdCBtb2RlbCB2YWxpZGF0aW9uIGVycm9ycyBhbmQgY29sbGVjdGlvbnMgb2YgdmFsaWRhdGlvblxuLy8gZXJyb3JzICh0b2dldGhlciBmb3JtaW5nIGEgdHJlZSBvZiBlcnJvcnMgc28gdGhhdCB3ZSBjYW4gdHJhY2UgdmFsaWRhdGlvbiBlcnJvcnMgdGhyb3VnaFxuLy8gYW4gb2JqZWN0IGdyYXBoKSwgYW5kIHZhbGlkYXRvcnMuXG4vL1xuLy8gVmFsaWRhdG9ycyBhcmUgc2ltcGx5IGZ1bmN0aW9ucyB0aGF0IHRha2UgYSB2YWx1ZSBhbmQgcmV0dXJuIGEgdmFsaWRhdGlvbiByZXN1bHRzLiBUaGVuXG4vLyB3ZSBoYXZlIHNvbWUgY29tYmluYXRvcnMgdG8gdHVybiBwcmltaXRpdmUgdmFsaWRhdG9ycyBpbnRvIG1vcmUgY29tcGxleCB2YWxpZGF0b3JzLlxuLy9cblxuLyoqXG4gKiBSZXByZXNlbnRhdGlvbiBvZiB2YWxpZGF0aW9uIHJlc3VsdHNcbiAqXG4gKiBNb2RlbHMgYSB0cmVlIG9mIHZhbGlkYXRpb24gZXJyb3JzIHNvIHRoYXQgd2UgaGF2ZSBhcyBtdWNoIGluZm9ybWF0aW9uIGFzIHBvc3NpYmxlXG4gKiBhYm91dCB0aGUgZmFpbHVyZSB0aGF0IG9jY3VycmVkLlxuICovXG5leHBvcnQgY2xhc3MgVmFsaWRhdGlvblJlc3VsdCB7XG4gIGNvbnN0cnVjdG9yKHJlYWRvbmx5IGVycm9yTWVzc2FnZTogc3RyaW5nID0gJycsIHJlYWRvbmx5IHJlc3VsdHM6IFZhbGlkYXRpb25SZXN1bHRzID0gbmV3IFZhbGlkYXRpb25SZXN1bHRzKCkpIHtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgaXNTdWNjZXNzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhdGhpcy5lcnJvck1lc3NhZ2UgJiYgdGhpcy5yZXN1bHRzLmlzU3VjY2VzcztcbiAgfVxuXG4gIC8qKlxuICAgKiBUdXJuIGEgZmFpbGVkIHZhbGlkYXRpb24gaW50byBhbiBleGNlcHRpb25cbiAgICovXG4gIHB1YmxpYyBhc3NlcnRTdWNjZXNzKCkge1xuICAgIGlmICghdGhpcy5pc1N1Y2Nlc3MpIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdGhpcy5lcnJvclRyZWUoKTtcbiAgICAgIC8vIFRoZSBmaXJzdCBsZXR0ZXIgd2lsbCBiZSBsb3dlcmNhc2UsIHNvIHVwcGVyY2FzZSBpdCBmb3IgYSBuaWNlciBlcnJvciBtZXNzYWdlXG4gICAgICBtZXNzYWdlID0gbWVzc2FnZS5zbGljZSgwLCAxKS50b1VwcGVyQ2FzZSgpICsgbWVzc2FnZS5zbGljZSgxKTtcbiAgICAgIHRocm93IG5ldyBDZm5TeW50aGVzaXNFcnJvcihtZXNzYWdlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGEgc3RyaW5nIHJlbmRlcmluZyBvZiB0aGUgdHJlZSBvZiB2YWxpZGF0aW9uIGZhaWx1cmVzXG4gICAqL1xuICBwdWJsaWMgZXJyb3JUcmVlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgY2hpbGRNZXNzYWdlcyA9IHRoaXMucmVzdWx0cy5lcnJvclRyZWVMaXN0KCk7XG4gICAgcmV0dXJuIHRoaXMuZXJyb3JNZXNzYWdlICsgKGNoaWxkTWVzc2FnZXMubGVuZ3RoID8gYFxcbiAgJHtjaGlsZE1lc3NhZ2VzLnJlcGxhY2UoL1xcbi9nLCAnXFxuICAnKX1gIDogJycpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdyYXAgdGhpcyByZXN1bHQgd2l0aCBhbiBlcnJvciBtZXNzYWdlLCBpZiBpdCBjb25jZXJucyBhbiBlcnJvclxuICAgKi9cbiAgcHVibGljIHByZWZpeChtZXNzYWdlOiBzdHJpbmcpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgICBpZiAodGhpcy5pc1N1Y2Nlc3MpIHsgcmV0dXJuIHRoaXM7IH1cbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7bWVzc2FnZX06ICR7dGhpcy5lcnJvck1lc3NhZ2V9YCwgdGhpcy5yZXN1bHRzKTtcbiAgfVxufVxuXG4vKipcbiAqIEEgY29sbGVjdGlvbiBvZiB2YWxpZGF0aW9uIHJlc3VsdHNcbiAqL1xuZXhwb3J0IGNsYXNzIFZhbGlkYXRpb25SZXN1bHRzIHtcbiAgY29uc3RydWN0b3IocHVibGljIHJlc3VsdHM6IFZhbGlkYXRpb25SZXN1bHRbXSA9IFtdKSB7XG4gIH1cblxuICBwdWJsaWMgY29sbGVjdChyZXN1bHQ6IFZhbGlkYXRpb25SZXN1bHQpIHtcbiAgICAvLyBPbmx5IGNvbGxlY3QgZmFpbHVyZXNcbiAgICBpZiAoIXJlc3VsdC5pc1N1Y2Nlc3MpIHtcbiAgICAgIHRoaXMucmVzdWx0cy5wdXNoKHJlc3VsdCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldCBpc1N1Y2Nlc3MoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucmVzdWx0cy5ldmVyeSh4ID0+IHguaXNTdWNjZXNzKTtcbiAgfVxuXG4gIHB1YmxpYyBlcnJvclRyZWVMaXN0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMucmVzdWx0cy5tYXAoY2hpbGQgPT4gY2hpbGQuZXJyb3JUcmVlKCkpLmpvaW4oJ1xcbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdyYXAgdXAgYWxsIHZhbGlkYXRpb24gcmVzdWx0cyBpbnRvIGEgc2luZ2xlIHRyZWUgbm9kZVxuICAgKlxuICAgKiBJZiB0aGVyZSBhcmUgZmFpbHVyZXMgaW4gdGhlIGNvbGxlY3Rpb24sIGFkZCBhIG1lc3NhZ2UsIG90aGVyd2lzZVxuICAgKiByZXR1cm4gYSBzdWNjZXNzLlxuICAgKi9cbiAgcHVibGljIHdyYXAobWVzc2FnZTogc3RyaW5nKTogVmFsaWRhdGlvblJlc3VsdCB7XG4gICAgaWYgKHRoaXMuaXNTdWNjZXNzKSB7wqByZXR1cm4gVkFMSURBVElPTl9TVUNDRVNTOyB9XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uUmVzdWx0KG1lc3NhZ2UsIHRoaXMpO1xuICB9XG59XG5cbi8vIFNpbmdsZXRvbiBvYmplY3QgdG8gc2F2ZSBvbiBhbGxvY2F0aW9uc1xuZXhwb3J0IGNvbnN0IFZBTElEQVRJT05fU1VDQ0VTUyA9IG5ldyBWYWxpZGF0aW9uUmVzdWx0KCk7XG5cbmV4cG9ydCB0eXBlIFZhbGlkYXRvciA9ICh4OiBhbnkpID0+IFZhbGlkYXRpb25SZXN1bHQ7XG5cbi8qKlxuICogUmV0dXJuIHdoZXRoZXIgdGhpcyBvYmplY3QgY2FuIGJlIHZhbGlkYXRlZCBhdCBhbGxcbiAqXG4gKiBUcnVlIHVubGVzcyBpdCdzIHVuZGVmaW5lZCBvciBhIENsb3VkRm9ybWF0aW9uIGludHJpbnNpY1xuICovXG5leHBvcnQgZnVuY3Rpb24gY2FuSW5zcGVjdCh4OiBhbnkpIHtcbiAgLy8gTm90ZTogdXNpbmcgd2VhayBlcXVhbGl0eSBvbiBwdXJwb3NlLCB3ZSBhbHNvIHdhbnQgdG8gY2F0Y2ggdW5kZWZpbmVkXG4gIHJldHVybiAoeCAhPSBudWxsICYmICFpc0Nsb3VkRm9ybWF0aW9uSW50cmluc2ljKHgpICYmICFpc0Nsb3VkRm9ybWF0aW9uRHluYW1pY1JlZmVyZW5jZSh4KSk7XG59XG5cbi8vIENsb3VkRm9ybWF0aW9uIHZhbGlkYXRvcnMgZm9yIHByaW1pdGl2ZSB0eXBlc1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlU3RyaW5nKHg6IGFueSk6IFZhbGlkYXRpb25SZXN1bHQge1xuICBpZiAoY2FuSW5zcGVjdCh4KSAmJiB0eXBlb2YgeCAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7SlNPTi5zdHJpbmdpZnkoeCl9IHNob3VsZCBiZSBhIHN0cmluZ2ApO1xuICB9XG4gIHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZU51bWJlcih4OiBhbnkpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgaWYgKGNhbkluc3BlY3QoeCkgJiYgdHlwZW9mIHggIT09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uUmVzdWx0KGAke0pTT04uc3RyaW5naWZ5KHgpfSBzaG91bGQgYmUgYSBudW1iZXJgKTtcbiAgfVxuICByZXR1cm4gVkFMSURBVElPTl9TVUNDRVNTO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVCb29sZWFuKHg6IGFueSk6IFZhbGlkYXRpb25SZXN1bHQge1xuICBpZiAoY2FuSW5zcGVjdCh4KSAmJiB0eXBlb2YgeCAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uUmVzdWx0KGAke0pTT04uc3RyaW5naWZ5KHgpfSBzaG91bGQgYmUgYSBib29sZWFuYCk7XG4gIH1cbiAgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlRGF0ZSh4OiBhbnkpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgaWYgKGNhbkluc3BlY3QoeCkgJiYgISh4IGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7SlNPTi5zdHJpbmdpZnkoeCl9IHNob3VsZCBiZSBhIERhdGVgKTtcbiAgfVxuXG4gIGlmICh4ICE9PSB1bmRlZmluZWQgJiYgaXNOYU4oeC5nZXRUaW1lKCkpKSB7XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uUmVzdWx0KCdnb3QgYW4gdW5wYXJzZWFibGUgRGF0ZScpO1xuICB9XG5cbiAgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlT2JqZWN0KHg6IGFueSk6IFZhbGlkYXRpb25SZXN1bHQge1xuICBpZiAoY2FuSW5zcGVjdCh4KSAmJiB0eXBlb2YgeCAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7SlNPTi5zdHJpbmdpZnkoeCl9IHNob3VsZCBiZSBhbiAnb2JqZWN0J2ApO1xuICB9XG4gIHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUNmblRhZyh4OiBhbnkpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgaWYgKCFjYW5JbnNwZWN0KHgpKSB7IHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7IH1cblxuICBpZiAoeC5rZXkgPT0gbnVsbCB8fCB4LnZhbHVlID09IG51bGwpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoYCR7SlNPTi5zdHJpbmdpZnkoeCl9IHNob3VsZCBoYXZlIGEgJ2tleScgYW5kIGEgJ3ZhbHVlJyBwcm9wZXJ0eWApO1xuICB9XG5cbiAgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUztcbn1cblxuLyoqXG4gKiBSZXR1cm4gYSBsaXN0IHZhbGlkYXRvciBiYXNlZCBvbiB0aGUgZ2l2ZW4gZWxlbWVudCB2YWxpZGF0b3JcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpc3RWYWxpZGF0b3IoZWxlbWVudFZhbGlkYXRvcjogVmFsaWRhdG9yKTogVmFsaWRhdG9yIHtcbiAgcmV0dXJuICh4OiBhbnkpID0+IHtcbiAgICBpZiAoIWNhbkluc3BlY3QoeCkpIHsgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUzsgfVxuXG4gICAgaWYgKCF4LmZvckVhY2gpIHtcbiAgICAgIHJldHVybiBuZXcgVmFsaWRhdGlvblJlc3VsdChgJHtKU09OLnN0cmluZ2lmeSh4KX0gc2hvdWxkIGJlIGEgbGlzdGApO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgZWxlbWVudCA9IHhbaV07XG4gICAgICBjb25zdCByZXN1bHQgPSBlbGVtZW50VmFsaWRhdG9yKGVsZW1lbnQpO1xuICAgICAgaWYgKCFyZXN1bHQuaXNTdWNjZXNzKSB7IHJldHVybiByZXN1bHQucHJlZml4KGBlbGVtZW50ICR7aX1gKTsgfVxuICAgIH1cblxuICAgIHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7XG4gIH07XG59XG5cbi8qKlxuICogUmV0dXJuIGEgaGFzaCB2YWxpZGF0b3IgYmFzZWQgb24gdGhlIGdpdmVuIGVsZW1lbnQgdmFsaWRhdG9yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNoVmFsaWRhdG9yKGVsZW1lbnRWYWxpZGF0b3I6IFZhbGlkYXRvcik6IFZhbGlkYXRvciB7XG4gIHJldHVybiAoeDogYW55KSA9PiB7XG4gICAgaWYgKCFjYW5JbnNwZWN0KHgpKSB7IHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7IH1cblxuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHgpKSB7XG4gICAgICBjb25zdCByZXN1bHQgPSBlbGVtZW50VmFsaWRhdG9yKHhba2V5XSk7XG4gICAgICBpZiAoIXJlc3VsdC5pc1N1Y2Nlc3MpIHsgcmV0dXJuIHJlc3VsdC5wcmVmaXgoYGVsZW1lbnQgJyR7a2V5fSdgKTsgfVxuICAgIH1cblxuICAgIHJldHVybiBWQUxJREFUSU9OX1NVQ0NFU1M7XG4gIH07XG59XG5cbi8qKlxuICogRGVjb3JhdGUgYSB2YWxpZGF0b3Igd2l0aCBhIG1lc3NhZ2UgY2xhcmlmeWluZyB0aGUgcHJvcGVydHkgdGhlIGZhaWx1cmUgaXMgZm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJvcGVydHlWYWxpZGF0b3IocHJvcE5hbWU6IHN0cmluZywgdmFsaWRhdG9yOiBWYWxpZGF0b3IpOiBWYWxpZGF0b3Ige1xuICByZXR1cm4gKHg6IGFueSkgPT4ge1xuICAgIHJldHVybiB2YWxpZGF0b3IoeCkucHJlZml4KHByb3BOYW1lKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXR1cm4gYSB2YWxpZGF0b3IgdGhhdCB3aWxsIGZhaWwgaWYgdGhlIHBhc3NlZCBwcm9wZXJ0eSBpcyBub3QgcHJlc2VudFxuICpcbiAqIERvZXMgbm90IGRpc3Rpbmd1aXNoIGJldHdlZW4gdGhlIHByb3BlcnR5IGFjdHVhbGx5IG5vdCBiZWluZyBwcmVzZW50LCB2cyBiZWluZyBwcmVzZW50IGJ1dCAnbnVsbCdcbiAqIG9yICd1bmRlZmluZWQnIChjb3VydGVzeSBvZiBKYXZhU2NyaXB0KSwgd2hpY2ggaXMgZ2VuZXJhbGx5IHRoZSBiZWhhdmlvciB0aGF0IHdlIHdhbnQuXG4gKlxuICogRW1wdHkgc3RyaW5ncyBhcmUgY29uc2lkZXJlZCBcInByZXNlbnRcIi0tZG9uJ3Qga25vdyBpZiB0aGlzIGFncmVlcyB3aXRoIGhvdyBDbG91ZEZvcm1hdGlvbiBsb29rc1xuICogYXQgdGhlIHdvcmxkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZWRWYWxpZGF0b3IoeDogYW55KSB7XG4gIGlmICh4ID09IG51bGwpIHtcbiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25SZXN1bHQoJ3JlcXVpcmVkIGJ1dCBtaXNzaW5nJyk7XG4gIH1cbiAgcmV0dXJuIFZBTElEQVRJT05fU1VDQ0VTUztcbn1cblxuLyoqXG4gKiBSZXF1aXJlIGEgcHJvcGVydHkgZnJvbSBhIHByb3BlcnR5IGJhZy5cbiAqXG4gKiBAcGFyYW0gcHJvcHMgIHRoZSBwcm9wZXJ0eSBiYWcgZnJvbSB3aGljaCBhIHByb3BlcnR5IGlzIHJlcXVpcmVkLlxuICogQHBhcmFtIG5hbWUgICB0aGUgbmFtZSBvZiB0aGUgcmVxdWlyZWQgcHJvcGVydHkuXG4gKiBAcGFyYW0gdHlwZU5hbWUgdGhlIG5hbWUgb2YgdGhlIGNvbnN0cnVjdCB0eXBlIHRoYXQgcmVxdWlyZXMgdGhlIHByb3BlcnR5XG4gKlxuICogQHJldHVybnMgdGhlIHZhbHVlIG9mIGBgcHJvcHNbbmFtZV1gYFxuICpcbiAqIEB0aHJvd3MgaWYgdGhlIHByb3BlcnR5IGBgbmFtZWBgIGlzIG5vdCBwcmVzZW50IGluIGBgcHJvcHNgYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVQcm9wZXJ0eShwcm9wczogeyBbbmFtZTogc3RyaW5nXTogYW55IH0sIG5hbWU6IHN0cmluZywgY29udGV4dDogQ29uc3RydWN0KTogYW55IHtcbiAgY29uc3QgdmFsdWUgPSBwcm9wc1tuYW1lXTtcbiAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dC50b1N0cmluZygpfSBpcyBtaXNzaW5nIHJlcXVpcmVkIHByb3BlcnR5OiAke25hbWV9YCk7XG4gIH1cbiAgLy8gUG9zc2libHkgYWRkIHR5cGUtY2hlY2tpbmcgaGVyZS4uLlxuICByZXR1cm4gdmFsdWU7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIGlmIGFueSBvZiB0aGUgZ2l2ZW4gdmFsaWRhdG9ycyBtYXRjaGVzXG4gKlxuICogV2UgYWRkIGVpdGhlci9vciB3b3JkcyB0byB0aGUgZnJvbnQgb2YgdGhlIGVycm9yIG1lc2FnZXMgc28gdGhhdCB0aGV5IHJlYWRcbiAqIG1vcmUgbmljZWx5LiBFeGFtcGxlOlxuICpcbiAqICAgUHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgJ0Z1bmN0aW9uUHJvcHMnXG4gKiAgICAgY29kZVVyaTogbm90IG9uZSBvZiB0aGUgcG9zc2libGUgdHlwZXNcbiAqICAgICAgIGVpdGhlcjogcHJvcGVydGllcyBub3QgY29ycmVjdCBmb3IgJ1MzTG9jYXRpb25Qcm9wZXJ0eSdcbiAqICAgICAgICAgYnVja2V0OiByZXF1aXJlZCBidXQgbWlzc2luZ1xuICogICAgICAgICBrZXk6IHJlcXVpcmVkIGJ1dCBtaXNzaW5nXG4gKiAgICAgICAgIHZlcnNpb246IHJlcXVpcmVkIGJ1dCBtaXNzaW5nXG4gKiAgICAgICBvcjogJzMnIHNob3VsZCBiZSBhICdzdHJpbmcnXG4gKlxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pb25WYWxpZGF0b3IoLi4udmFsaWRhdG9yczogVmFsaWRhdG9yW10pOiBWYWxpZGF0b3Ige1xuICByZXR1cm4gKHg6IGFueSkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBuZXcgVmFsaWRhdGlvblJlc3VsdHMoKTtcbiAgICBsZXQgZWl0aGVyT3IgPSAnZWl0aGVyJztcblxuICAgIGZvciAoY29uc3QgdmFsaWRhdG9yIG9mIHZhbGlkYXRvcnMpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHZhbGlkYXRvcih4KTtcbiAgICAgIGlmIChyZXN1bHQuaXNTdWNjZXNzKSB7IHJldHVybiByZXN1bHQ7IH1cbiAgICAgIHJlc3VsdHMuY29sbGVjdChyZXN1bHQucHJlZml4KGVpdGhlck9yKSk7XG4gICAgICBlaXRoZXJPciA9ICdvcic7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzLndyYXAoJ25vdCBvbmUgb2YgdGhlIHBvc3NpYmxlIHR5cGVzJyk7XG4gIH07XG59XG5cbi8qKlxuICogUmV0dXJuIHdoZXRoZXIgdGhlIGluZGljYXRlZCB2YWx1ZSByZXByZXNlbnRzIGEgQ2xvdWRGb3JtYXRpb24gaW50cmluc2ljLlxuICpcbiAqIENsb3VkRm9ybWF0aW9uIGludHJpbnNpY3MgYXJlIG1vZGVsZWQgYXMgb2JqZWN0cyB3aXRoIGEgc2luZ2xlIGtleSwgd2hpY2hcbiAqIGxvb2sgbGlrZTogeyBcIkZuOjpHZXRBdHRcIjogWy4uLl0gfSBvciBzaW1pbGFyLlxuICovXG5mdW5jdGlvbiBpc0Nsb3VkRm9ybWF0aW9uSW50cmluc2ljKHg6IGFueSkge1xuICBpZiAoISh0eXBlb2YgeCA9PT0gJ29iamVjdCcpKSB7IHJldHVybiBmYWxzZTsgfVxuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMoeCk7XG4gIGlmIChrZXlzLmxlbmd0aCAhPT0gMSkgeyByZXR1cm4gZmFsc2U7IH1cblxuICByZXR1cm4ga2V5c1swXSA9PT0gJ1JlZicgfHwga2V5c1swXS5zbGljZSgwLCA0KSA9PT0gJ0ZuOjonO1xufVxuXG4vKipcbiAqIENoZWNrIHdoZXRoZXIgdGhlIGluZGljYXRlZCB2YWx1ZSBpcyBhIENsb3VkRm9ybWF0aW9uIGR5bmFtaWMgcmVmZXJlbmNlLlxuICpcbiAqIENsb3VkRm9ybWF0aW9uIGR5bmFtaWMgcmVmZXJlbmNlcyB0YWtlIHRoZSBmb3JtYXQ6ICd7e3Jlc29sdmU6c2VydmljZS1uYW1lOnJlZmVyZW5jZS1rZXl9fSdcbiAqL1xuZnVuY3Rpb24gaXNDbG91ZEZvcm1hdGlvbkR5bmFtaWNSZWZlcmVuY2UoeDogYW55KSB7XG4gIHJldHVybiAodHlwZW9mIHggPT09ICdzdHJpbmcnICYmIHguc3RhcnRzV2l0aCgne3tyZXNvbHZlOicpICYmIHguZW5kc1dpdGgoJ319JykpO1xufVxuXG4vLyBDYW5ub3QgYmUgcHVibGljIGJlY2F1c2UgSlNJSSBnZXRzIGNvbmZ1c2VkIGFib3V0IGVzNS5kLnRzXG5jbGFzcyBDZm5TeW50aGVzaXNFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgcHVibGljIHJlYWRvbmx5IHR5cGUgPSAnQ2ZuU3ludGhlc2lzRXJyb3InO1xufVxuIl19
;