r2-explorer 1.1.10 → 1.1.12

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 (32) hide show
  1. package/README.md +1 -0
  2. package/dashboard/assets/{AuthLayout.44d95d02.js → AuthLayout.a658d9a1.js} +1 -1
  3. package/dashboard/assets/EmailFilePage.a119cdf2.js +2 -0
  4. package/dashboard/assets/ErrorNotFound.eee74d45.js +1 -0
  5. package/dashboard/assets/LoginPage.43f67aea.js +1 -0
  6. package/dashboard/assets/{auth-store.c1556190.js → auth-store.b5edde02.js} +1 -1
  7. package/dashboard/assets/{auth.e242b7eb.js → auth.d68e1e7f.js} +1 -1
  8. package/dashboard/assets/{bus.4a606b2f.js → bus.ccf0fe02.js} +1 -1
  9. package/dashboard/assets/{index.a1f775a6.css → index.4aacbd79.css} +1 -1
  10. package/dashboard/assets/{index.706c4d3e.js → index.ad530e3e.js} +28 -28
  11. package/dashboard/index.html +2 -2
  12. package/dashboard/spa/assets/{AuthLayout.44d95d02.js → AuthLayout.a658d9a1.js} +1 -1
  13. package/dashboard/spa/assets/EmailFilePage.a119cdf2.js +2 -0
  14. package/dashboard/spa/assets/ErrorNotFound.eee74d45.js +1 -0
  15. package/dashboard/spa/assets/LoginPage.43f67aea.js +1 -0
  16. package/dashboard/spa/assets/{auth-store.c1556190.js → auth-store.b5edde02.js} +1 -1
  17. package/dashboard/spa/assets/{auth.e242b7eb.js → auth.d68e1e7f.js} +1 -1
  18. package/dashboard/spa/assets/{bus.4a606b2f.js → bus.ccf0fe02.js} +1 -1
  19. package/dashboard/spa/assets/{index.a1f775a6.css → index.4aacbd79.css} +1 -1
  20. package/dashboard/spa/assets/{index.706c4d3e.js → index.ad530e3e.js} +28 -28
  21. package/dashboard/spa/index.html +2 -2
  22. package/dist/index.d.mts +1 -1
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +792 -454
  25. package/dist/index.mjs +782 -444
  26. package/package.json +15 -15
  27. package/dashboard/assets/EmailFilePage.ccbeefd3.js +0 -2
  28. package/dashboard/assets/ErrorNotFound.19a254c5.js +0 -1
  29. package/dashboard/assets/LoginPage.ca226917.js +0 -1
  30. package/dashboard/spa/assets/EmailFilePage.ccbeefd3.js +0 -2
  31. package/dashboard/spa/assets/ErrorNotFound.19a254c5.js +0 -1
  32. package/dashboard/spa/assets/LoginPage.ca226917.js +0 -1
package/dist/index.js CHANGED
@@ -28,15 +28,85 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
30
  // src/index.ts
31
- var src_exports = {};
32
- __export(src_exports, {
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
33
  R2Explorer: () => R2Explorer
34
34
  });
35
- module.exports = __toCommonJS(src_exports);
35
+ module.exports = __toCommonJS(index_exports);
36
36
  var import_cloudflare_access = require("@hono/cloudflare-access");
37
- var import_chanfana14 = require("chanfana");
37
+ var import_chanfana18 = require("chanfana");
38
+
39
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/compose.js
40
+ var compose = (middleware, onError, onNotFound) => {
41
+ return (context, next) => {
42
+ let index = -1;
43
+ return dispatch(0);
44
+ async function dispatch(i) {
45
+ if (i <= index) {
46
+ throw new Error("next() called multiple times");
47
+ }
48
+ index = i;
49
+ let res;
50
+ let isError = false;
51
+ let handler;
52
+ if (middleware[i]) {
53
+ handler = middleware[i][0][0];
54
+ context.req.routeIndex = i;
55
+ } else {
56
+ handler = i === middleware.length && next || void 0;
57
+ }
58
+ if (handler) {
59
+ try {
60
+ res = await handler(context, () => dispatch(i + 1));
61
+ } catch (err) {
62
+ if (err instanceof Error && onError) {
63
+ context.error = err;
64
+ res = await onError(err, context);
65
+ isError = true;
66
+ } else {
67
+ throw err;
68
+ }
69
+ }
70
+ } else {
71
+ if (context.finalized === false && onNotFound) {
72
+ res = await onNotFound(context);
73
+ }
74
+ }
75
+ if (res && (context.finalized === false || isError)) {
76
+ context.res = res;
77
+ }
78
+ return context;
79
+ }
80
+ };
81
+ };
82
+
83
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/http-exception.js
84
+ var HTTPException = class extends Error {
85
+ res;
86
+ status;
87
+ constructor(status = 500, options) {
88
+ super(options?.message, { cause: options?.cause });
89
+ this.res = options?.res;
90
+ this.status = status;
91
+ }
92
+ getResponse() {
93
+ if (this.res) {
94
+ const newResponse = new Response(this.res.body, {
95
+ status: this.status,
96
+ headers: this.res.headers
97
+ });
98
+ return newResponse;
99
+ }
100
+ return new Response(this.message, {
101
+ status: this.status
102
+ });
103
+ }
104
+ };
38
105
 
39
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/utils/body.js
106
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/request/constants.js
107
+ var GET_MATCH_RESULT = Symbol();
108
+
109
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/utils/body.js
40
110
  var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
41
111
  const { all = false, dot = false } = options;
42
112
  const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
@@ -83,7 +153,11 @@ var handleParsingAllValues = (form, key, value) => {
83
153
  form[key] = [form[key], value];
84
154
  }
85
155
  } else {
86
- form[key] = value;
156
+ if (!key.endsWith("[]")) {
157
+ form[key] = value;
158
+ } else {
159
+ form[key] = [value];
160
+ }
87
161
  }
88
162
  };
89
163
  var handleParsingNestedValues = (form, key, value) => {
@@ -101,7 +175,7 @@ var handleParsingNestedValues = (form, key, value) => {
101
175
  });
102
176
  };
103
177
 
104
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/utils/url.js
178
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/utils/url.js
105
179
  var splitPath = (path) => {
106
180
  const paths = path.split("/");
107
181
  if (paths[0] === "") {
@@ -116,9 +190,9 @@ var splitRoutingPath = (routePath) => {
116
190
  };
117
191
  var extractGroupsFromPath = (path) => {
118
192
  const groups = [];
119
- path = path.replace(/\{[^}]+\}/g, (match, index) => {
193
+ path = path.replace(/\{[^}]+\}/g, (match2, index) => {
120
194
  const mark = `@${index}`;
121
- groups.push([mark, match]);
195
+ groups.push([mark, match2]);
122
196
  return mark;
123
197
  });
124
198
  return { groups, path };
@@ -136,20 +210,21 @@ var replaceGroupMarks = (paths, groups) => {
136
210
  return paths;
137
211
  };
138
212
  var patternCache = {};
139
- var getPattern = (label) => {
213
+ var getPattern = (label, next) => {
140
214
  if (label === "*") {
141
215
  return "*";
142
216
  }
143
- const match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
144
- if (match) {
145
- if (!patternCache[label]) {
146
- if (match[2]) {
147
- patternCache[label] = [label, match[1], new RegExp("^" + match[2] + "$")];
217
+ const match2 = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
218
+ if (match2) {
219
+ const cacheKey = `${label}#${next}`;
220
+ if (!patternCache[cacheKey]) {
221
+ if (match2[2]) {
222
+ patternCache[cacheKey] = next && next[0] !== ":" && next[0] !== "*" ? [cacheKey, match2[1], new RegExp(`^${match2[2]}(?=/${next})`)] : [label, match2[1], new RegExp(`^${match2[2]}$`)];
148
223
  } else {
149
- patternCache[label] = [label, match[1], true];
224
+ patternCache[cacheKey] = [label, match2[1], true];
150
225
  }
151
226
  }
152
- return patternCache[label];
227
+ return patternCache[cacheKey];
153
228
  }
154
229
  return null;
155
230
  };
@@ -157,11 +232,11 @@ var tryDecode = (str, decoder) => {
157
232
  try {
158
233
  return decoder(str);
159
234
  } catch {
160
- return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match) => {
235
+ return str.replace(/(?:%[0-9A-Fa-f]{2})+/g, (match2) => {
161
236
  try {
162
- return decoder(match);
237
+ return decoder(match2);
163
238
  } catch {
164
- return match;
239
+ return match2;
165
240
  }
166
241
  });
167
242
  }
@@ -169,7 +244,7 @@ var tryDecode = (str, decoder) => {
169
244
  var tryDecodeURI = (str) => tryDecode(str, decodeURI);
170
245
  var getPath = (request) => {
171
246
  const url = request.url;
172
- const start = url.indexOf("/", 8);
247
+ const start = url.indexOf("/", url.indexOf(":") + 4);
173
248
  let i = start;
174
249
  for (; i < url.length; i++) {
175
250
  const charCode = url.charCodeAt(i);
@@ -187,30 +262,14 @@ var getPathNoStrict = (request) => {
187
262
  const result = getPath(request);
188
263
  return result.length > 1 && result.at(-1) === "/" ? result.slice(0, -1) : result;
189
264
  };
190
- var mergePath = (...paths) => {
191
- let p = "";
192
- let endsWithSlash = false;
193
- for (let path of paths) {
194
- if (p.at(-1) === "/") {
195
- p = p.slice(0, -1);
196
- endsWithSlash = true;
197
- }
198
- if (path[0] !== "/") {
199
- path = `/${path}`;
200
- }
201
- if (path === "/" && endsWithSlash) {
202
- p = `${p}/`;
203
- } else if (path !== "/") {
204
- p = `${p}${path}`;
205
- }
206
- if (path === "/" && p === "") {
207
- p = "/";
208
- }
265
+ var mergePath = (base, sub, ...rest) => {
266
+ if (rest.length) {
267
+ sub = mergePath(sub, ...rest);
209
268
  }
210
- return p;
269
+ return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
211
270
  };
212
271
  var checkOptionalParameter = (path) => {
213
- if (!path.match(/\:.+\?$/)) {
272
+ if (path.charCodeAt(path.length - 1) !== 63 || !path.includes(":")) {
214
273
  return null;
215
274
  }
216
275
  const segments = path.split("/");
@@ -243,14 +302,17 @@ var _decodeURI = (value) => {
243
302
  if (value.indexOf("+") !== -1) {
244
303
  value = value.replace(/\+/g, " ");
245
304
  }
246
- return value.indexOf("%") !== -1 ? decodeURIComponent_(value) : value;
305
+ return value.indexOf("%") !== -1 ? tryDecode(value, decodeURIComponent_) : value;
247
306
  };
248
307
  var _getQueryParam = (url, key, multiple) => {
249
308
  let encoded;
250
309
  if (!multiple && key && !/[%+]/.test(key)) {
251
- let keyIndex2 = url.indexOf(`?${key}`, 8);
310
+ let keyIndex2 = url.indexOf("?", 8);
252
311
  if (keyIndex2 === -1) {
253
- keyIndex2 = url.indexOf(`&${key}`, 8);
312
+ return void 0;
313
+ }
314
+ if (!url.startsWith(key, keyIndex2 + 1)) {
315
+ keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
254
316
  }
255
317
  while (keyIndex2 !== -1) {
256
318
  const trailingKeyCode = url.charCodeAt(keyIndex2 + key.length + 1);
@@ -315,7 +377,7 @@ var getQueryParams = (url, key) => {
315
377
  };
316
378
  var decodeURIComponent_ = decodeURIComponent;
317
379
 
318
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/request.js
380
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/request.js
319
381
  var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
320
382
  var HonoRequest = class {
321
383
  raw;
@@ -336,14 +398,14 @@ var HonoRequest = class {
336
398
  #getDecodedParam(key) {
337
399
  const paramKey = this.#matchResult[0][this.routeIndex][1][key];
338
400
  const param = this.#getParamValue(paramKey);
339
- return param ? /\%/.test(param) ? tryDecodeURIComponent(param) : param : void 0;
401
+ return param && /\%/.test(param) ? tryDecodeURIComponent(param) : param;
340
402
  }
341
403
  #getAllDecodedParams() {
342
404
  const decoded = {};
343
405
  const keys = Object.keys(this.#matchResult[0][this.routeIndex][1]);
344
406
  for (const key of keys) {
345
407
  const value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]);
346
- if (value && typeof value === "string") {
408
+ if (value !== void 0) {
347
409
  decoded[key] = /\%/.test(value) ? tryDecodeURIComponent(value) : value;
348
410
  }
349
411
  }
@@ -360,7 +422,7 @@ var HonoRequest = class {
360
422
  }
361
423
  header(name) {
362
424
  if (name) {
363
- return this.raw.headers.get(name.toLowerCase()) ?? void 0;
425
+ return this.raw.headers.get(name) ?? void 0;
364
426
  }
365
427
  const headerData = {};
366
428
  this.raw.headers.forEach((value, key) => {
@@ -389,7 +451,7 @@ var HonoRequest = class {
389
451
  return bodyCache[key] = raw2[key]();
390
452
  };
391
453
  json() {
392
- return this.#cachedBody("json");
454
+ return this.#cachedBody("text").then((text) => JSON.parse(text));
393
455
  }
394
456
  text() {
395
457
  return this.#cachedBody("text");
@@ -415,6 +477,9 @@ var HonoRequest = class {
415
477
  get method() {
416
478
  return this.raw.method;
417
479
  }
480
+ get [GET_MATCH_RESULT]() {
481
+ return this.#matchResult;
482
+ }
418
483
  get matchedRoutes() {
419
484
  return this.#matchResult[0].map(([[, route]]) => route);
420
485
  }
@@ -423,7 +488,7 @@ var HonoRequest = class {
423
488
  }
424
489
  };
425
490
 
426
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/utils/html.js
491
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/utils/html.js
427
492
  var HtmlEscapedCallbackPhase = {
428
493
  Stringify: 1,
429
494
  BeforeStream: 2,
@@ -465,13 +530,13 @@ var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) =>
465
530
  }
466
531
  };
467
532
 
468
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/context.js
533
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/context.js
469
534
  var TEXT_PLAIN = "text/plain; charset=UTF-8";
470
- var setHeaders = (headers, map = {}) => {
471
- for (const key of Object.keys(map)) {
472
- headers.set(key, map[key]);
473
- }
474
- return headers;
535
+ var setDefaultContentType = (contentType, headers) => {
536
+ return {
537
+ "Content-Type": contentType,
538
+ ...headers
539
+ };
475
540
  };
476
541
  var Context = class {
477
542
  #rawRequest;
@@ -480,15 +545,13 @@ var Context = class {
480
545
  #var;
481
546
  finalized = false;
482
547
  error;
483
- #status = 200;
548
+ #status;
484
549
  #executionCtx;
485
- #headers;
486
- #preparedHeaders;
487
550
  #res;
488
- #isFresh = true;
489
551
  #layout;
490
552
  #renderer;
491
553
  #notFoundHandler;
554
+ #preparedHeaders;
492
555
  #matchResult;
493
556
  #path;
494
557
  constructor(req, options) {
@@ -520,36 +583,25 @@ var Context = class {
520
583
  }
521
584
  }
522
585
  get res() {
523
- this.#isFresh = false;
524
- return this.#res ||= new Response("404 Not Found", { status: 404 });
586
+ return this.#res ||= new Response(null, {
587
+ headers: this.#preparedHeaders ??= new Headers()
588
+ });
525
589
  }
526
590
  set res(_res) {
527
- this.#isFresh = false;
528
591
  if (this.#res && _res) {
529
- try {
530
- for (const [k, v] of this.#res.headers.entries()) {
531
- if (k === "content-type") {
532
- continue;
533
- }
534
- if (k === "set-cookie") {
535
- const cookies = this.#res.headers.getSetCookie();
536
- _res.headers.delete("set-cookie");
537
- for (const cookie of cookies) {
538
- _res.headers.append("set-cookie", cookie);
539
- }
540
- } else {
541
- _res.headers.set(k, v);
542
- }
592
+ _res = new Response(_res.body, _res);
593
+ for (const [k, v] of this.#res.headers.entries()) {
594
+ if (k === "content-type") {
595
+ continue;
543
596
  }
544
- } catch (e) {
545
- if (e instanceof TypeError && e.message.includes("immutable")) {
546
- this.res = new Response(_res.body, {
547
- headers: _res.headers,
548
- status: _res.status
549
- });
550
- return;
597
+ if (k === "set-cookie") {
598
+ const cookies = this.#res.headers.getSetCookie();
599
+ _res.headers.delete("set-cookie");
600
+ for (const cookie of cookies) {
601
+ _res.headers.append("set-cookie", cookie);
602
+ }
551
603
  } else {
552
- throw e;
604
+ _res.headers.set(k, v);
553
605
  }
554
606
  }
555
607
  }
@@ -566,42 +618,19 @@ var Context = class {
566
618
  this.#renderer = renderer;
567
619
  };
568
620
  header = (name, value, options) => {
569
- if (value === void 0) {
570
- if (this.#headers) {
571
- this.#headers.delete(name);
572
- } else if (this.#preparedHeaders) {
573
- delete this.#preparedHeaders[name.toLocaleLowerCase()];
574
- }
575
- if (this.finalized) {
576
- this.res.headers.delete(name);
577
- }
578
- return;
621
+ if (this.finalized) {
622
+ this.#res = new Response(this.#res.body, this.#res);
579
623
  }
580
- if (options?.append) {
581
- if (!this.#headers) {
582
- this.#isFresh = false;
583
- this.#headers = new Headers(this.#preparedHeaders);
584
- this.#preparedHeaders = {};
585
- }
586
- this.#headers.append(name, value);
624
+ const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers();
625
+ if (value === void 0) {
626
+ headers.delete(name);
627
+ } else if (options?.append) {
628
+ headers.append(name, value);
587
629
  } else {
588
- if (this.#headers) {
589
- this.#headers.set(name, value);
590
- } else {
591
- this.#preparedHeaders ??= {};
592
- this.#preparedHeaders[name.toLowerCase()] = value;
593
- }
594
- }
595
- if (this.finalized) {
596
- if (options?.append) {
597
- this.res.headers.append(name, value);
598
- } else {
599
- this.res.headers.set(name, value);
600
- }
630
+ headers.set(name, value);
601
631
  }
602
632
  };
603
633
  status = (status) => {
604
- this.#isFresh = false;
605
634
  this.#status = status;
606
635
  };
607
636
  set = (key, value) => {
@@ -618,94 +647,58 @@ var Context = class {
618
647
  return Object.fromEntries(this.#var);
619
648
  }
620
649
  #newResponse(data, arg, headers) {
621
- if (this.#isFresh && !headers && !arg && this.#status === 200) {
622
- return new Response(data, {
623
- headers: this.#preparedHeaders
624
- });
625
- }
626
- if (arg && typeof arg !== "number") {
627
- const header = new Headers(arg.headers);
628
- if (this.#headers) {
629
- this.#headers.forEach((v, k) => {
630
- if (k === "set-cookie") {
631
- header.append(k, v);
632
- } else {
633
- header.set(k, v);
634
- }
635
- });
636
- }
637
- const headers2 = setHeaders(header, this.#preparedHeaders);
638
- return new Response(data, {
639
- headers: headers2,
640
- status: arg.status ?? this.#status
641
- });
642
- }
643
- const status = typeof arg === "number" ? arg : this.#status;
644
- this.#preparedHeaders ??= {};
645
- this.#headers ??= new Headers();
646
- setHeaders(this.#headers, this.#preparedHeaders);
647
- if (this.#res) {
648
- this.#res.headers.forEach((v, k) => {
649
- if (k === "set-cookie") {
650
- this.#headers?.append(k, v);
650
+ const responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders ?? new Headers();
651
+ if (typeof arg === "object" && "headers" in arg) {
652
+ const argHeaders = arg.headers instanceof Headers ? arg.headers : new Headers(arg.headers);
653
+ for (const [key, value] of argHeaders) {
654
+ if (key.toLowerCase() === "set-cookie") {
655
+ responseHeaders.append(key, value);
651
656
  } else {
652
- this.#headers?.set(k, v);
657
+ responseHeaders.set(key, value);
653
658
  }
654
- });
655
- setHeaders(this.#headers, this.#preparedHeaders);
659
+ }
656
660
  }
657
- headers ??= {};
658
- for (const [k, v] of Object.entries(headers)) {
659
- if (typeof v === "string") {
660
- this.#headers.set(k, v);
661
- } else {
662
- this.#headers.delete(k);
663
- for (const v2 of v) {
664
- this.#headers.append(k, v2);
661
+ if (headers) {
662
+ for (const [k, v] of Object.entries(headers)) {
663
+ if (typeof v === "string") {
664
+ responseHeaders.set(k, v);
665
+ } else {
666
+ responseHeaders.delete(k);
667
+ for (const v2 of v) {
668
+ responseHeaders.append(k, v2);
669
+ }
665
670
  }
666
671
  }
667
672
  }
668
- return new Response(data, {
669
- status,
670
- headers: this.#headers
671
- });
673
+ const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
674
+ return new Response(data, { status, headers: responseHeaders });
672
675
  }
673
676
  newResponse = (...args) => this.#newResponse(...args);
674
- body = (data, arg, headers) => {
675
- return typeof arg === "number" ? this.#newResponse(data, arg, headers) : this.#newResponse(data, arg);
676
- };
677
+ body = (data, arg, headers) => this.#newResponse(data, arg, headers);
677
678
  text = (text, arg, headers) => {
678
- if (!this.#preparedHeaders) {
679
- if (this.#isFresh && !headers && !arg) {
680
- return new Response(text);
681
- }
682
- this.#preparedHeaders = {};
683
- }
684
- this.#preparedHeaders["content-type"] = TEXT_PLAIN;
685
- if (typeof arg === "number") {
686
- return this.#newResponse(text, arg, headers);
687
- }
688
- return this.#newResponse(text, arg);
679
+ return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse(
680
+ text,
681
+ arg,
682
+ setDefaultContentType(TEXT_PLAIN, headers)
683
+ );
689
684
  };
690
685
  json = (object, arg, headers) => {
691
- const body = JSON.stringify(object);
692
- this.#preparedHeaders ??= {};
693
- this.#preparedHeaders["content-type"] = "application/json";
694
- return typeof arg === "number" ? this.#newResponse(body, arg, headers) : this.#newResponse(body, arg);
686
+ return this.#newResponse(
687
+ JSON.stringify(object),
688
+ arg,
689
+ setDefaultContentType("application/json", headers)
690
+ );
695
691
  };
696
692
  html = (html, arg, headers) => {
697
- this.#preparedHeaders ??= {};
698
- this.#preparedHeaders["content-type"] = "text/html; charset=UTF-8";
699
- if (typeof html === "object") {
700
- return resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then((html2) => {
701
- return typeof arg === "number" ? this.#newResponse(html2, arg, headers) : this.#newResponse(html2, arg);
702
- });
703
- }
704
- return typeof arg === "number" ? this.#newResponse(html, arg, headers) : this.#newResponse(html, arg);
693
+ const res = (html2) => this.#newResponse(html2, arg, setDefaultContentType("text/html; charset=UTF-8", headers));
694
+ return typeof html === "object" ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res) : res(html);
705
695
  };
706
696
  redirect = (location, status) => {
707
- this.#headers ??= new Headers();
708
- this.#headers.set("Location", String(location));
697
+ const locationString = String(location);
698
+ this.header(
699
+ "Location",
700
+ !/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString)
701
+ );
709
702
  return this.newResponse(null, status ?? 302);
710
703
  };
711
704
  notFound = () => {
@@ -714,56 +707,7 @@ var Context = class {
714
707
  };
715
708
  };
716
709
 
717
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/compose.js
718
- var compose = (middleware, onError, onNotFound) => {
719
- return (context, next) => {
720
- let index = -1;
721
- const isContext = context instanceof Context;
722
- return dispatch(0);
723
- async function dispatch(i) {
724
- if (i <= index) {
725
- throw new Error("next() called multiple times");
726
- }
727
- index = i;
728
- let res;
729
- let isError = false;
730
- let handler;
731
- if (middleware[i]) {
732
- handler = middleware[i][0][0];
733
- if (isContext) {
734
- context.req.routeIndex = i;
735
- }
736
- } else {
737
- handler = i === middleware.length && next || void 0;
738
- }
739
- if (!handler) {
740
- if (isContext && context.finalized === false && onNotFound) {
741
- res = await onNotFound(context);
742
- }
743
- } else {
744
- try {
745
- res = await handler(context, () => {
746
- return dispatch(i + 1);
747
- });
748
- } catch (err) {
749
- if (err instanceof Error && isContext && onError) {
750
- context.error = err;
751
- res = await onError(err, context);
752
- isError = true;
753
- } else {
754
- throw err;
755
- }
756
- }
757
- }
758
- if (res && (context.finalized === false || isError)) {
759
- context.res = res;
760
- }
761
- return context;
762
- }
763
- };
764
- };
765
-
766
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/router.js
710
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/router.js
767
711
  var METHOD_NAME_ALL = "ALL";
768
712
  var METHOD_NAME_ALL_LOWERCASE = "all";
769
713
  var METHODS = ["get", "post", "put", "delete", "options", "patch"];
@@ -771,16 +715,17 @@ var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is
771
715
  var UnsupportedPathError = class extends Error {
772
716
  };
773
717
 
774
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/utils/constants.js
718
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/utils/constants.js
775
719
  var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
776
720
 
777
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/hono-base.js
721
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/hono-base.js
778
722
  var notFoundHandler = (c) => {
779
723
  return c.text("404 Not Found", 404);
780
724
  };
781
725
  var errorHandler = (err, c) => {
782
726
  if ("getResponse" in err) {
783
- return err.getResponse();
727
+ const res = err.getResponse();
728
+ return c.newResponse(res.body, res);
784
729
  }
785
730
  console.error(err);
786
731
  return c.text("Internal Server Error", 500);
@@ -838,16 +783,17 @@ var Hono = class {
838
783
  });
839
784
  return this;
840
785
  };
841
- const strict = options.strict ?? true;
842
- delete options.strict;
843
- Object.assign(this, options);
844
- this.getPath = strict ? options.getPath ?? getPath : getPathNoStrict;
786
+ const { strict, ...optionsWithoutStrict } = options;
787
+ Object.assign(this, optionsWithoutStrict);
788
+ this.getPath = strict ?? true ? options.getPath ?? getPath : getPathNoStrict;
845
789
  }
846
790
  #clone() {
847
791
  const clone = new Hono({
848
792
  router: this.router,
849
793
  getPath: this.getPath
850
794
  });
795
+ clone.errorHandler = this.errorHandler;
796
+ clone.#notFoundHandler = this.#notFoundHandler;
851
797
  clone.routes = this.routes;
852
798
  return clone;
853
799
  }
@@ -888,7 +834,11 @@ var Hono = class {
888
834
  optionHandler = options;
889
835
  } else {
890
836
  optionHandler = options.optionHandler;
891
- replaceRequest = options.replaceRequest;
837
+ if (options.replaceRequest === false) {
838
+ replaceRequest = (request) => request;
839
+ } else {
840
+ replaceRequest = options.replaceRequest;
841
+ }
892
842
  }
893
843
  }
894
844
  const getOptions = optionHandler ? (c) => {
@@ -924,7 +874,7 @@ var Hono = class {
924
874
  #addRoute(method, path, handler) {
925
875
  method = method.toUpperCase();
926
876
  path = mergePath(this._basePath, path);
927
- const r = { path, method, handler };
877
+ const r = { basePath: this._basePath, path, method, handler };
928
878
  this.router.add(method, path, [handler, r]);
929
879
  this.routes.push(r);
930
880
  }
@@ -999,7 +949,28 @@ var Hono = class {
999
949
  };
1000
950
  };
1001
951
 
1002
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/router/reg-exp-router/node.js
952
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/router/reg-exp-router/matcher.js
953
+ var emptyParam = [];
954
+ function match(method, path) {
955
+ const matchers = this.buildAllMatchers();
956
+ const match2 = (method2, path2) => {
957
+ const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
958
+ const staticMatch = matcher[2][path2];
959
+ if (staticMatch) {
960
+ return staticMatch;
961
+ }
962
+ const match3 = path2.match(matcher[0]);
963
+ if (!match3) {
964
+ return [[], emptyParam];
965
+ }
966
+ const index = match3.indexOf("", 1);
967
+ return [matcher[1][index], match3];
968
+ };
969
+ this.match = match2;
970
+ return match2(method, path);
971
+ }
972
+
973
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/router/reg-exp-router/node.js
1003
974
  var LABEL_REG_EXP_STR = "[^/]+";
1004
975
  var ONLY_WILDCARD_REG_EXP_STR = ".*";
1005
976
  var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
@@ -1046,6 +1017,9 @@ var Node = class {
1046
1017
  const name = pattern[1];
1047
1018
  let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
1048
1019
  if (name && pattern[2]) {
1020
+ if (regexpStr === ".*") {
1021
+ throw PATH_ERROR;
1022
+ }
1049
1023
  regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
1050
1024
  if (/\((?!\?:)/.test(regexpStr)) {
1051
1025
  throw PATH_ERROR;
@@ -1104,7 +1078,7 @@ var Node = class {
1104
1078
  }
1105
1079
  };
1106
1080
 
1107
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/router/reg-exp-router/trie.js
1081
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/router/reg-exp-router/trie.js
1108
1082
  var Trie = class {
1109
1083
  #context = { varIndex: 0 };
1110
1084
  #root = new Node();
@@ -1160,8 +1134,7 @@ var Trie = class {
1160
1134
  }
1161
1135
  };
1162
1136
 
1163
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/router/reg-exp-router/router.js
1164
- var emptyParam = [];
1137
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/router/reg-exp-router/router.js
1165
1138
  var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
1166
1139
  var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
1167
1140
  function buildWildcardRegExp(path) {
@@ -1308,30 +1281,14 @@ var RegExpRouter = class {
1308
1281
  });
1309
1282
  }
1310
1283
  }
1311
- match(method, path) {
1312
- clearWildcardRegExpCache();
1313
- const matchers = this.#buildAllMatchers();
1314
- this.match = (method2, path2) => {
1315
- const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
1316
- const staticMatch = matcher[2][path2];
1317
- if (staticMatch) {
1318
- return staticMatch;
1319
- }
1320
- const match = path2.match(matcher[0]);
1321
- if (!match) {
1322
- return [[], emptyParam];
1323
- }
1324
- const index = match.indexOf("", 1);
1325
- return [matcher[1][index], match];
1326
- };
1327
- return this.match(method, path);
1328
- }
1329
- #buildAllMatchers() {
1284
+ match = match;
1285
+ buildAllMatchers() {
1330
1286
  const matchers = /* @__PURE__ */ Object.create(null);
1331
1287
  Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
1332
1288
  matchers[method] ||= this.#buildMatcher(method);
1333
1289
  });
1334
1290
  this.#middleware = this.#routes = void 0;
1291
+ clearWildcardRegExpCache();
1335
1292
  return matchers;
1336
1293
  }
1337
1294
  #buildMatcher(method) {
@@ -1356,7 +1313,7 @@ var RegExpRouter = class {
1356
1313
  }
1357
1314
  };
1358
1315
 
1359
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/router/smart-router/router.js
1316
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/router/smart-router/router.js
1360
1317
  var SmartRouter = class {
1361
1318
  name = "SmartRouter";
1362
1319
  #routers = [];
@@ -1411,7 +1368,7 @@ var SmartRouter = class {
1411
1368
  }
1412
1369
  };
1413
1370
 
1414
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/router/trie-router/node.js
1371
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/router/trie-router/node.js
1415
1372
  var emptyParams = /* @__PURE__ */ Object.create(null);
1416
1373
  var Node2 = class {
1417
1374
  #methods;
@@ -1436,30 +1393,30 @@ var Node2 = class {
1436
1393
  const possibleKeys = [];
1437
1394
  for (let i = 0, len = parts.length; i < len; i++) {
1438
1395
  const p = parts[i];
1439
- if (Object.keys(curNode.#children).includes(p)) {
1440
- curNode = curNode.#children[p];
1441
- const pattern2 = getPattern(p);
1442
- if (pattern2) {
1443
- possibleKeys.push(pattern2[1]);
1396
+ const nextP = parts[i + 1];
1397
+ const pattern = getPattern(p, nextP);
1398
+ const key = Array.isArray(pattern) ? pattern[0] : p;
1399
+ if (key in curNode.#children) {
1400
+ curNode = curNode.#children[key];
1401
+ if (pattern) {
1402
+ possibleKeys.push(pattern[1]);
1444
1403
  }
1445
1404
  continue;
1446
1405
  }
1447
- curNode.#children[p] = new Node2();
1448
- const pattern = getPattern(p);
1406
+ curNode.#children[key] = new Node2();
1449
1407
  if (pattern) {
1450
1408
  curNode.#patterns.push(pattern);
1451
1409
  possibleKeys.push(pattern[1]);
1452
1410
  }
1453
- curNode = curNode.#children[p];
1411
+ curNode = curNode.#children[key];
1454
1412
  }
1455
- const m = /* @__PURE__ */ Object.create(null);
1456
- const handlerSet = {
1457
- handler,
1458
- possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
1459
- score: this.#order
1460
- };
1461
- m[method] = handlerSet;
1462
- curNode.#methods.push(m);
1413
+ curNode.#methods.push({
1414
+ [method]: {
1415
+ handler,
1416
+ possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
1417
+ score: this.#order
1418
+ }
1419
+ });
1463
1420
  return curNode;
1464
1421
  }
1465
1422
  #getHandlerSets(node, method, nodeParams, params) {
@@ -1489,6 +1446,7 @@ var Node2 = class {
1489
1446
  const curNode = this;
1490
1447
  let curNodes = [curNode];
1491
1448
  const parts = splitPath(path);
1449
+ const curNodesQueue = [];
1492
1450
  for (let i = 0, len = parts.length; i < len; i++) {
1493
1451
  const part = parts[i];
1494
1452
  const isLast = i === len - 1;
@@ -1516,20 +1474,30 @@ var Node2 = class {
1516
1474
  const astNode = node.#children["*"];
1517
1475
  if (astNode) {
1518
1476
  handlerSets.push(...this.#getHandlerSets(astNode, method, node.#params));
1477
+ astNode.#params = params;
1519
1478
  tempNodes.push(astNode);
1520
1479
  }
1521
1480
  continue;
1522
1481
  }
1523
- if (part === "") {
1482
+ const [key, name, matcher] = pattern;
1483
+ if (!part && !(matcher instanceof RegExp)) {
1524
1484
  continue;
1525
1485
  }
1526
- const [key, name, matcher] = pattern;
1527
1486
  const child = node.#children[key];
1528
1487
  const restPathString = parts.slice(i).join("/");
1529
- if (matcher instanceof RegExp && matcher.test(restPathString)) {
1530
- params[name] = restPathString;
1531
- handlerSets.push(...this.#getHandlerSets(child, method, node.#params, params));
1532
- continue;
1488
+ if (matcher instanceof RegExp) {
1489
+ const m = matcher.exec(restPathString);
1490
+ if (m) {
1491
+ params[name] = m[0];
1492
+ handlerSets.push(...this.#getHandlerSets(child, method, node.#params, params));
1493
+ if (Object.keys(child.#children).length) {
1494
+ child.#params = params;
1495
+ const componentCount = m[0].match(/\//)?.length ?? 0;
1496
+ const targetCurNodes = curNodesQueue[componentCount] ||= [];
1497
+ targetCurNodes.push(child);
1498
+ }
1499
+ continue;
1500
+ }
1533
1501
  }
1534
1502
  if (matcher === true || matcher.test(part)) {
1535
1503
  params[name] = part;
@@ -1547,7 +1515,7 @@ var Node2 = class {
1547
1515
  }
1548
1516
  }
1549
1517
  }
1550
- curNodes = tempNodes;
1518
+ curNodes = tempNodes.concat(curNodesQueue.shift() ?? []);
1551
1519
  }
1552
1520
  if (handlerSets.length > 1) {
1553
1521
  handlerSets.sort((a, b) => {
@@ -1558,7 +1526,7 @@ var Node2 = class {
1558
1526
  }
1559
1527
  };
1560
1528
 
1561
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/router/trie-router/router.js
1529
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/router/trie-router/router.js
1562
1530
  var TrieRouter = class {
1563
1531
  name = "TrieRouter";
1564
1532
  #node;
@@ -1580,7 +1548,7 @@ var TrieRouter = class {
1580
1548
  }
1581
1549
  };
1582
1550
 
1583
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/hono.js
1551
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/hono.js
1584
1552
  var Hono2 = class extends Hono {
1585
1553
  constructor(options = {}) {
1586
1554
  super(options);
@@ -1590,30 +1558,7 @@ var Hono2 = class extends Hono {
1590
1558
  }
1591
1559
  };
1592
1560
 
1593
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/http-exception.js
1594
- var HTTPException = class extends Error {
1595
- res;
1596
- status;
1597
- constructor(status = 500, options) {
1598
- super(options?.message, { cause: options?.cause });
1599
- this.res = options?.res;
1600
- this.status = status;
1601
- }
1602
- getResponse() {
1603
- if (this.res) {
1604
- const newResponse = new Response(this.res.body, {
1605
- status: this.status,
1606
- headers: this.res.headers
1607
- });
1608
- return newResponse;
1609
- }
1610
- return new Response(this.message, {
1611
- status: this.status
1612
- });
1613
- }
1614
- };
1615
-
1616
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/utils/encode.js
1561
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/utils/encode.js
1617
1562
  var decodeBase64 = (str) => {
1618
1563
  const binary = atob(str);
1619
1564
  const bytes = new Uint8Array(new ArrayBuffer(binary.length));
@@ -1625,18 +1570,18 @@ var decodeBase64 = (str) => {
1625
1570
  return bytes;
1626
1571
  };
1627
1572
 
1628
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/utils/basic-auth.js
1573
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/utils/basic-auth.js
1629
1574
  var CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
1630
1575
  var USER_PASS_REGEXP = /^([^:]*):(.*)$/;
1631
1576
  var utf8Decoder = new TextDecoder();
1632
1577
  var auth = (req) => {
1633
- const match = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
1634
- if (!match) {
1578
+ const match2 = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
1579
+ if (!match2) {
1635
1580
  return void 0;
1636
1581
  }
1637
1582
  let userPass = void 0;
1638
1583
  try {
1639
- userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode(decodeBase64(match[1])));
1584
+ userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode(decodeBase64(match2[1])));
1640
1585
  } catch {
1641
1586
  }
1642
1587
  if (!userPass) {
@@ -1645,7 +1590,7 @@ var auth = (req) => {
1645
1590
  return { username: userPass[1], password: userPass[2] };
1646
1591
  };
1647
1592
 
1648
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/utils/crypto.js
1593
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/utils/crypto.js
1649
1594
  var sha256 = async (data) => {
1650
1595
  const algorithm = { name: "SHA-256", alias: "sha256" };
1651
1596
  const hash = await createHash(data, algorithm);
@@ -1674,7 +1619,7 @@ var createHash = async (data, algorithm) => {
1674
1619
  return null;
1675
1620
  };
1676
1621
 
1677
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/utils/buffer.js
1622
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/utils/buffer.js
1678
1623
  var timingSafeEqual = async (a, b, hashFunction) => {
1679
1624
  if (!hashFunction) {
1680
1625
  hashFunction = sha256;
@@ -1686,7 +1631,7 @@ var timingSafeEqual = async (a, b, hashFunction) => {
1686
1631
  return sa === sb && a === b;
1687
1632
  };
1688
1633
 
1689
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/middleware/basic-auth/index.js
1634
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/middleware/basic-auth/index.js
1690
1635
  var basicAuth = (options, ...users) => {
1691
1636
  const usernamePasswordInOptions = "username" in options && "password" in options;
1692
1637
  const verifyUserInOptions = "verifyUser" in options;
@@ -1741,7 +1686,7 @@ var basicAuth = (options, ...users) => {
1741
1686
  };
1742
1687
  };
1743
1688
 
1744
- // ../../node_modules/.pnpm/hono@4.6.15/node_modules/hono/dist/middleware/cors/index.js
1689
+ // ../../node_modules/.pnpm/hono@4.10.7/node_modules/hono/dist/middleware/cors/index.js
1745
1690
  var cors = (options) => {
1746
1691
  const defaults = {
1747
1692
  origin: "*",
@@ -1766,22 +1711,23 @@ var cors = (options) => {
1766
1711
  return (origin) => optsOrigin.includes(origin) ? origin : null;
1767
1712
  }
1768
1713
  })(opts.origin);
1714
+ const findAllowMethods = ((optsAllowMethods) => {
1715
+ if (typeof optsAllowMethods === "function") {
1716
+ return optsAllowMethods;
1717
+ } else if (Array.isArray(optsAllowMethods)) {
1718
+ return () => optsAllowMethods;
1719
+ } else {
1720
+ return () => [];
1721
+ }
1722
+ })(opts.allowMethods);
1769
1723
  return async function cors2(c, next) {
1770
1724
  function set(key, value) {
1771
1725
  c.res.headers.set(key, value);
1772
1726
  }
1773
- const allowOrigin = findAllowOrigin(c.req.header("origin") || "", c);
1727
+ const allowOrigin = await findAllowOrigin(c.req.header("origin") || "", c);
1774
1728
  if (allowOrigin) {
1775
1729
  set("Access-Control-Allow-Origin", allowOrigin);
1776
1730
  }
1777
- if (opts.origin !== "*") {
1778
- const existingVary = c.req.header("Vary");
1779
- if (existingVary) {
1780
- set("Vary", existingVary);
1781
- } else {
1782
- set("Vary", "Origin");
1783
- }
1784
- }
1785
1731
  if (opts.credentials) {
1786
1732
  set("Access-Control-Allow-Credentials", "true");
1787
1733
  }
@@ -1789,11 +1735,15 @@ var cors = (options) => {
1789
1735
  set("Access-Control-Expose-Headers", opts.exposeHeaders.join(","));
1790
1736
  }
1791
1737
  if (c.req.method === "OPTIONS") {
1738
+ if (opts.origin !== "*") {
1739
+ set("Vary", "Origin");
1740
+ }
1792
1741
  if (opts.maxAge != null) {
1793
1742
  set("Access-Control-Max-Age", opts.maxAge.toString());
1794
1743
  }
1795
- if (opts.allowMethods?.length) {
1796
- set("Access-Control-Allow-Methods", opts.allowMethods.join(","));
1744
+ const allowMethods = await findAllowMethods(c.req.header("origin") || "", c);
1745
+ if (allowMethods.length) {
1746
+ set("Access-Control-Allow-Methods", allowMethods.join(","));
1797
1747
  }
1798
1748
  let headers = opts.allowHeaders;
1799
1749
  if (!headers?.length) {
@@ -1815,11 +1765,14 @@ var cors = (options) => {
1815
1765
  });
1816
1766
  }
1817
1767
  await next();
1768
+ if (opts.origin !== "*") {
1769
+ c.header("Vary", "Origin", { append: true });
1770
+ }
1818
1771
  };
1819
1772
  };
1820
1773
 
1821
1774
  // src/index.ts
1822
- var import_zod13 = require("zod");
1775
+ var import_zod17 = require("zod");
1823
1776
 
1824
1777
  // src/foundation/middlewares/readonly.ts
1825
1778
  async function readOnlyMiddleware(c, next) {
@@ -1842,7 +1795,7 @@ async function readOnlyMiddleware(c, next) {
1842
1795
  }
1843
1796
 
1844
1797
  // package.json
1845
- var version = "1.1.10";
1798
+ var version = "1.1.12";
1846
1799
 
1847
1800
  // src/foundation/settings.ts
1848
1801
  var settings = {
@@ -1887,23 +1840,135 @@ var CreateFolder = class extends import_chanfana.OpenAPIRoute {
1887
1840
  }
1888
1841
  };
1889
1842
 
1890
- // src/modules/buckets/deleteObject.ts
1843
+ // src/modules/buckets/createShareLink.ts
1891
1844
  var import_chanfana2 = require("chanfana");
1892
1845
  var import_zod2 = require("zod");
1893
- var DeleteObject = class extends import_chanfana2.OpenAPIRoute {
1846
+ var CreateShareLink = class extends import_chanfana2.OpenAPIRoute {
1894
1847
  schema = {
1895
- operationId: "post-bucket-delete-object",
1848
+ operationId: "post-bucket-create-share-link",
1896
1849
  tags: ["Buckets"],
1897
- summary: "Delete object",
1850
+ summary: "Create shareable link for file",
1898
1851
  request: {
1899
1852
  params: import_zod2.z.object({
1900
- bucket: import_zod2.z.string()
1853
+ bucket: import_zod2.z.string(),
1854
+ key: import_zod2.z.string()
1901
1855
  }),
1902
1856
  body: {
1903
1857
  content: {
1904
1858
  "application/json": {
1905
1859
  schema: import_zod2.z.object({
1906
- key: import_zod2.z.string().describe("base64 encoded file key")
1860
+ expiresIn: import_zod2.z.number().optional().describe("Expiration time in seconds"),
1861
+ password: import_zod2.z.string().optional().describe("Optional password"),
1862
+ maxDownloads: import_zod2.z.number().optional().describe("Maximum downloads")
1863
+ })
1864
+ }
1865
+ }
1866
+ }
1867
+ },
1868
+ responses: {
1869
+ "200": {
1870
+ description: "Share link created successfully",
1871
+ content: {
1872
+ "application/json": {
1873
+ schema: import_zod2.z.object({
1874
+ shareId: import_zod2.z.string(),
1875
+ shareUrl: import_zod2.z.string(),
1876
+ expiresAt: import_zod2.z.number().optional()
1877
+ })
1878
+ }
1879
+ }
1880
+ }
1881
+ }
1882
+ };
1883
+ async handle(c) {
1884
+ const data = await this.getValidatedData();
1885
+ const bucketName = data.params.bucket;
1886
+ const bucket = c.env[bucketName];
1887
+ if (!bucket) {
1888
+ throw new HTTPException(500, {
1889
+ message: `Bucket binding not found: ${bucketName}`
1890
+ });
1891
+ }
1892
+ const key = decodeURIComponent(escape(atob(data.params.key)));
1893
+ const fileExists = await bucket.head(key);
1894
+ if (!fileExists) {
1895
+ throw new HTTPException(404, {
1896
+ message: `File not found: ${key}`
1897
+ });
1898
+ }
1899
+ let shareId = "";
1900
+ let attempts = 0;
1901
+ const maxAttempts = 5;
1902
+ while (attempts < maxAttempts) {
1903
+ shareId = crypto.randomUUID().replace(/-/g, "").substring(0, 10);
1904
+ const existingShare = await bucket.head(
1905
+ `.r2-explorer/sharable-links/${shareId}.json`
1906
+ );
1907
+ if (!existingShare) {
1908
+ break;
1909
+ }
1910
+ attempts++;
1911
+ }
1912
+ if (attempts === maxAttempts) {
1913
+ throw new HTTPException(500, {
1914
+ message: "Failed to generate unique share ID"
1915
+ });
1916
+ }
1917
+ let passwordHash;
1918
+ if (data.body.password) {
1919
+ const encoder = new TextEncoder();
1920
+ const passwordData = encoder.encode(data.body.password);
1921
+ const hashBuffer = await crypto.subtle.digest("SHA-256", passwordData);
1922
+ passwordHash = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
1923
+ }
1924
+ const expiresAt = data.body.expiresIn ? Date.now() + data.body.expiresIn * 1e3 : void 0;
1925
+ const shareMetadata = {
1926
+ bucket: bucketName,
1927
+ key,
1928
+ expiresAt,
1929
+ passwordHash,
1930
+ maxDownloads: data.body.maxDownloads,
1931
+ currentDownloads: 0,
1932
+ createdBy: c.get("authentication_username") || "anonymous",
1933
+ createdAt: Date.now()
1934
+ };
1935
+ await bucket.put(
1936
+ `.r2-explorer/sharable-links/${shareId}.json`,
1937
+ JSON.stringify(shareMetadata),
1938
+ {
1939
+ httpMetadata: { contentType: "application/json" },
1940
+ customMetadata: {
1941
+ targetBucket: bucketName,
1942
+ targetKey: key
1943
+ }
1944
+ }
1945
+ );
1946
+ const shareUrl = `${new URL(c.req.url).origin}/share/${shareId}`;
1947
+ return c.json({
1948
+ shareId,
1949
+ shareUrl,
1950
+ expiresAt
1951
+ });
1952
+ }
1953
+ };
1954
+
1955
+ // src/modules/buckets/deleteObject.ts
1956
+ var import_chanfana3 = require("chanfana");
1957
+ var import_zod3 = require("zod");
1958
+ var DeleteObject = class extends import_chanfana3.OpenAPIRoute {
1959
+ schema = {
1960
+ operationId: "post-bucket-delete-object",
1961
+ tags: ["Buckets"],
1962
+ summary: "Delete object",
1963
+ request: {
1964
+ params: import_zod3.z.object({
1965
+ bucket: import_zod3.z.string()
1966
+ }),
1967
+ body: {
1968
+ content: {
1969
+ "application/json": {
1970
+ schema: import_zod3.z.object({
1971
+ key: import_zod3.z.string().describe("base64 encoded file key")
1907
1972
  })
1908
1973
  }
1909
1974
  }
@@ -1925,24 +1990,73 @@ var DeleteObject = class extends import_chanfana2.OpenAPIRoute {
1925
1990
  }
1926
1991
  };
1927
1992
 
1993
+ // src/modules/buckets/deleteShareLink.ts
1994
+ var import_chanfana4 = require("chanfana");
1995
+ var import_zod4 = require("zod");
1996
+ var DeleteShareLink = class extends import_chanfana4.OpenAPIRoute {
1997
+ schema = {
1998
+ operationId: "delete-bucket-share-link",
1999
+ tags: ["Buckets"],
2000
+ summary: "Revoke/delete a share link",
2001
+ request: {
2002
+ params: import_zod4.z.object({
2003
+ bucket: import_zod4.z.string(),
2004
+ shareId: import_zod4.z.string().describe("10-character share ID")
2005
+ })
2006
+ },
2007
+ responses: {
2008
+ "200": {
2009
+ description: "Share link deleted successfully",
2010
+ content: {
2011
+ "application/json": {
2012
+ schema: import_zod4.z.object({
2013
+ success: import_zod4.z.boolean()
2014
+ })
2015
+ }
2016
+ }
2017
+ }
2018
+ }
2019
+ };
2020
+ async handle(c) {
2021
+ const data = await this.getValidatedData();
2022
+ const bucketName = data.params.bucket;
2023
+ const bucket = c.env[bucketName];
2024
+ if (!bucket) {
2025
+ throw new HTTPException(500, {
2026
+ message: `Bucket binding not found: ${bucketName}`
2027
+ });
2028
+ }
2029
+ const shareId = data.params.shareId;
2030
+ const shareKey = `.r2-explorer/sharable-links/${shareId}.json`;
2031
+ const shareExists = await bucket.head(shareKey);
2032
+ if (!shareExists) {
2033
+ throw new HTTPException(404, {
2034
+ message: `Share link not found: ${shareId}`
2035
+ });
2036
+ }
2037
+ await bucket.delete(shareKey);
2038
+ return c.json({ success: true });
2039
+ }
2040
+ };
2041
+
1928
2042
  // src/modules/buckets/getObject.ts
1929
- var import_chanfana3 = require("chanfana");
1930
- var import_zod3 = require("zod");
1931
- var GetObject = class extends import_chanfana3.OpenAPIRoute {
2043
+ var import_chanfana5 = require("chanfana");
2044
+ var import_zod5 = require("zod");
2045
+ var GetObject = class extends import_chanfana5.OpenAPIRoute {
1932
2046
  schema = {
1933
2047
  operationId: "get-bucket-object",
1934
2048
  tags: ["Buckets"],
1935
2049
  summary: "Get Object",
1936
2050
  request: {
1937
- params: import_zod3.z.object({
1938
- bucket: import_zod3.z.string(),
1939
- key: import_zod3.z.string().describe("base64 encoded file key")
2051
+ params: import_zod5.z.object({
2052
+ bucket: import_zod5.z.string(),
2053
+ key: import_zod5.z.string().describe("base64 encoded file key")
1940
2054
  })
1941
2055
  },
1942
2056
  responses: {
1943
2057
  "200": {
1944
2058
  description: "File binary",
1945
- schema: import_zod3.z.string().openapi({ format: "binary" })
2059
+ schema: import_zod5.z.string().openapi({ format: "binary" })
1946
2060
  }
1947
2061
  }
1948
2062
  };
@@ -1958,10 +2072,14 @@ var GetObject = class extends import_chanfana3.OpenAPIRoute {
1958
2072
  let filePath;
1959
2073
  try {
1960
2074
  filePath = decodeURIComponent(escape(atob(data.params.key)));
1961
- } catch (e) {
1962
- filePath = decodeURIComponent(
1963
- escape(atob(decodeURIComponent(data.params.key)))
1964
- );
2075
+ } catch {
2076
+ try {
2077
+ filePath = decodeURIComponent(
2078
+ escape(atob(decodeURIComponent(data.params.key)))
2079
+ );
2080
+ } catch {
2081
+ filePath = escape(atob(decodeURIComponent(data.params.key)));
2082
+ }
1965
2083
  }
1966
2084
  const object = await bucket.get(filePath);
1967
2085
  if (object === null) {
@@ -1970,6 +2088,7 @@ var GetObject = class extends import_chanfana3.OpenAPIRoute {
1970
2088
  const headers = new Headers();
1971
2089
  object.writeHttpMetadata(headers);
1972
2090
  headers.set("etag", object.httpEtag);
2091
+ headers.set("content-length", object.size.toString());
1973
2092
  headers.set(
1974
2093
  "Content-Disposition",
1975
2094
  `attachment; filename="${filePath.split("/").pop()}"`
@@ -1980,18 +2099,137 @@ var GetObject = class extends import_chanfana3.OpenAPIRoute {
1980
2099
  }
1981
2100
  };
1982
2101
 
2102
+ // src/modules/buckets/getShareLink.ts
2103
+ var import_chanfana6 = require("chanfana");
2104
+ var import_zod6 = require("zod");
2105
+ var GetShareLink = class extends import_chanfana6.OpenAPIRoute {
2106
+ schema = {
2107
+ operationId: "get-share-link",
2108
+ tags: ["Sharing"],
2109
+ summary: "Access shared file",
2110
+ security: [],
2111
+ // Public endpoint - no auth required
2112
+ request: {
2113
+ params: import_zod6.z.object({
2114
+ shareId: import_zod6.z.string().describe("10-character share ID")
2115
+ }),
2116
+ query: import_zod6.z.object({
2117
+ password: import_zod6.z.string().optional().describe("Password for protected shares")
2118
+ })
2119
+ },
2120
+ responses: {
2121
+ "200": {
2122
+ description: "File retrieved successfully"
2123
+ },
2124
+ "401": {
2125
+ description: "Password required or incorrect"
2126
+ },
2127
+ "404": {
2128
+ description: "Share link not found"
2129
+ },
2130
+ "410": {
2131
+ description: "Share link expired"
2132
+ },
2133
+ "403": {
2134
+ description: "Download limit reached"
2135
+ }
2136
+ }
2137
+ };
2138
+ async handle(c) {
2139
+ const data = await this.getValidatedData();
2140
+ const shareId = data.params.shareId;
2141
+ let shareMetadata = null;
2142
+ let bucket = null;
2143
+ for (const key in c.env) {
2144
+ if (key === "ASSETS") continue;
2145
+ const currentBucket = c.env[key];
2146
+ if (!currentBucket.get || typeof currentBucket.get !== "function") {
2147
+ continue;
2148
+ }
2149
+ const shareObject = await currentBucket.get(
2150
+ `.r2-explorer/sharable-links/${shareId}.json`
2151
+ );
2152
+ if (shareObject) {
2153
+ shareMetadata = JSON.parse(await shareObject.text());
2154
+ bucket = currentBucket;
2155
+ break;
2156
+ }
2157
+ }
2158
+ if (!shareMetadata || !bucket) {
2159
+ throw new HTTPException(404, {
2160
+ message: "Share link not found"
2161
+ });
2162
+ }
2163
+ if (shareMetadata.expiresAt && Date.now() > shareMetadata.expiresAt) {
2164
+ throw new HTTPException(410, {
2165
+ message: "Share link expired"
2166
+ });
2167
+ }
2168
+ if (shareMetadata.maxDownloads && shareMetadata.currentDownloads >= shareMetadata.maxDownloads) {
2169
+ throw new HTTPException(403, {
2170
+ message: "Download limit reached"
2171
+ });
2172
+ }
2173
+ if (shareMetadata.passwordHash) {
2174
+ if (!data.query.password) {
2175
+ throw new HTTPException(401, {
2176
+ message: "Password required"
2177
+ });
2178
+ }
2179
+ const encoder = new TextEncoder();
2180
+ const passwordData = encoder.encode(data.query.password);
2181
+ const hashBuffer = await crypto.subtle.digest("SHA-256", passwordData);
2182
+ const providedHash = Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
2183
+ if (providedHash !== shareMetadata.passwordHash) {
2184
+ throw new HTTPException(401, {
2185
+ message: "Incorrect password"
2186
+ });
2187
+ }
2188
+ }
2189
+ shareMetadata.currentDownloads++;
2190
+ await bucket.put(
2191
+ `.r2-explorer/sharable-links/${shareId}.json`,
2192
+ JSON.stringify(shareMetadata),
2193
+ {
2194
+ httpMetadata: { contentType: "application/json" },
2195
+ customMetadata: {
2196
+ targetBucket: shareMetadata.bucket,
2197
+ targetKey: shareMetadata.key
2198
+ }
2199
+ }
2200
+ );
2201
+ const file = await bucket.get(shareMetadata.key);
2202
+ if (!file) {
2203
+ throw new HTTPException(404, {
2204
+ message: "Shared file not found"
2205
+ });
2206
+ }
2207
+ const headers = new Headers();
2208
+ file.writeHttpMetadata(headers);
2209
+ headers.set("etag", file.httpEtag);
2210
+ const fileName = shareMetadata.key.split("/").pop() || "download";
2211
+ headers.set(
2212
+ "Content-Disposition",
2213
+ `attachment; filename="${encodeURIComponent(fileName)}"`
2214
+ );
2215
+ return new Response(file.body, {
2216
+ headers
2217
+ });
2218
+ }
2219
+ };
2220
+
1983
2221
  // src/modules/buckets/headObject.ts
1984
- var import_chanfana4 = require("chanfana");
1985
- var import_zod4 = require("zod");
1986
- var HeadObject = class extends import_chanfana4.OpenAPIRoute {
2222
+ var import_chanfana7 = require("chanfana");
2223
+ var import_zod7 = require("zod");
2224
+ var HeadObject = class extends import_chanfana7.OpenAPIRoute {
1987
2225
  schema = {
1988
2226
  operationId: "Head-bucket-object",
1989
2227
  tags: ["Buckets"],
1990
2228
  summary: "Get Object",
1991
2229
  request: {
1992
- params: import_zod4.z.object({
1993
- bucket: import_zod4.z.string(),
1994
- key: import_zod4.z.string().describe("base64 encoded file key")
2230
+ params: import_zod7.z.object({
2231
+ bucket: import_zod7.z.string(),
2232
+ key: import_zod7.z.string().describe("base64 encoded file key")
1995
2233
  })
1996
2234
  }
1997
2235
  };
@@ -2021,24 +2259,24 @@ var HeadObject = class extends import_chanfana4.OpenAPIRoute {
2021
2259
  };
2022
2260
 
2023
2261
  // src/modules/buckets/listObjects.ts
2024
- var import_chanfana5 = require("chanfana");
2025
- var import_zod5 = require("zod");
2026
- var ListObjects = class extends import_chanfana5.OpenAPIRoute {
2262
+ var import_chanfana8 = require("chanfana");
2263
+ var import_zod8 = require("zod");
2264
+ var ListObjects = class extends import_chanfana8.OpenAPIRoute {
2027
2265
  schema = {
2028
2266
  operationId: "get-bucket-list-objects",
2029
2267
  tags: ["Buckets"],
2030
2268
  summary: "List objects",
2031
2269
  request: {
2032
- params: import_zod5.z.object({
2033
- bucket: import_zod5.z.string()
2270
+ params: import_zod8.z.object({
2271
+ bucket: import_zod8.z.string()
2034
2272
  }),
2035
- query: import_zod5.z.object({
2036
- limit: import_zod5.z.number().optional(),
2037
- prefix: import_zod5.z.string().nullable().optional().describe("base64 encoded prefix"),
2038
- cursor: import_zod5.z.string().nullable().optional(),
2039
- delimiter: import_zod5.z.string().nullable().optional(),
2040
- startAfter: import_zod5.z.string().nullable().optional(),
2041
- include: import_zod5.z.enum(["httpMetadata", "customMetadata"]).array().optional()
2273
+ query: import_zod8.z.object({
2274
+ limit: import_zod8.z.number().optional(),
2275
+ prefix: import_zod8.z.string().nullable().optional().describe("base64 encoded prefix"),
2276
+ cursor: import_zod8.z.string().nullable().optional(),
2277
+ delimiter: import_zod8.z.string().nullable().optional(),
2278
+ startAfter: import_zod8.z.string().nullable().optional(),
2279
+ include: import_zod8.z.enum(["httpMetadata", "customMetadata"]).array().optional()
2042
2280
  })
2043
2281
  }
2044
2282
  };
@@ -2064,24 +2302,102 @@ var ListObjects = class extends import_chanfana5.OpenAPIRoute {
2064
2302
  }
2065
2303
  };
2066
2304
 
2305
+ // src/modules/buckets/listShares.ts
2306
+ var import_chanfana9 = require("chanfana");
2307
+ var import_zod9 = require("zod");
2308
+ var ListShares = class extends import_chanfana9.OpenAPIRoute {
2309
+ schema = {
2310
+ operationId: "get-bucket-shares",
2311
+ tags: ["Buckets"],
2312
+ summary: "List all active shares in bucket",
2313
+ request: {
2314
+ params: import_zod9.z.object({
2315
+ bucket: import_zod9.z.string()
2316
+ })
2317
+ },
2318
+ responses: {
2319
+ "200": {
2320
+ description: "List of active shares",
2321
+ content: {
2322
+ "application/json": {
2323
+ schema: import_zod9.z.object({
2324
+ shares: import_zod9.z.array(
2325
+ import_zod9.z.object({
2326
+ shareId: import_zod9.z.string(),
2327
+ shareUrl: import_zod9.z.string(),
2328
+ key: import_zod9.z.string(),
2329
+ expiresAt: import_zod9.z.number().optional(),
2330
+ maxDownloads: import_zod9.z.number().optional(),
2331
+ currentDownloads: import_zod9.z.number(),
2332
+ createdBy: import_zod9.z.string(),
2333
+ createdAt: import_zod9.z.number(),
2334
+ isExpired: import_zod9.z.boolean(),
2335
+ hasPassword: import_zod9.z.boolean()
2336
+ })
2337
+ )
2338
+ })
2339
+ }
2340
+ }
2341
+ }
2342
+ }
2343
+ };
2344
+ async handle(c) {
2345
+ const data = await this.getValidatedData();
2346
+ const bucketName = data.params.bucket;
2347
+ const bucket = c.env[bucketName];
2348
+ if (!bucket) {
2349
+ throw new HTTPException(500, {
2350
+ message: `Bucket binding not found: ${bucketName}`
2351
+ });
2352
+ }
2353
+ const sharesList = await bucket.list({
2354
+ prefix: ".r2-explorer/sharable-links/"
2355
+ });
2356
+ const shares = [];
2357
+ const now = Date.now();
2358
+ const origin = new URL(c.req.url).origin;
2359
+ for (const obj of sharesList.objects) {
2360
+ const shareId = obj.key.split("/").pop()?.replace(".json", "");
2361
+ if (!shareId) continue;
2362
+ const shareObject = await bucket.get(obj.key);
2363
+ if (!shareObject) continue;
2364
+ const metadata = JSON.parse(await shareObject.text());
2365
+ const isExpired = !!(metadata.expiresAt && now > metadata.expiresAt);
2366
+ shares.push({
2367
+ shareId,
2368
+ shareUrl: `${origin}/share/${shareId}`,
2369
+ key: metadata.key,
2370
+ expiresAt: metadata.expiresAt,
2371
+ maxDownloads: metadata.maxDownloads,
2372
+ currentDownloads: metadata.currentDownloads || 0,
2373
+ createdBy: metadata.createdBy,
2374
+ createdAt: metadata.createdAt,
2375
+ isExpired,
2376
+ hasPassword: !!metadata.passwordHash
2377
+ });
2378
+ }
2379
+ return c.json({ shares });
2380
+ }
2381
+ };
2382
+
2067
2383
  // src/modules/buckets/moveObject.ts
2068
- var import_chanfana6 = require("chanfana");
2069
- var import_zod6 = require("zod");
2070
- var MoveObject = class extends import_chanfana6.OpenAPIRoute {
2384
+ var import_chanfana10 = require("chanfana");
2385
+ var import_zod10 = require("zod");
2386
+ var MoveObject = class extends import_chanfana10.OpenAPIRoute {
2071
2387
  schema = {
2072
2388
  operationId: "post-bucket-move-object",
2073
2389
  tags: ["Buckets"],
2074
2390
  summary: "Move object",
2075
2391
  request: {
2076
- params: import_zod6.z.object({
2077
- bucket: import_zod6.z.string()
2392
+ params: import_zod10.z.object({
2393
+ bucket: import_zod10.z.string()
2078
2394
  }),
2079
2395
  body: {
2080
2396
  content: {
2081
2397
  "application/json": {
2082
- schema: import_zod6.z.object({
2083
- oldKey: import_zod6.z.string().describe("base64 encoded file key"),
2084
- newKey: import_zod6.z.string().describe("base64 encoded file key")
2398
+ schema: import_zod10.z.object({
2399
+ oldKey: import_zod10.z.string().describe("base64 encoded file key"),
2400
+ newKey: import_zod10.z.string().describe("base64 encoded file key")
2085
2401
  })
2086
2402
  }
2087
2403
  }
@@ -2115,27 +2431,27 @@ var MoveObject = class extends import_chanfana6.OpenAPIRoute {
2115
2431
  };
2116
2432
 
2117
2433
  // src/modules/buckets/multipart/completeUpload.ts
2118
- var import_chanfana7 = require("chanfana");
2119
- var import_zod7 = require("zod");
2120
- var CompleteUpload = class extends import_chanfana7.OpenAPIRoute {
2434
+ var import_chanfana11 = require("chanfana");
2435
+ var import_zod11 = require("zod");
2436
+ var CompleteUpload = class extends import_chanfana11.OpenAPIRoute {
2121
2437
  schema = {
2122
2438
  operationId: "post-multipart-complete-upload",
2123
2439
  tags: ["Multipart"],
2124
2440
  summary: "Complete upload",
2125
2441
  request: {
2126
- params: import_zod7.z.object({
2127
- bucket: import_zod7.z.string()
2442
+ params: import_zod11.z.object({
2443
+ bucket: import_zod11.z.string()
2128
2444
  }),
2129
2445
  body: {
2130
2446
  content: {
2131
2447
  "application/json": {
2132
- schema: import_zod7.z.object({
2133
- uploadId: import_zod7.z.string(),
2134
- parts: import_zod7.z.object({
2135
- etag: import_zod7.z.string(),
2136
- partNumber: import_zod7.z.number().int()
2448
+ schema: import_zod11.z.object({
2449
+ uploadId: import_zod11.z.string(),
2450
+ parts: import_zod11.z.object({
2451
+ etag: import_zod11.z.string(),
2452
+ partNumber: import_zod11.z.number().int()
2137
2453
  }).array(),
2138
- key: import_zod7.z.string().describe("base64 encoded file key")
2454
+ key: import_zod11.z.string().describe("base64 encoded file key")
2139
2455
  })
2140
2456
  }
2141
2457
  }
@@ -2145,6 +2461,12 @@ var CompleteUpload = class extends import_chanfana7.OpenAPIRoute {
2145
2461
  async handle(c) {
2146
2462
  const data = await this.getValidatedData();
2147
2463
  const bucket = c.env[data.params.bucket];
2464
+ if (!bucket || typeof bucket !== "object" || !("resumeMultipartUpload" in bucket)) {
2465
+ return Response.json(
2466
+ { error: `Bucket binding not found: ${data.params.bucket}` },
2467
+ { status: 500 }
2468
+ );
2469
+ }
2148
2470
  const uploadId = data.body.uploadId;
2149
2471
  const key = decodeURIComponent(escape(atob(data.body.key)));
2150
2472
  const parts = data.body.parts;
@@ -2162,27 +2484,33 @@ var CompleteUpload = class extends import_chanfana7.OpenAPIRoute {
2162
2484
  };
2163
2485
 
2164
2486
  // src/modules/buckets/multipart/createUpload.ts
2165
- var import_chanfana8 = require("chanfana");
2166
- var import_zod8 = require("zod");
2167
- var CreateUpload = class extends import_chanfana8.OpenAPIRoute {
2487
+ var import_chanfana12 = require("chanfana");
2488
+ var import_zod12 = require("zod");
2489
+ var CreateUpload = class extends import_chanfana12.OpenAPIRoute {
2168
2490
  schema = {
2169
2491
  operationId: "post-multipart-create-upload",
2170
2492
  tags: ["Multipart"],
2171
2493
  summary: "Create upload",
2172
2494
  request: {
2173
- params: import_zod8.z.object({
2174
- bucket: import_zod8.z.string()
2495
+ params: import_zod12.z.object({
2496
+ bucket: import_zod12.z.string()
2175
2497
  }),
2176
- query: import_zod8.z.object({
2177
- key: import_zod8.z.string().describe("base64 encoded file key"),
2178
- customMetadata: import_zod8.z.string().nullable().optional().describe("base64 encoded json string"),
2179
- httpMetadata: import_zod8.z.string().nullable().optional().describe("base64 encoded json string")
2498
+ query: import_zod12.z.object({
2499
+ key: import_zod12.z.string().describe("base64 encoded file key"),
2500
+ customMetadata: import_zod12.z.string().nullable().optional().describe("base64 encoded json string"),
2501
+ httpMetadata: import_zod12.z.string().nullable().optional().describe("base64 encoded json string")
2180
2502
  })
2181
2503
  }
2182
2504
  };
2183
2505
  async handle(c) {
2184
2506
  const data = await this.getValidatedData();
2185
2507
  const bucket = c.env[data.params.bucket];
2508
+ if (!bucket || typeof bucket !== "object" || !("createMultipartUpload" in bucket)) {
2509
+ return Response.json(
2510
+ { error: `Bucket binding not found: ${data.params.bucket}` },
2511
+ { status: 500 }
2512
+ );
2513
+ }
2186
2514
  const key = decodeURIComponent(escape(atob(data.query.key)));
2187
2515
  let customMetadata = void 0;
2188
2516
  if (data.query.customMetadata) {
@@ -2204,9 +2532,9 @@ var CreateUpload = class extends import_chanfana8.OpenAPIRoute {
2204
2532
  };
2205
2533
 
2206
2534
  // src/modules/buckets/multipart/partUpload.ts
2207
- var import_chanfana9 = require("chanfana");
2208
- var import_zod9 = require("zod");
2209
- var PartUpload = class extends import_chanfana9.OpenAPIRoute {
2535
+ var import_chanfana13 = require("chanfana");
2536
+ var import_zod13 = require("zod");
2537
+ var PartUpload = class extends import_chanfana13.OpenAPIRoute {
2210
2538
  schema = {
2211
2539
  operationId: "post-multipart-part-upload",
2212
2540
  tags: ["Multipart"],
@@ -2215,26 +2543,32 @@ var PartUpload = class extends import_chanfana9.OpenAPIRoute {
2215
2543
  body: {
2216
2544
  content: {
2217
2545
  "application/octet-stream": {
2218
- schema: import_zod9.z.object({}).openapi({
2546
+ schema: import_zod13.z.object({}).openapi({
2219
2547
  type: "string",
2220
2548
  format: "binary"
2221
2549
  })
2222
2550
  }
2223
2551
  }
2224
2552
  },
2225
- params: import_zod9.z.object({
2226
- bucket: import_zod9.z.string()
2553
+ params: import_zod13.z.object({
2554
+ bucket: import_zod13.z.string()
2227
2555
  }),
2228
- query: import_zod9.z.object({
2229
- key: import_zod9.z.string().describe("base64 encoded file key"),
2230
- uploadId: import_zod9.z.string(),
2231
- partNumber: import_zod9.z.number().int()
2556
+ query: import_zod13.z.object({
2557
+ key: import_zod13.z.string().describe("base64 encoded file key"),
2558
+ uploadId: import_zod13.z.string(),
2559
+ partNumber: import_zod13.z.number().int()
2232
2560
  })
2233
2561
  }
2234
2562
  };
2235
2563
  async handle(c) {
2236
2564
  const data = await this.getValidatedData();
2237
2565
  const bucket = c.env[data.params.bucket];
2566
+ if (!bucket || typeof bucket !== "object" || !("resumeMultipartUpload" in bucket)) {
2567
+ return Response.json(
2568
+ { error: `Bucket binding not found: ${data.params.bucket}` },
2569
+ { status: 500 }
2570
+ );
2571
+ }
2238
2572
  const key = decodeURIComponent(escape(atob(data.query.key)));
2239
2573
  const multipartUpload = bucket.resumeMultipartUpload(
2240
2574
  key,
@@ -2252,24 +2586,24 @@ var PartUpload = class extends import_chanfana9.OpenAPIRoute {
2252
2586
  };
2253
2587
 
2254
2588
  // src/modules/buckets/putMetadata.ts
2255
- var import_chanfana10 = require("chanfana");
2256
- var import_zod10 = require("zod");
2257
- var PutMetadata = class extends import_chanfana10.OpenAPIRoute {
2589
+ var import_chanfana14 = require("chanfana");
2590
+ var import_zod14 = require("zod");
2591
+ var PutMetadata = class extends import_chanfana14.OpenAPIRoute {
2258
2592
  schema = {
2259
2593
  operationId: "post-bucket-put-object-metadata",
2260
2594
  tags: ["Buckets"],
2261
2595
  summary: "Update object metadata",
2262
2596
  request: {
2263
- params: import_zod10.z.object({
2264
- bucket: import_zod10.z.string(),
2265
- key: import_zod10.z.string().describe("base64 encoded file key")
2597
+ params: import_zod14.z.object({
2598
+ bucket: import_zod14.z.string(),
2599
+ key: import_zod14.z.string().describe("base64 encoded file key")
2266
2600
  }),
2267
2601
  body: {
2268
2602
  content: {
2269
2603
  "application/json": {
2270
- schema: import_zod10.z.object({
2271
- customMetadata: import_zod10.z.record(import_zod10.z.string(), import_zod10.z.any()),
2272
- httpMetadata: import_zod10.z.record(import_zod10.z.string(), import_zod10.z.any())
2604
+ schema: import_zod14.z.object({
2605
+ customMetadata: import_zod14.z.record(import_zod14.z.string(), import_zod14.z.any()),
2606
+ httpMetadata: import_zod14.z.record(import_zod14.z.string(), import_zod14.z.any())
2273
2607
  }).openapi("Object metadata")
2274
2608
  }
2275
2609
  }
@@ -2305,9 +2639,9 @@ var PutMetadata = class extends import_chanfana10.OpenAPIRoute {
2305
2639
  };
2306
2640
 
2307
2641
  // src/modules/buckets/putObject.ts
2308
- var import_chanfana11 = require("chanfana");
2309
- var import_zod11 = require("zod");
2310
- var PutObject = class extends import_chanfana11.OpenAPIRoute {
2642
+ var import_chanfana15 = require("chanfana");
2643
+ var import_zod15 = require("zod");
2644
+ var PutObject = class extends import_chanfana15.OpenAPIRoute {
2311
2645
  schema = {
2312
2646
  operationId: "post-bucket-upload-object",
2313
2647
  tags: ["Buckets"],
@@ -2316,20 +2650,20 @@ var PutObject = class extends import_chanfana11.OpenAPIRoute {
2316
2650
  body: {
2317
2651
  content: {
2318
2652
  "application/octet-stream": {
2319
- schema: import_zod11.z.object({}).openapi({
2653
+ schema: import_zod15.z.object({}).openapi({
2320
2654
  type: "string",
2321
2655
  format: "binary"
2322
2656
  })
2323
2657
  }
2324
2658
  }
2325
2659
  },
2326
- params: import_zod11.z.object({
2327
- bucket: import_zod11.z.string()
2660
+ params: import_zod15.z.object({
2661
+ bucket: import_zod15.z.string()
2328
2662
  }),
2329
- query: import_zod11.z.object({
2330
- key: import_zod11.z.string().describe("base64 encoded file key"),
2331
- customMetadata: import_zod11.z.string().nullable().optional().describe("base64 encoded json string"),
2332
- httpMetadata: import_zod11.z.string().nullable().optional().describe("base64 encoded json string")
2663
+ query: import_zod15.z.object({
2664
+ key: import_zod15.z.string().describe("base64 encoded file key"),
2665
+ customMetadata: import_zod15.z.string().nullable().optional().describe("base64 encoded json string"),
2666
+ httpMetadata: import_zod15.z.string().nullable().optional().describe("base64 encoded json string")
2333
2667
  })
2334
2668
  }
2335
2669
  };
@@ -2414,7 +2748,7 @@ async function streamToArrayBuffer(stream, streamSize) {
2414
2748
  }
2415
2749
  async function receiveEmail(event, env, ctx, config) {
2416
2750
  let bucket;
2417
- if (config?.emailRouting?.targetBucket && env[config.emailRouting.targetBucket]) {
2751
+ if (config?.emailRouting && typeof config.emailRouting === "object" && config.emailRouting.targetBucket && env[config.emailRouting.targetBucket]) {
2418
2752
  bucket = env[config.emailRouting.targetBucket];
2419
2753
  }
2420
2754
  if (!bucket) {
@@ -2454,9 +2788,9 @@ async function receiveEmail(event, env, ctx, config) {
2454
2788
  }
2455
2789
 
2456
2790
  // src/modules/emails/sendEmail.ts
2457
- var import_chanfana12 = require("chanfana");
2458
- var import_zod12 = require("zod");
2459
- var SendEmail = class extends import_chanfana12.OpenAPIRoute {
2791
+ var import_chanfana16 = require("chanfana");
2792
+ var import_zod16 = require("zod");
2793
+ var SendEmail = class extends import_chanfana16.OpenAPIRoute {
2460
2794
  schema = {
2461
2795
  operationId: "post-email-send",
2462
2796
  tags: ["Emails"],
@@ -2465,17 +2799,17 @@ var SendEmail = class extends import_chanfana12.OpenAPIRoute {
2465
2799
  body: {
2466
2800
  content: {
2467
2801
  "application/json": {
2468
- schema: import_zod12.z.object({
2469
- subject: (0, import_chanfana12.Str)({ example: "Look! No servers" }),
2470
- from: import_zod12.z.object({
2471
- email: (0, import_chanfana12.Str)({ example: "sender@example.com" }),
2472
- name: (0, import_chanfana12.Str)({ example: "Workers - MailChannels integration" })
2802
+ schema: import_zod16.z.object({
2803
+ subject: (0, import_chanfana16.Str)({ example: "Look! No servers" }),
2804
+ from: import_zod16.z.object({
2805
+ email: (0, import_chanfana16.Str)({ example: "sender@example.com" }),
2806
+ name: (0, import_chanfana16.Str)({ example: "Workers - MailChannels integration" })
2473
2807
  }),
2474
- to: import_zod12.z.object({
2475
- email: (0, import_chanfana12.Str)({ example: "test@example.com" }),
2476
- name: (0, import_chanfana12.Str)({ example: "Test Recipient" })
2808
+ to: import_zod16.z.object({
2809
+ email: (0, import_chanfana16.Str)({ example: "test@example.com" }),
2810
+ name: (0, import_chanfana16.Str)({ example: "Test Recipient" })
2477
2811
  }).array(),
2478
- content: import_zod12.z.object({}).catchall(import_zod12.z.string())
2812
+ content: import_zod16.z.object({}).catchall(import_zod16.z.string())
2479
2813
  })
2480
2814
  }
2481
2815
  }
@@ -2493,8 +2827,8 @@ var SendEmail = class extends import_chanfana12.OpenAPIRoute {
2493
2827
  };
2494
2828
 
2495
2829
  // src/modules/server/getInfo.ts
2496
- var import_chanfana13 = require("chanfana");
2497
- var GetInfo = class extends import_chanfana13.OpenAPIRoute {
2830
+ var import_chanfana17 = require("chanfana");
2831
+ var GetInfo = class extends import_chanfana17.OpenAPIRoute {
2498
2832
  schema = {
2499
2833
  operationId: "get-server-info",
2500
2834
  tags: ["Server"],
@@ -2504,7 +2838,7 @@ var GetInfo = class extends import_chanfana13.OpenAPIRoute {
2504
2838
  const { basicAuth: basicAuth2, ...config } = c.get("config");
2505
2839
  const buckets = [];
2506
2840
  for (const [key, value] of Object.entries(c.env)) {
2507
- if (value.get && value.put && value.get.toString().includes("function") && value.put.toString().includes("function")) {
2841
+ if (value && typeof value === "object" && "get" in value && "put" in value && "list" in value && typeof value.get === "function" && typeof value.put === "function" && typeof value.list === "function") {
2508
2842
  buckets.push({ name: key });
2509
2843
  }
2510
2844
  }
@@ -2522,7 +2856,7 @@ var GetInfo = class extends import_chanfana13.OpenAPIRoute {
2522
2856
 
2523
2857
  // src/index.ts
2524
2858
  function R2Explorer(config) {
2525
- (0, import_chanfana14.extendZodWithOpenApi)(import_zod13.z);
2859
+ (0, import_chanfana18.extendZodWithOpenApi)(import_zod17.z);
2526
2860
  config = config || {};
2527
2861
  if (config.readonly !== false) config.readonly = true;
2528
2862
  const openapiSchema = {
@@ -2544,7 +2878,7 @@ function R2Explorer(config) {
2544
2878
  c.set("config", config);
2545
2879
  await next();
2546
2880
  });
2547
- const openapi = (0, import_chanfana14.fromHono)(app, {
2881
+ const openapi = (0, import_chanfana18.fromHono)(app, {
2548
2882
  schema: openapiSchema,
2549
2883
  raiseUnknownParameters: true,
2550
2884
  generateOperationIds: false
@@ -2597,9 +2931,13 @@ function R2Explorer(config) {
2597
2931
  openapi.post("/api/buckets/:bucket/delete", DeleteObject);
2598
2932
  openapi.on("head", "/api/buckets/:bucket/:key", HeadObject);
2599
2933
  openapi.get("/api/buckets/:bucket/:key/head", HeadObject);
2934
+ openapi.post("/api/buckets/:bucket/:key/share", CreateShareLink);
2935
+ openapi.get("/api/buckets/:bucket/shares", ListShares);
2936
+ openapi.delete("/api/buckets/:bucket/share/:shareId", DeleteShareLink);
2600
2937
  openapi.get("/api/buckets/:bucket/:key", GetObject);
2601
2938
  openapi.post("/api/buckets/:bucket/:key", PutMetadata);
2602
2939
  openapi.post("/api/emails/send", SendEmail);
2940
+ openapi.get("/share/:shareId", GetShareLink);
2603
2941
  openapi.get("/", dashboardIndex);
2604
2942
  openapi.get("*", dashboardRedirect);
2605
2943
  app.all(