2020-11-06 03:33:14 +01:00
import chalk from 'chalk'
2021-06-09 03:25:06 +02:00
import { join } from 'path'
2020-05-29 01:39:46 +02:00
2021-04-30 13:09:07 +02:00
import { fileExists } from './file-exists'
import { getOxfordCommaList } from './oxford-comma-list'
import { FatalError } from './fatal-error'
const requiredTSPackages = [
2020-05-29 01:39:46 +02:00
{ file : 'typescript' , pkg : 'typescript' } ,
{ file : '@types/react/index.d.ts' , pkg : '@types/react' } ,
{ file : '@types/node/index.d.ts' , pkg : '@types/node' } ,
]
2021-04-30 13:09:07 +02:00
const requiredLintPackages = [
{ file : 'eslint/lib/api.js' , pkg : 'eslint' } ,
{ file : 'eslint-config-next' , pkg : 'eslint-config-next' } ,
]
2020-05-29 01:39:46 +02:00
export type NecessaryDependencies = {
2021-06-15 03:31:40 +02:00
resolved : Map < string , string >
2020-05-29 01:39:46 +02:00
}
export async function hasNecessaryDependencies (
2021-04-30 13:09:07 +02:00
baseDir : string ,
checkTSDeps : boolean ,
checkESLintDeps : boolean ,
2021-06-03 14:01:24 +02:00
lintDuringBuild : boolean = false
2020-05-29 01:39:46 +02:00
) : Promise < NecessaryDependencies > {
2021-04-30 13:09:07 +02:00
if ( ! checkTSDeps && ! checkESLintDeps ) {
return { resolved : undefined ! }
}
2020-05-29 01:39:46 +02:00
let resolutions = new Map < string , string > ( )
2021-04-30 13:09:07 +02:00
let requiredPackages = checkESLintDeps
? requiredLintPackages
: requiredTSPackages
2020-05-29 01:39:46 +02:00
const missingPackages = requiredPackages . filter ( ( p ) = > {
try {
2021-01-11 15:43:08 +01:00
resolutions . set ( p . pkg , require . resolve ( p . file , { paths : [ baseDir ] } ) )
2020-05-29 01:39:46 +02:00
return false
} catch ( _ ) {
return true
}
} )
if ( missingPackages . length < 1 ) {
2021-04-30 13:09:07 +02:00
return {
2021-06-15 03:31:40 +02:00
resolved : resolutions ,
2021-04-30 13:09:07 +02:00
}
2020-05-29 01:39:46 +02:00
}
const packagesHuman = getOxfordCommaList ( missingPackages . map ( ( p ) = > p . pkg ) )
const packagesCli = missingPackages . map ( ( p ) = > p . pkg ) . join ( ' ' )
2021-06-03 14:01:24 +02:00
const yarnLockFile = join ( baseDir , 'yarn.lock' )
2020-05-29 01:39:46 +02:00
const isYarn = await fileExists ( yarnLockFile ) . catch ( ( ) = > false )
2021-06-03 14:01:24 +02:00
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
2021-06-09 03:25:06 +02:00
? ` 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. `
2021-06-03 14:01:24 +02:00
: ` Once installed, run ${ chalk . bold . cyan ( 'next lint' ) } again. ` )
const removalMsg = checkTSDeps ? removalTSMsg : removalLintMsg
2020-05-29 01:39:46 +02:00
2021-04-30 13:09:07 +02:00
throw new FatalError (
2020-05-29 01:39:46 +02:00
chalk . bold . red (
2021-06-03 14:01:24 +02:00
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. `
2020-05-29 01:39:46 +02:00
) +
'\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
) } ` +
2021-04-30 13:09:07 +02:00
removalMsg +
2020-05-29 01:39:46 +02:00
'\n'
)
}