shared-http-cache 1.0.4 → 1.0.6

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/index.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ interface FetchRequest {
2
+ /** Request URL. */
3
+ url: string;
4
+ /** Resource integrity. */
5
+ integrity?: string;
6
+ /** Request init options [MDN reference](https://developer.mozilla.org/en-US/docs/Web/API/RequestInit) */
7
+ options?: RequestInit;
8
+ /** Callback function. */
9
+ callback?: (response: {
10
+ /** Response buffer. */
11
+ buffer: Buffer;
12
+ /** Response headers [MDN reference](https://developer.mozilla.org/en-US/docs/Web/API/Headers) */
13
+ headers: Headers;
14
+ /** Is response from cache? */
15
+ fromCache: boolean;
16
+ /** Request index. */
17
+ index: number;
18
+ }) => void;
19
+ }
20
+ declare class SharedHttpCache {
21
+ constructor(options?: {
22
+ /** Cache directory (default: ".cache") */
23
+ cacheDir?: string;
24
+ /** Await storage (default: false) */
25
+ awaitStorage?: boolean;
26
+ /** Optional properties */
27
+ [key: string]: any;
28
+ });
29
+ /** Cache directory path (default: ".cache") */
30
+ readonly cacheDir: string;
31
+ /** Await storage (default: false) */
32
+ readonly awaitStorage: boolean;
33
+ /** Fetch multiple requests (async).*/
34
+ fetch(requests: readonly FetchRequest[]): Promise<this>;
35
+ /** Storage management */
36
+ readonly store: typeof import('cacache');
37
+ }
38
+
39
+ export = SharedHttpCache;
package/index.js CHANGED
@@ -7,12 +7,6 @@ class SharedHttpCache {
7
7
  Object.assign(this, { cacheDir: '.cache', awaitStorage: false }, options);
8
8
  this.store = cacache;
9
9
  }
10
- /**
11
- * Fetch multiple resources with HTTP cache support.
12
- * @param {Array<{url:string,integrity?:string,options?:RequestInit,callback:(response:{buffer:Buffer,headers:Headers,fromCache:boolean,index:number})=>void}>} requests
13
- * @returns {Promise<this|{url:string,headers?:Headers,error:Error,index:number}[]>}
14
- * @see [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/RequestInit), [Headers](https://developer.mozilla.org/en-US/docs/Web/API/Headers) MDN references
15
- */
16
10
  async fetch(requests) {
17
11
  if (!Array.isArray(requests)) return Promise.reject([{ error: new TypeError('requests must be an array.') }]);
18
12
  const errors = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shared-http-cache",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Node.Js Utility for fetching multiple HTTP resources with browser-like cache management.",
5
5
  "keywords": [
6
6
  "http-cache",
package/readme.md CHANGED
@@ -17,7 +17,7 @@ This implementation models a shared HTTP cache that follows the semantics define
17
17
  The cache is shared (not private) and applies shared-cache rules.
18
18
 
19
19
  - Request `methods` other than `GET` are not stored.
20
- - Private responses (request `Authorization`, response `Cache-Control="private"` and `Set-Cookie` headers) are not stored.
20
+ - Private responses (request `Authorization`, response `Cache-Control="private"` and `Set-Cookie` headers) not stored.
21
21
  - Variant responses (response header `Vary` present) are not stored.
22
22
  - Partial content (response `Content-Range` header) is not stored.
23
23
  - Time calculations rely exclusively on locally recorded timestamps, not on server-provided `Date`.
@@ -315,6 +315,16 @@ The underlying cache store (`cacache`) is exposed directly.
315
315
  sharedHttpCache.store -> cacache
316
316
  ```
317
317
 
318
+ **Listing (example with promise)**
319
+
320
+ ```js
321
+ sharedHttpCache
322
+ .fetch(requests)
323
+ .then((sharedHttpCache) => sharedHttpCache.store.ls(sharedHttpCache.cacheDir))
324
+ .then(console.log)
325
+ .catch((errors) => console.error('Errors:', errors));
326
+ ```
327
+
318
328
  **Compacting (example with await)**
319
329
 
320
330
  ```ts
@@ -322,20 +332,38 @@ sharedHttpCache.store.verify(cacheDir) -> Promise<Object>
322
332
  ```
323
333
 
324
334
  ```js
325
- await sharedHttpCache.store.verify(sharedHttpCache.cacheDir);
335
+ // deadbeef collected, because of invalid checksum.
336
+ sharedHttpCache.store.verify(sharedHttpCache.cacheDir).then((stats) => {
337
+ console.log('cache is much nicer now! stats:', stats);
338
+ });
326
339
  ```
327
340
 
328
- **Listing (example with promise)**
341
+ **Basic cleanup strategy**
329
342
 
330
343
  ```js
331
- sharedHttpCache
332
- .fetch(requests)
333
- .then((sharedHttpCache) => sharedHttpCache.store.ls(sharedHttpCache.cacheDir))
334
- .then(console.log)
335
- .catch((errors) => console.error('Errors:', errors));
344
+ const SharedHttpCache = require('shared-http-cache');
345
+ // only-if-cached also means ... and is not stale!
346
+ (async () => {
347
+ const cache = new SharedHttpCache({ cacheDir: '.cache', awaitStorage: true });
348
+ const entries = await cache.store.ls(cache.cacheDir);
349
+ const requests = Object.keys(entries).map((url) => ({ url, options: { headers: { 'cache-control': 'only-if-cached' } } }));
350
+ await cache.fetch(requests).catch(async (errors) => {
351
+ for (const { url } of errors) {
352
+ const file = url && await cache.store.get.info(cache.cacheDir, url);
353
+ if (file) {
354
+ await cache.store.rm.entry(cache.cacheDir, url, { removeFully: true });
355
+ await cache.store.rm.content(cache.cacheDir, file.integrity);
356
+ }
357
+ }
358
+ });
359
+ })();
336
360
  ```
337
361
 
338
- Other available operations
362
+ **Note:**
363
+
364
+ - This is a fully `RFC 9111` compliant strategy that cleans up all the resources that can be determined as expired based on the stored response headers. For a more flexible approach, `max-stale=$acceptedStaleness` directive can be used in conjunction with `only-if-cached`. Cleanup strategies that rely on empirical calculations, such as `least recently used`, are `NOT RECOMMENDED`.
365
+
366
+ **Other available operations**
339
367
 
340
368
  - sharedHttpCache.store.put(...)
341
369
  - sharedHttpCache.store.get(...)
@@ -347,6 +375,8 @@ See full list of [cacache options](https://github.com/npm/cacache?tab=readme-ov-
347
375
 
348
376
  ## Bottom line
349
377
 
350
- - `max-stale` is intended to be used: many servers enforce `max-age=0`, but clients usually know how much staleness they can tolerate. Using `max-stale` (recommended up to 24 h) can significantly reduce network requests.
378
+ - `max-stale` is intended to be used: many servers enforce `max-age=0`, but clients know how much staleness they can tolerate. Using `max-stale` (recommended up to 24 h) can significantly reduce network requests.
351
379
  - providing `integrity` on requests enables fast loads by allowing cached content to be read directly from store.
380
+ - `SharedHttpCache` init with `awaitStorage: true` is important when `fetch` is continued with `store` actions.
381
+ - private or sensitive content is served, but not stored.
352
382
  - cache cleanup and eviction are deliberately left to the consumer; a well-chosen cleanup strategy is essential for maintaining good performance.