Skip to content

Commit

Permalink
refactor: move config validation logging to validateConfig
Browse files Browse the repository at this point in the history
  • Loading branch information
iiroj committed Jul 22, 2021
1 parent fe2d4ac commit c7eb8fc
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 179 deletions.
142 changes: 60 additions & 82 deletions lib/index.js
Expand Up @@ -12,7 +12,6 @@ const {
ConfigNotFoundError,
GetBackupStashError,
GitError,
InvalidOptionsError,
} = require('./symbols')
const validateConfig = require('./validateConfig')
const validateOptions = require('./validateOptions')
Expand Down Expand Up @@ -83,99 +82,78 @@ const lintStaged = async (
} = {},
logger = console
) => {
try {
await validateOptions({ shell }, logger)
await validateOptions({ shell }, logger)

debugLog('Loading config using `cosmiconfig`')
debugLog('Loading config using `cosmiconfig`')

const resolved = configObject
? { config: configObject, filepath: '(input)' }
: await loadConfig(configPath)
const resolved = configObject
? { config: configObject, filepath: '(input)' }
: await loadConfig(configPath)

if (resolved == null) {
throw ConfigNotFoundError
}
if (resolved == null) {
logger.error(`${ConfigNotFoundError.message}.`)
throw ConfigNotFoundError
}

debugLog('Successfully loaded config from `%s`:\n%O', resolved.filepath, resolved.config)
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, logger)
// resolved.config is the parsed configuration object
// resolved.filepath is the path to the config file that was found
const config = validateConfig(resolved.config, logger)

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)
}
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 {
const ctx = await runAll(
{
allowEmpty,
concurrent,
config,
cwd,
debug,
maxArgLength,
quiet,
relative,
shell,
stash,
verbose,
},
logger
)
debugLog('Tasks were executed successfully!')
printTaskOutput(ctx, logger)
return true
} catch (runAllError) {
if (runAllError && runAllError.ctx && runAllError.ctx.errors) {
const { ctx } = runAllError
if (ctx.errors.has(ApplyEmptyCommitError)) {
logger.warn(PREVENTED_EMPTY_COMMIT)
} else if (ctx.errors.has(GitError) && !ctx.errors.has(GetBackupStashError)) {
logger.error(GIT_ERROR)
if (ctx.shouldBackup) {
// No sense to show this if the backup stash itself is missing.
logger.error(RESTORE_STASH_EXAMPLE)
}
}
// 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

printTaskOutput(ctx, logger)
return false
try {
const ctx = await runAll(
{
allowEmpty,
concurrent,
config,
cwd,
debug,
maxArgLength,
quiet,
relative,
shell,
stash,
verbose,
},
logger
)
debugLog('Tasks were executed successfully!')
printTaskOutput(ctx, logger)
return true
} catch (runAllError) {
if (runAllError && runAllError.ctx && runAllError.ctx.errors) {
const { ctx } = runAllError
if (ctx.errors.has(ApplyEmptyCommitError)) {
logger.warn(PREVENTED_EMPTY_COMMIT)
} else if (ctx.errors.has(GitError) && !ctx.errors.has(GetBackupStashError)) {
logger.error(GIT_ERROR)
if (ctx.shouldBackup) {
// No sense to show this if the backup stash itself is missing.
logger.error(RESTORE_STASH_EXAMPLE)
}
}

// Probably a compilation error in the config js file. Pass it up to the outer error handler for logging.
throw runAllError
}
} catch (lintStagedError) {
/** throw early because `validateOptions` options contains own logging */
if (lintStagedError === InvalidOptionsError) {
throw InvalidOptionsError
}

/** @todo move logging to `validateConfig` and remove this try/catch block */
if (lintStagedError === ConfigNotFoundError) {
logger.error(`${lintStagedError.message}.`)
} else {
// It was probably a parsing error
logger.error(`Could not parse lint-staged config.
${lintStagedError.message}`)
printTaskOutput(ctx, logger)
return false
}
// Print helpful message for all errors
logger.error(`Please make sure you have created it correctly.
See https://github.com/okonet/lint-staged#configuration.`)

throw lintStagedError
// Probably a compilation error in the config js file. Pass it up to the outer error handler for logging.
throw runAllError
}
}

Expand Down
11 changes: 4 additions & 7 deletions lib/messages.js
Expand Up @@ -7,14 +7,11 @@ const format = require('stringify-object')
const configurationError = (opt, helpMsg, value) =>
`${chalk.redBright(`${error} Validation Error:`)}
Invalid value for '${chalk.bold(opt)}'.
${helpMsg}.
Configured value is: ${chalk.bold(
Invalid value for '${chalk.bold(opt)}': ${chalk.bold(
format(value, { inlineCharacterLimit: Number.POSITIVE_INFINITY })
)}
`
${helpMsg}`

const NOT_GIT_REPO = chalk.redBright(`${error} Current directory is not a git directory!`)

Expand Down Expand Up @@ -47,7 +44,7 @@ const GIT_ERROR = `\n ${error} ${chalk.red(`lint-staged failed due to a git err

const invalidOption = (name, value, message) => `${chalk.redBright(`${error} Validation Error:`)}
Invalid value for option ${chalk.bold(name)}: ${chalk.bold(value)}
Invalid value for option '${chalk.bold(name)}': ${chalk.bold(value)}
${message}
Expand Down
18 changes: 11 additions & 7 deletions lib/validateConfig.js
Expand Up @@ -87,11 +87,7 @@ const validateConfig = (config, logger) => {
const testFn = TEST_DEPRECATED_KEYS.get(pattern)
if (testFn(task)) {
errors.push(
configurationError(
pattern,
'Advanced configuration has been deprecated. For more info, please visit: https://github.com/okonet/lint-staged',
task
)
configurationError(pattern, 'Advanced configuration has been deprecated.', task)
)
}

Expand All @@ -108,7 +104,7 @@ const validateConfig = (config, logger) => {
errors.push(
configurationError(
pattern,
'Should be a string, a function, or an array of strings and functions',
'Should be a string, a function, or an array of strings and functions.',
task
)
)
Expand All @@ -127,7 +123,15 @@ const validateConfig = (config, logger) => {
}, {})

if (errors.length) {
throw new Error(errors.join('\n'))
const message = errors.join('\n\n')

logger.error(`Could not parse lint-staged config.
${message}
See https://github.com/okonet/lint-staged#configuration.`)

throw new Error(message)
}

return validatedConfig
Expand Down
10 changes: 0 additions & 10 deletions test/__snapshots__/index2.spec.js.snap

This file was deleted.

0 comments on commit c7eb8fc

Please sign in to comment.