Skip to content

Commit ab1e0e4

Browse files
committed
feat: Add mongodb v5 support with strict filter types
BREAKING CHANGE: Filter and UpdateFilter types are now using the strict counterpart types from mongodb v5.
1 parent 68437e0 commit ab1e0e4

File tree

9 files changed

+339
-207
lines changed

9 files changed

+339
-207
lines changed

.eslintrc.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@
102102
],
103103
"@typescript-eslint/no-unnecessary-type-arguments": "error",
104104
"@typescript-eslint/no-unnecessary-type-constraint": "error",
105+
"@typescript-eslint/no-unsafe-argument": "warn",
106+
"@typescript-eslint/no-unsafe-assignment": "warn",
107+
"@typescript-eslint/no-unsafe-member-access": "warn",
108+
"@typescript-eslint/no-unsafe-return": "warn",
105109
"@typescript-eslint/no-useless-constructor": "warn",
106110
"@typescript-eslint/object-curly-spacing": ["error", "always"],
107111
"@typescript-eslint/parameter-properties": "error",

docs/api/model.md

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const User = papr.model('users', userSchema);
1818

1919
## `aggregate`
2020

21-
Calls the MongoDB [`aggregate()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#aggregate) method.
21+
Calls the MongoDB [`aggregate()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#aggregate) method.
2222

2323
The MongoDB aggregation pipeline syntax is very rich and powerful, however providing full typed support for the results is out of the scope of `papr`.
2424

@@ -50,7 +50,7 @@ const results = await User.aggregate<{ age: number }>([
5050

5151
## `bulkWrite`
5252

53-
Calls the MongoDB [`bulkWrite()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#bulkWrite) method.
53+
Calls the MongoDB [`bulkWrite()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#bulkWrite) method.
5454

5555
**Parameters:**
5656

@@ -61,7 +61,7 @@ Calls the MongoDB [`bulkWrite()`](https://mongodb.github.io/node-mongodb-native/
6161

6262
**Returns:**
6363

64-
[`Promise<BulkWriteResult>`](https://mongodb.github.io/node-mongodb-native/4.1/classes/BulkWriteResult.html)
64+
[`Promise<BulkWriteResult>`](https://mongodb.github.io/node-mongodb-native/5.0/classes/BulkWriteResult.html)
6565

6666
**Example:**
6767

@@ -88,13 +88,13 @@ const results = await User.bulkWrite([
8888

8989
## `countDocuments`
9090

91-
Calls the MongoDB [`countDocuments()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#countDocuments) method.
91+
Calls the MongoDB [`countDocuments()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#countDocuments) method.
9292

9393
**Parameters:**
9494

9595
| Name | Type | Attribute |
9696
| --------- | ----------------------- | --------- |
97-
| `filter` | `Filter<TSchema>` | required |
97+
| `filter` | `StrictFilter<TSchema>` | required |
9898
| `options` | `CountDocumentsOptions` | optional |
9999

100100
**Returns:**
@@ -110,18 +110,18 @@ const countWicks = await User.countDocuments({ lastName: 'Wick' });
110110

111111
## `deleteMany`
112112

113-
Calls the MongoDB [`deleteMany()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#deleteMany) method.
113+
Calls the MongoDB [`deleteMany()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#deleteMany) method.
114114

115115
**Parameters:**
116116

117-
| Name | Type | Attribute |
118-
| --------- | ----------------- | --------- |
119-
| `filter` | `Filter<TSchema>` | required |
120-
| `options` | `DeleteOptions` | optional |
117+
| Name | Type | Attribute |
118+
| --------- | ----------------------- | --------- |
119+
| `filter` | `StrictFilter<TSchema>` | required |
120+
| `options` | `DeleteOptions` | optional |
121121

122122
**Returns:**
123123

124-
[`Promise<DeleteResult>`](https://mongodb.github.io/node-mongodb-native/4.1/interfaces/DeleteResult.html)
124+
[`Promise<DeleteResult>`](https://mongodb.github.io/node-mongodb-native/5.0/interfaces/DeleteResult.html)
125125

126126
**Example:**
127127

@@ -131,18 +131,18 @@ await User.deleteMany({ lastName: 'Wick' });
131131

132132
## `deleteOne`
133133

134-
Calls the MongoDB [`deleteOne()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#deleteOne) method.
134+
Calls the MongoDB [`deleteOne()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#deleteOne) method.
135135

136136
**Parameters:**
137137

138-
| Name | Type | Attribute |
139-
| --------- | ----------------- | --------- |
140-
| `filter` | `Filter<TSchema>` | required |
141-
| `options` | `DeleteOptions` | optional |
138+
| Name | Type | Attribute |
139+
| --------- | ----------------------- | --------- |
140+
| `filter` | `StrictFilter<TSchema>` | required |
141+
| `options` | `DeleteOptions` | optional |
142142

143143
**Returns:**
144144

145-
[`Promise<DeleteResult>`](https://mongodb.github.io/node-mongodb-native/4.1/interfaces/DeleteResult.html)
145+
[`Promise<DeleteResult>`](https://mongodb.github.io/node-mongodb-native/5.0/interfaces/DeleteResult.html)
146146

147147
**Example:**
148148

@@ -152,15 +152,15 @@ await User.deleteOne({ lastName: 'Wick' });
152152

153153
## `distinct`
154154

155-
Calls the MongoDB [`distinct()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#distinct) method.
155+
Calls the MongoDB [`distinct()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#distinct) method.
156156

157157
**Parameters:**
158158

159-
| Name | Type | Attribute |
160-
| --------- | ----------------- | --------- |
161-
| `key` | `keyof TSchema` | required |
162-
| `filter` | `Filter<TSchema>` | optional |
163-
| `options` | `DistinctOptions` | optional |
159+
| Name | Type | Attribute |
160+
| --------- | ----------------------- | --------- |
161+
| `key` | `keyof TSchema` | required |
162+
| `filter` | `StrictFilter<TSchema>` | optional |
163+
| `options` | `DistinctOptions` | optional |
164164

165165
**Returns:**
166166

@@ -180,7 +180,7 @@ Performs an optimized `find` to test for the existence of any document matching
180180

181181
| Name | Type | Attribute |
182182
| --------- | --------------------------------------------------------------------------- | --------- |
183-
| `filter` | `Filter<TSchema>` | required |
183+
| `filter` | `StrictFilter<TSchema>` | required |
184184
| `options` | `Omit<FindOptions<TSchema>, ("projection" \| "limit" \| "sort" \| "skip")>` | optional |
185185

186186
**Returns:**
@@ -199,16 +199,16 @@ const isAlreadyActive = await User.exists({
199199

200200
## `find`
201201

202-
Calls the MongoDB [`find()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#find) method.
202+
Calls the MongoDB [`find()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#find) method.
203203

204204
The result type (`TProjected`) takes into account the projection for this query and reduces the original `TSchema` type accordingly. See also [`ProjectionType`](api/utils.md#ProjectionType).
205205

206206
**Parameters:**
207207

208-
| Name | Type | Attribute |
209-
| --------- | ---------------------- | --------- |
210-
| `filter` | `Filter<TSchema>` | required |
211-
| `options` | `FindOptions<TSchema>` | optional |
208+
| Name | Type | Attribute |
209+
| --------- | ----------------------- | --------- |
210+
| `filter` | `StrictFilter<TSchema>` | required |
211+
| `options` | `FindOptions<TSchema>` | optional |
212212

213213
**Returns:**
214214

@@ -228,7 +228,7 @@ usersProjected[0]?.lastName; // valid
228228

229229
## `findById`
230230

231-
Calls the MongoDB [`findOne()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#findOne) method.
231+
Calls the MongoDB [`findOne()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#findOne) method.
232232

233233
The result type (`TProjected`) takes into account the projection for this query and reduces the original `TSchema` type accordingly. See also [`ProjectionType`](api/utils.md#ProjectionType).
234234

@@ -259,16 +259,16 @@ userProjected.lastName; // valid
259259

260260
## `findOne`
261261

262-
Calls the MongoDB [`findOne()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#findOne) method.
262+
Calls the MongoDB [`findOne()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#findOne) method.
263263

264264
The result type (`TProjected`) takes into account the projection for this query and reduces the original `TSchema` type accordingly. See also [`ProjectionType`](api/utils.md#ProjectionType).
265265

266266
**Parameters:**
267267

268-
| Name | Type | Attribute |
269-
| --------- | ---------------------- | --------- |
270-
| `filter` | `Filter<TSchema>` | required |
271-
| `options` | `FindOptions<TSchema>` | optional |
268+
| Name | Type | Attribute |
269+
| --------- | ----------------------- | --------- |
270+
| `filter` | `StrictFilter<TSchema>` | required |
271+
| `options` | `FindOptions<TSchema>` | optional |
272272

273273
**Returns:**
274274

@@ -288,15 +288,15 @@ userProjected.lastName; // valid
288288

289289
## `findOneAndDelete`
290290

291-
Calls the MongoDB [`findOneAndDelete()`](http://mongodb.github.io/node-mongodb-native/4.1/classes/collection.html#findoneanddelete) method and returns the document found before removal.
291+
Calls the MongoDB [`findOneAndDelete()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#findOneAndDelete) method and returns the document found before removal.
292292

293293
The result type (`TProjected`) takes into account the projection for this query and reduces the original `TSchema` type accordingly. See also [`ProjectionType`](api/utils.md#ProjectionType).
294294

295295
**Parameters:**
296296

297297
| Name | Type | Attribute |
298298
| --------- | ------------------------- | --------- |
299-
| `filter` | `Filter<TSchema>` | required |
299+
| `filter` | `StrictFilter<TSchema>` | required |
300300
| `options` | `FindOneAndUpdateOptions` | optional |
301301

302302
**Returns:**
@@ -311,17 +311,17 @@ const user = await User.findOneAndDelete({ firstName: 'John' });
311311

312312
## `findOneAndUpdate`
313313

314-
Calls the MongoDB [`findOneAndUpdate()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#findOneAndUpdate) method.
314+
Calls the MongoDB [`findOneAndUpdate()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#findOneAndUpdate) method.
315315

316316
The result type (`TProjected`) takes into account the projection for this query and reduces the original `TSchema` type accordingly. See also [`ProjectionType`](api/utils.md#ProjectionType).
317317

318318
**Parameters:**
319319

320-
| Name | Type | Attribute |
321-
| --------- | ------------------------- | --------- |
322-
| `filter` | `Filter<TSchema>` | required |
323-
| `update` | `UpdateFilter<TSchema>` | required |
324-
| `options` | `FindOneAndUpdateOptions` | optional |
320+
| Name | Type | Attribute |
321+
| --------- | ----------------------------- | --------- |
322+
| `filter` | `StrictFilter<TSchema>` | required |
323+
| `update` | `StrictUpdateFilter<TSchema>` | required |
324+
| `options` | `FindOneAndUpdateOptions` | optional |
325325

326326
**Returns:**
327327

@@ -345,7 +345,7 @@ userProjected.lastName; // valid
345345

346346
## `insertMany`
347347

348-
Calls the MongoDB [`insertMany()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#insertMany) method.
348+
Calls the MongoDB [`insertMany()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#insertMany) method.
349349

350350
**Parameters:**
351351

@@ -369,7 +369,7 @@ const users = await User.insertMany([
369369

370370
## `insertOne`
371371

372-
Calls the MongoDB [`insertOne()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#insertOne) method.
372+
Calls the MongoDB [`insertOne()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#insertOne) method.
373373

374374
**Parameters:**
375375

@@ -393,19 +393,19 @@ const users = await User.insertOne([
393393

394394
## `updateMany`
395395

396-
Calls the MongoDB [`updateMany()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#updateMany) method.
396+
Calls the MongoDB [`updateMany()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#updateMany) method.
397397

398398
**Parameters:**
399399

400-
| Name | Type | Attribute |
401-
| --------- | ----------------------- | --------- |
402-
| `filter` | `Filter<TSchema>` | required |
403-
| `update` | `UpdateFilter<TSchema>` | required |
404-
| `options` | `UpdateOptions` | optional |
400+
| Name | Type | Attribute |
401+
| --------- | ----------------------------- | --------- |
402+
| `filter` | `StrictFilter<TSchema>` | required |
403+
| `update` | `StrictUpdateFilter<TSchema>` | required |
404+
| `options` | `UpdateOptions` | optional |
405405

406406
**Returns:**
407407

408-
[`Promise<UpdateResult>`](https://mongodb.github.io/node-mongodb-native/4.1/interfaces/UpdateResult.html)
408+
[`Promise<UpdateResult>`](https://mongodb.github.io/node-mongodb-native/5.0/interfaces/UpdateResult.html)
409409

410410
**Example:**
411411

@@ -415,19 +415,19 @@ const result = await User.updateMany({ firstName: 'John' }, { $set: { age: 40 }
415415

416416
## `updateOne`
417417

418-
Calls the MongoDB [`updateOne()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#updateOne) method.
418+
Calls the MongoDB [`updateOne()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#updateOne) method.
419419

420420
**Parameters:**
421421

422-
| Name | Type | Attribute |
423-
| --------- | ----------------------- | --------- |
424-
| `filter` | `Filter<TSchema>` | required |
425-
| `update` | `UpdateFilter<TSchema>` | required |
426-
| `options` | `UpdateOptions` | optional |
422+
| Name | Type | Attribute |
423+
| --------- | ----------------------------- | --------- |
424+
| `filter` | `StrictFilter<TSchema>` | required |
425+
| `update` | `StrictUpdateFilter<TSchema>` | required |
426+
| `options` | `UpdateOptions` | optional |
427427

428428
**Returns:**
429429

430-
[`Promise<UpdateResult>`](https://mongodb.github.io/node-mongodb-native/4.1/interfaces/UpdateResult.html)
430+
[`Promise<UpdateResult>`](https://mongodb.github.io/node-mongodb-native/5.0/interfaces/UpdateResult.html)
431431

432432
**Example:**
433433

@@ -437,14 +437,14 @@ const result = await User.updateOne({ firstName: 'John' }, { $set: { age: 40 } }
437437

438438
## `upsert`
439439

440-
Calls the MongoDB [`findOneAndUpdate()`](https://mongodb.github.io/node-mongodb-native/4.1/classes/Collection.html#findOneAndUpdate) method with the `upsert` option enabled.
440+
Calls the MongoDB [`findOneAndUpdate()`](https://mongodb.github.io/node-mongodb-native/5.0/classes/Collection.html#findOneAndUpdate) method with the `upsert` option enabled.
441441

442442
**Parameters:**
443443

444-
| Name | Type | Attribute |
445-
| -------- | ----------------------- | --------- |
446-
| `filter` | `Filter<TSchema>` | required |
447-
| `update` | `UpdateFilter<TSchema>` | required |
444+
| Name | Type | Attribute |
445+
| -------- | ----------------------------- | --------- |
446+
| `filter` | `StrictFilter<TSchema>` | required |
447+
| `update` | `StrictUpdateFilter<TSchema>` | required |
448448

449449
**Returns:**
450450

docs/recipes.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,28 @@ const postSchema = schema(
190190
}
191191
);
192192
```
193+
194+
## Filter Types
195+
196+
`mongodb` exposes two important TypeScript types for the most common operations you can do with the driver: the `Filter` (used for querying documents) and `UpdateFilter` (used for updating documents) types.
197+
198+
Starting with `mongodb` v4.3.0, these types were enhanced to support dot notation field access and type checking.
199+
200+
However, `mongodb` v5.0.0 [removed these types](https://github.com/mongodb/node-mongodb-native/blob/main/etc/notes/CHANGES_5.0.0.md#dot-notation-typescript-support-removed-by-default) as the default ones used in their methods and reverted to the old ones without dot notation support. The previous enhanced types were not removed, instead they were renamed to `StrictFilter` and `StrictUpdateFilter`, but they aren't referenced in any of their methods.
201+
202+
Papr is using the strict types to provide type safety for all query and update filters.
203+
204+
This comes with a caveat: whenever you need to interact with the `mongodb` driver collections, you need to cast filter types to their simple counterparts, since `Filter` is not compatible with `StrictFilter`.
205+
206+
```ts
207+
import { Filter, StrictFitler } from 'mongodb';
208+
import User, { UserDocument } from './user';
209+
210+
const filter: StrictFilter<UserDocument> = {
211+
firstName: 'John',
212+
};
213+
214+
await User.find(filter);
215+
216+
await User.collection.find(filter as Filter<UserDocument>);
217+
```

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"jsdoc-api": "8.0.0",
7979
"jsdoc-parse": "6.2.0",
8080
"lint-staged": "13.1.0",
81-
"mongodb": "4.13.0",
81+
"mongodb": "5.0.1",
8282
"mongodb-memory-server": "8.11.0",
8383
"mongoose": "6.3.5",
8484
"pinst": "3.0.0",
@@ -89,7 +89,7 @@
8989
"typescript": "4.9.3"
9090
},
9191
"peerDependencies": {
92-
"mongodb": ">=4.11.0"
92+
"mongodb": ">=5.0.0"
9393
},
9494
"commitlint": {
9595
"extends": [
@@ -125,4 +125,4 @@
125125
"yarn": "1.22.19"
126126
},
127127
"packageManager": "[email protected]"
128-
}
128+
}

src/__tests__/index.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ describe('index', () => {
145145
});
146146

147147
test('existing collection', async () => {
148-
// @ts-expect-error Ignore collection type
149148
(db.collections as jest.Mocked<Db['collections']>).mockResolvedValue([collection]);
150149

151150
const papr = new Papr();

0 commit comments

Comments
 (0)