Elysia.js Samples
Elysia.js modern TypeScript web framework examples including Hello World, routing, validation, and plugin development
Key Facts
- Category
- Web Frameworks
- Items
- 8
- Format Families
- text
Sample Overview
Elysia.js modern TypeScript web framework examples including Hello World, routing, validation, and plugin development This sample set belongs to Web Frameworks and can be used to test related workflows inside Elysia Tools.
💻 Elysia.js Hello World typescript
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 appBasic = new Elysia()
.get('/', () => 'Hello, World!')
.listen(3000)
console.log(`🦊 Elysia is running at ${appBasic.server?.hostname}:${appBasic.server?.port}`)
// 2. Hello World with different routes
const appRoutes = new Elysia()
.get('/', () => 'Hello, Elysia!')
.get('/hello', () => 'Hello from Elysia.js!')
.get('/hello/:name', ({ params: { name } }) => `Hello, ${name}!`)
.listen(3000)
// 3. JSON response
const appJson = 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 appHtml = 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 appTyped = new Elysia()
.get('/typed', () => ({
id: 1,
name: 'Elysia.js',
features: ['TypeScript', 'Performance', 'Simple API'] as const
}))
.listen(3000)
// 6. Async handlers
const appAsync = new Elysia()
.get('/async', async () => {
await new Promise(resolve => setTimeout(resolve, 1000))
return 'Async response from Elysia!'
})
.listen(3000)
// 7. Error handling
const appError = 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 appConfig = 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
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
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
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
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
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
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
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)