hono 4.6.19 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/adapter/lambda-edge/handler.js +6 -2
  2. package/dist/cjs/adapter/lambda-edge/handler.js +6 -2
  3. package/dist/cjs/helper/accepts/accepts.js +4 -26
  4. package/dist/cjs/helper/factory/index.js +6 -2
  5. package/dist/cjs/helper/proxy/index.js +75 -0
  6. package/dist/cjs/helper/streaming/sse.js +8 -5
  7. package/dist/cjs/helper/streaming/stream.js +8 -5
  8. package/dist/cjs/helper/streaming/utils.js +36 -0
  9. package/dist/cjs/middleware/etag/digest.js +2 -7
  10. package/dist/cjs/middleware/etag/index.js +7 -2
  11. package/dist/cjs/middleware/jwk/index.js +28 -0
  12. package/dist/cjs/middleware/jwk/jwk.js +124 -0
  13. package/dist/cjs/middleware/language/index.js +36 -0
  14. package/dist/cjs/middleware/language/language.js +210 -0
  15. package/dist/cjs/middleware/logger/index.js +2 -3
  16. package/dist/cjs/request.js +1 -1
  17. package/dist/cjs/router/linear-router/router.js +3 -1
  18. package/dist/cjs/router/trie-router/node.js +24 -11
  19. package/dist/cjs/utils/accept.js +86 -0
  20. package/dist/cjs/utils/jwt/index.js +1 -1
  21. package/dist/cjs/utils/jwt/jwt.js +56 -3
  22. package/dist/cjs/utils/jwt/types.js +8 -0
  23. package/dist/cjs/utils/url.js +6 -5
  24. package/dist/helper/accepts/accepts.js +2 -23
  25. package/dist/helper/factory/index.js +6 -2
  26. package/dist/helper/proxy/index.js +52 -0
  27. package/dist/helper/streaming/sse.js +8 -5
  28. package/dist/helper/streaming/stream.js +8 -5
  29. package/dist/helper/streaming/utils.js +13 -0
  30. package/dist/middleware/etag/digest.js +2 -7
  31. package/dist/middleware/etag/index.js +7 -2
  32. package/dist/middleware/jwk/index.js +5 -0
  33. package/dist/middleware/jwk/jwk.js +101 -0
  34. package/dist/middleware/language/index.js +15 -0
  35. package/dist/middleware/language/language.js +178 -0
  36. package/dist/middleware/logger/index.js +2 -3
  37. package/dist/request.js +1 -1
  38. package/dist/router/linear-router/router.js +3 -1
  39. package/dist/router/trie-router/node.js +24 -11
  40. package/dist/types/client/types.d.ts +1 -2
  41. package/dist/types/context.d.ts +2 -2
  42. package/dist/types/helper/accepts/accepts.d.ts +0 -1
  43. package/dist/types/helper/adapter/index.d.ts +1 -1
  44. package/dist/types/helper/factory/index.d.ts +4 -1
  45. package/dist/types/helper/proxy/index.d.ts +54 -0
  46. package/dist/types/helper/streaming/utils.d.ts +1 -0
  47. package/dist/types/middleware/etag/digest.d.ts +1 -1
  48. package/dist/types/middleware/etag/index.d.ts +4 -0
  49. package/dist/types/middleware/jwk/index.d.ts +1 -0
  50. package/dist/types/middleware/jwk/jwk.d.ts +40 -0
  51. package/dist/types/middleware/language/index.d.ts +7 -0
  52. package/dist/types/middleware/language/language.d.ts +102 -0
  53. package/dist/types/utils/accept.d.ts +11 -0
  54. package/dist/types/utils/jwt/index.d.ts +4 -0
  55. package/dist/types/utils/jwt/jws.d.ts +4 -1
  56. package/dist/types/utils/jwt/jwt.d.ts +7 -1
  57. package/dist/types/utils/jwt/types.d.ts +4 -0
  58. package/dist/types/utils/url.d.ts +1 -1
  59. package/dist/utils/accept.js +63 -0
  60. package/dist/utils/jwt/index.js +2 -2
  61. package/dist/utils/jwt/jwt.js +54 -2
  62. package/dist/utils/jwt/types.js +7 -0
  63. package/dist/utils/url.js +6 -5
  64. package/package.json +26 -5
  65. package/perf-measures/bundle-check/generated/.gitkeep +0 -0
  66. package/perf-measures/type-check/generated/.gitkeep +0 -0
@@ -1 +1 @@
1
- export declare const generateDigest: (stream: ReadableStream<Uint8Array> | null) => Promise<string | null>;
1
+ export declare const generateDigest: (stream: ReadableStream<Uint8Array> | null, generator: (body: Uint8Array) => ArrayBuffer | Promise<ArrayBuffer>) => Promise<string | null>;
@@ -6,6 +6,7 @@ import type { MiddlewareHandler } from '../../types';
6
6
  type ETagOptions = {
7
7
  retainedHeaders?: string[];
8
8
  weak?: boolean;
9
+ generateDigest?: (body: Uint8Array) => ArrayBuffer | Promise<ArrayBuffer>;
9
10
  };
10
11
  /**
11
12
  * Default headers to pass through on 304 responses. From the spec:
@@ -22,6 +23,9 @@ export declare const RETAINED_304_HEADERS: string[];
22
23
  * @param {ETagOptions} [options] - The options for the ETag middleware.
23
24
  * @param {boolean} [options.weak=false] - Define using or not using a weak validation. If true is set, then `W/` is added to the prefix of the value.
24
25
  * @param {string[]} [options.retainedHeaders=RETAINED_304_HEADERS] - The headers that you want to retain in the 304 Response.
26
+ * @param {function(Uint8Array): ArrayBuffer | Promise<ArrayBuffer>} [options.generateDigest] -
27
+ * A custom digest generation function. By default, it uses 'SHA-1'
28
+ * This function is called with the response body as a `Uint8Array` and should return a hash as an `ArrayBuffer` or a Promise of one.
25
29
  * @returns {MiddlewareHandler} The middleware handler function.
26
30
  *
27
31
  * @example
@@ -0,0 +1 @@
1
+ export { jwk } from './jwk';
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @module
3
+ * JWK Auth Middleware for Hono.
4
+ */
5
+ import type { MiddlewareHandler } from '../../types';
6
+ import type { CookiePrefixOptions } from '../../utils/cookie';
7
+ import '../../context';
8
+ import type { HonoJsonWebKey } from '../../utils/jwt/jws';
9
+ /**
10
+ * JWK Auth Middleware for Hono.
11
+ *
12
+ * @see {@link https://hono.dev/docs/middleware/builtin/jwk}
13
+ *
14
+ * @param {object} options - The options for the JWK middleware.
15
+ * @param {HonoJsonWebKey[] | (() => Promise<HonoJsonWebKey[]>)} [options.keys] - The values of your public keys, or a function that returns them.
16
+ * @param {string} [options.jwks_uri] - If this value is set, attempt to fetch JWKs from this URI, expecting a JSON response with `keys` which are added to the provided options.keys
17
+ * @param {string} [options.cookie] - If this value is set, then the value is retrieved from the cookie header using that value as a key, which is then validated as a token.
18
+ * @param {RequestInit} [init] - Optional initialization options for the `fetch` request when retrieving JWKS from a URI.
19
+ * @returns {MiddlewareHandler} The middleware handler function.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * const app = new Hono()
24
+ *
25
+ * app.use("/auth/*", jwk({ jwks_uri: "https://example-backend.hono.dev/.well-known/jwks.json" }))
26
+ *
27
+ * app.get('/auth/page', (c) => {
28
+ * return c.text('You are authorized')
29
+ * })
30
+ * ```
31
+ */
32
+ export declare const jwk: (options: {
33
+ keys?: HonoJsonWebKey[] | (() => Promise<HonoJsonWebKey[]>);
34
+ jwks_uri?: string;
35
+ cookie?: string | {
36
+ key: string;
37
+ secret?: string | BufferSource;
38
+ prefixOptions?: CookiePrefixOptions;
39
+ };
40
+ }, init?: RequestInit) => MiddlewareHandler;
@@ -0,0 +1,7 @@
1
+ import type { LanguageVariables, DetectorOptions, DetectorType, CacheType } from './language';
2
+ export type { LanguageVariables, DetectorOptions, DetectorType, CacheType };
3
+ export { languageDetector, detectFromCookie, detectFromHeader, detectFromPath, detectFromQuery, } from './language';
4
+ declare module '../..' {
5
+ interface ContextVariableMap extends LanguageVariables {
6
+ }
7
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * @module
3
+ * Language module for Hono.
4
+ */
5
+ import type { Context } from '../../context';
6
+ import type { MiddlewareHandler } from '../../types';
7
+ export type DetectorType = "path" | "querystring" | "cookie" | "header";
8
+ export type CacheType = "cookie";
9
+ export interface DetectorOptions {
10
+ /** Order of language detection strategies */
11
+ order: DetectorType[];
12
+ /** Query parameter name for language */
13
+ lookupQueryString: string;
14
+ /** Cookie name for language */
15
+ lookupCookie: string;
16
+ /** Index in URL path where language code appears */
17
+ lookupFromPathIndex: number;
18
+ /** Header key for language detection */
19
+ lookupFromHeaderKey: string;
20
+ /** Caching strategies */
21
+ caches: CacheType[] | false;
22
+ /** Cookie configuration options */
23
+ cookieOptions?: {
24
+ domain?: string;
25
+ path?: string;
26
+ sameSite?: "Strict" | "Lax" | "None";
27
+ secure?: boolean;
28
+ maxAge?: number;
29
+ httpOnly?: boolean;
30
+ };
31
+ /** Whether to ignore case in language codes */
32
+ ignoreCase: boolean;
33
+ /** Default language if none detected */
34
+ fallbackLanguage: string;
35
+ /** List of supported language codes */
36
+ supportedLanguages: string[];
37
+ /** Optional function to transform detected language codes */
38
+ convertDetectedLanguage?: (lang: string) => string;
39
+ /** Enable debug logging */
40
+ debug?: boolean;
41
+ }
42
+ export interface LanguageVariables {
43
+ language: string;
44
+ }
45
+ export declare const DEFAULT_OPTIONS: DetectorOptions;
46
+ /**
47
+ * Parse Accept-Language header values with quality scores
48
+ * @param header Accept-Language header string
49
+ * @returns Array of parsed languages with quality scores
50
+ */
51
+ export declare function parseAcceptLanguage(header: string): Array<{
52
+ lang: string;
53
+ q: number;
54
+ }>;
55
+ /**
56
+ * Validate and normalize language codes
57
+ * @param lang Language code to normalize
58
+ * @param options Detector options
59
+ * @returns Normalized language code or undefined
60
+ */
61
+ export declare const normalizeLanguage: (lang: string | null | undefined, options: DetectorOptions) => string | undefined;
62
+ /**
63
+ * Detects language from query parameter
64
+ */
65
+ export declare const detectFromQuery: (c: Context, options: DetectorOptions) => string | undefined;
66
+ /**
67
+ * Detects language from cookie
68
+ */
69
+ export declare const detectFromCookie: (c: Context, options: DetectorOptions) => string | undefined;
70
+ /**
71
+ * Detects language from Accept-Language header
72
+ */
73
+ export declare function detectFromHeader(c: Context, options: DetectorOptions): string | undefined;
74
+ /**
75
+ * Detects language from URL path
76
+ */
77
+ export declare function detectFromPath(c: Context, options: DetectorOptions): string | undefined;
78
+ /**
79
+ * Collection of all language detection strategies
80
+ */
81
+ export declare const detectors: {
82
+ readonly querystring: (c: Context, options: DetectorOptions) => string | undefined;
83
+ readonly cookie: (c: Context, options: DetectorOptions) => string | undefined;
84
+ readonly header: typeof detectFromHeader;
85
+ readonly path: typeof detectFromPath;
86
+ };
87
+ /** Type for detector functions */
88
+ export type DetectorFunction = (c: Context, options: DetectorOptions) => string | undefined;
89
+ /** Type-safe detector map */
90
+ export type Detectors = Record<keyof typeof detectors, DetectorFunction>;
91
+ /**
92
+ * Validate detector options
93
+ * @param options Detector options to validate
94
+ * @throws Error if options are invalid
95
+ */
96
+ export declare function validateOptions(options: DetectorOptions): void;
97
+ /**
98
+ * Language detector middleware factory
99
+ * @param userOptions Configuration options for the language detector
100
+ * @returns Hono middleware function
101
+ */
102
+ export declare const languageDetector: (userOptions: Partial<DetectorOptions>) => MiddlewareHandler;
@@ -0,0 +1,11 @@
1
+ export interface Accept {
2
+ type: string;
3
+ params: Record<string, string>;
4
+ q: number;
5
+ }
6
+ /**
7
+ * Parse an Accept header into an array of objects with type, parameters, and quality score.
8
+ * @param acceptHeader The Accept header string
9
+ * @returns An array of parsed Accept values
10
+ */
11
+ export declare const parseAccept: (acceptHeader: string) => Accept[];
@@ -9,4 +9,8 @@ export declare const Jwt: {
9
9
  header: import("./jwt").TokenHeader;
10
10
  payload: import("./types").JWTPayload;
11
11
  };
12
+ verifyFromJwks: (token: string, options: {
13
+ keys?: import("./jws").HonoJsonWebKey[] | (() => Promise<import("./jws").HonoJsonWebKey[]>);
14
+ jwks_uri?: string;
15
+ }, init?: RequestInit) => Promise<import("./types").JWTPayload>;
12
16
  };
@@ -4,6 +4,9 @@
4
4
  * https://datatracker.ietf.org/doc/html/rfc7515
5
5
  */
6
6
  import type { SignatureAlgorithm } from './jwa';
7
- export type SignatureKey = string | JsonWebKey | CryptoKey;
7
+ export interface HonoJsonWebKey extends JsonWebKey {
8
+ kid?: string;
9
+ }
10
+ export type SignatureKey = string | HonoJsonWebKey | CryptoKey;
8
11
  export declare function signing(privateKey: SignatureKey, alg: SignatureAlgorithm, data: BufferSource): Promise<ArrayBuffer>;
9
12
  export declare function verifying(publicKey: SignatureKey, alg: SignatureAlgorithm, signature: BufferSource, data: BufferSource): Promise<boolean>;
@@ -4,16 +4,22 @@
4
4
  * https://datatracker.ietf.org/doc/html/rfc7519
5
5
  */
6
6
  import type { SignatureAlgorithm } from './jwa';
7
- import type { SignatureKey } from './jws';
7
+ import type { HonoJsonWebKey, SignatureKey } from './jws';
8
8
  import type { JWTPayload } from './types';
9
9
  export interface TokenHeader {
10
10
  alg: SignatureAlgorithm;
11
11
  typ?: "JWT";
12
+ kid?: string;
12
13
  }
13
14
  export declare function isTokenHeader(obj: unknown): obj is TokenHeader;
14
15
  export declare const sign: (payload: JWTPayload, privateKey: SignatureKey, alg?: SignatureAlgorithm) => Promise<string>;
15
16
  export declare const verify: (token: string, publicKey: SignatureKey, alg?: SignatureAlgorithm) => Promise<JWTPayload>;
17
+ export declare const verifyFromJwks: (token: string, options: {
18
+ keys?: HonoJsonWebKey[] | (() => Promise<HonoJsonWebKey[]>);
19
+ jwks_uri?: string;
20
+ }, init?: RequestInit) => Promise<JWTPayload>;
16
21
  export declare const decode: (token: string) => {
17
22
  header: TokenHeader;
18
23
  payload: JWTPayload;
19
24
  };
25
+ export declare const decodeHeader: (token: string) => TokenHeader;
@@ -20,6 +20,9 @@ export declare class JwtTokenIssuedAt extends Error {
20
20
  export declare class JwtHeaderInvalid extends Error {
21
21
  constructor(header: object);
22
22
  }
23
+ export declare class JwtHeaderRequiresKid extends Error {
24
+ constructor(header: object);
25
+ }
23
26
  export declare class JwtTokenSignatureMismatched extends Error {
24
27
  constructor(token: string);
25
28
  }
@@ -51,3 +54,4 @@ export type JWTPayload = {
51
54
  */
52
55
  iat?: number;
53
56
  };
57
+ export type { HonoJsonWebKey } from './jws';
@@ -9,7 +9,7 @@ export type Pattern = readonly [
9
9
  ] | "*";
10
10
  export declare const splitPath: (path: string) => string[];
11
11
  export declare const splitRoutingPath: (routePath: string) => string[];
12
- export declare const getPattern: (label: string) => Pattern | null;
12
+ export declare const getPattern: (label: string, next?: string) => Pattern | null;
13
13
  type Decoder = (str: string) => string;
14
14
  export declare const tryDecode: (str: string, decoder: Decoder) => string;
15
15
  export declare const getPath: (request: Request) => string;
@@ -0,0 +1,63 @@
1
+ // src/utils/accept.ts
2
+ var parseAccept = (acceptHeader) => {
3
+ if (!acceptHeader) {
4
+ return [];
5
+ }
6
+ const acceptValues = acceptHeader.split(",").map((value, index) => ({ value, index }));
7
+ return acceptValues.map(parseAcceptValue).filter((item) => Boolean(item)).sort(sortByQualityAndIndex).map(({ type, params, q }) => ({ type, params, q }));
8
+ };
9
+ var parseAcceptValueRegex = /;(?=(?:(?:[^"]*"){2})*[^"]*$)/;
10
+ var parseAcceptValue = ({ value, index }) => {
11
+ const parts = value.trim().split(parseAcceptValueRegex).map((s) => s.trim());
12
+ const type = parts[0];
13
+ if (!type) {
14
+ return null;
15
+ }
16
+ const params = parseParams(parts.slice(1));
17
+ const q = parseQuality(params.q);
18
+ return { type, params, q, index };
19
+ };
20
+ var parseParams = (paramParts) => {
21
+ return paramParts.reduce((acc, param) => {
22
+ const [key, val] = param.split("=").map((s) => s.trim());
23
+ if (key && val) {
24
+ acc[key] = val;
25
+ }
26
+ return acc;
27
+ }, {});
28
+ };
29
+ var parseQuality = (qVal) => {
30
+ if (qVal === void 0) {
31
+ return 1;
32
+ }
33
+ if (qVal === "") {
34
+ return 1;
35
+ }
36
+ if (qVal === "NaN") {
37
+ return 0;
38
+ }
39
+ const num = Number(qVal);
40
+ if (num === Infinity) {
41
+ return 1;
42
+ }
43
+ if (num === -Infinity) {
44
+ return 0;
45
+ }
46
+ if (Number.isNaN(num)) {
47
+ return 1;
48
+ }
49
+ if (num < 0 || num > 1) {
50
+ return 1;
51
+ }
52
+ return num;
53
+ };
54
+ var sortByQualityAndIndex = (a, b) => {
55
+ const qDiff = b.q - a.q;
56
+ if (qDiff !== 0) {
57
+ return qDiff;
58
+ }
59
+ return a.index - b.index;
60
+ };
61
+ export {
62
+ parseAccept
63
+ };
@@ -1,6 +1,6 @@
1
1
  // src/utils/jwt/index.ts
2
- import { decode, sign, verify } from "./jwt.js";
3
- var Jwt = { sign, verify, decode };
2
+ import { decode, sign, verify, verifyFromJwks } from "./jwt.js";
3
+ var Jwt = { sign, verify, decode, verifyFromJwks };
4
4
  export {
5
5
  Jwt
6
6
  };
@@ -4,6 +4,7 @@ import { AlgorithmTypes } from "./jwa.js";
4
4
  import { signing, verifying } from "./jws.js";
5
5
  import {
6
6
  JwtHeaderInvalid,
7
+ JwtHeaderRequiresKid,
7
8
  JwtTokenExpired,
8
9
  JwtTokenInvalid,
9
10
  JwtTokenIssuedAt,
@@ -23,7 +24,13 @@ function isTokenHeader(obj) {
23
24
  }
24
25
  var sign = async (payload, privateKey, alg = "HS256") => {
25
26
  const encodedPayload = encodeJwtPart(payload);
26
- const encodedHeader = encodeJwtPart({ alg, typ: "JWT" });
27
+ let encodedHeader;
28
+ if (typeof privateKey === "object" && "alg" in privateKey) {
29
+ alg = privateKey.alg;
30
+ encodedHeader = encodeJwtPart({ alg, typ: "JWT", kid: privateKey.kid });
31
+ } else {
32
+ encodedHeader = encodeJwtPart({ alg, typ: "JWT" });
33
+ }
27
34
  const partialToken = `${encodedHeader}.${encodedPayload}`;
28
35
  const signaturePart = await signing(privateKey, alg, utf8Encoder.encode(partialToken));
29
36
  const signature = encodeSignaturePart(signaturePart);
@@ -60,6 +67,41 @@ var verify = async (token, publicKey, alg = "HS256") => {
60
67
  }
61
68
  return payload;
62
69
  };
70
+ var verifyFromJwks = async (token, options, init) => {
71
+ const header = decodeHeader(token);
72
+ if (!isTokenHeader(header)) {
73
+ throw new JwtHeaderInvalid(header);
74
+ }
75
+ if (!header.kid) {
76
+ throw new JwtHeaderRequiresKid(header);
77
+ }
78
+ let keys = typeof options.keys === "function" ? await options.keys() : options.keys;
79
+ if (options.jwks_uri) {
80
+ const response = await fetch(options.jwks_uri, init);
81
+ if (!response.ok) {
82
+ throw new Error(`failed to fetch JWKS from ${options.jwks_uri}`);
83
+ }
84
+ const data = await response.json();
85
+ if (!data.keys) {
86
+ throw new Error('invalid JWKS response. "keys" field is missing');
87
+ }
88
+ if (!Array.isArray(data.keys)) {
89
+ throw new Error('invalid JWKS response. "keys" field is not an array');
90
+ }
91
+ if (keys) {
92
+ keys.push(...data.keys);
93
+ } else {
94
+ keys = data.keys;
95
+ }
96
+ } else if (!keys) {
97
+ throw new Error('verifyFromJwks requires options for either "keys" or "jwks_uri" or both');
98
+ }
99
+ const matchingKey = keys.find((key) => key.kid === header.kid);
100
+ if (!matchingKey) {
101
+ throw new JwtTokenInvalid(token);
102
+ }
103
+ return await verify(token, matchingKey, matchingKey.alg);
104
+ };
63
105
  var decode = (token) => {
64
106
  try {
65
107
  const [h, p] = token.split(".");
@@ -73,9 +115,19 @@ var decode = (token) => {
73
115
  throw new JwtTokenInvalid(token);
74
116
  }
75
117
  };
118
+ var decodeHeader = (token) => {
119
+ try {
120
+ const [h] = token.split(".");
121
+ return decodeJwtPart(h);
122
+ } catch {
123
+ throw new JwtTokenInvalid(token);
124
+ }
125
+ };
76
126
  export {
77
127
  decode,
128
+ decodeHeader,
78
129
  isTokenHeader,
79
130
  sign,
80
- verify
131
+ verify,
132
+ verifyFromJwks
81
133
  };
@@ -35,6 +35,12 @@ var JwtHeaderInvalid = class extends Error {
35
35
  this.name = "JwtHeaderInvalid";
36
36
  }
37
37
  };
38
+ var JwtHeaderRequiresKid = class extends Error {
39
+ constructor(header) {
40
+ super(`required "kid" in jwt header: ${JSON.stringify(header)}`);
41
+ this.name = "JwtHeaderRequiresKid";
42
+ }
43
+ };
38
44
  var JwtTokenSignatureMismatched = class extends Error {
39
45
  constructor(token) {
40
46
  super(`token(${token}) signature mismatched`);
@@ -56,6 +62,7 @@ export {
56
62
  CryptoKeyUsage,
57
63
  JwtAlgorithmNotImplemented,
58
64
  JwtHeaderInvalid,
65
+ JwtHeaderRequiresKid,
59
66
  JwtTokenExpired,
60
67
  JwtTokenInvalid,
61
68
  JwtTokenIssuedAt,
package/dist/utils/url.js CHANGED
@@ -33,20 +33,21 @@ var replaceGroupMarks = (paths, groups) => {
33
33
  return paths;
34
34
  };
35
35
  var patternCache = {};
36
- var getPattern = (label) => {
36
+ var getPattern = (label, next) => {
37
37
  if (label === "*") {
38
38
  return "*";
39
39
  }
40
40
  const match = label.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
41
41
  if (match) {
42
- if (!patternCache[label]) {
42
+ const cacheKey = `${label}#${next}`;
43
+ if (!patternCache[cacheKey]) {
43
44
  if (match[2]) {
44
- patternCache[label] = [label, match[1], new RegExp("^" + match[2] + "$")];
45
+ patternCache[cacheKey] = next && next[0] !== ":" && next[0] !== "*" ? [cacheKey, match[1], new RegExp(`^${match[2]}(?=/${next})`)] : [label, match[1], new RegExp(`^${match[2]}$`)];
45
46
  } else {
46
- patternCache[label] = [label, match[1], true];
47
+ patternCache[cacheKey] = [label, match[1], true];
47
48
  }
48
49
  }
49
- return patternCache[label];
50
+ return patternCache[cacheKey];
50
51
  }
51
52
  return null;
52
53
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "4.6.19",
3
+ "version": "4.7.0",
4
4
  "description": "Web framework built on Web Standards",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",
@@ -204,6 +204,11 @@
204
204
  "import": "./dist/middleware/jwt/index.js",
205
205
  "require": "./dist/cjs/middleware/jwt/index.js"
206
206
  },
207
+ "./jwk": {
208
+ "types": "./dist/types/middleware/jwk/index.d.ts",
209
+ "import": "./dist/middleware/jwk/index.js",
210
+ "require": "./dist/cjs/middleware/jwk/index.js"
211
+ },
207
212
  "./timeout": {
208
213
  "types": "./dist/types/middleware/timeout/index.d.ts",
209
214
  "import": "./dist/middleware/timeout/index.js",
@@ -239,6 +244,11 @@
239
244
  "import": "./dist/middleware/request-id/index.js",
240
245
  "require": "./dist/cjs/middleware/request-id/index.js"
241
246
  },
247
+ "./language": {
248
+ "types": "./dist/types/middleware/language/index.d.ts",
249
+ "import": "./dist/middleware/language/index.js",
250
+ "require": "./dist/cjs/middleware/language/index.js"
251
+ },
242
252
  "./secure-headers": {
243
253
  "types": "./dist/types/middleware/secure-headers/index.d.ts",
244
254
  "import": "./dist/middleware/secure-headers/index.js",
@@ -388,6 +398,11 @@
388
398
  "types": "./dist/types/helper/conninfo/index.d.ts",
389
399
  "import": "./dist/helper/conninfo/index.js",
390
400
  "require": "./dist/cjs/helper/conninfo/index.js"
401
+ },
402
+ "./proxy": {
403
+ "types": "./dist/types/helper/proxy/index.d.ts",
404
+ "import": "./dist/helper/proxy/index.js",
405
+ "require": "./dist/cjs/helper/proxy/index.js"
391
406
  }
392
407
  },
393
408
  "typesVersions": {
@@ -506,6 +521,9 @@
506
521
  "request-id": [
507
522
  "./dist/types/middleware/request-id"
508
523
  ],
524
+ "language": [
525
+ "./dist/types/middleware/language"
526
+ ],
509
527
  "streaming": [
510
528
  "./dist/types/helper/streaming"
511
529
  ],
@@ -595,6 +613,9 @@
595
613
  ],
596
614
  "conninfo": [
597
615
  "./dist/types/helper/conninfo"
616
+ ],
617
+ "proxy": [
618
+ "./dist/types/helper/proxy"
598
619
  ]
599
620
  }
600
621
  },
@@ -632,21 +653,21 @@
632
653
  "@types/jsdom": "^21.1.7",
633
654
  "@types/node": "20.11.4",
634
655
  "@types/supertest": "^2.0.16",
635
- "@vitest/coverage-v8": "^2.0.5",
656
+ "@vitest/coverage-v8": "^3.0.5",
636
657
  "arg": "^5.0.2",
637
- "bun-types": "^1.1.34",
658
+ "bun-types": "^1.1.39",
638
659
  "esbuild": "^0.15.18",
639
660
  "eslint": "^9.10.0",
640
661
  "glob": "^11.0.0",
641
662
  "jsdom": "^22.1.0",
642
663
  "msw": "^2.6.0",
643
- "np": "7.7.0",
664
+ "np": "10.2.0",
644
665
  "prettier": "^2.6.2",
645
666
  "publint": "^0.1.16",
646
667
  "supertest": "^6.3.4",
647
668
  "typescript": "^5.3.3",
648
669
  "vite-plugin-fastly-js-compute": "^0.4.2",
649
- "vitest": "^2.0.5",
670
+ "vitest": "^3.0.5",
650
671
  "wrangler": "3.58.0",
651
672
  "ws": "^8.18.0",
652
673
  "zod": "^3.23.8"
File without changes
File without changes