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.
| Decorator | Purpose | Example |
|---|---|---|
@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
| Decorator | Purpose | Example |
|---|---|---|
@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).
| Decorator | HTTP 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)
| Decorator | Purpose | Example |
|---|---|---|
@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
| Decorator | Source | Example |
|---|---|---|
@request() | Express Request object | execute(@request() req: Request) |
@response() | Express Response object | execute(@response() res: Response) |
@next() | Express NextFunction | execute(@next() next: NextFunction) |
@principal() | The authenticated principal (see Security guards) | execute(@principal() user: Principal) |
@param(name?) | URL path parameter | execute(@param("id") id: string) |
@query(name?) | URL query string | execute(@query("page") page: string) |
@body() | Parsed request body | execute(@body() dto: MyDTO) |
@headers(name?) | Request header | execute(@headers("authorization") auth: string) |
@cookies(name?) | Cookie value | execute(@cookies("session") session: string) |
@validatedBody(schema) | Validated body (Zod / Yup / class-validator) | execute(@validatedBody(CreateUserDTO) dto: CreateUserDTO) |
@validatedQuery(schema) | Validated query | execute(@validatedQuery(ListQuerySchema) q: ListQuery) |
@validatedParam(name, schema) | Validated path param | execute(@validatedParam("id", uuidSchema) id: string) |
@validatedHeaders(schema) | Validated headers | execute(@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.
| Decorator | Purpose | Example |
|---|---|---|
@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.
| Decorator | Purpose | Example |
|---|---|---|
@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.
| Decorator | Purpose |
|---|---|
@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:
@OnEventand@OnEventsare class decorators. Apply them to the handler class, not to thehandle()method, otherwise auto-discovery won't see the handler.
| Decorator | Purpose | Example |
|---|---|---|
@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.
| Decorator | Purpose |
|---|---|
@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.
| Decorator | Purpose |
|---|---|
@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.
| Decorator | Purpose |
|---|---|
@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
- Lifecycle hooks: how DI scopes interact with
@postConstruct/@preDestroy. - Validation: full reference for the validation system.
- Interceptors: AOP cross-cuts deep dive.
- Guards & Authorization: security decorators in context.
- Event System: class-level
@OnEventdiscovery flow.