ng-http-caching 2.0.1 → 13.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.
- package/README.md +4 -3
- package/esm2020/lib/ng-http-caching-interceptor.service.mjs +66 -0
- package/esm2020/lib/ng-http-caching.module.mjs +45 -0
- package/esm2020/lib/ng-http-caching.service.mjs +265 -0
- package/esm2020/lib/storage/ng-http-caching-memory-storage.mjs +28 -0
- package/esm2020/lib/storage/ng-http-caching-storage.interface.mjs +2 -0
- package/{esm2015/ng-http-caching.js → esm2020/ng-http-caching.mjs} +0 -0
- package/{esm2015/public-api.js → esm2020/public-api.mjs} +0 -0
- package/fesm2015/ng-http-caching.mjs +410 -0
- package/fesm2015/ng-http-caching.mjs.map +1 -0
- package/{fesm2015/ng-http-caching.js → fesm2020/ng-http-caching.mjs} +58 -51
- package/fesm2020/ng-http-caching.mjs.map +1 -0
- package/lib/ng-http-caching.service.d.ts +1 -1
- package/package.json +23 -13
- package/bundles/ng-http-caching.umd.js +0 -455
- package/bundles/ng-http-caching.umd.js.map +0 -1
- package/esm2015/lib/ng-http-caching-interceptor.service.js +0 -65
- package/esm2015/lib/ng-http-caching.module.js +0 -45
- package/esm2015/lib/ng-http-caching.service.js +0 -260
- package/esm2015/lib/storage/ng-http-caching-memory-storage.js +0 -27
- package/esm2015/lib/storage/ng-http-caching-storage.interface.js +0 -2
- package/fesm2015/ng-http-caching.js.map +0 -1
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import { HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { InjectionToken, Injectable, Inject, Optional, NgModule } from '@angular/core';
|
|
4
|
+
import { of } from 'rxjs';
|
|
5
|
+
import { tap, finalize, share } from 'rxjs/operators';
|
|
6
|
+
|
|
7
|
+
class NgHttpCachingMemoryStorage {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.store = new Map();
|
|
10
|
+
}
|
|
11
|
+
get size() {
|
|
12
|
+
return this.store.size;
|
|
13
|
+
}
|
|
14
|
+
clear() {
|
|
15
|
+
this.store.clear();
|
|
16
|
+
}
|
|
17
|
+
delete(key) {
|
|
18
|
+
return this.store.delete(key);
|
|
19
|
+
}
|
|
20
|
+
// eslint-disable-next-line no-unused-vars
|
|
21
|
+
forEach(callbackfn) {
|
|
22
|
+
return this.store.forEach(callbackfn);
|
|
23
|
+
}
|
|
24
|
+
get(key) {
|
|
25
|
+
return this.store.get(key);
|
|
26
|
+
}
|
|
27
|
+
has(key) {
|
|
28
|
+
return this.store.has(key);
|
|
29
|
+
}
|
|
30
|
+
set(key, value) {
|
|
31
|
+
this.store.set(key, value);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const NG_HTTP_CACHING_CONFIG = new InjectionToken('ng-http-caching.config');
|
|
36
|
+
var NgHttpCachingStrategy;
|
|
37
|
+
(function (NgHttpCachingStrategy) {
|
|
38
|
+
// eslint-disable-next-line no-unused-vars
|
|
39
|
+
NgHttpCachingStrategy["ALLOW_ALL"] = "ALLOW_ALL";
|
|
40
|
+
// eslint-disable-next-line no-unused-vars
|
|
41
|
+
NgHttpCachingStrategy["DISALLOW_ALL"] = "DISALLOW_ALL";
|
|
42
|
+
})(NgHttpCachingStrategy || (NgHttpCachingStrategy = {}));
|
|
43
|
+
var NgHttpCachingHeaders;
|
|
44
|
+
(function (NgHttpCachingHeaders) {
|
|
45
|
+
// eslint-disable-next-line no-unused-vars
|
|
46
|
+
NgHttpCachingHeaders["ALLOW_CACHE"] = "X-NG-HTTP-CACHING-ALLOW-CACHE";
|
|
47
|
+
// eslint-disable-next-line no-unused-vars
|
|
48
|
+
NgHttpCachingHeaders["DISALLOW_CACHE"] = "X-NG-HTTP-CACHING-DISALLOW-CACHE";
|
|
49
|
+
// eslint-disable-next-line no-unused-vars
|
|
50
|
+
NgHttpCachingHeaders["LIFETIME"] = "X-NG-HTTP-CACHING-LIFETIME";
|
|
51
|
+
// eslint-disable-next-line no-unused-vars
|
|
52
|
+
NgHttpCachingHeaders["TAG"] = "X-NG-HTTP-CACHING-TAG";
|
|
53
|
+
})(NgHttpCachingHeaders || (NgHttpCachingHeaders = {}));
|
|
54
|
+
const NgHttpCachingConfigDefault = {
|
|
55
|
+
store: new NgHttpCachingMemoryStorage(),
|
|
56
|
+
lifetime: 60 * 60 * 100,
|
|
57
|
+
allowedMethod: ['GET'],
|
|
58
|
+
cacheStrategy: NgHttpCachingStrategy.ALLOW_ALL,
|
|
59
|
+
};
|
|
60
|
+
class NgHttpCachingService {
|
|
61
|
+
constructor(config) {
|
|
62
|
+
this.queue = new Map();
|
|
63
|
+
this.config = NgHttpCachingConfigDefault;
|
|
64
|
+
if (config) {
|
|
65
|
+
this.config = Object.assign(Object.assign({}, NgHttpCachingConfigDefault), config);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Return the config
|
|
70
|
+
*/
|
|
71
|
+
getConfig() {
|
|
72
|
+
return this.config;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Return the queue map
|
|
76
|
+
*/
|
|
77
|
+
getQueue() {
|
|
78
|
+
return this.queue;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Return the cache store
|
|
82
|
+
*/
|
|
83
|
+
getStore() {
|
|
84
|
+
return this.config.store;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Return response from cache
|
|
88
|
+
*/
|
|
89
|
+
getFromCache(req) {
|
|
90
|
+
var _a;
|
|
91
|
+
const key = this.getKey(req);
|
|
92
|
+
const cached = (_a = this.config.store) === null || _a === void 0 ? void 0 : _a.get(key);
|
|
93
|
+
if (!cached) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
if (this.isExpired(cached)) {
|
|
97
|
+
this.clearCacheByKey(key);
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
return cached.response;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Add response to cache
|
|
104
|
+
*/
|
|
105
|
+
addToCache(req, res) {
|
|
106
|
+
var _a;
|
|
107
|
+
const key = this.getKey(req);
|
|
108
|
+
const entry = {
|
|
109
|
+
url: req.urlWithParams,
|
|
110
|
+
response: res,
|
|
111
|
+
request: req,
|
|
112
|
+
addedTime: Date.now(),
|
|
113
|
+
};
|
|
114
|
+
if (this.isValid(entry)) {
|
|
115
|
+
(_a = this.config.store) === null || _a === void 0 ? void 0 : _a.set(key, entry);
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Delete response from cache
|
|
122
|
+
*/
|
|
123
|
+
deleteFromCache(req) {
|
|
124
|
+
const key = this.getKey(req);
|
|
125
|
+
return this.clearCacheByKey(key);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Clear the cache
|
|
129
|
+
*/
|
|
130
|
+
clearCache() {
|
|
131
|
+
var _a;
|
|
132
|
+
(_a = this.config.store) === null || _a === void 0 ? void 0 : _a.clear();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Clear the cache by key
|
|
136
|
+
*/
|
|
137
|
+
clearCacheByKey(key) {
|
|
138
|
+
return this.config.store.delete(key);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Clear the cache by regex
|
|
142
|
+
*/
|
|
143
|
+
clearCacheByRegex(regex) {
|
|
144
|
+
this.config.store.forEach((entry, key) => {
|
|
145
|
+
if (regex.test(key)) {
|
|
146
|
+
this.clearCacheByKey(key);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Clear the cache by TAG
|
|
152
|
+
*/
|
|
153
|
+
clearCacheByTag(tag) {
|
|
154
|
+
this.config.store.forEach((entry, key) => {
|
|
155
|
+
const tagHeader = entry.request.headers.get(NgHttpCachingHeaders.TAG);
|
|
156
|
+
if (tagHeader && tagHeader.split(',').includes(tag)) {
|
|
157
|
+
this.clearCacheByKey(key);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Run garbage collector (delete expired cache entry)
|
|
163
|
+
*/
|
|
164
|
+
runGc() {
|
|
165
|
+
this.config.store.forEach((entry, key) => {
|
|
166
|
+
if (this.isExpired(entry)) {
|
|
167
|
+
this.clearCacheByKey(key);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Return true if cache entry is expired
|
|
173
|
+
*/
|
|
174
|
+
isExpired(entry) {
|
|
175
|
+
// if user provide custom method, use it
|
|
176
|
+
if (typeof this.config.isExpired === 'function') {
|
|
177
|
+
const result = this.config.isExpired(entry);
|
|
178
|
+
// if result is undefined, normal behaviour is provided
|
|
179
|
+
if (typeof result !== 'undefined') {
|
|
180
|
+
return result;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// config/default lifetime
|
|
184
|
+
let lifetime = this.config.lifetime;
|
|
185
|
+
// request has own lifetime
|
|
186
|
+
if (entry.request.headers.has(NgHttpCachingHeaders.LIFETIME)) {
|
|
187
|
+
lifetime = +(entry.request.headers.get(NgHttpCachingHeaders.LIFETIME) || '');
|
|
188
|
+
}
|
|
189
|
+
// never expire if 0
|
|
190
|
+
if (lifetime === 0) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
// wrong lifetime
|
|
194
|
+
if (lifetime < 0) {
|
|
195
|
+
throw new Error('lifetime must be greater than or equal 0');
|
|
196
|
+
}
|
|
197
|
+
return entry.addedTime + lifetime < Date.now();
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Return true if cache entry is valid for store in the cache
|
|
201
|
+
*/
|
|
202
|
+
isValid(entry) {
|
|
203
|
+
// if user provide custom method, use it
|
|
204
|
+
if (typeof this.config.isValid === 'function') {
|
|
205
|
+
const result = this.config.isValid(entry);
|
|
206
|
+
// if result is undefined, normal behaviour is provided
|
|
207
|
+
if (typeof result !== 'undefined') {
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Return true if the request is cacheable
|
|
215
|
+
*/
|
|
216
|
+
isCacheable(req) {
|
|
217
|
+
// if user provide custom method, use it
|
|
218
|
+
if (typeof this.config.isCacheable === 'function') {
|
|
219
|
+
const result = this.config.isCacheable(req);
|
|
220
|
+
// if result is undefined, normal behaviour is provided
|
|
221
|
+
if (typeof result !== 'undefined') {
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// request has disallow cache header
|
|
226
|
+
if (req.headers.has(NgHttpCachingHeaders.DISALLOW_CACHE)) {
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
// strategy is disallow all...
|
|
230
|
+
if (this.config.cacheStrategy === NgHttpCachingStrategy.DISALLOW_ALL) {
|
|
231
|
+
// request isn't allowed if come without allow header
|
|
232
|
+
if (!req.headers.has(NgHttpCachingHeaders.ALLOW_CACHE)) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// if allowed method is only ALL, allow all http methos
|
|
237
|
+
if (this.config.allowedMethod) {
|
|
238
|
+
if (this.config.allowedMethod.length === 1) {
|
|
239
|
+
if (this.config.allowedMethod[0] === 'ALL') {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
// request is allowed if method is in allowedMethod
|
|
244
|
+
return this.config.allowedMethod.indexOf(req.method) !== -1;
|
|
245
|
+
}
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Return the cache key
|
|
250
|
+
*/
|
|
251
|
+
getKey(req) {
|
|
252
|
+
// if user provide custom method, use it
|
|
253
|
+
if (typeof this.config.getKey === 'function') {
|
|
254
|
+
const result = this.config.getKey(req);
|
|
255
|
+
// if result is undefined, normal behaviour is provided
|
|
256
|
+
if (typeof result !== 'undefined') {
|
|
257
|
+
return result;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// default key id is url with query parameters
|
|
261
|
+
return req.urlWithParams;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Return observable from cache
|
|
265
|
+
*/
|
|
266
|
+
getFromQueue(req) {
|
|
267
|
+
const key = this.getKey(req);
|
|
268
|
+
const cached = this.queue.get(key);
|
|
269
|
+
if (!cached) {
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
return cached;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Add observable to cache
|
|
276
|
+
*/
|
|
277
|
+
addToQueue(req, obs) {
|
|
278
|
+
const key = this.getKey(req);
|
|
279
|
+
this.queue.set(key, obs);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Delete observable from cache
|
|
283
|
+
*/
|
|
284
|
+
deleteFromQueue(req) {
|
|
285
|
+
const key = this.getKey(req);
|
|
286
|
+
return this.queue.delete(key);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
NgHttpCachingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingService, deps: [{ token: NG_HTTP_CACHING_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
290
|
+
NgHttpCachingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingService });
|
|
291
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingService, decorators: [{
|
|
292
|
+
type: Injectable
|
|
293
|
+
}], ctorParameters: function () {
|
|
294
|
+
return [{ type: undefined, decorators: [{
|
|
295
|
+
type: Inject,
|
|
296
|
+
args: [NG_HTTP_CACHING_CONFIG]
|
|
297
|
+
}, {
|
|
298
|
+
type: Optional
|
|
299
|
+
}] }];
|
|
300
|
+
} });
|
|
301
|
+
|
|
302
|
+
class NgHttpCachingInterceptorService {
|
|
303
|
+
// eslint-disable-next-line no-unused-vars
|
|
304
|
+
constructor(cacheService) {
|
|
305
|
+
this.cacheService = cacheService;
|
|
306
|
+
}
|
|
307
|
+
intercept(req, next) {
|
|
308
|
+
// run garbage collector
|
|
309
|
+
this.cacheService.runGc();
|
|
310
|
+
// Don't cache if it's not cacheable
|
|
311
|
+
if (!this.cacheService.isCacheable(req)) {
|
|
312
|
+
return this.sendRequest(req, next);
|
|
313
|
+
}
|
|
314
|
+
// Checked if there is pending response for this request
|
|
315
|
+
const cachedObservable = this.cacheService.getFromQueue(req);
|
|
316
|
+
if (cachedObservable) {
|
|
317
|
+
// console.log('cachedObservable', req);
|
|
318
|
+
return cachedObservable;
|
|
319
|
+
}
|
|
320
|
+
// Checked if there is cached response for this request
|
|
321
|
+
const cachedResponse = this.cacheService.getFromCache(req);
|
|
322
|
+
if (cachedResponse) {
|
|
323
|
+
// console.log('cachedResponse', req);
|
|
324
|
+
return of(cachedResponse.clone());
|
|
325
|
+
}
|
|
326
|
+
// If the request of going through for first time
|
|
327
|
+
// then let the request proceed and cache the response
|
|
328
|
+
// console.log('sendRequest', req);
|
|
329
|
+
const shared = this.sendRequest(req, next).pipe(tap(event => {
|
|
330
|
+
if (event instanceof HttpResponse) {
|
|
331
|
+
this.cacheService.addToCache(req, event.clone());
|
|
332
|
+
}
|
|
333
|
+
}), finalize(() => {
|
|
334
|
+
// delete pending request
|
|
335
|
+
this.cacheService.deleteFromQueue(req);
|
|
336
|
+
}), share());
|
|
337
|
+
// add pending request to queue for cache parallell request
|
|
338
|
+
this.cacheService.addToQueue(req, shared);
|
|
339
|
+
return shared;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Send http request (next handler)
|
|
343
|
+
*/
|
|
344
|
+
sendRequest(req, next) {
|
|
345
|
+
let cloned = req.clone();
|
|
346
|
+
// trim custom headers before send request
|
|
347
|
+
Object.values(NgHttpCachingHeaders).forEach(ngHttpCachingHeaders => {
|
|
348
|
+
if (cloned.headers.has(ngHttpCachingHeaders)) {
|
|
349
|
+
cloned = cloned.clone({ headers: cloned.headers.delete(ngHttpCachingHeaders) });
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
return next.handle(cloned);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
NgHttpCachingInterceptorService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingInterceptorService, deps: [{ token: NgHttpCachingService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
356
|
+
NgHttpCachingInterceptorService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingInterceptorService });
|
|
357
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingInterceptorService, decorators: [{
|
|
358
|
+
type: Injectable
|
|
359
|
+
}], ctorParameters: function () { return [{ type: NgHttpCachingService }]; } });
|
|
360
|
+
|
|
361
|
+
class NgHttpCachingModule {
|
|
362
|
+
static forRoot(ngHttpCachingConfig) {
|
|
363
|
+
return {
|
|
364
|
+
ngModule: NgHttpCachingModule,
|
|
365
|
+
providers: [
|
|
366
|
+
{
|
|
367
|
+
provide: NG_HTTP_CACHING_CONFIG,
|
|
368
|
+
useValue: ngHttpCachingConfig,
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
NgHttpCachingModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
375
|
+
NgHttpCachingModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingModule });
|
|
376
|
+
NgHttpCachingModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingModule, providers: [
|
|
377
|
+
NgHttpCachingService,
|
|
378
|
+
{
|
|
379
|
+
provide: HTTP_INTERCEPTORS,
|
|
380
|
+
useClass: NgHttpCachingInterceptorService,
|
|
381
|
+
multi: true,
|
|
382
|
+
},
|
|
383
|
+
], imports: [[]] });
|
|
384
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingModule, decorators: [{
|
|
385
|
+
type: NgModule,
|
|
386
|
+
args: [{
|
|
387
|
+
declarations: [],
|
|
388
|
+
imports: [],
|
|
389
|
+
providers: [
|
|
390
|
+
NgHttpCachingService,
|
|
391
|
+
{
|
|
392
|
+
provide: HTTP_INTERCEPTORS,
|
|
393
|
+
useClass: NgHttpCachingInterceptorService,
|
|
394
|
+
multi: true,
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
exports: [],
|
|
398
|
+
}]
|
|
399
|
+
}] });
|
|
400
|
+
|
|
401
|
+
/*
|
|
402
|
+
* Public API Surface of ng-http-caching
|
|
403
|
+
*/
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Generated bundle index. Do not edit.
|
|
407
|
+
*/
|
|
408
|
+
|
|
409
|
+
export { NG_HTTP_CACHING_CONFIG, NgHttpCachingConfigDefault, NgHttpCachingHeaders, NgHttpCachingInterceptorService, NgHttpCachingMemoryStorage, NgHttpCachingModule, NgHttpCachingService, NgHttpCachingStrategy };
|
|
410
|
+
//# sourceMappingURL=ng-http-caching.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ng-http-caching.mjs","sources":["../../../projects/ng-http-caching/src/lib/storage/ng-http-caching-memory-storage.ts","../../../projects/ng-http-caching/src/lib/ng-http-caching.service.ts","../../../projects/ng-http-caching/src/lib/ng-http-caching-interceptor.service.ts","../../../projects/ng-http-caching/src/lib/ng-http-caching.module.ts","../../../projects/ng-http-caching/src/public-api.ts","../../../projects/ng-http-caching/src/ng-http-caching.ts"],"sourcesContent":["import { NgHttpCachingStorageInterface } from './ng-http-caching-storage.interface';\r\nimport { NgHttpCachingEntry } from '../ng-http-caching.service';\r\n\r\nexport class NgHttpCachingMemoryStorage implements NgHttpCachingStorageInterface {\r\n\r\n get size(): number {\r\n return this.store.size;\r\n }\r\n\r\n private store = new Map<string, NgHttpCachingEntry>();\r\n\r\n clear(): void {\r\n this.store.clear();\r\n }\r\n\r\n delete(key: string): boolean {\r\n return this.store.delete(key);\r\n }\r\n\r\n // eslint-disable-next-line no-unused-vars\r\n forEach(callbackfn: (value: NgHttpCachingEntry, key: string) => void): void {\r\n return this.store.forEach(callbackfn);\r\n }\r\n\r\n get(key: string): NgHttpCachingEntry | undefined {\r\n return this.store.get(key);\r\n }\r\n\r\n has(key: string): boolean {\r\n return this.store.has(key);\r\n }\r\n\r\n set(key: string, value: NgHttpCachingEntry): void {\r\n this.store.set(key, value);\r\n }\r\n}\r\n","import { Injectable, InjectionToken, Inject, Optional } from '@angular/core';\r\nimport { HttpRequest, HttpResponse, HttpEvent } from '@angular/common/http';\r\nimport { Observable } from 'rxjs/internal/Observable';\r\nimport { NgHttpCachingStorageInterface } from './storage/ng-http-caching-storage.interface';\r\nimport { NgHttpCachingMemoryStorage } from './storage/ng-http-caching-memory-storage';\r\n\r\nexport interface NgHttpCachingEntry {\r\n url: string;\r\n response: HttpResponse<any>;\r\n request: HttpRequest<any>;\r\n addedTime: number;\r\n}\r\n\r\nexport const NG_HTTP_CACHING_CONFIG = new InjectionToken<NgHttpCachingConfig>(\r\n 'ng-http-caching.config'\r\n);\r\n\r\nexport enum NgHttpCachingStrategy {\r\n // eslint-disable-next-line no-unused-vars\r\n ALLOW_ALL = 'ALLOW_ALL',\r\n // eslint-disable-next-line no-unused-vars\r\n DISALLOW_ALL = 'DISALLOW_ALL',\r\n}\r\n\r\nexport enum NgHttpCachingHeaders {\r\n // eslint-disable-next-line no-unused-vars\r\n ALLOW_CACHE = 'X-NG-HTTP-CACHING-ALLOW-CACHE',\r\n // eslint-disable-next-line no-unused-vars\r\n DISALLOW_CACHE = 'X-NG-HTTP-CACHING-DISALLOW-CACHE',\r\n // eslint-disable-next-line no-unused-vars\r\n LIFETIME = 'X-NG-HTTP-CACHING-LIFETIME',\r\n // eslint-disable-next-line no-unused-vars\r\n TAG = 'X-NG-HTTP-CACHING-TAG',\r\n}\r\nexport interface NgHttpCachingConfig {\r\n store?: NgHttpCachingStorageInterface;\r\n lifetime?: number;\r\n allowedMethod?: string[];\r\n cacheStrategy?: NgHttpCachingStrategy;\r\n // eslint-disable-next-line no-unused-vars\r\n isExpired?: (entry: NgHttpCachingEntry) => boolean | undefined;\r\n // eslint-disable-next-line no-unused-vars\r\n isCacheable?: (req: HttpRequest<any>) => boolean | undefined;\r\n // eslint-disable-next-line no-unused-vars\r\n getKey?: (req: HttpRequest<any>) => string | undefined;\r\n // eslint-disable-next-line no-unused-vars\r\n isValid?: (entry: NgHttpCachingEntry) => boolean | undefined;\r\n}\r\n\r\nexport const NgHttpCachingConfigDefault: NgHttpCachingConfig = {\r\n store: new NgHttpCachingMemoryStorage(),\r\n lifetime: 60 * 60 * 100,\r\n allowedMethod: ['GET'],\r\n cacheStrategy: NgHttpCachingStrategy.ALLOW_ALL,\r\n};\r\n\r\n@Injectable()\r\nexport class NgHttpCachingService {\r\n\r\n private queue = new Map<string, Observable<HttpEvent<any>>>();\r\n\r\n private config: NgHttpCachingConfig = NgHttpCachingConfigDefault;\r\n\r\n constructor(\r\n @Inject(NG_HTTP_CACHING_CONFIG) @Optional() config: NgHttpCachingConfig\r\n ) {\r\n if (config) {\r\n this.config = { ...NgHttpCachingConfigDefault, ...config };\r\n }\r\n }\r\n\r\n /**\r\n * Return the config\r\n */\r\n getConfig(): NgHttpCachingConfig {\r\n return this.config;\r\n }\r\n\r\n /**\r\n * Return the queue map\r\n */\r\n getQueue(): Map<string, Observable<HttpEvent<any>>> {\r\n return this.queue;\r\n }\r\n\r\n /**\r\n * Return the cache store\r\n */\r\n getStore(): NgHttpCachingStorageInterface {\r\n return this.config.store as NgHttpCachingStorageInterface;\r\n }\r\n\r\n /**\r\n * Return response from cache\r\n */\r\n getFromCache(req: HttpRequest<any>): HttpResponse<any> | undefined {\r\n const key: string = this.getKey(req);\r\n const cached: NgHttpCachingEntry | undefined = this.config.store?.get(key);\r\n\r\n if (!cached) {\r\n return undefined;\r\n }\r\n\r\n if (this.isExpired(cached)) {\r\n this.clearCacheByKey(key);\r\n return undefined;\r\n }\r\n\r\n return cached.response;\r\n }\r\n\r\n /**\r\n * Add response to cache\r\n */\r\n addToCache(req: HttpRequest<any>, res: HttpResponse<any>): boolean {\r\n const key: string = this.getKey(req);\r\n const entry: NgHttpCachingEntry = {\r\n url: req.urlWithParams,\r\n response: res,\r\n request: req,\r\n addedTime: Date.now(),\r\n };\r\n if (this.isValid(entry)) {\r\n this.config.store?.set(key, entry);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Delete response from cache\r\n */\r\n deleteFromCache(req: HttpRequest<any>): boolean {\r\n const key: string = this.getKey(req);\r\n return this.clearCacheByKey(key);\r\n }\r\n\r\n /**\r\n * Clear the cache\r\n */\r\n clearCache(): void {\r\n this.config.store?.clear();\r\n }\r\n\r\n /**\r\n * Clear the cache by key\r\n */\r\n clearCacheByKey(key: string): boolean {\r\n return (this.config.store as NgHttpCachingStorageInterface).delete(key);\r\n }\r\n\r\n /**\r\n * Clear the cache by regex\r\n */\r\n clearCacheByRegex(regex: RegExp): void {\r\n (this.config.store as NgHttpCachingStorageInterface).forEach((entry: NgHttpCachingEntry, key: string) => {\r\n if (regex.test(key)) {\r\n this.clearCacheByKey(key);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Clear the cache by TAG\r\n */\r\n clearCacheByTag(tag: string): void {\r\n (this.config.store as NgHttpCachingStorageInterface).forEach((entry: NgHttpCachingEntry, key: string) => {\r\n const tagHeader = entry.request.headers.get(NgHttpCachingHeaders.TAG);\r\n if (tagHeader && tagHeader.split(',').includes(tag)) {\r\n this.clearCacheByKey(key);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Run garbage collector (delete expired cache entry)\r\n */\r\n runGc(): void {\r\n (this.config.store as NgHttpCachingStorageInterface).forEach((entry: NgHttpCachingEntry, key: string) => {\r\n if (this.isExpired(entry)) {\r\n this.clearCacheByKey(key);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Return true if cache entry is expired\r\n */\r\n isExpired(entry: NgHttpCachingEntry): boolean {\r\n // if user provide custom method, use it\r\n if (typeof this.config.isExpired === 'function') {\r\n const result = this.config.isExpired(entry);\r\n // if result is undefined, normal behaviour is provided\r\n if (typeof result !== 'undefined') {\r\n return result;\r\n }\r\n }\r\n // config/default lifetime\r\n let lifetime = this.config.lifetime;\r\n // request has own lifetime\r\n if (entry.request.headers.has(NgHttpCachingHeaders.LIFETIME)) {\r\n lifetime = +(entry.request.headers.get(NgHttpCachingHeaders.LIFETIME) || '');\r\n }\r\n // never expire if 0\r\n if (lifetime === 0) {\r\n return false;\r\n }\r\n // wrong lifetime\r\n if ((lifetime as number) < 0) {\r\n throw new Error('lifetime must be greater than or equal 0');\r\n }\r\n return entry.addedTime + (lifetime as number) < Date.now();\r\n }\r\n\r\n /**\r\n * Return true if cache entry is valid for store in the cache\r\n */\r\n isValid(entry: NgHttpCachingEntry): boolean {\r\n // if user provide custom method, use it\r\n if (typeof this.config.isValid === 'function') {\r\n const result = this.config.isValid(entry);\r\n // if result is undefined, normal behaviour is provided\r\n if (typeof result !== 'undefined') {\r\n return result;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Return true if the request is cacheable\r\n */\r\n isCacheable(req: HttpRequest<any>): boolean {\r\n // if user provide custom method, use it\r\n if (typeof this.config.isCacheable === 'function') {\r\n const result = this.config.isCacheable(req);\r\n // if result is undefined, normal behaviour is provided\r\n if (typeof result !== 'undefined') {\r\n return result;\r\n }\r\n }\r\n // request has disallow cache header\r\n if (req.headers.has(NgHttpCachingHeaders.DISALLOW_CACHE)) {\r\n return false;\r\n }\r\n // strategy is disallow all...\r\n if (this.config.cacheStrategy === NgHttpCachingStrategy.DISALLOW_ALL) {\r\n // request isn't allowed if come without allow header\r\n if (!req.headers.has(NgHttpCachingHeaders.ALLOW_CACHE)) {\r\n return false;\r\n }\r\n }\r\n // if allowed method is only ALL, allow all http methos\r\n if (this.config.allowedMethod) {\r\n if (this.config.allowedMethod.length === 1) {\r\n if (this.config.allowedMethod[0] === 'ALL') {\r\n return true;\r\n }\r\n }\r\n // request is allowed if method is in allowedMethod\r\n return this.config.allowedMethod.indexOf(req.method) !== -1;\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Return the cache key\r\n */\r\n getKey(req: HttpRequest<any>): string {\r\n // if user provide custom method, use it\r\n if (typeof this.config.getKey === 'function') {\r\n const result = this.config.getKey(req);\r\n // if result is undefined, normal behaviour is provided\r\n if (typeof result !== 'undefined') {\r\n return result;\r\n }\r\n }\r\n // default key id is url with query parameters\r\n return req.urlWithParams;\r\n }\r\n\r\n /**\r\n * Return observable from cache\r\n */\r\n getFromQueue(req: HttpRequest<any>): Observable<HttpEvent<any>> | undefined {\r\n const key: string = this.getKey(req);\r\n const cached: Observable<HttpEvent<any>> | undefined = this.queue.get(key);\r\n\r\n if (!cached) {\r\n return undefined;\r\n }\r\n\r\n return cached;\r\n }\r\n\r\n /**\r\n * Add observable to cache\r\n */\r\n addToQueue(req: HttpRequest<any>, obs: Observable<HttpEvent<any>>): void {\r\n const key: string = this.getKey(req);\r\n this.queue.set(key, obs);\r\n }\r\n\r\n /**\r\n * Delete observable from cache\r\n */\r\n deleteFromQueue(req: HttpRequest<any>): boolean {\r\n const key: string = this.getKey(req);\r\n return this.queue.delete(key);\r\n }\r\n}\r\n","import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { Observable, of } from 'rxjs';\nimport { tap, finalize, share } from 'rxjs/operators';\nimport { NgHttpCachingService, NgHttpCachingHeaders } from './ng-http-caching.service';\n\n\n@Injectable()\nexport class NgHttpCachingInterceptorService implements HttpInterceptor {\n\n // eslint-disable-next-line no-unused-vars\n constructor(private readonly cacheService: NgHttpCachingService) {}\n\n intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\n // run garbage collector\n this.cacheService.runGc();\n\n // Don't cache if it's not cacheable\n if ( !this.cacheService.isCacheable(req) ) {\n return this.sendRequest(req, next);\n }\n\n // Checked if there is pending response for this request\n const cachedObservable: Observable<HttpEvent<any>> | undefined = this.cacheService.getFromQueue(req);\n if ( cachedObservable ) {\n // console.log('cachedObservable', req);\n return cachedObservable;\n }\n\n // Checked if there is cached response for this request\n const cachedResponse: HttpResponse<any> | undefined = this.cacheService.getFromCache(req);\n if (cachedResponse) {\n // console.log('cachedResponse', req);\n return of(cachedResponse.clone());\n }\n\n // If the request of going through for first time\n // then let the request proceed and cache the response\n // console.log('sendRequest', req);\n const shared = this.sendRequest(req, next).pipe(\n tap(event => {\n if (event instanceof HttpResponse) {\n this.cacheService.addToCache(req, event.clone());\n }\n }),\n finalize(() => {\n // delete pending request\n this.cacheService.deleteFromQueue(req);\n }),\n share()\n );\n\n // add pending request to queue for cache parallell request\n this.cacheService.addToQueue(req, shared);\n\n return shared;\n }\n\n /**\n * Send http request (next handler)\n */\n sendRequest(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\n let cloned: HttpRequest<any> = req.clone();\n // trim custom headers before send request\n Object.values(NgHttpCachingHeaders).forEach(ngHttpCachingHeaders => {\n if ( cloned.headers.has(ngHttpCachingHeaders) ) {\n cloned = cloned.clone({ headers: cloned.headers.delete(ngHttpCachingHeaders) });\n }\n });\n return next.handle(cloned);\n }\n}\n","import { NgModule, ModuleWithProviders } from '@angular/core';\r\nimport { HTTP_INTERCEPTORS } from '@angular/common/http';\r\nimport {\r\n NG_HTTP_CACHING_CONFIG,\r\n NgHttpCachingConfig,\r\n NgHttpCachingService,\r\n} from './ng-http-caching.service';\r\nimport { NgHttpCachingInterceptorService } from './ng-http-caching-interceptor.service';\r\n\r\n@NgModule({\r\n declarations: [],\r\n imports: [],\r\n providers: [\r\n NgHttpCachingService,\r\n {\r\n provide: HTTP_INTERCEPTORS,\r\n useClass: NgHttpCachingInterceptorService,\r\n multi: true,\r\n },\r\n ],\r\n exports: [],\r\n})\r\nexport class NgHttpCachingModule {\r\n static forRoot(\r\n ngHttpCachingConfig?: NgHttpCachingConfig\r\n ): ModuleWithProviders<NgHttpCachingModule> {\r\n return {\r\n ngModule: NgHttpCachingModule,\r\n providers: [\r\n {\r\n provide: NG_HTTP_CACHING_CONFIG,\r\n useValue: ngHttpCachingConfig,\r\n },\r\n ],\r\n };\r\n }\r\n}\r\n","/*\r\n * Public API Surface of ng-http-caching\r\n */\r\n\r\nexport * from './lib/ng-http-caching-interceptor.service';\r\nexport * from './lib/ng-http-caching.service';\r\nexport * from './lib/ng-http-caching.module';\r\nexport * from './lib/storage/ng-http-caching-storage.interface';\r\nexport * from './lib/storage/ng-http-caching-memory-storage';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,7 @@ class NgHttpCachingMemoryStorage {
|
|
|
17
17
|
delete(key) {
|
|
18
18
|
return this.store.delete(key);
|
|
19
19
|
}
|
|
20
|
+
// eslint-disable-next-line no-unused-vars
|
|
20
21
|
forEach(callbackfn) {
|
|
21
22
|
return this.store.forEach(callbackfn);
|
|
22
23
|
}
|
|
@@ -34,18 +35,22 @@ class NgHttpCachingMemoryStorage {
|
|
|
34
35
|
const NG_HTTP_CACHING_CONFIG = new InjectionToken('ng-http-caching.config');
|
|
35
36
|
var NgHttpCachingStrategy;
|
|
36
37
|
(function (NgHttpCachingStrategy) {
|
|
38
|
+
// eslint-disable-next-line no-unused-vars
|
|
37
39
|
NgHttpCachingStrategy["ALLOW_ALL"] = "ALLOW_ALL";
|
|
40
|
+
// eslint-disable-next-line no-unused-vars
|
|
38
41
|
NgHttpCachingStrategy["DISALLOW_ALL"] = "DISALLOW_ALL";
|
|
39
42
|
})(NgHttpCachingStrategy || (NgHttpCachingStrategy = {}));
|
|
40
43
|
var NgHttpCachingHeaders;
|
|
41
44
|
(function (NgHttpCachingHeaders) {
|
|
45
|
+
// eslint-disable-next-line no-unused-vars
|
|
42
46
|
NgHttpCachingHeaders["ALLOW_CACHE"] = "X-NG-HTTP-CACHING-ALLOW-CACHE";
|
|
47
|
+
// eslint-disable-next-line no-unused-vars
|
|
43
48
|
NgHttpCachingHeaders["DISALLOW_CACHE"] = "X-NG-HTTP-CACHING-DISALLOW-CACHE";
|
|
49
|
+
// eslint-disable-next-line no-unused-vars
|
|
44
50
|
NgHttpCachingHeaders["LIFETIME"] = "X-NG-HTTP-CACHING-LIFETIME";
|
|
51
|
+
// eslint-disable-next-line no-unused-vars
|
|
45
52
|
NgHttpCachingHeaders["TAG"] = "X-NG-HTTP-CACHING-TAG";
|
|
46
53
|
})(NgHttpCachingHeaders || (NgHttpCachingHeaders = {}));
|
|
47
|
-
class NgHttpCachingConfig {
|
|
48
|
-
}
|
|
49
54
|
const NgHttpCachingConfigDefault = {
|
|
50
55
|
store: new NgHttpCachingMemoryStorage(),
|
|
51
56
|
lifetime: 60 * 60 * 100,
|
|
@@ -55,11 +60,9 @@ const NgHttpCachingConfigDefault = {
|
|
|
55
60
|
class NgHttpCachingService {
|
|
56
61
|
constructor(config) {
|
|
57
62
|
this.queue = new Map();
|
|
63
|
+
this.config = NgHttpCachingConfigDefault;
|
|
58
64
|
if (config) {
|
|
59
|
-
this.config =
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
this.config = NgHttpCachingConfigDefault;
|
|
65
|
+
this.config = { ...NgHttpCachingConfigDefault, ...config };
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
/**
|
|
@@ -85,7 +88,7 @@ class NgHttpCachingService {
|
|
|
85
88
|
*/
|
|
86
89
|
getFromCache(req) {
|
|
87
90
|
const key = this.getKey(req);
|
|
88
|
-
const cached = this.config.store
|
|
91
|
+
const cached = this.config.store?.get(key);
|
|
89
92
|
if (!cached) {
|
|
90
93
|
return undefined;
|
|
91
94
|
}
|
|
@@ -107,7 +110,7 @@ class NgHttpCachingService {
|
|
|
107
110
|
addedTime: Date.now(),
|
|
108
111
|
};
|
|
109
112
|
if (this.isValid(entry)) {
|
|
110
|
-
this.config.store
|
|
113
|
+
this.config.store?.set(key, entry);
|
|
111
114
|
return true;
|
|
112
115
|
}
|
|
113
116
|
return false;
|
|
@@ -123,7 +126,7 @@ class NgHttpCachingService {
|
|
|
123
126
|
* Clear the cache
|
|
124
127
|
*/
|
|
125
128
|
clearCache() {
|
|
126
|
-
this.config.store
|
|
129
|
+
this.config.store?.clear();
|
|
127
130
|
}
|
|
128
131
|
/**
|
|
129
132
|
* Clear the cache by key
|
|
@@ -178,7 +181,7 @@ class NgHttpCachingService {
|
|
|
178
181
|
let lifetime = this.config.lifetime;
|
|
179
182
|
// request has own lifetime
|
|
180
183
|
if (entry.request.headers.has(NgHttpCachingHeaders.LIFETIME)) {
|
|
181
|
-
lifetime = +entry.request.headers.get(NgHttpCachingHeaders.LIFETIME);
|
|
184
|
+
lifetime = +(entry.request.headers.get(NgHttpCachingHeaders.LIFETIME) || '');
|
|
182
185
|
}
|
|
183
186
|
// never expire if 0
|
|
184
187
|
if (lifetime === 0) {
|
|
@@ -228,13 +231,16 @@ class NgHttpCachingService {
|
|
|
228
231
|
}
|
|
229
232
|
}
|
|
230
233
|
// if allowed method is only ALL, allow all http methos
|
|
231
|
-
if (this.config.allowedMethod
|
|
232
|
-
if (this.config.allowedMethod
|
|
233
|
-
|
|
234
|
+
if (this.config.allowedMethod) {
|
|
235
|
+
if (this.config.allowedMethod.length === 1) {
|
|
236
|
+
if (this.config.allowedMethod[0] === 'ALL') {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
234
239
|
}
|
|
240
|
+
// request is allowed if method is in allowedMethod
|
|
241
|
+
return this.config.allowedMethod.indexOf(req.method) !== -1;
|
|
235
242
|
}
|
|
236
|
-
|
|
237
|
-
return this.config.allowedMethod.indexOf(req.method) !== -1;
|
|
243
|
+
return true;
|
|
238
244
|
}
|
|
239
245
|
/**
|
|
240
246
|
* Return the cache key
|
|
@@ -277,18 +283,19 @@ class NgHttpCachingService {
|
|
|
277
283
|
return this.queue.delete(key);
|
|
278
284
|
}
|
|
279
285
|
}
|
|
280
|
-
NgHttpCachingService.ɵfac =
|
|
281
|
-
NgHttpCachingService.ɵprov =
|
|
282
|
-
(
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
286
|
+
NgHttpCachingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingService, deps: [{ token: NG_HTTP_CACHING_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
287
|
+
NgHttpCachingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingService });
|
|
288
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingService, decorators: [{
|
|
289
|
+
type: Injectable
|
|
290
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
291
|
+
type: Inject,
|
|
292
|
+
args: [NG_HTTP_CACHING_CONFIG]
|
|
293
|
+
}, {
|
|
294
|
+
type: Optional
|
|
295
|
+
}] }]; } });
|
|
290
296
|
|
|
291
297
|
class NgHttpCachingInterceptorService {
|
|
298
|
+
// eslint-disable-next-line no-unused-vars
|
|
292
299
|
constructor(cacheService) {
|
|
293
300
|
this.cacheService = cacheService;
|
|
294
301
|
}
|
|
@@ -340,11 +347,11 @@ class NgHttpCachingInterceptorService {
|
|
|
340
347
|
return next.handle(cloned);
|
|
341
348
|
}
|
|
342
349
|
}
|
|
343
|
-
NgHttpCachingInterceptorService.ɵfac =
|
|
344
|
-
NgHttpCachingInterceptorService.ɵprov =
|
|
345
|
-
(
|
|
346
|
-
|
|
347
|
-
|
|
350
|
+
NgHttpCachingInterceptorService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingInterceptorService, deps: [{ token: NgHttpCachingService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
351
|
+
NgHttpCachingInterceptorService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingInterceptorService });
|
|
352
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingInterceptorService, decorators: [{
|
|
353
|
+
type: Injectable
|
|
354
|
+
}], ctorParameters: function () { return [{ type: NgHttpCachingService }]; } });
|
|
348
355
|
|
|
349
356
|
class NgHttpCachingModule {
|
|
350
357
|
static forRoot(ngHttpCachingConfig) {
|
|
@@ -359,9 +366,9 @@ class NgHttpCachingModule {
|
|
|
359
366
|
};
|
|
360
367
|
}
|
|
361
368
|
}
|
|
362
|
-
NgHttpCachingModule.ɵfac =
|
|
363
|
-
NgHttpCachingModule.ɵmod =
|
|
364
|
-
NgHttpCachingModule.ɵinj =
|
|
369
|
+
NgHttpCachingModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
370
|
+
NgHttpCachingModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingModule });
|
|
371
|
+
NgHttpCachingModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingModule, providers: [
|
|
365
372
|
NgHttpCachingService,
|
|
366
373
|
{
|
|
367
374
|
provide: HTTP_INTERCEPTORS,
|
|
@@ -369,22 +376,22 @@ NgHttpCachingModule.ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ providers: [
|
|
|
369
376
|
multi: true,
|
|
370
377
|
},
|
|
371
378
|
], imports: [[]] });
|
|
372
|
-
(
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
379
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.3", ngImport: i0, type: NgHttpCachingModule, decorators: [{
|
|
380
|
+
type: NgModule,
|
|
381
|
+
args: [{
|
|
382
|
+
declarations: [],
|
|
383
|
+
imports: [],
|
|
384
|
+
providers: [
|
|
385
|
+
NgHttpCachingService,
|
|
386
|
+
{
|
|
387
|
+
provide: HTTP_INTERCEPTORS,
|
|
388
|
+
useClass: NgHttpCachingInterceptorService,
|
|
389
|
+
multi: true,
|
|
390
|
+
},
|
|
391
|
+
],
|
|
392
|
+
exports: [],
|
|
393
|
+
}]
|
|
394
|
+
}] });
|
|
388
395
|
|
|
389
396
|
/*
|
|
390
397
|
* Public API Surface of ng-http-caching
|
|
@@ -394,5 +401,5 @@ NgHttpCachingModule.ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ providers: [
|
|
|
394
401
|
* Generated bundle index. Do not edit.
|
|
395
402
|
*/
|
|
396
403
|
|
|
397
|
-
export { NG_HTTP_CACHING_CONFIG,
|
|
398
|
-
//# sourceMappingURL=ng-http-caching.
|
|
404
|
+
export { NG_HTTP_CACHING_CONFIG, NgHttpCachingConfigDefault, NgHttpCachingHeaders, NgHttpCachingInterceptorService, NgHttpCachingMemoryStorage, NgHttpCachingModule, NgHttpCachingService, NgHttpCachingStrategy };
|
|
405
|
+
//# sourceMappingURL=ng-http-caching.mjs.map
|