UNPKG

@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
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=