Definition
The schema includes all the configuration that the ORM needs.
The schema separates the definition of the business model (Domain) from the persistence of the data (Infrastructure).
In the domain, the entities and enumerators that represent the business model are completely clean, without any attributes that couple them to persistence.
All queries are made according to the business model, so all queries are decoupled from the physical model of the data.
In the infrastructure, all the necessary configuration is defined to be able to persist and obtain the data from the different sources.
The schema configuration can be done in a yaml, json file or passed as a parameter when initializing the ORM.
All the queries that are used for the definition of conditions and for the execution of actions are based on the expression engine 3xpr
Structure
domain:
enums:
- name: string
values:
- name: string
value: any
entities:
- name: string
abstract: boolean
extends: string[]
view: boolean
mapping: string
primaryKey: string[]
uniqueKey: string[]
properties:
- name: string
mapping: string
type: string | integer | decimal | boolean | dateTime | date | time
length: number
required: boolean
autoIncrement: boolean
view: boolean
key: string
default: expression
readExp: expression
readValue: expression
writeValue: expression
indexes:
- name: string
fields: string[]
relations:
- name: string
type: oneToMany | manyToOne | oneToOne
from: string
entity: string
to: string
composite: boolean
constraints:
- message: string
condition: expression
application:
start:
- name: string
condition: expression
expression: expression
end:
- name: string
condition: expression
expression: expression
errors:
- name: string
condition: expression
expression: expression
listeners:
- name: string
on: [select|insert|bulkInsert|update|delete]
condition: expression
before: expression
after: expression
error: expression
infrastructure:
mappings:
- name: string
entities:
- name: string
mapping: string
abstract: boolean
filter: expression
properties:
- name: string
mapping: string
readMappingExp: expression
sources:
- name: string
dialect: [MySQL|MariaDB|PostgreSQL|Oracle|SqlServer|MongoDB|SQLjs]
mapping: string
connection: object | EnvironmentVariable
stages:
- name: string
sources:
- name: string
condition: expression
views:
- name: string
entities:
- name: string
exclude: boolean
properties:
- name: string
exclude: boolean
readExp: expression
paths:
src: string
state: string
domain: string
Main Definition
Property | Description |
---|---|
domain | definition of the business model |
application | implementation of events and listeners |
infrastructure | concrete implementation of the data model |
Domain
Property | Description |
---|---|
enums | definitions of enum of model |
entities | definitions of entity of model |
- In the enums section, enumerations are defined that can then be used as the data type of a property.
- In the entities section, the entities are defined with their properties, relationships and constraints
Enum
They define an enumeration which can then be used as the data type of a property.
Property | Description | required |
---|---|---|
name | name of enum | yes |
values | values of enum | yes |
Enum Example
In this example, the DeviceType enum is defined, which is used in the type property of the Devices entity.
Example:
domain:
enums:
- name: DeviceType
values:
- name: phone
value: phone
- name: computer
value: computer
- name: robot
value: robot
entities:
...
- name: Devices
extends: Products
primaryKey: ["id"]
uniqueKey: ["name"]
properties:
- name: id
length: 32
required: true
default: 'concat(type,"-",switch(type){case"phone":imei;default:mac;})'
- name: type
length: 16
required: true
enum: DeviceType
- name: name
length: 32
required: true
...
Entity
The entity is defined with its properties, relationships and constraints
Property | Description | required | default |
---|---|---|---|
name | name of entity | yes | |
abstract | if the entity is abstract | ||
extends | extension | ||
view | if the entity is a view | ||
primaryKey | primary key | ||
uniqueKey | unique key | ||
properties | entity properties | yes | |
indexes | indexes | ||
relations | relations | ||
constraints | constraints |
Abstract and extends in Entity
In this example the abstract entity positions is defined which extends the entity Countries
Example:
domain:
entities:
- name: Positions
abstract: true
properties:
- name: latitude
length: 16
- name: longitude
length: 16
- name: Countries
extends: Positions
primaryKey: ["iso3"]
uniqueKey: ["name"]
properties:
- name: name
required: true
- name: iso3
length: 3
required: true
Set Entity as view
This example defines the Users entity as a view. \
Since this entity is managed by an external system and only select queries are allowed.
Example:
domain:
entities:
...
- name: Users
view: true
extends: Basics
primaryKey: ["username"]
uniqueKey: ["email"]
properties:
- name: username
length: 32
required: true
- name: firstname
required: true
- name: lastname
...
Property
Property | Description | required | default |
---|---|---|---|
name | name of property | yes | |
type | type of property | yes | string |
length | length of property type | 80 | |
required | if the field is required | false | |
autoIncrement | if the field is self-incrementing | false | |
view | if the field is a view | ||
default | expression default resolved on server | ||
readExp | read expression resolved in source | ||
readValue | read expression resolved on server | ||
writeValue | write expression resolved in server | ||
key | key to filter or insert |
Set Property as view and readExp
A property set to view is a property that will be returned in read queries. \ The value of this property is defined in readExp using the expression language.
Example:
domain:
entities:
...
- name: Users
view: true
extends: Basics
primaryKey: ["username"]
uniqueKey: ["email"]
properties:
- name: username
length: 32
required: true
- name: firstname
required: true
- name: lastname
required: true
- name: fullmane
view: true
readExp: concat(lastname,", ",firstname)
...
ReadExp can be used as a view, in this case the read expression will be applied at the time of reading. \ But no modification will be applied at the time of writing.
Default value in Property
When a record is inserted, the expression defined in default will be evaluated on the server. \ This expression will be executed by the expression engine 3xpr
Example:
domain:
entities:
- name: Groups
extends: Basics
primaryKey: ["id"]
uniqueKey: ["name"]
properties:
- name: id
length: 32
default: lower(substring(replace(name," ","-"),0,32))
required: true
- name: name
length: 32
required: true
Read and write value in Property
Both readValue and writeValue are executed on the server. When reading, readValue will be applied and in the writing actions, writeValue will be executed. These expressions will be executed by the expression engine 3xpr
Example:
domain:
entities:
...
- name: Users
view: true
extends: Basics
primaryKey: ["username"]
uniqueKey: ["email"]
properties:
- name: username
length: 32
required: true
- name: firstname
required: true
- name: lastname
required: true
- name: fullmane
view: true
readExp: concat(lastname,", ",firstname)
- name: email
required: true
length: 255
writeValue: encrypt(lower(email),"${USERS_SECRET_KEY}")
readValue: decrypt(email,"${USERS_SECRET_KEY}")
...
Key value in Property
The key defined in keyValue will be used as a filter in the read and update queries. \ When a record is inserted this key is assigned to the field. \
This behavior is useful when we want to define different entities on the same table or collection. \ Let's imagine we have a Locations table where Countries, States and Cities are stored. \ but we want to work with the entities separately.
Example:
domain:
entities:
- name: Locations
abstract: true
primaryKey: ["type","code"]
uniqueKey: ["type","name"]
properties:
- name: code
required: true
length: 16
- name: type
required: true
length: 16
- name: name
required: true
- name: Country
extends: Locations
properties:
- name: type
key: 'country'
- name: States
extends: Locations
properties:
- name: type
key: 'state'
- name: Cities
extends: Locations
properties:
- name: type
key: 'city'
infrastructure:
mappings:
- name: default
entities:
- name: Locations
abstract: true
mapping: TBL_LOCATIONS
properties:
- name: code
mapping: CODE
- name: type
mapping: TYPE
- name: name
mapping: NAME
- name: Country
extends: Locations
- name: States
extends: Locations
- name: Cities
extends: Locations
Relation
Property | Description | required | default |
---|---|---|---|
name | name of property | yes | |
type | type of relationship | oneToMany | |
from | relationship field | ||
entity | entity with which it relates | ||
to | field of the entity to which it relates | ||
composite | if the relationship is composite | false | |
target | Name of the relation in the related entity |
Target relation
When defining target the corresponding relationship will be created in the target entity. For example, if in the entity DeviceStatuses a relationship with Devices is created and in this relationship target = "statuses" is set. \ A relationship called statuses will be created in the entity Devices which will be manyToOne. \ Types of target relation according to the source relation:
source | target |
---|---|
oneToMany | manyToOne |
manyToOne | oneToMany |
oneToOne | oneToOne |
Example:
domain:
entities:
- name: DeviceStatuses
extends: Basics
primaryKey: ["id"]
indexes:
- name: time
fields: ["time"]
properties:
- name: id
type: integer
required: true
autoIncrement: true
- name: deviceId
length: 32
required: true
- name: time
type: dateTime
relations:
- name: device
from: deviceId
entity: Devices
to: id
target: statuses
Constraint
Property | Description | required |
---|---|---|
message | message to display | yes |
condition | boolean expression to evaluate | yes |
Constraints are validated on the server using expressions. These expressions will be executed by the expression engine 3xpr
All constraints are validated when inserting or updating a record. \ The ORM will create various constraints based on other definitions, for example:
- When you define a property as required, a constraint will be created that will validate that this property is not null.
- When defining that a property is of an Enum type, a constraint is created that validates that the value is within this enum.
It is also possible to add a constraint for which the message and the condition must be defined. \ The defined message will be sent if the condition is not met.
Example:
domain:
entities:
- name: Users
properties:
...
- name: email
required: true
length: 255
readExp: mask(email)
writeValue: encrypt(lower(email),"${USERS_SECRET_KEY}")
readValue: decrypt(email,"${USERS_SECRET_KEY}")
constraints:
- message: invalid email
condition: test(email,"^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$")
- name: Files
properties:
- name: id
length: 255
required: true
- name: type
length: 16
required: true
enum: FileType
- name: deviceId
length: 32
required: true
- name: startDate
type: dateTime
required: true
- name: endDate
type: dateTime
required: true
constraints:
- message: endDate cannot be less than startDate
condition: startDate<=endDate
Application
Property | Description |
---|---|
start | commands to execute when starting the application |
end | commands to execute when the application is terminated |
errors | commands to execute when an error occurs |
listeners | definition of the listeners and the action to be executed |
Infrastructure
Property | Description |
---|---|
mappings | definitions of mappings |
sources | definitions of source |
stages | definitions of stages |
views | definitions of views |
paths |
- In the mappings section, the mapping between the entities in the tables or collections in the databases is defined.
- In the sources section the databases are defined
- In the stages section different scenarios are defined in which the rules that associate an entity with a source are determined
- In the views section, different views are defined that can restrict or modify the results of the queries.
- In the paths section, the configuration of the routes where configuration files or execution results will be generated is established.
Mapping
The mapping between entities in tables or collections in databases is defined.
Property | Description | required | default |
---|---|---|---|
name | name of mapping | yes | |
entities | list of entity mapping | yes |
Entity Mapping
Property | Description | required | default |
---|---|---|---|
name | name of entity | yes | |
abstract | if the entity is abstract | ||
extends | extension | ||
mapping | table name in the database | yes | equal name |
filter | filter expression | ||
properties | list of property mapping |
Abstract and extends in Entity Mapping
Abstract mapping entities are useful for use in extensions. \ This example defines the abstract mapping entity Locations which extends concrete entities.
...
infrastructure:
mappings:
- name: default
entities:
- name: Locations
abstract: true
mapping: TBL_LOCATIONS
properties:
- name: code
mapping: CODE
- name: type
mapping: TYPE
- name: name
mapping: NAME
- name: Country
extends: Locations
- name: States
extends: Locations
- name: Cities
extends: Locations
...
Filter in Entity Mapping
The filter defined in a Mapping entity is used to filter the records. This example filters records from the user_entity table where users are from a certain realmId.
...
infrastructure:
mappings:
- name: default
- name: keycloak
entities:
- name: Users
mapping: user_entity
filter: realmId == "${REALM_ID}"
properties:
- name: username
mapping: username
- name: firstname
mapping: first_name
- name: lastname
mapping: last_name
- name: email
mapping: email
- name: created
mapping: created_timestamp
readMappingExp: millisecondToDate(created/1000)
- name: realmId
length: 255
mapping: realm_id
...
Property Mapping
Property | Description | required | default |
---|---|---|---|
name | name of property | yes | |
mapping | table name in the database | yes | equal name |
readMappingExp | read expression resolved in source |
Read expression in Property Mapping
The result of the expression defined in readMappingExp using the expression language, will be returned in the read queries.
infrastructure:
mappings:
- name: default
- name: keycloak
entities:
- name: Users
mapping: user_entity
filter: realmId == "${REALM_ID}"
properties:
...
- name: created
mapping: created_timestamp
readMappingExp: millisecondToDate(created/1000)
- name: realmId
length: 255
mapping: realm_id
...
Source
Databases are defined with their connection
Property | Description | required | default |
---|---|---|---|
name | name of source | yes | |
mapping | name of reference to mapping | first | |
dialect | dialect of data source | yes | |
connection | string connection | yes |
Set connection in Source
Although it is possible to define the connection both using environment variables and directly in the configuration. \ This second option is not recommended due to security and different configurations that may exist by environment. \ The ability to define the connection by configuration should only be used for a temporary local test.
Using environment variable:
...
infrastructure:
sources:
- name: test
dialect: MySQL
mapping: test
connection: ${CNN_MYSQL}
...
In configuration:
...
infrastructure:
sources:
- name: test
dialect: MySQL
mapping: test
connection:
host: localhost
port: 3306
user: test
password: test
database: test
...
Stage
The stage is defined in which the rules that relate an entity to a source are determined
Property | Description | required | default |
---|---|---|---|
name | name of stage | yes | |
sources | list of sources rules | yes |
Source Rule
Property | Description | required | default |
---|---|---|---|
name | name of source | yes | |
condition | boolean expression to evaluate | true |
Condition on Source Rule
En condition se define la regla para determinar en que source se aplicaran las consultas. Las variables de contexto son las siguientes:
Variable | Description | value |
---|---|---|
entity | query entity | name of entity |
action | query action | select, insert, bulkInsert, update, delete, ddl |
read | it is a read action | boolean |
write | it is a write action | boolean |
dml | it is a dml action | boolean |
ddl | it is a ddl action | boolean |
The conditions are validated on the server using expressions. \ These expressions will be executed by the expression engine 3xpr \ In the event that more than one condition is met, the source will be determined according to the order in which it was defined.
In the following example, all entities except Users will use the source main. \ And in the case of the entity Users it will use the source keycloak.
Example:
...
infrastructure:
stages:
- name: default
sources:
- name: main
condition: entity != "Users"
- name: keycloak
condition: entity == "Users"
View
The view that can restrict or modify the results of the queries is defined.
Property | Description | required |
---|---|---|
name | name that identifies a view | yes |
entities | entity view list |
Entities not included in the view will not be subject to any restrictions.
In the following example, the admin view can access all entities.
Example:
infrastructure:
views:
- name: default
entities:
- name: Devices
properties:
- name: apiKey
readExp: '"***"'
- name: Users
properties:
- name: created
readExp: date(created)
- name: email
exclude: true
- name: collector
entities:
- name: Users
exclude: true
- name: Groups
exclude: true
- name: GroupUsers
exclude: true
- name: admin
entities: []
Entity View
Property | Description | required |
---|---|---|
name | entity name | yes |
exclude | determines whether the entity is excluded | |
properties | property view list |
Exclude in Entity View
Entities set to exclude will not be accessible when using this view.
infrastructure:
views:
...
- name: collector
entities:
- name: Users
exclude: true
- name: Groups
exclude: true
- name: GroupUsers
exclude: true
...
Property View
Property | Description | required |
---|---|---|
name | property name | yes |
exclude | determines whether the property is excluded | |
readExp | read expression resolved in source |
Exclude in Property View
Properties set to exclude will not be accessible when using this view.
infrastructure:
views:
- name: default
entities:
...
- name: Users
properties:
- name: created
readExp: date(created)
- name: email
exclude: true
...
Read expression in Property View
The result of the expression defined in readExp using the expression language, will be returned in the read queries.
Example:
infrastructure:
views:
- name: default
entities:
...
- name: Users
properties:
- name: created
readExp: date(created)
- name: email
exclude: true
...
Paths
In this app section, the configuration of the routes where the configuration files or execution results will be generated is established.
Property | Description | required | default |
---|---|---|---|
src | set path of source code | src | |
state | define path of orm state | orm_state | |
model | define path of model to generate | model |
Example:
app:
src: src
state: orm_state
domain: domain