UNPKG

@expo/cli

Version:
173 lines (172 loc) 7.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "ESLintProjectPrerequisite", { enumerable: true, get: ()=>ESLintProjectPrerequisite }); function _jsonFile() { const data = /*#__PURE__*/ _interopRequireDefault(require("@expo/json-file")); _jsonFile = function() { return data; }; return data; } function _promises() { const data = /*#__PURE__*/ _interopRequireDefault(require("fs/promises")); _promises = function() { return data; }; return data; } function _path() { const data = /*#__PURE__*/ _interopRequireDefault(require("path")); _path = function() { return data; }; return data; } const _log = require("../log"); const _prerequisite = require("../start/doctor/Prerequisite"); const _ensureDependenciesAsync = require("../start/doctor/dependencies/ensureDependenciesAsync"); const _findUp = require("../utils/findUp"); const _interactive = require("../utils/interactive"); const _prompts = require("../utils/prompts"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const debug = require("debug")("expo:lint"); class ESLintProjectPrerequisite extends _prerequisite.ProjectPrerequisite { async assertImplementation() { const hasEslintConfig = await eslintIsConfigured(this.projectRoot); const hasLintScript = await lintScriptIsConfigured(this.projectRoot); return hasEslintConfig && hasLintScript; } async bootstrapAsync() { debug("Setting up ESLint"); const hasEslintConfig = await eslintIsConfigured(this.projectRoot); if (!hasEslintConfig) { if (!(0, _interactive.isInteractive)()) { _log.Log.warn(`No ESLint config found. Configuring automatically.`); } else { const shouldSetupLint = await (0, _prompts.confirmAsync)({ message: "No ESLint config found. Install and configure ESLint in this project?" }); if (!shouldSetupLint) { throw new _prerequisite.PrerequisiteCommandError("ESLint is not configured for this project."); } } // TODO(cedric): if we want to add prettier, also configure proper prettier rules // const shouldIncludePrettier = await confirmAsync({ // message: 'Include Prettier?', // }); // if (shouldIncludePrettier) { // packages.push({ file: 'prettier/package.json', pkg: 'prettier', dev: true }); // packages.push({ // file: 'eslint-config-prettier/package.json', // pkg: 'eslint-config-prettier', // dev: true, // }); // packages.push({ // file: 'eslint-plugin-prettier/package.json', // pkg: 'eslint-plugin-prettier', // dev: true, // }); // } await this._ensureDependenciesInstalledAsync({ skipPrompt: true, isProjectMutable: true }); // TODO(cedric): if we want to add prettier, also configure proper prettier rules // if (shouldIncludePrettier) { // await fs.writeFile(path.join(this.projectRoot, '.prettierrc'), '{}', 'utf8'); // } await _promises().default.writeFile(_path().default.join(this.projectRoot, ".eslintrc.js"), await _promises().default.readFile(require.resolve(`@expo/cli/static/template/.eslintrc.js`), "utf8"), "utf8"); } const hasLintScript = await lintScriptIsConfigured(this.projectRoot); if (!hasLintScript) { const scripts = _jsonFile().default.read(_path().default.join(this.projectRoot, "package.json")).scripts; await _jsonFile().default.setAsync(_path().default.join(this.projectRoot, "package.json"), "scripts", typeof scripts === "object" ? { ...scripts, lint: "eslint ." } : { lint: "eslint ." }, { json5: false }); } _log.Log.log(); _log.Log.log("ESlint has been configured \uD83C\uDF89"); _log.Log.log(); return true; } async _ensureDependenciesInstalledAsync({ skipPrompt , isProjectMutable }) { try { return await (0, _ensureDependenciesAsync.ensureDependenciesAsync)(this.projectRoot, { skipPrompt, isProjectMutable, installMessage: "ESLint is required to lint your project.", warningMessage: "ESLint not installed, unable to set up linting for your project.", requiredPackages: [ { version: "^8.57.0", pkg: "eslint", file: "eslint/package.json", dev: true }, { pkg: "eslint-config-expo", file: "eslint-config-expo/package.json", dev: true }, ] }); } catch (error) { this.resetAssertion(); throw error; } } } async function eslintIsConfigured(projectRoot) { debug("Ensuring ESlint is configured in", projectRoot); // TODO(cedric): drop `package.json` check once we swap to flat config const packageFile = await _jsonFile().default.readAsync(_path().default.join(projectRoot, "package.json")); if (typeof packageFile.eslintConfig === "object" && Object.keys(packageFile.eslintConfig).length > 0) { debug("Found ESlint config in package.json"); return true; } const eslintConfigFiles = [ // TODO(cedric): drop these files once we swap to flat config // See: https://eslint.org/docs/latest/use/configure/configuration-files-deprecated ".eslintrc.js", ".eslintrc.cjs", ".eslintrc.yaml", ".eslintrc.yml", ".eslintrc.json", ]; for (const configFile of eslintConfigFiles){ const configPath = (0, _findUp.findFileInParents)(projectRoot, configFile); const configIsEmpty = configPath ? await eslintConfigIsEmpty(configPath) : null; if (configPath && !configIsEmpty) { debug("Found ESlint config file:", configPath); return true; } else if (configPath && configIsEmpty) { debug("Skipping empty ESlint config file:", configPath); } } return false; } /** Determine if the eslint config file is empty. */ async function eslintConfigIsEmpty(filePath) { const content = await _promises().default.readFile(filePath, "utf8").then((text)=>text.trim().replaceAll(/\s|\r\n|\n|\r/g, ""), ()=>null); return !content || content === "{}" || content === "---" || content.startsWith("module.exports={}") || content.startsWith("exportdefault{}") || content.startsWith("exportdefault[]") // .eslint.config.mjs ; } async function lintScriptIsConfigured(projectRoot) { var ref; const packageFile = await _jsonFile().default.readAsync(_path().default.join(projectRoot, "package.json")); return typeof ((ref = packageFile.scripts) == null ? void 0 : ref.lint) === "string"; } //# sourceMappingURL=ESlintPrerequisite.js.map