effect-mongodb 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +19 -0
  2. package/dist/cjs/AggregationCursor.js +4 -4
  3. package/dist/cjs/AggregationCursor.js.map +1 -1
  4. package/dist/cjs/Collection.js +24 -22
  5. package/dist/cjs/Collection.js.map +1 -1
  6. package/dist/cjs/Db.js +2 -2
  7. package/dist/cjs/Db.js.map +1 -1
  8. package/dist/cjs/DocumentAggregationCursor.js +4 -4
  9. package/dist/cjs/DocumentAggregationCursor.js.map +1 -1
  10. package/dist/cjs/DocumentCollection.js +24 -22
  11. package/dist/cjs/DocumentCollection.js.map +1 -1
  12. package/dist/cjs/DocumentFindCursor.js +27 -11
  13. package/dist/cjs/DocumentFindCursor.js.map +1 -1
  14. package/dist/cjs/FindCursor.js +33 -17
  15. package/dist/cjs/FindCursor.js.map +1 -1
  16. package/dist/cjs/ListCollectionsCursor.js +4 -4
  17. package/dist/cjs/ListCollectionsCursor.js.map +1 -1
  18. package/dist/cjs/MongoClient.js +3 -3
  19. package/dist/cjs/MongoClient.js.map +1 -1
  20. package/dist/cjs/internal/mongo-operation.js +18 -0
  21. package/dist/cjs/internal/mongo-operation.js.map +1 -0
  22. package/dist/cjs/internal/tracing.js +49 -0
  23. package/dist/cjs/internal/tracing.js.map +1 -0
  24. package/dist/cjs/internal/version.js +1 -1
  25. package/dist/dts/Collection.d.ts.map +1 -1
  26. package/dist/dts/DocumentCollection.d.ts.map +1 -1
  27. package/dist/dts/DocumentFindCursor.d.ts +4 -2
  28. package/dist/dts/DocumentFindCursor.d.ts.map +1 -1
  29. package/dist/dts/FindCursor.d.ts +4 -2
  30. package/dist/dts/FindCursor.d.ts.map +1 -1
  31. package/dist/dts/MongoClient.d.ts.map +1 -1
  32. package/dist/dts/internal/mongo-operation.d.ts +6 -0
  33. package/dist/dts/internal/mongo-operation.d.ts.map +1 -0
  34. package/dist/dts/internal/tracing.d.ts +6 -0
  35. package/dist/dts/internal/tracing.d.ts.map +1 -0
  36. package/dist/esm/AggregationCursor.js +4 -4
  37. package/dist/esm/AggregationCursor.js.map +1 -1
  38. package/dist/esm/Collection.js +24 -22
  39. package/dist/esm/Collection.js.map +1 -1
  40. package/dist/esm/Db.js +2 -2
  41. package/dist/esm/Db.js.map +1 -1
  42. package/dist/esm/DocumentAggregationCursor.js +4 -4
  43. package/dist/esm/DocumentAggregationCursor.js.map +1 -1
  44. package/dist/esm/DocumentCollection.js +24 -22
  45. package/dist/esm/DocumentCollection.js.map +1 -1
  46. package/dist/esm/DocumentFindCursor.js +27 -11
  47. package/dist/esm/DocumentFindCursor.js.map +1 -1
  48. package/dist/esm/FindCursor.js +31 -16
  49. package/dist/esm/FindCursor.js.map +1 -1
  50. package/dist/esm/ListCollectionsCursor.js +4 -4
  51. package/dist/esm/ListCollectionsCursor.js.map +1 -1
  52. package/dist/esm/MongoClient.js +3 -3
  53. package/dist/esm/MongoClient.js.map +1 -1
  54. package/dist/esm/internal/mongo-operation.js +8 -0
  55. package/dist/esm/internal/mongo-operation.js.map +1 -0
  56. package/dist/esm/internal/tracing.js +39 -0
  57. package/dist/esm/internal/tracing.js.map +1 -0
  58. package/dist/esm/internal/version.js +1 -1
  59. package/package.json +1 -1
  60. package/src/AggregationCursor.ts +4 -4
  61. package/src/Collection.ts +24 -26
  62. package/src/Db.ts +2 -2
  63. package/src/DocumentAggregationCursor.ts +4 -4
  64. package/src/DocumentCollection.ts +27 -31
  65. package/src/DocumentFindCursor.ts +28 -15
  66. package/src/FindCursor.ts +35 -18
  67. package/src/ListCollectionsCursor.ts +4 -4
  68. package/src/MongoClient.ts +3 -5
  69. package/src/internal/mongo-operation.ts +22 -0
  70. package/src/internal/tracing.ts +47 -0
  71. package/src/internal/version.ts +1 -1
@@ -45,7 +45,7 @@ import * as Collection from "./Collection.js"
45
45
  import * as DocumentAggregationCursor from "./DocumentAggregationCursor.js"
46
46
  import * as DocumentFindCursor from "./DocumentFindCursor.js"
47
47
  import type { ModifyResult } from "./internal/modify-result.js"
48
- import { mongoErrorOrDie } from "./internal/mongo-error.js"
48
+ import { mongoOperation } from "./internal/mongo-operation.js"
49
49
  import * as MongoError from "./MongoError.js"
50
50
 
51
51
  type DocumentCollectionFields = {
@@ -78,11 +78,11 @@ export const find: {
78
78
  } = F.dual(
79
79
  (args) => isDocumentCollection(args[0]),
80
80
  (collection: DocumentCollection, filter?: Filter<Document>, options?: FindOptions) =>
81
- new DocumentFindCursor.DocumentFindCursorImpl(
82
- {
83
- cursor: collection.collection.find(filter ?? {}, options)
84
- }
85
- )
81
+ new DocumentFindCursor.DocumentFindCursorImpl({
82
+ collection: collection.collection,
83
+ filter: filter ?? {},
84
+ options: options ?? {}
85
+ })
86
86
  )
87
87
 
88
88
  export const findOne: {
@@ -104,7 +104,7 @@ export const findOne: {
104
104
  F.pipe(
105
105
  Effect.promise(() => collection.collection.findOne(filter, options)),
106
106
  Effect.map((value) => O.fromNullable(value)),
107
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "findOne")))
107
+ mongoOperation(errorSource(collection, "findOne"))
108
108
  )
109
109
  )
110
110
 
@@ -128,7 +128,7 @@ export const insertOne: {
128
128
  ): Effect.Effect<InsertOneResult, MongoError.MongoError> =>
129
129
  F.pipe(
130
130
  Effect.promise(() => collection.collection.insertOne(doc, options)),
131
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "insertOne")))
131
+ mongoOperation(errorSource(collection, "insertOne"))
132
132
  ))
133
133
 
134
134
  export const insertMany: {
@@ -150,7 +150,7 @@ export const insertMany: {
150
150
  ): Effect.Effect<InsertManyResult, MongoError.MongoError> =>
151
151
  F.pipe(
152
152
  Effect.promise(() => collection.collection.insertMany(docs, options)),
153
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "insertMany")))
153
+ mongoOperation(errorSource(collection, "insertMany"))
154
154
  ))
155
155
 
156
156
  export const deleteOne: {
@@ -171,7 +171,7 @@ export const deleteOne: {
171
171
  ): Effect.Effect<DeleteResult, MongoError.MongoError> =>
172
172
  F.pipe(
173
173
  Effect.promise(() => collection.collection.deleteOne(filter, options)),
174
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "deleteOne")))
174
+ mongoOperation(errorSource(collection, "deleteOne"))
175
175
  )
176
176
  )
177
177
 
@@ -193,7 +193,7 @@ export const deleteMany: {
193
193
  ): Effect.Effect<DeleteResult, MongoError.MongoError> =>
194
194
  F.pipe(
195
195
  Effect.promise(() => collection.collection.deleteMany(filter, options)),
196
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "deleteMany")))
196
+ mongoOperation(errorSource(collection, "deleteMany"))
197
197
  )
198
198
  )
199
199
 
@@ -223,7 +223,7 @@ export const updateOne: {
223
223
  Effect.promise(() =>
224
224
  collection.collection.updateOne(filter, Array.isArray(update) ? [...update] : update, options)
225
225
  ),
226
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "updateOne")))
226
+ mongoOperation(errorSource(collection, "updateOne"))
227
227
  )
228
228
  )
229
229
 
@@ -253,7 +253,7 @@ export const updateMany: {
253
253
  Effect.promise(() =>
254
254
  collection.collection.updateMany(filter, Array.isArray(update) ? [...update] : update, options)
255
255
  ),
256
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "updateMany")))
256
+ mongoOperation(errorSource(collection, "updateMany"))
257
257
  )
258
258
  )
259
259
 
@@ -281,7 +281,7 @@ export const replaceOne: {
281
281
  ): Effect.Effect<UpdateResult | Document, MongoError.MongoError> =>
282
282
  F.pipe(
283
283
  Effect.promise(() => collection.collection.replaceOne(filter, replacement, options)),
284
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "replaceOne")))
284
+ mongoOperation(errorSource(collection, "replaceOne"))
285
285
  )
286
286
  )
287
287
 
@@ -350,9 +350,7 @@ export const findOneAndReplace: {
350
350
  }
351
351
  return O.fromNullable(value)
352
352
  }),
353
- Effect.catchAllDefect(
354
- mongoErrorOrDie(errorSource(collection, "findOneAndReplace"))
355
- )
353
+ mongoOperation(errorSource(collection, "findOneAndReplace"))
356
354
  )
357
355
  )
358
356
 
@@ -427,9 +425,7 @@ export const findOneAndUpdate: {
427
425
  }
428
426
  return O.fromNullable(value)
429
427
  }),
430
- Effect.catchAllDefect(
431
- mongoErrorOrDie(errorSource(collection, "findOneAndUpdate"))
432
- )
428
+ mongoOperation(errorSource(collection, "findOneAndUpdate"))
433
429
  )
434
430
  )
435
431
 
@@ -452,7 +448,7 @@ export const rename: {
452
448
  F.pipe(
453
449
  Effect.promise(() => collection.collection.rename(newName, options)),
454
450
  Effect.map((collection) => new DocumentCollectionImpl({ collection })),
455
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "rename")))
451
+ mongoOperation(errorSource(collection, "rename"))
456
452
  )
457
453
  )
458
454
 
@@ -467,7 +463,7 @@ export const drop: {
467
463
  ): Effect.Effect<boolean, MongoError.MongoError> =>
468
464
  F.pipe(
469
465
  Effect.promise(() => collection.collection.drop(options)),
470
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "drop")))
466
+ mongoOperation(errorSource(collection, "drop"))
471
467
  )
472
468
  )
473
469
 
@@ -489,7 +485,7 @@ export const createIndexes: {
489
485
  ): Effect.Effect<Array<string>, MongoError.MongoError> =>
490
486
  F.pipe(
491
487
  Effect.promise(() => collection.collection.createIndexes([...indexSpecs], options)),
492
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "createIndexes")))
488
+ mongoOperation(errorSource(collection, "createIndexes"))
493
489
  )
494
490
  )
495
491
 
@@ -512,7 +508,7 @@ export const createIndex: {
512
508
  ): Effect.Effect<string, MongoError.MongoError> =>
513
509
  F.pipe(
514
510
  Effect.promise(() => collection.collection.createIndex(indexSpec, options)),
515
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "createIndex")))
511
+ mongoOperation(errorSource(collection, "createIndex"))
516
512
  )
517
513
  )
518
514
 
@@ -535,7 +531,7 @@ export const dropIndex: {
535
531
  ): Effect.Effect<Document, MongoError.MongoError> =>
536
532
  F.pipe(
537
533
  Effect.promise(() => collection.collection.dropIndex(indexName, options)),
538
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "dropIndex")))
534
+ mongoOperation(errorSource(collection, "dropIndex"))
539
535
  )
540
536
  )
541
537
 
@@ -555,7 +551,7 @@ export const dropIndexes: {
555
551
  ): Effect.Effect<boolean, MongoError.MongoError> =>
556
552
  F.pipe(
557
553
  Effect.promise(() => collection.collection.dropIndexes(options)),
558
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "dropIndexes")))
554
+ mongoOperation(errorSource(collection, "dropIndexes"))
559
555
  )
560
556
  )
561
557
 
@@ -596,7 +592,7 @@ export const estimatedDocumentCount: {
596
592
  ): Effect.Effect<number, MongoError.MongoError> =>
597
593
  F.pipe(
598
594
  Effect.promise(() => collection.collection.estimatedDocumentCount(options)),
599
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "estimatedDocumentCount")))
595
+ mongoOperation(errorSource(collection, "estimatedDocumentCount"))
600
596
  )
601
597
  )
602
598
 
@@ -618,7 +614,7 @@ export const countDocuments: {
618
614
  ): Effect.Effect<number, MongoError.MongoError> =>
619
615
  F.pipe(
620
616
  Effect.promise(() => collection.collection.countDocuments(filter, options)),
621
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "countDocuments")))
617
+ mongoOperation(errorSource(collection, "countDocuments"))
622
618
  )
623
619
  )
624
620
 
@@ -653,8 +649,8 @@ export const bulkWrite: {
653
649
  operations: ReadonlyArray<AnyBulkWriteOperation<Document>>,
654
650
  options?: BulkWriteOptions
655
651
  ): Effect.Effect<BulkWriteResult, MongoError.MongoError> =>
656
- Effect.tryPromise(() => collection.collection.bulkWrite(operations, options)).pipe(
657
- Effect.catchAll(mongoErrorOrDie(errorSource(collection, "bulkWrite")))
652
+ Effect.promise(() => collection.collection.bulkWrite(operations, options)).pipe(
653
+ mongoOperation(errorSource(collection, "bulkWrite"))
658
654
  )
659
655
  )
660
656
 
@@ -665,7 +661,7 @@ const errorSource = (
665
661
  functionName: string
666
662
  ) =>
667
663
  new MongoError.CollectionErrorSource({
668
- module: DocumentCollectionImpl.name,
664
+ module: "DocumentCollection",
669
665
  functionName,
670
666
  db: collection.collection.dbName,
671
667
  collection: collection.collection.collectionName
@@ -8,13 +8,15 @@ import type { Pipeable } from "effect/Pipeable"
8
8
  import { pipeArguments } from "effect/Pipeable"
9
9
  import type * as Schema from "effect/Schema"
10
10
  import * as Stream from "effect/Stream"
11
- import type { Document, Filter, FindCursor as MongoFindCursor, Sort, SortDirection } from "mongodb"
11
+ import type { Collection as MongoCollection, Document, Filter, FindOptions, Sort, SortDirection } from "mongodb"
12
12
  import * as FindCursor from "./FindCursor.js"
13
- import { mongoErrorOrDie } from "./internal/mongo-error.js"
13
+ import { mongoOperation, mongoStreamOperation } from "./internal/mongo-operation.js"
14
14
  import * as MongoError from "./MongoError.js"
15
15
 
16
16
  type DocumentFindCursorFields = {
17
- cursor: MongoFindCursor<Document>
17
+ collection: MongoCollection
18
+ filter: Filter<Document>
19
+ options: FindOptions
18
20
  }
19
21
 
20
22
  export interface DocumentFindCursor extends DocumentFindCursorFields, Pipeable {
@@ -36,7 +38,7 @@ export const filter: {
36
38
  } = F.dual(
37
39
  (args) => isDocumentFindCursor(args[0]),
38
40
  (cursor: DocumentFindCursor, filter: Filter<Document>): DocumentFindCursor =>
39
- new DocumentFindCursorImpl({ cursor: cursor.cursor.filter(filter) })
41
+ new DocumentFindCursorImpl({ ...cursor, filter })
40
42
  )
41
43
 
42
44
  export const project: {
@@ -45,7 +47,7 @@ export const project: {
45
47
  } = F.dual(
46
48
  (args) => isDocumentFindCursor(args[0]),
47
49
  (cursor: DocumentFindCursor, value: Document): DocumentFindCursor =>
48
- new DocumentFindCursorImpl({ cursor: cursor.cursor.project(value) })
50
+ new DocumentFindCursorImpl({ ...cursor, options: { ...cursor.options, projection: value } })
49
51
  )
50
52
 
51
53
  export const sort: {
@@ -54,7 +56,10 @@ export const sort: {
54
56
  } = F.dual(
55
57
  (args) => isDocumentFindCursor(args[0]),
56
58
  (cursor: DocumentFindCursor, sort: Sort | string, direction?: SortDirection): DocumentFindCursor =>
57
- new DocumentFindCursorImpl({ cursor: cursor.cursor.sort(sort, direction) })
59
+ new DocumentFindCursorImpl({
60
+ ...cursor,
61
+ options: { ...cursor.options, sort: FindCursor.sortOption(sort, direction) }
62
+ })
58
63
  )
59
64
 
60
65
  export const limit: {
@@ -63,21 +68,21 @@ export const limit: {
63
68
  } = F.dual(
64
69
  (args) => isDocumentFindCursor(args[0]),
65
70
  (cursor: DocumentFindCursor, value: number): DocumentFindCursor =>
66
- new DocumentFindCursorImpl({ cursor: cursor.cursor.limit(value) })
71
+ new DocumentFindCursorImpl({ ...cursor, options: { ...cursor.options, limit: value } })
67
72
  )
68
73
 
69
74
  export const toArray = (cursor: DocumentFindCursor): Effect.Effect<Array<Document>, MongoError.MongoError> =>
70
75
  F.pipe(
71
- Effect.promise(() => cursor.cursor.toArray()),
72
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(cursor, "toArray")))
76
+ Effect.promise(() => nativeCursor(cursor).toArray()),
77
+ mongoOperation(errorSource(cursor, "toArray"))
73
78
  )
74
79
 
75
80
  export const toStream = (
76
81
  cursor: DocumentFindCursor
77
82
  ): Stream.Stream<Document, MongoError.MongoError> =>
78
83
  F.pipe(
79
- Stream.fromAsyncIterable(cursor.cursor, F.identity),
80
- Stream.catchAll(mongoErrorOrDie(errorSource(cursor, "toStream")))
84
+ Stream.suspend(() => Stream.fromAsyncIterable(nativeCursor(cursor), F.identity)),
85
+ mongoStreamOperation(errorSource(cursor, "toStream"))
81
86
  )
82
87
 
83
88
  export const typed: {
@@ -86,14 +91,22 @@ export const typed: {
86
91
  } = F.dual((args) => isDocumentFindCursor(args[0]), <A, I = A, R = never>(
87
92
  cursor: DocumentFindCursor,
88
93
  schema: Schema.Schema<A, I, R>
89
- ): FindCursor.FindCursor<A, I, R> => new FindCursor.FindCursorImpl<A, I, R>({ cursor: cursor.cursor, schema }))
94
+ ): FindCursor.FindCursor<A, I, R> =>
95
+ new FindCursor.FindCursorImpl<A, I, R>({
96
+ collection: cursor.collection,
97
+ filter: cursor.filter,
98
+ options: cursor.options,
99
+ schema
100
+ }))
101
+
102
+ const nativeCursor = (cursor: DocumentFindCursor) => cursor.collection.find(cursor.filter, cursor.options)
90
103
 
91
104
  const isDocumentFindCursor = (x: unknown) => x instanceof DocumentFindCursorImpl
92
105
 
93
106
  const errorSource = (cursor: DocumentFindCursor, functionName: string) =>
94
107
  new MongoError.CollectionErrorSource({
95
- module: DocumentFindCursorImpl.name,
108
+ module: "DocumentFindCursor",
96
109
  functionName,
97
- db: cursor.cursor.namespace.db,
98
- collection: cursor.cursor.namespace.collection ?? "NO_COLLECTION_NAME"
110
+ db: cursor.collection.dbName,
111
+ collection: cursor.collection.collectionName
99
112
  })
package/src/FindCursor.ts CHANGED
@@ -11,13 +11,22 @@ import { pipeArguments } from "effect/Pipeable"
11
11
  import * as Schema from "effect/Schema"
12
12
  import * as Stream from "effect/Stream"
13
13
  import * as Tuple from "effect/Tuple"
14
- import type { Document, FindCursor as FindCursor_, Sort, SortDirection } from "mongodb"
14
+ import type {
15
+ Collection as MongoCollection,
16
+ Document,
17
+ Filter as MongoFilter,
18
+ FindOptions as MongoFindOptions,
19
+ Sort,
20
+ SortDirection
21
+ } from "mongodb"
15
22
  import type { Filter as Filter_ } from "./internal/filter.js"
16
- import { mongoErrorOrDie } from "./internal/mongo-error.js"
23
+ import { mongoOperation, mongoStreamOperation } from "./internal/mongo-operation.js"
17
24
  import * as MongoError from "./MongoError.js"
18
25
 
19
26
  type FindCursorFields<A, I = A, R = never> = {
20
- cursor: FindCursor_<unknown>
27
+ collection: MongoCollection
28
+ filter: MongoFilter<Document>
29
+ options: MongoFindOptions
21
30
  schema: Schema.Schema<A, I, R>
22
31
  }
23
32
 
@@ -44,7 +53,7 @@ export const filter: {
44
53
  <A, I extends Document, R>(
45
54
  cursor: FindCursor<A, I, R>,
46
55
  filter: Filter<I>
47
- ): FindCursor<A, I, R> => new FindCursorImpl({ cursor: cursor.cursor.filter(filter), schema: cursor.schema })
56
+ ): FindCursor<A, I, R> => new FindCursorImpl({ ...cursor, filter })
48
57
  )
49
58
 
50
59
  export const project: {
@@ -63,7 +72,8 @@ export const project: {
63
72
  cursor: FindCursor<A, I, R>,
64
73
  newSchema: Schema.Schema<B, BI, BR>,
65
74
  value: T
66
- ): FindCursor<B, BI, BR> => new FindCursorImpl({ cursor: cursor.cursor.project(value), schema: newSchema })
75
+ ): FindCursor<B, BI, BR> =>
76
+ new FindCursorImpl({ ...cursor, schema: newSchema, options: { ...cursor.options, projection: value } })
67
77
  )
68
78
 
69
79
  export const sort: {
@@ -79,7 +89,8 @@ export const sort: {
79
89
  cursor: FindCursor<A, I, R>,
80
90
  sort: Sort | string,
81
91
  direction?: SortDirection
82
- ): FindCursor<A, I, R> => new FindCursorImpl({ cursor: cursor.cursor.sort(sort, direction), schema: cursor.schema })
92
+ ): FindCursor<A, I, R> =>
93
+ new FindCursorImpl({ ...cursor, options: { ...cursor.options, sort: sortOption(sort, direction) } })
83
94
  )
84
95
 
85
96
  export const limit: {
@@ -88,15 +99,15 @@ export const limit: {
88
99
  } = F.dual(
89
100
  (args) => isFindCursor(args[0]),
90
101
  <A, I, R>(cursor: FindCursor<A, I, R>, value: number): FindCursor<A, I, R> =>
91
- new FindCursorImpl({ cursor: cursor.cursor.limit(value), schema: cursor.schema })
102
+ new FindCursorImpl({ ...cursor, options: { ...cursor.options, limit: value } })
92
103
  )
93
104
 
94
105
  export const toArray = <A, I, R>(
95
106
  cursor: FindCursor<A, I, R>
96
107
  ): Effect.Effect<Array<A>, MongoError.MongoError | ParseResult.ParseError, R> => {
97
108
  const decode = Schema.decodeUnknown(cursor.schema)
98
- return Effect.promise(() => cursor.cursor.toArray()).pipe(
99
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(cursor, "toArray"))),
109
+ return Effect.promise(() => nativeCursor(cursor).toArray()).pipe(
110
+ mongoOperation(errorSource(cursor, "toArray")),
100
111
  Effect.flatMap(Effect.forEach((x) => decode(x)))
101
112
  )
102
113
  }
@@ -109,8 +120,8 @@ export const toArrayEither = <A, I, R>(
109
120
  R
110
121
  > => {
111
122
  const decode = Schema.decodeUnknown(cursor.schema)
112
- return Effect.promise(() => cursor.cursor.toArray()).pipe(
113
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(cursor, "toArrayEither"))),
123
+ return Effect.promise(() => nativeCursor(cursor).toArray()).pipe(
124
+ mongoOperation(errorSource(cursor, "toArrayEither")),
114
125
  Effect.flatMap(Effect.forEach((x) =>
115
126
  F.pipe(
116
127
  decode(x),
@@ -126,8 +137,8 @@ export const toStream = <A, I, R>(
126
137
  ): Stream.Stream<A, MongoError.MongoError | ParseResult.ParseError, R> => {
127
138
  const decode = Schema.decodeUnknown(cursor.schema)
128
139
  return F.pipe(
129
- Stream.fromAsyncIterable(cursor.cursor, F.identity),
130
- Stream.catchAll(mongoErrorOrDie(errorSource(cursor, "toStream"))),
140
+ Stream.suspend(() => Stream.fromAsyncIterable(nativeCursor(cursor), F.identity)),
141
+ mongoStreamOperation(errorSource(cursor, "toStream")),
131
142
  Stream.mapEffect((x) => decode(x))
132
143
  )
133
144
  }
@@ -137,8 +148,8 @@ export const toStreamEither = <A, I, R>(
137
148
  ): Stream.Stream<E.Either<A, [document: unknown, error: ParseResult.ParseError]>, MongoError.MongoError, R> => {
138
149
  const decode = Schema.decodeUnknown(cursor.schema)
139
150
  return F.pipe(
140
- Stream.fromAsyncIterable(cursor.cursor, F.identity),
141
- Stream.catchAll(mongoErrorOrDie(errorSource(cursor, "toStreamEither"))),
151
+ Stream.suspend(() => Stream.fromAsyncIterable(nativeCursor(cursor), F.identity)),
152
+ mongoStreamOperation(errorSource(cursor, "toStreamEither")),
142
153
  Stream.mapEffect((x) =>
143
154
  F.pipe(
144
155
  // keep new line
@@ -150,12 +161,18 @@ export const toStreamEither = <A, I, R>(
150
161
  )
151
162
  }
152
163
 
164
+ /** @internal */
165
+ export const sortOption = (sort: Sort | string, direction?: SortDirection): Sort =>
166
+ typeof sort === "string" && direction !== undefined ? { [sort]: direction } : sort
167
+
168
+ const nativeCursor = <A, I, R>(cursor: FindCursor<A, I, R>) => cursor.collection.find(cursor.filter, cursor.options)
169
+
153
170
  const isFindCursor = (x: unknown): x is FindCursor<unknown> => x instanceof FindCursorImpl
154
171
 
155
172
  const errorSource = <A, I, R>(cursor: FindCursor<A, I, R>, functionName: string) =>
156
173
  new MongoError.CollectionErrorSource({
157
- module: FindCursorImpl.name,
174
+ module: "FindCursor",
158
175
  functionName,
159
- db: cursor.cursor.namespace.db,
160
- collection: cursor.cursor.namespace.collection ?? "NO_COLLECTION_NAME"
176
+ db: cursor.collection.dbName,
177
+ collection: cursor.collection.collectionName
161
178
  })
@@ -11,7 +11,7 @@ import type {
11
11
  CollectionInfo as MongoCollectionInfo,
12
12
  ListCollectionsCursor as MongoListCollectionsCursor
13
13
  } from "mongodb"
14
- import { mongoErrorOrDie } from "./internal/mongo-error.js"
14
+ import { mongoOperation, mongoStreamOperation } from "./internal/mongo-operation.js"
15
15
  import * as MongoError from "./MongoError.js"
16
16
 
17
17
  export type NameOnlyCollectionInfo = Pick<MongoCollectionInfo, "name" | "type">
@@ -49,7 +49,7 @@ export const toArray = <T extends DefaultCollectionInfo>(
49
49
  ): Effect.Effect<Array<T>, MongoError.MongoError> =>
50
50
  F.pipe(
51
51
  Effect.promise(() => cursor.cursor.toArray()),
52
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(cursor, "toArray")))
52
+ mongoOperation(errorSource(cursor, "toArray"))
53
53
  )
54
54
 
55
55
  export const toStream = <T extends DefaultCollectionInfo>(
@@ -57,12 +57,12 @@ export const toStream = <T extends DefaultCollectionInfo>(
57
57
  ): Stream.Stream<T, MongoError.MongoError> =>
58
58
  F.pipe(
59
59
  Stream.fromAsyncIterable(cursor.cursor, F.identity),
60
- Stream.catchAll(mongoErrorOrDie(errorSource(cursor, "toStream")))
60
+ mongoStreamOperation(errorSource(cursor, "toStream"))
61
61
  )
62
62
 
63
63
  const errorSource = (cursor: ListCollectionsCursor, functionName: string) =>
64
64
  new MongoError.CollectionErrorSource({
65
- module: ListCollectionsCursorImpl.name,
65
+ module: "ListCollectionsCursor",
66
66
  functionName,
67
67
  db: cursor.cursor.namespace.db,
68
68
  collection: cursor.cursor.namespace.collection ?? "NO_COLLECTION_NAME"
@@ -8,7 +8,7 @@ import type * as Scope from "effect/Scope"
8
8
  import type { DbOptions, MongoClientOptions } from "mongodb"
9
9
  import { MongoClient as MongoClient_ } from "mongodb"
10
10
  import * as Db from "./Db.js"
11
- import { mongoErrorOrDie } from "./internal/mongo-error.js"
11
+ import { mongoOperation } from "./internal/mongo-operation.js"
12
12
  import * as MongoError from "./MongoError.js"
13
13
 
14
14
  export class MongoClient extends Data.TaggedClass("MongoClient")<{ client: MongoClient_ }> {}
@@ -19,7 +19,7 @@ export const connect = (
19
19
  ): Effect.Effect<MongoClient, MongoError.MongoError> =>
20
20
  Effect.promise(() => MongoClient_.connect(url, options)).pipe(
21
21
  Effect.map((client) => new MongoClient({ client })),
22
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(hostsFromUrl(url), "connect")))
22
+ mongoOperation(errorSource(hostsFromUrl(url), "connect"))
23
23
  )
24
24
 
25
25
  export const close: {
@@ -29,9 +29,7 @@ export const close: {
29
29
  (args) => isMongoClient(args[0]),
30
30
  ({ client }: MongoClient, force?: boolean): Effect.Effect<void, MongoError.MongoError> =>
31
31
  Effect.promise(() => client.close(force)).pipe(
32
- Effect.catchAllDefect(
33
- mongoErrorOrDie(errorSource(client.options.hosts.map((x) => x.host ?? UNKNOWN_HOST), "close"))
34
- )
32
+ mongoOperation(errorSource(client.options.hosts.map((x) => x.host ?? UNKNOWN_HOST), "close"))
35
33
  )
36
34
  )
37
35
 
@@ -0,0 +1,22 @@
1
+ import * as Effect from "effect/Effect"
2
+ import * as F from "effect/Function"
3
+ import * as Stream from "effect/Stream"
4
+ import type { ErrorSource, MongoError } from "../MongoError.js"
5
+ import { mongoErrorOrDie } from "./mongo-error.js"
6
+ import { withSpan, withSpanStream } from "./tracing.js"
7
+
8
+ export const mongoOperation =
9
+ (source: ErrorSource) => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E | MongoError, R> =>
10
+ F.pipe(
11
+ self,
12
+ Effect.catchAllDefect(mongoErrorOrDie(source)),
13
+ withSpan(source)
14
+ )
15
+
16
+ export const mongoStreamOperation =
17
+ (source: ErrorSource) => <A, E, R>(self: Stream.Stream<A, E, R>): Stream.Stream<A, MongoError, R> =>
18
+ F.pipe(
19
+ self,
20
+ Stream.catchAll(mongoErrorOrDie(source)),
21
+ withSpanStream(source)
22
+ )
@@ -0,0 +1,47 @@
1
+ import * as Effect from "effect/Effect"
2
+ import * as F from "effect/Function"
3
+ import * as Match from "effect/Match"
4
+ import * as Stream from "effect/Stream"
5
+ import type * as Tracer from "effect/Tracer"
6
+ import type { ErrorSource } from "../MongoError.js"
7
+
8
+ export const withSpan = (source: ErrorSource) => <A, E, R>(self: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
9
+ Effect.withSpan(self, spanName(source), spanOptions(source))
10
+
11
+ export const withSpanStream =
12
+ (source: ErrorSource) => <A, E, R>(self: Stream.Stream<A, E, R>): Stream.Stream<A, E, R> =>
13
+ Stream.withSpan(self, spanName(source), spanOptions(source))
14
+
15
+ const spanName = (source: ErrorSource) => `mongodb.${source.module}.${source.functionName}`
16
+
17
+ const spanOptions = (source: ErrorSource): Tracer.SpanOptions => ({
18
+ kind: "client",
19
+ captureStackTrace: false,
20
+ attributes: {
21
+ "db.system.name": "mongodb",
22
+ "db.operation.name": source.functionName,
23
+ ...sourceAttributes(source)
24
+ }
25
+ })
26
+
27
+ const sourceAttributes = (source: ErrorSource): Record<string, unknown> =>
28
+ F.pipe(
29
+ Match.value(source),
30
+ Match.tag("ClientErrorSource", (s) => serverAttributes(s.hosts)),
31
+ Match.tag("DbErrorSource", (s) => ({ "db.namespace": s.db })),
32
+ Match.tag("CollectionErrorSource", (s) => ({ "db.namespace": s.db, "db.collection.name": s.collection })),
33
+ Match.exhaustive
34
+ )
35
+
36
+ const serverAttributes = (hosts: Array<string>): Record<string, unknown> => {
37
+ if (hosts.length !== 1) return {}
38
+ const [address, port] = splitHost(hosts[0])
39
+ return port === undefined ? { "server.address": address } : { "server.address": address, "server.port": port }
40
+ }
41
+
42
+ const splitHost = (host: string): [address: string, port: number | undefined] => {
43
+ const separator = host.lastIndexOf(":")
44
+ if (separator === -1) return [host, undefined]
45
+ const port = Number(host.slice(separator + 1))
46
+ return Number.isInteger(port) ? [host.slice(0, separator), port] : [host, undefined]
47
+ }
@@ -1,4 +1,4 @@
1
- let moduleVersion = "0.4.1"
1
+ let moduleVersion = "0.6.0"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4