fenghuo/packages/client/src/api/hooks/useEntity.ts

116 lines
4.3 KiB
TypeScript
Raw Normal View History

2025-05-26 19:56:34 +08:00
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"),
};
}