UNPKG

@harmowatch/ngx-redux-core

Version:

[![Join the chat at https://gitter.im/harmowatch/ngx-redux-core](https://badges.gitter.im/harmowatch/ngx-redux-core.svg)](https://gitter.im/harmowatch/ngx-redux-core?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

828 lines (806 loc) 87.4 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@harmowatch/redux-decorators'), require('rxjs'), require('rxjs/operators'), require('redux'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('@harmowatch/ngx-redux-core', ['exports', '@angular/core', '@harmowatch/redux-decorators', 'rxjs', 'rxjs/operators', 'redux', '@angular/common'], factory) : (factory((global.harmowatch = global.harmowatch || {}, global.harmowatch['ngx-redux-core'] = {}),global.ng.core,null,global.rxjs,global.rxjs.operators,null,global.ng.common)); }(this, (function (exports,core,reduxDecorators,rxjs,operators,redux,common) { '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 = 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]; }; function __extends(d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __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; }; function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } 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,uselessCode} checked by tsc */ var ReduxStateDefinitionToken = /** @class */ (function (_super) { __extends(ReduxStateDefinitionToken, _super); function ReduxStateDefinitionToken() { return _super.call(this, 'ReduxStateDefinitionToken') || this; } return ReduxStateDefinitionToken; }(core.InjectionToken)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var ReduxStore = /** @class */ (function (_super) { __extends(ReduxStore, _super); function ReduxStore() { return _super.call(this, 'ReduxStore') || this; } return ReduxStore; }(core.InjectionToken)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var ReduxRegistry = /** @class */ (function () { function ReduxRegistry(store) { if (store === void 0) { store = null; } ReduxRegistry.reset(); ReduxRegistry.registerStore(store); } /** * @return {?} */ ReduxRegistry.reset = /** * @return {?} */ function () { ReduxRegistry._store = new rxjs.AsyncSubject(); }; /** * @param {?} store * @return {?} */ ReduxRegistry.registerStore = /** * @param {?} store * @return {?} */ function (store) { ReduxRegistry.reset(); ReduxRegistry._store.next(store); ReduxRegistry._store.complete(); reduxDecorators.ReduxActionDispatcher.dispatchedActions.subscribe(function (action) { /** @type {?} */ var reduxAction = { type: action.type, payload: action.payload, }; store.dispatch(reduxAction); if (action.onDispatchSuccess) { action.onDispatchSuccess(); } }); }; /** * @param {?} state * @return {?} */ ReduxRegistry.registerState = /** * @param {?} state * @return {?} */ function (state) { ReduxRegistry.getStore().then(function (store) { /** @type {?} */ var stateConfig = reduxDecorators.ReduxStateDecorator.get(state.constructor); /** @type {?} */ var initialState = state.getInitialState(); Promise .resolve(initialState instanceof rxjs.Observable ? initialState.toPromise() : initialState) .then(function (initialValue) { store.dispatch({ payload: { initialValue: initialValue, name: stateConfig.name, }, type: ReduxRegistry.ACTION_REGISTER_STATE, }); }); }); }; /** * @return {?} */ ReduxRegistry.getStore = /** * @return {?} */ function () { return new Promise(ReduxRegistry._store.subscribe.bind(ReduxRegistry._store)); }; ReduxRegistry.ACTION_REGISTER_STATE = "@harmowatch/ngx-redux-core/registerState"; ReduxRegistry._store = new rxjs.AsyncSubject(); ReduxRegistry.decorators = [ { type: core.Injectable } ]; /** @nocollapse */ ReduxRegistry.ctorParameters = function () { return [ { type: undefined, decorators: [{ type: core.Inject, args: [ReduxStore,] }] } ]; }; return ReduxRegistry; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** * @template T */ var ReduxSelector = /** @class */ (function (_super) { __extends(ReduxSelector, _super); function ReduxSelector(zone, selector, stateProvider) { if (selector === void 0) { selector = '/'; } var _this = this; if (!selector.startsWith(ReduxSelector.DELIMITER) && !stateProvider) { throw new Error('You need to provide a state provider, if you use relative selectors'); } _this = _super.call(this, 1) || this; ReduxRegistry.getStore().then(function (store) { /** @type {?} */ var next = function () { zone.run(function () { _this.next(ReduxSelector.getValueByState(store.getState(), selector, stateProvider)); }); }; store.subscribe(function () { return next(); }); next(); // we need to trigger a initial value, otherwise we've to wait until the first state change }); return _this; } /** * @param {?} selector * @param {?=} stateProvider * @return {?} */ ReduxSelector.normalize = /** * @param {?} selector * @param {?=} stateProvider * @return {?} */ function (selector, stateProvider) { if (!selector.startsWith(ReduxSelector.DELIMITER)) { /** @type {?} */ var stateName = reduxDecorators.ReduxStateDecorator.get(stateProvider).name; return "" + ReduxSelector.DELIMITER + stateName + ReduxSelector.DELIMITER + selector; } return selector; }; /** * @template S * @param {?} state * @param {?} selector * @param {?=} stateProvider * @return {?} */ ReduxSelector.getValueByState = /** * @template S * @param {?} state * @param {?} selector * @param {?=} stateProvider * @return {?} */ function (state, selector, stateProvider) { /** @type {?} */ var value = ReduxSelector.normalize(selector, stateProvider).split(ReduxSelector.DELIMITER) .filter(function (propertyKey) { return propertyKey !== ''; }) .reduce(function (previousValue, propertyKey) { if (!previousValue || !previousValue.hasOwnProperty(propertyKey)) { return null; } return previousValue[propertyKey]; }, /** @type {?} */ (state)); return value; }; ReduxSelector.DELIMITER = '/'; return ReduxSelector; }(rxjs.ReplaySubject)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** * @abstract * @template S */ var ReduxStateProvider = /** @class */ (function () { function ReduxStateProvider(stateDefs, zone) { if (stateDefs === void 0) { stateDefs = []; } var _this = this; this.zone = zone; this.selectorCache = {}; var _a = (reduxDecorators.ReduxStateDecorator.get(this.constructor) || {}).name, name = _a === void 0 ? null : _a; if (!name) { throw new Error('Unable to resolve state name! Make sure you\'ve decorated the provider by "@ReduxState"!'); } this.name = reduxDecorators.ReduxStateDecorator.get(this.constructor).name; this.stateDef = stateDefs.find(function (def) { return reduxDecorators.ReduxStateDecorator.get(def.provider).name === name; }); if (!this.stateDef) { throw new Error('Unable to resolve state definition! Make sure you\'ve registered the provider to ReduxModule!'); } this.reducerMethodsByType = (this.stateDef.reducers || []) .map(function (clazz) { return _this.getReducerMethods(new clazz()); }) .reduce(function (all, curr) { return [].concat(curr, all); }, []) // [].concat keeps the order, all.concat(curr) destroys the order // .reduce((all, curr) => [curr, ...all], []) // [].concat keeps the order, all.concat(curr) destroys the order .reduce(function (methodsByType, reducer) { var _a; /** @type {?} */ var type = reduxDecorators.ReduxActionDispatcher.getType(reducer.type); return __assign({}, methodsByType, (_a = {}, _a[type] = [reducer.method].concat(methodsByType[type] || []), _a)); }, {}); ReduxStateProvider.instancesByName[this.name] = this; } /** * @return {?} */ ReduxStateProvider.prototype.getInitialState = /** * @return {?} */ function () { throw new Error('Method "getInitialState" not implemented.'); }; /** * @template T * @param {?=} selector * @return {?} */ ReduxStateProvider.prototype.select = /** * @template T * @param {?=} selector * @return {?} */ function (selector) { if (selector === void 0) { selector = ''; } /** @type {?} */ var stateType = /** @type {?} */ (this.constructor); selector = ReduxSelector.normalize(selector, stateType); if (!this.selectorCache[selector]) { this.selectorCache[selector] = new ReduxSelector(this.zone, selector, stateType).pipe(operators.distinctUntilChanged()); } return /** @type {?} */ (this.selectorCache[selector]); }; /** * @return {?} */ ReduxStateProvider.prototype.getState = /** * @return {?} */ function () { var _this = this; return ReduxRegistry.getStore().then(function (store) { return ReduxSelector.getValueByState(store.getState(), '/' + _this.name); }); }; /** * @template P * @param {?} state * @param {?} action * @return {?} */ ReduxStateProvider.prototype.reduce = /** * @template P * @param {?} state * @param {?} action * @return {?} */ function (state, action) { /** @type {?} */ var reducerMethods = this.reducerMethodsByType[action.type] || []; return reducerMethods.reduce(function (stateToReduce, method) { return method(stateToReduce, action); }, state); }; /** * @param {?} reducerClassInstance * @return {?} */ ReduxStateProvider.prototype.getReducerMethods = /** * @param {?} reducerClassInstance * @return {?} */ function (reducerClassInstance) { return Object.values(Object.getPrototypeOf(reducerClassInstance)) .map(function (method) { return { method: ( /** @type {?} */(method)).bind(reducerClassInstance), type: reduxDecorators.ReduxReducerDecorator.get(method), }; }) .filter(function (reducer) { return reducer && reducer.type; }) // convert array of types to multiple method entries .reduce(function (all, curr) { return all.concat([].concat(curr.type).map(function (type) { return (__assign({}, curr, { type: type })); })); }, []); }; ReduxStateProvider.instancesByName = {}; /** @nocollapse */ ReduxStateProvider.ctorParameters = function () { return [ { type: Array, decorators: [{ type: core.Inject, args: [ReduxStateDefinitionToken,] }] }, { type: core.NgZone } ]; }; return ReduxStateProvider; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** * @template S * @param {?} expression * @param {?=} context * @return {?} */ function ReduxSelect(expression, context) { return function (target, propertyKey) { /** @type {?} */ var stateName = reduxDecorators.ReduxStateDecorator.get(context).name; Object.defineProperty(target, propertyKey, { get: function () { return ReduxStateProvider.instancesByName[stateName].select(expression); } }); }; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var ReduxReducerProvider = /** @class */ (function () { function ReduxReducerProvider() { this.stateProviders = {}; } Object.defineProperty(ReduxReducerProvider.prototype, "rootReducer", { get: /** * @return {?} */ function () { return this.reduce.bind(this); }, enumerable: true, configurable: true }); /** * @param {?} provider * @return {?} */ ReduxReducerProvider.prototype.addStateProvider = /** * @param {?} provider * @return {?} */ function (provider) { if (!this.stateProviders[provider.name]) { ReduxRegistry.registerState(provider); this.stateProviders[provider.name] = provider; } else { throw new Error("State \"" + provider.name + "\" is registered twice! Make sure your state name is unique!"); } }; /** * @param {?} rootState * @param {?} action * @return {?} */ ReduxReducerProvider.prototype.reduce = /** * @param {?} rootState * @param {?} action * @return {?} */ function (rootState, action) { var _a; if (action.type === ReduxRegistry.ACTION_REGISTER_STATE) { /** @type {?} */ var regAction = ( /** @type {?} */((action))); return __assign({}, rootState, (_a = {}, _a[regAction.payload.name] = regAction.payload.initialValue, _a)); } return Object.values(this.stateProviders).reduce(function (stateToReduce, provider) { var _a; return Object.assign({}, stateToReduce, (_a = {}, _a[provider.name] = provider.reduce(stateToReduce[provider.name], action), _a)); }, rootState); }; ReduxReducerProvider.decorators = [ { type: core.Injectable } ]; return ReduxReducerProvider; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var ReduxSelectPipe = /** @class */ (function () { function ReduxSelectPipe(stateDefs, injector) { if (stateDefs === void 0) { stateDefs = []; } this.provider = /** @type {?} */ (injector.get(stateDefs[0].provider)); } /** * @param {?} selector * @return {?} */ ReduxSelectPipe.prototype.transform = /** * @param {?} selector * @return {?} */ function (selector) { return this.provider.select(selector); }; ReduxSelectPipe.decorators = [ { type: core.Pipe, args: [{ name: 'reduxSelect' },] } ]; /** @nocollapse */ ReduxSelectPipe.ctorParameters = function () { return [ { type: Array, decorators: [{ type: core.Inject, args: [ReduxStateDefinitionToken,] }] }, { type: core.Injector } ]; }; return ReduxSelectPipe; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var ReduxTestingStore = /** @class */ (function () { function ReduxTestingStore() { this.state = new rxjs.BehaviorSubject(null); } /** * @return {?} */ ReduxTestingStore.factory = /** * @return {?} */ function () { return new ReduxTestingStore(); }; /** * @template S * @param {?} state * @param {?} value * @return {?} */ ReduxTestingStore.prototype.setState = /** * @template S * @param {?} state * @param {?} value * @return {?} */ function (state, value) { var _this = this; var _a; var name = reduxDecorators.ReduxStateDecorator.get(state).name; /** @type {?} */ var nextState = Object.assign({}, this.state.getValue(), (_a = {}, _a[name] = value, _a)); this.state.next(nextState); return this.state .pipe(operators.takeWhile(function (currentState) { return currentState !== nextState; })) .toPromise().then(function () { return _this.state.getValue(); }); }; /** * @return {?} */ ReduxTestingStore.prototype.getState = /** * @return {?} */ function () { return this.state.getValue(); }; /** * @param {?} listener * @return {?} */ ReduxTestingStore.prototype.subscribe = /** * @param {?} listener * @return {?} */ function (listener) { return this.state.subscribe.call(this.state, listener); }; /** * @return {?} */ ReduxTestingStore.prototype.replaceReducer = /** * @return {?} */ function () { }; /** * @template T * @param {?} action * @return {?} */ ReduxTestingStore.prototype.dispatch = /** * @template T * @param {?} action * @return {?} */ function (action) { return action; }; ReduxTestingStore.decorators = [ { type: core.Injectable } ]; return ReduxTestingStore; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var TestingStateProvider = /** @class */ (function (_super) { __extends(TestingStateProvider, _super); function TestingStateProvider() { return _super !== null && _super.apply(this, arguments) || this; } TestingStateProvider_1 = TestingStateProvider; /** * @return {?} */ TestingStateProvider.prototype.getInitialState = /** * @return {?} */ function () { return TestingStateProvider_1.INITIAL_STATE; }; var TestingStateProvider_1; TestingStateProvider.NAME = 'testing-7c66b613-20bd-4d35-8611-5181ca4a0b72'; TestingStateProvider.INITIAL_STATE = { todo: { isFetching: false, items: ['Item 1', 'Item 2'], }, }; TestingStateProvider = TestingStateProvider_1 = __decorate([ reduxDecorators.ReduxStateDecoratorForClass({ name: TestingStateProvider_1.NAME }) ], TestingStateProvider); return TestingStateProvider; }(ReduxStateProvider)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var ReduxMiddlewares = /** @class */ (function (_super) { __extends(ReduxMiddlewares, _super); function ReduxMiddlewares() { return _super.call(this, 'ReduxMiddlewares') || this; } return ReduxMiddlewares; }(core.InjectionToken)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ var ReduxModule = /** @class */ (function () { function ReduxModule(injector, reducerProvider, stateDefs) { if (stateDefs === void 0) { stateDefs = []; } injector.get(ReduxRegistry); // just make sure the provider is instantiated if (Array.isArray(stateDefs)) { stateDefs .filter(function (def) { return def && def.provider; }) .map(function (def) { return injector.get(def.provider); }) .forEach(function (provider) { return reducerProvider.addStateProvider(provider); }); } } /** * @template S * @param {?=} config * @return {?} */ ReduxModule.forChild = /** * @template S * @param {?=} config * @return {?} */ function (config) { if (config === void 0) { config = {}; } return { ngModule: ReduxModule, providers: [ { provide: ReduxStateDefinitionToken, useValue: config.state || null, multi: true }, ], }; }; /** * @template S * @param {?=} config * @return {?} */ ReduxModule.forRoot = /** * @template S * @param {?=} config * @return {?} */ function (config) { if (config === void 0) { config = {}; } return { ngModule: ReduxModule, providers: [ ReduxReducerProvider, ReduxRegistry, { provide: ReduxStore, useFactory: config.storeFactory || ReduxModule.defaultStoreFactory, deps: [ReduxReducerProvider, ReduxMiddlewares] }, { provide: ReduxStateDefinitionToken, useValue: config.state || null, multi: true }, { provide: ReduxMiddlewares, useValue: config.middlewareFunctions || [], multi: false }, ], }; }; /** * @param {?} reduxReducerProvider * @param {?} middlewareFunctions * @param {?=} devMode * @return {?} */ ReduxModule.defaultStoreFactory = /** * @param {?} reduxReducerProvider * @param {?} middlewareFunctions * @param {?=} devMode * @return {?} */ function (reduxReducerProvider, middlewareFunctions, devMode) { if (devMode === void 0) { devMode = core.isDevMode(); } return redux.createStore(reduxReducerProvider.rootReducer, {}, ReduxModule.defaultEnhancerFactory(middlewareFunctions, devMode)); }; /** * @param {?} middlewareFunctions * @param {?} devMode * @return {?} */ ReduxModule.defaultEnhancerFactory = /** * @param {?} middlewareFunctions * @param {?} devMode * @return {?} */ function (middlewareFunctions, devMode) { /** @type {?} */ var composeEnhancers = redux.compose; if (devMode && window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']) { composeEnhancers = window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']; } return composeEnhancers(redux.applyMiddleware.apply(void 0, __spread(middlewareFunctions))); }; ReduxModule.decorators = [ { type: core.NgModule, args: [{ declarations: [ ReduxSelectPipe, ], exports: [ ReduxSelectPipe, ], imports: [ common.CommonModule, ], },] } ]; /** @nocollapse */ ReduxModule.ctorParameters = function () { return [ { type: core.Injector }, { type: ReduxReducerProvider }, { type: Array, decorators: [{ type: core.Optional }, { type: core.Inject, args: [ReduxStateDefinitionToken,] }] } ]; }; return ReduxModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ /** @type {?} */ var getActionType = reduxDecorators.ReduxActionDispatcher.getType; /** @type {?} */ var dispatch = reduxDecorators.ReduxActionDispatcher.dispatch; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ exports.ReduxActionContext = reduxDecorators.ReduxActionContextDecoratorForClass; exports.ReduxAction = reduxDecorators.ReduxActionDecoratorForMethod; exports.ReduxReducer = reduxDecorators.ReduxReducerDecoratorForMethod; exports.ReduxState = reduxDecorators.ReduxStateDecoratorForClass; exports.ReduxModule = ReduxModule; exports.getActionType = getActionType; exports.dispatch = dispatch; exports.ReduxSelect = ReduxSelect; exports.ReduxReducerProvider = ReduxReducerProvider; exports.ReduxSelectPipe = ReduxSelectPipe; exports.ReduxSelector = ReduxSelector; exports.ReduxStateDefinitionToken = ReduxStateDefinitionToken; exports.ReduxStateProvider = ReduxStateProvider; exports.ReduxStore = ReduxStore; exports.ReduxTestingStore = ReduxTestingStore; exports.TestingStateProvider = TestingStateProvider; exports.ReduxRegistry = ReduxRegistry; exports.ɵa = ReduxMiddlewares; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFybW93YXRjaC1uZ3gtcmVkdXgtY29yZS51bWQuanMubWFwIiwic291cmNlcyI6W251bGwsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvdG9rZW5zL3JlZHV4LXN0YXRlLWRlZmluaXRpb24udG9rZW4udHMiLCJuZzovL0BoYXJtb3dhdGNoL25neC1yZWR1eC1jb3JlL3Rva2Vucy9yZWR1eC1zdG9yZS50b2tlbi50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvcHJvdmlkZXJzL3JlZHV4LXJlZ2lzdHJ5LnRzIiwibmc6Ly9AaGFybW93YXRjaC9uZ3gtcmVkdXgtY29yZS9yZWR1eC1zZWxlY3Rvci50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvcHJvdmlkZXJzL3JlZHV4LXN0YXRlLnByb3ZpZGVyLnRzIiwibmc6Ly9AaGFybW93YXRjaC9uZ3gtcmVkdXgtY29yZS9kZWNvcmF0b3JzL3JlZHV4LXNlbGVjdC5kZWNvcmF0b3IudHMiLCJuZzovL0BoYXJtb3dhdGNoL25neC1yZWR1eC1jb3JlL3Byb3ZpZGVycy9yZWR1eC1yZWR1Y2VyLnByb3ZpZGVyLnRzIiwibmc6Ly9AaGFybW93YXRjaC9uZ3gtcmVkdXgtY29yZS9waXBlcy9yZWR1eC1zZWxlY3QucGlwZS50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvdGVzdGluZy9zdG9yZS50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvdGVzdGluZy9zdGF0ZS50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvdG9rZW5zL3JlZHV4LW1pZGRsZXdhcmVzLnRva2VuLnRzIiwibmc6Ly9AaGFybW93YXRjaC9uZ3gtcmVkdXgtY29yZS9yZWR1eC5tb2R1bGUudHMiLCJuZzovL0BoYXJtb3dhdGNoL25neC1yZWR1eC1jb3JlL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cclxuTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTsgeW91IG1heSBub3QgdXNlXHJcbnRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlXHJcbkxpY2Vuc2UgYXQgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXHJcblxyXG5USElTIENPREUgSVMgUFJPVklERUQgT04gQU4gKkFTIElTKiBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZXHJcbktJTkQsIEVJVEhFUiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBXSVRIT1VUIExJTUlUQVRJT04gQU5ZIElNUExJRURcclxuV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIFRJVExFLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSxcclxuTUVSQ0hBTlRBQkxJVFkgT1IgTk9OLUlORlJJTkdFTUVOVC5cclxuXHJcblNlZSB0aGUgQXBhY2hlIFZlcnNpb24gMi4wIExpY2Vuc2UgZm9yIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xyXG5hbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlICovXHJcblxyXG52YXIgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxyXG4gICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoYi5oYXNPd25Qcm9wZXJ0eShwKSkgZFtwXSA9IGJbcF07IH07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xyXG4gICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIGlmIChlLmluZGV4T2YocFtpXSkgPCAwKVxyXG4gICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYykge1xyXG4gICAgdmFyIGMgPSBhcmd1bWVudHMubGVuZ3RoLCByID0gYyA8IDMgPyB0YXJnZXQgOiBkZXNjID09PSBudWxsID8gZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBrZXkpIDogZGVzYywgZDtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XHJcbiAgICBlbHNlIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSBpZiAoZCA9IGRlY29yYXRvcnNbaV0pIHIgPSAoYyA8IDMgPyBkKHIpIDogYyA+IDMgPyBkKHRhcmdldCwga2V5LCByKSA6IGQodGFyZ2V0LCBrZXkpKSB8fCByO1xyXG4gICAgcmV0dXJuIGMgPiAzICYmIHIgJiYgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwga2V5LCByKSwgcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcGFyYW0ocGFyYW1JbmRleCwgZGVjb3JhdG9yKSB7XHJcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpIHtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5tZXRhZGF0YSA9PT0gXCJmdW5jdGlvblwiKSByZXR1cm4gUmVmbGVjdC5tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XHJcbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHJlc3VsdC52YWx1ZSk7IH0pLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cclxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XHJcbiAgICB9KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZ2VuZXJhdG9yKHRoaXNBcmcsIGJvZHkpIHtcclxuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XHJcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoXykgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0geVtvcFswXSAmIDIgPyBcInJldHVyblwiIDogb3BbMF0gPyBcInRocm93XCIgOiBcIm5leHRcIl0pICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xyXG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gWzAsIHQudmFsdWVdO1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XHJcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cclxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZXhwb3J0U3RhcihtLCBleHBvcnRzKSB7XHJcbiAgICBmb3IgKHZhciBwIGluIG0pIGlmICghZXhwb3J0cy5oYXNPd25Qcm9wZXJ0eShwKSkgZXhwb3J0c1twXSA9IG1bcF07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3ZhbHVlcyhvKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl0sIGkgPSAwO1xyXG4gICAgaWYgKG0pIHJldHVybiBtLmNhbGwobyk7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcclxuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG8gJiYgb1tpKytdLCBkb25lOiAhbyB9O1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3JlYWQobywgbikge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xyXG4gICAgaWYgKCFtKSByZXR1cm4gbztcclxuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcclxuICAgIH1cclxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxyXG4gICAgZmluYWxseSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19zcHJlYWQoKSB7XHJcbiAgICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKylcclxuICAgICAgICBhciA9IGFyLmNvbmNhdChfX3JlYWQoYXJndW1lbnRzW2ldKSk7XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0KHYpIHtcclxuICAgIHJldHVybiB0aGlzIGluc3RhbmNlb2YgX19hd2FpdCA/ICh0aGlzLnYgPSB2LCB0aGlzKSA6IG5ldyBfX2F3YWl0KHYpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY0dlbmVyYXRvcih0aGlzQXJnLCBfYXJndW1lbnRzLCBnZW5lcmF0b3IpIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgZyA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSwgaSwgcSA9IFtdO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IGlmIChnW25dKSBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChhLCBiKSB7IHEucHVzaChbbiwgdiwgYSwgYl0pID4gMSB8fCByZXN1bWUobiwgdik7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiByZXN1bWUobiwgdikgeyB0cnkgeyBzdGVwKGdbbl0odikpOyB9IGNhdGNoIChlKSB7IHNldHRsZShxWzBdWzNdLCBlKTsgfSB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKHIpIHsgci52YWx1ZSBpbnN0YW5jZW9mIF9fYXdhaXQgPyBQcm9taXNlLnJlc29sdmUoci52YWx1ZS52KS50aGVuKGZ1bGZpbGwsIHJlamVjdCkgOiBzZXR0bGUocVswXVsyXSwgcik7IH1cclxuICAgIGZ1bmN0aW9uIGZ1bGZpbGwodmFsdWUpIHsgcmVzdW1lKFwibmV4dFwiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHJlamVjdCh2YWx1ZSkgeyByZXN1bWUoXCJ0aHJvd1wiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShmLCB2KSB7IGlmIChmKHYpLCBxLnNoaWZ0KCksIHEubGVuZ3RoKSByZXN1bWUocVswXVswXSwgcVswXVsxXSk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNEZWxlZ2F0b3Iobykge1xyXG4gICAgdmFyIGksIHA7XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIsIGZ1bmN0aW9uIChlKSB7IHRocm93IGU7IH0pLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuLCBmKSB7IGlbbl0gPSBvW25dID8gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIChwID0gIXApID8geyB2YWx1ZTogX19hd2FpdChvW25dKHYpKSwgZG9uZTogbiA9PT0gXCJyZXR1cm5cIiB9IDogZiA/IGYodikgOiB2OyB9IDogZjsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hc3luY1ZhbHVlcyhvKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIG0gPSBvW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSwgaTtcclxuICAgIHJldHVybiBtID8gbS5jYWxsKG8pIDogKG8gPSB0eXBlb2YgX192YWx1ZXMgPT09IFwiZnVuY3Rpb25cIiA/IF9fdmFsdWVzKG8pIDogb1tTeW1ib2wuaXRlcmF0b3JdKCksIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiKSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuYXN5bmNJdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpKTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpW25dID0gb1tuXSAmJiBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgeyB2ID0gb1tuXSh2KSwgc2V0dGxlKHJlc29sdmUsIHJlamVjdCwgdi5kb25lLCB2LnZhbHVlKTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShyZXNvbHZlLCByZWplY3QsIGQsIHYpIHsgUHJvbWlzZS5yZXNvbHZlKHYpLnRoZW4oZnVuY3Rpb24odikgeyByZXNvbHZlKHsgdmFsdWU6IHYsIGRvbmU6IGQgfSk7IH0sIHJlamVjdCk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWFrZVRlbXBsYXRlT2JqZWN0KGNvb2tlZCwgcmF3KSB7XHJcbiAgICBpZiAoT2JqZWN0LmRlZmluZVByb3BlcnR5KSB7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb29rZWQsIFwicmF3XCIsIHsgdmFsdWU6IHJhdyB9KTsgfSBlbHNlIHsgY29va2VkLnJhdyA9IHJhdzsgfVxyXG4gICAgcmV0dXJuIGNvb2tlZDtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydFN0YXIobW9kKSB7XHJcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xyXG4gICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgaWYgKG1vZCAhPSBudWxsKSBmb3IgKHZhciBrIGluIG1vZCkgaWYgKE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZCwgaykpIHJlc3VsdFtrXSA9IG1vZFtrXTtcclxuICAgIHJlc3VsdC5kZWZhdWx0ID0gbW9kO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0RGVmYXVsdChtb2QpIHtcclxuICAgIHJldHVybiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSA/IG1vZCA6IHsgZGVmYXVsdDogbW9kIH07XHJcbn1cclxuIiwiaW1wb3J0IHsgU3RvcmUgfSBmcm9tICdyZWR1eCc7XG5pbXBvcnQgeyBJbmplY3Rpb25Ub2tlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5leHBvcnQgY2xhc3MgUmVkdXhTdGF0ZURlZmluaXRpb25Ub2tlbiBleHRlbmRzIEluamVjdGlvblRva2VuPFN0b3JlPHt9Pj4ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCdSZWR1eFN0YXRlRGVmaW5pdGlvblRva2VuJyk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgSW5qZWN0aW9uVG9rZW4gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN0b3JlIH0gZnJvbSAncmVkdXgnO1xuXG5leHBvcnQgY2xhc3MgUmVkdXhTdG9yZSBleHRlbmRzIEluamVjdGlvblRva2VuPFN0b3JlPHt9Pj4ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCdSZWR1eFN0b3JlJyk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgUmVkdXhBY3Rpb25EaXNwYXRjaGVyLCBSZWR1eFN0YXRlRGVjb3JhdG9yIH0gZnJvbSAnQGhhcm1vd2F0Y2gvcmVkdXgtZGVjb3JhdG9ycyc7XG5cbmltcG9ydCB7IFN0b3JlIH0gZnJvbSAncmVkdXgnO1xuaW1wb3J0IHsgQXN5bmNTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUmVkdXhTdG9yZSB9IGZyb20gJy4uL3Rva2Vucy9yZWR1eC1zdG9yZS50b2tlbic7XG5pbXBvcnQgeyBSZWR1eEFjdGlvbldpdGhQYXlsb2FkIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZWR1eC1hY3Rpb24td2l0aC1wYXlsb2FkLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZWR1eFN0YXRlUHJvdmlkZXIgfSBmcm9tICcuL3JlZHV4LXN0YXRlLnByb3ZpZGVyJztcblxuZXhwb3J0IGludGVyZmFjZSBJUmVnaXN0ZXJTdGF0ZVBheWxvYWQge1xuICBpbml0aWFsVmFsdWU6IHt9O1xuICBuYW1lOiBzdHJpbmc7XG59XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBSZWR1eFJlZ2lzdHJ5IHtcblxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IEFDVElPTl9SRUdJU1RFUl9TVEFURSA9IGBAaGFybW93YXRjaC9uZ3gtcmVkdXgtY29yZS9yZWdpc3RlclN0YXRlYDtcblxuICBwcml2YXRlIHN0YXRpYyBfc3RvcmUgPSBuZXcgQXN5bmNTdWJqZWN0PFN0b3JlPHt9Pj4oKTtcblxuICBjb25zdHJ1Y3RvcihASW5qZWN0KFJlZHV4U3RvcmUpIHN0b3JlOiBTdG9yZTx7fT4gPSBudWxsKSB7XG4gICAgUmVkdXhSZWdpc3RyeS5yZXNldCgpO1xuICAgIFJlZHV4UmVnaXN0cnkucmVnaXN0ZXJTdG9yZShzdG9yZSk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIHJlc2V0KCkge1xuICAgIFJlZHV4UmVnaXN0cnkuX3N0b3JlID0gbmV3IEFzeW5jU3ViamVjdDxTdG9yZTx7fT4+KCk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIHJlZ2lzdGVyU3RvcmUoc3RvcmU6IFN0b3JlPHt9Pikge1xuICAgIFJlZHV4UmVnaXN0cnkucmVzZXQoKTtcbiAgICBSZWR1eFJlZ2lzdHJ5Ll9zdG9yZS5uZXh0KHN0b3JlKTtcbiAgICBSZWR1eFJlZ2lzdHJ5Ll9zdG9yZS5jb21wbGV0ZSgpO1xuXG4gICAgUmVkdXhBY3Rpb25EaXNwYXRjaGVyLmRpc3BhdGNoZWRBY3Rpb25zLnN1YnNjcmliZShhY3Rpb24gPT4ge1xuXG4gICAgICBjb25zdCByZWR1eEFjdGlvbjogUmVkdXhBY3Rpb25XaXRoUGF5bG9hZCA9IHtcbiAgICAgICAgdHlwZTogYWN0aW9uLnR5cGUsXG4gICAgICAgIHBheWxvYWQ6IGFjdGlvbi5wYXlsb2FkLFxuICAgICAgfTtcblxuICAgICAgc3RvcmUuZGlzcGF0Y2gocmVkdXhBY3Rpb24pO1xuXG4gICAgICBpZiAoYWN0aW9uLm9uRGlzcGF0Y2hTdWNjZXNzKSB7XG4gICAgICAgIGFjdGlvbi5vbkRpc3BhdGNoU3VjY2VzcygpO1xuICAgICAgfVxuXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIHJlZ2lzdGVyU3RhdGUoc3RhdGU6IFJlZHV4U3RhdGVQcm92aWRlcikge1xuICAgIFJlZHV4UmVnaXN0cnkuZ2V0U3RvcmUoKS50aGVuKChzdG9yZSkgPT4ge1xuXG4gICAgICBjb25zdCBzdGF0ZUNvbmZpZyA9IFJlZHV4U3RhdGVEZWNvcmF0b3IuZ2V0KHN0YXRlLmNvbnN0cnVjdG9yKTtcbiAgICAgIGNvbnN0IGluaXRpYWxTdGF0ZSA9IHN0YXRlLmdldEluaXRpYWxTdGF0ZSgpO1xuXG4gICAgICBQcm9taXNlXG4gICAgICAgIC5yZXNvbHZlKGluaXRpYWxTdGF0ZSBpbnN0YW5jZW9mIE9ic2VydmFibGUgPyBpbml0aWFsU3RhdGUudG9Qcm9taXNlKCkgOiBpbml0aWFsU3RhdGUpXG4gICAgICAgIC50aGVuKGluaXRpYWxWYWx1ZSA9PiB7XG4gICAgICAgICAgc3RvcmUuZGlzcGF0Y2g8UmVkdXhBY3Rpb25XaXRoUGF5bG9hZDxJUmVnaXN0ZXJTdGF0ZVBheWxvYWQ+Pih7XG4gICAgICAgICAgICBwYXlsb2FkOiB7XG4gICAgICAgICAgICAgIGluaXRpYWxWYWx1ZSxcbiAgICAgICAgICAgICAgbmFtZTogc3RhdGVDb25maWcubmFtZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0eXBlOiBSZWR1eFJlZ2lzdHJ5LkFDVElPTl9SRUdJU1RFUl9TVEFURSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZ2V0U3RvcmUoKTogUHJvbWlzZTxTdG9yZTx7fT4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoUmVkdXhSZWdpc3RyeS5fc3RvcmUuc3Vic2NyaWJlLmJpbmQoUmVkdXhSZWdpc3RyeS5fc3RvcmUpKTtcbiAgfVxuXG59XG4iLCJpbXBvcnQgeyBOZ1pvbmUsIFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJlcGxheVN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFJlZHV4U3RhdGVEZWNvcmF0b3IgfSBmcm9tICdAaGFybW93YXRjaC9yZWR1eC1kZWNvcmF0b3JzJztcblxuaW1wb3J0IHsgUmVkdXhSZWdpc3RyeSB9IGZyb20gJy4vcHJvdmlkZXJzL3JlZHV4LXJlZ2lzdHJ5JztcbmltcG9ydCB7IFJlZHV4Um9vdFN0YXRlIH0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlZHV4LXJvb3Qtc3RhdGUuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlZHV4U3RhdGVQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL3JlZHV4LXN0YXRlLnByb3ZpZGVyJztcblxuZXhwb3J0IGNsYXNzIFJlZHV4U2VsZWN0b3I8VD4gZXh0ZW5kcyBSZXBsYXlTdWJqZWN0PFQ+IHtcblxuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBERUxJTUlURVIgPSAnLyc7XG5cbiAgY29uc3RydWN0b3Ioem9uZTogTmdab25lLFxuICAgICAgICAgICAgICBzZWxlY3RvciA9ICcvJyxcbiAgICAgICAgICAgICAgc3RhdGVQcm92aWRlcj86IFR5cGU8UmVkdXhTdGF0ZVByb3ZpZGVyPikge1xuXG4gICAgaWYgKCFzZWxlY3Rvci5zdGFydHNXaXRoKFJlZHV4U2VsZWN0b3IuREVMSU1JVEVSKSAmJiAhc3RhdGVQcm92aWRlcikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgbmVlZCB0byBwcm92aWRlIGEgc3RhdGUgcHJvdmlkZXIsIGlmIHlvdSB1c2UgcmVsYXRpdmUgc2VsZWN0b3JzJyk7XG4gICAgfVxuXG4gICAgc3VwZXIoMSk7XG5cbiAgICBSZWR1eFJlZ2lzdHJ5LmdldFN0b3JlKCkudGhlbihzdG9yZSA9PiB7XG4gICAgICBjb25zdCBuZXh0ID0gKCkgPT4ge1xuICAgICAgICB6b25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgdGhpcy5uZXh0KFJlZHV4U2VsZWN0b3IuZ2V0VmFsdWVCeVN0YXRlKHN0b3JlLmdldFN0YXRlKCksIHNlbGVjdG9yLCBzdGF0ZVByb3ZpZGVyKSk7XG4gICAgICAgIH0pO1xuICAgICAgfTtcblxuICAgICAgc3RvcmUuc3Vic2NyaWJlKCgpID0+IG5leHQoKSk7XG4gICAgICBuZXh0KCk7IC8vIHdlIG5lZWQgdG8gdHJpZ2dlciBhIGluaXRpYWwgdmFsdWUsIG90aGVyd2lzZSB3ZSd2ZSB0byB3YWl0IHVudGlsIHRoZSBmaXJzdCBzdGF0ZSBjaGFuZ2VcbiAgICB9KTtcblxuICB9XG5cbiAgcHVibGljIHN0YXRpYyBub3JtYWxpemUoc2VsZWN0b3I6IHN0cmluZywgc3RhdG