hono-openapi
Version:
OpenAPI schema generator for Hono
280 lines (273 loc) • 12.7 kB
text/typescript
import * as openapi_types from 'openapi-types';
import { OpenAPIV3_1 } from 'openapi-types';
import { Env, Input, Context, Next, MiddlewareHandler, ValidationTargets, Hono } from 'hono';
import { TypedResponse, RouterRoute, ValidationTargets as ValidationTargets$1, BlankEnv, Input as Input$1, BlankInput, Schema, BlankSchema, MiddlewareHandler as MiddlewareHandler$1 } from 'hono/types';
import { loadVendor as loadVendor$2, ToOpenAPISchemaContext } from '@standard-community/standard-openapi';
import { Hook } from '@hono/standard-validator';
import { loadVendor as loadVendor$1 } from '@standard-community/standard-json';
import { StatusCode } from 'hono/utils/http-status';
import { JSONSchema7 } from 'json-schema';
/** The Standard Schema interface. */
interface StandardSchemaV1<Input = unknown, Output = Input> {
/** The Standard Schema properties. */
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
}
declare namespace StandardSchemaV1 {
/** The Standard Schema properties interface. */
export interface Props<Input = unknown, Output = Input> {
/** The version number of the standard. */
readonly version: 1;
/** The vendor name of the schema library. */
readonly vendor: string;
/** Validates unknown input values. */
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
/** Inferred types associated with the schema. */
readonly types?: Types<Input, Output> | undefined;
}
/** The result interface of the validate function. */
export type Result<Output> = SuccessResult<Output> | FailureResult;
/** The result interface if validation succeeds. */
export interface SuccessResult<Output> {
/** The typed output value. */
readonly value: Output;
/** The non-existent issues. */
readonly issues?: undefined;
}
/** The result interface if validation fails. */
export interface FailureResult {
/** The issues of failed validation. */
readonly issues: ReadonlyArray<Issue>;
}
/** The issue interface of the failure output. */
export interface Issue {
/** The error message of the issue. */
readonly message: string;
/** The path of the issue, if any. */
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
}
/** The path segment interface of the issue. */
export interface PathSegment {
/** The key representing a path segment. */
readonly key: PropertyKey;
}
/** The Standard Schema types interface. */
export interface Types<Input = unknown, Output = Input> {
/** The input type of the schema. */
readonly input: Input;
/** The output type of the schema. */
readonly output: Output;
}
/** Infers the input type of a Standard Schema. */
export type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
/** Infers the output type of a Standard Schema. */
export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
export { };
}
declare function loadVendor(vendor: string, fn: {
toJSONSchema?: Parameters<typeof loadVendor$1>[1];
toOpenAPISchema?: Parameters<typeof loadVendor$2>[1];
}): void;
/**
* Generate a resolver for a validation schema
* @param schema Validation schema
* @returns Resolver result
*/
declare function resolver<Schema extends StandardSchemaV1>(schema: Schema, options?: Record<string, unknown>): {
vendor: string;
validate: (value: unknown) => StandardSchemaV1.Result<unknown> | Promise<StandardSchemaV1.Result<unknown>>;
toJSONSchema: () => JSONSchema7 | Promise<JSONSchema7>;
toOpenAPISchema: () => Promise<{
schema: OpenAPIV3_1.SchemaObject;
components: OpenAPIV3_1.ComponentsObject | undefined;
}>;
};
type HasUndefined<T> = undefined extends T ? true : false;
/**
* Create a validator middleware
* @param target Target for validation
* @param schema Validation schema
* @param hook Hook for validation
* @returns Middleware handler
*/
declare function validator<Schema extends StandardSchemaV1, Target extends keyof ValidationTargets, E extends Env, P extends string, In = StandardSchemaV1.InferInput<Schema>, Out = StandardSchemaV1.InferOutput<Schema>, I extends Input = {
in: HasUndefined<In> extends true ? {
[K in Target]?: In extends ValidationTargets[K] ? In : {
[K2 in keyof In]?: ValidationTargets[K][K2];
};
} : {
[K in Target]: In extends ValidationTargets[K] ? In : {
[K2 in keyof In]: ValidationTargets[K][K2];
};
};
out: {
[K in Target]: Out;
};
}, V extends I = I>(target: Target, schema: Schema, hook?: Hook<StandardSchemaV1.InferOutput<Schema>, E, P, Target>, options?: ResolverReturnType["options"]): MiddlewareHandler<E, P, V>;
/**
* Describe a route with OpenAPI specs.
* @param spec Options for describing a route
* @returns Middleware handler
*/
declare function describeRoute(spec: DescribeRouteOptions): MiddlewareHandler;
type ResponseObject<T extends Partial<Record<StatusCode, StandardSchemaV1>>> = {
[K in keyof T]: OpenAPIV3_1.ReferenceObject | (OpenAPIV3_1.ResponseObject & {
content?: {
[media: string]: OpenAPIV3_1.MediaTypeObject & {
vSchema?: T[K];
};
};
});
};
type Num<T> = T extends `${infer N extends number}` ? N : T;
type HandlerResponse<T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = {
[K in keyof T]: T[K] extends StandardSchemaV1 ? PromiseOr<TypedResponse<StandardSchemaV1.InferOutput<T[K]>, Num<K> extends StatusCode ? Num<K> : never>> : never;
}[keyof T];
type Handler<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>> = (c: Context<E, P, I>, next: Next) => HandlerResponse<T>;
declare function describeResponse<E extends Env, P extends string, I extends Input, T extends Partial<Record<StatusCode, StandardSchemaV1>> = Partial<Record<StatusCode, StandardSchemaV1>>>(handler: Handler<E, P, I, T>, responses: ResponseObject<T>, options?: Record<string, unknown>): Handler<E, P, I, T>;
/**
* The unique symbol for the middlewares, which makes it easier to identify them. Not meant to be used directly, unless you're creating a custom middleware.
*/
declare const uniqueSymbol: unique symbol;
declare const ALLOWED_METHODS: readonly ["GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD", "PATCH", "TRACE"];
type AllowedMethods = (typeof ALLOWED_METHODS)[number];
declare function registerSchemaPath({ route, specs, paths, }: RegisterSchemaPathOptions): void;
declare function removeExcludedPaths(paths: OpenAPIV3_1.PathsObject, ctx: SpecContext): OpenAPIV3_1.PathsObject<{}, {}>;
type PromiseOr<T> = T | Promise<T>;
type ResolverReturnType = ReturnType<typeof resolver> & {
options?: {
/**
* Override the media type of the request body, if not specified, it will be `application/json` for `json` target and `multipart/form-data` for `form` target.
*/
media?: string;
} & Partial<ToOpenAPISchemaContext>;
};
type HandlerUniqueProperty = (ResolverReturnType & {
target: keyof ValidationTargets$1;
}) | {
spec: DescribeRouteOptions;
};
type GenerateSpecOptions = {
/**
* Customize OpenAPI config, refers to Swagger 2.0 config
*
* @see https://swagger.io/specification/v2/
*/
documentation: Omit<Partial<OpenAPIV3_1.Document>, "x-express-openapi-additional-middleware" | "x-express-openapi-validation-strict">;
/**
* Include paths which don't have the handlers.
* This is useful when you want to document the
* API without implementing it or index all the paths.
*/
includeEmptyPaths: boolean;
/**
* Determine if Swagger should exclude static files.
*
* @default true
*/
excludeStaticFile: boolean;
/**
* Paths to exclude from OpenAPI endpoint
*
* @default []
*/
exclude: string | RegExp | Array<string | RegExp>;
/**
* Exclude methods from the specs
*/
excludeMethods: AllowedMethods[];
/**
* Exclude tags from OpenAPI
*/
excludeTags: string[];
/**
* Default options for `describeRoute` method
*/
defaultOptions: Partial<Record<AllowedMethods | "ALL", DescribeRouteOptions>>;
};
type OperationId = string | ((route: RouterRoute) => string);
type DescribeRouteOptions = Omit<OpenAPIV3_1.OperationObject, "responses" | "operationId"> & {
operationId?: OperationId;
/**
* Pass `true` to hide route from OpenAPI/swagger document
*/
hide?: boolean | ((props: {
c?: Context;
method: string;
path: string;
}) => boolean);
/**
* Responses of the request
*/
responses?: {
[key: string]: (OpenAPIV3_1.ResponseObject & {
content?: {
[key: string]: Omit<OpenAPIV3_1.MediaTypeObject, "schema"> & {
schema?: OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.SchemaObject | ResolverReturnType;
};
};
}) | OpenAPIV3_1.ReferenceObject;
};
};
type RegisterSchemaPathOptions = {
route: RouterRoute;
specs?: DescribeRouteOptions & {
operationId?: OperationId;
};
paths: Partial<OpenAPIV3_1.PathsObject>;
};
type HaveDefaultValues = "documentation" | "excludeStaticFile" | "exclude" | "excludeMethods" | "excludeTags";
type SanitizedGenerateSpecOptions = Pick<GenerateSpecOptions, HaveDefaultValues> & Omit<Partial<GenerateSpecOptions>, HaveDefaultValues>;
type SpecContext = {
components: OpenAPIV3_1.ComponentsObject;
options: SanitizedGenerateSpecOptions;
};
/**
* Route handler for OpenAPI specs
* @param hono Instance of Hono
* @param options Options for generating OpenAPI specs
* @returns Middleware handler for OpenAPI specs
*/
declare function openAPIRouteHandler<E extends Env = BlankEnv, P extends string = string, I extends Input$1 = BlankInput, S extends Schema = BlankSchema>(hono: Hono<E, S, P>, options?: Partial<GenerateSpecOptions>): MiddlewareHandler$1<E, P, I>;
/**
* Generate OpenAPI specs for the given Hono instance
* @param hono Instance of Hono
* @param options Options for generating OpenAPI specs
* @param config Configuration for OpenAPI route handler
* @param Context Route context for hiding routes
* @returns OpenAPI specs
*/
declare function generateSpecs<E extends Env = BlankEnv, P extends string = string, I extends Input$1 = BlankInput, S extends Schema = BlankSchema>(hono: Hono<E, S, P>, options?: Partial<GenerateSpecOptions>, c?: Context<E, P, I>): Promise<{
tags: openapi_types.OpenAPIV3.TagObject[];
info: {
description: string;
title: string;
termsOfService?: string;
contact?: openapi_types.OpenAPIV3.ContactObject;
version: string;
summary?: string;
license?: OpenAPIV3_1.LicenseObject;
};
paths: {
[x: string]: Omit<openapi_types.OpenAPIV3.PathItemObject<{}>, "parameters" | "servers"> & {
servers?: OpenAPIV3_1.ServerObject[];
parameters?: (OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.ParameterObject)[];
} & {
get?: OpenAPIV3_1.OperationObject<{}>;
put?: OpenAPIV3_1.OperationObject<{}>;
post?: OpenAPIV3_1.OperationObject<{}>;
delete?: OpenAPIV3_1.OperationObject<{}>;
options?: OpenAPIV3_1.OperationObject<{}>;
head?: OpenAPIV3_1.OperationObject<{}>;
patch?: OpenAPIV3_1.OperationObject<{}>;
trace?: OpenAPIV3_1.OperationObject<{}>;
};
};
components: OpenAPIV3_1.ComponentsObject;
openapi: string;
externalDocs?: openapi_types.OpenAPIV3.ExternalDocumentationObject;
security?: openapi_types.OpenAPIV3.SecurityRequirementObject[];
servers?: OpenAPIV3_1.ServerObject[];
webhooks?: Record<string, OpenAPIV3_1.PathItemObject | OpenAPIV3_1.ReferenceObject>;
jsonSchemaDialect?: string;
}>;
export { ALLOWED_METHODS, type AllowedMethods, type DescribeRouteOptions, type GenerateSpecOptions, type HandlerUniqueProperty, type PromiseOr, type RegisterSchemaPathOptions, type ResolverReturnType, type SpecContext, describeResponse, describeRoute, generateSpecs, loadVendor, openAPIRouteHandler, registerSchemaPath, removeExcludedPaths, resolver, uniqueSymbol, validator };