@codewithagents/openapi-react-query

中文文档
3.13.0发布于 2026/11/03MITTypeScriptES Module构建来源已验证近 30 天下载 4069

从 OpenAPI 3.1 字符串生成已键入的回放查询 v5 钩

中文使用文档
文档目录17 节
  1. 安装
  2. 配置
  3. 生成
  4. 产生什么
  5. 类型 select 变换
  6. 按状态输入错误
  7. 动态并行查询
  8. Next.js App 路由器 SSR 预选
  9. 悬浮变种
  10. 突变成功时自动验证
  11. 优化更新
  12. 资源缓存时间
  13. 用这个
  14. 多个规格
  15. 测试
  16. 解决问题
  17. 许可证

@ code with agents/ openapi- react- query (英语)

npm CI codecov CodeQL

📖 完整文档

@codewithagents/openapi-react-query 是一个 OpenAPI React 查询码源工具, 生成已键入的 TanStack 查询 v5 hooks ()useQuery, (中文(简体) ), useMutation,关键工厂)直接取自您 OpenAPI 3.1 spec,没有手写锅炉板,并且完全TypeScript严格规范的遵守.

  • 每个操作一个钩子(单位:千美元) useQuery 每个获取和一个 useMutation 每写一篇。 类型直接取自生成的客户端,不重复.
  • queryOptions() 工厂: 一个平原 xxxQueryOptions() 工厂和工厂 useQuery 钩,启用 queryClient.prefetchQuery() 在 Next.js App 路由器服务器组件和 <HydrationBoundary> SSR图案.
  • 智能细节钩: 路径- 参数钩钩在参数时自动禁用 null 或者说 undefined。无 enabled: !!id 在每一个呼叫网站.
  • 包括主要工厂: 每个资源的结构化缓存密钥( q)all(), (中文(简体) ), list(params), (中文(简体) ), detail(id)) 用于一贯无效.
  • 变异时自动生效设置 auto_invalidate: true 和突变钩使关于成功的相关查询无效,没有 useQueryClient 需要锅炉板.
  • 悬浮变种设置 suspense: true 生成 useSuspense* 钩子和每个查询钩一起.
  • 高级清洁输出: 每一份生成的文件通行证 prettier --check 从盒子里出来.

此软件包会消耗已键入的获取客户端 openapi-zod-ts它有运行时间依赖它,所以 openapi-zod-ts 必须先跑。 生成的钩子直接取自该客户端输出的数据和可变类型. 它与工具链中的其他发电机并列, @codewithagents/openapi-server (服务接口加可选) hono | express | fastify | none 路由器)和 @codewithagents/openapi-msw (种子MSW v2 处理器),加 @codewithagents/api-errors 运行时间助手。 见 petstore-快取演示 用来证明这些东西是连在一起的.

安装

npm install -D @codewithagents/openapi-react-query openapi-zod-ts
npm install @tanstack/react-query

@tanstack/react-query ^5 是一个对等的依赖,而 React Query v5 需要 React 18 或 later. openapi-zod-ts 是此生成器的运行时间依赖, 必须先输出其客户端( 见 生成) (中文(简体) ).

配置

见 完整配置参考 所有选项,包括 overrides 编辑 --config CLI旗.

创建 openapi-react-query.config.json 在您的工程根中 :

{
  "input_openapi": "./openapi.json",
  "output": "./src/api",
  "stale_time": 30000,
  "gc_time": 300000,
  "suspense": false,
  "auto_invalidate": false,
  "infinite_query": "auto"
}
外地需求默认说明
input_openapi对无OpenAPI 3.x spec( JSON 或 YAML) 光谱
output对无写入生成文件的目录( 与 Openapi- zod- ts 输出相同)
stale_time没有0staleTime 适用于所有 useQuery 钩子
gc_time没有300000gcTime 适用于所有 useQuery 钩子
suspense没有false何时 true生成一个 useSuspense* 变量与每个查询钩
auto_invalidate没有false何时 true, 变异钩子自动验证成功相关查询
infinite_query没有'auto'boolean | 'auto'生成 a useXxxInfinite 标签列表操作的钩子 . 'auto' (一) 检测被粘合物得到; true 力量生成, false 关闭它
typed_errors没有false何时 true,会键入其错误作为客户端的过操作错误别名(例如. GetTaskError),这样 error.status 缩进 error.body (见 按状态输入错误(中文(简体) )
queries没有false何时 true生成一个 useXxxQueries(paramsList, options?, combine?) 每个带有参数的 GET 操作, 用于动态的并行查询( 见 动态并行查询(中文(简体) )
optimistic_updates没有false何时 true,变异钩接受 optimistic: { queryKey, updater } 选项,在请求前更新缓存并返回出错(参见 优化更新(中文(简体) )
overrides没有无资源缓存时间(见 资源缓存时间(中文(简体) )

生成

先运行两个发电机, openapi- zod- ts :

npx openapi-zod-ts
npx openapi-react-query

或加进 package.json数字 :

{
  "scripts": {
    "generate": "openapi-zod-ts && openapi-react-query"
  }
}

试钩? 输出目录也获得生成 test-utils.ts 与 createTestQueryClient() (不复试, gcTime: 0和 createWrapper() 联合国 QueryClientProvider 包装 renderHook),所以你不会手写设置。 见 测试。 。 。 .

产生什么

说到这个 /tasks 资源, hooks.ts 包含:

钥匙厂: 每个资源一个, 用于缓存无效 :

// Key factory (id stays string here; the hook widens it to allow undefined/null)
export const taskKeys = {
  all: () => ['tasks'] as const,
  list: (params?) => ['tasks', 'list', params] as const,
  detail: (id: string) => ['tasks', id] as const,
}

查询选项厂: 每个 GET 操作一次, 用于 RSC / 服务器侧前置 :

// Plain function, no hooks, safe to call in any context (RSC, loaders, tests)
export function listTasksQueryOptions(params?, options?) {
  return queryOptions({
    queryKey: taskKeys.list(params),
    queryFn: () => listTasks(params),
    staleTime: 30000,
    gcTime: 300000,
    ...options,
  })
}

export function getTaskQueryOptions(id: string, options?) {
  return queryOptions({
    queryKey: taskKeys.detail(id),
    queryFn: () => getTask(id),
    staleTime: 30000,
    gcTime: 300000,
    ...options,
  })
}

查询钩: 一次操作,消耗上面的工厂:

export function useListTasks(params?, options?) {
  return useQuery({
    queryKey: taskKeys.list(params),
    queryFn: () => listTasks(params),
    staleTime: 30000,
    gcTime: 300000,
    ...options,   // override any option per call site
  })
}

// Detail hook: id widened to allow undefined/null, auto-disabled until id is set
export function useGetTask(
  id: string | undefined | null,
  options?,
) {
  return useQuery({
    queryKey: taskKeys.detail(id!),
    queryFn: () => getTask(id!),
    enabled: id != null && (options?.enabled ?? true),
    ...options,
  })
}

详细钩子( 带有路径参数的钩子) 当参数是 null 或者说 undefined没有了 enabled: !!id 在每一个呼叫网站.

变形钩:每个POST/PUT/PATCH/DELETE:

export function useCreateTask(options?) {
  return useMutation({ mutationFn: (vars) => createTask(vars), ...options })
}

export function useUpdateTask(options?) {
  return useMutation({ mutationFn: ({ id, body }) => updateTask(id, body), ...options })
}

所有类型来自生成的客户端, 不重复 :

  • 数据类型 : Awaited<ReturnType<typeof listTasks>>
  • 变量类型 : Parameters<typeof createTask>[0]

类型 select 变换

每个查询钩, queryOptions 工厂, useSuspense* 钩子和 useXxxInfinite 钩子取出 TData 默认为响应类型。 A 类 select 因此,改变类型 data数字 :

const { data } = useGetTask(id, { select: (task) => task.title })
//      ^? string | undefined

const { data: count } = useListTasks({}, { select: (page) => page.items.length })
//      ^? number | undefined

// The queryOptions factory carries the select type into useQuery / useQueries
useQuery(getTaskQueryOptions(id, { select: (task) => task.id }))

无 select, (中文(简体) ), data 仍然为原始响应类型,所以现有的呼叫站点(包括明确 UseQueryResult<Task, ApiError> 说明)继续编译.

按状态输入错误

openapi-zod-ts 导出一个操作错误别名 client.ts 对于每个明确记录的操作 4xx 编号 : 5xx 答复,例如:. export type GetTaskError = ApiError<404, NotFound> | ApiError<422, ValidationProblem>与 typed_errors: true 钩子作为错误类型:

const { error } = useGetTask(id)
if (error?.status === 422) {
  error.body.errors // ValidationProblem
}

useCreateTask({
  onError: (error) => {
    if (error.status === 409) toast(error.body.message)
  },
})

没有记录错误状态的操作保留 ApiError。这是选入,因为别名只列出 文档 状态:与无证件状态的现有比较error.status === 500) 一旦类型缩小,停止编译,运行时的无证状态仍被抛出为平原 ApiError。 。 。 .

动态并行查询

何时 queries: true 在配置中,每个需要参数的 GET 操作也会得到一个 useXxxQueries 钩: a useQueries 将每个查询与操作的 xxxQueryOptions 工厂,所以缓存键,时间和 queryFn 和单管钩完全吻合.

// One argument (a path param or the params object): pass the values directly
const results = useGetTaskQueries(taskIds) // UseQueryResult<Task, ApiError>[]

// Several arguments: pass one tuple per query, in client-function order
const repos = useGetRepoQueries([
  ['acme', 'web', { ref: 'main' }],
  ['acme', 'api', { ref: 'main' }],
])

// Shared options apply to every query; `combine` reduces the results
const titles = useGetTaskQueries(taskIds, { staleTime: 60_000 }, (results) =>
  results.flatMap((r) => (r.data ? [r.data.title] : []))
)

没有参数的操作得到否 useXxxQueries 钩子(没有变化). 与 typed_errors: true 结果使用过操作错误的别名.

Next.js App 路由器 SSR 预选

生成的 queryOptions 工厂在React Server组件公司(RSC)工作,没有任何客户范围的工作。 服务器上的预选,然后将脱水缓存传递给客户端:

// app/tasks/page.tsx  (React Server Component)
import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'
import { listTasksQueryOptions } from '@/src/api/hooks'
import { TaskList } from './TaskList'

export default async function TasksPage() {
  const queryClient = new QueryClient()
  await queryClient.prefetchQuery(listTasksQueryOptions())
  // or with params: listTasksQueryOptions({ status: 'open' })

  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <TaskList />
    </HydrationBoundary>
  )
}
// app/tasks/TaskList.tsx  ('use client')
'use client'
import { useListTasks } from '@/src/api/hooks'

export function TaskList() {
  // Cache is already populated from the server; renders without a loading state
  const { data } = useListTasks()
  return <ul>{data?.map(t => <li key={t.id}>{t.title}</li>)}</ul>
}

细节页中,将 id 传递为普通字符串(工厂不会扩大为 string | undefined | null:

// app/tasks/[id]/page.tsx  (React Server Component)
import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query'
import { getTaskQueryOptions } from '@/src/api/hooks'
import { TaskDetail } from './TaskDetail'

export default async function TaskPage({ params }: { params: { id: string } }) {
  const queryClient = new QueryClient()
  await queryClient.prefetchQuery(getTaskQueryOptions(params.id))

  return (
    <HydrationBoundary state={dehydrate(queryClient)}>
      <TaskDetail id={params.id} />
    </HydrationBoundary>
  )
}

这个 queryOptions 工厂也与 useSuspenseQuery 在呼叫现场:

const { data } = useSuspenseQuery(getTaskQueryOptions(id))

悬浮变种

何时 suspense: true 在配置中,a useSuspense* 钩子与每个查询钩子一起生成 :

// Regular hook (always generated)
const { data, isLoading } = useGetTask(id)

// Suspense variant (generated when suspense: true)
// data is never undefined: wrap parent in <Suspense fallback={...}>
const { data } = useSuspenseGetTask(id)

与反应有关的工作 18 <Suspense> 边框和 Next.js App 路由器装入状态.

突变成功时自动验证

何时 auto_invalidate: true 在配置中,变异钩子在成功时会自动使相关的缓存条目无效。 没有 useQueryClient 在呼叫地点的锅炉板:

// With auto_invalidate: true, invalidation is generated inside the hook
const create = useCreateTask()
create.mutate({ title: 'New task' })
// taskKeys.all() is automatically invalidated on success

const update = useUpdateTask()
update.mutate({ id: '123', body: { title: 'Updated' } })
// taskKeys.all() AND taskKeys.detail('123') are invalidated on success

无效范围 :

  • POST − 无效 resourceKeys.all()
  • PUT 编号 : PATCH − 无效 resourceKeys.all() + 键 resourceKeys.detail(id)
  • DELETE − 无效 resourceKeys.all()

 onSuccess 回调( 如果提供在内) options)在无效后调用.

优化更新

何时 optimistic_updates: true 在配置中,每个突变钩都接受一个 optimistic 选项执行 TanStack 查询 v5 乐观更新配方:

const update = useUpdateTask({
  optimistic: {
    // static key, or derived from the mutation variables
    queryKey: (vars) => taskKeys.detail(vars.id),
    // annotate `old` to type the cache entry
    updater: (old: Task | undefined, vars) => old && { ...old, ...vars.body },
  },
})
update.mutate({ id: '123', body: { title: 'Renamed' } }) // the UI updates immediately

生成的钩子所做的:

  • 调试数字 : cancelQueries 对于键(因此飞行中获取不能覆盖乐观值),快照 getQueryData,则 setQueryData 还有你的 updater。 。 。 .
  • 错误: 恢复快照(或者如果条目之前没有被缓存的话重新发送).
  • 已解决: 使密钥无效, 使服务器状态获胜 .

属于你的 onMutate 编号 : onError 编号 : onSuccess 编号 : onSettled 仍然运行. onMutate 运行在乐观的写法之后,不管它返回到什么位置,都会作为上下文传递给您其他的回调,就像没有选项一样。 与 auto_invalidate: true 资源无效也取决于成功与否。 没有 optimistic 选择钩子的行为与普通突变完全相同。 钩子导出 OptimisticUpdate<TVariables, TQueryData> 财务报告和审定财务报表 OptimisticContext<TContext> 类型.

资源缓存时间

使用 overrides 在配置中设置不同的 staleTime 编号 : gcTime 每个资源 :

{
  "input_openapi": "./openapi.json",
  "output": "./src/api",
  "stale_time": 30000,
  "gc_time": 300000,
  "overrides": {
    "platforms": { "stale_time": 86400000 },
    "settings": { "stale_time": 5000, "gc_time": 60000 }
  }
}

超接键是API路径中出现的资源名称(例如. platforms 页:1 /api/v1/platforms) (中文(简体) ). 非重叠资源使用全球 stale_time 编号 : gc_time。 。 。 .

用这个

import { useListTasks, useCreateTask } from './src/api/hooks'

function TaskList() {
  const { data, isLoading } = useListTasks({ status: 'open' })

  // With auto_invalidate: true, useCreateTask invalidates taskKeys.all() automatically
  const create = useCreateTask()

  if (isLoading) return <Spinner />
  return (
    <>
      {data?.map(task => <Task key={task.id} task={task} />)}
      <button onClick={() => create.mutate({ title: 'New task' })}>Add</button>
    </>
  )
}

多个规格

使用 --config 指向每个供应商不同的配置文件:

npx openapi-zod-ts --config ./config/payments.config.json
npx openapi-react-query --config ./config/payments.config.json

配置文件目录中每个配置解析中的相对路径 .

测试

发电机还产生一个 test-utils.ts 文件并列 hooks.ts出口 createTestQueryClient() 财务报告和审定财务报表 createWrapper() 以去除测试锅炉板。 见 测试你的钩子 用于使用MSW复制可复制的 Vitest 示例.

为了嘲笑HTTP层 这些测试击中, @codewithagents/openapi-msw 生成来自同一 OpenAPI spec 的种子 MSW v2 处理器,因此请求会模拟与客户端同步 hooks call.

解决问题

见 解决问题 用于常见问题的文档中 : 缓存不无效, 细节钩用无效的 ID 点火, 以及 钩子不在 React Server 组件中工作.

许可证

麻省理工学院

版本与发布记录

@codewithagents/openapi-react-query 共发布 33 个版本,首次发布于 2026/05/24;过去 12 个月发布了 33 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
3.13.0latest2026/11/036 天前
3.12.32026/11/037 天前
3.12.22026/06/224 个月前
3.12.12026/06/154 个月前
3.12.02026/06/114 个月前
3.11.02026/06/055 个月前

关于 @codewithagents/openapi-react-query 的常见问题

@codewithagents/openapi-react-query 是什么?

从 OpenAPI 3.1 字符串生成已键入的回放查询 v5 钩

如何安装 @codewithagents/openapi-react-query?

在项目目录运行 npm install @codewithagents/openapi-react-query,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@tanstack/react-query(^5.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。它还提供命令行工具 openapi-react-query,可以用 npx openapi-react-query 直接运行。

@codewithagents/openapi-react-query 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@codewithagents/openapi-react-query 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@codewithagents/openapi-react-query 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.19.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@codewithagents/openapi-react-query 可以商用吗?

@codewithagents/openapi-react-query 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@codewithagents/openapi-react-query 的下载量有多少?

根据 npm 官方下载统计,@codewithagents/openapi-react-query 在 2026/10/10 – 2026/11/08 这 30 天内被下载 4,069 次,日均约 136 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@codewithagents/openapi-react-query 还在维护吗?

最新版本 3.13.0 发布于 2026/11/03(6 天前);至今共发布 33 个版本,其中过去 12 个月发布了 33 个;首次发布于 2026/05/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。