@b9g/cache 0.1.4 → 0.1.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b9g/cache",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Universal Cache API for ServiceWorker applications. Provides standard CacheStorage and Cache interfaces across all JavaScript runtimes.",
5
5
  "keywords": [
6
6
  "cache",
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "dependencies": {},
17
17
  "devDependencies": {
18
- "@b9g/libuild": "^0.1.11",
18
+ "@b9g/libuild": "^0.1.18",
19
19
  "bun-types": "latest"
20
20
  },
21
21
  "type": "module",
package/src/index.d.ts CHANGED
@@ -17,6 +17,10 @@ export interface CacheQueryOptions {
17
17
  /** Custom cache name for scoped operations */
18
18
  cacheName?: string;
19
19
  }
20
+ /**
21
+ * Convert RequestInfo or URL to Request
22
+ */
23
+ export declare function toRequest(request: RequestInfo | URL): Request;
20
24
  /**
21
25
  * Abstract Cache class implementing the Cache API interface
22
26
  * Provides shared implementations for add() and addAll() while requiring
@@ -26,19 +30,19 @@ export declare abstract class Cache {
26
30
  /**
27
31
  * Returns a Promise that resolves to the response associated with the first matching request
28
32
  */
29
- abstract match(request: Request, options?: CacheQueryOptions): Promise<Response | undefined>;
33
+ abstract match(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<Response | undefined>;
30
34
  /**
31
35
  * Puts a request/response pair into the cache
32
36
  */
33
- abstract put(request: Request, response: Response): Promise<void>;
37
+ abstract put(request: RequestInfo | URL, response: Response): Promise<void>;
34
38
  /**
35
39
  * Finds the cache entry whose key is the request, and if found, deletes it and returns true
36
40
  */
37
- abstract delete(request: Request, options?: CacheQueryOptions): Promise<boolean>;
41
+ abstract delete(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<boolean>;
38
42
  /**
39
43
  * Returns a Promise that resolves to an array of cache keys (Request objects)
40
44
  */
41
- abstract keys(request?: Request, options?: CacheQueryOptions): Promise<readonly Request[]>;
45
+ abstract keys(request?: RequestInfo | URL, options?: CacheQueryOptions): Promise<readonly Request[]>;
42
46
  /**
43
47
  * Takes a URL, retrieves it and adds the resulting response object to the cache
44
48
  * Shared implementation using fetch() and put()
@@ -56,10 +60,10 @@ export declare abstract class Cache {
56
60
  matchAll(request?: Request, options?: CacheQueryOptions): Promise<readonly Response[]>;
57
61
  }
58
62
  /**
59
- * Generate a cache key from a Request object
63
+ * Generate a cache key from a Request, string URL, or URL object
60
64
  * Normalizes the request for consistent cache key generation
61
65
  */
62
- export declare function generateCacheKey(request: Request, options?: CacheQueryOptions): string;
66
+ export declare function generateCacheKey(request: RequestInfo | URL, options?: CacheQueryOptions): string;
63
67
  /**
64
68
  * Factory function for creating Cache instances based on cache name
65
69
  */
package/src/index.js CHANGED
@@ -1,5 +1,14 @@
1
1
  /// <reference types="./index.d.ts" />
2
2
  // src/index.ts
3
+ function toRequest(request) {
4
+ if (typeof request === "string") {
5
+ return new Request(request);
6
+ }
7
+ if (request instanceof URL) {
8
+ return new Request(request.href);
9
+ }
10
+ return request;
11
+ }
3
12
  var Cache = class {
4
13
  /**
5
14
  * Takes a URL, retrieves it and adds the resulting response object to the cache
@@ -38,11 +47,12 @@ var Cache = class {
38
47
  }
39
48
  };
40
49
  function generateCacheKey(request, options) {
41
- const url = new URL(request.url);
50
+ const req = toRequest(request);
51
+ const url = new URL(req.url);
42
52
  if (options?.ignoreSearch) {
43
53
  url.search = "";
44
54
  }
45
- const method = options?.ignoreMethod ? "GET" : request.method;
55
+ const method = options?.ignoreMethod ? "GET" : req.method;
46
56
  return `${method}:${url.href}`;
47
57
  }
48
58
  var CustomCacheStorage = class {
@@ -183,5 +193,6 @@ var CustomCacheStorage = class {
183
193
  export {
184
194
  Cache,
185
195
  CustomCacheStorage,
186
- generateCacheKey
196
+ generateCacheKey,
197
+ toRequest
187
198
  };
package/src/memory.d.ts CHANGED
@@ -16,19 +16,19 @@ export declare class MemoryCache extends Cache {
16
16
  /**
17
17
  * Find a cached response for the given request
18
18
  */
19
- match(request: Request, options?: CacheQueryOptions): Promise<Response | undefined>;
19
+ match(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<Response | undefined>;
20
20
  /**
21
21
  * Store a request/response pair in the cache
22
22
  */
23
- put(request: Request, response: Response): Promise<void>;
23
+ put(request: RequestInfo | URL, response: Response): Promise<void>;
24
24
  /**
25
25
  * Delete matching entries from the cache
26
26
  */
27
- delete(request: Request, options?: CacheQueryOptions): Promise<boolean>;
27
+ delete(request: RequestInfo | URL, options?: CacheQueryOptions): Promise<boolean>;
28
28
  /**
29
29
  * Get all stored requests, optionally filtered by a request pattern
30
30
  */
31
- keys(request?: Request, options?: CacheQueryOptions): Promise<readonly Request[]>;
31
+ keys(request?: RequestInfo | URL, options?: CacheQueryOptions): Promise<readonly Request[]>;
32
32
  /**
33
33
  * Clear all entries from the cache
34
34
  */
package/src/memory.js CHANGED
@@ -1,6 +1,10 @@
1
1
  /// <reference types="./memory.d.ts" />
2
2
  // src/memory.ts
3
- import { Cache, generateCacheKey } from "./index.js";
3
+ import {
4
+ Cache,
5
+ generateCacheKey,
6
+ toRequest
7
+ } from "./index.js";
4
8
  var MemoryCache = class extends Cache {
5
9
  #storage;
6
10
  #accessOrder;
@@ -19,6 +23,22 @@ var MemoryCache = class extends Cache {
19
23
  * Find a cached response for the given request
20
24
  */
21
25
  async match(request, options) {
26
+ if (options?.ignoreSearch) {
27
+ const filterKey = generateCacheKey(request, options);
28
+ for (const [key2, entry2] of this.#storage) {
29
+ if (this.#isExpired(entry2)) {
30
+ this.#storage.delete(key2);
31
+ this.#accessOrder.delete(key2);
32
+ continue;
33
+ }
34
+ const entryKey = generateCacheKey(entry2.request, options);
35
+ if (entryKey === filterKey) {
36
+ this.#accessOrder.set(key2, ++this.#accessCounter);
37
+ return entry2.response.clone();
38
+ }
39
+ }
40
+ return void 0;
41
+ }
22
42
  const key = generateCacheKey(request, options);
23
43
  const entry = this.#storage.get(key);
24
44
  if (!entry) {
@@ -36,11 +56,12 @@ var MemoryCache = class extends Cache {
36
56
  * Store a request/response pair in the cache
37
57
  */
38
58
  async put(request, response) {
39
- const key = generateCacheKey(request);
40
- if (!this.#isCacheable(response)) {
41
- return;
59
+ const req = toRequest(request);
60
+ const key = generateCacheKey(req);
61
+ if (response.bodyUsed) {
62
+ throw new TypeError("Response body has already been used");
42
63
  }
43
- const clonedRequest = request.clone();
64
+ const clonedRequest = req.clone();
44
65
  const clonedResponse = response.clone();
45
66
  const entry = {
46
67
  request: clonedRequest,
@@ -55,6 +76,19 @@ var MemoryCache = class extends Cache {
55
76
  * Delete matching entries from the cache
56
77
  */
57
78
  async delete(request, options) {
79
+ if (options?.ignoreSearch) {
80
+ const filterKey = generateCacheKey(request, options);
81
+ let deleted2 = false;
82
+ for (const [key2, entry] of this.#storage) {
83
+ const entryKey = generateCacheKey(entry.request, options);
84
+ if (entryKey === filterKey) {
85
+ this.#storage.delete(key2);
86
+ this.#accessOrder.delete(key2);
87
+ deleted2 = true;
88
+ }
89
+ }
90
+ return deleted2;
91
+ }
58
92
  const key = generateCacheKey(request, options);
59
93
  const deleted = this.#storage.delete(key);
60
94
  if (deleted) {
@@ -118,21 +152,6 @@ var MemoryCache = class extends Cache {
118
152
  const maxAge = parseInt(maxAgeMatch[1], 10) * 1e3;
119
153
  return Date.now() - entry.timestamp > maxAge;
120
154
  }
121
- /**
122
- * Check if a response should be cached
123
- */
124
- #isCacheable(response) {
125
- if (!response.ok) {
126
- return false;
127
- }
128
- const cacheControl = response.headers.get("cache-control");
129
- if (cacheControl) {
130
- if (cacheControl.includes("no-cache") || cacheControl.includes("no-store")) {
131
- return false;
132
- }
133
- }
134
- return true;
135
- }
136
155
  /**
137
156
  * Enforce maximum entry limits using LRU eviction
138
157
  */
@@ -3,8 +3,6 @@ import { Cache, type CacheQueryOptions } from "./index.js";
3
3
  * Configuration options for PostMessageCache
4
4
  */
5
5
  export interface PostMessageCacheOptions {
6
- /** Maximum number of entries to store */
7
- maxEntries?: number;
8
6
  /** Timeout for cache operations in milliseconds (default: 30000) */
9
7
  timeout?: number;
10
8
  }
@@ -14,7 +12,7 @@ export interface PostMessageCacheOptions {
14
12
  */
15
13
  export declare class PostMessageCache extends Cache {
16
14
  #private;
17
- constructor(name: string, _options?: PostMessageCacheOptions);
15
+ constructor(name: string, options?: PostMessageCacheOptions);
18
16
  match(request: Request, options?: CacheQueryOptions): Promise<Response | undefined>;
19
17
  put(request: Request, response: Response): Promise<void>;
20
18
  delete(request: Request, options?: CacheQueryOptions): Promise<boolean>;
@@ -34,9 +34,11 @@ function handleCacheResponse(message) {
34
34
  var globalRequestID = 0;
35
35
  var PostMessageCache = class extends Cache {
36
36
  #name;
37
- constructor(name, _options = {}) {
37
+ #timeout;
38
+ constructor(name, options = {}) {
38
39
  super();
39
40
  this.#name = name;
41
+ this.#timeout = options.timeout ?? 3e4;
40
42
  setupMessageHandler();
41
43
  }
42
44
  async #sendRequest(type, data) {
@@ -58,7 +60,7 @@ var PostMessageCache = class extends Cache {
58
60
  pendingRequestsRegistry.delete(requestID);
59
61
  reject(new Error("Cache operation timeout"));
60
62
  }
61
- }, 3e4);
63
+ }, this.#timeout);
62
64
  });
63
65
  }
64
66
  async match(request, options) {