UNPKG

next

Version:

The React Framework

268 lines (267 loc) 13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.runLintCheck = runLintCheck; var _fs = require("fs"); var _chalk = _interopRequireDefault(require("next/dist/compiled/chalk")); var _path = _interopRequireDefault(require("path")); var _findUp = _interopRequireDefault(require("next/dist/compiled/find-up")); var _semver = _interopRequireDefault(require("next/dist/compiled/semver")); var CommentJson = _interopRequireWildcard(require("next/dist/compiled/comment-json")); var _customFormatter = require("./customFormatter"); var _writeDefaultConfig = require("./writeDefaultConfig"); var _hasEslintConfiguration = require("./hasEslintConfiguration"); var _constants = require("../constants"); var _findPagesDir = require("../find-pages-dir"); var _installDependencies = require("../install-dependencies"); var _hasNecessaryDependencies = require("../has-necessary-dependencies"); var _isYarn = require("../is-yarn"); var Log = _interopRequireWildcard(require("../../build/output/log")); var _isError = _interopRequireWildcard(require("../is-error")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for(var key in obj){ if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } // 0 is off, 1 is warn, 2 is error. See https://eslint.org/docs/user-guide/configuring/rules#configuring-rules const VALID_SEVERITY = [ 'off', 'warn', 'error' ]; function isValidSeverity(severity) { return VALID_SEVERITY.includes(severity); } const requiredPackages = [ { file: 'eslint', pkg: 'eslint', exportsRestrict: false }, { file: 'eslint-config-next', pkg: 'eslint-config-next', exportsRestrict: false }, ]; async function cliPrompt() { console.log(_chalk.default.bold(`${_chalk.default.cyan('?')} How would you like to configure ESLint? https://nextjs.org/docs/basic-features/eslint`)); try { const cliSelect = (await Promise.resolve(require('next/dist/compiled/cli-select'))).default; const { value } = await cliSelect({ values: _constants.ESLINT_PROMPT_VALUES, valueRenderer: ({ title , recommended }, selected)=>{ const name = selected ? _chalk.default.bold.underline.cyan(title) : title; return name + (recommended ? _chalk.default.bold.yellow(' (recommended)') : ''); }, selected: _chalk.default.cyan('❯ '), unselected: ' ' }); return { config: value === null || value === void 0 ? void 0 : value.config }; } catch { return { config: null }; } } async function lint(baseDir, lintDirs, eslintrcFile, pkgJsonPath, lintDuringBuild = false, eslintOptions = null, reportErrorsOnly = false, maxWarnings = -1, formatter = null) { try { var ref, ref1; // Load ESLint after we're sure it exists: const deps = await (0, _hasNecessaryDependencies).hasNecessaryDependencies(baseDir, requiredPackages); if (deps.missing.some((dep)=>dep.pkg === 'eslint' )) { Log.error(`ESLint must be installed${lintDuringBuild ? ' in order to run during builds:' : ':'} ${_chalk.default.bold.cyan(await (0, _isYarn).isYarn(baseDir) ? 'yarn add --dev eslint' : 'npm install --save-dev eslint')}`); return null; } const mod = await Promise.resolve(require(deps.resolved.get('eslint'))); const { ESLint } = mod; var ref2; let eslintVersion = (ref2 = ESLint === null || ESLint === void 0 ? void 0 : ESLint.version) !== null && ref2 !== void 0 ? ref2 : mod === null || mod === void 0 ? void 0 : (ref = mod.CLIEngine) === null || ref === void 0 ? void 0 : ref.version; if (!eslintVersion || _semver.default.lt(eslintVersion, '7.0.0')) { return `${_chalk.default.red('error')} - Your project has an older version of ESLint installed${eslintVersion ? ' (' + eslintVersion + ')' : ''}. Please upgrade to ESLint version 7 or above`; } let options = { useEslintrc: true, baseConfig: {}, errorOnUnmatchedPattern: false, extensions: [ '.js', '.jsx', '.ts', '.tsx' ], cache: true, ...eslintOptions }; let eslint = new ESLint(options); let nextEslintPluginIsEnabled = false; const nextRulesEnabled = new Map(); const pagesDirRules = [ '@next/next/no-html-link-for-pages' ]; for (const configFile of [ eslintrcFile, pkgJsonPath ]){ var ref3; if (!configFile) continue; const completeConfig = await eslint.calculateConfigForFile(configFile); if ((ref3 = completeConfig.plugins) === null || ref3 === void 0 ? void 0 : ref3.includes('@next/next')) { nextEslintPluginIsEnabled = true; for (const [name, [severity]] of Object.entries(completeConfig.rules)){ if (!name.startsWith('@next/next/')) { continue; } if (typeof severity === 'number' && severity >= 0 && severity < VALID_SEVERITY.length) { nextRulesEnabled.set(name, VALID_SEVERITY[severity]); } else if (typeof severity === 'string' && isValidSeverity(severity)) { nextRulesEnabled.set(name, severity); } } break; } } const pagesDir = (0, _findPagesDir).findPagesDir(baseDir); if (nextEslintPluginIsEnabled) { let updatedPagesDir = false; for (const rule of pagesDirRules){ var ref4, ref5; if (!((ref4 = options.baseConfig.rules) === null || ref4 === void 0 ? void 0 : ref4[rule]) && !((ref5 = options.baseConfig.rules) === null || ref5 === void 0 ? void 0 : ref5[rule.replace('@next/next', '@next/babel-plugin-next')])) { if (!options.baseConfig.rules) { options.baseConfig.rules = {}; } options.baseConfig.rules[rule] = [ 1, pagesDir ]; updatedPagesDir = true; } } if (updatedPagesDir) { eslint = new ESLint(options); } } else { Log.warn('The Next.js plugin was not detected in your ESLint configuration. See https://nextjs.org/docs/basic-features/eslint#migrating-existing-config'); } const lintStart = process.hrtime(); let results = await eslint.lintFiles(lintDirs); let selectedFormatter = null; if (options.fix) await ESLint.outputFixes(results); if (reportErrorsOnly) results = await ESLint.getErrorResults(results) // Only return errors if --quiet flag is used ; if (formatter) selectedFormatter = await eslint.loadFormatter(formatter); const formattedResult = (0, _customFormatter).formatResults(baseDir, results, selectedFormatter === null || selectedFormatter === void 0 ? void 0 : selectedFormatter.format); const lintEnd = process.hrtime(lintStart); const totalWarnings = results.reduce((sum, file)=>sum + file.warningCount , 0); return { output: formattedResult.output, isError: ((ref1 = ESLint.getErrorResults(results)) === null || ref1 === void 0 ? void 0 : ref1.length) > 0 || maxWarnings >= 0 && totalWarnings > maxWarnings, eventInfo: { durationInSeconds: lintEnd[0], eslintVersion: eslintVersion, lintedFilesCount: results.length, lintFix: !!options.fix, nextEslintPluginVersion: nextEslintPluginIsEnabled && deps.resolved.has('eslint-config-next') ? require(_path.default.join(_path.default.dirname(deps.resolved.get('eslint-config-next')), 'package.json')).version : null, nextEslintPluginErrorsCount: formattedResult.totalNextPluginErrorCount, nextEslintPluginWarningsCount: formattedResult.totalNextPluginWarningCount, nextRulesEnabled: Object.fromEntries(nextRulesEnabled) } }; } catch (err) { if (lintDuringBuild) { Log.error(`ESLint: ${(0, _isError).default(err) && err.message ? err.message.replace(/\n/g, ' ') : err}`); return null; } else { throw (0, _isError).getProperError(err); } } } async function runLintCheck(baseDir, lintDirs, lintDuringBuild = false, eslintOptions = null, reportErrorsOnly = false, maxWarnings = -1, formatter = null, strict = false) { try { var ref; // Find user's .eslintrc file // See: https://eslint.org/docs/user-guide/configuring/configuration-files#configuration-file-formats const eslintrcFile = (ref = await (0, _findUp).default([ '.eslintrc.js', '.eslintrc.cjs', '.eslintrc.yaml', '.eslintrc.yml', '.eslintrc.json', '.eslintrc', ], { cwd: baseDir })) !== null && ref !== void 0 ? ref : null; var ref6; const pkgJsonPath = (ref6 = await (0, _findUp).default('package.json', { cwd: baseDir })) !== null && ref6 !== void 0 ? ref6 : null; let packageJsonConfig = null; if (pkgJsonPath) { const pkgJsonContent = await _fs.promises.readFile(pkgJsonPath, { encoding: 'utf8' }); packageJsonConfig = CommentJson.parse(pkgJsonContent); } const config = await (0, _hasEslintConfiguration).hasEslintConfiguration(eslintrcFile, packageJsonConfig); let deps; if (config.exists) { // Run if ESLint config exists return await lint(baseDir, lintDirs, eslintrcFile, pkgJsonPath, lintDuringBuild, eslintOptions, reportErrorsOnly, maxWarnings, formatter); } else { // Display warning if no ESLint configuration is present during "next build" if (lintDuringBuild) { Log.warn(`No ESLint configuration detected. Run ${_chalk.default.bold.cyan('next lint')} to begin setup`); return null; } else { // Ask user what config they would like to start with for first time "next lint" setup const { config: selectedConfig } = strict ? _constants.ESLINT_PROMPT_VALUES.find((opt)=>opt.title === 'Strict' ) : await cliPrompt(); if (selectedConfig == null) { // Show a warning if no option is selected in prompt Log.warn('If you set up ESLint yourself, we recommend adding the Next.js ESLint plugin. See https://nextjs.org/docs/basic-features/eslint#migrating-existing-config'); return null; } else { // Check if necessary deps installed, and install any that are missing deps = await (0, _hasNecessaryDependencies).hasNecessaryDependencies(baseDir, requiredPackages); if (deps.missing.length > 0) await (0, _installDependencies).installDependencies(baseDir, deps.missing, true); // Write default ESLint config. // Check for /pages and src/pages is to make sure this happens in Next.js folder if ((0, _findPagesDir).existsSync(_path.default.join(baseDir, 'pages')) || (0, _findPagesDir).existsSync(_path.default.join(baseDir, 'src/pages'))) { await (0, _writeDefaultConfig).writeDefaultConfig(baseDir, config, selectedConfig, eslintrcFile, pkgJsonPath, packageJsonConfig); } } Log.ready(`ESLint has successfully been configured. Run ${_chalk.default.bold.cyan('next lint')} again to view warnings and errors.`); return null; } } } catch (err) { throw err; } } //# sourceMappingURL=runLintCheck.js.map