import { useTRPC, type RouterInputs, type RouterOutputs } from "../trpc"; import { useQueryClient } from "@tanstack/react-query"; import { useMutation, type UseMutationResult } from "@tanstack/react-query"; /** * 定义 MutationType 类型,用于提取指定实体类型的特定 mutation 方法名。 * @template T - 实体类型的键名(如 'post', 'user') * @description 该类型通过遍历 RouterInputs[T] 的键名,筛选出符合条件的 mutation 方法名(如 'create', 'update' 等)。 */ type MutationType = keyof { [K in keyof RouterInputs[T]]: K extends | "create" | "update" | "deleteMany" | "softDeleteByIds" | "restoreByIds" | "updateOrder" ? RouterInputs[T][K] : never; }; /** * 定义 MutationOptions 类型,用于配置特定 mutation 方法的回调函数。 * @template T - 实体类型的键名 * @template K - mutation 方法名 * @description 该类型包含一个可选的 onSuccess 回调函数,用于在 mutation 成功时执行。 */ type MutationOptions< T extends keyof RouterInputs, K extends MutationType, > = { onSuccess?: ( data: RouterOutputs[T][K], // mutation 成功后的返回数据 variables: RouterInputs[T][K], // mutation 的输入参数 context?: unknown // 可选的上下文信息 ) => void; }; /** * 定义 EntityOptions 类型,用于配置实体类型的所有 mutation 方法的回调函数。 * @template T - 实体类型的键名 * @description 该类型是一个对象,键为 mutation 方法名,值为对应的 MutationOptions 配置。 */ type EntityOptions = { [K in MutationType]?: MutationOptions; }; /** * 工具类型:更新为 TanStack Query 的 UseMutationResult 类型。 * @template T - 实体类型的键名 * @template K - mutation 方法名 * @description 该类型用于定义 mutation 函数的返回类型,适配新版 tRPC。 */ export type MutationResult< T extends keyof RouterInputs, K extends MutationType, > = UseMutationResult< RouterOutputs[T][K], // mutation 成功后的返回数据 Error, // mutation 的错误类型 RouterInputs[T][K], // mutation 的输入参数 unknown // mutation 的上下文类型 >; /** * 自定义 Hook:用于处理实体的 mutation 操作,并内置缓存失效机制。 * @template T - 实体类型的键名(如 'post', 'user') * @param {T} key - 实体键名 * @param {EntityOptions} [options] - 可选的 mutation 回调函数配置 * @returns 返回一个包含多个 mutation 函数的对象 * @description 该 Hook 封装了常见的 mutation 操作(如 create, update, deleteMany 等),并在每次 mutation 成功后自动失效相关缓存。 */ export function useEntity( key: T, options?: EntityOptions ) { const trpc = useTRPC(); const queryClient = useQueryClient(); /** * 创建 mutation 处理函数。 * @template K - mutation 方法名 * @param {K} mutation - mutation 方法名 * @returns 返回一个配置好的 mutation 函数 * @description 该函数根据传入的 mutation 方法名,生成对应的 mutation 函数,并配置 onSuccess 回调。 */ const createMutationHandler = >(mutation: K) => { // 获取对应的 tRPC mutation 配置 const mutationOptions = trpc[key as keyof typeof trpc][mutation as any].mutationOptions(); // 使用 TanStack Query 的 useMutation 创建 mutation return useMutation({ ...mutationOptions, onSuccess: (data, variables, context) => { // 调用原始配置的 onSuccess 回调(如果有) mutationOptions.onSuccess?.(data as any, variables as any, context); // 失效指定实体的缓存 queryClient.invalidateQueries({ queryKey: [key] }); // 调用用户自定义的 onSuccess 回调 options?.[mutation]?.onSuccess?.(data as any, variables as any, context); }, }) as MutationResult; }; // 返回包含多个 mutation 函数的对象 return { create: createMutationHandler("create"), createCourse: createMutationHandler("createCourse"), update: createMutationHandler("update"), deleteMany: createMutationHandler("deleteMany"), softDeleteByIds: createMutationHandler("softDeleteByIds"), restoreByIds: createMutationHandler("restoreByIds"), updateOrder: createMutationHandler("updateOrder"), updateOrderByIds: createMutationHandler("updateOrderByIds"), }; }