Skip to content

Commit

Permalink
feat: migrate to flat config 🚀
Browse files Browse the repository at this point in the history
BREAKING CHANGE: The ruleset has been migrated to ESLint flat config format and is therefore not compatible with ESLint v7 and using it with v8 requires a feature flag (`ESLINT_USE_FLAT_CONFIG=true`). Project configuration will also need to be completely reworked to use the new ruleset.
  • Loading branch information
robertrossmann committed Feb 15, 2024
1 parent e044364 commit a17b78f
Show file tree
Hide file tree
Showing 60 changed files with 2,417 additions and 7,909 deletions.
File renamed without changes.
22 changes: 0 additions & 22 deletions .eslintrc.js

This file was deleted.

3 changes: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"**/.git": true,
"**/.DS_Store": true,
"**/*.log": true,
"**/node_modules": true,
".eslintcache": true
},
// Custom Application window title ❤️
Expand All @@ -19,10 +18,10 @@
"javascript.format.enable": false,
"typescript.format.enable": false,
// Enable ESLint and its auto-fixer
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "always"
},
"eslint.lintTask.enable": true,
"eslint.lintTask.options": ".",
"eslint.experimental.useFlatConfig": true,
}
124 changes: 93 additions & 31 deletions documentation/eslint/migration.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,106 @@
# Migration from @strv/eslint-config-javascript
# Migrating to flat config (ESLint v9 or >=8.56.0)

This new initiative provides all the functionality which was included in the old ESLint config package, with the only exception being the **flow** ruleset which has been removed. The `v1.0.0` versions of all packages hosted here are 1:1 compatible with the latest version of `@strv/eslint-config-javascript` (`9.2.0`), therefore no new errors or warnings should be reported after the migration.
🚨 As of now (February 2024) some plugins used in these rulesets are not yet compatible with ESLint v9. While it is recommended that you upgrade your projects to the flat config format it also means that if you do, you will need to stay on ESLint v8 until all plugins are updated.

- Uninstall `@strv/eslint-config-javascript`
- Open your _.eslintrc.js_ file and check which rulesets you use
- Based on the table below, replace the rulesets in your config file with the new names
- Install the missing rulesets from npm
---

| Old ruleset | New ruleset | package |
| -------------------------------------------- | -------------------- | -------------------------------------------------------------------------- |
| `@strv/javascript/environments/nodejs/*` | `@strv/node/*` | [`@strv/eslint-config-node`][es-node-home] |
| `@strv/javascript/environments/react/*` | `@strv/react/*` | [`@strv/eslint-config-react`][es-react-home] |
| `@strv/javascript/environments/mocha/*` | `@strv/mocha/*` | [`@strv/eslint-config-mocha`][es-mocha-home] |
| `@strv/javascript/environments/typescript/*` | `@strv/typescript/*` | [`@strv/eslint-config-typescript`][es-ts-home] |
| `@strv/javascript/environments/flow/*` | 🔥 | Removed without replacement 😱 |
| `@strv/javascript/coding-styles/*` | 🔥 | Coding style rulesets are now part of the environment-specific packages ❤️ |
As of ESLint v9 the way ESLint is configured is going to change dramatically. Support for this new "flat" config format has been introduced to ESLint v8.56 behind a feature flag (`ESLINT_USE_FLAT_CONFIG=true` env var). This guide will help you rewrite your config to the new format.

The following rulesets have been removed as part of the migration:
## Documentation

- `@strv/javascript/environments/nodejs/v6`
- `@strv/javascript/environments/nodejs/v8-3`
- `@strv/javascript/environments/flow/*`
- `@strv/javascript/coding-styles/*`
ESLint: https://eslint.org/docs/latest/use/configure/configuration-files-new

## Still confused?
## Old way

Open an issue over at [@strv/code-quality-tools][cqt-home] or ping @robertrossmann on STRV Slack. 💪
The old system was designed to support YAML, JSON, and JavaScript configuration files. You would use a ruleset or a plugin by providing its name (a string) and ESLint would look it up and use it. Also, ESLint automatically checked known JavaScript files and you had to go the extra mile to add support for ie. TypeScript (`.ts`) or React (`.jsx`) files.

## ...but why?
```js
// .eslintrc.js

### More granular release cycle
// Example config. Notice how it's not clear which files are going to be linted by default.
// Also notice that the `extends` field is a string and ESLint needs to load that module.
/** @type {import("eslint").Linter.Config} */
module.exports = {
reportUnusedDisableDirectives: true,
extends: [
'@strv/node/v20',
'@strv/node/optional',
'@strv/node/style',
],
rules: {
'no-warning-comments': 'off',
},

Separating the environments into dedicated packages will reduce noise when a new version for a specific environment is released. Before, when a new rule has been added to the `nodejs` ruleset, everyone received an upgrade even if they only used the `react` ruleset and did not care about changes to the `nodejs` ruleset. With the new setup, each environment will follow its own semver release cycle.
overrides: [{
files: [
'**/*.ts',
'**/*.spec.ts',
'**/*.e2e-spec.ts',
],
extends: [
'@strv/node/v20',
'@strv/node/optional',
'@strv/eslint-config-typescript',
'@strv/eslint-config-typescript/style',
],
parserOptions: {
project: './tsconfig.json',
},
```
### Not just ESLint anymore
## New way
The new repository contains configurations for a bunch of other linting tools, not just ESLint. We wanted to keep all these configs under a single roof, so we decided to move the code over there.
The new system has several advantages over the previous config format but it also requires a bit more effort to properly set up. Each configuration now encourages to specify the files to which it should apply and all rulesets and plugins are provided as regular imported types because the configuration now must be written in JavaScript.
[cqt-home]: https://github.com/strvcom/code-quality-tools
[es-node-home]: https://github.com/strvcom/code-quality-tools/tree/master/packages/eslint-config-node
[es-react-home]: https://github.com/strvcom/code-quality-tools/tree/master/packages/eslint-config-react
[es-mocha-home]: https://github.com/strvcom/code-quality-tools/tree/master/packages/eslint-config-mocha
[es-ts-home]: https://github.com/strvcom/code-quality-tools/tree/master/packages/eslint-config-typescript
```js
// eslint.config.mjs

// This is a sample configuration for a TypeScript Node.js project.

// All plugins, parsers and rulesets must be imported as modules
import nodev20 from '@strv/eslint-config-node/v20'
import nodeopt from '@strv/eslint-config-node/optional'
import nodestyle from '@strv/eslint-config-node/style'
import ts from '@strv/eslint-config-typescript'
import tsopt from '@strv/eslint-config-typescript/optional'
import tsstyle from '@strv/eslint-config-typescript/style'
// Just to help us re-use the same globs multiple times
const files = {
ts: '**/*.ts',
mjs: '**/*.mjs',
}

// This will allow your IDE to provide autocomplete suggestions ✨
/** @type {Array<import("eslint").Linter.FlatConfig>} */
const config = [{
linterOptions: {
reportUnusedDisableDirectives: true,
},
ignores: ['**/*.js', '*.d.ts', '!.*.js', 'node_modules'],
}, {
// First, we provide a configuration object that supplies the tsconfig path to all plugins that might need it.
files: [files.ts],
languageOptions: {
parserOptions: { project: './tsconfig.json' },
} },
// Next, we apply all the rulesets, one by one, which we want to use for our TypeScript sources.
// ⚠️ Do not apply more than one ruleset inside the same configuration object as they would not get merged correctly.
{ files: [files.ts], ...nodev20 },
{ files: [files.ts], ...nodeopt },
{ files: [files.ts], ...ts },
{ files: [files.ts], ...tsopt },
{ files: [files.ts], ...tsstyle },

{ files: [files.mjs], ...nodev20 },
{ files: [files.mjs], ...nodeopt },
{ files: [files.mjs], ...nodestyle },
// Custom overrides
{ files: [files.ts],
rules: {
'no-warning-comments': 0,
'@typescript-eslint/naming-convention': 'off',
} },
]

export default config
```
8 changes: 1 addition & 7 deletions documentation/readme.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
# Documentation

Each package has it's own documentation living in it's package folder.

Over here you can find more generic stuff which is specific for multiple packages.

---

> 💡 Need help with migration from `@strv/eslint-config-javascript`? See the [eslint/migration.md](./eslint/migration.md) file.
Check out the subfolders to see the docs. 💪
25 changes: 25 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import node from './packages/eslint-config-node/index.mjs'
import optional from './packages/eslint-config-node/optional.mjs'
import style from './packages/eslint-config-node/style.mjs'

/** @type {Array<import("eslint").Linter.FlatConfig>} */
const configs = [{
linterOptions: {
reportUnusedDisableDirectives: true,
},
ignores: [
'node_modules',
'!.*.js',
],
},
node,
optional,
style,
{ files: ['**/*.js', '**/*.mjs'], languageOptions: { sourceType: 'module' } },
{ files: ['**/*.cjs'], languageOptions: { sourceType: 'commonjs' } },
{ rules: {
// TODO: Figure out why ESLint cannot resolve the @typescript-eslint packages

Check warning on line 21 in eslint.config.js

View workflow job for this annotation

GitHub Actions / lint

Unexpected 'todo' comment: 'TODO: Figure out why ESLint cannot...'

Check warning on line 21 in eslint.config.js

View workflow job for this annotation

GitHub Actions / lint

Unexpected 'todo' comment: 'TODO: Figure out why ESLint cannot...'
'import/no-unresolved': 'off',
} }]

export default configs
2 changes: 2 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
SHELL := sh
export PATH := bin/:node_modules/.bin/:$(PATH)
export NODE_OPTIONS := --trace-deprecation
# Enable ESLint Flat Config support
export ESLINT_USE_FLAT_CONFIG=true

# On CI servers, use the `npm ci` installer to avoid introducing changes to the package-lock.json
# On developer machines, prefer the generally more flexible `npm install`. 💪
Expand Down

0 comments on commit a17b78f

Please sign in to comment.