Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import {
type ListDatabasesResult
} from './operations/list_databases';
import { RemoveUserOperation, type RemoveUserOptions } from './operations/remove_user';
import { RunAdminCommandOperation, type RunCommandOptions } from './operations/run_command';
import { RunCommandOperation, type RunCommandOptions } from './operations/run_command';
import {
ValidateCollectionOperation,
type ValidateCollectionOptions
} from './operations/validate_collection';
import { MongoDBNamespace } from './utils';

/** @internal */
export interface AdminPrivate {
Expand Down Expand Up @@ -75,7 +76,7 @@ export class Admin {
async command(command: Document, options?: RunCommandOptions): Promise<Document> {
return await executeOperation(
this.s.db.client,
new RunAdminCommandOperation(command, {
new RunCommandOperation(new MongoDBNamespace('admin'), command, {
...resolveBSONOptions(options),
session: options?.session,
readPreference: options?.readPreference,
Expand Down
6 changes: 6 additions & 0 deletions src/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from './cursor/list_search_indexes_cursor';
import type { Db } from './db';
import { MongoAPIError, MongoInvalidArgumentError, MongoOperationTimeoutError } from './error';
import { type ExplainCommandOptions, type ExplainVerbosityLike } from './explain';
import type { MongoClient, PkFactory } from './mongo_client';
import type {
Abortable,
Expand Down Expand Up @@ -863,6 +864,11 @@ export class Collection<TSchema extends Document = Document> {
filter: Filter<TSchema>,
options: DistinctOptions
): Promise<Array<Flatten<WithId<TSchema>[Key]>>>;
distinct<Key extends keyof WithId<TSchema>>(
key: Key,
filter: Filter<TSchema>,
options: DistinctOptions & { explain: ExplainVerbosityLike | ExplainCommandOptions }
): Promise<Document>;

// Embedded documents overload
distinct(key: string): Promise<any[]>;
Expand Down
9 changes: 4 additions & 5 deletions src/cursor/run_command_cursor.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { BSONSerializeOptions, Document } from '../bson';
import { CursorResponse } from '../cmap/wire_protocol/responses';
import { type CursorResponse } from '../cmap/wire_protocol/responses';
import type { Db } from '../db';
import { MongoAPIError, MongoRuntimeError } from '../error';
import { executeOperation } from '../operations/execute_operation';
import { GetMoreOperation } from '../operations/get_more';
import { RunCommandOperation } from '../operations/run_command';
import { RunCursorCommandOperation } from '../operations/run_command';
import type { ReadConcernLike } from '../read_concern';
import type { ReadPreferenceLike } from '../read_preference';
import type { ClientSession } from '../sessions';
Expand Down Expand Up @@ -143,11 +143,10 @@ export class RunCommandCursor extends AbstractCursor {

/** @internal */
protected async _initialize(session: ClientSession): Promise<InitialCursorResponse> {
const operation = new RunCommandOperation<CursorResponse>(this.db, this.command, {
const operation = new RunCursorCommandOperation(this.db.s.namespace, this.command, {
...this.cursorOptions,
session: session,
readPreference: this.cursorOptions.readPreference,
responseType: CursorResponse
readPreference: this.cursorOptions.readPreference
});

const response = await executeOperation(this.client, operation, this.timeoutContext);
Expand Down
2 changes: 1 addition & 1 deletion src/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ export class Db {
return await executeOperation(
this.client,
new RunCommandOperation(
this,
this.s.namespace,
command,
resolveOptions(undefined, {
...resolveBSONOptions(options),
Expand Down
33 changes: 24 additions & 9 deletions src/mongo_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { promises as fs } from 'fs';
import type { TcpNetConnectOpts } from 'net';
import type { ConnectionOptions as TLSConnectionOptions, TLSSocketOptions } from 'tls';

import { type ServerCommandOptions, type TimeoutContext } from '.';
import { type BSONSerializeOptions, type Document, resolveBSONOptions } from './bson';
import { ChangeStream, type ChangeStreamDocument, type ChangeStreamOptions } from './change_stream';
import type { AutoEncrypter, AutoEncryptionOptions } from './client-side-encryption/auto_encrypter';
Expand All @@ -20,6 +21,7 @@ import {
makeClientMetadata
} from './cmap/handshake/client_metadata';
import type { CompressorName } from './cmap/wire_protocol/compression';
import { MongoDBResponse } from './cmap/wire_protocol/responses';
import { parseOptions, resolveSRVRecord } from './connection_string';
import { MONGO_CLIENT_EVENTS } from './constants';
import { type AbstractCursor } from './cursor/abstract_cursor';
Expand All @@ -42,7 +44,7 @@ import {
} from './operations/client_bulk_write/common';
import { ClientBulkWriteExecutor } from './operations/client_bulk_write/executor';
import { executeOperation } from './operations/execute_operation';
import { RunAdminCommandOperation } from './operations/run_command';
import { ModernizedOperation } from './operations/operation';
import type { ReadConcern, ReadConcernLevel, ReadConcernLike } from './read_concern';
import { ReadPreference, type ReadPreferenceMode } from './read_preference';
import { type AsyncDisposable, configureResourceManagement } from './resource_management';
Expand All @@ -60,7 +62,7 @@ import {
type HostAddress,
hostMatchesWildcards,
isHostMatch,
type MongoDBNamespace,
MongoDBNamespace,
noop,
ns,
resolveOptions,
Expand Down Expand Up @@ -790,13 +792,26 @@ export class MongoClient extends TypedEventEmitter<MongoClientEvents> implements
const endSessions = Array.from(this.s.sessionPool.sessions, ({ id }) => id);
if (endSessions.length !== 0) {
try {
await executeOperation(
this,
new RunAdminCommandOperation(
{ endSessions },
{ readPreference: ReadPreference.primaryPreferred, noResponse: true }
)
);
class EndSessionsOperation extends ModernizedOperation<void> {
override ns = MongoDBNamespace.fromString('admin.$cmd');
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override buildCommand(_connection: Connection, _session?: ClientSession): Document {
return {
endSessions
};
}
override buildOptions(timeoutContext: TimeoutContext): ServerCommandOptions {
return {
timeoutContext,
readPreference: ReadPreference.primaryPreferred,
noResponse: true
};
}
override get commandName(): string {
return 'endSessions';
}
}
await executeOperation(this, new EndSessionsOperation());
} catch (error) {
squashError(error);
}
Expand Down
65 changes: 24 additions & 41 deletions src/operations/distinct.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import type { Document } from '../bson';
import { type Document } from '../bson';
import { type Connection } from '../cmap/connection';
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
import type { Collection } from '../collection';
import type { Server } from '../sdam/server';
import type { ClientSession } from '../sessions';
import { type TimeoutContext } from '../timeout';
import { decorateWithCollation, decorateWithReadConcern } from '../utils';
import { CommandOperation, type CommandOperationOptions } from './command';
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
import { Aspect, defineAspects } from './operation';

/** @public */
Expand All @@ -27,7 +25,8 @@ export type DistinctOptions = CommandOperationOptions & {
* Return a list of distinct values for the given key across a collection.
* @internal
*/
export class DistinctOperation extends CommandOperation<any[]> {
export class DistinctOperation extends ModernizedCommandOperation<any[] | Document> {
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override options: DistinctOptions;
collection: Collection;
/** Field of the document to find distinct values for. */
Expand Down Expand Up @@ -56,48 +55,32 @@ export class DistinctOperation extends CommandOperation<any[]> {
return 'distinct' as const;
}

override async execute(
server: Server,
session: ClientSession | undefined,
timeoutContext: TimeoutContext
): Promise<any[]> {
const coll = this.collection;
const key = this.key;
const query = this.query;
const options = this.options;

// Distinct command
const cmd: Document = {
distinct: coll.collectionName,
key: key,
query: query
override buildCommandDocument(_connection: Connection): Document {
const command: Document = {
distinct: this.collection.collectionName,
key: this.key,
query: this.query
};

// Add maxTimeMS if defined
if (typeof options.maxTimeMS === 'number') {
cmd.maxTimeMS = options.maxTimeMS;
}

// we check for undefined specifically here to allow falsy values
// eslint-disable-next-line no-restricted-syntax
if (typeof options.comment !== 'undefined') {
cmd.comment = options.comment;
if (this.options.comment !== undefined) {
command.comment = this.options.comment;
}

if (options.hint != null) {
cmd.hint = options.hint;
if (this.options.hint != null) {
command.hint = this.options.hint;
}

// Do we have a readConcern specified
decorateWithReadConcern(cmd, coll, options);

// Have we specified collation
decorateWithCollation(cmd, coll, options);

const result = await super.executeCommand(server, session, cmd, timeoutContext);
return command;
}

// @ts-expect-error: Explain always returns a document
return this.explain ? result : result.values;
override handleOk(
response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
): any[] | Document {
if (this.explain) {
return response.toObject(this.bsonOptions);
}
return response.toObject(this.bsonOptions).values;
}
}

Expand Down
32 changes: 19 additions & 13 deletions src/operations/profiling_level.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import { BSONType, type Document } from '../bson';
import { type Connection } from '../cmap/connection';
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
import type { Db } from '../db';
import { MongoUnexpectedServerResponseError } from '../error';
import type { Server } from '../sdam/server';
import type { ClientSession } from '../sessions';
import { type TimeoutContext } from '../timeout';
import { CommandOperation, type CommandOperationOptions } from './command';
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';

/** @public */
export type ProfilingLevelOptions = CommandOperationOptions;

class ProfilingLevelResponse extends MongoDBResponse {
get was() {
return this.get('was', BSONType.int, true);
}
}

/** @internal */
export class ProfilingLevelOperation extends CommandOperation<string> {
export class ProfilingLevelOperation extends ModernizedCommandOperation<string> {
override SERVER_COMMAND_RESPONSE_TYPE = ProfilingLevelResponse;
override options: ProfilingLevelOptions;

constructor(db: Db, options: ProfilingLevelOptions) {
Expand All @@ -21,14 +28,13 @@ export class ProfilingLevelOperation extends CommandOperation<string> {
return 'profile' as const;
}

override async execute(
server: Server,
session: ClientSession | undefined,
timeoutContext: TimeoutContext
): Promise<string> {
const doc = await super.executeCommand(server, session, { profile: -1 }, timeoutContext);
if (doc.ok === 1) {
const was = doc.was;
override buildCommandDocument(_connection: Connection): Document {
return { profile: -1 };
}

override handleOk(response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): string {
if (response.ok === 1) {
const was = response.was;
if (was === 0) return 'off';
if (was === 1) return 'slow_only';
if (was === 2) return 'all';
Expand Down
22 changes: 11 additions & 11 deletions src/operations/remove_user.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import { type Document } from '../bson';
import { type Connection } from '../cmap/connection';
import { MongoDBResponse } from '../cmap/wire_protocol/responses';
import type { Db } from '../db';
import type { Server } from '../sdam/server';
import type { ClientSession } from '../sessions';
import { type TimeoutContext } from '../timeout';
import { CommandOperation, type CommandOperationOptions } from './command';
import { type CommandOperationOptions, ModernizedCommandOperation } from './command';
import { Aspect, defineAspects } from './operation';

/** @public */
export type RemoveUserOptions = CommandOperationOptions;

/** @internal */
export class RemoveUserOperation extends CommandOperation<boolean> {
export class RemoveUserOperation extends ModernizedCommandOperation<boolean> {
override SERVER_COMMAND_RESPONSE_TYPE = MongoDBResponse;
override options: RemoveUserOptions;
username: string;

Expand All @@ -23,12 +24,11 @@ export class RemoveUserOperation extends CommandOperation<boolean> {
return 'dropUser' as const;
}

override async execute(
server: Server,
session: ClientSession | undefined,
timeoutContext: TimeoutContext
): Promise<boolean> {
await super.executeCommand(server, session, { dropUser: this.username }, timeoutContext);
override buildCommandDocument(_connection: Connection): Document {
return { dropUser: this.username };
}

override handleOk(_response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>): boolean {
return true;
}
}
Expand Down
Loading