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/`.

+158 -60
+1 -1
.npmignore
··· 1 node_modules/ 2 tests/ 3 - example.js/
··· 1 node_modules/ 2 tests/ 3 + examples/
+94 -50
README.md
··· 1 - # mizzleORM 2 3 - A lightweight, fully type-safe MongoDB ODM in TypeScript, inspired by Drizzle ORM. 4 5 - ## Features 6 7 - * **Schema-first:** Define and validate document schemas using Zod. 8 - * **Type-safe queries:** Auto-complete and type-safe insert/find/update/delete operations. 9 - * **Lightweight & modular:** No decorators, no runtime magic – everything is composable and transparent. 10 - * **Developer-first DX:** Simple, minimal API with great IDE support. 11 - * Works directly on top of MongoDB's native driver. 12 13 - ## Installation 14 15 ```bash 16 npm install mizzleorm mongodb zod ··· 18 yarn add mizzleorm mongodb zod 19 ``` 20 21 - ## Usage 22 23 - ### 1. Define your schema 24 25 - ```typescript 26 // src/schemas/user.ts 27 import { z } from 'zod'; 28 import { defineModel } from 'mizzleorm'; ··· 37 export type User = z.infer<typeof userSchema>; 38 ``` 39 40 - ### 2. Connect to MongoDB and create a model 41 42 - ```typescript 43 - // src/index.ts or your main application file 44 - import { connect, MongoModel, InferModel, InsertType } from 'mizzleorm'; 45 - import { userSchema } from './schemas/user'; // Assuming you saved the schema above 46 import { ObjectId } from 'mongodb'; 47 48 - // Infer types 49 type User = InferModel<typeof userSchema>; 50 type UserInsert = InsertType<typeof userSchema>; 51 ··· 53 await connect('mongodb://localhost:27017', 'your_database_name'); 54 const UserModel = new MongoModel('users', userSchema); 55 56 - // ... perform operations 57 58 await disconnect(); 59 } ··· 61 main().catch(console.error); 62 ``` 63 64 ### 3. Perform operations 65 66 - ```typescript 67 - // Insert a document 68 const newUser: UserInsert = { 69 name: 'John Doe', 70 email: 'john.doe@example.com', 71 age: 30, 72 }; 73 const insertResult = await UserModel.insertOne(newUser); 74 - console.log('Inserted user:', insertResult.insertedId); 75 76 - // Find documents 77 const users = await UserModel.find({ name: 'John Doe' }); 78 - console.log('Found users:', users); 79 80 - // Find one document 81 - const foundUser = await UserModel.findOne({ _id: new ObjectId(insertResult.insertedId) }); 82 - console.log('Found one user:', foundUser); 83 84 - // Update a document 85 - const updateResult = await UserModel.update( 86 - { _id: new ObjectId(insertResult.insertedId) }, 87 - { age: 31 } 88 - ); 89 - console.log('Updated user count:', updateResult.modifiedCount); 90 91 - // Delete documents 92 - const deleteResult = await UserModel.delete({ name: 'John Doe' }); 93 - console.log('Deleted user count:', deleteResult.deletedCount); 94 ``` 95 96 - ## Project Structure 97 98 ``` 99 - mongo-orm/ 100 ├── src/ 101 - │ ├── schema.ts # schema definition utility 102 │ ├── model.ts # MongoModel wrapper 103 - │ ├── client.ts # MongoDB connection 104 - │ ├── index.ts # public API export 105 - ├── examples/ 106 - │ └── user.ts # usage example 107 - ├── tests/ 108 ├── package.json 109 ├── tsconfig.json 110 - ├── README.md 111 ``` 112 113 - ## Development 114 115 - To build the project: 116 117 ```bash 118 npm run build 119 ``` 120 121 - To run the example: 122 123 ```bash 124 npm run example 125 ``` 126 127 - ## License 128 129 - MIT 130 131
··· 1 + # **mizzleORM** 2 3 + 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. 4 5 + --- 6 7 + ## ✨ Features 8 9 + * **Schema-first:** Define and validate collections using [Zod](https://zod.dev/). 10 + * **Type-safe operations:** Auto-complete and strict typings for `insert`, `find`, `update`, and `delete`. 11 + * **Minimal & modular:** No decorators or magic. Just clean, composable APIs. 12 + * **Developer-friendly DX:** Great TypeScript support and IDE integration. 13 + * **Built on MongoDB native driver:** Zero overhead with full control. 14 + 15 + --- 16 + 17 + ## 📦 Installation 18 19 ```bash 20 npm install mizzleorm mongodb zod ··· 22 yarn add mizzleorm mongodb zod 23 ``` 24 25 + --- 26 27 + ## 🚀 Quick Start 28 29 + ### 1. Define a schema 30 + 31 + ```ts 32 // src/schemas/user.ts 33 import { z } from 'zod'; 34 import { defineModel } from 'mizzleorm'; ··· 43 export type User = z.infer<typeof userSchema>; 44 ``` 45 46 + --- 47 48 + ### 2. Initialize connection and model 49 + 50 + ```ts 51 + // src/index.ts 52 + import { connect, disconnect, MongoModel, InferModel, InsertType } from 'mizzleorm'; 53 + import { userSchema } from './schemas/user'; 54 import { ObjectId } from 'mongodb'; 55 56 type User = InferModel<typeof userSchema>; 57 type UserInsert = InsertType<typeof userSchema>; 58 ··· 60 await connect('mongodb://localhost:27017', 'your_database_name'); 61 const UserModel = new MongoModel('users', userSchema); 62 63 + // Your operations go here 64 65 await disconnect(); 66 } ··· 68 main().catch(console.error); 69 ``` 70 71 + --- 72 + 73 ### 3. Perform operations 74 75 + ```ts 76 + // Insert one 77 const newUser: UserInsert = { 78 name: 'John Doe', 79 email: 'john.doe@example.com', 80 age: 30, 81 }; 82 const insertResult = await UserModel.insertOne(newUser); 83 84 + // Find many 85 const users = await UserModel.find({ name: 'John Doe' }); 86 87 + // Find one 88 + const found = await UserModel.findOne({ _id: new ObjectId(insertResult.insertedId) }); 89 90 + // Update 91 + await UserModel.update({ name: 'John Doe' }, { age: 31 }); 92 93 + // Delete 94 + await UserModel.delete({ name: 'John Doe' }); 95 + 96 + // Insert many 97 + await UserModel.insertMany([ 98 + { name: 'Alice', email: 'alice@example.com', age: 25 }, 99 + { name: 'Bob', email: 'bob@example.com' }, 100 + ]); 101 + 102 + // Find by ID 103 + await UserModel.findById(insertResult.insertedId); 104 + 105 + // Update one 106 + await UserModel.updateOne({ name: 'Alice' }, { age: 26 }); 107 + 108 + // Replace one 109 + await UserModel.replaceOne({ name: 'Bob' }, { 110 + name: 'Bob', 111 + email: 'bob@newmail.com', 112 + age: 22, 113 + }); 114 + 115 + // Delete one 116 + await UserModel.deleteOne({ name: 'Alice' }); 117 + 118 + // Count 119 + const count = await UserModel.count({ age: { $gte: 18 } }); 120 + 121 + // Aggregation 122 + const aggregation = await UserModel.aggregate([ 123 + { $match: { age: { $gte: 18 } } }, 124 + { $group: { _id: null, avgAge: { $avg: '$age' } } }, 125 + ]); 126 + 127 + // Paginated query 128 + const paginated = await UserModel.findPaginated( 129 + { age: { $gte: 18 } }, 130 + { skip: 0, limit: 10, sort: { age: -1 } } 131 + ); 132 ``` 133 134 + --- 135 + 136 + ## 🧠 Project Structure 137 138 ``` 139 + mizzleorm/ 140 ├── src/ 141 + │ ├── schema.ts # Schema definition utility 142 │ ├── model.ts # MongoModel wrapper 143 + │ ├── client.ts # MongoDB client connection 144 + │ └── index.ts # Public API exports 145 + ├── examples/ # Example usage files 146 + │ └── user.ts 147 + ├── tests/ # Unit and integration tests 148 ├── package.json 149 ├── tsconfig.json 150 + └── README.md 151 ``` 152 153 + --- 154 155 + ## 🛠 Development 156 + 157 + ### Build the library: 158 159 ```bash 160 npm run build 161 ``` 162 163 + ### Run the example: 164 165 ```bash 166 npm run example 167 ``` 168 169 + --- 170 171 + ## 📄 License 172 173 + MIT — use it freely and contribute back if you'd like! 174 175 + ---
+1 -1
package.json
··· 1 { 2 "name": "mizzleorm", 3 - "version": "1.0.1", 4 "description": "A lightweight, fully type-safe MongoDB ODM in TypeScript, inspired by Drizzle ORM.", 5 "main": "dist/index.js", 6 "types": "dist/index.d.ts",
··· 1 { 2 "name": "mizzleorm", 3 + "version": "1.0.3", 4 "description": "A lightweight, fully type-safe MongoDB ODM in TypeScript, inspired by Drizzle ORM.", 5 "main": "dist/index.js", 6 "types": "dist/index.d.ts",
+62 -8
src/model.ts
··· 1 import { z } from 'zod'; 2 - import { Collection, InsertOneResult, UpdateResult, DeleteResult, Document, ObjectId, Filter } from 'mongodb'; 3 import { getDb } from './client'; 4 import { InsertType } from './schema'; 5 ··· 14 15 async insertOne(data: InsertType<T>): Promise<InsertOneResult<z.infer<T>>> { 16 const validatedData = this.schema.parse(data); 17 - return this.collection.insertOne(validatedData as any); 18 } 19 20 - find(query: Filter<z.infer<T>>): Promise<(z.infer<T> & { _id: ObjectId })[]> { 21 - return this.collection.find(query).toArray() as Promise<(z.infer<T> & { _id: ObjectId })[]>; 22 } 23 24 - findOne(query: Filter<z.infer<T>>): Promise<(z.infer<T> & { _id: ObjectId }) | null> { 25 - return this.collection.findOne(query) as Promise<(z.infer<T> & { _id: ObjectId }) | null>; 26 } 27 28 async update(query: Filter<z.infer<T>>, data: Partial<z.infer<T>>): Promise<UpdateResult> { 29 return this.collection.updateMany(query, { $set: data }); 30 } 31 32 - delete(query: Filter<z.infer<T>>): Promise<DeleteResult> { 33 return this.collection.deleteMany(query); 34 } 35 } 36 37 -
··· 1 import { z } from 'zod'; 2 + import { 3 + Collection, 4 + InsertOneResult, 5 + InsertManyResult, 6 + UpdateResult, 7 + DeleteResult, 8 + Document, 9 + ObjectId, 10 + Filter, 11 + OptionalUnlessRequiredId, 12 + WithId 13 + } from 'mongodb'; 14 import { getDb } from './client'; 15 import { InsertType } from './schema'; 16 ··· 25 26 async insertOne(data: InsertType<T>): Promise<InsertOneResult<z.infer<T>>> { 27 const validatedData = this.schema.parse(data); 28 + return this.collection.insertOne(validatedData as OptionalUnlessRequiredId<z.infer<T>>); 29 + } 30 + 31 + async insertMany(data: InsertType<T>[]): Promise<InsertManyResult<z.infer<T>>> { 32 + const validatedData = data.map((item) => this.schema.parse(item)); 33 + return this.collection.insertMany(validatedData as OptionalUnlessRequiredId<z.infer<T>>[]); 34 + } 35 + 36 + find(query: Filter<z.infer<T>>): Promise<(WithId<z.infer<T>>)[]> { 37 + return this.collection.find(query).toArray(); 38 } 39 40 + findOne(query: Filter<z.infer<T>>): Promise<WithId<z.infer<T>> | null> { 41 + return this.collection.findOne(query); 42 } 43 44 + async findById(id: string | ObjectId): Promise<WithId<z.infer<T>> | null> { 45 + const objectId = typeof id === 'string' ? new ObjectId(id) : id; 46 + return this.findOne({ _id: objectId } as Filter<z.infer<T>>); 47 } 48 49 async update(query: Filter<z.infer<T>>, data: Partial<z.infer<T>>): Promise<UpdateResult> { 50 return this.collection.updateMany(query, { $set: data }); 51 } 52 53 + async updateOne(query: Filter<z.infer<T>>, data: Partial<z.infer<T>>): Promise<UpdateResult> { 54 + return this.collection.updateOne(query, { $set: data }); 55 + } 56 + 57 + async replaceOne(query: Filter<z.infer<T>>, data: InsertType<T>): Promise<UpdateResult> { 58 + const validatedData = this.schema.parse(data); 59 + return this.collection.replaceOne(query, validatedData as OptionalUnlessRequiredId<z.infer<T>>); 60 + } 61 + 62 + async delete(query: Filter<z.infer<T>>): Promise<DeleteResult> { 63 return this.collection.deleteMany(query); 64 } 65 + 66 + async deleteOne(query: Filter<z.infer<T>>): Promise<DeleteResult> { 67 + return this.collection.deleteOne(query); 68 + } 69 + 70 + async count(query: Filter<z.infer<T>>): Promise<number> { 71 + return this.collection.countDocuments(query); 72 + } 73 + 74 + async aggregate(pipeline: Document[]): Promise<any[]> { 75 + return this.collection.aggregate(pipeline).toArray(); 76 + } 77 + 78 + // Pagination support for find 79 + async findPaginated( 80 + query: Filter<z.infer<T>>, 81 + options: { skip?: number; limit?: number; sort?: Document } = {} 82 + ): Promise<(WithId<z.infer<T>>)[]> { 83 + return this.collection 84 + .find(query) 85 + .skip(options.skip ?? 0) 86 + .limit(options.limit ?? 10) 87 + .sort(options.sort ?? {}) 88 + .toArray(); 89 + } 90 } 91