erest
Version:
Easy to build api server depend on @leizm/web and express.
168 lines (167 loc) • 5.15 kB
TypeScript
/**
* @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;
}