cf-nix-cache 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,192 +1,129 @@
1
1
  import { DurableObject, WorkerEntrypoint, WorkflowEntrypoint } from "cloudflare:workers";
2
- var compose = (middleware, onError, onNotFound) => {
3
- return (context, next) => {
4
- let index = -1;
5
- return dispatch(0);
6
- async function dispatch(i) {
7
- if (i <= index) {
8
- throw new Error("next() called multiple times");
9
- }
10
- index = i;
11
- let res;
12
- let isError = false;
13
- let handler;
14
- if (middleware[i]) {
15
- handler = middleware[i][0][0];
16
- context.req.routeIndex = i;
17
- } else {
18
- handler = i === middleware.length && next || void 0;
19
- }
20
- if (handler) {
21
- try {
22
- res = await handler(context, () => dispatch(i + 1));
23
- } catch (err) {
24
- if (err instanceof Error && onError) {
25
- context.error = err;
26
- res = await onError(err, context);
27
- isError = true;
28
- } else {
29
- throw err;
30
- }
31
- }
32
- } else {
33
- if (context.finalized === false && onNotFound) {
34
- res = await onNotFound(context);
35
- }
36
- }
37
- if (res && (context.finalized === false || isError)) {
38
- context.res = res;
39
- }
40
- return context;
41
- }
42
- };
43
- };
44
- var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
45
- var bufferToFormData = (arrayBuffer, contentType) => {
46
- const response = new Response(arrayBuffer, {
47
- headers: {
48
- // Normalize the media type (case-insensitive) while keeping parameters like the boundary
49
- "Content-Type": contentType.replace(/^[^;]+/, (mediaType) => mediaType.toLowerCase())
50
- }
51
- });
52
- return response.formData();
2
+ const GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
3
+ const bufferToFormData = (arrayBuffer, contentType) => {
4
+ return new Response(arrayBuffer, { headers: { "Content-Type": contentType.replace(/^[^;]+/, (mediaType) => mediaType.toLowerCase()) } }).formData();
53
5
  };
54
- var isRawRequest = (request) => "headers" in request;
55
- var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
6
+ const MAX_NESTED_OBJECTS = 1e4;
7
+ const isRawRequest = (request) => "headers" in request;
8
+ const parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
56
9
  const { all = false, dot = false } = options;
57
- const headers = isRawRequest(request) ? request.headers : request.raw.headers;
58
- const contentType = headers.get("Content-Type");
59
- const mediaType = contentType?.split(";")[0].trim().toLowerCase();
60
- if (mediaType === "multipart/form-data" || mediaType === "application/x-www-form-urlencoded") {
61
- return parseFormData(request, { all, dot });
62
- }
10
+ const mediaType = (isRawRequest(request) ? request.headers : request.raw.headers).get("Content-Type")?.split(";")[0].trim().toLowerCase();
11
+ if (mediaType === "multipart/form-data" || mediaType === "application/x-www-form-urlencoded") return parseFormData(request, {
12
+ all,
13
+ dot
14
+ });
63
15
  return {};
64
16
  };
65
17
  async function parseFormData(request, options) {
66
- if (!isRawRequest(request) && request.bodyCache.formData) {
67
- return convertFormDataToBodyData(
68
- await request.bodyCache.formData,
69
- options
70
- );
71
- }
18
+ if (!isRawRequest(request) && request.bodyCache.formData) return convertFormDataToBodyData(await request.bodyCache.formData, options);
72
19
  const headers = isRawRequest(request) ? request.headers : request.raw.headers;
73
20
  const arrayBuffer = await request.arrayBuffer();
74
21
  const formDataPromise = bufferToFormData(arrayBuffer, headers.get("Content-Type") || "");
75
- if (!isRawRequest(request)) {
76
- request.bodyCache.formData = formDataPromise;
77
- }
22
+ if (!isRawRequest(request)) request.bodyCache.formData = formDataPromise;
78
23
  const formData = await formDataPromise;
79
- if (formData) {
80
- return convertFormDataToBodyData(formData, options);
81
- }
24
+ if (formData) return convertFormDataToBodyData(formData, options);
82
25
  return {};
83
26
  }
84
27
  function convertFormDataToBodyData(formData, options) {
85
28
  const form = /* @__PURE__ */ Object.create(null);
29
+ const nestingState = { count: 0 };
86
30
  formData.forEach((value, key) => {
87
- const shouldParseAllValues = options.all || key.endsWith("[]");
88
- if (!shouldParseAllValues) {
89
- form[key] = value;
90
- } else {
91
- handleParsingAllValues(form, key, value);
31
+ if (!(options.all || key.endsWith("[]"))) form[key] = value;
32
+ else handleParsingAllValues(form, key, value);
33
+ });
34
+ if (options.dot) Object.entries(form).forEach(([key, value]) => {
35
+ if (key.includes(".")) {
36
+ handleParsingNestedValues(form, key, value, nestingState);
37
+ delete form[key];
92
38
  }
93
39
  });
94
- if (options.dot) {
95
- Object.entries(form).forEach(([key, value]) => {
96
- const shouldParseDotValues = key.includes(".");
97
- if (shouldParseDotValues) {
98
- handleParsingNestedValues(form, key, value);
99
- delete form[key];
100
- }
101
- });
102
- }
103
40
  return form;
104
41
  }
105
- var handleParsingAllValues = (form, key, value) => {
42
+ const handleParsingAllValues = (form, key, value) => {
106
43
  if (form[key] !== void 0) {
107
- if (Array.isArray(form[key])) {
108
- form[key].push(value);
109
- } else {
110
- form[key] = [form[key], value];
111
- }
112
- } else {
113
- if (!key.endsWith("[]")) {
114
- form[key] = value;
115
- } else {
116
- form[key] = [value];
117
- }
118
- }
44
+ if (Array.isArray(form[key])) form[key].push(value);
45
+ else form[key] = [form[key], value];
46
+ } else if (!key.endsWith("[]")) form[key] = value;
47
+ else form[key] = [value];
119
48
  };
120
- var handleParsingNestedValues = (form, key, value) => {
121
- if (/(?:^|\.)__proto__\./.test(key)) {
122
- return;
123
- }
49
+ const handleParsingNestedValues = (form, key, value, state2) => {
50
+ if (/(?:^|\.)__proto__\./.test(key)) return;
124
51
  let nestedForm = form;
125
- const keys = key.split(".");
52
+ const keys = key.split(".", 34);
53
+ if (keys.length > 33) throwNestingLimitExceeded();
126
54
  keys.forEach((key2, index) => {
127
- if (index === keys.length - 1) {
128
- nestedForm[key2] = value;
129
- } else {
55
+ if (index === keys.length - 1) nestedForm[key2] = value;
56
+ else {
130
57
  if (!nestedForm[key2] || typeof nestedForm[key2] !== "object" || Array.isArray(nestedForm[key2]) || nestedForm[key2] instanceof File) {
58
+ if (state2.count++ >= MAX_NESTED_OBJECTS) throwNestingLimitExceeded();
131
59
  nestedForm[key2] = /* @__PURE__ */ Object.create(null);
132
60
  }
133
61
  nestedForm = nestedForm[key2];
134
62
  }
135
63
  });
136
64
  };
137
- var splitPath = (path) => {
65
+ const throwNestingLimitExceeded = () => {
66
+ throw new Error("Nesting limit exceeded");
67
+ };
68
+ const splitPath = (path) => {
138
69
  const paths = path.split("/");
139
- if (paths[0] === "") {
140
- paths.shift();
141
- }
70
+ if (paths[0] === "") paths.shift();
142
71
  return paths;
143
72
  };
144
- var splitRoutingPath = (routePath) => {
73
+ const splitRoutingPath = (routePath) => {
145
74
  const { groups, path } = extractGroupsFromPath(routePath);
146
75
  const paths = splitPath(path);
147
76
  return replaceGroupMarks(paths, groups);
148
77
  };
149
- var extractGroupsFromPath = (path) => {
78
+ const extractGroupsFromPath = (path) => {
150
79
  const groups = [];
151
80
  path = path.replace(/\{[^}]+\}/g, (match2, index) => {
152
81
  const mark = `@${index}`;
153
82
  groups.push([mark, match2]);
154
83
  return mark;
155
84
  });
156
- return { groups, path };
85
+ return {
86
+ groups,
87
+ path
88
+ };
157
89
  };
158
- var replaceGroupMarks = (paths, groups) => {
90
+ const replaceGroupMarks = (paths, groups) => {
159
91
  for (let i = groups.length - 1; i >= 0; i--) {
160
92
  const [mark] = groups[i];
161
- for (let j = paths.length - 1; j >= 0; j--) {
162
- if (paths[j].includes(mark)) {
163
- paths[j] = paths[j].replace(mark, groups[i][1]);
164
- break;
165
- }
93
+ for (let j = paths.length - 1; j >= 0; j--) if (paths[j].includes(mark)) {
94
+ paths[j] = paths[j].replace(mark, groups[i][1]);
95
+ break;
166
96
  }
167
97
  }
168
98
  return paths;
169
99
  };
170
- var patternCache = {};
171
- var getPattern = (label, next) => {
172
- if (label === "*") {
173
- return "*";
174
- }
100
+ const patternCache = {};
101
+ const getPattern = (label, next) => {
102
+ if (label === "*") return "*";
175
103
  const match2 = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
176
104
  if (match2) {
177
105
  const cacheKey = `${label}#${next}`;
178
106
  if (!patternCache[cacheKey]) {
179
- if (match2[2]) {
180
- patternCache[cacheKey] = next && next[0] !== ":" && next[0] !== "*" ? [cacheKey, match2[1], new RegExp(`^${match2[2]}(?=/${next})`)] : [label, match2[1], new RegExp(`^${match2[2]}$`)];
181
- } else {
182
- patternCache[cacheKey] = [label, match2[1], true];
183
- }
107
+ if (match2[2]) patternCache[cacheKey] = next && next[0] !== ":" && next[0] !== "*" ? [
108
+ cacheKey,
109
+ match2[1],
110
+ new RegExp(`^${match2[2]}(?=/${next})`)
111
+ ] : [
112
+ label,
113
+ match2[1],
114
+ new RegExp(`^${match2[2]}$`)
115
+ ];
116
+ else patternCache[cacheKey] = [
117
+ label,
118
+ match2[1],
119
+ true
120
+ ];
184
121
  }
185
122
  return patternCache[cacheKey];
186
123
  }
187
124
  return null;
188
125
  };
189
- var tryDecode = (str, decoder2) => {
126
+ const tryDecode = (str, decoder2) => {
190
127
  try {
191
128
  return decoder2(str);
192
129
  } catch {
@@ -199,8 +136,8 @@ var tryDecode = (str, decoder2) => {
199
136
  });
200
137
  }
201
138
  };
202
- var tryDecodeURI = (str) => tryDecode(str, decodeURI);
203
- var getPath$1 = (request) => {
139
+ const tryDecodeURI = (str) => tryDecode(str, decodeURI);
140
+ const getPath$1 = (request) => {
204
141
  const url = request.url;
205
142
  const start = url.indexOf("/", url.indexOf(":") + 4);
206
143
  let i = start;
@@ -212,81 +149,66 @@ var getPath$1 = (request) => {
212
149
  const end = queryIndex === -1 ? hashIndex === -1 ? void 0 : hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
213
150
  const path = url.slice(start, end);
214
151
  return tryDecodeURI(path.includes("%25") ? path.replace(/%25/g, "%2525") : path);
215
- } else if (charCode === 63 || charCode === 35) {
216
- break;
217
- }
152
+ } else if (charCode === 63 || charCode === 35) break;
218
153
  }
219
154
  return url.slice(start, i);
220
155
  };
221
- var getPathNoStrict = (request) => {
156
+ const getPathNoStrict = (request) => {
222
157
  const result = getPath$1(request);
223
158
  return result.length > 1 && result.at(-1) === "/" ? result.slice(0, -1) : result;
224
159
  };
225
- var mergePath = (base, sub, ...rest) => {
226
- if (rest.length) {
227
- sub = mergePath(sub, ...rest);
228
- }
160
+ const mergePath = (base, sub, ...rest) => {
161
+ if (rest.length) sub = mergePath(sub, ...rest);
229
162
  return `${base?.[0] === "/" ? "" : "/"}${base}${sub === "/" ? "" : `${base?.at(-1) === "/" ? "" : "/"}${sub?.[0] === "/" ? sub.slice(1) : sub}`}`;
230
163
  };
231
- var checkOptionalParameter = (path) => {
232
- if (path.charCodeAt(path.length - 1) !== 63 || !path.includes(":")) {
233
- return null;
234
- }
164
+ const checkOptionalParameter = (path) => {
165
+ if (path.charCodeAt(path.length - 1) !== 63 || !path.includes(":")) return null;
235
166
  const segments = path.split("/");
236
167
  const results = [];
237
168
  let basePath = "";
238
169
  segments.forEach((segment) => {
239
- if (segment !== "" && !/\:/.test(segment)) {
240
- basePath += "/" + segment;
241
- } else if (/\:/.test(segment)) {
242
- if (/\?/.test(segment)) {
243
- if (results.length === 0 && basePath === "") {
244
- results.push("/");
245
- } else {
246
- results.push(basePath);
247
- }
248
- const optionalSegment = segment.replace("?", "");
170
+ if (segment !== "" && !/\:/.test(segment)) basePath += "/" + segment;
171
+ else if (/\:/.test(segment)) {
172
+ if (segment.charCodeAt(segment.length - 1) === 63) {
173
+ if (results.length === 0 && basePath === "") results.push("/");
174
+ else results.push(basePath);
175
+ const optionalSegment = segment.slice(0, -1);
249
176
  basePath += "/" + optionalSegment;
250
177
  results.push(basePath);
251
- } else {
252
- basePath += "/" + segment;
253
- }
178
+ } else basePath += "/" + segment;
254
179
  }
255
180
  });
256
181
  return results.filter((v, i, a) => a.indexOf(v) === i);
257
182
  };
258
- var tryDecodeURIComponent = (str) => str.indexOf("%") !== -1 ? tryDecode(str, decodeURIComponent_) : str;
259
- var _decodeURI = (value) => {
260
- if (value.indexOf("+") !== -1) {
261
- value = value.replace(/\+/g, " ");
262
- }
183
+ const tryDecodeURIComponent = (str) => str.indexOf("%") !== -1 ? tryDecode(str, decodeURIComponent_) : str;
184
+ const _decodeURI = (value) => {
185
+ if (value.indexOf("+") !== -1) value = value.replace(/\+/g, " ");
263
186
  return tryDecodeURIComponent(value);
264
187
  };
265
- var _getQueryParam = (url, key, multiple) => {
188
+ const _getQueryParam = (url, key, multiple) => {
189
+ const hashIndex = url.indexOf("#", 8);
190
+ if (hashIndex !== -1) url = url.slice(0, hashIndex);
266
191
  let encoded;
267
192
  if (!multiple && key && key.indexOf("%") === -1 && key.indexOf("+") === -1) {
268
- let keyIndex2 = url.indexOf("?", 8);
269
- if (keyIndex2 === -1) {
270
- return void 0;
271
- }
272
- if (!url.startsWith(key, keyIndex2 + 1)) {
273
- keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
274
- }
193
+ const queryIndex = url.indexOf("?", 8);
194
+ let keyIndex2 = queryIndex;
195
+ if (keyIndex2 === -1) return;
196
+ if (!url.startsWith(key, keyIndex2 + 1)) keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
275
197
  while (keyIndex2 !== -1) {
276
198
  const trailingKeyCode = url.charCodeAt(keyIndex2 + key.length + 1);
277
- if (trailingKeyCode === 61) {
278
- const valueIndex = keyIndex2 + key.length + 2;
279
- const endIndex = url.indexOf("&", valueIndex);
280
- return _decodeURI(url.slice(valueIndex, endIndex === -1 ? void 0 : endIndex));
281
- } else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) {
199
+ if (trailingKeyCode === 61 || trailingKeyCode === 38 || isNaN(trailingKeyCode)) {
200
+ if (keyIndex2 > queryIndex && /(?:^|&)[^=&]*[%+]/.test(url.slice(queryIndex + 1, keyIndex2))) break;
201
+ if (trailingKeyCode === 61) {
202
+ const valueIndex = keyIndex2 + key.length + 2;
203
+ const endIndex = url.indexOf("&", valueIndex);
204
+ return _decodeURI(url.slice(valueIndex, endIndex === -1 ? void 0 : endIndex));
205
+ }
282
206
  return "";
283
207
  }
284
208
  keyIndex2 = url.indexOf(`&${key}`, keyIndex2 + 1);
285
209
  }
286
210
  encoded = /[%+]/.test(url);
287
- if (!encoded) {
288
- return void 0;
289
- }
211
+ if (!encoded) return;
290
212
  }
291
213
  const results = /* @__PURE__ */ Object.create(null);
292
214
  encoded ??= /[%+]/.test(url);
@@ -294,77 +216,60 @@ var _getQueryParam = (url, key, multiple) => {
294
216
  while (keyIndex !== -1) {
295
217
  const nextKeyIndex = url.indexOf("&", keyIndex + 1);
296
218
  let valueIndex = url.indexOf("=", keyIndex);
297
- if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) {
298
- valueIndex = -1;
299
- }
300
- let name = url.slice(
301
- keyIndex + 1,
302
- valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex
303
- );
304
- if (encoded) {
305
- name = _decodeURI(name);
306
- }
219
+ if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) valueIndex = -1;
220
+ let name = url.slice(keyIndex + 1, valueIndex === -1 ? nextKeyIndex === -1 ? void 0 : nextKeyIndex : valueIndex);
221
+ if (encoded) name = _decodeURI(name);
307
222
  keyIndex = nextKeyIndex;
308
- if (name === "") {
309
- continue;
310
- }
223
+ if (name === "") continue;
311
224
  let value;
312
- if (valueIndex === -1) {
313
- value = "";
314
- } else {
225
+ if (valueIndex === -1) value = "";
226
+ else {
315
227
  value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? void 0 : nextKeyIndex);
316
- if (encoded) {
317
- value = _decodeURI(value);
318
- }
228
+ if (encoded) value = _decodeURI(value);
319
229
  }
320
230
  if (multiple) {
321
- if (!(results[name] && Array.isArray(results[name]))) {
322
- results[name] = [];
323
- }
231
+ if (!(results[name] && Array.isArray(results[name]))) results[name] = [];
324
232
  results[name].push(value);
325
- } else {
326
- results[name] ??= value;
327
- }
233
+ } else results[name] ??= value;
328
234
  }
329
235
  return key ? results[key] : results;
330
236
  };
331
- var getQueryParam = _getQueryParam;
332
- var getQueryParams = (url, key) => {
237
+ const getQueryParam = _getQueryParam;
238
+ const getQueryParams = (url, key) => {
333
239
  return _getQueryParam(url, key, true);
334
240
  };
335
- var decodeURIComponent_ = decodeURIComponent;
241
+ const decodeURIComponent_ = decodeURIComponent;
336
242
  var HonoRequest = class {
337
243
  /**
338
- * `.raw` can get the raw Request object.
339
- *
340
- * @see {@link https://hono.dev/docs/api/request#raw}
341
- *
342
- * @example
343
- * ```ts
344
- * // For Cloudflare Workers
345
- * app.post('/', async (c) => {
346
- * const metadata = c.req.raw.cf?.hostMetadata?
347
- * ...
348
- * })
349
- * ```
350
- */
244
+ * `.raw` can get the raw Request object.
245
+ *
246
+ * @see {@link https://hono.dev/docs/api/request#raw}
247
+ *
248
+ * @example
249
+ * ```ts
250
+ * // For Cloudflare Workers
251
+ * app.post('/', async (c) => {
252
+ * const metadata = c.req.raw.cf?.hostMetadata?
253
+ * ...
254
+ * })
255
+ * ```
256
+ */
351
257
  raw;
352
258
  #validatedData;
353
- // Short name of validatedData
354
259
  #matchResult;
355
260
  routeIndex = 0;
356
261
  /**
357
- * `.path` can get the pathname of the request.
358
- *
359
- * @see {@link https://hono.dev/docs/api/request#path}
360
- *
361
- * @example
362
- * ```ts
363
- * app.get('/about/me', (c) => {
364
- * const pathname = c.req.path // `/about/me`
365
- * })
366
- * ```
367
- */
262
+ * `.path` can get the pathname of the request.
263
+ *
264
+ * @see {@link https://hono.dev/docs/api/request#path}
265
+ *
266
+ * @example
267
+ * ```ts
268
+ * app.get('/about/me', (c) => {
269
+ * const pathname = c.req.path // `/about/me`
270
+ * })
271
+ * ```
272
+ */
368
273
  path;
369
274
  bodyCache = {};
370
275
  constructor(request, path = "/", matchResult = [[]]) {
@@ -376,18 +281,16 @@ var HonoRequest = class {
376
281
  return key ? this.#getDecodedParam(key) : this.#getAllDecodedParams();
377
282
  }
378
283
  #getDecodedParam(key) {
379
- const paramKey = this.#matchResult[0][this.routeIndex][1][key];
284
+ const paramKey = this.#matchResult[0][this.routeIndex]?.[1][key];
380
285
  const param = this.#getParamValue(paramKey);
381
286
  return param && tryDecodeURIComponent(param);
382
287
  }
383
288
  #getAllDecodedParams() {
384
289
  const decoded = {};
385
- const keys = Object.keys(this.#matchResult[0][this.routeIndex][1]);
290
+ const keys = Object.keys(this.#matchResult[0][this.routeIndex]?.[1] ?? {});
386
291
  for (const key of keys) {
387
292
  const value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]);
388
- if (value !== void 0) {
389
- decoded[key] = tryDecodeURIComponent(value);
390
- }
293
+ if (value !== void 0) decoded[key] = tryDecodeURIComponent(value);
391
294
  }
392
295
  return decoded;
393
296
  }
@@ -401,9 +304,7 @@ var HonoRequest = class {
401
304
  return getQueryParams(this.url, key);
402
305
  }
403
306
  header(name) {
404
- if (name) {
405
- return this.raw.headers.get(name) ?? void 0;
406
- }
307
+ if (name) return this.raw.headers.get(name) ?? void 0;
407
308
  const headerData = /* @__PURE__ */ Object.create(null);
408
309
  this.raw.headers.forEach((value, key) => {
409
310
  headerData[key] = value;
@@ -416,111 +317,106 @@ var HonoRequest = class {
416
317
  #cachedBody = (key) => {
417
318
  const { bodyCache, raw } = this;
418
319
  const cachedBody = bodyCache[key];
419
- if (cachedBody) {
420
- return cachedBody;
421
- }
422
- for (const anyCachedKey in bodyCache) {
423
- return bodyCache[anyCachedKey].then((body) => {
424
- if (anyCachedKey === "json") {
425
- body = JSON.stringify(body);
426
- }
427
- return new Response(body)[key]();
428
- });
429
- }
320
+ if (cachedBody) return cachedBody;
321
+ for (const anyCachedKey in bodyCache) return bodyCache[anyCachedKey].then((body) => {
322
+ if (anyCachedKey === "json") body = JSON.stringify(body);
323
+ const contentType = anyCachedKey === "formData" ? void 0 : raw.headers.get("content-type");
324
+ return new Response(body, { headers: contentType ? { "Content-Type": contentType } : void 0 })[key]();
325
+ });
430
326
  return bodyCache[key] = raw[key]();
431
327
  };
432
328
  /**
433
- * `.json()` can parse Request body of type `application/json`
434
- *
435
- * @see {@link https://hono.dev/docs/api/request#json}
436
- *
437
- * @example
438
- * ```ts
439
- * app.post('/entry', async (c) => {
440
- * const body = await c.req.json()
441
- * })
442
- * ```
443
- */
329
+ * `.json()` can parse Request body of type `application/json`
330
+ *
331
+ * @see {@link https://hono.dev/docs/api/request#json}
332
+ *
333
+ * @example
334
+ * ```ts
335
+ * app.post('/entry', async (c) => {
336
+ * const body = await c.req.json()
337
+ * })
338
+ * ```
339
+ */
444
340
  json() {
445
341
  return this.#cachedBody("text").then((text) => JSON.parse(text));
446
342
  }
447
343
  /**
448
- * `.text()` can parse Request body of type `text/plain`
449
- *
450
- * @see {@link https://hono.dev/docs/api/request#text}
451
- *
452
- * @example
453
- * ```ts
454
- * app.post('/entry', async (c) => {
455
- * const body = await c.req.text()
456
- * })
457
- * ```
458
- */
344
+ * `.text()` can parse Request body of type `text/plain`
345
+ *
346
+ * @see {@link https://hono.dev/docs/api/request#text}
347
+ *
348
+ * @example
349
+ * ```ts
350
+ * app.post('/entry', async (c) => {
351
+ * const body = await c.req.text()
352
+ * })
353
+ * ```
354
+ */
459
355
  text() {
460
356
  return this.#cachedBody("text");
461
357
  }
462
358
  /**
463
- * `.arrayBuffer()` parse Request body as an `ArrayBuffer`
464
- *
465
- * @see {@link https://hono.dev/docs/api/request#arraybuffer}
466
- *
467
- * @example
468
- * ```ts
469
- * app.post('/entry', async (c) => {
470
- * const body = await c.req.arrayBuffer()
471
- * })
472
- * ```
473
- */
359
+ * `.arrayBuffer()` parse Request body as an `ArrayBuffer`
360
+ *
361
+ * @see {@link https://hono.dev/docs/api/request#arraybuffer}
362
+ *
363
+ * @example
364
+ * ```ts
365
+ * app.post('/entry', async (c) => {
366
+ * const body = await c.req.arrayBuffer()
367
+ * })
368
+ * ```
369
+ */
474
370
  arrayBuffer() {
475
371
  return this.#cachedBody("arrayBuffer");
476
372
  }
477
373
  /**
478
- * `.bytes()` parses the request body as a `Uint8Array`.
479
- *
480
- * @see {@link https://hono.dev/docs/api/request#bytes}
481
- *
482
- * @example
483
- * ```ts
484
- * app.post('/entry', async (c) => {
485
- * const body = await c.req.bytes()
486
- * })
487
- * ```
488
- */
374
+ * `.bytes()` parses the request body as a `Uint8Array`.
375
+ *
376
+ * @see {@link https://hono.dev/docs/api/request#bytes}
377
+ *
378
+ * @example
379
+ * ```ts
380
+ * app.post('/entry', async (c) => {
381
+ * const body = await c.req.bytes()
382
+ * })
383
+ * ```
384
+ */
489
385
  bytes() {
490
386
  return this.#cachedBody("arrayBuffer").then((buffer) => new Uint8Array(buffer));
491
387
  }
492
388
  /**
493
- * Parses the request body as a `Blob`.
494
- * @example
495
- * ```ts
496
- * app.post('/entry', async (c) => {
497
- * const body = await c.req.blob();
498
- * });
499
- * ```
500
- * @see https://hono.dev/docs/api/request#blob
501
- */
389
+ * Parses the request body as a `Blob`.
390
+ * @example
391
+ * ```ts
392
+ * app.post('/entry', async (c) => {
393
+ * const body = await c.req.blob();
394
+ * });
395
+ * ```
396
+ * @see https://hono.dev/docs/api/request#blob
397
+ */
502
398
  blob() {
503
399
  return this.#cachedBody("blob");
504
400
  }
505
401
  /**
506
- * Parses the request body as `FormData`.
507
- * @example
508
- * ```ts
509
- * app.post('/entry', async (c) => {
510
- * const body = await c.req.formData();
511
- * });
512
- * ```
513
- * @see https://hono.dev/docs/api/request#formdata
514
- */
402
+ * Parses the request body as `FormData`.
403
+ * @example
404
+ * ```ts
405
+ * app.post('/entry', async (c) => {
406
+ * const body = await c.req.formData();
407
+ * });
408
+ * ```
409
+ * @see https://hono.dev/docs/api/request#formdata
410
+ */
515
411
  formData() {
516
412
  return this.#cachedBody("formData");
517
413
  }
518
414
  /**
519
- * Adds validated data to the request.
520
- *
521
- * @param target - The target of the validation.
522
- * @param data - The validated data to add.
523
- */
415
+ * Adds validated data to the request.
416
+ *
417
+ * @param target - The target of the validation.
418
+ * @param data - The validated data to add.
419
+ */
524
420
  addValidatedData(target, data) {
525
421
  (this.#validatedData ??= {})[target] = data;
526
422
  }
@@ -528,33 +424,33 @@ var HonoRequest = class {
528
424
  return this.#validatedData?.[target];
529
425
  }
530
426
  /**
531
- * `.url()` can get the request url strings.
532
- *
533
- * @see {@link https://hono.dev/docs/api/request#url}
534
- *
535
- * @example
536
- * ```ts
537
- * app.get('/about/me', (c) => {
538
- * const url = c.req.url // `http://localhost:8787/about/me`
539
- * ...
540
- * })
541
- * ```
542
- */
427
+ * `.url` can get the request url strings.
428
+ *
429
+ * @see {@link https://hono.dev/docs/api/request#url}
430
+ *
431
+ * @example
432
+ * ```ts
433
+ * app.get('/about/me', (c) => {
434
+ * const url = c.req.url // `http://localhost:8787/about/me`
435
+ * ...
436
+ * })
437
+ * ```
438
+ */
543
439
  get url() {
544
440
  return this.raw.url;
545
441
  }
546
442
  /**
547
- * `.method()` can get the method name of the request.
548
- *
549
- * @see {@link https://hono.dev/docs/api/request#method}
550
- *
551
- * @example
552
- * ```ts
553
- * app.get('/about/me', (c) => {
554
- * const method = c.req.method // `GET`
555
- * })
556
- * ```
557
- */
443
+ * `.method` can get the method name of the request.
444
+ *
445
+ * @see {@link https://hono.dev/docs/api/request#method}
446
+ *
447
+ * @example
448
+ * ```ts
449
+ * app.get('/about/me', (c) => {
450
+ * const method = c.req.method // `GET`
451
+ * })
452
+ * ```
453
+ */
558
454
  get method() {
559
455
  return this.raw.method;
560
456
  }
@@ -562,127 +458,116 @@ var HonoRequest = class {
562
458
  return this.#matchResult;
563
459
  }
564
460
  /**
565
- * `.matchedRoutes()` can return a matched route in the handler
566
- *
567
- * @deprecated
568
- *
569
- * Use matchedRoutes helper defined in "hono/route" instead.
570
- *
571
- * @see {@link https://hono.dev/docs/api/request#matchedroutes}
572
- *
573
- * @example
574
- * ```ts
575
- * app.use('*', async function logger(c, next) {
576
- * await next()
577
- * c.req.matchedRoutes.forEach(({ handler, method, path }, i) => {
578
- * const name = handler.name || (handler.length < 2 ? '[handler]' : '[middleware]')
579
- * console.log(
580
- * method,
581
- * ' ',
582
- * path,
583
- * ' '.repeat(Math.max(10 - path.length, 0)),
584
- * name,
585
- * i === c.req.routeIndex ? '<- respond from here' : ''
586
- * )
587
- * })
588
- * })
589
- * ```
590
- */
461
+ * `.matchedRoutes` can return a matched route in the handler
462
+ *
463
+ * @deprecated
464
+ *
465
+ * Use matchedRoutes helper defined in "hono/route" instead.
466
+ *
467
+ * @see {@link https://hono.dev/docs/api/request#matchedroutes}
468
+ *
469
+ * @example
470
+ * ```ts
471
+ * app.use('*', async function logger(c, next) {
472
+ * await next()
473
+ * c.req.matchedRoutes.forEach(({ handler, method, path }, i) => {
474
+ * const name = handler.name || (handler.length < 2 ? '[handler]' : '[middleware]')
475
+ * console.log(
476
+ * method,
477
+ * ' ',
478
+ * path,
479
+ * ' '.repeat(Math.max(10 - path.length, 0)),
480
+ * name,
481
+ * i === c.req.routeIndex ? '<- respond from here' : ''
482
+ * )
483
+ * })
484
+ * })
485
+ * ```
486
+ */
591
487
  get matchedRoutes() {
592
488
  return this.#matchResult[0].map(([[, route]]) => route);
593
489
  }
594
490
  /**
595
- * `routePath()` can retrieve the path registered within the handler
596
- *
597
- * @deprecated
598
- *
599
- * Use routePath helper defined in "hono/route" instead.
600
- *
601
- * @see {@link https://hono.dev/docs/api/request#routepath}
602
- *
603
- * @example
604
- * ```ts
605
- * app.get('/posts/:id', (c) => {
606
- * return c.json({ path: c.req.routePath })
607
- * })
608
- * ```
609
- */
491
+ * `.routePath` can retrieve the path registered within the handler
492
+ *
493
+ * @deprecated
494
+ *
495
+ * Use routePath helper defined in "hono/route" instead.
496
+ *
497
+ * @see {@link https://hono.dev/docs/api/request#routepath}
498
+ *
499
+ * @example
500
+ * ```ts
501
+ * app.get('/posts/:id', (c) => {
502
+ * return c.json({ path: c.req.routePath })
503
+ * })
504
+ * ```
505
+ */
610
506
  get routePath() {
611
507
  return this.#matchResult[0].map(([[, route]]) => route)[this.routeIndex].path;
612
508
  }
613
509
  };
614
- var HtmlEscapedCallbackPhase = {
510
+ const HtmlEscapedCallbackPhase = {
615
511
  Stringify: 1
616
512
  };
617
- var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => {
513
+ const resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => {
618
514
  if (typeof str === "object" && !(str instanceof String)) {
619
- if (!(str instanceof Promise)) {
620
- str = str.toString();
621
- }
622
- if (str instanceof Promise) {
623
- str = await str;
624
- }
515
+ if (!(str instanceof Promise)) str = str.toString();
516
+ if (str instanceof Promise) str = await str;
625
517
  }
626
518
  const callbacks = str.callbacks;
627
- if (!callbacks?.length) {
628
- return Promise.resolve(str);
629
- }
630
- if (buffer) {
631
- buffer[0] += str;
632
- } else {
633
- buffer = [str];
634
- }
635
- const resStr = Promise.all(callbacks.map((c) => c({ phase, buffer, context }))).then(
636
- (res) => Promise.all(
637
- res.filter(Boolean).map((str2) => resolveCallback(str2, phase, false, context, buffer))
638
- ).then(() => buffer[0])
639
- );
640
- {
641
- return resStr;
642
- }
519
+ if (!callbacks?.length) return Promise.resolve(str);
520
+ if (buffer) buffer[0] += str;
521
+ else buffer = [str];
522
+ const resStr = Promise.all(callbacks.map((c) => c({
523
+ phase,
524
+ buffer,
525
+ context
526
+ }))).then((res) => Promise.all(res.filter(Boolean).map((str2) => resolveCallback(str2, phase, false, context, buffer))).then(() => buffer[0]));
527
+ return resStr;
643
528
  };
644
- var TEXT_PLAIN = "text/plain; charset=UTF-8";
645
- var setDefaultContentType = (contentType, headers) => {
529
+ const TEXT_PLAIN = "text/plain; charset=UTF-8";
530
+ const setDefaultContentType = (contentType, headers) => {
646
531
  return {
647
532
  "Content-Type": contentType,
648
533
  ...headers
649
534
  };
650
535
  };
651
- var createResponseInstance = (body, init) => new Response(body, init);
536
+ const createResponseInstance = (body, init) => new Response(body, init);
652
537
  var Context = class {
653
538
  #rawRequest;
654
539
  #req;
655
540
  /**
656
- * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
657
- *
658
- * @see {@link https://hono.dev/docs/api/context#env}
659
- *
660
- * @example
661
- * ```ts
662
- * // Environment object for Cloudflare Workers
663
- * app.get('*', async c => {
664
- * const counter = c.env.COUNTER
665
- * })
666
- * ```
667
- */
541
+ * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
542
+ *
543
+ * @see {@link https://hono.dev/docs/api/context#env}
544
+ *
545
+ * @example
546
+ * ```ts
547
+ * // Environment object for Cloudflare Workers
548
+ * app.get('*', async c => {
549
+ * const counter = c.env.COUNTER
550
+ * })
551
+ * ```
552
+ */
668
553
  env = {};
669
554
  #var;
670
555
  finalized = false;
671
556
  /**
672
- * `.error` can get the error object from the middleware if the Handler throws an error.
673
- *
674
- * @see {@link https://hono.dev/docs/api/context#error}
675
- *
676
- * @example
677
- * ```ts
678
- * app.use('*', async (c, next) => {
679
- * await next()
680
- * if (c.error) {
681
- * // do something...
682
- * }
683
- * })
684
- * ```
685
- */
557
+ * `.error` can get the error object from the middleware if the Handler throws an error.
558
+ *
559
+ * @see {@link https://hono.dev/docs/api/context#error}
560
+ *
561
+ * @example
562
+ * ```ts
563
+ * app.use('*', async (c, next) => {
564
+ * await next()
565
+ * if (c.error) {
566
+ * // do something...
567
+ * }
568
+ * })
569
+ * ```
570
+ */
686
571
  error;
687
572
  #status;
688
573
  #executionCtx;
@@ -694,11 +579,11 @@ var Context = class {
694
579
  #matchResult;
695
580
  #path;
696
581
  /**
697
- * Creates an instance of the Context class.
698
- *
699
- * @param req - The Request object.
700
- * @param options - Optional configuration options for the context.
701
- */
582
+ * Creates an instance of the Context class.
583
+ *
584
+ * @param req - The Request object.
585
+ * @param options - Optional configuration options for the context.
586
+ */
702
587
  constructor(req, options) {
703
588
  this.#rawRequest = req;
704
589
  if (options) {
@@ -710,241 +595,210 @@ var Context = class {
710
595
  }
711
596
  }
712
597
  /**
713
- * `.req` is the instance of {@link HonoRequest}.
714
- */
598
+ * `.req` is the instance of {@link HonoRequest}.
599
+ */
715
600
  get req() {
716
601
  this.#req ??= new HonoRequest(this.#rawRequest, this.#path, this.#matchResult);
717
602
  return this.#req;
718
603
  }
719
604
  /**
720
- * @see {@link https://hono.dev/docs/api/context#event}
721
- * The FetchEvent associated with the current request.
722
- *
723
- * @throws Will throw an error if the context does not have a FetchEvent.
724
- */
605
+ * @see {@link https://hono.dev/docs/api/context#event}
606
+ * The FetchEvent associated with the current request.
607
+ *
608
+ * @throws Will throw an error if the context does not have a FetchEvent.
609
+ */
725
610
  get event() {
726
- if (this.#executionCtx && "respondWith" in this.#executionCtx) {
727
- return this.#executionCtx;
728
- } else {
729
- throw Error("This context has no FetchEvent");
730
- }
611
+ if (this.#executionCtx && "respondWith" in this.#executionCtx) return this.#executionCtx;
612
+ else throw Error("This context has no FetchEvent");
731
613
  }
732
614
  /**
733
- * @see {@link https://hono.dev/docs/api/context#executionctx}
734
- * The ExecutionContext associated with the current request.
735
- *
736
- * @throws Will throw an error if the context does not have an ExecutionContext.
737
- */
615
+ * @see {@link https://hono.dev/docs/api/context#executionctx}
616
+ * The ExecutionContext associated with the current request.
617
+ *
618
+ * @throws Will throw an error if the context does not have an ExecutionContext.
619
+ */
738
620
  get executionCtx() {
739
- if (this.#executionCtx) {
740
- return this.#executionCtx;
741
- } else {
742
- throw Error("This context has no ExecutionContext");
743
- }
621
+ if (this.#executionCtx) return this.#executionCtx;
622
+ else throw Error("This context has no ExecutionContext");
744
623
  }
745
624
  /**
746
- * @see {@link https://hono.dev/docs/api/context#res}
747
- * The Response object for the current request.
748
- */
625
+ * @see {@link https://hono.dev/docs/api/context#res}
626
+ * The Response object for the current request.
627
+ */
749
628
  get res() {
750
- return this.#res ||= createResponseInstance(null, {
751
- headers: this.#preparedHeaders ??= new Headers()
752
- });
629
+ return this.#res ||= createResponseInstance(null, { headers: this.#preparedHeaders ??= new Headers() });
753
630
  }
754
631
  /**
755
- * Sets the Response object for the current request.
756
- *
757
- * @param _res - The Response object to set.
758
- */
632
+ * Sets the Response object for the current request.
633
+ *
634
+ * @param _res - The Response object to set.
635
+ */
759
636
  set res(_res) {
760
637
  if (this.#res && _res) {
761
638
  _res = createResponseInstance(_res.body, _res);
762
639
  for (const [k, v] of this.#res.headers.entries()) {
763
- if (k === "content-type") {
764
- continue;
765
- }
640
+ if (k === "content-type") continue;
766
641
  if (k === "set-cookie") {
767
642
  const cookies = this.#res.headers.getSetCookie();
768
643
  _res.headers.delete("set-cookie");
769
- for (const cookie of cookies) {
770
- _res.headers.append("set-cookie", cookie);
771
- }
772
- } else {
773
- _res.headers.set(k, v);
774
- }
644
+ for (const cookie of cookies) _res.headers.append("set-cookie", cookie);
645
+ } else _res.headers.set(k, v);
775
646
  }
776
647
  }
777
648
  this.#res = _res;
778
649
  this.finalized = true;
779
650
  }
780
651
  /**
781
- * `.render()` can create a response within a layout.
782
- *
783
- * @see {@link https://hono.dev/docs/api/context#render-setrenderer}
784
- *
785
- * @example
786
- * ```ts
787
- * app.get('/', (c) => {
788
- * return c.render('Hello!')
789
- * })
790
- * ```
791
- */
652
+ * `.render()` can create a response within a layout.
653
+ *
654
+ * @see {@link https://hono.dev/docs/api/context#render-setrenderer}
655
+ *
656
+ * @example
657
+ * ```ts
658
+ * app.get('/', (c) => {
659
+ * return c.render('Hello!')
660
+ * })
661
+ * ```
662
+ */
792
663
  render = (...args) => {
793
664
  this.#renderer ??= (content) => this.html(content);
794
665
  return this.#renderer(...args);
795
666
  };
796
667
  /**
797
- * Sets the layout for the response.
798
- *
799
- * @param layout - The layout to set.
800
- * @returns The layout function.
801
- */
668
+ * Sets the layout for the response.
669
+ *
670
+ * @param layout - The layout to set.
671
+ * @returns The layout function.
672
+ */
802
673
  setLayout = (layout) => this.#layout = layout;
803
674
  /**
804
- * Gets the current layout for the response.
805
- *
806
- * @returns The current layout function.
807
- */
675
+ * Gets the current layout for the response.
676
+ *
677
+ * @returns The current layout function.
678
+ */
808
679
  getLayout = () => this.#layout;
809
680
  /**
810
- * `.setRenderer()` can set the layout in the custom middleware.
811
- *
812
- * @see {@link https://hono.dev/docs/api/context#render-setrenderer}
813
- *
814
- * @example
815
- * ```tsx
816
- * app.use('*', async (c, next) => {
817
- * c.setRenderer((content) => {
818
- * return c.html(
819
- * <html>
820
- * <body>
821
- * <p>{content}</p>
822
- * </body>
823
- * </html>
824
- * )
825
- * })
826
- * await next()
827
- * })
828
- * ```
829
- */
681
+ * `.setRenderer()` can set the layout in the custom middleware.
682
+ *
683
+ * @see {@link https://hono.dev/docs/api/context#render-setrenderer}
684
+ *
685
+ * @example
686
+ * ```tsx
687
+ * app.use('*', async (c, next) => {
688
+ * c.setRenderer((content) => {
689
+ * return c.html(
690
+ * <html>
691
+ * <body>
692
+ * <p>{content}</p>
693
+ * </body>
694
+ * </html>
695
+ * )
696
+ * })
697
+ * await next()
698
+ * })
699
+ * ```
700
+ */
830
701
  setRenderer = (renderer) => {
831
702
  this.#renderer = renderer;
832
703
  };
833
704
  /**
834
- * `.header()` can set headers.
835
- *
836
- * @see {@link https://hono.dev/docs/api/context#header}
837
- *
838
- * @example
839
- * ```ts
840
- * app.get('/welcome', (c) => {
841
- * // Set headers
842
- * c.header('X-Message', 'Hello!')
843
- * c.header('Content-Type', 'text/plain')
844
- *
845
- * return c.body('Thank you for coming')
846
- * })
847
- * ```
848
- */
705
+ * `.header()` can set headers.
706
+ *
707
+ * @see {@link https://hono.dev/docs/api/context#header}
708
+ *
709
+ * @example
710
+ * ```ts
711
+ * app.get('/welcome', (c) => {
712
+ * // Set headers
713
+ * c.header('X-Message', 'Hello!')
714
+ * c.header('Content-Type', 'text/plain')
715
+ *
716
+ * // Append multiple headers using the append option (e.g. Vary)
717
+ * c.header('Vary', 'Accept-Encoding', { append: true })
718
+ * c.header('Vary', 'User-Agent', { append: true })
719
+ *
720
+ * return c.body('Thank you for coming')
721
+ * })
722
+ * ```
723
+ */
849
724
  header = (name, value, options) => {
850
- if (this.finalized) {
851
- this.#res = createResponseInstance(this.#res.body, this.#res);
852
- }
725
+ if (this.finalized) this.#res = createResponseInstance(this.#res.body, this.#res);
853
726
  const headers = this.#res ? this.#res.headers : this.#preparedHeaders ??= new Headers();
854
- if (value === void 0) {
855
- headers.delete(name);
856
- } else if (options?.append) {
857
- headers.append(name, value);
858
- } else {
859
- headers.set(name, value);
860
- }
727
+ if (value === void 0) headers.delete(name);
728
+ else if (options?.append) headers.append(name, value);
729
+ else headers.set(name, value);
861
730
  };
862
731
  status = (status) => {
863
732
  this.#status = status;
864
733
  };
865
734
  /**
866
- * `.set()` can set the value specified by the key.
867
- *
868
- * @see {@link https://hono.dev/docs/api/context#set-get}
869
- *
870
- * @example
871
- * ```ts
872
- * app.use('*', async (c, next) => {
873
- * c.set('message', 'Hono is hot!!')
874
- * await next()
875
- * })
876
- * ```
877
- */
735
+ * `.set()` can set the value specified by the key.
736
+ *
737
+ * @see {@link https://hono.dev/docs/api/context#set-get}
738
+ *
739
+ * @example
740
+ * ```ts
741
+ * app.use('*', async (c, next) => {
742
+ * c.set('message', 'Hono is hot!!')
743
+ * await next()
744
+ * })
745
+ * ```
746
+ */
878
747
  set = (key, value) => {
879
748
  this.#var ??= /* @__PURE__ */ new Map();
880
749
  this.#var.set(key, value);
881
750
  };
882
751
  /**
883
- * `.get()` can use the value specified by the key.
884
- *
885
- * @see {@link https://hono.dev/docs/api/context#set-get}
886
- *
887
- * @example
888
- * ```ts
889
- * app.get('/', (c) => {
890
- * const message = c.get('message')
891
- * return c.text(`The message is "${message}"`)
892
- * })
893
- * ```
894
- */
752
+ * `.get()` can use the value specified by the key.
753
+ *
754
+ * @see {@link https://hono.dev/docs/api/context#set-get}
755
+ *
756
+ * @example
757
+ * ```ts
758
+ * app.get('/', (c) => {
759
+ * const message = c.get('message')
760
+ * return c.text(`The message is "${message}"`)
761
+ * })
762
+ * ```
763
+ */
895
764
  get = (key) => {
896
765
  return this.#var ? this.#var.get(key) : void 0;
897
766
  };
898
767
  /**
899
- * `.var` can access the value of a variable.
900
- *
901
- * @see {@link https://hono.dev/docs/api/context#var}
902
- *
903
- * @example
904
- * ```ts
905
- * const result = c.var.client.oneMethod()
906
- * ```
907
- */
908
- // c.var.propName is a read-only
768
+ * `.var` can access the value of a variable.
769
+ *
770
+ * @see {@link https://hono.dev/docs/api/context#var}
771
+ *
772
+ * @example
773
+ * ```ts
774
+ * const result = c.var.client.oneMethod()
775
+ * ```
776
+ */
909
777
  get var() {
910
- if (!this.#var) {
911
- return {};
912
- }
778
+ if (!this.#var) return {};
913
779
  return Object.fromEntries(this.#var);
914
780
  }
915
781
  #newResponse(data, arg, headers) {
916
782
  let responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders;
917
783
  if (typeof arg === "object" && arg.headers) {
918
784
  responseHeaders ??= new Headers();
919
- for (const [key, value] of new Headers(arg.headers)) {
920
- if (key === "set-cookie") {
921
- responseHeaders.append(key, value);
922
- } else {
923
- responseHeaders.set(key, value);
924
- }
925
- }
785
+ for (const [key, value] of new Headers(arg.headers)) if (key === "set-cookie") responseHeaders.append(key, value);
786
+ else responseHeaders.set(key, value);
926
787
  }
927
788
  if (headers) {
928
789
  if (!responseHeaders) {
929
790
  let count = 0;
930
- for (const k in headers) {
931
- if (++count > 1 || typeof headers[k] !== "string") {
932
- responseHeaders = new Headers();
933
- break;
934
- }
791
+ for (const k in headers) if (++count > 1 || typeof headers[k] !== "string") {
792
+ responseHeaders = new Headers();
793
+ break;
935
794
  }
936
795
  }
937
- if (responseHeaders) {
938
- for (const k in headers) {
939
- const v = headers[k];
940
- if (typeof v === "string") {
941
- responseHeaders.set(k, v);
942
- } else {
943
- responseHeaders.delete(k);
944
- for (const v2 of v) {
945
- responseHeaders.append(k, v2);
946
- }
947
- }
796
+ if (responseHeaders) for (const k in headers) {
797
+ const v = headers[k];
798
+ if (typeof v === "string") responseHeaders.set(k, v);
799
+ else {
800
+ responseHeaders.delete(k);
801
+ for (const v2 of v) responseHeaders.append(k, v2);
948
802
  }
949
803
  }
950
804
  }
@@ -956,122 +810,144 @@ var Context = class {
956
810
  }
957
811
  newResponse = (...args) => this.#newResponse(...args);
958
812
  /**
959
- * `.body()` can return the HTTP response.
960
- * You can set headers with `.header()` and set HTTP status code with `.status`.
961
- * This can also be set in `.text()`, `.json()` and so on.
962
- *
963
- * @see {@link https://hono.dev/docs/api/context#body}
964
- *
965
- * @example
966
- * ```ts
967
- * app.get('/welcome', (c) => {
968
- * // Set headers
969
- * c.header('X-Message', 'Hello!')
970
- * c.header('Content-Type', 'text/plain')
971
- * // Set HTTP status code
972
- * c.status(201)
973
- *
974
- * // Return the response body
975
- * return c.body('Thank you for coming')
976
- * })
977
- * ```
978
- */
813
+ * `.body()` can return the HTTP response.
814
+ * You can set headers with `.header()` and set HTTP status code with `.status`.
815
+ * This can also be set in `.text()`, `.json()` and so on.
816
+ *
817
+ * @see {@link https://hono.dev/docs/api/context#body}
818
+ *
819
+ * @example
820
+ * ```ts
821
+ * app.get('/welcome', (c) => {
822
+ * // Set headers
823
+ * c.header('X-Message', 'Hello!')
824
+ * c.header('Content-Type', 'text/plain')
825
+ * // Set HTTP status code
826
+ * c.status(201)
827
+ *
828
+ * // Return the response body
829
+ * return c.body('Thank you for coming')
830
+ * })
831
+ * ```
832
+ */
979
833
  body = (data, arg, headers) => this.#newResponse(data, arg, headers);
980
834
  /**
981
- * `.text()` can render text as `Content-Type:text/plain`.
982
- *
983
- * @see {@link https://hono.dev/docs/api/context#text}
984
- *
985
- * @example
986
- * ```ts
987
- * app.get('/say', (c) => {
988
- * return c.text('Hello!')
989
- * })
990
- * ```
991
- */
835
+ * `.text()` can render text as `Content-Type:text/plain`.
836
+ *
837
+ * @see {@link https://hono.dev/docs/api/context#text}
838
+ *
839
+ * @example
840
+ * ```ts
841
+ * app.get('/say', (c) => {
842
+ * return c.text('Hello!')
843
+ * })
844
+ * ```
845
+ */
992
846
  text = (text, arg, headers) => {
993
- return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse(
994
- text,
995
- arg,
996
- setDefaultContentType(TEXT_PLAIN, headers)
997
- );
847
+ return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse(text, arg, setDefaultContentType(TEXT_PLAIN, headers));
998
848
  };
999
849
  /**
1000
- * `.json()` can render JSON as `Content-Type:application/json`.
1001
- *
1002
- * @see {@link https://hono.dev/docs/api/context#json}
1003
- *
1004
- * @example
1005
- * ```ts
1006
- * app.get('/api', (c) => {
1007
- * return c.json({ message: 'Hello!' })
1008
- * })
1009
- * ```
1010
- */
850
+ * `.json()` can render JSON as `Content-Type:application/json`.
851
+ *
852
+ * @see {@link https://hono.dev/docs/api/context#json}
853
+ *
854
+ * @example
855
+ * ```ts
856
+ * app.get('/api', (c) => {
857
+ * return c.json({ message: 'Hello!' })
858
+ * })
859
+ * ```
860
+ */
1011
861
  json = (object, arg, headers) => {
1012
- return this.#newResponse(
1013
- JSON.stringify(object),
1014
- arg,
1015
- setDefaultContentType("application/json", headers)
1016
- );
862
+ return this.#newResponse(JSON.stringify(object), arg, setDefaultContentType("application/json", headers));
1017
863
  };
1018
864
  html = (html, arg, headers) => {
1019
865
  const res = (html2) => this.#newResponse(html2, arg, setDefaultContentType("text/html; charset=UTF-8", headers));
1020
866
  return typeof html === "object" ? resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then(res) : res(html);
1021
867
  };
1022
868
  /**
1023
- * `.redirect()` can Redirect, default status code is 302.
1024
- *
1025
- * @see {@link https://hono.dev/docs/api/context#redirect}
1026
- *
1027
- * @example
1028
- * ```ts
1029
- * app.get('/redirect', (c) => {
1030
- * return c.redirect('/')
1031
- * })
1032
- * app.get('/redirect-permanently', (c) => {
1033
- * return c.redirect('/', 301)
1034
- * })
1035
- * ```
1036
- */
869
+ * `.redirect()` can Redirect, default status code is 302.
870
+ *
871
+ * @see {@link https://hono.dev/docs/api/context#redirect}
872
+ *
873
+ * @example
874
+ * ```ts
875
+ * app.get('/redirect', (c) => {
876
+ * return c.redirect('/')
877
+ * })
878
+ * app.get('/redirect-permanently', (c) => {
879
+ * return c.redirect('/', 301)
880
+ * })
881
+ * ```
882
+ */
1037
883
  redirect = (location, status) => {
1038
884
  const locationString = String(location);
1039
- this.header(
1040
- "Location",
1041
- // Multibyes should be encoded
1042
- // eslint-disable-next-line no-control-regex
1043
- !/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString)
1044
- );
885
+ this.header("Location", !/[^\x00-\xFF]/.test(locationString) ? locationString : encodeURI(locationString));
1045
886
  return this.newResponse(null, status ?? 302);
1046
887
  };
1047
888
  /**
1048
- * `.notFound()` can return the Not Found Response.
1049
- *
1050
- * @see {@link https://hono.dev/docs/api/context#notfound}
1051
- *
1052
- * @example
1053
- * ```ts
1054
- * app.get('/notfound', (c) => {
1055
- * return c.notFound()
1056
- * })
1057
- * ```
1058
- */
889
+ * `.notFound()` can return the Not Found Response.
890
+ *
891
+ * @see {@link https://hono.dev/docs/api/context#notfound}
892
+ *
893
+ * @example
894
+ * ```ts
895
+ * app.get('/notfound', (c) => {
896
+ * return c.notFound()
897
+ * })
898
+ * ```
899
+ */
1059
900
  notFound = () => {
1060
901
  this.#notFoundHandler ??= () => createResponseInstance();
1061
902
  return this.#notFoundHandler(this);
1062
903
  };
1063
904
  };
1064
- var METHOD_NAME_ALL = "ALL";
1065
- var METHOD_NAME_ALL_LOWERCASE = "all";
1066
- var METHODS = ["get", "post", "put", "delete", "options", "patch", "query"];
1067
- var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
905
+ const compose = (middleware, onError, onNotFound) => {
906
+ return (context, next) => {
907
+ let index = -1;
908
+ return dispatch(0);
909
+ async function dispatch(i) {
910
+ if (i <= index) throw new Error("next() called multiple times");
911
+ index = i;
912
+ let res;
913
+ let isError = false;
914
+ let handler;
915
+ if (middleware[i]) {
916
+ handler = middleware[i][0][0];
917
+ context.req.routeIndex = i;
918
+ } else handler = i === middleware.length && next || void 0;
919
+ if (handler) try {
920
+ res = await handler(context, () => dispatch(i + 1));
921
+ } catch (err) {
922
+ if (err instanceof Error && onError) {
923
+ context.error = err;
924
+ res = await onError(err, context);
925
+ isError = true;
926
+ } else throw err;
927
+ }
928
+ else if (context.finalized === false && onNotFound) res = await onNotFound(context);
929
+ if (res && (context.finalized === false || isError)) context.res = res;
930
+ return context;
931
+ }
932
+ };
933
+ };
934
+ const METHODS = [
935
+ "get",
936
+ "post",
937
+ "put",
938
+ "delete",
939
+ "options",
940
+ "patch",
941
+ "query"
942
+ ];
943
+ const MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
1068
944
  var UnsupportedPathError = class extends Error {
1069
945
  };
1070
- var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
1071
- var notFoundHandler = (c) => {
946
+ const COMPOSED_HANDLER = "__COMPOSED_HANDLER";
947
+ const notFoundHandler = (c) => {
1072
948
  return c.text("404 Not Found", 404);
1073
949
  };
1074
- var errorHandler = (err, c) => {
950
+ const errorHandler = (err, c) => {
1075
951
  if ("getResponse" in err) {
1076
952
  const res = err.getResponse();
1077
953
  return c.newResponse(res.body, res);
@@ -1079,7 +955,7 @@ var errorHandler = (err, c) => {
1079
955
  console.error(err);
1080
956
  return c.text("Internal Server Error", 500);
1081
957
  };
1082
- var Hono$1 = class _Hono {
958
+ var Hono$1 = class Hono {
1083
959
  get;
1084
960
  post;
1085
961
  put;
@@ -1090,27 +966,19 @@ var Hono$1 = class _Hono {
1090
966
  all;
1091
967
  on;
1092
968
  use;
1093
- /*
1094
- This class is like an abstract class and does not have a router.
1095
- To use it, inherit the class and implement router in the constructor.
1096
- */
1097
969
  router;
1098
970
  getPath;
1099
- // Cannot use `#` because it requires visibility at JavaScript runtime.
1100
971
  _basePath = "/";
1101
972
  #path = "/";
1102
973
  routes = [];
1103
974
  constructor(options = {}) {
1104
- const allMethods = [...METHODS, METHOD_NAME_ALL_LOWERCASE];
1105
- allMethods.forEach((method) => {
975
+ [...METHODS, "all"].forEach((method) => {
1106
976
  this[method] = (args1, ...args) => {
1107
- if (typeof args1 === "string") {
1108
- this.#path = args1;
1109
- } else {
1110
- this.#addRoute(method, this.#path, args1);
1111
- }
977
+ const methodName = method.toUpperCase();
978
+ if (typeof args1 === "string") this.#path = args1;
979
+ else this.#addRoute(methodName, this.#path, args1);
1112
980
  args.forEach((handler) => {
1113
- this.#addRoute(method, this.#path, handler);
981
+ this.#addRoute(methodName, this.#path, handler);
1114
982
  });
1115
983
  return this;
1116
984
  };
@@ -1119,22 +987,20 @@ var Hono$1 = class _Hono {
1119
987
  for (const p of [path].flat()) {
1120
988
  this.#path = p;
1121
989
  for (const m of [method].flat()) {
1122
- handlers.map((handler) => {
1123
- this.#addRoute(m.toUpperCase(), this.#path, handler);
1124
- });
990
+ const methodName = m.toUpperCase();
991
+ for (const handler of handlers) this.#addRoute(methodName, this.#path, handler);
1125
992
  }
1126
993
  }
1127
994
  return this;
1128
995
  };
1129
996
  this.use = (arg1, ...handlers) => {
1130
- if (typeof arg1 === "string") {
1131
- this.#path = arg1;
1132
- } else {
997
+ if (typeof arg1 === "string") this.#path = arg1;
998
+ else {
1133
999
  this.#path = "*";
1134
1000
  handlers.unshift(arg1);
1135
1001
  }
1136
1002
  handlers.forEach((handler) => {
1137
- this.#addRoute(METHOD_NAME_ALL, this.#path, handler);
1003
+ this.#addRoute("ALL", this.#path, handler);
1138
1004
  });
1139
1005
  return this;
1140
1006
  };
@@ -1143,7 +1009,7 @@ var Hono$1 = class _Hono {
1143
1009
  this.getPath = strict ?? true ? options.getPath ?? getPath$1 : getPathNoStrict;
1144
1010
  }
1145
1011
  #clone() {
1146
- const clone = new _Hono({
1012
+ const clone = new Hono({
1147
1013
  router: this.router,
1148
1014
  getPath: this.getPath
1149
1015
  });
@@ -1153,33 +1019,31 @@ var Hono$1 = class _Hono {
1153
1019
  return clone;
1154
1020
  }
1155
1021
  #notFoundHandler = notFoundHandler;
1156
- // Cannot use `#` because it requires visibility at JavaScript runtime.
1157
1022
  errorHandler = errorHandler;
1158
1023
  /**
1159
- * `.route()` allows grouping other Hono instance in routes.
1160
- *
1161
- * @see {@link https://hono.dev/docs/api/routing#grouping}
1162
- *
1163
- * @param {string} path - base Path
1164
- * @param {Hono} app - other Hono instance
1165
- * @returns {Hono} routed Hono instance
1166
- *
1167
- * @example
1168
- * ```ts
1169
- * const app = new Hono()
1170
- * const app2 = new Hono()
1171
- *
1172
- * app2.get("/user", (c) => c.text("user"))
1173
- * app.route("/api", app2) // GET /api/user
1174
- * ```
1175
- */
1024
+ * `.route()` allows grouping other Hono instance in routes.
1025
+ *
1026
+ * @see {@link https://hono.dev/docs/api/routing#grouping}
1027
+ *
1028
+ * @param {string} path - base Path
1029
+ * @param {Hono} app - other Hono instance
1030
+ * @returns {Hono} routed Hono instance
1031
+ *
1032
+ * @example
1033
+ * ```ts
1034
+ * const app = new Hono()
1035
+ * const app2 = new Hono()
1036
+ *
1037
+ * app2.get("/user", (c) => c.text("user"))
1038
+ * app.route("/api", app2) // GET /api/user
1039
+ * ```
1040
+ */
1176
1041
  route(path, app2) {
1177
1042
  const subApp = this.basePath(path);
1178
1043
  app2.routes.map((r) => {
1179
1044
  let handler;
1180
- if (app2.errorHandler === errorHandler) {
1181
- handler = r.handler;
1182
- } else {
1045
+ if (app2.errorHandler === errorHandler) handler = r.handler;
1046
+ else {
1183
1047
  handler = async (c, next) => (await compose([], app2.errorHandler)(c, () => r.handler(c, next))).res;
1184
1048
  handler[COMPOSED_HANDLER] = r.handler;
1185
1049
  }
@@ -1188,107 +1052,105 @@ var Hono$1 = class _Hono {
1188
1052
  return this;
1189
1053
  }
1190
1054
  /**
1191
- * `.basePath()` allows base paths to be specified.
1192
- *
1193
- * @see {@link https://hono.dev/docs/api/routing#base-path}
1194
- *
1195
- * @param {string} path - base Path
1196
- * @returns {Hono} changed Hono instance
1197
- *
1198
- * @example
1199
- * ```ts
1200
- * const api = new Hono().basePath('/api')
1201
- * ```
1202
- */
1055
+ * `.basePath()` allows base paths to be specified.
1056
+ *
1057
+ * @see {@link https://hono.dev/docs/api/routing#base-path}
1058
+ *
1059
+ * @param {string} path - base Path
1060
+ * @returns {Hono} changed Hono instance
1061
+ *
1062
+ * @example
1063
+ * ```ts
1064
+ * const api = new Hono().basePath('/api')
1065
+ * ```
1066
+ */
1203
1067
  basePath(path) {
1204
1068
  const subApp = this.#clone();
1205
1069
  subApp._basePath = mergePath(this._basePath, path);
1206
1070
  return subApp;
1207
1071
  }
1208
1072
  /**
1209
- * `.onError()` handles an error and returns a customized Response.
1210
- *
1211
- * @see {@link https://hono.dev/docs/api/hono#error-handling}
1212
- *
1213
- * @param {ErrorHandler} handler - request Handler for error
1214
- * @returns {Hono} changed Hono instance
1215
- *
1216
- * @example
1217
- * ```ts
1218
- * app.onError((err, c) => {
1219
- * console.error(`${err}`)
1220
- * return c.text('Custom Error Message', 500)
1221
- * })
1222
- * ```
1223
- */
1073
+ * `.onError()` handles an error and returns a customized Response.
1074
+ *
1075
+ * @see {@link https://hono.dev/docs/api/hono#error-handling}
1076
+ *
1077
+ * @param {ErrorHandler} handler - request Handler for error
1078
+ * @returns {Hono} changed Hono instance
1079
+ *
1080
+ * @example
1081
+ * ```ts
1082
+ * app.onError((err, c) => {
1083
+ * console.error(`${err}`)
1084
+ * return c.text('Custom Error Message', 500)
1085
+ * })
1086
+ * ```
1087
+ */
1224
1088
  onError = (handler) => {
1225
1089
  this.errorHandler = handler;
1226
1090
  return this;
1227
1091
  };
1228
1092
  /**
1229
- * `.notFound()` allows you to customize a Not Found Response.
1230
- *
1231
- * @see {@link https://hono.dev/docs/api/hono#not-found}
1232
- *
1233
- * @param {NotFoundHandler} handler - request handler for not-found
1234
- * @returns {Hono} changed Hono instance
1235
- *
1236
- * @example
1237
- * ```ts
1238
- * app.notFound((c) => {
1239
- * return c.text('Custom 404 Message', 404)
1240
- * })
1241
- * ```
1242
- */
1093
+ * `.notFound()` allows you to customize a Not Found Response.
1094
+ *
1095
+ * @see {@link https://hono.dev/docs/api/hono#not-found}
1096
+ *
1097
+ * @param {NotFoundHandler} handler - request handler for not-found
1098
+ * @returns {Hono} changed Hono instance
1099
+ *
1100
+ * @example
1101
+ * ```ts
1102
+ * app.notFound((c) => {
1103
+ * return c.text('Custom 404 Message', 404)
1104
+ * })
1105
+ * ```
1106
+ */
1243
1107
  notFound = (handler) => {
1244
1108
  this.#notFoundHandler = handler;
1245
1109
  return this;
1246
1110
  };
1247
1111
  /**
1248
- * `.mount()` allows you to mount applications built with other frameworks into your Hono application.
1249
- *
1250
- * @see {@link https://hono.dev/docs/api/hono#mount}
1251
- *
1252
- * @param {string} path - base Path
1253
- * @param {Function} applicationHandler - other Request Handler
1254
- * @param {MountOptions} [options] - options of `.mount()`
1255
- * @returns {Hono} mounted Hono instance
1256
- *
1257
- * @example
1258
- * ```ts
1259
- * import { Router as IttyRouter } from 'itty-router'
1260
- * import { Hono } from 'hono'
1261
- * // Create itty-router application
1262
- * const ittyRouter = IttyRouter()
1263
- * // GET /itty-router/hello
1264
- * ittyRouter.get('/hello', () => new Response('Hello from itty-router'))
1265
- *
1266
- * const app = new Hono()
1267
- * app.mount('/itty-router', ittyRouter.handle)
1268
- * ```
1269
- *
1270
- * @example
1271
- * ```ts
1272
- * const app = new Hono()
1273
- * // Send the request to another application without modification.
1274
- * app.mount('/app', anotherApp, {
1275
- * replaceRequest: (req) => req,
1276
- * })
1277
- * ```
1278
- */
1112
+ * `.mount()` allows you to mount applications built with other frameworks into your Hono application.
1113
+ *
1114
+ * @deprecated Use `mount()` from `hono/mount` instead. `.mount()` will be removed in v5.
1115
+ *
1116
+ * @see {@link https://hono.dev/docs/api/hono#mount}
1117
+ *
1118
+ * @param {string} path - base Path
1119
+ * @param {Function} applicationHandler - other Request Handler
1120
+ * @param {MountOptions} [options] - options of `.mount()`
1121
+ * @returns {Hono} mounted Hono instance
1122
+ *
1123
+ * @example
1124
+ * ```ts
1125
+ * import { Router as IttyRouter } from 'itty-router'
1126
+ * import { Hono } from 'hono'
1127
+ * // Create itty-router application
1128
+ * const ittyRouter = IttyRouter()
1129
+ * // GET /itty-router/hello
1130
+ * ittyRouter.get('/hello', () => new Response('Hello from itty-router'))
1131
+ *
1132
+ * const app = new Hono()
1133
+ * app.mount('/itty-router', ittyRouter.handle)
1134
+ * ```
1135
+ *
1136
+ * @example
1137
+ * ```ts
1138
+ * const app = new Hono()
1139
+ * // Send the request to another application without modification.
1140
+ * app.mount('/app', anotherApp, {
1141
+ * replaceRequest: (req) => req,
1142
+ * })
1143
+ * ```
1144
+ */
1279
1145
  mount(path, applicationHandler, options) {
1280
1146
  let replaceRequest;
1281
1147
  let optionHandler;
1282
1148
  if (options) {
1283
- if (typeof options === "function") {
1284
- optionHandler = options;
1285
- } else {
1149
+ if (typeof options === "function") optionHandler = options;
1150
+ else {
1286
1151
  optionHandler = options.optionHandler;
1287
- if (options.replaceRequest === false) {
1288
- replaceRequest = (request) => request;
1289
- } else {
1290
- replaceRequest = options.replaceRequest;
1291
- }
1152
+ if (options.replaceRequest === false) replaceRequest = (request) => request;
1153
+ else replaceRequest = options.replaceRequest;
1292
1154
  }
1293
1155
  }
1294
1156
  const getOptions = optionHandler ? (c) => {
@@ -1313,16 +1175,13 @@ var Hono$1 = class _Hono {
1313
1175
  })();
1314
1176
  const handler = async (c, next) => {
1315
1177
  const res = await applicationHandler(replaceRequest(c.req.raw), ...getOptions(c));
1316
- if (res) {
1317
- return res;
1318
- }
1178
+ if (res) return res;
1319
1179
  await next();
1320
1180
  };
1321
- this.#addRoute(METHOD_NAME_ALL, mergePath(path, "*"), handler);
1181
+ this.#addRoute("ALL", mergePath(path, "*"), handler);
1322
1182
  return this;
1323
1183
  }
1324
1184
  #addRoute(method, path, handler, baseRoutePath) {
1325
- method = method.toUpperCase();
1326
1185
  path = mergePath(this._basePath, path);
1327
1186
  const r = {
1328
1187
  basePath: baseRoutePath !== void 0 ? mergePath(this._basePath, baseRoutePath) : this._basePath,
@@ -1334,15 +1193,11 @@ var Hono$1 = class _Hono {
1334
1193
  this.routes.push(r);
1335
1194
  }
1336
1195
  #handleError(err, c) {
1337
- if (err instanceof Error) {
1338
- return this.errorHandler(err, c);
1339
- }
1196
+ if (err instanceof Error) return this.errorHandler(err, c);
1340
1197
  throw err;
1341
1198
  }
1342
1199
  #dispatch(request, executionCtx, env, method) {
1343
- if (method === "HEAD") {
1344
- return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))();
1345
- }
1200
+ if (method === "HEAD") return (async () => new Response(null, await this.#dispatch(request, executionCtx, env, "GET")))();
1346
1201
  const path = this.getPath(request, { env });
1347
1202
  const matchResult = this.router.match(method, path);
1348
1203
  const c = new Context(request, {
@@ -1361,19 +1216,13 @@ var Hono$1 = class _Hono {
1361
1216
  } catch (err) {
1362
1217
  return this.#handleError(err, c);
1363
1218
  }
1364
- return res instanceof Promise ? res.then(
1365
- (resolved) => resolved || (c.finalized ? c.res : this.#notFoundHandler(c))
1366
- ).catch((err) => this.#handleError(err, c)) : res ?? this.#notFoundHandler(c);
1219
+ return res instanceof Promise ? res.then((resolved) => resolved || (c.finalized ? c.res : this.#notFoundHandler(c))).catch((err) => this.#handleError(err, c)) : res ?? this.#notFoundHandler(c);
1367
1220
  }
1368
1221
  const composed = compose(matchResult[0], this.errorHandler, this.#notFoundHandler);
1369
1222
  return (async () => {
1370
1223
  try {
1371
1224
  const context = await composed(c);
1372
- if (!context.finalized) {
1373
- throw new Error(
1374
- "Context is not finalized. Did you forget to return a Response object or `await next()`?"
1375
- );
1376
- }
1225
+ if (!context.finalized) throw new Error("Context is not finalized. Did you forget to return a Response object or `await next()`?");
1377
1226
  return context.res;
1378
1227
  } catch (err) {
1379
1228
  return this.#handleError(err, c);
@@ -1381,150 +1230,125 @@ var Hono$1 = class _Hono {
1381
1230
  })();
1382
1231
  }
1383
1232
  /**
1384
- * `.fetch()` will be entry point of your app.
1385
- *
1386
- * @see {@link https://hono.dev/docs/api/hono#fetch}
1387
- *
1388
- * @param {Request} request - request Object of request
1389
- * @param {Env} env - env Object
1390
- * @param {ExecutionContext} executionCtx - context of execution
1391
- * @returns {Response | Promise<Response>} response of request
1392
- *
1393
- */
1233
+ * `.fetch()` will be entry point of your app.
1234
+ *
1235
+ * @see {@link https://hono.dev/docs/api/hono#fetch}
1236
+ *
1237
+ * @param {Request} request - request Object of request
1238
+ * @param {Env} env - env Object
1239
+ * @param {ExecutionContext} executionCtx - context of execution
1240
+ * @returns {Response | Promise<Response>} response of request
1241
+ *
1242
+ */
1394
1243
  fetch = (request, ...rest) => {
1395
1244
  return this.#dispatch(request, rest[1], rest[0], request.method);
1396
1245
  };
1397
1246
  /**
1398
- * `.request()` is a useful method for testing.
1399
- * You can pass a URL or pathname to send a GET request.
1400
- * app will return a Response object.
1401
- * ```ts
1402
- * test('GET /hello is ok', async () => {
1403
- * const res = await app.request('/hello')
1404
- * expect(res.status).toBe(200)
1405
- * })
1406
- * ```
1407
- * @see https://hono.dev/docs/api/hono#request
1408
- */
1247
+ * `.request()` is a useful method for testing.
1248
+ * You can pass a URL or pathname to send a GET request.
1249
+ * app will return a Response object.
1250
+ * ```ts
1251
+ * test('GET /hello is ok', async () => {
1252
+ * const res = await app.request('/hello')
1253
+ * expect(res.status).toBe(200)
1254
+ * })
1255
+ * ```
1256
+ * @see https://hono.dev/docs/api/hono#request
1257
+ */
1409
1258
  request = (input, requestInit, Env, executionCtx) => {
1410
- if (input instanceof Request) {
1411
- return this.fetch(requestInit ? new Request(input, requestInit) : input, Env, executionCtx);
1412
- }
1259
+ if (input instanceof Request) return this.fetch(requestInit ? new Request(input, requestInit) : input, Env, executionCtx);
1413
1260
  input = input.toString();
1414
- return this.fetch(
1415
- new Request(
1416
- /^https?:\/\//.test(input) ? input : `http://localhost${mergePath("/", input)}`,
1417
- requestInit
1418
- ),
1419
- Env,
1420
- executionCtx
1421
- );
1261
+ return this.fetch(new Request(/^https?:\/\//.test(input) ? input : `http://localhost${mergePath("/", input)}`, requestInit), Env, executionCtx);
1422
1262
  };
1423
1263
  /**
1424
- * `.fire()` automatically adds a global fetch event listener.
1425
- * This can be useful for environments that adhere to the Service Worker API, such as non-ES module Cloudflare Workers.
1426
- * @deprecated
1427
- * Use `fire` from `hono/service-worker` instead.
1428
- * ```ts
1429
- * import { Hono } from 'hono'
1430
- * import { fire } from 'hono/service-worker'
1431
- *
1432
- * const app = new Hono()
1433
- * // ...
1434
- * fire(app)
1435
- * ```
1436
- * @see https://hono.dev/docs/api/hono#fire
1437
- * @see https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
1438
- * @see https://developers.cloudflare.com/workers/reference/migrate-to-module-workers/
1439
- */
1264
+ * `.fire()` automatically adds a global fetch event listener.
1265
+ * This can be useful for environments that adhere to the Service Worker API, such as non-ES module Cloudflare Workers.
1266
+ * @deprecated
1267
+ * Use `fire` from `hono/service-worker` instead.
1268
+ * ```ts
1269
+ * import { Hono } from 'hono'
1270
+ * import { fire } from 'hono/service-worker'
1271
+ *
1272
+ * const app = new Hono()
1273
+ * // ...
1274
+ * fire(app)
1275
+ * ```
1276
+ * @see https://hono.dev/docs/api/hono#fire
1277
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
1278
+ * @see https://developers.cloudflare.com/workers/reference/migrate-to-module-workers/
1279
+ */
1440
1280
  fire = () => {
1441
1281
  addEventListener("fetch", (event2) => {
1442
1282
  event2.respondWith(this.#dispatch(event2.request, event2, void 0, event2.request.method));
1443
1283
  });
1444
1284
  };
1445
1285
  };
1446
- var emptyParam = [];
1286
+ const createNullObject = () => /* @__PURE__ */ Object.create(null);
1287
+ const emptyParam = [];
1447
1288
  function match(method, path) {
1448
1289
  const matchers = this.buildAllMatchers();
1449
1290
  const match2 = ((method2, path2) => {
1450
- const matcher = matchers[method2] || matchers[METHOD_NAME_ALL];
1291
+ const matcher = matchers[method2] || matchers["ALL"];
1451
1292
  const staticMatch = matcher[2][path2];
1452
- if (staticMatch) {
1453
- return staticMatch;
1454
- }
1293
+ if (staticMatch) return staticMatch;
1455
1294
  const match3 = path2.match(matcher[0]);
1456
- if (!match3) {
1457
- return [[], emptyParam];
1458
- }
1295
+ if (!match3) return [[], emptyParam];
1459
1296
  const index = match3.indexOf("", 1);
1460
1297
  return [matcher[1][index], match3];
1461
1298
  });
1462
1299
  this.match = match2;
1463
1300
  return match2(method, path);
1464
1301
  }
1465
- var LABEL_REG_EXP_STR = "[^/]+";
1466
- var ONLY_WILDCARD_REG_EXP_STR = ".*";
1467
- var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
1468
- var PATH_ERROR = /* @__PURE__ */ Symbol();
1469
- var regExpMetaChars = new Set(".\\+*[^]$()");
1302
+ const LABEL_REG_EXP_STR = "[^/]+";
1303
+ const TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
1304
+ const PATH_ERROR = /* @__PURE__ */ Symbol();
1305
+ const regExpMetaChars = /* @__PURE__ */ new Set(".\\+*[^]$()");
1470
1306
  function compareKey(a, b) {
1471
- if (a.length === 1) {
1472
- return b.length === 1 ? a < b ? -1 : 1 : -1;
1473
- }
1474
- if (b.length === 1) {
1475
- return 1;
1476
- }
1477
- if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
1478
- return b === TAIL_WILDCARD_REG_EXP_STR ? -1 : 1;
1479
- } else if (b === ONLY_WILDCARD_REG_EXP_STR || b === TAIL_WILDCARD_REG_EXP_STR) {
1480
- return -1;
1481
- }
1482
- if (a === LABEL_REG_EXP_STR) {
1483
- return 1;
1484
- } else if (b === LABEL_REG_EXP_STR) {
1485
- return -1;
1486
- }
1307
+ if (a.length === 1) return b.length === 1 ? a < b ? -1 : 1 : -1;
1308
+ if (b.length === 1) return 1;
1309
+ if (a === ".*" || a === "(?:|/.*)") return b === "(?:|/.*)" ? -1 : 1;
1310
+ else if (b === ".*" || b === "(?:|/.*)") return -1;
1311
+ if (a === "[^/]+") return 1;
1312
+ else if (b === "[^/]+") return -1;
1487
1313
  return a.length === b.length ? a < b ? -1 : 1 : b.length - a.length;
1488
1314
  }
1489
- var Node$1 = class _Node {
1490
- // handler index of a dynamic path, or -1 for a static path terminal
1315
+ var Node$1 = class Node {
1491
1316
  #index;
1492
1317
  #varIndex;
1493
- #children = /* @__PURE__ */ Object.create(null);
1318
+ #children = createNullObject();
1494
1319
  insert(tokens, index, paramMap, context, isStatic) {
1495
1320
  let node = this;
1496
1321
  for (let i = 0, len = tokens.length; i < len; i++) {
1497
1322
  const token = tokens[i];
1498
- const pattern = token.length === 1 ? token === "*" ? i === len - 1 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : null : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
1323
+ const pattern = token.length === 1 ? token === "*" ? i === len - 1 ? [
1324
+ "",
1325
+ "",
1326
+ ".*"
1327
+ ] : [
1328
+ "",
1329
+ "",
1330
+ LABEL_REG_EXP_STR
1331
+ ] : null : token === "/*" ? [
1332
+ "",
1333
+ "",
1334
+ TAIL_WILDCARD_REG_EXP_STR
1335
+ ] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
1499
1336
  let nextNode;
1500
1337
  if (pattern) {
1501
1338
  const name = pattern[1];
1502
- let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
1339
+ let regexpStr = pattern[2] || "[^/]+";
1503
1340
  if (name && pattern[2]) {
1504
- if (regexpStr === ".*") {
1505
- throw PATH_ERROR;
1506
- }
1341
+ if (regexpStr === ".*") throw PATH_ERROR;
1507
1342
  regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
1508
- if (/\((?!\?:)/.test(regexpStr)) {
1509
- throw PATH_ERROR;
1510
- }
1511
- if (regexpStr.length === 1 && regExpMetaChars.has(regexpStr)) {
1512
- throw PATH_ERROR;
1513
- }
1343
+ if (/\((?!\?:)/.test(regexpStr)) throw PATH_ERROR;
1344
+ if (regexpStr.length === 1 && regExpMetaChars.has(regexpStr)) throw PATH_ERROR;
1514
1345
  }
1515
1346
  nextNode = node.#children[regexpStr];
1516
1347
  if (!nextNode) {
1517
- if (regexpStr !== ONLY_WILDCARD_REG_EXP_STR && regexpStr !== TAIL_WILDCARD_REG_EXP_STR) {
1518
- for (const k in node.#children) {
1519
- if (
1520
- // a single-char pattern coexists with single-char literals as a literal does
1521
- (regexpStr.length > 1 || k.length > 1) && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR
1522
- ) {
1523
- throw PATH_ERROR;
1524
- }
1525
- }
1348
+ if (regexpStr !== ".*" && regexpStr !== "(?:|/.*)") {
1349
+ for (const k in node.#children) if ((regexpStr.length > 1 || k.length > 1) && k !== ".*" && k !== "(?:|/.*)") throw PATH_ERROR;
1526
1350
  }
1527
- nextNode = node.#children[regexpStr] = new _Node();
1351
+ nextNode = node.#children[regexpStr] = new Node();
1528
1352
  }
1529
1353
  if (name !== "") {
1530
1354
  nextNode.#varIndex ??= context.varIndex++;
@@ -1533,37 +1357,24 @@ var Node$1 = class _Node {
1533
1357
  } else {
1534
1358
  nextNode = node.#children[token];
1535
1359
  if (!nextNode) {
1536
- for (const k in node.#children) {
1537
- if (k.length > 1 && k !== ONLY_WILDCARD_REG_EXP_STR && k !== TAIL_WILDCARD_REG_EXP_STR) {
1538
- throw PATH_ERROR;
1539
- }
1540
- }
1541
- nextNode = node.#children[token] = new _Node();
1360
+ for (const k in node.#children) if (k.length > 1 && k !== ".*" && k !== "(?:|/.*)") throw PATH_ERROR;
1361
+ nextNode = node.#children[token] = new Node();
1542
1362
  }
1543
1363
  }
1544
1364
  node = nextNode;
1545
1365
  }
1546
- if (node.#index !== void 0) {
1547
- throw PATH_ERROR;
1548
- }
1366
+ if (node.#index !== void 0) throw PATH_ERROR;
1549
1367
  node.#index = isStatic ? -1 : index;
1550
1368
  }
1551
1369
  buildRegExpStr() {
1552
- const childKeys = Object.keys(this.#children).sort(compareKey);
1553
- const strList = childKeys.map((k) => {
1370
+ const strList = Object.keys(this.#children).sort(compareKey).map((k) => {
1554
1371
  const c = this.#children[k];
1555
1372
  const childStr = c.buildRegExpStr();
1556
1373
  return childStr === "" ? "" : (typeof c.#varIndex === "number" ? `(${k})@${c.#varIndex}` : regExpMetaChars.has(k) ? `\\${k}` : k) + childStr;
1557
1374
  }).filter(Boolean);
1558
- if (typeof this.#index === "number" && this.#index !== -1) {
1559
- strList.unshift(`#${this.#index}`);
1560
- }
1561
- if (strList.length === 0) {
1562
- return "";
1563
- }
1564
- if (strList.length === 1) {
1565
- return strList[0];
1566
- }
1375
+ if (typeof this.#index === "number" && this.#index !== -1) strList.unshift(`#${this.#index}`);
1376
+ if (strList.length === 0) return "";
1377
+ if (strList.length === 1) return strList[0];
1567
1378
  return "(?:" + strList.join("|") + ")";
1568
1379
  }
1569
1380
  };
@@ -1571,8 +1382,7 @@ var Trie = class {
1571
1382
  #context = { varIndex: 0 };
1572
1383
  #root = new Node$1();
1573
1384
  #index = 0;
1574
- // dynamic path -> [handler index, param assoc]; static paths are not registered
1575
- paths = /* @__PURE__ */ Object.create(null);
1385
+ paths = createNullObject();
1576
1386
  insert(path, isStatic) {
1577
1387
  if (isStatic) {
1578
1388
  this.#root.insert(path.split(""), 0, [], this.#context, true);
@@ -1590,18 +1400,14 @@ var Trie = class {
1590
1400
  replaced = true;
1591
1401
  return mark;
1592
1402
  });
1593
- if (!replaced) {
1594
- break;
1595
- }
1403
+ if (!replaced) break;
1596
1404
  }
1597
1405
  const tokens = markedPath.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
1598
1406
  for (let i = groups.length - 1; i >= 0; i--) {
1599
1407
  const [mark] = groups[i];
1600
- for (let j = tokens.length - 1; j >= 0; j--) {
1601
- if (tokens[j].indexOf(mark) !== -1) {
1602
- tokens[j] = tokens[j].replace(mark, groups[i][1]);
1603
- break;
1604
- }
1408
+ for (let j = tokens.length - 1; j >= 0; j--) if (tokens[j].indexOf(mark) !== -1) {
1409
+ tokens[j] = tokens[j].replace(mark, groups[i][1]);
1410
+ break;
1605
1411
  }
1606
1412
  }
1607
1413
  this.#root.insert(tokens, this.#index, paramAssoc, this.#context, false);
@@ -1609,9 +1415,11 @@ var Trie = class {
1609
1415
  }
1610
1416
  buildRegExp() {
1611
1417
  let regexp = this.#root.buildRegExpStr();
1612
- if (regexp === "") {
1613
- return [/^$/, [], []];
1614
- }
1418
+ if (regexp === "") return [
1419
+ /^$/,
1420
+ [],
1421
+ []
1422
+ ];
1615
1423
  let captureIndex = 0;
1616
1424
  const indexReplacementMap = [];
1617
1425
  const paramReplacementMap = [];
@@ -1626,31 +1434,19 @@ var Trie = class {
1626
1434
  }
1627
1435
  return "";
1628
1436
  });
1629
- return [new RegExp(`^${regexp}`), indexReplacementMap, paramReplacementMap];
1437
+ return [
1438
+ new RegExp(`^${regexp}`),
1439
+ indexReplacementMap,
1440
+ paramReplacementMap
1441
+ ];
1630
1442
  }
1631
1443
  };
1632
- var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
1444
+ let wildcardRegExpCache = createNullObject();
1633
1445
  function buildWildcardRegExp(path) {
1634
- return wildcardRegExpCache[path] ??= new RegExp(
1635
- path === "*" ? "" : `^${path.replace(
1636
- /\/\*$|([.\\+*[^\]$()])/g,
1637
- (_, metaChar) => metaChar ? `\\${metaChar}` : "(?:|/.*)"
1638
- )}$`
1639
- );
1640
- }
1641
- function clearWildcardRegExpCache() {
1642
- wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
1446
+ return wildcardRegExpCache[path] ??= new RegExp(`^${path.replace(/\/:[^/{}]+(?:\{\[\^\/]\+})?(?=[/{]|$)|\/?\*$|([.\\+*[^\]$()?{}|])/g, (match2, metaChar) => metaChar ? `\\${metaChar}` : match2 === "/*" ? TAIL_WILDCARD_REG_EXP_STR : match2 === "*" ? ".*" : `/:${LABEL_REG_EXP_STR}`)}$`);
1643
1447
  }
1644
1448
  function findMiddleware(middleware, path) {
1645
- if (!middleware) {
1646
- return void 0;
1647
- }
1648
- for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) {
1649
- if (buildWildcardRegExp(k).test(path)) {
1650
- return [...middleware[k]];
1651
- }
1652
- }
1653
- return void 0;
1449
+ for (const k of Object.keys(middleware).sort((a, b) => b.length - a.length)) if (buildWildcardRegExp(k).test(path)) return [...middleware[k]];
1654
1450
  }
1655
1451
  var RegExpRouter = class {
1656
1452
  name = "RegExpRouter";
@@ -1658,9 +1454,9 @@ var RegExpRouter = class {
1658
1454
  #routes;
1659
1455
  #tries;
1660
1456
  constructor() {
1661
- this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
1662
- this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
1663
- this.#tries = { [METHOD_NAME_ALL]: new Trie() };
1457
+ this.#middleware = { ["ALL"]: createNullObject() };
1458
+ this.#routes = { ["ALL"]: createNullObject() };
1459
+ this.#tries = { ["ALL"]: new Trie() };
1664
1460
  }
1665
1461
  #insertPath(method, path) {
1666
1462
  try {
@@ -1672,117 +1468,69 @@ var RegExpRouter = class {
1672
1468
  add(method, path, handler) {
1673
1469
  const middleware = this.#middleware;
1674
1470
  const routes = this.#routes;
1675
- if (!middleware || !routes) {
1676
- throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
1677
- }
1471
+ if (!middleware) throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
1678
1472
  if (!middleware[method]) {
1679
1473
  this.#tries[method] = new Trie();
1680
- [middleware, routes].forEach((handlerMap) => {
1681
- handlerMap[method] = /* @__PURE__ */ Object.create(null);
1682
- Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p) => {
1683
- handlerMap[method][p] = [...handlerMap[METHOD_NAME_ALL][p]];
1474
+ for (const handlerMap of [middleware, routes]) {
1475
+ handlerMap[method] = createNullObject();
1476
+ for (const p in handlerMap["ALL"]) {
1477
+ handlerMap[method][p] = [...handlerMap["ALL"][p]];
1684
1478
  this.#insertPath(method, p);
1685
- });
1686
- });
1687
- }
1688
- if (path === "/*") {
1689
- path = "*";
1479
+ }
1480
+ }
1690
1481
  }
1691
- const paramCount = (path.match(/\/:/g) || []).length;
1482
+ if (path === "/*") path = "*";
1483
+ const methods = method === "ALL" ? Object.keys(middleware) : [method];
1692
1484
  if (/\*$/.test(path)) {
1693
1485
  const re = buildWildcardRegExp(path);
1694
- Object.keys(middleware).forEach((m) => {
1695
- if ((method === METHOD_NAME_ALL || method === m) && !middleware[m][path]) {
1696
- this.#insertPath(m, path);
1697
- middleware[m][path] = findMiddleware(middleware[m], path) || findMiddleware(middleware[METHOD_NAME_ALL], path) || [];
1698
- }
1699
- });
1700
- Object.keys(middleware).forEach((m) => {
1701
- if (method === METHOD_NAME_ALL || method === m) {
1702
- Object.keys(middleware[m]).forEach((p) => {
1703
- re.test(p) && middleware[m][p].push([handler, paramCount]);
1704
- });
1705
- }
1706
- });
1707
- Object.keys(routes).forEach((m) => {
1708
- if (method === METHOD_NAME_ALL || method === m) {
1709
- Object.keys(routes[m]).forEach(
1710
- (p) => re.test(p) && routes[m][p].push([handler, paramCount])
1711
- );
1712
- }
1713
- });
1486
+ for (const m of methods) if (!middleware[m][path]) {
1487
+ this.#insertPath(m, path);
1488
+ middleware[m][path] = findMiddleware(middleware[m], path) || findMiddleware(middleware["ALL"], path) || [];
1489
+ }
1490
+ for (const handlerMap of [middleware, routes]) for (const m of methods) for (const p in handlerMap[m]) re.test(p) && handlerMap[m][p].push([handler, path]);
1714
1491
  return;
1715
1492
  }
1716
1493
  const paths = checkOptionalParameter(path) || [path];
1717
- for (let i = 0, len = paths.length; i < len; i++) {
1718
- const path2 = paths[i];
1719
- Object.keys(routes).forEach((m) => {
1720
- if (method === METHOD_NAME_ALL || method === m) {
1721
- if (!routes[m][path2]) {
1722
- this.#insertPath(m, path2);
1723
- routes[m][path2] = [
1724
- ...findMiddleware(middleware[m], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || []
1725
- ];
1726
- }
1727
- routes[m][path2].push([handler, paramCount - len + i + 1]);
1728
- }
1729
- });
1494
+ for (const path2 of paths) for (const m of methods) {
1495
+ if (!routes[m][path2]) {
1496
+ this.#insertPath(m, path2);
1497
+ routes[m][path2] = findMiddleware(middleware[m], path2) || findMiddleware(middleware["ALL"], path2) || [];
1498
+ }
1499
+ routes[m][path2].push([handler, path2]);
1730
1500
  }
1731
1501
  }
1732
1502
  match = match;
1733
1503
  buildAllMatchers() {
1734
- const matchers = /* @__PURE__ */ Object.create(null);
1735
- Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
1736
- matchers[method] ||= this.#buildMatcher(method);
1737
- });
1504
+ const matchers = createNullObject();
1505
+ for (const method of Object.keys(this.#routes)) matchers[method] = this.#buildMatcher(method);
1738
1506
  this.#middleware = this.#routes = this.#tries = void 0;
1739
- clearWildcardRegExpCache();
1507
+ wildcardRegExpCache = createNullObject();
1740
1508
  return matchers;
1741
1509
  }
1742
1510
  #buildMatcher(method) {
1743
1511
  const middleware = this.#middleware[method];
1744
1512
  const routes = this.#routes[method];
1745
1513
  const trie = this.#tries[method];
1746
- const staticMap = /* @__PURE__ */ Object.create(null);
1514
+ const staticMap = createNullObject();
1747
1515
  const handlerData = [];
1748
- [middleware, routes].forEach((r) => {
1749
- for (const path in r) {
1750
- const handlers = r[path];
1751
- const pathData = trie.paths[path];
1752
- if (!pathData) {
1753
- staticMap[path] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
1754
- continue;
1755
- }
1756
- const paramAssoc = pathData[1];
1757
- handlerData[pathData[0]] = handlers.map(([h, paramCount]) => {
1758
- const paramIndexMap = /* @__PURE__ */ Object.create(null);
1759
- paramCount -= 1;
1760
- for (; paramCount >= 0; paramCount--) {
1761
- const [key, value] = paramAssoc[paramCount];
1762
- paramIndexMap[key] = value;
1763
- }
1764
- return [h, paramIndexMap];
1765
- });
1766
- }
1767
- });
1768
1516
  const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
1769
- for (let i = 0, len = handlerData.length; i < len; i++) {
1770
- for (let j = 0, len2 = handlerData[i].length; j < len2; j++) {
1771
- const map = handlerData[i][j]?.[1];
1772
- if (!map) {
1773
- continue;
1774
- }
1775
- const keys = Object.keys(map);
1776
- for (let k = 0, len3 = keys.length; k < len3; k++) {
1777
- map[keys[k]] = paramReplacementMap[map[keys[k]]];
1778
- }
1517
+ for (const r of [middleware, routes]) for (const path in r) {
1518
+ const handlers = r[path];
1519
+ const pathData = trie.paths[path];
1520
+ if (!pathData) {
1521
+ staticMap[path] = [handlers.map(([h]) => [h, createNullObject()]), emptyParam];
1522
+ continue;
1779
1523
  }
1524
+ handlerData[pathData[0]] = handlers.map(([h, handlerPath]) => [h, trie.paths[handlerPath][1].reduceRight((map, [key], i) => {
1525
+ map[key] = paramReplacementMap[pathData[1][i][1]];
1526
+ return map;
1527
+ }, createNullObject())]);
1780
1528
  }
1781
- const handlerMap = [];
1782
- for (const i in indexReplacementMap) {
1783
- handlerMap[i] = handlerData[indexReplacementMap[i]];
1784
- }
1785
- return [regexp, handlerMap, staticMap];
1529
+ return [
1530
+ regexp,
1531
+ indexReplacementMap.map((i) => handlerData[i]),
1532
+ staticMap
1533
+ ];
1786
1534
  }
1787
1535
  };
1788
1536
  var SmartRouter = class {
@@ -1793,15 +1541,15 @@ var SmartRouter = class {
1793
1541
  this.#routers = init.routers;
1794
1542
  }
1795
1543
  add(method, path, handler) {
1796
- if (!this.#routes) {
1797
- throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
1798
- }
1799
- this.#routes.push([method, path, handler]);
1544
+ if (!this.#routes) throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
1545
+ this.#routes.push([
1546
+ method,
1547
+ path,
1548
+ handler
1549
+ ]);
1800
1550
  }
1801
1551
  match(method, path) {
1802
- if (!this.#routes) {
1803
- throw new Error("Fatal error");
1804
- }
1552
+ if (!this.#routes) throw new Error("Fatal error");
1805
1553
  const routers = this.#routers;
1806
1554
  const routes = this.#routes;
1807
1555
  const len = routers.length;
@@ -1810,14 +1558,10 @@ var SmartRouter = class {
1810
1558
  for (; i < len; i++) {
1811
1559
  const router = routers[i];
1812
1560
  try {
1813
- for (let i2 = 0, len2 = routes.length; i2 < len2; i2++) {
1814
- router.add(...routes[i2]);
1815
- }
1561
+ for (let i2 = 0, len2 = routes.length; i2 < len2; i2++) router.add(...routes[i2]);
1816
1562
  res = router.match(method, path);
1817
1563
  } catch (e) {
1818
- if (e instanceof UnsupportedPathError) {
1819
- continue;
1820
- }
1564
+ if (e instanceof UnsupportedPathError) continue;
1821
1565
  throw e;
1822
1566
  }
1823
1567
  this.match = router.match.bind(router);
@@ -1825,90 +1569,57 @@ var SmartRouter = class {
1825
1569
  this.#routes = void 0;
1826
1570
  break;
1827
1571
  }
1828
- if (i === len) {
1829
- throw new Error("Fatal error");
1830
- }
1572
+ if (i === len) throw new Error("Fatal error");
1831
1573
  this.name = `SmartRouter + ${this.activeRouter.name}`;
1832
1574
  return res;
1833
1575
  }
1834
1576
  get activeRouter() {
1835
- if (this.#routes || this.#routers.length !== 1) {
1836
- throw new Error("No active router has been determined yet.");
1837
- }
1577
+ if (this.#routes || this.#routers.length !== 1) throw new Error("No active router has been determined yet.");
1838
1578
  return this.#routers[0];
1839
1579
  }
1840
1580
  };
1841
- var emptyParams = /* @__PURE__ */ Object.create(null);
1842
- var hasChildren = (children) => {
1843
- for (const _ in children) {
1844
- return true;
1845
- }
1846
- return false;
1847
- };
1848
- var Node = class _Node2 {
1849
- #methods;
1850
- #children;
1851
- #patterns;
1852
- #order = 0;
1581
+ const emptyParams = createNullObject();
1582
+ let order = 0;
1583
+ var Node2 = class Node3 {
1584
+ #methods = [];
1585
+ #children = createNullObject();
1586
+ #patterns = [];
1587
+ #pattern;
1853
1588
  #params = emptyParams;
1854
- constructor(method, handler, children) {
1855
- this.#children = children || /* @__PURE__ */ Object.create(null);
1856
- this.#methods = [];
1857
- if (method && handler) {
1858
- const m = /* @__PURE__ */ Object.create(null);
1859
- m[method] = { handler, possibleKeys: [], score: 0 };
1860
- this.#methods = [m];
1861
- }
1862
- this.#patterns = [];
1863
- }
1864
1589
  insert(method, path, handler) {
1865
- this.#order = ++this.#order;
1866
1590
  let curNode = this;
1867
1591
  const parts = splitRoutingPath(path);
1868
- const possibleKeys = [];
1869
- for (let i = 0, len = parts.length; i < len; i++) {
1870
- const p = parts[i];
1871
- const nextP = parts[i + 1];
1872
- const pattern = getPattern(p, nextP);
1873
- const key = Array.isArray(pattern) ? pattern[0] : p;
1874
- if (key in curNode.#children) {
1875
- curNode = curNode.#children[key];
1876
- if (pattern) {
1877
- possibleKeys.push(pattern[1]);
1878
- }
1879
- continue;
1880
- }
1881
- curNode.#children[key] = new _Node2();
1882
- if (pattern) {
1883
- curNode.#patterns.push(pattern);
1884
- possibleKeys.push(pattern[1]);
1885
- }
1886
- curNode = curNode.#children[key];
1887
- }
1888
- curNode.#methods.push({
1889
- [method]: {
1890
- handler,
1891
- possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
1892
- score: this.#order
1893
- }
1894
- });
1895
- return curNode;
1592
+ const possibleKeys = /* @__PURE__ */ new Set();
1593
+ let i = 0;
1594
+ for (const p of parts) {
1595
+ const nextP = parts[++i];
1596
+ const pattern = getPattern(p, nextP) || (nextP === void 0 && p && p.indexOf("*") === p.length - 1 ? p : null);
1597
+ const isParam = Array.isArray(pattern);
1598
+ const key = isParam ? pattern[0] : pattern || p;
1599
+ const child = curNode.#children[key] ||= new Node3();
1600
+ if (pattern && !child.#pattern) {
1601
+ child.#pattern = pattern;
1602
+ curNode.#patterns.push(child);
1603
+ }
1604
+ curNode = child;
1605
+ if (isParam) possibleKeys.add(pattern[1]);
1606
+ }
1607
+ curNode.#methods.push({ [method]: {
1608
+ handler,
1609
+ possibleKeys: [...possibleKeys],
1610
+ score: ++order
1611
+ } });
1896
1612
  }
1897
1613
  #pushHandlerSets(handlerSets, node, method, nodeParams, params) {
1898
1614
  for (let i = 0, len = node.#methods.length; i < len; i++) {
1899
1615
  const m = node.#methods[i];
1900
- const handlerSet = m[method] || m[METHOD_NAME_ALL];
1901
- const processedSet = {};
1902
- if (handlerSet !== void 0) {
1903
- handlerSet.params = /* @__PURE__ */ Object.create(null);
1616
+ const handlerSet = m[method] || m["ALL"];
1617
+ if (handlerSet) {
1618
+ handlerSet.params = createNullObject();
1904
1619
  handlerSets.push(handlerSet);
1905
- if (nodeParams !== emptyParams || params && params !== emptyParams) {
1906
- for (let i2 = 0, len2 = handlerSet.possibleKeys.length; i2 < len2; i2++) {
1907
- const key = handlerSet.possibleKeys[i2];
1908
- const processed = processedSet[handlerSet.score];
1909
- handlerSet.params[key] = params?.[key] && !processed ? params[key] : nodeParams[key] ?? params?.[key];
1910
- processedSet[handlerSet.score] = true;
1911
- }
1620
+ for (let i2 = 0, len2 = handlerSet.possibleKeys.length; i2 < len2; i2++) {
1621
+ const key = handlerSet.possibleKeys[i2];
1622
+ handlerSet.params[key] = params?.[key] && !i2 ? params[key] : nodeParams[key] ?? params?.[key];
1912
1623
  }
1913
1624
  }
1914
1625
  }
@@ -1916,8 +1627,7 @@ var Node = class _Node2 {
1916
1627
  search(method, path) {
1917
1628
  const handlerSets = [];
1918
1629
  this.#params = emptyParams;
1919
- const curNode = this;
1920
- let curNodes = [curNode];
1630
+ let curNodes = [this];
1921
1631
  const parts = splitPath(path);
1922
1632
  const curNodesQueue = [];
1923
1633
  const len = parts.length;
@@ -1932,76 +1642,54 @@ var Node = class _Node2 {
1932
1642
  if (nextNode) {
1933
1643
  nextNode.#params = node.#params;
1934
1644
  if (isLast) {
1935
- if (nextNode.#children["*"]) {
1936
- this.#pushHandlerSets(handlerSets, nextNode.#children["*"], method, node.#params);
1937
- }
1645
+ if (nextNode.#children["*"]) this.#pushHandlerSets(handlerSets, nextNode.#children["*"], method, node.#params);
1938
1646
  this.#pushHandlerSets(handlerSets, nextNode, method, node.#params);
1939
- } else {
1940
- tempNodes.push(nextNode);
1941
- }
1647
+ } else tempNodes.push(nextNode);
1942
1648
  }
1943
- for (let k = 0, len3 = node.#patterns.length; k < len3; k++) {
1944
- const pattern = node.#patterns[k];
1649
+ for (const child of node.#patterns) {
1650
+ const pattern = child.#pattern;
1945
1651
  const params = node.#params === emptyParams ? {} : { ...node.#params };
1946
- if (pattern === "*") {
1947
- const astNode = node.#children["*"];
1948
- if (astNode) {
1949
- this.#pushHandlerSets(handlerSets, astNode, method, node.#params);
1950
- astNode.#params = params;
1951
- tempNodes.push(astNode);
1652
+ if (typeof pattern === "string") {
1653
+ if (pattern === "*" || part.startsWith(pattern.slice(0, -1))) {
1654
+ this.#pushHandlerSets(handlerSets, child, method, node.#params);
1655
+ if (pattern === "*") {
1656
+ child.#params = params;
1657
+ tempNodes.push(child);
1658
+ }
1952
1659
  }
1953
1660
  continue;
1954
1661
  }
1955
- const [key, name, matcher] = pattern;
1956
- if (!part && !(matcher instanceof RegExp)) {
1957
- continue;
1958
- }
1959
- const child = node.#children[key];
1960
- if (matcher instanceof RegExp) {
1961
- if (partOffsets === null) {
1962
- partOffsets = new Array(len);
1662
+ const [, name, matcher] = pattern;
1663
+ if (!part && matcher === true) continue;
1664
+ if (matcher !== true) {
1665
+ if (!partOffsets) {
1666
+ partOffsets = [];
1963
1667
  let offset = path[0] === "/" ? 1 : 0;
1964
1668
  for (let p = 0; p < len; p++) {
1965
1669
  partOffsets[p] = offset;
1966
1670
  offset += parts[p].length + 1;
1967
1671
  }
1968
1672
  }
1969
- const restPathString = path.substring(partOffsets[i]);
1673
+ const restPathString = path.slice(partOffsets[i]);
1970
1674
  const m = matcher.exec(restPathString);
1971
1675
  if (m) {
1972
- params[name] = m[0];
1676
+ if (!Object.hasOwn(params, name)) params[name] = m[0];
1973
1677
  this.#pushHandlerSets(handlerSets, child, method, node.#params, params);
1974
- if (m[0].length === restPathString.length && child.#children["*"]) {
1975
- this.#pushHandlerSets(
1976
- handlerSets,
1977
- child.#children["*"],
1978
- method,
1979
- node.#params,
1980
- params
1981
- );
1982
- }
1983
- if (hasChildren(child.#children)) {
1678
+ if (m[0].length === restPathString.length && child.#children["*"]) this.#pushHandlerSets(handlerSets, child.#children["*"], method, node.#params, params);
1679
+ for (const _ in child.#children) {
1984
1680
  child.#params = params;
1985
1681
  const componentCount = m[0].match(/\//g)?.length ?? 0;
1986
- const targetCurNodes = curNodesQueue[componentCount] ||= [];
1987
- targetCurNodes.push(child);
1682
+ (curNodesQueue[componentCount] ||= []).push(child);
1683
+ break;
1988
1684
  }
1989
1685
  continue;
1990
1686
  }
1991
1687
  }
1992
1688
  if (matcher === true || matcher.test(part)) {
1993
- params[name] = part;
1689
+ if (!Object.hasOwn(params, name)) params[name] = part;
1994
1690
  if (isLast) {
1995
1691
  this.#pushHandlerSets(handlerSets, child, method, params, node.#params);
1996
- if (child.#children["*"]) {
1997
- this.#pushHandlerSets(
1998
- handlerSets,
1999
- child.#children["*"],
2000
- method,
2001
- params,
2002
- node.#params
2003
- );
2004
- }
1692
+ if (child.#children["*"]) this.#pushHandlerSets(handlerSets, child.#children["*"], method, params, node.#params);
2005
1693
  } else {
2006
1694
  child.#params = params;
2007
1695
  tempNodes.push(child);
@@ -2012,45 +1700,31 @@ var Node = class _Node2 {
2012
1700
  const shifted = curNodesQueue.shift();
2013
1701
  curNodes = shifted ? tempNodes.concat(shifted) : tempNodes;
2014
1702
  }
2015
- if (handlerSets.length > 1) {
2016
- handlerSets.sort((a, b) => {
2017
- return a.score - b.score;
2018
- });
2019
- }
1703
+ if (handlerSets[1]) handlerSets.sort((a, b) => {
1704
+ return a.score - b.score;
1705
+ });
2020
1706
  return [handlerSets.map(({ handler, params }) => [handler, params])];
2021
1707
  }
2022
1708
  };
2023
1709
  var TrieRouter = class {
2024
1710
  name = "TrieRouter";
2025
- #node;
2026
- constructor() {
2027
- this.#node = new Node();
2028
- }
1711
+ #node = new Node2();
2029
1712
  add(method, path, handler) {
2030
- const results = checkOptionalParameter(path);
2031
- if (results) {
2032
- for (let i = 0, len = results.length; i < len; i++) {
2033
- this.#node.insert(method, results[i], handler);
2034
- }
2035
- return;
2036
- }
2037
- this.#node.insert(method, path, handler);
1713
+ for (const result of checkOptionalParameter(path) || [path]) this.#node.insert(method, result, handler);
2038
1714
  }
2039
1715
  match(method, path) {
2040
1716
  return this.#node.search(method, path);
2041
1717
  }
2042
1718
  };
2043
- var Hono = class extends Hono$1 {
1719
+ var Hono2 = class extends Hono$1 {
2044
1720
  /**
2045
- * Creates an instance of the Hono class.
2046
- *
2047
- * @param options - Optional configuration options for the Hono instance.
2048
- */
1721
+ * Creates an instance of the Hono class.
1722
+ *
1723
+ * @param options - Optional configuration options for the Hono instance.
1724
+ */
2049
1725
  constructor(options = {}) {
2050
1726
  super(options);
2051
- this.router = options.router ?? new SmartRouter({
2052
- routers: [new RegExpRouter(), new TrieRouter()]
2053
- });
1727
+ this.router = options.router ?? new SmartRouter({ routers: [new RegExpRouter(), new TrieRouter()] });
2054
1728
  }
2055
1729
  };
2056
1730
  class AuthError extends Error {
@@ -2095,86 +1769,57 @@ class PublicationError extends Error {
2095
1769
  }
2096
1770
  retryable;
2097
1771
  }
2098
- const encoder$2 = new TextEncoder();
2099
- const decoder$1 = new TextDecoder();
2100
- const strictDecoder = new TextDecoder("utf-8", { fatal: true });
1772
+ const encoder$2 = new TextEncoder(), decoder$1 = new TextDecoder(), strictDecoder = new TextDecoder("utf-8", { fatal: true });
2101
1773
  function concat(...buffers) {
2102
- const size = buffers.reduce((acc, { length }) => acc + length, 0);
2103
- const buf = new Uint8Array(size);
1774
+ const size = buffers.reduce((acc, { length }) => acc + length, 0), buf = new Uint8Array(size);
2104
1775
  let i = 0;
2105
- for (const buffer of buffers) {
2106
- buf.set(buffer, i);
2107
- i += buffer.length;
2108
- }
1776
+ for (const buffer of buffers)
1777
+ buf.set(buffer, i), i += buffer.length;
2109
1778
  return buf;
2110
1779
  }
1780
+ const NON_ASCII = /[^\x00-\x7f]/;
2111
1781
  function encode$1(string) {
1782
+ if (typeof string == "string" && string.length >= 128) {
1783
+ if (NON_ASCII.test(string))
1784
+ throw new TypeError("non-ASCII string encountered in encode()");
1785
+ return encoder$2.encode(string);
1786
+ }
2112
1787
  const bytes = new Uint8Array(string.length);
2113
1788
  for (let i = 0; i < string.length; i++) {
2114
1789
  const code = string.charCodeAt(i);
2115
- if (code > 127) {
1790
+ if (code > 127)
2116
1791
  throw new TypeError("non-ASCII string encountered in encode()");
2117
- }
2118
1792
  bytes[i] = code;
2119
1793
  }
2120
1794
  return bytes;
2121
1795
  }
2122
- const unusable = (name, prop = "algorithm.name") => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
2123
- function checkUsage(key, usage) {
2124
- if (usage && !key.usages.includes(usage)) {
2125
- throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
2126
- }
2127
- }
2128
- function checkModulusLength(alg, key) {
2129
- const { modulusLength } = key.algorithm;
2130
- if (typeof modulusLength !== "number" || modulusLength < 2048) {
2131
- throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
2132
- }
2133
- }
2134
- function checkCryptoKey(key, expected, usage) {
2135
- const algorithm = key.algorithm;
2136
- if (algorithm.name !== expected.name) {
2137
- throw unusable(expected.name);
2138
- }
2139
- if (expected.hash && algorithm.hash?.name !== expected.hash) {
2140
- throw unusable(expected.hash, "algorithm.hash");
2141
- }
2142
- if (expected.namedCurve && algorithm.namedCurve !== expected.namedCurve) {
2143
- throw unusable(expected.namedCurve, "algorithm.namedCurve");
2144
- }
2145
- if (expected.length !== void 0 && algorithm.length !== expected.length) {
2146
- throw unusable(expected.length, "algorithm.length");
2147
- }
2148
- checkUsage(key, usage);
2149
- }
2150
- function message(msg, actual, ...types) {
2151
- if (types.length > 2) {
2152
- const last = types.pop();
2153
- msg += `one of type ${types.join(", ")}, or ${last}.`;
2154
- } else if (types.length === 2) {
2155
- msg += `one of type ${types[0]} or ${types[1]}.`;
2156
- } else {
2157
- msg += `of type ${types[0]}.`;
2158
- }
2159
- if (actual == null) {
2160
- msg += ` Received ${actual}`;
2161
- } else if (typeof actual === "function" && actual.name) {
2162
- msg += ` Received function ${actual.name}`;
2163
- } else if (typeof actual === "object" && actual != null) {
2164
- if (actual.constructor?.name) {
2165
- msg += ` Received an instance of ${actual.constructor.name}`;
2166
- }
2167
- }
2168
- return msg;
1796
+ function encodeBase64(input, url = false) {
1797
+ if (Uint8Array.prototype.toBase64)
1798
+ return input.toBase64({ alphabet: url ? "base64url" : "base64", omitPadding: url });
1799
+ const CHUNK_SIZE = 32768, arr = [];
1800
+ for (let i = 0; i < input.length; i += CHUNK_SIZE)
1801
+ arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
1802
+ const encoded = btoa(arr.join(""));
1803
+ return url ? encoded.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : encoded;
1804
+ }
1805
+ function decodeBase64(encoded, url = false) {
1806
+ if (Uint8Array.fromBase64)
1807
+ return Uint8Array.fromBase64(encoded, { alphabet: url ? "base64url" : "base64" });
1808
+ if (url) {
1809
+ if (encoded.includes("+") || encoded.includes("/"))
1810
+ throw new TypeError("Invalid base64url");
1811
+ encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
1812
+ }
1813
+ const binary = atob(encoded), bytes = new Uint8Array(binary.length);
1814
+ for (let i = 0; i < binary.length; i++)
1815
+ bytes[i] = binary.charCodeAt(i);
1816
+ return bytes;
2169
1817
  }
2170
- const withAlg = (alg, actual, ...types) => message(`Key for the ${alg} algorithm must be `, actual, ...types);
2171
1818
  class JOSEError extends Error {
2172
1819
  static code = "ERR_JOSE_GENERIC";
2173
1820
  code = "ERR_JOSE_GENERIC";
2174
1821
  constructor(message2, options) {
2175
- super(message2, options);
2176
- this.name = this.constructor.name;
2177
- Error.captureStackTrace?.(this, this.constructor);
1822
+ super(message2, options), this.name = this.constructor.name, Error.captureStackTrace?.(this, this.constructor);
2178
1823
  }
2179
1824
  }
2180
1825
  class JWTClaimValidationFailed extends JOSEError {
@@ -2184,10 +1829,7 @@ class JWTClaimValidationFailed extends JOSEError {
2184
1829
  reason;
2185
1830
  payload;
2186
1831
  constructor(message2, payload, claim = "unspecified", reason = "unspecified") {
2187
- super(message2, { cause: { claim, reason, payload } });
2188
- this.claim = claim;
2189
- this.reason = reason;
2190
- this.payload = payload;
1832
+ super(message2, { cause: { claim, reason, payload } }), this.claim = claim, this.reason = reason, this.payload = payload;
2191
1833
  }
2192
1834
  }
2193
1835
  class JWTExpired extends JOSEError {
@@ -2197,10 +1839,7 @@ class JWTExpired extends JOSEError {
2197
1839
  reason;
2198
1840
  payload;
2199
1841
  constructor(message2, payload, claim = "unspecified", reason = "unspecified") {
2200
- super(message2, { cause: { claim, reason, payload } });
2201
- this.claim = claim;
2202
- this.reason = reason;
2203
- this.payload = payload;
1842
+ super(message2, { cause: { claim, reason, payload } }), this.claim = claim, this.reason = reason, this.payload = payload;
2204
1843
  }
2205
1844
  }
2206
1845
  class JOSEAlgNotAllowed extends JOSEError {
@@ -2246,207 +1885,168 @@ class JWSSignatureVerificationFailed extends JOSEError {
2246
1885
  super(message2, options);
2247
1886
  }
2248
1887
  }
2249
- const isCryptoKey = (key) => {
2250
- if (key?.[Symbol.toStringTag] === "CryptoKey")
2251
- return true;
1888
+ const invalid$1 = "The input to be decoded is not correctly encoded.";
1889
+ function decode(input) {
2252
1890
  try {
2253
- return key instanceof CryptoKey;
2254
- } catch {
2255
- return false;
2256
- }
2257
- };
2258
- const isKeyObject = (key) => key?.[Symbol.toStringTag] === "KeyObject";
2259
- const isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);
2260
- function encodeBase64(input) {
2261
- if (Uint8Array.prototype.toBase64) {
2262
- return input.toBase64();
2263
- }
2264
- const CHUNK_SIZE = 32768;
2265
- const arr = [];
2266
- for (let i = 0; i < input.length; i += CHUNK_SIZE) {
2267
- arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
2268
- }
2269
- return btoa(arr.join(""));
2270
- }
2271
- function decodeBase64(encoded) {
2272
- if (Uint8Array.fromBase64) {
2273
- return Uint8Array.fromBase64(encoded);
2274
- }
2275
- const binary = atob(encoded);
2276
- const bytes = new Uint8Array(binary.length);
2277
- for (let i = 0; i < binary.length; i++) {
2278
- bytes[i] = binary.charCodeAt(i);
2279
- }
2280
- return bytes;
2281
- }
2282
- const invalid$1 = "The input to be decoded is not correctly encoded.";
2283
- function decode(input) {
2284
- if (Uint8Array.fromBase64) {
2285
- try {
2286
- return Uint8Array.fromBase64(typeof input === "string" ? input : decoder$1.decode(input), {
2287
- alphabet: "base64url"
2288
- });
2289
- } catch (cause) {
2290
- throw new TypeError(invalid$1, { cause });
2291
- }
2292
- }
2293
- let encoded = input;
2294
- if (encoded instanceof Uint8Array) {
2295
- encoded = decoder$1.decode(encoded);
2296
- }
2297
- if (encoded.includes("+") || encoded.includes("/")) {
2298
- throw new TypeError(invalid$1);
2299
- }
2300
- encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
2301
- try {
2302
- return decodeBase64(encoded);
2303
- } catch {
2304
- throw new TypeError(invalid$1);
1891
+ return decodeBase64(typeof input == "string" ? input : decoder$1.decode(input), true);
1892
+ } catch (cause) {
1893
+ throw new TypeError(invalid$1, { cause });
2305
1894
  }
2306
1895
  }
2307
1896
  function encode(input) {
2308
- let unencoded = input;
2309
- if (typeof unencoded === "string") {
2310
- unencoded = encoder$2.encode(unencoded);
2311
- }
2312
- if (Uint8Array.prototype.toBase64) {
2313
- return unencoded.toBase64({ alphabet: "base64url", omitPadding: true });
2314
- }
2315
- return encodeBase64(unencoded).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
1897
+ return encodeBase64(typeof input == "string" ? encoder$2.encode(input) : input, true);
2316
1898
  }
2317
1899
  function isObject(input) {
2318
- if (typeof input !== "object" || input === null || Object.prototype.toString.call(input) !== "[object Object]") {
1900
+ if (typeof input != "object" || input === null || Object.prototype.toString.call(input) !== "[object Object]")
2319
1901
  return false;
2320
- }
2321
1902
  const prototype = Object.getPrototypeOf(input);
2322
- if (prototype === null) {
2323
- return true;
2324
- }
2325
- let proto = prototype;
2326
- while (Object.getPrototypeOf(proto) !== null) {
2327
- proto = Object.getPrototypeOf(proto);
2328
- }
2329
- return prototype === proto;
1903
+ return prototype === null || Object.getPrototypeOf(prototype) === null;
1904
+ }
1905
+ function isJwkSet(input) {
1906
+ return isObject(input) && Array.isArray(input.keys) && Array.from(input.keys).every(isObject);
2330
1907
  }
2331
1908
  function isDisjoint(...headers) {
2332
1909
  const parameters = /* @__PURE__ */ new Set();
2333
- for (const header of headers) {
2334
- if (!header)
2335
- continue;
2336
- for (const parameter of Object.keys(header)) {
2337
- if (parameters.has(parameter)) {
2338
- return false;
1910
+ for (const header of headers)
1911
+ if (header)
1912
+ for (const parameter of Object.keys(header)) {
1913
+ if (parameters.has(parameter))
1914
+ return false;
1915
+ parameters.add(parameter);
2339
1916
  }
2340
- parameters.add(parameter);
2341
- }
2342
- }
2343
1917
  return true;
2344
1918
  }
2345
- const isJWK = (key) => isObject(key) && typeof key.kty === "string";
2346
- const isPrivateJWK = (key) => key.kty !== "oct" && (key.kty === "AKP" && typeof key.priv === "string" || typeof key.d === "string");
2347
- const isPublicJWK = (key) => key.kty !== "oct" && key.d === void 0 && key.priv === void 0;
2348
- const isSecretJWK = (key) => key.kty === "oct" && typeof key.k === "string";
2349
1919
  function assertNotSet(value, name) {
2350
- if (value) {
1920
+ if (value !== void 0)
2351
1921
  throw new TypeError(`${name} can only be called once`);
2352
- }
2353
1922
  }
2354
1923
  function decodeBase64url(value, label, ErrorClass) {
2355
1924
  try {
2356
1925
  return decode(value);
2357
- } catch {
2358
- throw new ErrorClass(`Failed to base64url decode the ${label}`);
1926
+ } catch (cause) {
1927
+ throw new ErrorClass(`Failed to base64url decode the ${label}`, { cause });
2359
1928
  }
2360
1929
  }
2361
- function encodeBase64url(value, label, ErrorClass) {
1930
+ function encodeAsciiMember(value, label, ErrorClass) {
2362
1931
  try {
2363
1932
  return encode$1(value);
2364
- } catch {
2365
- throw new ErrorClass(`The ${label} is not a valid base64url string`);
1933
+ } catch (cause) {
1934
+ throw new ErrorClass(`The ${label} is not a valid base64url string`, { cause });
2366
1935
  }
2367
1936
  }
2368
- function parseJoseHeader(b64, ErrorClass, message2) {
1937
+ function parseJoseHeader(encodedProtectedHeader, ErrorClass, message2) {
2369
1938
  let parsed;
2370
1939
  try {
2371
- parsed = JSON.parse(strictDecoder.decode(decode(b64)));
2372
- } catch {
2373
- throw new ErrorClass(message2);
1940
+ parsed = JSON.parse(strictDecoder.decode(decode(encodedProtectedHeader)));
1941
+ } catch (cause) {
1942
+ throw new ErrorClass(message2, { cause });
2374
1943
  }
2375
- if (!isObject(parsed)) {
1944
+ if (!isObject(parsed))
2376
1945
  throw new ErrorClass(message2);
2377
- }
2378
1946
  return parsed;
2379
1947
  }
2380
- async function jwkToKey(entry, jwk) {
2381
- if (jwk.kty === "RSA" && "oth" in jwk && jwk.oth !== void 0) {
2382
- throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported');
1948
+ const JWS_RECOGNIZED = { __proto__: null, b64: true };
1949
+ function validateAlgorithms(option, algorithms) {
1950
+ if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s != "string")))
1951
+ throw new TypeError(`"${option}" option must be an array of strings`);
1952
+ return algorithms === void 0 ? void 0 : new Set(algorithms);
1953
+ }
1954
+ function validateCritDuplicates(Err, protectedHeader) {
1955
+ const { crit } = protectedHeader ?? {};
1956
+ if (Array.isArray(crit) && new Set(crit).size !== crit.length)
1957
+ throw new Err('"crit" (Critical) Header Parameter MUST NOT contain duplicate values');
1958
+ }
1959
+ function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
1960
+ if (joseHeader.crit !== void 0 && protectedHeader?.crit === void 0)
1961
+ throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
1962
+ if (!protectedHeader || protectedHeader.crit === void 0)
1963
+ return [];
1964
+ if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input != "string" || input.length === 0))
1965
+ throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
1966
+ const recognized = recognizedOption === void 0 ? recognizedDefault : { __proto__: null, ...recognizedOption, ...recognizedDefault };
1967
+ for (const parameter of protectedHeader.crit) {
1968
+ if (!(parameter in recognized))
1969
+ throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
1970
+ if (!Object.hasOwn(joseHeader, parameter) || joseHeader[parameter] === void 0)
1971
+ throw new Err(`Extension Header Parameter "${parameter}" is missing`);
1972
+ if (recognized[parameter] && (!Object.hasOwn(protectedHeader, parameter) || protectedHeader[parameter] === void 0))
1973
+ throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
2383
1974
  }
2384
- if (!entry.kty.includes(jwk.kty)) {
2385
- throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
1975
+ return protectedHeader.crit;
1976
+ }
1977
+ function validateB64(protectedHeader, extensions) {
1978
+ if (extensions.includes("b64")) {
1979
+ const b64 = protectedHeader.b64;
1980
+ if (typeof b64 != "boolean")
1981
+ throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
1982
+ return b64;
2386
1983
  }
2387
- const algorithm = entry.resolve?.({ kty: jwk.kty, crv: jwk.crv }) ?? entry.subtle;
2388
- const isPrivate = !!(jwk.d || jwk.priv);
2389
- const keyData = { ...jwk };
2390
- if (keyData.kty !== "AKP") {
2391
- delete keyData.alg;
1984
+ return true;
1985
+ }
1986
+ function serializeJoseHeader(Err, header) {
1987
+ let serialized, parsed;
1988
+ try {
1989
+ serialized = JSON.stringify(header), parsed = JSON.parse(serialized);
1990
+ } catch (cause) {
1991
+ throw new Err("JOSE Header is not valid JSON", { cause });
2392
1992
  }
2393
- delete keyData.use;
2394
- return crypto.subtle.importKey("jwk", keyData, algorithm, jwk.ext ?? !isPrivate, jwk.key_ops ?? entry.usages[isPrivate ? 1 : 0]);
1993
+ if (!isObject(parsed))
1994
+ throw new Err("JOSE Header is not a JSON object");
1995
+ return [parsed, serialized];
2395
1996
  }
2396
- const tag = (key) => key[Symbol.toStringTag];
2397
- const jwkMatchesOp = (entry, key, usage) => {
1997
+ const tag = (key) => key[Symbol.toStringTag], jwkMatchesOp = (entry, key, usage) => {
2398
1998
  const { alg } = entry;
2399
1999
  if (key.use !== void 0) {
2400
2000
  const expected = usage === "sign" || usage === "verify" ? "sig" : "enc";
2401
- if (key.use !== expected) {
2001
+ if (key.use !== expected)
2402
2002
  throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
2403
- }
2404
2003
  }
2405
- if (key.alg !== void 0 && key.alg !== alg) {
2004
+ if (key.alg !== void 0 && key.alg !== alg)
2406
2005
  throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
2407
- }
2408
2006
  if (Array.isArray(key.key_ops)) {
2409
2007
  const expectedKeyOp = usage === "encrypt" || usage === "decrypt" ? entry.ops?.[usage === "encrypt" ? 0 : 1] : usage;
2410
- if (expectedKeyOp && !key.key_ops.includes(expectedKeyOp)) {
2008
+ if (expectedKeyOp && !key.key_ops.includes(expectedKeyOp))
2411
2009
  throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
2412
- }
2413
2010
  }
2414
2011
  };
2415
- function checkKeyType(entry, key, usage) {
2416
- const { alg, secret } = entry;
2417
- const privateKey = usage === "decrypt" || usage === "sign";
2012
+ async function prepareKey(entry, key, usage) {
2013
+ const { alg, secret } = entry, requiresPrivateKey = usage === "decrypt" || usage === "sign";
2418
2014
  if (secret && key instanceof Uint8Array)
2419
- return [BYTES, key];
2420
- if (isJWK(key)) {
2421
- if (secret ? !isSecretJWK(key) : !(privateKey ? isPrivateJWK(key) : isPublicJWK(key))) {
2422
- throw new TypeError(secret ? `JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present` : `JSON Web Key for this operation must be a ${privateKey ? "private" : "public"} JWK`);
2423
- }
2424
- jwkMatchesOp(entry, key, usage);
2425
- return [JWK, key];
2426
- }
2427
- if (!isKeyLike(key)) {
2428
- throw new TypeError(secret ? withAlg(alg, key, "CryptoKey", "KeyObject", "JSON Web Key", "Uint8Array") : withAlg(alg, key, "CryptoKey", "KeyObject", "JSON Web Key"));
2429
- }
2430
- if (secret) {
2431
- if (key.type !== "secret") {
2432
- throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
2015
+ return key;
2016
+ let normalized, keyObject;
2017
+ if (isObject(key)) {
2018
+ if (normalized = normalizeJwk(key), typeof normalized.kty != "string")
2019
+ throw invalidKeyType(alg, key, secret);
2020
+ if (!(secret ? normalized.kty === "oct" && typeof normalized.k == "string" : normalized.kty !== "oct" && (requiresPrivateKey ? normalized.kty === "AKP" && typeof normalized.priv == "string" || typeof normalized.d == "string" : normalized.d === void 0 && normalized.priv === void 0)))
2021
+ throw new TypeError(secret ? 'JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present' : `JSON Web Key for this operation must be a ${requiresPrivateKey ? "private" : "public"} JWK`);
2022
+ if (jwkMatchesOp(entry, normalized, usage), normalized.kty === "oct")
2023
+ return decode(normalized.k);
2024
+ if (!Object.isFrozen(key)) {
2025
+ const { key_ops } = key;
2026
+ Array.isArray(key_ops) && Object.freeze(key_ops), Object.freeze(key);
2433
2027
  }
2434
2028
  } else {
2435
- if (key.type === "secret") {
2436
- throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
2437
- }
2438
- const expectedType = privateKey ? "private" : "public";
2439
- if ((key.type === "public" || key.type === "private") && key.type !== expectedType) {
2440
- const operation = usage === "sign" ? "signing" : usage === "verify" ? "verifying" : `${usage.slice(0, -1)}tion`;
2441
- throw new TypeError(`${tag(key)} instances for asymmetric algorithm ${operation} must be of type "${expectedType}"`);
2442
- }
2029
+ if (!isKeyLike(key))
2030
+ throw invalidKeyType(alg, key, secret);
2031
+ const expectedType = secret ? "secret" : requiresPrivateKey ? "private" : "public";
2032
+ if (key.type !== expectedType && (secret || ["secret", "public", "private"].includes(key.type)))
2033
+ throw new TypeError(`${tag(key)} instances must be of type "${expectedType}" for the ${alg} algorithm`);
2034
+ if (isCryptoKey(key))
2035
+ return key;
2036
+ if (keyObject = key, keyObject.type === "secret")
2037
+ return keyObject.export();
2443
2038
  }
2444
- return isCryptoKey(key) ? [CRYPTO, key] : [KEYOBJECT, key];
2039
+ cache ||= /* @__PURE__ */ new WeakMap();
2040
+ const cacheKey = key;
2041
+ let cached = cache.get(cacheKey);
2042
+ if (cached?.[alg])
2043
+ return cached[alg];
2044
+ if (cached || cache.set(cacheKey, cached = {}), keyObject && typeof keyObject.toCryptoKey == "function") {
2045
+ const isPublic = keyObject.type === "public", crv = nist[keyObject.asymmetricKeyDetails?.namedCurve], params = entry.resolve?.({ crv, asymmetricKeyType: keyObject.asymmetricKeyType }) ?? entry.subtle;
2046
+ return cached[alg] = keyObject.toCryptoKey(params, isPublic, entry.usages[isPublic ? 0 : 1]);
2047
+ }
2048
+ return normalized ??= keyObject.export({ format: "jwk" }), normalized.alg = alg, cached[alg] = await jwkToKey(entry, normalized);
2445
2049
  }
2446
- const BYTES = 0;
2447
- const CRYPTO = 1;
2448
- const KEYOBJECT = 2;
2449
- const JWK = 3;
2450
2050
  let cache;
2451
2051
  const nist = {
2452
2052
  __proto__: null,
@@ -2454,93 +2054,104 @@ const nist = {
2454
2054
  secp384r1: "P-384",
2455
2055
  secp521r1: "P-521"
2456
2056
  };
2457
- function cached(key, alg, value) {
2458
- cache ||= /* @__PURE__ */ new WeakMap();
2459
- const entry = cache.get(key);
2460
- if (value) {
2461
- if (entry) {
2462
- entry[alg] = value;
2463
- } else {
2464
- cache.set(key, { __proto__: null, [alg]: value });
2465
- }
2466
- }
2467
- return value ?? entry?.[alg];
2468
- }
2469
- const handleJWK = async (key, jwk, entry) => cached(key, entry.alg) ?? cached(key, entry.alg, await jwkToKey(entry, { ...jwk, alg: entry.alg }));
2470
- const handleKeyObject = (keyObject, entry) => {
2471
- const hit = cached(keyObject, entry.alg);
2472
- if (hit)
2473
- return hit;
2474
- const isPublic = keyObject.type === "public";
2475
- const usages = entry.usages[isPublic ? 0 : 1];
2476
- const { asymmetricKeyType } = keyObject;
2477
- const crv = nist[keyObject.asymmetricKeyDetails?.namedCurve];
2478
- const params = entry.resolve?.({ crv, asymmetricKeyType }) ?? entry.subtle;
2479
- return cached(keyObject, entry.alg, keyObject.toCryptoKey(params, isPublic, usages));
2480
- };
2481
- async function prepareKey(entry, key, usage) {
2482
- const tagged = checkKeyType(entry, key, usage);
2483
- switch (tagged[0]) {
2484
- case BYTES:
2485
- case CRYPTO:
2486
- return tagged[1];
2487
- case JWK: {
2488
- const key2 = tagged[1];
2489
- if (key2.k) {
2490
- return decode(key2.k);
2491
- }
2492
- if (!Object.isFrozen(key2)) {
2493
- const { key_ops } = key2;
2494
- if (Array.isArray(key_ops))
2495
- Object.freeze(key_ops);
2496
- Object.freeze(key2);
2497
- }
2498
- return handleJWK(key2, key2, entry);
2499
- }
2500
- case KEYOBJECT: {
2501
- const keyObject = tagged[1];
2502
- if (keyObject.type === "secret") {
2503
- return keyObject.export();
2504
- }
2505
- if ("toCryptoKey" in keyObject && typeof keyObject.toCryptoKey === "function") {
2506
- return handleKeyObject(keyObject, entry);
2507
- }
2508
- return handleJWK(keyObject, keyObject.export({ format: "jwk" }), entry);
2509
- }
2057
+ const isCryptoKey = (key) => {
2058
+ if (key?.[Symbol.toStringTag] === "CryptoKey")
2059
+ return true;
2060
+ try {
2061
+ return key instanceof CryptoKey;
2062
+ } catch {
2063
+ return false;
2510
2064
  }
2065
+ }, isKeyObject = (key) => key?.[Symbol.toStringTag] === "KeyObject", isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);
2066
+ function message(msg, actual, ...types) {
2067
+ if (types.length > 2) {
2068
+ const last = types.pop();
2069
+ msg += `one of type ${types.join(", ")}, or ${last}.`;
2070
+ } else types.length === 2 ? msg += `one of type ${types[0]} or ${types[1]}.` : msg += `of type ${types[0]}.`;
2071
+ return actual == null ? msg += ` Received ${actual}` : typeof actual == "function" && actual.name ? msg += ` Received function ${actual.name}` : typeof actual == "object" && actual != null && actual.constructor?.name && (msg += ` Received an instance of ${actual.constructor.name}`), msg;
2072
+ }
2073
+ function invalidKeyType(alg, actual, secret) {
2074
+ const types = ["CryptoKey", "KeyObject", "JSON Web Key"];
2075
+ return secret && types.push("Uint8Array"), new TypeError(message(`Key for the ${alg} algorithm must be `, actual, ...types));
2076
+ }
2077
+ const unusable = (name, prop = "algorithm.name") => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
2078
+ function checkUsage(key, usage) {
2079
+ if (usage && !key.usages.includes(usage))
2080
+ throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
2081
+ }
2082
+ function checkModulusLength(alg, key) {
2083
+ const { modulusLength } = key.algorithm;
2084
+ if (typeof modulusLength != "number" || modulusLength < 2048)
2085
+ throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
2086
+ }
2087
+ function checkCryptoKey(key, expected, usage) {
2088
+ const algorithm = key.algorithm;
2089
+ if (algorithm.name !== expected.name)
2090
+ throw unusable(expected.name);
2091
+ if (expected.hash && algorithm.hash?.name !== expected.hash)
2092
+ throw unusable(expected.hash, "algorithm.hash");
2093
+ if (expected.namedCurve && algorithm.namedCurve !== expected.namedCurve)
2094
+ throw unusable(expected.namedCurve, "algorithm.namedCurve");
2095
+ if (expected.length !== void 0 && algorithm.length !== expected.length)
2096
+ throw unusable(expected.length, "algorithm.length");
2097
+ checkUsage(key, usage);
2098
+ }
2099
+ function snapshotJwk(jwk) {
2100
+ return { __proto__: null, ...jwk };
2101
+ }
2102
+ function normalizeJwk(jwk) {
2103
+ const normalized = snapshotJwk(jwk);
2104
+ if (normalized.ext !== void 0 && typeof normalized.ext != "boolean")
2105
+ throw new TypeError('"ext" (Extractable) Parameter must be a boolean');
2106
+ if (normalized.key_ops !== void 0) {
2107
+ const value = normalized.key_ops, keyOps = Array.isArray(value) ? [...value] : void 0;
2108
+ if (!keyOps || keyOps.some((operation) => typeof operation != "string") || new Set(keyOps).size !== keyOps.length)
2109
+ throw new TypeError('"key_ops" (Key Operations) Parameter must be an array of unique strings');
2110
+ normalized.key_ops = keyOps;
2111
+ }
2112
+ return normalized;
2113
+ }
2114
+ function validateExtractableOption(extractable) {
2115
+ return extractable;
2116
+ }
2117
+ async function jwkToKey(entry, jwk, extractable) {
2118
+ if (!entry.kty.includes(jwk.kty))
2119
+ throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
2120
+ const algorithm = entry.resolve?.({ kty: jwk.kty, crv: jwk.crv }) ?? entry.subtle, isPrivate = !!(jwk.d || jwk.priv), keyData = { ...jwk, ext: extractable ?? jwk.ext };
2121
+ return keyData.kty !== "AKP" && delete keyData.alg, delete keyData.use, crypto.subtle.importKey("jwk", keyData, algorithm, keyData.ext ?? !isPrivate, jwk.key_ops ?? entry.usages[isPrivate ? 1 : 0]);
2122
+ }
2123
+ async function rawKey(key, expected, usage, extractable = false) {
2124
+ return key instanceof Uint8Array && (key = await crypto.subtle.importKey("raw", key, expected, extractable, [usage])), checkCryptoKey(key, expected, usage), key;
2511
2125
  }
2512
2126
  function table(entries) {
2513
2127
  const out = { __proto__: null };
2514
- for (const alg in entries) {
2128
+ for (const alg in entries)
2515
2129
  out[alg] = { ...entries[alg], alg };
2516
- }
2517
2130
  return out;
2518
2131
  }
2519
2132
  const wrap = [
2520
2133
  ["encrypt", "wrapKey"],
2521
2134
  ["decrypt", "unwrapKey"]
2522
- ];
2523
- const derive = [[], ["deriveBits"]];
2524
- const none = [[], []];
2135
+ ], derive = [[], ["deriveBits"]], none = [[], []];
2525
2136
  function rsaes(bits) {
2526
2137
  return {
2527
2138
  kty: ["RSA"],
2139
+ mode: "key-encryption",
2528
2140
  subtle: { name: "RSA-OAEP", hash: `SHA-${bits}` },
2529
2141
  usages: wrap,
2530
2142
  ops: ["wrapKey", "unwrapKey"]
2531
2143
  };
2532
2144
  }
2533
- function ecdh() {
2145
+ function ecdh(mode) {
2534
2146
  return {
2535
2147
  kty: ["EC", "OKP"],
2148
+ mode,
2536
2149
  subtle: { name: "ECDH" },
2537
2150
  resolve: ({ kty, crv, asymmetricKeyType }) => {
2538
- if (crv === "X25519" || asymmetricKeyType === "x25519") {
2151
+ if (crv === "X25519" || asymmetricKeyType === "x25519")
2539
2152
  return { name: "X25519" };
2540
- }
2541
- if (kty === "OKP") {
2153
+ if (kty === "OKP")
2542
2154
  throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
2543
- }
2544
2155
  return { name: "ECDH", namedCurve: crv };
2545
2156
  },
2546
2157
  usages: derive,
@@ -2550,6 +2161,7 @@ function ecdh() {
2550
2161
  function aeskw(bits, gcm = false) {
2551
2162
  return {
2552
2163
  kty: ["oct"],
2164
+ mode: "key-wrapping",
2553
2165
  secret: true,
2554
2166
  subtle: { name: gcm ? "AES-GCM" : "AES-KW", length: bits },
2555
2167
  usages: none,
@@ -2559,6 +2171,7 @@ function aeskw(bits, gcm = false) {
2559
2171
  function pbes2() {
2560
2172
  return {
2561
2173
  kty: ["oct"],
2174
+ mode: "key-wrapping",
2562
2175
  secret: true,
2563
2176
  subtle: { name: "PBKDF2" },
2564
2177
  usages: none,
@@ -2568,6 +2181,7 @@ function pbes2() {
2568
2181
  const JWE = table({
2569
2182
  dir: {
2570
2183
  kty: ["oct"],
2184
+ mode: "direct-encryption",
2571
2185
  secret: true,
2572
2186
  subtle: { name: "AES-GCM" },
2573
2187
  usages: none,
@@ -2577,10 +2191,10 @@ const JWE = table({
2577
2191
  "RSA-OAEP-256": rsaes(256),
2578
2192
  "RSA-OAEP-384": rsaes(384),
2579
2193
  "RSA-OAEP-512": rsaes(512),
2580
- "ECDH-ES": ecdh(),
2581
- "ECDH-ES+A128KW": ecdh(),
2582
- "ECDH-ES+A192KW": ecdh(),
2583
- "ECDH-ES+A256KW": ecdh(),
2194
+ "ECDH-ES": ecdh("direct-key-agreement"),
2195
+ "ECDH-ES+A128KW": ecdh("key-agreement-with-key-wrapping"),
2196
+ "ECDH-ES+A192KW": ecdh("key-agreement-with-key-wrapping"),
2197
+ "ECDH-ES+A256KW": ecdh("key-agreement-with-key-wrapping"),
2584
2198
  A128KW: aeskw(128),
2585
2199
  A192KW: aeskw(192),
2586
2200
  A256KW: aeskw(256),
@@ -2590,8 +2204,7 @@ const JWE = table({
2590
2204
  "PBES2-HS256+A128KW": pbes2(),
2591
2205
  "PBES2-HS384+A192KW": pbes2(),
2592
2206
  "PBES2-HS512+A256KW": pbes2()
2593
- });
2594
- const contentOps = ["encrypt", "decrypt"];
2207
+ }), contentOps = ["encrypt", "decrypt"];
2595
2208
  function contentEncryption(bits, cbc = false) {
2596
2209
  return {
2597
2210
  kty: ["oct"],
@@ -2612,78 +2225,13 @@ table({
2612
2225
  "A192CBC-HS384": contentEncryption(384, true),
2613
2226
  "A256CBC-HS512": contentEncryption(512, true)
2614
2227
  });
2615
- const JWS_RECOGNIZED = { __proto__: null, b64: true };
2616
- function validateAlgorithms(option, algorithms) {
2617
- if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== "string"))) {
2618
- throw new TypeError(`"${option}" option must be an array of strings`);
2619
- }
2620
- if (!algorithms) {
2621
- return void 0;
2622
- }
2623
- return new Set(algorithms);
2624
- }
2625
- function validateCritDuplicates(Err, protectedHeader) {
2626
- const { crit } = protectedHeader ?? {};
2627
- if (Array.isArray(crit) && new Set(crit).size !== crit.length) {
2628
- throw new Err('"crit" (Critical) Header Parameter MUST NOT contain duplicate values');
2629
- }
2630
- }
2631
- function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
2632
- if (joseHeader.crit !== void 0 && protectedHeader?.crit === void 0) {
2633
- throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
2634
- }
2635
- if (!protectedHeader || protectedHeader.crit === void 0) {
2636
- return [];
2637
- }
2638
- if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input !== "string" || input.length === 0)) {
2639
- throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
2640
- }
2641
- const recognized = recognizedOption === void 0 ? recognizedDefault : { __proto__: null, ...recognizedOption, ...recognizedDefault };
2642
- for (const parameter of protectedHeader.crit) {
2643
- if (!(parameter in recognized)) {
2644
- throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
2645
- }
2646
- if (!Object.hasOwn(joseHeader, parameter) || joseHeader[parameter] === void 0) {
2647
- throw new Err(`Extension Header Parameter "${parameter}" is missing`);
2648
- }
2649
- if (recognized[parameter] && (!Object.hasOwn(protectedHeader, parameter) || protectedHeader[parameter] === void 0)) {
2650
- throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
2651
- }
2652
- }
2653
- return protectedHeader.crit;
2654
- }
2655
- async function getSigKey(entry, key, usage) {
2656
- if (key instanceof Uint8Array) {
2657
- return crypto.subtle.importKey("raw", key, entry.subtle, false, [
2658
- usage
2659
- ]);
2660
- }
2661
- checkCryptoKey(key, entry.subtle, usage);
2662
- if (entry.minRsaBits)
2663
- checkModulusLength(entry.alg, key);
2664
- return key;
2665
- }
2666
- async function sign(entry, key, data) {
2667
- const cryptoKey = await getSigKey(entry, key, "sign");
2668
- const signature = await crypto.subtle.sign(entry.signing, cryptoKey, data);
2669
- return new Uint8Array(signature);
2670
- }
2671
- async function verify(entry, key, signature, data) {
2672
- const cryptoKey = await getSigKey(entry, key, "verify");
2673
- try {
2674
- return await crypto.subtle.verify(entry.signing, cryptoKey, signature, data);
2675
- } catch {
2676
- return false;
2677
- }
2678
- }
2679
2228
  const sig = [["verify"], ["sign"]];
2680
2229
  function hmac(bits) {
2681
2230
  const subtle = { name: "HMAC", hash: `SHA-${bits}` };
2682
2231
  return { kty: ["oct"], secret: true, subtle, signing: subtle, usages: sig };
2683
2232
  }
2684
2233
  function rsa(bits, saltLength) {
2685
- const name = saltLength ? "RSA-PSS" : "RSASSA-PKCS1-v1_5";
2686
- const subtle = { name, hash: `SHA-${bits}` };
2234
+ const subtle = { name: saltLength ? "RSA-PSS" : "RSASSA-PKCS1-v1_5", hash: `SHA-${bits}` };
2687
2235
  return {
2688
2236
  kty: ["RSA"],
2689
2237
  subtle,
@@ -2711,9 +2259,8 @@ function eddsa() {
2711
2259
  usages: sig
2712
2260
  };
2713
2261
  }
2714
- function mldsa(bits) {
2715
- const name = `ML-DSA-${bits}`;
2716
- const subtle = { name };
2262
+ function mldsa(parameterSet) {
2263
+ const subtle = { name: `ML-DSA-${parameterSet}` };
2717
2264
  return {
2718
2265
  kty: ["AKP"],
2719
2266
  subtle,
@@ -2741,547 +2288,334 @@ const JWS = table({
2741
2288
  "ML-DSA-87": mldsa(87)
2742
2289
  });
2743
2290
  function jwsAlgorithm(alg) {
2744
- const entry = typeof alg === "string" ? JWS[alg] : void 0;
2745
- if (!entry) {
2291
+ const entry = typeof alg == "string" ? JWS[alg] : void 0;
2292
+ if (!entry)
2746
2293
  throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
2747
- }
2748
2294
  return entry;
2749
2295
  }
2750
2296
  function prepareVerify(options) {
2751
2297
  return [options && validateAlgorithms("algorithms", options.algorithms), options?.crit];
2752
2298
  }
2753
- async function verifySignature$1(jws, shared, key) {
2754
- const { protected: encodedProtected, header, payload: inputPayload } = jws;
2755
- let parsedProt = {};
2756
- if (encodedProtected) {
2757
- parsedProt = parseJoseHeader(encodedProtected, JWSInvalid, "JWS Protected Header is invalid");
2758
- }
2759
- let joseHeader;
2760
- if (header !== void 0) {
2761
- if (!isDisjoint(parsedProt, header)) {
2762
- throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
2763
- }
2764
- joseHeader = { ...parsedProt, ...header };
2765
- } else {
2766
- joseHeader = parsedProt;
2767
- }
2768
- const extensions = validateCrit(JWSInvalid, JWS_RECOGNIZED, shared[1], parsedProt, joseHeader);
2769
- let b64 = true;
2770
- if (extensions.includes("b64")) {
2771
- b64 = parsedProt.b64;
2772
- if (typeof b64 !== "boolean") {
2773
- throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
2774
- }
2299
+ function parseProtectedHeader(encodedProtectedHeader) {
2300
+ return encodedProtectedHeader === void 0 ? {} : parseJoseHeader(encodedProtectedHeader, JWSInvalid, "JWS Protected Header is invalid");
2301
+ }
2302
+ function encodeCompactUnencodedPayload(payload) {
2303
+ try {
2304
+ return encode$1(payload);
2305
+ } catch (cause) {
2306
+ throw new JWSInvalid("JWS Compact Serialization payload must use only ASCII characters", {
2307
+ cause
2308
+ });
2775
2309
  }
2776
- const { alg } = joseHeader;
2777
- if (typeof alg !== "string" || !alg) {
2310
+ }
2311
+ async function verifySignature$1(jws, shared, key, encodeUnencodedPayload, parsedProtected) {
2312
+ const { protected: encodedProtectedHeader, header, payload: inputPayload } = jws, protectedHeader = parseProtectedHeader(encodedProtectedHeader);
2313
+ if (!isDisjoint(protectedHeader, header))
2314
+ throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
2315
+ const joseHeader = { ...protectedHeader, ...header }, b64 = validateB64(protectedHeader, validateCrit(JWSInvalid, JWS_RECOGNIZED, shared[1], protectedHeader, joseHeader)), { alg } = joseHeader;
2316
+ if (typeof alg != "string" || !alg)
2778
2317
  throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
2779
- }
2780
- if (shared[0] && !shared[0].has(alg)) {
2318
+ if (shared[0] && !shared[0].has(alg))
2781
2319
  throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
2782
- }
2783
2320
  if (b64) {
2784
- if (typeof inputPayload !== "string") {
2321
+ if (typeof inputPayload != "string")
2785
2322
  throw new JWSInvalid("JWS Payload must be a string");
2786
- }
2787
- } else if (typeof inputPayload !== "string" && !(inputPayload instanceof Uint8Array)) {
2323
+ } else if (typeof inputPayload != "string" && !(inputPayload instanceof Uint8Array))
2788
2324
  throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance");
2789
- }
2325
+ const signingPayload = b64 || typeof inputPayload != "string" ? inputPayload : encodeUnencodedPayload(inputPayload);
2790
2326
  let resolvedKey = false;
2791
- if (typeof key === "function") {
2792
- key = await key(parsedProt, jws);
2793
- resolvedKey = true;
2327
+ typeof key == "function" && (key = await key(protectedHeader, jws), resolvedKey = true);
2328
+ const entry = jwsAlgorithm(alg), signingInput = concat(encodedProtectedHeader !== void 0 ? encode$1(encodedProtectedHeader) : new Uint8Array(), encode$1("."), typeof signingPayload == "string" ? shared[2] ??= encodeAsciiMember(signingPayload, "payload", JWSInvalid) : signingPayload), signature = decodeBase64url(jws.signature, "signature", JWSInvalid), verificationKey = await prepareKey(entry, key, "verify"), cryptoKey = await rawKey(verificationKey, entry.subtle, "verify");
2329
+ entry.minRsaBits && checkModulusLength(entry.alg, cryptoKey);
2330
+ let verified = false;
2331
+ try {
2332
+ verified = await crypto.subtle.verify(entry.signing, cryptoKey, signature, signingInput);
2333
+ } catch (cause) {
2334
+ throw new JWSSignatureVerificationFailed(void 0, { cause });
2794
2335
  }
2795
- const entry = jwsAlgorithm(alg);
2796
- const data = concat(encodedProtected !== void 0 ? encode$1(encodedProtected) : new Uint8Array(), encode$1("."), typeof inputPayload === "string" ? b64 ? shared[2] ??= encodeBase64url(inputPayload, "payload", JWSInvalid) : encoder$2.encode(inputPayload) : inputPayload);
2797
- const signature = decodeBase64url(jws.signature, "signature", JWSInvalid);
2798
- const k = await prepareKey(entry, key, "verify");
2799
- const verified = await verify(entry, k, signature, data);
2800
- if (!verified) {
2336
+ if (!verified)
2801
2337
  throw new JWSSignatureVerificationFailed();
2802
- }
2803
- let payload;
2804
- if (b64) {
2805
- payload = decodeBase64url(inputPayload, "payload", JWSInvalid);
2806
- } else if (typeof inputPayload === "string") {
2807
- payload = encoder$2.encode(inputPayload);
2808
- } else {
2809
- payload = inputPayload;
2810
- }
2811
- return [payload, parsedProt, b64, k, resolvedKey];
2338
+ const result = { payload: typeof signingPayload == "string" ? decodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload };
2339
+ return encodedProtectedHeader !== void 0 && (result.protectedHeader = protectedHeader), header !== void 0 && (result.unprotectedHeader = header), resolvedKey ? [{ ...result, key: verificationKey }, b64] : [result, b64];
2812
2340
  }
2813
2341
  async function verifyCompact(jws, shared, key) {
2814
- if (jws instanceof Uint8Array) {
2815
- jws = decoder$1.decode(jws);
2816
- }
2817
- if (typeof jws !== "string") {
2342
+ if (jws instanceof Uint8Array && (jws = decoder$1.decode(jws)), typeof jws != "string")
2818
2343
  throw new JWSInvalid("Compact JWS must be a string or Uint8Array");
2819
- }
2820
2344
  const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split(".");
2821
- if (length !== 3) {
2345
+ if (length !== 3)
2822
2346
  throw new JWSInvalid("Invalid Compact JWS");
2823
- }
2824
- return verifySignature$1({ payload, protected: protectedHeader, signature }, shared, key);
2347
+ return verifySignature$1({ payload, protected: protectedHeader, signature }, shared, key, encodeCompactUnencodedPayload);
2825
2348
  }
2826
- const epoch = (date) => Math.floor(date.getTime() / 1e3);
2827
- const multipliers = {
2349
+ const epoch = (date) => Math.floor(date.getTime() / 1e3), multipliers = {
2828
2350
  s: 1,
2829
2351
  m: 60,
2830
2352
  h: 3600,
2831
2353
  d: 86400,
2832
2354
  w: 604800,
2833
2355
  y: 31557600
2834
- };
2835
- const REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;
2836
- const checkFailed = "check_failed";
2356
+ }, REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i, checkFailed = "check_failed";
2357
+ function invalidDuration() {
2358
+ throw new TypeError("Invalid time period format");
2359
+ }
2837
2360
  function secs(str) {
2361
+ typeof str != "string" && invalidDuration();
2838
2362
  const matched = REGEX.exec(str);
2839
- if (!matched || matched[4] && matched[1]) {
2840
- throw new TypeError("Invalid time period format");
2841
- }
2842
- const value = parseFloat(matched[2]);
2843
- const numericDate2 = Math.round(value * multipliers[matched[3][0].toLowerCase()]);
2844
- if (matched[1] === "-" || matched[4] === "ago") {
2845
- return -numericDate2;
2846
- }
2847
- return numericDate2;
2363
+ (!matched || matched[4] && matched[1]) && invalidDuration();
2364
+ const value = parseFloat(matched[2]), durationSeconds = Math.round(value * multipliers[matched[3][0].toLowerCase()]);
2365
+ return Number.isFinite(durationSeconds) || invalidDuration(), matched[1] === "-" || matched[4] === "ago" ? -durationSeconds : durationSeconds;
2848
2366
  }
2849
2367
  function validateInput(label, input) {
2850
- if (!Number.isFinite(input)) {
2368
+ if (!Number.isFinite(input))
2851
2369
  throw new TypeError(`Invalid ${label} input`);
2852
- }
2853
2370
  return input;
2854
2371
  }
2855
- function numericDate(value, label) {
2856
- if (typeof value === "number")
2857
- return validateInput(label, value);
2858
- if (value instanceof Date)
2859
- return validateInput(label, epoch(value));
2860
- return epoch(/* @__PURE__ */ new Date()) + secs(value);
2372
+ function validateStringClaim(claim, value) {
2373
+ if (typeof value != "string")
2374
+ throw new TypeError(`"${claim}" claim must be a string`);
2861
2375
  }
2862
- const normalizeTyp = (value) => {
2863
- if (value.includes("/")) {
2864
- return value.toLowerCase();
2865
- }
2866
- return `application/${value.toLowerCase()}`;
2867
- };
2868
- const checkAudiencePresence = (audPayload, audOption) => {
2869
- if (typeof audPayload === "string") {
2870
- return audOption.includes(audPayload);
2871
- }
2872
- if (Array.isArray(audPayload)) {
2873
- return audOption.some((aud) => audPayload.includes(aud));
2874
- }
2875
- return false;
2876
- };
2877
- function validateNumericDate(payload, claim, required = false) {
2878
- const value = payload[claim];
2879
- if (value === void 0 && !required)
2880
- return void 0;
2881
- if (typeof value !== "number") {
2882
- throw new JWTClaimValidationFailed(`"${claim}" claim must be a number`, payload, claim, "invalid");
2883
- }
2884
- return value;
2376
+ function validateAudienceClaim(value) {
2377
+ if (typeof value != "string" && (!Array.isArray(value) || Array.from(value).some((member) => typeof member != "string")))
2378
+ throw new TypeError('"aud" claim must be a string or an array of strings');
2885
2379
  }
2886
- function unexpectedClaim(payload, claim) {
2887
- throw new JWTClaimValidationFailed(`unexpected "${claim}" claim value`, payload, claim, checkFailed);
2380
+ function numericDate(value, label) {
2381
+ return typeof value == "number" ? validateInput(label, value) : value instanceof Date ? validateInput(label, epoch(value)) : epoch(/* @__PURE__ */ new Date()) + secs(value);
2888
2382
  }
2889
- function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {
2890
- let payload;
2383
+ const normalizeTyp = (value) => {
2384
+ const normalized = value.toLowerCase();
2385
+ return value.includes("/") ? normalized : `application/${normalized}`;
2386
+ }, checkAudiencePresence = (audPayload, audOption) => typeof audPayload == "string" ? audOption.includes(audPayload) : Array.isArray(audPayload) ? audOption.some((aud) => audPayload.includes(aud)) : false;
2387
+ function validateNumericDate(claimsSet, claim, required = false) {
2388
+ const value = claimsSet[claim];
2389
+ if (!(value === void 0 && !required)) {
2390
+ if (typeof value != "number")
2391
+ throw new JWTClaimValidationFailed(`"${claim}" claim must be a number`, claimsSet, claim, "invalid");
2392
+ return value;
2393
+ }
2394
+ }
2395
+ function unexpectedClaim(claimsSet, claim) {
2396
+ throw new JWTClaimValidationFailed(`unexpected "${claim}" claim value`, claimsSet, claim, checkFailed);
2397
+ }
2398
+ function validateClaimsSet(protectedHeader, claimsSetBytes, options = {}) {
2399
+ let claimsSet;
2891
2400
  try {
2892
- payload = JSON.parse(strictDecoder.decode(encodedPayload));
2893
- } catch {
2401
+ claimsSet = JSON.parse(strictDecoder.decode(claimsSetBytes));
2402
+ } catch (cause) {
2403
+ throw new JWTInvalid("JWT Claims Set must be a top-level JSON object", { cause });
2894
2404
  }
2895
- if (!isObject(payload)) {
2405
+ if (!isObject(claimsSet))
2896
2406
  throw new JWTInvalid("JWT Claims Set must be a top-level JSON object");
2897
- }
2898
2407
  const { typ } = options;
2899
- if (typ && (typeof protectedHeader.typ !== "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) {
2900
- throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', payload, "typ", checkFailed);
2901
- }
2902
- const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options;
2903
- const presenceCheck = [...requiredClaims];
2904
- if (maxTokenAge !== void 0)
2905
- presenceCheck.push("iat");
2906
- if (audience !== void 0)
2907
- presenceCheck.push("aud");
2908
- if (subject !== void 0)
2909
- presenceCheck.push("sub");
2910
- if (issuer !== void 0)
2911
- presenceCheck.push("iss");
2912
- for (const claim of new Set(presenceCheck.reverse())) {
2913
- if (!Object.hasOwn(payload, claim)) {
2914
- throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, payload, claim, "missing");
2915
- }
2916
- }
2917
- if (issuer !== void 0 && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) {
2918
- unexpectedClaim(payload, "iss");
2919
- }
2920
- if (subject !== void 0 && payload.sub !== subject) {
2921
- unexpectedClaim(payload, "sub");
2922
- }
2923
- if (audience !== void 0 && !checkAudiencePresence(payload.aud, typeof audience === "string" ? [audience] : audience)) {
2924
- unexpectedClaim(payload, "aud");
2925
- }
2408
+ if (typ !== void 0 && (typeof protectedHeader.typ != "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ)))
2409
+ throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', claimsSet, "typ", checkFailed);
2410
+ const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options, presenceCheck = [...requiredClaims];
2411
+ maxTokenAge !== void 0 && presenceCheck.push("iat"), audience !== void 0 && presenceCheck.push("aud"), subject !== void 0 && presenceCheck.push("sub"), issuer !== void 0 && presenceCheck.push("iss");
2412
+ for (const claim of new Set(presenceCheck.reverse()))
2413
+ if (!Object.hasOwn(claimsSet, claim))
2414
+ throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, claimsSet, claim, "missing");
2415
+ issuer !== void 0 && !(Array.isArray(issuer) ? issuer : [issuer]).includes(claimsSet.iss) && unexpectedClaim(claimsSet, "iss"), subject !== void 0 && claimsSet.sub !== subject && unexpectedClaim(claimsSet, "sub"), audience !== void 0 && !checkAudiencePresence(claimsSet.aud, typeof audience == "string" ? [audience] : audience) && unexpectedClaim(claimsSet, "aud");
2926
2416
  const { clockTolerance } = options;
2927
2417
  let tolerance = 0;
2928
- if (typeof clockTolerance === "string") {
2418
+ if (typeof clockTolerance == "string")
2929
2419
  tolerance = secs(clockTolerance);
2930
- } else if (clockTolerance !== void 0) {
2931
- if (typeof clockTolerance !== "number") {
2420
+ else if (clockTolerance !== void 0) {
2421
+ if (typeof clockTolerance != "number")
2932
2422
  throw new TypeError("Invalid clockTolerance option type");
2933
- }
2934
2423
  tolerance = clockTolerance;
2935
2424
  }
2936
2425
  validateInput("clockTolerance option", tolerance);
2937
- const { currentDate } = options;
2938
- const now2 = validateInput("currentDate option", epoch(currentDate || /* @__PURE__ */ new Date()));
2939
- const iat = validateNumericDate(payload, "iat", maxTokenAge !== void 0);
2940
- const nbf = validateNumericDate(payload, "nbf");
2941
- if (nbf !== void 0) {
2942
- if (nbf > now2 + tolerance) {
2943
- throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', payload, "nbf", checkFailed);
2944
- }
2945
- }
2946
- const exp = validateNumericDate(payload, "exp");
2947
- if (exp !== void 0) {
2948
- if (exp <= now2 - tolerance) {
2949
- throw new JWTExpired('"exp" claim timestamp check failed', payload, "exp", checkFailed);
2950
- }
2951
- }
2426
+ const { currentDate } = options, now2 = validateInput("currentDate option", epoch(currentDate === void 0 ? /* @__PURE__ */ new Date() : currentDate)), iat = validateNumericDate(claimsSet, "iat", maxTokenAge !== void 0), nbf = validateNumericDate(claimsSet, "nbf");
2427
+ if (nbf !== void 0 && nbf > now2 + tolerance)
2428
+ throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', claimsSet, "nbf", checkFailed);
2429
+ const exp = validateNumericDate(claimsSet, "exp");
2430
+ if (exp !== void 0 && exp <= now2 - tolerance)
2431
+ throw new JWTExpired('"exp" claim timestamp check failed', claimsSet, "exp", checkFailed);
2952
2432
  if (maxTokenAge !== void 0) {
2953
- const age = now2 - iat;
2954
- const max = typeof maxTokenAge === "number" ? maxTokenAge : secs(maxTokenAge);
2955
- if (age - tolerance > max) {
2956
- throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', payload, "iat", checkFailed);
2957
- }
2958
- if (age < 0 - tolerance) {
2959
- throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', payload, "iat", checkFailed);
2960
- }
2433
+ const age = now2 - iat, max = validateInput("maxTokenAge option", typeof maxTokenAge == "number" ? maxTokenAge : secs(maxTokenAge));
2434
+ if (age - tolerance > max)
2435
+ throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', claimsSet, "iat", checkFailed);
2436
+ if (age < -tolerance)
2437
+ throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', claimsSet, "iat", checkFailed);
2961
2438
  }
2962
- return payload;
2439
+ return claimsSet;
2440
+ }
2441
+ let producerClaimsSets;
2442
+ function producerClaimsSet(producer) {
2443
+ return producerClaimsSets.get(producer);
2444
+ }
2445
+ function jwtClaimsSetBytes(producer) {
2446
+ const claimsSet = producerClaimsSet(producer);
2447
+ for (const claim of ["iat", "nbf", "exp"]) {
2448
+ const value = claimsSet[claim];
2449
+ if (typeof value == "number" && !Number.isFinite(value))
2450
+ throw new TypeError(`"${claim}" claim must be a finite number`);
2451
+ }
2452
+ return encoder$2.encode(JSON.stringify(claimsSet));
2963
2453
  }
2964
2454
  class JWTClaimsBuilder {
2965
- #payload;
2966
- constructor(payload) {
2967
- if (!isObject(payload)) {
2455
+ constructor(claimsSet = {}) {
2456
+ if (!isObject(claimsSet))
2968
2457
  throw new TypeError("JWT Claims Set MUST be an object");
2969
- }
2970
- this.#payload = structuredClone(payload);
2971
- }
2972
- data() {
2973
- return encoder$2.encode(JSON.stringify(this.#payload));
2458
+ (producerClaimsSets ||= /* @__PURE__ */ new WeakMap()).set(this, structuredClone(claimsSet));
2974
2459
  }
2975
- get iss() {
2976
- return this.#payload.iss;
2460
+ setIssuer(value) {
2461
+ return validateStringClaim("iss", value), producerClaimsSet(this).iss = value, this;
2977
2462
  }
2978
- set iss(value) {
2979
- this.#payload.iss = value;
2463
+ setSubject(value) {
2464
+ return validateStringClaim("sub", value), producerClaimsSet(this).sub = value, this;
2980
2465
  }
2981
- get sub() {
2982
- return this.#payload.sub;
2466
+ setAudience(value) {
2467
+ return validateAudienceClaim(value), producerClaimsSet(this).aud = value, this;
2983
2468
  }
2984
- set sub(value) {
2985
- this.#payload.sub = value;
2469
+ setJti(value) {
2470
+ return validateStringClaim("jti", value), producerClaimsSet(this).jti = value, this;
2986
2471
  }
2987
- get aud() {
2988
- return this.#payload.aud;
2472
+ setNotBefore(value) {
2473
+ return producerClaimsSet(this).nbf = numericDate(value, "setNotBefore"), this;
2989
2474
  }
2990
- set aud(value) {
2991
- this.#payload.aud = value;
2475
+ setExpirationTime(value) {
2476
+ return producerClaimsSet(this).exp = numericDate(value, "setExpirationTime"), this;
2992
2477
  }
2993
- set jti(value) {
2994
- this.#payload.jti = value;
2995
- }
2996
- set nbf(value) {
2997
- this.#payload.nbf = numericDate(value, "setNotBefore");
2998
- }
2999
- set exp(value) {
3000
- this.#payload.exp = numericDate(value, "setExpirationTime");
3001
- }
3002
- set iat(value) {
3003
- if (value === void 0) {
3004
- this.#payload.iat = epoch(/* @__PURE__ */ new Date());
3005
- } else if (typeof value === "string") {
3006
- this.#payload.iat = validateInput("setIssuedAt", epoch(/* @__PURE__ */ new Date()) + secs(value));
3007
- } else {
3008
- this.#payload.iat = numericDate(value, "setIssuedAt");
3009
- }
2478
+ setIssuedAt(value) {
2479
+ const claimsSet = producerClaimsSet(this);
2480
+ return value === void 0 ? claimsSet.iat = epoch(/* @__PURE__ */ new Date()) : typeof value == "string" ? claimsSet.iat = validateInput("setIssuedAt", epoch(/* @__PURE__ */ new Date()) + secs(value)) : claimsSet.iat = numericDate(value, "setIssuedAt"), this;
3010
2481
  }
3011
2482
  }
3012
2483
  async function jwtVerify(jwt, key, options) {
3013
- const verified = await verifyCompact(jwt, prepareVerify(options), key);
3014
- if (!verified[2]) {
2484
+ const [verified, b64] = await verifyCompact(jwt, prepareVerify(options), key);
2485
+ if (!b64)
3015
2486
  throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
3016
- }
3017
- const payload = validateClaimsSet(verified[1], verified[0], options);
3018
- const result = { payload, protectedHeader: verified[1] };
3019
- if (typeof key === "function") {
3020
- return { ...result, key: verified[3] };
3021
- }
3022
- return result;
3023
- }
3024
- function unencodedPayload(protectedHeader) {
3025
- return protectedHeader?.b64 === false && Array.isArray(protectedHeader.crit) && protectedHeader.crit.includes("b64");
2487
+ const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);
2488
+ return { ...verified, payload };
3026
2489
  }
3027
- async function createSignature(input, key) {
3028
- const { protectedHeader, unprotectedHeader } = input;
3029
- if (!protectedHeader && !unprotectedHeader) {
3030
- throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");
2490
+ async function createSignature(input, key, rejectUnencoded) {
2491
+ let [payload, protectedHeader, unprotectedHeader, crit] = input, encodedProtectedHeader = "";
2492
+ if (protectedHeader !== void 0) {
2493
+ const normalized = serializeJoseHeader(JWSInvalid, protectedHeader);
2494
+ protectedHeader = normalized[0], encodedProtectedHeader = encode(normalized[1]);
3031
2495
  }
3032
- if (!isDisjoint(protectedHeader, unprotectedHeader)) {
2496
+ if (unprotectedHeader !== void 0 && (unprotectedHeader = serializeJoseHeader(JWSInvalid, unprotectedHeader)[0]), !protectedHeader && !unprotectedHeader)
2497
+ throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");
2498
+ if (!isDisjoint(protectedHeader, unprotectedHeader))
3033
2499
  throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
3034
- }
3035
2500
  const joseHeader = { ...protectedHeader, ...unprotectedHeader };
3036
2501
  validateCritDuplicates(JWSInvalid, protectedHeader);
3037
- const extensions = validateCrit(JWSInvalid, JWS_RECOGNIZED, input.crit, protectedHeader, joseHeader);
3038
- let b64 = true;
3039
- if (extensions.includes("b64")) {
3040
- b64 = protectedHeader.b64;
3041
- if (typeof b64 !== "boolean") {
3042
- throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
3043
- }
3044
- }
2502
+ const b64 = validateB64(protectedHeader, validateCrit(JWSInvalid, JWS_RECOGNIZED, crit, protectedHeader, joseHeader));
2503
+ b64 || rejectUnencoded?.();
3045
2504
  const { alg } = joseHeader;
3046
- if (typeof alg !== "string" || !alg) {
2505
+ if (typeof alg != "string" || !alg)
3047
2506
  throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
3048
- }
3049
2507
  const entry = jwsAlgorithm(alg);
3050
- let payloadS;
3051
- let payloadB;
2508
+ let encodedPayload = "", signingPayload = payload, signingInput;
3052
2509
  if (b64) {
3053
- const encoded = input.encoded ??= [];
3054
- encoded[0] ??= encode(input.payload);
3055
- encoded[1] ??= encode$1(encoded[0]);
3056
- payloadS = encoded[0];
3057
- payloadB = encoded[1];
3058
- } else {
3059
- payloadB = input.payload;
3060
- payloadS = "";
3061
- }
3062
- let protectedHeaderString;
3063
- let protectedHeaderBytes;
3064
- if (protectedHeader) {
3065
- protectedHeaderString = encode(JSON.stringify(protectedHeader));
3066
- protectedHeaderBytes = encode$1(protectedHeaderString);
3067
- } else {
3068
- protectedHeaderString = "";
3069
- protectedHeaderBytes = new Uint8Array();
2510
+ const encodedPayloadCache = input[4];
2511
+ encodedPayloadCache ? (encodedPayload = encodedPayloadCache[0] ??= encode(payload), signingPayload = encodedPayloadCache[1] ??= encode$1(encodedPayload)) : (encodedPayload = encode(payload), signingInput = encoder$2.encode(`${encodedProtectedHeader}.${encodedPayload}`));
3070
2512
  }
3071
- const data = concat(protectedHeaderBytes, encode$1("."), payloadB);
3072
- const k = await prepareKey(entry, key, "sign");
3073
- const signature = await sign(entry, k, data);
2513
+ signingInput ??= concat(encode$1(encodedProtectedHeader), encode$1("."), signingPayload);
2514
+ const signingKey = await rawKey(await prepareKey(entry, key, "sign"), entry.subtle, "sign");
2515
+ entry.minRsaBits && checkModulusLength(entry.alg, signingKey);
3074
2516
  const jws = {
3075
- signature: encode(signature),
3076
- payload: payloadS
2517
+ signature: encode(new Uint8Array(await crypto.subtle.sign(entry.signing, signingKey, signingInput))),
2518
+ payload: encodedPayload
3077
2519
  };
3078
- if (protectedHeader) {
3079
- jws.protected = protectedHeaderString;
3080
- }
3081
- if (unprotectedHeader) {
3082
- jws.header = unprotectedHeader;
3083
- }
3084
- return jws;
2520
+ return protectedHeader && (jws.protected = encodedProtectedHeader), unprotectedHeader && (jws.header = unprotectedHeader), [jws, b64];
3085
2521
  }
3086
- class FlattenedSign {
3087
- #payload;
3088
- #protectedHeader;
3089
- #unprotectedHeader;
3090
- constructor(payload) {
3091
- if (!(payload instanceof Uint8Array)) {
3092
- throw new TypeError("payload must be an instance of Uint8Array");
3093
- }
3094
- this.#payload = payload;
3095
- }
3096
- setProtectedHeader(protectedHeader) {
3097
- assertNotSet(this.#protectedHeader, "setProtectedHeader");
3098
- this.#protectedHeader = protectedHeader;
3099
- return this;
3100
- }
3101
- setUnprotectedHeader(unprotectedHeader) {
3102
- assertNotSet(this.#unprotectedHeader, "setUnprotectedHeader");
3103
- this.#unprotectedHeader = unprotectedHeader;
3104
- return this;
3105
- }
3106
- async sign(key, options) {
3107
- return createSignature({
3108
- payload: this.#payload,
3109
- protectedHeader: this.#protectedHeader,
3110
- unprotectedHeader: this.#unprotectedHeader,
3111
- crit: options?.crit
3112
- }, key);
3113
- }
2522
+ async function createCompactSignature(payload, protectedHeader, crit, key, rejectUnencoded) {
2523
+ const [jws] = await createSignature([payload, protectedHeader, void 0, crit], key, rejectUnencoded);
2524
+ return `${jws.protected}.${jws.payload}.${jws.signature}`;
3114
2525
  }
3115
- class CompactSign {
3116
- #flattened;
2526
+ const SignJWT_base = JWTClaimsBuilder;
2527
+ class SignJWT extends SignJWT_base {
3117
2528
  #protectedHeader;
3118
- constructor(payload) {
3119
- this.#flattened = new FlattenedSign(payload);
3120
- }
3121
2529
  setProtectedHeader(protectedHeader) {
3122
- this.#flattened.setProtectedHeader(protectedHeader);
3123
- this.#protectedHeader = protectedHeader;
3124
- return this;
2530
+ return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
3125
2531
  }
3126
2532
  async sign(key, options) {
3127
- if (unencodedPayload(this.#protectedHeader)) {
3128
- throw new TypeError("use the flattened module for creating JWS with b64: false");
3129
- }
3130
- const jws = await this.#flattened.sign(key, options);
3131
- return `${jws.protected}.${jws.payload}.${jws.signature}`;
3132
- }
3133
- }
3134
- class SignJWT {
3135
- #protectedHeader;
3136
- #jwt;
3137
- constructor(payload = {}) {
3138
- this.#jwt = new JWTClaimsBuilder(payload);
3139
- }
3140
- setIssuer(issuer) {
3141
- this.#jwt.iss = issuer;
3142
- return this;
3143
- }
3144
- setSubject(subject) {
3145
- this.#jwt.sub = subject;
3146
- return this;
3147
- }
3148
- setAudience(audience) {
3149
- this.#jwt.aud = audience;
3150
- return this;
3151
- }
3152
- setJti(jwtId) {
3153
- this.#jwt.jti = jwtId;
3154
- return this;
3155
- }
3156
- setNotBefore(input) {
3157
- this.#jwt.nbf = input;
3158
- return this;
3159
- }
3160
- setExpirationTime(input) {
3161
- this.#jwt.exp = input;
3162
- return this;
3163
- }
3164
- setIssuedAt(input) {
3165
- this.#jwt.iat = input;
3166
- return this;
3167
- }
3168
- setProtectedHeader(protectedHeader) {
3169
- this.#protectedHeader = protectedHeader;
3170
- return this;
3171
- }
3172
- async sign(key, options) {
3173
- const sig2 = new CompactSign(this.#jwt.data());
3174
- sig2.setProtectedHeader(this.#protectedHeader);
3175
- if (unencodedPayload(this.#protectedHeader)) {
2533
+ return createCompactSignature(jwtClaimsSetBytes(this), this.#protectedHeader, options?.crit, key, () => {
3176
2534
  throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
3177
- }
3178
- return sig2.sign(key, options);
2535
+ });
3179
2536
  }
3180
2537
  }
3181
2538
  function unsupportedAlg(source = 'JWK "alg" (Algorithm) Parameter') {
3182
2539
  throw new JOSENotSupported(`Invalid or unsupported ${source} value`);
3183
2540
  }
3184
2541
  function keyAlgorithm(alg, source) {
3185
- return (typeof alg === "string" ? JWS[alg] ?? JWE[alg] : void 0) ?? unsupportedAlg(source);
2542
+ return (typeof alg == "string" ? JWS[alg] ?? JWE[alg] : void 0) ?? unsupportedAlg(source);
3186
2543
  }
3187
- function signatureAlgorithm(alg) {
3188
- const entry = typeof alg === "string" ? JWS[alg] : void 0;
3189
- if (!entry || entry.secret) {
3190
- throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
3191
- }
3192
- return entry;
2544
+ function isUsableJWK(jwk, entry, alg, kid) {
2545
+ const { kty, key_ops: keyOps, ext, kid: jwkKid, alg: jwkAlg, use, crv } = jwk;
2546
+ return (ext === void 0 || typeof ext == "boolean") && (keyOps === void 0 || Array.isArray(keyOps) && keyOps.every((operation, index) => typeof operation == "string" && keyOps.indexOf(operation) === index) && keyOps.includes("verify")) && entry.kty.includes(kty) && (kid === void 0 || typeof kid == "string" && kid === jwkKid) && (jwkAlg === void 0 ? kty !== "AKP" : alg === jwkAlg) && (use === void 0 || use === "sig") && (!entry.crv || crv === entry.crv);
3193
2547
  }
3194
- function isJWKSLike(jwks) {
3195
- if (!jwks || typeof jwks !== "object") {
3196
- return false;
2548
+ async function importWithAlgCache(cache2, jwk, entry) {
2549
+ const cached = cache2.get(jwk) || cache2.set(jwk, {}).get(jwk), { alg } = entry;
2550
+ if (cached[alg] === void 0) {
2551
+ const pending = jwkToKey(entry, jwk, true).then((key) => {
2552
+ if (key.type !== "public")
2553
+ throw new JWKSInvalid("JSON Web Key Set members must be public keys");
2554
+ return cached[alg] = key, key;
2555
+ }).catch((error) => {
2556
+ throw cached[alg] === pending && delete cached[alg], error;
2557
+ });
2558
+ cached[alg] = pending;
3197
2559
  }
3198
- const { keys } = jwks;
3199
- return Array.isArray(keys) && keys.every(isObject);
2560
+ return cached[alg];
3200
2561
  }
3201
- class LocalJWKSetImpl {
3202
- #jwks;
3203
- #cached = /* @__PURE__ */ new WeakMap();
3204
- constructor(jwks) {
3205
- if (!isJWKSLike(jwks)) {
3206
- throw new JWKSInvalid("JSON Web Key Set malformed");
3207
- }
3208
- this.#jwks = structuredClone(jwks);
3209
- }
3210
- jwks() {
3211
- return this.#jwks;
3212
- }
3213
- async getKey(protectedHeader, token) {
3214
- const { alg, kid } = { ...protectedHeader, ...token?.header };
3215
- const entry = signatureAlgorithm(alg);
3216
- const candidates = this.#jwks.keys.filter((jwk2) => entry.kty.includes(jwk2.kty) && (typeof kid !== "string" || kid === jwk2.kid) && (!(typeof jwk2.alg === "string" || jwk2.kty === "AKP") || alg === jwk2.alg) && (typeof jwk2.use !== "string" || jwk2.use === "sig") && (!Array.isArray(jwk2.key_ops) || jwk2.key_ops.includes("verify")) && (!entry.crv || jwk2.crv === entry.crv));
3217
- const { 0: jwk, length } = candidates;
3218
- if (length === 0) {
2562
+ function createLocalJWKSet(jwks) {
2563
+ let snapshot;
2564
+ try {
2565
+ snapshot = structuredClone(jwks);
2566
+ } catch (cause) {
2567
+ throw new JWKSInvalid("JSON Web Key Set malformed", { cause });
2568
+ }
2569
+ if (!isJwkSet(snapshot))
2570
+ throw new JWKSInvalid("JSON Web Key Set malformed");
2571
+ const metadata = snapshot.keys.map((jwk) => {
2572
+ const normalized = snapshotJwk(jwk);
2573
+ return Array.isArray(normalized.key_ops) && (normalized.key_ops = [...normalized.key_ops]), normalized;
2574
+ }), cached = /* @__PURE__ */ new WeakMap();
2575
+ return Object.defineProperty(async (protectedHeader, token) => {
2576
+ const { alg, kid } = { ...protectedHeader, ...token?.header }, entry = typeof alg == "string" ? JWS[alg] : void 0;
2577
+ if (!entry || entry.secret)
2578
+ throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set');
2579
+ const candidates = snapshot.keys.filter((_, index) => isUsableJWK(metadata[index], entry, alg, kid)), { 0: jwk, length } = candidates;
2580
+ if (!length)
3219
2581
  throw new JWKSNoMatchingKey();
3220
- }
3221
2582
  if (length !== 1) {
3222
2583
  const error = new JWKSMultipleMatchingKeys();
3223
- const _cached = this.#cached;
3224
- error[Symbol.asyncIterator] = async function* () {
3225
- for (const jwk2 of candidates) {
2584
+ throw error[Symbol.asyncIterator] = async function* () {
2585
+ for (const jwk2 of candidates)
3226
2586
  try {
3227
- yield await importWithAlgCache(_cached, jwk2, entry);
2587
+ yield await importWithAlgCache(cached, jwk2, entry);
3228
2588
  } catch {
3229
2589
  }
3230
- }
3231
- };
3232
- throw error;
2590
+ }, error;
3233
2591
  }
3234
- return importWithAlgCache(this.#cached, jwk, entry);
3235
- }
3236
- }
3237
- async function importWithAlgCache(cache2, jwk, entry) {
3238
- const cached2 = cache2.get(jwk) || cache2.set(jwk, { __proto__: null }).get(jwk);
3239
- if (cached2[entry.alg] === void 0) {
3240
- const key = await jwkToKey(entry, { ...jwk, alg: entry.alg, ext: true });
3241
- if (key.type !== "public") {
3242
- throw new JWKSInvalid("JSON Web Key Set members must be public keys");
3243
- }
3244
- cached2[entry.alg] = key;
3245
- }
3246
- return cached2[entry.alg];
3247
- }
3248
- function createLocalJWKSet(jwks) {
3249
- const set = new LocalJWKSetImpl(jwks);
3250
- const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token);
3251
- Object.defineProperty(localJWKSet, "jwks", {
3252
- value: () => structuredClone(set.jwks())
2592
+ return importWithAlgCache(cached, jwk, entry);
2593
+ }, "jwks", {
2594
+ value: () => structuredClone(snapshot)
3253
2595
  });
3254
- return localJWKSet;
3255
2596
  }
3256
2597
  async function importJWK(jwk, alg, options) {
3257
- if (!isObject(jwk)) {
2598
+ if (!isObject(jwk))
3258
2599
  throw new TypeError("JWK must be an object");
3259
- }
3260
- alg ??= jwk.alg;
3261
- const ext = jwk.ext;
3262
- if (jwk.kty !== "oct" && !alg) {
2600
+ const normalized = normalizeJwk(jwk), extractable = validateExtractableOption(options?.extractable), { alg: jwkAlg } = normalized;
2601
+ if (alg ??= jwkAlg, normalized.kty !== "oct" && !alg)
3263
2602
  throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
3264
- }
3265
- switch (jwk.kty) {
2603
+ switch (normalized.kty) {
3266
2604
  case "oct":
3267
- if (typeof jwk.k !== "string" || !jwk.k) {
2605
+ if (typeof normalized.k != "string")
3268
2606
  throw new TypeError('missing "k" (Key Value) Parameter value');
3269
- }
3270
- return decode(jwk.k);
3271
- case "RSA":
3272
- return jwkToKey(keyAlgorithm(alg), { ...jwk, alg, ext });
2607
+ return decode(normalized.k);
3273
2608
  case "AKP": {
3274
- if (typeof jwk.alg !== "string" || !jwk.alg) {
2609
+ if (typeof jwkAlg != "string" || !jwkAlg)
3275
2610
  throw new TypeError('missing "alg" (Algorithm) Parameter value');
3276
- }
3277
- if (alg !== void 0 && alg !== jwk.alg) {
2611
+ if (alg !== jwkAlg)
3278
2612
  throw new TypeError("JWK alg and alg option value mismatch");
3279
- }
3280
- return jwkToKey(keyAlgorithm(jwk.alg), { ...jwk, ext });
2613
+ return jwkToKey(keyAlgorithm(alg), normalized, extractable);
3281
2614
  }
2615
+ case "RSA":
3282
2616
  case "EC":
3283
2617
  case "OKP":
3284
- return jwkToKey(keyAlgorithm(alg), { ...jwk, alg, ext });
2618
+ return jwkToKey(keyAlgorithm(alg), normalized, extractable);
3285
2619
  default:
3286
2620
  throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
3287
2621
  }
@@ -5498,8 +4832,8 @@ async function assertActive$1(env, claims) {
5498
4832
  `https://token-status.invalid/${encodeURIComponent(claims.iss)}/${encodeURIComponent(claims.jti)}?exp=${claims.exp}`
5499
4833
  );
5500
4834
  try {
5501
- const cached2 = await caches.default.match(key);
5502
- if (cached2) return;
4835
+ const cached = await caches.default.match(key);
4836
+ if (cached) return;
5503
4837
  } catch {
5504
4838
  }
5505
4839
  const result = await namedStub(env.TOKEN_CATALOG, "catalog").check({
@@ -5603,8 +4937,8 @@ function effectiveLifecycle(catalogue, coordinatorLifecycle) {
5603
4937
  async function directoryReference(env, name) {
5604
4938
  const key = new Request(`https://directory.invalid/cache/${name}`);
5605
4939
  try {
5606
- const cached2 = await caches.default.match(key);
5607
- if (cached2) return await cached2.json();
4940
+ const cached = await caches.default.match(key);
4941
+ if (cached) return await cached.json();
5608
4942
  } catch {
5609
4943
  }
5610
4944
  const reference2 = unwrapRpc(await system(env).getCache(name));
@@ -5680,7 +5014,7 @@ function event(id, actor, action, resource, outcome) {
5680
5014
  metadata: {}
5681
5015
  };
5682
5016
  }
5683
- const cacheRoutes = new Hono();
5017
+ const cacheRoutes = new Hono2();
5684
5018
  cacheRoutes.post("/api/caches", async (c) => {
5685
5019
  const operationId = idempotency(c.req.raw);
5686
5020
  const admin = await authenticateGlobal(c.req.raw, c.env, "admin");
@@ -5885,7 +5219,7 @@ function publicationFor(env, cache2, storeHash) {
5885
5219
  new DurableQuotaLedgerAdapter(quota)
5886
5220
  );
5887
5221
  }
5888
- const pathRoutes = new Hono();
5222
+ const pathRoutes = new Hono2();
5889
5223
  pathRoutes.post("/api/caches/:name/missing", async (c) => {
5890
5224
  const name = c.req.param("name");
5891
5225
  assertCacheName(name);
@@ -5950,7 +5284,7 @@ function auditShardNames() {
5950
5284
  function auditStub(env, eventId) {
5951
5285
  return namedStub(env.AUDIT_LOG, auditShardName(eventId));
5952
5286
  }
5953
- const tokenRoutes = new Hono();
5287
+ const tokenRoutes = new Hono2();
5954
5288
  tokenRoutes.post("/api/bootstrap", async (c) => {
5955
5289
  const operationId = idempotency(c.req.raw);
5956
5290
  const input = parseJsonSchema(
@@ -6041,7 +5375,7 @@ tokenRoutes.get("/api/audit", async (c) => {
6041
5375
  next_cursor: hasMore && last ? encodeCursor({ timestamp: last.timestamp, id: last.id }) : null
6042
5376
  });
6043
5377
  });
6044
- const controlRoutes = new Hono();
5378
+ const controlRoutes = new Hono2();
6045
5379
  controlRoutes.get("/health", (c) => c.json({ status: "ok" }));
6046
5380
  controlRoutes.get(
6047
5381
  "/api/public-key",
@@ -6140,7 +5474,7 @@ async function serveNarObject(c, cache2, storeHash, record) {
6140
5474
  });
6141
5475
  return new Response(stream, { status, headers });
6142
5476
  }
6143
- const nixRoutes = new Hono();
5477
+ const nixRoutes = new Hono2();
6144
5478
  const NARINFO = new RegExp(`^(${STORE_HASH_PATTERN})\\.narinfo$`);
6145
5479
  const NAR_OBJECT = new RegExp(`^nar/(${STORE_HASH_PATTERN})\\.nar\\.zst$`);
6146
5480
  async function nixHandler(c) {
@@ -6195,7 +5529,7 @@ async function uploadAccess(c) {
6195
5529
  function stateResponse(value) {
6196
5530
  return Response.json(value, { headers: { "cache-control": "no-store" } });
6197
5531
  }
6198
- const uploadRoutes = new Hono();
5532
+ const uploadRoutes = new Hono2();
6199
5533
  uploadRoutes.post("/api/uploads", async (c) => {
6200
5534
  const key = idempotency(c.req.raw);
6201
5535
  const input = parseJsonSchema(
@@ -6277,7 +5611,7 @@ uploadRoutes.delete("/api/uploads/:id", async (c) => {
6277
5611
  return stateResponse(unwrapRpc(await job.abort()));
6278
5612
  });
6279
5613
  function createApp() {
6280
- const app2 = new Hono();
5614
+ const app2 = new Hono2();
6281
5615
  app2.use("*", async (c, next) => {
6282
5616
  const id = crypto.randomUUID();
6283
5617
  c.set("requestId", id);