Skip to content

Commit e98cb0f

Browse files
Merge 5315226 into 982acf9
2 parents 982acf9 + 5315226 commit e98cb0f

File tree

12 files changed

+473
-355
lines changed

12 files changed

+473
-355
lines changed

.changeset/serious-tables-grow.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
---
2+
---

packages/firestore/exp/src/api/reference.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ import * as firestore from '../../index';
2222
import { Firestore } from './database';
2323
import {
2424
DocumentKeyReference,
25-
ParsedUpdateData
25+
ParsedUpdateData,
26+
convertSetToMutations,
27+
convertUpdateToMutations
2628
} from '../../../src/api/user_data_reader';
2729
import { debugAssert } from '../../../src/util/assert';
2830
import { cast } from '../../../lite/src/api/util';
@@ -186,7 +188,9 @@ export function setDoc<T>(
186188
return firestore
187189
._getFirestoreClient()
188190
.then(firestoreClient =>
189-
firestoreClient.write(parsed.toMutations(ref._key, Precondition.none()))
191+
firestoreClient.write(
192+
convertSetToMutations(parsed, ref._key, Precondition.none())
193+
)
190194
);
191195
}
192196

@@ -234,7 +238,7 @@ export function updateDoc(
234238
._getFirestoreClient()
235239
.then(firestoreClient =>
236240
firestoreClient.write(
237-
parsed.toMutations(ref._key, Precondition.exists(true))
241+
convertUpdateToMutations(parsed, ref._key, Precondition.exists(true))
238242
)
239243
);
240244
}
@@ -273,7 +277,7 @@ export function addDoc<T>(
273277
._getFirestoreClient()
274278
.then(firestoreClient =>
275279
firestoreClient.write(
276-
parsed.toMutations(docRef._key, Precondition.exists(false))
280+
convertSetToMutations(parsed, docRef._key, Precondition.exists(false))
277281
)
278282
)
279283
.then(() => docRef);

packages/firestore/exp/src/api/write_batch.ts

Lines changed: 135 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,145 @@
2020
import * as firestore from '../../index';
2121

2222
import { cast } from '../../../lite/src/api/util';
23-
import { WriteBatch } from '../../../lite/src/api/write_batch';
2423
import { Firestore } from './database';
24+
import {
25+
DeleteMutation,
26+
Mutation,
27+
Precondition
28+
} from '../../../src/model/mutation';
29+
import { Code, FirestoreError } from '../../../src/util/error';
30+
import { applyFirestoreDataConverter } from '../../../src/api/database';
31+
import {
32+
convertSetToMutations,
33+
convertUpdateToMutations,
34+
UserDataReader
35+
} from '../../../src/api/user_data_reader';
36+
import { newUserDataReader } from '../../../lite/src/api/reference';
37+
import { FieldPath } from '../../../lite/src/api/field_path';
38+
import { validateReference } from '../../../lite/src/api/write_batch';
39+
40+
export class WriteBatch implements firestore.WriteBatch {
41+
private readonly _dataReader: UserDataReader;
42+
private _mutations = [] as Mutation[];
43+
private _committed = false;
44+
45+
constructor(private readonly _firestore: Firestore) {
46+
this._dataReader = newUserDataReader(_firestore);
47+
}
48+
49+
set<T>(documentRef: firestore.DocumentReference<T>, value: T): WriteBatch;
50+
set<T>(
51+
documentRef: firestore.DocumentReference<T>,
52+
value: Partial<T>,
53+
options: firestore.SetOptions
54+
): WriteBatch;
55+
set<T>(
56+
documentRef: firestore.DocumentReference<T>,
57+
value: T,
58+
options?: firestore.SetOptions
59+
): WriteBatch {
60+
this.verifyNotCommitted();
61+
const ref = validateReference(documentRef, this._firestore);
62+
63+
const convertedValue = applyFirestoreDataConverter(
64+
ref._converter,
65+
value,
66+
options
67+
);
68+
const parsed = this._dataReader.parseSetData(
69+
'WriteBatch.set',
70+
ref._key,
71+
convertedValue,
72+
ref._converter !== null,
73+
options
74+
);
75+
this._mutations = this._mutations.concat(
76+
convertSetToMutations(parsed, ref._key, Precondition.none())
77+
);
78+
return this;
79+
}
80+
81+
update(
82+
documentRef: firestore.DocumentReference<unknown>,
83+
value: firestore.UpdateData
84+
): WriteBatch;
85+
update(
86+
documentRef: firestore.DocumentReference<unknown>,
87+
field: string | firestore.FieldPath,
88+
value: unknown,
89+
...moreFieldsAndValues: unknown[]
90+
): WriteBatch;
91+
update(
92+
documentRef: firestore.DocumentReference<unknown>,
93+
fieldOrUpdateData: string | firestore.FieldPath | firestore.UpdateData,
94+
value?: unknown,
95+
...moreFieldsAndValues: unknown[]
96+
): WriteBatch {
97+
this.verifyNotCommitted();
98+
const ref = validateReference(documentRef, this._firestore);
99+
100+
let parsed;
101+
102+
if (
103+
typeof fieldOrUpdateData === 'string' ||
104+
fieldOrUpdateData instanceof FieldPath
105+
) {
106+
parsed = this._dataReader.parseUpdateVarargs(
107+
'WriteBatch.update',
108+
ref._key,
109+
fieldOrUpdateData,
110+
value,
111+
moreFieldsAndValues
112+
);
113+
} else {
114+
parsed = this._dataReader.parseUpdateData(
115+
'WriteBatch.update',
116+
ref._key,
117+
fieldOrUpdateData
118+
);
119+
}
120+
121+
this._mutations = this._mutations.concat(
122+
convertUpdateToMutations(parsed, ref._key, Precondition.exists(true))
123+
);
124+
return this;
125+
}
126+
127+
delete(documentRef: firestore.DocumentReference<unknown>): WriteBatch {
128+
this.verifyNotCommitted();
129+
const ref = validateReference(documentRef, this._firestore);
130+
this._mutations = this._mutations.concat(
131+
new DeleteMutation(ref._key, Precondition.none())
132+
);
133+
return this;
134+
}
135+
136+
commit(): Promise<void> {
137+
this.verifyNotCommitted();
138+
this._committed = true;
139+
if (this._mutations.length > 0) {
140+
return this._firestore
141+
._getFirestoreClient()
142+
.then(firestoreClient => firestoreClient.write(this._mutations));
143+
}
144+
145+
return Promise.resolve();
146+
}
147+
148+
private verifyNotCommitted(): void {
149+
if (this._committed) {
150+
throw new FirestoreError(
151+
Code.FAILED_PRECONDITION,
152+
'A write batch can no longer be used after commit() ' +
153+
'has been called.'
154+
);
155+
}
156+
}
157+
}
25158

26159
export function writeBatch(
27160
firestore: firestore.FirebaseFirestore
28161
): firestore.WriteBatch {
29162
const firestoreImpl = cast(firestore, Firestore);
30-
return new WriteBatch(firestoreImpl, writes =>
31-
firestoreImpl
32-
._getFirestoreClient()
33-
.then(firestoreClient => firestoreClient.write(writes))
34-
);
163+
return new WriteBatch(firestoreImpl);
35164
}

packages/firestore/lite/src/api/reference.ts

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ import { Firestore } from './database';
2323
import {
2424
DocumentKeyReference,
2525
ParsedUpdateData,
26-
UserDataReader
26+
convertSetToWrites,
27+
convertUpdateToWrites,
28+
UserDataReader,
29+
convertDeleteToWrite
2730
} from '../../../src/api/user_data_reader';
2831
import {
2932
Bound,
@@ -35,17 +38,17 @@ import { ResourcePath } from '../../../src/model/path';
3538
import { AutoId } from '../../../src/util/misc';
3639
import {
3740
DocumentSnapshot,
41+
fieldPathFromArgument,
3842
QueryDocumentSnapshot,
39-
QuerySnapshot,
40-
fieldPathFromArgument
43+
QuerySnapshot
4144
} from './snapshot';
4245
import {
4346
invokeBatchGetDocumentsRpc,
4447
invokeCommitRpc,
4548
invokeRunQueryRpc
4649
} from '../../../src/remote/datastore';
4750
import { hardAssert } from '../../../src/util/assert';
48-
import { DeleteMutation, Precondition } from '../../../src/model/mutation';
51+
import { Precondition } from '../../../src/model/mutation';
4952
import {
5053
applyFirestoreDataConverter,
5154
BaseQuery,
@@ -477,7 +480,12 @@ export function setDoc<T>(
477480
.then(datastore =>
478481
invokeCommitRpc(
479482
datastore,
480-
parsed.toMutations(ref._key, Precondition.none())
483+
convertSetToWrites(
484+
parsed,
485+
datastore.serializer,
486+
ref._key,
487+
Precondition.none()
488+
)
481489
)
482490
);
483491
}
@@ -526,7 +534,12 @@ export function updateDoc(
526534
.then(datastore =>
527535
invokeCommitRpc(
528536
datastore,
529-
parsed.toMutations(ref._key, Precondition.exists(true))
537+
convertUpdateToWrites(
538+
parsed,
539+
datastore.serializer,
540+
ref._key,
541+
Precondition.exists(true)
542+
)
530543
)
531544
);
532545
}
@@ -539,7 +552,11 @@ export function deleteDoc(
539552
._getDatastore()
540553
.then(datastore =>
541554
invokeCommitRpc(datastore, [
542-
new DeleteMutation(ref._key, Precondition.none())
555+
convertDeleteToWrite(
556+
datastore.serializer,
557+
ref._key,
558+
Precondition.none()
559+
)
543560
])
544561
);
545562
}
@@ -567,7 +584,12 @@ export function addDoc<T>(
567584
.then(datastore =>
568585
invokeCommitRpc(
569586
datastore,
570-
parsed.toMutations(docRef._key, Precondition.exists(false))
587+
convertSetToWrites(
588+
parsed,
589+
datastore.serializer,
590+
docRef._key,
591+
Precondition.exists(false)
592+
)
571593
)
572594
)
573595
.then(() => docRef);

packages/firestore/lite/src/api/write_batch.ts

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,39 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17+
import * as api from '../../../src/protos/firestore_proto_api';
1718

1819
import * as firestore from '../../index';
19-
import {
20-
DeleteMutation,
21-
Mutation,
22-
Precondition
23-
} from '../../../src/model/mutation';
20+
import { Precondition } from '../../../src/model/mutation';
2421
import { Code, FirestoreError } from '../../../src/util/error';
2522
import { applyFirestoreDataConverter } from '../../../src/api/database';
2623
import {
2724
DocumentKeyReference,
25+
convertDeleteToWrite,
26+
convertSetToWrites,
27+
convertUpdateToWrites,
2828
UserDataReader
2929
} from '../../../src/api/user_data_reader';
3030
import { cast } from './util';
3131
import { DocumentReference, newUserDataReader } from './reference';
3232
import { Firestore } from './database';
3333
import { invokeCommitRpc } from '../../../src/remote/datastore';
3434
import { FieldPath } from './field_path';
35+
import { JsonProtoSerializer } from '../../../src/remote/serializer';
36+
import { newSerializer } from '../../../src/platform/serializer';
3537

3638
export class WriteBatch implements firestore.WriteBatch {
3739
// This is the lite version of the WriteBatch API used in the legacy SDK. The
3840
// class is a close copy but takes different input types.
3941

4042
private readonly _dataReader: UserDataReader;
41-
private _mutations = [] as Mutation[];
43+
private readonly _serializer: JsonProtoSerializer;
44+
private _writes = [] as api.Write[];
4245
private _committed = false;
4346

44-
constructor(
45-
private readonly _firestore: Firestore,
46-
private readonly _commitHandler: (m: Mutation[]) => Promise<void>
47-
) {
47+
constructor(private readonly _firestore: Firestore) {
4848
this._dataReader = newUserDataReader(_firestore);
49+
this._serializer = newSerializer(_firestore._databaseId);
4950
}
5051

5152
set<T>(documentRef: firestore.DocumentReference<T>, value: T): WriteBatch;
@@ -74,8 +75,13 @@ export class WriteBatch implements firestore.WriteBatch {
7475
ref._converter !== null,
7576
options
7677
);
77-
this._mutations = this._mutations.concat(
78-
parsed.toMutations(ref._key, Precondition.none())
78+
this._writes = this._writes.concat(
79+
convertSetToWrites(
80+
parsed,
81+
this._serializer,
82+
ref._key,
83+
Precondition.none()
84+
)
7985
);
8086
return this;
8187
}
@@ -120,26 +126,33 @@ export class WriteBatch implements firestore.WriteBatch {
120126
);
121127
}
122128

123-
this._mutations = this._mutations.concat(
124-
parsed.toMutations(ref._key, Precondition.exists(true))
129+
this._writes = this._writes.concat(
130+
convertUpdateToWrites(
131+
parsed,
132+
this._serializer,
133+
ref._key,
134+
Precondition.exists(true)
135+
)
125136
);
126137
return this;
127138
}
128139

129140
delete(documentRef: firestore.DocumentReference<unknown>): WriteBatch {
130141
this.verifyNotCommitted();
131142
const ref = validateReference(documentRef, this._firestore);
132-
this._mutations = this._mutations.concat(
133-
new DeleteMutation(ref._key, Precondition.none())
143+
this._writes = this._writes.concat(
144+
convertDeleteToWrite(this._serializer, ref._key, Precondition.none())
134145
);
135146
return this;
136147
}
137148

138149
commit(): Promise<void> {
139150
this.verifyNotCommitted();
140151
this._committed = true;
141-
if (this._mutations.length > 0) {
142-
return this._commitHandler(this._mutations);
152+
if (this._writes.length > 0) {
153+
return this._firestore
154+
._getDatastore()
155+
.then(datastore => invokeCommitRpc(datastore, this._writes));
143156
}
144157

145158
return Promise.resolve();
@@ -174,9 +187,5 @@ export function writeBatch(
174187
firestore: firestore.FirebaseFirestore
175188
): firestore.WriteBatch {
176189
const firestoreImpl = cast(firestore, Firestore);
177-
return new WriteBatch(firestoreImpl, writes =>
178-
firestoreImpl
179-
._getDatastore()
180-
.then(datastore => invokeCommitRpc(datastore, writes))
181-
);
190+
return new WriteBatch(firestoreImpl);
182191
}

0 commit comments

Comments
 (0)