pnpm
Version:
A fast implementation of npm install
128 lines (126 loc) • 4.96 kB
JavaScript
"use strict";
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 path = require('path');
const normalizePath = require('normalize-path');
const common_tags_1 = require('common-tags');
const relSymlink_1 = require('../fs/relSymlink');
const fs = require('mz/fs');
const mkdirp_1 = require('../fs/mkdirp');
const requireJson_1 = require('../fs/requireJson');
const getPkgDirs_1 = require('../fs/getPkgDirs');
const binify_1 = require('../binify');
const env_1 = require('../env');
function linkAllBins(modules) {
return __awaiter(this, void 0, void 0, function* () {
const pkgDirs = yield getPkgDirs_1.default(modules);
return Promise.all(pkgDirs.map((pkgDir) => linkPkgBins(modules, pkgDir)));
});
}
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = linkAllBins;
/**
* Links executable into `node_modules/.bin`.
*
* @param {String} modules - the node_modules path
* @param {String} target - where the module is now; read package.json from here
*
* @example
* module = 'project/node_modules'
* target = 'project/node_modules/.store/rimraf@2.5.1'
* linkPkgBins(module, target)
*
* // node_modules/.bin/rimraf -> ../.store/rimraf@2.5.1/cmd.js
*/
function linkPkgBins(modules, target) {
return __awaiter(this, void 0, void 0, function* () {
const pkg = tryRequire(path.join(target, 'package.json'));
if (!pkg || !pkg.bin)
return;
const bins = binify_1.default(pkg);
const binDir = path.join(modules, '.bin');
yield mkdirp_1.default(binDir);
yield Promise.all(Object.keys(bins).map(function (bin) {
return __awaiter(this, void 0, void 0, function* () {
const actualBin = bins[bin];
const externalBinPath = path.join(binDir, bin);
const targetPath = normalizePath(path.join(pkg.name, actualBin));
if (env_1.isWindows) {
if (!env_1.preserveSymlinks) {
return cmdShim(externalBinPath, '../' + targetPath);
}
const proxyFilePath = path.join(binDir, bin + '.proxy');
fs.writeFileSync(proxyFilePath, 'require("../' + targetPath + '")', 'utf8');
return cmdShim(externalBinPath, path.relative(binDir, proxyFilePath));
}
if (!env_1.preserveSymlinks) {
yield makeExecutable(path.join(target, actualBin));
return relSymlink_1.default(path.join(target, actualBin), externalBinPath);
}
return proxy(externalBinPath, targetPath);
});
}));
});
}
exports.linkPkgBins = linkPkgBins;
function makeExecutable(filePath) {
return fs.chmod(filePath, 0o755);
}
function proxy(proxyPath, targetPath) {
const proxyContent = common_tags_1.stripIndent `
#!/bin/sh
":" //# comment; exec /usr/bin/env node --preserve-symlinks "$0" "$@"
require('../${targetPath}')`;
fs.writeFileSync(proxyPath, proxyContent, 'utf8');
return makeExecutable(proxyPath);
}
function cmdShim(proxyPath, targetPath) {
const nodeOptions = env_1.preserveSymlinks ? '--preserve-symlinks' : '';
const cmdContent = common_tags_1.stripIndent `
@IF EXIST "%~dp0\\node.exe" (
"%~dp0\\node.exe ${nodeOptions}" "%~dp0/${targetPath}" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
node ${nodeOptions} "%~dp0/${targetPath}" %*
)`;
fs.writeFileSync(proxyPath + '.cmd', cmdContent, 'utf8');
const shContent = common_tags_1.stripIndent `
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case \`uname\` in
*CYGWIN*) basedir=\`cygpath -w "$basedir"\`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node ${nodeOptions}" "$basedir/${targetPath}" "$@"
ret=$?
else
node ${nodeOptions} "$basedir/${targetPath}" "$@"
ret=$?
fi
exit $ret
`;
fs.writeFileSync(proxyPath, shContent, 'utf8');
return Promise.all([
makeExecutable(proxyPath + '.cmd'),
makeExecutable(proxyPath)
]);
}
/**
* Like `require()`, but returns `undefined` when it fails
*/
function tryRequire(path) {
try {
return requireJson_1.default(path);
}
catch (e) {
return null;
}
}
//# sourceMappingURL=linkBins.js.map