CRUD yang benar
CRUD bukan sekadar meneruskan fetch. Setiap operasi harus melewati route API, validasi schema, autentikasi, ownership check, dan service database.
Read
const response = await fetch(`${API_URL}/api/organization/${organizationId}/products`, {
headers: { Accept: 'application/json' },
cache: 'no-store'
});
if (!response.ok) throw new Error('Failed to load products');
const products = await response.json();Scope organisasi berasal dari session, bukan hanya input URL. API harus menolak ID yang tidak dimiliki user.
Create
await apiFetch('/api/organization', {
method: 'POST',
body: { name, email, category: 'retail' },
headers: { Authorization: `Bearer ${token}` }
});Validasi required fields, enum, format email, dan duplicate key berada di server. Client validation hanya untuk feedback cepat.
Update dan delete
await apiFetch(`/api/organization/${organizationId}`, {
method: 'PATCH',
body: { displayName },
headers: { Authorization: `Bearer ${token}` }
});
await apiFetch(`/api/organization/${organizationId}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${token}` }
});Gunakan PATCH untuk perubahan parsial. Jangan menghapus record lintas database tanpa cascade policy yang jelas. Untuk resource turunan, validasi parent dan ownership dalam transaksi/service yang sama.
Aturan lintas database
- Ambil user dan organization dari
runner. - Validasi
organizationIdpada runner. - Validasi resource reference di database pemiliknya.
- Tulis record pada database domain.
- Kembalikan response yang tidak mengekspos credential atau internal stack.
Jangan melakukan write langsung dari server component ke Prisma client database lain; panggil service/API boundary yang memiliki aturan tersebut.