UNPKG

@angular/common

Version:

Angular - commonly needed directives and services

142 lines 18.5 kB
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import { APP_BOOTSTRAP_LISTENER, ApplicationRef, inject, InjectionToken, makeStateKey, TransferState, ɵENABLED_SSR_FEATURES as ENABLED_SSR_FEATURES, ɵInitialRenderPendingTasks as InitialRenderPendingTasks } from '@angular/core'; import { of } from 'rxjs'; import { first, tap } from 'rxjs/operators'; import { HttpHeaders } from './headers'; import { HTTP_ROOT_INTERCEPTOR_FNS } from './interceptor'; import { HttpResponse } from './response'; const CACHE_STATE = new InjectionToken(ngDevMode ? 'HTTP_TRANSFER_STATE_CACHE_STATE' : ''); /** * A list of allowed HTTP methods to cache. */ const ALLOWED_METHODS = ['GET', 'HEAD']; export function transferCacheInterceptorFn(req, next) { const { isCacheActive } = inject(CACHE_STATE); // Stop using the cache if the application has stabilized, indicating initial rendering // is complete. if (!isCacheActive || !ALLOWED_METHODS.includes(req.method)) { // Cache is no longer active or method is not HEAD or GET. // Pass the request through. return next(req); } const transferState = inject(TransferState); const storeKey = makeCacheKey(req); const response = transferState.get(storeKey, null); if (response) { // Request found in cache. Respond using it. let body = response.body; switch (response.responseType) { case 'arraybuffer': body = new TextEncoder().encode(response.body).buffer; break; case 'blob': body = new Blob([response.body]); break; } return of(new HttpResponse({ body, headers: new HttpHeaders(response.headers), status: response.status, statusText: response.statusText, url: response.url, })); } // Request not found in cache. Make the request and cache it. return next(req).pipe(tap((event) => { if (event instanceof HttpResponse) { transferState.set(storeKey, { body: event.body, headers: getHeadersMap(event.headers), status: event.status, statusText: event.statusText, url: event.url || '', responseType: req.responseType, }); } })); } function getHeadersMap(headers) { const headersMap = {}; for (const key of headers.keys()) { const values = headers.getAll(key); if (values !== null) { headersMap[key] = values; } } return headersMap; } function makeCacheKey(request) { // make the params encoded same as a url so it's easy to identify const { params, method, responseType, url } = request; const encodedParams = params.keys().sort().map((k) => `${k}=${params.getAll(k)}`).join('&'); const key = method + '.' + responseType + '.' + url + '?' + encodedParams; const hash = generateHash(key); return makeStateKey(hash); } /** * A method that returns a hash representation of a string using a variant of DJB2 hash * algorithm. * * This is the same hashing logic that is used to generate component ids. */ function generateHash(value) { let hash = 0; for (const char of value) { hash = Math.imul(31, hash) + char.charCodeAt(0) << 0; } // Force positive number hash. // 2147483647 = equivalent of Integer.MAX_VALUE. hash += 2147483647 + 1; return hash.toString(); } /** * Returns the DI providers needed to enable HTTP transfer cache. * * By default, when using server rendering, requests are performed twice: once on the server and * other one on the browser. * * When these providers are added, requests performed on the server are cached and reused during the * bootstrapping of the application in the browser thus avoiding duplicate requests and reducing * load time. * */ export function withHttpTransferCache() { return [ { provide: CACHE_STATE, useFactory: () => { inject(ENABLED_SSR_FEATURES).add('httpcache'); return { isCacheActive: true }; } }, { provide: HTTP_ROOT_INTERCEPTOR_FNS, useValue: transferCacheInterceptorFn, multi: true, deps: [TransferState, CACHE_STATE] }, { provide: APP_BOOTSTRAP_LISTENER, multi: true, useFactory: () => { const appRef = inject(ApplicationRef); const cacheState = inject(CACHE_STATE); const pendingTasks = inject(InitialRenderPendingTasks); return () => { const isStablePromise = appRef.isStable.pipe(first((isStable) => isStable)).toPromise(); isStablePromise.then(() => pendingTasks.whenAllTasksComplete).then(() => { cacheState.isCacheActive = false; }); }; }, deps: [ApplicationRef, CACHE_STATE, InitialRenderPendingTasks] } ]; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXJfY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9jb21tb24vaHR0cC9zcmMvdHJhbnNmZXJfY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLHNCQUFzQixFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLFlBQVksRUFBc0IsYUFBYSxFQUFFLHFCQUFxQixJQUFJLG9CQUFvQixFQUFFLDBCQUEwQixJQUFJLHlCQUF5QixFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3RQLE9BQU8sRUFBYSxFQUFFLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDcEMsT0FBTyxFQUFDLEtBQUssRUFBRSxHQUFHLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUUxQyxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ3RDLE9BQU8sRUFBQyx5QkFBeUIsRUFBZ0IsTUFBTSxlQUFlLENBQUM7QUFFdkUsT0FBTyxFQUFZLFlBQVksRUFBQyxNQUFNLFlBQVksQ0FBQztBQVduRCxNQUFNLFdBQVcsR0FBRyxJQUFJLGNBQWMsQ0FDbEMsU0FBUyxDQUFDLENBQUMsQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7QUFFeEQ7O0dBRUc7QUFDSCxNQUFNLGVBQWUsR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztBQUV4QyxNQUFNLFVBQVUsMEJBQTBCLENBQ3RDLEdBQXlCLEVBQUUsSUFBbUI7SUFDaEQsTUFBTSxFQUFDLGFBQWEsRUFBQyxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUU1Qyx1RkFBdUY7SUFDdkYsZUFBZTtJQUNmLElBQUksQ0FBQyxhQUFhLElBQUksQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRTtRQUMzRCwwREFBMEQ7UUFDMUQsNEJBQTRCO1FBQzVCLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0tBQ2xCO0lBRUQsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQzVDLE1BQU0sUUFBUSxHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQyxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUVuRCxJQUFJLFFBQVEsRUFBRTtRQUNaLDRDQUE0QztRQUM1QyxJQUFJLElBQUksR0FBc0MsUUFBUSxDQUFDLElBQUksQ0FBQztRQUU1RCxRQUFRLFFBQVEsQ0FBQyxZQUFZLEVBQUU7WUFDN0IsS0FBSyxhQUFhO2dCQUNoQixJQUFJLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFDdEQsTUFBTTtZQUNSLEtBQUssTUFBTTtnQkFDVCxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFDakMsTUFBTTtTQUNUO1FBRUQsT0FBTyxFQUFFLENBQ0wsSUFBSSxZQUFZLENBQUM7WUFDZixJQUFJO1lBQ0osT0FBTyxFQUFFLElBQUksV0FBVyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7WUFDMUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxNQUFNO1lBQ3ZCLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVTtZQUMvQixHQUFHLEVBQUUsUUFBUSxDQUFDLEdBQUc7U0FDbEIsQ0FBQyxDQUNMLENBQUM7S0FDSDtJQUVELDZEQUE2RDtJQUM3RCxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQ2pCLEdBQUcsQ0FBQyxDQUFDLEtBQXlCLEVBQUUsRUFBRTtRQUNoQyxJQUFJLEtBQUssWUFBWSxZQUFZLEVBQUU7WUFDakMsYUFBYSxDQUFDLEdBQUcsQ0FBdUIsUUFBUSxFQUFFO2dCQUNoRCxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7Z0JBQ2hCLE9BQU8sRUFBRSxhQUFhLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQztnQkFDckMsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO2dCQUNwQixVQUFVLEVBQUUsS0FBSyxDQUFDLFVBQVU7Z0JBQzVCLEdBQUcsRUFBRSxLQUFLLENBQUMsR0FBRyxJQUFJLEVBQUU7Z0JBQ3BCLFlBQVksRUFBRSxHQUFHLENBQUMsWUFBWTthQUMvQixDQUFDLENBQUM7U0FDSjtJQUNILENBQUMsQ0FBQyxDQUNMLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsT0FBb0I7SUFDekMsTUFBTSxVQUFVLEdBQTZCLEVBQUUsQ0FBQztJQUVoRCxLQUFLLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRTtRQUNoQyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ25DLElBQUksTUFBTSxLQUFLLElBQUksRUFBRTtZQUNuQixVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDO1NBQzFCO0tBQ0Y7SUFFRCxPQUFPLFVBQVUsQ0FBQztBQUNwQixDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsT0FBeUI7SUFDN0MsaUVBQWlFO0lBQ2pFLE1BQU0sRUFBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUMsR0FBRyxPQUFPLENBQUM7SUFDcEQsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzVGLE1BQU0sR0FBRyxHQUFHLE1BQU0sR0FBRyxHQUFHLEdBQUcsWUFBWSxHQUFHLEdBQUcsR0FBRyxHQUFHLEdBQUcsR0FBRyxHQUFHLGFBQWEsQ0FBQztJQUUxRSxNQUFNLElBQUksR0FBRyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFL0IsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBUyxZQUFZLENBQUMsS0FBYTtJQUNqQyxJQUFJLElBQUksR0FBRyxDQUFDLENBQUM7SUFFYixLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRTtRQUN4QixJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDdEQ7SUFFRCw4QkFBOEI7SUFDOUIsZ0RBQWdEO0lBQ2hELElBQUksSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0lBRXZCLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ3pCLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLHFCQUFxQjtJQUNuQyxPQUFPO1FBQ0w7WUFDRSxPQUFPLEVBQUUsV0FBVztZQUNwQixVQUFVLEVBQUUsR0FBRyxFQUFFO2dCQUNmLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDOUMsT0FBTyxFQUFDLGFBQWEsRUFBRSxJQUFJLEVBQUMsQ0FBQztZQUMvQixDQUFDO1NBQ0Y7UUFDRDtZQUNFLE9BQU8sRUFBRSx5QkFBeUI7WUFDbEMsUUFBUSxFQUFFLDBCQUEwQjtZQUNwQyxLQUFLLEVBQUUsSUFBSTtZQUNYLElBQUksRUFBRSxDQUFDLGFBQWEsRUFBRSxXQUFXLENBQUM7U0FDbkM7UUFDRDtZQUNFLE9BQU8sRUFBRSxzQkFBc0I7WUFDL0IsS0FBSyxFQUFFLElBQUk7WUFDWCxVQUFVLEVBQUUsR0FBRyxFQUFFO2dCQUNmLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDdEMsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUN2QyxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQztnQkFFdkQsT0FBTyxHQUFHLEVBQUU7b0JBQ1YsTUFBTSxlQUFlLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO29CQUN4RixlQUFlLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7d0JBQ3RFLFVBQVUsQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO29CQUNuQyxDQUFDLENBQUMsQ0FBQztnQkFDTCxDQUFDLENBQUM7WUFDSixDQUFDO1lBQ0QsSUFBSSxFQUFFLENBQUMsY0FBYyxFQUFFLFdBQVcsRUFBRSx5QkFBeUIsQ0FBQztTQUMvRDtLQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7QVBQX0JPT1RTVFJBUF9MSVNURU5FUiwgQXBwbGljYXRpb25SZWYsIGluamVjdCwgSW5qZWN0aW9uVG9rZW4sIG1ha2VTdGF0ZUtleSwgUHJvdmlkZXIsIFN0YXRlS2V5LCBUcmFuc2ZlclN0YXRlLCDJtUVOQUJMRURfU1NSX0ZFQVRVUkVTIGFzIEVOQUJMRURfU1NSX0ZFQVRVUkVTLCDJtUluaXRpYWxSZW5kZXJQZW5kaW5nVGFza3MgYXMgSW5pdGlhbFJlbmRlclBlbmRpbmdUYXNrc30gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge09ic2VydmFibGUsIG9mfSBmcm9tICdyeGpzJztcbmltcG9ydCB7Zmlyc3QsIHRhcH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQge0h0dHBIZWFkZXJzfSBmcm9tICcuL2hlYWRlcnMnO1xuaW1wb3J0IHtIVFRQX1JPT1RfSU5URVJDRVBUT1JfRk5TLCBIdHRwSGFuZGxlckZufSBmcm9tICcuL2ludGVyY2VwdG9yJztcbmltcG9ydCB7SHR0cFJlcXVlc3R9IGZyb20gJy4vcmVxdWVzdCc7XG5pbXBvcnQge0h0dHBFdmVudCwgSHR0cFJlc3BvbnNlfSBmcm9tICcuL3Jlc3BvbnNlJztcblxuaW50ZXJmYWNlIFRyYW5zZmVySHR0cFJlc3BvbnNlIHtcbiAgYm9keTogYW55O1xuICBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT47XG4gIHN0YXR1cz86IG51bWJlcjtcbiAgc3RhdHVzVGV4dD86IHN0cmluZztcbiAgdXJsPzogc3RyaW5nO1xuICByZXNwb25zZVR5cGU/OiBIdHRwUmVxdWVzdDx1bmtub3duPlsncmVzcG9uc2VUeXBlJ107XG59XG5cbmNvbnN0IENBQ0hFX1NUQVRFID0gbmV3IEluamVjdGlvblRva2VuPHtpc0NhY2hlQWN0aXZlOiBib29sZWFufT4oXG4gICAgbmdEZXZNb2RlID8gJ0hUVFBfVFJBTlNGRVJfU1RBVEVfQ0FDSEVfU1RBVEUnIDogJycpO1xuXG4vKipcbiAqIEEgbGlzdCBvZiBhbGxvd2VkIEhUVFAgbWV0aG9kcyB0byBjYWNoZS5cbiAqL1xuY29uc3QgQUxMT1dFRF9NRVRIT0RTID0gWydHRVQnLCAnSEVBRCddO1xuXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNmZXJDYWNoZUludGVyY2VwdG9yRm4oXG4gICAgcmVxOiBIdHRwUmVxdWVzdDx1bmtub3duPiwgbmV4dDogSHR0cEhhbmRsZXJGbik6IE9ic2VydmFibGU8SHR0cEV2ZW50PHVua25vd24+PiB7XG4gIGNvbnN0IHtpc0NhY2hlQWN0aXZlfSA9IGluamVjdChDQUNIRV9TVEFURSk7XG5cbiAgLy8gU3RvcCB1c2luZyB0aGUgY2FjaGUgaWYgdGhlIGFwcGxpY2F0aW9uIGhhcyBzdGFiaWxpemVkLCBpbmRpY2F0aW5nIGluaXRpYWwgcmVuZGVyaW5nXG4gIC8vIGlzIGNvbXBsZXRlLlxuICBpZiAoIWlzQ2FjaGVBY3RpdmUgfHwgIUFMTE9XRURfTUVUSE9EUy5pbmNsdWRlcyhyZXEubWV0aG9kKSkge1xuICAgIC8vIENhY2hlIGlzIG5vIGxvbmdlciBhY3RpdmUgb3IgbWV0aG9kIGlzIG5vdCBIRUFEIG9yIEdFVC5cbiAgICAvLyBQYXNzIHRoZSByZXF1ZXN0IHRocm91Z2guXG4gICAgcmV0dXJuIG5leHQocmVxKTtcbiAgfVxuXG4gIGNvbnN0IHRyYW5zZmVyU3RhdGUgPSBpbmplY3QoVHJhbnNmZXJTdGF0ZSk7XG4gIGNvbnN0IHN0b3JlS2V5ID0gbWFrZUNhY2hlS2V5KHJlcSk7XG4gIGNvbnN0IHJlc3BvbnNlID0gdHJhbnNmZXJTdGF0ZS5nZXQoc3RvcmVLZXksIG51bGwpO1xuXG4gIGlmIChyZXNwb25zZSkge1xuICAgIC8vIFJlcXVlc3QgZm91bmQgaW4gY2FjaGUuIFJlc3BvbmQgdXNpbmcgaXQuXG4gICAgbGV0IGJvZHk6IEFycmF5QnVmZmVyfEJsb2J8c3RyaW5nfHVuZGVmaW5lZCA9IHJlc3BvbnNlLmJvZHk7XG5cbiAgICBzd2l0Y2ggKHJlc3BvbnNlLnJlc3BvbnNlVHlwZSkge1xuICAgICAgY2FzZSAnYXJyYXlidWZmZXInOlxuICAgICAgICBib2R5ID0gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHJlc3BvbnNlLmJvZHkpLmJ1ZmZlcjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdibG9iJzpcbiAgICAgICAgYm9keSA9IG5ldyBCbG9iKFtyZXNwb25zZS5ib2R5XSk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHJldHVybiBvZihcbiAgICAgICAgbmV3IEh0dHBSZXNwb25zZSh7XG4gICAgICAgICAgYm9keSxcbiAgICAgICAgICBoZWFkZXJzOiBuZXcgSHR0cEhlYWRlcnMocmVzcG9uc2UuaGVhZGVycyksXG4gICAgICAgICAgc3RhdHVzOiByZXNwb25zZS5zdGF0dXMsXG4gICAgICAgICAgc3RhdHVzVGV4dDogcmVzcG9uc2Uuc3RhdHVzVGV4dCxcbiAgICAgICAgICB1cmw6IHJlc3BvbnNlLnVybCxcbiAgICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIC8vIFJlcXVlc3Qgbm90IGZvdW5kIGluIGNhY2hlLiBNYWtlIHRoZSByZXF1ZXN0IGFuZCBjYWNoZSBpdC5cbiAgcmV0dXJuIG5leHQocmVxKS5waXBlKFxuICAgICAgdGFwKChldmVudDogSHR0cEV2ZW50PHVua25vd24+KSA9PiB7XG4gICAgICAgIGlmIChldmVudCBpbnN0YW5jZW9mIEh0dHBSZXNwb25zZSkge1xuICAgICAgICAgIHRyYW5zZmVyU3RhdGUuc2V0PFRyYW5zZmVySHR0cFJlc3BvbnNlPihzdG9yZUtleSwge1xuICAgICAgICAgICAgYm9keTogZXZlbnQuYm9keSxcbiAgICAgICAgICAgIGhlYWRlcnM6IGdldEhlYWRlcnNNYXAoZXZlbnQuaGVhZGVycyksXG4gICAgICAgICAgICBzdGF0dXM6IGV2ZW50LnN0YXR1cyxcbiAgICAgICAgICAgIHN0YXR1c1RleHQ6IGV2ZW50LnN0YXR1c1RleHQsXG4gICAgICAgICAgICB1cmw6IGV2ZW50LnVybCB8fCAnJyxcbiAgICAgICAgICAgIHJlc3BvbnNlVHlwZTogcmVxLnJlc3BvbnNlVHlwZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSksXG4gICk7XG59XG5cbmZ1bmN0aW9uIGdldEhlYWRlcnNNYXAoaGVhZGVyczogSHR0cEhlYWRlcnMpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT4ge1xuICBjb25zdCBoZWFkZXJzTWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmdbXT4gPSB7fTtcblxuICBmb3IgKGNvbnN0IGtleSBvZiBoZWFkZXJzLmtleXMoKSkge1xuICAgIGNvbnN0IHZhbHVlcyA9IGhlYWRlcnMuZ2V0QWxsKGtleSk7XG4gICAgaWYgKHZhbHVlcyAhPT0gbnVsbCkge1xuICAgICAgaGVhZGVyc01hcFtrZXldID0gdmFsdWVzO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBoZWFkZXJzTWFwO1xufVxuXG5mdW5jdGlvbiBtYWtlQ2FjaGVLZXkocmVxdWVzdDogSHR0cFJlcXVlc3Q8YW55Pik6IFN0YXRlS2V5PFRyYW5zZmVySHR0cFJlc3BvbnNlPiB7XG4gIC8vIG1ha2UgdGhlIHBhcmFtcyBlbmNvZGVkIHNhbWUgYXMgYSB1cmwgc28gaXQncyBlYXN5IHRvIGlkZW50aWZ5XG4gIGNvbnN0IHtwYXJhbXMsIG1ldGhvZCwgcmVzcG9uc2VUeXBlLCB1cmx9ID0gcmVxdWVzdDtcbiAgY29uc3QgZW5jb2RlZFBhcmFtcyA9IHBhcmFtcy5rZXlzKCkuc29ydCgpLm1hcCgoaykgPT4gYCR7a309JHtwYXJhbXMuZ2V0QWxsKGspfWApLmpvaW4oJyYnKTtcbiAgY29uc3Qga2V5ID0gbWV0aG9kICsgJy4nICsgcmVzcG9uc2VUeXBlICsgJy4nICsgdXJsICsgJz8nICsgZW5jb2RlZFBhcmFtcztcblxuICBjb25zdCBoYXNoID0gZ2VuZXJhdGVIYXNoKGtleSk7XG5cbiAgcmV0dXJuIG1ha2VTdGF0ZUtleShoYXNoKTtcbn1cblxuLyoqXG4gKiBBIG1ldGhvZCB0aGF0IHJldHVybnMgYSBoYXNoIHJlcHJlc2VudGF0aW9uIG9mIGEgc3RyaW5nIHVzaW5nIGEgdmFyaWFudCBvZiBESkIyIGhhc2hcbiAqIGFsZ29yaXRobS5cbiAqXG4gKiBUaGlzIGlzIHRoZSBzYW1lIGhhc2hpbmcgbG9naWMgdGhhdCBpcyB1c2VkIHRvIGdlbmVyYXRlIGNvbXBvbmVudCBpZHMuXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlSGFzaCh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgbGV0IGhhc2ggPSAwO1xuXG4gIGZvciAoY29uc3QgY2hhciBvZiB2YWx1ZSkge1xuICAgIGhhc2ggPSBNYXRoLmltdWwoMzEsIGhhc2gpICsgY2hhci5jaGFyQ29kZUF0KDApIDw8IDA7XG4gIH1cblxuICAvLyBGb3JjZSBwb3NpdGl2ZSBudW1iZXIgaGFzaC5cbiAgLy8gMjE0NzQ4MzY0NyA9IGVxdWl2YWxlbnQgb2YgSW50ZWdlci5NQVhfVkFMVUUuXG4gIGhhc2ggKz0gMjE0NzQ4MzY0NyArIDE7XG5cbiAgcmV0dXJuIGhhc2gudG9TdHJpbmcoKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBESSBwcm92aWRlcnMgbmVlZGVkIHRvIGVuYWJsZSBIVFRQIHRyYW5zZmVyIGNhY2hlLlxuICpcbiAqIEJ5IGRlZmF1bHQsIHdoZW4gdXNpbmcgc2VydmVyIHJlbmRlcmluZywgcmVxdWVzdHMgYXJlIHBlcmZvcm1lZCB0d2ljZTogb25jZSBvbiB0aGUgc2VydmVyIGFuZFxuICogb3RoZXIgb25lIG9uIHRoZSBicm93c2VyLlxuICpcbiAqIFdoZW4gdGhlc2UgcHJvdmlkZXJzIGFyZSBhZGRlZCwgcmVxdWVzdHMgcGVyZm9ybWVkIG9uIHRoZSBzZXJ2ZXIgYXJlIGNhY2hlZCBhbmQgcmV1c2VkIGR1cmluZyB0aGVcbiAqIGJvb3RzdHJhcHBpbmcgb2YgdGhlIGFwcGxpY2F0aW9uIGluIHRoZSBicm93c2VyIHRodXMgYXZvaWRpbmcgZHVwbGljYXRlIHJlcXVlc3RzIGFuZCByZWR1Y2luZ1xuICogbG9hZCB0aW1lLlxuICpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdpdGhIdHRwVHJhbnNmZXJDYWNoZSgpOiBQcm92aWRlcltdIHtcbiAgcmV0dXJuIFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBDQUNIRV9TVEFURSxcbiAgICAgIHVzZUZhY3Rvcnk6ICgpID0+IHtcbiAgICAgICAgaW5qZWN0KEVOQUJMRURfU1NSX0ZFQVRVUkVTKS5hZGQoJ2h0dHBjYWNoZScpO1xuICAgICAgICByZXR1cm4ge2lzQ2FjaGVBY3RpdmU6IHRydWV9O1xuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAgcHJvdmlkZTogSFRUUF9ST09UX0lOVEVSQ0VQVE9SX0ZOUyxcbiAgICAgIHVzZVZhbHVlOiB0cmFuc2ZlckNhY2hlSW50ZXJjZXB0b3JGbixcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgZGVwczogW1RyYW5zZmVyU3RhdGUsIENBQ0hFX1NUQVRFXVxuICAgIH0sXG4gICAge1xuICAgICAgcHJvdmlkZTogQVBQX0JPT1RTVFJBUF9MSVNURU5FUixcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgdXNlRmFjdG9yeTogKCkgPT4ge1xuICAgICAgICBjb25zdCBhcHBSZWYgPSBpbmplY3QoQXBwbGljYXRpb25SZWYpO1xuICAgICAgICBjb25zdCBjYWNoZVN0YXRlID0gaW5qZWN0KENBQ0hFX1NUQVRFKTtcbiAgICAgICAgY29uc3QgcGVuZGluZ1Rhc2tzID0gaW5qZWN0KEluaXRpYWxSZW5kZXJQZW5kaW5nVGFza3MpO1xuXG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgaXNTdGFibGVQcm9taXNlID0gYXBwUmVmLmlzU3RhYmxlLnBpcGUoZmlyc3QoKGlzU3RhYmxlKSA9PiBpc1N0YWJsZSkpLnRvUHJvbWlzZSgpO1xuICAgICAgICAgIGlzU3RhYmxlUHJvbWlzZS50aGVuKCgpID0+IHBlbmRpbmdUYXNrcy53aGVuQWxsVGFza3NDb21wbGV0ZSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICBjYWNoZVN0YXRlLmlzQ2FjaGVBY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgICBkZXBzOiBbQXBwbGljYXRpb25SZWYsIENBQ0hFX1NUQVRFLCBJbml0aWFsUmVuZGVyUGVuZGluZ1Rhc2tzXVxuICAgIH1cbiAgXTtcbn1cbiJdfQ==