1
1
import { type Document } from '../bson' ;
2
2
import { CursorResponse } from '../cmap/wire_protocol/responses' ;
3
- import { MongoInvalidArgumentError , MongoTailableCursorError } from '../error' ;
4
- import { type ExplainCommandOptions , type ExplainVerbosityLike } from '../explain' ;
3
+ import { MongoAPIError , MongoInvalidArgumentError , MongoTailableCursorError } from '../error' ;
4
+ import {
5
+ Explain ,
6
+ ExplainableCursor ,
7
+ type ExplainCommandOptions ,
8
+ type ExplainVerbosityLike ,
9
+ validateExplainTimeoutOptions
10
+ } from '../explain' ;
5
11
import type { MongoClient } from '../mongo_client' ;
6
12
import type { CollationOptions } from '../operations/command' ;
7
13
import { CountOperation , type CountOptions } from '../operations/count' ;
@@ -11,7 +17,7 @@ import type { Hint } from '../operations/operation';
11
17
import type { ClientSession } from '../sessions' ;
12
18
import { formatSort , type Sort , type SortDirection } from '../sort' ;
13
19
import { emitWarningOnce , mergeOptions , type MongoDBNamespace , squashError } from '../utils' ;
14
- import { AbstractCursor , type InitialCursorResponse } from './abstract_cursor' ;
20
+ import { type InitialCursorResponse } from './abstract_cursor' ;
15
21
16
22
/** @public Flags allowed for cursor */
17
23
export const FLAGS = [
@@ -24,7 +30,7 @@ export const FLAGS = [
24
30
] as const ;
25
31
26
32
/** @public */
27
- export class FindCursor < TSchema = any > extends AbstractCursor < TSchema > {
33
+ export class FindCursor < TSchema = any > extends ExplainableCursor < TSchema > {
28
34
/** @internal */
29
35
private cursorFilter : Document ;
30
36
/** @internal */
@@ -63,11 +69,21 @@ export class FindCursor<TSchema = any> extends AbstractCursor<TSchema> {
63
69
64
70
/** @internal */
65
71
async _initialize ( session : ClientSession ) : Promise < InitialCursorResponse > {
66
- const findOperation = new FindOperation ( this . namespace , this . cursorFilter , {
72
+ const options = {
67
73
...this . findOptions , // NOTE: order matters here, we may need to refine this
68
74
...this . cursorOptions ,
69
75
session
70
- } ) ;
76
+ } ;
77
+
78
+ try {
79
+ validateExplainTimeoutOptions ( options , Explain . fromOptions ( options ) ) ;
80
+ } catch {
81
+ throw new MongoAPIError (
82
+ 'timeoutMS cannot be used with explain when explain is specified in findOptions'
83
+ ) ;
84
+ }
85
+
86
+ const findOperation = new FindOperation ( this . namespace , this . cursorFilter , options ) ;
71
87
72
88
const response = await executeOperation ( this . client , findOperation , this . timeoutContext ) ;
73
89
@@ -133,14 +149,27 @@ export class FindCursor<TSchema = any> extends AbstractCursor<TSchema> {
133
149
}
134
150
135
151
/** Execute the explain for the cursor */
136
- async explain ( verbosity ?: ExplainVerbosityLike | ExplainCommandOptions ) : Promise < Document > {
152
+ async explain ( ) : Promise < Document > ;
153
+ async explain ( verbosity : ExplainVerbosityLike | ExplainCommandOptions ) : Promise < Document > ;
154
+ async explain ( options : { timeoutMS ?: number } ) : Promise < Document > ;
155
+ async explain (
156
+ verbosity : ExplainVerbosityLike | ExplainCommandOptions ,
157
+ options : { timeoutMS ?: number }
158
+ ) : Promise < Document > ;
159
+ async explain (
160
+ verbosity ?: ExplainVerbosityLike | ExplainCommandOptions | { timeoutMS ?: number } ,
161
+ options ?: { timeoutMS ?: number }
162
+ ) : Promise < Document > {
163
+ const { explain, timeout } = this . resolveExplainTimeoutOptions ( verbosity , options ) ;
164
+
137
165
return (
138
166
await executeOperation (
139
167
this . client ,
140
168
new FindOperation ( this . namespace , this . cursorFilter , {
141
169
...this . findOptions , // NOTE: order matters here, we may need to refine this
142
170
...this . cursorOptions ,
143
- explain : verbosity ?? true
171
+ ...timeout ,
172
+ explain : explain ?? true
144
173
} )
145
174
)
146
175
) . shift ( this . deserializationOptions ) ;
0 commit comments