UNPKG

@ngneat/spectator

Version:

A powerful tool to simplify your Angular tests

457 lines 70.3 kB
/** Credit: https://github.com/unindented/custom-jquery-matchers/tree/master/packages/custom-jquery-matchers */
// This should be imported before `jquery` since this library unpatches the `setTimeout`,
// so jQuery won't setup a timer, that might be captured by zone.js.
import { restoreSetTimeout } from '@ngneat/spectator/internals';
import $ from 'jquery';
restoreSetTimeout();
import { hex2rgb, isHex, trim } from './internals/rgb-to-hex';
import { isHTMLOptionElementArray, isObject } from './types';
import { isRunningInJsDom, coerceArray } from './utils';
const hasProperty = (actual, expected) => {
    return expected === undefined ? actual !== undefined : actual === expected;
};
const containsProperty = (actual, expected) => {
    return expected === undefined ? true : actual.includes(expected);
};
const checkProperty = (el, prop, predicate) => {
    let pass = false;
    let failing = '';
    for (const key of Object.keys(prop)) {
        const actual = $(el).prop(key);
        const addendum = prop[key] !== undefined ? ` with value '${prop[key]}'` : '';
        pass = predicate(actual, prop[key]);
        failing = !pass ? `'${prop}'${addendum}, but had '${actual}'` : '';
    }
    const message = () => `Expected element${pass ? ' not' : ''} to have property ${failing}`;
    return { pass, message };
};
const hasCss = (el, css) => {
    let prop;
    let value;
    const $el = $(el);
    for (prop in css) {
        if (css.hasOwnProperty(prop)) {
            value = css[prop];
            if (isHex(value)) {
                value = hex2rgb(css[prop]);
            }
            if (value === 'auto' && $el.get(0).style[prop] === 'auto') {
                continue;
            }
            if (trim($el.get(0).style[prop]) !== trim(value) &&
                trim(el.style[prop]) !== trim(value) &&
                trim(el.style.getPropertyValue(prop)) !== trim(value)) {
                return false;
            }
        }
    }
    return true;
};
const hasSameText = (el, expected, options) => {
    if (expected && Array.isArray(expected)) {
        let actual;
        let pass = false;
        let failing;
        $(el).each((i, e) => {
            actual = options.exact && !options.trim ? $(e).text() : $.trim($(e).text());
            pass = options.exact ? actual === expected[i] : actual.includes(expected[i]);
            if (!pass) {
                failing = expected[i];
                return false;
            }
        });
        const message = () => `Expected element${pass ? ' not' : ''} to have${options.exact ? ' exact' : ''} text '${failing}', but had '${actual}'`;
        return { pass, message };
    }
    const actual = options.exact && !options.trim ? $(el).text() : $.trim($(el).text());
    if (expected && typeof expected !== 'string') {
        const pass = expected(actual);
        const message = () => `Expected element${pass ? ' not' : ''} to have${options.exact ? ' exact' : ''} text matching '${expected}',` + ` but had '${actual}'`;
        return { pass, message };
    }
    const pass = options.exact && !Array.isArray(expected) ? actual === expected : actual.indexOf(expected) !== -1;
    const message = () => `Expected element${pass ? ' not' : ''} to have${options.exact ? ' exact' : ''} text '${expected}', but had '${actual}'`;
    return { pass, message };
};
const comparator = (func) => () => ({
    compare: func,
});
/**
 *
 * expect('.zippy__content').not.toExist();
 */
export const toExist = comparator((el) => {
    const actual = $(el).length;
    const pass = actual > 0;
    const message = () => `Expected ${el} element${pass ? ' not' : ''} to exist`;
    return { pass, message };
});
/**
 *
 * expect('.zippy__content').toHaveLength(3);
 */
export const toHaveLength = comparator((el, expected) => {
    const actual = $(el).length;
    const pass = actual === expected;
    const message = () => `Expected element${pass ? ' not' : ''} to have length ${expected}, but had ${actual}`;
    return { pass, message };
});
/**
 *
 * expect('.zippy__content').toHaveId('ID');
 */
export const toHaveId = comparator((el, expected) => {
    const actual = $(el).attr('id');
    const pass = actual === expected;
    const message = () => `Expected element${pass ? ' not' : ''} to have ID '${expected}', but had '${actual}'`;
    return { pass, message };
});
/**
 * This validates classes in strict order. If you want to validate classes in any order,
 * just set the strict config option to false.
 *
 * expect('.zippy__content').toHaveClass('class');
 * expect('.zippy__content').toHaveClass('class-a, class-b');
 * expect('.zippy__content').toHaveClass(['class-a, class-b']);
 * expect('.zippy__content').toHaveClass(['class-b, class-a']);
 * expect('.zippy__content').not.toHaveClass(['class-b, class-a'], { strict: true });
 */
export const toHaveClass = comparator((el, expected, options = { strict: true }) => {
    if (expected && Array.isArray(expected)) {
        const actual = $(el).attr('class');
        const expectedClasses = expected.join(' ');
        const pass = options.strict ? $(el).hasClass(expectedClasses) : expected.every((e) => $(el).hasClass(e));
        const message = () => `Expected element${pass ? ' not' : ''} to have value '${expectedClasses}', but had '${actual}'`;
        return { pass, message };
    }
    const actual = $(el).attr('class');
    const pass = $(el).hasClass(expected);
    const message = () => `Expected element${pass ? ' not' : ''} to have class '${expected}', but had '${actual}'`;
    return { pass, message };
});
/**
 * expect(host.query('.zippy')).toHaveAttribute('id', 'zippy');
 */
export const toHaveAttribute = comparator((el, attr, val) => {
    if (isObject(attr)) {
        let pass = false;
        let failing;
        for (const key of Object.keys(attr)) {
            const actual = $(el).attr(key);
            const addendum = attr[key] !== undefined ? ` with value '${attr[key]}'` : '';
            pass = hasProperty(actual, attr[key]);
            failing = !pass ? `'${attr}'${addendum}, but had '${actual}'` : '';
        }
        const message = () => `Expected element${pass ? ' not' : ''} to have attribute ${failing}`;
        return { pass, message };
    }
    const actual = $(el).attr(attr);
    const addendum = val !== undefined ? ` with value '${val}'` : '';
    const pass = hasProperty(actual, val);
    const message = () => `Expected element${pass ? ' not' : ''} to have attribute '${attr}'${addendum}, but had '${actual}'`;
    return { pass, message };
});
/**
 *  expect(host.query('.checkbox')).toHaveProperty('checked', true);
 *  expect(host.query('.checkbox')).toHaveProperty({checked: true});
 */
export const toHaveProperty = comparator((el, prop, val) => {
    if (isObject(prop)) {
        return checkProperty(el, prop, hasProperty);
    }
    const actual = $(el).prop(prop);
    const addendum = val !== undefined ? ` with value '${val}'` : '';
    const pass = hasProperty(actual, val);
    const message = () => `Expected element${pass ? ' not' : ''} to have property '${prop}'${addendum}, but had '${actual}'`;
    return { pass, message };
});
export const toContainProperty = comparator((el, prop, val) => {
    if (isObject(prop)) {
        return checkProperty(el, prop, containsProperty);
    }
    const actual = $(el).prop(prop);
    const addendum = val !== undefined ? ` with value '${val}'` : '';
    const pass = containsProperty(actual, val);
    const message = () => `Expected element${pass ? ' not' : ''} to have property '${prop}'${addendum}, but had '${actual}'`;
    return { pass, message };
});
/**
 *
 * expect('.zippy__content').toHaveText('Content');
 * expect('.zippy__content').toHaveText(['Content A', 'Content B']);
 *
 * expect('.zippy__content').toHaveText((text) => text.includes('..');
 */
export const toHaveText = comparator((el, expected, exact = false) => hasSameText(el, expected, { exact, trim: false }));
export const toHaveExactText = comparator((el, expected, options = { trim: false }) => hasSameText(el, expected, { exact: true, trim: options.trim }));
export const toHaveExactTrimmedText = comparator((el, expected) => hasSameText(el, expected, { exact: true, trim: true }));
export const toContainText = toHaveText;
/**
 *
 * expect('.zippy__content').toHaveValue('value');
 * expect('.zippy__content').toHaveValue(['value a', 'value b']);
 */
export const toHaveValue = comparator((el, expected) => {
    if (expected && Array.isArray(expected)) {
        let actual;
        let pass = false;
        let failing;
        $(el).each((i, e) => {
            actual = $(e).val();
            pass = actual === expected[i];
            if (!pass) {
                failing = expected[i];
                return false;
            }
        });
        const message = () => `Expected element${pass ? ' not' : ''} to have value '${failing}', but had '${actual}'`;
        return { pass, message };
    }
    const actual = $(el).val();
    const pass = actual === expected;
    const message = () => `Expected element${pass ? ' not' : ''} to have value '${expected}', but had '${actual}'`;
    return { pass, message };
});
export const toContainValue = toHaveValue;
/**
 *
 *  expect(host.element).toHaveStyle({
 *    backgroundColor: 'rgba(0, 0, 0, 0.1)'
 *  });
 */
export const toHaveStyle = comparator((el, expected) => {
    const pass = hasCss(el, expected);
    const message = () => `Expected element${pass ? ' not' : ''} to have CSS ${JSON.stringify(expected)}`;
    return { pass, message };
});
/**
 *
 * expect('.zippy__content').toHaveData({data: 'role', val: 'admin'});
 */
export const toHaveData = comparator((el, { data, val }) => {
    const actual = $(el).data(data);
    const addendum = val !== undefined ? ` with value '${val}'` : '';
    const pass = hasProperty(actual, val);
    const message = () => `Expected element${pass ? ' not' : ''} to have data '${data}'${addendum}, but had '${actual}'`;
    return { pass, message };
});
/**
 *
 * expect('.checkbox').toBeChecked();
 */
export const toBeChecked = comparator((el) => {
    const pass = $(el).is(':checked');
    const message = () => `Expected element${pass ? ' not' : ''} to be checked`;
    return { pass, message };
});
/**
 *
 * expect('.checkbox').toBeIndeterminate();
 */
export const toBeIndeterminate = comparator((el) => {
    const pass = $(el).is(':indeterminate');
    const message = () => `Expected element${pass ? ' not' : ''} to be indeterminate`;
    return { pass, message };
});
/**
 *
 * expect('.checkbox').toBeDisabled();
 */
export const toBeDisabled = comparator((el) => {
    const pass = $(el).is(':disabled');
    const message = () => `Expected element${pass ? ' not' : ''} to be disabled`;
    return { pass, message };
});
/**
 * An empty element is an element without child elements or text.
 *
 * expect('div').toBeEmpty();
 */
export const toBeEmpty = comparator((el) => {
    const pass = $(el).is(':empty');
    const message = () => `Expected element${pass ? ' not' : ''} to be empty`;
    return { pass, message };
});
/**
 * Verify if an object has some expected properties.
 *
 * const actual = { lorem: 'first', ipsum: 'second' };
 * expect(actual).toBePartial({ lorem: 'first' });
 */
export const toBePartial = comparator((actual, expected) => {
    const mapToPropsAndValues = (values, properties) => {
        return properties.map((prop) => {
            return {
                name: prop,
                value: values[prop],
                type: typeof values[prop],
            };
        });
    };
    const actualProps = Object.getOwnPropertyNames(actual);
    const actualPropsAndValues = mapToPropsAndValues(actual, actualProps);
    const expectedProps = Object.getOwnPropertyNames(expected);
    const expectedPropsAndValues = mapToPropsAndValues(expected, expectedProps);
    const pass = expectedProps.every((expectedProp) => actual[expectedProp] === expected[expectedProp]);
    const message = () => `Expected element${pass ? ' not' : ''} to contain properties: ${JSON.stringify(expectedPropsAndValues)}.`.concat(` Actual properties: ${JSON.stringify(actualPropsAndValues)}`);
    return { pass, message };
});
/**
 * Hidden elements are elements that have:
 * 1. Display or visibility style properties set to "none" or "hidden"
 * 2. Display or visibility computed styles set to "none" or "hidden"
 * 3. Width and height set to 0 (check not applied in jest)
 * 4. A hidden parent element (this also hides child elements)
 * 5. Type equal to "hidden" (only for form elements)
 * 6. A "hidden" attribute
 */
function isHidden(elOrSelector) {
    let el = $(elOrSelector)[0];
    if (!el) {
        return true;
    }
    const hiddenWhen = [
        (el) => !(el.offsetWidth || el.offsetHeight || el.getClientRects().length),
        (el) => el.style.display === 'none' || window.getComputedStyle(el).getPropertyValue?.('display') === 'none',
        (el) => el.style.visibility === 'hidden' || window.getComputedStyle(el).getPropertyValue?.('visibility') === 'hidden',
        (el) => el.type === 'hidden',
        (el) => el.hasAttribute('hidden'),
    ];
    if (isRunningInJsDom()) {
        // When running in JSDOM (Jest), offset-properties and client rects are always reported as 0
        // - hence, let's take a more "naive" approach here. (https://github.com/jsdom/jsdom/issues/135)
        hiddenWhen.shift();
    }
    while (el) {
        if (el === document) {
            break;
        }
        if (el.nodeType === Node.ELEMENT_NODE && hiddenWhen.some((rule) => rule(el))) {
            return true;
        }
        el = el.parentNode || el.host;
    }
    return false;
}
/**
 * Hidden elements are elements that have:
 * 1. Display or visibility style properties set to "none" or "hidden"
 * 2. Display or visibility computed styles set to "none" or "hidden"
 * 3. Width and height set to 0 (check not applied in jest)
 * 4. A hidden parent element (this also hides child elements)
 * 5. Type equal to "hidden" (only for form elements)
 * 6. A "hidden" attribute
 *
 * expect('div').toBeHidden();
 *
 */
export const toBeHidden = comparator((el) => {
    const pass = isHidden(el);
    const message = () => `Expected element${pass ? ' not' : ''} to be hidden`;
    return { pass, message };
});
/**
 * The :selected selector selects option elements that are pre-selected.
 *
 * expect('div').toBeSelected();
 *
 */
export const toBeSelected = comparator((el) => {
    const pass = $(el).is(':selected');
    const message = () => `Expected element${pass ? ' not' : ''} to be selected`;
    return { pass, message };
});
/**
 * Hidden elements are elements that have:
 * 1. Display property set to "none"
 * 2. Width and height set to 0
 * 3. A hidden parent element (this also hides child elements)
 * 4. Type equal to "hidden" (only for form elements)
 * 5. A "hidden" attribute
 *
 * expect('div').toBeVisible();
 *
 */
export const toBeVisible = comparator((el) => {
    const pass = !isHidden(el);
    const message = () => `Expected element${pass ? ' not' : ''} to be visible`;
    return { pass, message };
});
/**
 * The :focus selector selects the element that currently has focus.
 *
 * expect('input').toBeFocused();
 */
export const toBeFocused = comparator((el) => {
    const element = $(el).get(0);
    const pass = element === element.ownerDocument.activeElement;
    const message = () => `Expected element${pass ? ' not' : ''} to be focused`;
    return { pass, message };
});
/**
 * Check to see if the set of matched elements matches the given selector
 * returns true if the dom contains the element
 *
 * expect('div').toBeMatchedBy('.js-something')
 */
export const toBeMatchedBy = comparator((el, expected) => {
    const actual = $(el).filter(expected).length;
    const pass = actual > 0;
    const message = () => `Expected element${pass ? ' not' : ''} to be matched by '${expected}'`;
    return { pass, message };
});
/**
 *
 * expect('div').toHaveDescendant('.child')
 */
export const toHaveDescendant = comparator((el, selector) => {
    const actual = $(el).find(selector).length;
    const pass = actual > 0;
    const message = () => `Expected element${pass ? ' not' : ''} to contain child '${selector}'`;
    return { pass, message };
});
/**
 *
 * expect('div').toHaveDescendantWithText({selector: '.child', text: 'text'})
 */
export const toHaveDescendantWithText = comparator((el, { selector, text }) => {
    const actual = $.trim($(el).find(selector).text());
    if (text && $.isFunction(text.test)) {
        const pass = text.test(actual);
        const message = () => `Expected element${pass ? ' not' : ''} to have descendant '${selector}' with text matching '${text}',` + ` but had '${actual}'`;
        return { pass, message };
    }
    const pass = actual.indexOf(text) !== -1;
    const message = () => `Expected element${pass ? ' not' : ''} to have descendant '${selector}' with text '${text}', but had '${actual}'`;
    return { pass, message };
});
export const toHaveSelectedOptions = comparator((el, expected) => {
    if (expected instanceof HTMLOptionElement) {
        const actual = $(el).find(':selected');
        const pass = actual.is($(expected));
        const message = () => `Expected element${pass ? ' not' : ''} to have options '[${expected.outerHTML}]' but had '[${actual[0].outerHTML}]'`;
        return { pass, message };
    }
    if (isHTMLOptionElementArray(expected)) {
        const actual = $(el).find(':selected');
        const pass = actual.length === expected.length && actual.toArray().every((_, index) => $(actual[index]).is(expected[index]));
        const expectedOptionsString = $(expected)
            .get()
            .map((option) => option.outerHTML)
            .join(',');
        const actualOptionsString = actual
            .get()
            .map((option) => option.outerHTML)
            .join(',');
        const message = () => `Expected element${pass ? ' not' : ''} to have options '[${expectedOptionsString}]' but had '[${actualOptionsString}]'`;
        return { pass, message };
    }
    const actual = $(el).val();
    const pass = coerceArray(expected)?.every((v) => actual.includes(v));
    const expectedOptionsString = Array.isArray(expected)
        ? expected.reduce((acc, val, i) => acc + `${i === expected.length ? '' : ','}${val}`)
        : expected;
    const message = () => `Expected element${pass ? ' not' : ''} to have options '[${expectedOptionsString}]' but had '[${actual}]'`;
    return { pass, message };
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0Y2hlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9zcGVjdGF0b3Ivc3JjL2xpYi9tYXRjaGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrR0FBK0c7QUFFL0cseUZBQXlGO0FBQ3pGLG9FQUFvRTtBQUNwRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNoRSxPQUFPLENBQUMsTUFBTSxRQUFRLENBQUM7QUFFdkIsaUJBQWlCLEVBQUUsQ0FBQztBQUVwQixPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsUUFBUSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzdELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxXQUFXLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFleEQsTUFBTSxXQUFXLEdBQUcsQ0FBQyxNQUFlLEVBQUUsUUFBaUIsRUFBVyxFQUFFO0lBQ2xFLE9BQU8sUUFBUSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxLQUFLLFFBQVEsQ0FBQztBQUM3RSxDQUFDLENBQUM7QUFFRixNQUFNLGdCQUFnQixHQUFHLENBQUMsTUFBYyxFQUFFLFFBQWlCLEVBQVcsRUFBRTtJQUN0RSxPQUFPLFFBQVEsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFrQixDQUFDLENBQUM7QUFDN0UsQ0FBQyxDQUFDO0FBRUYsTUFBTSxhQUFhLEdBQUcsQ0FDcEIsRUFBZSxFQUNmLElBQVksRUFDWixTQUF3QyxFQUNFLEVBQUU7SUFDNUMsSUFBSSxJQUFJLEdBQUcsS0FBSyxDQUFDO0lBQ2pCLElBQUksT0FBTyxHQUFHLEVBQUUsQ0FBQztJQUVqQixL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Q0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRXJFLE1BQU0scUJBQXFCLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDbkQsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFXLEVBQUUsR0FBVyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBQ3JHLENBQUMsQ0FBQyxRQUFRLENBQUM7SUFDYixNQUFNLE9BQU8sR0FBRyxHQUFHLEVBQUUsQ0FBQyxtQkFBbUIsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsc0JBQXNCLHFCQUFxQixnQkFBZ0IsTUFBTSxJQUFJLENBQUM7SUFFakksT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUMzQixDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBDcmVkaXQ6IGh0dHBzOi8vZ2l0aHViLmNvbS91bmluZGVudGVkL2N1c3RvbS1qcXVlcnktbWF0Y2hlcnMvdHJlZS9tYXN0ZXIvcGFja2FnZXMvY3VzdG9tLWpxdWVyeS1tYXRjaGVycyAqL1xuXG4vLyBUaGlzIHNob3VsZCBiZSBpbXBvcnRlZCBiZWZvcmUgYGpxdWVyeWAgc2luY2UgdGhpcyBsaWJyYXJ5IHVucGF0Y2hlcyB0aGUgYHNldFRpbWVvdXRgLFxuLy8gc28galF1ZXJ5IHdvbid0IHNldHVwIGEgdGltZXIsIHRoYXQgbWlnaHQgYmUgY2FwdHVyZWQgYnkgem9uZS5qcy5cbmltcG9ydCB7IHJlc3RvcmVTZXRUaW1lb3V0IH0gZnJvbSAnQG5nbmVhdC9zcGVjdGF0b3IvaW50ZXJuYWxzJztcbmltcG9ydCAkIGZyb20gJ2pxdWVyeSc7XG5cbnJlc3RvcmVTZXRUaW1lb3V0KCk7XG5cbmltcG9ydCB7IGhleDJyZ2IsIGlzSGV4LCB0cmltIH0gZnJvbSAnLi9pbnRlcm5hbHMvcmdiLXRvLWhleCc7XG5pbXBvcnQgeyBpc0hUTUxPcHRpb25FbGVtZW50QXJyYXksIGlzT2JqZWN0IH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBpc1J1bm5pbmdJbkpzRG9tLCBjb2VyY2VBcnJheSB9IGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEN1c3RvbU1hdGNoZXJGYWN0b3J5IHtcbiAgKCk6IEN1c3RvbU1hdGNoZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3VzdG9tTWF0Y2hlciB7XG4gIGNvbXBhcmU8VD4oYWN0dWFsOiBULCBleHBlY3RlZDogVCwgLi4uYXJnczogYW55W10pOiBDdXN0b21NYXRjaGVyUmVzdWx0O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEN1c3RvbU1hdGNoZXJSZXN1bHQge1xuICBwYXNzOiBib29sZWFuO1xuICBtZXNzYWdlOiAoKSA9PiBzdHJpbmc7XG59XG5cbmNvbnN0IGhhc1Byb3BlcnR5ID0gKGFjdHVhbDogdW5rbm93biwgZXhwZWN0ZWQ6IHVua25vd24pOiBib29sZWFuID0+IHtcbiAgcmV0dXJuIGV4cGVjdGVkID09PSB1bmRlZmluZWQgPyBhY3R1YWwgIT09IHVuZGVmaW5lZCA6IGFjdHVhbCA9PT0gZXhwZWN0ZWQ7XG59O1xuXG5jb25zdCBjb250YWluc1Byb3BlcnR5ID0gKGFjdHVhbDogc3RyaW5nLCBleHBlY3RlZDogdW5rbm93bik6IGJvb2xlYW4gPT4ge1xuICByZXR1cm4gZXhwZWN0ZWQgPT09IHVuZGVmaW5lZCA/IHRydWUgOiBhY3R1YWwuaW5jbHVkZXMoZXhwZWN0ZWQgYXMgc3RyaW5nKTtcbn07XG5cbmNvbnN0IGNoZWNrUHJvcGVydHkgPSAoXG4gIGVsOiBIVE1MRWxlbWVudCxcbiAgcHJvcDogb2JqZWN0LFxuICBwcmVkaWNhdGU6IChhY3R1YWwsIGV4cGVjdGVkKSA9PiBib29sZWFuLFxuKTogeyBwYXNzOiBib29sZWFuOyBtZXNzYWdlOiAoKSA9PiBzdHJpbmcgfSA9PiB7XG4gIGxldCBwYXNzID0gZmFsc2U7XG4gIGxldCBmYWlsaW5nID0gJyc7XG5cbiAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMocHJvcCkpIHtcbiAgICBjb25zdCBhY3R1YWwgPSAkKGVsKS5wcm9wKGtleSk7XG4gICAgY29uc3QgYWRkZW5kdW0gPSBwcm9wW2tleV0gIT09IHVuZGVmaW5lZCA/IGAgd2l0aCB2YWx1ZSAnJHtwcm9wW2tleV19J2AgOiAnJztcblxuICAgIHBhc3MgPSBwcmVkaWNhdGUoYWN0dWFsLCBwcm9wW2tleV0pO1xuICAgIGZhaWxpbmcgPSAhcGFzcyA/IGAnJHtwcm9wfScke2FkZGVuZHVtfSwgYnV0IGhhZCAnJHthY3R1YWx9J2AgOiAnJztcbiAgfVxuXG4gIGNvbnN0IG1lc3NhZ2UgPSAoKSA9PiBgRXhwZWN0ZWQgZWxlbWVudCR7cGFzcyA/ICcgbm90JyA6ICcnfSB0byBoYXZlIHByb3BlcnR5ICR7ZmFpbGluZ31gO1xuXG4gIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbn07XG5cbmNvbnN0IGhhc0NzcyA9IChlbDogSFRNTEVsZW1lbnQsIGNzczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSkgPT4ge1xuICBsZXQgcHJvcDtcbiAgbGV0IHZhbHVlO1xuICBjb25zdCAkZWwgPSAkKGVsKTtcbiAgZm9yIChwcm9wIGluIGNzcykge1xuICAgIGlmIChjc3MuaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgIHZhbHVlID0gY3NzW3Byb3BdO1xuXG4gICAgICBpZiAoaXNIZXgodmFsdWUpKSB7XG4gICAgICAgIHZhbHVlID0gaGV4MnJnYihjc3NbcHJvcF0pO1xuICAgICAgfVxuXG4gICAgICBpZiAodmFsdWUgPT09ICdhdXRvJyAmJiAkZWwuZ2V0KDApLnN0eWxlW3Byb3BdID09PSAnYXV0bycpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgdHJpbSgkZWwuZ2V0KDApLnN0eWxlW3Byb3BdKSAhPT0gdHJpbSh2YWx1ZSkgJiZcbiAgICAgICAgdHJpbShlbC5zdHlsZVtwcm9wXSkgIT09IHRyaW0odmFsdWUpICYmXG4gICAgICAgIHRyaW0oZWwuc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZShwcm9wKSkgIT09IHRyaW0odmFsdWUpXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuY29uc3QgaGFzU2FtZVRleHQgPSAoXG4gIGVsOiBIVE1MRWxlbWVudCxcbiAgZXhwZWN0ZWQ6IHN0cmluZyB8IHN0cmluZ1tdIHwgKChzOiBzdHJpbmcpID0+IGJvb2xlYW4pLFxuICBvcHRpb25zOiB7XG4gICAgZXhhY3Q6IGJvb2xlYW47XG4gICAgdHJpbTogYm9vbGVhbjtcbiAgfSxcbikgPT4ge1xuICBpZiAoZXhwZWN0ZWQgJiYgQXJyYXkuaXNBcnJheShleHBlY3RlZCkpIHtcbiAgICBsZXQgYWN0dWFsOiBzdHJpbmc7XG4gICAgbGV0IHBhc3MgPSBmYWxzZTtcbiAgICBsZXQgZmFpbGluZzogc3RyaW5nO1xuXG4gICAgJChlbCkuZWFjaCgoaSwgZSkgPT4ge1xuICAgICAgYWN0dWFsID0gb3B0aW9ucy5leGFjdCAmJiAhb3B0aW9ucy50cmltID8gJChlKS50ZXh0KCkgOiAkLnRyaW0oJChlKS50ZXh0KCkpO1xuICAgICAgcGFzcyA9IG9wdGlvbnMuZXhhY3QgPyBhY3R1YWwgPT09IGV4cGVjdGVkW2ldIDogYWN0dWFsLmluY2x1ZGVzKGV4cGVjdGVkW2ldKTtcbiAgICAgIGlmICghcGFzcykge1xuICAgICAgICBmYWlsaW5nID0gZXhwZWN0ZWRbaV07XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgbWVzc2FnZSA9ICgpID0+XG4gICAgICBgRXhwZWN0ZWQgZWxlbWVudCR7cGFzcyA/ICcgbm90JyA6ICcnfSB0byBoYXZlJHtvcHRpb25zLmV4YWN0ID8gJyBleGFjdCcgOiAnJ30gdGV4dCAnJHtmYWlsaW5nfScsIGJ1dCBoYWQgJyR7YWN0dWFsfSdgO1xuXG4gICAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xuICB9XG5cbiAgY29uc3QgYWN0dWFsID0gb3B0aW9ucy5leGFjdCAmJiAhb3B0aW9ucy50cmltID8gJChlbCkudGV4dCgpIDogJC50cmltKCQoZWwpLnRleHQoKSk7XG5cbiAgaWYgKGV4cGVjdGVkICYmIHR5cGVvZiBleHBlY3RlZCAhPT0gJ3N0cmluZycpIHtcbiAgICBjb25zdCBwYXNzID0gZXhwZWN0ZWQoYWN0dWFsKTtcbiAgICBjb25zdCBtZXNzYWdlID0gKCkgPT5cbiAgICAgIGBFeHBlY3RlZCBlbGVtZW50JHtwYXNzID8gJyBub3QnIDogJyd9IHRvIGhhdmUke29wdGlvbnMuZXhhY3QgPyAnIGV4YWN0JyA6ICcnfSB0ZXh0IG1hdGNoaW5nICcke2V4cGVjdGVkfScsYCArIGAgYnV0IGhhZCAnJHthY3R1YWx9J2A7XG5cbiAgICByZXR1cm4geyBwYXNzLCBtZXNzYWdlIH07XG4gIH1cblxuICBjb25zdCBwYXNzID0gb3B0aW9ucy5leGFjdCAmJiAhQXJyYXkuaXNBcnJheShleHBlY3RlZCkgPyBhY3R1YWwgPT09IGV4cGVjdGVkIDogYWN0dWFsLmluZGV4T2YoZXhwZWN0ZWQpICE9PSAtMTtcbiAgY29uc3QgbWVzc2FnZSA9ICgpID0+XG4gICAgYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSR7b3B0aW9ucy5leGFjdCA/ICcgZXhhY3QnIDogJyd9IHRleHQgJyR7ZXhwZWN0ZWR9JywgYnV0IGhhZCAnJHthY3R1YWx9J2A7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufTtcblxuY29uc3QgY29tcGFyYXRvciA9XG4gIChmdW5jKTogQ3VzdG9tTWF0Y2hlckZhY3RvcnkgPT5cbiAgKCkgPT4gKHtcbiAgICBjb21wYXJlOiBmdW5jLFxuICB9KTtcblxuLyoqXG4gKlxuICogZXhwZWN0KCcuemlwcHlfX2NvbnRlbnQnKS5ub3QudG9FeGlzdCgpO1xuICovXG5leHBvcnQgY29uc3QgdG9FeGlzdCA9IGNvbXBhcmF0b3IoKGVsOiBzdHJpbmcgfCBFbGVtZW50KSA9PiB7XG4gIGNvbnN0IGFjdHVhbCA9ICQoZWwpLmxlbmd0aDtcbiAgY29uc3QgcGFzcyA9IGFjdHVhbCA+IDA7XG4gIGNvbnN0IG1lc3NhZ2UgPSAoKSA9PiBgRXhwZWN0ZWQgJHtlbH0gZWxlbWVudCR7cGFzcyA/ICcgbm90JyA6ICcnfSB0byBleGlzdGA7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbi8qKlxuICpcbiAqIGV4cGVjdCgnLnppcHB5X19jb250ZW50JykudG9IYXZlTGVuZ3RoKDMpO1xuICovXG5leHBvcnQgY29uc3QgdG9IYXZlTGVuZ3RoID0gY29tcGFyYXRvcigoZWw6IHN0cmluZywgZXhwZWN0ZWQ6IG51bWJlcikgPT4ge1xuICBjb25zdCBhY3R1YWwgPSAkKGVsKS5sZW5ndGg7XG4gIGNvbnN0IHBhc3MgPSBhY3R1YWwgPT09IGV4cGVjdGVkO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSBsZW5ndGggJHtleHBlY3RlZH0sIGJ1dCBoYWQgJHthY3R1YWx9YDtcblxuICByZXR1cm4geyBwYXNzLCBtZXNzYWdlIH07XG59KTtcblxuLyoqXG4gKlxuICogZXhwZWN0KCcuemlwcHlfX2NvbnRlbnQnKS50b0hhdmVJZCgnSUQnKTtcbiAqL1xuZXhwb3J0IGNvbnN0IHRvSGF2ZUlkID0gY29tcGFyYXRvcigoZWwsIGV4cGVjdGVkKSA9PiB7XG4gIGNvbnN0IGFjdHVhbCA9ICQoZWwpLmF0dHIoJ2lkJyk7XG4gIGNvbnN0IHBhc3MgPSBhY3R1YWwgPT09IGV4cGVjdGVkO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSBJRCAnJHtleHBlY3RlZH0nLCBidXQgaGFkICcke2FjdHVhbH0nYDtcblxuICByZXR1cm4geyBwYXNzLCBtZXNzYWdlIH07XG59KTtcblxuLyoqXG4gKiBUaGlzIHZhbGlkYXRlcyBjbGFzc2VzIGluIHN0cmljdCBvcmRlci4gSWYgeW91IHdhbnQgdG8gdmFsaWRhdGUgY2xhc3NlcyBpbiBhbnkgb3JkZXIsXG4gKiBqdXN0IHNldCB0aGUgc3RyaWN0IGNvbmZpZyBvcHRpb24gdG8gZmFsc2UuXG4gKlxuICogZXhwZWN0KCcuemlwcHlfX2NvbnRlbnQnKS50b0hhdmVDbGFzcygnY2xhc3MnKTtcbiAqIGV4cGVjdCgnLnppcHB5X19jb250ZW50JykudG9IYXZlQ2xhc3MoJ2NsYXNzLWEsIGNsYXNzLWInKTtcbiAqIGV4cGVjdCgnLnppcHB5X19jb250ZW50JykudG9IYXZlQ2xhc3MoWydjbGFzcy1hLCBjbGFzcy1iJ10pO1xuICogZXhwZWN0KCcuemlwcHlfX2NvbnRlbnQnKS50b0hhdmVDbGFzcyhbJ2NsYXNzLWIsIGNsYXNzLWEnXSk7XG4gKiBleHBlY3QoJy56aXBweV9fY29udGVudCcpLm5vdC50b0hhdmVDbGFzcyhbJ2NsYXNzLWIsIGNsYXNzLWEnXSwgeyBzdHJpY3Q6IHRydWUgfSk7XG4gKi9cbmV4cG9ydCBjb25zdCB0b0hhdmVDbGFzcyA9IGNvbXBhcmF0b3IoKGVsLCBleHBlY3RlZDogc3RyaW5nIHwgc3RyaW5nW10sIG9wdGlvbnM6IHsgc3RyaWN0OiBib29sZWFuIH0gPSB7IHN0cmljdDogdHJ1ZSB9KSA9PiB7XG4gIGlmIChleHBlY3RlZCAmJiBBcnJheS5pc0FycmF5KGV4cGVjdGVkKSkge1xuICAgIGNvbnN0IGFjdHVhbDogc3RyaW5nID0gJChlbCkuYXR0cignY2xhc3MnKTtcbiAgICBjb25zdCBleHBlY3RlZENsYXNzZXMgPSBleHBlY3RlZC5qb2luKCcgJyk7XG4gICAgY29uc3QgcGFzcyA9IG9wdGlvbnMuc3RyaWN0ID8gJChlbCkuaGFzQ2xhc3MoZXhwZWN0ZWRDbGFzc2VzKSA6IGV4cGVjdGVkLmV2ZXJ5KChlKSA9PiAkKGVsKS5oYXNDbGFzcyhlKSk7XG4gICAgY29uc3QgbWVzc2FnZSA9ICgpID0+IGBFeHBlY3RlZCBlbGVtZW50JHtwYXNzID8gJyBub3QnIDogJyd9IHRvIGhhdmUgdmFsdWUgJyR7ZXhwZWN0ZWRDbGFzc2VzfScsIGJ1dCBoYWQgJyR7YWN0dWFsfSdgO1xuXG4gICAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xuICB9XG5cbiAgY29uc3QgYWN0dWFsID0gJChlbCkuYXR0cignY2xhc3MnKTtcbiAgY29uc3QgcGFzcyA9ICQoZWwpLmhhc0NsYXNzKGV4cGVjdGVkKTtcbiAgY29uc3QgbWVzc2FnZSA9ICgpID0+IGBFeHBlY3RlZCBlbGVtZW50JHtwYXNzID8gJyBub3QnIDogJyd9IHRvIGhhdmUgY2xhc3MgJyR7ZXhwZWN0ZWR9JywgYnV0IGhhZCAnJHthY3R1YWx9J2A7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbi8qKlxuICogZXhwZWN0KGhvc3QucXVlcnkoJy56aXBweScpKS50b0hhdmVBdHRyaWJ1dGUoJ2lkJywgJ3ppcHB5Jyk7XG4gKi9cbmV4cG9ydCBjb25zdCB0b0hhdmVBdHRyaWJ1dGUgPSBjb21wYXJhdG9yKChlbCwgYXR0cjogc3RyaW5nIHwgb2JqZWN0LCB2YWwpID0+IHtcbiAgaWYgKGlzT2JqZWN0KGF0dHIpKSB7XG4gICAgbGV0IHBhc3MgPSBmYWxzZTtcbiAgICBsZXQgZmFpbGluZzogc3RyaW5nO1xuXG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoYXR0cikpIHtcbiAgICAgIGNvbnN0IGFjdHVhbCA9ICQoZWwpLmF0dHIoa2V5KTtcbiAgICAgIGNvbnN0IGFkZGVuZHVtID0gYXR0cltrZXldICE9PSB1bmRlZmluZWQgPyBgIHdpdGggdmFsdWUgJyR7YXR0cltrZXldfSdgIDogJyc7XG4gICAgICBwYXNzID0gaGFzUHJvcGVydHkoYWN0dWFsLCBhdHRyW2tleV0pO1xuICAgICAgZmFpbGluZyA9ICFwYXNzID8gYCcke2F0dHJ9JyR7YWRkZW5kdW19LCBidXQgaGFkICcke2FjdHVhbH0nYCA6ICcnO1xuICAgIH1cbiAgICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSBhdHRyaWJ1dGUgJHtmYWlsaW5nfWA7XG5cbiAgICByZXR1cm4geyBwYXNzLCBtZXNzYWdlIH07XG4gIH1cblxuICBjb25zdCBhY3R1YWwgPSAkKGVsKS5hdHRyKGF0dHIpO1xuICBjb25zdCBhZGRlbmR1bSA9IHZhbCAhPT0gdW5kZWZpbmVkID8gYCB3aXRoIHZhbHVlICcke3ZhbH0nYCA6ICcnO1xuICBjb25zdCBwYXNzID0gaGFzUHJvcGVydHkoYWN0dWFsLCB2YWwpO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSBhdHRyaWJ1dGUgJyR7YXR0cn0nJHthZGRlbmR1bX0sIGJ1dCBoYWQgJyR7YWN0dWFsfSdgO1xuXG4gIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbn0pO1xuXG4vKipcbiAqICBleHBlY3QoaG9zdC5xdWVyeSgnLmNoZWNrYm94JykpLnRvSGF2ZVByb3BlcnR5KCdjaGVja2VkJywgdHJ1ZSk7XG4gKiAgZXhwZWN0KGhvc3QucXVlcnkoJy5jaGVja2JveCcpKS50b0hhdmVQcm9wZXJ0eSh7Y2hlY2tlZDogdHJ1ZX0pO1xuICovXG5leHBvcnQgY29uc3QgdG9IYXZlUHJvcGVydHkgPSBjb21wYXJhdG9yKChlbCwgcHJvcCwgdmFsKSA9PiB7XG4gIGlmIChpc09iamVjdChwcm9wKSkge1xuICAgIHJldHVybiBjaGVja1Byb3BlcnR5KGVsLCBwcm9wLCBoYXNQcm9wZXJ0eSk7XG4gIH1cblxuICBjb25zdCBhY3R1YWwgPSAkKGVsKS5wcm9wKHByb3ApO1xuICBjb25zdCBhZGRlbmR1bSA9IHZhbCAhPT0gdW5kZWZpbmVkID8gYCB3aXRoIHZhbHVlICcke3ZhbH0nYCA6ICcnO1xuICBjb25zdCBwYXNzID0gaGFzUHJvcGVydHkoYWN0dWFsLCB2YWwpO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSBwcm9wZXJ0eSAnJHtwcm9wfScke2FkZGVuZHVtfSwgYnV0IGhhZCAnJHthY3R1YWx9J2A7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbmV4cG9ydCBjb25zdCB0b0NvbnRhaW5Qcm9wZXJ0eSA9IGNvbXBhcmF0b3IoKGVsLCBwcm9wLCB2YWwpID0+IHtcbiAgaWYgKGlzT2JqZWN0KHByb3ApKSB7XG4gICAgcmV0dXJuIGNoZWNrUHJvcGVydHkoZWwsIHByb3AsIGNvbnRhaW5zUHJvcGVydHkpO1xuICB9XG5cbiAgY29uc3QgYWN0dWFsID0gJChlbCkucHJvcChwcm9wKTtcbiAgY29uc3QgYWRkZW5kdW0gPSB2YWwgIT09IHVuZGVmaW5lZCA/IGAgd2l0aCB2YWx1ZSAnJHt2YWx9J2AgOiAnJztcbiAgY29uc3QgcGFzcyA9IGNvbnRhaW5zUHJvcGVydHkoYWN0dWFsLCB2YWwpO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSBwcm9wZXJ0eSAnJHtwcm9wfScke2FkZGVuZHVtfSwgYnV0IGhhZCAnJHthY3R1YWx9J2A7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbi8qKlxuICpcbiAqIGV4cGVjdCgnLnppcHB5X19jb250ZW50JykudG9IYXZlVGV4dCgnQ29udGVudCcpO1xuICogZXhwZWN0KCcuemlwcHlfX2NvbnRlbnQnKS50b0hhdmVUZXh0KFsnQ29udGVudCBBJywgJ0NvbnRlbnQgQiddKTtcbiAqXG4gKiBleHBlY3QoJy56aXBweV9fY29udGVudCcpLnRvSGF2ZVRleHQoKHRleHQpID0+IHRleHQuaW5jbHVkZXMoJy4uJyk7XG4gKi9cbmV4cG9ydCBjb25zdCB0b0hhdmVUZXh0ID0gY29tcGFyYXRvcigoZWwsIGV4cGVjdGVkLCBleGFjdCA9IGZhbHNlKSA9PiBoYXNTYW1lVGV4dChlbCwgZXhwZWN0ZWQsIHsgZXhhY3QsIHRyaW06IGZhbHNlIH0pKTtcblxuZXhwb3J0IGNvbnN0IHRvSGF2ZUV4YWN0VGV4dCA9IGNvbXBhcmF0b3IoKGVsLCBleHBlY3RlZCwgb3B0aW9uczogeyB0cmltOiBib29sZWFuIH0gPSB7IHRyaW06IGZhbHNlIH0pID0+XG4gIGhhc1NhbWVUZXh0KGVsLCBleHBlY3RlZCwgeyBleGFjdDogdHJ1ZSwgdHJpbTogb3B0aW9ucy50cmltIH0pLFxuKTtcblxuZXhwb3J0IGNvbnN0IHRvSGF2ZUV4YWN0VHJpbW1lZFRleHQgPSBjb21wYXJhdG9yKChlbCwgZXhwZWN0ZWQpID0+IGhhc1NhbWVUZXh0KGVsLCBleHBlY3RlZCwgeyBleGFjdDogdHJ1ZSwgdHJpbTogdHJ1ZSB9KSk7XG5cbmV4cG9ydCBjb25zdCB0b0NvbnRhaW5UZXh0ID0gdG9IYXZlVGV4dDtcblxuLyoqXG4gKlxuICogZXhwZWN0KCcuemlwcHlfX2NvbnRlbnQnKS50b0hhdmVWYWx1ZSgndmFsdWUnKTtcbiAqIGV4cGVjdCgnLnppcHB5X19jb250ZW50JykudG9IYXZlVmFsdWUoWyd2YWx1ZSBhJywgJ3ZhbHVlIGInXSk7XG4gKi9cbmV4cG9ydCBjb25zdCB0b0hhdmVWYWx1ZSA9IGNvbXBhcmF0b3IoKGVsLCBleHBlY3RlZCkgPT4ge1xuICBpZiAoZXhwZWN0ZWQgJiYgQXJyYXkuaXNBcnJheShleHBlY3RlZCkpIHtcbiAgICBsZXQgYWN0dWFsOiBzdHJpbmc7XG4gICAgbGV0IHBhc3MgPSBmYWxzZTtcbiAgICBsZXQgZmFpbGluZzogc3RyaW5nO1xuXG4gICAgJChlbCkuZWFjaCgoaSwgZSkgPT4ge1xuICAgICAgYWN0dWFsID0gJChlKS52YWwoKTtcbiAgICAgIHBhc3MgPSBhY3R1YWwgPT09IGV4cGVjdGVkW2ldO1xuICAgICAgaWYgKCFwYXNzKSB7XG4gICAgICAgIGZhaWxpbmcgPSBleHBlY3RlZFtpXTtcblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSB2YWx1ZSAnJHtmYWlsaW5nfScsIGJ1dCBoYWQgJyR7YWN0dWFsfSdgO1xuXG4gICAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xuICB9XG5cbiAgY29uc3QgYWN0dWFsID0gJChlbCkudmFsKCk7XG4gIGNvbnN0IHBhc3MgPSBhY3R1YWwgPT09IGV4cGVjdGVkO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSB2YWx1ZSAnJHtleHBlY3RlZH0nLCBidXQgaGFkICcke2FjdHVhbH0nYDtcblxuICByZXR1cm4geyBwYXNzLCBtZXNzYWdlIH07XG59KTtcblxuZXhwb3J0IGNvbnN0IHRvQ29udGFpblZhbHVlID0gdG9IYXZlVmFsdWU7XG5cbi8qKlxuICpcbiAqICBleHBlY3QoaG9zdC5lbGVtZW50KS50b0hhdmVTdHlsZSh7XG4gKiAgICBiYWNrZ3JvdW5kQ29sb3I6ICdyZ2JhKDAsIDAsIDAsIDAuMSknXG4gKiAgfSk7XG4gKi9cbmV4cG9ydCBjb25zdCB0b0hhdmVTdHlsZSA9IGNvbXBhcmF0b3IoKGVsLCBleHBlY3RlZCkgPT4ge1xuICBjb25zdCBwYXNzID0gaGFzQ3NzKGVsLCBleHBlY3RlZCk7XG4gIGNvbnN0IG1lc3NhZ2UgPSAoKSA9PiBgRXhwZWN0ZWQgZWxlbWVudCR7cGFzcyA/ICcgbm90JyA6ICcnfSB0byBoYXZlIENTUyAke0pTT04uc3RyaW5naWZ5KGV4cGVjdGVkKX1gO1xuXG4gIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbn0pO1xuXG4vKipcbiAqXG4gKiBleHBlY3QoJy56aXBweV9fY29udGVudCcpLnRvSGF2ZURhdGEoe2RhdGE6ICdyb2xlJywgdmFsOiAnYWRtaW4nfSk7XG4gKi9cbmV4cG9ydCBjb25zdCB0b0hhdmVEYXRhID0gY29tcGFyYXRvcigoZWwsIHsgZGF0YSwgdmFsIH0pID0+IHtcbiAgY29uc3QgYWN0dWFsID0gJChlbCkuZGF0YShkYXRhKTtcbiAgY29uc3QgYWRkZW5kdW0gPSB2YWwgIT09IHVuZGVmaW5lZCA/IGAgd2l0aCB2YWx1ZSAnJHt2YWx9J2AgOiAnJztcbiAgY29uc3QgcGFzcyA9IGhhc1Byb3BlcnR5KGFjdHVhbCwgdmFsKTtcbiAgY29uc3QgbWVzc2FnZSA9ICgpID0+IGBFeHBlY3RlZCBlbGVtZW50JHtwYXNzID8gJyBub3QnIDogJyd9IHRvIGhhdmUgZGF0YSAnJHtkYXRhfScke2FkZGVuZHVtfSwgYnV0IGhhZCAnJHthY3R1YWx9J2A7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbi8qKlxuICpcbiAqIGV4cGVjdCgnLmNoZWNrYm94JykudG9CZUNoZWNrZWQoKTtcbiAqL1xuZXhwb3J0IGNvbnN0IHRvQmVDaGVja2VkID0gY29tcGFyYXRvcigoZWwpID0+IHtcbiAgY29uc3QgcGFzcyA9ICQoZWwpLmlzKCc6Y2hlY2tlZCcpO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gYmUgY2hlY2tlZGA7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbi8qKlxuICpcbiAqIGV4cGVjdCgnLmNoZWNrYm94JykudG9CZUluZGV0ZXJtaW5hdGUoKTtcbiAqL1xuZXhwb3J0IGNvbnN0IHRvQmVJbmRldGVybWluYXRlID0gY29tcGFyYXRvcigoZWwpID0+IHtcbiAgY29uc3QgcGFzcyA9ICQoZWwpLmlzKCc6aW5kZXRlcm1pbmF0ZScpO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gYmUgaW5kZXRlcm1pbmF0ZWA7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbi8qKlxuICpcbiAqIGV4cGVjdCgnLmNoZWNrYm94JykudG9CZURpc2FibGVkKCk7XG4gKi9cbmV4cG9ydCBjb25zdCB0b0JlRGlzYWJsZWQgPSBjb21wYXJhdG9yKChlbCkgPT4ge1xuICBjb25zdCBwYXNzID0gJChlbCkuaXMoJzpkaXNhYmxlZCcpO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gYmUgZGlzYWJsZWRgO1xuXG4gIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbn0pO1xuXG4vKipcbiAqIEFuIGVtcHR5IGVsZW1lbnQgaXMgYW4gZWxlbWVudCB3aXRob3V0IGNoaWxkIGVsZW1lbnRzIG9yIHRleHQuXG4gKlxuICogZXhwZWN0KCdkaXYnKS50b0JlRW1wdHkoKTtcbiAqL1xuZXhwb3J0IGNvbnN0IHRvQmVFbXB0eSA9IGNvbXBhcmF0b3IoKGVsKSA9PiB7XG4gIGNvbnN0IHBhc3MgPSAkKGVsKS5pcygnOmVtcHR5Jyk7XG4gIGNvbnN0IG1lc3NhZ2UgPSAoKSA9PiBgRXhwZWN0ZWQgZWxlbWVudCR7cGFzcyA/ICcgbm90JyA6ICcnfSB0byBiZSBlbXB0eWA7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbi8qKlxuICogVmVyaWZ5IGlmIGFuIG9iamVjdCBoYXMgc29tZSBleHBlY3RlZCBwcm9wZXJ0aWVzLlxuICpcbiAqIGNvbnN0IGFjdHVhbCA9IHsgbG9yZW06ICdmaXJzdCcsIGlwc3VtOiAnc2Vjb25kJyB9O1xuICogZXhwZWN0KGFjdHVhbCkudG9CZVBhcnRpYWwoeyBsb3JlbTogJ2ZpcnN0JyB9KTtcbiAqL1xuZXhwb3J0IGNvbnN0IHRvQmVQYXJ0aWFsID0gY29tcGFyYXRvcigoYWN0dWFsLCBleHBlY3RlZCkgPT4ge1xuICBjb25zdCBtYXBUb1Byb3BzQW5kVmFsdWVzID0gKHZhbHVlczogYW55W10sIHByb3BlcnRpZXM6IGFueVtdKSA9PiB7XG4gICAgcmV0dXJuIHByb3BlcnRpZXMubWFwKChwcm9wKSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiBwcm9wLFxuICAgICAgICB2YWx1ZTogdmFsdWVzW3Byb3BdLFxuICAgICAgICB0eXBlOiB0eXBlb2YgdmFsdWVzW3Byb3BdLFxuICAgICAgfTtcbiAgICB9KTtcbiAgfTtcbiAgY29uc3QgYWN0dWFsUHJvcHMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhhY3R1YWwpO1xuICBjb25zdCBhY3R1YWxQcm9wc0FuZFZhbHVlcyA9IG1hcFRvUHJvcHNBbmRWYWx1ZXMoYWN0dWFsLCBhY3R1YWxQcm9wcyk7XG5cbiAgY29uc3QgZXhwZWN0ZWRQcm9wcyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGV4cGVjdGVkKTtcbiAgY29uc3QgZXhwZWN0ZWRQcm9wc0FuZFZhbHVlcyA9IG1hcFRvUHJvcHNBbmRWYWx1ZXMoZXhwZWN0ZWQsIGV4cGVjdGVkUHJvcHMpO1xuXG4gIGNvbnN0IHBhc3MgPSBleHBlY3RlZFByb3BzLmV2ZXJ5KChleHBlY3RlZFByb3ApID0+IGFjdHVhbFtleHBlY3RlZFByb3BdID09PSBleHBlY3RlZFtleHBlY3RlZFByb3BdKTtcbiAgY29uc3QgbWVzc2FnZSA9ICgpID0+XG4gICAgYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gY29udGFpbiBwcm9wZXJ0aWVzOiAke0pTT04uc3RyaW5naWZ5KGV4cGVjdGVkUHJvcHNBbmRWYWx1ZXMpfS5gLmNvbmNhdChcbiAgICAgIGAgQWN0dWFsIHByb3BlcnRpZXM6ICR7SlNPTi5zdHJpbmdpZnkoYWN0dWFsUHJvcHNBbmRWYWx1ZXMpfWAsXG4gICAgKTtcblxuICByZXR1cm4geyBwYXNzLCBtZXNzYWdlIH07XG59KTtcblxuLyoqXG4gKiBIaWRkZW4gZWxlbWVudHMgYXJlIGVsZW1lbnRzIHRoYXQgaGF2ZTpcbiAqIDEuIERpc3BsYXkgb3IgdmlzaWJpbGl0eSBzdHlsZSBwcm9wZXJ0aWVzIHNldCB0byBcIm5vbmVcIiBvciBcImhpZGRlblwiXG4gKiAyLiBEaXNwbGF5IG9yIHZpc2liaWxpdHkgY29tcHV0ZWQgc3R5bGVzIHNldCB0byBcIm5vbmVcIiBvciBcImhpZGRlblwiXG4gKiAzLiBXaWR0aCBhbmQgaGVpZ2h0IHNldCB0byAwIChjaGVjayBub3QgYXBwbGllZCBpbiBqZXN0KVxuICogNC4gQSBoaWRkZW4gcGFyZW50IGVsZW1lbnQgKHRoaXMgYWxzbyBoaWRlcyBjaGlsZCBlbGVtZW50cylcbiAqIDUuIFR5cGUgZXF1YWwgdG8gXCJoaWRkZW5cIiAob25seSBmb3IgZm9ybSBlbGVtZW50cylcbiAqIDYuIEEgXCJoaWRkZW5cIiBhdHRyaWJ1dGVcbiAqL1xuZnVuY3Rpb24gaXNIaWRkZW4oZWxPclNlbGVjdG9yOiBIVE1MRWxlbWVudCB8IHN0cmluZyk6IGJvb2xlYW4ge1xuICBsZXQgZWwgPSAkKGVsT3JTZWxlY3RvcilbMF07XG5cbiAgaWYgKCFlbCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgY29uc3QgaGlkZGVuV2hlbiA9IFtcbiAgICAoZWwpID0+ICEoZWwub2Zmc2V0V2lkdGggfHwgZWwub2Zmc2V0SGVpZ2h0IHx8IGVsLmdldENsaWVudFJlY3RzKCkubGVuZ3RoKSxcbiAgICAoZWwpID0+IGVsLnN0eWxlLmRpc3BsYXkgPT09ICdub25lJyB8fCB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlbCkuZ2V0UHJvcGVydHlWYWx1ZT8uKCdkaXNwbGF5JykgPT09ICdub25lJyxcbiAgICAoZWwpID0+IGVsLnN0eWxlLnZpc2liaWxpdHkgPT09ICdoaWRkZW4nIHx8IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGVsKS5nZXRQcm9wZXJ0eVZhbHVlPy4oJ3Zpc2liaWxpdHknKSA9PT0gJ2hpZGRlbicsXG4gICAgKGVsKSA9PiBlbC50eXBlID09PSAnaGlkZGVuJyxcbiAgICAoZWwpID0+IGVsLmhhc0F0dHJpYnV0ZSgnaGlkZGVuJyksXG4gIF07XG5cbiAgaWYgKGlzUnVubmluZ0luSnNEb20oKSkge1xuICAgIC8vIFdoZW4gcnVubmluZyBpbiBKU0RPTSAoSmVzdCksIG9mZnNldC1wcm9wZXJ0aWVzIGFuZCBjbGllbnQgcmVjdHMgYXJlIGFsd2F5cyByZXBvcnRlZCBhcyAwXG4gICAgLy8gLSBoZW5jZSwgbGV0J3MgdGFrZSBhIG1vcmUgXCJuYWl2ZVwiIGFwcHJvYWNoIGhlcmUuIChodHRwczovL2dpdGh1Yi5jb20vanNkb20vanNkb20vaXNzdWVzLzEzNSlcbiAgICBoaWRkZW5XaGVuLnNoaWZ0KCk7XG4gIH1cblxuICB3aGlsZSAoZWwpIHtcbiAgICBpZiAoZWwgPT09IGRvY3VtZW50KSB7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoZWwubm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFICYmIGhpZGRlbldoZW4uc29tZSgocnVsZSkgPT4gcnVsZShlbCkpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBlbCA9IGVsLnBhcmVudE5vZGUgfHwgZWwuaG9zdDtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBIaWRkZW4gZWxlbWVudHMgYXJlIGVsZW1lbnRzIHRoYXQgaGF2ZTpcbiAqIDEuIERpc3BsYXkgb3IgdmlzaWJpbGl0eSBzdHlsZSBwcm9wZXJ0aWVzIHNldCB0byBcIm5vbmVcIiBvciBcImhpZGRlblwiXG4gKiAyLiBEaXNwbGF5IG9yIHZpc2liaWxpdHkgY29tcHV0ZWQgc3R5bGVzIHNldCB0byBcIm5vbmVcIiBvciBcImhpZGRlblwiXG4gKiAzLiBXaWR0aCBhbmQgaGVpZ2h0IHNldCB0byAwIChjaGVjayBub3QgYXBwbGllZCBpbiBqZXN0KVxuICogNC4gQSBoaWRkZW4gcGFyZW50IGVsZW1lbnQgKHRoaXMgYWxzbyBoaWRlcyBjaGlsZCBlbGVtZW50cylcbiAqIDUuIFR5cGUgZXF1YWwgdG8gXCJoaWRkZW5cIiAob25seSBmb3IgZm9ybSBlbGVtZW50cylcbiAqIDYuIEEgXCJoaWRkZW5cIiBhdHRyaWJ1dGVcbiAqXG4gKiBleHBlY3QoJ2RpdicpLnRvQmVIaWRkZW4oKTtcbiAqXG4gKi9cbmV4cG9ydCBjb25zdCB0b0JlSGlkZGVuID0gY29tcGFyYXRvcigoZWwpID0+IHtcbiAgY29uc3QgcGFzcyA9IGlzSGlkZGVuKGVsKTtcbiAgY29uc3QgbWVzc2FnZSA9ICgpID0+IGBFeHBlY3RlZCBlbGVtZW50JHtwYXNzID8gJyBub3QnIDogJyd9IHRvIGJlIGhpZGRlbmA7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbi8qKlxuICogVGhlIDpzZWxlY3RlZCBzZWxlY3RvciBzZWxlY3RzIG9wdGlvbiBlbGVtZW50cyB0aGF0IGFyZSBwcmUtc2VsZWN0ZWQuXG4gKlxuICogZXhwZWN0KCdkaXYnKS50b0JlU2VsZWN0ZWQoKTtcbiAqXG4gKi9cbmV4cG9ydCBjb25zdCB0b0JlU2VsZWN0ZWQgPSBjb21wYXJhdG9yKChlbCkgPT4ge1xuICBjb25zdCBwYXNzID0gJChlbCkuaXMoJzpzZWxlY3RlZCcpO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gYmUgc2VsZWN0ZWRgO1xuXG4gIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbn0pO1xuXG4vKipcbiAqIEhpZGRlbiBlbGVtZW50cyBhcmUgZWxlbWVudHMgdGhhdCBoYXZlOlxuICogMS4gRGlzcGxheSBwcm9wZXJ0eSBzZXQgdG8gXCJub25lXCJcbiAqIDIuIFdpZHRoIGFuZCBoZWlnaHQgc2V0IHRvIDBcbiAqIDMuIEEgaGlkZGVuIHBhcmVudCBlbGVtZW50ICh0aGlzIGFsc28gaGlkZXMgY2hpbGQgZWxlbWVudHMpXG4gKiA0LiBUeXBlIGVxdWFsIHRvIFwiaGlkZGVuXCIgKG9ubHkgZm9yIGZvcm0gZWxlbWVudHMpXG4gKiA1LiBBIFwiaGlkZGVuXCIgYXR0cmlidXRlXG4gKlxuICogZXhwZWN0KCdkaXYnKS50b0JlVmlzaWJsZSgpO1xuICpcbiAqL1xuZXhwb3J0IGNvbnN0IHRvQmVWaXNpYmxlID0gY29tcGFyYXRvcigoZWwpID0+IHtcbiAgY29uc3QgcGFzcyA9ICFpc0hpZGRlbihlbCk7XG5cbiAgY29uc3QgbWVzc2FnZSA9ICgpID0+IGBFeHBlY3RlZCBlbGVtZW50JHtwYXNzID8gJyBub3QnIDogJyd9IHRvIGJlIHZpc2libGVgO1xuXG4gIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbn0pO1xuXG4vKipcbiAqIFRoZSA6Zm9jdXMgc2VsZWN0b3Igc2VsZWN0cyB0aGUgZWxlbWVudCB0aGF0IGN1cnJlbnRseSBoYXMgZm9jdXMuXG4gKlxuICogZXhwZWN0KCdpbnB1dCcpLnRvQmVGb2N1c2VkKCk7XG4gKi9cbmV4cG9ydCBjb25zdCB0b0JlRm9jdXNlZCA9IGNvbXBhcmF0b3IoKGVsKSA9PiB7XG4gIGNvbnN0IGVsZW1lbnQgPSAkKGVsKS5nZXQoMCk7XG4gIGNvbnN0IHBhc3MgPSBlbGVtZW50ID09PSBlbGVtZW50Lm93bmVyRG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcbiAgY29uc3QgbWVzc2FnZSA9ICgpID0+IGBFeHBlY3RlZCBlbGVtZW50JHtwYXNzID8gJyBub3QnIDogJyd9IHRvIGJlIGZvY3VzZWRgO1xuXG4gIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbn0pO1xuXG4vKipcbiAqIENoZWNrIHRvIHNlZSBpZiB0aGUgc2V0IG9mIG1hdGNoZWQgZWxlbWVudHMgbWF0Y2hlcyB0aGUgZ2l2ZW4gc2VsZWN0b3JcbiAqIHJldHVybnMgdHJ1ZSBpZiB0aGUgZG9tIGNvbnRhaW5zIHRoZSBlbGVtZW50XG4gKlxuICogZXhwZWN0KCdkaXYnKS50b0JlTWF0Y2hlZEJ5KCcuanMtc29tZXRoaW5nJylcbiAqL1xuZXhwb3J0IGNvbnN0IHRvQmVNYXRjaGVkQnkgPSBjb21wYXJhdG9yKChlbCwgZXhwZWN0ZWQpID0+IHtcbiAgY29uc3QgYWN0dWFsID0gJChlbCkuZmlsdGVyKGV4cGVjdGVkKS5sZW5ndGg7XG4gIGNvbnN0IHBhc3MgPSBhY3R1YWwgPiAwO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gYmUgbWF0Y2hlZCBieSAnJHtleHBlY3RlZH0nYDtcblxuICByZXR1cm4geyBwYXNzLCBtZXNzYWdlIH07XG59KTtcblxuLyoqXG4gKlxuICogZXhwZWN0KCdkaXYnKS50b0hhdmVEZXNjZW5kYW50KCcuY2hpbGQnKVxuICovXG5leHBvcnQgY29uc3QgdG9IYXZlRGVzY2VuZGFudCA9IGNvbXBhcmF0b3IoKGVsLCBzZWxlY3RvcikgPT4ge1xuICBjb25zdCBhY3R1YWwgPSAkKGVsKS5maW5kKHNlbGVjdG9yKS5sZW5ndGg7XG4gIGNvbnN0IHBhc3MgPSBhY3R1YWwgPiAwO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gY29udGFpbiBjaGlsZCAnJHtzZWxlY3Rvcn0nYDtcblxuICByZXR1cm4geyBwYXNzLCBtZXNzYWdlIH07XG59KTtcblxuLyoqXG4gKlxuICogZXhwZWN0KCdkaXYnKS50b0hhdmVEZXNjZW5kYW50V2l0aFRleHQoe3NlbGVjdG9yOiAnLmNoaWxkJywgdGV4dDogJ3RleHQnfSlcbiAqL1xuZXhwb3J0IGNvbnN0IHRvSGF2ZURlc2NlbmRhbnRXaXRoVGV4dCA9IGNvbXBhcmF0b3IoKGVsLCB7IHNlbGVjdG9yLCB0ZXh0IH0pID0+IHtcbiAgY29uc3QgYWN0dWFsID0gJC50cmltKCQoZWwpLmZpbmQoc2VsZWN0b3IpLnRleHQoKSk7XG4gIGlmICh0ZXh0ICYmICQuaXNGdW5jdGlvbih0ZXh0LnRlc3QpKSB7XG4gICAgY29uc3QgcGFzcyA9IHRleHQudGVzdChhY3R1YWwpO1xuICAgIGNvbnN0IG1lc3NhZ2UgPSAoKSA9PlxuICAgICAgYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSBkZXNjZW5kYW50ICcke3NlbGVjdG9yfScgd2l0aCB0ZXh0IG1hdGNoaW5nICcke3RleHR9JyxgICsgYCBidXQgaGFkICcke2FjdHVhbH0nYDtcblxuICAgIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbiAgfVxuICBjb25zdCBwYXNzID0gYWN0dWFsLmluZGV4T2YodGV4dCkgIT09IC0xO1xuICBjb25zdCBtZXNzYWdlID0gKCkgPT4gYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSBkZXNjZW5kYW50ICcke3NlbGVjdG9yfScgd2l0aCB0ZXh0ICcke3RleHR9JywgYnV0IGhhZCAnJHthY3R1YWx9J2A7XG5cbiAgcmV0dXJuIHsgcGFzcywgbWVzc2FnZSB9O1xufSk7XG5cbmV4cG9ydCBjb25zdCB0b0hhdmVTZWxlY3RlZE9wdGlvbnMgPSBjb21wYXJhdG9yKChlbCwgZXhwZWN0ZWQpID0+IHtcbiAgaWYgKGV4cGVjdGVkIGluc3RhbmNlb2YgSFRNTE9wdGlvbkVsZW1lbnQpIHtcbiAgICBjb25zdCBhY3R1YWwgPSAkKGVsKS5maW5kKCc6c2VsZWN0ZWQnKTtcblxuICAgIGNvbnN0IHBhc3MgPSBhY3R1YWwuaXMoJChleHBlY3RlZCkpO1xuXG4gICAgY29uc3QgbWVzc2FnZSA9ICgpID0+XG4gICAgICBgRXhwZWN0ZWQgZWxlbWVudCR7cGFzcyA/ICcgbm90JyA6ICcnfSB0byBoYXZlIG9wdGlvbnMgJ1ske2V4cGVjdGVkLm91dGVySFRNTH1dJyBidXQgaGFkICdbJHthY3R1YWxbMF0ub3V0ZXJIVE1MfV0nYDtcblxuICAgIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbiAgfVxuXG4gIGlmIChpc0hUTUxPcHRpb25FbGVtZW50QXJyYXkoZXhwZWN0ZWQpKSB7XG4gICAgY29uc3QgYWN0dWFsID0gJChlbCkuZmluZCgnOnNlbGVjdGVkJyk7XG5cbiAgICBjb25zdCBwYXNzID0gYWN0dWFsLmxlbmd0aCA9PT0gZXhwZWN0ZWQubGVuZ3RoICYmIGFjdHVhbC50b0FycmF5KCkuZXZlcnkoKF8sIGluZGV4KSA9PiAkKGFjdHVhbFtpbmRleF0pLmlzKGV4cGVjdGVkW2luZGV4XSkpO1xuXG4gICAgY29uc3QgZXhwZWN0ZWRPcHRpb25zU3RyaW5nID0gJChleHBlY3RlZClcbiAgICAgIC5nZXQoKVxuICAgICAgLm1hcCgob3B0aW9uKSA9PiBvcHRpb24ub3V0ZXJIVE1MKVxuICAgICAgLmpvaW4oJywnKTtcblxuICAgIGNvbnN0IGFjdHVhbE9wdGlvbnNTdHJpbmcgPSBhY3R1YWxcbiAgICAgIC5nZXQoKVxuICAgICAgLm1hcCgob3B0aW9uKSA9PiBvcHRpb24ub3V0ZXJIVE1MKVxuICAgICAgLmpvaW4oJywnKTtcblxuICAgIGNvbnN0IG1lc3NhZ2UgPSAoKSA9PlxuICAgICAgYEV4cGVjdGVkIGVsZW1lbnQke3Bhc3MgPyAnIG5vdCcgOiAnJ30gdG8gaGF2ZSBvcHRpb25zICdbJHtleHBlY3RlZE9wdGlvbnNTdHJpbmd9XScgYnV0IGhhZCAnWyR7YWN0dWFsT3B0aW9uc1N0cmluZ31dJ2A7XG5cbiAgICByZXR1cm4geyBwYXNzLCBtZXNzYWdlIH07XG4gIH1cblxuICBjb25zdCBhY3R1YWw6IHN0cmluZ1tdID0gJChlbCkudmFsKCk7XG5cbiAgY29uc3QgcGFzcyA9IGNvZXJjZUFycmF5KGV4cGVjdGVkKT8uZXZlcnkoKHYpID0+IGFjdHVhbC5pbmNsdWRlcyh2KSk7XG5cbiAgY29uc3QgZXhwZWN0ZWRPcHRpb25zU3RyaW5nID0gQXJyYXkuaXNBcnJheShleHBlY3RlZClcbiAgICA/IGV4cGVjdGVkLnJlZHVjZSgoYWNjOiBzdHJpbmcsIHZhbDogc3RyaW5nLCBpKSA9PiBhY2MgKyBgJHtpID09PSBleHBlY3RlZC5sZW5ndGggPyAnJyA6ICcsJ30ke3ZhbH1gKVxuICAgIDogZXhwZWN0ZWQ7XG4gIGNvbnN0IG1lc3NhZ2UgPSAoKSA9PiBgRXhwZWN0ZWQgZWxlbWVudCR7cGFzcyA/ICcgbm90JyA6ICcnfSB0byBoYXZlIG9wdGlvbnMgJ1ske2V4cGVjdGVkT3B0aW9uc1N0cmluZ31dJyBidXQgaGFkICdbJHthY3R1YWx9XSdgO1xuXG4gIHJldHVybiB7IHBhc3MsIG1lc3NhZ2UgfTtcbn0pO1xuIl19