@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)
578 lines (561 loc) • 57 kB
JavaScript
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 { __decorate } from 'tslib';
import { applyMiddleware, compose, createStore } from 'redux';
import { CommonModule } from '@angular/common';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class ReduxStateDefinitionToken extends InjectionToken {
constructor() {
super('ReduxStateDefinitionToken');
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class ReduxStore extends InjectionToken {
constructor() {
super('ReduxStore');
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class ReduxRegistry {
/**
* @param {?=} store
*/
constructor(store = null) {
ReduxRegistry.reset();
ReduxRegistry.registerStore(store);
}
/**
* @return {?}
*/
static reset() {
ReduxRegistry._store = new AsyncSubject();
}
/**
* @param {?} store
* @return {?}
*/
static registerStore(store) {
ReduxRegistry.reset();
ReduxRegistry._store.next(store);
ReduxRegistry._store.complete();
ReduxActionDispatcher.dispatchedActions.subscribe(action => {
/** @type {?} */
const reduxAction = {
type: action.type,
payload: action.payload,
};
store.dispatch(reduxAction);
if (action.onDispatchSuccess) {
action.onDispatchSuccess();
}
});
}
/**
* @param {?} state
* @return {?}
*/
static registerState(state) {
ReduxRegistry.getStore().then((store) => {
/** @type {?} */
const stateConfig = ReduxStateDecorator.get(state.constructor);
/** @type {?} */
const initialState = state.getInitialState();
Promise
.resolve(initialState instanceof Observable ? initialState.toPromise() : initialState)
.then(initialValue => {
store.dispatch({
payload: {
initialValue,
name: stateConfig.name,
},
type: ReduxRegistry.ACTION_REGISTER_STATE,
});
});
});
}
/**
* @return {?}
*/
static getStore() {
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 = () => [
{ type: undefined, decorators: [{ type: Inject, args: [ReduxStore,] }] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @template T
*/
class ReduxSelector extends ReplaySubject {
/**
* @param {?} zone
* @param {?=} selector
* @param {?=} stateProvider
*/
constructor(zone, selector = '/', stateProvider) {
if (!selector.startsWith(ReduxSelector.DELIMITER) && !stateProvider) {
throw new Error('You need to provide a state provider, if you use relative selectors');
}
super(1);
ReduxRegistry.getStore().then(store => {
/** @type {?} */
const next = () => {
zone.run(() => {
this.next(ReduxSelector.getValueByState(store.getState(), selector, stateProvider));
});
};
store.subscribe(() => next());
next(); // we need to trigger a initial value, otherwise we've to wait until the first state change
});
}
/**
* @param {?} selector
* @param {?=} stateProvider
* @return {?}
*/
static normalize(selector, stateProvider) {
if (!selector.startsWith(ReduxSelector.DELIMITER)) {
/** @type {?} */
const stateName = ReduxStateDecorator.get(stateProvider).name;
return `${ReduxSelector.DELIMITER}${stateName}${ReduxSelector.DELIMITER}${selector}`;
}
return selector;
}
/**
* @template S
* @param {?} state
* @param {?} selector
* @param {?=} stateProvider
* @return {?}
*/
static getValueByState(state, selector, stateProvider) {
/** @type {?} */
const value = ReduxSelector.normalize(selector, stateProvider).split(ReduxSelector.DELIMITER)
.filter(propertyKey => propertyKey !== '')
.reduce((previousValue, propertyKey) => {
if (!previousValue || !previousValue.hasOwnProperty(propertyKey)) {
return null;
}
return previousValue[propertyKey];
}, /** @type {?} */ (state));
return value;
}
}
ReduxSelector.DELIMITER = '/';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @abstract
* @template S
*/
class ReduxStateProvider {
/**
* @param {?=} stateDefs
* @param {?=} zone
*/
constructor(stateDefs = [], zone) {
this.zone = zone;
this.selectorCache = {};
const { name = null } = ReduxStateDecorator.get(this.constructor) || {};
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(def => 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(clazz => this.getReducerMethods(new clazz()))
.reduce((all, curr) => [].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((methodsByType, reducer) => {
/** @type {?} */
const type = ReduxActionDispatcher.getType(reducer.type);
return Object.assign({}, methodsByType, { [type]: [reducer.method].concat(methodsByType[type] || []) });
}, {});
ReduxStateProvider.instancesByName[this.name] = this;
}
/**
* @return {?}
*/
getInitialState() {
throw new Error('Method "getInitialState" not implemented.');
}
/**
* @template T
* @param {?=} selector
* @return {?}
*/
select(selector = '') {
/** @type {?} */
const 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 {?}
*/
getState() {
return ReduxRegistry.getStore().then(store => {
return ReduxSelector.getValueByState(store.getState(), '/' + this.name);
});
}
/**
* @template P
* @param {?} state
* @param {?} action
* @return {?}
*/
reduce(state, action) {
/** @type {?} */
const reducerMethods = this.reducerMethodsByType[action.type] || [];
return reducerMethods.reduce((stateToReduce, method) => method(stateToReduce, action), state);
}
/**
* @param {?} reducerClassInstance
* @return {?}
*/
getReducerMethods(reducerClassInstance) {
return Object.values(Object.getPrototypeOf(reducerClassInstance))
.map(method => {
return {
method: (/** @type {?} */ (method)).bind(reducerClassInstance),
type: ReduxReducerDecorator.get(method),
};
})
.filter(reducer => reducer && reducer.type)
// convert array of types to multiple method entries
.reduce((all, curr) => all.concat([].concat(curr.type).map(type => (Object.assign({}, curr, { type })))), []);
}
}
ReduxStateProvider.instancesByName = {};
/** @nocollapse */
ReduxStateProvider.ctorParameters = () => [
{ type: Array, decorators: [{ type: Inject, args: [ReduxStateDefinitionToken,] }] },
{ type: NgZone }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @template S
* @param {?} expression
* @param {?=} context
* @return {?}
*/
function ReduxSelect(expression, context) {
return (target, propertyKey) => {
/** @type {?} */
const stateName = ReduxStateDecorator.get(context).name;
Object.defineProperty(target, propertyKey, {
get: () => 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
*/
class ReduxReducerProvider {
constructor() {
this.stateProviders = {};
}
/**
* @return {?}
*/
get rootReducer() {
return this.reduce.bind(this);
}
/**
* @param {?} provider
* @return {?}
*/
addStateProvider(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 {?}
*/
reduce(rootState, action) {
if (action.type === ReduxRegistry.ACTION_REGISTER_STATE) {
/** @type {?} */
const regAction = (/** @type {?} */ ((action)));
return Object.assign({}, rootState, { [regAction.payload.name]: regAction.payload.initialValue });
}
return Object.values(this.stateProviders).reduce((stateToReduce, provider) => {
return Object.assign({}, stateToReduce, {
[provider.name]: provider.reduce(stateToReduce[provider.name], action),
});
}, rootState);
}
}
ReduxReducerProvider.decorators = [
{ type: Injectable }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class ReduxSelectPipe {
/**
* @param {?=} stateDefs
* @param {?=} injector
*/
constructor(stateDefs = [], injector) {
this.provider = /** @type {?} */ (injector.get(stateDefs[0].provider));
}
/**
* @param {?} selector
* @return {?}
*/
transform(selector) {
return this.provider.select(selector);
}
}
ReduxSelectPipe.decorators = [
{ type: Pipe, args: [{ name: 'reduxSelect' },] }
];
/** @nocollapse */
ReduxSelectPipe.ctorParameters = () => [
{ type: Array, decorators: [{ type: Inject, args: [ReduxStateDefinitionToken,] }] },
{ type: Injector }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class ReduxTestingStore {
constructor() {
this.state = new BehaviorSubject(null);
}
/**
* @return {?}
*/
static factory() {
return new ReduxTestingStore();
}
/**
* @template S
* @param {?} state
* @param {?} value
* @return {?}
*/
setState(state, value) {
const { name } = ReduxStateDecorator.get(state);
/** @type {?} */
const nextState = Object.assign({}, this.state.getValue(), {
[name]: value,
});
this.state.next(nextState);
return this.state
.pipe(takeWhile(currentState => currentState !== nextState))
.toPromise().then(() => this.state.getValue());
}
/**
* @return {?}
*/
getState() {
return this.state.getValue();
}
/**
* @param {?} listener
* @return {?}
*/
subscribe(listener) {
return this.state.subscribe.call(this.state, listener);
}
/**
* @return {?}
*/
replaceReducer() {
}
/**
* @template T
* @param {?} action
* @return {?}
*/
dispatch(action) {
return action;
}
}
ReduxTestingStore.decorators = [
{ type: Injectable }
];
var TestingStateProvider_1;
let TestingStateProvider = TestingStateProvider_1 = class TestingStateProvider extends ReduxStateProvider {
/**
* @return {?}
*/
getInitialState() {
return TestingStateProvider_1.INITIAL_STATE;
}
};
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);
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class ReduxMiddlewares extends InjectionToken {
constructor() {
super('ReduxMiddlewares');
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
class ReduxModule {
/**
* @param {?} injector
* @param {?} reducerProvider
* @param {?=} stateDefs
*/
constructor(injector, reducerProvider, stateDefs = []) {
injector.get(ReduxRegistry); // just make sure the provider is instantiated
if (Array.isArray(stateDefs)) {
stateDefs
.filter(def => def && def.provider)
.map(def => injector.get(def.provider))
.forEach(provider => reducerProvider.addStateProvider(provider));
}
}
/**
* @template S
* @param {?=} config
* @return {?}
*/
static forChild(config = {}) {
return {
ngModule: ReduxModule,
providers: [
{ provide: ReduxStateDefinitionToken, useValue: config.state || null, multi: true },
],
};
}
/**
* @template S
* @param {?=} config
* @return {?}
*/
static forRoot(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 {?}
*/
static defaultStoreFactory(reduxReducerProvider, middlewareFunctions, devMode = isDevMode()) {
return createStore(reduxReducerProvider.rootReducer, {}, ReduxModule.defaultEnhancerFactory(middlewareFunctions, devMode));
}
/**
* @param {?} middlewareFunctions
* @param {?} devMode
* @return {?}
*/
static defaultEnhancerFactory(middlewareFunctions, devMode) {
/** @type {?} */
let composeEnhancers = compose;
if (devMode && window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']) {
composeEnhancers = window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__'];
}
return composeEnhancers(applyMiddleware(...middlewareFunctions));
}
}
ReduxModule.decorators = [
{ type: NgModule, args: [{
declarations: [
ReduxSelectPipe,
],
exports: [
ReduxSelectPipe,
],
imports: [
CommonModule,
],
},] }
];
/** @nocollapse */
ReduxModule.ctorParameters = () => [
{ type: Injector },
{ type: ReduxReducerProvider },
{ type: Array, decorators: [{ type: Optional }, { type: Inject, args: [ReduxStateDefinitionToken,] }] }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/** @type {?} */
const getActionType = ReduxActionDispatcher.getType;
/** @type {?} */
const 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+IHtcblxuICAgIHJldHVybiBjcmVhdGVTdG9yZShcbiAgICAgIHJlZHV4UmVkdWNlclByb3ZpZGVyLnJvb3RSZWR1Y2VyLFxuICAgICAge30sXG4gICAgICBSZWR1eE1vZHVsZS5kZWZhdWx0RW5oYW5jZXJGYWN0b3J5KG1pZGRsZXdhcmVGdW5jdGlvbnMsIGRldk1vZGUpLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGRlZmF1bHRFbmhhbmNlckZhY3RvcnkobWlkZGxld2FyZUZ1bmN0aW9uczogTWlkZGxld2FyZVtdLCBkZXZNb2RlOiBib29sZWFuKTogU3RvcmVFbmhhbmNlcjx7fT4ge1xuXG4gICAgbGV0IGNvbXBvc2VFbmhhbmNlcnMgPSBjb21wb3NlO1xuXG4gICAgaWYgKGRldk1vZGUgJiYgd2luZG93WydfX1JFRFVYX0RFVlRPT0xTX0VYVEVOU0lPTl9DT01QT1NFX18nXSkge1xuICAgICAgY29tcG9zZUVuaGFuY2VycyA9IHdpbmRvd1snX19SRURVWF9ERVZUT09MU19FWFRFTlNJT05fQ09NUE9TRV9fJ107XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbXBvc2VFbmhhbmNlcnMoYXBwbHlNaWRkbGV3YXJlKC4uLm1pZGRsZXdhcmVGdW5jdGlvbnMpKTtcbiAgfVxuXG59XG4iLCJleHBvcnQgKiBmcm9tICcuL2ludGVyZmFjZXMvcmVkdXgtYWN0aW9uLXdpdGgtcGF5bG9hZC5pbnRlcmZhY2UnO1xuXG5leHBvcnQgKiBmcm9tICcuL2RlY29yYXRvcnMnO1xuZXhwb3J0ICogZnJvbSAnLi9pbnRlcmZhY2VzL3JlZHV4LWNoaWxkLW1vZHVsZS1jb25maWcuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vaW50ZXJmYWNlcy9yZWR1eC1yb290LW1vZHVsZS1jb25maWcuaW50ZXJmYWNlJztcbmV4cG9ydCAqIGZyb20gJy4vaW50ZXJmYWNlcy9yZWR1eC1yb290LXN0YXRlLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL3Byb3ZpZGVycy9yZWR1eC1yZWR1Y2VyLnByb3ZpZGVyJztcbmV4cG9ydCAqIGZyb20gJy4vZGVjb3JhdG9ycy9yZWR1eC1zZWxlY3QuZGVjb3JhdG9yJztcbmV4cG9ydCAqIGZyb20gJy4vcGlwZXMvcmVkdXgtc2VsZWN0LnBpcGUnO1xuZXhwb3J0ICogZnJvbSAnLi9yZWR1eC1zZWxlY3Rvcic7XG5leHBvcnQgKiBmcm9tICcuL3Rva2Vucy9yZWR1eC1zdGF0ZS1kZWZpbml0aW9uLnRva2VuJztcbmV4cG9ydCAqIGZyb20gJy4vaW50ZXJmYWNlcy9yZWR1eC1zdGF0ZS1kZWZpbml0aW9uLmludGVyZmFjZSc7XG5leHBvcnQgKiBmcm9tICcuL3Byb3ZpZGVycy9yZWR1eC1zdGF0ZS5wcm92aWRlcic7XG5leHBvcnQgKiBmcm9tICcuL3Rva2Vucy9yZWR1eC1zdG9yZS50b2tlbic7XG5leHBvcnQgKiBmcm9tICcuL3Rlc3Rpbmcvc3RvcmUnO1xuZXhwb3J0ICogZnJvbSAnLi90ZXN0aW5nL3N0YXRlJztcbmV4cG9ydCAqIGZyb20gJy4vcHJvdmlkZXJzL3JlZHV4LXJlZ2lzdHJ5JztcblxuZXhwb3J0IHsgUmVkdXhNb2R1bGUgfSBmcm9tICcuL3JlZHV4Lm1vZHVsZSc7XG5pbXBvcnQgeyBSZWR1eEFjdGlvbkRpc3BhdGNoZXIgfSBmcm9tICdAaGFybW93YXRjaC9yZWR1eC1kZWNvcmF0b3JzJztcblxuZXhwb3J0IGNvbnN0IGdldEFjdGlvblR5cGUgPSBSZWR1eEFjdGlvbkRpc3BhdGNoZXIuZ2V0VHlwZTtcbmV4cG9ydCBjb25zdCBkaXNwYXRjaCA9IFJlZHV4QWN0aW9uRGlzcGF0Y2hlci5kaXNwYXRjaDtcbiJdLCJuYW1lcyI6WyJSZWR1eFN0YXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBQ0EsK0JBRXVDLFNBQVEsY0FBeUI7SUFFdEU7UUFDRSxLQUFLLENBQUMsMkJBQTJCLENBQUMsQ0FBQztLQUNwQztDQUVGOzs7Ozs7QUNURCxnQkFHd0IsU0FBUSxjQUF5QjtJQUV2RDtRQUNFLEtBQUssQ0FBQyxZQUFZLENBQUMsQ0FBQztLQUNyQjtDQUVGOzs7Ozs7QUNURDs7OztJQXNCRSxZQUFnQyxRQUFtQixJQUFJO1FBQ3JELGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN0QixhQUFhLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQ3BDOzs7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