source: frontend/node_modules/@rushstack/eslint-patch/README.md@ 9af201e

Last change on this file since 9af201e was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 11.5 KB
Line 
1# @rushstack/eslint-patch
2
3Enhance [ESLint](https://eslint.org/) with better support for large scale monorepos!
4
5This is a runtime patch that enables new/experimental features for ESLint. It operates as a "monkey patch"
6that gets loaded with **.eslintrc.js** and modifies the ESLint engine in memory. This approach works
7with your existing ESLint version (no need to install a forked ESLint), and is fully interoperable with
8companion tools such as the ESLint extensions for VS Code and WebStorm.
9
10This package provides several independently loadable features:
11
12- **eslint-bulk-suppressions**: enables you to roll out new lint rules in your monorepo without having to
13 clutter up source files with thousands of machine-generated `// eslint-ignore-next-line` directives.
14 Instead, the "bulk suppressions" for legacy violations are managed in a separate file called
15 **.eslint-bulk-suppressions.json**.
16
17- **modern-module-resolution**: allows an ESLint config package to provide plugin dependencies, avoiding the
18 problem where hundreds of projects in a monorepo need to copy+paste the same `"devDependencies"` in
19 every **package.json** file.
20
21 > **NOTE:** ESLint 8.21.0 has now introduced a new `ESLINT_USE_FLAT_CONFIG` mode that may reduce the need
22 for the `modern-module-resolution` patch.
23
24- **custom-config-package-names**: enables [rig packages](https://heft.rushstack.io/pages/intro/rig_packages/)
25 to provide shareable configs for ESLint, by removing the requirement that `eslint-config` must appear in
26 the NPM package name.
27
28Contributions welcome! If you have more ideas for experimental ESLint enhancements that might benefit
29large scale monorepos, consider adding them to this patch.
30
31
32# eslint-bulk-suppressions feature
33
34<!-- ## is correct here, but ### looks better in NPM's rendering -->
35
36### What it does
37
38As your monorepo evolves and grows, there's an ongoing need to expand and improve lint rules. But whenever a
39new rule is enabled, there may be hundreds or thousands of "legacy violations" in existing source files.
40How to handle that? We could fix the old code, but that's often prohibitively expensive and may even cause
41regressions. We could disable the rule for those projects or files, but we want new code to follow the rule.
42An effective solution is to inject thousands of `// eslint-ignore-next-line` lines, but these "bulk suppressions"
43have an unintended side effect: It normalizes the practice of suppressing lint rules. If people get used to
44seeing `// eslint-ignore-next-line` everywhere, nobody will notice when humans suppress the rules for new code.
45That would undermine the mission of establishing better code standards.
46
47The `eslint-bulk-suppressions` feature introduces a way to store machine-generated suppressions in a separate
48file **.eslint-bulk-suppressions.json** which can even be protected using `CODEOWNERS` policies, since that file
49will generally only change when new lint rules are introduced, or in occasional circumstances when existing files
50are being moved or renamed. In this way `// eslint-ignore-next-line` remains a directive written by humans
51and hopefully rarely needed.
52
53
54### Why it's a patch
55
56As with `modern-module-resolution`, our hope is for this feature to eventually be incorporated as an official
57feature of ESLint. Starting out as an unofficial patch allows faster iteration and community feedback.
58
59
60### How to use it
61
621. Add `@rushstack/eslint-patch` as a dependency of your project:
63
64 ```bash
65 cd your-project
66 npm install --save-dev @rushstack/eslint-patch
67 ```
68
692. Globally install the [`@rushstack/eslint-bulk`](https://www.npmjs.com/package/@rushstack/eslint-bulk)
70 command line interface (CLI) package. For example:
71
72 ```bash
73 npm install --global @rushstack/eslint-bulk
74 ```
75
76 This installs the `eslint-bulk` shell command for managing the **.eslint-bulk-suppressions.json** files.
77 With it you can generate new suppressions as well as "prune" old suppressions that are no longer needed.
78
793. Load the patch by adding the following `require()` statement as the first line of
80 your **.eslintrc.js** file. For example:
81
82 **.eslintrc.js**
83 ```js
84 require("@rushstack/eslint-patch/eslint-bulk-suppressions"); // 👈 add this line
85
86 module.exports = {
87 rules: {
88 rule1: 'error',
89 rule2: 'warning'
90 },
91 parserOptions: { tsconfigRootDir: __dirname }
92 };
93 ```
94
95Typical workflow:
96
971. Checkout your `main` branch, which is in a clean state where ESLint reports no violations.
982. Update your configuration to enable the latest lint rules; ESLint now reports thousands of legacy violations.
993. Run `eslint-bulk suppress --all ./src` to update **.eslint-bulk-suppressions.json.**
1004. ESLint now no longer reports violations, so commit the results to Git and merge your pull request.
1015. Over time, engineers may improve some of the suppressed code, in which case the associated suppressions are no longer needed.
1026. Run `eslint-bulk prune` periodically to find and remove unnecessary suppressions from **.eslint-bulk-suppressions.json**, ensuring that new violations will now get caught in those scopes.
103
104### "eslint-bulk suppress" command
105
106```bash
107eslint-bulk suppress --rule NAME1 [--rule NAME2...] PATH1 [PATH2...]
108eslint-bulk suppress --all PATH1 [PATH2...]
109```
110
111Use this command to automatically generate bulk suppressions for the specified lint rules and file paths.
112The path argument is a [glob pattern](https://en.wikipedia.org/wiki/Glob_(programming)) with the same syntax
113as path arguments for the `eslint` command.
114
115
116### "eslint-bulk prune" command
117
118Use this command to automatically delete all unnecessary suppression entries in all
119**.eslint-bulk-suppressions.json** files under the current working directory.
120
121```bash
122eslint-bulk prune
123```
124
125### Implementation notes
126
127The `eslint-bulk` command is a thin wrapper whose behavior is actually provided by the patch itself.
128In this way, if your monorepo contains projects using different versions of this package, the same globally
129installed `eslint-bulk` command can be used under any project folder, and it will always invoke the correct
130version of the engine compatible with that project. Because the patch is loaded by ESLint, the `eslint-bulk`
131command must be invoked in a project folder that contains an **.eslintrc.js** configuration with correctly
132installed **package.json** dependencies.
133
134Here's an example of the bulk suppressions file content:
135
136**.eslint-bulk-suppressions.json**
137```js
138{
139 "suppressions": [
140 {
141 "rule": "no-var",
142 "file": "./src/your-file.ts",
143 "scopeId": ".ExampleClass.exampleMethod"
144 }
145 ]
146}
147```
148The `rule` field is the ESLint rule name. The `file` field is the source file path, relative to the **eslintrc.js** file. The `scopeId` is a special string built from the names of containing structures. (For implementation details, take a look at the [calculateScopeId()](https://github.com/microsoft/rushstack/blob/e95c51088341f01516ee5a7639d57c3f6dce8772/eslint/eslint-patch/src/eslint-bulk-suppressions/bulk-suppressions-patch.ts#L52) function.) The `scopeId` identifies a region of code where the rule should be suppressed, while being reasonably stable across edits of the source file.
149
150# modern-module-resolution feature
151
152### What it does
153
154This patch is a workaround for a longstanding [ESLint feature request](https://github.com/eslint/eslint/issues/3458)
155that would allow a shareable ESLint config to bring along its own plugins, rather than imposing peer dependencies
156on every consumer of the config. In a monorepo scenario, this enables your lint setup to be consolidated in a
157single NPM package. Doing so greatly reduces the copy+pasting and version management for all the other projects
158that use your standard lint rule set, but don't want to be bothered with the details.
159
160> **NOTE:** ESLint 8.21.0 has now introduced a new `ESLINT_USE_FLAT_CONFIG` mode that may reduce the need
161> for this patch.
162
163
164### Why it's a patch
165
166We initially proposed this feature in a pull request for the official ESLint back in 2019, however the
167maintainers preferred to implement a more comprehensive overhaul of the ESLint config engine. It ultimately
168shipped with the experimental new `ESLINT_USE_FLAT_CONFIG` mode (still opt-in as of ESLint 8).
169While waiting for that, Rush Stack's `modern-module-resolution` patch provided a reliable interim solution.
170We will continue to maintain this patch as long as it is being widely used, but we encourage you to check out
171`ESLINT_USE_FLAT_CONFIG` and see if it meets your needs.
172
173
174### How to use it
175
1761. Add `@rushstack/eslint-patch` as a dependency of your project:
177
178 ```bash
179 cd your-project
180 npm install --save-dev @rushstack/eslint-patch
181 ```
182
1832. Add a `require()` call to the to top of the **.eslintrc.js** file for each project that depends
184 on your shareable ESLint config, for example:
185
186 **.eslintrc.js**
187 ```ts
188 require("@rushstack/eslint-patch/modern-module-resolution"); // 👈 add this line
189
190 // Add your "extends" boilerplate here, for example:
191 module.exports = {
192 extends: ['@your-company/eslint-config'],
193 parserOptions: { tsconfigRootDir: __dirname }
194 };
195 ```
196
197With this change, the local project no longer needs any ESLint plugins in its **package.json** file.
198Instead, the hypothetical `@your-company/eslint-config` NPM package would declare the plugins as its
199own dependencies.
200
201This patch works by modifying the ESLint engine so that its module resolver will load relative to the folder of
202the referencing config file, rather than the project folder. The patch is compatible with ESLint 6, 7, and 8.
203It also works with any editor extensions that load ESLint as a library.
204
205For an even leaner setup, `@your-company/eslint-config` can provide the patches as its own dependency.
206See [@rushstack/eslint-config](https://github.com/microsoft/rushstack/blob/main/eslint/eslint-config/patch/modern-module-resolution.js) for a real world example.
207
208
209# custom-config-package-names feature
210
211### What it does
212
213Load the `custom-config-package-names` patch to remove ESLint's
214[naming requirement](https://eslint.org/docs/latest/extend/shareable-configs)
215that `eslint-config` must be part of the NPM package name for shareable configs.
216
217This is useful because Rush Stack's [rig package](https://heft.rushstack.io/pages/intro/rig_packages/)
218specification defines a way for many different tooling configurations and dependencies to be shared
219via a single NPM package, for example
220[`@rushstack/heft-web-rig`](https://www.npmjs.com/package/@rushstack/heft-web-rig).
221Rigs avoid a lot of copy+pasting of dependencies in a large scale monorepo.
222Rig packages always include the `-rig` suffix in their name. It doesn't make sense to enforce
223that `eslint-config` should also appear in the name of a package that includes shareable configs
224for many other tools besides ESLint.
225
226### How to use it
227
228Continuing the example above, to load this patch you would add a second line to your config file:
229
230**.eslintrc.js**
231```ts
232require("@rushstack/eslint-patch/modern-module-resolution");
233require("@rushstack/eslint-patch/custom-config-package-names"); // 👈 add this line
234
235// Add your "extends" boilerplate here, for example:
236module.exports = {
237 extends: [
238 '@your-company/build-rig/profile/default/includes/eslint/node' // Notice the package name does not start with "eslint-config-"
239 ],
240 parserOptions: { tsconfigRootDir: __dirname }
241};
242```
243
244
245# Links
246
247- [CHANGELOG.md](https://github.com/microsoft/rushstack/blob/main/eslint/eslint-patch/CHANGELOG.md) - Find
248 out what's new in the latest version
249
250- [`@rushstack/eslint-bulk`](https://www.npmjs.com/package/@rushstack/eslint-bulk) CLI package
251
252`@rushstack/eslint-patch` is part of the [Rush Stack](https://rushstack.io/) family of projects.
Note: See TracBrowser for help on using the repository browser.