appc-cli-titanium
Version:
Titanium CLI Plugin
204 lines (175 loc) • 6.47 kB
JavaScript
/**
* This code is closed source and Confidential and Proprietary to
* Appcelerator, Inc. All Rights Reserved. This code MUST not be
* modified, copied or otherwise redistributed without express
* written permission of Appcelerator. This file is licensed as
* part of the Appcelerator Platform and governed under the terms
* of the Appcelerator license agreement.
*/
var fs = require('fs-extra'),
os = require('os'),
path = require('path'),
util = require('./util'),
tiappxml = require('tiapp.xml'),
tmpdir = os.tmpdir();
module.exports = {
type: 'titanium',
subtype: 'app',
fields: [],
command: function (program, appc) {
this.fields.push(appc.fields.platform());
},
execute: execute,
when: function (opts) {
opts = opts || {};
var projectDir = path.join(opts.projectDir || process.cwd());
return fs.existsSync(path.join(projectDir, 'tiapp.xml')) || fs.existsSync(path.join(projectDir, 'timodule.xml'));
},
passthru: true
};
function execute(appc, args, opts, callback) {
var _ = appc.lodash,
tmpFile = path.join(tmpdir, 'build-' + Date.now() + '.json'),
entitlements = appc.commands.config.get('entitlements'),
projDir = path.resolve(opts.projectDir || process.cwd()),
tiappFile = path.join(projDir, 'tiapp.xml');
util.syncTiDownloads(appc, function (err) {
if (err) {
return callback(err);
}
util.getTiConfig(opts, updateConfig);
});
function updateConfig(err, tiConfig) {
if (err) {
return callback(err);
}
var appcHooks = getAppcHooks();
if (tiConfig.paths && Array.isArray(tiConfig.paths.hooks)) {
tiConfig.paths.hooks.push(path.join(__dirname, '..', 'hook'));
if (entitlements && entitlements.appPreview) {
appcHooks && tiConfig.paths.hooks.push(path.join(appcHooks, 'appc-app-preview'));
}
}
tiConfig.appc = {
filename: appc.filename,
opts: _.merge({
server: appc.constants.APPC_DASHBOARD_URL
}, opts),
privateKey: appc.constants.getDeveloperPrivateKeyFile(opts.session.username, opts.session.org_id)
};
const tiapp = fs.existsSync(tiappFile) && tiappxml.load(tiappFile);
if (tiapp && appc && appc.semver && appc.semver.gte(util.version.format(tiapp.sdkVersion, 3, 3), '8.0.0') && tiapp.getProperty('com-soasta-touchtest-version')) {
tiapp.removeModule('com.soasta.touchtest');
tiapp.removeModule('com.soasta.touchtest', 'android');
tiapp.removeModule('com.soasta.touchtest', 'iphone');
tiapp.removePlugin('com.soasta.touchtest.android');
tiapp.removeProperty('com-soasta-touchtest-version');
tiapp.removeProperty('com-soasta-touchtest-ios-appId');
try {
scrubTiappXmlSoasta(tiapp);
} catch (error) {
/* nop */
}
tiapp.write();
}
fs.writeFile(tmpFile, JSON.stringify(tiConfig), 'UTF-8', runTitanium);
}
function runTitanium(err) {
if (err) {
return callback(err);
}
var pwi = args.indexOf('--password');
if (pwi !== -1) {
args.splice(pwi, 2);
}
// run is not a valid command to ti
if (args[0] === 'run') {
args.shift();
}
if (args[0] !== 'build') {
args.unshift('build');
}
args.push('--config-file', tmpFile);
// set the default log level
if (args.indexOf('-l') === -1 && args.indexOf('--log-level') === -1) {
args.push('--log-level', 'info');
}
// set the banner
args.push('--no-banner');
// set the project dir
args.push('--project-dir', projDir);
updateAlloyHook(appc, projDir);
process.env.ALLOY_PATH = path.resolve(path.dirname(require.resolve('alloy')) + '/../bin/alloy');
args.unshift(require.resolve('titanium'));
args.unshift(process.argv[0]);
process.argv = args;
require('titanium');
}
}
function getAppcHooks() {
var coreHooksPath;
if (process.env.APPC_INSTALL_BIN_DIR) {
coreHooksPath = path.resolve(path.join(process.env.APPC_INSTALL_BIN_DIR, '..', '..', 'hooks'));
} else {
coreHooksPath = path.resolve(path.join(__dirname.split('node_modules')[0], 'hooks'));
}
return fs.existsSync(coreHooksPath) ? coreHooksPath : null;
}
function updateAlloyHook(appc, projDir) {
var alloyHookFile = path.resolve(path.dirname(require.resolve('alloy')) + '/../hooks/alloy.js'),
alloyHookVer = fs.existsSync(alloyHookFile) && require(alloyHookFile).version, // eslint-disable-line security/detect-non-literal-require
projAlloyHookFile = path.join(projDir, 'plugins', 'ti.alloy', 'hooks', 'alloy.js'),
projHookVer = fs.existsSync(projAlloyHookFile) && require(projAlloyHookFile).version; // eslint-disable-line security/detect-non-literal-require
if (alloyHookVer) {
if (!projHookVer) {
appc.log.trace('No project alloy hook; skipping update to %s', alloyHookVer);
} else if (util.ltSdkVersion(projHookVer, alloyHookVer)) {
appc.log.trace('Updating project alloy hook from version %s to %s', projHookVer, alloyHookVer);
fs.copySync(alloyHookFile, projAlloyHookFile);
}
}
}
function scrubTiappXmlSoasta(tiapp) {
// IOS
const plist = tiapp.doc.documentElement.getElementsByTagName('plist');
const dict = plist.length > 0 ? plist.item(0) : null;
const keys = dict && dict.getElementsByTagName('key');
for (let i = 0; i < keys.length; i++) {
const key = keys.item(i);
const name = key && key.firstChild && key.firstChild.data;
if (name === 'CFBundleURLTypes') {
let next = key.nextSibling;
while (next && next.tagName !== 'array') {
next = next.nextSibling;
}
const strings = next && next.getElementsByTagName('string');
for (let j = 0; j < strings.length; j++) {
const item = strings.item(j);
const value = item && item.firstChild && item.firstChild.data;
if (value.indexOf('touchtest-') === 0) {
if (strings.length < 4) {
dict.removeChild(key);
dict.removeChild(next);
} else {
next.removeChild(item);
}
break;
}
}
break;
}
}
// ANDROID
const serviceNode = tiapp.doc.documentElement.getElementsByTagName('service');
if (serviceNode.length > 0 && serviceNode.item(0) && serviceNode.item(0).getAttribute('android:name') === 'com.soasta.android.touchtest.TouchTestService') {
tiapp.doc.removeChild(serviceNode.item(0));
}
const intentFilters = tiapp.doc.documentElement.getElementsByTagName('intent-filter');
for (let i = 0; i < intentFilters.length; i++) {
const filter = intentFilters.item(i);
const data = filter && filter.getElementsByTagName('data');
if (data.length > 0 && data.item(0).getAttribute('android:scheme').indexOf('touchtest-') === 0) {
filter.removeChild(filter);
}
}
}