Decorators

Data & Database Decorators

Define TypeScript database operations, transactions, isolation levels, consistency models, read-only constraints, ORM entity mappings, relationships, and multi-tenant data isolation with AxilJS.

7 min readDocumentationEdit this page

Data & Database Decorators

AxilJS data decorators describe how application code interacts with persistent storage. They express database operations, transaction boundaries, consistency requirements, entity mappings, and tenant isolation as semantic metadata.

The decorators describe intent; database and ORM consumers interpret that metadata to implement the required behavior without coupling application code to a specific database driver.

@tDatabase

Declares the database operation semantics for a method.

typescript
import { tDatabase } from '@axiljs/decorator'
 
@tDatabase({ operation: 'read' })
async getUser(id: string) {}
 
@tDatabase({ operation: 'write', replica: 'primary' })
async updateUser(id: string, data: UpdateDto) {}

Options

OptionTypeDescription
operation'read' | 'write' | 'readwrite'Operation type
replica'primary' | 'replica' | 'auto'Connection pool routing
timeoutnumberQuery timeout in milliseconds

@tDatabase makes the intended database access pattern explicit. A runtime or ORM consumer can use this metadata to select an appropriate connection pool and enforce operation constraints.

@tTransaction

Defines a database transaction boundary around a method.

typescript
import { tTransaction } from '@axiljs/decorator'
 
@tTransaction()
async transferFunds(from: string, to: string, amount: number) {}

Transaction configuration can include isolation, timeout, and propagation behavior:

typescript
@tTransaction({
  isolation: 'serializable',
  timeout: 5000,
})
async processPayment(orderId: string) {}

Options

OptionTypeDescription
isolation'read-uncommitted' | 'read-committed' | 'repeatable-read' | 'serializable'Transaction isolation level
timeoutnumberTransaction timeout in milliseconds
propagation'required' | 'requires-new' | 'nested' | 'never'Transaction propagation behavior

The transaction decorator expresses the boundary and requirements. The underlying transaction manager is responsible for implementing the actual database transaction.

@tIsolation

Declares a minimum transaction isolation requirement.

Use @tIsolation when the isolation requirement needs to be expressed independently from the transaction boundary.

typescript
import { tIsolation } from '@axiljs/decorator'
 
@tIsolation('serializable')
async getBalance(accountId: string) {}

This allows infrastructure consumers to reason about isolation requirements separately from transaction configuration.

@tConsistent

Declares the consistency guarantee required by an operation.

This is particularly useful in distributed systems where data may be replicated across multiple database nodes or read replicas.

typescript
import { tConsistent } from '@axiljs/decorator'
 
@tConsistent('strong')
async getBalance() {}
 
@tConsistent('eventual')
async getRecommendations() {}

Consistency Values

ValueDescription
'strong'Requires strong, read-your-writes consistency
'eventual'Allows stale reads in exchange for lower latency
'snapshot'Uses a point-in-time snapshot
'bounded'Allows bounded staleness

The semantic requirement can be consumed by database routing or distributed data infrastructure to determine an appropriate read source.

@tReadOnly

Declares that a method must not perform write operations.

typescript
import { tReadOnly } from '@axiljs/decorator'
 
@tReadOnly()
async generateReport() {}

An ORM or database consumer can use this metadata to reject write queries executed within the operation.

This is useful for reporting, analytics, query services, and other operations where mutation should be explicitly prohibited.

@tTenantIsolated

Declares that database access must be scoped to the current tenant.

typescript
import { tTenantIsolated } from '@axiljs/decorator'
 
@tTenantIsolated()
async findAll() {
  return this.orderRepo.findAll()
}

A tenant-aware database consumer can apply the current tenant boundary to generated queries:

sql
WHERE tenant_id = currentTenant

This makes tenant isolation an explicit data-access requirement rather than relying entirely on individual repository implementations.

@tTenantIsolated describes the isolation requirement. The database, ORM, or infrastructure consumer is responsible for enforcing it.

Entity Decorators

AxilJS also provides semantic decorators for describing database entities and their mappings.

@tEntity

Declares a class as a database entity.

typescript
import {
  tEntity,
  tPrimaryKey,
  tColumn,
} from '@axiljs/decorator'
 
@tEntity({ table: 'users' })
class User {
  @tPrimaryKey()
  id: number
 
  @tColumn({ type: 'varchar', length: 255 })
  name: string
 
  @tColumn({ unique: true })
  email: string
}

The entity metadata describes how the application model maps to persistent storage.

@tColumn

Maps a class property to a database column.

typescript
import { tColumn } from '@axiljs/decorator'
 
@tColumn({
  type: 'decimal',
  precision: 10,
  scale: 2,
})
price: number
 
@tColumn({ type: 'jsonb' })
metadata: Record<string, any>
 
@tColumn({ select: false })
password: string

Column metadata can describe storage types and constraints required by the database consumer.

@tPrimaryKey

Marks a property as the entity's primary key.

typescript
import { tPrimaryKey } from '@axiljs/decorator'
 
@tPrimaryKey()
id: number

The resulting metadata can be used by an ORM or schema-management consumer when generating queries and persistence mappings.

@tRelation

Declares a relationship between entities.

typescript
import { tRelation } from '@axiljs/decorator'
 
@tRelation({
  type: 'many-to-one',
  target: () => User,
})
author: User
 
@tRelation({
  type: 'one-to-many',
  target: () => Post,
  cascade: true,
})
posts: Post[]

Relation Types

TypeDescription
'one-to-one'A single related entity
'one-to-many'A collection of related entities
'many-to-one'Multiple entities reference one entity
'many-to-many'A collection with a many-to-many relationship

Relations remain semantic metadata, allowing the persistence layer to determine how relationships are represented and queried.

Full Entity Example

typescript
import {
  tEntity,
  tPrimaryKey,
  tColumn,
  tRelation,
} from '@axiljs/decorator'
 
@tEntity({ table: 'orders' })
class Order {
  @tPrimaryKey()
  id: number
 
  @tColumn({
    type: 'decimal',
    precision: 10,
    scale: 2,
  })
  total: number
 
  @tColumn({
    type: 'enum',
    default: 'pending',
  })
  status: string
 
  @tRelation({
    type: 'many-to-one',
    target: () => User,
  })
  customer: User
 
  @tRelation({
    type: 'one-to-many',
    target: () => OrderItem,
    cascade: true,
  })
  items: OrderItem[]
}

Entity decorators produce metadata that a persistence consumer can use for queries, migrations, and type-safe repositories. The same metadata can also be consumed by tooling such as database browsers, schema generators, and compliance systems.

Composing Data Semantics

Data decorators can be combined when an operation has multiple storage requirements.

typescript
import {
  tDatabase,
  tTransaction,
  tIsolation,
  tConsistent,
  tTenantIsolated,
} from '@axiljs/decorator'
 
@tDatabase({
  operation: 'write',
  replica: 'primary',
})
@tTransaction({
  isolation: 'serializable',
  timeout: 5000,
})
@tIsolation('serializable')
@tConsistent('strong')
@tTenantIsolated()
async transferFunds(
  fromAccount: string,
  toAccount: string,
  amount: number,
) {
  // Business logic
}

This separates the business operation from infrastructure implementation while making its data requirements explicit:

  • The operation performs a write.
  • The write is routed to the primary database.
  • A transaction boundary is required.
  • Serializable isolation is required.
  • Strong consistency is required.
  • Data access must remain tenant-isolated.

The consumer layer can interpret these semantics and translate them into the appropriate database, ORM, transaction, and routing behavior.

Data Decorator Reference

DecoratorPurpose
@tDatabaseDeclares database operation and routing semantics
@tTransactionDefines a transaction boundary
@tIsolationDeclares a minimum transaction isolation level
@tConsistentDeclares a required consistency guarantee
@tReadOnlyPrevents write operations within a method
@tTenantIsolatedEnforces tenant-scoped data access
@tEntityDeclares a database entity
@tColumnMaps a property to a database column
@tPrimaryKeyDeclares an entity primary key
@tRelationDeclares an entity relationship

Help improve the documentation

AxilJS is open source and documentation improvements are welcome.

AxilJS DocumentationMIT License · Built by SyntaxilitY