UNPKG

@modern-js/runtime-utils

Version:

A Progressive React Framework for modern web development.

443 lines (442 loc) • 14.5 kB
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 };