Docs/decoratorsv1.0.0-rc.1

Decorator Reference

Prerequisites: All decorators require TypeScript compiler options experimentalDecorators: true and emitDecoratorMetadata: true, plus import '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, @Delete accept either a path string or a RouteOptions object. The object form supports path, middleware, statusCode, summary, description, plus: body, query, params, headers (validation schemas — UDIOT ValidationSchema maps), responses (status → schema/description), tags, operationId, deprecated. Schemas drive both runtime validation (failures throw unprocessableEntity() → 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.

From the canonical UDIOT public documentation.Try it in the playground ↗