用途
这是一个关于 Supabase SDK 使用模式的技能,面向使用 @supabase/supabase-js v2 或 supabase-py 实现 Supabase 查询、认证、实时、存储或 RPC 调用的场景。其核心约定是:每次调用都返回 { data, error },绝不假设成功。
主要能力
提供以下生产模式:
- 带 Database 泛型的类型安全单例客户端
- 使用完整过滤链(eq、gt、in、ilike 等)的 CRUD 操作
- insert-with-select 与 upsert(冲突处理)模式,可返回受影响行
- 注册、登录、会话管理与状态监听的认证流程
- 带行级过滤与清理的实时订阅
- 存储上传/下载,私有 bucket 使用签名 URL
- 查询模式的 Python 等价实现
前置条件
- 已具备含 URL 与 anon key 的 Supabase 项目(服务端可使用 service role key)
- 已安装 @supabase/supabase-js v2(TypeScript)或 supabase pip 包(Python)
- TypeScript 项目:通过 supabase gen types typescript 生成数据库类型
使用方式
第一步:初始化带类型的单例客户端
创建一个客户端实例并复用,不要每次请求都调用 createClient —— 单例可保留认证会话与连接池。
// lib/supabase.ts
import { createClient } from '@supabase/supabase-js'
import type { Database } from './database.types'
let supabase: ReturnType<typeof createClient<Database>>
export function getSupabase() {
if (!supabase) {
supabase = createClient<Database>(
process.env.SUPABASE_URL!,
process.env.SUPABASE_ANON_KEY!,
{
auth: { autoRefreshToken: true, persistSession: true },
db: { schema: 'public' },
global: { headers: { 'x-app-name': 'my-app' } },
}
)
}
return supabase
}
Python 等价写法:
from supabase import create_client, Client
_client: Client | None = None
def get_supabase() -> Client:
global _client
if _client is None:
_client = create_client(
os.environ["SUPABASE_URL"],
os.environ["SUPABASE_ANON_KEY"],
)
return _client
第二步:查询、过滤与修改数据
解构 { data, error },在访问 data 之前先检查 error。在 .from(table).select(...) 上链式添加过滤条件;在 insert/upsert 后使用 .select().single() 返回受影响行。骨架示例:
const { data, error } = await getSupabase()
.from('users')
.select('id, name, email')
.eq('active', true)
.order('name')
.limit(10)
if (error) throw error
完整的 CRUD 集合(insert-with-select、on conflict 的 upsert、update、delete、RPC)、完整的 12 个过滤条件参考表以及 Python 等价写法,请参见 queries and filters 部分。
第三步:认证、实时与存储
认证、实时频道与存储都遵循相同的 { data, error } 约定。认证暴露 signUp / signInWithPassword / getSession / onAuthStateChange;实时在频道上订阅 postgres_changes,并需要 removeChannel 清理;存储按 bucket 执行 upload / download / getPublicUrl / createSignedUrl。每个主题的完整代码讲解请参见 auth、realtime 和 storage 部分。
输出
应用这些模式可获得:
- 带 Database 泛型的类型安全单例客户端
- 使用完整过滤链(eq、gt、in、ilike 等)的 CRUD 操作
- 返回受影响行的 insert-with-select 与 upsert 模式
- 注册、登录、会话管理与状态监听的认证流程
- 带行级过滤与清理的实时订阅
- 私有 bucket 使用签名 URL 的存储上传/下载
- 查询模式的 Python 等价实现
错误处理
每个 Supabase 调用都返回 { data, error },绝不可跳过错误检查。
const { data, error } = await getSupabase().from('users').select('*')
if (error) {
// error 是 PostgrestError,包含以下字段:
// error.message — 人类可读的描述
// error.code — Postgres 错误码(例如 '23505')
// error.details — 附加上下文
// error.hint — Postgres 给出的修复建议
console.error(`Query failed [${error.code}]: ${error.message}`)
throw error
}
// 只有在错误检查通过后,使用 data 才是安全的
错误码对照:
| 错误码 | 含义 | 处理方式 |
|---|---|---|
| PGRST116 | 未找到行(.single()) | 返回 null 或 404,不要抛出 |
| 23505 | 唯一约束冲突(Postgres 重复键) | 使用 .upsert() 或显示冲突错误 |
| 42501 | RLS 策略违规(Postgres 权限不足) | 检查认证状态与 RLS 策略 |
| PGRST000 | 连接错误 | 使用指数退避重试 |
| 42P01 | 表不存在 | 核对表名并运行迁移 |
| 23503 | 外键违规 | 先确保被引用的行存在 |
| 42703 | 列不存在 | 检查列名,重新生成类型 |
示例
推荐的生产形态是一层类型安全的服务层,包装客户端,使调用方无需接触原始查询;再加一个分页辅助函数,在一次往返中返回一页行和总计数。两个可直接复制使用的完整实现见 service patterns 部分。
资源
- Supabase JS Client Reference
- TypeScript Support & Type Generation
- Supabase Auth Reference
- Realtime Guide
- Storage Guide
- Python Client Reference
后续步骤
数据库 schema 设计参见 supabase-schema-from-requirements;带 RLS 策略的认证深入讲解参见 supabase-install-auth;实时架构模式参见 supabase-auth-storage-realtime-core。