import type { Standard } from "#Source/validation/index.ts" export interface ApiSchemaOptions< Path extends string, Method extends "get" | "post", InputQuerySchema extends Standard.Schema, InputBodySchema extends Standard.Schema, OutputErrorSchema extends Standard.Schema, OutputSuccessSchema extends Standard.Schema, > { path: Path method: Method inputQuerySchema: InputQuerySchema inputBodySchema: InputBodySchema outputErrorSchema: OutputErrorSchema outputSuccessSchema: OutputSuccessSchema } /** * @description 每一个请求都由一个且仅由一个接口(Api)处理。每个 Api 在实现之前需要对其进行描述, * 描述中包含此接口处理的路径(Path)、方法(Method)、query 输入的数据形状(InputQuerySchema)、 * body 输入的数据形状(InputBodySchema)、错误输出的数据形状(OutputErrorSchema)和成功输出的数据形状 * (OutputSuccessSchema)等,这些描述共同构成 ApiSchema。 * * 具体来说: * - path:不能有通配符, 必须是完整的, 具体的路径。 * - method:暂时只支持 get 和 post。 * - inputQuerySchema:描述接口 query 输入的数据形状。 * - inputBodySchema:描述接口 body 输入的数据形状。 * - outputErrorSchema:描述接口失败输出的数据形状。 * - outputSuccessSchema:描述接口成功输出的数据形状。 * * ApiSchema 的主要用途是定义接口的类型,将接口的类型和实现分开,提高代码的可读性和 * 可维护性的同时让我们能够将接口类型独立导出给前端。 */ export class ApiSchema< Path extends string, Method extends "get" | "post", InputQuerySchema extends Standard.Schema, InputBodySchema extends Standard.Schema, OutputErrorSchema extends Standard.Schema, OutputSuccessSchema extends Standard.Schema, > { protected __PathPhantomType__?: Path protected __MethodPhantomType__?: Method protected __InputQuerySchemaPhantomType__?: InputQuerySchema protected __InputBodySchemaPhantomType__?: InputBodySchema protected __OutputErrorSchemaPhantomType__?: OutputErrorSchema protected __OutputSuccessSchemaPhantomType__?: OutputSuccessSchema private readonly path: Path private readonly method: Method private readonly inputQuerySchema: InputQuerySchema private readonly inputBodySchema: InputBodySchema private readonly outputSuccessSchema: OutputSuccessSchema private readonly outputErrorSchema: OutputErrorSchema constructor( options: ApiSchemaOptions< Path, Method, InputQuerySchema, InputBodySchema, OutputErrorSchema, OutputSuccessSchema >, ) { this.path = options.path this.method = options.method this.inputQuerySchema = options.inputQuerySchema this.inputBodySchema = options.inputBodySchema this.outputErrorSchema = options.outputErrorSchema this.outputSuccessSchema = options.outputSuccessSchema } getApiSchemaOptions(): ApiSchemaOptions< Path, Method, InputQuerySchema, InputBodySchema, OutputErrorSchema, OutputSuccessSchema > { return { path: this.path, method: this.method, inputQuerySchema: this.inputQuerySchema, inputBodySchema: this.inputBodySchema, outputErrorSchema: this.outputErrorSchema, outputSuccessSchema: this.outputSuccessSchema, } } getPath(): Path { return this.path } getMethod(): Method { return this.method } getInputQuerySchema(): InputQuerySchema { return this.inputQuerySchema } getInputBodySchema(): InputBodySchema { return this.inputBodySchema } getOutputErrorSchema(): OutputErrorSchema { return this.outputErrorSchema } getOutputSuccessSchema(): OutputSuccessSchema { return this.outputSuccessSchema } } export const createApiSchema = < Path extends string, Method extends "get" | "post", InputQuerySchema extends Standard.Schema, InputBodySchema extends Standard.Schema, OutputErrorSchema extends Standard.Schema, OutputSuccessSchema extends Standard.Schema, >( options: ApiSchemaOptions< Path, Method, InputQuerySchema, InputBodySchema, OutputErrorSchema, OutputSuccessSchema >, ): ApiSchema< Path, Method, InputQuerySchema, InputBodySchema, OutputErrorSchema, OutputSuccessSchema > => { return new ApiSchema(options) } // oxlint-disable-next-line typescript/no-explicit-any export type AnyApiSchema = ApiSchema export type GetInputQuerySchemaFromApiSchema = Target extends ApiSchema< infer _, infer __, infer InputQuerySchema, infer ___, infer ____, infer ______ > ? InputQuerySchema : never export type GetInputBodySchemaFromApiSchema = Target extends ApiSchema< infer _, infer __, infer ___, infer InputBodySchema, infer ____, infer ______ > ? InputBodySchema : never export type GetOutputErrorSchemaFromApiSchema = Target extends ApiSchema< infer _, infer __, infer ___, infer ____, infer OutputErrorSchema, infer _____ > ? OutputErrorSchema : never export type GetOutputSuccessSchemaFromApiSchema = Target extends ApiSchema< infer _, infer __, infer ___, infer ____, infer ______, infer OutputSuccessSchema > ? OutputSuccessSchema : never export type GetInputQueryFromApiSchema = Standard.Schema.InferOutput< GetInputQuerySchemaFromApiSchema > export type GetInputBodyFromApiSchema = Standard.Schema.InferOutput< GetInputBodySchemaFromApiSchema > export type GetOutputErrorFromApiSchema = Standard.Schema.InferOutput< GetOutputErrorSchemaFromApiSchema > export type GetOutputSuccessFromApiSchema = Standard.Schema.InferOutput> export type GetOutputFromApiSchema = | GetOutputErrorFromApiSchema | GetOutputSuccessFromApiSchema