├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── index.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Maxim Orlov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eslint-config-async 2 | 3 | A shareable ESLint config for writing better asynchronous code. 4 | 5 | Find an overview of what rules are enabled, and why, in this article: 6 | 7 | 📚 [**14 Linting Rules To Help You Write Asynchronous Code in JavaScript**](https://maximorlov.com/linting-rules-for-asynchronous-code-in-javascript/) 8 | 9 | ## Table of contents 10 | 11 | - [Table of contents](#table-of-contents) 12 | - [Requirements](#requirements) 13 | - [Installation \& usage](#installation--usage) 14 | - [Non-TypeScript users](#non-typescript-users) 15 | - [TypeScript users](#typescript-users) 16 | - [Migrating from v2 to v3](#migrating-from-v2-to-v3) 17 | - [Migrating from v1 to v2](#migrating-from-v1-to-v2) 18 | 19 | ## Requirements 20 | 21 | - ESLint v9 22 | - Node.js ^18.18.0, ^20.9.0, or >=21.1.0 (set by ESLint v9) 23 | 24 | If you're using ESLint v8, you should use v2 of this library. [Installation & usage for eslint-config-async v2](https://github.com/Maximization/eslint-config-async/blob/v2.0.3/README.md). 25 | 26 | ## Installation & usage 27 | 28 | ### Non-TypeScript users 29 | Install this package and ESLint: 30 | 31 | ```shell 32 | npm install --save-dev eslint eslint-config-async 33 | ``` 34 | 35 | In your `eslint.config.js` configuration file: 36 | 37 | ```js 38 | const asyncConfig = require("eslint-config-async"); 39 | 40 | module.exports = [ 41 | ...asyncConfig.base, // enable base rules 42 | ...asyncConfig.node, // enable Node.js specific rules (recommended) 43 | ]; 44 | ``` 45 | 46 | ### TypeScript users 47 | Install this package and its peer dependencies: 48 | 49 | ```shell 50 | npm install --save-dev eslint eslint-config-async typescript typescript-eslint 51 | ``` 52 | 53 | In your `eslint.config.js` configuration file: 54 | 55 | ```js 56 | const tseslint = require("typescript-eslint"); 57 | const asyncConfig = require("eslint-config-async"); 58 | 59 | module.exports = [ 60 | // One of tseslint configs must be enabled 61 | // Either the base config 62 | tseslint.configs.base, // adds the parser only, without any rules 63 | // or 64 | ...tseslint.configs.recommended, // includes base + a list of recommended rules 65 | // ..and others 66 | 67 | ...asyncConfig.base, // enable base rules 68 | ...asyncConfig.node, // enable Node.js specific rules (recommended) 69 | ...asyncConfig.typescript, // enable TypeScript specific rules 70 | { 71 | files: ["*.ts"], // tell ESLint to include TypeScript files 72 | languageOptions: { 73 | parserOptions: { 74 | projectService: true, 75 | tsconfigRootDir: __dirname, 76 | }, 77 | }, 78 | }, 79 | ]; 80 | ``` 81 | 82 | ## Migrating from v2 to v3 83 | 84 | Version 3 upgrades ESLint to v9. ESLint uses a [flat configuration file](https://eslint.org/docs/latest/use/configure/configuration-files). `.eslintrc.*` has been deprecated and you should rename it to `eslint.config.js` (or .cjs, .mjs): 85 | 86 | ```diff 87 | - .eslintrc 88 | + eslint.config.js 89 | ``` 90 | 91 | In your `eslint.config.js` file, make the following changes: 92 | 93 | ```diff 94 | - module.exports = { 95 | - plugins: [ 96 | - 'eslint-plugin-node' 97 | - ], 98 | - extends: [ 99 | - 'async', 100 | - 'async/node' 101 | - ], 102 | - }; 103 | + const asyncConfig = require("eslint-config-async"); 104 | + 105 | + module.exports = [ 106 | + ...asyncConfig.base, // enable base rules 107 | + ...asyncConfig.node, // enable Node.js specific rules (recommended) 108 | + ]; 109 | ``` 110 | 111 | `eslint-plugin-node` is no longer maintained and has been replaced with its fork, `eslint-plugin-n`. `eslint-plugin-n` is not a peer dependency and is included with this library, therefore you no longer need to install it separately: 112 | 113 | ```shell 114 | npm remove --save-dev eslint-plugin-node 115 | ``` 116 | 117 | For TypeScript users, change the contents of `eslint.config.js` file as follows: 118 | 119 | ```diff 120 | - module.exports = { 121 | - plugins: [ 122 | - 'eslint-plugin-node', 123 | - '@typescript-eslint' 124 | - ], 125 | - extends: [ 126 | - 'async', 127 | - 'async/node', 128 | - 'async/typescript' 129 | - ], 130 | - parser: '@typescript-eslint/parser', 131 | - parserOptions: { 132 | - tsconfigRootDir: __dirname, 133 | - project: ['./tsconfig.json'], 134 | - } 135 | - }; 136 | 137 | + const tseslint = require("typescript-eslint"); 138 | + const asyncConfig = require("eslint-config-async"); 139 | + 140 | + module.exports = [ 141 | + tseslint.configs.base, 142 | + ...asyncConfig.base, // enable base rules 143 | + ...asyncConfig.node, // enable Node.js specific rules (recommended) 144 | + ...asyncConfig.typescript, // enable TypeScript specific rules 145 | + { 146 | + files: ["*.ts"], // tell ESLint to include TypeScript files 147 | + languageOptions: { 148 | + parserOptions: { 149 | + projectService: true, 150 | + tsconfigRootDir: __dirname, 151 | + }, 152 | + }, 153 | + }, 154 | + ]; 155 | ``` 156 | 157 | Replace `@typescript-eslint/parser` and `@typescript-eslint/eslint-plugin` with `typescript-eslint`: 158 | 159 | ```shell 160 | npm remove @typescript-eslint/parser @typescript-eslint/eslint-plugin && npm install --save-dev typescript-eslint 161 | ``` 162 | 163 | ## Migrating from v1 to v2 164 | 165 | Version 2 adds TypeScript specific rules and exports multiple configs, namely: 166 | 167 | - Base rules (`eslint-config-async`) 168 | - Node.js specific rules (`eslint-config-async/node`) 169 | - TypeScript rules (`eslint-config-async/typescript`) 170 | 171 | In version 1, the base and Node.js specific rules were included by default. In version 2, you need to explicitly add the Node.js rules: 172 | 173 | ```diff 174 | module.exports = { 175 | extends: [ 176 | - 'eslint-config-async' 177 | + 'eslint-config-async', 178 | + 'eslint-config-async/node' 179 | ], 180 | } 181 | ``` 182 | 183 | Or using the short syntax: 184 | 185 | ```diff 186 | module.exports = { 187 | extends: [ 188 | - 'eslint-config-async' 189 | + 'async', 190 | + 'async/node' 191 | ], 192 | } 193 | ``` 194 | 195 | If you added the TypeScript specific rules manually in your project, you can remove them and replace them with this config: 196 | 197 | ```diff 198 | module.exports = { 199 | extends: [ 200 | 'async', 201 | 'async/node', 202 | + 'async/typescript' 203 | ], 204 | rules: { 205 | - "@typescript-eslint/await-thenable": "error", 206 | - "@typescript-eslint/no-floating-promises": "error", 207 | - "@typescript-eslint/no-misused-promises": "error", 208 | - "@typescript-eslint/promise-function-async": "error", 209 | } 210 | } 211 | ``` 212 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const nodePlugin = require("eslint-plugin-n"); 2 | 3 | module.exports = { 4 | // Base rules 5 | base: [ 6 | { 7 | rules: { 8 | "no-async-promise-executor": "error", 9 | "no-await-in-loop": "error", 10 | "no-promise-executor-return": "error", 11 | "require-atomic-updates": "error", 12 | "max-nested-callbacks": ["error", 3], 13 | "no-return-await": "error", 14 | "prefer-promise-reject-errors": "error", 15 | }, 16 | }, 17 | ], 18 | 19 | // Node.js rules 20 | node: [ 21 | { 22 | plugins: { n: nodePlugin }, 23 | rules: { 24 | "n/handle-callback-err": ["error", "^(e|err|error)$"], 25 | "n/no-callback-literal": "error", 26 | "n/no-sync": "error", 27 | }, 28 | }, 29 | ], 30 | 31 | // TypeScript rules 32 | typescript: [ 33 | { 34 | rules: { 35 | "@typescript-eslint/await-thenable": "error", 36 | "@typescript-eslint/no-floating-promises": "error", 37 | "@typescript-eslint/no-misused-promises": "error", 38 | "@typescript-eslint/promise-function-async": "error", 39 | }, 40 | }, 41 | ], 42 | }; 43 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-async", 3 | "version": "3.0.0", 4 | "description": "A shareable ESLint config for writing better asynchronous code", 5 | "main": "index.js", 6 | "engines": { 7 | "node": "^18.18.0 || ^20.9.0 || >=21.1.0" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/Maximization/eslint-config-async.git" 12 | }, 13 | "homepage": "https://github.com/Maximization/eslint-config-async#readme", 14 | "bugs": "https://github.com/Maximization/eslint-config-async/issues", 15 | "scripts": { 16 | "release": "np --no-tests" 17 | }, 18 | "files": [ 19 | "index.js" 20 | ], 21 | "keywords": [ 22 | "eslint", 23 | "eslintconfig" 24 | ], 25 | "author": "Maxim Orlov (https://maximorlov.com)", 26 | "license": "MIT", 27 | "dependencies": { 28 | "eslint-plugin-n": "17.10.2" 29 | }, 30 | "devDependencies": { 31 | "np": "8.0.4", 32 | "prettier": "2.6.0" 33 | }, 34 | "peerDependencies": { 35 | "eslint": "^9.0.0", 36 | "typescript": "*", 37 | "typescript-eslint": "^8.0.0" 38 | }, 39 | "peerDependenciesMeta": { 40 | "typescript": { 41 | "optional": true 42 | } 43 | } 44 | } 45 | --------------------------------------------------------------------------------