import { ZodOpenApiResponseObject, ZodOpenApiOperationObject, ZodOpenApiObject, createDocument } from 'zod-openapi';
export { extendZodWithOpenApi } from 'zod-openapi';
import { MiddlewareHandler, Env, ValidationTargets as ValidationTargets$1, Schema, Hono } from 'hono';
import { StatusCode } from 'hono/utils/http-status';
import { z } from 'zod';

type AnyZ = z.ZodType<any, z.ZodTypeDef, any>;
type ValidationTarget = 'json' | 'query' | 'param' | 'cookie' | 'header';
type RequestParam = ValidationTarget;
type ValidationSchemas = Partial<Record<ValidationTarget, AnyZ>>;
type ValidationTargets = Omit<ValidationTargets$1, 'form'>;
type ValidationTargetParams<T extends AnyZ> = {
    /**
     * Zod schema for the target.
     */
    schema: T;
    /**
     * Determines whether the target should be validated or if the schema should only be used for documentation.
     * @default true
     */
    validate?: boolean;
};
type StatusCodePrefix = '1' | '2' | '3' | '4' | '5';
type StatusCodeWithoutMinus1 = Exclude<StatusCode, -1>;
type StatusCodeWithWildcards = StatusCodeWithoutMinus1 | `${StatusCodePrefix}XX` | 'default';
/**
 * Mapping of zod-validator targets to their respective schemas, used both as a source of truth
 * for validation and for OpenAPI documentation.
 */
type HonoOpenApiRequestSchemas = Partial<Record<RequestParam, ValidationTargetParams<AnyZ> | AnyZ>>;
type HasUndefined<T> = undefined extends T ? true : false;
type IsUnknown<T> = unknown extends T ? [T] extends [null] ? false : true : false;
type Clean<T> = {
    [K in keyof T as T[K] extends never ? never : K]: T[K];
} & {};
type ExtractInValues<Schema extends AnyZ, Target extends keyof Omit<ValidationTargets, 'form'>, In = z.input<Schema>> = HasUndefined<In> extends true ? In extends ValidationTargets[Target] ? In : {
    [K2 in keyof In]?: ValidationTargets[Target][K2];
} : In extends ValidationTargets[Target] ? In : {
    [K2 in keyof In]: ValidationTargets[Target][K2];
};
type GetValidationSchemas<T extends HonoOpenApiRequestSchemas> = Clean<{
    [K in keyof T]: T[K] extends ValidationTargetParams<infer S> ? T[K]['validate'] extends false ? never : S : T[K] extends AnyZ ? T[K] : never;
}>;
type ToValidatorValues<T extends ValidationSchemas> = {
    in: Clean<{
        [K in keyof ValidationTargets]: IsUnknown<T[K]> extends true ? never : ExtractInValues<Exclude<T[K], undefined>, K>;
    }>;
    out: Clean<{
        [K in keyof ValidationTargets]: IsUnknown<T[K]> extends true ? never : z.output<Exclude<T[K], undefined>>;
    }>;
};
type Values<T extends HonoOpenApiRequestSchemas> = ToValidatorValues<GetValidationSchemas<T>>;
type ZodValidatorFn = <S extends AnyZ, T extends keyof ValidationTargets>(target: T, schema: S) => MiddlewareHandler;
interface ReferenceObject {
    $ref: string;
    summary?: string;
    description?: string;
}
interface SimpleResponseObject extends Pick<ZodOpenApiResponseObject, 'links' | 'headers' | 'ref'> {
    description?: string;
    schema: AnyZ;
    mediaType?: string;
}
/**
 * OpenAPI response object, augmented with Zod-based schema.
 */
type HonoOpenApiResponseObject = ZodOpenApiResponseObject | SimpleResponseObject | AnyZ | ReferenceObject;
type HonoOpenApiResponses = Partial<Record<StatusCodeWithWildcards, HonoOpenApiResponseObject>>;
/**
 * OpenAPI operation object, augmented with Zod-based request and response schemas.
 * See README for exhaustive set of examples.
 */
interface HonoOpenApiOperation<Req extends HonoOpenApiRequestSchemas = HonoOpenApiRequestSchemas> extends Omit<ZodOpenApiOperationObject, 'requestParams' | 'responses'> {
    request?: Req;
    responses: HonoOpenApiResponses;
}
/**
 * zod-openapi document without `openapi` property (set to 3.1.0, we do not support lower versions).
 * @see https://swagger.io/specification/
 */
type HonoOpenApiDocument = Omit<ZodOpenApiObject, 'openapi'>;
type HonoOpenApiMiddleware = <Req extends HonoOpenApiRequestSchemas, E extends Env, P extends string>(operation: HonoOpenApiOperation<Req>) => MiddlewareHandler<E, P, Values<Req>>;

interface DocumentRouteSettings {
    /**
     * Whether to add a new route with the OpenAPI document.
     * @default true
     */
    addRoute?: boolean;
    /**
     * Route name under which the OpenAPI document will be available, assuming `settings.addRoute` is `true`.
     * @default '/doc'
     */
    routeName?: string;
}
/**
 * Creates an OpenAPI document from a Hono router based on the routes decorated with `openApi` middleware.
 * By default it will create a new route at `/doc` that returns the OpenAPI document.
 * @param router Hono router containing routes decorated with `openApi` middleware
 * @param document OpenAPI document base. An object with at least `info` property is required
 * @param [routeSettings] Settings for the route that will serve the OpenAPI document
 * @returns object representing the OpenAPI document
 *
 * @example
 * ```ts
 * import { Hono } from 'hono';
 * import { z } from 'zod';
 * import { createOpenApiDocument, openApi } from 'hono-zod-openapi';
 *
 * export const app = new Hono().get(
 *   '/user',
 *   openApi({
 *     tags: ['User'],
 *     responses: {
 *       200: z.object({ hi: z.string() }).openapi({ example: { hi: 'user' } }),
 *     },
 *     request: {
 *       query: z.object({ id: z.string() }),
 *     },
 *   }),
 *   (c) => {
 *     const { id } = c.req.valid('query');
 *     return c.json({ hi: id }, 200);
 *   },
 * );
 *
 * createOpenApiDocument(app, {
 *   info: {
 *     title: 'Example API',
 *     version: '1.0.0',
 *   },
 * });
 * ```
 */
declare function createOpenApiDocument<E extends Env, S extends Schema, P extends string>(router: Hono<E, S, P>, document: HonoOpenApiDocument, { addRoute, routeName }?: DocumentRouteSettings): ReturnType<typeof createDocument>;

/**
 * Used internally to create the `openApi` middleware. You can use it if you have a custom `zod-validator` middleware,
 * e.g. one that has a custom error handler. Otherwise, you probably don't need it and you should just use `openApi` instead.
 * @param [zodValidator] `@hono/zod-validator`-compatible middleware
 * @returns `openApi` middleware
 */
declare function createOpenApiMiddleware(zodValidator?: ZodValidatorFn): HonoOpenApiMiddleware;
/**
 * Hono middleware that documents decorated route. Additionally validates request body/query params/path params etc.,
 * the same way `@hono/zod-validator` does.
 *
 * @see HonoOpenApiOperation for more information on how to use it.
 */
declare const openApi: HonoOpenApiMiddleware;
/**
 * A no-op function, used to ensure proper validator's type inference and provide autocomplete in cases where you don't want to define the spec inline.
 * @example
 *
 * ```ts
 * const operation = defineOpenApiOperation({
 *   responses: {
 *     200: z.object({ name: z.string() }),
 *   },
 *   request: {
 *     json: z.object({ email: z.string() }),
 *   },
 * });
 *
 * const app = new Hono().post('/user', openApi(operation), async (c) => {
 *   const { name } = c.req.valid('json');
 *
 *   return c.json({ name }, 200);
 * });
 * ```
 */
declare const defineOpenApiOperation: <Req extends HonoOpenApiRequestSchemas>(operation: HonoOpenApiOperation<Req>) => HonoOpenApiOperation<Req>;

export { type HonoOpenApiDocument, type HonoOpenApiOperation, type HonoOpenApiRequestSchemas, type HonoOpenApiResponseObject, createOpenApiDocument, createOpenApiMiddleware, defineOpenApiOperation, openApi };
