Skip to main content

ORM: Annotations

Check all available ORM annotations and it options.

@Column()

The @Column() annotation marks a model property as a database column:

import { Column, BaseModel } from '@athenna/database'

export class Flight extends BaseModel {
@Column()
public id: number

@Column()
public from: string

@Column()
public to: string

@Column({ isCreateDate: true })
public createdAt: Date

@Column({ isUpdateDate: true })
public updatedAt: Date
}

You can also define any of the following optional properties:

name

Default: the name of your class property (e.g name).

Map which will be the name of your column in database:

@Column({ name: 'my_name' })
public name: string

The default value of this property will be the name of your class property as camelCase.

type

Default: the type of your class property (e.g String).

Map the type of your column. This property is usefull only to synchronize your model with database:

@Column({ type: Number })
public id: string

By default the type of your model will be set as the type of your class property, in the example above, if we remove the type property, it would automatically be set as String.

length

Default: undefined

Map the column length in database. This property is usefull only when synchronizing your model with database:

@Column({ length: 10 })
public name: string

defaultTo

Default: null

This property doesn't change the behavior in your database, they are used only when the class property is undefined or null before running your model create(), createMany(), update() and createOrUpdate() methods:

@Column({ defaultTo: null })
public deletedAt: Date
warning

The value set to defaulTo property will only be used when the value for the specified column was not provided when calling the above methods and also when it was not set in static attributes() method of your model.

isPrimary

Default: false

Set if the column is a primary key:

@Column({ isPrimary: true })
public id: number

isHidden

Default: false

Set if the column should be hidden when retrieving it from database:

@Column({ isHidden: true })
public password: string

isUnique

Default: false

Set if the column needs to have a unique value in database:

@Column({ isUnique: true })
public email: string
note

If you try to create duplicated values Athenna will throw an exception until it gets in your database. This means that you migration could have or not the unique index defined

isNullable

Default: true

Set if the column is nullable or not:

@Column({ isNullable: false })
public name: string
note

Just like isUnique property, if isNullable is set to false and you try to create a model with null or undefined name, it will throw an exception.

isIndex

Default: false

Set if the column is an index:

@Column({ isIndex: true })
public email: string

isSparse

Default: false

Set if the column is an index sparse:

@Column({ isSparse: true })
public email: string

persist

Default: false

Set if the column should be persist in database or not. If set as false, Athenna will remove this column from operations like create or update, but it will still me available in listing operations:

@Column({ persist: false })
public name: string

isCreateDate

Default: false

Set if the column is a createdAt column. If this option is true, Athenna will automatically set a new Date() value in the column when creating it:

@Column({ isCreateDate: true })
public createdAt: Date

isUpdateDate

Default: false

Set if the column is an updatedAt column. If this option is true, Athenna will automatically set a new Date() value in the column when creating it:

@Column({ isUpdateDate: true })
public updatedAt: Date

isDeleteDate

Default: false

Set if the column is a deletedAt column and also if the model is using soft delete approach. If this option is true, Athenna will automatically set a new Date() value in the column when deleting it:

@Column({ isDeleteDate: true })
public deletedAt: Date

@HasOne()

The @HasOne() annotation marks a model property as an one-to-one relation:

import { Pilot } from '#app/models/Pilot'
import type { Relation } from '@athenna/database'
import { Column, HasOne, BaseModel } from '@athenna/database'

export class Flight extends BaseModel {
@Column()
public id: number

@HasOne(() => Pilot)
public pilot: Relation<Pilot>
}

The second argument is an object that accepts any of the following options:

isIncluded

Default: false

Set if the relation will be included when fetching data from the parent model:

@HasOne(() => Pilot, { isIncluded: true })
public pilot: Relation<Pilot>
tip

This option is used by methods like with() to eager load your relation in the parent model:

const flight = await Flight.query()
.with('pilot') // 👈 Set isIncluded to true in query schema.
.find()

This means that if you set this property to true, it will by default load your relation every time.

closure

Default: undefined

Set a closure that should be called when isIncluded is true, adding to possibility to call methods from the query builder of the relationship:

@HasOne(() => Pilot, { 
isIncluded: true,
closure: (query) => query.select('id')
})
public pilot: Relation<Pilot>
tip

Just like isIncluded property this option is used by methods like with() when eager loading your relation in your parent model:

const flight = await Flight.query()
// Set isIncluded to true and add a select
// statement to the relationship query builder.
.with('pilot', (query) => query.select('id'))
.find()

This means that if you set this property, it will by default be called when loading your relation without the need to set a second argument to the with() method.

primaryKey

Default: the isMainPrimary of the parent model (e.g id).

Define the primary key of the relationship:

@HasOne(() => Pilot, { primaryKey: 'myId' })
public pilot: Relation<Pilot>

foreignKey

Default: the parent model name in camel case with an Id at the end (e.g flightId).

Define the foreign key of the relationship:

@HasOne(() => Pilot, { foreignKey: 'myFlightId' })
public pilot: Relation<Pilot>

@HasMany()

The @HasMany() annotation marks a model property as an one-to-many relation:

import { Comment } from '#app/models/Comment'
import type { Relation } from '@athenna/database'
import { Column, HasOne, BaseModel } from '@athenna/database'

export class Post extends BaseModel {
@Column()
public id: number

@HasMany(() => Comment)
public comments: Relation<Comment[]>
}

The second argument is an object that accepts any of the following options:

isIncluded

Default: false

Set if the relation will be included when fetching data from the parent model:

@HasMany(() => Comment, { isIncluded: true })
public comments: Relation<Comment[]>
tip

This option is used by methods like with() to eager load your relation in the parent model:

const post = await Post.query()
.with('comments') // 👈 Set isIncluded to true in query schema.
.find()

This means that if you set this property to true, it will by default load your relation every time.

closure

Default: undefined

Set a closure that should be called when isIncluded is true, adding to possibility to call methods from the query builder of the relationship:

@HasMany(() => Comment, { 
isIncluded: true,
closure: (query) => query.select('id')
})
public comments: Relation<Comment[]>
tip

Just like isIncluded property this option is used by methods like with() when eager loading your relation in your parent model:

const post = await Post.query()
// Set isIncluded to true and add a select
// statement to the relationship query builder.
.with('comments', (query) => query.select('id'))
.find()

This means that if you set this property, it will by default be called when loading your relation without the need to set a second argument to the with() method.

primaryKey

Default: the isMainPrimary of the parent model (e.g id).

Define the primary key of the relationship:

@HasMany(() => Comment, { primaryKey: 'myId' })
public comments: Relation<Comment>

foreignKey

Default: the parent model name in camel case with an Id at the end (e.g flightId).

Define the foreign key of the relationship:

@HasMany(() => Comment, { foreignKey: 'myPostId' })
public comments: Relation<Comment[]>

@BelongsTo()

The @BelongsTo() annotation marks a model property as the inverse side of an one-to-one relation and the inverse side of an one-to-many relation (many-to-one):

import { User } from '#app/models/User'
import type { Relation } from '@athenna/database'
import { Column, BelongsTo, BaseModel } from '@athenna/database'

export class Phone extends BaseModel {
@Column()
public id: number

@Column()
public userId: number

@BelongsTo(() => User)
public user: Relation<User>
}

The second argument is an object that accepts any of the following options:

isIncluded

Default: false

Set if the relation will be included when fetching data from the parent model:

@BelongsTo(() => User, { isIncluded: true })
public user: Relation<User>
tip

This option is used by methods like with() to eager load your relation in the parent model:

const phone = await Phone.query()
.with('user') // 👈 Set isIncluded to true in query schema.
.find()

This means that if you set this property to true, it will by default load your relation every time.

closure

Default: undefined

Set a closure that should be called when isIncluded is true, adding to possibility to call methods from the query builder of the relationship:

@BelongsTo(() => User, { 
isIncluded: true,
closure: (query) => query.select('id')
})
public user: Relation<User>
tip

Just like isIncluded property this option is used by methods like with() when eager loading your relation in your parent model:

const phone = await Phone.query()
// Set isIncluded to true and add a select
// statement to the relationship query builder.
.with('user', (query) => query.select('id'))
.find()

This means that if you set this property, it will by default be called when loading your relation without the need to set a second argument to the with() method.

primaryKey

Default: the isMainPrimary of the parent model (e.g id).

Define the primary key of the relationship:

@BelongsTo(() => User, { primaryKey: 'myId' })
public user: Relation<User>

foreignKey

Default: the relation model name in camel case with an Id at the end (e.g userId).

Define the foreign key of the relationship:

@BelongsTo(() => User, { foreignKey: 'myUserId' })
public user: Relation<User>

@BelongsToMany()

The @BelongsToMany() annotation marks a model property as a many-to-many relation:

import { Role } from '#app/models/Role'
import type { Relation } from '@athenna/database'
import { RolesUsers } from '#app/models/RolesUsers'
import { Column, BaseModel, BelongsToMany } from '@athenna/database'

export class User extends BaseModel {
@Column()
public id: number

@BelongsToMany(() => Role, () => RolesUsers)
public roles: Relation<Role[]>
}

The third argument is an object that accepts any of the following options:

isIncluded

Default: false

Set if the relation will be included when fetching data from the parent model:

@BelongsToMany(() => Role, () => RolesUsers, { 
isIncluded: true
})
public roles: Relation<Role[]>
tip

This option is used by methods like with() to eager load your relation in the parent model:

const user = await User.query()
.with('roles') // 👈 Set isIncluded to true in query schema.
.find()

This means that if you set this property to true, it will by default load your relation every time.

closure

Default: undefined

Set a closure that should be called when isIncluded is true, adding to possibility to call methods from the query builder of the relationship:

@BelongsToMany(() => Role, () => RolesUsers, { 
isIncluded: true,
closure: (query) => query.select('id')
})
public roles: Relation<Roles[]>
tip

Just like isIncluded property this option is used by methods like with() when eager loading your relation in your parent model:

const user = await User.query()
// Set isIncluded to true and add a select
// statement to the relationship query builder.
.with('roles', (query) => query.select('id'))
.find()

This means that if you set this property, it will by default be called when loading your relation without the need to set a second argument to the with() method.

pivotTable

Default: Athenna will call the table() method of the pivot model. (e.g RolesUsers.table() -> roles_users)

Define the pivot table of the relationship:

@BelongsToMany(() => Role, () => RolesUsers, { 
pivotTable: 'roles_users'
})
public roles: Relation<Role>

primaryKey

Default: the isMainPrimary of the parent model (e.g id).

Define the primary key of the relationship:

@BelongsToMany(() => Role, () => RolesUsers, { 
primaryKey: 'myId'
})
public roles: Relation<Role>

foreignKey

Default: the parent model name in camel case with an Id at the end (e.g userId). This value needs to be defined in the pivot model (e.g RolesUsers).

Define the foreign key of the relationship:

@BelongsToMany(() => Role, () => RolesUsers, { 
foreignKey: 'myUserId'
})
public roles: Relation<Role[]>

relationPrimaryKey

Default: the isMainPrimary of the relation model (e.g id).

Define the relation primary key of the relationship:

@BelongsToMany(() => Role, () => RolesUsers, { 
relationPrimaryKey: 'myId'
})
public roles: Relation<Role>

relationForeignKey

Default: the relation model name in camel case with an Id at the end (e.g roleId). This value needs to be defined in the pivot model (e.g RolesUsers).

Define the relation foreign key of the relationship:

@BelongsToMany(() => Role, () => RolesUsers, { 
relationForeignKey: 'myRoleId'
})
public roles: Relation<Role[]>