@keq-request/cache 5.0.0-alpha.28 → 5.0.0-alpha.30
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.
- package/CHANGELOG.md +13 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/index.js +13 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13 -13
- package/dist/index.mjs.map +1 -1
- package/dist/request-cache-handler/request-cache-handler.d.ts +5 -4
- package/dist/request-cache-handler/request-cache-handler.d.ts.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 5.0.0-alpha.30
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- keq@5.0.0-alpha.30
|
|
8
|
+
|
|
9
|
+
## 5.0.0-alpha.29
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- ff5464b: Prevent other middlewares from inadvertently modifying the cache key.
|
|
14
|
+
- keq@5.0.0-alpha.29
|
|
15
|
+
|
|
3
16
|
## 5.0.0-alpha.28
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAA;AAC5C,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAEhE,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAGxF,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,mBAAmB,EAAE,cAAc,CAAC;IAChF,OAAO,EAAE,eAAe,CAAA;IAExB;;OAEG;IACH,UAAU,CAAC,EAAE,kBAAkB,CAAA;IAE/B,KAAK,CAAC,EAAE,YAAY,EAAE,CAAA;CACvB;AAGD,OAAO,QAAQ,KAAK,CAAC;IACnB,UAAiB,oBAAoB,CAAC,EAAE;QACtC;;WAEG;QACH,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,KAAK,GAAG,GAAG,CAAC,EAAE,CAAC,CAAA;KACpD;IAED,UAAiB,SAAS;QACxB,WAAW,EAAE;YACX,GAAG,EAAE,MAAM,CAAA;YACX,QAAQ,EAAE,QAAQ,CAAA;YAClB,OAAO,EAAE,UAAU,CAAA;SACpB,CAAA;QAED,YAAY,EAAE;YACZ,GAAG,EAAE,MAAM,CAAA;YACX,OAAO,EAAE,UAAU,CAAA;SACpB,CAAA;QAED,cAAc,EAAE;YACd,GAAG,EAAE,MAAM,CAAA;YACX,WAAW,CAAC,EAAE,QAAQ,CAAA;YACtB,WAAW,EAAE,QAAQ,CAAA;YACrB,OAAO,EAAE,UAAU,CAAA;SACpB,CAAA;KACF;IAED,UAAiB,aAAa;QAC5B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;YAAE,IAAI,EAAE,OAAO,CAAA;SAAE,EAAE,IAAI,CAAC,CAAC,CAAA;KACjE;CACF;AAGD,wBAAgB,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAA;AAC5C,OAAO,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAEhE,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AAGxF,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAAC,mBAAmB,EAAE,cAAc,CAAC;IAChF,OAAO,EAAE,eAAe,CAAA;IAExB;;OAEG;IACH,UAAU,CAAC,EAAE,kBAAkB,CAAA;IAE/B,KAAK,CAAC,EAAE,YAAY,EAAE,CAAA;CACvB;AAGD,OAAO,QAAQ,KAAK,CAAC;IACnB,UAAiB,oBAAoB,CAAC,EAAE;QACtC;;WAEG;QACH,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,KAAK,GAAG,GAAG,CAAC,EAAE,CAAC,CAAA;KACpD;IAED,UAAiB,SAAS;QACxB,WAAW,EAAE;YACX,GAAG,EAAE,MAAM,CAAA;YACX,QAAQ,EAAE,QAAQ,CAAA;YAClB,OAAO,EAAE,UAAU,CAAA;SACpB,CAAA;QAED,YAAY,EAAE;YACZ,GAAG,EAAE,MAAM,CAAA;YACX,OAAO,EAAE,UAAU,CAAA;SACpB,CAAA;QAED,cAAc,EAAE;YACd,GAAG,EAAE,MAAM,CAAA;YACX,WAAW,CAAC,EAAE,QAAQ,CAAA;YACtB,WAAW,EAAE,QAAQ,CAAA;YACrB,OAAO,EAAE,UAAU,CAAA;SACpB,CAAA;KACF;IAED,UAAiB,aAAa;QAC5B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC;YAAE,IAAI,EAAE,OAAO,CAAA;SAAE,EAAE,IAAI,CAAC,CAAC,CAAA;KACjE;CACF;AAGD,wBAAgB,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,aAAa,CA8D7D"}
|
package/dist/index.js
CHANGED
|
@@ -110,7 +110,7 @@ function random(min, max) {
|
|
|
110
110
|
|
|
111
111
|
// src/strategies/cache-first.ts
|
|
112
112
|
var cacheFirst = async function cacheFirst2(handler, context, next) {
|
|
113
|
-
const [cacheKey, cacheValue] = await handler.getCache(
|
|
113
|
+
const [cacheKey, cacheValue] = await handler.getCache();
|
|
114
114
|
if (handler.options.debug) {
|
|
115
115
|
Logger.debug([
|
|
116
116
|
"",
|
|
@@ -151,7 +151,7 @@ var cacheFirst = async function cacheFirst2(handler, context, next) {
|
|
|
151
151
|
var networkFirst = async function networkFirst2(handler, context, next) {
|
|
152
152
|
try {
|
|
153
153
|
await next();
|
|
154
|
-
const [cacheKey, cache2] = await handler.getCache(
|
|
154
|
+
const [cacheKey, cache2] = await handler.getCache();
|
|
155
155
|
const [, entry] = await handler.setCache(context);
|
|
156
156
|
if (handler.options.debug) {
|
|
157
157
|
Logger.debug([
|
|
@@ -171,7 +171,7 @@ var networkFirst = async function networkFirst2(handler, context, next) {
|
|
|
171
171
|
});
|
|
172
172
|
}
|
|
173
173
|
} catch (err) {
|
|
174
|
-
const [cacheKey, cache2] = await handler.getCache(
|
|
174
|
+
const [cacheKey, cache2] = await handler.getCache();
|
|
175
175
|
if (handler.options.debug) {
|
|
176
176
|
Logger.debug([
|
|
177
177
|
"",
|
|
@@ -197,7 +197,7 @@ var networkOnly = async function(handler, context, next) {
|
|
|
197
197
|
|
|
198
198
|
// src/strategies/stale-while-revalidate.ts
|
|
199
199
|
var staleWhileRevalidate = async function(handler, context, next) {
|
|
200
|
-
const [cacheKey, cache2] = await handler.getCache(
|
|
200
|
+
const [cacheKey, cache2] = await handler.getCache();
|
|
201
201
|
if (handler.options.debug) {
|
|
202
202
|
Logger.debug([
|
|
203
203
|
"",
|
|
@@ -318,15 +318,15 @@ var CacheEntry = class _CacheEntry {
|
|
|
318
318
|
|
|
319
319
|
// src/request-cache-handler/request-cache-handler.ts
|
|
320
320
|
var RequestCacheHandler = class {
|
|
321
|
-
constructor(storage, options) {
|
|
321
|
+
constructor(cacheKey, storage, options) {
|
|
322
|
+
this.cacheKey = cacheKey;
|
|
322
323
|
this.storage = storage;
|
|
323
324
|
this.options = options;
|
|
324
325
|
}
|
|
325
326
|
/**
|
|
326
|
-
*
|
|
327
|
+
* Resolve cache key for request context
|
|
327
328
|
*/
|
|
328
|
-
|
|
329
|
-
const options = this.options;
|
|
329
|
+
static resolveRequestCacheKey(context, options) {
|
|
330
330
|
if (typeof options.key === "string") return options.key;
|
|
331
331
|
else if (typeof options.key === "function") return options.key(context);
|
|
332
332
|
else if (R.isNil(options.key) && context.locationId) return context.locationId;
|
|
@@ -335,8 +335,8 @@ var RequestCacheHandler = class {
|
|
|
335
335
|
/**
|
|
336
336
|
* Get cache from storage
|
|
337
337
|
*/
|
|
338
|
-
async getCache(
|
|
339
|
-
const key = this.
|
|
338
|
+
async getCache() {
|
|
339
|
+
const key = this.cacheKey;
|
|
340
340
|
if (this.options.serverTiming) {
|
|
341
341
|
const startAt = /* @__PURE__ */ new Date();
|
|
342
342
|
const entry = await this.storage.get(key);
|
|
@@ -355,7 +355,7 @@ var RequestCacheHandler = class {
|
|
|
355
355
|
*/
|
|
356
356
|
async setCache(context) {
|
|
357
357
|
const options = this.options;
|
|
358
|
-
const key = this.
|
|
358
|
+
const key = this.cacheKey;
|
|
359
359
|
if (!context.response) return [key, void 0];
|
|
360
360
|
if (options.exclude && await options.exclude(context.response)) return [key, void 0];
|
|
361
361
|
const entry = await CacheEntry.build({
|
|
@@ -397,14 +397,14 @@ function cache(options) {
|
|
|
397
397
|
if (requestCacheOptions.serverTiming === void 0 && options.serverTiming !== void 0) {
|
|
398
398
|
requestCacheOptions.serverTiming = options.serverTiming;
|
|
399
399
|
}
|
|
400
|
-
const
|
|
400
|
+
const cacheKey = RequestCacheHandler.resolveRequestCacheKey(ctx, requestCacheOptions);
|
|
401
|
+
const handler = new RequestCacheHandler(cacheKey, storage, requestCacheOptions);
|
|
401
402
|
const strategy = requestCacheOptions.strategy;
|
|
402
403
|
if (requestCacheOptions.concurrent) {
|
|
403
404
|
await strategy(handler, ctx, next);
|
|
404
405
|
} else {
|
|
405
406
|
if (!ctx.global.core) ctx.global.core = {};
|
|
406
407
|
if (!ctx.global.core.cache) ctx.global.core.cache = {};
|
|
407
|
-
const cacheKey = handler.getRequestCacheKey(ctx);
|
|
408
408
|
if (!ctx.global.core.cache[cacheKey]) {
|
|
409
409
|
ctx.global.core.cache[cacheKey] = fastq.promise(async ({ next: next2 }) => {
|
|
410
410
|
await next2();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/cache.ts","../src/request-cache-handler/request-cache-handler.ts","../src/exceptions/cache-exception.ts","../src/cache-entry/cache-entry.ts","../src/utils/get-response-bytes.ts","../src/constants/max-expired-at.ts","../src/constants/eviction.enum.ts","../src/constants/size.enum.ts","../src/utils/logger.ts","../src/utils/random.ts","../src/strategies/cache-first.ts","../src/strategies/network-first.ts","../src/strategies/network-only.ts","../src/strategies/stale-while-revalidate.ts","../src/constants/strategy.enum.ts","../src/storage/memory-storage/ttl-memory-storage.ts","../src/storage/memory-storage/base-memory-storage.ts","../src/storage/keq-cache-storage.ts","../src/storage/internal-storage/internal-storage.ts","../src/storage/memory-storage/utils/humanize-size.ts","../src/storage/memory-storage/utils/serialize-response-body.ts","../src/storage/memory-storage/random-memory-storage.ts","../src/storage/memory-storage/lru-memory-storage.ts","../src/storage/memory-storage/lfu-memory-storage.ts","../src/storage/memory-storage/memory-storage.ts","../src/storage/indexed-db-storage/random-indexed-db-storage.ts","../src/storage/indexed-db-storage/base-indexed-db-storage.ts","../src/storage/indexed-db-storage/constants/default-table-name.ts","../src/storage/indexed-db-storage/lfu-indexed-db-storage.ts","../src/storage/indexed-db-storage/lru-indexed-db-storage.ts","../src/storage/indexed-db-storage/ttl-indexed-db-storage.ts","../src/storage/indexed-db-storage/indexed-db-storage.ts","../src/storage/multi-tier-storage/multi-tier-storage.ts","../src/storage/tier-storage/tier-storage.ts"],"sourcesContent":["export * from './cache.js'\n\nexport {\n Strategy,\n Eviction,\n Size,\n} from './constants/index.js'\n\n\nexport {\n KeqCacheStorage,\n IndexedDBStorage,\n MemoryStorage,\n MultiTierStorage,\n TierStorage,\n} from './storage/index.js'\n\nexport {\n type MemoryStorageOptions,\n type IndexedDbStorageOptions,\n type TierStorageOptions,\n type MultiTierStorageOptions,\n} from './storage/index.js'\n\n\nexport {\n type KeqCacheRule,\n type KeqCacheKey,\n type KeqCacheKeyFactory,\n type KeqCachePattern,\n type KeqCacheStrategy,\n} from './types/index.js'\n","import * as R from 'ramda'\nimport * as fastq from 'fastq'\nimport type { queueAsPromised } from 'fastq'\nimport type { Keq, KeqMiddleware, KeqContext, KeqNext } from 'keq'\nimport { KeqCacheStorage } from './storage/keq-cache-storage.js'\nimport { RequestCacheHandler } from './request-cache-handler/index.js'\nimport { KeqCacheKeyFactory, KeqCacheRule, RequestCacheOptions } from './types/index.js'\n\n\nexport interface KeqCacheOptions extends Pick<RequestCacheOptions, 'serverTiming'> {\n storage: KeqCacheStorage\n\n /**\n * Cache Key Factory\n */\n keyFactory?: KeqCacheKeyFactory\n\n rules?: KeqCacheRule[]\n}\n\n\ndeclare module 'keq' {\n export interface KeqMiddlewareOptions<OP> {\n /**\n * [keq-cache](https://github.com/keq-request/keq-cache)\n */\n cache(option: RequestCacheOptions | false): Keq<OP>\n }\n\n export interface KeqEvents {\n 'cache:hit': {\n key: string\n response: Response\n context: KeqContext\n }\n\n 'cache:miss': {\n key: string\n context: KeqContext\n }\n\n 'cache:update': {\n key: string\n oldResponse?: Response\n newResponse: Response\n context: KeqContext\n }\n }\n\n export interface KeqGlobalCore {\n cache?: Record<string, queueAsPromised<{ next: KeqNext }, void>>\n }\n}\n\n\nexport function cache(options: KeqCacheOptions): KeqMiddleware {\n const storage = options.storage\n\n const rules: KeqCacheRule[] = options?.rules || []\n\n return async function cache(ctx, next) {\n if (ctx.options.cache === false) {\n await next()\n return\n }\n\n let requestCacheOptions: RequestCacheOptions | undefined = ctx.options.cache\n // let requestOptions: KeqCacheRequestOptions | undefined = ctx.options.cache\n\n const rule = rules.find((rule) => {\n if (rule.pattern === undefined || rule.pattern === true) return true\n if (typeof rule.pattern === 'function') return rule.pattern(ctx)\n return rule.pattern.test(ctx.request.__url__.href)\n })\n\n if (rule) requestCacheOptions = R.mergeRight(rule, requestCacheOptions || ({} as any))\n\n if (!requestCacheOptions || R.isEmpty(requestCacheOptions)) {\n await next()\n return\n }\n\n if (!requestCacheOptions.key) requestCacheOptions.key = options.keyFactory\n\n if (!ctx.locationId && !requestCacheOptions.key) {\n console.warn('[@keq/cache] Warning: Cannot resolve Cache Key. Cache is skipped.')\n await next()\n return\n }\n\n if (requestCacheOptions.serverTiming === undefined && options.serverTiming !== undefined) {\n requestCacheOptions.serverTiming = options.serverTiming\n }\n\n\n const handler = new RequestCacheHandler(storage, requestCacheOptions)\n const strategy = requestCacheOptions.strategy\n\n if (requestCacheOptions.concurrent) {\n await strategy(handler, ctx, next)\n } else {\n if (!ctx.global.core) ctx.global.core = {}\n if (!ctx.global.core.cache) ctx.global.core.cache = {}\n\n const cacheKey = handler.getRequestCacheKey(ctx)\n if (!ctx.global.core.cache[cacheKey]) {\n ctx.global.core.cache[cacheKey] = fastq.promise(async ({ next }) => {\n await next()\n }, 1)\n }\n\n const queue = ctx.global.core.cache[cacheKey]!\n await queue.push({\n next: async () => {\n await strategy(handler, ctx, next)\n },\n })\n }\n }\n}\n","import * as R from 'ramda'\nimport { KeqContext } from 'keq'\nimport { CacheException } from '~/exceptions'\nimport { KeqCacheStorage } from '~/storage'\nimport { CacheEntry } from '~/cache-entry'\nimport { RequestCacheOptions } from '../types/index.js'\n\n\nexport type RequestCacheHandlerOptions = Omit<RequestCacheOptions, 'strategy'>\n\nexport class RequestCacheHandler {\n constructor(\n public readonly storage: KeqCacheStorage,\n public readonly options: Readonly<RequestCacheHandlerOptions>,\n ) {}\n\n /**\n * Get cache key for request\n */\n getRequestCacheKey(context: KeqContext): string {\n const options = this.options\n\n if (typeof options.key === 'string') return options.key\n else if (typeof options.key === 'function') return options.key(context)\n else if (R.isNil(options.key) && context.locationId) return context.locationId\n else throw new CacheException('Cannot resolve cache key')\n }\n\n /**\n * Get cache from storage\n */\n async getCache(context: KeqContext): Promise<[string, CacheEntry | undefined]> {\n const key = this.getRequestCacheKey(context)\n\n if (this.options.serverTiming) {\n const startAt = new Date()\n const entry = await this.storage.get(key)\n if (entry) {\n const dur = new Date().getTime() - startAt.getTime()\n\n const HeadersWithServerTiming = new Headers(entry.response.headers)\n HeadersWithServerTiming.set('Server-Timing', `keq-cache; dur=${dur}; desc=\"HIT\"`)\n\n entry.assignResponseHeaders(HeadersWithServerTiming)\n }\n\n return [key, entry]\n }\n\n return [key, await this.storage.get(key)]\n }\n\n /**\n * Store response that in context to storage\n */\n async setCache(context: KeqContext): Promise<[string, CacheEntry | undefined]> {\n const options = this.options\n const key = this.getRequestCacheKey(context)\n\n if (!context.response) return [key, undefined]\n if (options.exclude && (await options.exclude(context.response))) return [key, undefined]\n\n const entry = await CacheEntry.build({\n key,\n response: context.response,\n ttl: options.ttl,\n })\n\n void this.storage.set(entry)\n\n return [key, entry]\n }\n}\n","import { Exception } from 'keq'\n\nexport class CacheException extends Exception {\n constructor(message: string) {\n super(`[@keq-request/cache] ${message}`)\n }\n}\n","import { createProxyResponse } from 'keq'\nimport { getResponseBytes } from '~/utils/get-response-bytes.js'\nimport { CacheEntryOptions } from './types/cache-entry-options.js'\nimport { CacheEntryBuildOptions } from './types/cache-entry-build-options.js'\nimport { MAX_EXPIRED_AT } from '~/constants/index.js'\n\n\nexport class CacheEntry {\n key: string\n response: Response\n\n /**\n * @en bytes\n * @zh 字节数\n */\n size: number\n\n expiredAt: Date\n\n constructor(options: CacheEntryOptions) {\n this.key = options.key\n this.response = createProxyResponse(options.response)\n this.size = options.size\n this.expiredAt = options.expiredAt ?? MAX_EXPIRED_AT\n }\n\n static async build(options: CacheEntryBuildOptions): Promise<CacheEntry> {\n const expiredAt = 'expiredAt' in options\n ? options.expiredAt\n : ('ttl' in options && typeof options.ttl === 'number' && options.ttl > 0)\n ? new Date(Date.now() + options.ttl * 1000)\n : MAX_EXPIRED_AT\n\n const response = options.response.clone()\n return new CacheEntry({\n key: options.key,\n response,\n size: options.size ?? (await getResponseBytes(response)),\n expiredAt: expiredAt,\n })\n }\n\n clone(): CacheEntry {\n return new CacheEntry({\n key: this.key,\n response: this.response.clone(),\n size: this.size,\n expiredAt: this.expiredAt,\n })\n }\n\n assignResponseHeaders(headers: Headers): void {\n this.response = new Response(this.response.body, {\n status: this.response.status,\n statusText: this.response.statusText,\n headers: headers,\n })\n }\n}\n","export async function getResponseBytes(response: Response): Promise<number> {\n const contentLength = response.headers.get('content-length')\n if (contentLength) {\n return parseInt(contentLength)\n }\n\n const arrayBuffer = await response.clone().arrayBuffer()\n return arrayBuffer.byteLength\n}\n","export const MAX_EXPIRED_AT = new Date(8640000000000000)\n","export enum Eviction {\n LRU = 'lru',\n LFU = 'lfu',\n RANDOM = 'random',\n TTL = 'ttl',\n}\n","export enum Size {\n B = 1,\n KB = 1024,\n MB = 1024 * 1024,\n GB = 1024 * 1024 * 1024,\n}\n","export class Logger {\n static debug(...args: unknown[]): void {\n console.debug('[@keq-request/cache] [DEBUG] ', ...args)\n }\n\n static error(...args: unknown[]): void {\n console.error('[@keq-request/cache] [ERROR] ', ...args)\n }\n}\n","export function random(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min)) + min\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\n\nexport const cacheFirst: KeqCacheStrategy = async function cacheFirst(handler, context, next): Promise<void> {\n // return async function (context, next): Promise<void> {\n const [cacheKey, cacheValue] = await handler.getCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Cache First',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cacheValue ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (cacheValue) {\n // hit cache\n context.emitter.emit('cache:hit', { key: cacheKey, response: cacheValue.response, context })\n context.res = cacheValue.response\n return\n }\n\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n\n await next()\n\n const [, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Cache First',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: entry.key,\n oldResponse: undefined,\n newResponse: entry.response,\n context,\n })\n }\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\n\nexport const networkFirst: KeqCacheStrategy = async function networkFirst(handler, context, next) {\n try {\n await next()\n\n const [cacheKey, cache] = await handler.getCache(context)\n const [,entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Network First',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: entry.key,\n oldResponse: cache?.response,\n newResponse: entry.response,\n context,\n })\n }\n } catch (err) {\n const [cacheKey, cache] = await handler.getCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Network First',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cache ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (!cache) {\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n throw err\n }\n\n context.emitter.emit('cache:hit', { key: cacheKey, response: cache.response, context })\n context.res = cache.response\n }\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\n\n\nexport const networkOnly: KeqCacheStrategy = async function (handler, context, next) {\n await next()\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\nexport const staleWhileRevalidate: KeqCacheStrategy = async function (handler, context, next) {\n const [cacheKey, cache] = await handler.getCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cache ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (cache) {\n context.emitter.emit('cache:hit', { key: cacheKey, response: cache.response, context })\n } else {\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n }\n\n\n if (cache) {\n const orchestrator = context.orchestration.fork()\n\n context.res = cache.response\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await orchestrator.execute()\n const context = orchestrator.context\n const [cacheKey, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: cacheKey,\n oldResponse: cache.response,\n newResponse: entry.response,\n context,\n })\n }\n } catch (err) {\n // ignore\n }\n }, 1)\n } else {\n await next()\n const [cacheKey, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: cacheKey,\n oldResponse: undefined,\n newResponse: entry.response,\n context,\n })\n }\n }\n}\n","// export enum Strategy {\n// STALE_WHILE_REVALIDATE = 'stale-while-revalidate',\n// NETWORK_FIRST = 'network-first',\n// NETWORK_ONLY = 'network-only',\n// CATCH_FIRST = 'cache-first',\n// }\n\nimport { cacheFirst } from '~/strategies/cache-first.js'\nimport { networkFirst } from '~/strategies/network-first.js'\nimport { networkOnly } from '~/strategies/network-only.js'\nimport { staleWhileRevalidate } from '~/strategies/stale-while-revalidate.js'\n\nexport const Strategy = {\n STALE_WHILE_REVALIDATE: staleWhileRevalidate,\n NETWORK_FIRST: networkFirst,\n NETWORK_ONLY: networkOnly,\n CACHE_FIRST: cacheFirst,\n}\n","import dayjs from 'dayjs'\nimport * as R from 'ramda'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class TTLMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aExpiredAt = dayjs(a.expiredAt)\n const bExpiredAt = dayjs(b.expiredAt)\n\n return aExpiredAt.isBefore(bExpiredAt) ? 1 : -1\n })\n\n if (R.sum(R.pluck('size', entries)) < deficitSize) {\n this.debug((log) => log('Storage Size Not Enough: ', this.size.free, ' < ', deficitSize))\n return false\n }\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import dayjs from 'dayjs'\nimport * as R from 'ramda'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { MemoryStorageSize } from './types/memory-storage-size.js'\nimport { humanizeSize, serializeResponseBody } from './utils/index.js'\nimport { MAX_EXPIRED_AT } from '~/constants/index.js'\n\n\nexport abstract class BaseMemoryStorage extends InternalStorage {\n protected storage = new Map<string, CacheEntry>()\n\n protected visitTimeRecords = new Map<string, Date>()\n protected visitCountRecords = new Map<string, number>()\n\n protected get size(): MemoryStorageSize {\n const used = R.sum(R.pluck('size', [...this.storage.values()]))\n const free = this.__size__ > used ? this.__size__ - used : 0\n\n return {\n used,\n free,\n }\n }\n\n get(key: string): CacheEntry | undefined {\n this.evictExpired()\n const entry = this.storage.get(key)\n\n this.visitCountRecords.set(key, (this.visitCountRecords.get(key) ?? 0) + 1)\n this.visitTimeRecords.set(key, new Date())\n\n if (!entry) this.debug((log) => log(`Entry(${key}) Not Found`))\n else this.debug((log) => log(`Entry(${key}) Found: `, entry))\n\n return entry?.clone()\n }\n\n set(value: CacheEntry): void {\n if (!this.evict(value.size)) {\n this.debug((log) => log('Storage Size Not Enough: ', this.size.free, ' < ', value.size))\n return\n }\n\n this.storage.set(value.key, value)\n this.visitTimeRecords.set(value.key, new Date())\n this.visitCountRecords.set(value.key, (this.visitCountRecords.get(value.key) ?? 0))\n\n this.debug((log) => log('Entry Added: ', value))\n this.debug((log) => log('Storage Size: ', this.size))\n }\n\n __remove__(keys: string[]): void {\n for (const key of keys) {\n const entry = this.storage.get(key)\n if (!entry) return\n\n this.storage.delete(key)\n this.visitCountRecords.delete(key)\n this.visitTimeRecords.delete(key)\n\n this.debug((log) => log('Entry Removed: ', entry))\n this.debug((log) => log('Storage Size: ', this.size))\n }\n }\n\n remove(key: string): void {\n this.__remove__([key])\n }\n\n\n private lastEvictExpiredTime = dayjs()\n\n /**\n * @zh 清除过期的缓存\n */\n protected evictExpired(): void {\n const now = dayjs()\n\n if (now.diff(this.lastEvictExpiredTime, 'second') < 1) return\n\n const keys: string[] = []\n for (const [key, entry] of this.storage.entries()) {\n if (entry.expiredAt && now.isAfter(entry.expiredAt)) {\n keys.push(key)\n }\n }\n\n this.__remove__(keys)\n this.__onCacheExpired__?.({ keys })\n }\n\n /**\n * @en Evict the storage to make sure the size is enough\n * @zh 清除缓存以确保有足够的空间\n *\n * @return {boolean} - is evicted successfully\n */\n protected evict(expectSize: number): boolean {\n this.evictExpired()\n const size = this.size\n\n return size.free >= expectSize\n }\n\n\n /**\n * @en Print all cached data using console.table for debugging\n * @zh 使用 console.table 打印所有缓存数据,用于调试\n */\n async print(): Promise<void> {\n if (this.storage.size === 0) {\n console.log('MemoryStorage is empty')\n return\n }\n\n const entries = await Promise.all(\n [...this.storage.entries()].map(async ([key, entry]) => {\n const body = await serializeResponseBody(entry.response.clone())\n\n return {\n key,\n size: humanizeSize(entry.size),\n 'Expired Time': entry.expiredAt.getTime() >= MAX_EXPIRED_AT.getTime() ? '-' : entry.expiredAt.toISOString(),\n 'Visit Count': this.visitCountRecords.get(key) ?? 0,\n 'Last Visit Time': this.visitTimeRecords.get(key)?.toISOString() ?? '-',\n 'Response Status': entry.response.status,\n 'Response URL': entry.response.url,\n 'Response Body': body,\n }\n }),\n )\n\n console.table(entries)\n }\n}\n\n","import { Promisable } from 'type-fest'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport abstract class KeqCacheStorage {\n /**\n * @en Get the length of the storage\n * @zh 获取 Storage 缓存的条目数量\n */\n abstract get(key: string): Promisable<CacheEntry | undefined>\n\n /**\n * @en Set a new entry to the storage\n * @zh 将被缓存的数据添加到Storage中\n */\n abstract set(entry: CacheEntry): Promisable<void>\n\n /**\n * @en Remove an entry by key\n * @zh 根据key删除Storage中的数据\n */\n abstract remove(key: string): Promisable<void>\n}\n","import { InternalStorageOptions } from './types/storage-options.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { OnCacheEvictEvent, OnCacheExpiredEvent, OnCacheGetEvent, OnCacheRemoveEvent, OnCacheSetEvent } from './types/events.js'\nimport { CacheException } from '~/exceptions/index.js'\nimport { Logger } from '~/utils/index.js'\n\n\nexport abstract class InternalStorage extends KeqCacheStorage {\n protected readonly __id__: string = Math.random()\n .toString(36)\n .slice(2)\n\n protected readonly __size__: number\n protected readonly __debug__: boolean\n\n protected readonly __onCacheGet__?: (event: OnCacheGetEvent) => void\n protected readonly __onCacheSet__?: (event: OnCacheSetEvent) => void\n protected readonly __onCacheRemove__?: (event: OnCacheRemoveEvent) => void\n protected readonly __onCacheEvict__?: (event: OnCacheEvictEvent) => void\n protected readonly __onCacheExpired__?: (event: OnCacheExpiredEvent) => void\n\n constructor(options?: InternalStorageOptions) {\n super()\n\n if (options?.size && (typeof options?.size !== 'number' || options.size <= 0)) {\n throw new CacheException(`Invalid size: ${String(options?.size)}`)\n }\n\n this.__size__ = options?.size ?? Infinity\n this.__debug__ = !!options?.debug\n\n this.__onCacheGet__ = options?.onCacheGet\n this.__onCacheSet__ = options?.onCacheSet\n this.__onCacheRemove__ = options?.onCacheRemove\n this.__onCacheEvict__ = options?.onCacheEvict\n\n this.debug((log) => log('Storage Created: ', this))\n }\n\n protected debug(fn: (log: (...args: unknown[]) => void) => void): void {\n if (this.__debug__) {\n fn((...args: unknown[]) => {\n Logger.debug(`[Storage(${this.__id__})]`, ...args)\n })\n }\n }\n}\n","/**\n * @en Humanize size in bytes to KB, MB, GB\n * @zh 将字节数转换为 KB、MB、GB 等易读格式\n */\nexport function humanizeSize(size: number): string {\n if (size < 1024) return `${size} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)} KB`\n if (size < 1024 * 1024 * 1024) return `${(size / (1024 * 1024)).toFixed(2)} MB`\n return `${(size / (1024 * 1024 * 1024)).toFixed(2)} GB`\n}\n","/**\n * @en Serialize the response body based on content-type\n * @zh 根据 content-type 序列化响应体\n */\nexport async function serializeResponseBody(response: Response): Promise<string> {\n const contentType = response.headers.get('content-type') ?? ''\n\n try {\n if (contentType.includes('application/json')) {\n const json = await response.json()\n return JSON.stringify(json)\n }\n\n if (\n contentType.includes('text/')\n || contentType.includes('application/xml')\n || contentType.includes('application/javascript')\n ) {\n return await response.text()\n }\n\n return '[Binary or unsupported content]'\n } catch {\n return '[Unable to serialize]'\n }\n}\n","import { random } from '~/utils/random.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class RandomMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const index = random(0, entries.length - 1)\n const entry = entries[index]\n deficitSize -= entry.size\n entries.splice(index, 1)\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import dayjs from 'dayjs'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class LRUMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aVisitAt = this.visitTimeRecords.get(a.key)\n const bVisitAt = this.visitTimeRecords.get(b.key)\n\n if (aVisitAt === bVisitAt) return 0\n if (!aVisitAt) return 1\n if (!bVisitAt) return -1\n\n return dayjs(aVisitAt).isBefore(dayjs(bVisitAt)) ? 1 : -1\n })\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\n\n\nexport class LFUMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aVisitCount = this.visitCountRecords.get(a.key) || 0\n const bVisitCount = this.visitCountRecords.get(b.key) || 0\n return bVisitCount - aVisitCount\n })\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import { Promisable } from 'type-fest'\nimport { Eviction } from '~/constants/index.js'\nimport { TTLMemoryStorage } from './ttl-memory-storage.js'\nimport { RandomMemoryStorage } from './random-memory-storage.js'\nimport { LRUMemoryStorage } from './lru-memory-storage.js'\nimport { LFUMemoryStorage } from './lfu-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\n\nexport class MemoryStorage extends KeqCacheStorage {\n private storage: BaseMemoryStorage\n\n constructor(options?: MemoryStorageOptions) {\n super()\n\n const eviction = options?.eviction || Eviction.LRU\n\n if (eviction === Eviction.TTL) {\n this.storage = new TTLMemoryStorage(options)\n } else if (eviction === Eviction.RANDOM) {\n this.storage = new RandomMemoryStorage(options)\n } else if (eviction === Eviction.LRU) {\n this.storage = new LRUMemoryStorage(options)\n } else if (eviction === Eviction.LFU) {\n this.storage = new LFUMemoryStorage(options)\n } else {\n throw new TypeError(`Invalid eviction: ${String(eviction)}`)\n }\n }\n\n set(entry: CacheEntry): Promisable<void> {\n return this.storage.set(entry)\n }\n\n get(key: string): Promisable<CacheEntry | undefined> {\n return this.storage.get(key)\n }\n\n remove(key: string): Promisable<void> {\n return this.storage.remove(key)\n }\n\n async print(): Promise<void> {\n return this.storage.print()\n }\n}\n","import * as R from 'ramda'\nimport { random } from '~/utils/random.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/index.js'\n\n\nexport class RandomIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n\n const metadatas = await metadataStore.getAll()\n const totalSize = R.sum(metadatas.map((m) => m.size))\n\n if (totalSize < deficitSize) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize - totalSize}`))\n tx.abort()\n return false\n }\n\n const keys: string[] = []\n while (deficitSize > 0 && metadatas.length) {\n const index = random(0, metadatas.length - 1)\n\n const metadata = metadatas[index]\n deficitSize -= metadata.size\n keys.push(metadata.key)\n metadatas.splice(index, 1)\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import * as R from 'ramda'\nimport dayjs from 'dayjs'\nimport { IDBPDatabase, IDBPTransaction, openDB } from 'idb'\nimport { CacheEntry } from '~/cache-entry/index.js'\nimport { CacheException } from '~/exceptions/index.js'\nimport { Logger } from '~/utils/index.js'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { DEFAULT_TABLE_NAME } from './constants/default-table-name.js'\nimport { IndexedDBStorageSize, IndexedDbStorageOptions, IndexedDBSchema, IndexedDBEntryResponse, IndexedDBEntryMetadata } from './types/index.js'\n\n\nexport abstract class BaseIndexedDBStorage extends InternalStorage {\n private readonly tableName: string = DEFAULT_TABLE_NAME\n private db?: IDBPDatabase<IndexedDBSchema>\n\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n if (options?.tableName === DEFAULT_TABLE_NAME) {\n throw new CacheException(`IndexedDBStorage name cannot be \"${DEFAULT_TABLE_NAME}\"`)\n }\n\n this.tableName = options?.tableName || DEFAULT_TABLE_NAME\n }\n\n protected async openDB(): Promise<IDBPDatabase<IndexedDBSchema>> {\n if (this.db) return this.db\n const tableName = this.tableName\n\n const db = await openDB<IndexedDBSchema>(tableName, 2, {\n upgrade(db) {\n if (!db.objectStoreNames.contains('metadata')) {\n const entriesStore = db.createObjectStore('metadata', { keyPath: 'key' })\n\n entriesStore.createIndex('expiredAt', 'expiredAt')\n }\n\n if (!db.objectStoreNames.contains('response')) {\n const responsesStore = db.createObjectStore('response', { keyPath: 'key' })\n responsesStore.createIndex('responseStatus', 'responseStatus')\n }\n\n if (!db.objectStoreNames.contains('visits')) {\n const visitsStore = db.createObjectStore('visits', { keyPath: 'key' })\n visitsStore.createIndex('visitCount', 'visitCount')\n visitsStore.createIndex('lastVisitedAt', 'lastVisitedAt')\n }\n },\n\n blocked() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is blocked`)\n },\n\n blocking() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is blocking`)\n },\n\n terminated() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is terminated`)\n },\n })\n\n this.db = db\n return db\n }\n\n protected async getSize(): Promise<IndexedDBStorageSize> {\n const db = await this.openDB()\n const items = await db.getAll('metadata')\n const used = R.sum(items.map((entry) => entry.size))\n const free = this.__size__ - used\n return { used, free }\n }\n\n\n async get(key: string): Promise<CacheEntry | undefined> {\n await this.evictExpired()\n\n try {\n const db = await this.openDB()\n const dbMetadata = await db.get('metadata', key)\n const dbResponse = await db.get('response', key)\n const dbVisits = await db.get('visits', key)\n\n if (!dbMetadata || !dbResponse) return\n\n await db.put('visits', {\n key: dbMetadata.key,\n visitCount: dbVisits ? dbVisits.visitCount + 1 : 1,\n lastVisitedAt: new Date(),\n })\n\n const response = new Response(dbResponse.responseBody, {\n status: dbResponse.responseStatus,\n headers: new Headers(dbResponse.responseHeaders),\n statusText: dbResponse.responseStatusText,\n })\n\n return await CacheEntry.build({\n key: dbMetadata.key,\n expiredAt: dbMetadata.expiredAt,\n response,\n size: dbMetadata.size,\n })\n } catch (error) {\n return\n }\n }\n\n async set(entry: CacheEntry): Promise<void> {\n try {\n if (!await this.evict(entry.size)) {\n const size = await this.getSize()\n this.debug((log) => log(`Storage Size Not Enough: ${size.free} < ${entry.size}`))\n return\n }\n\n const dbMetadata: IndexedDBEntryMetadata = {\n key: entry.key,\n size: entry.size,\n expiredAt: entry.expiredAt,\n visitedAt: new Date(),\n visitCount: 0,\n }\n\n const response = entry.response.clone()\n const dbResponse: IndexedDBEntryResponse = {\n key: entry.key,\n responseBody: await response.arrayBuffer(),\n responseHeaders: [...response.headers.entries()],\n responseStatus: response.status,\n responseStatusText: response.statusText,\n }\n\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n const responseStore = tx.objectStore('response')\n const visitsStore = tx.objectStore('visits')\n\n const dbVisits = (await visitsStore.get(entry.key)) || {\n key: entry.key,\n visitCount: 0,\n lastVisitedAt: new Date(),\n }\n\n await Promise.all([\n metadataStore.put(dbMetadata),\n responseStore.put(dbResponse),\n visitsStore.put(dbVisits),\n ])\n\n await tx.done\n } catch (error) {\n return\n }\n }\n\n protected async __remove__(tx: IDBPTransaction<IndexedDBSchema, ('metadata' | 'response' | 'visits')[], 'readwrite'>, keys: string[]): Promise<void> {\n await Promise.all(\n R.unnest(\n keys.map((key) => [\n tx.objectStore('metadata').delete(key),\n tx.objectStore('response').delete(key),\n tx.objectStore('visits').delete(key),\n ]),\n ),\n )\n }\n\n async remove(key: string): Promise<void> {\n try {\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n await this.__remove__(tx, [key])\n await tx.done\n } catch (error) {\n return\n }\n }\n\n\n private lastEvictExpiredTime = dayjs(0)\n\n /**\n * @zh 清除过期的缓存\n */\n protected async evictExpired(): Promise<void> {\n const now = dayjs()\n if (now.diff(this.lastEvictExpiredTime, 'second') < 1) return\n this.lastEvictExpiredTime = now\n\n try {\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n // const responseStore = tx.objectStore('response')\n // const visitsStore = tx.objectStore('visits')\n\n let cursor = await metadataStore\n .index('expiredAt')\n .openCursor(IDBKeyRange.upperBound(now.toDate()))\n\n const expiredKeys: string[] = []\n while (cursor) {\n if (dayjs(cursor.value.expiredAt).isBefore(now)) {\n expiredKeys.push(cursor.value.key)\n cursor = await cursor.continue()\n } else {\n break\n }\n }\n\n await this.__remove__(tx, expiredKeys)\n await tx.done\n\n this.__onCacheExpired__?.({ keys: expiredKeys })\n } catch (error) {\n return\n }\n }\n\n protected abstract evict(expectSize: number): Promise<boolean>\n}\n\n","\nexport const DEFAULT_TABLE_NAME = 'keq_cache_indexed_db_storage'\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class LFUIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n const visitsStore = tx.objectStore('visits')\n\n let cursor = await visitsStore\n .index('visitCount')\n .openCursor()\n\n const keys: string[] = []\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class LRUIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n const visitsStore = tx.objectStore('visits')\n\n\n const keys: string[] = []\n let cursor = await visitsStore.index('lastVisitedAt').openCursor()\n\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class TTLIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n const size = await this.getSize()\n\n let deficitSize = expectSize - size.free\n\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n\n const keys: string[] = []\n let cursor = await metadataStore.index('expiredAt').openCursor()\n\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { Promisable } from 'type-fest'\nimport { Eviction } from '~/constants/index.js'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { RandomIndexedDBStorage } from './random-indexed-db-storage.js'\nimport { LFUIndexedDBStorage } from './lfu-indexed-db-storage.js'\nimport { LRUIndexedDBStorage } from './lru-indexed-db-storage.js'\nimport { TTLIndexedDBStorage } from './ttl-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { CacheException } from '~/exceptions/index.js'\n\n\nexport class IndexedDBStorage extends KeqCacheStorage {\n private storage: InternalStorage\n\n constructor(options?: IndexedDbStorageOptions) {\n super()\n\n const eviction = options?.eviction || Eviction.LRU\n\n if (eviction === Eviction.RANDOM) {\n this.storage = new RandomIndexedDBStorage(options)\n } else if (eviction === Eviction.LFU) {\n this.storage = new LFUIndexedDBStorage(options)\n } else if (eviction === Eviction.LRU) {\n this.storage = new LRUIndexedDBStorage(options)\n } else if (eviction === Eviction.TTL) {\n this.storage = new TTLIndexedDBStorage(options)\n } else {\n throw new CacheException(`Not Supported Eviction: ${String(options?.eviction)}`)\n }\n }\n\n set(entry: CacheEntry): Promisable<void> {\n return this.storage.set(entry)\n }\n\n get(key: string): Promisable<CacheEntry | undefined> {\n return this.storage.get(key)\n }\n\n remove(key: string): Promisable<void> {\n return this.storage.remove(key)\n }\n}\n","import { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { MultiTierStorageOptions } from './types/multi-tier-storage-options.js'\n\n/**\n * @en Multi-tier cache storage that manages multiple KeqCacheStorage instances in tiers\n * @zh 多层缓存存储,管理多个分层的 KeqCacheStorage 实例\n */\nexport class MultiTierStorage extends KeqCacheStorage {\n private readonly storages: KeqCacheStorage[]\n\n /**\n * @param storages Array of storage instances ordered by performance (fastest first)\n * @zh 按性价比排序的存储实例数组,排在前面的成本低,排在后面的成本高\n */\n constructor(options: MultiTierStorageOptions) {\n super()\n\n if (!options.tiers || options.tiers.length === 0) {\n throw new Error('At least one storage instance is required')\n }\n\n this.storages = [...options.tiers]\n }\n\n /**\n * @en Get cache entry, searching from lowest to highest tier\n * @zh 获取缓存条目,从最底层到高层依次搜索\n */\n async get(key: string): Promise<CacheEntry | undefined> {\n for (let i = 0; i < this.storages.length; i++) {\n const storage = this.storages[i]\n const entry = await storage.get(key)\n\n if (entry) {\n // 缓存命中,如果不是在最底层,则需要同步到所有低层存储\n if (i > 0) {\n await this.syncToLowerTiers(entry, i)\n }\n return entry\n }\n }\n\n // 所有层都未命中\n return undefined\n }\n\n /**\n * @en Set cache entry to all tiers concurrently\n * @zh 并发写入所有层的缓存\n */\n async set(entry: CacheEntry): Promise<void> {\n // 并发写入所有存储层\n const promises = this.storages.map(async (storage) => storage.set(entry))\n await Promise.all(promises)\n }\n\n /**\n * @en Remove cache entry from all tiers\n * @zh 从所有层删除缓存条目\n */\n async remove(key: string): Promise<void> {\n // 并发删除所有存储层\n const promises = this.storages.map(async (storage) => storage.remove(key))\n await Promise.all(promises)\n }\n\n /**\n * @en Sync cache entry to all lower tiers (tiers with index < currentTierIndex)\n * @zh 将缓存条目同步到所有低层存储(索引小于当前层的存储)\n */\n private async syncToLowerTiers(entry: CacheEntry, currentTierIndex: number): Promise<void> {\n // 只同步到低层(索引更小的层),不向高层同步\n const lowerTierStorages = this.storages.slice(0, currentTierIndex)\n\n if (lowerTierStorages.length === 0) {\n return\n }\n\n // 并发写入所有低层存储\n // 使用克隆避免并发修改问题\n const promises = lowerTierStorages.map(async (storage) => storage.set(entry.clone()))\n\n // 同步写入失败不应该影响主要的get操作,所以我们捕获错误但不抛出\n try {\n await Promise.all(promises)\n } catch (error) {\n // 可以在这里添加日志记录,但不抛出错误\n console.warn('Failed to sync cache entry to lower tiers:', error)\n }\n }\n}\n","import { MemoryStorage } from '../memory-storage/memory-storage.js'\nimport { IndexedDBStorage } from '../indexed-db-storage/indexed-db-storage.js'\nimport { MultiTierStorage } from '../multi-tier-storage/multi-tier-storage.js'\nimport { TierStorageOptions } from './types/tier-storage-options.js'\n\n/**\n * @en Two-tier cache storage that combines MemoryStorage (L1) and IndexedDBStorage (L2)\n * @zh 二级缓存存储,结合了MemoryStorage(一级)和IndexedDBStorage(二级)\n *\n * This is a convenience wrapper around MultiTierStorage that provides:\n * - Fast in-memory cache (L1)\n * - Persistent IndexedDB cache (L2)\n * - Simplified configuration options\n */\nexport class TierStorage extends MultiTierStorage {\n constructor(options?: TierStorageOptions) {\n // Handle memory storage: use existing instance or create new one\n const memoryStorage = options?.memory instanceof MemoryStorage\n ? options.memory\n : new MemoryStorage(options?.memory)\n\n // Handle IndexedDB storage: use existing instance or create new one\n const indexedDBStorage = options?.indexedDB instanceof IndexedDBStorage\n ? options.indexedDB\n : new IndexedDBStorage(options?.indexedDB)\n\n super({\n tiers: [memoryStorage, indexedDBStorage],\n })\n }\n}\n"],"mappings":"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","names":["R","import_keq","Eviction","Size","cacheFirst","networkFirst","cache","cache","context","cacheKey","cache","rule","next","import_dayjs","R","R","dayjs","dayjs","import_dayjs","dayjs","R","R","import_dayjs","dayjs","db"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/cache.ts","../src/request-cache-handler/request-cache-handler.ts","../src/exceptions/cache-exception.ts","../src/cache-entry/cache-entry.ts","../src/utils/get-response-bytes.ts","../src/constants/max-expired-at.ts","../src/constants/eviction.enum.ts","../src/constants/size.enum.ts","../src/utils/logger.ts","../src/utils/random.ts","../src/strategies/cache-first.ts","../src/strategies/network-first.ts","../src/strategies/network-only.ts","../src/strategies/stale-while-revalidate.ts","../src/constants/strategy.enum.ts","../src/storage/memory-storage/ttl-memory-storage.ts","../src/storage/memory-storage/base-memory-storage.ts","../src/storage/keq-cache-storage.ts","../src/storage/internal-storage/internal-storage.ts","../src/storage/memory-storage/utils/humanize-size.ts","../src/storage/memory-storage/utils/serialize-response-body.ts","../src/storage/memory-storage/random-memory-storage.ts","../src/storage/memory-storage/lru-memory-storage.ts","../src/storage/memory-storage/lfu-memory-storage.ts","../src/storage/memory-storage/memory-storage.ts","../src/storage/indexed-db-storage/random-indexed-db-storage.ts","../src/storage/indexed-db-storage/base-indexed-db-storage.ts","../src/storage/indexed-db-storage/constants/default-table-name.ts","../src/storage/indexed-db-storage/lfu-indexed-db-storage.ts","../src/storage/indexed-db-storage/lru-indexed-db-storage.ts","../src/storage/indexed-db-storage/ttl-indexed-db-storage.ts","../src/storage/indexed-db-storage/indexed-db-storage.ts","../src/storage/multi-tier-storage/multi-tier-storage.ts","../src/storage/tier-storage/tier-storage.ts"],"sourcesContent":["export * from './cache.js'\n\nexport {\n Strategy,\n Eviction,\n Size,\n} from './constants/index.js'\n\n\nexport {\n KeqCacheStorage,\n IndexedDBStorage,\n MemoryStorage,\n MultiTierStorage,\n TierStorage,\n} from './storage/index.js'\n\nexport {\n type MemoryStorageOptions,\n type IndexedDbStorageOptions,\n type TierStorageOptions,\n type MultiTierStorageOptions,\n} from './storage/index.js'\n\n\nexport {\n type KeqCacheRule,\n type KeqCacheKey,\n type KeqCacheKeyFactory,\n type KeqCachePattern,\n type KeqCacheStrategy,\n} from './types/index.js'\n","import * as R from 'ramda'\nimport * as fastq from 'fastq'\nimport type { queueAsPromised } from 'fastq'\nimport type { Keq, KeqMiddleware, KeqContext, KeqNext } from 'keq'\nimport { KeqCacheStorage } from './storage/keq-cache-storage.js'\nimport { RequestCacheHandler } from './request-cache-handler/index.js'\nimport { KeqCacheKeyFactory, KeqCacheRule, RequestCacheOptions } from './types/index.js'\n\n\nexport interface KeqCacheOptions extends Pick<RequestCacheOptions, 'serverTiming'> {\n storage: KeqCacheStorage\n\n /**\n * Cache Key Factory\n */\n keyFactory?: KeqCacheKeyFactory\n\n rules?: KeqCacheRule[]\n}\n\n\ndeclare module 'keq' {\n export interface KeqMiddlewareOptions<OP> {\n /**\n * [keq-cache](https://github.com/keq-request/keq-cache)\n */\n cache(option: RequestCacheOptions | false): Keq<OP>\n }\n\n export interface KeqEvents {\n 'cache:hit': {\n key: string\n response: Response\n context: KeqContext\n }\n\n 'cache:miss': {\n key: string\n context: KeqContext\n }\n\n 'cache:update': {\n key: string\n oldResponse?: Response\n newResponse: Response\n context: KeqContext\n }\n }\n\n export interface KeqGlobalCore {\n cache?: Record<string, queueAsPromised<{ next: KeqNext }, void>>\n }\n}\n\n\nexport function cache(options: KeqCacheOptions): KeqMiddleware {\n const storage = options.storage\n\n const rules: KeqCacheRule[] = options?.rules || []\n\n return async function cache(ctx, next) {\n if (ctx.options.cache === false) {\n await next()\n return\n }\n\n let requestCacheOptions: RequestCacheOptions | undefined = ctx.options.cache\n // let requestOptions: KeqCacheRequestOptions | undefined = ctx.options.cache\n\n const rule = rules.find((rule) => {\n if (rule.pattern === undefined || rule.pattern === true) return true\n if (typeof rule.pattern === 'function') return rule.pattern(ctx)\n return rule.pattern.test(ctx.request.__url__.href)\n })\n\n if (rule) requestCacheOptions = R.mergeRight(rule, requestCacheOptions || ({} as any))\n\n if (!requestCacheOptions || R.isEmpty(requestCacheOptions)) {\n await next()\n return\n }\n\n if (!requestCacheOptions.key) requestCacheOptions.key = options.keyFactory\n\n if (!ctx.locationId && !requestCacheOptions.key) {\n console.warn('[@keq/cache] Warning: Cannot resolve Cache Key. Cache is skipped.')\n await next()\n return\n }\n\n if (requestCacheOptions.serverTiming === undefined && options.serverTiming !== undefined) {\n requestCacheOptions.serverTiming = options.serverTiming\n }\n\n const cacheKey = RequestCacheHandler.resolveRequestCacheKey(ctx, requestCacheOptions)\n const handler = new RequestCacheHandler(cacheKey, storage, requestCacheOptions)\n const strategy = requestCacheOptions.strategy\n\n if (requestCacheOptions.concurrent) {\n await strategy(handler, ctx, next)\n } else {\n if (!ctx.global.core) ctx.global.core = {}\n if (!ctx.global.core.cache) ctx.global.core.cache = {}\n if (!ctx.global.core.cache[cacheKey]) {\n ctx.global.core.cache[cacheKey] = fastq.promise(async ({ next }) => {\n await next()\n }, 1)\n }\n\n const queue = ctx.global.core.cache[cacheKey]\n await queue.push({\n next: async () => {\n await strategy(handler, ctx, next)\n },\n })\n }\n }\n}\n","import * as R from 'ramda'\nimport { KeqContext } from 'keq'\nimport { CacheException } from '~/exceptions'\nimport { KeqCacheStorage } from '~/storage'\nimport { CacheEntry } from '~/cache-entry'\nimport { RequestCacheOptions } from '../types/index.js'\n\n\nexport type RequestCacheHandlerOptions = Omit<RequestCacheOptions, 'strategy'>\n\nexport class RequestCacheHandler {\n constructor(\n public readonly cacheKey: string,\n public readonly storage: KeqCacheStorage,\n public readonly options: Readonly<RequestCacheHandlerOptions>,\n ) {}\n\n /**\n * Resolve cache key for request context\n */\n static resolveRequestCacheKey(context: KeqContext, options: RequestCacheHandlerOptions): string {\n if (typeof options.key === 'string') return options.key\n else if (typeof options.key === 'function') return options.key(context)\n else if (R.isNil(options.key) && context.locationId) return context.locationId\n else throw new CacheException('Cannot resolve cache key')\n }\n\n /**\n * Get cache from storage\n */\n async getCache(): Promise<[string, CacheEntry | undefined]> {\n const key = this.cacheKey\n\n if (this.options.serverTiming) {\n const startAt = new Date()\n const entry = await this.storage.get(key)\n if (entry) {\n const dur = new Date().getTime() - startAt.getTime()\n\n const HeadersWithServerTiming = new Headers(entry.response.headers)\n HeadersWithServerTiming.set('Server-Timing', `keq-cache; dur=${dur}; desc=\"HIT\"`)\n\n entry.assignResponseHeaders(HeadersWithServerTiming)\n }\n\n return [key, entry]\n }\n\n return [key, await this.storage.get(key)]\n }\n\n /**\n * Store response that in context to storage\n */\n async setCache(context: KeqContext): Promise<[string, CacheEntry | undefined]> {\n const options = this.options\n const key = this.cacheKey\n\n if (!context.response) return [key, undefined]\n if (options.exclude && (await options.exclude(context.response))) return [key, undefined]\n\n const entry = await CacheEntry.build({\n key,\n response: context.response,\n ttl: options.ttl,\n })\n\n void this.storage.set(entry)\n\n return [key, entry]\n }\n}\n","import { Exception } from 'keq'\n\nexport class CacheException extends Exception {\n constructor(message: string) {\n super(`[@keq-request/cache] ${message}`)\n }\n}\n","import { createProxyResponse } from 'keq'\nimport { getResponseBytes } from '~/utils/get-response-bytes.js'\nimport { CacheEntryOptions } from './types/cache-entry-options.js'\nimport { CacheEntryBuildOptions } from './types/cache-entry-build-options.js'\nimport { MAX_EXPIRED_AT } from '~/constants/index.js'\n\n\nexport class CacheEntry {\n key: string\n response: Response\n\n /**\n * @en bytes\n * @zh 字节数\n */\n size: number\n\n expiredAt: Date\n\n constructor(options: CacheEntryOptions) {\n this.key = options.key\n this.response = createProxyResponse(options.response)\n this.size = options.size\n this.expiredAt = options.expiredAt ?? MAX_EXPIRED_AT\n }\n\n static async build(options: CacheEntryBuildOptions): Promise<CacheEntry> {\n const expiredAt = 'expiredAt' in options\n ? options.expiredAt\n : ('ttl' in options && typeof options.ttl === 'number' && options.ttl > 0)\n ? new Date(Date.now() + options.ttl * 1000)\n : MAX_EXPIRED_AT\n\n const response = options.response.clone()\n return new CacheEntry({\n key: options.key,\n response,\n size: options.size ?? (await getResponseBytes(response)),\n expiredAt: expiredAt,\n })\n }\n\n clone(): CacheEntry {\n return new CacheEntry({\n key: this.key,\n response: this.response.clone(),\n size: this.size,\n expiredAt: this.expiredAt,\n })\n }\n\n assignResponseHeaders(headers: Headers): void {\n this.response = new Response(this.response.body, {\n status: this.response.status,\n statusText: this.response.statusText,\n headers: headers,\n })\n }\n}\n","export async function getResponseBytes(response: Response): Promise<number> {\n const contentLength = response.headers.get('content-length')\n if (contentLength) {\n return parseInt(contentLength)\n }\n\n const arrayBuffer = await response.clone().arrayBuffer()\n return arrayBuffer.byteLength\n}\n","export const MAX_EXPIRED_AT = new Date(8640000000000000)\n","export enum Eviction {\n LRU = 'lru',\n LFU = 'lfu',\n RANDOM = 'random',\n TTL = 'ttl',\n}\n","export enum Size {\n B = 1,\n KB = 1024,\n MB = 1024 * 1024,\n GB = 1024 * 1024 * 1024,\n}\n","export class Logger {\n static debug(...args: unknown[]): void {\n console.debug('[@keq-request/cache] [DEBUG] ', ...args)\n }\n\n static error(...args: unknown[]): void {\n console.error('[@keq-request/cache] [ERROR] ', ...args)\n }\n}\n","export function random(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min)) + min\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\n\nexport const cacheFirst: KeqCacheStrategy = async function cacheFirst(handler, context, next): Promise<void> {\n // return async function (context, next): Promise<void> {\n const [cacheKey, cacheValue] = await handler.getCache()\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Cache First',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cacheValue ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (cacheValue) {\n // hit cache\n context.emitter.emit('cache:hit', { key: cacheKey, response: cacheValue.response, context })\n context.res = cacheValue.response\n return\n }\n\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n\n await next()\n\n const [, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Cache First',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: entry.key,\n oldResponse: undefined,\n newResponse: entry.response,\n context,\n })\n }\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\n\nexport const networkFirst: KeqCacheStrategy = async function networkFirst(handler, context, next) {\n try {\n await next()\n\n const [cacheKey, cache] = await handler.getCache()\n const [,entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Network First',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: entry.key,\n oldResponse: cache?.response,\n newResponse: entry.response,\n context,\n })\n }\n } catch (err) {\n const [cacheKey, cache] = await handler.getCache()\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Network First',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cache ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (!cache) {\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n throw err\n }\n\n context.emitter.emit('cache:hit', { key: cacheKey, response: cache.response, context })\n context.res = cache.response\n }\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\n\n\nexport const networkOnly: KeqCacheStrategy = async function (handler, context, next) {\n await next()\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\nexport const staleWhileRevalidate: KeqCacheStrategy = async function (handler, context, next) {\n const [cacheKey, cache] = await handler.getCache()\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cache ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (cache) {\n context.emitter.emit('cache:hit', { key: cacheKey, response: cache.response, context })\n } else {\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n }\n\n\n if (cache) {\n const orchestrator = context.orchestration.fork()\n\n context.res = cache.response\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await orchestrator.execute()\n const context = orchestrator.context\n const [cacheKey, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: cacheKey,\n oldResponse: cache.response,\n newResponse: entry.response,\n context,\n })\n }\n } catch (err) {\n // ignore\n }\n }, 1)\n } else {\n await next()\n const [cacheKey, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: cacheKey,\n oldResponse: undefined,\n newResponse: entry.response,\n context,\n })\n }\n }\n}\n","// export enum Strategy {\n// STALE_WHILE_REVALIDATE = 'stale-while-revalidate',\n// NETWORK_FIRST = 'network-first',\n// NETWORK_ONLY = 'network-only',\n// CATCH_FIRST = 'cache-first',\n// }\n\nimport { cacheFirst } from '~/strategies/cache-first.js'\nimport { networkFirst } from '~/strategies/network-first.js'\nimport { networkOnly } from '~/strategies/network-only.js'\nimport { staleWhileRevalidate } from '~/strategies/stale-while-revalidate.js'\n\nexport const Strategy = {\n STALE_WHILE_REVALIDATE: staleWhileRevalidate,\n NETWORK_FIRST: networkFirst,\n NETWORK_ONLY: networkOnly,\n CACHE_FIRST: cacheFirst,\n}\n","import dayjs from 'dayjs'\nimport * as R from 'ramda'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class TTLMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aExpiredAt = dayjs(a.expiredAt)\n const bExpiredAt = dayjs(b.expiredAt)\n\n return aExpiredAt.isBefore(bExpiredAt) ? 1 : -1\n })\n\n if (R.sum(R.pluck('size', entries)) < deficitSize) {\n this.debug((log) => log('Storage Size Not Enough: ', this.size.free, ' < ', deficitSize))\n return false\n }\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import dayjs from 'dayjs'\nimport * as R from 'ramda'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { MemoryStorageSize } from './types/memory-storage-size.js'\nimport { humanizeSize, serializeResponseBody } from './utils/index.js'\nimport { MAX_EXPIRED_AT } from '~/constants/index.js'\n\n\nexport abstract class BaseMemoryStorage extends InternalStorage {\n protected storage = new Map<string, CacheEntry>()\n\n protected visitTimeRecords = new Map<string, Date>()\n protected visitCountRecords = new Map<string, number>()\n\n protected get size(): MemoryStorageSize {\n const used = R.sum(R.pluck('size', [...this.storage.values()]))\n const free = this.__size__ > used ? this.__size__ - used : 0\n\n return {\n used,\n free,\n }\n }\n\n get(key: string): CacheEntry | undefined {\n this.evictExpired()\n const entry = this.storage.get(key)\n\n this.visitCountRecords.set(key, (this.visitCountRecords.get(key) ?? 0) + 1)\n this.visitTimeRecords.set(key, new Date())\n\n if (!entry) this.debug((log) => log(`Entry(${key}) Not Found`))\n else this.debug((log) => log(`Entry(${key}) Found: `, entry))\n\n return entry?.clone()\n }\n\n set(value: CacheEntry): void {\n if (!this.evict(value.size)) {\n this.debug((log) => log('Storage Size Not Enough: ', this.size.free, ' < ', value.size))\n return\n }\n\n this.storage.set(value.key, value)\n this.visitTimeRecords.set(value.key, new Date())\n this.visitCountRecords.set(value.key, (this.visitCountRecords.get(value.key) ?? 0))\n\n this.debug((log) => log('Entry Added: ', value))\n this.debug((log) => log('Storage Size: ', this.size))\n }\n\n __remove__(keys: string[]): void {\n for (const key of keys) {\n const entry = this.storage.get(key)\n if (!entry) return\n\n this.storage.delete(key)\n this.visitCountRecords.delete(key)\n this.visitTimeRecords.delete(key)\n\n this.debug((log) => log('Entry Removed: ', entry))\n this.debug((log) => log('Storage Size: ', this.size))\n }\n }\n\n remove(key: string): void {\n this.__remove__([key])\n }\n\n\n private lastEvictExpiredTime = dayjs()\n\n /**\n * @zh 清除过期的缓存\n */\n protected evictExpired(): void {\n const now = dayjs()\n\n if (now.diff(this.lastEvictExpiredTime, 'second') < 1) return\n\n const keys: string[] = []\n for (const [key, entry] of this.storage.entries()) {\n if (entry.expiredAt && now.isAfter(entry.expiredAt)) {\n keys.push(key)\n }\n }\n\n this.__remove__(keys)\n this.__onCacheExpired__?.({ keys })\n }\n\n /**\n * @en Evict the storage to make sure the size is enough\n * @zh 清除缓存以确保有足够的空间\n *\n * @return {boolean} - is evicted successfully\n */\n protected evict(expectSize: number): boolean {\n this.evictExpired()\n const size = this.size\n\n return size.free >= expectSize\n }\n\n\n /**\n * @en Print all cached data using console.table for debugging\n * @zh 使用 console.table 打印所有缓存数据,用于调试\n */\n async print(): Promise<void> {\n if (this.storage.size === 0) {\n console.log('MemoryStorage is empty')\n return\n }\n\n const entries = await Promise.all(\n [...this.storage.entries()].map(async ([key, entry]) => {\n const body = await serializeResponseBody(entry.response.clone())\n\n return {\n key,\n size: humanizeSize(entry.size),\n 'Expired Time': entry.expiredAt.getTime() >= MAX_EXPIRED_AT.getTime() ? '-' : entry.expiredAt.toISOString(),\n 'Visit Count': this.visitCountRecords.get(key) ?? 0,\n 'Last Visit Time': this.visitTimeRecords.get(key)?.toISOString() ?? '-',\n 'Response Status': entry.response.status,\n 'Response URL': entry.response.url,\n 'Response Body': body,\n }\n }),\n )\n\n console.table(entries)\n }\n}\n\n","import { Promisable } from 'type-fest'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport abstract class KeqCacheStorage {\n /**\n * @en Get the length of the storage\n * @zh 获取 Storage 缓存的条目数量\n */\n abstract get(key: string): Promisable<CacheEntry | undefined>\n\n /**\n * @en Set a new entry to the storage\n * @zh 将被缓存的数据添加到Storage中\n */\n abstract set(entry: CacheEntry): Promisable<void>\n\n /**\n * @en Remove an entry by key\n * @zh 根据key删除Storage中的数据\n */\n abstract remove(key: string): Promisable<void>\n}\n","import { InternalStorageOptions } from './types/storage-options.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { OnCacheEvictEvent, OnCacheExpiredEvent, OnCacheGetEvent, OnCacheRemoveEvent, OnCacheSetEvent } from './types/events.js'\nimport { CacheException } from '~/exceptions/index.js'\nimport { Logger } from '~/utils/index.js'\n\n\nexport abstract class InternalStorage extends KeqCacheStorage {\n protected readonly __id__: string = Math.random()\n .toString(36)\n .slice(2)\n\n protected readonly __size__: number\n protected readonly __debug__: boolean\n\n protected readonly __onCacheGet__?: (event: OnCacheGetEvent) => void\n protected readonly __onCacheSet__?: (event: OnCacheSetEvent) => void\n protected readonly __onCacheRemove__?: (event: OnCacheRemoveEvent) => void\n protected readonly __onCacheEvict__?: (event: OnCacheEvictEvent) => void\n protected readonly __onCacheExpired__?: (event: OnCacheExpiredEvent) => void\n\n constructor(options?: InternalStorageOptions) {\n super()\n\n if (options?.size && (typeof options?.size !== 'number' || options.size <= 0)) {\n throw new CacheException(`Invalid size: ${String(options?.size)}`)\n }\n\n this.__size__ = options?.size ?? Infinity\n this.__debug__ = !!options?.debug\n\n this.__onCacheGet__ = options?.onCacheGet\n this.__onCacheSet__ = options?.onCacheSet\n this.__onCacheRemove__ = options?.onCacheRemove\n this.__onCacheEvict__ = options?.onCacheEvict\n\n this.debug((log) => log('Storage Created: ', this))\n }\n\n protected debug(fn: (log: (...args: unknown[]) => void) => void): void {\n if (this.__debug__) {\n fn((...args: unknown[]) => {\n Logger.debug(`[Storage(${this.__id__})]`, ...args)\n })\n }\n }\n}\n","/**\n * @en Humanize size in bytes to KB, MB, GB\n * @zh 将字节数转换为 KB、MB、GB 等易读格式\n */\nexport function humanizeSize(size: number): string {\n if (size < 1024) return `${size} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)} KB`\n if (size < 1024 * 1024 * 1024) return `${(size / (1024 * 1024)).toFixed(2)} MB`\n return `${(size / (1024 * 1024 * 1024)).toFixed(2)} GB`\n}\n","/**\n * @en Serialize the response body based on content-type\n * @zh 根据 content-type 序列化响应体\n */\nexport async function serializeResponseBody(response: Response): Promise<string> {\n const contentType = response.headers.get('content-type') ?? ''\n\n try {\n if (contentType.includes('application/json')) {\n const json = await response.json()\n return JSON.stringify(json)\n }\n\n if (\n contentType.includes('text/')\n || contentType.includes('application/xml')\n || contentType.includes('application/javascript')\n ) {\n return await response.text()\n }\n\n return '[Binary or unsupported content]'\n } catch {\n return '[Unable to serialize]'\n }\n}\n","import { random } from '~/utils/random.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class RandomMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const index = random(0, entries.length - 1)\n const entry = entries[index]\n deficitSize -= entry.size\n entries.splice(index, 1)\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import dayjs from 'dayjs'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class LRUMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aVisitAt = this.visitTimeRecords.get(a.key)\n const bVisitAt = this.visitTimeRecords.get(b.key)\n\n if (aVisitAt === bVisitAt) return 0\n if (!aVisitAt) return 1\n if (!bVisitAt) return -1\n\n return dayjs(aVisitAt).isBefore(dayjs(bVisitAt)) ? 1 : -1\n })\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\n\n\nexport class LFUMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aVisitCount = this.visitCountRecords.get(a.key) || 0\n const bVisitCount = this.visitCountRecords.get(b.key) || 0\n return bVisitCount - aVisitCount\n })\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import { Promisable } from 'type-fest'\nimport { Eviction } from '~/constants/index.js'\nimport { TTLMemoryStorage } from './ttl-memory-storage.js'\nimport { RandomMemoryStorage } from './random-memory-storage.js'\nimport { LRUMemoryStorage } from './lru-memory-storage.js'\nimport { LFUMemoryStorage } from './lfu-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\n\nexport class MemoryStorage extends KeqCacheStorage {\n private storage: BaseMemoryStorage\n\n constructor(options?: MemoryStorageOptions) {\n super()\n\n const eviction = options?.eviction || Eviction.LRU\n\n if (eviction === Eviction.TTL) {\n this.storage = new TTLMemoryStorage(options)\n } else if (eviction === Eviction.RANDOM) {\n this.storage = new RandomMemoryStorage(options)\n } else if (eviction === Eviction.LRU) {\n this.storage = new LRUMemoryStorage(options)\n } else if (eviction === Eviction.LFU) {\n this.storage = new LFUMemoryStorage(options)\n } else {\n throw new TypeError(`Invalid eviction: ${String(eviction)}`)\n }\n }\n\n set(entry: CacheEntry): Promisable<void> {\n return this.storage.set(entry)\n }\n\n get(key: string): Promisable<CacheEntry | undefined> {\n return this.storage.get(key)\n }\n\n remove(key: string): Promisable<void> {\n return this.storage.remove(key)\n }\n\n async print(): Promise<void> {\n return this.storage.print()\n }\n}\n","import * as R from 'ramda'\nimport { random } from '~/utils/random.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/index.js'\n\n\nexport class RandomIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n\n const metadatas = await metadataStore.getAll()\n const totalSize = R.sum(metadatas.map((m) => m.size))\n\n if (totalSize < deficitSize) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize - totalSize}`))\n tx.abort()\n return false\n }\n\n const keys: string[] = []\n while (deficitSize > 0 && metadatas.length) {\n const index = random(0, metadatas.length - 1)\n\n const metadata = metadatas[index]\n deficitSize -= metadata.size\n keys.push(metadata.key)\n metadatas.splice(index, 1)\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import * as R from 'ramda'\nimport dayjs from 'dayjs'\nimport { IDBPDatabase, IDBPTransaction, openDB } from 'idb'\nimport { CacheEntry } from '~/cache-entry/index.js'\nimport { CacheException } from '~/exceptions/index.js'\nimport { Logger } from '~/utils/index.js'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { DEFAULT_TABLE_NAME } from './constants/default-table-name.js'\nimport { IndexedDBStorageSize, IndexedDbStorageOptions, IndexedDBSchema, IndexedDBEntryResponse, IndexedDBEntryMetadata } from './types/index.js'\n\n\nexport abstract class BaseIndexedDBStorage extends InternalStorage {\n private readonly tableName: string = DEFAULT_TABLE_NAME\n private db?: IDBPDatabase<IndexedDBSchema>\n\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n if (options?.tableName === DEFAULT_TABLE_NAME) {\n throw new CacheException(`IndexedDBStorage name cannot be \"${DEFAULT_TABLE_NAME}\"`)\n }\n\n this.tableName = options?.tableName || DEFAULT_TABLE_NAME\n }\n\n protected async openDB(): Promise<IDBPDatabase<IndexedDBSchema>> {\n if (this.db) return this.db\n const tableName = this.tableName\n\n const db = await openDB<IndexedDBSchema>(tableName, 2, {\n upgrade(db) {\n if (!db.objectStoreNames.contains('metadata')) {\n const entriesStore = db.createObjectStore('metadata', { keyPath: 'key' })\n\n entriesStore.createIndex('expiredAt', 'expiredAt')\n }\n\n if (!db.objectStoreNames.contains('response')) {\n const responsesStore = db.createObjectStore('response', { keyPath: 'key' })\n responsesStore.createIndex('responseStatus', 'responseStatus')\n }\n\n if (!db.objectStoreNames.contains('visits')) {\n const visitsStore = db.createObjectStore('visits', { keyPath: 'key' })\n visitsStore.createIndex('visitCount', 'visitCount')\n visitsStore.createIndex('lastVisitedAt', 'lastVisitedAt')\n }\n },\n\n blocked() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is blocked`)\n },\n\n blocking() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is blocking`)\n },\n\n terminated() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is terminated`)\n },\n })\n\n this.db = db\n return db\n }\n\n protected async getSize(): Promise<IndexedDBStorageSize> {\n const db = await this.openDB()\n const items = await db.getAll('metadata')\n const used = R.sum(items.map((entry) => entry.size))\n const free = this.__size__ - used\n return { used, free }\n }\n\n\n async get(key: string): Promise<CacheEntry | undefined> {\n await this.evictExpired()\n\n try {\n const db = await this.openDB()\n const dbMetadata = await db.get('metadata', key)\n const dbResponse = await db.get('response', key)\n const dbVisits = await db.get('visits', key)\n\n if (!dbMetadata || !dbResponse) return\n\n await db.put('visits', {\n key: dbMetadata.key,\n visitCount: dbVisits ? dbVisits.visitCount + 1 : 1,\n lastVisitedAt: new Date(),\n })\n\n const response = new Response(dbResponse.responseBody, {\n status: dbResponse.responseStatus,\n headers: new Headers(dbResponse.responseHeaders),\n statusText: dbResponse.responseStatusText,\n })\n\n return await CacheEntry.build({\n key: dbMetadata.key,\n expiredAt: dbMetadata.expiredAt,\n response,\n size: dbMetadata.size,\n })\n } catch (error) {\n return\n }\n }\n\n async set(entry: CacheEntry): Promise<void> {\n try {\n if (!await this.evict(entry.size)) {\n const size = await this.getSize()\n this.debug((log) => log(`Storage Size Not Enough: ${size.free} < ${entry.size}`))\n return\n }\n\n const dbMetadata: IndexedDBEntryMetadata = {\n key: entry.key,\n size: entry.size,\n expiredAt: entry.expiredAt,\n visitedAt: new Date(),\n visitCount: 0,\n }\n\n const response = entry.response.clone()\n const dbResponse: IndexedDBEntryResponse = {\n key: entry.key,\n responseBody: await response.arrayBuffer(),\n responseHeaders: [...response.headers.entries()],\n responseStatus: response.status,\n responseStatusText: response.statusText,\n }\n\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n const responseStore = tx.objectStore('response')\n const visitsStore = tx.objectStore('visits')\n\n const dbVisits = (await visitsStore.get(entry.key)) || {\n key: entry.key,\n visitCount: 0,\n lastVisitedAt: new Date(),\n }\n\n await Promise.all([\n metadataStore.put(dbMetadata),\n responseStore.put(dbResponse),\n visitsStore.put(dbVisits),\n ])\n\n await tx.done\n } catch (error) {\n return\n }\n }\n\n protected async __remove__(tx: IDBPTransaction<IndexedDBSchema, ('metadata' | 'response' | 'visits')[], 'readwrite'>, keys: string[]): Promise<void> {\n await Promise.all(\n R.unnest(\n keys.map((key) => [\n tx.objectStore('metadata').delete(key),\n tx.objectStore('response').delete(key),\n tx.objectStore('visits').delete(key),\n ]),\n ),\n )\n }\n\n async remove(key: string): Promise<void> {\n try {\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n await this.__remove__(tx, [key])\n await tx.done\n } catch (error) {\n return\n }\n }\n\n\n private lastEvictExpiredTime = dayjs(0)\n\n /**\n * @zh 清除过期的缓存\n */\n protected async evictExpired(): Promise<void> {\n const now = dayjs()\n if (now.diff(this.lastEvictExpiredTime, 'second') < 1) return\n this.lastEvictExpiredTime = now\n\n try {\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n // const responseStore = tx.objectStore('response')\n // const visitsStore = tx.objectStore('visits')\n\n let cursor = await metadataStore\n .index('expiredAt')\n .openCursor(IDBKeyRange.upperBound(now.toDate()))\n\n const expiredKeys: string[] = []\n while (cursor) {\n if (dayjs(cursor.value.expiredAt).isBefore(now)) {\n expiredKeys.push(cursor.value.key)\n cursor = await cursor.continue()\n } else {\n break\n }\n }\n\n await this.__remove__(tx, expiredKeys)\n await tx.done\n\n this.__onCacheExpired__?.({ keys: expiredKeys })\n } catch (error) {\n return\n }\n }\n\n protected abstract evict(expectSize: number): Promise<boolean>\n}\n\n","\nexport const DEFAULT_TABLE_NAME = 'keq_cache_indexed_db_storage'\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class LFUIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n const visitsStore = tx.objectStore('visits')\n\n let cursor = await visitsStore\n .index('visitCount')\n .openCursor()\n\n const keys: string[] = []\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class LRUIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n const visitsStore = tx.objectStore('visits')\n\n\n const keys: string[] = []\n let cursor = await visitsStore.index('lastVisitedAt').openCursor()\n\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class TTLIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n const size = await this.getSize()\n\n let deficitSize = expectSize - size.free\n\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n\n const keys: string[] = []\n let cursor = await metadataStore.index('expiredAt').openCursor()\n\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { Promisable } from 'type-fest'\nimport { Eviction } from '~/constants/index.js'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { RandomIndexedDBStorage } from './random-indexed-db-storage.js'\nimport { LFUIndexedDBStorage } from './lfu-indexed-db-storage.js'\nimport { LRUIndexedDBStorage } from './lru-indexed-db-storage.js'\nimport { TTLIndexedDBStorage } from './ttl-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { CacheException } from '~/exceptions/index.js'\n\n\nexport class IndexedDBStorage extends KeqCacheStorage {\n private storage: InternalStorage\n\n constructor(options?: IndexedDbStorageOptions) {\n super()\n\n const eviction = options?.eviction || Eviction.LRU\n\n if (eviction === Eviction.RANDOM) {\n this.storage = new RandomIndexedDBStorage(options)\n } else if (eviction === Eviction.LFU) {\n this.storage = new LFUIndexedDBStorage(options)\n } else if (eviction === Eviction.LRU) {\n this.storage = new LRUIndexedDBStorage(options)\n } else if (eviction === Eviction.TTL) {\n this.storage = new TTLIndexedDBStorage(options)\n } else {\n throw new CacheException(`Not Supported Eviction: ${String(options?.eviction)}`)\n }\n }\n\n set(entry: CacheEntry): Promisable<void> {\n return this.storage.set(entry)\n }\n\n get(key: string): Promisable<CacheEntry | undefined> {\n return this.storage.get(key)\n }\n\n remove(key: string): Promisable<void> {\n return this.storage.remove(key)\n }\n}\n","import { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { MultiTierStorageOptions } from './types/multi-tier-storage-options.js'\n\n/**\n * @en Multi-tier cache storage that manages multiple KeqCacheStorage instances in tiers\n * @zh 多层缓存存储,管理多个分层的 KeqCacheStorage 实例\n */\nexport class MultiTierStorage extends KeqCacheStorage {\n private readonly storages: KeqCacheStorage[]\n\n /**\n * @param storages Array of storage instances ordered by performance (fastest first)\n * @zh 按性价比排序的存储实例数组,排在前面的成本低,排在后面的成本高\n */\n constructor(options: MultiTierStorageOptions) {\n super()\n\n if (!options.tiers || options.tiers.length === 0) {\n throw new Error('At least one storage instance is required')\n }\n\n this.storages = [...options.tiers]\n }\n\n /**\n * @en Get cache entry, searching from lowest to highest tier\n * @zh 获取缓存条目,从最底层到高层依次搜索\n */\n async get(key: string): Promise<CacheEntry | undefined> {\n for (let i = 0; i < this.storages.length; i++) {\n const storage = this.storages[i]\n const entry = await storage.get(key)\n\n if (entry) {\n // 缓存命中,如果不是在最底层,则需要同步到所有低层存储\n if (i > 0) {\n await this.syncToLowerTiers(entry, i)\n }\n return entry\n }\n }\n\n // 所有层都未命中\n return undefined\n }\n\n /**\n * @en Set cache entry to all tiers concurrently\n * @zh 并发写入所有层的缓存\n */\n async set(entry: CacheEntry): Promise<void> {\n // 并发写入所有存储层\n const promises = this.storages.map(async (storage) => storage.set(entry))\n await Promise.all(promises)\n }\n\n /**\n * @en Remove cache entry from all tiers\n * @zh 从所有层删除缓存条目\n */\n async remove(key: string): Promise<void> {\n // 并发删除所有存储层\n const promises = this.storages.map(async (storage) => storage.remove(key))\n await Promise.all(promises)\n }\n\n /**\n * @en Sync cache entry to all lower tiers (tiers with index < currentTierIndex)\n * @zh 将缓存条目同步到所有低层存储(索引小于当前层的存储)\n */\n private async syncToLowerTiers(entry: CacheEntry, currentTierIndex: number): Promise<void> {\n // 只同步到低层(索引更小的层),不向高层同步\n const lowerTierStorages = this.storages.slice(0, currentTierIndex)\n\n if (lowerTierStorages.length === 0) {\n return\n }\n\n // 并发写入所有低层存储\n // 使用克隆避免并发修改问题\n const promises = lowerTierStorages.map(async (storage) => storage.set(entry.clone()))\n\n // 同步写入失败不应该影响主要的get操作,所以我们捕获错误但不抛出\n try {\n await Promise.all(promises)\n } catch (error) {\n // 可以在这里添加日志记录,但不抛出错误\n console.warn('Failed to sync cache entry to lower tiers:', error)\n }\n }\n}\n","import { MemoryStorage } from '../memory-storage/memory-storage.js'\nimport { IndexedDBStorage } from '../indexed-db-storage/indexed-db-storage.js'\nimport { MultiTierStorage } from '../multi-tier-storage/multi-tier-storage.js'\nimport { TierStorageOptions } from './types/tier-storage-options.js'\n\n/**\n * @en Two-tier cache storage that combines MemoryStorage (L1) and IndexedDBStorage (L2)\n * @zh 二级缓存存储,结合了MemoryStorage(一级)和IndexedDBStorage(二级)\n *\n * This is a convenience wrapper around MultiTierStorage that provides:\n * - Fast in-memory cache (L1)\n * - Persistent IndexedDB cache (L2)\n * - Simplified configuration options\n */\nexport class TierStorage extends MultiTierStorage {\n constructor(options?: TierStorageOptions) {\n // Handle memory storage: use existing instance or create new one\n const memoryStorage = options?.memory instanceof MemoryStorage\n ? options.memory\n : new MemoryStorage(options?.memory)\n\n // Handle IndexedDB storage: use existing instance or create new one\n const indexedDBStorage = options?.indexedDB instanceof IndexedDBStorage\n ? options.indexedDB\n : new IndexedDBStorage(options?.indexedDB)\n\n super({\n tiers: [memoryStorage, indexedDBStorage],\n })\n }\n}\n"],"mappings":"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","names":["R","import_keq","Eviction","Size","cacheFirst","networkFirst","cache","cache","context","cacheKey","cache","rule","next","import_dayjs","R","R","dayjs","dayjs","import_dayjs","dayjs","R","R","import_dayjs","dayjs","db"]}
|
package/dist/index.mjs
CHANGED
|
@@ -68,7 +68,7 @@ function random(min, max) {
|
|
|
68
68
|
|
|
69
69
|
// src/strategies/cache-first.ts
|
|
70
70
|
var cacheFirst = async function cacheFirst2(handler, context, next) {
|
|
71
|
-
const [cacheKey, cacheValue] = await handler.getCache(
|
|
71
|
+
const [cacheKey, cacheValue] = await handler.getCache();
|
|
72
72
|
if (handler.options.debug) {
|
|
73
73
|
Logger.debug([
|
|
74
74
|
"",
|
|
@@ -109,7 +109,7 @@ var cacheFirst = async function cacheFirst2(handler, context, next) {
|
|
|
109
109
|
var networkFirst = async function networkFirst2(handler, context, next) {
|
|
110
110
|
try {
|
|
111
111
|
await next();
|
|
112
|
-
const [cacheKey, cache2] = await handler.getCache(
|
|
112
|
+
const [cacheKey, cache2] = await handler.getCache();
|
|
113
113
|
const [, entry] = await handler.setCache(context);
|
|
114
114
|
if (handler.options.debug) {
|
|
115
115
|
Logger.debug([
|
|
@@ -129,7 +129,7 @@ var networkFirst = async function networkFirst2(handler, context, next) {
|
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
131
|
} catch (err) {
|
|
132
|
-
const [cacheKey, cache2] = await handler.getCache(
|
|
132
|
+
const [cacheKey, cache2] = await handler.getCache();
|
|
133
133
|
if (handler.options.debug) {
|
|
134
134
|
Logger.debug([
|
|
135
135
|
"",
|
|
@@ -155,7 +155,7 @@ var networkOnly = async function(handler, context, next) {
|
|
|
155
155
|
|
|
156
156
|
// src/strategies/stale-while-revalidate.ts
|
|
157
157
|
var staleWhileRevalidate = async function(handler, context, next) {
|
|
158
|
-
const [cacheKey, cache2] = await handler.getCache(
|
|
158
|
+
const [cacheKey, cache2] = await handler.getCache();
|
|
159
159
|
if (handler.options.debug) {
|
|
160
160
|
Logger.debug([
|
|
161
161
|
"",
|
|
@@ -276,15 +276,15 @@ var CacheEntry = class _CacheEntry {
|
|
|
276
276
|
|
|
277
277
|
// src/request-cache-handler/request-cache-handler.ts
|
|
278
278
|
var RequestCacheHandler = class {
|
|
279
|
-
constructor(storage, options) {
|
|
279
|
+
constructor(cacheKey, storage, options) {
|
|
280
|
+
this.cacheKey = cacheKey;
|
|
280
281
|
this.storage = storage;
|
|
281
282
|
this.options = options;
|
|
282
283
|
}
|
|
283
284
|
/**
|
|
284
|
-
*
|
|
285
|
+
* Resolve cache key for request context
|
|
285
286
|
*/
|
|
286
|
-
|
|
287
|
-
const options = this.options;
|
|
287
|
+
static resolveRequestCacheKey(context, options) {
|
|
288
288
|
if (typeof options.key === "string") return options.key;
|
|
289
289
|
else if (typeof options.key === "function") return options.key(context);
|
|
290
290
|
else if (R.isNil(options.key) && context.locationId) return context.locationId;
|
|
@@ -293,8 +293,8 @@ var RequestCacheHandler = class {
|
|
|
293
293
|
/**
|
|
294
294
|
* Get cache from storage
|
|
295
295
|
*/
|
|
296
|
-
async getCache(
|
|
297
|
-
const key = this.
|
|
296
|
+
async getCache() {
|
|
297
|
+
const key = this.cacheKey;
|
|
298
298
|
if (this.options.serverTiming) {
|
|
299
299
|
const startAt = /* @__PURE__ */ new Date();
|
|
300
300
|
const entry = await this.storage.get(key);
|
|
@@ -313,7 +313,7 @@ var RequestCacheHandler = class {
|
|
|
313
313
|
*/
|
|
314
314
|
async setCache(context) {
|
|
315
315
|
const options = this.options;
|
|
316
|
-
const key = this.
|
|
316
|
+
const key = this.cacheKey;
|
|
317
317
|
if (!context.response) return [key, void 0];
|
|
318
318
|
if (options.exclude && await options.exclude(context.response)) return [key, void 0];
|
|
319
319
|
const entry = await CacheEntry.build({
|
|
@@ -355,14 +355,14 @@ function cache(options) {
|
|
|
355
355
|
if (requestCacheOptions.serverTiming === void 0 && options.serverTiming !== void 0) {
|
|
356
356
|
requestCacheOptions.serverTiming = options.serverTiming;
|
|
357
357
|
}
|
|
358
|
-
const
|
|
358
|
+
const cacheKey = RequestCacheHandler.resolveRequestCacheKey(ctx, requestCacheOptions);
|
|
359
|
+
const handler = new RequestCacheHandler(cacheKey, storage, requestCacheOptions);
|
|
359
360
|
const strategy = requestCacheOptions.strategy;
|
|
360
361
|
if (requestCacheOptions.concurrent) {
|
|
361
362
|
await strategy(handler, ctx, next);
|
|
362
363
|
} else {
|
|
363
364
|
if (!ctx.global.core) ctx.global.core = {};
|
|
364
365
|
if (!ctx.global.core.cache) ctx.global.core.cache = {};
|
|
365
|
-
const cacheKey = handler.getRequestCacheKey(ctx);
|
|
366
366
|
if (!ctx.global.core.cache[cacheKey]) {
|
|
367
367
|
ctx.global.core.cache[cacheKey] = fastq.promise(async ({ next: next2 }) => {
|
|
368
368
|
await next2();
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cache.ts","../src/request-cache-handler/request-cache-handler.ts","../src/exceptions/cache-exception.ts","../src/cache-entry/cache-entry.ts","../src/utils/get-response-bytes.ts","../src/constants/max-expired-at.ts","../src/constants/eviction.enum.ts","../src/constants/size.enum.ts","../src/utils/logger.ts","../src/utils/random.ts","../src/strategies/cache-first.ts","../src/strategies/network-first.ts","../src/strategies/network-only.ts","../src/strategies/stale-while-revalidate.ts","../src/constants/strategy.enum.ts","../src/storage/memory-storage/ttl-memory-storage.ts","../src/storage/memory-storage/base-memory-storage.ts","../src/storage/keq-cache-storage.ts","../src/storage/internal-storage/internal-storage.ts","../src/storage/memory-storage/utils/humanize-size.ts","../src/storage/memory-storage/utils/serialize-response-body.ts","../src/storage/memory-storage/random-memory-storage.ts","../src/storage/memory-storage/lru-memory-storage.ts","../src/storage/memory-storage/lfu-memory-storage.ts","../src/storage/memory-storage/memory-storage.ts","../src/storage/indexed-db-storage/random-indexed-db-storage.ts","../src/storage/indexed-db-storage/base-indexed-db-storage.ts","../src/storage/indexed-db-storage/constants/default-table-name.ts","../src/storage/indexed-db-storage/lfu-indexed-db-storage.ts","../src/storage/indexed-db-storage/lru-indexed-db-storage.ts","../src/storage/indexed-db-storage/ttl-indexed-db-storage.ts","../src/storage/indexed-db-storage/indexed-db-storage.ts","../src/storage/multi-tier-storage/multi-tier-storage.ts","../src/storage/tier-storage/tier-storage.ts"],"sourcesContent":["import * as R from 'ramda'\nimport * as fastq from 'fastq'\nimport type { queueAsPromised } from 'fastq'\nimport type { Keq, KeqMiddleware, KeqContext, KeqNext } from 'keq'\nimport { KeqCacheStorage } from './storage/keq-cache-storage.js'\nimport { RequestCacheHandler } from './request-cache-handler/index.js'\nimport { KeqCacheKeyFactory, KeqCacheRule, RequestCacheOptions } from './types/index.js'\n\n\nexport interface KeqCacheOptions extends Pick<RequestCacheOptions, 'serverTiming'> {\n storage: KeqCacheStorage\n\n /**\n * Cache Key Factory\n */\n keyFactory?: KeqCacheKeyFactory\n\n rules?: KeqCacheRule[]\n}\n\n\ndeclare module 'keq' {\n export interface KeqMiddlewareOptions<OP> {\n /**\n * [keq-cache](https://github.com/keq-request/keq-cache)\n */\n cache(option: RequestCacheOptions | false): Keq<OP>\n }\n\n export interface KeqEvents {\n 'cache:hit': {\n key: string\n response: Response\n context: KeqContext\n }\n\n 'cache:miss': {\n key: string\n context: KeqContext\n }\n\n 'cache:update': {\n key: string\n oldResponse?: Response\n newResponse: Response\n context: KeqContext\n }\n }\n\n export interface KeqGlobalCore {\n cache?: Record<string, queueAsPromised<{ next: KeqNext }, void>>\n }\n}\n\n\nexport function cache(options: KeqCacheOptions): KeqMiddleware {\n const storage = options.storage\n\n const rules: KeqCacheRule[] = options?.rules || []\n\n return async function cache(ctx, next) {\n if (ctx.options.cache === false) {\n await next()\n return\n }\n\n let requestCacheOptions: RequestCacheOptions | undefined = ctx.options.cache\n // let requestOptions: KeqCacheRequestOptions | undefined = ctx.options.cache\n\n const rule = rules.find((rule) => {\n if (rule.pattern === undefined || rule.pattern === true) return true\n if (typeof rule.pattern === 'function') return rule.pattern(ctx)\n return rule.pattern.test(ctx.request.__url__.href)\n })\n\n if (rule) requestCacheOptions = R.mergeRight(rule, requestCacheOptions || ({} as any))\n\n if (!requestCacheOptions || R.isEmpty(requestCacheOptions)) {\n await next()\n return\n }\n\n if (!requestCacheOptions.key) requestCacheOptions.key = options.keyFactory\n\n if (!ctx.locationId && !requestCacheOptions.key) {\n console.warn('[@keq/cache] Warning: Cannot resolve Cache Key. Cache is skipped.')\n await next()\n return\n }\n\n if (requestCacheOptions.serverTiming === undefined && options.serverTiming !== undefined) {\n requestCacheOptions.serverTiming = options.serverTiming\n }\n\n\n const handler = new RequestCacheHandler(storage, requestCacheOptions)\n const strategy = requestCacheOptions.strategy\n\n if (requestCacheOptions.concurrent) {\n await strategy(handler, ctx, next)\n } else {\n if (!ctx.global.core) ctx.global.core = {}\n if (!ctx.global.core.cache) ctx.global.core.cache = {}\n\n const cacheKey = handler.getRequestCacheKey(ctx)\n if (!ctx.global.core.cache[cacheKey]) {\n ctx.global.core.cache[cacheKey] = fastq.promise(async ({ next }) => {\n await next()\n }, 1)\n }\n\n const queue = ctx.global.core.cache[cacheKey]!\n await queue.push({\n next: async () => {\n await strategy(handler, ctx, next)\n },\n })\n }\n }\n}\n","import * as R from 'ramda'\nimport { KeqContext } from 'keq'\nimport { CacheException } from '~/exceptions'\nimport { KeqCacheStorage } from '~/storage'\nimport { CacheEntry } from '~/cache-entry'\nimport { RequestCacheOptions } from '../types/index.js'\n\n\nexport type RequestCacheHandlerOptions = Omit<RequestCacheOptions, 'strategy'>\n\nexport class RequestCacheHandler {\n constructor(\n public readonly storage: KeqCacheStorage,\n public readonly options: Readonly<RequestCacheHandlerOptions>,\n ) {}\n\n /**\n * Get cache key for request\n */\n getRequestCacheKey(context: KeqContext): string {\n const options = this.options\n\n if (typeof options.key === 'string') return options.key\n else if (typeof options.key === 'function') return options.key(context)\n else if (R.isNil(options.key) && context.locationId) return context.locationId\n else throw new CacheException('Cannot resolve cache key')\n }\n\n /**\n * Get cache from storage\n */\n async getCache(context: KeqContext): Promise<[string, CacheEntry | undefined]> {\n const key = this.getRequestCacheKey(context)\n\n if (this.options.serverTiming) {\n const startAt = new Date()\n const entry = await this.storage.get(key)\n if (entry) {\n const dur = new Date().getTime() - startAt.getTime()\n\n const HeadersWithServerTiming = new Headers(entry.response.headers)\n HeadersWithServerTiming.set('Server-Timing', `keq-cache; dur=${dur}; desc=\"HIT\"`)\n\n entry.assignResponseHeaders(HeadersWithServerTiming)\n }\n\n return [key, entry]\n }\n\n return [key, await this.storage.get(key)]\n }\n\n /**\n * Store response that in context to storage\n */\n async setCache(context: KeqContext): Promise<[string, CacheEntry | undefined]> {\n const options = this.options\n const key = this.getRequestCacheKey(context)\n\n if (!context.response) return [key, undefined]\n if (options.exclude && (await options.exclude(context.response))) return [key, undefined]\n\n const entry = await CacheEntry.build({\n key,\n response: context.response,\n ttl: options.ttl,\n })\n\n void this.storage.set(entry)\n\n return [key, entry]\n }\n}\n","import { Exception } from 'keq'\n\nexport class CacheException extends Exception {\n constructor(message: string) {\n super(`[@keq-request/cache] ${message}`)\n }\n}\n","import { createProxyResponse } from 'keq'\nimport { getResponseBytes } from '~/utils/get-response-bytes.js'\nimport { CacheEntryOptions } from './types/cache-entry-options.js'\nimport { CacheEntryBuildOptions } from './types/cache-entry-build-options.js'\nimport { MAX_EXPIRED_AT } from '~/constants/index.js'\n\n\nexport class CacheEntry {\n key: string\n response: Response\n\n /**\n * @en bytes\n * @zh 字节数\n */\n size: number\n\n expiredAt: Date\n\n constructor(options: CacheEntryOptions) {\n this.key = options.key\n this.response = createProxyResponse(options.response)\n this.size = options.size\n this.expiredAt = options.expiredAt ?? MAX_EXPIRED_AT\n }\n\n static async build(options: CacheEntryBuildOptions): Promise<CacheEntry> {\n const expiredAt = 'expiredAt' in options\n ? options.expiredAt\n : ('ttl' in options && typeof options.ttl === 'number' && options.ttl > 0)\n ? new Date(Date.now() + options.ttl * 1000)\n : MAX_EXPIRED_AT\n\n const response = options.response.clone()\n return new CacheEntry({\n key: options.key,\n response,\n size: options.size ?? (await getResponseBytes(response)),\n expiredAt: expiredAt,\n })\n }\n\n clone(): CacheEntry {\n return new CacheEntry({\n key: this.key,\n response: this.response.clone(),\n size: this.size,\n expiredAt: this.expiredAt,\n })\n }\n\n assignResponseHeaders(headers: Headers): void {\n this.response = new Response(this.response.body, {\n status: this.response.status,\n statusText: this.response.statusText,\n headers: headers,\n })\n }\n}\n","export async function getResponseBytes(response: Response): Promise<number> {\n const contentLength = response.headers.get('content-length')\n if (contentLength) {\n return parseInt(contentLength)\n }\n\n const arrayBuffer = await response.clone().arrayBuffer()\n return arrayBuffer.byteLength\n}\n","export const MAX_EXPIRED_AT = new Date(8640000000000000)\n","export enum Eviction {\n LRU = 'lru',\n LFU = 'lfu',\n RANDOM = 'random',\n TTL = 'ttl',\n}\n","export enum Size {\n B = 1,\n KB = 1024,\n MB = 1024 * 1024,\n GB = 1024 * 1024 * 1024,\n}\n","export class Logger {\n static debug(...args: unknown[]): void {\n console.debug('[@keq-request/cache] [DEBUG] ', ...args)\n }\n\n static error(...args: unknown[]): void {\n console.error('[@keq-request/cache] [ERROR] ', ...args)\n }\n}\n","export function random(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min)) + min\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\n\nexport const cacheFirst: KeqCacheStrategy = async function cacheFirst(handler, context, next): Promise<void> {\n // return async function (context, next): Promise<void> {\n const [cacheKey, cacheValue] = await handler.getCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Cache First',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cacheValue ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (cacheValue) {\n // hit cache\n context.emitter.emit('cache:hit', { key: cacheKey, response: cacheValue.response, context })\n context.res = cacheValue.response\n return\n }\n\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n\n await next()\n\n const [, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Cache First',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: entry.key,\n oldResponse: undefined,\n newResponse: entry.response,\n context,\n })\n }\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\n\nexport const networkFirst: KeqCacheStrategy = async function networkFirst(handler, context, next) {\n try {\n await next()\n\n const [cacheKey, cache] = await handler.getCache(context)\n const [,entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Network First',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: entry.key,\n oldResponse: cache?.response,\n newResponse: entry.response,\n context,\n })\n }\n } catch (err) {\n const [cacheKey, cache] = await handler.getCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Network First',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cache ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (!cache) {\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n throw err\n }\n\n context.emitter.emit('cache:hit', { key: cacheKey, response: cache.response, context })\n context.res = cache.response\n }\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\n\n\nexport const networkOnly: KeqCacheStrategy = async function (handler, context, next) {\n await next()\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\nexport const staleWhileRevalidate: KeqCacheStrategy = async function (handler, context, next) {\n const [cacheKey, cache] = await handler.getCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cache ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (cache) {\n context.emitter.emit('cache:hit', { key: cacheKey, response: cache.response, context })\n } else {\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n }\n\n\n if (cache) {\n const orchestrator = context.orchestration.fork()\n\n context.res = cache.response\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await orchestrator.execute()\n const context = orchestrator.context\n const [cacheKey, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: cacheKey,\n oldResponse: cache.response,\n newResponse: entry.response,\n context,\n })\n }\n } catch (err) {\n // ignore\n }\n }, 1)\n } else {\n await next()\n const [cacheKey, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: cacheKey,\n oldResponse: undefined,\n newResponse: entry.response,\n context,\n })\n }\n }\n}\n","// export enum Strategy {\n// STALE_WHILE_REVALIDATE = 'stale-while-revalidate',\n// NETWORK_FIRST = 'network-first',\n// NETWORK_ONLY = 'network-only',\n// CATCH_FIRST = 'cache-first',\n// }\n\nimport { cacheFirst } from '~/strategies/cache-first.js'\nimport { networkFirst } from '~/strategies/network-first.js'\nimport { networkOnly } from '~/strategies/network-only.js'\nimport { staleWhileRevalidate } from '~/strategies/stale-while-revalidate.js'\n\nexport const Strategy = {\n STALE_WHILE_REVALIDATE: staleWhileRevalidate,\n NETWORK_FIRST: networkFirst,\n NETWORK_ONLY: networkOnly,\n CACHE_FIRST: cacheFirst,\n}\n","import dayjs from 'dayjs'\nimport * as R from 'ramda'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class TTLMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aExpiredAt = dayjs(a.expiredAt)\n const bExpiredAt = dayjs(b.expiredAt)\n\n return aExpiredAt.isBefore(bExpiredAt) ? 1 : -1\n })\n\n if (R.sum(R.pluck('size', entries)) < deficitSize) {\n this.debug((log) => log('Storage Size Not Enough: ', this.size.free, ' < ', deficitSize))\n return false\n }\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import dayjs from 'dayjs'\nimport * as R from 'ramda'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { MemoryStorageSize } from './types/memory-storage-size.js'\nimport { humanizeSize, serializeResponseBody } from './utils/index.js'\nimport { MAX_EXPIRED_AT } from '~/constants/index.js'\n\n\nexport abstract class BaseMemoryStorage extends InternalStorage {\n protected storage = new Map<string, CacheEntry>()\n\n protected visitTimeRecords = new Map<string, Date>()\n protected visitCountRecords = new Map<string, number>()\n\n protected get size(): MemoryStorageSize {\n const used = R.sum(R.pluck('size', [...this.storage.values()]))\n const free = this.__size__ > used ? this.__size__ - used : 0\n\n return {\n used,\n free,\n }\n }\n\n get(key: string): CacheEntry | undefined {\n this.evictExpired()\n const entry = this.storage.get(key)\n\n this.visitCountRecords.set(key, (this.visitCountRecords.get(key) ?? 0) + 1)\n this.visitTimeRecords.set(key, new Date())\n\n if (!entry) this.debug((log) => log(`Entry(${key}) Not Found`))\n else this.debug((log) => log(`Entry(${key}) Found: `, entry))\n\n return entry?.clone()\n }\n\n set(value: CacheEntry): void {\n if (!this.evict(value.size)) {\n this.debug((log) => log('Storage Size Not Enough: ', this.size.free, ' < ', value.size))\n return\n }\n\n this.storage.set(value.key, value)\n this.visitTimeRecords.set(value.key, new Date())\n this.visitCountRecords.set(value.key, (this.visitCountRecords.get(value.key) ?? 0))\n\n this.debug((log) => log('Entry Added: ', value))\n this.debug((log) => log('Storage Size: ', this.size))\n }\n\n __remove__(keys: string[]): void {\n for (const key of keys) {\n const entry = this.storage.get(key)\n if (!entry) return\n\n this.storage.delete(key)\n this.visitCountRecords.delete(key)\n this.visitTimeRecords.delete(key)\n\n this.debug((log) => log('Entry Removed: ', entry))\n this.debug((log) => log('Storage Size: ', this.size))\n }\n }\n\n remove(key: string): void {\n this.__remove__([key])\n }\n\n\n private lastEvictExpiredTime = dayjs()\n\n /**\n * @zh 清除过期的缓存\n */\n protected evictExpired(): void {\n const now = dayjs()\n\n if (now.diff(this.lastEvictExpiredTime, 'second') < 1) return\n\n const keys: string[] = []\n for (const [key, entry] of this.storage.entries()) {\n if (entry.expiredAt && now.isAfter(entry.expiredAt)) {\n keys.push(key)\n }\n }\n\n this.__remove__(keys)\n this.__onCacheExpired__?.({ keys })\n }\n\n /**\n * @en Evict the storage to make sure the size is enough\n * @zh 清除缓存以确保有足够的空间\n *\n * @return {boolean} - is evicted successfully\n */\n protected evict(expectSize: number): boolean {\n this.evictExpired()\n const size = this.size\n\n return size.free >= expectSize\n }\n\n\n /**\n * @en Print all cached data using console.table for debugging\n * @zh 使用 console.table 打印所有缓存数据,用于调试\n */\n async print(): Promise<void> {\n if (this.storage.size === 0) {\n console.log('MemoryStorage is empty')\n return\n }\n\n const entries = await Promise.all(\n [...this.storage.entries()].map(async ([key, entry]) => {\n const body = await serializeResponseBody(entry.response.clone())\n\n return {\n key,\n size: humanizeSize(entry.size),\n 'Expired Time': entry.expiredAt.getTime() >= MAX_EXPIRED_AT.getTime() ? '-' : entry.expiredAt.toISOString(),\n 'Visit Count': this.visitCountRecords.get(key) ?? 0,\n 'Last Visit Time': this.visitTimeRecords.get(key)?.toISOString() ?? '-',\n 'Response Status': entry.response.status,\n 'Response URL': entry.response.url,\n 'Response Body': body,\n }\n }),\n )\n\n console.table(entries)\n }\n}\n\n","import { Promisable } from 'type-fest'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport abstract class KeqCacheStorage {\n /**\n * @en Get the length of the storage\n * @zh 获取 Storage 缓存的条目数量\n */\n abstract get(key: string): Promisable<CacheEntry | undefined>\n\n /**\n * @en Set a new entry to the storage\n * @zh 将被缓存的数据添加到Storage中\n */\n abstract set(entry: CacheEntry): Promisable<void>\n\n /**\n * @en Remove an entry by key\n * @zh 根据key删除Storage中的数据\n */\n abstract remove(key: string): Promisable<void>\n}\n","import { InternalStorageOptions } from './types/storage-options.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { OnCacheEvictEvent, OnCacheExpiredEvent, OnCacheGetEvent, OnCacheRemoveEvent, OnCacheSetEvent } from './types/events.js'\nimport { CacheException } from '~/exceptions/index.js'\nimport { Logger } from '~/utils/index.js'\n\n\nexport abstract class InternalStorage extends KeqCacheStorage {\n protected readonly __id__: string = Math.random()\n .toString(36)\n .slice(2)\n\n protected readonly __size__: number\n protected readonly __debug__: boolean\n\n protected readonly __onCacheGet__?: (event: OnCacheGetEvent) => void\n protected readonly __onCacheSet__?: (event: OnCacheSetEvent) => void\n protected readonly __onCacheRemove__?: (event: OnCacheRemoveEvent) => void\n protected readonly __onCacheEvict__?: (event: OnCacheEvictEvent) => void\n protected readonly __onCacheExpired__?: (event: OnCacheExpiredEvent) => void\n\n constructor(options?: InternalStorageOptions) {\n super()\n\n if (options?.size && (typeof options?.size !== 'number' || options.size <= 0)) {\n throw new CacheException(`Invalid size: ${String(options?.size)}`)\n }\n\n this.__size__ = options?.size ?? Infinity\n this.__debug__ = !!options?.debug\n\n this.__onCacheGet__ = options?.onCacheGet\n this.__onCacheSet__ = options?.onCacheSet\n this.__onCacheRemove__ = options?.onCacheRemove\n this.__onCacheEvict__ = options?.onCacheEvict\n\n this.debug((log) => log('Storage Created: ', this))\n }\n\n protected debug(fn: (log: (...args: unknown[]) => void) => void): void {\n if (this.__debug__) {\n fn((...args: unknown[]) => {\n Logger.debug(`[Storage(${this.__id__})]`, ...args)\n })\n }\n }\n}\n","/**\n * @en Humanize size in bytes to KB, MB, GB\n * @zh 将字节数转换为 KB、MB、GB 等易读格式\n */\nexport function humanizeSize(size: number): string {\n if (size < 1024) return `${size} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)} KB`\n if (size < 1024 * 1024 * 1024) return `${(size / (1024 * 1024)).toFixed(2)} MB`\n return `${(size / (1024 * 1024 * 1024)).toFixed(2)} GB`\n}\n","/**\n * @en Serialize the response body based on content-type\n * @zh 根据 content-type 序列化响应体\n */\nexport async function serializeResponseBody(response: Response): Promise<string> {\n const contentType = response.headers.get('content-type') ?? ''\n\n try {\n if (contentType.includes('application/json')) {\n const json = await response.json()\n return JSON.stringify(json)\n }\n\n if (\n contentType.includes('text/')\n || contentType.includes('application/xml')\n || contentType.includes('application/javascript')\n ) {\n return await response.text()\n }\n\n return '[Binary or unsupported content]'\n } catch {\n return '[Unable to serialize]'\n }\n}\n","import { random } from '~/utils/random.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class RandomMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const index = random(0, entries.length - 1)\n const entry = entries[index]\n deficitSize -= entry.size\n entries.splice(index, 1)\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import dayjs from 'dayjs'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class LRUMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aVisitAt = this.visitTimeRecords.get(a.key)\n const bVisitAt = this.visitTimeRecords.get(b.key)\n\n if (aVisitAt === bVisitAt) return 0\n if (!aVisitAt) return 1\n if (!bVisitAt) return -1\n\n return dayjs(aVisitAt).isBefore(dayjs(bVisitAt)) ? 1 : -1\n })\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\n\n\nexport class LFUMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aVisitCount = this.visitCountRecords.get(a.key) || 0\n const bVisitCount = this.visitCountRecords.get(b.key) || 0\n return bVisitCount - aVisitCount\n })\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import { Promisable } from 'type-fest'\nimport { Eviction } from '~/constants/index.js'\nimport { TTLMemoryStorage } from './ttl-memory-storage.js'\nimport { RandomMemoryStorage } from './random-memory-storage.js'\nimport { LRUMemoryStorage } from './lru-memory-storage.js'\nimport { LFUMemoryStorage } from './lfu-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\n\nexport class MemoryStorage extends KeqCacheStorage {\n private storage: BaseMemoryStorage\n\n constructor(options?: MemoryStorageOptions) {\n super()\n\n const eviction = options?.eviction || Eviction.LRU\n\n if (eviction === Eviction.TTL) {\n this.storage = new TTLMemoryStorage(options)\n } else if (eviction === Eviction.RANDOM) {\n this.storage = new RandomMemoryStorage(options)\n } else if (eviction === Eviction.LRU) {\n this.storage = new LRUMemoryStorage(options)\n } else if (eviction === Eviction.LFU) {\n this.storage = new LFUMemoryStorage(options)\n } else {\n throw new TypeError(`Invalid eviction: ${String(eviction)}`)\n }\n }\n\n set(entry: CacheEntry): Promisable<void> {\n return this.storage.set(entry)\n }\n\n get(key: string): Promisable<CacheEntry | undefined> {\n return this.storage.get(key)\n }\n\n remove(key: string): Promisable<void> {\n return this.storage.remove(key)\n }\n\n async print(): Promise<void> {\n return this.storage.print()\n }\n}\n","import * as R from 'ramda'\nimport { random } from '~/utils/random.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/index.js'\n\n\nexport class RandomIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n\n const metadatas = await metadataStore.getAll()\n const totalSize = R.sum(metadatas.map((m) => m.size))\n\n if (totalSize < deficitSize) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize - totalSize}`))\n tx.abort()\n return false\n }\n\n const keys: string[] = []\n while (deficitSize > 0 && metadatas.length) {\n const index = random(0, metadatas.length - 1)\n\n const metadata = metadatas[index]\n deficitSize -= metadata.size\n keys.push(metadata.key)\n metadatas.splice(index, 1)\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import * as R from 'ramda'\nimport dayjs from 'dayjs'\nimport { IDBPDatabase, IDBPTransaction, openDB } from 'idb'\nimport { CacheEntry } from '~/cache-entry/index.js'\nimport { CacheException } from '~/exceptions/index.js'\nimport { Logger } from '~/utils/index.js'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { DEFAULT_TABLE_NAME } from './constants/default-table-name.js'\nimport { IndexedDBStorageSize, IndexedDbStorageOptions, IndexedDBSchema, IndexedDBEntryResponse, IndexedDBEntryMetadata } from './types/index.js'\n\n\nexport abstract class BaseIndexedDBStorage extends InternalStorage {\n private readonly tableName: string = DEFAULT_TABLE_NAME\n private db?: IDBPDatabase<IndexedDBSchema>\n\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n if (options?.tableName === DEFAULT_TABLE_NAME) {\n throw new CacheException(`IndexedDBStorage name cannot be \"${DEFAULT_TABLE_NAME}\"`)\n }\n\n this.tableName = options?.tableName || DEFAULT_TABLE_NAME\n }\n\n protected async openDB(): Promise<IDBPDatabase<IndexedDBSchema>> {\n if (this.db) return this.db\n const tableName = this.tableName\n\n const db = await openDB<IndexedDBSchema>(tableName, 2, {\n upgrade(db) {\n if (!db.objectStoreNames.contains('metadata')) {\n const entriesStore = db.createObjectStore('metadata', { keyPath: 'key' })\n\n entriesStore.createIndex('expiredAt', 'expiredAt')\n }\n\n if (!db.objectStoreNames.contains('response')) {\n const responsesStore = db.createObjectStore('response', { keyPath: 'key' })\n responsesStore.createIndex('responseStatus', 'responseStatus')\n }\n\n if (!db.objectStoreNames.contains('visits')) {\n const visitsStore = db.createObjectStore('visits', { keyPath: 'key' })\n visitsStore.createIndex('visitCount', 'visitCount')\n visitsStore.createIndex('lastVisitedAt', 'lastVisitedAt')\n }\n },\n\n blocked() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is blocked`)\n },\n\n blocking() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is blocking`)\n },\n\n terminated() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is terminated`)\n },\n })\n\n this.db = db\n return db\n }\n\n protected async getSize(): Promise<IndexedDBStorageSize> {\n const db = await this.openDB()\n const items = await db.getAll('metadata')\n const used = R.sum(items.map((entry) => entry.size))\n const free = this.__size__ - used\n return { used, free }\n }\n\n\n async get(key: string): Promise<CacheEntry | undefined> {\n await this.evictExpired()\n\n try {\n const db = await this.openDB()\n const dbMetadata = await db.get('metadata', key)\n const dbResponse = await db.get('response', key)\n const dbVisits = await db.get('visits', key)\n\n if (!dbMetadata || !dbResponse) return\n\n await db.put('visits', {\n key: dbMetadata.key,\n visitCount: dbVisits ? dbVisits.visitCount + 1 : 1,\n lastVisitedAt: new Date(),\n })\n\n const response = new Response(dbResponse.responseBody, {\n status: dbResponse.responseStatus,\n headers: new Headers(dbResponse.responseHeaders),\n statusText: dbResponse.responseStatusText,\n })\n\n return await CacheEntry.build({\n key: dbMetadata.key,\n expiredAt: dbMetadata.expiredAt,\n response,\n size: dbMetadata.size,\n })\n } catch (error) {\n return\n }\n }\n\n async set(entry: CacheEntry): Promise<void> {\n try {\n if (!await this.evict(entry.size)) {\n const size = await this.getSize()\n this.debug((log) => log(`Storage Size Not Enough: ${size.free} < ${entry.size}`))\n return\n }\n\n const dbMetadata: IndexedDBEntryMetadata = {\n key: entry.key,\n size: entry.size,\n expiredAt: entry.expiredAt,\n visitedAt: new Date(),\n visitCount: 0,\n }\n\n const response = entry.response.clone()\n const dbResponse: IndexedDBEntryResponse = {\n key: entry.key,\n responseBody: await response.arrayBuffer(),\n responseHeaders: [...response.headers.entries()],\n responseStatus: response.status,\n responseStatusText: response.statusText,\n }\n\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n const responseStore = tx.objectStore('response')\n const visitsStore = tx.objectStore('visits')\n\n const dbVisits = (await visitsStore.get(entry.key)) || {\n key: entry.key,\n visitCount: 0,\n lastVisitedAt: new Date(),\n }\n\n await Promise.all([\n metadataStore.put(dbMetadata),\n responseStore.put(dbResponse),\n visitsStore.put(dbVisits),\n ])\n\n await tx.done\n } catch (error) {\n return\n }\n }\n\n protected async __remove__(tx: IDBPTransaction<IndexedDBSchema, ('metadata' | 'response' | 'visits')[], 'readwrite'>, keys: string[]): Promise<void> {\n await Promise.all(\n R.unnest(\n keys.map((key) => [\n tx.objectStore('metadata').delete(key),\n tx.objectStore('response').delete(key),\n tx.objectStore('visits').delete(key),\n ]),\n ),\n )\n }\n\n async remove(key: string): Promise<void> {\n try {\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n await this.__remove__(tx, [key])\n await tx.done\n } catch (error) {\n return\n }\n }\n\n\n private lastEvictExpiredTime = dayjs(0)\n\n /**\n * @zh 清除过期的缓存\n */\n protected async evictExpired(): Promise<void> {\n const now = dayjs()\n if (now.diff(this.lastEvictExpiredTime, 'second') < 1) return\n this.lastEvictExpiredTime = now\n\n try {\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n // const responseStore = tx.objectStore('response')\n // const visitsStore = tx.objectStore('visits')\n\n let cursor = await metadataStore\n .index('expiredAt')\n .openCursor(IDBKeyRange.upperBound(now.toDate()))\n\n const expiredKeys: string[] = []\n while (cursor) {\n if (dayjs(cursor.value.expiredAt).isBefore(now)) {\n expiredKeys.push(cursor.value.key)\n cursor = await cursor.continue()\n } else {\n break\n }\n }\n\n await this.__remove__(tx, expiredKeys)\n await tx.done\n\n this.__onCacheExpired__?.({ keys: expiredKeys })\n } catch (error) {\n return\n }\n }\n\n protected abstract evict(expectSize: number): Promise<boolean>\n}\n\n","\nexport const DEFAULT_TABLE_NAME = 'keq_cache_indexed_db_storage'\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class LFUIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n const visitsStore = tx.objectStore('visits')\n\n let cursor = await visitsStore\n .index('visitCount')\n .openCursor()\n\n const keys: string[] = []\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class LRUIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n const visitsStore = tx.objectStore('visits')\n\n\n const keys: string[] = []\n let cursor = await visitsStore.index('lastVisitedAt').openCursor()\n\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class TTLIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n const size = await this.getSize()\n\n let deficitSize = expectSize - size.free\n\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n\n const keys: string[] = []\n let cursor = await metadataStore.index('expiredAt').openCursor()\n\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { Promisable } from 'type-fest'\nimport { Eviction } from '~/constants/index.js'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { RandomIndexedDBStorage } from './random-indexed-db-storage.js'\nimport { LFUIndexedDBStorage } from './lfu-indexed-db-storage.js'\nimport { LRUIndexedDBStorage } from './lru-indexed-db-storage.js'\nimport { TTLIndexedDBStorage } from './ttl-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { CacheException } from '~/exceptions/index.js'\n\n\nexport class IndexedDBStorage extends KeqCacheStorage {\n private storage: InternalStorage\n\n constructor(options?: IndexedDbStorageOptions) {\n super()\n\n const eviction = options?.eviction || Eviction.LRU\n\n if (eviction === Eviction.RANDOM) {\n this.storage = new RandomIndexedDBStorage(options)\n } else if (eviction === Eviction.LFU) {\n this.storage = new LFUIndexedDBStorage(options)\n } else if (eviction === Eviction.LRU) {\n this.storage = new LRUIndexedDBStorage(options)\n } else if (eviction === Eviction.TTL) {\n this.storage = new TTLIndexedDBStorage(options)\n } else {\n throw new CacheException(`Not Supported Eviction: ${String(options?.eviction)}`)\n }\n }\n\n set(entry: CacheEntry): Promisable<void> {\n return this.storage.set(entry)\n }\n\n get(key: string): Promisable<CacheEntry | undefined> {\n return this.storage.get(key)\n }\n\n remove(key: string): Promisable<void> {\n return this.storage.remove(key)\n }\n}\n","import { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { MultiTierStorageOptions } from './types/multi-tier-storage-options.js'\n\n/**\n * @en Multi-tier cache storage that manages multiple KeqCacheStorage instances in tiers\n * @zh 多层缓存存储,管理多个分层的 KeqCacheStorage 实例\n */\nexport class MultiTierStorage extends KeqCacheStorage {\n private readonly storages: KeqCacheStorage[]\n\n /**\n * @param storages Array of storage instances ordered by performance (fastest first)\n * @zh 按性价比排序的存储实例数组,排在前面的成本低,排在后面的成本高\n */\n constructor(options: MultiTierStorageOptions) {\n super()\n\n if (!options.tiers || options.tiers.length === 0) {\n throw new Error('At least one storage instance is required')\n }\n\n this.storages = [...options.tiers]\n }\n\n /**\n * @en Get cache entry, searching from lowest to highest tier\n * @zh 获取缓存条目,从最底层到高层依次搜索\n */\n async get(key: string): Promise<CacheEntry | undefined> {\n for (let i = 0; i < this.storages.length; i++) {\n const storage = this.storages[i]\n const entry = await storage.get(key)\n\n if (entry) {\n // 缓存命中,如果不是在最底层,则需要同步到所有低层存储\n if (i > 0) {\n await this.syncToLowerTiers(entry, i)\n }\n return entry\n }\n }\n\n // 所有层都未命中\n return undefined\n }\n\n /**\n * @en Set cache entry to all tiers concurrently\n * @zh 并发写入所有层的缓存\n */\n async set(entry: CacheEntry): Promise<void> {\n // 并发写入所有存储层\n const promises = this.storages.map(async (storage) => storage.set(entry))\n await Promise.all(promises)\n }\n\n /**\n * @en Remove cache entry from all tiers\n * @zh 从所有层删除缓存条目\n */\n async remove(key: string): Promise<void> {\n // 并发删除所有存储层\n const promises = this.storages.map(async (storage) => storage.remove(key))\n await Promise.all(promises)\n }\n\n /**\n * @en Sync cache entry to all lower tiers (tiers with index < currentTierIndex)\n * @zh 将缓存条目同步到所有低层存储(索引小于当前层的存储)\n */\n private async syncToLowerTiers(entry: CacheEntry, currentTierIndex: number): Promise<void> {\n // 只同步到低层(索引更小的层),不向高层同步\n const lowerTierStorages = this.storages.slice(0, currentTierIndex)\n\n if (lowerTierStorages.length === 0) {\n return\n }\n\n // 并发写入所有低层存储\n // 使用克隆避免并发修改问题\n const promises = lowerTierStorages.map(async (storage) => storage.set(entry.clone()))\n\n // 同步写入失败不应该影响主要的get操作,所以我们捕获错误但不抛出\n try {\n await Promise.all(promises)\n } catch (error) {\n // 可以在这里添加日志记录,但不抛出错误\n console.warn('Failed to sync cache entry to lower tiers:', error)\n }\n }\n}\n","import { MemoryStorage } from '../memory-storage/memory-storage.js'\nimport { IndexedDBStorage } from '../indexed-db-storage/indexed-db-storage.js'\nimport { MultiTierStorage } from '../multi-tier-storage/multi-tier-storage.js'\nimport { TierStorageOptions } from './types/tier-storage-options.js'\n\n/**\n * @en Two-tier cache storage that combines MemoryStorage (L1) and IndexedDBStorage (L2)\n * @zh 二级缓存存储,结合了MemoryStorage(一级)和IndexedDBStorage(二级)\n *\n * This is a convenience wrapper around MultiTierStorage that provides:\n * - Fast in-memory cache (L1)\n * - Persistent IndexedDB cache (L2)\n * - Simplified configuration options\n */\nexport class TierStorage extends MultiTierStorage {\n constructor(options?: TierStorageOptions) {\n // Handle memory storage: use existing instance or create new one\n const memoryStorage = options?.memory instanceof MemoryStorage\n ? options.memory\n : new MemoryStorage(options?.memory)\n\n // Handle IndexedDB storage: use existing instance or create new one\n const indexedDBStorage = options?.indexedDB instanceof IndexedDBStorage\n ? options.indexedDB\n : new IndexedDBStorage(options?.indexedDB)\n\n super({\n tiers: [memoryStorage, indexedDBStorage],\n })\n }\n}\n"],"mappings":"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","names":["R","Eviction","Size","cacheFirst","networkFirst","cache","cache","context","cacheKey","cache","rule","next","dayjs","R","R","dayjs","dayjs","dayjs","R","R","dayjs","dayjs","db"]}
|
|
1
|
+
{"version":3,"sources":["../src/cache.ts","../src/request-cache-handler/request-cache-handler.ts","../src/exceptions/cache-exception.ts","../src/cache-entry/cache-entry.ts","../src/utils/get-response-bytes.ts","../src/constants/max-expired-at.ts","../src/constants/eviction.enum.ts","../src/constants/size.enum.ts","../src/utils/logger.ts","../src/utils/random.ts","../src/strategies/cache-first.ts","../src/strategies/network-first.ts","../src/strategies/network-only.ts","../src/strategies/stale-while-revalidate.ts","../src/constants/strategy.enum.ts","../src/storage/memory-storage/ttl-memory-storage.ts","../src/storage/memory-storage/base-memory-storage.ts","../src/storage/keq-cache-storage.ts","../src/storage/internal-storage/internal-storage.ts","../src/storage/memory-storage/utils/humanize-size.ts","../src/storage/memory-storage/utils/serialize-response-body.ts","../src/storage/memory-storage/random-memory-storage.ts","../src/storage/memory-storage/lru-memory-storage.ts","../src/storage/memory-storage/lfu-memory-storage.ts","../src/storage/memory-storage/memory-storage.ts","../src/storage/indexed-db-storage/random-indexed-db-storage.ts","../src/storage/indexed-db-storage/base-indexed-db-storage.ts","../src/storage/indexed-db-storage/constants/default-table-name.ts","../src/storage/indexed-db-storage/lfu-indexed-db-storage.ts","../src/storage/indexed-db-storage/lru-indexed-db-storage.ts","../src/storage/indexed-db-storage/ttl-indexed-db-storage.ts","../src/storage/indexed-db-storage/indexed-db-storage.ts","../src/storage/multi-tier-storage/multi-tier-storage.ts","../src/storage/tier-storage/tier-storage.ts"],"sourcesContent":["import * as R from 'ramda'\nimport * as fastq from 'fastq'\nimport type { queueAsPromised } from 'fastq'\nimport type { Keq, KeqMiddleware, KeqContext, KeqNext } from 'keq'\nimport { KeqCacheStorage } from './storage/keq-cache-storage.js'\nimport { RequestCacheHandler } from './request-cache-handler/index.js'\nimport { KeqCacheKeyFactory, KeqCacheRule, RequestCacheOptions } from './types/index.js'\n\n\nexport interface KeqCacheOptions extends Pick<RequestCacheOptions, 'serverTiming'> {\n storage: KeqCacheStorage\n\n /**\n * Cache Key Factory\n */\n keyFactory?: KeqCacheKeyFactory\n\n rules?: KeqCacheRule[]\n}\n\n\ndeclare module 'keq' {\n export interface KeqMiddlewareOptions<OP> {\n /**\n * [keq-cache](https://github.com/keq-request/keq-cache)\n */\n cache(option: RequestCacheOptions | false): Keq<OP>\n }\n\n export interface KeqEvents {\n 'cache:hit': {\n key: string\n response: Response\n context: KeqContext\n }\n\n 'cache:miss': {\n key: string\n context: KeqContext\n }\n\n 'cache:update': {\n key: string\n oldResponse?: Response\n newResponse: Response\n context: KeqContext\n }\n }\n\n export interface KeqGlobalCore {\n cache?: Record<string, queueAsPromised<{ next: KeqNext }, void>>\n }\n}\n\n\nexport function cache(options: KeqCacheOptions): KeqMiddleware {\n const storage = options.storage\n\n const rules: KeqCacheRule[] = options?.rules || []\n\n return async function cache(ctx, next) {\n if (ctx.options.cache === false) {\n await next()\n return\n }\n\n let requestCacheOptions: RequestCacheOptions | undefined = ctx.options.cache\n // let requestOptions: KeqCacheRequestOptions | undefined = ctx.options.cache\n\n const rule = rules.find((rule) => {\n if (rule.pattern === undefined || rule.pattern === true) return true\n if (typeof rule.pattern === 'function') return rule.pattern(ctx)\n return rule.pattern.test(ctx.request.__url__.href)\n })\n\n if (rule) requestCacheOptions = R.mergeRight(rule, requestCacheOptions || ({} as any))\n\n if (!requestCacheOptions || R.isEmpty(requestCacheOptions)) {\n await next()\n return\n }\n\n if (!requestCacheOptions.key) requestCacheOptions.key = options.keyFactory\n\n if (!ctx.locationId && !requestCacheOptions.key) {\n console.warn('[@keq/cache] Warning: Cannot resolve Cache Key. Cache is skipped.')\n await next()\n return\n }\n\n if (requestCacheOptions.serverTiming === undefined && options.serverTiming !== undefined) {\n requestCacheOptions.serverTiming = options.serverTiming\n }\n\n const cacheKey = RequestCacheHandler.resolveRequestCacheKey(ctx, requestCacheOptions)\n const handler = new RequestCacheHandler(cacheKey, storage, requestCacheOptions)\n const strategy = requestCacheOptions.strategy\n\n if (requestCacheOptions.concurrent) {\n await strategy(handler, ctx, next)\n } else {\n if (!ctx.global.core) ctx.global.core = {}\n if (!ctx.global.core.cache) ctx.global.core.cache = {}\n if (!ctx.global.core.cache[cacheKey]) {\n ctx.global.core.cache[cacheKey] = fastq.promise(async ({ next }) => {\n await next()\n }, 1)\n }\n\n const queue = ctx.global.core.cache[cacheKey]\n await queue.push({\n next: async () => {\n await strategy(handler, ctx, next)\n },\n })\n }\n }\n}\n","import * as R from 'ramda'\nimport { KeqContext } from 'keq'\nimport { CacheException } from '~/exceptions'\nimport { KeqCacheStorage } from '~/storage'\nimport { CacheEntry } from '~/cache-entry'\nimport { RequestCacheOptions } from '../types/index.js'\n\n\nexport type RequestCacheHandlerOptions = Omit<RequestCacheOptions, 'strategy'>\n\nexport class RequestCacheHandler {\n constructor(\n public readonly cacheKey: string,\n public readonly storage: KeqCacheStorage,\n public readonly options: Readonly<RequestCacheHandlerOptions>,\n ) {}\n\n /**\n * Resolve cache key for request context\n */\n static resolveRequestCacheKey(context: KeqContext, options: RequestCacheHandlerOptions): string {\n if (typeof options.key === 'string') return options.key\n else if (typeof options.key === 'function') return options.key(context)\n else if (R.isNil(options.key) && context.locationId) return context.locationId\n else throw new CacheException('Cannot resolve cache key')\n }\n\n /**\n * Get cache from storage\n */\n async getCache(): Promise<[string, CacheEntry | undefined]> {\n const key = this.cacheKey\n\n if (this.options.serverTiming) {\n const startAt = new Date()\n const entry = await this.storage.get(key)\n if (entry) {\n const dur = new Date().getTime() - startAt.getTime()\n\n const HeadersWithServerTiming = new Headers(entry.response.headers)\n HeadersWithServerTiming.set('Server-Timing', `keq-cache; dur=${dur}; desc=\"HIT\"`)\n\n entry.assignResponseHeaders(HeadersWithServerTiming)\n }\n\n return [key, entry]\n }\n\n return [key, await this.storage.get(key)]\n }\n\n /**\n * Store response that in context to storage\n */\n async setCache(context: KeqContext): Promise<[string, CacheEntry | undefined]> {\n const options = this.options\n const key = this.cacheKey\n\n if (!context.response) return [key, undefined]\n if (options.exclude && (await options.exclude(context.response))) return [key, undefined]\n\n const entry = await CacheEntry.build({\n key,\n response: context.response,\n ttl: options.ttl,\n })\n\n void this.storage.set(entry)\n\n return [key, entry]\n }\n}\n","import { Exception } from 'keq'\n\nexport class CacheException extends Exception {\n constructor(message: string) {\n super(`[@keq-request/cache] ${message}`)\n }\n}\n","import { createProxyResponse } from 'keq'\nimport { getResponseBytes } from '~/utils/get-response-bytes.js'\nimport { CacheEntryOptions } from './types/cache-entry-options.js'\nimport { CacheEntryBuildOptions } from './types/cache-entry-build-options.js'\nimport { MAX_EXPIRED_AT } from '~/constants/index.js'\n\n\nexport class CacheEntry {\n key: string\n response: Response\n\n /**\n * @en bytes\n * @zh 字节数\n */\n size: number\n\n expiredAt: Date\n\n constructor(options: CacheEntryOptions) {\n this.key = options.key\n this.response = createProxyResponse(options.response)\n this.size = options.size\n this.expiredAt = options.expiredAt ?? MAX_EXPIRED_AT\n }\n\n static async build(options: CacheEntryBuildOptions): Promise<CacheEntry> {\n const expiredAt = 'expiredAt' in options\n ? options.expiredAt\n : ('ttl' in options && typeof options.ttl === 'number' && options.ttl > 0)\n ? new Date(Date.now() + options.ttl * 1000)\n : MAX_EXPIRED_AT\n\n const response = options.response.clone()\n return new CacheEntry({\n key: options.key,\n response,\n size: options.size ?? (await getResponseBytes(response)),\n expiredAt: expiredAt,\n })\n }\n\n clone(): CacheEntry {\n return new CacheEntry({\n key: this.key,\n response: this.response.clone(),\n size: this.size,\n expiredAt: this.expiredAt,\n })\n }\n\n assignResponseHeaders(headers: Headers): void {\n this.response = new Response(this.response.body, {\n status: this.response.status,\n statusText: this.response.statusText,\n headers: headers,\n })\n }\n}\n","export async function getResponseBytes(response: Response): Promise<number> {\n const contentLength = response.headers.get('content-length')\n if (contentLength) {\n return parseInt(contentLength)\n }\n\n const arrayBuffer = await response.clone().arrayBuffer()\n return arrayBuffer.byteLength\n}\n","export const MAX_EXPIRED_AT = new Date(8640000000000000)\n","export enum Eviction {\n LRU = 'lru',\n LFU = 'lfu',\n RANDOM = 'random',\n TTL = 'ttl',\n}\n","export enum Size {\n B = 1,\n KB = 1024,\n MB = 1024 * 1024,\n GB = 1024 * 1024 * 1024,\n}\n","export class Logger {\n static debug(...args: unknown[]): void {\n console.debug('[@keq-request/cache] [DEBUG] ', ...args)\n }\n\n static error(...args: unknown[]): void {\n console.error('[@keq-request/cache] [ERROR] ', ...args)\n }\n}\n","export function random(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min)) + min\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\n\nexport const cacheFirst: KeqCacheStrategy = async function cacheFirst(handler, context, next): Promise<void> {\n // return async function (context, next): Promise<void> {\n const [cacheKey, cacheValue] = await handler.getCache()\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Cache First',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cacheValue ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (cacheValue) {\n // hit cache\n context.emitter.emit('cache:hit', { key: cacheKey, response: cacheValue.response, context })\n context.res = cacheValue.response\n return\n }\n\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n\n await next()\n\n const [, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Cache First',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: entry.key,\n oldResponse: undefined,\n newResponse: entry.response,\n context,\n })\n }\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\n\nexport const networkFirst: KeqCacheStrategy = async function networkFirst(handler, context, next) {\n try {\n await next()\n\n const [cacheKey, cache] = await handler.getCache()\n const [,entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Network First',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: entry.key,\n oldResponse: cache?.response,\n newResponse: entry.response,\n context,\n })\n }\n } catch (err) {\n const [cacheKey, cache] = await handler.getCache()\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Network First',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cache ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (!cache) {\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n throw err\n }\n\n context.emitter.emit('cache:hit', { key: cacheKey, response: cache.response, context })\n context.res = cache.response\n }\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\n\n\nexport const networkOnly: KeqCacheStrategy = async function (handler, context, next) {\n await next()\n}\n","import { KeqCacheStrategy } from '~/types/keq-cache-strategy.js'\nimport { Logger } from '~/utils'\n\nexport const staleWhileRevalidate: KeqCacheStrategy = async function (handler, context, next) {\n const [cacheKey, cache] = await handler.getCache()\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `Cache Status: ${cache ? 'HIT' : 'MISS'}`,\n ].join('\\n'))\n }\n\n if (cache) {\n context.emitter.emit('cache:hit', { key: cacheKey, response: cache.response, context })\n } else {\n context.emitter.emit('cache:miss', { key: cacheKey, context })\n }\n\n\n if (cache) {\n const orchestrator = context.orchestration.fork()\n\n context.res = cache.response\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n setTimeout(async () => {\n try {\n await orchestrator.execute()\n const context = orchestrator.context\n const [cacheKey, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: cacheKey,\n oldResponse: cache.response,\n newResponse: entry.response,\n context,\n })\n }\n } catch (err) {\n // ignore\n }\n }, 1)\n } else {\n await next()\n const [cacheKey, entry] = await handler.setCache(context)\n\n if (handler.options.debug) {\n Logger.debug([\n '',\n `Request: ${context.request.method.toUpperCase()} ${context.request.__url__.href}`,\n 'Strategy: Stale While Revalidate',\n `Cache Key: ${cacheKey}`,\n `ACTIONS: ${entry ? 'UPDATED' : 'EXCLUDED'}`,\n ].join('\\n'))\n }\n\n if (entry) {\n context.emitter.emit('cache:update', {\n key: cacheKey,\n oldResponse: undefined,\n newResponse: entry.response,\n context,\n })\n }\n }\n}\n","// export enum Strategy {\n// STALE_WHILE_REVALIDATE = 'stale-while-revalidate',\n// NETWORK_FIRST = 'network-first',\n// NETWORK_ONLY = 'network-only',\n// CATCH_FIRST = 'cache-first',\n// }\n\nimport { cacheFirst } from '~/strategies/cache-first.js'\nimport { networkFirst } from '~/strategies/network-first.js'\nimport { networkOnly } from '~/strategies/network-only.js'\nimport { staleWhileRevalidate } from '~/strategies/stale-while-revalidate.js'\n\nexport const Strategy = {\n STALE_WHILE_REVALIDATE: staleWhileRevalidate,\n NETWORK_FIRST: networkFirst,\n NETWORK_ONLY: networkOnly,\n CACHE_FIRST: cacheFirst,\n}\n","import dayjs from 'dayjs'\nimport * as R from 'ramda'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class TTLMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aExpiredAt = dayjs(a.expiredAt)\n const bExpiredAt = dayjs(b.expiredAt)\n\n return aExpiredAt.isBefore(bExpiredAt) ? 1 : -1\n })\n\n if (R.sum(R.pluck('size', entries)) < deficitSize) {\n this.debug((log) => log('Storage Size Not Enough: ', this.size.free, ' < ', deficitSize))\n return false\n }\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import dayjs from 'dayjs'\nimport * as R from 'ramda'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { MemoryStorageSize } from './types/memory-storage-size.js'\nimport { humanizeSize, serializeResponseBody } from './utils/index.js'\nimport { MAX_EXPIRED_AT } from '~/constants/index.js'\n\n\nexport abstract class BaseMemoryStorage extends InternalStorage {\n protected storage = new Map<string, CacheEntry>()\n\n protected visitTimeRecords = new Map<string, Date>()\n protected visitCountRecords = new Map<string, number>()\n\n protected get size(): MemoryStorageSize {\n const used = R.sum(R.pluck('size', [...this.storage.values()]))\n const free = this.__size__ > used ? this.__size__ - used : 0\n\n return {\n used,\n free,\n }\n }\n\n get(key: string): CacheEntry | undefined {\n this.evictExpired()\n const entry = this.storage.get(key)\n\n this.visitCountRecords.set(key, (this.visitCountRecords.get(key) ?? 0) + 1)\n this.visitTimeRecords.set(key, new Date())\n\n if (!entry) this.debug((log) => log(`Entry(${key}) Not Found`))\n else this.debug((log) => log(`Entry(${key}) Found: `, entry))\n\n return entry?.clone()\n }\n\n set(value: CacheEntry): void {\n if (!this.evict(value.size)) {\n this.debug((log) => log('Storage Size Not Enough: ', this.size.free, ' < ', value.size))\n return\n }\n\n this.storage.set(value.key, value)\n this.visitTimeRecords.set(value.key, new Date())\n this.visitCountRecords.set(value.key, (this.visitCountRecords.get(value.key) ?? 0))\n\n this.debug((log) => log('Entry Added: ', value))\n this.debug((log) => log('Storage Size: ', this.size))\n }\n\n __remove__(keys: string[]): void {\n for (const key of keys) {\n const entry = this.storage.get(key)\n if (!entry) return\n\n this.storage.delete(key)\n this.visitCountRecords.delete(key)\n this.visitTimeRecords.delete(key)\n\n this.debug((log) => log('Entry Removed: ', entry))\n this.debug((log) => log('Storage Size: ', this.size))\n }\n }\n\n remove(key: string): void {\n this.__remove__([key])\n }\n\n\n private lastEvictExpiredTime = dayjs()\n\n /**\n * @zh 清除过期的缓存\n */\n protected evictExpired(): void {\n const now = dayjs()\n\n if (now.diff(this.lastEvictExpiredTime, 'second') < 1) return\n\n const keys: string[] = []\n for (const [key, entry] of this.storage.entries()) {\n if (entry.expiredAt && now.isAfter(entry.expiredAt)) {\n keys.push(key)\n }\n }\n\n this.__remove__(keys)\n this.__onCacheExpired__?.({ keys })\n }\n\n /**\n * @en Evict the storage to make sure the size is enough\n * @zh 清除缓存以确保有足够的空间\n *\n * @return {boolean} - is evicted successfully\n */\n protected evict(expectSize: number): boolean {\n this.evictExpired()\n const size = this.size\n\n return size.free >= expectSize\n }\n\n\n /**\n * @en Print all cached data using console.table for debugging\n * @zh 使用 console.table 打印所有缓存数据,用于调试\n */\n async print(): Promise<void> {\n if (this.storage.size === 0) {\n console.log('MemoryStorage is empty')\n return\n }\n\n const entries = await Promise.all(\n [...this.storage.entries()].map(async ([key, entry]) => {\n const body = await serializeResponseBody(entry.response.clone())\n\n return {\n key,\n size: humanizeSize(entry.size),\n 'Expired Time': entry.expiredAt.getTime() >= MAX_EXPIRED_AT.getTime() ? '-' : entry.expiredAt.toISOString(),\n 'Visit Count': this.visitCountRecords.get(key) ?? 0,\n 'Last Visit Time': this.visitTimeRecords.get(key)?.toISOString() ?? '-',\n 'Response Status': entry.response.status,\n 'Response URL': entry.response.url,\n 'Response Body': body,\n }\n }),\n )\n\n console.table(entries)\n }\n}\n\n","import { Promisable } from 'type-fest'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport abstract class KeqCacheStorage {\n /**\n * @en Get the length of the storage\n * @zh 获取 Storage 缓存的条目数量\n */\n abstract get(key: string): Promisable<CacheEntry | undefined>\n\n /**\n * @en Set a new entry to the storage\n * @zh 将被缓存的数据添加到Storage中\n */\n abstract set(entry: CacheEntry): Promisable<void>\n\n /**\n * @en Remove an entry by key\n * @zh 根据key删除Storage中的数据\n */\n abstract remove(key: string): Promisable<void>\n}\n","import { InternalStorageOptions } from './types/storage-options.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { OnCacheEvictEvent, OnCacheExpiredEvent, OnCacheGetEvent, OnCacheRemoveEvent, OnCacheSetEvent } from './types/events.js'\nimport { CacheException } from '~/exceptions/index.js'\nimport { Logger } from '~/utils/index.js'\n\n\nexport abstract class InternalStorage extends KeqCacheStorage {\n protected readonly __id__: string = Math.random()\n .toString(36)\n .slice(2)\n\n protected readonly __size__: number\n protected readonly __debug__: boolean\n\n protected readonly __onCacheGet__?: (event: OnCacheGetEvent) => void\n protected readonly __onCacheSet__?: (event: OnCacheSetEvent) => void\n protected readonly __onCacheRemove__?: (event: OnCacheRemoveEvent) => void\n protected readonly __onCacheEvict__?: (event: OnCacheEvictEvent) => void\n protected readonly __onCacheExpired__?: (event: OnCacheExpiredEvent) => void\n\n constructor(options?: InternalStorageOptions) {\n super()\n\n if (options?.size && (typeof options?.size !== 'number' || options.size <= 0)) {\n throw new CacheException(`Invalid size: ${String(options?.size)}`)\n }\n\n this.__size__ = options?.size ?? Infinity\n this.__debug__ = !!options?.debug\n\n this.__onCacheGet__ = options?.onCacheGet\n this.__onCacheSet__ = options?.onCacheSet\n this.__onCacheRemove__ = options?.onCacheRemove\n this.__onCacheEvict__ = options?.onCacheEvict\n\n this.debug((log) => log('Storage Created: ', this))\n }\n\n protected debug(fn: (log: (...args: unknown[]) => void) => void): void {\n if (this.__debug__) {\n fn((...args: unknown[]) => {\n Logger.debug(`[Storage(${this.__id__})]`, ...args)\n })\n }\n }\n}\n","/**\n * @en Humanize size in bytes to KB, MB, GB\n * @zh 将字节数转换为 KB、MB、GB 等易读格式\n */\nexport function humanizeSize(size: number): string {\n if (size < 1024) return `${size} B`\n if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)} KB`\n if (size < 1024 * 1024 * 1024) return `${(size / (1024 * 1024)).toFixed(2)} MB`\n return `${(size / (1024 * 1024 * 1024)).toFixed(2)} GB`\n}\n","/**\n * @en Serialize the response body based on content-type\n * @zh 根据 content-type 序列化响应体\n */\nexport async function serializeResponseBody(response: Response): Promise<string> {\n const contentType = response.headers.get('content-type') ?? ''\n\n try {\n if (contentType.includes('application/json')) {\n const json = await response.json()\n return JSON.stringify(json)\n }\n\n if (\n contentType.includes('text/')\n || contentType.includes('application/xml')\n || contentType.includes('application/javascript')\n ) {\n return await response.text()\n }\n\n return '[Binary or unsupported content]'\n } catch {\n return '[Unable to serialize]'\n }\n}\n","import { random } from '~/utils/random.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class RandomMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const index = random(0, entries.length - 1)\n const entry = entries[index]\n deficitSize -= entry.size\n entries.splice(index, 1)\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import dayjs from 'dayjs'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\n\n\nexport class LRUMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aVisitAt = this.visitTimeRecords.get(a.key)\n const bVisitAt = this.visitTimeRecords.get(b.key)\n\n if (aVisitAt === bVisitAt) return 0\n if (!aVisitAt) return 1\n if (!bVisitAt) return -1\n\n return dayjs(aVisitAt).isBefore(dayjs(bVisitAt)) ? 1 : -1\n })\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\n\n\nexport class LFUMemoryStorage extends BaseMemoryStorage {\n constructor(options?: MemoryStorageOptions) {\n super(options)\n }\n\n get(key: string): CacheEntry | undefined {\n const entry = super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n set(value: CacheEntry): void {\n super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n remove(key: string): void {\n super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n protected evict(expectSize: number): boolean {\n if (expectSize > this.__size__) {\n this.debug((log) => log('Storage Size Not Enough: ', this.__size__, ' < ', expectSize))\n return false\n }\n this.evictExpired()\n\n let deficitSize = expectSize - this.size.free\n if (deficitSize <= 0) return true\n\n const entries = [...this.storage.values()]\n .sort((a, b) => {\n const aVisitCount = this.visitCountRecords.get(a.key) || 0\n const bVisitCount = this.visitCountRecords.get(b.key) || 0\n return bVisitCount - aVisitCount\n })\n\n const keys: string[] = []\n while (deficitSize > 0 && entries.length) {\n const entry = entries.pop()!\n deficitSize -= entry.size\n keys.push(entry.key)\n }\n\n this.__remove__(keys)\n this.__onCacheEvict__?.({ keys })\n\n return true\n }\n}\n","import { Promisable } from 'type-fest'\nimport { Eviction } from '~/constants/index.js'\nimport { TTLMemoryStorage } from './ttl-memory-storage.js'\nimport { RandomMemoryStorage } from './random-memory-storage.js'\nimport { LRUMemoryStorage } from './lru-memory-storage.js'\nimport { LFUMemoryStorage } from './lfu-memory-storage.js'\nimport { MemoryStorageOptions } from './types/memory-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { BaseMemoryStorage } from './base-memory-storage.js'\n\nexport class MemoryStorage extends KeqCacheStorage {\n private storage: BaseMemoryStorage\n\n constructor(options?: MemoryStorageOptions) {\n super()\n\n const eviction = options?.eviction || Eviction.LRU\n\n if (eviction === Eviction.TTL) {\n this.storage = new TTLMemoryStorage(options)\n } else if (eviction === Eviction.RANDOM) {\n this.storage = new RandomMemoryStorage(options)\n } else if (eviction === Eviction.LRU) {\n this.storage = new LRUMemoryStorage(options)\n } else if (eviction === Eviction.LFU) {\n this.storage = new LFUMemoryStorage(options)\n } else {\n throw new TypeError(`Invalid eviction: ${String(eviction)}`)\n }\n }\n\n set(entry: CacheEntry): Promisable<void> {\n return this.storage.set(entry)\n }\n\n get(key: string): Promisable<CacheEntry | undefined> {\n return this.storage.get(key)\n }\n\n remove(key: string): Promisable<void> {\n return this.storage.remove(key)\n }\n\n async print(): Promise<void> {\n return this.storage.print()\n }\n}\n","import * as R from 'ramda'\nimport { random } from '~/utils/random.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/index.js'\n\n\nexport class RandomIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n\n const metadatas = await metadataStore.getAll()\n const totalSize = R.sum(metadatas.map((m) => m.size))\n\n if (totalSize < deficitSize) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize - totalSize}`))\n tx.abort()\n return false\n }\n\n const keys: string[] = []\n while (deficitSize > 0 && metadatas.length) {\n const index = random(0, metadatas.length - 1)\n\n const metadata = metadatas[index]\n deficitSize -= metadata.size\n keys.push(metadata.key)\n metadatas.splice(index, 1)\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import * as R from 'ramda'\nimport dayjs from 'dayjs'\nimport { IDBPDatabase, IDBPTransaction, openDB } from 'idb'\nimport { CacheEntry } from '~/cache-entry/index.js'\nimport { CacheException } from '~/exceptions/index.js'\nimport { Logger } from '~/utils/index.js'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { DEFAULT_TABLE_NAME } from './constants/default-table-name.js'\nimport { IndexedDBStorageSize, IndexedDbStorageOptions, IndexedDBSchema, IndexedDBEntryResponse, IndexedDBEntryMetadata } from './types/index.js'\n\n\nexport abstract class BaseIndexedDBStorage extends InternalStorage {\n private readonly tableName: string = DEFAULT_TABLE_NAME\n private db?: IDBPDatabase<IndexedDBSchema>\n\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n if (options?.tableName === DEFAULT_TABLE_NAME) {\n throw new CacheException(`IndexedDBStorage name cannot be \"${DEFAULT_TABLE_NAME}\"`)\n }\n\n this.tableName = options?.tableName || DEFAULT_TABLE_NAME\n }\n\n protected async openDB(): Promise<IDBPDatabase<IndexedDBSchema>> {\n if (this.db) return this.db\n const tableName = this.tableName\n\n const db = await openDB<IndexedDBSchema>(tableName, 2, {\n upgrade(db) {\n if (!db.objectStoreNames.contains('metadata')) {\n const entriesStore = db.createObjectStore('metadata', { keyPath: 'key' })\n\n entriesStore.createIndex('expiredAt', 'expiredAt')\n }\n\n if (!db.objectStoreNames.contains('response')) {\n const responsesStore = db.createObjectStore('response', { keyPath: 'key' })\n responsesStore.createIndex('responseStatus', 'responseStatus')\n }\n\n if (!db.objectStoreNames.contains('visits')) {\n const visitsStore = db.createObjectStore('visits', { keyPath: 'key' })\n visitsStore.createIndex('visitCount', 'visitCount')\n visitsStore.createIndex('lastVisitedAt', 'lastVisitedAt')\n }\n },\n\n blocked() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is blocked`)\n },\n\n blocking() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is blocking`)\n },\n\n terminated() {\n Logger.error(`[@keq-request/cache] IndexedDB Table ${tableName} is terminated`)\n },\n })\n\n this.db = db\n return db\n }\n\n protected async getSize(): Promise<IndexedDBStorageSize> {\n const db = await this.openDB()\n const items = await db.getAll('metadata')\n const used = R.sum(items.map((entry) => entry.size))\n const free = this.__size__ - used\n return { used, free }\n }\n\n\n async get(key: string): Promise<CacheEntry | undefined> {\n await this.evictExpired()\n\n try {\n const db = await this.openDB()\n const dbMetadata = await db.get('metadata', key)\n const dbResponse = await db.get('response', key)\n const dbVisits = await db.get('visits', key)\n\n if (!dbMetadata || !dbResponse) return\n\n await db.put('visits', {\n key: dbMetadata.key,\n visitCount: dbVisits ? dbVisits.visitCount + 1 : 1,\n lastVisitedAt: new Date(),\n })\n\n const response = new Response(dbResponse.responseBody, {\n status: dbResponse.responseStatus,\n headers: new Headers(dbResponse.responseHeaders),\n statusText: dbResponse.responseStatusText,\n })\n\n return await CacheEntry.build({\n key: dbMetadata.key,\n expiredAt: dbMetadata.expiredAt,\n response,\n size: dbMetadata.size,\n })\n } catch (error) {\n return\n }\n }\n\n async set(entry: CacheEntry): Promise<void> {\n try {\n if (!await this.evict(entry.size)) {\n const size = await this.getSize()\n this.debug((log) => log(`Storage Size Not Enough: ${size.free} < ${entry.size}`))\n return\n }\n\n const dbMetadata: IndexedDBEntryMetadata = {\n key: entry.key,\n size: entry.size,\n expiredAt: entry.expiredAt,\n visitedAt: new Date(),\n visitCount: 0,\n }\n\n const response = entry.response.clone()\n const dbResponse: IndexedDBEntryResponse = {\n key: entry.key,\n responseBody: await response.arrayBuffer(),\n responseHeaders: [...response.headers.entries()],\n responseStatus: response.status,\n responseStatusText: response.statusText,\n }\n\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n const responseStore = tx.objectStore('response')\n const visitsStore = tx.objectStore('visits')\n\n const dbVisits = (await visitsStore.get(entry.key)) || {\n key: entry.key,\n visitCount: 0,\n lastVisitedAt: new Date(),\n }\n\n await Promise.all([\n metadataStore.put(dbMetadata),\n responseStore.put(dbResponse),\n visitsStore.put(dbVisits),\n ])\n\n await tx.done\n } catch (error) {\n return\n }\n }\n\n protected async __remove__(tx: IDBPTransaction<IndexedDBSchema, ('metadata' | 'response' | 'visits')[], 'readwrite'>, keys: string[]): Promise<void> {\n await Promise.all(\n R.unnest(\n keys.map((key) => [\n tx.objectStore('metadata').delete(key),\n tx.objectStore('response').delete(key),\n tx.objectStore('visits').delete(key),\n ]),\n ),\n )\n }\n\n async remove(key: string): Promise<void> {\n try {\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n await this.__remove__(tx, [key])\n await tx.done\n } catch (error) {\n return\n }\n }\n\n\n private lastEvictExpiredTime = dayjs(0)\n\n /**\n * @zh 清除过期的缓存\n */\n protected async evictExpired(): Promise<void> {\n const now = dayjs()\n if (now.diff(this.lastEvictExpiredTime, 'second') < 1) return\n this.lastEvictExpiredTime = now\n\n try {\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n // const responseStore = tx.objectStore('response')\n // const visitsStore = tx.objectStore('visits')\n\n let cursor = await metadataStore\n .index('expiredAt')\n .openCursor(IDBKeyRange.upperBound(now.toDate()))\n\n const expiredKeys: string[] = []\n while (cursor) {\n if (dayjs(cursor.value.expiredAt).isBefore(now)) {\n expiredKeys.push(cursor.value.key)\n cursor = await cursor.continue()\n } else {\n break\n }\n }\n\n await this.__remove__(tx, expiredKeys)\n await tx.done\n\n this.__onCacheExpired__?.({ keys: expiredKeys })\n } catch (error) {\n return\n }\n }\n\n protected abstract evict(expectSize: number): Promise<boolean>\n}\n\n","\nexport const DEFAULT_TABLE_NAME = 'keq_cache_indexed_db_storage'\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class LFUIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n const visitsStore = tx.objectStore('visits')\n\n let cursor = await visitsStore\n .index('visitCount')\n .openCursor()\n\n const keys: string[] = []\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class LRUIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n\n const size = await this.getSize()\n let deficitSize = expectSize - size.free\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n const metadataStore = tx.objectStore('metadata')\n const visitsStore = tx.objectStore('visits')\n\n\n const keys: string[] = []\n let cursor = await visitsStore.index('lastVisitedAt').openCursor()\n\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { CacheEntry } from '~/cache-entry/index.js'\nimport { BaseIndexedDBStorage } from './base-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\n\n\nexport class TTLIndexedDBStorage extends BaseIndexedDBStorage {\n constructor(options?: IndexedDbStorageOptions) {\n super(options)\n }\n\n async get(key: string): Promise<CacheEntry | undefined> {\n const entry = await super.get(key)\n this.__onCacheGet__?.({ key })\n return entry\n }\n\n async set(value: CacheEntry): Promise<void> {\n await super.set(value)\n this.__onCacheSet__?.({ key: value.key })\n }\n\n async remove(key: string): Promise<void> {\n await super.remove(key)\n this.__onCacheRemove__?.({ key })\n }\n\n async evict(expectSize: number): Promise<boolean> {\n await this.evictExpired()\n const size = await this.getSize()\n\n let deficitSize = expectSize - size.free\n\n if (deficitSize <= 0) return true\n\n const db = await this.openDB()\n\n const tx = db.transaction(['metadata', 'response', 'visits'], 'readwrite')\n\n const metadataStore = tx.objectStore('metadata')\n\n const keys: string[] = []\n let cursor = await metadataStore.index('expiredAt').openCursor()\n\n while (deficitSize > 0 && cursor) {\n const metadata = await metadataStore.get(cursor.value.key)\n if (!metadata) {\n await cursor.delete()\n cursor = await cursor.continue()\n continue\n }\n\n deficitSize -= metadata.size\n keys.push(cursor.value.key)\n cursor = await cursor.continue()\n }\n\n if (deficitSize > 0) {\n this.debug((log) => log(`Storage Size Not Enough, deficit size: ${deficitSize}`))\n tx.abort()\n return false\n }\n\n await this.__remove__(tx, keys)\n await tx.done\n this.__onCacheEvict__?.({ keys })\n return true\n }\n}\n","import { Promisable } from 'type-fest'\nimport { Eviction } from '~/constants/index.js'\nimport { InternalStorage } from '../internal-storage/internal-storage.js'\nimport { RandomIndexedDBStorage } from './random-indexed-db-storage.js'\nimport { LFUIndexedDBStorage } from './lfu-indexed-db-storage.js'\nimport { LRUIndexedDBStorage } from './lru-indexed-db-storage.js'\nimport { TTLIndexedDBStorage } from './ttl-indexed-db-storage.js'\nimport { IndexedDbStorageOptions } from './types/indexed-db-storage-options.js'\nimport { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { CacheException } from '~/exceptions/index.js'\n\n\nexport class IndexedDBStorage extends KeqCacheStorage {\n private storage: InternalStorage\n\n constructor(options?: IndexedDbStorageOptions) {\n super()\n\n const eviction = options?.eviction || Eviction.LRU\n\n if (eviction === Eviction.RANDOM) {\n this.storage = new RandomIndexedDBStorage(options)\n } else if (eviction === Eviction.LFU) {\n this.storage = new LFUIndexedDBStorage(options)\n } else if (eviction === Eviction.LRU) {\n this.storage = new LRUIndexedDBStorage(options)\n } else if (eviction === Eviction.TTL) {\n this.storage = new TTLIndexedDBStorage(options)\n } else {\n throw new CacheException(`Not Supported Eviction: ${String(options?.eviction)}`)\n }\n }\n\n set(entry: CacheEntry): Promisable<void> {\n return this.storage.set(entry)\n }\n\n get(key: string): Promisable<CacheEntry | undefined> {\n return this.storage.get(key)\n }\n\n remove(key: string): Promisable<void> {\n return this.storage.remove(key)\n }\n}\n","import { CacheEntry } from '~/cache-entry/cache-entry.js'\nimport { KeqCacheStorage } from '../keq-cache-storage.js'\nimport { MultiTierStorageOptions } from './types/multi-tier-storage-options.js'\n\n/**\n * @en Multi-tier cache storage that manages multiple KeqCacheStorage instances in tiers\n * @zh 多层缓存存储,管理多个分层的 KeqCacheStorage 实例\n */\nexport class MultiTierStorage extends KeqCacheStorage {\n private readonly storages: KeqCacheStorage[]\n\n /**\n * @param storages Array of storage instances ordered by performance (fastest first)\n * @zh 按性价比排序的存储实例数组,排在前面的成本低,排在后面的成本高\n */\n constructor(options: MultiTierStorageOptions) {\n super()\n\n if (!options.tiers || options.tiers.length === 0) {\n throw new Error('At least one storage instance is required')\n }\n\n this.storages = [...options.tiers]\n }\n\n /**\n * @en Get cache entry, searching from lowest to highest tier\n * @zh 获取缓存条目,从最底层到高层依次搜索\n */\n async get(key: string): Promise<CacheEntry | undefined> {\n for (let i = 0; i < this.storages.length; i++) {\n const storage = this.storages[i]\n const entry = await storage.get(key)\n\n if (entry) {\n // 缓存命中,如果不是在最底层,则需要同步到所有低层存储\n if (i > 0) {\n await this.syncToLowerTiers(entry, i)\n }\n return entry\n }\n }\n\n // 所有层都未命中\n return undefined\n }\n\n /**\n * @en Set cache entry to all tiers concurrently\n * @zh 并发写入所有层的缓存\n */\n async set(entry: CacheEntry): Promise<void> {\n // 并发写入所有存储层\n const promises = this.storages.map(async (storage) => storage.set(entry))\n await Promise.all(promises)\n }\n\n /**\n * @en Remove cache entry from all tiers\n * @zh 从所有层删除缓存条目\n */\n async remove(key: string): Promise<void> {\n // 并发删除所有存储层\n const promises = this.storages.map(async (storage) => storage.remove(key))\n await Promise.all(promises)\n }\n\n /**\n * @en Sync cache entry to all lower tiers (tiers with index < currentTierIndex)\n * @zh 将缓存条目同步到所有低层存储(索引小于当前层的存储)\n */\n private async syncToLowerTiers(entry: CacheEntry, currentTierIndex: number): Promise<void> {\n // 只同步到低层(索引更小的层),不向高层同步\n const lowerTierStorages = this.storages.slice(0, currentTierIndex)\n\n if (lowerTierStorages.length === 0) {\n return\n }\n\n // 并发写入所有低层存储\n // 使用克隆避免并发修改问题\n const promises = lowerTierStorages.map(async (storage) => storage.set(entry.clone()))\n\n // 同步写入失败不应该影响主要的get操作,所以我们捕获错误但不抛出\n try {\n await Promise.all(promises)\n } catch (error) {\n // 可以在这里添加日志记录,但不抛出错误\n console.warn('Failed to sync cache entry to lower tiers:', error)\n }\n }\n}\n","import { MemoryStorage } from '../memory-storage/memory-storage.js'\nimport { IndexedDBStorage } from '../indexed-db-storage/indexed-db-storage.js'\nimport { MultiTierStorage } from '../multi-tier-storage/multi-tier-storage.js'\nimport { TierStorageOptions } from './types/tier-storage-options.js'\n\n/**\n * @en Two-tier cache storage that combines MemoryStorage (L1) and IndexedDBStorage (L2)\n * @zh 二级缓存存储,结合了MemoryStorage(一级)和IndexedDBStorage(二级)\n *\n * This is a convenience wrapper around MultiTierStorage that provides:\n * - Fast in-memory cache (L1)\n * - Persistent IndexedDB cache (L2)\n * - Simplified configuration options\n */\nexport class TierStorage extends MultiTierStorage {\n constructor(options?: TierStorageOptions) {\n // Handle memory storage: use existing instance or create new one\n const memoryStorage = options?.memory instanceof MemoryStorage\n ? options.memory\n : new MemoryStorage(options?.memory)\n\n // Handle IndexedDB storage: use existing instance or create new one\n const indexedDBStorage = options?.indexedDB instanceof IndexedDBStorage\n ? options.indexedDB\n : new IndexedDBStorage(options?.indexedDB)\n\n super({\n tiers: [memoryStorage, indexedDBStorage],\n })\n }\n}\n"],"mappings":"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","names":["R","Eviction","Size","cacheFirst","networkFirst","cache","cache","context","cacheKey","cache","rule","next","dayjs","R","R","dayjs","dayjs","dayjs","R","R","dayjs","dayjs","db"]}
|
|
@@ -4,17 +4,18 @@ import { CacheEntry } from '../cache-entry';
|
|
|
4
4
|
import { RequestCacheOptions } from '../types/index.js';
|
|
5
5
|
export type RequestCacheHandlerOptions = Omit<RequestCacheOptions, 'strategy'>;
|
|
6
6
|
export declare class RequestCacheHandler {
|
|
7
|
+
readonly cacheKey: string;
|
|
7
8
|
readonly storage: KeqCacheStorage;
|
|
8
9
|
readonly options: Readonly<RequestCacheHandlerOptions>;
|
|
9
|
-
constructor(storage: KeqCacheStorage, options: Readonly<RequestCacheHandlerOptions>);
|
|
10
|
+
constructor(cacheKey: string, storage: KeqCacheStorage, options: Readonly<RequestCacheHandlerOptions>);
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* Resolve cache key for request context
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
+
static resolveRequestCacheKey(context: KeqContext, options: RequestCacheHandlerOptions): string;
|
|
14
15
|
/**
|
|
15
16
|
* Get cache from storage
|
|
16
17
|
*/
|
|
17
|
-
getCache(
|
|
18
|
+
getCache(): Promise<[string, CacheEntry | undefined]>;
|
|
18
19
|
/**
|
|
19
20
|
* Store response that in context to storage
|
|
20
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-cache-handler.d.ts","sourceRoot":"","sources":["../../src/request-cache-handler/request-cache-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAGvD,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAA;AAE9E,qBAAa,mBAAmB;aAEZ,OAAO,EAAE,eAAe;aACxB,OAAO,EAAE,QAAQ,CAAC,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"request-cache-handler.d.ts","sourceRoot":"","sources":["../../src/request-cache-handler/request-cache-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAGvD,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAA;AAE9E,qBAAa,mBAAmB;aAEZ,QAAQ,EAAE,MAAM;aAChB,OAAO,EAAE,eAAe;aACxB,OAAO,EAAE,QAAQ,CAAC,0BAA0B,CAAC;gBAF7C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,eAAe,EACxB,OAAO,EAAE,QAAQ,CAAC,0BAA0B,CAAC;IAG/D;;OAEG;IACH,MAAM,CAAC,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,0BAA0B,GAAG,MAAM;IAO/F;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC;IAqB3D;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC;CAiB/E"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@keq-request/cache",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.30",
|
|
4
4
|
"description": "Adds request caching capabilities similar to service workers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"keq",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"@types/ramda": "^0.31.1",
|
|
31
31
|
"fake-indexeddb": "^6.2.5",
|
|
32
32
|
"isomorphic-fetch": "^3.0.0",
|
|
33
|
-
"keq": "5.0.0-alpha.
|
|
33
|
+
"keq": "5.0.0-alpha.30"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"keq": "^5.0.0-alpha.
|
|
36
|
+
"keq": "^5.0.0-alpha.30"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"dayjs": "^1.11.19",
|