UNPKG

@loona/angular

Version:

App State Management done with GraphQL (angular integration)

504 lines (494 loc) 39 kB
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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