🎯 Recommended Samples
Balanced sample collections from various categories for you to explore
Elysia.js Samples
Elysia.js modern TypeScript web framework examples including Hello World, routing, validation, and plugin development
💻 Elysia.js Hello World typescript
🟢 simple
Basic Elysia.js server setup and Hello World application with TypeScript
// Elysia.js Hello World Examples
import { Elysia } from 'elysia'
// 1. Basic Hello World server
const app = new Elysia()
.get('/', () => 'Hello, World!')
.listen(3000)
console.log(`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`)
// 2. Hello World with different routes
const app = new Elysia()
.get('/', () => 'Hello, Elysia!')
.get('/hello', () => 'Hello from Elysia.js!')
.get('/hello/:name', ({ params: { name } }) => `Hello, ${name}!`)
.listen(3000)
// 3. JSON response
const app = new Elysia()
.get('/api/hello', () => ({
message: 'Hello, World!',
timestamp: new Date().toISOString(),
version: '1.0.0',
framework: 'Elysia.js'
}))
.listen(3000)
// 4. HTML response
const app = new Elysia()
.get('/html', () => (
<html>
<head>
<title>Hello Elysia</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>This is an HTML response from Elysia.js</p>
</body>
</html>
))
.listen(3000)
// 5. Typed responses
const app = new Elysia()
.get('/typed', () => ({
id: 1,
name: 'Elysia.js',
features: ['TypeScript', 'Performance', 'Simple API'] as const
}))
.listen(3000)
// 6. Async handlers
const app = new Elysia()
.get('/async', async () => {
await new Promise(resolve => setTimeout(resolve, 1000))
return 'Async response from Elysia!'
})
.listen(3000)
// 7. Error handling
const app = new Elysia()
.get('/error', () => {
throw new Error('Something went wrong!')
})
.onError(({ code, error }) => {
if (code === 'NOT_FOUND')
return 'Route not found :('
return new Response(error.toString(), {
status: 500
})
})
.listen(3000)
// 8. Chain configuration
const app = new Elysia()
.state('version', '1.0.0')
.decorate('getDate', () => new Date())
.get('/', ({ getDate, store: { version } }) => ({
date: getDate(),
version
}))
.listen(3000)
💻 Elysia.js Routing and Parameters typescript
🟡 intermediate
Advanced routing examples with path parameters, query strings, and HTTP methods
// Elysia.js Routing Examples
import { Elysia } from 'elysia'
// 1. HTTP Methods
const app = new Elysia()
.get('/users', () => 'Get all users')
.post('/users', () => 'Create a new user')
.put('/users/:id', ({ params: { id } }) => `Update user ${id}`)
.patch('/users/:id', ({ params: { id } }) => `Patch user ${id}`)
.delete('/users/:id', ({ params: { id } }) => `Delete user ${id}`)
.listen(3000)
// 2. Path parameters
interface UserParams {
id: string
}
const app = new Elysia()
.get('/users/:id', ({ params: { id } }: { params: UserParams }) => {
return `User ID: ${id}`
})
.get('/posts/:category/:slug', ({ params }) => {
return `Category: ${params.category}, Slug: ${params.slug}`
})
.listen(3000)
// 3. Query parameters
const app = new Elysia()
.get('/search', ({ query }) => {
const { q, limit = '10', page = '1' } = query
return {
query: q || 'No query provided',
limit: parseInt(limit),
page: parseInt(page),
results: [`Result for "${q}"`]
}
})
.listen(3000)
// 4. Headers
const app = new Elysia()
.get('/info', ({ headers }) => {
return {
userAgent: headers['user-agent'],
accept: headers.accept,
host: headers.host
}
})
.listen(3000)
// 5. Request body
interface CreateUserBody {
name: string
email: string
age?: number
}
const app = new Elysia()
.post('/users', ({ body }: { body: CreateUserBody }) => {
return {
message: `User ${body.name} created successfully!`,
user: {
id: Math.random(),
name: body.name,
email: body.email,
age: body.age || 0
}
}
})
.listen(3000)
// 6. Route groups
const app = new Elysia()
.group('/api/v1', (app) => app
.get('/users', () => ['user1', 'user2'])
.post('/users', () => 'User created')
.get('/posts', () => ['post1', 'post2'])
)
.group('/api/v2', (app) => app
.get('/users', () => ['user1', 'user2', 'user3'])
.get('/posts', () => ['post1', 'post2', 'post3'])
)
.listen(3000)
// 7. Wildcard routes
const app = new Elysia()
.get('/static/*', ({ params }) => {
return `Serving file: ${params['*']}`
})
.all('/fallback/*', () => {
return 'This is a catch-all route'
})
.listen(3000)
// 8. Route guards
const app = new Elysia()
.guard({
beforeHandle({ set, headers }) {
const auth = headers.authorization
if (!auth?.startsWith('Bearer ')) {
set.status = 401
return 'Unauthorized'
}
}
}, (app) => app
.get('/protected', () => 'Protected data')
.post('/protected', () => 'Protected action')
)
.get('/public', () => 'Public data')
.listen(3000)
// 9. Custom responses
const app = new Elysia()
.get('/custom-status', ({ set }) => {
set.status = 418
return "I'm a teapot"
})
.get('/redirect', ({ set }) => {
set.headers['Location'] = '/'
set.status = 302
return
})
.listen(3000)
// 10. Route patterns
const app = new Elysia()
.match('GET|POST', '/users', ({ request }) => {
return `${request.method} /users`
})
.match(['PUT', 'PATCH'], '/users/:id', ({ request, params }) => {
return `${request.method} /users/${params.id}`
})
.listen(3000)
💻 Elysia.js Data Validation typescript
🟡 intermediate
TypeScript-first validation using built-in schema validation
// Elysia.js Validation Examples
import { Elysia, t } from 'elysia'
// 1. Basic body validation
const app = new Elysia()
.post('/users', ({ body }) => {
return `User ${body.name} (${body.email}) created!`
}, {
body: t.Object({
name: t.String(),
email: t.String({ format: 'email' }),
age: t.Number({ minimum: 18 })
})
})
.listen(3000)
// 2. Query parameter validation
const app = new Elysia()
.get('/search', ({ query }) => {
return `Searching for "${query.q}" with limit ${query.limit}`
}, {
query: t.Object({
q: t.String({ minLength: 1 }),
limit: t.Optional(t.Number({ minimum: 1, maximum: 100 })),
category: t.Optional(t.Enum(['tech', 'news', 'sports'] as const))
})
})
.listen(3000)
// 3. Path parameter validation
const app = new Elysia()
.get('/users/:id', ({ params: { id } }) => {
return `User ID: ${id}`
}, {
params: t.Object({
id: t.Numeric()
})
})
.listen(3000)
// 4. Header validation
const app = new Elysia()
.post('/data', ({ headers }) => {
return 'Data received'
}, {
headers: t.Object({
'content-type': t.Literal('application/json'),
'x-api-key': t.String({ minLength: 10 })
})
})
.listen(3000)
// 5. Response validation
const app = new Elysia()
.get('/user/:id', ({ params: { id } }) => {
return {
id: parseInt(id),
name: `User ${id}`,
email: `user${id}@example.com`,
createdAt: new Date()
}
}, {
params: t.Object({
id: t.Numeric()
}),
response: {
200: t.Object({
id: t.Number(),
name: t.String(),
email: t.String({ format: 'email' }),
createdAt: t.Date()
}),
404: t.Object({
error: t.String()
})
}
})
.listen(3000)
// 6. Custom validation with transform
const app = new Elysia()
.post('/register', ({ body }) => {
return body
}, {
body: t.Object({
username: t.String({
minLength: 3,
maxLength: 20,
pattern: '^[a-zA-Z0-9_]+$'
}),
email: t.String({ format: 'email' }),
password: t.String({ minLength: 8 }),
confirmPassword: t.String()
}),
transform({ body }) {
body.username = body.username.toLowerCase()
}
})
.listen(3000)
// 7. Array validation
const app = new Elysia()
.post('/batch', ({ body }) => {
return `Processed ${body.items.length} items`
}, {
body: t.Object({
items: t.Array(t.Object({
id: t.Number(),
name: t.String(),
price: t.Number({ minimum: 0 })
})),
metadata: t.Optional(t.Object({
total: t.Number(),
currency: t.String({ default: 'USD' })
}))
})
})
.listen(3000)
// 8. Nested object validation
const app = new Elysia()
.post('/order', ({ body }) => {
return 'Order created'
}, {
body: t.Object({
customer: t.Object({
name: t.String(),
address: t.Object({
street: t.String(),
city: t.String(),
zipCode: t.String(),
country: t.String()
})
}),
items: t.Array(t.Object({
productId: t.Number(),
quantity: t.Number({ minimum: 1 }),
price: t.Number()
})),
shipping: t.Optional(t.Union([
t.Literal('standard'),
t.Literal('express'),
t.Literal('overnight')
]))
})
})
.listen(3000)
// 9. File upload validation
const app = new Elysia()
.post('/upload', ({ body: { file } }) => {
return `Uploaded file: ${file.name} (${file.size} bytes)`
}, {
body: t.Object({
file: t.File({
type: ['image/jpeg', 'image/png', 'image/gif'],
maxSize: '5m'
}),
description: t.Optional(t.String({ maxLength: 500 }))
})
})
.listen(3000)
// 10. Custom error messages
const app = new Elysia()
.onError(({ code, error }) => {
if (code === 'VALIDATION') {
return {
success: false,
errors: error.all.map(({ path, message }) => ({
field: path.join('.'),
message
}))
}
}
})
.post('/custom-validation', ({ body }) => {
return 'Success'
}, {
body: t.Object({
username: t.String({
error: 'Username must be a string'
}),
email: t.String({
format: 'email',
error: 'Invalid email format'
})
})
})
.listen(3000)
💻 Elysia.js Middleware and Hooks typescript
🟡 intermediate
Lifecycle hooks, middleware, and advanced request handling
// Elysia.js Middleware and Hooks Examples
import { Elysia } from 'elysia'
// 1. Before handle hook
const app = new Elysia()
.onBeforeHandle({ as: 'global' }, ({ set, headers }) => {
// Add CORS headers
set.headers['Access-Control-Allow-Origin'] = '*'
set.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE'
set.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
})
.get('/data', () => 'CORS enabled data')
.listen(3000)
// 2. After handle hook
const app = new Elysia()
.onAfterHandle({ as: 'global' }, ({ response }) => {
// Wrap all responses
return {
success: true,
timestamp: new Date().toISOString(),
data: response
}
})
.get('/users', () => ['Alice', 'Bob', 'Charlie'])
.listen(3000)
// 3. Transform hook
const app = new Elysia()
.onTransform({ as: 'global' }, ({ request }) => {
console.log(`${request.method} ${request.url}`)
})
.get('/track', () => 'Tracked request')
.listen(3000)
// 4. Logger middleware
const logger = new Elysia({ name: 'logger' })
.onBeforeHandle(({ request, set }) => {
console.log(`[${new Date().toISOString()}] ${request.method} ${request.url}`)
})
.onAfterHandle(({ response }) => {
console.log(`Response: ${JSON.stringify(response)}`)
})
const app = new Elysia()
.use(logger)
.get('/logged', () => 'This request is logged')
.listen(3000)
// 5. Authentication middleware
const auth = new Elysia({ name: 'auth' })
.derive({ as: 'global' }, ({ headers }) => {
const authHeader = headers.authorization
if (!authHeader?.startsWith('Bearer ')) {
throw new Error('Unauthorized')
}
const token = authHeader.slice(7)
// Simplified token validation
const user = { id: 1, name: 'John Doe' }
return { user }
})
const app = new Elysia()
.use(auth)
.get('/profile', ({ user }) => `Hello, ${user.name}!`)
.listen(3000)
// 6. Rate limiting middleware
const rateLimiter = new Map<string, { count: number; resetTime: number }>()
const rateLimit = new Elysia({ name: 'rate-limit' })
.onBeforeHandle(({ set, headers }) => {
const ip = headers['x-forwarded-for'] || 'unknown'
const now = Date.now()
const windowMs = 60 * 1000 // 1 minute
const maxRequests = 10
const record = rateLimiter.get(ip)
if (!record || now > record.resetTime) {
rateLimiter.set(ip, { count: 1, resetTime: now + windowMs })
return
}
if (record.count >= maxRequests) {
set.status = 429
return 'Too many requests'
}
record.count++
})
const app = new Elysia()
.use(rateLimit)
.get('/limited', () => 'Rate limited endpoint')
.listen(3000)
// 7. Error handling
const app = new Elysia()
.onError(({ code, error, set }) => {
switch (code) {
case 'NOT_FOUND':
set.status = 404
return { error: 'Route not found' }
case 'VALIDATION':
set.status = 400
return {
error: 'Validation failed',
details: error.all
}
case 'INTERNAL_SERVER_ERROR':
set.status = 500
return { error: 'Internal server error' }
default:
set.status = 500
return { error: 'Unknown error' }
}
})
.get('/error', () => {
throw new Error('Test error')
})
.listen(3000)
// 8. Request context extension
const app = new Elysia()
.state('version', '1.0.0')
.decorate('getDb', () => {
// Mock database connection
return {
query: (sql: string) => `Executing: ${sql}`,
close: () => console.log('DB connection closed')
}
})
.derive({ as: 'global' }, ({ store }) => {
return {
appInfo: {
version: store.version,
uptime: process.uptime()
}
}
})
.get('/context', ({ getDb, appInfo }) => {
return {
db: getDb().query('SELECT * FROM users'),
appInfo
}
})
.listen(3000)
// 9. Plugin system
const loggingPlugin = new Elysia({ name: 'logging' })
.onBeforeHandle(({ request }) => {
console.log(`📝 ${request.method} ${request.url}`)
})
.onAfterHandle(() => {
console.log('✅ Request completed')
})
.onError(({ error }) => {
console.log(`❌ Error: ${error.message}`)
})
const timingPlugin = new Elysia({ name: 'timing' })
.onBeforeHandle(() => ({ startTime: Date.now() }))
.onAfterHandle({ beforeHandle: ({ startTime }) => ({ startTime }) }, ({ startTime }) => {
const duration = Date.now() - startTime
console.log(`⏱️ Request took ${duration}ms`)
})
const app = new Elysia()
.use(loggingPlugin)
.use(timingPlugin)
.get('/plugged', () => 'This request uses multiple plugins')
.listen(3000)
// 10. Route-specific hooks
const app = new Elysia()
.get('/specific',
() => 'Route with specific hooks',
{
beforeHandle({ set }) {
set.headers['X-Custom'] = 'value'
},
afterHandle({ response }) {
return `Processed: ${response}`
}
}
)
.listen(3000)
// 11. Lifecycle order demonstration
const app = new Elysia()
.onRequest(() => console.log('1. onRequest'))
.onBeforeHandle(() => console.log('2. onBeforeHandle'))
.onAfterHandle(() => console.log('3. onAfterHandle'))
.onResponse(() => console.log('4. onResponse'))
.get('/lifecycle', () => {
console.log('-> Handler executing')
return 'Lifecycle demo'
})
.listen(3000)
💻 Elysia.js WebSocket Support typescript
🟡 intermediate
Real-time WebSocket communication and chat examples
// Elysia.js WebSocket Examples
import { Elysia } from 'elysia'
import { websocket } from '@elysiajs/websocket'
// 1. Basic WebSocket server
const app = new Elysia()
.use(websocket())
.ws('/ws', {
message(ws, message) {
ws.send(`Echo: ${message}`)
},
open(ws) {
console.log('WebSocket connection opened')
ws.send('Welcome to the WebSocket server!')
},
close(ws) {
console.log('WebSocket connection closed')
}
})
.listen(3000)
// 2. Chat server
interface ChatMessage {
type: 'message' | 'join' | 'leave'
user: string
content: string
timestamp: string
}
const clients = new Map<string, any>()
const app = new Elysia()
.use(websocket())
.ws('/chat', {
message(ws, message: ChatMessage) {
const chatMessage: ChatMessage = {
type: 'message',
user: message.user,
content: message.content,
timestamp: new Date().toISOString()
}
// Broadcast to all connected clients
app.server?.publish('chat', JSON.stringify(chatMessage))
},
open(ws) {
const userId = `user_${Math.random().toString(36).substr(2, 9)}`
ws.data.id = userId
clients.set(userId, ws)
const joinMessage: ChatMessage = {
type: 'join',
user: 'System',
content: `User ${userId} joined the chat`,
timestamp: new Date().toISOString()
}
app.server?.publish('chat', JSON.stringify(joinMessage))
},
close(ws) {
const userId = ws.data.id
clients.delete(userId)
const leaveMessage: ChatMessage = {
type: 'leave',
user: 'System',
content: `User ${userId} left the chat`,
timestamp: new Date().toISOString()
}
app.server?.publish('chat', JSON.stringify(leaveMessage))
}
})
.listen(3000)
// 3. Real-time notifications
const app = new Elysia()
.use(websocket())
.ws('/notifications', {
open(ws) {
console.log('Notification client connected')
// Send periodic notifications
const interval = setInterval(() => {
const notification = {
type: 'notification',
title: 'System Update',
message: `System time: ${new Date().toLocaleTimeString()}`,
timestamp: new Date().toISOString()
}
ws.send(JSON.stringify(notification))
}, 5000)
ws.data.interval = interval
},
close(ws) {
if (ws.data.interval) {
clearInterval(ws.data.interval)
}
}
})
.listen(3000)
// 4. Multi-room chat
interface Room {
id: string
name: string
clients: Map<string, any>
}
const rooms = new Map<string, Room>()
const app = new Elysia()
.use(websocket())
.ws('/room/:roomId', {
params: {
roomId: t.String()
},
message(ws, message) {
const { roomId } = ws.data.params
const room = rooms.get(roomId)
if (!room) return
const chatMessage = {
type: 'message',
user: ws.data.user,
content: message.content,
timestamp: new Date().toISOString()
}
// Send to all clients in the room
room.clients.forEach((client) => {
client.send(JSON.stringify(chatMessage))
})
},
open(ws) {
const { roomId } = ws.data.params
const userId = `user_${Math.random().toString(36).substr(2, 9)}`
ws.data.user = userId
ws.data.roomId = roomId
// Get or create room
let room = rooms.get(roomId)
if (!room) {
room = {
id: roomId,
name: `Room ${roomId}`,
clients: new Map()
}
rooms.set(roomId, room)
}
// Add client to room
room.clients.set(userId, ws)
const joinMessage = {
type: 'join',
user: 'System',
content: `${userId} joined the room`,
timestamp: new Date().toISOString()
}
room.clients.forEach((client) => {
client.send(JSON.stringify(joinMessage))
})
},
close(ws) {
const { roomId, user } = ws.data
const room = rooms.get(roomId)
if (room) {
room.clients.delete(user)
const leaveMessage = {
type: 'leave',
user: 'System',
content: `${user} left the room`,
timestamp: new Date().toISOString()
}
room.clients.forEach((client) => {
client.send(JSON.stringify(leaveMessage))
})
// Clean up empty rooms
if (room.clients.size === 0) {
rooms.delete(roomId)
}
}
}
})
.listen(3000)
// 5. WebSocket with HTTP API
interface Todo {
id: number
text: string
completed: boolean
createdAt: string
}
const todos: Todo[] = [
{ id: 1, text: 'Learn Elysia.js', completed: true, createdAt: new Date().toISOString() },
{ id: 2, text: 'Build WebSocket app', completed: false, createdAt: new Date().toISOString() }
]
const app = new Elysia()
.use(websocket())
.ws('/todos', {
open(ws) {
// Send initial todos
ws.send(JSON.stringify({
type: 'todos',
data: todos
}))
}
})
.get('/api/todos', () => todos)
.post('/api/todos', ({ body }) => {
const newTodo: Todo = {
id: Date.now(),
text: body.text,
completed: false,
createdAt: new Date().toISOString()
}
todos.push(newTodo)
// Broadcast to all WebSocket clients
app.server?.publish('todos', JSON.stringify({
type: 'todo-added',
data: newTodo
}))
return newTodo
})
.put('/api/todos/:id', ({ params, body }) => {
const todo = todos.find(t => t.id === parseInt(params.id))
if (!todo) return null
Object.assign(todo, body)
// Broadcast update
app.server?.publish('todos', JSON.stringify({
type: 'todo-updated',
data: todo
}))
return todo
})
.delete('/api/todos/:id', ({ params }) => {
const index = todos.findIndex(t => t.id === parseInt(params.id))
if (index === -1) return null
const deletedTodo = todos.splice(index, 1)[0]
// Broadcast deletion
app.server?.publish('todos', JSON.stringify({
type: 'todo-deleted',
data: { id: deletedTodo.id }
}))
return deletedTodo
})
.listen(3000)
// 6. WebSocket authentication
const app = new Elysia()
.use(websocket())
.ws('/auth', {
beforeHandle({ headers, set }) {
const token = headers.authorization?.replace('Bearer ', '')
// Simple token validation
if (!token || token !== 'valid-token') {
set.headers['sec-websocket-protocol'] = 'close'
return 'Unauthorized'
}
},
message(ws, message) {
ws.send(`Authenticated message: ${message}`)
},
open(ws) {
ws.send('WebSocket connection authenticated')
}
})
.listen(3000)
// 7. WebSocket with binary data
const app = new Elysia()
.use(websocket())
.ws('/binary', {
message(ws, message) {
if (message instanceof ArrayBuffer) {
// Echo binary data
ws.send(message)
} else {
ws.send(`Received text: ${message}`)
}
},
open(ws) {
ws.send('Binary WebSocket server ready')
}
})
.listen(3000)
💻 Elysia.js Authentication typescript
🟡 intermediate
JWT authentication, OAuth, and authorization patterns
// Elysia.js Authentication Examples
import { Elysia, t } from 'elysia'
import { jwt } from '@elysiajs/jwt'
// 1. JWT Authentication
const app = new Elysia()
.use(
jwt({
name: 'jwt',
secret: process.env.JWT_SECRET || 'your-secret-key-here'
})
)
.post('/login', async ({ body, jwt }) => {
// Validate user credentials (in real app, check database)
const { username, password } = body
// Mock user validation
if (username === 'admin' && password === 'password123') {
const payload = {
sub: '1234567890',
name: 'John Doe',
email: '[email protected]',
role: 'admin',
iat: Math.floor(Date.now() / 1000)
}
const token = await jwt.sign(payload)
return {
success: true,
token,
user: {
id: payload.sub,
name: payload.name,
email: payload.email,
role: payload.role
}
}
}
return {
success: false,
message: 'Invalid credentials'
}
}, {
body: t.Object({
username: t.String(),
password: t.String({ minLength: 6 })
})
})
.get('/protected', async ({ jwt, headers }) => {
const auth = headers.authorization
if (!auth?.startsWith('Bearer ')) {
return { error: 'No token provided' }
}
const token = auth.slice(7)
const payload = await jwt.verify(token)
if (!payload) {
return { error: 'Invalid token' }
}
return {
message: 'Access granted',
user: payload
}
})
.listen(3000)
// 2. Middleware-based Authentication
const authMiddleware = new Elysia({ name: 'auth' })
.use(
jwt({
name: 'jwt',
secret: 'middleware-secret'
})
)
.derive({ as: 'global' }, async ({ jwt, headers }) => {
const auth = headers.authorization
const token = auth?.replace('Bearer ', '')
let user = null
if (token) {
user = await jwt.verify(token)
}
return {
user,
isAuthenticated: !!user
}
})
.guard({
beforeHandle({ user, set }) {
if (!user) {
set.status = 401
return { error: 'Unauthorized' }
}
}
}, (app) => app
.get('/api/users', () => ['Alice', 'Bob', 'Charlie'])
.post('/api/users', () => 'User created')
.put('/api/users/:id', () => 'User updated')
)
.get('/public', () => 'Public endpoint')
const mainApp = new Elysia()
.use(authMiddleware)
.listen(3000)
// 3. Role-based Authorization
interface User {
id: string
name: string
email: string
role: 'admin' | 'user' | 'moderator'
permissions: string[]
}
const rbacPlugin = new Elysia({ name: 'rbac' })
.use(
jwt({
name: 'jwt',
secret: 'rbac-secret'
})
)
.derive({ as: 'global' }, async ({ jwt, headers }) => {
const token = headers.authorization?.replace('Bearer ', '')
if (!token) {
return {
user: null as User | null,
hasRole: (role: string) => false,
hasPermission: (permission: string) => false
}
}
const payload = await jwt.verify(token) as any
const user: User = payload?.user || null
const hasRole = (role: string): boolean => {
return user?.role === role
}
const hasPermission = (permission: string): boolean => {
return user?.permissions?.includes(permission) || false
}
return { user, hasRole, hasPermission }
})
.guard({
beforeHandle({ user, set }) {
if (!user) {
set.status = 401
return { error: 'Unauthorized' }
}
}
}, (app) => app
.guard({
beforeHandle({ hasRole, set }) {
if (!hasRole('admin')) {
set.status = 403
return { error: 'Admin access required' }
}
}
}, (app) => app
.delete('/admin/users/:id', () => 'User deleted')
.get('/admin/stats', () => 'Admin statistics')
)
.guard({
beforeHandle({ hasPermission, set }) {
if (!hasPermission('read:posts')) {
set.status = 403
return { error: 'Read permission required' }
}
}
}, (app) => app
.get('/posts', () => 'List of posts')
)
.post('/posts', () => 'Post created') // No specific permission required
)
const app = new Elysia()
.use(rbacPlugin)
.listen(3000)
// 4. OAuth Integration (GitHub example)
const app = new Elysia()
.state('oauth', {
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
redirectUri: 'http://localhost:3000/auth/github/callback'
})
.get('/auth/github', ({ store: { oauth } }) => {
const authUrl = `https://github.com/login/oauth/authorize?` +
`client_id=${oauth.clientId}&` +
`redirect_uri=${encodeURIComponent(oauth.redirectUri)}&` +
`scope=user:email`
return { authUrl }
})
.get('/auth/github/callback', async ({ query, store: { oauth }, jwt }) => {
const { code } = query
if (!code) {
return { error: 'Authorization code not provided' }
}
// Exchange code for access token
const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
client_id: oauth.clientId,
client_secret: oauth.clientSecret,
code
})
}).then(res => res.json())
if (tokenResponse.error) {
return { error: tokenResponse.error_description }
}
// Get user information
const userResponse = await fetch('https://api.github.com/user', {
headers: {
'Authorization': `token ${tokenResponse.access_token}`
}
}).then(res => res.json())
// Create JWT token
const payload = {
sub: userResponse.id,
name: userResponse.name,
email: userResponse.email,
avatar: userResponse.avatar_url,
provider: 'github'
}
const token = await jwt.sign(payload)
return {
token,
user: payload
}
})
.listen(3000)
// 5. API Key Authentication
const apiKeys = new Set(['key1', 'key2', 'key3'])
const apiKeyAuth = new Elysia({ name: 'api-key' })
.onBeforeHandle({ as: 'global' }, ({ headers, set }) => {
const apiKey = headers['x-api-key']
if (!apiKey || !apiKeys.has(apiKey)) {
set.status = 401
return { error: 'Invalid API key' }
}
// You could also load rate limits based on the API key
set.headers['X-API-Key-Valid'] = 'true'
})
const app = new Elysia()
.use(apiKeyAuth)
.get('/api/data', () => ({ data: 'Protected by API key' }))
.post('/api/process', () => ({ result: 'Processing complete' }))
.listen(3000)
// 6. Session-based Authentication
const sessions = new Map<string, any>()
const sessionAuth = new Elysia({ name: 'session' })
.derive({ as: 'global' }, ({ headers, cookie }) => {
const sessionId = cookie?.sessionId || headers['x-session-id']
const session = sessionId ? sessions.get(sessionId) : null
const createSession = (userData: any): string => {
const newSessionId = `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
sessions.set(newSessionId, {
user: userData,
createdAt: new Date(),
lastAccessed: new Date()
})
return newSessionId
}
const destroySession = (sessionId: string): void => {
sessions.delete(sessionId)
}
return { session, createSession, destroySession }
})
.guard({
beforeHandle({ session, set }) {
if (!session) {
set.status = 401
return { error: 'No valid session' }
}
}
}, (app) => app
.get('/dashboard', ({ session }) => ({
user: session.user,
message: 'Welcome to your dashboard'
}))
.post('/logout', ({ headers, cookie, destroySession }) => {
const sessionId = cookie?.sessionId || headers['x-session-id']
if (sessionId) {
destroySession(sessionId)
}
return { message: 'Logged out successfully' }
})
)
.post('/login', ({ body, createSession, cookie }) => {
// Validate credentials
if (body.username === 'user' && body.password === 'pass') {
const sessionId = createSession({
id: 1,
name: 'John Doe',
username: body.username
})
// Set session cookie
cookie.sessionId.value = sessionId
cookie.sessionId.httpOnly = true
cookie.sessionId.maxAge = 3600
return {
success: true,
sessionId,
user: { id: 1, name: 'John Doe' }
}
}
return { success: false, message: 'Invalid credentials' }
})
const app = new Elysia()
.use(sessionAuth)
.listen(3000)
// 7. Refresh Token Pattern
const refreshTokens = new Map<string, any>()
const app = new Elysia()
.use(
jwt({
name: 'accessJwt',
secret: 'access-secret',
exp: '1h' // Short-lived access token
})
)
.use(
jwt({
name: 'refreshJwt',
secret: 'refresh-secret',
exp: '7d' // Long-lived refresh token
})
)
.post('/auth/login', async ({ body, accessJwt, refreshJwt }) => {
// Validate credentials
if (body.username === 'admin' && body.password === 'password') {
const user = {
id: '1',
name: 'Admin User',
role: 'admin'
}
const accessToken = await accessJwt.sign({ user })
const refreshToken = await refreshJwt.sign({ userId: user.id })
// Store refresh token
refreshTokens.set(refreshToken, {
userId: user.id,
createdAt: new Date()
})
return {
accessToken,
refreshToken,
user
}
}
throw new Error('Invalid credentials')
})
.post('/auth/refresh', async ({ body, accessJwt, refreshJwt }) => {
const { refreshToken } = body
// Validate refresh token
const payload = await refreshJwt.verify(refreshToken)
if (!payload || !refreshTokens.has(refreshToken)) {
throw new Error('Invalid refresh token')
}
// Generate new access token
const user = {
id: payload.userId,
name: 'User ' + payload.userId,
role: 'user'
}
const accessToken = await accessJwt.sign({ user })
return { accessToken }
})
.post('/auth/logout', ({ body }) => {
const { refreshToken } = body
refreshTokens.delete(refreshToken)
return { message: 'Logged out successfully' }
})
.listen(3000)
// 8. Multi-factor Authentication (MFA)
const app = new Elysia()
.state('mfa', {
// In real app, use TOTP library
generateMFACode: (userId: string) => {
return Math.floor(100000 + Math.random() * 900000).toString()
},
verifyMFACode: (userId: string, code: string): boolean => {
// Mock verification
return code === '123456'
}
})
.post('/auth/login-mfa', ({ body, store: { mfa } }) => {
const { username, password } = body
// Step 1: Validate username/password
if (username === 'admin' && password === 'password') {
const mfaCode = mfa.generateMFACode(username)
// In real app, send MFA code via SMS/email
console.log(`MFA Code for ${username}: ${mfaCode}`)
return {
requiresMFA: true,
message: 'MFA code sent to your registered device'
}
}
return { error: 'Invalid credentials' }
})
.post('/auth/verify-mfa', ({ body, store: { mfa }, jwt }) => {
const { username, mfaCode } = body
if (!mfa.verifyMFACode(username, mfaCode)) {
return { error: 'Invalid MFA code' }
}
// Generate final authentication token
return jwt.sign({
sub: username,
mfaVerified: true
})
})
.listen(3000)
💻 Elysia.js GraphQL Integration typescript
🟡 intermediate
GraphQL server implementation with Elysia.js
// Elysia.js GraphQL Examples
import { Elysia } from 'elysia'
import { gql } from '@elysiajs/graphql'
import { graphql } from '@elysiajs/graphql'
// 1. Basic GraphQL Server
const typeDefs = gql`
type Query {
hello: String
user(id: ID!): User
users: [User!]
}
type User {
id: ID!
name: String!
email: String!
createdAt: String!
}
type Mutation {
createUser(name: String!, email: String!): User
updateUser(id: ID!, name: String): User
deleteUser(id: ID!): Boolean
}
`
// Mock data
const users = [
{ id: '1', name: 'John Doe', email: '[email protected]', createdAt: '2024-01-01' },
{ id: '2', name: 'Jane Smith', email: '[email protected]', createdAt: '2024-01-02' }
]
const resolvers = {
Query: {
hello: () => 'Hello, GraphQL with Elysia!',
user: (_: any, { id }: { id: string }) => users.find(u => u.id === id),
users: () => users
},
Mutation: {
createUser: (_: any, { name, email }: { name: string; email: string }) => {
const newUser = {
id: (users.length + 1).toString(),
name,
email,
createdAt: new Date().toISOString()
}
users.push(newUser)
return newUser
},
updateUser: (_: any, { id, name }: { id: string; name?: string }) => {
const user = users.find(u => u.id === id)
if (!user) return null
if (name) user.name = name
return user
},
deleteUser: (_: any, { id }: { id: string }) => {
const index = users.findIndex(u => u.id === id)
if (index === -1) return false
users.splice(index, 1)
return true
}
}
}
const app = new Elysia()
.use(
graphql({
typeDefs,
resolvers
})
)
.listen(3000)
// 2. GraphQL with Context and Authentication
const app = new Elysia()
.state('users', users)
.derive({ as: 'global' }, ({ headers, store }) => {
// Extract user from Authorization header
const auth = headers.authorization
let currentUser = null
if (auth?.startsWith('Bearer ')) {
const token = auth.slice(7)
// Mock token validation
currentUser = store.users.find((u: any) => u.id === token)
}
return { currentUser }
})
.use(
graphql({
typeDefs: gql`
type Query {
me: User
users: [User!]
user(id: ID!): User
}
type User {
id: ID!
name: String!
email: String!
createdAt: String!
}
type Mutation {
updateProfile(name: String): User
}
`,
resolvers: {
Query: {
me: (_, __, { currentUser }) => currentUser,
users: (_, __, { store }) => store.users,
user: (_, { id }, { store }) =>
store.users.find((u: any) => u.id === id)
},
Mutation: {
updateProfile: (_, { name }, { currentUser, store }) => {
if (!currentUser) throw new Error('Unauthorized')
const user = store.users.find((u: any) => u.id === currentUser.id)
if (user && name) user.name = name
return user
}
}
}
})
)
.listen(3000)
// 3. GraphQL Subscriptions
const app = new Elysia()
.state('posts', [
{ id: '1', title: 'First Post', content: 'Hello, World!', author: 'Admin' }
])
.derive({ as: 'global' }, ({ store }) => {
const subscriptions = new Set<any>()
return {
subscriptions,
notifyPostCreated(post: any) {
subscriptions.forEach(ws => {
ws.send(JSON.stringify({
type: 'postCreated',
data: post
}))
})
}
}
})
.use(graphql({
typeDefs: gql`
type Query {
posts: [Post!]
post(id: ID!): Post
}
type Mutation {
createPost(title: String!, content: String!): Post
}
type Subscription {
postCreated: Post!
}
type Post {
id: ID!
title: String!
content: String!
author: String!
createdAt: String!
}
`,
resolvers: {
Query: {
posts: (_, __, { store }) => store.posts,
post: (_, { id }, { store }) =>
store.posts.find((p: any) => p.id === id)
},
Mutation: {
createPost: (_, { title, content }, { store, notifyPostCreated }) => {
const newPost = {
id: (store.posts.length + 1).toString(),
title,
content,
author: 'Anonymous',
createdAt: new Date().toISOString()
}
store.posts.push(newPost)
notifyPostCreated(newPost)
return newPost
}
},
Subscription: {
postCreated: {
subscribe: (_, __, { subscriptions }) => {
const iterator = {
[Symbol.asyncIterator]() {
return this
},
async next() {
return { value: { postCreated: null }, done: false }
}
}
return iterator
}
}
}
}
}))
.listen(3000)
// 4. GraphQL with DataLoader
import DataLoader from 'dataloader'
const app = new Elysia()
.derive({ as: 'global' }, () => {
// Create a DataLoader for batch user fetching
const userLoader = new DataLoader(async (ids: string[]) => {
console.log(`Batch loading users: ${ids.join(', ')}`)
// Simulate database batch query
return ids.map(id => users.find(u => u.id === id) || null)
})
return { userLoader }
})
.use(
graphql({
typeDefs: gql`
type Query {
users(ids: [ID!]!): [User]
posts: [Post]
}
type User {
id: ID!
name: String!
email: String!
}
type Post {
id: ID!
title: String!
author: User
authorId: ID!
}
`,
resolvers: {
Query: {
users: (_, { ids }, { userLoader }) =>
userLoader.loadMany(ids),
posts: () => [
{ id: '1', title: 'Post 1', authorId: '1' },
{ id: '2', title: 'Post 2', authorId: '2' },
{ id: '3', title: 'Post 3', authorId: '1' }
]
}
},
resolvers: {
Post: {
author: (post, _, { userLoader }) =>
userLoader.load(post.authorId)
}
}
})
)
.listen(3000)
// 5. GraphQL Schema Stitching
const userService = new Elysia()
.use(
graphql({
typeDefs: gql`
type Query {
user(id: ID!): User
}
type User {
id: ID!
name: String!
email: String!
}
`,
resolvers: {
Query: {
user: (_, { id }) => users.find(u => u.id === id)
}
}
})
)
const postService = new Elysia()
.state('posts', [
{ id: '1', title: 'Post 1', authorId: '1' },
{ id: '2', title: 'Post 2', authorId: '2' }
])
.use(
graphql({
typeDefs: gql`
extend type Query {
posts: [Post!]
}
type Post {
id: ID!
title: String!
author: User
}
extend type User {
posts: [Post!]
}
`,
resolvers: {
Query: {
posts: (_, __, { store }) => store.posts
},
Post: {
author: (post) => ({ __typename: 'User', id: post.authorId })
},
User: {
posts: (user, _, { store }) =>
store.posts.filter((p: any) => p.authorId === user.id)
}
}
})
)
// 6. GraphQL Federation
const accountsService = new Elysia()
.use(
graphql({
typeDefs: gql`
type Query {
me: User
}
type User @key(fields: "id") {
id: ID!
name: String!
}
`,
resolvers: {
Query: {
me: () => ({ id: '1', name: 'John Doe' })
},
User: {
__resolveReference: (user) =>
users.find(u => u.id === user.id) || user
}
}
})
)
const postsService = new Elysia()
.use(
graphql({
typeDefs: gql`
extend type Query {
posts: [Post]
}
type Post {
id: ID!
title: String!
author: User
}
extend type User @key(fields: "id") {
id: ID! @external
posts: [Post]
}
`,
resolvers: {
Query: {
posts: () => [
{ id: '1', title: 'Post 1', authorId: '1' },
{ id: '2', title: 'Post 2', authorId: '1' }
]
},
Post: {
author: (post) => ({ __typename: 'User', id: post.authorId })
},
User: {
posts: (user) => [
{ id: '1', title: 'Post 1', authorId: user.id },
{ id: '2', title: 'Post 2', authorId: user.id }
]
}
}
})
)
// 7. GraphQL with Validation
import { z } from 'zod'
const CreateUserSchema = z.object({
name: z.string().min(1),
email: z.string().email()
})
const app = new Elysia()
.use(
graphql({
typeDefs: gql`
type Query {
users: [User!]
}
type Mutation {
createUser(input: CreateUserInput!): User!
}
type User {
id: ID!
name: String!
email: String!
}
input CreateUserInput {
name: String!
email: String!
}
`,
resolvers: {
Query: {
users: () => users
},
Mutation: {
createUser: (_, { input }) => {
// Validate input with Zod
const validatedInput = CreateUserSchema.parse(input)
const newUser = {
id: (users.length + 1).toString(),
...validatedInput,
createdAt: new Date().toISOString()
}
users.push(newUser)
return newUser
}
}
}
})
)
.listen(3000)
// 8. GraphQL Playground and Documentation
const app = new Elysia()
.use(
graphql({
typeDefs,
resolvers,
playground: true, // Enable GraphQL Playground
graphiql: true // Enable GraphiQL interface
})
)
.get('/', () => ({
message: 'GraphQL Server',
endpoints: {
graphql: '/graphql',
playground: '/graphql'
}
}))
.listen(3000)
// 9. Custom Scalars
const app = new Elysia()
.use(
graphql({
typeDefs: gql`
scalar Date
scalar Email
type Query {
currentUser: User
}
type Mutation {
updateUser(birthday: Date, email: Email): User
}
type User {
id: ID!
name: String!
birthday: Date
email: Email
}
`,
resolvers: {
Date: {
serialize: (value: Date) => value.toISOString(),
parseValue: (value: string) => new Date(value),
parseLiteral: (ast: any) => new Date(ast.value)
},
Email: {
serialize: (value: string) => value,
parseValue: (value: string) => {
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
throw new Error('Invalid email format')
}
return value
},
parseLiteral: (ast: any) => {
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(ast.value)) {
throw new Error('Invalid email format')
}
return ast.value
}
},
Query: {
currentUser: () => ({
id: '1',
name: 'John Doe',
birthday: new Date('1990-01-01'),
email: '[email protected]'
})
},
Mutation: {
updateUser: (_, { birthday, email }) => ({
id: '1',
name: 'John Doe',
birthday,
email
})
}
}
})
)
.listen(3000)
// 10. GraphQL Error Handling
const app = new Elysia()
.use(
graphql({
typeDefs: gql`
type Query {
user(id: ID!): User
throwError: String
}
type User {
id: ID!
name: String!
}
`,
resolvers: {
Query: {
user: (_, { id }) => {
const user = users.find(u => u.id === id)
if (!user) {
throw new GraphQLError('User not found', {
extensions: { code: 'USER_NOT_FOUND' }
})
}
return user
},
throwError: () => {
throw new GraphQLError('This is a test error', {
extensions: {
code: 'TEST_ERROR',
details: 'Additional error information'
}
})
}
}
},
context: () => ({}),
formatError: (error) => {
console.error('GraphQL Error:', error)
return {
message: error.message,
code: error.extensions?.code,
details: error.extensions?.details,
path: error.path,
locations: error.locations
}
}
})
)
.listen(3000)
💻 Elysia.js Plugin Development typescript
🔴 complex
Creating custom plugins and using ecosystem plugins
// Elysia.js Plugin Development Examples
import { Elysia } from 'elysia'
// 1. Basic custom plugin
const timestampPlugin = new Elysia({ name: 'timestamp' })
.decorate('getTimestamp', () => new Date().toISOString())
.onBeforeHandle({ as: 'global' }, ({ set, getTimestamp }) => {
set.headers['X-Timestamp'] = getTimestamp()
})
// Using the plugin
const app = new Elysia()
.use(timestampPlugin)
.get('/time', ({ getTimestamp }) => getTimestamp())
.listen(3000)
// 2. Database plugin
interface Database {
query: (sql: string, params?: any[]) => Promise<any[]>
insert: (table: string, data: any) => Promise<any>
update: (table: string, id: string, data: any) => Promise<any>
delete: (table: string, id: string) => Promise<boolean>
}
const databasePlugin = new Elysia({ name: 'database' })
.derive({ as: 'global' }, () => {
// Mock database implementation
const database: Database = {
async query(sql: string, params: any[] = []) {
console.log(`Query: ${sql}`, params)
// Mock data
return [{ id: 1, name: 'John', email: '[email protected]' }]
},
async insert(table: string, data: any) {
console.log(`Insert into ${table}:`, data)
return { id: Date.now(), ...data }
},
async update(table: string, id: string, data: any) {
console.log(`Update ${table} ${id}:`, data)
return { id, ...data }
},
async delete(table: string, id: string) {
console.log(`Delete from ${table} where id=${id}`)
return true
}
}
return { database }
})
// Using database plugin
const app = new Elysia()
.use(databasePlugin)
.get('/users', async ({ database }) => {
const users = await database.query('SELECT * FROM users')
return users
})
.post('/users', async ({ body, database }) => {
const user = await database.insert('users', body)
return user
})
.listen(3000)
// 3. Caching plugin
const cachePlugin = new Elysia({ name: 'cache' })
.derive({ as: 'global' }, () => {
const cache = new Map<string, { data: any; expiry: number }>()
return {
cache: {
get(key: string) {
const item = cache.get(key)
if (!item || Date.now() > item.expiry) {
cache.delete(key)
return null
}
return item.data
},
set(key: string, data: any, ttl: number = 60000) {
cache.set(key, {
data,
expiry: Date.now() + ttl
})
},
clear() {
cache.clear()
}
}
}
})
const app = new Elysia()
.use(cachePlugin)
.get('/expensive', async ({ cache }) => {
const cacheKey = 'expensive-data'
let data = cache.get(cacheKey)
if (!data) {
// Simulate expensive operation
await new Promise(resolve => setTimeout(resolve, 2000))
data = { message: 'Expensive data', timestamp: Date.now() }
cache.set(cacheKey, data, 10000) // Cache for 10 seconds
}
return data
})
.listen(3000)
// 4. Configuration plugin
interface AppConfig {
database: {
url: string
maxConnections: number
}
auth: {
jwtSecret: string
expiresIn: string
}
server: {
port: number
host: string
}
}
const configPlugin = new Elysia({ name: 'config' })
.derive({ as: 'global' }, () => {
const config: AppConfig = {
database: {
url: process.env.DB_URL || 'sqlite:app.db',
maxConnections: parseInt(process.env.DB_MAX_CONN || '10')
},
auth: {
jwtSecret: process.env.JWT_SECRET || 'default-secret',
expiresIn: process.env.JWT_EXPIRES_IN || '1h'
},
server: {
port: parseInt(process.env.PORT || '3000'),
host: process.env.HOST || 'localhost'
}
}
return { config }
})
const app = new Elysia()
.use(configPlugin)
.get('/config', ({ config }) => config)
.listen(3000)
// 5. Logging plugin
const loggerPlugin = new Elysia({ name: 'logger' })
.derive({ as: 'global' }, () => {
const logLevels = ['debug', 'info', 'warn', 'error'] as const
const logger = {
debug: (message: string, ...args: any[]) => {
console.debug(`[DEBUG] ${new Date().toISOString()} - ${message}`, ...args)
},
info: (message: string, ...args: any[]) => {
console.info(`[INFO] ${new Date().toISOString()} - ${message}`, ...args)
},
warn: (message: string, ...args: any[]) => {
console.warn(`[WARN] ${new Date().toISOString()} - ${message}`, ...args)
},
error: (message: string, ...args: any[]) => {
console.error(`[ERROR] ${new Date().toISOString()} - ${message}`, ...args)
}
}
return { logger }
})
.onBeforeHandle({ as: 'global' }, ({ logger, request }) => {
logger.info(`${request.method} ${request.url}`)
})
.onError({ as: 'global' }, ({ logger, error }) => {
logger.error(error.message)
})
const app = new Elysia()
.use(loggerPlugin)
.get('/logged', ({ logger }) => {
logger.info('This is an info message')
logger.warn('This is a warning')
return 'Logged response'
})
.listen(3000)
// 6. Plugin with lifecycle
interface User {
id: number
name: string
email: string
}
const userPlugin = new Elysia({ name: 'user' })
.derive({ as: 'global' }, ({ headers }) => {
const authHeader = headers.authorization
// Extract user from JWT (simplified)
const getUser = (): User | null => {
if (!authHeader) return null
// In real app, decode JWT here
return {
id: 1,
name: 'John Doe',
email: '[email protected]'
}
}
return {
getUser,
requireAuth(): User {
const user = getUser()
if (!user) throw new Error('Unauthorized')
return user
}
}
})
.onBeforeHandle({ as: 'global' }, ({ set, getUser }) => {
const user = getUser()
if (user) {
set.headers['X-User-ID'] = user.id.toString()
}
})
const app = new Elysia()
.use(userPlugin)
.get('/profile', ({ getUser }) => {
const user = getUser()
return user || { message: 'Not authenticated' }
})
.get('/protected', ({ requireAuth }) => {
const user = requireAuth()
return `Welcome, ${user.name}!`
})
.listen(3000)
// 7. Plugin composition
const basePlugin = new Elysia({ name: 'base' })
.decorate('baseMethod', () => 'Base functionality')
.state('baseState', 'Base state')
const extendedPlugin = new Elysia({ name: 'extended' })
.use(basePlugin)
.decorate('extendedMethod', ({ baseMethod }) => `${baseMethod} + Extended`)
.state('extendedState', 'Extended state')
const app = new Elysia()
.use(extendedPlugin)
.get('/composed', ({ baseMethod, extendedMethod, store: { baseState, extendedState } }) => ({
baseMethod,
extendedMethod,
baseState,
extendedState
}))
.listen(3000)
// 8. Plugin with options
interface RateLimitOptions {
windowMs: number
maxRequests: number
message?: string
}
const rateLimitPlugin = (options: RateLimitOptions) => {
const requests = new Map<string, { count: number; resetTime: number }>()
return new Elysia({ name: 'rate-limit' })
.onBeforeHandle({ as: 'global' }, ({ set, headers }) => {
const key = headers['x-forwarded-for'] || 'default'
const now = Date.now()
const record = requests.get(key)
if (!record || now > record.resetTime) {
requests.set(key, { count: 1, resetTime: now + options.windowMs })
return
}
if (record.count >= options.maxRequests) {
set.status = 429
return options.message || 'Too many requests'
}
record.count++
})
}
const app = new Elysia()
.use(rateLimitPlugin({ windowMs: 60000, maxRequests: 10, message: 'Rate limit exceeded' }))
.get('/limited', () => 'Rate limited endpoint')
.listen(3000)
// 9. Third-party plugin example (JWT)
// npm install @elysiajs/jwt
import { jwt } from '@elysiajs/jwt'
const app = new Elysia()
.use(
jwt({
name: 'jwt',
secret: process.env.JWT_SECRET || 'default-secret'
})
)
.post('/login', async ({ body, jwt }) => {
// Validate credentials (simplified)
if (body.username === 'admin' && body.password === 'password') {
const token = await jwt.sign({
sub: 'user123',
name: 'Admin User'
})
return { token }
}
throw new Error('Invalid credentials')
})
.get('/profile', async ({ jwt, headers }) => {
const auth = headers.authorization
if (!auth) throw new Error('No token provided')
const token = auth.replace('Bearer ', '')
const payload = await jwt.verify(token)
return payload
})
.listen(3000)
// 10. Plugin with external dependencies
// npm install ioredis
import Redis from 'ioredis'
const redisPlugin = new Elysia({ name: 'redis' })
.derive({ as: 'global' }, async () => {
const redis = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: parseInt(process.env.REDIS_PORT || '6379')
})
return {
redis: {
async get(key: string): Promise<string | null> {
return await redis.get(key)
},
async set(key: string, value: string, ttl?: number): Promise<void> {
if (ttl) {
await redis.setex(key, ttl, value)
} else {
await redis.set(key, value)
}
},
async del(key: string): Promise<boolean> {
const result = await redis.del(key)
return result > 0
}
}
}
})
const app = new Elysia()
.use(redisPlugin)
.post('/cache/:key', async ({ params: { key }, body, redis }) => {
await redis.set(key, JSON.stringify(body), 3600)
return { cached: true, key }
})
.get('/cache/:key', async ({ params: { key }, redis }) => {
const value = await redis.get(key)
return value ? JSON.parse(value) : null
})
.listen(3000)