Step 5: Data Model Validator
Your templates cannot handle any combination of fields and attributes. To prevent this, you can associate a data model validator to your templates.
How does it work?
This validator is written in pure JavaScript. It receives a single data model and returns warnings
and errors
.
These warnings and errors will be displayed during data model management:
Warnings | Errors |
---|---|
![]() |
![]() |
Write a validator
When validating the data model, the JavaScript code is wrapped into a function. Therefore, the code you are writing is the body of that function. Your code must return an object like this:
return {
errors: ['Model has no primary key'],
warnings: []
}
Accessing the data model properties
In the validator script, the data model is available under the model
variable.
The model
variable is structured like this:
{
"id": "bdc6c58e-ec49-9193-6b29-6c75518bc3ad",
"name": "Bookmark",
"notes": "A user can only list its own bookmarks",
"fields": [
{
"name": "_id",
"notes": null,
"type": "string",
"subtype": null,
"value": null,
"primary": true,
"unique": false,
"label": false,
"nullable": false,
"multiple": false,
"embedded": false,
"searchable": false,
"sortable": false,
"hidden": false,
"internal": true,
"restricted": false,
"ownership": false
}
],
"accesses": {
"create": "auth",
"read": "owner",
"update": "admin",
"remove": "owner",
"search": "owner",
"count": "owner"
}
}
Unlike the JavaScript template engine, the data model properties are not pre-computed and you do not have access to the data model dependencies.
Example of validator
Here is an example of a validator that sends a warning for an unsupported field type, and an error if the primary key is not compliant.
// Model object is injected as "model"
const errors = [];
const warnings = [];
// -----------------------------
// File fields
if (model.fields.filter((f) => f.type === 'file').length) {
errors.push('File fields are not supported yet by this boilerplate');
}
// URL fields
if (model.fields.filter((f) => f.type === 'string' && f.subtype === 'url').length) {
warnings.push('URL string is not supported yet and will be handle as default string');
}
// -----------------------------
// Primary key
const primaries = model.fields.filter((f) => f.primary);
if (primaries.length > 1) {
errors.push('Only one field can be primary');
}
const primary = primaries[0];
if (primary) {
if (primary.name !== '_id') {
errors.push('Primary key must be called "_id"');
}
if (primary.type !== 'string') {
errors.push('Primary key must be a string');
}
if (!primary.internal) {
errors.push('Primary key must be a internal');
}
} else {
errors.push('Primary key is required');
}
// -----------------------------
// Meta values
if (!model.meta.plural) {
errors.push('Plural name is required');
}
return {
errors,
warnings,
};