diff --git a/packages/better-auth/src/db/from-zod-types.ts b/packages/better-auth/src/db/from-zod-types.ts index e93f0b6d6b..9a6cba42ec 100644 --- a/packages/better-auth/src/db/from-zod-types.ts +++ b/packages/better-auth/src/db/from-zod-types.ts @@ -1,6 +1,9 @@ import type { DBFieldAttribute } from "@better-auth/core/db"; import type { ZodTypeAny, z } from "zod"; +/** + * Maps a single Zod type (z.ZodString, etc.) to a DBFieldType string ("string", etc.) + */ type MapZodType = T extends z.ZodString ? "string" : T extends z.ZodNumber diff --git a/packages/better-auth/src/db/from-zod.ts b/packages/better-auth/src/db/from-zod.ts index 8c6fa84275..452ff579fb 100644 --- a/packages/better-auth/src/db/from-zod.ts +++ b/packages/better-auth/src/db/from-zod.ts @@ -8,20 +8,27 @@ export function isZodObject(value: unknown): value is z.ZodObject { } try { return value instanceof z.ZodObject; - } catch { + } catch (err) { + console.error("Error in isZodObject check:", err); return false; } } export function isZodType(value: unknown): value is z.ZodTypeAny { if (!!value && typeof value === "object") { - const typeName = (value as any)?._def?.typeName; - if (typeof typeName === "string") return true; - if (typeof (value as any).parse === "function") return true; + const def = (value as any)?._def; + if ( + def && + typeof def.typeName === "string" && + typeof (value as any).parse === "function" + ) { + return true; + } } try { return value instanceof z.ZodType; - } catch { + } catch (err) { + console.error("Error in isZodType check:", err); return false; } } @@ -46,19 +53,22 @@ function getZodObjectShape(schema: z.ZodObject) { if (typeof maybeShape === "function") { try { return maybeShape(); - } catch {} + } catch (err) { + console.error("Error extracting Zod object shape", err); + } } return maybeShape; } function zodTypeToDBField(zodType: z.ZodTypeAny): DBFieldAttribute { let isOptional = false; + let isNullable = false; let innerType = zodType; let defaultValue: any = undefined; while (innerType && (innerType._def as any)) { const tn = (innerType._def as any)?.typeName; - if (tn === "ZodOptional" || tn === "ZodNullable") { + if (tn === "ZodOptional") { isOptional = true; innerType = (innerType._def as any).innerType ?? @@ -67,6 +77,15 @@ function zodTypeToDBField(zodType: z.ZodTypeAny): DBFieldAttribute { innerType; continue; } + if (tn === "ZodNullable") { + isNullable = true; + innerType = + (innerType._def as any).innerType ?? + (innerType._def as any).schema ?? + (innerType._def as any).type ?? + innerType; + continue; + } if (tn === "ZodDefault") { const dv = (innerType._def as any).defaultValue; @@ -137,8 +156,7 @@ function zodTypeToDBField(zodType: z.ZodTypeAny): DBFieldAttribute { }; if (defaultValue !== undefined) { - field.defaultValue = - typeof defaultValue === "function" ? defaultValue : () => defaultValue; + field.defaultValue = defaultValue; field.required = false; } diff --git a/packages/better-auth/src/db/schema.ts b/packages/better-auth/src/db/schema.ts index 5ea00f6841..a665472467 100644 --- a/packages/better-auth/src/db/schema.ts +++ b/packages/better-auth/src/db/schema.ts @@ -105,7 +105,6 @@ export function parseInputData>( if (fields[key]!.input === false) { if (fields[key]!.defaultValue !== undefined) { if (action !== "update") { - parsedData[key] = fields[key]!.defaultValue; const dv = fields[key]!.defaultValue as unknown; parsedData[key] = typeof dv === "function" ? (dv as () => unknown)() : dv; @@ -137,6 +136,10 @@ export function parseInputData>( if (validator["~standard"]) { parsedData[key] = validator["~standard"].validate(data[key]); continue; + } else { + throw new APIError("BAD_REQUEST", { + message: `${key}: Unsupported validator type`, + }); } } if (fields[key]!.transform?.input && data[key] !== undefined) {