Ringkasan Validasi
Referensi: Repositori GitHub Typebox
Deserve memvalidasi input request lewat kontrak Typebox, sebuah library kontrak tanpa dependency yang ikut dalam framework. Sebuah kontrak menjelaskan satu sumber request, middleware validator menjalankannya sebelum handler, dan handler membaca data bertipe yang sudah lolos setiap aturan.
Validasi berdiri di samping middleware lain dan mengawasi request sebelum mencapai rute, tempat yang sama dengan CORS dan Session ikut terpasang.
Tiga Bagian
Validasi terbentuk dari tiga export, masing-masing dengan satu tugas:
Validator.definemembangun kontrak dari sebuah transform dan guard opsional. Lihat Define Schema.Validator.checkmengubah schema menjadi middleware yang memvalidasi sumber request. Lihat Middleware Validator.ctx.get.validated()membaca data tervalidasi di dalam handler. Lihat Membaca Data Tervalidasi.

Schema Memetakan Sumber Ke Kontrak
Sebuah schema adalah object biasa yang memasangkan sumber request dengan kontrak:
import { Validator } from '@neabyte/deserve'
// Satu kontrak per sumber request
const schema = {
body: Validator.define((body: { name: string }) => body)
}Ada empat sumber, dan masing-masing membaca dari bagian yang cocok di Context:
| Sumber | Membaca dari | Bentuk |
|---|---|---|
body | ctx.get.body() | body mentah hasil parse |
cookies | ctx.get.cookie() | Record<string, string> |
headers | ctx.get.header() | Record<string, string> |
query | ctx.get.query() | Record<string, string> |
Param rute bukan sumber validasi karena ia diresolusi setelah middleware berjalan. Validasi di dalam handler dengan panggilan kontrak langsung, dibahas di Membaca Data Tervalidasi.
Alur Request
Sebuah request tervalidasi melewati empat langkah:
- Middleware validator membaca setiap sumber yang disebut di schema
- Middleware menjalankan kontrak yang cocok pada nilai sumber itu
- Kontrak yang lolos menyimpan outputnya di context
- Handler membaca output itu dengan tipe penuh lewat
ctx.get.validated()

import { Router, Validator } from '@neabyte/deserve'
const router = new Router({
routes: { directory: './routes' }
})
const schema = {
body: Validator.define((body: { name: string }) => ({ name: body.name.trim() }))
}
// Validasi body sebelum handler
router.use('/users', Validator.check(schema))
await router.serve(8000)export function POST(ctx: Context): Response {
// Baca data bertipe yang sudah lolos
const { body } = ctx.get.validated<typeof schema>()
return ctx.send.json({ created: body.name })
}Kegagalan Menjadi 422
Kontrak yang menolak inputnya akan melempar, dan framework memetakan lemparan itu ke respons 422 Unprocessable Content. Alasan kegagalan menumpang di error.cause sebagai array string, jadi handler kustom membacanya dan memunculkan persis field mana yang salah. Pembentukan respons error tetap di satu tempat lewat Detail Object, router.catch yang sama yang menangani setiap error lain.
Lemparan dari input client tidak pernah menjadi 500. Aturan pemetaan itu ada di Membaca Data Tervalidasi.
Langkah Berikutnya
- Define Schema - menulis kontrak dengan transform dan guard
- Middleware Validator - mendaftarkan validasi per sumber dan per rute
- Membaca Data Tervalidasi - membaca output bertipe dan memeriksa param di handler
- Pola Lanjutan - memilih schema per method pada satu prefix bersama