diff --git a/lib/dependency-manager-adapters/base.js b/lib/dependency-manager-adapters/base.js index 5df0e1a0..92e47372 100644 --- a/lib/dependency-manager-adapters/base.js +++ b/lib/dependency-manager-adapters/base.js @@ -9,6 +9,27 @@ const Backup = require('../utils/backup'); const { warn } = require('../utils/console'); const { LOCKFILE, PACKAGE_JSON } = require('../utils/package-managers'); +function merge(a, b) { + const copy = {...a}; + + for (const k in b) { + // for merging arrays, provide your own function + if (Array.isArray(k)) { + copy[k] = b[k]; + } + + else if (typeof b[k] === 'object') { + copy[k] = merge(a[k] ?? {}, b[k]); + } + + else { + copy[k] = b[k]; + } + } + + return copy; +} + class BaseAdapter { configKey = 'npm'; defaultInstallOptions = []; @@ -41,13 +62,37 @@ class BaseAdapter { await this.backup.addFiles([PACKAGE_JSON, this.lockfile]); } - async changeToDependencySet(dependencySet) { - await this.applyDependencySet(dependencySet); - await this._install(dependencySet); + async changePackage(packageJson) { + // packageJson can be a function + // this.debug('Change package with: %s', JSON.stringify(packageJson)); + + const oldPackageJSON = JSON.parse(fs.readFileSync(this.backup.pathForFile(PACKAGE_JSON))); + const newPackageJSON = this._applyPackageChanges(oldPackageJSON, packageJson); + this.debug('Write package.json with: \n', JSON.stringify(newPackageJSON)); + + fs.writeFileSync(path.join(this.cwd, PACKAGE_JSON), JSON.stringify(newPackageJSON, null, 2)); + + // find the delta of deps + // put in the delta here + await this._install({}); + + // ... and here + return this._findChangedDependencies(newPackageJSON); + } + + _applyPackageChanges(originalPackage, packageChanges) { + if (typeof packageChanges === 'function') { + return packageChanges(originalPackage); + } + + return merge(originalPackage, packageChanges); + } + + async _findChangedDependencies(packageJson) { const dependencies = { - ...dependencySet.dependencies, - ...dependencySet.devDependencies, + ...packageJson.dependencies, + ...packageJson.devDependencies, }; const currentDependencies = Object.keys(dependencies).map((name) => ({ @@ -58,8 +103,13 @@ class BaseAdapter { })); this.debug('Switched to dependencies: \n', currentDependencies); + } + + async changeToDependencySet(dependencySet) { + await this.applyDependencySet(dependencySet); + await this._install(dependencySet); - return currentDependencies; + return this._findChangedDependencies(dependencySet); } async applyDependencySet(dependencySet) { diff --git a/lib/utils/scenario-manager.js b/lib/utils/scenario-manager.js index 9ea99a8e..251256e6 100644 --- a/lib/utils/scenario-manager.js +++ b/lib/utils/scenario-manager.js @@ -15,6 +15,13 @@ module.exports = class ScenarioManager { let results = []; for (let depManager of this.dependencyManagerAdapters) { + if ('packageJson' in scenario) { + let depManagerResults = await depManager.changePackage( + scenario.packageJson + ); + results.push(...depManagerResults); + } + if (scenario[depManager.configKey]) { let depManagerResults = await depManager.changeToDependencySet( scenario[depManager.configKey],