/** * ORPC 同构客户端 * * 根据运行环境自动选择最优调用方式: * - SSR (服务端): 直接调用 router,无 HTTP 开销 * - CSR (客户端): 通过 /api/rpc 端点 HTTP 调用 * * 同时配置了 TanStack Query 集成,mutation 成功后自动刷新相关查询。 */ import { createORPCClient } from '@orpc/client' import { RPCLink } from '@orpc/client/fetch' import { createRouterClient } from '@orpc/server' import { createTanstackQueryUtils } from '@orpc/tanstack-query' import { createIsomorphicFn } from '@tanstack/react-start' import { getRequestHeaders } from '@tanstack/react-start/server' import { router } from './router' import type { RouterClient } from './types' /** * 创建同构 ORPC 客户端 * * 服务端: 直接调用路由处理器 * 客户端: 通过 HTTP 调用 /api/rpc 端点 */ const getORPCClient = createIsomorphicFn() .server(() => createRouterClient(router, { context: () => ({ headers: getRequestHeaders(), }), }), ) .client(() => { const link = new RPCLink({ url: `${window.location.origin}/api/rpc`, }) return createORPCClient(link) }) const client: RouterClient = getORPCClient() /** * ORPC + TanStack Query 工具 * * 使用方式: * ```tsx * // 查询 * const { data } = useSuspenseQuery(orpc.todo.list.queryOptions()) * * // 变更 * const mutation = useMutation(orpc.todo.create.mutationOptions()) * mutation.mutate({ title: '新任务' }) * ``` * * 配置了自动缓存失效: 创建/更新/删除操作后自动刷新列表 */ export const orpc = createTanstackQueryUtils(client, { // 配置 mutation 成功后自动刷新相关查询 experimental_defaults: { todo: { create: { mutationOptions: { onSuccess: (_, __, ___, ctx) => { ctx.client.invalidateQueries({ queryKey: orpc.todo.list.key() }) }, }, }, update: { mutationOptions: { onSuccess: (_, __, ___, ctx) => { ctx.client.invalidateQueries({ queryKey: orpc.todo.list.key() }) }, }, }, remove: { mutationOptions: { onSuccess: (_, __, ___, ctx) => { ctx.client.invalidateQueries({ queryKey: orpc.todo.list.key() }) }, }, }, }, }, })