Aller au contenu

Validation et conditions

Utilisé avec des propriétés de type chaîne ou nombre pour afficher des listes déroulantes :

import type { StringProperty } from "@rebasepro/types";
// Simple: each value mapped to its label
const simple: StringProperty = {
type: "string",
name: "Status",
enum: { draft: "Draft", published: "Published", archived: "Archived" }
};
// As a list, which keeps the order you write
const listed: StringProperty = {
type: "string",
name: "Status",
enum: [
{ id: "draft", label: "Draft" },
{ id: "published", label: "Published" },
{ id: "archived", label: "Archived" }
]
};
// With colors (for Kanban columns and chips)
const colored: StringProperty = {
type: "string",
name: "Status",
enum: [
{ id: "draft", label: "Draft", color: "grayDark" },
{ id: "published", label: "Published", color: "greenDark" },
{ id: "archived", label: "Archived", color: "orangeDark" }
]
};

Une simple liste de valeurs, enum: ["draft", "published", "archived"], ne fait pas partie du type. Une configuration JavaScript qui en écrit une fonctionne tout de même : l’enum de la base de données, les types générés et la liste déroulante de l’admin la lisent comme ces valeurs, chacune étant son propre libellé.

Chaque règle réside dans le bloc validation de la propriété, et les règles acceptées par une propriété dépendent de son type — min compte les caractères pour une chaîne, compare les grandeurs pour un nombre, et compte les éléments pour un tableau.

properties: {
title: {
type: "string",
name: "Title",
validation: { required: true, min: 2, max: 200 }
},
slug: {
type: "string",
name: "Slug",
validation: {
unique: true,
matches: /^[a-z0-9-]+$/,
matchesMessage: "Lowercase letters, digits and hyphens only",
trim: true,
lowercase: true
}
},
readingMinutes: {
type: "number",
name: "Reading time",
validation: { integer: true, moreThan: 0, max: 120 }
}
}

Le serveur vérifie validation à la frontière de la requête — REST, le socket temps réel et MCP — sur ce que l’appelant a envoyé, avant l’exécution de beforeSave, et répond à une écriture qui enfreint une règle par une 400 nommant chaque champ en défaut. Le code serveur qui écrit en interne au processus est de confiance et n’est pas vérifié par rapport à ces règles : rebase.data et rebase.dataAsAdmin dans une fonction ou une tâche cron, context.data dans un callback, un script de seed. Ce qui s’applique là-bas est ce que la base de données impose elle-même — required (NOT NULL), unique (un index unique), le type d’un enum, et la largeur d’une colonne varchar ou char. Tout ce que votre code serveur écrit d’autre, vérifiez-le dans le code qui l’écrit.

Le panneau d’administration vérifie les mêmes règles avant d’enregistrer, dans le formulaire d’enregistrement et dans l’éditeur en ligne du tableau de la collection. Une cellule du tableau juge une valeur une fois que vous la modifiez : une valeur stockée qui enfreint une règle ajoutée plus tard n’affiche aucune erreur dans le tableau tant que quelqu’un n’a pas modifié cette cellule.

Règle Type Description
required boolean La valeur doit être présente. Sur une string, "" compte comme absente : l’API la refuse à toute écriture, création ou mise à jour, avec la même violation required (sauf si la collection a un beforeSave, qui peut la remplir)
requiredMessage string Le message affiché lorsqu’elle est absente : par le formulaire d’administration, et comme message de l’entrée required du champ dans le 400 de l’API. Le NOT NULL de la base de données ne porte aucun message
unique boolean Une seule ligne dans la table peut avoir cette valeur. Le formulaire d’administration la vérifie aussi lors de l’enregistrement d’une valeur que la modification a changée, de sorte qu’un doublon est signalé sur son champ avant l’écriture
uniqueInArray boolean Une seule entrée par tableau peut l’avoir. S’applique à un enfant direct d’une propriété array, ou à un enfant de premier niveau d’un map à l’intérieur de celui-ci. Formulaire d’administration uniquement — non appliqué par l’API ou la base de données.
Règle Type Description
min / max number Nombre minimum / maximum de caractères, inclusif. Avec columnType: "varchar" ou "char", max dimensionne également la colonne (VARCHAR(max)), donc le réduire sur une table contenant déjà des lignes plus longues est une migration que la base de données refusera, et l’éditeur de collection avertit lorsqu’une modification le réduit. La colonne par défaut est TEXT, que max laisse illimitée — la limite n’est alors imposée que par la vérification de requête du serveur
length number Exactement ce nombre de caractères — un code pays, une référence à longueur fixe
matches string | RegExp Un motif que la valeur entière doit respecter. Une chaîne est compilée par requête, donc une chaîne qui ne compile pas est rejetée au démarrage plutôt que de devenir silencieusement une règle inactive
matchesMessage string Le message affiché par le formulaire lorsque matches échoue
trim boolean Supprime les espaces au début et à la fin avant l’enregistrement. Une transformation, pas une vérification — cela modifie ce qui est écrit, ce qui permet de résoudre le cas du « même tag en double, dont un avec un espace final ». Formulaire d’administration uniquement — non appliqué par l’API ou la base de données.
lowercase / uppercase boolean Convertit la casse de la valeur avant l’enregistrement, comme trim. Formulaire d’administration uniquement — non appliqué par l’API ou la base de données.

Les formats d’e-mail et d’URL ne sont pas des règles de validation. email et url sont des indicateurs (flags) sur la propriété elle-même, aux côtés de type — des déclarations sur les données à partir desquelles le contrat OpenAPI est généré, plutôt qu’un comportement de formulaire :

properties: {
email: { type: "string", name: "Email", email: true },
website: { type: "string", name: "Website", url: true }
}

Voir Propriétés de chaîne.

Règle Type Description
min / max number Valeur acceptée la plus petite / la plus grande, inclusive
moreThan / lessThan number Les équivalents stricts de min et max
positive / negative boolean Strictement supérieur / inférieur à zéro. 0 est rejeté par les deux — utilisez min: 0 pour l’autoriser
integer boolean Pas de partie décimale. Ne modifie pas le type de la colonne ; columnType le fait
Règle Type Description
min / max Date Date acceptée la plus ancienne / la plus récente, inclusive. Un instant fixe, pas « aujourd’hui »
Règle Type Description
min / max number Nombre minimum / maximum d’éléments, inclusif. Des éléments, pas des caractères

Vous pouvez rendre les champs dynamiques afin qu’ils réagissent aux valeurs de l’entité. Il existe deux façons de procéder :

Vous pouvez utiliser la propriété conditions pour définir des règles déclaratives JSON Logic qui peuvent être sérialisées et modifiées visuellement dans l’éditeur de collection.

price: {
type: "number",
name: "Price",
conditions: {
disabled: { "==": [{ "var": "values.is_free" }, true] },
required: { "!=": [{ "var": "values.is_free" }, true] },
min: 0,
clearOnDisabled: true // Set to null if field gets disabled
}
}

L’objet conditions vous donne accès à :

  • disabled, disabledMessage, clearOnDisabled, hidden, readOnly
  • required, requiredMessage, min, max
  • defaultValue
  • enumConditions, allowedEnumValues, excludedEnumValues
  • referencePath, referenceFilter
  • canAddElements, sortable (pour les tableaux)
  • acceptedFiles, maxFileSize (pour les téléversements)

disabledMessage est la phrase qu’un utilisateur voit à la place du contrôle. Sans elle, un champ grisé n’explique rien, ce qui fait toute la différence entre un formulaire qui guide l’utilisateur et un formulaire qui le bloque.

Pour les comportements complexes qui ne peuvent pas être exprimés via JSON Logic, vous pouvez utiliser dynamicProps qui évalue une fonction JavaScript.

price: {
type: "number",
name: "Price",
dynamicProps: ({ values, authController }) => ({
admin: { disabled: values.is_free === true || !authController.user?.roles?.includes("admin") },
validation: values.is_free ? {} : { required: true, min: 0 }
})
}

Le même avertissement s’applique, et de manière encore plus marquée : la fonction est intégrée dans le panneau et appelée à chaque rendu du formulaire. Formulaire d’administration uniquement — non appliqué par l’API ou la base de données.