Core Functions
Core Functions
These functions form the core of the @nullix/zod-mongoose library, allowing you to convert Zod definitions into Mongoose-compatible schemas and definitions.
toMongooseSchema(zodSchema, options?)
Converts a Zod schema to a Mongoose schema instance (new mongoose.Schema(...)).
- zodSchema: A Zod object or any Zod type.
- options: Optional Mongoose
SchemaOptions.- validateBeforeSave: (Boolean) When
true(default), automatically runszodSchema.parse()in a Mongoosepost('validate')hook. This ensures all Zod validations (like.refine(),.transform(), etc.) are executed during Mongoose validation.
- validateBeforeSave: (Boolean) When
import { z } from 'zod/v4';
import { toMongooseSchema } from '@nullix/zod-mongoose';
const zodSchema = z.object({
name: z.string(),
});
// Basic conversion with timestamps enabled
const mongooseSchema = toMongooseSchema(zodSchema, { timestamps: true });
// Disable automatic Zod validation
const mongooseSchemaNoVal = toMongooseSchema(zodSchema, { validateBeforeSave: false });
Note: This function replaces the deprecated
toZodMongooseSchema(). It now returns a fullmongoose.Schemainstance directly.
Automatic Zod Validation
toMongooseSchema automatically adds a Mongoose post('validate') hook that runs zodSchema.parse(this.toObject()). This is crucial because many Zod features (like custom refinements, transformations, and complex unions) cannot be directly mapped to Mongoose schema options.
If a Zod validation fails, the hook throws an error with a JSON-formatted message containing:
context: Includesmodelname and documentid.errors: An array of Zod issues.
To disable this behavior, set validateBeforeSave: false in the schema options or via withMongoose metadata.
extractMongooseDef(zodSchema)
Converts a Zod schema to a Mongoose schema definition object (the POJO used as the first argument for new mongoose.Schema(...)). This is useful if you want to manually create the Mongoose schema, combine it with other definitions, or use it with Mongoose's .add() method.
import { z } from 'zod/v4';
import { extractMongooseDef } from '@nullix/zod-mongoose';
const zodSchema = z.object({
name: z.string(),
});
const definition = extractMongooseDef(zodSchema);
// Result: { name: { type: String, required: true } }
withMongoose(zodSchema, metadata)
Attaches Mongoose-specific metadata to any Zod schema. MongooseMeta extends Mongoose's SchemaTypeOptions<any> and SchemaOptions, allowing you to specify both field-level options and top-level schema options.
- metadata: A
MongooseMetaobject.
Field-level metadata
import { z } from 'zod/v4';
import { withMongoose } from '@nullix/zod-mongoose';
const zodSchema = z.object({
username: withMongoose(z.string(), {
unique: true,
index: true,
lowercase: true
}),
});
Schema-level metadata
You can also apply schema-level options (like disabling _id or setting a collection name) by wrapping the top-level Zod object.
const LogSchema = withMongoose(
z.object({ message: z.string() }),
{ _id: false, id: false, collection: 'system_logs' }
);
Explicit Subschemas
By default, nested Zod objects are mapped to separate Mongoose subschemas (with their own _id, middleware, etc.). If you want a nested object to be a simple nested document (POJO), use schema: false.
const UserSchema = z.object({
profile: withMongoose(
z.object({ bio: z.string() }),
{ schema: false }
),
});
You can also pass SchemaOptions to the schema property to customize the subschema:
const UserSchema = z.object({
profile: withMongoose(
z.object({ bio: z.string() }),
{ schema: { _id: true, timestamps: true } }
),
});
Note: To define a custom Mongoose type, use
withMongoose(zodSchema, { type: 'YourType' })instead of the deprecatedmongooseZodCustomType().
z.infer<T> / mz.infer<T>
@nullix/zod-mongoose provides a specialized z object (and mz alias) that overrides the standard z.infer to automatically include the _id: mongoose.Types.ObjectId field in the inferred type. This ensures that your TypeScript types accurately reflect the structure of a Mongoose document.
import { z } from '@nullix/zod-mongoose';
const UserSchema = z.object({
name: z.string(),
});
// User type will automatically include { _id: mongoose.Types.ObjectId }
type User = z.infer<typeof UserSchema>;
const user: User = {
_id: new mongoose.Types.ObjectId(),
name: 'John Doe',
};
This helper is available in both backend and frontend environments. In the browser, _id will be typed as a string unless mongoose types are available.