diff --git a/.changeset/serious-tables-grow.md b/.changeset/serious-tables-grow.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/serious-tables-grow.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/firestore/exp/src/api/reference.ts b/packages/firestore/exp/src/api/reference.ts index 3f1bcdea6b0..63ff3cf8d9c 100644 --- a/packages/firestore/exp/src/api/reference.ts +++ b/packages/firestore/exp/src/api/reference.ts @@ -22,7 +22,9 @@ import * as firestore from '../../index'; import { Firestore } from './database'; import { DocumentKeyReference, - ParsedUpdateData + ParsedUpdateData, + convertSetToMutations, + convertUpdateToMutations } from '../../../src/api/user_data_reader'; import { debugAssert } from '../../../src/util/assert'; import { cast } from '../../../lite/src/api/util'; @@ -186,7 +188,9 @@ export function setDoc( return firestore ._getFirestoreClient() .then(firestoreClient => - firestoreClient.write(parsed.toMutations(ref._key, Precondition.none())) + firestoreClient.write( + convertSetToMutations(parsed, ref._key, Precondition.none()) + ) ); } @@ -234,7 +238,7 @@ export function updateDoc( ._getFirestoreClient() .then(firestoreClient => firestoreClient.write( - parsed.toMutations(ref._key, Precondition.exists(true)) + convertUpdateToMutations(parsed, ref._key, Precondition.exists(true)) ) ); } @@ -273,7 +277,7 @@ export function addDoc( ._getFirestoreClient() .then(firestoreClient => firestoreClient.write( - parsed.toMutations(docRef._key, Precondition.exists(false)) + convertSetToMutations(parsed, docRef._key, Precondition.exists(false)) ) ) .then(() => docRef); diff --git a/packages/firestore/exp/src/api/write_batch.ts b/packages/firestore/exp/src/api/write_batch.ts index 559355be2ab..0a98f76ae4f 100644 --- a/packages/firestore/exp/src/api/write_batch.ts +++ b/packages/firestore/exp/src/api/write_batch.ts @@ -20,16 +20,145 @@ import * as firestore from '../../index'; import { cast } from '../../../lite/src/api/util'; -import { WriteBatch } from '../../../lite/src/api/write_batch'; import { Firestore } from './database'; +import { + DeleteMutation, + Mutation, + Precondition +} from '../../../src/model/mutation'; +import { Code, FirestoreError } from '../../../src/util/error'; +import { applyFirestoreDataConverter } from '../../../src/api/database'; +import { + convertSetToMutations, + convertUpdateToMutations, + UserDataReader +} from '../../../src/api/user_data_reader'; +import { newUserDataReader } from '../../../lite/src/api/reference'; +import { FieldPath } from '../../../lite/src/api/field_path'; +import { validateReference } from '../../../lite/src/api/write_batch'; + +export class WriteBatch implements firestore.WriteBatch { + private readonly _dataReader: UserDataReader; + private _mutations = [] as Mutation[]; + private _committed = false; + + constructor(private readonly _firestore: Firestore) { + this._dataReader = newUserDataReader(_firestore); + } + + set(documentRef: firestore.DocumentReference, value: T): WriteBatch; + set( + documentRef: firestore.DocumentReference, + value: Partial, + options: firestore.SetOptions + ): WriteBatch; + set( + documentRef: firestore.DocumentReference, + value: T, + options?: firestore.SetOptions + ): WriteBatch { + this.verifyNotCommitted(); + const ref = validateReference(documentRef, this._firestore); + + const convertedValue = applyFirestoreDataConverter( + ref._converter, + value, + options + ); + const parsed = this._dataReader.parseSetData( + 'WriteBatch.set', + ref._key, + convertedValue, + ref._converter !== null, + options + ); + this._mutations = this._mutations.concat( + convertSetToMutations(parsed, ref._key, Precondition.none()) + ); + return this; + } + + update( + documentRef: firestore.DocumentReference, + value: firestore.UpdateData + ): WriteBatch; + update( + documentRef: firestore.DocumentReference, + field: string | firestore.FieldPath, + value: unknown, + ...moreFieldsAndValues: unknown[] + ): WriteBatch; + update( + documentRef: firestore.DocumentReference, + fieldOrUpdateData: string | firestore.FieldPath | firestore.UpdateData, + value?: unknown, + ...moreFieldsAndValues: unknown[] + ): WriteBatch { + this.verifyNotCommitted(); + const ref = validateReference(documentRef, this._firestore); + + let parsed; + + if ( + typeof fieldOrUpdateData === 'string' || + fieldOrUpdateData instanceof FieldPath + ) { + parsed = this._dataReader.parseUpdateVarargs( + 'WriteBatch.update', + ref._key, + fieldOrUpdateData, + value, + moreFieldsAndValues + ); + } else { + parsed = this._dataReader.parseUpdateData( + 'WriteBatch.update', + ref._key, + fieldOrUpdateData + ); + } + + this._mutations = this._mutations.concat( + convertUpdateToMutations(parsed, ref._key, Precondition.exists(true)) + ); + return this; + } + + delete(documentRef: firestore.DocumentReference): WriteBatch { + this.verifyNotCommitted(); + const ref = validateReference(documentRef, this._firestore); + this._mutations = this._mutations.concat( + new DeleteMutation(ref._key, Precondition.none()) + ); + return this; + } + + commit(): Promise { + this.verifyNotCommitted(); + this._committed = true; + if (this._mutations.length > 0) { + return this._firestore + ._getFirestoreClient() + .then(firestoreClient => firestoreClient.write(this._mutations)); + } + + return Promise.resolve(); + } + + private verifyNotCommitted(): void { + if (this._committed) { + throw new FirestoreError( + Code.FAILED_PRECONDITION, + 'A write batch can no longer be used after commit() ' + + 'has been called.' + ); + } + } +} export function writeBatch( firestore: firestore.FirebaseFirestore ): firestore.WriteBatch { const firestoreImpl = cast(firestore, Firestore); - return new WriteBatch(firestoreImpl, writes => - firestoreImpl - ._getFirestoreClient() - .then(firestoreClient => firestoreClient.write(writes)) - ); + return new WriteBatch(firestoreImpl); } diff --git a/packages/firestore/lite/src/api/reference.ts b/packages/firestore/lite/src/api/reference.ts index 845ab52faa4..be151c16b80 100644 --- a/packages/firestore/lite/src/api/reference.ts +++ b/packages/firestore/lite/src/api/reference.ts @@ -23,7 +23,10 @@ import { Firestore } from './database'; import { DocumentKeyReference, ParsedUpdateData, - UserDataReader + convertSetToWrites, + convertUpdateToWrites, + UserDataReader, + convertDeleteToWrite } from '../../../src/api/user_data_reader'; import { Bound, @@ -35,9 +38,9 @@ import { ResourcePath } from '../../../src/model/path'; import { AutoId } from '../../../src/util/misc'; import { DocumentSnapshot, + fieldPathFromArgument, QueryDocumentSnapshot, - QuerySnapshot, - fieldPathFromArgument + QuerySnapshot } from './snapshot'; import { invokeBatchGetDocumentsRpc, @@ -45,7 +48,7 @@ import { invokeRunQueryRpc } from '../../../src/remote/datastore'; import { hardAssert } from '../../../src/util/assert'; -import { DeleteMutation, Precondition } from '../../../src/model/mutation'; +import { Precondition } from '../../../src/model/mutation'; import { applyFirestoreDataConverter, BaseQuery, @@ -477,7 +480,12 @@ export function setDoc( .then(datastore => invokeCommitRpc( datastore, - parsed.toMutations(ref._key, Precondition.none()) + convertSetToWrites( + parsed, + datastore.serializer, + ref._key, + Precondition.none() + ) ) ); } @@ -526,7 +534,12 @@ export function updateDoc( .then(datastore => invokeCommitRpc( datastore, - parsed.toMutations(ref._key, Precondition.exists(true)) + convertUpdateToWrites( + parsed, + datastore.serializer, + ref._key, + Precondition.exists(true) + ) ) ); } @@ -539,7 +552,11 @@ export function deleteDoc( ._getDatastore() .then(datastore => invokeCommitRpc(datastore, [ - new DeleteMutation(ref._key, Precondition.none()) + convertDeleteToWrite( + datastore.serializer, + ref._key, + Precondition.none() + ) ]) ); } @@ -567,7 +584,12 @@ export function addDoc( .then(datastore => invokeCommitRpc( datastore, - parsed.toMutations(docRef._key, Precondition.exists(false)) + convertSetToWrites( + parsed, + datastore.serializer, + docRef._key, + Precondition.exists(false) + ) ) ) .then(() => docRef); diff --git a/packages/firestore/lite/src/api/write_batch.ts b/packages/firestore/lite/src/api/write_batch.ts index 5f7f6e824bb..3dea4906567 100644 --- a/packages/firestore/lite/src/api/write_batch.ts +++ b/packages/firestore/lite/src/api/write_batch.ts @@ -14,17 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import * as api from '../../../src/protos/firestore_proto_api'; import * as firestore from '../../index'; -import { - DeleteMutation, - Mutation, - Precondition -} from '../../../src/model/mutation'; +import { Precondition } from '../../../src/model/mutation'; import { Code, FirestoreError } from '../../../src/util/error'; import { applyFirestoreDataConverter } from '../../../src/api/database'; import { DocumentKeyReference, + convertDeleteToWrite, + convertSetToWrites, + convertUpdateToWrites, UserDataReader } from '../../../src/api/user_data_reader'; import { cast } from './util'; @@ -32,20 +32,21 @@ import { DocumentReference, newUserDataReader } from './reference'; import { Firestore } from './database'; import { invokeCommitRpc } from '../../../src/remote/datastore'; import { FieldPath } from './field_path'; +import { JsonProtoSerializer } from '../../../src/remote/serializer'; +import { newSerializer } from '../../../src/platform/serializer'; export class WriteBatch implements firestore.WriteBatch { // This is the lite version of the WriteBatch API used in the legacy SDK. The // class is a close copy but takes different input types. private readonly _dataReader: UserDataReader; - private _mutations = [] as Mutation[]; + private readonly _serializer: JsonProtoSerializer; + private _writes = [] as api.Write[]; private _committed = false; - constructor( - private readonly _firestore: Firestore, - private readonly _commitHandler: (m: Mutation[]) => Promise - ) { + constructor(private readonly _firestore: Firestore) { this._dataReader = newUserDataReader(_firestore); + this._serializer = newSerializer(_firestore._databaseId); } set(documentRef: firestore.DocumentReference, value: T): WriteBatch; @@ -74,8 +75,13 @@ export class WriteBatch implements firestore.WriteBatch { ref._converter !== null, options ); - this._mutations = this._mutations.concat( - parsed.toMutations(ref._key, Precondition.none()) + this._writes = this._writes.concat( + convertSetToWrites( + parsed, + this._serializer, + ref._key, + Precondition.none() + ) ); return this; } @@ -120,8 +126,13 @@ export class WriteBatch implements firestore.WriteBatch { ); } - this._mutations = this._mutations.concat( - parsed.toMutations(ref._key, Precondition.exists(true)) + this._writes = this._writes.concat( + convertUpdateToWrites( + parsed, + this._serializer, + ref._key, + Precondition.exists(true) + ) ); return this; } @@ -129,8 +140,8 @@ export class WriteBatch implements firestore.WriteBatch { delete(documentRef: firestore.DocumentReference): WriteBatch { this.verifyNotCommitted(); const ref = validateReference(documentRef, this._firestore); - this._mutations = this._mutations.concat( - new DeleteMutation(ref._key, Precondition.none()) + this._writes = this._writes.concat( + convertDeleteToWrite(this._serializer, ref._key, Precondition.none()) ); return this; } @@ -138,8 +149,10 @@ export class WriteBatch implements firestore.WriteBatch { commit(): Promise { this.verifyNotCommitted(); this._committed = true; - if (this._mutations.length > 0) { - return this._commitHandler(this._mutations); + if (this._writes.length > 0) { + return this._firestore + ._getDatastore() + .then(datastore => invokeCommitRpc(datastore, this._writes)); } return Promise.resolve(); @@ -174,9 +187,5 @@ export function writeBatch( firestore: firestore.FirebaseFirestore ): firestore.WriteBatch { const firestoreImpl = cast(firestore, Firestore); - return new WriteBatch(firestoreImpl, writes => - firestoreImpl - ._getDatastore() - .then(datastore => invokeCommitRpc(datastore, writes)) - ); + return new WriteBatch(firestoreImpl); } diff --git a/packages/firestore/lite/test/dependencies.json b/packages/firestore/lite/test/dependencies.json index df88ad5b687..27bd9b5f2ec 100644 --- a/packages/firestore/lite/test/dependencies.json +++ b/packages/firestore/lite/test/dependencies.json @@ -57,7 +57,7 @@ ], "variables": [] }, - "sizeInBytes": 21896 + "sizeInBytes": 21899 }, "CollectionReference": { "dependencies": { @@ -199,7 +199,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "Document", "DocumentKey", "DocumentKeyReference", "DocumentReference", @@ -219,8 +218,6 @@ "JsonProtoSerializer", "KeyFieldFilter", "KeyFieldInFilter", - "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -228,27 +225,21 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query", "Query$1", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "TargetImpl", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 99162 + "sizeInBytes": 89385 }, "DocumentReference": { "dependencies": { @@ -294,7 +285,7 @@ ], "variables": [] }, - "sizeInBytes": 17572 + "sizeInBytes": 17575 }, "DocumentSnapshot": { "dependencies": { @@ -383,7 +374,7 @@ ], "variables": [] }, - "sizeInBytes": 38715 + "sizeInBytes": 38718 }, "FieldPath": { "dependencies": { @@ -439,7 +430,7 @@ ], "variables": [] }, - "sizeInBytes": 23529 + "sizeInBytes": 23532 }, "FieldValue": { "dependencies": { @@ -485,7 +476,7 @@ ], "variables": [] }, - "sizeInBytes": 17164 + "sizeInBytes": 17167 }, "FirebaseFirestore": { "dependencies": { @@ -529,7 +520,7 @@ ], "variables": [] }, - "sizeInBytes": 17071 + "sizeInBytes": 17074 }, "GeoPoint": { "dependencies": { @@ -582,7 +573,7 @@ ], "variables": [] }, - "sizeInBytes": 19960 + "sizeInBytes": 19963 }, "Query": { "dependencies": { @@ -698,7 +689,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "Document", "DocumentKey", "DocumentKeyReference", "DocumentReference", @@ -718,8 +708,6 @@ "JsonProtoSerializer", "KeyFieldFilter", "KeyFieldInFilter", - "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -727,25 +715,19 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query$1", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 85476 + "sizeInBytes": 75699 }, "QueryDocumentSnapshot": { "dependencies": { @@ -834,7 +816,7 @@ ], "variables": [] }, - "sizeInBytes": 38720 + "sizeInBytes": 38723 }, "QuerySnapshot": { "dependencies": { @@ -879,7 +861,7 @@ ], "variables": [] }, - "sizeInBytes": 17305 + "sizeInBytes": 17308 }, "Timestamp": { "dependencies": { @@ -924,7 +906,7 @@ ], "variables": [] }, - "sizeInBytes": 18607 + "sizeInBytes": 18610 }, "Transaction": { "dependencies": { @@ -1039,7 +1021,6 @@ "GrpcConnection", "JsonProtoSerializer", "MaybeDocument", - "Mutation", "NoDocument", "OAuthToken", "ObjectValue", @@ -1047,25 +1028,19 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "Timestamp", "Transaction$1", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 69588 + "sizeInBytes": 61028 }, "WriteBatch": { "dependencies": { @@ -1078,6 +1053,9 @@ "blobEquals", "cast", "coercedFieldValuesArray", + "convertDeleteToWrite", + "convertSetToWrites", + "convertUpdateToWrites", "createError", "createMetadata", "debugAssert", @@ -1145,7 +1123,6 @@ "toDouble", "toFieldTransform", "toInteger", - "toMutation", "toMutationDocument", "toName", "toNumber", @@ -1178,7 +1155,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "DeleteMutation", "Document", "DocumentKeyReference", "DocumentReference", @@ -1193,8 +1169,6 @@ "GrpcConnection", "JsonProtoSerializer", "MaybeDocument", - "Mutation", - "NoDocument", "NumericIncrementTransformOperation", "OAuthToken", "ObjectValue", @@ -1202,25 +1176,19 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", "Precondition", "ResourcePath", "SerializableFieldValue", "ServerTimestampTransform", - "SetMutation", - "SnapshotVersion", "StreamBridge", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", - "VerifyMutation", "WriteBatch" ], "variables": [] }, - "sizeInBytes": 72512 + "sizeInBytes": 63272 }, "addDoc": { "dependencies": { @@ -1257,6 +1225,7 @@ "compareNumbers", "compareReferences", "compareTimestamps", + "convertSetToWrites", "createError", "createMetadata", "debugAssert", @@ -1343,7 +1312,6 @@ "toDouble", "toFieldTransform", "toInteger", - "toMutation", "toMutationDocument", "toName", "toNumber", @@ -1384,7 +1352,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "DeleteMutation", "Document", "DocumentKey", "DocumentKeyReference", @@ -1406,8 +1373,6 @@ "KeyFieldFilter", "KeyFieldInFilter", "MaybeDocument", - "Mutation", - "NoDocument", "NumericIncrementTransformOperation", "OAuthToken", "ObjectValue", @@ -1416,7 +1381,6 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", "Precondition", "Query", "Query$1", @@ -1424,21 +1388,16 @@ "ResourcePath", "SerializableFieldValue", "ServerTimestampTransform", - "SetMutation", - "SnapshotVersion", "StreamBridge", "TargetImpl", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", - "UserDataWriter", - "VerifyMutation" + "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 109513 + "sizeInBytes": 99322 }, "arrayRemove": { "dependencies": { @@ -1549,7 +1508,7 @@ ], "variables": [] }, - "sizeInBytes": 42383 + "sizeInBytes": 42386 }, "arrayUnion": { "dependencies": { @@ -1660,7 +1619,7 @@ ], "variables": [] }, - "sizeInBytes": 42391 + "sizeInBytes": 42394 }, "collection": { "dependencies": { @@ -1804,7 +1763,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "Document", "DocumentKey", "DocumentKeyReference", "DocumentReference", @@ -1824,8 +1782,6 @@ "JsonProtoSerializer", "KeyFieldFilter", "KeyFieldInFilter", - "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -1833,27 +1789,21 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query", "Query$1", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "TargetImpl", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 99790 + "sizeInBytes": 90013 }, "collectionGroup": { "dependencies": { @@ -1995,7 +1945,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "Document", "DocumentKey", "DocumentKeyReference", "DocumentReference", @@ -2015,8 +1964,6 @@ "JsonProtoSerializer", "KeyFieldFilter", "KeyFieldInFilter", - "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -2024,58 +1971,38 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query", "Query$1", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "TargetImpl", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 99222 + "sizeInBytes": 89445 }, "deleteDoc": { "dependencies": { "functions": [ "argToString", - "arrayEquals", - "binaryStringFromUint8Array", - "blobEquals", "cast", - "coercedFieldValuesArray", + "convertDeleteToWrite", "createMetadata", "debugAssert", "debugCast", - "decodeBase64", "deleteDoc", - "encodeBase64", "fail", "formatJSON", "fullyQualifiedPrefixPath", - "geoPointEquals", "getEncodedDatabaseId", - "getLocalWriteTime", "hardAssert", "invokeCommitRpc", - "isArray", - "isDouble", - "isInteger", - "isMapValue", - "isNegativeZero", - "isNumber", - "isServerTimestamp", "loadProtos", "logDebug", "logError", @@ -2085,76 +2012,41 @@ "newDatastore", "newSerializer", "nodePromise", - "normalizeByteString", - "normalizeNumber", - "normalizeTimestamp", - "numberEquals", - "objectEquals", - "objectSize", "primitiveComparator", "registerFirestore", - "serverTimestamp", "terminate", "terminateDatastore", - "timestampEquals", - "toDocumentMask", - "toDouble", - "toFieldTransform", - "toInteger", - "toMutation", - "toMutationDocument", "toName", "toPrecondition", "toResourceName", "toTimestamp", - "toVersion", - "typeOrder", - "uint8ArrayFromBinaryString", - "valueEquals" + "toVersion" ], "classes": [ - "ArrayRemoveTransformOperation", - "ArrayUnionTransformOperation", "BasePath", - "ByteString", "DatabaseId", "DatabaseInfo", "Datastore", "DatastoreImpl", "Deferred", - "DeleteMutation", "Document", "DocumentKeyReference", "DocumentReference", - "FieldPath", "FirebaseCredentialsProvider", "Firestore", "FirestoreError", "GrpcConnection", "JsonProtoSerializer", "MaybeDocument", - "Mutation", - "NoDocument", - "NumericIncrementTransformOperation", "OAuthToken", - "ObjectValue", - "ObjectValueBuilder", - "PatchMutation", "Precondition", "ResourcePath", - "ServerTimestampTransform", - "SetMutation", - "SnapshotVersion", "StreamBridge", - "Timestamp", - "TransformMutation", - "UnknownDocument", - "User", - "VerifyMutation" + "User" ], "variables": [] }, - "sizeInBytes": 50238 + "sizeInBytes": 24018 }, "deleteField": { "dependencies": { @@ -2203,7 +2095,7 @@ ], "variables": [] }, - "sizeInBytes": 18238 + "sizeInBytes": 18241 }, "doc": { "dependencies": { @@ -2349,7 +2241,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "Document", "DocumentKey", "DocumentKeyReference", "DocumentReference", @@ -2369,8 +2260,6 @@ "JsonProtoSerializer", "KeyFieldFilter", "KeyFieldInFilter", - "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -2378,27 +2267,21 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query", "Query$1", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "TargetImpl", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 100611 + "sizeInBytes": 90834 }, "documentId": { "dependencies": { @@ -2455,7 +2338,7 @@ ], "variables": [] }, - "sizeInBytes": 23579 + "sizeInBytes": 23582 }, "getDoc": { "dependencies": { @@ -2575,7 +2458,7 @@ ], "variables": [] }, - "sizeInBytes": 47948 + "sizeInBytes": 47951 }, "getFirestore": { "dependencies": { @@ -2620,7 +2503,7 @@ ], "variables": [] }, - "sizeInBytes": 17150 + "sizeInBytes": 17153 }, "getQuery": { "dependencies": { @@ -2734,6 +2617,7 @@ "uint8ArrayFromBinaryString", "validateArgType", "validateExactNumberOfArgs", + "validateHasExplicitOrderByForLimitToLast", "validateNamedArrayAtLeastNumberOfElements", "validatePlainObject", "validatePositiveNumber", @@ -2778,7 +2662,6 @@ "KeyFieldFilter", "KeyFieldInFilter", "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -2786,26 +2669,21 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query$1", "QueryDocumentSnapshot", "QuerySnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", "SnapshotVersion", "StreamBridge", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 91235 + "sizeInBytes": 83253 }, "increment": { "dependencies": { @@ -2916,7 +2794,7 @@ ], "variables": [] }, - "sizeInBytes": 42341 + "sizeInBytes": 42344 }, "initializeFirestore": { "dependencies": { @@ -2961,7 +2839,7 @@ ], "variables": [] }, - "sizeInBytes": 17236 + "sizeInBytes": 17239 }, "parent": { "dependencies": { @@ -3104,7 +2982,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "Document", "DocumentKey", "DocumentKeyReference", "DocumentReference", @@ -3124,8 +3001,6 @@ "JsonProtoSerializer", "KeyFieldFilter", "KeyFieldInFilter", - "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -3133,27 +3008,21 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query", "Query$1", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "TargetImpl", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 99505 + "sizeInBytes": 89728 }, "queryEqual": { "dependencies": { @@ -3270,7 +3139,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "Document", "DocumentKey", "DocumentKeyReference", "DocumentReference", @@ -3290,8 +3158,6 @@ "JsonProtoSerializer", "KeyFieldFilter", "KeyFieldInFilter", - "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -3299,25 +3165,19 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query$1", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 85680 + "sizeInBytes": 75903 }, "refEqual": { "dependencies": { @@ -3460,7 +3320,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "Document", "DocumentKey", "DocumentKeyReference", "DocumentReference", @@ -3480,8 +3339,6 @@ "JsonProtoSerializer", "KeyFieldFilter", "KeyFieldInFilter", - "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -3489,27 +3346,21 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query", "Query$1", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "TargetImpl", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 99447 + "sizeInBytes": 89670 }, "runTransaction": { "dependencies": { @@ -3523,6 +3374,10 @@ "blobEquals", "cast", "coercedFieldValuesArray", + "convertDeleteToWrite", + "convertSetToWrites", + "convertUpdateToWrites", + "convertVerifyToWrite", "createError", "createMetadata", "debugAssert", @@ -3608,7 +3463,6 @@ "toDouble", "toFieldTransform", "toInteger", - "toMutation", "toMutationDocument", "toName", "toNumber", @@ -3643,7 +3497,6 @@ "Deferred", "DelayedOperation", "DeleteFieldValueImpl", - "DeleteMutation", "Document", "DocumentKey", "DocumentKeyReference", @@ -3661,7 +3514,6 @@ "GrpcConnection", "JsonProtoSerializer", "MaybeDocument", - "Mutation", "NoDocument", "NumericIncrementTransformOperation", "OAuthToken", @@ -3670,29 +3522,24 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", "Precondition", "QueryDocumentSnapshot", "ResourcePath", "SerializableFieldValue", "ServerTimestampTransform", - "SetMutation", "SnapshotVersion", "StreamBridge", "Timestamp", "Transaction", "Transaction$1", "TransactionRunner", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", - "UserDataWriter", - "VerifyMutation" + "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 91963 + "sizeInBytes": 84048 }, "serverTimestamp": { "dependencies": { @@ -3744,7 +3591,7 @@ ], "variables": [] }, - "sizeInBytes": 19024 + "sizeInBytes": 19027 }, "setDoc": { "dependencies": { @@ -3757,6 +3604,7 @@ "blobEquals", "cast", "coercedFieldValuesArray", + "convertSetToWrites", "createError", "createMetadata", "debugAssert", @@ -3825,7 +3673,6 @@ "toDouble", "toFieldTransform", "toInteger", - "toMutation", "toMutationDocument", "toName", "toNumber", @@ -3857,7 +3704,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "DeleteMutation", "Document", "DocumentKeyReference", "DocumentReference", @@ -3871,8 +3717,6 @@ "GrpcConnection", "JsonProtoSerializer", "MaybeDocument", - "Mutation", - "NoDocument", "NumericIncrementTransformOperation", "OAuthToken", "ObjectValue", @@ -3880,24 +3724,18 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", "Precondition", "ResourcePath", "SerializableFieldValue", "ServerTimestampTransform", - "SetMutation", - "SnapshotVersion", "StreamBridge", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", - "UserDataReader", - "VerifyMutation" + "UserDataReader" ], "variables": [] }, - "sizeInBytes": 70801 + "sizeInBytes": 60838 }, "setLogLevel": { "dependencies": { @@ -3942,7 +3780,7 @@ ], "variables": [] }, - "sizeInBytes": 17115 + "sizeInBytes": 17118 }, "snapshotEqual": { "dependencies": { @@ -4060,7 +3898,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "Document", "DocumentKey", "DocumentKeyReference", "DocumentReference", @@ -4080,8 +3917,6 @@ "JsonProtoSerializer", "KeyFieldFilter", "KeyFieldInFilter", - "MaybeDocument", - "Mutation", "OAuthToken", "ObjectValue", "ObjectValueBuilder", @@ -4089,26 +3924,20 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", - "Precondition", "Query$1", "QueryDocumentSnapshot", "QuerySnapshot", "ResourcePath", "SerializableFieldValue", - "SetMutation", - "SnapshotVersion", "StreamBridge", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", "UserDataWriter" ], "variables": [] }, - "sizeInBytes": 86413 + "sizeInBytes": 76636 }, "terminate": { "dependencies": { @@ -4152,7 +3981,7 @@ ], "variables": [] }, - "sizeInBytes": 17050 + "sizeInBytes": 17053 }, "updateDoc": { "dependencies": { @@ -4164,6 +3993,7 @@ "blobEquals", "cast", "coercedFieldValuesArray", + "convertUpdateToWrites", "createError", "createMetadata", "debugAssert", @@ -4231,7 +4061,6 @@ "toDouble", "toFieldTransform", "toInteger", - "toMutation", "toMutationDocument", "toName", "toNumber", @@ -4264,7 +4093,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "DeleteMutation", "Document", "DocumentKeyReference", "DocumentReference", @@ -4279,8 +4107,6 @@ "GrpcConnection", "JsonProtoSerializer", "MaybeDocument", - "Mutation", - "NoDocument", "NumericIncrementTransformOperation", "OAuthToken", "ObjectValue", @@ -4288,24 +4114,18 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", "Precondition", "ResourcePath", "SerializableFieldValue", "ServerTimestampTransform", - "SetMutation", - "SnapshotVersion", "StreamBridge", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", - "UserDataReader", - "VerifyMutation" + "UserDataReader" ], "variables": [] }, - "sizeInBytes": 70838 + "sizeInBytes": 60837 }, "writeBatch": { "dependencies": { @@ -4318,6 +4138,9 @@ "blobEquals", "cast", "coercedFieldValuesArray", + "convertDeleteToWrite", + "convertSetToWrites", + "convertUpdateToWrites", "createError", "createMetadata", "debugAssert", @@ -4385,7 +4208,6 @@ "toDouble", "toFieldTransform", "toInteger", - "toMutation", "toMutationDocument", "toName", "toNumber", @@ -4419,7 +4241,6 @@ "DatastoreImpl", "Deferred", "DeleteFieldValueImpl", - "DeleteMutation", "Document", "DocumentKeyReference", "DocumentReference", @@ -4434,8 +4255,6 @@ "GrpcConnection", "JsonProtoSerializer", "MaybeDocument", - "Mutation", - "NoDocument", "NumericIncrementTransformOperation", "OAuthToken", "ObjectValue", @@ -4443,24 +4262,18 @@ "ParseContext", "ParsedSetData", "ParsedUpdateData", - "PatchMutation", "Precondition", "ResourcePath", "SerializableFieldValue", "ServerTimestampTransform", - "SetMutation", - "SnapshotVersion", "StreamBridge", "Timestamp", - "TransformMutation", - "UnknownDocument", "User", "UserDataReader", - "VerifyMutation", "WriteBatch" ], "variables": [] }, - "sizeInBytes": 72592 + "sizeInBytes": 63386 } } \ No newline at end of file diff --git a/packages/firestore/src/api/database.ts b/packages/firestore/src/api/database.ts index 9625ac3086c..c05d0ecd6e1 100644 --- a/packages/firestore/src/api/database.ts +++ b/packages/firestore/src/api/database.ts @@ -90,6 +90,8 @@ import { import { DocumentKeyReference, fieldPathFromArgument, + convertSetToMutations, + convertUpdateToMutations, UntypedFirestoreDataConverter, UserDataReader } from './user_data_reader'; @@ -869,7 +871,7 @@ export class WriteBatch implements firestore.WriteBatch { options ); this._mutations = this._mutations.concat( - parsed.toMutations(ref._key, Precondition.none()) + convertSetToMutations(parsed, ref._key, Precondition.none()) ); return this; } @@ -927,7 +929,7 @@ export class WriteBatch implements firestore.WriteBatch { } this._mutations = this._mutations.concat( - parsed.toMutations(ref._key, Precondition.exists(true)) + convertUpdateToMutations(parsed, ref._key, Precondition.exists(true)) ); return this; } @@ -1069,7 +1071,7 @@ export class DocumentReference options ); return this._firestoreClient.write( - parsed.toMutations(this._key, Precondition.none()) + convertSetToMutations(parsed, this._key, Precondition.none()) ); } @@ -1108,7 +1110,7 @@ export class DocumentReference } return this._firestoreClient.write( - parsed.toMutations(this._key, Precondition.exists(true)) + convertUpdateToMutations(parsed, this._key, Precondition.exists(true)) ); } diff --git a/packages/firestore/src/api/user_data_reader.ts b/packages/firestore/src/api/user_data_reader.ts index 71abaeb5bec..45fb3cb8487 100644 --- a/packages/firestore/src/api/user_data_reader.ts +++ b/packages/firestore/src/api/user_data_reader.ts @@ -40,9 +40,14 @@ import { ObjectValue, ObjectValueBuilder } from '../model/object_value'; import { JsonProtoSerializer, toBytes, + toDocumentMask, + toFieldTransform, + toMutationDocument, + toName, toNumber, toResourceName, - toTimestamp + toTimestamp, + toPrecondition } from '../remote/serializer'; import { Blob } from './blob'; import { BaseFieldPath, fromDotSeparatedString } from './field_path'; @@ -82,25 +87,63 @@ export class DocumentKeyReference { /** The result of parsing document data (e.g. for a setData call). */ export class ParsedSetData { constructor( + readonly serializer: JsonProtoSerializer, readonly data: ObjectValue, readonly fieldMask: FieldMask | null, readonly fieldTransforms: FieldTransform[] ) {} +} - toMutations(key: DocumentKey, precondition: Precondition): Mutation[] { - const mutations = [] as Mutation[]; - if (this.fieldMask !== null) { - mutations.push( - new PatchMutation(key, this.data, this.fieldMask, precondition) - ); - } else { - mutations.push(new SetMutation(key, this.data, precondition)); - } - if (this.fieldTransforms.length > 0) { - mutations.push(new TransformMutation(key, this.fieldTransforms)); - } - return mutations; +export function convertSetToMutations( + parseSetData: ParsedSetData, + key: DocumentKey, + precondition: Precondition +): Mutation[] { + const mutations = [] as Mutation[]; + if (parseSetData.fieldMask !== null) { + mutations.push( + new PatchMutation( + key, + parseSetData.data, + parseSetData.fieldMask, + precondition + ) + ); + } else { + mutations.push(new SetMutation(key, parseSetData.data, precondition)); + } + if (parseSetData.fieldTransforms.length > 0) { + mutations.push(new TransformMutation(key, parseSetData.fieldTransforms)); } + return mutations; +} + +export function convertSetToWrites( + parseSetData: ParsedSetData, + serializer: JsonProtoSerializer, + key: DocumentKey, + precondition: Precondition +): api.Write[] { + const writes: api.Write[] = []; + writes.push({ + update: toMutationDocument(serializer, key, parseSetData.data), + updateMask: parseSetData.fieldMask + ? toDocumentMask(parseSetData.fieldMask) + : undefined, + currentDocument: toPrecondition(parseSetData.serializer, precondition) + }); + + if (parseSetData.fieldTransforms.length > 0) { + writes.push({ + transform: { + document: toName(serializer, key), + fieldTransforms: parseSetData.fieldTransforms.map(transform => + toFieldTransform(parseSetData.serializer, transform) + ) + } + }); + } + return writes; } /** The result of parsing "update" data (i.e. for an updateData call). */ @@ -110,16 +153,76 @@ export class ParsedUpdateData { readonly fieldMask: FieldMask, readonly fieldTransforms: FieldTransform[] ) {} +} - toMutations(key: DocumentKey, precondition: Precondition): Mutation[] { - const mutations = [ - new PatchMutation(key, this.data, this.fieldMask, precondition) - ] as Mutation[]; - if (this.fieldTransforms.length > 0) { - mutations.push(new TransformMutation(key, this.fieldTransforms)); - } - return mutations; +export function convertUpdateToMutations( + parseUpdateData: ParsedUpdateData, + key: DocumentKey, + precondition: Precondition +): Mutation[] { + const mutations = [ + new PatchMutation( + key, + parseUpdateData.data, + parseUpdateData.fieldMask, + precondition + ) + ] as Mutation[]; + if (parseUpdateData.fieldTransforms.length > 0) { + mutations.push(new TransformMutation(key, parseUpdateData.fieldTransforms)); + } + return mutations; +} + +export function convertUpdateToWrites( + parseUpdateData: ParsedUpdateData, + serializer: JsonProtoSerializer, + key: DocumentKey, + precondition: Precondition +): api.Write[] { + const writes: api.Write[] = []; + writes.push({ + update: toMutationDocument(serializer, key, parseUpdateData.data), + updateMask: toDocumentMask(parseUpdateData.fieldMask), + currentDocument: toPrecondition(serializer, precondition) + }); + + if (parseUpdateData.fieldTransforms.length > 0) { + writes.push({ + transform: { + document: toName(serializer, key), + fieldTransforms: parseUpdateData.fieldTransforms.map(transform => + toFieldTransform(serializer, transform) + ) + } + }); } + + return writes; +} + +/** Creates a Write Protobuf for a document delete. */ +export function convertDeleteToWrite( + serializer: JsonProtoSerializer, + key: DocumentKey, + precondition: Precondition +): api.Write { + return { + delete: toName(serializer, key), + currentDocument: toPrecondition(serializer, precondition) + }; +} + +/** Creates a Write Protobuf for a document verify. */ +export function convertVerifyToWrite( + serializer: JsonProtoSerializer, + key: DocumentKey, + precondition: Precondition +): api.Write { + return { + verify: toName(serializer, key), + currentDocument: toPrecondition(serializer, precondition) + }; } /* @@ -386,6 +489,7 @@ export class UserDataReader { } return new ParsedSetData( + this.serializer, new ObjectValue(updateData), fieldMask, fieldTransforms diff --git a/packages/firestore/src/core/transaction.ts b/packages/firestore/src/core/transaction.ts index 0beefda0bf5..09cb6a34a03 100644 --- a/packages/firestore/src/core/transaction.ts +++ b/packages/firestore/src/core/transaction.ts @@ -15,25 +15,29 @@ * limitations under the License. */ -import { ParsedSetData, ParsedUpdateData } from '../api/user_data_reader'; +import * as api from '../protos/firestore_proto_api'; +import { + ParsedSetData, + ParsedUpdateData, + convertDeleteToWrite, + convertSetToWrites, + convertUpdateToWrites, + convertVerifyToWrite +} from '../api/user_data_reader'; import { Document, MaybeDocument, NoDocument } from '../model/document'; import { DocumentKey } from '../model/document_key'; -import { - DeleteMutation, - Mutation, - Precondition, - VerifyMutation -} from '../model/mutation'; +import { Precondition } from '../model/mutation'; import { Datastore, invokeBatchGetDocumentsRpc, invokeCommitRpc } from '../remote/datastore'; -import { fail, debugAssert } from '../util/assert'; +import { debugAssert, fail } from '../util/assert'; import { Code, FirestoreError } from '../util/error'; import { SnapshotVersion } from './snapshot_version'; import { ResourcePath } from '../model/path'; +import { fromName } from '../remote/serializer'; /** * Internal transaction object responsible for accumulating the mutations to @@ -42,7 +46,7 @@ import { ResourcePath } from '../model/path'; export class Transaction { // The version of each document that was read during this transaction. private readVersions = new Map(); - private mutations: Mutation[] = []; + private writes: api.Write[] = []; private committed = false; /** @@ -57,14 +61,14 @@ export class Transaction { * When there's more than one write to the same key in a transaction, any * writes after the first are handled differently. */ - private writtenDocs: Set = new Set(); + private writtenDocs: Set = new Set(); constructor(private datastore: Datastore) {} async lookup(keys: DocumentKey[]): Promise { this.ensureCommitNotCalled(); - if (this.mutations.length > 0) { + if (this.writes.length > 0) { throw new FirestoreError( Code.INVALID_ARGUMENT, 'Firestore transactions require all reads to be executed before all writes.' @@ -82,22 +86,42 @@ export class Transaction { } set(key: DocumentKey, data: ParsedSetData): void { - this.write(data.toMutations(key, this.precondition(key))); - this.writtenDocs.add(key); + this.write( + convertSetToWrites( + data, + this.datastore.serializer, + key, + this.precondition(key) + ) + ); + this.writtenDocs.add(key.toString()); } update(key: DocumentKey, data: ParsedUpdateData): void { try { - this.write(data.toMutations(key, this.preconditionForUpdate(key))); + this.write( + convertUpdateToWrites( + data, + this.datastore.serializer, + key, + this.preconditionForUpdate(key) + ) + ); } catch (e) { this.lastWriteError = e; } - this.writtenDocs.add(key); + this.writtenDocs.add(key.toString()); } delete(key: DocumentKey): void { - this.write([new DeleteMutation(key, this.precondition(key))]); - this.writtenDocs.add(key); + this.write([ + convertDeleteToWrite( + this.datastore.serializer, + key, + this.precondition(key) + ) + ]); + this.writtenDocs.add(key.toString()); } async commit(): Promise { @@ -108,16 +132,25 @@ export class Transaction { } const unwritten = this.readVersions; // For each mutation, note that the doc was written. - this.mutations.forEach(mutation => { - unwritten.delete(mutation.key.toString()); + this.writes.forEach(write => { + const encodedPath = write.update ? write.update.name : write.delete; + debugAssert(!!encodedPath, 'Expected to find a key'); + const key = fromName(this.datastore.serializer, encodedPath); + unwritten.delete(key.toString()); }); // For each document that was read but not written to, we want to perform // a `verify` operation. unwritten.forEach((_, path) => { const key = new DocumentKey(ResourcePath.fromString(path)); - this.mutations.push(new VerifyMutation(key, this.precondition(key))); + this.writes.push( + convertVerifyToWrite( + this.datastore.serializer, + key, + this.precondition(key) + ) + ); }); - await invokeCommitRpc(this.datastore, this.mutations); + await invokeCommitRpc(this.datastore, this.writes); this.committed = true; } @@ -153,7 +186,7 @@ export class Transaction { */ private precondition(key: DocumentKey): Precondition { const version = this.readVersions.get(key.toString()); - if (!this.writtenDocs.has(key) && version) { + if (!this.writtenDocs.has(key.toString()) && version) { return Precondition.updateTime(version); } else { return Precondition.none(); @@ -167,7 +200,7 @@ export class Transaction { const version = this.readVersions.get(key.toString()); // The first time a document is written, we want to take into account the // read time and existence - if (!this.writtenDocs.has(key) && version) { + if (!this.writtenDocs.has(key.toString()) && version) { if (version.isEqual(SnapshotVersion.min())) { // The document doesn't exist, so fail the transaction. @@ -194,9 +227,9 @@ export class Transaction { } } - private write(mutations: Mutation[]): void { + private write(write: api.Write[]): void { this.ensureCommitNotCalled(); - this.mutations = this.mutations.concat(mutations); + this.writes = this.writes.concat(write); } private ensureCommitNotCalled(): void { diff --git a/packages/firestore/src/remote/datastore.ts b/packages/firestore/src/remote/datastore.ts index 1777bedb7fb..590482d8954 100644 --- a/packages/firestore/src/remote/datastore.ts +++ b/packages/firestore/src/remote/datastore.ts @@ -18,7 +18,6 @@ import { CredentialsProvider } from '../api/credentials'; import { Document, MaybeDocument } from '../model/document'; import { DocumentKey } from '../model/document_key'; -import { Mutation } from '../model/mutation'; import * as api from '../protos/firestore_proto_api'; import { debugCast, hardAssert } from '../util/assert'; import { Code, FirestoreError } from '../util/error'; @@ -28,7 +27,6 @@ import { fromMaybeDocument, getEncodedDatabaseId, JsonProtoSerializer, - toMutation, toName, toQueryTarget } from './serializer'; @@ -47,9 +45,7 @@ import { Query } from '../core/query'; * for the rest of the client SDK architecture to consume. */ export class Datastore { - // Make sure that the structural type of `Datastore` is unique. - // See https://github.com/microsoft/TypeScript/issues/5451 - private _ = undefined; + constructor(readonly serializer: JsonProtoSerializer) {} } /** @@ -62,9 +58,9 @@ class DatastoreImpl extends Datastore { constructor( readonly connection: Connection, readonly credentials: CredentialsProvider, - readonly serializer: JsonProtoSerializer + serializer: JsonProtoSerializer ) { - super(); + super(serializer); } private verifyNotTerminated(): void { @@ -126,12 +122,12 @@ export function newDatastore( export async function invokeCommitRpc( datastore: Datastore, - mutations: Mutation[] + writes: api.Write[] ): Promise { const datastoreImpl = debugCast(datastore, DatastoreImpl); const params = { database: getEncodedDatabaseId(datastoreImpl.serializer), - writes: mutations.map(m => toMutation(datastoreImpl.serializer, m)) + writes }; await datastoreImpl.invokeRPC('Commit', params); } diff --git a/packages/firestore/src/remote/serializer.ts b/packages/firestore/src/remote/serializer.ts index 3e0dd5e7182..41b904edd43 100644 --- a/packages/firestore/src/remote/serializer.ts +++ b/packages/firestore/src/remote/serializer.ts @@ -664,12 +664,13 @@ export function fromMutation( } } -function toPrecondition( +export function toPrecondition( serializer: JsonProtoSerializer, precondition: Precondition -): api.Precondition { - debugAssert(!precondition.isNone, "Can't serialize an empty precondition"); - if (precondition.updateTime !== undefined) { +): api.Precondition | undefined { + if (precondition.isNone) { + return undefined; + } else if (precondition.updateTime !== undefined) { return { updateTime: toVersion(serializer, precondition.updateTime) }; @@ -730,7 +731,9 @@ export function fromWriteResults( } } -function toFieldTransform( +// TODO(firestorelite): Make this tree-shakeable so that we don't include +// all transforms +export function toFieldTransform( serializer: JsonProtoSerializer, fieldTransform: FieldTransform ): api.FieldTransform { diff --git a/packages/firestore/test/integration/remote/remote.test.ts b/packages/firestore/test/integration/remote/remote.test.ts index 7e074e07a3e..ec2c979627a 100644 --- a/packages/firestore/test/integration/remote/remote.test.ts +++ b/packages/firestore/test/integration/remote/remote.test.ts @@ -25,6 +25,7 @@ import { invokeBatchGetDocumentsRpc, invokeCommitRpc } from '../../../src/remote/datastore'; +import { toMutation } from '../../../src/remote/serializer'; describe('Remote Storage', () => { addEqualityMatcher(); @@ -32,7 +33,7 @@ describe('Remote Storage', () => { it('can write', () => { return withTestDatastore(ds => { const mutation = setMutation('docs/1', { sort: 1 }); - return invokeCommitRpc(ds, [mutation]); + return invokeCommitRpc(ds, [toMutation(ds.serializer, mutation)]); }); }); @@ -41,7 +42,7 @@ describe('Remote Storage', () => { const k = key('docs/1'); const mutation = setMutation('docs/1', { sort: 10 }); - await invokeCommitRpc(ds, [mutation]); + await invokeCommitRpc(ds, [toMutation(ds.serializer, mutation)]); const docs = await invokeBatchGetDocumentsRpc(ds, [k]); expect(docs.length).to.equal(1);