Supabase 设置
设置 Supabase Auth、数据库、存储和 Edge Functions。
Supabase 是 Expo 模板的后端:Auth、Postgres 数据、私有 Storage、Edge
Functions,以及账号绑定的权益读模型都在这里。和 Swift 版本不同,Expo
模板已经带齐应用需要的迁移,所以 supabase db push 可以一次性搭好可用后端。
创建项目
创建 Supabase 项目
在 Supabase 控制台创建项目,然后从 Project Settings → API 复制项目 URL
和 anon key,写入 soar-expo/.env.local:
EXPO_PUBLIC_SUPABASE_URL=https://your-project-ref.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_PROJECT_ID=your-project-refURL 和 anon key 是公开客户端配置。不要把 service-role key 放进 Expo env 文件。
连接 CLI
brew install supabase/tap/supabase
supabase login
supabase link --project-ref <ref>supabase/config.toml 已经包含模板依赖的每个 Edge Function JWT 设置。
应用所有迁移
supabase db push --project-ref <ref>仓库内有四个迁移:
| 迁移 | 创建内容 |
|---|---|
20240101000000_init_profiles.sql | profiles、RLS,以及注册时从用户 metadata 复制 full_name 的触发器 |
20240101000001_init_todos.sql | todos、排序索引、updated_at 触发器、按用户隔离的 CRUD 策略 |
20240101000003_step7_examples.sql | sample_uploads、私有 sample-uploads bucket、50 MB 限制、按文件夹隔离的 Storage 策略 |
20260630120000_billing_entitlements.sql | subscriptions 和 payments,与 soar-electron 共享;客户端只有 SELECT RLS |
这些迁移使用 if not exists、create or replace 或受保护的策略创建逻辑,重复执行是安全的。如果不能使用 CLI,可以按时间顺序把迁移 SQL 粘贴到控制台 SQL editor。
生成客户端类型
pnpm gen:types脚本会根据 SUPABASE_PROJECT_ID 生成 Supabase 类型,并写入 types/database.ts。每次修改 schema 后,在编写新的 app 查询前都要重新运行。
Auth URL
当前应用的邮箱流程使用手动输入验证码,Apple 和 Google 使用原生 ID token 登录:
- 邮箱注册和密码重置先调用 Supabase Auth,再在应用内验证验证码。
- Apple 和 Google 调用
supabase.auth.signInWithIdToken(...),Supabase 不会重定向回应用。
因此当前代码路径没有必须实现的 app callback route。仍建议为本地 Web 测试设置 dashboard Site URL:
http://localhost:3000如果以后改成基于链接的 OAuth 或 magic link,再把 app.config.ts 里的变体 scheme 加入允许列表:
soar-starter-expo-dev://
soar-starter-expo-preview://
soar-starter-expo://Google 原生登录仍需要在 Google Cloud 的 Web OAuth client 中配置 Supabase provider callback:
https://<ref>.supabase.co/auth/v1/callbackApple 和 Google 的配置见 认证。
Edge Functions
从 soar-expo/supabase/functions 部署函数:
supabase functions deploy revenuecat-webhook --no-verify-jwt --project-ref <ref>
supabase functions deploy delete-account --project-ref <ref>
# 可选 APNs 调试产物:
supabase functions deploy send-test-push --project-ref <ref>functions/_shared/ 会被导入它的函数自动打包。不要单独部署 _shared。
| Function | JWT | 用途 |
|---|---|---|
revenuecat-webhook | 关闭 | RevenueCat 不带 Supabase JWT 调用;函数验证静态 Authorization header,并用 service role 写 subscriptions / payments |
delete-account | 开启 | 已登录用户调用;删除 rows、sample-uploads/<user-id>/ 文件,再删除 auth user |
send-test-push | 开启 | 从 Swift 模板复制来的可选 APNs 发送器;它需要 Expo 模板未提供的 device_tokens 表 |
Expo 客户端会在 lib/notifications.tsx 获取 Expo push token,但不会把 token
持久化到 Supabase。在你添加 token 表和注册流程前,请把 send-test-push 视为可选后端产物。
Edge secrets
只把服务端密钥设置到 Supabase:
supabase secrets set REVENUECAT_WEBHOOK_AUTH=<long-random-string> --project-ref <ref>| Secret | 使用方 | 说明 |
|---|---|---|
REVENUECAT_WEBHOOK_AUTH | revenuecat-webhook | 必须和 RevenueCat webhook 的 Authorization header 一致 |
APNS_TEAM_ID | send-test-push | 可选 Apple Developer Team ID |
APNS_KEY_ID | send-test-push | 可选 APNs auth key ID |
APNS_BUNDLE_ID | send-test-push | 可选 iOS bundle ID,例如 expo.soarstarter.com |
APNS_PRIVATE_KEY | send-test-push | 可选 .p8 私钥内容 |
不要把 SUPABASE_URL、SUPABASE_ANON_KEY 或 service-role key 设置成 Edge
secrets。Supabase 会在运行时自动注入这些值。
本地函数开发
supabase functions serve --env-file supabase/functions/.env
deno test supabase/functions/_shared/revenuecat.test.tsfunctions serve 会在 http://localhost:54321/functions/v1/... 暴露本地函数。
验证后端
- 在应用中注册、验证邮箱验证码,并确认该用户生成了
profilesrow。 - 创建、编辑、重排、删除 todos;重启后确认数据仍然存在。
- 在 Upload sample 上传文件,并确认同时存在 Storage object 和
sample_uploadsrow。 - 运行
supabase functions list --project-ref <ref>,确认函数已经部署。 - schema 修改后重新运行
pnpm gen:types,并提交更新后的types/database.ts。
