Validation des données entrantes
Que ce soit sur vos endpoints tRPC ou sur un endpoint à part dans Next.js pour recevoir des webhooks, la devise est de toujours valider les données entrantes.
Nous utilisons zod
pour faire la validation au moment du runtime (quand les types ne peuvent être garantis sur les données entrantes). Cela nous permet une certaine flexibilité puisqu'il peut servir à la validation d'entrée d'un endpoint mais aussi pour formater une structure métier (dans le cas où vous voulez que ça émette une erreur si la structure récupérée depuis une base de données est mal formatée par exemple).
- Une pratique peut être de définir vos structures métiers avec
zod
puisque les types peuvent être "inférés" ; - zod est nativement supporté par tRPC, donc vous n'avez qu'à mettre votre structure
input
au niveau du endpoint ; - zod peut s'utiliser côté frontend avec
react-hook-form
afin de faire des validations sans même contacter le serveur. Ce qui est pratique dans notre cas c'est que la même structure de validation est utilisée dans les 2 mondes (avec ces textes d'erreurs qui peuvent être personnalisés).
entities/agent.tsx | Déclaration d'une structure d'entité
import z from 'zod';
import { UserSchema } from './user';
export const AgentSchema = z
.object({
id: z.string().uuid(),
userId: z.string().uuid(),
authorityId: z.string().uuid(),
firstname: UserSchema.shape.firstname,
lastname: UserSchema.shape.lastname,
email: UserSchema.shape.email,
profilePicture: UserSchema.shape.profilePicture,
isMainAgent: z.boolean(),
createdAt: z.date(),
updatedAt: z.date(),
deletedAt: z.date().nullable(),
})
.strict();
export type AgentSchemaType = z.infer<typeof AgentSchema>;
actions/agent.tsx | Validation d'une mutation avec les propriétés d'entités existantes
import { AgentSchema } from '@mediature/main/src/models/entities/agent';
import { AuthoritySchema } from '@mediature/main/src/models/entities/authority';
import { UserSchema } from '@mediature/main/src/models/entities/user';
import z from 'zod';
export const AddAgentSchema = z
.object({
userId: UserSchema.shape.id,
authorityId: AgentSchema.shape.authorityId,
grantMainAgent: z.boolean(),
})
.strict();
export type AddAgentSchemaType = z.infer<typeof AddAgentSchema>;