Problem
Yes, but there is no easy solution. First you have to define a data migration strategy. Lets assume we make it only work for the required validation rule, because this is probably the easiest.
For this rule it already depends on the field type. Lets talk about a few example.
- String, Number, Boolean: Easy, it is
""
, 0
and false
- Arrays: Easy, it is
[]
.
- Json: No idea, could be
[]
, {}
, ""
, 0
or false
. It really depends what the user expects. This could be solved with an additional field in the UI, where you have to define something.
- Components (a field where you can embed another schema, for example either Article or Blog): No idea, what is a default Article, perhaps it does not even make sense to support this field type.
We only solved it for required fields, because this is the only issue with GraphQL. But you probably want to provide a solution that works fine for other validation rules as well and in this case you have to define a default value, because there is no way to create a default value that matches to a regex pattern.
So you already see, it gets complicated. Now there are 2 different migration strategies. Each of them has major problems:
- Enrich the content after it is queried from the database: This is fast and relatively easy to implement, but it has the problem, that the result you see as a developer does not match to the content in the database. Therefore, if you use filters, the result might not be as expected, because you don’t know the actual value in the database. Squidex already has a on-the-fly enrichment for default values and I don’t like it that much, because of this reason.
- Update all records in the database. This might take a long time, therefore you need a user interface for it, you have to track progress and so on. Squidex provides this feature via the AP and the CLI, because then no user interface is needed.
We could say: If a field is required and if there is a default value, which is not null, we can make the field non-null in GraphQL, BUT there is a special header which allows you to turn the enrichment off and is needed for some edge cases and this would then destroy the whole feature. You cannot decide per query whether a type is non-null or not.
No, it is the opposite. First you have to ensure that you will never, ever deliver a null value to GraphQL. Then you can make it required. But as mentioned above, I don’t see an easy solution.
The solution in your code
I was also facing this issue and this is how I usually solve it:
Create a clear interface
First I create an easy interface, that decouples Squidex from my application code, for example:
interface Recipe {
name: string;
author: string;
authorBio: string;
body: string;
mainImage: string;
}
interface RecipeRepository {
getAll(): Promise<Recipe[]>;
}
Inside the repository I deal with all these problems.
Perhaps I filter out the results that do not match to my query and log them somewhere and create an alert in my logging sytem, so I can tell the content editors, that someone has forgotten to add the nutrition information to a recipe.
Or I enrich my results with default values, if needed.
Conclusion / Opinion
I think you are right. It would be ideal if Squidex has stronger guarantees for data consistency. But I think it is not worth the effort. Because such a system would be restricted and/or very complicated. And it would not provide you all features. For example I mentioned logging and alerting. Or complex validation rules.
We could add a checkbox to the field settings, which would give you the opportunity to mark a field as non-null in GraphQL and then you are on your own to guarantee that, but we would have to add a big red, warning box next to it.