mongodb 5.4.0 → 5.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/admin.js +5 -5
- package/lib/admin.js.map +1 -1
- package/lib/bulk/common.js +4 -4
- package/lib/bulk/common.js.map +1 -1
- package/lib/change_stream.js +2 -2
- package/lib/change_stream.js.map +1 -1
- package/lib/cmap/connection_pool.js +21 -17
- package/lib/cmap/connection_pool.js.map +1 -1
- package/lib/cmap/handshake/client_metadata.js +1 -1
- package/lib/cmap/handshake/client_metadata.js.map +1 -1
- package/lib/cmap/wire_protocol/constants.js +3 -1
- package/lib/cmap/wire_protocol/constants.js.map +1 -1
- package/lib/collection.js +108 -33
- package/lib/collection.js.map +1 -1
- package/lib/cursor/list_collections_cursor.js +2 -2
- package/lib/cursor/list_collections_cursor.js.map +1 -1
- package/lib/cursor/list_indexes_cursor.js +2 -2
- package/lib/cursor/list_indexes_cursor.js.map +1 -1
- package/lib/cursor/list_search_indexes_cursor.js +14 -0
- package/lib/cursor/list_search_indexes_cursor.js.map +1 -0
- package/lib/cursor/run_command_cursor.js +94 -0
- package/lib/cursor/run_command_cursor.js.map +1 -0
- package/lib/db.js +29 -17
- package/lib/db.js.map +1 -1
- package/lib/error.js +16 -4
- package/lib/error.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/mongo_client.js +5 -7
- package/lib/mongo_client.js.map +1 -1
- package/lib/mongo_types.js +6 -1
- package/lib/mongo_types.js.map +1 -1
- package/lib/operations/create_collection.js +10 -3
- package/lib/operations/create_collection.js.map +1 -1
- package/lib/operations/drop.js +2 -3
- package/lib/operations/drop.js.map +1 -1
- package/lib/operations/search_indexes/create.js +29 -0
- package/lib/operations/search_indexes/create.js.map +1 -0
- package/lib/operations/search_indexes/drop.js +30 -0
- package/lib/operations/search_indexes/drop.js.map +1 -0
- package/lib/operations/search_indexes/update.js +30 -0
- package/lib/operations/search_indexes/update.js.map +1 -0
- package/lib/sdam/monitor.js +1 -1
- package/lib/sdam/monitor.js.map +1 -1
- package/lib/sdam/server.js +31 -19
- package/lib/sdam/server.js.map +1 -1
- package/lib/sdam/topology.js +4 -3
- package/lib/sdam/topology.js.map +1 -1
- package/lib/sessions.js +2 -2
- package/lib/sessions.js.map +1 -1
- package/lib/utils.js +19 -7
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +112 -16
- package/package.json +17 -17
- package/src/admin.ts +5 -5
- package/src/bulk/common.ts +4 -4
- package/src/change_stream.ts +2 -2
- package/src/cmap/connection_pool.ts +26 -18
- package/src/cmap/handshake/client_metadata.ts +2 -1
- package/src/cmap/wire_protocol/constants.ts +2 -0
- package/src/collection.ts +163 -41
- package/src/cursor/abstract_cursor.ts +1 -1
- package/src/cursor/list_collections_cursor.ts +2 -2
- package/src/cursor/list_indexes_cursor.ts +2 -2
- package/src/cursor/list_search_indexes_cursor.ts +20 -0
- package/src/cursor/run_command_cursor.ts +140 -0
- package/src/db.ts +34 -21
- package/src/deps.ts +2 -2
- package/src/error.ts +20 -3
- package/src/index.ts +9 -0
- package/src/mongo_client.ts +25 -17
- package/src/mongo_types.ts +16 -2
- package/src/operations/create_collection.ts +19 -5
- package/src/operations/drop.ts +2 -3
- package/src/operations/search_indexes/create.ts +48 -0
- package/src/operations/search_indexes/drop.ts +35 -0
- package/src/operations/search_indexes/update.ts +36 -0
- package/src/sdam/monitor.ts +1 -1
- package/src/sdam/server.ts +38 -23
- package/src/sdam/topology.ts +8 -3
- package/src/sessions.ts +2 -2
- package/src/utils.ts +18 -10
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Collection } from '../collection';
|
|
2
|
+
import type { AggregateOptions } from '../operations/aggregate';
|
|
3
|
+
import { AggregationCursor } from './aggregation_cursor';
|
|
4
|
+
|
|
5
|
+
/** @internal */
|
|
6
|
+
export type ListSearchIndexesOptions = AggregateOptions;
|
|
7
|
+
|
|
8
|
+
/** @internal */
|
|
9
|
+
export class ListSearchIndexesCursor extends AggregationCursor<{ name: string }> {
|
|
10
|
+
/** @internal */
|
|
11
|
+
constructor(
|
|
12
|
+
{ fullNamespace: ns, client }: Collection,
|
|
13
|
+
name: string | null,
|
|
14
|
+
options: ListSearchIndexesOptions = {}
|
|
15
|
+
) {
|
|
16
|
+
const pipeline =
|
|
17
|
+
name == null ? [{ $listSearchIndexes: {} }] : [{ $listSearchIndexes: { name } }];
|
|
18
|
+
super(client, ns, pipeline, options);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { BSONSerializeOptions, Document, Long } from '../bson';
|
|
2
|
+
import type { Db } from '../db';
|
|
3
|
+
import { MongoAPIError, MongoUnexpectedServerResponseError } from '../error';
|
|
4
|
+
import { executeOperation, ExecutionResult } from '../operations/execute_operation';
|
|
5
|
+
import { GetMoreOperation } from '../operations/get_more';
|
|
6
|
+
import { RunCommandOperation } from '../operations/run_command';
|
|
7
|
+
import type { ReadConcernLike } from '../read_concern';
|
|
8
|
+
import type { ReadPreferenceLike } from '../read_preference';
|
|
9
|
+
import type { ClientSession } from '../sessions';
|
|
10
|
+
import { Callback, ns } from '../utils';
|
|
11
|
+
import { AbstractCursor } from './abstract_cursor';
|
|
12
|
+
|
|
13
|
+
/** @public */
|
|
14
|
+
export type RunCursorCommandOptions = {
|
|
15
|
+
readPreference?: ReadPreferenceLike;
|
|
16
|
+
session?: ClientSession;
|
|
17
|
+
} & BSONSerializeOptions;
|
|
18
|
+
|
|
19
|
+
/** @internal */
|
|
20
|
+
type RunCursorCommandResponse = {
|
|
21
|
+
cursor: { id: bigint | Long | number; ns: string; firstBatch: Document[] };
|
|
22
|
+
ok: 1;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** @public */
|
|
26
|
+
export class RunCommandCursor extends AbstractCursor {
|
|
27
|
+
public readonly command: Readonly<Record<string, any>>;
|
|
28
|
+
public readonly getMoreOptions: {
|
|
29
|
+
comment?: any;
|
|
30
|
+
maxAwaitTimeMS?: number;
|
|
31
|
+
batchSize?: number;
|
|
32
|
+
} = {};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Controls the `getMore.comment` field
|
|
36
|
+
* @param comment - any BSON value
|
|
37
|
+
*/
|
|
38
|
+
public setComment(comment: any): this {
|
|
39
|
+
this.getMoreOptions.comment = comment;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Controls the `getMore.maxTimeMS` field. Only valid when cursor is tailable await
|
|
45
|
+
* @param maxTimeMS - the number of milliseconds to wait for new data
|
|
46
|
+
*/
|
|
47
|
+
public setMaxTimeMS(maxTimeMS: number): this {
|
|
48
|
+
this.getMoreOptions.maxAwaitTimeMS = maxTimeMS;
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Controls the `getMore.batchSize` field
|
|
54
|
+
* @param maxTimeMS - the number documents to return in the `nextBatch`
|
|
55
|
+
*/
|
|
56
|
+
public setBatchSize(batchSize: number): this {
|
|
57
|
+
this.getMoreOptions.batchSize = batchSize;
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Unsupported for RunCommandCursor */
|
|
62
|
+
public override clone(): never {
|
|
63
|
+
throw new MongoAPIError('Clone not supported, create a new cursor with db.runCursorCommand');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Unsupported for RunCommandCursor: readConcern must be configured directly on command document */
|
|
67
|
+
public override withReadConcern(_: ReadConcernLike): never {
|
|
68
|
+
throw new MongoAPIError(
|
|
69
|
+
'RunCommandCursor does not support readConcern it must be attached to the command being run'
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** Unsupported for RunCommandCursor: various cursor flags must be configured directly on command document */
|
|
74
|
+
public override addCursorFlag(_: string, __: boolean): never {
|
|
75
|
+
throw new MongoAPIError(
|
|
76
|
+
'RunCommandCursor does not support cursor flags, they must be attached to the command being run'
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Unsupported for RunCommandCursor: maxTimeMS must be configured directly on command document */
|
|
81
|
+
public override maxTimeMS(_: number): never {
|
|
82
|
+
throw new MongoAPIError(
|
|
83
|
+
'maxTimeMS must be configured on the command document directly, to configure getMore.maxTimeMS use cursor.setMaxTimeMS()'
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Unsupported for RunCommandCursor: batchSize must be configured directly on command document */
|
|
88
|
+
public override batchSize(_: number): never {
|
|
89
|
+
throw new MongoAPIError(
|
|
90
|
+
'batchSize must be configured on the command document directly, to configure getMore.batchSize use cursor.setBatchSize()'
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** @internal */
|
|
95
|
+
private db: Db;
|
|
96
|
+
|
|
97
|
+
/** @internal */
|
|
98
|
+
constructor(db: Db, command: Document, options: RunCursorCommandOptions = {}) {
|
|
99
|
+
super(db.client, ns(db.namespace), options);
|
|
100
|
+
this.db = db;
|
|
101
|
+
this.command = Object.freeze({ ...command });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** @internal */
|
|
105
|
+
protected _initialize(session: ClientSession, callback: Callback<ExecutionResult>) {
|
|
106
|
+
const operation = new RunCommandOperation<RunCursorCommandResponse>(this.db, this.command, {
|
|
107
|
+
...this.cursorOptions,
|
|
108
|
+
session: session,
|
|
109
|
+
readPreference: this.cursorOptions.readPreference
|
|
110
|
+
});
|
|
111
|
+
executeOperation(this.client, operation).then(
|
|
112
|
+
response => {
|
|
113
|
+
if (response.cursor == null) {
|
|
114
|
+
callback(
|
|
115
|
+
new MongoUnexpectedServerResponseError('Expected server to respond with cursor')
|
|
116
|
+
);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
callback(undefined, {
|
|
120
|
+
server: operation.server,
|
|
121
|
+
session,
|
|
122
|
+
response
|
|
123
|
+
});
|
|
124
|
+
},
|
|
125
|
+
err => callback(err)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** @internal */
|
|
130
|
+
override _getMore(_batchSize: number, callback: Callback<Document>) {
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
132
|
+
const getMoreOperation = new GetMoreOperation(this.namespace, this.id!, this.server!, {
|
|
133
|
+
...this.cursorOptions,
|
|
134
|
+
session: this.session,
|
|
135
|
+
...this.getMoreOptions
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
executeOperation(this.client, getMoreOperation, callback);
|
|
139
|
+
}
|
|
140
|
+
}
|
package/src/db.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { Collection, CollectionOptions } from './collection';
|
|
|
5
5
|
import * as CONSTANTS from './constants';
|
|
6
6
|
import { AggregationCursor } from './cursor/aggregation_cursor';
|
|
7
7
|
import { ListCollectionsCursor } from './cursor/list_collections_cursor';
|
|
8
|
+
import { RunCommandCursor, type RunCursorCommandOptions } from './cursor/run_command_cursor';
|
|
8
9
|
import { MongoAPIError, MongoInvalidArgumentError } from './error';
|
|
9
10
|
import type { MongoClient, PkFactory } from './mongo_client';
|
|
10
11
|
import type { TODO_NODE_3286 } from './mongo_types';
|
|
@@ -69,7 +70,6 @@ const DB_OPTIONS_ALLOW_LIST = [
|
|
|
69
70
|
|
|
70
71
|
/** @internal */
|
|
71
72
|
export interface DbPrivate {
|
|
72
|
-
client: MongoClient;
|
|
73
73
|
options?: DbOptions;
|
|
74
74
|
readPreference?: ReadPreference;
|
|
75
75
|
pkFactory: PkFactory;
|
|
@@ -121,6 +121,9 @@ export class Db {
|
|
|
121
121
|
/** @internal */
|
|
122
122
|
s: DbPrivate;
|
|
123
123
|
|
|
124
|
+
/** @internal */
|
|
125
|
+
readonly client: MongoClient;
|
|
126
|
+
|
|
124
127
|
public static SYSTEM_NAMESPACE_COLLECTION = CONSTANTS.SYSTEM_NAMESPACE_COLLECTION;
|
|
125
128
|
public static SYSTEM_INDEX_COLLECTION = CONSTANTS.SYSTEM_INDEX_COLLECTION;
|
|
126
129
|
public static SYSTEM_PROFILE_COLLECTION = CONSTANTS.SYSTEM_PROFILE_COLLECTION;
|
|
@@ -146,8 +149,6 @@ export class Db {
|
|
|
146
149
|
|
|
147
150
|
// Internal state of the db object
|
|
148
151
|
this.s = {
|
|
149
|
-
// Client
|
|
150
|
-
client,
|
|
151
152
|
// Options
|
|
152
153
|
options,
|
|
153
154
|
// Unpack read preference
|
|
@@ -162,6 +163,8 @@ export class Db {
|
|
|
162
163
|
// Namespace
|
|
163
164
|
namespace: new MongoDBNamespace(databaseName)
|
|
164
165
|
};
|
|
166
|
+
|
|
167
|
+
this.client = client;
|
|
165
168
|
}
|
|
166
169
|
|
|
167
170
|
get databaseName(): string {
|
|
@@ -190,7 +193,7 @@ export class Db {
|
|
|
190
193
|
*/
|
|
191
194
|
get readPreference(): ReadPreference {
|
|
192
195
|
if (this.s.readPreference == null) {
|
|
193
|
-
return this.
|
|
196
|
+
return this.client.readPreference;
|
|
194
197
|
}
|
|
195
198
|
|
|
196
199
|
return this.s.readPreference;
|
|
@@ -221,7 +224,7 @@ export class Db {
|
|
|
221
224
|
options?: CreateCollectionOptions
|
|
222
225
|
): Promise<Collection<TSchema>> {
|
|
223
226
|
return executeOperation(
|
|
224
|
-
this.
|
|
227
|
+
this.client,
|
|
225
228
|
new CreateCollectionOperation(this, name, resolveOptions(this, options)) as TODO_NODE_3286
|
|
226
229
|
);
|
|
227
230
|
}
|
|
@@ -253,7 +256,7 @@ export class Db {
|
|
|
253
256
|
*/
|
|
254
257
|
async command(command: Document, options?: RunCommandOptions): Promise<Document> {
|
|
255
258
|
// Intentionally, we do not inherit options from parent for this operation.
|
|
256
|
-
return executeOperation(this.
|
|
259
|
+
return executeOperation(this.client, new RunCommandOperation(this, command, options));
|
|
257
260
|
}
|
|
258
261
|
|
|
259
262
|
/**
|
|
@@ -267,7 +270,7 @@ export class Db {
|
|
|
267
270
|
options?: AggregateOptions
|
|
268
271
|
): AggregationCursor<T> {
|
|
269
272
|
return new AggregationCursor(
|
|
270
|
-
this.
|
|
273
|
+
this.client,
|
|
271
274
|
this.s.namespace,
|
|
272
275
|
pipeline,
|
|
273
276
|
resolveOptions(this, options)
|
|
@@ -301,10 +304,7 @@ export class Db {
|
|
|
301
304
|
* @param options - Optional settings for the command
|
|
302
305
|
*/
|
|
303
306
|
async stats(options?: DbStatsOptions): Promise<Document> {
|
|
304
|
-
return executeOperation(
|
|
305
|
-
this.s.client,
|
|
306
|
-
new DbStatsOperation(this, resolveOptions(this, options))
|
|
307
|
-
);
|
|
307
|
+
return executeOperation(this.client, new DbStatsOperation(this, resolveOptions(this, options)));
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
/**
|
|
@@ -351,7 +351,7 @@ export class Db {
|
|
|
351
351
|
): Promise<Collection<TSchema>> {
|
|
352
352
|
// Intentionally, we do not inherit options from parent for this operation.
|
|
353
353
|
return executeOperation(
|
|
354
|
-
this.
|
|
354
|
+
this.client,
|
|
355
355
|
new RenameOperation(
|
|
356
356
|
this.collection<TSchema>(fromCollection) as TODO_NODE_3286,
|
|
357
357
|
toCollection,
|
|
@@ -368,7 +368,7 @@ export class Db {
|
|
|
368
368
|
*/
|
|
369
369
|
async dropCollection(name: string, options?: DropCollectionOptions): Promise<boolean> {
|
|
370
370
|
return executeOperation(
|
|
371
|
-
this.
|
|
371
|
+
this.client,
|
|
372
372
|
new DropCollectionOperation(this, name, resolveOptions(this, options))
|
|
373
373
|
);
|
|
374
374
|
}
|
|
@@ -380,7 +380,7 @@ export class Db {
|
|
|
380
380
|
*/
|
|
381
381
|
async dropDatabase(options?: DropDatabaseOptions): Promise<boolean> {
|
|
382
382
|
return executeOperation(
|
|
383
|
-
this.
|
|
383
|
+
this.client,
|
|
384
384
|
new DropDatabaseOperation(this, resolveOptions(this, options))
|
|
385
385
|
);
|
|
386
386
|
}
|
|
@@ -392,7 +392,7 @@ export class Db {
|
|
|
392
392
|
*/
|
|
393
393
|
async collections(options?: ListCollectionsOptions): Promise<Collection[]> {
|
|
394
394
|
return executeOperation(
|
|
395
|
-
this.
|
|
395
|
+
this.client,
|
|
396
396
|
new CollectionsOperation(this, resolveOptions(this, options))
|
|
397
397
|
);
|
|
398
398
|
}
|
|
@@ -410,7 +410,7 @@ export class Db {
|
|
|
410
410
|
options?: CreateIndexesOptions
|
|
411
411
|
): Promise<string> {
|
|
412
412
|
return executeOperation(
|
|
413
|
-
this.
|
|
413
|
+
this.client,
|
|
414
414
|
new CreateIndexOperation(this, name, indexSpec, resolveOptions(this, options))
|
|
415
415
|
);
|
|
416
416
|
}
|
|
@@ -437,7 +437,7 @@ export class Db {
|
|
|
437
437
|
: undefined;
|
|
438
438
|
const password = typeof passwordOrOptions === 'string' ? passwordOrOptions : undefined;
|
|
439
439
|
return executeOperation(
|
|
440
|
-
this.
|
|
440
|
+
this.client,
|
|
441
441
|
new AddUserOperation(this, username, password, resolveOptions(this, options))
|
|
442
442
|
);
|
|
443
443
|
}
|
|
@@ -450,7 +450,7 @@ export class Db {
|
|
|
450
450
|
*/
|
|
451
451
|
async removeUser(username: string, options?: RemoveUserOptions): Promise<boolean> {
|
|
452
452
|
return executeOperation(
|
|
453
|
-
this.
|
|
453
|
+
this.client,
|
|
454
454
|
new RemoveUserOperation(this, username, resolveOptions(this, options))
|
|
455
455
|
);
|
|
456
456
|
}
|
|
@@ -466,7 +466,7 @@ export class Db {
|
|
|
466
466
|
options?: SetProfilingLevelOptions
|
|
467
467
|
): Promise<ProfilingLevel> {
|
|
468
468
|
return executeOperation(
|
|
469
|
-
this.
|
|
469
|
+
this.client,
|
|
470
470
|
new SetProfilingLevelOperation(this, level, resolveOptions(this, options))
|
|
471
471
|
);
|
|
472
472
|
}
|
|
@@ -478,7 +478,7 @@ export class Db {
|
|
|
478
478
|
*/
|
|
479
479
|
async profilingLevel(options?: ProfilingLevelOptions): Promise<string> {
|
|
480
480
|
return executeOperation(
|
|
481
|
-
this.
|
|
481
|
+
this.client,
|
|
482
482
|
new ProfilingLevelOperation(this, resolveOptions(this, options))
|
|
483
483
|
);
|
|
484
484
|
}
|
|
@@ -491,7 +491,7 @@ export class Db {
|
|
|
491
491
|
*/
|
|
492
492
|
async indexInformation(name: string, options?: IndexInformationOptions): Promise<Document> {
|
|
493
493
|
return executeOperation(
|
|
494
|
-
this.
|
|
494
|
+
this.client,
|
|
495
495
|
new IndexInformationOperation(this, name, resolveOptions(this, options))
|
|
496
496
|
);
|
|
497
497
|
}
|
|
@@ -523,6 +523,19 @@ export class Db {
|
|
|
523
523
|
|
|
524
524
|
return new ChangeStream<TSchema, TChange>(this, pipeline, resolveOptions(this, options));
|
|
525
525
|
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* A low level cursor API providing basic driver functionality:
|
|
529
|
+
* - ClientSession management
|
|
530
|
+
* - ReadPreference for server selection
|
|
531
|
+
* - Running getMores automatically when a local batch is exhausted
|
|
532
|
+
*
|
|
533
|
+
* @param command - The command that will start a cursor on the server.
|
|
534
|
+
* @param options - Configurations for running the command, bson options will apply to getMores
|
|
535
|
+
*/
|
|
536
|
+
runCursorCommand(command: Document, options?: RunCursorCommandOptions): RunCommandCursor {
|
|
537
|
+
return new RunCommandCursor(this, command, options);
|
|
538
|
+
}
|
|
526
539
|
}
|
|
527
540
|
|
|
528
541
|
// TODO(NODE-3484): Refactor into MongoDBNamespace
|
package/src/deps.ts
CHANGED
|
@@ -309,11 +309,11 @@ export interface AutoEncryptionOptions {
|
|
|
309
309
|
* Other validation rules in the JSON schema will not be enforced by the driver and will result in an error.
|
|
310
310
|
*/
|
|
311
311
|
schemaMap?: Document;
|
|
312
|
-
/**
|
|
312
|
+
/** Supply a schema for the encrypted fields in the document */
|
|
313
313
|
encryptedFieldsMap?: Document;
|
|
314
314
|
/** Allows the user to bypass auto encryption, maintaining implicit decryption */
|
|
315
315
|
bypassAutoEncryption?: boolean;
|
|
316
|
-
/**
|
|
316
|
+
/** Allows users to bypass query analysis */
|
|
317
317
|
bypassQueryAnalysis?: boolean;
|
|
318
318
|
options?: {
|
|
319
319
|
/** An optional hook to catch logging messages from the underlying encryption engine */
|
package/src/error.ts
CHANGED
|
@@ -108,6 +108,10 @@ export interface ErrorDescription extends Document {
|
|
|
108
108
|
errInfo?: Document;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
function isAggregateError(e: Error): e is Error & { errors: Error[] } {
|
|
112
|
+
return 'errors' in e && Array.isArray(e.errors);
|
|
113
|
+
}
|
|
114
|
+
|
|
111
115
|
/**
|
|
112
116
|
* @public
|
|
113
117
|
* @category Error
|
|
@@ -131,15 +135,28 @@ export class MongoError extends Error {
|
|
|
131
135
|
cause?: Error; // depending on the node version, this may or may not exist on the base
|
|
132
136
|
|
|
133
137
|
constructor(message: string | Error) {
|
|
138
|
+
super(MongoError.buildErrorMessage(message));
|
|
134
139
|
if (message instanceof Error) {
|
|
135
|
-
super(message.message);
|
|
136
140
|
this.cause = message;
|
|
137
|
-
} else {
|
|
138
|
-
super(message);
|
|
139
141
|
}
|
|
142
|
+
|
|
140
143
|
this[kErrorLabels] = new Set();
|
|
141
144
|
}
|
|
142
145
|
|
|
146
|
+
/** @internal */
|
|
147
|
+
private static buildErrorMessage(e: Error | string): string {
|
|
148
|
+
if (typeof e === 'string') {
|
|
149
|
+
return e;
|
|
150
|
+
}
|
|
151
|
+
if (isAggregateError(e) && e.message.length === 0) {
|
|
152
|
+
return e.errors.length === 0
|
|
153
|
+
? 'AggregateError has an empty errors array. Please check the `cause` property for more information.'
|
|
154
|
+
: e.errors.map(({ message }) => message).join(', ');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return e.message;
|
|
158
|
+
}
|
|
159
|
+
|
|
143
160
|
override get name(): string {
|
|
144
161
|
return 'MongoError';
|
|
145
162
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { AggregationCursor } from './cursor/aggregation_cursor';
|
|
|
8
8
|
import { FindCursor } from './cursor/find_cursor';
|
|
9
9
|
import { ListCollectionsCursor } from './cursor/list_collections_cursor';
|
|
10
10
|
import { ListIndexesCursor } from './cursor/list_indexes_cursor';
|
|
11
|
+
import type { RunCommandCursor } from './cursor/run_command_cursor';
|
|
11
12
|
import { Db } from './db';
|
|
12
13
|
import { GridFSBucket } from './gridfs';
|
|
13
14
|
import { GridFSBucketReadStream } from './gridfs/download';
|
|
@@ -87,6 +88,7 @@ export {
|
|
|
87
88
|
ListIndexesCursor,
|
|
88
89
|
MongoClient,
|
|
89
90
|
OrderedBulkOperation,
|
|
91
|
+
RunCommandCursor,
|
|
90
92
|
UnorderedBulkOperation
|
|
91
93
|
};
|
|
92
94
|
|
|
@@ -275,6 +277,11 @@ export type {
|
|
|
275
277
|
ChangeStreamAggregateRawResult,
|
|
276
278
|
ChangeStreamCursorOptions
|
|
277
279
|
} from './cursor/change_stream_cursor';
|
|
280
|
+
export type {
|
|
281
|
+
ListSearchIndexesCursor,
|
|
282
|
+
ListSearchIndexesOptions
|
|
283
|
+
} from './cursor/list_search_indexes_cursor';
|
|
284
|
+
export type { RunCursorCommandOptions } from './cursor/run_command_cursor';
|
|
278
285
|
export type { DbOptions, DbPrivate } from './db';
|
|
279
286
|
export type { AutoEncrypter, AutoEncryptionOptions, AutoEncryptionTlsOptions } from './deps';
|
|
280
287
|
export type { Encrypter, EncrypterOptions } from './encrypter';
|
|
@@ -415,6 +422,7 @@ export type { ProfilingLevelOptions } from './operations/profiling_level';
|
|
|
415
422
|
export type { RemoveUserOptions } from './operations/remove_user';
|
|
416
423
|
export type { RenameOptions } from './operations/rename';
|
|
417
424
|
export type { RunCommandOptions } from './operations/run_command';
|
|
425
|
+
export type { SearchIndexDescription } from './operations/search_indexes/create';
|
|
418
426
|
export type { SetProfilingLevelOptions } from './operations/set_profiling_level';
|
|
419
427
|
export type {
|
|
420
428
|
CollStats,
|
|
@@ -486,6 +494,7 @@ export type {
|
|
|
486
494
|
EventEmitterWithState,
|
|
487
495
|
HostAddress,
|
|
488
496
|
List,
|
|
497
|
+
MongoDBCollectionNamespace,
|
|
489
498
|
MongoDBNamespace
|
|
490
499
|
} from './utils';
|
|
491
500
|
export type { W, WriteConcernOptions, WriteConcernSettings } from './write_concern';
|
package/src/mongo_client.ts
CHANGED
|
@@ -325,7 +325,7 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
|
|
|
325
325
|
/** @internal */
|
|
326
326
|
topology?: Topology;
|
|
327
327
|
/** @internal */
|
|
328
|
-
readonly mongoLogger: MongoLogger;
|
|
328
|
+
override readonly mongoLogger: MongoLogger;
|
|
329
329
|
/** @internal */
|
|
330
330
|
private connectionLock?: Promise<this>;
|
|
331
331
|
|
|
@@ -471,23 +471,21 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> {
|
|
|
471
471
|
}
|
|
472
472
|
}
|
|
473
473
|
|
|
474
|
-
|
|
474
|
+
this.topology = new Topology(this, options.hosts, options);
|
|
475
475
|
// Events can be emitted before initialization is complete so we have to
|
|
476
476
|
// save the reference to the topology on the client ASAP if the event handlers need to access it
|
|
477
|
-
this.topology = topology;
|
|
478
|
-
topology.client = this;
|
|
479
477
|
|
|
480
|
-
topology.once(Topology.OPEN, () => this.emit('open', this));
|
|
478
|
+
this.topology.once(Topology.OPEN, () => this.emit('open', this));
|
|
481
479
|
|
|
482
480
|
for (const event of MONGO_CLIENT_EVENTS) {
|
|
483
|
-
topology.on(event, (...args: any[]) => this.emit(event, ...(args as any)));
|
|
481
|
+
this.topology.on(event, (...args: any[]) => this.emit(event, ...(args as any)));
|
|
484
482
|
}
|
|
485
483
|
|
|
486
484
|
const topologyConnect = async () => {
|
|
487
485
|
try {
|
|
488
|
-
await promisify(callback => topology
|
|
486
|
+
await promisify(callback => this.topology?.connect(options, callback))();
|
|
489
487
|
} catch (error) {
|
|
490
|
-
topology
|
|
488
|
+
this.topology?.close({ force: true });
|
|
491
489
|
throw error;
|
|
492
490
|
}
|
|
493
491
|
};
|
|
@@ -774,19 +772,29 @@ export interface MongoOptions
|
|
|
774
772
|
/**
|
|
775
773
|
* # NOTE ABOUT TLS Options
|
|
776
774
|
*
|
|
777
|
-
* If
|
|
775
|
+
* If `tls` is provided as an option, it is equivalent to setting the `ssl` option.
|
|
776
|
+
*
|
|
777
|
+
* NodeJS native TLS options are passed through to the socket and retain their original types.
|
|
778
778
|
*
|
|
779
779
|
* ### Additional options:
|
|
780
780
|
*
|
|
781
|
-
* |
|
|
782
|
-
*
|
|
783
|
-
* | `ca`
|
|
784
|
-
* | `crl`
|
|
785
|
-
* | `cert`
|
|
786
|
-
* | `key`
|
|
787
|
-
* | `passphrase`
|
|
788
|
-
* | `rejectUnauthorized` | `sslValidate`
|
|
781
|
+
* | nodejs native option | driver spec compliant option name | legacy option name | driver option type |
|
|
782
|
+
* |:----------------------|:----------------------------------------------|:-------------------|:-------------------|
|
|
783
|
+
* | `ca` | `tlsCAFile` | `sslCA` | `string` |
|
|
784
|
+
* | `crl` | N/A | `sslCRL` | `string` |
|
|
785
|
+
* | `cert` | `tlsCertificateFile`, `tlsCertificateKeyFile` | `sslCert` | `string` |
|
|
786
|
+
* | `key` | `tlsCertificateKeyFile` | `sslKey` | `string` |
|
|
787
|
+
* | `passphrase` | `tlsCertificateKeyFilePassword` | `sslPass` | `string` |
|
|
788
|
+
* | `rejectUnauthorized` | `tlsAllowInvalidCertificates` | `sslValidate` | `boolean` |
|
|
789
|
+
* | `checkServerIdentity` | `tlsAllowInvalidHostnames` | N/A | `boolean` |
|
|
790
|
+
* | see note below | `tlsInsecure` | N/A | `boolean` |
|
|
791
|
+
*
|
|
792
|
+
* If `tlsInsecure` is set to `true`, then it will set the node native options `checkServerIdentity`
|
|
793
|
+
* to a no-op and `rejectUnauthorized` to `false`.
|
|
789
794
|
*
|
|
795
|
+
* If `tlsInsecure` is set to `false`, then it will set the node native options `checkServerIdentity`
|
|
796
|
+
* to a no-op and `rejectUnauthorized` to the inverse value of `tlsAllowInvalidCertificates`. If
|
|
797
|
+
* `tlsAllowInvalidCertificates` is not set, then `rejectUnauthorized` will be set to `true`.
|
|
790
798
|
*/
|
|
791
799
|
tls: boolean;
|
|
792
800
|
|
package/src/mongo_types.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
ObjectId,
|
|
13
13
|
Timestamp
|
|
14
14
|
} from './bson';
|
|
15
|
+
import type { MongoLoggableComponent, MongoLogger } from './mongo_logger';
|
|
15
16
|
import type { Sort } from './sort';
|
|
16
17
|
|
|
17
18
|
/** @internal */
|
|
@@ -397,8 +398,21 @@ export declare interface TypedEventEmitter<Events extends EventsDescription> ext
|
|
|
397
398
|
* Typescript type safe event emitter
|
|
398
399
|
* @public
|
|
399
400
|
*/
|
|
400
|
-
|
|
401
|
-
export class TypedEventEmitter<Events extends EventsDescription> extends EventEmitter {
|
|
401
|
+
|
|
402
|
+
export class TypedEventEmitter<Events extends EventsDescription> extends EventEmitter {
|
|
403
|
+
/** @internal */
|
|
404
|
+
protected mongoLogger?: MongoLogger;
|
|
405
|
+
/** @internal */
|
|
406
|
+
protected component?: MongoLoggableComponent;
|
|
407
|
+
/** @internal */
|
|
408
|
+
protected emitAndLog<EventKey extends keyof Events>(
|
|
409
|
+
event: EventKey | symbol,
|
|
410
|
+
...args: Parameters<Events[EventKey]>
|
|
411
|
+
): void {
|
|
412
|
+
this.emit(event, ...args);
|
|
413
|
+
if (this.component) this.mongoLogger?.debug(this.component, args[0]);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
402
416
|
|
|
403
417
|
/** @public */
|
|
404
418
|
export class CancellationToken extends TypedEventEmitter<{ cancel(): void }> {}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { Document } from '../bson';
|
|
2
|
+
import {
|
|
3
|
+
MIN_SUPPORTED_QE_SERVER_VERSION,
|
|
4
|
+
MIN_SUPPORTED_QE_WIRE_VERSION
|
|
5
|
+
} from '../cmap/wire_protocol/constants';
|
|
2
6
|
import { Collection } from '../collection';
|
|
3
7
|
import type { Db } from '../db';
|
|
8
|
+
import { MongoCompatibilityError } from '../error';
|
|
4
9
|
import type { PkFactory } from '../mongo_client';
|
|
5
10
|
import type { Server } from '../sdam/server';
|
|
6
11
|
import type { ClientSession } from '../sessions';
|
|
@@ -41,6 +46,8 @@ export interface TimeSeriesCollectionOptions extends Document {
|
|
|
41
46
|
timeField: string;
|
|
42
47
|
metaField?: string;
|
|
43
48
|
granularity?: 'seconds' | 'minutes' | 'hours' | string;
|
|
49
|
+
bucketMaxSpanSeconds?: number;
|
|
50
|
+
bucketRoundingSeconds?: number;
|
|
44
51
|
}
|
|
45
52
|
|
|
46
53
|
/** @public
|
|
@@ -55,8 +62,6 @@ export interface ClusteredCollectionOptions extends Document {
|
|
|
55
62
|
|
|
56
63
|
/** @public */
|
|
57
64
|
export interface CreateCollectionOptions extends CommandOperationOptions {
|
|
58
|
-
/** Returns an error if the collection does not exist */
|
|
59
|
-
strict?: boolean;
|
|
60
65
|
/** Create a capped collection */
|
|
61
66
|
capped?: boolean;
|
|
62
67
|
/** @deprecated Create an index on the _id field of the document. This option is deprecated in MongoDB 3.2+ and will be removed once no longer supported by the server. */
|
|
@@ -98,6 +103,10 @@ export interface CreateCollectionOptions extends CommandOperationOptions {
|
|
|
98
103
|
changeStreamPreAndPostImages?: { enabled: boolean };
|
|
99
104
|
}
|
|
100
105
|
|
|
106
|
+
/* @internal */
|
|
107
|
+
const INVALID_QE_VERSION =
|
|
108
|
+
'Driver support of Queryable Encryption is incompatible with server. Upgrade server to use Queryable Encryption.';
|
|
109
|
+
|
|
101
110
|
/** @internal */
|
|
102
111
|
export class CreateCollectionOperation extends CommandOperation<Collection> {
|
|
103
112
|
override options: CreateCollectionOptions;
|
|
@@ -124,15 +133,20 @@ export class CreateCollectionOperation extends CommandOperation<Collection> {
|
|
|
124
133
|
|
|
125
134
|
const encryptedFields: Document | undefined =
|
|
126
135
|
options.encryptedFields ??
|
|
127
|
-
db.
|
|
136
|
+
db.client.options.autoEncryption?.encryptedFieldsMap?.[`${db.databaseName}.${name}`];
|
|
128
137
|
|
|
129
138
|
if (encryptedFields) {
|
|
139
|
+
// Creating a QE collection required min server of 7.0.0
|
|
140
|
+
if (server.description.maxWireVersion < MIN_SUPPORTED_QE_WIRE_VERSION) {
|
|
141
|
+
throw new MongoCompatibilityError(
|
|
142
|
+
`${INVALID_QE_VERSION} The minimum server version required is ${MIN_SUPPORTED_QE_SERVER_VERSION}`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
130
145
|
// Create auxilliary collections for queryable encryption support.
|
|
131
146
|
const escCollection = encryptedFields.escCollection ?? `enxcol_.${name}.esc`;
|
|
132
|
-
const eccCollection = encryptedFields.eccCollection ?? `enxcol_.${name}.ecc`;
|
|
133
147
|
const ecocCollection = encryptedFields.ecocCollection ?? `enxcol_.${name}.ecoc`;
|
|
134
148
|
|
|
135
|
-
for (const collectionName of [escCollection,
|
|
149
|
+
for (const collectionName of [escCollection, ecocCollection]) {
|
|
136
150
|
const createOp = new CreateCollectionOperation(db, collectionName, {
|
|
137
151
|
clusteredIndex: {
|
|
138
152
|
key: { _id: 1 },
|
package/src/operations/drop.ts
CHANGED
|
@@ -36,7 +36,7 @@ export class DropCollectionOperation extends CommandOperation<boolean> {
|
|
|
36
36
|
const options = this.options;
|
|
37
37
|
const name = this.name;
|
|
38
38
|
|
|
39
|
-
const encryptedFieldsMap = db.
|
|
39
|
+
const encryptedFieldsMap = db.client.options.autoEncryption?.encryptedFieldsMap;
|
|
40
40
|
let encryptedFields: Document | undefined =
|
|
41
41
|
options.encryptedFields ?? encryptedFieldsMap?.[`${db.databaseName}.${name}`];
|
|
42
42
|
|
|
@@ -53,10 +53,9 @@ export class DropCollectionOperation extends CommandOperation<boolean> {
|
|
|
53
53
|
|
|
54
54
|
if (encryptedFields) {
|
|
55
55
|
const escCollection = encryptedFields.escCollection || `enxcol_.${name}.esc`;
|
|
56
|
-
const eccCollection = encryptedFields.eccCollection || `enxcol_.${name}.ecc`;
|
|
57
56
|
const ecocCollection = encryptedFields.ecocCollection || `enxcol_.${name}.ecoc`;
|
|
58
57
|
|
|
59
|
-
for (const collectionName of [escCollection,
|
|
58
|
+
for (const collectionName of [escCollection, ecocCollection]) {
|
|
60
59
|
// Drop auxilliary collections, ignoring potential NamespaceNotFound errors.
|
|
61
60
|
const dropOp = new DropCollectionOperation(db, collectionName);
|
|
62
61
|
try {
|