mongodb 6.3.0 → 6.4.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 (221) hide show
  1. package/lib/bson.js +2 -1
  2. package/lib/bson.js.map +1 -1
  3. package/lib/bulk/common.js +14 -9
  4. package/lib/bulk/common.js.map +1 -1
  5. package/lib/change_stream.js +4 -2
  6. package/lib/change_stream.js.map +1 -1
  7. package/lib/client-side-encryption/state_machine.js +58 -52
  8. package/lib/client-side-encryption/state_machine.js.map +1 -1
  9. package/lib/cmap/auth/auth_provider.js +4 -0
  10. package/lib/cmap/auth/auth_provider.js.map +1 -1
  11. package/lib/cmap/auth/gssapi.js +1 -1
  12. package/lib/cmap/auth/gssapi.js.map +1 -1
  13. package/lib/cmap/auth/mongo_credentials.js.map +1 -1
  14. package/lib/cmap/auth/mongocr.js +2 -2
  15. package/lib/cmap/auth/mongocr.js.map +1 -1
  16. package/lib/cmap/auth/mongodb_aws.js +58 -55
  17. package/lib/cmap/auth/mongodb_aws.js.map +1 -1
  18. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js +2 -2
  19. package/lib/cmap/auth/mongodb_oidc/callback_workflow.js.map +1 -1
  20. package/lib/cmap/auth/mongodb_oidc/service_workflow.js +1 -1
  21. package/lib/cmap/auth/mongodb_oidc/service_workflow.js.map +1 -1
  22. package/lib/cmap/auth/plain.js +1 -1
  23. package/lib/cmap/auth/plain.js.map +1 -1
  24. package/lib/cmap/auth/scram.js +5 -7
  25. package/lib/cmap/auth/scram.js.map +1 -1
  26. package/lib/cmap/auth/x509.js +1 -1
  27. package/lib/cmap/auth/x509.js.map +1 -1
  28. package/lib/cmap/command_monitoring_events.js +6 -3
  29. package/lib/cmap/command_monitoring_events.js.map +1 -1
  30. package/lib/cmap/commands.js +2 -0
  31. package/lib/cmap/commands.js.map +1 -1
  32. package/lib/cmap/connect.js +88 -110
  33. package/lib/cmap/connect.js.map +1 -1
  34. package/lib/cmap/connection.js +280 -726
  35. package/lib/cmap/connection.js.map +1 -1
  36. package/lib/cmap/connection_pool.js +35 -95
  37. package/lib/cmap/connection_pool.js.map +1 -1
  38. package/lib/cmap/stream_description.js +19 -0
  39. package/lib/cmap/stream_description.js.map +1 -1
  40. package/lib/cmap/wire_protocol/compression.js.map +1 -1
  41. package/lib/cmap/wire_protocol/on_data.js +112 -0
  42. package/lib/cmap/wire_protocol/on_data.js.map +1 -0
  43. package/lib/collection.js +11 -3
  44. package/lib/collection.js.map +1 -1
  45. package/lib/connection_string.js +34 -2
  46. package/lib/connection_string.js.map +1 -1
  47. package/lib/constants.js +22 -2
  48. package/lib/constants.js.map +1 -1
  49. package/lib/cursor/abstract_cursor.js +5 -1
  50. package/lib/cursor/abstract_cursor.js.map +1 -1
  51. package/lib/error.js +7 -7
  52. package/lib/error.js.map +1 -1
  53. package/lib/index.js +9 -1
  54. package/lib/index.js.map +1 -1
  55. package/lib/mongo_client.js +8 -3
  56. package/lib/mongo_client.js.map +1 -1
  57. package/lib/mongo_client_auth_providers.js +55 -0
  58. package/lib/mongo_client_auth_providers.js.map +1 -0
  59. package/lib/mongo_logger.js +205 -27
  60. package/lib/mongo_logger.js.map +1 -1
  61. package/lib/mongo_types.js +26 -0
  62. package/lib/mongo_types.js.map +1 -1
  63. package/lib/operations/aggregate.js +3 -0
  64. package/lib/operations/aggregate.js.map +1 -1
  65. package/lib/operations/bulk_write.js +3 -0
  66. package/lib/operations/bulk_write.js.map +1 -1
  67. package/lib/operations/collections.js +3 -0
  68. package/lib/operations/collections.js.map +1 -1
  69. package/lib/operations/command.js +1 -1
  70. package/lib/operations/command.js.map +1 -1
  71. package/lib/operations/count.js +3 -0
  72. package/lib/operations/count.js.map +1 -1
  73. package/lib/operations/create_collection.js +3 -0
  74. package/lib/operations/create_collection.js.map +1 -1
  75. package/lib/operations/delete.js +3 -0
  76. package/lib/operations/delete.js.map +1 -1
  77. package/lib/operations/distinct.js +3 -0
  78. package/lib/operations/distinct.js.map +1 -1
  79. package/lib/operations/drop.js +6 -0
  80. package/lib/operations/drop.js.map +1 -1
  81. package/lib/operations/estimated_document_count.js +3 -0
  82. package/lib/operations/estimated_document_count.js.map +1 -1
  83. package/lib/operations/execute_operation.js +35 -9
  84. package/lib/operations/execute_operation.js.map +1 -1
  85. package/lib/operations/find.js +4 -1
  86. package/lib/operations/find.js.map +1 -1
  87. package/lib/operations/find_and_modify.js +5 -1
  88. package/lib/operations/find_and_modify.js.map +1 -1
  89. package/lib/operations/get_more.js +4 -1
  90. package/lib/operations/get_more.js.map +1 -1
  91. package/lib/operations/indexes.js +21 -0
  92. package/lib/operations/indexes.js.map +1 -1
  93. package/lib/operations/insert.js +6 -0
  94. package/lib/operations/insert.js.map +1 -1
  95. package/lib/operations/is_capped.js +3 -0
  96. package/lib/operations/is_capped.js.map +1 -1
  97. package/lib/operations/kill_cursors.js +4 -1
  98. package/lib/operations/kill_cursors.js.map +1 -1
  99. package/lib/operations/list_collections.js +3 -0
  100. package/lib/operations/list_collections.js.map +1 -1
  101. package/lib/operations/list_databases.js +3 -0
  102. package/lib/operations/list_databases.js.map +1 -1
  103. package/lib/operations/operation.js.map +1 -1
  104. package/lib/operations/options_operation.js +3 -0
  105. package/lib/operations/options_operation.js.map +1 -1
  106. package/lib/operations/profiling_level.js +3 -0
  107. package/lib/operations/profiling_level.js.map +1 -1
  108. package/lib/operations/remove_user.js +3 -0
  109. package/lib/operations/remove_user.js.map +1 -1
  110. package/lib/operations/rename.js +3 -0
  111. package/lib/operations/rename.js.map +1 -1
  112. package/lib/operations/run_command.js +8 -2
  113. package/lib/operations/run_command.js.map +1 -1
  114. package/lib/operations/search_indexes/create.js +4 -1
  115. package/lib/operations/search_indexes/create.js.map +1 -1
  116. package/lib/operations/search_indexes/drop.js +4 -1
  117. package/lib/operations/search_indexes/drop.js.map +1 -1
  118. package/lib/operations/search_indexes/update.js +4 -1
  119. package/lib/operations/search_indexes/update.js.map +1 -1
  120. package/lib/operations/set_profiling_level.js +3 -0
  121. package/lib/operations/set_profiling_level.js.map +1 -1
  122. package/lib/operations/stats.js +3 -0
  123. package/lib/operations/stats.js.map +1 -1
  124. package/lib/operations/update.js +3 -0
  125. package/lib/operations/update.js.map +1 -1
  126. package/lib/operations/validate_collection.js +3 -0
  127. package/lib/operations/validate_collection.js.map +1 -1
  128. package/lib/sdam/events.js +18 -0
  129. package/lib/sdam/events.js.map +1 -1
  130. package/lib/sdam/monitor.js +86 -71
  131. package/lib/sdam/monitor.js.map +1 -1
  132. package/lib/sdam/server.js +92 -98
  133. package/lib/sdam/server.js.map +1 -1
  134. package/lib/sdam/server_selection.js +13 -5
  135. package/lib/sdam/server_selection.js.map +1 -1
  136. package/lib/sdam/server_selection_events.js +85 -0
  137. package/lib/sdam/server_selection_events.js.map +1 -0
  138. package/lib/sdam/topology.js +61 -18
  139. package/lib/sdam/topology.js.map +1 -1
  140. package/lib/sessions.js +11 -9
  141. package/lib/sessions.js.map +1 -1
  142. package/lib/utils.js +25 -17
  143. package/lib/utils.js.map +1 -1
  144. package/mongodb.d.ts +131 -57
  145. package/package.json +28 -27
  146. package/src/bson.ts +2 -0
  147. package/src/bulk/common.ts +29 -22
  148. package/src/change_stream.ts +11 -5
  149. package/src/client-side-encryption/state_machine.ts +77 -62
  150. package/src/cmap/auth/auth_provider.ts +4 -0
  151. package/src/cmap/auth/gssapi.ts +1 -1
  152. package/src/cmap/auth/mongo_credentials.ts +2 -2
  153. package/src/cmap/auth/mongocr.ts +2 -6
  154. package/src/cmap/auth/mongodb_aws.ts +69 -64
  155. package/src/cmap/auth/mongodb_oidc/callback_workflow.ts +2 -2
  156. package/src/cmap/auth/mongodb_oidc/service_workflow.ts +1 -1
  157. package/src/cmap/auth/plain.ts +1 -1
  158. package/src/cmap/auth/scram.ts +7 -9
  159. package/src/cmap/auth/x509.ts +1 -5
  160. package/src/cmap/command_monitoring_events.ts +32 -4
  161. package/src/cmap/commands.ts +4 -0
  162. package/src/cmap/connect.ts +119 -159
  163. package/src/cmap/connection.ts +408 -961
  164. package/src/cmap/connection_pool.ts +93 -155
  165. package/src/cmap/stream_description.ts +21 -1
  166. package/src/cmap/wire_protocol/compression.ts +1 -2
  167. package/src/cmap/wire_protocol/on_data.ts +132 -0
  168. package/src/collection.ts +14 -6
  169. package/src/connection_string.ts +49 -3
  170. package/src/constants.ts +20 -0
  171. package/src/cursor/abstract_cursor.ts +7 -1
  172. package/src/error.ts +9 -9
  173. package/src/index.ts +33 -12
  174. package/src/mongo_client.ts +20 -7
  175. package/src/mongo_client_auth_providers.ts +54 -0
  176. package/src/mongo_logger.ts +376 -50
  177. package/src/mongo_types.ts +58 -3
  178. package/src/operations/aggregate.ts +4 -0
  179. package/src/operations/bulk_write.ts +4 -0
  180. package/src/operations/collections.ts +4 -0
  181. package/src/operations/command.ts +1 -1
  182. package/src/operations/count.ts +4 -0
  183. package/src/operations/create_collection.ts +4 -0
  184. package/src/operations/delete.ts +4 -0
  185. package/src/operations/distinct.ts +4 -0
  186. package/src/operations/drop.ts +8 -0
  187. package/src/operations/estimated_document_count.ts +4 -0
  188. package/src/operations/execute_operation.ts +28 -31
  189. package/src/operations/find.ts +5 -1
  190. package/src/operations/find_and_modify.ts +7 -5
  191. package/src/operations/get_more.ts +4 -1
  192. package/src/operations/indexes.ts +29 -0
  193. package/src/operations/insert.ts +8 -0
  194. package/src/operations/is_capped.ts +4 -0
  195. package/src/operations/kill_cursors.ts +5 -1
  196. package/src/operations/list_collections.ts +4 -0
  197. package/src/operations/list_databases.ts +4 -0
  198. package/src/operations/operation.ts +4 -0
  199. package/src/operations/options_operation.ts +3 -0
  200. package/src/operations/profiling_level.ts +4 -0
  201. package/src/operations/remove_user.ts +4 -0
  202. package/src/operations/rename.ts +4 -0
  203. package/src/operations/run_command.ts +10 -2
  204. package/src/operations/search_indexes/create.ts +5 -1
  205. package/src/operations/search_indexes/drop.ts +5 -1
  206. package/src/operations/search_indexes/update.ts +5 -1
  207. package/src/operations/set_profiling_level.ts +4 -0
  208. package/src/operations/stats.ts +4 -0
  209. package/src/operations/update.ts +4 -0
  210. package/src/operations/validate_collection.ts +4 -0
  211. package/src/sdam/events.ts +31 -3
  212. package/src/sdam/monitor.ts +119 -97
  213. package/src/sdam/server.ts +113 -152
  214. package/src/sdam/server_selection.ts +21 -13
  215. package/src/sdam/server_selection_events.ts +142 -0
  216. package/src/sdam/topology.ts +200 -46
  217. package/src/sessions.ts +33 -32
  218. package/src/utils.ts +28 -32
  219. package/lib/cmap/message_stream.js +0 -149
  220. package/lib/cmap/message_stream.js.map +0 -1
  221. package/src/cmap/message_stream.ts +0 -220
@@ -16,16 +16,9 @@ import {
16
16
  MongoRuntimeError,
17
17
  needsRetryableWriteLabel
18
18
  } from '../error';
19
- import { type Callback, HostAddress, ns } from '../utils';
20
- import { AuthContext, type AuthProvider } from './auth/auth_provider';
21
- import { GSSAPI } from './auth/gssapi';
22
- import { MongoCR } from './auth/mongocr';
23
- import { MongoDBAWS } from './auth/mongodb_aws';
24
- import { MongoDBOIDC } from './auth/mongodb_oidc';
25
- import { Plain } from './auth/plain';
19
+ import { HostAddress, ns, promiseWithResolvers } from '../utils';
20
+ import { AuthContext } from './auth/auth_provider';
26
21
  import { AuthMechanism } from './auth/providers';
27
- import { ScramSHA1, ScramSHA256 } from './auth/scram';
28
- import { X509 } from './auth/x509';
29
22
  import {
30
23
  type CommandOptions,
31
24
  Connection,
@@ -40,42 +33,29 @@ import {
40
33
  MIN_SUPPORTED_WIRE_VERSION
41
34
  } from './wire_protocol/constants';
42
35
 
43
- /** @internal */
44
- export const AUTH_PROVIDERS = new Map<AuthMechanism | string, AuthProvider>([
45
- [AuthMechanism.MONGODB_AWS, new MongoDBAWS()],
46
- [AuthMechanism.MONGODB_CR, new MongoCR()],
47
- [AuthMechanism.MONGODB_GSSAPI, new GSSAPI()],
48
- [AuthMechanism.MONGODB_OIDC, new MongoDBOIDC()],
49
- [AuthMechanism.MONGODB_PLAIN, new Plain()],
50
- [AuthMechanism.MONGODB_SCRAM_SHA1, new ScramSHA1()],
51
- [AuthMechanism.MONGODB_SCRAM_SHA256, new ScramSHA256()],
52
- [AuthMechanism.MONGODB_X509, new X509()]
53
- ]);
54
-
55
36
  /** @public */
56
37
  export type Stream = Socket | TLSSocket;
57
38
 
58
- export function connect(options: ConnectionOptions, callback: Callback<Connection>): void {
59
- makeConnection({ ...options, existingSocket: undefined }, (err, socket) => {
60
- if (err || !socket) {
61
- return callback(err);
62
- }
63
-
64
- let ConnectionType = options.connectionType ?? Connection;
65
- if (options.autoEncrypter) {
66
- ConnectionType = CryptoConnection;
67
- }
39
+ export async function connect(options: ConnectionOptions): Promise<Connection> {
40
+ let connection: Connection | null = null;
41
+ try {
42
+ const socket = await makeSocket(options);
43
+ connection = makeConnection(options, socket);
44
+ await performInitialHandshake(connection, options);
45
+ return connection;
46
+ } catch (error) {
47
+ connection?.destroy({ force: false });
48
+ throw error;
49
+ }
50
+ }
68
51
 
69
- const connection = new ConnectionType(socket, options);
52
+ export function makeConnection(options: ConnectionOptions, socket: Stream): Connection {
53
+ let ConnectionType = options.connectionType ?? Connection;
54
+ if (options.autoEncrypter) {
55
+ ConnectionType = CryptoConnection;
56
+ }
70
57
 
71
- performInitialHandshake(connection, options).then(
72
- () => callback(undefined, connection),
73
- error => {
74
- connection.destroy({ force: false });
75
- callback(error);
76
- }
77
- );
78
- });
58
+ return new ConnectionType(socket, options);
79
59
  }
80
60
 
81
61
  function checkSupportedServer(hello: Document, options: ConnectionOptions) {
@@ -103,7 +83,7 @@ function checkSupportedServer(hello: Document, options: ConnectionOptions) {
103
83
  return new MongoCompatibilityError(message);
104
84
  }
105
85
 
106
- async function performInitialHandshake(
86
+ export async function performInitialHandshake(
107
87
  conn: Connection,
108
88
  options: ConnectionOptions
109
89
  ): Promise<void> {
@@ -112,7 +92,7 @@ async function performInitialHandshake(
112
92
  if (credentials) {
113
93
  if (
114
94
  !(credentials.mechanism === AuthMechanism.MONGODB_DEFAULT) &&
115
- !AUTH_PROVIDERS.get(credentials.mechanism)
95
+ !options.authProviders.getOrCreateProvider(credentials.mechanism)
116
96
  ) {
117
97
  throw new MongoInvalidArgumentError(`AuthMechanism '${credentials.mechanism}' not supported`);
118
98
  }
@@ -131,7 +111,7 @@ async function performInitialHandshake(
131
111
  }
132
112
 
133
113
  const start = new Date().getTime();
134
- const response = await conn.commandAsync(ns('admin.$cmd'), handshakeDoc, handshakeOptions);
114
+ const response = await conn.command(ns('admin.$cmd'), handshakeDoc, handshakeOptions);
135
115
 
136
116
  if (!('isWritablePrimary' in response)) {
137
117
  // Provide hello-style response document.
@@ -167,7 +147,7 @@ async function performInitialHandshake(
167
147
  authContext.response = response;
168
148
 
169
149
  const resolvedCredentials = credentials.resolveAuthMechanism(response);
170
- const provider = AUTH_PROVIDERS.get(resolvedCredentials.mechanism);
150
+ const provider = options.authProviders.getOrCreateProvider(resolvedCredentials.mechanism);
171
151
  if (!provider) {
172
152
  throw new MongoInvalidArgumentError(
173
153
  `No AuthProvider for ${resolvedCredentials.mechanism} defined.`
@@ -186,8 +166,16 @@ async function performInitialHandshake(
186
166
  throw error;
187
167
  }
188
168
  }
169
+
170
+ // Connection establishment is socket creation (tcp handshake, tls handshake, MongoDB handshake (saslStart, saslContinue))
171
+ // Once connection is established, command logging can log events (if enabled)
172
+ conn.established = true;
189
173
  }
190
174
 
175
+ /**
176
+ * HandshakeDocument used during authentication.
177
+ * @internal
178
+ */
191
179
  export interface HandshakeDocument extends Document {
192
180
  /**
193
181
  * @deprecated Use hello instead
@@ -229,7 +217,9 @@ export async function prepareHandshakeDocument(
229
217
  if (credentials.mechanism === AuthMechanism.MONGODB_DEFAULT && credentials.username) {
230
218
  handshakeDoc.saslSupportedMechs = `${credentials.source}.${credentials.username}`;
231
219
 
232
- const provider = AUTH_PROVIDERS.get(AuthMechanism.MONGODB_SCRAM_SHA256);
220
+ const provider = authContext.options.authProviders.getOrCreateProvider(
221
+ AuthMechanism.MONGODB_SCRAM_SHA256
222
+ );
233
223
  if (!provider) {
234
224
  // This auth mechanism is always present.
235
225
  throw new MongoInvalidArgumentError(
@@ -238,7 +228,7 @@ export async function prepareHandshakeDocument(
238
228
  }
239
229
  return provider.prepare(handshakeDoc, authContext);
240
230
  }
241
- const provider = AUTH_PROVIDERS.get(credentials.mechanism);
231
+ const provider = authContext.options.authProviders.getOrCreateProvider(credentials.mechanism);
242
232
  if (!provider) {
243
233
  throw new MongoInvalidArgumentError(`No AuthProvider for ${credentials.mechanism} defined.`);
244
234
  }
@@ -325,11 +315,7 @@ function parseSslOptions(options: MakeConnectionOptions): TLSConnectionOpts {
325
315
  return result;
326
316
  }
327
317
 
328
- const SOCKET_ERROR_EVENT_LIST = ['error', 'close', 'timeout', 'parseError'] as const;
329
- type ErrorHandlerEventName = (typeof SOCKET_ERROR_EVENT_LIST)[number] | 'cancel';
330
- const SOCKET_ERROR_EVENTS = new Set(SOCKET_ERROR_EVENT_LIST);
331
-
332
- function makeConnection(options: MakeConnectionOptions, _callback: Callback<Stream>) {
318
+ export async function makeSocket(options: MakeConnectionOptions): Promise<Stream> {
333
319
  const useTLS = options.tls ?? false;
334
320
  const noDelay = options.noDelay ?? true;
335
321
  const connectTimeoutMS = options.connectTimeoutMS ?? 30000;
@@ -337,23 +323,13 @@ function makeConnection(options: MakeConnectionOptions, _callback: Callback<Stre
337
323
  const existingSocket = options.existingSocket;
338
324
 
339
325
  let socket: Stream;
340
- const callback: Callback<Stream> = function (err, ret) {
341
- if (err && socket) {
342
- socket.destroy();
343
- }
344
-
345
- _callback(err, ret);
346
- };
347
326
 
348
327
  if (options.proxyHost != null) {
349
328
  // Currently, only Socks5 is supported.
350
- return makeSocks5Connection(
351
- {
352
- ...options,
353
- connectTimeoutMS // Should always be present for Socks5
354
- },
355
- callback
356
- );
329
+ return makeSocks5Connection({
330
+ ...options,
331
+ connectTimeoutMS // Should always be present for Socks5
332
+ });
357
333
  }
358
334
 
359
335
  if (useTLS) {
@@ -375,47 +351,41 @@ function makeConnection(options: MakeConnectionOptions, _callback: Callback<Stre
375
351
  socket.setTimeout(connectTimeoutMS);
376
352
  socket.setNoDelay(noDelay);
377
353
 
378
- const connectEvent = useTLS ? 'secureConnect' : 'connect';
379
- let cancellationHandler: (err: Error) => void;
380
- function errorHandler(eventName: ErrorHandlerEventName) {
381
- return (err: Error) => {
382
- SOCKET_ERROR_EVENTS.forEach(event => socket.removeAllListeners(event));
383
- if (cancellationHandler && options.cancellationToken) {
384
- options.cancellationToken.removeListener('cancel', cancellationHandler);
385
- }
386
-
387
- socket.removeListener(connectEvent, connectHandler);
388
- callback(connectionFailureError(eventName, err));
389
- };
390
- }
354
+ let cancellationHandler: ((err: Error) => void) | null = null;
391
355
 
392
- function connectHandler() {
393
- SOCKET_ERROR_EVENTS.forEach(event => socket.removeAllListeners(event));
394
- if (cancellationHandler && options.cancellationToken) {
395
- options.cancellationToken.removeListener('cancel', cancellationHandler);
356
+ const { promise: connectedSocket, resolve, reject } = promiseWithResolvers<Stream>();
357
+ if (existingSocket) {
358
+ resolve(socket);
359
+ } else {
360
+ const connectEvent = useTLS ? 'secureConnect' : 'connect';
361
+ socket
362
+ .once(connectEvent, () => resolve(socket))
363
+ .once('error', error => reject(connectionFailureError('error', error)))
364
+ .once('timeout', () => reject(connectionFailureError('timeout')))
365
+ .once('close', () => reject(connectionFailureError('close')));
366
+
367
+ if (options.cancellationToken != null) {
368
+ cancellationHandler = () => reject(connectionFailureError('cancel'));
369
+ options.cancellationToken.once('cancel', cancellationHandler);
396
370
  }
371
+ }
397
372
 
398
- if ('authorizationError' in socket) {
399
- if (socket.authorizationError && rejectUnauthorized) {
400
- // TODO(NODE-5192): wrap this with a MongoError subclass
401
- return callback(socket.authorizationError);
402
- }
373
+ try {
374
+ socket = await connectedSocket;
375
+ return socket;
376
+ } catch (error) {
377
+ socket.destroy();
378
+ if ('authorizationError' in socket && socket.authorizationError != null && rejectUnauthorized) {
379
+ // TODO(NODE-5192): wrap this with a MongoError subclass
380
+ throw socket.authorizationError;
403
381
  }
404
-
382
+ throw error;
383
+ } finally {
405
384
  socket.setTimeout(0);
406
- callback(undefined, socket);
407
- }
408
-
409
- SOCKET_ERROR_EVENTS.forEach(event => socket.once(event, errorHandler(event)));
410
- if (options.cancellationToken) {
411
- cancellationHandler = errorHandler('cancel');
412
- options.cancellationToken.once('cancel', cancellationHandler);
413
- }
414
-
415
- if (existingSocket) {
416
- process.nextTick(connectHandler);
417
- } else {
418
- socket.once(connectEvent, connectHandler);
385
+ socket.removeAllListeners();
386
+ if (cancellationHandler != null) {
387
+ options.cancellationToken?.removeListener('cancel', cancellationHandler);
388
+ }
419
389
  }
420
390
  }
421
391
 
@@ -431,78 +401,68 @@ function loadSocks() {
431
401
  return socks;
432
402
  }
433
403
 
434
- function makeSocks5Connection(options: MakeConnectionOptions, callback: Callback<Stream>) {
404
+ async function makeSocks5Connection(options: MakeConnectionOptions): Promise<Stream> {
435
405
  const hostAddress = HostAddress.fromHostPort(
436
406
  options.proxyHost ?? '', // proxyHost is guaranteed to set here
437
407
  options.proxyPort ?? 1080
438
408
  );
439
409
 
440
410
  // First, connect to the proxy server itself:
441
- makeConnection(
442
- {
443
- ...options,
444
- hostAddress,
445
- tls: false,
446
- proxyHost: undefined
447
- },
448
- (err, rawSocket) => {
449
- if (err || !rawSocket) {
450
- return callback(err);
451
- }
411
+ const rawSocket = await makeSocket({
412
+ ...options,
413
+ hostAddress,
414
+ tls: false,
415
+ proxyHost: undefined
416
+ });
452
417
 
453
- const destination = parseConnectOptions(options) as net.TcpNetConnectOpts;
454
- if (typeof destination.host !== 'string' || typeof destination.port !== 'number') {
455
- return callback(
456
- new MongoInvalidArgumentError('Can only make Socks5 connections to TCP hosts')
457
- );
458
- }
418
+ const destination = parseConnectOptions(options) as net.TcpNetConnectOpts;
419
+ if (typeof destination.host !== 'string' || typeof destination.port !== 'number') {
420
+ throw new MongoInvalidArgumentError('Can only make Socks5 connections to TCP hosts');
421
+ }
459
422
 
460
- try {
461
- socks ??= loadSocks();
462
- } catch (error) {
463
- return callback(error);
423
+ socks ??= loadSocks();
424
+
425
+ try {
426
+ // Then, establish the Socks5 proxy connection:
427
+ const { socket } = await socks.SocksClient.createConnection({
428
+ existing_socket: rawSocket,
429
+ timeout: options.connectTimeoutMS,
430
+ command: 'connect',
431
+ destination: {
432
+ host: destination.host,
433
+ port: destination.port
434
+ },
435
+ proxy: {
436
+ // host and port are ignored because we pass existing_socket
437
+ host: 'iLoveJavaScript',
438
+ port: 0,
439
+ type: 5,
440
+ userId: options.proxyUsername || undefined,
441
+ password: options.proxyPassword || undefined
464
442
  }
443
+ });
465
444
 
466
- // Then, establish the Socks5 proxy connection:
467
- socks.SocksClient.createConnection({
468
- existing_socket: rawSocket,
469
- timeout: options.connectTimeoutMS,
470
- command: 'connect',
471
- destination: {
472
- host: destination.host,
473
- port: destination.port
474
- },
475
- proxy: {
476
- // host and port are ignored because we pass existing_socket
477
- host: 'iLoveJavaScript',
478
- port: 0,
479
- type: 5,
480
- userId: options.proxyUsername || undefined,
481
- password: options.proxyPassword || undefined
482
- }
483
- }).then(
484
- ({ socket }) => {
485
- // Finally, now treat the resulting duplex stream as the
486
- // socket over which we send and receive wire protocol messages:
487
- makeConnection(
488
- {
489
- ...options,
490
- existingSocket: socket,
491
- proxyHost: undefined
492
- },
493
- callback
494
- );
495
- },
496
- error => callback(connectionFailureError('error', error))
497
- );
498
- }
499
- );
445
+ // Finally, now treat the resulting duplex stream as the
446
+ // socket over which we send and receive wire protocol messages:
447
+ return await makeSocket({
448
+ ...options,
449
+ existingSocket: socket,
450
+ proxyHost: undefined
451
+ });
452
+ } catch (error) {
453
+ throw connectionFailureError('error', error);
454
+ }
500
455
  }
501
456
 
502
- function connectionFailureError(type: ErrorHandlerEventName, err: Error) {
457
+ function connectionFailureError(type: 'error', cause: Error): MongoNetworkError;
458
+ function connectionFailureError(type: 'close' | 'timeout' | 'cancel'): MongoNetworkError;
459
+ function connectionFailureError(
460
+ type: 'error' | 'close' | 'timeout' | 'cancel',
461
+ cause?: Error
462
+ ): MongoNetworkError {
503
463
  switch (type) {
504
464
  case 'error':
505
- return new MongoNetworkError(MongoError.buildErrorMessage(err), { cause: err });
465
+ return new MongoNetworkError(MongoError.buildErrorMessage(cause), { cause });
506
466
  case 'timeout':
507
467
  return new MongoNetworkTimeoutError('connection timed out');
508
468
  case 'close':