Skip to main content
Version: 4.0.0-preview

Decorators

Decorators are how ExpressoTS extends classes and methods with metadata the framework reads at runtime: DI bindings, route maps, validation hooks, AOP cross-cuts, security guards, event subscriptions, and more.

This page is a complete reference. For a tutorial on a specific subsystem, follow the linked deep-dive page after the relevant table.

DI & class registration

Imported from @expressots/core.

DecoratorPurposeExample
@provide(target)Bind a class to the DI container at request scope (default).@provide(UserService) class UserService {}
@provideSingleton(target)Same as @provide but singleton scope.@provideSingleton(Cache) class Cache {}
@provideTransient(target)Same as @provide but transient scope.@provideTransient(IdGen) class IdGen {}
@provideInScope(target, scope)Bind to a custom named scope (see ScopeRegistry).@provideInScope(Tenant, "tenant") class Tenant {}
@Provider({ scope })Annotate a provider with metadata for ProviderRegistry introspection.@Provider({ scope: "singleton" })
@injectable()Mark a class as injectable without binding it (re-export from InversifyJS).@injectable() class Helper {}
@inject(token)Inject a dependency into a constructor / property.constructor(@inject(UserRepo) private repo: UserRepo) {}
@multiInject(token)Inject all bindings registered for a token.@multiInject(IPlugin) plugins: IPlugin[]
@named(name)Disambiguate multiple bindings by name.@inject(MyToken) @named("primary") svc!: MySvc
@tagged(key, value)Disambiguate by tag.@inject(MyToken) @tagged("region", "us") svc!: MySvc
@optional()Make an injection optional (returns undefined if unbound).@inject(Cache) @optional() cache?: Cache
@unmanaged()Mark a constructor parameter as unmanaged (skipped by the container).constructor(@unmanaged() raw: unknown) {}
@postConstruct()Run a method right after construction.@postConstruct() init() {}
@preDestroy()Run a method right before destruction.@preDestroy() cleanup() {}

Controller & routing

Imported from @expressots/adapter-express unless noted.

Class-level

DecoratorPurposeExample
@controller(path, ...middleware)Mark a class as a controller, prefix its routes.@controller("/users", AuthMiddleware)
@scope(scope) (@expressots/core)Override the controller's DI scope.@scope("Singleton")

Method (HTTP verbs)

All accept (path, ...middleware).

DecoratorHTTP verb
@Get(path, …)GET
@Post(path, …)POST
@Put(path, …)PUT
@Patch(path, …)PATCH
@Delete(path, …)DELETE
@Head(path, …)HEAD
@All(path, …)All verbs
@Method(verb, path, …)Arbitrary verb (e.g. OPTIONS)

Method (response shaping)

DecoratorPurposeExample
@Http(code)Set the response status code.@Http(StatusCode.Created)
@Version(version)Bind a route handler to a specific API version (header or path-based). See API versioning.@Version("2")
@Render(view, data?)Render a view through the unified render service.@Render("home", { user })
@FileUpload(opts?)Multer-backed file upload.@FileUpload({ field: "avatar" })

Parameter

DecoratorSourceExample
@request()Express Request objectexecute(@request() req: Request)
@response()Express Response objectexecute(@response() res: Response)
@next()Express NextFunctionexecute(@next() next: NextFunction)
@principal()The authenticated principal (see Security guards)execute(@principal() user: Principal)
@param(name?)URL path parameterexecute(@param("id") id: string)
@query(name?)URL query stringexecute(@query("page") page: string)
@body()Parsed request bodyexecute(@body() dto: MyDTO)
@headers(name?)Request headerexecute(@headers("authorization") auth: string)
@cookies(name?)Cookie valueexecute(@cookies("session") session: string)
@validatedBody(schema)Validated body (Zod / Yup / class-validator)execute(@validatedBody(CreateUserDTO) dto: CreateUserDTO)
@validatedQuery(schema)Validated queryexecute(@validatedQuery(ListQuerySchema) q: ListQuery)
@validatedParam(name, schema)Validated path paramexecute(@validatedParam("id", uuidSchema) id: string)
@validatedHeaders(schema)Validated headersexecute(@validatedHeaders(authHeaders) h: AuthHeaders)

See Validation for the full validation flow.

Content negotiation

Imported from @expressots/adapter-express. See Content Negotiation for the deep dive.

DecoratorPurposeExample
@Accept(...types)Restrict what Content-Type the route accepts.@Accept("application/json", "application/xml")
@Produces(...types)Declare what types the route produces (used to format the response).@Produces("application/json", "text/csv")
@Consumes(...types)Document the request body content type.@Consumes("application/json")
@CsvOptions(opts)Configure CSV serialization for this handler.@CsvOptions({ delimiter: ";" })
@XmlOptions(opts)Configure XML serialization.@XmlOptions({ root: "users" })
@YamlOptions(opts)Configure YAML serialization.@YamlOptions({ indent: 2 })
@StreamResponse()Stream the response body instead of buffering.@StreamResponse()

AOP: interceptors

Imported from @expressots/core. See Interceptors.

DecoratorPurposeExample
@Interceptor({ priority })Mark a class as an interceptor; lower priority runs first.@Interceptor({ priority: 10 })
@UseInterceptors(...interceptors)Apply interceptors to a controller class or specific method.@UseInterceptors(LoggingInterceptor)

Security: guards & authorization

Imported from @expressots/core. See Guards & Authorization.

DecoratorPurpose
@Guard({ priority, cacheable })Mark a class as a guard.
@UseGuards(...guards)Apply guards to a controller class or method.
@RequireAuthentication()Shorthand for @UseGuards(AuthenticatedGuard).
@RequireRoles(...roles)Require all the listed roles.
@RequirePermissions(...permissions)Require all the listed permissions.
@RequireOwnership(paramName)Require the principal to own the resource identified by paramName.
@RequireAuth() / @RequireRole(role) / @RequirePermission(perm) / @RequireResourceOwner(paramName) / @RequirePolicy(policyFn)Single-value variants for cleaner one-off checks.

Events

Imported from @expressots/core. See Event System.

Important: @OnEvent and @OnEvents are class decorators. Apply them to the handler class, not to the handle() method, otherwise auto-discovery won't see the handler.

DecoratorPurposeExample
@OnEvent(EventClass, opts?)Subscribe a class to a single event type.@OnEvent(UserCreatedEvent, { priority: 1 })
@OnEvents([EventA, EventB])Subscribe a class to multiple event types.@OnEvents([UserCreatedEvent, UserUpdatedEvent])
@When(predicate)Run the handler only when the predicate is true.@When(event => event.user.isPremium)
@Event()Mark a class as an event payload (optional metadata; not strictly required).@Event() class UserCreatedEvent { … }

Validation

Imported from @expressots/core and @expressots/adapter-express. See Validation.

DecoratorPurpose
@Validate(schema, options?)Class-level: validate every method's input against a schema.
@validatedBody(schema) / @validatedQuery(schema) / @validatedParam(name, schema) / @validatedHeaders(schema)Parameter-level (see the Parameter table above).

Exception filters

Imported from @expressots/core (decorators) and @expressots/adapter-express (re-export). See Exception filters.

DecoratorPurpose
@Catch(...errorClasses)Mark a class as an exception filter that handles the listed error types.
@UseFilters(...filterClasses)Apply filters to a controller class or method.

Logging

Imported from @expressots/core. See Logging.

DecoratorPurpose
@LogPerformance()Wrap a method with high-precision timing.

Lifecycle (provider-level)

These are interfaces with @postConstruct / @preDestroy decorators inside, but you'll typically just implement the interface:

import { provide, IBootstrap, IShutdown } from "@expressots/core";

@provide(MyService)
export class MyService implements IBootstrap, IShutdown {
async bootstrap() { /* called by AppExpress before listen() */ }
async shutdown() { /* called on SIGINT / SIGTERM */ }
}

See Lifecycle hooks for the full bootstrap / shutdown sequence.

Configuration scaffolding

The CLI (expressots generate) recognises decorator metadata in expressots.config.ts to know where to place generated files (scaffoldSchematics.controller, scaffoldSchematics.guard, etc.). See ExpressoTS config.


See also