lint-staged 15.5.1 → 16.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION.md +70 -0
- package/README.md +21 -94
- package/bin/lint-staged.js +0 -3
- package/lib/execGit.js +13 -8
- package/lib/getFunctionTask.js +38 -0
- package/lib/{resolveTaskFn.js → getSpawnedTask.js} +41 -65
- package/lib/{makeCmdTasks.js → getSpawnedTasks.js} +7 -7
- package/lib/getStagedFiles.js +1 -1
- package/lib/index.d.ts +10 -10
- package/lib/index.js +0 -3
- package/lib/runAll.js +13 -12
- package/lib/searchConfigs.js +1 -1
- package/lib/validateConfig.js +20 -32
- package/lib/validateOptions.js +0 -13
- package/package.json +17 -16
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
## v16
|
|
2
|
+
|
|
3
|
+
#### Updated Node.js version requirement
|
|
4
|
+
|
|
5
|
+
The lowest supported Node.js version is `18.19.0` or `20.5.0`, following requirements of `execa@9`. Please upgrade your Node.js version.
|
|
6
|
+
|
|
7
|
+
#### Removed validation for removed advanced configuration file options
|
|
8
|
+
|
|
9
|
+
Advanced configuration options (removed in v9) are no longer validated separately, and might be treated as valid globs for tasks. Please do not try to use advanced config options anymore, they haven't been supported since v8.
|
|
10
|
+
|
|
11
|
+
#### Removed the `--shell` option
|
|
12
|
+
|
|
13
|
+
The `--shell` flag has been removed and _lint-staged_ no longer supports evaluating commands directly via a shell. To migrate existing commands, you can create a shell script and invoke it instead. Lint-staged will pass matched staged files as a list of arguments, accessible via `"$@"`:
|
|
14
|
+
|
|
15
|
+
```shell
|
|
16
|
+
# my-script.sh
|
|
17
|
+
#!/bin/bash
|
|
18
|
+
|
|
19
|
+
echo "Staged files: $@"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
and
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{ "*.js": "my-script.sh" }
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
If you were using the shell option to avoid passing filenames to tasks, for example `bash -c 'tsc --noEmit'`, use the function syntax instead:
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
export default { '*.ts': () => 'tsc --noEmit' }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
#### Processes are spawned using `nano-spawn`
|
|
35
|
+
|
|
36
|
+
Processes are spawned using [nano-spawn](https://github.com/sindresorhus/nano-spawn) instead of [execa](https://github.com/sindresorhus/execa). If you are using Node.js scripts as tasks, you might need to explicitly run them with `node`, especially when using Windows:
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"*.js": "node my-js-linter.js"
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## v15
|
|
45
|
+
|
|
46
|
+
- Since `v15.0.0` _lint-staged_ no longer supports Node.js 16. Please upgrade your Node.js version to at least `18.12.0`.
|
|
47
|
+
|
|
48
|
+
## v14
|
|
49
|
+
|
|
50
|
+
- Since `v14.0.0` _lint-staged_ no longer supports Node.js 14. Please upgrade your Node.js version to at least `16.14.0`.
|
|
51
|
+
|
|
52
|
+
## v13
|
|
53
|
+
|
|
54
|
+
- Since `v13.0.0` _lint-staged_ no longer supports Node.js 12. Please upgrade your Node.js version to at least `14.13.1`, or `16.0.0` onward.
|
|
55
|
+
- Version `v13.3.0` was incorrectly released including code of version `v14.0.0`. This means the breaking changes of `v14` are also included in `v13.3.0`, the last `v13` version released
|
|
56
|
+
|
|
57
|
+
## v12
|
|
58
|
+
|
|
59
|
+
- Since `v12.0.0` _lint-staged_ is a pure ESM module, so make sure your Node.js version is at least `12.20.0`, `14.13.1`, or `16.0.0`. Read more about ESM modules from the official [Node.js Documentation site here](https://nodejs.org/api/esm.html#introduction).
|
|
60
|
+
|
|
61
|
+
## v10
|
|
62
|
+
|
|
63
|
+
- From `v10.0.0` onwards any new modifications to originally staged files will be automatically added to the commit.
|
|
64
|
+
If your task previously contained a `git add` step, please remove this.
|
|
65
|
+
The automatic behaviour ensures there are less race-conditions,
|
|
66
|
+
since trying to run multiple git operations at the same time usually results in an error.
|
|
67
|
+
- From `v10.0.0` onwards, lint-staged uses git stashes to improve speed and provide backups while running.
|
|
68
|
+
Since git stashes require at least an initial commit, you shouldn't run lint-staged in an empty repo.
|
|
69
|
+
- From `v10.0.0` onwards, lint-staged requires Node.js version 10.13.0 or later.
|
|
70
|
+
- From `v10.0.0` onwards, lint-staged will abort the commit if linter tasks undo all staged changes. To allow creating an empty commit, please use the `--allow-empty` option.
|
package/README.md
CHANGED
|
@@ -79,33 +79,7 @@ See [Releases](https://github.com/okonet/lint-staged/releases).
|
|
|
79
79
|
|
|
80
80
|
### Migration
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
- Since `v15.0.0` _lint-staged_ no longer supports Node.js 16. Please upgrade your Node.js version to at least `18.12.0`.
|
|
85
|
-
|
|
86
|
-
#### v14
|
|
87
|
-
|
|
88
|
-
- Since `v14.0.0` _lint-staged_ no longer supports Node.js 14. Please upgrade your Node.js version to at least `16.14.0`.
|
|
89
|
-
|
|
90
|
-
#### v13
|
|
91
|
-
|
|
92
|
-
- Since `v13.0.0` _lint-staged_ no longer supports Node.js 12. Please upgrade your Node.js version to at least `14.13.1`, or `16.0.0` onward.
|
|
93
|
-
- Version `v13.3.0` was incorrectly released including code of version `v14.0.0`. This means the breaking changes of `v14` are also included in `v13.3.0`, the last `v13` version released
|
|
94
|
-
|
|
95
|
-
#### v12
|
|
96
|
-
|
|
97
|
-
- Since `v12.0.0` _lint-staged_ is a pure ESM module, so make sure your Node.js version is at least `12.20.0`, `14.13.1`, or `16.0.0`. Read more about ESM modules from the official [Node.js Documentation site here](https://nodejs.org/api/esm.html#introduction).
|
|
98
|
-
|
|
99
|
-
#### v10
|
|
100
|
-
|
|
101
|
-
- From `v10.0.0` onwards any new modifications to originally staged files will be automatically added to the commit.
|
|
102
|
-
If your task previously contained a `git add` step, please remove this.
|
|
103
|
-
The automatic behaviour ensures there are less race-conditions,
|
|
104
|
-
since trying to run multiple git operations at the same time usually results in an error.
|
|
105
|
-
- From `v10.0.0` onwards, lint-staged uses git stashes to improve speed and provide backups while running.
|
|
106
|
-
Since git stashes require at least an initial commit, you shouldn't run lint-staged in an empty repo.
|
|
107
|
-
- From `v10.0.0` onwards, lint-staged requires Node.js version 10.13.0 or later.
|
|
108
|
-
- From `v10.0.0` onwards, lint-staged will abort the commit if linter tasks undo all staged changes. To allow creating an empty commit, please use the `--allow-empty` option.
|
|
82
|
+
For breaking changes, see [MIGRATION.md](./MIGRATION.md).
|
|
109
83
|
|
|
110
84
|
## Command line flags
|
|
111
85
|
|
|
@@ -130,7 +104,6 @@ Options:
|
|
|
130
104
|
--no-hide-partially-staged disable hiding unstaged changes from partially staged files
|
|
131
105
|
-q, --quiet disable lint-staged’s own console output (default: false)
|
|
132
106
|
-r, --relative pass relative filepaths to tasks (default: false)
|
|
133
|
-
-x, --shell [path] skip parsing of tasks for better shell support (default: false)
|
|
134
107
|
-v, --verbose show task output even when tasks succeed; by default only failed output is
|
|
135
108
|
shown (default: false)
|
|
136
109
|
-h, --help display help for command
|
|
@@ -160,7 +133,6 @@ Any lost modifications can be restored from a git stash:
|
|
|
160
133
|
- **`--no-hide-partially-staged`**: By default, unstaged changes from partially staged files will be hidden. This option will disable this behavior and include all unstaged changes in partially staged files. Can be re-enabled with `--hide-partially-staged`
|
|
161
134
|
- **`--quiet`**: Supress all CLI output, except from tasks.
|
|
162
135
|
- **`--relative`**: Pass filepaths relative to `process.cwd()` (where `lint-staged` runs) to tasks. Default is `false`.
|
|
163
|
-
- **`--shell`**: By default task commands will be parsed for speed and security. This has the side-effect that regular shell scripts might not work as expected. You can skip parsing of commands with this option. To use a specific shell, use a path like `--shell "/bin/bash"`.
|
|
164
136
|
- **`--verbose`**: Show task output even when tasks succeed. By default only failed output is shown.
|
|
165
137
|
|
|
166
138
|
## Configuration
|
|
@@ -180,7 +152,7 @@ _Lint-staged_ can be configured in many ways:
|
|
|
180
152
|
whether your project's _package.json_ contains the `"type": "module"` option or not.
|
|
181
153
|
- Pass a configuration file using the `--config` or `-c` flag
|
|
182
154
|
|
|
183
|
-
Configuration should be an object where each value is a command to run and its key is a glob pattern to use for this command. This package uses [micromatch](https://github.com/micromatch/micromatch) for glob patterns. JavaScript files can also export advanced configuration as a function. See [Using JS configuration files](#using-js-configuration-files) for more info.
|
|
155
|
+
Configuration should be an object where each value is a **command** to run and its key is a glob pattern to use for this command. This package uses [micromatch](https://github.com/micromatch/micromatch) for glob patterns. JavaScript files can also export advanced configuration as a function. See [Using JS configuration files](#using-js-configuration-files) for more info.
|
|
184
156
|
|
|
185
157
|
You can also place multiple configuration files in different directories inside a project. For a given staged file, the closest configuration file will always be used. See ["How to use `lint-staged` in a multi-package monorepo?"](#how-to-use-lint-staged-in-a-multi-package-monorepo) for more info and an example.
|
|
186
158
|
|
|
@@ -363,12 +335,19 @@ export default {
|
|
|
363
335
|
|
|
364
336
|
This will result in _lint-staged_ first running `eslint .` (matching _all_ files), and if it passes, `prettier --write file-1.js file-2.js`, when you have staged files `file-1.js`, `file-2.js` and `README.md`.
|
|
365
337
|
|
|
366
|
-
###
|
|
338
|
+
### JavaScript Functions
|
|
367
339
|
|
|
368
|
-
|
|
340
|
+
You can also configure _lint-staged_ to run a JavaScript/Node.js script directly, passing the list of staged files as an argument:
|
|
369
341
|
|
|
370
|
-
```
|
|
371
|
-
|
|
342
|
+
```js
|
|
343
|
+
export default {
|
|
344
|
+
'*.js': {
|
|
345
|
+
title: 'Log staged JS files to console',
|
|
346
|
+
task: async (files) => {
|
|
347
|
+
console.log('Staged JS files:', files)
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
}
|
|
372
351
|
```
|
|
373
352
|
|
|
374
353
|
### Example: Export a function to build your own matchers
|
|
@@ -777,7 +756,6 @@ const success = await lintStaged({
|
|
|
777
756
|
maxArgLength: null,
|
|
778
757
|
quiet: false,
|
|
779
758
|
relative: false,
|
|
780
|
-
shell: false,
|
|
781
759
|
stash: true,
|
|
782
760
|
verbose: false,
|
|
783
761
|
})
|
|
@@ -795,7 +773,6 @@ const success = await lintStaged({
|
|
|
795
773
|
maxArgLength: null,
|
|
796
774
|
quiet: false,
|
|
797
775
|
relative: false,
|
|
798
|
-
shell: false,
|
|
799
776
|
stash: true,
|
|
800
777
|
verbose: false,
|
|
801
778
|
})
|
|
@@ -1022,26 +999,18 @@ ESLint v8.51.0 introduced [`--no-warn-ignored` CLI flag](https://eslint.org/docs
|
|
|
1022
999
|
When running `lint-staged` via Husky hooks, TypeScript may ignore `tsconfig.json`, leading to errors like:
|
|
1023
1000
|
|
|
1024
1001
|
> **TS17004:** Cannot use JSX unless the '--jsx' flag is provided.
|
|
1025
|
-
> **TS1056:** Accessors are only available when targeting ECMAScript 5 and higher.
|
|
1026
|
-
|
|
1027
|
-
See issue [#825](https://github.com/okonet/lint-staged/issues/825) for more details.
|
|
1028
|
-
|
|
1029
|
-
#### Root Cause
|
|
1030
|
-
|
|
1031
|
-
<details>
|
|
1032
|
-
<summary>Click to expand</summary>
|
|
1002
|
+
> **TS1056:** Accessors are only available when targeting ECMAScript 5 and higher.
|
|
1033
1003
|
|
|
1034
|
-
|
|
1035
|
-
2. Certain input files can cause TypeScript to ignore `tsconfig.json`. For more details, see this TypeScript issue: [Allow tsconfig.json when input files are specified](https://github.com/microsoft/TypeScript/issues/27379).
|
|
1004
|
+
See issue [#825](https://github.com/okonet/lint-staged/issues/825) for more details.
|
|
1036
1005
|
|
|
1037
|
-
|
|
1006
|
+
#### Root Cause
|
|
1038
1007
|
|
|
1039
|
-
|
|
1008
|
+
1. `lint-staged` automatically passes matched staged files as arguments to commands.
|
|
1009
|
+
2. Certain input files can cause TypeScript to ignore `tsconfig.json`. For more details, see this TypeScript issue: [Allow tsconfig.json when input files are specified](https://github.com/microsoft/TypeScript/issues/27379).
|
|
1040
1010
|
|
|
1041
|
-
|
|
1042
|
-
<summary>Click to expand</summary>
|
|
1011
|
+
#### Workaround: Use a [function signature](https://github.com/lint-staged/lint-staged?tab=readme-ov-file#example-run-tsc-on-changes-to-typescript-files-but-do-not-pass-any-filename-arguments) for the `tsc` command
|
|
1043
1012
|
|
|
1044
|
-
As suggested by @antoinerousseau in [#825 (comment)](https://github.com/lint-staged/lint-staged/issues/825#issuecomment-620018284), using a function prevents `lint-staged` from appending file arguments:
|
|
1013
|
+
As suggested by @antoinerousseau in [#825 (comment)](https://github.com/lint-staged/lint-staged/issues/825#issuecomment-620018284), using a function prevents `lint-staged` from appending file arguments:
|
|
1045
1014
|
|
|
1046
1015
|
**Before:**
|
|
1047
1016
|
|
|
@@ -1061,50 +1030,8 @@ As suggested by @antoinerousseau in [#825 (comment)](https://github.com/lint-sta
|
|
|
1061
1030
|
```js
|
|
1062
1031
|
// lint-staged.config.js
|
|
1063
1032
|
module.exports = {
|
|
1064
|
-
|
|
1065
|
-
() => "tsc --noEmit",
|
|
1066
|
-
"prettier --write"
|
|
1067
|
-
],
|
|
1068
|
-
}
|
|
1069
|
-
```
|
|
1070
|
-
|
|
1071
|
-
</details>
|
|
1072
|
-
|
|
1073
|
-
#### Workaround 2: Take the `sh` or `bash` to wrap the `tsc` command
|
|
1074
|
-
|
|
1075
|
-
<details>
|
|
1076
|
-
<summary>Click to expand</summary>
|
|
1077
|
-
|
|
1078
|
-
As suggested by @sombreroEnPuntas in [#825 (comment)](https://github.com/lint-staged/lint-staged/issues/825#issuecomment-674575655), wrapping `tsc` in a shell command prevents `lint-staged` from modifying its arguments:
|
|
1079
|
-
|
|
1080
|
-
**Before:**
|
|
1081
|
-
|
|
1082
|
-
```js
|
|
1083
|
-
// package.json
|
|
1084
|
-
|
|
1085
|
-
"lint-staged": {
|
|
1086
|
-
"*.{ts,tsx}":[
|
|
1087
|
-
"tsc --noEmit",
|
|
1088
|
-
"prettier --write"
|
|
1089
|
-
]
|
|
1033
|
+
'*.{ts,tsx}': [() => 'tsc --noEmit', 'prettier --write'],
|
|
1090
1034
|
}
|
|
1091
1035
|
```
|
|
1092
1036
|
|
|
1093
|
-
**After:**
|
|
1094
|
-
|
|
1095
|
-
```js
|
|
1096
|
-
// package.json
|
|
1097
|
-
|
|
1098
|
-
"lint-staged": {
|
|
1099
|
-
"*.{ts,tsx}":[
|
|
1100
|
-
"bash -c 'tsc --noEmit'"
|
|
1101
|
-
"prettier --write"
|
|
1102
|
-
]
|
|
1103
|
-
}
|
|
1104
|
-
```
|
|
1105
|
-
|
|
1106
|
-
**Note:** This approach may have cross-platform compatibility issues.
|
|
1107
|
-
|
|
1108
|
-
</details>
|
|
1109
|
-
|
|
1110
1037
|
</details>
|
package/bin/lint-staged.js
CHANGED
|
@@ -102,8 +102,6 @@ program.option('-q, --quiet', 'disable lint-staged’s own console output', fals
|
|
|
102
102
|
|
|
103
103
|
program.option('-r, --relative', 'pass relative filepaths to tasks', false)
|
|
104
104
|
|
|
105
|
-
program.option('-x, --shell [path]', 'skip parsing of tasks for better shell support', false)
|
|
106
|
-
|
|
107
105
|
program.option(
|
|
108
106
|
'-v, --verbose',
|
|
109
107
|
'show task output even when tasks succeed; by default only failed output is shown',
|
|
@@ -129,7 +127,6 @@ const options = {
|
|
|
129
127
|
maxArgLength: cliOptions.maxArgLength || undefined,
|
|
130
128
|
quiet: !!cliOptions.quiet,
|
|
131
129
|
relative: !!cliOptions.relative,
|
|
132
|
-
shell: cliOptions.shell /* Either a boolean or a string pointing to the shell */,
|
|
133
130
|
stash: !!cliOptions.stash, // commander inverts `no-<x>` flags to `!x`
|
|
134
131
|
hidePartiallyStaged: !!cliOptions.hidePartiallyStaged, // commander inverts `no-<x>` flags to `!x`
|
|
135
132
|
verbose: !!cliOptions.verbose,
|
package/lib/execGit.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import debug from 'debug'
|
|
2
|
-
import {
|
|
2
|
+
import spawn, { SubprocessError } from 'nano-spawn'
|
|
3
3
|
|
|
4
4
|
const debugLog = debug('lint-staged:execGit')
|
|
5
5
|
|
|
@@ -12,17 +12,22 @@ const NO_SUBMODULE_RECURSE = ['-c', 'submodule.recurse=false']
|
|
|
12
12
|
// exported for tests
|
|
13
13
|
export const GIT_GLOBAL_OPTIONS = [...NO_SUBMODULE_RECURSE]
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
/** @type {(cmd: string[], options?: import('nano-spawn').Options) => Promise<string>} */
|
|
16
|
+
export const execGit = async (cmd, options) => {
|
|
16
17
|
debugLog('Running git command', cmd)
|
|
17
18
|
try {
|
|
18
|
-
const
|
|
19
|
+
const result = await spawn('git', [...NO_SUBMODULE_RECURSE, ...cmd], {
|
|
19
20
|
...options,
|
|
20
|
-
|
|
21
|
-
cwd: options.cwd || process.cwd(),
|
|
21
|
+
cwd: options?.cwd ?? process.cwd(),
|
|
22
22
|
stdin: 'ignore',
|
|
23
23
|
})
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
|
|
25
|
+
return result.stdout
|
|
26
|
+
} catch (error) {
|
|
27
|
+
if (error instanceof SubprocessError) {
|
|
28
|
+
throw new Error(error.output, { cause: error })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
throw error
|
|
27
32
|
}
|
|
28
33
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import debug from 'debug'
|
|
2
|
+
|
|
3
|
+
import { makeErr } from './getSpawnedTask.js'
|
|
4
|
+
|
|
5
|
+
const debugLog = debug('lint-staged:getFunctionTasks')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {{ title: string; task: Function }} FunctionTask
|
|
9
|
+
* @type {(commands: FunctionTask|Array<string|Function>|string|Function) => boolean}
|
|
10
|
+
* @returns `true` if command is a function task
|
|
11
|
+
*/
|
|
12
|
+
export const isFunctionTask = (commands) => typeof commands === 'object' && !Array.isArray(commands)
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Handles function configuration and pushes the tasks into the task array
|
|
16
|
+
*
|
|
17
|
+
* @param {object} command
|
|
18
|
+
* @param {Array<string>} files
|
|
19
|
+
* @throws {Error} If the function configuration is not valid
|
|
20
|
+
*/
|
|
21
|
+
export const getFunctionTask = async (command, files) => {
|
|
22
|
+
debugLog('Creating Listr tasks for function %o', command)
|
|
23
|
+
|
|
24
|
+
const task = async (ctx) => {
|
|
25
|
+
try {
|
|
26
|
+
await command.task(files)
|
|
27
|
+
} catch (e) {
|
|
28
|
+
throw makeErr(command.title, e, ctx)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return [
|
|
33
|
+
{
|
|
34
|
+
title: command.title,
|
|
35
|
+
task,
|
|
36
|
+
},
|
|
37
|
+
]
|
|
38
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
2
|
import debug from 'debug'
|
|
3
|
-
import
|
|
3
|
+
import spawn from 'nano-spawn'
|
|
4
4
|
import pidTree from 'pidtree'
|
|
5
5
|
import { parseArgsStringToArgv } from 'string-argv'
|
|
6
6
|
|
|
@@ -8,40 +8,27 @@ import { error, info } from './figures.js'
|
|
|
8
8
|
import { getInitialState } from './state.js'
|
|
9
9
|
import { TaskError } from './symbols.js'
|
|
10
10
|
|
|
11
|
-
/**
|
|
12
|
-
* @see https://github.com/sindresorhus/execa/blob/f4b8b3ab601c94d1503f1010822952758dcc6350/lib/command.js#L32-L37
|
|
13
|
-
*/
|
|
14
|
-
const escapeSpaces = (input) => input.replaceAll(' ', '\\ ')
|
|
15
|
-
|
|
16
11
|
const TASK_ERROR = 'lint-staged:taskError'
|
|
17
12
|
|
|
18
|
-
const debugLog = debug('lint-staged:
|
|
13
|
+
const debugLog = debug('lint-staged:getSpawnedTask')
|
|
19
14
|
|
|
20
|
-
|
|
15
|
+
/** @type {(error: import('nano-spawn').SubprocessError) => string} */
|
|
16
|
+
const getTag = (error) => {
|
|
17
|
+
return error.signalName ?? 'FAILED'
|
|
18
|
+
}
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
21
|
* Handle task console output.
|
|
24
22
|
*
|
|
25
23
|
* @param {string} command
|
|
26
|
-
* @param {
|
|
27
|
-
* @param {string} result.stdout
|
|
28
|
-
* @param {string} result.stderr
|
|
29
|
-
* @param {boolean} result.failed
|
|
30
|
-
* @param {boolean} result.killed
|
|
31
|
-
* @param {string} result.signal
|
|
24
|
+
* @param {import('nano-spawn').Result | import('nano-spawn').SubprocessError} result
|
|
32
25
|
* @param {Object} ctx
|
|
33
26
|
* @returns {Error}
|
|
34
27
|
*/
|
|
35
28
|
const handleOutput = (command, result, ctx, isError = false) => {
|
|
36
|
-
|
|
37
|
-
const hasOutput = !!stderr || !!stdout
|
|
38
|
-
|
|
39
|
-
if (hasOutput) {
|
|
29
|
+
if (result.output) {
|
|
40
30
|
const outputTitle = isError ? chalk.redBright(`${error} ${command}:`) : `${info} ${command}:`
|
|
41
|
-
const output = []
|
|
42
|
-
.concat(ctx.quiet ? [] : ['', outputTitle])
|
|
43
|
-
.concat(stderr ? stderr : [])
|
|
44
|
-
.concat(stdout ? stdout : [])
|
|
31
|
+
const output = [...(ctx.quiet ? [] : ['', outputTitle]), result.output]
|
|
45
32
|
ctx.output.push(output.join('\n'))
|
|
46
33
|
} else if (isError) {
|
|
47
34
|
// Show generic error when task had no output
|
|
@@ -52,12 +39,14 @@ const handleOutput = (command, result, ctx, isError = false) => {
|
|
|
52
39
|
}
|
|
53
40
|
|
|
54
41
|
/**
|
|
55
|
-
* Kill
|
|
56
|
-
* @param {
|
|
42
|
+
* Kill subprocess along with all its child processes.
|
|
43
|
+
* @param {import('nano-spawn').Subprocess} subprocess
|
|
57
44
|
*/
|
|
58
|
-
const
|
|
45
|
+
const killSubprocess = async (subprocess) => {
|
|
46
|
+
const childProcess = await subprocess.nodeChildProcess
|
|
47
|
+
|
|
59
48
|
try {
|
|
60
|
-
const childPids = await pidTree(
|
|
49
|
+
const childPids = await pidTree(childProcess.pid)
|
|
61
50
|
for (const childPid of childPids) {
|
|
62
51
|
try {
|
|
63
52
|
process.kill(childPid)
|
|
@@ -68,27 +57,27 @@ const killExecaProcess = async (execaProcess) => {
|
|
|
68
57
|
} catch (error) {
|
|
69
58
|
// Suppress "No matching pid found" error. This probably means
|
|
70
59
|
// the process already died before executing.
|
|
71
|
-
debugLog(`Failed to kill process with pid "%d": %o`,
|
|
60
|
+
debugLog(`Failed to kill process with pid "%d": %o`, childProcess.pid, error)
|
|
72
61
|
}
|
|
73
62
|
|
|
74
|
-
// The
|
|
75
|
-
|
|
63
|
+
// The child process is terminated separately in order to get the `KILLED` status.
|
|
64
|
+
childProcess.kill('SIGKILL')
|
|
76
65
|
}
|
|
77
66
|
|
|
78
67
|
/**
|
|
79
|
-
* Interrupts the execution of the
|
|
68
|
+
* Interrupts the execution of the subprocess that we spawned if
|
|
80
69
|
* another task adds an error to the context.
|
|
81
70
|
*
|
|
82
71
|
* @param {Object} ctx
|
|
83
|
-
* @param {
|
|
72
|
+
* @param {import('nano-spawn').Subprocess} subprocess
|
|
84
73
|
* @returns {() => Promise<void>} Function that clears the interval that
|
|
85
74
|
* checks the context.
|
|
86
75
|
*/
|
|
87
|
-
const interruptExecutionOnError = (ctx,
|
|
76
|
+
const interruptExecutionOnError = (ctx, subprocess) => {
|
|
88
77
|
let killPromise
|
|
89
78
|
|
|
90
79
|
const errorListener = async () => {
|
|
91
|
-
killPromise =
|
|
80
|
+
killPromise = killSubprocess(subprocess)
|
|
92
81
|
await killPromise
|
|
93
82
|
}
|
|
94
83
|
|
|
@@ -104,23 +93,18 @@ const interruptExecutionOnError = (ctx, execaChildProcess) => {
|
|
|
104
93
|
* Create a error output depending on process result.
|
|
105
94
|
*
|
|
106
95
|
* @param {string} command
|
|
107
|
-
* @param {
|
|
108
|
-
* @param {string} result.stdout
|
|
109
|
-
* @param {string} result.stderr
|
|
110
|
-
* @param {boolean} result.failed
|
|
111
|
-
* @param {boolean} result.killed
|
|
112
|
-
* @param {string} result.signal
|
|
96
|
+
* @param {import('nano-spawn').SubprocessError} error
|
|
113
97
|
* @param {Object} ctx
|
|
114
98
|
* @returns {Error}
|
|
115
99
|
*/
|
|
116
|
-
const makeErr = (command,
|
|
100
|
+
export const makeErr = (command, error, ctx) => {
|
|
117
101
|
ctx.errors.add(TaskError)
|
|
118
102
|
|
|
119
103
|
// https://nodejs.org/api/events.html#error-events
|
|
120
104
|
ctx.events.emit(TASK_ERROR, TaskError)
|
|
121
105
|
|
|
122
|
-
handleOutput(command,
|
|
123
|
-
const tag = getTag(
|
|
106
|
+
handleOutput(command, error, ctx, true)
|
|
107
|
+
const tag = getTag(error)
|
|
124
108
|
return new Error(`${chalk.redBright(command)} ${chalk.dim(`[${tag}]`)}`)
|
|
125
109
|
}
|
|
126
110
|
|
|
@@ -133,53 +117,45 @@ const makeErr = (command, result, ctx) => {
|
|
|
133
117
|
* @param {String} options.topLevelDir - Current git repo top-level path
|
|
134
118
|
* @param {Boolean} options.isFn - Whether the linter task is a function
|
|
135
119
|
* @param {Array<string>} options.files — Filepaths to run the linter task against
|
|
136
|
-
* @param {Boolean} [options.shell] — Whether to skip parsing linter task for better shell support
|
|
137
120
|
* @param {Boolean} [options.verbose] — Always show task verbose
|
|
138
121
|
* @returns {() => Promise<Array<string>>}
|
|
139
122
|
*/
|
|
140
|
-
export const
|
|
123
|
+
export const getSpawnedTask = ({
|
|
141
124
|
command,
|
|
142
125
|
cwd = process.cwd(),
|
|
143
126
|
files,
|
|
144
127
|
topLevelDir,
|
|
145
128
|
isFn,
|
|
146
|
-
shell = false,
|
|
147
129
|
verbose = false,
|
|
148
130
|
}) => {
|
|
149
131
|
const [cmd, ...args] = parseArgsStringToArgv(command)
|
|
150
132
|
debugLog('cmd:', cmd)
|
|
151
133
|
debugLog('args:', args)
|
|
152
134
|
|
|
153
|
-
const
|
|
135
|
+
const spawnOptions = {
|
|
154
136
|
// Only use topLevelDir as CWD if we are using the git binary
|
|
155
137
|
// e.g `npm` should run tasks in the actual CWD
|
|
156
138
|
cwd: /^git(\.exe)?/i.test(cmd) ? topLevelDir : cwd,
|
|
157
139
|
preferLocal: true,
|
|
158
|
-
reject: false,
|
|
159
|
-
shell,
|
|
160
140
|
stdin: 'ignore',
|
|
161
141
|
}
|
|
162
142
|
|
|
163
|
-
debugLog('
|
|
143
|
+
debugLog('Spawn options:', spawnOptions)
|
|
164
144
|
|
|
165
145
|
return async (ctx = getInitialState()) => {
|
|
166
|
-
const
|
|
167
|
-
? execaCommand(
|
|
168
|
-
isFn ? command : `${command} ${files.map(escapeSpaces).join(' ')}`,
|
|
169
|
-
execaOptions
|
|
170
|
-
)
|
|
171
|
-
: execa(cmd, isFn ? args : args.concat(files), execaOptions)
|
|
172
|
-
|
|
173
|
-
const quitInterruptCheck = interruptExecutionOnError(ctx, execaChildProcess)
|
|
174
|
-
const result = await execaChildProcess
|
|
175
|
-
await quitInterruptCheck()
|
|
176
|
-
|
|
177
|
-
if (result.failed || result.killed || result.signal != null) {
|
|
178
|
-
throw makeErr(command, result, ctx)
|
|
179
|
-
}
|
|
146
|
+
const subprocess = spawn(cmd, isFn ? args : args.concat(files), spawnOptions)
|
|
180
147
|
|
|
181
|
-
|
|
182
|
-
|
|
148
|
+
const quitInterruptCheck = interruptExecutionOnError(ctx, subprocess)
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const result = await subprocess
|
|
152
|
+
if (verbose) {
|
|
153
|
+
handleOutput(command, result, ctx)
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
throw makeErr(command, error, ctx)
|
|
157
|
+
} finally {
|
|
158
|
+
await quitInterruptCheck()
|
|
183
159
|
}
|
|
184
160
|
}
|
|
185
161
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import debug from 'debug'
|
|
2
2
|
|
|
3
|
+
import { getSpawnedTask } from './getSpawnedTask.js'
|
|
3
4
|
import { configurationError } from './messages.js'
|
|
4
|
-
import { resolveTaskFn } from './resolveTaskFn.js'
|
|
5
5
|
|
|
6
|
-
const debugLog = debug('lint-staged:
|
|
6
|
+
const debugLog = debug('lint-staged:getSpawnedTasks')
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Creates and returns an array of listr tasks which map to the given commands.
|
|
@@ -13,14 +13,14 @@ const debugLog = debug('lint-staged:makeCmdTasks')
|
|
|
13
13
|
* @param {string} options.cwd
|
|
14
14
|
* @param {Array<string>} options.files
|
|
15
15
|
* @param {string} options.topLevelDir
|
|
16
|
-
* @param {Boolean} shell
|
|
17
16
|
* @param {Boolean} verbose
|
|
18
17
|
*/
|
|
19
|
-
export const
|
|
20
|
-
debugLog('Creating
|
|
21
|
-
const commandArray = Array.isArray(commands) ? commands : [commands]
|
|
18
|
+
export const getSpawnedTasks = async ({ commands, cwd, files, topLevelDir, verbose }) => {
|
|
19
|
+
debugLog('Creating Listr tasks for commands %o', commands)
|
|
22
20
|
const cmdTasks = []
|
|
23
21
|
|
|
22
|
+
const commandArray = Array.isArray(commands) ? commands : [commands]
|
|
23
|
+
|
|
24
24
|
for (const cmd of commandArray) {
|
|
25
25
|
// command function may return array of commands that already include `stagedFiles`
|
|
26
26
|
const isFn = typeof cmd === 'function'
|
|
@@ -43,7 +43,7 @@ export const makeCmdTasks = async ({ commands, cwd, files, topLevelDir, shell, v
|
|
|
43
43
|
)
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
const task =
|
|
46
|
+
const task = getSpawnedTask({ command, cwd, files, topLevelDir, isFn, verbose })
|
|
47
47
|
cmdTasks.push({ title: command, command, task })
|
|
48
48
|
}
|
|
49
49
|
}
|
package/lib/getStagedFiles.js
CHANGED
|
@@ -31,8 +31,8 @@ export const getStagedFiles = async ({ cwd = process.cwd(), diff, diffFilter } =
|
|
|
31
31
|
* roots and get the filename.
|
|
32
32
|
*/
|
|
33
33
|
return output
|
|
34
|
-
.split(':')
|
|
35
34
|
.slice(1)
|
|
35
|
+
.split('\u0000:')
|
|
36
36
|
.map(parseGitZOutput)
|
|
37
37
|
.flatMap(([info, src, dst]) => {
|
|
38
38
|
const [, dstMode, , , ,] = info.split(' ')
|
package/lib/index.d.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
type
|
|
1
|
+
type SyncGenerateTask = (stagedFileNames: string[]) => string | string[]
|
|
2
2
|
|
|
3
|
-
type
|
|
3
|
+
type AsyncGenerateTask = (stagedFileNames: string[]) => Promise<string | string[]>
|
|
4
4
|
|
|
5
|
-
type
|
|
5
|
+
type GenerateTask = SyncGenerateTask | AsyncGenerateTask
|
|
6
|
+
|
|
7
|
+
type TaskFunction = {
|
|
8
|
+
title: string
|
|
9
|
+
task: (stagedFileNames: string[]) => void | Promise<void>
|
|
10
|
+
}
|
|
6
11
|
|
|
7
12
|
export type Configuration =
|
|
8
|
-
| Record<string, string |
|
|
9
|
-
|
|
|
13
|
+
| Record<string, string | TaskFunction | GenerateTask | (string | GenerateTask)[]>
|
|
14
|
+
| GenerateTask
|
|
10
15
|
|
|
11
16
|
export type Options = {
|
|
12
17
|
/**
|
|
@@ -61,11 +66,6 @@ export type Options = {
|
|
|
61
66
|
* @default false
|
|
62
67
|
*/
|
|
63
68
|
relative?: boolean
|
|
64
|
-
/**
|
|
65
|
-
* Skip parsing of tasks for better shell support
|
|
66
|
-
* @default false
|
|
67
|
-
*/
|
|
68
|
-
shell?: boolean
|
|
69
69
|
/**
|
|
70
70
|
* Enable the backup stash, and revert in case of errors.
|
|
71
71
|
* @warn Disabling this also implies `hidePartiallyStaged: false`.
|
package/lib/index.js
CHANGED
|
@@ -57,7 +57,6 @@ const getMaxArgLength = () => {
|
|
|
57
57
|
* @param {number} [options.maxArgLength] - Maximum argument string length
|
|
58
58
|
* @param {boolean} [options.quiet] - Disable lint-staged’s own console output
|
|
59
59
|
* @param {boolean} [options.relative] - Pass relative filepaths to tasks
|
|
60
|
-
* @param {boolean|string} [options.shell] - Skip parsing of tasks for better shell support
|
|
61
60
|
* @param {boolean} [options.stash] - Enable the backup stash, and revert in case of errors
|
|
62
61
|
* @param {boolean} [options.verbose] - Show task output even when tasks succeed; by default only failed output is shown
|
|
63
62
|
* @param {Logger} [logger]
|
|
@@ -77,7 +76,6 @@ const lintStaged = async (
|
|
|
77
76
|
maxArgLength = getMaxArgLength() / 2,
|
|
78
77
|
quiet = false,
|
|
79
78
|
relative = false,
|
|
80
|
-
shell = false,
|
|
81
79
|
// Stashing should be disabled by default when the `diff` option is used
|
|
82
80
|
stash = diff === undefined,
|
|
83
81
|
hidePartiallyStaged = stash,
|
|
@@ -112,7 +110,6 @@ const lintStaged = async (
|
|
|
112
110
|
maxArgLength,
|
|
113
111
|
quiet,
|
|
114
112
|
relative,
|
|
115
|
-
shell,
|
|
116
113
|
stash,
|
|
117
114
|
hidePartiallyStaged,
|
|
118
115
|
verbose,
|
package/lib/runAll.js
CHANGED
|
@@ -9,11 +9,12 @@ import { Listr } from 'listr2'
|
|
|
9
9
|
import { chunkFiles } from './chunkFiles.js'
|
|
10
10
|
import { execGit } from './execGit.js'
|
|
11
11
|
import { generateTasks } from './generateTasks.js'
|
|
12
|
+
import { getFunctionTask, isFunctionTask } from './getFunctionTask.js'
|
|
12
13
|
import { getRenderer } from './getRenderer.js'
|
|
14
|
+
import { getSpawnedTasks } from './getSpawnedTasks.js'
|
|
13
15
|
import { getStagedFiles } from './getStagedFiles.js'
|
|
14
16
|
import { GitWorkflow } from './gitWorkflow.js'
|
|
15
17
|
import { groupFilesByConfig } from './groupFilesByConfig.js'
|
|
16
|
-
import { makeCmdTasks } from './makeCmdTasks.js'
|
|
17
18
|
import {
|
|
18
19
|
DEPRECATED_GIT_ADD,
|
|
19
20
|
FAILED_GET_STAGED_FILES,
|
|
@@ -58,7 +59,6 @@ const createError = (ctx) => Object.assign(new Error('lint-staged failed'), { ct
|
|
|
58
59
|
* @param {number} [options.maxArgLength] - Maximum argument string length
|
|
59
60
|
* @param {boolean} [options.quiet] - Disable lint-staged’s own console output
|
|
60
61
|
* @param {boolean} [options.relative] - Pass relative filepaths to tasks
|
|
61
|
-
* @param {boolean} [options.shell] - Skip parsing of tasks for better shell support
|
|
62
62
|
* @param {boolean} [options.stash] - Enable the backup stash, and revert in case of errors
|
|
63
63
|
* @param {boolean} [options.verbose] - Show task output even when tasks succeed; by default only failed output is shown
|
|
64
64
|
* @param {Logger} logger
|
|
@@ -77,7 +77,6 @@ export const runAll = async (
|
|
|
77
77
|
maxArgLength,
|
|
78
78
|
quiet = false,
|
|
79
79
|
relative = false,
|
|
80
|
-
shell = false,
|
|
81
80
|
// Stashing should be disabled by default when the `diff` option is used
|
|
82
81
|
stash = diff === undefined,
|
|
83
82
|
hidePartiallyStaged = stash,
|
|
@@ -165,7 +164,7 @@ export const runAll = async (
|
|
|
165
164
|
* This is used to set max event listener count to the total number
|
|
166
165
|
* of generated tasks. The event listener is used to keep track of
|
|
167
166
|
* the interrupt signal and kill all tasks when it happens. See the
|
|
168
|
-
* `interruptExecutionOnError` in `
|
|
167
|
+
* `interruptExecutionOnError` in `getSpawnedTask`.
|
|
169
168
|
*/
|
|
170
169
|
let listrTaskCount = 0
|
|
171
170
|
|
|
@@ -192,14 +191,16 @@ export const runAll = async (
|
|
|
192
191
|
for (const [index, files] of stagedFileChunks.entries()) {
|
|
193
192
|
const chunkListrTasks = await Promise.all(
|
|
194
193
|
generateTasks({ config, cwd: groupCwd, files, relative }).map((task) =>
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
194
|
+
(isFunctionTask(task.commands)
|
|
195
|
+
? getFunctionTask(task.commands, files)
|
|
196
|
+
: getSpawnedTasks({
|
|
197
|
+
commands: task.commands,
|
|
198
|
+
cwd: groupCwd,
|
|
199
|
+
files: task.fileList,
|
|
200
|
+
topLevelDir,
|
|
201
|
+
verbose,
|
|
202
|
+
})
|
|
203
|
+
).then((subTasks) => {
|
|
203
204
|
// Add files from task to match set
|
|
204
205
|
task.fileList.forEach((file) => {
|
|
205
206
|
// Make sure relative files are normalized to the
|
package/lib/searchConfigs.js
CHANGED
|
@@ -106,7 +106,7 @@ export const searchConfigs = async (
|
|
|
106
106
|
/** Get validated configs from the above object, without any `null` values (not found) */
|
|
107
107
|
const foundConfigs = Object.entries(configs)
|
|
108
108
|
.filter(([, value]) => !!value)
|
|
109
|
-
.reduce((acc, [key, value]) => (
|
|
109
|
+
.reduce((acc, [key, value]) => Object.assign(acc, { [key]: value }), {})
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
112
|
* Try to find a single config from parent directories
|
package/lib/validateConfig.js
CHANGED
|
@@ -10,19 +10,6 @@ import { validateBraces } from './validateBraces.js'
|
|
|
10
10
|
|
|
11
11
|
const debugLog = debug('lint-staged:validateConfig')
|
|
12
12
|
|
|
13
|
-
const isObject = (test) => test && typeof test === 'object' && !Array.isArray(test)
|
|
14
|
-
|
|
15
|
-
const TEST_DEPRECATED_KEYS = new Map([
|
|
16
|
-
['concurrent', (key) => typeof key === 'boolean'],
|
|
17
|
-
['chunkSize', (key) => typeof key === 'number'],
|
|
18
|
-
['globOptions', isObject],
|
|
19
|
-
['linters', isObject],
|
|
20
|
-
['ignore', (key) => Array.isArray(key)],
|
|
21
|
-
['subTaskConcurrency', (key) => typeof key === 'number'],
|
|
22
|
-
['renderer', (key) => typeof key === 'string'],
|
|
23
|
-
['relative', (key) => typeof key === 'boolean'],
|
|
24
|
-
])
|
|
25
|
-
|
|
26
13
|
export const validateConfigLogic = (config, configPath, logger) => {
|
|
27
14
|
debugLog('Validating config from `%s`...', configPath)
|
|
28
15
|
|
|
@@ -35,7 +22,7 @@ export const validateConfigLogic = (config, configPath, logger) => {
|
|
|
35
22
|
* They are not further validated here to make sure the function gets
|
|
36
23
|
* evaluated only once.
|
|
37
24
|
*
|
|
38
|
-
* @see
|
|
25
|
+
* @see getSpawnedTasks
|
|
39
26
|
*/
|
|
40
27
|
if (typeof config === 'function') {
|
|
41
28
|
return { '*': config }
|
|
@@ -53,29 +40,30 @@ export const validateConfigLogic = (config, configPath, logger) => {
|
|
|
53
40
|
* it can be used for validating the values at the same time.
|
|
54
41
|
*/
|
|
55
42
|
const validatedConfig = Object.entries(config).reduce((collection, [pattern, task]) => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (testFn(task)) {
|
|
43
|
+
if (Array.isArray(task)) {
|
|
44
|
+
/** Array with invalid values */
|
|
45
|
+
if (task.some((item) => typeof item !== 'string' && typeof item !== 'function')) {
|
|
60
46
|
errors.push(
|
|
61
|
-
configurationError(pattern, '
|
|
47
|
+
configurationError(pattern, 'Should be an array of strings or functions.', task)
|
|
62
48
|
)
|
|
63
49
|
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
50
|
+
} else if (typeof task === 'object') {
|
|
51
|
+
/** Invalid function task */
|
|
52
|
+
if (typeof task.title !== 'string' || typeof task.task !== 'function') {
|
|
53
|
+
errors.push(
|
|
54
|
+
configurationError(
|
|
55
|
+
pattern,
|
|
56
|
+
'Function task should contain `title` and `task` fields, where `title` should be a string and `task` should be a function.',
|
|
57
|
+
task
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
} else if (typeof task !== 'string' && typeof task !== 'function') {
|
|
62
|
+
/** Singular invalid value */
|
|
75
63
|
errors.push(
|
|
76
64
|
configurationError(
|
|
77
65
|
pattern,
|
|
78
|
-
'Should be a string, a function, or an array of strings and functions.',
|
|
66
|
+
'Should be a string, a function, an object or an array of strings and functions.',
|
|
79
67
|
task
|
|
80
68
|
)
|
|
81
69
|
)
|
|
@@ -87,7 +75,7 @@ export const validateConfigLogic = (config, configPath, logger) => {
|
|
|
87
75
|
*/
|
|
88
76
|
const fixedPattern = validateBraces(pattern, logger)
|
|
89
77
|
|
|
90
|
-
return
|
|
78
|
+
return Object.assign(collection, { [fixedPattern]: task })
|
|
91
79
|
}, {})
|
|
92
80
|
|
|
93
81
|
if (errors.length) {
|
package/lib/validateOptions.js
CHANGED
|
@@ -13,8 +13,6 @@ const debugLog = debug('lint-staged:validateOptions')
|
|
|
13
13
|
* Validate lint-staged options, either from the Node.js API or the command line flags.
|
|
14
14
|
* @param {*} options
|
|
15
15
|
* @param {boolean|string} [options.cwd] - Current working directory
|
|
16
|
-
* @param {boolean|string} [options.shell] - Skip parsing of tasks for better shell support
|
|
17
|
-
*
|
|
18
16
|
* @throws {InvalidOptionsError}
|
|
19
17
|
*/
|
|
20
18
|
export const validateOptions = async (options = {}, logger) => {
|
|
@@ -32,16 +30,5 @@ export const validateOptions = async (options = {}, logger) => {
|
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
/** Ensure the passed shell option is executable */
|
|
36
|
-
if (typeof options.shell === 'string') {
|
|
37
|
-
try {
|
|
38
|
-
await fs.access(options.shell, constants.X_OK)
|
|
39
|
-
} catch (error) {
|
|
40
|
-
debugLog('Failed to validate options: %o', options)
|
|
41
|
-
logger.error(invalidOption('shell', options.shell, error.message))
|
|
42
|
-
throw InvalidOptionsError
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
33
|
debugLog('Validated options: %o', options)
|
|
47
34
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lint-staged",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "16.0.0",
|
|
4
4
|
"description": "Lint files staged by git",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"url": "https://opencollective.com/lint-staged"
|
|
22
22
|
},
|
|
23
23
|
"engines": {
|
|
24
|
-
"node": ">=18
|
|
24
|
+
"node": ">=20.18"
|
|
25
25
|
},
|
|
26
26
|
"type": "module",
|
|
27
27
|
"bin": {
|
|
@@ -33,8 +33,9 @@
|
|
|
33
33
|
"./package.json": "./package.json"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
|
-
"bin",
|
|
37
|
-
"lib"
|
|
36
|
+
"bin/",
|
|
37
|
+
"lib/",
|
|
38
|
+
"MIGRATION.md"
|
|
38
39
|
],
|
|
39
40
|
"scripts": {
|
|
40
41
|
"lint": "eslint .",
|
|
@@ -49,27 +50,27 @@
|
|
|
49
50
|
"chalk": "^5.4.1",
|
|
50
51
|
"commander": "^13.1.0",
|
|
51
52
|
"debug": "^4.4.0",
|
|
52
|
-
"execa": "^8.0.1",
|
|
53
53
|
"lilconfig": "^3.1.3",
|
|
54
|
-
"listr2": "^8.
|
|
54
|
+
"listr2": "^8.3.3",
|
|
55
55
|
"micromatch": "^4.0.8",
|
|
56
|
+
"nano-spawn": "^1.0.0",
|
|
56
57
|
"pidtree": "^0.6.0",
|
|
57
58
|
"string-argv": "^0.3.2",
|
|
58
|
-
"yaml": "^2.7.
|
|
59
|
+
"yaml": "^2.7.1"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
62
|
"@changesets/changelog-github": "0.5.1",
|
|
62
|
-
"@changesets/cli": "2.
|
|
63
|
-
"@commitlint/cli": "19.8.
|
|
64
|
-
"@commitlint/config-conventional": "19.8.
|
|
65
|
-
"@eslint/js": "9.
|
|
63
|
+
"@changesets/cli": "2.29.3",
|
|
64
|
+
"@commitlint/cli": "19.8.1",
|
|
65
|
+
"@commitlint/config-conventional": "19.8.1",
|
|
66
|
+
"@eslint/js": "9.26.0",
|
|
66
67
|
"consolemock": "1.1.0",
|
|
67
68
|
"cross-env": "7.0.3",
|
|
68
|
-
"eslint": "9.
|
|
69
|
-
"eslint-config-prettier": "10.1.
|
|
69
|
+
"eslint": "9.26.0",
|
|
70
|
+
"eslint-config-prettier": "10.1.5",
|
|
70
71
|
"eslint-plugin-jest": "28.11.0",
|
|
71
|
-
"eslint-plugin-n": "17.
|
|
72
|
-
"eslint-plugin-prettier": "5.
|
|
72
|
+
"eslint-plugin-n": "17.18.0",
|
|
73
|
+
"eslint-plugin-prettier": "5.4.0",
|
|
73
74
|
"eslint-plugin-simple-import-sort": "12.1.1",
|
|
74
75
|
"husky": "9.1.7",
|
|
75
76
|
"jest": "29.7.0",
|
|
@@ -77,7 +78,7 @@
|
|
|
77
78
|
"mock-stdin": "1.0.0",
|
|
78
79
|
"prettier": "3.5.3",
|
|
79
80
|
"semver": "7.7.1",
|
|
80
|
-
"typescript": "5.8.
|
|
81
|
+
"typescript": "5.8.3"
|
|
81
82
|
},
|
|
82
83
|
"keywords": [
|
|
83
84
|
"lint",
|