mongodb 6.16.0-dev.20250422.sha.746af47a → 6.16.0-dev.20250424.sha.82303f3d

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.
@@ -247,9 +247,9 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
247
247
  this.lastUseTime = now();
248
248
 
249
249
  this.messageStream = this.socket
250
- .on('error', this.onError.bind(this))
250
+ .on('error', this.onSocketError.bind(this))
251
251
  .pipe(new SizedMessageTransform({ connection: this }))
252
- .on('error', this.onError.bind(this));
252
+ .on('error', this.onTransformError.bind(this));
253
253
  this.socket.on('close', this.onClose.bind(this));
254
254
  this.socket.on('timeout', this.onTimeout.bind(this));
255
255
 
@@ -304,6 +304,14 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
304
304
  this.lastUseTime = now();
305
305
  }
306
306
 
307
+ private onSocketError(cause: Error) {
308
+ this.onError(new MongoNetworkError(cause.message, { cause }));
309
+ }
310
+
311
+ private onTransformError(error: Error) {
312
+ this.onError(error);
313
+ }
314
+
307
315
  public onError(error: Error) {
308
316
  this.cleanup(error);
309
317
  }
@@ -769,7 +777,6 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
769
777
  } finally {
770
778
  this.dataEvents = null;
771
779
  this.messageStream.pause();
772
- this.throwIfAborted();
773
780
  }
774
781
  }
775
782
  }
package/src/collection.ts CHANGED
@@ -87,6 +87,7 @@ import {
87
87
  } from './operations/update';
88
88
  import { ReadConcern, type ReadConcernLike } from './read_concern';
89
89
  import { ReadPreference, type ReadPreferenceLike } from './read_preference';
90
+ import { type Sort } from './sort';
90
91
  import {
91
92
  DEFAULT_PK_FACTORY,
92
93
  MongoDBCollectionNamespace,
@@ -365,7 +366,7 @@ export class Collection<TSchema extends Document = Document> {
365
366
  async updateOne(
366
367
  filter: Filter<TSchema>,
367
368
  update: UpdateFilter<TSchema> | Document[],
368
- options?: UpdateOptions
369
+ options?: UpdateOptions & { sort?: Sort }
369
370
  ): Promise<UpdateResult<TSchema>> {
370
371
  return await executeOperation(
371
372
  this.client,
@@ -1273,6 +1273,7 @@ export const OPTIONS = {
1273
1273
  requestCert: { type: 'any' },
1274
1274
  rejectUnauthorized: { type: 'any' },
1275
1275
  checkServerIdentity: { type: 'any' },
1276
+ keepAliveInitialDelay: { type: 'any' },
1276
1277
  ALPNProtocols: { type: 'any' },
1277
1278
  SNICallback: { type: 'any' },
1278
1279
  session: { type: 'any' },
@@ -115,7 +115,12 @@ export type SupportedTLSSocketOptions = Pick<
115
115
 
116
116
  /** @public */
117
117
  export type SupportedSocketOptions = Pick<
118
- TcpNetConnectOpts & { autoSelectFamily?: boolean; autoSelectFamilyAttemptTimeout?: number },
118
+ TcpNetConnectOpts & {
119
+ autoSelectFamily?: boolean;
120
+ autoSelectFamilyAttemptTimeout?: number;
121
+ /** Node.JS socket option to set the time the first keepalive probe is sent on an idle socket. Defaults to 120000ms */
122
+ keepAliveInitialDelay?: number;
123
+ },
119
124
  (typeof LEGAL_TCP_SOCKET_OPTIONS)[number]
120
125
  >;
121
126
 
@@ -3,6 +3,7 @@ import { DocumentSequence } from '../../cmap/commands';
3
3
  import { MongoAPIError, MongoInvalidArgumentError } from '../../error';
4
4
  import { type PkFactory } from '../../mongo_client';
5
5
  import type { Filter, OptionalId, UpdateFilter, WithoutId } from '../../mongo_types';
6
+ import { formatSort, type SortForCmd } from '../../sort';
6
7
  import { DEFAULT_PK_FACTORY, hasAtomicOperators } from '../../utils';
7
8
  import { type CollationOptions } from '../command';
8
9
  import { type Hint } from '../operation';
@@ -327,6 +328,7 @@ export interface ClientUpdateOperation {
327
328
  upsert?: boolean;
328
329
  arrayFilters?: Document[];
329
330
  collation?: CollationOptions;
331
+ sort?: SortForCmd;
330
332
  }
331
333
 
332
334
  /**
@@ -398,6 +400,9 @@ function createUpdateOperation(
398
400
  if (model.collation) {
399
401
  document.collation = model.collation;
400
402
  }
403
+ if (!multi && 'sort' in model && model.sort != null) {
404
+ document.sort = formatSort(model.sort);
405
+ }
401
406
  return document;
402
407
  }
403
408
 
@@ -410,6 +415,7 @@ export interface ClientReplaceOneOperation {
410
415
  hint?: Hint;
411
416
  upsert?: boolean;
412
417
  collation?: CollationOptions;
418
+ sort?: SortForCmd;
413
419
  }
414
420
 
415
421
  /**
@@ -443,6 +449,9 @@ export const buildReplaceOneOperation = (
443
449
  if (model.collation) {
444
450
  document.collation = model.collation;
445
451
  }
452
+ if (model.sort != null) {
453
+ document.sort = formatSort(model.sort);
454
+ }
446
455
  return document;
447
456
  };
448
457
 
@@ -2,6 +2,7 @@ import { type Document } from '../../bson';
2
2
  import type { Filter, OptionalId, UpdateFilter, WithoutId } from '../../mongo_types';
3
3
  import type { CollationOptions, CommandOperationOptions } from '../../operations/command';
4
4
  import type { Hint } from '../../operations/operation';
5
+ import { type Sort } from '../../sort';
5
6
 
6
7
  /** @public */
7
8
  export interface ClientBulkWriteOptions extends CommandOperationOptions {
@@ -89,6 +90,8 @@ export interface ClientReplaceOneModel<TSchema> extends ClientWriteModel {
89
90
  hint?: Hint;
90
91
  /** When true, creates a new document if no document matches the query. */
91
92
  upsert?: boolean;
93
+ /** Specifies the sort order for the documents matched by the filter. */
94
+ sort?: Sort;
92
95
  }
93
96
 
94
97
  /** @public */
@@ -113,6 +116,8 @@ export interface ClientUpdateOneModel<TSchema> extends ClientWriteModel {
113
116
  hint?: Hint;
114
117
  /** When true, creates a new document if no document matches the query. */
115
118
  upsert?: boolean;
119
+ /** Specifies the sort order for the documents matched by the filter. */
120
+ sort?: Sort;
116
121
  }
117
122
 
118
123
  /** @public */
@@ -4,6 +4,7 @@ import { MongoCompatibilityError, MongoInvalidArgumentError, MongoServerError }
4
4
  import type { InferIdType, TODO_NODE_3286 } from '../mongo_types';
5
5
  import type { Server } from '../sdam/server';
6
6
  import type { ClientSession } from '../sessions';
7
+ import { formatSort, type Sort, type SortForCmd } from '../sort';
7
8
  import { type TimeoutContext } from '../timeout';
8
9
  import { hasAtomicOperators, type MongoDBNamespace } from '../utils';
9
10
  import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
@@ -58,6 +59,8 @@ export interface UpdateStatement {
58
59
  arrayFilters?: Document[];
59
60
  /** A document or string that specifies the index to use to support the query predicate. */
60
61
  hint?: Hint;
62
+ /** Specifies the sort order for the documents matched by the filter. */
63
+ sort?: SortForCmd;
61
64
  }
62
65
 
63
66
  /**
@@ -214,6 +217,8 @@ export interface ReplaceOptions extends CommandOperationOptions {
214
217
  upsert?: boolean;
215
218
  /** Map of parameter names and values that can be accessed using $$var (requires MongoDB 5.0). */
216
219
  let?: Document;
220
+ /** Specifies the sort order for the documents matched by the filter. */
221
+ sort?: Sort;
217
222
  }
218
223
 
219
224
  /** @internal */
@@ -259,7 +264,7 @@ export class ReplaceOneOperation extends UpdateOperation {
259
264
  export function makeUpdateStatement(
260
265
  filter: Document,
261
266
  update: Document | Document[],
262
- options: UpdateOptions & { multi?: boolean }
267
+ options: UpdateOptions & { multi?: boolean } & { sort?: Sort }
263
268
  ): UpdateStatement {
264
269
  if (filter == null || typeof filter !== 'object') {
265
270
  throw new MongoInvalidArgumentError('Selector must be a valid JavaScript object');
@@ -290,6 +295,10 @@ export function makeUpdateStatement(
290
295
  op.collation = options.collation;
291
296
  }
292
297
 
298
+ if (!options.multi && options.sort != null) {
299
+ op.sort = formatSort(options.sort);
300
+ }
301
+
293
302
  return op;
294
303
  }
295
304
 
package/src/sort.ts CHANGED
@@ -8,24 +8,24 @@ export type SortDirection =
8
8
  | 'desc'
9
9
  | 'ascending'
10
10
  | 'descending'
11
- | { $meta: string };
11
+ | { readonly $meta: string };
12
12
 
13
13
  /** @public */
14
14
  export type Sort =
15
15
  | string
16
- | Exclude<SortDirection, { $meta: string }>
17
- | string[]
18
- | { [key: string]: SortDirection }
19
- | Map<string, SortDirection>
20
- | [string, SortDirection][]
21
- | [string, SortDirection];
16
+ | Exclude<SortDirection, { readonly $meta: string }>
17
+ | ReadonlyArray<string>
18
+ | { readonly [key: string]: SortDirection }
19
+ | ReadonlyMap<string, SortDirection>
20
+ | ReadonlyArray<readonly [string, SortDirection]>
21
+ | readonly [string, SortDirection];
22
22
 
23
23
  /** Below stricter types were created for sort that correspond with type that the cmd takes */
24
24
 
25
- /** @internal */
25
+ /** @public */
26
26
  export type SortDirectionForCmd = 1 | -1 | { $meta: string };
27
27
 
28
- /** @internal */
28
+ /** @public */
29
29
  export type SortForCmd = Map<string, SortDirectionForCmd>;
30
30
 
31
31
  /** @internal */
@@ -55,7 +55,7 @@ function isMeta(t: SortDirection): t is { $meta: string } {
55
55
  }
56
56
 
57
57
  /** @internal */
58
- function isPair(t: Sort): t is [string, SortDirection] {
58
+ function isPair(t: Sort): t is readonly [string, SortDirection] {
59
59
  if (Array.isArray(t) && t.length === 2) {
60
60
  try {
61
61
  prepareDirection(t[1]);
@@ -67,33 +67,37 @@ function isPair(t: Sort): t is [string, SortDirection] {
67
67
  return false;
68
68
  }
69
69
 
70
- function isDeep(t: Sort): t is [string, SortDirection][] {
70
+ function isDeep(t: Sort): t is ReadonlyArray<readonly [string, SortDirection]> {
71
71
  return Array.isArray(t) && Array.isArray(t[0]);
72
72
  }
73
73
 
74
- function isMap(t: Sort): t is Map<string, SortDirection> {
74
+ function isMap(t: Sort): t is ReadonlyMap<string, SortDirection> {
75
75
  return t instanceof Map && t.size > 0;
76
76
  }
77
77
 
78
+ function isReadonlyArray<T>(value: any): value is readonly T[] {
79
+ return Array.isArray(value);
80
+ }
81
+
78
82
  /** @internal */
79
- function pairToMap(v: [string, SortDirection]): SortForCmd {
83
+ function pairToMap(v: readonly [string, SortDirection]): SortForCmd {
80
84
  return new Map([[`${v[0]}`, prepareDirection([v[1]])]]);
81
85
  }
82
86
 
83
87
  /** @internal */
84
- function deepToMap(t: [string, SortDirection][]): SortForCmd {
88
+ function deepToMap(t: ReadonlyArray<readonly [string, SortDirection]>): SortForCmd {
85
89
  const sortEntries: SortPairForCmd[] = t.map(([k, v]) => [`${k}`, prepareDirection(v)]);
86
90
  return new Map(sortEntries);
87
91
  }
88
92
 
89
93
  /** @internal */
90
- function stringsToMap(t: string[]): SortForCmd {
94
+ function stringsToMap(t: ReadonlyArray<string>): SortForCmd {
91
95
  const sortEntries: SortPairForCmd[] = t.map(key => [`${key}`, 1]);
92
96
  return new Map(sortEntries);
93
97
  }
94
98
 
95
99
  /** @internal */
96
- function objectToMap(t: { [key: string]: SortDirection }): SortForCmd {
100
+ function objectToMap(t: { readonly [key: string]: SortDirection }): SortForCmd {
97
101
  const sortEntries: SortPairForCmd[] = Object.entries(t).map(([k, v]) => [
98
102
  `${k}`,
99
103
  prepareDirection(v)
@@ -102,7 +106,7 @@ function objectToMap(t: { [key: string]: SortDirection }): SortForCmd {
102
106
  }
103
107
 
104
108
  /** @internal */
105
- function mapToMap(t: Map<string, SortDirection>): SortForCmd {
109
+ function mapToMap(t: ReadonlyMap<string, SortDirection>): SortForCmd {
106
110
  const sortEntries: SortPairForCmd[] = Array.from(t).map(([k, v]) => [
107
111
  `${k}`,
108
112
  prepareDirection(v)
@@ -116,17 +120,22 @@ export function formatSort(
116
120
  direction?: SortDirection
117
121
  ): SortForCmd | undefined {
118
122
  if (sort == null) return undefined;
119
- if (typeof sort === 'string') return new Map([[sort, prepareDirection(direction)]]);
123
+
124
+ if (typeof sort === 'string') return new Map([[sort, prepareDirection(direction)]]); // 'fieldName'
125
+
120
126
  if (typeof sort !== 'object') {
121
127
  throw new MongoInvalidArgumentError(
122
128
  `Invalid sort format: ${JSON.stringify(sort)} Sort must be a valid object`
123
129
  );
124
130
  }
125
- if (!Array.isArray(sort)) {
126
- return isMap(sort) ? mapToMap(sort) : Object.keys(sort).length ? objectToMap(sort) : undefined;
131
+
132
+ if (!isReadonlyArray(sort)) {
133
+ if (isMap(sort)) return mapToMap(sort); // Map<fieldName, SortDirection>
134
+ if (Object.keys(sort).length) return objectToMap(sort); // { [fieldName: string]: SortDirection }
135
+ return undefined;
127
136
  }
128
137
  if (!sort.length) return undefined;
129
- if (isDeep(sort)) return deepToMap(sort);
130
- if (isPair(sort)) return pairToMap(sort);
131
- return stringsToMap(sort);
138
+ if (isDeep(sort)) return deepToMap(sort); // [ [fieldName, sortDir], [fieldName, sortDir] ... ]
139
+ if (isPair(sort)) return pairToMap(sort); // [ fieldName, sortDir ]
140
+ return stringsToMap(sort); // [ fieldName, fieldName ]
132
141
  }