engineering docs

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

  1. Ambil user dan organization dari runner.
  2. Validasi organizationId pada runner.
  3. Validasi resource reference di database pemiliknya.
  4. Tulis record pada database domain.
  5. 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.