Memahami plugin system di ElysiaJS: membuat plugin custom dengan derive dan resolve, lifecycle hooks, serta menggunakan plugin ekosistem seperti CORS, JWT, Swagger, dan Bearer untuk modularisasi codebase.

Setelah di episode 6 kita menguasai schema validation, pada episode ini kita akan memahami plugin system — fitur yang membuat ElysiaJS sangat modular dan scalable. Di ElysiaJS, semua fitur tambahan diimplementasikan sebagai plugin, termasuk middleware, CORS, JWT, dan bahkan serializer.
Plugin adalah fungsi yang menerima instance app dan menambahkan route atau middleware kepadanya. Pendekatan ini memungkinkan modularisasi codebase tanpa dependencies silang:
import { Elysia } from 'elysia'
const healthPlugin = (app: Elysia) =>
app.get('/health', () => ({ status: 'ok' }))
const app = new Elysia()
.use(healthPlugin)
.listen(3000)Plugin bisa menambahkan route ke aplikasi:
import { Elysia, t } from 'elysia'
const userPlugin = (app: Elysia) =>
app
.get('/users', () => [{ id: 1, name: 'John' }])
.post('/users', ({ body }) => ({ id: 2, ...body }), {
body: t.Object({
name: t.String(),
email: t.String(),
})
})
const app = new Elysia()
.use(userPlugin)
.listen(3000)derive() menambahkan data ke context tanpa mengubah response — sangat berguna untuk autentikasi:
import { Elysia } from 'elysia'
const authPlugin = (app: Elysia) =>
app.derive(async ({ cookie }) => {
const token = cookie.auth.value
const user = token ? await verifyToken(token) : null
return { user }
})
const app = new Elysia()
.use(authPlugin)
.get('/profile', ({ user }) => {
if (!user) return { error: 'Unauthorized' }
return { name: user.name }
})
.listen(3000)derive() menghasilkan data baru yang ditambahkan ke context — di sini user tersedia di semua route handler.
resolve() mirip dengan derive(), tetapi bisa menjalankan validasi atau transformasi asynchronous:
const validatedPlugin = (app: Elysia) =>
app.resolve(async ({ body }) => {
if (body?.email) {
const exists = await checkEmailExists(body.email)
if (exists) throw new Error('Email already exists')
}
return {}
})ElysiaJS memiliki lifecycle hooks untuk plugin:
derive(): Menambahkan data ke context, berjalan setiap request.resolve(): Validasi atau transformasi async sebelum handler.onBeforeHandle(): Middleware sebelum handler utama.onAfterHandle(): Transformasi response setelah handler.onError(): Error handler untuk menangkap error.const loggingPlugin = (app: Elysia) =>
app
.onBeforeHandle(({ request }) => {
console.log(`[${request.method}] ${request.url}`)
})
.onAfterHandle(({ response }) => {
console.log('Response sent')
})
.onError(({ code, error }) => {
console.error(`Error: ${code}`, error)
})ElysiaJS memiliki ekosistem plugin yang luas untuk kebutuhan umum:
import { Elysia } from 'elysia'
import cors from '@elysiajs/cors'
import jwt from '@elysiajs/jwt'
import bearer from '@elysiajs/bearer'
import swagger from '@elysiajs/swagger'
const app = new Elysia()
.use(cors())
.use(jwt({ name: 'jwt', secret: process.env.JWT_SECRET }))
.use(bearer())
.use(swagger())
.listen(3000)Setiap plugin menambahkan fitur spesifik: CORS menghandle Cross-Origin Resource Sharing, JWT menyediakan autentikasi token, Bearer mengekstrak Bearer token, dan Swagger menghasilkan OpenAPI documentation.
Tip
Urutan pemasangan plugin penting. Plugin yang dipasang lebih awal berjalan lebih dulu. Untuk autentikasi, pastikan JWT dan Bearer dipasang sebelum route yang membutuhkan autentikasi.
Pada episode 7 ini, kalian telah memahami plugin system di ElysiaJS — dari membuat plugin custom dengan derive dan resolve hingga menggunakan plugin ekosistem.
Inti yang harus dibawa pulang:
app dan menambahkan route/middleware.derive() menambahkan data ke context, resolve() untuk validasi async.onBeforeHandle, onAfterHandle, onError.Di episode 8 selanjutnya kita akan memahami database integration dengan Drizzle ORM — setup Drizzle di proyek ElysiaJS, definisi schema, query builder, dan integrasi dengan plugin system. Sampai jumpa di episode 8!