Skip to main content

Decorators catalog

Titan and its ecosystem ship a lot of decorators. This page is the single-source-of-truth lookup: what each decorator does, which package to import it from, and which decorators share a name across packages (so you don't accidentally import the wrong one).

All entries verified against source via grep for ^export (function|const) [A-Z] returning a decorator type.

Quick lookup by purpose

You want to…Reach for
Mark a class as DI-injectable@Injectable() (core)
Expose a class as RPC service@Service('name@version') (core)
Expose a method on the wire@Public() (core)
Validate a method's args / return@Validate(schema) (core)
Require authenticated caller@RequireAuth() (titan-auth)
Skip auth for one method@Public() (titan-auth — opts out of auth)
Memoise an idempotent method@Cacheable() (titan-cache)
Throttle calls per key@RateLimit({ key, limit }) (titan-ratelimit)
Run at a cron schedule@Cron('0 * * * *') (titan-scheduler)
Run on an interval@Interval(60_000) (titan-scheduler)
Subscribe to a typed event@OnEvent('user.created') (titan-events)
Auto-emit an event from a method@EmitEvent('user.created') (titan-events)
Wrap a method in a distributed lock@WithDistributedLock(key, ttl) (titan-lock)
Instrument a method with counter + histogram@Metrics({ counter, histogram }) (titan-metrics)
Define a worker process class@Process() (titan-pm)
Define a supervised hierarchy@Supervisor() + @Child() (titan-pm)
Bind a class to a config subtree@Configuration('cache') (config built-in)
Read one config value@Config('cache.ttlMs', 60_000) (config built-in)
Apply RLS to a repository@Policy(...) + @Allow/@Deny/@Filter (titan-database)
Soft-delete a repository's rows@SoftDelete() (titan-database)
Auto-add created_at/updated_at@Timestamps() (titan-database)
Audit row changes@Audit() (titan-database)

Core decorators

Built-in@omnitron-dev/titan

Ships inside @omnitron-dev/titan. No additional install required.

Imported from the package root (@omnitron-dev/titan) unless noted.

DI

DecoratorTargetsEffect
@Injectable(opts?)classMarks a class as a DI provider
@Service(name)classMarks a class as a Netron RPC service
@Inject(token)parameter / propertyResolves a token from the container
@Optional()parameter / propertyAllow undefined if the token isn't registered
@Global()class (on Module)Makes the module's exports visible everywhere

RPC surface

DecoratorTargetsEffect
@Public(opts?)method / propertyExposes the method on the wire
@Contract(class)classBinds a Zod-based input/output contract
@Validate({input, output})methodRuns Zod schemas around the call
@NoValidation()methodOpts out of class-level validation
@WithValidationOptions(opts)classSets default validation behaviour for the class
@ValidateInput(schema)methodInput-only validation
@ValidateOutput(schema)methodOutput-only validation

The core @Public() exposes; the titan-auth @Public() further marks the same method as auth-bypass. They compose: @Public() @RequireAuth() for an exposed-but-protected method is the common pattern.

Lifecycle

DecoratorTargetsEffect
@PostConstruct()methodRun after construction, before onInit
@PreDestroy()methodRun during onDestroy

For full hooks (onInit, onStart, onStop, onDestroy) implement the interfaces instead — they're more discoverable than decorators. See Lifecycle reference.

Method utilities

Most utility decorators are method interceptors that compose freely with other decorators.

DecoratorEffect
@MemoizeCache the result of a function in-memory by arg fingerprint
@Retry({ attempts, delay })Retry on throw with linear delay
@Retryable({...})More configurable retry (backoff curve, predicate)
@Timeout({ ms })Reject if the method doesn't resolve within ms
@Log({...})Log entry / exit / error
@Monitor({...})Emit metric samples around the call
@Deprecated({ message, version })Warn callers; metadata for tooling

The core @Timeout clashes with titan-scheduler.@Timeout — distinguish by import path (@omnitron-dev/titan vs @omnitron-dev/titan-scheduler).

Built-in module decorators

config

Built-in@omnitron-dev/titan/module/config

Ships inside @omnitron-dev/titan. No additional install required.

DecoratorTargetsEffect
@Config(path, default?)propertyInject one config value at a dotted path
@InjectConfig()propertyInject the whole ConfigService
@Configuration(prefix?)classBind the class as a typed view of a config subtree
@ConfigSchema(schema)classClass-level Zod schema for the bound subtree
@ConfigWatch(path)methodMethod runs when the watched path changes
@ConfigDefaults({...})classProvide class-level defaults
@ConfigProvider(name)classCustom config provider class
@Configuration('cache')
class CacheConfig {
@Config('ttlMs', 60_000) ttlMs!: number;
@Config('maxItems', 1024) maxItems!: number;
}

logger

Built-in@omnitron-dev/titan/module/logger

Ships inside @omnitron-dev/titan. No additional install required.

The logger module exports no decorators — instances are injected via token / interface (LOGGER_SERVICE_TOKEN, LOGGER_TOKEN). See logger.

Official module decorators

titan-auth

Official@omnitron-dev/titan-auth

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@RequireAuth(opts?)methodCaller must present a valid JWT
@RequireServiceAuth()methodCaller must hold the service role
@RequireAdminAuth()methodCaller must hold the admin role
@RequireRole(roles[], message?)methodCaller must hold at least one of the listed roles
@Public()class / methodAuth bypass — explicitly mark as anonymous-allowed

Two @Public() decorators exist. The core one exposes the method on Netron. The titan-auth one opts it out of authentication. Import path determines which: @omnitron-dev/titan (expose) vs @omnitron-dev/titan-auth (auth bypass).

titan-cache

Official@omnitron-dev/titan-cache

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@Cacheable(opts?)methodMemoise return value; key derived from args
@CachePut(opts?)methodAlways run the method, but update cache with result
@CacheInvalidate(opts?)methodRemove cache entry / key pattern after method runs
@CacheKey()parameterMark one parameter as the cache key seed
@InjectCacheService()propertyInject the ICacheService directly
@InjectCacheLogger()propertyInject the cache-scoped logger

titan-database

Official@omnitron-dev/titan-database

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@InjectConnection(name?)parameterInject a named database connection
@InjectDatabaseManager()parameterInject the global DatabaseManager
@SoftDelete(config?)classApply Kysera soft-delete plugin
@Timestamps(config?)classApply Kysera timestamps plugin
@Audit(config?)classApply Kysera audit plugin
@Policy(config?)classDeclare RLS policy for the repository
@Allow(rule)methodRLS rule that ALLOWS access
@Deny(rule)methodRLS rule that DENIES access
@Filter(filter?)methodRLS row-level filter
@BypassRLS()methodSkip RLS for an admin-only operation
@AutoTransactional(opts?)methodRun the method in a transaction; commit on success

titan-discovery

Official@omnitron-dev/titan-discovery

Maintained by the Omnitron team. Independent npm package.

titan-discovery does not export decorators — it integrates transparently with Netron via the module's enableNetronIntegration option. Service announce / lookup is automatic.

titan-events

Official@omnitron-dev/titan-events

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@OnEvent(event, opts?)methodSubscribe to a named event
@OnceEvent(event, opts?)methodSubscribe once, then unsubscribe
@OnAnyEvent(opts?)methodSubscribe to every event (firehose — use with care)
@OnModuleEvent(module, event, opts?)methodSubscribe across module boundaries
@EmitEvent(event, opts?)methodAuto-emit the event after a successful return
@ScheduleEvent(event, opts?)methodEmit on a schedule (cron-like, via this module's scheduler)
@BatchEvents(event, opts?)methodBatch handler — invoked once per batch
@EventEmitter(opts?)classMarks the class as a typed event source

titan-health

Official@omnitron-dev/titan-health

Maintained by the Omnitron team. Independent npm package.

titan-health doesn't export decorators — indicators are registered as classes via forFeature([...]).

titan-lock

Official@omnitron-dev/titan-lock

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@WithDistributedLock(key, ttlMs?)methodAcquire a distributed Redis lock around the call
@Lock(key, ttlMs?)methodAlias of @WithDistributedLock

The decorator releases the lock in finally — even on throw.

titan-metrics

Official@omnitron-dev/titan-metrics

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@Metrics({ counter?, histogram?, ... })methodAuto-instrument the method with the listed metrics

titan-notifications

Official@omnitron-dev/titan-notifications

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@OnNotification(pattern, opts?)methodWorker-side handler for notifications matching a pattern

titan-pm

Official@omnitron-dev/titan-pm

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@Process(opts?)classMarks the class as a spawnable worker process
@Public(opts?)method/propertyExpose method to the process supervisor / IPC
@RateLimit(opts)methodWorker-runtime rate limiter (pm-internal)
@Cache(opts?)methodWorker-runtime cache (pm-internal)
@Validate(opts)methodWorker-runtime validation (pm-internal)
@Trace()methodAdd tracing span around method
@Metric(name?)methodEmit a metric per call
@Supervisor(opts?)classClass describing a supervised hierarchy
@Child(opts?)propertyDeclare a child within a supervisor
@Workflow()classWorkflow orchestration class
@Stage(opts?)methodA stage within a workflow
@Compensate(stageName)methodCompensating action if a stage fails
@Actor(opts?)classActor-style stateful entity
@CircuitBreaker(opts)methodCircuit-breaker around external calls
@SelfHeal(action)methodAuto-remediation action on failure
@Idempotent({ key, ttl? })methodIdempotency key-based deduplication

titan-pm re-exports several decorator names (@Public, @RateLimit, @Cache, @Validate) for its worker runtime. They operate within the worker process, not on the supervisor's Netron surface. Don't confuse them with the same-named decorators in @omnitron-dev/titan / titan-ratelimit / titan-cache.

titan-ratelimit

Official@omnitron-dev/titan-ratelimit

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@RateLimit(opts?)methodApply rate limit to the method (uses key derived from opts)
@Throttle(rps)methodConvenience for "N requests per second"

titan-redis

Official@omnitron-dev/titan-redis

Maintained by the Omnitron team. Independent npm package.

titan-redis exports no decorators — inject the Redis client via REDIS_TOKEN or getRedisClientToken(name). See titan-redis.

titan-scheduler

Official@omnitron-dev/titan-scheduler

Maintained by the Omnitron team. Independent npm package.

DecoratorTargetsEffect
@Cron(expression, opts?)methodRun on a cron schedule
@Interval(ms, opts?)methodRun every ms milliseconds
@Timeout(ms, opts?)methodRun once after ms milliseconds
@Schedulable()classMarks the class for scheduler discovery (when not auto-found)

titan-scheduler.@Timeout schedules a one-shot deferred call. Core @Timeout aborts a method if it doesn't return in time. Different decorators with the same name — distinguish by import.

titan-telemetry-relay

Official@omnitron-dev/titan-telemetry-relay

Maintained by the Omnitron team. Independent npm package.

No decorators — instantiate TelemetryRelayService and wire it in directly.

Name collisions — which one to import

When the same decorator name lives in multiple packages, import path resolves the ambiguity. Quick table:

NameAvailable inDefault expectation
@Public@omnitron-dev/titan (expose) + titan-auth (auth bypass) + titan-pm (worker IPC)Pick by purpose; compose if needed
@Validate@omnitron-dev/titan + titan-pmCore for Netron methods; pm for workers
@Timeout@omnitron-dev/titan (abort) + titan-scheduler (one-shot)Read the verb — abort vs defer
@RateLimittitan-ratelimit + titan-pmUse ratelimit for service methods
@Cachetitan-pm (worker)Compare with @Cacheable from titan-cache

When in doubt, the import path is authoritative.

Composability rules

Decorators apply outside-in — outermost runs last. The framework order normally arranges:

@Public() // Netron exposure (outermost)
@RequireAuth() // auth check
@RateLimit({ ... }) // rate limit
@Validate({ input }) // input validation
@Metrics({ counter, hist })// instrumentation
@WithDistributedLock(key) // lock
async create(input) {/*…*/}

The runtime order at call-time:

  • enter Public → enter auth → enter rate limit → enter validate → enter metrics → enter lock → method body → exit lock → exit metrics → exit validate → exit rate limit → exit auth → exit Public

This is the only order that makes sense:

  • Exposure outside auth (auth runs after the request enters the surface).
  • Rate limit before validate (cheaper to reject early).
  • Metrics around the lock (so you measure lock contention).

Anti-patterns

  • @Cacheable on a non-idempotent method. Cache returns the same value forever; the side-effect runs once. Use @CachePut or @CacheInvalidate if you have side-effects.
  • @RateLimit without a per-caller key. All callers share one bucket. Include the user / IP / api-key in the key template.
  • @WithDistributedLock without a TTL. A crashed holder pins the lock forever. Always set a TTL ≥ the longest credible work time.
  • @OnEvent handler that throws. Throws don't propagate through the bus by default; the bus may log and continue. Wrap in try/catch if you need to ensure recovery.
  • Two @Public() decorators on the same method. Each from a different package — they don't conflict, but the duplication is noise. Pick one (the one you import explicitly) or import a re-export alias.

See also