What is Monch?
Monch is a lightweight MongoDB ODM (Object Document Mapper) for TypeScript that combines the power of Zod validation with MongoDB operations. It provides a type-safe, developer-friendly way to work with MongoDB while ensuring data integrity through schema validation.
Why Monch?
The Problem
Working with MongoDB in TypeScript often involves:
- Manual type definitions that can drift from actual data
- No validation at the database boundary
- Tedious BSON serialization for frameworks like Next.js
- Boilerplate for common patterns like timestamps and pagination
The Solution
Monch addresses these issues with:
- Zod Schemas as Source of Truth - Your schema defines both validation rules and TypeScript types
- Automatic Validation - Documents are validated before insert, with partial validation on updates
- Built-in Serialization - Convert BSON types to JSON-safe values with a single
.serialize()call - Zero Configuration - Set
MONGODB_URIand start coding
Core Principles
1. Validation at the Boundary
Monch validates data at the database boundary—when documents enter MongoDB. This catches errors early and ensures data consistency:
typescript
// Invalid data is rejected before reaching MongoDB
await Users.insertOne({
name: '', // Throws: String must contain at least 1 character
email: 'not-an-email', // Throws: Invalid email
});2. Type Safety Throughout
Types flow from your Zod schema through queries to serialized output:
typescript
const Users = collection({
schema: {
_id: field.id(),
name: field.string(),
email: field.email(),
},
timestamps: true,
});
// TypeScript knows the shape
const user = await Users.findOne({ email: 'alice@example.com' });
// user: { _id: ObjectId, name: string, email: string, createdAt: Date, updatedAt: Date } | null
const serialized = user?.serialize();
// serialized: { _id: string, name: string, email: string, createdAt: string, updatedAt: string }3. Progressive Enhancement
Monch stays out of your way. Use as much or as little as you need:
typescript
// Basic: Just schema and name
const Simple = collection({
name: 'simple',
schema: { _id: field.id(), value: field.string() },
});
// Full-featured: Timestamps, hooks, methods, indexes
const Advanced = collection({
name: 'advanced',
schema: { /* ... */ },
timestamps: true,
indexes: [{ key: { email: 1 }, unique: true }],
hooks: { beforeInsert: (doc) => ({ ...doc, normalized: true }) },
methods: { fullName: (doc) => `${doc.first} ${doc.last}` },
});Comparison
| Feature | Monch | Mongoose | Prisma |
|---|---|---|---|
| TypeScript-first | ✅ | Partial | ✅ |
| Zod validation | ✅ | ❌ | ❌ |
| Zero config | ✅ | ❌ | ❌ |
| Serialization helpers | ✅ | ❌ | ❌ |
| Schema file required | ❌ | ❌ | ✅ |
| Code generation | ❌ | ❌ | ✅ |
| Bundle size | ~15KB | ~800KB | ~2MB |
Next Steps
- Getting Started - Install and create your first collection
- Schema Definition - Learn about defining schemas
- CRUD Operations - Query, insert, update, and delete