diff --git a/lib/src/firestore.dart b/lib/src/firestore.dart index 406cc7d..b35b7be 100644 --- a/lib/src/firestore.dart +++ b/lib/src/firestore.dart @@ -541,7 +541,7 @@ class _FirestoreData { if (data is! List) { throw new StateError('Expected list but got ${data.runtimeType}.'); } - final result = new List(); + final result = []; for (var item in data) { item = _dartify(item); result.add(item); @@ -1286,6 +1286,20 @@ class _FieldValueArrayRemove extends _FieldValueArray { String toString() => 'FieldValue.arrayRemove($elements)'; } +class _FieldValueIncrement implements FieldValue { + _FieldValueIncrement(this.value); + + final int value; + + @override + _jsify() { + return js.admin.firestore.FieldValue.increment(value); + } + + @override + String toString() => 'FieldValue.increment($value)'; +} + /// Sentinel values that can be used when writing document fields with set() /// or update(). abstract class FieldValue { @@ -1333,6 +1347,22 @@ class FieldValues { /// with an empty array. FieldValue arrayRemove(List elements) => _FieldValueArrayRemove(elements); + /// Returns a special value that tells the server to increment the field's + /// current value by the given [value]. + /// + /// Can be used with set() or update(). + /// + /// If either the operand or the current field value uses floating point precision, + /// all arithmetic follows IEEE 754 semantics. If both values are integers, + /// values outside of JavaScript's safe number range (Number.MIN_SAFE_INTEGER + /// to Number.MAX_SAFE_INTEGER) are also subject to precision loss. + /// Furthermore, once processed by the Firestore backend, all integer + /// operations are capped between -2^63 and 2^63-1. + /// + /// If the current field value is not of type `number`, or if the field does + /// not yet exist, sets the field to the given [value]. + FieldValue increment(int value) => _FieldValueIncrement(value); + FieldValues._(); final FieldValue _serverTimestamp = _FieldValueServerTimestamp(); diff --git a/lib/src/firestore_bindings.dart b/lib/src/firestore_bindings.dart index 8fe5858..cc70725 100644 --- a/lib/src/firestore_bindings.dart +++ b/lib/src/firestore_bindings.dart @@ -737,6 +737,22 @@ abstract class FieldValues { /// If the field being modified is not already an array it will be overwritten /// with an empty array. external FieldValue arrayRemove(List elements); + + /// Returns a special value that tells the server to increment the field's + /// current value by the given [value]. + /// + /// Can be used with set() or update(). + /// + /// If either the operand or the current field value uses floating point precision, + /// all arithmetic follows IEEE 754 semantics. If both values are integers, + /// values outside of JavaScript's safe number range (Number.MIN_SAFE_INTEGER + /// to Number.MAX_SAFE_INTEGER) are also subject to precision loss. + /// Furthermore, once processed by the Firestore backend, all integer + /// operations are capped between -2^63 and 2^63-1. + /// + /// If the current field value is not of type `number`, or if the field does + /// not yet exist, sets the field to the given [value]. + external FieldValue increment(int value); } @JS() diff --git a/pubspec.yaml b/pubspec.yaml index 733cba1..c8ee8ce 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: quiver_hashcode: ^2.0.0 dev_dependencies: - test: ^1.12.0 + test: ^1.15.7 build_runner: ^1.7.4 - build_node_compilers: ^0.2.4 + build_node_compilers: ^0.3.1 build_test: ^0.10.12+1 diff --git a/test/firestore_test.dart b/test/firestore_test.dart index a075cac..211a126 100644 --- a/test/firestore_test.dart +++ b/test/firestore_test.dart @@ -290,6 +290,56 @@ void main() { expect(documentData.getString("other_key"), "other_value"); }); + test('increment field', () async { + const incrementValue = 1; + const integerFieldKey = "integer_field"; + const doubleFieldKey = "double_key"; + const stringFieldKey = "string_key"; + const initialIntegerFieldValue = 1; + const initialDoubleFieldValue = 1.3; + + final expectedIntegerFieldValue = + initialIntegerFieldValue + incrementValue; + final expectedDoubleFieldValue = + initialDoubleFieldValue + incrementValue; + final expectedStringFieldValue = incrementValue; + + var ref = app.firestore().document('tests/increment_field'); + + final fieldValueIncrement = + Firestore.fieldValues.increment(incrementValue); + + // create document + final documentData = new DocumentData(); + documentData.setInt(integerFieldKey, initialIntegerFieldValue); + documentData.setDouble(doubleFieldKey, initialDoubleFieldValue); + documentData.setString(stringFieldKey, 'string'); + await ref.setData(documentData); + + // increment field values + final updateData = new UpdateData(); + updateData.setFieldValue(integerFieldKey, fieldValueIncrement); + updateData.setFieldValue(doubleFieldKey, fieldValueIncrement); + updateData.setFieldValue(stringFieldKey, fieldValueIncrement); + await ref.updateData(updateData); + + // read again + final updatedDocument = await ref.get(); + final updatedDocumentData = updatedDocument.data; + expect( + updatedDocumentData.getInt(integerFieldKey), + equals(expectedIntegerFieldValue), + ); + expect( + updatedDocumentData.getDouble(doubleFieldKey), + equals(expectedDoubleFieldValue), + ); + expect( + updatedDocumentData.getInt(stringFieldKey), + equals(expectedStringFieldValue), + ); + }); + test('array field value', () async { var ref = app.firestore().document('tests/array_field_value'); @@ -997,9 +1047,9 @@ void main() { var doc1Ref = collRef.document('counter'); await doc1Ref.setData(new DocumentData()..setInt('value', 1)); - List> futures = new List(); - List errors = new List(); - List complete = new List(); + List> futures = []; + List errors = []; + List complete = []; var futuresCount = 5; for (int i = 0; i < futuresCount; i++) {