@aws-cdk/assert
Version:
An assertion library for use with CDK Apps
404 lines • 45.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.annotateMatcher = exports.matcherFrom = exports.encodedJson = exports.Capture = exports.notMatching = exports.anything = exports.stringLike = exports.match = exports.failMatcher = exports.arrayWith = exports.exactValue = exports.deepObjectLike = exports.objectLike = void 0;
const have_resource_1 = require("./have-resource");
/**
* A matcher for an object that contains at least the given fields with the given matchers (or literals)
*
* Only does lenient matching one level deep, at the next level all objects must declare the
* exact expected keys again.
*/
function objectLike(pattern) {
return _objectContaining(pattern, false);
}
exports.objectLike = objectLike;
/**
* A matcher for an object that contains at least the given fields with the given matchers (or literals)
*
* Switches to "deep" lenient matching. Nested objects also only need to contain declared keys.
*/
function deepObjectLike(pattern) {
return _objectContaining(pattern, true);
}
exports.deepObjectLike = deepObjectLike;
function _objectContaining(pattern, deep) {
const anno = { [deep ? '$deepObjectLike' : '$objectLike']: pattern };
return annotateMatcher(anno, (value, inspection) => {
if (typeof value !== 'object' || !value) {
return failMatcher(inspection, `Expect an object but got '${typeof value}'`);
}
const errors = new Array();
for (const [patternKey, patternValue] of Object.entries(pattern)) {
if (patternValue === have_resource_1.ABSENT) {
if (value[patternKey] !== undefined) {
errors.push(`Field ${patternKey} present, but shouldn't be`);
}
continue;
}
if (!(patternKey in value)) {
errors.push(`Field ${patternKey} missing`);
continue;
}
// If we are doing DEEP objectLike, translate object literals in the pattern into
// more `deepObjectLike` matchers, even if they occur in lists.
const matchValue = deep ? deepMatcherFromObjectLiteral(patternValue) : patternValue;
const innerInspection = { ...inspection, failureReason: '' };
const valueMatches = match(value[patternKey], matchValue, innerInspection);
if (!valueMatches) {
errors.push(`Field ${patternKey} mismatch: ${innerInspection.failureReason}`);
}
}
/**
* Transform nested object literals into more deep object matchers, if applicable
*
* Object literals in lists are also transformed.
*/
function deepMatcherFromObjectLiteral(nestedPattern) {
if (isObject(nestedPattern)) {
return deepObjectLike(nestedPattern);
}
if (Array.isArray(nestedPattern)) {
return nestedPattern.map(deepMatcherFromObjectLiteral);
}
return nestedPattern;
}
if (errors.length > 0) {
return failMatcher(inspection, errors.join(', '));
}
return true;
});
}
/**
* Match exactly the given value
*
* This is the default, you only need this to escape from the deep lenient matching
* of `deepObjectLike`.
*/
function exactValue(expected) {
const anno = { $exactValue: expected };
return annotateMatcher(anno, (value, inspection) => {
return matchLiteral(value, expected, inspection);
});
}
exports.exactValue = exactValue;
/**
* A matcher for a list that contains all of the given elements in any order
*/
function arrayWith(...elements) {
if (elements.length === 0) {
return anything();
}
const anno = { $arrayContaining: elements.length === 1 ? elements[0] : elements };
return annotateMatcher(anno, (value, inspection) => {
if (!Array.isArray(value)) {
return failMatcher(inspection, `Expect an array but got '${typeof value}'`);
}
for (const element of elements) {
const failure = longestFailure(value, element);
if (failure) {
return failMatcher(inspection, `Array did not contain expected element, closest match at index ${failure[0]}: ${failure[1]}`);
}
}
return true;
/**
* Return 'null' if the matcher matches anywhere in the array, otherwise the longest error and its index
*/
function longestFailure(array, matcher) {
let fail = null;
for (let i = 0; i < array.length; i++) {
const innerInspection = { ...inspection, failureReason: '' };
if (match(array[i], matcher, innerInspection)) {
return null;
}
if (fail === null || innerInspection.failureReason.length > fail[1].length) {
fail = [i, innerInspection.failureReason];
}
}
return fail;
}
});
}
exports.arrayWith = arrayWith;
/**
* Whether a value is an object
*/
function isObject(x) {
// Because `typeof null === 'object'`.
return x && typeof x === 'object';
}
/**
* Helper function to make matcher failure reporting a little easier
*
* Our protocol is weird (change a string on a passed-in object and return 'false'),
* but I don't want to change that right now.
*/
function failMatcher(inspection, error) {
inspection.failureReason = error;
return false;
}
exports.failMatcher = failMatcher;
/**
* Match a given literal value against a matcher
*
* If the matcher is a callable, use that to evaluate the value. Otherwise, the values
* must be literally the same.
*/
function match(value, matcher, inspection) {
if (isCallable(matcher)) {
// Custom matcher (this mostly looks very weird because our `InspectionFailure` signature is weird)
const innerInspection = { ...inspection, failureReason: '' };
const result = matcher(value, innerInspection);
if (typeof result !== 'boolean') {
return failMatcher(inspection, `Predicate returned non-boolean return value: ${result}`);
}
if (!result && !innerInspection.failureReason) {
// Custom matcher neglected to return an error
return failMatcher(inspection, 'Predicate returned false');
}
// Propagate inner error in case of failure
if (!result) {
inspection.failureReason = innerInspection.failureReason;
}
return result;
}
return matchLiteral(value, matcher, inspection);
}
exports.match = match;
/**
* Match a literal value at the top level.
*
* When recursing into arrays or objects, the nested values can be either matchers
* or literals.
*/
function matchLiteral(value, pattern, inspection) {
if (pattern == null) {
return true;
}
const errors = new Array();
if (Array.isArray(value) !== Array.isArray(pattern)) {
return failMatcher(inspection, 'Array type mismatch');
}
if (Array.isArray(value)) {
if (pattern.length !== value.length) {
return failMatcher(inspection, 'Array length mismatch');
}
// Recurse comparison for individual objects
for (let i = 0; i < pattern.length; i++) {
if (!match(value[i], pattern[i], { ...inspection })) {
errors.push(`Array element ${i} mismatch`);
}
}
if (errors.length > 0) {
return failMatcher(inspection, errors.join(', '));
}
return true;
}
if ((typeof value === 'object') !== (typeof pattern === 'object')) {
return failMatcher(inspection, 'Object type mismatch');
}
if (typeof pattern === 'object') {
// Check that all fields in the pattern have the right value
const innerInspection = { ...inspection, failureReason: '' };
const matcher = objectLike(pattern)(value, innerInspection);
if (!matcher) {
inspection.failureReason = innerInspection.failureReason;
return false;
}
// Check no fields uncovered
const realFields = new Set(Object.keys(value));
for (const key of Object.keys(pattern)) {
realFields.delete(key);
}
if (realFields.size > 0) {
return failMatcher(inspection, `Unexpected keys present in object: ${Array.from(realFields).join(', ')}`);
}
return true;
}
if (value !== pattern) {
return failMatcher(inspection, 'Different values');
}
return true;
}
/**
* Whether a value is a callable
*/
function isCallable(x) {
return x && {}.toString.call(x) === '[object Function]';
}
/**
* Do a glob-like pattern match (which only supports *s). Supports multiline strings.
*/
function stringLike(pattern) {
// Replace * with .* in the string, escape the rest and brace with ^...$
const regex = new RegExp(`^${pattern.split('*').map(escapeRegex).join('.*')}$`, 'm');
return annotateMatcher({ $stringContaining: pattern }, (value, failure) => {
if (typeof value !== 'string') {
failure.failureReason = `Expected a string, but got '${typeof value}'`;
return false;
}
if (!regex.test(value)) {
failure.failureReason = 'String did not match pattern';
return false;
}
return true;
});
}
exports.stringLike = stringLike;
/**
* Matches any value
*/
function anything() {
return annotateMatcher({ $anything: true }, () => true);
}
exports.anything = anything;
/**
* Negate an inner matcher
*/
function notMatching(matcher) {
return annotateMatcher({ $notMatching: matcher }, (value, failure) => {
const result = matcherFrom(matcher)(value, failure);
if (result) {
failure.failureReason = 'Should not have matched, but did';
return false;
}
return true;
});
}
exports.notMatching = notMatching;
/**
* Captures a value onto an object if it matches a given inner matcher
*
* @example
*
* const someValue = Capture.aString();
* expect(stack).toHaveResource({
* // ...
* Value: someValue.capture(stringMatching('*a*')),
* });
* console.log(someValue.capturedValue);
*/
class Capture {
constructor(typeValidator) {
this.typeValidator = typeValidator;
this._didCapture = false;
this._wasInvoked = false;
}
/**
* A Capture object that captures any type
*/
static anyType() {
return new Capture();
}
/**
* A Capture object that captures a string type
*/
static aString() {
return new Capture((x) => {
if (typeof x !== 'string') {
throw new Error(`Expected to capture a string, got '${x}'`);
}
return true;
});
}
/**
* A Capture object that captures a custom type
*/
// eslint-disable-next-line @typescript-eslint/no-shadow
static a(validator) {
return new Capture(validator);
}
/**
* Capture the value if the inner matcher successfully matches it
*
* If no matcher is given, `anything()` is assumed.
*
* And exception will be thrown if the inner matcher returns `true` and
* the value turns out to be of a different type than the `Capture` object
* is expecting.
*/
capture(matcher) {
if (matcher === undefined) {
matcher = anything();
}
return annotateMatcher({ $capture: matcher }, (value, failure) => {
this._wasInvoked = true;
const result = matcherFrom(matcher)(value, failure);
if (result) {
if (this.typeValidator && !this.typeValidator(value)) {
throw new Error(`Value not of the expected type: ${value}`);
}
this._didCapture = true;
this._value = value;
}
return result;
});
}
/**
* Whether a value was successfully captured
*/
get didCapture() {
return this._didCapture;
}
/**
* Return the value that was captured
*
* Throws an exception if now value was captured
*/
get capturedValue() {
// When this module is ported to jsii, the type parameter will obviously
// have to be dropped and this will have to turn into an `any`.
if (!this.didCapture) {
throw new Error(`Did not capture a value: ${this._wasInvoked ? 'inner matcher failed' : 'never invoked'}`);
}
return this._value;
}
}
exports.Capture = Capture;
/**
* Match on the innards of a JSON string, instead of the complete string
*/
function encodedJson(matcher) {
return annotateMatcher({ $encodedJson: matcher }, (value, failure) => {
if (typeof value !== 'string') {
failure.failureReason = `Expected a string, but got '${typeof value}'`;
return false;
}
let decoded;
try {
decoded = JSON.parse(value);
}
catch (e) {
failure.failureReason = `String is not JSON: ${e}`;
return false;
}
return matcherFrom(matcher)(decoded, failure);
});
}
exports.encodedJson = encodedJson;
function escapeRegex(s) {
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
/**
* Make a matcher out of the given argument if it's not a matcher already
*
* If it's not a matcher, it will be treated as a literal.
*/
function matcherFrom(matcher) {
return isCallable(matcher) ? matcher : exactValue(matcher);
}
exports.matcherFrom = matcherFrom;
/**
* Annotate a matcher with toJSON
*
* We will JSON.stringify() values if we have a match failure, but for matchers this
* would show (in traditional JS fashion) something like '[function Function]', or more
* accurately nothing at all since functions cannot be JSONified.
*
* We override to JSON() in order to produce a readable version of the matcher.
*/
function annotateMatcher(how, matcher) {
matcher.toJSON = () => how;
return matcher;
}
exports.annotateMatcher = annotateMatcher;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGF2ZS1yZXNvdXJjZS1tYXRjaGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImhhdmUtcmVzb3VyY2UtbWF0Y2hlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbURBQTZFO0FBRTdFOzs7OztHQUtHO0FBQ0gsU0FBZ0IsVUFBVSxDQUFtQixPQUFVO0lBQ3JELE9BQU8saUJBQWlCLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFGRCxnQ0FFQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQixjQUFjLENBQW1CLE9BQVU7SUFDekQsT0FBTyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDMUMsQ0FBQztBQUZELHdDQUVDO0FBRUQsU0FBUyxpQkFBaUIsQ0FBbUIsT0FBVSxFQUFFLElBQWE7SUFDcEUsTUFBTSxJQUFJLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDO0lBRXJFLE9BQU8sZUFBZSxDQUFDLElBQUksRUFBRSxDQUFDLEtBQVUsRUFBRSxVQUE2QixFQUFXLEVBQUU7UUFDbEYsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDdkMsT0FBTyxXQUFXLENBQUMsVUFBVSxFQUFFLDZCQUE2QixPQUFPLEtBQUssR0FBRyxDQUFDLENBQUM7U0FDOUU7UUFFRCxNQUFNLE1BQU0sR0FBRyxJQUFJLEtBQUssRUFBVSxDQUFDO1FBRW5DLEtBQUssTUFBTSxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ2hFLElBQUksWUFBWSxLQUFLLHNCQUFNLEVBQUU7Z0JBQzNCLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxLQUFLLFNBQVMsRUFBRTtvQkFBRSxNQUFNLENB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Q2Q7UUFFRCxPQUFPLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDaEQsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBakJELGtDQWlCQztBQUVELFNBQVMsV0FBVyxDQUFDLENBQVM7SUFDNUIsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLHFCQUFxQixFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsb0NBQW9DO0FBQ3ZGLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsV0FBVyxDQUFDLE9BQVk7SUFDdEMsT0FBTyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBQzdELENBQUM7QUFGRCxrQ0FFQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBZ0IsZUFBZSxDQUFtQixHQUFNLEVBQUUsT0FBd0I7SUFDL0UsT0FBZSxDQUFDLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUM7SUFDcEMsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQztBQUhELDBDQUdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQUJTRU5ULCBJbnNwZWN0aW9uRmFpbHVyZSwgUHJvcGVydHlNYXRjaGVyIH0gZnJvbSAnLi9oYXZlLXJlc291cmNlJztcblxuLyoqXG4gKiBBIG1hdGNoZXIgZm9yIGFuIG9iamVjdCB0aGF0IGNvbnRhaW5zIGF0IGxlYXN0IHRoZSBnaXZlbiBmaWVsZHMgd2l0aCB0aGUgZ2l2ZW4gbWF0Y2hlcnMgKG9yIGxpdGVyYWxzKVxuICpcbiAqIE9ubHkgZG9lcyBsZW5pZW50IG1hdGNoaW5nIG9uZSBsZXZlbCBkZWVwLCBhdCB0aGUgbmV4dCBsZXZlbCBhbGwgb2JqZWN0cyBtdXN0IGRlY2xhcmUgdGhlXG4gKiBleGFjdCBleHBlY3RlZCBrZXlzIGFnYWluLlxuICovXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0TGlrZTxBIGV4dGVuZHMgb2JqZWN0PihwYXR0ZXJuOiBBKTogUHJvcGVydHlNYXRjaGVyIHtcbiAgcmV0dXJuIF9vYmplY3RDb250YWluaW5nKHBhdHRlcm4sIGZhbHNlKTtcbn1cblxuLyoqXG4gKiBBIG1hdGNoZXIgZm9yIGFuIG9iamVjdCB0aGF0IGNvbnRhaW5zIGF0IGxlYXN0IHRoZSBnaXZlbiBmaWVsZHMgd2l0aCB0aGUgZ2l2ZW4gbWF0Y2hlcnMgKG9yIGxpdGVyYWxzKVxuICpcbiAqIFN3aXRjaGVzIHRvIFwiZGVlcFwiIGxlbmllbnQgbWF0Y2hpbmcuIE5lc3RlZCBvYmplY3RzIGFsc28gb25seSBuZWVkIHRvIGNvbnRhaW4gZGVjbGFyZWQga2V5cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBPYmplY3RMaWtlPEEgZXh0ZW5kcyBvYmplY3Q+KHBhdHRlcm46IEEpOiBQcm9wZXJ0eU1hdGNoZXIge1xuICByZXR1cm4gX29iamVjdENvbnRhaW5pbmcocGF0dGVybiwgdHJ1ZSk7XG59XG5cbmZ1bmN0aW9uIF9vYmplY3RDb250YWluaW5nPEEgZXh0ZW5kcyBvYmplY3Q+KHBhdHRlcm46IEEsIGRlZXA6IGJvb2xlYW4pOiBQcm9wZXJ0eU1hdGNoZXIge1xuICBjb25zdCBhbm5vID0geyBbZGVlcCA/ICckZGVlcE9iamVjdExpa2UnIDogJyRvYmplY3RMaWtlJ106IHBhdHRlcm4gfTtcblxuICByZXR1cm4gYW5ub3RhdGVNYXRjaGVyKGFubm8sICh2YWx1ZTogYW55LCBpbnNwZWN0aW9uOiBJbnNwZWN0aW9uRmFpbHVyZSk6IGJvb2xlYW4gPT4ge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnIHx8ICF2YWx1ZSkge1xuICAgICAgcmV0dXJuIGZhaWxNYXRjaGVyKGluc3BlY3Rpb24sIGBFeHBlY3QgYW4gb2JqZWN0IGJ1dCBnb3QgJyR7dHlwZW9mIHZhbHVlfSdgKTtcbiAgICB9XG5cbiAgICBjb25zdCBlcnJvcnMgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuXG4gICAgZm9yIChjb25zdCBbcGF0dGVybktleSwgcGF0dGVyblZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhwYXR0ZXJuKSkge1xuICAgICAgaWYgKHBhdHRlcm5WYWx1ZSA9PT0gQUJTRU5UKSB7XG4gICAgICAgIGlmICh2YWx1ZVtwYXR0ZXJuS2V5XSAhPT0gdW5kZWZpbmVkKSB7IGVycm9ycy5wdXNoKGBGaWVsZCAke3BhdHRlcm5LZXl9IHByZXNlbnQsIGJ1dCBzaG91bGRuJ3QgYmVgKTsgfVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCEocGF0dGVybktleSBpbiB2YWx1ZSkpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goYEZpZWxkICR7cGF0dGVybktleX0gbWlzc2luZ2ApO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gSWYgd2UgYXJlIGRvaW5nIERFRVAgb2JqZWN0TGlrZSwgdHJhbnNsYXRlIG9iamVjdCBsaXRlcmFscyBpbiB0aGUgcGF0dGVybiBpbnRvXG4gICAgICAvLyBtb3JlIGBkZWVwT2JqZWN0TGlrZWAgbWF0Y2hlcnMsIGV2ZW4gaWYgdGhleSBvY2N1ciBpbiBsaXN0cy5cbiAgICAgIGNvbnN0IG1hdGNoVmFsdWUgPSBkZWVwID8gZGVlcE1hdGNoZXJGcm9tT2JqZWN0TGl0ZXJhbChwYXR0ZXJuVmFsdWUpIDogcGF0dGVyblZhbHVlO1xuXG4gICAgICBjb25zdCBpbm5lckluc3BlY3Rpb24gPSB7IC4uLmluc3BlY3Rpb24sIGZhaWx1cmVSZWFzb246ICcnIH07XG4gICAgICBjb25zdCB2YWx1ZU1hdGNoZXMgPSBtYXRjaCh2YWx1ZVtwYXR0ZXJuS2V5XSwgbWF0Y2hWYWx1ZSwgaW5uZXJJbnNwZWN0aW9uKTtcbiAgICAgIGlmICghdmFsdWVNYXRjaGVzKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKGBGaWVsZCAke3BhdHRlcm5LZXl9IG1pc21hdGNoOiAke2lubmVySW5zcGVjdGlvbi5mYWlsdXJlUmVhc29ufWApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRyYW5zZm9ybSBuZXN0ZWQgb2JqZWN0IGxpdGVyYWxzIGludG8gbW9yZSBkZWVwIG9iamVjdCBtYXRjaGVycywgaWYgYXBwbGljYWJsZVxuICAgICAqXG4gICAgICogT2JqZWN0IGxpdGVyYWxzIGluIGxpc3RzIGFyZSBhbHNvIHRyYW5zZm9ybWVkLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRlZXBNYXRjaGVyRnJvbU9iamVjdExpdGVyYWwobmVzdGVkUGF0dGVybjogYW55KTogYW55IHtcbiAgICAgIGlmIChpc09iamVjdChuZXN0ZWRQYXR0ZXJuKSkge1xuICAgICAgICByZXR1cm4gZGVlcE9iamVjdExpa2UobmVzdGVkUGF0dGVybik7XG4gICAgICB9XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShuZXN0ZWRQYXR0ZXJuKSkge1xuICAgICAgICByZXR1cm4gbmVzdGVkUGF0dGVybi5tYXAoZGVlcE1hdGNoZXJGcm9tT2JqZWN0TGl0ZXJhbCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmVzdGVkUGF0dGVybjtcbiAgICB9XG5cbiAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBmYWlsTWF0Y2hlcihpbnNwZWN0aW9uLCBlcnJvcnMuam9pbignLCAnKSk7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuLyoqXG4gKiBNYXRjaCBleGFjdGx5IHRoZSBnaXZlbiB2YWx1ZVxuICpcbiAqIFRoaXMgaXMgdGhlIGRlZmF1bHQsIHlvdSBvbmx5IG5lZWQgdGhpcyB0byBlc2NhcGUgZnJvbSB0aGUgZGVlcCBsZW5pZW50IG1hdGNoaW5nXG4gKiBvZiBgZGVlcE9iamVjdExpa2VgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXhhY3RWYWx1ZShleHBlY3RlZDogYW55KTogUHJvcGVydHlNYXRjaGVyIHtcbiAgY29uc3QgYW5ubyA9IHsgJGV4YWN0VmFsdWU6IGV4cGVjdGVkIH07XG4gIHJldHVybiBhbm5vdGF0ZU1hdGNoZXIoYW5ubywgKHZhbHVlOiBhbnksIGluc3BlY3Rpb246IEluc3BlY3Rpb25GYWlsdXJlKTogYm9vbGVhbiA9PiB7XG4gICAgcmV0dXJuIG1hdGNoTGl0ZXJhbCh2YWx1ZSwgZXhwZWN0ZWQsIGluc3BlY3Rpb24pO1xuICB9KTtcbn1cblxuLyoqXG4gKiBBIG1hdGNoZXIgZm9yIGEgbGlzdCB0aGF0IGNvbnRhaW5zIGFsbCBvZiB0aGUgZ2l2ZW4gZWxlbWVudHMgaW4gYW55IG9yZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcnJheVdpdGgoLi4uZWxlbWVudHM6IGFueVtdKTogUHJvcGVydHlNYXRjaGVyIHtcbiAgaWYgKGVsZW1lbnRzLmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gYW55dGhpbmcoKTsgfVxuXG4gIGNvbnN0IGFubm8gPSB7ICRhcnJheUNvbnRhaW5pbmc6IGVsZW1lbnRzLmxlbmd0aCA9PT0gMSA/IGVsZW1lbnRzWzBdIDogZWxlbWVudHMgfTtcbiAgcmV0dXJuIGFubm90YXRlTWF0Y2hlcihhbm5vLCAodmFsdWU6IGFueSwgaW5zcGVjdGlvbjogSW5zcGVjdGlvbkZhaWx1cmUpOiBib29sZWFuID0+IHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZmFpbE1hdGNoZXIoaW5zcGVjdGlvbiwgYEV4cGVjdCBhbiBhcnJheSBidXQgZ290ICcke3R5cGVvZiB2YWx1ZX0nYCk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVsZW1lbnRzKSB7XG4gICAgICBjb25zdCBmYWlsdXJlID0gbG9uZ2VzdEZhaWx1cmUodmFsdWUsIGVsZW1lbnQpO1xuICAgICAgaWYgKGZhaWx1cmUpIHtcbiAgICAgICAgcmV0dXJuIGZhaWxNYXRjaGVyKGluc3BlY3Rpb24sIGBBcnJheSBkaWQgbm90IGNvbnRhaW4gZXhwZWN0ZWQgZWxlbWVudCwgY2xvc2VzdCBtYXRjaCBhdCBpbmRleCAke2ZhaWx1cmVbMF19OiAke2ZhaWx1cmVbMV19YCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gJ251bGwnIGlmIHRoZSBtYXRjaGVyIG1hdGNoZXMgYW55d2hlcmUgaW4gdGhlIGFycmF5LCBvdGhlcndpc2UgdGhlIGxvbmdlc3QgZXJyb3IgYW5kIGl0cyBpbmRleFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGxvbmdlc3RGYWlsdXJlKGFycmF5OiBhbnlbXSwgbWF0Y2hlcjogYW55KTogW251bWJlciwgc3RyaW5nXSB8IG51bGwge1xuICAgICAgbGV0IGZhaWw6IFtudW1iZXIsIHN0cmluZ10gfCBudWxsID0gbnVsbDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgaW5uZXJJbnNwZWN0aW9uID0geyAuLi5pbnNwZWN0aW9uLCBmYWlsdXJlUmVhc29uOiAnJyB9O1xuICAgICAgICBpZiAobWF0Y2goYXJyYXlbaV0sIG1hdGNoZXIsIGlubmVySW5zcGVjdGlvbikpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmYWlsID09PSBudWxsIHx8IGlubmVySW5zcGVjdGlvbi5mYWlsdXJlUmVhc29uLmxlbmd0aCA+IGZhaWxbMV0ubGVuZ3RoKSB7XG4gICAgICAgICAgZmFpbCA9IFtpLCBpbm5lckluc3BlY3Rpb24uZmFpbHVyZVJlYXNvbl07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWlsO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogV2hldGhlciBhIHZhbHVlIGlzIGFuIG9iamVjdFxuICovXG5mdW5jdGlvbiBpc09iamVjdCh4OiBhbnkpOiB4IGlzIG9iamVjdCB7XG4gIC8vIEJlY2F1c2UgYHR5cGVvZiBudWxsID09PSAnb2JqZWN0J2AuXG4gIHJldHVybiB4ICYmIHR5cGVvZiB4ID09PSAnb2JqZWN0Jztcbn1cblxuLyoqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdG8gbWFrZSBtYXRjaGVyIGZhaWx1cmUgcmVwb3J0aW5nIGEgbGl0dGxlIGVhc2llclxuICpcbiAqIE91ciBwcm90b2NvbCBpcyB3ZWlyZCAoY2hhbmdlIGEgc3RyaW5nIG9uIGEgcGFzc2VkLWluIG9iamVjdCBhbmQgcmV0dXJuICdmYWxzZScpLFxuICogYnV0IEkgZG9uJ3Qgd2FudCB0byBjaGFuZ2UgdGhhdCByaWdodCBub3cuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmYWlsTWF0Y2hlcihpbnNwZWN0aW9uOiBJbnNwZWN0aW9uRmFpbHVyZSwgZXJyb3I6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBpbnNwZWN0aW9uLmZhaWx1cmVSZWFzb24gPSBlcnJvcjtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKipcbiAqIE1hdGNoIGEgZ2l2ZW4gbGl0ZXJhbCB2YWx1ZSBhZ2FpbnN0IGEgbWF0Y2hlclxuICpcbiAqIElmIHRoZSBtYXRjaGVyIGlzIGEgY2FsbGFibGUsIHVzZSB0aGF0IHRvIGV2YWx1YXRlIHRoZSB2YWx1ZS4gT3RoZXJ3aXNlLCB0aGUgdmFsdWVzXG4gKiBtdXN0IGJlIGxpdGVyYWxseSB0aGUgc2FtZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoKHZhbHVlOiBhbnksIG1hdGNoZXI6IGFueSwgaW5zcGVjdGlvbjogSW5zcGVjdGlvbkZhaWx1cmUpIHtcbiAgaWYgKGlzQ2FsbGFibGUobWF0Y2hlcikpIHtcbiAgICAvLyBDdXN0b20gbWF0Y2hlciAodGhpcyBtb3N0bHkgbG9va3MgdmVyeSB3ZWlyZCBiZWNhdXNlIG91ciBgSW5zcGVjdGlvbkZhaWx1cmVgIHNpZ25hdHVyZSBpcyB3ZWlyZClcbiAgICBjb25zdCBpbm5lckluc3BlY3Rpb246IEluc3BlY3Rpb25GYWlsdXJlID0geyAuLi5pbnNwZWN0aW9uLCBmYWlsdXJlUmVhc29uOiAnJyB9O1xuICAgIGNvbnN0IHJlc3VsdCA9IG1hdGNoZXIodmFsdWUsIGlubmVySW5zcGVjdGlvbik7XG4gICAgaWYgKHR5cGVvZiByZXN1bHQgIT09ICdib29sZWFuJykge1xuICAgICAgcmV0dXJuIGZhaWxNYXRjaGVyKGluc3BlY3Rpb24sIGBQcmVkaWNhdGUgcmV0dXJuZWQgbm9uLWJvb2xlYW4gcmV0dXJuIHZhbHVlOiAke3Jlc3VsdH1gKTtcbiAgICB9XG4gICAgaWYgKCFyZXN1bHQgJiYgIWlubmVySW5zcGVjdGlvbi5mYWlsdXJlUmVhc29uKSB7XG4gICAgICAvLyBDdXN0b20gbWF0Y2hlciBuZWdsZWN0ZWQgdG8gcmV0dXJuIGFuIGVycm9yXG4gICAgICByZXR1cm4gZmFpbE1hdGNoZXIoaW5zcGVjdGlvbiwgJ1ByZWRpY2F0ZSByZXR1cm5lZCBmYWxzZScpO1xuICAgIH1cbiAgICAvLyBQcm9wYWdhdGUgaW5uZXIgZXJyb3IgaW4gY2FzZSBvZiBmYWlsdXJlXG4gICAgaWYgKCFyZXN1bHQpIHsgaW5zcGVjdGlvbi5mYWlsdXJlUmVhc29uID0gaW5uZXJJbnNwZWN0aW9uLmZhaWx1cmVSZWFzb247IH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hdGNoTGl0ZXJhbCh2YWx1ZSwgbWF0Y2hlciwgaW5zcGVjdGlvbik7XG59XG5cbi8qKlxuICogTWF0Y2ggYSBsaXRlcmFsIHZhbHVlIGF0IHRoZSB0b3AgbGV2ZWwuXG4gKlxuICogV2hlbiByZWN1cnNpbmcgaW50byBhcnJheXMgb3Igb2JqZWN0cywgdGhlIG5lc3RlZCB2YWx1ZXMgY2FuIGJlIGVpdGhlciBtYXRjaGVyc1xuICogb3IgbGl0ZXJhbHMuXG4gKi9cbmZ1bmN0aW9uIG1hdGNoTGl0ZXJhbCh2YWx1ZTogYW55LCBwYXR0ZXJuOiBhbnksIGluc3BlY3Rpb246IEluc3BlY3Rpb25GYWlsdXJlKSB7XG4gIGlmIChwYXR0ZXJuID09IG51bGwpIHsgcmV0dXJuIHRydWU7IH1cblxuICBjb25zdCBlcnJvcnMgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuXG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSAhPT0gQXJyYXkuaXNBcnJheShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBmYWlsTWF0Y2hlcihpbnNwZWN0aW9uLCAnQXJyYXkgdHlwZSBtaXNtYXRjaCcpO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIGlmIChwYXR0ZXJuLmxlbmd0aCAhPT0gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFpbE1hdGNoZXIoaW5zcGVjdGlvbiwgJ0FycmF5IGxlbmd0aCBtaXNtYXRjaCcpO1xuICAgIH1cblxuICAgIC8vIFJlY3Vyc2UgY29tcGFyaXNvbiBmb3IgaW5kaXZpZHVhbCBvYmplY3RzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXR0ZXJuLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoIW1hdGNoKHZhbHVlW2ldLCBwYXR0ZXJuW2ldLCB7IC4uLmluc3BlY3Rpb24gfSkpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goYEFycmF5IGVsZW1lbnQgJHtpfSBtaXNtYXRjaGApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIGZhaWxNYXRjaGVyKGluc3BlY3Rpb24sIGVycm9ycy5qb2luKCcsICcpKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKCh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSAhPT0gKHR5cGVvZiBwYXR0ZXJuID09PSAnb2JqZWN0JykpIHtcbiAgICByZXR1cm4gZmFpbE1hdGNoZXIoaW5zcGVjdGlvbiwgJ09iamVjdCB0eXBlIG1pc21hdGNoJyk7XG4gIH1cbiAgaWYgKHR5cGVvZiBwYXR0ZXJuID09PSAnb2JqZWN0Jykge1xuICAgIC8vIENoZWNrIHRoYXQgYWxsIGZpZWxkcyBpbiB0aGUgcGF0dGVybiBoYXZlIHRoZSByaWdodCB2YWx1ZVxuICAgIGNvbnN0IGlubmVySW5zcGVjdGlvbiA9IHsgLi4uaW5zcGVjdGlvbiwgZmFpbHVyZVJlYXNvbjogJycgfTtcbiAgICBjb25zdCBtYXRjaGVyID0gb2JqZWN0TGlrZShwYXR0ZXJuKSh2YWx1ZSwgaW5uZXJJbnNwZWN0aW9uKTtcbiAgICBpZiAoIW1hdGNoZXIpIHtcbiAgICAgIGluc3BlY3Rpb24uZmFpbHVyZVJlYXNvbiA9IGlubmVySW5zcGVjdGlvbi5mYWlsdXJlUmVhc29uO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8vIENoZWNrIG5vIGZpZWxkcyB1bmNvdmVyZWRcbiAgICBjb25zdCByZWFsRmllbGRzID0gbmV3IFNldChPYmplY3Qua2V5cyh2YWx1ZSkpO1xuICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7IHJlYWxGaWVsZHMuZGVsZXRlKGtleSk7IH1cbiAgICBpZiAocmVhbEZpZWxkcy5zaXplID4gMCkge1xuICAgICAgcmV0dXJuIGZhaWxNYXRjaGVyKGluc3BlY3Rpb24sIGBVbmV4cGVjdGVkIGtleXMgcHJlc2VudCBpbiBvYmplY3Q6ICR7QXJyYXkuZnJvbShyZWFsRmllbGRzKS5qb2luKCcsICcpfWApO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmICh2YWx1ZSAhPT0gcGF0dGVybikge1xuICAgIHJldHVybiBmYWlsTWF0Y2hlcihpbnNwZWN0aW9uLCAnRGlmZmVyZW50IHZhbHVlcycpO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogV2hldGhlciBhIHZhbHVlIGlzIGEgY2FsbGFibGVcbiAqL1xuZnVuY3Rpb24gaXNDYWxsYWJsZSh4OiBhbnkpOiB4IGlzICgoLi4uYXJnczogYW55W10pID0+IGFueSkge1xuICByZXR1cm4geCAmJiB7fS50b1N0cmluZy5jYWxsKHgpID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG4vKipcbiAqIERvIGEgZ2xvYi1saWtlIHBhdHRlcm4gbWF0Y2ggKHdoaWNoIG9ubHkgc3VwcG9ydHMgKnMpLiBTdXBwb3J0cyBtdWx0aWxpbmUgc3RyaW5ncy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0cmluZ0xpa2UocGF0dGVybjogc3RyaW5nKTogUHJvcGVydHlNYXRjaGVyIHtcbiAgLy8gUmVwbGFjZSAqIHdpdGggLiogaW4gdGhlIHN0cmluZywgZXNjYXBlIHRoZSByZXN0IGFuZCBicmFjZSB3aXRoIF4uLi4kXG4gIGNvbnN0IHJlZ2V4ID0gbmV3IFJlZ0V4cChgXiR7cGF0dGVybi5zcGxpdCgnKicpLm1hcChlc2NhcGVSZWdleCkuam9pbignLionKX0kYCwgJ20nKTtcblxuICByZXR1cm4gYW5ub3RhdGVNYXRjaGVyKHsgJHN0cmluZ0NvbnRhaW5pbmc6IHBhdHRlcm4gfSwgKHZhbHVlOiBhbnksIGZhaWx1cmU6IEluc3BlY3Rpb25GYWlsdXJlKSA9PiB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIGZhaWx1cmUuZmFpbHVyZVJlYXNvbiA9IGBFeHBlY3RlZCBhIHN0cmluZywgYnV0IGdvdCAnJHt0eXBlb2YgdmFsdWV9J2A7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKCFyZWdleC50ZXN0KHZhbHVlKSkge1xuICAgICAgZmFpbHVyZS5mYWlsdXJlUmVhc29uID0gJ1N0cmluZyBkaWQgbm90IG1hdGNoIHBhdHRlcm4nO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuLyoqXG4gKiBNYXRjaGVzIGFueSB2YWx1ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gYW55dGhpbmcoKTogUHJvcGVydHlNYXRjaGVyIHtcbiAgcmV0dXJuIGFubm90YXRlTWF0Y2hlcih7ICRhbnl0aGluZzogdHJ1ZSB9LCAoKSA9PiB0cnVlKTtcbn1cblxuLyoqXG4gKiBOZWdhdGUgYW4gaW5uZXIgbWF0Y2hlclxuICovXG5leHBvcnQgZnVuY3Rpb24gbm90TWF0Y2hpbmcobWF0Y2hlcjogYW55KTogUHJvcGVydHlNYXRjaGVyIHtcbiAgcmV0dXJuIGFubm90YXRlTWF0Y2hlcih7ICRub3RNYXRjaGluZzogbWF0Y2hlciB9LCAodmFsdWU6IGFueSwgZmFpbHVyZTogSW5zcGVjdGlvbkZhaWx1cmUpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSBtYXRjaGVyRnJvbShtYXRjaGVyKSh2YWx1ZSwgZmFpbHVyZSk7XG4gICAgaWYgKHJlc3VsdCkge1xuICAgICAgZmFpbHVyZS5mYWlsdXJlUmVhc29uID0gJ1Nob3VsZCBub3QgaGF2ZSBtYXRjaGVkLCBidXQgZGlkJztcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xufVxuXG5leHBvcnQgdHlwZSBUeXBlVmFsaWRhdG9yPFQ+ID0gKHg6IGFueSkgPT4geCBpcyBUO1xuXG4vKipcbiAqIENhcHR1cmVzIGEgdmFsdWUgb250byBhbiBvYmplY3QgaWYgaXQgbWF0Y2hlcyBhIGdpdmVuIGlubmVyIG1hdGNoZXJcbiAqXG4gKiBAZXhhbXBsZVxuICpcbiAqIGNvbnN0IHNvbWVWYWx1ZSA9IENhcHR1cmUuYVN0cmluZygpO1xuICogZXhwZWN0KHN0YWNrKS50b0hhdmVSZXNvdXJjZSh7XG4gKiAgICAvLyAuLi5cbiAqICAgIFZhbHVlOiBzb21lVmFsdWUuY2FwdHVyZShzdHJpbmdNYXRjaGluZygnKmEqJykpLFxuICogfSk7XG4gKiBjb25zb2xlLmxvZyhzb21lVmFsdWUuY2FwdHVyZWRWYWx1ZSk7XG4gKi9cbmV4cG9ydCBjbGFzcyBDYXB0dXJlPFQ9YW55PiB7XG4gIC8qKlxuICAgKiBBIENhcHR1cmUgb2JqZWN0IHRoYXQgY2FwdHVyZXMgYW55IHR5cGVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgYW55VHlwZSgpOiBDYXB0dXJlPGFueT4ge1xuICAgIHJldHVybiBuZXcgQ2FwdHVyZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgQ2FwdHVyZSBvYmplY3QgdGhhdCBjYXB0dXJlcyBhIHN0cmluZyB0eXBlXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGFTdHJpbmcoKTogQ2FwdHVyZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IENhcHR1cmUoKHg6IGFueSk6IHggaXMgc3RyaW5nID0+IHtcbiAgICAgIGlmICh0eXBlb2YgeCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCB0byBjYXB0dXJlIGEgc3RyaW5nLCBnb3QgJyR7eH0nYCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIENhcHR1cmUgb2JqZWN0IHRoYXQgY2FwdHVyZXMgYSBjdXN0b20gdHlwZVxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1zaGFkb3dcbiAgcHVibGljIHN0YXRpYyBhPFQ+KHZhbGlkYXRvcjogVHlwZVZhbGlkYXRvcjxUPik6IENhcHR1cmU8VD4ge1xuICAgIHJldHVybiBuZXcgQ2FwdHVyZSh2YWxpZGF0b3IpO1xuICB9XG5cbiAgcHJpdmF0ZSBfdmFsdWU/OiBUO1xuICBwcml2YXRlIF9kaWRDYXB0dXJlID0gZmFsc2U7XG4gIHByaXZhdGUgX3dhc0ludm9rZWQgPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSB0eXBlVmFsaWRhdG9yPzogVHlwZVZhbGlkYXRvcjxUPikge1xuICB9XG5cbiAgLyoqXG4gICAqIENhcHR1cmUgdGhlIHZhbHVlIGlmIHRoZSBpbm5lciBtYXRjaGVyIHN1Y2Nlc3NmdWxseSBtYXRjaGVzIGl0XG4gICAqXG4gICAqIElmIG5vIG1hdGNoZXIgaXMgZ2l2ZW4sIGBhbnl0aGluZygpYCBpcyBhc3N1bWVkLlxuICAgKlxuICAgKiBBbmQgZXhjZXB0aW9uIHdpbGwgYmUgdGhyb3duIGlmIHRoZSBpbm5lciBtYXRjaGVyIHJldHVybnMgYHRydWVgIGFuZFxuICAgKiB0aGUgdmFsdWUgdHVybnMgb3V0IHRvIGJlIG9mIGEgZGlmZmVyZW50IHR5cGUgdGhhbiB0aGUgYENhcHR1cmVgIG9iamVjdFxuICAgKiBpcyBleHBlY3RpbmcuXG4gICAqL1xuICBwdWJsaWMgY2FwdHVyZShtYXRjaGVyPzogYW55KTogUHJvcGVydHlNYXRjaGVyIHtcbiAgICBpZiAobWF0Y2hlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBtYXRjaGVyID0gYW55dGhpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYW5ub3RhdGVNYXRjaGVyKHsgJGNhcHR1cmU6IG1hdGNoZXIgfSwgKHZhbHVlOiBhbnksIGZhaWx1cmU6IEluc3BlY3Rpb25GYWlsdXJlKSA9PiB7XG4gICAgICB0aGlzLl93YXNJbnZva2VkID0gdHJ1ZTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IG1hdGNoZXJGcm9tKG1hdGNoZXIpKHZhbHVlLCBmYWlsdXJlKTtcbiAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgaWYgKHRoaXMudHlwZVZhbGlkYXRvciAmJiAhdGhpcy50eXBlVmFsaWRhdG9yKHZhbHVlKSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgVmFsdWUgbm90IG9mIHRoZSBleHBlY3RlZCB0eXBlOiAke3ZhbHVlfWApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2RpZENhcHR1cmUgPSB0cnVlO1xuICAgICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIGEgdmFsdWUgd2FzIHN1Y2Nlc3NmdWxseSBjYXB0dXJlZFxuICAgKi9cbiAgcHVibGljIGdldCBkaWRDYXB0dXJlKCkge1xuICAgIHJldHVybiB0aGlzLl9kaWRDYXB0dXJlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgdmFsdWUgdGhhdCB3YXMgY2FwdHVyZWRcbiAgICpcbiAgICogVGhyb3dzIGFuIGV4Y2VwdGlvbiBpZiBub3cgdmFsdWUgd2FzIGNhcHR1cmVkXG4gICAqL1xuICBwdWJsaWMgZ2V0IGNhcHR1cmVkVmFsdWUoKTogVCB7XG4gICAgLy8gV2hlbiB0aGlzIG1vZHVsZSBpcyBwb3J0ZWQgdG8ganNpaSwgdGhlIHR5cGUgcGFyYW1ldGVyIHdpbGwgb2J2aW91c2x5XG4gICAgLy8gaGF2ZSB0byBiZSBkcm9wcGVkIGFuZCB0aGlzIHdpbGwgaGF2ZSB0byB0dXJuIGludG8gYW4gYGFueWAuXG4gICAgaWYgKCF0aGlzLmRpZENhcHR1cmUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRGlkIG5vdCBjYXB0dXJlIGEgdmFsdWU6ICR7dGhpcy5fd2FzSW52b2tlZCA/ICdpbm5lciBtYXRjaGVyIGZhaWxlZCcgOiAnbmV2ZXIgaW52b2tlZCd9YCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl92YWx1ZSE7XG4gIH1cbn1cblxuLyoqXG4gKiBNYXRjaCBvbiB0aGUgaW5uYXJkcyBvZiBhIEpTT04gc3RyaW5nLCBpbnN0ZWFkIG9mIHRoZSBjb21wbGV0ZSBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZWRKc29uKG1hdGNoZXI6IGFueSk6IFByb3BlcnR5TWF0Y2hlciB7XG4gIHJldHVybiBhbm5vdGF0ZU1hdGNoZXIoeyAkZW5jb2RlZEpzb246IG1hdGNoZXIgfSwgKHZhbHVlOiBhbnksIGZhaWx1cmU6IEluc3BlY3Rpb25GYWlsdXJlKSA9PiB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIGZhaWx1cmUuZmFpbHVyZVJlYXNvbiA9IGBFeHBlY3RlZCBhIHN0cmluZywgYnV0IGdvdCAnJHt0eXBlb2YgdmFsdWV9J2A7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbGV0IGRlY29kZWQ7XG4gICAgdHJ5IHtcbiAgICAgIGRlY29kZWQgPSBKU09OLnBhcnNlKHZhbHVlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBmYWlsdXJlLmZhaWx1cmVSZWFzb24gPSBgU3RyaW5nIGlzIG5vdCBKU09OOiAke2V9YDtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWF0Y2hlckZyb20obWF0Y2hlcikoZGVjb2RlZCwgZmFpbHVyZSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBlc2NhcGVSZWdleChzOiBzdHJpbmcpIHtcbiAgcmV0dXJuIHMucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csICdcXFxcJCYnKTsgLy8gJCYgbWVhbnMgdGhlIHdob2xlIG1hdGNoZWQgc3RyaW5nXG59XG5cbi8qKlxuICogTWFrZSBhIG1hdGNoZXIgb3V0IG9mIHRoZSBnaXZlbiBhcmd1bWVudCBpZiBpdCdzIG5vdCBhIG1hdGNoZXIgYWxyZWFkeVxuICpcbiAqIElmIGl0J3Mgbm90IGEgbWF0Y2hlciwgaXQgd2lsbCBiZSB0cmVhdGVkIGFzIGEgbGl0ZXJhbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoZXJGcm9tKG1hdGNoZXI6IGFueSk6IFByb3BlcnR5TWF0Y2hlciB7XG4gIHJldHVybiBpc0NhbGxhYmxlKG1hdGNoZXIpID8gbWF0Y2hlciA6IGV4YWN0VmFsdWUobWF0Y2hlcik7XG59XG5cbi8qKlxuICogQW5ub3RhdGUgYSBtYXRjaGVyIHdpdGggdG9KU09OXG4gKlxuICogV2Ugd2lsbCBKU09OLnN0cmluZ2lmeSgpIHZhbHVlcyBpZiB3ZSBoYXZlIGEgbWF0Y2ggZmFpbHVyZSwgYnV0IGZvciBtYXRjaGVycyB0aGlzXG4gKiB3b3VsZCBzaG93IChpbiB0cmFkaXRpb25hbCBKUyBmYXNoaW9uKSBzb21ldGhpbmcgbGlrZSAnW2Z1bmN0aW9uIEZ1bmN0aW9uXScsIG9yIG1vcmVcbiAqIGFjY3VyYXRlbHkgbm90aGluZyBhdCBhbGwgc2luY2UgZnVuY3Rpb25zIGNhbm5vdCBiZSBKU09OaWZpZWQuXG4gKlxuICogV2Ugb3ZlcnJpZGUgdG8gSlNPTigpIGluIG9yZGVyIHRvIHByb2R1Y2UgYSByZWFkYWJsZSB2ZXJzaW9uIG9mIHRoZSBtYXRjaGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYW5ub3RhdGVNYXRjaGVyPEEgZXh0ZW5kcyBvYmplY3Q+KGhvdzogQSwgbWF0Y2hlcjogUHJvcGVydHlNYXRjaGVyKTogUHJvcGVydHlNYXRjaGVyIHtcbiAgKG1hdGNoZXIgYXMgYW55KS50b0pTT04gPSAoKSA9PiBob3c7XG4gIHJldHVybiBtYXRjaGVyO1xufVxuIl19