hono 2.4.1 → 2.5.1

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.
@@ -38,7 +38,7 @@ const compose = (middleware, onNotFound, onError) => {
38
38
  let res;
39
39
  let isError = false;
40
40
  if (!handler) {
41
- if (context instanceof import_context.HonoContext && context.finalized === false && onNotFound) {
41
+ if (context instanceof import_context.Context && context.finalized === false && onNotFound) {
42
42
  res = onNotFound(context);
43
43
  }
44
44
  } else {
@@ -48,7 +48,7 @@ const compose = (middleware, onNotFound, onError) => {
48
48
  return dispatchRes instanceof Promise ? dispatchRes : Promise.resolve(dispatchRes);
49
49
  });
50
50
  } catch (err) {
51
- if (err instanceof Error && context instanceof import_context.HonoContext && onError) {
51
+ if (err instanceof Error && context instanceof import_context.Context && onError) {
52
52
  context.error = err;
53
53
  res = onError(err, context);
54
54
  isError = true;
@@ -69,7 +69,7 @@ const compose = (middleware, onNotFound, onError) => {
69
69
  }
70
70
  return context;
71
71
  }).catch((err) => {
72
- if (err instanceof Error && context instanceof import_context.HonoContext && onError) {
72
+ if (err instanceof Error && context instanceof import_context.Context && onError) {
73
73
  context.error = err;
74
74
  context.res = onError(err, context);
75
75
  return context;
@@ -18,11 +18,11 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var context_exports = {};
20
20
  __export(context_exports, {
21
- HonoContext: () => HonoContext
21
+ Context: () => Context
22
22
  });
23
23
  module.exports = __toCommonJS(context_exports);
24
24
  var import_cookie = require("./utils/cookie");
25
- class HonoContext {
25
+ class Context {
26
26
  constructor(req, env = {}, executionCtx = void 0, notFoundHandler = () => new Response()) {
27
27
  this.error = void 0;
28
28
  this._status = 200;
@@ -156,8 +156,30 @@ class HonoContext {
156
156
  notFound() {
157
157
  return this.notFoundHandler(this);
158
158
  }
159
+ get runtime() {
160
+ const global = globalThis;
161
+ if (global?.Deno !== void 0) {
162
+ return "deno";
163
+ }
164
+ if (global?.Bun !== void 0) {
165
+ return "bun";
166
+ }
167
+ if (typeof global?.WebSocketPair === "function") {
168
+ return "cloudflare";
169
+ }
170
+ if (global?.fastly !== void 0) {
171
+ return "fastly";
172
+ }
173
+ if (typeof global?.EdgeRuntime !== "string") {
174
+ return "vercel";
175
+ }
176
+ if (global?.process?.title === "node") {
177
+ return "node";
178
+ }
179
+ return "other";
180
+ }
159
181
  }
160
182
  // Annotate the CommonJS export names for ESM import in node:
161
183
  0 && (module.exports = {
162
- HonoContext
184
+ Context
163
185
  });
package/dist/cjs/hono.js CHANGED
@@ -102,6 +102,15 @@ class Hono extends defineDynamicClass() {
102
102
  });
103
103
  return this;
104
104
  }
105
+ on(method, path, ...handlers) {
106
+ if (!method)
107
+ return this;
108
+ this.path = path;
109
+ handlers.map((handler) => {
110
+ this.addRoute(method.toUpperCase(), this.path, handler);
111
+ });
112
+ return this;
113
+ }
105
114
  onError(handler) {
106
115
  this.errorHandler = handler;
107
116
  return this;
@@ -110,6 +119,14 @@ class Hono extends defineDynamicClass() {
110
119
  this.notFoundHandler = handler;
111
120
  return this;
112
121
  }
122
+ showRoutes() {
123
+ const length = 8;
124
+ this.routes.map((route) => {
125
+ console.log(
126
+ `\x1B[32m${route.method}\x1B[0m ${" ".repeat(length - route.method.length)} ${route.path}`
127
+ );
128
+ });
129
+ }
113
130
  addRoute(method, path, handler) {
114
131
  method = method.toUpperCase();
115
132
  if (this._tempPath) {
@@ -133,7 +150,7 @@ class Hono extends defineDynamicClass() {
133
150
  const method = request.method;
134
151
  const result = this.matchRoute(method, path);
135
152
  request.paramData = result?.params;
136
- const c = new import_context.HonoContext(request, env, eventOrExecutionCtx, this.notFoundHandler);
153
+ const c = new import_context.Context(request, env, eventOrExecutionCtx, this.notFoundHandler);
137
154
  if (result && result.handlers.length === 1) {
138
155
  const handler = result.handlers[0];
139
156
  let res;
@@ -151,21 +168,17 @@ class Hono extends defineDynamicClass() {
151
168
  let awaited;
152
169
  try {
153
170
  awaited = await res;
171
+ if (!awaited) {
172
+ return this.notFoundHandler(c);
173
+ }
154
174
  } catch (err) {
155
175
  return this.handleError(err, c);
156
176
  }
157
- if (!awaited) {
158
- return this.notFoundHandler(c);
159
- }
160
177
  return awaited;
161
178
  })();
162
179
  }
163
180
  const handlers = result ? result.handlers : [this.notFoundHandler];
164
- const composed = (0, import_compose.compose)(
165
- handlers,
166
- this.notFoundHandler,
167
- this.errorHandler
168
- );
181
+ const composed = (0, import_compose.compose)(handlers, this.notFoundHandler, this.errorHandler);
169
182
  return (async () => {
170
183
  try {
171
184
  const tmp = composed(c);
@@ -25,7 +25,7 @@ var import_router = require("../../router");
25
25
  var import_url = require("../../utils/url");
26
26
  var import_node = require("./node");
27
27
  var import_trie = require("./trie");
28
- const METHOD_NAMES = [import_router.METHOD_NAME_ALL, ...import_router.METHODS].map((method) => method.toUpperCase());
28
+ const methodNames = [import_router.METHOD_NAME_ALL, ...import_router.METHODS].map((method) => method.toUpperCase());
29
29
  const emptyParam = {};
30
30
  const nullMatcher = [/^$/, []];
31
31
  function buildWildcardRegExp(path) {
@@ -83,6 +83,8 @@ class RegExpRouter {
83
83
  if (!middleware || !routes) {
84
84
  throw new Error("Can not add a route since the matcher is already built.");
85
85
  }
86
+ if (!methodNames.includes(method))
87
+ methodNames.push(method);
86
88
  if (path === "/*") {
87
89
  path = "*";
88
90
  }
@@ -145,7 +147,7 @@ class RegExpRouter {
145
147
  }
146
148
  buildAllMatchers() {
147
149
  const matchers = {};
148
- METHOD_NAMES.forEach((method) => {
150
+ methodNames.forEach((method) => {
149
151
  matchers[method] = this.buildMatcher(method) || matchers[import_router.METHOD_NAME_ALL];
150
152
  });
151
153
  this.middleware = this.routes = void 0;
@@ -30,9 +30,21 @@ class StaticRouter {
30
30
  this.routes[method.toUpperCase()] = {};
31
31
  });
32
32
  }
33
+ newRoute() {
34
+ const route = {};
35
+ const routeAll = this.routes[import_router.METHOD_NAME_ALL];
36
+ Object.keys(routeAll).forEach((path) => {
37
+ route[path] = {
38
+ handlers: [...routeAll[path].handlers],
39
+ params: {}
40
+ };
41
+ });
42
+ return route;
43
+ }
33
44
  add(method, path, handler) {
34
45
  var _a, _b;
35
46
  const { middleware, routes } = this;
47
+ routes[method] || (routes[method] = this.newRoute());
36
48
  if (path === "/*") {
37
49
  path = "*";
38
50
  }
@@ -187,6 +187,7 @@ class VBase {
187
187
  if (this._nested())
188
188
  jsonData = dst;
189
189
  }
190
+ value = this.sanitizeValue(value);
190
191
  const results = [];
191
192
  let typeRule = this.rules.shift();
192
193
  for (const rule2 of this.rules) {
@@ -206,6 +207,10 @@ class VBase {
206
207
  }
207
208
  return results;
208
209
  };
210
+ this.sanitizeValue = (value) => this.sanitizers.reduce(
211
+ (acc, sanitizer2) => sanitizer2(acc),
212
+ value
213
+ );
209
214
  this.validateType = (value) => {
210
215
  if (this.isArray) {
211
216
  if (!Array.isArray(value)) {
@@ -238,9 +243,6 @@ class VBase {
238
243
  if (Array.isArray(value)) {
239
244
  if (value.length === 0 && !this._optional)
240
245
  return false;
241
- for (const sanitizer2 of this.sanitizers) {
242
- value = value.map((innerVal) => sanitizer2(innerVal));
243
- }
244
246
  for (const val of value) {
245
247
  if (!func(val)) {
246
248
  return false;
@@ -248,9 +250,6 @@ class VBase {
248
250
  }
249
251
  return true;
250
252
  } else {
251
- for (const sanitizer2 of this.sanitizers) {
252
- value = sanitizer2(value);
253
- }
254
253
  if (!func(value)) {
255
254
  return false;
256
255
  }
package/dist/compose.d.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import type { Environment, NotFoundHandler, ErrorHandler } from './types';
2
- import type { Schema } from './validator/schema';
3
2
  interface ComposeContext {
4
3
  finalized: boolean;
5
4
  res: unknown;
6
5
  }
7
- export declare const compose: <C extends ComposeContext, P extends string = string, E extends Partial<Environment> = Environment, D extends Partial<Schema> = Schema>(middleware: Function[], onNotFound?: NotFoundHandler<P, E, D> | undefined, onError?: ErrorHandler<P, E, D> | undefined) => (context: C, next?: Function) => C | Promise<C>;
6
+ export declare const compose: <C extends ComposeContext, E extends Partial<Environment> = Environment>(middleware: Function[], onNotFound?: NotFoundHandler<E> | undefined, onError?: ErrorHandler<E> | undefined) => (context: C, next?: Function) => C | Promise<C>;
8
7
  export {};
package/dist/compose.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/compose.ts
2
- import { HonoContext } from "./context.js";
2
+ import { Context } from "./context.js";
3
3
  var compose = (middleware, onNotFound, onError) => {
4
4
  const middlewareLength = middleware.length;
5
5
  return (context, next) => {
@@ -16,7 +16,7 @@ var compose = (middleware, onNotFound, onError) => {
16
16
  let res;
17
17
  let isError = false;
18
18
  if (!handler) {
19
- if (context instanceof HonoContext && context.finalized === false && onNotFound) {
19
+ if (context instanceof Context && context.finalized === false && onNotFound) {
20
20
  res = onNotFound(context);
21
21
  }
22
22
  } else {
@@ -26,7 +26,7 @@ var compose = (middleware, onNotFound, onError) => {
26
26
  return dispatchRes instanceof Promise ? dispatchRes : Promise.resolve(dispatchRes);
27
27
  });
28
28
  } catch (err) {
29
- if (err instanceof Error && context instanceof HonoContext && onError) {
29
+ if (err instanceof Error && context instanceof Context && onError) {
30
30
  context.error = err;
31
31
  res = onError(err, context);
32
32
  isError = true;
@@ -47,7 +47,7 @@ var compose = (middleware, onNotFound, onError) => {
47
47
  }
48
48
  return context;
49
49
  }).catch((err) => {
50
- if (err instanceof Error && context instanceof HonoContext && onError) {
50
+ if (err instanceof Error && context instanceof Context && onError) {
51
51
  context.error = err;
52
52
  context.res = onError(err, context);
53
53
  return context;
package/dist/context.d.ts CHANGED
@@ -4,42 +4,10 @@ import type { CookieOptions } from './utils/cookie';
4
4
  import type { StatusCode } from './utils/http-status';
5
5
  import type { Schema, SchemaToProp } from './validator/schema';
6
6
  declare type Headers = Record<string, string | string[]>;
7
+ declare type Runtime = 'node' | 'deno' | 'bun' | 'cloudflare' | 'fastly' | 'vercel' | 'other';
7
8
  export declare type Data = string | ArrayBuffer | ReadableStream;
8
- export interface Context<P extends string = string, E extends Partial<Environment> = Environment, S extends Partial<Schema> | unknown = Schema> {
9
- req: Request<P, S extends Schema ? SchemaToProp<S> : any>;
10
- env: E['Bindings'];
11
- event: FetchEvent;
12
- executionCtx: ExecutionContext;
13
- finalized: boolean;
14
- error: Error | undefined;
15
- get res(): Response;
16
- set res(_res: Response);
17
- header: (name: string, value: string, options?: {
18
- append?: boolean;
19
- }) => void;
20
- status: (status: StatusCode) => void;
21
- set: {
22
- <Key extends keyof ContextVariableMap>(key: Key, value: ContextVariableMap[Key]): void;
23
- <Key extends keyof E['Variables']>(key: Key, value: E['Variables'][Key]): void;
24
- (key: string, value: unknown): void;
25
- };
26
- get: {
27
- <Key extends keyof ContextVariableMap>(key: Key): ContextVariableMap[Key];
28
- <Key extends keyof E['Variables']>(key: Key): E['Variables'][Key];
29
- <T = any>(key: string): T;
30
- };
31
- pretty: (prettyJSON: boolean, space?: number) => void;
32
- newResponse: (data: Data | null, status: StatusCode, headers: Headers) => Response;
33
- body: (data: Data | null, status?: StatusCode, headers?: Headers) => Response;
34
- text: (text: string, status?: StatusCode, headers?: Headers) => Response;
35
- json: <T>(object: T, status?: StatusCode, headers?: Headers) => Response;
36
- html: (html: string, status?: StatusCode, headers?: Headers) => Response;
37
- redirect: (location: string, status?: StatusCode) => Response;
38
- cookie: (name: string, value: string, options?: CookieOptions) => void;
39
- notFound: () => Response | Promise<Response>;
40
- }
41
- export declare class HonoContext<P extends string = string, E extends Partial<Environment> = Environment, S extends Partial<Schema> = Schema> implements Context<P, E, S> {
42
- req: Request<P, S extends Schema ? SchemaToProp<S> : any>;
9
+ export declare class Context<P extends string = string, E extends Partial<Environment> = Environment, S extends Partial<Schema> = Schema> {
10
+ req: Request<P, S extends Schema ? SchemaToProp<S> : S>;
43
11
  env: E['Bindings'];
44
12
  finalized: boolean;
45
13
  error: Error | undefined;
@@ -51,7 +19,7 @@ export declare class HonoContext<P extends string = string, E extends Partial<En
51
19
  private _headers;
52
20
  private _res;
53
21
  private notFoundHandler;
54
- constructor(req: Request<P>, env?: E['Bindings'], executionCtx?: FetchEvent | ExecutionContext | undefined, notFoundHandler?: NotFoundHandler<P, E, S>);
22
+ constructor(req: Request<P>, env?: E['Bindings'], executionCtx?: FetchEvent | ExecutionContext | undefined, notFoundHandler?: NotFoundHandler<E>);
55
23
  get event(): FetchEvent;
56
24
  get executionCtx(): ExecutionContext;
57
25
  get res(): Response;
@@ -76,5 +44,6 @@ export declare class HonoContext<P extends string = string, E extends Partial<En
76
44
  redirect(location: string, status?: StatusCode): Response;
77
45
  cookie(name: string, value: string, opt?: CookieOptions): void;
78
46
  notFound(): Response | Promise<Response>;
47
+ get runtime(): Runtime;
79
48
  }
80
49
  export {};
package/dist/context.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/context.ts
2
2
  import { serialize } from "./utils/cookie.js";
3
- var HonoContext = class {
3
+ var Context = class {
4
4
  constructor(req, env = {}, executionCtx = void 0, notFoundHandler = () => new Response()) {
5
5
  this.error = void 0;
6
6
  this._status = 200;
@@ -134,7 +134,29 @@ var HonoContext = class {
134
134
  notFound() {
135
135
  return this.notFoundHandler(this);
136
136
  }
137
+ get runtime() {
138
+ const global = globalThis;
139
+ if (global?.Deno !== void 0) {
140
+ return "deno";
141
+ }
142
+ if (global?.Bun !== void 0) {
143
+ return "bun";
144
+ }
145
+ if (typeof global?.WebSocketPair === "function") {
146
+ return "cloudflare";
147
+ }
148
+ if (global?.fastly !== void 0) {
149
+ return "fastly";
150
+ }
151
+ if (typeof global?.EdgeRuntime !== "string") {
152
+ return "vercel";
153
+ }
154
+ if (global?.process?.title === "node") {
155
+ return "node";
156
+ }
157
+ return "other";
158
+ }
137
159
  };
138
160
  export {
139
- HonoContext
161
+ Context
140
162
  };
package/dist/hono.d.ts CHANGED
@@ -15,8 +15,8 @@ interface Route<P extends string = string, E extends Partial<Environment> = Envi
15
15
  handler: Handler<P, E, S>;
16
16
  }
17
17
  declare const Hono_base: new <E_1 extends Partial<Environment> = Environment, P_1 extends string = string, S_1 extends Partial<Schema> = Schema, U = Hono<E_1, P_1, S_1>>() => {
18
- all: HandlerInterface<P_1, E_1, S_1, U>;
19
18
  get: HandlerInterface<P_1, E_1, S_1, U>;
19
+ all: HandlerInterface<P_1, E_1, S_1, U>;
20
20
  post: HandlerInterface<P_1, E_1, S_1, U>;
21
21
  put: HandlerInterface<P_1, E_1, S_1, U>;
22
22
  delete: HandlerInterface<P_1, E_1, S_1, U>;
@@ -33,17 +33,19 @@ export declare class Hono<E extends Partial<Environment> = Environment, P extend
33
33
  constructor(init?: Partial<Pick<Hono, 'router' | 'strict'>>);
34
34
  private notFoundHandler;
35
35
  private errorHandler;
36
- route(path: string, app?: Hono<E, P, S>): this;
36
+ route(path: string, app?: Hono<any>): this;
37
37
  use<Path extends string = string, Data extends Partial<Schema> = Schema>(...middleware: Handler<Path, E, Data>[]): Hono<E, Path, S>;
38
38
  use<Path extends string = string, Data extends Partial<Schema> = Schema>(arg1: string, ...middleware: Handler<Path, E, Data>[]): Hono<E, Path, S>;
39
- onError(handler: ErrorHandler<P, E, S>): this;
40
- notFound(handler: NotFoundHandler<P, E, S>): this;
39
+ on(method: string, path: string, ...handlers: Handler<P, E, S>[]): this;
40
+ onError(handler: ErrorHandler<E>): this;
41
+ notFound(handler: NotFoundHandler<E>): this;
42
+ showRoutes(): void;
41
43
  private addRoute;
42
44
  private matchRoute;
43
45
  private handleError;
44
46
  private dispatch;
45
47
  handleEvent: (event: FetchEvent) => Response | Promise<Response>;
46
48
  fetch: (request: Request, Environment?: E['Bindings'], executionCtx?: ExecutionContext) => Response | Promise<Response>;
47
- request: (input: RequestInfo, requestInit?: RequestInit) => Promise<Response>;
49
+ request: (input: Request | string, requestInit?: RequestInit) => Promise<Response>;
48
50
  }
49
51
  export {};
package/dist/hono.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/hono.ts
2
2
  import { compose } from "./compose.js";
3
- import { HonoContext } from "./context.js";
3
+ import { Context } from "./context.js";
4
4
  import { extendRequestPrototype } from "./request.js";
5
5
  import { METHOD_NAME_ALL, METHOD_NAME_ALL_LOWERCASE, METHODS } from "./router.js";
6
6
  import { RegExpRouter } from "./router/reg-exp-router/index.js";
@@ -80,6 +80,15 @@ var Hono = class extends defineDynamicClass() {
80
80
  });
81
81
  return this;
82
82
  }
83
+ on(method, path, ...handlers) {
84
+ if (!method)
85
+ return this;
86
+ this.path = path;
87
+ handlers.map((handler) => {
88
+ this.addRoute(method.toUpperCase(), this.path, handler);
89
+ });
90
+ return this;
91
+ }
83
92
  onError(handler) {
84
93
  this.errorHandler = handler;
85
94
  return this;
@@ -88,6 +97,14 @@ var Hono = class extends defineDynamicClass() {
88
97
  this.notFoundHandler = handler;
89
98
  return this;
90
99
  }
100
+ showRoutes() {
101
+ const length = 8;
102
+ this.routes.map((route) => {
103
+ console.log(
104
+ `\x1B[32m${route.method}\x1B[0m ${" ".repeat(length - route.method.length)} ${route.path}`
105
+ );
106
+ });
107
+ }
91
108
  addRoute(method, path, handler) {
92
109
  method = method.toUpperCase();
93
110
  if (this._tempPath) {
@@ -111,7 +128,7 @@ var Hono = class extends defineDynamicClass() {
111
128
  const method = request.method;
112
129
  const result = this.matchRoute(method, path);
113
130
  request.paramData = result?.params;
114
- const c = new HonoContext(request, env, eventOrExecutionCtx, this.notFoundHandler);
131
+ const c = new Context(request, env, eventOrExecutionCtx, this.notFoundHandler);
115
132
  if (result && result.handlers.length === 1) {
116
133
  const handler = result.handlers[0];
117
134
  let res;
@@ -129,21 +146,17 @@ var Hono = class extends defineDynamicClass() {
129
146
  let awaited;
130
147
  try {
131
148
  awaited = await res;
149
+ if (!awaited) {
150
+ return this.notFoundHandler(c);
151
+ }
132
152
  } catch (err) {
133
153
  return this.handleError(err, c);
134
154
  }
135
- if (!awaited) {
136
- return this.notFoundHandler(c);
137
- }
138
155
  return awaited;
139
156
  })();
140
157
  }
141
158
  const handlers = result ? result.handlers : [this.notFoundHandler];
142
- const composed = compose(
143
- handlers,
144
- this.notFoundHandler,
145
- this.errorHandler
146
- );
159
+ const composed = compose(handlers, this.notFoundHandler, this.errorHandler);
147
160
  return (async () => {
148
161
  try {
149
162
  const tmp = composed(c);
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /// <reference path="request.d.ts" />
2
2
  import { Hono } from './hono';
3
- export type { Next, ContextVariableMap, MiddlewareHandler } from './types';
3
+ export type { Next, ContextVariableMap, MiddlewareHandler, ErrorHandler, NotFoundHandler, } from './types';
4
4
  export type { Context } from './context';
5
5
  export type { Validator } from './validator/validator';
6
6
  import type { CustomHandler } from './types';
package/dist/request.d.ts CHANGED
@@ -29,7 +29,7 @@ declare global {
29
29
  bodyData?: BodyData;
30
30
  parseBody<BodyType extends BodyData>(): Promise<BodyType>;
31
31
  jsonData?: any;
32
- json<JSONData = unknown>(): Promise<Partial<JSONData>>;
32
+ json<T>(): Promise<T>;
33
33
  data: Data;
34
34
  valid: {
35
35
  (key: string | string[], value: unknown): Data;
@@ -3,7 +3,7 @@ import { METHOD_NAME_ALL, METHODS, UnsupportedPathError } from "../../router.js"
3
3
  import { checkOptionalParameter } from "../../utils/url.js";
4
4
  import { PATH_ERROR } from "./node.js";
5
5
  import { Trie } from "./trie.js";
6
- var METHOD_NAMES = [METHOD_NAME_ALL, ...METHODS].map((method) => method.toUpperCase());
6
+ var methodNames = [METHOD_NAME_ALL, ...METHODS].map((method) => method.toUpperCase());
7
7
  var emptyParam = {};
8
8
  var nullMatcher = [/^$/, []];
9
9
  function buildWildcardRegExp(path) {
@@ -61,6 +61,8 @@ var RegExpRouter = class {
61
61
  if (!middleware || !routes) {
62
62
  throw new Error("Can not add a route since the matcher is already built.");
63
63
  }
64
+ if (!methodNames.includes(method))
65
+ methodNames.push(method);
64
66
  if (path === "/*") {
65
67
  path = "*";
66
68
  }
@@ -123,7 +125,7 @@ var RegExpRouter = class {
123
125
  }
124
126
  buildAllMatchers() {
125
127
  const matchers = {};
126
- METHOD_NAMES.forEach((method) => {
128
+ methodNames.forEach((method) => {
127
129
  matchers[method] = this.buildMatcher(method) || matchers[METHOD_NAME_ALL];
128
130
  });
129
131
  this.middleware = this.routes = void 0;
@@ -3,6 +3,7 @@ export declare class StaticRouter<T> implements Router<T> {
3
3
  middleware: Record<string, Result<T>>;
4
4
  routes: Record<string, Record<string, Result<T>>>;
5
5
  constructor();
6
+ private newRoute;
6
7
  add(method: string, path: string, handler: T): void;
7
8
  match(method: string, path: string): Result<T> | null;
8
9
  }
@@ -8,9 +8,21 @@ var StaticRouter = class {
8
8
  this.routes[method.toUpperCase()] = {};
9
9
  });
10
10
  }
11
+ newRoute() {
12
+ const route = {};
13
+ const routeAll = this.routes[METHOD_NAME_ALL];
14
+ Object.keys(routeAll).forEach((path) => {
15
+ route[path] = {
16
+ handlers: [...routeAll[path].handlers],
17
+ params: {}
18
+ };
19
+ });
20
+ return route;
21
+ }
11
22
  add(method, path, handler) {
12
23
  var _a, _b;
13
24
  const { middleware, routes } = this;
25
+ routes[method] || (routes[method] = this.newRoute());
14
26
  if (path === "/*") {
15
27
  path = "*";
16
28
  }
package/dist/types.d.ts CHANGED
@@ -10,13 +10,13 @@ export declare type Environment = {
10
10
  };
11
11
  export declare type Handler<P extends string = string, E extends Partial<Environment> = Environment, S extends Partial<Schema> = Schema> = (c: Context<P, E, S>, next: Next) => Response | Promise<Response | undefined | void>;
12
12
  export declare type MiddlewareHandler<P extends string = string, E extends Partial<Environment> = Environment, S extends Partial<Schema> = Schema> = (c: Context<P, E, S>, next: Next) => Promise<Response | undefined | void>;
13
- export declare type NotFoundHandler<P extends string = string, E extends Partial<Environment> = Environment, S extends Partial<Schema> = Schema> = (c: Context<P, E, S>) => Response | Promise<Response>;
14
- export declare type ErrorHandler<P extends string = string, E extends Partial<Environment> = Environment, S extends Partial<Schema> = Schema> = (err: Error, c: Context<P, E, S>) => Response;
13
+ export declare type NotFoundHandler<E extends Partial<Environment> = Environment> = (c: Context<string, E>) => Response | Promise<Response>;
14
+ export declare type ErrorHandler<E extends Partial<Environment> = Environment> = (err: Error, c: Context<string, E>) => Response;
15
15
  export declare type Next = () => Promise<void>;
16
16
  declare type ParamKeyName<NameWithPattern> = NameWithPattern extends `${infer Name}{${infer _Pattern}` ? Name : NameWithPattern;
17
17
  declare type ParamKey<Component> = Component extends `:${infer NameWithPattern}` ? ParamKeyName<NameWithPattern> : never;
18
18
  export declare type ParamKeys<Path> = Path extends `${infer Component}/${infer Rest}` ? ParamKey<Component> | ParamKeys<Rest> : ParamKey<Path>;
19
19
  export interface CustomHandler<P extends string | Partial<Environment> | Schema = string, E = Partial<Environment> | Partial<Schema>, S = Partial<Schema>> {
20
- (c: Context<P extends string ? P : P extends Partial<Environment> ? string : P extends Partial<Schema> ? string : never, P extends Partial<Environment> ? P : P extends Partial<Schema> ? Partial<Environment> : E extends Partial<Environment> ? E extends Partial<Schema> ? Environment : E : E extends Partial<Schema> ? Partial<Environment> : Environment, P extends Partial<Schema> ? P : E extends Partial<Schema> ? P extends Partial<Environment> ? E extends Partial<Environment> ? unknown : E : unknown : S extends Partial<Schema> ? S : never>, next: Next): Response | Promise<Response | undefined | void>;
20
+ (c: Context<P extends string ? P : P extends Partial<Environment> ? string : P extends Partial<Schema> ? string : never, P extends Partial<Environment> ? P : P extends Partial<Schema> ? Partial<Environment> : E extends Partial<Environment> ? E extends Partial<Schema> ? Environment : E : E extends Partial<Schema> ? Partial<Environment> : Environment, S extends Schema ? S : P extends Schema ? P : E extends Schema ? E : any>, next: Next): Response | Promise<Response | undefined | void>;
21
21
  }
22
22
  export {};
@@ -76,6 +76,7 @@ export declare abstract class VBase {
76
76
  [x: string]: any;
77
77
  }>>(req: R) => Promise<ValidateResult[]>;
78
78
  protected getTypeRuleName(): string;
79
+ private sanitizeValue;
79
80
  private validateRule;
80
81
  private validateType;
81
82
  private validateValue;
@@ -155,6 +155,7 @@ var VBase = class {
155
155
  if (this._nested())
156
156
  jsonData = dst;
157
157
  }
158
+ value = this.sanitizeValue(value);
158
159
  const results = [];
159
160
  let typeRule = this.rules.shift();
160
161
  for (const rule2 of this.rules) {
@@ -174,6 +175,10 @@ var VBase = class {
174
175
  }
175
176
  return results;
176
177
  };
178
+ this.sanitizeValue = (value) => this.sanitizers.reduce(
179
+ (acc, sanitizer2) => sanitizer2(acc),
180
+ value
181
+ );
177
182
  this.validateType = (value) => {
178
183
  if (this.isArray) {
179
184
  if (!Array.isArray(value)) {
@@ -206,9 +211,6 @@ var VBase = class {
206
211
  if (Array.isArray(value)) {
207
212
  if (value.length === 0 && !this._optional)
208
213
  return false;
209
- for (const sanitizer2 of this.sanitizers) {
210
- value = value.map((innerVal) => sanitizer2(innerVal));
211
- }
212
214
  for (const val of value) {
213
215
  if (!func(val)) {
214
216
  return false;
@@ -216,9 +218,6 @@ var VBase = class {
216
218
  }
217
219
  return true;
218
220
  } else {
219
- for (const sanitizer2 of this.sanitizers) {
220
- value = sanitizer2(value);
221
- }
222
221
  if (!func(value)) {
223
222
  return false;
224
223
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "2.4.1",
3
+ "version": "2.5.1",
4
4
  "description": "Ultrafast web framework for Cloudflare Workers.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",