Mengimplementasikan Operasi CRUD dengan Hapi JS dan PostgreSQL

Andro Syahreza
7 min readMar 8, 2023

--

Dalam pengembangan aplikasi, mengelola data dan menyimpannya dalam database merupakan hal yang sangat penting. Operasi CRUD (Create, Read, Update, Delete) merupakan operasi dasar yang digunakan untuk mengelola data dalam database. Operasi CRUD dapat diterapkan dengan menggunakan berbagai framework dan database.

Pada artikel sebelumnya, Menerapkan Plugin dan Routing Pada Aplikasi Hapi JS, kita telah berhasil membuat project Hapi menjadi modular dan membuat routing. Pada artikel ini, akan dibahas tentang bagaimana mengimplementasikan operasi CRUD menggunakan Hapi JS dan PostgreSQL.

Tools yang digunakan dalam project

Berikut adalah tools tambahan yang perlu dipersiapkan:

Deskripsi project dan pengenalan endpoint

Project ini merupakan lanjutan dari artikel sebelumnya, Silakan buka repositori Github untuk melihat kode sebelumnya.

Pada project ini akan dibuat tabel orders pada database PostgreSQL dan operasi CRUD yang akan dibuat adalah sebagai berikut:

project endpoint

Membuat project dan menginstall modul

Silakan buka terminal lalu jalankan perintah berikut:

npm i @hapi/boom dotenv pg sequelize

Perintah diatas berfungsi untuk menginstall modul berikut:

  • @hapi/boom : mengembalikan HTTP error untuk framework Hapi JS
  • dotenv : mengelola konfigurasi aplikasi Node JS, biasanya digunakan untuk menyimpan informasi rahasia
  • pg : modul untuk mengakses PostgreSQL database di Node JS
  • sequelize : ORM (Object-Relational Mapping) untuk Node.js yang mendukung berbagai jenis database seperti PostgreSQL

Kemudian masuk ke dalam folder src dan buatlah folder controller, config, dan models. Berikut adalah susunan foldernya:

- src
- config
- controller
- models
- routes
- route.js
- server.js

Selanjutnya buatlah file berikut pada folder yang tersedia:

  • pada folder config buatlah file config.js
  • pada folder controller buatlah file order.controller.js
  • pada folder models buatlah file index.js dan orders.js

Untuk sementara, biarkan file tetap kosong.

Setelah file berhasil dibuat maka susunan folder akan menjadi seperti berikut:

- src
- config
- config.js
- controller
- order.controller.js
- models
- index.js
- orders.js
- routes
- route.js
- server.js

Membuat username dan database pada PostgreSQL

Silakan buka terminal, lalu login menggunakan username default dari PostgreSQL yaitu postgres dengan mengetik perintah berikut:

psql postgres postgres

Buat username baru dengan perintah berikut:

CREATE ROLE admintutorial WITH LOGIN PASSWORD 'tutorial';
ALTER ROLE admintutorial CREATEDB ;
\q

Setelah user berhasil dibuat, silakan login dan buat database dengan perintah berikut:

psql -U admintutorial -d postgres
CREATE DATABASE hapi_rest_api;
\q

Melakukan konfigurasi database

Di dalam root folder buatlah file .env , buka file tersebut lalu ketikkan kode berikut:

DB_NAME = "hapi_rest_api"
DB_USER = "admintutorial"
DB_PASSWORD = "tutorial"
DB_HOST = "127.0.0.1"
DB_PORT = "5432"
  • File .env diatas berisi konfigurasi database yang akan kita gunakan. Karena file .env berisi informasi sensitif, maka file .env harus disimpan secara aman dan tidak boleh diunggah ke repositori git publik. Kita perlu menambahkannya ke dalam file .gitignore.
  • File .gitignore digunakan untuk menyimpan daftar file dan folder yang tidak ingin dimasukkan ke dalam repositori git.

Silakan buat file .gitignore pada root direktori, dan masukkan kode berikut:

node_modules
.env

Selanjutnya, silakan buka file config.js pada folder config , kemudian ketikkan code berikut:

require("dotenv").config();
module.exports = {
HOST: process.env.DB_HOST,
USER: process.env.DB_USER,
PASSWORD: process.env.DB_PASSWORD,
DB: process.env.DB_NAME,
dialect: 'postgres',
}

require(“dotenv”).config() berfungsi untuk melakukan konfigurasi environment variable dari file .env ke dalam process.env.

Mendefinisikan model dan membuat koneksi ke database

Selanjutnya, silakan buka file orders.js pada folder models, lalu ketikkan kode berikut:

module.exports = (sequelize, DataTypes) => {
const Order = sequelize.define("orders", {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
product_name: {
type: DataTypes.STRING,
allowNull: false,
},
order_date: {
type: DataTypes.DATE,
allowNull: false,
},
amount: {
type: DataTypes.INTEGER,
allowNull: false,
},
});

return Order;
};

Kode diatas berfungsi untuk menentukan struktur dan tipe data dari kolom pada tabel orders. Kode diatas mengembalikan objek Order yang akan merepresentasikan model orders sehingga model ini dapat diterapkan untuk melakukan operasi CRUD.

Selanjutnya, silakan buka file index.js pada folder models, lalu ketikkan kode berikut:

const dbConfig = require("../config/config");
const { Sequelize, DataTypes } = require("sequelize");

const sequelize = new Sequelize(dbConfig.DB, dbConfig.USER, dbConfig.PASSWORD, {
host: dbConfig.HOST,
dialect: dbConfig.dialect,
operatorsAliases: false,
});

sequelize
.authenticate()
.then(() => {
console.log("Connected to database!");
})
.catch((err) => {
console.log("Error" + err);
});

const db = {};

db.Sequelize = Sequelize;
db.sequelize = sequelize;

db.orders = require("./orders.js")(sequelize, DataTypes);

db.sequelize.sync({ force: false }).then(() => {
console.log("re-sync done!");
});

module.exports = db;
  • Pada file index.js dilakukan koneksi ke database menggunakan fungsi dari sequelize yaitu new Sequelize() dengan menggunakan konfigurasi yang telah diimpor sebelumnya
  • Selanjutnya dilakukan autentikasi konesi ke database menggunakan sequelize.authenticate().
  • const db = {} berfungsi untuk membuat objek db yang kemudian akan diisi dengan model sequelize.
  • db.orders = require(“./orders.js”)(sequelize, DataTypes) berfungsi untuk menambahkan model orders yang telah dibuat
  • db.sequelize.sync({ force: false }) berfungsi untuk melakukan sinkronisasi model dengan database
  • di akhir kode, objek db diekspor agar dapat digunakan diseluruh aplikasi

Membuat controller untuk operasi CRUD

Buka file order.controller.js pada folder controller, lalu tambahkan kode berikut:

const db = require("../models");
const Boom = require("@hapi/boom");

const Orders = db.orders;

const OrderController = {
async addOrder(request, h) {
try {
const { product_name, order_date, amount } = request.payload;
const order = await Orders.create({ product_name, order_date, amount });
return h.response(order).code(201);
} catch (err) {
return Boom.internal(err.message);
}
},
async getOrder(request, h) {
try {
const order = await Orders.findAll({
attributes: ["id", "product_name", "order_date", "amount"],
});
return h.response(order).code(200);
} catch (err) {
return Boom.internal(err.message);
}
},
async getOrderById(request, h) {
try {
const { id } = request.params;
const order = await Orders.findByPk(id, {
attributes: ["id", "product_name", "order_date", "amount"],
});
if (!order) {
return Boom.notFound(`Order with id ${id} not found`);
} else {
return h.response(order).code(200);
}
} catch (err) {
return Boom.internal(err.message);
}
},
async udpateOrder(request, h) {
try {
const { id } = request.params;
const order = await Orders.findByPk(id);
if (!order) {
return Boom.notFound(`Order with id ${id} not found`);
} else {
const { product_name, order_date, amount } = request.payload;
await Orders.update(
{ product_name, order_date, amount },
{ where: { id } }
);
return "Successfully Updated";
}
} catch (err) {
return Boom.internal(err.message);
}
},
async deleteOrder(request, h) {
try {
const { id } = request.params;
const order = await Orders.findByPk(id);
if (!order) {
return Boom.notFound(`Order with id ${id} not found`);
} else {
await Orders.destroy({ where: { id } });
return "Successfully Deleted";
}
} catch (err) {
return Boom.internal(err.message);
}
},
};

module.exports = OrderController;

Pada kode diatas terdapat beberapa fungsi yang ada di dalam objek OrderController, antara lain :

  • addOrder() : berfungsi untuk menambahkan data order baru ke database.
  • getOrder() : berfungsi untuk mengambil semua data order dari database dan mengembalikannya dengan atribut "id", "product_name", "order_date", dan "amount" .
  • getOrderById() : berfungsi untuk mengambil data order berdasarkan ID dan mengembalikannya dengan atribut "id", "product_name", "order_date", dan "amount" .
  • udpateOrder() : berfungsi untuk memperbarui data order berdasarkan ID.
  • deleteOrder() : berfungsi untuk menghapus data order berdasarkan ID.

Setiap fungsi menggunakan async/await untuk menangani operasi yang bersifat asinkron. Fungsi tersebut juga menggunakan library @hapi/boom untuk menangani kesalahan atau error. Controller ini diekspor dan akan digunakan pada route.

Menambahkan route

Setelah controller berhasil dibuat, silakan tambahkan route dengan memasukkan kode berikut pada file route.js :

const OrderController = require("../controller/order.controller");

const routes = [
{
method: "GET",
path: "/",
handler: (request, h) => {
return "Hello World !";
},
},
{
method: "GET",
path: "/{any*}",
handler: (request, h) => {
return "Oops! You must be lost!";
},
},
{
method: "POST",
path: "/api/orders",
handler: OrderController.addOrder,
},
{
method: "GET",
path: "/api/orders",
handler: OrderController.getOrder,
},
{
method: "GET",
path: "/api/orders/{id}",
handler: OrderController.getOrderById,
},
{
method: "PUT",
path: "/api/orders/{id}",
handler: OrderController.udpateOrder,
},
{
method: "DELETE",
path: "/api/orders/{id}",
handler: OrderController.deleteOrder,
},
];

module.exports = {
name: "routes",
version: "1.0.0",
register: async (server, options) => {
server.route(routes);
},
};

Pada kode diatas, handler untuk setiap rute menggunakan controller yang telah diimpor sebelumnya, yaitu OrderController. Controller ini berisi beberapa fungsi yang akan dijalankan ketika rute yang terkait dipanggil. Prefix “/api/” pada path bertujuan untuk memberi tanda bahwa endpoint tersebut terkait dengan API (Application Programming Interface) dan juga merupakan salah satu penerapan best practice.

Melakukan testing dengan Postman

Jalankan aplikasi dengan perintah berikut:

npm start

Selanjutnya untuk mencoba operasi CRUD, silakan buka aplikasi Postman dan buatlah new collection seperti berikut:

add new collection

Setelah collection berhasil dibuat, tampilan new collection akan seperti berikut:

new collection

Silakan tentukan nama collection dan tambahkan request, kemudian masukkan request URL serta body (jika diperlukan). Untuk melakukan tes silakan klik tombol send. Berikut adalah hasil testing:

  • Add Order
POST: http://localhost:3000/api/orders
  • Get Order
GET : http://localhost:3000/api/orders
  • Get Order By Id
GET : http://localhost:3000/api/orders/1
  • Update Order
PUT : http://localhost:3000/api/orders/1
  • Delete Order
DELETE : http://localhost:3000/api/orders/1

Selamat!!! dengan demikian kamu telah berhasil menerapkan operasi CRUD menggunakan Hapi JS dan PostgreSQL!

Sumber:
https://www.dewaweb.com/blog/apa-itu-crud/
https://sequelize.org/docs/v6/core-concepts/model-basics/

Silakan kunjungi repositori Github untuk melihat seluruh kode yang telah dibahas dalam artikel ini.

Ingin mengetahui lebih banyak? Jangan lewatkan artikel selanjutnya yang akan membahas topik Menarik tentang Menerapkan Pagination Pada Aplikasi Hapi JS.

--

--

Andro Syahreza
Andro Syahreza

Written by Andro Syahreza

0 Followers

Backend Web Development Enthusiast

No responses yet