pnpm
Version:
A fast implementation of npm install
109 lines • 5.77 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};
const rimraf = require('rimraf-then');
const path = require('path');
const getContext_1 = require('./getContext');
const getSaveType_1 = require('../getSaveType');
const removeDeps_1 = require('../removeDeps');
const binify_1 = require('../binify');
const extendOptions_1 = require('./extendOptions');
const requireJson_1 = require('../fs/requireJson');
const lock_1 = require('./lock');
const storeJsonController_1 = require('../fs/storeJsonController');
function uninstallCmd(pkgsToUninstall, maybeOpts) {
return __awaiter(this, void 0, void 0, function* () {
const opts = extendOptions_1.default(maybeOpts);
const ctx = yield getContext_1.default(opts);
if (!ctx.pkg) {
throw new Error('No package.json found - cannot uninstall');
}
const pkg = ctx.pkg;
return lock_1.default(ctx.store, () => uninstallInContext(pkgsToUninstall, pkg, ctx, opts));
});
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = uninstallCmd;
function uninstallInContext(pkgsToUninstall, pkg, ctx, opts) {
return __awaiter(this, void 0, void 0, function* () {
pkg.dependencies = pkg.dependencies || {};
// this is OK. The store might not have records for the package
// maybe it was cloned, `pnpm install` was not executed
// and remove is done on a package with no dependencies installed
ctx.storeJson.packages[ctx.root] = ctx.storeJson.packages[ctx.root] || {};
ctx.storeJson.packages[ctx.root].dependencies = ctx.storeJson.packages[ctx.root].dependencies || {};
const pkgIds = pkgsToUninstall
.map(dep => ctx.storeJson.packages[ctx.root].dependencies[dep])
.filter(pkgId => !!pkgId);
const uninstalledPkgs = tryUninstall(pkgIds.slice(), ctx.storeJson, ctx.root);
yield Promise.all(uninstalledPkgs.map(uninstalledPkg => removeBins(uninstalledPkg, ctx.store, ctx.root)));
if (ctx.storeJson.packages[ctx.root].dependencies) {
pkgsToUninstall.forEach(dep => {
delete ctx.storeJson.packages[ctx.root].dependencies[dep];
});
if (!Object.keys(ctx.storeJson.packages[ctx.root].dependencies).length) {
delete ctx.storeJson.packages[ctx.root].dependencies;
}
}
yield Promise.all(uninstalledPkgs.map(pkgId => removePkgFromStore(pkgId, ctx.store)));
storeJsonController_1.save(ctx.store, ctx.storeJson);
yield Promise.all(pkgsToUninstall.map(dep => rimraf(path.join(ctx.root, 'node_modules', dep))));
const saveType = getSaveType_1.default(opts);
if (saveType) {
const pkgJsonPath = path.join(ctx.root, 'package.json');
yield removeDeps_1.default(pkgJsonPath, pkgsToUninstall, saveType);
}
});
}
exports.uninstallInContext = uninstallInContext;
function canBeUninstalled(pkgId, storeJson, pkgPath) {
return !storeJson.packages[pkgId] || !storeJson.packages[pkgId].dependents || !storeJson.packages[pkgId].dependents.length ||
storeJson.packages[pkgId].dependents.length === 1 && storeJson.packages[pkgId].dependents.indexOf(pkgPath) !== -1;
}
function tryUninstall(pkgIds, storeJson, pkgPath) {
const uninstalledPkgs = [];
let numberOfUninstalls;
do {
numberOfUninstalls = 0;
for (let i = 0; i < pkgIds.length;) {
if (canBeUninstalled(pkgIds[i], storeJson, pkgPath)) {
const uninstalledPkg = pkgIds.splice(i, 1)[0];
uninstalledPkgs.push(uninstalledPkg);
const deps = storeJson.packages[uninstalledPkg] && storeJson.packages[uninstalledPkg].dependencies || {};
const depIds = Object.keys(deps).map(depName => deps[depName]);
delete storeJson.packages[uninstalledPkg];
depIds.forEach((dep) => removeDependency(dep, uninstalledPkg, storeJson));
Array.prototype.push.apply(uninstalledPkgs, tryUninstall(depIds, storeJson, uninstalledPkg));
numberOfUninstalls++;
continue;
}
i++;
}
} while (numberOfUninstalls);
return uninstalledPkgs;
}
exports.tryUninstall = tryUninstall;
function removeDependency(dependentPkgName, uninstalledPkg, storeJson) {
if (!storeJson.packages[dependentPkgName].dependents)
return;
storeJson.packages[dependentPkgName].dependents.splice(storeJson.packages[dependentPkgName].dependents.indexOf(uninstalledPkg), 1);
if (!storeJson.packages[dependentPkgName].dependents.length) {
delete storeJson.packages[dependentPkgName].dependents;
}
}
function removeBins(uninstalledPkg, store, root) {
const uninstalledPkgJson = requireJson_1.default(path.join(store, uninstalledPkg, '_/package.json'));
const bins = binify_1.default(uninstalledPkgJson);
return Promise.all(Object.keys(bins).map(bin => rimraf(path.join(root, 'node_modules/.bin', bin))));
}
function removePkgFromStore(pkgId, store) {
return rimraf(path.join(store, pkgId));
}
exports.removePkgFromStore = removePkgFromStore;
//# sourceMappingURL=uninstall.js.map