appc-cli-titanium
Version:
Titanium CLI Plugin
254 lines (230 loc) • 7.28 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 async = require('async'),
util = require('./util');
var TYPE = require('../appc').TYPE;
module.exports = {
type: TYPE,
name: 'Cross Platform Mobile App Setup',
execute: execute
};
function execute(appc, args, opts, callback) {
appc.inquirer.prompt([
{
message: 'Do you plan on developing Titanium apps?',
name: 'confirm',
type: 'confirm',
default: 'Y'
}
], function (answers) {
if (!answers.confirm) {
return callback();
} else {
var config,
latestVersion;
async.series([
// launch info (which will automatically install sdk)
function (cb) {
console.log('\nChecking your environment...\n');
appc.spinner.start();
cb();
},
function (cb) {
util.getLatestTiSDK(appc, function (err, latest) {
if (latest) {
latestVersion = latest;
}
cb(err);
});
},
function (cb) {
util.launchTi(appc, [ 'sdk', '-o', 'json', '--no-banner', '--no-prompt' ], opts, function (err, ti) {
if (err) {
return cb(err);
}
var stdout = '',
stderr = '';
ti.stdout.on('data', function (buf) {
buf = String(buf).replace(/\s$/, '');
appc.log.trace(buf);
stdout += buf;
});
ti.on('close', function (err) {
if (err) {
appc.log.debug(err);
appc.log.debug(stderr);
return cb(new Error('titanium exited with ' + err + ' exit code'));
}
try {
config = JSON.parse(stdout);
// check if active sdk is installed
if (!(config.activeSDK in config.installed)) {
// active sdk is not installed
// select latest installed sdk
var version = Object.keys(config.installed)[0];
async.series([
function (cb) {
// select most recent installed sdk
util.launchTi(appc, [ 'sdk', 'select', version ], opts, cb);
},
function (cb) {
// check for new version
util.installTi(appc, cb);
} ],
function () {
cb();
}
);
} else if (util.ltSdkVersion(config.activeSDK, latestVersion)) {
if (latestVersion in config.installed) {
appc.log.info('You have the latest Titanium SDK release ' + appc.chalk.blue(latestVersion) + ', but it\'s not currently set as the active SDK.');
appc.log.info('Changing your active version to the latest. You can reset it to the previous version by running:\n');
appc.log.info('\t' + appc.chalk.cyan('appc ti sdk select ' + config.activeSDK) + '\n');
util.launchTi(appc, [ 'sdk', 'select', latestVersion ], opts, cb);
} else {
// need to get the latest
appc.log.info('A new version of the Titanium SDK is available, will download it...');
util.installTi(appc, cb);
}
} else {
appc.log.info('You have the latest Titanium SDK release ' + appc.chalk.blue(config.activeSDK));
cb();
}
} catch (E) {
appc.log.trace(stdout);
appc.log.trace(E.message || E);
appc.log.trace(E.stack);
return cb(new Error('invalid config results returned from titanium. (JSON parse error)'));
}
});
});
},
function (cb) {
util.launchTi(appc, [ 'info', '-o', 'json', '--no-banner', '--no-prompt' ], opts, function (err, ti) {
appc.spinner.stop();
if (err) {
return cb(err);
}
var stdout = '',
stderr = '';
ti.stdout.on('data', function (buf) {
buf = String(buf).replace(/\s$/, '');
appc.log.trace(buf);
stdout += buf;
});
ti.stderr.on('data', function (buf) {
buf = String(buf).replace(/\s$/, '');
appc.log.trace(buf);
stderr += buf + '\n';
});
ti.on('close', function (err) {
if (err) {
appc.log.debug(err);
appc.log.debug(stderr);
return cb(new Error('titanium exited with ' + err + ' exit code'));
}
try {
config = JSON.parse(stdout);
cb();
} catch (E) {
appc.log.trace(stdout);
appc.log.trace(E.message || E);
return cb(new Error('invalid config results returned from titanium. (JSON parse error)'));
}
});
});
},
// now see what's missing
function (cb) {
var count = 0;
Object.keys(config).forEach(function (key) {
var obj = config[key];
count += dumpIssues(appc, obj, key);
});
if (count) {
appc.log.warn(appc.chalk.white.underline('Some issues were detected for your environment\n'));
console.log(appc.chalk.yellow('\tPlease review the above found issues that were detected for your environment.'));
console.log(appc.chalk.yellow('\tYou should resolve these issues before building or running a cross platform app.'));
console.log(appc.chalk.yellow('\tYou can re-run setup once they are resolved to validate.'));
console.log();
} else {
console.log(appc.chalk.green('Congrats! No issues detected for developing cross-platform mobile apps!'));
console.log();
}
cb();
}
], function (err) {
appc.spinner.stop();
return callback(err);
});
}
});
}
/**
* tokenize a string a word breaks (spaces) such that we have a line
* no longer than maxwidth
*/
function tokenize(line, maxwidth, result) {
var toks = line.split(' '),
len = 0,
tokenizedLine = '',
i = 0;
while (i < toks.length) {
var token = toks[i];
if (token.length + len >= maxwidth) {
len = 0;
result.push(tokenizedLine);
line = '';
}
tokenizedLine += token + ' ';
len += token.length;
i++;
}
if (len < maxwidth && line) {
result.push(tokenizedLine);
}
}
/**
* do a nice dump of the issues found by ti info
*/
function dumpIssues(appc, obj, label) {
var issues = getErrors(obj),
issueLinkRegex = /__(.*)__/g;
if (!issues) {
return 0;
}
var msgs = [];
var maxwidth = Math.max(Math.floor(process.stdout.columns * 0.75), 70);
issues.forEach(function (issue) {
var lines = [];
util.patchTiCommand(issue.message).split('\n').forEach(function (line) {
tokenize(line, maxwidth, lines);
});
var msg = lines.map(function (line, index) {
return '\t' + line.replace(issueLinkRegex, function (msg) {
return appc.chalk.blue.underline(issueLinkRegex.exec(msg)[1]);
});
}).join('\n') + '\n';
msgs.push(appc.chalk.red(msg));
});
appc.log.warn(appc.chalk.yellow('The following ' + appc.chalk.green.underline(label.toUpperCase()) + ' issues were found in your environment:\n\n') + msgs.join('\n'));
return issues.length;
}
function getErrors(obj) {
if (!obj || !obj.issues || !obj.issues.length) {
return null;
}
var errors = [];
obj.issues.forEach(function (o) {
if (o.type === 'error') {
errors.push(o);
}
});
return errors.length ? errors : null;
}