hono 4.7.10 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +1 -0
  2. package/dist/adapter/cloudflare-pages/handler.js +2 -1
  3. package/dist/adapter/service-worker/index.js +6 -0
  4. package/dist/cjs/adapter/cloudflare-pages/handler.js +2 -1
  5. package/dist/cjs/adapter/service-worker/index.js +7 -0
  6. package/dist/cjs/context.js +48 -116
  7. package/dist/cjs/helper/route/index.js +69 -0
  8. package/dist/cjs/helper/ssg/ssg.js +47 -8
  9. package/dist/cjs/helper/testing/index.js +2 -2
  10. package/dist/cjs/hono-base.js +3 -2
  11. package/dist/cjs/jsx/components.js +4 -1
  12. package/dist/cjs/jsx/streaming.js +6 -1
  13. package/dist/cjs/middleware/cache/index.js +5 -1
  14. package/dist/cjs/middleware/cors/index.js +12 -2
  15. package/dist/cjs/middleware/etag/index.js +2 -1
  16. package/dist/cjs/middleware/jwk/jwk.js +6 -1
  17. package/dist/cjs/middleware/jwt/jwt.js +2 -1
  18. package/dist/cjs/middleware/logger/index.js +6 -6
  19. package/dist/cjs/request/constants.js +28 -0
  20. package/dist/cjs/request.js +4 -0
  21. package/dist/cjs/router/trie-router/node.js +11 -13
  22. package/dist/cjs/utils/body.js +5 -1
  23. package/dist/cjs/utils/color.js +15 -2
  24. package/dist/cjs/utils/jwt/jwt.js +5 -6
  25. package/dist/cjs/utils/mime.js +1 -0
  26. package/dist/cjs/utils/url.js +5 -2
  27. package/dist/context.js +48 -116
  28. package/dist/helper/route/index.js +43 -0
  29. package/dist/helper/ssg/ssg.js +46 -8
  30. package/dist/helper/testing/index.js +2 -2
  31. package/dist/hono-base.js +3 -2
  32. package/dist/jsx/components.js +4 -1
  33. package/dist/jsx/streaming.js +5 -1
  34. package/dist/middleware/cache/index.js +5 -1
  35. package/dist/middleware/cors/index.js +12 -2
  36. package/dist/middleware/etag/index.js +2 -1
  37. package/dist/middleware/jwk/jwk.js +6 -1
  38. package/dist/middleware/jwt/jwt.js +2 -1
  39. package/dist/middleware/logger/index.js +7 -7
  40. package/dist/request/constants.js +5 -0
  41. package/dist/request.js +4 -0
  42. package/dist/router/trie-router/node.js +11 -13
  43. package/dist/types/adapter/cloudflare-pages/handler.d.ts +1 -0
  44. package/dist/types/adapter/service-worker/handler.d.ts +4 -3
  45. package/dist/types/adapter/service-worker/index.d.ts +23 -1
  46. package/dist/types/context.d.ts +5 -1
  47. package/dist/types/helper/adapter/index.d.ts +1 -1
  48. package/dist/types/helper/route/index.d.ts +67 -0
  49. package/dist/types/helper/ssg/ssg.d.ts +9 -2
  50. package/dist/types/helper/testing/index.d.ts +2 -2
  51. package/dist/types/hono-base.d.ts +10 -0
  52. package/dist/types/jsx/streaming.d.ts +16 -1
  53. package/dist/types/middleware/cache/index.d.ts +3 -0
  54. package/dist/types/middleware/cors/index.d.ts +2 -2
  55. package/dist/types/middleware/jwk/jwk.d.ts +10 -7
  56. package/dist/types/middleware/jwt/jwt.d.ts +3 -0
  57. package/dist/types/request/constants.d.ts +1 -0
  58. package/dist/types/request.d.ts +8 -0
  59. package/dist/types/types.d.ts +1 -0
  60. package/dist/types/utils/color.d.ts +9 -0
  61. package/dist/types/utils/jwt/index.d.ts +1 -1
  62. package/dist/types/utils/jwt/jwt.d.ts +1 -1
  63. package/dist/types/utils/mime.d.ts +1 -0
  64. package/dist/utils/body.js +5 -1
  65. package/dist/utils/color.js +7 -1
  66. package/dist/utils/jwt/jwt.js +5 -6
  67. package/dist/utils/mime.js +1 -0
  68. package/dist/utils/url.js +5 -2
  69. package/package.json +10 -1
@@ -4,8 +4,10 @@ import { HtmlEscapedCallbackPhase, resolveCallback } from "../utils/html.js";
4
4
  import { JSXNode } from "./base.js";
5
5
  import { childrenToString } from "./components.js";
6
6
  import { DOM_RENDERER, DOM_STASH } from "./constants.js";
7
+ import { createContext, useContext } from "./context.js";
7
8
  import { Suspense as SuspenseDomRenderer } from "./dom/components.js";
8
9
  import { buildDataStack } from "./dom/render.js";
10
+ var StreamingContext = createContext(null);
9
11
  var suspenseCounter = 0;
10
12
  var Suspense = async ({
11
13
  children,
@@ -17,6 +19,7 @@ var Suspense = async ({
17
19
  if (!Array.isArray(children)) {
18
20
  children = [children];
19
21
  }
22
+ const nonce = useContext(StreamingContext)?.scriptNonce;
20
23
  let resArray = [];
21
24
  const stackNode = { [DOM_STASH]: [0, []] };
22
25
  const popNodeStack = (value) => {
@@ -62,7 +65,7 @@ var Suspense = async ({
62
65
  content
63
66
  );
64
67
  }
65
- let html = buffer ? "" : `<template data-hono-target="H:${index}">${content}</template><script>
68
+ let html = buffer ? "" : `<template data-hono-target="H:${index}">${content}</template><script${nonce ? ` nonce="${nonce}"` : ""}>
66
69
  ((d,c,n) => {
67
70
  c=d.currentScript.previousSibling
68
71
  d=d.getElementById('H:${index}')
@@ -137,6 +140,7 @@ var renderToReadableStream = (content, onError = console.trace) => {
137
140
  return reader;
138
141
  };
139
142
  export {
143
+ StreamingContext,
140
144
  Suspense,
141
145
  renderToReadableStream
142
146
  };
@@ -1,4 +1,5 @@
1
1
  // src/middleware/cache/index.ts
2
+ var defaultCacheableStatusCodes = [200];
2
3
  var cache = (options) => {
3
4
  if (!globalThis.caches) {
4
5
  console.log("Cache Middleware is not enabled because caches is not defined.");
@@ -14,6 +15,9 @@ var cache = (options) => {
14
15
  'Middleware vary configuration cannot include "*", as it disallows effective caching.'
15
16
  );
16
17
  }
18
+ const cacheableStatusCodes = new Set(
19
+ options.cacheableStatusCodes ?? defaultCacheableStatusCodes
20
+ );
17
21
  const addHeader = (c) => {
18
22
  if (cacheControlDirectives) {
19
23
  const existingDirectives = c.res.headers.get("Cache-Control")?.split(",").map((d) => d.trim().split("=", 1)[0]) ?? [];
@@ -51,7 +55,7 @@ var cache = (options) => {
51
55
  return new Response(response.body, response);
52
56
  }
53
57
  await next();
54
- if (!c.res.ok) {
58
+ if (!cacheableStatusCodes.has(c.res.status)) {
55
59
  return;
56
60
  }
57
61
  addHeader(c);
@@ -23,6 +23,15 @@ var cors = (options) => {
23
23
  return (origin) => optsOrigin.includes(origin) ? origin : null;
24
24
  }
25
25
  })(opts.origin);
26
+ const findAllowMethods = ((optsAllowMethods) => {
27
+ if (typeof optsAllowMethods === "function") {
28
+ return optsAllowMethods;
29
+ } else if (Array.isArray(optsAllowMethods)) {
30
+ return () => optsAllowMethods;
31
+ } else {
32
+ return () => [];
33
+ }
34
+ })(opts.allowMethods);
26
35
  return async function cors2(c, next) {
27
36
  function set(key, value) {
28
37
  c.res.headers.set(key, value);
@@ -49,8 +58,9 @@ var cors = (options) => {
49
58
  if (opts.maxAge != null) {
50
59
  set("Access-Control-Max-Age", opts.maxAge.toString());
51
60
  }
52
- if (opts.allowMethods?.length) {
53
- set("Access-Control-Allow-Methods", opts.allowMethods.join(","));
61
+ const allowMethods = findAllowMethods(c.req.header("origin") || "", c);
62
+ if (allowMethods.length) {
63
+ set("Access-Control-Allow-Methods", allowMethods.join(","));
54
64
  }
55
65
  let headers = opts.allowHeaders;
56
66
  if (!headers?.length) {
@@ -8,8 +8,9 @@ var RETAINED_304_HEADERS = [
8
8
  "expires",
9
9
  "vary"
10
10
  ];
11
+ var stripWeak = (tag) => tag.replace(/^W\//, "");
11
12
  function etagMatches(etag2, ifNoneMatch) {
12
- return ifNoneMatch != null && ifNoneMatch.split(/,\s*/).indexOf(etag2) > -1;
13
+ return ifNoneMatch != null && ifNoneMatch.split(/,\s*/).some((t) => stripWeak(t) === stripWeak(etag2));
13
14
  }
14
15
  function initializeGenerator(generator) {
15
16
  if (!generator) {
@@ -51,6 +51,9 @@ var jwk = (options, init) => {
51
51
  }
52
52
  }
53
53
  if (!token) {
54
+ if (options.allow_anon) {
55
+ return next();
56
+ }
54
57
  const errDescription = "no authorization included in request";
55
58
  throw new HTTPException(401, {
56
59
  message: errDescription,
@@ -64,7 +67,9 @@ var jwk = (options, init) => {
64
67
  let payload;
65
68
  let cause;
66
69
  try {
67
- payload = await Jwt.verifyFromJwks(token, options, init);
70
+ const keys = typeof options.keys === "function" ? await options.keys(ctx) : options.keys;
71
+ const jwks_uri = typeof options.jwks_uri === "function" ? await options.jwks_uri(ctx) : options.jwks_uri;
72
+ payload = await Jwt.verifyFromJwks(token, { keys, jwks_uri }, init);
68
73
  } catch (e) {
69
74
  cause = e;
70
75
  }
@@ -11,7 +11,8 @@ var jwt = (options) => {
11
11
  throw new Error("`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.");
12
12
  }
13
13
  return async function jwt2(ctx, next) {
14
- const credentials = ctx.req.raw.headers.get("Authorization");
14
+ const headerName = options.headerName || "Authorization";
15
+ const credentials = ctx.req.raw.headers.get(headerName);
15
16
  let token;
16
17
  if (credentials) {
17
18
  const parts = credentials.split(/\s+/);
@@ -1,5 +1,5 @@
1
1
  // src/middleware/logger/index.ts
2
- import { getColorEnabled } from "../../utils/color.js";
2
+ import { getColorEnabledAsync } from "../../utils/color.js";
3
3
  var humanize = (times) => {
4
4
  const [delimiter, separator] = [",", "."];
5
5
  const orderTimes = times.map((v) => v.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1" + delimiter));
@@ -9,8 +9,8 @@ var time = (start) => {
9
9
  const delta = Date.now() - start;
10
10
  return humanize([delta < 1e3 ? delta + "ms" : Math.round(delta / 1e3) + "s"]);
11
11
  };
12
- var colorStatus = (status) => {
13
- const colorEnabled = getColorEnabled();
12
+ var colorStatus = async (status) => {
13
+ const colorEnabled = await getColorEnabledAsync();
14
14
  if (colorEnabled) {
15
15
  switch (status / 100 | 0) {
16
16
  case 5:
@@ -25,18 +25,18 @@ var colorStatus = (status) => {
25
25
  }
26
26
  return `${status}`;
27
27
  };
28
- function log(fn, prefix, method, path, status = 0, elapsed) {
29
- const out = prefix === "<--" /* Incoming */ ? `${prefix} ${method} ${path}` : `${prefix} ${method} ${path} ${colorStatus(status)} ${elapsed}`;
28
+ async function log(fn, prefix, method, path, status = 0, elapsed) {
29
+ const out = prefix === "<--" /* Incoming */ ? `${prefix} ${method} ${path}` : `${prefix} ${method} ${path} ${await colorStatus(status)} ${elapsed}`;
30
30
  fn(out);
31
31
  }
32
32
  var logger = (fn = console.log) => {
33
33
  return async function logger2(c, next) {
34
34
  const { method, url } = c.req;
35
35
  const path = url.slice(url.indexOf("/", 8));
36
- log(fn, "<--" /* Incoming */, method, path);
36
+ await log(fn, "<--" /* Incoming */, method, path);
37
37
  const start = Date.now();
38
38
  await next();
39
- log(fn, "-->" /* Outgoing */, method, path, c.res.status, time(start));
39
+ await log(fn, "-->" /* Outgoing */, method, path, c.res.status, time(start));
40
40
  };
41
41
  };
42
42
  export {
@@ -0,0 +1,5 @@
1
+ // src/request/constants.ts
2
+ var GET_MATCH_RESULT = Symbol();
3
+ export {
4
+ GET_MATCH_RESULT
5
+ };
package/dist/request.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/request.ts
2
+ import { GET_MATCH_RESULT } from "./request/constants.js";
2
3
  import { parseBody } from "./utils/body.js";
3
4
  import { decodeURIComponent_, getQueryParam, getQueryParams, tryDecode } from "./utils/url.js";
4
5
  var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
@@ -100,6 +101,9 @@ var HonoRequest = class {
100
101
  get method() {
101
102
  return this.raw.method;
102
103
  }
104
+ get [GET_MATCH_RESULT]() {
105
+ return this.#matchResult;
106
+ }
103
107
  get matchedRoutes() {
104
108
  return this.#matchResult[0].map(([[, route]]) => route);
105
109
  }
@@ -28,11 +28,10 @@ var Node = class {
28
28
  const nextP = parts[i + 1];
29
29
  const pattern = getPattern(p, nextP);
30
30
  const key = Array.isArray(pattern) ? pattern[0] : p;
31
- if (Object.keys(curNode.#children).includes(key)) {
31
+ if (key in curNode.#children) {
32
32
  curNode = curNode.#children[key];
33
- const pattern2 = getPattern(p, nextP);
34
- if (pattern2) {
35
- possibleKeys.push(pattern2[1]);
33
+ if (pattern) {
34
+ possibleKeys.push(pattern[1]);
36
35
  }
37
36
  continue;
38
37
  }
@@ -43,14 +42,13 @@ var Node = class {
43
42
  }
44
43
  curNode = curNode.#children[key];
45
44
  }
46
- const m = /* @__PURE__ */ Object.create(null);
47
- const handlerSet = {
48
- handler,
49
- possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
50
- score: this.#order
51
- };
52
- m[method] = handlerSet;
53
- curNode.#methods.push(m);
45
+ curNode.#methods.push({
46
+ [method]: {
47
+ handler,
48
+ possibleKeys: possibleKeys.filter((v, i, a) => a.indexOf(v) === i),
49
+ score: this.#order
50
+ }
51
+ });
54
52
  return curNode;
55
53
  }
56
54
  #getHandlerSets(node, method, nodeParams, params) {
@@ -113,7 +111,7 @@ var Node = class {
113
111
  }
114
112
  continue;
115
113
  }
116
- if (part === "") {
114
+ if (!part) {
117
115
  continue;
118
116
  }
119
117
  const [key, name, matcher] = pattern;
@@ -6,6 +6,7 @@ export type EventContext<Env = {}, P extends string = any, Data = Record<string,
6
6
  functionPath: string;
7
7
  waitUntil: (promise: Promise<unknown>) => void;
8
8
  passThroughOnException: () => void;
9
+ props: any;
9
10
  next: (input?: Request | string, init?: RequestInit) => Promise<Response>;
10
11
  env: Env & {
11
12
  ASSETS: {
@@ -5,10 +5,11 @@
5
5
  import type { Hono } from '../../hono';
6
6
  import type { FetchEvent } from './types';
7
7
  type Handler = (evt: FetchEvent) => void;
8
+ export type HandleOptions = {
9
+ fetch?: typeof fetch;
10
+ };
8
11
  /**
9
12
  * Adapter for Service Worker
10
13
  */
11
- export declare const handle: (app: Hono, opts?: {
12
- fetch?: typeof fetch;
13
- }) => Handler;
14
+ export declare const handle: (app: Hono, opts?: HandleOptions) => Handler;
14
15
  export {};
@@ -2,4 +2,26 @@
2
2
  * Service Worker Adapter for Hono.
3
3
  * @module
4
4
  */
5
- export { handle } from './handler';
5
+ import type { Hono } from '../../hono';
6
+ import { handle } from './handler';
7
+ import type { HandleOptions } from './handler';
8
+ /**
9
+ * Registers a Hono app to handle fetch events in a service worker.
10
+ * This sets up `addEventListener('fetch', handle(app, options))` for the provided app.
11
+ *
12
+ * @param app - The Hono application instance
13
+ * @param options - Options for handling requests (fetch defaults to undefined)
14
+ * @example
15
+ * ```ts
16
+ * import { Hono } from 'hono'
17
+ * import { fire } from 'hono/service-worker'
18
+ *
19
+ * const app = new Hono()
20
+ *
21
+ * app.get('/', (c) => c.text('Hi'))
22
+ *
23
+ * fire(app)
24
+ * ```
25
+ */
26
+ declare const fire: (app: Hono, options?: HandleOptions) => void;
27
+ export { handle, fire };
@@ -24,6 +24,10 @@ export interface ExecutionContext {
24
24
  * Allows the event to be passed through to subsequent event listeners.
25
25
  */
26
26
  passThroughOnException(): void;
27
+ /**
28
+ * For compatibility with Wrangler 4.x.
29
+ */
30
+ props: any;
27
31
  }
28
32
  /**
29
33
  * Interface for context variable mapping.
@@ -316,7 +320,7 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
316
320
  /**
317
321
  * `.header()` can set headers.
318
322
  *
319
- * @see {@link https://hono.dev/docs/api/context#body}
323
+ * @see {@link https://hono.dev/docs/api/context#header}
320
324
  *
321
325
  * @example
322
326
  * ```ts
@@ -6,7 +6,7 @@ import type { Context } from '../../context';
6
6
  export type Runtime = "node" | "deno" | "bun" | "workerd" | "fastly" | "edge-light" | "other";
7
7
  export declare const env: <T extends Record<string, unknown>, C extends Context = Context<{
8
8
  Bindings: T;
9
- }>>(c: T extends Record<string, unknown> ? Context : C, runtime?: Runtime) => T & C["env"];
9
+ }, any, {}>>(c: T extends Record<string, unknown> ? Context : C, runtime?: Runtime) => T & C["env"];
10
10
  export declare const knownUserAgents: Partial<Record<Runtime, string>>;
11
11
  export declare const getRuntimeKey: () => Runtime;
12
12
  export declare const checkUserAgentEquals: (platform: string) => boolean;
@@ -0,0 +1,67 @@
1
+ import type { Context } from '../../context';
2
+ import type { RouterRoute } from '../../types';
3
+ /**
4
+ * Get matched routes in the handler
5
+ *
6
+ * @param {Context} c - The context object
7
+ * @returns An array of matched routes
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { matchedRoutes } from 'hono/route'
12
+ *
13
+ * app.use('*', async function logger(c, next) {
14
+ * await next()
15
+ * matchedRoutes(c).forEach(({ handler, method, path }, i) => {
16
+ * const name = handler.name || (handler.length < 2 ? '[handler]' : '[middleware]')
17
+ * console.log(
18
+ * method,
19
+ * ' ',
20
+ * path,
21
+ * ' '.repeat(Math.max(10 - path.length, 0)),
22
+ * name,
23
+ * i === c.req.routeIndex ? '<- respond from here' : ''
24
+ * )
25
+ * })
26
+ * })
27
+ * ```
28
+ */
29
+ export declare const matchedRoutes: (c: Context) => RouterRoute[];
30
+ /**
31
+ * Get the route path registered within the handler
32
+ *
33
+ * @param {Context} c - The context object
34
+ * @returns The route path registered within the handler
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * import { routePath } from 'hono/route'
39
+ *
40
+ * app.get('/posts/:id', (c) => {
41
+ * return c.text(routePath(c)) // '/posts/:id'
42
+ * })
43
+ * ```
44
+ */
45
+ export declare const routePath: (c: Context) => string;
46
+ /**
47
+ * Get the basePath of the as-is route specified by routing.
48
+ *
49
+ * @param {Context} c - The context object
50
+ * @returns The basePath of the as-is route specified by routing.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * import { baseRoutePath } from 'hono/route'
55
+ *
56
+ * const app = new Hono()
57
+ *
58
+ * const subApp = new Hono()
59
+ * subApp.get('/posts/:id', (c) => {
60
+ * return c.text(baseRoutePath(c)) // '/:sub'
61
+ * })
62
+ *
63
+ * app.route('/:sub', subApp)
64
+ * ```
65
+ */
66
+ export declare const baseRoutePath: (c: Context) => string;
67
+ export declare const basePath: (c: Context) => string;
@@ -1,5 +1,6 @@
1
1
  import type { Hono } from '../../hono';
2
2
  import type { Env, Schema } from '../../types';
3
+ export declare const DEFAULT_OUTPUT_DIR = "./static";
3
4
  /**
4
5
  * @experimental
5
6
  * `FileSystemModule` is an experimental feature.
@@ -24,10 +25,15 @@ export interface ToSSGResult {
24
25
  export declare const defaultExtensionMap: Record<string, string>;
25
26
  export type BeforeRequestHook = (req: Request) => Request | false | Promise<Request | false>;
26
27
  export type AfterResponseHook = (res: Response) => Response | false | Promise<Response | false>;
27
- export type AfterGenerateHook = (result: ToSSGResult) => void | Promise<void>;
28
+ export type AfterGenerateHook = (result: ToSSGResult, fsModule: FileSystemModule, options?: ToSSGOptions) => void | Promise<void>;
28
29
  export declare const combineBeforeRequestHooks: (hooks: BeforeRequestHook | BeforeRequestHook[]) => BeforeRequestHook;
29
30
  export declare const combineAfterResponseHooks: (hooks: AfterResponseHook | AfterResponseHook[]) => AfterResponseHook;
30
- export declare const combineAfterGenerateHooks: (hooks: AfterGenerateHook | AfterGenerateHook[]) => AfterGenerateHook;
31
+ export declare const combineAfterGenerateHooks: (hooks: AfterGenerateHook | AfterGenerateHook[], fsModule: FileSystemModule, options?: ToSSGOptions) => AfterGenerateHook;
32
+ export interface SSGPlugin {
33
+ beforeRequestHook?: BeforeRequestHook | BeforeRequestHook[];
34
+ afterResponseHook?: AfterResponseHook | AfterResponseHook[];
35
+ afterGenerateHook?: AfterGenerateHook | AfterGenerateHook[];
36
+ }
31
37
  export interface ToSSGOptions {
32
38
  dir?: string;
33
39
  beforeRequestHook?: BeforeRequestHook | BeforeRequestHook[];
@@ -35,6 +41,7 @@ export interface ToSSGOptions {
35
41
  afterGenerateHook?: AfterGenerateHook | AfterGenerateHook[];
36
42
  concurrency?: number;
37
43
  extensionMap?: Record<string, string>;
44
+ plugins?: SSGPlugin[];
38
45
  }
39
46
  /**
40
47
  * @experimental
@@ -2,11 +2,11 @@
2
2
  * @module
3
3
  * Testing Helper for Hono.
4
4
  */
5
- import type { Client } from '../../client/types';
5
+ import type { Client, ClientRequestOptions } from '../../client/types';
6
6
  import type { ExecutionContext } from '../../context';
7
7
  import type { Hono } from '../../hono';
8
8
  import type { Schema } from '../../types';
9
9
  import type { UnionToIntersection } from '../../utils/types';
10
10
  type ExtractEnv<T> = T extends Hono<infer E, Schema, string> ? E : never;
11
- export declare const testClient: <T extends Hono<any, Schema, string>>(app: T, Env?: ExtractEnv<T>["Bindings"] | {}, executionCtx?: ExecutionContext) => UnionToIntersection<Client<T>>;
11
+ export declare const testClient: <T extends Hono<any, Schema, string>>(app: T, Env?: ExtractEnv<T>["Bindings"] | {}, executionCtx?: ExecutionContext, options?: Omit<ClientRequestOptions, "fetch">) => UnionToIntersection<Client<T>>;
12
12
  export {};
@@ -204,6 +204,16 @@ declare class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends
204
204
  /**
205
205
  * `.fire()` automatically adds a global fetch event listener.
206
206
  * This can be useful for environments that adhere to the Service Worker API, such as non-ES module Cloudflare Workers.
207
+ * @deprecated
208
+ * Use `fire` from `hono/service-worker` instead.
209
+ * ```ts
210
+ * import { Hono } from 'hono'
211
+ * import { fire } from 'hono/service-worker'
212
+ *
213
+ * const app = new Hono()
214
+ * // ...
215
+ * fire(app)
216
+ * ```
207
217
  * @see https://hono.dev/docs/api/hono#fire
208
218
  * @see https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
209
219
  * @see https://developers.cloudflare.com/workers/reference/migrate-to-module-workers/
@@ -4,7 +4,22 @@
4
4
  */
5
5
  import type { HtmlEscapedString } from '../utils/html';
6
6
  import { JSXNode } from './base';
7
- import type { FC, PropsWithChildren } from './';
7
+ import type { FC, PropsWithChildren, Context as JSXContext } from './';
8
+ /**
9
+ * Used to specify nonce for scripts generated by `Suspense` and `ErrorBoundary`.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * <StreamingContext.Provider value={{ scriptNonce: 'test-nonce' }}>
14
+ * <Suspense fallback={<p>Loading...</p>}>
15
+ * <Content />
16
+ * </Suspense>
17
+ * </StreamingContext.Provider>
18
+ * ```
19
+ */
20
+ export declare const StreamingContext: JSXContext<{
21
+ scriptNonce: string;
22
+ } | null>;
8
23
  /**
9
24
  * @experimental
10
25
  * `Suspense` is an experimental feature.
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import type { Context } from '../../context';
6
6
  import type { MiddlewareHandler } from '../../types';
7
+ import type { StatusCode } from '../../utils/http-status';
7
8
  /**
8
9
  * Cache Middleware for Hono.
9
10
  *
@@ -15,6 +16,7 @@ import type { MiddlewareHandler } from '../../types';
15
16
  * @param {string} [options.cacheControl] - A string of directives for the `Cache-Control` header.
16
17
  * @param {string | string[]} [options.vary] - Sets the `Vary` header in the response. If the original response header already contains a `Vary` header, the values are merged, removing any duplicates.
17
18
  * @param {Function} [options.keyGenerator] - Generates keys for every request in the `cacheName` store. This can be used to cache data based on request parameters or context parameters.
19
+ * @param {number[]} [options.cacheableStatusCodes=[200]] - An array of status codes that can be cached.
18
20
  * @returns {MiddlewareHandler} The middleware handler function.
19
21
  * @throws {Error} If the `vary` option includes "*".
20
22
  *
@@ -35,4 +37,5 @@ export declare const cache: (options: {
35
37
  cacheControl?: string;
36
38
  vary?: string | string[];
37
39
  keyGenerator?: (c: Context) => Promise<string> | string;
40
+ cacheableStatusCodes?: StatusCode[];
38
41
  }) => MiddlewareHandler;
@@ -6,7 +6,7 @@ import type { Context } from '../../context';
6
6
  import type { MiddlewareHandler } from '../../types';
7
7
  type CORSOptions = {
8
8
  origin: string | string[] | ((origin: string, c: Context) => string | undefined | null);
9
- allowMethods?: string[];
9
+ allowMethods?: string[] | ((origin: string, c: Context) => string[]);
10
10
  allowHeaders?: string[];
11
11
  maxAge?: number;
12
12
  credentials?: boolean;
@@ -19,7 +19,7 @@ type CORSOptions = {
19
19
  *
20
20
  * @param {CORSOptions} [options] - The options for the CORS middleware.
21
21
  * @param {string | string[] | ((origin: string, c: Context) => string | undefined | null)} [options.origin='*'] - The value of "Access-Control-Allow-Origin" CORS header.
22
- * @param {string[]} [options.allowMethods=['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH']] - The value of "Access-Control-Allow-Methods" CORS header.
22
+ * @param {string[] | ((origin: string, c: Context) => string[])} [options.allowMethods=['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH']] - The value of "Access-Control-Allow-Methods" CORS header.
23
23
  * @param {string[]} [options.allowHeaders=[]] - The value of "Access-Control-Allow-Headers" CORS header.
24
24
  * @param {number} [options.maxAge] - The value of "Access-Control-Max-Age" CORS header.
25
25
  * @param {boolean} [options.credentials] - The value of "Access-Control-Allow-Credentials" CORS header.
@@ -2,6 +2,7 @@
2
2
  * @module
3
3
  * JWK Auth Middleware for Hono.
4
4
  */
5
+ import type { Context } from '../../context';
5
6
  import type { MiddlewareHandler } from '../../types';
6
7
  import type { CookiePrefixOptions } from '../../utils/cookie';
7
8
  import '../../context';
@@ -12,17 +13,18 @@ import type { HonoJsonWebKey } from '../../utils/jwt/jws';
12
13
  * @see {@link https://hono.dev/docs/middleware/builtin/jwk}
13
14
  *
14
15
  * @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.
16
+ * @param {HonoJsonWebKey[] | ((ctx: Context) => Promise<HonoJsonWebKey[]> | HonoJsonWebKey[])} [options.keys] - The public keys used for JWK verification, or a function that returns them.
17
+ * @param {string | ((ctx: Context) => Promise<string> | string)} [options.jwks_uri] - If set to a URI string or a function that returns a URI string, attempt to fetch JWKs from it. The response must be a JSON object containing a `keys` array, which will be merged with the `keys` option.
18
+ * @param {boolean} [options.allow_anon] - If set to `true`, the middleware allows requests without a token to proceed without authentication.
19
+ * @param {string} [options.cookie] - If set, the middleware attempts to retrieve the token from a cookie with these options (optionally signed) only if no token is found in the header.
20
+ * @param {RequestInit} [init] - Optional init options for the `fetch` request when retrieving JWKS from a URI.
19
21
  * @returns {MiddlewareHandler} The middleware handler function.
20
22
  *
21
23
  * @example
22
24
  * ```ts
23
25
  * const app = new Hono()
24
26
  *
25
- * app.use("/auth/*", jwk({ jwks_uri: "https://example-backend.hono.dev/.well-known/jwks.json" }))
27
+ * app.use("/auth/*", jwk({ jwks_uri: (c) => `https://${c.env.authServer}/.well-known/jwks.json` }))
26
28
  *
27
29
  * app.get('/auth/page', (c) => {
28
30
  * return c.text('You are authorized')
@@ -30,8 +32,9 @@ import type { HonoJsonWebKey } from '../../utils/jwt/jws';
30
32
  * ```
31
33
  */
32
34
  export declare const jwk: (options: {
33
- keys?: HonoJsonWebKey[] | (() => Promise<HonoJsonWebKey[]>);
34
- jwks_uri?: string;
35
+ keys?: HonoJsonWebKey[] | ((ctx: Context) => Promise<HonoJsonWebKey[]> | HonoJsonWebKey[]);
36
+ jwks_uri?: string | ((ctx: Context) => Promise<string> | string);
37
+ allow_anon?: boolean;
35
38
  cookie?: string | {
36
39
  key: string;
37
40
  secret?: string | BufferSource;
@@ -19,6 +19,7 @@ export type JwtVariables<T = any> = {
19
19
  * @param {SignatureKey} [options.secret] - A value of your secret key.
20
20
  * @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.
21
21
  * @param {SignatureAlgorithm} [options.alg=HS256] - An algorithm type that is used for verifying. Available types are `HS256` | `HS384` | `HS512` | `RS256` | `RS384` | `RS512` | `PS256` | `PS384` | `PS512` | `ES256` | `ES384` | `ES512` | `EdDSA`.
22
+ * @param {string} [options.headerName='Authorization'] - The name of the header to look for the JWT token. Default is 'Authorization'.
22
23
  * @returns {MiddlewareHandler} The middleware handler function.
23
24
  *
24
25
  * @example
@@ -29,6 +30,7 @@ export type JwtVariables<T = any> = {
29
30
  * '/auth/*',
30
31
  * jwt({
31
32
  * secret: 'it-is-very-secret',
33
+ * headerName: 'x-custom-auth-header', // Optional, default is 'Authorization'
32
34
  * })
33
35
  * )
34
36
  *
@@ -45,6 +47,7 @@ export declare const jwt: (options: {
45
47
  prefixOptions?: CookiePrefixOptions;
46
48
  };
47
49
  alg?: SignatureAlgorithm;
50
+ headerName?: string;
48
51
  }) => MiddlewareHandler;
49
52
  export declare const verify: (token: string, publicKey: SignatureKey, alg?: SignatureAlgorithm) => Promise<import("../../utils/jwt/types").JWTPayload>;
50
53
  export declare const decode: (token: string) => {
@@ -0,0 +1 @@
1
+ export declare const GET_MATCH_RESULT: symbol;
@@ -235,6 +235,10 @@ export declare class HonoRequest<P extends string = "/", I extends Input["out"]
235
235
  /**
236
236
  * `.matchedRoutes()` can return a matched route in the handler
237
237
  *
238
+ * @deprecated
239
+ *
240
+ * Use matchedRoutes helper defined in "hono/route" instead.
241
+ *
238
242
  * @see {@link https://hono.dev/docs/api/request#matchedroutes}
239
243
  *
240
244
  * @example
@@ -259,6 +263,10 @@ export declare class HonoRequest<P extends string = "/", I extends Input["out"]
259
263
  /**
260
264
  * `routePath()` can retrieve the path registered within the handler
261
265
  *
266
+ * @deprecated
267
+ *
268
+ * Use routePath helper defined in "hono/route" instead.
269
+ *
262
270
  * @see {@link https://hono.dev/docs/api/request#routepath}
263
271
  *
264
272
  * @example
@@ -24,6 +24,7 @@ export type Input = {
24
24
  export type BlankSchema = {};
25
25
  export type BlankInput = {};
26
26
  export interface RouterRoute {
27
+ basePath: string;
27
28
  path: string;
28
29
  method: string;
29
30
  handler: H;
@@ -5,8 +5,17 @@
5
5
  /**
6
6
  * Get whether color change on terminal is enabled or disabled.
7
7
  * If `NO_COLOR` environment variable is set, this function returns `false`.
8
+ * Unlike getColorEnabledAsync(), this cannot check Cloudflare environment variables.
8
9
  * @see {@link https://no-color.org/}
9
10
  *
10
11
  * @returns {boolean}
11
12
  */
12
13
  export declare function getColorEnabled(): boolean;
14
+ /**
15
+ * Get whether color change on terminal is enabled or disabled.
16
+ * If `NO_COLOR` environment variable is set, this function returns `false`.
17
+ * @see {@link https://no-color.org/}
18
+ *
19
+ * @returns {boolean}
20
+ */
21
+ export declare function getColorEnabledAsync(): Promise<boolean>;