@getplate/validation
v0.1.1
Published
This package contains the validation system for Plate.
Downloads
19
Readme
validation
This package also provides common types, interfaces and classes for Content Validation.
Problem
The content that users will provide should be constrained by the Content Model (Content Types and Content Fields). To
this end, we set up a structure of content Validation Rules. These validation rules specify constraints on Content
Values or Content Items with respect to a specific Content Field. These validation rules direct what kind of Content
Values can be provided for Content Items of specific Content Types.
The execution of these validation rules is done both in frontend and backend to optimise the user experience.
Some validations are also used in frontend to determine the “type” of a content field, and act as “configurations” as well. These are for example
Count
, which can specify whether aContentField
is an array field or just a singular field.ValueType
specifies what type of inputs should be present in the interface (e.g. atext-area
, a date picker or a related Content Item selector).
Available validation rules
| Validation Rule name | Explanation | Applicability | Example | |--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------| | Count | Specifies that a Content Item should have at least x and at most y Content Values for a Content Field | All Content Fields | “Author” Content Items should have exactly 1 (aka min 1, max 1) Content Value for the Content Field “First name”. | | ValueType | Specifies that a Content Item can only have Content Values of a specific type (such as String, Number, Date or Content Item) for a Content Field | All Content Fields | “Author” Content Items should have Content Values of type String for the Content Field “First name” | | StringFormat | Content Value should follow a specific format (Regex) | Content Fields where ValueType is constrained to String | Content Field “email” should only have strings (Content Values) that are actually an email address. | | RelatableContentTypes | Content Value should be a Content Item of a specific Content Type(s) | Content Fields where ValueType is constrained to Content Item | The Content Field “author” of a “Recipe” Content Item, should only have Content Items (as Content Value) of the Content Type “Author” | | AllowedValues | Content Value should be one of a predefined set of values | All Content Fields | The Content Field “married” should only have Content Values that either are “yes” or “no”. | | NumberBetween | Content Value (number) should be between a min and max value | Content Fields where ValueType is constrained to Number | The Content Field “weight” should be at least 0 | | DecimalCount | Content Value (number) should have a min and max amount of decimals | Content Fields where ValueType is constrained to Number | The Content Field “weight” should have exactly 0 decimals (ie it is an Integer) | | DateBetween | Same as NumberBetween | Content Fields where ValueType is constrained to Date | |
Error Formatting
The validation errors are returned from the API in a specific format. Since GraphQL does not provide explicitly typed error messages, the API returns “untyped” error messages. To this end we defined a specific schema in which validation errors are communicated. The exact formatting can be deduced from the core package: https://bitbucket.org/startmetplate/utils-core/src/master/?search_id=c7245c92-5b81-40ed-8cdd-cccdba9499c8 (TODO: Generated JSON schema from this).
Some example showing the basic structure of content validation errors:
// Input request (Create ContentItem)
request = {
contentItem: {
contentType: "prn-content-type",
contentValues: [
{
contentField: "prn-content-field-1",
primitiveValue: "Nils"
},
{
contentField: "prn-content-field-1",
primitiveValue: "David"
},
{
contentField: "prn-content-field-2",
primitiveValue: "Möller"
},
]
}
}
// Validation Error
{
errors: [
{
target: {
// ... full input
},
property: "contentValues",
children: [
{
target: {
contentField: {
prn: "prn-content-field-2",
},
primitiveValue: "Möller",
},
property: "primitiveValue",
details: [
{
message: "Text should contain an email address",
contentField: {
prn: "prn-content-field-2",
},
validationRule: {
ruleType: "textFormat",
prn: "prn-validation-rule-123",
settings: {
regex: /[[SOME_EMAIL_REGEX]]/,
},
},
},
],
},
],
},
{
target: {
// ... full input
},
property: "contentValues",
// "We have too little ContentValues for ContentField 1"
details: [
{
message: "Provide at least 3 first names",
contentField: {
prn: "prn-content-field-1",
},
validationRule: {
ruleType: "count",
prn: "prn-validation-rule",
settings: {
min: 3,
max: 100,
},
},
},
],
children: [],
},
// ... and other errors
];
}
Error messages
Each Validation Rule contains a validate method that can generate a ValidationErrorDetail (shown in the example above in the details section) when it fails and is applicable. These messages provide the user with feedback what went wrong during the validation.
There are 2 locations where Content Validation can be triggered:
- When creating/updating a Content Value.
In this case, we just validate the Content Value with the validations for the related Content Field (so not the other Content Values of the Content Item) - When creating a Content Item.
Open question/limits
- What if I add a validation (or content field) with existing content items?
- How to deal with partial content, that should no be validated yet? Maybe temporarily add a “skipValidation” input for create/update mutation.
- We could maybe implement the validation not as validation on a single ContentItem + ContentValue, but on any generic graph of ContentItems and Contentvalues. We need to think about how to represent this in JSON response? , maybe later.
- No custom/templatable messages on ValidationRules for now.