Skip to content

Commit e593601

Browse files
Add updateDoc() (#3148)
1 parent 27d4286 commit e593601

File tree

4 files changed

+105
-9
lines changed

4 files changed

+105
-9
lines changed

packages/firestore/lite/index.d.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,15 +280,16 @@ export function setDoc<T>(
280280
options: SetOptions
281281
): Promise<void>;
282282
export function updateDoc(
283-
reference: DocumentReference,
283+
reference: DocumentReference<unknown>,
284284
data: UpdateData
285285
): Promise<void>;
286286
export function updateDoc(
287+
reference: DocumentReference<unknown>,
287288
field: string | FieldPath,
288289
value: any,
289290
...moreFieldsAndValues: any[]
290291
): Promise<void>;
291-
export function deleteDoc(reference: DocumentReference): Promise<void>;
292+
export function deleteDoc(reference: DocumentReference<unknown>): Promise<void>;
292293

293294
export class FieldValue {
294295
private constructor();

packages/firestore/lite/index.node.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export {
3838
getDoc,
3939
deleteDoc,
4040
setDoc,
41+
updateDoc,
4142
addDoc
4243
} from './src/api/reference';
4344

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

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ import { DocumentKey } from '../../../src/model/document_key';
2222
import { Firestore } from './database';
2323
import {
2424
DocumentKeyReference,
25+
ParsedUpdateData,
2526
UserDataReader
2627
} from '../../../src/api/user_data_reader';
2728
import { Query as InternalQuery } from '../../../src/core/query';
28-
import { FirebaseFirestore, FirestoreDataConverter } from '../../index';
2929
import { ResourcePath } from '../../../src/model/path';
3030
import { AutoId } from '../../../src/util/misc';
3131
import { DocumentSnapshot } from './snapshot';
@@ -38,6 +38,7 @@ import { DeleteMutation, Precondition } from '../../../src/model/mutation';
3838
import { PlatformSupport } from '../../../src/platform/platform';
3939
import { applyFirestoreDataConverter } from '../../../src/api/database';
4040
import { DatabaseId } from '../../../src/core/database_info';
41+
import { FieldPath } from './field_path';
4142
import { cast } from './util';
4243
import {
4344
validateArgType,
@@ -78,7 +79,7 @@ export class Query<T = firestore.DocumentData> implements firestore.Query<T> {
7879
constructor(
7980
readonly firestore: Firestore,
8081
readonly _query: InternalQuery,
81-
readonly _converter?: FirestoreDataConverter<T>
82+
readonly _converter?: firestore.FirestoreDataConverter<T>
8283
) {}
8384

8485
where(
@@ -173,11 +174,11 @@ export class CollectionReference<T = firestore.DocumentData> extends Query<T>
173174
}
174175

175176
export function collection(
176-
firestore: FirebaseFirestore,
177+
firestore: firestore.FirebaseFirestore,
177178
collectionPath: string
178179
): CollectionReference<firestore.DocumentData>;
179180
export function collection(
180-
reference: DocumentReference,
181+
reference: firestore.DocumentReference,
181182
collectionPath: string
182183
): CollectionReference<firestore.DocumentData>;
183184
export function collection(
@@ -198,11 +199,11 @@ export function collection(
198199
}
199200

200201
export function doc(
201-
firestore: FirebaseFirestore,
202+
firestore: firestore.FirebaseFirestore,
202203
documentPath: string
203204
): DocumentReference<firestore.DocumentData>;
204205
export function doc<T>(
205-
reference: CollectionReference<T>,
206+
reference: firestore.CollectionReference<T>,
206207
documentPath?: string
207208
): DocumentReference<T>;
208209
export function doc<T>(
@@ -277,6 +278,15 @@ export function getDoc<T>(
277278
});
278279
}
279280

281+
export function setDoc<T>(
282+
reference: firestore.DocumentReference<T>,
283+
data: T
284+
): Promise<void>;
285+
export function setDoc<T>(
286+
reference: firestore.DocumentReference<T>,
287+
data: Partial<T>,
288+
options: firestore.SetOptions
289+
): Promise<void>;
280290
export function setDoc<T>(
281291
reference: firestore.DocumentReference<T>,
282292
data: T,
@@ -307,6 +317,63 @@ export function setDoc<T>(
307317
);
308318
}
309319

320+
export function updateDoc(
321+
reference: firestore.DocumentReference,
322+
data: firestore.UpdateData
323+
): Promise<void>;
324+
export function updateDoc(
325+
reference: firestore.DocumentReference,
326+
field: string | firestore.FieldPath,
327+
value: unknown,
328+
...moreFieldsAndValues: unknown[]
329+
): Promise<void>;
330+
export function updateDoc(
331+
reference: firestore.DocumentReference,
332+
fieldOrUpdateData: string | firestore.FieldPath | firestore.UpdateData,
333+
value?: unknown,
334+
...moreFieldsAndValues: unknown[]
335+
): Promise<void> {
336+
const ref = cast(reference, DocumentReference);
337+
338+
// Kick off configuring the client, which freezes the settings.
339+
const configureClient = ref.firestore._ensureClientConfigured();
340+
const dataReader = newUserDataReader(
341+
ref.firestore._databaseId,
342+
ref.firestore._settings!
343+
);
344+
345+
let parsed: ParsedUpdateData;
346+
if (
347+
typeof fieldOrUpdateData === 'string' ||
348+
fieldOrUpdateData instanceof FieldPath
349+
) {
350+
parsed = dataReader.parseUpdateVarargs(
351+
'updateDoc',
352+
fieldOrUpdateData,
353+
value,
354+
moreFieldsAndValues
355+
);
356+
} else {
357+
parsed = dataReader.parseUpdateData('updateDoc', fieldOrUpdateData);
358+
}
359+
360+
return configureClient.then(datastore =>
361+
invokeCommitRpc(
362+
datastore,
363+
parsed.toMutations(ref._key, Precondition.none())
364+
)
365+
);
366+
367+
return ref.firestore
368+
._ensureClientConfigured()
369+
.then(datastore =>
370+
invokeCommitRpc(
371+
datastore,
372+
parsed.toMutations(ref._key, Precondition.exists(true))
373+
)
374+
);
375+
}
376+
310377
export function deleteDoc(
311378
reference: firestore.DocumentReference
312379
): Promise<void> {

packages/firestore/lite/test/integration.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ import {
3939
getDoc,
4040
deleteDoc,
4141
setDoc,
42-
addDoc
42+
addDoc,
43+
updateDoc
4344
} from '../src/api/reference';
4445
import { FieldPath } from '../src/api/field_path';
4546
import {
@@ -260,6 +261,32 @@ describe('setDoc()', () => {
260261
});
261262
});
262263

264+
describe('update()', () => {
265+
it('can update a document', () => {
266+
return withTestDocAndInitialData({ foo: 1, bar: 1 }, async docRef => {
267+
await updateDoc(docRef, { foo: 2, baz: 2 });
268+
const docSnap = await getDoc(docRef);
269+
expect(docSnap.data()).to.deep.equal({ foo: 2, bar: 1, baz: 2 });
270+
});
271+
});
272+
273+
it('can update a document (using varargs)', () => {
274+
return withTestDocAndInitialData({ foo: 1, bar: 1 }, async docRef => {
275+
await updateDoc(docRef, 'foo', 2, new FieldPath('baz'), 2);
276+
const docSnap = await getDoc(docRef);
277+
expect(docSnap.data()).to.deep.equal({ foo: 2, bar: 1, baz: 2 });
278+
});
279+
});
280+
281+
it('throws when user input fails validation', () => {
282+
return withTestDoc(async docRef => {
283+
expect(() => updateDoc(docRef, { val: undefined })).to.throw(
284+
'Function updateDoc() called with invalid data. Unsupported field value: undefined (found in field val)'
285+
);
286+
});
287+
});
288+
});
289+
263290
describe('addDoc()', () => {
264291
it('can add a document', () => {
265292
return withTestCollection(async collRef => {

0 commit comments

Comments
 (0)