mongodb 7.7.0 → 7.8.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 (90) hide show
  1. package/README.md +1 -1
  2. package/lib/bulk/unordered.js +1 -1
  3. package/lib/bulk/unordered.js.map +1 -1
  4. package/lib/change_stream.js +3 -11
  5. package/lib/change_stream.js.map +1 -1
  6. package/lib/client-side-encryption/client_encryption.js.map +1 -1
  7. package/lib/cmap/wire_protocol/compression.js +2 -0
  8. package/lib/cmap/wire_protocol/compression.js.map +1 -1
  9. package/lib/collection.js +18 -119
  10. package/lib/collection.js.map +1 -1
  11. package/lib/connection_string.js +110 -15
  12. package/lib/connection_string.js.map +1 -1
  13. package/lib/cursor/abstract_cursor.js +9 -62
  14. package/lib/cursor/abstract_cursor.js.map +1 -1
  15. package/lib/cursor/aggregation_cursor.js +0 -9
  16. package/lib/cursor/aggregation_cursor.js.map +1 -1
  17. package/lib/cursor/find_cursor.js +0 -9
  18. package/lib/cursor/find_cursor.js.map +1 -1
  19. package/lib/cursor/list_collections_cursor.js +1 -1
  20. package/lib/cursor/list_collections_cursor.js.map +1 -1
  21. package/lib/cursor/list_indexes_cursor.js +1 -1
  22. package/lib/cursor/list_indexes_cursor.js.map +1 -1
  23. package/lib/cursor/run_command_cursor.js.map +1 -1
  24. package/lib/db.js +5 -58
  25. package/lib/db.js.map +1 -1
  26. package/lib/deps.js +35 -1
  27. package/lib/deps.js.map +1 -1
  28. package/lib/explain.js +0 -8
  29. package/lib/explain.js.map +1 -1
  30. package/lib/gridfs/download.js +3 -11
  31. package/lib/gridfs/download.js.map +1 -1
  32. package/lib/gridfs/index.js +4 -4
  33. package/lib/gridfs/index.js.map +1 -1
  34. package/lib/gridfs/upload.js +3 -18
  35. package/lib/gridfs/upload.js.map +1 -1
  36. package/lib/mongo_client.js +2 -60
  37. package/lib/mongo_client.js.map +1 -1
  38. package/lib/operations/command.js +0 -2
  39. package/lib/operations/command.js.map +1 -1
  40. package/lib/operations/create_collection.js +1 -1
  41. package/lib/operations/create_collection.js.map +1 -1
  42. package/lib/operations/indexes.js +45 -16
  43. package/lib/operations/indexes.js.map +1 -1
  44. package/lib/sdam/srv_polling.js +7 -2
  45. package/lib/sdam/srv_polling.js.map +1 -1
  46. package/lib/sdam/topology.js +3 -1
  47. package/lib/sdam/topology.js.map +1 -1
  48. package/lib/sessions.js +10 -47
  49. package/lib/sessions.js.map +1 -1
  50. package/lib/sort.js +1 -1
  51. package/lib/sort.js.map +1 -1
  52. package/lib/timeout.js +2 -11
  53. package/lib/timeout.js.map +1 -1
  54. package/lib/utils.js +84 -23
  55. package/lib/utils.js.map +1 -1
  56. package/mongodb.d.ts +249 -314
  57. package/package.json +1 -1
  58. package/src/bulk/unordered.ts +1 -1
  59. package/src/change_stream.ts +4 -12
  60. package/src/client-side-encryption/client_encryption.ts +5 -32
  61. package/src/client-side-encryption/kms_options.ts +1 -0
  62. package/src/cmap/wire_protocol/compression.ts +3 -1
  63. package/src/collection.ts +83 -71
  64. package/src/connection_string.ts +135 -19
  65. package/src/cursor/abstract_cursor.ts +20 -97
  66. package/src/cursor/aggregation_cursor.ts +1 -16
  67. package/src/cursor/find_cursor.ts +2 -17
  68. package/src/cursor/list_collections_cursor.ts +1 -1
  69. package/src/cursor/list_indexes_cursor.ts +1 -1
  70. package/src/cursor/run_command_cursor.ts +4 -31
  71. package/src/db.ts +13 -59
  72. package/src/deps.ts +38 -1
  73. package/src/explain.ts +0 -8
  74. package/src/gridfs/download.ts +7 -14
  75. package/src/gridfs/index.ts +27 -8
  76. package/src/gridfs/upload.ts +6 -21
  77. package/src/index.ts +2 -0
  78. package/src/mongo_client.ts +46 -61
  79. package/src/operations/command.ts +1 -7
  80. package/src/operations/create_collection.ts +4 -2
  81. package/src/operations/drop.ts +1 -1
  82. package/src/operations/indexes.ts +213 -17
  83. package/src/operations/operation.ts +1 -1
  84. package/src/operations/run_command.ts +1 -1
  85. package/src/sdam/srv_polling.ts +12 -3
  86. package/src/sdam/topology.ts +5 -1
  87. package/src/sessions.ts +21 -63
  88. package/src/sort.ts +1 -1
  89. package/src/timeout.ts +2 -13
  90. package/src/utils.ts +96 -30
@@ -67,32 +67,8 @@ function removeActiveCursor(this: AbstractCursor) {
67
67
 
68
68
  /**
69
69
  * @public
70
- * @experimental
71
- * Specifies how `timeoutMS` is applied to the cursor. Can be either `'cursorLifeTime'` or `'iteration'`
72
- * When set to `'iteration'`, the deadline specified by `timeoutMS` applies to each call of
73
- * `cursor.next()`.
74
- * When set to `'cursorLifetime'`, the deadline applies to the life of the entire cursor.
75
- *
76
- * Depending on the type of cursor being used, this option has different default values.
77
- * For non-tailable cursors, this value defaults to `'cursorLifetime'`
78
- * For tailable cursors, this value defaults to `'iteration'` since tailable cursors, by
79
- * definition can have an arbitrarily long lifetime.
80
- *
81
- * @example
82
- * ```ts
83
- * const cursor = collection.find({}, {timeoutMS: 100, timeoutMode: 'iteration'});
84
- * for await (const doc of cursor) {
85
- * // process doc
86
- * // This will throw a timeout error if any of the iterator's `next()` calls takes more than 100ms, but
87
- * // will continue to iterate successfully otherwise, regardless of the number of batches.
88
- * }
89
- * ```
90
- *
91
- * @example
92
- * ```ts
93
- * const cursor = collection.find({}, { timeoutMS: 1000, timeoutMode: 'cursorLifetime' });
94
- * const docs = await cursor.toArray(); // This entire line will throw a timeout error if all batches are not fetched and returned within 1000ms.
95
- * ```
70
+ * Specifies how `timeoutMS` is applied to the cursor.
71
+ * @deprecated `timeoutMode` has no effect and will be removed in a future release.
96
72
  */
97
73
  export const CursorTimeoutMode = Object.freeze({
98
74
  ITERATION: 'iteration',
@@ -101,7 +77,7 @@ export const CursorTimeoutMode = Object.freeze({
101
77
 
102
78
  /**
103
79
  * @public
104
- * @experimental
80
+ * @deprecated `timeoutMode` has no effect and will be removed in a future release.
105
81
  */
106
82
  export type CursorTimeoutMode = (typeof CursorTimeoutMode)[keyof typeof CursorTimeoutMode];
107
83
 
@@ -143,36 +119,14 @@ export interface AbstractCursorOptions extends BSONSerializeOptions {
143
119
  */
144
120
  awaitData?: boolean;
145
121
  noCursorTimeout?: boolean;
146
- /** Specifies the time an operation will run until it throws a timeout error. See {@link AbstractCursorOptions.timeoutMode} for more details on how this option applies to cursors. */
122
+ /**
123
+ * Specifies the time an operation will run until it throws a timeout error.
124
+ * @deprecated `timeoutMS` has no effect and will be removed in a future release.
125
+ */
147
126
  timeoutMS?: number;
148
127
  /**
149
- * @public
150
- * @experimental
151
- * Specifies how `timeoutMS` is applied to the cursor. Can be either `'cursorLifeTime'` or `'iteration'`
152
- * When set to `'iteration'`, the deadline specified by `timeoutMS` applies to each call of
153
- * `cursor.next()`.
154
- * When set to `'cursorLifetime'`, the deadline applies to the life of the entire cursor.
155
- *
156
- * Depending on the type of cursor being used, this option has different default values.
157
- * For non-tailable cursors, this value defaults to `'cursorLifetime'`
158
- * For tailable cursors, this value defaults to `'iteration'` since tailable cursors, by
159
- * definition can have an arbitrarily long lifetime.
160
- *
161
- * @example
162
- * ```ts
163
- * const cursor = collection.find({}, {timeoutMS: 100, timeoutMode: 'iteration'});
164
- * for await (const doc of cursor) {
165
- * // process doc
166
- * // This will throw a timeout error if any of the iterator's `next()` calls takes more than 100ms, but
167
- * // will continue to iterate successfully otherwise, regardless of the number of batches.
168
- * }
169
- * ```
170
- *
171
- * @example
172
- * ```ts
173
- * const cursor = collection.find({}, { timeoutMS: 1000, timeoutMode: 'cursorLifetime' });
174
- * const docs = await cursor.toArray(); // This entire line will throw a timeout error if all batches are not fetched and returned within 1000ms.
175
- * ```
128
+ * Specifies how `timeoutMS` is applied to the cursor.
129
+ * @deprecated `timeoutMode` has no effect and will be removed in a future release.
176
130
  */
177
131
  timeoutMode?: CursorTimeoutMode;
178
132
 
@@ -258,6 +212,10 @@ export abstract class AbstractCursor<
258
212
  super();
259
213
  this.on('error', noop);
260
214
 
215
+ // timeoutMS and timeoutMode are no-ops, so they must never reach the operations built from these options
216
+ options.timeoutMS = undefined;
217
+ options.timeoutMode = undefined;
218
+
261
219
  if (!client.s.isMongoClient) {
262
220
  throw new MongoRuntimeError('Cursor must be constructed with MongoClient');
263
221
  }
@@ -273,50 +231,10 @@ export abstract class AbstractCursor<
273
231
  ? options.readPreference
274
232
  : ReadPreference.primary,
275
233
  ...pluckBSONSerializeOptions(options),
276
- timeoutMS: options?.timeoutContext?.csotEnabled()
277
- ? options.timeoutContext.timeoutMS
278
- : options.timeoutMS,
279
234
  tailable: options.tailable,
280
235
  awaitData: options.awaitData
281
236
  };
282
237
 
283
- if (this.cursorOptions.timeoutMS != null) {
284
- if (options.timeoutMode == null) {
285
- if (options.tailable) {
286
- if (options.awaitData) {
287
- if (
288
- options.maxAwaitTimeMS != null &&
289
- options.maxAwaitTimeMS >= this.cursorOptions.timeoutMS
290
- )
291
- throw new MongoInvalidArgumentError(
292
- 'Cannot specify maxAwaitTimeMS >= timeoutMS for a tailable awaitData cursor'
293
- );
294
- }
295
-
296
- this.cursorOptions.timeoutMode = CursorTimeoutMode.ITERATION;
297
- } else {
298
- this.cursorOptions.timeoutMode = CursorTimeoutMode.LIFETIME;
299
- }
300
- } else {
301
- if (options.tailable && options.timeoutMode === CursorTimeoutMode.LIFETIME) {
302
- throw new MongoInvalidArgumentError(
303
- "Cannot set tailable cursor's timeoutMode to LIFETIME"
304
- );
305
- }
306
- this.cursorOptions.timeoutMode = options.timeoutMode;
307
- }
308
- } else {
309
- if (options.timeoutMode != null)
310
- throw new MongoInvalidArgumentError('Cannot set timeoutMode without setting timeoutMS');
311
- }
312
-
313
- // Set for initial command
314
- this.cursorOptions.omitMaxTimeMS =
315
- this.cursorOptions.timeoutMS != null &&
316
- ((this.cursorOptions.timeoutMode === CursorTimeoutMode.ITERATION &&
317
- !this.cursorOptions.tailable) ||
318
- (this.cursorOptions.tailable && !this.cursorOptions.awaitData));
319
-
320
238
  const readConcern = ReadConcern.fromOptions(options);
321
239
  if (readConcern) {
322
240
  this.cursorOptions.readConcern = readConcern;
@@ -635,9 +553,14 @@ export abstract class AbstractCursor<
635
553
 
636
554
  /**
637
555
  * Frees any client-side resources used by the cursor.
556
+ *
557
+ * @param _options - `timeoutMS` is deprecated and has no effect
638
558
  */
639
- async close(options?: { timeoutMS?: number }): Promise<void> {
640
- await this.cleanup(options?.timeoutMS);
559
+ async close(_options?: {
560
+ /** @deprecated `timeoutMS` has no effect and will be removed in a future release. */
561
+ timeoutMS?: number;
562
+ }): Promise<void> {
563
+ await this.cleanup();
641
564
  }
642
565
 
643
566
  /**
@@ -1,11 +1,6 @@
1
1
  import type { Document } from '../bson';
2
2
  import { MongoAPIError } from '../error';
3
- import {
4
- Explain,
5
- type ExplainCommandOptions,
6
- type ExplainVerbosityLike,
7
- validateExplainTimeoutOptions
8
- } from '../explain';
3
+ import { type ExplainCommandOptions, type ExplainVerbosityLike } from '../explain';
9
4
  import type { MongoClient } from '../mongo_client';
10
5
  import { type Abortable } from '../mongo_types';
11
6
  import { AggregateOperation, type AggregateOptions } from '../operations/aggregate';
@@ -77,16 +72,6 @@ export class AggregationCursor<TSchema = any> extends ExplainableCursor<TSchema>
77
72
  session,
78
73
  signal: this.signal
79
74
  };
80
- if (options.explain) {
81
- try {
82
- validateExplainTimeoutOptions(options, Explain.fromOptions(options));
83
- } catch {
84
- throw new MongoAPIError(
85
- 'timeoutMS cannot be used with explain when explain is specified in aggregateOptions'
86
- );
87
- }
88
- }
89
-
90
75
  const aggregateOperation = new AggregateOperation(this.namespace, this.pipeline, options);
91
76
 
92
77
  const response = await executeOperation(this.client, aggregateOperation, this.timeoutContext);
@@ -1,12 +1,7 @@
1
1
  import { type Document } from '../bson';
2
2
  import { CursorResponse } from '../cmap/wire_protocol/responses';
3
- import { MongoAPIError, MongoInvalidArgumentError, MongoTailableCursorError } from '../error';
4
- import {
5
- Explain,
6
- type ExplainCommandOptions,
7
- type ExplainVerbosityLike,
8
- validateExplainTimeoutOptions
9
- } from '../explain';
3
+ import { MongoInvalidArgumentError, MongoTailableCursorError } from '../error';
4
+ import { type ExplainCommandOptions, type ExplainVerbosityLike } from '../explain';
10
5
  import type { MongoClient } from '../mongo_client';
11
6
  import { type Abortable } from '../mongo_types';
12
7
  import type { CollationOptions } from '../operations/command';
@@ -77,16 +72,6 @@ export class FindCursor<TSchema = any> extends ExplainableCursor<TSchema> {
77
72
  signal: this.signal
78
73
  };
79
74
 
80
- if (options.explain) {
81
- try {
82
- validateExplainTimeoutOptions(options, Explain.fromOptions(options));
83
- } catch {
84
- throw new MongoAPIError(
85
- 'timeoutMS cannot be used with explain when explain is specified in findOptions'
86
- );
87
- }
88
- }
89
-
90
75
  const findOperation = new FindOperation(this.namespace, this.cursorFilter, options);
91
76
 
92
77
  const response = await executeOperation(this.client, findOperation, this.timeoutContext);
@@ -21,7 +21,7 @@ export class ListCollectionsCursor<
21
21
  options?: ListCollectionsOptions & Abortable;
22
22
 
23
23
  constructor(db: Db, filter: Document, options?: ListCollectionsOptions & Abortable) {
24
- super(db.client, db.s.namespace, options);
24
+ super(db.client, db.s.namespace, { ...options });
25
25
  this.parent = db;
26
26
  this.filter = filter;
27
27
  this.options = options;
@@ -10,7 +10,7 @@ export class ListIndexesCursor extends AbstractCursor {
10
10
  options?: ListIndexesOptions;
11
11
 
12
12
  constructor(collection: Collection, options?: ListIndexesOptions) {
13
- super(collection.client, collection.s.namespace, options);
13
+ super(collection.client, collection.s.namespace, { ...options });
14
14
  this.parent = collection;
15
15
  this.options = options;
16
16
  }
@@ -20,40 +20,13 @@ export type RunCursorCommandOptions = {
20
20
  readPreference?: ReadPreferenceLike;
21
21
  session?: ClientSession;
22
22
  /**
23
- * @experimental
24
- * Specifies the time an operation will run until it throws a timeout error. Note that if
25
- * `maxTimeMS` is provided in the command in addition to setting `timeoutMS` in the options, then
26
- * the original value of `maxTimeMS` will be overwritten.
23
+ * Specifies the time an operation will run until it throws a timeout error.
24
+ * @deprecated `timeoutMS` has no effect and will be removed in a future release.
27
25
  */
28
26
  timeoutMS?: number;
29
27
  /**
30
- * @public
31
- * @experimental
32
- * Specifies how `timeoutMS` is applied to the cursor. Can be either `'cursorLifeTime'` or `'iteration'`
33
- * When set to `'iteration'`, the deadline specified by `timeoutMS` applies to each call of
34
- * `cursor.next()`.
35
- * When set to `'cursorLifetime'`, the deadline applies to the life of the entire cursor.
36
- *
37
- * Depending on the type of cursor being used, this option has different default values.
38
- * For non-tailable cursors, this value defaults to `'cursorLifetime'`
39
- * For tailable cursors, this value defaults to `'iteration'` since tailable cursors, by
40
- * definition can have an arbitrarily long lifetime.
41
- *
42
- * @example
43
- * ```ts
44
- * const cursor = collection.find({}, {timeoutMS: 100, timeoutMode: 'iteration'});
45
- * for await (const doc of cursor) {
46
- * // process doc
47
- * // This will throw a timeout error if any of the iterator's `next()` calls takes more than 100ms, but
48
- * // will continue to iterate successfully otherwise, regardless of the number of batches.
49
- * }
50
- * ```
51
- *
52
- * @example
53
- * ```ts
54
- * const cursor = collection.find({}, { timeoutMS: 1000, timeoutMode: 'cursorLifetime' });
55
- * const docs = await cursor.toArray(); // This entire line will throw a timeout error if all batches are not fetched and returned within 1000ms.
56
- * ```
28
+ * Specifies how `timeoutMS` is applied to the cursor.
29
+ * @deprecated `timeoutMode` has no effect and will be removed in a future release.
57
30
  */
58
31
  timeoutMode?: CursorTimeoutMode;
59
32
  tailable?: boolean;
package/src/db.ts CHANGED
@@ -64,8 +64,7 @@ const DB_OPTIONS_ALLOW_LIST = [
64
64
  'enableUtf8Validation',
65
65
  'promoteValues',
66
66
  'compression',
67
- 'retryWrites',
68
- 'timeoutMS'
67
+ 'retryWrites'
69
68
  ];
70
69
 
71
70
  /** @internal */
@@ -94,8 +93,8 @@ export interface DbOptions extends BSONSerializeOptions, WriteConcernOptions {
94
93
  /** Should retry failed writes */
95
94
  retryWrites?: boolean;
96
95
  /**
97
- * @experimental
98
96
  * Specifies the time an operation will run until it throws a timeout error
97
+ * @deprecated `timeoutMS` has no effect and will be removed in a future release.
99
98
  */
100
99
  timeoutMS?: number;
101
100
  }
@@ -224,8 +223,9 @@ export class Db {
224
223
  return this.s.namespace.toString();
225
224
  }
226
225
 
226
+ /** @deprecated `timeoutMS` has no effect and will be removed in a future release. */
227
227
  public get timeoutMS(): number | undefined {
228
- return this.s.options?.timeoutMS;
228
+ return undefined;
229
229
  }
230
230
 
231
231
  /**
@@ -454,7 +454,14 @@ export class Db {
454
454
  ): Promise<string> {
455
455
  const indexes = await executeOperation(
456
456
  this.client,
457
- CreateIndexesOperation.fromIndexSpecification(this, name, indexSpec, options)
457
+ CreateIndexesOperation.fromIndexSpecification(
458
+ this,
459
+ name,
460
+ indexSpec,
461
+ false,
462
+ options ?? {},
463
+ undefined
464
+ )
458
465
  );
459
466
  return indexes[0];
460
467
  }
@@ -535,59 +542,6 @@ export class Db {
535
542
  * watch() accepts two generic arguments for distinct use cases:
536
543
  * - The first is to provide the schema that may be defined for all the collections within this database
537
544
  * - 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
538
- *
539
- * @remarks
540
- * When `timeoutMS` is configured for a change stream, it will have different behaviour depending
541
- * on whether the change stream is in iterator mode or emitter mode. In both cases, a change
542
- * stream will time out if it does not receive a change event within `timeoutMS` of the last change
543
- * event.
544
- *
545
- * Note that if a change stream is consistently timing out when watching a collection, database or
546
- * client that is being changed, then this may be due to the server timing out before it can finish
547
- * processing the existing oplog. To address this, restart the change stream with a higher
548
- * `timeoutMS`.
549
- *
550
- * If the change stream times out the initial aggregate operation to establish the change stream on
551
- * the server, then the client will close the change stream. If the getMore calls to the server
552
- * time out, then the change stream will be left open, but will throw a MongoOperationTimeoutError
553
- * when in iterator mode and emit an error event that returns a MongoOperationTimeoutError in
554
- * emitter mode.
555
- *
556
- * To determine whether or not the change stream is still open following a timeout, check the
557
- * {@link ChangeStream.closed} getter.
558
- *
559
- * @example
560
- * In iterator mode, if a next() call throws a timeout error, it will attempt to resume the change stream.
561
- * The next call can just be retried after this succeeds.
562
- * ```ts
563
- * const changeStream = collection.watch([], { timeoutMS: 100 });
564
- * try {
565
- * await changeStream.next();
566
- * } catch (e) {
567
- * if (e instanceof MongoOperationTimeoutError && !changeStream.closed) {
568
- * await changeStream.next();
569
- * }
570
- * throw e;
571
- * }
572
- * ```
573
- *
574
- * @example
575
- * In emitter mode, if the change stream goes `timeoutMS` without emitting a change event, it will
576
- * emit an error event that returns a MongoOperationTimeoutError, but will not close the change
577
- * stream unless the resume attempt fails. There is no need to re-establish change listeners as
578
- * this will automatically continue emitting change events once the resume attempt completes.
579
- *
580
- * ```ts
581
- * const changeStream = collection.watch([], { timeoutMS: 100 });
582
- * changeStream.on('change', console.log);
583
- * changeStream.on('error', e => {
584
- * if (e instanceof MongoOperationTimeoutError && !changeStream.closed) {
585
- * // do nothing
586
- * } else {
587
- * changeStream.close();
588
- * }
589
- * });
590
- * ```
591
545
  * @param pipeline - An array of {@link https://www.mongodb.com/docs/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.
592
546
  * @param options - Optional settings for the command
593
547
  * @typeParam TSchema - Type of the data being detected by the change stream
@@ -616,6 +570,6 @@ export class Db {
616
570
  * @param options - Configurations for running the command, bson options will apply to getMores
617
571
  */
618
572
  runCursorCommand(command: Document, options?: RunCursorCommandOptions): RunCommandCursor {
619
- return new RunCommandCursor(this, command, options);
573
+ return new RunCommandCursor(this, command, { ...options });
620
574
  }
621
575
  }
package/src/deps.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import * as zlib from 'zlib';
2
+
1
3
  import { type Stream } from './cmap/connect';
2
4
  import { MongoMissingDependencyError } from './error';
3
5
  import type { Callback } from './utils';
@@ -60,7 +62,42 @@ type ZStandardLib = {
60
62
 
61
63
  export type ZStandard = ZStandardLib | { kModuleError: MongoMissingDependencyError };
62
64
 
65
+ /**
66
+ * Returns Node.js' built-in zstd (available since Node.js 22.15.0), or null when unavailable.
67
+ */
68
+ function getBuiltInZstdLibrary(): ZStandardLib | null {
69
+ if (typeof zlib.zstdCompress !== 'function' || typeof zlib.zstdDecompress !== 'function') {
70
+ return null;
71
+ }
72
+
73
+ return {
74
+ compress(buf: Uint8Array, level?: number): Promise<Uint8Array> {
75
+ const options =
76
+ level == null ? {} : { params: { [zlib.constants.ZSTD_c_compressionLevel]: level } };
77
+ return new Promise((resolve, reject) => {
78
+ zlib.zstdCompress(buf, options, (error, result) => {
79
+ if (error) return reject(error);
80
+ resolve(result);
81
+ });
82
+ });
83
+ },
84
+ decompress(buf: Uint8Array): Promise<Uint8Array> {
85
+ return new Promise((resolve, reject) => {
86
+ zlib.zstdDecompress(buf, (error, result) => {
87
+ if (error) return reject(error);
88
+ resolve(result);
89
+ });
90
+ });
91
+ }
92
+ };
93
+ }
94
+
63
95
  export function getZstdLibrary(): ZStandardLib | { kModuleError: MongoMissingDependencyError } {
96
+ const builtInZstd = getBuiltInZstdLibrary();
97
+ if (builtInZstd != null) {
98
+ return builtInZstd;
99
+ }
100
+
64
101
  let ZStandard: ZStandardLib | { kModuleError: MongoMissingDependencyError };
65
102
  try {
66
103
  // eslint-disable-next-line @typescript-eslint/no-require-imports
@@ -68,7 +105,7 @@ export function getZstdLibrary(): ZStandardLib | { kModuleError: MongoMissingDep
68
105
  } catch (error) {
69
106
  ZStandard = makeErrorModule(
70
107
  new MongoMissingDependencyError(
71
- 'Optional module `@mongodb-js/zstd` not found. Please install it to enable zstd compression',
108
+ 'Built-in zstd is unavailable (requires Node.js 22.15.0 or later) and optional module `@mongodb-js/zstd` not found. Please upgrade Node.js or install `@mongodb-js/zstd` to enable zstd compression',
72
109
  { cause: error, dependencyName: 'zstd' }
73
110
  )
74
111
  );
package/src/explain.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { type Document } from './bson';
2
- import { MongoAPIError } from './error';
3
2
 
4
3
  /** @public */
5
4
  export const ExplainVerbosity = Object.freeze({
@@ -90,13 +89,6 @@ export class Explain {
90
89
  }
91
90
  }
92
91
 
93
- export function validateExplainTimeoutOptions(options: Document, explain?: Explain) {
94
- const { maxTimeMS, timeoutMS } = options;
95
- if (timeoutMS != null && (maxTimeMS != null || explain?.maxTimeMS != null)) {
96
- throw new MongoAPIError('Cannot use maxTimeMS with timeoutMS for explain commands.');
97
- }
98
- }
99
-
100
92
  /**
101
93
  * Applies an explain to a given command.
102
94
  * @internal
@@ -2,7 +2,6 @@ import { Readable } from 'stream';
2
2
 
3
3
  import { ByteUtils, type Document, type ObjectId } from '../bson';
4
4
  import type { Collection } from '../collection';
5
- import { CursorTimeoutMode } from '../cursor/abstract_cursor';
6
5
  import type { FindCursor } from '../cursor/find_cursor';
7
6
  import {
8
7
  MongoGridFSChunkError,
@@ -13,7 +12,7 @@ import {
13
12
  import type { FindOptions } from '../operations/find';
14
13
  import type { ReadPreference } from '../read_preference';
15
14
  import type { Sort } from '../sort';
16
- import { CSOTTimeoutContext } from '../timeout';
15
+ import { type CSOTTimeoutContext } from '../timeout';
17
16
  import type { Callback } from '../utils';
18
17
  import type { GridFSChunk } from './upload';
19
18
 
@@ -31,8 +30,8 @@ export interface GridFSBucketReadStreamOptions {
31
30
  */
32
31
  end?: number;
33
32
  /**
34
- * @experimental
35
33
  * Specifies the time an operation will run until it throws a timeout error
34
+ * @deprecated `timeoutMS` has no effect and will be removed in a future release.
36
35
  */
37
36
  timeoutMS?: number;
38
37
  }
@@ -83,7 +82,7 @@ export interface GridFSBucketReadStreamPrivate {
83
82
  expected: number;
84
83
 
85
84
  /**
86
- * The filter used to search in the _files_ collection (i.e., `{ _id: <> }`)
85
+ * The filter used to search in the _files_ collection (i.e., `{ _id: { $eq: <> } }`)
87
86
  * This is not the same filter used when reading chunks from the chunks collection.
88
87
  */
89
88
  filter: Document;
@@ -151,11 +150,7 @@ export class GridFSBucketReadStream extends Readable {
151
150
  end: 0,
152
151
  ...options
153
152
  },
154
- readPreference,
155
- timeoutContext:
156
- options?.timeoutMS != null
157
- ? new CSOTTimeoutContext({ timeoutMS: options.timeoutMS, serverSelectionTimeoutMS: 0 })
158
- : undefined
153
+ readPreference
159
154
  };
160
155
  }
161
156
 
@@ -318,9 +313,8 @@ function init(stream: GridFSBucketReadStream): void {
318
313
  if (stream.destroyed) return;
319
314
 
320
315
  if (!doc) {
321
- const identifier = stream.s.filter._id
322
- ? stream.s.filter._id.toString()
323
- : stream.s.filter.filename;
316
+ const identifier =
317
+ stream.s.filter._id != null ? stream.s.filter._id.$eq : stream.s.filter.filename;
324
318
  const errmsg = `FileNotFound: file ${identifier} was not found`;
325
319
  // TODO(NODE-3483)
326
320
  const err = new MongoRuntimeError(errmsg);
@@ -349,7 +343,7 @@ function init(stream: GridFSBucketReadStream): void {
349
343
  return stream.destroy(error);
350
344
  }
351
345
 
352
- const filter: Document = { files_id: doc._id };
346
+ const filter: Document = { files_id: { $eq: doc._id } };
353
347
 
354
348
  // Currently the skip function does not support the index,
355
349
  // it needs to retrieve all the documents first and then skip them. (CS-25811)
@@ -372,7 +366,6 @@ function init(stream: GridFSBucketReadStream): void {
372
366
 
373
367
  stream.s.cursor = stream.s.chunks
374
368
  .find(filter, {
375
- timeoutMode: stream.s.options.timeoutMS != null ? CursorTimeoutMode.LIFETIME : undefined,
376
369
  timeoutMS: remainingTimeMS
377
370
  })
378
371
  .sort({ n: 1 });
@@ -39,9 +39,9 @@ export interface GridFSBucketOptions extends WriteConcernOptions {
39
39
  /** Read preference to be passed to read operations */
40
40
  readPreference?: ReadPreference;
41
41
  /**
42
- * @experimental
43
42
  * Specifies the lifetime duration of a gridFS stream. If any async operations are in progress
44
43
  * when this timeout expires, the stream will throw a timeout error.
44
+ * @deprecated `timeoutMS` has no effect and will be removed in a future release.
45
45
  */
46
46
  timeoutMS?: number;
47
47
  }
@@ -149,7 +149,7 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
149
149
  this.s._chunksCollection,
150
150
  this.s._filesCollection,
151
151
  this.s.options.readPreference,
152
- { _id: id },
152
+ { _id: { $eq: id } },
153
153
  { timeoutMS: this.s.options.timeoutMS, ...options }
154
154
  );
155
155
  }
@@ -159,7 +159,13 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
159
159
  *
160
160
  * @param id - The id of the file doc
161
161
  */
162
- async delete(id: ObjectId, options?: { timeoutMS: number }): Promise<void> {
162
+ async delete(
163
+ id: ObjectId,
164
+ options?: {
165
+ /** @deprecated `timeoutMS` has no effect and will be removed in a future release. */
166
+ timeoutMS?: number;
167
+ }
168
+ ): Promise<void> {
163
169
  const { timeoutMS } = resolveOptions(this.s.db, options);
164
170
  let timeoutContext: CSOTTimeoutContext | undefined = undefined;
165
171
 
@@ -171,7 +177,7 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
171
177
  }
172
178
 
173
179
  const { deletedCount } = await this.s._filesCollection.deleteOne(
174
- { _id: id },
180
+ { _id: { $eq: id } },
175
181
  { timeoutMS: timeoutContext?.remainingTimeMS }
176
182
  );
177
183
 
@@ -179,7 +185,10 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
179
185
  if (remainingTimeMS != null && remainingTimeMS <= 0)
180
186
  throw new MongoOperationTimeoutError(`Timed out after ${timeoutMS}ms`);
181
187
  // Delete orphaned chunks before returning FileNotFound
182
- await this.s._chunksCollection.deleteMany({ files_id: id }, { timeoutMS: remainingTimeMS });
188
+ await this.s._chunksCollection.deleteMany(
189
+ { files_id: { $eq: id } },
190
+ { timeoutMS: remainingTimeMS }
191
+ );
183
192
 
184
193
  if (deletedCount === 0) {
185
194
  // TODO(NODE-3483): Replace with more appropriate error
@@ -229,8 +238,15 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
229
238
  * @param id - the id of the file to rename
230
239
  * @param filename - new name for the file
231
240
  */
232
- async rename(id: ObjectId, filename: string, options?: { timeoutMS: number }): Promise<void> {
233
- const filter = { _id: id };
241
+ async rename(
242
+ id: ObjectId,
243
+ filename: string,
244
+ options?: {
245
+ /** @deprecated `timeoutMS` has no effect and will be removed in a future release. */
246
+ timeoutMS?: number;
247
+ }
248
+ ): Promise<void> {
249
+ const filter = { _id: { $eq: id } };
234
250
  const update = { $set: { filename } };
235
251
  const { matchedCount } = await this.s._filesCollection.updateOne(filter, update, options);
236
252
  if (matchedCount === 0) {
@@ -239,7 +255,10 @@ export class GridFSBucket extends TypedEventEmitter<GridFSBucketEvents> {
239
255
  }
240
256
 
241
257
  /** Removes this bucket's files collection, followed by its chunks collection. */
242
- async drop(options?: { timeoutMS: number }): Promise<void> {
258
+ async drop(options?: {
259
+ /** @deprecated `timeoutMS` has no effect and will be removed in a future release. */
260
+ timeoutMS?: number;
261
+ }): Promise<void> {
243
262
  const { timeoutMS } = resolveOptions(this.s.db, options);
244
263
  let timeoutContext: CSOTTimeoutContext | undefined = undefined;
245
264