把前面几块能力串起来。
#需求
- 用户注册登录
- 每个人只能看到自己的项目
- 附件上传到仓库
- 项目变化实时刷新
- 某些管理逻辑走 Edge Functions
#表结构与 RLS
create table public.projects (
id uuid primary key default gen_random_uuid(),
owner_id uuid not null references auth.users(id) on delete cascade,
name text not null,
status text not null default 'draft',
created_at timestamptz not null default now()
);
alter table public.projects enable row level security;
create policy "Own projects only"
on public.projects
for all
to authenticated
using ((select auth.uid()) = owner_id)
with check ((select auth.uid()) = owner_id);#前端读写
import { createClient } from "@supabase/supabase-js";
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
export async function createProject(name: string, ownerId: string) {
const { data, error } = await supabase
.from("projects")
.insert({ name, owner_id: ownerId })
.select()
.single();
if (error) throw error;
return data;
}
export async function listProjects() {
const { data, error } = await supabase
.from("projects")
.select("*")
.order("created_at", { ascending: false });
if (error) throw error;
return data;
}#Realtime 监听
export function watchProjects() {
return supabase
.channel("projects-room")
.on(
"postgres_changes",
{ event: "*", schema: "public", table: "projects" },
(payload) => console.log("变化:", payload)
)
.subscribe();
}#Storage 上传
export async function uploadProjectFile(file: File, userId: string) {
const path = `${userId}/${Date.now()}-${file.name}`;
const { data, error } = await supabase.storage
.from("project-files")
.upload(path, file);
if (error) throw error;
return data?.path;
}整个业务流可以记成:
用户通过海关登录
↓
前端通过标准码头口读写 projects
↓
RLS 只放行自己的货物
↓
大文件进港口仓库
↓
表变更通过航运广播推送
↓
特殊调度逻辑走 Edge Functions这就是 Supabase 的典型顺滑路径。