@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
152 lines • 24.3 kB
JavaScript
import { __decorate, __param, __read } 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 var SECONDS_BEFORE_EXPIRATION_TO_NOTIFY = new InjectionToken('wait time');
var SECONDS_IN_MINUTE = 60;
var DEFAULT_MINUTES_BEFORE_EXPIRATION_TO_NOTIFY = 5;
var DEFAULT_SECONDS_BEFORE_EXPIRATION_TO_NOTIFY = DEFAULT_MINUTES_BEFORE_EXPIRATION_TO_NOTIFY * SECONDS_IN_MINUTE;
var CLEANUP_DELAY = 100;
var TOKENS_EXPIRED_DELAY = 10;
var MS_IN_SECONDS = 1000;
var JwtTokenProviderEffects = /** @class */ (function () {
function JwtTokenProviderEffects(actions$,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
store, cookieService, initialTokenName, scheduler, timeToWaitBeforeExpiration) {
var _this = this;
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(function (_a) {
var _b = __read(_a, 2), _ = _b[0], tokens = _b[1];
return tokens;
}), take(1), flatMap(function (tokens) {
var actions = [];
for (var tokenName in tokens) {
if (tokens.hasOwnProperty(tokenName)) {
var token = tokens[tokenName];
if (token) {
actions.push(new JwtTokenProviderActions.StoreToken({
tokenName: tokenName,
token: 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(function (_a) {
var _b = __read(_a, 2), _ = _b[0], tokens = _b[1];
return tokens;
}), filter(function (tokens) { return Object.keys(tokens).length === 0; }), map(function (tokens) { return new JwtTokenProviderActions.AllTokensExpired(); }));
this.notifyOfTokenExpiration$ = this.actions$
.pipe(ofType(JwtTokenProviderActions.ActionTypes.StoreToken),
// eslint-disable-next-line max-len
map(function (action) { return [action, jwtDecode(action.token)]; }), filter(function (a) { return a[1].exp !== undefined; }), mergeMap(function (_a) {
var _b = __read(_a, 2), action = _b[0], claims = _b[1];
var currentEpoch = Math.ceil((new Date()).getTime() / MS_IN_SECONDS);
if (claims.exp > currentEpoch) {
var expiresIn = claims.exp - currentEpoch;
var expirationBuffer = _this.timeToWaitBeforeExpiration || DEFAULT_SECONDS_BEFORE_EXPIRATION_TO_NOTIFY;
var 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$ = function (_a) {
var _b = (_a === void 0 ? {} : _a).currentState, currentState = _b === void 0 ? _this.store.select(getJwtTokenRoot()) : _b;
return of(true).pipe(take(1), withLatestFrom(currentState), filter(function (_a) {
var _b = __read(_a, 2), _ = _b[0], state = _b[1];
return !!(state && state.jwtTokens.initialTokenStatus === 'uninitialized');
}), mergeMap(function (_a) {
var _b = __read(_a, 2), a = _b[0], _ = _b[1];
var 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.
*/
JwtTokenProviderEffects.prototype.buildDelayedExpirationObservable = function (emitTime, action, expired) {
var outputActionArgs = {
tokenName: action.tokenName,
token: action.token,
};
return timer(emitTime, this.scheduler || async).pipe(take(1), map(function () { return (expired
? new JwtTokenProviderActions.TokenExpired(outputActionArgs)
: new JwtTokenProviderActions.TokenNearingExpiration(outputActionArgs)); }));
};
JwtTokenProviderEffects.ctorParameters = function () { return [
{ 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);
return JwtTokenProviderEffects;
}());
export { JwtTokenProviderEffects };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWZmZWN0cy5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0B0ZXJtaW51cy9uZ3gtdG9vbHMvand0LyIsInNvdXJjZXMiOlsiand0LXRva2VuLW1hbmFnbWVudC9lZmZlY3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQ0wsTUFBTSxFQUNOLFVBQVUsRUFDVixjQUFjLEVBQ2QsUUFBUSxHQUNULE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCxPQUFPLEVBQ1AsTUFBTSxFQUNOLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM5RCxPQUFPLEVBQ0wsS0FBSyxFQUNMLEVBQUUsRUFDRixTQUFTLEVBQ1QsS0FBSyxHQUNOLE1BQU0sTUFBTSxDQUFDO0FBQ2QsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3RELE9BQU8sRUFDTCxLQUFLLEVBQ0wsTUFBTSxFQUNOLE9BQU8sRUFDUCxHQUFHLEVBQ0gsUUFBUSxFQUNSLElBQUksRUFDSixjQUFjLEdBQ2YsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFckQsT0FBTyxLQUFLLHVCQUF1QixNQUFNLFdBQVcsQ0FBQztBQUNyRCxPQUFPLEVBQ0wsZUFBZSxFQUNmLFNBQVMsR0FDVixNQUFNLGFBQWEsQ0FBQztBQUNyQixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDOUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBUzlELE1BQU0sQ0FBQyxJQUFNLG1DQUFtQyxHQUFHLElBQUksY0FBYyxDQUFTLFdBQVcsQ0FBQyxDQUFDO0FBRTNGLElBQU0saUJBQWlCLEdBQUcsRUFBRSxDQUFDO0FBQzdCLElB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Q29udGVudCI6WyJpbXBvcnQge1xuICBJbmplY3QsXG4gIEluamVjdGFibGUsXG4gIEluamVjdGlvblRva2VuLFxuICBPcHRpb25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBBY3Rpb25zLFxuICBFZmZlY3QsXG4gIG9mVHlwZSxcbn0gZnJvbSAnQG5ncngvZWZmZWN0cyc7XG5pbXBvcnQgeyBTdG9yZSB9IGZyb20gJ0BuZ3J4L3N0b3JlJztcbmltcG9ydCB7IFRzQ29va2llU2VydmljZSB9IGZyb20gJ0B0ZXJtaW51cy9uZ3gtdG9vbHMvYnJvd3Nlcic7XG5pbXBvcnQge1xuICBtZXJnZSxcbiAgb2YsXG4gIFNjaGVkdWxlcixcbiAgdGltZXIsXG59IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgYXN5bmMgfSBmcm9tICdyeGpzL2ludGVybmFsL3NjaGVkdWxlci9hc3luYyc7XG5pbXBvcnQge1xuICBkZWxheSxcbiAgZmlsdGVyLFxuICBmbGF0TWFwLFxuICBtYXAsXG4gIG1lcmdlTWFwLFxuICB0YWtlLFxuICB3aXRoTGF0ZXN0RnJvbSxcbn0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBqd3REZWNvZGUgfSBmcm9tICcuLi9qd3QtZGVjb2RlL2p3dC1kZWNvZGUnO1xuXG5pbXBvcnQgKiBhcyBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucyBmcm9tICcuL2FjdGlvbnMnO1xuaW1wb3J0IHtcbiAgZ2V0Snd0VG9rZW5Sb290LFxuICBnZXRUb2tlbnMsXG59IGZyb20gJy4vc2VsZWN0b3JzJztcbmltcG9ydCB7IElOSVRJQUxfVE9LRU5fTkFNRSB9IGZyb20gJy4vdG9rZW5zJztcbmltcG9ydCB7IFNDSEVEVUxFUiB9IGZyb20gJy4vdXRpbGl0aWVzL3JldHJ5LXdpdGgtZXNjYWxhdGlvbic7XG5cblxuZXhwb3J0IGludGVyZmFjZSBDbGFpbXMgeyBleHA6IG51bWJlcjsgfVxuXG5leHBvcnQgaW50ZXJmYWNlIE1pbmltYWxDbGFpbU1hcCB7XG4gIFtpZDogc3RyaW5nXTogQ2xhaW1zO1xufVxuXG5leHBvcnQgY29uc3QgU0VDT05EU19CRUZPUkVfRVhQSVJBVElPTl9UT19OT1RJRlkgPSBuZXcgSW5qZWN0aW9uVG9rZW48bnVtYmVyPignd2FpdCB0aW1lJyk7XG5cbmNvbnN0IFNFQ09ORFNfSU5fTUlOVVRFID0gNjA7XG5jb25zdCBERUZBVUxUX01JTlVURVNfQkVGT1JFX0VYUElSQVRJT05fVE9fTk9USUZZID0gNTtcbmNvbnN0IERFRkFVTFRfU0VDT05EU19CRUZPUkVfRVhQSVJBVElPTl9UT19OT1RJRlkgPSBERUZBVUxUX01JTlVURVNfQkVGT1JFX0VYUElSQVRJT05fVE9fTk9USUZZICogU0VDT05EU19JTl9NSU5VVEU7XG5jb25zdCBDTEVBTlVQX0RFTEFZID0gMTAwO1xuY29uc3QgVE9LRU5TX0VYUElSRURfREVMQVkgPSAxMDtcbmNvbnN0IE1TX0lOX1NFQ09ORFMgPSAxMDAwO1xuXG50eXBlIFBhcnRpYWxDbGFpbVR1cGxlID0gW1xuICBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5TdG9yZVRva2VuPE1pbmltYWxDbGFpbU1hcD4sXG4gIFBhcnRpYWw8Q2xhaW1zPlxuXTtcblxudHlwZSBGdWxsQ2xhaW1zVHVwbGUgPSBbXG4gIEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLlN0b3JlVG9rZW48TWluaW1hbENsYWltTWFwPixcbiAgQ2xhaW1zXG5dO1xuXG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBKd3RUb2tlblByb3ZpZGVyRWZmZWN0cyB7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBhY3Rpb25zJDogQWN0aW9uczxKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5BY3Rpb25zPE1pbmltYWxDbGFpbU1hcD4+LFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgcHJpdmF0ZSBzdG9yZTogU3RvcmU8YW55PixcbiAgICBwcml2YXRlIGNvb2tpZVNlcnZpY2U6IFRzQ29va2llU2VydmljZSxcblxuICAgIEBJbmplY3QoSU5JVElBTF9UT0tFTl9OQU1FKVxuICAgIHByaXZhdGUgaW5pdGlhbFRva2VuTmFtZTogc3RyaW5nLFxuXG4gICAgQE9wdGlvbmFsKClcbiAgICBASW5qZWN0KFNDSEVEVUxFUilcbiAgICAvLyBUT0RPOiBTY2hlZHVsZXIgaXMgbWFya2VkIGFzIGRlcHJlY2F0ZWQgdG8gc3RvcCBvdGhlcnMgZnJvbSB1c2luZyBhbHRob3VnaCBpdCBpcyBub3QgdGVjaG5pY2FsbHkgZGVwcmVjYXRlZCBmcm9tXG4gICAgLy8gd2hhdCBJIGNhbiB0ZWxsLiBUaGUgJ2NvcnJlY3QnIHBhdGggd291bGQgYmUgdG8gY3JlYXRlIG91ciBvd24gY2xhc3MgZXh0ZW5kaW5nIGBTY2hlZHVsZXJMaWtlYC5cbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vR2V0VGVybWludXMvbmd4LXRvb2xzL2lzc3Vlcy8yODdcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb25cbiAgICBwcml2YXRlIHNjaGVkdWxlcjogU2NoZWR1bGVyLFxuXG4gICAgQE9wdGlvbmFsKClcbiAgICBASW5qZWN0KFNFQ09ORFNfQkVGT1JFX0VYUElSQVRJT05fVE9fTk9USUZZKVxuICAgIHByaXZhdGUgdGltZVRvV2FpdEJlZm9yZUV4cGlyYXRpb246IG51bWJlcixcbiAgKSB7fVxuXG5cbiAgQEVmZmVjdCgpXG4gIHB1YmxpYyBpbml0aWFsaXphdGlvbkNsZWFudXAkID0gb2YodHJ1ZSlcbiAgICAucGlwZShcbiAgICAgIGRlbGF5KENMRUFOVVBfREVMQVksIHRoaXMuc2NoZWR1bGVyIHx8IGFzeW5jKSxcbiAgICAgIHdpdGhMYXRlc3RGcm9tKFxuICAgICAgICB0aGlzLnN0b3JlLnNlbGVjdChnZXRUb2tlbnM8TWluaW1hbENsYWltTWFwPigpKSxcbiAgICAgICksXG4gICAgICBtYXAoKFtfLCB0b2tlbnNdKSA9PiB0b2tlbnMpLFxuICAgICAgdGFrZSgxKSxcbiAgICAgIGZsYXRNYXAodG9rZW5zID0+IHtcbiAgICAgICAgY29uc3QgYWN0aW9uczogSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuU3RvcmVUb2tlbjxNaW5pbWFsQ2xhaW1NYXA+W10gPSBbXTtcblxuICAgICAgICBmb3IgKGNvbnN0IHRva2VuTmFtZSBpbiB0b2tlbnMpIHtcbiAgICAgICAgICBpZiAodG9rZW5zLmhhc093blByb3BlcnR5KHRva2VuTmFtZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IHRva2VuID0gdG9rZW5zW3Rva2VuTmFtZV07XG4gICAgICAgICAgICBpZiAodG9rZW4pIHtcbiAgICAgICAgICAgICAgYWN0aW9ucy5wdXNoKFxuICAgICAgICAgICAgICAgIG5ldyBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5TdG9yZVRva2VuKHtcbiAgICAgICAgICAgICAgICAgIHRva2VuTmFtZSxcbiAgICAgICAgICAgICAgICAgIHRva2VuLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYWN0aW9ucztcbiAgICAgIH0pLFxuICAgIClcbiAgO1xuXG5cbiAgQEVmZmVjdCgpXG4gIHB1YmxpYyBhbGxUb2tlbnNFeHBpcmVkJCA9IHRoaXMuYWN0aW9ucyRcbiAgICAucGlwZShcbiAgICAgIG9mVHlwZTxuZXZlcj4oSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuQWN0aW9uVHlwZXMuVG9rZW5FeHBpcmVkKSxcbiAgICAgIGRlbGF5KFRPS0VOU19FWFBJUkVEX0RFTEFZLCB0aGlzLnNjaGVkdWxlciB8fCBhc3luYyksXG4gICAgICB3aXRoTGF0ZXN0RnJvbShcbiAgICAgICAgdGhpcy5zdG9yZS5zZWxlY3QoZ2V0VG9rZW5zPE1pbmltYWxDbGFpbU1hcD4oKSksXG4gICAgICApLFxuICAgICAgbWFwKChbXywgdG9rZW5zXSkgPT4gdG9rZW5zKSxcbiAgICAgIGZpbHRlcih0b2tlbnMgPT4gT2JqZWN0LmtleXModG9rZW5zKS5sZW5ndGggPT09IDApLFxuICAgICAgbWFwKHRva2VucyA9PiBuZXcgSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuQWxsVG9rZW5zRXhwaXJlZCgpKSxcbiAgICApXG4gIDtcblxuXG4gIEBFZmZlY3QoKVxuICBwdWJsaWMgbm90aWZ5T2ZUb2tlbkV4cGlyYXRpb24kID0gdGhpcy5hY3Rpb25zJFxuICAgIC5waXBlKFxuICAgICAgb2ZUeXBlPEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLlN0b3JlVG9rZW48TWluaW1hbENsYWltTWFwPj4oSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuQWN0aW9uVHlwZXMuU3RvcmVUb2tlbiksXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgbWFwKChhY3Rpb246IEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLlN0b3JlVG9rZW48TWluaW1hbENsYWltTWFwPik6IFBhcnRpYWxDbGFpbVR1cGxlID0+IFthY3Rpb24sIGp3dERlY29kZTxQYXJ0aWFsPENsYWltcz4+KGFjdGlvbi50b2tlbildKSxcbiAgICAgIGZpbHRlcigoYTogUGFydGlhbENsYWltVHVwbGUpOiBhIGlzIEZ1bGxDbGFpbXNUdXBsZSA9PiBhWzFdLmV4cCAhPT0gdW5kZWZpbmVkKSxcbiAgICAgIG1lcmdlTWFwKChbYWN0aW9uLCBjbGFpbXNdKSA9PiB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRFcG9jaCA9IE1hdGguY2VpbCgobmV3IERhdGUoKSkuZ2V0VGltZSgpIC8gTVNfSU5fU0VDT05EUyk7XG5cbiAgICAgICAgaWYgKGNsYWltcy5leHAgPiBjdXJyZW50RXBvY2gpIHtcbiAgICAgICAgICBjb25zdCBleHBpcmVzSW4gPSBjbGFpbXMuZXhwIC0gY3VycmVudEVwb2NoO1xuICAgICAgICAgIGNvbnN0IGV4cGlyYXRpb25CdWZmZXIgPSB0aGlzLnRpbWVUb1dhaXRCZWZvcmVFeHBpcmF0aW9uIHx8IERFRkFVTFRfU0VDT05EU19CRUZPUkVfRVhQSVJBVElPTl9UT19OT1RJRlk7XG4gICAgICAgICAgbGV0IGV4cGlyYXRpb25OZWFySW4gPSAwO1xuXG4gICAgICAgICAgaWYgKGV4cGlyZXNJbiA8IGV4cGlyYXRpb25CdWZmZXIpIHtcbiAgICAgICAgICAgIGV4cGlyYXRpb25OZWFySW4gPSAxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBleHBpcmF0aW9uTmVhckluID0gZXhwaXJlc0luIC0gZXhwaXJhdGlvbkJ1ZmZlcjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gbWVyZ2UoXG4gICAgICAgICAgICB0aGlzLmJ1aWxkRGVsYXllZEV4cGlyYXRpb25PYnNlcnZhYmxlKGV4cGlyYXRpb25OZWFySW4gKiBNU19JTl9TRUNPTkRTLCBhY3Rpb24sIGZhbHNlKSxcbiAgICAgICAgICAgIHRoaXMuYnVpbGREZWxheWVkRXhwaXJhdGlvbk9ic2VydmFibGUoZXhwaXJlc0luICogTVNfSU5fU0VDT05EUywgYWN0aW9uLCB0cnVlKSxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvZihuZXcgSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuVG9rZW5FeHBpcmVkPE1pbmltYWxDbGFpbU1hcD4oe1xuICAgICAgICAgIHRva2VuTmFtZTogYWN0aW9uLnRva2VuTmFtZSxcbiAgICAgICAgICB0b2tlbjogYWN0aW9uLnRva2VuLFxuICAgICAgICB9KSk7XG5cbiAgICAgIH0pLFxuICAgIClcbiAgO1xuXG5cbiAgQEVmZmVjdCgpXG4gIHB1YmxpYyBpbml0aWFsQ29va2llTG9hZGVyJCA9ICh7XG4gICAgY3VycmVudFN0YXRlID0gdGhpcy5zdG9yZS5zZWxlY3QoZ2V0Snd0VG9rZW5Sb290KCkpLFxuICB9ID0ge30pID0+IG9mKHRydWUpLnBpcGUoXG4gICAgdGFrZSgxKSxcbiAgICB3aXRoTGF0ZXN0RnJvbShjdXJyZW50U3RhdGUpLFxuICAgIGZpbHRlcigoW18sIHN0YXRlXSkgPT4gISEoc3RhdGUgJiYgc3RhdGUuand0VG9rZW5zLmluaXRpYWxUb2tlblN0YXR1cyA9PT0gJ3VuaW5pdGlhbGl6ZWQnKSksXG4gICAgbWVyZ2VNYXAoKFthLCBfXSkgPT4ge1xuICAgICAgY29uc3QgY29va2llID0gdGhpcy5jb29raWVTZXJ2aWNlLmdldCgnand0X2Nvb2tpZScpO1xuICAgICAgaWYgKGNvb2tpZS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgbmV3IEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLkluaXRpYWxUb2tlbkV4dHJhY3RlZChjb29raWUpLFxuICAgICAgICAgIG5ldyBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5TdG9yZVRva2VuKHtcbiAgICAgICAgICAgIHRva2VuTmFtZTogdGhpcy5pbml0aWFsVG9rZW5OYW1lLFxuICAgICAgICAgICAgdG9rZW46IGNvb2tpZSxcbiAgICAgICAgICAgIGlzRGVmYXVsdFRva2VuOiB0cnVlLFxuICAgICAgICAgIH0pLFxuICAgICAgICBdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFtcbiAgICAgICAgbmV3IEp3dFRva2VuUHJvdmlkZXJBY3Rpb25zLkluaXRpYWxUb2tlbkV4dHJhY3RlZChjb29raWUpLFxuICAgICAgXTtcblxuICAgIH0pLFxuICApO1xuXG5cbiAgLypcbiAgICogVGhpcyBuZXh0IGZ1bmN0aW9uIGlzIGJlaW5nIGV4Y2x1ZGVkIGZyb20gY292ZXJhZ2UgZHVlIHRoZSBjb21wbGV4aXRpZXMgb2YgdGVzdGluZyB0aGUgYGRlbGF5YCBmdW5jdGlvbi5cbiAgICogSW4gb3JkZXIgdG8gdGVzdCBhcyBtdWNoIGFzIHBvc3NpYmxlLCBlYWNoIHBpZWNlIGhhcyBiZWVuIHNlcGFyYXRlZCBpbnRvIHNtYWxsZXIgdGVzdGFibGUgZnVuY3Rpb25zLlxuICAgKi9cbiAgcHVibGljIGJ1aWxkRGVsYXllZEV4cGlyYXRpb25PYnNlcnZhYmxlKFxuICAgIGVtaXRUaW1lOiBudW1iZXIgfCBEYXRlLFxuICAgIGFjdGlvbjogSnd0VG9rZW5Qcm92aWRlckFjdGlvbnMuU3RvcmVUb2tlbjxNaW5pbWFsQ2xhaW1NYXA+LFxuICAgIGV4cGlyZWQ6IGJvb2xlYW4sXG4gICkge1xuICAgIGNvbnN0IG91dHB1dEFjdGlvbkFyZ3MgPSB7XG4gICAgICB0b2tlbk5hbWU6IGFjdGlvbi50b2tlbk5hbWUsXG4gICAgICB0b2tlbjogYWN0aW9uLnRva2VuLFxuICAgIH07XG5cbiAgICByZXR1cm4gdGltZXIoZW1pdFRpbWUsIHRoaXMuc2NoZWR1bGVyIHx8IGFzeW5jKS5waXBlKFxuICAgICAgdGFrZSgxKSxcbiAgICAgIG1hcCgoKSA9PiAoZXhwaXJlZFxuICAgICAgICA/IG5ldyBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5Ub2tlbkV4cGlyZWQ8TWluaW1hbENsYWltTWFwPihvdXRwdXRBY3Rpb25BcmdzKVxuICAgICAgICA6IG5ldyBKd3RUb2tlblByb3ZpZGVyQWN0aW9ucy5Ub2tlbk5lYXJpbmdFeHBpcmF0aW9uPE1pbmltYWxDbGFpbU1hcD4ob3V0cHV0QWN0aW9uQXJncykpKSxcbiAgICApO1xuICB9XG59XG4iXX0=