@kovalenko/http-request-cache
Version:
TS decorator for caching logic of API calls.
71 lines • 4.06 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpRequestCache = void 0;
const rxjs_1 = require("rxjs");
const default_storage_1 = require("./default-storage");
const request_times_1 = require("./request-times");
const HttpRequestCache = (optionsHandler) => {
return (target, methodName, descriptor) => {
if (!((descriptor === null || descriptor === void 0 ? void 0 : descriptor.value) instanceof Function)) {
throw Error(`'@HttpRequestCache' can be applied only to the class method which returns an Observable`);
}
const cacheKeyPrefix = `${target.constructor.name}_${methodName}`;
const originalMethod = descriptor.value;
const working = {};
let subscribers = 0;
descriptor.value = function (...args) {
var _a, _b, _c, _d, _e;
const options = optionsHandler === null || optionsHandler === void 0 ? void 0 : optionsHandler.call(this, this, ...args);
if (!(options === null || options === void 0 ? void 0 : options.storage) && !target._____storage_____) {
target._____storage_____ = new default_storage_1.DefaultStorage();
}
if ((options === null || options === void 0 ? void 0 : options.ttl) && !target._____ttl_storage_____) {
target._____ttl_storage_____ = new request_times_1.RequestTimes();
}
const storage = (_a = options === null || options === void 0 ? void 0 : options.storage) !== null && _a !== void 0 ? _a : target._____storage_____;
const key = `${cacheKeyPrefix}_${JSON.stringify(args)}`;
let ttl = undefined;
if (options === null || options === void 0 ? void 0 : options.ttl) {
ttl = target._____ttl_storage_____.getItem(key);
if (!ttl) {
ttl = {
requestTime: Date.now(),
subject: new rxjs_1.Subject(),
};
}
else if (ttl.requestTime + options.ttl <= Date.now()) {
working[key] = true;
ttl.requestTime = Date.now();
ttl.subject.next();
}
target._____ttl_storage_____.setItem(key, ttl);
}
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);
let observable = storage.getItem(key);
if (!observable) {
observable = refreshOn.pipe((0, rxjs_1.startWith)(true), (0, rxjs_1.switchMap)(() => originalMethod.apply(this, [...args])), (0, rxjs_1.tap)(() => {
delete working[key];
}), (0, rxjs_1.shareReplay)({
bufferSize: 1,
refCount: (_d = options === null || options === void 0 ? void 0 : options.refCount) !== null && _d !== void 0 ? _d : false,
windowTime: (_e = options === null || options === void 0 ? void 0 : options.windowTime) !== null && _e !== void 0 ? _e : Infinity,
}), (0, rxjs_1.filter)(() => {
return !working[key];
}), (0, rxjs_1.finalize)(() => {
var _a;
subscribers--;
if (subscribers === 0 && (options === null || options === void 0 ? void 0 : options.refCount)) {
storage.deleteItem(key);
(_a = target._____ttl_storage_____) === null || _a === void 0 ? void 0 : _a.deleteItem(key);
}
}));
storage.setItem(key, observable);
}
subscribers++;
return observable;
};
return descriptor;
};
};
exports.HttpRequestCache = HttpRequestCache;
//# sourceMappingURL=http-request-cache.decorator.js.map