Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions .github/scripts/compare-types/configs/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/**
* Known differences between firebase-js-sdk @firebase/app and
* @react-native-firebase/app modular API.
*
* Each entry must have a `name` and a `reason`. Any undocumented
* difference or stale entry will fail `yarn compare:types`.
*/

import type { PackageConfig } from '../src/types';

const config: PackageConfig = {
nameMapping: {},

missingInRN: [
{
name: 'initializeServerApp',
reason:
'firebase-js-sdk server-side rendering entry point. Not applicable to React Native.',
},
{
name: 'FirebaseAppSettings',
reason:
'Settings type for firebase-js-sdk `FirebaseServerApp`. RN Firebase has no server-app API.',
},
{
name: 'FirebaseError',
reason:
'firebase-js-sdk base error class. RN Firebase uses `ReactNativeFirebase.NativeFirebaseError` from the native bridge instead.',
},
{
name: 'FirebaseOptions',
reason:
'firebase-js-sdk options interface. RN Firebase uses `ReactNativeFirebase.FirebaseAppOptions` (extends the same fields with RN-specific optional keys).',
},
{
name: 'FirebaseServerApp',
reason:
'firebase-js-sdk server-side app instance type. Not applicable to React Native.',
},
{
name: 'FirebaseServerAppSettings',
reason:
'Settings type for firebase-js-sdk server apps. Not applicable to React Native.',
},
],

extraInRN: [
{
name: 'setReactNativeAsyncStorage',
reason:
'RN Firebase-specific hook to wire `@react-native-async-storage/async-storage` into the firebase-js-sdk Other/Hermes persistence path.',
},
{
name: 'metaGetAll',
reason:
'RN Firebase native bridge helper — reads all entries from the native Firebase metadata store.',
},
{
name: 'jsonGetAll',
reason:
'RN Firebase native bridge helper — reads all entries from the native JSON config store.',
},
{
name: 'preferencesClearAll',
reason:
'RN Firebase native bridge helper — clears native shared preferences used by Firebase.',
},
{
name: 'preferencesGetAll',
reason:
'RN Firebase native bridge helper — reads all native shared preference entries.',
},
{
name: 'preferencesSetBool',
reason:
'RN Firebase native bridge helper — sets a native boolean preference.',
},
{
name: 'preferencesSetString',
reason:
'RN Firebase native bridge helper — sets a native string preference.',
},
{
name: 'getUtils',
reason:
'RN Firebase entry point for the native Utils module (Play Services, file paths, etc.). No firebase-js-sdk modular equivalent.',
},
{
name: 'FilePath',
reason:
'RN Firebase native device file-path constants for Storage and similar file-based APIs.',
},
{
name: 'LogCallbackParams',
reason:
'RN Firebase log-handler callback payload type exported for modular `setLogLevel` wiring.',
},
{
name: 'LogCallback',
reason:
'RN Firebase log-handler callback type exported for modular logging configuration.',
},
{
name: 'LogOptions',
reason:
'RN Firebase log-handler options type exported for modular logging configuration.',
},
],

differentShape: [
{
name: 'deleteApp',
reason:
'Parameter type is `ReactNativeFirebase.FirebaseApp` instead of firebase-js-sdk `FirebaseApp`. Runtime behavior matches.',
},
{
name: 'getApp',
reason:
'Return type is `ReactNativeFirebase.FirebaseApp` instead of firebase-js-sdk `FirebaseApp`. Runtime behavior matches.',
},
{
name: 'getApps',
reason:
'Return type is `ReactNativeFirebase.FirebaseApp[]` instead of firebase-js-sdk `FirebaseApp[]`. Runtime behavior matches.',
},
{
name: 'initializeApp',
reason:
'Returns `Promise<ReactNativeFirebase.FirebaseApp>` because initialization crosses the native bridge. Accepts `ReactNativeFirebase.FirebaseAppOptions` and optional `ReactNativeFirebase.FirebaseAppConfig` (name / auth domain) instead of firebase-js-sdk `(FirebaseOptions, string)` only.',
},
{
name: 'registerVersion',
reason:
'Returns `Promise<void>` in RN Firebase vs `void` in firebase-js-sdk. Bridge-forced async today — Phase S sync-conversion candidate when native work is in-memory only.',
},
{
name: 'setLogLevel',
reason:
'Parameter type is `ReactNativeFirebase.LogLevelString` instead of firebase-js-sdk `LogLevelString`. Accepted values match (`debug`, `verbose`, `info`, `warn`, `error`, `silent`).',
},
{
name: 'FirebaseApp',
reason:
'RN Firebase exports the `ReactNativeFirebase.FirebaseApp` class/interface from shared app declarations instead of re-exporting firebase-js-sdk `FirebaseApp`.',
},
],
};

export default config;
15 changes: 15 additions & 0 deletions .github/scripts/compare-types/src/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import remoteConfigConfig from '../configs/remote-config';
import authConfig from '../configs/auth';
import installationsConfig from '../configs/installations';
import perfConfig from '../configs/perf-config';
import appConfig from '../configs/app';

const REPO_ROOT = path.resolve(__dirname, '..', '..', '..', '..');

Expand Down Expand Up @@ -103,6 +104,20 @@ function optionalFirebasePackage(
}

export const packages: PackageEntry[] = [
{
name: 'app',
firebaseSdkTypesPaths: [requiredFirebaseTypes('app')],
rnFirebaseModularFiles: [
path.join(rnDist('app'), 'modular.d.ts'),
path.join(rnDist('app'), 'index.d.ts'),
],
rnFirebaseSupportFiles: [
path.join(rnDist('app'), 'types', 'app.d.ts'),
path.join(rnDist('app'), 'types', 'internal.d.ts'),
path.join(rnDist('app'), 'FirebaseApp.d.ts'),
],
config: appConfig,
},
{
name: 'auth',
firebaseSdkTypesPaths: [requiredFirebaseTypes('auth')],
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,8 @@ tests/ios/resetXcode.sh
google-services.json
GoogleService-Info.plist

tests/harness.overrides.js

# generated files
RNFBVersion.m
ReactNativeFirebaseVersion.java
Expand Down
126 changes: 119 additions & 7 deletions jest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ jest.doMock('react-native', () => {
OS: 'android',
select: () => {},
},
TurboModuleRegistry: {
get: jest.fn(() => undefined),
getEnforcing: jest.fn(() => {
throw new Error('TurboModuleRegistry.getEnforcing: module not found');
}),
},
AppRegistry: {
registerHeadlessTask: jest.fn(),
},
Expand All @@ -54,6 +60,73 @@ jest.doMock('react-native', () => {
initiateOnDeviceConversionMeasurementWithPhoneNumber: jest.fn(),
initiateOnDeviceConversionMeasurementWithHashedPhoneNumber: jest.fn(),
},
NativeRNFBTurboApp: {
getConstants: () => ({
NATIVE_FIREBASE_APPS: [
{
appConfig: {
name: '[DEFAULT]',
},
options: {},
},
{
appConfig: {
name: 'secondaryFromNative',
},
options: {},
},
],
FIREBASE_RAW_JSON: '{}',
}),
NATIVE_FIREBASE_APPS: [
{
appConfig: {
name: '[DEFAULT]',
},
options: {},
},

{
appConfig: {
name: 'secondaryFromNative',
},
options: {},
},
],
FIREBASE_RAW_JSON: '{}',
addListener: jest.fn(),
eventsAddListener: jest.fn(),
eventsNotifyReady: jest.fn(),
removeListeners: jest.fn(),
},
NativeRNFBTurboUtils: {
getConstants: () => ({
isRunningInTestLab: false,
MAIN_BUNDLE: '/',
CACHES_DIRECTORY: '/cache',
DOCUMENT_DIRECTORY: '/documents',
TEMP_DIRECTORY: '/tmp',
LIBRARY_DIRECTORY: '/library',
PICTURES_DIRECTORY: '/pictures',
MOVIES_DIRECTORY: '/movies',
}),
isRunningInTestLab: false,
MAIN_BUNDLE: '/',
CACHES_DIRECTORY: '/cache',
DOCUMENT_DIRECTORY: '/documents',
TEMP_DIRECTORY: '/tmp',
LIBRARY_DIRECTORY: '/library',
PICTURES_DIRECTORY: '/pictures',
MOVIES_DIRECTORY: '/movies',
androidGetPlayServicesStatus: jest.fn(() =>
Promise.resolve({
isAvailable: true,
status: 0,
hasResolution: false,
isUserResolvableError: false,
}),
),
},
RNFBAppModule: {
NATIVE_FIREBASE_APPS: [
{
Expand Down Expand Up @@ -138,7 +211,7 @@ jest.doMock('react-native', () => {
addAppCheckListener: jest.fn(),
removeAppCheckListener: jest.fn(),
},
RNFBAppDistributionModule: {
NativeRNFBTurboAppDistribution: {
isTesterSignedIn: jest.fn(),
signInTester: jest.fn(),
checkForUpdate: jest.fn(),
Expand Down Expand Up @@ -211,7 +284,8 @@ jest.doMock('react-native', () => {
),
getServerTime: jest.fn((_appName: any, _customUrl: any) => Promise.resolve(Date.now())),
},
RNFBFirestoreModule: {
NativeRNFBTurboFirestore: {
setLogLevel: jest.fn(),
loadBundle: jest.fn(() =>
Promise.resolve({
taskState: 'Success',
Expand All @@ -230,9 +304,20 @@ jest.doMock('react-native', () => {
settings: jest.fn(),
addSnapshotsInSync: jest.fn(),
removeSnapshotsInSync: jest.fn(),
persistenceCacheIndexManager: jest.fn(),
},
NativeRNFBTurboFirestoreCollection: {
collectionOffSnapshot: jest.fn(),
namedQueryOnSnapshot: jest.fn(),
collectionOnSnapshot: jest.fn(),
namedQueryGet: jest.fn(() =>
Promise.resolve({
source: 'cache',
changes: [],
documents: [],
metadata: {},
}),
),
collectionGet: jest.fn(() =>
Promise.resolve({
source: 'cache',
Expand All @@ -242,6 +327,15 @@ jest.doMock('react-native', () => {
}),
),
collectionCount: jest.fn(() => Promise.resolve({ count: 0 })),
aggregateQuery: jest.fn(() => Promise.resolve({})),
pipelineExecute: jest.fn(() =>
Promise.resolve({
results: [],
executionTime: Date.now(),
}),
),
},
NativeRNFBTurboFirestoreDocument: {
documentDelete: jest.fn(() => Promise.resolve()),
documentOffSnapshot: jest.fn(),
documentOnSnapshot: jest.fn(),
Expand All @@ -255,23 +349,36 @@ jest.doMock('react-native', () => {
),
documentSet: jest.fn(() => Promise.resolve()),
documentUpdate: jest.fn(() => Promise.resolve()),
persistenceCacheIndexManager: jest.fn(),
documentBatch: jest.fn(),
},
NativeRNFBTurboFirestoreTransaction: {
transactionApplyBuffer: jest.fn(),
transactionBegin: jest.fn(),
transactionDispose: jest.fn(),
transactionGetDocument: jest.fn(() =>
Promise.resolve({
data: {},
metadata: {},
path: 'firestore/document',
exists: true,
}),
),
},
RNFBFiamModule: {
NativeRNFBTurboFiam: {
getConstants: () => ({
isMessagesDisplaySuppressed: false,
isAutomaticDataCollectionEnabled: true,
}),
isMessagesDisplaySuppressed: false,
isAutomaticDataCollectionEnabled: true,
setMessagesDisplaySuppressed: jest.fn(),
setAutomaticDataCollectionEnabled: jest.fn(),
triggerEvent: jest.fn(),
},
RNFBInstallationsModule: {
NativeRNFBTurboInstallations: {
getId: jest.fn(),
getToken: jest.fn(),
delete: jest.fn(),
deleteInstallations: jest.fn(),
},
RNFBMessagingModule: {
isAutoInitEnabled: true,
Expand Down Expand Up @@ -299,7 +406,11 @@ jest.doMock('react-native', () => {
setDeliveryMetricsExportToBigQuery: jest.fn(),
setNotificationDelegationEnabled: jest.fn(),
},
RNFBPerfModule: {
NativeRNFBTurboPerf: {
getConstants: () => ({
isPerformanceCollectionEnabled: true,
isInstrumentationEnabled: true,
}),
isPerformanceCollectionEnabled: true,
isInstrumentationEnabled: true,
instrumentationEnabled: jest.fn(() => Promise.resolve()),
Expand All @@ -311,6 +422,7 @@ jest.doMock('react-native', () => {
startHttpMetric: jest.fn(() => Promise.resolve()),
stopHttpMetric: jest.fn(() => Promise.resolve()),
},
NativeRNFBTurboML: {},
RNFBConfigModule: {
onConfigUpdated: jest.fn(),
reset: jest.fn(() =>
Expand Down
Loading
Loading