@cacheable/net 1.0.2 → 2.0.1
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/README.md +156 -13
- package/dist/index.cjs +1 -570
- package/dist/index.d.cts +141 -29
- package/dist/index.d.ts +141 -29
- package/dist/index.js +1 -530
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1,530 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { Cacheable } from "cacheable";
|
|
3
|
-
import { Hookified } from "hookified";
|
|
4
|
-
|
|
5
|
-
// src/fetch.ts
|
|
6
|
-
import CachePolicy from "http-cache-semantics";
|
|
7
|
-
import {
|
|
8
|
-
fetch as undiciFetch
|
|
9
|
-
} from "undici";
|
|
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
|
-
const fetchOptions = {
|
|
15
|
-
...options,
|
|
16
|
-
cache: "no-cache"
|
|
17
|
-
};
|
|
18
|
-
if (options.method === "POST" || options.method === "PATCH" || options.method === "DELETE" || options.method === "HEAD") {
|
|
19
|
-
const response2 = await undiciFetch(url, fetchOptions);
|
|
20
|
-
if (!response2.ok) {
|
|
21
|
-
throw new Error(`Fetch failed with status ${response2.status}`);
|
|
22
|
-
}
|
|
23
|
-
return response2;
|
|
24
|
-
}
|
|
25
|
-
const useHttpCache = options.useHttpCache !== false;
|
|
26
|
-
const method = options.method || "GET";
|
|
27
|
-
const cacheKey = `${method}:${url}`;
|
|
28
|
-
if (!useHttpCache) {
|
|
29
|
-
const cachedData = await options.cache.getOrSet(cacheKey, async () => {
|
|
30
|
-
const response2 = await undiciFetch(url, fetchOptions);
|
|
31
|
-
if (!response2.ok) {
|
|
32
|
-
throw new Error(`Fetch failed with status ${response2.status}`);
|
|
33
|
-
}
|
|
34
|
-
const body2 = await response2.text();
|
|
35
|
-
return {
|
|
36
|
-
body: body2,
|
|
37
|
-
status: response2.status,
|
|
38
|
-
statusText: response2.statusText,
|
|
39
|
-
headers: Object.fromEntries(response2.headers.entries())
|
|
40
|
-
};
|
|
41
|
-
});
|
|
42
|
-
if (!cachedData) {
|
|
43
|
-
throw new Error("Failed to get or set cache data");
|
|
44
|
-
}
|
|
45
|
-
return new Response(cachedData.body, {
|
|
46
|
-
status: cachedData.status,
|
|
47
|
-
statusText: cachedData.statusText,
|
|
48
|
-
headers: cachedData.headers
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
const policyKey = `${cacheKey}:policy`;
|
|
52
|
-
const [cachedResponse, cachedPolicyData] = await Promise.all([
|
|
53
|
-
options.cache.get(cacheKey),
|
|
54
|
-
options.cache.get(policyKey)
|
|
55
|
-
]);
|
|
56
|
-
let policy;
|
|
57
|
-
let cachedBody;
|
|
58
|
-
let cachedStatus;
|
|
59
|
-
let cachedStatusText;
|
|
60
|
-
let cachedHeaders;
|
|
61
|
-
if (cachedPolicyData && cachedResponse) {
|
|
62
|
-
policy = CachePolicy.fromObject(
|
|
63
|
-
cachedPolicyData
|
|
64
|
-
);
|
|
65
|
-
cachedBody = cachedResponse.body;
|
|
66
|
-
cachedStatus = cachedResponse.status;
|
|
67
|
-
cachedStatusText = cachedResponse.statusText;
|
|
68
|
-
cachedHeaders = cachedResponse.headers;
|
|
69
|
-
}
|
|
70
|
-
const requestHeaders = fetchOptions.headers || {};
|
|
71
|
-
const request = {
|
|
72
|
-
url,
|
|
73
|
-
method,
|
|
74
|
-
headers: requestHeaders
|
|
75
|
-
};
|
|
76
|
-
if (policy?.satisfiesWithoutRevalidation(request)) {
|
|
77
|
-
const headers = policy.responseHeaders();
|
|
78
|
-
return new Response(cachedBody, {
|
|
79
|
-
status: cachedStatus,
|
|
80
|
-
statusText: cachedStatusText,
|
|
81
|
-
headers
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
let revalidationHeaders = {};
|
|
85
|
-
if (policy?.revalidationHeaders(request)) {
|
|
86
|
-
revalidationHeaders = policy.revalidationHeaders(request);
|
|
87
|
-
}
|
|
88
|
-
const response = await undiciFetch(url, {
|
|
89
|
-
...fetchOptions,
|
|
90
|
-
headers: {
|
|
91
|
-
...fetchOptions.headers,
|
|
92
|
-
...revalidationHeaders
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
if (response.status === 304 && policy) {
|
|
96
|
-
const { policy: updatedPolicy, modified } = policy.revalidatedPolicy(
|
|
97
|
-
request,
|
|
98
|
-
{
|
|
99
|
-
status: response.status,
|
|
100
|
-
headers: Object.fromEntries(response.headers.entries())
|
|
101
|
-
}
|
|
102
|
-
);
|
|
103
|
-
if (!modified) {
|
|
104
|
-
const ttl = updatedPolicy.timeToLive();
|
|
105
|
-
await options.cache.set(policyKey, updatedPolicy.toObject(), ttl);
|
|
106
|
-
await options.cache.set(
|
|
107
|
-
cacheKey,
|
|
108
|
-
{
|
|
109
|
-
body: cachedBody,
|
|
110
|
-
status: cachedStatus,
|
|
111
|
-
statusText: cachedStatusText,
|
|
112
|
-
headers: cachedHeaders
|
|
113
|
-
},
|
|
114
|
-
ttl
|
|
115
|
-
);
|
|
116
|
-
const headers = updatedPolicy.responseHeaders();
|
|
117
|
-
return new Response(cachedBody, {
|
|
118
|
-
status: cachedStatus,
|
|
119
|
-
statusText: cachedStatusText,
|
|
120
|
-
headers
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
if (!response.ok && response.status !== 304) {
|
|
125
|
-
throw new Error(`Fetch failed with status ${response.status}`);
|
|
126
|
-
}
|
|
127
|
-
const body = await response.text();
|
|
128
|
-
const responseForPolicy = {
|
|
129
|
-
status: response.status,
|
|
130
|
-
statusText: response.statusText,
|
|
131
|
-
headers: Object.fromEntries(response.headers.entries())
|
|
132
|
-
};
|
|
133
|
-
const newPolicy = new CachePolicy(request, responseForPolicy);
|
|
134
|
-
if (newPolicy.storable()) {
|
|
135
|
-
const ttl = newPolicy.timeToLive();
|
|
136
|
-
await Promise.all([
|
|
137
|
-
options.cache.set(
|
|
138
|
-
cacheKey,
|
|
139
|
-
{
|
|
140
|
-
body,
|
|
141
|
-
status: response.status,
|
|
142
|
-
statusText: response.statusText,
|
|
143
|
-
headers: responseForPolicy.headers
|
|
144
|
-
},
|
|
145
|
-
ttl
|
|
146
|
-
),
|
|
147
|
-
options.cache.set(policyKey, newPolicy.toObject(), ttl)
|
|
148
|
-
]);
|
|
149
|
-
}
|
|
150
|
-
return new Response(body, {
|
|
151
|
-
status: response.status,
|
|
152
|
-
statusText: response.statusText,
|
|
153
|
-
headers: response.headers
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
async function get(url, options) {
|
|
157
|
-
const response = await fetch(url, { ...options, method: "GET" });
|
|
158
|
-
const text = await response.text();
|
|
159
|
-
let data;
|
|
160
|
-
try {
|
|
161
|
-
data = JSON.parse(text);
|
|
162
|
-
} catch {
|
|
163
|
-
data = text;
|
|
164
|
-
}
|
|
165
|
-
const newResponse = new Response(text, {
|
|
166
|
-
status: response.status,
|
|
167
|
-
statusText: response.statusText,
|
|
168
|
-
headers: response.headers
|
|
169
|
-
});
|
|
170
|
-
return {
|
|
171
|
-
data,
|
|
172
|
-
response: newResponse
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
async function post(url, data, options) {
|
|
176
|
-
let body;
|
|
177
|
-
const headers = { ...options.headers };
|
|
178
|
-
if (typeof data === "string") {
|
|
179
|
-
body = data;
|
|
180
|
-
} else if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob) {
|
|
181
|
-
body = data;
|
|
182
|
-
} else {
|
|
183
|
-
body = JSON.stringify(data);
|
|
184
|
-
if (!headers["Content-Type"] && !headers["content-type"]) {
|
|
185
|
-
headers["Content-Type"] = "application/json";
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
const response = await fetch(url, {
|
|
189
|
-
...options,
|
|
190
|
-
headers,
|
|
191
|
-
body,
|
|
192
|
-
method: "POST"
|
|
193
|
-
});
|
|
194
|
-
const text = await response.text();
|
|
195
|
-
let responseData;
|
|
196
|
-
try {
|
|
197
|
-
responseData = JSON.parse(text);
|
|
198
|
-
} catch {
|
|
199
|
-
responseData = text;
|
|
200
|
-
}
|
|
201
|
-
const newResponse = new Response(text, {
|
|
202
|
-
status: response.status,
|
|
203
|
-
statusText: response.statusText,
|
|
204
|
-
headers: response.headers
|
|
205
|
-
});
|
|
206
|
-
return {
|
|
207
|
-
data: responseData,
|
|
208
|
-
response: newResponse
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
async function patch(url, data, options) {
|
|
212
|
-
let body;
|
|
213
|
-
const headers = { ...options.headers };
|
|
214
|
-
if (typeof data === "string") {
|
|
215
|
-
body = data;
|
|
216
|
-
} else if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob) {
|
|
217
|
-
body = data;
|
|
218
|
-
} else {
|
|
219
|
-
body = JSON.stringify(data);
|
|
220
|
-
if (!headers["Content-Type"] && !headers["content-type"]) {
|
|
221
|
-
headers["Content-Type"] = "application/json";
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
const response = await fetch(url, {
|
|
225
|
-
...options,
|
|
226
|
-
headers,
|
|
227
|
-
body,
|
|
228
|
-
method: "PATCH"
|
|
229
|
-
});
|
|
230
|
-
const text = await response.text();
|
|
231
|
-
let responseData;
|
|
232
|
-
try {
|
|
233
|
-
responseData = JSON.parse(text);
|
|
234
|
-
} catch {
|
|
235
|
-
responseData = text;
|
|
236
|
-
}
|
|
237
|
-
const newResponse = new Response(text, {
|
|
238
|
-
status: response.status,
|
|
239
|
-
statusText: response.statusText,
|
|
240
|
-
headers: response.headers
|
|
241
|
-
});
|
|
242
|
-
return {
|
|
243
|
-
data: responseData,
|
|
244
|
-
response: newResponse
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
async function del(url, data, options) {
|
|
248
|
-
let actualData;
|
|
249
|
-
let actualOptions;
|
|
250
|
-
if (data !== void 0 && typeof data === "object" && data !== null && "cache" in data) {
|
|
251
|
-
actualData = void 0;
|
|
252
|
-
actualOptions = data;
|
|
253
|
-
} else if (options) {
|
|
254
|
-
actualData = data;
|
|
255
|
-
actualOptions = options;
|
|
256
|
-
} else {
|
|
257
|
-
throw new Error("Fetch options must include a cache instance or options.");
|
|
258
|
-
}
|
|
259
|
-
let body;
|
|
260
|
-
const headers = { ...actualOptions.headers };
|
|
261
|
-
if (actualData !== void 0) {
|
|
262
|
-
if (typeof actualData === "string") {
|
|
263
|
-
body = actualData;
|
|
264
|
-
} else if (actualData instanceof FormData || actualData instanceof URLSearchParams || actualData instanceof Blob) {
|
|
265
|
-
body = actualData;
|
|
266
|
-
} else {
|
|
267
|
-
body = JSON.stringify(actualData);
|
|
268
|
-
if (!headers["Content-Type"] && !headers["content-type"]) {
|
|
269
|
-
headers["Content-Type"] = "application/json";
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
const response = await fetch(url, {
|
|
274
|
-
...actualOptions,
|
|
275
|
-
headers,
|
|
276
|
-
body,
|
|
277
|
-
method: "DELETE"
|
|
278
|
-
});
|
|
279
|
-
const text = await response.text();
|
|
280
|
-
let responseData;
|
|
281
|
-
try {
|
|
282
|
-
responseData = JSON.parse(text);
|
|
283
|
-
} catch {
|
|
284
|
-
responseData = text;
|
|
285
|
-
}
|
|
286
|
-
const newResponse = new Response(text, {
|
|
287
|
-
status: response.status,
|
|
288
|
-
statusText: response.statusText,
|
|
289
|
-
headers: response.headers
|
|
290
|
-
});
|
|
291
|
-
return {
|
|
292
|
-
data: responseData,
|
|
293
|
-
response: newResponse
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
async function head(url, options) {
|
|
297
|
-
const response = await fetch(url, { ...options, method: "HEAD" });
|
|
298
|
-
return response;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// src/index.ts
|
|
302
|
-
var CacheableNet = class extends Hookified {
|
|
303
|
-
_cache = new Cacheable();
|
|
304
|
-
_useHttpCache = true;
|
|
305
|
-
constructor(options) {
|
|
306
|
-
super(options);
|
|
307
|
-
if (options?.cache) {
|
|
308
|
-
this._cache = options.cache instanceof Cacheable ? options.cache : new Cacheable(options.cache);
|
|
309
|
-
}
|
|
310
|
-
if (options?.useHttpCache !== void 0) {
|
|
311
|
-
this._useHttpCache = options.useHttpCache;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
get cache() {
|
|
315
|
-
return this._cache;
|
|
316
|
-
}
|
|
317
|
-
set cache(value) {
|
|
318
|
-
this._cache = value;
|
|
319
|
-
}
|
|
320
|
-
/**
|
|
321
|
-
* Get the current HTTP cache setting.
|
|
322
|
-
* @returns {boolean} Whether HTTP cache semantics are enabled
|
|
323
|
-
*/
|
|
324
|
-
get useHttpCache() {
|
|
325
|
-
return this._useHttpCache;
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Set whether to use HTTP cache semantics.
|
|
329
|
-
* @param {boolean} value - Enable or disable HTTP cache semantics
|
|
330
|
-
*/
|
|
331
|
-
set useHttpCache(value) {
|
|
332
|
-
this._useHttpCache = value;
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* Fetch data from a URL with optional request options. Will use the cache that is already set in the instance.
|
|
336
|
-
*
|
|
337
|
-
* When `useHttpCache` is enabled (default), cache entries will have their TTL
|
|
338
|
-
* set based on HTTP cache headers (e.g., Cache-Control: max-age). When disabled,
|
|
339
|
-
* the default TTL from the Cacheable instance is used.
|
|
340
|
-
*
|
|
341
|
-
* @param {string} url The URL to fetch.
|
|
342
|
-
* @param {FetchRequestInit} options Optional request options.
|
|
343
|
-
* @returns {Promise<FetchResponse>} The response from the fetch.
|
|
344
|
-
*/
|
|
345
|
-
async fetch(url, options) {
|
|
346
|
-
const fetchOptions = {
|
|
347
|
-
...options,
|
|
348
|
-
cache: this._cache,
|
|
349
|
-
useHttpCache: this._useHttpCache
|
|
350
|
-
};
|
|
351
|
-
return fetch(url, fetchOptions);
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Perform a GET request to a URL with optional request options. Will use the cache that is already set in the instance.
|
|
355
|
-
* @param {string} url The URL to fetch.
|
|
356
|
-
* @param {Omit<FetchRequestInit, 'method'>} options Optional request options (method will be set to GET).
|
|
357
|
-
* @returns {Promise<DataResponse<T>>} The typed data and response from the fetch.
|
|
358
|
-
*/
|
|
359
|
-
async get(url, options) {
|
|
360
|
-
const response = await this.fetch(url, { ...options, method: "GET" });
|
|
361
|
-
const text = await response.text();
|
|
362
|
-
let data;
|
|
363
|
-
try {
|
|
364
|
-
data = JSON.parse(text);
|
|
365
|
-
} catch {
|
|
366
|
-
data = text;
|
|
367
|
-
}
|
|
368
|
-
const newResponse = new Response(text, {
|
|
369
|
-
status: response.status,
|
|
370
|
-
statusText: response.statusText,
|
|
371
|
-
headers: response.headers
|
|
372
|
-
});
|
|
373
|
-
return {
|
|
374
|
-
data,
|
|
375
|
-
response: newResponse
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
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.
|
|
380
|
-
* @param {string} url The URL to fetch.
|
|
381
|
-
* @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).
|
|
383
|
-
* @returns {Promise<DataResponse<T>>} The typed data and response from the fetch.
|
|
384
|
-
*/
|
|
385
|
-
async post(url, data, options) {
|
|
386
|
-
let body;
|
|
387
|
-
const headers = { ...options?.headers };
|
|
388
|
-
if (typeof data === "string") {
|
|
389
|
-
body = data;
|
|
390
|
-
} else if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob) {
|
|
391
|
-
body = data;
|
|
392
|
-
} else {
|
|
393
|
-
body = JSON.stringify(data);
|
|
394
|
-
if (!headers["Content-Type"] && !headers["content-type"]) {
|
|
395
|
-
headers["Content-Type"] = "application/json";
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
const response = await this.fetch(url, {
|
|
399
|
-
...options,
|
|
400
|
-
headers,
|
|
401
|
-
body,
|
|
402
|
-
method: "POST"
|
|
403
|
-
});
|
|
404
|
-
const text = await response.text();
|
|
405
|
-
let responseData;
|
|
406
|
-
try {
|
|
407
|
-
responseData = JSON.parse(text);
|
|
408
|
-
} catch {
|
|
409
|
-
responseData = text;
|
|
410
|
-
}
|
|
411
|
-
const newResponse = new Response(text, {
|
|
412
|
-
status: response.status,
|
|
413
|
-
statusText: response.statusText,
|
|
414
|
-
headers: response.headers
|
|
415
|
-
});
|
|
416
|
-
return {
|
|
417
|
-
data: responseData,
|
|
418
|
-
response: newResponse
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Perform a HEAD request to a URL with optional request options. Will use the cache that is already set in the instance.
|
|
423
|
-
* @param {string} url The URL to fetch.
|
|
424
|
-
* @param {Omit<FetchRequestInit, 'method'>} options Optional request options (method will be set to HEAD).
|
|
425
|
-
* @returns {Promise<FetchResponse>} The response from the fetch (no body).
|
|
426
|
-
*/
|
|
427
|
-
async head(url, options) {
|
|
428
|
-
const response = await this.fetch(url, { ...options, method: "HEAD" });
|
|
429
|
-
return response;
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
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.
|
|
433
|
-
* @param {string} url The URL to fetch.
|
|
434
|
-
* @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).
|
|
436
|
-
* @returns {Promise<DataResponse<T>>} The typed data and response from the fetch.
|
|
437
|
-
*/
|
|
438
|
-
async patch(url, data, options) {
|
|
439
|
-
let body;
|
|
440
|
-
const headers = { ...options?.headers };
|
|
441
|
-
if (typeof data === "string") {
|
|
442
|
-
body = data;
|
|
443
|
-
} else if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob) {
|
|
444
|
-
body = data;
|
|
445
|
-
} else {
|
|
446
|
-
body = JSON.stringify(data);
|
|
447
|
-
if (!headers["Content-Type"] && !headers["content-type"]) {
|
|
448
|
-
headers["Content-Type"] = "application/json";
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
const response = await this.fetch(url, {
|
|
452
|
-
...options,
|
|
453
|
-
headers,
|
|
454
|
-
body,
|
|
455
|
-
method: "PATCH"
|
|
456
|
-
});
|
|
457
|
-
const text = await response.text();
|
|
458
|
-
let responseData;
|
|
459
|
-
try {
|
|
460
|
-
responseData = JSON.parse(text);
|
|
461
|
-
} catch {
|
|
462
|
-
responseData = text;
|
|
463
|
-
}
|
|
464
|
-
const newResponse = new Response(text, {
|
|
465
|
-
status: response.status,
|
|
466
|
-
statusText: response.statusText,
|
|
467
|
-
headers: response.headers
|
|
468
|
-
});
|
|
469
|
-
return {
|
|
470
|
-
data: responseData,
|
|
471
|
-
response: newResponse
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
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.
|
|
476
|
-
* @param {string} url The URL to fetch.
|
|
477
|
-
* @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).
|
|
479
|
-
* @returns {Promise<DataResponse<T>>} The typed data and response from the fetch.
|
|
480
|
-
*/
|
|
481
|
-
async delete(url, data, options) {
|
|
482
|
-
let body;
|
|
483
|
-
const headers = { ...options?.headers };
|
|
484
|
-
if (data !== void 0) {
|
|
485
|
-
if (typeof data === "string") {
|
|
486
|
-
body = data;
|
|
487
|
-
} else if (data instanceof FormData || data instanceof URLSearchParams || data instanceof Blob) {
|
|
488
|
-
body = data;
|
|
489
|
-
} else {
|
|
490
|
-
body = JSON.stringify(data);
|
|
491
|
-
if (!headers["Content-Type"] && !headers["content-type"]) {
|
|
492
|
-
headers["Content-Type"] = "application/json";
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
const response = await this.fetch(url, {
|
|
497
|
-
...options,
|
|
498
|
-
headers,
|
|
499
|
-
body,
|
|
500
|
-
method: "DELETE"
|
|
501
|
-
});
|
|
502
|
-
const text = await response.text();
|
|
503
|
-
let responseData;
|
|
504
|
-
try {
|
|
505
|
-
responseData = JSON.parse(text);
|
|
506
|
-
} catch {
|
|
507
|
-
responseData = text;
|
|
508
|
-
}
|
|
509
|
-
const newResponse = new Response(text, {
|
|
510
|
-
status: response.status,
|
|
511
|
-
statusText: response.statusText,
|
|
512
|
-
headers: response.headers
|
|
513
|
-
});
|
|
514
|
-
return {
|
|
515
|
-
data: responseData,
|
|
516
|
-
response: newResponse
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
};
|
|
520
|
-
var Net = CacheableNet;
|
|
521
|
-
export {
|
|
522
|
-
CacheableNet,
|
|
523
|
-
Net,
|
|
524
|
-
del,
|
|
525
|
-
fetch,
|
|
526
|
-
get,
|
|
527
|
-
head,
|
|
528
|
-
patch,
|
|
529
|
-
post
|
|
530
|
-
};
|
|
1
|
+
import{Cacheable as b}from"cacheable";import{Hookified as U}from"hookified";import _ from"http-cache-semantics";import{fetch as m}from"undici";async function u(p,e){let t={...e,cache:"no-cache"};if(!e.cache){let h=await m(p,t);if(!h.ok)throw new Error(`Fetch failed with status ${h.status}`);return h}if(e.method==="POST"||e.method==="PATCH"||e.method==="DELETE"||e.method==="HEAD"){let h=await m(p,t);if(!h.ok)throw new Error(`Fetch failed with status ${h.status}`);return h}let s=e.httpCachePolicy!==!1,n=e.method||"GET",a=`${n}:${p}`;if(!s){let h=await e.cache.getOrSet(a,async()=>{let T=await m(p,t);if(!T.ok)throw new Error(`Fetch failed with status ${T.status}`);return{body:await T.text(),status:T.status,statusText:T.statusText,headers:Object.fromEntries(T.headers.entries())}});if(!h)throw new Error("Failed to get or set cache data");return new Response(h.body,{status:h.status,statusText:h.statusText,headers:h.headers})}let c=`${a}:policy`,[i,o]=await Promise.all([e.cache.get(a),e.cache.get(c)]),r,y,f,l,x;o&&i&&(r=_.fromObject(o),y=i.body,f=i.status,l=i.statusText,x=i.headers);let D=t.headers||{},g={url:p,method:n,headers:D};if(r?.satisfiesWithoutRevalidation(g)){let h=r.responseHeaders();return new Response(y,{status:f,statusText:l,headers:h})}let F={};r?.revalidationHeaders(g)&&(F=r.revalidationHeaders(g));let d=await m(p,{...t,headers:{...t.headers,...F}});if(d.status===304&&r){let{policy:h,modified:T}=r.revalidatedPolicy(g,{status:d.status,headers:Object.fromEntries(d.headers.entries())});if(!T){let R=h.timeToLive();await e.cache.set(c,h.toObject(),R),await e.cache.set(a,{body:y,status:f,statusText:l,headers:x},R);let I=h.responseHeaders();return new Response(y,{status:f,statusText:l,headers:I})}}if(!d.ok&&d.status!==304)throw new Error(`Fetch failed with status ${d.status}`);let P=await d.text(),C={status:d.status,statusText:d.statusText,headers:Object.fromEntries(d.headers.entries())},w=new _(g,C);if(w.storable()){let h=w.timeToLive();await Promise.all([e.cache.set(a,{body:P,status:d.status,statusText:d.statusText,headers:C.headers},h),e.cache.set(c,w.toObject(),h)])}return new Response(P,{status:d.status,statusText:d.statusText,headers:d.headers})}async function k(p,e){let t=await u(p,{...e,method:"GET"}),s=await t.text(),n;try{n=JSON.parse(s)}catch{n=s}let a=new Response(s,{status:t.status,statusText:t.statusText,headers:t.headers});return{data:n,response:a}}async function H(p,e,t){let s,n={...t.headers};typeof e=="string"||e instanceof FormData||e instanceof URLSearchParams||e instanceof Blob?s=e:(s=JSON.stringify(e),!n["Content-Type"]&&!n["content-type"]&&(n["Content-Type"]="application/json"));let a=await u(p,{...t,headers:n,body:s,method:"POST"}),c=await a.text(),i;try{i=JSON.parse(c)}catch{i=c}let o=new Response(c,{status:a.status,statusText:a.statusText,headers:a.headers});return{data:i,response:o}}async function S(p,e,t){let s,n={...t.headers};typeof e=="string"||e instanceof FormData||e instanceof URLSearchParams||e instanceof Blob?s=e:(s=JSON.stringify(e),!n["Content-Type"]&&!n["content-type"]&&(n["Content-Type"]="application/json"));let a=await u(p,{...t,headers:n,body:s,method:"PATCH"}),c=await a.text(),i;try{i=JSON.parse(c)}catch{i=c}let o=new Response(c,{status:a.status,statusText:a.statusText,headers:a.headers});return{data:i,response:o}}async function E(p,e,t){let s,n;if(e!==void 0&&typeof e=="object"&&e!==null&&"cache"in e)s=void 0,n=e;else if(t)s=e,n=t;else throw new Error("Fetch options must include a cache instance or options.");let a,c={...n.headers};s!==void 0&&(typeof s=="string"||s instanceof FormData||s instanceof URLSearchParams||s instanceof Blob?a=s:(a=JSON.stringify(s),!c["Content-Type"]&&!c["content-type"]&&(c["Content-Type"]="application/json")));let i=await u(p,{...n,headers:c,body:a,method:"DELETE"}),o=await i.text(),r;try{r=JSON.parse(o)}catch{r=o}let y=new Response(o,{status:i.status,statusText:i.statusText,headers:i.headers});return{data:r,response:y}}async function B(p,e){return await u(p,{...e,method:"HEAD"})}var O=class extends U{_cache=new b;_httpCachePolicy=!0;_stringify=JSON.stringify;_parse=JSON.parse;constructor(e){super(e),e?.cache&&(this._cache=e.cache instanceof b?e.cache:new b(e.cache)),e?.httpCachePolicy!==void 0&&(this._httpCachePolicy=e.httpCachePolicy),e?.stringify&&(this._stringify=e?.stringify),e?.parse&&(this._parse=e?.parse)}get stringify(){return this._stringify}set stringify(e){this._stringify=e}get parse(){return this._parse}set parse(e){this._parse=e}get cache(){return this._cache}set cache(e){this._cache=e}get httpCachePolicy(){return this._httpCachePolicy}set httpCachePolicy(e){this._httpCachePolicy=e}async fetch(e,t){let s={...t,cache:this._cache,httpCachePolicy:this._httpCachePolicy};return u(e,s)}async get(e,t){let s={...t,cache:this._cache,httpCachePolicy:this._httpCachePolicy,method:"GET"};t?.caching!==void 0&&delete s.cache;let n=await u(e,s),a=await n.text(),c,i=t?.parse||this._parse;try{c=i(a)}catch{c=a}let o=new Response(a,{status:n.status,statusText:n.statusText,headers:n.headers});return{data:c,response:o}}async post(e,t,s){let n,a={...s?.headers};typeof t=="string"||t instanceof FormData||t instanceof URLSearchParams||t instanceof Blob?n=t:(n=(s?.stringify||this._stringify)(t),!a["Content-Type"]&&!a["content-type"]&&(a["Content-Type"]="application/json"));let c={...s,headers:a,body:n,httpCachePolicy:this._httpCachePolicy,method:"POST"};s?.caching===!0&&(c.cache=this._cache);let i=await u(e,c),o=await i.text(),r,y=s?.parse||this._parse;try{r=y(o)}catch{r=o}let f=new Response(o,{status:i.status,statusText:i.statusText,headers:i.headers});return{data:r,response:f}}async head(e,t){let s={...t,cache:this._cache,httpCachePolicy:this._httpCachePolicy,method:"HEAD"};return t?.caching!==void 0&&!t.caching&&delete s.cache,await u(e,s)}async put(e,t,s){let n,a={...s?.headers};typeof t=="string"||t instanceof FormData||t instanceof URLSearchParams||t instanceof Blob?n=t:(n=(s?.stringify||this._stringify)(t),!a["Content-Type"]&&!a["content-type"]&&(a["Content-Type"]="application/json"));let c={...s,headers:a,body:n,httpCachePolicy:this._httpCachePolicy,method:"PUT"};s?.caching===!0&&(c.cache=this._cache);let i=await u(e,c),o=await i.text(),r,y=s?.parse||this._parse;try{r=y(o)}catch{r=o}let f=new Response(o,{status:i.status,statusText:i.statusText,headers:i.headers});return{data:r,response:f}}async patch(e,t,s){let n,a={...s?.headers};typeof t=="string"||t instanceof FormData||t instanceof URLSearchParams||t instanceof Blob?n=t:(n=(s?.stringify||this._stringify)(t),!a["Content-Type"]&&!a["content-type"]&&(a["Content-Type"]="application/json"));let c={...s,headers:a,body:n,httpCachePolicy:this._httpCachePolicy,method:"PATCH"};s?.caching===!0&&(c.cache=this._cache);let i=await u(e,c),o=await i.text(),r,y=s?.parse||this._parse;try{r=y(o)}catch{r=o}let f=new Response(o,{status:i.status,statusText:i.statusText,headers:i.headers});return{data:r,response:f}}async delete(e,t,s){let n,a={...s?.headers};t!==void 0&&(typeof t=="string"||t instanceof FormData||t instanceof URLSearchParams||t instanceof Blob?n=t:(n=(s?.stringify||this._stringify)(t),!a["Content-Type"]&&!a["content-type"]&&(a["Content-Type"]="application/json")));let c={...s,headers:a,body:n,httpCachePolicy:this._httpCachePolicy,method:"DELETE"};s?.caching===!0&&(c.cache=this._cache);let i=await u(e,c),o=await i.text(),r,y=s?.parse||this._parse;try{r=y(o)}catch{r=o}let f=new Response(o,{status:i.status,statusText:i.statusText,headers:i.headers});return{data:r,response:f}}},$=O;export{O as CacheableNet,$ as Net,E as del,u as fetch,k as get,B as head,S as patch,H as post};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cacheable/net",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
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.
|
|
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.
|
|
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.
|
|
35
|
+
"hookified": "^1.12.1",
|
|
36
36
|
"http-cache-semantics": "^4.2.0",
|
|
37
|
-
"undici": "^7.
|
|
38
|
-
"cacheable": "^2.0
|
|
37
|
+
"undici": "^7.16.0",
|
|
38
|
+
"cacheable": "^2.1.0"
|
|
39
39
|
},
|
|
40
40
|
"keywords": [
|
|
41
41
|
"cacheable",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"LICENSE"
|
|
70
70
|
],
|
|
71
71
|
"scripts": {
|
|
72
|
-
"build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean",
|
|
72
|
+
"build": "rimraf ./dist && tsup src/index.ts --format cjs,esm --dts --clean --minify",
|
|
73
73
|
"prepublish": "pnpm build",
|
|
74
74
|
"lint": "biome check --write --error-on-warnings",
|
|
75
75
|
"test": "pnpm lint && vitest run --coverage",
|