v3.3.1
Playground
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 each extractMongooseDef call (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 a z.object().
  • schema:object:field: Called for each field in a z.object().
  • schema:object:after: Called after processing a z.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 a z.union() or z.discriminatedUnion().
  • schema:union:after: Called after processing a union.
  • validation:mappers: Called after mapping Zod validations to Mongoose options.
  • schema:created: Called after a mongoose.Schema instance is created.