diff --git a/.eslintrc.js b/.eslintrc.js index 8a0755d0..650390c8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -39,10 +39,10 @@ module.exports = { browser: false, node: true }, - extends: ['plugin:node/recommended'], + extends: ['plugin:n/recommended'], rules: { // add your custom rules and overrides for node files here - 'no-process-exit': 'off' + 'n/no-process-exit': 'off' } }, // test files diff --git a/lib/dependency-manager-adapters/base.js b/lib/dependency-manager-adapters/base.js new file mode 100644 index 00000000..cb95f5fa --- /dev/null +++ b/lib/dependency-manager-adapters/base.js @@ -0,0 +1,177 @@ +'use strict'; + +const chalk = require('chalk'); +const debug = require('debug'); +const { get, set } = require('es-toolkit/compat'); +const fs = require('fs-extra'); +const path = require('node:path'); +const semver = require('semver'); +const Backup = require('../utils/backup'); +const { LOCKFILE, PACKAGE_JSON } = require('../utils/package-managers'); + +class BaseAdapter { + configKey = 'npm'; + defaultInstallOptions = []; + lockfile = ''; + name = ''; + overridesKey = ''; + + backup = null; + debugFunction = null; + + constructor(options) { + this.backup = new Backup({ cwd: options.cwd }); + this.buildManagerOptions = options.buildManagerOptions; + this.cwd = options.cwd; + this.managerOptions = options.managerOptions; + this.run = options.run ?? require('../utils/run'); + } + + debug(...args) { + if (this.debugFunction === null) { + this.debugFunction = debug(`ember-try:dependency-manager-adapter:${this.name}`); + } + + this.debugFunction(...args); + } + + async setup(options = {}) { + this._checkForDifferentLockfiles(options.ui); + + await this.backup.addFiles([PACKAGE_JSON, this.lockfile]); + } + + async changeToDependencySet(dependencySet) { + await this.applyDependencySet(dependencySet); + await this._install(dependencySet); + + const dependencies = { + ...dependencySet.dependencies, + ...dependencySet.devDependencies, + }; + + const currentDependencies = Object.keys(dependencies).map((name) => ({ + name, + packageManager: this.name, + versionExpected: dependencies[name], + versionSeen: this._findCurrentVersionOf(name), + })); + + this.debug('Switched to dependencies: \n', currentDependencies); + + return currentDependencies; + } + + async applyDependencySet(dependencySet) { + if (dependencySet === undefined) { + return; + } + + this.debug('Changing to dependency set: %s', JSON.stringify(dependencySet)); + + const oldPackageJSON = JSON.parse(fs.readFileSync(this.backup.pathForFile(PACKAGE_JSON))); + const newPackageJSON = this._packageJSONForDependencySet(oldPackageJSON, dependencySet); + + this.debug('Write package.json with: \n', JSON.stringify(newPackageJSON)); + + fs.writeFileSync(path.join(this.cwd, PACKAGE_JSON), JSON.stringify(newPackageJSON, null, 2)); + } + + async cleanup() { + try { + await this.backup.restoreFiles([PACKAGE_JSON, this.lockfile]); + await this.backup.cleanUp(); + await this._install(); + } catch (error) { + console.error('Error cleaning up scenario:', error); + } + } + + _checkForDifferentLockfiles(ui) { + for (const packageManager in LOCKFILE) { + const lockfile = LOCKFILE[packageManager]; + + if (lockfile === this.lockfile) { + continue; + } + + try { + if (fs.statSync(path.join(this.cwd, lockfile)).isFile()) { + ui.writeLine( + chalk.yellow( + `Detected a \`${lockfile}\` file. Add \`packageManager: '${packageManager}'\` to your \`config/ember-try.js\` configuration file if you want to use ${packageManager} to install dependencies.`, + ), + ); + } + } catch { + // Move along. + } + } + } + + _findCurrentVersionOf(name) { + const filename = path.join(this.cwd, 'node_modules', name, PACKAGE_JSON); + + if (fs.existsSync(filename)) { + return JSON.parse(fs.readFileSync(filename)).version; + } else { + return null; + } + } + + async _install(dependencySet) { + let managerOptions = this.managerOptions || []; + + if (typeof this.buildManagerOptions === 'function') { + managerOptions = this.buildManagerOptions(dependencySet); + + if (Array.isArray(managerOptions) === false) { + throw new Error('buildManagerOptions must return an array of options'); + } + } else if (this.defaultInstallOptions.length) { + for (const option of this.defaultInstallOptions) { + if (managerOptions.includes(option) === false) { + managerOptions.push(option); + } + } + } + + this.debug(`Running ${this.name} install with options %s`, managerOptions); + + await this.run(this.name, ['install', ...managerOptions], { cwd: this.cwd }); + } + + _packageJSONForDependencySet(packageJSON, dependencySet) { + this._overridePackageJSONDependencies(packageJSON, dependencySet, 'dependencies'); + this._overridePackageJSONDependencies(packageJSON, dependencySet, 'devDependencies'); + this._overridePackageJSONDependencies(packageJSON, dependencySet, 'peerDependencies'); + this._overridePackageJSONDependencies(packageJSON, dependencySet, 'ember'); + this._overridePackageJSONDependencies(packageJSON, dependencySet, this.overridesKey); + + return packageJSON; + } + + _overridePackageJSONDependencies(packageJSON, dependencySet, kindOfDependency) { + if (get(dependencySet, kindOfDependency) === undefined) { + return; + } + + let packageNames = Object.keys(get(dependencySet, kindOfDependency)); + + for (let packageName of packageNames) { + let version = get(dependencySet, `${kindOfDependency}.${packageName}`); + + if (version === null) { + delete get(packageJSON, kindOfDependency)[packageName]; + } else { + set(packageJSON, `${kindOfDependency}.${packageName}`, version); + + if (semver.prerelease(version) || /^https*:\/\/.*\.tg*z/.test(version)) { + set(packageJSON, `${this.overridesKey}.${packageName}`, `$${packageName}`); + } + } + } + } +} + +module.exports = { BaseAdapter }; diff --git a/lib/dependency-manager-adapters/npm.js b/lib/dependency-manager-adapters/npm.js index 064e4683..47d5e8c1 100644 --- a/lib/dependency-manager-adapters/npm.js +++ b/lib/dependency-manager-adapters/npm.js @@ -1,170 +1,11 @@ 'use strict'; -const fs = require('fs-extra'); -const path = require('path'); -const debug = require('debug')('ember-try:dependency-manager-adapter:npm'); -const chalk = require('chalk'); -const semver = require('semver'); -const Backup = require('../utils/backup'); - -module.exports = class { - configKey = 'npm'; - packageJSON = 'package.json'; - packageLock = 'package-lock.json'; - - constructor(options) { - this.buildManagerOptions = options.buildManagerOptions; - this.cwd = options.cwd; - this.managerOptions = options.managerOptions; - this.run = options.run || require('../utils/run'); - - this.backup = new Backup({ cwd: this.cwd }); - } - - async setup(options) { - if (!options) { - options = {}; - } - - this._runYarnCheck(options.ui); - - return await this._backupOriginalDependencies(); - } - - async changeToDependencySet(depSet) { - this.applyDependencySet(depSet); - - await this._install(depSet); - - let deps = Object.assign({}, depSet.dependencies, depSet.devDependencies); - let currentDeps = Object.keys(deps).map((dep) => { - return { - name: dep, - versionExpected: deps[dep], - versionSeen: this._findCurrentVersionOf(dep), - packageManager: 'npm', - }; - }); - - debug('Switched to dependencies: \n', currentDeps); - - return currentDeps; - } - - async cleanup() { - try { - await this._restoreOriginalDependencies(); - } catch (e) { - console.log('Error cleaning up npm scenario:', e); // eslint-disable-line no-console - } - } - - _runYarnCheck(ui) { - try { - if (fs.statSync(path.join(this.cwd, 'yarn.lock')).isFile()) { - ui.writeLine( - chalk.yellow( - "Detected a yarn.lock file. Add `packageManager: 'yarn'` to your `config/ember-try.js` configuration file if you want to use Yarn to install npm dependencies.", - ), - ); - } - } catch { - // If no yarn.lock is found, no need to warn. - } - } - - _findCurrentVersionOf(packageName) { - let filename = path.join(this.cwd, 'node_modules', packageName, this.packageJSON); - if (fs.existsSync(filename)) { - return JSON.parse(fs.readFileSync(filename)).version; - } else { - return null; - } - } - - async _install(depSet) { - let mgrOptions = this.managerOptions || []; - - // buildManagerOptions overrides all default - if (typeof this.buildManagerOptions === 'function') { - mgrOptions = this.buildManagerOptions(depSet); - - if (!Array.isArray(mgrOptions)) { - throw new Error('buildManagerOptions must return an array of options'); - } - } else if (mgrOptions.indexOf('--no-package-lock') === -1) { - mgrOptions = mgrOptions.concat(['--no-package-lock']); - } - - debug('Run npm install with options %s', mgrOptions); - - await this.run('npm', [].concat(['install'], mgrOptions), { cwd: this.cwd }); - } - - applyDependencySet(depSet) { - debug('Changing to dependency set: %s', JSON.stringify(depSet)); - - if (!depSet) { - return; - } - - let backupPackageJSON = this.backup.pathForFile(this.packageJSON); - let packageJSONFile = path.join(this.cwd, this.packageJSON); - let packageJSON = JSON.parse(fs.readFileSync(backupPackageJSON)); - let newPackageJSON = this._packageJSONForDependencySet(packageJSON, depSet); - - debug('Write package.json with: \n', JSON.stringify(newPackageJSON)); - - fs.writeFileSync(packageJSONFile, JSON.stringify(newPackageJSON, null, 2)); - } - - _packageJSONForDependencySet(packageJSON, depSet) { - this._overridePackageJSONDependencies(packageJSON, depSet, 'dependencies'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'devDependencies'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'peerDependencies'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'ember'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'overrides'); - - return packageJSON; - } - - _overridePackageJSONDependencies(packageJSON, depSet, kindOfDependency) { - if (!depSet[kindOfDependency]) { - return; - } - - let packageNames = Object.keys(depSet[kindOfDependency]); - - packageNames.forEach((packageName) => { - if (!packageJSON[kindOfDependency]) { - packageJSON[kindOfDependency] = {}; - } - - let version = depSet[kindOfDependency][packageName]; - if (version === null) { - delete packageJSON[kindOfDependency][packageName]; - } else { - packageJSON[kindOfDependency][packageName] = version; - - // in npm we need to always add an override if the version is a pre-release - if (semver.prerelease(version) || /^https*:\/\/.*\.tg*z/.test(version)) { - if (!packageJSON.overrides) { - packageJSON.overrides = {}; - } - - packageJSON.overrides[packageName] = `$${packageName}`; - } - } - }); - } - - async _restoreOriginalDependencies() { - await this.backup.restoreFiles([this.packageJSON, this.packageLock]); - await this.backup.cleanUp(); - await this._install(); - } - - async _backupOriginalDependencies() { - await this.backup.addFiles([this.packageJSON, this.packageLock]); - } +const { LOCKFILE } = require('../utils/package-managers'); +const { BaseAdapter } = require('./base'); + +module.exports = class NpmAdapter extends BaseAdapter { + defaultInstallOptions = ['--no-package-lock']; + lockfile = LOCKFILE.npm; + name = 'npm'; + overridesKey = 'overrides'; }; diff --git a/lib/dependency-manager-adapters/pnpm.js b/lib/dependency-manager-adapters/pnpm.js index 81517150..891f0053 100644 --- a/lib/dependency-manager-adapters/pnpm.js +++ b/lib/dependency-manager-adapters/pnpm.js @@ -1,70 +1,18 @@ 'use strict'; -const fs = require('fs-extra'); -const path = require('path'); -const debug = require('debug')('ember-try:dependency-manager-adapter:pnpm'); -const Backup = require('../utils/backup'); -const semverLt = require('semver/functions/lt'); -const semverGte = require('semver/functions/gte'); +const semver = require('semver'); +const { LOCKFILE } = require('../utils/package-managers'); +const { BaseAdapter } = require('./base'); -const PACKAGE_JSON = 'package.json'; -const PNPM_LOCKFILE = 'pnpm-lock.yaml'; +module.exports = class PnpmAdapter extends BaseAdapter { + defaultInstallOptions = ['--no-lockfile', '--ignore-scripts']; + lockfile = LOCKFILE.pnpm; + name = 'pnpm'; + overridesKey = 'pnpm.overrides'; -module.exports = class { - // This still needs to be `npm` because we're still reading the dependencies - // from the `npm` key of the ember-try config. - configKey = 'npm'; - - constructor(options) { - this.buildManagerOptions = options.buildManagerOptions; - this.cwd = options.cwd; - this.managerOptions = options.managerOptions; - this.run = options.run || require('../utils/run'); - - this.backup = new Backup({ cwd: this.cwd }); - } - - async setup() { + async setup(options) { await this._throwOnResolutionMode(); - await this.backup.addFiles([PACKAGE_JSON, PNPM_LOCKFILE]); - } - - async changeToDependencySet(depSet) { - await this.applyDependencySet(depSet); - await this._install(depSet); - - let deps = Object.assign({}, depSet.dependencies, depSet.devDependencies); - let currentDeps = Object.keys(deps).map((dep) => { - return { - name: dep, - versionExpected: deps[dep], - versionSeen: this._findCurrentVersionOf(dep), - packageManager: 'pnpm', - }; - }); - - debug('Switched to dependencies: \n', currentDeps); - - return currentDeps; - } - - async cleanup() { - try { - await this.backup.restoreFiles([PACKAGE_JSON, PNPM_LOCKFILE]); - await this.backup.cleanUp(); - await this._install(); - } catch (e) { - console.log('Error cleaning up scenario:', e); // eslint-disable-line no-console - } - } - - _findCurrentVersionOf(packageName) { - let filename = path.join(this.cwd, 'node_modules', packageName, PACKAGE_JSON); - if (fs.existsSync(filename)) { - return JSON.parse(fs.readFileSync(filename)).version; - } else { - return null; - } + await super.setup(options); } /** @@ -103,92 +51,14 @@ module.exports = class { _isResolutionModeWrong(versionStr, resolutionMode) { // The `resolution-mode` is not set explicitly, and the current pnpm version makes it default // to `lowest-direct` - if (!resolutionMode.length && semverGte(versionStr, '8.0.0') && semverLt(versionStr, '8.7.0')) { + if ( + !resolutionMode.length && + semver.gte(versionStr, '8.0.0') && + semver.lt(versionStr, '8.7.0') + ) { return true; } return false; } - - async _install(depSet) { - let mgrOptions = this.managerOptions || []; - - // buildManagerOptions overrides all default - if (typeof this.buildManagerOptions === 'function') { - mgrOptions = this.buildManagerOptions(depSet); - - if (!Array.isArray(mgrOptions)) { - throw new Error('buildManagerOptions must return an array of options'); - } - } else { - if (!mgrOptions.includes('--no-lockfile')) { - mgrOptions.push('--no-lockfile'); - } - - if (!mgrOptions.includes('--ignore-scripts')) { - mgrOptions.push('--ignore-scripts'); - } - } - - // Note: We are explicitly *not* using `--no-lockfile` here, so that we - // only have to resolve the dependencies that have actually changed. - - debug('Run pnpm install with options %s', mgrOptions); - - await this.run('pnpm', [].concat(['install'], mgrOptions), { cwd: this.cwd }); - } - - async applyDependencySet(depSet) { - debug('Changing to dependency set: %s', JSON.stringify(depSet)); - - if (!depSet) { - return; - } - - let backupPackageJSON = this.backup.pathForFile(PACKAGE_JSON); - let packageJSONFile = path.join(this.cwd, PACKAGE_JSON); - let packageJSON = JSON.parse(fs.readFileSync(backupPackageJSON)); - let newPackageJSON = this._packageJSONForDependencySet(packageJSON, depSet); - - debug('Write package.json with: \n', JSON.stringify(newPackageJSON)); - fs.writeFileSync(packageJSONFile, JSON.stringify(newPackageJSON, null, 2)); - - // We restore the original lockfile here, so that we always create a minimal - // diff compared to the original locked dependency set. - - await this.backup.restoreFile(PNPM_LOCKFILE); - } - - _packageJSONForDependencySet(packageJSON, depSet) { - this._overridePackageJSONDependencies(packageJSON, depSet, 'dependencies'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'devDependencies'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'peerDependencies'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'ember'); - - // see https://pnpm.io/package_json#pnpmoverrides - this._overridePackageJSONDependencies(packageJSON, depSet, 'overrides'); - - return packageJSON; - } - - _overridePackageJSONDependencies(packageJSON, depSet, kindOfDependency) { - if (!depSet[kindOfDependency]) { - return; - } - - let packageNames = Object.keys(depSet[kindOfDependency]); - - for (let packageName of packageNames) { - if (!packageJSON[kindOfDependency]) { - packageJSON[kindOfDependency] = {}; - } - - let version = depSet[kindOfDependency][packageName]; - if (version === null) { - delete packageJSON[kindOfDependency][packageName]; - } else { - packageJSON[kindOfDependency][packageName] = version; - } - } - } }; diff --git a/lib/dependency-manager-adapters/workspace.js b/lib/dependency-manager-adapters/workspace.js index f70b4a28..38c03457 100644 --- a/lib/dependency-manager-adapters/workspace.js +++ b/lib/dependency-manager-adapters/workspace.js @@ -4,12 +4,10 @@ const fs = require('fs-extra'); const path = require('path'); const debug = require('debug')('ember-try:dependency-manager-adapter:workspaces'); const walkSync = require('walk-sync'); - +const { PACKAGE_JSON } = require('../utils/package-managers'); const YarnAdapter = require('./yarn'); module.exports = class { - packageJSON = 'package.json'; - constructor(options) { this.buildManagerOptions = options.buildManagerOptions; this.cwd = options.cwd; @@ -21,7 +19,8 @@ module.exports = class { 'workspaces are currently only supported by Yarn, you must set `packageManager` to `yarn`', ); } - let packageJSON = JSON.parse(fs.readFileSync(this.packageJSON)); + + let packageJSON = JSON.parse(fs.readFileSync(PACKAGE_JSON)); let workspaceGlobs; if (Array.isArray(packageJSON.workspaces)) { @@ -56,10 +55,6 @@ module.exports = class { } setup(options) { - if (!options) { - options = {}; - } - return Promise.all(this._packageAdapters.map((adapter) => adapter.setup(options))); } diff --git a/lib/dependency-manager-adapters/yarn.js b/lib/dependency-manager-adapters/yarn.js index e2c5af23..5e775e16 100644 --- a/lib/dependency-manager-adapters/yarn.js +++ b/lib/dependency-manager-adapters/yarn.js @@ -1,150 +1,11 @@ 'use strict'; -const fs = require('fs-extra'); -const path = require('path'); -const debug = require('debug')('ember-try:dependency-manager-adapter:yarn'); -const Backup = require('../utils/backup'); - -module.exports = class { - configKey = 'npm'; // Still use `npm` for now! - packageJSON = 'package.json'; - yarnLock = 'yarn.lock'; - - constructor(options) { - this.buildManagerOptions = options.buildManagerOptions; - this.cwd = options.cwd; - this.managerOptions = options.managerOptions; - this.run = options.run || require('../utils/run'); - - this.backup = new Backup({ cwd: this.cwd }); - } - - async setup(options) { - if (!options) { - options = {}; - } - - return await this._backupOriginalDependencies(); - } - - async changeToDependencySet(depSet) { - this.applyDependencySet(depSet); - - await this._install(depSet); - - let deps = Object.assign({}, depSet.dependencies, depSet.devDependencies); - let currentDeps = Object.keys(deps).map((dep) => { - return { - name: dep, - versionExpected: deps[dep], - versionSeen: this._findCurrentVersionOf(dep), - packageManager: 'yarn', - }; - }); - - debug('Switched to dependencies: \n', currentDeps); - - return currentDeps; - } - - async cleanup() { - try { - await this._restoreOriginalDependencies(); - } catch (e) { - console.log('Error cleaning up npm scenario:', e); // eslint-disable-line no-console - } - } - - _findCurrentVersionOf(packageName) { - let filename = path.join(this.cwd, 'node_modules', packageName, this.packageJSON); - if (fs.existsSync(filename)) { - return JSON.parse(fs.readFileSync(filename)).version; - } else { - return null; - } - } - - async _install(depSet) { - let mgrOptions = this.managerOptions || []; - - // buildManagerOptions overrides all default - if (typeof this.buildManagerOptions === 'function') { - mgrOptions = this.buildManagerOptions(depSet); - - if (!Array.isArray(mgrOptions)) { - throw new Error('buildManagerOptions must return an array of options'); - } - } else { - if (mgrOptions.indexOf('--no-lockfile') === -1) { - mgrOptions = mgrOptions.concat(['--no-lockfile']); - } - - // yarn errors on incompatible engines, not a good experience - if (mgrOptions.indexOf('--ignore-engines') === -1) { - mgrOptions = mgrOptions.concat(['--ignore-engines']); - } - } - - debug('Run yarn install with options %s', mgrOptions); - - await this.run('yarn', [].concat(['install'], mgrOptions), { cwd: this.cwd }); - } - - applyDependencySet(depSet) { - debug('Changing to dependency set: %s', JSON.stringify(depSet)); - - if (!depSet) { - return; - } - - let backupPackageJSON = this.backup.pathForFile(this.packageJSON); - let packageJSONFile = path.join(this.cwd, this.packageJSON); - let packageJSON = JSON.parse(fs.readFileSync(backupPackageJSON)); - let newPackageJSON = this._packageJSONForDependencySet(packageJSON, depSet); - - debug('Write package.json with: \n', JSON.stringify(newPackageJSON)); - - fs.writeFileSync(packageJSONFile, JSON.stringify(newPackageJSON, null, 2)); - } - - _packageJSONForDependencySet(packageJSON, depSet) { - this._overridePackageJSONDependencies(packageJSON, depSet, 'dependencies'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'devDependencies'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'peerDependencies'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'ember'); - this._overridePackageJSONDependencies(packageJSON, depSet, 'resolutions'); - - return packageJSON; - } - - _overridePackageJSONDependencies(packageJSON, depSet, kindOfDependency) { - if (!depSet[kindOfDependency]) { - return; - } - - let packageNames = Object.keys(depSet[kindOfDependency]); - - packageNames.forEach((packageName) => { - if (!packageJSON[kindOfDependency]) { - packageJSON[kindOfDependency] = {}; - } - - let version = depSet[kindOfDependency][packageName]; - if (version === null) { - delete packageJSON[kindOfDependency][packageName]; - } else { - packageJSON[kindOfDependency][packageName] = version; - } - }); - } - - async _restoreOriginalDependencies() { - await this.backup.restoreFiles([this.packageJSON, this.yarnLock]); - await this.backup.cleanUp(); - await this._install(); - } - - async _backupOriginalDependencies() { - await this.backup.addFiles([this.packageJSON, this.yarnLock]); - } +const { LOCKFILE } = require('../utils/package-managers'); +const { BaseAdapter } = require('./base'); + +module.exports = class YarnAdapter extends BaseAdapter { + defaultInstallOptions = ['--no-lockfile', '--ignore-engines']; + lockfile = LOCKFILE.yarn; + name = 'yarn'; + overridesKey = 'resolutions'; }; diff --git a/lib/utils/package-managers.js b/lib/utils/package-managers.js new file mode 100644 index 00000000..ab17cf24 --- /dev/null +++ b/lib/utils/package-managers.js @@ -0,0 +1,9 @@ +const LOCKFILE = { + npm: 'package-lock.json', + pnpm: 'pnpm-lock.yaml', + yarn: 'yarn.lock', +}; + +const PACKAGE_JSON = 'package.json'; + +module.exports = { LOCKFILE, PACKAGE_JSON }; diff --git a/package.json b/package.json index 798ef749..720ec6f6 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "cli-table3": "^0.6.5", "debug": "^4.4.0", "ember-try-config": "^4.0.0", + "es-toolkit": "^1.29.0", "execa": "^4.1.0", "fs-extra": "^6.0.1", "resolve": "^1.22.8", @@ -42,6 +43,7 @@ "walk-sync": "^2.2.0" }, "devDependencies": { + "@babel/core": "^7.26.0", "@babel/eslint-parser": "^7.25.9", "@release-it-plugins/lerna-changelog": "^7.0.0", "chai": "^4.4.1", @@ -50,7 +52,7 @@ "ember-cli": "~5.12.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-node": "^11.1.0", + "eslint-plugin-n": "^17.15.0", "eslint-plugin-prettier": "^5.2.1", "mocha": "^10.8.2", "mockery": "^2.1.0", diff --git a/test/dependency-manager-adapters/npm-adapter-test.js b/test/dependency-manager-adapters/npm-adapter-test.js index b30fd9b8..f70c1123 100644 --- a/test/dependency-manager-adapters/npm-adapter-test.js +++ b/test/dependency-manager-adapters/npm-adapter-test.js @@ -144,7 +144,7 @@ describe('npm Adapter', () => { }); }); - describe('#_restoreOriginalDependencies', () => { + describe('#cleanup', () => { it('restores the `package.json` and `package-lock.json` files if they exist', async () => { writeJSONFile('package.json', { originalPackageJSON: true }); writeJSONFile('package-lock.json', { originalPackageLock: true }); @@ -157,7 +157,7 @@ describe('npm Adapter', () => { writeJSONFile('package.json', { originalPackageJSON: false }); writeJSONFile('package-lock.json', { originalPackageLock: false }); - await adapter._restoreOriginalDependencies(); + await adapter.cleanup(); assertFileContainsJSON(path.join(tmpdir, 'package.json'), { originalPackageJSON: true, @@ -187,7 +187,7 @@ describe('npm Adapter', () => { run: stubbedRun, }); - await adapter._restoreOriginalDependencies(); + await adapter.cleanup(); expect(runCount).to.equal(1); }); diff --git a/test/dependency-manager-adapters/pnpm-adapter-test.js b/test/dependency-manager-adapters/pnpm-adapter-test.js index ee134d7f..bd16a80e 100644 --- a/test/dependency-manager-adapters/pnpm-adapter-test.js +++ b/test/dependency-manager-adapters/pnpm-adapter-test.js @@ -349,12 +349,14 @@ describe('pnpm Adapter', () => { }; let depSet = { dependencies: { 'ember-cli-babel': '6.0.0' }, - overrides: { 'ember-cli-babel': '6.0.0' }, + pnpm: { + overrides: { 'ember-cli-babel': '6.0.0' }, + }, }; let resultJSON = adapter._packageJSONForDependencySet(packageJSON, depSet); - expect(resultJSON.overrides['ember-cli-babel']).to.equal('6.0.0'); + expect(resultJSON.pnpm.overrides['ember-cli-babel']).to.equal('6.0.0'); }); it('removes a dependency from overrides if its version is null', () => { @@ -363,16 +365,20 @@ describe('pnpm Adapter', () => { }); let packageJSON = { dependencies: { 'ember-cli-babel': '5.0.0' }, - overrides: { 'ember-cli-babel': '5.0.0' }, + pnpm: { + overrides: { 'ember-cli-babel': '5.0.0' }, + }, }; let depSet = { dependencies: { 'ember-cli-babel': '6.0.0' }, - overrides: { 'ember-cli-babel': null }, + pnpm: { + overrides: { 'ember-cli-babel': null }, + }, }; let resultJSON = adapter._packageJSONForDependencySet(packageJSON, depSet); - expect(resultJSON.overrides['ember-cli-babel']).to.be.undefined; + expect(resultJSON.pnpm.overrides['ember-cli-babel']).to.be.undefined; }); it('changes specified npm dev dependency versions', () => { diff --git a/test/dependency-manager-adapters/workspace-adapter-test.js b/test/dependency-manager-adapters/workspace-adapter-test.js index 6f13a3aa..be34e08f 100644 --- a/test/dependency-manager-adapters/workspace-adapter-test.js +++ b/test/dependency-manager-adapters/workspace-adapter-test.js @@ -238,7 +238,7 @@ describe('workspace Adapter', () => { let adapter = workspaceAdapter._packageAdapters[0]; - await adapter._backupOriginalDependencies(); + await adapter.setup(); // Simulate modifying the file: writeJSONFile('packages/test/package.json', { originalPackageJSON: false }); diff --git a/test/dependency-manager-adapters/yarn-adapter-test.js b/test/dependency-manager-adapters/yarn-adapter-test.js index 55ad3516..665a431a 100644 --- a/test/dependency-manager-adapters/yarn-adapter-test.js +++ b/test/dependency-manager-adapters/yarn-adapter-test.js @@ -144,7 +144,7 @@ describe('yarn Adapter', () => { }); }); - describe('#_restoreOriginalDependencies', () => { + describe('#cleanup', () => { it('restores the `package.json` and `yarn.lock` files if they exist', async () => { writeJSONFile('package.json', { originalPackageJSON: true }); writeJSONFile('yarn.lock', { originalYarnLock: true }); @@ -157,7 +157,7 @@ describe('yarn Adapter', () => { writeJSONFile('package.json', { originalPackageJSON: false }); writeJSONFile('yarn.lock', { originalYarnLock: false }); - await adapter._restoreOriginalDependencies(); + await adapter.cleanup(); assertFileContainsJSON(path.join(tmpdir, 'package.json'), { originalPackageJSON: true, @@ -187,7 +187,7 @@ describe('yarn Adapter', () => { run: stubbedRun, }); - await adapter._restoreOriginalDependencies(); + await adapter.cleanup(); expect(runCount).to.equal(1); }); diff --git a/test/tasks/try-each-test.js b/test/tasks/try-each-test.js index 21d0cc3a..11beb377 100644 --- a/test/tasks/try-each-test.js +++ b/test/tasks/try-each-test.js @@ -97,7 +97,7 @@ describe('tryEach', () => { return tryEachTask.run(config.scenarios, {}).then((exitCode) => { expect(exitCode).to.equal(0, 'exits 0 when all scenarios succeed'); expect(output).to.include( - "Detected a yarn.lock file. Add `packageManager: 'yarn'` to your `config/ember-try.js` configuration file if you want to use Yarn to install npm dependencies.", + "Detected a `yarn.lock` file. Add `packageManager: 'yarn'` to your `config/ember-try.js` configuration file if you want to use yarn to install dependencies.", ); expect(output).to.include('Scenario first: SUCCESS'); expect(output).to.include('Scenario second: SUCCESS'); diff --git a/yarn.lock b/yarn.lock index eddba9af..c2138598 100644 --- a/yarn.lock +++ b/yarn.lock @@ -70,7 +70,7 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/core@^7.23.9": +"@babel/core@^7.23.9", "@babel/core@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== @@ -460,6 +460,13 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== +"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.4.1": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== + dependencies: + eslint-visitor-keys "^3.4.3" + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -467,6 +474,11 @@ dependencies: eslint-visitor-keys "^3.3.0" +"@eslint-community/regexpp@^4.11.0": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + "@eslint-community/regexpp@^4.6.1": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" @@ -3111,6 +3123,14 @@ engine.io@~6.5.2: engine.io-parser "~5.2.1" ws "~8.11.0" +enhanced-resolve@^5.17.1: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + ensure-posix-path@^1.0.0, ensure-posix-path@^1.0.1, ensure-posix-path@^1.0.2, ensure-posix-path@^1.1.0, ensure-posix-path@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ensure-posix-path/-/ensure-posix-path-1.1.1.tgz#3c62bdb19fa4681544289edb2b382adc029179ce" @@ -3157,6 +3177,11 @@ es-errors@^1.3.0: resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== +es-toolkit@^1.29.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.29.0.tgz#a9c54e87880002e4186560fe0a567e76a61cb61a" + integrity sha512-GjTll+E6APcfAQA09D89HdT8Qn2Yb+TeDSDBTMcxAo+V+w1amAtCI15LJu4YPH/UCPoSo/F47Gr1LIM0TE0lZA== + es6-error@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" @@ -3203,30 +3228,40 @@ escodegen@^2.1.0: optionalDependencies: source-map "~0.6.1" +eslint-compat-utils@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz#7fc92b776d185a70c4070d03fd26fde3d59652e4" + integrity sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q== + dependencies: + semver "^7.5.4" + eslint-config-prettier@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== -eslint-plugin-es@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" - integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== - dependencies: - eslint-utils "^2.0.0" - regexpp "^3.0.0" - -eslint-plugin-node@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" - integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== - dependencies: - eslint-plugin-es "^3.0.0" - eslint-utils "^2.0.0" - ignore "^5.1.1" - minimatch "^3.0.4" - resolve "^1.10.1" - semver "^6.1.0" +eslint-plugin-es-x@^7.8.0: + version "7.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz#a207aa08da37a7923f2a9599e6d3eb73f3f92b74" + integrity sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ== + dependencies: + "@eslint-community/eslint-utils" "^4.1.2" + "@eslint-community/regexpp" "^4.11.0" + eslint-compat-utils "^0.5.1" + +eslint-plugin-n@^17.15.0: + version "17.15.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-n/-/eslint-plugin-n-17.15.0.tgz#c6ab639a7d7761085cff05313753413d898b087e" + integrity sha512-xF3zJkOfLlFOm5TvmqmsnA9/fO+/z2pYs0dkuKXKN/ymS6UB1yEcaoIkqxLKQ9Dw/WmLX/Tdh6/5ZS5azVixFQ== + dependencies: + "@eslint-community/eslint-utils" "^4.4.1" + enhanced-resolve "^5.17.1" + eslint-plugin-es-x "^7.8.0" + get-tsconfig "^4.8.1" + globals "^15.11.0" + ignore "^5.3.2" + minimatch "^9.0.5" + semver "^7.6.3" eslint-plugin-prettier@^5.2.1: version "5.2.1" @@ -3252,18 +3287,6 @@ eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" @@ -4144,6 +4167,13 @@ get-stream@^8.0.1: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== +get-tsconfig@^4.8.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.8.1.tgz#8995eb391ae6e1638d251118c7b56de7eb425471" + integrity sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg== + dependencies: + resolve-pkg-maps "^1.0.0" + get-uri@^6.0.1: version "6.0.3" resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.3.tgz#0d26697bc13cf91092e519aa63aa60ee5b6f385a" @@ -4271,6 +4301,11 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globals@^15.11.0: + version "15.13.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.13.0.tgz#bbec719d69aafef188ecd67954aae76a696010fc" + integrity sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g== + globby@10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.0.tgz#abfcd0630037ae174a88590132c2f6804e291072" @@ -4341,7 +4376,7 @@ graceful-fs@^4.2.0: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -graceful-fs@^4.2.11: +graceful-fs@^4.2.11, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -4702,6 +4737,11 @@ ignore@^5.2.0, ignore@^5.2.4: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== +ignore@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== + import-fresh@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" @@ -6139,6 +6179,13 @@ minimatch@^7.4.3: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.5: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" @@ -7331,11 +7378,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== - registry-auth-token@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.0.tgz#1d37dffda72bbecd0f581e4715540213a65eb7da" @@ -7487,12 +7529,17 @@ resolve-path@^1.4.0: http-errors "~1.6.2" path-is-absolute "1.0.1" +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.1: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.1: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -7709,7 +7756,7 @@ semver@^5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== -semver@^6.0.0, semver@^6.1.0, semver@^6.2.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -8382,6 +8429,11 @@ tap-parser@^7.0.0: js-yaml "^3.2.7" minipass "^2.2.0" +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + tar@^6.0.2: version "6.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"