Skip to content

Commit 4f9d4ce

Browse files
author
Thomas Reggi
authored
fix: typings for readConcern
NODE-2806
1 parent fe4821c commit 4f9d4ce

File tree

8 files changed

+45
-25
lines changed

8 files changed

+45
-25
lines changed

src/change_stream.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const CHANGE_DOMAIN_TYPES = {
3434
CLUSTER: Symbol('Cluster')
3535
};
3636

37+
/** @public */
3738
export interface ResumeOptions {
3839
startAtOperationTime?: Timestamp;
3940
batchSize?: number;

src/collection.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { UnorderedBulkOperation } from './bulk/unordered';
1414
import { OrderedBulkOperation } from './bulk/ordered';
1515
import { ChangeStream, ChangeStreamOptions } from './change_stream';
1616
import { WriteConcern, WriteConcernOptions } from './write_concern';
17-
import { ReadConcern } from './read_concern';
17+
import { ReadConcern, ReadConcernLike } from './read_concern';
1818
import { AggregationCursor, CommandCursor, Cursor } from './cursor';
1919
import { AggregateOperation, AggregateOptions } from './operations/aggregate';
2020
import { BulkWriteOperation } from './operations/bulk_write';
@@ -113,7 +113,7 @@ export interface CollectionOptions
113113
/** Returns an error if the collection does not exist */
114114
strict?: boolean;
115115
/** Specify a read concern for the collection. (only MongoDB 3.2 or higher supported) */
116-
readConcern?: ReadConcern;
116+
readConcern?: ReadConcernLike;
117117
/** The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST). */
118118
readPreference?: ReadPreferenceLike;
119119
}

src/db.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,7 @@ export class Db implements OperationParent {
250250
): Promise<Collection> | void {
251251
if (typeof options === 'function') (callback = options), (options = {});
252252
options = options || {};
253-
options.readConcern = options.readConcern
254-
? new ReadConcern(options.readConcern.level)
255-
: this.readConcern;
253+
options.readConcern = ReadConcern.fromOptions(options) ?? this.readConcern;
256254

257255
return executeOperation(
258256
this.s.topology,
@@ -340,9 +338,7 @@ export class Db implements OperationParent {
340338
options = Object.assign({}, options);
341339

342340
// If we have not set a collection level readConcern set the db level one
343-
options.readConcern = options.readConcern
344-
? new ReadConcern(options.readConcern.level)
345-
: this.readConcern;
341+
options.readConcern = ReadConcern.fromOptions(options) ?? this.readConcern;
346342

347343
// Do we have ignoreUndefined set
348344
if (this.s.options?.ignoreUndefined) {

src/index.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ export type {
104104
ResumeToken,
105105
PipeOptions,
106106
ChangeStreamCursorOptions,
107-
OperationTime
107+
OperationTime,
108+
ResumeOptions
108109
} from './change_stream';
109110
export type { AuthMechanism } from './cmap/auth/defaultAuthProviders';
110111
export type { MongoCredentials, MongoCredentialsOptions } from './cmap/auth/mongo_credentials';
@@ -239,12 +240,18 @@ export type { ProfilingLevel, SetProfilingLevelOptions } from './operations/set_
239240
export type { CollStatsOptions, DbStatsOptions } from './operations/stats';
240241
export type { UpdateResult, UpdateOptions } from './operations/update';
241242
export type { ValidateCollectionOptions } from './operations/validate_collection';
242-
export type { ReadConcern, ReadConcernLevel } from './read_concern';
243+
export type {
244+
ReadConcern,
245+
ReadConcernLevel,
246+
ReadConcernLike,
247+
ReadConcernLevelLike
248+
} from './read_concern';
243249
export type {
244250
ReadPreferenceLike,
245251
ReadPreferenceMode,
246252
ReadPreferenceOptions,
247253
ReadPreferenceLikeOptions,
254+
ReadPreferenceFromOptions,
248255
HedgeOptions
249256
} from './read_preference';
250257
export type { ClusterTime, ServerType, TimerQueue, TopologyType } from './sdam/common';

src/mongo_client.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { deprecate } from 'util';
99
import { connect, validOptions } from './operations/connect';
1010
import { PromiseProvider } from './promise_provider';
1111
import { Logger } from './logger';
12-
import { ReadConcernLevel, ReadConcern } from './read_concern';
12+
import { ReadConcern, ReadConcernLevelLike, ReadConcernLike } from './read_concern';
1313
import type { BSONSerializeOptions, Document } from './bson';
1414
import type { AutoEncryptionOptions } from './deps';
1515
import type { CompressorName } from './cmap/wire_protocol/compression';
@@ -91,7 +91,7 @@ export interface MongoURIOptions extends Pick<WriteConcernOptions, 'journal' | '
9191
/** The maximum time in milliseconds that a thread can wait for a connection to become available. */
9292
waitQueueTimeoutMS?: number;
9393
/** The level of isolation */
94-
readConcernLevel?: ReadConcernLevel;
94+
readConcernLevel?: ReadConcernLevelLike;
9595
/** Specifies the read preferences for this connection */
9696
readPreference?: ReadPreferenceMode | ReadPreference;
9797
/** Specifies, in seconds, how stale a secondary can be before the client stops using it for read operations. */
@@ -174,7 +174,7 @@ export interface MongoClientOptions
174174
/** A Promise library class the application wishes to use such as Bluebird, must be ES6 compatible */
175175
promiseLibrary?: any;
176176
/** Specify a read concern for the collection (only MongoDB 3.2 or higher supported) */
177-
readConcern?: ReadConcern;
177+
readConcern?: ReadConcernLike;
178178
/** The logging level */
179179
loggerLevel?: LogLevel;
180180
/** Custom logger object */

src/operations/command.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { Logger } from '../logger';
99
import type { Server } from '../sdam/server';
1010
import type { Document } from '../bson';
1111
import type { CollationOptions } from '../cmap/wire_protocol/write_command';
12+
import type { ReadConcernLike } from './../read_concern';
1213

1314
const SUPPORTS_WRITE_CONCERN_AND_COLLATION = 5;
1415

@@ -17,7 +18,7 @@ export interface CommandOperationOptions extends OperationOptions, WriteConcernO
1718
/** Return the full server response for the command */
1819
fullResponse?: boolean;
1920
/** Specify a read concern and level for the collection. (only MongoDB 3.2 or higher supported) */
20-
readConcern?: ReadConcern;
21+
readConcern?: ReadConcernLike;
2122
/** The preferred read preference (ReadPreference.primary, ReadPreference.primary_preferred, ReadPreference.secondary, ReadPreference.secondary_preferred, ReadPreference.nearest). */
2223
readPreference?: ReadPreferenceLike;
2324
/** Collation */

src/operations/find.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type { Server } from '../sdam/server';
1313
import type { Collection } from '../collection';
1414
import type { CollationOptions } from '../cmap/wire_protocol/write_command';
1515
import type { QueryOptions } from '../cmap/wire_protocol/query';
16-
import { CommandOperation } from './command';
16+
import { CommandOperation, CommandOperationOptions } from './command';
1717

1818
/** @public */
1919
export type SortDirection = 1 | -1 | 'asc' | 'desc' | { $meta: string };
@@ -24,7 +24,7 @@ export type Sort =
2424
| [string, SortDirection];
2525

2626
/** @public */
27-
export interface FindOptions extends QueryOptions {
27+
export interface FindOptions extends QueryOptions, CommandOperationOptions {
2828
/** Sets the limit of documents returned in the query. */
2929
limit?: number;
3030
/** Set to sort the documents coming back from the query. Array of indexes, `[['a', 1]]` etc. */

src/read_concern.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ export enum ReadConcernLevel {
77
snapshot = 'snapshot'
88
}
99

10+
/** @public */
11+
export type ReadConcernLevelLike = ReadConcernLevel | keyof typeof ReadConcernLevel;
12+
13+
/** @public */
14+
export type ReadConcernLike = ReadConcern | { level: ReadConcernLevelLike } | ReadConcernLevelLike;
15+
1016
/**
1117
* The MongoDB ReadConcern, which allows for control of the consistency and isolation properties
1218
* of the data read from replica sets and replica set shards.
@@ -15,11 +21,17 @@ export enum ReadConcernLevel {
1521
* @see https://docs.mongodb.com/manual/reference/read-concern/index.html
1622
*/
1723
export class ReadConcern {
18-
level: ReadConcernLevel;
24+
level: ReadConcernLevel | string;
1925

2026
/** Constructs a ReadConcern from the read concern level.*/
21-
constructor(level: ReadConcernLevel) {
22-
this.level = level;
27+
constructor(level: ReadConcernLevelLike) {
28+
/**
29+
* A spec test exists that allows level to be any string.
30+
* "invalid readConcern with out stage"
31+
* @see ./test/spec/crud/v2/aggregate-out-readConcern.json
32+
* @see https://github.com/mongodb/specifications/blob/master/source/read-write-concern/read-write-concern.rst#unknown-levels-and-additional-options-for-string-based-readconcerns
33+
*/
34+
this.level = ReadConcernLevel[level] || level;
2335
}
2436

2537
/**
@@ -28,19 +40,22 @@ export class ReadConcern {
2840
* @param options - The options object from which to extract the write concern.
2941
*/
3042
static fromOptions(options?: {
31-
readConcern?: ReadConcern | { level: ReadConcernLevel };
32-
level?: ReadConcernLevel;
43+
readConcern?: ReadConcernLike;
44+
level?: ReadConcernLevelLike;
3345
}): ReadConcern | undefined {
3446
if (options == null) {
3547
return;
3648
}
3749

3850
if (options.readConcern) {
39-
if (options.readConcern instanceof ReadConcern) {
40-
return options.readConcern;
51+
const { readConcern } = options;
52+
if (readConcern instanceof ReadConcern) {
53+
return readConcern;
54+
} else if (typeof readConcern === 'string') {
55+
return new ReadConcern(readConcern);
56+
} else if ('level' in readConcern && readConcern.level) {
57+
return new ReadConcern(readConcern.level);
4158
}
42-
43-
return new ReadConcern(options.readConcern.level);
4459
}
4560

4661
if (options.level) {

0 commit comments

Comments
 (0)