ENbext.dev
DocumentationOutils pour applications

Traduction automatique depuis l’anglais. Consulter l’original.

Sur cette page

Validation

@bext-stack/framework/validation valide une action serveur FormData, un corps de requête JSON ou tout objet simple par rapport à un schéma que vous écrivez dans TypeScript, et vous renvoie une valeur saisie et forcée ou une liste d'erreurs par champ. Il s'agit de l'équivalent pour les développeurs d'applications de la fonctionnalité Rust Validateur de demande : la fonctionnalité valide les fichiers de configuration et les charges utiles de la file d'attente côté serveur ; ce module est ce que vous recherchez à l'intérieur d'un PRISM action.

Il est en forme de zod donc le modèle mental transfère — v.object({...}), .parse / .safeParse - mais il s'agit de quelques centaines de lignes de TypeScript pur avec zéro dépendance, et il comprend le monde entièrement composé de chaînes des formulaires HTML (les chaînes numériques deviennent des nombres, les cases à cocher deviennent des booléens, les champs répétés deviennent des tableaux).

Quand l'utiliser#

  • Actions du serveur et routes API — validez request avant de lui faire confiance.
  • Formulaires multi-erreurs — affichez le problème de chaque champ en même temps, pas seulement le d'abord, tout en conservant les valeurs saisies par l'utilisateur lors d'un nouveau rendu.
  • Entrée typée — transforme FormData (toutes les chaînes) en un objet typé avec nombres, booléens et énumérations, vérifiés à la limite.

Pour une seule vérification de type ad hoc, un if en ligne est plus simple. Atteignez-le lorsque la forme est réelle, partagée ou montrée à un utilisateur.

Conseil

L’ordre des règles est significatif. errorsByField renvoie le premier message par champ, donc déclarer .nonempty("Required") avant .email("Malformed") vous donne gratuitement l'UX naturelle du « format ALORS requis » - tandis que errorsByFieldAll expose toujours chaque échec de vérification.

Générateurs de schémas#

Atteignez tous les constructeurs via l'espace de noms v.

Constructeur Produit Méthodes notables
v.string(opts?) string .trim() .toLowerCase() .nonempty() .min(n) .max(n) .length(n) .regex(re) .email() .url()
v.number(opts?) number (contraint à partir de chaînes numériques) .int() .min(n) .max(n) .positive() .nonnegative()
v.boolean() boolean sémantique de la case à cocher — absent → false, "on" / "true" / "1" → true, jamais d'erreurs
v.enum([...] as const) l'union des littéraux —
v.literal(x) la valeur exacte x —
v.array(inner) T[] .min(n) .max(n) .nonempty() — un seul champ de formulaire répété compte comme une liste à 1 élément
v.object(shape) le type d'objet déduit .partial() (tous en option) .strict() (rejeter les clés inconnues)

Chaque constructeur peut être chaîné avec .optional(), .nullable(), .default(value), .refine(test, message) et .transform(fn). Le opts sur v.string / v.number remplace les messages intégrés requis et de type incorrect (ceux que les méthodes de contrainte ne peuvent pas atteindre) - c'est le crochet pour la copie localisée.

Valider une demande#

validate(input, schema) lit le corps pour vous — FormData, application/json, ou x-www-form-urlencoded — valide ensuite :

ts
import { v, validate, errorsByField, type Infer } from "@bext-stack/framework/validation";

const Signup = v.object({
  email:    v.string().trim().nonempty("Email required").email("Looks malformed"),
  username: v.string().trim().min(3).regex(/^[a-z0-9_]+$/i, "letters, digits, _ only"),
  age:      v.number().int().min(13).max(120),
});
type Signup = Infer<typeof Signup>;   // { email: string; username: string; age: number }

export async function action({ request }: { request: Request }) {
  const result = await validate(request, Signup);
  if (!result.ok) {
    // Return a plain object → PRISM re-renders the page with actionData,
    // so the form shows per-field errors and keeps the user's typing.
    return { ok: false, errors: errorsByField(result.errors) };
  }
  const user = result.data;      // fully typed & coerced — user.age is a number
  await createUser(user);
  return new Response(null, { status: 303, headers: { Location: "/welcome" } });
}

Vous préférez éviter le passe-partout ? validated(schema, handler) encapsule une action afin que votre gestionnaire ne s'exécute que sur une entrée valide et reçoive les données saisies ; courts-circuits d'entrée non valides vers une charge utile de re-rendu { ok: false, errors, values } :

ts
export const action = validated(Signup, async (data, { request }) => {
  await createUser(data);        // data is Signup, typed & coerced
  return new Response(null, { status: 303, headers: { Location: "/welcome" } });
});

Règles de coercition#

Étant donné que les formulaires HTML envoient tout sous forme de chaînes, les constructeurs contraignent plutôt que rejettent :

  • v.number() analyse une chaîne numérique ( "27" → 27 ) ; un champ vide ou absent est required, une chaîne non numérique est invalid.
  • v.boolean() suit la sémantique des cases à cocher : une case à cocher absente est false, une celui actuel ( "on" ) est true. Il n'y a jamais d'erreurs.
  • v.array(inner) traite une valeur unique comme une liste à un élément, donc une valeur répétée le champ de formulaire ( tag=a&tag=b ) et un seul tag=a sont tous deux validés.
  • Rapport v.object / v.array imbriqué chemins en pointillés / entre crochets — address.zip, tags[2] — donc l'erreur correspond directement à vos entrées.

Aides aux erreurs#

Auxiliaire Retours Utiliser pour
errorsByField(errors) { field: firstMessage } le formulaire commun à un message par entrée
errorsByFieldAll(errors) { field: string[] } montrant tous les problèmes sur un terrain
stringValues(raw) { field: string } repeupler un formulaire rejeté
formToObject(fd) objet simple quand on veut l'objet brut avant de valider

.parse(input) lance un ValidationError (portant .errors ) en cas d'échec ; .safeParse(input) ne lance jamais et ne renvoie jamais un ValidationResult.

Relation avec la fonctionnalité Request Validator#

Le Rust Validateur de demande est un trait de plugin côté serveur permettant de valider les fichiers de configuration, les charges utiles de webhook décodées et les messages de file d'attente avant qu'ils n'atteignent un gestionnaire - soutenu par JSON-Schema / CUE, sélectionné par BEXT_VALIDATOR_PROVIDER. Ce module est le chemin isolé TypeScript pour la validation de demande/formulaire dans le code de votre application : aucun fournisseur à configurer, aucun aller-retour d'hôte et le schéma réside à côté du code qui l'utilise. Utilisez la fonctionnalité aux limites du plugin/configuration ; utilisez-le dans vos itinéraires PRISM.

Essayez-le#

Une démo exécutable - un formulaire d'inscription qui signale chaque erreur de champ en un seul passage et 303 s en cas de succès - se trouve sur démo. bext.dev/examples/validation, source dans sites/demo/src/app/examples/validation/page.tsx.

Voir aussi#

Modifier cette page ↗Besoin d’aide ? ↗
Rechercher dans la documentation

Saisissez un sujet, une commande ou une question.