@react-native-firebase/database 26.3.3 → 27.0.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/RNFBDatabase.podspec +10 -2
  3. package/android/build.gradle +7 -0
  4. package/android/src/main/java/io/invertase/firebase/database/DatabaseAbortable.java +22 -0
  5. package/android/src/main/java/io/invertase/firebase/database/DatabaseQueryHandle.java +24 -0
  6. package/android/src/main/java/io/invertase/firebase/database/RNFBDatabaseKeepSyncedRegistry.java +106 -0
  7. package/android/src/main/java/io/invertase/firebase/database/RNFBDatabaseListenerRegistry.kt +133 -0
  8. package/android/src/main/java/io/invertase/firebase/database/RNFBDatabaseQueryRegistry.kt +76 -0
  9. package/android/src/main/java/io/invertase/firebase/database/RNFBDatabaseTransactionRegistry.kt +67 -0
  10. package/android/src/main/java/io/invertase/firebase/database/UniversalFirebaseDatabaseOnDisconnectModule.java +102 -9
  11. package/android/src/reactnative/java/io/invertase/firebase/database/NativeRNFBTurboDatabaseOnDisconnect.java +6 -11
  12. package/android/src/reactnative/java/io/invertase/firebase/database/NativeRNFBTurboDatabaseQuery.java +111 -24
  13. package/android/src/reactnative/java/io/invertase/firebase/database/NativeRNFBTurboDatabaseTransaction.java +12 -25
  14. package/android/src/reactnative/java/io/invertase/firebase/database/ReactNativeFirebaseDatabaseQuery.java +30 -33
  15. package/android/src/reactnative/java/io/invertase/firebase/database/ReactNativeFirebaseDatabaseTransactionHandler.java +3 -3
  16. package/android/src/reactnative/java/io/invertase/firebase/database/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboDatabaseQuerySpec.java +4 -0
  17. package/android/src/reactnative/java/io/invertase/firebase/database/generated/jni/RNFBDatabaseTurboModules-generated.cpp +6 -0
  18. package/android/src/reactnative/java/io/invertase/firebase/database/generated/jni/react/renderer/components/RNFBDatabaseTurboModules/RNFBDatabaseTurboModulesJSI.h +12 -0
  19. package/android/src/test/java/io/invertase/firebase/database/RNFBDatabaseKeepSyncedRegistryTest.java +174 -0
  20. package/android/src/test/java/io/invertase/firebase/database/RNFBDatabaseListenerRegistryTest.java +191 -0
  21. package/android/src/test/java/io/invertase/firebase/database/RNFBDatabaseQueryRegistryTest.java +489 -0
  22. package/android/src/test/java/io/invertase/firebase/database/RNFBDatabaseTransactionRegistryTest.java +199 -0
  23. package/android/src/test/java/io/invertase/firebase/database/UniversalFirebaseDatabaseOnDisconnectCancelErrorTest.java +137 -0
  24. package/dist/module/DatabaseQuery.js +52 -1
  25. package/dist/module/DatabaseQuery.js.map +1 -1
  26. package/dist/module/DatabaseSyncTree.js +1 -1
  27. package/dist/module/DatabaseSyncTree.js.map +1 -1
  28. package/dist/module/index.js +1 -2
  29. package/dist/module/index.js.map +1 -1
  30. package/dist/module/modular/query.js +1 -1
  31. package/dist/module/modular/query.js.map +1 -1
  32. package/dist/module/version.js +1 -1
  33. package/dist/module/web/RNFBDatabaseModule.js +7 -0
  34. package/dist/module/web/RNFBDatabaseModule.js.map +1 -1
  35. package/dist/typescript/lib/DatabaseQuery.d.ts +25 -0
  36. package/dist/typescript/lib/DatabaseQuery.d.ts.map +1 -1
  37. package/dist/typescript/lib/index.d.ts +1 -1
  38. package/dist/typescript/lib/types/internal.d.ts +2 -0
  39. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  40. package/dist/typescript/lib/version.d.ts +1 -1
  41. package/dist/typescript/lib/web/RNFBDatabaseModule.d.ts.map +1 -1
  42. package/ios/RNFBDatabase/RNFBDatabaseListenerRegistry.h +37 -0
  43. package/ios/RNFBDatabase/RNFBDatabaseListenerRegistry.m +91 -0
  44. package/ios/RNFBDatabase/RNFBDatabaseListenerRegistryStorage.swift +81 -0
  45. package/ios/RNFBDatabase/RNFBDatabaseNullSentinelDecoder.h +36 -0
  46. package/ios/RNFBDatabase/RNFBDatabaseNullSentinelDecoder.m +48 -0
  47. package/ios/RNFBDatabase/RNFBDatabaseOnDisconnectHelper.m +29 -26
  48. package/ios/RNFBDatabase/RNFBDatabaseQuery.h +3 -2
  49. package/ios/RNFBDatabase/RNFBDatabaseQuery.m +14 -13
  50. package/ios/RNFBDatabase/RNFBDatabaseQueryHelper.h +7 -0
  51. package/ios/RNFBDatabase/RNFBDatabaseQueryHelper.m +44 -21
  52. package/ios/RNFBDatabase/RNFBDatabaseQueryModule.mm +14 -0
  53. package/ios/RNFBDatabase/RNFBDatabaseQueryRegistry.h +37 -0
  54. package/ios/RNFBDatabase/RNFBDatabaseQueryRegistry.m +79 -0
  55. package/ios/RNFBDatabase/RNFBDatabaseQueryRegistryStorage.swift +104 -0
  56. package/ios/RNFBDatabase/RNFBDatabaseReferenceHelper.m +14 -12
  57. package/ios/RNFBDatabase/RNFBDatabaseTransactionHelper.m +3 -1
  58. package/ios/RNFBDatabase.xcodeproj/project.pbxproj +12 -0
  59. package/ios/RNFBDatabaseUnitTests/RNFBDatabaseListenerRegistryStorageTests.swift +86 -0
  60. package/ios/RNFBDatabaseUnitTests/RNFBDatabaseListenerRegistryTests.m +90 -0
  61. package/ios/RNFBDatabaseUnitTests/RNFBDatabaseNullSentinelDecodeTests.m +118 -0
  62. package/ios/RNFBDatabaseUnitTests/RNFBDatabaseQueryRegistryStorageTests.swift +181 -0
  63. package/ios/RNFBDatabaseUnitTests/RNFBDatabaseQueryRegistryTests.m +390 -0
  64. package/ios/RNFBDatabaseUnitTests/RNFBDatabaseUnitTests.xcodeproj/project.pbxproj +303 -0
  65. package/ios/RNFBDatabaseUnitTests/RNFBDatabaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBDatabaseUnitTests.xcscheme +69 -0
  66. package/ios/generated/RNFBDatabaseTurboModules/RNFBDatabaseTurboModules-generated.mm +7 -0
  67. package/ios/generated/RNFBDatabaseTurboModules/RNFBDatabaseTurboModules.h +6 -0
  68. package/ios/generated/RNFBDatabaseTurboModulesJSI.h +12 -0
  69. package/lib/DatabaseQuery.ts +56 -0
  70. package/lib/DatabaseSyncTree.ts +1 -1
  71. package/lib/index.ts +1 -1
  72. package/lib/modular/query.ts +1 -1
  73. package/lib/types/internal.ts +2 -0
  74. package/lib/version.ts +1 -1
  75. package/lib/web/RNFBDatabaseModule.ts +13 -0
  76. package/package.json +5 -4
  77. package/specs/NativeRNFBTurboDatabaseQuery.ts +1 -0
@@ -0,0 +1,174 @@
1
+ package io.invertase.firebase.database;
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import static org.junit.Assert.assertEquals;
21
+ import static org.junit.Assert.assertFalse;
22
+ import static org.junit.Assert.assertTrue;
23
+
24
+ import java.util.ArrayList;
25
+ import java.util.Arrays;
26
+ import java.util.Collections;
27
+ import java.util.List;
28
+ import org.junit.Test;
29
+
30
+ public class RNFBDatabaseKeepSyncedRegistryTest {
31
+ private static final String LOCATION = "[DEFAULT]|https://db.example.com/users/1";
32
+ private static final String OTHER_LOCATION = "[DEFAULT]|https://db.example.com/users/2";
33
+
34
+ private final RNFBDatabaseKeepSyncedRegistry registry = new RNFBDatabaseKeepSyncedRegistry();
35
+ private final List<String> applied = new ArrayList<>();
36
+
37
+ private void keepSynced(String location, String queryKey, boolean enabled) {
38
+ registry.keepSynced(location, queryKey, enabled, () -> applied.add(queryKey + "=" + enabled));
39
+ }
40
+
41
+ @Test
42
+ public void beginNativeGet_nothingKeptSynced_returnsTrue() {
43
+ assertTrue(registry.beginNativeGet(LOCATION));
44
+ }
45
+
46
+ @Test
47
+ public void beginNativeGet_locationKeptSynced_returnsFalse() {
48
+ keepSynced(LOCATION, "plain", true);
49
+ assertFalse(registry.beginNativeGet(LOCATION));
50
+ }
51
+
52
+ @Test
53
+ public void beginNativeGet_queryAtLocationKeptSynced_returnsFalse() {
54
+ keepSynced(LOCATION, "limitToLast(1)", true);
55
+ assertFalse(registry.beginNativeGet(LOCATION));
56
+ }
57
+
58
+ @Test
59
+ public void beginNativeGet_otherLocationKeptSynced_returnsTrue() {
60
+ keepSynced(OTHER_LOCATION, "plain", true);
61
+ assertTrue(registry.beginNativeGet(LOCATION));
62
+ }
63
+
64
+ @Test
65
+ public void beginNativeGet_afterKeepSyncedFalse_returnsTrue() {
66
+ keepSynced(LOCATION, "plain", true);
67
+ keepSynced(LOCATION, "plain", false);
68
+ assertTrue(registry.beginNativeGet(LOCATION));
69
+ }
70
+
71
+ @Test
72
+ public void beginNativeGet_untilEveryQueryAtLocationIsCleared_returnsFalse() {
73
+ keepSynced(LOCATION, "plain", true);
74
+ keepSynced(LOCATION, "limitToLast(1)", true);
75
+ keepSynced(LOCATION, "plain", false);
76
+ assertFalse(registry.beginNativeGet(LOCATION));
77
+ keepSynced(LOCATION, "limitToLast(1)", false);
78
+ assertTrue(registry.beginNativeGet(LOCATION));
79
+ }
80
+
81
+ @Test
82
+ public void keepSynced_noNativeGetInFlight_appliesNow() {
83
+ keepSynced(LOCATION, "plain", true);
84
+ assertEquals(Collections.singletonList("plain=true"), applied);
85
+ }
86
+
87
+ @Test
88
+ public void keepSynced_disableWhenNothingKept_stillApplies() {
89
+ keepSynced(LOCATION, "plain", false);
90
+ assertEquals(Collections.singletonList("plain=false"), applied);
91
+ assertTrue(registry.beginNativeGet(LOCATION));
92
+ }
93
+
94
+ @Test
95
+ public void keepSynced_noNativeGetInFlight_runsApplyBeforeCallerCompletion() {
96
+ List<String> order = new ArrayList<>();
97
+ registry.keepSynced(
98
+ LOCATION,
99
+ "plain",
100
+ true,
101
+ () -> {
102
+ order.add("sdk");
103
+ order.add("promise");
104
+ });
105
+ assertEquals(Arrays.asList("sdk", "promise"), order);
106
+ }
107
+
108
+ @Test
109
+ public void keepSynced_nativeGetInFlight_waitsForItInCallOrder() {
110
+ registry.beginNativeGet(LOCATION);
111
+ keepSynced(LOCATION, "plain", true);
112
+ keepSynced(LOCATION, "limitToLast(1)", true);
113
+ keepSynced(LOCATION, "plain", false);
114
+ assertTrue(applied.isEmpty());
115
+
116
+ registry.endNativeGet(LOCATION);
117
+ assertEquals(Arrays.asList("plain=true", "limitToLast(1)=true", "plain=false"), applied);
118
+ }
119
+
120
+ @Test
121
+ public void keepSynced_nativeGetInFlight_runsEachApplyBeforeItsCallerCompletion() {
122
+ List<String> order = new ArrayList<>();
123
+ registry.beginNativeGet(LOCATION);
124
+ registry.keepSynced(
125
+ LOCATION,
126
+ "plain",
127
+ true,
128
+ () -> {
129
+ order.add("sdk-true");
130
+ order.add("promise-true");
131
+ });
132
+ registry.keepSynced(
133
+ LOCATION,
134
+ "plain",
135
+ false,
136
+ () -> {
137
+ order.add("sdk-false");
138
+ order.add("promise-false");
139
+ });
140
+ assertTrue(order.isEmpty());
141
+
142
+ registry.endNativeGet(LOCATION);
143
+ assertEquals(Arrays.asList("sdk-true", "promise-true", "sdk-false", "promise-false"), order);
144
+ }
145
+
146
+ @Test
147
+ public void keepSynced_nativeGetInFlight_makesLaterGetsUseOnce() {
148
+ registry.beginNativeGet(LOCATION);
149
+ keepSynced(LOCATION, "plain", true);
150
+ assertFalse(registry.beginNativeGet(LOCATION));
151
+ }
152
+
153
+ @Test
154
+ public void keepSynced_nativeGetInFlightAtOtherLocation_appliesNow() {
155
+ registry.beginNativeGet(OTHER_LOCATION);
156
+ keepSynced(LOCATION, "plain", true);
157
+ assertEquals(Collections.singletonList("plain=true"), applied);
158
+ }
159
+
160
+ @Test
161
+ public void endNativeGet_waitsForTheLastGetAtLocation() {
162
+ registry.beginNativeGet(LOCATION);
163
+ registry.beginNativeGet(LOCATION);
164
+ keepSynced(LOCATION, "plain", true);
165
+
166
+ registry.endNativeGet(LOCATION);
167
+ assertTrue(applied.isEmpty());
168
+ registry.endNativeGet(LOCATION);
169
+ assertEquals(Collections.singletonList("plain=true"), applied);
170
+
171
+ keepSynced(LOCATION, "plain", false);
172
+ assertEquals(Arrays.asList("plain=true", "plain=false"), applied);
173
+ }
174
+ }
@@ -0,0 +1,191 @@
1
+ package io.invertase.firebase.database;
2
+
3
+ /*
4
+ * Copyright (c) 2016-present Invertase Limited & Contributors
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this library except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ *
18
+ */
19
+
20
+ import static org.junit.Assert.assertEquals;
21
+ import static org.junit.Assert.assertFalse;
22
+ import static org.junit.Assert.assertNull;
23
+ import static org.junit.Assert.assertSame;
24
+ import static org.junit.Assert.assertTrue;
25
+ import static org.junit.Assert.fail;
26
+
27
+ import io.invertase.firebase.common.RNFBHandleCollisionException;
28
+ import org.junit.Test;
29
+
30
+ public class RNFBDatabaseListenerRegistryTest {
31
+
32
+ @Test
33
+ public void putValueGetTake_happyPath() throws Exception {
34
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
35
+ Object listener = new Object();
36
+ registry.putValue("k", listener);
37
+ assertSame(listener, registry.getValue("k"));
38
+ assertSame(listener, registry.takeValue("k"));
39
+ assertNull(registry.getValue("k"));
40
+ assertFalse(registry.hasListeners());
41
+ }
42
+
43
+ @Test
44
+ public void putChildGetTake_happyPath() throws Exception {
45
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
46
+ Object listener = new Object();
47
+ registry.putChild("k", listener);
48
+ assertSame(listener, registry.getChild("k"));
49
+ assertSame(listener, registry.takeChild("k"));
50
+ assertNull(registry.getChild("k"));
51
+ assertFalse(registry.hasListeners());
52
+ }
53
+
54
+ @Test
55
+ public void putValue_occupiedId_throwsCollision() throws Exception {
56
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
57
+ Object first = new Object();
58
+ registry.putValue("k", first);
59
+ try {
60
+ registry.putValue("k", new Object());
61
+ fail("expected RNFBHandleCollisionException");
62
+ } catch (RNFBHandleCollisionException e) {
63
+ assertTrue(e.getMessage().contains("k"));
64
+ assertSame(first, registry.getValue("k"));
65
+ }
66
+ }
67
+
68
+ @Test
69
+ public void putChild_occupiedId_throwsCollision() throws Exception {
70
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
71
+ Object first = new Object();
72
+ registry.putChild("k", first);
73
+ try {
74
+ registry.putChild("k", new Object());
75
+ fail("expected RNFBHandleCollisionException");
76
+ } catch (RNFBHandleCollisionException e) {
77
+ assertTrue(e.getMessage().contains("k"));
78
+ assertSame(first, registry.getChild("k"));
79
+ }
80
+ }
81
+
82
+ @Test
83
+ public void putValue_nullListener_throws() throws Exception {
84
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
85
+ try {
86
+ registry.putValue("k", null);
87
+ fail("expected NullPointerException");
88
+ } catch (NullPointerException e) {
89
+ assertEquals("listener", e.getMessage());
90
+ assertFalse(registry.hasListeners());
91
+ }
92
+ }
93
+
94
+ @Test
95
+ public void putChild_nullListener_throws() throws Exception {
96
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
97
+ try {
98
+ registry.putChild("k", null);
99
+ fail("expected NullPointerException");
100
+ } catch (NullPointerException e) {
101
+ assertEquals("listener", e.getMessage());
102
+ }
103
+ }
104
+
105
+ @Test
106
+ public void takeValue_missingKey_isNoOp() {
107
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
108
+ assertNull(registry.takeValue("missing"));
109
+ assertFalse(registry.hasListeners());
110
+ }
111
+
112
+ @Test
113
+ public void getValue_nullKey_returnsNull_noNpe() {
114
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
115
+ assertNull(registry.getValue(null));
116
+ }
117
+
118
+ @Test
119
+ public void getChild_nullKey_returnsNull_noNpe() {
120
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
121
+ assertNull(registry.getChild(null));
122
+ }
123
+
124
+ @Test
125
+ public void takeValue_nullKey_returnsNull_noNpe() {
126
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
127
+ assertNull(registry.takeValue(null));
128
+ assertFalse(registry.hasListeners());
129
+ }
130
+
131
+ @Test
132
+ public void takeChild_nullKey_returnsNull_noNpe() {
133
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
134
+ assertNull(registry.takeChild(null));
135
+ }
136
+
137
+ @Test
138
+ public void hasEventListener_nullKey_returnsFalse_noNpe() {
139
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
140
+ assertFalse(registry.hasEventListener(null));
141
+ }
142
+
143
+ @Test
144
+ public void takeChild_missingKey_isNoOp() {
145
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
146
+ assertNull(registry.takeChild("missing"));
147
+ }
148
+
149
+ @Test
150
+ public void takeAllValuesAndChildren_empty_isNoOp() {
151
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
152
+ assertTrue(registry.takeAllValues().isEmpty());
153
+ assertTrue(registry.takeAllChildren().isEmpty());
154
+ }
155
+
156
+ @Test
157
+ public void hasEventListener_valueOrChild() throws Exception {
158
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
159
+ assertFalse(registry.hasEventListener("k"));
160
+ registry.putValue("k", new Object());
161
+ assertTrue(registry.hasEventListener("k"));
162
+ registry.takeValue("k");
163
+ registry.putChild("k", new Object());
164
+ assertTrue(registry.hasEventListener("k"));
165
+ }
166
+
167
+ @Test
168
+ public void hasListeners_tracksOccupancyAcrossMaps() throws Exception {
169
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
170
+ registry.putValue("v", new Object());
171
+ registry.putChild("c", new Object());
172
+ assertTrue(registry.hasListeners());
173
+ registry.takeAllValues();
174
+ assertTrue(registry.hasListeners());
175
+ registry.takeAllChildren();
176
+ assertFalse(registry.hasListeners());
177
+ }
178
+
179
+ @Test
180
+ public void takeAll_combinesValueAndChildMaps() throws Exception {
181
+ RNFBDatabaseListenerRegistry registry = new RNFBDatabaseListenerRegistry();
182
+ Object value = new Object();
183
+ Object child = new Object();
184
+ registry.putValue("v", value);
185
+ registry.putChild("c", child);
186
+ assertEquals(2, registry.takeAll().size());
187
+ assertFalse(registry.hasListeners());
188
+ assertNull(registry.getValue("v"));
189
+ assertNull(registry.getChild("c"));
190
+ }
191
+ }