@react-native-firebase/firestore 15.7.1 → 16.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,20 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [16.1.0](https://github.com/invertase/react-native-firebase/compare/v16.0.0...v16.1.0) (2022-10-20)
7
+
8
+ ### Features
9
+
10
+ - **firestore, count:** implement AggregateQuery count() on collections ([bd52301](https://github.com/invertase/react-native-firebase/commit/bd52301ad4ef35eeb4dbdab1bc4926db72d40949))
11
+
12
+ ### Bug Fixes
13
+
14
+ - **firestore, emulator:** avoid double calls to useEmulator ([4e0d188](https://github.com/invertase/react-native-firebase/commit/4e0d188416f4ae8eb176ef024b5698bc892838d5)), closes [#5723](https://github.com/invertase/react-native-firebase/issues/5723)
15
+
16
+ ## [16.0.0](https://github.com/invertase/react-native-firebase/compare/v15.7.1...v16.0.0) (2022-10-19)
17
+
18
+ **Note:** Version bump only for package @react-native-firebase/firestore
19
+
6
20
  ## [15.7.1](https://github.com/invertase/react-native-firebase/compare/v15.7.0...v15.7.1) (2022-10-19)
7
21
 
8
22
  **Note:** Version bump only for package @react-native-firebase/firestore
@@ -28,11 +28,14 @@ import com.google.firebase.firestore.LoadBundleTask;
28
28
  import io.invertase.firebase.common.UniversalFirebaseModule;
29
29
  import io.invertase.firebase.common.UniversalFirebasePreferences;
30
30
  import java.nio.charset.StandardCharsets;
31
+ import java.util.HashMap;
31
32
  import java.util.Map;
32
33
  import java.util.Objects;
33
34
 
34
35
  public class UniversalFirebaseFirestoreModule extends UniversalFirebaseModule {
35
36
 
37
+ private static HashMap<String, String> emulatorConfigs = new HashMap<>();
38
+
36
39
  UniversalFirebaseFirestoreModule(Context context, String serviceName) {
37
40
  super(context, serviceName);
38
41
  }
@@ -49,7 +52,10 @@ public class UniversalFirebaseFirestoreModule extends UniversalFirebaseModule {
49
52
  return Tasks.call(
50
53
  getExecutor(),
51
54
  () -> {
52
- getFirestoreForApp(appName).useEmulator(host, port);
55
+ if (emulatorConfigs.get(appName) == null) {
56
+ emulatorConfigs.put(appName, "true");
57
+ getFirestoreForApp(appName).useEmulator(host, port);
58
+ }
53
59
  return null;
54
60
  });
55
61
  }
@@ -148,6 +148,36 @@ public class ReactNativeFirebaseFirestoreCollectionModule extends ReactNativeFir
148
148
  });
149
149
  }
150
150
 
151
+ @ReactMethod
152
+ public void collectionCount(
153
+ String appName,
154
+ String path,
155
+ String type,
156
+ ReadableArray filters,
157
+ ReadableArray orders,
158
+ ReadableMap options,
159
+ Promise promise) {
160
+ FirebaseFirestore firebaseFirestore = getFirestoreForApp(appName);
161
+ ReactNativeFirebaseFirestoreQuery firestoreQuery =
162
+ new ReactNativeFirebaseFirestoreQuery(
163
+ appName, getQueryForFirestore(firebaseFirestore, path, type), filters, orders, options);
164
+
165
+ AggregateQuery aggregateQuery = firestoreQuery.query.count();
166
+
167
+ aggregateQuery
168
+ .get(AggregateSource.SERVER)
169
+ .addOnCompleteListener(
170
+ task -> {
171
+ if (task.isSuccessful()) {
172
+ WritableMap result = Arguments.createMap();
173
+ result.putDouble("count", Long.valueOf(task.getResult().getCount()).doubleValue());
174
+ promise.resolve(result);
175
+ } else {
176
+ rejectPromiseFirestoreException(promise, task.getException());
177
+ }
178
+ });
179
+ }
180
+
151
181
  @ReactMethod
152
182
  public void collectionGet(
153
183
  String appName,
@@ -165,6 +165,43 @@ RCT_EXPORT_METHOD(namedQueryGet
165
165
  }];
166
166
  }
167
167
 
168
+ RCT_EXPORT_METHOD(collectionCount
169
+ : (FIRApp *)firebaseApp
170
+ : (NSString *)path
171
+ : (NSString *)type
172
+ : (NSArray *)filters
173
+ : (NSArray *)orders
174
+ : (NSDictionary *)options
175
+ : (RCTPromiseResolveBlock)resolve
176
+ : (RCTPromiseRejectBlock)reject) {
177
+ FIRFirestore *firestore = [RNFBFirestoreCommon getFirestoreForApp:firebaseApp];
178
+ FIRQuery *query = [RNFBFirestoreCommon getQueryForFirestore:firestore path:path type:type];
179
+ RNFBFirestoreQuery *firestoreQuery = [[RNFBFirestoreQuery alloc] initWithModifiers:firestore
180
+ query:query
181
+ filters:filters
182
+ orders:orders
183
+ options:options];
184
+
185
+ // NOTE: There is only "server" as the source at the moment. So this
186
+ // is unused for the time being. Using "FIRAggregateSourceServer".
187
+ // NSString *source = arguments[@"source"];
188
+
189
+ FIRAggregateQuery *aggregateQuery = [firestoreQuery.query count];
190
+
191
+ [aggregateQuery
192
+ aggregationWithSource:FIRAggregateSourceServer
193
+ completion:^(FIRAggregateQuerySnapshot *_Nullable snapshot,
194
+ NSError *_Nullable error) {
195
+ if (error) {
196
+ [RNFBFirestoreCommon promiseRejectFirestoreException:reject error:error];
197
+ } else {
198
+ NSMutableDictionary *snapshotMap = [NSMutableDictionary dictionary];
199
+ snapshotMap[@"count"] = snapshot.count;
200
+ resolve(snapshotMap);
201
+ }
202
+ }];
203
+ }
204
+
168
205
  RCT_EXPORT_METHOD(collectionGet
169
206
  : (FIRApp *)firebaseApp
170
207
  : (NSString *)path
@@ -20,6 +20,8 @@
20
20
  #import "RNFBFirestoreCommon.h"
21
21
  #import "RNFBPreferences.h"
22
22
 
23
+ NSMutableDictionary *emulatorConfigs;
24
+
23
25
  @implementation RNFBFirestoreModule
24
26
  #pragma mark -
25
27
  #pragma mark Module Setup
@@ -142,13 +144,19 @@ RCT_EXPORT_METHOD(useEmulator
142
144
  : (FIRApp *)firebaseApp
143
145
  : (nonnull NSString *)host
144
146
  : (NSInteger)port) {
145
- FIRFirestore *firestore = [RNFBFirestoreCommon getFirestoreForApp:firebaseApp];
146
- [firestore useEmulatorWithHost:host port:port];
147
-
148
- // It is not sufficient to just use emulator. You have toggle SSL off too.
149
- FIRFirestoreSettings *settings = firestore.settings;
150
- settings.sslEnabled = FALSE;
151
- firestore.settings = settings;
147
+ if (emulatorConfigs == nil) {
148
+ emulatorConfigs = [[NSMutableDictionary alloc] init];
149
+ }
150
+ if (!emulatorConfigs[firebaseApp.name]) {
151
+ FIRFirestore *firestore = [RNFBFirestoreCommon getFirestoreForApp:firebaseApp];
152
+ [firestore useEmulatorWithHost:host port:port];
153
+ emulatorConfigs[firebaseApp.name] = @YES;
154
+
155
+ // It is not sufficient to just use emulator. You have toggle SSL off too.
156
+ FIRFirestoreSettings *settings = firestore.settings;
157
+ settings.sslEnabled = FALSE;
158
+ firestore.settings = settings;
159
+ }
152
160
  }
153
161
 
154
162
  RCT_EXPORT_METHOD(waitForPendingWrites
@@ -0,0 +1,52 @@
1
+ /*
2
+ * Copyright (c) 2022-present Invertase Limited & Contributors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this library except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ */
17
+
18
+ export class FirestoreAggregateQuery {
19
+ constructor(firestore, query, collectionPath, modifiers) {
20
+ this._firestore = firestore;
21
+ this._query = query;
22
+ this._collectionPath = collectionPath;
23
+ this._modifiers = modifiers;
24
+ }
25
+
26
+ get query() {
27
+ return this._query;
28
+ }
29
+
30
+ get() {
31
+ return this._firestore.native
32
+ .collectionCount(
33
+ this._collectionPath.relativeName,
34
+ this._modifiers.type,
35
+ this._modifiers.filters,
36
+ this._modifiers.orders,
37
+ this._modifiers.options,
38
+ )
39
+ .then(data => new FirestoreAggregateQuerySnapshot(this._query, data));
40
+ }
41
+ }
42
+
43
+ export class FirestoreAggregateQuerySnapshot {
44
+ constructor(query, data) {
45
+ this._query = query;
46
+ this._data = data;
47
+ }
48
+
49
+ data() {
50
+ return { count: this._data.count };
51
+ }
52
+ }
@@ -26,6 +26,7 @@ import NativeError from '@react-native-firebase/app/lib/internal/NativeFirebaseE
26
26
  import FirestoreDocumentSnapshot from './FirestoreDocumentSnapshot';
27
27
  import FirestoreFieldPath, { fromDotSeparatedString } from './FirestoreFieldPath';
28
28
  import FirestoreQuerySnapshot from './FirestoreQuerySnapshot';
29
+ import { FirestoreAggregateQuery } from './FirestoreAggregate';
29
30
  import { parseSnapshotArgs } from './utils';
30
31
 
31
32
  let _id = 0;
@@ -130,6 +131,15 @@ export default class FirestoreQuery {
130
131
  return modifiers.setFieldsCursor(cursor, allFields);
131
132
  }
132
133
 
134
+ count() {
135
+ return new FirestoreAggregateQuery(
136
+ this._firestore,
137
+ this,
138
+ this._collectionPath,
139
+ this._modifiers,
140
+ );
141
+ }
142
+
133
143
  endAt(docOrField, ...fields) {
134
144
  return new FirestoreQuery(
135
145
  this._firestore,
package/lib/index.d.ts CHANGED
@@ -840,11 +840,107 @@ export namespace FirebaseFirestoreTypes {
840
840
  source: 'default' | 'server' | 'cache';
841
841
  }
842
842
 
843
+ /**
844
+ * Represents an aggregation that can be performed by Firestore.
845
+ */
846
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
847
+ export class AggregateField<T> {
848
+ /** A type string to uniquely identify instances of this class. */
849
+ type = 'AggregateField';
850
+ }
851
+
852
+ /**
853
+ * The union of all `AggregateField` types that are supported by Firestore.
854
+ */
855
+ export type AggregateFieldType = AggregateField<number>;
856
+
857
+ /**
858
+ * A type whose property values are all `AggregateField` objects.
859
+ */
860
+ export interface AggregateSpec {
861
+ [field: string]: AggregateFieldType;
862
+ }
863
+
864
+ /**
865
+ * A type whose keys are taken from an `AggregateSpec`, and whose values are the
866
+ * result of the aggregation performed by the corresponding `AggregateField`
867
+ * from the input `AggregateSpec`.
868
+ */
869
+ export type AggregateSpecData<T extends AggregateSpec> = {
870
+ [P in keyof T]: T[P] extends AggregateField<infer U> ? U : never;
871
+ };
872
+
873
+ /**
874
+ * The results of executing an aggregation query.
875
+ */
876
+ export interface AggregateQuerySnapshot<T extends AggregateSpec> {
877
+ /**
878
+ * The underlying query over which the aggregations recorded in this
879
+ * `AggregateQuerySnapshot` were performed.
880
+ */
881
+ get query(): Query<unknown>;
882
+
883
+ /**
884
+ * Returns the results of the aggregations performed over the underlying
885
+ * query.
886
+ *
887
+ * The keys of the returned object will be the same as those of the
888
+ * `AggregateSpec` object specified to the aggregation method, and the values
889
+ * will be the corresponding aggregation result.
890
+ *
891
+ * @returns The results of the aggregations performed over the underlying
892
+ * query.
893
+ */
894
+ data(): AggregateSpecData<T>;
895
+ }
896
+
897
+ /**
898
+ * The results of requesting an aggregated query.
899
+ */
900
+ export interface AggregateQuery<T extends AggregateSpec> {
901
+ /**
902
+ * The underlying query for this instance.
903
+ */
904
+ get query(): Query<unknown>;
905
+
906
+ /**
907
+ * Executes the query and returns the results as a AggregateQuerySnapshot.
908
+ *
909
+ *
910
+ * #### Example
911
+ *
912
+ * ```js
913
+ * const querySnapshot = await firebase.firestore()
914
+ * .collection('users')
915
+ * .count()
916
+ * .get();
917
+ * ```
918
+ *
919
+ * @param options An object to configure the get behavior.
920
+ */
921
+ get(): Promise<AggregateQuerySnapshot<T>>;
922
+ }
923
+
843
924
  /**
844
925
  * A Query refers to a `Query` which you can read or listen to. You can also construct refined `Query` objects by
845
926
  * adding filters and ordering.
846
927
  */
847
928
  export interface Query<T extends DocumentData = DocumentData> {
929
+ /**
930
+ * Calculates the number of documents in the result set of the given query, without actually downloading
931
+ * the documents.
932
+ *
933
+ * Using this function to count the documents is efficient because only the final count, not the
934
+ * documents' data, is downloaded. This function can even count the documents if the result set
935
+ * would be prohibitively large to download entirely (e.g. thousands of documents).
936
+ *
937
+ * The result received from the server is presented, unaltered, without considering any local state.
938
+ * That is, documents in the local cache are not taken into consideration, neither are local
939
+ * modifications not yet synchronized with the server. Previously-downloaded results, if any,
940
+ * are not used: every request using this source necessarily involves a round trip to the server.
941
+ */
942
+ count(): AggregateQuery<{ count: AggregateField<number> }>;
943
+
848
944
  /**
849
945
  * Creates and returns a new Query that ends at the provided document (inclusive). The end
850
946
  * position is relative to the order of the query. The document must contain all of the
package/lib/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- module.exports = '15.7.1';
2
+ module.exports = '16.1.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-firebase/firestore",
3
- "version": "15.7.1",
3
+ "version": "16.1.0",
4
4
  "author": "Invertase <oss@invertase.io> (http://invertase.io)",
5
5
  "description": "React Native Firebase - Cloud Firestore is a NoSQL cloud database to store and sync data between your React Native application and Firebase's database. The API matches the Firebase Web SDK whilst taking advantage of the native SDKs performance and offline capabilities.",
6
6
  "main": "lib/index.js",
@@ -27,10 +27,10 @@
27
27
  "firestore"
28
28
  ],
29
29
  "peerDependencies": {
30
- "@react-native-firebase/app": "15.7.1"
30
+ "@react-native-firebase/app": "16.1.0"
31
31
  },
32
32
  "publishConfig": {
33
33
  "access": "public"
34
34
  },
35
- "gitHead": "7845819f67e955d75b5756d30c2f5b55a68c9062"
35
+ "gitHead": "f2d1363b89fb046388f8336b08852c1ea0c285f2"
36
36
  }