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-ref

URL 和 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.sqlprofiles、RLS,以及注册时从用户 metadata 复制 full_name 的触发器
20240101000001_init_todos.sqltodos、排序索引、updated_at 触发器、按用户隔离的 CRUD 策略
20240101000003_step7_examples.sqlsample_uploads、私有 sample-uploads bucket、50 MB 限制、按文件夹隔离的 Storage 策略
20260630120000_billing_entitlements.sqlsubscriptionspayments,与 soar-electron 共享;客户端只有 SELECT RLS

这些迁移使用 if not existscreate 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/callback

Apple 和 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

FunctionJWT用途
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_AUTHrevenuecat-webhook必须和 RevenueCat webhook 的 Authorization header 一致
APNS_TEAM_IDsend-test-push可选 Apple Developer Team ID
APNS_KEY_IDsend-test-push可选 APNs auth key ID
APNS_BUNDLE_IDsend-test-push可选 iOS bundle ID,例如 expo.soarstarter.com
APNS_PRIVATE_KEYsend-test-push可选 .p8 私钥内容

不要把 SUPABASE_URLSUPABASE_ANON_KEY 或 service-role key 设置成 Edge secrets。Supabase 会在运行时自动注入这些值。

本地函数开发

supabase functions serve --env-file supabase/functions/.env
deno test supabase/functions/_shared/revenuecat.test.ts

functions serve 会在 http://localhost:54321/functions/v1/... 暴露本地函数。

验证后端

  • 在应用中注册、验证邮箱验证码,并确认该用户生成了 profiles row。
  • 创建、编辑、重排、删除 todos;重启后确认数据仍然存在。
  • 在 Upload sample 上传文件,并确认同时存在 Storage object 和 sample_uploads row。
  • 运行 supabase functions list --project-ref <ref>,确认函数已经部署。
  • schema 修改后重新运行 pnpm gen:types,并提交更新后的 types/database.ts

相关页面

On this page