A lightweight, type-safe router for Bun with middleware support and context utilities.
bun add bun-easy-router
import { Router, Logger, Cors, BearerAuth } from 'bun-easy-router'
Bun.serve({
port: 3001,
fetch: async (request: Request) => {
const router = Router(request)
// Add middleware
router.use(Logger())
router.use(Cors())
router.use(BearerAuth())
// Define routes with context
router.get('/', (c) => {
return c.json({ message: 'Hello, world!' })
})
router.get('/users/:id', (c) => {
const userId = c.params.id
return c.json({ userId })
})
return router.run()
},
})
- 🚀 Fast and lightweight
- 💪 Full TypeScript support
- 🎯 Type-safe route parameters
- 🔌 Middleware support
- 📝 Built-in logging
- 🔒 CORS and Authentication
- ⚡ Async/await support
- 🎉 Context utilities
- 📦 File handling
The router provides a rich context object with helpful utilities:
// JSON responses
router.get('/api/data', (c) => {
return c.json({ data: 'value' })
})
// Pretty JSON for debugging
router.get('/api/debug', (c) => {
return c.pretty({
nested: { data: [1, 2, 3] },
})
})
// Error responses
router.get('/api/error', (c) => {
return c.error('Not found', 404)
})
// Success responses
router.post('/api/users', (c) => {
return c.success('User created', 201)
})
// HTML responses
router.get('/page', async (c) => {
const html = await c.readHtml('./templates/page.html')
return c.html(html)
})
// File downloads
router.get('/download/:file', (c) => {
return c.sendFile(`./files/${c.params.file}`)
})
// Redirects
router.get('/old-path', (c) => {
return c.redirect('/new-path')
})
// Query parameters
router.get('/search', (c) => {
const query = c.query.get('q')
return c.json({ query })
})
The router supports type-safe route parameters with context:
// Parameters are automatically typed
router.get('/users/:id', (c) => {
// c.params.id is typed as string
return c.json({ userId: c.params.id })
})
// Multiple parameters
router.get('/users/:userId/posts/:postId', (c) => {
// Both c.params.userId and c.params.postId are typed
const { userId, postId } = c.params
return c.json({ userId, postId })
})
Supported HTTP methods with context:
router.get('/users', (c) =>
c.json({
/* ... */
})
)
router.post('/users', (c) =>
c.json({
/* ... */
})
)
router.put('/users/:id', (c) =>
c.json({
/* ... */
})
)
router.delete('/users/:id', (c) =>
c.json({
/* ... */
})
)
// Basic usage - serves files from ./public directory
router.use(Static())
// Advanced configuration
router.use(Static({
// Serve files from this directory
dir: "assets",
// Serve under this URL prefix
prefix: "/public",
// Custom index file
index: "main.html",
// Enable directory listing
listing: true,
// SPA mode - serve index.html for missing files
spa: true,
// Custom MIME types
mimeTypes: {
'webp': 'image/webp',
'mp4': 'video/mp4'
}
}))
The router provides full TypeScript support:
// Route parameters are automatically inferred
router.get('/users/:id/posts/:postId', (c) => {
// TypeScript knows about these parameters
const { id, postId } = c.params
return c.json({ id, postId })
})
[Previous middleware documentation remains the same...]
The router includes built-in error handling with context:
router.get('/api/data', async (c) => {
try {
const data = await fetchData()
return c.json(data)
} catch (error) {
return c.error('Internal Server Error', 500)
}
})
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - feel free to use this in your own projects!