@react-native-firebase/app 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 (283) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +10 -27
  3. package/RNFBApp.podspec +13 -5
  4. package/android/build.gradle +3 -0
  5. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.kt +29 -0
  6. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.kt +146 -0
  7. package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.kt +156 -0
  8. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.kt +44 -0
  9. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.kt +100 -0
  10. package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.kt +250 -0
  11. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.kt +64 -0
  12. package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppInitProvider.java → ReactNativeFirebaseAppInitProvider.kt} +3 -4
  13. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.kt +47 -0
  14. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.kt +33 -0
  15. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +1 -1
  16. package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.kt +185 -0
  17. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.kt +35 -0
  18. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.kt +662 -0
  19. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.kt +103 -0
  20. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.kt +96 -0
  21. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.kt +140 -0
  22. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.kt +109 -0
  23. package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.kt +451 -0
  24. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{ContextProvider.java → ContextProvider.kt} +8 -8
  25. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeError.java → NativeError.kt} +8 -8
  26. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeEvent.java → NativeEvent.kt} +6 -6
  27. package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.kt +219 -0
  28. package/android/src/test/java/expo/core/ModuleRegistry.java +9 -0
  29. package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +208 -60
  30. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppComponentsJavaCompatibilityTest.java +70 -0
  31. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppJavaCompatibilityTest.java +60 -0
  32. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackageTest.java +165 -0
  33. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppTest.kt +167 -0
  34. package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseJavaCompatibilityTest.java +112 -0
  35. package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseTest.kt +317 -0
  36. package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.kt +309 -0
  37. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterJavaCompatibilityTest.java +176 -0
  38. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +144 -13
  39. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventTest.kt +61 -0
  40. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONJavaCompatibilityTest.java +85 -0
  41. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.kt +296 -0
  42. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaJavaCompatibilityTest.java +67 -0
  43. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaTest.kt +246 -0
  44. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseModuleTest.kt +254 -0
  45. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesJavaCompatibilityTest.java +87 -0
  46. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesTest.kt +260 -0
  47. package/android/src/test/java/io/invertase/firebase/common/SharedUtilsJavaCompatibilityTest.java +255 -0
  48. package/android/src/test/java/io/invertase/firebase/common/SharedUtilsTest.kt +674 -0
  49. package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.kt +290 -0
  50. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebaseModuleJavaCompatibilityTest.java +178 -0
  51. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesJavaCompatibilityTest.java +99 -0
  52. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesTest.kt +217 -0
  53. package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleJavaCompatibilityTest.java +176 -0
  54. package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleKotlinCompatibilityTest.kt +52 -0
  55. package/android/src/test/java/io/invertase/firebase/interfaces/InterfacesJavaCompatibilityTest.java +144 -0
  56. package/android/src/test/java/io/invertase/firebase/interfaces/NativeEventTest.kt +56 -0
  57. package/android/src/test/java/io/invertase/firebase/utils/NativeRNFBTurboUtilsTest.java +517 -23
  58. package/dist/module/FirebaseApp.js +10 -0
  59. package/dist/module/FirebaseApp.js.map +1 -1
  60. package/dist/module/common/Base64.js +13 -21
  61. package/dist/module/common/Base64.js.map +1 -1
  62. package/dist/module/common/deeps.js +3 -0
  63. package/dist/module/common/deeps.js.map +1 -1
  64. package/dist/module/common/index.js +17 -9
  65. package/dist/module/common/index.js.map +1 -1
  66. package/dist/module/internal/FirebaseModule.js.map +1 -1
  67. package/dist/module/internal/RNFBNativeEventEmitter.js +12 -1
  68. package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
  69. package/dist/module/internal/SharedEventEmitter.js +3 -1
  70. package/dist/module/internal/SharedEventEmitter.js.map +1 -1
  71. package/dist/module/internal/asyncStorage.js +7 -11
  72. package/dist/module/internal/asyncStorage.js.map +1 -1
  73. package/dist/module/internal/index.js +1 -0
  74. package/dist/module/internal/index.js.map +1 -1
  75. package/dist/module/internal/logger.js +44 -40
  76. package/dist/module/internal/logger.js.map +1 -1
  77. package/dist/module/internal/nativeModuleAndroidIos.js +2 -29
  78. package/dist/module/internal/nativeModuleAndroidIos.js.map +1 -1
  79. package/dist/module/internal/nativeModuleDebug.js +74 -0
  80. package/dist/module/internal/nativeModuleDebug.js.map +1 -0
  81. package/dist/module/internal/nativeModuleWeb.js +9 -29
  82. package/dist/module/internal/nativeModuleWeb.js.map +1 -1
  83. package/dist/module/internal/registry/app.js +8 -2
  84. package/dist/module/internal/registry/app.js.map +1 -1
  85. package/dist/module/internal/registry/modular.js +2 -2
  86. package/dist/module/internal/registry/modular.js.map +1 -1
  87. package/dist/module/internal/registry/nativeModule.js +3 -3
  88. package/dist/module/internal/registry/nativeModule.js.map +1 -1
  89. package/dist/module/internal/web/RNFBAppModule.js +16 -15
  90. package/dist/module/internal/web/RNFBAppModule.js.map +1 -1
  91. package/dist/module/internal/web/memidb/lib/FakeEventTarget.js +3 -1
  92. package/dist/module/internal/web/memidb/lib/FakeEventTarget.js.map +1 -1
  93. package/dist/module/types/app.js.map +1 -1
  94. package/dist/module/types/internal.js +2 -0
  95. package/dist/module/version.js +1 -1
  96. package/dist/typescript/lib/FirebaseApp.d.ts +7 -0
  97. package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
  98. package/dist/typescript/lib/common/Base64.d.ts.map +1 -1
  99. package/dist/typescript/lib/common/deeps.d.ts.map +1 -1
  100. package/dist/typescript/lib/common/index.d.ts.map +1 -1
  101. package/dist/typescript/lib/internal/FirebaseModule.d.ts +2 -3
  102. package/dist/typescript/lib/internal/FirebaseModule.d.ts.map +1 -1
  103. package/dist/typescript/lib/internal/NativeModules.d.ts +4 -1
  104. package/dist/typescript/lib/internal/NativeModules.d.ts.map +1 -1
  105. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts +2 -2
  106. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
  107. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts +3 -3
  108. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts.map +1 -1
  109. package/dist/typescript/lib/internal/asyncStorage.d.ts.map +1 -1
  110. package/dist/typescript/lib/internal/index.d.ts +1 -0
  111. package/dist/typescript/lib/internal/index.d.ts.map +1 -1
  112. package/dist/typescript/lib/internal/logger.d.ts.map +1 -1
  113. package/dist/typescript/lib/internal/nativeModuleAndroidIos.d.ts.map +1 -1
  114. package/dist/typescript/lib/internal/nativeModuleDebug.d.ts +2 -0
  115. package/dist/typescript/lib/internal/nativeModuleDebug.d.ts.map +1 -0
  116. package/dist/typescript/lib/internal/nativeModuleWeb.d.ts.map +1 -1
  117. package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
  118. package/dist/typescript/lib/internal/web/RNFBAppModule.d.ts +7 -7
  119. package/dist/typescript/lib/internal/web/RNFBAppModule.d.ts.map +1 -1
  120. package/dist/typescript/lib/types/app.d.ts +10 -3
  121. package/dist/typescript/lib/types/app.d.ts.map +1 -1
  122. package/dist/typescript/lib/types/internal.d.ts +12 -0
  123. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  124. package/dist/typescript/lib/version.d.ts +1 -1
  125. package/firebase-schema.json +5 -1
  126. package/firebase_spm.rb +552 -96
  127. package/ios/RNFBApp/RCTConvert+FIRApp.h +2 -5
  128. package/ios/RNFBApp/RCTConvert+FIRApp.m +11 -6
  129. package/ios/RNFBApp/RCTConvert+FIROptions.h +2 -5
  130. package/ios/RNFBApp/RCTConvert+FIROptions.m +11 -10
  131. package/ios/RNFBApp/RCTConvertFIRApp.swift +86 -0
  132. package/ios/RNFBApp/RCTConvertFIROptions.swift +259 -0
  133. package/ios/RNFBApp/RNFBAppCustomAuthDomains.swift +63 -0
  134. package/ios/RNFBApp/RNFBAppInitializeOptionsMapper.swift +113 -0
  135. package/ios/RNFBApp/RNFBAppLogLevelMapper.swift +53 -0
  136. package/ios/RNFBApp/RNFBAppModule+CustomAuthDomain.m +35 -0
  137. package/ios/RNFBApp/RNFBAppModule.h +6 -2
  138. package/ios/RNFBApp/RNFBAppModule.mm +67 -204
  139. package/ios/RNFBApp/RNFBAppModuleFirebase.swift +439 -0
  140. package/ios/RNFBApp/RNFBAppModuleImplementation.h +68 -0
  141. package/ios/RNFBApp/RNFBAppModuleImplementation.m +195 -0
  142. package/ios/RNFBApp/RNFBHandleMap.h +73 -0
  143. package/ios/RNFBApp/RNFBHandleMap.m +87 -0
  144. package/ios/RNFBApp/RNFBHandleMapStorage.swift +90 -0
  145. package/ios/RNFBApp/RNFBInitializeAppArguments.swift +82 -0
  146. package/ios/RNFBApp/RNFBJSON.m +22 -38
  147. package/ios/RNFBApp/RNFBJSONImplementation.swift +71 -0
  148. package/ios/RNFBApp/RNFBMeta.m +24 -26
  149. package/ios/RNFBApp/RNFBMetaStorage.swift +76 -0
  150. package/ios/RNFBApp/RNFBNullSentinelDecoding.swift +135 -0
  151. package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +30 -3
  152. package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +28 -5
  153. package/ios/RNFBApp/RNFBPreferences.m +22 -20
  154. package/ios/RNFBApp/RNFBPreferencesStorage.swift +101 -0
  155. package/ios/RNFBApp/RNFBRCTEventEmitter.m +36 -93
  156. package/ios/RNFBApp/RNFBRCTEventEmitterCore.swift +161 -0
  157. package/ios/RNFBApp/RNFBSharedUtils.h +2 -5
  158. package/ios/RNFBApp/RNFBSharedUtils.m +109 -197
  159. package/ios/RNFBApp/RNFBSharedUtilsConfig.swift +72 -0
  160. package/ios/RNFBApp/RNFBSharedUtilsFIRApp.swift +271 -0
  161. package/ios/RNFBApp/RNFBSharedUtilsFormatting.swift +59 -0
  162. package/ios/RNFBApp/RNFBSharedUtilsPromiseRejection.swift +88 -0
  163. package/ios/RNFBApp/RNFBUtilsHelpers.swift +116 -0
  164. package/ios/RNFBApp/RNFBUtilsModule+Foundation.m +44 -0
  165. package/ios/RNFBApp/RNFBUtilsModule+PhotoAssets.m +47 -0
  166. package/ios/RNFBApp/RNFBUtilsModule.h +11 -1
  167. package/ios/RNFBApp/RNFBUtilsModule.mm +10 -85
  168. package/ios/RNFBApp/RNFBUtilsModuleImplementation.h +32 -0
  169. package/ios/RNFBApp/RNFBUtilsModuleImplementation.m +56 -0
  170. package/ios/RNFBApp/RNFBVersion.m +1 -1
  171. package/ios/RNFBApp.xcodeproj/project.pbxproj +106 -0
  172. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FIRApp.m +171 -0
  173. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FirebaseCore.h +78 -0
  174. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FIRInstallations.m +7 -0
  175. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FirebaseInstallations.h +8 -0
  176. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppModuleHostStub.m +55 -0
  177. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.h +89 -0
  178. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.mm +30 -0
  179. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.h +19 -0
  180. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.m +32 -0
  181. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridgeModule.h +19 -0
  182. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.h +28 -0
  183. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.m +23 -0
  184. package/ios/RNFBAppUnitTests/HostStubs/React/RCTEventEmitter.h +9 -0
  185. package/ios/RNFBAppUnitTests/HostStubs/React/RCTInvalidating.h +24 -0
  186. package/ios/RNFBAppUnitTests/HostStubs/React/RCTUtils.h +9 -0
  187. package/ios/RNFBAppUnitTests/HostStubs/module.modulemap +13 -0
  188. package/ios/RNFBAppUnitTests/RCTConvertFIRAppFacadeTests.m +61 -0
  189. package/ios/RNFBAppUnitTests/RCTConvertFIRAppTests.swift +73 -0
  190. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsFacadeTests.m +57 -0
  191. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsTests.swift +243 -0
  192. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsFacadeTests.m +73 -0
  193. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsTests.swift +70 -0
  194. package/ios/RNFBAppUnitTests/RNFBAppInitializeOptionsMapperTests.swift +190 -0
  195. package/ios/RNFBAppUnitTests/RNFBAppLogLevelFacadeTests.m +76 -0
  196. package/ios/RNFBAppUnitTests/RNFBAppLogLevelMapperTests.swift +59 -0
  197. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseFacadeTests.m +215 -0
  198. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseTests.swift +430 -0
  199. package/ios/RNFBAppUnitTests/RNFBAppModuleLifecycleTests.m +206 -0
  200. package/ios/RNFBAppUnitTests/RNFBAppModuleShellTests.mm +367 -0
  201. package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/project.pbxproj +590 -0
  202. package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBAppUnitTests.xcscheme +69 -0
  203. package/ios/RNFBAppUnitTests/RNFBFirebaseAppClientTests.swift +165 -0
  204. package/ios/RNFBAppUnitTests/RNFBHandleMapStorageTests.swift +121 -0
  205. package/ios/RNFBAppUnitTests/RNFBHandleMapTests.m +238 -0
  206. package/ios/RNFBAppUnitTests/RNFBInitializeAppArgumentsTests.swift +256 -0
  207. package/ios/RNFBAppUnitTests/RNFBJSONImplementationTests.swift +126 -0
  208. package/ios/RNFBAppUnitTests/RNFBJSONTests.m +172 -0
  209. package/ios/RNFBAppUnitTests/RNFBMetaStorageTests.swift +106 -0
  210. package/ios/RNFBAppUnitTests/RNFBMetaTests.m +65 -0
  211. package/ios/RNFBAppUnitTests/RNFBNullSentinelDecodingTests.swift +286 -0
  212. package/ios/RNFBAppUnitTests/RNFBNullSentinelInterceptorTests.m +312 -0
  213. package/ios/RNFBAppUnitTests/RNFBPreferencesStorageTests.swift +105 -0
  214. package/ios/RNFBAppUnitTests/RNFBPreferencesTests.m +110 -0
  215. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterCoreTests.swift +163 -0
  216. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterFacadeTests.m +141 -0
  217. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigFacadeTests.m +100 -0
  218. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigTests.swift +234 -0
  219. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppFacadeTests.m +145 -0
  220. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppTests.swift +173 -0
  221. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingFacadeTests.m +38 -0
  222. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingTests.swift +82 -0
  223. package/ios/RNFBAppUnitTests/RNFBSharedUtilsNullSentinelTests.m +35 -0
  224. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionFacadeTests.m +107 -0
  225. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionTests.swift +133 -0
  226. package/ios/RNFBAppUnitTests/RNFBUtilsHelpersTests.swift +144 -0
  227. package/ios/RNFBAppUnitTests/RNFBUtilsModuleFacadeTests.m +72 -0
  228. package/ios/RNFBAppUnitTests/RNFBUtilsModuleShellTests.mm +282 -0
  229. package/ios/RNFBFirebase/Package.swift +53 -0
  230. package/ios/RNFBFirebase/Sources/RNFBFirebase/RNFBFirebase.swift +285 -0
  231. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/Public/.gitkeep +0 -0
  232. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/RNFBFirebaseBridge.m +169 -0
  233. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/include/RNFBFirebaseBridge.h +52 -0
  234. package/ios/RNFBFirebaseUnitTests/RNFBAppDynamicFacadeTests.swift +240 -0
  235. package/{android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java → ios/RNFBFirebaseUnitTests/RNFBFirebaseClientImport.swift} +22 -17
  236. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/project.pbxproj +588 -0
  237. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBFirebaseUnitTests.xcscheme +83 -0
  238. package/ios_config.sh +50 -22
  239. package/lib/FirebaseApp.ts +10 -0
  240. package/lib/common/Base64.ts +10 -16
  241. package/lib/common/deeps.ts +3 -0
  242. package/lib/common/index.ts +20 -9
  243. package/lib/internal/FirebaseModule.ts +6 -3
  244. package/lib/internal/NativeModules.ts +4 -1
  245. package/lib/internal/RNFBNativeEventEmitter.ts +14 -5
  246. package/lib/internal/SharedEventEmitter.ts +5 -1
  247. package/lib/internal/asyncStorage.ts +7 -11
  248. package/lib/internal/index.ts +1 -0
  249. package/lib/internal/logger.ts +53 -43
  250. package/lib/internal/nativeModuleAndroidIos.ts +2 -40
  251. package/lib/internal/nativeModuleDebug.ts +97 -0
  252. package/lib/internal/nativeModuleWeb.ts +10 -40
  253. package/lib/internal/react-native-vendor-emitter.d.ts +11 -0
  254. package/lib/internal/registry/app.ts +8 -2
  255. package/lib/internal/registry/modular.ts +2 -2
  256. package/lib/internal/registry/nativeModule.ts +3 -3
  257. package/lib/internal/web/RNFBAppModule.ts +16 -15
  258. package/lib/internal/web/memidb/lib/FakeEventTarget.js +3 -1
  259. package/lib/types/app.ts +10 -3
  260. package/lib/types/internal.ts +19 -0
  261. package/lib/version.ts +1 -1
  262. package/package.json +9 -8
  263. package/plugin/build/ios/appDelegate.js +19 -9
  264. package/plugin/build/ios/podfile.js +16 -16
  265. package/plugin/build/pluginConfig.d.ts +4 -2
  266. package/plugin/src/ios/appDelegate.ts +45 -15
  267. package/plugin/src/ios/podfile.ts +20 -23
  268. package/plugin/src/pluginConfig.ts +4 -2
  269. package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +0 -124
  270. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +0 -62
  271. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +0 -91
  272. package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.java +0 -222
  273. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +0 -46
  274. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +0 -49
  275. package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +0 -191
  276. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +0 -53
  277. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +0 -606
  278. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +0 -107
  279. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +0 -101
  280. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +0 -146
  281. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +0 -96
  282. package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +0 -441
  283. package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.java +0 -223
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Copyright (c) 2016-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
+ import Foundation
18
+
19
+ /// Bridge-present check previously hard-wired to `self.bridge != nil`.
20
+ public typealias RNFBRCTEventEmitterBridgePresent = () -> Bool
21
+
22
+ /// Bridge emit previously hard-wired to `enqueueJSCall` (unprefixed event name + body).
23
+ public typealias RNFBRCTEventEmitterEmitHandler = (String, Any?) -> Void
24
+
25
+ /**
26
+ * Queue / listener state previously inline in `RNFBRCTEventEmitter.m`.
27
+ *
28
+ * Mirrors pre-port:
29
+ * - `isObserving` = `jsReady && jsListenerCount > 0`
30
+ * - emit when bridge present && observing && listener registered; else queue `{name,body}`
31
+ * - `notifyJsReady(true)` / `addListener` flush matching queued events via `sendEvent`
32
+ * - `@synchronized(jsListeners)` / `@synchronized(queuedEvents)` via `objc_sync_*`
33
+ */
34
+ @objc(RNFBRCTEventEmitterCore)
35
+ public final class RNFBRCTEventEmitterCore: NSObject {
36
+ @objc public static let eventNameKey = "name"
37
+ @objc public static let eventBodyKey = "body"
38
+
39
+ private var jsReady = false
40
+ private var jsListenerCount = 0
41
+ private var jsListeners = NSMutableDictionary()
42
+ private var queuedEvents = NSMutableArray()
43
+
44
+ private let isBridgePresent: RNFBRCTEventEmitterBridgePresent
45
+ private let emitHandler: RNFBRCTEventEmitterEmitHandler
46
+
47
+ @objc(initWithIsBridgePresent:emitHandler:)
48
+ public init(
49
+ isBridgePresent: @escaping RNFBRCTEventEmitterBridgePresent,
50
+ emitHandler: @escaping RNFBRCTEventEmitterEmitHandler
51
+ ) {
52
+ self.isBridgePresent = isBridgePresent
53
+ self.emitHandler = emitHandler
54
+ super.init()
55
+ }
56
+
57
+ @objc public func invalidate() {
58
+ jsReady = false
59
+ queuedEvents = NSMutableArray()
60
+ jsListeners = NSMutableDictionary()
61
+ jsListenerCount = 0
62
+ }
63
+
64
+ @objc(notifyJsReady:)
65
+ public func notifyJsReady(_ ready: Bool) {
66
+ objc_sync_enter(jsListeners)
67
+ defer { objc_sync_exit(jsListeners) }
68
+
69
+ jsReady = ready
70
+ if ready {
71
+ for case let event as NSDictionary in queuedEvents.copy() as! NSArray {
72
+ let name = event[Self.eventNameKey] as! String
73
+ let body = event[Self.eventBodyKey]
74
+ sendEvent(name: name, body: body)
75
+ objc_sync_enter(queuedEvents)
76
+ queuedEvents.remove(event)
77
+ objc_sync_exit(queuedEvents)
78
+ }
79
+ }
80
+ }
81
+
82
+ @objc(sendEventWithName:body:)
83
+ public func sendEvent(name eventName: String, body: Any?) {
84
+ objc_sync_enter(jsListeners)
85
+ defer { objc_sync_exit(jsListeners) }
86
+
87
+ if isBridgePresent(), isObserving, jsListeners[eventName] != nil {
88
+ emitHandler(eventName, body)
89
+ } else {
90
+ objc_sync_enter(queuedEvents)
91
+ let entry = NSMutableDictionary()
92
+ entry[Self.eventNameKey] = eventName
93
+ entry[Self.eventBodyKey] = body
94
+ queuedEvents.add(entry)
95
+ objc_sync_exit(queuedEvents)
96
+ }
97
+ }
98
+
99
+ @objc(addListener:)
100
+ public func addListener(_ eventName: String) {
101
+ objc_sync_enter(jsListeners)
102
+ defer { objc_sync_exit(jsListeners) }
103
+
104
+ jsListenerCount += 1
105
+
106
+ if jsListeners[eventName] == nil {
107
+ jsListeners[eventName] = NSNumber(value: 1)
108
+ } else {
109
+ let current = (jsListeners[eventName] as! NSNumber).intValue
110
+ jsListeners[eventName] = NSNumber(value: current + 1)
111
+ }
112
+
113
+ for case let event as NSDictionary in queuedEvents.copy() as! NSArray {
114
+ if (event[Self.eventNameKey] as? String) == eventName {
115
+ let body = event[Self.eventBodyKey]
116
+ sendEvent(name: eventName, body: body)
117
+ objc_sync_enter(queuedEvents)
118
+ queuedEvents.remove(event)
119
+ objc_sync_exit(queuedEvents)
120
+ }
121
+ }
122
+ }
123
+
124
+ @objc(removeListeners:all:)
125
+ public func removeListeners(_ eventName: String, all: Bool) {
126
+ objc_sync_enter(jsListeners)
127
+ defer { objc_sync_exit(jsListeners) }
128
+
129
+ if jsListeners[eventName] != nil {
130
+ let listenersForEvent = (jsListeners[eventName] as! NSNumber).intValue
131
+
132
+ if listenersForEvent <= 1 || all {
133
+ objc_sync_enter(jsListeners)
134
+ jsListeners.removeObject(forKey: eventName)
135
+ objc_sync_exit(jsListeners)
136
+ } else {
137
+ objc_sync_enter(jsListeners)
138
+ jsListeners[eventName] = NSNumber(value: listenersForEvent - 1)
139
+ objc_sync_exit(jsListeners)
140
+ }
141
+
142
+ if all {
143
+ jsListenerCount -= listenersForEvent
144
+ } else {
145
+ jsListenerCount -= 1
146
+ }
147
+ }
148
+ }
149
+
150
+ @objc public func getListenersDictionary() -> NSDictionary {
151
+ let listenersDictionary = NSMutableDictionary()
152
+ listenersDictionary["listeners"] = NSNumber(value: jsListenerCount)
153
+ listenersDictionary["queued"] = NSNumber(value: queuedEvents.count)
154
+ listenersDictionary["events"] = jsListeners.copy()
155
+ return listenersDictionary
156
+ }
157
+
158
+ private var isObserving: Bool {
159
+ jsReady && jsListenerCount > 0
160
+ }
161
+ }
@@ -18,13 +18,10 @@
18
18
  #ifndef RNFBSharedUtils_h
19
19
  #define RNFBSharedUtils_h
20
20
 
21
- #if __has_include(<FirebaseCore/FirebaseCore.h>)
22
- #import <FirebaseCore/FirebaseCore.h>
23
- #else
24
- @import FirebaseCore;
25
- #endif
26
21
  #import <React/RCTBridgeModule.h>
27
22
 
23
+ @class FIRApp;
24
+
28
25
  #ifdef DEBUG
29
26
  #define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
30
27
  #else
@@ -22,145 +22,154 @@
22
22
  #import "RNFBPreferences.h"
23
23
  #import "RNFBRCTEventEmitter.h"
24
24
 
25
+ #if __has_include(<RNFBApp/RNFBApp-Swift.h>)
26
+ #import <RNFBApp/RNFBApp-Swift.h>
27
+ #elif __has_include("RNFBApp-Swift.h")
28
+ #import "RNFBApp-Swift.h"
29
+ #elif __has_include("RNFBHandleMapStorage-Swift.inc")
30
+ #import "RNFBHandleMapStorage-Swift.inc"
31
+ #else
32
+ #error "RNFBApp Swift interface not found"
33
+ #endif
34
+
25
35
  #pragma mark -
26
36
  #pragma mark Constants
27
37
 
28
38
  NSString *const DEFAULT_APP_DISPLAY_NAME = @"[DEFAULT]";
29
39
  NSString *const DEFAULT_APP_NAME = @"__FIRAPP_DEFAULT";
30
40
 
41
+ /**
42
+ * Adapts `RNFBMeta` class methods to the instance-based config source protocol used by
43
+ * `RNFBSharedUtilsConfig`.
44
+ */
45
+ @interface RNFBConfigMetaSource : NSObject <RNFBConfigBooleanProviding>
46
+ @end
47
+
48
+ @implementation RNFBConfigMetaSource
49
+
50
+ - (BOOL)contains:(NSString *)key {
51
+ return [RNFBMeta contains:key];
52
+ }
53
+
54
+ - (BOOL)getBooleanValue:(NSString *)key defaultValue:(BOOL)defaultValue {
55
+ return [RNFBMeta getBooleanValue:key defaultValue:defaultValue];
56
+ }
57
+
58
+ @end
59
+
60
+ static id<RNFBConfigBooleanProviding> RNFBSharedUtilsMetaConfigSource(void) {
61
+ static RNFBConfigMetaSource *sharedSource;
62
+ static dispatch_once_t onceToken;
63
+ dispatch_once(&onceToken, ^{
64
+ sharedSource = [[RNFBConfigMetaSource alloc] init];
65
+ });
66
+ return sharedSource;
67
+ }
68
+
69
+ /**
70
+ * Adapts `RNFBAppModule getCustomDomain:` for `RNFBSharedUtilsFIRApp`.
71
+ */
72
+ @interface RNFBCustomDomainProvider : NSObject <RNFBCustomDomainProviding>
73
+ @end
74
+
75
+ @implementation RNFBCustomDomainProvider
76
+
77
+ - (NSString *)getCustomDomain:(NSString *)appName {
78
+ return [RNFBAppModule getCustomDomain:appName];
79
+ }
80
+
81
+ @end
82
+
83
+ /**
84
+ * Adapts `RNFBRCTEventEmitter.shared` for `RNFBSharedUtilsFIRApp`.
85
+ */
86
+ @interface RNFBJSEventSender : NSObject <RNFBJSEventSending>
87
+ @end
88
+
89
+ @implementation RNFBJSEventSender
90
+
91
+ - (void)sendEventWithName:(NSString *)name body:(id)body {
92
+ [[RNFBRCTEventEmitter shared] sendEventWithName:name body:body];
93
+ }
94
+
95
+ @end
96
+
97
+ static id<RNFBCustomDomainProviding> RNFBSharedUtilsCustomDomainProvider(void) {
98
+ static RNFBCustomDomainProvider *sharedProvider;
99
+ static dispatch_once_t onceToken;
100
+ dispatch_once(&onceToken, ^{
101
+ sharedProvider = [[RNFBCustomDomainProvider alloc] init];
102
+ });
103
+ return sharedProvider;
104
+ }
105
+
106
+ static id<RNFBJSEventSending> RNFBSharedUtilsJSEventSender(void) {
107
+ static RNFBJSEventSender *sharedSender;
108
+ static dispatch_once_t onceToken;
109
+ dispatch_once(&onceToken, ^{
110
+ sharedSender = [[RNFBJSEventSender alloc] init];
111
+ });
112
+ return sharedSender;
113
+ }
114
+
31
115
  @implementation RNFBSharedUtils
32
- static NSString *const RNFBErrorDomain = @"RNFBErrorDomain";
33
116
 
34
117
  #pragma mark -
35
118
  #pragma mark Methods
36
119
 
37
120
  + (NSString *)getAppJavaScriptName:(NSString *)appDisplayName {
38
- if ([appDisplayName isEqualToString:DEFAULT_APP_NAME]) {
39
- return DEFAULT_APP_DISPLAY_NAME;
40
- }
41
- return appDisplayName;
121
+ return [RNFBSharedUtilsFormatting getAppJavaScriptName:appDisplayName];
42
122
  }
43
123
 
44
124
  + (NSDictionary *)firAppToDictionary:(FIRApp *)firApp {
45
- FIROptions *firOptions = [firApp options];
46
- NSMutableDictionary *firAppDictionary = [NSMutableDictionary new];
47
- NSMutableDictionary *firAppOptions = [NSMutableDictionary new];
48
- NSMutableDictionary *firAppConfig = [NSMutableDictionary new];
49
-
50
- NSString *name = [firApp name];
51
- if ([name isEqualToString:DEFAULT_APP_NAME]) {
52
- name = DEFAULT_APP_DISPLAY_NAME;
53
- }
54
-
55
- firAppConfig[@"name"] = name;
56
- firAppConfig[@"automaticDataCollectionEnabled"] = @([firApp isDataCollectionDefaultEnabled]);
57
-
58
- firAppOptions[@"apiKey"] = firOptions.APIKey;
59
- firAppOptions[@"appId"] = firOptions.googleAppID;
60
- firAppOptions[@"projectId"] = firOptions.projectID;
61
- firAppOptions[@"databaseURL"] = firOptions.databaseURL;
62
- firAppOptions[@"storageBucket"] = firOptions.storageBucket;
63
- firAppOptions[@"messagingSenderId"] = firOptions.GCMSenderID;
64
- // missing from android sdk - ios only:
65
- firAppOptions[@"clientId"] = firOptions.clientID;
66
- // not in FIROptions API but in JS SDK and project config JSON
67
- if ([RNFBAppModule getCustomDomain:name] != nil) {
68
- firAppOptions[@"authDomain"] = [RNFBAppModule getCustomDomain:name];
69
- }
70
-
71
- firAppDictionary[@"options"] = firAppOptions;
72
- firAppDictionary[@"appConfig"] = firAppConfig;
73
-
74
- return firAppDictionary;
125
+ return [RNFBSharedUtilsFIRApp firAppToDictionaryFromFIRApp:firApp
126
+ customDomainProvider:RNFBSharedUtilsCustomDomainProvider()];
75
127
  }
76
128
 
77
129
  + (void)rejectPromiseWithExceptionDict:(RCTPromiseRejectBlock)reject
78
130
  exception:(NSException *)exception {
79
- NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
80
-
81
- [userInfo setValue:@(YES) forKey:@"fatal"];
82
- [userInfo setValue:@"unknown" forKey:@"code"];
83
- [userInfo setValue:exception.reason forKey:@"message"];
84
- [userInfo setValue:exception.name forKey:@"nativeErrorCode"];
85
- [userInfo setValue:exception.reason forKey:@"nativeErrorMessage"];
86
-
87
- NSError *error = [NSError errorWithDomain:RNFBErrorDomain code:666 userInfo:userInfo];
88
-
89
- reject(exception.name, exception.reason, error);
131
+ [RNFBSharedUtilsPromiseRejection rejectPromiseWithException:reject exception:exception];
90
132
  }
91
133
 
92
134
  + (void)rejectPromiseWithNSError:(RCTPromiseRejectBlock)reject error:(NSError *)error {
93
- NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
94
-
95
- [userInfo setValue:@(NO) forKey:@"fatal"];
96
- [userInfo setValue:@"unknown" forKey:@"code"];
97
- [userInfo setValue:error.localizedDescription forKey:@"message"];
98
- [userInfo setValue:@(error.code) forKey:@"nativeErrorCode"];
99
- [userInfo setValue:error.localizedDescription forKey:@"nativeErrorMessage"];
100
-
101
- NSError *newErrorWithUserInfo = [NSError errorWithDomain:RNFBErrorDomain
102
- code:666
103
- userInfo:userInfo];
104
- reject(@"unknown", error.localizedDescription, newErrorWithUserInfo);
135
+ [RNFBSharedUtilsPromiseRejection rejectPromiseWithNSError:reject error:error];
105
136
  }
106
137
 
107
138
  + (void)rejectPromiseWithUserInfo:(RCTPromiseRejectBlock)reject
108
139
  userInfo:(NSMutableDictionary *)userInfo {
109
- NSError *error = [NSError errorWithDomain:RNFBErrorDomain code:666 userInfo:userInfo];
110
- reject(userInfo[@"code"], userInfo[@"message"], error);
140
+ [RNFBSharedUtilsPromiseRejection rejectPromiseWithUserInfo:reject userInfo:userInfo];
111
141
  }
112
142
 
113
143
  // for easier v5 migration
114
144
  + (void)sendJSEventForApp:(FIRApp *)app name:(NSString *)name body:(NSDictionary *)body {
115
- NSMutableDictionary *newBody = [body mutableCopy];
116
- newBody[@"appName"] = [self getAppJavaScriptName:app.name];
117
- [[RNFBRCTEventEmitter shared] sendEventWithName:name body:newBody];
145
+ [RNFBSharedUtilsFIRApp sendJSEventForFIRApp:app
146
+ name:name
147
+ body:body
148
+ eventSender:RNFBSharedUtilsJSEventSender()];
118
149
  }
119
150
 
120
151
  + (NSString *)getISO8601String:(NSDate *)date {
121
- static NSDateFormatter *formatter = nil;
122
-
123
- if (!formatter) {
124
- formatter = [[NSDateFormatter alloc] init];
125
- [formatter setLocale:[NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]];
126
- formatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"UTC"];
127
- [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
128
- }
129
-
130
- NSString *iso8601String = [formatter stringFromDate:date];
131
-
132
- return [iso8601String stringByAppendingString:@"Z"];
152
+ return [RNFBSharedUtilsFormatting getISO8601String:date];
133
153
  }
134
154
 
135
155
  + (BOOL)configContains:(NSString *)key {
136
- return [[RNFBPreferences shared] contains:key] || [[RNFBJSON shared] contains:key] ||
137
- [RNFBMeta contains:key];
156
+ return [RNFBSharedUtilsConfig
157
+ configContainsKey:key
158
+ preferences:(id<RNFBConfigBooleanProviding>)[RNFBPreferences shared]
159
+ json:(id<RNFBConfigBooleanProviding>)[RNFBJSON shared]
160
+ meta:RNFBSharedUtilsMetaConfigSource()];
138
161
  }
139
162
 
140
163
  + (BOOL)getConfigBooleanValue:(NSString *)tag key:(NSString *)key defaultValue:(BOOL)defaultValue {
141
- BOOL enabled;
142
-
143
- if ([[RNFBPreferences shared] contains:key]) {
144
- enabled = [[RNFBPreferences shared] getBooleanValue:key defaultValue:defaultValue];
145
- DLog(@"%@ %@ via "
146
- @"RNFBPreferences: %d",
147
- tag, key, enabled);
148
- } else if ([[RNFBJSON shared] contains:key]) {
149
- enabled = [[RNFBJSON shared] getBooleanValue:key defaultValue:defaultValue];
150
- DLog(@"%@ %@ via "
151
- @"RNFBJSON: %d",
152
- tag, key, enabled);
153
- } else {
154
- // Note that if we're here, and the key is not set on the app's bundle, our final default is the
155
- // one passed in
156
- enabled = [RNFBMeta getBooleanValue:key defaultValue:defaultValue];
157
- DLog(@"%@ %@ via "
158
- @"RNFBMeta: %d",
159
- tag, key, enabled);
160
- }
161
-
164
+ BOOL enabled = [RNFBSharedUtilsConfig
165
+ getConfigBooleanValueForKey:key
166
+ defaultValue:defaultValue
167
+ preferences:(id<RNFBConfigBooleanProviding>)[RNFBPreferences shared]
168
+ json:(id<RNFBConfigBooleanProviding>)[RNFBJSON shared]
169
+ meta:RNFBSharedUtilsMetaConfigSource()];
170
+ // Branch-specific "via Preferences/JSON/Meta" DLogs lived in the pre-port body; keep the
171
+ // final-value log on the ObjC façade (DLog is an ObjC macro; return value unchanged).
162
172
  DLog(@"%@ %@ final value: %d", tag, key, enabled);
163
-
164
173
  return enabled;
165
174
  }
166
175
 
@@ -182,104 +191,7 @@ static NSString *const RNFBErrorDomain = @"RNFBErrorDomain";
182
191
  * @return The decoded value with sentinels replaced by NSNull
183
192
  */
184
193
  + (id)decodeNullSentinels:(id)value {
185
- // Non-container values are returned as-is
186
- if (![value isKindOfClass:[NSDictionary class]] && ![value isKindOfClass:[NSArray class]]) {
187
- return value;
188
- }
189
-
190
- // Helper to detect the sentinel
191
- BOOL (^isNullSentinel)(NSDictionary *) = ^BOOL(NSDictionary *dict) {
192
- id flag = dict[@"__rnfbNull"];
193
- return (dict.count == 1 && flag != nil && [flag boolValue]);
194
- };
195
-
196
- // Helper to process a child element and add it to the parent container
197
- void (^processChild)(id, id, id, BOOL, NSMutableArray *) =
198
- ^void(id child, id parentMutable, id keyOrNil, BOOL isParentDict, NSMutableArray *stack) {
199
- id processedValue = nil;
200
-
201
- if ([child isKindOfClass:[NSDictionary class]]) {
202
- NSDictionary *childDict = (NSDictionary *)child;
203
-
204
- if (isNullSentinel(childDict)) {
205
- // Replace sentinel with NSNull
206
- processedValue = [NSNull null];
207
- } else {
208
- // Process nested dictionary
209
- NSMutableDictionary *childMut =
210
- [NSMutableDictionary dictionaryWithCapacity:childDict.count];
211
- processedValue = childMut;
212
- [stack addObject:@{@"original" : childDict, @"mutable" : childMut}];
213
- }
214
- } else if ([child isKindOfClass:[NSArray class]]) {
215
- // Process nested array
216
- NSArray *childArray = (NSArray *)child;
217
- NSMutableArray *childMut = [NSMutableArray arrayWithCapacity:childArray.count];
218
- processedValue = childMut;
219
- [stack addObject:@{@"original" : childArray, @"mutable" : childMut}];
220
- } else {
221
- // Preserve primitive values
222
- processedValue = child ?: [NSNull null];
223
- }
224
-
225
- // Add to parent container based on type
226
- if (isParentDict) {
227
- NSMutableDictionary *mutDict = (NSMutableDictionary *)parentMutable;
228
- if (processedValue) {
229
- mutDict[keyOrNil] = processedValue;
230
- }
231
- // NSDictionary can't store nil, and original code wouldn't see nil values either.
232
- } else {
233
- NSMutableArray *mutArray = (NSMutableArray *)parentMutable;
234
- [mutArray addObject:processedValue];
235
- }
236
- };
237
-
238
- // Root-level sentinel case
239
- if ([value isKindOfClass:[NSDictionary class]] && isNullSentinel((NSDictionary *)value)) {
240
- return [NSNull null];
241
- }
242
-
243
- id rootOriginal = value;
244
- id rootMutable = nil;
245
-
246
- if ([value isKindOfClass:[NSDictionary class]]) {
247
- NSDictionary *dict = (NSDictionary *)value;
248
- rootMutable = [NSMutableDictionary dictionaryWithCapacity:dict.count];
249
- } else {
250
- NSArray *array = (NSArray *)value;
251
- rootMutable = [NSMutableArray arrayWithCapacity:array.count];
252
- }
253
-
254
- // Stack-based iteration to process nested structures without recursion
255
- // Stack frames: { @"original": container, @"mutable": mutableContainer }
256
- NSMutableArray<NSDictionary *> *stack = [NSMutableArray array];
257
- [stack addObject:@{@"original" : rootOriginal, @"mutable" : rootMutable}];
258
-
259
- while (stack.count > 0) {
260
- NSDictionary *frame = [stack lastObject];
261
- [stack removeLastObject];
262
-
263
- id original = frame[@"original"];
264
- id mutable = frame[@"mutable"];
265
-
266
- if ([original isKindOfClass:[NSDictionary class]]) {
267
- NSDictionary *origDict = (NSDictionary *)original;
268
-
269
- for (id key in origDict) {
270
- id child = origDict[key];
271
- processChild(child, mutable, key, YES, stack);
272
- }
273
- } else if ([original isKindOfClass:[NSArray class]]) {
274
- NSArray *origArray = (NSArray *)original;
275
-
276
- for (id child in origArray) {
277
- processChild(child, mutable, nil, NO, stack);
278
- }
279
- }
280
- }
281
-
282
- return rootMutable;
194
+ return [RNFBNullSentinelDecoder decodeNullSentinels:value];
283
195
  }
284
196
 
285
197
  @end
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Copyright (c) 2016-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
+ import Foundation
18
+
19
+ /**
20
+ * Boolean config source used by the SharedUtils config waterfall.
21
+ *
22
+ * Production passes `RNFBPreferences` / `RNFBJSON` instances and a Meta adapter;
23
+ * unit tests inject recording stubs to assert precedence and `||` short-circuit.
24
+ */
25
+ @objc public protocol RNFBConfigBooleanProviding: AnyObject {
26
+ @objc(contains:)
27
+ func contains(_ key: String) -> Bool
28
+
29
+ @objc(getBooleanValue:defaultValue:)
30
+ func getBooleanValue(_ key: String, defaultValue: Bool) -> Bool
31
+ }
32
+
33
+ /**
34
+ * Config waterfall previously inline in `RNFBSharedUtils.m`.
35
+ *
36
+ * Mirrors pre-port:
37
+ * - `configContains` is Preferences.contains || JSON.contains || Meta.contains
38
+ * (left-to-right short-circuit, same as ObjC `||`)
39
+ * - `getConfigBooleanValue` prefers Preferences if contains, else JSON if contains,
40
+ * else Meta (Meta path always used as final, with the passed-in `defaultValue`)
41
+ */
42
+ @objc(RNFBSharedUtilsConfig)
43
+ public final class RNFBSharedUtilsConfig: NSObject {
44
+ @objc(configContainsKey:preferences:json:meta:)
45
+ public static func configContains(
46
+ _ key: String,
47
+ preferences: RNFBConfigBooleanProviding,
48
+ json: RNFBConfigBooleanProviding,
49
+ meta: RNFBConfigBooleanProviding
50
+ ) -> Bool {
51
+ preferences.contains(key) || json.contains(key) || meta.contains(key)
52
+ }
53
+
54
+ @objc(getConfigBooleanValueForKey:defaultValue:preferences:json:meta:)
55
+ public static func getConfigBooleanValue(
56
+ forKey key: String,
57
+ defaultValue: Bool,
58
+ preferences: RNFBConfigBooleanProviding,
59
+ json: RNFBConfigBooleanProviding,
60
+ meta: RNFBConfigBooleanProviding
61
+ ) -> Bool {
62
+ if preferences.contains(key) {
63
+ return preferences.getBooleanValue(key, defaultValue: defaultValue)
64
+ }
65
+ if json.contains(key) {
66
+ return json.getBooleanValue(key, defaultValue: defaultValue)
67
+ }
68
+ // Note that if we're here, and the key is not set on the app's bundle, our final
69
+ // default is the one passed in (pre-port Meta path behaviour).
70
+ return meta.getBooleanValue(key, defaultValue: defaultValue)
71
+ }
72
+ }