-
-
Notifications
You must be signed in to change notification settings - Fork 421
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Remove support for npm scripts (#390)
- Update `findBin` to only resolve binaries installed locally or globally. Also add simple caching. - Check pkg scripts when `findBin` fails and print useful message to aid users in migration to newer version config. - Update readme. - Remove dependency `app-root-path`. - Update tests. BREAKING CHANGE: Remove implicit support for running npm scripts. Consider example `lint-staged` config: { "name": "My project", "version": "0.1.0", "scripts": { "my-custom-script": "linter --arg1 --arg2", "precommit": "lint-staged" }, "lint-staged": { "*.js": ["my-custom-script", "git add"] } } The list of commands should be changed to the following: "*.js": ["npm run my-custom-script --", "git add"]
- Loading branch information
1 parent
5a333a0
commit d8b836c
Showing
17 changed files
with
244 additions
and
190 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
'use strict' | ||
|
||
const chalk = require('chalk') | ||
const dedent = require('dedent') | ||
const has = require('lodash/has') | ||
|
||
const warn = msg => { | ||
console.warn(chalk.yellowBright.bold(msg)) | ||
} | ||
|
||
/** | ||
* Checks if the given command or binary name is present in the package.json scripts. This would be | ||
* called if and when resolving a binary fails in `findBin`. | ||
* | ||
* @param {Object} pkg package.json | ||
* @param {string} cmd | ||
* @param {string} binName | ||
* @param {Array<string>} args | ||
* @throws {Error} If a script is found in the pkg for the given `cmd` or `binName`. | ||
*/ | ||
module.exports = function checkPkgScripts(pkg, cmd, binName, args) { | ||
if (pkg && pkg.scripts) { | ||
let scriptName | ||
let script | ||
if (has(pkg.scripts, cmd)) { | ||
scriptName = cmd | ||
script = pkg.scripts[cmd] | ||
} else if (has(pkg.scripts, binName)) { | ||
scriptName = binName | ||
script = pkg.scripts[binName] | ||
} else { | ||
return | ||
} | ||
|
||
const argsStr = args && args.length ? args.join(' ') : '' | ||
warn(dedent` | ||
\`lint-staged\` no longer supports running scripts defined in package.json. | ||
The same behavior can be achieved by changing the command to any of the following: | ||
- \`npm run ${scriptName} -- ${argsStr}\` | ||
- \`${script} ${argsStr}\` | ||
`) | ||
throw new Error(`Could not resolve binary for \`${cmd}\``) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,86 +1,47 @@ | ||
'use strict' | ||
|
||
const appRoot = require('app-root-path') | ||
const npmWhich = require('npm-which')(process.cwd()) | ||
const checkPkgScripts = require('./checkPkgScripts') | ||
|
||
// Find and load the package.json at the root of the project. | ||
const pkg = require(appRoot.resolve('package.json')) // eslint-disable-line import/no-dynamic-require | ||
const debug = require('debug')('lint-staged:find-bin') | ||
|
||
module.exports = function findBin(cmd, scripts, debugMode) { | ||
const cache = new Map() | ||
|
||
module.exports = function findBin(cmd) { | ||
debug('Resolving binary for command `%s`', cmd) | ||
const npmArgs = (bin, args) => | ||
// We always add `--` even if args are not defined. This is required | ||
// because we pass filenames later. | ||
['run', debugMode ? undefined : '--silent', bin, '--'] | ||
// args could be undefined but we filter that out. | ||
.concat(args) | ||
.filter(arg => arg !== undefined) | ||
|
||
/* | ||
* If package.json has script with cmd defined we want it to be executed | ||
* first. For finding the bin from scripts defined in package.json, there | ||
* are 2 possibilities. It's a command which does not have any arguments | ||
* passed to it in the lint-staged config. Or it could be something like | ||
* `kcd-scripts` which has arguments such as `format`, `lint` passed to it. | ||
* But we always cannot assume that the cmd, which has a space in it, is of | ||
* the format `bin argument` because it is legal to define a package.json | ||
* script with space in it's name. So we do 2 types of lookup. First a naive | ||
* lookup which just looks for the scripts entry with cmd. Then we split on | ||
* space, parse the bin and args, and try again. | ||
* | ||
* Related: | ||
* - https://github.com/kentcdodds/kcd-scripts/pull/3 | ||
* - https://github.com/okonet/lint-staged/issues/294 | ||
* Try to locate the binary in node_modules/.bin and if this fails, in | ||
* $PATH. | ||
* | ||
* Example: | ||
* This allows to use linters installed for the project: | ||
* | ||
* "scripts": { | ||
* "my cmd": "echo deal-wth-it", | ||
* "demo-bin": "node index.js" | ||
* }, | ||
* "lint-staged": { | ||
* "*.js": ["my cmd", "demo-bin hello"] | ||
* } | ||
* "lint-staged": { | ||
* "*.js": "eslint" | ||
* } | ||
*/ | ||
if (scripts[cmd] !== undefined) { | ||
// Support for scripts from package.json | ||
debug('`%s` resolved to npm script - `%s`', cmd, scripts[cmd]) | ||
return { bin: 'npm', args: npmArgs(cmd) } | ||
} | ||
|
||
const parts = cmd.split(' ') | ||
let bin = parts[0] | ||
const binName = parts[0] | ||
const args = parts.splice(1) | ||
|
||
if (scripts[bin] !== undefined) { | ||
debug('`%s` resolved to npm script - `%s`', bin, scripts[bin]) | ||
return { bin: 'npm', args: npmArgs(bin, args) } | ||
if (cache.has(binName)) { | ||
debug('Resolving binary for `%s` from cache', binName) | ||
return { bin: cache.get(binName), args } | ||
} | ||
|
||
/* | ||
* If cmd wasn't found in package.json scripts | ||
* we'll try to locate the binary in node_modules/.bin | ||
* and if this fails in $PATH. | ||
* | ||
* This is useful for shorter configs like: | ||
* | ||
* "lint-staged": { | ||
* "*.js": "eslint" | ||
* } | ||
* | ||
* without adding | ||
* | ||
* "scripts" { | ||
* "eslint": "eslint" | ||
* } | ||
*/ | ||
|
||
try { | ||
/* npm-which tries to resolve the bin in local node_modules/.bin */ | ||
/* and if this fails it look in $PATH */ | ||
bin = npmWhich.sync(bin) | ||
const bin = npmWhich.sync(binName) | ||
debug('Binary for `%s` resolved to `%s`', cmd, bin) | ||
cache.set(binName, bin) | ||
return { bin, args } | ||
} catch (err) { | ||
throw new Error(`${bin} could not be found. Try \`npm install ${bin}\`.`) | ||
// throw helpful error if matching script is present in package.json | ||
checkPkgScripts(pkg, cmd, binName, args) | ||
throw new Error(`${binName} could not be found. Try \`npm install ${binName}\`.`) | ||
} | ||
|
||
debug('Binary for `%s` resolved to `%s`', cmd, bin) | ||
return { bin, args } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,14 @@ | ||
const mockFn = jest.fn(path => { | ||
if (path.includes('missing')) { | ||
throw new Error(`not found: ${path}`) | ||
} | ||
return path | ||
}) | ||
|
||
module.exports = function npmWhich() { | ||
return { | ||
sync(path) { | ||
if (path.includes('missing')) { | ||
throw new Error(`not found: ${path}`) | ||
} | ||
return path | ||
} | ||
sync: mockFn | ||
} | ||
} | ||
|
||
module.exports.mockFn = mockFn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`checkPkgScripts throws if the binary name is defined in script 1`] = ` | ||
" | ||
WARN \`lint-staged\` no longer supports running scripts defined in package.json. | ||
The same behavior can be achieved by changing the command to any of the following: | ||
- \`npm run lint -- --fix\` | ||
- \`eslint . --fix\`" | ||
`; | ||
|
||
exports[`checkPkgScripts throws if the cmd is defined in script 1`] = ` | ||
" | ||
WARN \`lint-staged\` no longer supports running scripts defined in package.json. | ||
The same behavior can be achieved by changing the command to any of the following: | ||
- \`npm run lint -- \` | ||
- \`eslint . \`" | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`findBin should throw a helpful error if the cmd is present in pkg scripts 1`] = ` | ||
" | ||
WARN \`lint-staged\` no longer supports running scripts defined in package.json. | ||
The same behavior can be achieved by changing the command to any of the following: | ||
- \`npm run lint -- \` | ||
- \`eslint . \`" | ||
`; |
Oops, something went wrong.