mongodb 5.4.0 → 5.6.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 (81) hide show
  1. package/lib/admin.js +5 -5
  2. package/lib/admin.js.map +1 -1
  3. package/lib/bulk/common.js +4 -4
  4. package/lib/bulk/common.js.map +1 -1
  5. package/lib/change_stream.js +2 -2
  6. package/lib/change_stream.js.map +1 -1
  7. package/lib/cmap/connection_pool.js +21 -17
  8. package/lib/cmap/connection_pool.js.map +1 -1
  9. package/lib/cmap/handshake/client_metadata.js +1 -1
  10. package/lib/cmap/handshake/client_metadata.js.map +1 -1
  11. package/lib/cmap/wire_protocol/constants.js +3 -1
  12. package/lib/cmap/wire_protocol/constants.js.map +1 -1
  13. package/lib/collection.js +108 -33
  14. package/lib/collection.js.map +1 -1
  15. package/lib/cursor/list_collections_cursor.js +2 -2
  16. package/lib/cursor/list_collections_cursor.js.map +1 -1
  17. package/lib/cursor/list_indexes_cursor.js +2 -2
  18. package/lib/cursor/list_indexes_cursor.js.map +1 -1
  19. package/lib/cursor/list_search_indexes_cursor.js +14 -0
  20. package/lib/cursor/list_search_indexes_cursor.js.map +1 -0
  21. package/lib/cursor/run_command_cursor.js +94 -0
  22. package/lib/cursor/run_command_cursor.js.map +1 -0
  23. package/lib/db.js +29 -17
  24. package/lib/db.js.map +1 -1
  25. package/lib/error.js +16 -4
  26. package/lib/error.js.map +1 -1
  27. package/lib/index.js.map +1 -1
  28. package/lib/mongo_client.js +5 -7
  29. package/lib/mongo_client.js.map +1 -1
  30. package/lib/mongo_types.js +6 -1
  31. package/lib/mongo_types.js.map +1 -1
  32. package/lib/operations/create_collection.js +10 -3
  33. package/lib/operations/create_collection.js.map +1 -1
  34. package/lib/operations/drop.js +2 -3
  35. package/lib/operations/drop.js.map +1 -1
  36. package/lib/operations/search_indexes/create.js +29 -0
  37. package/lib/operations/search_indexes/create.js.map +1 -0
  38. package/lib/operations/search_indexes/drop.js +30 -0
  39. package/lib/operations/search_indexes/drop.js.map +1 -0
  40. package/lib/operations/search_indexes/update.js +30 -0
  41. package/lib/operations/search_indexes/update.js.map +1 -0
  42. package/lib/sdam/monitor.js +1 -1
  43. package/lib/sdam/monitor.js.map +1 -1
  44. package/lib/sdam/server.js +31 -19
  45. package/lib/sdam/server.js.map +1 -1
  46. package/lib/sdam/topology.js +4 -3
  47. package/lib/sdam/topology.js.map +1 -1
  48. package/lib/sessions.js +2 -2
  49. package/lib/sessions.js.map +1 -1
  50. package/lib/utils.js +19 -7
  51. package/lib/utils.js.map +1 -1
  52. package/mongodb.d.ts +112 -16
  53. package/package.json +17 -17
  54. package/src/admin.ts +5 -5
  55. package/src/bulk/common.ts +4 -4
  56. package/src/change_stream.ts +2 -2
  57. package/src/cmap/connection_pool.ts +26 -18
  58. package/src/cmap/handshake/client_metadata.ts +2 -1
  59. package/src/cmap/wire_protocol/constants.ts +2 -0
  60. package/src/collection.ts +163 -41
  61. package/src/cursor/abstract_cursor.ts +1 -1
  62. package/src/cursor/list_collections_cursor.ts +2 -2
  63. package/src/cursor/list_indexes_cursor.ts +2 -2
  64. package/src/cursor/list_search_indexes_cursor.ts +20 -0
  65. package/src/cursor/run_command_cursor.ts +140 -0
  66. package/src/db.ts +34 -21
  67. package/src/deps.ts +2 -2
  68. package/src/error.ts +20 -3
  69. package/src/index.ts +9 -0
  70. package/src/mongo_client.ts +25 -17
  71. package/src/mongo_types.ts +16 -2
  72. package/src/operations/create_collection.ts +19 -5
  73. package/src/operations/drop.ts +2 -3
  74. package/src/operations/search_indexes/create.ts +48 -0
  75. package/src/operations/search_indexes/drop.ts +35 -0
  76. package/src/operations/search_indexes/update.ts +36 -0
  77. package/src/sdam/monitor.ts +1 -1
  78. package/src/sdam/server.ts +38 -23
  79. package/src/sdam/topology.ts +8 -3
  80. package/src/sessions.ts +2 -2
  81. package/src/utils.ts +18 -10
@@ -0,0 +1,48 @@
1
+ import type { Document } from 'bson';
2
+
3
+ import type { Collection } from '../../collection';
4
+ import type { Server } from '../../sdam/server';
5
+ import type { ClientSession } from '../../sessions';
6
+ import type { Callback } from '../../utils';
7
+ import { AbstractOperation } from '../operation';
8
+
9
+ /** @internal */
10
+ export interface SearchIndexDescription {
11
+ /** The name of the index. */
12
+ name?: string;
13
+
14
+ /** The index definition. */
15
+ description: Document;
16
+ }
17
+
18
+ /** @internal */
19
+ export class CreateSearchIndexesOperation extends AbstractOperation<string[]> {
20
+ constructor(
21
+ private readonly collection: Collection,
22
+ private readonly descriptions: ReadonlyArray<SearchIndexDescription>
23
+ ) {
24
+ super();
25
+ }
26
+
27
+ execute(server: Server, session: ClientSession | undefined, callback: Callback<string[]>): void {
28
+ const namespace = this.collection.fullNamespace;
29
+ const command = {
30
+ createSearchIndexes: namespace.collection,
31
+ indexes: this.descriptions
32
+ };
33
+
34
+ server.command(namespace, command, { session }, (err, res) => {
35
+ if (err || !res) {
36
+ callback(err);
37
+ return;
38
+ }
39
+
40
+ const indexesCreated: Array<{ name: string }> = res?.indexesCreated ?? [];
41
+
42
+ callback(
43
+ undefined,
44
+ indexesCreated.map(({ name }) => name)
45
+ );
46
+ });
47
+ }
48
+ }
@@ -0,0 +1,35 @@
1
+ import type { Document } from 'bson';
2
+
3
+ import type { Collection } from '../../collection';
4
+ import type { Server } from '../../sdam/server';
5
+ import type { ClientSession } from '../../sessions';
6
+ import type { Callback } from '../../utils';
7
+ import { AbstractOperation } from '../operation';
8
+
9
+ /** @internal */
10
+ export class DropSearchIndexOperation extends AbstractOperation<void> {
11
+ constructor(private readonly collection: Collection, private readonly name: string) {
12
+ super();
13
+ }
14
+
15
+ execute(server: Server, session: ClientSession | undefined, callback: Callback<void>): void {
16
+ const namespace = this.collection.fullNamespace;
17
+
18
+ const command: Document = {
19
+ dropSearchIndex: namespace.collection
20
+ };
21
+
22
+ if (typeof this.name === 'string') {
23
+ command.name = this.name;
24
+ }
25
+
26
+ server.command(namespace, command, { session }, err => {
27
+ if (err) {
28
+ callback(err);
29
+ return;
30
+ }
31
+
32
+ callback();
33
+ });
34
+ }
35
+ }
@@ -0,0 +1,36 @@
1
+ import type { Document } from 'bson';
2
+
3
+ import type { Collection } from '../../collection';
4
+ import type { Server } from '../../sdam/server';
5
+ import type { ClientSession } from '../../sessions';
6
+ import type { Callback } from '../../utils';
7
+ import { AbstractOperation } from '../operation';
8
+
9
+ /** @internal */
10
+ export class UpdateSearchIndexOperation extends AbstractOperation<void> {
11
+ constructor(
12
+ private readonly collection: Collection,
13
+ private readonly name: string,
14
+ private readonly definition: Document
15
+ ) {
16
+ super();
17
+ }
18
+
19
+ execute(server: Server, session: ClientSession | undefined, callback: Callback<void>): void {
20
+ const namespace = this.collection.fullNamespace;
21
+ const command = {
22
+ updateSearchIndex: namespace.collection,
23
+ name: this.name,
24
+ definition: this.definition
25
+ };
26
+
27
+ server.command(namespace, command, { session }, err => {
28
+ if (err) {
29
+ callback(err);
30
+ return;
31
+ }
32
+
33
+ callback();
34
+ });
35
+ }
36
+ }
@@ -111,7 +111,7 @@ export class Monitor extends TypedEventEmitter<MonitorEvents> {
111
111
  const connectOptions = Object.assign(
112
112
  {
113
113
  id: '<monitor>' as const,
114
- generation: server.s.pool.generation,
114
+ generation: server.pool.generation,
115
115
  connectionType: Connection,
116
116
  cancellationToken,
117
117
  hostAddress: server.description.hostAddress
@@ -87,10 +87,6 @@ export interface ServerPrivate {
87
87
  options: ServerOptions;
88
88
  /** The current state of the Server */
89
89
  state: string;
90
- /** The topology this server is a part of */
91
- topology: Topology;
92
- /** A connection pool for this server */
93
- pool: ConnectionPool;
94
90
  /** MongoDB server API version */
95
91
  serverApi?: ServerApi;
96
92
  /** A count of the operations currently running against the server. */
@@ -114,6 +110,10 @@ export type ServerEvents = {
114
110
  export class Server extends TypedEventEmitter<ServerEvents> {
115
111
  /** @internal */
116
112
  s: ServerPrivate;
113
+ /** @internal */
114
+ topology: Topology;
115
+ /** @internal */
116
+ pool: ConnectionPool;
117
117
  serverApi?: ServerApi;
118
118
  hello?: Document;
119
119
  [kMonitor]: Monitor | null;
@@ -143,20 +143,21 @@ export class Server extends TypedEventEmitter<ServerEvents> {
143
143
 
144
144
  const poolOptions = { hostAddress: description.hostAddress, ...options };
145
145
 
146
+ this.topology = topology;
147
+ this.pool = new ConnectionPool(this, poolOptions);
148
+
146
149
  this.s = {
147
150
  description,
148
151
  options,
149
152
  state: STATE_CLOSED,
150
- topology,
151
- pool: new ConnectionPool(this, poolOptions),
152
153
  operationCount: 0
153
154
  };
154
155
 
155
156
  for (const event of [...CMAP_EVENTS, ...APM_EVENTS]) {
156
- this.s.pool.on(event, (e: any) => this.emit(event, e));
157
+ this.pool.on(event, (e: any) => this.emit(event, e));
157
158
  }
158
159
 
159
- this.s.pool.on(Connection.CLUSTER_TIME_RECEIVED, (clusterTime: ClusterTime) => {
160
+ this.pool.on(Connection.CLUSTER_TIME_RECEIVED, (clusterTime: ClusterTime) => {
160
161
  this.clusterTime = clusterTime;
161
162
  });
162
163
 
@@ -192,11 +193,11 @@ export class Server extends TypedEventEmitter<ServerEvents> {
192
193
  }
193
194
 
194
195
  get clusterTime(): ClusterTime | undefined {
195
- return this.s.topology.clusterTime;
196
+ return this.topology.clusterTime;
196
197
  }
197
198
 
198
199
  set clusterTime(clusterTime: ClusterTime | undefined) {
199
- this.s.topology.clusterTime = clusterTime;
200
+ this.topology.clusterTime = clusterTime;
200
201
  }
201
202
 
202
203
  get description(): ServerDescription {
@@ -215,7 +216,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
215
216
  }
216
217
 
217
218
  get loadBalanced(): boolean {
218
- return this.s.topology.description.type === TopologyType.LoadBalanced;
219
+ return this.topology.description.type === TopologyType.LoadBalanced;
219
220
  }
220
221
 
221
222
  /**
@@ -261,7 +262,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
261
262
  this[kMonitor]?.close();
262
263
  }
263
264
 
264
- this.s.pool.close(options, err => {
265
+ this.pool.close(options, err => {
265
266
  stateTransition(this, STATE_CLOSED);
266
267
  this.emit('closed');
267
268
  if (typeof callback === 'function') {
@@ -330,7 +331,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
330
331
  // balanced code makes a recursive call). Instead, we increment the count after this
331
332
  // check.
332
333
  if (this.loadBalanced && session && conn == null && isPinnableCommand(cmd, session)) {
333
- this.s.pool.checkOut((err, checkedOut) => {
334
+ this.pool.checkOut((err, checkedOut) => {
334
335
  if (err || checkedOut == null) {
335
336
  if (callback) return callback(err);
336
337
  return;
@@ -342,13 +343,13 @@ export class Server extends TypedEventEmitter<ServerEvents> {
342
343
  return;
343
344
  }
344
345
 
345
- this.s.operationCount += 1;
346
+ this.incrementOperationCount();
346
347
 
347
- this.s.pool.withConnection(
348
+ this.pool.withConnection(
348
349
  conn,
349
350
  (err, conn, cb) => {
350
351
  if (err || !conn) {
351
- this.s.operationCount -= 1;
352
+ this.decrementOperationCount();
352
353
  if (!err) {
353
354
  return cb(new MongoRuntimeError('Failed to create connection without error'));
354
355
  }
@@ -363,7 +364,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
363
364
  cmd,
364
365
  finalOptions,
365
366
  makeOperationHandler(this, conn, cmd, finalOptions, (error, response) => {
366
- this.s.operationCount -= 1;
367
+ this.decrementOperationCount();
367
368
  cb(error, response);
368
369
  })
369
370
  );
@@ -382,7 +383,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
382
383
  }
383
384
 
384
385
  const isStaleError =
385
- error.connectionGeneration && error.connectionGeneration < this.s.pool.generation;
386
+ error.connectionGeneration && error.connectionGeneration < this.pool.generation;
386
387
  if (isStaleError) {
387
388
  return;
388
389
  }
@@ -398,14 +399,14 @@ export class Server extends TypedEventEmitter<ServerEvents> {
398
399
  error.addErrorLabel(MongoErrorLabel.ResetPool);
399
400
  markServerUnknown(this, error);
400
401
  } else if (connection) {
401
- this.s.pool.clear({ serviceId: connection.serviceId });
402
+ this.pool.clear({ serviceId: connection.serviceId });
402
403
  }
403
404
  } else {
404
405
  if (isSDAMUnrecoverableError(error)) {
405
406
  if (shouldHandleStateChangeError(this, error)) {
406
407
  const shouldClearPool = maxWireVersion(this) <= 7 || isNodeShuttingDownError(error);
407
408
  if (this.loadBalanced && connection && shouldClearPool) {
408
- this.s.pool.clear({ serviceId: connection.serviceId });
409
+ this.pool.clear({ serviceId: connection.serviceId });
409
410
  }
410
411
 
411
412
  if (!this.loadBalanced) {
@@ -419,6 +420,20 @@ export class Server extends TypedEventEmitter<ServerEvents> {
419
420
  }
420
421
  }
421
422
  }
423
+
424
+ /**
425
+ * Decrement the operation count, returning the new count.
426
+ */
427
+ private decrementOperationCount(): number {
428
+ return (this.s.operationCount -= 1);
429
+ }
430
+
431
+ /**
432
+ * Increment the operation count, returning the new count.
433
+ */
434
+ private incrementOperationCount(): number {
435
+ return (this.s.operationCount += 1);
436
+ }
422
437
  }
423
438
 
424
439
  function calculateRoundTripTime(oldRtt: number, duration: number): number {
@@ -514,7 +529,7 @@ function makeOperationHandler(
514
529
  return callback(error);
515
530
  }
516
531
 
517
- if (connectionIsStale(server.s.pool, connection)) {
532
+ if (connectionIsStale(server.pool, connection)) {
518
533
  return callback(error);
519
534
  }
520
535
 
@@ -532,7 +547,7 @@ function makeOperationHandler(
532
547
  }
533
548
 
534
549
  if (
535
- (isRetryableWritesEnabled(server.s.topology) || isTransactionCommand(cmd)) &&
550
+ (isRetryableWritesEnabled(server.topology) || isTransactionCommand(cmd)) &&
536
551
  supportsRetryableWrites(server) &&
537
552
  !inActiveTransaction(session, cmd)
538
553
  ) {
@@ -540,7 +555,7 @@ function makeOperationHandler(
540
555
  }
541
556
  } else {
542
557
  if (
543
- (isRetryableWritesEnabled(server.s.topology) || isTransactionCommand(cmd)) &&
558
+ (isRetryableWritesEnabled(server.topology) || isTransactionCommand(cmd)) &&
544
559
  needsRetryableWriteLabel(error, maxWireVersion(server)) &&
545
560
  !inActiveTransaction(session, cmd)
546
561
  ) {
@@ -227,9 +227,14 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
227
227
  /**
228
228
  * @param seedlist - a list of HostAddress instances to connect to
229
229
  */
230
- constructor(seeds: string | string[] | HostAddress | HostAddress[], options: TopologyOptions) {
230
+ constructor(
231
+ client: MongoClient,
232
+ seeds: string | string[] | HostAddress | HostAddress[],
233
+ options: TopologyOptions
234
+ ) {
231
235
  super();
232
236
 
237
+ this.client = client;
233
238
  this.selectServerAsync = promisify(
234
239
  (
235
240
  selector: string | ReadPreference | ServerSelector,
@@ -787,7 +792,7 @@ function updateServers(topology: Topology, incomingServerDescription?: ServerDes
787
792
  MongoErrorLabel.InterruptInUseConnections
788
793
  );
789
794
 
790
- server.s.pool.clear({ interruptInUseConnections });
795
+ server.pool.clear({ interruptInUseConnections });
791
796
  } else if (incomingServerDescription.error == null) {
792
797
  const newTopologyType = topology.s.description.type;
793
798
  const shouldMarkPoolReady =
@@ -795,7 +800,7 @@ function updateServers(topology: Topology, incomingServerDescription?: ServerDes
795
800
  (incomingServerDescription.type !== ServerType.Unknown &&
796
801
  newTopologyType === TopologyType.Single);
797
802
  if (shouldMarkPoolReady) {
798
- server.s.pool.ready();
803
+ server.pool.ready();
799
804
  }
800
805
  }
801
806
  }
package/src/sessions.ts CHANGED
@@ -505,7 +505,7 @@ export function maybeClearPinnedConnection(
505
505
  const loadBalancer = servers[0];
506
506
 
507
507
  if (options?.error == null || options?.force) {
508
- loadBalancer.s.pool.checkIn(conn);
508
+ loadBalancer.pool.checkIn(conn);
509
509
  conn.emit(
510
510
  UNPINNED,
511
511
  session.transaction.state !== TxnState.NO_TRANSACTION
@@ -514,7 +514,7 @@ export function maybeClearPinnedConnection(
514
514
  );
515
515
 
516
516
  if (options?.forceClear) {
517
- loadBalancer.s.pool.clear({ serviceId: conn.serviceId });
517
+ loadBalancer.pool.clear({ serviceId: conn.serviceId });
518
518
  }
519
519
  }
520
520
 
package/src/utils.ts CHANGED
@@ -288,10 +288,8 @@ export function getTopology(provider: TopologyProvider): Topology {
288
288
  // MongoClient or ClientSession or AbstractCursor
289
289
  if ('topology' in provider && provider.topology) {
290
290
  return provider.topology;
291
- } else if ('s' in provider && 'client' in provider.s && provider.s.client.topology) {
292
- return provider.s.client.topology;
293
- } else if ('s' in provider && 'db' in provider.s && provider.s.db.s.client.topology) {
294
- return provider.s.db.s.client.topology;
291
+ } else if ('client' in provider && provider.client.topology) {
292
+ return provider.client.topology;
295
293
  }
296
294
 
297
295
  throw new MongoNotConnectedError('MongoClient must be connected to perform this operation');
@@ -304,16 +302,13 @@ export function ns(ns: string): MongoDBNamespace {
304
302
 
305
303
  /** @public */
306
304
  export class MongoDBNamespace {
307
- db: string;
308
- collection: string | undefined;
309
305
  /**
310
306
  * Create a namespace object
311
307
  *
312
308
  * @param db - database name
313
309
  * @param collection - collection name
314
310
  */
315
- constructor(db: string, collection?: string) {
316
- this.db = db;
311
+ constructor(public db: string, public collection?: string) {
317
312
  this.collection = collection === '' ? undefined : collection;
318
313
  }
319
314
 
@@ -321,8 +316,8 @@ export class MongoDBNamespace {
321
316
  return this.collection ? `${this.db}.${this.collection}` : this.db;
322
317
  }
323
318
 
324
- withCollection(collection: string): MongoDBNamespace {
325
- return new MongoDBNamespace(this.db, collection);
319
+ withCollection(collection: string): MongoDBCollectionNamespace {
320
+ return new MongoDBCollectionNamespace(this.db, collection);
326
321
  }
327
322
 
328
323
  static fromString(namespace?: string): MongoDBNamespace {
@@ -337,6 +332,19 @@ export class MongoDBNamespace {
337
332
  }
338
333
  }
339
334
 
335
+ /**
336
+ * @public
337
+ *
338
+ * A class representing a collection's namespace. This class enforces (through Typescript) that
339
+ * the `collection` portion of the namespace is defined and should only be
340
+ * used in scenarios where this can be guaranteed.
341
+ */
342
+ export class MongoDBCollectionNamespace extends MongoDBNamespace {
343
+ constructor(db: string, override collection: string) {
344
+ super(db, collection);
345
+ }
346
+ }
347
+
340
348
  /** @internal */
341
349
  export function* makeCounter(seed = 0): Generator<number> {
342
350
  let count = seed;