@modern-js/runtime-utils 2.68.0 → 2.68.2

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.
@@ -1,8 +1,14 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
6
12
  var __copyProps = (to, from, except, desc) => {
7
13
  if (from && typeof from === "object" || typeof from === "function") {
8
14
  for (let key of __getOwnPropNames(from))
@@ -12,11 +18,26 @@ var __copyProps = (to, from, except, desc) => {
12
18
  return to;
13
19
  };
14
20
  var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
15
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
16
30
  var remixRouter_exports = {};
31
+ __export(remixRouter_exports, {
32
+ DEFERRED_SYMBOL: () => DEFERRED_SYMBOL
33
+ });
17
34
  module.exports = __toCommonJS(remixRouter_exports);
18
35
  __reExport(remixRouter_exports, require("@remix-run/router"), module.exports);
36
+ var remixRouter = __toESM(require("@remix-run/router"));
37
+ const symbolName = "UNSAFE_DEFERRED_SYMBOL";
38
+ const DEFERRED_SYMBOL = symbolName in remixRouter ? remixRouter[symbolName] : Symbol("deferred");
19
39
  // Annotate the CommonJS export names for ESM import in node:
20
40
  0 && (module.exports = {
41
+ DEFERRED_SYMBOL,
21
42
  ...require("@remix-run/router")
22
43
  });
@@ -43,50 +43,6 @@ const CacheTime = {
43
43
  WEEK: 7 * 24 * 60 * 60 * 1e3,
44
44
  MONTH: 30 * 24 * 60 * 60 * 1e3
45
45
  };
46
- const isServer = typeof window === "undefined";
47
- const requestCacheMap = /* @__PURE__ */ new WeakMap();
48
- let lruCache;
49
- let cacheConfig = {
50
- maxSize: CacheSize.GB
51
- };
52
- const tagKeyMap = /* @__PURE__ */ new Map();
53
- function addTagKeyRelation(tag, key) {
54
- let keys = tagKeyMap.get(tag);
55
- if (!keys) {
56
- keys = /* @__PURE__ */ new Set();
57
- tagKeyMap.set(tag, keys);
58
- }
59
- keys.add(key);
60
- }
61
- function configureCache(config) {
62
- cacheConfig = {
63
- ...cacheConfig,
64
- ...config
65
- };
66
- }
67
- function getLRUCache() {
68
- if (!lruCache) {
69
- var _cacheConfig_maxSize;
70
- lruCache = new import_lru_cache.LRUCache({
71
- maxSize: (_cacheConfig_maxSize = cacheConfig.maxSize) !== null && _cacheConfig_maxSize !== void 0 ? _cacheConfig_maxSize : CacheSize.GB,
72
- sizeCalculation: (value) => {
73
- if (!value.size) {
74
- return 1;
75
- }
76
- let size = 0;
77
- for (const [k, item] of value.entries()) {
78
- size += k.length * 2;
79
- size += estimateObjectSize(item.data);
80
- size += 8;
81
- }
82
- return size;
83
- },
84
- updateAgeOnGet: true,
85
- updateAgeOnHas: true
86
- });
87
- }
88
- return lruCache;
89
- }
90
46
  function estimateObjectSize(data) {
91
47
  const type = typeof data;
92
48
  if (type === "number")
@@ -114,6 +70,67 @@ function estimateObjectSize(data) {
114
70
  }
115
71
  return 1;
116
72
  }
73
+ class MemoryContainer {
74
+ async get(key) {
75
+ return this.lru.get(key);
76
+ }
77
+ async set(key, value, options) {
78
+ if (options === null || options === void 0 ? void 0 : options.ttl) {
79
+ this.lru.set(key, value, {
80
+ ttl: options.ttl * 1e3
81
+ });
82
+ } else {
83
+ this.lru.set(key, value);
84
+ }
85
+ }
86
+ async has(key) {
87
+ return this.lru.has(key);
88
+ }
89
+ async delete(key) {
90
+ return this.lru.delete(key);
91
+ }
92
+ async clear() {
93
+ this.lru.clear();
94
+ }
95
+ constructor(options) {
96
+ var _options_maxSize;
97
+ this.lru = new import_lru_cache.LRUCache({
98
+ maxSize: (_options_maxSize = options === null || options === void 0 ? void 0 : options.maxSize) !== null && _options_maxSize !== void 0 ? _options_maxSize : CacheSize.GB,
99
+ sizeCalculation: estimateObjectSize,
100
+ updateAgeOnGet: true,
101
+ updateAgeOnHas: true
102
+ });
103
+ }
104
+ }
105
+ const isServer = typeof window === "undefined";
106
+ const requestCacheMap = /* @__PURE__ */ new WeakMap();
107
+ const TAG_PREFIX = "tag:";
108
+ const CACHE_PREFIX = "modernjs_cache:";
109
+ const ongoingRevalidations = /* @__PURE__ */ new Map();
110
+ let storage;
111
+ let cacheConfig = {
112
+ maxSize: CacheSize.GB
113
+ };
114
+ function getStorage() {
115
+ if (storage) {
116
+ return storage;
117
+ }
118
+ if (cacheConfig.container) {
119
+ storage = cacheConfig.container;
120
+ } else {
121
+ storage = new MemoryContainer({
122
+ maxSize: cacheConfig.maxSize
123
+ });
124
+ }
125
+ return storage;
126
+ }
127
+ function configureCache(config) {
128
+ cacheConfig = {
129
+ ...cacheConfig,
130
+ ...config
131
+ };
132
+ storage = void 0;
133
+ }
117
134
  function generateKey(args) {
118
135
  return JSON.stringify(args, (_, value) => {
119
136
  if (value && typeof value === "object" && !Array.isArray(value)) {
@@ -125,24 +142,22 @@ function generateKey(args) {
125
142
  return value;
126
143
  });
127
144
  }
145
+ function generateStableFunctionId(fn) {
146
+ const fnString = fn.toString();
147
+ let hash = 0;
148
+ for (let i = 0; i < fnString.length; i++) {
149
+ const char = fnString.charCodeAt(i);
150
+ hash = (hash << 5) - hash + char;
151
+ hash = hash & hash;
152
+ }
153
+ return `fn_${fn.name || "anonymous"}_${Math.abs(hash).toString(36)}`;
154
+ }
128
155
  function cache(fn, options) {
129
- const { tag = "default", maxAge = CacheTime.MINUTE * 5, revalidate = 0, customKey, onCache, getKey } = options || {};
130
- const store = getLRUCache();
131
- const tags = Array.isArray(tag) ? tag : [
132
- tag
133
- ];
134
- const getCacheKey = (args, generatedKey) => {
135
- return customKey ? customKey({
136
- params: args,
137
- fn,
138
- generatedKey
139
- }) : fn;
140
- };
141
156
  return async (...args) => {
142
157
  if (isServer && typeof options === "undefined") {
143
158
  var _storage_useContext;
144
- const storage = (0, import_async_storage.getAsyncLocalStorage)();
145
- const request = storage === null || storage === void 0 ? void 0 : (_storage_useContext = storage.useContext()) === null || _storage_useContext === void 0 ? void 0 : _storage_useContext.request;
159
+ const storage2 = (0, import_async_storage.getAsyncLocalStorage)();
160
+ const request = storage2 === null || storage2 === void 0 ? void 0 : (_storage_useContext = storage2.useContext()) === null || _storage_useContext === void 0 ? void 0 : _storage_useContext.request;
146
161
  if (request) {
147
162
  let shouldDisableCaching = false;
148
163
  if (cacheConfig.unstable_shouldDisable) {
@@ -178,123 +193,231 @@ function cache(fn, options) {
178
193
  }
179
194
  }
180
195
  } else if (typeof options !== "undefined") {
181
- const genKey = getKey ? getKey(...args) : generateKey(args);
182
- const now = Date.now();
183
- const cacheKey = getCacheKey(args, genKey);
184
- const finalKey = typeof cacheKey === "function" ? genKey : cacheKey;
185
- tags.forEach((t) => addTagKeyRelation(t, cacheKey));
186
- let cacheStore = store.get(cacheKey);
187
- if (!cacheStore) {
188
- cacheStore = /* @__PURE__ */ new Map();
189
- }
190
- const storeKey = customKey && typeof cacheKey === "symbol" ? "symbol-key" : genKey;
191
- let shouldDisableCaching = false;
192
- if (isServer && cacheConfig.unstable_shouldDisable) {
193
- var _storage_useContext1;
194
- const storage = (0, import_async_storage.getAsyncLocalStorage)();
195
- const request = storage === null || storage === void 0 ? void 0 : (_storage_useContext1 = storage.useContext()) === null || _storage_useContext1 === void 0 ? void 0 : _storage_useContext1.request;
196
- if (request) {
197
- shouldDisableCaching = await cacheConfig.unstable_shouldDisable({
198
- request
196
+ try {
197
+ const { tag, maxAge = CacheTime.MINUTE * 5, revalidate = 0, customKey, onCache, getKey, unstable_shouldCache } = options;
198
+ let missReason;
199
+ const currentStorage = getStorage();
200
+ const now = Date.now();
201
+ const tags = tag ? Array.isArray(tag) ? tag : [
202
+ tag
203
+ ] : [];
204
+ const genKey = getKey ? getKey(...args) : generateKey(args);
205
+ let finalKey;
206
+ if (customKey) {
207
+ finalKey = customKey({
208
+ params: args,
209
+ fn,
210
+ generatedKey: genKey
199
211
  });
212
+ } else {
213
+ const functionId = generateStableFunctionId(fn);
214
+ finalKey = `${functionId}:${genKey}`;
200
215
  }
201
- }
202
- const cached = cacheStore.get(storeKey);
203
- if (cached && !shouldDisableCaching) {
204
- const age = now - cached.timestamp;
205
- if (age < maxAge) {
206
- if (onCache) {
207
- onCache({
208
- status: "hit",
209
- key: finalKey,
210
- params: args,
211
- result: cached.data
216
+ const storageKey = `${CACHE_PREFIX}${finalKey}`;
217
+ let shouldDisableCaching = false;
218
+ if (isServer && cacheConfig.unstable_shouldDisable) {
219
+ var _asyncStorage_useContext;
220
+ const asyncStorage = (0, import_async_storage.getAsyncLocalStorage)();
221
+ const request = asyncStorage === null || asyncStorage === void 0 ? void 0 : (_asyncStorage_useContext = asyncStorage.useContext()) === null || _asyncStorage_useContext === void 0 ? void 0 : _asyncStorage_useContext.request;
222
+ if (request) {
223
+ shouldDisableCaching = await cacheConfig.unstable_shouldDisable({
224
+ request
212
225
  });
213
226
  }
214
- return cached.data;
215
227
  }
216
- if (revalidate > 0 && age < maxAge + revalidate) {
217
- if (onCache) {
218
- onCache({
219
- status: "stale",
220
- key: finalKey,
221
- params: args,
222
- result: cached.data
223
- });
224
- }
225
- if (!cached.isRevalidating) {
226
- cached.isRevalidating = true;
227
- Promise.resolve().then(async () => {
228
- try {
229
- const newData = await fn(...args);
230
- cacheStore.set(storeKey, {
231
- data: newData,
232
- timestamp: Date.now(),
233
- isRevalidating: false
228
+ if (!shouldDisableCaching) {
229
+ const cached = await currentStorage.get(storageKey);
230
+ if (cached) {
231
+ try {
232
+ const cacheItem = cached;
233
+ const age = now - cacheItem.timestamp;
234
+ if (age < maxAge) {
235
+ onCache === null || onCache === void 0 ? void 0 : onCache({
236
+ status: "hit",
237
+ key: finalKey,
238
+ params: args,
239
+ result: cacheItem.data
240
+ });
241
+ return cacheItem.data;
242
+ }
243
+ if (revalidate > 0 && age < maxAge + revalidate) {
244
+ onCache === null || onCache === void 0 ? void 0 : onCache({
245
+ status: "stale",
246
+ key: finalKey,
247
+ params: args,
248
+ result: cacheItem.data
234
249
  });
235
- store.set(cacheKey, cacheStore);
236
- } catch (error) {
237
- cached.isRevalidating = false;
238
- if (isServer) {
239
- var _storage_useContext_monitors, _storage_useContext2;
240
- const storage = (0, import_async_storage.getAsyncLocalStorage)();
241
- storage === null || storage === void 0 ? void 0 : (_storage_useContext2 = storage.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(error.message);
242
- } else {
243
- console.error("Background revalidation failed:", error);
250
+ if (!ongoingRevalidations.has(storageKey)) {
251
+ const revalidationPromise = (async () => {
252
+ try {
253
+ const newData = await fn(...args);
254
+ let shouldCache = true;
255
+ if (unstable_shouldCache) {
256
+ shouldCache = await unstable_shouldCache({
257
+ params: args,
258
+ result: newData
259
+ });
260
+ }
261
+ if (shouldCache) {
262
+ await setCacheItem(currentStorage, storageKey, newData, tags, maxAge, revalidate);
263
+ }
264
+ } catch (error) {
265
+ if (isServer) {
266
+ var _asyncStorage_useContext_monitors, _asyncStorage_useContext2;
267
+ const asyncStorage = (0, import_async_storage.getAsyncLocalStorage)();
268
+ asyncStorage === null || asyncStorage === void 0 ? void 0 : (_asyncStorage_useContext2 = asyncStorage.useContext()) === null || _asyncStorage_useContext2 === void 0 ? void 0 : (_asyncStorage_useContext_monitors = _asyncStorage_useContext2.monitors) === null || _asyncStorage_useContext_monitors === void 0 ? void 0 : _asyncStorage_useContext_monitors.error(error.message);
269
+ } else {
270
+ console.error("Background revalidation failed:", error);
271
+ }
272
+ } finally {
273
+ ongoingRevalidations.delete(storageKey);
274
+ }
275
+ })();
276
+ ongoingRevalidations.set(storageKey, revalidationPromise);
244
277
  }
278
+ return cacheItem.data;
245
279
  }
280
+ missReason = 3;
281
+ } catch (error) {
282
+ console.warn("Failed to parse cached data:", error);
283
+ missReason = 4;
284
+ }
285
+ } else {
286
+ missReason = 2;
287
+ }
288
+ } else {
289
+ missReason = 1;
290
+ }
291
+ const data = await fn(...args);
292
+ if (!shouldDisableCaching) {
293
+ let shouldCache = true;
294
+ if (unstable_shouldCache) {
295
+ shouldCache = await unstable_shouldCache({
296
+ params: args,
297
+ result: data
246
298
  });
247
299
  }
248
- return cached.data;
300
+ if (shouldCache) {
301
+ await setCacheItem(currentStorage, storageKey, data, tags, maxAge, revalidate);
302
+ }
249
303
  }
250
- }
251
- const data = await fn(...args);
252
- if (!shouldDisableCaching) {
253
- cacheStore.set(storeKey, {
254
- data,
255
- timestamp: now,
256
- isRevalidating: false
257
- });
258
- store.set(cacheKey, cacheStore);
259
- }
260
- if (onCache) {
261
- onCache({
304
+ onCache === null || onCache === void 0 ? void 0 : onCache({
262
305
  status: "miss",
263
306
  key: finalKey,
264
307
  params: args,
265
- result: data
308
+ result: data,
309
+ reason: missReason
266
310
  });
311
+ return data;
312
+ } catch (error) {
313
+ console.warn("Cache operation failed, falling back to direct execution:", error);
314
+ const data = await fn(...args);
315
+ const { onCache } = options;
316
+ try {
317
+ onCache === null || onCache === void 0 ? void 0 : onCache({
318
+ status: "miss",
319
+ key: "cache_failed",
320
+ params: args,
321
+ result: data,
322
+ reason: 5
323
+ });
324
+ } catch (callbackError) {
325
+ console.warn("Failed to call onCache callback:", callbackError);
326
+ }
327
+ return data;
267
328
  }
268
- return data;
269
329
  } else {
270
330
  console.warn("The cache function will not work because it runs on the browser and there are no options are provided.");
271
331
  return fn(...args);
272
332
  }
273
333
  };
274
334
  }
335
+ async function setCacheItem(storage2, storageKey, data, tags, maxAge, revalidate) {
336
+ const newItem = {
337
+ data,
338
+ timestamp: Date.now(),
339
+ tags: tags.length > 0 ? tags : void 0
340
+ };
341
+ const ttl = (maxAge + revalidate) / 1e3;
342
+ await storage2.set(storageKey, newItem, {
343
+ ttl: ttl > 0 ? ttl : void 0
344
+ });
345
+ await updateTagRelationships(storage2, storageKey, tags);
346
+ }
347
+ async function updateTagRelationships(storage2, storageKey, tags) {
348
+ for (const tag of tags) {
349
+ const tagStoreKey = `${TAG_PREFIX}${tag}`;
350
+ const keyList = await storage2.get(tagStoreKey);
351
+ const keyArray = keyList || [];
352
+ if (!keyArray.includes(storageKey)) {
353
+ keyArray.push(storageKey);
354
+ }
355
+ await storage2.set(tagStoreKey, keyArray);
356
+ }
357
+ }
358
+ async function removeKeyFromTags(storage2, storageKey, tags) {
359
+ for (const tag of tags) {
360
+ const tagStoreKey = `${TAG_PREFIX}${tag}`;
361
+ const keyList = await storage2.get(tagStoreKey);
362
+ if (keyList) {
363
+ try {
364
+ const keyArray = Array.isArray(keyList) ? keyList : [];
365
+ const updatedKeyList = keyArray.filter((key) => key !== storageKey);
366
+ if (updatedKeyList.length > 0) {
367
+ await storage2.set(tagStoreKey, updatedKeyList);
368
+ } else {
369
+ await storage2.delete(tagStoreKey);
370
+ }
371
+ } catch (error) {
372
+ console.warn(`Failed to process tag key list for tag ${tag}:`, error);
373
+ }
374
+ }
375
+ }
376
+ }
275
377
  function withRequestCache(handler) {
276
378
  if (!isServer) {
277
379
  return handler;
278
380
  }
279
381
  return async (req, ...args) => {
280
- const storage = (0, import_async_storage.getAsyncLocalStorage)();
281
- return storage.run({
382
+ const storage2 = (0, import_async_storage.getAsyncLocalStorage)();
383
+ return storage2.run({
282
384
  request: req
283
385
  }, () => handler(req, ...args));
284
386
  };
285
387
  }
286
- function revalidateTag(tag) {
287
- const keys = tagKeyMap.get(tag);
288
- if (keys) {
289
- keys.forEach((key) => {
290
- lruCache === null || lruCache === void 0 ? void 0 : lruCache.delete(key);
291
- });
388
+ async function revalidateTag(tag) {
389
+ const currentStorage = getStorage();
390
+ const tagStoreKey = `${TAG_PREFIX}${tag}`;
391
+ const keyList = await currentStorage.get(tagStoreKey);
392
+ if (keyList) {
393
+ try {
394
+ const keyArray = Array.isArray(keyList) ? keyList : [];
395
+ for (const cacheKey of keyArray) {
396
+ const cached = await currentStorage.get(cacheKey);
397
+ if (cached) {
398
+ try {
399
+ const cacheItem = cached;
400
+ if (cacheItem.tags) {
401
+ const otherTags = cacheItem.tags.filter((t) => t !== tag);
402
+ await removeKeyFromTags(currentStorage, cacheKey, otherTags);
403
+ }
404
+ } catch (error) {
405
+ console.warn("Failed to parse cached data while revalidating:", error);
406
+ }
407
+ }
408
+ await currentStorage.delete(cacheKey);
409
+ }
410
+ await currentStorage.delete(tagStoreKey);
411
+ } catch (error) {
412
+ console.warn("Failed to process tag key list:", error);
413
+ }
292
414
  }
293
415
  }
294
- function clearStore() {
295
- lruCache === null || lruCache === void 0 ? void 0 : lruCache.clear();
296
- lruCache = void 0;
297
- tagKeyMap.clear();
416
+ async function clearStore() {
417
+ const currentStorage = getStorage();
418
+ await currentStorage.clear();
419
+ storage = void 0;
420
+ ongoingRevalidations.clear();
298
421
  }
299
422
  // Annotate the CommonJS export names for ESM import in node:
300
423
  0 && (module.exports = {
@@ -1 +1,7 @@
1
1
  export * from "@remix-run/router";
2
+ import * as remixRouter from "@remix-run/router";
3
+ var symbolName = "UNSAFE_DEFERRED_SYMBOL";
4
+ var DEFERRED_SYMBOL = symbolName in remixRouter ? remixRouter[symbolName] : Symbol("deferred");
5
+ export {
6
+ DEFERRED_SYMBOL
7
+ };