# Supabase

Supabase 的两条接入路径：把它当托管 Postgres 直连（配合 Drizzle/postgres.js，见 [PostgreSQL 与 Drizzle](/docs/database/postgres-drizzle)），或用官方 SDK `@supabase/supabase-js` 走 PostgREST/Auth/Storage API。SDK 同时发布在 npm 和 JSR（`jsr:@supabase/supabase-js`）上。

```ts title="src/supabase.ts"
import { createClient } from "jsr:@supabase/supabase-js@2";

const url = Deno.env.get("SUPABASE_URL");
const key = Deno.env.get("SUPABASE_PUBLISHABLE_KEY");
if (!url || !key) throw new Error("SUPABASE_URL / SUPABASE_PUBLISHABLE_KEY required");

export const supabase = createClient(url, key);
```

```bash
deno run \
  --allow-env=SUPABASE_URL,SUPABASE_PUBLISHABLE_KEY \
  --allow-net=<project-ref>.supabase.co \
  src/main.ts
```

## 直连 Postgres 与连接池

Supabase 提供多种连接方式，端口与适用场景（官方连接文档）：

| 方式 | 主机:端口 | 适用 |
| --- | --- | --- |
| Direct connection | `db.<project-ref>.supabase.co:5432` | 常驻服务、migration、`pg_dump`；IPv6，IPv4 需付费 add-on |
| Supavisor session 模式 | `aws-<region>.pooler.supabase.com:5432` | IPv4-only 网络的直连替代 |
| Supavisor transaction 模式 | `aws-<region>.pooler.supabase.com:6543` | serverless / 边缘函数等大量短连接 |

- Deno Deploy 一类无常驻进程的环境用 transaction 模式（6543）；官方明确 transaction 模式不支持 prepared statements，客户端要禁用（`postgres.js`：`postgres(url, { prepare: false })`）。
- serverless 并发扩容时按最大实例数核算总连接数，池上限别按单实例拍。
- migration 用 direct connection 或 session 模式，走独立发布步骤，不给线上 HTTP 进程 schema 修改权限。

```bash
deno run \
  --allow-env=DATABASE_URL \
  --allow-net=aws-<region>.pooler.supabase.com:6543 \
  src/main.ts
```

## Auth 与 RLS 边界

- SDK 默认按调用者身份执行：新 publishable key（对应 legacy anon JWT key，两者是可并存的不同密钥类型而非简单改名）+ 用户 JWT 时，PostgREST 以该用户角色访问，RLS 策略生效。
- 官方 RLS 文档要求暴露 schema（默认 `public`）中的表必须启用 RLS；启用后没有策略则 publishable key 下 API 不可读任何数据。Table Editor 建表默认开启，手写 SQL 建表要自己 `enable row level security`。
- 新 secret key（对应 legacy service_role JWT key）会绕过 RLS，官方明确禁止出现在浏览器或交付给客户的代码里；只在服务端、从环境变量注入、不进日志。
- Deno 后端如果只做受信服务间调用，直连 Postgres 往往比 service key + PostgREST 更直观；需要按终端用户鉴权时才走 SDK + RLS。

## Edge Functions 与本地 Deno 的差异

Supabase Edge Functions 运行在 Supabase Edge Runtime 上——官方称其为 Deno 兼容、TypeScript 优先的运行时（开源，github.com/supabase/edge-runtime）。与本地 Deno 的实际差异：

- 依赖导入支持 `npm:`、`jsr:` 和 Node 内置模块；官方推荐每个函数配自己的 `deno.json`，部署时不要共享 `/supabase/functions` 下的全局配置。
- 本地用 `supabase functions serve` 获得与生产接近的运行时，部署用 `supabase functions deploy`。
- 函数面向短生命周期、幂等操作设计，可能有冷启动；长任务交给后台 worker，不要塞进函数。
- 它是 Deno 兼容运行时而非 Deno 本体，不要假设与本地 `deno` 版本特性完全对齐；用到新 API 前在 Edge Runtime 仓库核对。

## 密钥管理

- 只需要 publishable 级别的权限就不要引入 secret key；两者用不同环境变量名分开，避免误用。
- secret 只从环境或 secret store 读取，不进源码、日志和错误响应；轮换时按 Supabase dashboard 的密钥滚动流程走。
- `--allow-env` 精确到变量名，`--allow-net` 精确到项目主机；CI 加 `--no-prompt`。

官方参考：[Connecting to your database](https://supabase.com/docs/guides/database/connecting-to-postgres)、[Row Level Security](https://supabase.com/docs/guides/database/postgres/row-level-security)、[Edge Functions](https://supabase.com/docs/guides/functions)、[Function dependencies](https://supabase.com/docs/guides/functions/dependencies)、[Deno 官方 Supabase 示例](https://docs.deno.com/examples/supabase/)。
