lint-staged 16.1.6 → 16.2.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.
@@ -1,11 +1,10 @@
1
1
  import path from 'node:path'
2
2
 
3
- import debug from 'debug'
4
-
3
+ import { createDebug } from './debug.js'
5
4
  import { execGit } from './execGit.js'
6
5
  import { normalizePath } from './normalizePath.js'
7
6
 
8
- const debugLog = debug('lint-staged:resolveGitRepo')
7
+ const debugLog = createDebug('lint-staged:resolveGitRepo')
9
8
 
10
9
  /**
11
10
  * Relative path up to the repo top-level directory
package/lib/runAll.js CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  import path from 'node:path'
4
4
 
5
- import chalk from 'chalk'
6
- import debug from 'debug'
7
5
  import { Listr } from 'listr2'
8
6
 
9
7
  import { chunkFiles } from './chunkFiles.js'
8
+ import { blackBright } from './colors.js'
9
+ import { createDebug } from './debug.js'
10
10
  import { execGit } from './execGit.js'
11
11
  import { generateTasks } from './generateTasks.js'
12
12
  import { getFunctionTask, isFunctionTask } from './getFunctionTask.js'
@@ -36,11 +36,11 @@ import {
36
36
  restoreOriginalStateEnabled,
37
37
  restoreOriginalStateSkipped,
38
38
  restoreUnstagedChangesSkipped,
39
- shouldHidePartiallyStagedFiles,
39
+ shouldHideUnstagedFiles,
40
40
  } from './state.js'
41
41
  import { ConfigNotFoundError, GetStagedFilesError, GitError, GitRepoError } from './symbols.js'
42
42
 
43
- const debugLog = debug('lint-staged:runAll')
43
+ const debugLog = createDebug('lint-staged:runAll')
44
44
 
45
45
  /**
46
46
  * @param {ReturnType<typeof getInitialState>} ctx context
@@ -54,15 +54,20 @@ const createError = (ctx, cause) =>
54
54
  *
55
55
  * @param {object} options
56
56
  * @param {boolean} [options.allowEmpty] - Allow empty commits when tasks revert all staged changes
57
+ * @param {Object} [options.color] - Enable ANSI colors in output
57
58
  * @param {boolean | number} [options.concurrent] - The number of tasks to run concurrently, or false to run tasks serially
58
59
  * @param {Object} [options.configObject] - Explicit config object from the js API
59
60
  * @param {string} [options.configPath] - Explicit path to a config file
61
+ * @param {boolean} [options.continueOnError] - Run all tasks to completion even if one fails
60
62
  * @param {string} [options.cwd] - Current working directory
61
63
  * @param {boolean} [options.debug] - Enable debug mode
62
64
  * @param {string} [options.diff] - Override the default "--staged" flag of "git diff" to get list of files
63
65
  * @param {string} [options.diffFilter] - Override the default "--diff-filter=ACMR" flag of "git diff" to get list of files
66
+ * @param {boolean} [options.failOnChanges] - Fail with exit code 1 when tasks modify tracked files
67
+ * @param {boolean} [options.hidePartiallyStaged] - Whether to hide unstaged changes from partially staged files before running tasks
68
+ * @param {boolean} [options.hideUnstaged] - Whether to hide all unstaged changes before running tasks
64
69
  * @param {number} [options.maxArgLength] - Maximum argument string length
65
- * @param {boolean} [options.quiet] - Disable lint-stageds own console output
70
+ * @param {boolean} [options.quiet] - Disable lint-staged's own console output
66
71
  * @param {boolean} [options.relative] - Pass relative filepaths to tasks
67
72
  * @param {boolean} [options.revert] - revert to original state in case of errors
68
73
  * @param {boolean} [options.stash] - Enable the backup stash, and revert in case of errors
@@ -73,13 +78,18 @@ const createError = (ctx, cause) =>
73
78
  export const runAll = async (
74
79
  {
75
80
  allowEmpty = false,
81
+ color = false,
76
82
  concurrent = true,
77
83
  configObject,
78
84
  configPath,
85
+ continueOnError = false,
79
86
  cwd,
80
87
  debug = false,
81
88
  diff,
82
89
  diffFilter,
90
+ failOnChanges = false,
91
+ hidePartiallyStaged = true,
92
+ hideUnstaged = false,
83
93
  maxArgLength,
84
94
  quiet = false,
85
95
  relative = false,
@@ -87,7 +97,6 @@ export const runAll = async (
87
97
  stash = diff === undefined,
88
98
  // Cannot revert to original state without stash
89
99
  revert = stash,
90
- hidePartiallyStaged = true,
91
100
  verbose = false,
92
101
  },
93
102
  logger = console
@@ -99,7 +108,12 @@ export const runAll = async (
99
108
  cwd = hasExplicitCwd ? path.resolve(cwd) : process.cwd()
100
109
  debugLog('Using working directory `%s`', cwd)
101
110
 
102
- const ctx = getInitialState({ quiet, revert })
111
+ const ctx = getInitialState({
112
+ hidePartiallyStaged,
113
+ hideUnstaged,
114
+ quiet,
115
+ revert,
116
+ })
103
117
 
104
118
  const { topLevelDir, gitConfigDir } = await resolveGitRepo(cwd)
105
119
  if (!topLevelDir) {
@@ -121,12 +135,16 @@ export const runAll = async (
121
135
  logger.warn(skippingBackup(hasInitialCommit, diff))
122
136
  }
123
137
 
124
- ctx.shouldHidePartiallyStaged = hidePartiallyStaged
125
138
  if (!ctx.shouldHidePartiallyStaged && !quiet) {
126
139
  logger.warn(SKIPPING_HIDE_PARTIALLY_CHANGED)
127
140
  }
128
141
 
129
- const stagedFiles = await getStagedFiles({ cwd: topLevelDir, diff, diffFilter })
142
+ // Run staged files retrieval and config search in parallel since they're independent
143
+ const [stagedFiles, foundConfigs] = await Promise.all([
144
+ getStagedFiles({ cwd: topLevelDir, diff, diffFilter }),
145
+ searchConfigs({ configObject, configPath, cwd, topLevelDir }, logger),
146
+ ])
147
+
130
148
  if (!stagedFiles) {
131
149
  if (!quiet) ctx.output.push(FAILED_GET_STAGED_FILES)
132
150
  ctx.errors.add(GetStagedFilesError)
@@ -140,7 +158,6 @@ export const runAll = async (
140
158
  return ctx
141
159
  }
142
160
 
143
- const foundConfigs = await searchConfigs({ configObject, configPath, cwd, topLevelDir }, logger)
144
161
  const numberOfConfigs = Object.keys(foundConfigs).length
145
162
 
146
163
  // Throw if no configurations were found
@@ -165,7 +182,7 @@ export const runAll = async (
165
182
  ctx,
166
183
  exitOnError: false,
167
184
  registerSignalListeners: false,
168
- ...getRenderer({ debug, quiet }, logger),
185
+ ...getRenderer({ color, debug, quiet }, logger),
169
186
  }
170
187
 
171
188
  /**
@@ -203,6 +220,7 @@ export const runAll = async (
203
220
  (isFunctionTask(task.commands)
204
221
  ? getFunctionTask(task.commands, task.fileList)
205
222
  : getSpawnedTasks({
223
+ color,
206
224
  commands: task.commands,
207
225
  cwd: groupCwd,
208
226
  files: task.fileList,
@@ -231,19 +249,19 @@ export const runAll = async (
231
249
  const fileCount = task.fileList.length
232
250
 
233
251
  return {
234
- title: `${task.pattern}${chalk.dim(
252
+ title: `${task.pattern}${blackBright(
235
253
  ` — ${fileCount} ${fileCount === 1 ? 'file' : 'files'}`
236
254
  )}`,
237
255
  task: async (ctx, task) =>
238
256
  task.newListr(
239
257
  subTasks,
240
258
  // Subtasks should not run in parallel, and should exit on error
241
- { concurrent: false, exitOnError: true }
259
+ { concurrent: false, exitOnError: !continueOnError }
242
260
  ),
243
261
  skip: () => {
244
262
  // Skip task when no files matched
245
263
  if (fileCount === 0) {
246
- return `${task.pattern}${chalk.dim(' — no files')}`
264
+ return `${task.pattern}${blackBright(' — no files')}`
247
265
  }
248
266
  return false
249
267
  },
@@ -256,15 +274,16 @@ export const runAll = async (
256
274
 
257
275
  listrTasks.push({
258
276
  title:
259
- `${configName}${chalk.dim(` — ${files.length} ${files.length > 1 ? 'files' : 'file'}`)}` +
260
- (chunkCount > 1 ? chalk.dim(` (chunk ${index + 1}/${chunkCount})...`) : ''),
261
- task: (ctx, task) => task.newListr(chunkListrTasks, { concurrent, exitOnError: true }),
277
+ `${configName}${blackBright(` — ${files.length} ${files.length > 1 ? 'files' : 'file'}`)}` +
278
+ (chunkCount > 1 ? blackBright(` (chunk ${index + 1}/${chunkCount})...`) : ''),
279
+ task: (ctx, task) =>
280
+ task.newListr(chunkListrTasks, { concurrent, exitOnError: !continueOnError }),
262
281
  skip: () => {
263
282
  // Skip if the first step (backup) failed
264
283
  if (ctx.errors.has(GitError)) return SKIPPED_GIT_ERROR
265
284
  // Skip chunk when no every task is skipped (due to no matches)
266
285
  if (chunkListrTasks.every((task) => task.skip())) {
267
- return `${configName}${chalk.dim(' — no tasks to run')}`
286
+ return `${configName}${blackBright(' — no tasks to run')}`
268
287
  }
269
288
  return false
270
289
  },
@@ -295,11 +314,12 @@ export const runAll = async (
295
314
 
296
315
  const git = new GitWorkflow({
297
316
  allowEmpty,
298
- gitConfigDir,
299
- topLevelDir,
300
- matchedFileChunks,
301
317
  diff,
302
318
  diffFilter,
319
+ failOnChanges,
320
+ gitConfigDir,
321
+ matchedFileChunks,
322
+ topLevelDir,
303
323
  })
304
324
 
305
325
  const runner = new Listr(
@@ -311,7 +331,7 @@ export const runAll = async (
311
331
  {
312
332
  title: 'Hiding unstaged changes to partially staged files...',
313
333
  task: (ctx) => git.hideUnstagedChanges(ctx),
314
- enabled: shouldHidePartiallyStagedFiles,
334
+ enabled: shouldHideUnstagedFiles,
315
335
  },
316
336
  {
317
337
  title: `Running tasks for ${diff ? 'changed' : 'staged'} files...`,
@@ -326,7 +346,7 @@ export const runAll = async (
326
346
  {
327
347
  title: 'Restoring unstaged changes to partially staged files...',
328
348
  task: (ctx) => git.restoreUnstagedChanges(ctx),
329
- enabled: shouldHidePartiallyStagedFiles,
349
+ enabled: shouldHideUnstagedFiles,
330
350
  skip: restoreUnstagedChangesSkipped,
331
351
  },
332
352
  {
@@ -1,17 +1,17 @@
1
1
  /** @typedef {import('./index').Logger} Logger */
2
2
 
3
+ import fs, { constants } from 'node:fs/promises'
3
4
  import path from 'node:path'
4
5
 
5
- import debug from 'debug'
6
-
7
6
  import { CONFIG_FILE_NAMES } from './configFiles.js'
7
+ import { createDebug } from './debug.js'
8
8
  import { execGit } from './execGit.js'
9
9
  import { loadConfig } from './loadConfig.js'
10
10
  import { normalizePath } from './normalizePath.js'
11
11
  import { parseGitZOutput } from './parseGitZOutput.js'
12
12
  import { validateConfig } from './validateConfig.js'
13
13
 
14
- const debugLog = debug('lint-staged:searchConfigs')
14
+ const debugLog = createDebug('lint-staged:searchConfigs')
15
15
 
16
16
  const EXEC_GIT = ['ls-files', '-z', '--full-name', '-t']
17
17
 
@@ -21,6 +21,87 @@ const numberOfLevels = (file) => file.split('/').length
21
21
 
22
22
  const sortDeepestParth = (a, b) => (numberOfLevels(a) > numberOfLevels(b) ? -1 : 1)
23
23
 
24
+ /**
25
+ * Get all possible config files from git
26
+ *
27
+ * @param {object} options
28
+ * @param {string} options.cwd
29
+ * @param {string} options.topLevelDir
30
+ * @returns {Promise<string[]>}
31
+ */
32
+ const listConfigFilesFromGit = async ({ cwd, topLevelDir }) =>
33
+ execGit(
34
+ [
35
+ ...EXEC_GIT,
36
+ '--cached', // show all tracked files
37
+ '--others', // show untracked files
38
+ '--exclude-standard', // apply standard git exclusions (.gitignore, etc.)
39
+ '--',
40
+ ...CONFIG_PATHSPEC,
41
+ ],
42
+ { cwd }
43
+ )
44
+ .then(parseGitZOutput)
45
+ .then((lines) => {
46
+ const possibleConfigFiles = lines
47
+ .flatMap((line) => {
48
+ /**
49
+ * Leave out lines starting with "S " to ignore not-checked-out files in a sparse repo.
50
+ * The "S" status means a tracked file that is "skip-worktree"
51
+ * @see https://git-scm.com/docs/git-ls-files#Documentation/git-ls-files.txt--t
52
+ */
53
+ if (line.startsWith('S ')) {
54
+ return []
55
+ }
56
+
57
+ const relativePath = line.replace(/^[HSMRCK?U] /, '')
58
+ const absolutePath = normalizePath(path.join(topLevelDir, relativePath))
59
+ return [absolutePath]
60
+ })
61
+ .sort(sortDeepestParth)
62
+
63
+ debugLog('Found possible config files from git:', possibleConfigFiles)
64
+
65
+ return possibleConfigFiles
66
+ })
67
+
68
+ /**
69
+ * Get all possible config files from filesystem, starting from `cwd` and
70
+ * moving upwards if nothing is found.
71
+ *
72
+ * @param {object} options
73
+ * @param {string} options.cwd
74
+ * @param {string[]} [possibleConfigFiles]
75
+ * @returns {Promise<string[]>}
76
+ */
77
+ export const listConfigFilesFromFs = async ({ cwd }) => {
78
+ debugLog('Listing possible configs from filesystem starting from "%s"...', cwd)
79
+
80
+ const results = await Promise.allSettled(
81
+ CONFIG_FILE_NAMES.map(async (f) => {
82
+ const filepath = path.join(cwd, f)
83
+ await fs.access(filepath, constants.F_OK)
84
+ return filepath
85
+ })
86
+ )
87
+
88
+ const possibleConfigFiles = results.flatMap((r) =>
89
+ r.status === 'fulfilled' ? [normalizePath(r.value)] : []
90
+ )
91
+
92
+ if (possibleConfigFiles.length > 0) {
93
+ debugLog('Found possible config files from filesystem:', possibleConfigFiles)
94
+ return possibleConfigFiles.sort((a, b) => a.localeCompare(b))
95
+ }
96
+
97
+ const parentDir = path.dirname(cwd)
98
+ if (parentDir === cwd) {
99
+ return [] /** Root-level / */
100
+ }
101
+
102
+ return listConfigFilesFromFs({ cwd: parentDir })
103
+ }
104
+
24
105
  /**
25
106
  * Search all config files from the git repository, preferring those inside `cwd`.
26
107
  *
@@ -28,6 +109,7 @@ const sortDeepestParth = (a, b) => (numberOfLevels(a) > numberOfLevels(b) ? -1 :
28
109
  * @param {Object} [options.configObject] - Explicit config object from the js API
29
110
  * @param {string} [options.configPath] - Explicit path to a config file
30
111
  * @param {string} [options.cwd] - Current working directory
112
+ * @param {string} [options.topLevelDir] - Top-level directory of the git repo
31
113
  * @param {Logger} logger
32
114
  *
33
115
  * @returns {Promise<{ [key: string]: { config: *, files: string[] } }>} found configs with filepath as key, and config as value
@@ -55,40 +137,10 @@ export const searchConfigs = async (
55
137
  return { [configPath]: validateConfig(config, filepath, logger) }
56
138
  }
57
139
 
58
- /** Get all possible config files from git (both cached and uncommitted) */
59
- const gitListedFiles = await execGit(
60
- [
61
- ...EXEC_GIT,
62
- '--cached', // show all tracked files
63
- '--others', // show untracked files
64
- '--exclude-standard', // apply standard git exclusions (.gitignore, etc.)
65
- '--',
66
- ...CONFIG_PATHSPEC,
67
- ],
68
- { cwd }
69
- ).then(parseGitZOutput)
70
-
71
- debugLog('Git listed files matching config files:', gitListedFiles)
72
-
73
- /** Sort possible config files so that deepest is first */
74
- const possibleConfigFiles = gitListedFiles
75
- .flatMap((line) => {
76
- /**
77
- * Leave out lines starting with "S " to ignore not-checked-out files in a sparse repo.
78
- * The "S" status means a tracked file that is "skip-worktree"
79
- * @see https://git-scm.com/docs/git-ls-files#Documentation/git-ls-files.txt--t
80
- */
81
- if (line.startsWith('S ')) {
82
- return []
83
- }
84
-
85
- const relativePath = line.replace(/^[HSMRCK?U] /, '')
86
- const absolutePath = normalizePath(path.join(topLevelDir, relativePath))
87
- return [absolutePath]
88
- })
89
- .sort(sortDeepestParth)
90
-
91
- debugLog('Found possible config files:', possibleConfigFiles)
140
+ let possibleConfigFiles = await listConfigFilesFromGit({ cwd, topLevelDir })
141
+ if (possibleConfigFiles.length === 0) {
142
+ possibleConfigFiles = await listConfigFilesFromFs({ cwd })
143
+ }
92
144
 
93
145
  /** Create object with key as config file, and value as null */
94
146
  const configs = possibleConfigFiles.reduce(
@@ -112,26 +164,13 @@ export const searchConfigs = async (
112
164
  )
113
165
 
114
166
  /** Get validated configs from the above object, without any `null` values (not found) */
115
- const foundConfigs = Object.entries(configs)
116
- .filter(([, value]) => !!value)
117
- .reduce((acc, [key, value]) => Object.assign(acc, { [key]: value }), {})
118
-
119
- /**
120
- * Try to find a single config from parent directories
121
- * to match old behavior before monorepo support
122
- */
123
- if (!Object.keys(foundConfigs).length) {
124
- debugLog('Could not find config files inside "%s"', cwd)
125
-
126
- const { config, filepath } = await loadConfig({ cwd }, logger)
127
- if (config) {
128
- debugLog('Found parent configuration file from "%s"', filepath)
129
-
130
- foundConfigs[filepath] = validateConfig(config, filepath, logger)
131
- } else {
132
- debugLog('Could not find parent configuration files from "%s"', cwd)
167
+ const foundConfigs = Object.entries(configs).reduce((acc, [key, value]) => {
168
+ if (value) {
169
+ Object.assign(acc, { [key]: value })
133
170
  }
134
- }
171
+
172
+ return acc
173
+ }, {})
135
174
 
136
175
  debugLog('Found %d config files', Object.keys(foundConfigs).length)
137
176
 
package/lib/state.js CHANGED
@@ -2,27 +2,34 @@ import EventEmitter from 'events'
2
2
 
3
3
  import { GIT_ERROR, TASK_ERROR } from './messages.js'
4
4
  import {
5
+ ExitCodeError,
5
6
  GitError,
6
7
  RestoreOriginalStateError,
7
8
  RestoreUnstagedChangesError,
8
9
  TaskError,
9
10
  } from './symbols.js'
10
11
 
11
- export const getInitialState = ({ quiet = false, revert = true } = {}) => ({
12
+ export const getInitialState = ({
13
+ hidePartiallyStaged = true,
14
+ hideUnstaged = false,
15
+ quiet = false,
16
+ revert = true,
17
+ } = {}) => ({
12
18
  backupHash: null,
13
19
  errors: new Set([]),
14
20
  events: new EventEmitter(),
15
- hasPartiallyStagedFiles: null,
21
+ hasFilesToHide: null,
16
22
  output: [],
17
23
  quiet,
18
24
  shouldBackup: null,
19
- shouldHidePartiallyStaged: true,
25
+ shouldHidePartiallyStaged: hidePartiallyStaged,
26
+ shouldHideUnstaged: hideUnstaged,
20
27
  shouldRevert: revert,
21
28
  unstagedPatch: null,
22
29
  })
23
30
 
24
- export const shouldHidePartiallyStagedFiles = (ctx) =>
25
- ctx.hasPartiallyStagedFiles && ctx.shouldHidePartiallyStaged
31
+ export const shouldHideUnstagedFiles = (ctx) =>
32
+ (ctx.shouldHideUnstaged || ctx.shouldHidePartiallyStaged) && ctx.hasFilesToHide
26
33
 
27
34
  export const applyModificationsSkipped = (ctx) => {
28
35
  // Always apply back unstaged modifications when skipping revert or backup
@@ -52,11 +59,17 @@ export const restoreUnstagedChangesSkipped = (ctx) => {
52
59
  export const restoreOriginalStateEnabled = (ctx) =>
53
60
  !!ctx.shouldRevert &&
54
61
  !!ctx.shouldBackup &&
55
- (ctx.errors.has(TaskError) || ctx.errors.has(RestoreUnstagedChangesError))
62
+ (ctx.errors.has(ExitCodeError) ||
63
+ ctx.errors.has(TaskError) ||
64
+ ctx.errors.has(RestoreUnstagedChangesError))
56
65
 
57
66
  export const restoreOriginalStateSkipped = (ctx) => {
58
67
  // Should be skipped in case of unknown git errors
59
- if (ctx.errors.has(GitError) && !ctx.errors.has(RestoreUnstagedChangesError)) {
68
+ if (
69
+ ctx.errors.has(GitError) &&
70
+ !ctx.errors.has(RestoreUnstagedChangesError) &&
71
+ !ctx.errors.has(ExitCodeError)
72
+ ) {
60
73
  return GIT_ERROR
61
74
  }
62
75
  }
package/lib/symbols.js CHANGED
@@ -25,3 +25,5 @@ export const RestoreOriginalStateError = Symbol('RestoreOriginalStateError')
25
25
  export const RestoreUnstagedChangesError = Symbol('RestoreUnstagedChangesError')
26
26
 
27
27
  export const TaskError = Symbol('TaskError')
28
+
29
+ export const ExitCodeError = Symbol('ExitCodeError')
@@ -2,13 +2,12 @@
2
2
 
3
3
  import { inspect } from 'node:util'
4
4
 
5
- import debug from 'debug'
6
-
5
+ import { createDebug } from './debug.js'
7
6
  import { configurationError, failedToParseConfig } from './messages.js'
8
7
  import { ConfigEmptyError, ConfigFormatError } from './symbols.js'
9
8
  import { validateBraces } from './validateBraces.js'
10
9
 
11
- const debugLog = debug('lint-staged:validateConfig')
10
+ const debugLog = createDebug('lint-staged:validateConfig')
12
11
 
13
12
  export const validateConfigLogic = (config, configPath, logger) => {
14
13
  debugLog('Validating config from `%s`...', configPath)
@@ -2,12 +2,11 @@ import { constants } from 'node:fs'
2
2
  import fs from 'node:fs/promises'
3
3
  import path from 'node:path'
4
4
 
5
- import debug from 'debug'
6
-
5
+ import { createDebug } from './debug.js'
7
6
  import { invalidOption } from './messages.js'
8
7
  import { InvalidOptionsError } from './symbols.js'
9
8
 
10
- const debugLog = debug('lint-staged:validateOptions')
9
+ const debugLog = createDebug('lint-staged:validateOptions')
11
10
 
12
11
  /**
13
12
  * Validate lint-staged options, either from the Node.js API or the command line flags.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lint-staged",
3
- "version": "16.1.6",
3
+ "version": "16.2.0",
4
4
  "description": "Lint files staged by git",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -13,8 +13,6 @@
13
13
  },
14
14
  "author": "Andrey Okonetchnikov <andrey@okonet.ru>",
15
15
  "maintainers": [
16
- "Lufty Wiranda <lufty.wiranda@gmail.com>",
17
- "Suhas Karanth <sudo.suhas@gmail.com>",
18
16
  "Iiro Jäppinen <iiro@jappinen.fi> (https://iiro.fi)"
19
17
  ],
20
18
  "funding": {
@@ -42,47 +40,43 @@
42
40
  "MIGRATION.md"
43
41
  ],
44
42
  "scripts": {
45
- "lint": "eslint .",
46
- "test": "cross-env NODE_OPTIONS=--experimental-vm-modules npx jest --coverage",
47
- "test:watch": "npm run test -- --watch",
48
- "typecheck": "tsc --noEmit --strict test/types/index.ts",
43
+ "lint": "eslint",
44
+ "test": "vitest",
45
+ "typecheck": "tsc",
49
46
  "version": "npx changeset version",
50
47
  "postversion": "npm i --package-lock-only && git commit -am \"chore(changeset): release\"",
51
48
  "tag": "npx changeset tag"
52
49
  },
53
50
  "dependencies": {
54
- "chalk": "^5.6.0",
55
- "commander": "^14.0.0",
56
- "debug": "^4.4.1",
57
- "lilconfig": "^3.1.3",
58
- "listr2": "^9.0.3",
59
- "micromatch": "^4.0.8",
60
- "nano-spawn": "^1.0.2",
61
- "pidtree": "^0.6.0",
62
- "string-argv": "^0.3.2",
63
- "yaml": "^2.8.1"
51
+ "commander": "14.0.1",
52
+ "listr2": "9.0.4",
53
+ "micromatch": "4.0.8",
54
+ "nano-spawn": "1.0.3",
55
+ "pidtree": "0.6.0",
56
+ "string-argv": "0.3.2",
57
+ "yaml": "2.8.1"
64
58
  },
65
59
  "devDependencies": {
66
60
  "@changesets/changelog-github": "0.5.1",
67
- "@changesets/cli": "2.29.6",
61
+ "@changesets/cli": "2.29.7",
68
62
  "@commitlint/cli": "19.8.1",
69
63
  "@commitlint/config-conventional": "19.8.1",
70
- "@eslint/js": "9.34.0",
64
+ "@eslint/js": "9.35.0",
65
+ "@vitest/coverage-v8": "3.2.4",
66
+ "@vitest/eslint-plugin": "1.3.12",
71
67
  "consolemock": "1.1.0",
72
68
  "cross-env": "10.0.0",
73
- "eslint": "9.34.0",
69
+ "eslint": "9.35.0",
74
70
  "eslint-config-prettier": "10.1.8",
75
- "eslint-plugin-jest": "29.0.1",
76
- "eslint-plugin-n": "17.21.3",
71
+ "eslint-plugin-n": "17.23.1",
77
72
  "eslint-plugin-prettier": "5.5.4",
78
73
  "eslint-plugin-simple-import-sort": "12.1.1",
79
74
  "husky": "9.1.7",
80
- "jest": "30.1.1",
81
- "jest-snapshot-serializer-ansi": "2.2.1",
82
75
  "mock-stdin": "1.0.0",
83
76
  "prettier": "3.6.2",
84
77
  "semver": "7.7.2",
85
- "typescript": "5.9.2"
78
+ "typescript": "5.9.2",
79
+ "vitest": "3.2.4"
86
80
  },
87
81
  "keywords": [
88
82
  "lint",