Decorator Reference
Prerequisites: All decorators require TypeScript compiler options
experimentalDecorators: trueandemitDecoratorMetadata: true, plusimport 'reflect-metadata'as the first import in your entry file.
Dependency Injection
@Injectable
| Target | Class |
| Import | @tagna/udiot |
| Description | Marks a class as injectable so the DI container can manage its lifecycle and inject its dependencies. |
Options: scope (ServiceScope.SINGLETON | ServiceScope.TRANSIENT | ServiceScope.SCOPED), providedIn (string | 'root')
@Injectable({ scope: ServiceScope.SINGLETON })
class UserService {
constructor(private db: DatabaseService) {}
}
@Inject
| Target | Parameter |
| Import | @tagna/udiot |
| Description | Explicitly specifies an injection token for a constructor parameter, required when the type alone is insufficient (primitives, string tokens). |
Options: token (string | symbol | Function)
constructor(@Inject('API_URL') private url: string) {}
@InjectProperty
| Target | Property |
| Import | @tagna/udiot |
| Description | Injects a dependency into a class property after construction, without requiring a constructor parameter. |
Options: token? (string | symbol | Function) — defaults to the property's reflected type
@InjectProperty('CONFIG') private config: AppConfig;
@Optional
| Target | Parameter |
| Import | @tagna/udiot |
| Description | Marks a constructor parameter as optional; injects undefined instead of throwing if the dependency is not registered. |
constructor(@Optional() @Inject('CACHE') private cache?: CacheService) {}
@ComponentDecorator
| Target | Class |
| Import | @tagna/udiot |
| Description | Declares a class as a UI component; automatically makes it injectable and registers it in the ComponentRegistry. |
Key options: selector (required), template?, templateUrl?, styles?, inputs?, outputs?, description?, tags?, aiGenerated?
@ComponentDecorator({ selector: 'user-card', template: '<div>{{name}}</div>' })
class UserCard extends BaseComponent {}
@Controller
| Target | Class |
| Import | @tagna/udiot |
| Description | Marks a class as an HTTP controller; makes it injectable and associates a base route path with all its route handlers. |
Options: path? (string), middleware? (any[])
@Controller('/api/users')
class UsersController {
constructor(private userService: UserService) {}
}
HTTP method decorators
@Get,@Post,@Put,@Patch,@Deleteaccept either a path string or aRouteOptionsobject. The object form supportspath,middleware,statusCode,summary,description, plus:body,query,params,headers(validation schemas — UDIOTValidationSchemamaps),responses(status → schema/description),tags,operationId,deprecated. Schemas drive both runtime validation (failures throwunprocessableEntity()→ Problem Details JSON) and OpenAPI emit. Parameter decorators:@Param,@Query,@Body,@Header,@Req,@Res,@CurrentUser. See the API conventions guide for examples.
@Module
| Target | Class |
| Import | @tagna/udiot |
| Description | Groups related controllers, providers, and components into a cohesive module and controls what they export to other modules. |
Key options: imports?, providers?, controllers?, components?, exports?
@Module({ providers: [UserService], controllers: [UserController], exports: [UserService] })
class UserModule {}
HTTP Controller Auth & Limits
These decorators are read by toExpressRouter() (and surfaced through
createWebServer({ controllers })). They cooperate with WebServerOptions.authResolver
and WebServerOptions.rateLimits configured at boot — keeping policy in app
config and intent on the route, the way the rest of UDIOT splits semantics
from configuration.
@RequireAuth
| Target | Class or method |
| Import | @tagna/udiot |
| Description | Marks a controller (or single route) as authenticated. The Express adapter calls the configured authResolver(req); a falsy result fails closed with a 401 application/problem+json (code: UNAUTHENTICATED) unless optional: true. Method-level options merge over class-level. |
Options: schemes? (Array<'bearer' \| 'session-cookie' \| 'api-key' \| string>), roles? (string[]), scopes? (string[]), optional? (boolean)
@RequireAuth({ scopes: ['reports:read'] })
@Get('/reports')
async list(@CurrentUser() user: AuthenticatedUser) {
return this.reports.list(user.id);
}
The resolver is plug-in: bring your own JWT, session, or API-key strategy. For an end-to-end example see the production composition recipe.
@CurrentUser
| Target | Parameter |
| Import | @tagna/udiot |
| Description | Injects the resolved auth principal (whatever authResolver returned). On routes without @RequireAuth, resolves to undefined. |
@RequireAuth()
@Get('/me')
me(@CurrentUser() user: AuthenticatedUser) {
return { user };
}
@UseRateLimit
| Target | Class or method |
| Import | @tagna/udiot |
| Description | Tags a route with a named rate-limit policy declared on WebServerOptions.rateLimits. The framework refuses to start if a referenced policy is not registered, so missing policies surface at boot rather than at request time. |
Argument: policy (string) — must match a key in rateLimits.
@UseRateLimit('checkout')
@Post('/checkout/capture')
async capture(@Body() body: CheckoutCaptureDto) {
return this.checkout.capture(body);
}
Policy definitions accept maxRequests, windowMs, and key ('ip' |
'user' | 'userOrIp' | (req) => string); responses include
Retry-After and X-RateLimit-* headers.
State Management
@ReactiveStore
| Target | Class |
| Import | @tagna/udiot |
| Description | Wraps a Store subclass to enable automatic registration in StoreRegistry and configure store-level options. |
Key options: name?, aiTracking?, trackHistory?, devTools?, persist?, maxHistory?
@ReactiveStore({ name: 'TodoStore', trackHistory: true })
class TodoStore extends Store<TodoState> {}
@Mutation
| Target | Method |
| Import | @tagna/udiot |
| Description | Marks a synchronous method as a state mutation; enables optional validation and AI tracking of mutation patterns. |
Key options: name?, validate?, aiTracking?, description?
@Mutation({ aiTracking: true })
addItem(item: Item): void { this.dispatch({ type: 'ADD_ITEM', payload: item }); }
@Action
| Target | Method |
| Import | @tagna/udiot |
| Description | Marks an async method as a store action; automatically dispatches _PENDING, _FULFILLED, and _REJECTED lifecycle actions and supports debounce, throttle, retry, and caching. |
Key options: name?, debounce?, throttle?, retry?, retryDelay?, cache?, cacheTTL?, aiTracking?
@Action({ retry: 3, cache: true, cacheTTL: 30000 })
async fetchUsers(): Promise<User[]> { return fetch('/api/users').then(r => r.json()); }
@Selector
| Target | Method |
| Import | @tagna/udiot |
| Description | Converts a store method into a memoized selector that caches results and only recomputes when state dependencies change. |
Key options: deps? (string[] — names of other selector methods), name?, equalityFn?, aiTracking?
@Selector()
completedTodos(): Todo[] { return this.getState().todos.filter(t => t.completed); }
@Computed
| Target | Method / getter |
| Import | @tagna/udiot |
| Description | Alias for @Selector on stores; on components, marks a getter as a cached computed property that invalidates when state changes. |
@Computed()
get totalPrice(): number { return this.items.reduce((s, i) => s + i.price, 0); }
Component state
Use the public component/state APIs described in state. Do not assume a source-level decorator is exported from the root entry point.
@Persist
| Target | Class |
| Import | @tagna/udiot |
| Description | Enables automatic state persistence for a store; loads state on initialization and saves on every change. |
Key options: key?, storage? ('localStorage' | 'sessionStorage' | 'indexedDB' | 'memory'), debounce?, version?, migrate?, whitelist?, blacklist?, serialize?, deserialize?, autoLoad?, autoSave?
@Persist({ storage: 'localStorage', whitelist: ['items', 'filter'] })
class CartStore extends Store<CartState> {}
@AIPowered
| Target | Class |
| Import | @tagna/udiot |
| Description | Enables the full AI feature set (state analysis, optimizer, predictor) on a store class and wires them into the dispatch pipeline. |
Key options: analyzer?, optimizer?, predictor?, autoAnalyze?, autoOptimize?, logInsights?, onSuggestion?, onAnomaly?
@AIPowered({ autoAnalyze: true, logInsights: true })
class SmartStore extends Store<AppState> {}
@EnableDevTools
| Target | Class |
| Import | @tagna/udiot |
| Description | Connects a store to Redux DevTools and the UDIOT StateInspector; supports time-travel, state import/export, and reset. |
Key options: devTools?, inspector?, consoleLogger?, autoConnect?
@EnableDevTools({ consoleLogger: true })
class AppStore extends Store<AppState> {}
Middleware, telemetry and AI limitations
The internal middleware decorators (Middleware, Handle, Next,
Pipeline, UseMiddleware, Before, After, CatchErrors,
Measure, When) are not public runtime exports. Root Middleware is a
type and Context is a reactive class, not a parameter decorator.
Use functional composition.
AILogged, AIAlert, AIController, AIEndpoint and TenantScoped
are internal decorators, not public root imports. Use
telemetry functions, controller adapters
and tenant scope instead.
Public experimental component decorators are documented in AI decorators. Presence in the export map is not a stable support promise; see API status.