Thin MongoDB ODM built for Standard Schema
mongodb zod deno

feat: Enhance mizzleORM with extended functionalities and improved documentation

- Update package version to 1.0.3.
- Enhance `MongoModel` with methods for `insertMany`, `findById`, `updateOne`, `replaceOne`, `deleteOne`, `count`, `aggregate`, and `findPaginated`.
- Improve README.md with more detailed explanations, installation instructions, quick start guide, project structure, development guidelines, and license information.
- Correct `.npmignore` to exclude the `examples/` directory instead of `example.js/`.

Changed files
+158 -60
src
+1 -1
.npmignore
···
node_modules/
tests/
-
example.js/
+
examples/
+94 -50
README.md
···
-
# mizzleORM
+
# **mizzleORM**
-
A lightweight, fully type-safe MongoDB ODM in TypeScript, inspired by Drizzle ORM.
+
A lightweight, type-safe ODM for MongoDB in TypeScript — inspired by [Drizzle ORM](https://orm.drizzle.team/) and built for developers who value simplicity, transparency, and strong typings.
-
## Features
+
---
-
* **Schema-first:** Define and validate document schemas using Zod.
-
* **Type-safe queries:** Auto-complete and type-safe insert/find/update/delete operations.
-
* **Lightweight & modular:** No decorators, no runtime magic – everything is composable and transparent.
-
* **Developer-first DX:** Simple, minimal API with great IDE support.
-
* Works directly on top of MongoDB's native driver.
+
## ✨ Features
-
## Installation
+
* **Schema-first:** Define and validate collections using [Zod](https://zod.dev/).
+
* **Type-safe operations:** Auto-complete and strict typings for `insert`, `find`, `update`, and `delete`.
+
* **Minimal & modular:** No decorators or magic. Just clean, composable APIs.
+
* **Developer-friendly DX:** Great TypeScript support and IDE integration.
+
* **Built on MongoDB native driver:** Zero overhead with full control.
+
+
---
+
+
## 📦 Installation
```bash
npm install mizzleorm mongodb zod
···
yarn add mizzleorm mongodb zod
```
-
## Usage
+
---
-
### 1. Define your schema
+
## 🚀 Quick Start
-
```typescript
+
### 1. Define a schema
+
+
```ts
// src/schemas/user.ts
import { z } from 'zod';
import { defineModel } from 'mizzleorm';
···
export type User = z.infer<typeof userSchema>;
```
-
### 2. Connect to MongoDB and create a model
+
---
-
```typescript
-
// src/index.ts or your main application file
-
import { connect, MongoModel, InferModel, InsertType } from 'mizzleorm';
-
import { userSchema } from './schemas/user'; // Assuming you saved the schema above
+
### 2. Initialize connection and model
+
+
```ts
+
// src/index.ts
+
import { connect, disconnect, MongoModel, InferModel, InsertType } from 'mizzleorm';
+
import { userSchema } from './schemas/user';
import { ObjectId } from 'mongodb';
-
// Infer types
type User = InferModel<typeof userSchema>;
type UserInsert = InsertType<typeof userSchema>;
···
await connect('mongodb://localhost:27017', 'your_database_name');
const UserModel = new MongoModel('users', userSchema);
-
// ... perform operations
+
// Your operations go here
await disconnect();
}
···
main().catch(console.error);
```
+
---
+
### 3. Perform operations
-
```typescript
-
// Insert a document
+
```ts
+
// Insert one
const newUser: UserInsert = {
name: 'John Doe',
email: 'john.doe@example.com',
age: 30,
};
const insertResult = await UserModel.insertOne(newUser);
-
console.log('Inserted user:', insertResult.insertedId);
-
// Find documents
+
// Find many
const users = await UserModel.find({ name: 'John Doe' });
-
console.log('Found users:', users);
-
// Find one document
-
const foundUser = await UserModel.findOne({ _id: new ObjectId(insertResult.insertedId) });
-
console.log('Found one user:', foundUser);
+
// Find one
+
const found = await UserModel.findOne({ _id: new ObjectId(insertResult.insertedId) });
-
// Update a document
-
const updateResult = await UserModel.update(
-
{ _id: new ObjectId(insertResult.insertedId) },
-
{ age: 31 }
-
);
-
console.log('Updated user count:', updateResult.modifiedCount);
+
// Update
+
await UserModel.update({ name: 'John Doe' }, { age: 31 });
-
// Delete documents
-
const deleteResult = await UserModel.delete({ name: 'John Doe' });
-
console.log('Deleted user count:', deleteResult.deletedCount);
+
// Delete
+
await UserModel.delete({ name: 'John Doe' });
+
+
// Insert many
+
await UserModel.insertMany([
+
{ name: 'Alice', email: 'alice@example.com', age: 25 },
+
{ name: 'Bob', email: 'bob@example.com' },
+
]);
+
+
// Find by ID
+
await UserModel.findById(insertResult.insertedId);
+
+
// Update one
+
await UserModel.updateOne({ name: 'Alice' }, { age: 26 });
+
+
// Replace one
+
await UserModel.replaceOne({ name: 'Bob' }, {
+
name: 'Bob',
+
email: 'bob@newmail.com',
+
age: 22,
+
});
+
+
// Delete one
+
await UserModel.deleteOne({ name: 'Alice' });
+
+
// Count
+
const count = await UserModel.count({ age: { $gte: 18 } });
+
+
// Aggregation
+
const aggregation = await UserModel.aggregate([
+
{ $match: { age: { $gte: 18 } } },
+
{ $group: { _id: null, avgAge: { $avg: '$age' } } },
+
]);
+
+
// Paginated query
+
const paginated = await UserModel.findPaginated(
+
{ age: { $gte: 18 } },
+
{ skip: 0, limit: 10, sort: { age: -1 } }
+
);
```
-
## Project Structure
+
---
+
+
## 🧠 Project Structure
```
-
mongo-orm/
+
mizzleorm/
├── src/
-
│ ├── schema.ts # schema definition utility
+
│ ├── schema.ts # Schema definition utility
│ ├── model.ts # MongoModel wrapper
-
│ ├── client.ts # MongoDB connection
-
│ ├── index.ts # public API export
-
├── examples/
-
│ └── user.ts # usage example
-
├── tests/
+
│ ├── client.ts # MongoDB client connection
+
│ └── index.ts # Public API exports
+
├── examples/ # Example usage files
+
│ └── user.ts
+
├── tests/ # Unit and integration tests
├── package.json
├── tsconfig.json
-
├── README.md
+
└── README.md
```
-
## Development
+
---
-
To build the project:
+
## 🛠 Development
+
+
### Build the library:
```bash
npm run build
```
-
To run the example:
+
### Run the example:
```bash
npm run example
```
-
## License
+
---
-
MIT
+
## 📄 License
+
MIT — use it freely and contribute back if you'd like!
+
---
+1 -1
package.json
···
{
"name": "mizzleorm",
-
"version": "1.0.1",
+
"version": "1.0.3",
"description": "A lightweight, fully type-safe MongoDB ODM in TypeScript, inspired by Drizzle ORM.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
+62 -8
src/model.ts
···
import { z } from 'zod';
-
import { Collection, InsertOneResult, UpdateResult, DeleteResult, Document, ObjectId, Filter } from 'mongodb';
+
import {
+
Collection,
+
InsertOneResult,
+
InsertManyResult,
+
UpdateResult,
+
DeleteResult,
+
Document,
+
ObjectId,
+
Filter,
+
OptionalUnlessRequiredId,
+
WithId
+
} from 'mongodb';
import { getDb } from './client';
import { InsertType } from './schema';
···
async insertOne(data: InsertType<T>): Promise<InsertOneResult<z.infer<T>>> {
const validatedData = this.schema.parse(data);
-
return this.collection.insertOne(validatedData as any);
+
return this.collection.insertOne(validatedData as OptionalUnlessRequiredId<z.infer<T>>);
+
}
+
+
async insertMany(data: InsertType<T>[]): Promise<InsertManyResult<z.infer<T>>> {
+
const validatedData = data.map((item) => this.schema.parse(item));
+
return this.collection.insertMany(validatedData as OptionalUnlessRequiredId<z.infer<T>>[]);
+
}
+
+
find(query: Filter<z.infer<T>>): Promise<(WithId<z.infer<T>>)[]> {
+
return this.collection.find(query).toArray();
}
-
find(query: Filter<z.infer<T>>): Promise<(z.infer<T> & { _id: ObjectId })[]> {
-
return this.collection.find(query).toArray() as Promise<(z.infer<T> & { _id: ObjectId })[]>;
+
findOne(query: Filter<z.infer<T>>): Promise<WithId<z.infer<T>> | null> {
+
return this.collection.findOne(query);
}
-
findOne(query: Filter<z.infer<T>>): Promise<(z.infer<T> & { _id: ObjectId }) | null> {
-
return this.collection.findOne(query) as Promise<(z.infer<T> & { _id: ObjectId }) | null>;
+
async findById(id: string | ObjectId): Promise<WithId<z.infer<T>> | null> {
+
const objectId = typeof id === 'string' ? new ObjectId(id) : id;
+
return this.findOne({ _id: objectId } as Filter<z.infer<T>>);
}
async update(query: Filter<z.infer<T>>, data: Partial<z.infer<T>>): Promise<UpdateResult> {
return this.collection.updateMany(query, { $set: data });
}
-
delete(query: Filter<z.infer<T>>): Promise<DeleteResult> {
+
async updateOne(query: Filter<z.infer<T>>, data: Partial<z.infer<T>>): Promise<UpdateResult> {
+
return this.collection.updateOne(query, { $set: data });
+
}
+
+
async replaceOne(query: Filter<z.infer<T>>, data: InsertType<T>): Promise<UpdateResult> {
+
const validatedData = this.schema.parse(data);
+
return this.collection.replaceOne(query, validatedData as OptionalUnlessRequiredId<z.infer<T>>);
+
}
+
+
async delete(query: Filter<z.infer<T>>): Promise<DeleteResult> {
return this.collection.deleteMany(query);
}
+
+
async deleteOne(query: Filter<z.infer<T>>): Promise<DeleteResult> {
+
return this.collection.deleteOne(query);
+
}
+
+
async count(query: Filter<z.infer<T>>): Promise<number> {
+
return this.collection.countDocuments(query);
+
}
+
+
async aggregate(pipeline: Document[]): Promise<any[]> {
+
return this.collection.aggregate(pipeline).toArray();
+
}
+
+
// Pagination support for find
+
async findPaginated(
+
query: Filter<z.infer<T>>,
+
options: { skip?: number; limit?: number; sort?: Document } = {}
+
): Promise<(WithId<z.infer<T>>)[]> {
+
return this.collection
+
.find(query)
+
.skip(options.skip ?? 0)
+
.limit(options.limit ?? 10)
+
.sort(options.sort ?? {})
+
.toArray();
+
}
}
-