Correct Zod type-level and runtime logic

Signed-off-by: GautamBytes <manchandanigautam@gmail.com>
This commit is contained in:
GautamBytes
2025-11-09 13:53:44 +00:00
parent 70334a2b68
commit 5eb3669ea5
3 changed files with 34 additions and 10 deletions

View File

@@ -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 ZodTypeAny> = T extends z.ZodString
? "string"
: T extends z.ZodNumber

View File

@@ -8,20 +8,27 @@ export function isZodObject(value: unknown): value is z.ZodObject<any> {
}
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<any>) {
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;
}

View File

@@ -105,7 +105,6 @@ export function parseInputData<T extends Record<string, any>>(
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<T extends Record<string, any>>(
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) {