@@ -82,6 +82,38 @@ export class FieldValue {
8282 return ServerTimestampTransform . SERVER_TIMESTAMP_SENTINEL ;
8383 }
8484
85+ /**
86+ * Returns a special value that can be used with set(), create() or update()
87+ * that tells the server to add the given value to the field's current
88+ * value.
89+ *
90+ * If the either current field value or the operand uses floating point
91+ * precision, both values will be interpreted as floating point numbers and
92+ * all arithmetic will follow IEEE 754 semantics. Otherwise, integer
93+ * precision is kept and the result is capped between -2^63 and 2^63-1.
94+ *
95+ * If the current field value is not of type 'number', or if the field does
96+ * not yet exist, the transformation will set the field to the given value.
97+ *
98+ * @param n The value to add.
99+ * @return The FieldValue sentinel for use in a call to set() or update().
100+ *
101+ * @example
102+ * let documentRef = firestore.doc('col/doc');
103+ *
104+ * documentRef.update(
105+ * 'counter', Firestore.FieldValue.numericAdd(1)
106+ * ).then(() => {
107+ * return documentRef.get();
108+ * }).then(doc => {
109+ * // doc.get('counter') was incremented
110+ * });
111+ */
112+ static numericAdd ( n : number ) : FieldValue {
113+ validate . minNumberOfArguments ( 'FieldValue.numericAdd' , arguments , 1 ) ;
114+ return new NumericAddTransform ( n ) ;
115+ }
116+
85117 /**
86118 * Returns a special value that can be used with set(), create() or update()
87119 * that tells the server to union the given elements with any array value that
@@ -280,6 +312,52 @@ class ServerTimestampTransform extends FieldTransform {
280312 }
281313}
282314
315+ /**
316+ * Increments a field value on the backend.
317+ *
318+ * @private
319+ */
320+ class NumericAddTransform extends FieldTransform {
321+ constructor ( private readonly operand : number ) {
322+ super ( ) ;
323+ }
324+
325+ /**
326+ * Numeric transforms are omitted from document masks.
327+ */
328+ get includeInDocumentMask ( ) : false {
329+ return false ;
330+ }
331+
332+ /**
333+ * Numeric transforms are included in document transforms.
334+ */
335+ get includeInDocumentTransform ( ) : true {
336+ return true ;
337+ }
338+
339+ get methodName ( ) : string {
340+ return 'FieldValue.numericAdd' ;
341+ }
342+
343+ validate ( validator : AnyDuringMigration ) : boolean {
344+ return validator . isNumber ( 'FieldValue.numericAdd()' , this . operand ) ;
345+ }
346+
347+ toProto ( serializer : Serializer , fieldPath : FieldPath ) :
348+ api . DocumentTransform . IFieldTransform {
349+ const encodedOperand = serializer . encodeValue ( this . operand ) ! ;
350+ return { fieldPath : fieldPath . formattedName , numericAdd : encodedOperand } ;
351+ }
352+
353+ isEqual ( other : FieldValue ) : boolean {
354+ return (
355+ this === other ||
356+ ( other instanceof NumericAddTransform &&
357+ this . operand === other . operand ) ) ;
358+ }
359+ }
360+
283361/**
284362 * Transforms an array value via a union operation.
285363 *
0 commit comments