@netlify/cache 1.7.0 → 1.8.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.
@@ -78,17 +78,15 @@ var allowedProtocols = /* @__PURE__ */ new Set(["http:", "https:"]);
78
78
  var discardedHeaders = /* @__PURE__ */ new Set(["cookie", "content-encoding", "content-length"]);
79
79
  var getInternalHeaders = Symbol("getInternalHeaders");
80
80
  var serializeResourceHeaders = Symbol("serializeResourceHeaders");
81
- var _base64Encode, _getContext, _logger, _name, _userAgent;
81
+ var _base64Encode, _getContext, _name, _userAgent;
82
82
  var NetlifyCache = class {
83
- constructor({ base64Encode, getContext, logger, name, userAgent }) {
83
+ constructor({ base64Encode, getContext, name, userAgent }) {
84
84
  __privateAdd(this, _base64Encode, void 0);
85
85
  __privateAdd(this, _getContext, void 0);
86
- __privateAdd(this, _logger, void 0);
87
86
  __privateAdd(this, _name, void 0);
88
87
  __privateAdd(this, _userAgent, void 0);
89
88
  __privateSet(this, _base64Encode, base64Encode);
90
89
  __privateSet(this, _getContext, getContext);
91
- __privateSet(this, _logger, logger);
92
90
  __privateSet(this, _name, name);
93
91
  __privateSet(this, _userAgent, userAgent);
94
92
  }
@@ -171,7 +169,6 @@ var NetlifyCache = class {
171
169
  return res ? [res] : [];
172
170
  }
173
171
  async put(request, response) {
174
- var _a;
175
172
  if (!response.ok) {
176
173
  throw new TypeError(`Cannot cache response with status ${response.status}.`);
177
174
  }
@@ -203,13 +200,12 @@ var NetlifyCache = class {
203
200
  if (!cacheResponse.ok) {
204
201
  const errorDetail = cacheResponse.headers.get(ErrorDetail) ?? "";
205
202
  const errorMessage = ERROR_CODES[errorDetail] || GENERIC_ERROR;
206
- (_a = __privateGet(this, _logger)) == null ? void 0 : _a.call(this, `Failed to write to the cache: ${errorMessage}`);
203
+ context.logger?.(`Failed to write to the cache: ${errorMessage}`);
207
204
  }
208
205
  }
209
206
  };
210
207
  _base64Encode = new WeakMap();
211
208
  _getContext = new WeakMap();
212
- _logger = new WeakMap();
213
209
  _name = new WeakMap();
214
210
  _userAgent = new WeakMap();
215
211
  var extractAndValidateURL = (input) => {
@@ -1,5 +1,5 @@
1
- import { E as EnvironmentOptions } from '../cache-089d07a0.js';
2
- export { B as Base64Encoder, N as NetlifyCache, O as Operation, R as RequestContextFactory } from '../cache-089d07a0.js';
1
+ import { E as EnvironmentOptions } from '../cache-7af07baa.js';
2
+ export { B as Base64Encoder, N as NetlifyCache, O as Operation, R as RequestContextFactory } from '../cache-7af07baa.js';
3
3
 
4
4
  declare class NetlifyCacheStorage {
5
5
  #private;
@@ -1,5 +1,5 @@
1
- import { E as EnvironmentOptions } from '../cache-089d07a0.js';
2
- export { B as Base64Encoder, N as NetlifyCache, O as Operation, R as RequestContextFactory } from '../cache-089d07a0.js';
1
+ import { E as EnvironmentOptions } from '../cache-7af07baa.js';
2
+ export { B as Base64Encoder, N as NetlifyCache, O as Operation, R as RequestContextFactory } from '../cache-7af07baa.js';
3
3
 
4
4
  declare class NetlifyCacheStorage {
5
5
  #private;
@@ -51,17 +51,15 @@ var allowedProtocols = /* @__PURE__ */ new Set(["http:", "https:"]);
51
51
  var discardedHeaders = /* @__PURE__ */ new Set(["cookie", "content-encoding", "content-length"]);
52
52
  var getInternalHeaders = Symbol("getInternalHeaders");
53
53
  var serializeResourceHeaders = Symbol("serializeResourceHeaders");
54
- var _base64Encode, _getContext, _logger, _name, _userAgent;
54
+ var _base64Encode, _getContext, _name, _userAgent;
55
55
  var NetlifyCache = class {
56
- constructor({ base64Encode, getContext, logger, name, userAgent }) {
56
+ constructor({ base64Encode, getContext, name, userAgent }) {
57
57
  __privateAdd(this, _base64Encode, void 0);
58
58
  __privateAdd(this, _getContext, void 0);
59
- __privateAdd(this, _logger, void 0);
60
59
  __privateAdd(this, _name, void 0);
61
60
  __privateAdd(this, _userAgent, void 0);
62
61
  __privateSet(this, _base64Encode, base64Encode);
63
62
  __privateSet(this, _getContext, getContext);
64
- __privateSet(this, _logger, logger);
65
63
  __privateSet(this, _name, name);
66
64
  __privateSet(this, _userAgent, userAgent);
67
65
  }
@@ -144,7 +142,6 @@ var NetlifyCache = class {
144
142
  return res ? [res] : [];
145
143
  }
146
144
  async put(request, response) {
147
- var _a;
148
145
  if (!response.ok) {
149
146
  throw new TypeError(`Cannot cache response with status ${response.status}.`);
150
147
  }
@@ -176,13 +173,12 @@ var NetlifyCache = class {
176
173
  if (!cacheResponse.ok) {
177
174
  const errorDetail = cacheResponse.headers.get(ErrorDetail) ?? "";
178
175
  const errorMessage = ERROR_CODES[errorDetail] || GENERIC_ERROR;
179
- (_a = __privateGet(this, _logger)) == null ? void 0 : _a.call(this, `Failed to write to the cache: ${errorMessage}`);
176
+ context.logger?.(`Failed to write to the cache: ${errorMessage}`);
180
177
  }
181
178
  }
182
179
  };
183
180
  _base64Encode = new WeakMap();
184
181
  _getContext = new WeakMap();
185
- _logger = new WeakMap();
186
182
  _name = new WeakMap();
187
183
  _userAgent = new WeakMap();
188
184
  var extractAndValidateURL = (input) => {
@@ -3,7 +3,6 @@ type Logger = (...args: any[]) => void;
3
3
  interface EnvironmentOptions {
4
4
  base64Encode: Base64Encoder;
5
5
  getContext: RequestContextFactory;
6
- logger?: Logger;
7
6
  userAgent?: string;
8
7
  }
9
8
  declare enum Operation {
@@ -16,6 +15,7 @@ type RequestContextFactory = (options: {
16
15
  }) => RequestContext | null;
17
16
  interface RequestContext {
18
17
  host: string;
18
+ logger?: Logger;
19
19
  token: string;
20
20
  url: string;
21
21
  }
@@ -27,7 +27,7 @@ declare const getInternalHeaders: unique symbol;
27
27
  declare const serializeResourceHeaders: unique symbol;
28
28
  declare class NetlifyCache implements Cache {
29
29
  #private;
30
- constructor({ base64Encode, getContext, logger, name, userAgent }: NetlifyCacheOptions);
30
+ constructor({ base64Encode, getContext, name, userAgent }: NetlifyCacheOptions);
31
31
  private [getInternalHeaders];
32
32
  private [serializeResourceHeaders];
33
33
  add(request: RequestInfo): Promise<void>;
package/dist/main.cjs CHANGED
@@ -16,6 +16,24 @@ var __copyProps = (to, from, except, desc) => {
16
16
  return to;
17
17
  };
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var __accessCheck = (obj, member, msg) => {
20
+ if (!member.has(obj))
21
+ throw TypeError("Cannot " + msg);
22
+ };
23
+ var __privateGet = (obj, member, getter) => {
24
+ __accessCheck(obj, member, "read from private field");
25
+ return getter ? getter.call(obj) : member.get(obj);
26
+ };
27
+ var __privateAdd = (obj, member, value) => {
28
+ if (member.has(obj))
29
+ throw TypeError("Cannot add the same private member more than once");
30
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
31
+ };
32
+ var __privateSet = (obj, member, value, setter) => {
33
+ __accessCheck(obj, member, "write to private field");
34
+ setter ? setter.call(obj, value) : member.set(obj, value);
35
+ return value;
36
+ };
19
37
 
20
38
  // src/main.ts
21
39
  var main_exports = {};
@@ -25,18 +43,245 @@ __export(main_exports, {
25
43
  MINUTE: () => MINUTE,
26
44
  WEEK: () => WEEK,
27
45
  YEAR: () => YEAR,
46
+ caches: () => caches,
28
47
  fetchWithCache: () => fetchWithCache,
29
48
  getCacheStatus: () => getCacheStatus,
30
49
  setCacheHeaders: () => setCacheHeaders
31
50
  });
32
51
  module.exports = __toCommonJS(main_exports);
33
52
 
53
+ // src/bootstrap/errors.ts
54
+ var ERROR_CODES = {
55
+ invalid_vary: "Responses must not use unsupported directives of the `Netlify-Vary` header (https://ntl.fyi/cache_api_invalid_vary).",
56
+ no_cache: "Responses must not set cache control headers with the `private`, `no-cache` or `no-store` directives (https://ntl.fyi/cache_api_no_cache).",
57
+ low_ttl: "Responses must have a cache control header with a `max-age` or `s-maxage` directive (https://ntl.fyi/cache_api_low_ttl).",
58
+ no_directive: "Responses must have a cache control header with caching directives (https://ntl.fyi/cache_api_no_directive).",
59
+ no_ttl: "Responses must have a cache control header with a `max-age` or `s-maxage` directive (https://ntl.fyi/cache_api_no_ttl).",
60
+ no_status: "Responses must specify a status code (https://ntl.fyi/cache_api_no_status).",
61
+ invalid_directive: "Responses must have a cache control header with caching directives (https://ntl.fyi/cache_api_invalid_directive).",
62
+ status: "Responses must have a status code between 200 and 299 (https://ntl.fyi/cache_api_status)."
63
+ };
64
+ var GENERIC_ERROR = "The server has returned an unexpected error (https://ntl.fyi/cache_api_error).";
65
+
34
66
  // src/headers.ts
35
67
  var CacheStatus = "cache-status";
36
68
  var NetlifyCacheId = "netlify-cache-id";
37
69
  var NetlifyCacheTag = "netlify-cache-tag";
38
70
  var NetlifyCdnCacheControl = "netlify-cdn-cache-control";
39
71
  var NetlifyVary = "netlify-vary";
72
+ var ErrorDetail = "netlify-programmable-error";
73
+ var ResourceHeaders = "netlify-programmable-headers";
74
+ var ResourceStatus = "netlify-programmable-status";
75
+ var ResourceStore = "netlify-programmable-store";
76
+ var NetlifyForwardedHost = "netlify-forwarded-host";
77
+ var UserAgent = "user-agent";
78
+
79
+ // src/bootstrap/cache.ts
80
+ var allowedProtocols = /* @__PURE__ */ new Set(["http:", "https:"]);
81
+ var discardedHeaders = /* @__PURE__ */ new Set(["cookie", "content-encoding", "content-length"]);
82
+ var getInternalHeaders = Symbol("getInternalHeaders");
83
+ var serializeResourceHeaders = Symbol("serializeResourceHeaders");
84
+ var _base64Encode, _getContext, _name, _userAgent;
85
+ var NetlifyCache = class {
86
+ constructor({ base64Encode, getContext, name, userAgent }) {
87
+ __privateAdd(this, _base64Encode, void 0);
88
+ __privateAdd(this, _getContext, void 0);
89
+ __privateAdd(this, _name, void 0);
90
+ __privateAdd(this, _userAgent, void 0);
91
+ __privateSet(this, _base64Encode, base64Encode);
92
+ __privateSet(this, _getContext, getContext);
93
+ __privateSet(this, _name, name);
94
+ __privateSet(this, _userAgent, userAgent);
95
+ }
96
+ [getInternalHeaders](requestContext) {
97
+ const { host, token } = requestContext;
98
+ const headers = {
99
+ Authorization: `Bearer ${token}`,
100
+ [ResourceStore]: __privateGet(this, _name)
101
+ };
102
+ if (host) {
103
+ headers[NetlifyForwardedHost] = host;
104
+ }
105
+ if (__privateGet(this, _userAgent)) {
106
+ headers[UserAgent] = __privateGet(this, _userAgent);
107
+ }
108
+ return headers;
109
+ }
110
+ [serializeResourceHeaders](headers) {
111
+ const headersMap = {};
112
+ headers.forEach((value, key) => {
113
+ if (discardedHeaders.has(key)) {
114
+ return;
115
+ }
116
+ if (key === "set-cookie") {
117
+ headersMap[key] = headersMap[key] || [];
118
+ headersMap[key].push(value);
119
+ } else {
120
+ headersMap[key] = value.split(",");
121
+ }
122
+ });
123
+ return __privateGet(this, _base64Encode).call(this, JSON.stringify(headersMap));
124
+ }
125
+ async add(request) {
126
+ await this.put(new Request(request), await fetch(request));
127
+ }
128
+ async addAll(requests) {
129
+ await Promise.allSettled(requests.map((request) => this.add(request)));
130
+ }
131
+ // eslint-disable-next-line class-methods-use-this, require-await, @typescript-eslint/no-unused-vars
132
+ async delete(request) {
133
+ const context = __privateGet(this, _getContext).call(this, { operation: "delete" /* Delete */ });
134
+ if (context) {
135
+ const resourceURL = extractAndValidateURL(request);
136
+ await fetch(`${context.url}/${toCacheKey(resourceURL)}`, {
137
+ headers: this[getInternalHeaders](context),
138
+ method: "DELETE"
139
+ });
140
+ }
141
+ return true;
142
+ }
143
+ // eslint-disable-next-line class-methods-use-this, require-await, @typescript-eslint/no-unused-vars
144
+ async keys(_request) {
145
+ return [];
146
+ }
147
+ async match(request) {
148
+ try {
149
+ const context = __privateGet(this, _getContext).call(this, { operation: "read" /* Read */ });
150
+ if (!context) {
151
+ return;
152
+ }
153
+ const resourceURL = extractAndValidateURL(request);
154
+ const cacheURL = `${context.url}/${toCacheKey(resourceURL)}`;
155
+ const response = await fetch(cacheURL, {
156
+ headers: this[getInternalHeaders](context),
157
+ method: "GET"
158
+ });
159
+ if (!response.ok) {
160
+ return;
161
+ }
162
+ return response;
163
+ } catch {
164
+ }
165
+ }
166
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
167
+ async matchAll(request, _options) {
168
+ if (!request) {
169
+ return [];
170
+ }
171
+ const res = await this.match(request);
172
+ return res ? [res] : [];
173
+ }
174
+ async put(request, response) {
175
+ if (!response.ok) {
176
+ throw new TypeError(`Cannot cache response with status ${response.status}.`);
177
+ }
178
+ if (request instanceof Request && request.method !== "GET") {
179
+ throw new TypeError(`Cannot cache response to ${request.method} request.`);
180
+ }
181
+ if (response.status === 206) {
182
+ throw new TypeError("Cannot cache response to a range request (206 Partial Content).");
183
+ }
184
+ if (response.headers.get("vary")?.includes("*")) {
185
+ throw new TypeError("Cannot cache response with 'Vary: *' header.");
186
+ }
187
+ const context = __privateGet(this, _getContext).call(this, { operation: "write" /* Write */ });
188
+ if (!context) {
189
+ return;
190
+ }
191
+ const resourceURL = extractAndValidateURL(request);
192
+ const cacheResponse = await fetch(`${context.url}/${toCacheKey(resourceURL)}`, {
193
+ body: response.body,
194
+ headers: {
195
+ ...this[getInternalHeaders](context),
196
+ [ResourceHeaders]: this[serializeResourceHeaders](response.headers),
197
+ [ResourceStatus]: response.status.toString()
198
+ },
199
+ // @ts-expect-error https://github.com/whatwg/fetch/pull/1457
200
+ duplex: "half",
201
+ method: "POST"
202
+ });
203
+ if (!cacheResponse.ok) {
204
+ const errorDetail = cacheResponse.headers.get(ErrorDetail) ?? "";
205
+ const errorMessage = ERROR_CODES[errorDetail] || GENERIC_ERROR;
206
+ context.logger?.(`Failed to write to the cache: ${errorMessage}`);
207
+ }
208
+ }
209
+ };
210
+ _base64Encode = new WeakMap();
211
+ _getContext = new WeakMap();
212
+ _name = new WeakMap();
213
+ _userAgent = new WeakMap();
214
+ var extractAndValidateURL = (input) => {
215
+ let url;
216
+ if (input instanceof Request) {
217
+ url = new URL(input.url);
218
+ } else {
219
+ try {
220
+ url = new URL(String(input));
221
+ } catch {
222
+ throw new TypeError(`${input} is not a valid URL.`);
223
+ }
224
+ }
225
+ if (!allowedProtocols.has(url.protocol)) {
226
+ throw new TypeError(
227
+ `Cannot cache response for URL with unsupported protocol (${url.protocol}). Supported protocols are ${[
228
+ ...allowedProtocols
229
+ ].join(", ")}.`
230
+ );
231
+ }
232
+ return url;
233
+ };
234
+ var toCacheKey = (url) => encodeURIComponent(url.toString());
235
+
236
+ // src/bootstrap/cachestorage.ts
237
+ var _environmentOptions, _stores;
238
+ var NetlifyCacheStorage = class {
239
+ constructor(environmentOptions) {
240
+ __privateAdd(this, _environmentOptions, void 0);
241
+ __privateAdd(this, _stores, void 0);
242
+ __privateSet(this, _environmentOptions, environmentOptions);
243
+ __privateSet(this, _stores, /* @__PURE__ */ new Map());
244
+ }
245
+ open(name) {
246
+ let store = __privateGet(this, _stores).get(name);
247
+ if (!store) {
248
+ store = new NetlifyCache({
249
+ ...__privateGet(this, _environmentOptions),
250
+ name
251
+ });
252
+ __privateGet(this, _stores).set(name, store);
253
+ }
254
+ return Promise.resolve(store);
255
+ }
256
+ has(name) {
257
+ return Promise.resolve(__privateGet(this, _stores).has(name));
258
+ }
259
+ delete(name) {
260
+ return Promise.resolve(__privateGet(this, _stores).delete(name));
261
+ }
262
+ keys() {
263
+ return Promise.resolve([...__privateGet(this, _stores).keys()]);
264
+ }
265
+ async match(request, options) {
266
+ if (options?.cacheName) {
267
+ return __privateGet(this, _stores).get(options.cacheName)?.match(request);
268
+ }
269
+ for (const store of __privateGet(this, _stores).values()) {
270
+ const response = await store.match(request);
271
+ if (response === void 0) {
272
+ return;
273
+ }
274
+ }
275
+ }
276
+ };
277
+ _environmentOptions = new WeakMap();
278
+ _stores = new WeakMap();
279
+
280
+ // src/polyfill.ts
281
+ var caches = globalThis.caches ?? new NetlifyCacheStorage({
282
+ base64Encode: () => "",
283
+ getContext: () => null
284
+ });
40
285
 
41
286
  // src/cache-headers/validation.ts
42
287
  var ensureArray = (value) => Array.isArray(value) ? value : [value];
@@ -309,6 +554,7 @@ var YEAR = 365 * DAY;
309
554
  MINUTE,
310
555
  WEEK,
311
556
  YEAR,
557
+ caches,
312
558
  fetchWithCache,
313
559
  getCacheStatus,
314
560
  setCacheHeaders
package/dist/main.d.cts CHANGED
@@ -1,4 +1,11 @@
1
- import { N as NetlifyCache } from './cache-089d07a0.js';
1
+ import { N as NetlifyCache } from './cache-7af07baa.js';
2
+
3
+ /**
4
+ * Polyfill for local development environments where `globalThis.caches` is not
5
+ * available. This is a no-op cache, which will automatically work with the
6
+ * real one in production.
7
+ */
8
+ declare const caches: CacheStorage;
2
9
 
3
10
  interface CacheSettings {
4
11
  /**
@@ -174,4 +181,4 @@ declare const WEEK: number;
174
181
  */
175
182
  declare const YEAR: number;
176
183
 
177
- export { DAY, HOUR, MINUTE, WEEK, YEAR, fetchWithCache, getCacheStatus, setCacheHeaders };
184
+ export { DAY, HOUR, MINUTE, WEEK, YEAR, caches, fetchWithCache, getCacheStatus, setCacheHeaders };
package/dist/main.d.ts CHANGED
@@ -1,4 +1,11 @@
1
- import { N as NetlifyCache } from './cache-089d07a0.js';
1
+ import { N as NetlifyCache } from './cache-7af07baa.js';
2
+
3
+ /**
4
+ * Polyfill for local development environments where `globalThis.caches` is not
5
+ * available. This is a no-op cache, which will automatically work with the
6
+ * real one in production.
7
+ */
8
+ declare const caches: CacheStorage;
2
9
 
3
10
  interface CacheSettings {
4
11
  /**
@@ -174,4 +181,4 @@ declare const WEEK: number;
174
181
  */
175
182
  declare const YEAR: number;
176
183
 
177
- export { DAY, HOUR, MINUTE, WEEK, YEAR, fetchWithCache, getCacheStatus, setCacheHeaders };
184
+ export { DAY, HOUR, MINUTE, WEEK, YEAR, caches, fetchWithCache, getCacheStatus, setCacheHeaders };
package/dist/main.js CHANGED
@@ -1,9 +1,254 @@
1
+ var __accessCheck = (obj, member, msg) => {
2
+ if (!member.has(obj))
3
+ throw TypeError("Cannot " + msg);
4
+ };
5
+ var __privateGet = (obj, member, getter) => {
6
+ __accessCheck(obj, member, "read from private field");
7
+ return getter ? getter.call(obj) : member.get(obj);
8
+ };
9
+ var __privateAdd = (obj, member, value) => {
10
+ if (member.has(obj))
11
+ throw TypeError("Cannot add the same private member more than once");
12
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
13
+ };
14
+ var __privateSet = (obj, member, value, setter) => {
15
+ __accessCheck(obj, member, "write to private field");
16
+ setter ? setter.call(obj, value) : member.set(obj, value);
17
+ return value;
18
+ };
19
+
20
+ // src/bootstrap/errors.ts
21
+ var ERROR_CODES = {
22
+ invalid_vary: "Responses must not use unsupported directives of the `Netlify-Vary` header (https://ntl.fyi/cache_api_invalid_vary).",
23
+ no_cache: "Responses must not set cache control headers with the `private`, `no-cache` or `no-store` directives (https://ntl.fyi/cache_api_no_cache).",
24
+ low_ttl: "Responses must have a cache control header with a `max-age` or `s-maxage` directive (https://ntl.fyi/cache_api_low_ttl).",
25
+ no_directive: "Responses must have a cache control header with caching directives (https://ntl.fyi/cache_api_no_directive).",
26
+ no_ttl: "Responses must have a cache control header with a `max-age` or `s-maxage` directive (https://ntl.fyi/cache_api_no_ttl).",
27
+ no_status: "Responses must specify a status code (https://ntl.fyi/cache_api_no_status).",
28
+ invalid_directive: "Responses must have a cache control header with caching directives (https://ntl.fyi/cache_api_invalid_directive).",
29
+ status: "Responses must have a status code between 200 and 299 (https://ntl.fyi/cache_api_status)."
30
+ };
31
+ var GENERIC_ERROR = "The server has returned an unexpected error (https://ntl.fyi/cache_api_error).";
32
+
1
33
  // src/headers.ts
2
34
  var CacheStatus = "cache-status";
3
35
  var NetlifyCacheId = "netlify-cache-id";
4
36
  var NetlifyCacheTag = "netlify-cache-tag";
5
37
  var NetlifyCdnCacheControl = "netlify-cdn-cache-control";
6
38
  var NetlifyVary = "netlify-vary";
39
+ var ErrorDetail = "netlify-programmable-error";
40
+ var ResourceHeaders = "netlify-programmable-headers";
41
+ var ResourceStatus = "netlify-programmable-status";
42
+ var ResourceStore = "netlify-programmable-store";
43
+ var NetlifyForwardedHost = "netlify-forwarded-host";
44
+ var UserAgent = "user-agent";
45
+
46
+ // src/bootstrap/cache.ts
47
+ var allowedProtocols = /* @__PURE__ */ new Set(["http:", "https:"]);
48
+ var discardedHeaders = /* @__PURE__ */ new Set(["cookie", "content-encoding", "content-length"]);
49
+ var getInternalHeaders = Symbol("getInternalHeaders");
50
+ var serializeResourceHeaders = Symbol("serializeResourceHeaders");
51
+ var _base64Encode, _getContext, _name, _userAgent;
52
+ var NetlifyCache = class {
53
+ constructor({ base64Encode, getContext, name, userAgent }) {
54
+ __privateAdd(this, _base64Encode, void 0);
55
+ __privateAdd(this, _getContext, void 0);
56
+ __privateAdd(this, _name, void 0);
57
+ __privateAdd(this, _userAgent, void 0);
58
+ __privateSet(this, _base64Encode, base64Encode);
59
+ __privateSet(this, _getContext, getContext);
60
+ __privateSet(this, _name, name);
61
+ __privateSet(this, _userAgent, userAgent);
62
+ }
63
+ [getInternalHeaders](requestContext) {
64
+ const { host, token } = requestContext;
65
+ const headers = {
66
+ Authorization: `Bearer ${token}`,
67
+ [ResourceStore]: __privateGet(this, _name)
68
+ };
69
+ if (host) {
70
+ headers[NetlifyForwardedHost] = host;
71
+ }
72
+ if (__privateGet(this, _userAgent)) {
73
+ headers[UserAgent] = __privateGet(this, _userAgent);
74
+ }
75
+ return headers;
76
+ }
77
+ [serializeResourceHeaders](headers) {
78
+ const headersMap = {};
79
+ headers.forEach((value, key) => {
80
+ if (discardedHeaders.has(key)) {
81
+ return;
82
+ }
83
+ if (key === "set-cookie") {
84
+ headersMap[key] = headersMap[key] || [];
85
+ headersMap[key].push(value);
86
+ } else {
87
+ headersMap[key] = value.split(",");
88
+ }
89
+ });
90
+ return __privateGet(this, _base64Encode).call(this, JSON.stringify(headersMap));
91
+ }
92
+ async add(request) {
93
+ await this.put(new Request(request), await fetch(request));
94
+ }
95
+ async addAll(requests) {
96
+ await Promise.allSettled(requests.map((request) => this.add(request)));
97
+ }
98
+ // eslint-disable-next-line class-methods-use-this, require-await, @typescript-eslint/no-unused-vars
99
+ async delete(request) {
100
+ const context = __privateGet(this, _getContext).call(this, { operation: "delete" /* Delete */ });
101
+ if (context) {
102
+ const resourceURL = extractAndValidateURL(request);
103
+ await fetch(`${context.url}/${toCacheKey(resourceURL)}`, {
104
+ headers: this[getInternalHeaders](context),
105
+ method: "DELETE"
106
+ });
107
+ }
108
+ return true;
109
+ }
110
+ // eslint-disable-next-line class-methods-use-this, require-await, @typescript-eslint/no-unused-vars
111
+ async keys(_request) {
112
+ return [];
113
+ }
114
+ async match(request) {
115
+ try {
116
+ const context = __privateGet(this, _getContext).call(this, { operation: "read" /* Read */ });
117
+ if (!context) {
118
+ return;
119
+ }
120
+ const resourceURL = extractAndValidateURL(request);
121
+ const cacheURL = `${context.url}/${toCacheKey(resourceURL)}`;
122
+ const response = await fetch(cacheURL, {
123
+ headers: this[getInternalHeaders](context),
124
+ method: "GET"
125
+ });
126
+ if (!response.ok) {
127
+ return;
128
+ }
129
+ return response;
130
+ } catch {
131
+ }
132
+ }
133
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
134
+ async matchAll(request, _options) {
135
+ if (!request) {
136
+ return [];
137
+ }
138
+ const res = await this.match(request);
139
+ return res ? [res] : [];
140
+ }
141
+ async put(request, response) {
142
+ if (!response.ok) {
143
+ throw new TypeError(`Cannot cache response with status ${response.status}.`);
144
+ }
145
+ if (request instanceof Request && request.method !== "GET") {
146
+ throw new TypeError(`Cannot cache response to ${request.method} request.`);
147
+ }
148
+ if (response.status === 206) {
149
+ throw new TypeError("Cannot cache response to a range request (206 Partial Content).");
150
+ }
151
+ if (response.headers.get("vary")?.includes("*")) {
152
+ throw new TypeError("Cannot cache response with 'Vary: *' header.");
153
+ }
154
+ const context = __privateGet(this, _getContext).call(this, { operation: "write" /* Write */ });
155
+ if (!context) {
156
+ return;
157
+ }
158
+ const resourceURL = extractAndValidateURL(request);
159
+ const cacheResponse = await fetch(`${context.url}/${toCacheKey(resourceURL)}`, {
160
+ body: response.body,
161
+ headers: {
162
+ ...this[getInternalHeaders](context),
163
+ [ResourceHeaders]: this[serializeResourceHeaders](response.headers),
164
+ [ResourceStatus]: response.status.toString()
165
+ },
166
+ // @ts-expect-error https://github.com/whatwg/fetch/pull/1457
167
+ duplex: "half",
168
+ method: "POST"
169
+ });
170
+ if (!cacheResponse.ok) {
171
+ const errorDetail = cacheResponse.headers.get(ErrorDetail) ?? "";
172
+ const errorMessage = ERROR_CODES[errorDetail] || GENERIC_ERROR;
173
+ context.logger?.(`Failed to write to the cache: ${errorMessage}`);
174
+ }
175
+ }
176
+ };
177
+ _base64Encode = new WeakMap();
178
+ _getContext = new WeakMap();
179
+ _name = new WeakMap();
180
+ _userAgent = new WeakMap();
181
+ var extractAndValidateURL = (input) => {
182
+ let url;
183
+ if (input instanceof Request) {
184
+ url = new URL(input.url);
185
+ } else {
186
+ try {
187
+ url = new URL(String(input));
188
+ } catch {
189
+ throw new TypeError(`${input} is not a valid URL.`);
190
+ }
191
+ }
192
+ if (!allowedProtocols.has(url.protocol)) {
193
+ throw new TypeError(
194
+ `Cannot cache response for URL with unsupported protocol (${url.protocol}). Supported protocols are ${[
195
+ ...allowedProtocols
196
+ ].join(", ")}.`
197
+ );
198
+ }
199
+ return url;
200
+ };
201
+ var toCacheKey = (url) => encodeURIComponent(url.toString());
202
+
203
+ // src/bootstrap/cachestorage.ts
204
+ var _environmentOptions, _stores;
205
+ var NetlifyCacheStorage = class {
206
+ constructor(environmentOptions) {
207
+ __privateAdd(this, _environmentOptions, void 0);
208
+ __privateAdd(this, _stores, void 0);
209
+ __privateSet(this, _environmentOptions, environmentOptions);
210
+ __privateSet(this, _stores, /* @__PURE__ */ new Map());
211
+ }
212
+ open(name) {
213
+ let store = __privateGet(this, _stores).get(name);
214
+ if (!store) {
215
+ store = new NetlifyCache({
216
+ ...__privateGet(this, _environmentOptions),
217
+ name
218
+ });
219
+ __privateGet(this, _stores).set(name, store);
220
+ }
221
+ return Promise.resolve(store);
222
+ }
223
+ has(name) {
224
+ return Promise.resolve(__privateGet(this, _stores).has(name));
225
+ }
226
+ delete(name) {
227
+ return Promise.resolve(__privateGet(this, _stores).delete(name));
228
+ }
229
+ keys() {
230
+ return Promise.resolve([...__privateGet(this, _stores).keys()]);
231
+ }
232
+ async match(request, options) {
233
+ if (options?.cacheName) {
234
+ return __privateGet(this, _stores).get(options.cacheName)?.match(request);
235
+ }
236
+ for (const store of __privateGet(this, _stores).values()) {
237
+ const response = await store.match(request);
238
+ if (response === void 0) {
239
+ return;
240
+ }
241
+ }
242
+ }
243
+ };
244
+ _environmentOptions = new WeakMap();
245
+ _stores = new WeakMap();
246
+
247
+ // src/polyfill.ts
248
+ var caches = globalThis.caches ?? new NetlifyCacheStorage({
249
+ base64Encode: () => "",
250
+ getContext: () => null
251
+ });
7
252
 
8
253
  // src/cache-headers/validation.ts
9
254
  var ensureArray = (value) => Array.isArray(value) ? value : [value];
@@ -275,6 +520,7 @@ export {
275
520
  MINUTE,
276
521
  WEEK,
277
522
  YEAR,
523
+ caches,
278
524
  fetchWithCache,
279
525
  getCacheStatus,
280
526
  setCacheHeaders
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlify/cache",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "TypeScript utilities for interacting with the Netlify cache",
5
5
  "type": "module",
6
6
  "engines": {