diff --git a/.changeset/many-sails-hang.md b/.changeset/many-sails-hang.md new file mode 100644 index 000000000..54600cc4a --- /dev/null +++ b/.changeset/many-sails-hang.md @@ -0,0 +1,5 @@ +--- +"@svenvw/fdm-app": patch +--- + +Migrate to zod v4 diff --git a/fdm-app/app/components/blocks/cultivation/schema.ts b/fdm-app/app/components/blocks/cultivation/schema.ts index 43e4f5063..7fa35063c 100644 --- a/fdm-app/app/components/blocks/cultivation/schema.ts +++ b/fdm-app/app/components/blocks/cultivation/schema.ts @@ -2,9 +2,15 @@ import { z } from "zod" export const CultivationDetailsFormSchema = z .object({ - b_lu_start: z.coerce.date({ - required_error: "Zaaidatum is verplicht.", - }), + b_lu_start: z.preprocess( + (val) => (typeof val === "string" ? new Date(val) : val), + z.date({ + error: (issue) => + issue.input === undefined + ? "Zaaidatum is verplicht." + : undefined, + }), + ), b_lu_end: z .preprocess((value) => { if (typeof value === "string") { @@ -12,7 +18,7 @@ export const CultivationDetailsFormSchema = z } return value }, z.coerce.date().optional().nullable()) - .default(null), + .prefault(null), m_cropresidue: z.preprocess((value) => { if (typeof value === "string") { if (value.toLowerCase() === "false") return false @@ -36,8 +42,8 @@ export const CultivationDetailsFormSchema = z return true }, { - message: "Einddatum moet na de zaaidatum liggen.", path: ["b_lu_end"], + error: "Einddatum moet na de zaaidatum liggen." }, ) @@ -47,9 +53,15 @@ export type CultivationDetailsFormSchemaType = z.infer< export const CultivationAddFormSchema = z.object({ b_lu_catalogue: z.string().min(1, "Gewas is verplicht."), - b_lu_start: z.coerce.date({ - required_error: "Zaaidatum is verplicht.", - }), + b_lu_start: z.preprocess( + (val) => (typeof val === "string" ? new Date(val) : val), + z.date({ + error: (issue) => + issue.input === undefined + ? "Zaaidatum is verplicht." + : undefined, + }), + ), b_lu_end: z.preprocess((value) => { if (typeof value === "string") { if (value.toLowerCase() === "null") return null diff --git a/fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx b/fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx index 5aa24ced7..e3fab95c4 100644 --- a/fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx +++ b/fdm-app/app/components/blocks/fertilizer-applications/formschema.tsx @@ -1,34 +1,43 @@ import { z } from "zod" export const FormSchema = z.object({ - p_app_amount: z.coerce - .number({ - required_error: "Hoeveelheid is verplicht", - invalid_type_error: "Hoeveelheid moet een getal zijn", - }) - .positive({ - message: "Hoeveelheid moet positief zijn", - }) - .finite({ - message: "Hoeveelheid moet een geheel getal zijn", + p_app_amount: z.preprocess( + (val) => (typeof val === "string" && val !== "" ? Number(val) : val), + z.number({ + error: (issue) => + issue.input === undefined + ? "Hoeveelheid is verplicht" + : "Hoeveelheid moet een getal zijn", + }).positive({ + error: "Hoeveelheid moet positief zijn", }), + ), p_app_method: z.string().min(1, "Toepassingsmethode is verplicht"), - p_app_date: z.coerce.date({ - required_error: "Datum is verplicht", - invalid_type_error: "Datum is ongeldig", - }), + p_app_date: z.preprocess( + (val) => (typeof val === "string" ? new Date(val) : val), + z.date({ + error: (issue) => + issue.input === undefined + ? "Datum is verplicht" + : "Datum is ongeldig", + }), + ), p_id: z.string({ // TODO: Validate against the options that are available - required_error: "Keuze van meststof is verplicht", - invalid_type_error: "Meststof is ongeldig", + error: (issue) => + issue.input === undefined + ? "Keuze van meststof is verplicht" + : "Meststof is ongeldig", }), }) export const FormSchemaModify = FormSchema.extend({ p_app_id: z.string({ // TODO: Validate against the options that are available - required_error: "Bemesting id is verplicht", - invalid_type_error: "Bemesting id is ongeldig", + error: (issue) => + issue.input === undefined + ? "Bemesting id is verplicht" + : "Bemesting id is ongeldig", }), }) diff --git a/fdm-app/app/components/blocks/fertilizer/formschema.tsx b/fdm-app/app/components/blocks/fertilizer/formschema.tsx index d25a3f501..e950f640a 100644 --- a/fdm-app/app/components/blocks/fertilizer/formschema.tsx +++ b/fdm-app/app/components/blocks/fertilizer/formschema.tsx @@ -4,29 +4,40 @@ export const FormSchema = z .object({ p_name_nl: z .string({ - required_error: "Naam is verplicht", - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? "Naam is verplicht" + : "Ongeldige waarde", }) - .min(1, { message: "Geef een naam op voor deze meststof" }), + .min(1, { + error: "Geef een naam op voor deze meststof", + }), p_name_en: z.string().optional(), p_description: z.string().optional(), p_type_rvo: z .string({ - required_error: "RVO mestcode is verplicht", - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? "RVO mestcode is verplicht" + : "Ongeldige waarde", }) - .min(1, { message: "RVO mestcode mag niet leeg zijn" }), + .min(1, { + error: "RVO mestcode mag niet leeg zijn", + }), p_dm: z.preprocess( (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000, { - message: "Waarde mag niet groter zijn dan 1000", + error: "Waarde mag niet groter zijn dan 1000", }) .optional(), ), @@ -34,13 +45,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0.00016, { - message: "Waarde mag niet kleiner dan 0.00016 zijn", + error: "Waarde mag niet kleiner dan 0.00016 zijn", }) .max(17.31, { - message: "Waarde mag niet groter zijn dan 17.31", + error: "Waarde mag niet groter zijn dan 17.31", }) .optional(), ), @@ -48,13 +62,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000, { - message: "Waarde mag niet groter zijn dan 1000", + error: "Waarde mag niet groter zijn dan 1000", }) .optional(), ), @@ -74,13 +91,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000, { - message: "Waarde mag niet groter zijn dan 1000", + error: "Waarde mag niet groter zijn dan 1000", }) .optional(), ), @@ -108,13 +128,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000, { - message: "Waarde mag niet groter zijn dan 1000", + error: "Waarde mag niet groter zijn dan 1000", }) .optional(), ), @@ -130,13 +153,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1, { - message: "Waarde mag niet groter zijn dan 1", + error: "Waarde mag niet groter zijn dan 1", }) .optional(), ), @@ -144,13 +170,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000, { - message: "Waarde mag niet groter zijn dan 1000", + error: "Waarde mag niet groter zijn dan 1000", }) .optional(), ), @@ -158,13 +187,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000, { - message: "Waarde mag niet groter zijn dan 1000", + error: "Waarde mag niet groter zijn dan 1000", }) .optional(), ), @@ -172,13 +204,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(4583, { - message: "Waarde mag niet groter zijn dan 4583", + error: "Waarde mag niet groter zijn dan 4583", }) .optional(), ), @@ -186,13 +221,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(2409.2, { - message: "Waarde mag niet groter zijn dan 2409.2", + error: "Waarde mag niet groter zijn dan 2409.2", }) .optional(), ), @@ -200,13 +238,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1659, { - message: "Waarde mag niet groter zijn dan 1659", + error: "Waarde mag niet groter zijn dan 1659", }) .optional(), ), @@ -214,13 +255,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1399.2, { - message: "Waarde mag niet groter zijn dan 1399.2", + error: "Waarde mag niet groter zijn dan 1399.2", }) .optional(), ), @@ -232,13 +276,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(2497.2, { - message: "Waarde mag niet groter zijn dan 2497.2", + error: "Waarde mag niet groter zijn dan 2497.2", }) .optional(), ), @@ -250,13 +297,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000000, { - message: "Waarde mag niet groter zijn dan 1000000", + error: "Waarde mag niet groter zijn dan 1000000", }) .optional(), ), @@ -264,13 +314,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000000, { - message: "Waarde mag niet groter zijn dan 1000000", + error: "Waarde mag niet groter zijn dan 1000000", }) .optional(), ), @@ -278,13 +331,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(2695900, { - message: "Waarde mag niet groter zijn dan 2695900", + error: "Waarde mag niet groter zijn dan 2695900", }) .optional(), ), @@ -296,13 +352,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000000, { - message: "Waarde mag niet groter zijn dan 1000000", + error: "Waarde mag niet groter zijn dan 1000000", }) .optional(), ), @@ -310,13 +369,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000000, { - message: "Waarde mag niet groter zijn dan 1000000", + error: "Waarde mag niet groter zijn dan 1000000", }) .optional(), ), @@ -332,13 +394,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000000, { - message: "Waarde mag niet groter zijn dan 1000000", + error: "Waarde mag niet groter zijn dan 1000000", }) .optional(), ), @@ -346,13 +411,16 @@ export const FormSchema = z (val) => (val === "" || val === null ? undefined : val), z.coerce .number({ - invalid_type_error: "Ongeldige waarde", + error: (issue) => + issue.input === undefined + ? undefined + : "Ongeldige waarde", }) .min(0, { - message: "Waarde mag niet negatief zijn", + error: "Waarde mag niet negatief zijn", }) .max(1000000, { - message: "Waarde mag niet groter zijn dan 1000000", + error: "Waarde mag niet groter zijn dan 1000000", }) .optional(), ), @@ -386,11 +454,14 @@ export const FormSchema = z ), p_app_method_options: z .array(z.string(), { - required_error: "Selecteer minimaal 1 methode", + error: (issue) => + issue.input === undefined + ? "Selecteer minimaal 1 methode" + : undefined, }) - .default([]) + .prefault([]) .refine((value) => value.some((item) => item), { - message: "Selecteer minimaal 1 methode", + error: "Selecteer minimaal 1 methode", }), }) .refine( @@ -401,9 +472,8 @@ export const FormSchema = z return true }, { - message: - "N-werkingscoëfficiënt is verplicht als meststof stikstofbevat", path: ["p_n_wc"], + error: "N-werkingscoëfficiënt is verplicht als meststof stikstofbevat", }, ) .refine( @@ -425,8 +495,7 @@ export const FormSchema = z return true }, { - message: - "De som van nitraat en ammonium kan niet groter zijn dan het totale stikstofgehalte", path: ["p_n_rt"], + error: "De som van nitraat en ammonium kan niet groter zijn dan het totale stikstofgehalte", }, ) diff --git a/fdm-app/app/components/blocks/field/schema.tsx b/fdm-app/app/components/blocks/field/schema.tsx index 47996bd9e..714e62fb2 100644 --- a/fdm-app/app/components/blocks/field/schema.tsx +++ b/fdm-app/app/components/blocks/field/schema.tsx @@ -3,22 +3,32 @@ import { z } from "zod" const FormSchema = z.object({ b_name: z .string({ - required_error: "Naam van perceel is verplicht", + error: (issue) => + issue.input === undefined + ? "Naam van perceel is verplicht" + : undefined, }) .min(3, { - message: "Naam van perceel moet minimaal 3 karakters bevatten", + error: "Naam van perceel moet minimaal 3 karakters bevatten", }), b_lu_catalogue: z.string({ - required_error: "Hoofdgewas is verplicht", + error: (issue) => + issue.input === undefined ? "Hoofdgewas is verplicht" : undefined, }), b_id_source: z .string({ - required_error: "ID van bron is verplicht", + error: (issue) => + issue.input === undefined + ? "ID van bron is verplicht" + : undefined, }) .optional(), b_geometry: z .string({ - required_error: "Geometrie van perceel is verplicht", + error: (issue) => + issue.input === undefined + ? "Geometrie van perceel is verplicht" + : undefined, }) .optional(), }) diff --git a/fdm-app/app/components/blocks/harvest/schema.tsx b/fdm-app/app/components/blocks/harvest/schema.tsx index 2c90bf437..007f94f6a 100644 --- a/fdm-app/app/components/blocks/harvest/schema.tsx +++ b/fdm-app/app/components/blocks/harvest/schema.tsx @@ -6,14 +6,16 @@ export const FormSchema = z .object({ b_lu_harvest_date: z .string({ - required_error: "Selecteer een oogstdatum", - invalid_type_error: "Selecteer een geldige oogstdatum", + error: (issue) => + issue.input === undefined + ? "Selecteer een oogstdatum" + : "Selecteer een geldige oogstdatum", }) .transform((val, ctx) => { const date = new Date(val) if (Number.isNaN(date.getTime())) { ctx.addIssue({ - code: z.ZodIssueCode.custom, + code: "custom", message: "Selecteer een geldige oogstdatum", }) return z.NEVER @@ -21,192 +23,157 @@ export const FormSchema = z return date }), b_lu_yield: z.preprocess( - (val) => (val === "" ? undefined : val), - z.coerce - .number({ - invalid_type_error: "De waarde moet een getal zijn", + (val) => (val === "" ? undefined : typeof val === "string" ? Number(val) : val), + z.number({ + error: "De opbrengst (DS) moet een getal zijn", + }) + .int({ + message: "De opbrengst (DS) moet een geheel getal zijn (zonder decimalen)", }) .positive({ - message: "De waarde moet groter zijn dan 0", - }) - .finite({ - message: "De waarde moet een geldig getal zijn", + message: "De opbrengst (DS) moet groter zijn dan 0", }) .max(250000, { - message: - "Opbrengst mag niet groter zijn dan 250.000 kg DS / ha", - }) - .safe({ - message: "De waarde is buiten het toegestane bereik", + message: "De opbrengst (DS) mag niet groter zijn dan 250.000 kg DS/ha", }) .optional(), ), b_lu_yield_fresh: z.preprocess( - (val) => (val === "" ? undefined : val), - z.coerce - .number({ - invalid_type_error: "De waarde moet een getal zijn", + (val) => (val === "" ? undefined : typeof val === "string" ? Number(val) : val), + z.number({ + error: "De versproduct opbrengst moet een getal zijn", + }) + .int({ + message: "De versproduct opbrengst moet een geheel getal zijn (zonder decimalen)", }) .positive({ - message: "De waarde moet groter zijn dan 0", - }) - .finite({ - message: "De waarde moet een geldig getal zijn", + message: "De versproduct opbrengst moet groter zijn dan 0", }) .max(250000, { - message: - "Opbrengst mag niet groter zijn dan 250.000 kg versproduct / ha", - }) - .safe({ - message: "De waarde is buiten het toegestane bereik", + message: "De versproduct opbrengst mag niet groter zijn dan 250.000 kg versproduct/ha", }) .optional(), ), b_lu_yield_bruto: z.preprocess( - (val) => (val === "" ? undefined : val), - z.coerce - .number({ - invalid_type_error: "De waarde moet een getal zijn", + (val) => (val === "" ? undefined : typeof val === "string" ? Number(val) : val), + z.number({ + error: "De bruto opbrengst (incl. tarra) moet een getal zijn", + }) + .int({ + message: "De bruto opbrengst (incl. tarra) moet een geheel getal zijn (zonder decimalen)", }) .positive({ - message: "De waarde moet groter zijn dan 0", - }) - .finite({ - message: "De waarde moet een geldig getal zijn", + message: "De bruto opbrengst (incl. tarra) moet groter zijn dan 0", }) .max(250000, { - message: - "Opbrengst mag niet groter zijn dan 250.000 kg versproduct (incl. tarra) / ha", - }) - .safe({ - message: "De waarde is buiten het toegestane bereik", + message: "De bruto opbrengst mag niet groter zijn dan 250.000 kg versproduct (incl. tarra)/ha", }) .optional(), ), b_lu_dm: z.preprocess( - (val) => (val === "" ? undefined : val), - z.coerce - .number({ - invalid_type_error: "De waarde moet een getal zijn", + (val) => (val === "" ? undefined : typeof val === "string" ? Number(val) : val), + z.number({ + error: "Het droge stofgehalte moet een getal zijn", + }) + .int({ + message: "Het droge stofgehalte moet een geheel getal zijn (zonder decimalen)", }) .positive({ - message: "De waarde moet groter zijn dan 0", - }) - .finite({ - message: "De waarde moet een geldig getal zijn", + message: "Het droge stofgehalte moet groter zijn dan 0", }) .max(1000, { - message: - "Het droge stof gehalte mag niet groter zijn dan 1.000 g / kg", - }) - .safe({ - message: "De waarde is buiten het toegestane bereik", + message: "Het droge stofgehalte mag niet groter zijn dan 1.000 g/kg", }) .optional(), ), b_lu_n_harvestable: z.preprocess( - (val) => (val === "" ? undefined : val), - z.coerce - .number({ - invalid_type_error: "De waarde moet een getal zijn", - }) + (val) => (val === "" ? undefined : typeof val === "string" ? Number(val) : val), + z.number({ + error: "De stikstofopbrengst moet een getal zijn", + }) .positive({ - message: "De waarde moet groter zijn dan 0", + message: "De stikstofopbrengst moet groter zijn dan 0", }) .max(1000, { - message: - "De stikstofopbrengst mag niet groter zijn dan 1.000 kg N / ha", + message: "De stikstofopbrengst mag niet groter zijn dan 1.000 kg N/ha", }) .optional(), ), b_lu_tarra: z.preprocess( - (val) => (val === "" ? undefined : val), - z.coerce - .number({ - invalid_type_error: "De waarde moet een getal zijn", + (val) => (val === "" ? undefined : typeof val === "string" ? Number(val) : val), + z.number({ + error: "Het tarra-percentage moet een getal zijn", + }) + .int({ + message: "Het tarra-percentage moet een geheel getal zijn (zonder decimalen)", }) .positive({ - message: "De waarde moet groter zijn dan 0", - }) - .finite({ - message: "De waarde moet een geldig getal zijn", + message: "Het tarra-percentage moet groter zijn dan 0", }) .max(25, { message: "Het tarra-percentage mag niet hoger zijn dan 25%", }) - .safe({ - message: "De waarde is buiten het toegestane bereik", - }) .optional(), ), b_lu_uww: z.preprocess( - (val) => (val === "" ? undefined : val), - z.coerce - .number({ - invalid_type_error: "De waarde moet een getal zijn", + (val) => (val === "" ? undefined : typeof val === "string" ? Number(val) : val), + z.number({ + error: "Het onderwatergewicht moet een getal zijn", + }) + .int({ + message: "Het onderwatergewicht moet een geheel getal zijn (zonder decimalen)", }) .positive({ - message: "De waarde moet groter zijn dan 0", - }) - .finite({ - message: "De waarde moet een geldig getal zijn", + message: "Het onderwatergewicht moet groter zijn dan 0", }) .min(100, { - message: - "Het onderwatergewicht mag niet kleiner zijn dan 100 g / 5 kg", + message: "Het onderwatergewicht mag niet kleiner zijn dan 100 g / 5 kg", }) .max(1000, { - message: - "Het onderwatergewicht mag niet groter zijn dan 1.000 g / 5 kg", - }) - .safe({ - message: "De waarde is buiten het toegestane bereik", + message: "Het onderwatergewicht mag niet groter zijn dan 1.000 g / 5 kg", }) .optional(), ), b_lu_moist: z.preprocess( - (val) => (val === "" ? undefined : val), - z.coerce - .number({ - invalid_type_error: "De waarde moet een getal zijn", + (val) => (val === "" ? undefined : typeof val === "string" ? Number(val) : val), + z.number({ + error: "Het vochtpercentage moet een getal zijn", + }) + .int({ + message: "Het vochtpercentage moet een geheel getal zijn (zonder decimalen)", }) .positive({ - message: "De waarde moet groter zijn dan 0", - }) - .finite({ - message: "De waarde moet een geldig getal zijn", + message: "Het vochtpercentage moet groter zijn dan 0", }) .max(100, { message: "Het vochtpercentage mag niet hoger zijn dan 100%", }) - .safe({ - message: "De waarde is buiten het toegestane bereik", - }) .optional(), - ), + ), b_lu_cp: z.preprocess( - (val) => (val === "" ? undefined : val), - z.coerce - .number({ - invalid_type_error: "De waarde moet een getal zijn", + (val) => (val === "" ? undefined : typeof val === "string" ? Number(val) : val), + z.number({ + error: "Het ruw eiwitgehalte moet een getal zijn", + }) + .int({ + message: "Het ruw eiwitgehalte moet een geheel getal zijn (zonder decimalen)", }) .positive({ - message: "De waarde moet groter zijn dan 0", - }) - .finite({ - message: "De waarde moet een geldig getal zijn", + message: "Het ruw eiwitgehalte moet groter zijn dan 0", }) .max(500, { - message: - "Het ruw eiwit gehalte mag niet groter zijn dan 500 g / kg DS", - }) - .safe({ - message: "De waarde is buiten het toegestane bereik", + message: "Het ruw eiwitgehalte mag niet groter zijn dan 500 g/kg DS", }) .optional(), ), - b_lu_start: z.coerce.date().optional().nullable(), - b_lu_end: z.coerce.date().optional().nullable(), + b_lu_start: z.preprocess( + (val) => (typeof val === "string" ? new Date(val) : val), + z.date().optional().nullable(), + ), + b_lu_end: z.preprocess( + (val) => (typeof val === "string" ? new Date(val) : val), + z.date().optional().nullable(), + ), b_lu_harvestable: z.enum(["once", "multiple", "none"]), }) .superRefine((data, ctx) => { @@ -216,7 +183,7 @@ export const FormSchema = z data.b_lu_harvest_date <= data.b_lu_start ) { ctx.addIssue({ - code: z.ZodIssueCode.custom, + code: "custom", message: `De oogstdatum mag niet vóór de start van de teelt (${format(data.b_lu_start, "PP", { locale: nl })}) vallen`, path: ["b_lu_harvest_date"], }) @@ -228,7 +195,7 @@ export const FormSchema = z data.b_lu_harvestable === "multiple" ) { ctx.addIssue({ - code: z.ZodIssueCode.custom, + code: "custom", message: `De oogstdatum mag niet ná het einde van de teelt (${format(data.b_lu_end, "PP", { locale: nl })}) vallen`, path: ["b_lu_harvest_date"], }) diff --git a/fdm-app/app/components/blocks/mijnpercelen/form-upload.tsx b/fdm-app/app/components/blocks/mijnpercelen/form-upload.tsx index ce6ad2ca6..584c22b41 100644 --- a/fdm-app/app/components/blocks/mijnpercelen/form-upload.tsx +++ b/fdm-app/app/components/blocks/mijnpercelen/form-upload.tsx @@ -460,7 +460,7 @@ export const FormSchema = z.object({ (file) => file.size > 0 && file.size <= fileSizeLimit, ), { - message: "Een of meerdere bestanden zijn ongeldig of te groot.", + error: "Een of meerdere bestanden zijn ongeldig of te groot.", }, ) .refine( @@ -476,8 +476,7 @@ export const FormSchema = z.object({ ) }, { - message: - "Een of meerdere bestanden hebben een ongeldig bestandstype.", + error: "Een of meerdere bestanden hebben een ongeldig bestandstype.", }, ) .refine( @@ -490,8 +489,7 @@ export const FormSchema = z.object({ ) }, { - message: - "Zorg ervoor dat u een .shp, .shx, .dbf, en .prj bestand selecteert.", + error: "Zorg ervoor dat u een .shp, .shx, .dbf, en .prj bestand selecteert.", }, ), }) diff --git a/fdm-app/app/components/blocks/organic-certification/schema.ts b/fdm-app/app/components/blocks/organic-certification/schema.ts index 669f5a2d0..0e3a7e174 100644 --- a/fdm-app/app/components/blocks/organic-certification/schema.ts +++ b/fdm-app/app/components/blocks/organic-certification/schema.ts @@ -32,22 +32,28 @@ export const formSchema = z .trim() .optional() .refine((val) => !val || isValidTracesNumber(val), { - message: "Ongeldig TRACES-nummer", + error: "Ongeldig TRACES-nummer", }), b_organic_skal: z .string() .trim() .optional() .refine((val) => !val || isValidSkalNumber(val), { - message: "Ongeldig SKAL-nummer", + error: "Ongeldig SKAL-nummer", }), - b_organic_issued: z.coerce.date({ - required_error: "Startdatum is verplicht", - invalid_type_error: "Ongeldige datum", - }), + b_organic_issued: z.preprocess( + (val) => (typeof val === "string" ? new Date(val) : val), + z.date({ + error: (issue) => + issue.input === undefined + ? "Startdatum is verplicht" + : "Ongeldige datum", + }), + ), b_organic_expires: z.coerce .date({ - invalid_type_error: "Ongeldige datum", + error: (issue) => + issue.input === undefined ? undefined : "Ongeldige datum", }) .optional(), }) @@ -62,11 +68,11 @@ export const formSchema = z return true }, { - message: "Startdatum kan niet na einddatum liggen", path: ["b_organic_issued"], + error: "Startdatum kan niet na einddatum liggen", }, ) .refine((data) => !!(data.b_organic_traces || data.b_organic_skal), { - message: "Vul een TRACES- of SKAL-nummer in", path: ["b_organic_traces"], + error: "Vul een TRACES- of SKAL-nummer in", }) diff --git a/fdm-app/app/components/blocks/rotation/schema.ts b/fdm-app/app/components/blocks/rotation/schema.ts index b399584d7..b1978ac67 100644 --- a/fdm-app/app/components/blocks/rotation/schema.ts +++ b/fdm-app/app/components/blocks/rotation/schema.ts @@ -37,8 +37,8 @@ export const RotationTableFormSchema = z return true }, { - message: "Einddatum moet na de zaaidatum liggen.", path: ["b_lu_end"], + error: "Einddatum moet na de zaaidatum liggen.", }, ) diff --git a/fdm-app/app/components/blocks/soil/form-upload.tsx b/fdm-app/app/components/blocks/soil/form-upload.tsx index f863bbb8b..9f842ae75 100644 --- a/fdm-app/app/components/blocks/soil/form-upload.tsx +++ b/fdm-app/app/components/blocks/soil/form-upload.tsx @@ -257,12 +257,12 @@ export const FormSchema = z.object({ soilAnalysisFile: z .instanceof(File) .refine((file) => ["application/pdf"].includes(file.type), { - message: "Ongeldig bestandstype", + error: "Ongeldig bestandstype", }) .refine((file) => file.size > 0, { - message: "Bestand is ongeldig", + error: "Bestand is ongeldig", }) .refine((file) => file.size <= fileSizeLimit, { - message: "Bestand mag niet groter zijn dan 5MB", + error: "Bestand mag niet groter zijn dan 5MB", }), }) diff --git a/fdm-app/app/components/blocks/soil/formschema.tsx b/fdm-app/app/components/blocks/soil/formschema.tsx index ed2e007d5..5c607fe8e 100644 --- a/fdm-app/app/components/blocks/soil/formschema.tsx +++ b/fdm-app/app/components/blocks/soil/formschema.tsx @@ -4,21 +4,31 @@ export const FormSchema = z .object({ a_source: z .string({ - invalid_type_error: "Laboratorium is ongeldig", - required_error: "Kies een laboratorium", + error: (issue) => + issue.input === undefined + ? "Kies een laboratorium" + : "Laboratorium is ongeldig", }) .refine((value) => value.toLowerCase() !== "nl-other-nmi", { - message: "Bron mag niet 'NMI BodemSchat' zijn.", + error: "Bron mag niet 'NMI BodemSchat' zijn.", }), - b_sampling_date: z.coerce.date({ - invalid_type_error: "Datum is ongeldig", - required_error: "Vul een datum in", - }), + b_sampling_date: z.preprocess( + (val) => (typeof val === "string" ? new Date(val) : val), + z.date({ + error: (issue) => + issue.input === undefined + ? "Vul een datum in" + : "Datum is ongeldig", + }), + ), a_depth_upper: z.preprocess( (val) => (val === "" ? undefined : val), z.coerce .number({ - invalid_type_error: "Waarde moet een getal zijn", + error: (issue) => + issue.input === undefined + ? undefined + : "Waarde moet een getal zijn", }) .gte(0, "Waarde moet groter of gelijk aan 0 zijn") .lte(200, "Waarde moet kleiner of gelijk aan 200 zijn") @@ -26,8 +36,10 @@ export const FormSchema = z ), a_depth_lower: z.coerce .number({ - invalid_type_error: "Waarde moet een getal zijn", - required_error: "Vul in tot hoe diep is bemonsterd", + error: (issue) => + issue.input === undefined + ? "Vul in tot hoe diep is bemonsterd" + : "Waarde moet een getal zijn", }) .gte(1, "Waarde moet groter of gelijk aan 1 zijn") .lte(200, "Waarde moet kleiner of gelijk aan 200 zijn"), @@ -318,8 +330,7 @@ export const FormSchema = z return true }, { - message: - "Bovenkant van bemonsterde laag moet minder diep zijn dan onderkant", path: ["a_depth_upper"], + error: "Bovenkant van bemonsterde laag moet minder diep zijn dan onderkant", }, ) diff --git a/fdm-app/app/integrations/nmi.ts b/fdm-app/app/integrations/nmi.ts index ab2d0f04e..23a96599a 100644 --- a/fdm-app/app/integrations/nmi.ts +++ b/fdm-app/app/integrations/nmi.ts @@ -99,7 +99,7 @@ export async function getSoilParameterEstimates( if (!parsedResponse.success) { console.error( "NMI API response validation failed:", - JSON.stringify(parsedResponse.error.format(), null, 2), + JSON.stringify(z.treeifyError(parsedResponse.error), null, 2), ) throw new Error( `Invalid response from NMI API: ${parsedResponse.error.message}`, diff --git a/fdm-app/app/lib/schemas/access.schema.ts b/fdm-app/app/lib/schemas/access.schema.ts index 787b4b14b..bd9d540af 100644 --- a/fdm-app/app/lib/schemas/access.schema.ts +++ b/fdm-app/app/lib/schemas/access.schema.ts @@ -1,7 +1,7 @@ import { z } from "zod" export const AccessFormSchema = z.object({ - email: z.string().email().optional(), + email: z.email().optional(), username: z.string().optional(), role: z.enum(["owner", "advisor", "researcher"]).optional(), intent: z.enum(["invite_user", "update_role", "remove_user"]), diff --git a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.overview.tsx b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.overview.tsx index 8d0b330b9..b9bdf8f3a 100644 --- a/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.overview.tsx +++ b/fdm-app/app/routes/farm.$b_id_farm.$calendar.field.$b_id.overview.tsx @@ -243,7 +243,9 @@ export default function FarmFieldsOverviewBlock() { @@ -345,15 +347,23 @@ export async function action({ request, params }: ActionFunctionArgs) { const FormSchema = z .object({ b_name: z.string().min(2, { - message: "Naam van perceel moet minimaal 2 karakters bevatten", + error: "Naam van perceel moet minimaal 2 karakters bevatten", }), b_acquiring_method: z.string({ - required_error: - "Selecteer of het perceel in eigendom is of gepacht", - }), - b_start: z.coerce.date({ - required_error: "Kies een startdatum voor het perceel", + error: (issue) => + issue.input === undefined + ? "Selecteer of het perceel in eigendom is of gepacht" + : undefined, }), + b_start: z.preprocess( + (val) => (typeof val === "string" ? new Date(val) : val), + z.date({ + error: (issue) => + issue.input === undefined + ? "Kies een startdatum voor het perceel" + : undefined, + }), + ), b_end: z.coerce.date().nullable().optional(), b_bufferstrip: z.boolean().optional(), }) @@ -365,7 +375,7 @@ const FormSchema = z return true }, { - message: "Einddatum moet na de startdatum zijn", path: ["b_end"], + error: "Einddatum moet na de startdatum zijn", }, ) diff --git a/fdm-app/app/routes/farm.$b_id_farm.settings.properties.tsx b/fdm-app/app/routes/farm.$b_id_farm.settings.properties.tsx index 519c0b6ce..0d7e2c132 100644 --- a/fdm-app/app/routes/farm.$b_id_farm.settings.properties.tsx +++ b/fdm-app/app/routes/farm.$b_id_farm.settings.properties.tsx @@ -327,7 +327,7 @@ export async function action({ request, params }: ActionFunctionArgs) { // Form Schema const FormSchema = z.object({ b_name_farm: z.string().min(3, { - message: "Naam van bedrijf moet minimaal 3 karakters bevatten", + error: "Naam van bedrijf moet minimaal 3 karakters bevatten", }), b_businessid_farm: z.string().optional(), b_address_farm: z.string().optional(), @@ -335,6 +335,6 @@ const FormSchema = z.object({ .string() .optional() .refine((value) => !value || isPostalCode(value, "NL"), { - message: "Ongeldige postcode", + error: "Ongeldige postcode", }), }) diff --git a/fdm-app/app/routes/farm.create._index.tsx b/fdm-app/app/routes/farm.create._index.tsx index 16a930e8e..dd1567a47 100644 --- a/fdm-app/app/routes/farm.create._index.tsx +++ b/fdm-app/app/routes/farm.create._index.tsx @@ -67,23 +67,31 @@ export const meta: MetaFunction = () => { const FormSchema = z.object({ b_name_farm: z .string({ - required_error: "Naam van bedrijf is verplicht", + error: (issue) => + issue.input === undefined + ? "Naam van bedrijf is verplicht" + : undefined, }) .min(3, { - message: "Naam van bedrijf moet minimaal 3 karakters bevatten", + error: "Naam van bedrijf moet minimaal 3 karakters bevatten", }), - year: z.coerce.number({ - required_error: "Jaar is verplicht", - invalid_type_error: "Jaar moet een getal zijn", - }), - has_derogation: z.coerce.boolean().default(false), + year: z.preprocess( + (val) => (typeof val === "string" && val !== "" ? Number(val) : val), + z.number({ + error: (issue) => + issue.input === undefined + ? "Jaar is verplicht" + : "Jaar moet een getal zijn", + }), + ), + has_derogation: z.coerce.boolean().prefault(false), derogation_start_year: z.coerce .number() .min(2006, { - message: "Startjaar moet minimaal 2006 zijn", + error: "Startjaar moet minimaal 2006 zijn", }) .max(2025, { - message: "Startjaar mag maximaal 2025 zijn", + error: "Startjaar mag maximaal 2025 zijn", }) .optional(), }) diff --git a/fdm-app/app/routes/organization.$slug.tsx b/fdm-app/app/routes/organization.$slug.tsx index 31c8d8b5b..1070f1ff5 100644 --- a/fdm-app/app/routes/organization.$slug.tsx +++ b/fdm-app/app/routes/organization.$slug.tsx @@ -1,4 +1,3 @@ -import type { User } from "better-auth" import type { Invitation, Member, Organization } from "better-auth/plugins" import { formatDistanceToNow } from "date-fns" import { nl } from "date-fns/locale" @@ -363,7 +362,7 @@ const InvitationForm = ({ } const FormSchema = z.object({ - email: z.string().email().optional(), + email: z.email().optional(), role: z.enum(["owner", "admin", "member"]).optional(), memberId: z.string().optional(), invitation_id: z.string().optional(), diff --git a/fdm-app/app/routes/organization.new.tsx b/fdm-app/app/routes/organization.new.tsx index 8fa5ef05b..aa4b60019 100644 --- a/fdm-app/app/routes/organization.new.tsx +++ b/fdm-app/app/routes/organization.new.tsx @@ -1,10 +1,6 @@ import { zodResolver } from "@hookform/resolvers/zod" import { useEffect } from "react" -import { - type ActionFunctionArgs, - Form, - type MetaFunction, -} from "react-router" +import { type ActionFunctionArgs, Form, type MetaFunction } from "react-router" import { RemixFormProvider, useRemixForm } from "remix-hook-form" import { dataWithError, redirectWithSuccess } from "remix-toast" import { z } from "zod" @@ -46,19 +42,23 @@ export const meta: MetaFunction = () => { const FormSchema = z.object({ name: z .string({ - required_error: "Naam van de organisatie is verplicht", + error: (issue) => + issue.input === undefined + ? "Naam van de organisatie is verplicht" + : undefined, }) .min(3, { - message: - "Naam van de organisatie moet minimaal 3 karakters bevatten", + error: "Naam van de organisatie moet minimaal 3 karakters bevatten", }), slug: z .string({ - required_error: "ID de organisatie is verplicht", + error: (issue) => + issue.input === undefined + ? "ID de organisatie is verplicht" + : undefined, }) .refine(isValidSlug, { - message: - "ID moet minimaal 3 karakters bevatten, enkel kleine letters, cijfers of '-'", + error: "ID moet minimaal 3 karakters bevatten, enkel kleine letters, cijfers of '-'", }), description: z.string({}).optional(), }) diff --git a/fdm-app/app/routes/signin._index.tsx b/fdm-app/app/routes/signin._index.tsx index ab36c738b..d00114f73 100644 --- a/fdm-app/app/routes/signin._index.tsx +++ b/fdm-app/app/routes/signin._index.tsx @@ -126,14 +126,9 @@ export const links: LinksFunction = () => { const FormSchema = z.object({ timeZone: z.string().optional(), - email: z.coerce - .string({ - required_error: - "Voor aanmelden met e-mail hebben we je e-mailadres nodig", - }) - .email({ - message: "Dit is geen geldig e-mailadres", - }), + email: z.email({ + error: "Dit is geen geldig e-mailadres", + }), }) /** diff --git a/fdm-app/app/routes/welcome.tsx b/fdm-app/app/routes/welcome.tsx index 7fe9e76f7..9b45bfa12 100644 --- a/fdm-app/app/routes/welcome.tsx +++ b/fdm-app/app/routes/welcome.tsx @@ -47,19 +47,21 @@ export const meta: MetaFunction = () => { } const FormSchema = z.object({ - firstname: z.coerce + firstname: z .string({ - required_error: "Vul je voornaam in", + error: (issue) => + issue.input === undefined ? "Vul je voornaam in" : undefined, }) .min(1, { - message: "Vul je voornaam in", + error: "Vul je voornaam in", }), - surname: z.coerce + surname: z .string({ - required_error: "Vul je achternaam in", + error: (issue) => + issue.input === undefined ? "Vul je achternaam in" : undefined, }) .min(1, { - message: "Vul je achternaam in", + error: "Vul je achternaam in", }), }) diff --git a/fdm-app/package.json b/fdm-app/package.json index 294c6303a..8254a294f 100644 --- a/fdm-app/package.json +++ b/fdm-app/package.json @@ -87,7 +87,7 @@ "tailwind-merge": "^3.4.0", "tailwindcss-animate": "^1.0.7", "validator": "^13.15.26", - "zod": "^3.25.76", + "zod": "^4.3.6", "zustand": "^5.0.10" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 40f8411b4..9232079e7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -299,8 +299,8 @@ importers: specifier: ^13.15.26 version: 13.15.26 zod: - specifier: ^3.25.76 - version: 3.25.76 + specifier: ^4.3.6 + version: 4.3.6 zustand: specifier: ^5.0.10 version: 5.0.10(@types/react@19.2.8)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) @@ -11149,12 +11149,12 @@ packages: yoga-layout@3.2.1: resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==} - zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.3.5: resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zstddec@0.1.0: resolution: {integrity: sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==} @@ -12178,20 +12178,20 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@better-auth/core@1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@3.25.76))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)': + '@better-auth/core@1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)': dependencies: '@better-auth/utils': 0.3.0 '@better-fetch/fetch': 1.1.21 '@standard-schema/spec': 1.1.0 - better-call: 1.1.8(zod@4.3.5) + better-call: 1.1.8(zod@4.3.6) jose: 6.1.3 kysely: 0.28.10 nanostores: 1.1.0 - zod: 4.3.5 + zod: 4.3.6 - '@better-auth/telemetry@1.4.15(@better-auth/core@1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@3.25.76))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))': + '@better-auth/telemetry@1.4.15(@better-auth/core@1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0))': dependencies: - '@better-auth/core': 1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@3.25.76))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0) + '@better-auth/core': 1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0) '@better-auth/utils': 0.3.0 '@better-fetch/fetch': 1.1.21 @@ -18248,18 +18248,18 @@ snapshots: better-auth@1.4.15(drizzle-kit@0.31.8)(drizzle-orm@0.45.1(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(kysely@0.28.10)(postgres@3.4.8))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(vitest@4.0.17(@opentelemetry/api@1.9.0)(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(yaml@2.8.2)): dependencies: - '@better-auth/core': 1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@3.25.76))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0) - '@better-auth/telemetry': 1.4.15(@better-auth/core@1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@3.25.76))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)) + '@better-auth/core': 1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0) + '@better-auth/telemetry': 1.4.15(@better-auth/core@1.4.15(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.10)(nanostores@1.1.0)) '@better-auth/utils': 0.3.0 '@better-fetch/fetch': 1.1.21 '@noble/ciphers': 2.1.1 '@noble/hashes': 2.0.1 - better-call: 1.1.8(zod@4.3.5) + better-call: 1.1.8(zod@4.3.6) defu: 6.1.4 jose: 6.1.3 kysely: 0.28.10 nanostores: 1.1.0 - zod: 4.3.5 + zod: 4.3.6 optionalDependencies: drizzle-kit: 0.31.8 drizzle-orm: 0.45.1(@electric-sql/pglite@0.3.15)(@opentelemetry/api@1.9.0)(@types/pg@8.15.6)(kysely@0.28.10)(postgres@3.4.8) @@ -18267,14 +18267,14 @@ snapshots: react-dom: 19.2.3(react@19.2.3) vitest: 4.0.17(@opentelemetry/api@1.9.0)(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(yaml@2.8.2) - better-call@1.1.8(zod@4.3.5): + better-call@1.1.8(zod@4.3.6): dependencies: '@better-auth/utils': 0.3.0 '@better-fetch/fetch': 1.1.21 rou3: 0.7.12 set-cookie-parser: 2.7.2 optionalDependencies: - zod: 4.3.5 + zod: 4.3.6 better-path-resolve@1.0.0: dependencies: @@ -22793,7 +22793,7 @@ snapshots: remix-toast@4.0.0(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)): dependencies: react-router: 7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - zod: 4.3.5 + zod: 4.3.6 remix-utils@9.0.0(@standard-schema/spec@1.1.0)(react-router@7.12.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(react@19.2.3): dependencies: @@ -24238,10 +24238,10 @@ snapshots: yoga-layout@3.2.1: {} - zod@3.25.76: {} - zod@4.3.5: {} + zod@4.3.6: {} + zstddec@0.1.0: {} zustand@5.0.10(@types/react@19.2.8)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)):