import chalk from 'chalk' import { join } from 'path' import { fileExists } from './file-exists' import { getOxfordCommaList } from './oxford-comma-list' import { FatalError } from './fatal-error' const requiredTSPackages = [ { file: 'typescript', pkg: 'typescript' }, { file: '@types/react/index.d.ts', pkg: '@types/react' }, { file: '@types/node/index.d.ts', pkg: '@types/node' }, ] const requiredLintPackages = [ { file: 'eslint/lib/api.js', pkg: 'eslint' }, { file: 'eslint-config-next', pkg: 'eslint-config-next' }, ] export type NecessaryDependencies = { resolved: Map } export async function hasNecessaryDependencies( baseDir: string, checkTSDeps: boolean, checkESLintDeps: boolean, lintDuringBuild: boolean = false ): Promise { if (!checkTSDeps && !checkESLintDeps) { return { resolved: undefined! } } let resolutions = new Map() let requiredPackages = checkESLintDeps ? requiredLintPackages : requiredTSPackages const missingPackages = requiredPackages.filter((p) => { try { resolutions.set(p.pkg, require.resolve(p.file, { paths: [baseDir] })) return false } catch (_) { return true } }) if (missingPackages.length < 1) { return { resolved: resolutions, } } const packagesHuman = getOxfordCommaList(missingPackages.map((p) => p.pkg)) const packagesCli = missingPackages.map((p) => p.pkg).join(' ') const yarnLockFile = join(baseDir, 'yarn.lock') const isYarn = await fileExists(yarnLockFile).catch(() => false) const removalTSMsg = '\n\n' + chalk.bold( 'If you are not trying to use TypeScript, please remove the ' + chalk.cyan('tsconfig.json') + ' file from your package root (and any TypeScript files in your pages directory).' ) const removalLintMsg = `\n\n` + (lintDuringBuild ? `If you do not want to run ESLint during builds, disable it in next.config.js. See https://nextjs.org/docs/api-reference/next.config.js/ignoring-eslint.` : `Once installed, run ${chalk.bold.cyan('next lint')} again.`) const removalMsg = checkTSDeps ? removalTSMsg : removalLintMsg throw new FatalError( chalk.bold.red( checkTSDeps ? `It looks like you're trying to use TypeScript but do not have the required package(s) installed.` : `To use ESLint, additional required package(s) must be installed.` ) + '\n\n' + chalk.bold(`Please install ${chalk.bold(packagesHuman)} by running:`) + '\n\n' + `\t${chalk.bold.cyan( (isYarn ? 'yarn add --dev' : 'npm install --save-dev') + ' ' + packagesCli )}` + removalMsg + '\n' ) }