@kovalenko/http-request-cache 1.1.0 → 1.2.0
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/CHANGELOG.md +7 -0
- package/README.md +71 -0
- package/esm2020/lib/http-cache-options.mjs +1 -1
- package/esm2020/lib/http-request-cache.decorator.mjs +30 -4
- package/esm2020/lib/request-times.mjs +15 -0
- package/fesm2015/kovalenko-http-request-cache.mjs +47 -7
- package/fesm2015/kovalenko-http-request-cache.mjs.map +1 -1
- package/fesm2020/kovalenko-http-request-cache.mjs +43 -3
- package/fesm2020/kovalenko-http-request-cache.mjs.map +1 -1
- package/lib/http-cache-options.d.ts +1 -0
- package/lib/request-times.d.ts +8 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [1.2.0](https://github.com/menelai/http-request-cache/compare/v1.1.0...v1.2.0) (2022-06-27)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* TTL option for cache ([#25](https://github.com/menelai/http-request-cache/issues/25)) ([7163fc9](https://github.com/menelai/http-request-cache/commit/7163fc9da90ba3c2d07d675330adca959884e08c))
|
|
7
|
+
|
|
1
8
|
# [1.1.0](https://github.com/menelai/http-request-cache/compare/v1.0.0...v1.1.0) (2022-06-27)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -22,6 +22,7 @@ npm install @kovalenko/http-request-cache
|
|
|
22
22
|
interface HttpCacheOptions {
|
|
23
23
|
refCount?: boolean; // If `refCount` is true, the source will be unsubscribed from once the reference count drops to zero
|
|
24
24
|
windowTime?: number; // Maximum time length of the replay buffer in milliseconds
|
|
25
|
+
ttl?: number; // cache time to live before it will be refreshed. Unlike refreshOn: interval(1000), ttl will not refresh automatically
|
|
25
26
|
storage?: HttpCacheStorage; // if none specified, the default cache object will be used
|
|
26
27
|
refreshOn?: Observable<unknown> | Subject<unknown> | BehaviorSubject<unknown>; // refresh trigger
|
|
27
28
|
}
|
|
@@ -105,6 +106,76 @@ export class DataService {
|
|
|
105
106
|
}
|
|
106
107
|
```
|
|
107
108
|
|
|
109
|
+
### TTL
|
|
110
|
+
|
|
111
|
+
When someone subscribes list() method after TTL period, every subscription is being refreshed
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
@Injectable()
|
|
115
|
+
export class DataService {
|
|
116
|
+
constructor(private http: HttpClient) { }
|
|
117
|
+
|
|
118
|
+
@HttpRequestCache(() => ({
|
|
119
|
+
ttl: 5000
|
|
120
|
+
}))
|
|
121
|
+
list(): Observable<any> {
|
|
122
|
+
return this.http.get('assets/angular.json');
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@Component({
|
|
128
|
+
selector: 'app-root',
|
|
129
|
+
templateUrl: './app.component.html',
|
|
130
|
+
styleUrls: ['./app.component.scss'],
|
|
131
|
+
})
|
|
132
|
+
export class AppComponent implements OnInit {
|
|
133
|
+
|
|
134
|
+
constructor(
|
|
135
|
+
private http: HttpClient,
|
|
136
|
+
private dataService: DataService
|
|
137
|
+
) { }
|
|
138
|
+
|
|
139
|
+
ngOnInit(): void {
|
|
140
|
+
this.dataService.list().subscribe(g => {
|
|
141
|
+
console.log('1', g);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// outputs:
|
|
145
|
+
// 1 {...}
|
|
146
|
+
|
|
147
|
+
setTimeout(() => {
|
|
148
|
+
this.dataService.list().subscribe(g => {
|
|
149
|
+
console.log('2', g);
|
|
150
|
+
});
|
|
151
|
+
}, 1000);
|
|
152
|
+
|
|
153
|
+
// outputs:
|
|
154
|
+
// 2 {...}
|
|
155
|
+
|
|
156
|
+
setTimeout(() => {
|
|
157
|
+
this.dataService.list().subscribe(g => {
|
|
158
|
+
console.log('3', g);
|
|
159
|
+
});
|
|
160
|
+
}, 6000);
|
|
161
|
+
|
|
162
|
+
// outputs:
|
|
163
|
+
// 1 {...}
|
|
164
|
+
// 2 {...}
|
|
165
|
+
// 3 {...}
|
|
166
|
+
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
this.dataService.list().subscribe(g => {
|
|
169
|
+
console.log('4', g);
|
|
170
|
+
});
|
|
171
|
+
}, 8000);
|
|
172
|
+
|
|
173
|
+
// outputs:
|
|
174
|
+
// 4 {...}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
108
179
|
### If cache invalidation is not necessary
|
|
109
180
|
```typescript
|
|
110
181
|
@Injectable()
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC1jYWNoZS1vcHRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvaHR0cC1yZXF1ZXN0LWNhY2hlL3NyYy9saWIvaHR0cC1jYWNoZS1vcHRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgU3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge0h0dHBDYWNoZVN0b3JhZ2V9IGZyb20gJy4vaHR0cC1jYWNoZS1zdG9yYWdlJztcblxuZXhwb3J0IGludGVyZmFjZSBIdHRwQ2FjaGVPcHRpb25zIHtcbiAgcmVmQ291bnQ/
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC1jYWNoZS1vcHRpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvaHR0cC1yZXF1ZXN0LWNhY2hlL3NyYy9saWIvaHR0cC1jYWNoZS1vcHRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0JlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgU3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge0h0dHBDYWNoZVN0b3JhZ2V9IGZyb20gJy4vaHR0cC1jYWNoZS1zdG9yYWdlJztcblxuZXhwb3J0IGludGVyZmFjZSBIdHRwQ2FjaGVPcHRpb25zIHtcbiAgcmVmQ291bnQ/OiBib29sZWFuO1xuICB3aW5kb3dUaW1lPzogbnVtYmVyO1xuICB0dGw/OiBudW1iZXI7XG4gIHN0b3JhZ2U/OiBIdHRwQ2FjaGVTdG9yYWdlO1xuICByZWZyZXNoT24/OiBPYnNlcnZhYmxlPHVua25vd24+IHwgU3ViamVjdDx1bmtub3duPiB8IEJlaGF2aW9yU3ViamVjdDx1bmtub3duPjtcbn1cbiJdfQ==
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { NEVER } from 'rxjs';
|
|
1
|
+
import { filter, merge, NEVER, Subject, tap } from 'rxjs';
|
|
2
2
|
import { shareReplay, startWith, switchMap } from 'rxjs/operators';
|
|
3
3
|
import { DefaultStorage } from './default-storage';
|
|
4
|
+
import { RequestTimes } from './request-times';
|
|
4
5
|
export const HttpRequestCache = (optionsHandler) => {
|
|
5
6
|
return (target, methodName, descriptor) => {
|
|
6
7
|
if (!(descriptor?.value instanceof Function)) {
|
|
@@ -9,19 +10,44 @@ export const HttpRequestCache = (optionsHandler) => {
|
|
|
9
10
|
const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;
|
|
10
11
|
const originalMethod = descriptor.value;
|
|
11
12
|
descriptor.value = function (...args) {
|
|
13
|
+
var _a;
|
|
12
14
|
const options = optionsHandler?.call(this, this, ...args);
|
|
13
15
|
if (!options?.storage && !target._____storage_____) {
|
|
14
16
|
target._____storage_____ = new DefaultStorage();
|
|
15
17
|
}
|
|
18
|
+
if (options?.ttl && !target._____ttl_storage_____) {
|
|
19
|
+
target._____ttl_storage_____ = new RequestTimes();
|
|
20
|
+
}
|
|
16
21
|
const storage = options?.storage ?? target._____storage_____;
|
|
17
|
-
const refreshOn = options?.refreshOn ?? NEVER;
|
|
18
22
|
const key = `${cacheKeyPrefix}_${JSON.stringify(args)}`;
|
|
23
|
+
(_a = target)._____working_____ ?? (_a._____working_____ = {});
|
|
24
|
+
let ttl = undefined;
|
|
25
|
+
if (options?.ttl) {
|
|
26
|
+
ttl = target._____ttl_storage_____.getItem(key);
|
|
27
|
+
if (!ttl) {
|
|
28
|
+
ttl = {
|
|
29
|
+
requestTime: Date.now(),
|
|
30
|
+
subject: new Subject(),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
else if (ttl.requestTime + options.ttl <= Date.now()) {
|
|
34
|
+
target._____working_____[key] = true;
|
|
35
|
+
ttl.requestTime = Date.now();
|
|
36
|
+
ttl.subject.next();
|
|
37
|
+
}
|
|
38
|
+
target._____ttl_storage_____.setItem(key, ttl);
|
|
39
|
+
}
|
|
40
|
+
const refreshOn = merge(options?.refreshOn ?? NEVER, ttl?.subject ?? NEVER);
|
|
19
41
|
let observable = storage.getItem(key);
|
|
20
42
|
if (!observable) {
|
|
21
|
-
observable = refreshOn.pipe(startWith(true), switchMap(() => originalMethod.apply(this, [...args])),
|
|
43
|
+
observable = refreshOn.pipe(startWith(true), switchMap(() => originalMethod.apply(this, [...args])), tap(() => {
|
|
44
|
+
delete target._____working_____[key];
|
|
45
|
+
}), shareReplay({
|
|
22
46
|
bufferSize: 1,
|
|
23
47
|
refCount: options?.refCount ?? false,
|
|
24
48
|
windowTime: options?.windowTime ?? Infinity,
|
|
49
|
+
}), filter(() => {
|
|
50
|
+
return !target._____working_____[key];
|
|
25
51
|
}));
|
|
26
52
|
storage.setItem(key, observable);
|
|
27
53
|
}
|
|
@@ -30,4 +56,4 @@ export const HttpRequestCache = (optionsHandler) => {
|
|
|
30
56
|
return descriptor;
|
|
31
57
|
};
|
|
32
58
|
};
|
|
33
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC1yZXF1ZXN0LWNhY2hlLmRlY29yYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2h0dHAtcmVxdWVzdC1jYWNoZS9zcmMvbGliL2h0dHAtcmVxdWVzdC1jYWNoZS5kZWNvcmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFjLE9BQU8sRUFBRSxHQUFHLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDcEUsT0FBTyxFQUFDLFdBQVcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDakUsT0FBTyxFQUFDLGNBQWMsRUFBQyxNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUk3QyxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxDQUFnQyxjQUE2RCxFQUFFLEVBQUU7SUFDL0gsT0FBTyxDQUFDLE1BQVMsRUFBRSxVQUFrQixFQUFFLFVBQTJELEVBQW1ELEVBQUU7UUFDckosSUFBSSxDQUFDLENBQUMsVUFBVSxFQUFFLEtBQUssWUFBWSxRQUFRLENBQUMsRUFBRTtZQUM1QyxNQUFNLEtBQUssQ0FBQyx5RkFBeUYsQ0FBQyxDQUFDO1NBQ3hHO1FBRUQsTUFBTSxjQUFjLEdBQUcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUNsRSxNQUFNLGNBQWMsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBRXhDLFVBQVUsQ0FBQyxLQUFLLEdBQUcsVUFBUyxHQUFHLElBQVc7O1lBQ3hDLE1BQU0sT0FBTyxHQUFHLGNBQWMsRUFBRSxJQUFJLENBQUMsSUFBUyxFQUFFLElBQVMsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO1lBRXBFLElBQUksQ0FBQyxPQUFPLEVBQUUsT0FBTyxJQUFJLENBQUUs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aGUtb3B0aW9ucyc7XG5pbXBvcnQge2ZpbHRlciwgbWVyZ2UsIE5FVkVSLCBPYnNlcnZhYmxlLCBTdWJqZWN0LCB0YXB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtzaGFyZVJlcGxheSwgc3RhcnRXaXRoLCBzd2l0Y2hNYXB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7RGVmYXVsdFN0b3JhZ2V9IGZyb20gJy4vZGVmYXVsdC1zdG9yYWdlJztcbmltcG9ydCB7UmVxdWVzdFRpbWVzfSBmcm9tICcuL3JlcXVlc3QtdGltZXMnO1xuXG50eXBlIEh0dHBSZXF1ZXN0Q2FjaGVNZXRob2QgPSAoLi4uYXJnczogYW55W10pID0+IE9ic2VydmFibGU8YW55PjtcblxuZXhwb3J0IGNvbnN0IEh0dHBSZXF1ZXN0Q2FjaGUgPSA8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4+KG9wdGlvbnNIYW5kbGVyPzogKG9iajogVCwgLi4uYXJnczogYW55W10pID0+IEh0dHBDYWNoZU9wdGlvbnMpID0+IHtcbiAgcmV0dXJuICh0YXJnZXQ6IFQsIG1ldGhvZE5hbWU6IHN0cmluZywgZGVzY3JpcHRvcjogVHlwZWRQcm9wZXJ0eURlc2NyaXB0b3I8SHR0cFJlcXVlc3RDYWNoZU1ldGhvZD4pOiBUeXBlZFByb3BlcnR5RGVzY3JpcHRvcjxIdHRwUmVxdWVzdENhY2hlTWV0aG9kPiA9PiB7XG4gICAgaWYgKCEoZGVzY3JpcHRvcj8udmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbikpIHtcbiAgICAgIHRocm93IEVycm9yKGAnQEh0dHBSZXF1ZXN0Q2FjaGUnIGNhbiBiZSBhcHBsaWVkIG9ubHkgdG8gdGhlIGNsYXNzIG1ldGhvZCB3aGljaCByZXR1cm5zIGFuIE9ic2VydmFibGVgKTtcbiAgICB9XG5cbiAgICBjb25zdCBjYWNoZUtleVByZWZpeCA9IGAke3RhcmdldC5jb25zdHJ1Y3Rvci5uYW1lfV8ke21ldGhvZE5hbWV9YDtcbiAgICBjb25zdCBvcmlnaW5hbE1ldGhvZCA9IGRlc2NyaXB0b3IudmFsdWU7XG5cbiAgICBkZXNjcmlwdG9yLnZhbHVlID0gZnVuY3Rpb24oLi4uYXJnczogYW55W10pOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgICAgY29uc3Qgb3B0aW9ucyA9IG9wdGlvbnNIYW5kbGVyPy5jYWxsKHRoaXMgYXMgVCwgdGhpcyBhcyBULCAuLi5hcmdzKTtcblxuICAgICAgaWYgKCFvcHRpb25zPy5zdG9yYWdlICYmICEodGFyZ2V0IGFzIGFueSkuX19fX19zdG9yYWdlX19fX18pIHtcbiAgICAgICAgKHRhcmdldCBhcyBhbnkpLl9fX19fc3RvcmFnZV9fX19fID0gbmV3IERlZmF1bHRTdG9yYWdlKCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zPy50dGwgJiYgISh0YXJnZXQgYXMgYW55KS5fX19fX3R0bF9zdG9yYWdlX19fX18pIHtcbiAgICAgICAgKHRhcmdldCBhcyBhbnkpLl9fX19fdHRsX3N0b3JhZ2VfX19fXyA9IG5ldyBSZXF1ZXN0VGltZXMoKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RvcmFnZSA9IG9wdGlvbnM/LnN0b3JhZ2UgPz8gKHRhcmdldCBhcyBhbnkpLl9fX19fc3RvcmFnZV9fX19fO1xuXG4gICAgICBjb25zdCBrZXkgPSBgJHtjYWNoZUtleVByZWZpeH1fJHtKU09OLnN0cmluZ2lmeShhcmdzKX1gO1xuXG4gICAgICAodGFyZ2V0IGFzIGFueSkuX19fX193b3JraW5nX19fX18gPz89IHt9O1xuXG4gICAgICBsZXQgdHRsOiB7cmVxdWVzdFRpbWU6IG51bWJlciwgc3ViamVjdDogU3ViamVjdDx2b2lkPn0gPSB1bmRlZmluZWQgYXMgYW55O1xuXG4gICAgICBpZiAob3B0aW9ucz8udHRsKSB7XG4gICAgICAgIHR0bCA9ICh0YXJnZXQgYXMgYW55KS5fX19fX3R0bF9zdG9yYWdlX19fX18uZ2V0SXRlbShrZXkpO1xuXG4gICAgICAgIGlmICghdHRsKSB7XG4gICAgICAgICAgdHRsID0ge1xuICAgICAgICAgICAgcmVxdWVzdFRpbWU6IERhdGUubm93KCksXG4gICAgICAgICAgICBzdWJqZWN0OiBuZXcgU3ViamVjdCgpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSBpZiAodHRsLnJlcXVlc3RUaW1lICsgb3B0aW9ucy50dGwgPD0gRGF0ZS5ub3coKSkge1xuICAgICAgICAgICh0YXJnZXQgYXMgYW55KS5fX19fX3dvcmtpbmdfX19fX1trZXldID0gdHJ1ZTtcbiAgICAgICAgICB0dGwucmVxdWVzdFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgICAgIHR0bC5zdWJqZWN0Lm5leHQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgICh0YXJnZXQgYXMgYW55KS5fX19fX3R0bF9zdG9yYWdlX19fX18uc2V0SXRlbShrZXksIHR0bCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlZnJlc2hPbiA9IG1lcmdlKFxuICAgICAgICBvcHRpb25zPy5yZWZyZXNoT24gPz8gTkVWRVIgYXMgT2JzZXJ2YWJsZTx1bmtub3duPixcbiAgICAgICAgIHR0bD8uc3ViamVjdCA/PyBORVZFUixcbiAgICAgICk7XG5cbiAgICAgIGxldCBvYnNlcnZhYmxlID0gc3RvcmFnZS5nZXRJdGVtKGtleSk7XG5cbiAgICAgIGlmICghb2JzZXJ2YWJsZSkge1xuICAgICAgICBvYnNlcnZhYmxlID0gcmVmcmVzaE9uLnBpcGUoXG4gICAgICAgICAgc3RhcnRXaXRoKHRydWUpLFxuICAgICAgICAgIHN3aXRjaE1hcCgoKSA9PiBvcmlnaW5hbE1ldGhvZC5hcHBseSh0aGlzLCBbLi4uYXJnc10pKSxcbiAgICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgICAgZGVsZXRlICh0YXJnZXQgYXMgYW55KS5fX19fX3dvcmtpbmdfX19fX1trZXldO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIHNoYXJlUmVwbGF5KHtcbiAgICAgICAgICAgIGJ1ZmZlclNpemU6IDEsXG4gICAgICAgICAgICByZWZDb3VudDogb3B0aW9ucz8ucmVmQ291bnQgPz8gZmFsc2UsXG4gICAgICAgICAgICB3aW5kb3dUaW1lOiBvcHRpb25zPy53aW5kb3dUaW1lID8/IEluZmluaXR5LFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIGZpbHRlcigoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gISh0YXJnZXQgYXMgYW55KS5fX19fX3dvcmtpbmdfX19fX1trZXldO1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgICBzdG9yYWdlLnNldEl0ZW0oa2V5LCBvYnNlcnZhYmxlKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG9ic2VydmFibGU7XG4gICAgfTtcblxuICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICB9XG59XG5cbiJdfQ==
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class RequestTimes {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.storage = new Map();
|
|
4
|
+
}
|
|
5
|
+
getItem(key) {
|
|
6
|
+
return this.storage.get(key);
|
|
7
|
+
}
|
|
8
|
+
setItem(key, item) {
|
|
9
|
+
this.storage.set(key, item);
|
|
10
|
+
}
|
|
11
|
+
deleteItem(key) {
|
|
12
|
+
this.storage.delete(key);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVxdWVzdC10aW1lcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2h0dHAtcmVxdWVzdC1jYWNoZS9zcmMvbGliL3JlcXVlc3QtdGltZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBR0EsTUFBTSxPQUFPLFlBQVk7SUFBekI7UUFDVSxZQUFPLEdBQUcsSUFBSSxHQUFHLEVBQTJCLENBQUM7SUFhdkQsQ0FBQztJQVhDLE9BQU8sQ0FBQyxHQUFXO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVELE9BQU8sQ0FBQyxHQUFXLEVBQUUsSUFBcUI7UUFDeEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRCxVQUFVLENBQUMsR0FBVztRQUNwQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMzQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0h0dHBDYWNoZVN0b3JhZ2V9IGZyb20gJy4vaHR0cC1jYWNoZS1zdG9yYWdlJztcbmltcG9ydCB7T2JzZXJ2YWJsZX0gZnJvbSAncnhqcyc7XG5cbmV4cG9ydCBjbGFzcyBSZXF1ZXN0VGltZXMgaW1wbGVtZW50cyBIdHRwQ2FjaGVTdG9yYWdlIHtcbiAgcHJpdmF0ZSBzdG9yYWdlID0gbmV3IE1hcDxzdHJpbmcsIE9ic2VydmFibGU8YW55Pj4oKTtcblxuICBnZXRJdGVtKGtleTogc3RyaW5nKTogT2JzZXJ2YWJsZTxhbnk+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldChrZXkpO1xuICB9XG5cbiAgc2V0SXRlbShrZXk6IHN0cmluZywgaXRlbTogT2JzZXJ2YWJsZTxhbnk+KTogdm9pZCB7XG4gICAgdGhpcy5zdG9yYWdlLnNldChrZXksIGl0ZW0pO1xuICB9XG5cbiAgZGVsZXRlSXRlbShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuc3RvcmFnZS5kZWxldGUoa2V5KTtcbiAgfVxufVxuIl19
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NEVER } from 'rxjs';
|
|
1
|
+
import { Subject, merge, NEVER, tap, filter } from 'rxjs';
|
|
2
2
|
import { startWith, switchMap, shareReplay } from 'rxjs/operators';
|
|
3
3
|
|
|
4
4
|
class DefaultStorage {
|
|
@@ -16,6 +16,21 @@ class DefaultStorage {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
class RequestTimes {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.storage = new Map();
|
|
22
|
+
}
|
|
23
|
+
getItem(key) {
|
|
24
|
+
return this.storage.get(key);
|
|
25
|
+
}
|
|
26
|
+
setItem(key, item) {
|
|
27
|
+
this.storage.set(key, item);
|
|
28
|
+
}
|
|
29
|
+
deleteItem(key) {
|
|
30
|
+
this.storage.delete(key);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
19
34
|
const HttpRequestCache = (optionsHandler) => {
|
|
20
35
|
return (target, methodName, descriptor) => {
|
|
21
36
|
if (!((descriptor === null || descriptor === void 0 ? void 0 : descriptor.value) instanceof Function)) {
|
|
@@ -24,20 +39,45 @@ const HttpRequestCache = (optionsHandler) => {
|
|
|
24
39
|
const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;
|
|
25
40
|
const originalMethod = descriptor.value;
|
|
26
41
|
descriptor.value = function (...args) {
|
|
27
|
-
var
|
|
42
|
+
var _b, _c, _d, _e, _f, _g;
|
|
43
|
+
var _a;
|
|
28
44
|
const options = optionsHandler === null || optionsHandler === void 0 ? void 0 : optionsHandler.call(this, this, ...args);
|
|
29
45
|
if (!(options === null || options === void 0 ? void 0 : options.storage) && !target._____storage_____) {
|
|
30
46
|
target._____storage_____ = new DefaultStorage();
|
|
31
47
|
}
|
|
32
|
-
|
|
33
|
-
|
|
48
|
+
if ((options === null || options === void 0 ? void 0 : options.ttl) && !target._____ttl_storage_____) {
|
|
49
|
+
target._____ttl_storage_____ = new RequestTimes();
|
|
50
|
+
}
|
|
51
|
+
const storage = (_b = options === null || options === void 0 ? void 0 : options.storage) !== null && _b !== void 0 ? _b : target._____storage_____;
|
|
34
52
|
const key = `${cacheKeyPrefix}_${JSON.stringify(args)}`;
|
|
53
|
+
(_c = (_a = target)._____working_____) !== null && _c !== void 0 ? _c : (_a._____working_____ = {});
|
|
54
|
+
let ttl = undefined;
|
|
55
|
+
if (options === null || options === void 0 ? void 0 : options.ttl) {
|
|
56
|
+
ttl = target._____ttl_storage_____.getItem(key);
|
|
57
|
+
if (!ttl) {
|
|
58
|
+
ttl = {
|
|
59
|
+
requestTime: Date.now(),
|
|
60
|
+
subject: new Subject(),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
else if (ttl.requestTime + options.ttl <= Date.now()) {
|
|
64
|
+
target._____working_____[key] = true;
|
|
65
|
+
ttl.requestTime = Date.now();
|
|
66
|
+
ttl.subject.next();
|
|
67
|
+
}
|
|
68
|
+
target._____ttl_storage_____.setItem(key, ttl);
|
|
69
|
+
}
|
|
70
|
+
const refreshOn = merge((_d = options === null || options === void 0 ? void 0 : options.refreshOn) !== null && _d !== void 0 ? _d : NEVER, (_e = ttl === null || ttl === void 0 ? void 0 : ttl.subject) !== null && _e !== void 0 ? _e : NEVER);
|
|
35
71
|
let observable = storage.getItem(key);
|
|
36
72
|
if (!observable) {
|
|
37
|
-
observable = refreshOn.pipe(startWith(true), switchMap(() => originalMethod.apply(this, [...args])),
|
|
73
|
+
observable = refreshOn.pipe(startWith(true), switchMap(() => originalMethod.apply(this, [...args])), tap(() => {
|
|
74
|
+
delete target._____working_____[key];
|
|
75
|
+
}), shareReplay({
|
|
38
76
|
bufferSize: 1,
|
|
39
|
-
refCount: (
|
|
40
|
-
windowTime: (
|
|
77
|
+
refCount: (_f = options === null || options === void 0 ? void 0 : options.refCount) !== null && _f !== void 0 ? _f : false,
|
|
78
|
+
windowTime: (_g = options === null || options === void 0 ? void 0 : options.windowTime) !== null && _g !== void 0 ? _g : Infinity,
|
|
79
|
+
}), filter(() => {
|
|
80
|
+
return !target._____working_____[key];
|
|
41
81
|
}));
|
|
42
82
|
storage.setItem(key, observable);
|
|
43
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kovalenko-http-request-cache.mjs","sources":["../../../projects/http-request-cache/src/lib/default-storage.ts","../../../projects/http-request-cache/src/lib/http-request-cache.decorator.ts","../../../projects/http-request-cache/src/public-api.ts","../../../projects/http-request-cache/src/kovalenko-http-request-cache.ts"],"sourcesContent":["import {HttpCacheStorage} from './http-cache-storage';\nimport {Observable} from 'rxjs';\n\nexport class DefaultStorage implements HttpCacheStorage {\n private storage = new Map<string, Observable<any>>();\n\n getItem(key: string): Observable<any> | undefined {\n return this.storage.get(key);\n }\n\n setItem(key: string, item: Observable<any>): void {\n this.storage.set(key, item);\n }\n\n deleteItem(key: string): void {\n this.storage.delete(key);\n }\n}\n","import {HttpCacheOptions} from './http-cache-options';\nimport {NEVER, Observable} from 'rxjs';\nimport {shareReplay, startWith, switchMap} from 'rxjs/operators';\nimport {DefaultStorage} from './default-storage';\n\ntype HttpRequestCacheMethod = (...args: any[]) => Observable<any>;\n\nexport const HttpRequestCache = <T extends Record<string, any>>(optionsHandler?: (obj: T, ...args: any[]) => HttpCacheOptions) => {\n return (target: T, methodName: string, descriptor: TypedPropertyDescriptor<HttpRequestCacheMethod>): TypedPropertyDescriptor<HttpRequestCacheMethod> => {\n if (!(descriptor?.value instanceof Function)) {\n throw Error(`'@HttpRequestCache' can be applied only to the class method which returns an Observable`);\n }\n\n const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;\n const originalMethod = descriptor.value;\n\n descriptor.value = function(...args: any[]): Observable<any> {\n const options = optionsHandler?.call(this as T, this as T, ...args);\n\n if (!options?.storage && !(target as any)._____storage_____) {\n (target as any)._____storage_____ = new DefaultStorage();\n }\n\n
|
|
1
|
+
{"version":3,"file":"kovalenko-http-request-cache.mjs","sources":["../../../projects/http-request-cache/src/lib/default-storage.ts","../../../projects/http-request-cache/src/lib/request-times.ts","../../../projects/http-request-cache/src/lib/http-request-cache.decorator.ts","../../../projects/http-request-cache/src/public-api.ts","../../../projects/http-request-cache/src/kovalenko-http-request-cache.ts"],"sourcesContent":["import {HttpCacheStorage} from './http-cache-storage';\nimport {Observable} from 'rxjs';\n\nexport class DefaultStorage implements HttpCacheStorage {\n private storage = new Map<string, Observable<any>>();\n\n getItem(key: string): Observable<any> | undefined {\n return this.storage.get(key);\n }\n\n setItem(key: string, item: Observable<any>): void {\n this.storage.set(key, item);\n }\n\n deleteItem(key: string): void {\n this.storage.delete(key);\n }\n}\n","import {HttpCacheStorage} from './http-cache-storage';\nimport {Observable} from 'rxjs';\n\nexport class RequestTimes implements HttpCacheStorage {\n private storage = new Map<string, Observable<any>>();\n\n getItem(key: string): Observable<any> | undefined {\n return this.storage.get(key);\n }\n\n setItem(key: string, item: Observable<any>): void {\n this.storage.set(key, item);\n }\n\n deleteItem(key: string): void {\n this.storage.delete(key);\n }\n}\n","import {HttpCacheOptions} from './http-cache-options';\nimport {filter, merge, NEVER, Observable, Subject, tap} from 'rxjs';\nimport {shareReplay, startWith, switchMap} from 'rxjs/operators';\nimport {DefaultStorage} from './default-storage';\nimport {RequestTimes} from './request-times';\n\ntype HttpRequestCacheMethod = (...args: any[]) => Observable<any>;\n\nexport const HttpRequestCache = <T extends Record<string, any>>(optionsHandler?: (obj: T, ...args: any[]) => HttpCacheOptions) => {\n return (target: T, methodName: string, descriptor: TypedPropertyDescriptor<HttpRequestCacheMethod>): TypedPropertyDescriptor<HttpRequestCacheMethod> => {\n if (!(descriptor?.value instanceof Function)) {\n throw Error(`'@HttpRequestCache' can be applied only to the class method which returns an Observable`);\n }\n\n const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;\n const originalMethod = descriptor.value;\n\n descriptor.value = function(...args: any[]): Observable<any> {\n const options = optionsHandler?.call(this as T, this as T, ...args);\n\n if (!options?.storage && !(target as any)._____storage_____) {\n (target as any)._____storage_____ = new DefaultStorage();\n }\n\n if (options?.ttl && !(target as any)._____ttl_storage_____) {\n (target as any)._____ttl_storage_____ = new RequestTimes();\n }\n\n const storage = options?.storage ?? (target as any)._____storage_____;\n\n const key = `${cacheKeyPrefix}_${JSON.stringify(args)}`;\n\n (target as any)._____working_____ ??= {};\n\n let ttl: {requestTime: number, subject: Subject<void>} = undefined as any;\n\n if (options?.ttl) {\n ttl = (target as any)._____ttl_storage_____.getItem(key);\n\n if (!ttl) {\n ttl = {\n requestTime: Date.now(),\n subject: new Subject(),\n };\n } else if (ttl.requestTime + options.ttl <= Date.now()) {\n (target as any)._____working_____[key] = true;\n ttl.requestTime = Date.now();\n ttl.subject.next();\n }\n\n (target as any)._____ttl_storage_____.setItem(key, ttl);\n }\n\n const refreshOn = merge(\n options?.refreshOn ?? NEVER as Observable<unknown>,\n ttl?.subject ?? NEVER,\n );\n\n let observable = storage.getItem(key);\n\n if (!observable) {\n observable = refreshOn.pipe(\n startWith(true),\n switchMap(() => originalMethod.apply(this, [...args])),\n tap(() => {\n delete (target as any)._____working_____[key];\n }),\n shareReplay({\n bufferSize: 1,\n refCount: options?.refCount ?? false,\n windowTime: options?.windowTime ?? Infinity,\n }),\n filter(() => {\n return !(target as any)._____working_____[key];\n }),\n );\n storage.setItem(key, observable);\n }\n\n return observable;\n };\n\n return descriptor;\n }\n}\n\n","/*\n * Public API Surface of http-request-cache\n */\n\nexport * from './lib/http-request-cache.decorator';\nexport * from './lib/http-cache-storage';\nexport * from './lib/http-cache-options';\nexport * from './lib/default-storage';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NEVER } from 'rxjs';
|
|
1
|
+
import { Subject, merge, NEVER, tap, filter } from 'rxjs';
|
|
2
2
|
import { startWith, switchMap, shareReplay } from 'rxjs/operators';
|
|
3
3
|
|
|
4
4
|
class DefaultStorage {
|
|
@@ -16,6 +16,21 @@ class DefaultStorage {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
class RequestTimes {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.storage = new Map();
|
|
22
|
+
}
|
|
23
|
+
getItem(key) {
|
|
24
|
+
return this.storage.get(key);
|
|
25
|
+
}
|
|
26
|
+
setItem(key, item) {
|
|
27
|
+
this.storage.set(key, item);
|
|
28
|
+
}
|
|
29
|
+
deleteItem(key) {
|
|
30
|
+
this.storage.delete(key);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
19
34
|
const HttpRequestCache = (optionsHandler) => {
|
|
20
35
|
return (target, methodName, descriptor) => {
|
|
21
36
|
if (!(descriptor?.value instanceof Function)) {
|
|
@@ -24,19 +39,44 @@ const HttpRequestCache = (optionsHandler) => {
|
|
|
24
39
|
const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;
|
|
25
40
|
const originalMethod = descriptor.value;
|
|
26
41
|
descriptor.value = function (...args) {
|
|
42
|
+
var _a;
|
|
27
43
|
const options = optionsHandler?.call(this, this, ...args);
|
|
28
44
|
if (!options?.storage && !target._____storage_____) {
|
|
29
45
|
target._____storage_____ = new DefaultStorage();
|
|
30
46
|
}
|
|
47
|
+
if (options?.ttl && !target._____ttl_storage_____) {
|
|
48
|
+
target._____ttl_storage_____ = new RequestTimes();
|
|
49
|
+
}
|
|
31
50
|
const storage = options?.storage ?? target._____storage_____;
|
|
32
|
-
const refreshOn = options?.refreshOn ?? NEVER;
|
|
33
51
|
const key = `${cacheKeyPrefix}_${JSON.stringify(args)}`;
|
|
52
|
+
(_a = target)._____working_____ ?? (_a._____working_____ = {});
|
|
53
|
+
let ttl = undefined;
|
|
54
|
+
if (options?.ttl) {
|
|
55
|
+
ttl = target._____ttl_storage_____.getItem(key);
|
|
56
|
+
if (!ttl) {
|
|
57
|
+
ttl = {
|
|
58
|
+
requestTime: Date.now(),
|
|
59
|
+
subject: new Subject(),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
else if (ttl.requestTime + options.ttl <= Date.now()) {
|
|
63
|
+
target._____working_____[key] = true;
|
|
64
|
+
ttl.requestTime = Date.now();
|
|
65
|
+
ttl.subject.next();
|
|
66
|
+
}
|
|
67
|
+
target._____ttl_storage_____.setItem(key, ttl);
|
|
68
|
+
}
|
|
69
|
+
const refreshOn = merge(options?.refreshOn ?? NEVER, ttl?.subject ?? NEVER);
|
|
34
70
|
let observable = storage.getItem(key);
|
|
35
71
|
if (!observable) {
|
|
36
|
-
observable = refreshOn.pipe(startWith(true), switchMap(() => originalMethod.apply(this, [...args])),
|
|
72
|
+
observable = refreshOn.pipe(startWith(true), switchMap(() => originalMethod.apply(this, [...args])), tap(() => {
|
|
73
|
+
delete target._____working_____[key];
|
|
74
|
+
}), shareReplay({
|
|
37
75
|
bufferSize: 1,
|
|
38
76
|
refCount: options?.refCount ?? false,
|
|
39
77
|
windowTime: options?.windowTime ?? Infinity,
|
|
78
|
+
}), filter(() => {
|
|
79
|
+
return !target._____working_____[key];
|
|
40
80
|
}));
|
|
41
81
|
storage.setItem(key, observable);
|
|
42
82
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kovalenko-http-request-cache.mjs","sources":["../../../projects/http-request-cache/src/lib/default-storage.ts","../../../projects/http-request-cache/src/lib/http-request-cache.decorator.ts","../../../projects/http-request-cache/src/public-api.ts","../../../projects/http-request-cache/src/kovalenko-http-request-cache.ts"],"sourcesContent":["import {HttpCacheStorage} from './http-cache-storage';\nimport {Observable} from 'rxjs';\n\nexport class DefaultStorage implements HttpCacheStorage {\n private storage = new Map<string, Observable<any>>();\n\n getItem(key: string): Observable<any> | undefined {\n return this.storage.get(key);\n }\n\n setItem(key: string, item: Observable<any>): void {\n this.storage.set(key, item);\n }\n\n deleteItem(key: string): void {\n this.storage.delete(key);\n }\n}\n","import {HttpCacheOptions} from './http-cache-options';\nimport {NEVER, Observable} from 'rxjs';\nimport {shareReplay, startWith, switchMap} from 'rxjs/operators';\nimport {DefaultStorage} from './default-storage';\n\ntype HttpRequestCacheMethod = (...args: any[]) => Observable<any>;\n\nexport const HttpRequestCache = <T extends Record<string, any>>(optionsHandler?: (obj: T, ...args: any[]) => HttpCacheOptions) => {\n return (target: T, methodName: string, descriptor: TypedPropertyDescriptor<HttpRequestCacheMethod>): TypedPropertyDescriptor<HttpRequestCacheMethod> => {\n if (!(descriptor?.value instanceof Function)) {\n throw Error(`'@HttpRequestCache' can be applied only to the class method which returns an Observable`);\n }\n\n const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;\n const originalMethod = descriptor.value;\n\n descriptor.value = function(...args: any[]): Observable<any> {\n const options = optionsHandler?.call(this as T, this as T, ...args);\n\n if (!options?.storage && !(target as any)._____storage_____) {\n (target as any)._____storage_____ = new DefaultStorage();\n }\n\n
|
|
1
|
+
{"version":3,"file":"kovalenko-http-request-cache.mjs","sources":["../../../projects/http-request-cache/src/lib/default-storage.ts","../../../projects/http-request-cache/src/lib/request-times.ts","../../../projects/http-request-cache/src/lib/http-request-cache.decorator.ts","../../../projects/http-request-cache/src/public-api.ts","../../../projects/http-request-cache/src/kovalenko-http-request-cache.ts"],"sourcesContent":["import {HttpCacheStorage} from './http-cache-storage';\nimport {Observable} from 'rxjs';\n\nexport class DefaultStorage implements HttpCacheStorage {\n private storage = new Map<string, Observable<any>>();\n\n getItem(key: string): Observable<any> | undefined {\n return this.storage.get(key);\n }\n\n setItem(key: string, item: Observable<any>): void {\n this.storage.set(key, item);\n }\n\n deleteItem(key: string): void {\n this.storage.delete(key);\n }\n}\n","import {HttpCacheStorage} from './http-cache-storage';\nimport {Observable} from 'rxjs';\n\nexport class RequestTimes implements HttpCacheStorage {\n private storage = new Map<string, Observable<any>>();\n\n getItem(key: string): Observable<any> | undefined {\n return this.storage.get(key);\n }\n\n setItem(key: string, item: Observable<any>): void {\n this.storage.set(key, item);\n }\n\n deleteItem(key: string): void {\n this.storage.delete(key);\n }\n}\n","import {HttpCacheOptions} from './http-cache-options';\nimport {filter, merge, NEVER, Observable, Subject, tap} from 'rxjs';\nimport {shareReplay, startWith, switchMap} from 'rxjs/operators';\nimport {DefaultStorage} from './default-storage';\nimport {RequestTimes} from './request-times';\n\ntype HttpRequestCacheMethod = (...args: any[]) => Observable<any>;\n\nexport const HttpRequestCache = <T extends Record<string, any>>(optionsHandler?: (obj: T, ...args: any[]) => HttpCacheOptions) => {\n return (target: T, methodName: string, descriptor: TypedPropertyDescriptor<HttpRequestCacheMethod>): TypedPropertyDescriptor<HttpRequestCacheMethod> => {\n if (!(descriptor?.value instanceof Function)) {\n throw Error(`'@HttpRequestCache' can be applied only to the class method which returns an Observable`);\n }\n\n const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;\n const originalMethod = descriptor.value;\n\n descriptor.value = function(...args: any[]): Observable<any> {\n const options = optionsHandler?.call(this as T, this as T, ...args);\n\n if (!options?.storage && !(target as any)._____storage_____) {\n (target as any)._____storage_____ = new DefaultStorage();\n }\n\n if (options?.ttl && !(target as any)._____ttl_storage_____) {\n (target as any)._____ttl_storage_____ = new RequestTimes();\n }\n\n const storage = options?.storage ?? (target as any)._____storage_____;\n\n const key = `${cacheKeyPrefix}_${JSON.stringify(args)}`;\n\n (target as any)._____working_____ ??= {};\n\n let ttl: {requestTime: number, subject: Subject<void>} = undefined as any;\n\n if (options?.ttl) {\n ttl = (target as any)._____ttl_storage_____.getItem(key);\n\n if (!ttl) {\n ttl = {\n requestTime: Date.now(),\n subject: new Subject(),\n };\n } else if (ttl.requestTime + options.ttl <= Date.now()) {\n (target as any)._____working_____[key] = true;\n ttl.requestTime = Date.now();\n ttl.subject.next();\n }\n\n (target as any)._____ttl_storage_____.setItem(key, ttl);\n }\n\n const refreshOn = merge(\n options?.refreshOn ?? NEVER as Observable<unknown>,\n ttl?.subject ?? NEVER,\n );\n\n let observable = storage.getItem(key);\n\n if (!observable) {\n observable = refreshOn.pipe(\n startWith(true),\n switchMap(() => originalMethod.apply(this, [...args])),\n tap(() => {\n delete (target as any)._____working_____[key];\n }),\n shareReplay({\n bufferSize: 1,\n refCount: options?.refCount ?? false,\n windowTime: options?.windowTime ?? Infinity,\n }),\n filter(() => {\n return !(target as any)._____working_____[key];\n }),\n );\n storage.setItem(key, observable);\n }\n\n return observable;\n };\n\n return descriptor;\n }\n}\n\n","/*\n * Public API Surface of http-request-cache\n */\n\nexport * from './lib/http-request-cache.decorator';\nexport * from './lib/http-cache-storage';\nexport * from './lib/http-cache-options';\nexport * from './lib/default-storage';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { HttpCacheStorage } from './http-cache-storage';
|
|
|
3
3
|
export interface HttpCacheOptions {
|
|
4
4
|
refCount?: boolean;
|
|
5
5
|
windowTime?: number;
|
|
6
|
+
ttl?: number;
|
|
6
7
|
storage?: HttpCacheStorage;
|
|
7
8
|
refreshOn?: Observable<unknown> | Subject<unknown> | BehaviorSubject<unknown>;
|
|
8
9
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { HttpCacheStorage } from './http-cache-storage';
|
|
2
|
+
import { Observable } from 'rxjs';
|
|
3
|
+
export declare class RequestTimes implements HttpCacheStorage {
|
|
4
|
+
private storage;
|
|
5
|
+
getItem(key: string): Observable<any> | undefined;
|
|
6
|
+
setItem(key: string, item: Observable<any>): void;
|
|
7
|
+
deleteItem(key: string): void;
|
|
8
|
+
}
|