mongodb 5.2.0 → 5.3.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 (60) hide show
  1. package/lib/admin.js +2 -0
  2. package/lib/admin.js.map +1 -1
  3. package/lib/bulk/common.js +28 -7
  4. package/lib/bulk/common.js.map +1 -1
  5. package/lib/cmap/command_monitoring_events.js +6 -0
  6. package/lib/cmap/command_monitoring_events.js.map +1 -1
  7. package/lib/cmap/connect.js +1 -0
  8. package/lib/cmap/connect.js.map +1 -1
  9. package/lib/cmap/connection.js.map +1 -1
  10. package/lib/cmap/connection_pool.js +7 -3
  11. package/lib/cmap/connection_pool.js.map +1 -1
  12. package/lib/cmap/connection_pool_events.js +28 -3
  13. package/lib/cmap/connection_pool_events.js.map +1 -1
  14. package/lib/cmap/handshake/client_metadata.js +173 -0
  15. package/lib/cmap/handshake/client_metadata.js.map +1 -0
  16. package/lib/connection_string.js +40 -53
  17. package/lib/connection_string.js.map +1 -1
  18. package/lib/constants.js +11 -0
  19. package/lib/constants.js.map +1 -1
  20. package/lib/cursor/abstract_cursor.js +1 -0
  21. package/lib/cursor/abstract_cursor.js.map +1 -1
  22. package/lib/db.js +2 -0
  23. package/lib/db.js.map +1 -1
  24. package/lib/mongo_client.js +1 -0
  25. package/lib/mongo_client.js.map +1 -1
  26. package/lib/mongo_logger.js +224 -27
  27. package/lib/mongo_logger.js.map +1 -1
  28. package/lib/operations/add_user.js.map +1 -1
  29. package/lib/operations/find.js +0 -7
  30. package/lib/operations/find.js.map +1 -1
  31. package/lib/operations/update.js.map +1 -1
  32. package/lib/sdam/srv_polling.js +1 -15
  33. package/lib/sdam/srv_polling.js.map +1 -1
  34. package/lib/sdam/topology.js.map +1 -1
  35. package/lib/utils.js +33 -35
  36. package/lib/utils.js.map +1 -1
  37. package/mongodb.d.ts +139 -23
  38. package/package.json +2 -2
  39. package/src/admin.ts +2 -0
  40. package/src/bulk/common.ts +28 -7
  41. package/src/cmap/command_monitoring_events.ts +13 -1
  42. package/src/cmap/connect.ts +3 -1
  43. package/src/cmap/connection.ts +3 -1
  44. package/src/cmap/connection_pool.ts +14 -4
  45. package/src/cmap/connection_pool_events.ts +68 -6
  46. package/src/cmap/handshake/client_metadata.ts +272 -0
  47. package/src/collection.ts +3 -3
  48. package/src/connection_string.ts +44 -55
  49. package/src/constants.ts +11 -0
  50. package/src/cursor/abstract_cursor.ts +1 -0
  51. package/src/db.ts +2 -0
  52. package/src/index.ts +20 -3
  53. package/src/mongo_client.ts +25 -4
  54. package/src/mongo_logger.ts +326 -43
  55. package/src/operations/add_user.ts +8 -2
  56. package/src/operations/find.ts +0 -10
  57. package/src/operations/update.ts +8 -4
  58. package/src/sdam/srv_polling.ts +1 -16
  59. package/src/sdam/topology.ts +1 -3
  60. package/src/utils.ts +37 -73
@@ -6,6 +6,7 @@ import { URLSearchParams } from 'url';
6
6
  import type { Document } from './bson';
7
7
  import { MongoCredentials } from './cmap/auth/mongo_credentials';
8
8
  import { AUTH_MECHS_AUTH_SRC_EXTERNAL, AuthMechanism } from './cmap/auth/providers';
9
+ import { makeClientMetadata } from './cmap/handshake/client_metadata';
9
10
  import { Compressor, CompressorName } from './cmap/wire_protocol/compression';
10
11
  import { Encrypter } from './encrypter';
11
12
  import {
@@ -32,7 +33,7 @@ import {
32
33
  emitWarningOnce,
33
34
  HostAddress,
34
35
  isRecord,
35
- makeClientMetadata,
36
+ matchesParentDomain,
36
37
  parseInteger,
37
38
  setDifference
38
39
  } from './utils';
@@ -45,21 +46,6 @@ const LB_REPLICA_SET_ERROR = 'loadBalanced option not supported with a replicaSe
45
46
  const LB_DIRECT_CONNECTION_ERROR =
46
47
  'loadBalanced option not supported when directConnection is provided';
47
48
 
48
- /**
49
- * Determines whether a provided address matches the provided parent domain in order
50
- * to avoid certain attack vectors.
51
- *
52
- * @param srvAddress - The address to check against a domain
53
- * @param parentDomain - The domain to check the provided address against
54
- * @returns Whether the provided address matches the parent domain
55
- */
56
- function matchesParentDomain(srvAddress: string, parentDomain: string): boolean {
57
- const regex = /^.*?\./;
58
- const srv = `.${srvAddress.replace(regex, '')}`;
59
- const parent = `.${parentDomain.replace(regex, '')}`;
60
- return srv.endsWith(parent);
61
- }
62
-
63
49
  /**
64
50
  * Lookup a `mongodb+srv` connection string, combine the parts and reparse it as a normal
65
51
  * connection string.
@@ -277,7 +263,7 @@ export function parseOptions(
277
263
 
278
264
  mongoOptions.hosts = isSRV ? [] : hosts.map(HostAddress.fromString);
279
265
 
280
- const urlOptions = new CaseInsensitiveMap<any[]>();
266
+ const urlOptions = new CaseInsensitiveMap<unknown[]>();
281
267
 
282
268
  if (url.pathname !== '/' && url.pathname !== '') {
283
269
  const dbName = decodeURIComponent(
@@ -312,7 +298,7 @@ export function parseOptions(
312
298
  }
313
299
  }
314
300
 
315
- const objectOptions = new CaseInsensitiveMap(
301
+ const objectOptions = new CaseInsensitiveMap<unknown>(
316
302
  Object.entries(options).filter(([, v]) => v != null)
317
303
  );
318
304
 
@@ -330,48 +316,42 @@ export function parseOptions(
330
316
 
331
317
  // All option collection
332
318
 
333
- const allOptions = new CaseInsensitiveMap();
319
+ const allProvidedOptions = new CaseInsensitiveMap<unknown[]>();
334
320
 
335
- const allKeys = new Set<string>([
336
- ...urlOptions.keys(),
337
- ...objectOptions.keys(),
338
- ...DEFAULT_OPTIONS.keys()
339
- ]);
321
+ const allProvidedKeys = new Set<string>([...urlOptions.keys(), ...objectOptions.keys()]);
340
322
 
341
- for (const key of allKeys) {
323
+ for (const key of allProvidedKeys) {
342
324
  const values = [];
343
325
  const objectOptionValue = objectOptions.get(key);
344
326
  if (objectOptionValue != null) {
345
327
  values.push(objectOptionValue);
346
328
  }
347
- const urlValue = urlOptions.get(key);
348
- if (urlValue != null) {
349
- values.push(...urlValue);
350
- }
351
- const defaultOptionsValue = DEFAULT_OPTIONS.get(key);
352
- if (defaultOptionsValue != null) {
353
- values.push(defaultOptionsValue);
354
- }
355
- allOptions.set(key, values);
329
+
330
+ const urlValues = urlOptions.get(key) ?? [];
331
+ values.push(...urlValues);
332
+ allProvidedOptions.set(key, values);
356
333
  }
357
334
 
358
- if (allOptions.has('tlsCertificateKeyFile') && !allOptions.has('tlsCertificateFile')) {
359
- allOptions.set('tlsCertificateFile', allOptions.get('tlsCertificateKeyFile'));
335
+ if (
336
+ allProvidedOptions.has('tlsCertificateKeyFile') &&
337
+ !allProvidedOptions.has('tlsCertificateFile')
338
+ ) {
339
+ allProvidedOptions.set('tlsCertificateFile', allProvidedOptions.get('tlsCertificateKeyFile'));
360
340
  }
361
341
 
362
- if (allOptions.has('tls') || allOptions.has('ssl')) {
363
- const tlsAndSslOpts = (allOptions.get('tls') || [])
364
- .concat(allOptions.get('ssl') || [])
342
+ if (allProvidedOptions.has('tls') || allProvidedOptions.has('ssl')) {
343
+ const tlsAndSslOpts = (allProvidedOptions.get('tls') || [])
344
+ .concat(allProvidedOptions.get('ssl') || [])
365
345
  .map(getBoolean.bind(null, 'tls/ssl'));
366
346
  if (new Set(tlsAndSslOpts).size !== 1) {
367
347
  throw new MongoParseError('All values of tls/ssl must be the same.');
368
348
  }
369
349
  }
370
350
 
371
- checkTLSOptions(allOptions);
351
+ checkTLSOptions(allProvidedOptions);
372
352
 
373
353
  const unsupportedOptions = setDifference(
374
- allKeys,
354
+ allProvidedKeys,
375
355
  Array.from(Object.keys(OPTIONS)).map(s => s.toLowerCase())
376
356
  );
377
357
  if (unsupportedOptions.size !== 0) {
@@ -385,9 +365,20 @@ export function parseOptions(
385
365
  // Option parsing and setting
386
366
 
387
367
  for (const [key, descriptor] of Object.entries(OPTIONS)) {
388
- const values = allOptions.get(key);
389
- if (!values || values.length === 0) continue;
390
- setOption(mongoOptions, key, descriptor, values);
368
+ const values = allProvidedOptions.get(key);
369
+ if (!values || values.length === 0) {
370
+ if (DEFAULT_OPTIONS.has(key)) {
371
+ setOption(mongoOptions, key, descriptor, [DEFAULT_OPTIONS.get(key)]);
372
+ }
373
+ } else {
374
+ const { deprecated } = descriptor;
375
+ if (deprecated) {
376
+ const deprecatedMsg = typeof deprecated === 'string' ? `: ${deprecated}` : '';
377
+ emitWarning(`${key} is a deprecated option${deprecatedMsg}`);
378
+ }
379
+
380
+ setOption(mongoOptions, key, descriptor, values);
381
+ }
391
382
  }
392
383
 
393
384
  if (mongoOptions.credentials) {
@@ -397,7 +388,7 @@ export function parseOptions(
397
388
  const isOidc = mongoOptions.credentials.mechanism === AuthMechanism.MONGODB_OIDC;
398
389
  if (
399
390
  (isGssapi || isX509) &&
400
- allOptions.has('authSource') &&
391
+ allProvidedOptions.has('authSource') &&
401
392
  mongoOptions.credentials.source !== '$external'
402
393
  ) {
403
394
  // If authSource was explicitly given and its incorrect, we error
@@ -409,7 +400,7 @@ export function parseOptions(
409
400
  if (
410
401
  !(isGssapi || isX509 || isAws || isOidc) &&
411
402
  mongoOptions.dbName &&
412
- !allOptions.has('authSource')
403
+ !allProvidedOptions.has('authSource')
413
404
  ) {
414
405
  // inherit the dbName unless GSSAPI or X509, then silently ignore dbName
415
406
  // and there was no specific authSource given
@@ -585,14 +576,9 @@ function setOption(
585
576
  descriptor: OptionDescriptor,
586
577
  values: unknown[]
587
578
  ) {
588
- const { target, type, transform, deprecated } = descriptor;
579
+ const { target, type, transform } = descriptor;
589
580
  const name = target ?? key;
590
581
 
591
- if (deprecated) {
592
- const deprecatedMsg = typeof deprecated === 'string' ? `: ${deprecated}` : '';
593
- emitWarning(`${key} is a deprecated option${deprecatedMsg}`);
594
- }
595
-
596
582
  switch (type) {
597
583
  case 'boolean':
598
584
  mongoOptions[name] = getBoolean(name, values[0]);
@@ -866,11 +852,13 @@ export const OPTIONS = {
866
852
  },
867
853
  keepAlive: {
868
854
  default: true,
869
- type: 'boolean'
855
+ type: 'boolean',
856
+ deprecated: 'Will not be able to turn off in the future.'
870
857
  },
871
858
  keepAliveInitialDelay: {
872
859
  default: 120000,
873
- type: 'uint'
860
+ type: 'uint',
861
+ deprecated: 'Will not be configurable in the future.'
874
862
  },
875
863
  loadBalanced: {
876
864
  default: false,
@@ -1292,5 +1280,6 @@ export const DEFAULT_OPTIONS = new CaseInsensitiveMap(
1292
1280
  */
1293
1281
  export const FEATURE_FLAGS = new Set([
1294
1282
  Symbol.for('@@mdb.skipPingOnConnect'),
1295
- Symbol.for('@@mdb.enableMongoLogger')
1283
+ Symbol.for('@@mdb.enableMongoLogger'),
1284
+ Symbol.for('@@mdb.internalLoggerConfig')
1296
1285
  ]);
package/src/constants.ts CHANGED
@@ -23,16 +23,27 @@ export const SERVER_DESCRIPTION_CHANGED = 'serverDescriptionChanged' as const;
23
23
  export const TOPOLOGY_OPENING = 'topologyOpening' as const;
24
24
  export const TOPOLOGY_CLOSED = 'topologyClosed' as const;
25
25
  export const TOPOLOGY_DESCRIPTION_CHANGED = 'topologyDescriptionChanged' as const;
26
+ /** @internal */
26
27
  export const CONNECTION_POOL_CREATED = 'connectionPoolCreated' as const;
28
+ /** @internal */
27
29
  export const CONNECTION_POOL_CLOSED = 'connectionPoolClosed' as const;
30
+ /** @internal */
28
31
  export const CONNECTION_POOL_CLEARED = 'connectionPoolCleared' as const;
32
+ /** @internal */
29
33
  export const CONNECTION_POOL_READY = 'connectionPoolReady' as const;
34
+ /** @internal */
30
35
  export const CONNECTION_CREATED = 'connectionCreated' as const;
36
+ /** @internal */
31
37
  export const CONNECTION_READY = 'connectionReady' as const;
38
+ /** @internal */
32
39
  export const CONNECTION_CLOSED = 'connectionClosed' as const;
40
+ /** @internal */
33
41
  export const CONNECTION_CHECK_OUT_STARTED = 'connectionCheckOutStarted' as const;
42
+ /** @internal */
34
43
  export const CONNECTION_CHECK_OUT_FAILED = 'connectionCheckOutFailed' as const;
44
+ /** @internal */
35
45
  export const CONNECTION_CHECKED_OUT = 'connectionCheckedOut' as const;
46
+ /** @internal */
36
47
  export const CONNECTION_CHECKED_IN = 'connectionCheckedIn' as const;
37
48
  export const CLUSTER_TIME_RECEIVED = 'clusterTimeReceived' as const;
38
49
  export const COMMAND_STARTED = 'commandStarted' as const;
@@ -397,6 +397,7 @@ export abstract class AbstractCursor<
397
397
  * If the iterator returns `false`, iteration will stop.
398
398
  *
399
399
  * @param iterator - The iteration callback.
400
+ * @deprecated - Will be removed in a future release. Use for await...of instead.
400
401
  */
401
402
  async forEach(iterator: (doc: TSchema) => boolean | void): Promise<void> {
402
403
  if (typeof iterator !== 'function') {
package/src/db.ts CHANGED
@@ -405,6 +405,8 @@ export class Db {
405
405
  * @param username - The username for the new user
406
406
  * @param passwordOrOptions - An optional password for the new user, or the options for the command
407
407
  * @param options - Optional settings for the command
408
+ * @deprecated Use the createUser command in `db.command()` instead.
409
+ * @see https://www.mongodb.com/docs/manual/reference/command/createUser/
408
410
  */
409
411
  async addUser(
410
412
  username: string,
package/src/index.ts CHANGED
@@ -238,6 +238,7 @@ export type {
238
238
  WaitQueueMember,
239
239
  WithConnectionCallback
240
240
  } from './cmap/connection_pool';
241
+ export type { ClientMetadata, ClientMetadataOptions } from './cmap/handshake/client_metadata';
241
242
  export type {
242
243
  MessageStream,
243
244
  MessageStreamOptions,
@@ -247,7 +248,20 @@ export type { ConnectionPoolMetrics } from './cmap/metrics';
247
248
  export type { StreamDescription, StreamDescriptionOptions } from './cmap/stream_description';
248
249
  export type { CompressorName } from './cmap/wire_protocol/compression';
249
250
  export type { CollectionOptions, CollectionPrivate, ModifyResult } from './collection';
250
- export type { MONGO_CLIENT_EVENTS } from './constants';
251
+ export type {
252
+ CONNECTION_CHECK_OUT_FAILED,
253
+ CONNECTION_CHECK_OUT_STARTED,
254
+ CONNECTION_CHECKED_IN,
255
+ CONNECTION_CHECKED_OUT,
256
+ CONNECTION_CLOSED,
257
+ CONNECTION_CREATED,
258
+ CONNECTION_POOL_CLEARED,
259
+ CONNECTION_POOL_CLOSED,
260
+ CONNECTION_POOL_CREATED,
261
+ CONNECTION_POOL_READY,
262
+ CONNECTION_READY,
263
+ MONGO_CLIENT_EVENTS
264
+ } from './constants';
251
265
  export type {
252
266
  AbstractCursorEvents,
253
267
  AbstractCursorOptions,
@@ -289,6 +303,11 @@ export type {
289
303
  WithSessionCallback
290
304
  } from './mongo_client';
291
305
  export type {
306
+ Log,
307
+ LogConvertible,
308
+ Loggable,
309
+ LoggableEvent,
310
+ MongoDBLogWritable,
292
311
  MongoLoggableComponent,
293
312
  MongoLogger,
294
313
  MongoLoggerEnvOptions,
@@ -463,8 +482,6 @@ export type { Transaction, TransactionOptions, TxnState } from './transactions';
463
482
  export type {
464
483
  BufferPool,
465
484
  Callback,
466
- ClientMetadata,
467
- ClientMetadataOptions,
468
485
  EventEmitterWithState,
469
486
  HostAddress,
470
487
  List,
@@ -8,6 +8,7 @@ import type { AuthMechanismProperties, MongoCredentials } from './cmap/auth/mong
8
8
  import type { AuthMechanism } from './cmap/auth/providers';
9
9
  import type { LEGAL_TCP_SOCKET_OPTIONS, LEGAL_TLS_SOCKET_OPTIONS } from './cmap/connect';
10
10
  import type { Connection } from './cmap/connection';
11
+ import type { ClientMetadata } from './cmap/handshake/client_metadata';
11
12
  import type { CompressorName } from './cmap/wire_protocol/compression';
12
13
  import { parseOptions, resolveSRVRecord } from './connection_string';
13
14
  import { MONGO_CLIENT_EVENTS } from './constants';
@@ -24,7 +25,7 @@ import { readPreferenceServerSelector } from './sdam/server_selection';
24
25
  import type { SrvPoller } from './sdam/srv_polling';
25
26
  import { Topology, TopologyEvents } from './sdam/topology';
26
27
  import { ClientSession, ClientSessionOptions, ServerSessionPool } from './sessions';
27
- import { ClientMetadata, HostAddress, MongoDBNamespace, ns, resolveOptions } from './utils';
28
+ import { HostAddress, MongoDBNamespace, ns, resolveOptions } from './utils';
28
29
  import type { W, WriteConcern, WriteConcernSettings } from './write_concern';
29
30
 
30
31
  /** @public */
@@ -211,9 +212,12 @@ export interface MongoClientOptions extends BSONSerializeOptions, SupportedNodeC
211
212
  sslCRL?: string;
212
213
  /** TCP Connection no delay */
213
214
  noDelay?: boolean;
214
- /** TCP Connection keep alive enabled */
215
+ /** @deprecated TCP Connection keep alive enabled. Will not be able to turn off in the future. */
215
216
  keepAlive?: boolean;
216
- /** The number of milliseconds to wait before initiating keepAlive on the TCP socket */
217
+ /**
218
+ * @deprecated The number of milliseconds to wait before initiating keepAlive on the TCP socket.
219
+ * Will not be configurable in the future.
220
+ */
217
221
  keepAliveInitialDelay?: number;
218
222
  /** Force server to assign `_id` values instead of driver */
219
223
  forceServerObjectId?: boolean;
@@ -363,6 +367,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
363
367
  };
364
368
  }
365
369
 
370
+ /** @see MongoOptions */
366
371
  get options(): Readonly<MongoOptions> {
367
372
  return Object.freeze({ ...this[kOptions] });
368
373
  }
@@ -660,7 +665,22 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
660
665
  }
661
666
 
662
667
  /**
663
- * Mongo Client Options
668
+ * Parsed Mongo Client Options.
669
+ *
670
+ * User supplied options are documented by `MongoClientOptions`.
671
+ *
672
+ * **NOTE:** The client's options parsing is subject to change to support new features.
673
+ * This type is provided to aid with inspection of options after parsing, it should not be relied upon programmatically.
674
+ *
675
+ * Options are sourced from:
676
+ * - connection string
677
+ * - options object passed to the MongoClient constructor
678
+ * - file system (ex. tls settings)
679
+ * - environment variables
680
+ * - DNS SRV records and TXT records
681
+ *
682
+ * Not all options may be present after client construction as some are obtained from asynchronous operations.
683
+ *
664
684
  * @public
665
685
  */
666
686
  export interface MongoOptions
@@ -717,6 +737,7 @@ export interface MongoOptions
717
737
  proxyPort?: number;
718
738
  proxyUsername?: string;
719
739
  proxyPassword?: string;
740
+
720
741
  /** @internal */
721
742
  connectionType?: typeof Connection;
722
743