MONDEL LLM REFERENCE (v0.3.x) ============================= Purpose ------- Mondel is a lightweight TypeScript ODM for MongoDB: - schema via defineSchema + s.* field builders - typed collection access via createClient - runtime Zod validation on writes - CLI pull/push for indexes and JSON Schema validators - thin wrapper: native MongoDB filters/operators stay first-class Positioning ----------- "If you know the MongoDB driver, you know Mondel." NOT Mongoose (no middleware/virtuals/populate). NOT Prisma (no relation engine / full migrations). Escape hatch: collection.getCollection(). Install ------- npm install mondel mongodb zod Peers: mongodb ^6 || ^7, zod ^3.24 || ^4 Node >= 18 (Node >= 20 recommended with mongodb@7) MongoDB server 6.x–8.x Core schema ----------- import { defineSchema, s } from "mondel"; const userSchema = defineSchema("users", { collection: "users", timestamps: true, fields: { email: s.string().required().email().unique(), name: s.string(), role: s.enum(["ADMIN", "USER"]).default("USER"), age: s.number().min(0), meta: s.object({ active: s.boolean() }), tags: s.array(s.string()), authorId: s.objectId(), location: s.object({ type: s.literal("Point"), coordinates: s.array(s.number()), }).index({ type: "2dsphere" }), }, indexes: [ { fields: { role: 1, createdAt: -1 }, options: { name: "idx_role_created" } }, ], }); export const schemas = [userSchema] as const; // REQUIRED for typed client Field builders: s.string, s.number, s.boolean, s.date, s.objectId, s.array, s.object, s.json, s.literal, s.enum Modifiers: .required .unique .default .index .min .max .email .url .pattern _id is implicit (ObjectId). Do not define _id in fields. Client ------ import { createClient, type SchemasToClient } from "mondel"; // Serverless factory const connect = createClient({ serverless: true, schemas, validation: "strict", // "strict" | "loose" | "off" }); const db = await connect(process.env.MONGODB_URI!); // optional: connect(uri, mongoClientOptions) // Node singleton const db2 = await createClient({ uri: process.env.MONGODB_URI!, schemas, validation: "strict", options: { maxPoolSize: 20 }, }); type DbClient = SchemasToClient; // db.close(), db.getDb(), db.startSession() syncIndexes on createClient is DEPRECATED. Use CLI push. Collection methods ------------------ findOne(where?, options?) findMany(where?, options?) findById(id, options?) create(data, options?) // returns InsertOneResult (insertedId), NOT full doc createMany(data[], options?) // empty array => no-op, insertedCount 0 updateOne(where, data, options?) updateMany(where, data, options?) updateById(id, data, options?) findOneAndUpdate(where, data, options?) bulkWrite(operations, options?) deleteOne(where, options?) // options.soft=true => set deletedAt deleteMany(where, options?) deleteById(id, options?) count(where?, options?) exists(where, options?) aggregate(pipeline, options?) getCollection() Find options: select (runtime projection ONLY — TS type NOT narrowed), sort, skip, limit, session, timeoutMS, and other driver find options. Update options: upsert, timestamps, session, ... Delete options: session, soft Create options: timestamps, session, ... Validation rules ---------------- - create/createMany: Zod create schema; applies .default() at all nesting levels; keeps unknown keys - plain update + $set + $setOnInsert: Zod update schema; does NOT apply defaults (any nesting) - validation off: no defaults applied - $inc $push $unset etc: not validated - bulkWrite: not validated - reads: not validated - strict throws ZodError; loose warns; off skips - soft delete deletedCount = matchedCount Timestamps ---------- timestamps: true => createdAt/updatedAt managed timestamps: false on call disables for that operation upsert sets createdAt via $setOnInsert Soft delete ----------- deleteOne(filter, { soft: true }) sets deletedAt (+ updatedAt if timestamps) Reads are NOT auto-filtered — add deletedAt: { $exists: false } Filters ------- Use native MongoDB filter documents: { age: { $gte: 18 }, role: { $in: ["ADMIN", "USER"] } } Types ----- import type { InferSchemaType, CreateInput, UpdateInput, SchemasToClient, MondelCliConfig, } from "mondel"; import { ObjectId } from "mondel"; // prefer over duplicate bson CLI --- npx mondel pull | push | help --config, --uri (database from URI) pull: --format ts|json, --out, --out-dir, --per-collection Infers fields from ONE sample doc per collection (bootstrap only). push: --schema , --manifest, --export schemas, --apply-validators, --drop-indexes, --dry-run Prefer compiled JS exporting schemas array. Config (MondelCliConfig): { uri?: string, pull?: { uri?, format?, outFile?, outDir?, perCollectionFiles? }, push?: { uri?, schemaFile?, manifestFile?, schemaExport?, applyValidators?, dropIndexes?, dryRun? } } Best practices -------------- - schemas as const - push indexes in CI/deploy, not cold start - getCollection() for watch/distinct/advanced - multi-DB = multiple createClient calls - transactions need replica set; pass { session } - MongoDB 8: null queries no longer match undefined fields Upgrade 0.2 → 0.3 ----------------- Public API surface preserved (names, overloads, modes). NOT bit-for-bit identical behavior. See docs/guide/upgrade-0.2-to-0.3.md - defaults applied on create (strict/loose) - $set/$setOnInsert validated in strict - timestamps:false honored on updates - soft:true now soft-deletes (default delete still hard) - create() TS type is InsertOneResult (runtime always was) Human docs ---------- https://mondel-orm.pages.dev Guide: getting-started, concepts, schemas, client, queries, validation, transactions, cli, advanced, compatibility, upgrade-0.2-to-0.3, troubleshooting, faq, comparison Recipes: cloudflare-workers, node-express, geospatial, soft-delete API: /api/reference, /api/field-types llms.txt index on site root