From f3b3877b9e01a777aac79b6cbe943099c96e744b Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 16:26:34 +0100 Subject: [PATCH 01/12] refactor(installations): convert package sources to TypeScript --- packages/installations/lib/index.js | 81 ---------- packages/installations/lib/index.ts | 163 ++++++++++++++++++++ packages/installations/lib/modular/index.js | 63 -------- packages/installations/lib/modular/index.ts | 88 +++++++++++ packages/installations/package.json | 38 ++++- packages/installations/tsconfig.json | 18 +++ 6 files changed, 303 insertions(+), 148 deletions(-) delete mode 100644 packages/installations/lib/index.js create mode 100644 packages/installations/lib/index.ts delete mode 100644 packages/installations/lib/modular/index.js create mode 100644 packages/installations/lib/modular/index.ts create mode 100644 packages/installations/tsconfig.json diff --git a/packages/installations/lib/index.js b/packages/installations/lib/index.js deleted file mode 100644 index 65deb37618..0000000000 --- a/packages/installations/lib/index.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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 { isIOS } from '@react-native-firebase/app/dist/module/common'; -import { - createModuleNamespace, - FirebaseModule, - getFirebaseRoot, -} from '@react-native-firebase/app/dist/module/internal'; - -import version from './version'; - -const statics = {}; - -const namespace = 'installations'; - -const nativeModuleName = 'RNFBInstallationsModule'; - -class FirebaseInstallationsModule extends FirebaseModule { - getId() { - return this.native.getId(); - } - - getToken(forceRefresh) { - if (!forceRefresh) { - return this.native.getToken(false); - } else { - return this.native.getToken(true); - } - } - - delete() { - return this.native.delete(); - } - - onIdChange() { - if (isIOS) { - return () => {}; - } - - // TODO implement change listener on Android - return () => {}; - } -} - -// import { SDK_VERSION } from '@react-native-firebase/installations'; -export const SDK_VERSION = version; - -// import installations from '@react-native-firebase/installations'; -// installations().X(...); -export default createModuleNamespace({ - statics, - version, - namespace, - nativeModuleName, - nativeEvents: false, // TODO implement android id change listener: ['installations_id_changed'], - hasMultiAppSupport: true, - hasCustomUrlOrRegionSupport: false, - ModuleClass: FirebaseInstallationsModule, -}); - -// import installations, { firebase } from '@react-native-firebase/installations'; -// installations().X(...); -// firebase.installations().X(...); -export const firebase = getFirebaseRoot(); - -export * from './modular'; diff --git a/packages/installations/lib/index.ts b/packages/installations/lib/index.ts new file mode 100644 index 0000000000..d127c7bc15 --- /dev/null +++ b/packages/installations/lib/index.ts @@ -0,0 +1,163 @@ +/* + * 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 { isIOS } from '@react-native-firebase/app/dist/module/common'; +import type { ReactNativeFirebase } from '@react-native-firebase/app'; +import { + createModuleNamespace, + FirebaseModule, + getFirebaseRoot, +} from '@react-native-firebase/app/dist/module/internal'; + +import { version } from './version'; + +const statics = {}; + +const namespace = 'installations'; + +const nativeModuleName = 'RNFBInstallationsModule'; + +interface InstallationsNativeModule { + getId(): Promise; + getToken(forceRefresh: boolean): Promise; + delete(): Promise; +} + +/** + * Firebase Installations package for React Native. + * + * @firebase installations + */ +export namespace FirebaseInstallationsTypes { + export interface Statics { + SDK_VERSION: string; + } + + /** + * The Firebase Installations service is available for the default app or a given app. + */ + export interface Module extends ReactNativeFirebase.FirebaseModule { + /** + * The current `FirebaseApp` instance for this Firebase service. + */ + app: ReactNativeFirebase.FirebaseApp; + + /** + * Creates a Firebase Installation if there isn't one for the app and returns the Installation ID. + */ + getId(): Promise; + + /** + * Retrieves a valid installation auth token. + */ + getToken(forceRefresh?: boolean): Promise; + + /** + * Deletes the Firebase Installation and all associated data from the Firebase backend. + */ + delete(): Promise; + } +} + +class FirebaseInstallationsModule extends FirebaseModule { + get native(): InstallationsNativeModule { + return super.native as unknown as InstallationsNativeModule; + } + + getId(): Promise { + return this.native.getId(); + } + + getToken(forceRefresh?: boolean): Promise { + if (!forceRefresh) { + return this.native.getToken(false); + } else { + return this.native.getToken(true); + } + } + + delete(): Promise { + return this.native.delete(); + } + + onIdChange(): () => void { + if (isIOS) { + return () => {}; + } + + // TODO implement change listener on Android + return () => {}; + } +} + +type InstallationsNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebaseInstallationsTypes.Module, + FirebaseInstallationsTypes.Statics +> & { + firebase: ReactNativeFirebase.Module; + app(name?: string): ReactNativeFirebase.FirebaseApp; +}; + +// import { SDK_VERSION } from '@react-native-firebase/installations'; +export const SDK_VERSION = version; + +// import installations from '@react-native-firebase/installations'; +// installations().X(...); +const defaultExport = createModuleNamespace({ + statics, + version, + namespace, + nativeModuleName, + nativeEvents: false, // TODO implement android id change listener: ['installations_id_changed'], + hasMultiAppSupport: true, + hasCustomUrlOrRegionSupport: false, + ModuleClass: FirebaseInstallationsModule, +}) as unknown as InstallationsNamespace; + +export default defaultExport; + +// import installations, { firebase } from '@react-native-firebase/installations'; +// installations().X(...); +// firebase.installations().X(...); +export const firebase = getFirebaseRoot() as unknown as ReactNativeFirebase.Module & { + installations: typeof defaultExport; + app( + name?: string, + ): ReactNativeFirebase.FirebaseApp & { installations(): FirebaseInstallationsTypes.Module }; +}; + +export * from './modular'; + +/** + * Attach namespace to `firebase.` and `FirebaseApp.`. + */ +declare module '@react-native-firebase/app' { + namespace ReactNativeFirebase { + import FirebaseModuleWithStaticsAndApp = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; + + interface Module { + installations: FirebaseModuleWithStaticsAndApp< + FirebaseInstallationsTypes.Module, + FirebaseInstallationsTypes.Statics + >; + } + + interface FirebaseApp { + installations(): FirebaseInstallationsTypes.Module; + } + } +} diff --git a/packages/installations/lib/modular/index.js b/packages/installations/lib/modular/index.js deleted file mode 100644 index 85a7a279b8..0000000000 --- a/packages/installations/lib/modular/index.js +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 { getApp } from '@react-native-firebase/app'; -import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; -/** - * @typedef {import('..').FirebaseInstallationsTypes.Module} FirebaseInstallation - */ - -export function getInstallations(app) { - if (app) { - return getApp(app.name).installations(); - } - return getApp().installations(); -} - -/** - * @param {FirebaseInstallation} installations - * @returns {Promise} - */ -export function deleteInstallations(installations) { - return installations.delete.call(installations, MODULAR_DEPRECATION_ARG); -} - -/** - * @param {FirebaseInstallation} installations - * @returns {Promise} - */ -export function getId(installations) { - return installations.getId.call(installations, MODULAR_DEPRECATION_ARG); -} - -/** - * @param {FirebaseInstallation} installations - * @param {boolean | undefined} forceRefresh - * @returns {Promise} - */ -export function getToken(installations, forceRefresh) { - return installations.getToken.call(installations, forceRefresh, MODULAR_DEPRECATION_ARG); -} - -/** - * @param {FirebaseInstallation} installations - * @param {(string) => void} callback - * @returns {() => void} - */ -export function onIdChange(_installations, _callback) { - throw new Error('onIdChange() is unsupported by the React Native Firebase SDK.'); -} diff --git a/packages/installations/lib/modular/index.ts b/packages/installations/lib/modular/index.ts new file mode 100644 index 0000000000..d47a297c0c --- /dev/null +++ b/packages/installations/lib/modular/index.ts @@ -0,0 +1,88 @@ +/* + * 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 { getApp } from '@react-native-firebase/app'; +import type { ReactNativeFirebase } from '@react-native-firebase/app'; +import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; +import type { FirebaseInstallationsTypes } from '..'; + +type FirebaseInstallation = FirebaseInstallationsTypes.Module; +type IdChangeCallbackFn = (installationId: string) => void; +type IdChangeUnsubscribeFn = () => void; +type InstallationsModularDeprecationArg = string; + +interface FirebaseInstallationInternal extends FirebaseInstallation { + delete(deprecationArg?: InstallationsModularDeprecationArg): Promise; + getId(deprecationArg?: InstallationsModularDeprecationArg): Promise; + getToken( + forceRefresh?: boolean, + deprecationArg?: InstallationsModularDeprecationArg, + ): Promise; +} + +/** + * Returns an instance of Installations associated with the given FirebaseApp instance. + */ +export function getInstallations(app?: ReactNativeFirebase.FirebaseApp): FirebaseInstallation { + if (app) { + return getApp(app.name).installations(); + } + return getApp().installations(); +} + +/** + * Deletes the Firebase Installation and all associated data. + */ +export function deleteInstallations(installations?: FirebaseInstallation): Promise { + const internalInstallations = installations as FirebaseInstallationInternal; + return internalInstallations.delete.call(internalInstallations, MODULAR_DEPRECATION_ARG); +} + +/** + * Creates a Firebase Installation if there isn't one for the app and returns the Installation ID. + */ +export function getId(installations: FirebaseInstallation): Promise { + const internalInstallations = installations as FirebaseInstallationInternal; + return internalInstallations.getId.call(internalInstallations, MODULAR_DEPRECATION_ARG); +} + +/** + * Returns a Firebase Installations auth token, identifying the current Firebase Installation. + */ +export function getToken( + installations: FirebaseInstallation, + forceRefresh?: boolean, +): Promise { + const internalInstallations = installations as FirebaseInstallationInternal; + return internalInstallations.getToken.call( + internalInstallations, + forceRefresh, + MODULAR_DEPRECATION_ARG, + ); +} + +/** + * Throw an error since react-native-firebase does not support this method. + * + * Sets a new callback that will get called when Installation ID changes. Returns an unsubscribe function that will remove the callback when called. + */ +export function onIdChange( + _installations: FirebaseInstallation, + _callback: IdChangeCallbackFn, +): IdChangeUnsubscribeFn { + throw new Error('onIdChange() is unsupported by the React Native Firebase SDK.'); +} diff --git a/packages/installations/package.json b/packages/installations/package.json index de1373a88d..125db21776 100644 --- a/packages/installations/package.json +++ b/packages/installations/package.json @@ -3,12 +3,13 @@ "version": "24.0.0", "author": "Invertase (http://invertase.io)", "description": "React Native Firebase - Installations", - "main": "lib/index.js", - "types": "lib/index.d.ts", + "main": "./dist/module/index.js", + "types": "./dist/typescript/lib/index.d.ts", "scripts": { - "build": "genversion --semi lib/version.js", + "build": "genversion --esm --semi lib/version.ts", "build:clean": "rimraf android/build && rimraf ios/build", - "prepare": "yarn run build" + "compile": "bob build", + "prepare": "yarn run build && yarn compile" }, "repository": { "type": "git", @@ -27,5 +28,34 @@ "publishConfig": { "access": "public", "provenance": true + }, + "devDependencies": { + "react-native-builder-bob": "^0.40.13" + }, + "exports": { + ".": { + "source": "./lib/index.ts", + "types": "./dist/typescript/lib/index.d.ts", + "default": "./dist/module/index.js" + }, + "./package.json": "./package.json" + }, + "react-native-builder-bob": { + "source": "lib", + "output": "dist", + "targets": [ + [ + "module", + { + "esm": true + } + ], + [ + "typescript", + { + "tsc": "../../node_modules/.bin/tsc" + } + ] + ] } } diff --git a/packages/installations/tsconfig.json b/packages/installations/tsconfig.json new file mode 100644 index 0000000000..4cb30685a7 --- /dev/null +++ b/packages/installations/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.packages.base.json", + "compilerOptions": { + "baseUrl": ".", + "rootDir": ".", + "paths": { + "@react-native-firebase/app/dist/module/common/*": ["../app/dist/typescript/lib/common/*"], + "@react-native-firebase/app/dist/module/common": ["../app/dist/typescript/lib/common"], + "@react-native-firebase/app/dist/module/internal/*": [ + "../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"] + } + }, + "include": ["lib/**/*.ts"], + "exclude": ["node_modules", "dist", "__tests__", "**/*.test.ts", "lib/**/*.d.ts"] +} From 73fca45247ee3ebe3a188cff3c4a423d2b68b5c1 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 16:38:01 +0100 Subject: [PATCH 02/12] refactor(installations): split modular and namespaced TypeScript surfaces --- packages/installations/lib/index.d.ts | 173 ------------------ packages/installations/lib/index.ts | 150 +-------------- .../lib/{modular/index.ts => modular.ts} | 39 ++-- packages/installations/lib/modular/index.d.ts | 41 ----- packages/installations/lib/namespaced.ts | 92 ++++++++++ .../installations/lib/types/installations.ts | 43 +++++ packages/installations/lib/types/internal.ts | 36 ++++ .../installations/lib/types/namespaced.ts | 108 +++++++++++ 8 files changed, 301 insertions(+), 381 deletions(-) delete mode 100644 packages/installations/lib/index.d.ts rename packages/installations/lib/{modular/index.ts => modular.ts} (62%) delete mode 100644 packages/installations/lib/modular/index.d.ts create mode 100644 packages/installations/lib/namespaced.ts create mode 100644 packages/installations/lib/types/installations.ts create mode 100644 packages/installations/lib/types/internal.ts create mode 100644 packages/installations/lib/types/namespaced.ts diff --git a/packages/installations/lib/index.d.ts b/packages/installations/lib/index.d.ts deleted file mode 100644 index 47b4434dc0..0000000000 --- a/packages/installations/lib/index.d.ts +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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 { ReactNativeFirebase } from '@react-native-firebase/app'; - -/** - * Firebase Installations package for React Native. - * - * #### Example 1 - * - * Access the firebase export from the `installations` package: - * - * ```js - * import { firebase } from '@react-native-firebase/installations'; - * - * // firebase.installations().X - * ``` - * - * #### Example 2 - * - * Using the default export from the `installations` package: - * - * ```js - * import installations from '@react-native-firebase/installations'; - * - * // installations().X - * ``` - * - * #### Example 3 - * - * Using the default export from the `app` package: - * - * ```js - * import firebase from '@react-native-firebase/app'; - * import '@react-native-firebase/installations'; - * - * // firebase.installations().X - * ``` - * - * @firebase installations - */ -export namespace FirebaseInstallationsTypes { - import FirebaseModule = ReactNativeFirebase.FirebaseModule; - - export interface Statics { - SDK_VERSION: string; - } - - /** - * The Firebase Installations service is available for the default app or a given app. - * - * #### Example 1 - * - * Get the installations instance for the **default app**: - * - * ```js - * const installationsForDefaultApp = firebase.installations(); - * ``` - * - * #### Example 2 - * - * Get the installations instance for a **secondary app**: - *˚ - * ```js - * const otherApp = firebase.app('otherApp'); - * const installationsForOtherApp = firebase.installations(otherApp); - * ``` - * - */ - export class Module extends FirebaseModule { - /** - * The current `FirebaseApp` instance for this Firebase service. - */ - app: ReactNativeFirebase.FirebaseApp; - - /** - * Creates a Firebase Installation if there isn't one for the app and - * returns the Installation ID. The installation ID is a globally unique, - * stable, URL-safe base64 string identifier that uniquely identifies the app instance. - * NOTE: If the application already has an existing FirebaseInstanceID then the InstanceID identifier will be used. - * - * @return Firebase Installation ID, this is an url-safe base64 string of a 128-bit integer. - */ - getId(): Promise; - - /** - * Retrieves (locally or from the server depending on forceRefresh value) a valid installation auth token. - * An existing token may be invalidated or expire, so it is recommended to fetch the installation auth token - * before any request to external servers (it will be refreshed automatically for firebase API calls). - * This method should be used with forceRefresh == YES when e.g. a request with the previously fetched - * installation auth token failed with “Not Authorized” error. - * - * @param forceRefresh Options to get an auth token either by force refreshing or not. - * @return Firebase Installation Authentication Token - */ - getToken(forceRefresh?: boolean): Promise; - - /** - * Deletes the Firebase Installation and all associated data from the Firebase backend. - * This call may cause Firebase Cloud Messaging, Firebase Remote Config, Firebase Predictions, - * or Firebase In-App Messaging to not function properly. Fetching a new installations ID should - * reset all the dependent services to a stable state again. A network connection is required - * for the method to succeed. If it fails, the existing installation data remains untouched. - */ - delete(): Promise; - - /** - * TODO implement id change listener for android. - * - * Sets a new callback that will get called when Installation ID changes. - * Returns an unsubscribe function that will remove the callback when called. - * Only the Android SDK supports sending ID change events. - * - * @android - */ - // onIdChange(callback: (installationId: string) => void): () => void; - } -} - -type InstallationsNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< - FirebaseInstallationsTypes.Module, - FirebaseInstallationsTypes.Statics -> & { - firebase: ReactNativeFirebase.Module; - app(name?: string): ReactNativeFirebase.FirebaseApp; -}; - -declare const defaultExport: InstallationsNamespace; - -export const firebase: ReactNativeFirebase.Module & { - installations: typeof defaultExport; - app( - name?: string, - ): ReactNativeFirebase.FirebaseApp & { installations(): FirebaseInstallationsTypes.Module }; -}; - -export * from './modular'; - -export default defaultExport; - -/** - * Attach namespace to `firebase.` and `FirebaseApp.`. - */ -declare module '@react-native-firebase/app' { - namespace ReactNativeFirebase { - import FirebaseModuleWithStaticsAndApp = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; - - interface Module { - installations: FirebaseModuleWithStaticsAndApp< - FirebaseInstallationsTypes.Module, - FirebaseInstallationsTypes.Statics - >; - } - - interface FirebaseApp { - installations(): FirebaseInstallationsTypes.Module; - } - } -} diff --git a/packages/installations/lib/index.ts b/packages/installations/lib/index.ts index d127c7bc15..bc592b178f 100644 --- a/packages/installations/lib/index.ts +++ b/packages/installations/lib/index.ts @@ -15,149 +15,13 @@ * */ -import { isIOS } from '@react-native-firebase/app/dist/module/common'; -import type { ReactNativeFirebase } from '@react-native-firebase/app'; -import { - createModuleNamespace, - FirebaseModule, - getFirebaseRoot, -} from '@react-native-firebase/app/dist/module/internal'; - -import { version } from './version'; - -const statics = {}; - -const namespace = 'installations'; - -const nativeModuleName = 'RNFBInstallationsModule'; - -interface InstallationsNativeModule { - getId(): Promise; - getToken(forceRefresh: boolean): Promise; - delete(): Promise; -} - -/** - * Firebase Installations package for React Native. - * - * @firebase installations - */ -export namespace FirebaseInstallationsTypes { - export interface Statics { - SDK_VERSION: string; - } - - /** - * The Firebase Installations service is available for the default app or a given app. - */ - export interface Module extends ReactNativeFirebase.FirebaseModule { - /** - * The current `FirebaseApp` instance for this Firebase service. - */ - app: ReactNativeFirebase.FirebaseApp; - - /** - * Creates a Firebase Installation if there isn't one for the app and returns the Installation ID. - */ - getId(): Promise; - - /** - * Retrieves a valid installation auth token. - */ - getToken(forceRefresh?: boolean): Promise; - - /** - * Deletes the Firebase Installation and all associated data from the Firebase backend. - */ - delete(): Promise; - } -} - -class FirebaseInstallationsModule extends FirebaseModule { - get native(): InstallationsNativeModule { - return super.native as unknown as InstallationsNativeModule; - } - - getId(): Promise { - return this.native.getId(); - } - - getToken(forceRefresh?: boolean): Promise { - if (!forceRefresh) { - return this.native.getToken(false); - } else { - return this.native.getToken(true); - } - } - - delete(): Promise { - return this.native.delete(); - } - - onIdChange(): () => void { - if (isIOS) { - return () => {}; - } - - // TODO implement change listener on Android - return () => {}; - } -} - -type InstallationsNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< - FirebaseInstallationsTypes.Module, - FirebaseInstallationsTypes.Statics -> & { - firebase: ReactNativeFirebase.Module; - app(name?: string): ReactNativeFirebase.FirebaseApp; -}; - -// import { SDK_VERSION } from '@react-native-firebase/installations'; -export const SDK_VERSION = version; - -// import installations from '@react-native-firebase/installations'; -// installations().X(...); -const defaultExport = createModuleNamespace({ - statics, - version, - namespace, - nativeModuleName, - nativeEvents: false, // TODO implement android id change listener: ['installations_id_changed'], - hasMultiAppSupport: true, - hasCustomUrlOrRegionSupport: false, - ModuleClass: FirebaseInstallationsModule, -}) as unknown as InstallationsNamespace; - -export default defaultExport; - -// import installations, { firebase } from '@react-native-firebase/installations'; -// installations().X(...); -// firebase.installations().X(...); -export const firebase = getFirebaseRoot() as unknown as ReactNativeFirebase.Module & { - installations: typeof defaultExport; - app( - name?: string, - ): ReactNativeFirebase.FirebaseApp & { installations(): FirebaseInstallationsTypes.Module }; -}; +// Export modular/public types. +export type * from './types/installations'; +// Export modular API functions. export * from './modular'; -/** - * Attach namespace to `firebase.` and `FirebaseApp.`. - */ -declare module '@react-native-firebase/app' { - namespace ReactNativeFirebase { - import FirebaseModuleWithStaticsAndApp = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; - - interface Module { - installations: FirebaseModuleWithStaticsAndApp< - FirebaseInstallationsTypes.Module, - FirebaseInstallationsTypes.Statics - >; - } - - interface FirebaseApp { - installations(): FirebaseInstallationsTypes.Module; - } - } -} +// Export namespaced API. +export type { FirebaseInstallationsTypes } from './types/namespaced'; +export * from './namespaced'; +export { default } from './namespaced'; diff --git a/packages/installations/lib/modular/index.ts b/packages/installations/lib/modular.ts similarity index 62% rename from packages/installations/lib/modular/index.ts rename to packages/installations/lib/modular.ts index d47a297c0c..26c2937cfd 100644 --- a/packages/installations/lib/modular/index.ts +++ b/packages/installations/lib/modular.ts @@ -16,28 +16,22 @@ */ import { getApp } from '@react-native-firebase/app'; -import type { ReactNativeFirebase } from '@react-native-firebase/app'; +import type { FirebaseApp } from '@react-native-firebase/app'; import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; -import type { FirebaseInstallationsTypes } from '..'; +import type { Installations } from './types/installations'; +import type { InstallationsInternal } from './types/internal'; + +function withModularDeprecationArg(installations: Installations): InstallationsInternal { + return installations as InstallationsInternal; +} -type FirebaseInstallation = FirebaseInstallationsTypes.Module; type IdChangeCallbackFn = (installationId: string) => void; type IdChangeUnsubscribeFn = () => void; -type InstallationsModularDeprecationArg = string; - -interface FirebaseInstallationInternal extends FirebaseInstallation { - delete(deprecationArg?: InstallationsModularDeprecationArg): Promise; - getId(deprecationArg?: InstallationsModularDeprecationArg): Promise; - getToken( - forceRefresh?: boolean, - deprecationArg?: InstallationsModularDeprecationArg, - ): Promise; -} /** * Returns an instance of Installations associated with the given FirebaseApp instance. */ -export function getInstallations(app?: ReactNativeFirebase.FirebaseApp): FirebaseInstallation { +export function getInstallations(app?: FirebaseApp): Installations { if (app) { return getApp(app.name).installations(); } @@ -47,27 +41,24 @@ export function getInstallations(app?: ReactNativeFirebase.FirebaseApp): Firebas /** * Deletes the Firebase Installation and all associated data. */ -export function deleteInstallations(installations?: FirebaseInstallation): Promise { - const internalInstallations = installations as FirebaseInstallationInternal; +export function deleteInstallations(installations?: Installations): Promise { + const internalInstallations = withModularDeprecationArg(installations as Installations); return internalInstallations.delete.call(internalInstallations, MODULAR_DEPRECATION_ARG); } /** * Creates a Firebase Installation if there isn't one for the app and returns the Installation ID. */ -export function getId(installations: FirebaseInstallation): Promise { - const internalInstallations = installations as FirebaseInstallationInternal; +export function getId(installations: Installations): Promise { + const internalInstallations = withModularDeprecationArg(installations); return internalInstallations.getId.call(internalInstallations, MODULAR_DEPRECATION_ARG); } /** * Returns a Firebase Installations auth token, identifying the current Firebase Installation. */ -export function getToken( - installations: FirebaseInstallation, - forceRefresh?: boolean, -): Promise { - const internalInstallations = installations as FirebaseInstallationInternal; +export function getToken(installations: Installations, forceRefresh?: boolean): Promise { + const internalInstallations = withModularDeprecationArg(installations); return internalInstallations.getToken.call( internalInstallations, forceRefresh, @@ -81,7 +72,7 @@ export function getToken( * Sets a new callback that will get called when Installation ID changes. Returns an unsubscribe function that will remove the callback when called. */ export function onIdChange( - _installations: FirebaseInstallation, + _installations: Installations, _callback: IdChangeCallbackFn, ): IdChangeUnsubscribeFn { throw new Error('onIdChange() is unsupported by the React Native Firebase SDK.'); diff --git a/packages/installations/lib/modular/index.d.ts b/packages/installations/lib/modular/index.d.ts deleted file mode 100644 index 8e493590ac..0000000000 --- a/packages/installations/lib/modular/index.d.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { ReactNativeFirebase } from '@react-native-firebase/app'; -import { FirebaseInstallationsTypes } from '../index'; - -import FirebaseInstallations = FirebaseInstallationsTypes.Module; -/** - * Returns an instance of Installations associated with the given FirebaseApp instance. - */ -export declare function getInstallations( - app?: ReactNativeFirebase.FirebaseApp, -): FirebaseInstallations; - -/** - * Deletes the Firebase Installation and all associated data. - */ -export declare function deleteInstallations(installations?: FirebaseInstallations): Promise; - -/** - * Creates a Firebase Installation if there isn't one for the app and returns the Installation ID. - */ -export declare function getId(installations: FirebaseInstallations): Promise; - -/** - * Returns a Firebase Installations auth token, identifying the current Firebase Installation. - */ -export declare function getToken( - installations: FirebaseInstallations, - forceRefresh?: boolean, -): Promise; - -declare type IdChangeCallbackFn = (installationId: string) => void; -declare type IdChangeUnsubscribeFn = () => void; - -/** - * Throw an error since react-native-firebase does not support this method. - * - * Sets a new callback that will get called when Installation ID changes. Returns an unsubscribe function that will remove the callback when called. - */ -export declare function onIdChange( - installations: FirebaseInstallations, - callback: IdChangeCallbackFn, -): IdChangeUnsubscribeFn; diff --git a/packages/installations/lib/namespaced.ts b/packages/installations/lib/namespaced.ts new file mode 100644 index 0000000000..8d0c8c6333 --- /dev/null +++ b/packages/installations/lib/namespaced.ts @@ -0,0 +1,92 @@ +/* + * 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 { isIOS } from '@react-native-firebase/app/dist/module/common'; +import { + createModuleNamespace, + FirebaseModule, + getFirebaseRoot, +} from '@react-native-firebase/app/dist/module/internal'; +import type { ReactNativeFirebase } from '@react-native-firebase/app'; + +import { version } from './version'; +import type { FirebaseInstallationsTypes } from './types/namespaced'; +import type { RNFBInstallationsModule } from './types/internal'; + +const statics = {}; + +const namespace = 'installations'; +const nativeModuleName = 'RNFBInstallationsModule'; + +class FirebaseInstallationsModule extends FirebaseModule { + get native(): RNFBInstallationsModule { + return super.native as unknown as RNFBInstallationsModule; + } + + getId(): Promise { + return this.native.getId(); + } + + getToken(forceRefresh?: boolean): Promise { + if (!forceRefresh) { + return this.native.getToken(false); + } else { + return this.native.getToken(true); + } + } + + delete(): Promise { + return this.native.delete(); + } + + onIdChange(): () => void { + if (isIOS) { + return () => {}; + } + + // TODO implement change listener on Android + return () => {}; + } +} + +// import { SDK_VERSION } from '@react-native-firebase/installations'; +export const SDK_VERSION = version; + +// import installations from '@react-native-firebase/installations'; +// installations().X(...); +const defaultExport = createModuleNamespace({ + statics, + version, + namespace, + nativeModuleName, + nativeEvents: false, // TODO implement android id change listener: ['installations_id_changed'], + hasMultiAppSupport: true, + hasCustomUrlOrRegionSupport: false, + ModuleClass: FirebaseInstallationsModule, +}) as unknown as FirebaseInstallationsTypes.InstallationsNamespace; + +export default defaultExport; + +// import installations, { firebase } from '@react-native-firebase/installations'; +// installations().X(...); +// firebase.installations().X(...); +export const firebase = getFirebaseRoot() as unknown as ReactNativeFirebase.Module & { + installations: typeof defaultExport; + app( + name?: string, + ): ReactNativeFirebase.FirebaseApp & { installations(): FirebaseInstallationsTypes.Module }; +}; diff --git a/packages/installations/lib/types/installations.ts b/packages/installations/lib/types/installations.ts new file mode 100644 index 0000000000..37a8eecbe1 --- /dev/null +++ b/packages/installations/lib/types/installations.ts @@ -0,0 +1,43 @@ +/* + * 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 { FirebaseApp, ReactNativeFirebase } from '@react-native-firebase/app'; + +/** + * Firebase Installations service instance. + */ +export interface Installations extends ReactNativeFirebase.FirebaseModule { + /** + * The current `FirebaseApp` instance for this Firebase service. + */ + app: FirebaseApp; + + /** + * Creates a Firebase Installation if there isn't one for the app and returns the Installation ID. + */ + getId(): Promise; + + /** + * Retrieves a valid installation auth token. + */ + getToken(forceRefresh?: boolean): Promise; + + /** + * Deletes the Firebase Installation and all associated data from the Firebase backend. + */ + delete(): Promise; +} diff --git a/packages/installations/lib/types/internal.ts b/packages/installations/lib/types/internal.ts new file mode 100644 index 0000000000..c44b052a80 --- /dev/null +++ b/packages/installations/lib/types/internal.ts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file 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 { Installations } from './installations'; + +/** Optional final argument passed by modular API wrappers (MODULAR_DEPRECATION_ARG). */ +export type InstallationsModularDeprecationArg = string; + +export interface InstallationsInternal extends Installations { + delete(deprecationArg?: InstallationsModularDeprecationArg): Promise; + getId(deprecationArg?: InstallationsModularDeprecationArg): Promise; + getToken( + forceRefresh?: boolean, + deprecationArg?: InstallationsModularDeprecationArg, + ): Promise; +} + +export interface RNFBInstallationsModule { + getId(): Promise; + getToken(forceRefresh: boolean): Promise; + delete(): Promise; +} diff --git a/packages/installations/lib/types/namespaced.ts b/packages/installations/lib/types/namespaced.ts new file mode 100644 index 0000000000..113b3cb7ba --- /dev/null +++ b/packages/installations/lib/types/namespaced.ts @@ -0,0 +1,108 @@ +/* + * 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 Installations package for React Native. + * + * @firebase installations + */ +/** + * @deprecated Use the exported types directly instead. + * FirebaseInstallationsTypes namespace is kept for backwards compatibility. + */ +/* eslint-disable @typescript-eslint/no-namespace */ +export namespace FirebaseInstallationsTypes { + export interface Statics { + SDK_VERSION: string; + } + + /** + * The Firebase Installations service is available for the default app or a given app. + * + * @deprecated Use the exported types directly instead. FirebaseInstallationsTypes namespace is kept for backwards compatibility. + */ + export interface Module extends ReactNativeFirebase.FirebaseModule { + /** + * The current `FirebaseApp` instance for this Firebase service. + * + * @deprecated Use the exported types directly instead. + */ + app: ReactNativeFirebase.FirebaseApp; + + /** + * Creates a Firebase Installation if there isn't one for the app and returns the Installation ID. + * + * @deprecated Use `getId()` from the modular API instead. + */ + getId(): Promise; + + /** + * Retrieves a valid installation auth token. + * + * @deprecated Use `getToken()` from the modular API instead. + */ + getToken(forceRefresh?: boolean): Promise; + + /** + * Deletes the Firebase Installation and all associated data from the Firebase backend. + * + * @deprecated Use `deleteInstallations()` from the modular API instead. + */ + delete(): Promise; + } + + export type InstallationsNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + Module, + Statics + > & { + firebase: ReactNativeFirebase.Module; + app(name?: string): ReactNativeFirebase.FirebaseApp; + }; +} + +declare const defaultExport: FirebaseInstallationsTypes.InstallationsNamespace; + +export declare const firebase: ReactNativeFirebase.Module & { + installations: typeof defaultExport; + app( + name?: string, + ): ReactNativeFirebase.FirebaseApp & { installations(): FirebaseInstallationsTypes.Module }; +}; + +export default defaultExport; + +/** + * Attach namespace to `firebase.` and `FirebaseApp.`. + */ +declare module '@react-native-firebase/app' { + namespace ReactNativeFirebase { + import FirebaseModuleWithStaticsAndApp = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; + + interface Module { + installations: FirebaseModuleWithStaticsAndApp< + FirebaseInstallationsTypes.Module, + FirebaseInstallationsTypes.Statics + >; + } + + interface FirebaseApp { + installations(): FirebaseInstallationsTypes.Module; + } + } +} From a290ca02f946ce21b9a5c664c24026868a4cb03d Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 16:53:17 +0100 Subject: [PATCH 03/12] refactor(installations): type namespaced module and native bridge --- packages/installations/lib/namespaced.ts | 7 +------ packages/installations/lib/types/internal.ts | 6 ++++++ packages/installations/tsconfig.json | 3 +++ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/installations/lib/namespaced.ts b/packages/installations/lib/namespaced.ts index 8d0c8c6333..ea015e5fe0 100644 --- a/packages/installations/lib/namespaced.ts +++ b/packages/installations/lib/namespaced.ts @@ -25,18 +25,13 @@ import type { ReactNativeFirebase } from '@react-native-firebase/app'; import { version } from './version'; import type { FirebaseInstallationsTypes } from './types/namespaced'; -import type { RNFBInstallationsModule } from './types/internal'; const statics = {}; const namespace = 'installations'; const nativeModuleName = 'RNFBInstallationsModule'; -class FirebaseInstallationsModule extends FirebaseModule { - get native(): RNFBInstallationsModule { - return super.native as unknown as RNFBInstallationsModule; - } - +class FirebaseInstallationsModule extends FirebaseModule { getId(): Promise { return this.native.getId(); } diff --git a/packages/installations/lib/types/internal.ts b/packages/installations/lib/types/internal.ts index c44b052a80..2b0b4b36b6 100644 --- a/packages/installations/lib/types/internal.ts +++ b/packages/installations/lib/types/internal.ts @@ -34,3 +34,9 @@ export interface RNFBInstallationsModule { getToken(forceRefresh: boolean): Promise; delete(): Promise; } + +declare module '@react-native-firebase/app/dist/module/internal/NativeModules' { + interface ReactNativeFirebaseNativeModules { + RNFBInstallationsModule: RNFBInstallationsModule; + } +} diff --git a/packages/installations/tsconfig.json b/packages/installations/tsconfig.json index 4cb30685a7..3dc86a647b 100644 --- a/packages/installations/tsconfig.json +++ b/packages/installations/tsconfig.json @@ -10,6 +10,9 @@ "../app/dist/typescript/lib/internal/*" ], "@react-native-firebase/app/dist/module/internal": ["../app/dist/typescript/lib/internal"], + "@react-native-firebase/app/dist/module/internal/NativeModules": [ + "../app/dist/typescript/lib/internal/NativeModules" + ], "@react-native-firebase/app": ["../app/dist/typescript/lib"] } }, From 12f6843cb9388bef872ed07e156198d3e139f566 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 17:04:32 +0100 Subject: [PATCH 04/12] refactor(installations): align modular API with firebase-js-sdk --- packages/installations/lib/modular.ts | 13 +++++---- .../installations/lib/types/installations.ts | 29 ++++++++----------- packages/installations/type-test.ts | 10 +++++-- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/packages/installations/lib/modular.ts b/packages/installations/lib/modular.ts index 26c2937cfd..7b6247a592 100644 --- a/packages/installations/lib/modular.ts +++ b/packages/installations/lib/modular.ts @@ -18,16 +18,17 @@ import { getApp } from '@react-native-firebase/app'; import type { FirebaseApp } from '@react-native-firebase/app'; import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; -import type { Installations } from './types/installations'; +import type { + IdChangeCallbackFn, + IdChangeUnsubscribeFn, + Installations, +} from './types/installations'; import type { InstallationsInternal } from './types/internal'; function withModularDeprecationArg(installations: Installations): InstallationsInternal { return installations as InstallationsInternal; } -type IdChangeCallbackFn = (installationId: string) => void; -type IdChangeUnsubscribeFn = () => void; - /** * Returns an instance of Installations associated with the given FirebaseApp instance. */ @@ -41,8 +42,8 @@ export function getInstallations(app?: FirebaseApp): Installations { /** * Deletes the Firebase Installation and all associated data. */ -export function deleteInstallations(installations?: Installations): Promise { - const internalInstallations = withModularDeprecationArg(installations as Installations); +export function deleteInstallations(installations: Installations): Promise { + const internalInstallations = withModularDeprecationArg(installations); return internalInstallations.delete.call(internalInstallations, MODULAR_DEPRECATION_ARG); } diff --git a/packages/installations/lib/types/installations.ts b/packages/installations/lib/types/installations.ts index 37a8eecbe1..e1e0a14c71 100644 --- a/packages/installations/lib/types/installations.ts +++ b/packages/installations/lib/types/installations.ts @@ -15,29 +15,24 @@ * */ -import type { FirebaseApp, ReactNativeFirebase } from '@react-native-firebase/app'; +import type { FirebaseApp } from '@react-native-firebase/app'; + +/** + * An user defined callback function that gets called when Installations ID changes. + */ +export type IdChangeCallbackFn = (installationId: string) => void; + +/** + * Unsubscribe a callback function previously added via {@link IdChangeCallbackFn}. + */ +export type IdChangeUnsubscribeFn = () => void; /** * Firebase Installations service instance. */ -export interface Installations extends ReactNativeFirebase.FirebaseModule { +export interface Installations { /** * The current `FirebaseApp` instance for this Firebase service. */ app: FirebaseApp; - - /** - * Creates a Firebase Installation if there isn't one for the app and returns the Installation ID. - */ - getId(): Promise; - - /** - * Retrieves a valid installation auth token. - */ - getToken(forceRefresh?: boolean): Promise; - - /** - * Deletes the Firebase Installation and all associated data from the Firebase backend. - */ - delete(): Promise; } diff --git a/packages/installations/type-test.ts b/packages/installations/type-test.ts index 3df090f8b3..06221551e0 100644 --- a/packages/installations/type-test.ts +++ b/packages/installations/type-test.ts @@ -6,6 +6,7 @@ import installations, { getToken, onIdChange, } from '.'; +import type { IdChangeCallbackFn, IdChangeUnsubscribeFn } from '.'; console.log(installations().app); @@ -80,9 +81,14 @@ deleteInstallations(modularInstallations1).then(() => { // Note: onIdChange throws an error in React Native Firebase try { - onIdChange(modularInstallations1, (id: string) => { + const onInstallationsIdChange: IdChangeCallbackFn = id => { console.log(id); - }); + }; + const unsubscribe: IdChangeUnsubscribeFn = onIdChange( + modularInstallations1, + onInstallationsIdChange, + ); + unsubscribe(); } catch (error) { console.log('Modular onIdChange not supported'); } From fc4d881042bc9161e26e94e65ecd6af6577d1939 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 17:16:44 +0100 Subject: [PATCH 05/12] test(installations): add type coverage and compare-types wiring --- .../packages/installations/config.ts | 19 ++++ .../packages/installations/firebase-sdk.d.ts | 91 +++++++++++++++++++ .github/scripts/compare-types/src/registry.ts | 26 +++--- packages/installations/type-test.ts | 14 ++- tsconfig.json | 4 +- 5 files changed, 139 insertions(+), 15 deletions(-) create mode 100644 .github/scripts/compare-types/packages/installations/config.ts create mode 100644 .github/scripts/compare-types/packages/installations/firebase-sdk.d.ts diff --git a/.github/scripts/compare-types/packages/installations/config.ts b/.github/scripts/compare-types/packages/installations/config.ts new file mode 100644 index 0000000000..45bdfc8953 --- /dev/null +++ b/.github/scripts/compare-types/packages/installations/config.ts @@ -0,0 +1,19 @@ +/** + * Known differences between the firebase-js-sdk @firebase/installations public + * API and the @react-native-firebase/installations 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: [], + extraInRN: [], + differentShape: [], +}; + +export default config; diff --git a/.github/scripts/compare-types/packages/installations/firebase-sdk.d.ts b/.github/scripts/compare-types/packages/installations/firebase-sdk.d.ts new file mode 100644 index 0000000000..17aa364556 --- /dev/null +++ b/.github/scripts/compare-types/packages/installations/firebase-sdk.d.ts @@ -0,0 +1,91 @@ +/** + * The Firebase Installations Web SDK. + * This SDK does not work in a Node.js environment. + * + * @packageDocumentation + */ + +import { FirebaseApp } from '@firebase/app'; + +/** + * Deletes the Firebase Installation and all associated data. + * @param installations - The `Installations` instance. + * + * @public + */ +export declare function deleteInstallations(installations: Installations): Promise; + +/* Excluded from this release type: _FirebaseInstallationsInternal */ + +/** + * Creates a Firebase Installation if there isn't one for the app and + * returns the Installation ID. + * @param installations - The `Installations` instance. + * + * @public + */ +export declare function getId(installations: Installations): Promise; + +/** + * Returns an instance of {@link Installations} associated with the given + * {@link @firebase/app#FirebaseApp} instance. + * @param app - The {@link @firebase/app#FirebaseApp} instance. + * + * @public + */ +export declare function getInstallations(app?: FirebaseApp): Installations; + +/** + * Returns a Firebase Installations auth token, identifying the current + * Firebase Installation. + * @param installations - The `Installations` instance. + * @param forceRefresh - Force refresh regardless of token expiration. + * + * @public + */ +export declare function getToken( + installations: Installations, + forceRefresh?: boolean, +): Promise; + +/** + * An user defined callback function that gets called when Installations ID changes. + * + * @public + */ +export declare type IdChangeCallbackFn = (installationId: string) => void; + +/** + * Unsubscribe a callback function previously added via {@link IdChangeCallbackFn}. + * + * @public + */ +export declare type IdChangeUnsubscribeFn = () => void; + +/** + * Public interface of the Firebase Installations SDK. + * + * @public + */ +export declare interface Installations { + /** + * The {@link @firebase/app#FirebaseApp} this `Installations` instance is associated with. + */ + app: FirebaseApp; +} + +/** + * Sets a new callback that will get called when Installation ID changes. + * Returns an unsubscribe function that will remove the callback when called. + * @param installations - The `Installations` instance. + * @param callback - The callback function that is invoked when FID changes. + * @returns A function that can be called to unsubscribe. + * + * @public + */ +export declare function onIdChange( + installations: Installations, + callback: IdChangeCallbackFn, +): IdChangeUnsubscribeFn; + +export {}; diff --git a/.github/scripts/compare-types/src/registry.ts b/.github/scripts/compare-types/src/registry.ts index e1f546a0f8..b9afd21e27 100644 --- a/.github/scripts/compare-types/src/registry.ts +++ b/.github/scripts/compare-types/src/registry.ts @@ -18,6 +18,7 @@ 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'; +import installationsConfig from '../packages/installations/config'; import remoteConfigConfig from '../packages/remote-config/config'; const SCRIPT_DIR = path.resolve(__dirname, '..'); @@ -53,12 +54,7 @@ function rnDist(packageName: string): string { export const packages: PackageEntry[] = [ { name: 'storage', - firebaseSdkTypesPaths: [path.join( - SCRIPT_DIR, - 'packages', - 'storage', - 'storage-js-sdk.d.ts', - )], + firebaseSdkTypesPaths: [path.join(SCRIPT_DIR, 'packages', 'storage', 'storage-js-sdk.d.ts')], rnFirebaseModularFiles: [ path.join(rnDist('storage'), 'types', 'storage.d.ts'), path.join(rnDist('storage'), 'modular.d.ts'), @@ -121,9 +117,7 @@ export const packages: PackageEntry[] = [ }, { name: 'app-check', - firebaseSdkTypesPaths: [ - path.join(SCRIPT_DIR, 'packages', 'app-check', 'app-check-sdk.d.ts'), - ], + 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'), @@ -134,6 +128,18 @@ export const packages: PackageEntry[] = [ ], config: appCheckConfig, }, + { + name: 'installations', + firebaseSdkTypesPaths: [ + path.join(SCRIPT_DIR, 'packages', 'installations', 'firebase-sdk.d.ts'), + ], + rnFirebaseModularFiles: [ + path.join(rnDist('installations'), 'types', 'installations.d.ts'), + path.join(rnDist('installations'), 'modular.d.ts'), + ], + rnFirebaseSupportFiles: [path.join(rnDist('installations'), 'types', 'internal.d.ts')], + config: installationsConfig, + }, { name: 'firestore', firebaseSdkTypesPaths: [ @@ -190,5 +196,3 @@ export const packages: PackageEntry[] = [ config: firestorePipelinesConfig, }, ]; - - diff --git a/packages/installations/type-test.ts b/packages/installations/type-test.ts index 06221551e0..943d4fa128 100644 --- a/packages/installations/type-test.ts +++ b/packages/installations/type-test.ts @@ -6,7 +6,12 @@ import installations, { getToken, onIdChange, } from '.'; -import type { IdChangeCallbackFn, IdChangeUnsubscribeFn } from '.'; +import type { + FirebaseInstallationsTypes, + IdChangeCallbackFn, + IdChangeUnsubscribeFn, + Installations, +} from '.'; console.log(installations().app); @@ -56,6 +61,8 @@ installationsInstance.delete().then(() => { // checks modular API functions const modularInstallations1 = getInstallations(); console.log(modularInstallations1.app.name); +const typedInstallations: Installations = modularInstallations1; +console.log(typedInstallations.app.name); const modularInstallations2 = getInstallations(firebase.app()); console.log(modularInstallations2.app.name); @@ -79,6 +86,11 @@ deleteInstallations(modularInstallations1).then(() => { console.log('Modular installation deleted'); }); +const namespacedInstallations: FirebaseInstallationsTypes.Module = installationsInstance; +namespacedInstallations.getId().then((id: string) => { + console.log(id); +}); + // Note: onIdChange throws an error in React Native Firebase try { const onInstallationsIdChange: IdChangeCallbackFn = id => { diff --git a/tsconfig.json b/tsconfig.json index 0e75593f74..60ceefdb5f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,8 +21,6 @@ "packages/firestore/lib/modular/VectorValue.d.ts", "packages/in-app-messaging/lib/index.d.ts", "packages/in-app-messaging/lib/modular/index.d.ts", - "packages/installations/lib/index.d.ts", - "packages/installations/lib/modular/index.d.ts", "packages/ml/lib/index.d.ts", "packages/ml/lib/modular/index.d.ts", "packages/perf/lib/index.d.ts", @@ -74,7 +72,7 @@ ], "@react-native-firebase/firestore/pipelines": [ "./packages/firestore/dist/typescript/lib/pipelines/index.d.ts" - ], + ] } }, "exclude": ["node_modules", "**/*.spec.ts", "packages/**/dist"] From ffded1dfab84cc911b317786cb5e80cdf1c54ceb Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 13:45:08 +0100 Subject: [PATCH 06/12] chore: update namespace types --- packages/installations/lib/namespaced.ts | 31 +++++++++++++------ .../installations/lib/types/namespaced.ts | 4 +++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/packages/installations/lib/namespaced.ts b/packages/installations/lib/namespaced.ts index ea015e5fe0..893e24ee78 100644 --- a/packages/installations/lib/namespaced.ts +++ b/packages/installations/lib/namespaced.ts @@ -63,7 +63,7 @@ export const SDK_VERSION = version; // import installations from '@react-native-firebase/installations'; // installations().X(...); -const defaultExport = createModuleNamespace({ +const installationsNamespace = createModuleNamespace({ statics, version, namespace, @@ -72,16 +72,29 @@ const defaultExport = createModuleNamespace({ hasMultiAppSupport: true, hasCustomUrlOrRegionSupport: false, ModuleClass: FirebaseInstallationsModule, -}) as unknown as FirebaseInstallationsTypes.InstallationsNamespace; +}); -export default defaultExport; +type InstallationsNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebaseInstallationsTypes.Module, + FirebaseInstallationsTypes.Statics +> & { + installations: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebaseInstallationsTypes.Module, + FirebaseInstallationsTypes.Statics + >; + firebase: ReactNativeFirebase.Module; + app(name?: string): ReactNativeFirebase.FirebaseApp; +}; + +export default installationsNamespace as unknown as InstallationsNamespace; // import installations, { firebase } from '@react-native-firebase/installations'; // installations().X(...); // firebase.installations().X(...); -export const firebase = getFirebaseRoot() as unknown as ReactNativeFirebase.Module & { - installations: typeof defaultExport; - app( - name?: string, - ): ReactNativeFirebase.FirebaseApp & { installations(): FirebaseInstallationsTypes.Module }; -}; +export const firebase = + getFirebaseRoot() as unknown as ReactNativeFirebase.FirebaseNamespacedExport< + 'installations', + FirebaseInstallationsTypes.Module, + FirebaseInstallationsTypes.Statics, + false + >; diff --git a/packages/installations/lib/types/namespaced.ts b/packages/installations/lib/types/namespaced.ts index 113b3cb7ba..83cc3a0820 100644 --- a/packages/installations/lib/types/namespaced.ts +++ b/packages/installations/lib/types/namespaced.ts @@ -28,6 +28,9 @@ import type { ReactNativeFirebase } from '@react-native-firebase/app'; */ /* eslint-disable @typescript-eslint/no-namespace */ export namespace FirebaseInstallationsTypes { + /** + * @deprecated Use the exported types directly instead. + */ export interface Statics { SDK_VERSION: string; } @@ -71,6 +74,7 @@ export namespace FirebaseInstallationsTypes { Module, Statics > & { + installations: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; firebase: ReactNativeFirebase.Module; app(name?: string): ReactNativeFirebase.FirebaseApp; }; From 3ce5166d9c6aad1fe29b08691834ffcb7cea43fb Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 14:00:13 +0100 Subject: [PATCH 07/12] yarn.lock --- yarn.lock | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yarn.lock b/yarn.lock index 1721ecdee5..b91a91eb9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6372,6 +6372,8 @@ __metadata: "@react-native-firebase/installations@npm:24.0.0, @react-native-firebase/installations@workspace:packages/installations": version: 0.0.0-use.local resolution: "@react-native-firebase/installations@workspace:packages/installations" + dependencies: + react-native-builder-bob: "npm:^0.40.13" peerDependencies: "@react-native-firebase/app": 24.0.0 languageName: unknown From 0db9870d84495c188c3159027e2c14eef21ef43e Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 14:49:36 +0100 Subject: [PATCH 08/12] test: expect error for modular and namespace api --- packages/installations/__tests__/installations.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/installations/__tests__/installations.test.ts b/packages/installations/__tests__/installations.test.ts index 8c76b1cd84..1a0f08203c 100644 --- a/packages/installations/__tests__/installations.test.ts +++ b/packages/installations/__tests__/installations.test.ts @@ -109,6 +109,7 @@ describe('installations()', function () { const installations = getInstallations(); installationsV9Deprecation( () => deleteInstallations(installations), + // @ts-expect-error Combines modular and namespace API () => installations.delete(), 'delete', ); @@ -118,6 +119,7 @@ describe('installations()', function () { const installations = getInstallations(); installationsV9Deprecation( () => getId(installations), + // @ts-expect-error Combines modular and namespace API () => installations.getId(), 'getId', ); @@ -127,6 +129,7 @@ describe('installations()', function () { const installations = getInstallations(); installationsV9Deprecation( () => getToken(installations), + // @ts-expect-error Combines modular and namespace API () => installations.getToken(), 'getToken', ); From d43aed9620d660cc6bcb906f1cf82dd8e617db55 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 14:55:00 +0100 Subject: [PATCH 09/12] fix: typedoc.json updated --- packages/installations/typedoc.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/installations/typedoc.json b/packages/installations/typedoc.json index bf93ba7159..e83cc5c235 100644 --- a/packages/installations/typedoc.json +++ b/packages/installations/typedoc.json @@ -1,6 +1,5 @@ { "$schema": "https://typedoc.org/schema.json", - "entryPoints": ["lib/index.d.ts"], - "intentionallyNotExported": ["InstallationsNamespace"] - + "entryPoints": ["lib/modular.ts", "lib/types/installations.ts"], + "tsconfig": "tsconfig.json" } From 7716bb8b3920183717c71dc0bdf1999afd16f40c Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 12 May 2026 17:25:07 +0100 Subject: [PATCH 10/12] chore: move installation type config to flat directories --- .../config.ts => configs/installations.ts} | 2 +- .../packages/installations/firebase-sdk.d.ts | 91 ------------------- 2 files changed, 1 insertion(+), 92 deletions(-) rename .github/scripts/compare-types/{packages/installations/config.ts => configs/installations.ts} (90%) delete mode 100644 .github/scripts/compare-types/packages/installations/firebase-sdk.d.ts diff --git a/.github/scripts/compare-types/packages/installations/config.ts b/.github/scripts/compare-types/configs/installations.ts similarity index 90% rename from .github/scripts/compare-types/packages/installations/config.ts rename to .github/scripts/compare-types/configs/installations.ts index 45bdfc8953..0a438d6107 100644 --- a/.github/scripts/compare-types/packages/installations/config.ts +++ b/.github/scripts/compare-types/configs/installations.ts @@ -7,7 +7,7 @@ * fail so that new drift is caught and deliberately acknowledged. */ -import type { PackageConfig } from '../../src/types'; +import type { PackageConfig } from '../src/types'; const config: PackageConfig = { nameMapping: {}, diff --git a/.github/scripts/compare-types/packages/installations/firebase-sdk.d.ts b/.github/scripts/compare-types/packages/installations/firebase-sdk.d.ts deleted file mode 100644 index 17aa364556..0000000000 --- a/.github/scripts/compare-types/packages/installations/firebase-sdk.d.ts +++ /dev/null @@ -1,91 +0,0 @@ -/** - * The Firebase Installations Web SDK. - * This SDK does not work in a Node.js environment. - * - * @packageDocumentation - */ - -import { FirebaseApp } from '@firebase/app'; - -/** - * Deletes the Firebase Installation and all associated data. - * @param installations - The `Installations` instance. - * - * @public - */ -export declare function deleteInstallations(installations: Installations): Promise; - -/* Excluded from this release type: _FirebaseInstallationsInternal */ - -/** - * Creates a Firebase Installation if there isn't one for the app and - * returns the Installation ID. - * @param installations - The `Installations` instance. - * - * @public - */ -export declare function getId(installations: Installations): Promise; - -/** - * Returns an instance of {@link Installations} associated with the given - * {@link @firebase/app#FirebaseApp} instance. - * @param app - The {@link @firebase/app#FirebaseApp} instance. - * - * @public - */ -export declare function getInstallations(app?: FirebaseApp): Installations; - -/** - * Returns a Firebase Installations auth token, identifying the current - * Firebase Installation. - * @param installations - The `Installations` instance. - * @param forceRefresh - Force refresh regardless of token expiration. - * - * @public - */ -export declare function getToken( - installations: Installations, - forceRefresh?: boolean, -): Promise; - -/** - * An user defined callback function that gets called when Installations ID changes. - * - * @public - */ -export declare type IdChangeCallbackFn = (installationId: string) => void; - -/** - * Unsubscribe a callback function previously added via {@link IdChangeCallbackFn}. - * - * @public - */ -export declare type IdChangeUnsubscribeFn = () => void; - -/** - * Public interface of the Firebase Installations SDK. - * - * @public - */ -export declare interface Installations { - /** - * The {@link @firebase/app#FirebaseApp} this `Installations` instance is associated with. - */ - app: FirebaseApp; -} - -/** - * Sets a new callback that will get called when Installation ID changes. - * Returns an unsubscribe function that will remove the callback when called. - * @param installations - The `Installations` instance. - * @param callback - The callback function that is invoked when FID changes. - * @returns A function that can be called to unsubscribe. - * - * @public - */ -export declare function onIdChange( - installations: Installations, - callback: IdChangeCallbackFn, -): IdChangeUnsubscribeFn; - -export {}; From 00ef079c75800a4f3b9759316648464078bfb0ab Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 12 May 2026 17:26:16 +0100 Subject: [PATCH 11/12] yarn.lock --- yarn.lock | 268 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 231 insertions(+), 37 deletions(-) diff --git a/yarn.lock b/yarn.lock index a9b9dc5c5e..01892e8be7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1233,7 +1233,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-flow-strip-types@npm:^7.25.2, @babel/plugin-transform-flow-strip-types@npm:^7.27.1": +"@babel/plugin-transform-flow-strip-types@npm:^7.25.2, @babel/plugin-transform-flow-strip-types@npm:^7.26.5, @babel/plugin-transform-flow-strip-types@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-flow-strip-types@npm:7.27.1" dependencies: @@ -1375,6 +1375,20 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-systemjs@npm:^7.29.4": + version: 7.29.4 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.4" + dependencies: + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-validator-identifier": "npm:^7.28.5" + "@babel/traverse": "npm:^7.29.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/79269e6ec8ec831bb63bf1c7cc1a980e28da785e92b36d42612f0139e4044499b99aa109fca849e1a156c092aabf6c24d145f4cabf2ac9ea84ef468852fe4c03 + languageName: node + linkType: hard + "@babel/plugin-transform-modules-umd@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-modules-umd@npm:7.27.1" @@ -1804,7 +1818,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-strict-mode@npm:^7.27.1": +"@babel/plugin-transform-strict-mode@npm:^7.24.7, @babel/plugin-transform-strict-mode@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-strict-mode@npm:7.27.1" dependencies: @@ -1899,6 +1913,87 @@ __metadata: languageName: node linkType: hard +"@babel/preset-env@npm:^7.25.2": + version: 7.29.5 + resolution: "@babel/preset-env@npm:7.29.5" + dependencies: + "@babel/compat-data": "npm:^7.29.3" + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-validator-option": "npm:^7.27.1" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.28.5" + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.27.1" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.27.1" + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "npm:^7.29.3" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.27.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.28.6" + "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-import-assertions": "npm:^7.28.6" + "@babel/plugin-syntax-import-attributes": "npm:^7.28.6" + "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" + "@babel/plugin-transform-arrow-functions": "npm:^7.27.1" + "@babel/plugin-transform-async-generator-functions": "npm:^7.29.0" + "@babel/plugin-transform-async-to-generator": "npm:^7.28.6" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.27.1" + "@babel/plugin-transform-block-scoping": "npm:^7.28.6" + "@babel/plugin-transform-class-properties": "npm:^7.28.6" + "@babel/plugin-transform-class-static-block": "npm:^7.28.6" + "@babel/plugin-transform-classes": "npm:^7.28.6" + "@babel/plugin-transform-computed-properties": "npm:^7.28.6" + "@babel/plugin-transform-destructuring": "npm:^7.28.5" + "@babel/plugin-transform-dotall-regex": "npm:^7.28.6" + "@babel/plugin-transform-duplicate-keys": "npm:^7.27.1" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.29.0" + "@babel/plugin-transform-dynamic-import": "npm:^7.27.1" + "@babel/plugin-transform-explicit-resource-management": "npm:^7.28.6" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.28.6" + "@babel/plugin-transform-export-namespace-from": "npm:^7.27.1" + "@babel/plugin-transform-for-of": "npm:^7.27.1" + "@babel/plugin-transform-function-name": "npm:^7.27.1" + "@babel/plugin-transform-json-strings": "npm:^7.28.6" + "@babel/plugin-transform-literals": "npm:^7.27.1" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.28.6" + "@babel/plugin-transform-member-expression-literals": "npm:^7.27.1" + "@babel/plugin-transform-modules-amd": "npm:^7.27.1" + "@babel/plugin-transform-modules-commonjs": "npm:^7.28.6" + "@babel/plugin-transform-modules-systemjs": "npm:^7.29.4" + "@babel/plugin-transform-modules-umd": "npm:^7.27.1" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.29.0" + "@babel/plugin-transform-new-target": "npm:^7.27.1" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.28.6" + "@babel/plugin-transform-numeric-separator": "npm:^7.28.6" + "@babel/plugin-transform-object-rest-spread": "npm:^7.28.6" + "@babel/plugin-transform-object-super": "npm:^7.27.1" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.28.6" + "@babel/plugin-transform-optional-chaining": "npm:^7.28.6" + "@babel/plugin-transform-parameters": "npm:^7.27.7" + "@babel/plugin-transform-private-methods": "npm:^7.28.6" + "@babel/plugin-transform-private-property-in-object": "npm:^7.28.6" + "@babel/plugin-transform-property-literals": "npm:^7.27.1" + "@babel/plugin-transform-regenerator": "npm:^7.29.0" + "@babel/plugin-transform-regexp-modifiers": "npm:^7.28.6" + "@babel/plugin-transform-reserved-words": "npm:^7.27.1" + "@babel/plugin-transform-shorthand-properties": "npm:^7.27.1" + "@babel/plugin-transform-spread": "npm:^7.28.6" + "@babel/plugin-transform-sticky-regex": "npm:^7.27.1" + "@babel/plugin-transform-template-literals": "npm:^7.27.1" + "@babel/plugin-transform-typeof-symbol": "npm:^7.27.1" + "@babel/plugin-transform-unicode-escapes": "npm:^7.27.1" + "@babel/plugin-transform-unicode-property-regex": "npm:^7.28.6" + "@babel/plugin-transform-unicode-regex": "npm:^7.27.1" + "@babel/plugin-transform-unicode-sets-regex": "npm:^7.28.6" + "@babel/preset-modules": "npm:0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2: "npm:^0.4.15" + babel-plugin-polyfill-corejs3: "npm:^0.14.0" + babel-plugin-polyfill-regenerator: "npm:^0.6.6" + core-js-compat: "npm:^3.48.0" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/2e54630764b6650d81df5ce5a47fa260acd3695dc95a6b989b713bf6c0713fb320e3ae3f76f0c636bfda058ee5c582a3de7f5d58d691c68ca566129c7d3d0f0a + languageName: node + linkType: hard + "@babel/preset-env@npm:^7.29.2, @babel/preset-env@npm:^7.29.3": version: 7.29.3 resolution: "@babel/preset-env@npm:7.29.3" @@ -2006,7 +2101,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-react@npm:^7.22.15, @babel/preset-react@npm:^7.28.5": +"@babel/preset-react@npm:^7.22.15, @babel/preset-react@npm:^7.24.7, @babel/preset-react@npm:^7.28.5": version: 7.28.5 resolution: "@babel/preset-react@npm:7.28.5" dependencies: @@ -8141,7 +8236,7 @@ __metadata: languageName: node linkType: hard -"arktype@npm:^2.2.0": +"arktype@npm:^2.1.15, arktype@npm:^2.2.0": version: 2.2.0 resolution: "arktype@npm:2.2.0" dependencies: @@ -8206,6 +8301,13 @@ __metadata: languageName: node linkType: hard +"array-union@npm:^2.1.0": + version: 2.1.0 + resolution: "array-union@npm:2.1.0" + checksum: 10/5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d + languageName: node + linkType: hard + "array.prototype.findlast@npm:^1.2.5": version: 1.2.5 resolution: "array.prototype.findlast@npm:1.2.5" @@ -8601,7 +8703,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-syntax-hermes-parser@npm:0.28.1": +"babel-plugin-syntax-hermes-parser@npm:0.28.1, babel-plugin-syntax-hermes-parser@npm:^0.28.0": version: 0.28.1 resolution: "babel-plugin-syntax-hermes-parser@npm:0.28.1" dependencies: @@ -9045,6 +9147,21 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.20.4, browserslist@npm:^4.28.1, browserslist@npm:^4.28.2": + version: 4.28.2 + resolution: "browserslist@npm:4.28.2" + dependencies: + baseline-browser-mapping: "npm:^2.10.12" + caniuse-lite: "npm:^1.0.30001782" + electron-to-chromium: "npm:^1.5.328" + node-releases: "npm:^2.0.36" + update-browserslist-db: "npm:^1.2.3" + bin: + browserslist: cli.js + checksum: 10/cff88386e5b5ba5614c9063bd32ef94865bba22b6a381844c7d09ea1eea62a2247e7106e516abdbfda6b75b9986044c991dfe45f92f10add5ad63dccc07589ec + languageName: node + linkType: hard + "browserslist@npm:^4.24.0, browserslist@npm:^4.25.0, browserslist@npm:^4.28.0": version: 4.28.1 resolution: "browserslist@npm:4.28.1" @@ -9060,21 +9177,6 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.28.1, browserslist@npm:^4.28.2": - version: 4.28.2 - resolution: "browserslist@npm:4.28.2" - dependencies: - baseline-browser-mapping: "npm:^2.10.12" - caniuse-lite: "npm:^1.0.30001782" - electron-to-chromium: "npm:^1.5.328" - node-releases: "npm:^2.0.36" - update-browserslist-db: "npm:^1.2.3" - bin: - browserslist: cli.js - checksum: 10/cff88386e5b5ba5614c9063bd32ef94865bba22b6a381844c7d09ea1eea62a2247e7106e516abdbfda6b75b9986044c991dfe45f92f10add5ad63dccc07589ec - languageName: node - linkType: hard - "bs-logger@npm:^0.2.6": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" @@ -10765,6 +10867,13 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^0.7.0": + version: 0.7.0 + resolution: "dedent@npm:0.7.0" + checksum: 10/87de191050d9a40dd70cad01159a0bcf05ecb59750951242070b6abf9569088684880d00ba92a955b4058804f16eeaf91d604f283929b4f614d181cd7ae633d2 + languageName: node + linkType: hard + "dedent@npm:^1.6.0": version: 1.7.0 resolution: "dedent@npm:1.7.0" @@ -10885,6 +10994,22 @@ __metadata: languageName: node linkType: hard +"del@npm:^6.1.1": + version: 6.1.1 + resolution: "del@npm:6.1.1" + dependencies: + globby: "npm:^11.0.1" + graceful-fs: "npm:^4.2.4" + is-glob: "npm:^4.0.1" + is-path-cwd: "npm:^2.2.0" + is-path-inside: "npm:^3.0.2" + p-map: "npm:^4.0.0" + rimraf: "npm:^3.0.2" + slash: "npm:^3.0.0" + checksum: 10/563288b73b8b19a7261c47fd21a330eeab6e2acd7c6208c49790dfd369127120dd7836cdf0c1eca216b77c94782a81507eac6b4734252d3bef2795cb366996b6 + languageName: node + linkType: hard + "del@npm:^8.0.1": version: 8.0.1 resolution: "del@npm:8.0.1" @@ -11125,6 +11250,15 @@ __metadata: languageName: node linkType: hard +"dir-glob@npm:^3.0.1": + version: 3.0.1 + resolution: "dir-glob@npm:3.0.1" + dependencies: + path-type: "npm:^4.0.0" + checksum: 10/fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 + languageName: node + linkType: hard + "discontinuous-range@npm:1.0.0": version: 1.0.0 resolution: "discontinuous-range@npm:1.0.0" @@ -12418,29 +12552,29 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.3.2": - version: 3.3.2 - resolution: "fast-glob@npm:3.3.2" +"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.3": + version: 3.3.3 + resolution: "fast-glob@npm:3.3.3" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.4" - checksum: 10/222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df + micromatch: "npm:^4.0.8" + checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad languageName: node linkType: hard -"fast-glob@npm:^3.3.3": - version: 3.3.3 - resolution: "fast-glob@npm:3.3.3" +"fast-glob@npm:^3.3.2": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.8" - checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad + micromatch: "npm:^4.0.4" + checksum: 10/222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df languageName: node linkType: hard @@ -13652,6 +13786,20 @@ __metadata: languageName: node linkType: hard +"globby@npm:^11.0.1": + version: 11.1.0 + resolution: "globby@npm:11.1.0" + dependencies: + array-union: "npm:^2.1.0" + dir-glob: "npm:^3.0.1" + fast-glob: "npm:^3.2.9" + ignore: "npm:^5.2.0" + merge2: "npm:^1.4.1" + slash: "npm:^3.0.0" + checksum: 10/288e95e310227bbe037076ea81b7c2598ccbc3122d87abc6dab39e1eec309aa14f0e366a98cdc45237ffcfcbad3db597778c0068217dcb1950fef6249104e1b1 + languageName: node + linkType: hard + "globby@npm:^14.0.2": version: 14.1.0 resolution: "globby@npm:14.1.0" @@ -14950,7 +15098,7 @@ __metadata: languageName: node linkType: hard -"is-git-dirty@npm:^2.0.2": +"is-git-dirty@npm:^2.0.1, is-git-dirty@npm:^2.0.2": version: 2.0.2 resolution: "is-git-dirty@npm:2.0.2" dependencies: @@ -15058,6 +15206,13 @@ __metadata: languageName: node linkType: hard +"is-path-cwd@npm:^2.2.0": + version: 2.2.0 + resolution: "is-path-cwd@npm:2.2.0" + checksum: 10/46a840921bb8cc0dc7b5b423a14220e7db338072a4495743a8230533ce78812dc152548c86f4b828411fe98c5451959f07cf841c6a19f611e46600bd699e8048 + languageName: node + linkType: hard + "is-path-cwd@npm:^3.0.0": version: 3.0.0 resolution: "is-path-cwd@npm:3.0.0" @@ -16435,7 +16590,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.2.2, json5@npm:^2.2.3": +"json5@npm:^2.2.1, json5@npm:^2.2.2, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -16619,7 +16774,7 @@ __metadata: languageName: node linkType: hard -"kleur@npm:^4.1.5": +"kleur@npm:^4.1.4, kleur@npm:^4.1.5": version: 4.1.5 resolution: "kleur@npm:4.1.5" checksum: 10/44d84cc4eedd4311099402ef6d4acd9b2d16e08e499d6ef3bb92389bd4692d7ef09e35248c26e27f98acac532122acb12a1bfee645994ae3af4f0a37996da7df @@ -17728,7 +17883,7 @@ __metadata: languageName: node linkType: hard -"merge2@npm:^1.3.0": +"merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" checksum: 10/7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 @@ -20675,7 +20830,7 @@ __metadata: languageName: node linkType: hard -"p-map@npm:4.0.0": +"p-map@npm:4.0.0, p-map@npm:^4.0.0": version: 4.0.0 resolution: "p-map@npm:4.0.0" dependencies: @@ -21163,6 +21318,13 @@ __metadata: languageName: node linkType: hard +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 10/5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 + languageName: node + linkType: hard + "path-type@npm:^6.0.0": version: 6.0.0 resolution: "path-type@npm:6.0.0" @@ -21978,6 +22140,38 @@ __metadata: languageName: node linkType: hard +"react-native-builder-bob@npm:^0.40.13": + version: 0.40.18 + resolution: "react-native-builder-bob@npm:0.40.18" + dependencies: + "@babel/core": "npm:^7.25.2" + "@babel/plugin-transform-flow-strip-types": "npm:^7.26.5" + "@babel/plugin-transform-strict-mode": "npm:^7.24.7" + "@babel/preset-env": "npm:^7.25.2" + "@babel/preset-react": "npm:^7.24.7" + "@babel/preset-typescript": "npm:^7.24.7" + arktype: "npm:^2.1.15" + babel-plugin-syntax-hermes-parser: "npm:^0.28.0" + browserslist: "npm:^4.20.4" + cross-spawn: "npm:^7.0.3" + dedent: "npm:^0.7.0" + del: "npm:^6.1.1" + escape-string-regexp: "npm:^4.0.0" + fs-extra: "npm:^10.1.0" + glob: "npm:^10.5.0" + is-git-dirty: "npm:^2.0.1" + json5: "npm:^2.2.1" + kleur: "npm:^4.1.4" + prompts: "npm:^2.4.2" + react-native-monorepo-config: "npm:^0.3.3" + which: "npm:^2.0.2" + yargs: "npm:^17.5.1" + bin: + bob: bin/bob + checksum: 10/06eddba046a508dff0aa322c823fa57a280e2ed6a6f586de2114ebc11b6bb7863714eaaff8e93d681bb851fb4f9e792b102541211847f0e546f4e9546df6c3de + languageName: node + linkType: hard + "react-native-builder-bob@npm:^0.41.0": version: 0.41.0 resolution: "react-native-builder-bob@npm:0.41.0" @@ -26232,7 +26426,7 @@ __metadata: languageName: node linkType: hard -"which@npm:^2.0.1": +"which@npm:^2.0.1, which@npm:^2.0.2": version: 2.0.2 resolution: "which@npm:2.0.2" dependencies: @@ -26639,7 +26833,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.6.2, yargs@npm:^17.7.2": +"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.5.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: From 2dd2b23dc20e56812578ba7bb0926869aa0c5357 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 12 May 2026 17:26:37 +0100 Subject: [PATCH 12/12] chore: import installations types --- .github/scripts/compare-types/src/registry.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/scripts/compare-types/src/registry.ts b/.github/scripts/compare-types/src/registry.ts index 64350cb00e..97756f7930 100644 --- a/.github/scripts/compare-types/src/registry.ts +++ b/.github/scripts/compare-types/src/registry.ts @@ -18,6 +18,7 @@ import appCheckConfig from '../configs/app-check'; import firestoreConfig from '../configs/firestore'; import firestorePipelinesConfig from '../configs/firestore-pipelines'; import remoteConfigConfig from '../configs/remote-config'; +import installationsConfig from '../configs/installations'; const SCRIPT_DIR = path.resolve(__dirname, '..'); const REPO_ROOT = path.resolve(SCRIPT_DIR, '..', '..', '..');