ember-introjs
Version:
An Ember Component for intro.js
175 lines (150 loc) • 6.1 kB
JavaScript
'use strict';
var CoreObject = require('core-object');
var fs = require('fs-extra');
var RSVP = require('rsvp');
var path = require('path');
var extend = require('extend');
var debug = require('debug')('ember-try:dependency-manager-adapter:npm');
var rimraf = RSVP.denodeify(require('rimraf'));
var chalk = require('chalk');
module.exports = CoreObject.extend({
init: function() {
this._super.apply(this, arguments);
this.run = this.run || require('../utils/run');
},
useYarnCommand: false,
yarnLock: 'yarn.lock',
configKey: 'npm',
packageJSON: 'package.json',
packageJSONBackupFileName: 'package.json.ember-try',
nodeModules: 'node_modules',
nodeModulesBackupLocation: '.node_modules.ember-try',
setup: function(options) {
if (!options) {
options = {};
}
this._runYarnCheck(options.ui);
return this._backupOriginalDependencies();
},
changeToDependencySet: function(depSet) {
var adapter = this;
depSet = depSet[adapter.configKey];
debug('Changing to dependency set: %s', JSON.stringify(depSet));
if (!depSet) { return RSVP.resolve([]); }
var backupPackageJSON = path.join(adapter.cwd, adapter.packageJSONBackupFileName);
var packageJSONFile = path.join(adapter.cwd, adapter.packageJSON);
var packageJSON = JSON.parse(fs.readFileSync(backupPackageJSON));
var newPackageJSON = adapter._packageJSONForDependencySet(packageJSON, depSet);
debug('Write package.json with: \n', JSON.stringify(newPackageJSON));
fs.writeFileSync(packageJSONFile, JSON.stringify(newPackageJSON, null, 2));
return adapter._install().then(function() {
var deps = extend({}, depSet.dependencies || {}, depSet.devDependencies || {});
var currentDeps = Object.keys(deps).map(function(dep) {
return {
name: dep,
versionExpected: deps[dep],
versionSeen: adapter._findCurrentVersionOf(dep),
packageManager: adapter.useYarnCommand ? 'yarn' : 'npm'
};
});
debug('Switched to dependencies: \n', currentDeps);
return RSVP.Promise.resolve(currentDeps);
});
},
cleanup: function() {
var adapter = this;
return this._restoreOriginalDependencies().then(function() {
debug('Remove backup package.json and node_modules');
var cleanupTasks = [rimraf(path.join(adapter.cwd, adapter.packageJSONBackupFileName)),
rimraf(path.join(adapter.cwd, adapter.nodeModulesBackupLocation))];
return RSVP.all(cleanupTasks);
}).catch(function(e) {
console.log('Error cleaning up npm scenario:', e);
});
},
_runYarnCheck: function(ui) {
if (!this.useYarnCommand) {
try {
if (fs.statSync(path.join(this.cwd, this.yarnLock)).isFile()) {
ui.writeLine(chalk.yellow('Detected a yarn.lock file, add useYarn: true to your configuration if you want to use Yarn to install npm dependencies.'));
}
} catch (e) {
// If no yarn.lock is found, no need to warn.
}
}
},
_findCurrentVersionOf: function(packageName) {
var filename = path.join(this.cwd, this.nodeModules, packageName, this.packageJSON);
if (fs.existsSync(filename)) {
return JSON.parse(fs.readFileSync(filename)).version;
} else {
return null;
}
},
_install: function() {
var adapter = this;
var mgrOptions = this.managerOptions || [];
debug('Run npm install with options %s', mgrOptions);
var cmd = this.useYarnCommand ? 'yarn' : 'npm';
if (this.useYarnCommand) {
if (mgrOptions.indexOf('--no-lockfile') === -1) {
mgrOptions = mgrOptions.concat(['--no-lockfile']);
}
// npm warns on incompatible engines
// yarn errors, not a good experience
if (mgrOptions.indexOf('--ignore-engines') === -1) {
mgrOptions = mgrOptions.concat(['--ignore-engines']);
}
} else if (mgrOptions.indexOf('--no-shrinkwrap') === -1) {
mgrOptions = mgrOptions.concat(['--no-shrinkwrap']);
}
return this.run(cmd, [].concat(['install'], mgrOptions), { cwd: this.cwd }).then(function() {
if (!adapter.useYarnCommand) {
debug('Run npm prune');
return adapter.run(adapter.configKey, [].concat(['prune'], mgrOptions), { cwd: adapter.cwd });
}
});
},
_packageJSONForDependencySet: function(packageJSON, depSet) {
this._overridePackageJSONDependencies(packageJSON, depSet, 'dependencies');
this._overridePackageJSONDependencies(packageJSON, depSet, 'devDependencies');
this._overridePackageJSONDependencies(packageJSON, depSet, 'peerDependencies');
return packageJSON;
},
_overridePackageJSONDependencies: function(packageJSON, depSet, kindOfDependency) {
if (!depSet[kindOfDependency]) { return; }
var pkgs = Object.keys(depSet[kindOfDependency]);
pkgs.forEach(function(pkg) {
if (!packageJSON[kindOfDependency]) {
packageJSON[kindOfDependency] = {};
}
var version = depSet[kindOfDependency][pkg];
if (version === null) {
delete packageJSON[kindOfDependency][pkg];
} else {
packageJSON[kindOfDependency][pkg] = version;
}
});
},
_restoreOriginalDependencies: function() {
var copy = RSVP.denodeify(fs.copy);
debug('Restoring original package.json and node_modules');
var restoreTasks = [
copy(path.join(this.cwd, this.packageJSONBackupFileName),
path.join(this.cwd, this.packageJSON)),
copy(path.join(this.cwd, this.nodeModulesBackupLocation),
path.join(this.cwd, this.nodeModules), { clobber: true })
];
return RSVP.all(restoreTasks);
},
_backupOriginalDependencies: function() {
var copy = RSVP.denodeify(fs.copy);
debug('Backing up package.json and node_modules');
var backupTasks = [
copy(path.join(this.cwd, this.packageJSON),
path.join(this.cwd, this.packageJSONBackupFileName)),
copy(path.join(this.cwd, this.nodeModules),
path.join(this.cwd, this.nodeModulesBackupLocation), { clobber: true })];
return RSVP.all(backupTasks);
}
});