UNPKG

@loona/angular

Version:

App State Management done with GraphQL (angular integration)

692 lines (677 loc) 66 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('rxjs'), require('apollo-angular'), require('rxjs/operators'), require('@loona/core'), require('apollo-cache')) : typeof define === 'function' && define.amd ? define('@loona/angular', ['exports', '@angular/core', 'rxjs', 'apollo-angular', 'rxjs/operators', '@loona/core', 'apollo-cache'], factory) : (factory((global.loona = global.loona || {}, global.loona.angular = {}),global.ng.core,global.rxjs,global.apollo.core,global.rxjs.operators,global.loona.core,global.apollo.cache.core)); }(this, (function (exports,core,rxjs,apolloAngular,operators,core$1,apolloCache) { 'use strict'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ /* global Reflect, Promise */ var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function () { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spread() { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** @type {?} */ var INITIAL_STATE = new core.InjectionToken('Loona/State'); /** @type {?} */ var CHILD_STATE = new core.InjectionToken('Loona/ChildState'); /** @type {?} */ var LOONA_CACHE = new core.InjectionToken('Loona/Cache'); /** @type {?} */ var INIT = '@@init'; /** @type {?} */ var ROOT_EFFECTS_INIT = '@@effects/init'; /** @type {?} */ var UPDATE_EFFECTS = '@@effects/update'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * @template V */ var /** * @template V */ Actions = /** @class */ (function (_super) { __extends(Actions, _super); function Actions() { return _super !== null && _super.apply(this, arguments) || this; } return Actions; }(rxjs.Observable)); var ScannedActions = /** @class */ (function (_super) { __extends(ScannedActions, _super); function ScannedActions() { return _super !== null && _super.apply(this, arguments) || this; } /** * @return {?} */ ScannedActions.prototype.ngOnDestroy = /** * @return {?} */ function () { this.complete(); }; ScannedActions.decorators = [ { type: core.Injectable } ]; return ScannedActions; }(rxjs.Subject)); var InnerActions = /** @class */ (function (_super) { __extends(InnerActions, _super); function InnerActions() { return _super.call(this, { type: INIT }) || this; } /** * @param {?} action * @return {?} */ InnerActions.prototype.next = /** * @param {?} action * @return {?} */ function (action) { if (typeof action === 'undefined') { throw new TypeError("Actions must be objects"); } else if (typeof action.type === 'undefined') { throw new TypeError("Actions must have a type property"); } _super.prototype.next.call(this, action); }; /** * @return {?} */ InnerActions.prototype.complete = /** * @return {?} */ function () { }; /** * @return {?} */ InnerActions.prototype.ngOnDestroy = /** * @return {?} */ function () { _super.prototype.complete.call(this); }; InnerActions.decorators = [ { type: core.Injectable } ]; /** @nocollapse */ InnerActions.ctorParameters = function () { return []; }; return InnerActions; }(rxjs.BehaviorSubject)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var Loona = /** @class */ (function () { function Loona(apollo, manager, actions, scannedActions, errorHandler) { this.apollo = apollo; this.manager = manager; this.actions = actions; this.direct$ = new rxjs.Subject(); this.queue$ = rxjs.merge(actions, this.direct$).pipe(operators.observeOn(rxjs.queueScheduler)); this.queue$.subscribe({ next: function (action) { scannedActions.next(action); }, error: function (error) { errorHandler.handleError(error); }, }); } /** * @template T, V * @param {?} queryOrOptions * @param {?=} variables * @param {?=} options * @return {?} */ Loona.prototype.query = /** * @template T, V * @param {?} queryOrOptions * @param {?=} variables * @param {?=} options * @return {?} */ function (queryOrOptions, variables, options) { return this.apollo.watchQuery(core$1.isDocument(queryOrOptions) ? __assign({ query: queryOrOptions, variables: variables }, options) : queryOrOptions); }; /** * @template T, V * @param {?} mutationOrOptions * @param {?=} variables * @param {?=} options * @return {?} */ Loona.prototype.mutate = /** * @template T, V * @param {?} mutationOrOptions * @param {?=} variables * @param {?=} options * @return {?} */ function (mutationOrOptions, variables, options) { var _this = this; /** @type {?} */ var config = core$1.isDocument(mutationOrOptions) ? __assign({ mutation: mutationOrOptions, variables: variables }, options) : mutationOrOptions; return this.apollo .mutate(core$1.withUpdates(config, this.manager)) .pipe(operators.tap(function (result) { _this.direct$.next(core$1.buildActionFromResult(config, result)); }), operators.catchError(function (error) { _this.direct$.next(core$1.buildActionFromError(config, error)); return rxjs.throwError(error); })); }; /** * @param {?} action * @return {?} */ Loona.prototype.dispatch = /** * @param {?} action * @return {?} */ function (action) { if (core$1.isMutation(action)) { /** @type {?} */ var mutation = core$1.getMutation(action); this.mutate(__assign({ mutation: mutation }, action)).subscribe(); } else { this.actions.next(__assign({ type: core$1.getActionType(action) }, action)); } }; /** * @template T * @return {?} */ Loona.prototype.extract = /** * @template T * @return {?} */ function () { return this.apollo.getClient().extract(); }; /** * @return {?} */ Loona.prototype.reset = /** * @return {?} */ function () { this.apollo.getClient().resetStore(); }; /** * @param {?} state * @return {?} */ Loona.prototype.restore = /** * @param {?} state * @return {?} */ function (state) { this.apollo.getClient().restore(state); }; Loona.decorators = [ { type: core.Injectable } ]; /** @nocollapse */ Loona.ctorParameters = function () { return [ { type: apolloAngular.Apollo }, { type: core$1.Manager }, { type: InnerActions }, { type: ScannedActions }, { type: core.ErrorHandler } ]; }; return Loona; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var Effects = /** @class */ (function () { function Effects(loona, apollo, cache) { this.effects = {}; this.getContext = function () { return (__assign({}, core$1.buildContext({ cache: cache, getCacheKey: core$1.buildGetCacheKey(cache), }, apollo.getClient()), { dispatch: loona.dispatch.bind(loona) })); }; } /** * @param {?} instance * @param {?=} meta * @return {?} */ Effects.prototype.addEffects = /** * @param {?} instance * @param {?=} meta * @return {?} */ function (instance, meta) { var _this = this; if (!meta) { return; } var _loop_1 = function (type) { if (!this_1.effects[type]) { this_1.effects[type] = []; } meta[type].forEach(function (_a) { var propName = _a.propName; _this.effects[type].push(instance[propName].bind(instance)); }); }; var this_1 = this; for (var type in meta) { _loop_1(type); } }; /** * @param {?} action * @return {?} */ Effects.prototype.runEffects = /** * @param {?} action * @return {?} */ function (action) { var _this = this; /** @type {?} */ var type = action.type; if (core$1.isMutationAsAction(action)) { type = core$1.getNameOfMutation(action.options.mutation); } /** @type {?} */ var effectsToRun = this.effects[type]; if (effectsToRun) { effectsToRun.forEach(function (effect) { effect(action, _this.getContext()); }); } }; Effects.decorators = [ { type: core.Injectable } ]; /** @nocollapse */ Effects.ctorParameters = function () { return [ { type: Loona }, { type: apolloAngular.Apollo }, { type: apolloCache.ApolloCache, decorators: [{ type: core.Inject, args: [LOONA_CACHE,] }] } ]; }; return Effects; }()); var EffectsRunner = /** @class */ (function () { function EffectsRunner(effects, scannedActions) { this.effects = effects; this.scannedActions = scannedActions; this.actionsSubscription = null; } /** * @return {?} */ EffectsRunner.prototype.start = /** * @return {?} */ function () { var _this = this; if (!this.actionsSubscription) { this.actionsSubscription = this.scannedActions.subscribe(function (action) { _this.effects.runEffects(action); }); } }; /** * @return {?} */ EffectsRunner.prototype.ngOnDestroy = /** * @return {?} */ function () { if (this.actionsSubscription) { this.actionsSubscription.unsubscribe(); this.actionsSubscription = null; } }; EffectsRunner.decorators = [ { type: core.Injectable } ]; /** @nocollapse */ EffectsRunner.ctorParameters = function () { return [ { type: Effects }, { type: ScannedActions } ]; }; return EffectsRunner; }()); /** * @return {?} */ function mapStates() { /** @type {?} */ var names = []; /** @type {?} */ var add = function (state) { names.push(state.constructor && state.constructor.name); }; return { names: names, add: add }; } /** * @param {?} state * @param {?} injector * @return {?} */ function extractState(state, injector) { return { instance: injector.get(state), meta: state[core$1.METADATA_KEY], }; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * @template T * @param {?} val * @return {?} */ function isObservable(val) { return val instanceof rxjs.Observable; } /** * @param {?} resolver * @return {?} */ function handleObservable(resolver) { return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } /** @type {?} */ var result; try { result = resolver.apply(void 0, __spread(args)); } catch (e) { return Promise.reject(e); } return result instanceof Promise || isObservable(result) ? rxjs.from(result).toPromise() : Promise.resolve(result); }; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ var LoonaRootModule = /** @class */ (function () { function LoonaRootModule(effects, states, loona, manager, runner, injector) { var _this = this; this.effects = effects; runner.start(); var _a = mapStates(), names = _a.names, add = _a.add; states.forEach(function (state) { var _a = extractState(state, injector), instance = _a.instance, meta = _a.meta; manager.addState(instance, meta, handleObservable); _this.addEffects(instance, meta.effects); add(instance); }); loona.dispatch({ type: ROOT_EFFECTS_INIT, states: names, }); } /** * @param {?} state * @param {?=} meta * @return {?} */ LoonaRootModule.prototype.addEffects = /** * @param {?} state * @param {?=} meta * @return {?} */ function (state, meta) { this.effects.addEffects(state, meta); }; LoonaRootModule.decorators = [ { type: core.NgModule } ]; /** @nocollapse */ LoonaRootModule.ctorParameters = function () { return [ { type: Effects }, { type: Array, decorators: [{ type: core.Inject, args: [INITIAL_STATE,] }] }, { type: Loona }, { type: core$1.Manager }, { type: EffectsRunner }, { type: core.Injector } ]; }; return LoonaRootModule; }()); var LoonaChildModule = /** @class */ (function () { function LoonaChildModule(states, injector, manager, loona, rootModule) { var _a = mapStates(), names = _a.names, add = _a.add; states.forEach(function (state) { var _a = extractState(state, injector), instance = _a.instance, meta = _a.meta; manager.addState(instance, meta, handleObservable); rootModule.addEffects(instance, meta.effects); add(instance); }); loona.dispatch({ type: UPDATE_EFFECTS, states: names, }); } LoonaChildModule.decorators = [ { type: core.NgModule } ]; /** @nocollapse */ LoonaChildModule.ctorParameters = function () { return [ { type: Array, decorators: [{ type: core.Inject, args: [CHILD_STATE,] }] }, { type: core.Injector }, { type: core$1.Manager }, { type: Loona }, { type: LoonaRootModule } ]; }; return LoonaChildModule; }()); var LoonaModule = /** @class */ (function () { function LoonaModule() { } /** * @param {?=} states * @return {?} */ LoonaModule.forRoot = /** * @param {?=} states * @return {?} */ function (states) { if (states === void 0) { states = []; } return { ngModule: LoonaRootModule, providers: __spread([ Loona, InnerActions, ScannedActions, { provide: Actions, useExisting: ScannedActions, } ], states, [ { provide: INITIAL_STATE, useValue: states }, { provide: core$1.Manager, useFactory: managerFactory, deps: [LOONA_CACHE, core.Injector], }, { provide: core$1.LoonaLink, useFactory: linkFactory, deps: [core$1.Manager], }, Effects, EffectsRunner, ]), }; }; /** * @param {?=} states * @return {?} */ LoonaModule.forChild = /** * @param {?=} states * @return {?} */ function (states) { if (states === void 0) { states = []; } return { ngModule: LoonaChildModule, providers: __spread(states, [{ provide: CHILD_STATE, useValue: states }]), }; }; LoonaModule.decorators = [ { type: core.NgModule } ]; return LoonaModule; }()); /** * @param {?} manager * @return {?} */ function linkFactory(manager) { return new core$1.LoonaLink(manager); } /** * @param {?} cache * @param {?} injector * @return {?} */ function managerFactory(cache, injector) { /** @type {?} */ var manager = new core$1.Manager({ cache: cache, getClient: function () { return injector.get(apolloAngular.Apollo).getClient(); }, }); return manager; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ exports.Manager = core$1.Manager; exports.LoonaLink = core$1.LoonaLink; exports.State = core$1.State; exports.Mutation = core$1.Mutation; exports.Update = core$1.Update; exports.Resolve = core$1.Resolve; exports.Effect = core$1.Effect; exports.Actions = Actions; exports.Loona = Loona; exports.LoonaModule = LoonaModule; exports.INITIAL_STATE = INITIAL_STATE; exports.CHILD_STATE = CHILD_STATE; exports.LOONA_CACHE = LOONA_CACHE; exports.INIT = INIT; exports.UPDATE_EFFECTS = UPDATE_EFFECTS; exports.ROOT_EFFECTS_INIT = ROOT_EFFECTS_INIT; exports.ɵb = InnerActions; exports.ɵa = ScannedActions; exports.ɵg = Effects; exports.ɵh = EffectsRunner; exports.ɵd = LoonaChildModule; exports.ɵc = LoonaRootModule; exports.ɵe = linkFactory; exports.ɵf = managerFactory; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9vbmEuYW5ndWxhci51bWQuanMubWFwIiwic291cmNlcyI6WyIuLi8uLi9ub2RlX21vZHVsZXMvdHNsaWIvdHNsaWIuZXM2LmpzIiwibmc6Ly9AbG9vbmEvYW5ndWxhci90b2tlbnMudHMiLCJuZzovL0Bsb29uYS9hbmd1bGFyL2FjdGlvbnMudHMiLCJuZzovL0Bsb29uYS9hbmd1bGFyL2NsaWVudC50cyIsIm5nOi8vQGxvb25hL2FuZ3VsYXIvZWZmZWN0cy50cyIsIm5nOi8vQGxvb25hL2FuZ3VsYXIvdXRpbHMudHMiLCJuZzovL0Bsb29uYS9hbmd1bGFyL21vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZVxyXG50aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZVxyXG5MaWNlbnNlIGF0IGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxyXG5cclxuVEhJUyBDT0RFIElTIFBST1ZJREVEIE9OIEFOICpBUyBJUyogQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxyXG5LSU5ELCBFSVRIRVIgRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgV0lUSE9VVCBMSU1JVEFUSU9OIEFOWSBJTVBMSUVEXHJcbldBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBUSVRMRSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UsXHJcbk1FUkNIQU5UQUJMSVRZIE9SIE5PTi1JTkZSSU5HRU1FTlQuXHJcblxyXG5TZWUgdGhlIEFwYWNoZSBWZXJzaW9uIDIuMCBMaWNlbnNlIGZvciBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcclxuYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDApXHJcbiAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XHJcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcclxuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XHJcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wYXJhbShwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUocmVzdWx0LnZhbHVlKTsgfSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxyXG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19nZW5lcmF0b3IodGhpc0FyZywgYm9keSkge1xyXG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcclxuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XHJcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xyXG4gICAgICAgIHdoaWxlIChfKSB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XHJcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcclxuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xyXG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XHJcbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4cG9ydFN0YXIobSwgZXhwb3J0cykge1xyXG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAoIWV4cG9ydHMuaGFzT3duUHJvcGVydHkocCkpIGV4cG9ydHNbcF0gPSBtW3BdO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX192YWx1ZXMobykge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdLCBpID0gMDtcclxuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xyXG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgYXIgPSBhci5jb25jYXQoX19yZWFkKGFyZ3VtZW50c1tpXSkpO1xyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdCh2KSB7XHJcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIGcgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSksIGksIHEgPSBbXTtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpZiAoZ1tuXSkgaVtuXSA9IGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAoYSwgYikgeyBxLnB1c2goW24sIHYsIGEsIGJdKSA+IDEgfHwgcmVzdW1lKG4sIHYpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IG4gPT09IFwicmV0dXJuXCIgfSA6IGYgPyBmKHYpIDogdjsgfSA6IGY7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNWYWx1ZXMobykge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBtID0gb1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0sIGk7XHJcbiAgICByZXR1cm4gbSA/IG0uY2FsbChvKSA6IChvID0gdHlwZW9mIF9fdmFsdWVzID09PSBcImZ1bmN0aW9uXCIgPyBfX3ZhbHVlcyhvKSA6IG9bU3ltYm9sLml0ZXJhdG9yXSgpLCBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaSk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaVtuXSA9IG9bbl0gJiYgZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdiA9IG9bbl0odiksIHNldHRsZShyZXNvbHZlLCByZWplY3QsIHYuZG9uZSwgdi52YWx1ZSk7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCBkLCB2KSB7IFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGZ1bmN0aW9uKHYpIHsgcmVzb2x2ZSh7IHZhbHVlOiB2LCBkb25lOiBkIH0pOyB9LCByZWplY3QpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ha2VUZW1wbGF0ZU9iamVjdChjb29rZWQsIHJhdykge1xyXG4gICAgaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29va2VkLCBcInJhd1wiLCB7IHZhbHVlOiByYXcgfSk7IH0gZWxzZSB7IGNvb2tlZC5yYXcgPSByYXc7IH1cclxuICAgIHJldHVybiBjb29rZWQ7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSByZXN1bHRba10gPSBtb2Rba107XHJcbiAgICByZXN1bHQuZGVmYXVsdCA9IG1vZDtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydERlZmF1bHQobW9kKSB7XHJcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IGRlZmF1bHQ6IG1vZCB9O1xyXG59XHJcbiIsImltcG9ydCB7SW5qZWN0aW9uVG9rZW59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtBcG9sbG9DYWNoZX0gZnJvbSAnYXBvbGxvLWNhY2hlJztcbmltcG9ydCB7U3RhdGVDbGFzcywgTWV0YWRhdGF9IGZyb20gJ0Bsb29uYS9jb3JlJztcblxuZXhwb3J0IGNvbnN0IElOSVRJQUxfU1RBVEUgPSBuZXcgSW5qZWN0aW9uVG9rZW48U3RhdGVDbGFzczxNZXRhZGF0YT4+KFxuICAnTG9vbmEvU3RhdGUnLFxuKTtcbmV4cG9ydCBjb25zdCBDSElMRF9TVEFURSA9IG5ldyBJbmplY3Rpb25Ub2tlbjxTdGF0ZUNsYXNzPE1ldGFkYXRhPj4oXG4gICdMb29uYS9DaGlsZFN0YXRlJyxcbik7XG5leHBvcnQgY29uc3QgTE9PTkFfQ0FDSEUgPSBuZXcgSW5qZWN0aW9uVG9rZW48QXBvbGxvQ2FjaGU8YW55Pj4oJ0xvb25hL0NhY2hlJyk7XG5cbmV4cG9ydCBjb25zdCBJTklUID0gJ0BAaW5pdCc7XG5leHBvcnQgY29uc3QgUk9PVF9FRkZFQ1RTX0lOSVQgPSAnQEBlZmZlY3RzL2luaXQnO1xuZXhwb3J0IGNvbnN0IFVQREFURV9FRkZFQ1RTID0gJ0BAZWZmZWN0cy91cGRhdGUnO1xuIiwiaW1wb3J0IHtJbmplY3RhYmxlLCBPbkRlc3Ryb3l9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtPYnNlcnZhYmxlLCBCZWhhdmlvclN1YmplY3QsIFN1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtBY3Rpb259IGZyb20gJ0Bsb29uYS9jb3JlJztcblxuaW1wb3J0IHtJTklUfSBmcm9tICcuL3Rva2Vucyc7XG5cbmV4cG9ydCBjbGFzcyBBY3Rpb25zPFYgPSBBY3Rpb24+IGV4dGVuZHMgT2JzZXJ2YWJsZTxWPiB7fVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgU2Nhbm5lZEFjdGlvbnMgZXh0ZW5kcyBTdWJqZWN0PEFjdGlvbj4gaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLmNvbXBsZXRlKCk7XG4gIH1cbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIElubmVyQWN0aW9ucyBleHRlbmRzIEJlaGF2aW9yU3ViamVjdDxBY3Rpb24+IGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoe3R5cGU6IElOSVR9KTtcbiAgfVxuXG4gIG5leHQoYWN0aW9uOiBBY3Rpb24pIHtcbiAgICBpZiAodHlwZW9mIGFjdGlvbiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEFjdGlvbnMgbXVzdCBiZSBvYmplY3RzYCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgYWN0aW9uLnR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBBY3Rpb25zIG11c3QgaGF2ZSBhIHR5cGUgcHJvcGVydHlgKTtcbiAgICB9XG5cbiAgICBzdXBlci5uZXh0KGFjdGlvbik7XG4gIH1cblxuICBjb21wbGV0ZSgpIHt9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgc3VwZXIuY29tcGxldGUoKTtcbiAgfVxufVxuIiwiaW1wb3J0IHtJbmplY3RhYmxlLCBFcnJvckhhbmRsZXJ9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtBcG9sbG8sIFF1ZXJ5UmVmfSBmcm9tICdhcG9sbG8tYW5ndWxhcic7XG5pbXBvcnQge1xuICBXYXRjaFF1ZXJ5T3B0aW9ucyxcbiAgTXV0YXRpb25PcHRpb25zIGFzIENvcmVNdXRhdGlvbk9wdGlvbnMsXG59IGZyb20gJ2Fwb2xsby1jbGllbnQnO1xuaW1wb3J0IHtGZXRjaFJlc3VsdH0gZnJvbSAnYXBvbGxvLWxpbmsnO1xuaW1wb3J0IHtPYnNlcnZhYmxlLCBTdWJqZWN0LCBxdWV1ZVNjaGVkdWxlciwgbWVyZ2UsIHRocm93RXJyb3J9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtvYnNlcnZlT24sIHRhcCwgY2F0Y2hFcnJvcn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtEb2N1bWVudE5vZGV9IGZyb20gJ2dyYXBocWwnO1xuaW1wb3J0IHtcbiAgaXNNdXRhdGlvbixcbiAgZ2V0TXV0YXRpb24sXG4gIEFjdGlvbixcbiAgaXNEb2N1bWVudCxcbiAgTWFuYWdlcixcbiAgd2l0aFVwZGF0ZXMsXG4gIGdldEFjdGlvblR5cGUsXG4gIGJ1aWxkQWN0aW9uRnJvbVJlc3VsdCxcbiAgYnVpbGRBY3Rpb25Gcm9tRXJyb3IsXG59IGZyb20gJ0Bsb29uYS9jb3JlJztcblxuaW1wb3J0IHtJbm5lckFjdGlvbnMsIFNjYW5uZWRBY3Rpb25zfSBmcm9tICcuL2FjdGlvbnMnO1xuXG5leHBvcnQgdHlwZSBPbWl0PFQsIEsgZXh0ZW5kcyBrZXlvZiBUPiA9IFBpY2s8VCwgRXhjbHVkZTxrZXlvZiBULCBLPj47XG5cbmV4cG9ydCBpbnRlcmZhY2UgUXVlcnlPcHRpb25zXG4gIGV4dGVuZHMgT21pdDxXYXRjaFF1ZXJ5T3B0aW9ucywgJ3F1ZXJ5JyB8ICd2YXJpYWJsZXMnPiB7fVxuXG5leHBvcnQgaW50ZXJmYWNlIE11dGF0aW9uT3B0aW9uc1xuICBleHRlbmRzIE9taXQ8Q29yZU11dGF0aW9uT3B0aW9ucywgJ211dGF0aW9uJyB8ICd2YXJpYWJsZXMnPiB7fVxuXG5leHBvcnQgdHlwZSBSID0gUmVjb3JkPHN0cmluZywgYW55PjtcblxuZXhwb3J0IGludGVyZmFjZSBUeXBlZFZhcmlhYmxlczxWPiB7XG4gIHZhcmlhYmxlcz86IFY7XG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBMb29uYSB7XG4gIHByaXZhdGUgcXVldWUkOiBPYnNlcnZhYmxlPEFjdGlvbj47XG4gIHByaXZhdGUgZGlyZWN0JCA9IG5ldyBTdWJqZWN0PEFjdGlvbj4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGFwb2xsbzogQXBvbGxvLFxuICAgIHByaXZhdGUgbWFuYWdlcjogTWFuYWdlcixcbiAgICBwcml2YXRlIGFjdGlvbnM6IElubmVyQWN0aW9ucyxcbiAgICBzY2FubmVkQWN0aW9uczogU2Nhbm5lZEFjdGlvbnMsXG4gICAgZXJyb3JIYW5kbGVyOiBFcnJvckhhbmRsZXIsXG4gICkge1xuICAgIHRoaXMucXVldWUkID0gbWVyZ2UoYWN0aW9ucywgdGhpcy5kaXJlY3QkKS5waXBlKG9ic2VydmVPbihxdWV1ZVNjaGVkdWxlcikpO1xuICAgIHRoaXMucXVldWUkLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiBhY3Rpb24gPT4ge1xuICAgICAgICBzY2FubmVkQWN0aW9ucy5uZXh0KGFjdGlvbik7XG4gICAgICB9LFxuICAgICAgZXJyb3I6IGVycm9yID0+IHtcbiAgICAgICAgZXJyb3JIYW5kbGVyLmhhbmRsZUVycm9yKGVycm9yKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICBxdWVyeTxULCBWID0gYW55PihcbiAgICBxdWVyeTogRG9jdW1lbnROb2RlLFxuICAgIHZhcmlhYmxlcz86IFYsXG4gICAgb3B0aW9ucz86IFF1ZXJ5T3B0aW9ucyxcbiAgKTogUXVlcnlSZWY8VCwgVj47XG5cbiAgcXVlcnk8VCwgViA9IGFueT4oXG4gICAgb3B0aW9uczogV2F0Y2hRdWVyeU9wdGlvbnMgJiBUeXBlZFZhcmlhYmxlczxWPixcbiAgKTogUXVlcnlSZWY8VCwgVj47XG5cbiAgcXVlcnk8VCwgViA9IGFueT4oXG4gICAgcXVlcnlPck9wdGlvbnM6IERvY3VtZW50Tm9kZSB8IChXYXRjaFF1ZXJ5T3B0aW9ucyAmIFR5cGVkVmFyaWFibGVzPFY+KSxcbiAgICB2YXJpYWJsZXM/OiBWLFxuICAgIG9wdGlvbnM/OiBRdWVyeU9wdGlvbnMsXG4gICk6IFF1ZXJ5UmVmPFQsIFY+IHtcbiAgICByZXR1cm4gdGhpcy5hcG9sbG8ud2F0Y2hRdWVyeTxULCBWPihcbiAgICAgIGlzRG9jdW1lbnQocXVlcnlPck9wdGlvbnMpXG4gICAgICAgID8ge1xuICAgICAgICAgICAgcXVlcnk6IHF1ZXJ5T3JPcHRpb25zLFxuICAgICAgICAgICAgdmFyaWFibGVzLFxuICAgICAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgICB9XG4gICAgICAgIDogcXVlcnlPck9wdGlvbnMsXG4gICAgKTtcbiAgfVxuXG4gIG11dGF0ZTxULCBWID0gUj4oXG4gICAgbXV0YXRpb246IERvY3VtZW50Tm9kZSxcbiAgICB2YXJpYWJsZXM/OiBWLFxuICAgIG9wdGlvbnM/OiBNdXRhdGlvbk9wdGlvbnMsXG4gICk6IE9ic2VydmFibGU8RmV0Y2hSZXN1bHQ8VD4+O1xuXG4gIG11dGF0ZTxULCBWID0gUj4oXG4gICAgb3B0aW9uczogQ29yZU11dGF0aW9uT3B0aW9uczxULCBWPixcbiAgKTogT2JzZXJ2YWJsZTxGZXRjaFJlc3VsdDxUPj47XG5cbiAgbXV0YXRlPFQsIFYgPSBSPihcbiAgICBtdXRhdGlvbk9yT3B0aW9uczogRG9jdW1lbnROb2RlIHwgQ29yZU11dGF0aW9uT3B0aW9uczxULCBWPixcbiAgICB2YXJpYWJsZXM/OiBWLFxuICAgIG9wdGlvbnM/OiBNdXRhdGlvbk9wdGlvbnMsXG4gICk6IE9ic2VydmFibGU8RmV0Y2hSZXN1bHQ8VD4+IHtcbiAgICBjb25zdCBjb25maWcgPSBpc0RvY3VtZW50KG11dGF0aW9uT3JPcHRpb25zKVxuICAgICAgPyB7XG4gICAgICAgICAgbXV0YXRpb246IG11dGF0aW9uT3JPcHRpb25zLFxuICAgICAgICAgIHZhcmlhYmxlcyxcbiAgICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICB9XG4gICAgICA6IG11dGF0aW9uT3JPcHRpb25zO1xuXG4gICAgcmV0dXJuIHRoaXMuYXBvbGxvXG4gICAgICAubXV0YXRlPFQsIFY+KHdpdGhVcGRhdGVzPFQsIFY+KGNvbmZpZywgdGhpcy5tYW5hZ2VyKSlcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAocmVzdWx0ID0+IHtcbiAgICAgICAgICB0aGlzLmRpcmVjdCQubmV4dChidWlsZEFjdGlvbkZyb21SZXN1bHQoY29uZmlnLCByZXN1bHQpKTtcbiAgICAgICAgfSksXG4gICAgICAgIGNhdGNoRXJyb3IoZXJyb3IgPT4ge1xuICAgICAgICAgIHRoaXMuZGlyZWN0JC5uZXh0KGJ1aWxkQWN0aW9uRnJvbUVycm9yKGNvbmZpZywgZXJyb3IpKTtcbiAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcihlcnJvcik7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfVxuXG4gIGRpc3BhdGNoKGFjdGlvbjogYW55KTogdm9pZCB7XG4gICAgaWYgKGlzTXV0YXRpb24oYWN0aW9uKSkge1xuICAgICAgY29uc3QgbXV0YXRpb24gPSBnZXRNdXRhdGlvbihhY3Rpb24pO1xuXG4gICAgICB0aGlzLm11dGF0ZSh7XG4gICAgICAgIG11dGF0aW9uLFxuICAgICAgICAuLi5hY3Rpb24sXG4gICAgICB9KS5zdWJzY3JpYmUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5hY3Rpb25zLm5leHQoe1xuICAgICAgICB0eXBlOiBnZXRBY3Rpb25UeXBlKGFjdGlvbiksXG4gICAgICAgIC4uLmFjdGlvbixcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGV4dHJhY3Q8VCA9IGFueT4oKTogVCB7XG4gICAgcmV0dXJuIHRoaXMuYXBvbGxvLmdldENsaWVudCgpLmV4dHJhY3QoKTtcbiAgfVxuXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMuYXBvbGxvLmdldENsaWVudCgpLnJlc2V0U3RvcmUoKTtcbiAgfVxuXG4gIHJlc3RvcmUoc3RhdGU6IGFueSk6IHZvaWQge1xuICAgIHRoaXMuYXBvbGxvLmdldENsaWVudCgpLnJlc3RvcmUoc3RhdGUpO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBidWlsZENvbnRleHQsXG4gIGdldE5hbWVPZk11dGF0aW9uLFxuICBpc011dGF0aW9uQXNBY3Rpb24sXG4gIE1ldGFkYXRhLFxuICBFZmZlY3RNZXRob2QsXG4gIEFjdGlvbixcbiAgRWZmZWN0Q29udGV4dCxcbiAgU3RhdGVDbGFzcyxcbiAgTUVUQURBVEFfS0VZLFxuICBidWlsZEdldENhY2hlS2V5LFxufSBmcm9tICdAbG9vbmEvY29yZSc7XG5pbXBvcnQge0luamVjdGFibGUsIEluamVjdCwgT25EZXN0cm95LCBJbmplY3Rvcn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0Fwb2xsb0NhY2hlfSBmcm9tICdhcG9sbG8tY2FjaGUnO1xuaW1wb3J0IHtBcG9sbG99IGZyb20gJ2Fwb2xsby1hbmd1bGFyJztcbmltcG9ydCB7U3Vic2NyaXB0aW9ufSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHtMb29uYX0gZnJvbSAnLi9jbGllbnQnO1xuaW1wb3J0IHtMT09OQV9DQUNIRX0gZnJvbSAnLi90b2tlbnMnO1xuaW1wb3J0IHtTY2FubmVkQWN0aW9uc30gZnJvbSAnLi9hY3Rpb25zJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEVmZmVjdHMge1xuICBlZmZlY3RzOiBSZWNvcmQ8c3RyaW5nLCBBcnJheTxFZmZlY3RNZXRob2Q+PiA9IHt9O1xuICBnZXRDb250ZXh0OiAoKSA9PiBFZmZlY3RDb250ZXh0O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGxvb25hOiBMb29uYSxcbiAgICBhcG9sbG86IEFwb2xsbyxcbiAgICBASW5qZWN0KExPT05BX0NBQ0hFKSBjYWNoZTogQXBvbGxvQ2FjaGU8YW55PixcbiAgKSB7XG4gICAgdGhpcy5nZXRDb250ZXh0ID0gKCkgPT4gKHtcbiAgICAgIC4uLmJ1aWxkQ29udGV4dChcbiAgICAgICAge1xuICAgICAgICAgIGNhY2hlLFxuICAgICAgICAgIGdldENhY2hlS2V5OiBidWlsZEdldENhY2hlS2V5KGNhY2hlKSxcbiAgICAgICAgfSxcbiAgICAgICAgYXBvbGxvLmdldENsaWVudCgpLFxuICAgICAgKSxcbiAgICAgIGRpc3BhdGNoOiBsb29uYS5kaXNwYXRjaC5iaW5kKGxvb25hKSxcbiAgICB9KTtcbiAgfVxuXG4gIGFkZEVmZmVjdHMoaW5zdGFuY2U6IGFueSwgbWV0YT86IE1ldGFkYXRhLkVmZmVjdHMpIHtcbiAgICBpZiAoIW1ldGEpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHR5cGUgaW4gbWV0YSkge1xuICAgICAgaWYgKCF0aGlzLmVmZmVjdHNbdHlwZV0pIHtcbiAgICAgICAgdGhpcy5lZmZlY3RzW3R5cGVdID0gW107XG4gICAgICB9XG5cbiAgICAgIG1ldGFbdHlwZV0uZm9yRWFjaCgoe3Byb3BOYW1lfSkgPT4ge1xuICAgICAgICB0aGlzLmVmZmVjdHNbdHlwZV0ucHVzaChpbnN0YW5jZVtwcm9wTmFtZV0uYmluZChpbnN0YW5jZSkpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcnVuRWZmZWN0cyhhY3Rpb246IEFjdGlvbikge1xuICAgIGxldCB0eXBlID0gYWN0aW9uLnR5cGU7XG5cbiAgICBpZiAoaXNNdXRhdGlvbkFzQWN0aW9uKGFjdGlvbikpIHtcbiAgICAgIHR5cGUgPSBnZXROYW1lT2ZNdXRhdGlvbihhY3Rpb24ub3B0aW9ucy5tdXRhdGlvbik7XG4gICAgfVxuXG4gICAgY29uc3QgZWZmZWN0c1RvUnVuID0gdGhpcy5lZmZlY3RzW3R5cGVdO1xuXG4gICAgaWYgKGVmZmVjdHNUb1J1bikge1xuICAgICAgZWZmZWN0c1RvUnVuLmZvckVhY2goZWZmZWN0ID0+IHtcbiAgICAgICAgZWZmZWN0KGFjdGlvbiwgdGhpcy5nZXRDb250ZXh0KCkpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBFZmZlY3RzUnVubmVyIGltcGxlbWVudHMgT25EZXN0cm95IHtcbiAgcHJpdmF0ZSBhY3Rpb25zU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVmZmVjdHM6IEVmZmVjdHMsXG4gICAgcHJpdmF0ZSBzY2FubmVkQWN0aW9uczogU2Nhbm5lZEFjdGlvbnMsXG4gICkge31cblxuICBzdGFydCgpIHtcbiAgICBpZiAoIXRoaXMuYWN0aW9uc1N1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5hY3Rpb25zU3Vic2NyaXB0aW9uID0gdGhpcy5zY2FubmVkQWN0aW9ucy5zdWJzY3JpYmUoYWN0aW9uID0+IHtcbiAgICAgICAgdGhpcy5lZmZlY3RzLnJ1bkVmZmVjdHMoYWN0aW9uKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIGlmICh0aGlzLmFjdGlvbnNTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuYWN0aW9uc1N1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy5hY3Rpb25zU3Vic2NyaXB0aW9uID0gbnVsbDtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1hcFN0YXRlcygpIHtcbiAgY29uc3QgbmFtZXM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IGFkZCA9IChzdGF0ZTogYW55KSA9PiB7XG4gICAgbmFtZXMucHVzaChzdGF0ZS5jb25zdHJ1Y3RvciAmJiBzdGF0ZS5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgfTtcblxuICByZXR1cm4ge25hbWVzLCBhZGR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdFN0YXRlKFxuICBzdGF0ZTogU3RhdGVDbGFzczxNZXRhZGF0YT4sXG4gIGluamVjdG9yOiBJbmplY3Rvcixcbik6IHtcbiAgaW5zdGFuY2U6IGFueTtcbiAgbWV0YTogTWV0YWRhdGE7XG59IHtcbiAgcmV0dXJuIHtcbiAgICBpbnN0YW5jZTogaW5qZWN0b3IuZ2V0KHN0YXRlKSxcbiAgICBtZXRhOiBzdGF0ZVtNRVRBREFUQV9LRVldLFxuICB9O1xufVxuIiwiaW1wb3J0IHtPYnNlcnZhYmxlLCBmcm9tfSBmcm9tICdyeGpzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGlzT2JzZXJ2YWJsZTxUID0gYW55Pih2YWw6IGFueSk6IHZhbCBpcyBPYnNlcnZhYmxlPFQ+IHtcbiAgcmV0dXJuIHZhbCBpbnN0YW5jZW9mIE9ic2VydmFibGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYW5kbGVPYnNlcnZhYmxlKHJlc29sdmVyOiBhbnkpIHtcbiAgcmV0dXJuICguLi5hcmdzOiBhbnlbXSkgPT4ge1xuICAgIGxldCByZXN1bHQ6IGFueTtcblxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSByZXNvbHZlciguLi5hcmdzKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdCBpbnN0YW5jZW9mIFByb21pc2UgfHwgaXNPYnNlcnZhYmxlKHJlc3VsdClcbiAgICAgID8gZnJvbShyZXN1bHQpLnRvUHJvbWlzZSgpXG4gICAgICA6IFByb21pc2UucmVzb2x2ZShyZXN1bHQpO1xuICB9O1xufVxuIiwiaW1wb3J0IHtOZ01vZHVsZSwgTW9kdWxlV2l0aFByb3ZpZGVycywgSW5qZWN0b3IsIEluamVjdH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0Fwb2xsb0NhY2hlfSBmcm9tICdhcG9sbG8tY2FjaGUnO1xuaW1wb3J0IHtBcG9sbG99IGZyb20gJ2Fwb2xsby1hbmd1bGFyJztcbmltcG9ydCB7TWFuYWdlciwgTG9vbmFMaW5rLCBTdGF0ZUNsYXNzLCBNZXRhZGF0YX0gZnJvbSAnQGxvb25hL2NvcmUnO1xuXG5pbXBvcnQge0xvb25hfSBmcm9tICcuL2NsaWVudCc7XG5pbXBvcnQge0lubmVyQWN0aW9ucywgU2Nhbm5lZEFjdGlvbnMsIEFjdGlvbnN9IGZyb20gJy4vYWN0aW9ucyc7XG5pbXBvcnQge0VmZmVjdHNSdW5uZXIsIEVmZmVjdHMsIG1hcFN0YXRlcywgZXh0cmFjdFN0YXRlfSBmcm9tICcuL2VmZmVjdHMnO1xuaW1wb3J0IHtcbiAgSU5JVElBTF9TVEFURSxcbiAgQ0hJTERfU1RBVEUsXG4gIExPT05BX0NBQ0hFLFxuICBST09UX0VGRkVDVFNfSU5JVCxcbiAgVVBEQVRFX0VGRkVDVFMsXG59IGZyb20gJy4vdG9rZW5zJztcbmltcG9ydCB7aGFuZGxlT2JzZXJ2YWJsZX0gZnJvbSAnLi91dGlscyc7XG5cbkBOZ01vZHVsZSgpXG5leHBvcnQgY2xhc3MgTG9vbmFSb290TW9kdWxlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBlZmZlY3RzOiBFZmZlY3RzLFxuICAgIEBJbmplY3QoSU5JVElBTF9TVEFURSkgc3RhdGVzOiBTdGF0ZUNsYXNzPE1ldGFkYXRhPltdLFxuICAgIGxvb25hOiBMb29uYSxcbiAgICBtYW5hZ2VyOiBNYW5hZ2VyLFxuICAgIHJ1bm5lcjogRWZmZWN0c1J1bm5lcixcbiAgICBpbmplY3RvcjogSW5qZWN0b3IsXG4gICkge1xuICAgIHJ1bm5lci5zdGFydCgpO1xuXG4gICAgY29uc3Qge25hbWVzLCBhZGR9ID0gbWFwU3RhdGVzKCk7XG5cbiAgICBzdGF0ZXMuZm9yRWFjaChzdGF0ZSA9PiB7XG4gICAgICBjb25zdCB7aW5zdGFuY2UsIG1ldGF9ID0gZXh0cmFjdFN0YXRlKHN0YXRlLCBpbmplY3Rvcik7XG5cbiAgICAgIG1hbmFnZXIuYWRkU3RhdGUoaW5zdGFuY2UsIG1ldGEsIGhhbmRsZU9ic2VydmFibGUpO1xuICAgICAgdGhpcy5hZGRFZmZlY3RzKGluc3RhbmNlLCBtZXRhLmVmZmVjdHMpO1xuICAgICAgYWRkKGluc3RhbmNlKTtcbiAgICB9KTtcblxuICAgIGxvb25hLmRpc3BhdGNoKHtcbiAgICAgIHR5cGU6IFJPT1RfRUZGRUNUU19JTklULFxuICAgICAgc3RhdGVzOiBuYW1lcyxcbiAgICB9KTtcbiAgfVxuXG4gIGFkZEVmZmVjdHMoc3RhdGU6IGFueSwgbWV0YT86IE1ldGFkYXRhLkVmZmVjdHMpIHtcbiAgICB0aGlzLmVmZmVjdHMuYWRkRWZmZWN0cyhzdGF0ZSwgbWV0YSk7XG4gIH1cbn1cblxuQE5nTW9kdWxlKClcbmV4cG9ydCBjbGFzcyBMb29uYUNoaWxkTW9kdWxlIHtcbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChDSElMRF9TVEFURSkgc3RhdGVzOiBTdGF0ZUNsYXNzPE1ldGFkYXRhPltdLFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICBtYW5hZ2VyOiBNYW5hZ2VyLFxuICAgIGxvb25hOiBMb29uYSxcbiAgICByb290TW9kdWxlOiBMb29uYVJvb3RNb2R1bGUsXG4gICkge1xuICAgIGNvbnN0IHtuYW1lcywgYWRkfSA9IG1hcFN0YXRlcygpO1xuXG4gICAgc3RhdGVzLmZvckVhY2goc3RhdGUgPT4ge1xuICAgICAgY29uc3Qge2luc3RhbmNlLCBtZXRhfSA9IGV4dHJhY3RTdGF0ZShzdGF0ZSwgaW5qZWN0b3IpO1xuXG4gICAgICBtYW5hZ2VyLmFkZFN0YXRlKGluc3RhbmNlLCBtZXRhLCBoYW5kbGVPYnNlcnZhYmxlKTtcbiAgICAgIHJvb3RNb2R1bGUuYW