-
Notifications
You must be signed in to change notification settings - Fork 16
Models
Per the Domain Driven Design definition, there are two types of models which Paris allows to define:
- Entity - A model which has identity, it has a life in its own context. It makes sense, for example, to ask the backend for an Entity by its ID. In an SQL implementation, you'd expect to have a table for an Entity. For example, a User is an entity, since it has an ID.
- Value object - A model which only exists in the context of an entity. Value objects may be sub-models of entities (or other value objects), but it doesn't make sense to request a value object from the backend on its own. Value objects are retrieved either as properties inside other models or as relations of other models.
Entities and value objects are implemented in Paris using TypeScript classes, decorated by Paris' Entity or ValueObject decorators. Example:
@Entity({
singularName: "User",
pluralName: "Users",
endpoint: "users"
})
export class User extends EntityModelBase{
@EntityField()
name:string;
@EntityField()
lastLogin:Login;
}
The above Entity contains a sub-model named Login. Its definition is as follows:
@ValueObject({
singularName: "Login",
pluralName: "Logins"
})
export class Login extends ModelBase{
@EntityField()
date:Date;
}
When a User model is retrieved by Paris, data will be fetched by HTTP GET from /users, then an instance of User is created, which also includes an instance of Login in the User's lastLogin
property.
Properties in model classes that correspond to data model properties should be decorated with the EntityField
decorator. When Paris creates a model, it looks for these decorator properties and assigns the proper value to the model instance.
The EntityField
decorator may specify how to match the raw data to the model's property. Consider the following user data:
{
"name": "John",
"age": 30
}
And an entity that contains the following EntityFields:
@EntityField()
name:string;
@EntityField()
age:number;
@EntityField({
data: "age",
parse: age => new Date().getFullYear - age
})
yearOfBirth:number;
@EntityField({ defaultValue: false })
isMarried:boolean;
The resulting model will have the following properties:
{
name: 'John',
age: 30,
yearOfBirth: 1988, // Assuming we're in 2018
isMarried: false
}