DISKON TERBATAS! Masukkan kupon "skillbaru" saat checkout di kelas apa saja
Skodev
Belajar coding dalam bahasa Indonesia
Di antara banyaknya opsi framework backend web yang tersedia, Elysia adalah salah satu framework backend yang wajib teman-teman coba untuk membuat aplikasi backend yang super ngebut.
Daftar Isi:
Dalam pengembangan aplikasi web, framework backend memainkan peran penting dalam menyediakan fondasi dan kerangka kerja yang robust untuk membangun aplikasi yang scalable dan maintainable. Framework backend membantu developer dalam mempermudah pengelolaan data, logika aplikasi, autentikasi, dan berbagai fungsi backend lainnya yang penting untuk aplikasi web yang modern.
Bun adalah runtime JavaScript all-in-one yang dibuat dengan tujuan untuk mempercepat pengembangan aplikasi. Bun menyediakan environment development yang ringan dan cepat untuk menjalankan Javascript dan Typescript, membuat bundling, transpiling, dan menjalankan kode lebih efisien. Dengan dukungan yang luas untuk API NodeJS dan kecepatan yang tinggi, Bun menjadi pilihan menarik bagi developer yang mencari runtime yang cepat dan efisien.
Baca Juga: Mengenal Bun, Runtime Javascript cepat
Saat ini sudah tersedia banyak opsi framework backend Javascript, tetapi kebanyakan masih berjalan di NodeJS. Nah, pada artikel kali ini aku akan membahas tentang Elysia, sebuah framework backend yang berjalan di Bun. Aku akan menjelaskan mulai dari pengenalan, keunggulan, hingga panduan praktis untuk memulai proyek dengan Elysia menggunakan Bun. Langsung saja kita ke pembahasannya ya teman-teman.
Elysia adalah framework backend web yang dibangun di atas Bun. Tujuan utama dari pengembangan Elysia adalah untuk menyediakan framework yang mudah digunakan, efisien, dan memiliki performa tinggi untuk pengembangan aplikasi web modern. Elysia memanfaatkan kecepatan dan efisiensi Bun untuk memberikan pengalaman pengembangan yang optimal.
Untuk memulai proyek dengan Elysia menggunakan Bun, ikuti langkah-langkah berikut:
Kunjungi situs resmi Bun di Situs Resmi Bun dan ikuti petunjuk instalasi sesuai dengan sistem operasi yang kalian gunakan.
curl -fsSL https://bun.sh/install | bash
Setelah instalasi selesai, pastikan Bun telah terinstal dengan benar dengan menjalankan perintah berikut di terminal:
bun --version
Buat direktori baru untuk proyek kalian dan inisialisasi proyek dengan Bun.
mkdir elysia-project
cd elysia-project
bun init
Install Elysia dan @elysiajs/swagger sebagai dependensi dalam proyek kalian.
bun add elysia @elysiajs/swagger
package.json
Tambahkan kode di bawah ini pada file package.json
kalian.
"scripts": {
"dev": "bun --watch src/index.ts",
"build": "bun build src/index.ts",
"start": "NODE_ENV=production bun src/index.ts"
},
Script diatas merujuk pada tahapan-tahapan berbeda dalam mengembangkan sebuah aplikasi:
Setelah menginisialisasi proyek, struktur direktori proyek akan terlihat seperti ini:
elysia-project/
├── node_modules/
├── src/
│ └── index.ts
├── .gitignore
├── bun.lockb
├── package.json
├── README.md
└── tsconfig.json
Sekarang, kita akan membuat REST API sederhana menggunakan Elysia. Disini aku akan menggunakan bahasa Typescript dan studi kasus yang akan kita gunakan adalah API CRUD (Create, Read, Update, Delete) untuk mengelola kontak. Berikut merupakan langkah-langkahnya:
Buat file types.d.ts
pada root project dan tambahkan type untuk kontak.
type Contact {
id: number;
name: string;
email: string;
}
db.ts
di folder src
File ini akan berperan sebagai pusat operasi CRUD dari API kontak. Tambahkan kode di bawah ini pada file db.ts
.
const contacts: Contact[] = [];
let nextId = 1;
export class ContactDB {
async getContacts(): Promise<Contact[]> {
return contacts;
}
async getContact(id: number): Promise<Contact | undefined> {
return contacts.find(c => c.id === id);
}
async addContact(contact: Omit<Contact, 'id'>): Promise<Contact> {
const newContact = { ...contact, id: nextId++ };
contacts.push(newContact);
return newContact;
}
async updateContact(id: number, updatedContact: Omit<Contact, 'id'>): Promise<string | undefined> {
const contactIndex = contacts.findIndex(c => c.id === id);
if (contactIndex !== -1) {
contacts[contactIndex] = { ...updatedContact, id };
return "success";
} else {
return undefined;
}
}
async removeContact(id: number): Promise<string | undefined> {
const contactIndex = contacts.findIndex(c => c.id === id);
if (contactIndex !== -1) {
contacts.splice(contactIndex, 1);
return "success";
} else {
return undefined;
}
}
}
contactApi
pada file index.ts
**Buat plugin instance contactApi
pada file index.ts
untuk mengelompokkan route dengan prefix /api
.
..
import { Elysia } from 'elysia';
..
const contactApi = new Elysia({ prefix: '/api' })
...
Tambahkan endpoint untuk menambah kontak baru pada contactApi
.
...
import { ContactDB } from './db';
...
.post(
"/contacts",
async ({ db, body }: { db: ContactDB, body: Contact }) => {
const id = (await db.addContact(body)).id
return { success: true, message: `Contact ${id} added` };
},
{
detail: {
summary: 'Add contact',
description: 'Add contact to the database',
requestBody: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
name: { type: 'string' },
email: { type: 'string' }
},
example: {
name: 'Wahyu',
email: 'wahyu@example.com'
},
required: ['name', 'email']
}
}
}
},
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: true
},
message: {
type: 'string',
example: 'Contact 1 added'
}
},
required: ['success', 'message']
}
}
}
},
400: {
description: 'Bad Request',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: false
},
message: {
type: 'string',
example: 'Invalid request'
}
},
required: ['success', 'message']
}
}
}
}
}
}
}
)
...
Tambahkan endpoint untuk mendapatkan list semua kontak pada contactApi
.
...
.get('/contacts',
async ({ db }: { db: ContactDB }) => {
const contacts = await db.getContacts();
return {
success: true,
data: contacts
};
},
{
detail: {
summary: 'Get contacts',
description: 'Get all contacts from the database',
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean'
},
data: {
type: 'array',
items: {
$ref: '#/components/schemas/Contact'
},
example: [{
id: 1,
name: 'Wahyu',
email: 'wahyu@example.com'
}]
}
},
required: ['success', 'data']
}
}
}
}
}
}
}
)
...
Tambahkan endpoint untuk mendapatkan kontak berdasarkan ID pada contactApi
.
...
.get('/contacts/:id',
async ({ db, params }: { db: ContactDB, params: { id: string } }) => {
const id = parseInt(params.id);
if (id === undefined) {
return { success: false, message: 'Invalid request' };
}
const contact = await db.getContact(id);
if (contact === undefined) {
return { success: false, message: 'Not found' };
}
return { success: true, data: contact };
},
{
detail: {
summary: 'Get contact by ID',
description: 'Get contact from the database by ID',
parameters: [
{
name: 'id',
in: 'path',
description: 'Contact ID',
required: true,
schema: {
type: 'number'
}
}
],
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean'
},
data: {
type: 'object',
properties: {
id: {
type: 'number'
},
name: {
type: 'string'
},
email: {
type: 'string'
}
},
example: {
id: 1,
name: 'Wahyu',
email: 'wahyu@example.com'
},
required: ['id', 'name', 'email']
}
},
required: ['success', 'data']
}
}
}
},
404: {
description: 'Not Found',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: false
},
message: {
type: 'string',
example: 'Contact not found'
}
},
required: ['success', 'message']
}
}
}
}
}
}
}
)
...
Tambahkan endpoint untuk mengupdate kontak berdasarkan ID pada contactApi
.
...
.put(
"/contacts/:id",
async ({ db, params, body }: { db: ContactDB, params: { id: string }, body: Contact }) => {
const id = parseInt(params.id);
if (id === undefined) {
return { success: false, message: 'Invalid request' };
}
const contact = await db.updateContact(id, body);
if (contact === undefined) {
return { success: false, message: 'Not found' };
}
return { success: true, message: `Contact ${id} updated` };
},
{
detail: {
summary: 'Update contact',
description: 'Update contact in the database',
parameters: [
{
name: 'id',
in: 'path',
description: 'Contact ID',
required: true,
schema: {
type: 'number'
}
}
],
requestBody: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
name: { type: 'string' },
email: { type: 'string' }
},
example: {
name: 'Wahyu Ivan',
email: 'wahyu@example.com'
},
required: ['name', 'email']
}
}
}
},
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: true
},
message: {
type: 'string',
example: 'Contact 1 updated'
}
},
required: ['success', 'message']
}
}
}
},
400: {
description: 'Bad Request',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: false
},
message: {
type: 'string',
example: 'Invalid request'
}
},
required: ['success', 'message']
}
}
}
},
404: {
description: 'Not Found',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: false
},
message: {
type: 'string',
example: 'Contact not found'
}
},
required: ['success', 'message']
}
}
}
}
}
}
}
)
Tambahkan endpoint untuk menghapus kontak berdasarkan ID pada contactApi
.
...
.delete(
"/contacts/:id",
async ({ db, params }: { db: ContactDB, params: { id: string } }) => {
const id = parseInt(params.id);
if (id === undefined) {
return { success: false, message: 'Invalid request' };
}
const contact = await db.removeContact(id);
if (contact === undefined) {
return { success: false, message: 'Not found' };
}
return { success: true, message: `Contact ${id} removed` };
},
{
detail: {
summary: 'Remove contact',
description: 'Remove contact from the database',
parameters: [
{
name: 'id',
in: 'path',
description: 'Contact ID',
required: true,
schema: {
type: 'number'
}
}
],
responses: {
200: {
description: 'Success',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: true
},
message: {
type: 'string',
example: 'Contact 1 removed'
}
},
required: ['success', 'message']
}
}
}
},
404: {
description: 'Not Found',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
success: {
type: 'boolean',
example: false
},
message: {
type: 'string',
example: 'Contact not found'
}
},
required: ['success', 'message']
}
}
}
}
}
}
}
);
Buat instance Elysia baru dan tambahkan plugin contactApi
, Swagger dan property ContactDB
pada file index.ts
. Swagger disini adalah sebuah open-source project yang memungkinkan kita untuk membuat dokumentasi API dengan mudah. Setalah itu, set server agar berjalan pada port 3000
.
...
import { swagger } from '@elysiajs/swagger'
...
new Elysia()
.use(swagger({
documentation: {
info: {
title: 'Contact API',
version: '1.0.0',
description: 'Contact API project. Developed using Elysia framework, bun, and TypeScript.'
}
}
}))
.use(contactApi)
.decorate('db', new ContactDB())
.listen(3000);
Untuk menjalankan server, gunakan perintah berikut di terminal:
bun dev
Server akan berjalan di http://localhost:3000
dan kalian sudah bisa mengakses API yang telah dibuat. Untuk melihat dokumentasi API dengan Swagger, akses endpoint /swagger
.
Untuk melihat project dan source code secara penuh: Link Github Proyek
Elysia menawarkan solusi modern untuk pengembangan backend web dengan memanfaatkan kekuatan dan kecepatan Bun sebagai fondasinya. Dengan kemudahan integrasi dan dukungan penuh untuk Typescript, Elysia memberikan pengalaman development yang cepat dan efisien. Semoga artikel ini membantu kalian dalam memulai dan mengembangkan API menggunakan Elysia dan Bun. Selamat mencoba!
Halo, saya Wahyu. Saat ini saya bekerja sebagai Software Engineer di Taksu Tech. Semoga artikel yang saya tulis bermanfaat untuk temen-temen.