@react-native-firebase/app 26.4.0 → 27.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 +62 -0
- package/README.md +10 -27
- package/RNFBApp.podspec +13 -5
- package/android/build.gradle +3 -0
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.kt +29 -0
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.kt +146 -0
- package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.kt +156 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.kt +44 -0
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.kt +100 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.kt +250 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.kt +64 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppInitProvider.java → ReactNativeFirebaseAppInitProvider.kt} +3 -4
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.kt +47 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.kt +33 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +1 -1
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.kt +185 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.kt +35 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.kt +662 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.kt +103 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.kt +96 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.kt +140 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.kt +109 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.kt +451 -0
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{ContextProvider.java → ContextProvider.kt} +8 -8
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeError.java → NativeError.kt} +8 -8
- package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeEvent.java → NativeEvent.kt} +6 -6
- package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.kt +219 -0
- package/android/src/test/java/expo/core/ModuleRegistry.java +9 -0
- package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +182 -59
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppComponentsJavaCompatibilityTest.java +70 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppJavaCompatibilityTest.java +60 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackageTest.java +165 -0
- package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppTest.kt +167 -0
- package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseJavaCompatibilityTest.java +112 -0
- package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseTest.kt +317 -0
- package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.kt +309 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterJavaCompatibilityTest.java +176 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +143 -12
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventTest.kt +61 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONJavaCompatibilityTest.java +85 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.kt +296 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaJavaCompatibilityTest.java +67 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaTest.kt +246 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseModuleTest.kt +254 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesJavaCompatibilityTest.java +87 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesTest.kt +260 -0
- package/android/src/test/java/io/invertase/firebase/common/SharedUtilsJavaCompatibilityTest.java +255 -0
- package/android/src/test/java/io/invertase/firebase/common/SharedUtilsTest.kt +674 -0
- package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.kt +290 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebaseModuleJavaCompatibilityTest.java +178 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesJavaCompatibilityTest.java +99 -0
- package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesTest.kt +217 -0
- package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleJavaCompatibilityTest.java +176 -0
- package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleKotlinCompatibilityTest.kt +52 -0
- package/android/src/test/java/io/invertase/firebase/interfaces/InterfacesJavaCompatibilityTest.java +144 -0
- package/android/src/test/java/io/invertase/firebase/interfaces/NativeEventTest.kt +56 -0
- package/android/src/test/java/io/invertase/firebase/utils/NativeRNFBTurboUtilsTest.java +517 -21
- package/dist/module/FirebaseApp.js +10 -0
- package/dist/module/FirebaseApp.js.map +1 -1
- package/dist/module/common/deeps.js +3 -0
- package/dist/module/common/deeps.js.map +1 -1
- package/dist/module/internal/FirebaseModule.js.map +1 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js +12 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
- package/dist/module/internal/SharedEventEmitter.js +3 -1
- package/dist/module/internal/SharedEventEmitter.js.map +1 -1
- package/dist/module/internal/index.js +1 -0
- package/dist/module/internal/index.js.map +1 -1
- package/dist/module/internal/registry/app.js +7 -1
- package/dist/module/internal/registry/app.js.map +1 -1
- package/dist/module/types/app.js.map +1 -1
- package/dist/module/types/internal.js +2 -0
- package/dist/module/version.js +1 -1
- package/dist/typescript/lib/FirebaseApp.d.ts +7 -0
- package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
- package/dist/typescript/lib/common/deeps.d.ts.map +1 -1
- package/dist/typescript/lib/internal/FirebaseModule.d.ts +2 -3
- package/dist/typescript/lib/internal/FirebaseModule.d.ts.map +1 -1
- package/dist/typescript/lib/internal/NativeModules.d.ts +4 -1
- package/dist/typescript/lib/internal/NativeModules.d.ts.map +1 -1
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts +2 -2
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/SharedEventEmitter.d.ts +3 -3
- package/dist/typescript/lib/internal/SharedEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/index.d.ts +1 -0
- package/dist/typescript/lib/internal/index.d.ts.map +1 -1
- package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/app.d.ts +10 -3
- package/dist/typescript/lib/types/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/internal.d.ts +12 -0
- package/dist/typescript/lib/types/internal.d.ts.map +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/firebase-schema.json +4 -0
- package/firebase_spm.rb +552 -96
- package/ios/RNFBApp/RCTConvert+FIRApp.h +2 -5
- package/ios/RNFBApp/RCTConvert+FIRApp.m +11 -6
- package/ios/RNFBApp/RCTConvert+FIROptions.h +2 -5
- package/ios/RNFBApp/RCTConvert+FIROptions.m +11 -10
- package/ios/RNFBApp/RCTConvertFIRApp.swift +86 -0
- package/ios/RNFBApp/RCTConvertFIROptions.swift +259 -0
- package/ios/RNFBApp/RNFBAppCustomAuthDomains.swift +63 -0
- package/ios/RNFBApp/RNFBAppInitializeOptionsMapper.swift +113 -0
- package/ios/RNFBApp/RNFBAppLogLevelMapper.swift +53 -0
- package/ios/RNFBApp/RNFBAppModule+CustomAuthDomain.m +35 -0
- package/ios/RNFBApp/RNFBAppModule.h +6 -2
- package/ios/RNFBApp/RNFBAppModule.mm +65 -228
- package/ios/RNFBApp/RNFBAppModuleFirebase.swift +439 -0
- package/ios/RNFBApp/RNFBAppModuleImplementation.h +68 -0
- package/ios/RNFBApp/RNFBAppModuleImplementation.m +195 -0
- package/ios/RNFBApp/RNFBHandleMap.m +27 -56
- package/ios/RNFBApp/RNFBHandleMapStorage.swift +90 -0
- package/ios/RNFBApp/RNFBInitializeAppArguments.swift +82 -0
- package/ios/RNFBApp/RNFBJSON.m +22 -38
- package/ios/RNFBApp/RNFBJSONImplementation.swift +71 -0
- package/ios/RNFBApp/RNFBMeta.m +24 -26
- package/ios/RNFBApp/RNFBMetaStorage.swift +76 -0
- package/ios/RNFBApp/RNFBNullSentinelDecoding.swift +135 -0
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +30 -3
- package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +28 -5
- package/ios/RNFBApp/RNFBPreferences.m +22 -20
- package/ios/RNFBApp/RNFBPreferencesStorage.swift +101 -0
- package/ios/RNFBApp/RNFBRCTEventEmitter.m +36 -93
- package/ios/RNFBApp/RNFBRCTEventEmitterCore.swift +161 -0
- package/ios/RNFBApp/RNFBSharedUtils.h +2 -5
- package/ios/RNFBApp/RNFBSharedUtils.m +109 -198
- package/ios/RNFBApp/RNFBSharedUtilsConfig.swift +72 -0
- package/ios/RNFBApp/RNFBSharedUtilsFIRApp.swift +271 -0
- package/ios/RNFBApp/RNFBSharedUtilsFormatting.swift +59 -0
- package/ios/RNFBApp/RNFBSharedUtilsPromiseRejection.swift +88 -0
- package/ios/RNFBApp/RNFBUtilsHelpers.swift +116 -0
- package/ios/RNFBApp/RNFBUtilsModule+Foundation.m +44 -0
- package/ios/RNFBApp/RNFBUtilsModule+PhotoAssets.m +47 -0
- package/ios/RNFBApp/RNFBUtilsModule.h +11 -1
- package/ios/RNFBApp/RNFBUtilsModule.mm +10 -85
- package/ios/RNFBApp/RNFBUtilsModuleImplementation.h +32 -0
- package/ios/RNFBApp/RNFBUtilsModuleImplementation.m +56 -0
- package/ios/RNFBApp/RNFBVersion.m +1 -1
- package/ios/RNFBApp.xcodeproj/project.pbxproj +100 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FIRApp.m +171 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FirebaseCore.h +78 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FIRInstallations.m +7 -0
- package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FirebaseInstallations.h +8 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppModuleHostStub.m +55 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.h +89 -0
- package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.mm +30 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.h +19 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.m +32 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridgeModule.h +19 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.h +28 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.m +23 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTEventEmitter.h +9 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTInvalidating.h +24 -0
- package/ios/RNFBAppUnitTests/HostStubs/React/RCTUtils.h +9 -0
- package/ios/RNFBAppUnitTests/HostStubs/module.modulemap +13 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIRAppFacadeTests.m +61 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIRAppTests.swift +73 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIROptionsFacadeTests.m +57 -0
- package/ios/RNFBAppUnitTests/RCTConvertFIROptionsTests.swift +243 -0
- package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsFacadeTests.m +73 -0
- package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsTests.swift +70 -0
- package/ios/RNFBAppUnitTests/RNFBAppInitializeOptionsMapperTests.swift +190 -0
- package/ios/RNFBAppUnitTests/RNFBAppLogLevelFacadeTests.m +76 -0
- package/ios/RNFBAppUnitTests/RNFBAppLogLevelMapperTests.swift +59 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseFacadeTests.m +215 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseTests.swift +430 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleLifecycleTests.m +206 -0
- package/ios/RNFBAppUnitTests/RNFBAppModuleShellTests.mm +367 -0
- package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/project.pbxproj +355 -2
- package/ios/RNFBAppUnitTests/RNFBFirebaseAppClientTests.swift +165 -0
- package/ios/RNFBAppUnitTests/RNFBHandleMapStorageTests.swift +121 -0
- package/ios/RNFBAppUnitTests/RNFBInitializeAppArgumentsTests.swift +256 -0
- package/ios/RNFBAppUnitTests/RNFBJSONImplementationTests.swift +126 -0
- package/ios/RNFBAppUnitTests/RNFBJSONTests.m +172 -0
- package/ios/RNFBAppUnitTests/RNFBMetaStorageTests.swift +106 -0
- package/ios/RNFBAppUnitTests/RNFBMetaTests.m +65 -0
- package/ios/RNFBAppUnitTests/RNFBNullSentinelDecodingTests.swift +286 -0
- package/ios/RNFBAppUnitTests/RNFBNullSentinelInterceptorTests.m +312 -0
- package/ios/RNFBAppUnitTests/RNFBPreferencesStorageTests.swift +105 -0
- package/ios/RNFBAppUnitTests/RNFBPreferencesTests.m +110 -0
- package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterCoreTests.swift +163 -0
- package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterFacadeTests.m +141 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigFacadeTests.m +100 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigTests.swift +234 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppFacadeTests.m +145 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppTests.swift +173 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingFacadeTests.m +38 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingTests.swift +82 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsNullSentinelTests.m +35 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionFacadeTests.m +107 -0
- package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionTests.swift +133 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsHelpersTests.swift +144 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsModuleFacadeTests.m +72 -0
- package/ios/RNFBAppUnitTests/RNFBUtilsModuleShellTests.mm +282 -0
- package/ios/RNFBFirebase/Package.swift +53 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebase/RNFBFirebase.swift +285 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/Public/.gitkeep +0 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/RNFBFirebaseBridge.m +169 -0
- package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/include/RNFBFirebaseBridge.h +52 -0
- package/ios/RNFBFirebaseUnitTests/RNFBAppDynamicFacadeTests.swift +240 -0
- package/{android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.java → ios/RNFBFirebaseUnitTests/RNFBFirebaseClientImport.swift} +23 -14
- package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/project.pbxproj +588 -0
- package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBFirebaseUnitTests.xcscheme +83 -0
- package/ios_config.sh +50 -22
- package/lib/FirebaseApp.ts +10 -0
- package/lib/common/deeps.ts +3 -0
- package/lib/internal/FirebaseModule.ts +6 -3
- package/lib/internal/NativeModules.ts +4 -1
- package/lib/internal/RNFBNativeEventEmitter.ts +14 -5
- package/lib/internal/SharedEventEmitter.ts +5 -1
- package/lib/internal/index.ts +1 -0
- package/lib/internal/react-native-vendor-emitter.d.ts +11 -0
- package/lib/internal/registry/app.ts +7 -1
- package/lib/types/app.ts +10 -3
- package/lib/types/internal.ts +19 -0
- package/lib/version.ts +1 -1
- package/package.json +8 -8
- package/plugin/build/ios/appDelegate.js +2 -2
- package/plugin/build/ios/podfile.js +16 -16
- package/plugin/build/pluginConfig.d.ts +4 -2
- package/plugin/src/ios/appDelegate.ts +2 -2
- package/plugin/src/ios/podfile.ts +20 -23
- package/plugin/src/pluginConfig.ts +4 -2
- package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.java +0 -150
- package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +0 -148
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +0 -62
- package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +0 -91
- package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.java +0 -224
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +0 -46
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +0 -49
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java +0 -35
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +0 -192
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +0 -53
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +0 -606
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +0 -109
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +0 -101
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +0 -146
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +0 -96
- package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +0 -441
- package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.java +0 -223
- package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.java +0 -275
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.java +0 -108
- package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.java +0 -97
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,68 @@
|
|
|
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
|
+
## [27.1.0](https://github.com/invertase/react-native-firebase/compare/v27.0.0...v27.1.0) (2026-10-23)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **app, sdk:** bump Firebase Android SDK to 35.0.2 ([da2d14e](https://github.com/invertase/react-native-firebase/commit/da2d14e6bfdf3e4388198a7184b4ff166afd1cb0))
|
|
11
|
+
- **app, sdk:** bump Firebase iOS SDK to 13.1.0 ([4a1ceaf](https://github.com/invertase/react-native-firebase/commit/4a1ceafa6f914b712aeef5350142abd95597dde6))
|
|
12
|
+
- **app, sdk:** bump Firebase JS SDK to 13.1.0 ([1d28f07](https://github.com/invertase/react-native-firebase/commit/1d28f076722ca7566a450a5bc1c7a3415ca2f7d0))
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
- **app, sdk:** bump Firebase iOS SDK to 13.1.1 ([4505c11](https://github.com/invertase/react-native-firebase/commit/4505c1172d731e3a73f8d47cb977c8bc2e6b0f60))
|
|
17
|
+
- **app, sdk:** sync RNFBFirebase Package.swift pin to 13.1.0 ([dc83824](https://github.com/invertase/react-native-firebase/commit/dc8382425d1a2957db83d0b721a365f97a3f8fb8))
|
|
18
|
+
- **test:** cold-boot Android emulator on ANR and missing package/activity services ([b02ef7f](https://github.com/invertase/react-native-firebase/commit/b02ef7f9d85fc2adcd6b9a19150aebb24040df8d))
|
|
19
|
+
|
|
20
|
+
## [27.0.0](https://github.com/invertase/react-native-firebase/compare/v26.4.0...v27.0.0) (2026-10-19)
|
|
21
|
+
|
|
22
|
+
### ⚠ BREAKING CHANGES
|
|
23
|
+
|
|
24
|
+
- **ios:** drop CocoaPods Firebase matrix; SPM-only
|
|
25
|
+
- **app, sdk:** bump Firebase Android 35, Apple 13, and JS 13
|
|
26
|
+
- **ml:** remove discontinued @react-native-firebase/ml package
|
|
27
|
+
- **app, ios:** initializeApp now reads automaticDataCollectionEnabled as a
|
|
28
|
+
boolean. Previously any non-nil value (including JS false) enabled collection
|
|
29
|
+
via pointer cast; false, 0, null, and absent now disable it. See
|
|
30
|
+
docs/migrating-to-v27.mdx.
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
- **app, sdk:** bump Firebase Android 35, Apple 13, and JS 13 ([0ca03d1](https://github.com/invertase/react-native-firebase/commit/0ca03d11b0c271fb37cfbee8a0c3074a21969f0b))
|
|
35
|
+
- **app, sdk:** bump Firebase Android SDK to 34.19.0 ([ca054bc](https://github.com/invertase/react-native-firebase/commit/ca054bc2fdcb298575f1e7412aa8b02540d53def))
|
|
36
|
+
- **app, sdk:** bump Firebase iOS SDK to 12.19.0 ([95dca6a](https://github.com/invertase/react-native-firebase/commit/95dca6a4eeb849bc2910946e1477694635bee6b7))
|
|
37
|
+
- **app, sdk:** bump Firebase JS SDK to 12.18.0 ([5e2617d](https://github.com/invertase/react-native-firebase/commit/5e2617dcddfd55f10f441f2e9d83fe7b4681470e))
|
|
38
|
+
- **app, sdk:** bump Firebase JS SDK to 12.19.0 ([34d0318](https://github.com/invertase/react-native-firebase/commit/34d031849146527ab9b9ee3ba4fbd207bdab0803))
|
|
39
|
+
- **messaging:** add messaging_installation_id_enabled firebase.json opt-in ([e9c9741](https://github.com/invertase/react-native-firebase/commit/e9c9741a65a76cc102d2d27ff675c453fd506243))
|
|
40
|
+
- **ml:** remove discontinued @react-native-firebase/ml package ([58622b1](https://github.com/invertase/react-native-firebase/commit/58622b1a24a32008fd33ff56346cceb4f71bc29f))
|
|
41
|
+
|
|
42
|
+
### Bug Fixes
|
|
43
|
+
|
|
44
|
+
- **app, android:** bind nullable recent-task fields before use ([bed8c71](https://github.com/invertase/react-native-firebase/commit/bed8c71313cd3c0bf60bf9a9d86417ae550ec98f))
|
|
45
|
+
- **app, android:** harden RecentTaskInfo null and JSON parse ([908400b](https://github.com/invertase/react-native-firebase/commit/908400b230cfd5d7d4406da9bb350332d6bc8c4c))
|
|
46
|
+
- **app, expo:** match scene-based AppDelegate for Expo SDK 58 config plugin ([dce165d](https://github.com/invertase/react-native-firebase/commit/dce165d7283a30060c5b08066cf5841d9247105a))
|
|
47
|
+
- **app, ios:** clarify SPM static linkage error when use_frameworks is absent ([cdf99cd](https://github.com/invertase/react-native-firebase/commit/cdf99cde79d46be737b671096e1cc3af7a14f58f))
|
|
48
|
+
- **app, ios:** import ObjC NullSentinelDecoder in SharedUtils ([9a565c8](https://github.com/invertase/react-native-firebase/commit/9a565c879edc11c18b5c7ffca92c7f22e2b639e7))
|
|
49
|
+
- **app, ios:** pin SPM Firebase SDK and retain Measurement ObjC categories ([7e271af](https://github.com/invertase/react-native-firebase/commit/7e271afecab65ef150140056171265e9c9ca621c))
|
|
50
|
+
- **app, ios:** read automaticDataCollectionEnabled as a boolean ([cc18140](https://github.com/invertase/react-native-firebase/commit/cc181400e465895bdb012eff881209315adaed70))
|
|
51
|
+
- **app, ios:** tighten the dynamic Firebase probe and import guard ([cac843c](https://github.com/invertase/react-native-firebase/commit/cac843c09156237751274073c67b6105fa7b4188))
|
|
52
|
+
- **app, storage:** link Photos framework on tvOS ([56f5c1f](https://github.com/invertase/react-native-firebase/commit/56f5c1fcf83bc89d8cd80f019696e13bc96578dd))
|
|
53
|
+
- **app, tests:** ignore iOS host stubs in TurboModule spec parity lookup ([e2f515d](https://github.com/invertase/react-native-firebase/commit/e2f515da36a180d16d6f6002886c17f6fd511749))
|
|
54
|
+
- **app,database:** resolve platform native module when bundlers apply package exports ([959d91f](https://github.com/invertase/react-native-firebase/commit/959d91fc79d7155d1d9a08e1f836789e6e6d6156))
|
|
55
|
+
- **app:** import e2e native module resolver via internal barrel ([93f51ff](https://github.com/invertase/react-native-firebase/commit/93f51fff8b2b4f1355bc213f5f98fbbf7986c7e0))
|
|
56
|
+
- **app:** reject unsafe deepSet path segments ([ec3ac24](https://github.com/invertase/react-native-firebase/commit/ec3ac2455b30cfabc501845364623d9ab55e7193))
|
|
57
|
+
- **app:** restore vendor EventEmitter for RN macOS 0.78 ([6b13c9d](https://github.com/invertase/react-native-firebase/commit/6b13c9d468abde5b5acc990e43a3d3fd6c7a140e))
|
|
58
|
+
- **app:** seed automaticDataCollectionEnabled from the native initializeApp result ([5d187f9](https://github.com/invertase/react-native-firebase/commit/5d187f9271f183ccac4d7b70e233a4ccd2145fd0))
|
|
59
|
+
- **app:** stop evaluating firebase.json content as Ruby/Python source in ios_config.sh ([d333ab3](https://github.com/invertase/react-native-firebase/commit/d333ab39a83454606d9ede4aa4a3c031a63cf898))
|
|
60
|
+
- **app:** swizzle null sentinels after codegen converters load ([bcff184](https://github.com/invertase/react-native-firebase/commit/bcff18471b187bda0476c8bbc76e4c216de58ec2))
|
|
61
|
+
- **ci:** unblock Yarn hardened CI and Xcode 27 iOS archive ([9c63630](https://github.com/invertase/react-native-firebase/commit/9c636307e9f87e106e802f5d39d2be32ef2cecdb))
|
|
62
|
+
- **e2e:** skip watchman watch-del when a sibling Metro owns the root ([7695132](https://github.com/invertase/react-native-firebase/commit/769513224d0e6f9bb6fb2a98c578411a5016615d))
|
|
63
|
+
|
|
64
|
+
### Continuous Integration
|
|
65
|
+
|
|
66
|
+
- **ios:** drop CocoaPods Firebase matrix; SPM-only ([89e270f](https://github.com/invertase/react-native-firebase/commit/89e270f3d1f4c1f3c22e32ca539ebe3da30dbd7e))
|
|
67
|
+
|
|
6
68
|
## [26.4.0](https://github.com/invertase/react-native-firebase/compare/v26.3.3...v26.4.0) (2026-09-05)
|
|
7
69
|
|
|
8
70
|
### Features
|
package/README.md
CHANGED
|
@@ -36,40 +36,23 @@ yarn add @react-native-firebase/app
|
|
|
36
36
|
|
|
37
37
|
- [Utils](https://rnfirebase.io/app/utils)
|
|
38
38
|
|
|
39
|
-
## iOS Dependency Resolution
|
|
39
|
+
## iOS Dependency Resolution (SPM-only)
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
Firebase
|
|
41
|
+
Firebase Apple SDK 13+ is distributed **only** via Swift Package Manager.
|
|
42
|
+
React Native Firebase requires React Native 0.75+ (`spm_dependency`) and
|
|
43
|
+
dynamic linkage:
|
|
43
44
|
|
|
44
45
|
```ruby
|
|
45
46
|
use_frameworks! :linkage => :dynamic
|
|
46
47
|
```
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
`$RNFirebaseDisableSPM = true` and Expo `ios.disableSPM: true` /
|
|
50
|
+
`disableSPM: true` **fail** `pod install` / prebuild — CocoaPods Firebase is
|
|
51
|
+
no longer available. Remove those flags and stay on SPM + dynamic frameworks.
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Expo projects can set the same flag through the config plugin, which adds it
|
|
55
|
-
to the generated Podfile during prebuild:
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
[
|
|
59
|
-
"@react-native-firebase/app",
|
|
60
|
-
{
|
|
61
|
-
"ios": {
|
|
62
|
-
"disableSPM": true
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
]
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
CocoaPods mode supports static or dynamic linkage. React Native versions older
|
|
69
|
-
than 0.75 fall back to CocoaPods automatically.
|
|
70
|
-
|
|
71
|
-
See the [iOS SPM guide](https://rnfirebase.io/ios-spm) for Xcode 26 setup,
|
|
72
|
-
Expo configuration, framework-embedding fallback, and troubleshooting.
|
|
53
|
+
See [iOS SPM Support](https://rnfirebase.io/ios-spm) and
|
|
54
|
+
[Migrating to v27](https://rnfirebase.io/migrating-to-v27) for setup,
|
|
55
|
+
Expo configuration, and troubleshooting.
|
|
73
56
|
|
|
74
57
|
## License
|
|
75
58
|
|
package/RNFBApp.podspec
CHANGED
|
@@ -23,9 +23,15 @@ Pod::Spec.new do |s|
|
|
|
23
23
|
s.macos.deployment_target = firebase_macos_target
|
|
24
24
|
s.tvos.deployment_target = firebase_tvos_target
|
|
25
25
|
s.cocoapods_version = '>= 1.12.0'
|
|
26
|
-
s.
|
|
26
|
+
s.swift_version = '5.10'
|
|
27
|
+
s.source_files = "ios/**/*.{h,m,mm,cpp,swift}"
|
|
27
28
|
s.private_header_files = "ios/**/*.h"
|
|
28
|
-
|
|
29
|
+
# CocoaPods FileList uses FNM_PATHNAME: `ios/*UnitTests/**` does not match nested
|
|
30
|
+
# paths like `ios/RNFBAppUnitTests/HostStubs/**` (those would compile into the pod).
|
|
31
|
+
# CocoaPods FileList uses FNM_PATHNAME: a trailing `/**` alone does not match
|
|
32
|
+
# nested files (same reason UnitTests use `/**/*`). Exclude the CI-only local
|
|
33
|
+
# SPM package so its sources are never compiled into the RNFBApp pod.
|
|
34
|
+
s.exclude_files = 'ios/generated/RCTThirdPartyComponentsProvider.*', 'ios/generated/RCTAppDependencyProvider.*', 'ios/generated/RCTModuleProviders.*', 'ios/generated/RCTModulesConformingToProtocolsProvider.*', 'ios/generated/RCTUnstableModulesRequiringMainQueueSetupProvider.*', 'ios/*UnitTests/**/*', 'ios/RNFBFirebase/**/*'
|
|
29
35
|
|
|
30
36
|
# Fail fast for old architecture users, but safely in case the variable goes away
|
|
31
37
|
# completely in future react-native versions
|
|
@@ -42,15 +48,17 @@ Pod::Spec.new do |s|
|
|
|
42
48
|
"CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES" => "YES",
|
|
43
49
|
}
|
|
44
50
|
|
|
45
|
-
# RNFBUtilsModule.
|
|
51
|
+
# RNFBUtilsModule+PhotoAssets.m uses PHAsset (Photos.framework) to resolve local asset paths.
|
|
46
52
|
# Not declaring this explicitly used to work by luck (CocoaPods normally relies on
|
|
47
53
|
# this declaration -- not Clang autolinking -- to populate OTHER_LDFLAGS), but with
|
|
48
54
|
# use_frameworks! each pod is a standalone dynamic framework that must resolve its
|
|
49
55
|
# own symbols at its own link step, so the missing declaration now surfaces as
|
|
50
|
-
# "Undefined symbols ... _OBJC_CLASS_$_PHAsset".
|
|
51
|
-
#
|
|
56
|
+
# "Undefined symbols ... _OBJC_CLASS_$_PHAsset". PhotoKit is available on
|
|
57
|
+
# tvOS 10+, and this .m file emits no Clang autolink record, so tvOS needs
|
|
58
|
+
# the same explicit link.
|
|
52
59
|
s.ios.frameworks = 'Photos'
|
|
53
60
|
s.osx.frameworks = 'Photos'
|
|
61
|
+
s.tvos.frameworks = 'Photos'
|
|
54
62
|
|
|
55
63
|
# React Native dependencies
|
|
56
64
|
if defined?(install_modules_dependencies()) != nil
|
package/android/build.gradle
CHANGED
|
@@ -14,6 +14,7 @@ buildscript {
|
|
|
14
14
|
|
|
15
15
|
dependencies {
|
|
16
16
|
classpath("com.android.tools.build:gradle:8.4.0")
|
|
17
|
+
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.findProperty('kotlinVersion') ?: '2.4.0'}")
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
}
|
|
@@ -22,6 +23,8 @@ plugins {
|
|
|
22
23
|
id "io.invertase.gradle.build" version "1.5"
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
apply plugin: "org.jetbrains.kotlin.android"
|
|
27
|
+
|
|
25
28
|
def packageJson = PackageJson.getForProject(project)
|
|
26
29
|
def firebaseBomVersion = packageJson['sdkVersions']['android']['firebase']
|
|
27
30
|
def playServicesAuthVersion = packageJson['sdkVersions']['android']['playServicesAuth']
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
package io.invertase.firebase.common
|
|
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
|
+
/**
|
|
21
|
+
* Thrown when [RNFBHandleMap.put] is asked to register an id that is already occupied.
|
|
22
|
+
*
|
|
23
|
+
* This remains a checked Java-visible exception ([Exception], not [RuntimeException]) so callers
|
|
24
|
+
* must handle collisions explicitly. There is no upsert: replace an existing registration with
|
|
25
|
+
* [RNFBHandleMap.take] then [RNFBHandleMap.put].
|
|
26
|
+
*/
|
|
27
|
+
open class RNFBHandleCollisionException(
|
|
28
|
+
id: Any?,
|
|
29
|
+
) : Exception("Handle id already registered: $id")
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
package io.invertase.firebase.common
|
|
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 java.util.function.Predicate
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Thread-safe id → handle registry. The lock only moves pointers; this class never invokes methods
|
|
24
|
+
* on stored values (no SDK `cancel`/`remove`). Callers [take] or [takeAll], then act on the returned
|
|
25
|
+
* object(s) outside the lock.
|
|
26
|
+
*
|
|
27
|
+
* [put] is unique: an occupied id throws [RNFBHandleCollisionException]. There is no upsert. Use
|
|
28
|
+
* [putIfAbsent] (first wins), [putIfAbsentOrSame] (first wins or same instance), or [putReplacing]
|
|
29
|
+
* (last wins) for atomic upsert. Replace at the call site with `take` then `put` only when neither
|
|
30
|
+
* helper fits.
|
|
31
|
+
*
|
|
32
|
+
* **Do not lock on the map or on a [RNFBHandleMap] instance.** Callers that synchronize on `this`
|
|
33
|
+
* (or on the internal map) can deadlock with the dedicated monitor. Android uses a private [lock]
|
|
34
|
+
* object; never expose it and never `synchronized(this)` around these methods.
|
|
35
|
+
*/
|
|
36
|
+
open class RNFBHandleMap<K, V> {
|
|
37
|
+
private val lock = Any()
|
|
38
|
+
private val map = HashMap<K, V>()
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Registers [handle] under [id].
|
|
42
|
+
*
|
|
43
|
+
* @throws RNFBHandleCollisionException if [id] is already occupied
|
|
44
|
+
*/
|
|
45
|
+
@Throws(RNFBHandleCollisionException::class)
|
|
46
|
+
open fun put(
|
|
47
|
+
id: K,
|
|
48
|
+
handle: V,
|
|
49
|
+
) {
|
|
50
|
+
synchronized(lock) {
|
|
51
|
+
if (map.containsKey(id)) {
|
|
52
|
+
throw RNFBHandleCollisionException(id)
|
|
53
|
+
}
|
|
54
|
+
map[id] = handle
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Stores [handle] under [id] only when the id is free (first wins).
|
|
60
|
+
*
|
|
61
|
+
* @return `true` if stored, `false` if [id] was already occupied
|
|
62
|
+
*/
|
|
63
|
+
open fun putIfAbsent(
|
|
64
|
+
id: K,
|
|
65
|
+
handle: V,
|
|
66
|
+
): Boolean =
|
|
67
|
+
synchronized(lock) {
|
|
68
|
+
if (map.containsKey(id)) {
|
|
69
|
+
false
|
|
70
|
+
} else {
|
|
71
|
+
map[id] = handle
|
|
72
|
+
true
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Under one lock: stores [handle] when the id is free, or returns `true` when the existing mapping
|
|
78
|
+
* is the same instance (`===`). Returns `false` when occupied by a different handle.
|
|
79
|
+
*/
|
|
80
|
+
open fun putIfAbsentOrSame(
|
|
81
|
+
id: K,
|
|
82
|
+
handle: V,
|
|
83
|
+
): Boolean =
|
|
84
|
+
synchronized(lock) {
|
|
85
|
+
if (!map.containsKey(id)) {
|
|
86
|
+
map[id] = handle
|
|
87
|
+
true
|
|
88
|
+
} else {
|
|
89
|
+
map[id] === handle
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Atomically replaces the mapping for [id] (last wins). Returns the previous handle, or `null` if
|
|
95
|
+
* the id was free.
|
|
96
|
+
*/
|
|
97
|
+
open fun putReplacing(
|
|
98
|
+
id: K,
|
|
99
|
+
handle: V,
|
|
100
|
+
): V? = synchronized(lock) { map.put(id, handle) }
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Peeks at the handle for [id] without removing it (for emit while still registered).
|
|
104
|
+
*
|
|
105
|
+
* @return the handle, or `null` if absent
|
|
106
|
+
*/
|
|
107
|
+
open fun get(id: K): V? = synchronized(lock) { map[id] }
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Removes and returns the handle for [id].
|
|
111
|
+
*
|
|
112
|
+
* @return the handle, or `null` if absent
|
|
113
|
+
*/
|
|
114
|
+
open fun take(id: K): V? = synchronized(lock) { map.remove(id) }
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* When [id] is mapped and [shouldTake] accepts the handle, removes and returns it; otherwise
|
|
118
|
+
* returns `null` and leaves the map unchanged. Lookup, predicate, and removal run under one lock —
|
|
119
|
+
* use for check-and-take that must not race with concurrent [put] / [take] on the same id.
|
|
120
|
+
*
|
|
121
|
+
* The predicate runs under this map's lock; keep it lightweight (no SDK cancel/remove).
|
|
122
|
+
*/
|
|
123
|
+
open fun takeIf(
|
|
124
|
+
id: K,
|
|
125
|
+
shouldTake: Predicate<V>,
|
|
126
|
+
): V? =
|
|
127
|
+
synchronized(lock) {
|
|
128
|
+
val value = map[id]
|
|
129
|
+
if (value != null && shouldTake.test(value)) {
|
|
130
|
+
map.remove(id)
|
|
131
|
+
} else {
|
|
132
|
+
null
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Snapshot of current values, then clear. Cancel/remove each returned object after this method
|
|
138
|
+
* returns, not under this map's lock.
|
|
139
|
+
*/
|
|
140
|
+
open fun takeAll(): List<V> =
|
|
141
|
+
synchronized(lock) {
|
|
142
|
+
val values = ArrayList(map.values)
|
|
143
|
+
map.clear()
|
|
144
|
+
values
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
package io.invertase.firebase.common
|
|
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 java.util.concurrent.ExecutorService
|
|
21
|
+
import java.util.concurrent.LinkedBlockingQueue
|
|
22
|
+
import java.util.concurrent.RejectedExecutionException
|
|
23
|
+
import java.util.concurrent.RejectedExecutionHandler
|
|
24
|
+
import java.util.concurrent.SynchronousQueue
|
|
25
|
+
import java.util.concurrent.ThreadPoolExecutor
|
|
26
|
+
import java.util.concurrent.TimeUnit
|
|
27
|
+
|
|
28
|
+
open class TaskExecutorService(
|
|
29
|
+
private val name: String,
|
|
30
|
+
) {
|
|
31
|
+
private val maximumPoolSize: Int
|
|
32
|
+
private val keepAliveSeconds: Int
|
|
33
|
+
|
|
34
|
+
init {
|
|
35
|
+
val json = ReactNativeFirebaseJSON.getSharedInstance()
|
|
36
|
+
maximumPoolSize = json.getIntValue(MAXIMUM_POOL_SIZE_KEY, 1)
|
|
37
|
+
keepAliveSeconds = json.getIntValue(KEEP_ALIVE_SECONDS_KEY, 3)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
open fun getExecutor(): ExecutorService {
|
|
41
|
+
val isTransactional = maximumPoolSize <= 1
|
|
42
|
+
return getExecutor(isTransactional, "")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
open fun getTransactionalExecutor(): ExecutorService = getExecutor(true, "")
|
|
46
|
+
|
|
47
|
+
open fun getTransactionalExecutor(identifier: String): ExecutorService {
|
|
48
|
+
val executorIdentifier = if (maximumPoolSize != 0) identifier else ""
|
|
49
|
+
return getExecutor(true, executorIdentifier)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
open fun getExecutor(
|
|
53
|
+
isTransactional: Boolean,
|
|
54
|
+
identifier: String,
|
|
55
|
+
): ExecutorService {
|
|
56
|
+
val executorName = getExecutorName(isTransactional, identifier)
|
|
57
|
+
synchronized(executors) {
|
|
58
|
+
val existingExecutor = executors[executorName]
|
|
59
|
+
if (existingExecutor == null) {
|
|
60
|
+
val newExecutor = getNewExecutor(isTransactional)
|
|
61
|
+
executors[executorName] = newExecutor
|
|
62
|
+
return newExecutor
|
|
63
|
+
}
|
|
64
|
+
return existingExecutor
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private fun getNewExecutor(isTransactional: Boolean): ExecutorService {
|
|
69
|
+
if (isTransactional) {
|
|
70
|
+
// A bare Executors.newSingleThreadExecutor() has no rejection handler, so a
|
|
71
|
+
// play-services Task completing after shutdown() (module invalidation racing
|
|
72
|
+
// in-flight work, e.g. App Check attestation or Auth network calls finishing
|
|
73
|
+
// while the React instance is torn down) posts to the dead executor and
|
|
74
|
+
// crashes the process with an uncaught RejectedExecutionException. Use an
|
|
75
|
+
// equivalent single-thread pool that discards work arriving after shutdown.
|
|
76
|
+
return ThreadPoolExecutor(
|
|
77
|
+
1,
|
|
78
|
+
1,
|
|
79
|
+
0L,
|
|
80
|
+
TimeUnit.MILLISECONDS,
|
|
81
|
+
LinkedBlockingQueue(),
|
|
82
|
+
).apply { rejectedExecutionHandler = discardAfterShutdown }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return ThreadPoolExecutor(
|
|
86
|
+
0,
|
|
87
|
+
maximumPoolSize,
|
|
88
|
+
keepAliveSeconds.toLong(),
|
|
89
|
+
TimeUnit.SECONDS,
|
|
90
|
+
SynchronousQueue(),
|
|
91
|
+
).apply { rejectedExecutionHandler = executeInFallback }
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private val executeInFallback =
|
|
95
|
+
RejectedExecutionHandler { runnable, executor ->
|
|
96
|
+
// isShutdown() remains true through the terminating and terminated states,
|
|
97
|
+
// so it is the only check needed to detect work arriving after shutdown.
|
|
98
|
+
if (executor.isShutdown) {
|
|
99
|
+
return@RejectedExecutionHandler
|
|
100
|
+
}
|
|
101
|
+
val fallbackExecutor = getTransactionalExecutor()
|
|
102
|
+
fallbackExecutor.execute(runnable)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
open fun getExecutorName(
|
|
106
|
+
isTransactional: Boolean,
|
|
107
|
+
identifier: String,
|
|
108
|
+
): String =
|
|
109
|
+
if (isTransactional) {
|
|
110
|
+
"${name}TransactionalExecutor$identifier"
|
|
111
|
+
} else {
|
|
112
|
+
"${name}Executor$identifier"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
open fun shutdown() {
|
|
116
|
+
synchronized(executors) {
|
|
117
|
+
val existingExecutorNames = ArrayList(executors.keys)
|
|
118
|
+
for (executorName in existingExecutorNames) {
|
|
119
|
+
if (!executorName.startsWith(name)) {
|
|
120
|
+
executors.remove(executorName)
|
|
121
|
+
} else {
|
|
122
|
+
removeExecutor(executorName)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
open fun removeExecutor(executorName: String) {
|
|
129
|
+
synchronized(executors) {
|
|
130
|
+
val existingExecutor = executors[executorName]
|
|
131
|
+
if (existingExecutor != null) {
|
|
132
|
+
existingExecutor.shutdownNow()
|
|
133
|
+
executors.remove(executorName)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private companion object {
|
|
139
|
+
private const val MAXIMUM_POOL_SIZE_KEY = "android_task_executor_maximum_pool_size"
|
|
140
|
+
private const val KEEP_ALIVE_SECONDS_KEY = "android_task_executor_keep_alive_seconds"
|
|
141
|
+
|
|
142
|
+
private val executors = HashMap<String, ExecutorService>()
|
|
143
|
+
|
|
144
|
+
private val discardAfterShutdown =
|
|
145
|
+
RejectedExecutionHandler { runnable, executor ->
|
|
146
|
+
// isShutdown() remains true through the terminating and terminated states,
|
|
147
|
+
// so it is the only check needed to detect work arriving after shutdown.
|
|
148
|
+
if (executor.isShutdown) {
|
|
149
|
+
return@RejectedExecutionHandler
|
|
150
|
+
}
|
|
151
|
+
// Unreachable with an unbounded queue, but preserve AbortPolicy semantics
|
|
152
|
+
// for any rejection that is not caused by shutdown.
|
|
153
|
+
throw RejectedExecutionException("Task $runnable rejected from $executor")
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package io.invertase.firebase.common
|
|
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
|
+
import android.content.Context
|
|
20
|
+
import java.util.HashMap
|
|
21
|
+
import java.util.concurrent.ExecutorService
|
|
22
|
+
import javax.annotation.OverridingMethodsMustInvokeSuper
|
|
23
|
+
|
|
24
|
+
open class UniversalFirebaseModule(
|
|
25
|
+
private val context: Context?,
|
|
26
|
+
private val serviceName: String?,
|
|
27
|
+
) {
|
|
28
|
+
private val executorService: TaskExecutorService = TaskExecutorService(getName())
|
|
29
|
+
|
|
30
|
+
open fun getContext(): Context? = context
|
|
31
|
+
|
|
32
|
+
open fun getApplicationContext(): Context? = getContext()!!.applicationContext
|
|
33
|
+
|
|
34
|
+
open fun getExecutor(): ExecutorService = executorService.getExecutor()
|
|
35
|
+
|
|
36
|
+
open fun getName(): String = "Universal${serviceName}Module"
|
|
37
|
+
|
|
38
|
+
@OverridingMethodsMustInvokeSuper
|
|
39
|
+
open fun onTearDown() {
|
|
40
|
+
executorService.shutdown()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
open fun getConstants(): Map<String, Any> = HashMap()
|
|
44
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
package io.invertase.firebase.common
|
|
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 android.content.Context
|
|
21
|
+
import android.content.SharedPreferences
|
|
22
|
+
import io.invertase.firebase.app.ReactNativeFirebaseApp
|
|
23
|
+
|
|
24
|
+
open class UniversalFirebasePreferences {
|
|
25
|
+
private var preferences: SharedPreferences? = null
|
|
26
|
+
|
|
27
|
+
open fun contains(key: String?): Boolean = getPreferences().contains(key)
|
|
28
|
+
|
|
29
|
+
open fun setBooleanValue(
|
|
30
|
+
key: String?,
|
|
31
|
+
value: Boolean,
|
|
32
|
+
) {
|
|
33
|
+
getPreferences().edit().putBoolean(key, value).apply()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
open fun getBooleanValue(
|
|
37
|
+
key: String?,
|
|
38
|
+
defaultValue: Boolean,
|
|
39
|
+
): Boolean = getPreferences().getBoolean(key, defaultValue)
|
|
40
|
+
|
|
41
|
+
open fun setIntValue(
|
|
42
|
+
key: String?,
|
|
43
|
+
value: Int,
|
|
44
|
+
) {
|
|
45
|
+
getPreferences().edit().putInt(key, value).apply()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
open fun getIntValue(
|
|
49
|
+
key: String?,
|
|
50
|
+
defaultValue: Int,
|
|
51
|
+
): Int = getPreferences().getInt(key, defaultValue)
|
|
52
|
+
|
|
53
|
+
open fun setLongValue(
|
|
54
|
+
key: String?,
|
|
55
|
+
value: Long,
|
|
56
|
+
) {
|
|
57
|
+
getPreferences().edit().putLong(key, value).apply()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
open fun getLongValue(
|
|
61
|
+
key: String?,
|
|
62
|
+
defaultValue: Long,
|
|
63
|
+
): Long = getPreferences().getLong(key, defaultValue)
|
|
64
|
+
|
|
65
|
+
open fun setStringValue(
|
|
66
|
+
key: String?,
|
|
67
|
+
value: String?,
|
|
68
|
+
) {
|
|
69
|
+
getPreferences().edit().putString(key, value).apply()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
open fun getStringValue(
|
|
73
|
+
key: String?,
|
|
74
|
+
defaultValue: String?,
|
|
75
|
+
): String? = getPreferences().getString(key, defaultValue)
|
|
76
|
+
|
|
77
|
+
open fun clearAll() {
|
|
78
|
+
getPreferences().edit().clear().apply()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// The caller is responsible for calling apply() or commit() on the returned editor.
|
|
82
|
+
open fun remove(key: String?): SharedPreferences.Editor = getPreferences().edit().remove(key)
|
|
83
|
+
|
|
84
|
+
private fun getPreferences(): SharedPreferences {
|
|
85
|
+
if (preferences == null) {
|
|
86
|
+
preferences =
|
|
87
|
+
ReactNativeFirebaseApp
|
|
88
|
+
.getApplicationContext()
|
|
89
|
+
.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE)
|
|
90
|
+
}
|
|
91
|
+
return preferences!!
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
companion object {
|
|
95
|
+
private const val PREFERENCES_FILE = "io.invertase.firebase"
|
|
96
|
+
private val sharedInstance = UniversalFirebasePreferences()
|
|
97
|
+
|
|
98
|
+
@JvmStatic fun getSharedInstance(): UniversalFirebasePreferences = sharedInstance
|
|
99
|
+
}
|
|
100
|
+
}
|