effect-mongodb 0.4.0 → 0.5.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 (69) 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 +32 -21
  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 +31 -21
  11. package/dist/cjs/DocumentCollection.js.map +1 -1
  12. package/dist/cjs/DocumentFindCursor.js +4 -4
  13. package/dist/cjs/DocumentFindCursor.js.map +1 -1
  14. package/dist/cjs/FindCursor.js +6 -6
  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 +19 -1
  26. package/dist/dts/Collection.d.ts.map +1 -1
  27. package/dist/dts/DocumentCollection.d.ts +19 -1
  28. package/dist/dts/DocumentCollection.d.ts.map +1 -1
  29. package/dist/dts/MongoClient.d.ts.map +1 -1
  30. package/dist/dts/internal/mongo-operation.d.ts +6 -0
  31. package/dist/dts/internal/mongo-operation.d.ts.map +1 -0
  32. package/dist/dts/internal/tracing.d.ts +6 -0
  33. package/dist/dts/internal/tracing.d.ts.map +1 -0
  34. package/dist/esm/AggregationCursor.js +4 -4
  35. package/dist/esm/AggregationCursor.js.map +1 -1
  36. package/dist/esm/Collection.js +31 -20
  37. package/dist/esm/Collection.js.map +1 -1
  38. package/dist/esm/Db.js +2 -2
  39. package/dist/esm/Db.js.map +1 -1
  40. package/dist/esm/DocumentAggregationCursor.js +4 -4
  41. package/dist/esm/DocumentAggregationCursor.js.map +1 -1
  42. package/dist/esm/DocumentCollection.js +30 -20
  43. package/dist/esm/DocumentCollection.js.map +1 -1
  44. package/dist/esm/DocumentFindCursor.js +4 -4
  45. package/dist/esm/DocumentFindCursor.js.map +1 -1
  46. package/dist/esm/FindCursor.js +6 -6
  47. package/dist/esm/FindCursor.js.map +1 -1
  48. package/dist/esm/ListCollectionsCursor.js +4 -4
  49. package/dist/esm/ListCollectionsCursor.js.map +1 -1
  50. package/dist/esm/MongoClient.js +3 -3
  51. package/dist/esm/MongoClient.js.map +1 -1
  52. package/dist/esm/internal/mongo-operation.js +8 -0
  53. package/dist/esm/internal/mongo-operation.js.map +1 -0
  54. package/dist/esm/internal/tracing.js +39 -0
  55. package/dist/esm/internal/tracing.js.map +1 -0
  56. package/dist/esm/internal/version.js +1 -1
  57. package/package.json +1 -1
  58. package/src/AggregationCursor.ts +4 -4
  59. package/src/Collection.ts +103 -22
  60. package/src/Db.ts +2 -2
  61. package/src/DocumentAggregationCursor.ts +4 -4
  62. package/src/DocumentCollection.ts +97 -23
  63. package/src/DocumentFindCursor.ts +4 -4
  64. package/src/FindCursor.ts +6 -6
  65. package/src/ListCollectionsCursor.ts +4 -4
  66. package/src/MongoClient.ts +3 -5
  67. package/src/internal/mongo-operation.ts +22 -0
  68. package/src/internal/tracing.ts +47 -0
  69. package/src/internal/version.ts +1 -1
@@ -25,6 +25,7 @@ import type {
25
25
  EstimatedDocumentCountOptions,
26
26
  Filter,
27
27
  FindOneAndReplaceOptions,
28
+ FindOneAndUpdateOptions,
28
29
  FindOptions,
29
30
  IndexDescription,
30
31
  IndexSpecification,
@@ -44,7 +45,7 @@ import * as Collection from "./Collection.js"
44
45
  import * as DocumentAggregationCursor from "./DocumentAggregationCursor.js"
45
46
  import * as DocumentFindCursor from "./DocumentFindCursor.js"
46
47
  import type { ModifyResult } from "./internal/modify-result.js"
47
- import { mongoErrorOrDie } from "./internal/mongo-error.js"
48
+ import { mongoOperation } from "./internal/mongo-operation.js"
48
49
  import * as MongoError from "./MongoError.js"
49
50
 
50
51
  type DocumentCollectionFields = {
@@ -103,7 +104,7 @@ export const findOne: {
103
104
  F.pipe(
104
105
  Effect.promise(() => collection.collection.findOne(filter, options)),
105
106
  Effect.map((value) => O.fromNullable(value)),
106
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "findOne")))
107
+ mongoOperation(errorSource(collection, "findOne"))
107
108
  )
108
109
  )
109
110
 
@@ -127,7 +128,7 @@ export const insertOne: {
127
128
  ): Effect.Effect<InsertOneResult, MongoError.MongoError> =>
128
129
  F.pipe(
129
130
  Effect.promise(() => collection.collection.insertOne(doc, options)),
130
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "insertOne")))
131
+ mongoOperation(errorSource(collection, "insertOne"))
131
132
  ))
132
133
 
133
134
  export const insertMany: {
@@ -149,7 +150,7 @@ export const insertMany: {
149
150
  ): Effect.Effect<InsertManyResult, MongoError.MongoError> =>
150
151
  F.pipe(
151
152
  Effect.promise(() => collection.collection.insertMany(docs, options)),
152
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "insertMany")))
153
+ mongoOperation(errorSource(collection, "insertMany"))
153
154
  ))
154
155
 
155
156
  export const deleteOne: {
@@ -170,7 +171,7 @@ export const deleteOne: {
170
171
  ): Effect.Effect<DeleteResult, MongoError.MongoError> =>
171
172
  F.pipe(
172
173
  Effect.promise(() => collection.collection.deleteOne(filter, options)),
173
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "deleteOne")))
174
+ mongoOperation(errorSource(collection, "deleteOne"))
174
175
  )
175
176
  )
176
177
 
@@ -192,7 +193,7 @@ export const deleteMany: {
192
193
  ): Effect.Effect<DeleteResult, MongoError.MongoError> =>
193
194
  F.pipe(
194
195
  Effect.promise(() => collection.collection.deleteMany(filter, options)),
195
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "deleteMany")))
196
+ mongoOperation(errorSource(collection, "deleteMany"))
196
197
  )
197
198
  )
198
199
 
@@ -222,7 +223,7 @@ export const updateOne: {
222
223
  Effect.promise(() =>
223
224
  collection.collection.updateOne(filter, Array.isArray(update) ? [...update] : update, options)
224
225
  ),
225
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "updateOne")))
226
+ mongoOperation(errorSource(collection, "updateOne"))
226
227
  )
227
228
  )
228
229
 
@@ -252,7 +253,7 @@ export const updateMany: {
252
253
  Effect.promise(() =>
253
254
  collection.collection.updateMany(filter, Array.isArray(update) ? [...update] : update, options)
254
255
  ),
255
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "updateMany")))
256
+ mongoOperation(errorSource(collection, "updateMany"))
256
257
  )
257
258
  )
258
259
 
@@ -280,7 +281,7 @@ export const replaceOne: {
280
281
  ): Effect.Effect<UpdateResult | Document, MongoError.MongoError> =>
281
282
  F.pipe(
282
283
  Effect.promise(() => collection.collection.replaceOne(filter, replacement, options)),
283
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "replaceOne")))
284
+ mongoOperation(errorSource(collection, "replaceOne"))
284
285
  )
285
286
  )
286
287
 
@@ -349,9 +350,82 @@ export const findOneAndReplace: {
349
350
  }
350
351
  return O.fromNullable(value)
351
352
  }),
352
- Effect.catchAllDefect(
353
- mongoErrorOrDie(errorSource(collection, "findOneAndReplace"))
354
- )
353
+ mongoOperation(errorSource(collection, "findOneAndReplace"))
354
+ )
355
+ )
356
+
357
+ export const findOneAndUpdate: {
358
+ (
359
+ filter: Filter<Document>,
360
+ update: UpdateFilter<Document> | ReadonlyArray<Document>,
361
+ options: FindOneAndUpdateOptions & { includeResultMetadata: true }
362
+ ): (
363
+ collection: DocumentCollection
364
+ ) => Effect.Effect<ModifyResult<Document>, MongoError.MongoError>
365
+ (
366
+ filter: Filter<Document>,
367
+ update: UpdateFilter<Document> | ReadonlyArray<Document>,
368
+ options: FindOneAndUpdateOptions & { includeResultMetadata: false }
369
+ ): (
370
+ collection: DocumentCollection
371
+ ) => Effect.Effect<O.Option<Document>, MongoError.MongoError>
372
+ (
373
+ filter: Filter<Document>,
374
+ update: UpdateFilter<Document> | ReadonlyArray<Document>,
375
+ options: FindOneAndUpdateOptions
376
+ ): (
377
+ collection: DocumentCollection
378
+ ) => Effect.Effect<O.Option<Document>, MongoError.MongoError>
379
+ (filter: Filter<Document>, update: UpdateFilter<Document> | ReadonlyArray<Document>): (
380
+ collection: DocumentCollection
381
+ ) => Effect.Effect<O.Option<Document>, MongoError.MongoError>
382
+ (
383
+ collection: DocumentCollection,
384
+ filter: Filter<Document>,
385
+ update: UpdateFilter<Document> | ReadonlyArray<Document>,
386
+ options: FindOneAndUpdateOptions & { includeResultMetadata: true }
387
+ ): Effect.Effect<ModifyResult<Document>, MongoError.MongoError>
388
+ (
389
+ collection: DocumentCollection,
390
+ filter: Filter<Document>,
391
+ update: UpdateFilter<Document> | ReadonlyArray<Document>,
392
+ options: FindOneAndUpdateOptions & { includeResultMetadata: false }
393
+ ): Effect.Effect<O.Option<Document>, MongoError.MongoError>
394
+ (
395
+ collection: DocumentCollection,
396
+ filter: Filter<Document>,
397
+ update: UpdateFilter<Document> | ReadonlyArray<Document>,
398
+ options: FindOneAndUpdateOptions
399
+ ): Effect.Effect<O.Option<Document>, MongoError.MongoError>
400
+ (
401
+ collection: DocumentCollection,
402
+ filter: Filter<Document>,
403
+ update: UpdateFilter<Document> | ReadonlyArray<Document>
404
+ ): Effect.Effect<O.Option<Document>, MongoError.MongoError>
405
+ } = F.dual(
406
+ (args) => isDocumentCollection(args[0]),
407
+ (
408
+ collection: DocumentCollection,
409
+ filter: Filter<Document>,
410
+ update: UpdateFilter<Document> | ReadonlyArray<Document>,
411
+ options?: FindOneAndUpdateOptions
412
+ ): Effect.Effect<O.Option<Document> | ModifyResult<Document>, MongoError.MongoError> =>
413
+ F.pipe(
414
+ Effect.promise(() =>
415
+ collection.collection.findOneAndUpdate(
416
+ filter,
417
+ Array.isArray(update) ? [...update] : update,
418
+ options ?? {}
419
+ )
420
+ ),
421
+ Effect.map((value) => {
422
+ if (options?.includeResultMetadata && !!value) {
423
+ const result = value as unknown as MongoModifyResult<Document>
424
+ return { ...result, value: O.fromNullable(result.value) }
425
+ }
426
+ return O.fromNullable(value)
427
+ }),
428
+ mongoOperation(errorSource(collection, "findOneAndUpdate"))
355
429
  )
356
430
  )
357
431
 
@@ -374,7 +448,7 @@ export const rename: {
374
448
  F.pipe(
375
449
  Effect.promise(() => collection.collection.rename(newName, options)),
376
450
  Effect.map((collection) => new DocumentCollectionImpl({ collection })),
377
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "rename")))
451
+ mongoOperation(errorSource(collection, "rename"))
378
452
  )
379
453
  )
380
454
 
@@ -389,7 +463,7 @@ export const drop: {
389
463
  ): Effect.Effect<boolean, MongoError.MongoError> =>
390
464
  F.pipe(
391
465
  Effect.promise(() => collection.collection.drop(options)),
392
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "drop")))
466
+ mongoOperation(errorSource(collection, "drop"))
393
467
  )
394
468
  )
395
469
 
@@ -411,7 +485,7 @@ export const createIndexes: {
411
485
  ): Effect.Effect<Array<string>, MongoError.MongoError> =>
412
486
  F.pipe(
413
487
  Effect.promise(() => collection.collection.createIndexes([...indexSpecs], options)),
414
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "createIndexes")))
488
+ mongoOperation(errorSource(collection, "createIndexes"))
415
489
  )
416
490
  )
417
491
 
@@ -434,7 +508,7 @@ export const createIndex: {
434
508
  ): Effect.Effect<string, MongoError.MongoError> =>
435
509
  F.pipe(
436
510
  Effect.promise(() => collection.collection.createIndex(indexSpec, options)),
437
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "createIndex")))
511
+ mongoOperation(errorSource(collection, "createIndex"))
438
512
  )
439
513
  )
440
514
 
@@ -457,7 +531,7 @@ export const dropIndex: {
457
531
  ): Effect.Effect<Document, MongoError.MongoError> =>
458
532
  F.pipe(
459
533
  Effect.promise(() => collection.collection.dropIndex(indexName, options)),
460
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "dropIndex")))
534
+ mongoOperation(errorSource(collection, "dropIndex"))
461
535
  )
462
536
  )
463
537
 
@@ -477,7 +551,7 @@ export const dropIndexes: {
477
551
  ): Effect.Effect<boolean, MongoError.MongoError> =>
478
552
  F.pipe(
479
553
  Effect.promise(() => collection.collection.dropIndexes(options)),
480
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "dropIndexes")))
554
+ mongoOperation(errorSource(collection, "dropIndexes"))
481
555
  )
482
556
  )
483
557
 
@@ -518,7 +592,7 @@ export const estimatedDocumentCount: {
518
592
  ): Effect.Effect<number, MongoError.MongoError> =>
519
593
  F.pipe(
520
594
  Effect.promise(() => collection.collection.estimatedDocumentCount(options)),
521
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "estimatedDocumentCount")))
595
+ mongoOperation(errorSource(collection, "estimatedDocumentCount"))
522
596
  )
523
597
  )
524
598
 
@@ -540,7 +614,7 @@ export const countDocuments: {
540
614
  ): Effect.Effect<number, MongoError.MongoError> =>
541
615
  F.pipe(
542
616
  Effect.promise(() => collection.collection.countDocuments(filter, options)),
543
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(collection, "countDocuments")))
617
+ mongoOperation(errorSource(collection, "countDocuments"))
544
618
  )
545
619
  )
546
620
 
@@ -575,8 +649,8 @@ export const bulkWrite: {
575
649
  operations: ReadonlyArray<AnyBulkWriteOperation<Document>>,
576
650
  options?: BulkWriteOptions
577
651
  ): Effect.Effect<BulkWriteResult, MongoError.MongoError> =>
578
- Effect.tryPromise(() => collection.collection.bulkWrite(operations, options)).pipe(
579
- Effect.catchAll(mongoErrorOrDie(errorSource(collection, "bulkWrite")))
652
+ Effect.promise(() => collection.collection.bulkWrite(operations, options)).pipe(
653
+ mongoOperation(errorSource(collection, "bulkWrite"))
580
654
  )
581
655
  )
582
656
 
@@ -587,7 +661,7 @@ const errorSource = (
587
661
  functionName: string
588
662
  ) =>
589
663
  new MongoError.CollectionErrorSource({
590
- module: DocumentCollectionImpl.name,
664
+ module: "DocumentCollection",
591
665
  functionName,
592
666
  db: collection.collection.dbName,
593
667
  collection: collection.collection.collectionName
@@ -10,7 +10,7 @@ import type * as Schema from "effect/Schema"
10
10
  import * as Stream from "effect/Stream"
11
11
  import type { Document, Filter, FindCursor as MongoFindCursor, 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 = {
@@ -69,7 +69,7 @@ export const limit: {
69
69
  export const toArray = (cursor: DocumentFindCursor): Effect.Effect<Array<Document>, MongoError.MongoError> =>
70
70
  F.pipe(
71
71
  Effect.promise(() => cursor.cursor.toArray()),
72
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(cursor, "toArray")))
72
+ mongoOperation(errorSource(cursor, "toArray"))
73
73
  )
74
74
 
75
75
  export const toStream = (
@@ -77,7 +77,7 @@ export const toStream = (
77
77
  ): Stream.Stream<Document, MongoError.MongoError> =>
78
78
  F.pipe(
79
79
  Stream.fromAsyncIterable(cursor.cursor, F.identity),
80
- Stream.catchAll(mongoErrorOrDie(errorSource(cursor, "toStream")))
80
+ mongoStreamOperation(errorSource(cursor, "toStream"))
81
81
  )
82
82
 
83
83
  export const typed: {
@@ -92,7 +92,7 @@ const isDocumentFindCursor = (x: unknown) => x instanceof DocumentFindCursorImpl
92
92
 
93
93
  const errorSource = (cursor: DocumentFindCursor, functionName: string) =>
94
94
  new MongoError.CollectionErrorSource({
95
- module: DocumentFindCursorImpl.name,
95
+ module: "DocumentFindCursor",
96
96
  functionName,
97
97
  db: cursor.cursor.namespace.db,
98
98
  collection: cursor.cursor.namespace.collection ?? "NO_COLLECTION_NAME"
package/src/FindCursor.ts CHANGED
@@ -13,7 +13,7 @@ import * as Stream from "effect/Stream"
13
13
  import * as Tuple from "effect/Tuple"
14
14
  import type { Document, FindCursor as FindCursor_, Sort, SortDirection } from "mongodb"
15
15
  import type { Filter as Filter_ } from "./internal/filter.js"
16
- import { mongoErrorOrDie } from "./internal/mongo-error.js"
16
+ import { mongoOperation, mongoStreamOperation } from "./internal/mongo-operation.js"
17
17
  import * as MongoError from "./MongoError.js"
18
18
 
19
19
  type FindCursorFields<A, I = A, R = never> = {
@@ -96,7 +96,7 @@ export const toArray = <A, I, R>(
96
96
  ): Effect.Effect<Array<A>, MongoError.MongoError | ParseResult.ParseError, R> => {
97
97
  const decode = Schema.decodeUnknown(cursor.schema)
98
98
  return Effect.promise(() => cursor.cursor.toArray()).pipe(
99
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(cursor, "toArray"))),
99
+ mongoOperation(errorSource(cursor, "toArray")),
100
100
  Effect.flatMap(Effect.forEach((x) => decode(x)))
101
101
  )
102
102
  }
@@ -110,7 +110,7 @@ export const toArrayEither = <A, I, R>(
110
110
  > => {
111
111
  const decode = Schema.decodeUnknown(cursor.schema)
112
112
  return Effect.promise(() => cursor.cursor.toArray()).pipe(
113
- Effect.catchAllDefect(mongoErrorOrDie(errorSource(cursor, "toArrayEither"))),
113
+ mongoOperation(errorSource(cursor, "toArrayEither")),
114
114
  Effect.flatMap(Effect.forEach((x) =>
115
115
  F.pipe(
116
116
  decode(x),
@@ -127,7 +127,7 @@ export const toStream = <A, I, R>(
127
127
  const decode = Schema.decodeUnknown(cursor.schema)
128
128
  return F.pipe(
129
129
  Stream.fromAsyncIterable(cursor.cursor, F.identity),
130
- Stream.catchAll(mongoErrorOrDie(errorSource(cursor, "toStream"))),
130
+ mongoStreamOperation(errorSource(cursor, "toStream")),
131
131
  Stream.mapEffect((x) => decode(x))
132
132
  )
133
133
  }
@@ -138,7 +138,7 @@ export const toStreamEither = <A, I, R>(
138
138
  const decode = Schema.decodeUnknown(cursor.schema)
139
139
  return F.pipe(
140
140
  Stream.fromAsyncIterable(cursor.cursor, F.identity),
141
- Stream.catchAll(mongoErrorOrDie(errorSource(cursor, "toStreamEither"))),
141
+ mongoStreamOperation(errorSource(cursor, "toStreamEither")),
142
142
  Stream.mapEffect((x) =>
143
143
  F.pipe(
144
144
  // keep new line
@@ -154,7 +154,7 @@ const isFindCursor = (x: unknown): x is FindCursor<unknown> => x instanceof Find
154
154
 
155
155
  const errorSource = <A, I, R>(cursor: FindCursor<A, I, R>, functionName: string) =>
156
156
  new MongoError.CollectionErrorSource({
157
- module: FindCursorImpl.name,
157
+ module: "FindCursor",
158
158
  functionName,
159
159
  db: cursor.cursor.namespace.db,
160
160
  collection: cursor.cursor.namespace.collection ?? "NO_COLLECTION_NAME"
@@ -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.0"
1
+ let moduleVersion = "0.5.0"
2
2
 
3
3
  export const getCurrentVersion = () => moduleVersion
4
4