Elysia
TypeScript-first framework with Bun - Web Standards native, no adapter needed!
Using pushduck with Elysia
Elysia is a TypeScript-first web framework designed for Bun. Since Elysia uses Web Standard Request objects natively, pushduck handlers work directly without any adapters!
Web Standards Native: Elysia exposes context.request as a Web Standard Request object, making pushduck integration seamless with zero overhead.
Quick Setup
Install dependencies
bun add pushducknpm install pushduckyarn add pushduckpnpm add pushduckConfigure upload router
import { createUploadConfig } from 'pushduck/server';
const { s3, createS3Router } = createUploadConfig()
.provider("cloudflareR2",{
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
region: 'auto',
endpoint: process.env.AWS_ENDPOINT_URL!,
bucket: process.env.S3_BUCKET_NAME!,
accountId: process.env.R2_ACCOUNT_ID!,
})
.build();
export const uploadRouter = createS3Router({
imageUpload: s3.image().maxFileSize("5MB"),
documentUpload: s3.file().maxFileSize("10MB")
});
export type AppUploadRouter = typeof uploadRouter;Create Elysia app with upload routes
import { Elysia } from 'elysia';
import { uploadRouter } from './lib/upload';
const app = new Elysia();
// Direct usage - no adapter needed!
app.get('/api/upload', ({ request }) => uploadRouter.handlers.GET(request));
app.post('/api/upload', ({ request }) => uploadRouter.handlers.POST(request));
app.listen(3000);Basic Integration
Simple Upload Route
import { Elysia } from 'elysia';
import { uploadRouter } from './lib/upload';
const app = new Elysia();
// Separate GET and POST handlers (required)
app.get('/api/upload', ({ request }) => uploadRouter.handlers.GET(request));
app.post('/api/upload', ({ request }) => uploadRouter.handlers.POST(request));
app.listen(3000);With Middleware and CORS
import { Elysia } from 'elysia';
import { cors } from '@elysiajs/cors';
import { uploadRouter } from './lib/upload';
const app = new Elysia()
.use(cors({
origin: ['http://localhost:3000', 'https://your-domain.com'],
allowedHeaders: ['Content-Type', 'Authorization'],
methods: ['GET', 'POST']
}))
// Upload routes
.get('/api/upload', ({ request }) => uploadRouter.handlers.GET(request))
.post('/api/upload', ({ request }) => uploadRouter.handlers.POST(request))
// Health check
.get('/health', () => ({ status: 'ok' }))
.listen(3000);
console.log(`🦊 Elysia is running at http://localhost:3000`);Advanced Configuration
Authentication with JWT
import { createUploadConfig } from 'pushduck/server';
import jwt from '@elysiajs/jwt';
const { s3, createS3Router } = createUploadConfig()
.provider("cloudflareR2",{
accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
region: 'auto',
endpoint: process.env.AWS_ENDPOINT_URL!,
bucket: process.env.S3_BUCKET_NAME!,
accountId: process.env.R2_ACCOUNT_ID!,
})
.paths({
prefix: 'uploads',
generateKey: (file, metadata) => {
return `${metadata.userId}/${Date.now()}/${file.name}`;
}
})
.build();
export const uploadRouter = createS3Router({
// Private uploads with JWT authentication
privateUpload: s3
.image()
.maxFileSize("5MB")
.middleware(async ({ req }) => {
const authHeader = req.headers.get('authorization');
if (!authHeader?.startsWith('Bearer ')) {
throw new Error('Authorization required');
}
const token = authHeader.substring(7);
try {
// Use your JWT verification logic here
const payload = jwt.verify(token, process.env.JWT_SECRET!);
return {
userId: payload.sub as string,
userRole: payload.role as string
};
} catch (error) {
throw new Error('Invalid token');
}
}),
// Public uploads (no auth)
publicUpload: s3
.image()
.maxFileSize("2MB")
// No middleware = public access
});
export type AppUploadRouter = typeof uploadRouter;Full Production Setup
import { Elysia } from 'elysia';
import { cors } from '@elysiajs/cors';
import { rateLimit } from '@elysiajs/rate-limit';
import { swagger } from '@elysiajs/swagger';
import { uploadRouter } from './lib/upload';
const app = new Elysia()
// Swagger documentation
.use(swagger({
documentation: {
info: {
title: 'Upload API',
version: '1.0.0'
}
}
}))
// CORS
.use(cors({
origin: process.env.NODE_ENV === 'production'
? ['https://your-domain.com']
: true,
allowedHeaders: ['Content-Type', 'Authorization'],
methods: ['GET', 'POST']
}))
// Rate limiting
.use(rateLimit({
max: 100,
windowMs: 15 * 60 * 1000, // 15 minutes
}))
// Upload routes
.get('/api/upload', ({ request }) => uploadRouter.handlers.GET(request))
.post('/api/upload', ({ request }) => uploadRouter.handlers.POST(request))
// Health check
.get('/health', () => ({
status: 'ok',
timestamp: new Date().toISOString()
}))
.listen(process.env.PORT || 3000);
console.log(`🦊 Elysia is running at http://localhost:${process.env.PORT || 3000}`);TypeScript Integration
Type-Safe Client
import { createUploadClient } from 'pushduck/client';
import type { AppUploadRouter } from './upload';
export const uploadClient = createUploadClient<AppUploadRouter>({
baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'
});Client Usage
import { uploadClient } from '../lib/upload-client';
export function UploadComponent() {
const handleUpload = async (files: File[]) => {
try {
const results = await uploadClient.upload('imageUpload', {
files,
// Type-safe metadata based on your router configuration
metadata: { userId: 'user-123' }
});
console.log('Upload successful:', results);
} catch (error) {
console.error('Upload failed:', error);
}
};
return (
<input
type="file"
multiple
onChange={(e) => {
if (e.target.files) {
handleUpload(Array.from(e.target.files));
}
}}
/>
);
}Performance Benefits
🚀 Zero Overhead
Direct Web Standards integration
No adapter layer means zero performance overhead - pushduck handlers run directly in Elysia.
⚡ Bun Performance
Ultra-fast JavaScript runtime
Built for Bun's exceptional performance, perfect for high-throughput upload APIs.
📝 TypeScript First
End-to-end type safety
Full TypeScript support from server to client with compile-time safety.
🔧 Plugin Ecosystem
Rich middleware support
Extensive plugin ecosystem for authentication, validation, rate limiting, and more.
Deployment
Production Deployment
FROM oven/bun:1 as base
WORKDIR /usr/src/app
# Install dependencies
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
# Copy source code
COPY . .
# Expose port
EXPOSE 3000
# Run the app
CMD ["bun", "run", "server.ts"]# Build and run
docker build -t my-upload-api .
docker run -p 3000:3000 my-upload-apiPerfect TypeScript Integration: Elysia's TypeScript-first approach combined with pushduck's type-safe design creates an exceptional developer experience with full end-to-end type safety.