blob: b264df754dc15777cc9ebb1c59bfdfe6e5c12e09 [file] [log] [blame]
var cordova_util = require('./util'),
util = require('util'),
fs = require('fs'),
shell = require('shelljs'),
path = require('path'),
shell = require('shelljs'),
config_parser = require('./config_parser'),
hooker = require('./hooker'),
platform = require('./platform'),
plugin_parser = require('./plugin_parser'),
ls = fs.readdirSync;
module.exports = function plugin(command, targets, callback) {
var projectRoot = cordova_util.isCordova(process.cwd());
if (!projectRoot) {
throw 'Current working directory is not a Cordova-based project.';
}
if (arguments.length === 0) command = 'ls';
var hooks = new hooker(projectRoot);
var projectWww = path.join(projectRoot, 'www');
// Grab config info for the project
var xml = path.join(projectWww, 'config.xml');
var cfg = new config_parser(xml);
var platforms = ls(path.join(projectRoot, 'platforms'));
// Massage plugin name(s) / path(s)
var pluginPath, plugins, names = [];
pluginPath = path.join(projectRoot, 'plugins');
plugins = ls(pluginPath);
if (targets) {
if (!(targets instanceof Array)) targets = [targets];
targets.forEach(function(target) {
var targetName = target.substr(target.lastIndexOf('/') + 1);
if (targetName[targetName.length-1] == '/') targetName = targetName.substr(0, targetName.length-1);
names.push(targetName);
});
}
switch(command) {
case 'ls':
case 'list':
// TODO awkward before+after hooks here
hooks.fire('before_plugin_ls');
hooks.fire('after_plugin_ls');
if (plugins.length) {
return plugins;
} else return 'No plugins added. Use `cordova plugin add <plugin>`.';
break;
case 'add':
if (platforms.length === 0) {
throw 'You need at least one platform added to your app. Use `cordova platform add <platform>`.';
}
targets.forEach(function(target, index) {
var pluginContents = ls(target);
var targetName = names[index];
// Check if we already have the plugin.
// TODO edge case: if a new platform is added, then you want
// to re-add the plugin to the new platform.
if (plugins.indexOf(targetName) > -1) {
throw 'Plugin "' + targetName + '" already added to project.';
}
// Check if the plugin has a plugin.xml in the root of the
// specified dir.
if (pluginContents.indexOf('plugin.xml') == -1) {
throw 'Plugin "' + targetName + '" does not have a plugin.xml in the root. Plugin must support the Cordova Plugin Specification: https://github.com/alunny/cordova-plugin-spec';
}
// Check if there is at least one match between plugin
// supported platforms and app platforms
var pluginXml = new plugin_parser(path.join(target, 'plugin.xml'));
var intersection = pluginXml.platforms.filter(function(e) {
if (platforms.indexOf(e) == -1) return false;
else return true;
});
if (intersection.length === 0) {
throw 'Plugin "' + targetName + '" does not support any of your application\'s platforms. Plugin platforms: ' + pluginXml.platforms.join(', ') + '; your application\'s platforms: ' + platforms.join(', ');
}
hooks.fire('before_plugin_add');
var pluginWww = path.join(target, 'www');
var wwwContents = ls(pluginWww);
var cli = path.join(__dirname, '..', 'node_modules', 'pluginstall', 'pluginstall.js');
// Iterate over all matchin app-plugin platforms in the project and install the
// plugin.
intersection.forEach(function(platform) {
var cmd = util.format('%s --platform %s --project "%s" --plugin "%s"', cli, platform, path.join(projectRoot, 'platforms', platform), target);
var plugin_cli = shell.exec(cmd, {silent:true});
if (plugin_cli.code > 0) throw 'An error occured during plugin installation for ' + platform + '. ' + plugin_cli.output;
});
// Add the plugin web assets to the www folder as well
// TODO: assumption that web assets go under www folder
// inside plugin dir; instead should read plugin.xml
wwwContents.forEach(function(asset) {
asset = path.resolve(path.join(pluginWww, asset));
var info = fs.lstatSync(asset);
var name = asset.substr(asset.lastIndexOf('/')+1);
var wwwPath = path.join(projectWww, name);
if (info.isDirectory()) {
shell.cp('-r', asset, projectWww);
} else {
fs.writeFileSync(wwwPath, fs.readFileSync(asset));
}
});
// Finally copy the plugin into the project
var targetPath = path.join(pluginPath, targetName);
shell.mkdir('-p', targetPath);
shell.cp('-r', path.join(target, '*'), targetPath);
hooks.fire('after_plugin_add');
});
if (callback) callback();
break;
case 'rm':
case 'remove':
if (platforms.length === 0) {
throw 'You need at least one platform added to your app. Use `cordova platform add <platform>`.';
}
targets.forEach(function(target, index) {
var targetName = names[index];
// Check if we have the plugin.
if (plugins.indexOf(targetName) > -1) {
var targetPath = path.join(pluginPath, targetName);
hooks.fire('before_plugin_rm');
var pluginWww = path.join(targetPath, 'www');
var wwwContents = ls(pluginWww);
var cli = path.join(__dirname, '..', 'node_modules', 'pluginstall', 'pluginstall.js');
// Check if there is at least one match between plugin
// supported platforms and app platforms
var pluginXml = new plugin_parser(path.join(targetPath, 'plugin.xml'));
var intersection = pluginXml.platforms.filter(function(e) {
if (platforms.indexOf(e) == -1) return false;
else return true;
});
// Iterate over all matchin app-plugin platforms in the project and uninstall the
// plugin.
intersection.forEach(function(platform) {
var cmd = util.format('%s --platform %s --project "%s" --plugin "%s" --remove', cli, platform, path.join(projectRoot, 'platforms', platform), targetPath);
var plugin_cli = shell.exec(cmd, {silent:true});
if (plugin_cli.code > 0) throw 'An error occured during plugin uninstallation for ' + platform + '. ' + plugin_cli.output;
});
// Remove the plugin web assets to the www folder as well
// TODO: assumption that web assets go under www folder
// inside plugin dir; instead should read plugin.xml
wwwContents.forEach(function(asset) {
asset = path.resolve(path.join(projectWww, asset));
var info = fs.lstatSync(asset);
if (info.isDirectory()) {
shell.rm('-rf', asset);
} else {
fs.unlinkSync(asset);
}
});
// Finally remove the plugin dir from plugins/
shell.rm('-rf', targetPath);
hooks.fire('after_plugin_rm');
} else {
throw 'Plugin "' + targetName + '" not added to project.';
}
});
if (callback) callback();
break;
default:
throw 'Unrecognized command "' + command + '". Use either `add`, `remove`, or `list`.';
}
};