mongodb 6.18.0 → 6.19.0-dev.20250828.sha.41034f16
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 +2 -1
- package/lib/admin.js.map +1 -1
- package/lib/beta.d.ts +59 -7
- package/lib/bulk/common.js +19 -32
- package/lib/bulk/common.js.map +1 -1
- package/lib/client-side-encryption/client_encryption.js +4 -1
- package/lib/client-side-encryption/client_encryption.js.map +1 -1
- package/lib/client-side-encryption/state_machine.js +4 -0
- package/lib/client-side-encryption/state_machine.js.map +1 -1
- package/lib/cmap/connection.js.map +1 -1
- package/lib/collection.js +62 -19
- package/lib/collection.js.map +1 -1
- package/lib/cursor/aggregation_cursor.js +2 -1
- package/lib/cursor/aggregation_cursor.js.map +1 -1
- package/lib/cursor/explainable_cursor.js +36 -0
- package/lib/cursor/explainable_cursor.js.map +1 -0
- package/lib/cursor/find_cursor.js +2 -1
- package/lib/cursor/find_cursor.js.map +1 -1
- package/lib/cursor/run_command_cursor.js +2 -4
- package/lib/cursor/run_command_cursor.js.map +1 -1
- package/lib/db.js +12 -5
- package/lib/db.js.map +1 -1
- package/lib/explain.js +1 -33
- package/lib/explain.js.map +1 -1
- package/lib/index.js +6 -6
- package/lib/index.js.map +1 -1
- package/lib/mongo_client.js +25 -2
- package/lib/mongo_client.js.map +1 -1
- package/lib/operations/aggregate.js +9 -7
- package/lib/operations/aggregate.js.map +1 -1
- package/lib/operations/client_bulk_write/client_bulk_write.js +8 -41
- package/lib/operations/client_bulk_write/client_bulk_write.js.map +1 -1
- package/lib/operations/command.js +16 -19
- package/lib/operations/command.js.map +1 -1
- package/lib/operations/count.js +7 -3
- package/lib/operations/count.js.map +1 -1
- package/lib/operations/create_collection.js +56 -49
- package/lib/operations/create_collection.js.map +1 -1
- package/lib/operations/delete.js +15 -12
- package/lib/operations/delete.js.map +1 -1
- package/lib/operations/distinct.js +18 -26
- package/lib/operations/distinct.js.map +1 -1
- package/lib/operations/drop.js +57 -39
- package/lib/operations/drop.js.map +1 -1
- package/lib/operations/estimated_document_count.js +7 -3
- package/lib/operations/estimated_document_count.js.map +1 -1
- package/lib/operations/execute_operation.js +14 -3
- package/lib/operations/execute_operation.js.map +1 -1
- package/lib/operations/find.js +21 -30
- package/lib/operations/find.js.map +1 -1
- package/lib/operations/find_and_modify.js +52 -41
- package/lib/operations/find_and_modify.js.map +1 -1
- package/lib/operations/get_more.js +10 -11
- package/lib/operations/get_more.js.map +1 -1
- package/lib/operations/indexes.js +21 -12
- package/lib/operations/indexes.js.map +1 -1
- package/lib/operations/insert.js +8 -47
- package/lib/operations/insert.js.map +1 -1
- package/lib/operations/kill_cursors.js +13 -15
- package/lib/operations/kill_cursors.js.map +1 -1
- package/lib/operations/list_collections.js +7 -6
- package/lib/operations/list_collections.js.map +1 -1
- package/lib/operations/list_databases.js +5 -3
- package/lib/operations/list_databases.js.map +1 -1
- package/lib/operations/operation.js +30 -1
- package/lib/operations/operation.js.map +1 -1
- package/lib/operations/profiling_level.js +14 -4
- package/lib/operations/profiling_level.js.map +1 -1
- package/lib/operations/remove_user.js +6 -2
- package/lib/operations/remove_user.js.map +1 -1
- package/lib/operations/rename.js +10 -8
- package/lib/operations/rename.js.map +1 -1
- package/lib/operations/run_command.js +28 -32
- package/lib/operations/run_command.js.map +1 -1
- package/lib/operations/search_indexes/create.js +11 -8
- package/lib/operations/search_indexes/create.js.map +1 -1
- package/lib/operations/search_indexes/drop.js +16 -9
- package/lib/operations/search_indexes/drop.js.map +1 -1
- package/lib/operations/search_indexes/update.js +11 -4
- package/lib/operations/search_indexes/update.js.map +1 -1
- package/lib/operations/set_profiling_level.js +8 -4
- package/lib/operations/set_profiling_level.js.map +1 -1
- package/lib/operations/stats.js +4 -2
- package/lib/operations/stats.js.map +1 -1
- package/lib/operations/update.js +22 -19
- package/lib/operations/update.js.map +1 -1
- package/lib/operations/validate_collection.js +17 -18
- package/lib/operations/validate_collection.js.map +1 -1
- package/lib/sdam/server.js +46 -35
- 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 +3 -3
- package/lib/sessions.js.map +1 -1
- package/lib/utils.js +8 -13
- package/lib/utils.js.map +1 -1
- package/mongodb.d.ts +59 -7
- package/package.json +19 -19
- package/src/admin.ts +3 -2
- package/src/bulk/common.ts +21 -41
- package/src/client-side-encryption/client_encryption.ts +52 -3
- package/src/client-side-encryption/state_machine.ts +5 -1
- package/src/cmap/connection.ts +0 -1
- package/src/collection.ts +94 -65
- package/src/cursor/aggregation_cursor.ts +1 -1
- package/src/cursor/explainable_cursor.ts +51 -0
- package/src/cursor/find_cursor.ts +1 -1
- package/src/cursor/run_command_cursor.ts +4 -5
- package/src/db.ts +16 -19
- package/src/explain.ts +0 -49
- package/src/index.ts +4 -4
- package/src/mongo_client.ts +24 -9
- package/src/operations/aggregate.ts +15 -20
- package/src/operations/client_bulk_write/client_bulk_write.ts +21 -65
- package/src/operations/command.ts +22 -45
- package/src/operations/count.ts +9 -9
- package/src/operations/create_collection.ts +83 -75
- package/src/operations/delete.ts +27 -35
- package/src/operations/distinct.ts +23 -40
- package/src/operations/drop.ts +76 -60
- package/src/operations/estimated_document_count.ts +8 -9
- package/src/operations/execute_operation.ts +21 -11
- package/src/operations/find.ts +40 -57
- package/src/operations/find_and_modify.ts +78 -54
- package/src/operations/get_more.ts +17 -19
- package/src/operations/indexes.ts +26 -30
- package/src/operations/insert.ts +11 -77
- package/src/operations/kill_cursors.ts +21 -22
- package/src/operations/list_collections.ts +13 -21
- package/src/operations/list_databases.ts +6 -15
- package/src/operations/operation.ts +47 -10
- package/src/operations/profiling_level.ts +17 -11
- package/src/operations/remove_user.ts +9 -9
- package/src/operations/rename.ts +11 -14
- package/src/operations/run_command.ts +40 -68
- package/src/operations/search_indexes/create.ts +15 -15
- package/src/operations/search_indexes/drop.ts +23 -14
- package/src/operations/search_indexes/update.ts +14 -9
- package/src/operations/set_profiling_level.ts +13 -11
- package/src/operations/stats.ts +5 -10
- package/src/operations/update.ts +49 -52
- package/src/operations/validate_collection.ts +19 -27
- package/src/sdam/server.ts +56 -59
- package/src/sdam/topology.ts +5 -4
- package/src/sessions.ts +5 -4
- package/src/utils.ts +10 -25
- package/lib/operations/bulk_write.js +0 -39
- package/lib/operations/bulk_write.js.map +0 -1
- package/lib/operations/collections.js +0 -33
- package/lib/operations/collections.js.map +0 -1
- package/lib/operations/is_capped.js +0 -28
- package/lib/operations/is_capped.js.map +0 -1
- package/lib/operations/options_operation.js +0 -28
- package/lib/operations/options_operation.js.map +0 -1
- package/src/operations/bulk_write.ts +0 -64
- package/src/operations/collections.ts +0 -47
- package/src/operations/is_capped.ts +0 -35
- package/src/operations/options_operation.ts +0 -35
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { Document } from '../../bson';
|
|
2
|
+
import { type Connection } from '../../cmap/connection';
|
|
3
|
+
import { MongoDBResponse } from '../../cmap/wire_protocol/responses';
|
|
2
4
|
import type { Collection } from '../../collection';
|
|
3
|
-
import type {
|
|
5
|
+
import type { ServerCommandOptions } from '../../sdam/server';
|
|
4
6
|
import type { ClientSession } from '../../sessions';
|
|
5
7
|
import { type TimeoutContext } from '../../timeout';
|
|
6
8
|
import { AbstractOperation } from '../operation';
|
|
7
9
|
|
|
8
10
|
/** @internal */
|
|
9
11
|
export class UpdateSearchIndexOperation extends AbstractOperation<void> {
|
|
12
|
+
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
|
|
10
13
|
private readonly collection: Collection;
|
|
11
14
|
private readonly name: string;
|
|
12
15
|
private readonly definition: Document;
|
|
@@ -16,25 +19,27 @@ export class UpdateSearchIndexOperation extends AbstractOperation<void> {
|
|
|
16
19
|
this.collection = collection;
|
|
17
20
|
this.name = name;
|
|
18
21
|
this.definition = definition;
|
|
22
|
+
this.ns = collection.fullNamespace;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
override get commandName() {
|
|
22
26
|
return 'updateSearchIndex' as const;
|
|
23
27
|
}
|
|
24
28
|
|
|
25
|
-
override
|
|
26
|
-
server: Server,
|
|
27
|
-
session: ClientSession | undefined,
|
|
28
|
-
timeoutContext: TimeoutContext
|
|
29
|
-
): Promise<void> {
|
|
29
|
+
override buildCommand(_connection: Connection, _session?: ClientSession): Document {
|
|
30
30
|
const namespace = this.collection.fullNamespace;
|
|
31
|
-
|
|
31
|
+
return {
|
|
32
32
|
updateSearchIndex: namespace.collection,
|
|
33
33
|
name: this.name,
|
|
34
34
|
definition: this.definition
|
|
35
35
|
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override handleOk(_response: MongoDBResponse): void {
|
|
39
|
+
// no response.
|
|
40
|
+
}
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
return;
|
|
42
|
+
override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
|
|
43
|
+
return { session: this.session, timeoutContext };
|
|
39
44
|
}
|
|
40
45
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { type Document } from '../bson';
|
|
2
|
+
import { type Connection } from '../cmap/connection';
|
|
3
|
+
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
1
4
|
import type { Db } from '../db';
|
|
2
5
|
import { MongoInvalidArgumentError } from '../error';
|
|
3
|
-
import type { Server } from '../sdam/server';
|
|
4
|
-
import type { ClientSession } from '../sessions';
|
|
5
|
-
import { type TimeoutContext } from '../timeout';
|
|
6
6
|
import { enumToString } from '../utils';
|
|
7
7
|
import { CommandOperation, type CommandOperationOptions } from './command';
|
|
8
8
|
|
|
@@ -23,6 +23,7 @@ export type SetProfilingLevelOptions = CommandOperationOptions;
|
|
|
23
23
|
|
|
24
24
|
/** @internal */
|
|
25
25
|
export class SetProfilingLevelOperation extends CommandOperation<ProfilingLevel> {
|
|
26
|
+
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
|
|
26
27
|
override options: SetProfilingLevelOptions;
|
|
27
28
|
level: ProfilingLevel;
|
|
28
29
|
profile: 0 | 1 | 2;
|
|
@@ -52,21 +53,22 @@ export class SetProfilingLevelOperation extends CommandOperation<ProfilingLevel>
|
|
|
52
53
|
return 'profile' as const;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
override
|
|
56
|
-
server: Server,
|
|
57
|
-
session: ClientSession | undefined,
|
|
58
|
-
timeoutContext: TimeoutContext
|
|
59
|
-
): Promise<ProfilingLevel> {
|
|
56
|
+
override buildCommandDocument(_connection: Connection): Document {
|
|
60
57
|
const level = this.level;
|
|
61
58
|
|
|
62
59
|
if (!levelValues.has(level)) {
|
|
60
|
+
// TODO(NODE-3483): Determine error to put here
|
|
63
61
|
throw new MongoInvalidArgumentError(
|
|
64
62
|
`Profiling level must be one of "${enumToString(ProfilingLevel)}"`
|
|
65
63
|
);
|
|
66
64
|
}
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
return { profile: this.profile };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
override handleOk(
|
|
70
|
+
_response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
|
|
71
|
+
): ProfilingLevel {
|
|
72
|
+
return this.level;
|
|
71
73
|
}
|
|
72
74
|
}
|
package/src/operations/stats.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { Document } from '../bson';
|
|
2
|
+
import { type Connection } from '../cmap/connection';
|
|
3
|
+
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
2
4
|
import type { Db } from '../db';
|
|
3
|
-
import type { Server } from '../sdam/server';
|
|
4
|
-
import type { ClientSession } from '../sessions';
|
|
5
|
-
import { type TimeoutContext } from '../timeout';
|
|
6
5
|
import { CommandOperation, type CommandOperationOptions } from './command';
|
|
7
6
|
import { Aspect, defineAspects } from './operation';
|
|
8
7
|
|
|
@@ -14,6 +13,7 @@ export interface DbStatsOptions extends CommandOperationOptions {
|
|
|
14
13
|
|
|
15
14
|
/** @internal */
|
|
16
15
|
export class DbStatsOperation extends CommandOperation<Document> {
|
|
16
|
+
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
|
|
17
17
|
override options: DbStatsOptions;
|
|
18
18
|
|
|
19
19
|
constructor(db: Db, options: DbStatsOptions) {
|
|
@@ -25,17 +25,12 @@ export class DbStatsOperation extends CommandOperation<Document> {
|
|
|
25
25
|
return 'dbStats' as const;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
override
|
|
29
|
-
server: Server,
|
|
30
|
-
session: ClientSession | undefined,
|
|
31
|
-
timeoutContext: TimeoutContext
|
|
32
|
-
): Promise<Document> {
|
|
28
|
+
override buildCommandDocument(_connection: Connection): Document {
|
|
33
29
|
const command: Document = { dbStats: true };
|
|
34
30
|
if (this.options.scale != null) {
|
|
35
31
|
command.scale = this.options.scale;
|
|
36
32
|
}
|
|
37
|
-
|
|
38
|
-
return await super.executeCommand(server, session, command, timeoutContext);
|
|
33
|
+
return command;
|
|
39
34
|
}
|
|
40
35
|
}
|
|
41
36
|
|
package/src/operations/update.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { Document } from '../bson';
|
|
2
|
-
import type
|
|
2
|
+
import { type Connection } from '../cmap/connection';
|
|
3
|
+
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
3
4
|
import { MongoCompatibilityError, MongoInvalidArgumentError, MongoServerError } from '../error';
|
|
4
|
-
import type { InferIdType
|
|
5
|
-
import type { Server } from '../sdam/server';
|
|
5
|
+
import type { InferIdType } from '../mongo_types';
|
|
6
6
|
import type { ClientSession } from '../sessions';
|
|
7
7
|
import { formatSort, type Sort, type SortForCmd } from '../sort';
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import {
|
|
9
|
+
hasAtomicOperators,
|
|
10
|
+
type MongoDBCollectionNamespace,
|
|
11
|
+
type MongoDBNamespace
|
|
12
|
+
} from '../utils';
|
|
10
13
|
import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
|
|
11
14
|
import { Aspect, defineAspects, type Hint } from './operation';
|
|
12
15
|
|
|
@@ -68,6 +71,7 @@ export interface UpdateStatement {
|
|
|
68
71
|
* UpdateOperation is used in bulk write, while UpdateOneOperation and UpdateManyOperation are only used in the collections API
|
|
69
72
|
*/
|
|
70
73
|
export class UpdateOperation extends CommandOperation<Document> {
|
|
74
|
+
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
|
|
71
75
|
override options: UpdateOptions & { ordered?: boolean };
|
|
72
76
|
statements: UpdateStatement[];
|
|
73
77
|
|
|
@@ -95,17 +99,12 @@ export class UpdateOperation extends CommandOperation<Document> {
|
|
|
95
99
|
return this.statements.every(op => op.multi == null || op.multi === false);
|
|
96
100
|
}
|
|
97
101
|
|
|
98
|
-
override
|
|
99
|
-
|
|
100
|
-
session: ClientSession | undefined,
|
|
101
|
-
timeoutContext: TimeoutContext
|
|
102
|
-
): Promise<Document> {
|
|
103
|
-
const options = this.options ?? {};
|
|
104
|
-
const ordered = typeof options.ordered === 'boolean' ? options.ordered : true;
|
|
102
|
+
override buildCommandDocument(_connection: Connection, _session?: ClientSession): Document {
|
|
103
|
+
const options = this.options;
|
|
105
104
|
const command: Document = {
|
|
106
105
|
update: this.ns.collection,
|
|
107
106
|
updates: this.statements,
|
|
108
|
-
ordered
|
|
107
|
+
ordered: options.ordered ?? true
|
|
109
108
|
};
|
|
110
109
|
|
|
111
110
|
if (typeof options.bypassDocumentValidation === 'boolean') {
|
|
@@ -122,7 +121,7 @@ export class UpdateOperation extends CommandOperation<Document> {
|
|
|
122
121
|
command.comment = options.comment;
|
|
123
122
|
}
|
|
124
123
|
|
|
125
|
-
const unacknowledgedWrite = this.writeConcern
|
|
124
|
+
const unacknowledgedWrite = this.writeConcern?.w === 0;
|
|
126
125
|
if (unacknowledgedWrite) {
|
|
127
126
|
if (this.statements.find((o: Document) => o.hint)) {
|
|
128
127
|
// TODO(NODE-3541): fix error for hint with unacknowledged writes
|
|
@@ -130,32 +129,33 @@ export class UpdateOperation extends CommandOperation<Document> {
|
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
|
|
133
|
-
|
|
134
|
-
return res;
|
|
132
|
+
return command;
|
|
135
133
|
}
|
|
136
134
|
}
|
|
137
135
|
|
|
138
136
|
/** @internal */
|
|
139
137
|
export class UpdateOneOperation extends UpdateOperation {
|
|
140
|
-
constructor(
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
138
|
+
constructor(
|
|
139
|
+
ns: MongoDBCollectionNamespace,
|
|
140
|
+
filter: Document,
|
|
141
|
+
update: Document,
|
|
142
|
+
options: UpdateOptions
|
|
143
|
+
) {
|
|
144
|
+
super(ns, [makeUpdateStatement(filter, update, { ...options, multi: false })], options);
|
|
146
145
|
|
|
147
146
|
if (!hasAtomicOperators(update, options)) {
|
|
148
147
|
throw new MongoInvalidArgumentError('Update document requires atomic operators');
|
|
149
148
|
}
|
|
150
149
|
}
|
|
151
150
|
|
|
152
|
-
override
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
151
|
+
override handleOk(
|
|
152
|
+
response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
|
|
153
|
+
): UpdateResult {
|
|
154
|
+
const res = super.handleOk(response);
|
|
155
|
+
|
|
156
|
+
// @ts-expect-error Explain typing is broken
|
|
158
157
|
if (this.explain != null) return res;
|
|
158
|
+
|
|
159
159
|
if (res.code) throw new MongoServerError(res);
|
|
160
160
|
if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
|
|
161
161
|
|
|
@@ -172,24 +172,25 @@ export class UpdateOneOperation extends UpdateOperation {
|
|
|
172
172
|
|
|
173
173
|
/** @internal */
|
|
174
174
|
export class UpdateManyOperation extends UpdateOperation {
|
|
175
|
-
constructor(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
constructor(
|
|
176
|
+
ns: MongoDBCollectionNamespace,
|
|
177
|
+
filter: Document,
|
|
178
|
+
update: Document,
|
|
179
|
+
options: UpdateOptions
|
|
180
|
+
) {
|
|
181
|
+
super(ns, [makeUpdateStatement(filter, update, { ...options, multi: true })], options);
|
|
181
182
|
|
|
182
183
|
if (!hasAtomicOperators(update, options)) {
|
|
183
184
|
throw new MongoInvalidArgumentError('Update document requires atomic operators');
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
187
|
|
|
187
|
-
override
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
188
|
+
override handleOk(
|
|
189
|
+
response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
|
|
190
|
+
): UpdateResult {
|
|
191
|
+
const res = super.handleOk(response);
|
|
192
|
+
|
|
193
|
+
// @ts-expect-error Explain typing is broken
|
|
193
194
|
if (this.explain != null) return res;
|
|
194
195
|
if (res.code) throw new MongoServerError(res);
|
|
195
196
|
if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
|
|
@@ -224,28 +225,24 @@ export interface ReplaceOptions extends CommandOperationOptions {
|
|
|
224
225
|
/** @internal */
|
|
225
226
|
export class ReplaceOneOperation extends UpdateOperation {
|
|
226
227
|
constructor(
|
|
227
|
-
|
|
228
|
+
ns: MongoDBCollectionNamespace,
|
|
228
229
|
filter: Document,
|
|
229
230
|
replacement: Document,
|
|
230
231
|
options: ReplaceOptions
|
|
231
232
|
) {
|
|
232
|
-
super(
|
|
233
|
-
collection.s.namespace,
|
|
234
|
-
[makeUpdateStatement(filter, replacement, { ...options, multi: false })],
|
|
235
|
-
options
|
|
236
|
-
);
|
|
233
|
+
super(ns, [makeUpdateStatement(filter, replacement, { ...options, multi: false })], options);
|
|
237
234
|
|
|
238
235
|
if (hasAtomicOperators(replacement)) {
|
|
239
236
|
throw new MongoInvalidArgumentError('Replacement document must not contain atomic operators');
|
|
240
237
|
}
|
|
241
238
|
}
|
|
242
239
|
|
|
243
|
-
override
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
240
|
+
override handleOk(
|
|
241
|
+
response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
|
|
242
|
+
): UpdateResult {
|
|
243
|
+
const res = super.handleOk(response);
|
|
244
|
+
|
|
245
|
+
// @ts-expect-error Explain typing is broken
|
|
249
246
|
if (this.explain != null) return res;
|
|
250
247
|
if (res.code) throw new MongoServerError(res);
|
|
251
248
|
if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { type Connection } from '..';
|
|
1
2
|
import type { Admin } from '../admin';
|
|
2
|
-
import type
|
|
3
|
+
import { type Document } from '../bson';
|
|
4
|
+
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
|
|
3
5
|
import { MongoUnexpectedServerResponseError } from '../error';
|
|
4
|
-
import type { Server } from '../sdam/server';
|
|
5
6
|
import type { ClientSession } from '../sessions';
|
|
6
|
-
import { type TimeoutContext } from '../timeout';
|
|
7
7
|
import { CommandOperation, type CommandOperationOptions } from './command';
|
|
8
8
|
|
|
9
9
|
/** @public */
|
|
@@ -14,23 +14,13 @@ export interface ValidateCollectionOptions extends CommandOperationOptions {
|
|
|
14
14
|
|
|
15
15
|
/** @internal */
|
|
16
16
|
export class ValidateCollectionOperation extends CommandOperation<Document> {
|
|
17
|
+
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
|
|
17
18
|
override options: ValidateCollectionOptions;
|
|
18
19
|
collectionName: string;
|
|
19
|
-
command: Document;
|
|
20
20
|
|
|
21
21
|
constructor(admin: Admin, collectionName: string, options: ValidateCollectionOptions) {
|
|
22
|
-
// Decorate command with extra options
|
|
23
|
-
const command: Document = { validate: collectionName };
|
|
24
|
-
const keys = Object.keys(options);
|
|
25
|
-
for (let i = 0; i < keys.length; i++) {
|
|
26
|
-
if (Object.prototype.hasOwnProperty.call(options, keys[i]) && keys[i] !== 'session') {
|
|
27
|
-
command[keys[i]] = (options as Document)[keys[i]];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
22
|
super(admin.s.db, options);
|
|
32
23
|
this.options = options;
|
|
33
|
-
this.command = command;
|
|
34
24
|
this.collectionName = collectionName;
|
|
35
25
|
}
|
|
36
26
|
|
|
@@ -38,21 +28,23 @@ export class ValidateCollectionOperation extends CommandOperation<Document> {
|
|
|
38
28
|
return 'validate' as const;
|
|
39
29
|
}
|
|
40
30
|
|
|
41
|
-
override
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
31
|
+
override buildCommandDocument(_connection: Connection, _session?: ClientSession): Document {
|
|
32
|
+
// Decorate command with extra options
|
|
33
|
+
return {
|
|
34
|
+
validate: this.collectionName,
|
|
35
|
+
...Object.fromEntries(Object.entries(this.options).filter(entry => entry[0] !== 'session'))
|
|
36
|
+
};
|
|
37
|
+
}
|
|
47
38
|
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): Document {
|
|
40
|
+
const result = super.handleOk(response);
|
|
41
|
+
if (result.result != null && typeof result.result !== 'string')
|
|
50
42
|
throw new MongoUnexpectedServerResponseError('Error with validation data');
|
|
51
|
-
if (
|
|
52
|
-
throw new MongoUnexpectedServerResponseError(`Invalid collection ${collectionName}`);
|
|
53
|
-
if (
|
|
54
|
-
throw new MongoUnexpectedServerResponseError(`Invalid collection ${collectionName}`);
|
|
43
|
+
if (result.result != null && result.result.match(/exception|corrupt/) != null)
|
|
44
|
+
throw new MongoUnexpectedServerResponseError(`Invalid collection ${this.collectionName}`);
|
|
45
|
+
if (result.valid != null && !result.valid)
|
|
46
|
+
throw new MongoUnexpectedServerResponseError(`Invalid collection ${this.collectionName}`);
|
|
55
47
|
|
|
56
|
-
return
|
|
48
|
+
return response;
|
|
57
49
|
}
|
|
58
50
|
}
|
package/src/sdam/server.ts
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
type ConnectionPoolOptions
|
|
8
8
|
} from '../cmap/connection_pool';
|
|
9
9
|
import { PoolClearedError } from '../cmap/errors';
|
|
10
|
-
import { type MongoDBResponseConstructor } from '../cmap/wire_protocol/responses';
|
|
11
10
|
import {
|
|
12
11
|
APM_EVENTS,
|
|
13
12
|
CLOSED,
|
|
@@ -27,7 +26,6 @@ import {
|
|
|
27
26
|
MONGODB_ERROR_CODES,
|
|
28
27
|
MongoError,
|
|
29
28
|
MongoErrorLabel,
|
|
30
|
-
MongoInvalidArgumentError,
|
|
31
29
|
MongoNetworkError,
|
|
32
30
|
MongoNetworkTimeoutError,
|
|
33
31
|
MongoRuntimeError,
|
|
@@ -37,7 +35,9 @@ import {
|
|
|
37
35
|
} from '../error';
|
|
38
36
|
import type { ServerApi } from '../mongo_client';
|
|
39
37
|
import { type Abortable, TypedEventEmitter } from '../mongo_types';
|
|
38
|
+
import { AggregateOperation } from '../operations/aggregate';
|
|
40
39
|
import type { GetMoreOptions } from '../operations/get_more';
|
|
40
|
+
import { type AbstractOperation } from '../operations/operation';
|
|
41
41
|
import type { ClientSession } from '../sessions';
|
|
42
42
|
import { type TimeoutContext } from '../timeout';
|
|
43
43
|
import { isTransactionCommand } from '../transactions';
|
|
@@ -46,7 +46,6 @@ import {
|
|
|
46
46
|
type EventEmitterWithState,
|
|
47
47
|
makeStateMachine,
|
|
48
48
|
maxWireVersion,
|
|
49
|
-
type MongoDBNamespace,
|
|
50
49
|
noop,
|
|
51
50
|
squashError,
|
|
52
51
|
supportsRetryableWrites
|
|
@@ -67,6 +66,7 @@ import type {
|
|
|
67
66
|
} from './events';
|
|
68
67
|
import { Monitor, type MonitorOptions } from './monitor';
|
|
69
68
|
import { compareTopologyVersion, ServerDescription } from './server_description';
|
|
69
|
+
import { MIN_SECONDARY_WRITE_WIRE_VERSION } from './server_selection';
|
|
70
70
|
import type { Topology } from './topology';
|
|
71
71
|
|
|
72
72
|
const stateTransition = makeStateMachine({
|
|
@@ -110,6 +110,7 @@ export type ServerEvents = {
|
|
|
110
110
|
/** @internal */
|
|
111
111
|
export type ServerCommandOptions = Omit<CommandOptions, 'timeoutContext' | 'socketTimeoutMS'> & {
|
|
112
112
|
timeoutContext: TimeoutContext;
|
|
113
|
+
returnFieldSelector?: Document | null;
|
|
113
114
|
} & Abortable;
|
|
114
115
|
|
|
115
116
|
/** @internal */
|
|
@@ -277,57 +278,21 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
277
278
|
}
|
|
278
279
|
}
|
|
279
280
|
|
|
280
|
-
public async command<
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
responseType: T | undefined
|
|
285
|
-
): Promise<typeof responseType extends undefined ? Document : InstanceType<T>>;
|
|
286
|
-
|
|
287
|
-
public async command(
|
|
288
|
-
ns: MongoDBNamespace,
|
|
289
|
-
command: Document,
|
|
290
|
-
options: ServerCommandOptions
|
|
291
|
-
): Promise<Document>;
|
|
292
|
-
|
|
293
|
-
public async command(
|
|
294
|
-
ns: MongoDBNamespace,
|
|
295
|
-
cmd: Document,
|
|
296
|
-
{ ...options }: ServerCommandOptions,
|
|
297
|
-
responseType?: MongoDBResponseConstructor
|
|
298
|
-
): Promise<Document> {
|
|
299
|
-
if (ns.db == null || typeof ns === 'string') {
|
|
300
|
-
throw new MongoInvalidArgumentError('Namespace must not be a string');
|
|
301
|
-
}
|
|
302
|
-
|
|
281
|
+
public async command<TResult>(
|
|
282
|
+
operation: AbstractOperation<TResult>,
|
|
283
|
+
timeoutContext: TimeoutContext
|
|
284
|
+
): Promise<InstanceType<typeof operation.SERVER_COMMAND_RESPONSE_TYPE>> {
|
|
303
285
|
if (this.s.state === STATE_CLOSING || this.s.state === STATE_CLOSED) {
|
|
304
286
|
throw new MongoServerClosedError();
|
|
305
287
|
}
|
|
288
|
+
const session = operation.session;
|
|
306
289
|
|
|
307
|
-
options.directConnection = this.topology.s.options.directConnection;
|
|
308
|
-
|
|
309
|
-
// There are cases where we need to flag the read preference not to get sent in
|
|
310
|
-
// the command, such as pre-5.0 servers attempting to perform an aggregate write
|
|
311
|
-
// with a non-primary read preference. In this case the effective read preference
|
|
312
|
-
// (primary) is not the same as the provided and must be removed completely.
|
|
313
|
-
if (options.omitReadPreference) {
|
|
314
|
-
delete options.readPreference;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (this.description.iscryptd) {
|
|
318
|
-
options.omitMaxTimeMS = true;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const session = options.session;
|
|
322
290
|
let conn = session?.pinnedConnection;
|
|
323
291
|
|
|
324
292
|
this.incrementOperationCount();
|
|
325
293
|
if (conn == null) {
|
|
326
294
|
try {
|
|
327
|
-
conn = await this.pool.checkOut(options);
|
|
328
|
-
if (this.loadBalanced && isPinnableCommand(cmd, session)) {
|
|
329
|
-
session?.pin(conn);
|
|
330
|
-
}
|
|
295
|
+
conn = await this.pool.checkOut({ timeoutContext, signal: operation.options.signal });
|
|
331
296
|
} catch (checkoutError) {
|
|
332
297
|
this.decrementOperationCount();
|
|
333
298
|
if (!(checkoutError instanceof PoolClearedError)) this.handleError(checkoutError);
|
|
@@ -336,10 +301,53 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
336
301
|
}
|
|
337
302
|
|
|
338
303
|
let reauthPromise: Promise<void> | null = null;
|
|
304
|
+
const cleanup = () => {
|
|
305
|
+
this.decrementOperationCount();
|
|
306
|
+
if (session?.pinnedConnection !== conn) {
|
|
307
|
+
if (reauthPromise != null) {
|
|
308
|
+
// The reauth promise only exists if it hasn't thrown.
|
|
309
|
+
const checkBackIn = () => {
|
|
310
|
+
this.pool.checkIn(conn);
|
|
311
|
+
};
|
|
312
|
+
void reauthPromise.then(checkBackIn, checkBackIn);
|
|
313
|
+
} else {
|
|
314
|
+
this.pool.checkIn(conn);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
let cmd;
|
|
320
|
+
try {
|
|
321
|
+
cmd = operation.buildCommand(conn, session);
|
|
322
|
+
} catch (e) {
|
|
323
|
+
cleanup();
|
|
324
|
+
throw e;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const options = operation.buildOptions(timeoutContext);
|
|
328
|
+
const ns = operation.ns;
|
|
329
|
+
|
|
330
|
+
if (this.loadBalanced && isPinnableCommand(cmd, session) && !session?.pinnedConnection) {
|
|
331
|
+
session?.pin(conn);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
options.directConnection = this.topology.s.options.directConnection;
|
|
335
|
+
|
|
336
|
+
const omitReadPreference =
|
|
337
|
+
operation instanceof AggregateOperation &&
|
|
338
|
+
operation.hasWriteStage &&
|
|
339
|
+
maxWireVersion(conn) < MIN_SECONDARY_WRITE_WIRE_VERSION;
|
|
340
|
+
if (omitReadPreference) {
|
|
341
|
+
delete options.readPreference;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (this.description.iscryptd) {
|
|
345
|
+
options.omitMaxTimeMS = true;
|
|
346
|
+
}
|
|
339
347
|
|
|
340
348
|
try {
|
|
341
349
|
try {
|
|
342
|
-
const res = await conn.command(ns, cmd, options,
|
|
350
|
+
const res = await conn.command(ns, cmd, options, operation.SERVER_COMMAND_RESPONSE_TYPE);
|
|
343
351
|
throwIfWriteConcernError(res);
|
|
344
352
|
return res;
|
|
345
353
|
} catch (commandError) {
|
|
@@ -360,7 +368,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
360
368
|
reauthPromise = null; // only reachable if reauth succeeds
|
|
361
369
|
|
|
362
370
|
try {
|
|
363
|
-
const res = await conn.command(ns, cmd, options,
|
|
371
|
+
const res = await conn.command(ns, cmd, options, operation.SERVER_COMMAND_RESPONSE_TYPE);
|
|
364
372
|
throwIfWriteConcernError(res);
|
|
365
373
|
return res;
|
|
366
374
|
} catch (commandError) {
|
|
@@ -370,18 +378,7 @@ export class Server extends TypedEventEmitter<ServerEvents> {
|
|
|
370
378
|
throw operationError;
|
|
371
379
|
}
|
|
372
380
|
} finally {
|
|
373
|
-
|
|
374
|
-
if (session?.pinnedConnection !== conn) {
|
|
375
|
-
if (reauthPromise != null) {
|
|
376
|
-
// The reauth promise only exists if it hasn't thrown.
|
|
377
|
-
const checkBackIn = () => {
|
|
378
|
-
this.pool.checkIn(conn);
|
|
379
|
-
};
|
|
380
|
-
void reauthPromise.then(checkBackIn, checkBackIn);
|
|
381
|
-
} else {
|
|
382
|
-
this.pool.checkIn(conn);
|
|
383
|
-
}
|
|
384
|
-
}
|
|
381
|
+
cleanup();
|
|
385
382
|
}
|
|
386
383
|
}
|
|
387
384
|
|
package/src/sdam/topology.ts
CHANGED
|
@@ -46,7 +46,6 @@ import {
|
|
|
46
46
|
makeStateMachine,
|
|
47
47
|
noop,
|
|
48
48
|
now,
|
|
49
|
-
ns,
|
|
50
49
|
promiseWithResolvers,
|
|
51
50
|
shuffle
|
|
52
51
|
} from '../utils';
|
|
@@ -459,7 +458,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
459
458
|
waitQueueTimeoutMS: this.client.s.options.waitQueueTimeoutMS
|
|
460
459
|
});
|
|
461
460
|
const selectServerOptions = {
|
|
462
|
-
operationName: '
|
|
461
|
+
operationName: 'handshake',
|
|
463
462
|
...options,
|
|
464
463
|
timeoutContext
|
|
465
464
|
};
|
|
@@ -469,9 +468,11 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
469
468
|
readPreferenceServerSelector(readPreference),
|
|
470
469
|
selectServerOptions
|
|
471
470
|
);
|
|
471
|
+
|
|
472
472
|
const skipPingOnConnect = this.s.options.__skipPingOnConnect === true;
|
|
473
473
|
if (!skipPingOnConnect && this.s.credentials) {
|
|
474
|
-
await server.
|
|
474
|
+
const connection = await server.pool.checkOut({ timeoutContext: timeoutContext });
|
|
475
|
+
server.pool.checkIn(connection);
|
|
475
476
|
stateTransition(this, STATE_CONNECTED);
|
|
476
477
|
this.emit(Topology.OPEN, this);
|
|
477
478
|
this.emit(Topology.CONNECT, this);
|
|
@@ -749,7 +750,7 @@ export class Topology extends TypedEventEmitter<TopologyEvents> {
|
|
|
749
750
|
}
|
|
750
751
|
|
|
751
752
|
auth(credentials?: MongoCredentials, callback?: Callback): void {
|
|
752
|
-
if (typeof credentials === 'function') (callback = credentials), (credentials = undefined);
|
|
753
|
+
if (typeof credentials === 'function') ((callback = credentials), (credentials = undefined));
|
|
753
754
|
if (typeof callback === 'function') callback(undefined, true);
|
|
754
755
|
}
|
|
755
756
|
|
package/src/sessions.ts
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
import type { MongoClient, MongoOptions } from './mongo_client';
|
|
25
25
|
import { TypedEventEmitter } from './mongo_types';
|
|
26
26
|
import { executeOperation } from './operations/execute_operation';
|
|
27
|
-
import {
|
|
27
|
+
import { RunCommandOperation } from './operations/run_command';
|
|
28
28
|
import { ReadConcernLevel } from './read_concern';
|
|
29
29
|
import { ReadPreference } from './read_preference';
|
|
30
30
|
import { type AsyncDisposable, configureResourceManagement } from './resource_management';
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
isPromiseLike,
|
|
44
44
|
List,
|
|
45
45
|
maxWireVersion,
|
|
46
|
+
MongoDBNamespace,
|
|
46
47
|
noop,
|
|
47
48
|
now,
|
|
48
49
|
squashError,
|
|
@@ -505,7 +506,7 @@ export class ClientSession
|
|
|
505
506
|
command.recoveryToken = this.transaction.recoveryToken;
|
|
506
507
|
}
|
|
507
508
|
|
|
508
|
-
const operation = new
|
|
509
|
+
const operation = new RunCommandOperation(new MongoDBNamespace('admin'), command, {
|
|
509
510
|
session: this,
|
|
510
511
|
readPreference: ReadPreference.primary,
|
|
511
512
|
bypassPinningCheck: true
|
|
@@ -536,7 +537,7 @@ export class ClientSession
|
|
|
536
537
|
try {
|
|
537
538
|
await executeOperation(
|
|
538
539
|
this.client,
|
|
539
|
-
new
|
|
540
|
+
new RunCommandOperation(new MongoDBNamespace('admin'), command, {
|
|
540
541
|
session: this,
|
|
541
542
|
readPreference: ReadPreference.primary,
|
|
542
543
|
bypassPinningCheck: true
|
|
@@ -637,7 +638,7 @@ export class ClientSession
|
|
|
637
638
|
command.recoveryToken = this.transaction.recoveryToken;
|
|
638
639
|
}
|
|
639
640
|
|
|
640
|
-
const operation = new
|
|
641
|
+
const operation = new RunCommandOperation(new MongoDBNamespace('admin'), command, {
|
|
641
642
|
session: this,
|
|
642
643
|
readPreference: ReadPreference.primary,
|
|
643
644
|
bypassPinningCheck: true
|