Getting started
A model defines an entity schema that will be handled by Pinia ORM. You can visualize a model as a table definition in a database. You can use models wherever your application needs to manage a collection of entities, whether they actually correspond to a database or not. Models encapsulate most of the functionality that you'll need to work with your data.
Defining A Model
You can create a model by defining a new class that extends the Pinia ORM base Model
. All models require two static properties, an entity
and fields
property.
The following example sets up a new model that can be used to manage users:
import { Model } from 'pinia-orm'
class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.attr(null),
name: this.attr('John Doe')
}
}
}
Entity
entity
is a property that identifies a model, similar to the name of a database table. Each model's entity
name must be unique!
All models will create a Pinia module by their entity property and are found in state.entities
. In our example above, we will have created state.entities.users
. The default namespace entities
can be configured during installation.
Fields
fields
is a required property method that returns an object of field attributes to the model's schema. It maps data to their respective fields. It should return an object of key-value pairs consisting of the field name , and attribute definitions.
Field Attributes
Pinia ORM supports the most common Javascript datatypes including primitives, object literals, and arrays. These datatypes are defined using various field attributes. The most common type of attribute you'll come across is the generic attribute type.
Attributes take a single argument โ the fields default value. This default value is used in the event the field is missing when inserting data.
Generic Type
Generic attributes can be defined using this.attr(...)
. This type of attribute, unlike other attributes, will take any datatype as its default value, including String
, Number
, Boolean
, Object
and Array
.
The following example defines id
and name
fields on a user model using the generic attribute type:
class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.attr(null),
name: this.attr('John Doe'),
address: this.attr(() => 'street')
}
}
}
string
Type
string
you will get a console warningString attributes can be defined using this.string(...)
. The default value can be any string, including an empty string or a closure.
The following example defines the name
field on a user model using the string attribute:
class User extends Model {
static entity = 'users'
static fields () {
return {
...
name: this.string('')
}
}
}
This attribute will ensure a given value is cast as a string. For example, if name
receives a value of false
or null
, it will become 'false'
or 'null'
.
This attribute has null
as a default value. However, if you want to get warning if a value should not be nullable you can set notNullable()
.
{
...
name: this.string(null).notNullable()
}
number
Type
number
you will get a console warningNumber attributes can be defined using this.number(...)
. The default value can be any integer or a closure.
The following example defines the id
field on a user model using the number attribute:
class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.number(0)
...
}
}
}
This attribute will ensure a given value is cast as a number. For example, if id
receives a value of false
, it will become 0
, null
will become 0
, '123'
will become 123
, and so on.
This attribute has null
as a default value. However, if you want to get warning if a value should not be nullable you can set notNullable()
.
{
...
name: this.number(null).notNullable()
}
boolean
Type
boolean
you will get a console warningBoolean attributes can be defined using this.boolean(...)
. The default value can be either true
or false
or a closure.
The following example defines the active
field on a user model using the boolean attribute:
class User extends Model {
static entity = 'users'
static fields () {
return {
...
active: this.boolean(false)
}
}
}
This attribute will ensure a given value is cast as a boolean. Any truthy or falsy value will be cast accordingly. For example, if active
receives a value of 0
or null
, it will become false
. Likewise, if it receives a value of 1
or 'yes'
(non-empty string) it will become true
.
This attribute has null
as a default value. However, if you want to get warning if a value should not be nullable you can set notNullable()
.
{
...
active: this.boolean(null).notNullable()
}
Special Attributes
uid
Type
UID attribute is the special attribute that works similarly to "Autoincrement" column type in RDB. When you try to save a record without the value set to the UID field, it will generate a unique ID automatically.
class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.uid(),
name: this.string('')
}
}
}
This attribute will generate a unique string value using simple version of nanoid/non-secure package.
You can configure generated value by supplying custom alphabet and/or desired size:
this.uid({ alphabet: '0123456789abcdef', size: 7 })
Since version 'v1.0.0-rc-6' you can also use uuid libraries. By your own or the implemented ones. There are ready to use decorators and casts.
nanoid
nanoid
installed:yarn add nanoid
For more details look at nanoid. Standard methods
import { UidCast } from 'pinia-orm/nanoid'
// import { UidCast } from 'pinia-orm/nanoid/non-secure'
// import { UidCast } from 'pinia-orm/nanoid/async'
class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.uid(),
name: this.string('')
}
}
static casts () {
return {
id: UidCast
}
}
}
with decorator:
import { Uid } from 'pinia-orm/nanoid'
// import { Uid } from 'pinia-orm/nanoid/non-secure'
// import { Uid } from 'pinia-orm/nanoid/async'
class User extends Model {
static entity = 'users'
@Uid() declare id: string
}
Custom alphabets and sizes are also supported in both syntaxes.
uuid
uuid
installed:yarn add uuid
For more details look at uuid. Standard methods
import { UidCast } from 'pinia-orm/uuid/v1'
// import { UidCast } from 'pinia-orm/uuid/v4'
class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.attr(),
name: this.string('')
}
}
static casts () {
return {
id: UidCast
}
}
}
with decorator:
import { Uid } from 'pinia-orm/uuid/v1'
// import { Uid } from 'pinia-orm/uuid/v4'
class User extends Model {
static entity = 'users'
@Uid() declare id: string
}
const user = useRepo(User).make()
user.id // <- '2c5ea4c0-4067-11e9-8bad-9b1deb4d3b7d'
Defining Relations
You can define a relationship between different models using relation attributes such as this.hasMany
, this.belongsTo
, etc. To learn more about these, please take a look at Relationships page.
Primary Key
All models must have a primary key field. The primary key serves as an index key that Pinia ORM will use to persist entities to the store by its value.
By default, Pinia ORM will look for a primary key field called id
.
class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.attr(null)
...
}
}
}
Custom Primary Key
The primary key can be mapped to any field that will have a unique value by defining the static primaryKey
property on a model.
The following example configures a user model to identify the field myId
as the primary key:
class User extends Model {
static entity = 'users'
static primaryKey = 'myId'
static fields () {
return {
myId: this.attr(null)
...
}
}
}
Missing Primary Key
If a model is missing a primary key field definition, Pinia ORM will generate a primary key field automatically during database registration. The generated field will be configured using the uid
attribute type and named id
unless the static primaryKey
property is defined on a model.
The following example sets up a user model without an id
primary key field:
class User extends Model {
static entity = 'users'
static fields () {
return {
name: this.attr('')
}
}
}
Pinia ORM will recognize the model is missing an id
field and will generate one in its absence. The model will now be configured as follows:
class User extends Model {
static entity = 'users'
static fields () {
return {
id: this.uid(), // The auto-generated primary key field.
name: this.attr('')
}
}
}
The same principle applies to a model with a custom primary key definition. Pinia ORM will generate a primary key field using the name defined as the static primaryKey
property.
The following example sets up a user model configured with a primaryKey
property but without a corresponding primary key field:
class User extends Model {
static entity = 'users'
static primaryKey = 'myId'
static fields () {
return {
name: this.attr('')
}
}
}
Pinia ORM will recognize a custom primaryKey
has been defined but is unable to locate the corresponding field definition, and will generate one in its absence. The model will now be configured as follows:
class User extends Model {
static entity = 'users'
static primaryKey = 'myId'
static fields () {
return {
myId: this.uid(), // The auto-generated custom primary key field.
name: this.attr('')
}
}
}
Hide fields
By property
In Pinia ORM you have to hide fields when you retrieve data from the store. You can define for each model separate fields
with hidden
or visible
.
class User extends Model {
static entity = 'users'
// only return fields "name" and "phone" for this model by default
static hidden = ['secret']
// or use visible
static visible = ['name', 'phone']
static fields () {
return {
id: this.uid(),
name: this.string(''),
phone: this.number(0),
secret: this.string('')
}
}
}
By function
Once you have defined hidden fields in your model you still have the option to define fields hidden or visible
at runtime. For that you can usee makeVisible
or makeHidden
.
import { useRepo } from 'pinia-orm'
import User from './models/User'
const userRepo = useRepo(User)
// Returns User with hidden field 'secret'
userRepo.makeVisible(['secret']).first()
// Returns User with 'name' not returned
userRepo.makeHidden(['name']).first()
By global config
You also have the option to define default hidden visible fields in you ORM setup
const app = createApp({})
const pinia = createPinia()
pinia.use(createORM({
model: {
visible: ['*'],
hidden: []
}
}))
app.use(pinia)
setActivePinia(pinia)
Meta Info
In Pinia ORM you have that options that each model saves metadata. This metadata contains following properties:
createdAt
updatedAt
If you have enabled them either through global configuration createORM({ model: { withMeta:true } })
for all models or by
the model property static withMeta = true
for a single one, than metadata will be saved under the _meta
prop.
This property is by default hidden!
So you can either unhide by default with createORM({ model: { hidden: [] } })
or in the model.
Or you access it through withMeta()
at runtime