@loona/angular
Version:
App State Management done with GraphQL (angular integration)
583 lines (573 loc) • 42.7 kB
JavaScript
import { InjectionToken, Injectable, ErrorHandler, Inject, NgModule, Injector } from '@angular/core';
import { __extends, __assign, __spread } from 'tslib';
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 {?} */
var INITIAL_STATE = new InjectionToken('Loona/State');
/** @type {?} */
var CHILD_STATE = new InjectionToken('Loona/ChildState');
/** @type {?} */
var LOONA_CACHE = new InjectionToken('Loona/Cache');
/** @type {?} */
var INIT = '@@init';
/** @type {?} */
var ROOT_EFFECTS_INIT = '@@effects/init';
/** @type {?} */
var UPDATE_EFFECTS = '@@effects/update';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
/**
* @template V
*/
var /**
* @template V
*/
Actions = /** @class */ (function (_super) {
__extends(Actions, _super);
function Actions() {
return _super !== null && _super.apply(this, arguments) || this;
}
return Actions;
}(Observable));
var ScannedActions = /** @class */ (function (_super) {
__extends(ScannedActions, _super);
function ScannedActions() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* @return {?}
*/
ScannedActions.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.complete();
};
ScannedActions.decorators = [
{ type: Injectable }
];
return ScannedActions;
}(Subject));
var InnerActions = /** @class */ (function (_super) {
__extends(InnerActions, _super);
function InnerActions() {
return _super.call(this, { type: INIT }) || this;
}
/**
* @param {?} action
* @return {?}
*/
InnerActions.prototype.next = /**
* @param {?} action
* @return {?}
*/
function (action) {
if (typeof action === 'undefined') {
throw new TypeError("Actions must be objects");
}
else if (typeof action.type === 'undefined') {
throw new TypeError("Actions must have a type property");
}
_super.prototype.next.call(this, action);
};
/**
* @return {?}
*/
InnerActions.prototype.complete = /**
* @return {?}
*/
function () { };
/**
* @return {?}
*/
InnerActions.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
_super.prototype.complete.call(this);
};
InnerActions.decorators = [
{ type: Injectable }
];
/** @nocollapse */
InnerActions.ctorParameters = function () { return []; };
return InnerActions;
}(BehaviorSubject));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var Loona = /** @class */ (function () {
function Loona(apollo, manager, actions, scannedActions, errorHandler) {
this.apollo = apollo;
this.manager = manager;
this.actions = actions;
this.direct$ = new Subject();
this.queue$ = merge(actions, this.direct$).pipe(observeOn(queueScheduler));
this.queue$.subscribe({
next: function (action) {
scannedActions.next(action);
},
error: function (error) {
errorHandler.handleError(error);
},
});
}
/**
* @template T, V
* @param {?} queryOrOptions
* @param {?=} variables
* @param {?=} options
* @return {?}
*/
Loona.prototype.query = /**
* @template T, V
* @param {?} queryOrOptions
* @param {?=} variables
* @param {?=} options
* @return {?}
*/
function (queryOrOptions, variables, options) {
return this.apollo.watchQuery(isDocument(queryOrOptions)
? __assign({ query: queryOrOptions, variables: variables }, options) : queryOrOptions);
};
/**
* @template T, V
* @param {?} mutationOrOptions
* @param {?=} variables
* @param {?=} options
* @return {?}
*/
Loona.prototype.mutate = /**
* @template T, V
* @param {?} mutationOrOptions
* @param {?=} variables
* @param {?=} options
* @return {?}
*/
function (mutationOrOptions, variables, options) {
var _this = this;
/** @type {?} */
var config = isDocument(mutationOrOptions)
? __assign({ mutation: mutationOrOptions, variables: variables }, options) : mutationOrOptions;
return this.apollo
.mutate(withUpdates(config, this.manager))
.pipe(tap(function (result) {
_this.direct$.next(buildActionFromResult(config, result));
}), catchError(function (error) {
_this.direct$.next(buildActionFromError(config, error));
return throwError(error);
}));
};
/**
* @param {?} action
* @return {?}
*/
Loona.prototype.dispatch = /**
* @param {?} action
* @return {?}
*/
function (action) {
if (isMutation(action)) {
/** @type {?} */
var mutation = getMutation(action);
this.mutate(__assign({ mutation: mutation }, action)).subscribe();
}
else {
this.actions.next(__assign({ type: getActionType(action) }, action));
}
};
/**
* @template T
* @return {?}
*/
Loona.prototype.extract = /**
* @template T
* @return {?}
*/
function () {
return this.apollo.getClient().extract();
};
/**
* @return {?}
*/
Loona.prototype.reset = /**
* @return {?}
*/
function () {
this.apollo.getClient().resetStore();
};
/**
* @param {?} state
* @return {?}
*/
Loona.prototype.restore = /**
* @param {?} state
* @return {?}
*/
function (state) {
this.apollo.getClient().restore(state);
};
Loona.decorators = [
{ type: Injectable }
];
/** @nocollapse */
Loona.ctorParameters = function () { return [
{ type: Apollo },
{ type: Manager },
{ type: InnerActions },
{ type: ScannedActions },
{ type: ErrorHandler }
]; };
return Loona;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var Effects = /** @class */ (function () {
function Effects(loona, apollo, cache) {
this.effects = {};
this.getContext = function () { return (__assign({}, buildContext({
cache: cache,
getCacheKey: buildGetCacheKey(cache),
}, apollo.getClient()), { dispatch: loona.dispatch.bind(loona) })); };
}
/**
* @param {?} instance
* @param {?=} meta
* @return {?}
*/
Effects.prototype.addEffects = /**
* @param {?} instance
* @param {?=} meta
* @return {?}
*/
function (instance, meta) {
var _this = this;
if (!meta) {
return;
}
var _loop_1 = function (type) {
if (!this_1.effects[type]) {
this_1.effects[type] = [];
}
meta[type].forEach(function (_a) {
var propName = _a.propName;
_this.effects[type].push(instance[propName].bind(instance));
});
};
var this_1 = this;
for (var type in meta) {
_loop_1(type);
}
};
/**
* @param {?} action
* @return {?}
*/
Effects.prototype.runEffects = /**
* @param {?} action
* @return {?}
*/
function (action) {
var _this = this;
/** @type {?} */
var type = action.type;
if (isMutationAsAction(action)) {
type = getNameOfMutation(action.options.mutation);
}
/** @type {?} */
var effectsToRun = this.effects[type];
if (effectsToRun) {
effectsToRun.forEach(function (effect) {
effect(action, _this.getContext());
});
}
};
Effects.decorators = [
{ type: Injectable }
];
/** @nocollapse */
Effects.ctorParameters = function () { return [
{ type: Loona },
{ type: Apollo },
{ type: ApolloCache, decorators: [{ type: Inject, args: [LOONA_CACHE,] }] }
]; };
return Effects;
}());
var EffectsRunner = /** @class */ (function () {
function EffectsRunner(effects, scannedActions) {
this.effects = effects;
this.scannedActions = scannedActions;
this.actionsSubscription = null;
}
/**
* @return {?}
*/
EffectsRunner.prototype.start = /**
* @return {?}
*/
function () {
var _this = this;
if (!this.actionsSubscription) {
this.actionsSubscription = this.scannedActions.subscribe(function (action) {
_this.effects.runEffects(action);
});
}
};
/**
* @return {?}
*/
EffectsRunner.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
if (this.actionsSubscription) {
this.actionsSubscription.unsubscribe();
this.actionsSubscription = null;
}
};
EffectsRunner.decorators = [
{ type: Injectable }
];
/** @nocollapse */
EffectsRunner.ctorParameters = function () { return [
{ type: Effects },
{ type: ScannedActions }
]; };
return EffectsRunner;
}());
/**
* @return {?}
*/
function mapStates() {
/** @type {?} */
var names = [];
/** @type {?} */
var add = function (state) {
names.push(state.constructor && state.constructor.name);
};
return { names: names, add: add };
}
/**
* @param {?} state
* @param {?} injector
* @return {?}
*/
function extractState(state, injector) {
return {
instance: injector.get(state),
meta: state[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 function () {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
/** @type {?} */
var result;
try {
result = resolver.apply(void 0, __spread(args));
}
catch (e) {
return Promise.reject(e);
}
return result instanceof Promise || isObservable(result)
? from(result).toPromise()
: Promise.resolve(result);
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc
*/
var LoonaRootModule = /** @class */ (function () {
function LoonaRootModule(effects, states, loona, manager, runner, injector) {
var _this = this;
this.effects = effects;
runner.start();
var _a = mapStates(), names = _a.names, add = _a.add;
states.forEach(function (state) {
var _a = extractState(state, injector), instance = _a.instance, meta = _a.meta;
manager.addState(instance, meta, handleObservable);
_this.addEffects(instance, meta.effects);
add(instance);
});
loona.dispatch({
type: ROOT_EFFECTS_INIT,
states: names,
});
}
/**
* @param {?} state
* @param {?=} meta
* @return {?}
*/
LoonaRootModule.prototype.addEffects = /**
* @param {?} state
* @param {?=} meta
* @return {?}
*/
function (state, meta) {
this.effects.addEffects(state, meta);
};
LoonaRootModule.decorators = [
{ type: NgModule }
];
/** @nocollapse */
LoonaRootModule.ctorParameters = function () { return [
{ type: Effects },
{ type: Array, decorators: [{ type: Inject, args: [INITIAL_STATE,] }] },
{ type: Loona },
{ type: Manager },
{ type: EffectsRunner },
{ type: Injector }
]; };
return LoonaRootModule;
}());
var LoonaChildModule = /** @class */ (function () {
function LoonaChildModule(states, injector, manager, loona, rootModule) {
var _a = mapStates(), names = _a.names, add = _a.add;
states.forEach(function (state) {
var _a = extractState(state, injector), instance = _a.instance, meta = _a.meta;
manager.addState(instance, meta, handleObservable);
rootModule.addEffects(instance, meta.effects);
add(instance);
});
loona.dispatch({
type: UPDATE_EFFECTS,
states: names,
});
}
LoonaChildModule.decorators = [
{ type: NgModule }
];
/** @nocollapse */
LoonaChildModule.ctorParameters = function () { return [
{ type: Array, decorators: [{ type: Inject, args: [CHILD_STATE,] }] },
{ type: Injector },
{ type: Manager },
{ type: Loona },
{ type: LoonaRootModule }
]; };
return LoonaChildModule;
}());
var LoonaModule = /** @class */ (function () {
function LoonaModule() {
}
/**
* @param {?=} states
* @return {?}
*/
LoonaModule.forRoot = /**
* @param {?=} states
* @return {?}
*/
function (states) {
if (states === void 0) { states = []; }
return {
ngModule: LoonaRootModule,
providers: __spread([
Loona,
InnerActions,
ScannedActions,
{
provide: Actions,
useExisting: ScannedActions,
}
], states, [
{ provide: INITIAL_STATE, useValue: states },
{
provide: Manager,
useFactory: managerFactory,
deps: [LOONA_CACHE, Injector],
},
{
provide: LoonaLink,
useFactory: linkFactory,
deps: [Manager],
},
Effects,
EffectsRunner,
]),
};
};
/**
* @param {?=} states
* @return {?}
*/
LoonaModule.forChild = /**
* @param {?=} states
* @return {?}
*/
function (states) {
if (states === void 0) { states = []; }
return {
ngModule: LoonaChildModule,
providers: __spread(states, [{ provide: CHILD_STATE, useValue: states }]),
};
};
LoonaModule.decorators = [
{ type: NgModule }
];
return LoonaModule;
}());
/**
* @param {?} manager
* @return {?}
*/
function linkFactory(manager) {
return new LoonaLink(manager);
}
/**
* @param {?} cache
* @param {?} injector
* @return {?}
*/
function managerFactory(cache, injector) {
/** @type {?} */
var manager = new Manager({
cache: cache,
getClient: function () { return 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+W10sXG4gICAgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIG1hbmFnZXI6IE1hbmFnZXIsXG4gICAgbG9vbmE6IExvb25hLFxuICAgIHJvb3RNb2R1bGU6IExvb25hUm9vdE1vZHVsZSxcbiAgKSB7XG4gICAgY29uc3Qge25hbWVzLCBhZGR9ID0gbWFwU3RhdGVzKCk7XG5cbiAgICBzdGF0ZXMuZm9yRWFjaChzdGF0ZSA9PiB7XG4gICAgICBjb25zdCB7aW5zdGFuY2UsIG1ldGF9ID0gZXh0cmFjdFN0YXRlKHN0YXRlLCBpbmplY3Rvcik7XG5cbiAgICAgIG1hbmFnZXIuYWRkU3RhdGUoaW5zdGFuY2UsIG1ldGEsIGhhbmRsZU9ic2VydmFibGUpO1xuICAgICAgcm9vdE1vZHVsZS5hZGRFZmZlY3RzKGluc3RhbmNlLCBtZXRhLmVmZmVjdHMpO1xuICAgICAgYWRkKGluc3RhbmNlKTtcbiAgICB9KTtcblxuICAgIGxvb25hLmRpc3BhdGNoKHtcbiAgICAgIHR5cGU6IFVQREFURV9FRkZFQ1RTLFxuICAgICAgc3RhdGVzOiBuYW1lcyxcbiAgICB9KTtcbiAgfVxufVxuXG5ATmdNb2R1bGUoKVxuZXhwb3J0IGNsYXNzIExvb25hTW9kdWxlIHtcbiAgc3RhdGljIGZvclJvb3Qoc3RhdGVzOiBhbnlbXSA9IFtdKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5nTW9kdWxlOiBMb29uYVJvb3RNb2R1bGUsXG4gICAgICBwcm92aWRlcnM6IFtcbiAgICAgICAgTG9vbmEsXG4gICAgICAgIElubmVyQWN0aW9ucyxcbiAgICAgICAgU2Nhbm5lZEFjdGlvbnMsXG4gICAgICAgIHtcbiAgICAgICAgICBwcm92aWRlOiBBY3Rpb25zLFxuICAgICAgICAgIHVzZUV4aXN0aW5nOiBTY2FubmVkQWN0aW9ucyxcbiAgICAgICAgfSxcbiAgICAgICAgLi4uc3RhdGVzLFxuICAgICAgICB7cHJvdmlkZTogSU5JVElBTF9TVEFURSwgdXNlVmFsdWU6IHN0YXRlc30sXG4gICAgICAgIHtcbiAgICAgICAgICBwcm92aWRlOiBNYW5hZ2VyLFxuICAgICAgICAgIHVzZUZhY3Rvcnk6IG1hbmFnZXJGYWN0b3J5LFxuICAgICAgICAgIGRlcHM6IFtMT09OQV9DQUNIRSwgSW5qZWN0b3JdLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgcHJvdmlkZTogTG9vbmFMaW5rLFxuICAgICAgICAgIHVzZUZhY3Rvcnk6IGxpbmtGYWN0b3J5LFxuICAgICAgICAgIGRlcHM6IFtNYW5hZ2VyXSxcbiAgICAgICAgfSxcbiAgICAgICAgRWZmZWN0cyxcbiAgICAgICAgRWZmZWN0c1J1bm5lcixcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIHN0YXRpYyBmb3JDaGlsZChzdGF0ZXM6IGFueVtdID0gW10pOiBNb2R1bGVXaXRoUHJvdmlkZXJzIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmdNb2R1bGU6IExvb25hQ2hpbGRNb2R1bGUsXG4gICAgICBwcm92aWRlcnM6IFsuLi5zdGF0ZXMsIHtwcm92aWRlOiBDSElMRF9TVEFURSwgdXNlVmFsdWU6IHN0YXRlc31dLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpbmtGYWN0b3J5KG1hbmFnZXI6IE1hbmFnZXIpOiBMb29uYUxpbmsge1xuICByZXR1cm4gbmV3IExvb25hTGluayhtYW5hZ2VyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1hbmFnZXJGYWN0b3J5KFxuICBjYWNoZTogQXBvbGxvQ2FjaGU8YW55PixcbiAgaW5qZWN0b3I6IEluamVjdG9yLFxuKTogTWFuYWdlciB7XG4gIGNvbnN0IG1hbmFnZXIgPSBuZXcgTWFuYWdlcih7XG4gICAgY2FjaGUsXG4gICAgZ2V0Q2xpZW50OiAoKSA9PiBpbmplY3Rvci5nZXQoQXBvbGxvKS5nZXRDbGllbnQoKSxcbiAgfSk7XG5cbiAgcmV0dXJuIG1hbmFnZXI7XG59XG4iXSwibmFtZXMiOlsidHNsaWJfMS5fX2V4dGVuZHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUlBLElBQWEsYUFBYSxHQUFHLElBQUksY0FBYyxDQUM3QyxhQUFhLENBQ2Q7O0FBQ0QsSUFBYSxXQUFXLEdBQUcsSUFBSSxjQUFjLENBQzNDLGtCQUFrQixDQUNuQjs7QUFDRCxJQUFhLFdBQVcsR0FBRyxJQUFJLGNBQWMsQ0FBbUIsYUFBYSxDQUFDOztBQUU5RSxJQUFhLElBQUksR0FBRyxRQUFROztBQUM1QixJQUFhLGlCQUFpQixHQUFHLGdCQUFnQjs7QUFDakQsSUFBYSxjQUFjLEdBQUcsa0JBQWtCOzs7Ozs7Ozs7QUNSaEQ7Ozs7SUFBeUNBLDJCQUFhO0lBQXREOztLQUF5RDtJQUFELGNBQUM7Q0FBekQsQ0FBeUMsVUFBVSxHQUFNOztJQUdyQkEsa0NBQWU7SUFEbkQ7O0tBS0M7Ozs7SUFIQyxvQ0FBVzs7O0lBQVg7UUFDRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDakI7O2dCQUpGLFVBQVU7O0lBS1gscUJBQUM7Q0FBQSxDQUptQyxPQUFPLEdBSTFDOztJQUdpQ0EsZ0NBQXVCO0lBQ3ZEO2VBQ0Usa0JBQU0sRUFBQyxJQUFJLEVBQUUsSUFBSSxFQUFDLENBQUM7S0FDcEI7Ozs7O0lBRUQsMkJBQUk7Ozs7SUFBSixVQUFLLE1BQWM7UUFDakIsSUFBSSxPQUFPLE1BQU0sS0FBSyxXQUFXLEVBQUU7WUFDakMsTUFBTSxJQUFJLFNBQVMsQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1NBQ2hEO2FBQU0sSUFBSSxPQUFPLE1BQU0s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