在 Convex 中编写 Query 与 Mutation 函数:基于 tsgo-test 示例的完整实战指南
数据库后端【免费下载链接】convex-backendThe open-source reactive database for app developers项目地址https://gitcode.com/gh_mirrors/co/convex-backend点击查看免费下载导读本文以开源仓库 convex-backend 中npm-packages/private-demos/tsgo-test演示项目为背景完整讲解 Convex 函数Functions目录的标准组织方式如何编写带参数校验Validator的 query 与 mutation 函数、如何在 React 客户端调用它们、如何通过 Convex CLI 将函数推送到部署环境以及如何用 TypeScript 7 原生编译器 tsgo 对函数进行类型检查。读完本文你将掌握一套可直接复制到任何 Convex 项目中的最小可运行函数代码骨架并理解其背后 CLI 类型检查的实现原理。一、Convex 函数目录是什么在 Convex 应用中服务端代码存放在项目的convex/目录中即函数目录。这个目录里的每个 TypeScript/JavaScript 文件都会被打包并在 Convex 的云端或自托管后端中执行构成应用的服务端逻辑。以仓库中的npm-packages/private-demos/tsgo-test/convex/目录为例其标准结构包含README.md官方生成的函数目录说明模板即本文依据的核心文档example.ts一个最小可运行的 query 函数示例_generated/由npx convex dev自动生成的类型与 API 绑定代码api.ts、server.ts、dataModel.ts等tsconfig.json用于对 Convex 函数做类型检查的 TypeScript 工程配置。_generated目录是自动生成、不应手工修改的。在 server.d.ts 文件头部明确写着THIS CODE IS AUTOMATICALLY GENERATED. To regenerate, runnpx convex dev.其中导出了query、mutation、action、internalQuery、internalMutation、httpAction等全部服务端函数构造器以及QueryCtx、MutationCtx、DatabaseReader、DatabaseWriter等上下文类型。这些类型化的导出正是下面所有函数示例的类型安全基础。二、编写一个带参数校验的 query 函数2.1 函数定义骨架query 函数用于读取数据库是 Convex 中默认只读、可被客户端订阅的函数。官方模板给出的标准写法如下对应文档原文可在 README.md 中查看// convex/myFunctions.ts import { query } from ./_generated/server; import { v } from convex/values; export const myQueryFunction query({ // Validators for arguments. args: { first: v.number(), second: v.string(), }, // Function implementation. handler: async (ctx, args) { // Read the database as many times as you need here. const documents await ctx.db.query(tablename).collect(); // Arguments passed from the client are properties of the args object. console.log(args.first, args.second); // Write arbitrary JavaScript here: filter, aggregate, build derived data, // remove non-public properties, or create new objects. return documents; }, });拆解这个骨架有三个关键点args中的 Validator 是 Convex 的核心安全机制v.number()、v.string()来自convex/values包运行时会对客户端传入的每个参数做校验类型不匹配的函数调用会被直接拒绝从而避免脏数据进入数据库查询。除上述两种外v还提供v.id()、v.object()、v.array()、v.union()、v.optional()等完整校验器集合并支持.optional()链式写法。handler的第一个参数ctx是函数上下文ctx.db提供数据库访问能力。对 query 而言ctx.db的类型是只读的DatabaseReader见 server.d.ts只能get、query无法写入。handler可以写任意 JS 逻辑在返回前进行过滤、聚合、派生数据、剥离非公开字段等处理都是推荐做法——这相当于把数据脱敏与业务加工放在服务端完成。2.2 最小可运行示例仓库里的真实代码上述模板是教学示例仓库中tsgo-test演示项目实际部署了一个极简 query 函数见 example.tsimport { query } from ./_generated/server; export const hello query({ args: {}, handler: async (): Promisestring { return Hello from TypeScript!; }, });这个hello函数没有参数args: {}不做任何数据库访问直接返回一个字符串。它虽然简单却完整演示了 Convex 函数的最小闭环定义 → 生成 API 绑定 → 被客户端调用。在生成产物 api.d.ts 中可以看到api对象通过ApiFromModules自动收集了example模块下所有导出的函数引用客户端即可通过api.example.hello类型安全地调用它。2.3 在 React 中调用 queryConvex 为 React 提供了useQueryHook模板中的用法如下const data useQuery(api.myFunctions.myQueryFunction, { first: 10, second: hello, });useQuery会自动完成三件事订阅该查询、在数据变化时触发组件重新渲染、在组件卸载时取消订阅。它接收的参数对象与args中声明的 Validator 一一对应类型由_generated/api.d.ts从函数定义中推导因此参数写错会在编译期直接报错。三、编写一个带参数校验的 mutation 函数3.1 函数定义骨架mutation 函数用于写入数据库也可读取并具备原子性保证。官方模板如下// convex/myFunctions.ts import { mutation } from ./_generated/server; import { v } from convex/values; export const myMutationFunction mutation({ // Validators for arguments. args: { first: v.string(), second: v.string(), }, // Function implementation. handler: async (ctx, args) { // Insert or modify documents in the database here. // Mutations can also read from the database like queries. const message { body: args.first, author: args.second }; const id await ctx.db.insert(messages, message); // Optionally, return a value from your mutation. return await ctx.db.get(messages, id); }, });关键差异点ctx.db是读写类型DatabaseWriter除get、query外还提供insert、patch、replace、delete等写操作原子性保证单个 mutation 内的所有写入会被原子地提交见 server.d.ts 中DatabaseWriter的文档注释不会出现写了一半的中间状态也天然规避了乐观并发控制下的部分写问题可以返回值handler的返回值会被序列化后传回客户端便于客户端拿到刚插入文档的_id做后续跳转或 UI 更新。3.2 在 React 中调用 mutationmutation 在 React 中通过useMutationHook 调用模板给出了两种典型用法const mutation useMutation(api.myFunctions.myMutationFunction); function handleButtonPress() { // fire and forget, the most common way to use mutations mutation({ first: Hello!, second: me }); // OR // use the result once the mutation has completed mutation({ first: Hello!, second: me }).then((result) console.log(result), ); }Fire-and-forget推荐多数 UI 场景下不关心返回值直接调用即可Convex 客户端会负责把结果同步到所有订阅相关查询的组件获取结果mutation(...)返回 Promise.then()中拿到的正是服务端handler的返回值如上面示例中插入后重新读回的完整文档。四、推送函数与 CLI 工具链4.1 常用 CLI 命令函数写好后需要通过 Convex CLI 与部署环境交互。文档明确给出了两条基础命令查看 CLI 全部能力在项目根目录运行npx convex -h启动本地文档运行npx convex docs会打开本地/在线的 Convex 文档站点。实际开发中最常用的还有npx convex dev本地开发模式持续监听convex/目录自动完成代码生成_generated与函数推送并启动本地后端npx convex deploy将函数推送到生产部署npx convex codegen --init在缺少convex/tsconfig.json时创建类型检查所需的工程配置。4.2 CLI 的类型检查实现CLI 在每次推送前都会对函数目录执行 TypeScript 类型检查。仓库中的核心实现在 typecheck.ts编译器解析优先级resolveTypescriptCompiler第33-39行CLI 命令行参数 →convex.json中的typescriptCompiler字段 → 默认tsc类型检查模式TypeCheckMode第21行enable失败即中止推送、try找不到编译器时降级跳过、disable完全跳过通过--typecheckdisable启用检查入口读取convex/tsconfig.json若不存在则跳过并提示运行npx convex codegen --init第120-128行慢检查提示当单次类型检查超过 10 秒阈值SLOW_TYPECHECK_THRESHOLD_MS时CLI 会切换 spinner 并给出性能排查建议第25-27行、第69-73行。4.3 使用 tsgoTypeScript 7 原生编译器tsgo-test这个演示项目的特殊之处正是用tsgoTypeScript 原生编译器即 TypeScript 7 的 Native Preview替代传统tsc做类型检查。其配置链条如下①convex.json指定编译器见 convex.json{ typescriptCompiler: tsgo, $schema: https://raw.githubusercontent.com/get-convex/convex-backend/refs/heads/main/npm-packages/convex/schemas/convex.schema.json }②package.json声明 tsgo 依赖见 package.json{ name: tsgo-test, version: 0.0.0, scripts: { build: tsgo --noEmit -p convex/tsconfig.json }, dependencies: { convex: workspace:* }, devDependencies: { typescript/native-preview: ~7.0.0-dev.20251205.1 } }这里typescript/native-preview就是 tsgo 的 npm 发行包build脚本直接以tsgo --noEmit -p convex/tsconfig.json方式对函数目录做纯类型检查不产出文件因此该脚本也可作为 CI 中独立于 Convex CLI 的类型检查步骤。仓库的 turbo.json 进一步注明该任务的outputs为空即只检查、无产物。③ CLI 如何定位 tsgo 可执行文件在 typecheck.ts 的findTypeScriptCompilerPath中tsgo会依次查找node_modules/typescript/native-preview/bin/tsgo与bin/tsgo.js两个候选路径tsc则会兼容 TypeScript 6/7 并存的场景依次查找node_modules/typescript/native/bin/tsc与node_modules/typescript/bin/tsc。若找不到编译器二进制CLI 会以cantTypeCheck结果降级处理。④ 版本兼容性注意typescriptCompiler字段目前在convex.jsonschema 中已被标记为deprecated见 convex.schema.json 与 CHANGELOG.md。原因是 TypeScript 7 正式发布后Convex CLI 会自动探测并选用原生编译器无需再显式配置但tsgo-test这类依赖 Native Preview 开发版的旧项目仍可通过该字段保持显式指定两者兼容。4.4 函数目录的 tsconfig.json 要点convex/tsconfig.json描述了函数运行环境的 TypeScript 配置其注释明确区分了可修改与必需两组选项见 tsconfig.json可自由修改allowJs、strict、moduleResolution: Bundler、jsx、skipLibCheck、allowSyntheticDefaultImportsConvex 必需勿改target: ESNext、lib: [ES2023, dom]、forceConsistentCasingInFileNames、module: ESNext、isolatedModules、noEmitinclude/excludeinclude: [./**/*]覆盖全部函数源码exclude: [./_generated]排除自动生成目录避免与手工源码重复检查。五、从模板到生产函数开发的最佳实践要点综合官方模板README.md与仓库实现可以把 Convex 函数开发的关键实践总结为以下几条始终为args声明 Validator这是客户端输入的第一道防线也是客户端类型推导的数据源空参数也应显式写args: {}参考hello函数查询逻辑尽量收敛到 query写入逻辑收敛到 mutationquery 只读、可订阅、可被自动缓存mutation 原子写入二者职责分离能让 UI 保持实时一致服务端完成数据加工过滤敏感字段、聚合、派生计算放在 handler 中而不是让客户端拿到全量数据把convex/下的 README 模板当作速查手册模板中 query/mutation 的完整骨架、React 调用示例、CLI 命令提示覆盖了 80% 的日常开发场景用 tsgo/tsc 做独立类型检查可将tsgo --noEmit -p convex/tsconfig.json或tsc等价命令接入 CI与npx convex deploy内置的类型检查形成双保险。六、参考资料官方函数目录模板README.md最小 query 函数实现example.ts自动生成的类型绑定server.d.ts、api.d.ts编译器与工程配置convex.json、tsconfig.json、package.jsonCLI 类型检查实现typecheck.tstypescriptCompiler配置项 schemaconvex.schema.json赞分享数据库后端【免费下载链接】convex-backendThe open-source reactive database for app developers项目地址https://gitcode.com/gh_mirrors/co/convex-backend点击查看免费下载相关推荐编写 Convex 函数从 query 到 mutation 的完整实战指南基于 convex-backend 开源仓库编写 Convex 函数从 query 到 mutation 的完整实战指南基于 convex backend 开源仓库 导读 本文围绕 convex b数据库后端Convex 函数开发实战指南在 Next.js 中编写 Query 与 Mutation基于 convex-backend 源码解析Convex 函数开发实战指南在 Next.js 中编写 Query 与 Mutation基于 convex backend 源码解析 本文以 conve数据库后端Convex 函数开发实战在 TanStack Start WorkOS 示例项目中编写 Query、Mutation 与 ActionConvex 函数开发实战在 TanStack Start WorkOS 示例项目中编写 Query、Mutation 与 Action 本文以开源仓库数据库后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

ESP32-P4 USB摄像头实战:从UVC协议到MJPEG拼帧显示

ESP32-P4 USB摄像头实战:从UVC协议到MJPEG拼帧显示

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 9:18:31 阅读更多 →
Relay Derived Fields 派生字段完全指南:用 `@rootFragment` 构建可组合、全局记忆化的客户端计算图

Relay Derived Fields 派生字段完全指南:用 `@rootFragment` 构建可组合、全局记忆化的客户端计算图

前端开发工具 【免费下载链接】relay Relay is a JavaScript framework for building data-driven React applications. 项目地址: https://gitcode.com/gh_mirrors/relay29/relay 点击查看 免费下载 本篇技术指南以 Relay v18 官方文档「Derived Fields」为核心&a…

2026/9/24 9:17:31 阅读更多 →
市场报告的脚注不能跳过:让 Agent 把每个数字和它的分母绑在一起

市场报告的脚注不能跳过:让 Agent 把每个数字和它的分母绑在一起

会议室里最容易被截图带走的东西,是一行漂亮的增长率。 设想某份市场报告写着"需求增长三成",Agent 把它放进了结论页。有人继续往下翻,才发现脚注写着:统计对象只包括接受问卷的四十家样本企业,观察期只有两…

2026/9/24 9:17:31 阅读更多 →

最新新闻

Juniper SRX防火墙HA双机配置实战:Chassis Cluster部署与切换验证

Juniper SRX防火墙HA双机配置实战:Chassis Cluster部署与切换验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 10:01:02 阅读更多 →
基于Python的书籍推荐系统设计与实现:从协同过滤到混合策略

基于Python的书籍推荐系统设计与实现:从协同过滤到混合策略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 10:01:02 阅读更多 →
MCP安全系列之意图流颠覆

MCP安全系列之意图流颠覆

MCP安全系列之意图流颠覆 介绍 意图流颠覆相当于模型本来要去做A任务,我们通过注入让其去做B任务,或者是影响A任务的结果,即改变了Agent原本的任务流。我们这里通过一个简单代码审计示例来复现下。 复现 这里直接用CherryStudio自带的文件读取…

2026/9/24 10:01:02 阅读更多 →
投了100份海外简历0回复?直到我发现了这个AI海外求职外挂

投了100份海外简历0回复?直到我发现了这个AI海外求职外挂

1. 为什么海投100份简历,却收不到一个回复?很多留学生和远程求职者都有过这样的经历:精心准备的简历投出去上百份,邮箱却始终静悄悄。问题往往不在你的能力,而在于海投的方式本身——简历与岗位不匹配、投递时机不对、…

2026/9/24 10:01:02 阅读更多 →
麦芽AI vs Cursor:产研协作范式的选择逻辑

麦芽AI vs Cursor:产研协作范式的选择逻辑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 10:00:02 阅读更多 →
Allegro覆铜异常:Unassigned与Out of Date Shapes排查

Allegro覆铜异常:Unassigned与Out of Date Shapes排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 10:00:02 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →