Plugin Composition
Compose Elysia plugins directly in AbsoluteJS with clear boundaries and predictable hook behavior.
#Basics
Stack plugins in the same Elysia chain:
TS
import { Elysia } from 'elysia';
import { cors } from '@elysiajs/cors';
import { swagger } from '@elysiajs/swagger';
import { staticPlugin } from '@elysiajs/static';
new Elysia()
.use(cors())
.use(swagger())
.use(staticPlugin({ assets: './public' }));#Encapsulation
Use sub-plugins to isolate API and background job behavior:
TS
import { Elysia } from 'elysia';
import { cors } from '@elysiajs/cors';
import { cron } from '@elysiajs/cron';
const apiPlugin = new Elysia({ prefix: '/api' })
.use(cors({ origin: ['https://app.example.com'] }))
.get('/health', () => ({ ok: true }));
const jobsPlugin = new Elysia({ prefix: '/jobs' })
.use(
cron({
name: 'heartbeat',
pattern: '*/30 * * * * *',
run() {
console.log('background heartbeat');
}
})
);
new Elysia()
.use(apiPlugin)
.use(jobsPlugin);#Scoped Hooks
Hooks defined in a plugin apply to routes in that plugin scope:
TS
import { Elysia } from 'elysia';
const authPlugin = new Elysia({ prefix: '/app' })
.onBeforeHandle(({ cookie, status }) => {
if (!cookie.session?.value) {
return status(401, 'Unauthorized');
}
})
.get('/dashboard', () => 'private');
new Elysia()
.get('/', () => 'public')
.use(authPlugin);#Registration Order
Registration order determines what hooks and plugins apply to each route:
TS
import { Elysia } from 'elysia';
import { cors } from '@elysiajs/cors';
import { swagger } from '@elysiajs/swagger';
new Elysia()
.use(cors())
.use(swagger())
// register routes after plugins/hooks you want applied
.get('/api/users', () => [])
.listen(3000);Plugin before routePlugin behavior applies
Plugin after routeExisting route is unaffected