Skip to content

Commit

Permalink
fix($compile): update cordova hooks so that you don't need to build u…
Browse files Browse the repository at this point in the history
…sing Xcode as described by BranchMetrics#271

Cordova has introduced the ability for the user to define their entitlements files:

apache/cordova-ios@b5fb016

The provide the base files and you can overwrite for your project.  These files get created for the iOS build at:

<app name>/platforms/ios/<app name>/Entitlements-<release type>.plist

Currently the cordova-ionic-phonegap-branch-deep-linking hook code updates:

<app name>/platforms/ios/build/device/<app name>.app/<app name>.entitlements

But misses the new entitlement files that the user can provide.

If these files are updated by the branchio hook then one can have a reliable means for
using cordova in build systems to push out application updates to the user
without manual intervention of Xcode.
  • Loading branch information
Cliff Cyphers committed Feb 28, 2017
1 parent 7f01f61 commit 60d904d
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 26 deletions.
65 changes: 65 additions & 0 deletions hooks.es6/beforeCompileHook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict';

/**
Hook is executed at the end of the 'prepare' stage. Usually, when you call 'cordova build'.
It will inject required preferences in the platform-specific projects, based on <branch-config>
data you have specified in the projects config.xml file.
*/

var configParser = require('./lib/configXmlParser.js'),
androidManifestWriter = require('./lib/android/manifestWriter.js'),


// androidWebHook = require('./lib/android/webSiteHook.js'),
iosProjectEntitlements = require('./lib/ios/projectEntitlements.js'),
iosProjectPreferences = require('./lib/ios/xcodePreferences.js'),
IOS = 'ios';

module.exports = function (ctx) {
run(ctx);
};

/**
* Execute hook.
*
* @param {Object} cordovaContext - cordova context object
*/
function run(cordovaContext) {
var pluginPreferences = configParser.readPreferences(cordovaContext),
platformsList = cordovaContext.opts.platforms;

// if no preferences are found - exit
if (pluginPreferences == null) {
return;
}

// if no host is defined - exit
if (pluginPreferences.hosts == null || pluginPreferences.hosts.length == 0) {
console.warn('No host is specified in the config.xml. Universal Links plugin is not going to work.');
return;
}

platformsList.forEach(function (platform) {
if (platform === IOS) {
activateUniversalLinksInIos(cordovaContext, pluginPreferences);
}
});
}

/**
* Activate Universal Links for iOS application.
*
* @param {Object} cordovaContext - cordova context object
* @param {Object} pluginPreferences - plugin preferences from the config.xml file. Basically, content from <branch-config> tag.
*/
function activateUniversalLinksInIos(cordovaContext, pluginPreferences) {
// modify xcode project preferences
//iosProjectPreferences.enableAssociativeDomainsCapability(cordovaContext);

// generate entitlements file
var buildTypes = ['Debug', 'Release'];
for (var x = 0; x < buildTypes.length; x++) {
iosProjectEntitlements.generateAssociatedDomainsEntitlements(cordovaContext, pluginPreferences, buildTypes[x]);
}
}
41 changes: 28 additions & 13 deletions hooks.es6/lib/ios/projectEntitlements.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ Script only generates content. File it self is included in the xcode project in
*
* @param {Object} cordovaContext - cordova context object
* @param {Object} pluginPreferences - plugin preferences from config.xml; already parsed
* @param {String} buildType - optional value to control which entitlement file to update
*/
function generateEntitlements(cordovaContext, pluginPreferences) {
function generateEntitlements(cordovaContext, pluginPreferences, buildType) {
context = cordovaContext;

var currentEntitlements = getEntitlementsFileContent(),
var currentEntitlements = getEntitlementsFileContent(buildType),
newEntitlements = injectPreferences(currentEntitlements, pluginPreferences);

saveContentToEntitlementsFile(newEntitlements);
saveContentToEntitlementsFile(newEntitlements, buildType);
}

// endregion
Expand All @@ -47,8 +48,9 @@ Script only generates content. File it self is included in the xcode project in
* Save data to entitlements file.
*
* @param {Object} content - data to save; JSON object that will be transformed into xml
* @param {String} buildType - optional value to control which entitlement file to update
*/
function saveContentToEntitlementsFile(content) {
function saveContentToEntitlementsFile(content, buildType) {
var plistContent = plist.build(content),
filePath = pathToEntitlementsFile();

Expand All @@ -57,15 +59,23 @@ Script only generates content. File it self is included in the xcode project in

// save it's content
fs.writeFileSync(filePath, plistContent, 'utf8');

if(buildType) {
filePath = pathToEntitlementsFile(buildType);
mkpath.sync(path.dirname(filePath));
// save it's content
fs.writeFileSync(filePath, plistContent, 'utf8');
}

}

/**
* Read data from existing entitlements file. If none exist - default value is returned
*
* @param {String} buildType - optional value to control which entitlement file to update
* @return {String} entitlements file content
*/
function getEntitlementsFileContent() {
var pathToFile = pathToEntitlementsFile(),
function getEntitlementsFileContent(buildType) {
var pathToFile = pathToEntitlementsFile(buildType),
content;

try {
Expand Down Expand Up @@ -137,15 +147,20 @@ Script only generates content. File it self is included in the xcode project in

/**
* Path to entitlements file.
*
* @param {String} buildType - optional value to control which entitlement file to update
* @return {String} absolute path to entitlements file
*/
function pathToEntitlementsFile() {
if (entitlementsFilePath === undefined) {
entitlementsFilePath = path.join(getProjectRoot(), 'platforms', 'ios', getProjectName(), 'Resources', getProjectName() + '.entitlements');
function pathToEntitlementsFile(buildType) {
if (buildType) {
var validTypes = ['Debug', 'Release'];
if(validTypes.indexOf(buildType) === -1) {
throw Error('pathToEntitlementsFile invalid build type specified: ' + buildType)
}
return path.join(getProjectRoot(), 'platforms', 'ios', getProjectName(), 'Entitlements-' + buildType + '.plist');

} else {
return path.join(getProjectRoot(), 'platforms', 'ios', getProjectName(), 'Resources', getProjectName() + '.entitlements');
}

return entitlementsFilePath;
}

/**
Expand Down
65 changes: 65 additions & 0 deletions hooks/beforeCompileHook.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict';

/**
Hook is executed at the end of the 'prepare' stage. Usually, when you call 'cordova build'.
It will inject required preferences in the platform-specific projects, based on <branch-config>
data you have specified in the projects config.xml file.
*/

var configParser = require('./lib/configXmlParser.js'),
androidManifestWriter = require('./lib/android/manifestWriter.js'),


// androidWebHook = require('./lib/android/webSiteHook.js'),
iosProjectEntitlements = require('./lib/ios/projectEntitlements.js'),
iosProjectPreferences = require('./lib/ios/xcodePreferences.js'),
IOS = 'ios';

module.exports = function (ctx) {
run(ctx);
};

/**
* Execute hook.
*
* @param {Object} cordovaContext - cordova context object
*/
function run(cordovaContext) {
var pluginPreferences = configParser.readPreferences(cordovaContext),
platformsList = cordovaContext.opts.platforms;

// if no preferences are found - exit
if (pluginPreferences == null) {
return;
}

// if no host is defined - exit
if (pluginPreferences.hosts == null || pluginPreferences.hosts.length == 0) {
console.warn('No host is specified in the config.xml. Universal Links plugin is not going to work.');
return;
}

platformsList.forEach(function (platform) {
if (platform === IOS) {
activateUniversalLinksInIos(cordovaContext, pluginPreferences);
}
});
}

/**
* Activate Universal Links for iOS application.
*
* @param {Object} cordovaContext - cordova context object
* @param {Object} pluginPreferences - plugin preferences from the config.xml file. Basically, content from <branch-config> tag.
*/
function activateUniversalLinksInIos(cordovaContext, pluginPreferences) {
// modify xcode project preferences
//iosProjectPreferences.enableAssociativeDomainsCapability(cordovaContext);

// generate entitlements file
var buildTypes = ['Debug', 'Release'];
for (var x = 0; x < buildTypes.length; x++) {
iosProjectEntitlements.generateAssociatedDomainsEntitlements(cordovaContext, pluginPreferences, buildTypes[x]);
}
}
39 changes: 26 additions & 13 deletions hooks/lib/ios/projectEntitlements.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,15 @@ Script only generates content. File it self is included in the xcode project in
*
* @param {Object} cordovaContext - cordova context object
* @param {Object} pluginPreferences - plugin preferences from config.xml; already parsed
* @param {String} buildType - optional value to control which entitlement file to update
*/
function generateEntitlements(cordovaContext, pluginPreferences) {
function generateEntitlements(cordovaContext, pluginPreferences, buildType) {
context = cordovaContext;

var currentEntitlements = getEntitlementsFileContent(),
var currentEntitlements = getEntitlementsFileContent(buildType),
newEntitlements = injectPreferences(currentEntitlements, pluginPreferences);

saveContentToEntitlementsFile(newEntitlements);
saveContentToEntitlementsFile(newEntitlements, buildType);
}

// endregion
Expand All @@ -49,8 +50,9 @@ Script only generates content. File it self is included in the xcode project in
* Save data to entitlements file.
*
* @param {Object} content - data to save; JSON object that will be transformed into xml
* @param {String} buildType - optional value to control which entitlement file to update
*/
function saveContentToEntitlementsFile(content) {
function saveContentToEntitlementsFile(content, buildType) {
var plistContent = plist.build(content),
filePath = pathToEntitlementsFile();

Expand All @@ -59,15 +61,22 @@ Script only generates content. File it self is included in the xcode project in

// save it's content
fs.writeFileSync(filePath, plistContent, 'utf8');

if (buildType) {
filePath = pathToEntitlementsFile(buildType);
mkpath.sync(path.dirname(filePath));
// save it's content
fs.writeFileSync(filePath, plistContent, 'utf8');
}
}

/**
* Read data from existing entitlements file. If none exist - default value is returned
*
* @param {String} buildType - optional value to control which entitlement file to update
* @return {String} entitlements file content
*/
function getEntitlementsFileContent() {
var pathToFile = pathToEntitlementsFile(),
function getEntitlementsFileContent(buildType) {
var pathToFile = pathToEntitlementsFile(buildType),
content;

try {
Expand Down Expand Up @@ -139,15 +148,19 @@ Script only generates content. File it self is included in the xcode project in

/**
* Path to entitlements file.
*
* @param {String} buildType - optional value to control which entitlement file to update
* @return {String} absolute path to entitlements file
*/
function pathToEntitlementsFile() {
if (entitlementsFilePath === undefined) {
entitlementsFilePath = path.join(getProjectRoot(), 'platforms', 'ios', getProjectName(), 'Resources', getProjectName() + '.entitlements');
function pathToEntitlementsFile(buildType) {
if (buildType) {
var validTypes = ['Debug', 'Release'];
if (validTypes.indexOf(buildType) === -1) {
throw Error('pathToEntitlementsFile invalid build type specified: ' + buildType);
}
return path.join(getProjectRoot(), 'platforms', 'ios', getProjectName(), 'Entitlements-' + buildType + '.plist');
} else {
return path.join(getProjectRoot(), 'platforms', 'ios', getProjectName(), 'Resources', getProjectName() + '.entitlements');
}

return entitlementsFilePath;
}

/**
Expand Down
1 change: 1 addition & 0 deletions plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ SOFTWARE.
<preference name="URI_SCHEME" />

<!-- Hooks -->
<hook src="hooks/beforeCompileHook.js" type="before_compile" />
<hook src="hooks/afterPrepareHook.js" type="after_prepare" />
<hook src="hooks/beforePluginInstallHook.js" type="before_prepare" />

Expand Down

0 comments on commit 60d904d

Please sign in to comment.