ng-http-caching 15.2.4 → 16.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/esm2022/lib/ng-http-caching-interceptor.service.mjs +72 -0
  2. package/esm2022/lib/ng-http-caching.module.mjs +43 -0
  3. package/esm2022/lib/ng-http-caching.service.mjs +330 -0
  4. package/{esm2020 → esm2022}/lib/storage/ng-http-caching-browser-storage.mjs +122 -122
  5. package/{esm2020 → esm2022}/lib/storage/ng-http-caching-local-storage.mjs +6 -6
  6. package/{esm2020 → esm2022}/lib/storage/ng-http-caching-memory-storage.mjs +26 -26
  7. package/{esm2020 → esm2022}/lib/storage/ng-http-caching-session-storage.mjs +6 -6
  8. package/{esm2020 → esm2022}/lib/storage/ng-http-caching-storage.interface.mjs +1 -1
  9. package/{esm2020 → esm2022}/ng-http-caching.mjs +4 -4
  10. package/{esm2020 → esm2022}/public-api.mjs +11 -11
  11. package/{fesm2020 → fesm2022}/ng-http-caching.mjs +578 -578
  12. package/{fesm2020 → fesm2022}/ng-http-caching.mjs.map +1 -1
  13. package/index.d.ts +5 -5
  14. package/lib/ng-http-caching-interceptor.service.d.ts +15 -15
  15. package/lib/ng-http-caching.module.d.ts +9 -9
  16. package/lib/ng-http-caching.service.d.ts +213 -213
  17. package/lib/storage/ng-http-caching-browser-storage.d.ts +18 -18
  18. package/lib/storage/ng-http-caching-local-storage.d.ts +4 -4
  19. package/lib/storage/ng-http-caching-memory-storage.d.ts +12 -12
  20. package/lib/storage/ng-http-caching-session-storage.d.ts +4 -4
  21. package/lib/storage/ng-http-caching-storage.interface.d.ts +31 -31
  22. package/package.json +7 -13
  23. package/public-api.d.ts +8 -8
  24. package/esm2020/lib/ng-http-caching-interceptor.service.mjs +0 -71
  25. package/esm2020/lib/ng-http-caching.module.mjs +0 -42
  26. package/esm2020/lib/ng-http-caching.service.mjs +0 -329
  27. package/fesm2015/ng-http-caching.mjs +0 -606
  28. package/fesm2015/ng-http-caching.mjs.map +0 -1
@@ -0,0 +1,72 @@
1
+ import { HttpResponse } from '@angular/common/http';
2
+ import { Injectable } from '@angular/core';
3
+ import { asapScheduler, scheduled } from 'rxjs';
4
+ import { tap, finalize, shareReplay } from 'rxjs/operators';
5
+ import { NgHttpCachingHeadersList } from './ng-http-caching.service';
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "./ng-http-caching.service";
8
+ /**
9
+ * Fix for https://github.com/ReactiveX/rxjs/issues/7241
10
+ */
11
+ function* _of(value) {
12
+ yield value;
13
+ }
14
+ class NgHttpCachingInterceptorService {
15
+ constructor(cacheService) {
16
+ this.cacheService = cacheService;
17
+ }
18
+ intercept(req, next) {
19
+ // run garbage collector
20
+ this.cacheService.runGc();
21
+ // Don't cache if it's not cacheable
22
+ if (!this.cacheService.isCacheable(req)) {
23
+ return this.sendRequest(req, next);
24
+ }
25
+ // Checked if there is pending response for this request
26
+ const cachedObservable = this.cacheService.getFromQueue(req);
27
+ if (cachedObservable) {
28
+ // console.log('cachedObservable',cachedObservable);
29
+ return cachedObservable;
30
+ }
31
+ // Checked if there is cached response for this request
32
+ const cachedResponse = this.cacheService.getFromCache(req);
33
+ if (cachedResponse) {
34
+ // console.log('cachedResponse');
35
+ return scheduled(_of(cachedResponse.clone()), asapScheduler);
36
+ }
37
+ // If the request of going through for first time
38
+ // then let the request proceed and cache the response
39
+ // console.log('sendRequest', req);
40
+ const shared = this.sendRequest(req, next).pipe(tap(event => {
41
+ if (event instanceof HttpResponse) {
42
+ this.cacheService.addToCache(req, event.clone());
43
+ }
44
+ }), finalize(() => {
45
+ // delete pending request
46
+ this.cacheService.deleteFromQueue(req);
47
+ }), shareReplay());
48
+ // add pending request to queue for cache parallell request
49
+ this.cacheService.addToQueue(req, shared);
50
+ return shared;
51
+ }
52
+ /**
53
+ * Send http request (next handler)
54
+ */
55
+ sendRequest(req, next) {
56
+ let cloned = req.clone();
57
+ // trim custom headers before send request
58
+ NgHttpCachingHeadersList.forEach(ngHttpCachingHeaders => {
59
+ if (cloned.headers.has(ngHttpCachingHeaders)) {
60
+ cloned = cloned.clone({ headers: cloned.headers.delete(ngHttpCachingHeaders) });
61
+ }
62
+ });
63
+ return next.handle(cloned);
64
+ }
65
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingInterceptorService, deps: [{ token: i1.NgHttpCachingService }], target: i0.ɵɵFactoryTarget.Injectable }); }
66
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingInterceptorService }); }
67
+ }
68
+ export { NgHttpCachingInterceptorService };
69
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingInterceptorService, decorators: [{
70
+ type: Injectable
71
+ }], ctorParameters: function () { return [{ type: i1.NgHttpCachingService }]; } });
72
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctaHR0cC1jYWNoaW5nLWludGVyY2VwdG9yLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1odHRwLWNhY2hpbmcvc3JjL2xpYi9uZy1odHRwLWNhY2hpbmctaW50ZXJjZXB0b3Iuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQXdELFlBQVksRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzFHLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGFBQWEsRUFBYyxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDNUQsT0FBTyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUQsT0FBTyxFQUF3Qix3QkFBd0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDOzs7QUFFM0Y7O0dBRUc7QUFDSCxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUksS0FBUTtJQUN2QixNQUFNLEtBQUssQ0FBQztBQUNkLENBQUM7QUFFRCxNQUNhLCtCQUErQjtJQUUxQyxZQUE2QixZQUFrQztRQUFsQyxpQkFBWSxHQUFaLFlBQVksQ0FBc0I7SUFBSSxDQUFDO0lBRXBFLFNBQVMsQ0FBQyxHQUFxQixFQUFFLElBQWlCO1FBQ2hELHdCQUF3QjtRQUN4QixJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRTFCLG9DQUFvQztRQUNwQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDdkMsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztTQUNwQztRQUVELHdEQUF3RDtRQUN4RCxNQUFNLGdCQUFnQixHQUEyQyxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNyRyxJQUFJLGdCQUFnQixFQUFFO1lBQ3BCLG9EQUFvRDtZQUNwRCxPQUFPLGdCQUFnQixDQUFDO1NBQ3pCO1FBRUQsdURBQXVEO1FBQ3ZELE1BQU0sY0FBYyxHQUFrQyxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMxRixJQUFJLGNBQWMsRUFBRTtZQUNsQixpQ0FBaUM7WUFDakMsT0FBTyxTQUFTLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1NBQzlEO1FBRUQsaURBQWlEO1FBQ2pELHNEQUFzRDtRQUN0RCxtQ0FBbUM7UUFDbkMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUM3QyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDVixJQUFJLEtBQUssWUFBWSxZQUFZLEVBQUU7Z0JBQ2pDLElBQUksQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQzthQUNsRDtRQUNILENBQUMsQ0FBQyxFQUNGLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDWix5QkFBeUI7WUFDekIsSUFBSSxDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLEVBQ0YsV0FBVyxFQUFFLENBQ2QsQ0FBQztRQUVGLDJEQUEyRDtRQUMzRCxJQUFJLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFFMUMsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVyxDQUFDLEdBQXFCLEVBQUUsSUFBaUI7UUFDbEQsSUFBSSxNQUFNLEdBQXFCLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUMzQywwQ0FBMEM7UUFDMUMsd0JBQXdCLENBQUMsT0FBTyxDQUFDLG9CQUFvQixDQUFDLEVBQUU7WUFDdEQsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFO2dCQUM1QyxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLENBQUMsQ0FBQzthQUNqRjtRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdCLENBQUM7OEdBN0RVLCtCQUErQjtrSEFBL0IsK0JBQStCOztTQUEvQiwrQkFBK0I7MkZBQS9CLCtCQUErQjtrQkFEM0MsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBFdmVudCwgSHR0cEhhbmRsZXIsIEh0dHBJbnRlcmNlcHRvciwgSHR0cFJlcXVlc3QsIEh0dHBSZXNwb25zZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBhc2FwU2NoZWR1bGVyLCBPYnNlcnZhYmxlLCBzY2hlZHVsZWQgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgdGFwLCBmaW5hbGl6ZSwgc2hhcmVSZXBsYXkgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7IE5nSHR0cENhY2hpbmdTZXJ2aWNlLCBOZ0h0dHBDYWNoaW5nSGVhZGVyc0xpc3QgfSBmcm9tICcuL25nLWh0dHAtY2FjaGluZy5zZXJ2aWNlJztcclxuXHJcbi8qKlxyXG4gKiBGaXggZm9yIGh0dHBzOi8vZ2l0aHViLmNvbS9SZWFjdGl2ZVgvcnhqcy9pc3N1ZXMvNzI0MVxyXG4gKi9cclxuZnVuY3Rpb24qIF9vZjxUPih2YWx1ZTogVCk6IEdlbmVyYXRvcjxUPiB7XHJcbiAgeWllbGQgdmFsdWU7XHJcbn1cclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIE5nSHR0cENhY2hpbmdJbnRlcmNlcHRvclNlcnZpY2UgaW1wbGVtZW50cyBIdHRwSW50ZXJjZXB0b3Ige1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGNhY2hlU2VydmljZTogTmdIdHRwQ2FjaGluZ1NlcnZpY2UpIHsgfVxyXG5cclxuICBpbnRlcmNlcHQocmVxOiBIdHRwUmVxdWVzdDxhbnk+LCBuZXh0OiBIdHRwSGFuZGxlcik6IE9ic2VydmFibGU8SHR0cEV2ZW50PGFueT4+IHtcclxuICAgIC8vIHJ1biBnYXJiYWdlIGNvbGxlY3RvclxyXG4gICAgdGhpcy5jYWNoZVNlcnZpY2UucnVuR2MoKTtcclxuXHJcbiAgICAvLyBEb24ndCBjYWNoZSBpZiBpdCdzIG5vdCBjYWNoZWFibGVcclxuICAgIGlmICghdGhpcy5jYWNoZVNlcnZpY2UuaXNDYWNoZWFibGUocmVxKSkge1xyXG4gICAgICByZXR1cm4gdGhpcy5zZW5kUmVxdWVzdChyZXEsIG5leHQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENoZWNrZWQgaWYgdGhlcmUgaXMgcGVuZGluZyByZXNwb25zZSBmb3IgdGhpcyByZXF1ZXN0XHJcbiAgICBjb25zdCBjYWNoZWRPYnNlcnZhYmxlOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxhbnk+PiB8IHVuZGVmaW5lZCA9IHRoaXMuY2FjaGVTZXJ2aWNlLmdldEZyb21RdWV1ZShyZXEpO1xyXG4gICAgaWYgKGNhY2hlZE9ic2VydmFibGUpIHtcclxuICAgICAgLy8gY29uc29sZS5sb2coJ2NhY2hlZE9ic2VydmFibGUnLGNhY2hlZE9ic2VydmFibGUpO1xyXG4gICAgICByZXR1cm4gY2FjaGVkT2JzZXJ2YWJsZTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBDaGVja2VkIGlmIHRoZXJlIGlzIGNhY2hlZCByZXNwb25zZSBmb3IgdGhpcyByZXF1ZXN0XHJcbiAgICBjb25zdCBjYWNoZWRSZXNwb25zZTogSHR0cFJlc3BvbnNlPGFueT4gfCB1bmRlZmluZWQgPSB0aGlzLmNhY2hlU2VydmljZS5nZXRGcm9tQ2FjaGUocmVxKTtcclxuICAgIGlmIChjYWNoZWRSZXNwb25zZSkge1xyXG4gICAgICAvLyBjb25zb2xlLmxvZygnY2FjaGVkUmVzcG9uc2UnKTtcclxuICAgICAgcmV0dXJuIHNjaGVkdWxlZChfb2YoY2FjaGVkUmVzcG9uc2UuY2xvbmUoKSksIGFzYXBTY2hlZHVsZXIpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIElmIHRoZSByZXF1ZXN0IG9mIGdvaW5nIHRocm91Z2ggZm9yIGZpcnN0IHRpbWVcclxuICAgIC8vIHRoZW4gbGV0IHRoZSByZXF1ZXN0IHByb2NlZWQgYW5kIGNhY2hlIHRoZSByZXNwb25zZVxyXG4gICAgLy8gY29uc29sZS5sb2coJ3NlbmRSZXF1ZXN0JywgcmVxKTtcclxuICAgIGNvbnN0IHNoYXJlZCA9IHRoaXMuc2VuZFJlcXVlc3QocmVxLCBuZXh0KS5waXBlKFxyXG4gICAgICB0YXAoZXZlbnQgPT4ge1xyXG4gICAgICAgIGlmIChldmVudCBpbnN0YW5jZW9mIEh0dHBSZXNwb25zZSkge1xyXG4gICAgICAgICAgdGhpcy5jYWNoZVNlcnZpY2UuYWRkVG9DYWNoZShyZXEsIGV2ZW50LmNsb25lKCkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSksXHJcbiAgICAgIGZpbmFsaXplKCgpID0+IHtcclxuICAgICAgICAvLyBkZWxldGUgcGVuZGluZyByZXF1ZXN0XHJcbiAgICAgICAgdGhpcy5jYWNoZVNlcnZpY2UuZGVsZXRlRnJvbVF1ZXVlKHJlcSk7XHJcbiAgICAgIH0pLFxyXG4gICAgICBzaGFyZVJlcGxheSgpXHJcbiAgICApO1xyXG5cclxuICAgIC8vIGFkZCBwZW5kaW5nIHJlcXVlc3QgdG8gcXVldWUgZm9yIGNhY2hlIHBhcmFsbGVsbCByZXF1ZXN0XHJcbiAgICB0aGlzLmNhY2hlU2VydmljZS5hZGRUb1F1ZXVlKHJlcSwgc2hhcmVkKTtcclxuXHJcbiAgICByZXR1cm4gc2hhcmVkO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2VuZCBodHRwIHJlcXVlc3QgKG5leHQgaGFuZGxlcilcclxuICAgKi9cclxuICBzZW5kUmVxdWVzdChyZXE6IEh0dHBSZXF1ZXN0PGFueT4sIG5leHQ6IEh0dHBIYW5kbGVyKTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8YW55Pj4ge1xyXG4gICAgbGV0IGNsb25lZDogSHR0cFJlcXVlc3Q8YW55PiA9IHJlcS5jbG9uZSgpO1xyXG4gICAgLy8gdHJpbSBjdXN0b20gaGVhZGVycyBiZWZvcmUgc2VuZCByZXF1ZXN0XHJcbiAgICBOZ0h0dHBDYWNoaW5nSGVhZGVyc0xpc3QuZm9yRWFjaChuZ0h0dHBDYWNoaW5nSGVhZGVycyA9PiB7XHJcbiAgICAgIGlmIChjbG9uZWQuaGVhZGVycy5oYXMobmdIdHRwQ2FjaGluZ0hlYWRlcnMpKSB7XHJcbiAgICAgICAgY2xvbmVkID0gY2xvbmVkLmNsb25lKHsgaGVhZGVyczogY2xvbmVkLmhlYWRlcnMuZGVsZXRlKG5nSHR0cENhY2hpbmdIZWFkZXJzKSB9KTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gbmV4dC5oYW5kbGUoY2xvbmVkKTtcclxuICB9XHJcbn1cclxuIl19
@@ -0,0 +1,43 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { HTTP_INTERCEPTORS } from '@angular/common/http';
3
+ import { NG_HTTP_CACHING_CONFIG, NgHttpCachingService, } from './ng-http-caching.service';
4
+ import { NgHttpCachingInterceptorService } from './ng-http-caching-interceptor.service';
5
+ import * as i0 from "@angular/core";
6
+ class NgHttpCachingModule {
7
+ static forRoot(ngHttpCachingConfig) {
8
+ return {
9
+ ngModule: NgHttpCachingModule,
10
+ providers: [
11
+ {
12
+ provide: NG_HTTP_CACHING_CONFIG,
13
+ useValue: ngHttpCachingConfig,
14
+ },
15
+ ],
16
+ };
17
+ }
18
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
19
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingModule }); }
20
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingModule, providers: [
21
+ NgHttpCachingService,
22
+ {
23
+ provide: HTTP_INTERCEPTORS,
24
+ useClass: NgHttpCachingInterceptorService,
25
+ multi: true,
26
+ },
27
+ ] }); }
28
+ }
29
+ export { NgHttpCachingModule };
30
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingModule, decorators: [{
31
+ type: NgModule,
32
+ args: [{
33
+ providers: [
34
+ NgHttpCachingService,
35
+ {
36
+ provide: HTTP_INTERCEPTORS,
37
+ useClass: NgHttpCachingInterceptorService,
38
+ multi: true,
39
+ },
40
+ ]
41
+ }]
42
+ }] });
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctaHR0cC1jYWNoaW5nLm1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWh0dHAtY2FjaGluZy9zcmMvbGliL25nLWh0dHAtY2FjaGluZy5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBdUIsTUFBTSxlQUFlLENBQUM7QUFDOUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUNMLHNCQUFzQixFQUV0QixvQkFBb0IsR0FDckIsTUFBTSwyQkFBMkIsQ0FBQztBQUNuQyxPQUFPLEVBQUUsK0JBQStCLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQzs7QUFFeEYsTUFVYSxtQkFBbUI7SUFDOUIsTUFBTSxDQUFDLE9BQU8sQ0FDWixtQkFBeUM7UUFFekMsT0FBTztZQUNMLFFBQVEsRUFBRSxtQkFBbUI7WUFDN0IsU0FBUyxFQUFFO2dCQUNUO29CQUNFLE9BQU8sRUFBRSxzQkFBc0I7b0JBQy9CLFFBQVEsRUFBRSxtQkFBbUI7aUJBQzlCO2FBQ0Y7U0FDRixDQUFDO0lBQ0osQ0FBQzs4R0FiVSxtQkFBbUI7K0dBQW5CLG1CQUFtQjsrR0FBbkIsbUJBQW1CLGFBVG5CO1lBQ1Qsb0JBQW9CO1lBQ3BCO2dCQUNFLE9BQU8sRUFBRSxpQkFBaUI7Z0JBQzFCLFFBQVEsRUFBRSwrQkFBK0I7Z0JBQ3pDLEtBQUssRUFBRSxJQUFJO2FBQ1o7U0FDRjs7U0FFVSxtQkFBbUI7MkZBQW5CLG1CQUFtQjtrQkFWL0IsUUFBUTttQkFBQztvQkFDUixTQUFTLEVBQUU7d0JBQ1Qsb0JBQW9CO3dCQUNwQjs0QkFDRSxPQUFPLEVBQUUsaUJBQWlCOzRCQUMxQixRQUFRLEVBQUUsK0JBQStCOzRCQUN6QyxLQUFLLEVBQUUsSUFBSTt5QkFDWjtxQkFDRjtpQkFDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE5nTW9kdWxlLCBNb2R1bGVXaXRoUHJvdmlkZXJzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEhUVFBfSU5URVJDRVBUT1JTIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xyXG5pbXBvcnQge1xyXG4gIE5HX0hUVFBfQ0FDSElOR19DT05GSUcsXHJcbiAgTmdIdHRwQ2FjaGluZ0NvbmZpZyxcclxuICBOZ0h0dHBDYWNoaW5nU2VydmljZSxcclxufSBmcm9tICcuL25nLWh0dHAtY2FjaGluZy5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTmdIdHRwQ2FjaGluZ0ludGVyY2VwdG9yU2VydmljZSB9IGZyb20gJy4vbmctaHR0cC1jYWNoaW5nLWludGVyY2VwdG9yLnNlcnZpY2UnO1xyXG5cclxuQE5nTW9kdWxlKHtcclxuICBwcm92aWRlcnM6IFtcclxuICAgIE5nSHR0cENhY2hpbmdTZXJ2aWNlLFxyXG4gICAge1xyXG4gICAgICBwcm92aWRlOiBIVFRQX0lOVEVSQ0VQVE9SUyxcclxuICAgICAgdXNlQ2xhc3M6IE5nSHR0cENhY2hpbmdJbnRlcmNlcHRvclNlcnZpY2UsXHJcbiAgICAgIG11bHRpOiB0cnVlLFxyXG4gICAgfSxcclxuICBdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBOZ0h0dHBDYWNoaW5nTW9kdWxlIHtcclxuICBzdGF0aWMgZm9yUm9vdChcclxuICAgIG5nSHR0cENhY2hpbmdDb25maWc/OiBOZ0h0dHBDYWNoaW5nQ29uZmlnXHJcbiAgKTogTW9kdWxlV2l0aFByb3ZpZGVyczxOZ0h0dHBDYWNoaW5nTW9kdWxlPiB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBuZ01vZHVsZTogTmdIdHRwQ2FjaGluZ01vZHVsZSxcclxuICAgICAgcHJvdmlkZXJzOiBbXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgcHJvdmlkZTogTkdfSFRUUF9DQUNISU5HX0NPTkZJRyxcclxuICAgICAgICAgIHVzZVZhbHVlOiBuZ0h0dHBDYWNoaW5nQ29uZmlnLFxyXG4gICAgICAgIH0sXHJcbiAgICAgIF0sXHJcbiAgICB9O1xyXG4gIH1cclxufVxyXG4iXX0=
@@ -0,0 +1,330 @@
1
+ import { Injectable, InjectionToken, Inject, Optional, VERSION, isDevMode } from '@angular/core';
2
+ import { NgHttpCachingMemoryStorage } from './storage/ng-http-caching-memory-storage';
3
+ import * as i0 from "@angular/core";
4
+ export const NG_HTTP_CACHING_CONFIG = new InjectionToken('ng-http-caching.config');
5
+ export var NgHttpCachingStrategy;
6
+ (function (NgHttpCachingStrategy) {
7
+ /**
8
+ * All request are cacheable if HTTP method is into `allowedMethod`
9
+ */
10
+ NgHttpCachingStrategy["ALLOW_ALL"] = "ALLOW_ALL";
11
+ /**
12
+ * Only the request with `X-NG-HTTP-CACHING-ALLOW-CACHE` header are cacheable if HTTP method is into `allowedMethod`
13
+ */
14
+ NgHttpCachingStrategy["DISALLOW_ALL"] = "DISALLOW_ALL";
15
+ })(NgHttpCachingStrategy || (NgHttpCachingStrategy = {}));
16
+ export var NgHttpCachingHeaders;
17
+ (function (NgHttpCachingHeaders) {
18
+ /**
19
+ * Request is cacheable if HTTP method is into `allowedMethod`
20
+ */
21
+ NgHttpCachingHeaders["ALLOW_CACHE"] = "X-NG-HTTP-CACHING-ALLOW-CACHE";
22
+ /**
23
+ * Request isn't cacheable
24
+ */
25
+ NgHttpCachingHeaders["DISALLOW_CACHE"] = "X-NG-HTTP-CACHING-DISALLOW-CACHE";
26
+ /**
27
+ * Specific cache lifetime for the request
28
+ */
29
+ NgHttpCachingHeaders["LIFETIME"] = "X-NG-HTTP-CACHING-LIFETIME";
30
+ /**
31
+ * You can tag multiple request by adding this header with the same tag and
32
+ * using `NgHttpCachingService.clearCacheByTag(tag: string)` for delete all the tagged request
33
+ */
34
+ NgHttpCachingHeaders["TAG"] = "X-NG-HTTP-CACHING-TAG";
35
+ })(NgHttpCachingHeaders || (NgHttpCachingHeaders = {}));
36
+ export const NgHttpCachingHeadersList = Object.values(NgHttpCachingHeaders);
37
+ export const NG_HTTP_CACHING_SECOND_IN_MS = 1000;
38
+ export const NG_HTTP_CACHING_MINUTE_IN_MS = NG_HTTP_CACHING_SECOND_IN_MS * 60;
39
+ export const NG_HTTP_CACHING_HOUR_IN_MS = NG_HTTP_CACHING_MINUTE_IN_MS * 60;
40
+ export const NG_HTTP_CACHING_DAY_IN_MS = NG_HTTP_CACHING_HOUR_IN_MS * 24;
41
+ export const NG_HTTP_CACHING_WEEK_IN_MS = NG_HTTP_CACHING_DAY_IN_MS * 7;
42
+ export const NG_HTTP_CACHING_MONTH_IN_MS = NG_HTTP_CACHING_DAY_IN_MS * 30;
43
+ export const NG_HTTP_CACHING_YEAR_IN_MS = NG_HTTP_CACHING_DAY_IN_MS * 365;
44
+ export const NgHttpCachingConfigDefault = {
45
+ store: new NgHttpCachingMemoryStorage(),
46
+ lifetime: NG_HTTP_CACHING_HOUR_IN_MS,
47
+ version: VERSION.major,
48
+ allowedMethod: ['GET', 'HEAD'],
49
+ cacheStrategy: NgHttpCachingStrategy.ALLOW_ALL,
50
+ };
51
+ class NgHttpCachingService {
52
+ constructor(config) {
53
+ this.queue = new Map();
54
+ this.gcLock = false;
55
+ this.devMode = isDevMode();
56
+ if (config) {
57
+ this.config = { ...NgHttpCachingConfigDefault, ...config };
58
+ }
59
+ else {
60
+ this.config = { ...NgHttpCachingConfigDefault };
61
+ }
62
+ // start cache clean
63
+ this.runGc();
64
+ }
65
+ /**
66
+ * Return the config
67
+ */
68
+ getConfig() {
69
+ return this.config;
70
+ }
71
+ /**
72
+ * Return the queue map
73
+ */
74
+ getQueue() {
75
+ return this.queue;
76
+ }
77
+ /**
78
+ * Return the cache store
79
+ */
80
+ getStore() {
81
+ return this.config.store;
82
+ }
83
+ /**
84
+ * Return response from cache
85
+ */
86
+ getFromCache(req) {
87
+ const key = this.getKey(req);
88
+ const cached = this.config.store.get(key);
89
+ if (!cached) {
90
+ return undefined;
91
+ }
92
+ if (this.isExpired(cached)) {
93
+ this.clearCacheByKey(key);
94
+ return undefined;
95
+ }
96
+ return this.deepFreeze(cached.response);
97
+ }
98
+ /**
99
+ * Add response to cache
100
+ */
101
+ addToCache(req, res) {
102
+ const entry = {
103
+ url: req.urlWithParams,
104
+ response: res,
105
+ request: req,
106
+ addedTime: Date.now(),
107
+ version: this.config.version,
108
+ };
109
+ if (this.isValid(entry)) {
110
+ const key = this.getKey(req);
111
+ this.config.store.set(key, entry);
112
+ return true;
113
+ }
114
+ return false;
115
+ }
116
+ /**
117
+ * Delete response from cache
118
+ */
119
+ deleteFromCache(req) {
120
+ const key = this.getKey(req);
121
+ return this.clearCacheByKey(key);
122
+ }
123
+ /**
124
+ * Clear the cache
125
+ */
126
+ clearCache() {
127
+ this.config.store.clear();
128
+ }
129
+ /**
130
+ * Clear the cache by key
131
+ */
132
+ clearCacheByKey(key) {
133
+ return this.config.store.delete(key);
134
+ }
135
+ /**
136
+ * Clear the cache by regex
137
+ */
138
+ clearCacheByRegex(regex) {
139
+ this.config.store.forEach((_, key) => {
140
+ if (regex.test(key)) {
141
+ this.clearCacheByKey(key);
142
+ }
143
+ });
144
+ }
145
+ /**
146
+ * Clear the cache by TAG
147
+ */
148
+ clearCacheByTag(tag) {
149
+ this.config.store.forEach((entry, key) => {
150
+ const tagHeader = entry.request.headers.get(NgHttpCachingHeaders.TAG);
151
+ if (tagHeader && tagHeader.split(',').includes(tag)) {
152
+ this.clearCacheByKey(key);
153
+ }
154
+ });
155
+ }
156
+ /**
157
+ * Run garbage collector (delete expired cache entry)
158
+ */
159
+ runGc() {
160
+ if (this.gcLock) {
161
+ return false;
162
+ }
163
+ this.gcLock = true;
164
+ this.config.store.forEach((entry, key) => {
165
+ if (this.isExpired(entry)) {
166
+ this.clearCacheByKey(key);
167
+ }
168
+ });
169
+ this.gcLock = false;
170
+ return true;
171
+ }
172
+ /**
173
+ * Return true if cache entry is expired
174
+ */
175
+ isExpired(entry) {
176
+ // if user provide custom method, use it
177
+ if (typeof this.config.isExpired === 'function') {
178
+ const result = this.config.isExpired(entry);
179
+ // if result is undefined, normal behaviour is provided
180
+ if (result !== undefined) {
181
+ return result;
182
+ }
183
+ }
184
+ // config/default lifetime
185
+ let lifetime = this.config.lifetime;
186
+ // request has own lifetime
187
+ const headerLifetime = entry.request.headers.get(NgHttpCachingHeaders.LIFETIME);
188
+ if (headerLifetime) {
189
+ lifetime = +headerLifetime;
190
+ }
191
+ // never expire if 0
192
+ if (lifetime === 0) {
193
+ return false;
194
+ }
195
+ // wrong lifetime
196
+ if (lifetime < 0 || isNaN(lifetime)) {
197
+ throw new Error('lifetime must be greater than or equal 0');
198
+ }
199
+ return entry.addedTime + lifetime < Date.now();
200
+ }
201
+ /**
202
+ * Return true if cache entry is valid for store in the cache
203
+ */
204
+ isValid(entry) {
205
+ // if user provide custom method, use it
206
+ if (typeof this.config.isValid === 'function') {
207
+ const result = this.config.isValid(entry);
208
+ // if result is undefined, normal behaviour is provided
209
+ if (result !== undefined) {
210
+ return result;
211
+ }
212
+ }
213
+ // different version
214
+ if (this.config.version !== entry.version) {
215
+ return false;
216
+ }
217
+ return true;
218
+ }
219
+ /**
220
+ * Return true if the request is cacheable
221
+ */
222
+ isCacheable(req) {
223
+ // if user provide custom method, use it
224
+ if (typeof this.config.isCacheable === 'function') {
225
+ const result = this.config.isCacheable(req);
226
+ // if result is undefined, normal behaviour is provided
227
+ if (result !== undefined) {
228
+ return result;
229
+ }
230
+ }
231
+ // request has disallow cache header
232
+ if (req.headers.has(NgHttpCachingHeaders.DISALLOW_CACHE)) {
233
+ return false;
234
+ }
235
+ // strategy is disallow all...
236
+ if (this.config.cacheStrategy === NgHttpCachingStrategy.DISALLOW_ALL) {
237
+ // request isn't allowed if come without allow header
238
+ if (!req.headers.has(NgHttpCachingHeaders.ALLOW_CACHE)) {
239
+ return false;
240
+ }
241
+ }
242
+ // if allowed method is only ALL, allow all http methos
243
+ if (this.config.allowedMethod.length === 1) {
244
+ if (this.config.allowedMethod[0] === 'ALL') {
245
+ return true;
246
+ }
247
+ }
248
+ // request is allowed if method is in allowedMethod
249
+ return this.config.allowedMethod.indexOf(req.method) !== -1;
250
+ }
251
+ /**
252
+ * Return the cache key.
253
+ * Default key is http method plus url with query parameters, eg.:
254
+ * `GET@https://github.com/nigrosimone/ng-http-caching`
255
+ */
256
+ getKey(req) {
257
+ // if user provide custom method, use it
258
+ if (typeof this.config.getKey === 'function') {
259
+ const result = this.config.getKey(req);
260
+ // if result is undefined, normal behaviour is provided
261
+ if (result !== undefined) {
262
+ return result;
263
+ }
264
+ }
265
+ // default key is req.method plus url with query parameters
266
+ return req.method + '@' + req.urlWithParams;
267
+ }
268
+ /**
269
+ * Return observable from cache
270
+ */
271
+ getFromQueue(req) {
272
+ const key = this.getKey(req);
273
+ const cached = this.queue.get(key);
274
+ if (!cached) {
275
+ return undefined;
276
+ }
277
+ return cached;
278
+ }
279
+ /**
280
+ * Add observable to cache
281
+ */
282
+ addToQueue(req, obs) {
283
+ const key = this.getKey(req);
284
+ this.queue.set(key, obs);
285
+ }
286
+ /**
287
+ * Delete observable from cache
288
+ */
289
+ deleteFromQueue(req) {
290
+ const key = this.getKey(req);
291
+ return this.queue.delete(key);
292
+ }
293
+ /**
294
+ * Recursively Object.freeze simple Javascript structures consisting of plain objects, arrays, and primitives.
295
+ * Make the data immutable.
296
+ * @returns immutable object
297
+ */
298
+ deepFreeze(object) {
299
+ // No freezing in production (for better performance).
300
+ if (!this.devMode || !object || typeof object !== 'object') {
301
+ return object;
302
+ }
303
+ // When already frozen, we assume its children are frozen (for better performance).
304
+ // This should be true if you always use `deepFreeze` to freeze objects.
305
+ //
306
+ // Note that Object.isFrozen will also return `true` for primitives (numbers,
307
+ // strings, booleans, undefined, null), so there is no need to check for
308
+ // those explicitly.
309
+ if (Object.isFrozen(object)) {
310
+ return object;
311
+ }
312
+ // At this point we know that we're dealing with either an array or plain object, so
313
+ // just freeze it and recurse on its values.
314
+ Object.freeze(object);
315
+ Object.keys(object).forEach(key => this.deepFreeze(object[key]));
316
+ return object;
317
+ }
318
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingService, deps: [{ token: NG_HTTP_CACHING_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
319
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingService }); }
320
+ }
321
+ export { NgHttpCachingService };
322
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: NgHttpCachingService, decorators: [{
323
+ type: Injectable
324
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
325
+ type: Inject,
326
+ args: [NG_HTTP_CACHING_CONFIG]
327
+ }, {
328
+ type: Optional
329
+ }] }]; } });
330
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctaHR0cC1jYWNoaW5nLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1odHRwLWNhY2hpbmcvc3JjL2xpYi9uZy1odHRwLWNhY2hpbmcuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFJakcsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sMENBQTBDLENBQUM7O0FBeUJ0RixNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLGNBQWMsQ0FDdEQsd0JBQXdCLENBQ3pCLENBQUM7QUFFRixNQUFNLENBQU4sSUFBWSxxQkFTWDtBQVRELFdBQVkscUJBQXFCO0lBQy9COztPQUVHO0lBQ0gsZ0RBQXVCLENBQUE7SUFDdkI7O09BRUc7SUFDSCxzREFBNkIsQ0FBQTtBQUMvQixDQUFDLEVBVFcscUJBQXFCLEtBQXJCLHFCQUFxQixRQVNoQztBQUVELE1BQU0sQ0FBTixJQUFZLG9CQWtCWDtBQWxCRCxXQUFZLG9CQUFvQjtJQUM5Qjs7T0FFRztJQUNILHFFQUE2QyxDQUFBO0lBQzdDOztPQUVHO0lBQ0gsMkVBQW1ELENBQUE7SUFDbkQ7O09BRUc7SUFDSCwrREFBdUMsQ0FBQTtJQUN2Qzs7O09BR0c7SUFDSCxxREFBNkIsQ0FBQTtBQUMvQixDQUFDLEVBbEJXLG9CQUFvQixLQUFwQixvQkFBb0IsUUFrQi9CO0FBRUQsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0FBRTVFLE1BQU0sQ0FBQyxNQUFNLDRCQUE0QixHQUFHLElBQUksQ0FBQztBQUNqRCxNQUFNLENBQUMsTUFBTSw0QkFBNEIsR0FBRyw0QkFBNEIsR0FBRyxFQUFFLENBQUM7QUFDOUUs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QU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEIsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFFLE1BQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFMUUsT0FBTyxNQUFxQixDQUFDO0lBQy9CLENBQUM7OEdBNVNVLG9CQUFvQixrQkFXckIsc0JBQXNCO2tIQVhyQixvQkFBb0I7O1NBQXBCLG9CQUFvQjsyRkFBcEIsb0JBQW9CO2tCQURoQyxVQUFVOzswQkFZTixNQUFNOzJCQUFDLHNCQUFzQjs7MEJBQUcsUUFBUSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIEluamVjdGlvblRva2VuLCBJbmplY3QsIE9wdGlvbmFsLCBWRVJTSU9OLCBpc0Rldk1vZGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgSHR0cFJlcXVlc3QsIEh0dHBSZXNwb25zZSwgSHR0cEV2ZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9PYnNlcnZhYmxlJztcclxuaW1wb3J0IHsgTmdIdHRwQ2FjaGluZ1N0b3JhZ2VJbnRlcmZhY2UgfSBmcm9tICcuL3N0b3JhZ2UvbmctaHR0cC1jYWNoaW5nLXN0b3JhZ2UuaW50ZXJmYWNlJztcclxuaW1wb3J0IHsgTmdIdHRwQ2FjaGluZ01lbW9yeVN0b3JhZ2UgfSBmcm9tICcuL3N0b3JhZ2UvbmctaHR0cC1jYWNoaW5nLW1lbW9yeS1zdG9yYWdlJztcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgTmdIdHRwQ2FjaGluZ0VudHJ5PEsgPSBhbnksIFQgPSBhbnk+IHtcclxuICAvKipcclxuICAgKiBVUkxcclxuICAgKi9cclxuICB1cmw6IHN0cmluZztcclxuICAvKipcclxuICAgKiBIdHRwUmVzcG9uc2VcclxuICAgKi9cclxuICByZXNwb25zZTogSHR0cFJlc3BvbnNlPFQ+O1xyXG4gIC8qKlxyXG4gICAqIEh0dHBSZXF1ZXN0XHJcbiAgICovXHJcbiAgcmVxdWVzdDogSHR0cFJlcXVlc3Q8Sz47XHJcbiAgLyoqXHJcbiAgICogVGltZXN0YW0gb2YgYWRkIHRvIGNhY2hlIHRpbWVcclxuICAgKi9cclxuICBhZGRlZFRpbWU6IG51bWJlcjtcclxuICAvKipcclxuICAgKiBDYWNoZSB2ZXJzaW9uXHJcbiAgICovXHJcbiAgdmVyc2lvbjogc3RyaW5nO1xyXG59XHJcblxyXG5leHBvcnQgY29uc3QgTkdfSFRUUF9DQUNISU5HX0NPTkZJRyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxOZ0h0dHBDYWNoaW5nQ29uZmlnPihcclxuICAnbmctaHR0cC1jYWNoaW5nLmNvbmZpZydcclxuKTtcclxuXHJcbmV4cG9ydCBlbnVtIE5nSHR0cENhY2hpbmdTdHJhdGVneSB7XHJcbiAgLyoqXHJcbiAgICogQWxsIHJlcXVlc3QgYXJlIGNhY2hlYWJsZSBpZiBIVFRQIG1ldGhvZCBpcyBpbnRvIGBhbGxvd2VkTWV0aG9kYFxyXG4gICAqL1xyXG4gIEFMTE9XX0FMTCA9ICdBTExPV19BTEwnLFxyXG4gIC8qKlxyXG4gICAqIE9ubHkgdGhlIHJlcXVlc3Qgd2l0aCBgWC1ORy1IVFRQLUNBQ0hJTkctQUxMT1ctQ0FDSEVgIGhlYWRlciBhcmUgY2FjaGVhYmxlIGlmIEhUVFAgbWV0aG9kIGlzIGludG8gYGFsbG93ZWRNZXRob2RgXHJcbiAgICovXHJcbiAgRElTQUxMT1dfQUxMID0gJ0RJU0FMTE9XX0FMTCdcclxufVxyXG5cclxuZXhwb3J0IGVudW0gTmdIdHRwQ2FjaGluZ0hlYWRlcnMge1xyXG4gIC8qKlxyXG4gICAqIFJlcXVlc3QgaXMgY2FjaGVhYmxlIGlmIEhUVFAgbWV0aG9kIGlzIGludG8gYGFsbG93ZWRNZXRob2RgXHJcbiAgICovXHJcbiAgQUxMT1dfQ0FDSEUgPSAnWC1ORy1IVFRQLUNBQ0hJTkctQUxMT1ctQ0FDSEUnLFxyXG4gIC8qKlxyXG4gICAqIFJlcXVlc3QgaXNuJ3QgY2FjaGVhYmxlXHJcbiAgICovXHJcbiAgRElTQUxMT1dfQ0FDSEUgPSAnWC1ORy1IVFRQLUNBQ0hJTkctRElTQUxMT1ctQ0FDSEUnLFxyXG4gIC8qKlxyXG4gICAqIFNwZWNpZmljIGNhY2hlIGxpZmV0aW1lIGZvciB0aGUgcmVxdWVzdFxyXG4gICAqL1xyXG4gIExJRkVUSU1FID0gJ1gtTkctSFRUUC1DQUNISU5HLUxJRkVUSU1FJyxcclxuICAvKipcclxuICAgKiBZb3UgY2FuIHRhZyBtdWx0aXBsZSByZXF1ZXN0IGJ5IGFkZGluZyB0aGlzIGhlYWRlciB3aXRoIHRoZSBzYW1lIHRhZyBhbmQgXHJcbiAgICogdXNpbmcgYE5nSHR0cENhY2hpbmdTZXJ2aWNlLmNsZWFyQ2FjaGVCeVRhZyh0YWc6IHN0cmluZylgIGZvciBkZWxldGUgYWxsIHRoZSB0YWdnZWQgcmVxdWVzdFxyXG4gICAqL1xyXG4gIFRBRyA9ICdYLU5HLUhUVFAtQ0FDSElORy1UQUcnXHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBOZ0h0dHBDYWNoaW5nSGVhZGVyc0xpc3QgPSBPYmplY3QudmFsdWVzKE5nSHR0cENhY2hpbmdIZWFkZXJzKTtcclxuXHJcbmV4cG9ydCBjb25zdCBOR19IVFRQX0NBQ0hJTkdfU0VDT05EX0lOX01TID0gMTAwMDtcclxuZXhwb3J0IGNvbnN0IE5HX0hUVFBfQ0FDSElOR19NSU5VVEVfSU5fTVMgPSBOR19IVFRQX0NBQ0hJTkdfU0VDT05EX0lOX01TICogNjA7XHJcbmV4cG9ydCBjb25zdCBOR19IVFRQX0NBQ0hJTkdfSE9VUl9JTl9NUyA9IE5HX0hUVFBfQ0FDSElOR19NSU5VVEVfSU5fTVMgKiA2MDtcclxuZXhwb3J0IGNvbnN0IE5HX0hUVFBfQ0FDSElOR19EQVlfSU5fTVMgPSBOR19IVFRQX0NBQ0hJTkdfSE9VUl9JTl9NUyAqIDI0O1xyXG5leHBvcnQgY29uc3QgTkdfSFRUUF9DQUNISU5HX1dFRUtfSU5fTVMgPSBOR19IVFRQX0NBQ0hJTkdfREFZX0lOX01TICogNztcclxuZXhwb3J0IGNvbnN0IE5HX0hUVFBfQ0FDSElOR19NT05USF9JTl9NUyA9IE5HX0hUVFBfQ0FDSElOR19EQVlfSU5fTVMgKiAzMDtcclxuZXhwb3J0IGNvbnN0IE5HX0hUVFBfQ0FDSElOR19ZRUFSX0lOX01TID0gTkdfSFRUUF9DQUNISU5HX0RBWV9JTl9NUyAqIDM2NTtcclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgTmdIdHRwQ2FjaGluZ0NvbmZpZyB7XHJcbiAgLyoqXHJcbiAgICogU2V0IHRoZSBjYWNoZSBzdG9yZS4gWW91IGNhbiBpbXBsZW1lbnQgeW91ciBjdXN0b20gc3RvcmUgYnkgaW1wbGVtZW50IHRoZSBgTmdIdHRwQ2FjaGluZ1N0b3JhZ2VJbnRlcmZhY2VgIGludGVyZmFjZSwgZWcuOlxyXG4gICAqL1xyXG4gIHN0b3JlPzogTmdIdHRwQ2FjaGluZ1N0b3JhZ2VJbnRlcmZhY2U7XHJcbiAgLyoqXHJcbiAgICogTnVtYmVyIG9mIG1pbGxpc2Vjb25kIHRoYXQgYSByZXNwb25zZSBpcyBzdG9yZWQgaW4gdGhlIGNhY2hlLiBcclxuICAgKiBZb3UgY2FuIHNldCBzcGVjaWZpYyBcImxpZmV0aW1lXCIgZm9yIGVhY2ggcmVxdWVzdCBieSBhZGQgdGhlIGhlYWRlciBgWC1ORy1IVFRQLUNBQ0hJTkctTElGRVRJTUVgIChzZWUgZXhhbXBsZSBiZWxvdykuXHJcbiAgICovXHJcbiAgbGlmZXRpbWU/OiBudW1iZXI7XHJcbiAgLyoqXHJcbiAgICogQXJyYXkgb2YgYWxsb3dlZCBIVFRQIG1ldGhvZHMgdG8gY2FjaGUuIFxyXG4gICAqIFlvdSBjYW4gYWxsb3cgbXVsdGlwbGUgbWV0aG9kcywgZWcuOiBgWydHRVQnLCAnUE9TVCcsICdQVVQnLCAnREVMRVRFJywgJ0hFQUQnXWAgb3IgXHJcbiAgICogYWxsb3cgYWxsIG1ldGhvZHMgYnk6IGBbJ0FMTCddYC4gSWYgYGFsbG93ZWRNZXRob2RgIGlzIGFuIGVtcHR5IGFycmF5IChgW11gKSwgbm8gcmVzcG9uc2UgYXJlIGNhY2hlZC5cclxuICAgKiAqV2FybmluZyEqIGBOZ0h0dHBDYWNoaW5nYCB1c2UgdGhlIGZ1bGwgdXJsICh1cmwgd2l0aCBxdWVyeSBwYXJhbWV0ZXJzKSBhcyB1bmlxdWUga2V5IGZvciB0aGUgY2FjaGVkIHJlc3BvbnNlLFxyXG4gICAqIHRoaXMgaXMgY29ycmVjdCBmb3IgdGhlIGBHRVRgIHJlcXVlc3QgYnV0IGlzIF9wb3RlbnRpYWxseV8gd3JvbmcgZm9yIG90aGVyIHR5cGUgb2YgcmVxdWVzdCAoZWcuIGBQT1NUYCwgYFBVVGApLiBcclxuICAgKiBZb3UgY2FuIHNldCBhIGRpZmZlcmVudCBcImtleVwiIGJ5IGN1c3RvbWl6aW5nIHRoZSBgZ2V0S2V5YCBjb25maWcgbWV0aG9kIChzZWUgYGdldEtleWAgc2VjdGlvbikuXHJcbiAgICovXHJcbiAgYWxsb3dlZE1ldGhvZD86IHN0cmluZ1tdO1xyXG4gIC8qKlxyXG4gICAqIFNldCB0aGUgY2FjaGUgc3RyYXRlZ3ksIHBvc3NpYmxlIHN0cmF0ZWdpZXMgYXJlOlxyXG4gICAqIC0gYE5nSHR0cENhY2hpbmdTdHJhdGVneS5BTExPV19BTExgOiBBbGwgcmVxdWVzdCBhcmUgY2FjaGVhYmxlIGlmIEhUVFAgbWV0aG9kIGlzIGludG8gYGFsbG93ZWRNZXRob2RgO1xyXG4gICAqIC0gYE5nSHR0cENhY2hpbmdTdHJhdGVneS5ESVNBTExPV19BTExgOiBPbmx5IHRoZSByZXF1ZXN0IHdpdGggYFgtTkctSFRUUC1DQUNISU5HLUFMTE9XLUNBQ0hFYCBoZWFkZXIgYXJlIGNhY2hlYWJsZSBpZiBIVFRQIG1ldGhvZCBpcyBpbnRvIGBhbGxvd2VkTWV0aG9kYDtcclxuICAgKi9cclxuICBjYWNoZVN0cmF0ZWd5PzogTmdIdHRwQ2FjaGluZ1N0cmF0ZWd5O1xyXG4gIC8qKlxyXG4gICAqIENhY2hlIHZlcnNpb24uIFdoZW4geW91IGhhdmUgYSBicmVha2luZyBjaGFuZ2UsIGNoYW5nZSB0aGUgdmVyc2lvbiwgYW5kIGl0J2xsIGRlbGV0ZSB0aGUgY3VycmVudCBjYWNoZSBhdXRvbWF0aWNhbGx5LlxyXG4gICAqIFRoZSBkZWZhdWx0IHZhbHVlIGlzIEFuZ3VsYXIgbWFqb3IgdmVyc2lvbiAoZWcuIDEzKSwgaW4gdGhpcyB3YXksIHRoZSBjYWNoZSBpcyBpbnZhbGl0YWRlZCBvbiBldmVyeSBBbmd1bGFyIHVwZ3JhZGUuXHJcbiAgICovXHJcbiAgdmVyc2lvbj86IHN0cmluZztcclxuICAvKipcclxuICAgKiBJZiB0aGlzIGZ1bmN0aW9uIHJldHVybiBgdHJ1ZWAgdGhlIHJlcXVlc3QgaXMgZXhwaXJlZCBhbmQgYSBuZXcgcmVxdWVzdCBpcyBzZW5kIHRvIGJhY2tlbmQsIGlmIHJldHVybiBgZmFsc2VgIGlzbid0IGV4cGlyZWQuIFxyXG4gICAqIElmIHRoZSByZXN1bHQgaXMgYHVuZGVmaW5lZGAsIHRoZSBub3JtYWwgYmVoYXZpb3VyIGlzIHByb3ZpZGVkLlxyXG4gICAqL1xyXG4gIGlzRXhwaXJlZD86IDxLLCBUPihlbnRyeTogTmdIdHRwQ2FjaGluZ0VudHJ5PEssIFQ+KSA9PiBib29sZWFuIHwgdW5kZWZpbmVkO1xyXG4gIC8qKlxyXG4gICAqIElmIHRoaXMgZnVuY3Rpb24gcmV0dXJuIGB0cnVlYCB0aGUgcmVxdWVzdCBpcyBjYWNoZWFibGUsIGlmIHJldHVybiBgZmFsc2VgIGlzbid0IGNhY2hlYWJsZS4gXHJcbiAgICogSWYgdGhlIHJlc3VsdCBpcyBgdW5kZWZpbmVkYCwgdGhlIG5vcm1hbCBiZWhhdmlvdXIgaXMgcHJvdmlkZWQuXHJcbiAgICovXHJcbiAgaXNDYWNoZWFibGU/OiA8Sz4ocmVxOiBIdHRwUmVxdWVzdDxLPikgPT4gYm9vbGVhbiB8IHVuZGVmaW5lZDtcclxuICAvKipcclxuICAgKiBUaGlzIGZ1bmN0aW9uIHJldHVybiB0aGUgdW5pcXVlIGtleSAoYHN0cmluZ2ApIGZvciBzdG9yZSB0aGUgcmVzcG9uc2UgaW50byB0aGUgY2FjaGUuIFxyXG4gICAqIElmIHRoZSByZXN1bHQgaXMgYHVuZGVmaW5lZGAsIHRoZSBub3JtYWwgYmVoYXZpb3VyIGlzIHByb3ZpZGVkLlxyXG4gICAqL1xyXG4gIGdldEtleT86IDxLPihyZXE6IEh0dHBSZXF1ZXN0PEs+KSA9PiBzdHJpbmcgfCB1bmRlZmluZWQ7XHJcbiAgLyoqXHJcbiAgICogSWYgdGhpcyBmdW5jdGlvbiByZXR1cm4gYHRydWVgIHRoZSBjYWNoZSBlbnRyeSBpcyB2YWxpZCBhbmQgY2FuIGJlIHN0cm9yZWQsIGlmIHJldHVybiBgZmFsc2VgIGlzbid0IHZhbGlkLiBcclxuICAgKiBJZiB0aGUgcmVzdWx0IGlzIGB1bmRlZmluZWRgLCB0aGUgbm9ybWFsIGJlaGF2aW91ciBpcyBwcm92aWRlZC5cclxuICAgKi9cclxuICBpc1ZhbGlkPzogPEssIFQ+KGVudHJ5OiBOZ0h0dHBDYWNoaW5nRW50cnk8SywgVD4pID0+IGJvb2xlYW4gfCB1bmRlZmluZWQ7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgTmdIdHRwQ2FjaGluZ0RlZmF1bHRDb25maWcgZXh0ZW5kcyBOZ0h0dHBDYWNoaW5nQ29uZmlnIHtcclxuICBzdG9yZTogTmdIdHRwQ2FjaGluZ1N0b3JhZ2VJbnRlcmZhY2U7XHJcbiAgbGlmZXRpbWU6IG51bWJlcjtcclxuICBhbGxvd2VkTWV0aG9kOiBzdHJpbmdbXTtcclxuICBjYWNoZVN0cmF0ZWd5OiBOZ0h0dHBDYWNoaW5nU3RyYXRlZ3k7XHJcbiAgdmVyc2lvbjogc3RyaW5nO1xyXG59XHJcblxyXG5leHBvcnQgY29uc3QgTmdIdHRwQ2FjaGluZ0NvbmZpZ0RlZmF1bHQ6IFJlYWRvbmx5PE5nSHR0cENhY2hpbmdEZWZhdWx0Q29uZmlnPiA9IHtcclxuICBzdG9yZTogbmV3IE5nSHR0cENhY2hpbmdNZW1vcnlTdG9yYWdlKCksXHJcbiAgbGlmZXRpbWU6IE5HX0hUVFBfQ0FDSElOR19IT1VSX0lOX01TLFxyXG4gIHZlcnNpb246IFZFUlNJT04ubWFqb3IsXHJcbiAgYWxsb3dlZE1ldGhvZDogWydHRVQnLCAnSEVBRCddLFxyXG4gIGNhY2hlU3RyYXRlZ3k6IE5nSHR0cENhY2hpbmdTdHJhdGVneS5BTExPV19BTEwsXHJcbn07XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBOZ0h0dHBDYWNoaW5nU2VydmljZSB7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgcXVldWUgPSBuZXcgTWFwPHN0cmluZywgT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8YW55Pj4+KCk7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBOZ0h0dHBDYWNoaW5nRGVmYXVsdENvbmZpZztcclxuXHJcbiAgcHJpdmF0ZSBnY0xvY2sgPSBmYWxzZTtcclxuXHJcbiAgcHJpdmF0ZSBkZXZNb2RlOiBib29sZWFuID0gaXNEZXZNb2RlKCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgQEluamVjdChOR19IVFRQX0NBQ0hJTkdfQ09ORklHKSBAT3B0aW9uYWwoKSBjb25maWc6IFJlYWRvbmx5PE5nSHR0cENhY2hpbmdDb25maWc+XHJcbiAgKSB7XHJcbiAgICBpZiAoY29uZmlnKSB7XHJcbiAgICAgIHRoaXMuY29uZmlnID0geyAuLi5OZ0h0dHBDYWNoaW5nQ29uZmlnRGVmYXVsdCwgLi4uY29uZmlnIH07XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmNvbmZpZyA9IHsgLi4uTmdIdHRwQ2FjaGluZ0NvbmZpZ0RlZmF1bHQgfTtcclxuICAgIH1cclxuICAgIC8vIHN0YXJ0IGNhY2hlIGNsZWFuXHJcbiAgICB0aGlzLnJ1bkdjKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm4gdGhlIGNvbmZpZ1xyXG4gICAqL1xyXG4gIGdldENvbmZpZygpOiBSZWFkb25seTxOZ0h0dHBDYWNoaW5nQ29uZmlnPiB7XHJcbiAgICByZXR1cm4gdGhpcy5jb25maWc7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm4gdGhlIHF1ZXVlIG1hcFxyXG4gICAqL1xyXG4gIGdldFF1ZXVlKCk6IFJlYWRvbmx5PE1hcDxzdHJpbmcsIE9ic2VydmFibGU8SHR0cEV2ZW50PGFueT4+Pj4ge1xyXG4gICAgcmV0dXJuIHRoaXMucXVldWU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm4gdGhlIGNhY2hlIHN0b3JlXHJcbiAgICovXHJcbiAgZ2V0U3RvcmUoKTogUmVhZG9ubHk8TmdIdHRwQ2FjaGluZ1N0b3JhZ2VJbnRlcmZhY2U+IHtcclxuICAgIHJldHVybiB0aGlzLmNvbmZpZy5zdG9yZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybiByZXNwb25zZSBmcm9tIGNhY2hlXHJcbiAgICovXHJcbiAgZ2V0RnJvbUNhY2hlPEssIFQ+KHJlcTogSHR0cFJlcXVlc3Q8Sz4pOiBSZWFkb25seTxIdHRwUmVzcG9uc2U8VD4+IHwgdW5kZWZpbmVkIHtcclxuICAgIGNvbnN0IGtleTogc3RyaW5nID0gdGhpcy5nZXRLZXkocmVxKTtcclxuICAgIGNvbnN0IGNhY2hlZDogTmdIdHRwQ2FjaGluZ0VudHJ5PEssIFQ+IHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWcuc3RvcmUuZ2V0PEssIFQ+KGtleSk7XHJcblxyXG4gICAgaWYgKCFjYWNoZWQpIHtcclxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5pc0V4cGlyZWQoY2FjaGVkKSkge1xyXG4gICAgICB0aGlzLmNsZWFyQ2FjaGVCeUtleShrZXkpO1xyXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLmRlZXBGcmVlemUoY2FjaGVkLnJlc3BvbnNlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFkZCByZXNwb25zZSB0byBjYWNoZVxyXG4gICAqL1xyXG4gIGFkZFRvQ2FjaGU8SywgVD4ocmVxOiBIdHRwUmVxdWVzdDxLPiwgcmVzOiBIdHRwUmVzcG9uc2U8VD4pOiBib29sZWFuIHtcclxuICAgIGNvbnN0IGVudHJ5OiBOZ0h0dHBDYWNoaW5nRW50cnk8SywgVD4gPSB7XHJcbiAgICAgIHVybDogcmVxLnVybFdpdGhQYXJhbXMsXHJcbiAgICAgIHJlc3BvbnNlOiByZXMsXHJcbiAgICAgIHJlcXVlc3Q6IHJlcSxcclxuICAgICAgYWRkZWRUaW1lOiBEYXRlLm5vdygpLFxyXG4gICAgICB2ZXJzaW9uOiB0aGlzLmNvbmZpZy52ZXJzaW9uLFxyXG4gICAgfTtcclxuICAgIGlmICh0aGlzLmlzVmFsaWQoZW50cnkpKSB7XHJcbiAgICAgIGNvbnN0IGtleTogc3RyaW5nID0gdGhpcy5nZXRLZXkocmVxKTtcclxuICAgICAgdGhpcy5jb25maWcuc3RvcmUuc2V0KGtleSwgZW50cnkpO1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIERlbGV0ZSByZXNwb25zZSBmcm9tIGNhY2hlXHJcbiAgICovXHJcbiAgZGVsZXRlRnJvbUNhY2hlPEs+KHJlcTogSHR0cFJlcXVlc3Q8Sz4pOiBib29sZWFuIHtcclxuICAgIGNvbnN0IGtleTogc3RyaW5nID0gdGhpcy5nZXRLZXkocmVxKTtcclxuICAgIHJldHVybiB0aGlzLmNsZWFyQ2FjaGVCeUtleShrZXkpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2xlYXIgdGhlIGNhY2hlXHJcbiAgICovXHJcbiAgY2xlYXJDYWNoZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuY29uZmlnLnN0b3JlLmNsZWFyKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbGVhciB0aGUgY2FjaGUgYnkga2V5XHJcbiAgICovXHJcbiAgY2xlYXJDYWNoZUJ5S2V5KGtleTogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5jb25maWcuc3RvcmUuZGVsZXRlKGtleSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbGVhciB0aGUgY2FjaGUgYnkgcmVnZXhcclxuICAgKi9cclxuICBjbGVhckNhY2hlQnlSZWdleDxLLCBUPihyZWdleDogUmVnRXhwKTogdm9pZCB7XHJcbiAgICB0aGlzLmNvbmZpZy5zdG9yZS5mb3JFYWNoPEssIFQ+KChfOiBOZ0h0dHBDYWNoaW5nRW50cnk8SywgVD4sIGtleTogc3RyaW5nKSA9PiB7XHJcbiAgICAgIGlmIChyZWdleC50ZXN0KGtleSkpIHtcclxuICAgICAgICB0aGlzLmNsZWFyQ2FjaGVCeUtleShrZXkpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENsZWFyIHRoZSBjYWNoZSBieSBUQUdcclxuICAgKi9cclxuICBjbGVhckNhY2hlQnlUYWc8SywgVD4odGFnOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuY29uZmlnLnN0b3JlLmZvckVhY2g8SywgVD4oKGVudHJ5OiBOZ0h0dHBDYWNoaW5nRW50cnk8SywgVD4sIGtleTogc3RyaW5nKSA9PiB7XHJcbiAgICAgIGNvbnN0IHRhZ0hlYWRlciA9IGVudHJ5LnJlcXVlc3QuaGVhZGVycy5nZXQoTmdIdHRwQ2FjaGluZ0hlYWRlcnMuVEFHKTtcclxuICAgICAgaWYgKHRhZ0hlYWRlciAmJiB0YWdIZWFkZXIuc3BsaXQoJywnKS5pbmNsdWRlcyh0YWcpKSB7XHJcbiAgICAgICAgdGhpcy5jbGVhckNhY2hlQnlLZXkoa2V5KTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSdW4gZ2FyYmFnZSBjb2xsZWN0b3IgKGRlbGV0ZSBleHBpcmVkIGNhY2hlIGVudHJ5KVxyXG4gICAqL1xyXG4gIHJ1bkdjPEssIFQ+KCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMuZ2NMb2NrKSB7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIHRoaXMuZ2NMb2NrID0gdHJ1ZTtcclxuICAgIHRoaXMuY29uZmlnLnN0b3JlLmZvckVhY2g8SywgVD4oKGVudHJ5OiBOZ0h0dHBDYWNoaW5nRW50cnk8SywgVD4sIGtleTogc3RyaW5nKSA9PiB7XHJcbiAgICAgIGlmICh0aGlzLmlzRXhwaXJlZChlbnRyeSkpIHtcclxuICAgICAgICB0aGlzLmNsZWFyQ2FjaGVCeUtleShrZXkpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIHRoaXMuZ2NMb2NrID0gZmFsc2U7XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybiB0cnVlIGlmIGNhY2hlIGVudHJ5IGlzIGV4cGlyZWRcclxuICAgKi9cclxuICBpc0V4cGlyZWQ8SywgVD4oZW50cnk6IE5nSHR0cENhY2hpbmdFbnRyeTxLLCBUPik6IGJvb2xlYW4ge1xyXG4gICAgLy8gaWYgdXNlciBwcm92aWRlIGN1c3RvbSBtZXRob2QsIHVzZSBpdFxyXG4gICAgaWYgKHR5cGVvZiB0aGlzLmNvbmZpZy5pc0V4cGlyZWQgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5jb25maWcuaXNFeHBpcmVkKGVudHJ5KTtcclxuICAgICAgLy8gaWYgcmVzdWx0IGlzIHVuZGVmaW5lZCwgbm9ybWFsIGJlaGF2aW91ciBpcyBwcm92aWRlZFxyXG4gICAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvLyBjb25maWcvZGVmYXVsdCBsaWZldGltZVxyXG4gICAgbGV0IGxpZmV0aW1lOiBudW1iZXIgPSB0aGlzLmNvbmZpZy5saWZldGltZTtcclxuICAgIC8vIHJlcXVlc3QgaGFzIG93biBsaWZldGltZVxyXG4gICAgY29uc3QgaGVhZGVyTGlmZXRpbWUgPSBlbnRyeS5yZXF1ZXN0LmhlYWRlcnMuZ2V0KE5nSHR0cENhY2hpbmdIZWFkZXJzLkxJRkVUSU1FKTtcclxuICAgIGlmIChoZWFkZXJMaWZldGltZSkge1xyXG4gICAgICBsaWZldGltZSA9ICtoZWFkZXJMaWZldGltZTtcclxuICAgIH1cclxuICAgIC8vIG5ldmVyIGV4cGlyZSBpZiAwXHJcbiAgICBpZiAobGlmZXRpbWUgPT09IDApIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgLy8gd3JvbmcgbGlmZXRpbWVcclxuICAgIGlmIChsaWZldGltZSA8IDAgfHwgaXNOYU4obGlmZXRpbWUpKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignbGlmZXRpbWUgbXVzdCBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgMCcpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGVudHJ5LmFkZGVkVGltZSArIGxpZmV0aW1lIDwgRGF0ZS5ub3coKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJldHVybiB0cnVlIGlmIGNhY2hlIGVudHJ5IGlzIHZhbGlkIGZvciBzdG9yZSBpbiB0aGUgY2FjaGVcclxuICAgKi9cclxuICBpc1ZhbGlkPEssIFQ+KGVudHJ5OiBOZ0h0dHBDYWNoaW5nRW50cnk8SywgVD4pOiBib29sZWFuIHtcclxuICAgIC8vIGlmIHVzZXIgcHJvdmlkZSBjdXN0b20gbWV0aG9kLCB1c2UgaXRcclxuICAgIGlmICh0eXBlb2YgdGhpcy5jb25maWcuaXNWYWxpZCA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmNvbmZpZy5pc1ZhbGlkKGVudHJ5KTtcclxuICAgICAgLy8gaWYgcmVzdWx0IGlzIHVuZGVmaW5lZCwgbm9ybWFsIGJlaGF2aW91ciBpcyBwcm92aWRlZFxyXG4gICAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvLyBkaWZmZXJlbnQgdmVyc2lvblxyXG4gICAgaWYgKHRoaXMuY29uZmlnLnZlcnNpb24gIT09IGVudHJ5LnZlcnNpb24pIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXR1cm4gdHJ1ZSBpZiB0aGUgcmVxdWVzdCBpcyBjYWNoZWFibGVcclxuICAgKi9cclxuICBpc0NhY2hlYWJsZTxLPihyZXE6IEh0dHBSZXF1ZXN0PEs+KTogYm9vbGVhbiB7XHJcbiAgICAvLyBpZiB1c2VyIHByb3ZpZGUgY3VzdG9tIG1ldGhvZCwgdXNlIGl0XHJcbiAgICBpZiAodHlwZW9mIHRoaXMuY29uZmlnLmlzQ2FjaGVhYmxlID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuY29uZmlnLmlzQ2FjaGVhYmxlKHJlcSk7XHJcbiAgICAgIC8vIGlmIHJlc3VsdCBpcyB1bmRlZmluZWQsIG5vcm1hbCBiZWhhdmlvdXIgaXMgcHJvdmlkZWRcclxuICAgICAgaWYgKHJlc3VsdCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgLy8gcmVxdWVzdCBoYXMgZGlzYWxsb3cgY2FjaGUgaGVhZGVyXHJcbiAgICBpZiAocmVxLmhlYWRlcnMuaGFzKE5nSHR0cENhY2hpbmdIZWFkZXJzLkRJU0FMTE9XX0NBQ0hFKSkge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgICAvLyBzdHJhdGVneSBpcyBkaXNhbGxvdyBhbGwuLi5cclxuICAgIGlmICh0aGlzLmNvbmZpZy5jYWNoZVN0cmF0ZWd5ID09PSBOZ0h0dHBDYWNoaW5nU3RyYXRlZ3kuRElTQUxMT1dfQUxMKSB7XHJcbiAgICAgIC8vIHJlcXVlc3QgaXNuJ3QgYWxsb3dlZCBpZiBjb21lIHdpdGhvdXQgYWxsb3cgaGVhZGVyXHJcbiAgICAgIGlmICghcmVxLmhlYWRlcnMuaGFzKE5nSHR0cENhY2hpbmdIZWFkZXJzLkFMTE9XX0NBQ0hFKSkge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgLy8gaWYgYWxsb3dlZCBtZXRob2QgaXMgb25seSBBTEwsIGFsbG93IGFsbCBodHRwIG1ldGhvc1xyXG4gICAgaWYgKHRoaXMuY29uZmlnLmFsbG93ZWRNZXRob2QubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgIGlmICh0aGlzLmNvbmZpZy5hbGxvd2VkTWV0aG9kWzBdID09PSAnQUxMJykge1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvLyByZXF1ZXN0IGlzIGFsbG93ZWQgaWYgbWV0aG9kIGlzIGluIGFsbG93ZWRNZXRob2RcclxuICAgIHJldHVybiB0aGlzLmNvbmZpZy5hbGxvd2VkTWV0aG9kLmluZGV4T2YocmVxLm1ldGhvZCkgIT09IC0xO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJuIHRoZSBjYWNoZSBrZXkuXHJcbiAgICogRGVmYXVsdCBrZXkgaXMgaHR0cCBtZXRob2QgcGx1cyB1cmwgd2l0aCBxdWVyeSBwYXJhbWV0ZXJzLCBlZy46XHJcbiAgICogYEdFVEBodHRwczovL2dpdGh1Yi5jb20vbmlncm9zaW1vbmUvbmctaHR0cC1jYWNoaW5nYFxyXG4gICAqL1xyXG4gIGdldEtleTxLPihyZXE6IEh0dHBSZXF1ZXN0PEs+KTogc3RyaW5nIHtcclxuICAgIC8vIGlmIHVzZXIgcHJvdmlkZSBjdXN0b20gbWV0aG9kLCB1c2UgaXRcclxuICAgIGlmICh0eXBlb2YgdGhpcy5jb25maWcuZ2V0S2V5ID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuY29uZmlnLmdldEtleShyZXEpO1xyXG4gICAgICAvLyBpZiByZXN1bHQgaXMgdW5kZWZpbmVkLCBub3JtYWwgYmVoYXZpb3VyIGlzIHByb3ZpZGVkXHJcbiAgICAgIGlmIChyZXN1bHQgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIC8vIGRlZmF1bHQga2V5IGlzIHJlcS5tZXRob2QgcGx1cyB1cmwgd2l0aCBxdWVyeSBwYXJhbWV0ZXJzXHJcbiAgICByZXR1cm4gcmVxLm1ldGhvZCArICdAJyArIHJlcS51cmxXaXRoUGFyYW1zO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJuIG9ic2VydmFibGUgZnJvbSBjYWNoZVxyXG4gICAqL1xyXG4gIGdldEZyb21RdWV1ZTxLLCBUPihyZXE6IEh0dHBSZXF1ZXN0PEs+KTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8VD4+IHwgdW5kZWZpbmVkIHtcclxuICAgIGNvbnN0IGtleTogc3RyaW5nID0gdGhpcy5nZXRLZXkocmVxKTtcclxuICAgIGNvbnN0IGNhY2hlZDogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8VD4+IHwgdW5kZWZpbmVkID0gdGhpcy5xdWV1ZS5nZXQoa2V5KTtcclxuXHJcbiAgICBpZiAoIWNhY2hlZCkge1xyXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBjYWNoZWQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBZGQgb2JzZXJ2YWJsZSB0byBjYWNoZVxyXG4gICAqL1xyXG4gIGFkZFRvUXVldWU8SywgVD4ocmVxOiBIdHRwUmVxdWVzdDxLPiwgb2JzOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxUPj4pOiB2b2lkIHtcclxuICAgIGNvbnN0IGtleTogc3RyaW5nID0gdGhpcy5nZXRLZXkocmVxKTtcclxuICAgIHRoaXMucXVldWUuc2V0KGtleSwgb2JzKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIERlbGV0ZSBvYnNlcnZhYmxlIGZyb20gY2FjaGVcclxuICAgKi9cclxuICBkZWxldGVGcm9tUXVldWU8Sz4ocmVxOiBIdHRwUmVxdWVzdDxLPik6IGJvb2xlYW4ge1xyXG4gICAgY29uc3Qga2V5OiBzdHJpbmcgPSB0aGlzLmdldEtleShyZXEpO1xyXG4gICAgcmV0dXJuIHRoaXMucXVldWUuZGVsZXRlKGtleSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZWN1cnNpdmVseSBPYmplY3QuZnJlZXplIHNpbXBsZSBKYXZhc2NyaXB0IHN0cnVjdHVyZXMgY29uc2lzdGluZyBvZiBwbGFpbiBvYmplY3RzLCBhcnJheXMsIGFuZCBwcmltaXRpdmVzLlxyXG4gICAqIE1ha2UgdGhlIGRhdGEgaW1tdXRhYmxlLlxyXG4gICAqIEByZXR1cm5zIGltbXV0YWJsZSBvYmplY3RcclxuICAgKi9cclxuICBwcml2YXRlIGRlZXBGcmVlemU8Uz4ob2JqZWN0OiBTKTogUmVhZG9ubHk8Uz4ge1xyXG4gICAgLy8gTm8gZnJlZXppbmcgaW4gcHJvZHVjdGlvbiAoZm9yIGJldHRlciBwZXJmb3JtYW5jZSkuXHJcbiAgICBpZiAoIXRoaXMuZGV2TW9kZSB8fCAhb2JqZWN0IHx8IHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnKSB7XHJcbiAgICAgIHJldHVybiBvYmplY3QgYXMgUmVhZG9ubHk8Uz47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gV2hlbiBhbHJlYWR5IGZyb3plbiwgd2UgYXNzdW1lIGl0cyBjaGlsZHJlbiBhcmUgZnJvemVuIChmb3IgYmV0dGVyIHBlcmZvcm1hbmNlKS5cclxuICAgIC8vIFRoaXMgc2hvdWxkIGJlIHRydWUgaWYgeW91IGFsd2F5cyB1c2UgYGRlZXBGcmVlemVgIHRvIGZyZWV6ZSBvYmplY3RzLlxyXG4gICAgLy9cclxuICAgIC8vIE5vdGUgdGhhdCBPYmplY3QuaXNGcm96ZW4gd2lsbCBhbHNvIHJldHVybiBgdHJ1ZWAgZm9yIHByaW1pdGl2ZXMgKG51bWJlcnMsXHJcbiAgICAvLyBzdHJpbmdzLCBib29sZWFucywgdW5kZWZpbmVkLCBudWxsKSwgc28gdGhlcmUgaXMgbm8gbmVlZCB0byBjaGVjayBmb3JcclxuICAgIC8vIHRob3NlIGV4cGxpY2l0bHkuXHJcbiAgICBpZiAoT2JqZWN0LmlzRnJvemVuKG9iamVjdCkpIHtcclxuICAgICAgcmV0dXJuIG9iamVjdCBhcyBSZWFkb25seTxTPjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBdCB0aGlzIHBvaW50IHdlIGtub3cgdGhhdCB3ZSdyZSBkZWFsaW5nIHdpdGggZWl0aGVyIGFuIGFycmF5IG9yIHBsYWluIG9iamVjdCwgc29cclxuICAgIC8vIGp1c3QgZnJlZXplIGl0IGFuZCByZWN1cnNlIG9uIGl0cyB2YWx1ZXMuXHJcbiAgICBPYmplY3QuZnJlZXplKG9iamVjdCk7XHJcbiAgICBPYmplY3Qua2V5cyhvYmplY3QpLmZvckVhY2goa2V5ID0+IHRoaXMuZGVlcEZyZWV6ZSgob2JqZWN0IGFzIGFueSlba2V5XSkpO1xyXG5cclxuICAgIHJldHVybiBvYmplY3QgYXMgUmVhZG9ubHk8Uz47XHJcbiAgfVxyXG59XHJcbiJdfQ==