hono 4.4.2 β†’ 4.4.3

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/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  <p align="center">
10
10
  <a href="https://hono.dev"><b>Documentation πŸ‘‰ hono.dev</b></a><br />
11
- <i>v4 has been released!</i> <a href="docs/MIGRATION.md">Migration guide</b>
11
+ <i>Now supports <a href="https://jsr.io/@hono/hono">JSR</a> and <code>deno.land/x</code> is deprecated! See <a href="docs/MIGRATION.md">Migration guide</a>.</i>
12
12
  </p>
13
13
 
14
14
  <hr />
@@ -22,6 +22,7 @@
22
22
  [![Bundle Size](https://img.shields.io/bundlephobia/minzip/hono)](https://bundlephobia.com/result?p=hono)
23
23
  [![GitHub commit activity](https://img.shields.io/github/commit-activity/m/honojs/hono)](https://github.com/honojs/hono/pulse)
24
24
  [![GitHub last commit](https://img.shields.io/github/last-commit/honojs/hono)](https://github.com/honojs/hono/commits/main)
25
+ [![codecov](https://codecov.io/github/honojs/hono/graph/badge.svg)](https://codecov.io/github/honojs/hono)
25
26
  [![Discord badge](https://img.shields.io/discord/1011308539819597844?label=Discord&logo=Discord)](https://discord.gg/KMh2eNSdxV)
26
27
 
27
28
  Hono - _**\[η‚Ž\] means flameπŸ”₯ in Japanese**_ - is a small, simple, and ultrafast web framework for the Edges.
@@ -35,6 +35,7 @@ var upgradeWebSocket = (createEvents) => async (c, next) => {
35
35
  }
36
36
  server.accept?.();
37
37
  return new Response(null, {
38
+ status: 101,
38
39
  webSocket: client
39
40
  });
40
41
  };
@@ -4,13 +4,12 @@ var { open } = Deno;
4
4
  var serveStatic = (options) => {
5
5
  return async function serveStatic2(c, next) {
6
6
  const getContent = async (path) => {
7
- let file;
8
7
  try {
9
- file = await open(path);
8
+ const file = await open(path);
9
+ return file ? file.readable : null;
10
10
  } catch (e) {
11
11
  console.warn(`${e}`);
12
12
  }
13
- return file ? file.readable : null;
14
13
  };
15
14
  const pathResolve = (path) => {
16
15
  return `./${path}`;
@@ -3,8 +3,8 @@ var upgradeWebSocket = (createEvents) => async (c, next) => {
3
3
  if (c.req.header("upgrade") !== "websocket") {
4
4
  return await next();
5
5
  }
6
- const { response, socket } = Deno.upgradeWebSocket(c.req.raw);
7
6
  const events = await createEvents(c);
7
+ const { response, socket } = Deno.upgradeWebSocket(c.req.raw);
8
8
  const wsContext = {
9
9
  binaryType: "arraybuffer",
10
10
  close: (code, reason) => socket.close(code, reason),
@@ -57,6 +57,7 @@ const upgradeWebSocket = (createEvents) => async (c, next) => {
57
57
  }
58
58
  server.accept?.();
59
59
  return new Response(null, {
60
+ status: 101,
60
61
  webSocket: client
61
62
  });
62
63
  };
@@ -26,13 +26,12 @@ const { open } = Deno;
26
26
  const serveStatic = (options) => {
27
27
  return async function serveStatic2(c, next) {
28
28
  const getContent = async (path) => {
29
- let file;
30
29
  try {
31
- file = await open(path);
30
+ const file = await open(path);
31
+ return file ? file.readable : null;
32
32
  } catch (e) {
33
33
  console.warn(`${e}`);
34
34
  }
35
- return file ? file.readable : null;
36
35
  };
37
36
  const pathResolve = (path) => {
38
37
  return `./${path}`;
@@ -25,8 +25,8 @@ const upgradeWebSocket = (createEvents) => async (c, next) => {
25
25
  if (c.req.header("upgrade") !== "websocket") {
26
26
  return await next();
27
27
  }
28
- const { response, socket } = Deno.upgradeWebSocket(c.req.raw);
29
28
  const events = await createEvents(c);
29
+ const { response, socket } = Deno.upgradeWebSocket(c.req.raw);
30
30
  const wsContext = {
31
31
  binaryType: "arraybuffer",
32
32
  close: (code, reason) => socket.close(code, reason),
@@ -142,25 +142,39 @@ class Hono {
142
142
  this.notFoundHandler = handler;
143
143
  return this;
144
144
  };
145
- mount(path, applicationHandler, optionHandler) {
146
- const mergedPath = (0, import_url.mergePath)(this._basePath, path);
147
- const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
148
- const handler = async (c, next) => {
145
+ mount(path, applicationHandler, options) {
146
+ let replaceRequest;
147
+ let optionHandler;
148
+ if (options) {
149
+ if (typeof options === "function") {
150
+ optionHandler = options;
151
+ } else {
152
+ optionHandler = options.optionHandler;
153
+ replaceRequest = options.replaceRequest;
154
+ }
155
+ }
156
+ const getOptions = optionHandler ? (c) => {
157
+ const options2 = optionHandler(c);
158
+ return Array.isArray(options2) ? options2 : [options2];
159
+ } : (c) => {
149
160
  let executionContext = void 0;
150
161
  try {
151
162
  executionContext = c.executionCtx;
152
163
  } catch {
153
164
  }
154
- const options = optionHandler ? optionHandler(c) : [c.env, executionContext];
155
- const optionsArray = Array.isArray(options) ? options : [options];
156
- const queryStrings = (0, import_url.getQueryStrings)(c.req.url);
157
- const res = await applicationHandler(
158
- new Request(
159
- new URL((c.req.path.slice(pathPrefixLength) || "/") + queryStrings, c.req.url),
160
- c.req.raw
161
- ),
162
- ...optionsArray
163
- );
165
+ return [c.env, executionContext];
166
+ };
167
+ replaceRequest ||= (() => {
168
+ const mergedPath = (0, import_url.mergePath)(this._basePath, path);
169
+ const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
170
+ return (request) => {
171
+ const url = new URL(request.url);
172
+ url.pathname = url.pathname.slice(pathPrefixLength) || "/";
173
+ return new Request(url, request);
174
+ };
175
+ })();
176
+ const handler = async (c, next) => {
177
+ const res = await applicationHandler(replaceRequest(c.req.raw), ...getOptions(c));
164
178
  if (res) {
165
179
  return res;
166
180
  }
package/dist/hono-base.js CHANGED
@@ -4,7 +4,7 @@ import { Context } from "./context.js";
4
4
  import { HTTPException } from "./http-exception.js";
5
5
  import { HonoRequest } from "./request.js";
6
6
  import { METHODS, METHOD_NAME_ALL, METHOD_NAME_ALL_LOWERCASE } from "./router.js";
7
- import { getPath, getPathNoStrict, getQueryStrings, mergePath } from "./utils/url.js";
7
+ import { getPath, getPathNoStrict, mergePath } from "./utils/url.js";
8
8
  var COMPOSED_HANDLER = Symbol("composedHandler");
9
9
  var notFoundHandler = (c) => {
10
10
  return c.text("404 Not Found", 404);
@@ -119,25 +119,39 @@ var Hono = class {
119
119
  this.notFoundHandler = handler;
120
120
  return this;
121
121
  };
122
- mount(path, applicationHandler, optionHandler) {
123
- const mergedPath = mergePath(this._basePath, path);
124
- const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
125
- const handler = async (c, next) => {
122
+ mount(path, applicationHandler, options) {
123
+ let replaceRequest;
124
+ let optionHandler;
125
+ if (options) {
126
+ if (typeof options === "function") {
127
+ optionHandler = options;
128
+ } else {
129
+ optionHandler = options.optionHandler;
130
+ replaceRequest = options.replaceRequest;
131
+ }
132
+ }
133
+ const getOptions = optionHandler ? (c) => {
134
+ const options2 = optionHandler(c);
135
+ return Array.isArray(options2) ? options2 : [options2];
136
+ } : (c) => {
126
137
  let executionContext = void 0;
127
138
  try {
128
139
  executionContext = c.executionCtx;
129
140
  } catch {
130
141
  }
131
- const options = optionHandler ? optionHandler(c) : [c.env, executionContext];
132
- const optionsArray = Array.isArray(options) ? options : [options];
133
- const queryStrings = getQueryStrings(c.req.url);
134
- const res = await applicationHandler(
135
- new Request(
136
- new URL((c.req.path.slice(pathPrefixLength) || "/") + queryStrings, c.req.url),
137
- c.req.raw
138
- ),
139
- ...optionsArray
140
- );
142
+ return [c.env, executionContext];
143
+ };
144
+ replaceRequest ||= (() => {
145
+ const mergedPath = mergePath(this._basePath, path);
146
+ const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
147
+ return (request) => {
148
+ const url = new URL(request.url);
149
+ url.pathname = url.pathname.slice(pathPrefixLength) || "/";
150
+ return new Request(url, request);
151
+ };
152
+ })();
153
+ const handler = async (c, next) => {
154
+ const res = await applicationHandler(replaceRequest(c.req.raw), ...getOptions(c));
141
155
  if (res) {
142
156
  return res;
143
157
  }
@@ -1,7 +1,6 @@
1
1
  import type { Hono } from '../../hono';
2
2
  import type { Env, Schema } from '../../types';
3
- import type { ALBRequestContext, ApiGatewayRequestContext, ApiGatewayRequestContextV2 } from './custom-context';
4
- import type { Handler, LambdaContext } from './types';
3
+ import type { ALBRequestContext, ApiGatewayRequestContext, ApiGatewayRequestContextV2, Handler, LambdaContext } from './types';
5
4
  export type LambdaEvent = APIGatewayProxyEvent | APIGatewayProxyEventV2 | ALBProxyEvent;
6
5
  export interface APIGatewayProxyEventV2 {
7
6
  version: string;
@@ -4,5 +4,4 @@
4
4
  */
5
5
  export { handle, streamHandle } from './handler';
6
6
  export type { APIGatewayProxyResult, LambdaEvent } from './handler';
7
- export type { ApiGatewayRequestContext, ApiGatewayRequestContextV2, ALBRequestContext, } from './custom-context';
8
- export type { LambdaContext } from './types';
7
+ export type { ApiGatewayRequestContext, ApiGatewayRequestContextV2, ALBRequestContext, LambdaContext, } from './types';
@@ -40,4 +40,86 @@ export interface LambdaContext {
40
40
  }
41
41
  type Callback<TResult = any> = (error?: Error | string | null, result?: TResult) => void;
42
42
  export type Handler<TEvent = any, TResult = any> = (event: TEvent, context: LambdaContext, callback: Callback<TResult>) => void | Promise<TResult>;
43
+ interface ClientCert {
44
+ clientCertPem: string;
45
+ subjectDN: string;
46
+ issuerDN: string;
47
+ serialNumber: string;
48
+ validity: {
49
+ notBefore: string;
50
+ notAfter: string;
51
+ };
52
+ }
53
+ interface Identity {
54
+ accessKey?: string;
55
+ accountId?: string;
56
+ caller?: string;
57
+ cognitoAuthenticationProvider?: string;
58
+ cognitoAuthenticationType?: string;
59
+ cognitoIdentityId?: string;
60
+ cognitoIdentityPoolId?: string;
61
+ principalOrgId?: string;
62
+ sourceIp: string;
63
+ user?: string;
64
+ userAgent: string;
65
+ userArn?: string;
66
+ clientCert?: ClientCert;
67
+ }
68
+ export interface ApiGatewayRequestContext {
69
+ accountId: string;
70
+ apiId: string;
71
+ authorizer: {
72
+ claims?: unknown;
73
+ scopes?: unknown;
74
+ };
75
+ domainName: string;
76
+ domainPrefix: string;
77
+ extendedRequestId: string;
78
+ httpMethod: string;
79
+ identity: Identity;
80
+ path: string;
81
+ protocol: string;
82
+ requestId: string;
83
+ requestTime: string;
84
+ requestTimeEpoch: number;
85
+ resourceId?: string;
86
+ resourcePath: string;
87
+ stage: string;
88
+ }
89
+ interface Authorizer {
90
+ iam?: {
91
+ accessKey: string;
92
+ accountId: string;
93
+ callerId: string;
94
+ cognitoIdentity: null;
95
+ principalOrgId: null;
96
+ userArn: string;
97
+ userId: string;
98
+ };
99
+ }
100
+ export interface ApiGatewayRequestContextV2 {
101
+ accountId: string;
102
+ apiId: string;
103
+ authentication: null;
104
+ authorizer: Authorizer;
105
+ domainName: string;
106
+ domainPrefix: string;
107
+ http: {
108
+ method: string;
109
+ path: string;
110
+ protocol: string;
111
+ sourceIp: string;
112
+ userAgent: string;
113
+ };
114
+ requestId: string;
115
+ routeKey: string;
116
+ stage: string;
117
+ time: string;
118
+ timeEpoch: number;
119
+ }
120
+ export interface ALBRequestContext {
121
+ elb: {
122
+ targetGroupArn: string;
123
+ };
124
+ }
43
125
  export {};
@@ -157,6 +157,9 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
157
157
  req: HonoRequest<P, I['out']>;
158
158
  /**
159
159
  * `.env` can get bindings (environment variables, secrets, KV namespaces, D1 database, R2 bucket etc.) in Cloudflare Workers.
160
+ *
161
+ * @see {@link https://hono.dev/api/context#env}
162
+ *
160
163
  * @example
161
164
  * ```ts
162
165
  * // Environment object for Cloudflare Workers
@@ -164,13 +167,15 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
164
167
  * const counter = c.env.COUNTER
165
168
  * })
166
169
  * ```
167
- * @see https://hono.dev/api/context#env
168
170
  */
169
171
  env: E['Bindings'];
170
172
  private _var;
171
173
  finalized: boolean;
172
174
  /**
173
175
  * `.error` can get the error object from the middleware if the Handler throws an error.
176
+ *
177
+ * @see {@link https://hono.dev/api/context#error}
178
+ *
174
179
  * @example
175
180
  * ```ts
176
181
  * app.use('*', async (c, next) => {
@@ -180,7 +185,6 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
180
185
  * }
181
186
  * })
182
187
  * ```
183
- * @see https://hono.dev/api/context#error
184
188
  */
185
189
  error: Error | undefined;
186
190
  private layout;
@@ -194,25 +198,22 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
194
198
  */
195
199
  constructor(req: HonoRequest<P, I['out']>, options?: ContextOptions<E>);
196
200
  /**
201
+ * @see {@link https://hono.dev/api/context#event}
197
202
  * The FetchEvent associated with the current request.
198
203
  *
199
204
  * @throws Will throw an error if the context does not have a FetchEvent.
200
- *
201
- * @see https://hono.dev/api/context#event
202
205
  */
203
206
  get event(): FetchEventLike;
204
207
  /**
208
+ * @see {@link https://hono.dev/api/context#executionctx}
205
209
  * The ExecutionContext associated with the current request.
206
210
  *
207
211
  * @throws Will throw an error if the context does not have an ExecutionContext.
208
- *
209
- * @see https://hono.dev/api/context#executionctx
210
212
  */
211
213
  get executionCtx(): ExecutionContext;
212
214
  /**
215
+ * @see {@link https://hono.dev/api/context#res}
213
216
  * The Response object for the current request.
214
- *
215
- * @see https://hono.dev/api/context#res
216
217
  */
217
218
  get res(): Response;
218
219
  /**
@@ -222,7 +223,9 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
222
223
  */
223
224
  set res(_res: Response | undefined);
224
225
  /**
225
- * Renders a response within a layout.
226
+ * `.render()` can create a response within a layout.
227
+ *
228
+ * @see {@link https://hono.dev/api/context#render-setrenderer}
226
229
  *
227
230
  * @example
228
231
  * ```ts
@@ -230,7 +233,6 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
230
233
  * return c.render('Hello!')
231
234
  * })
232
235
  * ```
233
- * @see https://hono.dev/api/context#render-setrenderer
234
236
  */
235
237
  render: Renderer;
236
238
  /**
@@ -254,6 +256,9 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
254
256
  }> | undefined;
255
257
  /**
256
258
  * `.setRenderer()` can set the layout in the custom middleware.
259
+ *
260
+ * @see {@link https://hono.dev/api/context#render-setrenderer}
261
+ *
257
262
  * @example
258
263
  * ```tsx
259
264
  * app.use('*', async (c, next) => {
@@ -269,11 +274,13 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
269
274
  * await next()
270
275
  * })
271
276
  * ```
272
- * @see https://hono.dev/api/context#render-setrenderer
273
277
  */
274
278
  setRenderer: (renderer: Renderer) => void;
275
279
  /**
276
280
  * `.header()` can set headers.
281
+ *
282
+ * @see {@link https://hono.dev/api/context#body}
283
+ *
277
284
  * @example
278
285
  * ```ts
279
286
  * app.get('/welcome', (c) => {
@@ -284,7 +291,6 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
284
291
  * return c.body('Thank you for coming')
285
292
  * })
286
293
  * ```
287
- * @see https://hono.dev/api/context#body
288
294
  */
289
295
  header: (name: string, value: string | undefined, options?: {
290
296
  append?: boolean;
@@ -292,6 +298,9 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
292
298
  status: (status: StatusCode) => void;
293
299
  /**
294
300
  * `.set()` can set the value specified by the key.
301
+ *
302
+ * @see {@link https://hono.dev/api/context#set-get}
303
+ *
295
304
  * @example
296
305
  * ```ts
297
306
  * app.use('*', async (c, next) => {
@@ -299,12 +308,14 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
299
308
  * await next()
300
309
  * })
301
310
  * ```
302
- * @see https://hono.dev/api/context#set-get
303
311
  ```
304
312
  */
305
313
  set: Set<E>;
306
314
  /**
307
315
  * `.get()` can use the value specified by the key.
316
+ *
317
+ * @see {@link https://hono.dev/api/context#set-get}
318
+ *
308
319
  * @example
309
320
  * ```ts
310
321
  * app.get('/', (c) => {
@@ -312,16 +323,17 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
312
323
  * return c.text(`The message is "${message}"`)
313
324
  * })
314
325
  * ```
315
- * @see https://hono.dev/api/context#set-get
316
326
  */
317
327
  get: Get<E>;
318
328
  /**
319
329
  * `.var` can access the value of a variable.
330
+ *
331
+ * @see {@link https://hono.dev/api/context#var}
332
+ *
320
333
  * @example
321
334
  * ```ts
322
335
  * const result = c.var.client.oneMethod()
323
336
  * ```
324
- * @see https://hono.dev/api/context#var
325
337
  */
326
338
  get var(): Readonly<ContextVariableMap & (IsAny<E['Variables']> extends true ? Record<string, any> : E['Variables'])>;
327
339
  newResponse: NewResponse;
@@ -329,6 +341,9 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
329
341
  * `.body()` can return the HTTP response.
330
342
  * You can set headers with `.header()` and set HTTP status code with `.status`.
331
343
  * This can also be set in `.text()`, `.json()` and so on.
344
+ *
345
+ * @see {@link https://hono.dev/api/context#body}
346
+ *
332
347
  * @example
333
348
  * ```ts
334
349
  * app.get('/welcome', (c) => {
@@ -342,34 +357,40 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
342
357
  * return c.body('Thank you for coming')
343
358
  * })
344
359
  * ```
345
- * @see https://hono.dev/api/context#body
346
360
  */
347
361
  body: BodyRespond;
348
362
  /**
349
363
  * `.text()` can render text as `Content-Type:text/plain`.
364
+ *
365
+ * @see {@link https://hono.dev/api/context#text}
366
+ *
350
367
  * @example
351
368
  * ```ts
352
369
  * app.get('/say', (c) => {
353
370
  * return c.text('Hello!')
354
371
  * })
355
372
  * ```
356
- * @see https://hono.dev/api/context#text
357
373
  */
358
374
  text: TextRespond;
359
375
  /**
360
376
  * `.json()` can render JSON as `Content-Type:application/json`.
377
+ *
378
+ * @see {@link https://hono.dev/api/context#json}
379
+ *
361
380
  * @example
362
381
  * ```ts
363
382
  * app.get('/api', (c) => {
364
383
  * return c.json({ message: 'Hello!' })
365
384
  * })
366
385
  * ```
367
- * @see https://hono.dev/api/context#json
368
386
  */
369
387
  json: JSONRespond;
370
388
  html: HTMLRespond;
371
389
  /**
372
390
  * `.redirect()` can Redirect, default status code is 302.
391
+ *
392
+ * @see {@link https://hono.dev/api/context#redirect}
393
+ *
373
394
  * @example
374
395
  * ```ts
375
396
  * app.get('/redirect', (c) => {
@@ -379,18 +400,19 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
379
400
  * return c.redirect('/', 301)
380
401
  * })
381
402
  * ```
382
- * @see https://hono.dev/api/context#redirect
383
403
  */
384
404
  redirect: (location: string, status?: RedirectStatusCode) => Response;
385
405
  /**
386
406
  * `.notFound()` can return the Not Found Response.
407
+ *
408
+ * @see {@link https://hono.dev/api/context#notfound}
409
+ *
387
410
  * @example
388
411
  * ```ts
389
412
  * app.get('/notfound', (c) => {
390
413
  * return c.notFound()
391
414
  * })
392
415
  * ```
393
- * @see https://hono.dev/api/context#notfound
394
416
  */
395
417
  notFound: () => Response | Promise<Response>;
396
418
  }
@@ -16,20 +16,28 @@ type GetPath<E extends Env> = (request: Request, options?: {
16
16
  export type HonoOptions<E extends Env> = {
17
17
  /**
18
18
  * `strict` option specifies whether to distinguish whether the last path is a directory or not.
19
+ *
20
+ * @see {@link https://hono.dev/api/hono#strict-mode}
21
+ *
19
22
  * @default true
20
- * @see https://hono.dev/api/hono#strict-mode
21
23
  */
22
24
  strict?: boolean;
23
25
  /**
24
26
  * `router` option specifices which router to use.
27
+ *
28
+ * @see {@link https://hono.dev/api/hono#router-option}
29
+ *
30
+ * @example
25
31
  * ```ts
26
32
  * const app = new Hono({ router: new RegExpRouter() })
27
33
  * ```
28
- * @see https://hono.dev/api/hono#router-option
29
34
  */
30
35
  router?: Router<[H, RouterRoute]>;
31
36
  /**
32
37
  * `getPath` can handle the host header value.
38
+ *
39
+ * @see {@link https://hono.dev/api/routing#routing-with-host-header-value}
40
+ *
33
41
  * @example
34
42
  * ```ts
35
43
  * const app = new Hono({
@@ -44,10 +52,15 @@ export type HonoOptions<E extends Env> = {
44
52
  * // headers: { host: 'www1.example.com' },
45
53
  * // })
46
54
  * ```
47
- * @see https://hono.dev/api/routing#routing-with-host-header-value
48
55
  */
49
56
  getPath?: GetPath<E>;
50
57
  };
58
+ type MountOptionHandler = (c: Context) => unknown;
59
+ type MountReplaceRequest = (originalRequest: Request) => Request;
60
+ type MountOptions = MountOptionHandler | {
61
+ optionHandler?: MountOptionHandler;
62
+ replaceRequest?: MountReplaceRequest;
63
+ };
51
64
  declare class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'> {
52
65
  #private;
53
66
  get: HandlerInterface<E, 'get', S, BasePath>;
@@ -67,18 +80,48 @@ declare class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends
67
80
  private clone;
68
81
  private notFoundHandler;
69
82
  private errorHandler;
83
+ /**
84
+ * `.route()` allows grouping other Hono instance in routes.
85
+ *
86
+ * @see {@link https://hono.dev/api/routing#grouping}
87
+ *
88
+ * @param {string} path - base Path
89
+ * @param {Hono} app - other Hono instance
90
+ * @returns {Hono} routed Hono instnace
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * const app = new Hono()
95
+ * const app2 = new Hono()
96
+ *
97
+ * app2.get("/user", (c) => c.text("user"))
98
+ * app.route("/api", app2) // GET /api/user
99
+ * ```
100
+ */
70
101
  route<SubPath extends string, SubEnv extends Env, SubSchema extends Schema, SubBasePath extends string>(path: SubPath, app?: Hono<SubEnv, SubSchema, SubBasePath>): Hono<E, MergeSchemaPath<SubSchema, MergePath<BasePath, SubPath>> & S, BasePath>;
71
102
  /**
72
103
  * `.basePath()` allows base paths to be specified.
104
+ *
105
+ * @see {@link https://hono.dev/api/routing#base-path}
106
+ *
107
+ * @param {string} path - base Path
108
+ * @returns {Hono} changed Hono instance
109
+ *
73
110
  * @example
74
111
  * ```ts
75
112
  * const api = new Hono().basePath('/api')
76
113
  * ```
77
- * @see https://hono.dev/api/routing#base-path
78
114
  */
79
115
  basePath<SubPath extends string>(path: SubPath): Hono<E, S, MergePath<BasePath, SubPath>>;
80
116
  /**
81
117
  * `.onError()` handles an error and returns a customized Response.
118
+ *
119
+ * @see {@link https://hono.dev/api/hono#error-handling}
120
+ *
121
+ * @param {ErrorHandler} handler - request Handler for error
122
+ * @returns {Hono} changed Hono instance
123
+ *
124
+ * @example
82
125
  * ```ts
83
126
  * app.onError((err, c) => {
84
127
  * console.error(`${err}`)
@@ -89,39 +132,67 @@ declare class Hono<E extends Env = Env, S extends Schema = {}, BasePath extends
89
132
  onError: (handler: ErrorHandler<E>) => Hono<E, S, BasePath>;
90
133
  /**
91
134
  * `.notFound()` allows you to customize a Not Found Response.
135
+ *
136
+ * @see {@link https://hono.dev/api/hono#not-found}
137
+ *
138
+ * @param {NotFoundHandler} handler - request handler for not-found
139
+ * @returns {Hono} changed Hono instance
140
+ *
141
+ * @example
92
142
  * ```ts
93
143
  * app.notFound((c) => {
94
144
  * return c.text('Custom 404 Message', 404)
95
145
  * })
96
146
  * ```
97
- * @see https://hono.dev/api/hono#not-found
98
147
  */
99
148
  notFound: (handler: NotFoundHandler<E>) => Hono<E, S, BasePath>;
100
149
  /**
101
- * Mounts an external application handler to the specified path.
150
+ * `.mount()` allows you to mount applications built with other frameworks into your Hono application.
102
151
  *
103
- * @param path - The path where the external application handler should be mounted.
104
- * @param applicationHandler - The external application handler function that processes requests.
105
- * @param optionHandler - Optional function to handle additional options, such as environment variables and execution context.
152
+ * @see {@link https://hono.dev/api/hono#mount}
106
153
  *
107
- * @returns The current instance of Hono for chaining.
154
+ * @param {string} path - base Path
155
+ * @param {Function} applicationHandler - other Request Handler
156
+ * @param {MountOptions} [options] - options of `.mount()`
157
+ * @returns {Hono} mounted Hono instance
108
158
  *
109
159
  * @example
110
160
  * ```ts
161
+ * import { Router as IttyRouter } from 'itty-router'
162
+ * import { Hono } from 'hono'
163
+ * // Create itty-router application
164
+ * const ittyRouter = IttyRouter()
165
+ * // GET /itty-router/hello
166
+ * ittyRouter.get('/hello', () => new Response('Hello from itty-router'))
167
+ *
111
168
  * const app = new Hono()
112
- * const externalAppHandler = () => new Response('External App')
113
- * app.mount('/external', externalAppHandler)
169
+ * app.mount('/itty-router', ittyRouter.handle)
170
+ * ```
171
+ *
172
+ * @example
173
+ * ```ts
174
+ * const app = new Hono()
175
+ * // Send the request to another application without modification.
176
+ * app.mount('/app', anotherApp, {
177
+ * replaceRequest: (req) => req,
178
+ * })
114
179
  * ```
115
- * @see https://hono.dev/api/hono#mount
116
180
  */
117
- mount(path: string, applicationHandler: (request: Request, ...args: any) => Response | Promise<Response>, optionHandler?: (c: Context) => unknown): Hono<E, S, BasePath>;
181
+ mount(path: string, applicationHandler: (request: Request, ...args: any) => Response | Promise<Response>, options?: MountOptions): Hono<E, S, BasePath>;
118
182
  private addRoute;
119
183
  private matchRoute;
120
184
  private handleError;
121
185
  private dispatch;
122
186
  /**
123
187
  * `.fetch()` will be entry point of your app.
124
- * @see https://hono.dev/api/hono#fetch
188
+ *
189
+ * @see {@link https://hono.dev/api/hono#fetch}
190
+ *
191
+ * @param {Request} request - reuqest Object of request
192
+ * @param {Env} Env - env Object
193
+ * @param {ExecutionContext} - context of execution
194
+ * @returns {Response | Promise<Response>} response of request
195
+ *
125
196
  */
126
197
  fetch: (request: Request, Env?: E['Bindings'] | {}, executionCtx?: ExecutionContext) => Response | Promise<Response>;
127
198
  /**
@@ -16,6 +16,15 @@ type HTTPExceptionOptions = {
16
16
  };
17
17
  /**
18
18
  * `HTTPException` must be used when a fatal error such as authentication failure occurs.
19
+ *
20
+ * @see {@link https://hono.dev/api/exception}
21
+ *
22
+ * @param {StatusCode} status - status code of HTTPException
23
+ * @param {HTTPExceptionOptions} options - options of HTTPException
24
+ * @param {HTTPExceptionOptions["res"]} options.res - response of options of HTTPException
25
+ * @param {HTTPExceptionOptions["message"]} options.message - message of options of HTTPException
26
+ * @param {HTTPExceptionOptions["cause"]} options.cause - cause of options of HTTPException
27
+ *
19
28
  * @example
20
29
  * ```ts
21
30
  * import { HTTPException } from 'hono/http-exception'
@@ -30,7 +39,6 @@ type HTTPExceptionOptions = {
30
39
  * await next()
31
40
  * })
32
41
  * ```
33
- * @see https://hono.dev/api/exception
34
42
  */
35
43
  export declare class HTTPException extends Error {
36
44
  readonly res?: Response;
@@ -16,6 +16,9 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
16
16
  #private;
17
17
  /**
18
18
  * `.raw` can get the raw Request object.
19
+ *
20
+ * @see {@link https://hono.dev/api/request#raw}
21
+ *
19
22
  * @example
20
23
  * ```ts
21
24
  * // For Cloudflare Workers
@@ -24,32 +27,35 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
24
27
  * ...
25
28
  * })
26
29
  * ```
27
- * @see https://hono.dev/api/request#raw
28
30
  */
29
31
  raw: Request;
30
32
  routeIndex: number;
31
33
  /**
32
34
  * `.path` can get the pathname of the request.
35
+ *
36
+ * @see {@link https://hono.dev/api/request#path}
37
+ *
33
38
  * @example
34
39
  * ```ts
35
40
  * app.get('/about/me', (c) => {
36
41
  * const pathname = c.req.path // `/about/me`
37
42
  * })
38
43
  * ```
39
- * @see https://hono.dev/api/request#path
40
44
  */
41
45
  path: string;
42
46
  bodyCache: BodyCache;
43
47
  constructor(request: Request, path?: string, matchResult?: Result<[unknown, RouterRoute]>);
44
48
  /**
45
49
  * `.req.param()` gets the path parameters.
50
+ *
51
+ * @see {@link https://hono.dev/api/routing#path-parameter}
52
+ *
46
53
  * @example
47
54
  * ```ts
48
55
  * const name = c.req.param('name')
49
56
  * // or all parameters at once
50
57
  * const { id, comment_id } = c.req.param()
51
58
  * ```
52
- * @see https://hono.dev/api/routing#path-parameter
53
59
  */
54
60
  param<P2 extends ParamKeys<P> = ParamKeys<P>>(key: P2 extends `${infer _}?` ? never : P2): string;
55
61
  param<P2 extends RemoveQuestion<ParamKeys<P>> = RemoveQuestion<ParamKeys<P>>>(key: P2): string | undefined;
@@ -60,6 +66,9 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
60
66
  private getParamValue;
61
67
  /**
62
68
  * `.query()` can get querystring parameters.
69
+ *
70
+ * @see {@link https://hono.dev/api/request#query}
71
+ *
63
72
  * @example
64
73
  * ```ts
65
74
  * // Query params
@@ -72,12 +81,14 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
72
81
  * const { q, limit, offset } = c.req.query()
73
82
  * })
74
83
  * ```
75
- * @see https://hono.dev/api/request#query
76
84
  */
77
85
  query(key: string): string | undefined;
78
86
  query(): Record<string, string>;
79
87
  /**
80
88
  * `.queries()` can get multiple querystring parameter values, e.g. /search?tags=A&tags=B
89
+ *
90
+ * @see {@link https://hono.dev/api/request#queries}
91
+ *
81
92
  * @example
82
93
  * ```ts
83
94
  * app.get('/search', (c) => {
@@ -85,66 +96,75 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
85
96
  * const tags = c.req.queries('tags')
86
97
  * })
87
98
  * ```
88
- * @see https://hono.dev/api/request#queries
89
99
  */
90
100
  queries(key: string): string[] | undefined;
91
101
  queries(): Record<string, string[]>;
92
102
  /**
93
103
  * `.header()` can get the request header value.
104
+ *
105
+ * @see {@link https://hono.dev/api/request#header}
106
+ *
94
107
  * @example
95
108
  * ```ts
96
109
  * app.get('/', (c) => {
97
110
  * const userAgent = c.req.header('User-Agent')
98
111
  * })
99
112
  * ```
100
- * @see https://hono.dev/api/request#header
101
113
  */
102
114
  header(name: string): string | undefined;
103
115
  header(): Record<string, string>;
104
116
  /**
105
117
  * `.parseBody()` can parse Request body of type `multipart/form-data` or `application/x-www-form-urlencoded`
118
+ *
119
+ * @see {@link https://hono.dev/api/request#parsebody}
120
+ *
106
121
  * @example
107
122
  * ```ts
108
123
  * app.post('/entry', async (c) => {
109
124
  * const body = await c.req.parseBody()
110
125
  * })
111
126
  * ```
112
- * @see https://hono.dev/api/request#parsebody
113
127
  */
114
128
  parseBody<Options extends Partial<ParseBodyOptions>, T extends BodyData<Options>>(options?: Options): Promise<T>;
115
129
  parseBody<T extends BodyData>(options?: Partial<ParseBodyOptions>): Promise<T>;
116
130
  private cachedBody;
117
131
  /**
118
132
  * `.json()` can parse Request body of type `application/json`
133
+ *
134
+ * @see {@link https://hono.dev/api/request#json}
135
+ *
119
136
  * @example
120
137
  * ```ts
121
138
  * app.post('/entry', async (c) => {
122
139
  * const body = await c.req.json()
123
140
  * })
124
141
  * ```
125
- * @see https://hono.dev/api/request#json
126
142
  */
127
143
  json<T = any>(): Promise<T>;
128
144
  /**
129
145
  * `.text()` can parse Request body of type `text/plain`
146
+ *
147
+ * @see {@link https://hono.dev/api/request#text}
148
+ *
130
149
  * @example
131
150
  * ```ts
132
151
  * app.post('/entry', async (c) => {
133
152
  * const body = await c.req.text()
134
153
  * })
135
154
  * ```
136
- * @see https://hono.dev/api/request#text
137
155
  */
138
156
  text(): Promise<string>;
139
157
  /**
140
158
  * `.arrayBuffer()` parse Request body as an `ArrayBuffer`
159
+ *
160
+ * @see {@link https://hono.dev/api/request#arraybuffer}
161
+ *
141
162
  * @example
142
163
  * ```ts
143
164
  * app.post('/entry', async (c) => {
144
165
  * const body = await c.req.arrayBuffer()
145
166
  * })
146
167
  * ```
147
- * @see https://hono.dev/api/request#arraybuffer
148
168
  */
149
169
  arrayBuffer(): Promise<ArrayBuffer>;
150
170
  /**
@@ -187,6 +207,9 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
187
207
  valid<T extends keyof I & keyof ValidationTargets>(target: T): InputToDataByTarget<I, T>;
188
208
  /**
189
209
  * `.url()` can get the request url strings.
210
+ *
211
+ * @see {@link https://hono.dev/api/request#url}
212
+ *
190
213
  * @example
191
214
  * ```ts
192
215
  * app.get('/about/me', (c) => {
@@ -194,22 +217,26 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
194
217
  * ...
195
218
  * })
196
219
  * ```
197
- * @see https://hono.dev/api/request#url
198
220
  */
199
221
  get url(): string;
200
222
  /**
201
223
  * `.method()` can get the method name of the request.
224
+ *
225
+ * @see {@link https://hono.dev/api/request#method}
226
+ *
202
227
  * @example
203
228
  * ```ts
204
229
  * app.get('/about/me', (c) => {
205
230
  * const method = c.req.method // `GET`
206
231
  * })
207
232
  * ```
208
- * @see https://hono.dev/api/request#method
209
233
  */
210
234
  get method(): string;
211
235
  /**
212
236
  * `.matchedRoutes()` can return a matched route in the handler
237
+ *
238
+ * @see {@link https://hono.dev/api/request#matchedroutes}
239
+ *
213
240
  * @example
214
241
  * ```ts
215
242
  * app.use('*', async function logger(c, next) {
@@ -227,18 +254,19 @@ export declare class HonoRequest<P extends string = '/', I extends Input['out']
227
254
  * })
228
255
  * })
229
256
  * ```
230
- * @see https://hono.dev/api/request#matchedroutes
231
257
  */
232
258
  get matchedRoutes(): RouterRoute[];
233
259
  /**
234
260
  * `routePath()` can retrieve the path registered within the handler
261
+ *
262
+ * @see {@link https://hono.dev/api/request#routepath}
263
+ *
235
264
  * @example
236
265
  * ```ts
237
266
  * app.get('/posts/:id', (c) => {
238
267
  * return c.json({ path: c.req.routePath })
239
268
  * })
240
269
  * ```
241
- * @see https://hono.dev/api/request#routepath
242
270
  */
243
271
  get routePath(): string;
244
272
  }
@@ -9,17 +9,22 @@ export type RedirectStatusCode = 300 | 301 | 302 | 303 | 304 | DeprecatedStatusC
9
9
  export type ClientErrorStatusCode = 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451;
10
10
  export type ServerErrorStatusCode = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511;
11
11
  /**
12
- * `UnOfficalStatusCode` can be used to specify an informal status code.
12
+ * `UnofficialStatusCode` can be used to specify an unofficial status code.
13
13
  * @example
14
14
  *
15
15
  * ```ts
16
- * app.get('/', (c) => {
17
- * return c.text("hono is cool", 666 as UnOfficalStatusCode)
16
+ * app.get('/unknown', (c) => {
17
+ * return c.text("Unknown Error", 520 as UnofficialStatusCode)
18
18
  * })
19
19
  * ```
20
20
  */
21
+ export type UnofficialStatusCode = -1;
22
+ /**
23
+ * @deprecated
24
+ * Use `UnofficialStatusCode` instead.
25
+ */
21
26
  export type UnOfficalStatusCode = -1;
22
27
  /**
23
- * If you want to use an unofficial status, use `UnOfficalStatusCode`.
28
+ * If you want to use an unofficial status, use `UnofficialStatusCode`.
24
29
  */
25
- export type StatusCode = InfoStatusCode | SuccessStatusCode | RedirectStatusCode | ClientErrorStatusCode | ServerErrorStatusCode | UnOfficalStatusCode;
30
+ export type StatusCode = InfoStatusCode | SuccessStatusCode | RedirectStatusCode | ClientErrorStatusCode | ServerErrorStatusCode | UnofficialStatusCode | UnOfficalStatusCode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "4.4.2",
3
+ "version": "4.4.3",
4
4
  "description": "Ultrafast web framework for the Edges",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",
@@ -16,10 +16,10 @@
16
16
  "test:bun": "bun test --jsx-import-source ../../src/jsx runtime_tests/bun/index.test.tsx",
17
17
  "test:fastly": "vitest --run --config ./runtime_tests/fastly/vitest.config.ts",
18
18
  "test:node": "vitest --run --config ./runtime_tests/node/vitest.config.ts",
19
- "test:wrangler": "vitest --run --config ./runtime_tests/wrangler/vitest.config.ts",
19
+ "test:workerd": "vitest --run --config ./runtime_tests/workerd/vitest.config.ts",
20
20
  "test:lambda": "vitest --run --config ./runtime_tests/lambda/vitest.config.ts",
21
21
  "test:lambda-edge": "vitest --run --config ./runtime_tests/lambda-edge/vitest.config.ts",
22
- "test:all": "bun run test && bun test:deno && bun test:bun && bun test:fastly && bun test:node && bun test:wrangler && bun test:lambda && bun test:lambda-edge",
22
+ "test:all": "bun run test && bun test:deno && bun test:bun && bun test:fastly && bun test:node && bun test:workerd && bun test:lambda && bun test:lambda-edge",
23
23
  "lint": "eslint --ext js,ts,tsx src runtime_tests",
24
24
  "lint:fix": "eslint --ext js,ts,tsx src runtime_tests --fix",
25
25
  "format": "prettier --check --cache \"src/**/*.{js,ts,tsx}\" \"runtime_tests/**/*.{js,ts,tsx}\"",
@@ -593,7 +593,8 @@
593
593
  "typescript": "^5.3.3",
594
594
  "vite-plugin-fastly-js-compute": "^0.4.2",
595
595
  "vitest": "^1.2.2",
596
- "wrangler": "3.17.1",
596
+ "wrangler": "^3.58.0",
597
+ "ws": "^8.17.0",
597
598
  "zod": "^3.20.2"
598
599
  },
599
600
  "engines": {
File without changes
@@ -1,16 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __copyProps = (to, from, except, desc) => {
7
- if (from && typeof from === "object" || typeof from === "function") {
8
- for (let key of __getOwnPropNames(from))
9
- if (!__hasOwnProp.call(to, key) && key !== except)
10
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
- }
12
- return to;
13
- };
14
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
- var custom_context_exports = {};
16
- module.exports = __toCommonJS(custom_context_exports);
@@ -1,83 +0,0 @@
1
- interface ClientCert {
2
- clientCertPem: string;
3
- subjectDN: string;
4
- issuerDN: string;
5
- serialNumber: string;
6
- validity: {
7
- notBefore: string;
8
- notAfter: string;
9
- };
10
- }
11
- interface Identity {
12
- accessKey?: string;
13
- accountId?: string;
14
- caller?: string;
15
- cognitoAuthenticationProvider?: string;
16
- cognitoAuthenticationType?: string;
17
- cognitoIdentityId?: string;
18
- cognitoIdentityPoolId?: string;
19
- principalOrgId?: string;
20
- sourceIp: string;
21
- user?: string;
22
- userAgent: string;
23
- userArn?: string;
24
- clientCert?: ClientCert;
25
- }
26
- export interface ApiGatewayRequestContext {
27
- accountId: string;
28
- apiId: string;
29
- authorizer: {
30
- claims?: unknown;
31
- scopes?: unknown;
32
- };
33
- domainName: string;
34
- domainPrefix: string;
35
- extendedRequestId: string;
36
- httpMethod: string;
37
- identity: Identity;
38
- path: string;
39
- protocol: string;
40
- requestId: string;
41
- requestTime: string;
42
- requestTimeEpoch: number;
43
- resourceId?: string;
44
- resourcePath: string;
45
- stage: string;
46
- }
47
- interface Authorizer {
48
- iam?: {
49
- accessKey: string;
50
- accountId: string;
51
- callerId: string;
52
- cognitoIdentity: null;
53
- principalOrgId: null;
54
- userArn: string;
55
- userId: string;
56
- };
57
- }
58
- export interface ApiGatewayRequestContextV2 {
59
- accountId: string;
60
- apiId: string;
61
- authentication: null;
62
- authorizer: Authorizer;
63
- domainName: string;
64
- domainPrefix: string;
65
- http: {
66
- method: string;
67
- path: string;
68
- protocol: string;
69
- sourceIp: string;
70
- userAgent: string;
71
- };
72
- requestId: string;
73
- routeKey: string;
74
- stage: string;
75
- time: string;
76
- timeEpoch: number;
77
- }
78
- export interface ALBRequestContext {
79
- elb: {
80
- targetGroupArn: string;
81
- };
82
- }
83
- export {};