mongodb 6.15.0 → 6.16.0-dev.20250423.sha.28857b79
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.
- package/README.md +2 -0
- package/lib/beta.d.ts +48 -12
- package/lib/bulk/common.js +1 -1
- package/lib/bulk/common.js.map +1 -1
- package/lib/change_stream.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js +1 -5
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/cmap/connection.js +24 -11
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/wire_protocol/responses.js +7 -9
- package/lib/cmap/wire_protocol/responses.js.map +1 -1
- package/lib/collection.js.map +1 -1
- package/lib/error.js +2 -1
- package/lib/error.js.map +1 -1
- package/lib/operations/client_bulk_write/command_builder.js +7 -0
- package/lib/operations/client_bulk_write/command_builder.js.map +1 -1
- package/lib/operations/distinct.js +3 -0
- package/lib/operations/distinct.js.map +1 -1
- package/lib/operations/update.js +4 -0
- package/lib/operations/update.js.map +1 -1
- package/lib/sort.js +13 -6
- package/lib/sort.js.map +1 -1
- package/mongodb.d.ts +48 -12
- package/package.json +19 -19
- package/src/bulk/common.ts +8 -3
- package/src/change_stream.ts +5 -1
- package/src/client-side-encryption/auto_encrypter.ts +4 -8
- package/src/cmap/connection.ts +31 -11
- package/src/cmap/wire_protocol/responses.ts +4 -5
- package/src/collection.ts +2 -1
- package/src/error.ts +2 -1
- package/src/operations/client_bulk_write/command_builder.ts +9 -0
- package/src/operations/client_bulk_write/common.ts +5 -0
- package/src/operations/distinct.ts +18 -1
- package/src/operations/update.ts +10 -1
- package/src/sort.ts +32 -23
package/src/change_stream.ts
CHANGED
|
@@ -521,8 +521,12 @@ export interface UpdateDescription<TSchema extends Document = Document> {
|
|
|
521
521
|
* }
|
|
522
522
|
* ```
|
|
523
523
|
*
|
|
524
|
-
* This field is only present when there are ambiguous paths that are updated as a part of the update event
|
|
524
|
+
* This field is only present when there are ambiguous paths that are updated as a part of the update event.
|
|
525
|
+
*
|
|
526
|
+
* On \<8.2.0 servers, this field is only present when `showExpandedEvents` is set to true.
|
|
525
527
|
* is enabled for the change stream.
|
|
528
|
+
*
|
|
529
|
+
* On 8.2.0+ servers, this field is present for update events regardless of whether `showExpandedEvents` is enabled.
|
|
526
530
|
* @sinceServerVersion 6.1.0
|
|
527
531
|
*/
|
|
528
532
|
disambiguatedPaths?: Document;
|
|
@@ -365,14 +365,10 @@ export class AutoEncrypter {
|
|
|
365
365
|
const client = await this._mongocryptdClient.connect();
|
|
366
366
|
return client;
|
|
367
367
|
} catch (error) {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
{ cause: error }
|
|
373
|
-
);
|
|
374
|
-
}
|
|
375
|
-
throw error;
|
|
368
|
+
throw new MongoRuntimeError(
|
|
369
|
+
'Unable to connect to `mongocryptd`, please make sure it is running or in your PATH for auto-spawn',
|
|
370
|
+
{ cause: error }
|
|
371
|
+
);
|
|
376
372
|
}
|
|
377
373
|
}
|
|
378
374
|
|
package/src/cmap/connection.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
MongoNetworkTimeoutError,
|
|
28
28
|
MongoOperationTimeoutError,
|
|
29
29
|
MongoParseError,
|
|
30
|
+
MongoRuntimeError,
|
|
30
31
|
MongoServerError,
|
|
31
32
|
MongoUnexpectedServerResponseError
|
|
32
33
|
} from '../error';
|
|
@@ -791,22 +792,41 @@ export class SizedMessageTransform extends Transform {
|
|
|
791
792
|
}
|
|
792
793
|
|
|
793
794
|
this.bufferPool.append(chunk);
|
|
794
|
-
const sizeOfMessage = this.bufferPool.getInt32();
|
|
795
795
|
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
}
|
|
796
|
+
while (this.bufferPool.length) {
|
|
797
|
+
// While there are any bytes in the buffer
|
|
799
798
|
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
799
|
+
// Try to fetch a size from the top 4 bytes
|
|
800
|
+
const sizeOfMessage = this.bufferPool.getInt32();
|
|
801
|
+
|
|
802
|
+
if (sizeOfMessage == null) {
|
|
803
|
+
// Not even an int32 worth of data. Stop the loop, we need more chunks.
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
if (sizeOfMessage < 0) {
|
|
808
|
+
// The size in the message has a negative value, this is probably corruption, throw:
|
|
809
|
+
return callback(new MongoParseError(`Message size cannot be negative: ${sizeOfMessage}`));
|
|
810
|
+
}
|
|
803
811
|
|
|
804
|
-
|
|
805
|
-
|
|
812
|
+
if (sizeOfMessage > this.bufferPool.length) {
|
|
813
|
+
// We do not have enough bytes to make a sizeOfMessage chunk
|
|
814
|
+
break;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// Add a message to the stream
|
|
818
|
+
const message = this.bufferPool.read(sizeOfMessage);
|
|
819
|
+
|
|
820
|
+
if (!this.push(message)) {
|
|
821
|
+
// We only subscribe to data events so we should never get backpressure
|
|
822
|
+
// if we do, we do not have the handling for it.
|
|
823
|
+
return callback(
|
|
824
|
+
new MongoRuntimeError(`SizedMessageTransform does not support backpressure`)
|
|
825
|
+
);
|
|
826
|
+
}
|
|
806
827
|
}
|
|
807
828
|
|
|
808
|
-
|
|
809
|
-
return callback(null, message);
|
|
829
|
+
callback();
|
|
810
830
|
}
|
|
811
831
|
}
|
|
812
832
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
parseToElementsToArray,
|
|
9
9
|
parseUtf8ValidationOption,
|
|
10
10
|
pluckBSONSerializeOptions,
|
|
11
|
+
serialize,
|
|
11
12
|
type Timestamp
|
|
12
13
|
} from '../../bson';
|
|
13
14
|
import { MONGODB_ERROR_CODES, MongoUnexpectedServerResponseError } from '../../error';
|
|
@@ -230,11 +231,9 @@ export class CursorResponse extends MongoDBResponse {
|
|
|
230
231
|
* This supports a feature of the FindCursor.
|
|
231
232
|
* It is an optimization to avoid an extra getMore when the limit has been reached
|
|
232
233
|
*/
|
|
233
|
-
static emptyGetMore: CursorResponse
|
|
234
|
-
id:
|
|
235
|
-
|
|
236
|
-
shift: () => null
|
|
237
|
-
} as unknown as CursorResponse;
|
|
234
|
+
static get emptyGetMore(): CursorResponse {
|
|
235
|
+
return new CursorResponse(serialize({ ok: 1, cursor: { id: 0n, nextBatch: [] } }));
|
|
236
|
+
}
|
|
238
237
|
|
|
239
238
|
static override is(value: unknown): value is CursorResponse {
|
|
240
239
|
return value instanceof CursorResponse || value === CursorResponse.emptyGetMore;
|
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,
|
package/src/error.ts
CHANGED
|
@@ -56,7 +56,8 @@ export const MONGODB_ERROR_CODES = Object.freeze({
|
|
|
56
56
|
FailedToSatisfyReadPreference: 133,
|
|
57
57
|
CursorNotFound: 43,
|
|
58
58
|
LegacyNotPrimary: 10058,
|
|
59
|
-
WriteConcernFailed
|
|
59
|
+
// WriteConcernTimeout is WriteConcernFailed on pre-8.1 servers
|
|
60
|
+
WriteConcernTimeout: 64,
|
|
60
61
|
NamespaceNotFound: 26,
|
|
61
62
|
IllegalOperation: 20,
|
|
62
63
|
MaxTimeMSExpired: 50,
|
|
@@ -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 */
|
|
@@ -8,7 +8,20 @@ import { CommandOperation, type CommandOperationOptions } from './command';
|
|
|
8
8
|
import { Aspect, defineAspects } from './operation';
|
|
9
9
|
|
|
10
10
|
/** @public */
|
|
11
|
-
export type DistinctOptions = CommandOperationOptions
|
|
11
|
+
export type DistinctOptions = CommandOperationOptions & {
|
|
12
|
+
/**
|
|
13
|
+
* @sinceServerVersion 7.1
|
|
14
|
+
*
|
|
15
|
+
* The index to use. Specify either the index name as a string or the index key pattern.
|
|
16
|
+
* If specified, then the query system will only consider plans using the hinted index.
|
|
17
|
+
*
|
|
18
|
+
* If provided as a string, `hint` must be index name for an index on the collection.
|
|
19
|
+
* If provided as an object, `hint` must be an index description for an index defined on the collection.
|
|
20
|
+
*
|
|
21
|
+
* See https://www.mongodb.com/docs/manual/reference/command/distinct/#command-fields.
|
|
22
|
+
*/
|
|
23
|
+
hint?: Document | string;
|
|
24
|
+
};
|
|
12
25
|
|
|
13
26
|
/**
|
|
14
27
|
* Return a list of distinct values for the given key across a collection.
|
|
@@ -71,6 +84,10 @@ export class DistinctOperation extends CommandOperation<any[]> {
|
|
|
71
84
|
cmd.comment = options.comment;
|
|
72
85
|
}
|
|
73
86
|
|
|
87
|
+
if (options.hint != null) {
|
|
88
|
+
cmd.hint = options.hint;
|
|
89
|
+
}
|
|
90
|
+
|
|
74
91
|
// Do we have a readConcern specified
|
|
75
92
|
decorateWithReadConcern(cmd, coll, options);
|
|
76
93
|
|
package/src/operations/update.ts
CHANGED
|
@@ -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
|
-
|
|
|
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
|
-
/** @
|
|
25
|
+
/** @public */
|
|
26
26
|
export type SortDirectionForCmd = 1 | -1 | { $meta: string };
|
|
27
27
|
|
|
28
|
-
/** @
|
|
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
|
|
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]
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
126
|
-
|
|
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
|
}
|