@kovalenko/http-request-cache 1.3.5 → 1.3.6
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/esm2020/lib/http-request-cache.decorator.mjs +47 -106
- package/fesm2015/kovalenko-http-request-cache.mjs +50 -107
- package/fesm2015/kovalenko-http-request-cache.mjs.map +1 -1
- package/fesm2020/kovalenko-http-request-cache.mjs +46 -105
- package/fesm2020/kovalenko-http-request-cache.mjs.map +1 -1
- package/lib/http-request-cache.decorator.js +48 -106
- package/lib/http-request-cache.decorator.js.map +1 -1
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Subject, merge, NEVER, startWith, switchMap,
|
|
1
|
+
import { Subject, merge, NEVER, startWith, switchMap, tap, share, ReplaySubject, timer, filter, finalize } from 'rxjs';
|
|
2
2
|
|
|
3
3
|
class DefaultStorage {
|
|
4
4
|
constructor() {
|
|
@@ -30,148 +30,89 @@ class RequestTimes {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
const serializeArg = (value) => {
|
|
34
|
-
const seen = new WeakMap();
|
|
35
|
-
let counter = 0;
|
|
36
|
-
const serialize = (v) => {
|
|
37
|
-
if (v === null) {
|
|
38
|
-
return 'null';
|
|
39
|
-
}
|
|
40
|
-
const t = typeof v;
|
|
41
|
-
if (t === 'number' || t === 'boolean') {
|
|
42
|
-
return String(v);
|
|
43
|
-
}
|
|
44
|
-
if (t === 'bigint') {
|
|
45
|
-
return `${v}n`;
|
|
46
|
-
}
|
|
47
|
-
if (t === 'undefined' || t === 'symbol' || t === 'function') {
|
|
48
|
-
return 'undef';
|
|
49
|
-
}
|
|
50
|
-
if (t === 'string') {
|
|
51
|
-
return `str:${v}`;
|
|
52
|
-
}
|
|
53
|
-
if (t !== 'object') {
|
|
54
|
-
return `${t}:${String(v)}`;
|
|
55
|
-
}
|
|
56
|
-
if (v instanceof Date) {
|
|
57
|
-
return `date:${v.toISOString()}`;
|
|
58
|
-
}
|
|
59
|
-
if (v instanceof RegExp) {
|
|
60
|
-
return `regexp:${v.toString()}`;
|
|
61
|
-
}
|
|
62
|
-
const path = seen.get(v);
|
|
63
|
-
if (path !== undefined) {
|
|
64
|
-
return `circ:${path}`;
|
|
65
|
-
}
|
|
66
|
-
seen.set(v, `v${counter++}`);
|
|
67
|
-
let out;
|
|
68
|
-
if (v instanceof Map) {
|
|
69
|
-
out = `map:${serialize(Array.from(v.entries()))}`;
|
|
70
|
-
}
|
|
71
|
-
else if (v instanceof Set) {
|
|
72
|
-
out = `set:${serialize(Array.from(v.values()))}`;
|
|
73
|
-
}
|
|
74
|
-
else if (Array.isArray(v)) {
|
|
75
|
-
out = `[${v.map(serialize).join(',')}]`;
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
out = `{${Object.keys(v).sort().map(k => `${serialize(k)}:${serialize(v[k])}`).join(',')}}`;
|
|
79
|
-
}
|
|
80
|
-
seen.delete(v);
|
|
81
|
-
return out;
|
|
82
|
-
};
|
|
83
|
-
return serialize(value);
|
|
84
|
-
};
|
|
85
|
-
const hashArgs = (input) => {
|
|
86
|
-
let h = 0x811c9dc5;
|
|
87
|
-
for (let i = 0; i < input.length; i++) {
|
|
88
|
-
h ^= input.charCodeAt(i);
|
|
89
|
-
h = Math.imul(h, 0x01000193);
|
|
90
|
-
}
|
|
91
|
-
return (h >>> 0).toString(36);
|
|
92
|
-
};
|
|
93
33
|
const HttpRequestCache = (optionsHandler) => {
|
|
94
34
|
return (target, methodName, descriptor) => {
|
|
95
|
-
if (
|
|
35
|
+
if (!(descriptor?.value instanceof Function)) {
|
|
96
36
|
throw Error(`'@HttpRequestCache' can be applied only to the class method which returns an Observable`);
|
|
97
37
|
}
|
|
98
38
|
const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;
|
|
99
39
|
const originalMethod = descriptor.value;
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
|
|
40
|
+
const working = {};
|
|
41
|
+
const subscribers = {};
|
|
42
|
+
const removeTimers = {};
|
|
103
43
|
descriptor.value = function (...args) {
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (useDefaultStorage && !self.___storage___) {
|
|
108
|
-
self.___storage___ = new DefaultStorage();
|
|
44
|
+
const options = optionsHandler?.call(this, this, ...args);
|
|
45
|
+
if (!options?.storage && !target._____storage_____) {
|
|
46
|
+
target._____storage_____ = new DefaultStorage();
|
|
109
47
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
self.___ttl_storage___ = new RequestTimes();
|
|
48
|
+
if (options?.ttl && !target._____ttl_storage_____) {
|
|
49
|
+
target._____ttl_storage_____ = new RequestTimes();
|
|
113
50
|
}
|
|
114
|
-
const storage = options?.storage ??
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
id = ++instanceIdCounter;
|
|
121
|
-
instanceIds.set(self, id);
|
|
122
|
-
}
|
|
123
|
-
instanceId = `_${id}`;
|
|
51
|
+
const storage = options?.storage ?? target._____storage_____;
|
|
52
|
+
const key = `${cacheKeyPrefix}_${JSON.stringify(args)}`;
|
|
53
|
+
// отменяем запланированное удаление
|
|
54
|
+
if (removeTimers[key]) {
|
|
55
|
+
clearTimeout(removeTimers[key]);
|
|
56
|
+
delete removeTimers[key];
|
|
124
57
|
}
|
|
125
|
-
const key = `${cacheKeyPrefix}${instanceId}_${hashArgs(serializeArg(args))}`;
|
|
126
|
-
const latest = latestCall[key] ?? (latestCall[key] = { self, args });
|
|
127
|
-
latest.self = self;
|
|
128
|
-
latest.args = args;
|
|
129
58
|
let ttl = undefined;
|
|
130
|
-
if (
|
|
131
|
-
ttl =
|
|
59
|
+
if (options?.ttl) {
|
|
60
|
+
ttl = target._____ttl_storage_____.getItem(key);
|
|
132
61
|
if (!ttl) {
|
|
133
62
|
ttl = {
|
|
134
63
|
requestTime: Date.now(),
|
|
135
64
|
subject: new Subject(),
|
|
136
65
|
};
|
|
137
66
|
}
|
|
138
|
-
else if (ttl.requestTime + options
|
|
67
|
+
else if (ttl.requestTime + options.ttl <= Date.now()) {
|
|
68
|
+
working[key] = true;
|
|
139
69
|
ttl.requestTime = Date.now();
|
|
140
70
|
ttl.subject.next();
|
|
141
71
|
}
|
|
142
|
-
|
|
72
|
+
target._____ttl_storage_____.setItem(key, ttl);
|
|
143
73
|
}
|
|
144
74
|
const refreshOn = merge(options?.refreshOn ?? NEVER, ttl?.subject ?? NEVER);
|
|
145
75
|
let observable = storage.getItem(key);
|
|
146
76
|
if (!observable) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
: 0;
|
|
150
|
-
observable = refreshOn.pipe(startWith(true), switchMap(() => originalMethod.apply(latest.self, latest.args)), finalize(() => {
|
|
151
|
-
storage.deleteItem(key);
|
|
152
|
-
ttlStorage?.deleteItem(key);
|
|
153
|
-
delete latestCall[key];
|
|
77
|
+
observable = refreshOn.pipe(startWith(true), switchMap(() => originalMethod.apply(this, [...args])), tap(() => {
|
|
78
|
+
delete working[key];
|
|
154
79
|
}), share({
|
|
155
80
|
connector: () => new ReplaySubject(1),
|
|
156
81
|
resetOnComplete: false,
|
|
157
82
|
resetOnError: true,
|
|
158
|
-
resetOnRefCountZero: options?.refCount
|
|
159
|
-
?
|
|
83
|
+
resetOnRefCountZero: !options?.refCount
|
|
84
|
+
? false
|
|
85
|
+
: options.refCountDelay != null
|
|
160
86
|
? () => timer(options.refCountDelay)
|
|
161
|
-
: true
|
|
162
|
-
: ttlRemaining > 0
|
|
163
|
-
? () => timer(ttlRemaining)
|
|
164
87
|
: true,
|
|
88
|
+
}), filter(() => !working[key]), finalize(() => {
|
|
89
|
+
subscribers[key]--;
|
|
90
|
+
if (subscribers[key] <= 0) {
|
|
91
|
+
delete subscribers[key];
|
|
92
|
+
if (options?.refCount) {
|
|
93
|
+
const unset = () => {
|
|
94
|
+
storage.deleteItem(key);
|
|
95
|
+
target._____ttl_storage_____?.deleteItem(key);
|
|
96
|
+
delete removeTimers[key];
|
|
97
|
+
};
|
|
98
|
+
if (options.refCountDelay == null) {
|
|
99
|
+
unset();
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
removeTimers[key] = setTimeout(unset, options.refCountDelay);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
165
106
|
}));
|
|
166
107
|
storage.setItem(key, observable);
|
|
167
108
|
if (options?.windowTime) {
|
|
168
109
|
setTimeout(() => {
|
|
169
110
|
storage.deleteItem(key);
|
|
170
|
-
|
|
171
|
-
delete latestCall[key];
|
|
111
|
+
target._____ttl_storage_____?.deleteItem(key);
|
|
172
112
|
}, options.windowTime);
|
|
173
113
|
}
|
|
174
114
|
}
|
|
115
|
+
subscribers[key]++;
|
|
175
116
|
return observable;
|
|
176
117
|
};
|
|
177
118
|
return descriptor;
|
|
@@ -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/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 {\n finalize, merge, NEVER, Observable, Subject, startWith, switchMap, share,\n ReplaySubject, timer,\n} from 'rxjs';\n\nimport {DefaultStorage} from './default-storage';\nimport {HttpCacheOptions} from './http-cache-options';\nimport {RequestTimes} from './request-times';\n\ntype HttpRequestCacheMethod = (...args: any[]) => Observable<any>;\n\nconst serializeArg = (value: any): string => {\n const seen = new WeakMap<object, string>();\n let counter = 0;\n\n const serialize = (v: any): string => {\n if (v === null) {\n return 'null';\n }\n const t = typeof v;\n\n if (t === 'number' || t === 'boolean') {\n return String(v);\n }\n if (t === 'bigint') {\n return `${v}n`;\n }\n if (t === 'undefined' || t === 'symbol' || t === 'function') {\n return 'undef';\n }\n if (t === 'string') {\n return `str:${v}`;\n }\n if (t !== 'object') {\n return `${t}:${String(v)}`;\n }\n\n if (v instanceof Date) {\n return `date:${v.toISOString()}`;\n }\n if (v instanceof RegExp) {\n return `regexp:${v.toString()}`;\n }\n\n const path = seen.get(v);\n if (path !== undefined) {\n return `circ:${path}`;\n }\n seen.set(v, `v${counter++}`);\n\n let out: string;\n if (v instanceof Map) {\n out = `map:${serialize(Array.from(v.entries()))}`;\n } else if (v instanceof Set) {\n out = `set:${serialize(Array.from(v.values()))}`;\n } else if (Array.isArray(v)) {\n out = `[${v.map(serialize).join(',')}]`;\n } else {\n out = `{${Object.keys(v).sort().map(k => `${serialize(k)}:${serialize(v[k])}`).join(',')}}`;\n }\n\n seen.delete(v);\n return out;\n };\n\n return serialize(value);\n};\n\nconst hashArgs = (input: string): string => {\n let h = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n h ^= input.charCodeAt(i);\n h = Math.imul(h, 0x01000193);\n }\n return (h >>> 0).toString(36);\n};\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 (typeof descriptor?.value !== '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 const latestCall: Record<string, {self: any, args: any[]}> = {};\n\n const instanceIds = new WeakMap<object, number>();\n let instanceIdCounter = 0;\n\n descriptor.value = function(...args: any[]): Observable<any> {\n const self = this as Record<string, any>;\n const options = optionsHandler?.call(self as T, self as T, ...args);\n\n const useDefaultStorage = !options?.storage;\n if (useDefaultStorage && !self.___storage___) {\n self.___storage___ = new DefaultStorage();\n }\n\n const ttlEnabled = options?.ttl != null;\n if (ttlEnabled && !self.___ttl_storage___) {\n self.___ttl_storage___ = new RequestTimes();\n }\n\n const storage = options?.storage ?? self.___storage___;\n const ttlStorage = self.___ttl_storage___;\n\n let instanceId = '';\n if (useDefaultStorage) {\n let id = instanceIds.get(self);\n if (id === undefined) {\n id = ++instanceIdCounter;\n instanceIds.set(self, id);\n }\n instanceId = `_${id}`;\n }\n\n const key = `${cacheKeyPrefix}${instanceId}_${hashArgs(serializeArg(args))}`;\n const latest = latestCall[key] ?? (latestCall[key] = {self, args});\n latest.self = self;\n latest.args = args;\n\n let ttl: {requestTime: number, subject: Subject<void>} = undefined as any;\n\n if (ttlEnabled && ttlStorage) {\n ttl = ttlStorage.getItem(key);\n\n if (!ttl) {\n ttl = {\n requestTime: Date.now(),\n subject: new Subject(),\n };\n } else if (ttl.requestTime + (options?.ttl as number) <= Date.now()) {\n ttl.requestTime = Date.now();\n ttl.subject.next();\n }\n\n ttlStorage.setItem(key, ttl);\n }\n\n const refreshOn = merge(\n options?.refreshOn ?? NEVER as Observable<unknown>,\n ttl?.subject ?? NEVER as Observable<unknown>,\n );\n\n let observable = storage.getItem(key);\n\n if (!observable) {\n const ttlRemaining = ttlEnabled && ttl\n ? ttl.requestTime + (options?.ttl as number) - Date.now()\n : 0;\n\n observable = refreshOn.pipe(\n startWith(true),\n switchMap(() => originalMethod.apply(latest.self, latest.args)),\n finalize(() => {\n storage.deleteItem(key);\n ttlStorage?.deleteItem(key);\n delete latestCall[key];\n }),\n share({\n connector: () => new ReplaySubject(1),\n resetOnComplete: false,\n resetOnError: true,\n resetOnRefCountZero: options?.refCount\n ? options.refCountDelay != null\n ? (): Observable<number> => timer(options.refCountDelay!)\n : true\n : ttlRemaining > 0\n ? (): Observable<number> => timer(ttlRemaining)\n : true,\n }),\n );\n storage.setItem(key, observable);\n\n if (options?.windowTime) {\n setTimeout(\n () => {\n storage.deleteItem(key);\n ttlStorage?.deleteItem(key);\n delete latestCall[key];\n },\n options.windowTime,\n );\n }\n }\n\n return observable;\n };\n\n return descriptor;\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
|
+
{"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 {\n filter,\n finalize,\n merge,\n NEVER,\n Observable,\n ReplaySubject,\n share,\n startWith,\n Subject,\n switchMap,\n tap,\n timer,\n} from 'rxjs';\n\nimport {DefaultStorage} from './default-storage';\nimport {HttpCacheOptions} from './http-cache-options';\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 (\n target: T,\n methodName: string,\n descriptor: TypedPropertyDescriptor<HttpRequestCacheMethod>,\n ): 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 const working: Record<string, boolean> = {};\n const subscribers: Record<string, number> = {};\n const removeTimers: Record<string, ReturnType<typeof setTimeout>> = {};\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 // отменяем запланированное удаление\n if (removeTimers[key]) {\n clearTimeout(removeTimers[key]);\n delete removeTimers[key];\n }\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 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 as Observable<unknown>,\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 working[key];\n }),\n share({\n connector: () => new ReplaySubject(1),\n resetOnComplete: false,\n resetOnError: true,\n resetOnRefCountZero: !options?.refCount\n ? false\n : options.refCountDelay != null\n ? () => timer(options.refCountDelay!)\n : true,\n }),\n filter(() => !working[key]),\n finalize(() => {\n subscribers[key]--;\n\n if (subscribers[key] <= 0) {\n delete subscribers[key];\n\n if (options?.refCount) {\n const unset = () => {\n storage.deleteItem(key);\n (target as any)._____ttl_storage_____?.deleteItem(key);\n\n delete removeTimers[key];\n };\n\n if (options.refCountDelay == null) {\n unset();\n } else {\n removeTimers[key] = setTimeout(unset, options.refCountDelay);\n }\n }\n }\n }),\n );\n storage.setItem(key, observable);\n\n if (options?.windowTime) {\n setTimeout(\n () => {\n storage.deleteItem(key);\n (target as any)._____ttl_storage_____?.deleteItem(key);\n },\n options.windowTime,\n );\n }\n }\n\n subscribers[key]++;\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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"}
|
|
@@ -4,149 +4,91 @@ exports.HttpRequestCache = void 0;
|
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const default_storage_1 = require("./default-storage");
|
|
6
6
|
const request_times_1 = require("./request-times");
|
|
7
|
-
const serializeArg = (value) => {
|
|
8
|
-
const seen = new WeakMap();
|
|
9
|
-
let counter = 0;
|
|
10
|
-
const serialize = (v) => {
|
|
11
|
-
if (v === null) {
|
|
12
|
-
return 'null';
|
|
13
|
-
}
|
|
14
|
-
const t = typeof v;
|
|
15
|
-
if (t === 'number' || t === 'boolean') {
|
|
16
|
-
return String(v);
|
|
17
|
-
}
|
|
18
|
-
if (t === 'bigint') {
|
|
19
|
-
return `${v}n`;
|
|
20
|
-
}
|
|
21
|
-
if (t === 'undefined' || t === 'symbol' || t === 'function') {
|
|
22
|
-
return 'undef';
|
|
23
|
-
}
|
|
24
|
-
if (t === 'string') {
|
|
25
|
-
return `str:${v}`;
|
|
26
|
-
}
|
|
27
|
-
if (t !== 'object') {
|
|
28
|
-
return `${t}:${String(v)}`;
|
|
29
|
-
}
|
|
30
|
-
if (v instanceof Date) {
|
|
31
|
-
return `date:${v.toISOString()}`;
|
|
32
|
-
}
|
|
33
|
-
if (v instanceof RegExp) {
|
|
34
|
-
return `regexp:${v.toString()}`;
|
|
35
|
-
}
|
|
36
|
-
const path = seen.get(v);
|
|
37
|
-
if (path !== undefined) {
|
|
38
|
-
return `circ:${path}`;
|
|
39
|
-
}
|
|
40
|
-
seen.set(v, `v${counter++}`);
|
|
41
|
-
let out;
|
|
42
|
-
if (v instanceof Map) {
|
|
43
|
-
out = `map:${serialize(Array.from(v.entries()))}`;
|
|
44
|
-
}
|
|
45
|
-
else if (v instanceof Set) {
|
|
46
|
-
out = `set:${serialize(Array.from(v.values()))}`;
|
|
47
|
-
}
|
|
48
|
-
else if (Array.isArray(v)) {
|
|
49
|
-
out = `[${v.map(serialize).join(',')}]`;
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
out = `{${Object.keys(v).sort().map(k => `${serialize(k)}:${serialize(v[k])}`).join(',')}}`;
|
|
53
|
-
}
|
|
54
|
-
seen.delete(v);
|
|
55
|
-
return out;
|
|
56
|
-
};
|
|
57
|
-
return serialize(value);
|
|
58
|
-
};
|
|
59
|
-
const hashArgs = (input) => {
|
|
60
|
-
let h = 0x811c9dc5;
|
|
61
|
-
for (let i = 0; i < input.length; i++) {
|
|
62
|
-
h ^= input.charCodeAt(i);
|
|
63
|
-
h = Math.imul(h, 0x01000193);
|
|
64
|
-
}
|
|
65
|
-
return (h >>> 0).toString(36);
|
|
66
|
-
};
|
|
67
7
|
const HttpRequestCache = (optionsHandler) => {
|
|
68
8
|
return (target, methodName, descriptor) => {
|
|
69
|
-
if (
|
|
9
|
+
if (!((descriptor === null || descriptor === void 0 ? void 0 : descriptor.value) instanceof Function)) {
|
|
70
10
|
throw Error(`'@HttpRequestCache' can be applied only to the class method which returns an Observable`);
|
|
71
11
|
}
|
|
72
12
|
const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;
|
|
73
13
|
const originalMethod = descriptor.value;
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
14
|
+
const working = {};
|
|
15
|
+
const subscribers = {};
|
|
16
|
+
const removeTimers = {};
|
|
77
17
|
descriptor.value = function (...args) {
|
|
78
|
-
var _a, _b, _c
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (useDefaultStorage && !self.___storage___) {
|
|
83
|
-
self.___storage___ = new default_storage_1.DefaultStorage();
|
|
18
|
+
var _a, _b, _c;
|
|
19
|
+
const options = optionsHandler === null || optionsHandler === void 0 ? void 0 : optionsHandler.call(this, this, ...args);
|
|
20
|
+
if (!(options === null || options === void 0 ? void 0 : options.storage) && !target._____storage_____) {
|
|
21
|
+
target._____storage_____ = new default_storage_1.DefaultStorage();
|
|
84
22
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
self.___ttl_storage___ = new request_times_1.RequestTimes();
|
|
23
|
+
if ((options === null || options === void 0 ? void 0 : options.ttl) && !target._____ttl_storage_____) {
|
|
24
|
+
target._____ttl_storage_____ = new request_times_1.RequestTimes();
|
|
88
25
|
}
|
|
89
|
-
const storage = (_a = options === null || options === void 0 ? void 0 : options.storage) !== null && _a !== void 0 ? _a :
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (id === undefined) {
|
|
95
|
-
id = ++instanceIdCounter;
|
|
96
|
-
instanceIds.set(self, id);
|
|
97
|
-
}
|
|
98
|
-
instanceId = `_${id}`;
|
|
26
|
+
const storage = (_a = options === null || options === void 0 ? void 0 : options.storage) !== null && _a !== void 0 ? _a : target._____storage_____;
|
|
27
|
+
const key = `${cacheKeyPrefix}_${JSON.stringify(args)}`;
|
|
28
|
+
if (removeTimers[key]) {
|
|
29
|
+
clearTimeout(removeTimers[key]);
|
|
30
|
+
delete removeTimers[key];
|
|
99
31
|
}
|
|
100
|
-
const key = `${cacheKeyPrefix}${instanceId}_${hashArgs(serializeArg(args))}`;
|
|
101
|
-
const latest = (_b = latestCall[key]) !== null && _b !== void 0 ? _b : (latestCall[key] = { self, args });
|
|
102
|
-
latest.self = self;
|
|
103
|
-
latest.args = args;
|
|
104
32
|
let ttl = undefined;
|
|
105
|
-
if (
|
|
106
|
-
ttl =
|
|
33
|
+
if (options === null || options === void 0 ? void 0 : options.ttl) {
|
|
34
|
+
ttl = target._____ttl_storage_____.getItem(key);
|
|
107
35
|
if (!ttl) {
|
|
108
36
|
ttl = {
|
|
109
37
|
requestTime: Date.now(),
|
|
110
38
|
subject: new rxjs_1.Subject(),
|
|
111
39
|
};
|
|
112
40
|
}
|
|
113
|
-
else if (ttl.requestTime +
|
|
41
|
+
else if (ttl.requestTime + options.ttl <= Date.now()) {
|
|
42
|
+
working[key] = true;
|
|
114
43
|
ttl.requestTime = Date.now();
|
|
115
44
|
ttl.subject.next();
|
|
116
45
|
}
|
|
117
|
-
|
|
46
|
+
target._____ttl_storage_____.setItem(key, ttl);
|
|
118
47
|
}
|
|
119
|
-
const refreshOn = (0, rxjs_1.merge)((
|
|
48
|
+
const refreshOn = (0, rxjs_1.merge)((_b = options === null || options === void 0 ? void 0 : options.refreshOn) !== null && _b !== void 0 ? _b : rxjs_1.NEVER, (_c = ttl === null || ttl === void 0 ? void 0 : ttl.subject) !== null && _c !== void 0 ? _c : rxjs_1.NEVER);
|
|
120
49
|
let observable = storage.getItem(key);
|
|
121
50
|
if (!observable) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
: 0;
|
|
125
|
-
observable = refreshOn.pipe((0, rxjs_1.startWith)(true), (0, rxjs_1.switchMap)(() => originalMethod.apply(latest.self, latest.args)), (0, rxjs_1.finalize)(() => {
|
|
126
|
-
storage.deleteItem(key);
|
|
127
|
-
ttlStorage === null || ttlStorage === void 0 ? void 0 : ttlStorage.deleteItem(key);
|
|
128
|
-
delete latestCall[key];
|
|
51
|
+
observable = refreshOn.pipe((0, rxjs_1.startWith)(true), (0, rxjs_1.switchMap)(() => originalMethod.apply(this, [...args])), (0, rxjs_1.tap)(() => {
|
|
52
|
+
delete working[key];
|
|
129
53
|
}), (0, rxjs_1.share)({
|
|
130
54
|
connector: () => new rxjs_1.ReplaySubject(1),
|
|
131
55
|
resetOnComplete: false,
|
|
132
56
|
resetOnError: true,
|
|
133
|
-
resetOnRefCountZero: (options === null || options === void 0 ? void 0 : options.refCount)
|
|
134
|
-
?
|
|
57
|
+
resetOnRefCountZero: !(options === null || options === void 0 ? void 0 : options.refCount)
|
|
58
|
+
? false
|
|
59
|
+
: options.refCountDelay != null
|
|
135
60
|
? () => (0, rxjs_1.timer)(options.refCountDelay)
|
|
136
|
-
: true
|
|
137
|
-
: ttlRemaining > 0
|
|
138
|
-
? () => (0, rxjs_1.timer)(ttlRemaining)
|
|
139
61
|
: true,
|
|
62
|
+
}), (0, rxjs_1.filter)(() => !working[key]), (0, rxjs_1.finalize)(() => {
|
|
63
|
+
subscribers[key]--;
|
|
64
|
+
if (subscribers[key] <= 0) {
|
|
65
|
+
delete subscribers[key];
|
|
66
|
+
if (options === null || options === void 0 ? void 0 : options.refCount) {
|
|
67
|
+
const unset = () => {
|
|
68
|
+
var _a;
|
|
69
|
+
storage.deleteItem(key);
|
|
70
|
+
(_a = target._____ttl_storage_____) === null || _a === void 0 ? void 0 : _a.deleteItem(key);
|
|
71
|
+
delete removeTimers[key];
|
|
72
|
+
};
|
|
73
|
+
if (options.refCountDelay == null) {
|
|
74
|
+
unset();
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
removeTimers[key] = setTimeout(unset, options.refCountDelay);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
140
81
|
}));
|
|
141
82
|
storage.setItem(key, observable);
|
|
142
83
|
if (options === null || options === void 0 ? void 0 : options.windowTime) {
|
|
143
84
|
setTimeout(() => {
|
|
85
|
+
var _a;
|
|
144
86
|
storage.deleteItem(key);
|
|
145
|
-
|
|
146
|
-
delete latestCall[key];
|
|
87
|
+
(_a = target._____ttl_storage_____) === null || _a === void 0 ? void 0 : _a.deleteItem(key);
|
|
147
88
|
}, options.windowTime);
|
|
148
89
|
}
|
|
149
90
|
}
|
|
91
|
+
subscribers[key]++;
|
|
150
92
|
return observable;
|
|
151
93
|
};
|
|
152
94
|
return descriptor;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-request-cache.decorator.js","sourceRoot":"","sources":["../../../projects/http-request-cache/src/lib/http-request-cache.decorator.ts"],"names":[],"mappings":";;;AAAA,+
|
|
1
|
+
{"version":3,"file":"http-request-cache.decorator.js","sourceRoot":"","sources":["../../../projects/http-request-cache/src/lib/http-request-cache.decorator.ts"],"names":[],"mappings":"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"}
|