用途
convex-create-component 用于在 Convex 项目中创建可复用的组件(component)。这些组件拥有隔离的数据表以及面向上层应用的 API,目标是让边界清晰、应用侧接口保持精简。
适用场景包括:
- 在已有应用中创建新的 Convex 组件
- 将可复用的后端逻辑抽取成组件
- 构建应拥有自有表与工作流的第三方集成
- 将 Convex 功能打包,以便在多个应用间复用
不适用场景包括:
- 属于主应用的一次性业务逻辑
- 不需要 Convex 表或函数的轻量工具
- 应留在 convex/ 中的应用级编排
- 普通 TypeScript 库即可满足的情况
主要能力
该技能提供一套完整的工作流:
- 向用户确认要构建的内容与最终目标。若仓库已能明确答案,先说明并确认再继续。
- 通过决策树选择组件形态,并读取对应参考文件。
- 判断是否真的需要组件。若功能不需要隔离表、后端函数或可复用持久状态,优先使用普通应用代码或常规库。
- 制定简短计划,涵盖:组件拥有哪些表、暴露哪些公开函数、应用需传入哪些数据(认证、环境变量、父级 ID)、哪些内容作为包装器或 HTTP 挂载留在应用侧。
- 创建组件结构,包括 convex.config.ts、schema.ts 与函数文件。
- 使用组件自身的 ./_generated/server 导入实现函数,而非应用生成的导入文件。
- 通过 app.use(...) 将组件接入应用。若应用尚无 convex/convex.config.ts,则创建它。
- 在应用侧通过 components.<name> 并使用 ctx.runQuery、ctx.runMutation 或 ctx.runAction 调用组件。
- 若 React 客户端、HTTP 调用方或公开 API 需要访问,在应用侧创建包装函数,而不是直接暴露组件函数。
- 运行 npx convex dev,在完成前修复代码生成、类型或边界问题。
形态选择
根据目标选择一种路径:
- 仅用于本应用的组件:本地(Local),参考 references/local-components.md
- 发布或跨应用共享:打包(Packaged),参考 references/packaged-components.md
- 用户明确需要本地 + 共享库代码:混合(Hybrid),参考 references/hybrid-components.md
- 不确定:默认本地,参考 references/local-components.md
在继续前只读取其中一个参考文件。除非用户明确需要 npm 包,否则默认使用本地组件:放在 convex/components/<componentName>/ 下,用自身 convex.config.ts 中的 defineComponent(...) 定义,在应用的 convex/convex.config.ts 中通过 app.use(...) 安装,让 npx convex dev 生成组件自身的 _generated/ 文件。
使用方式
该技能给出一个包含表与两个函数的最小本地组件骨架,以及应用接入代码。组件内部函数从组件自身的 ./_generated/server.js 导入 mutation、query,并在应用侧包装函数中通过 components.notifications.lib.send 这类路径调用。注意引用路径形态:convex/components/notifications/lib.ts 中的函数在应用侧被调用为 components.notifications.lib.send。
关于认证与环境访问:组件代码不能依赖应用认证或环境变量。应用侧解析认证与环境后传入显式值,例如由应用获取 userId、读取 process.env.OPENAI_API_KEY,再通过 ctx.runAction 将 userId、apiKey、text 传给组件。
关于面向客户端的 API:不应假设组件函数可直接被客户端调用,应通过应用侧的 mutation 或 query 重新导出、包装。
关于跨边界 ID:父应用表 ID 在边界处应视为字符串,组件参数使用 v.string() 而非 v.id("users")。
关键规则
- 认证保留在应用侧,因为组件内不可用 ctx.auth。
- 环境访问保留在应用侧,因为组件函数无法读取 process.env。
- 父应用 ID 以字符串跨边界传递,因为 Id 类型在面向上层应用的 ComponentApi 中会变成普通字符串。
- 组件参数或 schema 中不要对应用拥有的表使用 v.id("parentTable"),因为组件无法访问应用的表命名空间。
- 从组件自身的 ./_generated/server 导入 query、mutation、action,而非应用生成的文件。
- 不要直接向客户端暴露组件函数。需要客户端访问时创建应用包装器,因为组件是内部的,需要应用提供认证与环境接线。
- 若组件定义 HTTP 处理器,路由需挂载在应用的 convex/http.ts 中,因为组件无法注册自己的 HTTP 路由。
- 若组件需要分页,使用 convex-helpers 的 paginator 而非内置 .paginate(),因为 .paginate() 无法跨组件边界工作。
- 为查询字段定义索引,而不是在数据库查询后使用 Convex 的 .filter()。
- 为所有公开组件函数添加 args 与 returns 校验器,因为组件边界需要显式类型契约。
验证与限制
验证按以下顺序尝试:
- npx convex codegen --component-dir convex/components/<name>
- npx convex codegen
- npx convex dev
注意事项:新仓库在配置 CONVEX_DEPLOYMENT 前,这些命令可能失败。在代码生成运行前,组件本地的 ./_generated/* 导入与应用侧的 components.<name>... 引用将无法通过类型检查。若验证因 Convex 登录或部署设置受阻,应停下来向用户询问该具体步骤,而不是猜测。
官方文档:Authoring Components。
检查清单
- 已询问用户要构建什么并确认形态
- 已读取匹配的参考文件
- 已确认组件是正确的抽象
- 已规划表、公开 API、边界与应用包装器
- 组件位于 convex/components/<name>/(若发布则为包布局)
- 组件从自身的 ./_generated/server 导入
- 认证、环境访问与 HTTP 路由保留在应用侧
- 父应用 ID 以 v.string() 跨边界
- 公开函数具有 args 与 returns 校验器
- 已运行 npx convex dev 并修复代码生成或类型问题