Getting started
DORM brings the ergonomics of the Django ORM to MongoDB in TypeScript: define a model once, then query and write through it — including Django's field__lookup filter syntax, which compiles to MongoDB aggregation pipelines (relational __ traversals become $lookup joins).
Install
bash
npm install @m1abdullah/dorm mongodbmongodb is a peer dependency (DORM has no other runtime dependencies), so you always control the single copy of the driver.
Requirements. Node.js 20+ and mongodb 6+. DORM is ESM-only (no CommonJS build) — import it with ESM import syntax (or a dynamic import() from CommonJS); a top-level require("@m1abdullah/dorm") is not supported.
Quickstart
ts
import { DORMClient, f } from "@m1abdullah/dorm";
const dorm = new DORMClient(process.env.MONGODB_URL!); // e.g. mongodb://localhost:27017/app
// Declare models synchronously — safe before connecting.
const User = dorm.model(
"users",
{
username: f.string({ required: true }),
email: f.string({ required: true, unique: true }),
salary: f.number({ default: 0 }),
active: f.boolean({ default: true }),
supervisor: f.ref("users"),
},
{ timestamps: true },
);
const Asset = dorm.model(
"assets",
{
name: f.string({ required: true }),
price: f.number({ default: 0 }),
assigned_to: f.ref("users"),
},
{ timestamps: true },
);
await dorm.connect(); // open the connection once, at startup
await dorm.ensureIndexes(); // create declared indexes (unique email, …)
// Create — validates, applies defaults + timestamps, returns the stored doc.
const boss = await User.objects.create({ username: "boss", email: "b@co.com", salary: 90000 });
const abed = await User.objects.create({
username: "abed",
email: "abed@co.com",
salary: 40000,
supervisor: boss._id,
});
await Asset.objects.create({ name: "Macbook", price: 2000, assigned_to: abed._id });
// Query — Django-style lookups.
await User.objects.filter({ salary__gte: 50000 });
await User.objects.get({ username: "abed" });
await User.objects.count({ active: true });
// Relational traversal — assets whose assignee's supervisor earns >= 50k.
await Asset.objects.filter({ assigned_to__supervisor__salary__gte: 50000 });
// Write.
await User.objects.update({ username: "abed" }, { salary: 60000 });
await User.objects.delete({ active: false });
await dorm.close();Next steps
- Models & fields — the schema and field builders.
- Querying — lookups and the chainable
QuerySet. - Data modeling — arrays, embedded documents, enums, indexes,
populate. - Lifecycle & transactions — hooks,
transaction, and validation errors.
There's also a runnable Express example in the examples/ folder.