UNPKG

cli-engine

Version:
187 lines (153 loc) 5.59 kB
'use strict'; 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); var _manager = require('./manager'); var _namespaces = require('../namespaces'); var _namespaces2 = _interopRequireDefault(_namespaces); var _yarn = require('./yarn'); var _yarn2 = _interopRequireDefault(_yarn); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } class UserPluginPath extends _manager.PluginPath { constructor({ output, type, path, tag, userPlugins }) { super({ output, type, path, tag }); this.repairAttempted = false; this.userPlugins = userPlugins; } async repair(err) { if (err.code !== 'MODULE_NOT_FOUND') return false; if (this.repairAttempted) return false; this.out.warn(err); this.out.action.start(`Repairing plugin ${this.path}`); this.repairAttempted = true; await this.userPlugins.installForce(); this.out.action.stop(); return true; } } class UserPlugins extends _manager.Manager { constructor({ out, config, cache }) { super({ out, config, cache }); this.yarn = new _yarn2.default(this.out, this.userPluginsDir); /** * There is a bug with snappy & node-gyp & semver that causes issues when * we rebuild. What happens is that semver is downgraded from 5.3.0 to * 4.3.2 which has a bug in it that causes node-gyp to fail * * I was going to try and make this an add to package.json to save some * time but that causes 4.3.2 to install into node-gyp/node_modules for * reasons I do not understand but `add` does the right thing * * I set version to ~5.3.0 to match the current dependency from node-gyp * under the assumption that it is the most likely to work properly * * https://github.com/nodejs/node-gyp/blob/75cfae290fee1791a23fa68820ae5dd841e93e14/package.json#L34 */ this.hardcodedDepFixes = { semver: '~5.3.0' }; } /** * list user plugins * @returns {PluginPath[]} */ async list() { try { const pjson = this.userPluginsPJSON; return entries(pjson.dependencies || {}).filter(([name, tag]) => { return !this.hardcodedDepFixes[name]; }).map(([name, tag]) => { return new UserPluginPath({ output: this.out, type: 'user', path: this.userPluginPath(name), tag: tag, userPlugins: this }); }); } catch (err) { this.out.warn(err, 'error loading user plugins'); return []; } } get userPluginsPJSON() { try { return _fsExtra2.default.readJSONSync(this.userPluginsPJSONPath); } catch (err) { return { dependencies: {} }; } } saveUserPluginsPJSON(pjson) { _fsExtra2.default.writeJSONSync(_path2.default.join(this.userPluginsPJSONPath), pjson); } async setupUserPlugins() { const pjson = _path2.default.join(this.userPluginsDir, 'package.json'); const yarnrc = _path2.default.join(this.userPluginsDir, '.yarnrc'); _fsExtra2.default.mkdirpSync(this.userPluginsDir); if (!_fsExtra2.default.existsSync(pjson)) _fsExtra2.default.writeFileSync(pjson, JSON.stringify({ private: true })); if (!_fsExtra2.default.existsSync(yarnrc)) _fsExtra2.default.writeFileSync(yarnrc, 'registry "https://cli-npm.heroku.com/"'); } async installForce() { if (_fsExtra2.default.existsSync(_path2.default.join(this.userPluginsDir, 'node_modules'))) { let dependencies = this.userPluginsPJSON['dependencies'] || {}; for (let mod in this.hardcodedDepFixes) { if (!dependencies[mod]) { await this.yarn.exec(['add', `${mod}@${this.hardcodedDepFixes[mod]}`]); } } await this.yarn.exec(['install', '--force']); } } async handleNodeVersionChange() { try { await this.installForce(); } catch (err) { this.out.warn(err); } } async install(name, tag = 'latest') { await this.setupUserPlugins(); this.addPackageToPJSON(name, tag); try { await this.yarn.exec(); let path = this.userPluginPath(name); _namespaces2.default.throwErrorIfNotPermitted(path, this.config); let plugin = require(path); if (!plugin.commands) throw new Error(`${name} does not appear to be a ${this.config.bin} CLI plugin`); return path; } catch (err) { this.removePackageFromPJSON(name); this.out.error(err); throw new Error('unreachable'); } } async update() { await this.setupUserPlugins(); await this.yarn.exec(['upgrade']); } async remove(name) { await this.yarn.exec(['remove', name]); } addPackageToPJSON(name, version = '*') { let pjson = this.userPluginsPJSON; if (!pjson.dependencies) pjson.dependencies = {}; pjson.dependencies[name] = version; this.saveUserPluginsPJSON(pjson); } removePackageFromPJSON(name) { let pjson = this.userPluginsPJSON; if (!pjson.dependencies) pjson.dependencies = {}; delete pjson.dependencies[name]; this.saveUserPluginsPJSON(pjson); } get userPluginsDir() { return _path2.default.join(this.config.dataDir, 'plugins'); } get userPluginsPJSONPath() { return _path2.default.join(this.userPluginsDir, 'package.json'); } userPluginPath(name) { return _path2.default.join(this.userPluginsDir, 'node_modules', name); } } exports.default = UserPlugins; const entries = o => Object.keys(o).map(k => [k, o[k]]);