Skip to content

Commit 5de41db

Browse files
committed
DocumentCollection: add type-level tests (#26)
1 parent 8094688 commit 5de41db

File tree

3 files changed

+247
-14
lines changed

3 files changed

+247
-14
lines changed

.changeset/nice-roses-yell.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"effect-mongodb": patch
3+
---
4+
5+
Fix errors on `DocumentCollection`:
6+
7+
- `insertOne` data-first overload when only passing collection and doc
8+
- `insertMany` return type is always `InsertManyResult`
9+
- `rename` now returns a new `DocumentCollection` (like `Collection.rename`)
10+
- `dropIndex` now returns void (like `Collection.dropIndex`)
Lines changed: 220 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,234 @@
11
import * as DocumentCollection from "effect-mongodb/DocumentCollection"
2+
import * as DocumentFindCursor from "effect-mongodb/DocumentFindCursor"
3+
import * as F from "effect/Function"
24
import * as Schema from "effect/Schema"
5+
import type { Document } from "mongodb"
36

47
const MyType = Schema.Struct({
58
birthday: Schema.Date
69
})
10+
type MyType = typeof MyType.Type
711

8-
declare const documentCollection: DocumentCollection.DocumentCollection
12+
declare const anyDocument: Document
13+
14+
declare const collection: DocumentCollection.DocumentCollection
15+
16+
// -------------------------------------------------------------------------------------
17+
// find
18+
// -------------------------------------------------------------------------------------
19+
20+
// $ExpectType Effect<Document[], MongoError, never>
21+
DocumentFindCursor.toArray(DocumentCollection.find(collection, { birthday: "2024-11-28" }))
22+
23+
// $ExpectType Effect<Document[], MongoError, never>
24+
F.pipe(collection, DocumentCollection.find({ birthday: "2024-11-28" }), DocumentFindCursor.toArray)
25+
26+
// -------------------------------------------------------------------------------------
27+
// findOne
28+
// -------------------------------------------------------------------------------------
29+
30+
// $ExpectType Effect<Option<Document>, MongoError, never>
31+
DocumentCollection.findOne(collection, { birthday: "2024-11-28" })
32+
33+
// $ExpectType Effect<Option<Document>, MongoError, never>
34+
F.pipe(collection, DocumentCollection.findOne({ birthday: "2024-11-28" }))
35+
36+
// -------------------------------------------------------------------------------------
37+
// insertOne
38+
// -------------------------------------------------------------------------------------
39+
40+
// $ExpectType Effect<InsertOneResult<Document>, MongoError, never>
41+
DocumentCollection.insertOne(collection, anyDocument)
42+
43+
// $ExpectType Effect<InsertOneResult<Document>, MongoError, never>
44+
DocumentCollection.insertOne(collection, anyDocument, { comment: "any" })
45+
46+
// $ExpectType Effect<InsertOneResult<Document>, MongoError, never>
47+
F.pipe(collection, DocumentCollection.insertOne(anyDocument))
48+
49+
// -------------------------------------------------------------------------------------
50+
// insertMany
51+
// -------------------------------------------------------------------------------------
52+
53+
// $ExpectType Effect<InsertManyResult<Document>, MongoError, never>
54+
DocumentCollection.insertMany(collection, [anyDocument])
55+
56+
// $ExpectType Effect<InsertManyResult<Document>, MongoError, never>
57+
F.pipe(collection, DocumentCollection.insertMany([anyDocument]))
58+
59+
// -------------------------------------------------------------------------------------
60+
// deleteOne
61+
// -------------------------------------------------------------------------------------
62+
63+
// $ExpectType Effect<DeleteResult, MongoError, never>
64+
DocumentCollection.deleteOne(collection, { birthday: "2024-11-28" })
65+
66+
// $ExpectType Effect<DeleteResult, MongoError, never>
67+
F.pipe(collection, DocumentCollection.deleteOne({ birthday: "2024-11-28" }))
68+
69+
// -------------------------------------------------------------------------------------
70+
// deleteMany
71+
// -------------------------------------------------------------------------------------
72+
73+
// $ExpectType Effect<DeleteResult, MongoError, never>
74+
DocumentCollection.deleteMany(collection, { birthday: "2024-11-28" })
75+
76+
// $ExpectType Effect<DeleteResult, MongoError, never>
77+
F.pipe(collection, DocumentCollection.deleteMany({ birthday: "2024-11-28" }))
78+
79+
// -------------------------------------------------------------------------------------
80+
// updateMany
81+
// -------------------------------------------------------------------------------------
82+
83+
// $ExpectType Effect<UpdateResult<Document>, MongoError, never>
84+
DocumentCollection.updateMany(collection, { birthday: "2024-11-28" }, { $set: { birthday: "2024-11-29" } })
85+
86+
// $ExpectType Effect<UpdateResult<Document>, MongoError, never>
87+
F.pipe(collection, DocumentCollection.updateMany({ birthday: "2024-11-28" }, { $set: { birthday: "2024-11-29" } }))
88+
89+
// -------------------------------------------------------------------------------------
90+
// replaceOne
91+
// -------------------------------------------------------------------------------------
92+
93+
// $ExpectType Effect<Document | UpdateResult<Document>, MongoError, never>
94+
DocumentCollection.replaceOne(collection, { birthday: "2024-11-28" }, anyDocument)
95+
96+
// $ExpectType Effect<Document | UpdateResult<Document>, MongoError, never>
97+
F.pipe(collection, DocumentCollection.replaceOne({ birthday: "2024-11-28" }, anyDocument))
98+
99+
// -------------------------------------------------------------------------------------
100+
// findOneAndReplace
101+
// -------------------------------------------------------------------------------------
102+
103+
// $ExpectType Effect<ModifyResult<Document>, MongoError, never>
104+
DocumentCollection.findOneAndReplace(collection, { birthday: "2024-11-28" }, anyDocument, {
105+
includeResultMetadata: true
106+
})
107+
108+
// $ExpectType Effect<ModifyResult<Document>, MongoError, never>
109+
F.pipe(
110+
collection,
111+
DocumentCollection.findOneAndReplace({ birthday: "2024-11-28" }, anyDocument, { includeResultMetadata: true })
112+
)
113+
114+
// $ExpectType Effect<Option<Document>, MongoError, never>
115+
DocumentCollection.findOneAndReplace(collection, { birthday: "2024-11-28" }, anyDocument, {
116+
includeResultMetadata: false
117+
})
118+
119+
// $ExpectType Effect<Option<Document>, MongoError, never>
120+
F.pipe(
121+
collection,
122+
DocumentCollection.findOneAndReplace({ birthday: "2024-11-28" }, anyDocument, { includeResultMetadata: false })
123+
)
124+
125+
// $ExpectType Effect<Option<Document>, MongoError, never>
126+
DocumentCollection.findOneAndReplace(collection, { birthday: "2024-11-28" }, anyDocument, { comment: "any" })
127+
128+
// $ExpectType Effect<Option<Document>, MongoError, never>
129+
F.pipe(collection, DocumentCollection.findOneAndReplace({ birthday: "2024-11-28" }, anyDocument, { comment: "any" }))
130+
131+
// $ExpectType Effect<Option<Document>, MongoError, never>
132+
DocumentCollection.findOneAndReplace(collection, { birthday: "2024-11-28" }, anyDocument)
133+
134+
// $ExpectType Effect<Option<Document>, MongoError, never>
135+
F.pipe(collection, DocumentCollection.findOneAndReplace({ birthday: "2024-11-28" }, anyDocument))
136+
137+
// -------------------------------------------------------------------------------------
138+
// rename
139+
// -------------------------------------------------------------------------------------
140+
141+
// $ExpectType Effect<DocumentCollection, MongoError, never>
142+
DocumentCollection.rename(collection, "new-collection")
143+
144+
// $ExpectType Effect<DocumentCollection, MongoError, never>
145+
F.pipe(collection, DocumentCollection.rename("new-collection"))
146+
147+
// -------------------------------------------------------------------------------------
148+
// drop
149+
// -------------------------------------------------------------------------------------
150+
151+
// $ExpectType Effect<boolean, MongoError, never>
152+
DocumentCollection.drop(collection)
153+
154+
// $ExpectType Effect<boolean, MongoError, never>
155+
F.pipe(collection, DocumentCollection.drop())
156+
157+
// -------------------------------------------------------------------------------------
158+
// createIndexes
159+
// -------------------------------------------------------------------------------------
160+
161+
// $ExpectType Effect<string[], MongoError, never>
162+
DocumentCollection.createIndexes(collection, [{ key: { birthday: 1 } }])
163+
164+
// $ExpectType Effect<string[], MongoError, never>
165+
F.pipe(collection, DocumentCollection.createIndexes([{ key: { birthday: 1 } }]))
166+
167+
// -------------------------------------------------------------------------------------
168+
// createIndex
169+
// -------------------------------------------------------------------------------------
170+
171+
// $ExpectType Effect<string, MongoError, never>
172+
DocumentCollection.createIndex(collection, { birthday: 1 })
173+
174+
// $ExpectType Effect<string, MongoError, never>
175+
F.pipe(collection, DocumentCollection.createIndex({ birthday: 1 }))
176+
177+
// -------------------------------------------------------------------------------------
178+
// dropIndex
179+
// -------------------------------------------------------------------------------------
180+
181+
// $ExpectType Effect<void, MongoError, never>
182+
DocumentCollection.dropIndex(collection, "birthday_1")
183+
184+
// $ExpectType Effect<void, MongoError, never>
185+
F.pipe(collection, DocumentCollection.dropIndex("birthday_1"))
186+
187+
// -------------------------------------------------------------------------------------
188+
// aggregate
189+
// -------------------------------------------------------------------------------------
190+
191+
const groupByBirthday = [{ $group: { _id: "$birthday", birthdays: { $sum: 1 } } }]
192+
193+
// $ExpectType DocumentAggregationCursor
194+
DocumentCollection.aggregate(collection, groupByBirthday)
195+
196+
// $ExpectType DocumentAggregationCursor
197+
F.pipe(collection, DocumentCollection.aggregate(groupByBirthday))
198+
199+
// -------------------------------------------------------------------------------------
200+
// estimatedDocumentCount
201+
// -------------------------------------------------------------------------------------
202+
203+
// $ExpectType Effect<number, MongoError, never>
204+
DocumentCollection.estimatedDocumentCount(collection)
205+
206+
// $ExpectType Effect<number, MongoError, never>
207+
F.pipe(collection, DocumentCollection.estimatedDocumentCount())
208+
209+
// -------------------------------------------------------------------------------------
210+
// countDocuments
211+
// -------------------------------------------------------------------------------------
212+
213+
// $ExpectType Effect<number, MongoError, never>
214+
DocumentCollection.countDocuments(collection, { birthday: "2024-11-28" })
215+
216+
// $ExpectType Effect<number, MongoError, never>
217+
F.pipe(collection, DocumentCollection.countDocuments({ birthday: "2024-11-28" }))
218+
219+
// -------------------------------------------------------------------------------------
220+
// typed
221+
// -----------------------------------------------------------------
222+
223+
// $ExpectType Collection<{ readonly birthday: Date; }, { readonly birthday: string; }, never>
224+
DocumentCollection.typed(collection, MyType)
9225

10226
// $ExpectType Collection<{ readonly birthday: Date; }, { readonly birthday: string; }, never>
11-
DocumentCollection.typed(documentCollection, MyType)
227+
F.pipe(collection, DocumentCollection.typed(MyType))
12228

13229
// @ts-expect-error
14-
DocumentCollection.typed(documentCollection, Schema.Date)
230+
DocumentCollection.typed(collection, Schema.Date)
15231

16232
// TODO the following test should work, i.e. array are not acceptable as a collection type
17233
// // @ts-expect-error
18-
// DocumentCollection.typed(documentCollection, Schema.Array(MyType))
234+
// DocumentCollection.typed(collection, Schema.Array(MyType))

packages/effect-mongodb/src/DocumentCollection.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ export const findOne: {
9191
)
9292

9393
export const insertOne: {
94+
(
95+
collection: DocumentCollection,
96+
doc: OptionalUnlessRequiredId<Document>
97+
): Effect.Effect<InsertOneResult, MongoError.MongoError>
9498
(doc: OptionalUnlessRequiredId<Document>, options?: InsertOneOptions): (
9599
collection: DocumentCollection
96100
) => Effect.Effect<InsertOneResult, MongoError.MongoError>
@@ -115,12 +119,12 @@ export const insertMany: {
115119
options?: BulkWriteOptions
116120
): (
117121
collection: DocumentCollection
118-
) => Effect.Effect<InsertOneResult, MongoError.MongoError>
122+
) => Effect.Effect<InsertManyResult, MongoError.MongoError>
119123
(
120124
collection: DocumentCollection,
121125
docs: ReadonlyArray<OptionalUnlessRequiredId<Document>>,
122126
options?: BulkWriteOptions
123-
): Effect.Effect<InsertOneResult, MongoError.MongoError>
127+
): Effect.Effect<InsertManyResult, MongoError.MongoError>
124128
} = F.dual((args) => isDocumentCollection(args[0]), (
125129
collection: DocumentCollection,
126130
docs: ReadonlyArray<OptionalUnlessRequiredId<Document>>,
@@ -307,22 +311,23 @@ export const findOneAndReplace: {
307311
export const rename: {
308312
(newName: string, options?: RenameOptions): (
309313
collection: DocumentCollection
310-
) => Effect.Effect<MongoCollection, MongoError.MongoError>
314+
) => Effect.Effect<DocumentCollection, MongoError.MongoError>
311315
(
312316
collection: DocumentCollection,
313317
newName: string,
314318
options?: RenameOptions
315-
): Effect.Effect<MongoCollection, MongoError.MongoError>
319+
): Effect.Effect<DocumentCollection, MongoError.MongoError>
316320
} = F.dual(
317321
(args) => isDocumentCollection(args[0]),
318322
(
319323
collection: DocumentCollection,
320324
newName: string,
321325
options?: RenameOptions
322-
): Effect.Effect<MongoCollection, MongoError.MongoError> =>
326+
): Effect.Effect<DocumentCollection, MongoError.MongoError> =>
323327
F.pipe(
324328
Effect.promise(() => collection.collection.rename(newName, options)),
325-
Effect.catchAllDefect(MongoError.mongoErrorDie<MongoCollection>("rename error"))
329+
Effect.map((collection) => new DocumentCollection({ collection })),
330+
Effect.catchAllDefect(MongoError.mongoErrorDie<DocumentCollection>("rename error"))
326331
)
327332
)
328333

@@ -386,26 +391,28 @@ export const createIndex: {
386391
)
387392
)
388393

394+
// TODO: review return type. Should we return Document like mongodb driver?
389395
export const dropIndex: {
390396
(
391397
indexName: string,
392398
options?: DropIndexesOptions
393-
): (collection: DocumentCollection) => Effect.Effect<Document, MongoError.MongoError>
399+
): (collection: DocumentCollection) => Effect.Effect<void, MongoError.MongoError>
394400
(
395401
collection: DocumentCollection,
396402
indexName: string,
397403
options?: DropIndexesOptions
398-
): Effect.Effect<Document, MongoError.MongoError>
404+
): Effect.Effect<void, MongoError.MongoError>
399405
} = F.dual(
400406
(args) => isDocumentCollection(args[0]),
401407
(
402408
collection: DocumentCollection,
403409
indexName: string,
404410
options?: DropIndexesOptions
405-
): Effect.Effect<Document, MongoError.MongoError> =>
411+
): Effect.Effect<void, MongoError.MongoError> =>
406412
F.pipe(
407413
Effect.promise(() => collection.collection.dropIndex(indexName, options)),
408-
Effect.catchAllDefect(MongoError.mongoErrorDie<Document>("dropIndex error"))
414+
Effect.asVoid,
415+
Effect.catchAllDefect(MongoError.mongoErrorDie<void>("dropIndex error"))
409416
)
410417
)
411418

0 commit comments

Comments
 (0)