/
index.js
130 lines (117 loc) · 4.24 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
'use strict'
const dedent = require('dedent')
const { cosmiconfig } = require('cosmiconfig')
const stringifyObject = require('stringify-object')
const printErrors = require('./printErrors')
const runAll = require('./runAll')
const validateConfig = require('./validateConfig')
const debugLog = require('debug')('lint-staged')
const errConfigNotFound = new Error('Config could not be found')
function resolveConfig(configPath) {
try {
return require.resolve(configPath)
} catch {
return configPath
}
}
function loadConfig(configPath) {
const explorer = cosmiconfig('lint-staged', {
searchPlaces: [
'package.json',
'.lintstagedrc',
'.lintstagedrc.json',
'.lintstagedrc.yaml',
'.lintstagedrc.yml',
'.lintstagedrc.js',
'lint-staged.config.js'
]
})
return configPath ? explorer.load(resolveConfig(configPath)) : explorer.search()
}
/**
* @typedef {(...any) => void} LogFunction
* @typedef {{ error: LogFunction, log: LogFunction, warn: LogFunction }} Logger
*
* Root lint-staged function that is called from `bin/lint-staged`.
*
* @param {object} options
* @param {Object} [options.allowEmpty] - Allow empty commits when tasks revert all staged changes
* @param {boolean | number} [options.concurrent] - The number of tasks to run concurrently, or false to run tasks serially
* @param {object} [options.config] - Object with configuration for programmatic API
* @param {string} [options.configPath] - Path to configuration file
* @param {number} [options.maxArgLength] - Maximum argument string length
* @param {boolean} [options.relative] - Pass relative filepaths to tasks
* @param {boolean} [options.shell] - Skip parsing of tasks for better shell support
* @param {boolean} [options.quiet] - Disable lint-staged’s own console output
* @param {boolean} [options.debug] - Enable debug mode
* @param {boolean | number} [options.concurrent] - The number of tasks to run concurrently, or false to run tasks serially
* @param {Logger} [logger]
*
* @returns {Promise<boolean>} Promise of whether the linting passed or failed
*/
module.exports = async function lintStaged(
{
allowEmpty = false,
concurrent = true,
config: configObject,
configPath,
maxArgLength,
relative = false,
shell = false,
quiet = false,
debug = false
} = {},
logger = console
) {
try {
debugLog('Loading config using `cosmiconfig`')
const resolved = configObject
? { config: configObject, filepath: '(input)' }
: await loadConfig(configPath)
if (resolved == null) throw errConfigNotFound
debugLog('Successfully loaded config from `%s`:\n%O', resolved.filepath, resolved.config)
// resolved.config is the parsed configuration object
// resolved.filepath is the path to the config file that was found
const config = validateConfig(resolved.config)
if (debug) {
// Log using logger to be able to test through `consolemock`.
logger.log('Running lint-staged with the following config:')
logger.log(stringifyObject(config, { indent: ' ' }))
} else {
// We might not be in debug mode but `DEBUG=lint-staged*` could have
// been set.
debugLog('lint-staged config:\n%O', config)
}
// Unset GIT_LITERAL_PATHSPECS to not mess with path interpretation
debugLog('Unset GIT_LITERAL_PATHSPECS (was `%s`)', process.env.GIT_LITERAL_PATHSPECS)
delete process.env.GIT_LITERAL_PATHSPECS
try {
await runAll(
{ allowEmpty, concurrent, config, debug, maxArgLength, quiet, relative, shell },
logger
)
debugLog('tasks were executed successfully!')
return true
} catch (runAllError) {
printErrors(runAllError, logger)
return false
}
} catch (lintStagedError) {
if (lintStagedError === errConfigNotFound) {
logger.error(`${lintStagedError.message}.`)
} else {
// It was probably a parsing error
logger.error(dedent`
Could not parse lint-staged config.
${lintStagedError}
`)
}
logger.error() // empty line
// Print helpful message for all errors
logger.error(dedent`
Please make sure you have created it correctly.
See https://github.com/okonet/lint-staged#configuration.
`)
throw lintStagedError
}
}