@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 +2 -2
- package/src/index.d.ts +10 -6
- package/src/index.js +14 -3
- package/src/memory.d.ts +4 -4
- package/src/memory.js +39 -20
- package/src/postmessage.d.ts +1 -3
- package/src/postmessage.js +4 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@b9g/cache",
|
|
3
|
-
"version": "0.1.
|
|
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.
|
|
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:
|
|
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:
|
|
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:
|
|
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?:
|
|
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:
|
|
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
|
|
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" :
|
|
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:
|
|
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:
|
|
23
|
+
put(request: RequestInfo | URL, response: Response): Promise<void>;
|
|
24
24
|
/**
|
|
25
25
|
* Delete matching entries from the cache
|
|
26
26
|
*/
|
|
27
|
-
delete(request:
|
|
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?:
|
|
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 {
|
|
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
|
|
40
|
-
|
|
41
|
-
|
|
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 =
|
|
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
|
*/
|
package/src/postmessage.d.ts
CHANGED
|
@@ -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,
|
|
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>;
|
package/src/postmessage.js
CHANGED
|
@@ -34,9 +34,11 @@ function handleCacheResponse(message) {
|
|
|
34
34
|
var globalRequestID = 0;
|
|
35
35
|
var PostMessageCache = class extends Cache {
|
|
36
36
|
#name;
|
|
37
|
-
|
|
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
|
-
},
|
|
63
|
+
}, this.#timeout);
|
|
62
64
|
});
|
|
63
65
|
}
|
|
64
66
|
async match(request, options) {
|