cli-engine
Version:
Generic CLI Framework
135 lines (110 loc) • 3.75 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
require('cli-engine-config');
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _fsExtra = require('fs-extra');
var _fsExtra2 = _interopRequireDefault(_fsExtra);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const debug = require('debug')('cli-engine:plugins:yarn');
class Yarn {
constructor(output, cwd) {
this.out = output;
this.config = output.config;
this.cwd = cwd;
}
get version() {
return require('../../package.json')['cli-engine']['yarnDependency'];
}
get bin() {
return _path2.default.join(__dirname, '..', '..', 'yarn', `yarn-${this.version}.js`);
}
// https://github.com/yarnpkg/yarn/blob/master/src/constants.js#L73-L90
pathKey(env = process.env) {
let pathKey = 'PATH';
// windows calls its path "Path" usually, but this is not guaranteed.
if (this.config.windows) {
pathKey = 'Path';
for (const key in env) {
if (key.toLowerCase() === 'path') {
pathKey = key;
}
}
}
return pathKey;
}
// https://github.com/yarnpkg/yarn/blob/master/src/util/execute-lifecycle-script.js#L130-L154
pathEnv() {
let pathKey = this.pathKey();
const pathParts = (process.env[pathKey] || '').split(_path2.default.delimiter);
pathParts.unshift(_path2.default.dirname(process.execPath));
const env = {};
env[pathKey] = pathParts.join(_path2.default.delimiter);
return env;
}
fork(modulePath, args = [], options = {}) {
const { fork } = require('child_process');
return new Promise((resolve, reject) => {
let forked = fork(modulePath, args, options);
let error = '';
forked.stdout.setEncoding('utf8');
forked.stdout.on('data', data => {
if (this.config.debug) {
this.out.stdout.write(data);
}
});
forked.stderr.setEncoding('utf8');
forked.stderr.on('data', data => {
if (this.config.debug) {
this.out.stderr.write(data);
}
error += data;
});
forked.on('error', reject);
forked.on('exit', code => {
if (code === 0) {
resolve();
} else {
reject(new Error(`yarn ${args.join(' ')} exited with code ${code}\n${error}`));
}
});
// Fix windows bug with node-gyp hanging for input forever
if (this.config.windows) {
forked.stdin.write('\n');
}
});
}
async exec(args = []) {
if (args.length !== 0) await this.checkForYarnLock();
args = args.concat(['--non-interactive']).concat(Yarn.extraOpts);
if (global.yarnCacheDir !== false) {
let cacheDir = _path2.default.join(this.config.cacheDir, 'yarn');
args = args.concat([`--mutex=file:${cacheDir}`, `--cache-folder=${cacheDir}`]);
}
let options = {
cwd: this.cwd,
stdio: [null, null, null, 'ipc'],
env: Object.assign({}, process.env, this.pathEnv())
};
debug(`${options.cwd}: ${this.bin} ${args.join(' ')}`);
try {
await this.fork(this.bin, args, options);
} catch (err) {
// TODO: https://github.com/yarnpkg/yarn/issues/2191
let networkConcurrency = '--network-concurrency=1';
if (err.message.includes('EAI_AGAIN') && !args.includes(networkConcurrency)) {
return this.exec(args.concat(networkConcurrency));
} else throw err;
}
}
async checkForYarnLock() {
// add yarn lockfile if it does not exist
if (this.cwd && !_fsExtra2.default.existsSync(_path2.default.join(this.cwd, 'yarn.lock'))) {
await this.exec();
}
}
}
exports.default = Yarn;
Yarn.extraOpts = [];