From fd5b92b3cd40361daec5bf4486e455a41f4c9738 Mon Sep 17 00:00:00 2001 From: Anshuman Verma Date: Sat, 10 Oct 2020 09:51:44 +0530 Subject: [PATCH] fix: cleanup `package-utils` package (#1822) This commit removes the redundant `package-utils` package and moves the shared outing utils to the core CLI. This is because we felt the package was redundant and this seemed like the better way of doing things. All the tests and code has been migrated to core CLI and any packages which use it directly read it from the main CLI package. --- .eslintignore | 3 +- .gitignore | 2 + .../__tests__/addon-generator.test.ts | 4 +- packages/generators/package.json | 1 - packages/generators/src/addon-generator.ts | 2 +- packages/generators/src/init-generator.ts | 2 +- packages/generators/tsconfig.json | 2 +- packages/package-utils/CHANGELOG.md | 34 ---- packages/package-utils/README.md | 11 -- .../package-utils/__tests__/index.test.ts | 26 --- .../__tests__/packageUtils.test.ts | 183 ------------------ packages/package-utils/package.json | 57 ------ packages/package-utils/src/index.ts | 2 - packages/package-utils/src/packageUtils.ts | 102 ---------- packages/package-utils/tsconfig.json | 8 - .../__tests__/global-packages-path.test.ts | 34 ++++ packages/utils/package.json | 24 ++- packages/utils/src/global-packages-path.ts | 25 +++ packages/utils/src/index.ts | 1 + packages/utils/src/modify-config-helper.ts | 2 +- packages/utils/src/npm-packages-exists.ts | 2 +- packages/utils/src/resolve-packages.ts | 3 +- packages/utils/src/scaffold.ts | 2 +- .../src/spawn-child.ts} | 16 +- packages/utils/tsconfig.json | 3 +- packages/webpack-cli/bin/cli.js | 3 +- .../lib/commands/resolveCommand.js | 3 +- .../webpack-cli/lib/groups/resolveAdvanced.js | 3 +- packages/webpack-cli/lib/utils/Compiler.js | 2 +- .../__tests__/get-package-manager.test.js | 78 ++++++++ .../utils/__tests__/package-exists.test.js | 22 +++ .../__tests__/prompt-installation.test.js | 82 ++++++++ .../__tests__/test-both/package-lock.json} | 0 .../lib/utils/__tests__/test-both}/yarn.lock | 0 .../__tests__/test-npm-lock/package-lock.json | 0 .../utils/__tests__/test-yarn-lock/yarn.lock | 0 packages/webpack-cli/lib/utils/cli-flags.js | 2 +- .../lib/utils/get-package-manager.js | 35 ++++ .../webpack-cli/lib/utils/package-exists.js | 12 ++ .../lib/utils/prompt-installation.js | 40 ++++ packages/webpack-cli/lib/utils/run-command.js | 16 ++ packages/webpack-cli/package.json | 1 - tsconfig.json | 1 - yarn.lock | 13 +- 44 files changed, 399 insertions(+), 465 deletions(-) delete mode 100644 packages/package-utils/CHANGELOG.md delete mode 100644 packages/package-utils/README.md delete mode 100644 packages/package-utils/__tests__/index.test.ts delete mode 100644 packages/package-utils/__tests__/packageUtils.test.ts delete mode 100644 packages/package-utils/package.json delete mode 100644 packages/package-utils/src/index.ts delete mode 100644 packages/package-utils/src/packageUtils.ts delete mode 100644 packages/package-utils/tsconfig.json create mode 100644 packages/utils/__tests__/global-packages-path.test.ts create mode 100644 packages/utils/src/global-packages-path.ts rename packages/{package-utils/src/processUtils.ts => utils/src/spawn-child.ts} (73%) create mode 100644 packages/webpack-cli/lib/utils/__tests__/get-package-manager.test.js create mode 100644 packages/webpack-cli/lib/utils/__tests__/package-exists.test.js create mode 100644 packages/webpack-cli/lib/utils/__tests__/prompt-installation.test.js rename packages/{package-utils/__tests__/test-both/yarn.lock => webpack-cli/lib/utils/__tests__/test-both/package-lock.json} (100%) rename packages/{package-utils/__tests__/test-yarn-lock => webpack-cli/lib/utils/__tests__/test-both}/yarn.lock (100%) create mode 100644 packages/webpack-cli/lib/utils/__tests__/test-npm-lock/package-lock.json create mode 100644 packages/webpack-cli/lib/utils/__tests__/test-yarn-lock/yarn.lock create mode 100644 packages/webpack-cli/lib/utils/get-package-manager.js create mode 100644 packages/webpack-cli/lib/utils/package-exists.js create mode 100644 packages/webpack-cli/lib/utils/prompt-installation.js create mode 100644 packages/webpack-cli/lib/utils/run-command.js diff --git a/.eslintignore b/.eslintignore index 447742e4312..aafbffa5401 100644 --- a/.eslintignore +++ b/.eslintignore @@ -7,7 +7,6 @@ packages/generators/lib packages/info/lib packages/init/lib packages/migrate/lib -packages/package-utils/lib packages/serve/lib packages/utils/lib packages/webpack-scaffold/lib @@ -28,4 +27,4 @@ test/loader/test-loader/examples/simple/webpack.config.js test/loader/test-loader/examples/simple/src/static-esm-module.js test/loader/test-loader/examples/simple/src/lazy-module.js test/loader/test-loader/examples/simple/example_dist/** -lib/test/loader/error-test/src/index.d.ts \ No newline at end of file +lib/test/loader/error-test/src/index.d.ts diff --git a/.gitignore b/.gitignore index f810ae20a0e..efdfb260487 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,8 @@ packages/**/*.map # build files packages/**/lib packages/**/yarn.lock +!packages/webpack-cli/lib/utils/__tests__/**/yarn.lock +!packages/webpack-cli/lib/utils/__tests__/**/package-lock.json !packages/webpack-cli/lib # test output files diff --git a/packages/generators/__tests__/addon-generator.test.ts b/packages/generators/__tests__/addon-generator.test.ts index 1c2045567dc..d0958cd59f9 100644 --- a/packages/generators/__tests__/addon-generator.test.ts +++ b/packages/generators/__tests__/addon-generator.test.ts @@ -1,4 +1,4 @@ -jest.setMock('@webpack-cli/package-utils', { +jest.setMock('@webpack-cli/utils', { getPackageManager: jest.fn(), }); @@ -6,7 +6,7 @@ import fs from 'fs'; import path from 'path'; import mkdirp from 'mkdirp'; import rimraf from 'rimraf'; -import { getPackageManager } from '@webpack-cli/package-utils'; +import { getPackageManager } from 'webpack-cli/lib/utils/get-package-manager'; import addonGenerator from '../src/addon-generator'; // TODO: enable after jest release diff --git a/packages/generators/package.json b/packages/generators/package.json index a01d89e1129..a0bb9571678 100644 --- a/packages/generators/package.json +++ b/packages/generators/package.json @@ -14,7 +14,6 @@ "templates" ], "dependencies": { - "@webpack-cli/package-utils": "^1.0.1-rc.1", "@webpack-cli/utils": "^1.0.1-rc.1", "@webpack-cli/webpack-scaffold": "^1.0.1-rc.1", "colorette": "^1.2.1", diff --git a/packages/generators/src/addon-generator.ts b/packages/generators/src/addon-generator.ts index a801f7e591d..3cab6939dc3 100644 --- a/packages/generators/src/addon-generator.ts +++ b/packages/generators/src/addon-generator.ts @@ -2,8 +2,8 @@ import logger from 'webpack-cli/lib/utils/logger'; import mkdirp from 'mkdirp'; import path from 'path'; import Generator from 'yeoman-generator'; -import { getPackageManager } from '@webpack-cli/package-utils'; import { generatorCopy, generatorCopyTpl } from '@webpack-cli/utils'; +import { getPackageManager } from 'webpack-cli/lib/utils/get-package-manager'; /** * Creates a Yeoman Generator that generates a project conforming diff --git a/packages/generators/src/init-generator.ts b/packages/generators/src/init-generator.ts index 5eb9862c41e..3cc7fa85021 100644 --- a/packages/generators/src/init-generator.ts +++ b/packages/generators/src/init-generator.ts @@ -2,7 +2,7 @@ import { blue, green, bold } from 'colorette'; import logger from 'webpack-cli/lib/utils/logger'; import logSymbols from 'log-symbols'; import path from 'path'; -import { getPackageManager } from '@webpack-cli/package-utils'; +import { getPackageManager } from 'webpack-cli/lib/utils/get-package-manager'; import { Confirm, Input, List } from '@webpack-cli/webpack-scaffold'; import { diff --git a/packages/generators/tsconfig.json b/packages/generators/tsconfig.json index 5da888dfbe0..63a4818f8b2 100644 --- a/packages/generators/tsconfig.json +++ b/packages/generators/tsconfig.json @@ -5,5 +5,5 @@ "rootDir": "src" }, "include": ["src"], - "references": [{ "path": "../package-utils" }, { "path": "../utils" }, { "path": "../webpack-scaffold" }] + "references": [{ "path": "../utils" }, { "path": "../webpack-scaffold" }] } diff --git a/packages/package-utils/CHANGELOG.md b/packages/package-utils/CHANGELOG.md deleted file mode 100644 index 444b22aaf22..00000000000 --- a/packages/package-utils/CHANGELOG.md +++ /dev/null @@ -1,34 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [1.0.1-rc.1](https://github.com/webpack/webpack-cli/compare/@webpack-cli/package-utils@1.0.1-alpha.4...@webpack-cli/package-utils@1.0.1-rc.1) (2020-10-06) - -### Bug Fixes - -- **utils:** respect package-lock.json ([#1375](https://github.com/webpack/webpack-cli/issues/1375)) ([ce8ec5a](https://github.com/webpack/webpack-cli/commit/ce8ec5a9f56ab5c1ce30742dced56dcbea237600)) -- **webpack-cli:** handle promise rejection with package installation ([#1284](https://github.com/webpack/webpack-cli/issues/1284)) ([eb1112e](https://github.com/webpack/webpack-cli/commit/eb1112edf05b0a1bc83dced0e83987e4f459174c)) -- check webpack installation before running cli ([#1827](https://github.com/webpack/webpack-cli/issues/1827)) ([be509fa](https://github.com/webpack/webpack-cli/commit/be509fac9a03e202e062229484bb10af7876968f)) -- declare default commands as optional peer dependency ([#1816](https://github.com/webpack/webpack-cli/issues/1816)) ([dcc75c8](https://github.com/webpack/webpack-cli/commit/dcc75c8b24d2d170a9274d80ecfb8b2329e4ad2e)) -- use appropriate exit codes ([#1755](https://github.com/webpack/webpack-cli/issues/1755)) ([83f73b0](https://github.com/webpack/webpack-cli/commit/83f73b056e224301b871bee5e9b7254e64e84e95)) - -## [1.0.1-alpha.4](https://github.com/webpack/webpack-cli/compare/@webpack-cli/package-utils@1.0.1-alpha.3...@webpack-cli/package-utils@1.0.1-alpha.4) (2020-03-02) - -**Note:** Version bump only for package @webpack-cli/package-utils - -## [1.0.1-alpha.3](https://github.com/webpack/webpack-cli/compare/@webpack-cli/package-utils@1.0.1-alpha.2...@webpack-cli/package-utils@1.0.1-alpha.3) (2020-02-29) - -**Note:** Version bump only for package @webpack-cli/package-utils - -## [1.0.1-alpha.2](https://github.com/webpack/webpack-cli/compare/@webpack-cli/package-utils@1.0.1-alpha.1...@webpack-cli/package-utils@1.0.1-alpha.2) (2020-02-23) - -**Note:** Version bump only for package @webpack-cli/package-utils - -## [1.0.1-alpha.1](https://github.com/webpack/webpack-cli/compare/@webpack-cli/package-utils@1.0.1-alpha.0...@webpack-cli/package-utils@1.0.1-alpha.1) (2020-02-23) - -**Note:** Version bump only for package @webpack-cli/package-utils - -## 1.0.1-alpha.0 (2020-02-23) - -**Note:** Version bump only for package @webpack-cli/package-utils diff --git a/packages/package-utils/README.md b/packages/package-utils/README.md deleted file mode 100644 index 6b781a5f484..00000000000 --- a/packages/package-utils/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# `@webpack-cli/package-utils` - -> TODO: description - -## Usage - -``` -const packageUtils = require('@webpack-cli/package-utils'); - -// TODO: DEMONSTRATE API -``` diff --git a/packages/package-utils/__tests__/index.test.ts b/packages/package-utils/__tests__/index.test.ts deleted file mode 100644 index 4ceda50a35b..00000000000 --- a/packages/package-utils/__tests__/index.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -'use strict'; - -jest.mock('../lib/packageUtils', () => { - return { - packageExists: jest.fn(), - promptInstallation: jest.fn(), - }; -}); - -import { packageExists, promptInstallation } from '../lib/packageUtils'; -import run from '../../webpack-cli/lib/commands/resolveCommand'; - -describe('@webpack-cli/package-utils', () => { - it('should check existence of package', () => { - (packageExists as jest.Mock).mockImplementation(() => true); - const exists = packageExists('@webpack-cli/info'); - expect(exists).toBeTruthy(); - }); - - it('should not throw if the user interrupts', async () => { - (promptInstallation as jest.Mock).mockImplementation(() => { - throw new Error(); - }); - await expect(run('info')).resolves.not.toThrow(); - }); -}); diff --git a/packages/package-utils/__tests__/packageUtils.test.ts b/packages/package-utils/__tests__/packageUtils.test.ts deleted file mode 100644 index e853fa2ac0a..00000000000 --- a/packages/package-utils/__tests__/packageUtils.test.ts +++ /dev/null @@ -1,183 +0,0 @@ -'use strict'; - -jest.mock('execa'); -jest.mock('cross-spawn'); -const globalModulesNpmValue = 'test-npm'; -jest.setMock('global-modules', globalModulesNpmValue); -jest.setMock('enquirer', { - prompt: jest.fn(), -}); -jest.setMock('../lib/processUtils', { - runCommand: jest.fn(), -}); - -import fs from 'fs'; -import path from 'path'; -import execa from 'execa'; -import spawn from 'cross-spawn'; -import { prompt } from 'enquirer'; -import { getPackageManager, packageExists } from '../lib/packageUtils'; -import { runCommand } from '../lib/processUtils'; - -describe('packageUtils', () => { - describe('getPackageManager', () => { - const testYarnLockPath = path.resolve(__dirname, 'test-yarn-lock'); - const testNpmLockPath = path.resolve(__dirname, 'test-npm-lock'); - const testBothPath = path.resolve(__dirname, 'test-both'); - - const cwdSpy = jest.spyOn(process, 'cwd'); - - beforeAll(() => { - // mock sync - execa.sync = jest.fn(); - - // package-lock.json is ignored by .gitignore, so we simply - // write a lockfile here for testing - if (!fs.existsSync(testNpmLockPath)) { - fs.mkdirSync(testNpmLockPath); - } - fs.writeFileSync(path.resolve(testNpmLockPath, 'package-lock.json'), ''); - fs.writeFileSync(path.resolve(testBothPath, 'package-lock.json'), ''); - }); - - beforeEach(() => { - (execa.sync as jest.Mock).mockClear(); - }); - - it('should find yarn.lock', () => { - cwdSpy.mockReturnValue(testYarnLockPath); - expect(getPackageManager()).toEqual('yarn'); - expect((execa.sync as jest.Mock).mock.calls.length).toEqual(0); - }); - - it('should find package-lock.json', () => { - cwdSpy.mockReturnValue(testNpmLockPath); - expect(getPackageManager()).toEqual('npm'); - expect((execa.sync as jest.Mock).mock.calls.length).toEqual(0); - }); - - it('should prioritize yarn with many lock files', () => { - cwdSpy.mockReturnValue(testBothPath); - expect(getPackageManager()).toEqual('yarn'); - expect((execa.sync as jest.Mock).mock.calls.length).toEqual(0); - }); - - it('should use yarn if yarn command works', () => { - // yarn should output a version number to stdout if - // it is installed - (execa.sync as jest.Mock).mockImplementation(() => { - return { - stdout: '1.0.0', - }; - }); - cwdSpy.mockReturnValue(path.resolve(__dirname)); - expect(getPackageManager()).toEqual('yarn'); - expect((execa.sync as jest.Mock).mock.calls.length).toEqual(1); - }); - - it('should use npm if yarn command fails', () => { - (execa.sync as jest.Mock).mockImplementation(() => { - throw new Error(); - }); - cwdSpy.mockReturnValue(path.resolve(__dirname)); - expect(getPackageManager()).toEqual('npm'); - expect((execa.sync as jest.Mock).mock.calls.length).toEqual(1); - }); - }); - - describe('getPathToGlobalPackages', () => { - let packageUtils; - beforeAll(() => { - packageUtils = require('../lib/packageUtils'); - packageUtils.getPackageManager = jest.fn(); - }); - - it('uses global-modules if package manager is npm', () => { - packageUtils.getPackageManager.mockReturnValue('npm'); - expect(packageUtils.getPathToGlobalPackages()).toEqual(globalModulesNpmValue); - }); - - it('executes a command to find yarn global dir if package manager is yarn', () => { - packageUtils.getPackageManager.mockReturnValue('yarn'); - (spawn.sync as jest.Mock).mockReturnValue({ - stdout: { - toString: (): string => { - return 'test-yarn'; - }, - }, - }); - // after the yarn global dir is found, the node_modules directory - // is added on to the path - expect(packageUtils.getPathToGlobalPackages()).toEqual(`test-yarn${path.sep}node_modules`); - }); - }); - - describe('packageExists', () => { - it('should check existence of package', () => { - // use an actual path relative to the packageUtils file - expect(packageExists('./processUtils')).toBeTruthy(); - expect(packageExists('./nonexistent-package')).toBeFalsy(); - }); - }); - - describe('promptInstallation', () => { - let packageUtils; - beforeAll(() => { - packageUtils = require('../lib/packageUtils'); - packageUtils.getPackageManager = jest.fn(); - packageUtils.packageExists = jest.fn(() => true); - }); - - beforeEach(() => { - (runCommand as jest.Mock).mockClear(); - (prompt as jest.Mock).mockClear(); - }); - - it('should prompt to install using npm if npm is package manager', async () => { - packageUtils.getPackageManager.mockReturnValue('npm'); - (prompt as jest.Mock).mockReturnValue({ - installConfirm: true, - }); - - const preMessage = jest.fn(); - const promptResult = await packageUtils.promptInstallation('test-package', preMessage); - expect(promptResult).toBeTruthy(); - expect(preMessage.mock.calls.length).toEqual(1); - expect((prompt as jest.Mock).mock.calls.length).toEqual(1); - expect((runCommand as jest.Mock).mock.calls.length).toEqual(1); - expect((prompt as jest.Mock).mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/); - // install the package using npm - expect((runCommand as jest.Mock).mock.calls[0][0]).toEqual('npm install -D test-package'); - }); - - it('should prompt to install using yarn if yarn is package manager', async () => { - packageUtils.getPackageManager.mockReturnValue('yarn'); - (prompt as jest.Mock).mockReturnValue({ - installConfirm: true, - }); - - const promptResult = await packageUtils.promptInstallation('test-package'); - expect(promptResult).toBeTruthy(); - expect((prompt as jest.Mock).mock.calls.length).toEqual(1); - expect((runCommand as jest.Mock).mock.calls.length).toEqual(1); - expect((prompt as jest.Mock).mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/); - // install the package using yarn - expect((runCommand as jest.Mock).mock.calls[0][0]).toEqual('yarn add -D test-package'); - }); - - it('should not install if install is not confirmed', async () => { - packageUtils.getPackageManager.mockReturnValue('npm'); - (prompt as jest.Mock).mockReturnValue({ - installConfirm: false, - }); - - const promptResult = await packageUtils.promptInstallation('test-package'); - expect(promptResult).toBeUndefined(); - expect((prompt as jest.Mock).mock.calls.length).toEqual(1); - // runCommand should not be called, because the installation is not confirmed - expect((runCommand as jest.Mock).mock.calls.length).toEqual(0); - expect((prompt as jest.Mock).mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/); - expect(process.exitCode).toEqual(2); - }); - }); -}); diff --git a/packages/package-utils/package.json b/packages/package-utils/package.json deleted file mode 100644 index b89b3259a1a..00000000000 --- a/packages/package-utils/package.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "@webpack-cli/package-utils", - "version": "1.0.1-rc.1", - "description": "A module to help managing packages and modules inside webpack CLI", - "keywords": [ - "webpack", - "webpack-cli", - "node", - "package", - "utils", - "npm", - "yarn" - ], - "author": "emanuele ", - "homepage": "https://github.com/webpack/webpack-cli#readme", - "license": "MIT", - "main": "lib/index.js", - "types": "lib/index.d.ts", - "directories": { - "test": "__tests__" - }, - "publishConfig": { - "access": "public" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/webpack/webpack-cli.git" - }, - "bugs": { - "url": "https://github.com/webpack/webpack-cli/issues" - }, - "files": [ - "lib" - ], - "dependencies": { - "colorette": "^1.2.1", - "cross-spawn": "^7.0.1", - "enquirer": "^2.3.4", - "execa": "^4.0.0", - "global-modules": "^2.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "@webpack-cli/info": { - "optional": true - }, - "@webpack-cli/init": { - "optional": true - }, - "@webpack-cli/serve": { - "optional": true - } - }, - "gitHead": "fb50f766851f500ca12867a2aa9de81fa6e368f9" -} diff --git a/packages/package-utils/src/index.ts b/packages/package-utils/src/index.ts deleted file mode 100644 index caffda148a9..00000000000 --- a/packages/package-utils/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './packageUtils'; -export * from './processUtils'; diff --git a/packages/package-utils/src/packageUtils.ts b/packages/package-utils/src/packageUtils.ts deleted file mode 100644 index 167d7bee322..00000000000 --- a/packages/package-utils/src/packageUtils.ts +++ /dev/null @@ -1,102 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { sync } from 'execa'; -import spawn from 'cross-spawn'; -import { green } from 'colorette'; -import { prompt } from 'enquirer'; -import { runCommand } from './processUtils'; - -/** - * - * Returns the name of package manager to use, - * preferring yarn over npm if available - * - * @returns {String} - The package manager name - */ - -type PackageName = 'npm' | 'yarn'; - -export function getPackageManager(): PackageName { - const hasLocalYarn = fs.existsSync(path.resolve(process.cwd(), 'yarn.lock')); - const hasLocalNpm = fs.existsSync(path.resolve(process.cwd(), 'package-lock.json')); - - if (hasLocalYarn) { - return 'yarn'; - } else if (hasLocalNpm) { - return 'npm'; - } - - try { - // if the sync function below fails because yarn is not installed, - // an error will be thrown - if (sync('yarn', ['--version']).stdout) { - return 'yarn'; - } - } catch (e) { - // Nothing - } - - return 'npm'; -} - -/** - * - * Returns the path to globally installed - * npm packages, depending on the available - * package manager determined by `getPackageManager` - * - * @returns {String} path - Path to global node_modules folder - */ -export function getPathToGlobalPackages(): string { - const manager: string = exports.getPackageManager(); - if (manager === 'yarn') { - try { - const yarnDir = spawn.sync('yarn', ['global', 'dir']).stdout.toString().trim(); - return path.join(yarnDir, 'node_modules'); - } catch (e) { - // Default to the global npm path below - } - } - - return require('global-modules'); -} - -export function packageExists(packageName: string): boolean { - try { - require(packageName); - return true; - } catch (err) { - return false; - } -} - -/** - * - * @param packageName - * @param preMessage Message to show before the question - */ -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -export async function promptInstallation(packageName: string, preMessage?: Function) { - const packageManager = exports.getPackageManager(); - const options = [packageManager === 'yarn' ? 'add' : 'install', '-D', packageName]; - - const commandToBeRun = `${packageManager} ${options.join(' ')}`; - if (preMessage) { - preMessage(); - } - const question = `Would you like to install ${packageName}? (That will run ${green(commandToBeRun)})`; - const { installConfirm } = await prompt([ - { - type: 'confirm', - name: 'installConfirm', - message: question, - initial: 'Y', - }, - ]); - if (installConfirm) { - await runCommand(commandToBeRun); - return exports.packageExists(packageName); - } - // eslint-disable-next-line require-atomic-updates - process.exitCode = 2; -} diff --git a/packages/package-utils/tsconfig.json b/packages/package-utils/tsconfig.json deleted file mode 100644 index 279b3e923cc..00000000000 --- a/packages/package-utils/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "./lib", - "rootDir": "./src" - }, - "include": ["./src"] -} diff --git a/packages/utils/__tests__/global-packages-path.test.ts b/packages/utils/__tests__/global-packages-path.test.ts new file mode 100644 index 00000000000..2e3350772e9 --- /dev/null +++ b/packages/utils/__tests__/global-packages-path.test.ts @@ -0,0 +1,34 @@ +'use strict'; +jest.setMock('webpack-cli/lib/utils/get-package-manager', { + getPackageManager: jest.fn(), +}); +import { getPathToGlobalPackages } from '../lib/global-packages-path'; +import { getPackageManager } from 'webpack-cli/lib/utils/get-package-manager'; +jest.mock('execa'); +jest.mock('cross-spawn'); +const globalModulesNpmValue = 'test-npm'; +jest.setMock('global-modules', globalModulesNpmValue); + +import path from 'path'; +import spawn from 'cross-spawn'; + +describe('getPathToGlobalPackages', () => { + it('uses global-modules if package manager is npm', () => { + (getPackageManager as jest.Mock).mockReturnValue('npm'); + expect(getPathToGlobalPackages()).toEqual(globalModulesNpmValue); + }); + + it('executes a command to find yarn global dir if package manager is yarn', () => { + (getPackageManager as jest.Mock).mockReturnValue('yarn'); + (spawn.sync as jest.Mock).mockReturnValue({ + stdout: { + toString: (): string => { + return 'test-yarn'; + }, + }, + }); + // after the yarn global dir is found, the node_modules directory + // is added on to the path + expect(getPathToGlobalPackages()).toEqual(`test-yarn${path.sep}node_modules`); + }); +}); diff --git a/packages/utils/package.json b/packages/utils/package.json index 4a3146f5f24..a77b8ecc641 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -12,29 +12,41 @@ "lib" ], "dependencies": { - "@webpack-cli/package-utils": "^1.0.1-rc.1", "colorette": "^1.2.1", + "cross-spawn": "^7.0.3", + "enquirer": "^2.3.6", "execa": "^4.0.0", "findup-sync": "^4.0.0", + "global-modules": "^2.0.0", "got": "^10.7.0", "jscodeshift": "^0.7.0", "p-each-series": "^2.1.0", "yeoman-environment": "^2.8.1", "yeoman-generator": "^4.7.2" }, - "peerDependenciesMeta": { - "prettier": { - "optional": true - } - }, "peerDependencies": { "webpack": "4.x.x || 5.x.x", "webpack-cli": "4.x.x" }, "devDependencies": { + "@types/cross-spawn": "^6.0.2", "@types/got": "9.6.9", "@types/prettier": "1.19.0", "@types/yeoman-generator": "^4.11.2" }, + "peerDependenciesMeta": { + "@webpack-cli/info": { + "optional": true + }, + "@webpack-cli/init": { + "optional": true + }, + "@webpack-cli/serve": { + "optional": true + }, + "prettier": { + "optional": true + } + }, "gitHead": "fb50f766851f500ca12867a2aa9de81fa6e368f9" } diff --git a/packages/utils/src/global-packages-path.ts b/packages/utils/src/global-packages-path.ts new file mode 100644 index 00000000000..acdc7fecc45 --- /dev/null +++ b/packages/utils/src/global-packages-path.ts @@ -0,0 +1,25 @@ +import spawn from 'cross-spawn'; +import path from 'path'; +import { getPackageManager } from 'webpack-cli/lib/utils/get-package-manager'; + +/** + * + * Returns the path to globally installed + * npm packages, depending on the available + * package manager determined by `getPackageManager` + * + * @returns {String} path - Path to global node_modules folder + */ +export function getPathToGlobalPackages(): string { + const manager: string = getPackageManager(); + if (manager === 'yarn') { + try { + const yarnDir = spawn.sync('yarn', ['global', 'dir']).stdout.toString().trim(); + return path.join(yarnDir, 'node_modules'); + } catch (e) { + // Default to the global npm path below + } + } + + return require('global-modules'); +} diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index e897f093c2a..68fef1ebafe 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -9,3 +9,4 @@ export * from './run-prettier'; export * from './scaffold'; export * from './validate-identifier'; export * from './prop-types'; +export * from './global-packages-path'; diff --git a/packages/utils/src/modify-config-helper.ts b/packages/utils/src/modify-config-helper.ts index a36e6696d9b..aba3b571725 100644 --- a/packages/utils/src/modify-config-helper.ts +++ b/packages/utils/src/modify-config-helper.ts @@ -5,7 +5,7 @@ import path from 'path'; import yeoman from 'yeoman-environment'; import Generator from 'yeoman-generator'; import { runTransform } from './scaffold'; -import { getPackageManager } from '@webpack-cli/package-utils'; +import { getPackageManager } from 'webpack-cli/lib/utils/get-package-manager'; export interface Config extends Object { item?: { diff --git a/packages/utils/src/npm-packages-exists.ts b/packages/utils/src/npm-packages-exists.ts index 3233a8027bb..42897c33b2a 100644 --- a/packages/utils/src/npm-packages-exists.ts +++ b/packages/utils/src/npm-packages-exists.ts @@ -4,7 +4,7 @@ import { red, bold } from 'colorette'; import { npmExists } from './npm-exists'; import { isLocalPath } from './path-utils'; import { resolvePackages } from './resolve-packages'; -import { getPathToGlobalPackages } from '@webpack-cli/package-utils'; +import { getPathToGlobalPackages } from './global-packages-path'; const WEBPACK_SCAFFOLD_PREFIX = 'webpack-scaffold'; /** diff --git a/packages/utils/src/resolve-packages.ts b/packages/utils/src/resolve-packages.ts index 773cc0f9d41..9fa19f2ca80 100644 --- a/packages/utils/src/resolve-packages.ts +++ b/packages/utils/src/resolve-packages.ts @@ -2,7 +2,8 @@ import { bold } from 'colorette'; import logger from 'webpack-cli/lib/utils/logger'; import path from 'path'; import { modifyHelperUtil } from './modify-config-helper'; -import { getPathToGlobalPackages, spawnChild } from '@webpack-cli/package-utils'; +import { getPathToGlobalPackages } from './global-packages-path'; +import { spawnChild } from './spawn-child'; import { isLocalPath } from './path-utils'; import { ExecaSyncReturnValue } from 'execa'; diff --git a/packages/utils/src/scaffold.ts b/packages/utils/src/scaffold.ts index a9b2229ca41..18383e30e6a 100644 --- a/packages/utils/src/scaffold.ts +++ b/packages/utils/src/scaffold.ts @@ -3,7 +3,7 @@ import j from 'jscodeshift'; import logger from 'webpack-cli/lib/utils/logger'; import pEachSeries = require('p-each-series'); import path from 'path'; -import { getPackageManager } from '@webpack-cli/package-utils'; +import { getPackageManager } from 'webpack-cli/lib/utils/get-package-manager'; import { findProjectRoot } from './path-utils'; import { Error } from './types'; import { Config, TransformConfig } from './types'; diff --git a/packages/package-utils/src/processUtils.ts b/packages/utils/src/spawn-child.ts similarity index 73% rename from packages/package-utils/src/processUtils.ts rename to packages/utils/src/spawn-child.ts index a85324f5bdc..93b10a9f79e 100644 --- a/packages/package-utils/src/processUtils.ts +++ b/packages/utils/src/spawn-child.ts @@ -1,7 +1,8 @@ -import execa, { ExecaSyncReturnValue, sync } from 'execa'; -import { getPackageManager, getPathToGlobalPackages } from './packageUtils'; import path from 'path'; import fs from 'fs'; +import { ExecaSyncReturnValue, sync } from 'execa'; +import { getPathToGlobalPackages } from './global-packages-path'; +import { getPackageManager } from 'webpack-cli/lib/utils/get-package-manager'; /** * @@ -39,14 +40,3 @@ export function spawnChild(pkg: string): ExecaSyncReturnValue { return spawnWithArg(pkg, isNew); } - -export async function runCommand(command, args = []): Promise { - try { - await execa(command, args, { - stdio: 'inherit', - shell: true, - }); - } catch (e) { - throw new Error(e); - } -} diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json index e813c20f537..279b3e923cc 100644 --- a/packages/utils/tsconfig.json +++ b/packages/utils/tsconfig.json @@ -4,6 +4,5 @@ "outDir": "./lib", "rootDir": "./src" }, - "include": ["./src"], - "references": [{ "path": "../package-utils" }] + "include": ["./src"] } diff --git a/packages/webpack-cli/bin/cli.js b/packages/webpack-cli/bin/cli.js index 12783d03a18..e591bb25dc5 100755 --- a/packages/webpack-cli/bin/cli.js +++ b/packages/webpack-cli/bin/cli.js @@ -6,7 +6,8 @@ const importLocal = require('import-local'); const runCLI = require('../lib/bootstrap'); const { yellow } = require('colorette'); const { error, success } = require('../lib/utils/logger'); -const { packageExists, promptInstallation } = require('@webpack-cli/package-utils'); +const { packageExists } = require('../lib/utils/package-exists'); +const { promptInstallation } = require('../lib/utils/prompt-installation'); // Prefer the local installation of webpack-cli if (importLocal(__filename)) { diff --git a/packages/webpack-cli/lib/commands/resolveCommand.js b/packages/webpack-cli/lib/commands/resolveCommand.js index 5719aac528c..fae1398cd03 100644 --- a/packages/webpack-cli/lib/commands/resolveCommand.js +++ b/packages/webpack-cli/lib/commands/resolveCommand.js @@ -1,6 +1,7 @@ const { yellow, cyan } = require('colorette'); const logger = require('../utils/logger'); -const { packageExists, promptInstallation } = require('@webpack-cli/package-utils'); +const { packageExists } = require('../utils/package-exists'); +const { promptInstallation } = require('../utils/prompt-installation'); const packagePrefix = '@webpack-cli'; diff --git a/packages/webpack-cli/lib/groups/resolveAdvanced.js b/packages/webpack-cli/lib/groups/resolveAdvanced.js index 02211e847e8..dc7fd01186b 100644 --- a/packages/webpack-cli/lib/groups/resolveAdvanced.js +++ b/packages/webpack-cli/lib/groups/resolveAdvanced.js @@ -1,4 +1,5 @@ -const { packageExists, promptInstallation } = require('@webpack-cli/package-utils'); +const { packageExists } = require('../utils/package-exists'); +const { promptInstallation } = require('../utils/prompt-installation'); const { yellow } = require('colorette'); const { error, success } = require('../utils/logger'); diff --git a/packages/webpack-cli/lib/utils/Compiler.js b/packages/webpack-cli/lib/utils/Compiler.js index 9bd5b4e2c6e..d2cd7949816 100644 --- a/packages/webpack-cli/lib/utils/Compiler.js +++ b/packages/webpack-cli/lib/utils/Compiler.js @@ -1,4 +1,4 @@ -const { packageExists } = require('@webpack-cli/package-utils'); +const { packageExists } = require('./package-exists'); const webpack = packageExists('webpack') ? require('webpack') : undefined; const logger = require('./logger'); const { writeFileSync } = require('fs'); diff --git a/packages/webpack-cli/lib/utils/__tests__/get-package-manager.test.js b/packages/webpack-cli/lib/utils/__tests__/get-package-manager.test.js new file mode 100644 index 00000000000..b11c0113d86 --- /dev/null +++ b/packages/webpack-cli/lib/utils/__tests__/get-package-manager.test.js @@ -0,0 +1,78 @@ +const fs = require('fs'); +const path = require('path'); + +const syncMock = jest.fn(() => { + return { + stdout: '1.0.0', + }; +}); +jest.setMock('execa', { + sync: syncMock, +}); +const { getPackageManager } = require('../get-package-manager'); + +jest.mock('cross-spawn'); +const globalModulesNpmValue = 'test-npm'; +jest.setMock('global-modules', globalModulesNpmValue); +jest.setMock('enquirer', { + prompt: jest.fn(), +}); + +describe('packageUtils', () => { + describe('getPackageManager', () => { + const testYarnLockPath = path.resolve(__dirname, 'test-yarn-lock'); + const testNpmLockPath = path.resolve(__dirname, 'test-npm-lock'); + const testBothPath = path.resolve(__dirname, 'test-both'); + + const cwdSpy = jest.spyOn(process, 'cwd'); + + beforeAll(() => { + // package-lock.json is ignored by .gitignore, so we simply + // write a lockfile here for testing + if (!fs.existsSync(testNpmLockPath)) { + fs.mkdirSync(testNpmLockPath); + } + fs.writeFileSync(path.resolve(testNpmLockPath, 'package-lock.json'), ''); + fs.writeFileSync(path.resolve(testBothPath, 'package-lock.json'), ''); + }); + + beforeEach(() => { + syncMock.mockClear(); + }); + + it('should find yarn.lock', () => { + cwdSpy.mockReturnValue(testYarnLockPath); + expect(getPackageManager()).toEqual('yarn'); + expect(syncMock.mock.calls.length).toEqual(0); + }); + + it('should find package-lock.json', () => { + cwdSpy.mockReturnValue(testNpmLockPath); + expect(getPackageManager()).toEqual('npm'); + expect(syncMock.mock.calls.length).toEqual(0); + }); + + it('should prioritize yarn with many lock files', () => { + cwdSpy.mockReturnValue(testBothPath); + expect(getPackageManager()).toEqual('yarn'); + expect(syncMock.mock.calls.length).toEqual(0); + }); + + it('should use yarn if yarn command works', () => { + // yarn should output a version number to stdout if + // it is installed + cwdSpy.mockReturnValue(path.resolve(__dirname)); + expect(getPackageManager()).toEqual('yarn'); + expect(syncMock.mock.calls.length).toEqual(1); + }); + + it('should use npm if yarn command fails', () => { + syncMock.mockImplementation(() => { + throw new Error(); + }); + cwdSpy.mockReturnValue(path.resolve(__dirname)); + expect(getPackageManager()).toEqual('npm'); + expect(syncMock.mock.calls.length).toEqual(1); + }); + }); +}); diff --git a/packages/webpack-cli/lib/utils/__tests__/package-exists.test.js b/packages/webpack-cli/lib/utils/__tests__/package-exists.test.js new file mode 100644 index 00000000000..309f479c408 --- /dev/null +++ b/packages/webpack-cli/lib/utils/__tests__/package-exists.test.js @@ -0,0 +1,22 @@ +jest.setMock('../prompt-installation', { + promptInstallation: jest.fn(), +}); + +const ExternalCommand = require('../../commands/resolveCommand'); +const { packageExists } = require('../package-exists'); +const { promptInstallation } = require('../prompt-installation'); + +describe('@webpack-cli/utils', () => { + it('should check existence of package', () => { + // use an actual path relative to the packageUtils file + expect(packageExists('./logger')).toBeTruthy(); + expect(packageExists('./nonexistent-package')).toBeFalsy(); + }); + + it('should not throw if the user interrupts', async () => { + promptInstallation.mockImplementation(() => { + throw new Error(); + }); + await expect(ExternalCommand('info')).resolves.not.toThrow(); + }); +}); diff --git a/packages/webpack-cli/lib/utils/__tests__/prompt-installation.test.js b/packages/webpack-cli/lib/utils/__tests__/prompt-installation.test.js new file mode 100644 index 00000000000..2108828c010 --- /dev/null +++ b/packages/webpack-cli/lib/utils/__tests__/prompt-installation.test.js @@ -0,0 +1,82 @@ +'use strict'; + +jest.mock('execa'); +jest.mock('cross-spawn'); +const globalModulesNpmValue = 'test-npm'; +jest.setMock('global-modules', globalModulesNpmValue); +jest.setMock('enquirer', { + prompt: jest.fn(), +}); + +jest.setMock('../run-command', { + runCommand: jest.fn(), +}); + +jest.setMock('../package-exists', { + packageExists: jest.fn(), +}); + +jest.setMock('../get-package-manager', { + getPackageManager: jest.fn(), +}); + +const { getPackageManager } = require('../get-package-manager'); +const { packageExists } = require('../package-exists'); +const { promptInstallation } = require('../prompt-installation'); +const { runCommand } = require('../run-command'); +const { prompt } = require('enquirer'); + +describe('promptInstallation', () => { + beforeAll(() => { + packageExists.mockReturnValue(true); + }); + beforeEach(() => { + runCommand.mockClear(); + prompt.mockClear(); + }); + + it('should prompt to install using npm if npm is package manager', async () => { + prompt.mockReturnValue({ + installConfirm: true, + }); + getPackageManager.mockReturnValue('npm'); + const preMessage = jest.fn(); + const promptResult = await promptInstallation('test-package', preMessage); + expect(promptResult).toBeTruthy(); + expect(preMessage.mock.calls.length).toEqual(1); + expect(prompt.mock.calls.length).toEqual(1); + expect(runCommand.mock.calls.length).toEqual(1); + expect(prompt.mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/); + // install the package using npm + expect(runCommand.mock.calls[0][0]).toEqual('npm install -D test-package'); + }); + + it('should prompt to install using yarn if yarn is package manager', async () => { + prompt.mockReturnValue({ + installConfirm: true, + }); + getPackageManager.mockReturnValue('yarn'); + + const promptResult = await promptInstallation('test-package'); + expect(promptResult).toBeTruthy(); + expect(prompt.mock.calls.length).toEqual(1); + expect(runCommand.mock.calls.length).toEqual(1); + expect(prompt.mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/); + // install the package using yarn + expect(runCommand.mock.calls[0][0]).toEqual('yarn add -D test-package'); + }); + + it('should not install if install is not confirmed', async () => { + prompt.mockReturnValue({ + installConfirm: false, + }); + + const promptResult = await promptInstallation('test-package'); + expect(promptResult).toBeUndefined(); + expect(prompt.mock.calls.length).toEqual(1); + // runCommand should not be called, because the installation is not confirmed + expect(runCommand.mock.calls.length).toEqual(0); + expect(prompt.mock.calls[0][0][0].message).toMatch(/Would you like to install test-package\?/); + expect(process.exitCode).toEqual(2); + }); +}); diff --git a/packages/package-utils/__tests__/test-both/yarn.lock b/packages/webpack-cli/lib/utils/__tests__/test-both/package-lock.json similarity index 100% rename from packages/package-utils/__tests__/test-both/yarn.lock rename to packages/webpack-cli/lib/utils/__tests__/test-both/package-lock.json diff --git a/packages/package-utils/__tests__/test-yarn-lock/yarn.lock b/packages/webpack-cli/lib/utils/__tests__/test-both/yarn.lock similarity index 100% rename from packages/package-utils/__tests__/test-yarn-lock/yarn.lock rename to packages/webpack-cli/lib/utils/__tests__/test-both/yarn.lock diff --git a/packages/webpack-cli/lib/utils/__tests__/test-npm-lock/package-lock.json b/packages/webpack-cli/lib/utils/__tests__/test-npm-lock/package-lock.json new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/webpack-cli/lib/utils/__tests__/test-yarn-lock/yarn.lock b/packages/webpack-cli/lib/utils/__tests__/test-yarn-lock/yarn.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/webpack-cli/lib/utils/cli-flags.js b/packages/webpack-cli/lib/utils/cli-flags.js index f5d5c2261e7..0f5f508169a 100644 --- a/packages/webpack-cli/lib/utils/cli-flags.js +++ b/packages/webpack-cli/lib/utils/cli-flags.js @@ -1,4 +1,4 @@ -const { packageExists } = require('@webpack-cli/package-utils'); +const { packageExists } = require('./package-exists'); const cli = packageExists('webpack') ? require('webpack').cli : undefined; const HELP_GROUP = 'help'; diff --git a/packages/webpack-cli/lib/utils/get-package-manager.js b/packages/webpack-cli/lib/utils/get-package-manager.js new file mode 100644 index 00000000000..7ac3efb9c07 --- /dev/null +++ b/packages/webpack-cli/lib/utils/get-package-manager.js @@ -0,0 +1,35 @@ +const fs = require('fs'); +const path = require('path'); +const { sync } = require('execa'); + +/** + * + * Returns the name of package manager to use, + * preferring yarn over npm if available + * + * @returns {String} - The package manager name + */ +function getPackageManager() { + const hasLocalYarn = fs.existsSync(path.resolve(process.cwd(), 'yarn.lock')); + const hasLocalNpm = fs.existsSync(path.resolve(process.cwd(), 'package-lock.json')); + if (hasLocalYarn) { + return 'yarn'; + } else if (hasLocalNpm) { + return 'npm'; + } + try { + // if the sync function below fails because yarn is not installed, + // an error will be thrown + if (sync('yarn', ['--version'])) { + return 'yarn'; + } + } catch (e) { + // Nothing + } + + return 'npm'; +} + +module.exports = { + getPackageManager, +}; diff --git a/packages/webpack-cli/lib/utils/package-exists.js b/packages/webpack-cli/lib/utils/package-exists.js new file mode 100644 index 00000000000..ebb8c3d9321 --- /dev/null +++ b/packages/webpack-cli/lib/utils/package-exists.js @@ -0,0 +1,12 @@ +function packageExists(packageName) { + try { + require(packageName); + return true; + } catch (err) { + return false; + } +} + +module.exports = { + packageExists, +}; diff --git a/packages/webpack-cli/lib/utils/prompt-installation.js b/packages/webpack-cli/lib/utils/prompt-installation.js new file mode 100644 index 00000000000..03259bdbf87 --- /dev/null +++ b/packages/webpack-cli/lib/utils/prompt-installation.js @@ -0,0 +1,40 @@ +const { prompt } = require('enquirer'); +const { green } = require('colorette'); +const { runCommand } = require('./run-command'); +const { getPackageManager } = require('./get-package-manager'); +const { packageExists } = require('./package-exists'); + +/** + * + * @param packageName + * @param preMessage Message to show before the question + */ +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type +async function promptInstallation(packageName, preMessage) { + const packageManager = getPackageManager(); + const options = [packageManager === 'yarn' ? 'add' : 'install', '-D', packageName]; + + const commandToBeRun = `${packageManager} ${options.join(' ')}`; + if (preMessage) { + preMessage(); + } + const question = `Would you like to install ${packageName}? (That will run ${green(commandToBeRun)})`; + const { installConfirm } = await prompt([ + { + type: 'confirm', + name: 'installConfirm', + message: question, + initial: 'Y', + }, + ]); + if (installConfirm) { + await runCommand(commandToBeRun); + return packageExists(packageName); + } + // eslint-disable-next-line require-atomic-updates + process.exitCode = 2; +} + +module.exports = { + promptInstallation, +}; diff --git a/packages/webpack-cli/lib/utils/run-command.js b/packages/webpack-cli/lib/utils/run-command.js new file mode 100644 index 00000000000..47c13d7b791 --- /dev/null +++ b/packages/webpack-cli/lib/utils/run-command.js @@ -0,0 +1,16 @@ +const execa = require('execa'); + +async function runCommand(command, args = []) { + try { + await execa(command, args, { + stdio: 'inherit', + shell: true, + }); + } catch (e) { + throw new Error(e); + } +} + +module.exports = { + runCommand, +}; diff --git a/packages/webpack-cli/package.json b/packages/webpack-cli/package.json index 5f411a7a68c..8283d8028fe 100644 --- a/packages/webpack-cli/package.json +++ b/packages/webpack-cli/package.json @@ -29,7 +29,6 @@ "dependencies": { "@webpack-cli/info": "^1.0.1-rc.1", "@webpack-cli/init": "^1.0.1-rc.1", - "@webpack-cli/package-utils": "^1.0.1-rc.1", "@webpack-cli/serve": "^1.0.1-rc.1", "ansi-escapes": "^4.3.1", "colorette": "^1.2.1", diff --git a/tsconfig.json b/tsconfig.json index 2955029a9f3..6090b21c41a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,7 +26,6 @@ { "path": "packages/info" }, { "path": "packages/init" }, { "path": "packages/migrate" }, - { "path": "packages/package-utils" }, { "path": "packages/serve" }, { "path": "packages/utils" }, // { "path": "packages/webpack-cli" }, diff --git a/yarn.lock b/yarn.lock index 69fdb2e9b0d..122ddcbb23f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2235,7 +2235,7 @@ "@types/node" "*" "@types/responselike" "*" -"@types/cross-spawn@^6.0.1": +"@types/cross-spawn@^6.0.1", "@types/cross-spawn@^6.0.2": version "6.0.2" resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.2.tgz#168309de311cd30a2b8ae720de6475c2fbf33ac7" integrity sha512-KuwNhp3eza+Rhu8IFI5HUXRP0LIhqH5cAjubUvGXXthh4YYBuP2ntwEX+Cz8GJoZUHlKo247wPWOfA9LYEq4cw== @@ -4348,7 +4348,16 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.1: +cross-spawn@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==