@cloudfour/eslint-config
v28.0.0
Published
Cloud Four's shareable ESLint configuration
Readme
@cloudfour/eslint-config
Cloud Four's ESLint configuration.
This config extends the following plugins:
It is built on eslint-config-xo, which
bundles and configures most of the plugins we rely on — including
unicorn,
jsdoc,
n,
@typescript-eslint,
regexp and
import-x — plus rules for
package.json, JSON, Markdown, CSS and HTML. On top of that we add our own
overrides, which is where our house style actually lives.
Rule names use xo's namespaces as-is. Note that import rules are import-x/*, not
import/*.
One plugin is ours directly rather than xo's:
promise. We are considering dropping this:promise/param-namesis the only rule we take from it, and a whole dependency for one rule is hard to justify. If we drop it, that rule goes with it.
Usage
This package exports a flat ESLint configuration.
npm install --save-dev eslint @cloudfour/eslint-configExample eslint.config.js:
import cloudFourConfig from '@cloudfour/eslint-config';
export default [
...cloudFourConfig,
{
rules: {
// your overrides here
...
}
},
];Writing your own overrides
xo scopes its layers to the file types they lint, and registers plugins on those
layers. A rules block with no files applies to everything — including the
JSON, Markdown, CSS and HTML that xo now lints, where those plugins were never
registered. ESLint then fails to load the config entirely:
A configuration object specifies rule "jsdoc/check-indentation",
but could not find plugin "jsdoc".So scope any override for a JavaScript-only plugin:
{
files: ['**/*.{js,cjs,mjs,ts}'],
rules: {
'jsdoc/check-indentation': 'off',
},
}This is easy to miss, because it passes when you lint a single file
(eslint src/index.js) and only fails across the project (eslint .).
Recommended settings for published packages
We turn off three package.json rules that would otherwise fire on every
project, including the many that never publish anything. Each one asks for
something genuinely worth having in a package you do publish to npm, so
consider switching them back on there:
| Rule | Asks for | Worth it when |
| --------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| package-json/prefer-exports | An exports field instead of main | The package is published and you want a defined public interface. Blocks deep imports into internals, so it's a breaking change — pair it with a major release. |
| package-json/require-engines | engines.node | The package actually runs in Node. Skip it for browser libraries, where there is no Node version to describe. |
| package-json/prefer-type-module | "type": "module" | You are ready to go ESM-only. This breaks every consumer using require(), so it is a major-release decision. |
To adopt them in a project:
{
files: ['package.json'],
rules: {
'package-json/prefer-exports': 'error',
'package-json/require-engines': 'error',
},
}Note that we scope xo's package.json layer to the root manifest. Rules
like require-fields and prefer-type-module describe a package's manifest,
and applying them to every **/package.json reports on files that are not
packages — most notably the {"type": "commonjs"} marker files that dual
CommonJS/ESM builds place in their output directories. If you keep real
manifests somewhere other than the repository root, such as npm workspaces,
widen the scope in your own config:
{
files: ['packages/*/package.json'],
rules: {
'package-json/require-fields': 'error',
},
}