hono 4.11.1 → 4.11.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
@@ -63,8 +63,8 @@ The migration guide is available on [docs/MIGRATION.md](docs/MIGRATION.md).
63
63
  Contributions Welcome! You can contribute in the following ways.
64
64
 
65
65
  - Create an Issue - Propose a new feature. Report a bug.
66
- - Pull Request - Fix a bug and typo. Refactor the code.
67
- - Create third-party middleware - Instruct below.
66
+ - Pull Request - Fix a bug or typo. Refactor the code.
67
+ - Create third-party middleware - See instructions below.
68
68
  - Share - Share your thoughts on the Blog, X, and others.
69
69
  - Make your application - Please try to use Hono.
70
70
 
@@ -0,0 +1,16 @@
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 utils_exports = {};
16
+ module.exports = __toCommonJS(utils_exports);
@@ -84,19 +84,14 @@ export interface ClientResponse<T, U extends number = StatusCode, F extends Resp
84
84
  formData(): Promise<FormData>;
85
85
  arrayBuffer(): Promise<ArrayBuffer>;
86
86
  }
87
- type HonoURL<Prefix extends string, Path extends string, Arg> = IsLiteral<Prefix> extends true ? TrimEndSlash<Prefix> extends `${infer Protocol}://${infer Rest}` ? Rest extends `${infer Hostname}/${infer P}` ? ParseHostName<Hostname> extends [infer Host extends string, infer Port extends string] ? Arg extends {
87
+ type BuildSearch<Arg, Key extends 'query'> = Arg extends {
88
+ [K in Key]: infer Query;
89
+ } ? IsEmptyObject<Query> extends true ? '' : `?${string}` : '';
90
+ type BuildPathname<P extends string, Arg> = Arg extends {
88
91
  param: infer Param;
89
- } ? Arg extends {
90
- query: infer Query;
91
- } ? IsEmptyObject<Query> extends true ? TypedURL<`${Protocol}:`, Host, Port, `${ApplyParam<TrimStartSlash<P>, Param>}`, ''> : TypedURL<`${Protocol}:`, Host, Port, `${ApplyParam<TrimStartSlash<P>, Param>}`, `?${string}`> : TypedURL<`${Protocol}:`, Host, Port, `${ApplyParam<TrimStartSlash<P>, Param>}`, ''> : Arg extends {
92
- query: infer Query;
93
- } ? IsEmptyObject<Query> extends true ? TypedURL<`${Protocol}:`, Host, Port, `/${TrimStartSlash<P>}`, ''> : TypedURL<`${Protocol}:`, Host, Port, `/${TrimStartSlash<P>}`, `?${string}`> : TypedURL<`${Protocol}:`, Host, Port, `/${TrimStartSlash<P>}`, ''> : never : ParseHostName<Rest> extends [infer Host extends string, infer Port extends string] ? Arg extends {
94
- param: infer Param;
95
- } ? Arg extends {
96
- query: infer Query;
97
- } ? IsEmptyObject<Query> extends true ? TypedURL<`${Protocol}:`, Host, Port, `${ApplyParam<TrimStartSlash<Path>, Param>}`, ''> : TypedURL<`${Protocol}:`, Host, Port, `${ApplyParam<TrimStartSlash<Path>, Param>}`, `?${string}`> : TypedURL<`${Protocol}:`, Host, Port, `${ApplyParam<TrimStartSlash<Path>, Param>}`, ''> : Arg extends {
98
- query: infer Query;
99
- } ? IsEmptyObject<Query> extends true ? TypedURL<`${Protocol}:`, Host, Port, `/${TrimStartSlash<Path>}`, ''> : TypedURL<`${Protocol}:`, Host, Port, `/${TrimStartSlash<Path>}`, `?${string}`> : TypedURL<`${Protocol}:`, Host, Port, `/${TrimStartSlash<Path>}`, ''> : never : URL : URL;
92
+ } ? `${ApplyParam<TrimStartSlash<P>, Param>}` : `/${TrimStartSlash<P>}`;
93
+ type BuildTypedURL<Protocol extends string, Host extends string, Port extends string, P extends string, Arg> = TypedURL<`${Protocol}:`, Host, Port, BuildPathname<P, Arg>, BuildSearch<Arg, 'query'>>;
94
+ type HonoURL<Prefix extends string, Path extends string, Arg> = IsLiteral<Prefix> extends true ? TrimEndSlash<Prefix> extends `${infer Protocol}://${infer Rest}` ? Rest extends `${infer Hostname}/${infer P}` ? ParseHostName<Hostname> extends [infer Host extends string, infer Port extends string] ? BuildTypedURL<Protocol, Host, Port, P, Arg> : never : ParseHostName<Rest> extends [infer Host extends string, infer Port extends string] ? BuildTypedURL<Protocol, Host, Port, Path, Arg> : never : URL : URL;
100
95
  type ParseHostName<T extends string> = T extends `${infer Host}:${infer Port}` ? [Host, Port] : [T, ''];
101
96
  type TrimStartSlash<T extends string> = T extends `/${infer R}` ? TrimStartSlash<R> : T;
102
97
  type TrimEndSlash<T extends string> = T extends `${infer R}/` ? TrimEndSlash<R> : T;
@@ -445,35 +445,35 @@ export interface OnHandlerInterface<E extends Env = Env, S extends Schema = Blan
445
445
  <M extends string, P extends string, R extends HandlerResponse<any> = any, I extends Input = BlankInput>(methods: M[], path: P, ...handlers: [H<E, MergePath<BasePath, P>, I, R>, ...H<E, MergePath<BasePath, P>, I, R>[]]): HonoBase<E, S & ToSchema<M, MergePath<BasePath, P>, I, MergeTypedResponse<R>>, BasePath, MergePath<BasePath, P>>;
446
446
  <M extends string, const Ps extends string[], I extends Input = BlankInput, R extends HandlerResponse<any> = any, E2 extends Env = E>(methods: M | M[], paths: Ps, ...handlers: H<E2, MergePath<BasePath, Ps[number]>, I, R>[]): HonoBase<E, S & ToSchema<M, MergePath<BasePath, Ps[number]>, I, MergeTypedResponse<R>>, BasePath, Ps extends [...string[], infer LastPath extends string] ? MergePath<BasePath, LastPath> : never>;
447
447
  }
448
- export type ToSchema<M extends string, P extends string, I extends Input | Input['in'], RorO> = IsAny<RorO> extends true ? Simplify<{
448
+ type ToSchemaOutput<RorO, I extends Input | Input['in']> = RorO extends TypedResponse<infer T, infer U, infer F> ? {
449
+ output: unknown extends T ? {} : T;
450
+ outputFormat: I extends {
451
+ outputFormat: string;
452
+ } ? I['outputFormat'] : F;
453
+ status: U;
454
+ } : {
455
+ output: unknown extends RorO ? {} : RorO;
456
+ outputFormat: unknown extends RorO ? 'json' : I extends {
457
+ outputFormat: string;
458
+ } ? I['outputFormat'] : 'json';
459
+ status: StatusCode;
460
+ };
461
+ export type ToSchema<M extends string, P extends string, I extends Input | Input['in'], RorO> = IsAny<RorO> extends true ? {
449
462
  [K in P]: {
450
- [K2 in M as AddDollar<K2>]: Simplify<{
463
+ [K2 in M as AddDollar<K2>]: {
451
464
  input: AddParam<ExtractInput<I>, P>;
452
- } & {
453
465
  output: {};
454
466
  outputFormat: ResponseFormat;
455
467
  status: StatusCode;
456
- }>;
468
+ };
457
469
  };
458
- }> : [RorO] extends [never] ? {} : [RorO] extends [Promise<void>] ? {} : Simplify<{
470
+ } : [RorO] extends [never] ? {} : [RorO] extends [Promise<void>] ? {} : {
459
471
  [K in P]: {
460
472
  [K2 in M as AddDollar<K2>]: Simplify<{
461
473
  input: AddParam<ExtractInput<I>, P>;
462
- } & (RorO extends TypedResponse<infer T, infer U, infer F> ? {
463
- output: unknown extends T ? {} : T;
464
- outputFormat: I extends {
465
- outputFormat: string;
466
- } ? I['outputFormat'] : F;
467
- status: U;
468
- } : {
469
- output: unknown extends RorO ? {} : RorO;
470
- outputFormat: unknown extends RorO ? 'json' : I extends {
471
- outputFormat: string;
472
- } ? I['outputFormat'] : 'json';
473
- status: StatusCode;
474
- })>;
474
+ } & ToSchemaOutput<RorO, I>>;
475
475
  };
476
- }>;
476
+ };
477
477
  export type Schema = {
478
478
  [Path: string]: {
479
479
  [Method: `$${Lowercase<string>}`]: Endpoint;
@@ -532,8 +532,8 @@ export type TypedResponse<T = unknown, U extends StatusCode = StatusCode, F exte
532
532
  _format: F;
533
533
  };
534
534
  type MergeTypedResponse<T> = T extends Promise<void> ? T : T extends Promise<infer T2> ? T2 extends TypedResponse ? T2 : TypedResponse : T extends TypedResponse ? T : TypedResponse;
535
- type MergeTypedResponseStrict<T> = T extends Promise<infer T2> ? T2 extends TypedResponse ? T2 : never : T extends TypedResponse ? T : never;
536
- type MergeMiddlewareResponse<T> = MergeTypedResponseStrict<ExtractHandlerResponse<T>>;
535
+ type ExtractTypedResponseOnly<T> = T extends TypedResponse ? T : never;
536
+ type MergeMiddlewareResponse<T> = T extends (c: any, next: any) => Promise<infer R> ? Exclude<R, void> extends never ? never : Exclude<R, void> extends Response | TypedResponse<any, any, any> ? ExtractTypedResponseOnly<Exclude<R, void>> : never : T extends (c: any, next: any) => infer R ? R extends Response | TypedResponse<any, any, any> ? ExtractTypedResponseOnly<R> : never : never;
537
537
  export type FormValue = string | Blob;
538
538
  export type ParsedFormValue = string | File;
539
539
  export type ValidationTargets<T extends FormValue = ParsedFormValue, P extends string = string> = {
@@ -4,3 +4,4 @@
4
4
  */
5
5
  export { validator } from './validator';
6
6
  export type { ValidationFunction } from './validator';
7
+ export type { InferInput } from './utils';
@@ -0,0 +1,29 @@
1
+ import type { FormValue, ParsedFormValue, ValidationTargets } from '../types';
2
+ import type { UnionToIntersection } from '../utils/types';
3
+ /**
4
+ * Checks if T is a literal union type (e.g., 'asc' | 'desc')
5
+ * that should be preserved in input types.
6
+ * Returns true for union literals, false for single literals or wide types.
7
+ */
8
+ export type IsLiteralUnion<T, Base> = [Exclude<T, undefined>] extends [Base] ? [Exclude<T, undefined>] extends [UnionToIntersection<Exclude<T, undefined>>] ? false : true : false;
9
+ type IsOptionalUnion<T> = [unknown] extends [T] ? false : undefined extends T ? true : false;
10
+ type SimplifyDeep<T> = {
11
+ [K in keyof T]: T[K];
12
+ } & {};
13
+ type InferInputInner<Output, Target extends keyof ValidationTargets, T extends FormValue> = SimplifyDeep<{
14
+ [K in keyof Output]: IsLiteralUnion<Output[K], string> extends true ? Output[K] : IsOptionalUnion<Output[K]> extends true ? Output[K] : Target extends 'form' ? T | T[] : Target extends 'query' ? string | string[] : Target extends 'param' ? string : Target extends 'header' ? string : Target extends 'cookie' ? string : unknown;
15
+ }>;
16
+ /**
17
+ * Utility type to infer input types for validation targets.
18
+ * Preserves literal union types (e.g., 'asc' | 'desc') while using
19
+ * the default ValidationTargets type for other values.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // In @hono/zod-validator or similar:
24
+ * type Input = InferInput<z.input<Schema>, 'query'>
25
+ * // { orderBy: 'asc' | 'desc', page: string | string[] }
26
+ * ```
27
+ */
28
+ export type InferInput<Output, Target extends keyof ValidationTargets, T extends FormValue = ParsedFormValue> = [Exclude<Output, undefined>] extends [never] ? {} : [Exclude<Output, undefined>] extends [object] ? undefined extends Output ? SimplifyDeep<InferInputInner<Exclude<Output, undefined>, Target, T>> | undefined : SimplifyDeep<InferInputInner<Output, Target, T>> : {};
29
+ export {};
@@ -1,14 +1,15 @@
1
1
  import type { Context } from '../context';
2
2
  import type { Env, MiddlewareHandler, TypedResponse, ValidationTargets, FormValue } from '../types';
3
+ import type { InferInput } from './utils';
3
4
  type ValidationTargetKeysWithBody = 'form' | 'json';
4
5
  type ValidationTargetByMethod<M> = M extends 'get' | 'head' ? Exclude<keyof ValidationTargets, ValidationTargetKeysWithBody> : keyof ValidationTargets;
5
6
  export type ValidationFunction<InputType, OutputType, E extends Env = {}, P extends string = string> = (value: InputType, c: Context<E, P>) => OutputType | TypedResponse | Promise<OutputType> | Promise<TypedResponse>;
6
7
  export type ExtractValidationResponse<VF> = VF extends (value: any, c: any) => infer R ? R extends Promise<infer PR> ? PR extends TypedResponse<infer T, infer S, infer F> ? TypedResponse<T, S, F> : PR extends Response ? PR : PR extends undefined ? never : never : R extends TypedResponse<infer T, infer S, infer F> ? TypedResponse<T, S, F> : R extends Response ? R : R extends undefined ? never : never : never;
7
8
  export declare const validator: <InputType, P extends string, M extends string, U extends ValidationTargetByMethod<M>, P2 extends string = P, VF extends (value: unknown extends InputType ? ValidationTargets[U] : InputType, c: Context<any, P2>) => any = (value: unknown extends InputType ? ValidationTargets[U] : InputType, c: Context<any, P2>) => any, V extends {
8
- in: { [K in U]: K extends "json" ? unknown extends InputType ? ExtractValidatorOutput<VF> : InputType : { [K2 in keyof ExtractValidatorOutput<VF>]: ValidationTargets<FormValue>[K][K2]; }; };
9
+ in: { [K in U]: K extends "json" ? unknown extends InputType ? ExtractValidatorOutput<VF> : InputType : InferInput<ExtractValidatorOutput<VF>, K, FormValue>; };
9
10
  out: { [K in U]: ExtractValidatorOutput<VF>; };
10
11
  } = {
11
- in: { [K in U]: K extends "json" ? unknown extends InputType ? ExtractValidatorOutput<VF> : InputType : { [K2 in keyof ExtractValidatorOutput<VF>]: ValidationTargets<FormValue>[K][K2]; }; };
12
+ in: { [K in U]: K extends "json" ? unknown extends InputType ? ExtractValidatorOutput<VF> : InputType : InferInput<ExtractValidatorOutput<VF>, K, FormValue>; };
12
13
  out: { [K in U]: ExtractValidatorOutput<VF>; };
13
14
  }, E extends Env = any>(target: U, validationFunc: VF) => MiddlewareHandler<E, P, V, ExtractValidationResponse<VF>>;
14
15
  export type ExtractValidatorOutput<VF> = VF extends (value: any, c: any) => infer R ? R extends Promise<infer PR> ? PR extends Response | TypedResponse<any, any, any> ? never : PR : R extends Response | TypedResponse<any, any, any> ? never : R : never;
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hono",
3
- "version": "4.11.1",
3
+ "version": "4.11.3",
4
4
  "description": "Web framework built on Web Standards",
5
5
  "main": "dist/cjs/index.js",
6
6
  "type": "module",
@@ -661,7 +661,7 @@
661
661
  "@types/glob": "^9.0.0",
662
662
  "@types/jsdom": "^21.1.7",
663
663
  "@types/node": "^24.3.0",
664
- "@typescript/native-preview": "7.0.0-dev.20250523.1",
664
+ "@typescript/native-preview": "7.0.0-dev.20251220.1",
665
665
  "@vitest/coverage-v8": "^3.2.4",
666
666
  "arg": "^5.0.2",
667
667
  "bun-types": "^1.2.20",