module-link-unlink
Version:
Link and unlink a module with saving and restoring the previous install
43 lines (42 loc) • 1.63 kB
JavaScript
import fs from 'fs';
import { unlink } from 'link-unlink';
import { Lock } from 'lock';
import path from 'path';
import Queue from 'queue-cb';
const lock = Lock();
function unlinkBin(nodeModules, binName, callback) {
const destBin = path.join(nodeModules, '.bin', binName);
fs.stat(destBin, (err)=>{
if (!err) return unlink(destBin, callback);
console.log(`bin not found: ${destBin}. Skipping`);
callback();
});
}
function worker(src, nodeModules, callback) {
lock([
src,
nodeModules
], (release)=>{
callback = release(callback);
try {
const pkg = JSON.parse(fs.readFileSync(path.join(src, 'package.json'), 'utf8'));
const dest = path.join.apply(null, [
nodeModules,
...pkg.name.split('/')
]);
const queue = new Queue(1);
queue.defer(unlink.bind(null, dest));
if (typeof pkg.bin === 'string') queue.defer(unlinkBin.bind(null, nodeModules, pkg.name)); // single bins
else for(const binName in pkg.bin)queue.defer(unlinkBin.bind(null, nodeModules, binName)); // object of bins
queue.await((err)=>{
err ? callback(err) : callback(null, dest);
});
} catch (err) {
return callback(err);
}
});
}
export default function unlinkModule(src, nodeModules, callback) {
if (typeof callback === 'function') return worker(src, nodeModules, callback);
return new Promise((resolve, reject)=>worker(src, nodeModules, (err, restore)=>err ? reject(err) : resolve(restore)));
}