mongodb 6.16.0 → 6.17.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.
- package/README.md +2 -0
- package/lib/beta.d.ts +132 -33
- package/lib/bulk/common.js +4 -4
- package/lib/bulk/common.js.map +1 -1
- package/lib/client-side-encryption/auto_encrypter.js +5 -2
- package/lib/client-side-encryption/auto_encrypter.js.map +1 -1
- package/lib/client-side-encryption/client_encryption.js.map +1 -1
- package/lib/client-side-encryption/state_machine.js +1 -1
- package/lib/client-side-encryption/state_machine.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js +6 -0
- package/lib/cmap/auth/mongodb_oidc/automated_callback_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js +21 -33
- package/lib/cmap/auth/mongodb_oidc/azure_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js +14 -21
- package/lib/cmap/auth/mongodb_oidc/gcp_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js +19 -26
- package/lib/cmap/auth/mongodb_oidc/k8s_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js +12 -24
- package/lib/cmap/auth/mongodb_oidc/token_machine_workflow.js.map +1 -1
- package/lib/cmap/auth/mongodb_oidc.js +5 -4
- package/lib/cmap/auth/mongodb_oidc.js.map +1 -1
- package/lib/cmap/connect.js +4 -3
- package/lib/cmap/connect.js.map +1 -1
- package/lib/cmap/connection.js +8 -3
- package/lib/cmap/connection.js.map +1 -1
- package/lib/cmap/connection_pool.js +6 -1
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/wire_protocol/constants.js +2 -2
- package/lib/cmap/wire_protocol/responses.js.map +1 -1
- package/lib/collection.js.map +1 -1
- package/lib/connection_string.js +2 -0
- package/lib/connection_string.js.map +1 -1
- package/lib/constants.js +0 -1
- package/lib/constants.js.map +1 -1
- package/lib/encrypter.js +3 -7
- package/lib/encrypter.js.map +1 -1
- package/lib/error.js +28 -1
- package/lib/error.js.map +1 -1
- package/lib/index.js +4 -3
- package/lib/index.js.map +1 -1
- package/lib/mongo_client.js +66 -20
- package/lib/mongo_client.js.map +1 -1
- package/lib/operations/aggregate.js +0 -1
- package/lib/operations/aggregate.js.map +1 -1
- package/lib/operations/client_bulk_write/command_builder.js +20 -13
- package/lib/operations/client_bulk_write/command_builder.js.map +1 -1
- package/lib/operations/find_and_modify.js +1 -1
- package/lib/operations/find_and_modify.js.map +1 -1
- package/lib/operations/update.js +6 -2
- package/lib/operations/update.js.map +1 -1
- package/lib/sdam/server.js +4 -1
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/topology.js +9 -4
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sort.js +13 -6
- package/lib/sort.js.map +1 -1
- package/lib/utils.js +15 -1
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +132 -33
- package/package.json +19 -19
- package/src/bulk/common.ts +11 -6
- package/src/client-side-encryption/auto_encrypter.ts +10 -2
- package/src/client-side-encryption/client_encryption.ts +5 -0
- package/src/client-side-encryption/state_machine.ts +1 -1
- package/src/cmap/auth/mongodb_oidc/automated_callback_workflow.ts +6 -0
- package/src/cmap/auth/mongodb_oidc/azure_machine_workflow.ts +23 -35
- package/src/cmap/auth/mongodb_oidc/gcp_machine_workflow.ts +16 -23
- package/src/cmap/auth/mongodb_oidc/k8s_machine_workflow.ts +17 -25
- package/src/cmap/auth/mongodb_oidc/token_machine_workflow.ts +11 -24
- package/src/cmap/auth/mongodb_oidc.ts +13 -8
- package/src/cmap/connect.ts +4 -3
- package/src/cmap/connection.ts +11 -4
- package/src/cmap/connection_pool.ts +8 -1
- package/src/cmap/wire_protocol/constants.ts +2 -2
- package/src/cmap/wire_protocol/on_demand/document.ts +1 -1
- package/src/cmap/wire_protocol/responses.ts +2 -2
- package/src/collection.ts +2 -1
- package/src/connection_string.ts +2 -0
- package/src/constants.ts +0 -1
- package/src/encrypter.ts +3 -10
- package/src/error.ts +28 -0
- package/src/index.ts +1 -0
- package/src/mongo_client.ts +73 -21
- package/src/operations/aggregate.ts +0 -1
- package/src/operations/client_bulk_write/command_builder.ts +32 -14
- package/src/operations/client_bulk_write/common.ts +5 -0
- package/src/operations/find_and_modify.ts +1 -1
- package/src/operations/update.ts +12 -3
- package/src/sdam/server.ts +5 -1
- package/src/sdam/topology.ts +10 -4
- package/src/sort.ts +32 -23
- package/src/utils.ts +21 -1
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js +0 -110
- package/lib/cmap/auth/mongodb_oidc/machine_workflow.js.map +0 -1
- package/src/cmap/auth/mongodb_oidc/machine_workflow.ts +0 -142
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { BSON, type Document } from '../../bson';
|
|
1
|
+
import { BSON, type BSONSerializeOptions, type Document } from '../../bson';
|
|
2
2
|
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';
|
|
@@ -127,7 +128,7 @@ export class ClientBulkWriteCommandBuilder {
|
|
|
127
128
|
|
|
128
129
|
if (nsIndex != null) {
|
|
129
130
|
// Build the operation and serialize it to get the bytes buffer.
|
|
130
|
-
const operation = buildOperation(model, nsIndex, this.pkFactory);
|
|
131
|
+
const operation = buildOperation(model, nsIndex, this.pkFactory, this.options);
|
|
131
132
|
let operationBuffer;
|
|
132
133
|
try {
|
|
133
134
|
operationBuffer = BSON.serialize(operation);
|
|
@@ -158,7 +159,12 @@ export class ClientBulkWriteCommandBuilder {
|
|
|
158
159
|
// construct our nsInfo and ops documents and buffers.
|
|
159
160
|
namespaces.set(ns, currentNamespaceIndex);
|
|
160
161
|
const nsInfo = { ns: ns };
|
|
161
|
-
const operation = buildOperation(
|
|
162
|
+
const operation = buildOperation(
|
|
163
|
+
model,
|
|
164
|
+
currentNamespaceIndex,
|
|
165
|
+
this.pkFactory,
|
|
166
|
+
this.options
|
|
167
|
+
);
|
|
162
168
|
let nsInfoBuffer;
|
|
163
169
|
let operationBuffer;
|
|
164
170
|
try {
|
|
@@ -327,6 +333,7 @@ export interface ClientUpdateOperation {
|
|
|
327
333
|
upsert?: boolean;
|
|
328
334
|
arrayFilters?: Document[];
|
|
329
335
|
collation?: CollationOptions;
|
|
336
|
+
sort?: SortForCmd;
|
|
330
337
|
}
|
|
331
338
|
|
|
332
339
|
/**
|
|
@@ -337,9 +344,10 @@ export interface ClientUpdateOperation {
|
|
|
337
344
|
*/
|
|
338
345
|
export const buildUpdateOneOperation = (
|
|
339
346
|
model: ClientUpdateOneModel<Document>,
|
|
340
|
-
index: number
|
|
347
|
+
index: number,
|
|
348
|
+
options: BSONSerializeOptions
|
|
341
349
|
): ClientUpdateOperation => {
|
|
342
|
-
return createUpdateOperation(model, index, false);
|
|
350
|
+
return createUpdateOperation(model, index, false, options);
|
|
343
351
|
};
|
|
344
352
|
|
|
345
353
|
/**
|
|
@@ -350,17 +358,18 @@ export const buildUpdateOneOperation = (
|
|
|
350
358
|
*/
|
|
351
359
|
export const buildUpdateManyOperation = (
|
|
352
360
|
model: ClientUpdateManyModel<Document>,
|
|
353
|
-
index: number
|
|
361
|
+
index: number,
|
|
362
|
+
options: BSONSerializeOptions
|
|
354
363
|
): ClientUpdateOperation => {
|
|
355
|
-
return createUpdateOperation(model, index, true);
|
|
364
|
+
return createUpdateOperation(model, index, true, options);
|
|
356
365
|
};
|
|
357
366
|
|
|
358
367
|
/**
|
|
359
368
|
* Validate the update document.
|
|
360
369
|
* @param update - The update document.
|
|
361
370
|
*/
|
|
362
|
-
function validateUpdate(update: Document) {
|
|
363
|
-
if (!hasAtomicOperators(update)) {
|
|
371
|
+
function validateUpdate(update: Document, options: BSONSerializeOptions) {
|
|
372
|
+
if (!hasAtomicOperators(update, options)) {
|
|
364
373
|
throw new MongoAPIError(
|
|
365
374
|
'Client bulk write update models must only contain atomic modifiers (start with $) and must not be empty.'
|
|
366
375
|
);
|
|
@@ -373,13 +382,14 @@ function validateUpdate(update: Document) {
|
|
|
373
382
|
function createUpdateOperation(
|
|
374
383
|
model: ClientUpdateOneModel<Document> | ClientUpdateManyModel<Document>,
|
|
375
384
|
index: number,
|
|
376
|
-
multi: boolean
|
|
385
|
+
multi: boolean,
|
|
386
|
+
options: BSONSerializeOptions
|
|
377
387
|
): ClientUpdateOperation {
|
|
378
388
|
// Update documents provided in UpdateOne and UpdateMany write models are
|
|
379
389
|
// required only to contain atomic modifiers (i.e. keys that start with "$").
|
|
380
390
|
// Drivers MUST throw an error if an update document is empty or if the
|
|
381
391
|
// document's first key does not start with "$".
|
|
382
|
-
validateUpdate(model.update);
|
|
392
|
+
validateUpdate(model.update, options);
|
|
383
393
|
const document: ClientUpdateOperation = {
|
|
384
394
|
update: index,
|
|
385
395
|
multi: multi,
|
|
@@ -398,6 +408,9 @@ function createUpdateOperation(
|
|
|
398
408
|
if (model.collation) {
|
|
399
409
|
document.collation = model.collation;
|
|
400
410
|
}
|
|
411
|
+
if (!multi && 'sort' in model && model.sort != null) {
|
|
412
|
+
document.sort = formatSort(model.sort);
|
|
413
|
+
}
|
|
401
414
|
return document;
|
|
402
415
|
}
|
|
403
416
|
|
|
@@ -410,6 +423,7 @@ export interface ClientReplaceOneOperation {
|
|
|
410
423
|
hint?: Hint;
|
|
411
424
|
upsert?: boolean;
|
|
412
425
|
collation?: CollationOptions;
|
|
426
|
+
sort?: SortForCmd;
|
|
413
427
|
}
|
|
414
428
|
|
|
415
429
|
/**
|
|
@@ -443,6 +457,9 @@ export const buildReplaceOneOperation = (
|
|
|
443
457
|
if (model.collation) {
|
|
444
458
|
document.collation = model.collation;
|
|
445
459
|
}
|
|
460
|
+
if (model.sort != null) {
|
|
461
|
+
document.sort = formatSort(model.sort);
|
|
462
|
+
}
|
|
446
463
|
return document;
|
|
447
464
|
};
|
|
448
465
|
|
|
@@ -450,7 +467,8 @@ export const buildReplaceOneOperation = (
|
|
|
450
467
|
export function buildOperation(
|
|
451
468
|
model: AnyClientBulkWriteModel<Document>,
|
|
452
469
|
index: number,
|
|
453
|
-
pkFactory: PkFactory
|
|
470
|
+
pkFactory: PkFactory,
|
|
471
|
+
options: BSONSerializeOptions
|
|
454
472
|
): Document {
|
|
455
473
|
switch (model.name) {
|
|
456
474
|
case 'insertOne':
|
|
@@ -460,9 +478,9 @@ export function buildOperation(
|
|
|
460
478
|
case 'deleteMany':
|
|
461
479
|
return buildDeleteManyOperation(model, index);
|
|
462
480
|
case 'updateOne':
|
|
463
|
-
return buildUpdateOneOperation(model, index);
|
|
481
|
+
return buildUpdateOneOperation(model, index, options);
|
|
464
482
|
case 'updateMany':
|
|
465
|
-
return buildUpdateManyOperation(model, index);
|
|
483
|
+
return buildUpdateManyOperation(model, index, options);
|
|
466
484
|
case 'replaceOne':
|
|
467
485
|
return buildReplaceOneOperation(model, index);
|
|
468
486
|
}
|
|
@@ -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 */
|
|
@@ -273,7 +273,7 @@ export class FindOneAndUpdateOperation extends FindAndModifyOperation {
|
|
|
273
273
|
throw new MongoInvalidArgumentError('Argument "update" must be an object');
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
if (!hasAtomicOperators(update)) {
|
|
276
|
+
if (!hasAtomicOperators(update, options)) {
|
|
277
277
|
throw new MongoInvalidArgumentError('Update document requires atomic operators');
|
|
278
278
|
}
|
|
279
279
|
|
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
|
/**
|
|
@@ -141,7 +144,7 @@ export class UpdateOneOperation extends UpdateOperation {
|
|
|
141
144
|
options
|
|
142
145
|
);
|
|
143
146
|
|
|
144
|
-
if (!hasAtomicOperators(update)) {
|
|
147
|
+
if (!hasAtomicOperators(update, options)) {
|
|
145
148
|
throw new MongoInvalidArgumentError('Update document requires atomic operators');
|
|
146
149
|
}
|
|
147
150
|
}
|
|
@@ -176,7 +179,7 @@ export class UpdateManyOperation extends UpdateOperation {
|
|
|
176
179
|
options
|
|
177
180
|
);
|
|
178
181
|
|
|
179
|
-
if (!hasAtomicOperators(update)) {
|
|
182
|
+
if (!hasAtomicOperators(update, options)) {
|
|
180
183
|
throw new MongoInvalidArgumentError('Update document requires atomic operators');
|
|
181
184
|
}
|
|
182
185
|
}
|
|
@@ -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/sdam/server.ts
CHANGED
|
@@ -246,8 +246,12 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
closeCheckedOutConnections() {
|
|
250
|
+
return this.pool.closeCheckedOutConnections();
|
|
251
|
+
}
|
|
252
|
+
|
|
249
253
|
/** Destroy the server connection */
|
|
250
|
-
|
|
254
|
+
close(): void {
|
|
251
255
|
if (this.s.state === STATE_CLOSED) {
|
|
252
256
|
return;
|
|
253
257
|
}
|
package/src/sdam/topology.ts
CHANGED
|
@@ -490,6 +490,12 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
490
490
|
}
|
|
491
491
|
}
|
|
492
492
|
|
|
493
|
+
closeCheckedOutConnections() {
|
|
494
|
+
for (const server of this.s.servers.values()) {
|
|
495
|
+
return server.closeCheckedOutConnections();
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
493
499
|
/** Close this topology */
|
|
494
500
|
close(): void {
|
|
495
501
|
if (this.s.state === STATE_CLOSED || this.s.state === STATE_CLOSING) {
|
|
@@ -497,7 +503,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
497
503
|
}
|
|
498
504
|
|
|
499
505
|
for (const server of this.s.servers.values()) {
|
|
500
|
-
|
|
506
|
+
closeServer(server, this);
|
|
501
507
|
}
|
|
502
508
|
|
|
503
509
|
this.s.servers.clear();
|
|
@@ -791,12 +797,12 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
791
797
|
}
|
|
792
798
|
|
|
793
799
|
/** Destroys a server, and removes all event listeners from the instance */
|
|
794
|
-
function
|
|
800
|
+
function closeServer(server: Server, topology: Topology) {
|
|
795
801
|
for (const event of LOCAL_SERVER_EVENTS) {
|
|
796
802
|
server.removeAllListeners(event);
|
|
797
803
|
}
|
|
798
804
|
|
|
799
|
-
server.
|
|
805
|
+
server.close();
|
|
800
806
|
topology.emitAndLog(
|
|
801
807
|
Topology.SERVER_CLOSED,
|
|
802
808
|
new ServerClosedEvent(topology.s.id, server.description.address)
|
|
@@ -903,7 +909,7 @@ function updateServers(topology: Topology, incomingServerDescription?: ServerDes
|
|
|
903
909
|
|
|
904
910
|
// prepare server for garbage collection
|
|
905
911
|
if (server) {
|
|
906
|
-
|
|
912
|
+
closeServer(server, topology);
|
|
907
913
|
}
|
|
908
914
|
}
|
|
909
915
|
}
|
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
|
}
|
package/src/utils.ts
CHANGED
|
@@ -476,7 +476,10 @@ export function calculateDurationInMs(started: number | undefined): number {
|
|
|
476
476
|
}
|
|
477
477
|
|
|
478
478
|
/** @internal */
|
|
479
|
-
export function hasAtomicOperators(
|
|
479
|
+
export function hasAtomicOperators(
|
|
480
|
+
doc: Document | Document[],
|
|
481
|
+
options?: CommandOperationOptions
|
|
482
|
+
): boolean {
|
|
480
483
|
if (Array.isArray(doc)) {
|
|
481
484
|
for (const document of doc) {
|
|
482
485
|
if (hasAtomicOperators(document)) {
|
|
@@ -487,6 +490,23 @@ export function hasAtomicOperators(doc: Document | Document[]): boolean {
|
|
|
487
490
|
}
|
|
488
491
|
|
|
489
492
|
const keys = Object.keys(doc);
|
|
493
|
+
// In this case we need to throw if all the atomic operators are undefined.
|
|
494
|
+
if (options?.ignoreUndefined) {
|
|
495
|
+
let allUndefined = true;
|
|
496
|
+
for (const key of keys) {
|
|
497
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
498
|
+
if (doc[key] !== undefined) {
|
|
499
|
+
allUndefined = false;
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (allUndefined) {
|
|
504
|
+
throw new MongoInvalidArgumentError(
|
|
505
|
+
'Update operations require that all atomic operators have defined values, but none were provided.'
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
490
510
|
return keys.length > 0 && keys[0][0] === '$';
|
|
491
511
|
}
|
|
492
512
|
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MachineWorkflow = void 0;
|
|
4
|
-
const promises_1 = require("timers/promises");
|
|
5
|
-
const utils_1 = require("../../../utils");
|
|
6
|
-
const command_builders_1 = require("./command_builders");
|
|
7
|
-
/** The time to throttle callback calls. */
|
|
8
|
-
const THROTTLE_MS = 100;
|
|
9
|
-
/**
|
|
10
|
-
* Common behaviour for OIDC machine workflows.
|
|
11
|
-
* @internal
|
|
12
|
-
*/
|
|
13
|
-
class MachineWorkflow {
|
|
14
|
-
/**
|
|
15
|
-
* Instantiate the machine workflow.
|
|
16
|
-
*/
|
|
17
|
-
constructor(cache) {
|
|
18
|
-
this.cache = cache;
|
|
19
|
-
this.callback = this.withLock(this.getToken.bind(this));
|
|
20
|
-
this.lastExecutionTime = Date.now() - THROTTLE_MS;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Execute the workflow. Gets the token from the subclass implementation.
|
|
24
|
-
*/
|
|
25
|
-
async execute(connection, credentials) {
|
|
26
|
-
const token = await this.getTokenFromCacheOrEnv(connection, credentials);
|
|
27
|
-
const command = (0, command_builders_1.finishCommandDocument)(token);
|
|
28
|
-
await connection.command((0, utils_1.ns)(credentials.source), command, undefined);
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Reauthenticate on a machine workflow just grabs the token again since the server
|
|
32
|
-
* has said the current access token is invalid or expired.
|
|
33
|
-
*/
|
|
34
|
-
async reauthenticate(connection, credentials) {
|
|
35
|
-
if (this.cache.hasAccessToken) {
|
|
36
|
-
// Reauthentication implies the token has expired.
|
|
37
|
-
if (connection.accessToken === this.cache.getAccessToken()) {
|
|
38
|
-
// If connection's access token is the same as the cache's, remove
|
|
39
|
-
// the token from the cache and connection.
|
|
40
|
-
this.cache.removeAccessToken();
|
|
41
|
-
delete connection.accessToken;
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
// If the connection's access token is different from the cache's, set
|
|
45
|
-
// the cache's token on the connection and do not remove from the
|
|
46
|
-
// cache.
|
|
47
|
-
connection.accessToken = this.cache.getAccessToken();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
await this.execute(connection, credentials);
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Get the document to add for speculative authentication.
|
|
54
|
-
*/
|
|
55
|
-
async speculativeAuth(connection, credentials) {
|
|
56
|
-
// The spec states only cached access tokens can use speculative auth.
|
|
57
|
-
if (!this.cache.hasAccessToken) {
|
|
58
|
-
return {};
|
|
59
|
-
}
|
|
60
|
-
const token = await this.getTokenFromCacheOrEnv(connection, credentials);
|
|
61
|
-
const document = (0, command_builders_1.finishCommandDocument)(token);
|
|
62
|
-
document.db = credentials.source;
|
|
63
|
-
return { speculativeAuthenticate: document };
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Get the token from the cache or environment.
|
|
67
|
-
*/
|
|
68
|
-
async getTokenFromCacheOrEnv(connection, credentials) {
|
|
69
|
-
if (this.cache.hasAccessToken) {
|
|
70
|
-
const token = this.cache.getAccessToken();
|
|
71
|
-
// New connections won't have an access token so ensure we set here.
|
|
72
|
-
if (!connection.accessToken) {
|
|
73
|
-
connection.accessToken = token;
|
|
74
|
-
}
|
|
75
|
-
return token;
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
const token = await this.callback(credentials);
|
|
79
|
-
this.cache.put({ accessToken: token.access_token, expiresInSeconds: token.expires_in });
|
|
80
|
-
// Put the access token on the connection as well.
|
|
81
|
-
connection.accessToken = token.access_token;
|
|
82
|
-
return token.access_token;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Ensure the callback is only executed one at a time, and throttled to
|
|
87
|
-
* only once per 100ms.
|
|
88
|
-
*/
|
|
89
|
-
withLock(callback) {
|
|
90
|
-
let lock = Promise.resolve();
|
|
91
|
-
return async (credentials) => {
|
|
92
|
-
// We do this to ensure that we would never return the result of the
|
|
93
|
-
// previous lock, only the current callback's value would get returned.
|
|
94
|
-
await lock;
|
|
95
|
-
lock = lock
|
|
96
|
-
.catch(() => null)
|
|
97
|
-
.then(async () => {
|
|
98
|
-
const difference = Date.now() - this.lastExecutionTime;
|
|
99
|
-
if (difference <= THROTTLE_MS) {
|
|
100
|
-
await (0, promises_1.setTimeout)(THROTTLE_MS - difference);
|
|
101
|
-
}
|
|
102
|
-
this.lastExecutionTime = Date.now();
|
|
103
|
-
return await callback(credentials);
|
|
104
|
-
});
|
|
105
|
-
return await lock;
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
exports.MachineWorkflow = MachineWorkflow;
|
|
110
|
-
//# sourceMappingURL=machine_workflow.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"machine_workflow.js","sourceRoot":"","sources":["../../../../src/cmap/auth/mongodb_oidc/machine_workflow.ts"],"names":[],"mappings":"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"}
|