@terminus/ngx-tools
Version:
[![CircleCI][circle-badge]][circle-link] [![codecov][codecov-badge]][codecov-project] [![semantic-release][semantic-release-badge]][semantic-release] [![MIT License][license-image]][license-url] <br> [![NPM version][npm-version-image]][npm-url] [![Github
136 lines • 23.3 kB
JavaScript
import { __decorate, __param } from "tslib";
import { Inject, Injectable, InjectionToken, Optional, } from '@angular/core';
import { Actions, Effect, ofType, } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { TsCookieService } from '@terminus/ngx-tools/browser';
import { merge, of, Scheduler, timer, } from 'rxjs';
import { async } from 'rxjs/internal/scheduler/async';
import { delay, filter, flatMap, map, mergeMap, take, withLatestFrom, } from 'rxjs/operators';
import { jwtDecode } from '../jwt-decode/jwt-decode';
import * as JwtTokenProviderActions from './actions';
import { getJwtTokenRoot, getTokens, } from './selectors';
import { INITIAL_TOKEN_NAME } from './tokens';
import { SCHEDULER } from './utilities/retry-with-escalation';
export const SECONDS_BEFORE_EXPIRATION_TO_NOTIFY = new InjectionToken('wait time');
const SECONDS_IN_MINUTE = 60;
const DEFAULT_MINUTES_BEFORE_EXPIRATION_TO_NOTIFY = 5;
const DEFAULT_SECONDS_BEFORE_EXPIRATION_TO_NOTIFY = DEFAULT_MINUTES_BEFORE_EXPIRATION_TO_NOTIFY * SECONDS_IN_MINUTE;
const CLEANUP_DELAY = 100;
const TOKENS_EXPIRED_DELAY = 10;
const MS_IN_SECONDS = 1000;
let JwtTokenProviderEffects = class JwtTokenProviderEffects {
constructor(actions$,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
store, cookieService, initialTokenName, scheduler, timeToWaitBeforeExpiration) {
this.actions$ = actions$;
this.store = store;
this.cookieService = cookieService;
this.initialTokenName = initialTokenName;
this.scheduler = scheduler;
this.timeToWaitBeforeExpiration = timeToWaitBeforeExpiration;
this.initializationCleanup$ = of(true)
.pipe(delay(CLEANUP_DELAY, this.scheduler || async), withLatestFrom(this.store.select(getTokens())), map(([_, tokens]) => tokens), take(1), flatMap(tokens => {
const actions = [];
for (const tokenName in tokens) {
if (tokens.hasOwnProperty(tokenName)) {
const token = tokens[tokenName];
if (token) {
actions.push(new JwtTokenProviderActions.StoreToken({
tokenName,
token,
}));
}
}
}
return actions;
}));
this.allTokensExpired$ = this.actions$
.pipe(ofType(JwtTokenProviderActions.ActionTypes.TokenExpired), delay(TOKENS_EXPIRED_DELAY, this.scheduler || async), withLatestFrom(this.store.select(getTokens())), map(([_, tokens]) => tokens), filter(tokens => Object.keys(tokens).length === 0), map(tokens => new JwtTokenProviderActions.AllTokensExpired()));
this.notifyOfTokenExpiration$ = this.actions$
.pipe(ofType(JwtTokenProviderActions.ActionTypes.StoreToken),
// eslint-disable-next-line max-len
map((action) => [action, jwtDecode(action.token)]), filter((a) => a[1].exp !== undefined), mergeMap(([action, claims]) => {
const currentEpoch = Math.ceil((new Date()).getTime() / MS_IN_SECONDS);
if (claims.exp > currentEpoch) {
const expiresIn = claims.exp - currentEpoch;
const expirationBuffer = this.timeToWaitBeforeExpiration || DEFAULT_SECONDS_BEFORE_EXPIRATION_TO_NOTIFY;
let expirationNearIn = 0;
if (expiresIn < expirationBuffer) {
expirationNearIn = 1;
}
else {
expirationNearIn = expiresIn - expirationBuffer;
}
return merge(this.buildDelayedExpirationObservable(expirationNearIn * MS_IN_SECONDS, action, false), this.buildDelayedExpirationObservable(expiresIn * MS_IN_SECONDS, action, true));
}
return of(new JwtTokenProviderActions.TokenExpired({
tokenName: action.tokenName,
token: action.token,
}));
}));
this.initialCookieLoader$ = ({ currentState = this.store.select(getJwtTokenRoot()), } = {}) => of(true).pipe(take(1), withLatestFrom(currentState), filter(([_, state]) => !!(state && state.jwtTokens.initialTokenStatus === 'uninitialized')), mergeMap(([a, _]) => {
const cookie = this.cookieService.get('jwt_cookie');
if (cookie.length > 0) {
return [
new JwtTokenProviderActions.InitialTokenExtracted(cookie),
new JwtTokenProviderActions.StoreToken({
tokenName: this.initialTokenName,
token: cookie,
isDefaultToken: true,
}),
];
}
return [
new JwtTokenProviderActions.InitialTokenExtracted(cookie),
];
}));
}
/*
* This next function is being excluded from coverage due the complexities of testing the `delay` function.
* In order to test as much as possible, each piece has been separated into smaller testable functions.
*/
buildDelayedExpirationObservable(emitTime, action, expired) {
const outputActionArgs = {
tokenName: action.tokenName,
token: action.token,
};
return timer(emitTime, this.scheduler || async).pipe(take(1), map(() => (expired
? new JwtTokenProviderActions.TokenExpired(outputActionArgs)
: new JwtTokenProviderActions.TokenNearingExpiration(outputActionArgs))));
}
};
JwtTokenProviderEffects.ctorParameters = () => [
{ type: Actions },
{ type: Store },
{ type: TsCookieService },
{ type: String, decorators: [{ type: Inject, args: [INITIAL_TOKEN_NAME,] }] },
{ type: Scheduler, decorators: [{ type: Optional }, { type: Inject, args: [SCHEDULER,] }] },
{ type: Number, decorators: [{ type: Optional }, { type: Inject, args: [SECONDS_BEFORE_EXPIRATION_TO_NOTIFY,] }] }
];
__decorate([
Effect()
], JwtTokenProviderEffects.prototype, "initializationCleanup$", void 0);
__decorate([
Effect()
], JwtTokenProviderEffects.prototype, "allTokensExpired$", void 0);
__decorate([
Effect()
], JwtTokenProviderEffects.prototype, "notifyOfTokenExpiration$", void 0);
__decorate([
Effect()
], JwtTokenProviderEffects.prototype, "initialCookieLoader$", void 0);
JwtTokenProviderEffects = __decorate([
Injectable(),
__param(3, Inject(INITIAL_TOKEN_NAME)),
__param(4, Optional()),
__param(4, Inject(SCHEDULER))
// TODO: Scheduler is marked as deprecated to stop others from using although it is not technically deprecated from
// what I can tell. The 'correct' path would be to create our own class extending `SchedulerLike`.
// https://github.com/GetTerminus/ngx-tools/issues/287
// eslint-disable-next-line deprecation/deprecation
,
__param(5, Optional()),
__param(5, Inject(SECONDS_BEFORE_EXPIRATION_TO_NOTIFY))
], JwtTokenProviderEffects);
export { JwtTokenProviderEffects };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWZmZWN0cy5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0B0ZXJtaW51cy9uZ3gtdG9vbHMvand0LyIsInNvdXJjZXMiOlsiand0LXRva2VuLW1hbmFnbWVudC9lZmZlY3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQ0wsTUFBTSxFQUNOLFVBQVUsRUFDVixjQUFjLEVBQ2QsUUFBUSxHQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxPQUFPLEVBQ1AsTUFBTSxFQUNOLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM5RCxPQUFPLEVBQ0wsS0FBSyxFQUNMLEVBQUUsRUFDRixTQUFTLEVBQ1QsS0FBSyxHQUNOLE1BQU0sTUFBTSxDQUFDO0FBQ2QsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3RELE9BQU8sRUFDTCxLQUFLLEVBQ0wsTUFBTSxFQUNOLE9BQU8sRUFDUCxHQUFHLEVBQ0gsUUFBUSxFQUNSLElBQUksRUFDSixjQUFjLEdBQ2YsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFckQsT0FBTyxLQUFLLHVCQUF1QixNQUFNLFdBQVcsQ0FBQztBQUNyRCxPQUFPLEVBQ0wsZUFBZSxFQUNmLFNBQVMsR0FDVixNQUFNLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDOUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBUzlELE1BQU0sQ0FBQyxNQUFNLG1DQUFtQyxHQUFHLElBQUksY0FBYyxDQUFTLFdBQVcsQ0FBQyxDQUFDO0FBRTNGLE1BQU0saUJBQWlCLEdBQUcsRUFBRSxDQUFDO0FBQzdCLE1B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QU8sS0FBSyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsU0FBUyxJQUFJLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FDbEQsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUNQLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLE9BQU87WUFDaEIsQ0FBQyxDQUFDLElBQUksdUJBQXVCLENBQUMsWUFBWSxDQUFrQixnQkFBZ0IsQ0FBQztZQUM3RSxDQUFDLENBQUMsSUFBSSx1QkFBdUIsQ0FBQyxzQkFBc0IsQ0FBa0IsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQzVGLENBQUM7SUFDSixDQUFDO0NBQ0YsQ0FBQTs7WUF4SnFCLE9BQU87WUFFVixLQUFLO1lBQ0csZUFBZTt5Q0FFckMsTUFBTSxTQUFDLGtCQUFrQjtZQVNQLFNBQVMsdUJBTjNCLFFBQVEsWUFDUixNQUFNLFNBQUMsU0FBUzt5Q0FPaEIsUUFBUSxZQUNSLE1BQU0sU0FBQyxtQ0FBbUM7O0FBTTdDO0lBREMsTUFBTSxFQUFFO3VFQTRCUjtBQUlEO0lBREMsTUFBTSxFQUFFO2tFQVlSO0FBSUQ7SUFEQyxNQUFNLEVBQUU7eUVBaUNSO0FBSUQ7SUFEQyxNQUFNLEVBQUU7cUVBd0JQO0FBbklTLHVCQUF1QjtJQURuQyxVQUFVLEVBQUU7SUFTUixXQUFBLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFBO0lBRzFCLFdBQUEsUUFBUSxFQUFFLENBQUE7SUFDVixXQUFBLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUNsQixtSEFBbUg7SUFDbkgsa0dBQWtHO0lBQ2xHLHNEQUFzRDtJQUN0RCxtREFBbUQ7O0lBR2xELFdBQUEsUUFBUSxFQUFFLENBQUE7SUFDVixXQUFBLE1BQU0sQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFBO0dBcEJuQyx1QkFBdUIsQ0EySm5DO1NBM0pZLHVCQUF1QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEluamVjdCxcbiAgSW5qZWN0YWJsZSxcbiAgSW5qZWN0aW9uVG9rZW4sXG4gIE9wdGlvbmFsLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIEFjdGlvbnMsXG4gIEVmZmVjdCxcbiAgb2ZUeXBlLFxufSBmcm9tICdAbmdyeC9lZmZlY3RzJztcbmltcG9ydCB7IFN0b3JlIH0gZnJvbSAnQG5ncngvc3RvcmUnO1xuaW1wb3J0IHsgVHNDb29raWVTZXJ2aWNlIH0gZnJvbSAnQHRlcm1pbnVzL25neC10b29scy9icm93c2VyJztcbmltcG9ydCB7XG4gIG1lcmdlLFxuICBvZixcbiAgU2NoZWR1bGVyLFxuICB0aW1lcixcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBhc3luYyB9IGZyb20gJ3J4anMvaW50ZXJuYWwvc2NoZWR1bGVyL2FzeW5jJztcbmltcG9ydCB7XG4gIGRlbGF5LFxuICBmaWx0ZXIsXG4gIGZsYXRNYXAsXG4gIG1hcCxcbiAgbWVyZ2VNYXAsXG4gIHRha2UsXG4gIHdpdGhMYXRlc3RGcm9tLFxufSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IGp3dERlY29kZSB9IGZyb20gJy4uL2p3dC1kZWNvZGUvand0LWRlY29kZSc7XG5cbmltcG9ydCAqIGFzIEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zIGZyb20gJy4vYWN0aW9ucyc7XG5pbXBvcnQge1xuICBnZXRKd3RUb2tlblJvb3QsXG4gIGdldFRva2Vucyxcbn0gZnJvbSAnLi9zZWxlY3RvcnMnO1xuaW1wb3J0IHsgSU5JVElBTF9UT0tFTl9OQU1FIH0gZnJvbSAnLi90b2tlbnMnO1xuaW1wb3J0IHsgU0NIRURVTEVSIH0gZnJvbSAnLi91dGlsaXRpZXMvcmV0cnktd2l0aC1lc2NhbGF0aW9uJztcblxuXG5leHBvcnQgaW50ZXJmYWNlIENsYWltcyB7IGV4cDogbnVtYmVyOyB9XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWluaW1hbENsYWltTWFwIHtcbiAgW2lkOiBzdHJpbmddOiBDbGFpbXM7XG59XG5cbmV4cG9ydCBjb25zdCBTRUNPTkRTX0JFRk9SRV9FWFBJUkFUSU9OX1RPX05PVElGWSA9IG5ldyBJbmplY3Rpb25Ub2tlbjxudW1iZXI+KCd3YWl0IHRpbWUnKTtcblxuY29uc3QgU0VDT05EU19JTl9NSU5VVEUgPSA2MDtcbmNvbnN0IERFRkFVTFRfTUlOVVRFU19CRUZPUkVfRVhQSVJBVElPTl9UT19OT1RJRlkgPSA1O1xuY29uc3QgREVGQVVMVF9TRUNPTkRTX0JFRk9SRV9FWFBJUkFUSU9OX1RPX05PVElGWSA9IERFRkFVTFRfTUlOVVRFU19CRUZPUkVfRVhQSVJBVElPTl9UT19OT1RJRlkgKiBTRUNPTkRTX0lOX01JTlVURTtcbmNvbnN0IENMRUFOVVBfREVMQVkgPSAxMDA7XG5jb25zdCBUT0tFTlNfRVhQSVJFRF9ERUxBWSA9IDEwO1xuY29uc3QgTVNfSU5fU0VDT05EUyA9IDEwMDA7XG5cbnR5cGUgUGFydGlhbENsYWltVHVwbGUgPSBbXG4gIEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLlN0b3JlVG9rZW48TWluaW1hbENsYWltTWFwPixcbiAgUGFydGlhbDxDbGFpbXM+XG5dO1xuXG50eXBlIEZ1bGxDbGFpbXNUdXBsZSA9IFtcbiAgSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuU3RvcmVUb2tlbjxNaW5pbWFsQ2xhaW1NYXA+LFxuICBDbGFpbXNcbl07XG5cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEp3dFRva2VuUHJvdmlkZXJFZmZlY3RzIHtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGFjdGlvbnMkOiBBY3Rpb25zPEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLkFjdGlvbnM8TWluaW1hbENsYWltTWFwPj4sXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBwcml2YXRlIHN0b3JlOiBTdG9yZTxhbnk+LFxuICAgIHByaXZhdGUgY29va2llU2VydmljZTogVHNDb29raWVTZXJ2aWNlLFxuXG4gICAgQEluamVjdChJTklUSUFMX1RPS0VOX05BTUUpXG4gICAgcHJpdmF0ZSBpbml0aWFsVG9rZW5OYW1lOiBzdHJpbmcsXG5cbiAgICBAT3B0aW9uYWwoKVxuICAgIEBJbmplY3QoU0NIRURVTEVSKVxuICAgIC8vIFRPRE86IFNjaGVkdWxlciBpcyBtYXJrZWQgYXMgZGVwcmVjYXRlZCB0byBzdG9wIG90aGVycyBmcm9tIHVzaW5nIGFsdGhvdWdoIGl0IGlzIG5vdCB0ZWNobmljYWxseSBkZXByZWNhdGVkIGZyb21cbiAgICAvLyB3aGF0IEkgY2FuIHRlbGwuIFRoZSAnY29ycmVjdCcgcGF0aCB3b3VsZCBiZSB0byBjcmVhdGUgb3VyIG93biBjbGFzcyBleHRlbmRpbmcgYFNjaGVkdWxlckxpa2VgLlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9HZXRUZXJtaW51cy9uZ3gtdG9vbHMvaXNzdWVzLzI4N1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvblxuICAgIHByaXZhdGUgc2NoZWR1bGVyOiBTY2hlZHVsZXIsXG5cbiAgICBAT3B0aW9uYWwoKVxuICAgIEBJbmplY3QoU0VDT05EU19CRUZPUkVfRVhQSVJBVElPTl9UT19OT1RJRlkpXG4gICAgcHJpdmF0ZSB0aW1lVG9XYWl0QmVmb3JlRXhwaXJhdGlvbjogbnVtYmVyLFxuICApIHt9XG5cblxuICBARWZmZWN0KClcbiAgcHVibGljIGluaXRpYWxpemF0aW9uQ2xlYW51cCQgPSBvZih0cnVlKVxuICAgIC5waXBlKFxuICAgICAgZGVsYXkoQ0xFQU5VUF9ERUxBWSwgdGhpcy5zY2hlZHVsZXIgfHwgYXN5bmMpLFxuICAgICAgd2l0aExhdGVzdEZyb20oXG4gICAgICAgIHRoaXMuc3RvcmUuc2VsZWN0KGdldFRva2VuczxNaW5pbWFsQ2xhaW1NYXA+KCkpLFxuICAgICAgKSxcbiAgICAgIG1hcCgoW18sIHRva2Vuc10pID0+IHRva2VucyksXG4gICAgICB0YWtlKDEpLFxuICAgICAgZmxhdE1hcCh0b2tlbnMgPT4ge1xuICAgICAgICBjb25zdCBhY3Rpb25zOiBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5TdG9yZVRva2VuPE1pbmltYWxDbGFpbU1hcD5bXSA9IFtdO1xuXG4gICAgICAgIGZvciAoY29uc3QgdG9rZW5OYW1lIGluIHRva2Vucykge1xuICAgICAgICAgIGlmICh0b2tlbnMuaGFzT3duUHJvcGVydHkodG9rZW5OYW1lKSkge1xuICAgICAgICAgICAgY29uc3QgdG9rZW4gPSB0b2tlbnNbdG9rZW5OYW1lXTtcbiAgICAgICAgICAgIGlmICh0b2tlbikge1xuICAgICAgICAgICAgICBhY3Rpb25zLnB1c2goXG4gICAgICAgICAgICAgICAgbmV3IEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLlN0b3JlVG9rZW4oe1xuICAgICAgICAgICAgICAgICAgdG9rZW5OYW1lLFxuICAgICAgICAgICAgICAgICAgdG9rZW4sXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhY3Rpb25zO1xuICAgICAgfSksXG4gICAgKVxuICA7XG5cblxuICBARWZmZWN0KClcbiAgcHVibGljIGFsbFRva2Vuc0V4cGlyZWQkID0gdGhpcy5hY3Rpb25zJFxuICAgIC5waXBlKFxuICAgICAgb2ZUeXBlPG5ldmVyPihKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5BY3Rpb25UeXBlcy5Ub2tlbkV4cGlyZWQpLFxuICAgICAgZGVsYXkoVE9LRU5TX0VYUElSRURfREVMQVksIHRoaXMuc2NoZWR1bGVyIHx8IGFzeW5jKSxcbiAgICAgIHdpdGhMYXRlc3RGcm9tKFxuICAgICAgICB0aGlzLnN0b3JlLnNlbGVjdChnZXRUb2tlbnM8TWluaW1hbENsYWltTWFwPigpKSxcbiAgICAgICksXG4gICAgICBtYXAoKFtfLCB0b2tlbnNdKSA9PiB0b2tlbnMpLFxuICAgICAgZmlsdGVyKHRva2VucyA9PiBPYmplY3Qua2V5cyh0b2tlbnMpLmxlbmd0aCA9PT0gMCksXG4gICAgICBtYXAodG9rZW5zID0+IG5ldyBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5BbGxUb2tlbnNFeHBpcmVkKCkpLFxuICAgIClcbiAgO1xuXG5cbiAgQEVmZmVjdCgpXG4gIHB1YmxpYyBub3RpZnlPZlRva2VuRXhwaXJhdGlvbiQgPSB0aGlzLmFjdGlvbnMkXG4gICAgLnBpcGUoXG4gICAgICBvZlR5cGU8Snd0VG9rZW5Qcm92aWRlckFjdGlvbnMuU3RvcmVUb2tlbjxNaW5pbWFsQ2xhaW1NYXA+PihKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5BY3Rpb25UeXBlcy5TdG9yZVRva2VuKSxcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG4gICAgICBtYXAoKGFjdGlvbjogSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuU3RvcmVUb2tlbjxNaW5pbWFsQ2xhaW1NYXA+KTogUGFydGlhbENsYWltVHVwbGUgPT4gW2FjdGlvbiwgand0RGVjb2RlPFBhcnRpYWw8Q2xhaW1zPj4oYWN0aW9uLnRva2VuKV0pLFxuICAgICAgZmlsdGVyKChhOiBQYXJ0aWFsQ2xhaW1UdXBsZSk6IGEgaXMgRnVsbENsYWltc1R1cGxlID0+IGFbMV0uZXhwICE9PSB1bmRlZmluZWQpLFxuICAgICAgbWVyZ2VNYXAoKFthY3Rpb24sIGNsYWltc10pID0+IHtcbiAgICAgICAgY29uc3QgY3VycmVudEVwb2NoID0gTWF0aC5jZWlsKChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLyBNU19JTl9TRUNPTkRTKTtcblxuICAgICAgICBpZiAoY2xhaW1zLmV4cCA+IGN1cnJlbnRFcG9jaCkge1xuICAgICAgICAgIGNvbnN0IGV4cGlyZXNJbiA9IGNsYWltcy5leHAgLSBjdXJyZW50RXBvY2g7XG4gICAgICAgICAgY29uc3QgZXhwaXJhdGlvbkJ1ZmZlciA9IHRoaXMudGltZVRvV2FpdEJlZm9yZUV4cGlyYXRpb24gfHwgREVGQVVMVF9TRUNPTkRTX0JFRk9SRV9FWFBJUkFUSU9OX1RPX05PVElGWTtcbiAgICAgICAgICBsZXQgZXhwaXJhdGlvbk5lYXJJbiA9IDA7XG5cbiAgICAgICAgICBpZiAoZXhwaXJlc0luIDwgZXhwaXJhdGlvbkJ1ZmZlcikge1xuICAgICAgICAgICAgZXhwaXJhdGlvbk5lYXJJbiA9IDE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV4cGlyYXRpb25OZWFySW4gPSBleHBpcmVzSW4gLSBleHBpcmF0aW9uQnVmZmVyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBtZXJnZShcbiAgICAgICAgICAgIHRoaXMuYnVpbGREZWxheWVkRXhwaXJhdGlvbk9ic2VydmFibGUoZXhwaXJhdGlvbk5lYXJJbiAqIE1TX0lOX1NFQ09ORFMsIGFjdGlvbiwgZmFsc2UpLFxuICAgICAgICAgICAgdGhpcy5idWlsZERlbGF5ZWRFeHBpcmF0aW9uT2JzZXJ2YWJsZShleHBpcmVzSW4gKiBNU19JTl9TRUNPTkRTLCBhY3Rpb24sIHRydWUpLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9mKG5ldyBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5Ub2tlbkV4cGlyZWQ8TWluaW1hbENsYWltTWFwPih7XG4gICAgICAgICAgdG9rZW5OYW1lOiBhY3Rpb24udG9rZW5OYW1lLFxuICAgICAgICAgIHRva2VuOiBhY3Rpb24udG9rZW4sXG4gICAgICAgIH0pKTtcblxuICAgICAgfSksXG4gICAgKVxuICA7XG5cblxuICBARWZmZWN0KClcbiAgcHVibGljIGluaXRpYWxDb29raWVMb2FkZXIkID0gKHtcbiAgICBjdXJyZW50U3RhdGUgPSB0aGlzLnN0b3JlLnNlbGVjdChnZXRKd3RUb2tlblJvb3QoKSksXG4gIH0gPSB7fSkgPT4gb2YodHJ1ZSkucGlwZShcbiAgICB0YWtlKDEpLFxuICAgIHdpdGhMYXRlc3RGcm9tKGN1cnJlbnRTdGF0ZSksXG4gICAgZmlsdGVyKChbXywgc3RhdGVdKSA9PiAhIShzdGF0ZSAmJiBzdGF0ZS5qd3RUb2tlbnMuaW5pdGlhbFRva2VuU3RhdHVzID09PSAndW5pbml0aWFsaXplZCcpKSxcbiAgICBtZXJnZU1hcCgoW2EsIF9dKSA9PiB7XG4gICAgICBjb25zdCBjb29raWUgPSB0aGlzLmNvb2tpZVNlcnZpY2UuZ2V0KCdqd3RfY29va2llJyk7XG4gICAgICBpZiAoY29va2llLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICBuZXcgSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuSW5pdGlhbFRva2VuRXh0cmFjdGVkKGNvb2tpZSksXG4gICAgICAgICAgbmV3IEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLlN0b3JlVG9rZW4oe1xuICAgICAgICAgICAgdG9rZW5OYW1lOiB0aGlzLmluaXRpYWxUb2tlbk5hbWUsXG4gICAgICAgICAgICB0b2tlbjogY29va2llLFxuICAgICAgICAgICAgaXNEZWZhdWx0VG9rZW46IHRydWUsXG4gICAgICAgICAgfSksXG4gICAgICAgIF07XG4gICAgICB9XG4gICAgICByZXR1cm4gW1xuICAgICAgICBuZXcgSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuSW5pdGlhbFRva2VuRXh0cmFjdGVkKGNvb2tpZSksXG4gICAgICBdO1xuXG4gICAgfSksXG4gICk7XG5cblxuICAvKlxuICAgKiBUaGlzIG5leHQgZnVuY3Rpb24gaXMgYmVpbmcgZXhjbHVkZWQgZnJvbSBjb3ZlcmFnZSBkdWUgdGhlIGNvbXBsZXhpdGllcyBvZiB0ZXN0aW5nIHRoZSBgZGVsYXlgIGZ1bmN0aW9uLlxuICAgKiBJbiBvcmRlciB0byB0ZXN0IGFzIG11Y2ggYXMgcG9zc2libGUsIGVhY2ggcGllY2UgaGFzIGJlZW4gc2VwYXJhdGVkIGludG8gc21hbGxlciB0ZXN0YWJsZSBmdW5jdGlvbnMuXG4gICAqL1xuICBwdWJsaWMgYnVpbGREZWxheWVkRXhwaXJhdGlvbk9ic2VydmFibGUoXG4gICAgZW1pdFRpbWU6IG51bWJlciB8IERhdGUsXG4gICAgYWN0aW9uOiBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5TdG9yZVRva2VuPE1pbmltYWxDbGFpbU1hcD4sXG4gICAgZXhwaXJlZDogYm9vbGVhbixcbiAgKSB7XG4gICAgY29uc3Qgb3V0cHV0QWN0aW9uQXJncyA9IHtcbiAgICAgIHRva2VuTmFtZTogYWN0aW9uLnRva2VuTmFtZSxcbiAgICAgIHRva2VuOiBhY3Rpb24udG9rZW4sXG4gICAgfTtcblxuICAgIHJldHVybiB0aW1lcihlbWl0VGltZSwgdGhpcy5zY2hlZHVsZXIgfHwgYXN5bmMpLnBpcGUoXG4gICAgICB0YWtlKDEpLFxuICAgICAgbWFwKCgpID0+IChleHBpcmVkXG4gICAgICAgID8gbmV3IEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLlRva2VuRXhwaXJlZDxNaW5pbWFsQ2xhaW1NYXA+KG91dHB1dEFjdGlvbkFyZ3MpXG4gICAgICAgIDogbmV3IEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLlRva2VuTmVhcmluZ0V4cGlyYXRpb248TWluaW1hbENsYWltTWFwPihvdXRwdXRBY3Rpb25BcmdzKSkpLFxuICAgICk7XG4gIH1cbn1cbiJdfQ==