@loona/angular
Version:
App State Management done with GraphQL (angular integration)
504 lines (494 loc) • 39 kB
JavaScript
import { InjectionToken, Injectable, ErrorHandler, Inject, NgModule, Injector } from '@angular/core';
import { Observable, BehaviorSubject, Subject, queueScheduler, merge, throwError, from } from 'rxjs';
import { Apollo } from 'apollo-angular';
import { observeOn, tap, catchError } from 'rxjs/operators';
import { isMutation, getMutation, isDocument, Manager, withUpdates, getActionType, buildActionFromResult, buildActionFromError, buildContext, getNameOfMutation, isMutationAsAction, METADATA_KEY, buildGetCacheKey, LoonaLink } from '@loona/core';
export { Manager, LoonaLink, State, Mutation, Update, Resolve, Effect } from '@loona/core';
import { ApolloCache } from 'apollo-cache';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/** @type {?} */
const INITIAL_STATE = new InjectionToken('Loona/State');
/** @type {?} */
const CHILD_STATE = new InjectionToken('Loona/ChildState');
/** @type {?} */
const LOONA_CACHE = new InjectionToken('Loona/Cache');
/** @type {?} */
const INIT = '@@init';
/** @type {?} */
const ROOT_EFFECTS_INIT = '@@effects/init';
/** @type {?} */
const UPDATE_EFFECTS = '@@effects/update';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @template V
*/
class Actions extends Observable {
}
class ScannedActions extends Subject {
/**
* @return {?}
*/
ngOnDestroy() {
this.complete();
}
}
ScannedActions.decorators = [
{ type: Injectable }
];
class InnerActions extends BehaviorSubject {
constructor() {
super({ type: INIT });
}
/**
* @param {?} action
* @return {?}
*/
next(action) {
if (typeof action === 'undefined') {
throw new TypeError(`Actions must be objects`);
}
else if (typeof action.type === 'undefined') {
throw new TypeError(`Actions must have a type property`);
}
super.next(action);
}
/**
* @return {?}
*/
complete() { }
/**
* @return {?}
*/
ngOnDestroy() {
super.complete();
}
}
InnerActions.decorators = [
{ type: Injectable }
];
/** @nocollapse */
InnerActions.ctorParameters = () => [];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
class Loona {
/**
* @param {?} apollo
* @param {?} manager
* @param {?} actions
* @param {?} scannedActions
* @param {?} errorHandler
*/
constructor(apollo, manager, actions, scannedActions, errorHandler) {
this.apollo = apollo;
this.manager = manager;
this.actions = actions;
this.direct$ = new Subject();
this.queue$ = merge(actions, this.direct$).pipe(observeOn(queueScheduler));
this.queue$.subscribe({
next: action => {
scannedActions.next(action);
},
error: error => {
errorHandler.handleError(error);
},
});
}
/**
* @template T, V
* @param {?} queryOrOptions
* @param {?=} variables
* @param {?=} options
* @return {?}
*/
query(queryOrOptions, variables, options) {
return this.apollo.watchQuery(isDocument(queryOrOptions)
? Object.assign({ query: queryOrOptions, variables }, options) : queryOrOptions);
}
/**
* @template T, V
* @param {?} mutationOrOptions
* @param {?=} variables
* @param {?=} options
* @return {?}
*/
mutate(mutationOrOptions, variables, options) {
/** @type {?} */
const config = isDocument(mutationOrOptions)
? Object.assign({ mutation: mutationOrOptions, variables }, options) : mutationOrOptions;
return this.apollo
.mutate(withUpdates(config, this.manager))
.pipe(tap(result => {
this.direct$.next(buildActionFromResult(config, result));
}), catchError(error => {
this.direct$.next(buildActionFromError(config, error));
return throwError(error);
}));
}
/**
* @param {?} action
* @return {?}
*/
dispatch(action) {
if (isMutation(action)) {
/** @type {?} */
const mutation = getMutation(action);
this.mutate(Object.assign({ mutation }, action)).subscribe();
}
else {
this.actions.next(Object.assign({ type: getActionType(action) }, action));
}
}
/**
* @template T
* @return {?}
*/
extract() {
return this.apollo.getClient().extract();
}
/**
* @return {?}
*/
reset() {
this.apollo.getClient().resetStore();
}
/**
* @param {?} state
* @return {?}
*/
restore(state) {
this.apollo.getClient().restore(state);
}
}
Loona.decorators = [
{ type: Injectable }
];
/** @nocollapse */
Loona.ctorParameters = () => [
{ type: Apollo },
{ type: Manager },
{ type: InnerActions },
{ type: ScannedActions },
{ type: ErrorHandler }
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
class Effects {
/**
* @param {?} loona
* @param {?} apollo
* @param {?} cache
*/
constructor(loona, apollo, cache) {
this.effects = {};
this.getContext = () => (Object.assign({}, buildContext({
cache,
getCacheKey: buildGetCacheKey(cache),
}, apollo.getClient()), { dispatch: loona.dispatch.bind(loona) }));
}
/**
* @param {?} instance
* @param {?=} meta
* @return {?}
*/
addEffects(instance, meta) {
if (!meta) {
return;
}
for (const type in meta) {
if (!this.effects[type]) {
this.effects[type] = [];
}
meta[type].forEach(({ propName }) => {
this.effects[type].push(instance[propName].bind(instance));
});
}
}
/**
* @param {?} action
* @return {?}
*/
runEffects(action) {
/** @type {?} */
let type = action.type;
if (isMutationAsAction(action)) {
type = getNameOfMutation(action.options.mutation);
}
/** @type {?} */
const effectsToRun = this.effects[type];
if (effectsToRun) {
effectsToRun.forEach(effect => {
effect(action, this.getContext());
});
}
}
}
Effects.decorators = [
{ type: Injectable }
];
/** @nocollapse */
Effects.ctorParameters = () => [
{ type: Loona },
{ type: Apollo },
{ type: ApolloCache, decorators: [{ type: Inject, args: [LOONA_CACHE,] }] }
];
class EffectsRunner {
/**
* @param {?} effects
* @param {?} scannedActions
*/
constructor(effects, scannedActions) {
this.effects = effects;
this.scannedActions = scannedActions;
this.actionsSubscription = null;
}
/**
* @return {?}
*/
start() {
if (!this.actionsSubscription) {
this.actionsSubscription = this.scannedActions.subscribe(action => {
this.effects.runEffects(action);
});
}
}
/**
* @return {?}
*/
ngOnDestroy() {
if (this.actionsSubscription) {
this.actionsSubscription.unsubscribe();
this.actionsSubscription = null;
}
}
}
EffectsRunner.decorators = [
{ type: Injectable }
];
/** @nocollapse */
EffectsRunner.ctorParameters = () => [
{ type: Effects },
{ type: ScannedActions }
];
/**
* @return {?}
*/
function mapStates() {
/** @type {?} */
const names = [];
/** @type {?} */
const add = (state) => {
names.push(state.constructor && state.constructor.name);
};
return { names, add };
}
/**
* @param {?} state
* @param {?} injector
* @return {?}
*/
function extractState(state, injector) {
return {
instance: injector.get(state),
meta: state[METADATA_KEY],
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @template T
* @param {?} val
* @return {?}
*/
function isObservable(val) {
return val instanceof Observable;
}
/**
* @param {?} resolver
* @return {?}
*/
function handleObservable(resolver) {
return (...args) => {
/** @type {?} */
let result;
try {
result = resolver(...args);
}
catch (e) {
return Promise.reject(e);
}
return result instanceof Promise || isObservable(result)
? from(result).toPromise()
: Promise.resolve(result);
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
class LoonaRootModule {
/**
* @param {?} effects
* @param {?} states
* @param {?} loona
* @param {?} manager
* @param {?} runner
* @param {?} injector
*/
constructor(effects, states, loona, manager, runner, injector) {
this.effects = effects;
runner.start();
const { names, add } = mapStates();
states.forEach(state => {
const { instance, meta } = extractState(state, injector);
manager.addState(instance, meta, handleObservable);
this.addEffects(instance, meta.effects);
add(instance);
});
loona.dispatch({
type: ROOT_EFFECTS_INIT,
states: names,
});
}
/**
* @param {?} state
* @param {?=} meta
* @return {?}
*/
addEffects(state, meta) {
this.effects.addEffects(state, meta);
}
}
LoonaRootModule.decorators = [
{ type: NgModule }
];
/** @nocollapse */
LoonaRootModule.ctorParameters = () => [
{ type: Effects },
{ type: Array, decorators: [{ type: Inject, args: [INITIAL_STATE,] }] },
{ type: Loona },
{ type: Manager },
{ type: EffectsRunner },
{ type: Injector }
];
class LoonaChildModule {
/**
* @param {?} states
* @param {?} injector
* @param {?} manager
* @param {?} loona
* @param {?} rootModule
*/
constructor(states, injector, manager, loona, rootModule) {
const { names, add } = mapStates();
states.forEach(state => {
const { instance, meta } = extractState(state, injector);
manager.addState(instance, meta, handleObservable);
rootModule.addEffects(instance, meta.effects);
add(instance);
});
loona.dispatch({
type: UPDATE_EFFECTS,
states: names,
});
}
}
LoonaChildModule.decorators = [
{ type: NgModule }
];
/** @nocollapse */
LoonaChildModule.ctorParameters = () => [
{ type: Array, decorators: [{ type: Inject, args: [CHILD_STATE,] }] },
{ type: Injector },
{ type: Manager },
{ type: Loona },
{ type: LoonaRootModule }
];
class LoonaModule {
/**
* @param {?=} states
* @return {?}
*/
static forRoot(states = []) {
return {
ngModule: LoonaRootModule,
providers: [
Loona,
InnerActions,
ScannedActions,
{
provide: Actions,
useExisting: ScannedActions,
},
...states,
{ provide: INITIAL_STATE, useValue: states },
{
provide: Manager,
useFactory: managerFactory,
deps: [LOONA_CACHE, Injector],
},
{
provide: LoonaLink,
useFactory: linkFactory,
deps: [Manager],
},
Effects,
EffectsRunner,
],
};
}
/**
* @param {?=} states
* @return {?}
*/
static forChild(states = []) {
return {
ngModule: LoonaChildModule,
providers: [...states, { provide: CHILD_STATE, useValue: states }],
};
}
}
LoonaModule.decorators = [
{ type: NgModule }
];
/**
* @param {?} manager
* @return {?}
*/
function linkFactory(manager) {
return new LoonaLink(manager);
}
/**
* @param {?} cache
* @param {?} injector
* @return {?}
*/
function managerFactory(cache, injector) {
/** @type {?} */
const manager = new Manager({
cache,
getClient: () => injector.get(Apollo).getClient(),
});
return manager;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
export { Actions, Loona, LoonaModule, INITIAL_STATE, CHILD_STATE, LOONA_CACHE, INIT, UPDATE_EFFECTS, ROOT_EFFECTS_INIT, InnerActions as ɵb, ScannedActions as ɵa, Effects as ɵg, EffectsRunner as ɵh, LoonaChildModule as ɵd, LoonaRootModule as ɵc, linkFactory as ɵe, managerFactory as ɵf };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9vbmEuYW5ndWxhci5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQGxvb25hL2FuZ3VsYXIvdG9rZW5zLnRzIiwibmc6Ly9AbG9vbmEvYW5ndWxhci9hY3Rpb25zLnRzIiwibmc6Ly9AbG9vbmEvYW5ndWxhci9jbGllbnQudHMiLCJuZzovL0Bsb29uYS9hbmd1bGFyL2VmZmVjdHMudHMiLCJuZzovL0Bsb29uYS9hbmd1bGFyL3V0aWxzLnRzIiwibmc6Ly9AbG9vbmEvYW5ndWxhci9tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3Rpb25Ub2tlbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0Fwb2xsb0NhY2hlfSBmcm9tICdhcG9sbG8tY2FjaGUnO1xuaW1wb3J0IHtTdGF0ZUNsYXNzLCBNZXRhZGF0YX0gZnJvbSAnQGxvb25hL2NvcmUnO1xuXG5leHBvcnQgY29uc3QgSU5JVElBTF9TVEFURSA9IG5ldyBJbmplY3Rpb25Ub2tlbjxTdGF0ZUNsYXNzPE1ldGFkYXRhPj4oXG4gICdMb29uYS9TdGF0ZScsXG4pO1xuZXhwb3J0IGNvbnN0IENISUxEX1NUQVRFID0gbmV3IEluamVjdGlvblRva2VuPFN0YXRlQ2xhc3M8TWV0YWRhdGE+PihcbiAgJ0xvb25hL0NoaWxkU3RhdGUnLFxuKTtcbmV4cG9ydCBjb25zdCBMT09OQV9DQUNIRSA9IG5ldyBJbmplY3Rpb25Ub2tlbjxBcG9sbG9DYWNoZTxhbnk+PignTG9vbmEvQ2FjaGUnKTtcblxuZXhwb3J0IGNvbnN0IElOSVQgPSAnQEBpbml0JztcbmV4cG9ydCBjb25zdCBST09UX0VGRkVDVFNfSU5JVCA9ICdAQGVmZmVjdHMvaW5pdCc7XG5leHBvcnQgY29uc3QgVVBEQVRFX0VGRkVDVFMgPSAnQEBlZmZlY3RzL3VwZGF0ZSc7XG4iLCJpbXBvcnQge0luamVjdGFibGUsIE9uRGVzdHJveX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge09ic2VydmFibGUsIEJlaGF2aW9yU3ViamVjdCwgU3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge0FjdGlvbn0gZnJvbSAnQGxvb25hL2NvcmUnO1xuXG5pbXBvcnQge0lOSVR9IGZyb20gJy4vdG9rZW5zJztcblxuZXhwb3J0IGNsYXNzIEFjdGlvbnM8ViA9IEFjdGlvbj4gZXh0ZW5kcyBPYnNlcnZhYmxlPFY+IHt9XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBTY2FubmVkQWN0aW9ucyBleHRlbmRzIFN1YmplY3Q8QWN0aW9uPiBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMuY29tcGxldGUoKTtcbiAgfVxufVxuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgSW5uZXJBY3Rpb25zIGV4dGVuZHMgQmVoYXZpb3JTdWJqZWN0PEFjdGlvbj4gaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcih7dHlwZTogSU5JVH0pO1xuICB9XG5cbiAgbmV4dChhY3Rpb246IEFjdGlvbikge1xuICAgIGlmICh0eXBlb2YgYWN0aW9uID09PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgQWN0aW9ucyBtdXN0IGJlIG9iamVjdHNgKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBhY3Rpb24udHlwZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEFjdGlvbnMgbXVzdCBoYXZlIGEgdHlwZSBwcm9wZXJ0eWApO1xuICAgIH1cblxuICAgIHN1cGVyLm5leHQoYWN0aW9uKTtcbiAgfVxuXG4gIGNvbXBsZXRlKCkge31cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBzdXBlci5jb21wbGV0ZSgpO1xuICB9XG59XG4iLCJpbXBvcnQge0luamVjdGFibGUsIEVycm9ySGFuZGxlcn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0Fwb2xsbywgUXVlcnlSZWZ9IGZyb20gJ2Fwb2xsby1hbmd1bGFyJztcbmltcG9ydCB7XG4gIFdhdGNoUXVlcnlPcHRpb25zLFxuICBNdXRhdGlvbk9wdGlvbnMgYXMgQ29yZU11dGF0aW9uT3B0aW9ucyxcbn0gZnJvbSAnYXBvbGxvLWNsaWVudCc7XG5pbXBvcnQge0ZldGNoUmVzdWx0fSBmcm9tICdhcG9sbG8tbGluayc7XG5pbXBvcnQge09ic2VydmFibGUsIFN1YmplY3QsIHF1ZXVlU2NoZWR1bGVyLCBtZXJnZSwgdGhyb3dFcnJvcn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge29ic2VydmVPbiwgdGFwLCBjYXRjaEVycm9yfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge0RvY3VtZW50Tm9kZX0gZnJvbSAnZ3JhcGhxbCc7XG5pbXBvcnQge1xuICBpc011dGF0aW9uLFxuICBnZXRNdXRhdGlvbixcbiAgQWN0aW9uLFxuICBpc0RvY3VtZW50LFxuICBNYW5hZ2VyLFxuICB3aXRoVXBkYXRlcyxcbiAgZ2V0QWN0aW9uVHlwZSxcbiAgYnVpbGRBY3Rpb25Gcm9tUmVzdWx0LFxuICBidWlsZEFjdGlvbkZyb21FcnJvcixcbn0gZnJvbSAnQGxvb25hL2NvcmUnO1xuXG5pbXBvcnQge0lubmVyQWN0aW9ucywgU2Nhbm5lZEFjdGlvbnN9IGZyb20gJy4vYWN0aW9ucyc7XG5cbmV4cG9ydCB0eXBlIE9taXQ8VCwgSyBleHRlbmRzIGtleW9mIFQ+ID0gUGljazxULCBFeGNsdWRlPGtleW9mIFQsIEs+PjtcblxuZXhwb3J0IGludGVyZmFjZSBRdWVyeU9wdGlvbnNcbiAgZXh0ZW5kcyBPbWl0PFdhdGNoUXVlcnlPcHRpb25zLCAncXVlcnknIHwgJ3ZhcmlhYmxlcyc+IHt9XG5cbmV4cG9ydCBpbnRlcmZhY2UgTXV0YXRpb25PcHRpb25zXG4gIGV4dGVuZHMgT21pdDxDb3JlTXV0YXRpb25PcHRpb25zLCAnbXV0YXRpb24nIHwgJ3ZhcmlhYmxlcyc+IHt9XG5cbmV4cG9ydCB0eXBlIFIgPSBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG5leHBvcnQgaW50ZXJmYWNlIFR5cGVkVmFyaWFibGVzPFY+IHtcbiAgdmFyaWFibGVzPzogVjtcbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIExvb25hIHtcbiAgcHJpdmF0ZSBxdWV1ZSQ6IE9ic2VydmFibGU8QWN0aW9uPjtcbiAgcHJpdmF0ZSBkaXJlY3QkID0gbmV3IFN1YmplY3Q8QWN0aW9uPigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYXBvbGxvOiBBcG9sbG8sXG4gICAgcHJpdmF0ZSBtYW5hZ2VyOiBNYW5hZ2VyLFxuICAgIHByaXZhdGUgYWN0aW9uczogSW5uZXJBY3Rpb25zLFxuICAgIHNjYW5uZWRBY3Rpb25zOiBTY2FubmVkQWN0aW9ucyxcbiAgICBlcnJvckhhbmRsZXI6IEVycm9ySGFuZGxlcixcbiAgKSB7XG4gICAgdGhpcy5xdWV1ZSQgPSBtZXJnZShhY3Rpb25zLCB0aGlzLmRpcmVjdCQpLnBpcGUob2JzZXJ2ZU9uKHF1ZXVlU2NoZWR1bGVyKSk7XG4gICAgdGhpcy5xdWV1ZSQuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IGFjdGlvbiA9PiB7XG4gICAgICAgIHNjYW5uZWRBY3Rpb25zLm5leHQoYWN0aW9uKTtcbiAgICAgIH0sXG4gICAgICBlcnJvcjogZXJyb3IgPT4ge1xuICAgICAgICBlcnJvckhhbmRsZXIuaGFuZGxlRXJyb3IoZXJyb3IpO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHF1ZXJ5PFQsIFYgPSBhbnk+KFxuICAgIHF1ZXJ5OiBEb2N1bWVudE5vZGUsXG4gICAgdmFyaWFibGVzPzogVixcbiAgICBvcHRpb25zPzogUXVlcnlPcHRpb25zLFxuICApOiBRdWVyeVJlZjxULCBWPjtcblxuICBxdWVyeTxULCBWID0gYW55PihcbiAgICBvcHRpb25zOiBXYXRjaFF1ZXJ5T3B0aW9ucyAmIFR5cGVkVmFyaWFibGVzPFY+LFxuICApOiBRdWVyeVJlZjxULCBWPjtcblxuICBxdWVyeTxULCBWID0gYW55PihcbiAgICBxdWVyeU9yT3B0aW9uczogRG9jdW1lbnROb2RlIHwgKFdhdGNoUXVlcnlPcHRpb25zICYgVHlwZWRWYXJpYWJsZXM8Vj4pLFxuICAgIHZhcmlhYmxlcz86IFYsXG4gICAgb3B0aW9ucz86IFF1ZXJ5T3B0aW9ucyxcbiAgKTogUXVlcnlSZWY8VCwgVj4ge1xuICAgIHJldHVybiB0aGlzLmFwb2xsby53YXRjaFF1ZXJ5PFQsIFY+KFxuICAgICAgaXNEb2N1bWVudChxdWVyeU9yT3B0aW9ucylcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBxdWVyeTogcXVlcnlPck9wdGlvbnMsXG4gICAgICAgICAgICB2YXJpYWJsZXMsXG4gICAgICAgICAgICAuLi5vcHRpb25zLFxuICAgICAgICAgIH1cbiAgICAgICAgOiBxdWVyeU9yT3B0aW9ucyxcbiAgICApO1xuICB9XG5cbiAgbXV0YXRlPFQsIFYgPSBSPihcbiAgICBtdXRhdGlvbjogRG9jdW1lbnROb2RlLFxuICAgIHZhcmlhYmxlcz86IFYsXG4gICAgb3B0aW9ucz86IE11dGF0aW9uT3B0aW9ucyxcbiAgKTogT2JzZXJ2YWJsZTxGZXRjaFJlc3VsdDxUPj47XG5cbiAgbXV0YXRlPFQsIFYgPSBSPihcbiAgICBvcHRpb25zOiBDb3JlTXV0YXRpb25PcHRpb25zPFQsIFY+LFxuICApOiBPYnNlcnZhYmxlPEZldGNoUmVzdWx0PFQ+PjtcblxuICBtdXRhdGU8VCwgViA9IFI+KFxuICAgIG11dGF0aW9uT3JPcHRpb25zOiBEb2N1bWVudE5vZGUgfCBDb3JlTXV0YXRpb25PcHRpb25zPFQsIFY+LFxuICAgIHZhcmlhYmxlcz86IFYsXG4gICAgb3B0aW9ucz86IE11dGF0aW9uT3B0aW9ucyxcbiAgKTogT2JzZXJ2YWJsZTxGZXRjaFJlc3VsdDxUPj4ge1xuICAgIGNvbnN0IGNvbmZpZyA9IGlzRG9jdW1lbnQobXV0YXRpb25Pck9wdGlvbnMpXG4gICAgICA/IHtcbiAgICAgICAgICBtdXRhdGlvbjogbXV0YXRpb25Pck9wdGlvbnMsXG4gICAgICAgICAgdmFyaWFibGVzLFxuICAgICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgIH1cbiAgICAgIDogbXV0YXRpb25Pck9wdGlvbnM7XG5cbiAgICByZXR1cm4gdGhpcy5hcG9sbG9cbiAgICAgIC5tdXRhdGU8VCwgVj4od2l0aFVwZGF0ZXM8VCwgVj4oY29uZmlnLCB0aGlzLm1hbmFnZXIpKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRhcChyZXN1bHQgPT4ge1xuICAgICAgICAgIHRoaXMuZGlyZWN0JC5uZXh0KGJ1aWxkQWN0aW9uRnJvbVJlc3VsdChjb25maWcsIHJlc3VsdCkpO1xuICAgICAgICB9KSxcbiAgICAgICAgY2F0Y2hFcnJvcihlcnJvciA9PiB7XG4gICAgICAgICAgdGhpcy5kaXJlY3QkLm5leHQoYnVpbGRBY3Rpb25Gcm9tRXJyb3IoY29uZmlnLCBlcnJvcikpO1xuICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKGVycm9yKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICB9XG5cbiAgZGlzcGF0Y2goYWN0aW9uOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAoaXNNdXRhdGlvbihhY3Rpb24pKSB7XG4gICAgICBjb25zdCBtdXRhdGlvbiA9IGdldE11dGF0aW9uKGFjdGlvbik7XG5cbiAgICAgIHRoaXMubXV0YXRlKHtcbiAgICAgICAgbXV0YXRpb24sXG4gICAgICAgIC4uLmFjdGlvbixcbiAgICAgIH0pLnN1YnNjcmliZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFjdGlvbnMubmV4dCh7XG4gICAgICAgIHR5cGU6IGdldEFjdGlvblR5cGUoYWN0aW9uKSxcbiAgICAgICAgLi4uYWN0aW9uLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZXh0cmFjdDxUID0gYW55PigpOiBUIHtcbiAgICByZXR1cm4gdGhpcy5hcG9sbG8uZ2V0Q2xpZW50KCkuZXh0cmFjdCgpO1xuICB9XG5cbiAgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5hcG9sbG8uZ2V0Q2xpZW50KCkucmVzZXRTdG9yZSgpO1xuICB9XG5cbiAgcmVzdG9yZShzdGF0ZTogYW55KTogdm9pZCB7XG4gICAgdGhpcy5hcG9sbG8uZ2V0Q2xpZW50KCkucmVzdG9yZShzdGF0ZSk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIGJ1aWxkQ29udGV4dCxcbiAgZ2V0TmFtZU9mTXV0YXRpb24sXG4gIGlzTXV0YXRpb25Bc0FjdGlvbixcbiAgTWV0YWRhdGEsXG4gIEVmZmVjdE1ldGhvZCxcbiAgQWN0aW9uLFxuICBFZmZlY3RDb250ZXh0LFxuICBTdGF0ZUNsYXNzLFxuICBNRVRBREFUQV9LRVksXG4gIGJ1aWxkR2V0Q2FjaGVLZXksXG59IGZyb20gJ0Bsb29uYS9jb3JlJztcbmltcG9ydCB7SW5qZWN0YWJsZSwgSW5qZWN0LCBPbkRlc3Ryb3ksIEluamVjdG9yfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7QXBvbGxvQ2FjaGV9IGZyb20gJ2Fwb2xsby1jYWNoZSc7XG5pbXBvcnQge0Fwb2xsb30gZnJvbSAnYXBvbGxvLWFuZ3VsYXInO1xuaW1wb3J0IHtTdWJzY3JpcHRpb259IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQge0xvb25hfSBmcm9tICcuL2NsaWVudCc7XG5pbXBvcnQge0xPT05BX0NBQ0hFfSBmcm9tICcuL3Rva2Vucyc7XG5pbXBvcnQge1NjYW5uZWRBY3Rpb25zfSBmcm9tICcuL2FjdGlvbnMnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgRWZmZWN0cyB7XG4gIGVmZmVjdHM6IFJlY29yZDxzdHJpbmcsIEFycmF5PEVmZmVjdE1ldGhvZD4+ID0ge307XG4gIGdldENvbnRleHQ6ICgpID0+IEVmZmVjdENvbnRleHQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgbG9vbmE6IExvb25hLFxuICAgIGFwb2xsbzogQXBvbGxvLFxuICAgIEBJbmplY3QoTE9PTkFfQ0FDSEUpIGNhY2hlOiBBcG9sbG9DYWNoZTxhbnk+LFxuICApIHtcbiAgICB0aGlzLmdldENvbnRleHQgPSAoKSA9PiAoe1xuICAgICAgLi4uYnVpbGRDb250ZXh0KFxuICAgICAgICB7XG4gICAgICAgICAgY2FjaGUsXG4gICAgICAgICAgZ2V0Q2FjaGVLZXk6IGJ1aWxkR2V0Q2FjaGVLZXkoY2FjaGUpLFxuICAgICAgICB9LFxuICAgICAgICBhcG9sbG8uZ2V0Q2xpZW50KCksXG4gICAgICApLFxuICAgICAgZGlzcGF0Y2g6IGxvb25hLmRpc3BhdGNoLmJpbmQobG9vbmEpLFxuICAgIH0pO1xuICB9XG5cbiAgYWRkRWZmZWN0cyhpbnN0YW5jZTogYW55LCBtZXRhPzogTWV0YWRhdGEuRWZmZWN0cykge1xuICAgIGlmICghbWV0YSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgdHlwZSBpbiBtZXRhKSB7XG4gICAgICBpZiAoIXRoaXMuZWZmZWN0c1t0eXBlXSkge1xuICAgICAgICB0aGlzLmVmZmVjdHNbdHlwZV0gPSBbXTtcbiAgICAgIH1cblxuICAgICAgbWV0YVt0eXBlXS5mb3JFYWNoKCh7cHJvcE5hbWV9KSA9PiB7XG4gICAgICAgIHRoaXMuZWZmZWN0c1t0eXBlXS5wdXNoKGluc3RhbmNlW3Byb3BOYW1lXS5iaW5kKGluc3RhbmNlKSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBydW5FZmZlY3RzKGFjdGlvbjogQWN0aW9uKSB7XG4gICAgbGV0IHR5cGUgPSBhY3Rpb24udHlwZTtcblxuICAgIGlmIChpc011dGF0aW9uQXNBY3Rpb24oYWN0aW9uKSkge1xuICAgICAgdHlwZSA9IGdldE5hbWVPZk11dGF0aW9uKGFjdGlvbi5vcHRpb25zLm11dGF0aW9uKTtcbiAgICB9XG5cbiAgICBjb25zdCBlZmZlY3RzVG9SdW4gPSB0aGlzLmVmZmVjdHNbdHlwZV07XG5cbiAgICBpZiAoZWZmZWN0c1RvUnVuKSB7XG4gICAgICBlZmZlY3RzVG9SdW4uZm9yRWFjaChlZmZlY3QgPT4ge1xuICAgICAgICBlZmZlY3QoYWN0aW9uLCB0aGlzLmdldENvbnRleHQoKSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEVmZmVjdHNSdW5uZXIgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwcml2YXRlIGFjdGlvbnNTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgZWZmZWN0czogRWZmZWN0cyxcbiAgICBwcml2YXRlIHNjYW5uZWRBY3Rpb25zOiBTY2FubmVkQWN0aW9ucyxcbiAgKSB7fVxuXG4gIHN0YXJ0KCkge1xuICAgIGlmICghdGhpcy5hY3Rpb25zU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLmFjdGlvbnNTdWJzY3JpcHRpb24gPSB0aGlzLnNjYW5uZWRBY3Rpb25zLnN1YnNjcmliZShhY3Rpb24gPT4ge1xuICAgICAgICB0aGlzLmVmZmVjdHMucnVuRWZmZWN0cyhhY3Rpb24pO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMuYWN0aW9uc1N1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5hY3Rpb25zU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICB0aGlzLmFjdGlvbnNTdWJzY3JpcHRpb24gPSBudWxsO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbWFwU3RhdGVzKCkge1xuICBjb25zdCBuYW1lczogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgYWRkID0gKHN0YXRlOiBhbnkpID0+IHtcbiAgICBuYW1lcy5wdXNoKHN0YXRlLmNvbnN0cnVjdG9yICYmIHN0YXRlLmNvbnN0cnVjdG9yLm5hbWUpO1xuICB9O1xuXG4gIHJldHVybiB7bmFtZXMsIGFkZH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0U3RhdGUoXG4gIHN0YXRlOiBTdGF0ZUNsYXNzPE1ldGFkYXRhPixcbiAgaW5qZWN0b3I6IEluamVjdG9yLFxuKToge1xuICBpbnN0YW5jZTogYW55O1xuICBtZXRhOiBNZXRhZGF0YTtcbn0ge1xuICByZXR1cm4ge1xuICAgIGluc3RhbmNlOiBpbmplY3Rvci5nZXQoc3RhdGUpLFxuICAgIG1ldGE6IHN0YXRlW01FVEFEQVRBX0tFWV0sXG4gIH07XG59XG4iLCJpbXBvcnQge09ic2VydmFibGUsIGZyb219IGZyb20gJ3J4anMnO1xuXG5leHBvcnQgZnVuY3Rpb24gaXNPYnNlcnZhYmxlPFQgPSBhbnk+KHZhbDogYW55KTogdmFsIGlzIE9ic2VydmFibGU8VD4ge1xuICByZXR1cm4gdmFsIGluc3RhbmNlb2YgT2JzZXJ2YWJsZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhbmRsZU9ic2VydmFibGUocmVzb2x2ZXI6IGFueSkge1xuICByZXR1cm4gKC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgbGV0IHJlc3VsdDogYW55O1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IHJlc29sdmVyKC4uLmFyZ3MpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0IGluc3RhbmNlb2YgUHJvbWlzZSB8fCBpc09ic2VydmFibGUocmVzdWx0KVxuICAgICAgPyBmcm9tKHJlc3VsdCkudG9Qcm9taXNlKClcbiAgICAgIDogUHJvbWlzZS5yZXNvbHZlKHJlc3VsdCk7XG4gIH07XG59XG4iLCJpbXBvcnQge05nTW9kdWxlLCBNb2R1bGVXaXRoUHJvdmlkZXJzLCBJbmplY3RvciwgSW5qZWN0fSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7QXBvbGxvQ2FjaGV9IGZyb20gJ2Fwb2xsby1jYWNoZSc7XG5pbXBvcnQge0Fwb2xsb30gZnJvbSAnYXBvbGxvLWFuZ3VsYXInO1xuaW1wb3J0IHtNYW5hZ2VyLCBMb29uYUxpbmssIFN0YXRlQ2xhc3MsIE1ldGFkYXRhfSBmcm9tICdAbG9vbmEvY29yZSc7XG5cbmltcG9ydCB7TG9vbmF9IGZyb20gJy4vY2xpZW50JztcbmltcG9ydCB7SW5uZXJBY3Rpb25zLCBTY2FubmVkQWN0aW9ucywgQWN0aW9uc30gZnJvbSAnLi9hY3Rpb25zJztcbmltcG9ydCB7RWZmZWN0c1J1bm5lciwgRWZmZWN0cywgbWFwU3RhdGVzLCBleHRyYWN0U3RhdGV9IGZyb20gJy4vZWZmZWN0cyc7XG5pbXBvcnQge1xuICBJTklUSUFMX1NUQVRFLFxuICBDSElMRF9TVEFURSxcbiAgTE9PTkFfQ0FDSEUsXG4gIFJPT1RfRUZGRUNUU19JTklULFxuICBVUERBVEVfRUZGRUNUUyxcbn0gZnJvbSAnLi90b2tlbnMnO1xuaW1wb3J0IHtoYW5kbGVPYnNlcnZhYmxlfSBmcm9tICcuL3V0aWxzJztcblxuQE5nTW9kdWxlKClcbmV4cG9ydCBjbGFzcyBMb29uYVJvb3RNb2R1bGUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVmZmVjdHM6IEVmZmVjdHMsXG4gICAgQEluamVjdChJTklUSUFMX1NUQVRFKSBzdGF0ZXM6IFN0YXRlQ2xhc3M8TWV0YWRhdGE+W10sXG4gICAgbG9vbmE6IExvb25hLFxuICAgIG1hbmFnZXI6IE1hbmFnZXIsXG4gICAgcnVubmVyOiBFZmZlY3RzUnVubmVyLFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgKSB7XG4gICAgcnVubmVyLnN0YXJ0KCk7XG5cbiAgICBjb25zdCB7bmFtZXMsIGFkZH0gPSBtYXBTdGF0ZXMoKTtcblxuICAgIHN0YXRlcy5mb3JFYWNoKHN0YXRlID0+IHtcbiAgICAgIGNvbnN0IHtpbnN0YW5jZSwgbWV0YX0gPSBleHRyYWN0U3RhdGUoc3RhdGUsIGluamVjdG9yKTtcblxuICAgICAgbWFuYWdlci5hZGRTdGF0ZShpbnN0YW5jZSwgbWV0YSwgaGFuZGxlT2JzZXJ2YWJsZSk7XG4gICAgICB0aGlzLmFkZEVmZmVjdHMoaW5zdGFuY2UsIG1ldGEuZWZmZWN0cyk7XG4gICAgICBhZGQoaW5zdGFuY2UpO1xuICAgIH0pO1xuXG4gICAgbG9vbmEuZGlzcGF0Y2goe1xuICAgICAgdHlwZTogUk9PVF9FRkZFQ1RTX0lOSVQsXG4gICAgICBzdGF0ZXM6IG5hbWVzLFxuICAgIH0pO1xuICB9XG5cbiAgYWRkRWZmZWN0cyhzdGF0ZTogYW55LCBtZXRhPzogTWV0YWRhdGEuRWZmZWN0cykge1xuICAgIHRoaXMuZWZmZWN0cy5hZGRFZmZlY3RzKHN0YXRlLCBtZXRhKTtcbiAgfVxufVxuXG5ATmdNb2R1bGUoKVxuZXhwb3J0IGNsYXNzIExvb25hQ2hpbGRNb2R1bGUge1xuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KENISUxEX1NUQVRFKSBzdGF0ZXM6IFN0YXRlQ2xhc3M8TWV0YWRhdGE+W10sXG4gICAgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIG1hbmFnZXI6IE1hbmFnZXIsXG4gICAgbG9vbmE6IExvb25hLFxuICAgIHJvb3RNb2R1bGU6IExvb25hUm9vdE1vZHVsZSxcbiAgKSB7XG4gICAgY29uc3Qge25hbWVzLCBhZGR9ID0gbWFwU3RhdGVzKCk7XG5cbiAgICBzdGF0ZXMuZm9yRWFjaChzdGF0ZSA9PiB7XG4gICAgICBjb25zdCB7aW5zdGFuY2UsIG1ldGF9ID0gZXh0cmFjdFN0YXRlKHN0YXRlLCBpbmplY3Rvcik7XG5cbiAgICAgIG1hbmFnZXIuYWRkU3RhdGUoaW5zdGFuY2UsIG1ldGEsIGhhbmRsZU9ic2VydmFibGUpO1xuICAgICAgcm9vdE1vZHVsZS5hZGRFZmZlY3RzKGluc3RhbmNlLCBtZXRhLmVmZmVjdHMpO1xuICAgICAgYWRkKGluc3RhbmNlKTtcbiAgICB9KTtcblxuICAgIGxvb25hLmRpc3BhdGNoKHtcbiAgICAgIHR5cGU6IFVQREFURV9FRkZFQ1RTLFxuICAgICAgc3RhdGVzOiBuYW1lcyxcbiAgICB9KTtcbiAgfVxufVxuXG5ATmdNb2R1bGUoKVxuZXhwb3J0IGNsYXNzIExvb25hTW9kdWxlIHtcbiAgc3RhdGljIGZvclJvb3Qoc3RhdGVzOiBhbnlbXSA9IFtdKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5nTW9kdWxlOiBMb29uYVJvb3RNb2R1bGUsXG4gICAgICBwcm92aWRlcnM6IFtcbiAgICAgICAgTG9vbmEsXG4gICAgICAgIElubmVyQWN0aW9ucyxcbiAgICAgICAgU2Nhbm5lZEFjdGlvbnMsXG4gICAgICAgIHtcbiAgICAgICAgICBwcm92aWRlOiBBY3Rpb25zLFxuICAgICAgICAgIHVzZUV4aXN0aW5nOiBTY2FubmVkQWN0aW9ucyxcbiAgICAgICAgfSxcbiAgICAgICAgLi4uc3RhdGVzLFxuICAgICAgICB7cHJvdmlkZTogSU5JVElBTF9TVEFURSwgdXNlVmFsdWU6IHN0YXRlc30sXG4gICAgICAgIHtcbiAgICAgICAgICBwcm92aWRlOiBNYW5hZ2VyLFxuICAgICAgICAgIHVzZUZhY3Rvcnk6IG1hbmFnZXJGYWN0b3J5LFxuICAgICAgICAgIGRlcHM6IFtMT09OQV9DQUNIRSwgSW5qZWN0b3JdLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgcHJvdmlkZTogTG9vbmFMaW5rLFxuICAgICAgICAgIHVzZUZhY3Rvcnk6IGxpbmtGYWN0b3J5LFxuICAgICAgICAgIGRlcHM6IFtNYW5hZ2VyXSxcbiAgICAgICAgfSxcbiAgICAgICAgRWZmZWN0cyxcbiAgICAgICAgRWZmZWN0c1J1bm5lcixcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBmb3JDaGlsZChzdGF0ZXM6IGFueVtdID0gW10pOiBNb2R1bGVXaXRoUHJvdmlkZXJzIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmdNb2R1bGU6IExvb25hQ2hpbGRNb2R1bGUsXG4gICAgICBwcm92aWRlcnM6IFsuLi5zdGF0ZXMsIHtwcm92aWRlOiBDSElMRF9TVEFURSwgdXNlVmFsdWU6IHN0YXRlc31dLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpbmtGYWN0b3J5KG1hbmFnZXI6IE1hbmFnZXIpOiBMb29uYUxpbmsge1xuICByZXR1cm4gbmV3IExvb25hTGluayhtYW5hZ2VyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1hbmFnZXJGYWN0b3J5KFxuICBjYWNoZTogQXBvbGxvQ2FjaGU8YW55PixcbiAgaW5qZWN0b3I6IEluamVjdG9yLFxuKTogTWFuYWdlciB7XG4gIGNvbnN0IG1hbmFnZXIgPSBuZXcgTWFuYWdlcih7XG4gICAgY2FjaGUsXG4gICAgZ2V0Q2xpZW50OiAoKSA9PiBpbmplY3Rvci5nZXQoQXBvbGxvKS5nZXRDbGllbnQoKSxcbiAgfSk7XG5cbiAgcmV0dXJuIG1hbmFnZXI7XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUE7QUFJQSxNQUFhLGFBQWEsR0FBRyxJQUFJLGNBQWMsQ0FDN0MsYUFBYSxDQUNkOztBQUNELE1BQWEsV0FBVyxHQUFHLElBQUksY0FBYyxDQUMzQyxrQkFBa0IsQ0FDbkI7O0FBQ0QsTUFBYSxXQUFXLEdBQUcsSUFBSSxjQUFjLENBQW1CLGFBQWEsQ0FBQzs7QUFFOUUsTUFBYSxJQUFJLEdBQUcsUUFBUTs7QUFDNUIsTUFBYSxpQkFBaUIsR0FBRyxnQkFBZ0I7O0FBQ2pELE1BQWEsY0FBYyxHQUFHLGtCQUFrQjs7Ozs7O0FDZGhEOzs7QUFNQSxNQUFhLE9BQW9CLFNBQVEsVUFBYTtDQUFHO0FBR3pELE1BQWEsY0FBZSxTQUFRLE9BQWU7Ozs7SUFDakQsV0FBVztRQUNULElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztLQUNqQjs7O1lBSkYsVUFBVTs7QUFRWCxNQUFhLFlBQWEsU0FBUSxlQUF1QjtJQUN2RDtRQUNFLEtBQUssQ0FBQyxFQUFDLElBQUksRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO0tBQ3JCOzs7OztJQUVELElBQUksQ0FBQyxNQUFjO1FBQ2pCLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVyxFQUFFO1lBQ2pDLE1BQU0sSUFBSSxTQUFTLENBQUMseUJBQXlCLENBQUMsQ0FBQztTQUNoRDthQUFNLElBQUksT0FBTyxNQUFNLENBQUMsSUFBSSxLQUFLLFdBQVcsRUFBRTtZQUM3QyxNQUFNLElBQUksU0FBUyxDQUFDLG1DQUFtQyxDQUFDLENBQUM7U0FDMUQ7UUFFRCxL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