mongodb 3.2.5 → 3.3.0-beta2

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 (133) hide show
  1. package/HISTORY.md +0 -10
  2. package/index.js +4 -4
  3. package/lib/admin.js +56 -56
  4. package/lib/aggregation_cursor.js +7 -3
  5. package/lib/bulk/common.js +18 -13
  6. package/lib/change_stream.js +196 -89
  7. package/lib/collection.js +217 -169
  8. package/lib/command_cursor.js +17 -7
  9. package/lib/core/auth/auth_provider.js +158 -0
  10. package/lib/core/auth/defaultAuthProviders.js +29 -0
  11. package/lib/core/auth/gssapi.js +241 -0
  12. package/lib/core/auth/mongo_credentials.js +81 -0
  13. package/lib/core/auth/mongocr.js +51 -0
  14. package/lib/core/auth/plain.js +35 -0
  15. package/lib/core/auth/scram.js +293 -0
  16. package/lib/core/auth/sspi.js +131 -0
  17. package/lib/core/auth/x509.js +26 -0
  18. package/lib/core/connection/apm.js +236 -0
  19. package/lib/core/connection/command_result.js +36 -0
  20. package/lib/core/connection/commands.js +507 -0
  21. package/lib/core/connection/connect.js +370 -0
  22. package/lib/core/connection/connection.js +624 -0
  23. package/lib/core/connection/logger.js +246 -0
  24. package/lib/core/connection/msg.js +219 -0
  25. package/lib/core/connection/pool.js +1285 -0
  26. package/lib/core/connection/utils.js +57 -0
  27. package/lib/core/cursor.js +752 -0
  28. package/lib/core/error.js +186 -0
  29. package/lib/core/index.js +50 -0
  30. package/lib/core/sdam/monitoring.js +228 -0
  31. package/lib/core/sdam/server.js +467 -0
  32. package/lib/core/sdam/server_description.js +163 -0
  33. package/lib/core/sdam/server_selectors.js +244 -0
  34. package/lib/core/sdam/srv_polling.js +135 -0
  35. package/lib/core/sdam/topology.js +1151 -0
  36. package/lib/core/sdam/topology_description.js +408 -0
  37. package/lib/core/sessions.js +711 -0
  38. package/lib/core/tools/smoke_plugin.js +61 -0
  39. package/lib/core/topologies/mongos.js +1337 -0
  40. package/lib/core/topologies/read_preference.js +202 -0
  41. package/lib/core/topologies/replset.js +1507 -0
  42. package/lib/core/topologies/replset_state.js +1121 -0
  43. package/lib/core/topologies/server.js +984 -0
  44. package/lib/core/topologies/shared.js +453 -0
  45. package/lib/core/transactions.js +167 -0
  46. package/lib/core/uri_parser.js +631 -0
  47. package/lib/core/utils.js +165 -0
  48. package/lib/core/wireprotocol/command.js +170 -0
  49. package/lib/core/wireprotocol/compression.js +73 -0
  50. package/lib/core/wireprotocol/constants.js +13 -0
  51. package/lib/core/wireprotocol/get_more.js +86 -0
  52. package/lib/core/wireprotocol/index.js +18 -0
  53. package/lib/core/wireprotocol/kill_cursors.js +70 -0
  54. package/lib/core/wireprotocol/query.js +224 -0
  55. package/lib/core/wireprotocol/shared.js +115 -0
  56. package/lib/core/wireprotocol/write_command.js +50 -0
  57. package/lib/cursor.js +40 -46
  58. package/lib/db.js +141 -95
  59. package/lib/dynamic_loaders.js +32 -0
  60. package/lib/error.js +12 -10
  61. package/lib/gridfs/chunk.js +2 -2
  62. package/lib/gridfs/grid_store.js +31 -25
  63. package/lib/gridfs-stream/index.js +4 -4
  64. package/lib/gridfs-stream/upload.js +1 -1
  65. package/lib/mongo_client.js +37 -15
  66. package/lib/operations/add_user.js +96 -0
  67. package/lib/operations/aggregate.js +24 -13
  68. package/lib/operations/aggregate_operation.js +127 -0
  69. package/lib/operations/bulk_write.js +104 -0
  70. package/lib/operations/close.js +47 -0
  71. package/lib/operations/collection_ops.js +28 -287
  72. package/lib/operations/collections.js +55 -0
  73. package/lib/operations/command.js +120 -0
  74. package/lib/operations/command_v2.js +43 -0
  75. package/lib/operations/common_functions.js +372 -0
  76. package/lib/operations/{mongo_client_ops.js → connect.js} +185 -157
  77. package/lib/operations/count.js +72 -0
  78. package/lib/operations/count_documents.js +46 -0
  79. package/lib/operations/create_collection.js +118 -0
  80. package/lib/operations/create_index.js +92 -0
  81. package/lib/operations/create_indexes.js +61 -0
  82. package/lib/operations/cursor_ops.js +3 -4
  83. package/lib/operations/db_ops.js +15 -12
  84. package/lib/operations/delete_many.js +25 -0
  85. package/lib/operations/delete_one.js +25 -0
  86. package/lib/operations/distinct.js +85 -0
  87. package/lib/operations/drop.js +53 -0
  88. package/lib/operations/drop_index.js +42 -0
  89. package/lib/operations/drop_indexes.js +23 -0
  90. package/lib/operations/estimated_document_count.js +33 -0
  91. package/lib/operations/execute_db_admin_command.js +34 -0
  92. package/lib/operations/execute_operation.js +165 -0
  93. package/lib/operations/explain.js +23 -0
  94. package/lib/operations/find_and_modify.js +98 -0
  95. package/lib/operations/find_one.js +33 -0
  96. package/lib/operations/find_one_and_delete.js +16 -0
  97. package/lib/operations/find_one_and_replace.js +18 -0
  98. package/lib/operations/find_one_and_update.js +19 -0
  99. package/lib/operations/geo_haystack_search.js +79 -0
  100. package/lib/operations/has_next.js +40 -0
  101. package/lib/operations/index_exists.js +39 -0
  102. package/lib/operations/index_information.js +23 -0
  103. package/lib/operations/indexes.js +22 -0
  104. package/lib/operations/insert_many.js +63 -0
  105. package/lib/operations/insert_one.js +75 -0
  106. package/lib/operations/is_capped.js +19 -0
  107. package/lib/operations/list_indexes.js +66 -0
  108. package/lib/operations/map_reduce.js +189 -0
  109. package/lib/operations/next.js +32 -0
  110. package/lib/operations/operation.js +63 -0
  111. package/lib/operations/options_operation.js +32 -0
  112. package/lib/operations/profiling_level.js +31 -0
  113. package/lib/operations/re_index.js +28 -0
  114. package/lib/operations/remove_user.js +52 -0
  115. package/lib/operations/rename.js +61 -0
  116. package/lib/operations/replace_one.js +47 -0
  117. package/lib/operations/set_profiling_level.js +48 -0
  118. package/lib/operations/stats.js +45 -0
  119. package/lib/operations/to_array.js +68 -0
  120. package/lib/operations/update_many.js +29 -0
  121. package/lib/operations/update_one.js +44 -0
  122. package/lib/operations/validate_collection.js +40 -0
  123. package/lib/read_concern.js +55 -0
  124. package/lib/topologies/mongos.js +3 -3
  125. package/lib/topologies/native_topology.js +22 -2
  126. package/lib/topologies/replset.js +3 -3
  127. package/lib/topologies/server.js +4 -4
  128. package/lib/topologies/topology_base.js +6 -6
  129. package/lib/url_parser.js +4 -3
  130. package/lib/utils.js +46 -59
  131. package/lib/write_concern.js +66 -0
  132. package/package.json +15 -6
  133. package/lib/.DS_Store +0 -0
@@ -0,0 +1,370 @@
1
+ 'use strict';
2
+ const net = require('net');
3
+ const tls = require('tls');
4
+ const Connection = require('./connection');
5
+ const Query = require('./commands').Query;
6
+ const createClientInfo = require('../topologies/shared').createClientInfo;
7
+ const MongoError = require('../error').MongoError;
8
+ const MongoNetworkError = require('../error').MongoNetworkError;
9
+ const defaultAuthProviders = require('../auth/defaultAuthProviders').defaultAuthProviders;
10
+ const WIRE_CONSTANTS = require('../wireprotocol/constants');
11
+ const MAX_SUPPORTED_WIRE_VERSION = WIRE_CONSTANTS.MAX_SUPPORTED_WIRE_VERSION;
12
+ const MAX_SUPPORTED_SERVER_VERSION = WIRE_CONSTANTS.MAX_SUPPORTED_SERVER_VERSION;
13
+ const MIN_SUPPORTED_WIRE_VERSION = WIRE_CONSTANTS.MIN_SUPPORTED_WIRE_VERSION;
14
+ const MIN_SUPPORTED_SERVER_VERSION = WIRE_CONSTANTS.MIN_SUPPORTED_SERVER_VERSION;
15
+ let AUTH_PROVIDERS;
16
+
17
+ function connect(options, callback) {
18
+ if (AUTH_PROVIDERS == null) {
19
+ AUTH_PROVIDERS = defaultAuthProviders(options.bson);
20
+ }
21
+
22
+ if (options.family !== void 0) {
23
+ makeConnection(options.family, options, (err, socket) => {
24
+ if (err) {
25
+ callback(err, socket); // in the error case, `socket` is the originating error event name
26
+ return;
27
+ }
28
+
29
+ performInitialHandshake(new Connection(socket, options), options, callback);
30
+ });
31
+
32
+ return;
33
+ }
34
+
35
+ return makeConnection(6, options, (err, ipv6Socket) => {
36
+ if (err) {
37
+ makeConnection(4, options, (err, ipv4Socket) => {
38
+ if (err) {
39
+ callback(err, ipv4Socket); // in the error case, `ipv4Socket` is the originating error event name
40
+ return;
41
+ }
42
+
43
+ performInitialHandshake(new Connection(ipv4Socket, options), options, callback);
44
+ });
45
+
46
+ return;
47
+ }
48
+
49
+ performInitialHandshake(new Connection(ipv6Socket, options), options, callback);
50
+ });
51
+ }
52
+
53
+ function getSaslSupportedMechs(options) {
54
+ if (!(options && options.credentials)) {
55
+ return {};
56
+ }
57
+
58
+ const credentials = options.credentials;
59
+
60
+ // TODO: revisit whether or not items like `options.user` and `options.dbName` should be checked here
61
+ const authMechanism = credentials.mechanism;
62
+ const authSource = credentials.source || options.dbName || 'admin';
63
+ const user = credentials.username || options.user;
64
+
65
+ if (typeof authMechanism === 'string' && authMechanism.toUpperCase() !== 'DEFAULT') {
66
+ return {};
67
+ }
68
+
69
+ if (!user) {
70
+ return {};
71
+ }
72
+
73
+ return { saslSupportedMechs: `${authSource}.${user}` };
74
+ }
75
+
76
+ function checkSupportedServer(ismaster, options) {
77
+ const serverVersionHighEnough =
78
+ ismaster &&
79
+ typeof ismaster.maxWireVersion === 'number' &&
80
+ ismaster.maxWireVersion >= MIN_SUPPORTED_WIRE_VERSION;
81
+ const serverVersionLowEnough =
82
+ ismaster &&
83
+ typeof ismaster.minWireVersion === 'number' &&
84
+ ismaster.minWireVersion <= MAX_SUPPORTED_WIRE_VERSION;
85
+
86
+ if (serverVersionHighEnough) {
87
+ if (serverVersionLowEnough) {
88
+ return null;
89
+ }
90
+
91
+ const message = `Server at ${options.host}:${options.port} reports minimum wire version ${
92
+ ismaster.minWireVersion
93
+ }, but this version of the Node.js Driver requires at most ${MAX_SUPPORTED_WIRE_VERSION} (MongoDB ${MAX_SUPPORTED_SERVER_VERSION})`;
94
+ return new MongoError(message);
95
+ }
96
+
97
+ const message = `Server at ${options.host}:${
98
+ options.port
99
+ } reports maximum wire version ${ismaster.maxWireVersion ||
100
+ 0}, but this version of the Node.js Driver requires at least ${MIN_SUPPORTED_WIRE_VERSION} (MongoDB ${MIN_SUPPORTED_SERVER_VERSION})`;
101
+ return new MongoError(message);
102
+ }
103
+
104
+ function performInitialHandshake(conn, options, _callback) {
105
+ const callback = function(err, ret) {
106
+ if (err && conn) {
107
+ conn.destroy();
108
+ }
109
+ _callback(err, ret);
110
+ };
111
+
112
+ let compressors = [];
113
+ if (options.compression && options.compression.compressors) {
114
+ compressors = options.compression.compressors;
115
+ }
116
+
117
+ const handshakeDoc = Object.assign(
118
+ {
119
+ ismaster: true,
120
+ client: createClientInfo(options),
121
+ compression: compressors
122
+ },
123
+ getSaslSupportedMechs(options)
124
+ );
125
+
126
+ const start = new Date().getTime();
127
+ runCommand(conn, 'admin.$cmd', handshakeDoc, options, (err, ismaster) => {
128
+ if (err) {
129
+ callback(err, null);
130
+ return;
131
+ }
132
+
133
+ if (ismaster.ok === 0) {
134
+ callback(new MongoError(ismaster), null);
135
+ return;
136
+ }
137
+
138
+ const supportedServerErr = checkSupportedServer(ismaster, options);
139
+ if (supportedServerErr) {
140
+ callback(supportedServerErr, null);
141
+ return;
142
+ }
143
+
144
+ // resolve compression
145
+ if (ismaster.compression) {
146
+ const agreedCompressors = compressors.filter(
147
+ compressor => ismaster.compression.indexOf(compressor) !== -1
148
+ );
149
+
150
+ if (agreedCompressors.length) {
151
+ conn.agreedCompressor = agreedCompressors[0];
152
+ }
153
+
154
+ if (options.compression && options.compression.zlibCompressionLevel) {
155
+ conn.zlibCompressionLevel = options.compression.zlibCompressionLevel;
156
+ }
157
+ }
158
+
159
+ // NOTE: This is metadata attached to the connection while porting away from
160
+ // handshake being done in the `Server` class. Likely, it should be
161
+ // relocated, or at very least restructured.
162
+ conn.ismaster = ismaster;
163
+ conn.lastIsMasterMS = new Date().getTime() - start;
164
+
165
+ const credentials = options.credentials;
166
+ if (!ismaster.arbiterOnly && credentials) {
167
+ credentials.resolveAuthMechanism(ismaster);
168
+ authenticate(conn, credentials, callback);
169
+ return;
170
+ }
171
+
172
+ callback(null, conn);
173
+ });
174
+ }
175
+
176
+ const LEGAL_SSL_SOCKET_OPTIONS = [
177
+ 'pfx',
178
+ 'key',
179
+ 'passphrase',
180
+ 'cert',
181
+ 'ca',
182
+ 'ciphers',
183
+ 'NPNProtocols',
184
+ 'ALPNProtocols',
185
+ 'servername',
186
+ 'ecdhCurve',
187
+ 'secureProtocol',
188
+ 'secureContext',
189
+ 'session',
190
+ 'minDHSize',
191
+ 'crl',
192
+ 'rejectUnauthorized'
193
+ ];
194
+
195
+ function parseConnectOptions(family, options) {
196
+ const host = typeof options.host === 'string' ? options.host : 'localhost';
197
+ if (host.indexOf('/') !== -1) {
198
+ return { path: host };
199
+ }
200
+
201
+ const result = {
202
+ family,
203
+ host,
204
+ port: typeof options.port === 'number' ? options.port : 27017,
205
+ rejectUnauthorized: false
206
+ };
207
+
208
+ return result;
209
+ }
210
+
211
+ function parseSslOptions(family, options) {
212
+ const result = parseConnectOptions(family, options);
213
+
214
+ // Merge in valid SSL options
215
+ for (const name in options) {
216
+ if (options[name] != null && LEGAL_SSL_SOCKET_OPTIONS.indexOf(name) !== -1) {
217
+ result[name] = options[name];
218
+ }
219
+ }
220
+
221
+ // Override checkServerIdentity behavior
222
+ if (options.checkServerIdentity === false) {
223
+ // Skip the identiy check by retuning undefined as per node documents
224
+ // https://nodejs.org/api/tls.html#tls_tls_connect_options_callback
225
+ result.checkServerIdentity = function() {
226
+ return undefined;
227
+ };
228
+ } else if (typeof options.checkServerIdentity === 'function') {
229
+ result.checkServerIdentity = options.checkServerIdentity;
230
+ }
231
+
232
+ // Set default sni servername to be the same as host
233
+ if (result.servername == null) {
234
+ result.servername = result.host;
235
+ }
236
+
237
+ return result;
238
+ }
239
+
240
+ function makeConnection(family, options, _callback) {
241
+ const useSsl = typeof options.ssl === 'boolean' ? options.ssl : false;
242
+ const keepAlive = typeof options.keepAlive === 'boolean' ? options.keepAlive : true;
243
+ let keepAliveInitialDelay =
244
+ typeof options.keepAliveInitialDelay === 'number' ? options.keepAliveInitialDelay : 300000;
245
+ const noDelay = typeof options.noDelay === 'boolean' ? options.noDelay : true;
246
+ const connectionTimeout =
247
+ typeof options.connectionTimeout === 'number' ? options.connectionTimeout : 30000;
248
+ const socketTimeout = typeof options.socketTimeout === 'number' ? options.socketTimeout : 360000;
249
+ const rejectUnauthorized =
250
+ typeof options.rejectUnauthorized === 'boolean' ? options.rejectUnauthorized : true;
251
+
252
+ if (keepAliveInitialDelay > socketTimeout) {
253
+ keepAliveInitialDelay = Math.round(socketTimeout / 2);
254
+ }
255
+
256
+ let socket;
257
+ const callback = function(err, ret) {
258
+ if (err && socket) {
259
+ socket.destroy();
260
+ }
261
+ _callback(err, ret);
262
+ };
263
+
264
+ try {
265
+ if (useSsl) {
266
+ socket = tls.connect(parseSslOptions(family, options));
267
+ if (typeof socket.disableRenegotiation === 'function') {
268
+ socket.disableRenegotiation();
269
+ }
270
+ } else {
271
+ socket = net.createConnection(parseConnectOptions(family, options));
272
+ }
273
+ } catch (err) {
274
+ return callback(err);
275
+ }
276
+
277
+ socket.setKeepAlive(keepAlive, keepAliveInitialDelay);
278
+ socket.setTimeout(connectionTimeout);
279
+ socket.setNoDelay(noDelay);
280
+
281
+ const errorEvents = ['error', 'close', 'timeout', 'parseError'];
282
+ function errorHandler(eventName) {
283
+ return err => {
284
+ errorEvents.forEach(event => socket.removeAllListeners(event));
285
+ socket.removeListener('connect', connectHandler);
286
+ callback(connectionFailureError(eventName, err), eventName);
287
+ };
288
+ }
289
+
290
+ function connectHandler() {
291
+ errorEvents.forEach(event => socket.removeAllListeners(event));
292
+ if (socket.authorizationError && rejectUnauthorized) {
293
+ return callback(socket.authorizationError);
294
+ }
295
+
296
+ socket.setTimeout(socketTimeout);
297
+ callback(null, socket);
298
+ }
299
+
300
+ socket.once('error', errorHandler('error'));
301
+ socket.once('close', errorHandler('close'));
302
+ socket.once('timeout', errorHandler('timeout'));
303
+ socket.once('parseError', errorHandler('parseError'));
304
+ socket.once('connect', connectHandler);
305
+ }
306
+
307
+ const CONNECTION_ERROR_EVENTS = ['error', 'close', 'timeout', 'parseError'];
308
+ function runCommand(conn, ns, command, options, callback) {
309
+ if (typeof options === 'function') (callback = options), (options = {});
310
+ const socketTimeout = typeof options.socketTimeout === 'number' ? options.socketTimeout : 360000;
311
+ const bson = conn.options.bson;
312
+ const query = new Query(bson, ns, command, {
313
+ numberToSkip: 0,
314
+ numberToReturn: 1
315
+ });
316
+
317
+ function errorHandler(err) {
318
+ conn.resetSocketTimeout();
319
+ CONNECTION_ERROR_EVENTS.forEach(eventName => conn.removeListener(eventName, errorHandler));
320
+ conn.removeListener('message', messageHandler);
321
+ callback(err, null);
322
+ }
323
+
324
+ function messageHandler(msg) {
325
+ if (msg.responseTo !== query.requestId) {
326
+ return;
327
+ }
328
+
329
+ conn.resetSocketTimeout();
330
+ CONNECTION_ERROR_EVENTS.forEach(eventName => conn.removeListener(eventName, errorHandler));
331
+ conn.removeListener('message', messageHandler);
332
+
333
+ msg.parse({ promoteValues: true });
334
+ callback(null, msg.documents[0]);
335
+ }
336
+
337
+ conn.setSocketTimeout(socketTimeout);
338
+ CONNECTION_ERROR_EVENTS.forEach(eventName => conn.once(eventName, errorHandler));
339
+ conn.on('message', messageHandler);
340
+ conn.write(query.toBin());
341
+ }
342
+
343
+ function authenticate(conn, credentials, callback) {
344
+ const mechanism = credentials.mechanism;
345
+ if (!AUTH_PROVIDERS[mechanism]) {
346
+ callback(new MongoError(`authMechanism '${mechanism}' not supported`));
347
+ return;
348
+ }
349
+
350
+ const provider = AUTH_PROVIDERS[mechanism];
351
+ provider.auth(runCommand, [conn], credentials, err => {
352
+ if (err) return callback(err);
353
+ callback(null, conn);
354
+ });
355
+ }
356
+
357
+ function connectionFailureError(type, err) {
358
+ switch (type) {
359
+ case 'error':
360
+ return new MongoNetworkError(err);
361
+ case 'timeout':
362
+ return new MongoNetworkError(`connection timed out`);
363
+ case 'close':
364
+ return new MongoNetworkError(`connection closed`);
365
+ default:
366
+ return new MongoNetworkError(`unknown network error`);
367
+ }
368
+ }
369
+
370
+ module.exports = connect;