mcpField
I
integrating-convex-expo

integrating-convex-expo

github.com/tristanmanchester开发474 次安装8 周前更新
代码仓库

关于 integrating-convex-expo

integrating-convex-expo 是一项技能,用于在 Expo 和 React Native 应用中添加、修复或扩展 Convex 后端。内容涵盖环境与 Provider 配置、功能开发、验证和发布加固。

主要功能

  1. 01配置 Convex 客户端与 Provider
  2. 02设置环境变量和 EAS
  3. 03构建 Schema、函数及前端 Hooks
  4. 04实现身份验证和文件上传
  5. 05验证并加固集成

适用场景

  1. 01将 Convex 接入 Expo 应用
  2. 02跨后端与应用实现功能
  3. 03修复 Provider、环境或生成 API 问题
  4. 04为发布准备集成

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/tristanmanchester/agent-skills --skill integrating-convex-expo

安装后在 Claude Code 中输入/integrating-convex-expo确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
trigger-queries.json
references/
auth.md
components-and-helpers.md
eas-env.md
evaluation.md
file-uploads.md
frontend-patterns.md
functions.md
migrations.md
production-checklist.md
schema-and-indexes.md
sources.md
tasks-example.md
troubleshooting.md
scripts/
scaffold_tasks_example.py
validate_project.py

详细介绍

将 Convex 集成到 Expo(React Native)

使用此技能为 Expo 应用添加、修复、扩展或加固 Convex 后端,同时避免偏离到仅适用于 Web 的模式或泛泛的 React Native 建议。

适用场景

  • 将 Convex 添加到现有的 Expo 或 Expo Router 应用中。
  • 修复有问题的环境配置、提供程序接线或生成的 API 导入。
  • 构建端到端的功能切片:架构、索引、后端函数、前端钩子和验证。
  • 为 Expo + Convex 选择并实现身份验证。
  • 将文件从 Expo URI 上传到 Convex 存储。
  • 为分页、索引、迁移或可复用组件进行重构。
  • 在预览版或生产版发布前加固项目。

不适用场景

  • 不涉及 Convex 的纯 Expo UI、动画、导航或样式工作。
  • 前端不是 Expo 或 React Native 的 Convex 项目。
  • 不需要 Expo 专属环境或客户端接线的通用后端架构讨论。

成功标准

良好的结果应使项目具备:

  1. 一个范围设置正确的 Convex 客户端和提供程序。
  2. EXPO_PUBLIC_CONVEX_URL 在本地开发和 EAS 中均能正常使用。
  3. 后端函数符合 Convex 关于验证器、身份验证、操作和查询性能的最佳实践。
  4. 前端钩子使用生成的 api 引用,并清晰处理加载、空数据和错误状态。
  5. 使用 scripts/validate_project.py 完成验证。
  6. 为后续扩展提供清晰路径:分页、索引、身份验证包装器、迁移和 lint。

不可妥协的要求

  • 开发或修复集成时,保持 npx convex dev 运行。
  • 从 process.env.EXPO_PUBLIC_CONVEX_URL 读取部署 URL。
  • 在 EAS 环境中镜像此值,以用于预览版和生产版构建。
  • 每个应用仅创建一个 ConvexReactClient,并将其放在渲染路径之外。
  • 在真正的根入口挂载提供程序:app/_layout.tsx、src/app/_layout.tsx 或 App.tsx。
  • 在 Expo 和 React Native 中,设置 unsavedChangesWarning: false。
  • 从 convex/_generated/api 导入生成的引用,不要使用依赖字符串的名称。
  • 将所有客户端可调用的 Convex 函数视为不可信入口。
  • 为公共函数添加 args 验证器,并且也尽量使用 returns 验证器。
  • 保持公共包装器精简;将重复逻辑移至辅助函数、内部函数或自定义包装器。
  • 不要在查询逻辑中使用 Date.now() 或 new Date()。
  • 不要在查询或变更中使用仅限 Node.js 的 API 或第三方 SDK。
  • 将外部 API 调用、繁重计算或仅限 Node.js 的库放入 action 或 internalAction 文件;如果文件以 "use node" 开头,则只放置操作。
  • 避免在大型表上使用 .filter() 和无界的 .collect();优先使用索引和分页。
  • 等待每一个 Promise 完成。
  • 优先使用 TypeScript 严格模式和官方 Convex ESLint 插件。

首轮排查

进行更改前,先检查项目并确定任务类别。

1. 确认应用入口点

检查以下文件:

  • Expo Router 项目的 app/_layout.tsx 或 src/app/_layout.tsx。
  • 传统入口项目的 App.tsx 或 App.jsx。
2. 审查 Convex 状态

检查以下内容:

  • package.json 依赖项:convex、expo、身份验证库、ESLint 工具。
  • convex/ 和 convex/_generated/。
  • .env.local、.env、.env.development、.env.production。
  • 如果涉及云构建,检查 eas.json。
  • 现有的提供程序用法:ConvexProvider、ConvexProviderWithClerk 或自定义身份验证包装器。
  • convex/schema.ts 中现有的架构和索引。
  • 缺少验证器、身份验证检查或分页的现有公共函数。
3. 运行验证器

在项目根目录运行:

python scripts/validate_project.py --root <project-root>

需要机器可读的输出时使用 --json;需要更严格的门禁时使用 --fail-on-warning。

4. 选择工作流
  • 初始化 / 修复基线:缺少 Convex 设置、环境变量、提供程序或生成的 API。
  • 构建功能切片:同时添加后端数据和 UI。
  • 身份验证:添加或修复登录和后端授权。
  • 文件上传:将媒体或文档从设备 URI 移至 Convex 存储。
  • 扩展 / 加固:索引、分页、组件、Lint 检查、生产环境检查清单。
  • 迁移:重塑现有表,或逐步从其他后端迁移。

工作流 A — 初始化或修复基线集成

步骤 1:安装或确认客户端包
npx expo install convex
步骤 2:创建或重新连接 Convex 项目
npx convex dev

此操作会:

  • 创建或连接 Convex 项目,
  • 在缺失时创建 convex/,
  • 生成 convex/_generated/,
  • 将 EXPO_PUBLIC_CONVEX_URL 写入 .env.local,
  • 并在命令运行期间持续同步。
步骤 3:确保根提供程序存在

对于 Expo Router:

import { ConvexProvider, ConvexReactClient } from "convex/react";
import { Stack } from "expo-router";

const convex = new ConvexReactClient(process.env.EXPO_PUBLIC_CONVEX_URL!, {
  unsavedChangesWarning: false,
});

export default function RootLayout() {
  return (
    <ConvexProvider client={convex}>
      <Stack />
    </ConvexProvider>
  );
}

对于经典的 App.tsx,以相同方式包装顶层导航树。

步骤 4:确认生成的导入

使用:

import { api } from "../convex/_generated/api";

或根据项目布局使用正确的相对路径。不要手动编写函数名称。

步骤 5:验证开发和构建环境

阅读 references/eas-env.md,并确保 EAS 采用相同的部署 URL 策略。

步骤 6:验证并进行冒烟测试
  • 启动 Expo 应用。
  • 确认 useQuery(...) 从 undefined 变为真实数据。
  • 运行 python scripts/validate_project.py --root <project-root>。
  • 如有需要,使用 python scripts/scaffold_tasks_example.py --root <project-root> 搭建规范示例。

工作流 B — 端到端构建功能切片

按以下顺序构建每项功能。

1. 首先对访问模式建模

开始编写代码前,回答以下问题:

  • 数据是公开的、限定用户的、限定组织的,还是仅限管理员访问?
  • 列表会保持较小规模,还是应进行分页?
  • 哪些字段是查找键,因此需要索引?
  • 是否有步骤需要外部 API、AI SDK、Stripe 或 Node API?
2. 设计架构

当数据模型趋于稳定时,先添加或扩展 convex/schema.ts,再编写函数层。

请参阅 references/schema-and-indexes.md,了解:

  • 扁平关系建模,
  • 外键索引,
  • 基于实际查询模式的复合索引,
  • 有界数组指南,
  • 以及分页阈值。
3. 实现后端函数

详细模式请参阅 references/functions.md。

默认规则:

  • 对确定性读取使用 query。
  • 对写入使用 mutation。
  • 对外部 API、第三方 SDK 或仅限 Node 的代码使用 action 或 internalAction。
  • 对不应由客户端调用的逻辑使用 internalQuery 或 internalMutation。
4. 在后端强制执行访问控制

如果功能不是公开的,请采用以下方式之一:

  • 在每个函数中显式检查 ctx.auth.getUserIdentity(),或
  • 通过 convex-helpers 使用可复用的自定义包装器。

请参阅 references/auth.md 和 references/components-and-helpers.md。

5. 接入前端

请参阅 references/frontend-patterns.md。

务必处理:

  • 加载状态:useQuery(...) === undefined,
  • 空状态,
  • 相关情况下的 mutation 等待状态,
  • 可恢复的错误,
  • 以及无界列表的分页。
6. 验证功能切片

完成前:

  • 使用项目根目录运行验证器,
  • 如果项目配置了 Lint 和类型检查,请运行它们,
  • 在设备或模拟器上验证功能,
  • 并在发布前更新或添加索引。

工作流 C — 身份验证和授权

选择一种身份验证方案,并确保技术栈保持一致。

选项 1:Clerk

适用于已使用 Clerk 或希望采用完善身份验证产品的应用。

选项 2:Convex Auth

适用于希望使用 Convex 原生身份验证技术栈,并愿意采用 Beta 库的情况。

选项 3:现有 JWT 或 OIDC 提供方

适用于产品已依赖 Auth0、WorkOS、公司 IdP 或其他 OIDC 流程的情况。

无论使用哪种提供方,都应遵守以下规则
  • 后端授权是强制要求;客户端限制访问仅用于改善用户体验。
  • 如果在 Convex 中持久化用户,请使用 tokenIdentifier 等稳定标识符建立索引。
  • 对每个受保护函数,都要检查所有权、组织成员资格或角色。
  • 尽量使用辅助函数或自定义封装,避免重复编写身份验证样板代码。
  • 对特权内部操作使用内部函数。

请阅读 references/auth.md,了解决策矩阵和实现模式。

工作流 D — 从 Expo 上传文件

使用 Convex 上传 URL,而不是尝试通过 mutation 传送原始文件。

推荐流程:

  1. 公共或受保护的 mutation 返回 ctx.storage.generateUploadUrl(),
  2. 客户端使用 fetch(uri) 加载本地 file:// URI,并将其转换为 Blob,
  3. 客户端将该 blob POST 到上传 URL,
  4. 第二个 mutation 保存返回的 storageId 以及应用专属的元数据,
  5. 可选的后处理在之后通过计划任务或 action 执行。

请阅读 references/file-uploads.md。

工作流 E — 扩展和强化

基线功能正常后,提高质量标准。

性能
  • 尽可能将 .filter() 扫描替换为索引查询。
  • 将不受限的 .collect() 替换为 take、first 或分页查询。
  • 对不断增长的信息流、通知和无限滚动页面使用 usePaginatedQuery。
  • 当边界明确时,将重复或可复用的功能区域移至 Convex 组件。
安全性
  • 始终添加验证器。
  • 将特权逻辑置于内部函数之后。
  • 对预期的失败使用 ConvexError 或清晰的返回结构。
  • 未检查所有权或成员资格前,切勿信任来自客户端的 ID。
可维护性
  • 启用 @convex-dev/eslint-plugin。
  • 使用 TypeScript 严格模式。
  • 保持封装精简,并将共享逻辑移至纯 TypeScript 辅助函数。
  • 将 "use node" action 文件与常规运行时文件分开。

请阅读 references/production-checklist.md。

工作流 F — 迁移

更改线上 schema 时,优先采用增量式过渡。

默认迁移策略:

  1. 以向后兼容的方式添加新字段或表,
  2. 如果数据结构发生变化,则同时读取或同时写入,
  3. 以幂等批次回填现有文档,
  4. 切换读取端和写入端,
  5. 然后移除旧结构。

使用内部函数或计划任务进行回填,并确保迁移可以安全重启。

请阅读 references/migrations.md。

快速故障排查流程

如果应用出现故障,请按顺序检查:

  1. npx convex dev 是否正在运行,且没有 TypeScript 错误?
  2. .env.local 是否包含 EXPO_PUBLIC_CONVEX_URL?
  3. 环境文件更改后是否重启了 Metro?
  4. 是否恰好只有一个 ConvexReactClient?
  5. Provider 是否挂载在真正的根节点?
  6. convex/_generated/api 是否存在,导入路径是否正确指向它?
  7. 公共函数是否缺少 args 或 returns 验证器?
  8. 查询是否使用了 Date.now()、.filter() 或不受限的 .collect()?
  9. "use node" 文件是否错误地混用了查询或 mutation?
  10. 客户端 Provider 与后端配置中的身份验证是否不匹配?

请参阅 references/troubleshooting.md。

可用脚本

  • scripts/validate_project.py

    • 验证以 --root 指定的项目;如果该脚本被复制到仓库中,则验证当前工作树。
    • 验证 Expo 和 Convex 依赖项。
    • 检查环境文件、提供方接线、生成的代码、验证器是否存在、误用 "use node" 的情况,以及常见的查询反模式。
    • 支持 --json、--root 和 --fail-on-warning。
  • scripts/scaffold_tasks_example.py

    • 默认进行试运行。
    • 可以生成 sampleData.jsonl、convex/schema.ts、convex/tasks.ts,以及可选的 Expo 屏幕文件。
    • 支持 --write、--overwrite、--ui-file 和 --json。

参考资料

仅加载与当前任务对应的文件。

评论

支持 Markdown