diff options
Diffstat (limited to 'StoneIsland/plugins/cordova-plugin-firebasex/scripts')
6 files changed, 552 insertions, 0 deletions
diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/after_prepare.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/after_prepare.js new file mode 100644 index 00000000..b3a7ab59 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/after_prepare.js @@ -0,0 +1,164 @@ +#!/usr/bin/env node + +'use strict'; + +/** + * This hook makes sure projects using [cordova-plugin-firebase](https://github.com/arnesson/cordova-plugin-firebase) + * will build properly and have the required key files copied to the proper destinations when the app is build on Ionic Cloud using the package command. + * Credits: https://github.com/arnesson. + */ +var fs = require('fs'); +var path = require("path"); +var Utilities = require("./lib/utilities"); + +var appName = Utilities.getAppName(); +var pluginVariables = {}; + +var IOS_DIR = 'platforms/ios'; +var ANDROID_DIR = 'platforms/android'; +var PLUGIN_ID = 'cordova-plugin-firebasex'; + +var PLATFORM = { + IOS: { + dest: IOS_DIR + '/' + appName + '/Resources/GoogleService-Info.plist', + src: [ + 'GoogleService-Info.plist', + IOS_DIR + '/www/GoogleService-Info.plist', + 'www/GoogleService-Info.plist' + ], + appPlist: IOS_DIR + '/' + appName + '/'+appName+'-Info.plist', + }, + ANDROID: { + dest: ANDROID_DIR + '/app/google-services.json', + src: [ + 'google-services.json', + ANDROID_DIR + '/assets/www/google-services.json', + 'www/google-services.json', + ANDROID_DIR + '/app/src/main/google-services.json' + ], + colorsXml:{ + src: './plugins/' + Utilities.getPluginId() +'/src/android/colors.xml', + target: ANDROID_DIR + '/app/src/main/res/values/colors.xml' + } + } +}; + + +var parsePluginVariables = function(){ + // Parse plugin.xml + var plugin = Utilities.parsePluginXml(); + var prefs = []; + if(plugin.plugin.preference){ + prefs = prefs.concat(plugin.plugin.preference); + } + plugin.plugin.platform.forEach(function(platform){ + if(platform.preference){ + prefs = prefs.concat(platform.preference); + } + }); + prefs.forEach(function(pref){ + pluginVariables[pref._attributes.name] = pref._attributes.default; + }); + + // Parse config.xml + var config = Utilities.parseConfigXml(); + (config.widget.plugin ? [].concat(config.widget.plugin) : []).forEach(function(plugin){ + (plugin.variable ? [].concat(plugin.variable) : []).forEach(function(variable){ + if((plugin._attributes.name === PLUGIN_ID || plugin._attributes.id === PLUGIN_ID) && variable._attributes.name && variable._attributes.value){ + pluginVariables[variable._attributes.name] = variable._attributes.value; + } + }); + }); + + // Parse package.json + var packageJSON = Utilities.parsePackageJson(); + if(packageJSON.cordova && packageJSON.cordova.plugins){ + for(const pluginId in packageJSON.cordova.plugins){ + if(pluginId === PLUGIN_ID){ + for(const varName in packageJSON.cordova.plugins[pluginId]){ + var varValue = packageJSON.cordova.plugins[pluginId][varName]; + pluginVariables[varName] = varValue; + } + } + } + } + + // set platform key path from plugin variable + if (pluginVariables.ANDROID_FIREBASE_CONFIG_FILEPATH) PLATFORM.ANDROID.src = [pluginVariables.ANDROID_FIREBASE_CONFIG_FILEPATH]; + if (pluginVariables.IOS_FIREBASE_CONFIG_FILEPATH) PLATFORM.IOS.src = [pluginVariables.IOS_FIREBASE_CONFIG_FILEPATH]; +}; + +module.exports = function (context) { + + //get platform from the context supplied by cordova + var platforms = context.opts.platforms; + parsePluginVariables(); + + // Copy key files to their platform specific folders + if (platforms.indexOf('android') !== -1 && Utilities.directoryExists(ANDROID_DIR)) { + Utilities.log('Preparing Firebase on Android'); + Utilities.copyKey(PLATFORM.ANDROID); + + if(!fs.existsSync(path.resolve(PLATFORM.ANDROID.colorsXml.target))){ + fs.copyFileSync(path.resolve(PLATFORM.ANDROID.colorsXml.src), path.resolve(PLATFORM.ANDROID.colorsXml.target)); + } + + const $colorsXml = Utilities.parseXmlFileToJson(PLATFORM.ANDROID.colorsXml.target, {compact: true}); + var accentColor = pluginVariables.ANDROID_ICON_ACCENT, + $resources = $colorsXml.resources, + existingAccent = false, + writeChanges = false; + + if($resources.color){ + var $colors = $resources.color.length ? $resources.color : [$resources.color]; + $colors.forEach(function($color){ + if($color._attributes.name === 'accent'){ + existingAccent = true; + if($color._text !== accentColor){ + $color._text = accentColor; + writeChanges = true; + } + } + }); + }else{ + $resources.color = {}; + } + + if(!existingAccent){ + var $accentColor = { + _attributes: { + name: 'accent' + }, + _text: accentColor + }; + if($resources.color && Object.keys($resources.color).length){ + if(typeof $resources.color.length === 'undefined'){ + $resources.color = [$resources.color]; + } + $resources.color.push($accentColor) + }else{ + $resources.color = $accentColor; + } + writeChanges = true; + } + + if(writeChanges){ + Utilities.writeJsonToXmlFile($colorsXml, PLATFORM.ANDROID.colorsXml.target); + Utilities.log('Updated colors.xml with accent color'); + } + } + + if (platforms.indexOf('ios') !== -1 && Utilities.directoryExists(IOS_DIR)){ + Utilities.log('Preparing Firebase on iOS'); + Utilities.copyKey(PLATFORM.IOS); + + var helper = require("./ios/helper"); + var xcodeProjectPath = helper.getXcodeProjectPath(); + helper.ensureRunpathSearchPath(context, xcodeProjectPath); + + if(pluginVariables['IOS_STRIP_DEBUG'] && pluginVariables['IOS_STRIP_DEBUG'] === 'true'){ + helper.stripDebugSymbols(); + } + helper.applyPluginVarsToPlists(PLATFORM.IOS.dest, PLATFORM.IOS.appPlist, pluginVariables); + } +}; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/after_plugin_install.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/after_plugin_install.js new file mode 100644 index 00000000..3384f75b --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/after_plugin_install.js @@ -0,0 +1,10 @@ +var helper = require("./helper"); + +module.exports = function(context) { + + // Add a build phase which runs a shell script that executes the Crashlytics + // run command line tool which uploads the debug symbols at build time. + var xcodeProjectPath = helper.getXcodeProjectPath(); + helper.removeShellScriptBuildPhase(context, xcodeProjectPath); + helper.addShellScriptBuildPhase(context, xcodeProjectPath); +}; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_install.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_install.js new file mode 100644 index 00000000..9b860005 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_install.js @@ -0,0 +1,23 @@ +var execSync = require('child_process').execSync; +var semver = require('semver'); + +var minCocoapodsVersion = "^1.9.1"; + +module.exports = function(context) { + checkCocoapodsVersion(); +}; + +function checkCocoapodsVersion(){ + var version; + try{ + version = execSync('pod --version', {encoding: 'utf8'}).match(/(\d+\.\d+\.\d+)/)[1]; + }catch(err){ + throw new Error("cocoapods not found - please install cocoapods >="+minCocoapodsVersion); + } + + if(!semver.valid(version)){ + throw new Error("cocoapods version is invalid - please reinstall cocoapods@"+minCocoapodsVersion + ": "+version); + }else if(!semver.satisfies(version, minCocoapodsVersion)){ + throw new Error("cocoapods version is out-of-date - please update to cocoapods@"+minCocoapodsVersion + " - current version: "+version); + } +}
\ No newline at end of file diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_uninstall.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_uninstall.js new file mode 100644 index 00000000..783512a6 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/before_plugin_uninstall.js @@ -0,0 +1,8 @@ +var helper = require("./helper"); + +module.exports = function(context) { + + // Remove the build script that was added when the plugin was installed. + var xcodeProjectPath = helper.getXcodeProjectPath(); + helper.removeShellScriptBuildPhase(context, xcodeProjectPath); +}; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/helper.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/helper.js new file mode 100644 index 00000000..be12ae06 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/ios/helper.js @@ -0,0 +1,238 @@ +var fs = require("fs"); +var path = require("path"); +var utilities = require("../lib/utilities"); +var xcode = require("xcode"); +var plist = require('plist'); + +/** + * This is used as the display text for the build phase block in XCode as well as the + * inline comments inside of the .pbxproj file for the build script phase block. + */ +var comment = "\"Crashlytics\""; + +module.exports = { + + /** + * Used to get the path to the XCode project's .pbxproj file. + */ + getXcodeProjectPath: function () { + var appName = utilities.getAppName(); + return path.join("platforms", "ios", appName + ".xcodeproj", "project.pbxproj"); + }, + + /** + * This helper is used to add a build phase to the XCode project which runs a shell + * script during the build process. The script executes Crashlytics run command line + * tool with the API and Secret keys. This tool is used to upload the debug symbols + * (dSYMs) so that Crashlytics can display stack trace information in it's web console. + */ + addShellScriptBuildPhase: function (context, xcodeProjectPath) { + + // Read and parse the XCode project (.pxbproj) from disk. + // File format information: http://www.monobjc.net/xcode-project-file-format.html + var xcodeProject = xcode.project(xcodeProjectPath); + xcodeProject.parseSync(); + + // Build the body of the script to be executed during the build phase. + var script = '"' + '\\"${PODS_ROOT}/FirebaseCrashlytics/run\\"' + '"'; + + // Generate a unique ID for our new build phase. + var id = xcodeProject.generateUuid(); + // Create the build phase. + xcodeProject.hash.project.objects.PBXShellScriptBuildPhase[id] = { + isa: "PBXShellScriptBuildPhase", + buildActionMask: 2147483647, + files: [], + inputPaths: ['"' + '$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)' + '"'], + name: comment, + outputPaths: [], + runOnlyForDeploymentPostprocessing: 0, + shellPath: "/bin/sh", + shellScript: script, + showEnvVarsInLog: 0 + }; + + // Add a comment to the block (viewable in the source of the pbxproj file). + xcodeProject.hash.project.objects.PBXShellScriptBuildPhase[id + "_comment"] = comment; + + // Add this new shell script build phase block to the targets. + for (var nativeTargetId in xcodeProject.hash.project.objects.PBXNativeTarget) { + + // Skip over the comment blocks. + if (nativeTargetId.indexOf("_comment") !== -1) { + continue; + } + + var nativeTarget = xcodeProject.hash.project.objects.PBXNativeTarget[nativeTargetId]; + + nativeTarget.buildPhases.push({ + value: id, + comment: comment + }); + } + + // Finally, write the .pbxproj back out to disk. + fs.writeFileSync(path.resolve(xcodeProjectPath), xcodeProject.writeSync()); + }, + + /** + * This helper is used to remove the build phase from the XCode project that was added + * by the addShellScriptBuildPhase() helper method. + */ + removeShellScriptBuildPhase: function (context, xcodeProjectPath) { + + // Read and parse the XCode project (.pxbproj) from disk. + // File format information: http://www.monobjc.net/xcode-project-file-format.html + var xcodeProject = xcode.project(xcodeProjectPath); + xcodeProject.parseSync(); + + // First, we want to delete the build phase block itself. + + var buildPhases = xcodeProject.hash.project.objects.PBXShellScriptBuildPhase; + + var commentTest = comment.replace(/"/g, ''); + for (var buildPhaseId in buildPhases) { + + var buildPhase = xcodeProject.hash.project.objects.PBXShellScriptBuildPhase[buildPhaseId]; + var shouldDelete = false; + + if (buildPhaseId.indexOf("_comment") === -1) { + // Dealing with a build phase block. + + // If the name of this block matches ours, then we want to delete it. + shouldDelete = buildPhase.name && buildPhase.name.indexOf(commentTest) !== -1; + } else { + // Dealing with a comment block. + + // If this is a comment block that matches ours, then we want to delete it. + shouldDelete = buildPhase === commentTest; + } + + if (shouldDelete) { + delete buildPhases[buildPhaseId]; + } + } + + // Second, we want to delete the native target reference to the block. + + var nativeTargets = xcodeProject.hash.project.objects.PBXNativeTarget; + + for (var nativeTargetId in nativeTargets) { + + // Skip over the comment blocks. + if (nativeTargetId.indexOf("_comment") !== -1) { + continue; + } + + var nativeTarget = nativeTargets[nativeTargetId]; + + // We remove the reference to the block by filtering out the the ones that match. + nativeTarget.buildPhases = nativeTarget.buildPhases.filter(function (buildPhase) { + return buildPhase.comment !== commentTest; + }); + } + + // Finally, write the .pbxproj back out to disk. + fs.writeFileSync(path.resolve(xcodeProjectPath), xcodeProject.writeSync()); + }, + + ensureRunpathSearchPath: function(context, xcodeProjectPath){ + + function addRunpathSearchBuildProperty(proj, build) { + let LD_RUNPATH_SEARCH_PATHS = proj.getBuildProperty("LD_RUNPATH_SEARCH_PATHS", build); + + if (!Array.isArray(LD_RUNPATH_SEARCH_PATHS)) { + LD_RUNPATH_SEARCH_PATHS = [LD_RUNPATH_SEARCH_PATHS]; + } + + LD_RUNPATH_SEARCH_PATHS.forEach(LD_RUNPATH_SEARCH_PATH => { + if (!LD_RUNPATH_SEARCH_PATH) { + proj.addBuildProperty("LD_RUNPATH_SEARCH_PATHS", "\"$(inherited) @executable_path/Frameworks\"", build); + } + if (LD_RUNPATH_SEARCH_PATH.indexOf("@executable_path/Frameworks") == -1) { + var newValue = LD_RUNPATH_SEARCH_PATH.substr(0, LD_RUNPATH_SEARCH_PATH.length - 1); + newValue += ' @executable_path/Frameworks\"'; + proj.updateBuildProperty("LD_RUNPATH_SEARCH_PATHS", newValue, build); + } + if (LD_RUNPATH_SEARCH_PATH.indexOf("$(inherited)") == -1) { + var newValue = LD_RUNPATH_SEARCH_PATH.substr(0, LD_RUNPATH_SEARCH_PATH.length - 1); + newValue += ' $(inherited)\"'; + proj.updateBuildProperty("LD_RUNPATH_SEARCH_PATHS", newValue, build); + } + }); + } + + // Read and parse the XCode project (.pxbproj) from disk. + // File format information: http://www.monobjc.net/xcode-project-file-format.html + var xcodeProject = xcode.project(xcodeProjectPath); + xcodeProject.parseSync(); + + // Add search paths build property + addRunpathSearchBuildProperty(xcodeProject, "Debug"); + addRunpathSearchBuildProperty(xcodeProject, "Release"); + + // Finally, write the .pbxproj back out to disk. + fs.writeFileSync(path.resolve(xcodeProjectPath), xcodeProject.writeSync()); + }, + stripDebugSymbols: function(){ + var podFilePath = 'platforms/ios/Podfile', + podFile = fs.readFileSync(path.resolve(podFilePath)).toString(); + if(!podFile.match('DEBUG_INFORMATION_FORMAT')){ + podFile += "\npost_install do |installer|\n" + + " installer.pods_project.targets.each do |target|\n" + + " target.build_configurations.each do |config|\n" + + " config.build_settings['DEBUG_INFORMATION_FORMAT'] = 'dwarf'\n" + + " end\n" + + " end\n" + + "end"; + fs.writeFileSync(path.resolve(podFilePath), podFile); + console.log('cordova-plugin-firebasex: Applied IOS_STRIP_DEBUG to Podfile'); + } + }, + applyPluginVarsToPlists: function(googlePlistPath, appPlistPath, pluginVariables){ + var googlePlist = plist.parse(fs.readFileSync(path.resolve(googlePlistPath), 'utf8')), + appPlist = plist.parse(fs.readFileSync(path.resolve(appPlistPath), 'utf8')), + googlePlistModified = false, + appPlistModified = false; + + if(typeof pluginVariables['FIREBASE_ANALYTICS_COLLECTION_ENABLED'] !== 'undefined'){ + googlePlist["FIREBASE_ANALYTICS_COLLECTION_ENABLED"] = (pluginVariables['FIREBASE_ANALYTICS_COLLECTION_ENABLED'] !== "false" ? "true" : "false") ; + googlePlistModified = true; + } + if(typeof pluginVariables['FIREBASE_PERFORMANCE_COLLECTION_ENABLED'] !== 'undefined'){ + googlePlist["FIREBASE_PERFORMANCE_COLLECTION_ENABLED"] = (pluginVariables['FIREBASE_PERFORMANCE_COLLECTION_ENABLED'] !== "false" ? "true" : "false") ; + googlePlistModified = true; + } + if(typeof pluginVariables['FIREBASE_CRASHLYTICS_COLLECTION_ENABLED'] !== 'undefined'){ + googlePlist["FirebaseCrashlyticsCollectionEnabled"] = (pluginVariables['FIREBASE_CRASHLYTICS_COLLECTION_ENABLED'] !== "false" ? "true" : "false") ; + googlePlistModified = true; + } + if(typeof pluginVariables['IOS_SHOULD_ESTABLISH_DIRECT_CHANNEL'] !== 'undefined'){ + appPlist["shouldEstablishDirectChannel"] = (pluginVariables['IOS_SHOULD_ESTABLISH_DIRECT_CHANNEL'] === "true") ; + appPlistModified = true; + } + if(pluginVariables['SETUP_RECAPTCHA_VERIFICATION'] === 'true'){ + var reversedClientId = googlePlist['REVERSED_CLIENT_ID']; + + if(!appPlist['CFBundleURLTypes']) appPlist['CFBundleURLTypes'] = []; + var entry, i; + for(i=0; i<appPlist['CFBundleURLTypes'].length; i++){ + if(typeof appPlist['CFBundleURLTypes'][i] === 'object' && appPlist['CFBundleURLTypes'][i]['CFBundleURLSchemes']){ + entry = appPlist['CFBundleURLTypes'][i]; + break; + } + } + if(!entry) entry = {}; + if(!entry['CFBundleTypeRole']) entry['CFBundleTypeRole'] = 'Editor'; + if(!entry['CFBundleURLSchemes']) entry['CFBundleURLSchemes'] = []; + if(entry['CFBundleURLSchemes'].indexOf(reversedClientId) === -1){ + entry['CFBundleURLSchemes'].push(reversedClientId) + } + appPlist['CFBundleURLTypes'][i] = entry; + appPlistModified = true; + } + + if(googlePlistModified) fs.writeFileSync(path.resolve(googlePlistPath), plist.build(googlePlist)); + if(appPlistModified) fs.writeFileSync(path.resolve(appPlistPath), plist.build(appPlist)); + } +}; diff --git a/StoneIsland/plugins/cordova-plugin-firebasex/scripts/lib/utilities.js b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/lib/utilities.js new file mode 100644 index 00000000..837ff459 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-firebasex/scripts/lib/utilities.js @@ -0,0 +1,109 @@ +/** + * Utilities and shared functionality for the build hooks. + */ +var fs = require('fs'); +var path = require("path"); +var parser = require('xml-js'); + +var _configXml, _pluginXml; + +var Utilities = {}; + +fs.ensureDirSync = function(dir){ + if(!fs.existsSync(dir)){ + dir.split(path.sep).reduce(function(currentPath, folder){ + currentPath += folder + path.sep; + if(!fs.existsSync(currentPath)){ + fs.mkdirSync(currentPath); + } + return currentPath; + }, ''); + } +}; + +Utilities.parsePackageJson = function(){ + return JSON.parse(fs.readFileSync(path.resolve('./package.json'))); +}; + +Utilities.parseConfigXml = function(){ + if(_configXml) return _configXml; + _configXml = Utilities.parseXmlFileToJson("config.xml"); + return _configXml; +}; + +Utilities.parsePluginXml = function(){ + if(_pluginXml) return _pluginXml; + _pluginXml = Utilities.parseXmlFileToJson("plugins/"+Utilities.getPluginId()+"/plugin.xml"); + return _pluginXml; +}; + +Utilities.parseXmlFileToJson = function(filepath, parseOpts){ + parseOpts = parseOpts || {compact: true}; + return JSON.parse(parser.xml2json(fs.readFileSync(path.resolve(filepath), 'utf-8'), parseOpts)); +}; + +Utilities.writeJsonToXmlFile = function(jsonObj, filepath, parseOpts){ + parseOpts = parseOpts || {compact: true, spaces: 4}; + var xmlStr = parser.json2xml(JSON.stringify(jsonObj), parseOpts); + fs.writeFileSync(path.resolve(filepath), xmlStr); +}; + +/** + * Used to get the name of the application as defined in the config.xml. + */ +Utilities.getAppName = function(){ + return Utilities.parseConfigXml().widget.name._text.toString().trim(); +}; + +/** + * The ID of the plugin; this should match the ID in plugin.xml. + */ +Utilities.getPluginId = function(){ + return "cordova-plugin-firebasex"; +}; + +Utilities.copyKey = function(platform){ + for(var i = 0; i < platform.src.length; i++){ + var file = platform.src[i]; + if(this.fileExists(file)){ + try{ + var contents = fs.readFileSync(path.resolve(file)).toString(); + + try{ + var destinationPath = platform.dest; + var folder = destinationPath.substring(0, destinationPath.lastIndexOf('/')); + fs.ensureDirSync(folder); + fs.writeFileSync(path.resolve(destinationPath), contents); + }catch(e){ + // skip + } + }catch(err){ + console.log(err); + } + + break; + } + } +}; + +Utilities.fileExists = function(filePath){ + try{ + return fs.statSync(path.resolve(filePath)).isFile(); + }catch(e){ + return false; + } +}; + +Utilities.directoryExists = function(dirPath){ + try{ + return fs.statSync(path.resolve(dirPath)).isDirectory(); + }catch(e){ + return false; + } +}; + +Utilities.log = function(msg){ + console.log(Utilities.getPluginId()+': '+msg); +}; + +module.exports = Utilities; |
