Skip to Content
Examples

Examples

See Monkko in action with these practical examples that showcase its key features.

Pre-v1 Notice: Monkko is currently in pre-v1 development. The API may change between releases. We recommend pinning to specific versions in production environments.

Basic Schema Definition

Here’s what working with Monkko looks like:

1. Define Your Schema

// schemas/User.monkko.ts import { defineSchema, fields } from '@monkko/orm' export const User = defineSchema({ name: "User", db: "myapp", collection: "users", fields: { name: fields.string({ required: true }), email: fields.string({ required: true, unique: true }), age: fields.number({ optional: true }), organisation: fields.objectId({ required: false, ref: "Organisation" }) createdAt: fields.date({ default: () => new Date() }) } });

2. Generate Types & Validation

# Run the CLI to generate everything you need pnpm monkko generate

This automatically creates:

  • ✅ TypeScript types for your models
  • ✅ Zod schemas for validation
  • ✅ Fully typed query builders

3. Use Your Fully-Typed Models

import { userModel } from './models/User' // ✨ Everything is typed with generics! const users = await userModel .find({ name: { $regex: /john/i } }) .populate("organisation") .toJSON(); // ← Handles serialization automatically // TypeScript knows the exact shape: // users: Array<{ // name: string; // email: string; // age?: number; // organisation: Organisation; // ← Populated! // createdAt: Date; // }>

💡 Info: Monkko uses generics for type safety throughout your query chain. The toJSON() function automatically handles serialization, so you don’t need to worry about manual type casting or serialization!

Multi-Database Architecture

Unlike other ORMs that assume a single database, Monkko is designed for MongoDB clusters where you have multiple databases. Each model connects to the correct database:

// Each model connects to the right database export const User = defineSchema({ name: "User", db: "users", // ← Connects to the users database collection: "users", fields: { /* ... */ } }); export const AnalyticsEvent = defineSchema({ name: "AnalyticsEvent", db: "analytics", // ← Different database, same cluster collection: "events", fields: { /* ... */ } });

Type Safety Examples

Stop casting to any and losing type safety. Monkko uses generics to preserve types through your entire query chain:

// Without populate - use toJSON() for proper serialization const user = await userModel.findById(userId).toJSON(); // user.organisation → ObjectId (string) // With populate - types automatically update const user = await userModel .findById(userId) .populate("organisation") .toJSON(); // user.organisation → Organisation (full object!) // Multiple populates - all handled with generics const post = await postModel .findById(postId) .populate("author") .populate("comments.user") .toJSON(); // TypeScript knows exactly what's populated!

🔥 Pro Tip: Always use .toJSON() at the end of your queries. It handles serialization automatically and ensures you get the correct TypeScript types without manual casting!

Last updated on