116 lines
4.3 KiB
TypeScript
Executable File
116 lines
4.3 KiB
TypeScript
Executable File
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<T extends keyof RouterInputs> = 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<T>,
|
||
> = {
|
||
onSuccess?: (
|
||
data: RouterOutputs[T][K], // mutation 成功后的返回数据
|
||
variables: RouterInputs[T][K], // mutation 的输入参数
|
||
context?: unknown // 可选的上下文信息
|
||
) => void;
|
||
};
|
||
|
||
/**
|
||
* 定义 EntityOptions 类型,用于配置实体类型的所有 mutation 方法的回调函数。
|
||
* @template T - 实体类型的键名
|
||
* @description 该类型是一个对象,键为 mutation 方法名,值为对应的 MutationOptions 配置。
|
||
*/
|
||
type EntityOptions<T extends keyof RouterInputs> = {
|
||
[K in MutationType<T>]?: MutationOptions<T, K>;
|
||
};
|
||
|
||
/**
|
||
* 工具类型:更新为 TanStack Query 的 UseMutationResult 类型。
|
||
* @template T - 实体类型的键名
|
||
* @template K - mutation 方法名
|
||
* @description 该类型用于定义 mutation 函数的返回类型,适配新版 tRPC。
|
||
*/
|
||
export type MutationResult<
|
||
T extends keyof RouterInputs,
|
||
K extends MutationType<T>,
|
||
> = UseMutationResult<
|
||
RouterOutputs[T][K], // mutation 成功后的返回数据
|
||
Error, // mutation 的错误类型
|
||
RouterInputs[T][K], // mutation 的输入参数
|
||
unknown // mutation 的上下文类型
|
||
>;
|
||
|
||
/**
|
||
* 自定义 Hook:用于处理实体的 mutation 操作,并内置缓存失效机制。
|
||
* @template T - 实体类型的键名(如 'post', 'user')
|
||
* @param {T} key - 实体键名
|
||
* @param {EntityOptions<T>} [options] - 可选的 mutation 回调函数配置
|
||
* @returns 返回一个包含多个 mutation 函数的对象
|
||
* @description 该 Hook 封装了常见的 mutation 操作(如 create, update, deleteMany 等),并在每次 mutation 成功后自动失效相关缓存。
|
||
*/
|
||
export function useEntity<T extends keyof RouterInputs>(
|
||
key: T,
|
||
options?: EntityOptions<T>
|
||
) {
|
||
const trpc = useTRPC();
|
||
const queryClient = useQueryClient();
|
||
/**
|
||
* 创建 mutation 处理函数。
|
||
* @template K - mutation 方法名
|
||
* @param {K} mutation - mutation 方法名
|
||
* @returns 返回一个配置好的 mutation 函数
|
||
* @description 该函数根据传入的 mutation 方法名,生成对应的 mutation 函数,并配置 onSuccess 回调。
|
||
*/
|
||
|
||
const createMutationHandler = <K extends MutationType<T>>(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<T, K>;
|
||
};
|
||
|
||
// 返回包含多个 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"),
|
||
};
|
||
}
|