UNPKG

erest

Version:

Easy to build api server depend on @leizm/web and express.

168 lines (167 loc) 5.15 kB
/** * @file API Scheme * @author Yourtion Guo <yourtion@gmail.com> */ import { type ZodTypeAny, z } from "zod"; import type ERest from "."; import type { ISchemaType, SchemaType } from "./params"; import { type SourceResult } from "./utils"; export type TYPE_RESPONSE = string | SchemaType | ISchemaType | Record<string, ISchemaType>; export interface IExample { name?: string | undefined; path?: string; headers?: Record<string, unknown>; input?: Record<string, unknown>; output?: Record<string, unknown>; } export type DEFAULT_HANDLER = (...args: unknown[]) => unknown; export declare const SUPPORT_METHOD: readonly ["get", "post", "put", "delete", "patch"]; export type SUPPORT_METHODS = (typeof SUPPORT_METHOD)[number]; export interface APICommon<T = DEFAULT_HANDLER> { method: SUPPORT_METHODS; path: string; title: string; description?: string; handler?: T; response?: TYPE_RESPONSE; } export interface APIDefine<T> extends APICommon<T> { group?: string; headers?: Record<string, ISchemaType>; query?: Record<string, ISchemaType>; body?: Record<string, ISchemaType>; params?: Record<string, ISchemaType>; required?: string[]; requiredOneOf?: string[]; before?: Array<T>; middlewares?: Array<T>; handler?: T; mock?: Record<string, unknown>; } export interface APIOption<T> extends Record<string, unknown> { group: string; realPath: string; examples: IExample[]; beforeHooks: Set<T>; middlewares: Set<T>; required: Set<string>; requiredOneOf: string[][]; _allParams: Map<string, ISchemaType>; mock?: Record<string, unknown>; tested: boolean; response?: TYPE_RESPONSE; responseSchema?: SchemaType | ISchemaType; querySchema?: z.ZodObject<z.ZodRawShape>; bodySchema?: z.ZodObject<z.ZodRawShape>; paramsSchema?: z.ZodObject<z.ZodRawShape>; headersSchema?: z.ZodObject<z.ZodRawShape>; } export default class API<T = DEFAULT_HANDLER> { key: string; pathTestRegExp: RegExp; inited: boolean; options: APIOption<T>; /** * 构造函数 */ constructor(method: SUPPORT_METHODS, path: string, sourceFile: SourceResult, group?: string, prefix?: string); static define<T>(options: APIDefine<T>, sourceFile: SourceResult, group?: string, prefix?: string): API<T>; /** * 检查是否已经完成初始化,如果是则报错 */ private checkInited; /** * 检查URL是否符合API规则 */ pathTest(method: SUPPORT_METHODS, path: string): boolean; /** * API标题 */ title(title: string): this; /** * API描述 */ description(description: string): this; /** * API分组 */ group(group: string): this; private addExample; /** * API使用例子 */ example(example: IExample): this; /** * 输出结果对象 */ response(response: TYPE_RESPONSE): this; /** * 输入参数 */ private setParam; /** * 输入参数 */ private setParams; /** * 检测混合使用并设置 Zod Schema */ private setZodSchema; /** * 检测混合使用并设置 ISchemaType 参数 */ private checkMixedUsage; /** * Body 参数 - 支持 ISchemaType 和原生 Zod Schema */ body(obj: Record<string, ISchemaType> | ZodTypeAny): this; /** * Query 参数 - 支持 ISchemaType 和原生 Zod Schema */ query(obj: Record<string, ISchemaType> | ZodTypeAny): this; /** * Param 参数 - 支持 ISchemaType 和原生 Zod Schema */ params(obj: Record<string, ISchemaType> | ZodTypeAny): this; /** * Headers 参数 - 支持 ISchemaType 和原生 Zod Schema */ headers(obj: Record<string, ISchemaType> | ZodTypeAny): this; /** * 必填参数 */ required(list: string[]): this; /** * 多选一必填参数 */ requiredOneOf(list: string[]): this; /** * 中间件 */ middlewares(...list: Array<T>): this; /** * 注册执行之前的钩子 */ before(...list: Array<T>): this; /** * 注册处理函数 */ register(fn: T): this; /** * 注册强类型处理函数 (基于 zod schema) */ registerTyped<TQuery extends z.ZodRawShape = Record<string, never>, TBody extends z.ZodRawShape = Record<string, never>, TParams extends z.ZodRawShape = Record<string, never>, THeaders extends z.ZodRawShape = Record<string, never>, TResponse extends z.ZodTypeAny = z.ZodAny>(schemas: { query?: z.ZodObject<TQuery>; body?: z.ZodObject<TBody>; params?: z.ZodObject<TParams>; headers?: z.ZodObject<THeaders>; response?: TResponse; }, handler: (req: { query: z.infer<z.ZodObject<TQuery>>; body: z.infer<z.ZodObject<TBody>>; params: z.infer<z.ZodObject<TParams>>; headers: z.infer<z.ZodObject<THeaders>>; }, res: unknown) => z.infer<TResponse> | Promise<z.infer<TResponse>>): this; mock(data?: Record<string, unknown>): void; init(parent: ERest<unknown>): void; }