Skip to content

refactor: consolidate options inheritance logic #2614

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

126 changes: 71 additions & 55 deletions src/collection.ts

Large diffs are not rendered by default.

114 changes: 45 additions & 69 deletions src/db.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { deprecate } from 'util';
import { emitDeprecatedOptionWarning, Callback } from './utils';
import {
emitDeprecatedOptionWarning,
Callback,
resolveOptions,
filterOptions,
deprecateOptions,
MongoDBNamespace,
getTopology
} from './utils';
import { loadAdmin } from './dynamic_loaders';
import { AggregationCursor, CommandCursor } from './cursor';
import { ObjectId, Code, Document, BSONSerializeOptions, resolveBSONOptions } from './bson';
Expand All @@ -11,13 +19,6 @@ import * as CONSTANTS from './constants';
import { WriteConcern, WriteConcernOptions } from './write_concern';
import { ReadConcern } from './read_concern';
import { Logger, LoggerOptions } from './logger';
import {
filterOptions,
mergeOptionsAndWriteConcern,
deprecateOptions,
MongoDBNamespace,
getTopology
} from './utils';
import { AggregateOperation, AggregateOptions } from './operations/aggregate';
import { AddUserOperation, AddUserOptions } from './operations/add_user';
import { CollectionsOperation } from './operations/collections';
Expand Down Expand Up @@ -254,12 +255,10 @@ export class Db implements OperationParent {
callback?: Callback<Collection>
): Promise<Collection> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};
options.readConcern = ReadConcern.fromOptions(options) ?? this.readConcern;

return executeOperation(
getTopology(this),
new CreateCollectionOperation(this, name, options),
new CreateCollectionOperation(this, name, resolveOptions(this, options)),
callback
);
}
Expand All @@ -281,11 +280,11 @@ export class Db implements OperationParent {
callback?: Callback<Document>
): Promise<Document> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

// Intentionally, we do not inherit options from parent for this operation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add this to the function's docs for the ops that do this. Particularly with BSON options the return value could be unexpectedly different.

return executeOperation(
getTopology(this),
new RunCommandOperation(this, command, options),
new RunCommandOperation(this, command, options ?? {}),
callback
);
}
Expand All @@ -307,8 +306,7 @@ export class Db implements OperationParent {
throw new TypeError('`options` parameter must not be function');
}

options = options || {};

options = resolveOptions(this, options);
const cursor = new AggregationCursor(
getTopology(this),
new AggregateOperation(this, pipeline, options),
Expand Down Expand Up @@ -341,21 +339,10 @@ export class Db implements OperationParent {
callback?: Callback<Collection>
): Collection | void {
if (typeof options === 'function') (callback = options), (options = {});
options = Object.assign({}, options);

// If we have not set a collection level readConcern set the db level one
options.readConcern = ReadConcern.fromOptions(options) ?? this.readConcern;

// Merge in all needed options and ensure correct writeConcern merging from db level
const finalOptions = mergeOptionsAndWriteConcern(
options,
this.s.options ?? {},
collectionKeys,
true
) as CollectionOptions;
const finalOptions = resolveOptions(this, options);

// Execute
if (finalOptions == null || !finalOptions.strict) {
if (!finalOptions.strict) {
try {
const collection = new Collection(this, name, finalOptions);
if (callback) callback(undefined, collection);
Expand Down Expand Up @@ -414,9 +401,11 @@ export class Db implements OperationParent {
callback?: Callback<Document>
): Promise<Document> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(getTopology(this), new DbStatsOperation(this, options), callback);
return executeOperation(
getTopology(this),
new DbStatsOperation(this, resolveOptions(this, options)),
callback
);
}

/**
Expand All @@ -427,7 +416,7 @@ export class Db implements OperationParent {
*/
listCollections(filter?: Document, options?: ListCollectionsOptions): CommandCursor {
filter = filter || {};
options = options || {};
options = resolveOptions(this, options);

return new CommandCursor(
getTopology(this),
Expand Down Expand Up @@ -468,7 +457,9 @@ export class Db implements OperationParent {
callback?: Callback<Collection>
): Promise<Collection> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = Object.assign({}, options, { readPreference: ReadPreference.PRIMARY });

// Intentionally, we do not inherit options from parent for this operation.
options = { ...options, readPreference: ReadPreference.PRIMARY };

// Add return new collection
options.new_collection = true;
Expand Down Expand Up @@ -497,11 +488,10 @@ export class Db implements OperationParent {
callback?: Callback<boolean>
): Promise<boolean> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(
getTopology(this),
new DropCollectionOperation(this, name, options),
new DropCollectionOperation(this, name, resolveOptions(this, options)),
callback
);
}
Expand All @@ -521,9 +511,12 @@ export class Db implements OperationParent {
callback?: Callback<boolean>
): Promise<boolean> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(getTopology(this), new DropDatabaseOperation(this, options), callback);
return executeOperation(
getTopology(this),
new DropDatabaseOperation(this, resolveOptions(this, options)),
callback
);
}

/**
Expand All @@ -541,9 +534,12 @@ export class Db implements OperationParent {
callback?: Callback<Collection[]>
): Promise<Collection[]> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(getTopology(this), new CollectionsOperation(this, options), callback);
return executeOperation(
getTopology(this),
new CollectionsOperation(this, resolveOptions(this, options)),
callback
);
}

/**
Expand All @@ -567,11 +563,11 @@ export class Db implements OperationParent {
callback?: Callback<void>
): Promise<void> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

// Intentionally, we do not inherit options from parent for this operation.
return executeOperation(
getTopology(this),
new RunAdminCommandOperation(this, command, options),
new RunAdminCommandOperation(this, command, options ?? {}),
callback
);
}
Expand Down Expand Up @@ -604,11 +600,10 @@ export class Db implements OperationParent {
callback?: Callback<Document>
): Promise<Document> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options ? Object.assign({}, options) : {};

return executeOperation(
getTopology(this),
new CreateIndexOperation(this, name, indexSpec, options),
new CreateIndexOperation(this, name, indexSpec, resolveOptions(this, options)),
callback
);
}
Expand Down Expand Up @@ -652,10 +647,9 @@ export class Db implements OperationParent {
if (typeof options === 'function') (callback = options), (options = {});
}

options = options || {};
return executeOperation(
getTopology(this),
new AddUserOperation(this, username, password, options),
new AddUserOperation(this, username, password, resolveOptions(this, options)),
callback
);
}
Expand All @@ -677,11 +671,10 @@ export class Db implements OperationParent {
callback?: Callback<boolean>
): Promise<boolean> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(
getTopology(this),
new RemoveUserOperation(this, username, options),
new RemoveUserOperation(this, username, resolveOptions(this, options)),
callback
);
}
Expand Down Expand Up @@ -710,11 +703,10 @@ export class Db implements OperationParent {
callback?: Callback<ProfilingLevel>
): Promise<ProfilingLevel> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(
getTopology(this),
new SetProfilingLevelOperation(this, level, options),
new SetProfilingLevelOperation(this, level, resolveOptions(this, options)),
callback
);
}
Expand All @@ -734,11 +726,10 @@ export class Db implements OperationParent {
callback?: Callback<string>
): Promise<string> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(
getTopology(this),
new ProfilingLevelOperation(this, options),
new ProfilingLevelOperation(this, resolveOptions(this, options)),
callback
);
}
Expand All @@ -764,11 +755,10 @@ export class Db implements OperationParent {
callback?: Callback<Document>
): Promise<Document> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(
getTopology(this),
new IndexInformationOperation(this, name, options),
new IndexInformationOperation(this, name, resolveOptions(this, options)),
callback
);
}
Expand Down Expand Up @@ -835,11 +825,10 @@ export class Db implements OperationParent {
callback?: Callback<Document>
): Promise<Document> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(
getTopology(this),
new EvalOperation(this, code, parameters, options),
new EvalOperation(this, code, parameters, resolveOptions(this, options)),
callback
);
}
Expand Down Expand Up @@ -873,11 +862,10 @@ export class Db implements OperationParent {
callback?: Callback<Document>
): Promise<Document> | void {
if (typeof options === 'function') (callback = options), (options = {});
options = options || {};

return executeOperation(
getTopology(this),
new EnsureIndexOperation(this, name, fieldOrSpec, options),
new EnsureIndexOperation(this, name, fieldOrSpec, resolveOptions(this, options)),
callback
);
}
Expand Down Expand Up @@ -905,18 +893,6 @@ export class Db implements OperationParent {
}
}

const collectionKeys = [
'pkFactory',
'readPreference',
'serializeFunctions',
'strict',
'readConcern',
'ignoreUndefined',
'promoteValues',
'promoteBuffers',
'promoteLongs'
];

Db.prototype.createCollection = deprecateOptions(
{
name: 'Db.createCollection',
Expand Down
20 changes: 5 additions & 15 deletions src/operations/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,13 @@ export abstract class CommandOperation<
: new MongoDBNamespace('admin', '$cmd');
}

const propertyProvider = this.hasAspect(Aspect.NO_INHERIT_OPTIONS) ? undefined : parent;
this.readPreference = this.hasAspect(Aspect.WRITE_OPERATION)
? ReadPreference.primary
: ReadPreference.resolve(propertyProvider, this.options);
this.readConcern = resolveReadConcern(propertyProvider, this.options);
this.writeConcern = resolveWriteConcern(propertyProvider, this.options);
: ReadPreference.fromOptions(options) ?? ReadPreference.primary;
this.readConcern = ReadConcern.fromOptions(options);
this.writeConcern = WriteConcern.fromOptions(options);
this.bsonOptions = resolveBSONOptions(options);

this.explain = false;
this.fullResponse =
options && typeof options.fullResponse === 'boolean' ? options.fullResponse : false;
Expand All @@ -91,9 +92,6 @@ export abstract class CommandOperation<
if (parent && parent.logger) {
this.logger = parent.logger;
}

// Assign BSON serialize options to OperationBase, preferring options over parent options.
this.bsonOptions = resolveBSONOptions(options, parent);
}

abstract execute(server: Server, callback: Callback<TResult>): void;
Expand Down Expand Up @@ -149,11 +147,3 @@ export abstract class CommandOperation<
);
}
}

function resolveWriteConcern(parent: OperationParent | undefined, options: any) {
return WriteConcern.fromOptions(options) || parent?.writeConcern;
}

function resolveReadConcern(parent: OperationParent | undefined, options: any) {
return ReadConcern.fromOptions(options) || parent?.readConcern;
}
10 changes: 8 additions & 2 deletions src/operations/create_collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ const ILLEGAL_COMMAND_FIELDS = new Set([
'j',
'fsync',
'autoIndexId',
'serializeFunctions',
'pkFactory',
'raw',
'readPreference',
'session',
'readConcern',
'writeConcern'
'writeConcern',
'raw',
'fieldsAsRaw',
'promoteLongs',
'promoteValues',
'promoteBuffers',
'serializeFunctions',
'ignoreUndefined'
]);

/** @public */
Expand Down
3 changes: 0 additions & 3 deletions src/operations/find.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Aspect, defineAspects, Hint } from './operation';
import { ReadPreference } from '../read_preference';
import { maxWireVersion, MongoDBNamespace, Callback, normalizeHintField } from '../utils';
import { MongoError } from '../error';
import type { Document } from '../bson';
Expand Down Expand Up @@ -64,7 +63,6 @@ const SUPPORTS_WRITE_CONCERN_AND_COLLATION = 5;
export class FindOperation extends CommandOperation<FindOptions, Document> {
cmd: Document;
filter: Document;
readPreference: ReadPreference;

hint?: Hint;

Expand All @@ -76,7 +74,6 @@ export class FindOperation extends CommandOperation<FindOptions, Document> {
) {
super(collection, options);
this.ns = ns;
this.readPreference = ReadPreference.resolve(collection, this.options);

if (typeof filter !== 'object' || Array.isArray(filter)) {
throw new MongoError('Query filter must be a plain object or ObjectId');
Expand Down
Loading