@react-native-firebase/app 25.0.1 → 26.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.
- package/CHANGELOG.md +49 -0
- package/RNFBApp.podspec +7 -13
- package/android/build.gradle +25 -6
- package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppModule.java → NativeRNFBTurboApp.java} +81 -45
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +3 -3
- package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +2 -2
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboAppSpec.java +136 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/java/com/facebook/fbreact/specs/NativeRNFBTurboUtilsSpec.java +94 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/CMakeLists.txt +36 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/RNFBAppTurboModules-generated.cpp +170 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/RNFBAppTurboModules.h +39 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/react/renderer/components/RNFBAppTurboModules/RNFBAppTurboModulesJSI-generated.cpp +187 -0
- package/android/src/reactnative/java/io/invertase/firebase/app/generated/jni/react/renderer/components/RNFBAppTurboModules/RNFBAppTurboModulesJSI.h +606 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +3 -3
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +475 -20
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +8 -0
- package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +8 -0
- package/android/src/reactnative/java/io/invertase/firebase/utils/{ReactNativeFirebaseUtilsModule.java → NativeRNFBTurboUtils.java} +57 -40
- package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +400 -0
- package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +1823 -0
- package/app.plugin.js +1 -1
- package/dist/module/FirebaseApp.js +0 -9
- package/dist/module/FirebaseApp.js.map +1 -1
- package/dist/module/common/index.js +0 -645
- package/dist/module/common/index.js.map +1 -1
- package/dist/module/common/unitTestUtils.js +18 -54
- package/dist/module/common/unitTestUtils.js.map +1 -1
- package/dist/module/index.js +0 -1
- package/dist/module/index.js.map +1 -1
- package/dist/module/internal/RNFBNativeEventEmitter.js +12 -6
- package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
- package/dist/module/internal/constants.js +2 -2
- package/dist/module/internal/constants.js.map +1 -1
- package/dist/module/internal/index.js +1 -1
- package/dist/module/internal/index.js.map +1 -1
- package/dist/module/internal/nativeModuleAndroidIos.js +50 -10
- package/dist/module/internal/nativeModuleAndroidIos.js.map +1 -1
- package/dist/module/internal/nativeModuleWeb.js +12 -4
- package/dist/module/internal/nativeModuleWeb.js.map +1 -1
- package/dist/module/internal/registry/app.js +20 -12
- package/dist/module/internal/registry/app.js.map +1 -1
- package/dist/module/internal/registry/modular.js +73 -0
- package/dist/module/internal/registry/modular.js.map +1 -0
- package/dist/module/internal/registry/nativeModule.js +116 -95
- package/dist/module/internal/registry/nativeModule.js.map +1 -1
- package/dist/module/modular.js +44 -37
- package/dist/module/modular.js.map +1 -1
- package/dist/module/types/app.js +0 -3
- package/dist/module/types/app.js.map +1 -1
- package/dist/module/types/internal.js +0 -2
- package/dist/module/utils/UtilsStatics.js +2 -2
- package/dist/module/utils/UtilsStatics.js.map +1 -1
- package/dist/module/utils/index.js +21 -17
- package/dist/module/utils/index.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/typescript/lib/FirebaseApp.d.ts +1 -2
- package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
- package/dist/typescript/lib/common/index.d.ts +0 -8
- package/dist/typescript/lib/common/index.d.ts.map +1 -1
- package/dist/typescript/lib/common/unitTestUtils.d.ts +1 -4
- package/dist/typescript/lib/common/unitTestUtils.d.ts.map +1 -1
- package/dist/typescript/lib/index.d.ts +0 -1
- package/dist/typescript/lib/index.d.ts.map +1 -1
- package/dist/typescript/lib/internal/NativeFirebaseError.d.ts +1 -1
- package/dist/typescript/lib/internal/NativeFirebaseError.d.ts.map +1 -1
- package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
- package/dist/typescript/lib/internal/constants.d.ts +2 -3
- package/dist/typescript/lib/internal/constants.d.ts.map +1 -1
- package/dist/typescript/lib/internal/index.d.ts +1 -1
- package/dist/typescript/lib/internal/index.d.ts.map +1 -1
- package/dist/typescript/lib/internal/nativeModuleAndroidIos.d.ts +2 -6
- package/dist/typescript/lib/internal/nativeModuleAndroidIos.d.ts.map +1 -1
- package/dist/typescript/lib/internal/nativeModuleWeb.d.ts.map +1 -1
- package/dist/typescript/lib/internal/registry/app.d.ts +2 -2
- package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
- package/dist/typescript/lib/internal/registry/modular.d.ts +22 -0
- package/dist/typescript/lib/internal/registry/modular.d.ts.map +1 -0
- package/dist/typescript/lib/internal/registry/nativeModule.d.ts +3 -11
- package/dist/typescript/lib/internal/registry/nativeModule.d.ts.map +1 -1
- package/dist/typescript/lib/modular.d.ts +21 -7
- package/dist/typescript/lib/modular.d.ts.map +1 -1
- package/dist/typescript/lib/types/app.d.ts +4 -4
- package/dist/typescript/lib/types/app.d.ts.map +1 -1
- package/dist/typescript/lib/types/internal.d.ts +1 -33
- package/dist/typescript/lib/types/internal.d.ts.map +1 -1
- package/dist/typescript/lib/utils/index.d.ts +7 -3
- package/dist/typescript/lib/utils/index.d.ts.map +1 -1
- package/dist/typescript/lib/version.d.ts +1 -1
- package/firebase-schema.json +5 -1
- package/ios/RNFBApp/RNFBAppModule.h +1 -3
- package/ios/RNFBApp/{RNFBAppModule.m → RNFBAppModule.mm} +74 -77
- package/ios/RNFBApp/RNFBUtilsModule.h +1 -3
- package/ios/RNFBApp/{RNFBUtilsModule.m → RNFBUtilsModule.mm} +68 -25
- package/ios/RNFBApp/RNFBVersion.m +1 -1
- package/ios/RNFBApp.xcodeproj/project.pbxproj +12 -12
- package/ios/generated/RCTAppDependencyProvider.h +25 -0
- package/ios/generated/RCTAppDependencyProvider.mm +55 -0
- package/ios/generated/RCTModuleProviders.h +16 -0
- package/ios/generated/RCTModuleProviders.mm +52 -0
- package/ios/generated/RCTModulesConformingToProtocolsProvider.h +18 -0
- package/ios/generated/RCTModulesConformingToProtocolsProvider.mm +33 -0
- package/ios/generated/RCTThirdPartyComponentsProvider.h +16 -0
- package/ios/generated/RCTThirdPartyComponentsProvider.mm +23 -0
- package/ios/generated/RCTUnstableModulesRequiringMainQueueSetupProvider.h +14 -0
- package/ios/generated/RCTUnstableModulesRequiringMainQueueSetupProvider.mm +19 -0
- package/ios/generated/RNFBAppTurboModules/RNFBAppTurboModules-generated.mm +210 -0
- package/ios/generated/RNFBAppTurboModules/RNFBAppTurboModules.h +399 -0
- package/ios/generated/RNFBAppTurboModulesJSI-generated.cpp +187 -0
- package/ios/generated/RNFBAppTurboModulesJSI.h +606 -0
- package/ios/generated/ReactAppDependencyProvider.podspec +34 -0
- package/ios/generated/ReactCodegen.podspec +111 -0
- package/lib/FirebaseApp.ts +1 -10
- package/lib/common/index.ts +0 -742
- package/lib/common/unitTestUtils.ts +17 -73
- package/lib/index.ts +0 -1
- package/lib/internal/NativeFirebaseError.ts +1 -1
- package/lib/internal/RNFBNativeEventEmitter.ts +12 -6
- package/lib/internal/constants.ts +3 -25
- package/lib/internal/global.d.ts +0 -4
- package/lib/internal/index.ts +1 -1
- package/lib/internal/nativeModuleAndroidIos.ts +69 -12
- package/lib/internal/nativeModuleWeb.ts +11 -5
- package/lib/internal/registry/app.ts +24 -22
- package/lib/internal/registry/modular.ts +97 -0
- package/lib/internal/registry/nativeModule.ts +136 -107
- package/lib/modular.ts +47 -72
- package/lib/types/app.ts +6 -11
- package/lib/types/internal.ts +1 -46
- package/lib/utils/UtilsStatics.ts +2 -2
- package/lib/utils/index.ts +24 -18
- package/lib/version.ts +1 -1
- package/package.json +41 -3
- package/plugin/build/app.plugin.d.ts +2 -0
- package/plugin/build/app.plugin.js +6 -0
- package/plugin/src/app.plugin.ts +3 -0
- package/plugin/tsconfig.tsbuildinfo +1 -1
- package/react-native.config.js +2 -0
- package/specs/NativeRNFBTurboApp.ts +57 -0
- package/specs/NativeRNFBTurboUtils.ts +34 -0
- package/typedoc.json +1 -2
- package/dist/module/internal/registry/namespace.js +0 -262
- package/dist/module/internal/registry/namespace.js.map +0 -1
- package/dist/module/namespaced.js +0 -25
- package/dist/module/namespaced.js.map +0 -1
- package/dist/typescript/lib/internal/registry/namespace.d.ts +0 -26
- package/dist/typescript/lib/internal/registry/namespace.d.ts.map +0 -1
- package/dist/typescript/lib/namespaced.d.ts +0 -5
- package/dist/typescript/lib/namespaced.d.ts.map +0 -1
- package/lib/internal/registry/namespace.ts +0 -338
- package/lib/namespaced.ts +0 -24
|
@@ -1,74 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
+
*/
|
|
3
17
|
|
|
4
|
-
export
|
|
5
|
-
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
6
|
-
consoleWarnSpy.mockRestore();
|
|
7
|
-
modularFunction();
|
|
8
|
-
expect(consoleWarnSpy).not.toHaveBeenCalled();
|
|
9
|
-
consoleWarnSpy.mockClear();
|
|
10
|
-
const consoleWarnSpy2 = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|
11
|
-
nonModularFunction();
|
|
12
|
-
|
|
13
|
-
expect(consoleWarnSpy2).toHaveBeenCalledTimes(1);
|
|
14
|
-
consoleWarnSpy2.mockClear();
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type CheckV9DeprecationFunction = (
|
|
18
|
-
modularFunction: () => void,
|
|
19
|
-
nonModularFunction: () => void,
|
|
20
|
-
methodNameKey: string,
|
|
21
|
-
uniqueMessage?: string | null,
|
|
22
|
-
ignoreFirebaseAppDeprecationWarning?: boolean,
|
|
23
|
-
) => void;
|
|
24
|
-
|
|
25
|
-
export const withDeprecationWarningsSilenced = <T>(fn: () => T): T => {
|
|
26
|
-
const previous = globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS;
|
|
27
|
-
globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS = true;
|
|
28
|
-
try {
|
|
29
|
-
return fn();
|
|
30
|
-
} finally {
|
|
31
|
-
globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS = previous;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export const createCheckV9Deprecation = (moduleNames: string[]): CheckV9DeprecationFunction => {
|
|
36
|
-
return (
|
|
37
|
-
modularFunction: () => void,
|
|
38
|
-
nonModularFunction: () => void,
|
|
39
|
-
methodNameKey: string,
|
|
40
|
-
uniqueMessage?: string | null,
|
|
41
|
-
checkFirebaseAppDeprecationWarning: boolean = false,
|
|
42
|
-
) => {
|
|
43
|
-
const moduleName = moduleNames[0] as string; // firestore, database, etc
|
|
44
|
-
const instanceName = moduleNames[1] || 'default'; // default, FirestoreCollectionReference, etc
|
|
45
|
-
const consoleWarnSpy = jest.spyOn(console, 'warn');
|
|
46
|
-
consoleWarnSpy.mockReset();
|
|
47
|
-
|
|
48
|
-
consoleWarnSpy.mockImplementation(warnMessage => {
|
|
49
|
-
const firebaseAppDeprecationMessage = warnMessage.includes('Please use `getApp()` instead.');
|
|
50
|
-
if (checkFirebaseAppDeprecationWarning) {
|
|
51
|
-
throw new Error(`Console warn was called unexpectedly with: ${warnMessage}`);
|
|
52
|
-
} else {
|
|
53
|
-
if (!firebaseAppDeprecationMessage) {
|
|
54
|
-
// we want to ignore all firebase app deprecation warnings (e.g. "Please use `getApp()` instead.") unless actually testing for it which we do above
|
|
55
|
-
throw new Error(`Console warn was called unexpectedly with: ${warnMessage}`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
// Do not call `mockRestore()` unless removing the spy
|
|
60
|
-
modularFunction();
|
|
61
|
-
consoleWarnSpy.mockReset();
|
|
62
|
-
consoleWarnSpy.mockRestore();
|
|
63
|
-
const consoleWarnSpy2 = jest.spyOn(console, 'warn').mockImplementation(warnMessage => {
|
|
64
|
-
const message = createMessage(moduleName, methodNameKey, instanceName, uniqueMessage);
|
|
65
|
-
if (message) {
|
|
66
|
-
expect(warnMessage).toMatch(message);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
nonModularFunction();
|
|
70
|
-
|
|
71
|
-
expect(consoleWarnSpy2).toHaveBeenCalledTimes(1);
|
|
72
|
-
consoleWarnSpy2.mockReset();
|
|
73
|
-
};
|
|
74
|
-
};
|
|
18
|
+
export {};
|
package/lib/index.ts
CHANGED
|
@@ -22,7 +22,7 @@ export default class NativeFirebaseError extends Error {
|
|
|
22
22
|
readonly code!: string;
|
|
23
23
|
readonly jsStack!: string;
|
|
24
24
|
readonly userInfo!: NativeErrorUserInfo;
|
|
25
|
-
readonly customData
|
|
25
|
+
readonly customData!: Record<string, unknown> | null;
|
|
26
26
|
readonly operationType!: string | null;
|
|
27
27
|
readonly nativeErrorCode!: string | number | null;
|
|
28
28
|
readonly nativeErrorMessage!: string | null;
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import { type EmitterSubscription, NativeEventEmitter } from 'react-native';
|
|
19
|
+
import { APP_NATIVE_MODULE } from './constants';
|
|
19
20
|
import { getReactNativeModule } from './nativeModule';
|
|
20
21
|
import type { RNFBAppModuleInterface } from './NativeModules';
|
|
21
22
|
|
|
@@ -38,10 +39,11 @@ class RNFBNativeEventEmitter extends NativeEventEmitter {
|
|
|
38
39
|
ready: boolean;
|
|
39
40
|
|
|
40
41
|
constructor() {
|
|
41
|
-
|
|
42
|
+
// NewArch-AD-18 E1: NativeEventEmitter must receive the same raw host that implements addListener/removeListeners.
|
|
43
|
+
const RNFBAppModule = getReactNativeModule(APP_NATIVE_MODULE);
|
|
42
44
|
if (!RNFBAppModule) {
|
|
43
45
|
throw new Error(
|
|
44
|
-
|
|
46
|
+
`Native module ${APP_NATIVE_MODULE} not found. Re-check module install, linking, configuration, build and install steps.`,
|
|
45
47
|
);
|
|
46
48
|
}
|
|
47
49
|
// Cast to any for NativeEventEmitter constructor which expects React Native's NativeModule type
|
|
@@ -54,8 +56,9 @@ class RNFBNativeEventEmitter extends NativeEventEmitter {
|
|
|
54
56
|
listener: (...args: unknown[]) => unknown,
|
|
55
57
|
context?: object,
|
|
56
58
|
): EmitterSubscription {
|
|
59
|
+
// NewArch-AD-18 E1: event bridge identity requires raw app-module host for listener registration.
|
|
57
60
|
const RNFBAppModule = getReactNativeModule(
|
|
58
|
-
|
|
61
|
+
APP_NATIVE_MODULE,
|
|
59
62
|
) as unknown as RNFBAppModuleInterface;
|
|
60
63
|
if (!this.ready) {
|
|
61
64
|
(RNFBAppModule.eventsNotifyReady as EventsNotifyReadyMethod)(true);
|
|
@@ -99,7 +102,8 @@ class RNFBNativeEventEmitter extends NativeEventEmitter {
|
|
|
99
102
|
// we will modify it to do our native unsubscription then call the original
|
|
100
103
|
const originalRemove = subscription.remove;
|
|
101
104
|
const newRemove = () => {
|
|
102
|
-
|
|
105
|
+
// NewArch-AD-18 E1: raw host for eventsRemoveListener on unsubscribe.
|
|
106
|
+
const module = getReactNativeModule(APP_NATIVE_MODULE) as unknown as RNFBAppModuleInterface;
|
|
103
107
|
(module.eventsRemoveListener as EventsRemoveListenerMethod)(eventType, false);
|
|
104
108
|
const superClass = Object.getPrototypeOf(Object.getPrototypeOf(this));
|
|
105
109
|
if (superClass.removeSubscription != null) {
|
|
@@ -115,8 +119,9 @@ class RNFBNativeEventEmitter extends NativeEventEmitter {
|
|
|
115
119
|
}
|
|
116
120
|
|
|
117
121
|
removeAllListeners(eventType: string): void {
|
|
122
|
+
// NewArch-AD-18 E1: raw host for eventsRemoveListener.
|
|
118
123
|
const RNFBAppModule = getReactNativeModule(
|
|
119
|
-
|
|
124
|
+
APP_NATIVE_MODULE,
|
|
120
125
|
) as unknown as RNFBAppModuleInterface;
|
|
121
126
|
(RNFBAppModule.eventsRemoveListener as EventsRemoveListenerMethod)(eventType, true);
|
|
122
127
|
super.removeAllListeners(`rnfb_${eventType}`);
|
|
@@ -124,8 +129,9 @@ class RNFBNativeEventEmitter extends NativeEventEmitter {
|
|
|
124
129
|
|
|
125
130
|
// This is likely no longer ever called, but it is here for backwards compatibility with RN <= 0.64
|
|
126
131
|
removeSubscription(subscription: EmitterSubscription & { eventType?: string }): void {
|
|
132
|
+
// NewArch-AD-18 E1: raw host for legacy removeSubscription path.
|
|
127
133
|
const RNFBAppModule = getReactNativeModule(
|
|
128
|
-
|
|
134
|
+
APP_NATIVE_MODULE,
|
|
129
135
|
) as unknown as RNFBAppModuleInterface;
|
|
130
136
|
const eventType = subscription.eventType?.replace('rnfb_', '') || '';
|
|
131
137
|
(RNFBAppModule.eventsRemoveListener as EventsRemoveListenerMethod)(eventType, false);
|
|
@@ -15,30 +15,8 @@
|
|
|
15
15
|
*
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
export const APP_NATIVE_MODULE = '
|
|
18
|
+
export const APP_NATIVE_MODULE = 'NativeRNFBTurboApp';
|
|
19
19
|
|
|
20
|
-
export const
|
|
21
|
-
|
|
22
|
-
export const KNOWN_NAMESPACES = [
|
|
23
|
-
'appCheck',
|
|
24
|
-
'appDistribution',
|
|
25
|
-
'auth',
|
|
26
|
-
'analytics',
|
|
27
|
-
'remoteConfig',
|
|
28
|
-
'crashlytics',
|
|
29
|
-
'database',
|
|
30
|
-
'inAppMessaging',
|
|
31
|
-
'installations',
|
|
32
|
-
'firestore',
|
|
33
|
-
'functions',
|
|
34
|
-
'indexing',
|
|
35
|
-
'storage',
|
|
36
|
-
'messaging',
|
|
37
|
-
'naturalLanguage',
|
|
38
|
-
'ml',
|
|
39
|
-
'notifications',
|
|
40
|
-
'perf',
|
|
41
|
-
'utils',
|
|
42
|
-
] as const;
|
|
20
|
+
export const UTILS_NATIVE_MODULE = 'NativeRNFBTurboUtils';
|
|
43
21
|
|
|
44
|
-
export
|
|
22
|
+
export const DEFAULT_APP_NAME = '[DEFAULT]';
|
package/lib/internal/global.d.ts
CHANGED
|
@@ -24,10 +24,6 @@ declare global {
|
|
|
24
24
|
var RNFBTest: boolean | undefined;
|
|
25
25
|
var RNFBDebugInTestLeakDetection: boolean | undefined;
|
|
26
26
|
var RNFBDebugLastTest: string | undefined;
|
|
27
|
-
|
|
28
|
-
// Modular API deprecation flags
|
|
29
|
-
var RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS: boolean | undefined;
|
|
30
|
-
var RNFB_MODULAR_DEPRECATION_STRICT_MODE: boolean | undefined;
|
|
31
27
|
}
|
|
32
28
|
|
|
33
29
|
export {};
|
package/lib/internal/index.ts
CHANGED
|
@@ -21,7 +21,7 @@ export { default as FirebaseModule } from './FirebaseModule';
|
|
|
21
21
|
export { default as NativeFirebaseError } from './NativeFirebaseError';
|
|
22
22
|
export * from './NativeModules';
|
|
23
23
|
export * from './registry/app';
|
|
24
|
-
export * from './registry/
|
|
24
|
+
export * from './registry/modular';
|
|
25
25
|
export * from './registry/nativeModule';
|
|
26
26
|
export { default as SharedEventEmitter } from './SharedEventEmitter';
|
|
27
27
|
export { Logger } from './logger';
|
|
@@ -1,30 +1,85 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
|
-
import {
|
|
2
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
3
|
+
|
|
4
|
+
const DYNAMIC_CONSTANT_KEYS = new Set(['androidPlayServices']);
|
|
5
|
+
|
|
6
|
+
const memoizedModuleConstants = new Map<string, Record<string, unknown>>();
|
|
7
|
+
const memoizedDebugProxies = new Map<string, Record<string, unknown>>();
|
|
8
|
+
|
|
9
|
+
function withTurboConstants(
|
|
10
|
+
moduleName: string,
|
|
11
|
+
module: Record<string, unknown> | undefined,
|
|
12
|
+
): Record<string, unknown> | undefined {
|
|
13
|
+
if (!module) {
|
|
14
|
+
return module;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const getConstants = module.getConstants;
|
|
18
|
+
if (typeof getConstants !== 'function') {
|
|
19
|
+
return module;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let constants = memoizedModuleConstants.get(moduleName);
|
|
23
|
+
if (!constants) {
|
|
24
|
+
constants = (getConstants as () => Record<string, unknown>).call(module) || {};
|
|
25
|
+
memoizedModuleConstants.set(moduleName, constants);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const descriptors: PropertyDescriptorMap = {};
|
|
29
|
+
for (const key of Object.keys(constants)) {
|
|
30
|
+
if (DYNAMIC_CONSTANT_KEYS.has(key)) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
descriptors[key] = {
|
|
34
|
+
value: constants[key],
|
|
35
|
+
enumerable: true,
|
|
36
|
+
writable: true,
|
|
37
|
+
configurable: true,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return Object.create(module, descriptors);
|
|
42
|
+
}
|
|
3
43
|
|
|
4
44
|
/**
|
|
5
|
-
*
|
|
6
|
-
* We additionally add a Proxy to the module to intercept calls
|
|
7
|
-
* and log them to the console for debugging purposes, if enabled.
|
|
8
|
-
* @param moduleName
|
|
9
|
-
* @returns Raw native module from React Native (object with methods/properties or undefined)
|
|
45
|
+
* Unified native module resolver — TurboModule only (NewArch-AD-6 Phase R).
|
|
10
46
|
*/
|
|
11
|
-
export function getReactNativeModule(moduleName: string): Record<string, unknown>
|
|
12
|
-
const
|
|
47
|
+
export function getReactNativeModule(moduleName: string): Record<string, unknown> {
|
|
48
|
+
const turboModule = TurboModuleRegistry.get(moduleName);
|
|
49
|
+
if (!turboModule) {
|
|
50
|
+
throw new Error(`Native module ${moduleName} is not registered.`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const nativeModule = withTurboConstants(
|
|
54
|
+
moduleName,
|
|
55
|
+
turboModule as Record<string, unknown>,
|
|
56
|
+
) as Record<string, unknown>;
|
|
57
|
+
|
|
13
58
|
if (!globalThis.RNFBDebug) {
|
|
14
59
|
return nativeModule;
|
|
15
60
|
}
|
|
16
|
-
|
|
61
|
+
|
|
62
|
+
let debugProxy = memoizedDebugProxies.get(moduleName);
|
|
63
|
+
if (debugProxy) {
|
|
64
|
+
return debugProxy;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
debugProxy = new Proxy(nativeModule as Record<string, unknown>, {
|
|
17
68
|
ownKeys(target) {
|
|
18
|
-
|
|
69
|
+
const keys: string[] = [];
|
|
70
|
+
for (const key in target) {
|
|
71
|
+
keys.push(key);
|
|
72
|
+
}
|
|
73
|
+
return keys;
|
|
19
74
|
},
|
|
20
75
|
get: (_, name) => {
|
|
21
|
-
const prop = nativeModule[name as string];
|
|
76
|
+
const prop = (nativeModule as Record<string, unknown>)[name as string];
|
|
22
77
|
if (typeof prop !== 'function') return prop;
|
|
23
78
|
return (...args: unknown[]) => {
|
|
24
79
|
console.debug(
|
|
25
80
|
`[RNFB->Native][🔵] ${moduleName}.${String(name)} -> ${JSON.stringify(args)}`,
|
|
26
81
|
);
|
|
27
|
-
const result: unknown = (prop as (...args: unknown[]) => unknown)(
|
|
82
|
+
const result: unknown = (prop as (...args: unknown[]) => unknown).apply(nativeModule, args);
|
|
28
83
|
if (result && typeof result === 'object' && 'then' in result) {
|
|
29
84
|
return (result as Promise<unknown>).then(
|
|
30
85
|
(res: unknown) => {
|
|
@@ -48,6 +103,8 @@ export function getReactNativeModule(moduleName: string): Record<string, unknown
|
|
|
48
103
|
};
|
|
49
104
|
},
|
|
50
105
|
});
|
|
106
|
+
memoizedDebugProxies.set(moduleName, debugProxy);
|
|
107
|
+
return debugProxy;
|
|
51
108
|
}
|
|
52
109
|
|
|
53
110
|
export function setReactNativeModule(): void {
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import RNFBAppModule from './web/RNFBAppModule';
|
|
3
|
+
import { APP_NATIVE_MODULE } from './constants';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
// Register before exporting getters — RNFBNativeEventEmitter instantiates during circular imports.
|
|
6
|
+
const nativeModuleRegistry: Record<string, Record<string, unknown>> = {
|
|
7
|
+
RNFBAppModule: RNFBAppModule as unknown as Record<string, unknown>,
|
|
8
|
+
[APP_NATIVE_MODULE]: RNFBAppModule as unknown as Record<string, unknown>,
|
|
9
|
+
};
|
|
5
10
|
|
|
6
11
|
export function getReactNativeModule(moduleName: string): Record<string, unknown> | undefined {
|
|
7
12
|
const nativeModule = nativeModuleRegistry[moduleName];
|
|
@@ -14,8 +19,11 @@ export function getReactNativeModule(moduleName: string): Record<string, unknown
|
|
|
14
19
|
}
|
|
15
20
|
return new Proxy(nativeModule, {
|
|
16
21
|
ownKeys(target) {
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
const keys: string[] = [];
|
|
23
|
+
for (const key in target) {
|
|
24
|
+
keys.push(key);
|
|
25
|
+
}
|
|
26
|
+
return keys;
|
|
19
27
|
},
|
|
20
28
|
get: (_, name) => {
|
|
21
29
|
const prop = nativeModule[name as string];
|
|
@@ -56,5 +64,3 @@ export function setReactNativeModule(
|
|
|
56
64
|
): void {
|
|
57
65
|
nativeModuleRegistry[moduleName] = nativeModule;
|
|
58
66
|
}
|
|
59
|
-
|
|
60
|
-
setReactNativeModule('RNFBAppModule', RNFBAppModule);
|
|
@@ -15,16 +15,7 @@
|
|
|
15
15
|
*
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import {
|
|
19
|
-
isIOS,
|
|
20
|
-
isOther,
|
|
21
|
-
isNull,
|
|
22
|
-
warnIfNotModularCall,
|
|
23
|
-
isObject,
|
|
24
|
-
isFunction,
|
|
25
|
-
isString,
|
|
26
|
-
isUndefined,
|
|
27
|
-
} from '../../common';
|
|
18
|
+
import { isIOS, isOther, isNull, isObject, isFunction, isString, isUndefined } from '../../common';
|
|
28
19
|
import FirebaseApp from '../../FirebaseApp';
|
|
29
20
|
import { DEFAULT_APP_NAME } from '../constants';
|
|
30
21
|
import { setReactNativeAsyncStorageInternal } from '../asyncStorage';
|
|
@@ -38,7 +29,7 @@ type ReactNativeAsyncStorage = ReactNativeFirebase.ReactNativeAsyncStorage;
|
|
|
38
29
|
|
|
39
30
|
const APP_REGISTRY: Record<string, FirebaseApp> = {};
|
|
40
31
|
let onAppCreateFn: ((app: FirebaseApp) => void) | null = null;
|
|
41
|
-
|
|
32
|
+
const onAppDestroyCallbacks: Array<(app: FirebaseApp) => void> = [];
|
|
42
33
|
let initializedNativeApps = false;
|
|
43
34
|
|
|
44
35
|
/**
|
|
@@ -50,11 +41,11 @@ export function setOnAppCreate(fn: (app: FirebaseApp) => void): void {
|
|
|
50
41
|
}
|
|
51
42
|
|
|
52
43
|
/**
|
|
53
|
-
*
|
|
44
|
+
* Registers an app-destroy listener.
|
|
54
45
|
* @param fn
|
|
55
46
|
*/
|
|
56
|
-
export function
|
|
57
|
-
|
|
47
|
+
export function addOnAppDestroy(fn: (app: FirebaseApp) => void): void {
|
|
48
|
+
onAppDestroyCallbacks.push(fn);
|
|
58
49
|
}
|
|
59
50
|
|
|
60
51
|
/**
|
|
@@ -93,7 +84,6 @@ export function initializeNativeApps(): void {
|
|
|
93
84
|
* @param name
|
|
94
85
|
*/
|
|
95
86
|
export function getApp(name: string = DEFAULT_APP_NAME): ReactNativeFirebase.FirebaseApp {
|
|
96
|
-
warnIfNotModularCall(arguments, 'getApp()');
|
|
97
87
|
if (!initializedNativeApps) {
|
|
98
88
|
initializeNativeApps();
|
|
99
89
|
}
|
|
@@ -110,7 +100,6 @@ export function getApp(name: string = DEFAULT_APP_NAME): ReactNativeFirebase.Fir
|
|
|
110
100
|
* Gets all app instances, used for `firebase.apps`
|
|
111
101
|
*/
|
|
112
102
|
export function getApps(): ReactNativeFirebase.FirebaseApp[] {
|
|
113
|
-
warnIfNotModularCall(arguments, 'getApps()');
|
|
114
103
|
if (!initializedNativeApps) {
|
|
115
104
|
initializeNativeApps();
|
|
116
105
|
}
|
|
@@ -126,7 +115,6 @@ export function initializeApp(
|
|
|
126
115
|
options: Partial<FirebaseAppOptions> = {},
|
|
127
116
|
configOrName?: string | FirebaseAppConfig,
|
|
128
117
|
): Promise<ReactNativeFirebase.FirebaseApp> {
|
|
129
|
-
warnIfNotModularCall(arguments, 'initializeApp()');
|
|
130
118
|
let appConfig: FirebaseAppConfig = configOrName as FirebaseAppConfig;
|
|
131
119
|
|
|
132
120
|
if (!isObject(configOrName) || isNull(configOrName)) {
|
|
@@ -220,7 +208,6 @@ export function initializeApp(
|
|
|
220
208
|
}
|
|
221
209
|
|
|
222
210
|
export function setLogLevel(logLevel: ReactNativeFirebase.LogLevelString): void {
|
|
223
|
-
warnIfNotModularCall(arguments, 'setLogLevel()');
|
|
224
211
|
if (!['error', 'warn', 'info', 'debug', 'verbose'].includes(logLevel)) {
|
|
225
212
|
throw new Error('LogLevel must be one of "error", "warn", "info", "debug", "verbose"');
|
|
226
213
|
}
|
|
@@ -233,8 +220,6 @@ export function setLogLevel(logLevel: ReactNativeFirebase.LogLevelString): void
|
|
|
233
220
|
}
|
|
234
221
|
|
|
235
222
|
export function setReactNativeAsyncStorage(asyncStorage: ReactNativeAsyncStorage): void {
|
|
236
|
-
warnIfNotModularCall(arguments, 'setReactNativeAsyncStorage()');
|
|
237
|
-
|
|
238
223
|
if (!isObject(asyncStorage)) {
|
|
239
224
|
throw new Error("setReactNativeAsyncStorage(*) 'asyncStorage' must be an object.");
|
|
240
225
|
}
|
|
@@ -272,7 +257,24 @@ export function deleteApp(name: string, nativeInitialized: boolean): Promise<voi
|
|
|
272
257
|
|
|
273
258
|
return nativeModule.deleteApp(name).then(() => {
|
|
274
259
|
(app as any)._deleted = true;
|
|
275
|
-
|
|
276
|
-
|
|
260
|
+
try {
|
|
261
|
+
for (let i = 0; i < onAppDestroyCallbacks.length; i++) {
|
|
262
|
+
try {
|
|
263
|
+
onAppDestroyCallbacks[i]?.(app);
|
|
264
|
+
} catch (e) {
|
|
265
|
+
// A failing destroy listener must not prevent the remaining listeners (or the
|
|
266
|
+
// registry cleanup below) from running. Surface it for diagnosis — partial cleanup
|
|
267
|
+
// here can leave a module's native/JS state stale for the deleted app.
|
|
268
|
+
// eslint-disable-next-line no-console
|
|
269
|
+
console.warn(
|
|
270
|
+
`Firebase: an onAppDestroy callback (index ${i}) for app '${name}' threw and was ` +
|
|
271
|
+
'skipped; remaining callbacks will still run. Inspect the offending listener:',
|
|
272
|
+
e,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} finally {
|
|
277
|
+
delete APP_REGISTRY[name];
|
|
278
|
+
}
|
|
277
279
|
});
|
|
278
280
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
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
|
+
|
|
18
|
+
import { DEFAULT_APP_NAME } from '../constants';
|
|
19
|
+
import type FirebaseModule from '../FirebaseModule';
|
|
20
|
+
import type { ReactNativeFirebase } from '../../types/app';
|
|
21
|
+
import type { ModuleConfig } from '../../types/internal';
|
|
22
|
+
import { addOnAppDestroy, getApp } from './app';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Constructor signature shared by every {@link FirebaseModule} subclass.
|
|
26
|
+
*/
|
|
27
|
+
type ModularModuleClass<T extends FirebaseModule> = new (
|
|
28
|
+
app: ReactNativeFirebase.FirebaseAppBase,
|
|
29
|
+
config: ModuleConfig,
|
|
30
|
+
customUrlOrRegion?: string | null,
|
|
31
|
+
) => T;
|
|
32
|
+
|
|
33
|
+
// app.name -> instanceKey -> module instance
|
|
34
|
+
const MODULAR_INSTANCES: Record<string, Record<string, FirebaseModule>> = {};
|
|
35
|
+
|
|
36
|
+
let destroyHookRegistered = false;
|
|
37
|
+
function ensureDestroyHook(): void {
|
|
38
|
+
if (destroyHookRegistered) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
destroyHookRegistered = true;
|
|
42
|
+
addOnAppDestroy(app => {
|
|
43
|
+
delete MODULAR_INSTANCES[app.name];
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Builds (and memoises per app) a Firebase service instance for the modular API.
|
|
49
|
+
*
|
|
50
|
+
* Each module's `index.ts` defines its own `ModuleClass` and `ModuleConfig` and calls this from
|
|
51
|
+
* `getX(app?)`.
|
|
52
|
+
*
|
|
53
|
+
* @param ModuleClass - The module's `FirebaseModule` subclass.
|
|
54
|
+
* @param config - Static `ModuleConfig` for the module (namespace, native module name, support flags).
|
|
55
|
+
* @param app - The `FirebaseApp` to use; defaults to the default app.
|
|
56
|
+
* @param customUrlOrRegion - Optional URL/region/databaseId for modules that support it.
|
|
57
|
+
* @returns The memoised module instance for that app + key.
|
|
58
|
+
*/
|
|
59
|
+
export function getOrCreateModularInstance<T extends FirebaseModule>(
|
|
60
|
+
ModuleClass: ModularModuleClass<T>,
|
|
61
|
+
config: ModuleConfig,
|
|
62
|
+
app?: ReactNativeFirebase.FirebaseApp,
|
|
63
|
+
customUrlOrRegion?: string | null,
|
|
64
|
+
): T {
|
|
65
|
+
ensureDestroyHook();
|
|
66
|
+
|
|
67
|
+
const _app = getApp(app?.name);
|
|
68
|
+
|
|
69
|
+
const { namespace, hasMultiAppSupport } = config;
|
|
70
|
+
|
|
71
|
+
// Modules such as analytics only run on the default app.
|
|
72
|
+
if (!hasMultiAppSupport && _app.name !== DEFAULT_APP_NAME) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
[
|
|
75
|
+
`You attempted to call "${namespace}" with a secondary Firebase App but; ${namespace} does not support multiple Firebase Apps.`,
|
|
76
|
+
'',
|
|
77
|
+
`Ensure you access ${namespace} from the default application only.`,
|
|
78
|
+
].join('\r\n'),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const key = customUrlOrRegion ? `${customUrlOrRegion}:${namespace}` : namespace;
|
|
83
|
+
|
|
84
|
+
if (!MODULAR_INSTANCES[_app.name]) {
|
|
85
|
+
MODULAR_INSTANCES[_app.name] = {};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!MODULAR_INSTANCES[_app.name]![key]) {
|
|
89
|
+
MODULAR_INSTANCES[_app.name]![key] = new ModuleClass(
|
|
90
|
+
_app as unknown as ReactNativeFirebase.FirebaseAppBase,
|
|
91
|
+
Object.assign({}, config),
|
|
92
|
+
customUrlOrRegion,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return MODULAR_INSTANCES[_app.name]![key] as T;
|
|
97
|
+
}
|