Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: replace cosmiconfig with lilconfig + yaml to reduce dependencies #1042

Merged
merged 1 commit into from Nov 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -109,7 +109,7 @@ Starting with v3.1 you can now use different ways of configuring lint-staged:
- `lint-staged.config.js`, `.lintstagedrc.js`, or `.lintstagedrc.cjs` file in CommonJS format
- Pass a configuration file using the `--config` or `-c` flag
See [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for more details on what formats are supported.
See [lilconfig](https://github.com/antonk52/lilconfig) for more details on what formats are supported.
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.
Expand Down
6 changes: 2 additions & 4 deletions lib/index.js
Expand Up @@ -58,21 +58,19 @@ const lintStaged = async (
) => {
await validateOptions({ shell }, logger)

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

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

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

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)

if (debug) {
Expand Down
60 changes: 37 additions & 23 deletions lib/loadConfig.js
@@ -1,9 +1,44 @@
import { cosmiconfig } from 'cosmiconfig'
import { lilconfig } from 'lilconfig'
import YAML from 'yaml'

/**
* The list of files `lint-staged` will read configuration
* from, in the declared order.
*/
const searchPlaces = [
'package.json',
'.lintstagedrc',
'.lintstagedrc.json',
'.lintstagedrc.yaml',
'.lintstagedrc.yml',
'.lintstagedrc.mjs',
'.lintstagedrc.js',
'.lintstagedrc.cjs',
'lint-staged.config.mjs',
'lint-staged.config.js',
'lint-staged.config.cjs',
]

const dynamicImport = (path) => import(path).then((module) => module.default)

const jsonParse = (path, content) => JSON.parse(content)

/**
* `lilconfig` doesn't support yaml files by default,
* so we add custom loaders for those. Files without
* an extensions are assumed to be yaml — this
* assumption is in `cosmiconfig` as well.
*/
const loaders = {
'.js': dynamicImport,
'.json': jsonParse,
'.mjs': dynamicImport,
'.cjs': dynamicImport,
'.yaml': YAML.parse,
'.yml': YAML.parse,
noExt: YAML.parse,
}

const resolveConfig = (configPath) => {
try {
return require.resolve(configPath)
Expand All @@ -16,27 +51,6 @@ const resolveConfig = (configPath) => {
* @param {string} [configPath]
*/
export const loadConfig = (configPath) => {
const explorer = cosmiconfig('lint-staged', {
searchPlaces: [
'package.json',
'.lintstagedrc',
'.lintstagedrc.json',
'.lintstagedrc.yaml',
'.lintstagedrc.yml',
'.lintstagedrc.mjs',
'.lintstagedrc.js',
'.lintstagedrc.cjs',
'lint-staged.config.mjs',
'lint-staged.config.js',
'lint-staged.config.cjs',
],
loaders: {
'.cjs': dynamicImport,
'.js': dynamicImport,
'.json': jsonParse,
'.mjs': dynamicImport,
},
})

const explorer = lilconfig('lint-staged', { searchPlaces, loaders })
return configPath ? explorer.load(resolveConfig(configPath)) : explorer.search()
}
6 changes: 5 additions & 1 deletion lib/symbols.js
@@ -1,6 +1,10 @@
export const ApplyEmptyCommitError = Symbol('ApplyEmptyCommitError')

export const ConfigNotFoundError = new Error('Config could not be found')
export const ConfigNotFoundError = new Error('Configuration could not be found')

export const ConfigFormatError = new Error('Configuration should be an object or a function')

export const ConfigEmptyError = new Error('Configuration should not be empty')

export const GetBackupStashError = Symbol('GetBackupStashError')

Expand Down
5 changes: 3 additions & 2 deletions lib/validateConfig.js
@@ -1,6 +1,7 @@
import debug from 'debug'

import { configurationError } from './messages.js'
import { ConfigEmptyError, ConfigFormatError } from './symbols.js'
import { validateBraces } from './validateBraces.js'

const debugLog = debug('lint-staged:validateConfig')
Expand All @@ -27,7 +28,7 @@ export const validateConfig = (config, logger) => {
debugLog('Validating config')

if (!config || (typeof config !== 'object' && typeof config !== 'function')) {
throw new Error('Configuration should be an object or a function!')
throw ConfigFormatError
}

/**
Expand All @@ -42,7 +43,7 @@ export const validateConfig = (config, logger) => {
}

if (Object.entries(config).length === 0) {
throw new Error('Configuration should not be empty!')
throw ConfigEmptyError
}

const errors = []
Expand Down