hono 3.0.2 → 3.0.4

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
@@ -49,7 +49,7 @@ npm create hono@latest my-app
49
49
  - **Ultrafast** - The routers are really fast and smart. Not using linear loops. Fast.
50
50
  - **Multi-runtime** - Works on Cloudflare Workers, Fastly Compute@Edge, Deno, Bun, Lagon, or Node.js. The same code runs on all platforms.
51
51
  - **Batteries Included** - Hono has built-in middleware, custom middleware, and third-party middleware. Batteries included.
52
- - **Fine DX** - First-class TypeScript support. Now, we've got "Types".
52
+ - **Delightful DX** - First-class TypeScript support. Now, we've got "Types".
53
53
  - **Small** - About 20kB. Zero-dependencies. Using only Web Standard API.
54
54
 
55
55
  ## Benchmarks
@@ -97,6 +97,8 @@ Thanks to [all contributors](https://github.com/honojs/hono/graphs/contributors)
97
97
 
98
98
  Yusuke Wada <https://github.com/yusukebe>
99
99
 
100
+ "RegExpRouter" and "SmartRouter" are created by Taku Amano <https://github.com/usualoma>
101
+
100
102
  ## License
101
103
 
102
104
  Distributed under the MIT License. See [LICENSE](LICENSE) for more information.
@@ -1,7 +1,10 @@
1
1
  // src/adapter/cloudflare-pages/handler.ts
2
2
  import { Hono } from "../../hono.js";
3
- var handle = (subApp, path = "/") => ({ request, env, waitUntil }) => new Hono().route(path, subApp).fetch(request, env, { waitUntil, passThroughOnException: () => {
4
- } });
3
+ var handle = (subApp, path) => ({ request, env, waitUntil }) => {
4
+ const app = path ? new Hono().route(path, subApp) : subApp;
5
+ return app.fetch(request, env, { waitUntil, passThroughOnException: () => {
6
+ } });
7
+ };
5
8
  export {
6
9
  handle
7
10
  };
@@ -1,6 +1,9 @@
1
1
  // src/adapter/nextjs/handler.ts
2
2
  import { Hono } from "../../hono.js";
3
- var handle = (subApp, path = "/") => async (req) => new Hono().route(path, subApp).fetch(req);
3
+ var handle = (subApp, path) => (req) => {
4
+ const app = path ? new Hono().route(path, subApp) : subApp;
5
+ return app.fetch(req);
6
+ };
4
7
  export {
5
8
  handle
6
9
  };
@@ -22,8 +22,11 @@ __export(handler_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(handler_exports);
24
24
  var import_hono = require("../../hono");
25
- const handle = (subApp, path = "/") => ({ request, env, waitUntil }) => new import_hono.Hono().route(path, subApp).fetch(request, env, { waitUntil, passThroughOnException: () => {
26
- } });
25
+ const handle = (subApp, path) => ({ request, env, waitUntil }) => {
26
+ const app = path ? new import_hono.Hono().route(path, subApp) : subApp;
27
+ return app.fetch(request, env, { waitUntil, passThroughOnException: () => {
28
+ } });
29
+ };
27
30
  // Annotate the CommonJS export names for ESM import in node:
28
31
  0 && (module.exports = {
29
32
  handle
@@ -22,7 +22,10 @@ __export(handler_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(handler_exports);
24
24
  var import_hono = require("../../hono");
25
- const handle = (subApp, path = "/") => async (req) => new import_hono.Hono().route(path, subApp).fetch(req);
25
+ const handle = (subApp, path) => (req) => {
26
+ const app = path ? new import_hono.Hono().route(path, subApp) : subApp;
27
+ return app.fetch(req);
28
+ };
26
29
  // Annotate the CommonJS export names for ESM import in node:
27
30
  0 && (module.exports = {
28
31
  handle
package/dist/cjs/hono.js CHANGED
@@ -51,7 +51,7 @@ class Hono extends defineDynamicClass() {
51
51
  routers: [new import_reg_exp_router.RegExpRouter(), new import_trie_router.TrieRouter()]
52
52
  });
53
53
  this.strict = true;
54
- this._tempPath = "";
54
+ this.basePath = "";
55
55
  this.path = "*";
56
56
  this.routes = [];
57
57
  this.notFoundHandler = notFoundHandler;
@@ -64,8 +64,12 @@ class Hono extends defineDynamicClass() {
64
64
  };
65
65
  this.request = async (input, requestInit) => {
66
66
  if (input instanceof Request) {
67
+ if (requestInit !== void 0) {
68
+ input = new Request(input, requestInit);
69
+ }
67
70
  return await this.fetch(input);
68
71
  }
72
+ input = input.toString();
69
73
  const path = /^https?:\/\//.test(input) ? input : `http://localhost${(0, import_url.mergePath)("/", input)}`;
70
74
  const req = new Request(path, requestInit);
71
75
  return await this.fetch(req);
@@ -110,16 +114,24 @@ class Hono extends defineDynamicClass() {
110
114
  };
111
115
  Object.assign(this, init);
112
116
  }
117
+ clone() {
118
+ const clone = new Hono({
119
+ router: this.router,
120
+ strict: this.strict
121
+ });
122
+ clone.routes = this.routes;
123
+ return clone;
124
+ }
113
125
  route(path, app) {
114
- this._tempPath = path;
126
+ const subApp = this.clone();
127
+ subApp.basePath = (0, import_url.mergePath)(this.basePath, path);
115
128
  if (app) {
116
129
  app.routes.map((r) => {
117
130
  const handler = app.errorHandler === errorHandler ? r.handler : async (c, next) => (await (0, import_compose.compose)([r.handler], app.errorHandler)(c, next)).res;
118
- this.addRoute(r.method, r.path, handler);
131
+ subApp.addRoute(r.method, r.path, handler);
119
132
  });
120
- this._tempPath = "";
121
133
  }
122
- return this;
134
+ return subApp;
123
135
  }
124
136
  onError(handler) {
125
137
  this.errorHandler = handler;
@@ -139,8 +151,8 @@ class Hono extends defineDynamicClass() {
139
151
  }
140
152
  addRoute(method, path, handler) {
141
153
  method = method.toUpperCase();
142
- if (this._tempPath) {
143
- path = (0, import_url.mergePath)(this._tempPath, path);
154
+ if (this.basePath) {
155
+ path = (0, import_url.mergePath)(this.basePath, path);
144
156
  }
145
157
  this.router.add(method, path, handler);
146
158
  const r = { path, method, handler };
@@ -34,7 +34,10 @@ const etag = (options = { weak: false }) => {
34
34
  await clone.blob();
35
35
  c.res = new Response(null, {
36
36
  status: 304,
37
- statusText: "Not Modified"
37
+ statusText: "Not Modified",
38
+ headers: {
39
+ ETag: etag2
40
+ }
38
41
  });
39
42
  c.res.headers.delete("Content-Length");
40
43
  } else {
package/dist/hono.js CHANGED
@@ -29,7 +29,7 @@ var Hono = class extends defineDynamicClass() {
29
29
  routers: [new RegExpRouter(), new TrieRouter()]
30
30
  });
31
31
  this.strict = true;
32
- this._tempPath = "";
32
+ this.basePath = "";
33
33
  this.path = "*";
34
34
  this.routes = [];
35
35
  this.notFoundHandler = notFoundHandler;
@@ -42,8 +42,12 @@ var Hono = class extends defineDynamicClass() {
42
42
  };
43
43
  this.request = async (input, requestInit) => {
44
44
  if (input instanceof Request) {
45
+ if (requestInit !== void 0) {
46
+ input = new Request(input, requestInit);
47
+ }
45
48
  return await this.fetch(input);
46
49
  }
50
+ input = input.toString();
47
51
  const path = /^https?:\/\//.test(input) ? input : `http://localhost${mergePath("/", input)}`;
48
52
  const req = new Request(path, requestInit);
49
53
  return await this.fetch(req);
@@ -88,16 +92,24 @@ var Hono = class extends defineDynamicClass() {
88
92
  };
89
93
  Object.assign(this, init);
90
94
  }
95
+ clone() {
96
+ const clone = new Hono({
97
+ router: this.router,
98
+ strict: this.strict
99
+ });
100
+ clone.routes = this.routes;
101
+ return clone;
102
+ }
91
103
  route(path, app) {
92
- this._tempPath = path;
104
+ const subApp = this.clone();
105
+ subApp.basePath = mergePath(this.basePath, path);
93
106
  if (app) {
94
107
  app.routes.map((r) => {
95
108
  const handler = app.errorHandler === errorHandler ? r.handler : async (c, next) => (await compose([r.handler], app.errorHandler)(c, next)).res;
96
- this.addRoute(r.method, r.path, handler);
109
+ subApp.addRoute(r.method, r.path, handler);
97
110
  });
98
- this._tempPath = "";
99
111
  }
100
- return this;
112
+ return subApp;
101
113
  }
102
114
  onError(handler) {
103
115
  this.errorHandler = handler;
@@ -117,8 +129,8 @@ var Hono = class extends defineDynamicClass() {
117
129
  }
118
130
  addRoute(method, path, handler) {
119
131
  method = method.toUpperCase();
120
- if (this._tempPath) {
121
- path = mergePath(this._tempPath, path);
132
+ if (this.basePath) {
133
+ path = mergePath(this.basePath, path);
122
134
  }
123
135
  this.router.add(method, path, handler);
124
136
  const r = { path, method, handler };
@@ -12,7 +12,10 @@ var etag = (options = { weak: false }) => {
12
12
  await clone.blob();
13
13
  c.res = new Response(null, {
14
14
  status: 304,
15
- statusText: "Not Modified"
15
+ statusText: "Not Modified",
16
+ headers: {
17
+ ETag: etag2
18
+ }
16
19
  });
17
20
  c.res.headers.delete("Content-Length");
18
21
  } else {
@@ -1,7 +1,7 @@
1
1
  import { Hono } from '../../hono';
2
2
  import type { Env } from '../../types';
3
3
  interface HandleInterface {
4
- <E extends Env>(subApp: Hono<E>, path?: string): (req: Request) => Promise<Response>;
4
+ <E extends Env>(subApp: Hono<E>, path?: string): (req: Request) => Response | Promise<Response>;
5
5
  }
6
6
  export declare const handle: HandleInterface;
7
7
  export {};
@@ -1,4 +1,4 @@
1
1
  import type { Hono } from '../hono';
2
2
  import type { UnionToIntersection } from '../utils/types';
3
3
  import type { Client, RequestOptions } from './types';
4
- export declare const hc: <T extends Hono<any, {}>>(baseUrl: string, options?: RequestOptions) => UnionToIntersection<Client<T>>;
4
+ export declare const hc: <T extends Hono<any, any, any>>(baseUrl: string, options?: RequestOptions) => UnionToIntersection<Client<T>>;
@@ -1,5 +1,6 @@
1
1
  import type { Hono } from '../hono';
2
2
  import type { ValidationTargets } from '../types';
3
+ import type { RemoveBlankRecord } from '../utils/types';
3
4
  declare type MethodName = `$${string}`;
4
5
  declare type Endpoint = Record<MethodName, Data>;
5
6
  declare type Data = {
@@ -16,20 +17,20 @@ declare type ClientRequest<S extends Data> = {
16
17
  [M in keyof S]: S[M] extends {
17
18
  input: infer R;
18
19
  output: infer O;
19
- } ? (args?: R, options?: RequestOptions) => Promise<ClientResponse<O>> : never;
20
+ } ? RemoveBlankRecord<R> extends never ? (args?: {}, options?: RequestOptions) => Promise<ClientResponse<O>> : (args: R, options?: RequestOptions) => Promise<ClientResponse<O>> : never;
20
21
  };
21
22
  export interface ClientResponse<T> extends Response {
22
23
  json(): Promise<T>;
23
24
  }
24
25
  export declare type Fetch<T> = (args?: InferRequestType<T>, opt?: RequestOptions) => Promise<ClientResponse<InferResponseType<T>>>;
25
- export declare type InferResponseType<T> = T extends () => Promise<ClientResponse<infer O>> ? O : never;
26
+ export declare type InferResponseType<T> = T extends (args: any | undefined) => Promise<ClientResponse<infer O>> ? O : never;
26
27
  export declare type InferRequestType<T> = T extends (args: infer R) => Promise<ClientResponse<unknown>> ? NonNullable<R> : never;
27
28
  declare type PathToChain<Path extends string, E extends Endpoint, Original extends string = ''> = Path extends `/${infer P}` ? PathToChain<P, E, Path> : Path extends `${infer P}/${infer R}` ? {
28
29
  [K in P]: PathToChain<R, E, Original>;
29
30
  } : {
30
31
  [K in Path extends '' ? 'index' : Path]: ClientRequest<E extends Record<string, unknown> ? E[Original] : never>;
31
32
  };
32
- export declare type Client<T> = T extends Hono<any, infer S> ? S extends Record<infer K, Endpoint> ? K extends string ? PathToChain<K, S> : never : never : never;
33
+ export declare type Client<T> = T extends Hono<any, infer S, any> ? S extends Record<infer K, Endpoint> ? K extends string ? PathToChain<K, S> : never : never : never;
33
34
  export declare type Callback = (opts: CallbackOptions) => unknown;
34
35
  interface CallbackOptions {
35
36
  path: string[];
@@ -3,6 +3,7 @@ import type { TypedResponse } from './types';
3
3
  import type { Env, NotFoundHandler, Input } from './types';
4
4
  import type { CookieOptions } from './utils/cookie';
5
5
  import type { StatusCode } from './utils/http-status';
6
+ import type { PrettyJSON, JSONValue } from './utils/types';
6
7
  declare type Runtime = 'node' | 'deno' | 'bun' | 'workerd' | 'fastly' | 'edge-light' | 'lagon' | 'other';
7
8
  declare type HeaderRecord = Record<string, string | string[]>;
8
9
  declare type Data = string | ArrayBuffer | ReadableStream;
@@ -52,7 +53,7 @@ export declare class Context<E extends Env = any, P extends string = any, I exte
52
53
  body: (data: Data | null, status?: StatusCode, headers?: HeaderRecord) => Response;
53
54
  text: (text: string, status?: StatusCode, headers?: HeaderRecord) => Response;
54
55
  json: <T = object>(object: T, status?: StatusCode, headers?: HeaderRecord) => Response;
55
- jsonT: <T = object>(object: T, status?: StatusCode, headers?: HeaderRecord) => TypedResponse<T>;
56
+ jsonT: <T>(object: T extends JSONValue ? T : JSONValue, status?: StatusCode, headers?: HeaderRecord) => TypedResponse<T extends JSONValue ? JSONValue extends T ? never : PrettyJSON<T> : never>;
56
57
  html: (html: string, status?: StatusCode, headers?: HeaderRecord) => Response;
57
58
  redirect: (location: string, status?: StatusCode) => Response;
58
59
  cookie: (name: string, value: string, opt?: CookieOptions) => void;
@@ -1,35 +1,37 @@
1
1
  import type { ExecutionContext } from './context';
2
2
  import type { Router } from './router';
3
- import type { Env, ErrorHandler, H, HandlerInterface, MiddlewareHandlerInterface, NotFoundHandler, OnHandlerInterface, MergeSchemaPath, RemoveBlankRecord } from './types';
3
+ import type { Env, ErrorHandler, H, HandlerInterface, MiddlewareHandlerInterface, NotFoundHandler, OnHandlerInterface, MergePath, MergeSchemaPath } from './types';
4
+ import type { RemoveBlankRecord } from './utils/types';
4
5
  interface RouterRoute {
5
6
  path: string;
6
7
  method: string;
7
8
  handler: H;
8
9
  }
9
- declare const Hono_base: new <E_1 extends Env = Env, S_1 = {}>() => {
10
- all: HandlerInterface<E_1, "all", S_1>;
11
- get: HandlerInterface<E_1, "get", S_1>;
12
- post: HandlerInterface<E_1, "post", S_1>;
13
- put: HandlerInterface<E_1, "put", S_1>;
14
- delete: HandlerInterface<E_1, "delete", S_1>;
15
- head: HandlerInterface<E_1, "head", S_1>;
16
- options: HandlerInterface<E_1, "options", S_1>;
17
- patch: HandlerInterface<E_1, "patch", S_1>;
10
+ declare const Hono_base: new <E_1 extends Env = Env, S_1 = {}, BasePath_1 extends string = "">() => {
11
+ all: HandlerInterface<E_1, "all", S_1, BasePath_1>;
12
+ get: HandlerInterface<E_1, "get", S_1, BasePath_1>;
13
+ post: HandlerInterface<E_1, "post", S_1, BasePath_1>;
14
+ put: HandlerInterface<E_1, "put", S_1, BasePath_1>;
15
+ delete: HandlerInterface<E_1, "delete", S_1, BasePath_1>;
16
+ head: HandlerInterface<E_1, "head", S_1, BasePath_1>;
17
+ options: HandlerInterface<E_1, "options", S_1, BasePath_1>;
18
+ patch: HandlerInterface<E_1, "patch", S_1, BasePath_1>;
18
19
  } & {
19
- on: OnHandlerInterface<E_1, S_1>;
20
+ on: OnHandlerInterface<E_1, S_1, BasePath_1>;
20
21
  } & {
21
- use: MiddlewareHandlerInterface<E_1, S_1>;
22
+ use: MiddlewareHandlerInterface<E_1, S_1, BasePath_1>;
22
23
  };
23
- export declare class Hono<E extends Env = Env, S = {}> extends Hono_base<E, S> {
24
+ export declare class Hono<E extends Env = Env, S = {}, BasePath extends string = ''> extends Hono_base<E, S, BasePath> {
24
25
  readonly router: Router<H>;
25
26
  readonly strict: boolean;
26
- private _tempPath;
27
+ private basePath;
27
28
  private path;
28
29
  routes: RouterRoute[];
29
30
  constructor(init?: Partial<Pick<Hono, 'router' | 'strict'>>);
31
+ private clone;
30
32
  private notFoundHandler;
31
33
  private errorHandler;
32
- route<SubPath extends string, SubEnv extends Env, SubSchema>(path: SubPath, app?: Hono<SubEnv, SubSchema>): Hono<E, RemoveBlankRecord<MergeSchemaPath<SubSchema, SubPath> | S>>;
34
+ route<SubPath extends string, SubEnv extends Env, SubSchema>(path: SubPath, app?: Hono<SubEnv, SubSchema>): Hono<E, RemoveBlankRecord<MergeSchemaPath<SubSchema, SubPath> | S>, MergePath<BasePath, SubPath>>;
33
35
  onError(handler: ErrorHandler<E>): this;
34
36
  notFound(handler: NotFoundHandler<E>): this;
35
37
  showRoutes(): void;
@@ -39,6 +41,6 @@ export declare class Hono<E extends Env = Env, S = {}> extends Hono_base<E, S> {
39
41
  private dispatch;
40
42
  handleEvent: (event: FetchEvent) => Response | Promise<Response>;
41
43
  fetch: (request: Request, Env?: E['Bindings'] | {}, executionCtx?: ExecutionContext) => Response | Promise<Response>;
42
- request: (input: Request | string, requestInit?: RequestInit) => Promise<Response>;
44
+ request: (input: Request | string | URL, requestInit?: RequestInit) => Promise<Response>;
43
45
  }
44
46
  export {};
@@ -1,6 +1,6 @@
1
1
  import type { Context } from './context';
2
2
  import type { Hono } from './hono';
3
- import type { UnionToIntersection } from './utils/types';
3
+ import type { UnionToIntersection, RemoveBlankRecord } from './utils/types';
4
4
  export declare type Bindings = Record<string, unknown>;
5
5
  export declare type Variables = Record<string, unknown>;
6
6
  export declare type Env = {
@@ -14,7 +14,7 @@ export declare type MiddlewareHandler<E extends Env = any, P extends string = an
14
14
  export declare type H<E extends Env = any, P extends string = any, I extends Input = {}, O = {}> = Handler<E, P, I, O> | MiddlewareHandler<E, P, I>;
15
15
  export declare type NotFoundHandler<E extends Env = any> = (c: Context<E>) => Response | Promise<Response>;
16
16
  export declare type ErrorHandler<E extends Env = any> = (err: Error, c: Context<E>) => Response;
17
- export interface HandlerInterface<E extends Env = Env, M extends string = any, S = {}> {
17
+ export interface HandlerInterface<E extends Env = Env, M extends string = any, S = {}, BasePath extends string = ''> {
18
18
  <I = {}, O = {}>(...handlers: [H<E, ExtractKey<S>, I, O>, H<E, ExtractKey<S>, I, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, ExtractKey<S>, I, O>>>;
19
19
  <P extends string, O = {}, I = {}, I2 = I, I3 = I & I2>(...handlers: [H<E, ExtractKey<S>, I, O>, H<E, ExtractKey<S>, I2, O>, H<E, ExtractKey<S>, I3, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, ExtractKey<S>, I3, O>>>;
20
20
  <P extends string, O = {}, I = {}, I2 = I, I3 = I & I2, I4 = I2 & I3>(...handlers: [
@@ -31,23 +31,53 @@ export interface HandlerInterface<E extends Env = Env, M extends string = any, S
31
31
  H<E, ExtractKey<S>, I5, O>
32
32
  ]): Hono<E, RemoveBlankRecord<S | Schema<M, ExtractKey<S>, I5, O>>>;
33
33
  <I = {}, O = {}>(...handlers: Handler<E, ExtractKey<S>, I, O>[]): Hono<E, RemoveBlankRecord<S | Schema<M, ExtractKey<S>, I, O>>>;
34
- <P extends string, O = {}, I = {}>(path: P, ...handlers: [H<E, P, I, O>, H<E, P, I, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I, O>>>;
35
- <P extends string, O = {}, I = {}, I2 = I, I3 = I & I2>(path: P, ...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I3, O>>>;
36
- <P extends string, O = {}, I = {}, I2 = I, I3 = I & I2, I4 = I2 & I3>(path: P, ...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>, H<E, P, I4, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I4, O>>>;
37
- <P extends string, O = {}, I = {}, I2 = I, I3 = I & I2, I4 = I2 & I3, I5 = I3 & I4>(path: P, ...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>, H<E, P, I4, O>, H<E, P, I5, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I5, O>>>;
38
- <P extends string, I = {}, O = {}>(path: P, ...handlers: H<E, P, I, O>[]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I, O>>>;
34
+ <P extends string, O = {}, I = {}>(path: P, ...handlers: [H<E, P, I, O>, H<E, P, I, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I, O>>>;
35
+ <P extends string, O = {}, I = {}, I2 = I, I3 = I & I2>(path: P, ...handlers: [
36
+ H<E, MergePath<BasePath, P>, I, O>,
37
+ H<E, MergePath<BasePath, P>, I2, O>,
38
+ H<E, MergePath<BasePath, P>, I3, O>
39
+ ]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I3, O>>>;
40
+ <P extends string, O = {}, I = {}, I2 = I, I3 = I & I2, I4 = I2 & I3>(path: P, ...handlers: [
41
+ H<E, MergePath<BasePath, P>, I, O>,
42
+ H<E, MergePath<BasePath, P>, I2, O>,
43
+ H<E, MergePath<BasePath, P>, I3, O>,
44
+ H<E, MergePath<BasePath, P>, I4, O>
45
+ ]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I4, O>>>;
46
+ <P extends string, O = {}, I = {}, I2 = I, I3 = I & I2, I4 = I2 & I3, I5 = I3 & I4>(path: P, ...handlers: [
47
+ H<E, MergePath<BasePath, P>, I, O>,
48
+ H<E, MergePath<BasePath, P>, I2, O>,
49
+ H<E, MergePath<BasePath, P>, I3, O>,
50
+ H<E, MergePath<BasePath, P>, I4, O>,
51
+ H<E, MergePath<BasePath, P>, I5, O>
52
+ ]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I5, O>>>;
53
+ <P extends string, I = {}, O = {}>(path: P, ...handlers: H<E, MergePath<BasePath, P>, I, O>[]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I, O>>>;
39
54
  }
40
- export interface MiddlewareHandlerInterface<E extends Env = Env, S = {}> {
41
- (...handlers: MiddlewareHandler<E, ExtractKey<S>>[]): Hono<E, S>;
42
- <P extends string>(path: P, ...handlers: MiddlewareHandler<E, P>[]): Hono<E, S>;
55
+ export interface MiddlewareHandlerInterface<E extends Env = Env, S = {}, BasePath extends string = ''> {
56
+ (...handlers: MiddlewareHandler<E, MergePath<BasePath, ExtractKey<S>>>[]): Hono<E, S, BasePath>;
57
+ <P extends string>(path: P, ...handlers: MiddlewareHandler<E, MergePath<BasePath, P>>[]): Hono<E, S, BasePath>;
43
58
  }
44
- export interface OnHandlerInterface<E extends Env = Env, S = {}> {
45
- <M extends string, P extends string, O = {}, I = {}>(method: M, path: P, ...handlers: [H<E, P, I, O>, H<E, P, I, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I, O>>>;
46
- <M extends string, P extends string, O = {}, I = {}, I2 = I, I3 = I & I2>(method: M, path: P, ...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I3, O>>>;
47
- <M extends string, P extends string, O = {}, I = {}, I2 = I, I3 = I & I2, I4 = I2 & I3>(method: M, path: P, ...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>, H<E, P, I4, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I4, O>>>;
48
- <M extends string, P extends string, O = {}, I = {}, I2 = I, I3 = I & I2, I4 = I2 & I3, I5 = I3 & I4>(method: M, path: P, ...handlers: [H<E, P, I, O>, H<E, P, I2, O>, H<E, P, I3, O>, H<E, P, I4, O>, H<E, P, I5, O>]): Hono<E, S | Schema<M, P, I5, O>>;
49
- <M extends string, P extends string, O extends {} = {}, I = {}>(method: M, path: P, ...handlers: H<E, P, I, O>[]): Hono<E, RemoveBlankRecord<S | Schema<M, P, I, O>>>;
50
- <P extends string, O extends {} = {}, I = {}>(methods: string[], path: P, ...handlers: H<E, P, I, O>[]): Hono<E, RemoveBlankRecord<S | Schema<string, P, I, O>>>;
59
+ export interface OnHandlerInterface<E extends Env = Env, S = {}, BasePath extends string = ''> {
60
+ <M extends string, P extends string, O = {}, I = {}>(method: M, path: P, ...handlers: [H<E, MergePath<BasePath, P>, I, O>, H<E, MergePath<BasePath, P>, I, O>]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I, O>>, BasePath>;
61
+ <M extends string, P extends string, O = {}, I = {}, I2 = I, I3 = I & I2>(method: M, path: P, ...handlers: [
62
+ H<E, MergePath<BasePath, P>, I, O>,
63
+ H<E, MergePath<BasePath, P>, I2, O>,
64
+ H<E, MergePath<BasePath, P>, I3, O>
65
+ ]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I3, O>>, BasePath>;
66
+ <M extends string, P extends string, O = {}, I = {}, I2 = I, I3 = I & I2, I4 = I2 & I3>(method: M, path: P, ...handlers: [
67
+ H<E, MergePath<BasePath, P>, I, O>,
68
+ H<E, MergePath<BasePath, P>, I2, O>,
69
+ H<E, MergePath<BasePath, P>, I3, O>,
70
+ H<E, MergePath<BasePath, P>, I4, O>
71
+ ]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I4, O>>, BasePath>;
72
+ <M extends string, P extends string, O = {}, I = {}, I2 = I, I3 = I & I2, I4 = I2 & I3, I5 = I3 & I4>(method: M, path: P, ...handlers: [
73
+ H<E, MergePath<BasePath, P>, I, O>,
74
+ H<E, MergePath<BasePath, P>, I2, O>,
75
+ H<E, MergePath<BasePath, P>, I3, O>,
76
+ H<E, MergePath<BasePath, P>, I4, O>,
77
+ H<E, MergePath<BasePath, P>, I5, O>
78
+ ]): Hono<E, S | Schema<M, MergePath<BasePath, P>, I5, O>, BasePath>;
79
+ <M extends string, P extends string, O extends {} = {}, I = {}>(method: M, path: P, ...handlers: H<E, MergePath<BasePath, P>, I, O>[]): Hono<E, RemoveBlankRecord<S | Schema<M, MergePath<BasePath, P>, I, O>>, BasePath>;
80
+ <P extends string, O extends {} = {}, I = {}>(methods: string[], path: P, ...handlers: H<E, MergePath<BasePath, P>, I, O>[]): Hono<E, RemoveBlankRecord<S | Schema<string, MergePath<BasePath, P>, I, O>>, BasePath>;
51
81
  }
52
82
  declare type ExtractKey<S> = S extends Record<infer Key, unknown> ? Key extends string ? Key : never : string;
53
83
  export declare type Schema<M extends string, P extends string, I extends Input, O> = {
@@ -65,7 +95,7 @@ export declare type AddDollar<T> = T extends Record<infer K, infer R> ? K extend
65
95
  [MethodName in `$${Lowercase<K>}`]: R;
66
96
  } : never : never;
67
97
  export declare type MergeSchemaPath<S, P extends string> = S extends Record<infer Key, infer T> ? Key extends string ? Record<MergePath<P, Key>, T> : never : never;
68
- export declare type MergePath<A extends string, B extends string> = A extends `${infer P}/` ? `${P}${B}` : `${A}${B}`;
98
+ export declare type MergePath<A extends string, B extends string> = A extends '' ? B : A extends `${infer P}/` ? B extends `/${infer Q}` ? `${P}/${Q}` : `${P}/${B}` : B extends `/${infer Q}` ? `${A}/${Q}` : `${A}/${B}`;
69
99
  export declare type TypedResponse<T = unknown> = {
70
100
  response: Response | Promise<Response>;
71
101
  data: T;
@@ -89,5 +119,4 @@ export declare type InputToDataByTarget<T extends Input, Target extends keyof Va
89
119
  export declare type RemoveQuestion<T> = T extends `${infer R}?` ? R : T;
90
120
  export declare type UndefinedIfHavingQuestion<T> = T extends `${infer _}?` ? string | undefined : string;
91
121
  export declare type ExtractSchema<T> = T extends Hono<infer _, infer S> ? S : never;
92
- export declare type RemoveBlankRecord<T> = T extends Record<infer K, unknown> ? K extends string ? T : never : never;
93
122
  export {};
@@ -2,3 +2,15 @@ export declare type Expect<T extends true> = T;
2
2
  export declare type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false;
3
3
  export declare type NotEqual<X, Y> = true extends Equal<X, Y> ? false : true;
4
4
  export declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
5
+ export declare type RemoveBlankRecord<T> = T extends Record<infer K, unknown> ? K extends string ? T : never : never;
6
+ export declare type JSONPrimitive = string | boolean | number | null | undefined;
7
+ export declare type JSONArray = (JSONPrimitive | JSONObject | JSONArray)[];
8
+ export declare type JSONObject = {
9
+ [key: string]: JSONPrimitive | JSONArray | JSONObject;
10
+ };
11
+ export declare type JSONValue = JSONObject | JSONArray | JSONPrimitive;
12
+ declare type TrueAndFalseToBoolean<T> = T extends true ? boolean : T extends false ? boolean : T;
13
+ export declare type PrettyJSON<T> = T extends JSONPrimitive ? TrueAndFalseToBoolean<T> : T extends JSONArray ? PrettyJSON<T[number]> : T extends JSONObject ? {
14
+ [K in keyof T]: PrettyJSON<T[K]>;
15
+ } : never;
16
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "3.0.2",
3
+ "version": "3.0.4",
4
4
  "description": "Ultrafast web framework for the Edge",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",