From 71dac3af4b151ad6ad36afae98c9d9f50d1065ac Mon Sep 17 00:00:00 2001 From: Adrien Thiery Date: Tue, 10 Dec 2019 13:58:30 -0500 Subject: [PATCH 1/2] Renewed plugin for compatibility with react-native-firebase@v6 --- .editorconfig | 21 + README.md | 78 +++- package.json | 5 +- plugin.js | 642 +++++++++++++++++++++---------- templates/FirebaseExample.js.ejs | 10 - templates/Podfile | 14 - test/add.js | 22 +- test/remove.js | 16 +- 8 files changed, 553 insertions(+), 255 deletions(-) create mode 100644 .editorconfig delete mode 100644 templates/FirebaseExample.js.ejs delete mode 100644 templates/Podfile diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b8d3690 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# http://editorconfig.org +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +max_line_length = 80 +trim_trailing_whitespace = true + +[*.md] +max_line_length = 0 +trim_trailing_whitespace = false + +[*.{yaml,yml,json}] +indent_size = 2 + +[COMMIT_EDITMSG] +max_line_length = 0 diff --git a/README.md b/README.md index 3f2a12e..e0a3ab6 100644 --- a/README.md +++ b/README.md @@ -2,24 +2,84 @@ #### THIS PLUGIN IS STILL IN VERY EARLY STAGE. USE AT OWN RISK. +This plugin adds [react-native-firebase](https://github.com/invertase/react-native-firebase) to your [Ignite](https://github.com/infinitered/ignite) React Native project and configures it so it works out of the box with Ignite projects. -This plugin adds [react-native-firebase](https://github.com/invertase/react-native-firebase) -to your [Ignite](https://github.com/infinitered/ignite) React Native project and -configures it so it works out of the box with Ignite projects. +## Compatibility + +This version supports [react-native-firebase](https://github.com/invertase/react-native-firebase) `v6` and therefore is only compatible with [react-native](https://facebook.github.io/react-native) 0.60.0+ ## Usage -First go through [initial setup](https://rnfirebase.io/docs/master/installation/initial-setup) and get the GoogleService-Info.plist and google-services.json files ready and in the correct places. After that run: -(if you don't have CocoaPods installed check [installation instructions for CocoaPods](https://guides.cocoapods.org/using/getting-started.html#getting-started)) +First get the credentials files from https://console.firebase.google.com/ as stated in: + + * Android: https://invertase.io/oss/react-native-firebase/quick-start/android-firebase-credentials + * iOS: https://invertase.io/oss/react-native-firebase/quick-start/ios-firebase-credentials\n + +And put them: +* `google-services.json` in `android/app/` +* `GoogleService-Info.plist` in `ios/YourApp/` + +❌ DO NOT modify the native files, this plugin will take care of it ⚠️ + +### Adding Firebase + +Then: + +```sh +ignite add firebase +``` + +You can also pass some information directly as CLI paramaters when adding the plugin: + +* `--config-files-setup` : Use if you already set the google-services.json and GoogleService-Info.plist in your project +* `--modules` : Firebase modules to install, to select in: + * `AdMob` + * `Analytics` + * `Authentication` + * `Cloud Firestore` + * `Cloud Functions` + * `Cloud Messaging` + * `Cloud Storage` + * `Crashlytics` + * `Dynamic Links` + * `In-app Messaging` + * `Instance ID` + * `ML Kit Natural Language` + * `ML Kit Vision` + * `Performance Monitoring` + * `Realtime Database` + * `Remote Config` +Examples: + +``` +ignite add firebase --modules=Analytics,"Cloud Functions" +ignite add firebase --modules=all +ignite add firebase --modules=Crashlytics --config-files-setup +``` + +You can get this information by using: + +```sh +ignite add firebase --help ``` -$ ignite add firebase -$ cd ios && pod install + +### Removing Firebase + +```sh +ignite remove firebase ``` -This adds `ignite-firebase`. +Same here, you can use CLI parameters to convey some information: + +* `--remove-config-files` : Use if you want to remove the google-services.json and GoogleService-Info.plist files +* `--modules` : Firebase modules to remove, see above for more examples -If you want to use FCM for push notifications please check [3.1 and 3.2](http://invertase.io/react-native-firebase/#/installation-ios?id=_31-set-up-certificates) +You can get this information by using: + +```sh +ignite remove firebase --help +``` ## Contributing diff --git a/package.json b/package.json index e1224af..70f7af2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "ignite-firebase", "description": "An Ignite plugin for react-native-firebase", - "version": "0.0.4", + "version": "1.0.0", "license": "MIT", "author": { "name": "Aleksi Pousar", @@ -27,7 +27,8 @@ "nyc": "^10.1.2", "sinon": "^1.17.7", "standard": "^8.6.0" - } + }, + "dependencies": {} } diff --git a/plugin.js b/plugin.js index 99b8b36..f8bb6ac 100644 --- a/plugin.js +++ b/plugin.js @@ -1,238 +1,468 @@ -const NPM_MODULE_NAME = 'react-native-firebase' -const EXAMPLE_FILE = 'FirebaseExample.js.ejs' -const APP_PATH = process.cwd() -const PROJECT_NAME = process.cwd().split('/').pop() +const NPM_MODULE_NAME = '@react-native-firebase/app' +const NPM_MODULE_VERSION = '~6.2.0' -const GRADLE_CONFIG_COMPILE = ` compile(project(':react-native-firebase')) { - transitive = false - } - compile "com.google.firebase:firebase-core:11.0.0" - compile "com.google.firebase:firebase-ads:11.0.0" - compile "com.google.firebase:firebase-analytics:11.0.0" - compile "com.google.firebase:firebase-auth:11.0.0" - compile "com.google.firebase:firebase-config:11.0.0" - compile "com.google.firebase:firebase-crash:11.0.0" - compile "com.google.firebase:firebase-database:11.0.0" - compile "com.google.firebase:firebase-messaging:11.0.0" - compile "com.google.firebase:firebase-perf:11.0.0" - compile "com.google.firebase:firebase-storage:11.0.0"` - -const ANDROID_IMPORTS = `import io.invertase.firebase.RNFirebasePackage; -import io.invertase.firebase.admob.RNFirebaseAdMobPackage; //Firebase AdMob -import io.invertase.firebase.analytics.RNFirebaseAnalyticsPackage; // Firebase Analytics -import io.invertase.firebase.auth.RNFirebaseAuthPackage; // Firebase Auth -import io.invertase.firebase.config.RNFirebaseRemoteConfigPackage; // Firebase Remote Config -import io.invertase.firebase.crash.RNFirebaseCrashPackage; // Firebase Crash Reporting -import io.invertase.firebase.database.RNFirebaseDatabasePackage; // Firebase Realtime Database -import io.invertase.firebase.messaging.RNFirebaseMessagingPackage; // Firebase Cloud Messaging -import io.invertase.firebase.perf.RNFirebasePerformancePackage; // Firebase Messaging -import io.invertase.firebase.storage.RNFirebaseStoragePackage; // Firebase Storage` - -const ANDROID_PACKAGES = ` new RNFirebasePackage(), - new RNFirebaseAdMobPackage(), - new RNFirebaseAnalyticsPackage(), - new RNFirebaseAuthPackage(), - new RNFirebaseRemoteConfigPackage(), - new RNFirebaseCrashPackage(), - new RNFirebaseDatabasePackage(), - new RNFirebaseMessagingPackage(), - new RNFirebasePerformancePackage(), - new RNFirebaseStoragePackage(),` - -const ANDROID_SETTINGS = `include ':react-native-firebase' -project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-firebase/android')` - -const ANDROID_PERMISSIONS = ` - - - - ` - -const OLD_ANDROID_PERMISSIONS = ` - - ` - -const ANDROID_MESSAGING_SERVICE = ` - - - - - - - - - ` - -const MESSAGING_FUNCTIONS_IOS = `-(void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { - [RNFirebaseMessaging didReceiveLocalNotification:notification]; -} +const IOS_INSERT_APPDELEGATE_1 = `@import Firebase;\n`; +const IOS_INSERT_APPDELEGATE_2 = ` [FIRApp configure];`; +const ANDROID_INSERT_BUILD_GRADLE = ` classpath("com.google.gms:google-services:4.2.0")`; +const ANDROID_GOOGLE_SERVICES_PLUGIN = `apply plugin: 'com.google.gms.google-services'\n`; -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo { - [RNFirebaseMessaging didReceiveRemoteNotification:userInfo]; -} +const ANDROID_PERF_BUILD_GRADLE = ` classpath("com.google.firebase:perf-plugin:1.3.1")`; +const ANDROID_PERF_PLUGIN = `apply plugin: 'com.google.firebase.firebase-perf'\n`; -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo -fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler{ - [RNFirebaseMessaging didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; -} +const ANDROID_CRASHLYTICS_MAVEN = ` maven {\n url("https://maven.fabric.io/public")\n }` +const ANDROID_CRASHLYTICS_FABRIC_GRADLE = ` classpath("io.fabric.tools:gradle:1.28.1")` +const ANDROID_CRASHLYTICS_FABRIC_PLUGIN = `apply plugin: "io.fabric"` +const ANDROID_CRASHLYTICS_NDK = `\ncrashlytics {\n enableNdk true\n}` + +const UUID1 = `9D418FEC239FF80B00B0C90E`; +const UUID2 = `9D418FEB239FF80A00B0C90E`; +// Before /* End PBXBuildFile section */ +const IOS_GOOGLE_SERCICE_FILE_1 = ` ${UUID1} /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = ${UUID2} /* GoogleService-Info.plist */; };` +// Before /* End PBXFileReference section */ +const IOS_GOOGLE_SERCICE_FILE_2 = ` ${UUID2} /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };`; +// Before /* main.jsbundle */, +const IOS_GOOGLE_SERCICE_FILE_3 = ` ${UUID2} /* GoogleService-Info.plist */,`; +// After /* Images.xcassets in Resources */ +const IOS_GOOGLE_SERCICE_FILE_4 = ` ${UUID1} /* GoogleService-Info.plist in Resources */,` +const UUID3 = `9D418FED239FFABA00B0C90E`; +// After /* Bundle React Native code and images */, +const IOS_EXTRA_SCRIPT_REF = ` ${UUID3} /* ShellScript */,`; +// Before /* [CP] Check Pods Manifest.lock */ = { +const IOS_EXTRA_SCRIPT = ` + ${UUID3} /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\\"$\{PODS_ROOT\}/Fabric/run\\""; + }; ` -const add = async function (context) { - // Learn more about context: https://infinitered.github.io/gluegun/#/context-api.md - const { ignite, filesystem } = context +const createConfirmationMessage = (slug) => `You're ready to go! Check out https://invertase.io/oss/react-native-firebase/v6/${slug}/quick-start#module-usage to see how to use it!`; +const getModuleName = (slug) => `@react-native-firebase/${slug}`; + +const MODULE_OPTIONS = [ + { + name: 'AdMob', + module: getModuleName('admob'), + warning: 'IMPORTANT: Ensure you update the "Contains ads" settings in the Google Play Store (via Pricing & Distribution tab).', + confirmationMessage: createConfirmationMessage('admob'), + }, + { + name: 'Analytics', + module: getModuleName('analytics'), + confirmationMessage: createConfirmationMessage('analytics'), + }, + { + name: 'Authentication', + module: getModuleName('auth'), + confirmationMessage: createConfirmationMessage('auth'), + }, + { + name: 'Cloud Firestore', + module: getModuleName('firestore'), + confirmationMessage: createConfirmationMessage('firestore'), + dependencies: ['auth'], + }, + { + name: 'Cloud Functions', + module: getModuleName('functions'), + confirmationMessage: createConfirmationMessage('functions'), + }, + { + name: 'Cloud Messaging', + module: getModuleName('messaging'), + confirmationMessage: createConfirmationMessage('messaging'), + }, + { + name: 'Cloud Storage', + module: getModuleName('storage'), + confirmationMessage: createConfirmationMessage('storage'), + }, + { + name: 'Crashlytics', + module: getModuleName('crashlytics'), + confirmationMessage: createConfirmationMessage('crashlytics'), + extraAddSteps: async (APP_PATH, { ignite, prompt, print, parameters }) => { + const packageJSON = require(`${APP_PATH}/package.json`); + const PROJECT_NAME = packageJSON.name; + // iOS Setup + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { + insert: IOS_EXTRA_SCRIPT_REF, + after: `\\/\\* Bundle React Native code and images \\*\\/,` + }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { + insert: IOS_EXTRA_SCRIPT, + before: `\\/\\* \\[CP\\] Check Pods Manifest.lock \\*\\/ = {` + }); - // install a npm module - await ignite.addModule(NPM_MODULE_NAME, { link: false }) + // Android Setup + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + insert: ANDROID_CRASHLYTICS_MAVEN, + after: `jcenter()` + }); + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + insert: ANDROID_CRASHLYTICS_FABRIC_GRADLE, + after: `dependencies {` + }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { + insert: ANDROID_CRASHLYTICS_FABRIC_PLUGIN, + after: `apply plugin: "com.android.application"` + }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { + insert: ANDROID_CRASHLYTICS_NDK, + after: `apply plugin: "io.fabric"` + }); + }, + extraRemoveSteps: async (APP_PATH, { ignite, prompt, print }) => { + const packageJSON = require(`${APP_PATH}/package.json`); + const PROJECT_NAME = packageJSON.name; + // iOS Setup + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_EXTRA_SCRIPT_REF }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_EXTRA_SCRIPT }); - await ignite.addPluginComponentExample(EXAMPLE_FILE, { title: 'Firebase Example' }) + // Android Setup + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { delete: ANDROID_CRASHLYTICS_MAVEN }); + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { delete: ANDROID_CRASHLYTICS_FABRIC_GRADLE }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { delete: ANDROID_CRASHLYTICS_FABRIC_PLUGIN }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { delete: ANDROID_CRASHLYTICS_NDK }); + }, + }, + { + name: 'Dynamic Links', + module: getModuleName('dynamic-links'), + confirmationMessage: createConfirmationMessage('dynamic-links'), + }, + { + name: 'In-app Messaging', + module: getModuleName('in-app-messaging'), + confirmationMessage: createConfirmationMessage('in-app-messaging'), + }, + { + name: 'Instance ID', + module: getModuleName('iid'), + confirmationMessage: createConfirmationMessage('iid'), + }, + { + name: 'ML Kit Natural Language', + module: getModuleName('ml-natural-language'), + confirmationMessage: createConfirmationMessage('ml-natural-language'), + }, + { + name: 'ML Kit Vision', + module: getModuleName('ml-vision'), + confirmationMessage: createConfirmationMessage('ml-vision'), + }, + { + name: 'Performance Monitoring', + module: getModuleName('perf'), + confirmationMessage: createConfirmationMessage('perf'), + extraAddSteps: async (APP_PATH, { ignite, patching }) => { + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + insert: ANDROID_PERF_BUILD_GRADLE, + after: `dependencies {` + }); + patching.append(`${APP_PATH}/android/app/build.gradle`, ANDROID_PERF_PLUGIN); + }, + extraRemoveSteps: async (APP_PATH, { ignite, patching }) => { + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { delete: ANDROID_PERF_BUILD_GRADLE }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { delete: ANDROID_PERF_PLUGIN }); + }, + }, + { + name: 'Realtime Database', + module: getModuleName('database'), + confirmationMessage: createConfirmationMessage('database'), + }, + { + name: 'Remote Config', + module: getModuleName('remote-config'), + confirmationMessage: createConfirmationMessage('remote-config'), + }, +] - // Copy Podfile to correct place - if (!filesystem.exists(`${APP_PATH}/ios/Podfile`)) { - filesystem.copy(`${__dirname}/templates/Podfile`, `${APP_PATH}/ios/Podfile`) +const add = async function (toolbox) { + // Learn more about toolbox: https://infinitered.github.io/gluegun/#/toolbox-api.md + const { ignite, system, filesystem, print, patching, parameters } = toolbox + + const PLUGIN_PATH = __dirname; + const APP_PATH = process.cwd(); + const packageJSON = require(`${APP_PATH}/package.json`); + const PROJECT_NAME = packageJSON.name; + + if (parameters.options.help) { + print.info(` + Adding this plugin will help you install and configure Firebase for your React Native project. + + If you need to remove interactivity, you can specify most of the options as command-line parameters: + + --config-files-setup : Use if you already set the google-services.json and GoogleService-Info.plist + + --modules : Firebase modules to install, to select in: ${MODULE_OPTIONS.map((item) => item.name).join(', ')} + + ex: --modules=Analytics,"Cloud Functions" ("all" is also a valid value for --modules) + `) + process.exit(); } - // Patch AppDelegate.m + if (packageJSON.dependencies['react-native'] < '0.60.0') { + print.error('Sorry, this package supports only react-native@0.60.0+ right now'); + process.exit(); + } + + let isReady = parameters.options.configFilesSetup || await toolbox.prompt.confirm('Did you setup your project on the Firebase console and got the google services configuration files?'); + + while (!isReady) { + print.warning('Please follow the steps to get the credentials files from https://console.firebase.google.com/ as stated in:\n * Android: https://invertase.io/oss/react-native-firebase/quick-start/android-firebase-credentials\n * iOS: https://invertase.io/oss/react-native-firebase/quick-start/ios-firebase-credentials\n'); + + const result = await system.run(`cd ${APP_PATH}/android && ./gradlew signingReport | grep "> Task :app:signingReport" -A 45 | grep "Variant: debugAndroidTest$" -A 8 | grep "SHA1:"`, { trimmed: true }); + + const splitResult = result ? result.split(': ') : []; + if (splitResult.length > 1 && splitResult[1]) { + print.warning(`(optional) Your android Debug Signing certificate SHA1 is ${splitResult[1]}`); + } + + print.warning('❌ DO NOT modify the native files, this plugin will take care of it ⚠️'); + // print.warning('✅ DO drag and drop the GoogleService-Info.plist file into your .xcworkspace in XCode ⚠️'); + + isReady = await toolbox.prompt.confirm(`Got the google services configuration files set in ios/${packageJSON.name}/ and android/app/ ?`); + } + + await ignite.addModule(NPM_MODULE_NAME, { link: false, version: NPM_MODULE_VERSION }) + + const spinner = print.spin('Patching iOS files'); + // Patch AppDelegate.m for base config ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { - insert: `#import \n#import "RNFirebaseMessaging.h"`, - after: `#import ` - }) + insert: IOS_INSERT_APPDELEGATE_1, + before: `@implementation AppDelegate` + }); ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { - insert: `[FIRApp configure];\n[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];`, + insert: IOS_INSERT_APPDELEGATE_2, before: `return YES;` - }) - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { - insert: `${MESSAGING_FUNCTIONS_IOS}`, - before: `@end` - }) - // Patch AppDelegate.h - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.h`, { - insert: `@import UserNotifications;`, - after: `#import ` - }) - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.h`, { - insert: `@interface AppDelegate : UIResponder `, - replace: `@interface AppDelegate : UIResponder ` - }) + }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { + insert: IOS_GOOGLE_SERCICE_FILE_1, + before: 'End PBXBuildFile section' + }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { + insert: IOS_GOOGLE_SERCICE_FILE_2, + before: 'End PBXFileReference section' + }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { + insert: IOS_GOOGLE_SERCICE_FILE_3, + after: 'main.jsbundle \\*\\/,' + }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { + insert: IOS_GOOGLE_SERCICE_FILE_4, + before: 'Images.xcassets in Resources \\*\\/,' + }); + spinner.succeed('Patched iOS files'); + + spinner.text = 'Updating pods (this will probably take a while)'; + spinner.start(); + await system.spawn('pod install', { cwd: `${APP_PATH}/ios` }); + spinner.succeed('Updated pods'); + + spinner.text = 'Patching Android files'; + spinner.start(); // Patch android/build.gradle ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { - insert: `classpath 'com.google.gms:google-services:3.0.0'`, - after: `classpath 'com.android.tools.build:gradle:2.2.3'` - }) - // Patch android/app/build.gradle - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { - insert: `apply plugin: 'com.google.gms.google-services'\n`, - before: `// Run this once to be able to run the application with BUCK` - }) - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { - insert: `${GRADLE_CONFIG_COMPILE}`, + insert: ANDROID_INSERT_BUILD_GRADLE, after: `dependencies {` }) - // Patch MainApplivation.java - ignite.patchInFile(`${APP_PATH}/android/app/src/main/java/com/${PROJECT_NAME}/MainApplication.java`, { - insert: `${ANDROID_IMPORTS}`, - after: `import com.facebook.react.ReactApplication;` - }) - ignite.patchInFile(`${APP_PATH}/android/app/src/main/java/com/${PROJECT_NAME}/MainApplication.java`, { - insert: `${ANDROID_PACKAGES}`, - after: `new MainReactPackage()` - }) - // Patch android/app/src/main/AndroidManifest.xml - ignite.patchInFile(`${APP_PATH}/android/app/src/main/AndroidManifest.xml`, { - insert: `${ANDROID_PERMISSIONS}`, - replace: `${OLD_ANDROID_PERMISSIONS}` - }) - ignite.patchInFile(`${APP_PATH}/android/app/src/main/AndroidManifest.xml`, { - insert: ` android:launchMode="singleTop"`, - before: `android:windowSoftInputMode="adjustResize"` - }) - ignite.patchInFile(`${APP_PATH}/android/app/src/main/AndroidManifest.xml`, { - insert: `${ANDROID_MESSAGING_SERVICE}`, - before: `` - }) + // Patch android/app/build.gradle + patching.append(`${APP_PATH}/android/app/build.gradle`, ANDROID_GOOGLE_SERVICES_PLUGIN); + spinner.succeed('Patched Android files'); + + let modulesToInstall; + + if (!parameters.options.modules) { + const { submodules } = await toolbox.prompt.ask({ + type: 'multiselect', + name: 'submodules', + message: 'Which firebase services do you need?', + choices: MODULE_OPTIONS, + }); + + modulesToInstall = submodules; + } else if (parameters.options.modules === 'all') { + modulesToInstall = MODULE_OPTIONS.map((item) => item.name); + } else { + modulesToInstall = parameters.options.modules.split(',').map((item) => item.trim()); + } + + for (let index = 0; index < modulesToInstall.length; index++) { + const moduleName = modulesToInstall[index]; + const moduleOptions = MODULE_OPTIONS.find((item) => item.name === moduleName); + + print.warning(`Installing module ${moduleName}`); + + await ignite.addModule(moduleOptions.module, { link: false, version: NPM_MODULE_VERSION }); + + if (moduleOptions.warning) { + print.warning(moduleOptions.warning); + } + + if (moduleOptions.extraAddSteps) { + await moduleOptions.extraAddSteps(APP_PATH, toolbox); + } + + if (moduleOptions.confirmationMessage) { + print.success(moduleOptions.confirmationMessage); + } + } + + if (modulesToInstall.length > 0) { + await system.spawn('pod install', { cwd: `${APP_PATH}/ios` }); + } + + print.success('You are all set!'); } /** * Remove yourself from the project. */ -const remove = async function (context) { - // Learn more about context: https://infinitered.github.io/gluegun/#/context-api.md - const { ignite, filesystem } = context +const remove = async function (toolbox) { + // Learn more about toolbox: https://infinitered.github.io/gluegun/#/toolbox-api.md + const { ignite, system, filesystem, print, patching, parameters } = toolbox + + const PLUGIN_PATH = __dirname; + const APP_PATH = process.cwd(); + const packageJSON = require(`${APP_PATH}/package.json`); + const PROJECT_NAME = packageJSON.name; + + if (parameters.options.help) { + print.info(` + If you need to remove interactivity, you can specify most of the options as command-line parameters: + + --remove-config-files : Use if you want to remove the google-services.json and GoogleService-Info.plist files + + --modules : Firebase modules to remove, to select in: ${MODULE_OPTIONS.map((item) => item.name).join(', ')} - // remove the npm module and unlink it - await ignite.removeModule(NPM_MODULE_NAME, { unlink: false }) + ex: --modules=Analytics,"Cloud Functions" ("all" is also a valid value for --modules) + `) + process.exit(); + } - await ignite.removePluginComponentExample(EXAMPLE_FILE) + let allOrSelected; + if (!parameters.options.modules) { + const { choice } = await toolbox.prompt.ask({ + type: 'select', + name: 'choice', + message: 'Do you want to remove the whole library, or just a part?', + choices: [ + { name: 'EVERYTHING' }, + { name: 'ONLY SOME MODULES' }, + ], + }); - // remove Podfile - if (filesystem.exists(`${APP_PATH}/ios/Podfile`)) { - filesystem.remove(`${APP_PATH}/ios/Podfile`) + allOrSelected = choice; } - // Patch AppDelegate.m - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { - delete: `#import \n#import "RNFirebaseMessaging.h"` - }) - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { - delete: `[FIRApp configure];\n[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];` - }) - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { - delete: `${MESSAGING_FUNCTIONS_IOS}` - }) - // Patch AppDelegate.h - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.h`, { - delete: `@import UserNotifications;` - }) - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.h`, { - insert: `@interface AppDelegate : UIResponder `, - replace: `@interface AppDelegate : UIResponder ` - }) - // Patch android/build.gradle - ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { - delete: `classpath 'com.google.gms:google-services:3.0.0'` - }) - // Patch android/app/build.gradle - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { - delete: `apply plugin: 'com.google.gms.google-services'\n` - }) - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { - delete: `${GRADLE_CONFIG_COMPILE}` - }) - // Patch MainApplivation.java - ignite.patchInFile(`${APP_PATH}/android/app/src/main/java/com/${PROJECT_NAME}/MainApplication.java`, { - delete: `${ANDROID_IMPORTS}` - }) - ignite.patchInFile(`${APP_PATH}/android/app/src/main/java/com/${PROJECT_NAME}/MainApplication.java`, { - delete: `${ANDROID_PACKAGES}` - }) - // Patch android/settings.gradle - ignite.patchInFile(`${APP_PATH}/android/settings.gradle`, { - delete: `${ANDROID_SETTINGS}` - }) - // Patch android/app/src/main/AndroidManifest.xml - ignite.patchInFile(`${APP_PATH}/android/app/src/main/AndroidManifest.xml`, { - insert: `${OLD_ANDROID_PERMISSIONS}`, - replace: `${ANDROID_PERMISSIONS}` - }) - ignite.patchInFile(`${APP_PATH}/android/app/src/main/AndroidManifest.xml`, { - delete: ` android:launchMode="singleTop"` - }) - ignite.patchInFile(`${APP_PATH}/android/app/src/main/AndroidManifest.xml`, { - delete: `${ANDROID_MESSAGING_SERVICE}` - }) + let submodulesToRemove = []; + + if (allOrSelected === 'EVERYTHING' || parameters.options.modules === 'all') { + const removeConfigFiles = parameters.options.removeConfigFiles !== undefined + ? parameters.options.removeConfigFiles + : await toolbox.prompt.confirm(`Do you want us to remove the google services configuration files set in ios/${packageJSON.name}/ and android/app/ ?`); + + if (removeConfigFiles) { + filesystem.delete(`${APP_PATH}/android/app/google-services.json`); + filesystem.delete(`${APP_PATH}/ios/${PROJECT_NAME}/GoogleService-Info.plist`); + + // Remove reference from XCode proj + if (parameters.options.removeConfigFiles !== undefined) { + print.warning(`You still need to remove the GoogleService-Info.plist from your iOS project by opening ios/${PROJECT_NAME}.xcworkspace and delete it from the tree left.`); + } else { + let isIOSGoogleServiceFileRemoved = false; + while (!isIOSGoogleServiceFileRemoved) { + isIOSGoogleServiceFileRemoved = await toolbox.prompt.confirm(`You need to remove the GoogleService-Info.plist from your iOS project by opening ios/${PROJECT_NAME}.xcworkspace and delete it from the tree left. Once that's done, continue?`); + } + } + } + + await ignite.removeModule(NPM_MODULE_NAME, { unlink: false }) + + const spinner = print.spin('Unpatching iOS files'); + // Patch AppDelegate.m for base config + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { delete: IOS_INSERT_APPDELEGATE_1 }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { delete: IOS_INSERT_APPDELEGATE_2 }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_GOOGLE_SERCICE_FILE_1 }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_GOOGLE_SERCICE_FILE_2 }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_GOOGLE_SERCICE_FILE_3 }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_GOOGLE_SERCICE_FILE_4 }); + spinner.succeed('Unpatched iOS files'); + + spinner.text = 'Updating pods (this will probably take a while)'; + spinner.start(); + await system.spawn('pod install', { cwd: `${APP_PATH}/ios` }); + spinner.succeed('Updated pods'); + + spinner.text = 'Unpatching Android files'; + spinner.start(); + // Patch android/build.gradle + // WARNING: We might not want to remove the google-services there... A lot of other stuff are using that. + // ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { delete: ANDROID_INSERT_BUILD_GRADLE }) + // Patch android/app/build.gradle + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { delete: ANDROID_GOOGLE_SERVICES_PLUGIN }) + spinner.succeed('Unpatched Android files'); - // Example of removing App/Firebase folder - // const removeFirebase = await context.prompt.confirm( - // 'Do you want to remove App/Firebase?' - // ) - // if (removeFirebase) { filesystem.remove(`${APP_PATH}/App/Firebase`) } + submodulesToRemove = MODULE_OPTIONS.map((item) => item.name); + } else if (!parameters.options.modules) { + const { submodules } = await toolbox.prompt.ask({ + type: 'multiselect', + name: 'submodules', + message: 'Which firebase services do you need?', + choices: MODULE_OPTIONS, + }); + + submodulesToRemove = submodules; + } else { + submodulesToRemove = parameters.options.modules.split(',').map((item) => item.trim()); + } + + print.warning(submodulesToRemove) + + for (let index = 0; index < submodulesToRemove.length; index++) { + const moduleName = submodulesToRemove[index]; + const moduleOptions = MODULE_OPTIONS.find((item) => item.name === moduleName); + + print.warning(`Removing module ${moduleName}`); + + try { + await ignite.removeModule(moduleOptions.module, { unlink: false }); + + if (moduleOptions.warning) { + print.warning(moduleOptions.warning); + } + + if (moduleOptions.extraRemoveSteps) { + await moduleOptions.extraRemoveSteps(APP_PATH, toolbox); + } + + if (moduleOptions.confirmationMessage) { + print.success(`${moduleName} has been removed successfully`); + } + } catch (e) { + print.warning(`Could not remove ${moduleName}: ${e.message}`) + } + } + + if (submodulesToRemove.length > 0) { + await system.spawn('pod install', { cwd: `${APP_PATH}/ios` }); + } - // Example of unpatching a file - // ignite.patchInFile(`${APP_PATH}/App/Config/AppConfig.js`, { - // delete: `import '../Firebase/Firebase'\n` - // ) + print.success('Farewell, my friend!'); } // Required in all Ignite plugins diff --git a/templates/FirebaseExample.js.ejs b/templates/FirebaseExample.js.ejs deleted file mode 100644 index 1281162..0000000 --- a/templates/FirebaseExample.js.ejs +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react' -import { View, Text } from 'react-native' -import ExamplesRegistry from '../../../App/Services/ExamplesRegistry' - -// Example -ExamplesRegistry.addPluginExample('Firebase', () => - - {/* Add your component or plugin example here */} - -) diff --git a/templates/Podfile b/templates/Podfile deleted file mode 100644 index 6b8bc08..0000000 --- a/templates/Podfile +++ /dev/null @@ -1,14 +0,0 @@ -# Required by RNFirebase -pod 'Firebase/Core' -pod 'RNFirebase', :path => '../node_modules/react-native-firebase' - -# [OPTIONAL PODS] - comment out pods for firebase products you won't be using. -pod 'Firebase/AdMob' -pod 'Firebase/Analytics' -pod 'Firebase/Auth' -pod 'Firebase/Crash' -pod 'Firebase/Database' -pod 'Firebase/DynamicLinks' -pod 'Firebase/Messaging' -pod 'Firebase/RemoteConfig' -pod 'Firebase/Storage' \ No newline at end of file diff --git a/test/add.js b/test/add.js index 778bf00..11c3aea 100644 --- a/test/add.js +++ b/test/add.js @@ -2,22 +2,26 @@ const test = require('ava') const sinon = require('sinon') const plugin = require('../plugin') -test('adds the proper npm module and component example', async t => { +test('adds react-native-firebase', async t => { // spy on few things so we know they're called const addModule = sinon.spy() - const addPluginComponentExample = sinon.spy() + const ask = (question) => ({ [question.name]: [] }) + const confirm = sinon.spy() + const info = sinon.spy() + const warning = sinon.spy() + const success = sinon.spy() + const run = sinon.spy() // mock a context const context = { - ignite: { addModule, addPluginComponentExample } + ignite: { addModule }, + parameters: { options: {} }, + prompt: { ask, confirm }, + print: { info, warning, success }, + system: { run }, } await plugin.add(context) - t.true(addModule.calledWith('react-native-firebase', { link: true })) - t.true( - addPluginComponentExample.calledWith('FirebaseExample.js', { - title: 'Firebase Example' - }) - ) + t.true(addModule.calledWith('react-native-firebase', { link: false, version: '~6.2.0' })) }) diff --git a/test/remove.js b/test/remove.js index 937c784..378ad1f 100644 --- a/test/remove.js +++ b/test/remove.js @@ -2,16 +2,22 @@ const test = require('ava') const sinon = require('sinon') const plugin = require('../plugin') -test('removes Firebase', async t => { +test('removes react-native-firebase', async t => { const removeModule = sinon.spy() - const removePluginComponentExample = sinon.spy() + const ask = (question) => ({ [question.name]: [] }) + const confirm = sinon.spy() + const info = sinon.spy() + const warning = sinon.spy() + const success = sinon.spy() const context = { - ignite: { removeModule, removePluginComponentExample } + ignite: { removeModule }, + parameters: { options: {} }, + prompt: { ask, confirm }, + print: { info, warning, success }, } await plugin.remove(context) - t.true(removeModule.calledWith('react-native-firebase', { unlink: true })) - t.true(removePluginComponentExample.calledWith('FirebaseExample.js')) + t.true(removeModule.calledWith('react-native-firebase', { unlink: false })) }) From caac75dbbef9cde3b17a9db6e273a7dbe4af76b5 Mon Sep 17 00:00:00 2001 From: Adrien Thiery Date: Tue, 10 Dec 2019 14:00:46 -0500 Subject: [PATCH 2/2] Formatted plugin.js --- plugin.js | 880 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 494 insertions(+), 386 deletions(-) diff --git a/plugin.js b/plugin.js index f8bb6ac..b146128 100644 --- a/plugin.js +++ b/plugin.js @@ -1,5 +1,5 @@ -const NPM_MODULE_NAME = '@react-native-firebase/app' -const NPM_MODULE_VERSION = '~6.2.0' +const NPM_MODULE_NAME = "@react-native-firebase/app"; +const NPM_MODULE_VERSION = "~6.2.0"; const IOS_INSERT_APPDELEGATE_1 = `@import Firebase;\n`; const IOS_INSERT_APPDELEGATE_2 = ` [FIRApp configure];`; @@ -9,21 +9,21 @@ const ANDROID_GOOGLE_SERVICES_PLUGIN = `apply plugin: 'com.google.gms.google-ser const ANDROID_PERF_BUILD_GRADLE = ` classpath("com.google.firebase:perf-plugin:1.3.1")`; const ANDROID_PERF_PLUGIN = `apply plugin: 'com.google.firebase.firebase-perf'\n`; -const ANDROID_CRASHLYTICS_MAVEN = ` maven {\n url("https://maven.fabric.io/public")\n }` -const ANDROID_CRASHLYTICS_FABRIC_GRADLE = ` classpath("io.fabric.tools:gradle:1.28.1")` -const ANDROID_CRASHLYTICS_FABRIC_PLUGIN = `apply plugin: "io.fabric"` -const ANDROID_CRASHLYTICS_NDK = `\ncrashlytics {\n enableNdk true\n}` +const ANDROID_CRASHLYTICS_MAVEN = ` maven {\n url("https://maven.fabric.io/public")\n }`; +const ANDROID_CRASHLYTICS_FABRIC_GRADLE = ` classpath("io.fabric.tools:gradle:1.28.1")`; +const ANDROID_CRASHLYTICS_FABRIC_PLUGIN = `apply plugin: "io.fabric"`; +const ANDROID_CRASHLYTICS_NDK = `\ncrashlytics {\n enableNdk true\n}`; const UUID1 = `9D418FEC239FF80B00B0C90E`; const UUID2 = `9D418FEB239FF80A00B0C90E`; // Before /* End PBXBuildFile section */ -const IOS_GOOGLE_SERCICE_FILE_1 = ` ${UUID1} /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = ${UUID2} /* GoogleService-Info.plist */; };` +const IOS_GOOGLE_SERCICE_FILE_1 = ` ${UUID1} /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = ${UUID2} /* GoogleService-Info.plist */; };`; // Before /* End PBXFileReference section */ const IOS_GOOGLE_SERCICE_FILE_2 = ` ${UUID2} /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };`; // Before /* main.jsbundle */, const IOS_GOOGLE_SERCICE_FILE_3 = ` ${UUID2} /* GoogleService-Info.plist */,`; // After /* Images.xcassets in Resources */ -const IOS_GOOGLE_SERCICE_FILE_4 = ` ${UUID1} /* GoogleService-Info.plist in Resources */,` +const IOS_GOOGLE_SERCICE_FILE_4 = ` ${UUID1} /* GoogleService-Info.plist in Resources */,`; const UUID3 = `9D418FED239FFABA00B0C90E`; // After /* Bundle React Native code and images */, const IOS_EXTRA_SCRIPT_REF = ` ${UUID3} /* ShellScript */,`; @@ -46,425 +46,533 @@ const IOS_EXTRA_SCRIPT = ` shellPath = /bin/sh; shellScript = "\\"$\{PODS_ROOT\}/Fabric/run\\""; }; -` +`; -const createConfirmationMessage = (slug) => `You're ready to go! Check out https://invertase.io/oss/react-native-firebase/v6/${slug}/quick-start#module-usage to see how to use it!`; -const getModuleName = (slug) => `@react-native-firebase/${slug}`; +const createConfirmationMessage = slug => + `You're ready to go! Check out https://invertase.io/oss/react-native-firebase/v6/${slug}/quick-start#module-usage to see how to use it!`; +const getModuleName = slug => `@react-native-firebase/${slug}`; const MODULE_OPTIONS = [ - { - name: 'AdMob', - module: getModuleName('admob'), - warning: 'IMPORTANT: Ensure you update the "Contains ads" settings in the Google Play Store (via Pricing & Distribution tab).', - confirmationMessage: createConfirmationMessage('admob'), - }, - { - name: 'Analytics', - module: getModuleName('analytics'), - confirmationMessage: createConfirmationMessage('analytics'), - }, - { - name: 'Authentication', - module: getModuleName('auth'), - confirmationMessage: createConfirmationMessage('auth'), - }, - { - name: 'Cloud Firestore', - module: getModuleName('firestore'), - confirmationMessage: createConfirmationMessage('firestore'), - dependencies: ['auth'], - }, - { - name: 'Cloud Functions', - module: getModuleName('functions'), - confirmationMessage: createConfirmationMessage('functions'), - }, - { - name: 'Cloud Messaging', - module: getModuleName('messaging'), - confirmationMessage: createConfirmationMessage('messaging'), - }, - { - name: 'Cloud Storage', - module: getModuleName('storage'), - confirmationMessage: createConfirmationMessage('storage'), - }, - { - name: 'Crashlytics', - module: getModuleName('crashlytics'), - confirmationMessage: createConfirmationMessage('crashlytics'), - extraAddSteps: async (APP_PATH, { ignite, prompt, print, parameters }) => { - const packageJSON = require(`${APP_PATH}/package.json`); - const PROJECT_NAME = packageJSON.name; - // iOS Setup - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { - insert: IOS_EXTRA_SCRIPT_REF, - after: `\\/\\* Bundle React Native code and images \\*\\/,` - }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { - insert: IOS_EXTRA_SCRIPT, - before: `\\/\\* \\[CP\\] Check Pods Manifest.lock \\*\\/ = {` - }); - - // Android Setup - ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { - insert: ANDROID_CRASHLYTICS_MAVEN, - after: `jcenter()` - }); - ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { - insert: ANDROID_CRASHLYTICS_FABRIC_GRADLE, - after: `dependencies {` - }); - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { - insert: ANDROID_CRASHLYTICS_FABRIC_PLUGIN, - after: `apply plugin: "com.android.application"` - }); - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { - insert: ANDROID_CRASHLYTICS_NDK, - after: `apply plugin: "io.fabric"` - }); + { + name: "AdMob", + module: getModuleName("admob"), + warning: + 'IMPORTANT: Ensure you update the "Contains ads" settings in the Google Play Store (via Pricing & Distribution tab).', + confirmationMessage: createConfirmationMessage("admob") }, - extraRemoveSteps: async (APP_PATH, { ignite, prompt, print }) => { - const packageJSON = require(`${APP_PATH}/package.json`); - const PROJECT_NAME = packageJSON.name; - // iOS Setup - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_EXTRA_SCRIPT_REF }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_EXTRA_SCRIPT }); - - // Android Setup - ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { delete: ANDROID_CRASHLYTICS_MAVEN }); - ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { delete: ANDROID_CRASHLYTICS_FABRIC_GRADLE }); - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { delete: ANDROID_CRASHLYTICS_FABRIC_PLUGIN }); - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { delete: ANDROID_CRASHLYTICS_NDK }); + { + name: "Analytics", + module: getModuleName("analytics"), + confirmationMessage: createConfirmationMessage("analytics") }, - }, - { - name: 'Dynamic Links', - module: getModuleName('dynamic-links'), - confirmationMessage: createConfirmationMessage('dynamic-links'), - }, - { - name: 'In-app Messaging', - module: getModuleName('in-app-messaging'), - confirmationMessage: createConfirmationMessage('in-app-messaging'), - }, - { - name: 'Instance ID', - module: getModuleName('iid'), - confirmationMessage: createConfirmationMessage('iid'), - }, - { - name: 'ML Kit Natural Language', - module: getModuleName('ml-natural-language'), - confirmationMessage: createConfirmationMessage('ml-natural-language'), - }, - { - name: 'ML Kit Vision', - module: getModuleName('ml-vision'), - confirmationMessage: createConfirmationMessage('ml-vision'), - }, - { - name: 'Performance Monitoring', - module: getModuleName('perf'), - confirmationMessage: createConfirmationMessage('perf'), - extraAddSteps: async (APP_PATH, { ignite, patching }) => { - ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { - insert: ANDROID_PERF_BUILD_GRADLE, - after: `dependencies {` - }); - patching.append(`${APP_PATH}/android/app/build.gradle`, ANDROID_PERF_PLUGIN); + { + name: "Authentication", + module: getModuleName("auth"), + confirmationMessage: createConfirmationMessage("auth") + }, + { + name: "Cloud Firestore", + module: getModuleName("firestore"), + confirmationMessage: createConfirmationMessage("firestore"), + dependencies: ["auth"] + }, + { + name: "Cloud Functions", + module: getModuleName("functions"), + confirmationMessage: createConfirmationMessage("functions") + }, + { + name: "Cloud Messaging", + module: getModuleName("messaging"), + confirmationMessage: createConfirmationMessage("messaging") + }, + { + name: "Cloud Storage", + module: getModuleName("storage"), + confirmationMessage: createConfirmationMessage("storage") + }, + { + name: "Crashlytics", + module: getModuleName("crashlytics"), + confirmationMessage: createConfirmationMessage("crashlytics"), + extraAddSteps: async ( + APP_PATH, + { ignite, prompt, print, parameters } + ) => { + const packageJSON = require(`${APP_PATH}/package.json`); + const PROJECT_NAME = packageJSON.name; + // iOS Setup + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { + insert: IOS_EXTRA_SCRIPT_REF, + after: `\\/\\* Bundle React Native code and images \\*\\/,` + } + ); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { + insert: IOS_EXTRA_SCRIPT, + before: `\\/\\* \\[CP\\] Check Pods Manifest.lock \\*\\/ = {` + } + ); + + // Android Setup + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + insert: ANDROID_CRASHLYTICS_MAVEN, + after: `jcenter()` + }); + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + insert: ANDROID_CRASHLYTICS_FABRIC_GRADLE, + after: `dependencies {` + }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { + insert: ANDROID_CRASHLYTICS_FABRIC_PLUGIN, + after: `apply plugin: "com.android.application"` + }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { + insert: ANDROID_CRASHLYTICS_NDK, + after: `apply plugin: "io.fabric"` + }); + }, + extraRemoveSteps: async (APP_PATH, { ignite, prompt, print }) => { + const packageJSON = require(`${APP_PATH}/package.json`); + const PROJECT_NAME = packageJSON.name; + // iOS Setup + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { delete: IOS_EXTRA_SCRIPT_REF } + ); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { delete: IOS_EXTRA_SCRIPT } + ); + + // Android Setup + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + delete: ANDROID_CRASHLYTICS_MAVEN + }); + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + delete: ANDROID_CRASHLYTICS_FABRIC_GRADLE + }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { + delete: ANDROID_CRASHLYTICS_FABRIC_PLUGIN + }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { + delete: ANDROID_CRASHLYTICS_NDK + }); + } + }, + { + name: "Dynamic Links", + module: getModuleName("dynamic-links"), + confirmationMessage: createConfirmationMessage("dynamic-links") + }, + { + name: "In-app Messaging", + module: getModuleName("in-app-messaging"), + confirmationMessage: createConfirmationMessage("in-app-messaging") }, - extraRemoveSteps: async (APP_PATH, { ignite, patching }) => { - ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { delete: ANDROID_PERF_BUILD_GRADLE }); - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { delete: ANDROID_PERF_PLUGIN }); + { + name: "Instance ID", + module: getModuleName("iid"), + confirmationMessage: createConfirmationMessage("iid") }, - }, - { - name: 'Realtime Database', - module: getModuleName('database'), - confirmationMessage: createConfirmationMessage('database'), - }, - { - name: 'Remote Config', - module: getModuleName('remote-config'), - confirmationMessage: createConfirmationMessage('remote-config'), - }, -] - -const add = async function (toolbox) { - // Learn more about toolbox: https://infinitered.github.io/gluegun/#/toolbox-api.md - const { ignite, system, filesystem, print, patching, parameters } = toolbox - - const PLUGIN_PATH = __dirname; - const APP_PATH = process.cwd(); - const packageJSON = require(`${APP_PATH}/package.json`); - const PROJECT_NAME = packageJSON.name; - - if (parameters.options.help) { - print.info(` + { + name: "ML Kit Natural Language", + module: getModuleName("ml-natural-language"), + confirmationMessage: createConfirmationMessage("ml-natural-language") + }, + { + name: "ML Kit Vision", + module: getModuleName("ml-vision"), + confirmationMessage: createConfirmationMessage("ml-vision") + }, + { + name: "Performance Monitoring", + module: getModuleName("perf"), + confirmationMessage: createConfirmationMessage("perf"), + extraAddSteps: async (APP_PATH, { ignite, patching }) => { + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + insert: ANDROID_PERF_BUILD_GRADLE, + after: `dependencies {` + }); + patching.append( + `${APP_PATH}/android/app/build.gradle`, + ANDROID_PERF_PLUGIN + ); + }, + extraRemoveSteps: async (APP_PATH, { ignite, patching }) => { + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + delete: ANDROID_PERF_BUILD_GRADLE + }); + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { + delete: ANDROID_PERF_PLUGIN + }); + } + }, + { + name: "Realtime Database", + module: getModuleName("database"), + confirmationMessage: createConfirmationMessage("database") + }, + { + name: "Remote Config", + module: getModuleName("remote-config"), + confirmationMessage: createConfirmationMessage("remote-config") + } +]; + +const add = async function(toolbox) { + // Learn more about toolbox: https://infinitered.github.io/gluegun/#/toolbox-api.md + const { ignite, system, filesystem, print, patching, parameters } = toolbox; + + const PLUGIN_PATH = __dirname; + const APP_PATH = process.cwd(); + const packageJSON = require(`${APP_PATH}/package.json`); + const PROJECT_NAME = packageJSON.name; + + if (parameters.options.help) { + print.info(` Adding this plugin will help you install and configure Firebase for your React Native project. If you need to remove interactivity, you can specify most of the options as command-line parameters: - + --config-files-setup : Use if you already set the google-services.json and GoogleService-Info.plist - - --modules : Firebase modules to install, to select in: ${MODULE_OPTIONS.map((item) => item.name).join(', ')} + + --modules : Firebase modules to install, to select in: ${MODULE_OPTIONS.map( + item => item.name + ).join(", ")} ex: --modules=Analytics,"Cloud Functions" ("all" is also a valid value for --modules) - `) - process.exit(); - } - - if (packageJSON.dependencies['react-native'] < '0.60.0') { - print.error('Sorry, this package supports only react-native@0.60.0+ right now'); - process.exit(); - } - - let isReady = parameters.options.configFilesSetup || await toolbox.prompt.confirm('Did you setup your project on the Firebase console and got the google services configuration files?'); - - while (!isReady) { - print.warning('Please follow the steps to get the credentials files from https://console.firebase.google.com/ as stated in:\n * Android: https://invertase.io/oss/react-native-firebase/quick-start/android-firebase-credentials\n * iOS: https://invertase.io/oss/react-native-firebase/quick-start/ios-firebase-credentials\n'); - - const result = await system.run(`cd ${APP_PATH}/android && ./gradlew signingReport | grep "> Task :app:signingReport" -A 45 | grep "Variant: debugAndroidTest$" -A 8 | grep "SHA1:"`, { trimmed: true }); - - const splitResult = result ? result.split(': ') : []; - if (splitResult.length > 1 && splitResult[1]) { - print.warning(`(optional) Your android Debug Signing certificate SHA1 is ${splitResult[1]}`); + `); + process.exit(); } - print.warning('❌ DO NOT modify the native files, this plugin will take care of it ⚠️'); - // print.warning('✅ DO drag and drop the GoogleService-Info.plist file into your .xcworkspace in XCode ⚠️'); - - isReady = await toolbox.prompt.confirm(`Got the google services configuration files set in ios/${packageJSON.name}/ and android/app/ ?`); - } - - await ignite.addModule(NPM_MODULE_NAME, { link: false, version: NPM_MODULE_VERSION }) - - const spinner = print.spin('Patching iOS files'); - // Patch AppDelegate.m for base config - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { - insert: IOS_INSERT_APPDELEGATE_1, - before: `@implementation AppDelegate` - }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { - insert: IOS_INSERT_APPDELEGATE_2, - before: `return YES;` - }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { - insert: IOS_GOOGLE_SERCICE_FILE_1, - before: 'End PBXBuildFile section' - }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { - insert: IOS_GOOGLE_SERCICE_FILE_2, - before: 'End PBXFileReference section' - }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { - insert: IOS_GOOGLE_SERCICE_FILE_3, - after: 'main.jsbundle \\*\\/,' - }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { - insert: IOS_GOOGLE_SERCICE_FILE_4, - before: 'Images.xcassets in Resources \\*\\/,' - }); - spinner.succeed('Patched iOS files'); - - spinner.text = 'Updating pods (this will probably take a while)'; - spinner.start(); - await system.spawn('pod install', { cwd: `${APP_PATH}/ios` }); - spinner.succeed('Updated pods'); - - spinner.text = 'Patching Android files'; - spinner.start(); - // Patch android/build.gradle - ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { - insert: ANDROID_INSERT_BUILD_GRADLE, - after: `dependencies {` - }) - // Patch android/app/build.gradle - patching.append(`${APP_PATH}/android/app/build.gradle`, ANDROID_GOOGLE_SERVICES_PLUGIN); - spinner.succeed('Patched Android files'); - - let modulesToInstall; - - if (!parameters.options.modules) { - const { submodules } = await toolbox.prompt.ask({ - type: 'multiselect', - name: 'submodules', - message: 'Which firebase services do you need?', - choices: MODULE_OPTIONS, - }); + if (packageJSON.dependencies["react-native"] < "0.60.0") { + print.error( + "Sorry, this package supports only react-native@0.60.0+ right now" + ); + process.exit(); + } - modulesToInstall = submodules; - } else if (parameters.options.modules === 'all') { - modulesToInstall = MODULE_OPTIONS.map((item) => item.name); - } else { - modulesToInstall = parameters.options.modules.split(',').map((item) => item.trim()); - } + let isReady = + parameters.options.configFilesSetup || + (await toolbox.prompt.confirm( + "Did you setup your project on the Firebase console and got the google services configuration files?" + )); + + while (!isReady) { + print.warning( + "Please follow the steps to get the credentials files from https://console.firebase.google.com/ as stated in:\n * Android: https://invertase.io/oss/react-native-firebase/quick-start/android-firebase-credentials\n * iOS: https://invertase.io/oss/react-native-firebase/quick-start/ios-firebase-credentials\n" + ); + + const result = await system.run( + `cd ${APP_PATH}/android && ./gradlew signingReport | grep "> Task :app:signingReport" -A 45 | grep "Variant: debugAndroidTest$" -A 8 | grep "SHA1:"`, + { trimmed: true } + ); + + const splitResult = result ? result.split(": ") : []; + if (splitResult.length > 1 && splitResult[1]) { + print.warning( + `(optional) Your android Debug Signing certificate SHA1 is ${splitResult[1]}` + ); + } - for (let index = 0; index < modulesToInstall.length; index++) { - const moduleName = modulesToInstall[index]; - const moduleOptions = MODULE_OPTIONS.find((item) => item.name === moduleName); + print.warning( + "❌ DO NOT modify the native files, this plugin will take care of it ⚠️" + ); + // print.warning('✅ DO drag and drop the GoogleService-Info.plist file into your .xcworkspace in XCode ⚠️'); - print.warning(`Installing module ${moduleName}`); + isReady = await toolbox.prompt.confirm( + `Got the google services configuration files set in ios/${packageJSON.name}/ and android/app/ ?` + ); + } - await ignite.addModule(moduleOptions.module, { link: false, version: NPM_MODULE_VERSION }); + await ignite.addModule(NPM_MODULE_NAME, { + link: false, + version: NPM_MODULE_VERSION + }); - if (moduleOptions.warning) { - print.warning(moduleOptions.warning); - } - - if (moduleOptions.extraAddSteps) { - await moduleOptions.extraAddSteps(APP_PATH, toolbox); + const spinner = print.spin("Patching iOS files"); + // Patch AppDelegate.m for base config + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { + insert: IOS_INSERT_APPDELEGATE_1, + before: `@implementation AppDelegate` + }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { + insert: IOS_INSERT_APPDELEGATE_2, + before: `return YES;` + }); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { + insert: IOS_GOOGLE_SERCICE_FILE_1, + before: "End PBXBuildFile section" + } + ); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { + insert: IOS_GOOGLE_SERCICE_FILE_2, + before: "End PBXFileReference section" + } + ); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { + insert: IOS_GOOGLE_SERCICE_FILE_3, + after: "main.jsbundle \\*\\/," + } + ); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { + insert: IOS_GOOGLE_SERCICE_FILE_4, + before: "Images.xcassets in Resources \\*\\/," + } + ); + spinner.succeed("Patched iOS files"); + + spinner.text = "Updating pods (this will probably take a while)"; + spinner.start(); + await system.spawn("pod install", { cwd: `${APP_PATH}/ios` }); + spinner.succeed("Updated pods"); + + spinner.text = "Patching Android files"; + spinner.start(); + // Patch android/build.gradle + ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { + insert: ANDROID_INSERT_BUILD_GRADLE, + after: `dependencies {` + }); + // Patch android/app/build.gradle + patching.append( + `${APP_PATH}/android/app/build.gradle`, + ANDROID_GOOGLE_SERVICES_PLUGIN + ); + spinner.succeed("Patched Android files"); + + let modulesToInstall; + + if (!parameters.options.modules) { + const { submodules } = await toolbox.prompt.ask({ + type: "multiselect", + name: "submodules", + message: "Which firebase services do you need?", + choices: MODULE_OPTIONS + }); + + modulesToInstall = submodules; + } else if (parameters.options.modules === "all") { + modulesToInstall = MODULE_OPTIONS.map(item => item.name); + } else { + modulesToInstall = parameters.options.modules + .split(",") + .map(item => item.trim()); } - - if (moduleOptions.confirmationMessage) { - print.success(moduleOptions.confirmationMessage); + + for (let index = 0; index < modulesToInstall.length; index++) { + const moduleName = modulesToInstall[index]; + const moduleOptions = MODULE_OPTIONS.find( + item => item.name === moduleName + ); + + print.warning(`Installing module ${moduleName}`); + + await ignite.addModule(moduleOptions.module, { + link: false, + version: NPM_MODULE_VERSION + }); + + if (moduleOptions.warning) { + print.warning(moduleOptions.warning); + } + + if (moduleOptions.extraAddSteps) { + await moduleOptions.extraAddSteps(APP_PATH, toolbox); + } + + if (moduleOptions.confirmationMessage) { + print.success(moduleOptions.confirmationMessage); + } } - } - if (modulesToInstall.length > 0) { - await system.spawn('pod install', { cwd: `${APP_PATH}/ios` }); - } + if (modulesToInstall.length > 0) { + await system.spawn("pod install", { cwd: `${APP_PATH}/ios` }); + } - print.success('You are all set!'); -} + print.success("You are all set!"); +}; /** * Remove yourself from the project. */ -const remove = async function (toolbox) { - // Learn more about toolbox: https://infinitered.github.io/gluegun/#/toolbox-api.md - const { ignite, system, filesystem, print, patching, parameters } = toolbox - - const PLUGIN_PATH = __dirname; - const APP_PATH = process.cwd(); - const packageJSON = require(`${APP_PATH}/package.json`); - const PROJECT_NAME = packageJSON.name; - - if (parameters.options.help) { - print.info(` +const remove = async function(toolbox) { + // Learn more about toolbox: https://infinitered.github.io/gluegun/#/toolbox-api.md + const { ignite, system, filesystem, print, patching, parameters } = toolbox; + + const PLUGIN_PATH = __dirname; + const APP_PATH = process.cwd(); + const packageJSON = require(`${APP_PATH}/package.json`); + const PROJECT_NAME = packageJSON.name; + + if (parameters.options.help) { + print.info(` If you need to remove interactivity, you can specify most of the options as command-line parameters: - + --remove-config-files : Use if you want to remove the google-services.json and GoogleService-Info.plist files - - --modules : Firebase modules to remove, to select in: ${MODULE_OPTIONS.map((item) => item.name).join(', ')} + + --modules : Firebase modules to remove, to select in: ${MODULE_OPTIONS.map( + item => item.name + ).join(", ")} ex: --modules=Analytics,"Cloud Functions" ("all" is also a valid value for --modules) - `) - process.exit(); - } - - let allOrSelected; - if (!parameters.options.modules) { - const { choice } = await toolbox.prompt.ask({ - type: 'select', - name: 'choice', - message: 'Do you want to remove the whole library, or just a part?', - choices: [ - { name: 'EVERYTHING' }, - { name: 'ONLY SOME MODULES' }, - ], - }); + `); + process.exit(); + } + + let allOrSelected; + if (!parameters.options.modules) { + const { choice } = await toolbox.prompt.ask({ + type: "select", + name: "choice", + message: "Do you want to remove the whole library, or just a part?", + choices: [{ name: "EVERYTHING" }, { name: "ONLY SOME MODULES" }] + }); + + allOrSelected = choice; + } - allOrSelected = choice; - } - - let submodulesToRemove = []; - - if (allOrSelected === 'EVERYTHING' || parameters.options.modules === 'all') { - const removeConfigFiles = parameters.options.removeConfigFiles !== undefined - ? parameters.options.removeConfigFiles - : await toolbox.prompt.confirm(`Do you want us to remove the google services configuration files set in ios/${packageJSON.name}/ and android/app/ ?`); - - if (removeConfigFiles) { - filesystem.delete(`${APP_PATH}/android/app/google-services.json`); - filesystem.delete(`${APP_PATH}/ios/${PROJECT_NAME}/GoogleService-Info.plist`); - - // Remove reference from XCode proj - if (parameters.options.removeConfigFiles !== undefined) { - print.warning(`You still need to remove the GoogleService-Info.plist from your iOS project by opening ios/${PROJECT_NAME}.xcworkspace and delete it from the tree left.`); - } else { - let isIOSGoogleServiceFileRemoved = false; - while (!isIOSGoogleServiceFileRemoved) { - isIOSGoogleServiceFileRemoved = await toolbox.prompt.confirm(`You need to remove the GoogleService-Info.plist from your iOS project by opening ios/${PROJECT_NAME}.xcworkspace and delete it from the tree left. Once that's done, continue?`); + let submodulesToRemove = []; + + if ( + allOrSelected === "EVERYTHING" || + parameters.options.modules === "all" + ) { + const removeConfigFiles = + parameters.options.removeConfigFiles !== undefined + ? parameters.options.removeConfigFiles + : await toolbox.prompt.confirm( + `Do you want us to remove the google services configuration files set in ios/${packageJSON.name}/ and android/app/ ?` + ); + + if (removeConfigFiles) { + filesystem.delete(`${APP_PATH}/android/app/google-services.json`); + filesystem.delete( + `${APP_PATH}/ios/${PROJECT_NAME}/GoogleService-Info.plist` + ); + + // Remove reference from XCode proj + if (parameters.options.removeConfigFiles !== undefined) { + print.warning( + `You still need to remove the GoogleService-Info.plist from your iOS project by opening ios/${PROJECT_NAME}.xcworkspace and delete it from the tree left.` + ); + } else { + let isIOSGoogleServiceFileRemoved = false; + while (!isIOSGoogleServiceFileRemoved) { + isIOSGoogleServiceFileRemoved = await toolbox.prompt.confirm( + `You need to remove the GoogleService-Info.plist from your iOS project by opening ios/${PROJECT_NAME}.xcworkspace and delete it from the tree left. Once that's done, continue?` + ); + } + } } - } + + await ignite.removeModule(NPM_MODULE_NAME, { unlink: false }); + + const spinner = print.spin("Unpatching iOS files"); + // Patch AppDelegate.m for base config + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { + delete: IOS_INSERT_APPDELEGATE_1 + }); + ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { + delete: IOS_INSERT_APPDELEGATE_2 + }); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { delete: IOS_GOOGLE_SERCICE_FILE_1 } + ); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { delete: IOS_GOOGLE_SERCICE_FILE_2 } + ); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { delete: IOS_GOOGLE_SERCICE_FILE_3 } + ); + ignite.patchInFile( + `${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, + { delete: IOS_GOOGLE_SERCICE_FILE_4 } + ); + spinner.succeed("Unpatched iOS files"); + + spinner.text = "Updating pods (this will probably take a while)"; + spinner.start(); + await system.spawn("pod install", { cwd: `${APP_PATH}/ios` }); + spinner.succeed("Updated pods"); + + spinner.text = "Unpatching Android files"; + spinner.start(); + // Patch android/build.gradle + // WARNING: We might not want to remove the google-services there... A lot of other stuff are using that. + // ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { delete: ANDROID_INSERT_BUILD_GRADLE }) + // Patch android/app/build.gradle + ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { + delete: ANDROID_GOOGLE_SERVICES_PLUGIN + }); + spinner.succeed("Unpatched Android files"); + + submodulesToRemove = MODULE_OPTIONS.map(item => item.name); + } else if (!parameters.options.modules) { + const { submodules } = await toolbox.prompt.ask({ + type: "multiselect", + name: "submodules", + message: "Which firebase services do you need?", + choices: MODULE_OPTIONS + }); + + submodulesToRemove = submodules; + } else { + submodulesToRemove = parameters.options.modules + .split(",") + .map(item => item.trim()); } - await ignite.removeModule(NPM_MODULE_NAME, { unlink: false }) + print.warning(submodulesToRemove); - const spinner = print.spin('Unpatching iOS files'); - // Patch AppDelegate.m for base config - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { delete: IOS_INSERT_APPDELEGATE_1 }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}/AppDelegate.m`, { delete: IOS_INSERT_APPDELEGATE_2 }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_GOOGLE_SERCICE_FILE_1 }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_GOOGLE_SERCICE_FILE_2 }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_GOOGLE_SERCICE_FILE_3 }); - ignite.patchInFile(`${APP_PATH}/ios/${PROJECT_NAME}.xcodeproj/project.pbxproj`, { delete: IOS_GOOGLE_SERCICE_FILE_4 }); - spinner.succeed('Unpatched iOS files'); - - spinner.text = 'Updating pods (this will probably take a while)'; - spinner.start(); - await system.spawn('pod install', { cwd: `${APP_PATH}/ios` }); - spinner.succeed('Updated pods'); + for (let index = 0; index < submodulesToRemove.length; index++) { + const moduleName = submodulesToRemove[index]; + const moduleOptions = MODULE_OPTIONS.find( + item => item.name === moduleName + ); - spinner.text = 'Unpatching Android files'; - spinner.start(); - // Patch android/build.gradle - // WARNING: We might not want to remove the google-services there... A lot of other stuff are using that. - // ignite.patchInFile(`${APP_PATH}/android/build.gradle`, { delete: ANDROID_INSERT_BUILD_GRADLE }) - // Patch android/app/build.gradle - ignite.patchInFile(`${APP_PATH}/android/app/build.gradle`, { delete: ANDROID_GOOGLE_SERVICES_PLUGIN }) - spinner.succeed('Unpatched Android files'); - - submodulesToRemove = MODULE_OPTIONS.map((item) => item.name); - } else if (!parameters.options.modules) { - const { submodules } = await toolbox.prompt.ask({ - type: 'multiselect', - name: 'submodules', - message: 'Which firebase services do you need?', - choices: MODULE_OPTIONS, - }); + print.warning(`Removing module ${moduleName}`); + + try { + await ignite.removeModule(moduleOptions.module, { unlink: false }); + + if (moduleOptions.warning) { + print.warning(moduleOptions.warning); + } - submodulesToRemove = submodules; - } else { - submodulesToRemove = parameters.options.modules.split(',').map((item) => item.trim()); - } - - print.warning(submodulesToRemove) - - for (let index = 0; index < submodulesToRemove.length; index++) { - const moduleName = submodulesToRemove[index]; - const moduleOptions = MODULE_OPTIONS.find((item) => item.name === moduleName); - - print.warning(`Removing module ${moduleName}`); - - try { - await ignite.removeModule(moduleOptions.module, { unlink: false }); - - if (moduleOptions.warning) { - print.warning(moduleOptions.warning); - } - - if (moduleOptions.extraRemoveSteps) { - await moduleOptions.extraRemoveSteps(APP_PATH, toolbox); - } - - if (moduleOptions.confirmationMessage) { - print.success(`${moduleName} has been removed successfully`); - } - } catch (e) { - print.warning(`Could not remove ${moduleName}: ${e.message}`) + if (moduleOptions.extraRemoveSteps) { + await moduleOptions.extraRemoveSteps(APP_PATH, toolbox); + } + + if (moduleOptions.confirmationMessage) { + print.success(`${moduleName} has been removed successfully`); + } + } catch (e) { + print.warning(`Could not remove ${moduleName}: ${e.message}`); + } } - } - if (submodulesToRemove.length > 0) { - await system.spawn('pod install', { cwd: `${APP_PATH}/ios` }); - } + if (submodulesToRemove.length > 0) { + await system.spawn("pod install", { cwd: `${APP_PATH}/ios` }); + } - print.success('Farewell, my friend!'); -} + print.success("Farewell, my friend!"); +}; // Required in all Ignite plugins -module.exports = { add, remove } - +module.exports = { add, remove };