@keq-request/cache 5.0.0-alpha.21 → 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 +26 -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.mjs CHANGED
@@ -3,45 +3,21 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
 
5
5
  // src/cache.ts
6
+ import * as R2 from "ramda";
7
+
8
+ // src/request-cache-handler/request-cache-handler.ts
6
9
  import * as R from "ramda";
10
+
11
+ // src/exceptions/cache-exception.ts
7
12
  import { Exception } from "keq";
8
- function cache(opts) {
9
- const storage = opts.storage;
10
- const rules = (opts == null ? void 0 : opts.rules) || [];
11
- return async function cache2(ctx, next) {
12
- if (ctx.options.cache === false) {
13
- await next();
14
- return;
15
- }
16
- let cOpt = ctx.options.cache;
17
- const rule = rules.find((rule2) => {
18
- if (rule2.pattern === void 0 || rule2.pattern === true) return true;
19
- if (typeof rule2.pattern === "function") return rule2.pattern(ctx);
20
- return rule2.pattern.test(ctx.request.__url__.href);
21
- });
22
- if (rule) cOpt = R.mergeRight(rule, cOpt || {});
23
- if (!cOpt || R.isEmpty(cOpt)) {
24
- await next();
25
- return;
26
- }
27
- let key = ctx.locationId;
28
- if (cOpt.key) {
29
- if (typeof cOpt.key === "function") key = cOpt.key(ctx);
30
- else key = cOpt.key;
31
- } else if (opts == null ? void 0 : opts.keyFactory) {
32
- key = opts.keyFactory(ctx);
33
- }
34
- if (!key) throw new Exception("Cache key is required");
35
- const strategy = cOpt.strategy;
36
- const opt = {
37
- key,
38
- storage,
39
- ttl: cOpt.ttl,
40
- exclude: cOpt.exclude
41
- };
42
- await strategy(opt)(ctx, next);
43
- };
44
- }
13
+ var CacheException = class extends Exception {
14
+ constructor(message) {
15
+ super("[@keq-request/cache] ".concat(message));
16
+ }
17
+ };
18
+
19
+ // src/cache-entry/cache-entry.ts
20
+ import { createProxyResponse } from "keq";
45
21
 
46
22
  // src/utils/get-response-bytes.ts
47
23
  async function getResponseBytes(response) {
@@ -53,6 +29,124 @@ async function getResponseBytes(response) {
53
29
  return arrayBuffer.byteLength;
54
30
  }
55
31
 
32
+ // src/constants/max-expired-at.ts
33
+ var MAX_EXPIRED_AT = /* @__PURE__ */ new Date(864e13);
34
+
35
+ // src/constants/eviction.enum.ts
36
+ var Eviction = /* @__PURE__ */ ((Eviction2) => {
37
+ Eviction2["LRU"] = "lru";
38
+ Eviction2["LFU"] = "lfu";
39
+ Eviction2["RANDOM"] = "random";
40
+ Eviction2["TTL"] = "ttl";
41
+ return Eviction2;
42
+ })(Eviction || {});
43
+
44
+ // src/constants/size.enum.ts
45
+ var Size = /* @__PURE__ */ ((Size2) => {
46
+ Size2[Size2["B"] = 1] = "B";
47
+ Size2[Size2["KB"] = 1024] = "KB";
48
+ Size2[Size2["MB"] = 1048576] = "MB";
49
+ Size2[Size2["GB"] = 1073741824] = "GB";
50
+ return Size2;
51
+ })(Size || {});
52
+
53
+ // src/strategies/cache-first.ts
54
+ var cacheFirst = async function cacheFirst2(handler, context, next) {
55
+ const [cacheKey, cacheValue] = await handler.getCache(context);
56
+ if (cacheValue) {
57
+ context.emitter.emit("cache:hit", { key: cacheKey, response: cacheValue.response, context });
58
+ context.res = cacheValue.response;
59
+ return;
60
+ }
61
+ context.emitter.emit("cache:miss", { key: cacheKey, context });
62
+ await next();
63
+ const [, entry] = await handler.setCache(context);
64
+ if (entry) {
65
+ context.emitter.emit("cache:update", {
66
+ key: entry.key,
67
+ oldResponse: void 0,
68
+ newResponse: entry.response,
69
+ context
70
+ });
71
+ }
72
+ };
73
+
74
+ // src/strategies/network-first.ts
75
+ var networkFirst = async function networkFirst2(handler, context, next) {
76
+ try {
77
+ await next();
78
+ const [, cache2] = await handler.getCache(context);
79
+ const [, entry] = await handler.setCache(context);
80
+ if (entry) {
81
+ context.emitter.emit("cache:update", {
82
+ key: entry.key,
83
+ oldResponse: cache2 == null ? void 0 : cache2.response,
84
+ newResponse: entry.response,
85
+ context
86
+ });
87
+ }
88
+ } catch (err) {
89
+ const [key, cache2] = await handler.getCache(context);
90
+ if (!cache2) {
91
+ context.emitter.emit("cache:miss", { key, context });
92
+ throw err;
93
+ }
94
+ context.emitter.emit("cache:hit", { key, response: cache2.response, context });
95
+ context.res = cache2.response;
96
+ }
97
+ };
98
+
99
+ // src/strategies/network-only.ts
100
+ var networkOnly = async function(handler, context, next) {
101
+ await next();
102
+ };
103
+
104
+ // src/strategies/stale-while-revalidate.ts
105
+ var staleWhileRevalidate = async function(handler, context, next) {
106
+ const [key, cache2] = await handler.getCache(context);
107
+ if (cache2) {
108
+ context.emitter.emit("cache:hit", { key, response: cache2.response, context });
109
+ const orchestrator = context.orchestration.fork();
110
+ context.res = cache2.response;
111
+ setTimeout(async () => {
112
+ try {
113
+ await orchestrator.execute();
114
+ const context2 = orchestrator.context;
115
+ const [, entry] = await handler.setCache(context2);
116
+ if (entry) {
117
+ context2.emitter.emit("cache:update", {
118
+ key,
119
+ oldResponse: cache2.response,
120
+ newResponse: entry.response,
121
+ context: context2
122
+ });
123
+ }
124
+ } catch (err) {
125
+ }
126
+ }, 1);
127
+ } else {
128
+ context.emitter.emit("cache:miss", { key, context });
129
+ await next();
130
+ const [, entry] = await handler.setCache(context);
131
+ if (entry) {
132
+ context.emitter.emit("cache:update", {
133
+ key,
134
+ oldResponse: void 0,
135
+ newResponse: entry.response,
136
+ context
137
+ });
138
+ }
139
+ }
140
+ };
141
+
142
+ // src/constants/strategy.enum.ts
143
+ var Strategy = {
144
+ STALE_WHILE_REVALIDATE: staleWhileRevalidate,
145
+ NETWORK_FIRST: networkFirst,
146
+ NETWORK_ONLY: networkOnly,
147
+ CACHE_FIRST: cacheFirst
148
+ };
149
+
56
150
  // src/cache-entry/cache-entry.ts
57
151
  var CacheEntry = class _CacheEntry {
58
152
  constructor(options) {
@@ -66,13 +160,13 @@ var CacheEntry = class _CacheEntry {
66
160
  __publicField(this, "expiredAt");
67
161
  var _a;
68
162
  this.key = options.key;
69
- this.response = options.response;
163
+ this.response = createProxyResponse(options.response);
70
164
  this.size = options.size;
71
- this.expiredAt = (_a = options.expiredAt) != null ? _a : /* @__PURE__ */ new Date(864e13);
165
+ this.expiredAt = (_a = options.expiredAt) != null ? _a : MAX_EXPIRED_AT;
72
166
  }
73
167
  static async build(options) {
74
168
  var _a;
75
- 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);
169
+ 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;
76
170
  const response = options.response.clone();
77
171
  return new _CacheEntry({
78
172
  key: options.key,
@@ -98,164 +192,106 @@ var CacheEntry = class _CacheEntry {
98
192
  }
99
193
  };
100
194
 
101
- // src/strategies/utils/cache-context.ts
102
- async function cacheContext(opts, context) {
103
- if (!context.response) return;
104
- if (opts.exclude && await opts.exclude(context.response)) return;
105
- const key = opts.key;
106
- const storage = opts.storage;
107
- const entry = await CacheEntry.build({
108
- key,
109
- response: context.response,
110
- ttl: opts.ttl
111
- });
112
- storage.set(entry);
113
- return entry;
114
- }
195
+ // src/request-cache-handler/request-cache-handler.ts
196
+ var RequestCacheHandler = class {
197
+ constructor(storage, options) {
198
+ this.storage = storage;
199
+ this.options = options;
200
+ }
201
+ /**
202
+ * Get cache key for request
203
+ */
204
+ getRequestCacheKey(context) {
205
+ const options = this.options;
206
+ if (typeof options.key === "string") return options.key;
207
+ else if (typeof options.key === "function") return options.key(context);
208
+ else if (R.isNil(options.key) && context.locationId) return context.locationId;
209
+ else throw new CacheException("Cannot resolve cache key");
210
+ }
211
+ /**
212
+ * Get cache from storage
213
+ */
214
+ async getCache(context) {
215
+ const key = this.getRequestCacheKey(context);
216
+ return [key, await this.storage.get(key)];
217
+ }
218
+ /**
219
+ * Store response that in context to storage
220
+ */
221
+ async setCache(context) {
222
+ const options = this.options;
223
+ const key = this.getRequestCacheKey(context);
224
+ if (!context.response) return [key, void 0];
225
+ if (options.exclude && await options.exclude(context.response)) return [key, void 0];
226
+ const entry = await CacheEntry.build({
227
+ key,
228
+ response: context.response,
229
+ ttl: options.ttl
230
+ });
231
+ void this.storage.set(entry);
232
+ return [key, entry];
233
+ }
234
+ };
115
235
 
116
- // src/strategies/cache-first.ts
117
- var cacheFirst = function(opts) {
118
- const { storage, key } = opts;
119
- return async function(context, next) {
120
- const cache2 = await storage.get(key);
121
- if (cache2) {
122
- context.emitter.emit("cache:hit", { key, response: cache2.response, context });
123
- context.res = cache2.response;
236
+ // src/cache.ts
237
+ function cache(options) {
238
+ const storage = options.storage;
239
+ const rules = (options == null ? void 0 : options.rules) || [];
240
+ return async function cache2(ctx, next) {
241
+ if (ctx.options.cache === false) {
242
+ await next();
124
243
  return;
125
244
  }
126
- context.emitter.emit("cache:miss", { key, context });
127
- await next();
128
- const entry = await cacheContext(opts, context);
129
- if (entry) {
130
- context.emitter.emit("cache:update", {
131
- key,
132
- oldResponse: void 0,
133
- newResponse: entry.response,
134
- context
135
- });
136
- }
137
- };
138
- };
139
-
140
- // src/strategies/network-first.ts
141
- var networkFirst = function(opts) {
142
- const { key, storage } = opts;
143
- return async function(context, next) {
144
- try {
245
+ let requestCacheOptions = ctx.options.cache;
246
+ const rule = rules.find((rule2) => {
247
+ if (rule2.pattern === void 0 || rule2.pattern === true) return true;
248
+ if (typeof rule2.pattern === "function") return rule2.pattern(ctx);
249
+ return rule2.pattern.test(ctx.request.__url__.href);
250
+ });
251
+ if (rule) requestCacheOptions = R2.mergeRight(rule, requestCacheOptions || {});
252
+ if (!requestCacheOptions || R2.isEmpty(requestCacheOptions)) {
145
253
  await next();
146
- const cache2 = await storage.get(key);
147
- const entry = await cacheContext(opts, context);
148
- if (entry) {
149
- context.emitter.emit("cache:update", {
150
- key,
151
- oldResponse: cache2 == null ? void 0 : cache2.response,
152
- newResponse: entry.response,
153
- context
154
- });
155
- }
156
- } catch (err) {
157
- const cache2 = await storage.get(key);
158
- if (!cache2) {
159
- context.emitter.emit("cache:miss", { key, context });
160
- throw err;
161
- }
162
- context.emitter.emit("cache:hit", { key, response: cache2.response, context });
163
- context.res = cache2.response;
254
+ return;
164
255
  }
165
- };
166
- };
167
-
168
- // src/strategies/network-only.ts
169
- var networkOnly = function(opts) {
170
- return async function(ctx, next) {
171
- await next();
172
- };
173
- };
174
-
175
- // src/strategies/stale-while-revalidate.ts
176
- var staleWhileRevalidate = function(opts) {
177
- const { key, storage } = opts;
178
- return async function(context, next) {
179
- const cache2 = await storage.get(key);
180
- if (cache2) {
181
- context.emitter.emit("cache:hit", { key, response: cache2.response, context });
182
- const orchestrator = context.orchestration.fork();
183
- context.res = cache2.response;
184
- setTimeout(async () => {
185
- try {
186
- await orchestrator.execute();
187
- const context2 = orchestrator.context;
188
- const entry = await cacheContext(opts, context2);
189
- if (entry) {
190
- context2.emitter.emit("cache:update", {
191
- key,
192
- oldResponse: cache2.response,
193
- newResponse: entry.response,
194
- context: context2
195
- });
196
- }
197
- } catch (err) {
198
- }
199
- }, 1);
200
- } else {
201
- context.emitter.emit("cache:miss", { key, context });
256
+ if (!requestCacheOptions.key) requestCacheOptions.key = options.keyFactory;
257
+ if (!ctx.locationId && !requestCacheOptions.key) {
258
+ console.warn("[@keq/cache] Warning: Cannot resolve Cache Key. Cache is skipped.");
202
259
  await next();
203
- const entry = await cacheContext(opts, context);
204
- if (entry) {
205
- context.emitter.emit("cache:update", {
206
- key,
207
- oldResponse: void 0,
208
- newResponse: entry.response,
209
- context
210
- });
211
- }
260
+ return;
212
261
  }
262
+ const handler = new RequestCacheHandler(storage, requestCacheOptions);
263
+ const strategy = requestCacheOptions.strategy;
264
+ await strategy(handler, ctx, next);
213
265
  };
214
- };
215
-
216
- // src/constants/strategy.enum.ts
217
- var Strategy = {
218
- STALE_WHILE_REVALIDATE: staleWhileRevalidate,
219
- NETWORK_FIRST: networkFirst,
220
- NETWORK_ONLY: networkOnly,
221
- CACHE_FIRST: cacheFirst
222
- };
223
-
224
- // src/constants/eviction.enum.ts
225
- var Eviction = /* @__PURE__ */ ((Eviction2) => {
226
- Eviction2["LRU"] = "lru";
227
- Eviction2["LFU"] = "lfu";
228
- Eviction2["RANDOM"] = "random";
229
- Eviction2["TTL"] = "ttl";
230
- return Eviction2;
231
- })(Eviction || {});
232
-
233
- // src/constants/size.enum.ts
234
- var Size = /* @__PURE__ */ ((Size2) => {
235
- Size2[Size2["B"] = 1] = "B";
236
- Size2[Size2["KB"] = 1024] = "KB";
237
- Size2[Size2["MB"] = 1048576] = "MB";
238
- Size2[Size2["GB"] = 1073741824] = "GB";
239
- return Size2;
240
- })(Size || {});
266
+ }
241
267
 
242
268
  // src/storage/memory-storage/ttl-memory-storage.ts
243
269
  import dayjs2 from "dayjs";
244
- import * as R3 from "ramda";
270
+ import * as R4 from "ramda";
245
271
 
246
272
  // src/storage/memory-storage/base-memory-storage.ts
247
273
  import dayjs from "dayjs";
248
- import * as R2 from "ramda";
249
-
250
- // src/utils/debug.ts
251
- function debug(...args) {
252
- console.debug("[@keq-cache] [DEBUG] ", ...args);
253
- }
274
+ import * as R3 from "ramda";
254
275
 
255
276
  // src/storage/keq-cache-storage.ts
256
277
  var KeqCacheStorage = class {
257
278
  };
258
279
 
280
+ // src/utils/logger.ts
281
+ var Logger = class {
282
+ static debug(...args) {
283
+ console.debug("[@keq-cache] [DEBUG] ", ...args);
284
+ }
285
+ static error(...args) {
286
+ console.error("[@keq-cache] [ERROR] ", ...args);
287
+ }
288
+ };
289
+
290
+ // src/utils/random.ts
291
+ function random(min, max) {
292
+ return Math.floor(Math.random() * (max - min)) + min;
293
+ }
294
+
259
295
  // src/storage/internal-storage/internal-storage.ts
260
296
  var InternalStorage = class extends KeqCacheStorage {
261
297
  constructor(options) {
@@ -270,7 +306,7 @@ var InternalStorage = class extends KeqCacheStorage {
270
306
  __publicField(this, "__onCacheEvict__");
271
307
  __publicField(this, "__onCacheExpired__");
272
308
  if ((options == null ? void 0 : options.size) && (typeof (options == null ? void 0 : options.size) !== "number" || options.size <= 0)) {
273
- throw TypeError("Invalid size: ".concat(String(options == null ? void 0 : options.size)));
309
+ throw new CacheException("Invalid size: ".concat(String(options == null ? void 0 : options.size)));
274
310
  }
275
311
  this.__size__ = (_a = options == null ? void 0 : options.size) != null ? _a : Infinity;
276
312
  this.__debug__ = !!(options == null ? void 0 : options.debug);
@@ -283,12 +319,38 @@ var InternalStorage = class extends KeqCacheStorage {
283
319
  debug(fn) {
284
320
  if (this.__debug__) {
285
321
  fn((...args) => {
286
- debug("[Storage(".concat(this.__id__, ")]"), ...args);
322
+ Logger.debug("[Storage(".concat(this.__id__, ")]"), ...args);
287
323
  });
288
324
  }
289
325
  }
290
326
  };
291
327
 
328
+ // src/storage/memory-storage/utils/humanize-size.ts
329
+ function humanizeSize(size) {
330
+ if (size < 1024) return "".concat(size, " B");
331
+ if (size < 1024 * 1024) return "".concat((size / 1024).toFixed(2), " KB");
332
+ if (size < 1024 * 1024 * 1024) return "".concat((size / (1024 * 1024)).toFixed(2), " MB");
333
+ return "".concat((size / (1024 * 1024 * 1024)).toFixed(2), " GB");
334
+ }
335
+
336
+ // src/storage/memory-storage/utils/serialize-response-body.ts
337
+ async function serializeResponseBody(response) {
338
+ var _a;
339
+ const contentType = (_a = response.headers.get("content-type")) != null ? _a : "";
340
+ try {
341
+ if (contentType.includes("application/json")) {
342
+ const json = await response.json();
343
+ return JSON.stringify(json);
344
+ }
345
+ if (contentType.includes("text/") || contentType.includes("application/xml") || contentType.includes("application/javascript")) {
346
+ return await response.text();
347
+ }
348
+ return "[Binary or unsupported content]";
349
+ } catch {
350
+ return "[Unable to serialize]";
351
+ }
352
+ }
353
+
292
354
  // src/storage/memory-storage/base-memory-storage.ts
293
355
  var BaseMemoryStorage = class extends InternalStorage {
294
356
  constructor() {
@@ -299,7 +361,7 @@ var BaseMemoryStorage = class extends InternalStorage {
299
361
  __publicField(this, "lastEvictExpiredTime", dayjs());
300
362
  }
301
363
  get size() {
302
- const used = R2.sum(R2.pluck("size", [...this.storage.values()]));
364
+ const used = R3.sum(R3.pluck("size", [...this.storage.values()]));
303
365
  const free = this.__size__ > used ? this.__size__ - used : 0;
304
366
  return {
305
367
  used,
@@ -342,23 +404,6 @@ var BaseMemoryStorage = class extends InternalStorage {
342
404
  remove(key) {
343
405
  this.__remove__([key]);
344
406
  }
345
- /**
346
- * Print all cache entries
347
- */
348
- print() {
349
- const entries = Array.from(this.storage.entries()).map(([key, entry]) => {
350
- var _a;
351
- return {
352
- key,
353
- size: entry.size,
354
- expiredAt: entry.expiredAt ? dayjs(entry.expiredAt).format("YYYY-MM-DD HH:mm:ss") : "N/A",
355
- visitCount: (_a = this.visitCountRecords.get(key)) != null ? _a : 0,
356
- lastVisit: this.visitTimeRecords.get(key) ? dayjs(this.visitTimeRecords.get(key)).format("YYYY-MM-DD HH:mm:ss") : "N/A"
357
- };
358
- });
359
- console.table(entries);
360
- console.log("Total: ".concat(entries.length, " entries, Used: ").concat(this.size.used, ", Free: ").concat(this.size.free));
361
- }
362
407
  /**
363
408
  * @zh 清除过期的缓存
364
409
  */
@@ -386,6 +431,33 @@ var BaseMemoryStorage = class extends InternalStorage {
386
431
  const size = this.size;
387
432
  return size.free >= expectSize;
388
433
  }
434
+ /**
435
+ * @en Print all cached data using console.table for debugging
436
+ * @zh 使用 console.table 打印所有缓存数据,用于调试
437
+ */
438
+ async print() {
439
+ if (this.storage.size === 0) {
440
+ console.log("MemoryStorage is empty");
441
+ return;
442
+ }
443
+ const entries = await Promise.all(
444
+ [...this.storage.entries()].map(async ([key, entry]) => {
445
+ var _a, _b, _c;
446
+ const body = await serializeResponseBody(entry.response.clone());
447
+ return {
448
+ key,
449
+ size: humanizeSize(entry.size),
450
+ "Expired Time": entry.expiredAt.getTime() >= MAX_EXPIRED_AT.getTime() ? "-" : entry.expiredAt.toISOString(),
451
+ "Visit Count": (_a = this.visitCountRecords.get(key)) != null ? _a : 0,
452
+ "Last Visit Time": (_c = (_b = this.visitTimeRecords.get(key)) == null ? void 0 : _b.toISOString()) != null ? _c : "-",
453
+ "Response Status": entry.response.status,
454
+ "Response URL": entry.response.url,
455
+ "Response Body": body
456
+ };
457
+ })
458
+ );
459
+ console.table(entries);
460
+ }
389
461
  };
390
462
 
391
463
  // src/storage/memory-storage/ttl-memory-storage.ts
@@ -423,7 +495,7 @@ var TTLMemoryStorage = class extends BaseMemoryStorage {
423
495
  const bExpiredAt = dayjs2(b.expiredAt);
424
496
  return aExpiredAt.isBefore(bExpiredAt) ? 1 : -1;
425
497
  });
426
- if (R3.sum(R3.pluck("size", entries)) < deficitSize) {
498
+ if (R4.sum(R4.pluck("size", entries)) < deficitSize) {
427
499
  this.debug((log) => log("Storage Size Not Enough: ", this.size.free, " < ", deficitSize));
428
500
  return false;
429
501
  }
@@ -439,11 +511,6 @@ var TTLMemoryStorage = class extends BaseMemoryStorage {
439
511
  }
440
512
  };
441
513
 
442
- // src/utils/random.ts
443
- function random(min, max) {
444
- return Math.floor(Math.random() * (max - min)) + min;
445
- }
446
-
447
514
  // src/storage/memory-storage/random-memory-storage.ts
448
515
  var RandomMemoryStorage = class extends BaseMemoryStorage {
449
516
  constructor(options) {
@@ -614,15 +681,18 @@ var MemoryStorage = class extends KeqCacheStorage {
614
681
  remove(key) {
615
682
  return this.storage.remove(key);
616
683
  }
684
+ async print() {
685
+ return this.storage.print();
686
+ }
617
687
  };
618
688
 
619
689
  // src/storage/indexed-db-storage/random-indexed-db-storage.ts
620
- import * as R5 from "ramda";
690
+ import * as R6 from "ramda";
621
691
 
622
692
  // src/storage/indexed-db-storage/base-indexed-db-storage.ts
623
- import * as R4 from "ramda";
624
- import { openDB } from "idb";
693
+ import * as R5 from "ramda";
625
694
  import dayjs4 from "dayjs";
695
+ import { openDB } from "idb";
626
696
 
627
697
  // src/storage/indexed-db-storage/constants/default-table-name.ts
628
698
  var DEFAULT_TABLE_NAME = "keq_cache_indexed_db_storage";
@@ -633,9 +703,9 @@ var BaseIndexedDBStorage = class extends InternalStorage {
633
703
  super(options);
634
704
  __publicField(this, "tableName", DEFAULT_TABLE_NAME);
635
705
  __publicField(this, "db");
636
- __publicField(this, "lastEvictExpiredTime", dayjs4());
706
+ __publicField(this, "lastEvictExpiredTime", dayjs4(0));
637
707
  if ((options == null ? void 0 : options.tableName) === DEFAULT_TABLE_NAME) {
638
- throw new TypeError('[keq-cache] IndexedDBStorage name cannot be "'.concat(DEFAULT_TABLE_NAME, '"'));
708
+ throw new CacheException('IndexedDBStorage name cannot be "'.concat(DEFAULT_TABLE_NAME, '"'));
639
709
  }
640
710
  this.tableName = (options == null ? void 0 : options.tableName) || DEFAULT_TABLE_NAME;
641
711
  }
@@ -659,13 +729,13 @@ var BaseIndexedDBStorage = class extends InternalStorage {
659
729
  }
660
730
  },
661
731
  blocked() {
662
- console.error("IndexedDB Table ".concat(tableName, " is blocked"));
732
+ Logger.error("[@keq-request/cache] IndexedDB Table ".concat(tableName, " is blocked"));
663
733
  },
664
734
  blocking() {
665
- console.error("IndexedDB Table ".concat(tableName, " is blocking"));
735
+ Logger.error("[@keq-request/cache] IndexedDB Table ".concat(tableName, " is blocking"));
666
736
  },
667
737
  terminated() {
668
- console.error("IndexedDB Table ".concat(tableName, " is terminated"));
738
+ Logger.error("[@keq-request/cache] IndexedDB Table ".concat(tableName, " is terminated"));
669
739
  }
670
740
  });
671
741
  this.db = db;
@@ -674,7 +744,7 @@ var BaseIndexedDBStorage = class extends InternalStorage {
674
744
  async getSize() {
675
745
  const db = await this.openDB();
676
746
  const items = await db.getAll("metadata");
677
- const used = R4.sum(items.map((entry) => entry.size));
747
+ const used = R5.sum(items.map((entry) => entry.size));
678
748
  const free = this.__size__ - used;
679
749
  return { used, free };
680
750
  }
@@ -750,7 +820,7 @@ var BaseIndexedDBStorage = class extends InternalStorage {
750
820
  }
751
821
  async __remove__(tx, keys) {
752
822
  await Promise.all(
753
- R4.unnest(
823
+ R5.unnest(
754
824
  keys.map((key) => [
755
825
  tx.objectStore("metadata").delete(key),
756
826
  tx.objectStore("response").delete(key),
@@ -776,15 +846,15 @@ var BaseIndexedDBStorage = class extends InternalStorage {
776
846
  var _a;
777
847
  const now = dayjs4();
778
848
  if (now.diff(this.lastEvictExpiredTime, "second") < 1) return;
849
+ this.lastEvictExpiredTime = now;
779
850
  try {
780
- const now2 = dayjs4();
781
851
  const db = await this.openDB();
782
852
  const tx = db.transaction(["metadata", "response", "visits"], "readwrite");
783
853
  const metadataStore = tx.objectStore("metadata");
784
- let cursor = await metadataStore.index("expiredAt").openCursor(IDBKeyRange.upperBound(now2.valueOf()));
854
+ let cursor = await metadataStore.index("expiredAt").openCursor(IDBKeyRange.upperBound(now.toDate()));
785
855
  const expiredKeys = [];
786
856
  while (cursor) {
787
- if (dayjs4(cursor.value.expiredAt).isBefore(now2)) {
857
+ if (dayjs4(cursor.value.expiredAt).isBefore(now)) {
788
858
  expiredKeys.push(cursor.value.key);
789
859
  cursor = await cursor.continue();
790
860
  } else {
@@ -831,7 +901,7 @@ var RandomIndexedDBStorage = class extends BaseIndexedDBStorage {
831
901
  const tx = db.transaction(["metadata", "response", "visits"], "readwrite");
832
902
  const metadataStore = tx.objectStore("metadata");
833
903
  const metadatas = await metadataStore.getAll();
834
- const totalSize = R5.sum(metadatas.map((m) => m.size));
904
+ const totalSize = R6.sum(metadatas.map((m) => m.size));
835
905
  if (totalSize < deficitSize) {
836
906
  this.debug((log) => log("Storage Size Not Enough, deficit size: ".concat(deficitSize - totalSize)));
837
907
  tx.abort();
@@ -1034,7 +1104,7 @@ var IndexedDBStorage = class extends KeqCacheStorage {
1034
1104
  } else if (eviction === "ttl" /* TTL */) {
1035
1105
  this.storage = new TTLIndexedDBStorage(options);
1036
1106
  } else {
1037
- throw TypeError("Not Supported Eviction: ".concat(String(options == null ? void 0 : options.eviction)));
1107
+ throw new CacheException("Not Supported Eviction: ".concat(String(options == null ? void 0 : options.eviction)));
1038
1108
  }
1039
1109
  }
1040
1110
  set(entry) {
@@ -1084,7 +1154,7 @@ var MultiTierStorage = class extends KeqCacheStorage {
1084
1154
  * @zh 并发写入所有层的缓存
1085
1155
  */
1086
1156
  async set(entry) {
1087
- const promises = this.storages.map((storage) => storage.set(entry));
1157
+ const promises = this.storages.map(async (storage) => storage.set(entry));
1088
1158
  await Promise.all(promises);
1089
1159
  }
1090
1160
  /**
@@ -1092,7 +1162,7 @@ var MultiTierStorage = class extends KeqCacheStorage {
1092
1162
  * @zh 从所有层删除缓存条目
1093
1163
  */
1094
1164
  async remove(key) {
1095
- const promises = this.storages.map((storage) => storage.remove(key));
1165
+ const promises = this.storages.map(async (storage) => storage.remove(key));
1096
1166
  await Promise.all(promises);
1097
1167
  }
1098
1168
  /**
@@ -1104,7 +1174,7 @@ var MultiTierStorage = class extends KeqCacheStorage {
1104
1174
  if (lowerTierStorages.length === 0) {
1105
1175
  return;
1106
1176
  }
1107
- const promises = lowerTierStorages.map((storage) => storage.set(entry.clone()));
1177
+ const promises = lowerTierStorages.map(async (storage) => storage.set(entry.clone()));
1108
1178
  try {
1109
1179
  await Promise.all(promises);
1110
1180
  } catch (error) {
@@ -1124,10 +1194,11 @@ var TierStorage = class extends MultiTierStorage {
1124
1194
  }
1125
1195
  };
1126
1196
  export {
1127
- KeqCacheStorage as CacheStorage,
1128
1197
  Eviction,
1129
1198
  IndexedDBStorage,
1199
+ KeqCacheStorage,
1130
1200
  MemoryStorage,
1201
+ MultiTierStorage,
1131
1202
  Size,
1132
1203
  Strategy,
1133
1204
  TierStorage,