Guides
Plugins and Hooks
Add a Mongoose plugin or customize conversion with the hook system.
Plugins and Hooks
Use a Mongoose plugin to change one generated schema. Use a conversion hook when you need to inspect or change conversion across schemas.
Mongoose Plugins
Pass plugins in the second argument to toMongooseSchema(). This example uses a local plugin so you can see exactly what gets applied.
post-plugin.ts
import mongoose from 'mongoose';
import {z} from 'zod/v4';
import {toMongooseSchema} from '@nullix/zod-mongoose';
const PostZodSchema = z.object({title: z.string()});
const slugPlugin = (schema: mongoose.Schema) => {
schema.virtual('slug').get(function () {
return String(this.get('title')).toLowerCase().replaceAll(' ', '-');
});
};
const PostMongooseSchema = toMongooseSchema(PostZodSchema, {
plugins: [slugPlugin],
});
const Post = mongoose.model('Post', PostMongooseSchema);
console.log(new Post({title: 'Hello World'}).get('slug')); // hello-world
Hook System
The package uses hookable for conversion hooks. Register a hook before converting a schema. Hooks are shared, so unregister a temporary hook after use.
Registering Hooks
uppercase-fields.ts
import {hooks} from '@nullix/zod-mongoose';
// Modify every string field to be uppercase at the Mongoose level
const unregister = hooks.hook('converter:node', (context) => {
if (context.type === 'string') {
context.mongooseProp.uppercase = true;
}
});
// Call unregister() when the customization should stop applying.
Advanced Hook: schema:created
The callback receives the source Zod schema as schema and the generated Mongoose schema as mongooseSchema.
schema-created.ts
import {z} from 'zod/v4';
import {hooks, toMongooseSchema} from '@nullix/zod-mongoose';
const unregister = hooks.hook('schema:created', ({schema, mongooseSchema}) => {
if (schema instanceof z.ZodObject && 'title' in schema.shape) {
mongooseSchema.virtual('slug').get(function () {
return String(this.get('title')).toLowerCase().replaceAll(' ', '-');
});
}
});
const PostZodSchema = z.object({title: z.string()});
const PostMongooseSchema = toMongooseSchema(PostZodSchema);
unregister();
Available Hooks
The following hook points are available:
converter:before: Called before starting the conversion.converter:start: Called at the start of eachextractMongooseDefcall (recursive).converter:unwrapped: Called after unwrapping a Zod schema and extracting metadata.converter:node: Called for each Zod type node being processed.converter:after: Called after a node's conversion is complete.schema:object:before: Called before processing az.object().schema:object:field: Called for each field in az.object().schema:object:after: Called after processing az.object().schema:array:before: Called before processing an array-like type (z.array(),z.set(),z.tuple()).schema:array:after: Called after processing an array-like type.schema:record:before: Called before processing a record/map type (z.record(),z.map()).schema:record:after: Called after processing a record/map type.schema:union:before: Called before processing az.union()orz.discriminatedUnion().schema:union:after: Called after processing a union.validation:mappers: Called after mapping Zod validations to Mongoose options.schema:created: Called after amongoose.Schemainstance is created.