Service Layer
Menempatkan Supabase query dan auth-aware data access dalam fungsi server yang bernama jelas, bukan di component UI acak.
Tujuan belajar
- Menjelaskan alasan data access dipusatkan dalam service function
- Membuat fungsi server yang membaca identity sebelum query user-owned data
- Membedakan state UI dari operasi data
- Menangani error data tanpa mengembalikan detail database ke user
Isi lesson
6 blok- 1.Component menjelaskan UI, service menjelaskan data accessBelum selesaiWajib
- 2.Service untuk profile user saat iniBelum selesaiWajib
- 3.Coding practiceBelum selesaiWajib
- 4.Cek pemahamanBelum selesaiWajib
- 5.Jangan menerima userId dari form lalu langsung mempercayainyaBelum selesaiWajib
- 6.RingkasanBelum selesaiWajib
Component menjelaskan UI, service menjelaskan data access
WajibSaat query Supabase langsung ditulis di banyak page, component mulai mencampur markup, session check, nama tabel, error handling, dan mapping data. Perubahan policy atau bentuk data lalu sulit ditelusuri. Service layer menyimpan operasi tersebut dalam fungsi kecil dengan nama yang menjelaskan tujuan, misalnya getCurrentProfile atau saveLearningNote.
Service layer bukan abstraction besar yang harus dibuat untuk setiap baris query. Mulailah saat query mempunyai identity check, aturan user-owned, mapping, atau error handling yang akan membuat component sulit dibaca. Page tetap bertanggung jawab memilih loading/error UI; service bertanggung jawab menjalankan operasi data dengan boundary server yang jelas.
Bagian ini memengaruhi progres lesson.
Service untuk profile user saat ini
Wajib// lib/services/profile-service.ts
import "server-only";
import { createClient } from "@/lib/supabase/server";
export async function getCurrentProfile() {
const supabase = await createClient();
const { data: claimsData, error: claimsError } =
await supabase.auth.getClaims();
const userId = claimsData?.claims.sub;
if (claimsError || !userId) {
return null;
}
const { data, error } = await supabase
.from("profiles")
.select("id, display_name, bio")
.eq("id", userId)
.maybeSingle();
if (error) {
throw new Error("Profile belum bisa dimuat.");
}
return data;
}server-only menyatakan bahwa service ini tidak boleh diimport ke browser bundle. Fungsi memverifikasi identity terlebih dahulu, lalu hanya meminta profile dengan id user saat ini. RLS tetap menjadi proteksi database jika query berubah atau dipanggil dari tempat lain. Error internal tidak diteruskan mentah ke UI; page dapat menangkap error dan menampilkan fallback yang sesuai.
Bagian ini memengaruhi progres lesson.
Coding practice
WajibDibuka di workspace khususExtract profile service layer
Lengkapi getCurrentProfile sebagai service server yang memverifikasi claims lalu membaca profile user saat ini.
Tujuan awal: Fokus di tab TSX.
Practice ini dibuka di workspace khusus. Buka practice untuk memakai editor, preview, dan cek otomatis.
Tombol selesai aktif setelah semua validasi wajib lolos.
Cek pemahaman
WajibJawab duluCek pemahaman singkat
Apa alasan terbaik memindahkan query profile yang berulang ke getCurrentProfile?
Progres lesson naik setelah jawaban benar.
Catatan penting
WajibJangan menerima userId dari form lalu langsung mempercayainya
Untuk operasi user-owned, ambil identity dari auth context yang diverifikasi pada server. Nilai userId dari form, URL, atau Client Component dapat dimanipulasi. Kamu masih dapat menggunakan userId dari claims untuk query atau insert, lalu RLS tetap memastikan row yang diakses memang sesuai policy.
Bagian ini memengaruhi progres lesson.
Ringkasan
Wajib- Service layer memisahkan data access dari presentasi UI.
- Gunakan fungsi bernama jelas untuk identity check, query, mapping, dan error handling yang berulang.
- server-only membantu mencegah service server diimport ke Client Component.
- Identity user-owned berasal dari auth context server, bukan field yang dikirim browser.
- Berikutnya, kamu akan memakai service untuk alur create/read/update data yang kecil.
Bagian ini memengaruhi progres lesson.
Langkah berikutnya
Selesaikan bagian penting lesson ini
Lanjutkan blok wajib berikutnya: Component menjelaskan UI, service menjelaskan data access.