Kita sudah melatih setiap keterampilan secara terpisah: membuat server HTTP, merancang endpoint REST, menulis query parameterized, dan menguji kode dengan node:test. Proyek ini merangkai semuanya menjadi satu aplikasi yang utuh dan berguna: Blog API — layanan JSON tempat kita menerbitkan artikel dan menerima komentar pembaca, disimpan di SQLite lewat node:sqlite, dilayani oleh node:http murni tanpa framework. Seluruh kode nyata tersedia di folder src/ dan tests/, dan empat bagian tutorial menuntun kita membangunnya dari skema hingga test.

Apa yang Kita Bangun #

Aplikasi ini adalah API kecil dengan dua entitas yang berelasi: artikel dan komentar. Proyek sengaja dijaga tanpa dependensi eksternal — hanya modul inti Node.js — supaya fokus tertuju pada tiga hal yang paling berharga: desain skema relasional, disiplin query parameterized, dan pemetaan hasil database ke status code HTTP. Arsitekturnya mengikuti pola dari Section Architecture dan Design: lapisan data (src/db.js) tidak mengenal HTTP, lapisan HTTP (src/server.js) tidak membuka database sendiri, dan keduanya dihubungkan lewat fungsi pabrik buatDb(jalur) serta buatServer(db).

Daftar Endpoint #

Delapan endpoint menutupi seluruh kebutuhan dasar blog:

MethodPathSuksesKeterangan
GET/artikel200Daftar seluruh artikel; ?q= menyaring judul dan isi
POST/artikel201Tulis artikel baru dari body {judul, isi}
GET/artikel/:id200Satu artikel beserta komentarnya (hasil LEFT JOIN)
PATCH/artikel/:id200Ubah sebagian field artikel
DELETE/artikel/:id204Hapus artikel; komentarnya ikut terhapus lewat CASCADE
GET/artikel/:id/komentar200Daftar komentar; ?halaman= dan ?batas= untuk pagination
POST/artikel/:id/komentar201Tambah komentar dari body {nama, isi}
DELETE/komentar/:id204Hapus satu komentar

Kegagalan selalu dijawab JSON berbentuk {"galat": "..."}: status 400 untuk body yang tidak valid atau field kosong, dan 404 untuk id maupun endpoint yang tidak ditemukan.

Struktur Direktori #

text
blog-api/
├── package.json          # {"type": "module"} — seluruh berkas .js adalah ESM
├── bagian/               # empat bagian tutorial
│   ├── bagian-1-skema-database/
│   ├── bagian-2-endpoint-artikel/
│   ├── bagian-3-komentar-dan-relasi/
│   └── bagian-4-pengujian-dan-perapihan/
├── src/
│   ├── db.js             # skema + query parameterized (lapisan data)
│   ├── server.js         # routing + handler (lapisan HTTP)
│   ├── cli.js            # titik masuk produksi (PORT, DB_PATH)
│   └── demo.mjs          # sesi demo in-process
└── tests/
    ├── db.test.js        # test unit lapisan data
    └── api.test.js       # integration test endpoint

Sesi Pemakaian Singkat #

Seperti apa tampilannya saat API ini bekerja? Berkas src/demo.mjs menjawabnya dengan satu sesi nyata: ia menyalakan server di port acak pada database :memory:, menjalankan rangkaian permintaan lewat fetch, mencetak status beserta body, lalu mematikan semuanya — deterministik, tanpa menyisakan berkas:

bash
node src/demo.mjs

Output yang Dihasilkan:

text
POST /artikel -> 201 {"id":1,"judul":"Belajar node:sqlite","isi":"SQLite kini dibawa langsung oleh Node.js tanpa package tambahan.","created_at":"2026-01-15T08:00:00.000Z"}
POST /artikel -> 201 {"id":2,"judul":"REST API tanpa framework","isi":"Untuk API kecil, node:http sudah lebih dari cukup.","created_at":"2026-01-15T08:00:00.000Z"}
GET /artikel -> 200 [{"id":1,"judul":"Belajar node:sqlite","isi":"SQLite kini dibawa langsung oleh Node.js tanpa package tambahan.","created_at":"2026-01-15T08:00:00.000Z"},{"id":2,"judul":"REST API tanpa framework","isi":"Untuk API kecil, node:http sudah lebih dari cukup.","created_at":"2026-01-15T08:00:00.000Z"}]
GET /artikel?q=sqlite -> 200 [{"id":1,"judul":"Belajar node:sqlite","isi":"SQLite kini dibawa langsung oleh Node.js tanpa package tambahan.","created_at":"2026-01-15T08:00:00.000Z"}]
POST /artikel/1/komentar -> 201 {"id":1,"artikel_id":1,"nama":"Siti","isi":"Penjelasannya jelas sekali, terima kasih!","created_at":"2026-01-15T08:00:00.000Z"}
POST /artikel/1/komentar -> 201 {"id":2,"artikel_id":1,"nama":"Dewi","isi":"Saya menunggu tulisan lanjutannya.","created_at":"2026-01-15T08:00:00.000Z"}
POST /artikel/2/komentar -> 201 {"id":3,"artikel_id":2,"nama":"Budi","isi":"Setuju, tanpa dependensi tambahan.","created_at":"2026-01-15T08:00:00.000Z"}
GET /artikel/1 -> 200 {"id":1,"judul":"Belajar node:sqlite","isi":"SQLite kini dibawa langsung oleh Node.js tanpa package tambahan.","created_at":"2026-01-15T08:00:00.000Z","komentar":[{"id":1,"nama":"Siti","isi":"Penjelasannya jelas sekali, terima kasih!","created_at":"2026-01-15T08:00:00.000Z"},{"id":2,"nama":"Dewi","isi":"Saya menunggu tulisan lanjutannya.","created_at":"2026-01-15T08:00:00.000Z"}]}
GET /artikel/1/komentar?halaman=1&batas=1 -> 200 [{"id":1,"nama":"Siti","isi":"Penjelasannya jelas sekali, terima kasih!","created_at":"2026-01-15T08:00:00.000Z"}]
PATCH /artikel/2 -> 200 {"id":2,"judul":"REST API dengan node:http","isi":"Untuk API kecil, node:http sudah lebih dari cukup.","created_at":"2026-01-15T08:00:00.000Z"}
POST /artikel -> 400 {"galat":"Field judul wajib string tidak kosong"}
GET /artikel/999 -> 404 {"galat":"Artikel tidak ditemukan"}
POST /artikel/999/komentar -> 404 {"galat":"Artikel tidak ditemukan"}
DELETE /komentar/3 -> 204
DELETE /artikel/1 -> 204
GET /artikel/1 -> 404 {"galat":"Artikel tidak ditemukan"}
komentar tersisa milik artikel 1 (efek CASCADE): 0

Sesi di atas sudah menyentuh hampir seluruh permukaan API: menulis dua artikel, menyaring dengan ?q=, berkomentar, melihat detail yang menyematkan komentar, membelah halaman komentar, menabrak validasi 400 dan 404, menghapus, dan membuktikan komentar ikut terhapus. Untuk pemakaian interaktif, node src/cli.js menyalakan server yang sama di http://localhost:3000 dengan database berkas data/blog.db.

Pembagian Empat Bagian #

  1. Bagian 1 — Skema Database: merancang tabel artikel dan komentar beserta foreign key, indeks, dan pabrik buatDb dengan jam yang bisa disuntik.
  2. Bagian 2 — Endpoint Artikel: membangun buatServer(db), routing berbasis segmen, dan empat operasi CRUD artikel lengkap dengan status code dan validasi body.
  3. Bagian 3 — Komentar dan Relasi: endpoint bersarang untuk komentar, LEFT JOIN yang menyatukan dua tabel, pagination LIMIT/OFFSET, dan penghapusan berantai CASCADE.
  4. Bagian 4 — Pengujian dan Perapihan: test unit dan integration test dengan node:test, titik masuk produksi src/cli.js, serta daftar pengembangan lanjutan.

Seluruh proyek ditutup dengan satu perintah node --test yang harus hijau penuh — empat puluh tiga test yang menjaga setiap perilaku di tabel endpoint tetap terpenuhi. Mari kita mulai dari fondasinya: skema database.

Referensi resmi: node:sqlite dan node:http .