mongo_client.js
9.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MongoClient = exports.ServerApiVersion = void 0;
const bson_1 = require("./bson");
const change_stream_1 = require("./change_stream");
const connection_string_1 = require("./connection_string");
const db_1 = require("./db");
const error_1 = require("./error");
const mongo_types_1 = require("./mongo_types");
const connect_1 = require("./operations/connect");
const promise_provider_1 = require("./promise_provider");
const utils_1 = require("./utils");
/** @public */
exports.ServerApiVersion = Object.freeze({
v1: '1'
});
/** @internal */
const kOptions = Symbol('options');
/**
* The **MongoClient** class is a class that allows for making Connections to MongoDB.
* @public
*
* @remarks
* The programmatically provided options take precedent over the URI options.
*
* @example
* ```js
* // Connect using a MongoClient instance
* const MongoClient = require('mongodb').MongoClient;
* const test = require('assert');
* // Connection url
* const url = 'mongodb://localhost:27017';
* // Database Name
* const dbName = 'test';
* // Connect using MongoClient
* const mongoClient = new MongoClient(url);
* mongoClient.connect(function(err, client) {
* const db = client.db(dbName);
* client.close();
* });
* ```
*
* @example
* ```js
* // Connect using the MongoClient.connect static method
* const MongoClient = require('mongodb').MongoClient;
* const test = require('assert');
* // Connection url
* const url = 'mongodb://localhost:27017';
* // Database Name
* const dbName = 'test';
* // Connect using MongoClient
* MongoClient.connect(url, function(err, client) {
* const db = client.db(dbName);
* client.close();
* });
* ```
*/
class MongoClient extends mongo_types_1.TypedEventEmitter {
constructor(url, options) {
super();
this[kOptions] = (0, connection_string_1.parseOptions)(url, this, options);
// eslint-disable-next-line @typescript-eslint/no-this-alias
const client = this;
// The internal state
this.s = {
url,
sessions: new Set(),
bsonOptions: (0, bson_1.resolveBSONOptions)(this[kOptions]),
namespace: (0, utils_1.ns)('admin'),
get options() {
return client[kOptions];
},
get readConcern() {
return client[kOptions].readConcern;
},
get writeConcern() {
return client[kOptions].writeConcern;
},
get readPreference() {
return client[kOptions].readPreference;
},
get logger() {
return client[kOptions].logger;
}
};
}
get options() {
return Object.freeze({ ...this[kOptions] });
}
get serverApi() {
return this[kOptions].serverApi && Object.freeze({ ...this[kOptions].serverApi });
}
/**
* Intended for APM use only
* @internal
*/
get monitorCommands() {
return this[kOptions].monitorCommands;
}
set monitorCommands(value) {
this[kOptions].monitorCommands = value;
}
get autoEncrypter() {
return this[kOptions].autoEncrypter;
}
get readConcern() {
return this.s.readConcern;
}
get writeConcern() {
return this.s.writeConcern;
}
get readPreference() {
return this.s.readPreference;
}
get bsonOptions() {
return this.s.bsonOptions;
}
get logger() {
return this.s.logger;
}
connect(callback) {
if (callback && typeof callback !== 'function') {
throw new error_1.MongoInvalidArgumentError('Method `connect` only accepts a callback');
}
return (0, utils_1.maybePromise)(callback, cb => {
(0, connect_1.connect)(this, this[kOptions], err => {
if (err)
return cb(err);
cb(undefined, this);
});
});
}
close(forceOrCallback, callback) {
if (typeof forceOrCallback === 'function') {
callback = forceOrCallback;
}
const force = typeof forceOrCallback === 'boolean' ? forceOrCallback : false;
return (0, utils_1.maybePromise)(callback, callback => {
if (this.topology == null) {
return callback();
}
// clear out references to old topology
const topology = this.topology;
this.topology = undefined;
topology.close({ force }, error => {
if (error)
return callback(error);
const { encrypter } = this[kOptions];
if (encrypter) {
return encrypter.close(this, force, error => {
callback(error);
});
}
callback();
});
});
}
/**
* Create a new Db instance sharing the current socket connections.
*
* @param dbName - The name of the database we want to use. If not provided, use database name from connection string.
* @param options - Optional settings for Db construction
*/
db(dbName, options) {
options = options !== null && options !== void 0 ? options : {};
// Default to db from connection string if not provided
if (!dbName) {
dbName = this.options.dbName;
}
// Copy the options and add out internal override of the not shared flag
const finalOptions = Object.assign({}, this[kOptions], options);
// Return the db object
const db = new db_1.Db(this, dbName, finalOptions);
// Return the database
return db;
}
static connect(url, options, callback) {
if (typeof options === 'function')
(callback = options), (options = {});
options = options !== null && options !== void 0 ? options : {};
try {
// Create client
const mongoClient = new MongoClient(url, options);
// Execute the connect method
if (callback) {
return mongoClient.connect(callback);
}
else {
return mongoClient.connect();
}
}
catch (error) {
if (callback)
return callback(error);
else
return promise_provider_1.PromiseProvider.get().reject(error);
}
}
startSession(options) {
options = Object.assign({ explicit: true }, options);
if (!this.topology) {
throw new error_1.MongoNotConnectedError('MongoClient must be connected to start a session');
}
return this.topology.startSession(options, this.s.options);
}
withSession(optionsOrOperation, callback) {
const options = {
// Always define an owner
owner: Symbol(),
// If it's an object inherit the options
...(typeof optionsOrOperation === 'object' ? optionsOrOperation : {})
};
const withSessionCallback = typeof optionsOrOperation === 'function' ? optionsOrOperation : callback;
if (withSessionCallback == null) {
throw new error_1.MongoInvalidArgumentError('Missing required callback parameter');
}
const session = this.startSession(options);
const Promise = promise_provider_1.PromiseProvider.get();
return Promise.resolve()
.then(() => withSessionCallback(session))
.then(() => {
// Do not return the result of callback
})
.finally(() => session.endSession());
}
/**
* Create a new Change Stream, watching for new changes (insertions, updates,
* replacements, deletions, and invalidations) in this cluster. Will ignore all
* changes to system collections, as well as the local, admin, and config databases.
*
* @remarks
* watch() accepts two generic arguments for distinct usecases:
* - The first is to provide the schema that may be defined for all the data within the current cluster
* - The second is to override the shape of the change stream document entirely, if it is not provided the type will default to ChangeStreamDocument of the first argument
*
* @param pipeline - An array of {@link https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/|aggregation pipeline stages} through which to pass change stream documents. This allows for filtering (using $match) and manipulating the change stream documents.
* @param options - Optional settings for the command
* @typeParam TSchema - Type of the data being detected by the change stream
* @typeParam TChange - Type of the whole change stream document emitted
*/
watch(pipeline = [], options = {}) {
// Allow optionally not specifying a pipeline
if (!Array.isArray(pipeline)) {
options = pipeline;
pipeline = [];
}
return new change_stream_1.ChangeStream(this, pipeline, (0, utils_1.resolveOptions)(this, options));
}
/** Return the mongo client logger */
getLogger() {
return this.s.logger;
}
}
exports.MongoClient = MongoClient;
//# sourceMappingURL=mongo_client.js.map