Model field

This article introduces model scalar field. Head to model relation or model property if you are finding these concepts.

A model scalar field represents a database table column, an API input, an API output or some of those above.

A virtual field doesn't have a corresponding table column but it's useful for providing additional information in API. A field marked with @readonly is not accessible from the API input. Similarly, A field marked with @writeonly is not accessible from the API output.

Declare a model scalar field

Model scalar fields are declared within model blocks. Let's see some examples of fields.

model User {
  @id @readonly @map("_id") @auto
  id: ObjectId
}

This field represents a typical MongoDB primary field.

model User {
  @unique @onSet($isEmail)
  email: String
}

This field is a typical email field. It is unique. When setting a new value, $isEmail pipeline item is checked.

Field type

A field has a field type. These field types are mapped to programming data types and database types. The currently supported field types are:

  • Bool
  • String
  • Int
  • Int64
  • Float
  • Float32
  • Date
  • DateTime
  • Decimal (only available in SQL databases)
  • Array (only available in PostgreSQL and MongoDB)
  • ObjectId (only available in MongoDB)
  • Enum
enum Sex {
  male
  female
}
 
model Item {
  @id
  id: Int
  int32: Int
  int64: Int64
  float64: Float
  float32: Float32?
  date: Date?
  dateTime: DateTime?
  decimal: Decimal?
  sex: Sex // this field is an enum
  stringArray: String[] // this field is an array of strings
}

Field optionality

In the preceding code snippet, you've already seen the ? punctuation. A field which type is marked with ? is optional. But we have more. Teo has conditional optionality. These are optional in the database level. But they are validated with logics on API level. The supported optionalities are:

  • presentWith field is required if some other field is present
  • presentWithout field is required if some other field is not present
  • presentIf field is required if some condition satisfies

presentWith means if some other fields are present, this field is required. presentWithout means if some other fields are not present, this field is required. Custom checkers can be provided with presentIf. Teo validates this on its own when an object is created or updated.

model User {
  @id
  id: Int
  // If phone number is not present, email should be present
  @presentWithout(.phoneNo)
  email: String?
  // If email is not present, phone number should be present
  @presentWithout(.email)
  phoneNo: String?
  // If phone number is present, calling code should be present
  @presentIf($self.get(.phoneNo).presents)
  callingCode: String?
}

Field accessibility

Field accessibility is an important concept in Teo. This protects data from being exposed when not desired. Supported accessibilities are:

  • readonly prevents value from being passed in from input
  • writeonly prevents value from being seen by frontend users
  • readwrite the default accessibility
  • internal is equivalent to readonly and writeonly
  • writeOnCreate prevents value from being passed in on updation
  • writeNonNull prevents value from being passed in on updation if value passed in is null
  • writeOnce prevents value from being passed in if current value is not null
  • readIf value can be read when condition is true
  • writeIf value can be written when condition is true

By default, all fields have readwrite accessibility. readonly is those you cannot pass from the frontend, such as object ids. writeonly is those you don't want frontend users to see, e.g. user's passwords. internal is those you want to hide entirely from the user, e.g. auth codes. readIf and writeIf are only accessible if some condition satisfies.

model User {
  @id
  id: Int
  // password is writeonly
  @writeonly
  password: String
  // sex is writeOnce
  @writeOnce
  sex: Sex?
}

Default value

A field can have a default value. Use the @default decorator on a field to specify whether a constant value or a calculated value through pipeline CONCEPT.

model Post {
  @id
  id: Int
  @default("Untitled")
  title: String
}

Field database type

Each field type has different default database type for different databases. You can specify a designated database type for a field explicitly.

model Post {
  @id
  id: Int
  @db(.text)
  title: String
}

For a complete list of supported database types, view:

Virtual field

Use the @virtual decorator to define a virtual field. Virtual field won't save its value to the database. is designed to complete API requirements. Values of these fields can be used for validation and transformation.

model User {
  @id
  id: Int
  @writeonly
  password: String
  @writeonly
  oldPassword: String?
}