src/install-command.ts
import * as fs from "fs";
import * as path from 'path';
import * as rmrf from 'rimraf';
export class InstallCommand {
static from = installCommand;
static capture = captureVariants;
}
function captureVariants() {
const REAL_ADD = 'add';
let commandIndex = 2, command = process.argv[commandIndex];
if (command === 'help') {
commandIndex = 3;
command = process.argv[commandIndex];
}
switch(command) {
case 'i': case 'add': case 'install':
process.argv[commandIndex] = REAL_ADD;
break;
default:
}
}
function installCommand(args, options, logger) {
args.packagePaths.push(args.packagePath);
args.packagePaths.forEach(packagePath=>copyPackage(packagePath));
function copyPackage(packagePath:string) {
const absPackagePath = path.join(process.cwd(),packagePath),
absNodeModulesPath = path.join(process.cwd(),'node_modules');
if (options.dry) logger.info(`âšī¸ Looking for package.json in ${absPackagePath}`);
fs.readFile(
path.join(absPackagePath,'package.json'),
{encoding:'utf8'},
(err, file)=>{
if (err || !file) logger.error(`â Couldn't access package.json: ${err||'file empty'}`);
if (options.verbose) {
logger.debug(`đ raw package.json`);
logger.info(file);
}
const packageData = JSON.parse(file),
absInstallPath = path.join(absNodeModulesPath, packageData.name);
fs.lstat(path.join(absNodeModulesPath),
(err, info)=>{
if (err || !info.isDirectory()) {
logger.error(`â Couldn't access node_modules: ${err||'not a directory'}`);
return;
}
logger.info(`đĻ Installing ${packageData.name}@${packageData.version}\n đ in ${absInstallPath}`)
//logger.info(`đ Deleting ${absInstallPath}`);
if (!options.dry) rmrf(absInstallPath, (err)=>{
if (err) {
logger.error(`â Couldn't remove ${absInstallPath}`);
return;
}
if (options.verbose) logger.debug(`â
Removed ${absInstallPath}`);
if (options.verbose) logger.debug(`đ Copying ${absPackagePath} to ${absInstallPath}}`);
copy(absPackagePath, absInstallPath);
}); // rmrf
else {
logger.info(`đ Would be removing & copying ${absPackagePath} to ${absInstallPath}}`);
copy(absPackagePath, absInstallPath);
}
}
); // lstat
}
);
} // copyPackage(...)
function copy(src:string, dest:string) {
const absNodeModulesPath = path.join(process.cwd(), 'node_modules/');
fs.lstat(src, (err,info)=>{
if (err) {
logger.error(`â Couldn't lstat ${src}:\n\t${err}`);
return err;
}
if (info.isDirectory()) {
let ensureDest = dest.slice(absNodeModulesPath.length);
if (!options.dry) ensureDirectory(absNodeModulesPath, ensureDest.split(/\/|\\/g), (err)=>{
if (err) {
logger.error(`â Couldn't mkdir ${dest}:\n\t${err}`);
return err;
}
read();
});
else read();
}
else if (!options.dry)
fs.copyFile(
src, dest,
(err)=>
err?
logger.error(`â Didn't copy ${dest}:\n\t${err}`):
(options.verbose)?logger.info(`â
Copied ${dest}`):null
);
else logger.info(`âī¸ Would copy ${dest}`);
function read() {
fs.readdir(src, (err, items)=>{
if (err) {
logger.error(`â Couldn't read ${src}: ${err}`);
return err;
}
if (options.verbose) logger.info(`đ Copying ${src} to ${dest}`);
items.forEach(
item=>{
var srcFile = path.join(src, item), destFile = path.join(dest,item);
if (options.verbose) logger.info(`đ Copying ${srcFile} to ${destFile}`);
copy(srcFile, destFile);
}
);
});
}
});
}
function ensureDirectory(cwd:string, paths:string[], callback:(err:any)=>any) {
console.info(paths)
var ensureDir = paths.shift(), ensurePath = path.join(cwd, ensureDir);
console.info(ensurePath);
fs.lstat(ensurePath, (err, info)=>err?next():(info&&info.isDirectory()?ensureDirectory(ensurePath, paths, callback):callback(err)));
function next() {
fs.mkdir(ensurePath, (err)=>{
if (err) return callback(err);
if (paths.length) return ensureDirectory(ensurePath, paths, callback);
else return callback(err);
});
}
}
}