Supabase өгөгдлийн сан
Supabase-н үндэс нь PostgreSQL өгөгдлийн сан. SQL бичихгүйгээр JavaScript объект шиг өгөгдөл унших, нэмэх, шинэчлэх, устгах боломжтой. Энэ хичээлд Supabase client ашиглан бүрэн CRUD хэрэгжүүлнэ.
Өгөгдөл унших — select
Server Component дотор өгөгдөл унших нь маш цэгцтэй:
// app/profile/page.tsx
import { createClient } from '@/lib/supabase/server';
import { redirect } from 'next/navigation';
export default async function ProfilePage() {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) redirect('/login');
// profiles хүснэгтээс унших
const { data: profile, error } = await supabase
.from('profiles')
.select('username, xp, streak')
.eq('id', user.id)
.single();
if (error || !profile) {
return <div>Профайл олдсонгүй</div>;
}
return (
<main>
<h1>{profile.username}</h1>
<p>XP: {profile.xp}</p>
<p>Streak: {profile.streak} өдөр</p>
</main>
);
}
.eq('id', user.id) нь SQL-н WHERE id = user.id гэсэнтэй адил. .single() нь нэг мөр буцаана — олдохгүй бол error гарна.
Олон мөр унших ба шүүх
// lib/courses.ts
import { createClient } from "@/lib/supabase/server";
export async function getUserProgress(userId: string) {
const supabase = await createClient();
const { data, error } = await supabase
.from("lesson_progress")
.select("course_slug, lesson_slug, completed_at")
.eq("user_id", userId)
.order("completed_at", { ascending: false }); // шинэ эхлээд
if (error) return [];
return data;
}
// Олон баганыг нэг дор сонгох
const { data } = await supabase
.from("profiles")
.select("id, username, xp")
.gte("xp", 100) // xp >= 100
.order("xp", { ascending: false })
.limit(10); // top 10
Өгөгдөл нэмэх ба шинэчлэх — insert / upsert
// Server Action — хичээл дуусгах
"use server";
import { createClient } from "@/lib/supabase/server";
import { revalidatePath } from "next/cache";
export async function completeLesson(courseSlug: string, lessonSlug: string) {
const supabase = await createClient();
const {
data: { user },
} = await supabase.auth.getUser();
if (!user) throw new Error("Нэвтрээгүй байна");
// upsert: байвал шинэчлэх, байхгүй бол нэмэх
const { error } = await supabase.from("lesson_progress").upsert({
user_id: user.id,
course_slug: courseSlug,
lesson_slug: lessonSlug,
});
if (error) throw new Error("Хадгалахад алдаа гарлаа");
// XP нэмэх
await supabase.rpc("increment_xp", { user_id: user.id, amount: 10 });
revalidatePath("/profile");
return { success: true };
}
upsert нь (user_id, course_slug, lesson_slug) давхардал байвал шинэчлэх, байхгүй бол шинэ мөр нэмэх — нэг дуудлагаар хоёуланг хийдэг.
Өгөгдөл шинэчлэх ба устгах — update / delete
// Профайл шинэчлэх
const { error } = await supabase
.from("profiles")
.update({ username: "Шинэ нэр", last_active: new Date().toISOString() })
.eq("id", user.id);
// Өгөгдөл устгах
const { error } = await supabase
.from("project_submissions")
.delete()
.eq("id", submissionId)
.eq("user_id", user.id); // заавал өөрийн бичлэгийг л устгана
delete хийхдээ eq filter заавал нэмнэ — filter байхгүй бол хүснэгтийн бүх мөрийг устгаж болох тул маш болгоомжтой байх хэрэгтэй.
Дараагийн хичээлд:
Row Level Security (RLS) гэж юу болохыг судална. Бусад хэрэглэгч өөрийн өгөгдлийг харах, өөрчлөх боломжгүй болгох аюулгүй байдлын тохиргоог ойлгоно.