GoScrobble/web/node_modules/react-scripts/scripts/utils/verifyPackageTree.js

164 lines
6.6 KiB
JavaScript
Raw Normal View History

2022-04-25 02:47:15 +00:00
// @remove-file-on-eject
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const chalk = require('react-dev-utils/chalk');
const fs = require('fs');
const semver = require('semver');
const path = require('path');
// We assume that having wrong versions of these
// in the tree will likely break your setup.
// This is a relatively low-effort way to find common issues.
function verifyPackageTree() {
const depsToCheck = [
// These are packages most likely to break in practice.
// See https://github.com/facebook/create-react-app/issues/1795 for reasons why.
// I have not included Babel here because plugins typically don't import Babel (so it's not affected).
'babel-eslint',
'babel-jest',
'babel-loader',
'eslint',
'jest',
'webpack',
'webpack-dev-server',
];
// Inlined from semver-regex, MIT license.
// Don't want to make this a dependency after ejecting.
const getSemverRegex = () =>
/\bv?(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[\da-z-]+(?:\.[\da-z-]+)*)?(?:\+[\da-z-]+(?:\.[\da-z-]+)*)?\b/gi;
const ownPackageJson = require('../../package.json');
const expectedVersionsByDep = {};
// Gather wanted deps
depsToCheck.forEach(dep => {
const expectedVersion = ownPackageJson.dependencies[dep];
if (!expectedVersion) {
throw new Error('This dependency list is outdated, fix it.');
}
if (!getSemverRegex().test(expectedVersion)) {
throw new Error(
`The ${dep} package should be pinned, instead got version ${expectedVersion}.`
);
}
expectedVersionsByDep[dep] = expectedVersion;
});
// Verify we don't have other versions up the tree
let currentDir = __dirname;
// eslint-disable-next-line no-constant-condition
while (true) {
const previousDir = currentDir;
currentDir = path.resolve(currentDir, '..');
if (currentDir === previousDir) {
// We've reached the root.
break;
}
const maybeNodeModules = path.resolve(currentDir, 'node_modules');
if (!fs.existsSync(maybeNodeModules)) {
continue;
}
depsToCheck.forEach(dep => {
const maybeDep = path.resolve(maybeNodeModules, dep);
if (!fs.existsSync(maybeDep)) {
return;
}
const maybeDepPackageJson = path.resolve(maybeDep, 'package.json');
if (!fs.existsSync(maybeDepPackageJson)) {
return;
}
const depPackageJson = JSON.parse(
fs.readFileSync(maybeDepPackageJson, 'utf8')
);
const expectedVersion = expectedVersionsByDep[dep];
if (!semver.satisfies(depPackageJson.version, expectedVersion)) {
console.error(
chalk.red(
`\nThere might be a problem with the project dependency tree.\n` +
`It is likely ${chalk.bold(
'not'
)} a bug in Create React App, but something you need to fix locally.\n\n`
) +
`The ${chalk.bold(
ownPackageJson.name
)} package provided by Create React App requires a dependency:\n\n` +
chalk.green(
` "${chalk.bold(dep)}": "${chalk.bold(expectedVersion)}"\n\n`
) +
`Don't try to install it manually: your package manager does it automatically.\n` +
`However, a different version of ${chalk.bold(
dep
)} was detected higher up in the tree:\n\n` +
` ${chalk.bold(chalk.red(maybeDep))} (version: ${chalk.bold(
chalk.red(depPackageJson.version)
)}) \n\n` +
`Manually installing incompatible versions is known to cause hard-to-debug issues.\n\n` +
chalk.red(
`If you would prefer to ignore this check, add ${chalk.bold(
'SKIP_PREFLIGHT_CHECK=true'
)} to an ${chalk.bold('.env')} file in your project.\n` +
`That will permanently disable this message but you might encounter other issues.\n\n`
) +
`To ${chalk.green(
'fix'
)} the dependency tree, try following the steps below in the exact order:\n\n` +
` ${chalk.cyan('1.')} Delete ${chalk.bold(
'package-lock.json'
)} (${chalk.underline('not')} ${chalk.bold(
'package.json'
)}!) and/or ${chalk.bold('yarn.lock')} in your project folder.\n` +
` ${chalk.cyan('2.')} Delete ${chalk.bold(
'node_modules'
)} in your project folder.\n` +
` ${chalk.cyan('3.')} Remove "${chalk.bold(
dep
)}" from ${chalk.bold('dependencies')} and/or ${chalk.bold(
'devDependencies'
)} in the ${chalk.bold(
'package.json'
)} file in your project folder.\n` +
` ${chalk.cyan('4.')} Run ${chalk.bold(
'npm install'
)} or ${chalk.bold(
'yarn'
)}, depending on the package manager you use.\n\n` +
`In most cases, this should be enough to fix the problem.\n` +
`If this has not helped, there are a few other things you can try:\n\n` +
` ${chalk.cyan('5.')} If you used ${chalk.bold(
'npm'
)}, install ${chalk.bold(
'yarn'
)} (http://yarnpkg.com/) and repeat the above steps with it instead.\n` +
` This may help because npm has known issues with package hoisting which may get resolved in future versions.\n\n` +
` ${chalk.cyan('6.')} Check if ${chalk.bold(
maybeDep
)} is outside your project directory.\n` +
` For example, you might have accidentally installed something in your home folder.\n\n` +
` ${chalk.cyan('7.')} Try running ${chalk.bold(
`npm ls ${dep}`
)} in your project folder.\n` +
` This will tell you which ${chalk.underline(
'other'
)} package (apart from the expected ${chalk.bold(
ownPackageJson.name
)}) installed ${chalk.bold(dep)}.\n\n` +
`If nothing else helps, add ${chalk.bold(
'SKIP_PREFLIGHT_CHECK=true'
)} to an ${chalk.bold('.env')} file in your project.\n` +
`That would permanently disable this preflight check in case you want to proceed anyway.\n\n` +
chalk.cyan(
`P.S. We know this message is long but please read the steps above :-) We hope you find them helpful!\n`
)
);
process.exit(1);
}
});
}
}
module.exports = verifyPackageTree;