eslint-config-beslogic 3.1.1 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.dprint.jsonc CHANGED
@@ -3,5 +3,5 @@
3
3
 
4
4
  {
5
5
  // https://dprint.dev/config/#extending-a-different-configuration-file
6
- "extends": "https://raw.githubusercontent.com/BesLogic/shared-configs/main/dprint-json-like.json"
6
+ "extends": "https://raw.githubusercontent.com/BesLogic/shared-configs/main/dprint-json-like.json",
7
7
  }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.0.2
4
+
5
+ - Initial support for Flat Configs. v4 will only support Flat Configs (`eslint.config.js`), please use v3 for Legacy Configs (`.eslintrc`).
6
+ - `angular-eslint` won't work on HTML files on ESLint v8 due to parser configuration issues.
7
+ - Autodetection of `.gitignore` using `eslint-config-flat-gitignore`
8
+ - Updated dependencies:
9
+ - Using the combined `typescript-eslint` package instead of `@typescript-eslint/eslint-plugin` + `@typescript-eslint/parser`
10
+ - Using the combined `angular-eslint` package instead of `@angular-eslint/eslint-plugin` + `@angular-eslint/eslint-plugin-template` + `@angular-eslint/template-parser`
11
+ - Bumped `typescript-eslint` to `^8.15`
12
+ - Bumped `angular-eslint` to `>=18.0`
13
+ - Bumped `eslint-plugin-react-hooks` to `^5.0`
14
+ - Bumped `eslint-plugin-react-prefer-function-component` to `^3.3.0`
15
+ - Bumped `eslint-plugin-storybook` to `^0.10`
16
+ - Bumped `eslint-plugin-react` to `^7.37.1`
17
+ - Added dependency on `@eslint/compat` and `eslint-config-flat-gitignore`
18
+
19
+ ## 3.1.2
20
+
21
+ - Removed `globalThis` from `no-restricted-globals` as the adoption is now much wider (no more IE11) and it conflicts with `unicorn/prefer-global-this`
22
+
3
23
  ## 3.1.1
4
24
 
5
25
  - Turned on `"objectLiteralTypeAssertions": "allow-as-parameter"` as error for `@typescript-eslint/consistent-type-assertions` in extra-strict config
package/README.md CHANGED
@@ -6,10 +6,10 @@ Run `npm i --save-dev eslint-config-beslogic`
6
6
 
7
7
  Depending on your needs, you will need to also install other peer dependencies for linting.
8
8
 
9
- In your `.eslintrc` file, add `"extends": "beslogic/<preset>"` (see all available presets below)
9
+ In your `eslint.config.[cm]?js` file, simply [extend](https://typescript-eslint.io/getting-started#step-2-configuration) our [presets](#presets) appropriate for your project.
10
10
 
11
11
  For stylistic rules, it is highly recommended to use a dedicated formatter over ESLint. Read more here: <https://typescript-eslint.io/docs/linting/troubleshooting/formatting/>\
12
- A [dprint preset](#beslogicdprint) is offered below.
12
+ We assume [dprint](https://dprint.dev/) and don't enable any rules it covers by default. If you're not using a formatter, a [stylistic.mjs](#stylisticmjs) configuration is offered below.
13
13
 
14
14
  ## Parallel configurations
15
15
 
@@ -59,7 +59,7 @@ Extend the following in your base `.dprint.jsonc` (follow link for more details)
59
59
  This configuration automatically includes known "exclusion" folders. But if you need to add more, you can copy and expand the `exludes` list in [dprint.json](https://github.com/BesLogic/shared-configs/blob/main/dprint.json).\
60
60
  If you'd like to pin your config version, you can use a commit hash, like `https://raw.githubusercontent.com/BesLogic/shared-configs/a0d9a34/dprint.json`.
61
61
 
62
- If also using [`beslogic/json-like` preset](#beslogicjson-like) extend from `https://raw.githubusercontent.com/BesLogic/shared-configs/main/dprint-json-like.json` instead.
62
+ If also using [`json-like.mjs` preset](#json-likemjs) extend from `https://raw.githubusercontent.com/BesLogic/shared-configs/main/dprint-json-like.json` instead.
63
63
 
64
64
  ### PR Autofixes
65
65
 
@@ -84,29 +84,91 @@ Angular Material's MatDialogRef [defaults it dialog result generic to `any`](htt
84
84
 
85
85
  ## Presets
86
86
 
87
- Below are all the different configurations you can extend from. You can mix and match as you want if a predefined configuration does not exist for your specific stack. You should import TypeScript configs after regular javascript ones. ie `"extends": ["beslogic/node", "beslogic/typescript"]` at the root of the configuration.
87
+ Below are all the different configurations you can extend from. You can mix and match as you want if a predefined configuration does not exist for your specific stack. You should import TypeScript configs after regular javascript ones at the root of the configuration.
88
88
 
89
- ### `beslogic`
89
+ Examples
90
90
 
91
- Default preset, extends from `beslogic/javascript` and `beslogic/typescript`.
91
+ <details>
92
+ <summary>React + TypeScript</summary>
92
93
 
93
- ### `beslogic/jest`
94
+ ```js
95
+ import tseslint from 'typescript-eslint'
96
+ import beslogicExtraStrict from 'eslint-config-beslogic/extra-strict.mjs'
97
+ import beslogicReact from 'eslint-config-beslogic/react.mjs'
98
+ import beslogicTypeScript from 'eslint-config-beslogic/typescript.mjs'
94
99
 
95
- [Jest](https://www.npmjs.com/package/jest) and [Testing Library](https://testing-library.com/) configs. Is already extended by `beslogic/javascript` and `beslogic/typescript` for all `*spec.[jt]s` and `*.test.[jt]sx` files, as well as `*.[jt]s` and `*.[jt]sx` files inside of `__tests__` folders. You should not need to extend from this configuration unless you want to add it to a test file that is not automatically picked up by the naming convention.
100
+ export default tseslint.config(
101
+ beslogicReact,
102
+ beslogicTypeScript,
103
+ beslogicExtraStrict,
104
+ // Your configs here
105
+ {...}
106
+ )
107
+ ```
108
+
109
+ </details>
110
+
111
+ <details>
112
+ <summary>Angular</summary>
113
+
114
+ ```js
115
+ import tseslint from 'typescript-eslint'
116
+ import beslogicAngular from 'eslint-config-beslogic/angular.mjs'
117
+ import beslogicExtraStrict from 'eslint-config-beslogic/extra-strict.mjs'
118
+
119
+ export default tseslint.config(
120
+ beslogicAngular,
121
+ beslogicExtraStrict,
122
+ // Your configs here
123
+ {...}
124
+ )
125
+ ```
126
+
127
+ </details>
128
+
129
+ <details>
130
+ <summary>Frameworkless TypeScript w/o dprint</summary>
131
+
132
+ ```js
133
+ import tseslint from 'typescript-eslint'
134
+ import beslogicExtraStrict from 'eslint-config-beslogic/extra-strict.mjs'
135
+ import beslogicJavascript from 'eslint-config-beslogic/javascript.mjs'
136
+ import beslogicStylistic from 'eslint-config-beslogic/stylistic.mjs'
137
+ import beslogicTypeScript from 'eslint-config-beslogic/typescript.mjs'
138
+
139
+ export default tseslint.config(
140
+ beslogicJavascript,
141
+ beslogicTypeScript,
142
+ beslogicExtraStrict,
143
+ beslogicStylistic,
144
+ // Your configs here
145
+ {...}
146
+ )
147
+ ```
148
+
149
+ </details>
150
+
151
+ ### `index.mjs`
152
+
153
+ Default preset, extends from `javascript.mjs` and `typescript.mjs`.
96
154
 
97
- ### `beslogic/javascript`
155
+ ### `jest.mjs`
98
156
 
99
- Basic javascript configs, is extended by all other configs except `beslogic/typescript`, `beslogic/jest`, `beslogic/storybook` and `beslogic/json-like`.
157
+ [Jest](https://www.npmjs.com/package/jest) and [Testing Library](https://testing-library.com/) configs. Is already extended by `javascript.mjs` and `typescript.mjs` for all `*spec.[jt]s` and `*.test.[jt]sx` files, as well as `*.[jt]s` and `*.[jt]sx` files inside of `__tests__` folders. You should not need to extend from this configuration unless you want to add it to a test file that is not automatically picked up by the naming convention.
100
158
 
101
- ### `beslogic/typescript`
159
+ ### `javascript.mjs`
102
160
 
103
- Basic TypeScript-specific configs and `TSX` support, is extended by all other TypeScript exclusive configs. To avoid rules conflicts, it does **not** already extend from `beslogic/javascript`. So you should extend from both in a pure TypeScript project. You may also need to specify `parserOptions.project`. ie: `"parserOptions": { "project": ["tsconfig.json"] },` and `"parser": "@typescript-eslint/parser"` if you reconfigure some rules yourself.
161
+ Basic javascript configs, is extended by all other configs except `typescript.mjs`, `jest.mjs`, `storybook.mjs` and `json-like.mjs`.
162
+
163
+ ### `typescript.mjs`
164
+
165
+ Basic TypeScript-specific configs and `TSX` support, is extended by all other TypeScript exclusive configs. To avoid rules conflicts, it does **not** already extend from `javascript.mjs`. So you should extend from both in a pure TypeScript project. You may also need to specify `parserOptions.project`. ie: `"parserOptions": { "project": ["tsconfig.json"] },` and `"parser": "@typescript-eslint/parser"` if you reconfigure some rules yourself.
104
166
 
105
167
  For the linting to be fully effective, please make sure that your base `tsconfig.json` extends `eslint-config-beslogic/tsconfig.X.X.json` (see [Parallel configurations](#parallel-configurations)).
106
168
 
107
- If you want extra strict linting, consider adding the [`beslogic/extra-strict` preset](#beslogicextra-strict).
169
+ If you want extra strict linting, consider adding the [`extra-strict.mjs` preset](#extra-strictmjs).
108
170
 
109
- ### `beslogic/node-js`
171
+ ### `node-js.mjs`
110
172
 
111
173
  Configurations for NodeJS backends.
112
174
 
@@ -116,9 +178,9 @@ Add the following `devDependencies` to your `package.json`:
116
178
  npm install --save-dev eslint-plugin-n
117
179
  ```
118
180
 
119
- ### `beslogic/rxjs`
181
+ ### `rxjs.mjs`
120
182
 
121
- Configurations for projects using RxJs. Already extends and `beslogic/typescript` for TypeScript-specific rules and is already extended by `beslogic/angular`.
183
+ Configurations for projects using RxJs. Already extends and `typescript.mjs` for TypeScript-specific rules and is already extended by `angular.mjs`.
122
184
 
123
185
  Add the following `devDependencies` to your `package.json`:
124
186
 
@@ -126,7 +188,7 @@ Add the following `devDependencies` to your `package.json`:
126
188
  npm install --save-dev eslint-plugin-rxjs
127
189
  ```
128
190
 
129
- ### `beslogic/react`
191
+ ### `react.mjs`
130
192
 
131
193
  Configurations for React projects. Comes with `JSX` support.
132
194
 
@@ -136,9 +198,9 @@ Add the following `devDependencies` to your `package.json`:
136
198
  npm install --save-dev eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-react-prefer-function-component
137
199
  ```
138
200
 
139
- ### `beslogic/react-native`
201
+ ### `react-native.mjs`
140
202
 
141
- Configurations for [React Native](https://reactnative.dev/) projects, including [Expo](https://expo.dev/). Already extends `beslogic/react`.
203
+ Configurations for [React Native](https://reactnative.dev/) projects, including [Expo](https://expo.dev/). Already extends `react.mjs`.
142
204
 
143
205
  Add the following `devDependencies` to your `package.json`:
144
206
 
@@ -146,9 +208,9 @@ Add the following `devDependencies` to your `package.json`:
146
208
  npm install --save-dev eslint-plugin-react-native eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-react-prefer-function-component
147
209
  ```
148
210
 
149
- ### `beslogic/react-redux`
211
+ ### `react-redux.mjs`
150
212
 
151
- Configurations for React projects using the Redux bindings. Already extends `beslogic/react`.
213
+ Configurations for React projects using the Redux bindings. Already extends `react.mjs`.
152
214
 
153
215
  Add the following `devDependencies` to your `package.json`:
154
216
 
@@ -156,9 +218,9 @@ Add the following `devDependencies` to your `package.json`:
156
218
  npm install --save-dev eslint-plugin-react-redux eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-react-prefer-function-component
157
219
  ```
158
220
 
159
- ### `beslogic/mui`
221
+ ### `mui.mjs`
160
222
 
161
- [MUI/material](https://github.com/mui-org/material-ui) framework configurations. Already extends `beslogic/react` and `beslogic/typescript`.
223
+ [MUI/material](https://github.com/mui-org/material-ui) framework configurations. Already extends `react.mjs` and `typescript.mjs`.
162
224
 
163
225
  Add the following `devDependencies` to your `package.json`:
164
226
 
@@ -166,20 +228,22 @@ Add the following `devDependencies` to your `package.json`:
166
228
  npm install --save-dev eslint-plugin-mui eslint-plugin-jsx-a11y eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-react-prefer-function-component
167
229
  ```
168
230
 
169
- ### `beslogic/angular`
231
+ ### `angular.mjs`
170
232
 
171
- Configurations for NGX projects. Comes with `html` template and inline template support. Already extends `beslogic/rxjs` and `beslogic/typescript`. Also extends `beslogic/node-js` for Javascript files.
233
+ Configurations for NGX projects. Comes with `html` template and inline template support. Already extends `rxjs.mjs` and `typescript.mjs`. Also extends `node-js.mjs` for Javascript files.
172
234
 
173
235
  For the linting to be fully effective, please make sure that your base `tsconfig.json` extends `eslint-config-beslogic/tsconfig.X.X.json` (see [Parallel configurations](#parallel-configurations)).\
174
236
  If bundling as an npm package set `"strictMetadataEmit": true` under `angularCompilerOptions`.
175
237
 
238
+ **NOTE**: `angular-eslint` won't work on HTML files on ESLint v8 due to parser configuration issues.
239
+
176
240
  Add the following `devDependencies` to your `package.json`:
177
241
 
178
242
  ```shell
179
243
  npm install --save-dev @angular-eslint/eslint-plugin @angular-eslint/eslint-plugin-template @angular-eslint/template-parser github:BesLogic/eslint-plugin-rxjs-angular#dist eslint-plugin-angular-file-naming
180
244
  ```
181
245
 
182
- ### `beslogic/storybook`
246
+ ### `storybook.mjs`
183
247
 
184
248
  Includes strict Storybook ESLint plugin and a custom rule for Angular components. This preset should be added last.\
185
249
  If you're using different ESLint configs for your Angular and Storybook projects, you should add this preset to both.
@@ -194,11 +258,11 @@ npm install --save-dev eslint-plugin-storybook
194
258
 
195
259
  If used, these presets should always come last, in this specific order.
196
260
 
197
- ### `beslogic/extra-strict`
261
+ ### `extra-strict.mjs`
198
262
 
199
- Enables extra-strict rules for `beslogic/typescript` and `beslogic/angular`, and forces that your `tsconfig.json` is strictly configured.
263
+ Enables extra-strict rules for `typescript.mjs` and `angular.mjs`, and forces that your `tsconfig.json` is strictly configured.
200
264
 
201
- ### `beslogic/stylistic`
265
+ ### `stylistic.mjs`
202
266
 
203
267
  Enables stylistic rules that would be taken care of by [dprint](https://dprint.dev/plugins/typescript/). Please read [What About Formatting?](https://typescript-eslint.io/users/what-about-formatting/)
204
268
 
@@ -206,7 +270,7 @@ We don't recommend using this preset, and to use dprint instead (see [Parallel c
206
270
 
207
271
  But if for some reason, `dprint` isn't an option for you, this preset follows our standards using ESLint.
208
272
 
209
- ### `beslogic/json-like`
273
+ ### `json-like.mjs`
210
274
 
211
275
  Enforces stylistic rules for JS objects to look like valid JSON objects.
212
276
 
@@ -220,6 +284,6 @@ You can view the changelog under the [Code Tab](https://www.npmjs.com/package/es
220
284
  To test updates to ESLint-Config-Beslogic in other existing projects:
221
285
  1. At the root of this repo, run `npm i` then `npm run yalc`
222
286
  2. In the target project, run `npm i --save-dev yalc` then `yalc add eslint-config-beslogic`
223
- 3. Update the project's .eslintrc config file as needed
287
+ 3. Update the project's eslintrc.config.mjs config file as needed
224
288
  4. Run your linting
225
289
  -->
@@ -28,7 +28,6 @@
28
28
  "sonarjs/encryption-secure-mode": "error",
29
29
  "sonarjs/file-permissions": "error",
30
30
  "sonarjs/file-uploads": "error",
31
- "sonarjs/fixme-tag": "error",
32
31
  "sonarjs/for-loop-increment-sign": "error",
33
32
  "sonarjs/frame-ancestors": "error",
34
33
  "sonarjs/function-inside-loop": "error",
package/angular.mjs ADDED
@@ -0,0 +1,358 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright 2024 Beslogic Inc.
3
+
4
+ import angular from "angular-eslint"
5
+ import angularFileNaming from "eslint-plugin-angular-file-naming"
6
+ import rxjsAngular from "eslint-plugin-rxjs-angular"
7
+ import testingLibrary from "eslint-plugin-testing-library"
8
+ import tseslint from "typescript-eslint"
9
+
10
+ import { noAutofixRreferArrowFunctionsConfig, noRestrictedSyntax as noRestrictedSyntaxJS, preferArrowFunctionsConfig, preventAbbreviationsConfig as preventAbbreviationsConfigJS } from "./javascript.mjs"
11
+ import { getModuleVersion, jestFilePatterns, jestNoRestrictedSyntax } from "./lib/utils.mjs"
12
+ import beslogicNodeJS from "./node-js.mjs"
13
+ import beslogicRXJS from "./rxjs.mjs"
14
+ import beslogicTypeScript from "./typescript.mjs"
15
+
16
+ const typescriptVersion = getModuleVersion("typescript", 4.7)
17
+ const eslintVersion = getModuleVersion("eslint", 8.56)
18
+
19
+ const typeDefinitionOverride = beslogicTypeScript.find(
20
+ config => config.files?.includes("**/*.d.ts")
21
+ )
22
+
23
+ export const noRestrictedSyntax = [
24
+ ...noRestrictedSyntaxJS,
25
+ // TODO: Asked to be its own rule: https://github.com/angular-eslint/angular-eslint/issues/1002
26
+ {
27
+ "selector":
28
+ "ClassDeclaration:has(Decorator :matches([name=\"Component\"], [name=\"Injectable\"], [name=\"Directive\"], [name=\"Pipe\"])) :matches(PropertyDefinition[key.name=\"intercept\"], PropertyDefinition[key.name=\"ngOnChanges\"], PropertyDefinition[key.name=\"ngOnInit\"], PropertyDefinition[key.name=\"ngDoCheck\"], PropertyDefinition[key.name=\"ngAfterContentInit\"], PropertyDefinition[key.name=\"ngAfterContentChecked\"], PropertyDefinition[key.name=\"ngAfterViewInit\"], PropertyDefinition[key.name=\"ngAfterViewChecked\"], PropertyDefinition[key.name=\"ngOnDestroy\"])",
29
+ "message":
30
+ "Angular hooks need to be functions defined on the prototype: https://github.com/angular/angular/issues/7270#issuecomment-201137617"
31
+ },
32
+ // TODO: Possibly implement that ourselves?
33
+ // Upstream request: https://github.com/MelvinVermeer/eslint-plugin-no-relative-import-paths/issues/30
34
+ {
35
+ "selector": "ImportDeclaration[source.value=/\\.\\.\\u002F?$/]",
36
+ "message": "Don't use imports that ends in \"..\" or \"../\""
37
+ },
38
+ // From typescript configs, but allow on @Input()
39
+ {
40
+ "selector":
41
+ "PropertyDefinition[definite=true]:not(:has(Decorator[expression.callee.name=\"Input\"] Property[key.name=\"required\"][value.value=true]))",
42
+ "message":
43
+ "Forbidden non-null property assertion. https://typescript-eslint.io/rules/no-non-null-assertion . "
44
+ + "This is only allowed on required component @Input({ required:true }). https://angular.io/api/core/Input#required"
45
+ },
46
+ {
47
+ "selector":
48
+ "MethodDefinition[key.name=\"constructor\"]:has(TSParameterProperty:has(Decorator[expression.callee.name=\"Optional\"]):not(:has(Identifier[optional=true])))",
49
+ "message":
50
+ "Constructor parameter with @Optional decorator should be marked as optional using `?`."
51
+ },
52
+ {
53
+ "selector":
54
+ "ClassDeclaration:has(Decorator :matches([name=\"Component\"], [name=\"Injectable\"], [name=\"Directive\"], [name=\"Pipe\"])) MethodDefinition[key.name=\"constructor\"]:has(TSParameterProperty:has(Identifier[optional=true]):not(:has(Decorator[expression.callee.name=\"Optional\"])))",
55
+ "message": "Optional constructor parameter should have @Optional decorator."
56
+ }
57
+ ]
58
+
59
+ const preventAbbreviationsConfig = { ...preventAbbreviationsConfigJS }
60
+
61
+ // Supported Refs
62
+ preventAbbreviationsConfig.allowList.Ref = true
63
+ // ag-grid ColumnDef
64
+ preventAbbreviationsConfig.allowList.Def = true
65
+ preventAbbreviationsConfig.allowList.def = true
66
+
67
+ const end2endPreventAbbreviationsConfig = { ...preventAbbreviationsConfig }
68
+ end2endPreventAbbreviationsConfig.allowList.e = true
69
+
70
+ export default tseslint.config(
71
+ beslogicRXJS,
72
+ beslogicTypeScript,
73
+ // For some reasons I'm unable to configure the parser.
74
+ // The doc doesn't even mention needing to configure it, could be a v9 only support.
75
+ eslintVersion >= 9
76
+ ? {
77
+ "files": ["**/*.html"],
78
+ "extends": [...angular.configs.templateAll],
79
+ "rules": {
80
+ "@angular-eslint/template/click-events-have-key-events": "off",
81
+ "@angular-eslint/template/conditional-complexity": [
82
+ "error",
83
+ // Same as ESLint sonarjs/cognitive-complexity
84
+ { "maxComplexity": 20 }
85
+ ],
86
+ "@angular-eslint/template/cyclomatic-complexity": [
87
+ "error",
88
+ // Same as ESLint complexity
89
+ { "maxComplexity": 20 }
90
+ ],
91
+ "@angular-eslint/template/eqeqeq": [
92
+ "error",
93
+ { "allowNullOrUndefined": true }
94
+ ],
95
+ "@angular-eslint/template/no-inline-styles": [
96
+ "error",
97
+ {
98
+ "allowNgStyle": true,
99
+ "allowBindToStyle": true
100
+ }
101
+ ],
102
+ "@angular-eslint/template/attributes-order": "error",
103
+ // Don't autofix as these should be handled manually, also configured in extra-strict preset
104
+ "@angular-eslint/template/i18n": "off",
105
+ // This constantly requires wrapping images in an additional div or knowing the exact display size.
106
+ // Doesn't support relative sizing either, not sure if worth even trying to enforce.
107
+ "@angular-eslint/template/prefer-ngsrc": "off",
108
+ // TODO: Investigate the value of this rule.
109
+ // It is new to me as well and I want to ensure I can isolate and understand breaking changes.
110
+ // Maybe with NG17's new control flow syntax that eliminates the need for track-by directive?
111
+ "@angular-eslint/template/use-track-by-function": "off"
112
+ }
113
+ }
114
+ : {},
115
+ {
116
+ "files": ["**/*.ts"],
117
+ "extends": [...angular.configs.tsAll],
118
+ "processor": angular.processInlineTemplates,
119
+ "plugins": {
120
+ "rxjs-angular": rxjsAngular,
121
+ "angular-file-naming": angularFileNaming
122
+ },
123
+ "languageOptions": {
124
+ "parserOptions": {
125
+ "project": [
126
+ "tsconfig?(.*).json",
127
+ "**/tsconfig?(.*).json" // For example: e2e/tsconfig.json
128
+ ],
129
+ // Needed specifically for @typescript-eslint/consistent-type-imports
130
+ // https://typescript-eslint.io/rules/consistent-type-imports/#caveat-decorators--experimentaldecorators-true--emitdecoratormetadata-true
131
+ "emitDecoratorMetadata": typescriptVersion >= 5
132
+ }
133
+ },
134
+ "rules": {
135
+ /*
136
+ * angular-file-naming rules (https://github.com/takuya-nakayasu/eslint-plugin-angular-file-naming#rules)
137
+ */
138
+ "angular-file-naming/component-filename-suffix": "error",
139
+ "angular-file-naming/directive-filename-suffix": "error",
140
+ "angular-file-naming/module-filename-suffix": "error",
141
+ "angular-file-naming/pipe-filename-suffix": "error",
142
+ "angular-file-naming/service-filename-suffix": [
143
+ "error",
144
+ {
145
+ "suffixes": [
146
+ "service",
147
+ "data-service",
148
+ "interceptor",
149
+ "guard"
150
+ ]
151
+ }
152
+ ],
153
+
154
+ /*
155
+ * rxjs-angular rules
156
+ */
157
+ "rxjs/no-finnish": "error",
158
+ "rxjs-angular/prefer-async-pipe": "off",
159
+ "rxjs-angular/prefer-composition": [
160
+ "error",
161
+ {
162
+ "superClass": [
163
+ "BaseComponent",
164
+ "BaseDirective"
165
+ ]
166
+ }
167
+ ],
168
+ "rxjs-angular/prefer-takeuntil": [
169
+ "error",
170
+ {
171
+ "checkComplete": true,
172
+ "superClass": [
173
+ "BaseComponent",
174
+ "BaseDirective"
175
+ ]
176
+ }
177
+ ],
178
+
179
+ /*
180
+ * Angular-eslint overrides (https://github.com/angular-eslint/angular-eslint/tree/master/packages/eslint-plugin/docs/rules)
181
+ */
182
+ "@angular-eslint/component-class-suffix": [
183
+ "error",
184
+ {
185
+ "suffixes": [
186
+ "Component",
187
+ "Dialog"
188
+ ]
189
+ }
190
+ ],
191
+ "@angular-eslint/component-selector": [
192
+ "error",
193
+ {
194
+ "type": "element",
195
+ "style": "kebab-case"
196
+ }
197
+ ],
198
+ "@angular-eslint/directive-selector": [
199
+ "error",
200
+ {
201
+ "type": "attribute",
202
+ "style": "camelCase"
203
+ }
204
+ ],
205
+ "@angular-eslint/prefer-on-push-component-change-detection": "off",
206
+ // We need to disable the autofix because some of the "new" standalone components
207
+ // would still be declared in their module. This breaks Angular and requires manual changes.
208
+ "@angular-eslint/prefer-standalone-component": "off",
209
+ // IDEM but updated rule that now works on more than components
210
+ "@angular-eslint/prefer-standalone": "off",
211
+ // Prefer Standalone still requires a bit of convincing,
212
+ // maybe with NG17's new control flow syntax that reduces imports in standalone components?
213
+ // And not until this rule also applies to Pipes and Directives
214
+ // https://github.com/angular-eslint/angular-eslint/pull/1627#pullrequestreview-1807581472
215
+ "no-autofix/@angular-eslint/prefer-standalone-component": "off",
216
+ // IDEM but updated rule that now works on more than components
217
+ "no-autofix/@angular-eslint/prefer-standalone": "off",
218
+
219
+ /*
220
+ * Custom rules and @typescript-eslint/all overrides (https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/src/configs/all.ts)
221
+ */
222
+ "@typescript-eslint/consistent-type-definitions": [
223
+ "error",
224
+ "interface"
225
+ ],
226
+ // TODO: https://dev.azure.com/Beslogic/ESLint-Config-Beslogic/_workitems/edit/16268
227
+ "@typescript-eslint/member-ordering": "off",
228
+ // Angular directives can lead to empty classes
229
+ // Angular's withConfig pattern for @NgModule leads to only static method
230
+ // https://angular.io/api/platform-browser/animations/BrowserAnimationsModule#withconfig
231
+ "@typescript-eslint/no-extraneous-class": [
232
+ "error",
233
+ { "allowWithDecorator": true }
234
+ ],
235
+ // Incompatible with Angular's dependecy injection
236
+ "@typescript-eslint/no-invalid-this": "off",
237
+ // Redundant with Angular's dependecy injection
238
+ "@typescript-eslint/parameter-properties": "off",
239
+ "unicorn/no-keyword-prefix": [
240
+ "error",
241
+ {
242
+ // Allow class because of "classList"
243
+ "disallowedPrefixes": [
244
+ "for",
245
+ "of"
246
+ ]
247
+ }
248
+ ],
249
+ // Angular is ESM
250
+ "unicorn/prefer-module": "error",
251
+ // This is not supported in Angular's Vite builder https://github.com/angular/angular-cli/issues/26507
252
+ "unicorn/prefer-top-level-await": "off",
253
+ "unicorn/prevent-abbreviations": [
254
+ "error",
255
+ preventAbbreviationsConfig
256
+ ],
257
+ // In Angular, @Input decorated only-setters are valid
258
+ "accessor-pairs": [
259
+ "error",
260
+ { "enforceForClassMembers": false }
261
+ ],
262
+ "no-restricted-syntax": noRestrictedSyntax
263
+ }
264
+ },
265
+ {
266
+ "files": [
267
+ "**/*.js",
268
+ "**/*.[cm]js"
269
+ ],
270
+ "extends": [...beslogicNodeJS]
271
+ },
272
+ {
273
+ "files": ["**/polyfills.ts"],
274
+ "rules": {
275
+ "simple-import-sort/imports": "off"
276
+ }
277
+ },
278
+ {
279
+ "files": [
280
+ // See no-restricted-syntax
281
+ // TODO: See if it's possible to implement myself (library updates or eslint-rule-composer)
282
+ "**/*[.-]component.ts",
283
+ "**/*[.-]directive.ts",
284
+ "**/*[.-]interceptor.ts",
285
+ "**/*[.-]pipes.ts"
286
+ ],
287
+ "rules": {
288
+ // Angular hooks should be named functions
289
+ // https://github.com/bahmutov/eslint-rules/issues/54
290
+ // TODO: consider https://github.com/jonaskello/eslint-plugin-functional/blob/HEAD/docs/rules/prefer-tacit.md
291
+ "extra-rules/potential-point-free": "off",
292
+ "no-autofix/prefer-arrow/prefer-arrow-functions": [
293
+ "error",
294
+ {
295
+ ...noAutofixRreferArrowFunctionsConfig,
296
+ // https://github.com/TristonJ/eslint-plugin-prefer-arrow/issues/17
297
+ "classPropertiesAllowed": false
298
+ }
299
+ ],
300
+ "prefer-arrow/prefer-arrow-functions": [
301
+ "error",
302
+ {
303
+ ...preferArrowFunctionsConfig,
304
+ // https://github.com/TristonJ/eslint-plugin-prefer-arrow/issues/17
305
+ "classPropertiesAllowed": false
306
+ }
307
+ ]
308
+ }
309
+ },
310
+ {
311
+ "files": jestFilePatterns,
312
+ "extends": [testingLibrary.configs["flat/angular"]],
313
+ "rules": {
314
+ "no-restricted-syntax": jestNoRestrictedSyntax(noRestrictedSyntax)
315
+ }
316
+ },
317
+ {
318
+ "files": [
319
+ "**/*.e2e-spec.ts",
320
+ "**/*.d.ts"
321
+ ],
322
+ "rules": {
323
+ "unicorn/prevent-abbreviations": [
324
+ // Can't configure e in e2e
325
+ "off",
326
+ end2endPreventAbbreviationsConfig
327
+ ]
328
+ }
329
+ },
330
+ {
331
+ // Exceptions for Storybook
332
+ "files": [
333
+ "**/*.stories.ts",
334
+ "**/*.story.ts"
335
+ ],
336
+ "rules": {
337
+ // Stories are allowed to use inline-templates to stay single-file.
338
+ "@angular-eslint/component-max-inline-declarations": "off",
339
+ // Stories don't need to add `.component`, that's redundant.
340
+ "angular-file-naming/component-filename-suffix": "off"
341
+ }
342
+ },
343
+ {
344
+ "files": [
345
+ "**/*.[jt]s",
346
+ "**/*.html"
347
+ ],
348
+ "rules": {
349
+ "unicorn/filename-case": [
350
+ "error",
351
+ {
352
+ "case": "kebabCase"
353
+ }
354
+ ]
355
+ }
356
+ },
357
+ typeDefinitionOverride
358
+ )