albatross 3.4.2 → 4.0.0-rc.2

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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Linus Unnebäck
3
+ Copyright (c) 2014-2021 Linus Unnebäck
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/index.d.ts CHANGED
@@ -1,101 +1,86 @@
1
1
  import * as mongodb from 'mongodb'
2
2
 
3
+ export { Binary, Code, Decimal128, Double, Int32, Long, MaxKey, MinKey, ObjectId, Timestamp } from 'mongodb'
4
+
3
5
  type DeepReadonly<T> = T extends Date | RegExp | string | number | boolean | bigint | symbol | undefined | null
4
6
  ? T
5
7
  : T extends {}
6
8
  ? { readonly [K in keyof T]: DeepReadonly<T[K]> }
7
9
  : Readonly<T>
8
10
 
9
- type FlattenIfArray<T> = T extends Array<infer R> ? R : T
10
11
  type SpecificProjection<T, TProjection> = Omit<T, 'projection'> & { projection: TProjection }
11
12
  type WithoutProjection<T> = T & { fields?: undefined, projection?: undefined }
12
13
 
13
- declare function albatross (uri: string): albatross.Albatross
14
-
15
- declare namespace albatross {
16
- interface Collection<TSchema extends { _id: any }> {
17
- readonly parent: Albatross
18
- id (hexString?: mongodb.ObjectId | string): mongodb.ObjectId
19
-
20
- findOne (filter: mongodb.FilterQuery<TSchema>, options?: WithoutProjection<mongodb.FindOneOptions<TSchema>>): Promise<TSchema | null>
21
- findOne<TKey extends keyof TSchema> (filter: mongodb.FilterQuery<TSchema>, options: SpecificProjection<mongodb.FindOneOptions<TSchema>, { [key in TKey]: 1 | true } & { _id: 0 | false }>): Promise<Pick<TSchema, TKey> | null>
22
- findOne<TKey extends keyof TSchema> (filter: mongodb.FilterQuery<TSchema>, options: SpecificProjection<mongodb.FindOneOptions<TSchema>, { [key in TKey]: 1 | true } & { _id?: 1 | true }>): Promise<Pick<TSchema, '_id' | TKey> | null>
23
- findOne (filter: mongodb.FilterQuery<TSchema>, options: mongodb.FindOneOptions<TSchema>): Promise<object | null>
24
-
25
- find (query: mongodb.FilterQuery<TSchema>, options?: WithoutProjection<mongodb.FindOneOptions<TSchema>>): Promise<TSchema[]>
26
- find<TKey extends keyof TSchema> (query: mongodb.FilterQuery<TSchema>, options: SpecificProjection<mongodb.FindOneOptions<TSchema>, { [key in TKey]: 1 | true } & { _id: 0 | false }>): Promise<Array<Pick<TSchema, TKey>>>
27
- find<TKey extends keyof TSchema> (query: mongodb.FilterQuery<TSchema>, options: SpecificProjection<mongodb.FindOneOptions<TSchema>, { [key in TKey]: 1 | true } & { _id?: 1 | true }>): Promise<Array<Pick<TSchema, '_id' | TKey>>>
28
- find (query: mongodb.FilterQuery<TSchema>, options: mongodb.FindOneOptions<TSchema>): Promise<object[]>
29
-
30
- count (query?: mongodb.FilterQuery<TSchema>, options?: mongodb.MongoCountPreferences): Promise<number>
31
-
32
- distinct<TKey extends keyof mongodb.WithId<TSchema>> (key: TKey, query?: mongodb.FilterQuery<TSchema>, options?: { readPreference?: mongodb.ReadPreference | string, maxTimeMS?: number, session?: mongodb.ClientSession }): Promise<Array<FlattenIfArray<mongodb.WithId<TSchema>[TKey]>>>
33
- distinct (key: string, query?: mongodb.FilterQuery<TSchema>, options?: { readPreference?: mongodb.ReadPreference | string, maxTimeMS?: number, session?: mongodb.ClientSession }): Promise<any[]>
34
-
35
- exists (query?: mongodb.FilterQuery<TSchema>): Promise<boolean>
36
-
37
- insert (doc: DeepReadonly<mongodb.OptionalId<TSchema>>, options?: mongodb.CollectionInsertOneOptions): Promise<mongodb.WithId<TSchema>>
38
- insert (docs: DeepReadonly<mongodb.OptionalId<TSchema>>[], options?: mongodb.CollectionInsertManyOptions): Promise<mongodb.WithId<TSchema>[]>
39
-
40
- findOneAndUpdate (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options: WithoutProjection<mongodb.FindOneAndUpdateOption<TSchema> & { returnOriginal: false, upsert: true }>): Promise<TSchema>
41
- findOneAndUpdate (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options?: WithoutProjection<mongodb.FindOneAndUpdateOption<TSchema>>): Promise<TSchema | null>
42
-
43
- findOneAndUpdate<TKey extends keyof TSchema> (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options: SpecificProjection<mongodb.FindOneAndUpdateOption<TSchema> & { returnOriginal: false, upsert: true }, { [key in TKey]: 1 | true } & { _id: 0 | false }>): Promise<Pick<TSchema, TKey>>
44
- findOneAndUpdate<TKey extends keyof TSchema> (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options: SpecificProjection<mongodb.FindOneAndUpdateOption<TSchema>, { [key in TKey]: 1 | true } & { _id: 0 | false }>): Promise<Pick<TSchema, TKey> | null>
45
-
46
- findOneAndUpdate<TKey extends keyof TSchema> (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options: SpecificProjection<mongodb.FindOneAndUpdateOption<TSchema> & { returnOriginal: false, upsert: true }, { [key in TKey]: 1 | true } & { _id?: 1 | true }>): Promise<Pick<TSchema, '_id' | TKey>>
47
- findOneAndUpdate<TKey extends keyof TSchema> (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options: SpecificProjection<mongodb.FindOneAndUpdateOption<TSchema>, { [key in TKey]: 1 | true } & { _id?: 1 | true }>): Promise<Pick<TSchema, '_id' | TKey> | null>
48
-
49
- findOneAndUpdate (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options: mongodb.FindOneAndUpdateOption<TSchema> & { returnOriginal: false, upsert: true }): Promise<object>
50
- findOneAndUpdate (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options?: mongodb.FindOneAndUpdateOption<TSchema>): Promise<object | null>
51
-
52
- updateOne (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options?: mongodb.UpdateOneOptions): Promise<{ matched: 0 | 1, modified: 0 | 1 }>
53
- updateMany (filter: mongodb.FilterQuery<TSchema>, update: mongodb.UpdateQuery<TSchema> | Partial<TSchema>, options?: mongodb.UpdateManyOptions): Promise<{ matched: number, modified: number }>
54
-
55
- deleteOne (filter: mongodb.FilterQuery<TSchema>, options?: mongodb.CommonOptions & { bypassDocumentValidation?: boolean }): Promise<0 | 1>
56
- deleteMany (filter: mongodb.FilterQuery<TSchema>, options?: mongodb.CommonOptions): Promise<number>
57
-
58
- aggregate (pipeline: object[], options?: mongodb.CollectionAggregationOptions): Promise<object[]>
59
- }
60
-
61
- interface FileInfo {
62
- id: mongodb.ObjectId
63
- md5: string
64
- length: number
65
- chunkSize: number
66
- uploadDate: Date
67
- contentType: string
68
- filename: string
69
- metadata: any
70
- }
71
-
72
- interface Grid {
73
- readonly parent: Albatross
74
- id (hexString?: mongodb.ObjectId | string): mongodb.ObjectId
75
- upload (stream: NodeJS.ReadableStream, options?: mongodb.GridFSBucketOpenUploadStreamOptions & { filename?: string }): Promise<FileInfo>
76
- download (id: mongodb.ObjectId): Promise<FileInfo & { stream: NodeJS.ReadableStream }>
77
- delete (id: mongodb.ObjectId): Promise<void>
78
- }
79
-
80
- interface Albatross {
81
- id (hexString?: mongodb.ObjectId | string): mongodb.ObjectId
82
- collection<TSchema extends { _id: any }> (name: string): Collection<TSchema>
83
- grid (name?: string): Grid
84
- ping (timeout?: number): Promise<void>
85
- close (force?: boolean): Promise<void>
86
- }
87
-
88
- const Binary: typeof mongodb.Binary
89
- const Code: typeof mongodb.Code
90
- const DBRef: typeof mongodb.DBRef
91
- const Decimal128: typeof mongodb.Decimal128
92
- const Double: typeof mongodb.Double
93
- const Int32: typeof mongodb.Int32
94
- const Long: typeof mongodb.Long
95
- const MaxKey: typeof mongodb.MaxKey
96
- const MinKey: typeof mongodb.MinKey
97
- const ObjectId: typeof mongodb.ObjectId
98
- const Timestamp: typeof mongodb.Timestamp
14
+ export interface Collection<TSchema extends { _id: any }> {
15
+ readonly parent: Albatross
16
+ id (hexString?: mongodb.ObjectId | string): mongodb.ObjectId
17
+
18
+ findOne (filter: mongodb.Filter<TSchema>, options?: WithoutProjection<mongodb.FindOptions<TSchema>>): Promise<TSchema | null>
19
+ findOne<TKey extends keyof TSchema> (filter: mongodb.Filter<TSchema>, options: SpecificProjection<mongodb.FindOptions<TSchema>, { [key in TKey]: 1 | true } & { _id: 0 | false }>): Promise<Pick<TSchema, TKey> | null>
20
+ findOne<TKey extends keyof TSchema> (filter: mongodb.Filter<TSchema>, options: SpecificProjection<mongodb.FindOptions<TSchema>, { [key in TKey]: 1 | true } & { _id?: 1 | true }>): Promise<Pick<TSchema, '_id' | TKey> | null>
21
+ findOne (filter: mongodb.Filter<TSchema>, options: mongodb.FindOptions<TSchema>): Promise<object | null>
22
+
23
+ find (query: mongodb.Filter<TSchema>, options?: WithoutProjection<mongodb.FindOptions<TSchema>>): Promise<TSchema[]>
24
+ find<TKey extends keyof TSchema> (query: mongodb.Filter<TSchema>, options: SpecificProjection<mongodb.FindOptions<TSchema>, { [key in TKey]: 1 | true } & { _id: 0 | false }>): Promise<Array<Pick<TSchema, TKey>>>
25
+ find<TKey extends keyof TSchema> (query: mongodb.Filter<TSchema>, options: SpecificProjection<mongodb.FindOptions<TSchema>, { [key in TKey]: 1 | true } & { _id?: 1 | true }>): Promise<Array<Pick<TSchema, '_id' | TKey>>>
26
+ find (query: mongodb.Filter<TSchema>, options: mongodb.FindOptions<TSchema>): Promise<object[]>
27
+
28
+ count (query?: mongodb.Filter<TSchema>, options?: mongodb.CountOptions): Promise<number>
29
+
30
+ distinct<TKey extends keyof mongodb.WithId<TSchema>> (key: TKey, query?: mongodb.Filter<TSchema>, options?: mongodb.DistinctOptions): Promise<Array<mongodb.Flatten<mongodb.WithId<TSchema>[TKey]>>>
31
+ distinct (key: string, query?: mongodb.Filter<TSchema>, options?: mongodb.DistinctOptions): Promise<any[]>
32
+
33
+ exists (query?: mongodb.Filter<TSchema>): Promise<boolean>
34
+
35
+ insert (doc: DeepReadonly<mongodb.OptionalId<TSchema>>, options?: mongodb.InsertOneOptions): Promise<mongodb.WithId<TSchema>>
36
+ insert (docs: DeepReadonly<mongodb.OptionalId<TSchema>>[], options?: mongodb.BulkWriteOptions): Promise<mongodb.WithId<TSchema>[]>
37
+
38
+ findOneAndUpdate (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema>, options: WithoutProjection<mongodb.FindOneAndUpdateOptions & { returnDocument: 'after', upsert: true }>): Promise<TSchema>
39
+ findOneAndUpdate (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema>, options?: WithoutProjection<mongodb.FindOneAndUpdateOptions>): Promise<TSchema | null>
40
+
41
+ findOneAndUpdate<TKey extends keyof TSchema> (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema>, options: SpecificProjection<mongodb.FindOneAndUpdateOptions & { returnDocument: 'after', upsert: true }, { [key in TKey]: 1 | true } & { _id: 0 | false }>): Promise<Pick<TSchema, TKey>>
42
+ findOneAndUpdate<TKey extends keyof TSchema> (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema>, options: SpecificProjection<mongodb.FindOneAndUpdateOptions, { [key in TKey]: 1 | true } & { _id: 0 | false }>): Promise<Pick<TSchema, TKey> | null>
43
+
44
+ findOneAndUpdate<TKey extends keyof TSchema> (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema>, options: SpecificProjection<mongodb.FindOneAndUpdateOptions & { returnDocument: 'after', upsert: true }, { [key in TKey]: 1 | true } & { _id?: 1 | true }>): Promise<Pick<TSchema, '_id' | TKey>>
45
+ findOneAndUpdate<TKey extends keyof TSchema> (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema>, options: SpecificProjection<mongodb.FindOneAndUpdateOptions, { [key in TKey]: 1 | true } & { _id?: 1 | true }>): Promise<Pick<TSchema, '_id' | TKey> | null>
46
+
47
+ findOneAndUpdate (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema>, options: mongodb.FindOneAndUpdateOptions & { returnDocument: 'after', upsert: true }): Promise<object>
48
+ findOneAndUpdate (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema>, options?: mongodb.FindOneAndUpdateOptions): Promise<object | null>
49
+
50
+ updateOne (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema> | Partial<TSchema>, options?: mongodb.UpdateOptions): Promise<{ matched: 0 | 1, modified: 0 | 1 }>
51
+ updateMany (filter: mongodb.Filter<TSchema>, update: mongodb.UpdateFilter<TSchema>, options?: mongodb.UpdateOptions): Promise<{ matched: number, modified: number }>
52
+
53
+ deleteOne (filter: mongodb.Filter<TSchema>, options?: mongodb.DeleteOptions): Promise<0 | 1>
54
+ deleteMany (filter: mongodb.Filter<TSchema>, options?: mongodb.DeleteOptions): Promise<number>
55
+
56
+ aggregate (pipeline: object[], options?: mongodb.AggregateOptions): Promise<object[]>
57
+ }
58
+
59
+ export interface FileInfo {
60
+ id: mongodb.ObjectId
61
+ length: number
62
+ chunkSize: number
63
+ uploadDate: Date
64
+ contentType: string
65
+ filename: string
66
+ metadata: any
67
+ }
68
+
69
+ export interface Grid {
70
+ readonly parent: Albatross
71
+ id (hexString?: mongodb.ObjectId | string): mongodb.ObjectId
72
+ upload (stream: NodeJS.ReadableStream, options?: mongodb.GridFSBucketWriteStreamOptions & { filename?: string }): Promise<FileInfo>
73
+ download (id: mongodb.ObjectId): Promise<FileInfo & { stream: NodeJS.ReadableStream }>
74
+ delete (id: mongodb.ObjectId): Promise<void>
75
+ }
76
+
77
+ export interface Albatross {
78
+ id (hexString?: mongodb.ObjectId | string): mongodb.ObjectId
79
+ collection<TSchema extends { _id: any }> (name: string): Collection<TSchema>
80
+ grid (name?: string): Grid
81
+ ping (timeout?: number): Promise<void>
82
+ transaction<T> (fn: (session: mongodb.ClientSession) => PromiseLike<T>): Promise<T>
83
+ close (force?: boolean): Promise<void>
99
84
  }
100
85
 
101
- export = albatross
86
+ export default function albatross (uri: string): Albatross
package/index.js CHANGED
@@ -1,16 +1,11 @@
1
- const mongodb = require('mongodb')
2
- const Albatross = require('./lib/albatross')
1
+ import Albatross from './lib/albatross.js'
3
2
 
4
- module.exports = (uri) => new Albatross(uri)
3
+ import mongodb from 'mongodb'
5
4
 
6
- module.exports.Binary = mongodb.Binary
7
- module.exports.Code = mongodb.Code
8
- module.exports.DBRef = mongodb.DBRef
9
- module.exports.Decimal128 = mongodb.Decimal128
10
- module.exports.Double = mongodb.Double
11
- module.exports.Int32 = mongodb.Int32
12
- module.exports.Long = mongodb.Long
13
- module.exports.MaxKey = mongodb.MaxKey
14
- module.exports.MinKey = mongodb.MinKey
15
- module.exports.ObjectId = mongodb.ObjectId
16
- module.exports.Timestamp = mongodb.Timestamp
5
+ const { Binary, Code, Decimal128, Double, Int32, Long, MaxKey, MinKey, ObjectId, Timestamp } = mongodb
6
+
7
+ export { Binary, Code, Decimal128, Double, Int32, Long, MaxKey, MinKey, ObjectId, Timestamp }
8
+
9
+ export default function albatross (uri) {
10
+ return new Albatross(uri)
11
+ }
package/lib/albatross.js CHANGED
@@ -1,50 +1,28 @@
1
- const { GridStore, MongoClient, ObjectId } = require('mongodb')
1
+ import mongodb from 'mongodb'
2
2
 
3
- const Collection = require('./collection')
4
- const Grid = require('./grid')
3
+ import Collection from './collection.js'
4
+ import Grid from './grid.js'
5
+
6
+ const DEFAULT_ROOT_COLLECTION = 'fs'
5
7
 
6
8
  const kClient = Symbol('client')
7
9
  const kCollections = Symbol('collections')
8
- const kConnect = Symbol('connect')
9
10
  const kGrids = Symbol('grids')
10
- const kURI = Symbol('uri')
11
11
 
12
- class Albatross {
12
+ export default class Albatross {
13
13
  constructor (uri) {
14
- this[kClient] = null
14
+ this[kClient] = new mongodb.MongoClient(uri, { ignoreUndefined: true })
15
15
  this[kCollections] = new Map()
16
16
  this[kGrids] = new Map()
17
- this[kURI] = uri
18
- }
19
-
20
- async [kConnect] () {
21
- if (this[kClient] == null) {
22
- this[kClient] = MongoClient.connect(this[kURI], { useNewUrlParser: true, useUnifiedTopology: true, ignoreUndefined: true })
23
-
24
- try {
25
- return await this[kClient]
26
- } catch (err) {
27
- this[kClient] = null
28
- throw err
29
- }
30
- }
31
-
32
- const client = await this[kClient]
33
-
34
- if (!client.isConnected()) {
35
- this[kClient] = null
36
- return this[kConnect]()
37
- }
38
-
39
- return client
40
17
  }
41
18
 
42
19
  async db () {
43
- return (await this[kConnect]()).db()
20
+ await this[kClient].connect()
21
+ return this[kClient].db()
44
22
  }
45
23
 
46
24
  id (hexString) {
47
- return (hexString instanceof ObjectId) ? hexString : new ObjectId(hexString)
25
+ return (hexString instanceof mongodb.ObjectId) ? hexString : new mongodb.ObjectId(hexString)
48
26
  }
49
27
 
50
28
  collection (name) {
@@ -55,7 +33,7 @@ class Albatross {
55
33
  return this[kCollections].get(name)
56
34
  }
57
35
 
58
- grid (bucketName = GridStore.DEFAULT_ROOT_COLLECTION) {
36
+ grid (bucketName = DEFAULT_ROOT_COLLECTION) {
59
37
  if (!this[kGrids].has(bucketName)) {
60
38
  this[kGrids].set(bucketName, new Grid(this, bucketName))
61
39
  }
@@ -64,12 +42,11 @@ class Albatross {
64
42
  }
65
43
 
66
44
  async ping (timeout) {
67
- let client
68
45
  let timeoutHandle
69
46
 
70
47
  const ping = async () => {
71
- client = await this[kConnect]()
72
- return client.db().command({ ping: 1 })
48
+ await this[kClient].connect()
49
+ await this[kClient].db().command({ ping: 1 })
73
50
  }
74
51
 
75
52
  try {
@@ -85,13 +62,6 @@ class Albatross {
85
62
  } else {
86
63
  await ping()
87
64
  }
88
- } catch (err) {
89
- if (client) {
90
- client.close(true).catch(() => {})
91
- }
92
-
93
- this[kClient] = null
94
- throw err
95
65
  } finally {
96
66
  if (timeoutHandle) {
97
67
  clearTimeout(timeoutHandle)
@@ -99,13 +69,23 @@ class Albatross {
99
69
  }
100
70
  }
101
71
 
102
- async close (force) {
103
- if (this[kClient] == null) return
72
+ async transaction (fn) {
73
+ const session = this[kClient].startSession()
74
+
75
+ let result
104
76
 
105
- const client = await this[kClient]
106
- await client.close(force)
107
- this[kClient] = null
77
+ try {
78
+ await session.withTransaction(async (...args) => {
79
+ result = await fn(...args)
80
+ })
81
+ } finally {
82
+ session.endSession()
83
+ }
84
+
85
+ return result
108
86
  }
109
- }
110
87
 
111
- module.exports = Albatross
88
+ async close (force) {
89
+ await this[kClient].close(force)
90
+ }
91
+ }
package/lib/collection.js CHANGED
@@ -1,15 +1,13 @@
1
- const debug = require('debug')
2
- const { BSON } = require('bson')
1
+ import BSON from 'bson'
2
+ import debug from 'debug'
3
3
 
4
4
  const kDebug = Symbol('debug')
5
5
 
6
- const bsonParser = new BSON()
7
-
8
6
  function prepareDocument (document) {
9
- return bsonParser.deserialize(bsonParser.serialize(document), { promoteValues: true })
7
+ return BSON.deserialize(BSON.serialize(document), { promoteValues: true })
10
8
  }
11
9
 
12
- class Collection {
10
+ export default class Collection {
13
11
  constructor (parent, name) {
14
12
  this.name = name
15
13
  this.parent = parent
@@ -53,7 +51,7 @@ class Collection {
53
51
 
54
52
  try {
55
53
  this[kDebug]('count(%o)', query)
56
- const res = await db.collection(this.name).countDocuments(query, { ignoreUndefined: true, ...opts })
54
+ const res = await db.collection(this.name).countDocuments(query, opts)
57
55
  this[kDebug]('reply OK')
58
56
  return res
59
57
  } catch (err) {
@@ -100,15 +98,17 @@ class Collection {
100
98
 
101
99
  try {
102
100
  if (Array.isArray(docs)) {
103
- this[kDebug]('insertMany(%o)', docs)
104
- const res = await db.collection(this.name).insertMany(docs.map(prepareDocument), opts)
101
+ const documents = docs.map(prepareDocument)
102
+ this[kDebug]('insertMany(%o)', documents)
103
+ await db.collection(this.name).insertMany(documents, opts)
105
104
  this[kDebug]('reply OK')
106
- return res.ops
105
+ return documents
107
106
  } else {
108
- this[kDebug]('insertOne(%o)', docs)
109
- const res = await db.collection(this.name).insertOne(prepareDocument(docs), opts)
107
+ const document = prepareDocument(docs)
108
+ this[kDebug]('insertOne(%o)', document)
109
+ await db.collection(this.name).insertOne(document, opts)
110
110
  this[kDebug]('reply OK')
111
- return res.ops[0]
111
+ return document
112
112
  }
113
113
  } catch (err) {
114
114
  this[kDebug]('reply ERR')
@@ -121,7 +121,7 @@ class Collection {
121
121
 
122
122
  try {
123
123
  this[kDebug]('findOneAndUpdate(%o, %o)', filter, update)
124
- const res = await db.collection(this.name).findOneAndUpdate(filter, update, { ignoreUndefined: true, ...opts })
124
+ const res = await db.collection(this.name).findOneAndUpdate(filter, update, opts)
125
125
  this[kDebug]('reply OK')
126
126
  return res.value
127
127
  } catch (err) {
@@ -136,8 +136,8 @@ class Collection {
136
136
  try {
137
137
  this[kDebug]('updateOne(%o, %o)', filter, update)
138
138
  const res = await db.collection(this.name).updateOne(filter, update, opts)
139
- this[kDebug](`reply OK ${res.result.n} ${res.result.nModified}`)
140
- return { matched: res.result.n, modified: res.result.nModified }
139
+ this[kDebug](`reply OK ${res.matchedCount} ${res.modifiedCount}`)
140
+ return { matched: res.matchedCount, modified: res.modifiedCount }
141
141
  } catch (err) {
142
142
  this[kDebug]('reply ERR')
143
143
  throw err
@@ -150,8 +150,8 @@ class Collection {
150
150
  try {
151
151
  this[kDebug]('updateMany(%o, %o)', filter, update)
152
152
  const res = await db.collection(this.name).updateMany(filter, update, opts)
153
- this[kDebug](`reply OK ${res.result.n} ${res.result.nModified}`)
154
- return { matched: res.result.n, modified: res.result.nModified }
153
+ this[kDebug](`reply OK ${res.matchedCount} ${res.modifiedCount}`)
154
+ return { matched: res.matchedCount, modified: res.modifiedCount }
155
155
  } catch (err) {
156
156
  this[kDebug]('reply ERR')
157
157
  throw err
@@ -164,8 +164,8 @@ class Collection {
164
164
  try {
165
165
  this[kDebug]('deleteOne(%o)', filter)
166
166
  const res = await db.collection(this.name).deleteOne(filter, opts)
167
- this[kDebug](`reply OK ${res.result.n}`)
168
- return res.result.n
167
+ this[kDebug](`reply OK ${res.deletedCount}`)
168
+ return res.deletedCount
169
169
  } catch (err) {
170
170
  this[kDebug]('reply ERR')
171
171
  throw err
@@ -178,8 +178,8 @@ class Collection {
178
178
  try {
179
179
  this[kDebug]('deleteMany(%o)', filter)
180
180
  const res = await db.collection(this.name).deleteMany(filter, opts)
181
- this[kDebug](`reply OK ${res.result.n}`)
182
- return res.result.n
181
+ this[kDebug](`reply OK ${res.deletedCount}`)
182
+ return res.deletedCount
183
183
  } catch (err) {
184
184
  this[kDebug]('reply ERR')
185
185
  throw err
@@ -191,7 +191,7 @@ class Collection {
191
191
 
192
192
  try {
193
193
  this[kDebug]('aggregate(%o)', pipeline)
194
- const res = await db.collection(this.name).aggregate(pipeline, { ignoreUndefined: true, ...opts }).toArray()
194
+ const res = await db.collection(this.name).aggregate(pipeline, opts).toArray()
195
195
  this[kDebug]('reply OK')
196
196
  return res
197
197
  } catch (err) {
@@ -200,5 +200,3 @@ class Collection {
200
200
  }
201
201
  }
202
202
  }
203
-
204
- module.exports = Collection
package/lib/grid.js CHANGED
@@ -1,6 +1,6 @@
1
- const debug = require('debug')
2
- const { GridFSBucket } = require('mongodb')
3
- const stream = require('stream')
1
+ import debug from 'debug'
2
+ import mongodb from 'mongodb'
3
+ import { PassThrough } from 'node:stream'
4
4
 
5
5
  const reFileNotFound = /^FileNotFound: /
6
6
 
@@ -9,7 +9,6 @@ const kDebug = Symbol('debug')
9
9
  function fileInfo (file) {
10
10
  return {
11
11
  id: file._id,
12
- md5: file.md5,
13
12
  length: file.length,
14
13
  chunkSize: file.chunkSize,
15
14
  uploadDate: file.uploadDate,
@@ -19,7 +18,7 @@ function fileInfo (file) {
19
18
  }
20
19
  }
21
20
 
22
- class Grid {
21
+ export default class Grid {
23
22
  constructor (parent, name) {
24
23
  this.name = name
25
24
  this.parent = parent
@@ -34,8 +33,8 @@ class Grid {
34
33
  const db = await this.parent.db()
35
34
 
36
35
  return new Promise((resolve, reject) => {
37
- const bucket = new GridFSBucket(db, { bucketName: this.name })
38
- const upload = bucket.openUploadStream(opts.filename, opts)
36
+ const bucket = new mongodb.GridFSBucket(db, { bucketName: this.name })
37
+ const upload = bucket.openUploadStream(opts.filename || '', opts)
39
38
 
40
39
  upload.on('error', reject)
41
40
  upload.on('finish', (file) => resolve(fileInfo(file)))
@@ -48,9 +47,9 @@ class Grid {
48
47
  const db = await this.parent.db()
49
48
 
50
49
  return new Promise((resolve, reject) => {
51
- const bucket = new GridFSBucket(db, { bucketName: this.name })
50
+ const bucket = new mongodb.GridFSBucket(db, { bucketName: this.name })
52
51
  const download = bucket.openDownloadStream(this.id(id))
53
- const through = new stream.PassThrough()
52
+ const through = new PassThrough()
54
53
 
55
54
  // the download stream won't query the db until piped
56
55
  download.pipe(through)
@@ -73,10 +72,8 @@ class Grid {
73
72
  const db = await this.parent.db()
74
73
 
75
74
  return new Promise((resolve, reject) => {
76
- const bucket = new GridFSBucket(db, { bucketName: this.name })
75
+ const bucket = new mongodb.GridFSBucket(db, { bucketName: this.name })
77
76
  bucket.delete(this.id(id), (err) => err ? reject(err) : resolve())
78
77
  })
79
78
  }
80
79
  }
81
-
82
- module.exports = Grid
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "albatross",
3
- "version": "3.4.2",
3
+ "version": "4.0.0-rc.2",
4
4
  "license": "MIT",
5
- "author": "Linus Unnebäck <linus@folkdatorn.se>",
6
5
  "repository": "LinusU/node-albatross",
6
+ "type": "module",
7
+ "exports": "./index.js",
7
8
  "files": [
8
9
  "index.d.ts",
9
10
  "index.js",
@@ -11,25 +12,22 @@
11
12
  ],
12
13
  "scripts": {
13
14
  "test": "standard && mocha && npm run tsc",
14
- "tsc": "tsc --noEmit --allowJs --checkJs index.d.ts test/*.js"
15
+ "tsc": "tsc --allowSyntheticDefaultImports --noEmit --allowJs --checkJs index.d.ts test/*.js"
15
16
  },
16
17
  "dependencies": {
17
- "@types/bson": "1.0.11",
18
- "@types/mongodb": "3.6.12",
19
- "bson": "^1.1.4",
20
- "debug": "^4.1.1",
21
- "mongodb": "^3.6.0"
18
+ "bson": "^4.7.0",
19
+ "debug": "^4.3.4",
20
+ "mongodb": "^4.9.0"
22
21
  },
23
22
  "devDependencies": {
24
- "@types/mocha": "^5.2.7",
25
- "@types/node": "^8.10.54",
26
- "assert-rejects": "^1.0.0",
27
- "get-stream": "^5.1.0",
28
- "mocha": "^6.2.1",
29
- "standard": "^14.3.1",
30
- "typescript": "^3.7.3"
23
+ "@types/mocha": "^9.0.0",
24
+ "@types/node": "^16.4.13",
25
+ "get-stream": "^6.0.1",
26
+ "mocha": "^9.0.3",
27
+ "standard": "^17.0.0",
28
+ "typescript": "^4.8.2"
31
29
  },
32
30
  "engines": {
33
- "node": ">=8.3"
31
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
34
32
  }
35
33
  }
package/readme.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # ![Albatross](/header.png?raw=true "Albatross")
2
2
 
3
- Albatross is a small library that makes accessing MongoDB from Node.js a
4
- breeze. It's goal is to be a thin wrapper that enables you to forget about
5
- connection state and get right to accessing your data.
3
+ Albatross is a small library that makes accessing MongoDB from Node.js a breeze. It's goal is to be a thin wrapper that enables you to forget about connection state and get right to accessing your data.
6
4
 
7
5
  ## Installation
8
6
 
@@ -13,7 +11,8 @@ npm install --save albatross
13
11
  ## Usage
14
12
 
15
13
  ```js
16
- const albatross = require('albatross')
14
+ import albatross from 'albatross'
15
+ import fs from 'node:fs'
17
16
 
18
17
  const db = albatross('mongodb://localhost/test')
19
18
  const user = db.collection('user')
@@ -25,7 +24,6 @@ const doc = await user.findOne({ born: 1992 })
25
24
  console.log('Hello ' + doc.name)
26
25
  //=> Hello Linus
27
26
 
28
- const fs = require('fs')
29
27
  const grid = db.grid()
30
28
 
31
29
  const input = fs.createReadStream('readme.md')
@@ -40,15 +38,13 @@ result.contentType // 'text/plain'
40
38
  result.stream.pipe(process.stdout)
41
39
  ```
42
40
 
43
- You can start querying the database right away, as soon as a connection is
44
- established it will start sending your commands to the server.
41
+ You can start querying the database right away, as soon as a connection is established it will start sending your commands to the server.
45
42
 
46
43
  ## API
47
44
 
48
45
  ### Module
49
46
 
50
- The module exposes a single function to create a new `Albatross` instance. It
51
- also exposes the BSON Binary API on this function.
47
+ The module default exports a single function to create a new `Albatross` instance. It also exports the BSON Binary API as named exports.
52
48
 
53
49
  #### `albatross(uri)`
54
50
 
@@ -58,12 +54,11 @@ Creates a new instance of `Albatross` and connect to the specified uri.
58
54
 
59
55
  #### BSON Binary API
60
56
 
61
- The following functions are exposed on the module:
57
+ The following functions are exported from the module:
62
58
 
63
59
  ```text
64
60
  Binary
65
61
  Code
66
- DBRef
67
62
  Decimal128
68
63
  Double
69
64
  Int32
@@ -82,8 +77,7 @@ Returns a new instance of Collection bound to the collection named `name`.
82
77
 
83
78
  #### `.grid([name])`
84
79
 
85
- Returns a new instance of Grid, optionally using the supplied `name` as the
86
- name of the root collection.
80
+ Returns a new instance of Grid, optionally using the supplied `name` as the name of the root collection.
87
81
 
88
82
  #### `.id(strOrObjectId)`
89
83
 
@@ -95,6 +89,26 @@ Send the `ping` command to the server, to check that the connection is still int
95
89
 
96
90
  Optionally accepts a timeout in milliseconds.
97
91
 
92
+ #### `.transaction(fn): Promise`
93
+
94
+ Runs a provided function within a transaction, retrying either the commit operation or entire transaction as needed (and when the error permits) to better ensure that the transaction can complete successfully.
95
+
96
+ Example:
97
+
98
+ ```js
99
+ const user = db.collection('user')
100
+
101
+ const result = await db.transaction(async (session) => {
102
+ await user.insert({ name: 'Linus', born: 1992 }, { session })
103
+ await user.insert({ name: 'Steve', born: 1955 }, { session })
104
+
105
+ return await user.findOne({ born: 1992 }, { session })
106
+ })
107
+
108
+ console.log('Hello ' + result.name)
109
+ //=> Hello Linus
110
+ ```
111
+
98
112
  #### `.close(): Promise<void>`
99
113
 
100
114
  Closes the connection to the server.
@@ -131,9 +145,7 @@ Check if at least one document is matching the query.
131
145
 
132
146
  Inserts a single document or a an array of documents.
133
147
 
134
- The Promise will resolve with the documents that was inserted. When called
135
- with an object instead of an array as the first argument, the Promise resolves
136
- with an object instead of an array as well.
148
+ The Promise will resolve with the documents that was inserted. When called with an object instead of an array as the first argument, the Promise resolves with an object instead of an array as well.
137
149
 
138
150
  **Note:** Contrary to the standard MongoDB Node.js driver, this function will *not modify* any objects that are passed in. Instead, the returned documents from this function are what was saved in the database.
139
151
 
@@ -141,7 +153,7 @@ with an object instead of an array as well.
141
153
 
142
154
  Finds a document and updates it in one atomic operation.
143
155
 
144
- By default, the document _before_ the update is returned. To return the document _after_ the update, pass `returnOriginal: false` in the options.
156
+ By default, the document _before_ the update is returned. To return the document _after_ the update, pass `returnDocument: 'after'` in the options.
145
157
 
146
158
  #### `updateOne(filter, update[, opts]): Promise<UpdateResult>`
147
159
 
@@ -177,8 +189,7 @@ Makes sure that the given argument is an ObjectId.
177
189
 
178
190
  #### `upload(stream[, opts]): Promise<FileInfo>`
179
191
 
180
- Store the `stream` as a file in the grid store, `opts` is a object with the
181
- following properties. All options are optionally.
192
+ Store the `stream` as a file in the grid store, `opts` is a object with the following properties. All options are optionally.
182
193
 
183
194
  - `filename`: The value of the `filename` key in the files doc
184
195
  - `chunkSizeBytes`: Overwrite this bucket's `chunkSizeBytes` for this file
@@ -189,7 +200,6 @@ following properties. All options are optionally.
189
200
  The `FileInfo` object has the following properties:
190
201
 
191
202
  - `id`: The id of the file
192
- - `md5`: The md5 hash of the file
193
203
  - `length`: The length of the file
194
204
  - `chunkSize`: The size of each chunk in bytes
195
205
  - `filename`: The value of the `filename` key in the files doc
@@ -198,12 +208,9 @@ The `FileInfo` object has the following properties:
198
208
 
199
209
  #### `download(id): Promise<FileInfo>`
200
210
 
201
- Get the file with the specified `id` from the grid store. The Promise will
202
- resolve with an object with the following properties. If no file with the
203
- indicated `id` was found, the Promise will resolve to `null`.
211
+ Get the file with the specified `id` from the grid store. The Promise will resolve with an object with the following properties. If no file with the indicated `id` was found, the Promise will resolve to `null`.
204
212
 
205
213
  - `id`: The id of the file
206
- - `md5`: The md5 hash of the file
207
214
  - `length`: The length of the file
208
215
  - `chunkSize`: The size of each chunk in bytes
209
216
  - `filename`: The value of the `filename` key in the files doc
@@ -217,13 +224,11 @@ Delete the file with the specified `id` from the grid store.
217
224
 
218
225
  ## In depth documentation
219
226
 
220
- For more in depth documentation please see the [mongodb module](http://mongodb.github.io/node-mongodb-native/)
221
- which Albatross wraps, especially the [Collection object](http://mongodb.github.io/node-mongodb-native/api-generated/collection.html).
227
+ For more in depth documentation please see the [mongodb module](http://mongodb.github.io/node-mongodb-native/) which Albatross wraps, especially the [Collection object](http://mongodb.github.io/node-mongodb-native/api-generated/collection.html).
222
228
 
223
229
  ## Contributing
224
230
 
225
- Pull requests are always welcome, please make sure to add tests and run
226
- `mocha` before submitting.
231
+ Pull requests are always welcome, please make sure to add tests and run `mocha` before submitting.
227
232
 
228
233
  The tests requiers a MongoDB server running at `localhost`.
229
234