Files
whistle/bin/plugin.js
2019-08-22 21:28:59 +08:00

150 lines
4.3 KiB
JavaScript
Executable File

var os = require('os');
var cp = require('child_process');
var fs = require('fs');
var path = require('path');
var fse = require('fs-extra2');
var CMD_SUFFIX = process.platform === 'win32' ? '.cmd' : '';
var WHISLTE_PLUGIN_RE = /^(@[\w\-]+\/)?whistle\.[a-z\d_\-]+$/;
var PLUGIN_PATH = path.join(getWhistlePath(), 'plugins');
var CUSTOM_PLUGIN_PATH = path.join(getWhistlePath(), 'custom_plugins');
var PACKAGE_JSON = '{"repository":"https://github.com/avwo/whistle","license":"MIT"}';
var LICENSE = 'Copyright (c) 2019 avwo';
var RESP_URL = 'https://github.com/avwo/whistle';
function getInstallPath(name, dir) {
return path.join(dir || CUSTOM_PLUGIN_PATH, name);
}
function getHomedir() {
//默认设置为`~`,防止Linux在开机启动时Node无法获取homedir
return (typeof os.homedir == 'function' ? os.homedir() :
process.env[process.platform == 'win32' ? 'USERPROFILE' : 'HOME']) || '~';
}
function getWhistlePath() {
return process.env.WHISTLE_PATH || path.join(getHomedir(), '.WhistleAppData');
}
function getPlugins(argv) {
return argv.filter(function(name) {
return WHISLTE_PLUGIN_RE.test(name);
});
}
function removeDir(installPath) {
if (fs.existsSync(installPath)) {
fse.removeSync(installPath);
}
}
function removeOldPlugin(name) {
removeDir(path.join(PLUGIN_PATH, 'node_modules', name));
removeDir(path.join(PLUGIN_PATH, 'node_modules', getTempName(name)));
}
function getTempName(name) {
if (name.indexOf('/') === -1) {
return '.' + name;
}
name = name.split('/');
var lastIndex = name.length - 1;
name[lastIndex] = '.' + name[lastIndex];
return name.join('/');
}
function getInstallDir(argv) {
var result = { argv: argv };
for (var i = 0, len = argv.length; i < len; i++) {
var option = argv[i];
if (option && option.indexOf('--dir=') === 0) {
var dir = option.substring(option.indexOf('=') + 1);
result.dir = dir && path.resolve(dir);
argv.splice(i, 1);
return result;
}
}
return result;
}
function install(cmd, name, argv) {
argv = argv.slice();
var result = getInstallDir(argv);
argv = result.argv;
var installPath = getInstallPath(getTempName(name), result.dir);
fse.ensureDirSync(installPath);
fse.emptyDirSync(installPath);
fs.writeFileSync(path.join(installPath, 'package.json'), PACKAGE_JSON);
fs.writeFileSync(path.join(installPath, 'LICENSE'), LICENSE);
fs.writeFileSync(path.join(installPath, 'README.md'), RESP_URL);
argv.unshift('install', name);
cp.spawn(cmd, argv, {
stdio: 'inherit',
cwd: installPath
}).on('exit', function(code) {
if (code) {
removeDir(installPath);
} else {
var realPath = getInstallPath(name, result.dir);
removeDir(realPath);
try {
fs.renameSync(installPath, realPath);
} catch (e) {
fse.copySync(installPath, realPath);
try {
removeDir(installPath);
} catch (e) {}
}
}
});
}
exports.install = function(cmd, argv) {
var plugins = getPlugins(argv);
if (!plugins.length) {
return;
}
argv = argv.filter(function(name) {
return plugins.indexOf(name) === -1;
});
cmd += CMD_SUFFIX;
argv.push('--no-package-lock');
plugins.forEach(function(name) {
removeOldPlugin(name);
install(cmd, name, argv);
});
};
exports.uninstall = function(plugins) {
var result = getInstallDir(plugins);
plugins = result.argv;
getPlugins(plugins).forEach(function(name) {
!result.dir && removeOldPlugin(name);
removeDir(getInstallPath(name, result.dir));
});
};
exports.run = function(cmd, argv) {
var newPath = [];
fse.ensureDirSync(CUSTOM_PLUGIN_PATH);
fs.readdirSync(CUSTOM_PLUGIN_PATH).forEach(function(name) {
if (!name.indexOf('whistle.')) {
newPath.push(path.join(CUSTOM_PLUGIN_PATH, name, 'node_modules/.bin'));
} else if (name[0] === '@') {
try {
fs.readdirSync(path.join(CUSTOM_PLUGIN_PATH, name)).forEach(function(modName) {
newPath.push(path.join(CUSTOM_PLUGIN_PATH, name, modName, 'node_modules/.bin'));
});
} catch (e) {}
}
});
process.env.PATH && newPath.push(process.env.PATH);
newPath = newPath.join(os.platform() === 'win32' ? ';' : ':');
process.env.PATH = newPath;
cp.spawn(cmd + CMD_SUFFIX, argv, {
stdio: 'inherit',
env: process.env
});
};