Decorators
ExisJS provides a rich ecosystem of standard ES6 decorators for developers who prefer the Object-Oriented Programming (OOP) paradigm (heavily inspired by NestJS).
Because ExisJS does not rely on heavy reflection libraries like reflect-metadata, these decorators are incredibly fast and memory-efficient.
All decorators can be imported directly from exisjs/decorators.
1. Servers & Gateways
ExisJS allows you to configure your root application and directory-scoped gateways using decorators, completely replacing the need for functional exis() and defineGateway() wrappers if you prefer OOP.
@Server(config)
Used exclusively in your src/http/server.ts file to bootstrap the application.
import { Server } from 'exisjs/decorators'import { metricsPlugin } from './plugins/metrics'import type { App } from 'exisjs'
@Server({ plugins: [metricsPlugin], providers: [['Logger', { useValue: console }]]})export default class RootServer { async onStart(app: App) { console.log('Server started!') }}@Gateway(config)
Used inside any folder (e.g. src/http/admin/gateway.ts) to act as a gatekeeper for all routes within that directory and its subdirectories.
import { Gateway } from 'exisjs/decorators'import { requireAuth } from '../../middleware/auth'
@Gateway({ middleware: [requireAuth], cors: { origin: 'https://admin.com' }, timeout: 10000, metadata: { openapi: { tags: ['Admin'] } }})export default class AdminGateway {}1. Controllers & Routing
To map a class to a route prefix, use the @Controller() decorator. You can then use HTTP Method decorators to map class methods to specific endpoints.
import { Controller, Get, Post, Put, Delete } from 'exisjs/decorators'
@Controller('/users')export default class UsersController { @Get('/') async listUsers() { return { users: [] } }
@Post('/create') async createUser() { return { success: true } } @Delete('/:id') async deleteUser() {}}Available Method Decorators
@Get(path?, schema?)@Post(path?, schema?)@Put(path?, schema?)@Patch(path?, schema?)@Delete(path?, schema?)@Options(path?, schema?)@Head(path?, schema?)@All(path?, schema?)@Ws(path?, schema?)(For WebSockets)@Sse(path?, schema?)(For Server-Sent Events)
2. Request Parameters
Instead of manually digging through the req object, ExisJS allows you to cleanly inject request properties directly into your method parameters.
import { Controller, Post, Body, Param, Headers, Req, Res } from 'exisjs/decorators'
@Controller('/users')export default class UsersController { @Post('/:id') async update( @Param('id') id: string, @Body() payload: any, @Headers('authorization') token: string, @Req() req: any, @Res() res: any ) { return { success: true, id, payload } }}Available Parameter Decorators
@Body(key?)- Extractsreq.bodyor a specific key.@Param(key?)- Extractsreq.paramsor a specific key.@Query(key?)- Extractsreq.queryor a specific key.@Headers(key?)- Extractsreq.headersor a specific key.@Req()- Injects the underlyingExisRequestobject.@Res({ passthrough?: boolean })- Injects the underlyingExisResponseobject.@Ip()- Extracts the client IP address.@Next()- Injects thenext()function for middleware bypass.@Session()- Injectsreq.session(if a session plugin is active).@Socket()- Injects theExisWebSocket(only valid in@Wsroutes).@Stream()- Injects theExisSSEstream (only valid in@Sseroutes).@UploadedFile()/@UploadedFiles()- Automatically extracts multipart form-data files!
3. Middleware & Lifecycles
You can bind Middleware, Guards, Exception Filters, and Interceptors directly to your Controllers or individual methods using decorators!
import { Controller, Get, Use, UseGuards, UseFilters } from 'exisjs/decorators'import { requireAuth } from '../../middleware/auth'import { RoleGuard } from '../../guards/role'import { AdminErrorFilter } from '../../filters/admin'
@Controller('/admin')@Use(requireAuth) // Applies to the entire class@UseFilters(AdminErrorFilter) // Applies to the entire classexport default class AdminController { @Get('/dashboard') @UseGuards(RoleGuard) // Applies ONLY to this method async getDashboard() { return { secret: 'data' } }}Available Lifecycle Decorators
@Use(...middlewares)- Binds standard Express-style middleware.@UseGuards(...guards)- Binds ExisJS authorization Guards.@UseInterceptors(...interceptors)- Binds response Interceptors.@UseFilters(...filters)- Binds Exception Filters.
4. Response Modifiers
Sometimes you need to modify the HTTP Response (like changing the status code or adding a header) without injecting the raw @Res() object.
import { Controller, Post, HttpCode, Header, Redirect } from 'exisjs/decorators'
@Controller('/api')export default class ApiController { @Post('/create') @HttpCode(201) // Forces the response status to 201 Created @Header('X-Custom-Version', '2.0') // Appends a custom header async create() { return { success: true } } @Get('/legacy') @Redirect('/new-api', 301) // Automatically redirects the client! async legacy() {}}Available Response Decorators
@HttpCode(code: number)@Header(name: string, value: string)@Redirect(url: string, statusCode?: number)@Hosts(...hosts: string[])- Restricts a route/controller to a specific Host header (e.g.api.example.com).
5. Dependency Injection
To mark a class as a service that can be injected into your controllers, use the @Injectable() decorator.
import { Injectable } from 'exisjs/decorators'
@Injectable({ scope: 'singleton' })export class DatabaseService { async findUser() { ... }}