From 6d30520a8560a3df9bce6bfcfb762bfb0f53f372 Mon Sep 17 00:00:00 2001 From: Bertrand Marron Date: Wed, 17 Nov 2021 13:38:36 +0100 Subject: [PATCH] fix: make _id optional in replacement for replaceOne operations The _id field is immutable in a replaceOne operation, so it does not make sense to require passing it. Also, this makes replaceOne consistent with insertOne. --- src/bulk/common.ts | 2 +- src/collection.ts | 13 ++++++----- .../community/collection/bulkWrite.test-d.ts | 18 +++++++++++++++ .../community/collection/replaceX.test-d.ts | 22 +++++++++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 test/types/community/collection/replaceX.test-d.ts diff --git a/src/bulk/common.ts b/src/bulk/common.ts index d25fe09753..48503f5bb3 100644 --- a/src/bulk/common.ts +++ b/src/bulk/common.ts @@ -79,7 +79,7 @@ export interface ReplaceOneModel { /** The filter to limit the replaced document. */ filter: Filter; /** The document with which to replace the matched document. */ - replacement: TSchema; + replacement: OptionalId; /** Specifies a collation. */ collation?: CollationOptions; /** The index to use. If specified, then the query system will only consider plans using the hinted index. */ diff --git a/src/collection.ts b/src/collection.ts index 598af08d3b..7173cca0bd 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -459,26 +459,29 @@ export class Collection { * @param options - Optional settings for the command * @param callback - An optional callback, a Promise will be returned if none is provided */ - replaceOne(filter: Filter, replacement: TSchema): Promise; replaceOne( filter: Filter, - replacement: TSchema, + replacement: OptionalId + ): Promise; + replaceOne( + filter: Filter, + replacement: OptionalId, callback: Callback ): void; replaceOne( filter: Filter, - replacement: TSchema, + replacement: OptionalId, options: ReplaceOptions ): Promise; replaceOne( filter: Filter, - replacement: TSchema, + replacement: OptionalId, options: ReplaceOptions, callback: Callback ): void; replaceOne( filter: Filter, - replacement: TSchema, + replacement: OptionalId, options?: ReplaceOptions | Callback, callback?: Callback ): Promise | void { diff --git a/test/types/community/collection/bulkWrite.test-d.ts b/test/types/community/collection/bulkWrite.test-d.ts index 82f9e6aae5..00cf7961a5 100644 --- a/test/types/community/collection/bulkWrite.test-d.ts +++ b/test/types/community/collection/bulkWrite.test-d.ts @@ -181,6 +181,24 @@ collectionType.bulkWrite([ } } ]); +// allow a replacement doc without an _id +collectionType.bulkWrite([ + { + replaceOne: { + filter: {}, + replacement: { + dateField: new Date(), + fruitTags: [], + numberField: 0, + readonlyFruitTags: [], + stringField: 'string', + subInterfaceArray: [], + subInterfaceField: { field1: '1', field2: '2' } + }, + upsert: true + } + } +]); expectError( collectionType.bulkWrite([ diff --git a/test/types/community/collection/replaceX.test-d.ts b/test/types/community/collection/replaceX.test-d.ts new file mode 100644 index 0000000000..5519b66cc1 --- /dev/null +++ b/test/types/community/collection/replaceX.test-d.ts @@ -0,0 +1,22 @@ +import { expectError } from 'tsd'; +import { MongoClient, ObjectId } from '../../../../src'; + +// test collection.replaceX functions +const client = new MongoClient(''); +const db = client.db('test'); + +interface TestModel { + _id: ObjectId; + stringField: string; +} + +const collection = db.collection('testCollection'); + +// should accept a replacement doc with an _id +await collection.replaceOne({}, { _id: new ObjectId(), stringField: 'a' }); + +// should accept a replacement doc without an _id +await collection.replaceOne({}, { stringField: 'b' }); + +// should not allow _id with a non-ObjectId type +expectError(await collection.replaceOne({}, { _id: 1, stringField: 'c' }));