UNPKG

45.7 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.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;
4const have_resource_1 = require("./have-resource");
5/**
6 * A matcher for an object that contains at least the given fields with the given matchers (or literals)
7 *
8 * Only does lenient matching one level deep, at the next level all objects must declare the
9 * exact expected keys again.
10 */
11function objectLike(pattern) {
12 return _objectContaining(pattern, false);
13}
14exports.objectLike = objectLike;
15/**
16 * A matcher for an object that contains at least the given fields with the given matchers (or literals)
17 *
18 * Switches to "deep" lenient matching. Nested objects also only need to contain declared keys.
19 */
20function deepObjectLike(pattern) {
21 return _objectContaining(pattern, true);
22}
23exports.deepObjectLike = deepObjectLike;
24function _objectContaining(pattern, deep) {
25 const anno = { [deep ? '$deepObjectLike' : '$objectLike']: pattern };
26 return annotateMatcher(anno, (value, inspection) => {
27 if (typeof value !== 'object' || !value) {
28 return failMatcher(inspection, `Expect an object but got '${typeof value}'`);
29 }
30 const errors = new Array();
31 for (const [patternKey, patternValue] of Object.entries(pattern)) {
32 if (patternValue === have_resource_1.ABSENT) {
33 if (value[patternKey] !== undefined) {
34 errors.push(`Field ${patternKey} present, but shouldn't be`);
35 }
36 continue;
37 }
38 if (!(patternKey in value)) {
39 errors.push(`Field ${patternKey} missing`);
40 continue;
41 }
42 // If we are doing DEEP objectLike, translate object literals in the pattern into
43 // more `deepObjectLike` matchers, even if they occur in lists.
44 const matchValue = deep ? deepMatcherFromObjectLiteral(patternValue) : patternValue;
45 const innerInspection = { ...inspection, failureReason: '' };
46 const valueMatches = match(value[patternKey], matchValue, innerInspection);
47 if (!valueMatches) {
48 errors.push(`Field ${patternKey} mismatch: ${innerInspection.failureReason}`);
49 }
50 }
51 /**
52 * Transform nested object literals into more deep object matchers, if applicable
53 *
54 * Object literals in lists are also transformed.
55 */
56 function deepMatcherFromObjectLiteral(nestedPattern) {
57 if (isObject(nestedPattern)) {
58 return deepObjectLike(nestedPattern);
59 }
60 if (Array.isArray(nestedPattern)) {
61 return nestedPattern.map(deepMatcherFromObjectLiteral);
62 }
63 return nestedPattern;
64 }
65 if (errors.length > 0) {
66 return failMatcher(inspection, errors.join(', '));
67 }
68 return true;
69 });
70}
71/**
72 * Match exactly the given value
73 *
74 * This is the default, you only need this to escape from the deep lenient matching
75 * of `deepObjectLike`.
76 */
77function exactValue(expected) {
78 const anno = { $exactValue: expected };
79 return annotateMatcher(anno, (value, inspection) => {
80 return matchLiteral(value, expected, inspection);
81 });
82}
83exports.exactValue = exactValue;
84/**
85 * A matcher for a list that contains all of the given elements in any order
86 */
87function arrayWith(...elements) {
88 if (elements.length === 0) {
89 return anything();
90 }
91 const anno = { $arrayContaining: elements.length === 1 ? elements[0] : elements };
92 return annotateMatcher(anno, (value, inspection) => {
93 if (!Array.isArray(value)) {
94 return failMatcher(inspection, `Expect an array but got '${typeof value}'`);
95 }
96 for (const element of elements) {
97 const failure = longestFailure(value, element);
98 if (failure) {
99 return failMatcher(inspection, `Array did not contain expected element, closest match at index ${failure[0]}: ${failure[1]}`);
100 }
101 }
102 return true;
103 /**
104 * Return 'null' if the matcher matches anywhere in the array, otherwise the longest error and its index
105 */
106 function longestFailure(array, matcher) {
107 let fail = null;
108 for (let i = 0; i < array.length; i++) {
109 const innerInspection = { ...inspection, failureReason: '' };
110 if (match(array[i], matcher, innerInspection)) {
111 return null;
112 }
113 if (fail === null || innerInspection.failureReason.length > fail[1].length) {
114 fail = [i, innerInspection.failureReason];
115 }
116 }
117 return fail;
118 }
119 });
120}
121exports.arrayWith = arrayWith;
122/**
123 * Whether a value is an object
124 */
125function isObject(x) {
126 // Because `typeof null === 'object'`.
127 return x && typeof x === 'object';
128}
129/**
130 * Helper function to make matcher failure reporting a little easier
131 *
132 * Our protocol is weird (change a string on a passed-in object and return 'false'),
133 * but I don't want to change that right now.
134 */
135function failMatcher(inspection, error) {
136 inspection.failureReason = error;
137 return false;
138}
139exports.failMatcher = failMatcher;
140/**
141 * Match a given literal value against a matcher
142 *
143 * If the matcher is a callable, use that to evaluate the value. Otherwise, the values
144 * must be literally the same.
145 */
146function match(value, matcher, inspection) {
147 if (isCallable(matcher)) {
148 // Custom matcher (this mostly looks very weird because our `InspectionFailure` signature is weird)
149 const innerInspection = { ...inspection, failureReason: '' };
150 const result = matcher(value, innerInspection);
151 if (typeof result !== 'boolean') {
152 return failMatcher(inspection, `Predicate returned non-boolean return value: ${result}`);
153 }
154 if (!result && !innerInspection.failureReason) {
155 // Custom matcher neglected to return an error
156 return failMatcher(inspection, 'Predicate returned false');
157 }
158 // Propagate inner error in case of failure
159 if (!result) {
160 inspection.failureReason = innerInspection.failureReason;
161 }
162 return result;
163 }
164 return matchLiteral(value, matcher, inspection);
165}
166exports.match = match;
167/**
168 * Match a literal value at the top level.
169 *
170 * When recursing into arrays or objects, the nested values can be either matchers
171 * or literals.
172 */
173function matchLiteral(value, pattern, inspection) {
174 if (pattern == null) {
175 return true;
176 }
177 const errors = new Array();
178 if (Array.isArray(value) !== Array.isArray(pattern)) {
179 return failMatcher(inspection, 'Array type mismatch');
180 }
181 if (Array.isArray(value)) {
182 if (pattern.length !== value.length) {
183 return failMatcher(inspection, 'Array length mismatch');
184 }
185 // Recurse comparison for individual objects
186 for (let i = 0; i < pattern.length; i++) {
187 if (!match(value[i], pattern[i], { ...inspection })) {
188 errors.push(`Array element ${i} mismatch`);
189 }
190 }
191 if (errors.length > 0) {
192 return failMatcher(inspection, errors.join(', '));
193 }
194 return true;
195 }
196 if ((typeof value === 'object') !== (typeof pattern === 'object')) {
197 return failMatcher(inspection, 'Object type mismatch');
198 }
199 if (typeof pattern === 'object') {
200 // Check that all fields in the pattern have the right value
201 const innerInspection = { ...inspection, failureReason: '' };
202 const matcher = objectLike(pattern)(value, innerInspection);
203 if (!matcher) {
204 inspection.failureReason = innerInspection.failureReason;
205 return false;
206 }
207 // Check no fields uncovered
208 const realFields = new Set(Object.keys(value));
209 for (const key of Object.keys(pattern)) {
210 realFields.delete(key);
211 }
212 if (realFields.size > 0) {
213 return failMatcher(inspection, `Unexpected keys present in object: ${Array.from(realFields).join(', ')}`);
214 }
215 return true;
216 }
217 if (value !== pattern) {
218 return failMatcher(inspection, 'Different values');
219 }
220 return true;
221}
222/**
223 * Whether a value is a callable
224 */
225function isCallable(x) {
226 return x && {}.toString.call(x) === '[object Function]';
227}
228/**
229 * Do a glob-like pattern match (which only supports *s). Supports multiline strings.
230 */
231function stringLike(pattern) {
232 // Replace * with .* in the string, escape the rest and brace with ^...$
233 const regex = new RegExp(`^${pattern.split('*').map(escapeRegex).join('.*')}$`, 'm');
234 return annotateMatcher({ $stringContaining: pattern }, (value, failure) => {
235 if (typeof value !== 'string') {
236 failure.failureReason = `Expected a string, but got '${typeof value}'`;
237 return false;
238 }
239 if (!regex.test(value)) {
240 failure.failureReason = 'String did not match pattern';
241 return false;
242 }
243 return true;
244 });
245}
246exports.stringLike = stringLike;
247/**
248 * Matches any value
249 */
250function anything() {
251 return annotateMatcher({ $anything: true }, () => true);
252}
253exports.anything = anything;
254/**
255 * Negate an inner matcher
256 */
257function notMatching(matcher) {
258 return annotateMatcher({ $notMatching: matcher }, (value, failure) => {
259 const result = matcherFrom(matcher)(value, failure);
260 if (result) {
261 failure.failureReason = 'Should not have matched, but did';
262 return false;
263 }
264 return true;
265 });
266}
267exports.notMatching = notMatching;
268/**
269 * Captures a value onto an object if it matches a given inner matcher
270 *
271 * @example
272 *
273 * const someValue = Capture.aString();
274 * expect(stack).toHaveResource({
275 * // ...
276 * Value: someValue.capture(stringMatching('*a*')),
277 * });
278 * console.log(someValue.capturedValue);
279 */
280class Capture {
281 constructor(typeValidator) {
282 this.typeValidator = typeValidator;
283 this._didCapture = false;
284 this._wasInvoked = false;
285 }
286 /**
287 * A Capture object that captures any type
288 */
289 static anyType() {
290 return new Capture();
291 }
292 /**
293 * A Capture object that captures a string type
294 */
295 static aString() {
296 return new Capture((x) => {
297 if (typeof x !== 'string') {
298 throw new Error(`Expected to capture a string, got '${x}'`);
299 }
300 return true;
301 });
302 }
303 /**
304 * A Capture object that captures a custom type
305 */
306 // eslint-disable-next-line @typescript-eslint/no-shadow
307 static a(validator) {
308 return new Capture(validator);
309 }
310 /**
311 * Capture the value if the inner matcher successfully matches it
312 *
313 * If no matcher is given, `anything()` is assumed.
314 *
315 * And exception will be thrown if the inner matcher returns `true` and
316 * the value turns out to be of a different type than the `Capture` object
317 * is expecting.
318 */
319 capture(matcher) {
320 if (matcher === undefined) {
321 matcher = anything();
322 }
323 return annotateMatcher({ $capture: matcher }, (value, failure) => {
324 this._wasInvoked = true;
325 const result = matcherFrom(matcher)(value, failure);
326 if (result) {
327 if (this.typeValidator && !this.typeValidator(value)) {
328 throw new Error(`Value not of the expected type: ${value}`);
329 }
330 this._didCapture = true;
331 this._value = value;
332 }
333 return result;
334 });
335 }
336 /**
337 * Whether a value was successfully captured
338 */
339 get didCapture() {
340 return this._didCapture;
341 }
342 /**
343 * Return the value that was captured
344 *
345 * Throws an exception if now value was captured
346 */
347 get capturedValue() {
348 // When this module is ported to jsii, the type parameter will obviously
349 // have to be dropped and this will have to turn into an `any`.
350 if (!this.didCapture) {
351 throw new Error(`Did not capture a value: ${this._wasInvoked ? 'inner matcher failed' : 'never invoked'}`);
352 }
353 return this._value;
354 }
355}
356exports.Capture = Capture;
357/**
358 * Match on the innards of a JSON string, instead of the complete string
359 */
360function encodedJson(matcher) {
361 return annotateMatcher({ $encodedJson: matcher }, (value, failure) => {
362 if (typeof value !== 'string') {
363 failure.failureReason = `Expected a string, but got '${typeof value}'`;
364 return false;
365 }
366 let decoded;
367 try {
368 decoded = JSON.parse(value);
369 }
370 catch (e) {
371 failure.failureReason = `String is not JSON: ${e}`;
372 return false;
373 }
374 return matcherFrom(matcher)(decoded, failure);
375 });
376}
377exports.encodedJson = encodedJson;
378function escapeRegex(s) {
379 return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
380}
381/**
382 * Make a matcher out of the given argument if it's not a matcher already
383 *
384 * If it's not a matcher, it will be treated as a literal.
385 */
386function matcherFrom(matcher) {
387 return isCallable(matcher) ? matcher : exactValue(matcher);
388}
389exports.matcherFrom = matcherFrom;
390/**
391 * Annotate a matcher with toJSON
392 *
393 * We will JSON.stringify() values if we have a match failure, but for matchers this
394 * would show (in traditional JS fashion) something like '[function Function]', or more
395 * accurately nothing at all since functions cannot be JSONified.
396 *
397 * We override to JSON() in order to produce a readadable version of the matcher.
398 */
399function annotateMatcher(how, matcher) {
400 matcher.toJSON = () => how;
401 return matcher;
402}
403exports.annotateMatcher = annotateMatcher;
404//# 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/ICdpbm5lciBtYXRjaGVyIGZhaWxlZCcgOiAnbmV2ZXIgaW52b2tlZCd9YCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl92YWx1ZSE7XG4gIH1cbn1cblxuLyoqXG4gKiBNYXRjaCBvbiB0aGUgaW5uYXJkcyBvZiBhIEpTT04gc3RyaW5nLCBpbnN0ZWFkIG9mIHRoZSBjb21wbGV0ZSBzdHJpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZWRKc29uKG1hdGNoZXI6IGFueSk6IFByb3BlcnR5TWF0Y2hlciB7XG4gIHJldHVybiBhbm5vdGF0ZU1hdGNoZXIoeyAkZW5jb2RlZEpzb246IG1hdGNoZXIgfSwgKHZhbHVlOiBhbnksIGZhaWx1cmU6IEluc3BlY3Rpb25GYWlsdXJlKSA9PiB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIGZhaWx1cmUuZmFpbHVyZVJlYXNvbiA9IGBFeHBlY3RlZCBhIHN0cmluZywgYnV0IGdvdCAnJHt0eXBlb2YgdmFsdWV9J2A7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgbGV0IGRlY29kZWQ7XG4gICAgdHJ5IHtcbiAgICAgIGRlY29kZWQgPSBKU09OLnBhcnNlKHZhbHVlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBmYWlsdXJlLmZhaWx1cmVSZWFzb24gPSBgU3RyaW5nIGlzIG5vdCBKU09OOiAke2V9YDtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWF0Y2hlckZyb20obWF0Y2hlcikoZGVjb2RlZCwgZmFpbHVyZSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBlc2NhcGVSZWdleChzOiBzdHJpbmcpIHtcbiAgcmV0dXJuIHMucmVwbGFjZSgvWy4qKz9eJHt9KCl8W1xcXVxcXFxdL2csICdcXFxcJCYnKTsgLy8gJCYgbWVhbnMgdGhlIHdob2xlIG1hdGNoZWQgc3RyaW5nXG59XG5cbi8qKlxuICogTWFrZSBhIG1hdGNoZXIgb3V0IG9mIHRoZSBnaXZlbiBhcmd1bWVudCBpZiBpdCdzIG5vdCBhIG1hdGNoZXIgYWxyZWFkeVxuICpcbiAqIElmIGl0J3Mgbm90IGEgbWF0Y2hlciwgaXQgd2lsbCBiZSB0cmVhdGVkIGFzIGEgbGl0ZXJhbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1hdGNoZXJGcm9tKG1hdGNoZXI6IGFueSk6IFByb3BlcnR5TWF0Y2hlciB7XG4gIHJldHVybiBpc0NhbGxhYmxlKG1hdGNoZXIpID8gbWF0Y2hlciA6IGV4YWN0VmFsdWUobWF0Y2hlcik7XG59XG5cbi8qKlxuICogQW5ub3RhdGUgYSBtYXRjaGVyIHdpdGggdG9KU09OXG4gKlxuICogV2Ugd2lsbCBKU09OLnN0cmluZ2lmeSgpIHZhbHVlcyBpZiB3ZSBoYXZlIGEgbWF0Y2ggZmFpbHVyZSwgYnV0IGZvciBtYXRjaGVycyB0aGlzXG4gKiB3b3VsZCBzaG93IChpbiB0cmFkaXRpb25hbCBKUyBmYXNoaW9uKSBzb21ldGhpbmcgbGlrZSAnW2Z1bmN0aW9uIEZ1bmN0aW9uXScsIG9yIG1vcmVcbiAqIGFjY3VyYXRlbHkgbm90aGluZyBhdCBhbGwgc2luY2UgZnVuY3Rpb25zIGNhbm5vdCBiZSBKU09OaWZpZWQuXG4gKlxuICogV2Ugb3ZlcnJpZGUgdG8gSlNPTigpIGluIG9yZGVyIHRvIHByb2R1Y2UgYSByZWFkYWRhYmxlIHZlcnNpb24gb2YgdGhlIG1hdGNoZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhbm5vdGF0ZU1hdGNoZXI8QSBleHRlbmRzIG9iamVjdD4oaG93OiBBLCBtYXRjaGVyOiBQcm9wZXJ0eU1hdGNoZXIpOiBQcm9wZXJ0eU1hdGNoZXIge1xuICAobWF0Y2hlciBhcyBhbnkpLnRvSlNPTiA9ICgpID0+IGhvdztcbiAgcmV0dXJuIG1hdGNoZXI7XG59XG4iXX0=
\No newline at end of file