You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm trying to add a handler for the zod schema. If the scheme contains an optional value, then it infer the unknown in the types, but if the optional value is nested, for example, inside another object, then it works correctly.
import { ObjectId } from "mongodb";
import { z } from "zod";
type ZodType = z.ZodType<any, any, any>;
/**
* Transforms a Zod schema to handle MongoDB ObjectId fields
* @param schema The Zod schema to transform
* @returns A new schema with transformed ID fields
*/
function createMongoSchema<T extends z.ZodObject<any, any, any>>(
schema: T
): z.ZodObject<
{
[k in keyof z.infer<T> as k extends "id" ? "_id" : k]: k extends "id"
? z.ZodType<ObjectId>
: k extends `${string}Id` | `${string}Ids`
? z.infer<T>[k] extends any[]
? z.ZodArray<z.ZodType<ObjectId>>
: z.ZodType<ObjectId>
: T["shape"][k] extends z.ZodOptional<infer U>
? z.ZodOptional<U extends z.ZodObject<any, any, any> ? ReturnType<typeof createMongoSchema<U>> : U>
: T["shape"][k];
},
"strip"
> {
if (!(schema instanceof z.ZodType)) {
return schema;
}
if (schema instanceof z.ZodObject) {
const shape = schema._def.shape();
const newShape: Record<string, ZodType> = {};
for (const [key, value] of Object.entries(shape)) {
if (isZodId(value as ZodType)) {
// Handle 'id' field specially
if (key === "id") {
newShape._id = z.instanceof(ObjectId);
continue;
}
// Handle other ID fields
newShape[key] = z.instanceof(ObjectId);
continue;
}
// Recursively transform nested objects and arrays
if (value instanceof z.ZodObject) {
newShape[key] = createMongoSchema(value);
} else if (value instanceof z.ZodArray) {
const elementSchema = value.element;
if (elementSchema instanceof z.ZodObject) {
newShape[key] = z.array(createMongoSchema(elementSchema));
} else if (isZodId(elementSchema)) {
newShape[key] = z.array(z.instanceof(ObjectId));
} else {
newShape[key] = value;
}
} else if (value instanceof z.ZodOptional) {
const innerSchema = value.unwrap();
if (innerSchema instanceof z.ZodObject) {
newShape[key] = z.optional(createMongoSchema(innerSchema));
} else if (isZodId(innerSchema)) {
newShape[key] = z.optional(z.instanceof(ObjectId));
} else {
newShape[key] = z.optional(innerSchema);
}
} else {
newShape[key] = value as ZodType;
}
}
return z.object(newShape) as any;
}
return schema;
}
/**
* Checks if a Zod type is created using zodId()
*/
function isZodId(schema: ZodType): boolean {
return (
schema instanceof z.ZodString &&
schema._def.checks.some((check) => check.kind === "regex" && check.regex.source === "^[a-f\\d]{24}$")
);
}
export { createMongoSchema };
I'm trying to add a handler for the zod schema. If the scheme contains an optional value, then it infer the unknown in the types, but if the optional value is nested, for example, inside another object, then it works correctly.
Any ideas how to fix this?
The text was updated successfully, but these errors were encountered: