From 423b3e91521f9ee859017b09074db6668893007f Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 12 Feb 2026 15:46:54 +0000 Subject: [PATCH 01/24] refactor: match AppCheck with firebase-js-sdk --- packages/app-check/lib/types/appcheck.ts | 106 ++------------------- packages/app-check/lib/types/internal.ts | 113 +++++++++++++++++++++++ 2 files changed, 119 insertions(+), 100 deletions(-) create mode 100644 packages/app-check/lib/types/internal.ts diff --git a/packages/app-check/lib/types/appcheck.ts b/packages/app-check/lib/types/appcheck.ts index e26c72bb29..0d466d0d56 100644 --- a/packages/app-check/lib/types/appcheck.ts +++ b/packages/app-check/lib/types/appcheck.ts @@ -206,109 +206,15 @@ export type ProviderWithOptions = // ============ Module Interface ============ /** - * App Check module instance - returned from firebase.appCheck() or firebase.app().appCheck() + * The Firebase App Check service interface. + * + * @public */ -export interface AppCheck extends ReactNativeFirebase.FirebaseModule { - /** The FirebaseApp this module is associated with */ - app: ReactNativeFirebase.FirebaseApp; - - /** - * Create a ReactNativeFirebaseAppCheckProvider option for use in react-native-firebase - */ - newReactNativeFirebaseAppCheckProvider(): ReactNativeFirebaseAppCheckProvider; - - /** - * Initialize the AppCheck module. Note that in react-native-firebase AppCheckOptions must always - * be an object with a `provider` member containing `ReactNativeFirebaseAppCheckProvider` that has returned successfully - * from a call to the `configure` method, with sub-providers for the various platforms configured to meet your project - * requirements. This must be called prior to interacting with any firebase services protected by AppCheck - * - * @param options an AppCheckOptions with a configured ReactNativeFirebaseAppCheckProvider as the provider - */ - initializeAppCheck(options: AppCheckOptions): Promise; - - /** - * Activate App Check - * On iOS App Check is activated with DeviceCheck provider simply by including the module, using the token auto refresh default or - * the specific value (if configured) in firebase.json, but calling this does no harm. - * On Android if you call this it will install the PlayIntegrity provider in release builds, the Debug provider if debuggable. - * On both platforms you may use this method to alter the token refresh setting after startup. - * On iOS if you want to set a specific AppCheckProviderFactory (for instance to FIRAppCheckDebugProviderFactory or - * FIRAppAttestProvider) you must manually do that in your AppDelegate.m prior to calling [FIRApp configure] - * - * @deprecated use initializeAppCheck to gain access to all platform providers and firebase-js-sdk v9 compatibility - * @param siteKeyOrProvider - This is ignored, Android uses DebugProviderFactory if the app is debuggable (https://firebase.google.com/docs/app-check/android/debug-provider) - * Android uses PlayIntegrityProviderFactory for release builds. - * iOS uses DeviceCheckProviderFactory by default unless altered in AppDelegate.m manually - * @param isTokenAutoRefreshEnabled - If true, enables SDK to automatically - * refresh AppCheck token as needed. If undefined, the value will default - * to the value of `app.automaticDataCollectionEnabled`. That property - * defaults to false and can be set in the app config. - */ - activate( - siteKeyOrProvider: string | AppCheckProvider, - isTokenAutoRefreshEnabled?: boolean, - ): Promise; - - /** - * Alter the token auto refresh setting. By default it will take the value of automaticDataCollectionEnabled from Info.plist / AndroidManifest.xml - * @param isTokenAutoRefreshEnabled - If true, the SDK automatically - * refreshes App Check tokens as needed. This overrides any value set - * during `activate()` or taken by default from automaticDataCollectionEnabled in plist / android manifest - */ - setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled: boolean): void; - - /** - * Requests Firebase App Check token. - * This method should only be used if you need to authorize requests to a non-Firebase backend. - * Requests to Firebase backend are authorized automatically if configured. - * - * @param forceRefresh - If true, a new Firebase App Check token is requested and the token cache is ignored. - * If false, the cached token is used if it exists and has not expired yet. - * In most cases, false should be used. True should only be used if the server explicitly returns an error, indicating a revoked token. - */ - getToken(forceRefresh?: boolean): Promise; - - /** - * Requests a Firebase App Check token. This method should be used only if you need to authorize requests - * to a non-Firebase backend. Returns limited-use tokens that are intended for use with your non-Firebase - * backend endpoints that are protected with Replay Protection (https://firebase.google.com/docs/app-check/custom-resource-backend#replay-protection). - * This method does not affect the token generation behavior of the getAppCheckToken() method. - */ - getLimitedUseToken(): Promise; - - /** - * Registers a listener to changes in the token state. There can be more - * than one listener registered at the same time for one or more - * App Check instances. The listeners call back on the UI thread whenever - * the current token associated with this App Check instance changes. - * - * @returns A function that unsubscribes this listener. - */ - onTokenChanged(observer: PartialObserver): () => void; - +export interface AppCheck { /** - * Registers a listener to changes in the token state. There can be more - * than one listener registered at the same time for one or more - * App Check instances. The listeners call back on the UI thread whenever - * the current token associated with this App Check instance changes. - * - * Token listeners do not exist in the native SDK for iOS, no token change events will be emitted on that platform. - * This is not yet implemented on Android, no token change events will be emitted until implemented. - * - * NOTE: Although an `onError` callback can be provided, it will - * never be called, Android sdk code doesn't provide handling for onError function - * - * NOTE: Although an `onCompletion` callback can be provided, it will - * never be called because the token stream is never-ending. - * - * @returns A function that unsubscribes this listener. + * this `AppCheck` instance is associated with this FirebaseApp. */ - onTokenChanged( - onNext: (tokenResult: AppCheckListenerResult) => void, - onError?: (error: Error) => void, - onCompletion?: () => void, - ): () => void; + app: FirebaseApp; } // ============ Statics Interface ============ diff --git a/packages/app-check/lib/types/internal.ts b/packages/app-check/lib/types/internal.ts new file mode 100644 index 0000000000..75d36ad41c --- /dev/null +++ b/packages/app-check/lib/types/internal.ts @@ -0,0 +1,113 @@ +import type { FirebaseApp } from '@react-native-firebase/app'; +import type { + AppCheck, + AppCheckListenerResult, + AppCheckOptions, + AppCheckProvider, + AppCheckTokenResult, + PartialObserver, + ReactNativeFirebaseAppCheckProvider, +} from './appcheck'; + +export type AppCheckInternal = AppCheck & { + /** The FirebaseApp this module is associated with */ + app: FirebaseApp; + + /** + * Create a ReactNativeFirebaseAppCheckProvider option for use in react-native-firebase + */ + newReactNativeFirebaseAppCheckProvider(): ReactNativeFirebaseAppCheckProvider; + + /** + * Initialize the AppCheck module. Note that in react-native-firebase AppCheckOptions must always + * be an object with a `provider` member containing `ReactNativeFirebaseAppCheckProvider` that has returned successfully + * from a call to the `configure` method, with sub-providers for the various platforms configured to meet your project + * requirements. This must be called prior to interacting with any firebase services protected by AppCheck + * + * @param options an AppCheckOptions with a configured ReactNativeFirebaseAppCheckProvider as the provider + */ + initializeAppCheck(options: AppCheckOptions): Promise; + + /** + * Activate App Check + * On iOS App Check is activated with DeviceCheck provider simply by including the module, using the token auto refresh default or + * the specific value (if configured) in firebase.json, but calling this does no harm. + * On Android if you call this it will install the PlayIntegrity provider in release builds, the Debug provider if debuggable. + * On both platforms you may use this method to alter the token refresh setting after startup. + * On iOS if you want to set a specific AppCheckProviderFactory (for instance to FIRAppCheckDebugProviderFactory or + * FIRAppAttestProvider) you must manually do that in your AppDelegate.m prior to calling [FIRApp configure] + * + * @deprecated use initializeAppCheck to gain access to all platform providers and firebase-js-sdk v9 compatibility + * @param siteKeyOrProvider - This is ignored, Android uses DebugProviderFactory if the app is debuggable (https://firebase.google.com/docs/app-check/android/debug-provider) + * Android uses PlayIntegrityProviderFactory for release builds. + * iOS uses DeviceCheckProviderFactory by default unless altered in AppDelegate.m manually + * @param isTokenAutoRefreshEnabled - If true, enables SDK to automatically + * refresh AppCheck token as needed. If undefined, the value will default + * to the value of `app.automaticDataCollectionEnabled`. That property + * defaults to false and can be set in the app config. + */ + activate( + siteKeyOrProvider: string | AppCheckProvider, + isTokenAutoRefreshEnabled?: boolean, + ): Promise; + + /** + * Alter the token auto refresh setting. By default it will take the value of automaticDataCollectionEnabled from Info.plist / AndroidManifest.xml + * @param isTokenAutoRefreshEnabled - If true, the SDK automatically + * refreshes App Check tokens as needed. This overrides any value set + * during `activate()` or taken by default from automaticDataCollectionEnabled in plist / android manifest + */ + setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled: boolean): void; + + /** + * Requests Firebase App Check token. + * This method should only be used if you need to authorize requests to a non-Firebase backend. + * Requests to Firebase backend are authorized automatically if configured. + * + * @param forceRefresh - If true, a new Firebase App Check token is requested and the token cache is ignored. + * If false, the cached token is used if it exists and has not expired yet. + * In most cases, false should be used. True should only be used if the server explicitly returns an error, indicating a revoked token. + */ + getToken(forceRefresh?: boolean): Promise; + + /** + * Requests a Firebase App Check token. This method should be used only if you need to authorize requests + * to a non-Firebase backend. Returns limited-use tokens that are intended for use with your non-Firebase + * backend endpoints that are protected with Replay Protection (https://firebase.google.com/docs/app-check/custom-resource-backend#replay-protection). + * This method does not affect the token generation behavior of the getAppCheckToken() method. + */ + getLimitedUseToken(): Promise; + + /** + * Registers a listener to changes in the token state. There can be more + * than one listener registered at the same time for one or more + * App Check instances. The listeners call back on the UI thread whenever + * the current token associated with this App Check instance changes. + * + * @returns A function that unsubscribes this listener. + */ + onTokenChanged(observer: PartialObserver): () => void; + + /** + * Registers a listener to changes in the token state. There can be more + * than one listener registered at the same time for one or more + * App Check instances. The listeners call back on the UI thread whenever + * the current token associated with this App Check instance changes. + * + * Token listeners do not exist in the native SDK for iOS, no token change events will be emitted on that platform. + * This is not yet implemented on Android, no token change events will be emitted until implemented. + * + * NOTE: Although an `onError` callback can be provided, it will + * never be called, Android sdk code doesn't provide handling for onError function + * + * NOTE: Although an `onCompletion` callback can be provided, it will + * never be called because the token stream is never-ending. + * + * @returns A function that unsubscribes this listener. + */ + onTokenChanged( + onNext: (tokenResult: AppCheckListenerResult) => void, + onError?: (error: Error) => void, + onCompletion?: () => void, + ): () => void; +}; From 54355501ae4ead9bdbde82c29ee4702c7424aa10 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 12 Feb 2026 15:48:48 +0000 Subject: [PATCH 02/24] refactor: modular should use internal AppCheck type --- packages/app-check/lib/modular.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/app-check/lib/modular.ts b/packages/app-check/lib/modular.ts index 9c867f5f70..12e97ac7c8 100644 --- a/packages/app-check/lib/modular.ts +++ b/packages/app-check/lib/modular.ts @@ -27,6 +27,7 @@ import type { Unsubscribe, AppCheckListenerResult, } from './types/appcheck'; +import type { AppCheckInternal } from './types/internal'; /** * Activate App Check for the given app. Can be called only once per app. @@ -63,7 +64,7 @@ export function getToken( appCheckInstance: AppCheck, forceRefresh?: boolean, ): Promise { - return appCheckInstance.getToken.call( + return (appCheckInstance as AppCheckInternal).getToken.call( appCheckInstance, forceRefresh, // @ts-ignore - Extra arg used by deprecation proxy to detect modular calls @@ -78,7 +79,7 @@ export function getToken( * @returns Promise */ export function getLimitedUseToken(appCheckInstance: AppCheck): Promise { - return appCheckInstance.getLimitedUseToken.call( + return (appCheckInstance as AppCheckInternal).getLimitedUseToken.call( appCheckInstance, // @ts-ignore - Extra arg used by deprecation proxy to detect modular calls MODULAR_DEPRECATION_ARG, @@ -94,7 +95,7 @@ export function setTokenAutoRefreshEnabled( appCheckInstance: AppCheck, isAutoRefreshEnabled: boolean, ): void { - appCheckInstance.setTokenAutoRefreshEnabled.call( + (appCheckInstance as AppCheckInternal).setTokenAutoRefreshEnabled.call( appCheckInstance, isAutoRefreshEnabled, // @ts-ignore - Extra arg used by deprecation proxy to detect modular calls @@ -144,7 +145,7 @@ export function onTokenChanged( onError?: (error: Error) => void, onCompletion?: () => void, ): Unsubscribe { - return appCheckInstance.onTokenChanged.call( + return (appCheckInstance as AppCheckInternal).onTokenChanged.call( appCheckInstance, onNextOrObserver, onError, From 2b63dbfdc299848f7f24370c9e7dd63d302964a8 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 12 Feb 2026 16:05:43 +0000 Subject: [PATCH 03/24] chore: use AppCheckInternal in modular and remove ts-ignore for MODULAR_DEPRECATION_ARG --- packages/app-check/lib/modular.ts | 63 ++++++++++++++++++------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/packages/app-check/lib/modular.ts b/packages/app-check/lib/modular.ts index 12e97ac7c8..eccc4fb44d 100644 --- a/packages/app-check/lib/modular.ts +++ b/packages/app-check/lib/modular.ts @@ -15,7 +15,7 @@ * */ -import { getApp, type ReactNativeFirebase } from '@react-native-firebase/app'; +import { getApp, type FirebaseApp, type ReactNativeFirebase } from '@react-native-firebase/app'; import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; import ReactNativeFirebaseAppCheckProvider from './ReactNativeFirebaseAppCheckProvider'; @@ -29,6 +29,10 @@ import type { } from './types/appcheck'; import type { AppCheckInternal } from './types/internal'; +type WithModularDeprecationArg = F extends (...args: infer P) => infer R + ? (...args: [...P, typeof MODULAR_DEPRECATION_ARG]) => R + : never; + /** * Activate App Check for the given app. Can be called only once per app. * @param app - The app to initialize App Check for. Optional. @@ -40,16 +44,22 @@ export async function initializeAppCheck( options?: AppCheckOptions, ): Promise { if (app) { - const appInstance = getApp(app.name) as ReactNativeFirebase.FirebaseApp; + const appInstance = getApp(app.name) as FirebaseApp; const appCheck = appInstance.appCheck(); - // @ts-ignore - Extra arg used by deprecation proxy to detect modular calls - await appCheck.initializeAppCheck.call(appCheck, options, MODULAR_DEPRECATION_ARG); + await ( + (appCheck as AppCheckInternal).initializeAppCheck as WithModularDeprecationArg< + AppCheckInternal['initializeAppCheck'] + > + ).call(appCheck, options as AppCheckOptions, MODULAR_DEPRECATION_ARG); return appCheck; } - const appInstance = getApp() as ReactNativeFirebase.FirebaseApp; + const appInstance = getApp() as FirebaseApp; const appCheck = appInstance.appCheck(); - // @ts-ignore - Extra arg used by deprecation proxy to detect modular calls - await appCheck.initializeAppCheck.call(appCheck, options, MODULAR_DEPRECATION_ARG); + await ( + (appCheck as AppCheckInternal).initializeAppCheck as WithModularDeprecationArg< + AppCheckInternal['initializeAppCheck'] + > + ).call(appCheck, options as AppCheckOptions, MODULAR_DEPRECATION_ARG); return appCheck; } @@ -64,12 +74,11 @@ export function getToken( appCheckInstance: AppCheck, forceRefresh?: boolean, ): Promise { - return (appCheckInstance as AppCheckInternal).getToken.call( - appCheckInstance, - forceRefresh, - // @ts-ignore - Extra arg used by deprecation proxy to detect modular calls - MODULAR_DEPRECATION_ARG, - ) as Promise; + return ( + (appCheckInstance as AppCheckInternal).getToken as WithModularDeprecationArg< + AppCheckInternal['getToken'] + > + ).call(appCheckInstance, forceRefresh, MODULAR_DEPRECATION_ARG) as Promise; } /** @@ -79,11 +88,11 @@ export function getToken( * @returns Promise */ export function getLimitedUseToken(appCheckInstance: AppCheck): Promise { - return (appCheckInstance as AppCheckInternal).getLimitedUseToken.call( - appCheckInstance, - // @ts-ignore - Extra arg used by deprecation proxy to detect modular calls - MODULAR_DEPRECATION_ARG, - ) as Promise; + return ( + (appCheckInstance as AppCheckInternal).getLimitedUseToken as WithModularDeprecationArg< + AppCheckInternal['getLimitedUseToken'] + > + ).call(appCheckInstance, MODULAR_DEPRECATION_ARG) as Promise; } /** @@ -95,12 +104,11 @@ export function setTokenAutoRefreshEnabled( appCheckInstance: AppCheck, isAutoRefreshEnabled: boolean, ): void { - (appCheckInstance as AppCheckInternal).setTokenAutoRefreshEnabled.call( - appCheckInstance, - isAutoRefreshEnabled, - // @ts-ignore - Extra arg used by deprecation proxy to detect modular calls - MODULAR_DEPRECATION_ARG, - ); + ( + (appCheckInstance as AppCheckInternal).setTokenAutoRefreshEnabled as WithModularDeprecationArg< + AppCheckInternal['setTokenAutoRefreshEnabled'] + > + ).call(appCheckInstance, isAutoRefreshEnabled, MODULAR_DEPRECATION_ARG); } /** @@ -145,12 +153,15 @@ export function onTokenChanged( onError?: (error: Error) => void, onCompletion?: () => void, ): Unsubscribe { - return (appCheckInstance as AppCheckInternal).onTokenChanged.call( + return ( + (appCheckInstance as AppCheckInternal).onTokenChanged as WithModularDeprecationArg< + AppCheckInternal['onTokenChanged'] + > + ).call( appCheckInstance, onNextOrObserver, onError, onCompletion, - // @ts-ignore - Extra arg used by deprecation proxy to detect modular calls MODULAR_DEPRECATION_ARG, ) as Unsubscribe; } From bda105bef416264ba44f1796fb2081b602d19ba2 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 12 Feb 2026 17:47:28 +0000 Subject: [PATCH 04/24] refactor: namespaced.ts using previous index.d.ts + update modular appcheck.ts type so modular only --- packages/app-check/lib/types/appcheck.ts | 68 +--- packages/app-check/lib/types/namespaced.ts | 378 +++++++++++++++++++++ 2 files changed, 379 insertions(+), 67 deletions(-) create mode 100644 packages/app-check/lib/types/namespaced.ts diff --git a/packages/app-check/lib/types/appcheck.ts b/packages/app-check/lib/types/appcheck.ts index 0d466d0d56..a368a3a174 100644 --- a/packages/app-check/lib/types/appcheck.ts +++ b/packages/app-check/lib/types/appcheck.ts @@ -15,7 +15,7 @@ * */ -import type { ReactNativeFirebase } from '@react-native-firebase/app'; +import type { FirebaseApp } from '@react-native-firebase/app'; // ============ Provider Types ============ @@ -203,8 +203,6 @@ export type ProviderWithOptions = | ReactNativeFirebaseAppCheckProvider | ReactNativeFirebaseAppCheckProviderConfig; -// ============ Module Interface ============ - /** * The Firebase App Check service interface. * @@ -226,67 +224,3 @@ export interface AppCheckStatics { CustomProvider: new (customProviderOptions: CustomProviderOptions) => CustomProvider; SDK_VERSION: string; } - -/** - * FirebaseApp type with appCheck() method. - * @deprecated Import FirebaseApp from '@react-native-firebase/app' instead. - * The appCheck() method is added via module augmentation. - */ -export type FirebaseApp = ReactNativeFirebase.FirebaseApp; - -// ============ Module Augmentation ============ - -/* eslint-disable @typescript-eslint/no-namespace */ -declare module '@react-native-firebase/app' { - namespace ReactNativeFirebase { - interface Module { - appCheck: FirebaseModuleWithStaticsAndApp; - } - interface FirebaseApp { - appCheck(): AppCheck; - } - } -} -/* eslint-enable @typescript-eslint/no-namespace */ - -// ============ Backwards Compatibility Namespace ============ - -// Helper types to reference outer scope types within the namespace -// These are needed because TypeScript can't directly alias types with the same name -type _AppCheckProvider = AppCheckProvider; -type _CustomProviderOptions = CustomProviderOptions; -type _AppCheckOptions = AppCheckOptions; -type _AppCheckToken = AppCheckToken; -type _AppCheckTokenResult = AppCheckTokenResult; -type _AppCheckListenerResult = AppCheckListenerResult; -type _AppCheck = AppCheck; -type _AppCheckStatics = AppCheckStatics; - -/** - * @deprecated Use the exported types directly instead. - * FirebaseAppCheckTypes namespace is kept for backwards compatibility. - */ -/* eslint-disable @typescript-eslint/no-namespace */ -export namespace FirebaseAppCheckTypes { - // Short name aliases referencing top-level types - export type Provider = AppCheckProvider; - export type ProviderOptions = CustomProviderOptions; - export type Options = AppCheckOptions; - export type Token = AppCheckToken; - export type TokenResult = AppCheckTokenResult; - export type ListenerResult = AppCheckListenerResult; - export type Statics = AppCheckStatics; - export type Module = AppCheck; - - // AppCheck* aliases that reference the exported types above via helper types - // These provide backwards compatibility for code using FirebaseAppCheckTypes.AppCheckProvider - export type AppCheckProvider = _AppCheckProvider; - export type CustomProviderOptions = _CustomProviderOptions; - export type AppCheckOptions = _AppCheckOptions; - export type AppCheckToken = _AppCheckToken; - export type AppCheckTokenResult = _AppCheckTokenResult; - export type AppCheckListenerResult = _AppCheckListenerResult; - export type AppCheck = _AppCheck; - export type AppCheckStatics = _AppCheckStatics; -} -/* eslint-enable @typescript-eslint/no-namespace */ diff --git a/packages/app-check/lib/types/namespaced.ts b/packages/app-check/lib/types/namespaced.ts new file mode 100644 index 0000000000..c16f959bc2 --- /dev/null +++ b/packages/app-check/lib/types/namespaced.ts @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import type { ReactNativeFirebase } from '@react-native-firebase/app'; + +/** + * Firebase App Check package for React Native. + * + * #### Example 1 + * + * Access the firebase export from the `appCheck` package: + * + * ```js + * import { firebase } from '@react-native-firebase/app-check'; + * + * // firebase.appCheck().X + * ``` + * + * #### Example 2 + * + * Using the default export from the `appCheck` package: + * + * ```js + * import appCheck from '@react-native-firebase/app-check'; + * + * // appCheck().X + * ``` + * + * #### Example 3 + * + * Using the default export from the `app` package: + * + * ```js + * import firebase from '@react-native-firebase/app'; + * import '@react-native-firebase/app-check'; + * + * // firebase.appCheck().X + * ``` + * + * @firebase app-check + */ +/* eslint-disable @typescript-eslint/no-namespace */ +export namespace FirebaseAppCheckTypes { + type FirebaseModule = ReactNativeFirebase.FirebaseModule; + + /** + * An App Check provider. This can be either the built-in reCAPTCHA provider + * or a custom provider. For more on custom providers, see + * https://firebase.google.com/docs/app-check/web-custom-provider + */ + export interface AppCheckProvider { + /** + * Returns an AppCheck token. + */ + getToken(): Promise; + } + + /** + * Custom provider class. + * @public + */ + export declare class CustomProvider implements AppCheckProvider { + constructor(customProviderOptions: CustomProviderOptions); + getToken(): Promise; + } + + export interface CustomProviderOptions { + /** + * Function to get an App Check token through a custom provider + * service. + */ + getToken: () => Promise; + } + /** + * Options for App Check initialization. + */ + export interface AppCheckOptions { + /** + * The App Check provider to use. This can be either the built-in reCAPTCHA provider + * or a custom provider. + */ + provider: CustomProvider | ReactNativeFirebaseAppCheckProvider; + + /** + * If true, enables SDK to automatically + * refresh AppCheck token as needed. If undefined, the value will default + * to the value of `app.automaticDataCollectionEnabled`. That property + * defaults to false and can be set in the app config. + */ + isTokenAutoRefreshEnabled?: boolean; + } + + export type NextFn = (value: T) => void; + export type ErrorFn = (error: Error) => void; + export type CompleteFn = () => void; + + export interface Observer { + next: NextFn; + error: ErrorFn; + complete: CompleteFn; + } + + export type PartialObserver = Partial>; + + /** + * A function that unsubscribes from token changes. + */ + export type Unsubscribe = () => void; + + export interface ReactNativeFirebaseAppCheckProviderOptions { + /** + * debug token to use, if any. Defaults to undefined, pre-configure tokens in firebase web console if needed + */ + debugToken?: string; + } + + export interface ReactNativeFirebaseAppCheckProviderWebOptions extends ReactNativeFirebaseAppCheckProviderOptions { + /** + * The web provider to use, either `reCaptchaV3` or `reCaptchaEnterprise`, defaults to `reCaptchaV3` + */ + provider?: 'debug' | 'reCaptchaV3' | 'reCaptchaEnterprise'; + + /** + * siteKey for use in web queries, defaults to `none` + */ + siteKey?: string; + } + + export interface ReactNativeFirebaseAppCheckProviderAppleOptions extends ReactNativeFirebaseAppCheckProviderOptions { + /** + * The apple provider to use, either `deviceCheck` or `appAttest`, or `appAttestWithDeviceCheckFallback`, + * defaults to `DeviceCheck`. `appAttest` requires iOS 14+ or will fail, `appAttestWithDeviceCheckFallback` + * will use `appAttest` for iOS14+ and fallback to `deviceCheck` on devices with ios13 and lower + */ + provider?: 'debug' | 'deviceCheck' | 'appAttest' | 'appAttestWithDeviceCheckFallback'; + } + + export interface ReactNativeFirebaseAppCheckProviderAndroidOptions extends ReactNativeFirebaseAppCheckProviderOptions { + /** + * The android provider to use, either `debug` or `playIntegrity`. default is `playIntegrity`. + */ + provider?: 'debug' | 'playIntegrity'; + } + + export interface ReactNativeFirebaseAppCheckProvider extends AppCheckProvider { + /** + * Specify how the app check provider should be configured. The new configuration is + * in effect when this call returns. You must call `getToken()` + * after this call to get a token using the new configuration. + * This custom provider allows for delayed configuration and re-configuration on all platforms + * so AppCheck has the same experience across all platforms, with the only difference being the native + * providers you choose to use on each platform. + */ + configure(options: { + web?: ReactNativeFirebaseAppCheckProviderWebOptions; + android?: ReactNativeFirebaseAppCheckProviderAndroidOptions; + apple?: ReactNativeFirebaseAppCheckProviderAppleOptions; + isTokenAutoRefreshEnabled?: boolean; + }): void; + } + + /** + * Result returned by `getToken()`. + */ + export interface AppCheckTokenResult { + /** + * The token string in JWT format. + */ + readonly token: string; + } + /** + * The token returned from an `AppCheckProvider`. + */ + export interface AppCheckToken { + /** + * The token string in JWT format. + */ + readonly token: string; + /** + * The local timestamp after which the token will expire. + */ + readonly expireTimeMillis: number; + } + /** + * The result return from `onTokenChanged` + */ + export type AppCheckListenerResult = AppCheckToken & { readonly appName: string }; + + export interface Statics { + // firebase.appCheck.* static props go here + CustomProvider: typeof CustomProvider; + SDK_VERSION: string; + } + + /** + * The Firebase App Check service is available for the default app or a given app. + * + * #### Example 1 + * + * Get the appCheck instance for the **default app**: + * + * ```js + * const appCheckForDefaultApp = firebase.appCheck(); + * ``` + * + * #### Example 2 + * + * Get the appCheck instance for a **secondary app**: + *˚ + * ```js + * const otherApp = firebase.app('otherApp'); + * const appCheckForOtherApp = firebase.appCheck(otherApp); + * ``` + * + */ + export interface Module extends FirebaseModule { + /** + * The current `FirebaseApp` instance for this Firebase service. + */ + app: ReactNativeFirebase.FirebaseApp; + + /** + * Create a ReactNativeFirebaseAppCheckProvider option for use in react-native-firebase + */ + newReactNativeFirebaseAppCheckProvider(): ReactNativeFirebaseAppCheckProvider; + + /** + * Initialize the AppCheck module. Note that in react-native-firebase AppCheckOptions must always + * be an object with a `provider` member containing `ReactNativeFirebaseAppCheckProvider` that has returned successfully + * from a call to the `configure` method, with sub-providers for the various platforms configured to meet your project + * requirements. This must be called prior to interacting with any firebase services protected by AppCheck + * + * @param options an AppCheckOptions with a configured ReactNativeFirebaseAppCheckProvider as the provider + */ + // TODO wrong types + initializeAppCheck(options: AppCheckOptions): Promise; + + /** + * Activate App Check + * On iOS App Check is activated with DeviceCheck provider simply by including the module, using the token auto refresh default or + * the specific value (if configured) in firebase.json, but calling this does no harm. + * On Android if you call this it will install the PlayIntegrity provider in release builds, the Debug provider if debuggable. + * On both platforms you may use this method to alter the token refresh setting after startup. + * On iOS if you want to set a specific AppCheckProviderFactory (for instance to FIRAppCheckDebugProviderFactory or + * FIRAppAttestProvider) you must manually do that in your AppDelegate.m prior to calling [FIRApp configure] + * + * @deprecated use initializeAppCheck to gain access to all platform providers and firebase-js-sdk v9 compatibility + * @param siteKeyOrProvider - This is ignored, Android uses DebugProviderFactory if the app is debuggable (https://firebase.google.com/docs/app-check/android/debug-provider) + * Android uses PlayIntegrityProviderFactory for release builds. + * iOS uses DeviceCheckProviderFactory by default unless altered in AppDelegate.m manually + * @param isTokenAutoRefreshEnabled - If true, enables SDK to automatically + * refresh AppCheck token as needed. If undefined, the value will default + * to the value of `app.automaticDataCollectionEnabled`. That property + * defaults to false and can be set in the app config. + */ + activate( + siteKeyOrProvider: string | AppCheckProvider, + isTokenAutoRefreshEnabled?: boolean, + ): Promise; + + /** + * Alter the token auto refresh setting. By default it will take the value of automaticDataCollectionEnabled from Info.plist / AndroidManifest.xml + * @param isTokenAutoRefreshEnabled - If true, the SDK automatically + * refreshes App Check tokens as needed. This overrides any value set + * during `activate()` or taken by default from automaticDataCollectionEnabled in plist / android manifest + */ + setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled: boolean): void; + + /** + * Requests Firebase App Check token. + * This method should only be used if you need to authorize requests to a non-Firebase backend. + * Requests to Firebase backend are authorized automatically if configured. + * + * @param forceRefresh - If true, a new Firebase App Check token is requested and the token cache is ignored. + * If false, the cached token is used if it exists and has not expired yet. + * In most cases, false should be used. True should only be used if the server explicitly returns an error, indicating a revoked token. + */ + getToken(forceRefresh?: boolean): Promise; + + /** + * Requests a Firebase App Check token. This method should be used only if you need to authorize requests + * to a non-Firebase backend. Returns limited-use tokens that are intended for use with your non-Firebase + * backend endpoints that are protected with Replay Protection (https://firebase.google.com/docs/app-check/custom-resource-backend#replay-protection). + * This method does not affect the token generation behavior of the getAppCheckToken() method. + */ + getLimitedUseToken(): Promise; + + /** + * Registers a listener to changes in the token state. There can be more + * than one listener registered at the same time for one or more + * App Check instances. The listeners call back on the UI thread whenever + * the current token associated with this App Check instance changes. + * + * @returns A function that unsubscribes this listener. + */ + // TODO wrong types + onTokenChanged(observer: PartialObserver): () => void; + + /** + * Registers a listener to changes in the token state. There can be more + * than one listener registered at the same time for one or more + * App Check instances. The listeners call back on the UI thread whenever + * the current token associated with this App Check instance changes. + * + * Token listeners do not exist in the native SDK for iOS, no token change events will be emitted on that platform. + * This is not yet implemented on Android, no token change events will be emitted until implemented. + * + * NOTE: Although an `onError` callback can be provided, it will + * never be called, Android sdk code doesn't provide handling for onError function + * + * NOTE: Although an `onCompletion` callback can be provided, it will + * never be called because the token stream is never-ending. + * + * @returns A function that unsubscribes this listener. + */ + // TODO wrong types + onTokenChanged( + onNext: (tokenResult: AppCheckListenerResult) => void, + onError?: (error: Error) => void, + onCompletion?: () => void, + ): () => void; + } +} + +type AppCheckNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebaseAppCheckTypes.Module, + FirebaseAppCheckTypes.Statics +> & { + appCheck: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebaseAppCheckTypes.Module, + FirebaseAppCheckTypes.Statics + >; + firebase: ReactNativeFirebase.Module; + app(name?: string): ReactNativeFirebase.FirebaseApp; +}; + +declare const defaultExport: AppCheckNamespace; + +export declare const firebase: ReactNativeFirebase.Module & { + appCheck: typeof defaultExport; + app( + name?: string, + ): ReactNativeFirebase.FirebaseApp & { appCheck(): FirebaseAppCheckTypes.Module }; +}; + +export default defaultExport; + +/** + * Attach namespace to `firebase.` and `FirebaseApp.`. + */ +declare module '@react-native-firebase/app' { + namespace ReactNativeFirebase { + import FirebaseModuleWithStaticsAndApp = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; + interface Module { + appCheck: FirebaseModuleWithStaticsAndApp< + FirebaseAppCheckTypes.Module, + FirebaseAppCheckTypes.Statics + >; + } + interface FirebaseApp { + appCheck(): FirebaseAppCheckTypes.Module; + } + } +} From bdeff283a7929d9a6f741596f0c38028da570667 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 12 Feb 2026 17:50:21 +0000 Subject: [PATCH 05/24] chore: annotate namespaced types as deprecated --- packages/app-check/lib/types/namespaced.ts | 48 +++++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/app-check/lib/types/namespaced.ts b/packages/app-check/lib/types/namespaced.ts index c16f959bc2..71f7d0c442 100644 --- a/packages/app-check/lib/types/namespaced.ts +++ b/packages/app-check/lib/types/namespaced.ts @@ -50,7 +50,7 @@ import type { ReactNativeFirebase } from '@react-native-firebase/app'; * * // firebase.appCheck().X * ``` - * + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. * @firebase app-check */ /* eslint-disable @typescript-eslint/no-namespace */ @@ -61,6 +61,7 @@ export namespace FirebaseAppCheckTypes { * An App Check provider. This can be either the built-in reCAPTCHA provider * or a custom provider. For more on custom providers, see * https://firebase.google.com/docs/app-check/web-custom-provider + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ export interface AppCheckProvider { /** @@ -71,13 +72,16 @@ export namespace FirebaseAppCheckTypes { /** * Custom provider class. + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. * @public */ export declare class CustomProvider implements AppCheckProvider { constructor(customProviderOptions: CustomProviderOptions); getToken(): Promise; } - + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export interface CustomProviderOptions { /** * Function to get an App Check token through a custom provider @@ -87,6 +91,7 @@ export namespace FirebaseAppCheckTypes { } /** * Options for App Check initialization. + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ export interface AppCheckOptions { /** @@ -104,16 +109,25 @@ export namespace FirebaseAppCheckTypes { isTokenAutoRefreshEnabled?: boolean; } + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export type NextFn = (value: T) => void; export type ErrorFn = (error: Error) => void; export type CompleteFn = () => void; + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export interface Observer { next: NextFn; error: ErrorFn; complete: CompleteFn; } + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export type PartialObserver = Partial>; /** @@ -121,6 +135,9 @@ export namespace FirebaseAppCheckTypes { */ export type Unsubscribe = () => void; + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export interface ReactNativeFirebaseAppCheckProviderOptions { /** * debug token to use, if any. Defaults to undefined, pre-configure tokens in firebase web console if needed @@ -128,6 +145,9 @@ export namespace FirebaseAppCheckTypes { debugToken?: string; } + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export interface ReactNativeFirebaseAppCheckProviderWebOptions extends ReactNativeFirebaseAppCheckProviderOptions { /** * The web provider to use, either `reCaptchaV3` or `reCaptchaEnterprise`, defaults to `reCaptchaV3` @@ -140,6 +160,9 @@ export namespace FirebaseAppCheckTypes { siteKey?: string; } + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export interface ReactNativeFirebaseAppCheckProviderAppleOptions extends ReactNativeFirebaseAppCheckProviderOptions { /** * The apple provider to use, either `deviceCheck` or `appAttest`, or `appAttestWithDeviceCheckFallback`, @@ -149,6 +172,9 @@ export namespace FirebaseAppCheckTypes { provider?: 'debug' | 'deviceCheck' | 'appAttest' | 'appAttestWithDeviceCheckFallback'; } + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export interface ReactNativeFirebaseAppCheckProviderAndroidOptions extends ReactNativeFirebaseAppCheckProviderOptions { /** * The android provider to use, either `debug` or `playIntegrity`. default is `playIntegrity`. @@ -156,6 +182,9 @@ export namespace FirebaseAppCheckTypes { provider?: 'debug' | 'playIntegrity'; } + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export interface ReactNativeFirebaseAppCheckProvider extends AppCheckProvider { /** * Specify how the app check provider should be configured. The new configuration is @@ -175,6 +204,7 @@ export namespace FirebaseAppCheckTypes { /** * Result returned by `getToken()`. + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ export interface AppCheckTokenResult { /** @@ -184,6 +214,7 @@ export namespace FirebaseAppCheckTypes { } /** * The token returned from an `AppCheckProvider`. + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ export interface AppCheckToken { /** @@ -197,9 +228,13 @@ export namespace FirebaseAppCheckTypes { } /** * The result return from `onTokenChanged` + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ export type AppCheckListenerResult = AppCheckToken & { readonly appName: string }; + /** + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. + */ export interface Statics { // firebase.appCheck.* static props go here CustomProvider: typeof CustomProvider; @@ -226,6 +261,7 @@ export namespace FirebaseAppCheckTypes { * const appCheckForOtherApp = firebase.appCheck(otherApp); * ``` * + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ export interface Module extends FirebaseModule { /** @@ -235,6 +271,7 @@ export namespace FirebaseAppCheckTypes { /** * Create a ReactNativeFirebaseAppCheckProvider option for use in react-native-firebase + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ newReactNativeFirebaseAppCheckProvider(): ReactNativeFirebaseAppCheckProvider; @@ -245,6 +282,7 @@ export namespace FirebaseAppCheckTypes { * requirements. This must be called prior to interacting with any firebase services protected by AppCheck * * @param options an AppCheckOptions with a configured ReactNativeFirebaseAppCheckProvider as the provider + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ // TODO wrong types initializeAppCheck(options: AppCheckOptions): Promise; @@ -266,6 +304,7 @@ export namespace FirebaseAppCheckTypes { * refresh AppCheck token as needed. If undefined, the value will default * to the value of `app.automaticDataCollectionEnabled`. That property * defaults to false and can be set in the app config. + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ activate( siteKeyOrProvider: string | AppCheckProvider, @@ -277,6 +316,7 @@ export namespace FirebaseAppCheckTypes { * @param isTokenAutoRefreshEnabled - If true, the SDK automatically * refreshes App Check tokens as needed. This overrides any value set * during `activate()` or taken by default from automaticDataCollectionEnabled in plist / android manifest + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled: boolean): void; @@ -288,6 +328,7 @@ export namespace FirebaseAppCheckTypes { * @param forceRefresh - If true, a new Firebase App Check token is requested and the token cache is ignored. * If false, the cached token is used if it exists and has not expired yet. * In most cases, false should be used. True should only be used if the server explicitly returns an error, indicating a revoked token. + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ getToken(forceRefresh?: boolean): Promise; @@ -296,6 +337,7 @@ export namespace FirebaseAppCheckTypes { * to a non-Firebase backend. Returns limited-use tokens that are intended for use with your non-Firebase * backend endpoints that are protected with Replay Protection (https://firebase.google.com/docs/app-check/custom-resource-backend#replay-protection). * This method does not affect the token generation behavior of the getAppCheckToken() method. + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. */ getLimitedUseToken(): Promise; @@ -305,6 +347,7 @@ export namespace FirebaseAppCheckTypes { * App Check instances. The listeners call back on the UI thread whenever * the current token associated with this App Check instance changes. * + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. * @returns A function that unsubscribes this listener. */ // TODO wrong types @@ -325,6 +368,7 @@ export namespace FirebaseAppCheckTypes { * NOTE: Although an `onCompletion` callback can be provided, it will * never be called because the token stream is never-ending. * + * @deprecated Use the exported types directly instead. FirebaseAppCheckTypes namespace is kept for backwards compatibility. * @returns A function that unsubscribes this listener. */ // TODO wrong types From 0fd4dcc74ccdf6adc42259e4964b54bb55d4d6b3 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 12 Feb 2026 17:53:59 +0000 Subject: [PATCH 06/24] chore: update types to unsubscribe --- packages/app-check/lib/types/internal.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/app-check/lib/types/internal.ts b/packages/app-check/lib/types/internal.ts index 75d36ad41c..dd09c07693 100644 --- a/packages/app-check/lib/types/internal.ts +++ b/packages/app-check/lib/types/internal.ts @@ -7,6 +7,7 @@ import type { AppCheckTokenResult, PartialObserver, ReactNativeFirebaseAppCheckProvider, + Unsubscribe, } from './appcheck'; export type AppCheckInternal = AppCheck & { @@ -109,5 +110,16 @@ export type AppCheckInternal = AppCheck & { onNext: (tokenResult: AppCheckListenerResult) => void, onError?: (error: Error) => void, onCompletion?: () => void, - ): () => void; + ): Unsubscribe; + + /** + * Implementation signature used by modular wrappers. + */ + onTokenChanged( + onNextOrObserver: + | PartialObserver + | ((tokenResult: AppCheckTokenResult) => void), + onError?: (error: Error) => void, + onCompletion?: () => void, + ): Unsubscribe; }; From 86982934ac1cb6b00905f14384c7d1c7ea901e76 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 13 Feb 2026 12:49:17 +0000 Subject: [PATCH 07/24] refactor: change AppCheckListenerResult to AppCheckTokenResult --- packages/app-check/lib/modular.ts | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/packages/app-check/lib/modular.ts b/packages/app-check/lib/modular.ts index eccc4fb44d..f2ed9f9aac 100644 --- a/packages/app-check/lib/modular.ts +++ b/packages/app-check/lib/modular.ts @@ -15,7 +15,7 @@ * */ -import { getApp, type FirebaseApp, type ReactNativeFirebase } from '@react-native-firebase/app'; +import { getApp, type FirebaseApp } from '@react-native-firebase/app'; import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; import ReactNativeFirebaseAppCheckProvider from './ReactNativeFirebaseAppCheckProvider'; @@ -25,7 +25,6 @@ import type { AppCheckTokenResult, PartialObserver, Unsubscribe, - AppCheckListenerResult, } from './types/appcheck'; import type { AppCheckInternal } from './types/internal'; @@ -40,20 +39,10 @@ type WithModularDeprecationArg = F extends (...args: infer P) => infer R * @returns Promise */ export async function initializeAppCheck( - app?: ReactNativeFirebase.FirebaseApp, + app?: FirebaseApp, options?: AppCheckOptions, ): Promise { - if (app) { - const appInstance = getApp(app.name) as FirebaseApp; - const appCheck = appInstance.appCheck(); - await ( - (appCheck as AppCheckInternal).initializeAppCheck as WithModularDeprecationArg< - AppCheckInternal['initializeAppCheck'] - > - ).call(appCheck, options as AppCheckOptions, MODULAR_DEPRECATION_ARG); - return appCheck; - } - const appInstance = getApp() as FirebaseApp; + const appInstance = app ? (getApp(app.name) as FirebaseApp) : (getApp() as FirebaseApp); const appCheck = appInstance.appCheck(); await ( (appCheck as AppCheckInternal).initializeAppCheck as WithModularDeprecationArg< @@ -140,7 +129,7 @@ export function onTokenChanged( */ export function onTokenChanged( appCheckInstance: AppCheck, - onNext: (tokenResult: AppCheckListenerResult) => void, + onNext: (tokenResult: AppCheckTokenResult) => void, onError?: (error: Error) => void, onCompletion?: () => void, ): Unsubscribe; @@ -149,7 +138,7 @@ export function onTokenChanged( appCheckInstance: AppCheck, onNextOrObserver: | PartialObserver - | ((tokenResult: AppCheckListenerResult) => void), + | ((tokenResult: AppCheckTokenResult) => void), onError?: (error: Error) => void, onCompletion?: () => void, ): Unsubscribe { From 421ea77b0c28f40e62becc446ffdec87bd056a24 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 13 Feb 2026 12:51:12 +0000 Subject: [PATCH 08/24] fix(ai): use deprecated type so when we remove this will be flagged as another change needed --- packages/ai/lib/models/utils.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/ai/lib/models/utils.ts b/packages/ai/lib/models/utils.ts index 0f2dba4923..1ac7cc4a08 100644 --- a/packages/ai/lib/models/utils.ts +++ b/packages/ai/lib/models/utils.ts @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +import type { FirebaseAppCheckTypes } from '@react-native-firebase/app-check'; import { AIError } from '../errors'; import { AI, AIErrorCode } from '../public-types'; import { AIService } from '../service'; @@ -52,12 +52,10 @@ export function initApiSettings(ai: AI): ApiSettings { backend: ai.backend, }; - if ((ai as AIService).appCheck) { - if (ai.options?.useLimitedUseAppCheckTokens) { - apiSettings.getAppCheckToken = () => (ai as AIService).appCheck!.getLimitedUseToken(); - } else { - apiSettings.getAppCheckToken = () => (ai as AIService).appCheck!.getToken(); - } + const appCheck = ai.appCheck as FirebaseAppCheckTypes.Module; + if (appCheck) { + apiSettings.getAppCheckToken = () => + ai.options?.useLimitedUseAppCheckTokens ? appCheck.getLimitedUseToken() : appCheck.getToken(); } if ((ai as AIService).auth?.currentUser) { From 2649a8cc05676caa72549eee6d6c836fcdb52cf3 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 13 Feb 2026 12:54:01 +0000 Subject: [PATCH 09/24] chore: use firebase-js-sdk types for app check web --- .../app-check/lib/web/RNFBAppCheckModule.ts | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/packages/app-check/lib/web/RNFBAppCheckModule.ts b/packages/app-check/lib/web/RNFBAppCheckModule.ts index 1ad79e5daa..b6bd76edd5 100644 --- a/packages/app-check/lib/web/RNFBAppCheckModule.ts +++ b/packages/app-check/lib/web/RNFBAppCheckModule.ts @@ -7,9 +7,10 @@ import { CustomProvider, onTokenChanged, makeIDBAvailable, + type AppCheckOptions, + type AppCheckTokenResult, } from '@react-native-firebase/app/dist/module/internal/web/firebaseAppCheck'; import { guard, emitEvent } from '@react-native-firebase/app/dist/module/internal/web/utils'; -import type { FirebaseAppCheckTypes } from '../types/appcheck'; let appCheckInstances: Record = {}; let listenersForApp: Record void> = {}; @@ -24,16 +25,10 @@ function getAppCheckInstanceForApp(appName: string): any { } interface AppCheckModule { - initializeAppCheck( - appName: string, - options: FirebaseAppCheckTypes.AppCheckOptions, - ): Promise; + initializeAppCheck(appName: string, options: AppCheckOptions): Promise; setTokenAutoRefreshEnabled(appName: string, isTokenAutoRefreshEnabled: boolean): Promise; - getLimitedUseToken(appName: string): Promise; - getToken( - appName: string, - forceRefresh: boolean, - ): Promise; + getLimitedUseToken(appName: string): Promise; + getToken(appName: string, forceRefresh: boolean): Promise; addAppCheckListener(appName: string): Promise; removeAppCheckListener(appName: string): Promise; } @@ -45,7 +40,7 @@ interface AppCheckModule { * java methods on Android. */ const module: AppCheckModule = { - initializeAppCheck(appName: string, options: FirebaseAppCheckTypes.AppCheckOptions) { + initializeAppCheck(appName: string, options: AppCheckOptions) { makeIDBAvailable(); return guard(async () => { if (appCheckInstances[appName]) { @@ -90,15 +85,12 @@ const module: AppCheckModule = { return; } const instance = getAppCheckInstanceForApp(appName); - listenersForApp[appName] = onTokenChanged( - instance, - (tokenResult: FirebaseAppCheckTypes.AppCheckTokenResult) => { - emitEvent('appCheck_token_changed', { - appName, - ...tokenResult, - }); - }, - ); + listenersForApp[appName] = onTokenChanged(instance, (tokenResult: AppCheckTokenResult) => { + emitEvent('appCheck_token_changed', { + appName, + ...tokenResult, + }); + }); }); }, removeAppCheckListener(appName: string) { From c27735572a6191d97c18594f74c533f432056a7a Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 13 Feb 2026 12:54:47 +0000 Subject: [PATCH 10/24] fix: remove FirebaseAppCheckTypes export from modular types --- packages/app-check/lib/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/app-check/lib/index.ts b/packages/app-check/lib/index.ts index 6aaaf4f702..10439ce22e 100644 --- a/packages/app-check/lib/index.ts +++ b/packages/app-check/lib/index.ts @@ -35,7 +35,6 @@ export type { ReactNativeFirebaseAppCheckProviderAndroidOptions, ReactNativeFirebaseAppCheckProvider, AppCheck, - FirebaseAppCheckTypes, } from './types/appcheck'; // Export modular API functions From 4aa08e7eb7fc9e8102a16a97263bf71adedb7992 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 13 Feb 2026 13:03:10 +0000 Subject: [PATCH 11/24] fix: export FirebaseAppCheckTypes from index and fix type-tests --- packages/app-check/lib/index.ts | 1 + packages/app-check/type-test.ts | 17 +++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/app-check/lib/index.ts b/packages/app-check/lib/index.ts index 10439ce22e..d9eb82f530 100644 --- a/packages/app-check/lib/index.ts +++ b/packages/app-check/lib/index.ts @@ -41,5 +41,6 @@ export type { export * from './modular'; // Export namespaced API +export { FirebaseAppCheckTypes } from './types/namespaced'; export * from './namespaced'; export { default } from './namespaced'; diff --git a/packages/app-check/type-test.ts b/packages/app-check/type-test.ts index 3314f4ca9d..d1d92a051d 100644 --- a/packages/app-check/type-test.ts +++ b/packages/app-check/type-test.ts @@ -7,6 +7,8 @@ import appCheck, { setTokenAutoRefreshEnabled, onTokenChanged, CustomProvider, + AppCheck, + AppCheckTokenResult, } from '.'; console.log(appCheck().app); @@ -113,33 +115,33 @@ modularProvider.configure({ initializeAppCheck(firebase.app(), { provider: modularProvider, isTokenAutoRefreshEnabled: true, -}).then((appCheckModular: FirebaseAppCheckTypes.Module) => { +}).then((appCheckModular: AppCheck) => { console.log(appCheckModular.app.name); }); initializeAppCheck(undefined, { provider: modularProvider, isTokenAutoRefreshEnabled: true, -}).then((appCheckModular: FirebaseAppCheckTypes.Module) => { +}).then((appCheckModular: AppCheck) => { console.log(appCheckModular.app.name); }); -getToken(appCheckInstance).then((result: FirebaseAppCheckTypes.AppCheckTokenResult) => { +getToken(appCheckInstance).then((result: AppCheckTokenResult) => { console.log(result.token); }); -getToken(appCheckInstance, true).then((result: FirebaseAppCheckTypes.AppCheckTokenResult) => { +getToken(appCheckInstance, true).then((result: AppCheckTokenResult) => { console.log(result.token); }); -getLimitedUseToken(appCheckInstance).then((result: FirebaseAppCheckTypes.AppCheckTokenResult) => { +getLimitedUseToken(appCheckInstance).then((result: AppCheckTokenResult) => { console.log(result.token); }); setTokenAutoRefreshEnabled(appCheckInstance, true); const modularUnsubscribe1 = onTokenChanged(appCheckInstance, { - next: (tokenResult: FirebaseAppCheckTypes.AppCheckTokenResult) => { + next: (tokenResult: AppCheckTokenResult) => { console.log(tokenResult.token); }, error: (error: Error) => { @@ -152,9 +154,8 @@ const modularUnsubscribe1 = onTokenChanged(appCheckInstance, { const modularUnsubscribe2 = onTokenChanged( appCheckInstance, - (tokenResult: FirebaseAppCheckTypes.AppCheckListenerResult) => { + (tokenResult: AppCheckTokenResult) => { console.log(tokenResult.token); - console.log(tokenResult.appName); }, (error: Error) => { console.log(error.message); From f5de6b89b6decf6b80e32ff5ba060f568f310510 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 13 Feb 2026 13:51:05 +0000 Subject: [PATCH 12/24] refactor: remove statics from modular and export CustomProvider from modular --- packages/app-check/lib/modular.ts | 27 +++++++++++++++-- packages/app-check/lib/namespaced.ts | 37 +++++++----------------- packages/app-check/lib/types/appcheck.ts | 9 ------ 3 files changed, 34 insertions(+), 39 deletions(-) diff --git a/packages/app-check/lib/modular.ts b/packages/app-check/lib/modular.ts index f2ed9f9aac..e9e630d9c1 100644 --- a/packages/app-check/lib/modular.ts +++ b/packages/app-check/lib/modular.ts @@ -16,13 +16,18 @@ */ import { getApp, type FirebaseApp } from '@react-native-firebase/app'; -import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; -import ReactNativeFirebaseAppCheckProvider from './ReactNativeFirebaseAppCheckProvider'; +import { + isFunction, + isObject, + MODULAR_DEPRECATION_ARG, +} from '@react-native-firebase/app/dist/module/common'; import type { AppCheck, AppCheckOptions, + AppCheckProvider, AppCheckTokenResult, + CustomProviderOptions, PartialObserver, Unsubscribe, } from './types/appcheck'; @@ -155,4 +160,20 @@ export function onTokenChanged( ) as Unsubscribe; } -export { ReactNativeFirebaseAppCheckProvider }; +export class CustomProvider implements AppCheckProvider { + private _customProviderOptions: CustomProviderOptions; + + constructor(_customProviderOptions: CustomProviderOptions) { + if (!isObject(_customProviderOptions)) { + throw new Error('Invalid configuration: no provider options defined.'); + } + if (!isFunction(_customProviderOptions.getToken)) { + throw new Error('Invalid configuration: no getToken function defined.'); + } + this._customProviderOptions = _customProviderOptions; + } + + async getToken() { + return this._customProviderOptions.getToken(); + } +} diff --git a/packages/app-check/lib/namespaced.ts b/packages/app-check/lib/namespaced.ts index ff9998cfd1..2e4c764535 100644 --- a/packages/app-check/lib/namespaced.ts +++ b/packages/app-check/lib/namespaced.ts @@ -20,7 +20,6 @@ import { isIOS, isString, isObject, - isFunction, isUndefined, isOther, parseListenerOrObserver, @@ -37,40 +36,21 @@ import { setReactNativeModule } from '@react-native-firebase/app/dist/module/int import fallBackModule from './web/RNFBAppCheckModule'; import { version } from './version'; import type { - CustomProviderOptions, AppCheckProvider, AppCheckTokenResult, AppCheckOptions, AppCheckListenerResult, PartialObserver, - AppCheck, - AppCheckStatics, ProviderWithOptions, } from './types/appcheck'; +import type { FirebaseAppCheckTypes } from './types/namespaced'; import type { ReactNativeFirebase } from '@react-native-firebase/app'; +import { CustomProvider } from './modular'; const namespace = 'appCheck'; const nativeModuleName = 'RNFBAppCheckModule'; -export class CustomProvider implements AppCheckProvider { - private _customProviderOptions: CustomProviderOptions; - - constructor(_customProviderOptions: CustomProviderOptions) { - if (!isObject(_customProviderOptions)) { - throw new Error('Invalid configuration: no provider options defined.'); - } - if (!isFunction(_customProviderOptions.getToken)) { - throw new Error('Invalid configuration: no getToken function defined.'); - } - this._customProviderOptions = _customProviderOptions; - } - - async getToken() { - return this._customProviderOptions.getToken(); - } -} - const statics = { CustomProvider, }; @@ -278,10 +258,13 @@ const appCheckNamespace = createModuleNamespace({ }); type AppCheckNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< - AppCheck, - AppCheckStatics + FirebaseAppCheckTypes.Module, + FirebaseAppCheckTypes.Statics > & { - appCheck: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; + appCheck: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebaseAppCheckTypes.Module, + FirebaseAppCheckTypes.Statics + >; firebase: ReactNativeFirebase.Module; app(name?: string): ReactNativeFirebase.FirebaseApp; }; @@ -296,8 +279,8 @@ export default appCheckNamespace as unknown as AppCheckNamespace; export const firebase = getFirebaseRoot() as unknown as ReactNativeFirebase.FirebaseNamespacedExport< 'appCheck', - AppCheck, - AppCheckStatics, + FirebaseAppCheckTypes.Module, + FirebaseAppCheckTypes.Statics, false >; diff --git a/packages/app-check/lib/types/appcheck.ts b/packages/app-check/lib/types/appcheck.ts index a368a3a174..ff7a7d5867 100644 --- a/packages/app-check/lib/types/appcheck.ts +++ b/packages/app-check/lib/types/appcheck.ts @@ -215,12 +215,3 @@ export interface AppCheck { app: FirebaseApp; } -// ============ Statics Interface ============ - -/** - * Static properties available on firebase.appCheck - */ -export interface AppCheckStatics { - CustomProvider: new (customProviderOptions: CustomProviderOptions) => CustomProvider; - SDK_VERSION: string; -} From 98e0ac9aa5fc7bf5d2712c14daaea581c2e61abf Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 16 Feb 2026 13:25:28 +0000 Subject: [PATCH 13/24] refactor: allow passing in providerOptions into constructor --- packages/app-check/lib/ReactNativeFirebaseAppCheckProvider.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/app-check/lib/ReactNativeFirebaseAppCheckProvider.ts b/packages/app-check/lib/ReactNativeFirebaseAppCheckProvider.ts index bdc9887082..a252b9955f 100644 --- a/packages/app-check/lib/ReactNativeFirebaseAppCheckProvider.ts +++ b/packages/app-check/lib/ReactNativeFirebaseAppCheckProvider.ts @@ -7,7 +7,9 @@ import type { export default class ReactNativeFirebaseAppCheckProvider implements AppCheckProvider { providerOptions?: ProviderOptions; - constructor() {} + constructor(options?: ProviderOptions) { + this.providerOptions = options; + } configure(options: ProviderOptions): void { this.providerOptions = options; From 76ab3a8485a7a871162aa3ba7fa9a8cb1b41a27f Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 16 Feb 2026 13:50:54 +0000 Subject: [PATCH 14/24] refactor: move Custom Provider and ReactNativeFirebaseAppCheckProvider to provider.ts --- .../ReactNativeFirebaseAppCheckProvider.ts | 23 --------- packages/app-check/lib/modular.ts | 30 ++---------- packages/app-check/lib/namespaced.ts | 3 +- packages/app-check/lib/providers.ts | 49 +++++++++++++++++++ packages/app-check/lib/types/appcheck.ts | 1 - 5 files changed, 54 insertions(+), 52 deletions(-) delete mode 100644 packages/app-check/lib/ReactNativeFirebaseAppCheckProvider.ts create mode 100644 packages/app-check/lib/providers.ts diff --git a/packages/app-check/lib/ReactNativeFirebaseAppCheckProvider.ts b/packages/app-check/lib/ReactNativeFirebaseAppCheckProvider.ts deleted file mode 100644 index a252b9955f..0000000000 --- a/packages/app-check/lib/ReactNativeFirebaseAppCheckProvider.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { - AppCheckProvider, - AppCheckToken, - ReactNativeFirebaseAppCheckProviderOptionsMap as ProviderOptions, -} from './types/appcheck'; - -export default class ReactNativeFirebaseAppCheckProvider implements AppCheckProvider { - providerOptions?: ProviderOptions; - - constructor(options?: ProviderOptions) { - this.providerOptions = options; - } - - configure(options: ProviderOptions): void { - this.providerOptions = options; - } - - async getToken(): Promise { - // This is a placeholder - the actual implementation is handled by the native modules - // This method exists to satisfy the AppCheckProvider interface - throw new Error('getToken() must be called after configure() and is handled by native modules'); - } -} diff --git a/packages/app-check/lib/modular.ts b/packages/app-check/lib/modular.ts index e9e630d9c1..eebc3d844a 100644 --- a/packages/app-check/lib/modular.ts +++ b/packages/app-check/lib/modular.ts @@ -16,23 +16,19 @@ */ import { getApp, type FirebaseApp } from '@react-native-firebase/app'; -import { - isFunction, - isObject, - MODULAR_DEPRECATION_ARG, -} from '@react-native-firebase/app/dist/module/common'; +import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; import type { AppCheck, AppCheckOptions, - AppCheckProvider, AppCheckTokenResult, - CustomProviderOptions, PartialObserver, Unsubscribe, } from './types/appcheck'; import type { AppCheckInternal } from './types/internal'; +export { CustomProvider, ReactNativeFirebaseAppCheckProvider } from './providers'; + type WithModularDeprecationArg = F extends (...args: infer P) => infer R ? (...args: [...P, typeof MODULAR_DEPRECATION_ARG]) => R : never; @@ -117,7 +113,7 @@ export function setTokenAutoRefreshEnabled( */ export function onTokenChanged( appCheckInstance: AppCheck, - listener: PartialObserver, + observer: PartialObserver, ): Unsubscribe; /** @@ -159,21 +155,3 @@ export function onTokenChanged( MODULAR_DEPRECATION_ARG, ) as Unsubscribe; } - -export class CustomProvider implements AppCheckProvider { - private _customProviderOptions: CustomProviderOptions; - - constructor(_customProviderOptions: CustomProviderOptions) { - if (!isObject(_customProviderOptions)) { - throw new Error('Invalid configuration: no provider options defined.'); - } - if (!isFunction(_customProviderOptions.getToken)) { - throw new Error('Invalid configuration: no getToken function defined.'); - } - this._customProviderOptions = _customProviderOptions; - } - - async getToken() { - return this._customProviderOptions.getToken(); - } -} diff --git a/packages/app-check/lib/namespaced.ts b/packages/app-check/lib/namespaced.ts index 2e4c764535..691779b36d 100644 --- a/packages/app-check/lib/namespaced.ts +++ b/packages/app-check/lib/namespaced.ts @@ -31,7 +31,6 @@ import { } from '@react-native-firebase/app/dist/module/internal'; import type { ModuleConfig } from '@react-native-firebase/app/dist/module/internal'; import { Platform } from 'react-native'; -import ReactNativeFirebaseAppCheckProvider from './ReactNativeFirebaseAppCheckProvider'; import { setReactNativeModule } from '@react-native-firebase/app/dist/module/internal/nativeModule'; import fallBackModule from './web/RNFBAppCheckModule'; import { version } from './version'; @@ -45,7 +44,7 @@ import type { } from './types/appcheck'; import type { FirebaseAppCheckTypes } from './types/namespaced'; import type { ReactNativeFirebase } from '@react-native-firebase/app'; -import { CustomProvider } from './modular'; +import { CustomProvider, ReactNativeFirebaseAppCheckProvider } from './providers'; const namespace = 'appCheck'; diff --git a/packages/app-check/lib/providers.ts b/packages/app-check/lib/providers.ts new file mode 100644 index 0000000000..508f43e84a --- /dev/null +++ b/packages/app-check/lib/providers.ts @@ -0,0 +1,49 @@ +import type { + AppCheckProvider, + AppCheckToken, + CustomProviderOptions, + ReactNativeFirebaseAppCheckProviderOptionsMap as ProviderOptions, +} from './types/appcheck'; +import { isFunction, isObject } from '@react-native-firebase/app/dist/module/common'; + +/** + * @public Use this to configure providers for android, iOS and "other" platforms. + */ +export class ReactNativeFirebaseAppCheckProvider implements AppCheckProvider { + providerOptions?: ProviderOptions; + + constructor(options?: ProviderOptions) { + this.providerOptions = options; + } + + configure(options: ProviderOptions): void { + this.providerOptions = options; + } + + async getToken(): Promise { + // This is a placeholder - the actual implementation is handled by the native modules + // This method exists to satisfy the AppCheckProvider interface + throw new Error('getToken() must be called after configure() and is handled by native modules'); + } +} + +/** + * @public Use this to configure a Custom Provider on "other" platform. This will not work on iOS and android. + */ +export class CustomProvider implements AppCheckProvider { + private _customProviderOptions: CustomProviderOptions; + + constructor(_customProviderOptions: CustomProviderOptions) { + if (!isObject(_customProviderOptions)) { + throw new Error('Invalid configuration: no provider options defined.'); + } + if (!isFunction(_customProviderOptions.getToken)) { + throw new Error('Invalid configuration: no getToken function defined.'); + } + this._customProviderOptions = _customProviderOptions; + } + + async getToken() { + return this._customProviderOptions.getToken(); + } +} diff --git a/packages/app-check/lib/types/appcheck.ts b/packages/app-check/lib/types/appcheck.ts index ff7a7d5867..2313df531c 100644 --- a/packages/app-check/lib/types/appcheck.ts +++ b/packages/app-check/lib/types/appcheck.ts @@ -214,4 +214,3 @@ export interface AppCheck { */ app: FirebaseApp; } - From 2b8d3cf42d3aab3144847adb2223c74c13fd5a94 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 16 Feb 2026 14:54:53 +0000 Subject: [PATCH 15/24] refactor: modular types to match firebase-js-sdk as close as possible --- packages/app-check/lib/namespaced.ts | 24 ++--- packages/app-check/lib/types/appcheck.ts | 106 ++++++++--------------- packages/app-check/lib/types/internal.ts | 17 +++- packages/app/lib/index.ts | 1 + packages/app/lib/types/common.ts | 33 +++++++ 5 files changed, 92 insertions(+), 89 deletions(-) create mode 100644 packages/app/lib/types/common.ts diff --git a/packages/app-check/lib/namespaced.ts b/packages/app-check/lib/namespaced.ts index 691779b36d..8df01bf90a 100644 --- a/packages/app-check/lib/namespaced.ts +++ b/packages/app-check/lib/namespaced.ts @@ -34,14 +34,8 @@ import { Platform } from 'react-native'; import { setReactNativeModule } from '@react-native-firebase/app/dist/module/internal/nativeModule'; import fallBackModule from './web/RNFBAppCheckModule'; import { version } from './version'; -import type { - AppCheckProvider, - AppCheckTokenResult, - AppCheckOptions, - AppCheckListenerResult, - PartialObserver, - ProviderWithOptions, -} from './types/appcheck'; +import type { AppCheckOptions, PartialObserver } from './types/appcheck'; +import type { ProviderWithOptions } from './types/internal'; import type { FirebaseAppCheckTypes } from './types/namespaced'; import type { ReactNativeFirebase } from '@react-native-firebase/app'; import { CustomProvider, ReactNativeFirebaseAppCheckProvider } from './providers'; @@ -158,7 +152,7 @@ class FirebaseAppCheckModule extends FirebaseModule { } activate( - siteKeyOrProvider: string | AppCheckProvider, + siteKeyOrProvider: string | FirebaseAppCheckTypes.AppCheckProvider, isTokenAutoRefreshEnabled?: boolean, ): Promise { if (isOther) { @@ -191,7 +185,7 @@ class FirebaseAppCheckModule extends FirebaseModule { this.native.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled); } - getToken(forceRefresh?: boolean): Promise { + getToken(forceRefresh?: boolean): Promise { if (!forceRefresh) { return this.native.getToken(false); } else { @@ -199,14 +193,14 @@ class FirebaseAppCheckModule extends FirebaseModule { } } - getLimitedUseToken(): Promise { + getLimitedUseToken(): Promise { return this.native.getLimitedUseToken(); } onTokenChanged( onNextOrObserver: - | PartialObserver - | ((tokenResult: AppCheckListenerResult) => void), + | PartialObserver + | ((tokenResult: FirebaseAppCheckTypes.AppCheckListenerResult) => void), _onError?: (error: Error) => void, _onCompletion?: () => void, ): () => void { @@ -218,8 +212,8 @@ class FirebaseAppCheckModule extends FirebaseModule { } const nextFn = parseListenerOrObserver( onNextOrObserver as - | ((value: AppCheckListenerResult) => void) - | { next: (value: AppCheckListenerResult) => void }, + | ((value: FirebaseAppCheckTypes.AppCheckListenerResult) => void) + | { next: (value: FirebaseAppCheckTypes.AppCheckListenerResult) => void }, ); // let errorFn = function () { }; // if (onNextOrObserver.error != null) { diff --git a/packages/app-check/lib/types/appcheck.ts b/packages/app-check/lib/types/appcheck.ts index 2313df531c..9b95b4d3e0 100644 --- a/packages/app-check/lib/types/appcheck.ts +++ b/packages/app-check/lib/types/appcheck.ts @@ -16,41 +16,39 @@ */ import type { FirebaseApp } from '@react-native-firebase/app'; +import type { CustomProvider } from '../providers'; -// ============ Provider Types ============ - +export type { Unsubscribe, PartialObserver } from '@react-native-firebase/app'; /** - * An App Check provider. This can be either the built-in reCAPTCHA provider - * or a custom provider. For more on custom providers, see - * https://firebase.google.com/docs/app-check/web-custom-provider + * The Firebase App Check service interface. + * + * @public */ -export interface AppCheckProvider { +export interface AppCheck { /** - * Returns an AppCheck token. + * this `AppCheck` instance is associated with this FirebaseApp. */ - getToken(): Promise; -} - -/** - * Function to get an App Check token through a custom provider service. - */ -export interface CustomProviderOptions { - getToken: () => Promise; + app: FirebaseApp; } -// ============ Options & Result Types ============ - /** - * Custom provider class. + * The token returned from an `AppCheckProvider`. * @public */ -export declare class CustomProvider implements AppCheckProvider { - constructor(customProviderOptions: CustomProviderOptions); - getToken(): Promise; +export interface AppCheckToken { + /** + * The token string in JWT format. + */ + readonly token: string; + /** + * The local timestamp after which the token will expire. + */ + readonly expireTimeMillis: number; } /** * Options for App Check initialization. + * @public */ export interface AppCheckOptions { /** @@ -73,21 +71,21 @@ export interface AppCheckOptions { } /** - * The token returned from an `AppCheckProvider`. + * Function to get an App Check token through a custom provider service. This is for + * "other" platform only, this is not supported on iOS and android. + * @public */ -export interface AppCheckToken { - /** - * The token string in JWT format. - */ - readonly token: string; +export interface CustomProviderOptions { /** - * The local timestamp after which the token will expire. + * Function to get an App Check token through a custom provider + * service. */ - readonly expireTimeMillis: number; + getToken: () => Promise; } /** * Result returned by `getToken()`. + * @public */ export interface AppCheckTokenResult { /** @@ -97,31 +95,17 @@ export interface AppCheckTokenResult { } /** - * The result return from `onTokenChanged` + * An App Check provider. This can be either the built-in reCAPTCHA provider + * or a custom provider. For more on custom providers, see + * https://firebase.google.com/docs/app-check/web-custom-provider */ -export type AppCheckListenerResult = AppCheckToken & { readonly appName: string }; - -// ============ Observer Types ============ - -export type NextFn = (value: T) => void; -export type ErrorFn = (error: Error) => void; -export type CompleteFn = () => void; - -export interface Observer { - next: NextFn; - error: ErrorFn; - complete: CompleteFn; +export interface AppCheckProvider { + /** + * Returns an AppCheck token. + */ + getToken(): Promise; } -export type PartialObserver = Partial>; - -/** - * A function that unsubscribes from token changes. - */ -export type Unsubscribe = () => void; - -// ============ ReactNativeFirebaseAppCheckProvider Types ============ - export interface ReactNativeFirebaseAppCheckProviderOptions { /** * debug token to use, if any. Defaults to undefined, pre-configure tokens in firebase web console if needed @@ -194,23 +178,3 @@ export interface ReactNativeFirebaseAppCheckProvider extends AppCheckProvider { */ configure(options: ReactNativeFirebaseAppCheckProviderOptionsMap): void; } - -/** - * Type representing providers that have providerOptions. - * Used for type narrowing in runtime code. - */ -export type ProviderWithOptions = - | ReactNativeFirebaseAppCheckProvider - | ReactNativeFirebaseAppCheckProviderConfig; - -/** - * The Firebase App Check service interface. - * - * @public - */ -export interface AppCheck { - /** - * this `AppCheck` instance is associated with this FirebaseApp. - */ - app: FirebaseApp; -} diff --git a/packages/app-check/lib/types/internal.ts b/packages/app-check/lib/types/internal.ts index dd09c07693..855c9a7040 100644 --- a/packages/app-check/lib/types/internal.ts +++ b/packages/app-check/lib/types/internal.ts @@ -1,14 +1,15 @@ import type { FirebaseApp } from '@react-native-firebase/app'; import type { AppCheck, - AppCheckListenerResult, AppCheckOptions, AppCheckProvider, AppCheckTokenResult, PartialObserver, ReactNativeFirebaseAppCheckProvider, + ReactNativeFirebaseAppCheckProviderConfig, Unsubscribe, } from './appcheck'; +import type { FirebaseAppCheckTypes } from './namespaced' export type AppCheckInternal = AppCheck & { /** The FirebaseApp this module is associated with */ @@ -87,7 +88,9 @@ export type AppCheckInternal = AppCheck & { * * @returns A function that unsubscribes this listener. */ - onTokenChanged(observer: PartialObserver): () => void; + onTokenChanged( + observer: PartialObserver, + ): () => void; /** * Registers a listener to changes in the token state. There can be more @@ -107,7 +110,7 @@ export type AppCheckInternal = AppCheck & { * @returns A function that unsubscribes this listener. */ onTokenChanged( - onNext: (tokenResult: AppCheckListenerResult) => void, + onNext: (tokenResult: FirebaseAppCheckTypes.AppCheckListenerResult) => void, onError?: (error: Error) => void, onCompletion?: () => void, ): Unsubscribe; @@ -123,3 +126,11 @@ export type AppCheckInternal = AppCheck & { onCompletion?: () => void, ): Unsubscribe; }; + +/** + * Type representing providers that have providerOptions. + * Used for type narrowing in runtime code. + */ +export type ProviderWithOptions = + | ReactNativeFirebaseAppCheckProvider + | ReactNativeFirebaseAppCheckProviderConfig; diff --git a/packages/app/lib/index.ts b/packages/app/lib/index.ts index 131ad4a115..5b00fb0a2b 100644 --- a/packages/app/lib/index.ts +++ b/packages/app/lib/index.ts @@ -17,6 +17,7 @@ export { firebase, utils, default } from './namespaced'; export * from './modular'; +export * from './types/common'; export type { ReactNativeFirebase, Utils, diff --git a/packages/app/lib/types/common.ts b/packages/app/lib/types/common.ts new file mode 100644 index 0000000000..8eae14d815 --- /dev/null +++ b/packages/app/lib/types/common.ts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +export type NextFn = (value: T) => void; +export type ErrorFn = (error: Error) => void; +export type CompleteFn = () => void; + +export interface Observer { + next: NextFn; + error: ErrorFn; + complete: CompleteFn; +} + +export type PartialObserver = Partial>; + +/** + * A function that unsubscribes from an event listener. + */ +export type Unsubscribe = () => void; From 2f447320b516008387b9b1b7848b581bc165f07b Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 16 Feb 2026 15:57:01 +0000 Subject: [PATCH 16/24] chore: ensure native module is types for app check --- packages/app-check/lib/namespaced.ts | 2 +- packages/app-check/lib/types/internal.ts | 29 +++++++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/packages/app-check/lib/namespaced.ts b/packages/app-check/lib/namespaced.ts index 8df01bf90a..c38c26b821 100644 --- a/packages/app-check/lib/namespaced.ts +++ b/packages/app-check/lib/namespaced.ts @@ -62,7 +62,7 @@ function hasProviderOptions( ); } -class FirebaseAppCheckModule extends FirebaseModule { +class FirebaseAppCheckModule extends FirebaseModule { _listenerCount: number; constructor( diff --git a/packages/app-check/lib/types/internal.ts b/packages/app-check/lib/types/internal.ts index 855c9a7040..e84b3e1be1 100644 --- a/packages/app-check/lib/types/internal.ts +++ b/packages/app-check/lib/types/internal.ts @@ -9,7 +9,7 @@ import type { ReactNativeFirebaseAppCheckProviderConfig, Unsubscribe, } from './appcheck'; -import type { FirebaseAppCheckTypes } from './namespaced' +import type { FirebaseAppCheckTypes } from './namespaced'; export type AppCheckInternal = AppCheck & { /** The FirebaseApp this module is associated with */ @@ -134,3 +134,30 @@ export type AppCheckInternal = AppCheck & { export type ProviderWithOptions = | ReactNativeFirebaseAppCheckProvider | ReactNativeFirebaseAppCheckProviderConfig; + +/** + * Wrapped native module interface for App Check. + * + * Note: React Native Firebase internally wraps native methods and auto-prepends the app name + * when `hasMultiAppSupport` is enabled. This interface represents the *wrapped* module shape + * that is exposed as `this.native` within FirebaseModule subclasses. + */ +export interface RNFBAppCheckModule { + initializeAppCheck(options: AppCheckOptions): Promise; + + setTokenAutoRefreshEnabled(enabled: boolean): void | Promise; + + configureProvider(provider: string, debugToken?: string): Promise; + + getToken(forceRefresh: boolean): Promise; + getLimitedUseToken(): Promise; + + addAppCheckListener(): void | Promise; + removeAppCheckListener(): void | Promise; +} + +declare module '@react-native-firebase/app/dist/module/internal/NativeModules' { + interface ReactNativeFirebaseNativeModules { + RNFBAppCheckModule: RNFBAppCheckModule; + } +} From 283b7ceaaa1bcdb97e551a92e2bcfb46f49f77c8 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 16 Feb 2026 16:03:29 +0000 Subject: [PATCH 17/24] chore: annotate public types and rm deprecated types from internal --- packages/app-check/lib/namespaced.ts | 13 +++++++++---- packages/app-check/lib/types/appcheck.ts | 23 +++++++++++++++++++++++ packages/app-check/lib/types/internal.ts | 13 ++++++------- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/packages/app-check/lib/namespaced.ts b/packages/app-check/lib/namespaced.ts index c38c26b821..678773adcc 100644 --- a/packages/app-check/lib/namespaced.ts +++ b/packages/app-check/lib/namespaced.ts @@ -34,7 +34,12 @@ import { Platform } from 'react-native'; import { setReactNativeModule } from '@react-native-firebase/app/dist/module/internal/nativeModule'; import fallBackModule from './web/RNFBAppCheckModule'; import { version } from './version'; -import type { AppCheckOptions, PartialObserver } from './types/appcheck'; +import type { + AppCheckOptions, + AppCheckProvider, + AppCheckTokenResult, + PartialObserver, +} from './types/appcheck'; import type { ProviderWithOptions } from './types/internal'; import type { FirebaseAppCheckTypes } from './types/namespaced'; import type { ReactNativeFirebase } from '@react-native-firebase/app'; @@ -152,7 +157,7 @@ class FirebaseAppCheckModule extends FirebaseModule { } activate( - siteKeyOrProvider: string | FirebaseAppCheckTypes.AppCheckProvider, + siteKeyOrProvider: string | AppCheckProvider, isTokenAutoRefreshEnabled?: boolean, ): Promise { if (isOther) { @@ -185,7 +190,7 @@ class FirebaseAppCheckModule extends FirebaseModule { this.native.setTokenAutoRefreshEnabled(isTokenAutoRefreshEnabled); } - getToken(forceRefresh?: boolean): Promise { + getToken(forceRefresh?: boolean): Promise { if (!forceRefresh) { return this.native.getToken(false); } else { @@ -193,7 +198,7 @@ class FirebaseAppCheckModule extends FirebaseModule { } } - getLimitedUseToken(): Promise { + getLimitedUseToken(): Promise { return this.native.getLimitedUseToken(); } diff --git a/packages/app-check/lib/types/appcheck.ts b/packages/app-check/lib/types/appcheck.ts index 9b95b4d3e0..314af82709 100644 --- a/packages/app-check/lib/types/appcheck.ts +++ b/packages/app-check/lib/types/appcheck.ts @@ -98,6 +98,7 @@ export interface AppCheckTokenResult { * An App Check provider. This can be either the built-in reCAPTCHA provider * or a custom provider. For more on custom providers, see * https://firebase.google.com/docs/app-check/web-custom-provider + * @public */ export interface AppCheckProvider { /** @@ -106,6 +107,10 @@ export interface AppCheckProvider { getToken(): Promise; } +/** + * Options for ReactNativeFirebaseAppCheckProvider. + * @public + */ export interface ReactNativeFirebaseAppCheckProviderOptions { /** * debug token to use, if any. Defaults to undefined, pre-configure tokens in firebase web console if needed @@ -113,6 +118,10 @@ export interface ReactNativeFirebaseAppCheckProviderOptions { debugToken?: string; } +/** + * Options for ReactNativeFirebaseAppCheckProvider on web. + * @public + */ export interface ReactNativeFirebaseAppCheckProviderWebOptions extends ReactNativeFirebaseAppCheckProviderOptions { /** * The web provider to use, either `reCaptchaV3` or `reCaptchaEnterprise`, defaults to `reCaptchaV3` @@ -125,6 +134,10 @@ export interface ReactNativeFirebaseAppCheckProviderWebOptions extends ReactNati siteKey?: string; } +/** + * Options for ReactNativeFirebaseAppCheckProvider on apple. + * @public + */ export interface ReactNativeFirebaseAppCheckProviderAppleOptions extends ReactNativeFirebaseAppCheckProviderOptions { /** * The apple provider to use, either `deviceCheck` or `appAttest`, or `appAttestWithDeviceCheckFallback`, @@ -134,6 +147,10 @@ export interface ReactNativeFirebaseAppCheckProviderAppleOptions extends ReactNa provider?: 'debug' | 'deviceCheck' | 'appAttest' | 'appAttestWithDeviceCheckFallback'; } +/** + * Options for ReactNativeFirebaseAppCheckProvider on android. + * @public + */ export interface ReactNativeFirebaseAppCheckProviderAndroidOptions extends ReactNativeFirebaseAppCheckProviderOptions { /** * The android provider to use, either `debug` or `playIntegrity`. default is `playIntegrity`. @@ -143,6 +160,7 @@ export interface ReactNativeFirebaseAppCheckProviderAndroidOptions extends React /** * Platform-specific provider options configuration. + * @public */ export type ReactNativeFirebaseAppCheckProviderOptionsMap = { web?: ReactNativeFirebaseAppCheckProviderWebOptions; @@ -156,11 +174,16 @@ export type ReactNativeFirebaseAppCheckProviderOptionsMap = { * that can be passed directly with providerOptions (for convenience in initialization). * The runtime accepts objects with providerOptions even if they don't have * getToken() and configure() methods. + * @public */ export interface ReactNativeFirebaseAppCheckProviderConfig { providerOptions: ReactNativeFirebaseAppCheckProviderOptionsMap; } +/** + * ReactNativeFirebaseAppCheckProvider interface. + * @public + */ export interface ReactNativeFirebaseAppCheckProvider extends AppCheckProvider { /** * Provider options for platform-specific configuration. diff --git a/packages/app-check/lib/types/internal.ts b/packages/app-check/lib/types/internal.ts index e84b3e1be1..50a35895e8 100644 --- a/packages/app-check/lib/types/internal.ts +++ b/packages/app-check/lib/types/internal.ts @@ -9,7 +9,8 @@ import type { ReactNativeFirebaseAppCheckProviderConfig, Unsubscribe, } from './appcheck'; -import type { FirebaseAppCheckTypes } from './namespaced'; + +type AppCheckListenerResult = AppCheckTokenResult & { readonly appName: string }; export type AppCheckInternal = AppCheck & { /** The FirebaseApp this module is associated with */ @@ -88,9 +89,7 @@ export type AppCheckInternal = AppCheck & { * * @returns A function that unsubscribes this listener. */ - onTokenChanged( - observer: PartialObserver, - ): () => void; + onTokenChanged(observer: PartialObserver): () => void; /** * Registers a listener to changes in the token state. There can be more @@ -110,7 +109,7 @@ export type AppCheckInternal = AppCheck & { * @returns A function that unsubscribes this listener. */ onTokenChanged( - onNext: (tokenResult: FirebaseAppCheckTypes.AppCheckListenerResult) => void, + onNext: (tokenResult: AppCheckListenerResult) => void, onError?: (error: Error) => void, onCompletion?: () => void, ): Unsubscribe; @@ -149,8 +148,8 @@ export interface RNFBAppCheckModule { configureProvider(provider: string, debugToken?: string): Promise; - getToken(forceRefresh: boolean): Promise; - getLimitedUseToken(): Promise; + getToken(forceRefresh: boolean): Promise; + getLimitedUseToken(): Promise; addAppCheckListener(): void | Promise; removeAppCheckListener(): void | Promise; From 572df70fc5b58455c84e4b9dce995f13086cb0d7 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 16 Feb 2026 16:24:03 +0000 Subject: [PATCH 18/24] refactor: use class ReactNativeFirebaseAppCheckProvider as type --- packages/app-check/lib/index.ts | 21 +-------------------- packages/app-check/lib/types/appcheck.ts | 24 +----------------------- packages/app-check/lib/types/internal.ts | 2 +- 3 files changed, 3 insertions(+), 44 deletions(-) diff --git a/packages/app-check/lib/index.ts b/packages/app-check/lib/index.ts index d9eb82f530..13ca7dfd89 100644 --- a/packages/app-check/lib/index.ts +++ b/packages/app-check/lib/index.ts @@ -16,26 +16,7 @@ */ // Export types from types/appcheck -export type { - AppCheckProvider, - CustomProviderOptions, - AppCheckOptions, - AppCheckToken, - AppCheckTokenResult, - AppCheckListenerResult, - PartialObserver, - Observer, - NextFn, - ErrorFn, - CompleteFn, - Unsubscribe, - ReactNativeFirebaseAppCheckProviderOptions, - ReactNativeFirebaseAppCheckProviderWebOptions, - ReactNativeFirebaseAppCheckProviderAppleOptions, - ReactNativeFirebaseAppCheckProviderAndroidOptions, - ReactNativeFirebaseAppCheckProvider, - AppCheck, -} from './types/appcheck'; +export type * from './types/appcheck'; // Export modular API functions export * from './modular'; diff --git a/packages/app-check/lib/types/appcheck.ts b/packages/app-check/lib/types/appcheck.ts index 314af82709..bbc1754d41 100644 --- a/packages/app-check/lib/types/appcheck.ts +++ b/packages/app-check/lib/types/appcheck.ts @@ -16,7 +16,7 @@ */ import type { FirebaseApp } from '@react-native-firebase/app'; -import type { CustomProvider } from '../providers'; +import type { CustomProvider, ReactNativeFirebaseAppCheckProvider } from '../providers'; export type { Unsubscribe, PartialObserver } from '@react-native-firebase/app'; /** @@ -179,25 +179,3 @@ export type ReactNativeFirebaseAppCheckProviderOptionsMap = { export interface ReactNativeFirebaseAppCheckProviderConfig { providerOptions: ReactNativeFirebaseAppCheckProviderOptionsMap; } - -/** - * ReactNativeFirebaseAppCheckProvider interface. - * @public - */ -export interface ReactNativeFirebaseAppCheckProvider extends AppCheckProvider { - /** - * Provider options for platform-specific configuration. - * This is set when configure() is called. - */ - providerOptions?: ReactNativeFirebaseAppCheckProviderOptionsMap; - - /** - * Specify how the app check provider should be configured. The new configuration is - * in effect when this call returns. You must call `getToken()` - * after this call to get a token using the new configuration. - * This custom provider allows for delayed configuration and re-configuration on all platforms - * so AppCheck has the same experience across all platforms, with the only difference being the native - * providers you choose to use on each platform. - */ - configure(options: ReactNativeFirebaseAppCheckProviderOptionsMap): void; -} diff --git a/packages/app-check/lib/types/internal.ts b/packages/app-check/lib/types/internal.ts index 50a35895e8..8c24672710 100644 --- a/packages/app-check/lib/types/internal.ts +++ b/packages/app-check/lib/types/internal.ts @@ -5,10 +5,10 @@ import type { AppCheckProvider, AppCheckTokenResult, PartialObserver, - ReactNativeFirebaseAppCheckProvider, ReactNativeFirebaseAppCheckProviderConfig, Unsubscribe, } from './appcheck'; +import type { ReactNativeFirebaseAppCheckProvider } from '../providers'; type AppCheckListenerResult = AppCheckTokenResult & { readonly appName: string }; From a2dbafb51064cdc7e5eec57472b4bedcb088f95a Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 16 Feb 2026 17:18:24 +0000 Subject: [PATCH 19/24] chore: get common types internally --- packages/app-check/lib/types/appcheck.ts | 5 ++++- packages/app-check/tsconfig.json | 3 ++- packages/app/lib/index.ts | 1 - 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/app-check/lib/types/appcheck.ts b/packages/app-check/lib/types/appcheck.ts index bbc1754d41..71b2683762 100644 --- a/packages/app-check/lib/types/appcheck.ts +++ b/packages/app-check/lib/types/appcheck.ts @@ -18,7 +18,10 @@ import type { FirebaseApp } from '@react-native-firebase/app'; import type { CustomProvider, ReactNativeFirebaseAppCheckProvider } from '../providers'; -export type { Unsubscribe, PartialObserver } from '@react-native-firebase/app'; +export type { + Unsubscribe, + PartialObserver, +} from '@react-native-firebase/app/dist/module/types/common'; /** * The Firebase App Check service interface. * diff --git a/packages/app-check/tsconfig.json b/packages/app-check/tsconfig.json index d23f0c8b5a..d3c1ec5ac4 100644 --- a/packages/app-check/tsconfig.json +++ b/packages/app-check/tsconfig.json @@ -13,7 +13,8 @@ "../app/dist/typescript/lib/internal/*" ], "@react-native-firebase/app/dist/module/internal": ["../app/dist/typescript/lib/internal"], - "@react-native-firebase/app": ["../app/dist/typescript/lib"] + "@react-native-firebase/app": ["../app/dist/typescript/lib"], + "@react-native-firebase/app/dist/module/types/common": ["../app/dist/typescript/lib/types/common"] } }, "include": ["lib/**/*", "../app/lib/internal/global.d.ts"], diff --git a/packages/app/lib/index.ts b/packages/app/lib/index.ts index 5b00fb0a2b..131ad4a115 100644 --- a/packages/app/lib/index.ts +++ b/packages/app/lib/index.ts @@ -17,7 +17,6 @@ export { firebase, utils, default } from './namespaced'; export * from './modular'; -export * from './types/common'; export type { ReactNativeFirebase, Utils, From 540ee789f6e90ae98a18a953d6391772bf8e4de6 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 16 Feb 2026 17:44:30 +0000 Subject: [PATCH 20/24] fix: export FirebaseAppCheckTypes as type --- packages/app-check/lib/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app-check/lib/index.ts b/packages/app-check/lib/index.ts index 13ca7dfd89..4b9fd720da 100644 --- a/packages/app-check/lib/index.ts +++ b/packages/app-check/lib/index.ts @@ -22,6 +22,6 @@ export type * from './types/appcheck'; export * from './modular'; // Export namespaced API -export { FirebaseAppCheckTypes } from './types/namespaced'; +export type { FirebaseAppCheckTypes } from './types/namespaced'; export * from './namespaced'; export { default } from './namespaced'; From 3366f97ca55967d19fad454abb3cf3b6330c0f16 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 9 Apr 2026 15:40:04 +0100 Subject: [PATCH 21/24] chore: port over js sdk app check types --- .../packages/app-check/app-check-sdk.d.ts | 248 ++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 .github/scripts/compare-types/packages/app-check/app-check-sdk.d.ts diff --git a/.github/scripts/compare-types/packages/app-check/app-check-sdk.d.ts b/.github/scripts/compare-types/packages/app-check/app-check-sdk.d.ts new file mode 100644 index 0000000000..f3239432a4 --- /dev/null +++ b/.github/scripts/compare-types/packages/app-check/app-check-sdk.d.ts @@ -0,0 +1,248 @@ +/** + * The Firebase App Check Web SDK. + * + * @remarks + * Firebase App Check does not work in a Node.js environment using `ReCaptchaV3Provider` or + * `ReCaptchaEnterpriseProvider`, but can be used in Node.js if you use + * `CustomProvider` and write your own attestation method. + * + * @packageDocumentation + */ + +import { FirebaseApp } from '@firebase/app'; +import { PartialObserver } from '@firebase/util'; +import { Unsubscribe } from '@firebase/util'; + +/** + * The Firebase App Check service interface. + * + * @public + */ +export declare interface AppCheck { + /** + * The {@link @firebase/app#FirebaseApp} this `AppCheck` instance is associated with. + */ + app: FirebaseApp; +} + +/* Excluded from this release type: _AppCheckComponentName */ + +/* Excluded from this release type: _AppCheckInternalComponentName */ + +/** + * Options for App Check initialization. + * @public + */ +export declare interface AppCheckOptions { + /** + * A reCAPTCHA V3 provider, reCAPTCHA Enterprise provider, or custom provider. + */ + provider: CustomProvider | ReCaptchaV3Provider | ReCaptchaEnterpriseProvider; + /** + * If set to true, enables automatic background refresh of App Check token. + */ + isTokenAutoRefreshEnabled?: boolean; +} + +declare interface AppCheckProvider { + /* Excluded from this release type: getToken */ + /* Excluded from this release type: initialize */ +} + +/** + * The token returned from an App Check provider. + * @public + */ +export declare interface AppCheckToken { + readonly token: string; + /** + * The local timestamp after which the token will expire. + */ + readonly expireTimeMillis: number; +} + +declare interface AppCheckTokenInternal extends AppCheckToken { + issuedAtTimeMillis: number; +} + +/** + * A listener that is called whenever the App Check token changes. + * @public + */ +export declare type AppCheckTokenListener = (token: AppCheckTokenResult) => void; + +/** + * Result returned by `getToken()`. + * @public + */ +export declare interface AppCheckTokenResult { + /** + * The token string in JWT format. + */ + readonly token: string; +} + +/** + * Custom provider class. + * @public + */ +export declare class CustomProvider implements AppCheckProvider { + private _customProviderOptions; + private _app?; + constructor(_customProviderOptions: CustomProviderOptions); + /* Excluded from this release type: getToken */ + /* Excluded from this release type: initialize */ + /* Excluded from this release type: isEqual */ +} + +/** + * Options when creating a {@link CustomProvider}. + * @public + */ +export declare interface CustomProviderOptions { + /** + * Function to get an App Check token through a custom provider + * service. + */ + getToken: () => Promise; +} + +/** + * Requests a Firebase App Check token. This method should be used + * only if you need to authorize requests to a non-Firebase backend. + * + * Returns limited-use tokens that are intended for use with your + * non-Firebase backend endpoints that are protected with + * + * Replay Protection. This method + * does not affect the token generation behavior of the + * #getAppCheckToken() method. + * + * @param appCheckInstance - The App Check service instance. + * @returns The limited use token. + * @public + */ +export declare function getLimitedUseToken(appCheckInstance: AppCheck): Promise; + +/** + * Get the current App Check token. If `forceRefresh` is false, this function first + * checks for a valid token in memory, then local persistence (IndexedDB). + * If not found, or if `forceRefresh` is true, it makes a request to the + * App Check endpoint for a fresh token. That request attaches + * to the most recent in-flight request if one is present. + * + * @param appCheckInstance - The App Check service instance. + * @param forceRefresh - If true, will always try to fetch a fresh token. + * If false, will use a cached token if found in storage. + * @public + */ +export declare function getToken(appCheckInstance: AppCheck, forceRefresh?: boolean): Promise; + +/** + * Activate App Check for the given app. Can be called only once per app. + * @param app - the {@link @firebase/app#FirebaseApp} to activate App Check for + * @param options - App Check initialization options + * @public + */ +export declare function initializeAppCheck(app: FirebaseApp | undefined, options: AppCheckOptions): AppCheck; + +/** + * Registers a listener to changes in the token state. There can be more + * than one listener registered at the same time for one or more + * App Check instances. The listeners call back on the UI thread whenever + * the current token associated with this App Check instance changes. + * + * @param appCheckInstance - The App Check service instance. + * @param observer - An object with `next`, `error`, and `complete` + * properties. `next` is called with an + * {@link AppCheckTokenResult} + * whenever the token changes. `error` is optional and is called if an + * error is thrown by the listener (the `next` function). `complete` + * is unused, as the token stream is unending. + * + * @returns A function that unsubscribes this listener. + * @public + */ +export declare function onTokenChanged(appCheckInstance: AppCheck, observer: PartialObserver): Unsubscribe; + +/** + * Registers a listener to changes in the token state. There can be more + * than one listener registered at the same time for one or more + * App Check instances. The listeners call back on the UI thread whenever + * the current token associated with this App Check instance changes. + * + * @param appCheckInstance - The App Check service instance. + * @param onNext - When the token changes, this function is called with an + * {@link AppCheckTokenResult}. + * @param onError - Optional. Called if there is an error thrown by the + * listener (the `onNext` function). + * @param onCompletion - Currently unused, as the token stream is unending. + * @returns A function that unsubscribes this listener. + * @public + */ +export declare function onTokenChanged(appCheckInstance: AppCheck, onNext: (tokenResult: AppCheckTokenResult) => void, onError?: (error: Error) => void, onCompletion?: () => void): Unsubscribe; +export { PartialObserver } + +/** + * App Check provider that can obtain a reCAPTCHA Enterprise token and exchange it + * for an App Check token. + * + * @public + */ +export declare class ReCaptchaEnterpriseProvider implements AppCheckProvider { + private _siteKey; + private _app?; + private _heartbeatServiceProvider?; + /** + * Throttle requests on certain error codes to prevent too many retries + * in a short time. + */ + private _throttleData; + /** + * Create a ReCaptchaEnterpriseProvider instance. + * @param siteKey - reCAPTCHA Enterprise score-based site key. + */ + constructor(_siteKey: string); + /* Excluded from this release type: getToken */ + /* Excluded from this release type: initialize */ + /* Excluded from this release type: isEqual */ +} + +/** + * App Check provider that can obtain a reCAPTCHA V3 token and exchange it + * for an App Check token. + * + * @public + */ +export declare class ReCaptchaV3Provider implements AppCheckProvider { + private _siteKey; + private _app?; + private _heartbeatServiceProvider?; + /** + * Throttle requests on certain error codes to prevent too many retries + * in a short time. + */ + private _throttleData; + /** + * Create a ReCaptchaV3Provider instance. + * @param siteKey - ReCAPTCHA V3 siteKey. + */ + constructor(_siteKey: string); + /* Excluded from this release type: getToken */ + /* Excluded from this release type: initialize */ + /* Excluded from this release type: isEqual */ +} + +/** + * Set whether App Check will automatically refresh tokens as needed. + * + * @param appCheckInstance - The App Check service instance. + * @param isTokenAutoRefreshEnabled - If true, the SDK automatically + * refreshes App Check tokens as needed. This overrides any value set + * during `initializeAppCheck()`. + * @public + */ +export declare function setTokenAutoRefreshEnabled(appCheckInstance: AppCheck, isTokenAutoRefreshEnabled: boolean): void; +export { Unsubscribe } + +export { } From 6470f1c2cd18a8d0723e85a5de4c0d683b47d1ab Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 9 Apr 2026 16:41:46 +0100 Subject: [PATCH 22/24] docs: created v25 migraiton guide + update app-check docs with provider configuration --- docs/app-check/usage/index.md | 31 +++++++++++++ docs/migrating-to-v24.md | 1 + docs/migrating-to-v25.md | 86 +++++++++++++++++++++++++++++++++++ docs/typescript.md | 2 +- 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 docs/migrating-to-v25.md diff --git a/docs/app-check/usage/index.md b/docs/app-check/usage/index.md index ce4357dd36..fca8f3f249 100644 --- a/docs/app-check/usage/index.md +++ b/docs/app-check/usage/index.md @@ -185,6 +185,8 @@ It is through the use of a react-native-specific `ReactNativeFirebaseAppCheckPro So AppCheck module initialization is done in two steps in react-native-firebase - first you create and configure the custom provider, then you initialize AppCheck using that custom provider. +Starting in v25, the modular App Check helpers and types are exported from `@react-native-firebase/app-check` at the package root to better match the Firebase JS SDK. For example, import `initializeAppCheck`, `AppCheck`, and `AppCheckTokenResult` directly from `@react-native-firebase/app-check` when using the modular API. + ### Configure a Custom Provider To configure the react-native-firebase custom provider, first obtain one, then configure it according to the providers you want to use on each platform. @@ -223,6 +225,35 @@ const appCheck = await initializeAppCheck(getApp(), { }); ``` +### Inline Provider Configuration + +If you do not need to keep a provider instance around, you can pass the React Native provider configuration inline using `providerOptions`: + +```javascript +import { getApp } from '@react-native-firebase/app'; +import { initializeAppCheck } from '@react-native-firebase/app-check'; + +const appCheck = await initializeAppCheck(getApp(), { + provider: { + providerOptions: { + android: { + provider: __DEV__ ? 'debug' : 'playIntegrity', + debugToken: 'some token you have configured for your project firebase web console', + }, + apple: { + provider: __DEV__ ? 'debug' : 'appAttestWithDeviceCheckFallback', + debugToken: 'some token you have configured for your project firebase web console', + }, + web: { + provider: 'reCaptchaV3', + siteKey: 'unknown', + }, + }, + }, + isTokenAutoRefreshEnabled: true, +}); +``` + ### Verify AppCheck was initialized correctly After initializing the custom provider, you can verify AppCheck is working by logging a response from the token server: diff --git a/docs/migrating-to-v24.md b/docs/migrating-to-v24.md index bda49224ab..8db104b14e 100644 --- a/docs/migrating-to-v24.md +++ b/docs/migrating-to-v24.md @@ -2,6 +2,7 @@ title: Migrating to v24 description: Migrate to React Native Firebase v24. previous: /migrate-to-v23 +next: /migrating-to-v25 --- # Firestore diff --git a/docs/migrating-to-v25.md b/docs/migrating-to-v25.md new file mode 100644 index 0000000000..e4ee2d9385 --- /dev/null +++ b/docs/migrating-to-v25.md @@ -0,0 +1,86 @@ +--- +title: Migrating to v25 +description: Migrate to React Native Firebase v25. +previous: /migrating-to-v24 +next: /typescript +--- + +# App Check + +Version 25 aligns App Check's modular exports more closely with the Firebase JS SDK. If your app uses the modular API, import App Check types and helpers directly from `@react-native-firebase/app-check` instead of routing modular code through `FirebaseAppCheckTypes`. + +The most common updates are: + +- Import modular helpers such as `initializeAppCheck`, `getToken`, `getLimitedUseToken`, `setTokenAutoRefreshEnabled`, and `onTokenChanged` from the package root. +- Import modular types such as `AppCheck` and `AppCheckTokenResult` from the package root. +- Keep using `ReactNativeFirebaseAppCheckProvider` on React Native when you need native provider selection for Android / Apple / web. + +```js +// Previously +import appCheck, { FirebaseAppCheckTypes } from '@react-native-firebase/app-check'; + +const instance = appCheck(); + +instance.getToken().then((result: FirebaseAppCheckTypes.AppCheckTokenResult) => { + console.log(result.token); +}); +``` + +```js +// Now +import { getApp } from '@react-native-firebase/app'; +import { + AppCheckTokenResult, + ReactNativeFirebaseAppCheckProvider, + initializeAppCheck, + getToken, +} from '@react-native-firebase/app-check'; + +const provider = new ReactNativeFirebaseAppCheckProvider(); + +provider.configure({ + android: { + provider: __DEV__ ? 'debug' : 'playIntegrity', + }, + apple: { + provider: __DEV__ ? 'debug' : 'appAttestWithDeviceCheckFallback', + }, + web: { + provider: 'reCaptchaV3', + siteKey: 'your-recaptcha-site-key', + }, +}); + +const appCheck = await initializeAppCheck(getApp(), { + provider, + isTokenAutoRefreshEnabled: true, +}); + +const result: AppCheckTokenResult = await getToken(appCheck); +console.log(result.token); +``` + +If you do not need to reuse a provider instance, you can now also pass the React Native provider configuration inline through `providerOptions`: + +```js +import { getApp } from '@react-native-firebase/app'; +import { initializeAppCheck } from '@react-native-firebase/app-check'; + +await initializeAppCheck(getApp(), { + provider: { + providerOptions: { + android: { + provider: __DEV__ ? 'debug' : 'playIntegrity', + }, + apple: { + provider: __DEV__ ? 'debug' : 'appAttestWithDeviceCheckFallback', + }, + web: { + provider: 'reCaptchaV3', + siteKey: 'your-recaptcha-site-key', + }, + }, + }, + isTokenAutoRefreshEnabled: true, +}); +``` diff --git a/docs/typescript.md b/docs/typescript.md index 83c8a8169d..bbb58cd93f 100644 --- a/docs/typescript.md +++ b/docs/typescript.md @@ -2,7 +2,7 @@ title: TypeScript description: Using TypeScript with React Native Firebase next: /other-platforms -previous: /migrating-to-v24 +previous: /migrating-to-v25 --- The React Native Firebase project comes with support for TypeScript. The project provides From 8c75ab41cff83a924d9f121b5059b9157ebf7c74 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 9 Apr 2026 16:42:59 +0100 Subject: [PATCH 23/24] chore: update comparison script with app check types --- .../packages/app-check/config.ts | 102 ++++++++++++++++++ .github/scripts/compare-types/src/registry.ts | 16 +++ 2 files changed, 118 insertions(+) create mode 100644 .github/scripts/compare-types/packages/app-check/config.ts diff --git a/.github/scripts/compare-types/packages/app-check/config.ts b/.github/scripts/compare-types/packages/app-check/config.ts new file mode 100644 index 0000000000..118c64308c --- /dev/null +++ b/.github/scripts/compare-types/packages/app-check/config.ts @@ -0,0 +1,102 @@ +/** + * Known differences between the firebase-js-sdk @firebase/app-check public + * API and the @react-native-firebase/app-check modular API. + * + * Each entry must have a `name` (the export name) and a `reason` explaining + * why the difference exists. Any difference NOT listed here will cause CI to + * fail so that new drift is caught and deliberately acknowledged. + */ + +import type { PackageConfig } from '../../src/types'; + +const config: PackageConfig = { + nameMapping: {}, + missingInRN: [ + { + name: 'AppCheckTokenListener', + reason: + 'RN Firebase exposes token change listeners through the `onTokenChanged` overloads but does not export the standalone listener type alias from the firebase-js-sdk.', + }, + { + name: 'PartialObserver', + reason: + 'RN Firebase re-exports this type from `@react-native-firebase/app` common types rather than mirroring the firebase-js-sdk utility export directly.', + }, + { + name: 'ReCaptchaEnterpriseProvider', + reason: + 'Web-only reCAPTCHA Enterprise provider from the firebase-js-sdk. RN Firebase uses `ReactNativeFirebaseAppCheckProvider` to configure native platform providers instead.', + }, + { + name: 'ReCaptchaV3Provider', + reason: + 'Web-only reCAPTCHA v3 provider from the firebase-js-sdk. RN Firebase uses `ReactNativeFirebaseAppCheckProvider` for cross-platform provider configuration.', + }, + { + name: 'Unsubscribe', + reason: + 'RN Firebase re-exports this type from `@react-native-firebase/app` common types rather than mirroring the firebase-js-sdk utility export directly.', + }, + ], + extraInRN: [ + { + name: 'AppCheckProvider', + reason: + 'RN Firebase keeps the provider interface public because its native and React Native-specific provider classes are part of the package surface.', + }, + { + name: 'ReactNativeFirebaseAppCheckProviderOptions', + reason: + 'RN Firebase-specific base options type used to configure native and React Native provider behavior across platforms.', + }, + { + name: 'ReactNativeFirebaseAppCheckProviderWebOptions', + reason: + 'RN Firebase-specific web provider config shape used by `ReactNativeFirebaseAppCheckProvider.configure()`.', + }, + { + name: 'ReactNativeFirebaseAppCheckProviderAppleOptions', + reason: + 'RN Firebase-specific Apple provider config shape used to select native iOS/macOS App Check providers.', + }, + { + name: 'ReactNativeFirebaseAppCheckProviderAndroidOptions', + reason: + 'RN Firebase-specific Android provider config shape used to select native Android App Check providers.', + }, + { + name: 'ReactNativeFirebaseAppCheckProviderOptionsMap', + reason: + 'RN Firebase-specific cross-platform provider options map used to configure Android, Apple, and web providers together.', + }, + { + name: 'ReactNativeFirebaseAppCheckProviderConfig', + reason: + 'RN Firebase convenience config object that allows provider options to be passed directly during initialization.', + }, + { + name: 'ReactNativeFirebaseAppCheckProvider', + reason: + 'RN Firebase-specific provider class that wraps native platform provider selection; there is no firebase-js-sdk equivalent export.', + }, + ], + differentShape: [ + { + name: 'initializeAppCheck', + reason: + 'RN Firebase returns `Promise` because App Check initialization crosses the native bridge, whereas the firebase-js-sdk returns `AppCheck` synchronously.', + }, + { + name: 'AppCheckOptions', + reason: + 'RN Firebase accepts `CustomProvider`, `ReactNativeFirebaseAppCheckProvider`, or a RN-specific provider config object instead of the firebase-js-sdk reCAPTCHA provider classes.', + }, + { + name: 'CustomProvider', + reason: + 'The RN Firebase `CustomProvider` class is tailored to the React Native/native initialization model, so its public class shape differs from the firebase-js-sdk version.', + }, + ], +}; + +export default config; diff --git a/.github/scripts/compare-types/src/registry.ts b/.github/scripts/compare-types/src/registry.ts index d05982f7b4..314f9063e2 100644 --- a/.github/scripts/compare-types/src/registry.ts +++ b/.github/scripts/compare-types/src/registry.ts @@ -14,6 +14,7 @@ import path from 'path'; import type { PackageConfig } from './types'; import aiConfig from '../packages/ai/config'; +import appCheckConfig from '../packages/app-check/config'; import firestoreConfig from '../packages/firestore/config'; import firestorePipelinesConfig from '../packages/firestore-pipelines/config'; @@ -109,6 +110,21 @@ export const packages: PackageEntry[] = [ ], config: aiConfig, }, + { + name: 'app-check', + firebaseSdkTypesPaths: [ + path.join(SCRIPT_DIR, 'packages', 'app-check', 'app-check-sdk.d.ts'), + ], + rnFirebaseModularFiles: [ + path.join(rnDist('app-check'), 'types', 'appcheck.d.ts'), + path.join(rnDist('app-check'), 'modular.d.ts'), + ], + rnFirebaseSupportFiles: [ + path.join(rnDist('app-check'), 'providers.d.ts'), + path.join(rnDist('app-check'), 'types', 'internal.d.ts'), + ], + config: appCheckConfig, + }, { name: 'firestore', firebaseSdkTypesPaths: [ From 28b725e1a485cef3dc3c8e2ebc140a9bbd30a9ed Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 9 Apr 2026 17:00:41 +0100 Subject: [PATCH 24/24] docs: add v25 to spellchecker --- .spellcheck.dict.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.spellcheck.dict.txt b/.spellcheck.dict.txt index 9852f5c292..31ca459a4b 100644 --- a/.spellcheck.dict.txt +++ b/.spellcheck.dict.txt @@ -225,6 +225,7 @@ v6 v7 v9 v22 +v25 Ventura VertexAI VPN