@modern-js/runtime-utils
Version:
A Progressive React Framework for modern web development.
443 lines (442 loc) • 14.5 kB
JavaScript
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
import { _ as _instanceof } from "@swc/helpers/_/_instanceof";
import { _ as _object_spread } from "@swc/helpers/_/_object_spread";
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
import { _ as _to_consumable_array } from "@swc/helpers/_/_to_consumable_array";
import { _ as _type_of } from "@swc/helpers/_/_type_of";
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
import { LRUCache } from "lru-cache";
import { getAsyncLocalStorage } from "./async_storage";
var CacheSize = {
KB: 1024,
MB: 1024 * 1024,
GB: 1024 * 1024 * 1024
};
var CacheTime = {
SECOND: 1e3,
MINUTE: 60 * 1e3,
HOUR: 60 * 60 * 1e3,
DAY: 24 * 60 * 60 * 1e3,
WEEK: 7 * 24 * 60 * 60 * 1e3,
MONTH: 30 * 24 * 60 * 60 * 1e3
};
var isServer = typeof window === "undefined";
var requestCacheMap = /* @__PURE__ */ new WeakMap();
var lruCache;
var cacheConfig = {
maxSize: CacheSize.GB
};
var tagKeyMap = /* @__PURE__ */ new Map();
function addTagKeyRelation(tag, key) {
var keys = tagKeyMap.get(tag);
if (!keys) {
keys = /* @__PURE__ */ new Set();
tagKeyMap.set(tag, keys);
}
keys.add(key);
}
function configureCache(config) {
cacheConfig = _object_spread({}, cacheConfig, config);
}
function getLRUCache() {
if (!lruCache) {
var _cacheConfig_maxSize;
lruCache = new LRUCache({
maxSize: (_cacheConfig_maxSize = cacheConfig.maxSize) !== null && _cacheConfig_maxSize !== void 0 ? _cacheConfig_maxSize : CacheSize.GB,
sizeCalculation: function(value) {
if (!value.size) {
return 1;
}
var size = 0;
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = void 0;
try {
for (var _iterator = value.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _step_value = _sliced_to_array(_step.value, 2), k = _step_value[0], item = _step_value[1];
size += k.length * 2;
size += estimateObjectSize(item.data);
size += 8;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return != null) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return size;
},
updateAgeOnGet: true,
updateAgeOnHas: true
});
}
return lruCache;
}
function estimateObjectSize(data) {
var type = typeof data === "undefined" ? "undefined" : _type_of(data);
if (type === "number")
return 8;
if (type === "boolean")
return 4;
if (type === "string")
return Math.max(data.length * 2, 1);
if (data === null || data === void 0)
return 1;
if (ArrayBuffer.isView(data)) {
return Math.max(data.byteLength, 1);
}
if (Array.isArray(data)) {
return Math.max(data.reduce(function(acc, item) {
return acc + estimateObjectSize(item);
}, 0), 1);
}
if (_instanceof(data, Map) || _instanceof(data, Set)) {
return 1024;
}
if (_instanceof(data, Date)) {
return 8;
}
if (type === "object") {
return Math.max(Object.entries(data).reduce(function(acc, param) {
var _param = _sliced_to_array(param, 2), key = _param[0], value = _param[1];
return acc + key.length * 2 + estimateObjectSize(value);
}, 0), 1);
}
return 1;
}
function generateKey(args) {
return JSON.stringify(args, function(_, value) {
if (value && (typeof value === "undefined" ? "undefined" : _type_of(value)) === "object" && !Array.isArray(value)) {
return Object.keys(value).sort().reduce(function(result, key) {
result[key] = value[key];
return result;
}, {});
}
return value;
});
}
function cache(fn, options) {
var _ref = options || {}, _ref_tag = _ref.tag, tag = _ref_tag === void 0 ? "default" : _ref_tag, _ref_maxAge = _ref.maxAge, maxAge = _ref_maxAge === void 0 ? CacheTime.MINUTE * 5 : _ref_maxAge, _ref_revalidate = _ref.revalidate, revalidate = _ref_revalidate === void 0 ? 0 : _ref_revalidate, customKey = _ref.customKey, onCache = _ref.onCache, getKey = _ref.getKey;
var store = getLRUCache();
var tags = Array.isArray(tag) ? tag : [
tag
];
var getCacheKey = function(args, generatedKey) {
return customKey ? customKey({
params: args,
fn,
generatedKey
}) : fn;
};
return /* @__PURE__ */ _async_to_generator(function() {
var _len, args, _key, _storage_useContext, storage, request, shouldDisableCaching, requestCache, fnCache, key, promise, data, error, genKey, now, cacheKey, finalKey, cacheStore, storeKey, shouldDisableCaching1, _storage_useContext1, storage1, request1, cached, age, data1;
var _arguments = arguments;
return _ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
for (_len = _arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = _arguments[_key];
}
if (!(isServer && typeof options === "undefined"))
return [
3,
7
];
storage = getAsyncLocalStorage();
request = storage === null || storage === void 0 ? void 0 : (_storage_useContext = storage.useContext()) === null || _storage_useContext === void 0 ? void 0 : _storage_useContext.request;
if (!request)
return [
3,
6
];
shouldDisableCaching = false;
if (!cacheConfig.unstable_shouldDisable)
return [
3,
2
];
return [
4,
cacheConfig.unstable_shouldDisable({
request
})
];
case 1:
shouldDisableCaching = _state.sent();
_state.label = 2;
case 2:
if (shouldDisableCaching) {
return [
2,
fn.apply(void 0, _to_consumable_array(args))
];
}
requestCache = requestCacheMap.get(request);
if (!requestCache) {
requestCache = /* @__PURE__ */ new Map();
requestCacheMap.set(request, requestCache);
}
fnCache = requestCache.get(fn);
if (!fnCache) {
fnCache = /* @__PURE__ */ new Map();
requestCache.set(fn, fnCache);
}
key = generateKey(args);
if (fnCache.has(key)) {
return [
2,
fnCache.get(key)
];
}
promise = fn.apply(void 0, _to_consumable_array(args));
fnCache.set(key, promise);
_state.label = 3;
case 3:
_state.trys.push([
3,
5,
,
6
]);
return [
4,
promise
];
case 4:
data = _state.sent();
return [
2,
data
];
case 5:
error = _state.sent();
fnCache.delete(key);
throw error;
case 6:
return [
3,
12
];
case 7:
if (!(typeof options !== "undefined"))
return [
3,
11
];
genKey = getKey ? getKey.apply(void 0, _to_consumable_array(args)) : generateKey(args);
now = Date.now();
cacheKey = getCacheKey(args, genKey);
finalKey = typeof cacheKey === "function" ? genKey : cacheKey;
tags.forEach(function(t) {
return addTagKeyRelation(t, cacheKey);
});
cacheStore = store.get(cacheKey);
if (!cacheStore) {
cacheStore = /* @__PURE__ */ new Map();
}
storeKey = customKey && (typeof cacheKey === "undefined" ? "undefined" : _type_of(cacheKey)) === "symbol" ? "symbol-key" : genKey;
shouldDisableCaching1 = false;
if (!(isServer && cacheConfig.unstable_shouldDisable))
return [
3,
9
];
storage1 = getAsyncLocalStorage();
request1 = storage1 === null || storage1 === void 0 ? void 0 : (_storage_useContext1 = storage1.useContext()) === null || _storage_useContext1 === void 0 ? void 0 : _storage_useContext1.request;
if (!request1)
return [
3,
9
];
return [
4,
cacheConfig.unstable_shouldDisable({
request: request1
})
];
case 8:
shouldDisableCaching1 = _state.sent();
_state.label = 9;
case 9:
cached = cacheStore.get(storeKey);
if (cached && !shouldDisableCaching1) {
age = now - cached.timestamp;
if (age < maxAge) {
if (onCache) {
onCache({
status: "hit",
key: finalKey,
params: args,
result: cached.data
});
}
return [
2,
cached.data
];
}
if (revalidate > 0 && age < maxAge + revalidate) {
if (onCache) {
onCache({
status: "stale",
key: finalKey,
params: args,
result: cached.data
});
}
if (!cached.isRevalidating) {
cached.isRevalidating = true;
Promise.resolve().then(/* @__PURE__ */ _async_to_generator(function() {
var newData, error2, _storage_useContext_monitors, _storage_useContext2, storage2;
return _ts_generator(this, function(_state2) {
switch (_state2.label) {
case 0:
_state2.trys.push([
0,
2,
,
3
]);
return [
4,
fn.apply(void 0, _to_consumable_array(args))
];
case 1:
newData = _state2.sent();
cacheStore.set(storeKey, {
data: newData,
timestamp: Date.now(),
isRevalidating: false
});
store.set(cacheKey, cacheStore);
return [
3,
3
];
case 2:
error2 = _state2.sent();
cached.isRevalidating = false;
if (isServer) {
;
storage2 = getAsyncLocalStorage();
storage2 === null || storage2 === void 0 ? void 0 : (_storage_useContext2 = storage2.useContext()) === null || _storage_useContext2 === void 0 ? void 0 : (_storage_useContext_monitors = _storage_useContext2.monitors) === null || _storage_useContext_monitors === void 0 ? void 0 : _storage_useContext_monitors.error(error2.message);
} else {
console.error("Background revalidation failed:", error2);
}
return [
3,
3
];
case 3:
return [
2
];
}
});
}));
}
return [
2,
cached.data
];
}
}
return [
4,
fn.apply(void 0, _to_consumable_array(args))
];
case 10:
data1 = _state.sent();
if (!shouldDisableCaching1) {
cacheStore.set(storeKey, {
data: data1,
timestamp: now,
isRevalidating: false
});
store.set(cacheKey, cacheStore);
}
if (onCache) {
onCache({
status: "miss",
key: finalKey,
params: args,
result: data1
});
}
return [
2,
data1
];
case 11:
console.warn("The cache function will not work because it runs on the browser and there are no options are provided.");
return [
2,
fn.apply(void 0, _to_consumable_array(args))
];
case 12:
return [
2
];
}
});
});
}
function withRequestCache(handler) {
if (!isServer) {
return handler;
}
return function() {
var _ref = _async_to_generator(function(req) {
var _len, args, _key, storage;
var _arguments = arguments;
return _ts_generator(this, function(_state) {
for (_len = _arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = _arguments[_key];
}
storage = getAsyncLocalStorage();
return [
2,
storage.run({
request: req
}, function() {
return handler.apply(void 0, [
req
].concat(_to_consumable_array(args)));
})
];
});
});
return function(req) {
return _ref.apply(this, arguments);
};
}();
}
function revalidateTag(tag) {
var keys = tagKeyMap.get(tag);
if (keys) {
keys.forEach(function(key) {
lruCache === null || lruCache === void 0 ? void 0 : lruCache.delete(key);
});
}
}
function clearStore() {
lruCache === null || lruCache === void 0 ? void 0 : lruCache.clear();
lruCache = void 0;
tagKeyMap.clear();
}
export {
CacheSize,
CacheTime,
cache,
clearStore,
configureCache,
generateKey,
revalidateTag,
withRequestCache
};