@cacheable/net 1.0.2 → 2.0.0

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/dist/index.js CHANGED
@@ -8,13 +8,17 @@ import {
8
8
  fetch as undiciFetch
9
9
  } from "undici";
10
10
  async function fetch(url, options) {
11
- if (!options.cache) {
12
- throw new Error("Fetch options must include a cache instance or options.");
13
- }
14
11
  const fetchOptions = {
15
12
  ...options,
16
13
  cache: "no-cache"
17
14
  };
15
+ if (!options.cache) {
16
+ const response2 = await undiciFetch(url, fetchOptions);
17
+ if (!response2.ok) {
18
+ throw new Error(`Fetch failed with status ${response2.status}`);
19
+ }
20
+ return response2;
21
+ }
18
22
  if (options.method === "POST" || options.method === "PATCH" || options.method === "DELETE" || options.method === "HEAD") {
19
23
  const response2 = await undiciFetch(url, fetchOptions);
20
24
  if (!response2.ok) {
@@ -22,10 +26,10 @@ async function fetch(url, options) {
22
26
  }
23
27
  return response2;
24
28
  }
25
- const useHttpCache = options.useHttpCache !== false;
29
+ const httpCachePolicy = options.httpCachePolicy !== false;
26
30
  const method = options.method || "GET";
27
31
  const cacheKey = `${method}:${url}`;
28
- if (!useHttpCache) {
32
+ if (!httpCachePolicy) {
29
33
  const cachedData = await options.cache.getOrSet(cacheKey, async () => {
30
34
  const response2 = await undiciFetch(url, fetchOptions);
31
35
  if (!response2.ok) {
@@ -301,67 +305,122 @@ async function head(url, options) {
301
305
  // src/index.ts
302
306
  var CacheableNet = class extends Hookified {
303
307
  _cache = new Cacheable();
304
- _useHttpCache = true;
308
+ _httpCachePolicy = true;
309
+ _stringify = JSON.stringify;
310
+ _parse = JSON.parse;
305
311
  constructor(options) {
306
312
  super(options);
307
313
  if (options?.cache) {
308
314
  this._cache = options.cache instanceof Cacheable ? options.cache : new Cacheable(options.cache);
309
315
  }
310
- if (options?.useHttpCache !== void 0) {
311
- this._useHttpCache = options.useHttpCache;
316
+ if (options?.httpCachePolicy !== void 0) {
317
+ this._httpCachePolicy = options.httpCachePolicy;
318
+ }
319
+ if (options?.stringify) {
320
+ this._stringify = options?.stringify;
312
321
  }
322
+ if (options?.parse) {
323
+ this._parse = options?.parse;
324
+ }
325
+ }
326
+ /**
327
+ * Get the stringify function used for converting objects to strings.
328
+ * @returns {StringifyType} The current stringify function
329
+ */
330
+ get stringify() {
331
+ return this._stringify;
332
+ }
333
+ /**
334
+ * Set the stringify function for converting objects to strings.
335
+ * @param {StringifyType} value - The stringify function to use
336
+ */
337
+ set stringify(value) {
338
+ this._stringify = value;
339
+ }
340
+ /**
341
+ * Get the parse function used for converting strings to objects.
342
+ * @returns {ParseType} The current parse function
343
+ */
344
+ get parse() {
345
+ return this._parse;
346
+ }
347
+ /**
348
+ * Set the parse function for converting strings to objects.
349
+ * @param {ParseType} value - The parse function to use
350
+ */
351
+ set parse(value) {
352
+ this._parse = value;
313
353
  }
354
+ /**
355
+ * Get the Cacheable instance used for caching fetch operations.
356
+ * @returns {Cacheable} The current Cacheable instance
357
+ */
314
358
  get cache() {
315
359
  return this._cache;
316
360
  }
361
+ /**
362
+ * Set the Cacheable instance for caching fetch operations.
363
+ * @param {Cacheable} value - The Cacheable instance to use for caching
364
+ */
317
365
  set cache(value) {
318
366
  this._cache = value;
319
367
  }
320
368
  /**
321
- * Get the current HTTP cache setting.
369
+ * Get the current HTTP cache policy setting.
322
370
  * @returns {boolean} Whether HTTP cache semantics are enabled
323
371
  */
324
- get useHttpCache() {
325
- return this._useHttpCache;
372
+ get httpCachePolicy() {
373
+ return this._httpCachePolicy;
326
374
  }
327
375
  /**
328
376
  * Set whether to use HTTP cache semantics.
329
377
  * @param {boolean} value - Enable or disable HTTP cache semantics
330
378
  */
331
- set useHttpCache(value) {
332
- this._useHttpCache = value;
379
+ set httpCachePolicy(value) {
380
+ this._httpCachePolicy = value;
333
381
  }
334
382
  /**
335
383
  * Fetch data from a URL with optional request options. Will use the cache that is already set in the instance.
336
384
  *
337
- * When `useHttpCache` is enabled (default), cache entries will have their TTL
385
+ * When `httpCachePolicy` is enabled (default), cache entries will have their TTL
338
386
  * set based on HTTP cache headers (e.g., Cache-Control: max-age). When disabled,
339
387
  * the default TTL from the Cacheable instance is used.
340
388
  *
341
389
  * @param {string} url The URL to fetch.
342
- * @param {FetchRequestInit} options Optional request options.
390
+ * @param {Omit<FetchOptions, "cache">} options Optional request options.
343
391
  * @returns {Promise<FetchResponse>} The response from the fetch.
344
392
  */
345
393
  async fetch(url, options) {
346
394
  const fetchOptions = {
347
395
  ...options,
348
396
  cache: this._cache,
349
- useHttpCache: this._useHttpCache
397
+ httpCachePolicy: this._httpCachePolicy
350
398
  };
351
399
  return fetch(url, fetchOptions);
352
400
  }
353
401
  /**
354
- * Perform a GET request to a URL with optional request options. Will use the cache that is already set in the instance.
402
+ * Perform a GET request to a URL with optional request options. By default caching is enabled on all requests. To
403
+ * disable set `options.caching` to false.
355
404
  * @param {string} url The URL to fetch.
356
- * @param {Omit<FetchRequestInit, 'method'>} options Optional request options (method will be set to GET).
405
+ * @param {NetFetchOptions} options Optional request options (method will be set to GET).
357
406
  * @returns {Promise<DataResponse<T>>} The typed data and response from the fetch.
358
407
  */
359
408
  async get(url, options) {
360
- const response = await this.fetch(url, { ...options, method: "GET" });
409
+ const fetchOptions = {
410
+ ...options,
411
+ cache: this._cache,
412
+ httpCachePolicy: this._httpCachePolicy,
413
+ method: "GET"
414
+ };
415
+ if (options?.caching !== void 0) {
416
+ delete fetchOptions.cache;
417
+ }
418
+ const response = await fetch(url, fetchOptions);
361
419
  const text = await response.text();
362
420
  let data;
421
+ const parseFn = options?.parse || this._parse;
363
422
  try {
364
- data = JSON.parse(text);
423
+ data = parseFn(text);
365
424
  } catch {
366
425
  data = text;
367
426
  }
@@ -376,10 +435,11 @@ var CacheableNet = class extends Hookified {
376
435
  };
377
436
  }
378
437
  /**
379
- * Perform a POST request to a URL with data and optional request options. Will use the cache that is already set in the instance.
438
+ * Perform a POST request to a URL with data and optional request options. By default caching is not enabled. To enable it
439
+ * set `options.caching` to true. Note, setting caching to tru means it will not post if the data is the same.
380
440
  * @param {string} url The URL to fetch.
381
441
  * @param {unknown} data The data to send in the request body.
382
- * @param {Omit<FetchRequestInit, 'method' | 'body'>} options Optional request options (method and body will be set).
442
+ * @param {Omit<NetFetchOptions, "method" | "body" >} options Optional request options (method and body will be set).
383
443
  * @returns {Promise<DataResponse<T>>} The typed data and response from the fetch.
384
444
  */
385
445
  async post(url, data, options) {
@@ -390,21 +450,28 @@ var CacheableNet = class extends Hookified {
390
450
  } else if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob) {
391
451
  body = data;
392
452
  } else {
393
- body = JSON.stringify(data);
453
+ const stringifyFn = options?.stringify || this._stringify;
454
+ body = stringifyFn(data);
394
455
  if (!headers["Content-Type"] && !headers["content-type"]) {
395
456
  headers["Content-Type"] = "application/json";
396
457
  }
397
458
  }
398
- const response = await this.fetch(url, {
459
+ const fetchOptions = {
399
460
  ...options,
400
461
  headers,
401
462
  body,
463
+ httpCachePolicy: this._httpCachePolicy,
402
464
  method: "POST"
403
- });
465
+ };
466
+ if (options?.caching === true) {
467
+ fetchOptions.cache = this._cache;
468
+ }
469
+ const response = await fetch(url, fetchOptions);
404
470
  const text = await response.text();
405
471
  let responseData;
472
+ const parseFn = options?.parse || this._parse;
406
473
  try {
407
- responseData = JSON.parse(text);
474
+ responseData = parseFn(text);
408
475
  } catch {
409
476
  responseData = text;
410
477
  }
@@ -419,20 +486,82 @@ var CacheableNet = class extends Hookified {
419
486
  };
420
487
  }
421
488
  /**
422
- * Perform a HEAD request to a URL with optional request options. Will use the cache that is already set in the instance.
489
+ * Perform a HEAD request to a URL with optional request options. By default caching is enabled on all requests. To
490
+ * disable set `options.caching` to false.
423
491
  * @param {string} url The URL to fetch.
424
- * @param {Omit<FetchRequestInit, 'method'>} options Optional request options (method will be set to HEAD).
492
+ * @param {NetFetchOptions} options Optional request options (method will be set to HEAD).
425
493
  * @returns {Promise<FetchResponse>} The response from the fetch (no body).
426
494
  */
427
495
  async head(url, options) {
428
- const response = await this.fetch(url, { ...options, method: "HEAD" });
496
+ const fetchOptions = {
497
+ ...options,
498
+ cache: this._cache,
499
+ httpCachePolicy: this._httpCachePolicy,
500
+ method: "HEAD"
501
+ };
502
+ if (options?.caching !== void 0 && !options.caching) {
503
+ delete fetchOptions.cache;
504
+ }
505
+ const response = await fetch(url, fetchOptions);
429
506
  return response;
430
507
  }
431
508
  /**
432
- * Perform a PATCH request to a URL with data and optional request options. Will use the cache that is already set in the instance.
509
+ * Perform a PUT request to a URL with data and optional request options. By default caching is not enabled. To enable it
510
+ * set `options.caching` to true. Note, setting caching to true means it will not put if the data is the same.
511
+ * @param {string} url The URL to fetch.
512
+ * @param {unknown} data The data to send in the request body.
513
+ * @param {Omit<NetFetchOptions, 'method' | 'body'>} options Optional request options (method and body will be set).
514
+ * @returns {Promise<DataResponse<T>>} The typed data and response from the fetch.
515
+ */
516
+ async put(url, data, options) {
517
+ let body;
518
+ const headers = { ...options?.headers };
519
+ if (typeof data === "string") {
520
+ body = data;
521
+ } else if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob) {
522
+ body = data;
523
+ } else {
524
+ const stringifyFn = options?.stringify || this._stringify;
525
+ body = stringifyFn(data);
526
+ if (!headers["Content-Type"] && !headers["content-type"]) {
527
+ headers["Content-Type"] = "application/json";
528
+ }
529
+ }
530
+ const fetchOptions = {
531
+ ...options,
532
+ headers,
533
+ body,
534
+ httpCachePolicy: this._httpCachePolicy,
535
+ method: "PUT"
536
+ };
537
+ if (options?.caching === true) {
538
+ fetchOptions.cache = this._cache;
539
+ }
540
+ const response = await fetch(url, fetchOptions);
541
+ const text = await response.text();
542
+ let responseData;
543
+ const parseFn = options?.parse || this._parse;
544
+ try {
545
+ responseData = parseFn(text);
546
+ } catch {
547
+ responseData = text;
548
+ }
549
+ const newResponse = new Response(text, {
550
+ status: response.status,
551
+ statusText: response.statusText,
552
+ headers: response.headers
553
+ });
554
+ return {
555
+ data: responseData,
556
+ response: newResponse
557
+ };
558
+ }
559
+ /**
560
+ * Perform a PATCH request to a URL with data and optional request options. By default caching is not enabled. To enable it
561
+ * set `options.caching` to true. Note, setting caching to true means it will not patch if the data is the same.
433
562
  * @param {string} url The URL to fetch.
434
563
  * @param {unknown} data The data to send in the request body.
435
- * @param {Omit<FetchRequestInit, 'method' | 'body'>} options Optional request options (method and body will be set).
564
+ * @param {Omit<NetFetchOptions, 'method' | 'body'>} options Optional request options (method and body will be set).
436
565
  * @returns {Promise<DataResponse<T>>} The typed data and response from the fetch.
437
566
  */
438
567
  async patch(url, data, options) {
@@ -443,21 +572,28 @@ var CacheableNet = class extends Hookified {
443
572
  } else if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob) {
444
573
  body = data;
445
574
  } else {
446
- body = JSON.stringify(data);
575
+ const stringifyFn = options?.stringify || this._stringify;
576
+ body = stringifyFn(data);
447
577
  if (!headers["Content-Type"] && !headers["content-type"]) {
448
578
  headers["Content-Type"] = "application/json";
449
579
  }
450
580
  }
451
- const response = await this.fetch(url, {
581
+ const fetchOptions = {
452
582
  ...options,
453
583
  headers,
454
584
  body,
585
+ httpCachePolicy: this._httpCachePolicy,
455
586
  method: "PATCH"
456
- });
587
+ };
588
+ if (options?.caching === true) {
589
+ fetchOptions.cache = this._cache;
590
+ }
591
+ const response = await fetch(url, fetchOptions);
457
592
  const text = await response.text();
458
593
  let responseData;
594
+ const parseFn = options?.parse || this._parse;
459
595
  try {
460
- responseData = JSON.parse(text);
596
+ responseData = parseFn(text);
461
597
  } catch {
462
598
  responseData = text;
463
599
  }
@@ -472,10 +608,11 @@ var CacheableNet = class extends Hookified {
472
608
  };
473
609
  }
474
610
  /**
475
- * Perform a DELETE request to a URL with optional data and request options. Will use the cache that is already set in the instance.
611
+ * Perform a DELETE request to a URL with optional data and request options. By default caching is not enabled. To enable it
612
+ * set `options.caching` to true. Note, setting caching to true means it will not delete if the data is the same.
476
613
  * @param {string} url The URL to fetch.
477
614
  * @param {unknown} data Optional data to send in the request body.
478
- * @param {Omit<FetchRequestInit, 'method' | 'body'>} options Optional request options (method and body will be set).
615
+ * @param {Omit<NetFetchOptions, 'method' | 'body'>} options Optional request options (method and body will be set).
479
616
  * @returns {Promise<DataResponse<T>>} The typed data and response from the fetch.
480
617
  */
481
618
  async delete(url, data, options) {
@@ -487,22 +624,29 @@ var CacheableNet = class extends Hookified {
487
624
  } else if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob) {
488
625
  body = data;
489
626
  } else {
490
- body = JSON.stringify(data);
627
+ const stringifyFn = options?.stringify || this._stringify;
628
+ body = stringifyFn(data);
491
629
  if (!headers["Content-Type"] && !headers["content-type"]) {
492
630
  headers["Content-Type"] = "application/json";
493
631
  }
494
632
  }
495
633
  }
496
- const response = await this.fetch(url, {
634
+ const fetchOptions = {
497
635
  ...options,
498
636
  headers,
499
637
  body,
638
+ httpCachePolicy: this._httpCachePolicy,
500
639
  method: "DELETE"
501
- });
640
+ };
641
+ if (options?.caching === true) {
642
+ fetchOptions.cache = this._cache;
643
+ }
644
+ const response = await fetch(url, fetchOptions);
502
645
  const text = await response.text();
503
646
  let responseData;
647
+ const parseFn = options?.parse || this._parse;
504
648
  try {
505
- responseData = JSON.parse(text);
649
+ responseData = parseFn(text);
506
650
  } catch {
507
651
  responseData = text;
508
652
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cacheable/net",
3
- "version": "1.0.2",
3
+ "version": "2.0.0",
4
4
  "description": "High Performance Network Caching for Node.js with fetch, request, http 1.1, and http 2 support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -21,10 +21,10 @@
21
21
  "license": "MIT",
22
22
  "private": false,
23
23
  "devDependencies": {
24
- "@biomejs/biome": "^2.2.2",
24
+ "@biomejs/biome": "^2.2.4",
25
25
  "@faker-js/faker": "^10.0.0",
26
26
  "@types/http-cache-semantics": "^4.0.4",
27
- "@types/node": "^24.3.0",
27
+ "@types/node": "^24.5.2",
28
28
  "@vitest/coverage-v8": "^3.2.4",
29
29
  "rimraf": "^6.0.1",
30
30
  "tsup": "^8.5.0",
@@ -32,10 +32,10 @@
32
32
  "vitest": "^3.2.4"
33
33
  },
34
34
  "dependencies": {
35
- "hookified": "^1.12.0",
35
+ "hookified": "^1.12.1",
36
36
  "http-cache-semantics": "^4.2.0",
37
- "undici": "^7.15.0",
38
- "cacheable": "^2.0.1"
37
+ "undici": "^7.16.0",
38
+ "cacheable": "^2.0.3"
39
39
  },
40
40
  "keywords": [
41
41
  "cacheable",