@keq-request/cache 5.0.0-alpha.22 → 5.0.0-alpha.23

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.
Files changed (95) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cache-entry/cache-entry.d.ts.map +1 -1
  3. package/dist/cache.d.ts +13 -4
  4. package/dist/cache.d.ts.map +1 -1
  5. package/dist/constants/index.d.ts +5 -0
  6. package/dist/constants/index.d.ts.map +1 -0
  7. package/dist/constants/max-expired-at.d.ts +2 -0
  8. package/dist/constants/max-expired-at.d.ts.map +1 -0
  9. package/dist/exceptions/cache-exception.d.ts +5 -0
  10. package/dist/exceptions/cache-exception.d.ts.map +1 -0
  11. package/dist/exceptions/index.d.ts +2 -0
  12. package/dist/exceptions/index.d.ts.map +1 -0
  13. package/dist/index.d.ts +4 -9
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +295 -224
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +295 -224
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/request-cache-handler/index.d.ts +3 -0
  20. package/dist/request-cache-handler/index.d.ts.map +1 -0
  21. package/dist/request-cache-handler/request-cache-handler.d.ts +22 -0
  22. package/dist/request-cache-handler/request-cache-handler.d.ts.map +1 -0
  23. package/dist/request-cache-handler/types/index.d.ts +2 -0
  24. package/dist/request-cache-handler/types/index.d.ts.map +1 -0
  25. package/dist/{types/keq-cache-option.d.ts → request-cache-handler/types/request-cache-options.d.ts} +6 -4
  26. package/dist/request-cache-handler/types/request-cache-options.d.ts.map +1 -0
  27. package/dist/storage/index.d.ts +4 -4
  28. package/dist/storage/index.d.ts.map +1 -1
  29. package/dist/storage/indexed-db-storage/base-indexed-db-storage.d.ts +2 -4
  30. package/dist/storage/indexed-db-storage/base-indexed-db-storage.d.ts.map +1 -1
  31. package/dist/storage/indexed-db-storage/index.d.ts +3 -0
  32. package/dist/storage/indexed-db-storage/index.d.ts.map +1 -0
  33. package/dist/storage/indexed-db-storage/indexed-db-storage.d.ts.map +1 -1
  34. package/dist/storage/indexed-db-storage/types/index.d.ts +7 -0
  35. package/dist/storage/indexed-db-storage/types/index.d.ts.map +1 -0
  36. package/dist/storage/indexed-db-storage/types/indexed-db-storage-options.d.ts +1 -1
  37. package/dist/storage/indexed-db-storage/types/indexed-db-storage-options.d.ts.map +1 -1
  38. package/dist/storage/internal-storage/internal-storage.d.ts +1 -1
  39. package/dist/storage/internal-storage/internal-storage.d.ts.map +1 -1
  40. package/dist/storage/memory-storage/base-memory-storage.d.ts +5 -4
  41. package/dist/storage/memory-storage/base-memory-storage.d.ts.map +1 -1
  42. package/dist/storage/memory-storage/index.d.ts +3 -0
  43. package/dist/storage/memory-storage/index.d.ts.map +1 -0
  44. package/dist/storage/memory-storage/memory-storage.d.ts +1 -0
  45. package/dist/storage/memory-storage/memory-storage.d.ts.map +1 -1
  46. package/dist/storage/memory-storage/types/index.d.ts +3 -0
  47. package/dist/storage/memory-storage/types/index.d.ts.map +1 -0
  48. package/dist/storage/memory-storage/types/memory-storage-options.d.ts +1 -1
  49. package/dist/storage/memory-storage/types/memory-storage-options.d.ts.map +1 -1
  50. package/dist/storage/memory-storage/utils/humanize-size.d.ts +6 -0
  51. package/dist/storage/memory-storage/utils/humanize-size.d.ts.map +1 -0
  52. package/dist/storage/memory-storage/utils/index.d.ts +3 -0
  53. package/dist/storage/memory-storage/utils/index.d.ts.map +1 -0
  54. package/dist/storage/memory-storage/utils/serialize-response-body.d.ts +6 -0
  55. package/dist/storage/memory-storage/utils/serialize-response-body.d.ts.map +1 -0
  56. package/dist/storage/multi-tier-storage/index.d.ts +1 -0
  57. package/dist/storage/multi-tier-storage/index.d.ts.map +1 -1
  58. package/dist/storage/multi-tier-storage/types/index.d.ts +2 -0
  59. package/dist/storage/multi-tier-storage/types/index.d.ts.map +1 -0
  60. package/dist/storage/tier-storage/index.d.ts +2 -2
  61. package/dist/storage/tier-storage/index.d.ts.map +1 -1
  62. package/dist/storage/tier-storage/types/index.d.ts +2 -0
  63. package/dist/storage/tier-storage/types/index.d.ts.map +1 -0
  64. package/dist/strategies/cache-first.d.ts.map +1 -1
  65. package/dist/strategies/index.d.ts +5 -0
  66. package/dist/strategies/index.d.ts.map +1 -0
  67. package/dist/strategies/network-first.d.ts.map +1 -1
  68. package/dist/strategies/network-only.d.ts.map +1 -1
  69. package/dist/strategies/stale-while-revalidate.d.ts.map +1 -1
  70. package/dist/types/index.d.ts +5 -0
  71. package/dist/types/index.d.ts.map +1 -0
  72. package/dist/types/keq-cache-key.d.ts +2 -1
  73. package/dist/types/keq-cache-key.d.ts.map +1 -1
  74. package/dist/types/keq-cache-pattern.d.ts +3 -0
  75. package/dist/types/keq-cache-pattern.d.ts.map +1 -0
  76. package/dist/types/keq-cache-rule.d.ts +4 -4
  77. package/dist/types/keq-cache-rule.d.ts.map +1 -1
  78. package/dist/types/keq-cache-strategy.d.ts +2 -2
  79. package/dist/types/keq-cache-strategy.d.ts.map +1 -1
  80. package/dist/utils/index.d.ts +4 -0
  81. package/dist/utils/index.d.ts.map +1 -0
  82. package/dist/utils/logger.d.ts +5 -0
  83. package/dist/utils/logger.d.ts.map +1 -0
  84. package/package.json +6 -11
  85. package/dist/strategies/utils/cache-context.d.ts +0 -5
  86. package/dist/strategies/utils/cache-context.d.ts.map +0 -1
  87. package/dist/strategies/utils/index.d.ts +0 -2
  88. package/dist/strategies/utils/index.d.ts.map +0 -1
  89. package/dist/types/keq-cache-option.d.ts.map +0 -1
  90. package/dist/types/keq-cache-parameters.d.ts +0 -12
  91. package/dist/types/keq-cache-parameters.d.ts.map +0 -1
  92. package/dist/types/strategies-options.d.ts +0 -14
  93. package/dist/types/strategies-options.d.ts.map +0 -1
  94. package/dist/utils/debug.d.ts +0 -2
  95. package/dist/utils/debug.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -32,10 +32,11 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
32
32
  // src/index.ts
33
33
  var index_exports = {};
34
34
  __export(index_exports, {
35
- CacheStorage: () => KeqCacheStorage,
36
35
  Eviction: () => Eviction,
37
36
  IndexedDBStorage: () => IndexedDBStorage,
37
+ KeqCacheStorage: () => KeqCacheStorage,
38
38
  MemoryStorage: () => MemoryStorage,
39
+ MultiTierStorage: () => MultiTierStorage,
39
40
  Size: () => Size,
40
41
  Strategy: () => Strategy,
41
42
  TierStorage: () => TierStorage,
@@ -44,45 +45,21 @@ __export(index_exports, {
44
45
  module.exports = __toCommonJS(index_exports);
45
46
 
46
47
  // src/cache.ts
48
+ var R2 = __toESM(require("ramda"));
49
+
50
+ // src/request-cache-handler/request-cache-handler.ts
47
51
  var R = __toESM(require("ramda"));
52
+
53
+ // src/exceptions/cache-exception.ts
48
54
  var import_keq = require("keq");
49
- function cache(opts) {
50
- const storage = opts.storage;
51
- const rules = (opts == null ? void 0 : opts.rules) || [];
52
- return async function cache2(ctx, next) {
53
- if (ctx.options.cache === false) {
54
- await next();
55
- return;
56
- }
57
- let cOpt = ctx.options.cache;
58
- const rule = rules.find((rule2) => {
59
- if (rule2.pattern === void 0 || rule2.pattern === true) return true;
60
- if (typeof rule2.pattern === "function") return rule2.pattern(ctx);
61
- return rule2.pattern.test(ctx.request.__url__.href);
62
- });
63
- if (rule) cOpt = R.mergeRight(rule, cOpt || {});
64
- if (!cOpt || R.isEmpty(cOpt)) {
65
- await next();
66
- return;
67
- }
68
- let key = ctx.locationId;
69
- if (cOpt.key) {
70
- if (typeof cOpt.key === "function") key = cOpt.key(ctx);
71
- else key = cOpt.key;
72
- } else if (opts == null ? void 0 : opts.keyFactory) {
73
- key = opts.keyFactory(ctx);
74
- }
75
- if (!key) throw new import_keq.Exception("Cache key is required");
76
- const strategy = cOpt.strategy;
77
- const opt = {
78
- key,
79
- storage,
80
- ttl: cOpt.ttl,
81
- exclude: cOpt.exclude
82
- };
83
- await strategy(opt)(ctx, next);
84
- };
85
- }
55
+ var CacheException = class extends import_keq.Exception {
56
+ constructor(message) {
57
+ super("[@keq-request/cache] ".concat(message));
58
+ }
59
+ };
60
+
61
+ // src/cache-entry/cache-entry.ts
62
+ var import_keq2 = require("keq");
86
63
 
87
64
  // src/utils/get-response-bytes.ts
88
65
  async function getResponseBytes(response) {
@@ -94,6 +71,124 @@ async function getResponseBytes(response) {
94
71
  return arrayBuffer.byteLength;
95
72
  }
96
73
 
74
+ // src/constants/max-expired-at.ts
75
+ var MAX_EXPIRED_AT = /* @__PURE__ */ new Date(864e13);
76
+
77
+ // src/constants/eviction.enum.ts
78
+ var Eviction = /* @__PURE__ */ ((Eviction2) => {
79
+ Eviction2["LRU"] = "lru";
80
+ Eviction2["LFU"] = "lfu";
81
+ Eviction2["RANDOM"] = "random";
82
+ Eviction2["TTL"] = "ttl";
83
+ return Eviction2;
84
+ })(Eviction || {});
85
+
86
+ // src/constants/size.enum.ts
87
+ var Size = /* @__PURE__ */ ((Size2) => {
88
+ Size2[Size2["B"] = 1] = "B";
89
+ Size2[Size2["KB"] = 1024] = "KB";
90
+ Size2[Size2["MB"] = 1048576] = "MB";
91
+ Size2[Size2["GB"] = 1073741824] = "GB";
92
+ return Size2;
93
+ })(Size || {});
94
+
95
+ // src/strategies/cache-first.ts
96
+ var cacheFirst = async function cacheFirst2(handler, context, next) {
97
+ const [cacheKey, cacheValue] = await handler.getCache(context);
98
+ if (cacheValue) {
99
+ context.emitter.emit("cache:hit", { key: cacheKey, response: cacheValue.response, context });
100
+ context.res = cacheValue.response;
101
+ return;
102
+ }
103
+ context.emitter.emit("cache:miss", { key: cacheKey, context });
104
+ await next();
105
+ const [, entry] = await handler.setCache(context);
106
+ if (entry) {
107
+ context.emitter.emit("cache:update", {
108
+ key: entry.key,
109
+ oldResponse: void 0,
110
+ newResponse: entry.response,
111
+ context
112
+ });
113
+ }
114
+ };
115
+
116
+ // src/strategies/network-first.ts
117
+ var networkFirst = async function networkFirst2(handler, context, next) {
118
+ try {
119
+ await next();
120
+ const [, cache2] = await handler.getCache(context);
121
+ const [, entry] = await handler.setCache(context);
122
+ if (entry) {
123
+ context.emitter.emit("cache:update", {
124
+ key: entry.key,
125
+ oldResponse: cache2 == null ? void 0 : cache2.response,
126
+ newResponse: entry.response,
127
+ context
128
+ });
129
+ }
130
+ } catch (err) {
131
+ const [key, cache2] = await handler.getCache(context);
132
+ if (!cache2) {
133
+ context.emitter.emit("cache:miss", { key, context });
134
+ throw err;
135
+ }
136
+ context.emitter.emit("cache:hit", { key, response: cache2.response, context });
137
+ context.res = cache2.response;
138
+ }
139
+ };
140
+
141
+ // src/strategies/network-only.ts
142
+ var networkOnly = async function(handler, context, next) {
143
+ await next();
144
+ };
145
+
146
+ // src/strategies/stale-while-revalidate.ts
147
+ var staleWhileRevalidate = async function(handler, context, next) {
148
+ const [key, cache2] = await handler.getCache(context);
149
+ if (cache2) {
150
+ context.emitter.emit("cache:hit", { key, response: cache2.response, context });
151
+ const orchestrator = context.orchestration.fork();
152
+ context.res = cache2.response;
153
+ setTimeout(async () => {
154
+ try {
155
+ await orchestrator.execute();
156
+ const context2 = orchestrator.context;
157
+ const [, entry] = await handler.setCache(context2);
158
+ if (entry) {
159
+ context2.emitter.emit("cache:update", {
160
+ key,
161
+ oldResponse: cache2.response,
162
+ newResponse: entry.response,
163
+ context: context2
164
+ });
165
+ }
166
+ } catch (err) {
167
+ }
168
+ }, 1);
169
+ } else {
170
+ context.emitter.emit("cache:miss", { key, context });
171
+ await next();
172
+ const [, entry] = await handler.setCache(context);
173
+ if (entry) {
174
+ context.emitter.emit("cache:update", {
175
+ key,
176
+ oldResponse: void 0,
177
+ newResponse: entry.response,
178
+ context
179
+ });
180
+ }
181
+ }
182
+ };
183
+
184
+ // src/constants/strategy.enum.ts
185
+ var Strategy = {
186
+ STALE_WHILE_REVALIDATE: staleWhileRevalidate,
187
+ NETWORK_FIRST: networkFirst,
188
+ NETWORK_ONLY: networkOnly,
189
+ CACHE_FIRST: cacheFirst
190
+ };
191
+
97
192
  // src/cache-entry/cache-entry.ts
98
193
  var CacheEntry = class _CacheEntry {
99
194
  constructor(options) {
@@ -107,13 +202,13 @@ var CacheEntry = class _CacheEntry {
107
202
  __publicField(this, "expiredAt");
108
203
  var _a;
109
204
  this.key = options.key;
110
- this.response = options.response;
205
+ this.response = (0, import_keq2.createProxyResponse)(options.response);
111
206
  this.size = options.size;
112
- this.expiredAt = (_a = options.expiredAt) != null ? _a : /* @__PURE__ */ new Date(864e13);
207
+ this.expiredAt = (_a = options.expiredAt) != null ? _a : MAX_EXPIRED_AT;
113
208
  }
114
209
  static async build(options) {
115
210
  var _a;
116
- const expiredAt = "expiredAt" in options ? options.expiredAt : "ttl" in options && typeof options.ttl === "number" && options.ttl > 0 ? new Date(Date.now() + options.ttl * 1e3) : /* @__PURE__ */ new Date(864e13);
211
+ const expiredAt = "expiredAt" in options ? options.expiredAt : "ttl" in options && typeof options.ttl === "number" && options.ttl > 0 ? new Date(Date.now() + options.ttl * 1e3) : MAX_EXPIRED_AT;
117
212
  const response = options.response.clone();
118
213
  return new _CacheEntry({
119
214
  key: options.key,
@@ -139,164 +234,106 @@ var CacheEntry = class _CacheEntry {
139
234
  }
140
235
  };
141
236
 
142
- // src/strategies/utils/cache-context.ts
143
- async function cacheContext(opts, context) {
144
- if (!context.response) return;
145
- if (opts.exclude && await opts.exclude(context.response)) return;
146
- const key = opts.key;
147
- const storage = opts.storage;
148
- const entry = await CacheEntry.build({
149
- key,
150
- response: context.response,
151
- ttl: opts.ttl
152
- });
153
- storage.set(entry);
154
- return entry;
155
- }
237
+ // src/request-cache-handler/request-cache-handler.ts
238
+ var RequestCacheHandler = class {
239
+ constructor(storage, options) {
240
+ this.storage = storage;
241
+ this.options = options;
242
+ }
243
+ /**
244
+ * Get cache key for request
245
+ */
246
+ getRequestCacheKey(context) {
247
+ const options = this.options;
248
+ if (typeof options.key === "string") return options.key;
249
+ else if (typeof options.key === "function") return options.key(context);
250
+ else if (R.isNil(options.key) && context.locationId) return context.locationId;
251
+ else throw new CacheException("Cannot resolve cache key");
252
+ }
253
+ /**
254
+ * Get cache from storage
255
+ */
256
+ async getCache(context) {
257
+ const key = this.getRequestCacheKey(context);
258
+ return [key, await this.storage.get(key)];
259
+ }
260
+ /**
261
+ * Store response that in context to storage
262
+ */
263
+ async setCache(context) {
264
+ const options = this.options;
265
+ const key = this.getRequestCacheKey(context);
266
+ if (!context.response) return [key, void 0];
267
+ if (options.exclude && await options.exclude(context.response)) return [key, void 0];
268
+ const entry = await CacheEntry.build({
269
+ key,
270
+ response: context.response,
271
+ ttl: options.ttl
272
+ });
273
+ void this.storage.set(entry);
274
+ return [key, entry];
275
+ }
276
+ };
156
277
 
157
- // src/strategies/cache-first.ts
158
- var cacheFirst = function(opts) {
159
- const { storage, key } = opts;
160
- return async function(context, next) {
161
- const cache2 = await storage.get(key);
162
- if (cache2) {
163
- context.emitter.emit("cache:hit", { key, response: cache2.response, context });
164
- context.res = cache2.response;
278
+ // src/cache.ts
279
+ function cache(options) {
280
+ const storage = options.storage;
281
+ const rules = (options == null ? void 0 : options.rules) || [];
282
+ return async function cache2(ctx, next) {
283
+ if (ctx.options.cache === false) {
284
+ await next();
165
285
  return;
166
286
  }
167
- context.emitter.emit("cache:miss", { key, context });
168
- await next();
169
- const entry = await cacheContext(opts, context);
170
- if (entry) {
171
- context.emitter.emit("cache:update", {
172
- key,
173
- oldResponse: void 0,
174
- newResponse: entry.response,
175
- context
176
- });
177
- }
178
- };
179
- };
180
-
181
- // src/strategies/network-first.ts
182
- var networkFirst = function(opts) {
183
- const { key, storage } = opts;
184
- return async function(context, next) {
185
- try {
287
+ let requestCacheOptions = ctx.options.cache;
288
+ const rule = rules.find((rule2) => {
289
+ if (rule2.pattern === void 0 || rule2.pattern === true) return true;
290
+ if (typeof rule2.pattern === "function") return rule2.pattern(ctx);
291
+ return rule2.pattern.test(ctx.request.__url__.href);
292
+ });
293
+ if (rule) requestCacheOptions = R2.mergeRight(rule, requestCacheOptions || {});
294
+ if (!requestCacheOptions || R2.isEmpty(requestCacheOptions)) {
186
295
  await next();
187
- const cache2 = await storage.get(key);
188
- const entry = await cacheContext(opts, context);
189
- if (entry) {
190
- context.emitter.emit("cache:update", {
191
- key,
192
- oldResponse: cache2 == null ? void 0 : cache2.response,
193
- newResponse: entry.response,
194
- context
195
- });
196
- }
197
- } catch (err) {
198
- const cache2 = await storage.get(key);
199
- if (!cache2) {
200
- context.emitter.emit("cache:miss", { key, context });
201
- throw err;
202
- }
203
- context.emitter.emit("cache:hit", { key, response: cache2.response, context });
204
- context.res = cache2.response;
296
+ return;
205
297
  }
206
- };
207
- };
208
-
209
- // src/strategies/network-only.ts
210
- var networkOnly = function(opts) {
211
- return async function(ctx, next) {
212
- await next();
213
- };
214
- };
215
-
216
- // src/strategies/stale-while-revalidate.ts
217
- var staleWhileRevalidate = function(opts) {
218
- const { key, storage } = opts;
219
- return async function(context, next) {
220
- const cache2 = await storage.get(key);
221
- if (cache2) {
222
- context.emitter.emit("cache:hit", { key, response: cache2.response, context });
223
- const orchestrator = context.orchestration.fork();
224
- context.res = cache2.response;
225
- setTimeout(async () => {
226
- try {
227
- await orchestrator.execute();
228
- const context2 = orchestrator.context;
229
- const entry = await cacheContext(opts, context2);
230
- if (entry) {
231
- context2.emitter.emit("cache:update", {
232
- key,
233
- oldResponse: cache2.response,
234
- newResponse: entry.response,
235
- context: context2
236
- });
237
- }
238
- } catch (err) {
239
- }
240
- }, 1);
241
- } else {
242
- context.emitter.emit("cache:miss", { key, context });
298
+ if (!requestCacheOptions.key) requestCacheOptions.key = options.keyFactory;
299
+ if (!ctx.locationId && !requestCacheOptions.key) {
300
+ console.warn("[@keq/cache] Warning: Cannot resolve Cache Key. Cache is skipped.");
243
301
  await next();
244
- const entry = await cacheContext(opts, context);
245
- if (entry) {
246
- context.emitter.emit("cache:update", {
247
- key,
248
- oldResponse: void 0,
249
- newResponse: entry.response,
250
- context
251
- });
252
- }
302
+ return;
253
303
  }
304
+ const handler = new RequestCacheHandler(storage, requestCacheOptions);
305
+ const strategy = requestCacheOptions.strategy;
306
+ await strategy(handler, ctx, next);
254
307
  };
255
- };
256
-
257
- // src/constants/strategy.enum.ts
258
- var Strategy = {
259
- STALE_WHILE_REVALIDATE: staleWhileRevalidate,
260
- NETWORK_FIRST: networkFirst,
261
- NETWORK_ONLY: networkOnly,
262
- CACHE_FIRST: cacheFirst
263
- };
264
-
265
- // src/constants/eviction.enum.ts
266
- var Eviction = /* @__PURE__ */ ((Eviction2) => {
267
- Eviction2["LRU"] = "lru";
268
- Eviction2["LFU"] = "lfu";
269
- Eviction2["RANDOM"] = "random";
270
- Eviction2["TTL"] = "ttl";
271
- return Eviction2;
272
- })(Eviction || {});
273
-
274
- // src/constants/size.enum.ts
275
- var Size = /* @__PURE__ */ ((Size2) => {
276
- Size2[Size2["B"] = 1] = "B";
277
- Size2[Size2["KB"] = 1024] = "KB";
278
- Size2[Size2["MB"] = 1048576] = "MB";
279
- Size2[Size2["GB"] = 1073741824] = "GB";
280
- return Size2;
281
- })(Size || {});
308
+ }
282
309
 
283
310
  // src/storage/memory-storage/ttl-memory-storage.ts
284
311
  var import_dayjs2 = __toESM(require("dayjs"));
285
- var R3 = __toESM(require("ramda"));
312
+ var R4 = __toESM(require("ramda"));
286
313
 
287
314
  // src/storage/memory-storage/base-memory-storage.ts
288
315
  var import_dayjs = __toESM(require("dayjs"));
289
- var R2 = __toESM(require("ramda"));
290
-
291
- // src/utils/debug.ts
292
- function debug(...args) {
293
- console.debug("[@keq-cache] [DEBUG] ", ...args);
294
- }
316
+ var R3 = __toESM(require("ramda"));
295
317
 
296
318
  // src/storage/keq-cache-storage.ts
297
319
  var KeqCacheStorage = class {
298
320
  };
299
321
 
322
+ // src/utils/logger.ts
323
+ var Logger = class {
324
+ static debug(...args) {
325
+ console.debug("[@keq-cache] [DEBUG] ", ...args);
326
+ }
327
+ static error(...args) {
328
+ console.error("[@keq-cache] [ERROR] ", ...args);
329
+ }
330
+ };
331
+
332
+ // src/utils/random.ts
333
+ function random(min, max) {
334
+ return Math.floor(Math.random() * (max - min)) + min;
335
+ }
336
+
300
337
  // src/storage/internal-storage/internal-storage.ts
301
338
  var InternalStorage = class extends KeqCacheStorage {
302
339
  constructor(options) {
@@ -311,7 +348,7 @@ var InternalStorage = class extends KeqCacheStorage {
311
348
  __publicField(this, "__onCacheEvict__");
312
349
  __publicField(this, "__onCacheExpired__");
313
350
  if ((options == null ? void 0 : options.size) && (typeof (options == null ? void 0 : options.size) !== "number" || options.size <= 0)) {
314
- throw TypeError("Invalid size: ".concat(String(options == null ? void 0 : options.size)));
351
+ throw new CacheException("Invalid size: ".concat(String(options == null ? void 0 : options.size)));
315
352
  }
316
353
  this.__size__ = (_a = options == null ? void 0 : options.size) != null ? _a : Infinity;
317
354
  this.__debug__ = !!(options == null ? void 0 : options.debug);
@@ -324,12 +361,38 @@ var InternalStorage = class extends KeqCacheStorage {
324
361
  debug(fn) {
325
362
  if (this.__debug__) {
326
363
  fn((...args) => {
327
- debug("[Storage(".concat(this.__id__, ")]"), ...args);
364
+ Logger.debug("[Storage(".concat(this.__id__, ")]"), ...args);
328
365
  });
329
366
  }
330
367
  }
331
368
  };
332
369
 
370
+ // src/storage/memory-storage/utils/humanize-size.ts
371
+ function humanizeSize(size) {
372
+ if (size < 1024) return "".concat(size, " B");
373
+ if (size < 1024 * 1024) return "".concat((size / 1024).toFixed(2), " KB");
374
+ if (size < 1024 * 1024 * 1024) return "".concat((size / (1024 * 1024)).toFixed(2), " MB");
375
+ return "".concat((size / (1024 * 1024 * 1024)).toFixed(2), " GB");
376
+ }
377
+
378
+ // src/storage/memory-storage/utils/serialize-response-body.ts
379
+ async function serializeResponseBody(response) {
380
+ var _a;
381
+ const contentType = (_a = response.headers.get("content-type")) != null ? _a : "";
382
+ try {
383
+ if (contentType.includes("application/json")) {
384
+ const json = await response.json();
385
+ return JSON.stringify(json);
386
+ }
387
+ if (contentType.includes("text/") || contentType.includes("application/xml") || contentType.includes("application/javascript")) {
388
+ return await response.text();
389
+ }
390
+ return "[Binary or unsupported content]";
391
+ } catch {
392
+ return "[Unable to serialize]";
393
+ }
394
+ }
395
+
333
396
  // src/storage/memory-storage/base-memory-storage.ts
334
397
  var BaseMemoryStorage = class extends InternalStorage {
335
398
  constructor() {
@@ -340,7 +403,7 @@ var BaseMemoryStorage = class extends InternalStorage {
340
403
  __publicField(this, "lastEvictExpiredTime", (0, import_dayjs.default)());
341
404
  }
342
405
  get size() {
343
- const used = R2.sum(R2.pluck("size", [...this.storage.values()]));
406
+ const used = R3.sum(R3.pluck("size", [...this.storage.values()]));
344
407
  const free = this.__size__ > used ? this.__size__ - used : 0;
345
408
  return {
346
409
  used,
@@ -383,23 +446,6 @@ var BaseMemoryStorage = class extends InternalStorage {
383
446
  remove(key) {
384
447
  this.__remove__([key]);
385
448
  }
386
- /**
387
- * Print all cache entries
388
- */
389
- print() {
390
- const entries = Array.from(this.storage.entries()).map(([key, entry]) => {
391
- var _a;
392
- return {
393
- key,
394
- size: entry.size,
395
- expiredAt: entry.expiredAt ? (0, import_dayjs.default)(entry.expiredAt).format("YYYY-MM-DD HH:mm:ss") : "N/A",
396
- visitCount: (_a = this.visitCountRecords.get(key)) != null ? _a : 0,
397
- lastVisit: this.visitTimeRecords.get(key) ? (0, import_dayjs.default)(this.visitTimeRecords.get(key)).format("YYYY-MM-DD HH:mm:ss") : "N/A"
398
- };
399
- });
400
- console.table(entries);
401
- console.log("Total: ".concat(entries.length, " entries, Used: ").concat(this.size.used, ", Free: ").concat(this.size.free));
402
- }
403
449
  /**
404
450
  * @zh 清除过期的缓存
405
451
  */
@@ -427,6 +473,33 @@ var BaseMemoryStorage = class extends InternalStorage {
427
473
  const size = this.size;
428
474
  return size.free >= expectSize;
429
475
  }
476
+ /**
477
+ * @en Print all cached data using console.table for debugging
478
+ * @zh 使用 console.table 打印所有缓存数据,用于调试
479
+ */
480
+ async print() {
481
+ if (this.storage.size === 0) {
482
+ console.log("MemoryStorage is empty");
483
+ return;
484
+ }
485
+ const entries = await Promise.all(
486
+ [...this.storage.entries()].map(async ([key, entry]) => {
487
+ var _a, _b, _c;
488
+ const body = await serializeResponseBody(entry.response.clone());
489
+ return {
490
+ key,
491
+ size: humanizeSize(entry.size),
492
+ "Expired Time": entry.expiredAt.getTime() >= MAX_EXPIRED_AT.getTime() ? "-" : entry.expiredAt.toISOString(),
493
+ "Visit Count": (_a = this.visitCountRecords.get(key)) != null ? _a : 0,
494
+ "Last Visit Time": (_c = (_b = this.visitTimeRecords.get(key)) == null ? void 0 : _b.toISOString()) != null ? _c : "-",
495
+ "Response Status": entry.response.status,
496
+ "Response URL": entry.response.url,
497
+ "Response Body": body
498
+ };
499
+ })
500
+ );
501
+ console.table(entries);
502
+ }
430
503
  };
431
504
 
432
505
  // src/storage/memory-storage/ttl-memory-storage.ts
@@ -464,7 +537,7 @@ var TTLMemoryStorage = class extends BaseMemoryStorage {
464
537
  const bExpiredAt = (0, import_dayjs2.default)(b.expiredAt);
465
538
  return aExpiredAt.isBefore(bExpiredAt) ? 1 : -1;
466
539
  });
467
- if (R3.sum(R3.pluck("size", entries)) < deficitSize) {
540
+ if (R4.sum(R4.pluck("size", entries)) < deficitSize) {
468
541
  this.debug((log) => log("Storage Size Not Enough: ", this.size.free, " < ", deficitSize));
469
542
  return false;
470
543
  }
@@ -480,11 +553,6 @@ var TTLMemoryStorage = class extends BaseMemoryStorage {
480
553
  }
481
554
  };
482
555
 
483
- // src/utils/random.ts
484
- function random(min, max) {
485
- return Math.floor(Math.random() * (max - min)) + min;
486
- }
487
-
488
556
  // src/storage/memory-storage/random-memory-storage.ts
489
557
  var RandomMemoryStorage = class extends BaseMemoryStorage {
490
558
  constructor(options) {
@@ -655,15 +723,18 @@ var MemoryStorage = class extends KeqCacheStorage {
655
723
  remove(key) {
656
724
  return this.storage.remove(key);
657
725
  }
726
+ async print() {
727
+ return this.storage.print();
728
+ }
658
729
  };
659
730
 
660
731
  // src/storage/indexed-db-storage/random-indexed-db-storage.ts
661
- var R5 = __toESM(require("ramda"));
732
+ var R6 = __toESM(require("ramda"));
662
733
 
663
734
  // src/storage/indexed-db-storage/base-indexed-db-storage.ts
664
- var R4 = __toESM(require("ramda"));
665
- var import_idb = require("idb");
735
+ var R5 = __toESM(require("ramda"));
666
736
  var import_dayjs4 = __toESM(require("dayjs"));
737
+ var import_idb = require("idb");
667
738
 
668
739
  // src/storage/indexed-db-storage/constants/default-table-name.ts
669
740
  var DEFAULT_TABLE_NAME = "keq_cache_indexed_db_storage";
@@ -674,9 +745,9 @@ var BaseIndexedDBStorage = class extends InternalStorage {
674
745
  super(options);
675
746
  __publicField(this, "tableName", DEFAULT_TABLE_NAME);
676
747
  __publicField(this, "db");
677
- __publicField(this, "lastEvictExpiredTime", (0, import_dayjs4.default)());
748
+ __publicField(this, "lastEvictExpiredTime", (0, import_dayjs4.default)(0));
678
749
  if ((options == null ? void 0 : options.tableName) === DEFAULT_TABLE_NAME) {
679
- throw new TypeError('[keq-cache] IndexedDBStorage name cannot be "'.concat(DEFAULT_TABLE_NAME, '"'));
750
+ throw new CacheException('IndexedDBStorage name cannot be "'.concat(DEFAULT_TABLE_NAME, '"'));
680
751
  }
681
752
  this.tableName = (options == null ? void 0 : options.tableName) || DEFAULT_TABLE_NAME;
682
753
  }
@@ -700,13 +771,13 @@ var BaseIndexedDBStorage = class extends InternalStorage {
700
771
  }
701
772
  },
702
773
  blocked() {
703
- console.error("IndexedDB Table ".concat(tableName, " is blocked"));
774
+ Logger.error("[@keq-request/cache] IndexedDB Table ".concat(tableName, " is blocked"));
704
775
  },
705
776
  blocking() {
706
- console.error("IndexedDB Table ".concat(tableName, " is blocking"));
777
+ Logger.error("[@keq-request/cache] IndexedDB Table ".concat(tableName, " is blocking"));
707
778
  },
708
779
  terminated() {
709
- console.error("IndexedDB Table ".concat(tableName, " is terminated"));
780
+ Logger.error("[@keq-request/cache] IndexedDB Table ".concat(tableName, " is terminated"));
710
781
  }
711
782
  });
712
783
  this.db = db;
@@ -715,7 +786,7 @@ var BaseIndexedDBStorage = class extends InternalStorage {
715
786
  async getSize() {
716
787
  const db = await this.openDB();
717
788
  const items = await db.getAll("metadata");
718
- const used = R4.sum(items.map((entry) => entry.size));
789
+ const used = R5.sum(items.map((entry) => entry.size));
719
790
  const free = this.__size__ - used;
720
791
  return { used, free };
721
792
  }
@@ -791,7 +862,7 @@ var BaseIndexedDBStorage = class extends InternalStorage {
791
862
  }
792
863
  async __remove__(tx, keys) {
793
864
  await Promise.all(
794
- R4.unnest(
865
+ R5.unnest(
795
866
  keys.map((key) => [
796
867
  tx.objectStore("metadata").delete(key),
797
868
  tx.objectStore("response").delete(key),
@@ -817,15 +888,15 @@ var BaseIndexedDBStorage = class extends InternalStorage {
817
888
  var _a;
818
889
  const now = (0, import_dayjs4.default)();
819
890
  if (now.diff(this.lastEvictExpiredTime, "second") < 1) return;
891
+ this.lastEvictExpiredTime = now;
820
892
  try {
821
- const now2 = (0, import_dayjs4.default)();
822
893
  const db = await this.openDB();
823
894
  const tx = db.transaction(["metadata", "response", "visits"], "readwrite");
824
895
  const metadataStore = tx.objectStore("metadata");
825
- let cursor = await metadataStore.index("expiredAt").openCursor(IDBKeyRange.upperBound(now2.valueOf()));
896
+ let cursor = await metadataStore.index("expiredAt").openCursor(IDBKeyRange.upperBound(now.toDate()));
826
897
  const expiredKeys = [];
827
898
  while (cursor) {
828
- if ((0, import_dayjs4.default)(cursor.value.expiredAt).isBefore(now2)) {
899
+ if ((0, import_dayjs4.default)(cursor.value.expiredAt).isBefore(now)) {
829
900
  expiredKeys.push(cursor.value.key);
830
901
  cursor = await cursor.continue();
831
902
  } else {
@@ -872,7 +943,7 @@ var RandomIndexedDBStorage = class extends BaseIndexedDBStorage {
872
943
  const tx = db.transaction(["metadata", "response", "visits"], "readwrite");
873
944
  const metadataStore = tx.objectStore("metadata");
874
945
  const metadatas = await metadataStore.getAll();
875
- const totalSize = R5.sum(metadatas.map((m) => m.size));
946
+ const totalSize = R6.sum(metadatas.map((m) => m.size));
876
947
  if (totalSize < deficitSize) {
877
948
  this.debug((log) => log("Storage Size Not Enough, deficit size: ".concat(deficitSize - totalSize)));
878
949
  tx.abort();
@@ -1075,7 +1146,7 @@ var IndexedDBStorage = class extends KeqCacheStorage {
1075
1146
  } else if (eviction === "ttl" /* TTL */) {
1076
1147
  this.storage = new TTLIndexedDBStorage(options);
1077
1148
  } else {
1078
- throw TypeError("Not Supported Eviction: ".concat(String(options == null ? void 0 : options.eviction)));
1149
+ throw new CacheException("Not Supported Eviction: ".concat(String(options == null ? void 0 : options.eviction)));
1079
1150
  }
1080
1151
  }
1081
1152
  set(entry) {
@@ -1125,7 +1196,7 @@ var MultiTierStorage = class extends KeqCacheStorage {
1125
1196
  * @zh 并发写入所有层的缓存
1126
1197
  */
1127
1198
  async set(entry) {
1128
- const promises = this.storages.map((storage) => storage.set(entry));
1199
+ const promises = this.storages.map(async (storage) => storage.set(entry));
1129
1200
  await Promise.all(promises);
1130
1201
  }
1131
1202
  /**
@@ -1133,7 +1204,7 @@ var MultiTierStorage = class extends KeqCacheStorage {
1133
1204
  * @zh 从所有层删除缓存条目
1134
1205
  */
1135
1206
  async remove(key) {
1136
- const promises = this.storages.map((storage) => storage.remove(key));
1207
+ const promises = this.storages.map(async (storage) => storage.remove(key));
1137
1208
  await Promise.all(promises);
1138
1209
  }
1139
1210
  /**
@@ -1145,7 +1216,7 @@ var MultiTierStorage = class extends KeqCacheStorage {
1145
1216
  if (lowerTierStorages.length === 0) {
1146
1217
  return;
1147
1218
  }
1148
- const promises = lowerTierStorages.map((storage) => storage.set(entry.clone()));
1219
+ const promises = lowerTierStorages.map(async (storage) => storage.set(entry.clone()));
1149
1220
  try {
1150
1221
  await Promise.all(promises);
1151
1222
  } catch (error) {