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
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 field should be hidden when executing the
toJSON()
method of the model:
@Column({ isHidden: true })
public password: string
To force return hidden fields in toJSON()
calls,
use the withHidden
option:
const flight = await Flight.find()
const flightJson = flight.toJSON({ withHidden: true })
isUnique
Default:
false
Set if the column needs to have a unique value in database:
@Column({ isUnique: true })
public email: string
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
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 '#src/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>
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>
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.gid
).
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.gflightId
).
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 '#src/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[]>
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[]>
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.gid
).
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.gflightId
).
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 '#src/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>
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>
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.gid
).
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.guserId
).
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 '#src/models/Role'
import type { Relation } from '@athenna/database'
import { RolesUsers } from '#src/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[]>
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[]>
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.gid
).
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.guserId
). 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.gid
).
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.groleId
). 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[]>