Saatnya 'ngobrol' dengan database Supabase dari kodemu! Pelajari cara melakukan operasi CRUD (Create, Read, Update, Delete) menggunakan Supabase JS Client (`@supabase/supabase-js`) dengan contoh query yang jelas.
17m bacaanKuis WajibMicro Badge Lesson
"Ngobrol" Langsung Sama Database Supabase: Jurus CRUD Pake Supabase JS Client!
Udah punya tabel kue yang cantik di database Supabase-mu? Udah juga nyiapin "saluran telepon" Supabase Client di proyek Next.js kita? Mantap! Sekarang, saatnya kita bener-bener "ngobrol" sama database itu dari kode JavaScript/TypeScript kita.
Kita bakal belajar cara ngelakuin empat operasi paling dasar yang jadi tulang punggung interaksi data: CRUD (Create, Read, Update, Delete). Dan kita bakal pake metode-metode keren dari Supabase JS Client (@supabase/supabase-js) yang bikin semua ini jadi gampang dan intuitif.
Ingat:
Pastikan kamu udah ngimpor dan nginisialisasi Supabase Client-mu (biasanya dari file kayak src/lib/supabase-client.ts.ts):
typescript
// Di file tempat kamu mau query, misalnya di API Route atau Client Componentimport { supabase } from '@/lib/supabase-client.ts'; // Sesuaikan path-nya// Untuk contoh di bawah, kita asumsikan 'supabase' sudah jadi instance SupabaseClient.
Semua operasi database pake Supabase Client itu asinkron (asynchronous), jadi kita bakal sering pake async/await.
Hasil dari query Supabase Client biasanya adalah objek yang punya dua properti utama: data (isinya hasil query kalau sukses) dan error (isinya objek error kalau ada masalah). Selalu cek error-nya ya!
1. Create (Membuat Data Baru / insert)
Buat nambahin baris data baru ke tabel kue kita, kita pake metode .insert().
from('nama_tabel'): Nunjuk ke tabel mana kita mau insert.
insert([...]): Nerima array dari objek yang mau diinsert. Meskipun cuma satu objek, tetep harus di dalem array. Tiap objek strukturnya harus cocok sama kolom di tabelmu.
Contoh Membuat Kue Baru:
typescript
// Asumsikan ini di dalam sebuah fungsi async, misal di API Route Next.js// atau di Client Component yang manggil Server Action.// Impor tipe Kue jika perlu untuk type safety objek dataKueBaruimport { Kue } from '@/data/kue'; // Atau tipe yang sesuai dengan tabelmu// Kita definisikan tipe untuk data input, tanpa id, created_at, updated_attype KueInput = Omit<Kue, 'id' | 'created_at' | 'updated_at'>;async function tambahKueBaru(dataKueBaru: KueInput) { try { const { data, error } = await supabase .from('kue') // Nama tabel kita .insert([ // Kita bisa insert satu atau beberapa objek sekaligus { nama: dataKueBaru.nama, deskripsi_singkat: dataKueBaru.deskripsi_singkat, deskripsi_lengkap: dataKueBaru.deskripsi_lengkap, harga: dataKueBaru.harga, gambar_url: dataKueBaru.gambar_url, // Pastikan nama kolom di DB sama kategori: dataKueBaru.kategori, rating: dataKueBaru.rating, bahan_utama: dataKueBaru.bahan_utama // id, created_at, updated_at biasanya otomatis diisi database } ]) .select() // PENTING: .select() di akhir biar ngembaliin data yang baru diinsert .single(); // Jika kita yakin hanya satu item yang diinsert dan ingin objeknya langsung if (error) { console.error("Error Supabase pas nambah kue:", error.message); throw error; // Lempar error biar bisa ditangkep di atas } console.log("Kue baru berhasil ditambah:", data); return data; // data di sini adalah objek kue yang baru ditambah (karena .single()) } catch (err: any) { console.error("Gagal total nambah kue:", err.message); return null; }}// Contoh pemanggilan:// const kueDonat: KueInput = {// nama: "Donat Coklat Keju Spesial",// deskripsi_singkat: "Donat empuk dengan topping coklat dan keju melimpah.",// deskripsi_lengkap: "Donat klasik yang selalu jadi favorit...",// harga: 8000,// gambar_url: "/images/kue/donat-coklat-keju.jpg", // Nanti ganti dengan URL dari Supabase Storage// kategori: "Donat",// rating: 4.7,// bahan_utama: ["Tepung", "Coklat", "Keju"]// };// tambahKueBaru(kueDonat);
.select().single() setelah insert(): Kalau kamu mau dapet balik data yang baru aja diinsert (lengkap sama id dan created_at yang di-generate database) sebagai satu objek (bukan array), tambahin .select().single() di akhir.
2. Read (Membaca/Mengambil Data / select)
Ini operasi yang paling sering dilakuin. Buat ngambil data, kita pake metode .select().
select('string_kolom_atau_query'): String ini nentuin kolom apa aja yang mau diambil.
'*' : Ambil semua kolom.
nama_kolom: Ambil kolom spesifik.
kolom1, kolom2: Ambil beberapa kolom spesifik, dipisah koma.
nama_tabel_relasi(kolom_di_relasi): Buat ngambil data dari tabel yang berelasi (join). (Ini lebih advance, kita fokus ke kolom tabel utama dulu).
Kamu bisa nambahin berbagai modifier (filter, urutan, limit) sebelum .select().
Contoh Mengambil Data Kue:
typescript
// Ambil SEMUA kue dengan SEMUA kolomnyaasync function ambilSemuaKue() { const { data: semuaKue, error } = await supabase .from('kue') .select('*'); if (error) console.error("Error ambil semua kue:", error); else console.log("Semua Kue:", semuaKue); // semuaKue akan jadi array of Kue return semuaKue;}// ambilSemuaKue();// Ambil SEMUA kue, tapi cuma kolom NAMA dan HARGA ajaasync function ambilNamaDanHargaKue() { const { data, error } = await supabase .from('kue') .select('nama, harga'); // Pisah koma buat milih kolom if (error) console.error("Error:", error); else console.log("Nama & Harga Kue:", data);}// ambilNamaDanHargaKue();// Ambil SATU kue berdasarkan ID (misalnya, ID uuid string)async function ambilKueById(idKue: string) { const { data: kueDetail, error } = await supabase .from('kue') .select('*') .eq('id', idKue) // .eq() adalah filter "equals" (sama dengan) .single(); // .single() ngarepin cuma satu hasil, error kalau banyak atau gak ada (kecuali dihandle) if (error && error.code !== 'PGRST116') { console.error("Error ambil detail kue:", error); } else if (kueDetail) { console.log(`Detail Kue ID ${idKue}:`, kueDetail); } else { console.log(`Kue dengan ID ${idKue} tidak ditemukan.`); } return kueDetail;}// ambilKueById("uuid-kue-yang-valid"); // Ganti dengan ID uuid beneran// Ambil kue yang harganya di bawah 50000 dan urutkan dari harga termurahasync function ambilKueMurah() { const { data, error } = await supabase .from('kue') .select('nama, harga, kategori') .lt('harga', 50000) // .lt() adalah filter "less than" (kurang dari) .order('harga', { ascending: true }); // Urutkan berdasarkan harga, ascending if (error) console.error("Error:", error); else console.log("Kue Murah:", data);}// ambilKueMurah();
Query filter (kayak .eq()) WAJIB ada setelah delete() buat nentuin record mana yang mau dihapus.
Biasanya diakhiri .select() kalau mau dapet data yang baru aja dihapus (meskipun kadang gak perlu).
Contoh Menghapus Kue:
typescript
async function hapusKue(idKue: string) { // Sebaiknya tambahkan konfirmasi atau logika bisnis sebelum benar-benar menghapus const { data, error } = await supabase .from('kue') .delete() .eq('id', idKue) .select(); // (Opsional) if (error) console.error("Error hapus kue:", error); else console.log("Kue berhasil dihapus (data yang dihapus):", data);}// HATI-HATI SEBELUM MENJALANKAN INI!// hapusKue("uuid-kue-yang-mau-dihapus");
Penting: Row Level Security (RLS) dan Akses Data
Ingat, Supabase sangat menekankan keamanan dengan Row Level Security (RLS).
Kalau RLS di tabelmu aktif (dan seharusnya aktif untuk produksi!), anon key yang kita pake di Supabase Client ini cuma bisa ngelakuin operasi (SELECT, INSERT, UPDATE, DELETE) kalau ada Policy RLS yang ngebolehin.
Misalnya, buat insert data pesanan, kamu mungkin perlu bikin policy yang bilang "Pengguna yang sudah login (yang auth.uid()-nya sama dengan user_id di data pesanan) boleh INSERT."
Kalau query-mu gak jalan atau ngembaliin data kosong padahal harusnya ada, selalu cek RLS Policies-mu dulu di dashboard Supabase > Authentication > Policies (atau di Table Editor > Policies).
Dengan metode-metode .insert(), .select(), .update(), dan .delete() dari Supabase JS Client, kamu udah punya "senjata" lengkap buat ngelakuin semua operasi CRUD dasar ke database Supabase-mu. Yang keren, sintaksnya lumayan mirip SQL tapi ditulis dengan gaya JavaScript yang chaining.
Jangan lupa selalu cek error yang dikembaliin dan perhatiin RLS ya! Di bagian selanjutnya, kita bakal mulai nambahin fitur "pintu masuk" ke Toko Kue kita: Autentikasi Pengguna pake Supabase Auth!
Checkpoint KuisTarget: 70%
Kuis Operasi CRUD dengan Supabase JS Client
Kuis ini wajib untuk sertifikat. Kamu tetap bisa lanjut ke pelajaran berikutnya dan mengerjakannya nanti.