SPB Git

spb/phi-conseil

Public
2.0 KB · 65 lines typescript
1import { z } from "zod";23/** Supprime les caractères de contrôle et normalise les espaces. */4export function cleanText(value: string): string {5  return value6    .normalize("NFC")7    .replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, "")8    .replace(/[ \t]+/g, " ")9    .trim();10}1112/** Une seule ligne : empêche l'injection d'en-têtes dans les courriels. */13const singleLine = (max: number) =>14  z15    .string()16    .transform(cleanText)17    .pipe(18      z19        .string()20        .min(1, "Ce champ est requis.")21        .max(max, `Maximum ${max} caractères.`)22        .refine((v) => !/[\r\n]/.test(v), "Les retours à la ligne ne sont pas permis."),23    );2425export const contactSchema = z.object({26  name: singleLine(120),27  email: z28    .string()29    .transform((v) => cleanText(v).toLowerCase())30    .pipe(z.email("Adresse courriel invalide.").max(254)),31  organization: z32    .string()33    .optional()34    .default("")35    .transform(cleanText)36    .pipe(z.string().max(160, "Maximum 160 caractères.")),37  subject: singleLine(160),38  message: z39    .string()40    .transform((v) => v.normalize("NFC").replace(/\r\n?/g, "\n").trim())41    .pipe(42      z43        .string()44        .min(20, "Décrivez votre demande en au moins 20 caractères.")45        .max(4000, "Maximum 4 000 caractères."),46    ),47  consent: z.literal(true, {48    error: "Votre consentement est requis pour traiter la demande.",49  }),50  /** Honeypot : doit rester vide (champ invisible pour les humains). */51  website: z.string().max(0).optional().default(""),52  /** Horodatage du rendu du formulaire : rejette les soumissions instantanées. */53  startedAt: z.coerce.number().int().nonnegative().optional(),54});5556export type ContactInput = z.input<typeof contactSchema>;57export type ContactData = z.output<typeof contactSchema>;5859/** Schéma côté client (sans honeypot/horodatage, consentement booléen). */60export const contactFormSchema = contactSchema.omit({61  website: true,62  startedAt: true,63});64export type ContactFormValues = z.input<typeof contactFormSchema>;65
Files · 986334f6f6688676835eaf88399856804855ca6d
Menu

Theme