Skip to content
This repository has been archived by the owner on Nov 22, 2021. It is now read-only.

[WIP] New: implement --init #5

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 14 additions & 8 deletions bin/eslint.js
Expand Up @@ -6,25 +6,31 @@
"use strict"

const debug = require("debug")("eslint-cli")
const debugMode = process.argv.indexOf("--debug") !== -1
const isDebugMode = process.argv.indexOf("--debug") !== -1
const isInit = process.argv.indexOf("--init") !== -1
const cwd = process.cwd()

if (debugMode) {
if (isDebugMode) {
require("debug").enable("eslint-cli")
}

debug("START", process.argv)
debug("ROOT", cwd)

const binPath = require("../lib/get-local-eslint")(cwd) || require("../lib/get-bin-eslint-js")(cwd)
if (binPath != null) {
require(binPath)
if (isInit) {
require("../lib/init")(cwd)
}
else {
//eslint-disable-next-line no-console
console.error(`
const binPath = require("../lib/get-local-eslint")(cwd) || require("../lib/get-bin-eslint-js")(cwd)
if (binPath != null) {
require(binPath)
}
else {
//eslint-disable-next-line no-console
console.error(`
Could not find local ESLint.
Please install ESLint by 'npm install --save-dev eslint'.
`)
process.exitCode = 1
process.exitCode = 1
}
}
4 changes: 2 additions & 2 deletions lib/get-bin-eslint-js.js
Expand Up @@ -26,7 +26,7 @@ module.exports = (basedir) => {
debug("FOUND '%s'", binPath)
return binPath
}
debug("NOT FOUND '%s'", binPath)
debug("NOT_FOUND '%s'", binPath)

// Finish if package.json is found.
if (fs.existsSync(path.join(dir, "package.json"))) {
Expand All @@ -39,6 +39,6 @@ module.exports = (basedir) => {
}
while (dir !== prevDir)

debug("NOT FOUND './bin/eslint.js'")
debug("NOT_FOUND './bin/eslint.js'")
return null
}
4 changes: 2 additions & 2 deletions lib/get-local-eslint.js
Expand Up @@ -11,7 +11,7 @@ const resolve = require("resolve")
* Finds and tries executing a local eslint module.
*
* @param {string} basedir - A path of the directory that it starts searching.
* @returns {string|null} The path of a local eslint module.
* @returns {string|null} The path of the local eslint module.
*/
module.exports = (basedir) => {
try {
Expand All @@ -23,7 +23,7 @@ module.exports = (basedir) => {
if ((err && err.code) !== "MODULE_NOT_FOUND") {
throw err
}
debug("NOT FOUND 'eslint/bin/eslint.js'")
debug("NOT_FOUND 'eslint/bin/eslint.js'")
return null
}
}
57 changes: 57 additions & 0 deletions lib/init/common-questions.js
@@ -0,0 +1,57 @@
/**
* @author Toru Nagashima <https://github.com/mysticatea>
* See LICENSE file in root directory for full license.
*/
"use strict"

module.exports = {
es2015: () => ({
type: "confirm",
name: "es2015",
message: "Are you using ECMAScript 2015 features?",
default: false,
}),
modules: () => ({
type: "confirm",
name: "modules",
message: "Are you using ES modules?",
default: false,
when(answers) {
return answers.es2015 === true
},
}),
envs: () => ({
type: "checkbox",
name: "envs",
message: "Where will your code run?",
default: ["browser"],
choices: [
{ name: "Browser", value: "browser" },
{ name: "Node", value: "node" },
],
}),
commonjs: () => ({
type: "confirm",
name: "commonjs",
message: "Do you use CommonJS?",
default: false,
when(answers) {
return !answers.modules && answers.envs.indexOf("browser") !== -1
},
}),
jsx: () => ({
type: "confirm",
name: "jsx",
message: "Do you use JSX?",
default: false,
}),
react: (context) => ({
type: "confirm",
name: "react",
message: "Do you use React?",
default: false,
when(answers) {
return answers.jsx && context.packageJsonPath != null
},
}),
}
29 changes: 29 additions & 0 deletions lib/init/get-local-eslint.js
@@ -0,0 +1,29 @@
/**
* @author Toru Nagashima <https://github.com/mysticatea>
* See LICENSE file in root directory for full license.
*/
"use strict"

const debug = require("debug")("eslint-cli")
const resolve = require("resolve")

/**
* Finds and tries executing a local eslint module.
*
* @param {string} basedir - A path of the directory that it starts searching.
* @returns {object|null} The local eslint module.
*/
module.exports = (basedir) => {
try {
const binPath = resolve.sync("eslint", { basedir })
debug("FOUND '%s'", binPath)
return require(binPath)
}
catch (err) {
if ((err && err.code) !== "MODULE_NOT_FOUND") {
throw err
}
debug("NOT_FOUND 'eslint'")
return null
}
}
98 changes: 98 additions & 0 deletions lib/init/index.js
@@ -0,0 +1,98 @@
/**
* @author Toru Nagashima <https://github.com/mysticatea>
* See LICENSE file in root directory for full license.
*/
"use strict"

const path = require("path")
const debug = require("debug")("eslint-cli")
const pkgUp = require("pkg-up")
const fetchPluginsAndConfigs = require("./npm-util/fetch-plugins-and-configs")
const installPackages = require("./npm-util/install-packages")
const promptMethod = require("./prompt-method")
const promptFormat = require("./prompt-format")
const saveConfigFile = require("./save-config-file")

//eslint-disable-next-line no-console
const log = console.log.bind(console)

// Error messages.
const MESSAGES = Object.create(null)
MESSAGES.NPM_NOT_FOUND = `
The CLI command 'npm' was not found.
It's required in order to manage dependent packages such as plugins/configs.

Please ensure Node.js is installed correctly.
`
MESSAGES.PACKAGE_JSON_NOT_FOUND = `
The file 'package.json' was not found.
It's required in order to manage dependent packages such as config preset.

Please do 'npm init' before 'eslint --init'.

Further reading: https://docs.npmjs.com/cli/init
`

/**
* Initialize ESLint for the current project.
* @param {string} cwd The path to the current working directory.
* @returns {void}
*/
module.exports = (cwd) => {
debug("START --init on '%s'", cwd)

const packageJsonPath = pkgUp.sync(cwd)
const context = { cwd, packageJsonPath, log }
let config = null
let format = null

return Promise.resolve().then(() => {
if (!packageJsonPath) {
const error = new Error("package.json not found")
error.code = "PACKAGE_JSON_NOT_FOUND"
throw error
}

// Ask to choose the method to initialize.
return promptMethod()
}).then(answers => {
debug("METHOD '%s'", answers.method)

// Ask to configure user's preference.
const promptConfig = require(`./prompt-config/${answers.method}`)
return promptConfig(context)
}).then(config0 => {
debug("CONFIG '%j'", config0)
config = config0

// Ask to choose the saving format.
return promptFormat(context, config)
}).then(format0 => {
debug("FORMAT '%j'", format0)
format = format0

// Install dependencies into project-local (including ESLint itself).
const installESLint = format.installESLint !== false
return fetchPluginsAndConfigs(context, config, installESLint)
}).then(packages =>
installPackages(context, packages)
).then(() => {
// Execute postprocess if exists.
if (config.$postprocess != null) {
const postprocess = config.$postprocess
delete config.$postprocess

return postprocess()
}
return config
}).then(config0 => {
config = config0

// Save the generated config.
const filePath = path.join(cwd, `.eslintrc${format.fileType}`)
return saveConfigFile(filePath, config)
}).catch(error => {
log(MESSAGES[error.code] || error.stack)
process.exitCode = 1
})
}