Skip to content

Commit b6e66d3

Browse files
POC
1 parent f525403 commit b6e66d3

File tree

3 files changed

+56
-13
lines changed

3 files changed

+56
-13
lines changed

src/explain.ts

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,18 @@ export type ExplainVerbosity = string;
1919
*/
2020
export type ExplainVerbosityLike = ExplainVerbosity | boolean;
2121

22+
/**
23+
* @public
24+
*/
25+
export interface ExplainCommandOptions {
26+
verbosity: ExplainVerbosityLike;
27+
maxTimeMS?: number;
28+
}
29+
2230
/** @public */
2331
export interface ExplainOptions {
2432
/** Specifies the verbosity mode for the explain output. */
25-
explain?: ExplainVerbosityLike;
33+
explain?: ExplainVerbosityLike | ExplainCommandOptions;
2634
}
2735

2836
/** @internal */
@@ -39,14 +47,34 @@ export class Explain {
3947
}
4048
}
4149

42-
static fromOptions(options?: ExplainOptions): Explain | undefined {
43-
if (options?.explain == null) return;
50+
static fromOptions({ explain }: ExplainOptions = {}): Explain | undefined {
51+
if (explain == null) return;
4452

45-
const explain = options.explain;
4653
if (typeof explain === 'boolean' || typeof explain === 'string') {
4754
return new Explain(explain);
4855
}
4956

50-
throw new MongoInvalidArgumentError('Field "explain" must be a string or a boolean');
57+
if (typeof explain === 'object') {
58+
const { verbosity } = explain;
59+
return new Explain(verbosity);
60+
}
61+
62+
throw new MongoInvalidArgumentError(
63+
'Field "explain" must be a string, a boolean or an ExplainCommandOptions object.'
64+
);
65+
}
66+
}
67+
68+
export class ExplainCommandOptions2 {
69+
private constructor(
70+
public readonly explain: Explain,
71+
public readonly maxTimeMS: number | undefined
72+
) {}
73+
74+
static fromOptions(options: ExplainOptions = {}): ExplainCommandOptions2 | undefined {
75+
const explain = Explain.fromOptions(options);
76+
const maxTimeMS = typeof options.explain === 'object' ? options.explain.maxTimeMS : undefined;
77+
78+
return explain ? new ExplainCommandOptions2(explain, maxTimeMS) : undefined;
5179
}
5280
}

src/operations/command.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { BSONSerializeOptions, Document } from '../bson';
22
import { type MongoDBResponseConstructor } from '../cmap/wire_protocol/responses';
33
import { MongoInvalidArgumentError } from '../error';
4-
import { Explain, type ExplainOptions } from '../explain';
4+
import { ExplainCommandOptions2, type ExplainOptions } from '../explain';
55
import { ReadConcern } from '../read_concern';
66
import type { ReadPreference } from '../read_preference';
77
import type { Server } from '../sdam/server';
@@ -72,7 +72,7 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
7272
override options: CommandOperationOptions;
7373
readConcern?: ReadConcern;
7474
writeConcern?: WriteConcern;
75-
explain?: Explain;
75+
explain?: ExplainCommandOptions2;
7676

7777
constructor(parent?: OperationParent, options?: CommandOperationOptions) {
7878
super(options);
@@ -94,7 +94,7 @@ export abstract class CommandOperation<T> extends AbstractOperation<T> {
9494
this.writeConcern = WriteConcern.fromOptions(options);
9595

9696
if (this.hasAspect(Aspect.EXPLAINABLE)) {
97-
this.explain = Explain.fromOptions(options);
97+
this.explain = ExplainCommandOptions2.fromOptions(options);
9898
} else if (options?.explain != null) {
9999
throw new MongoInvalidArgumentError(`Option "explain" is not supported on this command`);
100100
}

src/utils.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import {
2525
MongoParseError,
2626
MongoRuntimeError
2727
} from './error';
28-
import type { Explain } from './explain';
28+
import type { ExplainCommandOptions2, ExplainVerbosity } from './explain';
2929
import type { MongoClient } from './mongo_client';
3030
import type { CommandOperationOptions, OperationParent } from './operations/command';
3131
import type { Hint, OperationOptions } from './operations/operation';
@@ -252,12 +252,27 @@ export function decorateWithReadConcern(
252252
* @param command - the command on which to apply the explain
253253
* @param options - the options containing the explain verbosity
254254
*/
255-
export function decorateWithExplain(command: Document, explain: Explain): Document {
256-
if (command.explain) {
257-
return command;
255+
export function decorateWithExplain(
256+
command: Document,
257+
explainOptions: ExplainCommandOptions2
258+
): {
259+
explain: Document;
260+
verbosity: ExplainVerbosity;
261+
maxTimeMS?: number;
262+
} {
263+
type ExplainCommand = ReturnType<typeof decorateWithExplain>;
264+
if ('explain' in command && 'verbosity' in command) {
265+
return command as ExplainCommand;
258266
}
259267

260-
return { explain: command, verbosity: explain.verbosity };
268+
const { explain, maxTimeMS } = explainOptions;
269+
const { verbosity } = explain;
270+
271+
const baseCommand: ExplainCommand = { explain: command, verbosity };
272+
if (typeof maxTimeMS === 'number') {
273+
baseCommand.maxTimeMS = maxTimeMS;
274+
}
275+
return baseCommand;
261276
}
262277

263278
/**

0 commit comments

Comments
 (0)