@harmowatch/ngx-redux-core
Version:
[](https://gitter.im/harmowatch/ngx-redux-core?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
711 lines (694 loc) • 62.6 kB
JavaScript
import { __extends, __spread, __assign, __decorate } from 'tslib';
import { InjectionToken, Inject, Injectable, NgZone, Injector, Pipe, isDevMode, NgModule, Optional } from '@angular/core';
import { ReduxActionDispatcher, ReduxStateDecorator, ReduxReducerDecorator, ReduxStateDecoratorForClass } from '@harmowatch/redux-decorators';
export { ReduxActionContextDecoratorForClass as ReduxActionContext, ReduxActionDecoratorForMethod as ReduxAction, ReduxReducerDecoratorForMethod as ReduxReducer, ReduxStateDecoratorForClass as ReduxState } from '@harmowatch/redux-decorators';
import { AsyncSubject, Observable, ReplaySubject, BehaviorSubject } from 'rxjs';
import { distinctUntilChanged, takeWhile } from 'rxjs/operators';
import { applyMiddleware, compose, createStore } from 'redux';
import { CommonModule } from '@angular/common';
/**
* @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;
}(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;
}(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 AsyncSubject();
};
/**
* @param {?} store
* @return {?}
*/
ReduxRegistry.registerStore = /**
* @param {?} store
* @return {?}
*/
function (store) {
ReduxRegistry.reset();
ReduxRegistry._store.next(store);
ReduxRegistry._store.complete();
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 = ReduxStateDecorator.get(state.constructor);
/** @type {?} */
var initialState = state.getInitialState();
Promise
.resolve(initialState instanceof 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 AsyncSubject();
ReduxRegistry.decorators = [
{ type: Injectable }
];
/** @nocollapse */
ReduxRegistry.ctorParameters = function () { return [
{ type: undefined, decorators: [{ type: 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 = 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;
}(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 = (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 = ReduxStateDecorator.get(this.constructor).name;
this.stateDef = stateDefs.find(function (def) { return 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 = 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(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: 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: Inject, args: [ReduxStateDefinitionToken,] }] },
{ type: 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 = 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: 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: Pipe, args: [{ name: 'reduxSelect' },] }
];
/** @nocollapse */
ReduxSelectPipe.ctorParameters = function () { return [
{ type: Array, decorators: [{ type: Inject, args: [ReduxStateDefinitionToken,] }] },
{ type: Injector }
]; };
return ReduxSelectPipe;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var ReduxTestingStore = /** @class */ (function () {
function ReduxTestingStore() {
this.state = new 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 = 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(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: 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([
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;
}(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 = isDevMode(); }
return 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 = compose;
if (devMode && window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']) {
composeEnhancers = window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__'];
}
return composeEnhancers(applyMiddleware.apply(void 0, __spread(middlewareFunctions)));
};
ReduxModule.decorators = [
{ type: NgModule, args: [{
declarations: [
ReduxSelectPipe,
],
exports: [
ReduxSelectPipe,
],
imports: [
CommonModule,
],
},] }
];
/** @nocollapse */
ReduxModule.ctorParameters = function () { return [
{ type: Injector },
{ type: ReduxReducerProvider },
{ type: Array, decorators: [{ type: Optional }, { type: Inject, args: [ReduxStateDefinitionToken,] }] }
]; };
return ReduxModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/** @type {?} */
var getActionType = ReduxActionDispatcher.getType;
/** @type {?} */
var dispatch = ReduxActionDispatcher.dispatch;
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
export { ReduxModule, getActionType, dispatch, ReduxSelect, ReduxReducerProvider, ReduxSelectPipe, ReduxSelector, ReduxStateDefinitionToken, ReduxStateProvider, ReduxStore, ReduxTestingStore, TestingStateProvider, ReduxRegistry, ReduxMiddlewares as ɵa };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFybW93YXRjaC1uZ3gtcmVkdXgtY29yZS5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvdG9rZW5zL3JlZHV4LXN0YXRlLWRlZmluaXRpb24udG9rZW4udHMiLCJuZzovL0BoYXJtb3dhdGNoL25neC1yZWR1eC1jb3JlL3Rva2Vucy9yZWR1eC1zdG9yZS50b2tlbi50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvcHJvdmlkZXJzL3JlZHV4LXJlZ2lzdHJ5LnRzIiwibmc6Ly9AaGFybW93YXRjaC9uZ3gtcmVkdXgtY29yZS9yZWR1eC1zZWxlY3Rvci50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvcHJvdmlkZXJzL3JlZHV4LXN0YXRlLnByb3ZpZGVyLnRzIiwibmc6Ly9AaGFybW93YXRjaC9uZ3gtcmVkdXgtY29yZS9kZWNvcmF0b3JzL3JlZHV4LXNlbGVjdC5kZWNvcmF0b3IudHMiLCJuZzovL0BoYXJtb3dhdGNoL25neC1yZWR1eC1jb3JlL3Byb3ZpZGVycy9yZWR1eC1yZWR1Y2VyLnByb3ZpZGVyLnRzIiwibmc6Ly9AaGFybW93YXRjaC9uZ3gtcmVkdXgtY29yZS9waXBlcy9yZWR1eC1zZWxlY3QucGlwZS50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvdGVzdGluZy9zdG9yZS50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvdGVzdGluZy9zdGF0ZS50cyIsIm5nOi8vQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvdG9rZW5zL3JlZHV4LW1pZGRsZXdhcmVzLnRva2VuLnRzIiwibmc6Ly9AaGFybW93YXRjaC9uZ3gtcmVkdXgtY29yZS9yZWR1eC5tb2R1bGUudHMiLCJuZzovL0BoYXJtb3dhdGNoL25neC1yZWR1eC1jb3JlL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFN0b3JlIH0gZnJvbSAncmVkdXgnO1xuaW1wb3J0IHsgSW5qZWN0aW9uVG9rZW4gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuZXhwb3J0IGNsYXNzIFJlZHV4U3RhdGVEZWZpbml0aW9uVG9rZW4gZXh0ZW5kcyBJbmplY3Rpb25Ub2tlbjxTdG9yZTx7fT4+IHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcignUmVkdXhTdGF0ZURlZmluaXRpb25Ub2tlbicpO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IEluamVjdGlvblRva2VuIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdG9yZSB9IGZyb20gJ3JlZHV4JztcblxuZXhwb3J0IGNsYXNzIFJlZHV4U3RvcmUgZXh0ZW5kcyBJbmplY3Rpb25Ub2tlbjxTdG9yZTx7fT4+IHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcignUmVkdXhTdG9yZScpO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IFJlZHV4QWN0aW9uRGlzcGF0Y2hlciwgUmVkdXhTdGF0ZURlY29yYXRvciB9IGZyb20gJ0BoYXJtb3dhdGNoL3JlZHV4LWRlY29yYXRvcnMnO1xuXG5pbXBvcnQgeyBTdG9yZSB9IGZyb20gJ3JlZHV4JztcbmltcG9ydCB7IEFzeW5jU3ViamVjdCwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJlZHV4U3RvcmUgfSBmcm9tICcuLi90b2tlbnMvcmVkdXgtc3RvcmUudG9rZW4nO1xuaW1wb3J0IHsgUmVkdXhBY3Rpb25XaXRoUGF5bG9hZCB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVkdXgtYWN0aW9uLXdpdGgtcGF5bG9hZC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVkdXhTdGF0ZVByb3ZpZGVyIH0gZnJvbSAnLi9yZWR1eC1zdGF0ZS5wcm92aWRlcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVJlZ2lzdGVyU3RhdGVQYXlsb2FkIHtcbiAgaW5pdGlhbFZhbHVlOiB7fTtcbiAgbmFtZTogc3RyaW5nO1xufVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgUmVkdXhSZWdpc3RyeSB7XG5cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBBQ1RJT05fUkVHSVNURVJfU1RBVEUgPSBgQGhhcm1vd2F0Y2gvbmd4LXJlZHV4LWNvcmUvcmVnaXN0ZXJTdGF0ZWA7XG5cbiAgcHJpdmF0ZSBzdGF0aWMgX3N0b3JlID0gbmV3IEFzeW5jU3ViamVjdDxTdG9yZTx7fT4+KCk7XG5cbiAgY29uc3RydWN0b3IoQEluamVjdChSZWR1eFN0b3JlKSBzdG9yZTogU3RvcmU8e30+ID0gbnVsbCkge1xuICAgIFJlZHV4UmVnaXN0cnkucmVzZXQoKTtcbiAgICBSZWR1eFJlZ2lzdHJ5LnJlZ2lzdGVyU3RvcmUoc3RvcmUpO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyByZXNldCgpIHtcbiAgICBSZWR1eFJlZ2lzdHJ5Ll9zdG9yZSA9IG5ldyBBc3luY1N1YmplY3Q8U3RvcmU8e30+PigpO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyByZWdpc3RlclN0b3JlKHN0b3JlOiBTdG9yZTx7fT4pIHtcbiAgICBSZWR1eFJlZ2lzdHJ5LnJlc2V0KCk7XG4gICAgUmVkdXhSZWdpc3RyeS5fc3RvcmUubmV4dChzdG9yZSk7XG4gICAgUmVkdXhSZWdpc3RyeS5fc3RvcmUuY29tcGxldGUoKTtcblxuICAgIFJlZHV4QWN0aW9uRGlzcGF0Y2hlci5kaXNwYXRjaGVkQWN0aW9ucy5zdWJzY3JpYmUoYWN0aW9uID0+IHtcblxuICAgICAgY29uc3QgcmVkdXhBY3Rpb246IFJlZHV4QWN0aW9uV2l0aFBheWxvYWQgPSB7XG4gICAgICAgIHR5cGU6IGFjdGlvbi50eXBlLFxuICAgICAgICBwYXlsb2FkOiBhY3Rpb24ucGF5bG9hZCxcbiAgICAgIH07XG5cbiAgICAgIHN0b3JlLmRpc3BhdGNoKHJlZHV4QWN0aW9uKTtcblxuICAgICAgaWYgKGFjdGlvbi5vbkRpc3BhdGNoU3VjY2Vzcykge1xuICAgICAgICBhY3Rpb24ub25EaXNwYXRjaFN1Y2Nlc3MoKTtcbiAgICAgIH1cblxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyByZWdpc3RlclN0YXRlKHN0YXRlOiBSZWR1eFN0YXRlUHJvdmlkZXIpIHtcbiAgICBSZWR1eFJlZ2lzdHJ5LmdldFN0b3JlKCkudGhlbigoc3RvcmUpID0+IHtcblxuICAgICAgY29uc3Qgc3RhdGVDb25maWcgPSBSZWR1eFN0YXRlRGVjb3JhdG9yLmdldChzdGF0ZS5jb25zdHJ1Y3Rvcik7XG4gICAgICBjb25zdCBpbml0aWFsU3RhdGUgPSBzdGF0ZS5nZXRJbml0aWFsU3RhdGUoKTtcblxuICAgICAgUHJvbWlzZVxuICAgICAgICAucmVzb2x2ZShpbml0aWFsU3RhdGUgaW5zdGFuY2VvZiBPYnNlcnZhYmxlID8gaW5pdGlhbFN0YXRlLnRvUHJvbWlzZSgpIDogaW5pdGlhbFN0YXRlKVxuICAgICAgICAudGhlbihpbml0aWFsVmFsdWUgPT4ge1xuICAgICAgICAgIHN0b3JlLmRpc3BhdGNoPFJlZHV4QWN0aW9uV2l0aFBheWxvYWQ8SVJlZ2lzdGVyU3RhdGVQYXlsb2FkPj4oe1xuICAgICAgICAgICAgcGF5bG9hZDoge1xuICAgICAgICAgICAgICBpbml0aWFsVmFsdWUsXG4gICAgICAgICAgICAgIG5hbWU6IHN0YXRlQ29uZmlnLm5hbWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdHlwZTogUmVkdXhSZWdpc3RyeS5BQ1RJT05fUkVHSVNURVJfU1RBVEUsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGdldFN0b3JlKCk6IFByb21pc2U8U3RvcmU8e30+PiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKFJlZHV4UmVnaXN0cnkuX3N0b3JlLnN1YnNjcmliZS5iaW5kKFJlZHV4UmVnaXN0cnkuX3N0b3JlKSk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgTmdab25lLCBUeXBlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSZXBsYXlTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBSZWR1eFN0YXRlRGVjb3JhdG9yIH0gZnJvbSAnQGhhcm1vd2F0Y2gvcmVkdXgtZGVjb3JhdG9ycyc7XG5cbmltcG9ydCB7IFJlZHV4UmVnaXN0cnkgfSBmcm9tICcuL3Byb3ZpZGVycy9yZWR1eC1yZWdpc3RyeSc7XG5pbXBvcnQgeyBSZWR1eFJvb3RTdGF0ZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZWR1eC1yb290LXN0YXRlLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZWR1eFN0YXRlUHJvdmlkZXIgfSBmcm9tICcuL3Byb3ZpZGVycy9yZWR1eC1zdGF0ZS5wcm92aWRlcic7XG5cbmV4cG9ydCBjbGFzcyBSZWR1eFNlbGVjdG9yPFQ+IGV4dGVuZHMgUmVwbGF5U3ViamVjdDxUPiB7XG5cbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgREVMSU1JVEVSID0gJy8nO1xuXG4gIGNvbnN0cnVjdG9yKHpvbmU6IE5nWm9uZSxcbiAgICAgICAgICAgICAgc2VsZWN0b3IgPSAnLycsXG4gICAgICAgICAgICAgIHN0YXRlUHJvdmlkZXI/OiBUeXBlPFJlZHV4U3RhdGVQcm92aWRlcj4pIHtcblxuICAgIGlmICghc2VsZWN0b3Iuc3RhcnRzV2l0aChSZWR1eFNlbGVjdG9yLkRFTElNSVRFUikgJiYgIXN0YXRlUHJvdmlkZXIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignWW91IG5lZWQgdG8gcHJvdmlkZSBhIHN0YXRlIHByb3ZpZGVyLCBpZiB5b3UgdXNlIHJlbGF0aXZlIHNlbGVjdG9ycycpO1xuICAgIH1cblxuICAgIHN1cGVyKDEpO1xuXG4gICAgUmVkdXhSZWdpc3RyeS5nZXRTdG9yZSgpLnRoZW4oc3RvcmUgPT4ge1xuICAgICAgY29uc3QgbmV4dCA9ICgpID0+IHtcbiAgICAgICAgem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgIHRoaXMubmV4dChSZWR1eFNlbGVjdG9yLmdldFZhbHVlQnlTdGF0ZShzdG9yZS5nZXRTdGF0ZSgpLCBzZWxlY3Rvciwgc3RhdGVQcm92aWRlcikpO1xuICAgICAgICB9KTtcbiAgICAgIH07XG5cbiAgICAgIHN0b3JlLnN1YnNjcmliZSgoKSA9PiBuZXh0KCkpO1xuICAgICAgbmV4dCgpOyAvLyB3ZSBuZWVkIHRvIHRyaWdnZXIgYSBpbml0aWFsIHZhbHVlLCBvdGhlcndpc2Ugd2UndmUgdG8gd2FpdCB1bnRpbCB0aGUgZmlyc3Qgc3RhdGUgY2hhbmdlXG4gICAgfSk7XG5cbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgbm9ybWFsaXplKHNlbGVjdG9yOiBzdHJpbmcsIHN0YXRlUHJvdmlkZXI/OiBUeXBlPFJlZHV4U3RhdGVQcm92aWRlcj4pOiBzdHJpbmcge1xuICAgIGlmICghc2VsZWN0b3Iuc3RhcnRzV2l0aChSZWR1eFNlbGVjdG9yLkRFTElNSVRFUikpIHtcbiAgICAgIGNvbnN0IHN0YXRlTmFtZSA9IFJlZHV4U3RhdGVEZWNvcmF0b3IuZ2V0KHN0YXRlUHJvdmlkZXIpLm5hbWU7XG4gICAgICByZXR1cm4gYCR7UmVkdXhTZWxlY3Rvci5ERUxJTUlURVJ9JHtzdGF0ZU5hbWV9JHtSZWR1eFNlbGVjdG9yLkRFTElNSVRFUn0ke3NlbGVjdG9yfWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbGVjdG9yO1xuICB9XG5cbiAgcHVibGljIHN0YXRpYyBnZXRWYWx1ZUJ5U3RhdGU8Uz4oc3RhdGU6IFJlZHV4Um9vdFN0YXRlPFM+LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3Rvcjogc3RyaW5nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZVByb3ZpZGVyPzogVHlwZTxSZWR1eFN0YXRlUHJvdmlkZXI+KTogUyB7XG5cbiAgICAvKiBzYXZlIHRoZSByZXR1cm4gdmFsdWUgaW4gYSBjb25zdGFudCB0byBwcmV2ZW50XG4gICAgICogXCJNZXRhZGF0YSBjb2xsZWN0ZWQgY29udGFpbnMgYW4gZXJyb3IgdGhhdCB3aWxsIGJlIHJlcG9ydGVkIGF0IHJ1bnRpbWU6IExhbWJkYSBub3Qgc3VwcG9ydGVkLlwiXG4gICAgICogZXJyb3JcbiAgICAgKi9cbiAgICBjb25zdCB2YWx1ZTogUyA9IFJlZHV4U2VsZWN0b3Iubm9ybWFsaXplKHNlbGVjdG9yLCBzdGF0ZVByb3ZpZGVyKS5zcGxpdChSZWR1eFNlbGVjdG9yLkRFTElNSVRFUilcbiAgICAgIC5maWx0ZXIocHJvcGVydHlLZXkgPT4gcHJvcGVydHlLZXkgIT09ICcnKVxuICAgICAgLnJlZHVjZSgocHJldmlvdXNWYWx1ZSwgcHJvcGVydHlLZXkpID0+IHtcbiAgICAgICAgaWYgKCFwcmV2aW91c1ZhbHVlIHx8ICFwcmV2aW91c1ZhbHVlLmhhc093blByb3BlcnR5KHByb3BlcnR5S2V5KSkge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHByZXZpb3VzVmFsdWVbIHByb3BlcnR5S2V5IF07XG4gICAgICB9LCBzdGF0ZSBhcyB7fSk7XG5cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGlzdGluY3RVbnRpbENoYW5nZWQgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBJbmplY3QsIE5nWm9uZSwgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUmVkdXhBY3Rpb25EaXNwYXRjaGVyLCBSZWR1eFJlZHVjZXJEZWNvcmF0b3IsIFJlZHV4U3RhdGVEZWNvcmF0b3IgfSBmcm9tICdAaGFybW93YXRjaC9yZWR1eC1kZWNvcmF0b3JzJztcblxuaW1wb3J0IHsgUmVkdXhTdGF0ZURlZmluaXRpb24gfSBmcm9tICcuLi9pbnRlcmZhY2VzL3JlZHV4LXN0YXRlLWRlZmluaXRpb24uaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlZHV4QWN0aW9uV2l0aFBheWxvYWQgfSBmcm9tICcuLi9pbnRlcmZhY2VzL3JlZHV4LWFjdGlvbi13aXRoLXBheWxvYWQuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlZHV4U3RhdGVEZWZpbml0aW9uVG9rZW4gfSBmcm9tICcuLi90b2tlbnMvcmVkdXgtc3RhdGUtZGVmaW5pdGlvbi50b2tlbic7XG5cbmltcG9ydCB7IFJlZHV4U2VsZWN0b3IgfSBmcm9tICcuLi9yZWR1eC1zZWxlY3Rvcic7XG5pbXBvcnQgeyBSZWR1eFJlZ2lzdHJ5IH0gZnJvbSAnLi9yZWR1eC1yZWdpc3RyeSc7XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSZWR1eFN0YXRlUHJvdmlkZXI8UyA9IHt9PiB7XG5cbiAgcHVibGljIHN0YXRpYyBpbnN0YW5jZXNCeU5hbWU6IHsgW3N0YXRlTmFtZTogc3RyaW5nXTogUmVkdXhTdGF0ZVByb3ZpZGVyIH0gPSB7fTtcblxuICBwdWJsaWMgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgc3RhdGVEZWY6IFJlZHV4U3RhdGVEZWZpbml0aW9uO1xuXG4gIHByb3RlY3RlZCBzZWxlY3RvckNhY2hlOiB7IFtzZWxlY3Rvcjogc3RyaW5nXTogT2JzZXJ2YWJsZTx7fT4gfSA9IHt9O1xuICBwcm90ZWN0ZWQgcmVkdWNlck1ldGhvZHNCeVR5cGU6IHsgW2FjdGlvblR5cGU6IHN0cmluZ106IEZ1bmN0aW9uW10gfTtcblxuICBjb25zdHJ1Y3RvcihASW5qZWN0KFJlZHV4U3RhdGVEZWZpbml0aW9uVG9rZW4pIHN0YXRlRGVmczogUmVkdXhTdGF0ZURlZmluaXRpb25bXSA9IFtdLFxuICAgICAgICAgICAgICBwcml2YXRlIHpvbmU6IE5nWm9uZSkge1xuXG4gICAgY29uc3Qge25hbWUgPSBudWxsfSA9IFJlZHV4U3RhdGVEZWNvcmF0b3IuZ2V0KHRoaXMuY29uc3RydWN0b3IpIHx8IHt9O1xuXG4gICAgaWYgKCFuYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdVbmFibGUgdG8gcmVzb2x2ZSBzdGF0ZSBuYW1lISBNYWtlIHN1cmUgeW91XFwndmUgZGVjb3JhdGVkIHRoZSBwcm92aWRlciBieSBcIkBSZWR1eFN0YXRlXCIhJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLm5hbWUgPSBSZWR1eFN0YXRlRGVjb3JhdG9yLmdldCh0aGlzLmNvbnN0cnVjdG9yKS5uYW1lO1xuICAgIHRoaXMuc3RhdGVEZWYgPSBzdGF0ZURlZnMuZmluZChkZWYgPT4gUmVkdXhTdGF0ZURlY29yYXRvci5nZXQoZGVmLnByb3ZpZGVyKS5uYW1lID09PSBuYW1lKTtcblxuICAgIGlmICghdGhpcy5zdGF0ZURlZikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnVW5hYmxlIHRvIHJlc29sdmUgc3RhdGUgZGVmaW5pdGlvbiEgTWFrZSBzdXJlIHlvdVxcJ3ZlIHJlZ2lzdGVyZWQgdGhlIHByb3ZpZGVyIHRvIFJlZHV4TW9kdWxlISdcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5yZWR1Y2VyTWV0aG9kc0J5VHlwZSA9ICh0aGlzLnN0YXRlRGVmLnJlZHVjZXJzIHx8IFtdKVxuICAgICAgLm1hcChjbGF6eiA9PiB0aGlzLmdldFJlZHVjZXJNZXRob2RzKG5ldyBjbGF6eigpKSlcbiAgICAgIC5yZWR1Y2UoKGFsbCwgY3VycikgPT4gW10uY29uY2F0KGN1cnIsIGFsbCksIFtdKSAvLyBbXS5jb25jYXQga2VlcHMgdGhlIG9yZGVyLCBhbGwuY29uY2F0KGN1cnIpIGRlc3Ryb3lzIHRoZSBvcmRlclxuICAgICAgLy8gLnJlZHVjZSgoYWxsLCBjdXJyKSA9PiBbY3VyciwgLi4uYWxsXSwgW10pIC8vIFtdLmNvbmNhdCBrZWVwcyB0aGUgb3JkZXIsIGFsbC5jb25jYXQoY3VycikgZGVzdHJveXMgdGhlIG9yZGVyXG4gICAgICAucmVkdWNlKChtZXRob2RzQnlUeXBlLCByZWR1Y2VyKSA9PiB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSBSZWR1eEFjdGlvbkRpc3BhdGNoZXIuZ2V0VHlwZShyZWR1Y2VyLnR5cGUpO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4ubWV0aG9kc0J5VHlwZSxcbiAgICAgICAgICBbIHR5cGUgXTogWyByZWR1Y2VyLm1ldGhvZCBdLmNvbmNhdChtZXRob2RzQnlUeXBlWyB0eXBlIF0gfHwgW10pXG4gICAgICAgIH07XG4gICAgICB9LCB7fSk7XG5cbiAgICBSZWR1eFN0YXRlUHJvdmlkZXIuaW5zdGFuY2VzQnlOYW1lWyB0aGlzLm5hbWUgXSA9IHRoaXM7XG4gIH1cblxuICBnZXRJbml0aWFsU3RhdGUoKTogUyB8IFByb21pc2U8Uz4gfCBPYnNlcnZhYmxlPFM+IHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBcImdldEluaXRpYWxTdGF0ZVwiIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgfVxuXG4gIHNlbGVjdDxUPihzZWxlY3RvciA9ICcnKTogT2JzZXJ2YWJsZTxUPiB7XG5cbiAgICBjb25zdCBzdGF0ZVR5cGUgPSB0aGlzLmNvbnN0cnVjdG9yIGFzIFR5cGU8UmVkdXhTdGF0ZVByb3ZpZGVyPFM+PjtcbiAgICBzZWxlY3RvciA9IFJlZHV4U2VsZWN0b3Iubm9ybWFsaXplKHNlbGVjdG9yLCBzdGF0ZVR5cGUpO1xuXG4gICAgaWYgKCF0aGlzLnNlbGVjdG9yQ2FjaGVbIHNlbGVjdG9yIF0pIHtcbiAgICAgIHRoaXMuc2VsZWN0b3JDYWNoZVsgc2VsZWN0b3IgXSA9IG5ldyBSZWR1eFNlbGVjdG9yPFQ+KHRoaXMuem9uZSwgc2VsZWN0b3IsIHN0YXRlVHlwZSkucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zZWxlY3RvckNhY2hlWyBzZWxlY3RvciBdIGFzIFJlZHV4U2VsZWN0b3I8VD47XG4gIH1cblxuICBnZXRTdGF0ZSgpOiBQcm9taXNlPFM+IHtcbiAgICByZXR1cm4gUmVkdXhSZWdpc3RyeS5nZXRTdG9yZSgpLnRoZW4oc3RvcmUgPT4ge1xuICAgICAgcmV0dXJuIFJlZHV4U2VsZWN0b3IuZ2V0VmFsdWVCeVN0YXRlPFM+KHN0b3JlLmdldFN0YXRlKCksICcvJyArIHRoaXMubmFtZSk7XG4gICAgfSk7XG4gIH1cblxuICByZWR1Y2U8UD4oc3RhdGU6IFMsIGFjdGlvbjogUmVkdXhBY3Rpb25XaXRoUGF5bG9hZDxQPik6IFMge1xuICAgIGNvbnN0IHJlZHVjZXJNZXRob2RzID0gdGhpcy5yZWR1Y2VyTWV0aG9kc0J5VHlwZVsgYWN0aW9uLnR5cGUgXSB8fCBbXTtcbiAgICByZXR1cm4gcmVkdWNlck1ldGhvZHMucmVkdWNlKChzdGF0ZVRvUmVkdWNlLCBtZXRob2QpID0+IG1ldGhvZChzdGF0ZVRvUmVkdWNlLCBhY3Rpb24pLCBzdGF0ZSk7XG4gIH1cblxuICBwcml2YXRlIGdldFJlZHVjZXJNZXRob2RzKHJlZHVjZXJDbGFzc0luc3RhbmNlOiBhbnkpIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhPYmplY3QuZ2V0UHJvdG90eXBlT2YocmVkdWNlckNsYXNzSW5zdGFuY2UpKVxuICAgICAgLm1hcChtZXRob2QgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG1ldGhvZDogKG1ldGhvZCBhcyBGdW5jdGlvbikuYmluZChyZWR1Y2VyQ2xhc3NJbnN0YW5jZSksXG4gICAgICAgICAgdHlwZTogUmVkdXhSZWR1Y2VyRGVjb3JhdG9yLmdldChtZXRob2QpLFxuICAgICAgICB9O1xuICAgICAgfSlcbiAgICAgIC5maWx0ZXIocmVkdWNlciA9PiByZWR1Y2VyICYmIHJlZHVjZXIudHlwZSlcbiAgICAgIC8vIGNvbnZlcnQgYXJyYXkgb2YgdHlwZXMgdG8gbXVsdGlwbGUgbWV0aG9kIGVudHJpZXNcbiAgICAgIC5yZWR1Y2UoKGFsbCwgY3VycikgPT4gYWxsLmNvbmNhdChbXS5jb25jYXQoY3Vyci50eXBlKS5tYXAodHlwZSA9PiAoey4uLmN1cnIsIHR5cGV9KSkpLCBbXSk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUmVkdXhTdGF0ZURlY29yYXRvciB9IGZyb20gJ0BoYXJtb3dhdGNoL3JlZHV4LWRlY29yYXRvcnMnO1xuXG5pbXBvcnQgeyBSZWR1eFN0YXRlUHJvdmlkZXIgfSBmcm9tICcuLi9wcm92aWRlcnMvcmVkdXgtc3RhdGUucHJvdmlkZXInO1xuXG5leHBvcnQgZnVuY3Rpb24gUmVkdXhTZWxlY3Q8UyA9IHt9PihleHByZXNzaW9uOiBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0PzogVHlwZTxSZWR1eFN0YXRlUHJvdmlkZXI+KTogUHJvcGVydHlEZWNvcmF0b3Ige1xuXG4gIHJldHVybiAodGFyZ2V0OiB7fSwgcHJvcGVydHlLZXk6IHN0cmluZykgPT4ge1xuICAgIGNvbnN0IHN0YXRlTmFtZSA9IFJlZHV4U3RhdGVEZWNvcmF0b3IuZ2V0KGNvbnRleHQpLm5hbWU7XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBwcm9wZXJ0eUtleSwge1xuICAgICAgZ2V0OiAoKSA9PiBSZWR1eFN0YXRlUHJvdmlkZXIuaW5zdGFuY2VzQnlOYW1lWyBzdGF0ZU5hbWUgXS5zZWxlY3QoZXhwcmVzc2lvbilcbiAgICB9KTtcblxuICB9O1xufVxuIiwiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBSZWR1Y2VyIH0gZnJvbSAncmVkdXgnO1xuaW1wb3J0IHsgUmVkdXhTdGF0ZVByb3ZpZGVyIH0gZnJvbSAnLi9yZWR1eC1zdGF0ZS5wcm92aWRlcic7XG5pbXBvcnQgeyBJUmVnaXN0ZXJTdGF0ZVBheWxvYWQsIFJlZHV4UmVnaXN0cnkgfSBmcm9tICcuL3JlZHV4LXJlZ2lzdHJ5JztcbmltcG9ydCB7IFJlZHV4Um9vdFN0YXRlIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZWR1eC1yb290LXN0YXRlLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZWR1eEFjdGlvbldpdGhQYXlsb2FkIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZWR1eC1hY3Rpb24td2l0aC1wYXlsb2FkLmludGVyZmFjZSc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBSZWR1eFJlZHVjZXJQcm92aWRlciB7XG5cbiAgcHJpdmF0ZSBzdGF0ZVByb3ZpZGVyczoge1xuICAgIFtuYW1lOiBzdHJpbmddOiBSZWR1eFN0YXRlUHJvdmlkZXIsXG4gIH0gPSB7fTtcblxuICBwdWJsaWMgZ2V0IHJvb3RSZWR1Y2VyKCk6IFJlZHVjZXI8UmVkdXhSb290U3RhdGU+IHtcbiAgICByZXR1cm4gdGhpcy5yZWR1Y2UuYmluZCh0aGlzKTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRTdGF0ZVByb3ZpZGVyKHByb3ZpZGVyOiBSZWR1eFN0YXRlUHJvdmlkZXIpIHtcbiAgICBpZiAoIXRoaXMuc3RhdGVQcm92aWRlcnNbIHByb3ZpZGVyLm5hbWUgXSkge1xuICAgICAgUmVkdXhSZWdpc3RyeS5yZWdpc3RlclN0YXRlKHByb3ZpZGVyKTtcbiAgICAgIHRoaXMuc3RhdGVQcm92aWRlcnNbIHByb3ZpZGVyLm5hbWUgXSA9IHByb3ZpZGVyO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFN0YXRlIFwiJHtwcm92aWRlci5uYW1lfVwiIGlzIHJlZ2lzdGVyZWQgdHdpY2UhIE1ha2Ugc3VyZSB5b3VyIHN0YXRlIG5hbWUgaXMgdW5pcXVlIWApO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyByZWR1Y2Uocm9vdFN0YXRlOiBSZWR1eFJvb3RTdGF0ZSwgYWN0aW9uOiBSZWR1eEFjdGlvbldpdGhQYXlsb2FkPGFueT4pOiBSZWR1eFJvb3RTdGF0ZSB7XG5cbiAgICBpZiAoYWN0aW9uLnR5cGUgPT09IFJlZHV4UmVnaXN0cnkuQUNUSU9OX1JFR0lTVEVSX1NUQVRFKSB7XG4gICAgICBjb25zdCByZWdBY3Rpb24gPSAoYWN0aW9uIGFzIHt9IGFzIFJlZHV4QWN0aW9uV2l0aFBheWxvYWQ8SVJlZ2lzdGVyU3RhdGVQYXlsb2FkPik7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnJvb3RTdGF0ZSxcbiAgICAgICAgWyByZWdBY3Rpb24ucGF5bG9hZC5uYW1lIF06IHJlZ0FjdGlvbi5wYXlsb2FkLmluaXRpYWxWYWx1ZSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5zdGF0ZVByb3ZpZGVycykucmVkdWNlKChzdGF0ZVRvUmVkdWNlLCBwcm92aWRlcikgPT4ge1xuICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIHN0YXRlVG9SZWR1Y2UsIHtcbiAgICAgICAgWyBwcm92aWRlci5uYW1lIF06IHByb3ZpZGVyLnJlZHVjZShzdGF0ZVRvUmVkdWNlWyBwcm92aWRlci5uYW1lIF0sIGFjdGlvbiksXG4gICAgICB9KTtcbiAgICB9LCByb290U3RhdGUpO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEluamVjdCwgSW5qZWN0b3IsIFBpcGUsIFBpcGVUcmFuc2Zvcm0gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgUmVkdXhTdGF0ZVByb3ZpZGVyIH0gZnJvbSAnLi4vcHJvdmlkZXJzL3JlZHV4LXN0YXRlLnByb3ZpZGVyJztcbmltcG9ydCB7IFJlZHV4U3RhdGVEZWZpbml0aW9uVG9rZW4gfSBmcm9tICcuLi90b2tlbnMvcmVkdXgtc3RhdGUtZGVmaW5pdGlvbi50b2tlbic7XG5pbXBvcnQgeyBSZWR1eFN0YXRlRGVmaW5pdGlvbiB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVkdXgtc3RhdGUtZGVmaW5pdGlvbi5pbnRlcmZhY2UnO1xuXG5AUGlwZSh7bmFtZTogJ3JlZHV4U2VsZWN0J30pXG5leHBvcnQgY2xhc3MgUmVkdXhTZWxlY3RQaXBlIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSB7XG5cbiAgcHJpdmF0ZSBwcm92aWRlcjogUmVkdXhTdGF0ZVByb3ZpZGVyO1xuXG4gIGNvbnN0cnVjdG9yKEBJbmplY3QoUmVkdXhTdGF0ZURlZmluaXRpb25Ub2tlbikgc3RhdGVEZWZzOiBSZWR1eFN0YXRlRGVmaW5pdGlvbltdID0gW10sIGluamVjdG9yOiBJbmplY3Rvcikge1xuICAgIHRoaXMucHJvdmlkZXIgPSBpbmplY3Rvci5nZXQoc3RhdGVEZWZzWyAwIF0ucHJvdmlkZXIpIGFzIFJlZHV4U3RhdGVQcm92aWRlcjtcbiAgfVxuXG4gIHRyYW5zZm9ybShzZWxlY3Rvcjogc3RyaW5nKTogT2JzZXJ2YWJsZTx7fT4ge1xuICAgIHJldHVybiB0aGlzLnByb3ZpZGVyLnNlbGVjdChzZWxlY3Rvcik7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgQWN0aW9uLCBTdG9yZSwgVW5zdWJzY3JpYmUgfSBmcm9tICdyZWR1eCc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VXaGlsZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEluamVjdGFibGUsIFR5cGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJlZHV4Um9vdFN0YXRlIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZWR1eC1yb290LXN0YXRlLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZWR1eFN0YXRlRGVjb3JhdG9yIH0gZnJvbSAnQGhhcm1vd2F0Y2gvcmVkdXgtZGVjb3JhdG9ycyc7XG5pbXBvcnQgeyBSZWR1eFN0YXRlUHJvdmlkZXIgfSBmcm9tICcuLi9wcm92aWRlcnMvcmVkdXgtc3RhdGUucHJvdmlkZXInO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgUmVkdXhUZXN0aW5nU3RvcmUgaW1wbGVtZW50cyBTdG9yZTx7fT4ge1xuXG4gIHByaXZhdGUgc3RhdGUgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KG51bGwpO1xuXG4gIHB1YmxpYyBzdGF0aWMgZmFjdG9yeSgpOiBSZWR1eFRlc3RpbmdTdG9yZSB7XG4gICAgcmV0dXJuIG5ldyBSZWR1eFRlc3RpbmdTdG9yZSgpO1xuICB9XG5cbiAgcHVibGljIHNldFN0YXRlPFM+KHN0YXRlOiBUeXBlPFJlZHV4U3RhdGVQcm92aWRlcj4sIHZhbHVlOiBTKTogUHJvbWlzZTxSZWR1eFJvb3RTdGF0ZT4ge1xuICAgIGNvbnN0IHtuYW1lfSA9IFJlZHV4U3RhdGVEZWNvcmF0b3IuZ2V0KHN0YXRlKTtcblxuICAgIGNvbnN0IG5leHRTdGF0ZSA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuc3RhdGUuZ2V0VmFsdWUoKSwge1xuICAgICAgWyBuYW1lIF06IHZhbHVlLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zdGF0ZS5uZXh0KG5leHRTdGF0ZSk7XG5cbiAgICByZXR1cm4gdGhpcy5zdGF0ZVxuICAgICAgLnBpcGUodGFrZVdoaWxlKGN1cnJlbnRTdGF0ZSA9PiBjdXJyZW50U3RhdGUgIT09IG5leHRTdGF0ZSkpXG4gICAgICAudG9Qcm9taXNlKCkudGhlbigoKSA9PiB0aGlzLnN0YXRlLmdldFZhbHVlKCkpO1xuICB9XG5cbiAgcHVibGljIGdldFN0YXRlKCk6IHt9IHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5nZXRWYWx1ZSgpO1xuICB9XG5cbiAgcHVibGljIHN1YnNjcmliZShsaXN0ZW5lcjogKCkgPT4gdm9pZCk6IFVuc3Vic2NyaWJlIHtcbiAgICByZXR1cm4gdGhpcy5zdGF0ZS5zdWJzY3JpYmUuY2FsbCh0aGlzLnN0YXRlLCBsaXN0ZW5lcik7XG4gIH1cblxuICBwdWJsaWMgcmVwbGFjZVJlZHVjZXIoKSB7XG4gIH1cblxuICBwdWJsaWMgZGlzcGF0Y2g8VCBleHRlbmRzIEFjdGlvbj4oYWN0aW9uOiBUKTogVCB7XG4gICAgcmV0dXJuIGFjdGlvbjtcbiAgfVxuXG59XG4iLCJpbXBvcnQgeyBSZWR1eFN0YXRlIH0gZnJvbSAnLi4vZGVjb3JhdG9ycy9pbmRleCc7XG5pbXBvcnQgeyBSZWR1eFN0YXRlUHJvdmlkZXIgfSBmcm9tICcuLi9wcm92aWRlcnMvcmVkdXgtc3RhdGUucHJvdmlkZXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIFRlc3RpbmdTdGF0ZSB7XG4gIHRvZG86IHtcbiAgICBpc0ZldGNoaW5nOiBib29sZWFuO1xuICAgIGl0ZW1zOiBzdHJpbmdbXTtcbiAgfTtcbn1cblxuQFJlZHV4U3RhdGUoe25hbWU6IFRlc3RpbmdTdGF0ZVByb3ZpZGVyLk5BTUV9KVxuZXhwb3J0IGNsYXNzIFRlc3RpbmdTdGF0ZVByb3ZpZGVyIGV4dGVuZHMgUmVkdXhTdGF0ZVByb3ZpZGVyPFRlc3RpbmdTdGF0ZT4ge1xuXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgTkFNRSA9ICd0ZXN0aW5nLTdjNjZiNjEzLTIwYmQtNGQzNS04NjExLTUxODFjYTRhMGI3Mic7XG5cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBJTklUSUFMX1NUQVRFOiBUZXN0aW5nU3RhdGUgPSB7XG4gICAgdG9kbzoge1xuICAgICAgaXNGZXRjaGluZzogZmFsc2UsXG4gICAgICBpdGVtczogWyAnSXRlbSAxJywgJ0l0ZW0gMicgXSxcbiAgICB9LFxuICB9O1xuXG4gIGdldEluaXRpYWxTdGF0ZSgpOiBUZXN0aW5nU3RhdGUge1xuICAgIHJldHVybiBUZXN0aW5nU3RhdGVQcm92aWRlci5JTklUSUFMX1NUQVRFO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IEluamVjdGlvblRva2VuIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmV4cG9ydCBjbGFzcyBSZWR1eE1pZGRsZXdhcmVzIGV4dGVuZHMgSW5qZWN0aW9uVG9rZW48RnVuY3Rpb25bXT4ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKCdSZWR1eE1pZGRsZXdhcmVzJyk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgYXBwbHlNaWRkbGV3YXJlLCBjb21wb3NlLCBjcmVhdGVTdG9yZSwgTWlkZGxld2FyZSwgU3RvcmUsIFN0b3JlRW5oYW5jZXIgfSBmcm9tICdyZWR1eCc7XG5cbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBJbmplY3QsIEluamVjdG9yLCBpc0Rldk1vZGUsIE1vZHVsZVdpdGhQcm92aWRlcnMsIE5nTW9kdWxlLCBPcHRpb25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUmVkdXhTZWxlY3RQaXBlIH0gZnJvbSAnLi9waXBlcy9yZWR1eC1zZWxlY3QucGlwZSc7XG5pbXBvcnQgeyBSZWR1eFJlZHVjZXJQcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL3JlZHV4LXJlZHVjZXIucHJvdmlkZXInO1xuaW1wb3J0IHsgUmVkdXhTdGF0ZURlZmluaXRpb25Ub2tlbiB9IGZyb20gJy4vdG9rZW5zL3JlZHV4LXN0YXRlLWRlZmluaXRpb24udG9rZW4nO1xuaW1wb3J0IHsgUmVkdXhTdGF0ZURlZmluaXRpb24gfSBmcm9tICcuL2ludGVyZmFjZXMvcmVkdXgtc3RhdGUtZGVmaW5pdGlvbi5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVkdXhSZWdpc3RyeSB9IGZyb20gJy4vcHJvdmlkZXJzL3JlZHV4LXJlZ2lzdHJ5JztcbmltcG9ydCB7IFJlZHV4Q2hpbGRNb2R1bGVDb25maWcgfSBmcm9tICcuL2ludGVyZmFjZXMvcmVkdXgtY2hpbGQtbW9kdWxlLWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVkdXhSb290TW9kdWxlQ29uZmlnIH0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlZHV4LXJvb3QtbW9kdWxlLWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVkdXhTdG9yZSB9IGZyb20gJy4vdG9rZW5zL3JlZHV4LXN0b3JlLnRva2VuJztcbmltcG9ydCB7IFJlZHV4TWlkZGxld2FyZXMgfSBmcm9tICcuL3Rva2Vucy9yZWR1eC1taWRkbGV3YXJlcy50b2tlbic7XG5cbkBOZ01vZHVsZSh7XG4gIGRlY2xhcmF0aW9uczogW1xuICAgIFJlZHV4U2VsZWN0UGlwZSxcbiAgXSxcbiAgZXhwb3J0czogW1xuICAgIFJlZHV4U2VsZWN0UGlwZSxcbiAgXSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgUmVkdXhNb2R1bGUge1xuXG4gIGNvbnN0cnVjdG9yKGluamVjdG9yOiBJbmplY3RvcixcbiAgICAgICAgICAgICAgcmVkdWNlclByb3ZpZGVyOiBSZWR1eFJlZHVjZXJQcm92aWRlcixcbiAgICAgICAgICAgICAgQE9wdGlvbmFsKCkgQEluamVjdChSZWR1eFN0YXRlRGVmaW5pdGlvblRva2VuKSBzdGF0ZURlZnM6IFJlZHV4U3RhdGVEZWZpbml0aW9uW10gPSBbXSkge1xuXG4gICAgaW5qZWN0b3IuZ2V0KFJlZHV4UmVnaXN0cnkpOyAvLyBqdXN0IG1ha2Ugc3VyZSB0aGUgcHJvdmlkZXIgaXMgaW5zdGFudGlhdGVkXG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShzdGF0ZURlZnMpKSB7XG4gICAgICBzdGF0ZURlZnNcbiAgICAgICAgLmZpbHRlcihkZWYgPT4gZGVmICYmIGRlZi5wcm92aWRlcilcbiAgICAgICAgLm1hcChkZWYgPT4gaW5qZWN0b3IuZ2V0KGRlZi5wcm92aWRlcikpXG4gICAgICAgIC5mb3JFYWNoKHByb3ZpZGVyID0+IHJlZHVjZXJQcm92aWRlci5hZGRTdGF0ZVByb3ZpZGVyKHByb3ZpZGVyKSk7XG4gICAgfVxuXG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGZvckNoaWxkPFMgPSB7fT4oY29uZmlnOiBSZWR1eENoaWxkTW9kdWxlQ29uZmlnPFM+ID0ge30pOiBNb2R1bGVXaXRoUHJvdmlkZXJzIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmdNb2R1bGU6IFJlZHV4TW9kdWxlLFxuICAgICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHtwcm92aWRlOiBSZWR1eFN0YXRlRGVmaW5pdGlvblRva2VuLCB1c2VWYWx1ZTogY29uZmlnLnN0YXRlIHx8IG51bGwsIG11bHRpOiB0cnVlfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZm9yUm9vdDxTID0ge30+KGNvbmZpZzogUmVkdXhSb290TW9kdWxlQ29uZmlnPFM+ID0ge30pOiBNb2R1bGVXaXRoUHJvdmlkZXJzIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmdNb2R1bGU6IFJlZHV4TW9kdWxlLFxuICAgICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIFJlZHV4UmVkdWNlclByb3ZpZGVyLFxuICAgICAgICBSZWR1eFJlZ2lzdHJ5LFxuICAgICAgICB7XG4gICAgICAgICAgcHJvdmlkZTogUmVkdXhTdG9yZSxcbiAgICAgICAgICB1c2VGYWN0b3J5OiBjb25maWcuc3RvcmVGYWN0b3J5IHx8IFJlZHV4TW9kdWxlLmRlZmF1bHRTdG9yZUZhY3RvcnksXG4gICAgICAgICAgZGVwczogW1JlZHV4UmVkdWNlclByb3ZpZGVyLCBSZWR1eE1pZGRsZXdhcmVzXVxuICAgICAgICB9LFxuICAgICAgICB7cHJvdmlkZTogUmVkdXhTdGF0ZURlZmluaXRpb25Ub2tlbiwgdXNlVmFsdWU6IGNvbmZpZy5zdGF0ZSB8fCBudWxsLCBtdWx0aTogdHJ1ZX0sXG4gICAgICAgIHtwcm92aWRlOiBSZWR1eE1pZGRsZXdhcmVzLCB1c2VWYWx1ZTogY29uZmlnLm1pZGRsZXdhcmVGdW5jdGlvbnMgfHwgW10sIG11bHRpOiBmYWxzZX0sXG4gICAgICBdLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGRlZmF1bHRTdG9yZUZhY3RvcnkocmVkdXhSZWR1Y2VyUHJvdmlkZXI6IFJlZHV4UmVkdWNlclByb3ZpZGVyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlkZGxld2FyZUZ1bmN0aW9uczogTWlkZGxld2FyZVtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2TW9kZSA9IGlzRGV2TW9kZSgpKTogU3RvcmU8e30+IHtcblxuICAgIHJldHVybiBjcmVhdGVTdG9yZShcbiAgICAgIHJlZHV4UmVkdWNlclByb3ZpZGVyLnJvb3RSZWR1Y2VyLFxuICAgICAge30sXG4gICAgICBSZWR1eE1vZHVsZS5kZWZhdWx0RW5oYW5jZXJGYWN0b3J5KG1pZGRsZXdhcmVGdW5jdGlvbnMsIGRldk1vZGUpLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGRlZmF1bHRFbmhhbmNlckZhY3RvcnkobWlkZGxld2FyZUZ1bmN0aW9uczogTWlkZGxld2FyZVtdLCBkZXZNb2RlOiBib29sZWFuKTogU3RvcmVFbmhhbmNlcjx7fT4ge1xuXG4gICAgbGV0IGNvbXBvc2VFbmhhbmNlcnMgPSBjb21wb3NlO1xuXG4gICAgaWYgKGRldk1vZGUgJiYgd2luZG93WydfX1JFRFVYX0RFVlRPT0xTX0VYVEVOU0lPTl9DT01QT1NFX18nXSkge1xuICAgICAgY29tcG9zZUVuaGFuY2VycyA9IHdpbmRvd1snX19SRURVWF9ERVZUT09MU19FWFRFTlNJT05fQ09NUE9TRV9fJ107XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbXBvc2VFbmhhbmNlcnMoYXBwbHlNaWRkbGV3YXJlKC4uLm1pZGRsZXdhcmVGdW5jdGlvbnMpKTtcbiAgfVxuXG59XG4iLCJleHBvcnQgKiBmcm9tICcuL2ludGVyZmFjZXMvcmVkdXgtYWN0aW9uLXdpdGgtcGF5bG9hZC5pbnRlcmZhY2UnO1xuXG5leHBvcnQgKiBmcm9tICcuL2RlY29yYXRvcnMnO1xuZXhwb3J0ICogZnJvbSAnLi9pbnRlcmZhY2VzL3JlZHV4LWNoaWxkLW1vZHVsZS1jb25maWcuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vaW50ZXJmYWNlcy9yZWR1eC1yb290LW1vZHVsZS1jb25maWcuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vaW50ZXJmYWNlcy9yZWR1eC1yb290LXN0YXRlLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL3Byb3ZpZGVycy9yZWR1eC1yZWR1Y2VyLnByb3ZpZGVyJztcbmV4cG9ydCAqIGZyb20gJy4vZGVjb3JhdG9ycy9yZWR1eC1zZWxlY3QuZGVjb3JhdG9yJztcbmV4cG9ydCAqIGZyb20gJy4vcGlwZXMvcmVkdXgtc2VsZWN0LnBpcGUnO1xuZXhwb3J0ICogZnJvbSAnLi9yZWR1eC1zZWxlY3Rvcic7XG5leHBvcnQgKiBmcm9tICcuL3Rva2Vucy9yZWR1eC1zdGF0ZS1kZWZpbml0aW9uLnRva2VuJztcbmV4cG9ydCAqIGZyb20gJy4vaW50ZXJmYWNlcy9yZWR1eC1zdGF0ZS1kZWZpbml0aW9uLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL3Byb3ZpZGVycy9yZWR1eC1zdGF0ZS5wcm92aWRlcic7XG5leHBvcnQgKiBmcm9tICcuL3Rva2Vucy9yZWR1eC1zdG9yZS50b2tlbic7XG5leHBvcnQgKiBmcm9tICcuL3Rlc3Rpbmcvc3RvcmUnO1xuZXhwb3J0ICogZnJvbSAnLi90ZXN0aW5nL3N0YXRlJztcbmV4cG9ydCAqIGZyb20gJy4vcHJvdmlkZXJzL3JlZHV4LXJlZ2lzdHJ5JztcblxuZXhwb3J0IHsgUmVkdXhNb2R1bGUgfSBmcm9tICcuL3JlZHV4Lm1vZHVsZSc7XG5pbXBvcnQgeyBSZWR1eEFjdGlvbkRpc3BhdGNoZXIgfSBmcm9tICdAaGFybW93YXRjaC9yZWR1eC1kZWNvcmF0b3JzJztcblxuZXhwb3J0IGNvbnN0IGdldEFjdGlvblR5cGUgPSBSZWR1eEFjdGlvbkRpc3BhdGNoZXIuZ2V0VHlwZTtcbmV4cG9ydCBjb25zdCBkaXNwYXRjaCA9IFJlZHV4QWN0aW9uRGlzcGF0Y2hlci5kaXNwYXRjaDtcbiJdLCJuYW1lcyI6WyJ0c2xpYl8xLl9fZXh0ZW5kcyIsIlJlZHV4U3RhdGUiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7SUFHQTtJQUErQ0EsNkNBQXlCO0lBRXRFO2VBQ0Usa0JBQU0sMkJBQTJCLENBQUM7S0FDbkM7b0NBUEg7RUFHK0MsY0FBYyxFQU01RDs7Ozs7O0lDTkQ7SUFBZ0NBLDhCQUF5QjtJQUV2RDtlQUNFLGtCQUFNLFlBQVksQ0FBQztLQUNwQjtxQkFQSDtFQUdnQyxjQUFjLEVBTTdDOzs7Ozs7QUNURDtJQXNCRSx1QkFBZ0MsS0FBdUI7UUFBM0Msc0JBQUEsRUFBQSxZQUEyQztRQUNyRCxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDdEIsYUFBYSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztLQUNwQzs7OztJQUVhLG1CQUFLOzs7O1FBQ2pCLGFBQWEsQ0FBQyxNQUFNLEdBQUcsSUFBSSxZQUFZLEVBQWEsQ0FBQzs7Ozs7O0lBR3pDLDJCQUFhOzs7O2NBQUMsS0FBZ0I7UUFDMUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3RCLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pDLGFBQWEsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFaEMscUJBQXFCLENBQUMsaUJ