Skip to content

Concepts

Positioning

If you know the MongoDB driver, you know Mondel.

Mondel is a thin ODM (object–document mapper):

  1. You declare collections with defineSchema + s.*
  2. createClient exposes typed proxies (db.users)
  3. Writes are optionally validated with Zod derived from the schema
  4. Everything else is the official mongodb driver

There is no document class hierarchy, no global model registry, and no query language to re-learn.

Core ideas

1. Schema is the source of truth

From one schema definition Mondel derives:

ArtifactHow
Collection name on the clientSchema name (e.g. "users"db.users)
MongoDB collectioncollection option or same as name
TypeScript document shapeInferSchemaType<typeof schema>
Create / update input typesCreateInput / UpdateInput
Runtime validatorszodCreateSchema / zodUpdateSchema
Indexes & JSON SchemaCLI mondel push

2. Plain objects

findOne / findMany return plain documents (POJOs + BSON types like ObjectId / Date).
No hydration into model instances. Serialize with JSON.stringify as usual (ObjectIds need care).

3. Native filters

There is no Prisma-style where: { email: { contains: "a" } }.

Use MongoDB filter syntax:

typescript
await db.users.findMany({
  age: { $gte: 18, $lte: 65 },
  role: { $in: ["ADMIN", "USER"] },
  email: { $regex: /@example\.com$/i },
});

4. Validation boundary

OperationValidated?
create / createManyYes (mode-dependent)
Plain update objectsYes
$set / $setOnInsertYes
$inc, $push, $unset, …No (passed through)
find* / aggregateNo (reads trust stored data)
bulkWriteNo (use typed helpers when you need validation)

Modes: strict (throw ZodError), loose (warn), off (skip).

5. Timestamps are opt-in

timestamps: true adds createdAt / updatedAt management on create/update/upsert.
Disable per call with { timestamps: false }.

6. Indexes are a deploy concern

Creating indexes on every serverless cold start is an anti-pattern.
Mondel’s recommended path: npx mondel push in CI/deploy.

7. Escape hatch is first-class

typescript
const col = db.users.getCollection();
const stream = col.watch();
await col.createIndex({ email: 1 });

Anything missing on the proxy is one method away from the driver.

Type safety — honest scope

Mondel gives you:

  • Compile-time checks that collection names exist on the client
  • Typed field names in many helpers (select, create input shapes)
  • Runtime enforcement of formats (email, min/max, enums)

Mondel does not currently:

  • Narrow return types based on select projections (projection is applied at runtime; TypeScript still sees the full document type)
  • Force every .required() field as required in all inferred create types with perfect fidelity in every edge case

Prefer: “typed collections and validated writes” over “100% type-safe everything”.

Serverless mental model

createClient({ serverless: true })  →  lightweight factory (no I/O)
connect(uri)                        →  MongoClient.connect + proxy
request work                        →  CRUD
db.close()                          →  optional; platform/pool dependent

For connection limits and reuse patterns, see Client & Connections.

Released under the MIT License. · llms.txt