From 51534dff9729c50165e7054da4a08f54d78573e2 Mon Sep 17 00:00:00 2001
From: Mike Hardy
Date: Tue, 17 Aug 2021 18:31:52 -0500
Subject: [PATCH 1/4] test(e2e): make sure all e2e tests are run even in
sub-directories
I tested to verify this does not stop running any existing tests (even if
not in sub-directories), but there's no reason not to add the recursive glob
in now just in case to future proof all tests
---
tests/e2e/.mocharc.js | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/tests/e2e/.mocharc.js b/tests/e2e/.mocharc.js
index c15d4922b3..b3e23fe121 100644
--- a/tests/e2e/.mocharc.js
+++ b/tests/e2e/.mocharc.js
@@ -11,20 +11,20 @@ module.exports = {
recursive: true,
require: 'node_modules/jet/platform/node',
spec: [
- '../packages/app/e2e/*.e2e.js',
- '../packages/app-check/e2e/*.e2e.js',
- '../packages/analytics/e2e/*.e2e.js',
- '../packages/auth/e2e/*.e2e.js',
- '../packages/crashlytics/e2e/*.e2e.js',
+ '../packages/app/e2e/**/*.e2e.js',
+ '../packages/app-check/e2e/**/*.e2e.js',
+ '../packages/analytics/e2e/**/*.e2e.js',
+ '../packages/auth/e2e/**/*.e2e.js',
+ '../packages/crashlytics/e2e/**/*.e2e.js',
'../packages/database/e2e/**/*.e2e.js',
- '../packages/dynamic-links/e2e/*.e2e.js',
+ '../packages/dynamic-links/e2e/**/*.e2e.js',
'../packages/firestore/e2e/**/*.e2e.js',
- '../packages/functions/e2e/*.e2e.js',
- '../packages/perf/e2e/*.e2e.js',
- '../packages/messaging/e2e/*.e2e.js',
- '../packages/ml/e2e/*.e2e.js',
- '../packages/in-app-messaging/e2e/*.e2e.js',
- '../packages/remote-config/e2e/*.e2e.js',
- '../packages/storage/e2e/*.e2e.js',
+ '../packages/functions/e2e/**/*.e2e.js',
+ '../packages/perf/e2e/**/*.e2e.js',
+ '../packages/messaging/e2e/**/*.e2e.js',
+ '../packages/ml/e2e/**/*.e2e.js',
+ '../packages/in-app-messaging/e2e/**/*.e2e.js',
+ '../packages/remote-config/e2e/**/*.e2e.js',
+ '../packages/storage/e2e/**/*.e2e.js',
],
};
From 3900a5dedd28d1e9ea74753d45e1c9ff743e9f1c Mon Sep 17 00:00:00 2001
From: Mike Hardy
Date: Tue, 17 Aug 2021 18:38:41 -0500
Subject: [PATCH 2/4] chore(template): groom new module template more
this is the version used to generate the installations module boilerplate
---
scripts/_TEMPLATE_/e2e/_template_.e2e.js | 1 -
scripts/_TEMPLATE_/type-test.ts | 10 +++++-----
scripts/create-firebase-module.js | 12 +++++++++++-
3 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/scripts/_TEMPLATE_/e2e/_template_.e2e.js b/scripts/_TEMPLATE_/e2e/_template_.e2e.js
index d8bb85f380..e134dabc4f 100644
--- a/scripts/_TEMPLATE_/e2e/_template_.e2e.js
+++ b/scripts/_TEMPLATE_/e2e/_template_.e2e.js
@@ -16,7 +16,6 @@
*/
describe('_template_()', function () {
-
describe('aMethod()', function () {
// TODO
});
diff --git a/scripts/_TEMPLATE_/type-test.ts b/scripts/_TEMPLATE_/type-test.ts
index b08e556268..a02f58033c 100644
--- a/scripts/_TEMPLATE_/type-test.ts
+++ b/scripts/_TEMPLATE_/type-test.ts
@@ -1,14 +1,14 @@
import firebase from '@react-native-firebase/app';
-import defaultExport, { firebase as firebaseFromModule } from '@react-native-firebase/_Template_';
+import defaultExport, { firebase as firebaseFromModule } from '@react-native-firebase/_template_';
// checks module exists at root
-console.log(firebase._Template_().app.name);
+console.log(firebase._template_().app.name);
// checks module exists at app level
-console.log(firebase.app()._Template_().app.name);
+console.log(firebase.app()._template_().app.name);
// checks statics exist
-console.log(firebase._Template_.SDK_VERSION);
+console.log(firebase._template_.SDK_VERSION);
// checks statics exist on defaultExport
console.log(defaultExport.SDK_VERSION);
@@ -20,7 +20,7 @@ console.log(firebase.SDK_VERSION);
console.log(firebaseFromModule.SDK_VERSION);
// checks multi-app support exists
-console.log(firebase._Template_(firebase.app()).app.name);
+console.log(firebase._template_(firebase.app()).app.name);
// checks default export supports app arg
console.log(defaultExport(firebase.app()).app.name);
diff --git a/scripts/create-firebase-module.js b/scripts/create-firebase-module.js
index ebf05fd196..45b7ecea6e 100644
--- a/scripts/create-firebase-module.js
+++ b/scripts/create-firebase-module.js
@@ -101,7 +101,12 @@ inquirer
console.log('1) ADD IT TO `KNOWN_NAMESPACES` in packages/app/lib/internal/constants.js');
console.log('');
console.log('2) ADD IT TO THE docs:');
- console.log(' - in website/docs/sidebar.yaml');
+ console.log(' - in docs//index.md and usage/index.md');
+ console.log(
+ ' - in docs//... find the prev next links where you slice in and fix them',
+ );
+ console.log(' - in docs/app/usage.md list of apps that are multi-app, if it is multi-app');
+ console.log(' - in docs/sidebar.yaml');
console.log(' - in website/scripts/source-reference.js');
console.log(' - in website/src/templates/utils.ts');
console.log('');
@@ -109,5 +114,10 @@ inquirer
console.log(' - package namespaces in java and package.json and index.d.ts');
console.log(' - the @firebase tag in index.d.ts (creates docs site reference API links)');
console.log('');
+ console.log('4) Add the e2e tests:');
+ console.log(' - tests/e2e/.mocharc.js');
+ console.log(' - tests/package.json (and run yarn + yarn tests:pod:install)');
+ console.log(' - tests/app.js');
+ console.log('');
})
.catch(console.error);
From 0eb412c0d0d6b21f484ae5abe755ddaee3a49f72 Mon Sep 17 00:00:00 2001
From: Mike Hardy
Date: Tue, 17 Aug 2021 18:40:50 -0500
Subject: [PATCH 3/4] feat(installations): implement Firebase Installations
module
In particular Installations.delete() is needed for GDPR compliance
---
.spellcheck.dict.txt | 1 +
docs/app/usage.md | 3 +-
docs/in-app-messaging/usage/index.md | 2 +-
docs/installations/usage/index.md | 37 ++
docs/ml/usage/index.md | 2 +-
docs/sidebar.yaml | 4 +
packages/app/lib/internal/constants.js | 1 +
packages/installations/.npmignore | 65 ++++
packages/installations/LICENSE | 32 ++
packages/installations/README.md | 61 +++
.../installations/RNFBInstallations.podspec | 45 +++
.../__tests__/installations.test.ts | 21 ++
packages/installations/android/.editorconfig | 10 +
packages/installations/android/build.gradle | 99 +++++
packages/installations/android/lint.xml | 5 +
.../installations/android/settings.gradle | 1 +
.../android/src/main/AndroidManifest.xml | 8 +
...eactNativeFirebaseInstallationsModule.java | 107 ++++++
...actNativeFirebaseInstallationsPackage.java | 41 ++
.../installations/e2e/installations.e2e.js | 80 ++++
.../project.pbxproj | 349 ++++++++++++++++++
.../contents.xcworkspacedata | 7 +
.../xcshareddata/IDEWorkspaceChecks.plist | 8 +
.../xcshareddata/WorkspaceSettings.xcsettings | 5 +
.../xcshareddata/IDETemplateMacros.plist | 24 ++
.../RNFBInstallationsModule.h | 24 ++
.../RNFBInstallationsModule.m | 125 +++++++
packages/installations/lib/index.d.ts | 160 ++++++++
packages/installations/lib/index.js | 79 ++++
packages/installations/package.json | 30 ++
packages/installations/type-test.ts | 26 ++
tests/app.js | 1 +
tests/e2e/.mocharc.js | 1 +
tests/ios/Podfile.lock | 99 ++---
tests/package.json | 1 +
website/scripts/source-reference.js | 2 +
website/src/templates/utils.ts | 2 +
37 files changed, 1521 insertions(+), 47 deletions(-)
create mode 100644 docs/installations/usage/index.md
create mode 100644 packages/installations/.npmignore
create mode 100644 packages/installations/LICENSE
create mode 100644 packages/installations/README.md
create mode 100644 packages/installations/RNFBInstallations.podspec
create mode 100644 packages/installations/__tests__/installations.test.ts
create mode 100644 packages/installations/android/.editorconfig
create mode 100644 packages/installations/android/build.gradle
create mode 100644 packages/installations/android/lint.xml
create mode 100644 packages/installations/android/settings.gradle
create mode 100644 packages/installations/android/src/main/AndroidManifest.xml
create mode 100644 packages/installations/android/src/main/java/io/invertase/firebase/installations/ReactNativeFirebaseInstallationsModule.java
create mode 100644 packages/installations/android/src/main/java/io/invertase/firebase/installations/ReactNativeFirebaseInstallationsPackage.java
create mode 100644 packages/installations/e2e/installations.e2e.js
create mode 100644 packages/installations/ios/RNFBInstallations.xcodeproj/project.pbxproj
create mode 100644 packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/contents.xcworkspacedata
create mode 100644 packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
create mode 100644 packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
create mode 100644 packages/installations/ios/RNFBInstallations.xcodeproj/xcshareddata/IDETemplateMacros.plist
create mode 100644 packages/installations/ios/RNFBInstallations/RNFBInstallationsModule.h
create mode 100644 packages/installations/ios/RNFBInstallations/RNFBInstallationsModule.m
create mode 100644 packages/installations/lib/index.d.ts
create mode 100644 packages/installations/lib/index.js
create mode 100644 packages/installations/package.json
create mode 100644 packages/installations/type-test.ts
diff --git a/.spellcheck.dict.txt b/.spellcheck.dict.txt
index 74087c8078..d7d2f40149 100644
--- a/.spellcheck.dict.txt
+++ b/.spellcheck.dict.txt
@@ -55,6 +55,7 @@ Fastlane
FCM
firebase
Firebase
+FirebaseApp
firebase-ios-sdk
Firestore
getIdToken
diff --git a/docs/app/usage.md b/docs/app/usage.md
index 3cd0265396..e304c8b5e2 100644
--- a/docs/app/usage.md
+++ b/docs/app/usage.md
@@ -21,13 +21,14 @@ for manually initializing secondary Firebase app instances.
Currently, the native Firebase SDKs only provide functionality for creating secondary apps on the following services:
-- [AppCheck](/app-check/usage).
+- [App Check](/app-check/usage).
- [Authentication](/auth/usage).
- [Realtime Database](/database/usage).
- [Cloud Firestore](/firestore/usage).
- [Cloud Functions](/functions/usage)
- [Cloud Storage](/storage/usage).
- [ML](/ml/usage).
+- [Installations](/installations/usage),
- [Remote Config](/remote-config/usage).
## Initializing secondary apps
diff --git a/docs/in-app-messaging/usage/index.md b/docs/in-app-messaging/usage/index.md
index 72358725d4..04ad034e8a 100644
--- a/docs/in-app-messaging/usage/index.md
+++ b/docs/in-app-messaging/usage/index.md
@@ -2,7 +2,7 @@
title: In App Messaging
description: Installation and getting started with In App Messaging.
icon: //static.invertase.io/assets/firebase/in-app-messaging.svg
-next: /ml/usage
+next: /installations/usage
previous: /dynamic-links/usage
---
diff --git a/docs/installations/usage/index.md b/docs/installations/usage/index.md
new file mode 100644
index 0000000000..ed98d490ac
--- /dev/null
+++ b/docs/installations/usage/index.md
@@ -0,0 +1,37 @@
+---
+title: Installations
+description: Installation and getting started with Installations.
+icon: //static.invertase.io/assets/social/firebase-logo.png
+next: /ml/usage
+previous: /in-app-messaging/usage
+---
+
+# Installation
+
+This module requires that the `@react-native-firebase/app` module is already setup and installed. To install the "app"
+module, view the [Getting Started](/) documentation.
+
+```bash
+# Install & setup the app module
+yarn add @react-native-firebase/app
+
+# Install the installations module
+yarn add @react-native-firebase/installations
+
+# If you're developing your app using iOS, run this command
+cd ios/ && pod install
+```
+
+# What does it do
+
+The Firebase installations service:
+
+- provides a unique identifier for a Firebase installation
+- provides an auth token for a Firebase installation
+- provides an API to perform GDPR-compliant deletion of a Firebase installation.
+
+Each configured `FirebaseApp` has a corresponding single instance of Installations. An instance of the class provides access to the installation info for the FirebaseApp as well as the ability to delete it. A Firebase Installation is unique by `FirebaseApp.name` and `FirebaseApp.options.googleAppID`
+
+# Usage
+
+Please see the API Reference for detailed usage information on the available APIs
diff --git a/docs/ml/usage/index.md b/docs/ml/usage/index.md
index 8bb49c671b..3c48815c14 100644
--- a/docs/ml/usage/index.md
+++ b/docs/ml/usage/index.md
@@ -3,7 +3,7 @@ title: ML
description: Installation and getting started with ML.
icon: //static.invertase.io/assets/firebase/ml-kit.svg
next: /remote-config/usage
-previous: /in-app-messaging/usage
+previous: /installations/usage
---
# Installation
diff --git a/docs/sidebar.yaml b/docs/sidebar.yaml
index 51897590ca..86dd79753a 100644
--- a/docs/sidebar.yaml
+++ b/docs/sidebar.yaml
@@ -97,6 +97,10 @@
- - - Usage
- '/in-app-messaging/usage'
- '//static.invertase.io/assets/firebase/in-app-messaging.svg'
+- - Installations
+ - - - Usage
+ - '/installations/usage'
+ - '//static.invertase.io/assets/social/firebase-logo.png'
- - ML
- - - Usage
- '/ml/usage'
diff --git a/packages/app/lib/internal/constants.js b/packages/app/lib/internal/constants.js
index 4bc585ef6b..aae6cb3d62 100644
--- a/packages/app/lib/internal/constants.js
+++ b/packages/app/lib/internal/constants.js
@@ -27,6 +27,7 @@ export const KNOWN_NAMESPACES = [
'crashlytics',
'database',
'inAppMessaging',
+ 'installations',
'firestore',
'functions',
'indexing',
diff --git a/packages/installations/.npmignore b/packages/installations/.npmignore
new file mode 100644
index 0000000000..d9fa30e5a5
--- /dev/null
+++ b/packages/installations/.npmignore
@@ -0,0 +1,65 @@
+# Built application files
+android/*/build/
+
+# Crashlytics configuations
+android/com_crashlytics_export_strings.xml
+
+# Local configuration file (sdk path, etc)
+android/local.properties
+
+# Gradle generated files
+android/.gradle/
+
+# Signing files
+android/.signing/
+
+# User-specific configurations
+android/.idea/gradle.xml
+android/.idea/libraries/
+android/.idea/workspace.xml
+android/.idea/tasks.xml
+android/.idea/.name
+android/.idea/compiler.xml
+android/.idea/copyright/profiles_settings.xml
+android/.idea/encodings.xml
+android/.idea/misc.xml
+android/.idea/modules.xml
+android/.idea/scopes/scope_settings.xml
+android/.idea/vcs.xml
+android/*.iml
+
+# Xcode
+*.pbxuser
+*.mode1v3
+*.mode2v3
+*.perspectivev3
+*.xcuserstate
+ios/Pods
+ios/build
+*project.xcworkspace*
+*xcuserdata*
+
+# OS-specific files
+.DS_Store
+.DS_Store?
+._*
+.Spotlight-V100
+.Trashes
+ehthumbs.db
+Thumbs.dbandroid/gradle
+android/gradlew
+android/build
+android/gradlew.bat
+android/gradle/
+
+.idea
+coverage
+yarn.lock
+e2e/
+.github
+.vscode
+.nyc_output
+android/.settings
+*.coverage.json
+.circleci
+.eslintignore
diff --git a/packages/installations/LICENSE b/packages/installations/LICENSE
new file mode 100644
index 0000000000..ef3ed44f06
--- /dev/null
+++ b/packages/installations/LICENSE
@@ -0,0 +1,32 @@
+Apache-2.0 License
+------------------
+
+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 Apache-2.0 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.
+
+
+Creative Commons Attribution 3.0 License
+----------------------------------------
+
+Copyright (c) 2016-present Invertase Limited & Contributors
+
+Documentation and other instructional materials provided for this project
+(including on a separate documentation repository or it's documentation website) are
+licensed under the Creative Commons Attribution 3.0 License. Code samples/blocks
+contained therein are licensed under the Apache License, Version 2.0 (the "License"), as above.
+
+You may obtain a copy of the Creative Commons Attribution 3.0 License at
+
+ https://creativecommons.org/licenses/by/3.0/
diff --git a/packages/installations/README.md b/packages/installations/README.md
new file mode 100644
index 0000000000..b926f3ac08
--- /dev/null
+++ b/packages/installations/README.md
@@ -0,0 +1,61 @@
+
+
+ 
+
+
React Native Firebase - Installations
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+----
+
+Entry point for Firebase installations.
+
+The Firebase installations service:
+
+- provides a unique identifier for a Firebase installation
+- provides an auth token for a Firebase installation
+- provides a API to perform GDPR-compliant deletion of a Firebase installation.
+
+
+[> Learn More](https://firebase.google.com/docs/projects/manage-installations)
+
+## Installation
+
+Requires `@react-native-firebase/app` to be installed.
+
+```bash
+yarn add @react-native-firebase/installations
+```
+
+## Documentation
+
+ - [Guides](https://rnfirebase.io/installations/usage/)
+ - [Reference](https://rnfirebase.io/reference/installations)
+
+## License
+
+- See [LICENSE](/LICENSE)
+
+----
+
+
+
+
+ Built and maintained with đź’› by Invertase.
+
+
+
+----
diff --git a/packages/installations/RNFBInstallations.podspec b/packages/installations/RNFBInstallations.podspec
new file mode 100644
index 0000000000..3a9aa1b4cd
--- /dev/null
+++ b/packages/installations/RNFBInstallations.podspec
@@ -0,0 +1,45 @@
+require 'json'
+package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
+appPackage = JSON.parse(File.read(File.join('..', 'app', 'package.json')))
+
+coreVersionDetected = appPackage['version']
+coreVersionRequired = package['peerDependencies'][appPackage['name']]
+firebase_sdk_version = appPackage['sdkVersions']['ios']['firebase']
+if coreVersionDetected != coreVersionRequired
+ Pod::UI.warn "NPM package '#{package['name']}' depends on '#{appPackage['name']}' v#{coreVersionRequired} but found v#{coreVersionDetected}, this might cause build issues or runtime crashes."
+end
+
+Pod::Spec.new do |s|
+ s.name = "RNFBInstallations"
+ s.version = package["version"]
+ s.description = package["description"]
+ s.summary = <<-DESC
+ A well tested feature rich Firebase implementation for React Native, supporting iOS & Android.
+ DESC
+ s.homepage = "http://invertase.io/oss/react-native-firebase"
+ s.license = package['license']
+ s.authors = "Invertase Limited"
+ s.source = { :git => "https://github.com/invertase/react-native-firebase.git", :tag => "v#{s.version}" }
+ s.social_media_url = 'http://twitter.com/invertaseio'
+ s.ios.deployment_target = "10.0"
+ s.source_files = 'ios/**/*.{h,m}'
+
+ # React Native dependencies
+ s.dependency 'React-Core'
+ s.dependency 'RNFBApp'
+
+ if defined?($FirebaseSDKVersion)
+ Pod::UI.puts "#{s.name}: Using user specified Firebase SDK version '#{$FirebaseSDKVersion}'"
+ firebase_sdk_version = $FirebaseSDKVersion
+ end
+
+ # Firebase dependencies
+ s.dependency 'Firebase/Installations', firebase_sdk_version
+
+ if defined?($RNFirebaseAsStaticFramework)
+ Pod::UI.puts "#{s.name}: Using overridden static_framework value of '#{$RNFirebaseAsStaticFramework}'"
+ s.static_framework = $RNFirebaseAsStaticFramework
+ else
+ s.static_framework = false
+ end
+end
diff --git a/packages/installations/__tests__/installations.test.ts b/packages/installations/__tests__/installations.test.ts
new file mode 100644
index 0000000000..c1a945bcad
--- /dev/null
+++ b/packages/installations/__tests__/installations.test.ts
@@ -0,0 +1,21 @@
+import { firebase } from '../lib';
+
+describe('installations()', function () {
+ describe('namespace', function () {
+ it('accessible from firebase.app()', function () {
+ const app = firebase.app();
+ expect(app.installations).toBeDefined();
+ expect(app.installations().app).toEqual(app);
+ });
+
+ it('supports multiple apps', async function () {
+ expect(firebase.installations().app.name).toEqual('[DEFAULT]');
+ expect(firebase.installations(firebase.app('secondaryFromNative')).app.name).toEqual(
+ 'secondaryFromNative',
+ );
+ expect(firebase.app('secondaryFromNative').installations().app.name).toEqual(
+ 'secondaryFromNative',
+ );
+ });
+ });
+});
diff --git a/packages/installations/android/.editorconfig b/packages/installations/android/.editorconfig
new file mode 100644
index 0000000000..670398e990
--- /dev/null
+++ b/packages/installations/android/.editorconfig
@@ -0,0 +1,10 @@
+# editorconfig
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
diff --git a/packages/installations/android/build.gradle b/packages/installations/android/build.gradle
new file mode 100644
index 0000000000..75788c2138
--- /dev/null
+++ b/packages/installations/android/build.gradle
@@ -0,0 +1,99 @@
+import io.invertase.gradle.common.PackageJson
+
+buildscript {
+ // The Android Gradle plugin is only required when opening the android folder stand-alone.
+ // This avoids unnecessary downloads and potential conflicts when the library is included as a
+ // module dependency in an application project.
+ if (project == rootProject) {
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath("com.android.tools.build:gradle:7.0.0")
+ }
+ }
+}
+
+plugins {
+ id "io.invertase.gradle.build" version "1.5"
+}
+
+def appProject
+if (findProject(':@react-native-firebase_app')) {
+ appProject = project(':@react-native-firebase_app')
+} else if (findProject(':react-native-firebase_app')) {
+ appProject = project(':react-native-firebase_app')
+} else {
+ throw new GradleException('Could not find the react-native-firebase/app package, have you installed it?')
+}
+def packageJson = PackageJson.getForProject(project)
+def appPackageJson = PackageJson.getForProject(appProject)
+def firebaseBomVersion = appPackageJson['sdkVersions']['android']['firebase']
+def jsonMinSdk = appPackageJson['sdkVersions']['android']['minSdk']
+def jsonTargetSdk = appPackageJson['sdkVersions']['android']['targetSdk']
+def jsonCompileSdk = appPackageJson['sdkVersions']['android']['compileSdk']
+def jsonBuildTools = appPackageJson['sdkVersions']['android']['buildTools']
+def coreVersionDetected = appPackageJson['version']
+def coreVersionRequired = packageJson['peerDependencies'][appPackageJson['name']]
+// Only log after build completed so log warning appears at the end
+if (coreVersionDetected != coreVersionRequired) {
+ gradle.buildFinished {
+ project.logger.warn("ReactNativeFirebase WARNING: NPM package '${packageJson['name']}' depends on '${appPackageJson['name']}' v${coreVersionRequired} but found v${coreVersionDetected}, this might cause build issues or runtime crashes.")
+ }
+}
+
+project.ext {
+ set('react-native', [
+ versions: [
+ android : [
+ minSdk : jsonMinSdk,
+ targetSdk : jsonTargetSdk,
+ compileSdk: jsonCompileSdk,
+ // optional as gradle.buildTools comes with one by default
+ // overriding here though to match the version RN uses
+ buildTools: jsonBuildTools
+ ],
+
+ firebase: [
+ bom: firebaseBomVersion,
+ ],
+ ],
+ ])
+}
+
+android {
+ defaultConfig {
+ multiDexEnabled true
+ }
+ lintOptions {
+ disable 'GradleCompatible'
+ abortOnError false
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ sourceSets {
+ main {
+ java.srcDirs = ['src/main/java', 'src/reactnative/java']
+ }
+ }
+}
+
+repositories {
+ google()
+ mavenCentral()
+}
+
+dependencies {
+ api appProject
+ implementation platform("com.google.firebase:firebase-bom:${ReactNative.ext.getVersion("firebase", "bom")}")
+ implementation "com.google.firebase:firebase-installations"
+}
+
+ReactNative.shared.applyPackageVersion()
+ReactNative.shared.applyDefaultExcludes()
+ReactNative.module.applyAndroidVersions()
+ReactNative.module.applyReactNativeDependency("api")
diff --git a/packages/installations/android/lint.xml b/packages/installations/android/lint.xml
new file mode 100644
index 0000000000..c3dd72aca0
--- /dev/null
+++ b/packages/installations/android/lint.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/packages/installations/android/settings.gradle b/packages/installations/android/settings.gradle
new file mode 100644
index 0000000000..82e62bda0e
--- /dev/null
+++ b/packages/installations/android/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = '@react-native-firebase_installations'
diff --git a/packages/installations/android/src/main/AndroidManifest.xml b/packages/installations/android/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..7790b94d21
--- /dev/null
+++ b/packages/installations/android/src/main/AndroidManifest.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/packages/installations/android/src/main/java/io/invertase/firebase/installations/ReactNativeFirebaseInstallationsModule.java b/packages/installations/android/src/main/java/io/invertase/firebase/installations/ReactNativeFirebaseInstallationsModule.java
new file mode 100644
index 0000000000..eb40ad7a97
--- /dev/null
+++ b/packages/installations/android/src/main/java/io/invertase/firebase/installations/ReactNativeFirebaseInstallationsModule.java
@@ -0,0 +1,107 @@
+package io.invertase.firebase.installations;
+
+/*
+ * 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 android.util.Log;
+import com.facebook.react.bridge.*;
+import com.google.android.gms.tasks.Tasks;
+import com.google.firebase.FirebaseApp;
+import com.google.firebase.installations.FirebaseInstallations;
+import io.invertase.firebase.common.ReactNativeFirebaseModule;
+
+public class ReactNativeFirebaseInstallationsModule extends ReactNativeFirebaseModule {
+ private static final String TAG = "Installations";
+
+ ReactNativeFirebaseInstallationsModule(ReactApplicationContext reactContext) {
+ super(reactContext, TAG);
+ }
+
+ @ReactMethod
+ public void getId(String appName, Promise promise) {
+ FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
+
+ Tasks.call(
+ getExecutor(),
+ () -> {
+ return Tasks.await(FirebaseInstallations.getInstance(firebaseApp).getId());
+ })
+ .addOnCompleteListener(
+ getExecutor(),
+ (task) -> {
+ if (task.isSuccessful()) {
+ promise.resolve(task.getResult());
+ } else {
+ Log.e(
+ TAG,
+ "RNFB: Unknown error while fetching Installations ID "
+ + task.getException().getMessage());
+ rejectPromiseWithCodeAndMessage(
+ promise, "id-error", task.getException().getMessage());
+ }
+ });
+ }
+
+ @ReactMethod
+ public void getToken(String appName, boolean forceRefresh, Promise promise) {
+ FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
+ Tasks.call(
+ getExecutor(),
+ () -> {
+ return Tasks.await(
+ FirebaseInstallations.getInstance(firebaseApp).getToken(forceRefresh));
+ })
+ .addOnCompleteListener(
+ getExecutor(),
+ (task) -> {
+ if (task.isSuccessful()) {
+ promise.resolve(task.getResult().getToken());
+ } else {
+ Log.e(
+ TAG,
+ "RNFB: Unknown error while fetching Installations token "
+ + task.getException().getMessage());
+ rejectPromiseWithCodeAndMessage(
+ promise, "token-error", task.getException().getMessage());
+ }
+ });
+ }
+
+ @ReactMethod
+ public void delete(String appName, Promise promise) {
+ FirebaseApp firebaseApp = FirebaseApp.getInstance(appName);
+ Tasks.call(
+ getExecutor(),
+ () -> {
+ return Tasks.await(FirebaseInstallations.getInstance(firebaseApp).delete());
+ })
+ .addOnCompleteListener(
+ getExecutor(),
+ (task) -> {
+ if (task.isSuccessful()) {
+ promise.resolve(null);
+ } else {
+ Log.e(
+ TAG,
+ "RNFB: Unknown error while deleting Installations"
+ + task.getException().getMessage());
+ rejectPromiseWithCodeAndMessage(
+ promise, "delete-error", task.getException().getMessage());
+ }
+ });
+ }
+}
diff --git a/packages/installations/android/src/main/java/io/invertase/firebase/installations/ReactNativeFirebaseInstallationsPackage.java b/packages/installations/android/src/main/java/io/invertase/firebase/installations/ReactNativeFirebaseInstallationsPackage.java
new file mode 100644
index 0000000000..a845533203
--- /dev/null
+++ b/packages/installations/android/src/main/java/io/invertase/firebase/installations/ReactNativeFirebaseInstallationsPackage.java
@@ -0,0 +1,41 @@
+package io.invertase.firebase.installations;
+
+/*
+ * 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 com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.uimanager.ViewManager;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@SuppressWarnings("unused")
+public class ReactNativeFirebaseInstallationsPackage implements ReactPackage {
+ @Override
+ public List createNativeModules(ReactApplicationContext reactContext) {
+ List modules = new ArrayList<>();
+ modules.add(new ReactNativeFirebaseInstallationsModule(reactContext));
+ return modules;
+ }
+
+ @Override
+ public List createViewManagers(ReactApplicationContext reactContext) {
+ return Collections.emptyList();
+ }
+}
diff --git a/packages/installations/e2e/installations.e2e.js b/packages/installations/e2e/installations.e2e.js
new file mode 100644
index 0000000000..41967e0ebd
--- /dev/null
+++ b/packages/installations/e2e/installations.e2e.js
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ *
+ */
+
+const jwt = require('jsonwebtoken');
+
+const ID_LENGTH = 22;
+const PROJECT_ID = 448618578101; // this is "magic", it's the react-native-firebase-testing project ID
+
+describe('installations()', function () {
+ describe('getId()', function () {
+ it('returns a valid installation id', async function () {
+ const id = await firebase.installations().getId();
+ id.should.be.a.String();
+ id.length.should.be.equals(ID_LENGTH);
+ });
+ });
+
+ describe('getToken()', function () {
+ it('returns a valid auth token with no arguments', async function () {
+ const id = await firebase.installations().getId();
+ const token = await firebase.installations().getToken();
+ token.should.be.a.String();
+ token.should.not.equal('');
+ const decodedToken = jwt.decode(token);
+ decodedToken.fid.should.equal(id); // fid == firebase installations id
+ decodedToken.projectNumber.should.equal(PROJECT_ID);
+ if (decodedToken.exp < Date.now()) {
+ Promise.reject('Token already expired');
+ }
+
+ const token2 = await firebase.installations().getToken(true);
+ token2.should.be.a.String();
+ token2.should.not.equal('');
+ const decodedToken2 = jwt.decode(token2);
+ decodedToken2.fid.should.equal(id);
+ decodedToken2.projectNumber.should.equal(PROJECT_ID);
+ if (decodedToken2.exp < Date.now()) {
+ Promise.reject('Token already expired');
+ }
+ (token === token2).should.be.false();
+ });
+ });
+
+ describe('delete()', function () {
+ it('successfully deletes', async function () {
+ const id = await firebase.installations().getId();
+ id.should.be.a.String();
+ id.length.should.be.equals(ID_LENGTH);
+ await firebase.installations().delete();
+
+ // New id should be different
+ const id2 = await firebase.installations().getId();
+ id2.should.be.a.String();
+ id2.length.should.be.equals(ID_LENGTH);
+ (id === id2).should.be.false();
+
+ const token = await firebase.installations().getToken(false);
+ const decodedToken = jwt.decode(token);
+ decodedToken.fid.should.equal(id2); // fid == firebase installations id
+ decodedToken.projectNumber.should.equal(PROJECT_ID);
+ if (decodedToken.exp < Date.now()) {
+ Promise.reject('Token already expired');
+ }
+ });
+ });
+});
diff --git a/packages/installations/ios/RNFBInstallations.xcodeproj/project.pbxproj b/packages/installations/ios/RNFBInstallations.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..d238d5a79d
--- /dev/null
+++ b/packages/installations/ios/RNFBInstallations.xcodeproj/project.pbxproj
@@ -0,0 +1,349 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 48;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 2744B98621F45429004F8E3F /* RNFBInstallationsModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 2744B98521F45429004F8E3F /* RNFBInstallationsModule.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 2744B98021F45429004F8E3F /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 16;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 2744B98221F45429004F8E3F /* libRNFBInstallations.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNFBInstallations.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 2744B98421F45429004F8E3F /* RNFBInstallationsModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RNFBInstallationsModule.h; path = RNFBInstallations/RNFBInstallationsModule.h; sourceTree = SOURCE_ROOT; };
+ 2744B98521F45429004F8E3F /* RNFBInstallationsModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RNFBInstallationsModule.m; path = RNFBInstallations/RNFBInstallationsModule.m; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 2744B97F21F45429004F8E3F /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 2744B97521F452B8004F8E3F /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 2744B98221F45429004F8E3F /* libRNFBInstallations.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 2744B98321F45429004F8E3F /* RNFBInstallations */ = {
+ isa = PBXGroup;
+ children = (
+ 2744B9A121F48736004F8E3F /* converters */,
+ 2744B98C21F45C64004F8E3F /* common */,
+ 2744B98421F45429004F8E3F /* RNFBInstallationsModule.h */,
+ 2744B98521F45429004F8E3F /* RNFBInstallationsModule.m */,
+ );
+ path = RNFBInstallations;
+ sourceTree = "";
+ };
+ 3323F52AAFE26B7384BE4DE3 = {
+ isa = PBXGroup;
+ children = (
+ 2744B98321F45429004F8E3F /* RNFBInstallations */,
+ 2744B97521F452B8004F8E3F /* Products */,
+ );
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 2744B98121F45429004F8E3F /* RNFBInstallations */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 2744B98821F45429004F8E3F /* Build configuration list for PBXNativeTarget "RNFBInstallations" */;
+ buildPhases = (
+ 2744B97E21F45429004F8E3F /* Sources */,
+ 2744B97F21F45429004F8E3F /* Frameworks */,
+ 2744B98021F45429004F8E3F /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = RNFBInstallations;
+ productName = RNFBInstallations;
+ productReference = 2744B98221F45429004F8E3F /* libRNFBInstallations.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 3323F95273A95DB34F55C6D7 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ CLASSPREFIX = RNFBInstallations;
+ LastUpgradeCheck = 1010;
+ ORGANIZATIONNAME = Invertase;
+ TargetAttributes = {
+ 2744B98121F45429004F8E3F = {
+ CreatedOnToolsVersion = 10.1;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 3323F1C5716BA966BBBB95A4 /* Build configuration list for PBXProject "RNFBInstallations" */;
+ compatibilityVersion = "Xcode 8.0";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 3323F52AAFE26B7384BE4DE3;
+ productRefGroup = 2744B97521F452B8004F8E3F /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 2744B98121F45429004F8E3F /* RNFBInstallations */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 2744B97E21F45429004F8E3F /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2744B98621F45429004F8E3F /* RNFBInstallationsModule.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 2744B98921F45429004F8E3F /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 2744B98A21F45429004F8E3F /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_IDENTITY = "iPhone Developer";
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ OTHER_LDFLAGS = "-ObjC";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = iphoneos;
+ SKIP_INSTALL = YES;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 3323F77D701E1896E6D239CF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "${BUILT_PRODUCTS_DIR}/**",
+ "${SRCROOT}/../../../ios/Firebase/**",
+ "$(FIREBASE_SEARCH_PATH)/Firebase/**",
+ "$(SRCROOT)/../../../ios/Pods/FirebaseInstallations/Frameworks",
+ "$(SRCROOT)/../../../tests/ios/Pods/FirebaseInstallations/Frameworks",
+ );
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(REACT_SEARCH_PATH)/React/**",
+ "$(SRCROOT)/../../react-native/React/**",
+ "$(SRCROOT)/../../react-native-firebase/ios/**",
+ "$(FIREBASE_SEARCH_PATH)/Firebase/**",
+ "${SRCROOT}/../../../ios/Firebase/**",
+ "${SRCROOT}/../../../ios/Pods/Headers/Public/**",
+ "${SRCROOT}/../../../tests/ios/Pods/Headers/Public/**",
+ "$(SRCROOT)/../../../node_modules/react-native/React/**",
+ "$(SRCROOT)/../../../node_modules/react-native-firebase/ios/**",
+ "$(SRCROOT)/../../../packages/app/ios/**",
+ );
+ IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
+ MACH_O_TYPE = staticlib;
+ OTHER_LDFLAGS = "$(inherited)";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ };
+ name = Release;
+ };
+ 3323F7E33E1559A2B9826720 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "${BUILT_PRODUCTS_DIR}/**",
+ "${SRCROOT}/../../../ios/Firebase/**",
+ "$(FIREBASE_SEARCH_PATH)/Firebase/**",
+ "$(SRCROOT)/../../../ios/Pods/FirebaseInstallations/Frameworks",
+ );
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(REACT_SEARCH_PATH)/React/**",
+ "$(SRCROOT)/../../react-native/React/**",
+ "$(SRCROOT)/../../react-native-firebase/ios/**",
+ "$(FIREBASE_SEARCH_PATH)/Firebase/**",
+ "${SRCROOT}/../../../ios/Firebase/**",
+ "${SRCROOT}/../../../ios/Pods/Headers/Public/**",
+ "${SRCROOT}/../../../tests/ios/Pods/Headers/Public/**",
+ "$(SRCROOT)/../../../node_modules/react-native/React/**",
+ "$(SRCROOT)/../../../node_modules/react-native-firebase/ios/**",
+ "$(SRCROOT)/../../../packages/app/ios/**",
+ );
+ IPHONEOS_DEPLOYMENT_TARGET = 10.0;
+ LIBRARY_SEARCH_PATHS = "$(inherited)";
+ MACH_O_TYPE = staticlib;
+ ONLY_ACTIVE_ARCH = YES;
+ OTHER_LDFLAGS = "$(inherited)";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 2744B98821F45429004F8E3F /* Build configuration list for PBXNativeTarget "RNFBInstallations" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 2744B98921F45429004F8E3F /* Debug */,
+ 2744B98A21F45429004F8E3F /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 3323F1C5716BA966BBBB95A4 /* Build configuration list for PBXProject "RNFBInstallations" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 3323F7E33E1559A2B9826720 /* Debug */,
+ 3323F77D701E1896E6D239CF /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 3323F95273A95DB34F55C6D7 /* Project object */;
+}
diff --git a/packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000000..919434a625
--- /dev/null
+++ b/packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000000..18d981003d
--- /dev/null
+++ b/packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -0,0 +1,8 @@
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 0000000000..0c67376eba
--- /dev/null
+++ b/packages/installations/ios/RNFBInstallations.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/packages/installations/ios/RNFBInstallations.xcodeproj/xcshareddata/IDETemplateMacros.plist b/packages/installations/ios/RNFBInstallations.xcodeproj/xcshareddata/IDETemplateMacros.plist
new file mode 100644
index 0000000000..63f0a6e5dd
--- /dev/null
+++ b/packages/installations/ios/RNFBInstallations.xcodeproj/xcshareddata/IDETemplateMacros.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ FILEHEADER
+
+/**
+ * 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.
+ *
+ */
+
+
diff --git a/packages/installations/ios/RNFBInstallations/RNFBInstallationsModule.h b/packages/installations/ios/RNFBInstallations/RNFBInstallationsModule.h
new file mode 100644
index 0000000000..a734bb8f29
--- /dev/null
+++ b/packages/installations/ios/RNFBInstallations/RNFBInstallationsModule.h
@@ -0,0 +1,24 @@
+/**
+ * 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
+
+#import
+
+@interface RNFBInstallationsModule : NSObject
+
+@end
diff --git a/packages/installations/ios/RNFBInstallations/RNFBInstallationsModule.m b/packages/installations/ios/RNFBInstallations/RNFBInstallationsModule.m
new file mode 100644
index 0000000000..7b07b36a0b
--- /dev/null
+++ b/packages/installations/ios/RNFBInstallations/RNFBInstallationsModule.m
@@ -0,0 +1,125 @@
+/**
+ * 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
+#import
+
+#import "RNFBApp/RNFBSharedUtils.h"
+#import "RNFBInstallationsModule.h"
+
+#import "FirebaseInstallations/FIRInstallations.h"
+
+@implementation RNFBInstallationsModule
+#pragma mark -
+#pragma mark Module Setup
+
+RCT_EXPORT_MODULE();
+
+- (dispatch_queue_t)methodQueue {
+ return dispatch_get_main_queue();
+}
+
+#pragma mark -
+#pragma mark Firebase Installations Methods
+
+RCT_EXPORT_METHOD(delete
+ : (FIRApp *)firebaseApp
+ : (RCTPromiseResolveBlock)resolve
+ : (RCTPromiseRejectBlock)reject) {
+ FIRInstallations *installations = [FIRInstallations installationsWithApp:firebaseApp];
+ [installations deleteWithCompletion:^(NSError *_Nullable error) {
+ if (error != nil) {
+ // Handle any errors if the delete failed
+ DLog(@"Unable to delete Installations ID: %@", error);
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
+ userInfo:(NSMutableDictionary *)@{
+ @"code" : @"delete-error",
+ @"message" : [error localizedDescription],
+ }];
+ return;
+ }
+
+ resolve([NSNull null]);
+ }];
+}
+
+RCT_EXPORT_METHOD(getId
+ : (FIRApp *)firebaseApp
+ : (RCTPromiseResolveBlock)resolve
+ : (RCTPromiseRejectBlock)reject) {
+ FIRInstallations *installations = [FIRInstallations installationsWithApp:firebaseApp];
+ [installations installationIDWithCompletion:^(NSString *_Nullable id, NSError *_Nullable error) {
+ if (error != nil) {
+ // Handle any errors if the id was not retrieved.
+ DLog(@"Unable to retrieve Installations ID: %@", error);
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
+ userInfo:(NSMutableDictionary *)@{
+ @"code" : @"id-error",
+ @"message" : [error localizedDescription],
+ }];
+ return;
+ }
+ if (id == nil) {
+ DLog(@"Unable to retrieve Installations ID.");
+ [RNFBSharedUtils rejectPromiseWithUserInfo:reject
+ userInfo:(NSMutableDictionary *)@{
+ @"code" : @"id-null",
+ @"message" : @"no id fetched",
+ }];
+ return;
+ }
+
+ resolve(id);
+ }];
+}
+
+RCT_EXPORT_METHOD(getToken
+ : (FIRApp *)firebaseApp
+ : (BOOL)forceRefresh
+ : (RCTPromiseResolveBlock)resolve
+ : (RCTPromiseRejectBlock)reject) {
+ FIRInstallations *installations = [FIRInstallations installationsWithApp:firebaseApp];
+ [installations authTokenForcingRefresh:forceRefresh
+ completion:^(FIRInstallationsAuthTokenResult *_Nullable token,
+ NSError *_Nullable error) {
+ if (error != nil) {
+ // Handle any errors if the token was not retrieved.
+ DLog(@"Unable to retrieve Installations auth token: %@", error);
+ [RNFBSharedUtils
+ rejectPromiseWithUserInfo:reject
+ userInfo:(NSMutableDictionary *)@{
+ @"code" : @"token-error",
+ @"message" : [error localizedDescription],
+ }];
+ return;
+ }
+ if (token == nil) {
+ DLog(@"Unable to retrieve Installations auth token.");
+ [RNFBSharedUtils
+ rejectPromiseWithUserInfo:reject
+ userInfo:(NSMutableDictionary *)@{
+ @"code" : @"token-null",
+ @"message" : @"no token fetched",
+ }];
+ return;
+ }
+
+ resolve(token.authToken);
+ }];
+}
+
+@end
diff --git a/packages/installations/lib/index.d.ts b/packages/installations/lib/index.d.ts
new file mode 100644
index 0000000000..834289ca2b
--- /dev/null
+++ b/packages/installations/lib/index.d.ts
@@ -0,0 +1,160 @@
+/*
+ * 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;
+
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
+ export interface Statics {
+ // firebase.installations.* static props go here
+ }
+
+ /**
+ * 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 {
+ /**
+ * 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 a 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 of 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 Installlation 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;
+ }
+}
+
+declare const defaultExport: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp<
+ Installations.Module,
+ Installations.Statics
+>;
+
+export 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;
+ }
+ }
+}
diff --git a/packages/installations/lib/index.js b/packages/installations/lib/index.js
new file mode 100644
index 0000000000..cc00baddca
--- /dev/null
+++ b/packages/installations/lib/index.js
@@ -0,0 +1,79 @@
+/*
+ * 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/lib/common';
+import {
+ createModuleNamespace,
+ FirebaseModule,
+ getFirebaseRoot,
+} from '@react-native-firebase/app/lib/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();
diff --git a/packages/installations/package.json b/packages/installations/package.json
new file mode 100644
index 0000000000..eb1ebb5069
--- /dev/null
+++ b/packages/installations/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "@react-native-firebase/installations",
+ "version": "12.6.1",
+ "author": "Invertase (http://invertase.io)",
+ "description": "React Native Firebase - Installations",
+ "main": "lib/index.js",
+ "types": "lib/index.d.ts",
+ "scripts": {
+ "build": "genversion --semi lib/version.js",
+ "build:clean": "rimraf android/build && rimraf ios/build",
+ "prepare": "yarn run build"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/invertase/react-native-firebase/tree/master/packages/installations"
+ },
+ "license": "Apache-2.0",
+ "keywords": [
+ "react",
+ "react-native",
+ "firebase",
+ "installations"
+ ],
+ "peerDependencies": {
+ "@react-native-firebase/app": "12.6.1"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/installations/type-test.ts b/packages/installations/type-test.ts
new file mode 100644
index 0000000000..a0d0f17120
--- /dev/null
+++ b/packages/installations/type-test.ts
@@ -0,0 +1,26 @@
+import firebase from '@react-native-firebase/app';
+import defaultExport, { firebase as firebaseFromModule } from '@react-native-firebase/installations';
+
+// checks module exists at root
+console.log(firebase.installations().app.name);
+
+// checks module exists at app level
+console.log(firebase.app().installations().app.name);
+
+// checks statics exist
+console.log(firebase.installations.SDK_VERSION);
+
+// checks statics exist on defaultExport
+console.log(defaultExport.SDK_VERSION);
+
+// checks root exists
+console.log(firebase.SDK_VERSION);
+
+// checks firebase named export exists on module
+console.log(firebaseFromModule.SDK_VERSION);
+
+// checks multi-app support exists
+console.log(firebase.installations(firebase.app()).app.name);
+
+// checks default export supports app arg
+console.log(defaultExport(firebase.app()).app.name);
diff --git a/tests/app.js b/tests/app.js
index 51fa792f13..03ff6abb04 100644
--- a/tests/app.js
+++ b/tests/app.js
@@ -27,6 +27,7 @@ import '@react-native-firebase/dynamic-links';
import '@react-native-firebase/firestore';
import '@react-native-firebase/functions';
import '@react-native-firebase/in-app-messaging';
+import '@react-native-firebase/installations';
import '@react-native-firebase/messaging';
import '@react-native-firebase/ml';
import '@react-native-firebase/perf';
diff --git a/tests/e2e/.mocharc.js b/tests/e2e/.mocharc.js
index b3e23fe121..89631fb6ac 100644
--- a/tests/e2e/.mocharc.js
+++ b/tests/e2e/.mocharc.js
@@ -24,6 +24,7 @@ module.exports = {
'../packages/messaging/e2e/**/*.e2e.js',
'../packages/ml/e2e/**/*.e2e.js',
'../packages/in-app-messaging/e2e/**/*.e2e.js',
+ '../packages/installations/e2e/**/*.e2e.js',
'../packages/remote-config/e2e/**/*.e2e.js',
'../packages/storage/e2e/**/*.e2e.js',
],
diff --git a/tests/ios/Podfile.lock b/tests/ios/Podfile.lock
index 7e21b867d7..3a33702120 100644
--- a/tests/ios/Podfile.lock
+++ b/tests/ios/Podfile.lock
@@ -385,6 +385,9 @@ PODS:
- Firebase/InAppMessaging (8.5.0):
- Firebase/CoreOnly
- FirebaseInAppMessaging (~> 8.5.0-beta)
+ - Firebase/Installations (8.5.0):
+ - Firebase/CoreOnly
+ - FirebaseInstallations (~> 8.5.0)
- Firebase/Messaging (8.5.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 8.5.0)
@@ -397,7 +400,7 @@ PODS:
- Firebase/Storage (8.5.0):
- Firebase/CoreOnly
- FirebaseStorage (~> 8.5.0)
- - FirebaseABTesting (8.5.0):
+ - FirebaseABTesting (8.6.0):
- FirebaseCore (~> 8.0)
- FirebaseAnalytics (8.5.0):
- FirebaseAnalytics/AdIdSupport (= 8.5.0)
@@ -430,7 +433,7 @@ PODS:
- FirebaseCoreDiagnostics (~> 8.0)
- GoogleUtilities/Environment (~> 7.4)
- GoogleUtilities/Logger (~> 7.4)
- - FirebaseCoreDiagnostics (8.5.0):
+ - FirebaseCoreDiagnostics (8.6.0):
- GoogleDataTransport (~> 9.0)
- GoogleUtilities/Environment (~> 7.4)
- GoogleUtilities/Logger (~> 7.4)
@@ -517,25 +520,25 @@ PODS:
- GoogleUtilities/Environment (~> 7.2)
- nanopb (~> 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- - GoogleUtilities/AppDelegateSwizzler (7.5.0):
+ - GoogleUtilities/AppDelegateSwizzler (7.5.1):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- - GoogleUtilities/Environment (7.5.0):
+ - GoogleUtilities/Environment (7.5.1):
- PromisesObjC (< 3.0, >= 1.2)
- - GoogleUtilities/ISASwizzler (7.5.0)
- - GoogleUtilities/Logger (7.5.0):
+ - GoogleUtilities/ISASwizzler (7.5.1)
+ - GoogleUtilities/Logger (7.5.1):
- GoogleUtilities/Environment
- - GoogleUtilities/MethodSwizzler (7.5.0):
+ - GoogleUtilities/MethodSwizzler (7.5.1):
- GoogleUtilities/Logger
- - GoogleUtilities/Network (7.5.0):
+ - GoogleUtilities/Network (7.5.1):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- - "GoogleUtilities/NSData+zlib (7.5.0)"
- - GoogleUtilities/Reachability (7.5.0):
+ - "GoogleUtilities/NSData+zlib (7.5.1)"
+ - GoogleUtilities/Reachability (7.5.1):
- GoogleUtilities/Logger
- - GoogleUtilities/UserDefaults (7.5.0):
+ - GoogleUtilities/UserDefaults (7.5.1):
- GoogleUtilities/Logger
- "gRPC-C++ (1.28.2)":
- "gRPC-C++/Implementation (= 1.28.2)"
@@ -829,62 +832,66 @@ PODS:
- React-cxxreact (= 0.64.2)
- React-jsi (= 0.64.2)
- React-perflogger (= 0.64.2)
- - RNFBAnalytics (12.6.0):
+ - RNFBAnalytics (12.6.1):
- Firebase/Analytics (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBApp (12.6.0):
+ - RNFBApp (12.6.1):
- Firebase/CoreOnly (= 8.5.0)
- React-Core
- - RNFBAppCheck (12.6.0):
+ - RNFBAppCheck (12.6.1):
- Firebase/AppCheck (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBAuth (12.6.0):
+ - RNFBAuth (12.6.1):
- Firebase/Auth (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBCrashlytics (12.6.0):
+ - RNFBCrashlytics (12.6.1):
- Firebase/Crashlytics (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBDatabase (12.6.0):
+ - RNFBDatabase (12.6.1):
- Firebase/Database (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBDynamicLinks (12.6.0):
+ - RNFBDynamicLinks (12.6.1):
- Firebase/DynamicLinks (= 8.5.0)
- GoogleUtilities/AppDelegateSwizzler
- React-Core
- RNFBApp
- - RNFBFirestore (12.6.0):
+ - RNFBFirestore (12.6.1):
- Firebase/Firestore (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBFunctions (12.6.0):
+ - RNFBFunctions (12.6.1):
- Firebase/Functions (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBInAppMessaging (12.6.0):
+ - RNFBInAppMessaging (12.6.1):
- Firebase/InAppMessaging (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBMessaging (12.6.0):
+ - RNFBInstallations (12.6.1):
+ - Firebase/Installations (= 8.5.0)
+ - React-Core
+ - RNFBApp
+ - RNFBMessaging (12.6.1):
- Firebase/Messaging (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBML (12.6.0):
+ - RNFBML (12.6.1):
- React-Core
- RNFBApp
- - RNFBPerf (12.6.0):
+ - RNFBPerf (12.6.1):
- Firebase/Performance (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBRemoteConfig (12.6.0):
+ - RNFBRemoteConfig (12.6.1):
- Firebase/RemoteConfig (= 8.5.0)
- React-Core
- RNFBApp
- - RNFBStorage (12.6.0):
+ - RNFBStorage (12.6.1):
- Firebase/Storage (= 8.5.0)
- React-Core
- RNFBApp
@@ -931,6 +938,7 @@ DEPENDENCIES:
- RNFBFirestore (from `../../packages/firestore`)
- RNFBFunctions (from `../../packages/functions`)
- RNFBInAppMessaging (from `../../packages/in-app-messaging`)
+ - RNFBInstallations (from `../../packages/installations`)
- RNFBMessaging (from `../../packages/messaging`)
- RNFBML (from `../../packages/ml`)
- RNFBPerf (from `../../packages/perf`)
@@ -1049,6 +1057,8 @@ EXTERNAL SOURCES:
:path: "../../packages/functions"
RNFBInAppMessaging:
:path: "../../packages/in-app-messaging"
+ RNFBInstallations:
+ :path: "../../packages/installations"
RNFBMessaging:
:path: "../../packages/messaging"
RNFBML:
@@ -1070,12 +1080,12 @@ SPEC CHECKSUMS:
FBLazyVector: e686045572151edef46010a6f819ade377dfeb4b
FBReactNativeSpec: 25e094945df743fcfa1283399bf9715648bff333
Firebase: ff8c73105b90e33e1dc6c8e5445d7adc2ccdc7c1
- FirebaseABTesting: f7cb3fbed1c5bd3e733a79d9955447be3f3b06a5
+ FirebaseABTesting: c3e48ebf5e7e5c674c5a131c68e941d7921d83dc
FirebaseAnalytics: 96325c1e0acbd2bb805c6a613028b1fe599d6a37
FirebaseAppCheck: 0cced04f86b12f8b72d0a6437a7a4cf76e2ecc07
FirebaseAuth: b152ea261b60eeb9419ae7e5bf34761382b33277
FirebaseCore: 1c1ca72483b59b17050f5b4cec4fb748425a3901
- FirebaseCoreDiagnostics: 7bf55d386f9fc690d971b70a582142321a390eb8
+ FirebaseCoreDiagnostics: 3721920bde3a9a6d5aa093c1d25e9d3e47f694af
FirebaseCrashlytics: 8e7cf678cb149d421198388c6fc3d3acfd266539
FirebaseDatabase: 65c3742ed355f9b9db222036fd154e699ab7d672
FirebaseDynamicLinks: 6e406b3bb669f8c8a63e7254bb63251fa3f88a43
@@ -1090,7 +1100,7 @@ SPEC CHECKSUMS:
glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
GoogleAppMeasurement: 8d10c1c470fcb0e5143ed74fddd164f0a0384800
GoogleDataTransport: 85fd18ff3019bb85d3f2c551d04c481dedf71fc9
- GoogleUtilities: eea970f4a389963963bffe8d8fabe43540678b9c
+ GoogleUtilities: 3df19e3c24f7bbc291d8b5809aa6b0d41e642437
"gRPC-C++": 13d8ccef97d5c3c441b7e3c529ef28ebee86fad2
gRPC-Core: 4afa11bfbedf7cdecd04de535a9e046893404ed5
GTMSessionFetcher: 36689134877faeb055b27dfa4ccc9ceaa42e029e
@@ -1122,21 +1132,22 @@ SPEC CHECKSUMS:
React-RCTVibration: 24600e3b1aaa77126989bc58b6747509a1ba14f3
React-runtimeexecutor: a9904c6d0218fb9f8b19d6dd88607225927668f9
ReactCommon: 149906e01aa51142707a10665185db879898e966
- RNFBAnalytics: d176dc0b499a7d61a0a713d596742282c50a36d3
- RNFBApp: 6fbdb0d684c16507c4eb51689d4ff4cfef3bf11f
- RNFBAppCheck: 591b7fc417c0df45c4096335b0bd298b30825c42
- RNFBAuth: 352fddc14c7de4fcac69b12c821e20212845d974
- RNFBCrashlytics: 629aeb5619dd7501a28a3be42d0728de8f3d7bf8
- RNFBDatabase: b5a92ea365161fef1c522b644ad2f723de6bf3fd
- RNFBDynamicLinks: ef3c14bff6d716959999119161924005227e9059
- RNFBFirestore: b817db23e6cc021e60644efc04803be807fb07f1
- RNFBFunctions: 5cafd47980bca562d7c6175fde7aca154bb9ff77
- RNFBInAppMessaging: 7beecf33a06164b0de5a7f3744570c145d2b3e3b
- RNFBMessaging: 18158b22e06e2297df9628486193455eb619b46d
- RNFBML: 0742fa4815d7f9576c5d13b270fed7a51d1d030d
- RNFBPerf: 5d5d4a6a8a5506703c119b8742e8a12a5af2caa9
- RNFBRemoteConfig: 60c686bd4e6227ac5a013378be2f2e34d76c7803
- RNFBStorage: 8084581b1133aa14267f6cc6272d9d22f4470b08
+ RNFBAnalytics: c546bf14fbf0a19f0801890dc8569efd7e7892ba
+ RNFBApp: 169c26e7f857173bd17b3eb5aba4e80bab598b76
+ RNFBAppCheck: 6c135d623d954f47e83f7b05654ab0deaabe3c1f
+ RNFBAuth: 018b6408d969c734455e72d508400be021ceafa3
+ RNFBCrashlytics: e9026dec158d1d1bb303e6f01fc712aeee1b6fbb
+ RNFBDatabase: bcfffc8c1bcc595decb7567d2bce305d6e2ce5a5
+ RNFBDynamicLinks: 92cd6c4ba5edef4d37a927d09122aeccda1def0e
+ RNFBFirestore: 2b5601224411db7f3ada77c286d299094f56caee
+ RNFBFunctions: 6376a08f448bc8f40ce6bf2459fb4282cc79dffa
+ RNFBInAppMessaging: 6f2b66ab43952da1fc91711774454cdefce2931d
+ RNFBInstallations: e6dd6113016a96518177a2e1eb170c4bf44e8c17
+ RNFBMessaging: 5ceb208f9b65941db520be903cbd778f7ebd0065
+ RNFBML: dd88f4f3ab120c48737ff3fbe07c2ba5ece1e5d9
+ RNFBPerf: f2db4bed596bba3697a6bd8f801a592b21990fe2
+ RNFBRemoteConfig: 2e2c2df520233083918647752a9b41a54aada45a
+ RNFBStorage: e4ddd8a58cf28a7f67876d6298d19273c1fd65e4
Yoga: 575c581c63e0d35c9a83f4b46d01d63abc1100ac
PODFILE CHECKSUM: c61aa64b498060e6a9470f21629e95b1ece6f524
diff --git a/tests/package.json b/tests/package.json
index ef95336f3c..7737446863 100644
--- a/tests/package.json
+++ b/tests/package.json
@@ -18,6 +18,7 @@
"@react-native-firebase/firestore": "12.6.1",
"@react-native-firebase/functions": "12.6.1",
"@react-native-firebase/in-app-messaging": "12.6.1",
+ "@react-native-firebase/installations": "12.6.1",
"@react-native-firebase/messaging": "12.6.1",
"@react-native-firebase/ml": "12.6.1",
"@react-native-firebase/perf": "12.6.1",
diff --git a/website/scripts/source-reference.js b/website/scripts/source-reference.js
index e8df4fb7cd..82df859b22 100644
--- a/website/scripts/source-reference.js
+++ b/website/scripts/source-reference.js
@@ -165,6 +165,8 @@ function moduleNameToFullName(name) {
return 'Instance ID';
case 'in-app-messaging':
return 'In-App Messaging';
+ case 'installations':
+ return 'Installations';
case 'messaging':
return 'Cloud Messaging';
case 'ml':
diff --git a/website/src/templates/utils.ts b/website/src/templates/utils.ts
index 0bced9c3b1..91c7772052 100644
--- a/website/src/templates/utils.ts
+++ b/website/src/templates/utils.ts
@@ -47,6 +47,8 @@ function iconForModule(module: string): string {
return '//static.invertase.io/assets/firebase/dynamic-links.svg';
case 'in-app-messaging':
return '//static.invertase.io/assets/firebase/in-app-messaging.svg';
+ case 'installations':
+ return '//static.invertase.io/assets/social/firebase-logo.png';
case 'ml':
return '//static.invertase.io/assets/firebase/ml-kit.svg';
case 'remote-config':
From 25962fcd43f6ccceac2e0ec49e5164959c05b103 Mon Sep 17 00:00:00 2001
From: Mike Hardy
Date: Tue, 17 Aug 2021 23:29:33 -0500
Subject: [PATCH 4/4] fix(app-check): getToken(false) fix, listener unsubscribe
is a function
- previously sending false through would crash android
- forceRefresh currently ignored on iOS because of upstream issue causing native crash
- fix docs
---
packages/app-check/README.md | 14 +++++++++-----
packages/app-check/e2e/appcheck.e2e.js | 15 ++++++++++++++-
.../ios/RNFBAppcheck/RNFBAppCheckModule.m | 3 ++-
packages/app-check/lib/index.js | 12 ++++++++----
4 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/packages/app-check/README.md b/packages/app-check/README.md
index 3eceee080d..f5381f4910 100644
--- a/packages/app-check/README.md
+++ b/packages/app-check/README.md
@@ -21,9 +21,14 @@
---
-AppCheck description.
+App Check works alongside other Firebase services to help protect your backend resources from abuse, such as billing fraud or phishing. With App Check, devices running your app will use an app or device attestation provider that attests to one or both of the following:
-[> Learn More](https://firebase.google.com/products/app-check/)
+- Requests originate from your authentic app
+- Requests originate from an authentic, untampered device
+
+This attestation is attached to every request your app makes to your Firebase backend resources.
+
+[> Learn More](https://firebase.google.com/docs/app-check/)
## Installation
@@ -35,9 +40,8 @@ yarn add @react-native-firebase/app-check
## Documentation
-- [Guides](#TODO)
-- [Installation](#TODO)
-- [Reference](#TODO)
+- [Guides](https://rnfirebase.io/app-check/usage/)
+- [Reference](https://rnfirebase.io/reference/app-check)
## License
diff --git a/packages/app-check/e2e/appcheck.e2e.js b/packages/app-check/e2e/appcheck.e2e.js
index 6de89a42d1..eebbbafbd0 100644
--- a/packages/app-check/e2e/appcheck.e2e.js
+++ b/packages/app-check/e2e/appcheck.e2e.js
@@ -43,13 +43,26 @@ describe('appCheck()', function () {
describe('getToken())', function () {
it('token fetch attempt should work', async function () {
// Our tests configure a debug provider with shared secret so we should get a valid token
- const token = await firebase.appCheck().getToken(true);
+ const token = await firebase.appCheck().getToken();
token.should.not.equal('');
const decodedToken = jwt.decode(token);
decodedToken.aud[1].should.equal('projects/react-native-firebase-testing');
if (decodedToken.exp < Date.now()) {
Promise.reject('Token already expired');
}
+
+ // Force refresh should get a different token?
+ // TODO iOS tokens are stale because of https://github.com/firebase/firebase-ios-sdk/issues/8544
+ if (device.getPlatform() === 'android') {
+ const token2 = await firebase.appCheck().getToken(true);
+ token2.should.not.equal('');
+ const decodedToken2 = jwt.decode(token2);
+ decodedToken2.aud[1].should.equal('projects/react-native-firebase-testing');
+ if (decodedToken2.exp < Date.now()) {
+ Promise.reject('Token already expired');
+ }
+ (token === token2).should.be.false();
+ }
});
});
describe('activate())', function () {
diff --git a/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.m b/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.m
index 5f77170e7a..a37e183d8f 100644
--- a/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.m
+++ b/packages/app-check/ios/RNFBAppcheck/RNFBAppCheckModule.m
@@ -75,7 +75,8 @@ - (dispatch_queue_t)methodQueue {
: (RCTPromiseResolveBlock)resolve
: (RCTPromiseRejectBlock)reject) {
FIRAppCheck *appCheck = [FIRAppCheck appCheckWithApp:firebaseApp];
- [appCheck tokenForcingRefresh:NO
+ [appCheck tokenForcingRefresh:NO // TODO Cannot use forceRefresh argument, if we send 'YES' in
+ // https://github.com/firebase/firebase-ios-sdk/issues/8544
completion:^(FIRAppCheckToken *_Nullable token, NSError *_Nullable error) {
if (error != nil) {
// Handle any errors if the token was not retrieved.
diff --git a/packages/app-check/lib/index.js b/packages/app-check/lib/index.js
index 9342304d5a..126888d2e8 100644
--- a/packages/app-check/lib/index.js
+++ b/packages/app-check/lib/index.js
@@ -40,16 +40,20 @@ class FirebaseAppCheckModule extends FirebaseModule {
}
getToken(forceRefresh) {
- return this.native.getToken(forceRefresh);
+ if (!forceRefresh) {
+ return this.native.getToken(false);
+ } else {
+ return this.native.getToken(true);
+ }
}
onTokenChanged() {
// iOS does not provide any native listening feature
if (isIOS) {
- return;
+ return () => {};
}
// TODO unimplemented on Android
- return;
+ return () => {};
}
}
@@ -63,7 +67,7 @@ export default createModuleNamespace({
version,
namespace,
nativeModuleName,
- nativeEvents: false, // TODO verify if this is interesting - token refresh listener perhaps?
+ nativeEvents: false, // TODO implement ['appcheck-token-changed'],
hasMultiAppSupport: true,
hasCustomUrlOrRegionSupport: false,
ModuleClass: FirebaseAppCheckModule,