Selamat datang di repositori Bookshelf API! Proyek ini merupakan submission untuk kelas "Belajar Back-End Pemula dengan JavaScript" dari Dicoding Indonesia. API ini memungkinkan pengguna untuk menyimpan, melihat, memperbarui, dan menghapus data buku dalam sebuah rak buku digital.
Proyek ini dibangun dengan Node.js dan menggunakan Hapi Framework (atau Node.js native, sesuai pilihan Anda saat mengerjakan) untuk menangani routing dan request/response HTTP. Data buku disimpan sementara dalam memori server.
Proyek ini dibuat sebagai syarat kelulusan dari kelas "Belajar Back-End Pemula dengan JavaScript" di Dicoding. Melalui pengerjaan proyek ini, konsep-konsep berikut telah dipelajari dan diterapkan:
- Istilah back-end, front-end, server, client, web service, REST API.
- Komunikasi client-server menggunakan cURL.
- Dasar-dasar Node.js: global object, process, modularization, event, dll.
- Membangun web server dengan Node.js native maupun Hapi Framework.
- Membuat RESTful API sederhana.
- (Meskipun tidak diimplementasikan dalam submission ini, konsep deploy ke Amazon EC2 dan pengujian otomatis dengan Postman juga telah dipelajari).
- Fitur Utama
- Prasyarat
- Instalasi
- Menjalankan Aplikasi
- Struktur Proyek (Contoh)
- Dokumentasi API
- Kriteria Proyek
- Fitur Opsional yang Diimplementasikan
- Pengujian API
- Teknologi yang Digunakan
- Menyimpan Buku Baru: Menambahkan buku baru ke dalam daftar.
- Menampilkan Semua Buku: Mendapatkan daftar semua buku yang tersimpan, dengan opsi filter.
- Menampilkan Detail Buku: Mendapatkan informasi lengkap satu buku berdasarkan ID.
- Mengubah Data Buku: Memperbarui informasi buku yang sudah ada.
- Menghapus Buku: Menghapus buku dari daftar.
- Node.js (Versi LTS yang direkomendasikan untuk reviewer adalah 18.13.0 atau lebih baru)
- NPM (biasanya terinstal bersama Node.js)
- Git (untuk clone repositori)
- Postman (untuk pengujian API)
-
Clone repositori ini ke mesin lokal Anda:
git clone https://github.com/irfandwisamudra/bookshelf-api.git cd bookshelf-api
-
Instal semua dependensi yang dibutuhkan:
npm install
Aplikasi ini dapat dijalankan menggunakan perintah berikut pada package.json:
- Untuk mode produksi (sesuai kriteria submission):
Ini akan menjalankan server menggunakan
npm run start
node src/server.js
(atau path ke file server utama Anda).
Secara default, server akan berjalan pada port 9000
.
Berikut adalah struktur direktori yang saya gunakan:
bookshelf-api/
├── src/
│ ├── books.js # Array untuk menyimpan data buku (in-memory)
│ ├── handler.js # Logika handler untuk setiap route
│ ├── routes.js # Definisi semua route API
│ └── server.js # Konfigurasi dan start Hapi server
├── .gitignore
├── .eslintrc.json # Konfigurasi ESLint
├── package-lock.json
├── package.json
└── README.md
API ini menyediakan beberapa endpoint untuk mengelola data buku.
-
Method:
POST
-
URL:
/books
-
Body Request (JSON):
{ "name": "string", "year": "number", "author": "string", "summary": "string", "publisher": "string", "pageCount": "number", "readPage": "number", "reading": "boolean" }
-
Struktur Objek Buku yang Disimpan:
{ "id": "Qbax5Oy7L8WKf74l", // string, unik (nanoid) "name": "Buku A", "year": 2010, "author": "John Doe", "summary": "Lorem ipsum dolor sit amet", "publisher": "Dicoding Indonesia", "pageCount": 100, "readPage": 25, "finished": false, // boolean (pageCount === readPage) "reading": false, "insertedAt": "2021-03-04T09:11:44.598Z", // string (new Date().toISOString()) "updatedAt": "2021-03-04T09:11:44.598Z" // string (new Date().toISOString()) }
-
Respons Sukses (201 Created):
{ "status": "success", "message": "Buku berhasil ditambahkan", "data": { "bookId": "1L7ZtDUFeGs7VlEt" } }
-
Respons Gagal (400 Bad Request):
- Jika
name
tidak dilampirkan:{ "status": "fail", "message": "Gagal menambahkan buku. Mohon isi nama buku" }
- Jika
readPage
>pageCount
:{ "status": "fail", "message": "Gagal menambahkan buku. readPage tidak boleh lebih besar dari pageCount" }
- Jika
-
Method:
GET
-
URL:
/books
-
Query Parameters (Opsional):
name
:string
(filter buku berdasarkan nama, non-case sensitive)- Contoh:
/books?name=dicoding
- Contoh:
reading
:0
atau1
(filter buku berdasarkan status dibaca)0
:reading: false
1
:reading: true
- Contoh:
/books?reading=1
finished
:0
atau1
(filter buku berdasarkan status selesai dibaca)0
:finished: false
1
:finished: true
- Contoh:
/books?finished=0
-
Respons Sukses (200 OK):
{ "status": "success", "data": { "books": [ { "id": "Qbax5Oy7L8WKf74l", "name": "Buku A", "publisher": "Dicoding Indonesia" } // ... buku lainnya ] } }
Jika tidak ada buku,
books
akan menjadi array kosong:{ "status": "success", "data": { "books": [] } }
-
Method:
GET
-
URL:
/books/{bookId}
-
Path Parameter:
bookId
: ID unik buku
-
Respons Sukses (200 OK):
{ "status": "success", "data": { "book": { "id": "aWZBUW3JN_VBE-9I", "name": "Buku A Revisi", "year": 2011, "author": "Jane Doe", "summary": "Lorem Dolor sit Amet", "publisher": "Dicoding", "pageCount": 200, "readPage": 26, "finished": false, "reading": false, "insertedAt": "2021-03-05T06:14:28.930Z", "updatedAt": "2021-03-05T06:14:30.718Z" } } }
-
Respons Gagal (404 Not Found):
- Jika
bookId
tidak ditemukan:{ "status": "fail", "message": "Buku tidak ditemukan" }
- Jika
- Method:
PUT
- URL:
/books/{bookId}
- Path Parameter:
bookId
: ID unik buku
- Body Request (JSON):
{ "name": "string", "year": "number", "author": "string", "summary": "string", "publisher": "string", "pageCount": "number", "readPage": "number", "reading": "boolean" }
- Respons Sukses (200 OK):
{ "status": "success", "message": "Buku berhasil diperbarui" }
- Respons Gagal (400 Bad Request):
- Jika
name
tidak dilampirkan:{ "status": "fail", "message": "Gagal memperbarui buku. Mohon isi nama buku" }
- Jika
readPage
>pageCount
:{ "status": "fail", "message": "Gagal memperbarui buku. readPage tidak boleh lebih besar dari pageCount" }
- Jika
- Respons Gagal (404 Not Found):
- Jika
bookId
tidak ditemukan:{ "status": "fail", "message": "Gagal memperbarui buku. Id tidak ditemukan" }
- Jika
-
Method:
DELETE
-
URL:
/books/{bookId}
-
Path Parameter:
bookId
: ID unik buku
-
Respons Sukses (200 OK):
{ "status": "success", "message": "Buku berhasil dihapus" }
-
Respons Gagal (404 Not Found):
- Jika
bookId
tidak ditemukan:{ "status": "fail", "message": "Buku gagal dihapus. Id tidak ditemukan" }
- Jika
Proyek ini telah memenuhi kriteria wajib berikut:
- Aplikasi menggunakan port
9000
. - Aplikasi dijalankan dengan perintah
npm run start
(bukannodemon
). - API dapat menyimpan buku sesuai spesifikasi.
- API dapat menampilkan seluruh buku sesuai spesifikasi.
- API dapat menampilkan detail buku sesuai spesifikasi.
- API dapat mengubah data buku sesuai spesifikasi.
- API dapat menghapus buku sesuai spesifikasi.
- Menggunakan
nanoid@3
untuk ID unik buku. - Data buku disimpan dalam struktur yang benar, termasuk properti
id
,finished
,insertedAt
, danupdatedAt
yang diolah di sisi server. - Validasi input (misalnya,
name
wajib ada,readPage
tidak boleh lebih besar daripageCount
) diimplementasikan dengan respons error yang sesuai.
- Query Parameters pada
GET /books
:-
?name
: Filter buku berdasarkan nama. -
?reading
: Filter buku berdasarkan statusreading
. -
?finished
: Filter buku berdasarkan statusfinished
.
-
- Penggunaan ESLint dan Style Guide:
- Proyek ini menggunakan ESLint dengan style guide Dicoding Academy.
- Perintah
npx eslint .
tidak menghasilkan error.
Pengujian API dapat dilakukan menggunakan Postman. Dicoding telah menyediakan Collection dan Environment untuk pengujian ini:
- Unduh berkas pengujian dari tautan yang diberikan oleh Dicoding.
- Ekstrak berkas ZIP hingga mendapatkan dua file JSON (Collection dan Environment).
- Import kedua file JSON tersebut ke dalam aplikasi Postman Anda melalui tombol "Import".
- Pastikan server API Anda sedang berjalan (
npm run start
). - Pilih environment yang sesuai di Postman.
- Jalankan request yang ada dalam collection untuk menguji setiap endpoint. Perhatikan request yang bertanda
[Mandatory]
dan[Optional]
.
- Node.js: Lingkungan runtime JavaScript.
- Hapi Framework: Framework untuk membangun API. * nanoid (versi 3): Untuk generate ID unik.
- ESLint (Opsional): Linter untuk menjaga konsistensi kode.
Dibuat dengan ❤️ untuk Submission Dicoding.
Disusun oleh: Irfan Dwi Samudra (irfandwisamudra)