import type { Context, Env } from "hono";
import type { RouteOutput } from "./routing";
import type { z, ZodType } from "zod";
type MaybePromise<T> = T | Promise<T>;
type ExtractZodSchema<T> = T extends ZodType ? T : never;
type ValidKeys = "query" | "param" | "header" | "json" | "form";
type InputFromRequest<Request> = {
param: Request extends { params: infer P }
? z.output<ExtractZodSchema<P>>
: never;
query: Request extends { query: infer Q }
? z.output<ExtractZodSchema<Q>>
: never;
header: Request extends { headers: infer H }
? z.output<ExtractZodSchema<H>>
: never;
json: Request extends {
body: { content: { "application/json": { schema: infer Schema } } };
}
? z.output<ExtractZodSchema<Schema>>
: never;
form: Request extends {
body: { content: { "multipart/form-data": { schema: infer Schema } } };
}
? z.output<ExtractZodSchema<Schema>>
: never;
};
type MergeInput<I extends Record<string, any>> = {
[K in keyof I]: I[K];
};
type ExtractResponseContent<R> = R extends { responses: infer Responses }
? {
[K in keyof Responses]: Responses[K] extends { content: infer Content }
? Content
: never;
}[keyof Responses]
: never;
type ValidatedContext<
E extends Env,
I extends Record<string, any>,
> = Context<E> & {
req: {
valid: <K extends ValidKeys>(key: K) => I[K];
};
};
export type RouteHandler<
R extends RouteOutput<any, any, any, any, any, any>,
E extends Env = Env,
> = (
c: ValidatedContext<E, MergeInput<InputFromRequest<R["request"]>>>,
) => MaybePromise<ExtractResponseContent<R["description"]>>;