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:
| Method | Path | Sukses | Keterangan |
|---|---|---|---|
| GET | /artikel | 200 | Daftar seluruh artikel; ?q= menyaring judul dan isi |
| POST | /artikel | 201 | Tulis artikel baru dari body {judul, isi} |
| GET | /artikel/:id | 200 | Satu artikel beserta komentarnya (hasil LEFT JOIN) |
| PATCH | /artikel/:id | 200 | Ubah sebagian field artikel |
| DELETE | /artikel/:id | 204 | Hapus artikel; komentarnya ikut terhapus lewat CASCADE |
| GET | /artikel/:id/komentar | 200 | Daftar komentar; ?halaman= dan ?batas= untuk pagination |
| POST | /artikel/:id/komentar | 201 | Tambah komentar dari body {nama, isi} |
| DELETE | /komentar/:id | 204 | Hapus 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 #
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 endpointSesi 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:
node src/demo.mjsOutput yang Dihasilkan:
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): 0Sesi 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 #
- Bagian 1 — Skema Database: merancang tabel
artikeldankomentarbeserta foreign key, indeks, dan pabrikbuatDbdengan jam yang bisa disuntik. - Bagian 2 — Endpoint Artikel: membangun
buatServer(db), routing berbasis segmen, dan empat operasi CRUD artikel lengkap dengan status code dan validasi body. - Bagian 3 — Komentar dan Relasi: endpoint bersarang untuk komentar,
LEFT JOINyang menyatukan dua tabel, paginationLIMIT/OFFSET, dan penghapusan berantaiCASCADE. - Bagian 4 — Pengujian dan Perapihan: test unit dan integration test dengan
node:test, titik masuk produksisrc/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 .
Rancang skema SQLite untuk artikel dan komentar dengan node:sqlite.
Buka → # Bagian 2: Endpoint ArtikelImplementasikan CRUD artikel dengan query parameterized.
Buka → # Bagian 3: Komentar dan RelasiImplementasikan komentar berelasi dengan JOIN dan pagination.
Buka → # Bagian 4: Pengujian dan PerapihanUji endpoint dan relasi database lewat integration test terisolasi.
Buka →