miniflare 0.0.0-020b04921

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.
Files changed (38) hide show
  1. package/README.md +858 -0
  2. package/bootstrap.js +11 -0
  3. package/dist/src/index.d.ts +4408 -0
  4. package/dist/src/index.js +10391 -0
  5. package/dist/src/index.js.map +6 -0
  6. package/dist/src/workers/assets/assets-kv.worker.js +28 -0
  7. package/dist/src/workers/assets/assets-kv.worker.js.map +6 -0
  8. package/dist/src/workers/assets/assets.worker.js +9275 -0
  9. package/dist/src/workers/assets/assets.worker.js.map +6 -0
  10. package/dist/src/workers/assets/router.worker.js +8755 -0
  11. package/dist/src/workers/assets/router.worker.js.map +6 -0
  12. package/dist/src/workers/cache/cache-entry-noop.worker.js +19 -0
  13. package/dist/src/workers/cache/cache-entry-noop.worker.js.map +6 -0
  14. package/dist/src/workers/cache/cache-entry.worker.js +28 -0
  15. package/dist/src/workers/cache/cache-entry.worker.js.map +6 -0
  16. package/dist/src/workers/cache/cache.worker.js +656 -0
  17. package/dist/src/workers/cache/cache.worker.js.map +6 -0
  18. package/dist/src/workers/core/entry.worker.js +1040 -0
  19. package/dist/src/workers/core/entry.worker.js.map +6 -0
  20. package/dist/src/workers/d1/database.worker.js +350 -0
  21. package/dist/src/workers/d1/database.worker.js.map +6 -0
  22. package/dist/src/workers/kv/namespace.worker.js +258 -0
  23. package/dist/src/workers/kv/namespace.worker.js.map +6 -0
  24. package/dist/src/workers/kv/sites.worker.js +147 -0
  25. package/dist/src/workers/kv/sites.worker.js.map +6 -0
  26. package/dist/src/workers/queues/broker.worker.js +294 -0
  27. package/dist/src/workers/queues/broker.worker.js.map +6 -0
  28. package/dist/src/workers/r2/bucket.worker.js +1157 -0
  29. package/dist/src/workers/r2/bucket.worker.js.map +6 -0
  30. package/dist/src/workers/ratelimit/ratelimit.worker.js +54 -0
  31. package/dist/src/workers/ratelimit/ratelimit.worker.js.map +6 -0
  32. package/dist/src/workers/shared/index.worker.js +706 -0
  33. package/dist/src/workers/shared/index.worker.js.map +6 -0
  34. package/dist/src/workers/shared/object-entry.worker.js +21 -0
  35. package/dist/src/workers/shared/object-entry.worker.js.map +6 -0
  36. package/dist/src/workers/shared/zod.worker.js +2719 -0
  37. package/dist/src/workers/shared/zod.worker.js.map +6 -0
  38. package/package.json +108 -0
@@ -0,0 +1,656 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __commonJS = (cb, mod) => function() {
7
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from == "object" || typeof from == "function")
11
+ for (let key of __getOwnPropNames(from))
12
+ !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ return to;
14
+ };
15
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
16
+ // If the importer is in node compatibility mode or this is not an ESM
17
+ // file that has been converted to a CommonJS file using a Babel-
18
+ // compatible transform (i.e. "__esModule" has not been set), then set
19
+ // "default" to the CommonJS "module.exports" for node compatibility.
20
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target,
21
+ mod
22
+ ));
23
+ var __decorateClass = (decorators, target, key, kind) => {
24
+ for (var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target, i = decorators.length - 1, decorator; i >= 0; i--)
25
+ (decorator = decorators[i]) && (result = (kind ? decorator(target, key, result) : decorator(result)) || result);
26
+ return kind && result && __defProp(target, key, result), result;
27
+ };
28
+
29
+ // ../../node_modules/.pnpm/http-cache-semantics@4.1.1/node_modules/http-cache-semantics/index.js
30
+ var require_http_cache_semantics = __commonJS({
31
+ "../../node_modules/.pnpm/http-cache-semantics@4.1.1/node_modules/http-cache-semantics/index.js"(exports, module) {
32
+ "use strict";
33
+ var statusCodeCacheableByDefault = /* @__PURE__ */ new Set([
34
+ 200,
35
+ 203,
36
+ 204,
37
+ 206,
38
+ 300,
39
+ 301,
40
+ 308,
41
+ 404,
42
+ 405,
43
+ 410,
44
+ 414,
45
+ 501
46
+ ]), understoodStatuses = /* @__PURE__ */ new Set([
47
+ 200,
48
+ 203,
49
+ 204,
50
+ 300,
51
+ 301,
52
+ 302,
53
+ 303,
54
+ 307,
55
+ 308,
56
+ 404,
57
+ 405,
58
+ 410,
59
+ 414,
60
+ 501
61
+ ]), errorStatusCodes = /* @__PURE__ */ new Set([
62
+ 500,
63
+ 502,
64
+ 503,
65
+ 504
66
+ ]), hopByHopHeaders = {
67
+ date: !0,
68
+ // included, because we add Age update Date
69
+ connection: !0,
70
+ "keep-alive": !0,
71
+ "proxy-authenticate": !0,
72
+ "proxy-authorization": !0,
73
+ te: !0,
74
+ trailer: !0,
75
+ "transfer-encoding": !0,
76
+ upgrade: !0
77
+ }, excludedFromRevalidationUpdate = {
78
+ // Since the old body is reused, it doesn't make sense to change properties of the body
79
+ "content-length": !0,
80
+ "content-encoding": !0,
81
+ "transfer-encoding": !0,
82
+ "content-range": !0
83
+ };
84
+ function toNumberOrZero(s) {
85
+ let n = parseInt(s, 10);
86
+ return isFinite(n) ? n : 0;
87
+ }
88
+ function isErrorResponse(response) {
89
+ return response ? errorStatusCodes.has(response.status) : !0;
90
+ }
91
+ function parseCacheControl(header) {
92
+ let cc = {};
93
+ if (!header)
94
+ return cc;
95
+ let parts = header.trim().split(/,/);
96
+ for (let part of parts) {
97
+ let [k, v] = part.split(/=/, 2);
98
+ cc[k.trim()] = v === void 0 ? !0 : v.trim().replace(/^"|"$/g, "");
99
+ }
100
+ return cc;
101
+ }
102
+ function formatCacheControl(cc) {
103
+ let parts = [];
104
+ for (let k in cc) {
105
+ let v = cc[k];
106
+ parts.push(v === !0 ? k : k + "=" + v);
107
+ }
108
+ if (parts.length)
109
+ return parts.join(", ");
110
+ }
111
+ module.exports = class {
112
+ constructor(req, res, {
113
+ shared,
114
+ cacheHeuristic,
115
+ immutableMinTimeToLive,
116
+ ignoreCargoCult,
117
+ _fromObject
118
+ } = {}) {
119
+ if (_fromObject) {
120
+ this._fromObject(_fromObject);
121
+ return;
122
+ }
123
+ if (!res || !res.headers)
124
+ throw Error("Response headers missing");
125
+ this._assertRequestHasHeaders(req), this._responseTime = this.now(), this._isShared = shared !== !1, this._cacheHeuristic = cacheHeuristic !== void 0 ? cacheHeuristic : 0.1, this._immutableMinTtl = immutableMinTimeToLive !== void 0 ? immutableMinTimeToLive : 24 * 3600 * 1e3, this._status = "status" in res ? res.status : 200, this._resHeaders = res.headers, this._rescc = parseCacheControl(res.headers["cache-control"]), this._method = "method" in req ? req.method : "GET", this._url = req.url, this._host = req.headers.host, this._noAuthorization = !req.headers.authorization, this._reqHeaders = res.headers.vary ? req.headers : null, this._reqcc = parseCacheControl(req.headers["cache-control"]), ignoreCargoCult && "pre-check" in this._rescc && "post-check" in this._rescc && (delete this._rescc["pre-check"], delete this._rescc["post-check"], delete this._rescc["no-cache"], delete this._rescc["no-store"], delete this._rescc["must-revalidate"], this._resHeaders = Object.assign({}, this._resHeaders, {
126
+ "cache-control": formatCacheControl(this._rescc)
127
+ }), delete this._resHeaders.expires, delete this._resHeaders.pragma), res.headers["cache-control"] == null && /no-cache/.test(res.headers.pragma) && (this._rescc["no-cache"] = !0);
128
+ }
129
+ now() {
130
+ return Date.now();
131
+ }
132
+ storable() {
133
+ return !!(!this._reqcc["no-store"] && // A cache MUST NOT store a response to any request, unless:
134
+ // The request method is understood by the cache and defined as being cacheable, and
135
+ (this._method === "GET" || this._method === "HEAD" || this._method === "POST" && this._hasExplicitExpiration()) && // the response status code is understood by the cache, and
136
+ understoodStatuses.has(this._status) && // the "no-store" cache directive does not appear in request or response header fields, and
137
+ !this._rescc["no-store"] && // the "private" response directive does not appear in the response, if the cache is shared, and
138
+ (!this._isShared || !this._rescc.private) && // the Authorization header field does not appear in the request, if the cache is shared,
139
+ (!this._isShared || this._noAuthorization || this._allowsStoringAuthenticated()) && // the response either:
140
+ // contains an Expires header field, or
141
+ (this._resHeaders.expires || // contains a max-age response directive, or
142
+ // contains a s-maxage response directive and the cache is shared, or
143
+ // contains a public response directive.
144
+ this._rescc["max-age"] || this._isShared && this._rescc["s-maxage"] || this._rescc.public || // has a status code that is defined as cacheable by default
145
+ statusCodeCacheableByDefault.has(this._status)));
146
+ }
147
+ _hasExplicitExpiration() {
148
+ return this._isShared && this._rescc["s-maxage"] || this._rescc["max-age"] || this._resHeaders.expires;
149
+ }
150
+ _assertRequestHasHeaders(req) {
151
+ if (!req || !req.headers)
152
+ throw Error("Request headers missing");
153
+ }
154
+ satisfiesWithoutRevalidation(req) {
155
+ this._assertRequestHasHeaders(req);
156
+ let requestCC = parseCacheControl(req.headers["cache-control"]);
157
+ return requestCC["no-cache"] || /no-cache/.test(req.headers.pragma) || requestCC["max-age"] && this.age() > requestCC["max-age"] || requestCC["min-fresh"] && this.timeToLive() < 1e3 * requestCC["min-fresh"] || this.stale() && !(requestCC["max-stale"] && !this._rescc["must-revalidate"] && (requestCC["max-stale"] === !0 || requestCC["max-stale"] > this.age() - this.maxAge())) ? !1 : this._requestMatches(req, !1);
158
+ }
159
+ _requestMatches(req, allowHeadMethod) {
160
+ return (!this._url || this._url === req.url) && this._host === req.headers.host && // the request method associated with the stored response allows it to be used for the presented request, and
161
+ (!req.method || this._method === req.method || allowHeadMethod && req.method === "HEAD") && // selecting header fields nominated by the stored response (if any) match those presented, and
162
+ this._varyMatches(req);
163
+ }
164
+ _allowsStoringAuthenticated() {
165
+ return this._rescc["must-revalidate"] || this._rescc.public || this._rescc["s-maxage"];
166
+ }
167
+ _varyMatches(req) {
168
+ if (!this._resHeaders.vary)
169
+ return !0;
170
+ if (this._resHeaders.vary === "*")
171
+ return !1;
172
+ let fields = this._resHeaders.vary.trim().toLowerCase().split(/\s*,\s*/);
173
+ for (let name of fields)
174
+ if (req.headers[name] !== this._reqHeaders[name])
175
+ return !1;
176
+ return !0;
177
+ }
178
+ _copyWithoutHopByHopHeaders(inHeaders) {
179
+ let headers = {};
180
+ for (let name in inHeaders)
181
+ hopByHopHeaders[name] || (headers[name] = inHeaders[name]);
182
+ if (inHeaders.connection) {
183
+ let tokens = inHeaders.connection.trim().split(/\s*,\s*/);
184
+ for (let name of tokens)
185
+ delete headers[name];
186
+ }
187
+ if (headers.warning) {
188
+ let warnings = headers.warning.split(/,/).filter((warning) => !/^\s*1[0-9][0-9]/.test(warning));
189
+ warnings.length ? headers.warning = warnings.join(",").trim() : delete headers.warning;
190
+ }
191
+ return headers;
192
+ }
193
+ responseHeaders() {
194
+ let headers = this._copyWithoutHopByHopHeaders(this._resHeaders), age = this.age();
195
+ return age > 3600 * 24 && !this._hasExplicitExpiration() && this.maxAge() > 3600 * 24 && (headers.warning = (headers.warning ? `${headers.warning}, ` : "") + '113 - "rfc7234 5.5.4"'), headers.age = `${Math.round(age)}`, headers.date = new Date(this.now()).toUTCString(), headers;
196
+ }
197
+ /**
198
+ * Value of the Date response header or current time if Date was invalid
199
+ * @return timestamp
200
+ */
201
+ date() {
202
+ let serverDate = Date.parse(this._resHeaders.date);
203
+ return isFinite(serverDate) ? serverDate : this._responseTime;
204
+ }
205
+ /**
206
+ * Value of the Age header, in seconds, updated for the current time.
207
+ * May be fractional.
208
+ *
209
+ * @return Number
210
+ */
211
+ age() {
212
+ let age = this._ageValue(), residentTime = (this.now() - this._responseTime) / 1e3;
213
+ return age + residentTime;
214
+ }
215
+ _ageValue() {
216
+ return toNumberOrZero(this._resHeaders.age);
217
+ }
218
+ /**
219
+ * Value of applicable max-age (or heuristic equivalent) in seconds. This counts since response's `Date`.
220
+ *
221
+ * For an up-to-date value, see `timeToLive()`.
222
+ *
223
+ * @return Number
224
+ */
225
+ maxAge() {
226
+ if (!this.storable() || this._rescc["no-cache"] || this._isShared && this._resHeaders["set-cookie"] && !this._rescc.public && !this._rescc.immutable || this._resHeaders.vary === "*")
227
+ return 0;
228
+ if (this._isShared) {
229
+ if (this._rescc["proxy-revalidate"])
230
+ return 0;
231
+ if (this._rescc["s-maxage"])
232
+ return toNumberOrZero(this._rescc["s-maxage"]);
233
+ }
234
+ if (this._rescc["max-age"])
235
+ return toNumberOrZero(this._rescc["max-age"]);
236
+ let defaultMinTtl = this._rescc.immutable ? this._immutableMinTtl : 0, serverDate = this.date();
237
+ if (this._resHeaders.expires) {
238
+ let expires = Date.parse(this._resHeaders.expires);
239
+ return Number.isNaN(expires) || expires < serverDate ? 0 : Math.max(defaultMinTtl, (expires - serverDate) / 1e3);
240
+ }
241
+ if (this._resHeaders["last-modified"]) {
242
+ let lastModified = Date.parse(this._resHeaders["last-modified"]);
243
+ if (isFinite(lastModified) && serverDate > lastModified)
244
+ return Math.max(
245
+ defaultMinTtl,
246
+ (serverDate - lastModified) / 1e3 * this._cacheHeuristic
247
+ );
248
+ }
249
+ return defaultMinTtl;
250
+ }
251
+ timeToLive() {
252
+ let age = this.maxAge() - this.age(), staleIfErrorAge = age + toNumberOrZero(this._rescc["stale-if-error"]), staleWhileRevalidateAge = age + toNumberOrZero(this._rescc["stale-while-revalidate"]);
253
+ return Math.max(0, age, staleIfErrorAge, staleWhileRevalidateAge) * 1e3;
254
+ }
255
+ stale() {
256
+ return this.maxAge() <= this.age();
257
+ }
258
+ _useStaleIfError() {
259
+ return this.maxAge() + toNumberOrZero(this._rescc["stale-if-error"]) > this.age();
260
+ }
261
+ useStaleWhileRevalidate() {
262
+ return this.maxAge() + toNumberOrZero(this._rescc["stale-while-revalidate"]) > this.age();
263
+ }
264
+ static fromObject(obj) {
265
+ return new this(void 0, void 0, { _fromObject: obj });
266
+ }
267
+ _fromObject(obj) {
268
+ if (this._responseTime)
269
+ throw Error("Reinitialized");
270
+ if (!obj || obj.v !== 1)
271
+ throw Error("Invalid serialization");
272
+ this._responseTime = obj.t, this._isShared = obj.sh, this._cacheHeuristic = obj.ch, this._immutableMinTtl = obj.imm !== void 0 ? obj.imm : 24 * 3600 * 1e3, this._status = obj.st, this._resHeaders = obj.resh, this._rescc = obj.rescc, this._method = obj.m, this._url = obj.u, this._host = obj.h, this._noAuthorization = obj.a, this._reqHeaders = obj.reqh, this._reqcc = obj.reqcc;
273
+ }
274
+ toObject() {
275
+ return {
276
+ v: 1,
277
+ t: this._responseTime,
278
+ sh: this._isShared,
279
+ ch: this._cacheHeuristic,
280
+ imm: this._immutableMinTtl,
281
+ st: this._status,
282
+ resh: this._resHeaders,
283
+ rescc: this._rescc,
284
+ m: this._method,
285
+ u: this._url,
286
+ h: this._host,
287
+ a: this._noAuthorization,
288
+ reqh: this._reqHeaders,
289
+ reqcc: this._reqcc
290
+ };
291
+ }
292
+ /**
293
+ * Headers for sending to the origin server to revalidate stale response.
294
+ * Allows server to return 304 to allow reuse of the previous response.
295
+ *
296
+ * Hop by hop headers are always stripped.
297
+ * Revalidation headers may be added or removed, depending on request.
298
+ */
299
+ revalidationHeaders(incomingReq) {
300
+ this._assertRequestHasHeaders(incomingReq);
301
+ let headers = this._copyWithoutHopByHopHeaders(incomingReq.headers);
302
+ if (delete headers["if-range"], !this._requestMatches(incomingReq, !0) || !this.storable())
303
+ return delete headers["if-none-match"], delete headers["if-modified-since"], headers;
304
+ if (this._resHeaders.etag && (headers["if-none-match"] = headers["if-none-match"] ? `${headers["if-none-match"]}, ${this._resHeaders.etag}` : this._resHeaders.etag), headers["accept-ranges"] || headers["if-match"] || headers["if-unmodified-since"] || this._method && this._method != "GET") {
305
+ if (delete headers["if-modified-since"], headers["if-none-match"]) {
306
+ let etags = headers["if-none-match"].split(/,/).filter((etag) => !/^\s*W\//.test(etag));
307
+ etags.length ? headers["if-none-match"] = etags.join(",").trim() : delete headers["if-none-match"];
308
+ }
309
+ } else
310
+ this._resHeaders["last-modified"] && !headers["if-modified-since"] && (headers["if-modified-since"] = this._resHeaders["last-modified"]);
311
+ return headers;
312
+ }
313
+ /**
314
+ * Creates new CachePolicy with information combined from the previews response,
315
+ * and the new revalidation response.
316
+ *
317
+ * Returns {policy, modified} where modified is a boolean indicating
318
+ * whether the response body has been modified, and old cached body can't be used.
319
+ *
320
+ * @return {Object} {policy: CachePolicy, modified: Boolean}
321
+ */
322
+ revalidatedPolicy(request, response) {
323
+ if (this._assertRequestHasHeaders(request), this._useStaleIfError() && isErrorResponse(response))
324
+ return {
325
+ modified: !1,
326
+ matches: !1,
327
+ policy: this
328
+ };
329
+ if (!response || !response.headers)
330
+ throw Error("Response headers missing");
331
+ let matches = !1;
332
+ if (response.status !== void 0 && response.status != 304 ? matches = !1 : response.headers.etag && !/^\s*W\//.test(response.headers.etag) ? matches = this._resHeaders.etag && this._resHeaders.etag.replace(/^\s*W\//, "") === response.headers.etag : this._resHeaders.etag && response.headers.etag ? matches = this._resHeaders.etag.replace(/^\s*W\//, "") === response.headers.etag.replace(/^\s*W\//, "") : this._resHeaders["last-modified"] ? matches = this._resHeaders["last-modified"] === response.headers["last-modified"] : !this._resHeaders.etag && !this._resHeaders["last-modified"] && !response.headers.etag && !response.headers["last-modified"] && (matches = !0), !matches)
333
+ return {
334
+ policy: new this.constructor(request, response),
335
+ // Client receiving 304 without body, even if it's invalid/mismatched has no option
336
+ // but to reuse a cached body. We don't have a good way to tell clients to do
337
+ // error recovery in such case.
338
+ modified: response.status != 304,
339
+ matches: !1
340
+ };
341
+ let headers = {};
342
+ for (let k in this._resHeaders)
343
+ headers[k] = k in response.headers && !excludedFromRevalidationUpdate[k] ? response.headers[k] : this._resHeaders[k];
344
+ let newResponse = Object.assign({}, response, {
345
+ status: this._status,
346
+ method: this._method,
347
+ headers
348
+ });
349
+ return {
350
+ policy: new this.constructor(request, newResponse, {
351
+ shared: this._isShared,
352
+ cacheHeuristic: this._cacheHeuristic,
353
+ immutableMinTimeToLive: this._immutableMinTtl
354
+ }),
355
+ modified: !1,
356
+ matches: !0
357
+ };
358
+ }
359
+ };
360
+ }
361
+ });
362
+
363
+ // src/workers/cache/cache.worker.ts
364
+ var import_http_cache_semantics = __toESM(require_http_cache_semantics());
365
+ import assert from "node:assert";
366
+ import { Buffer as Buffer2 } from "node:buffer";
367
+ import {
368
+ DeferredPromise,
369
+ GET,
370
+ KeyValueStorage,
371
+ LogLevel,
372
+ MiniflareDurableObject,
373
+ parseRanges,
374
+ PURGE,
375
+ PUT
376
+ } from "miniflare:shared";
377
+
378
+ // src/workers/kv/constants.ts
379
+ import { testRegExps } from "miniflare:shared";
380
+ var KVLimits = {
381
+ MIN_CACHE_TTL: 60,
382
+ MAX_LIST_KEYS: 1e3,
383
+ MAX_KEY_SIZE: 512,
384
+ MAX_VALUE_SIZE: 25 * 1024 * 1024,
385
+ MAX_VALUE_SIZE_TEST: 1024,
386
+ MAX_METADATA_SIZE: 1024
387
+ };
388
+ var SITES_NO_CACHE_PREFIX = "$__MINIFLARE_SITES__$/";
389
+ function isSitesRequest(request) {
390
+ return new URL(request.url).pathname.startsWith(`/${SITES_NO_CACHE_PREFIX}`);
391
+ }
392
+
393
+ // src/workers/cache/errors.worker.ts
394
+ import { HttpError } from "miniflare:shared";
395
+
396
+ // src/workers/cache/constants.ts
397
+ var CacheHeaders = {
398
+ NAMESPACE: "cf-cache-namespace",
399
+ STATUS: "cf-cache-status"
400
+ };
401
+
402
+ // src/workers/cache/errors.worker.ts
403
+ var CacheError = class extends HttpError {
404
+ constructor(code, message, headers = []) {
405
+ super(code, message);
406
+ this.headers = headers;
407
+ }
408
+ toResponse() {
409
+ return new Response(null, {
410
+ status: this.code,
411
+ headers: this.headers
412
+ });
413
+ }
414
+ context(info) {
415
+ return this.message += ` (${info})`, this;
416
+ }
417
+ }, StorageFailure = class extends CacheError {
418
+ constructor() {
419
+ super(413, "Cache storage failed");
420
+ }
421
+ }, PurgeFailure = class extends CacheError {
422
+ constructor() {
423
+ super(404, "Couldn't find asset to purge");
424
+ }
425
+ }, CacheMiss = class extends CacheError {
426
+ constructor() {
427
+ super(
428
+ // workerd ignores this, but it's the correct status code
429
+ 504,
430
+ "Asset not found in cache",
431
+ [[CacheHeaders.STATUS, "MISS"]]
432
+ );
433
+ }
434
+ }, RangeNotSatisfiable = class extends CacheError {
435
+ constructor(size) {
436
+ super(416, "Range not satisfiable", [
437
+ ["Content-Range", `bytes */${size}`],
438
+ [CacheHeaders.STATUS, "HIT"]
439
+ ]);
440
+ }
441
+ };
442
+
443
+ // src/workers/cache/cache.worker.ts
444
+ function getCacheKey(req) {
445
+ return req.cf?.cacheKey ? String(req.cf?.cacheKey) : req.url;
446
+ }
447
+ function getExpiration(timers, req, res) {
448
+ let reqHeaders = normaliseHeaders(req.headers);
449
+ delete reqHeaders["cache-control"];
450
+ let resHeaders = normaliseHeaders(res.headers);
451
+ resHeaders["cache-control"]?.toLowerCase().includes("private=set-cookie") && (resHeaders["cache-control"] = resHeaders["cache-control"]?.toLowerCase().replace(/private=set-cookie;?/i, ""), delete resHeaders["set-cookie"]);
452
+ let cacheReq = {
453
+ url: req.url,
454
+ // If a request gets to the Cache service, it's method will be GET. See README.md for details
455
+ method: "GET",
456
+ headers: reqHeaders
457
+ }, cacheRes = {
458
+ status: res.status,
459
+ headers: resHeaders
460
+ }, originalNow = import_http_cache_semantics.default.prototype.now;
461
+ import_http_cache_semantics.default.prototype.now = timers.now;
462
+ try {
463
+ let policy = new import_http_cache_semantics.default(cacheReq, cacheRes, { shared: !0 });
464
+ return {
465
+ // Check if the request & response is cacheable
466
+ storable: policy.storable() && !("set-cookie" in resHeaders),
467
+ expiration: policy.timeToLive(),
468
+ // Cache Policy Headers is typed as [header: string]: string | string[] | undefined
469
+ // It's safe to ignore the undefined here, which is what casting to HeadersInit does
470
+ headers: policy.responseHeaders()
471
+ };
472
+ } finally {
473
+ import_http_cache_semantics.default.prototype.now = originalNow;
474
+ }
475
+ }
476
+ function normaliseHeaders(headers) {
477
+ let result = {};
478
+ for (let [key, value] of headers)
479
+ result[key.toLowerCase()] = value;
480
+ return result;
481
+ }
482
+ var etagRegexp = /^(W\/)?"(.+)"$/;
483
+ function parseETag(value) {
484
+ return etagRegexp.exec(value.trim())?.[2] ?? void 0;
485
+ }
486
+ var utcDateRegexp = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), \d\d (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d\d\d\d \d\d:\d\d:\d\d GMT$/;
487
+ function parseUTCDate(value) {
488
+ return utcDateRegexp.test(value) ? Date.parse(value) : NaN;
489
+ }
490
+ function getMatchResponse(reqHeaders, res) {
491
+ let reqIfNoneMatchHeader = reqHeaders.get("If-None-Match"), resETagHeader = res.headers.get("ETag");
492
+ if (reqIfNoneMatchHeader !== null && resETagHeader !== null) {
493
+ let resETag = parseETag(resETagHeader);
494
+ if (resETag !== void 0) {
495
+ if (reqIfNoneMatchHeader.trim() === "*")
496
+ return new Response(null, { status: 304, headers: res.headers });
497
+ for (let reqIfNoneMatch of reqIfNoneMatchHeader.split(","))
498
+ if (resETag === parseETag(reqIfNoneMatch))
499
+ return new Response(null, { status: 304, headers: res.headers });
500
+ }
501
+ }
502
+ let reqIfModifiedSinceHeader = reqHeaders.get("If-Modified-Since"), resLastModifiedHeader = res.headers.get("Last-Modified");
503
+ if (reqIfModifiedSinceHeader !== null && resLastModifiedHeader !== null) {
504
+ let reqIfModifiedSince = parseUTCDate(reqIfModifiedSinceHeader);
505
+ if (parseUTCDate(resLastModifiedHeader) <= reqIfModifiedSince)
506
+ return new Response(null, { status: 304, headers: res.headers });
507
+ }
508
+ if (res.ranges.length > 0)
509
+ if (res.status = 206, res.ranges.length > 1)
510
+ assert(!(res.body instanceof ReadableStream)), res.headers.set("Content-Type", res.body.multipartContentType);
511
+ else {
512
+ let { start, end } = res.ranges[0];
513
+ res.headers.set(
514
+ "Content-Range",
515
+ `bytes ${start}-${end}/${res.totalSize}`
516
+ ), res.headers.set("Content-Length", `${end - start + 1}`);
517
+ }
518
+ return res.body instanceof ReadableStream || (res.body = res.body.body), new Response(res.body, { status: res.status, headers: res.headers });
519
+ }
520
+ var CR = "\r".charCodeAt(0), LF = `
521
+ `.charCodeAt(0), STATUS_REGEXP = /^HTTP\/\d(?:\.\d)? (?<rawStatusCode>\d+) (?<statusText>.*)$/;
522
+ async function parseHttpResponse(stream) {
523
+ let buffer = Buffer2.alloc(0), blankLineIndex = -1;
524
+ for await (let chunk of stream.values({ preventCancel: !0 }))
525
+ if (buffer = Buffer2.concat([buffer, chunk]), blankLineIndex = buffer.findIndex(
526
+ (_value, index) => buffer[index] === CR && buffer[index + 1] === LF && buffer[index + 2] === CR && buffer[index + 3] === LF
527
+ ), blankLineIndex !== -1)
528
+ break;
529
+ assert(blankLineIndex !== -1, "Expected to find blank line in HTTP message");
530
+ let rawStatusHeaders = buffer.subarray(0, blankLineIndex).toString(), [rawStatus, ...rawHeaders] = rawStatusHeaders.split(`\r
531
+ `), statusMatch = rawStatus.match(STATUS_REGEXP);
532
+ assert(
533
+ statusMatch?.groups != null,
534
+ `Expected first line ${JSON.stringify(rawStatus)} to be HTTP status line`
535
+ );
536
+ let { rawStatusCode, statusText } = statusMatch.groups, statusCode = parseInt(rawStatusCode), headers = rawHeaders.map((rawHeader) => {
537
+ let index = rawHeader.indexOf(":");
538
+ return [
539
+ rawHeader.substring(0, index),
540
+ rawHeader.substring(index + 1).trim()
541
+ ];
542
+ }), prefix = buffer.subarray(
543
+ blankLineIndex + 4
544
+ /* "\r\n\r\n" */
545
+ ), { readable, writable } = new IdentityTransformStream(), writer = writable.getWriter();
546
+ return writer.write(prefix).then(() => (writer.releaseLock(), stream.pipeTo(writable))).catch((e) => console.error("Error writing HTTP body:", e)), new Response(readable, { status: statusCode, statusText, headers });
547
+ }
548
+ var SizingStream = class extends TransformStream {
549
+ size;
550
+ constructor() {
551
+ let sizePromise = new DeferredPromise(), size = 0;
552
+ super({
553
+ transform(chunk, controller) {
554
+ size += chunk.byteLength, controller.enqueue(chunk);
555
+ },
556
+ flush() {
557
+ sizePromise.resolve(size);
558
+ }
559
+ }), this.size = sizePromise;
560
+ }
561
+ }, CacheObject = class extends MiniflareDurableObject {
562
+ #warnedUsage = !1;
563
+ async #maybeWarnUsage(request) {
564
+ !this.#warnedUsage && request.cf?.miniflare?.cacheWarnUsage === !0 && (this.#warnedUsage = !0, await this.logWithLevel(
565
+ LogLevel.WARN,
566
+ "Cache operations will have no impact if you deploy to a workers.dev subdomain!"
567
+ ));
568
+ }
569
+ #storage;
570
+ get storage() {
571
+ return this.#storage ??= new KeyValueStorage(this);
572
+ }
573
+ match = async (req) => {
574
+ await this.#maybeWarnUsage(req);
575
+ let cacheKey = getCacheKey(req);
576
+ if (isSitesRequest(req))
577
+ throw new CacheMiss();
578
+ let resHeaders, resRanges, cached = await this.storage.get(cacheKey, ({ size, headers }) => {
579
+ resHeaders = new Headers(headers);
580
+ let contentType = resHeaders.get("Content-Type"), rangeHeader = req.headers.get("Range");
581
+ if (rangeHeader !== null && (resRanges = parseRanges(rangeHeader, size), resRanges === void 0))
582
+ throw new RangeNotSatisfiable(size);
583
+ return {
584
+ ranges: resRanges,
585
+ contentLength: size,
586
+ contentType: contentType ?? void 0
587
+ };
588
+ });
589
+ if (cached?.metadata === void 0)
590
+ throw new CacheMiss();
591
+ return assert(resHeaders !== void 0), resHeaders.set("CF-Cache-Status", "HIT"), resRanges ??= [], getMatchResponse(req.headers, {
592
+ status: cached.metadata.status,
593
+ headers: resHeaders,
594
+ ranges: resRanges,
595
+ body: cached.value,
596
+ totalSize: cached.metadata.size
597
+ });
598
+ };
599
+ put = async (req) => {
600
+ await this.#maybeWarnUsage(req);
601
+ let cacheKey = getCacheKey(req);
602
+ if (isSitesRequest(req))
603
+ throw new CacheMiss();
604
+ assert(req.body !== null);
605
+ let res = await parseHttpResponse(req.body), body = res.body;
606
+ assert(body !== null);
607
+ let { storable, expiration, headers } = getExpiration(
608
+ this.timers,
609
+ req,
610
+ res
611
+ );
612
+ if (!storable) {
613
+ try {
614
+ await body.pipeTo(new WritableStream());
615
+ } catch {
616
+ }
617
+ throw new StorageFailure();
618
+ }
619
+ let contentLength = parseInt(res.headers.get("Content-Length")), sizePromise;
620
+ if (Number.isNaN(contentLength)) {
621
+ let stream = new SizingStream();
622
+ body = body.pipeThrough(stream), sizePromise = stream.size;
623
+ } else
624
+ sizePromise = Promise.resolve(contentLength);
625
+ let metadata = sizePromise.then((size) => ({
626
+ headers: Object.entries(headers),
627
+ status: res.status,
628
+ size
629
+ }));
630
+ return await this.storage.put({
631
+ key: cacheKey,
632
+ value: body,
633
+ expiration: this.timers.now() + expiration,
634
+ metadata
635
+ }), new Response(null, { status: 204 });
636
+ };
637
+ delete = async (req) => {
638
+ await this.#maybeWarnUsage(req);
639
+ let cacheKey = getCacheKey(req);
640
+ if (!await this.storage.delete(cacheKey))
641
+ throw new PurgeFailure();
642
+ return new Response(null);
643
+ };
644
+ };
645
+ __decorateClass([
646
+ GET()
647
+ ], CacheObject.prototype, "match", 2), __decorateClass([
648
+ PUT()
649
+ ], CacheObject.prototype, "put", 2), __decorateClass([
650
+ PURGE()
651
+ ], CacheObject.prototype, "delete", 2);
652
+ export {
653
+ CacheObject,
654
+ parseHttpResponse
655
+ };
656
+ //# sourceMappingURL=cache.worker.js.map