@rushstack/eslint-config 4.2.0 → 4.4.0

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/CHANGELOG.json CHANGED
@@ -1,6 +1,58 @@
1
1
  {
2
2
  "name": "@rushstack/eslint-config",
3
3
  "entries": [
4
+ {
5
+ "version": "4.4.0",
6
+ "tag": "@rushstack/eslint-config_v4.4.0",
7
+ "date": "Thu, 26 Jun 2025 18:57:04 GMT",
8
+ "comments": {
9
+ "minor": [
10
+ {
11
+ "comment": "Add flat config compatible versions of profiles and mixins. These are located under the `/flat/*` path."
12
+ }
13
+ ],
14
+ "dependency": [
15
+ {
16
+ "comment": "Updating dependency \"@rushstack/eslint-patch\" to `1.12.0`"
17
+ },
18
+ {
19
+ "comment": "Updating dependency \"@rushstack/eslint-plugin\" to `0.19.0`"
20
+ },
21
+ {
22
+ "comment": "Updating dependency \"@rushstack/eslint-plugin-packlets\" to `0.12.0`"
23
+ },
24
+ {
25
+ "comment": "Updating dependency \"@rushstack/eslint-plugin-security\" to `0.11.0`"
26
+ }
27
+ ]
28
+ }
29
+ },
30
+ {
31
+ "version": "4.3.0",
32
+ "tag": "@rushstack/eslint-config_v4.3.0",
33
+ "date": "Tue, 11 Mar 2025 02:12:33 GMT",
34
+ "comments": {
35
+ "minor": [
36
+ {
37
+ "comment": "Bump the `@typescript-eslint/*` packages to add support for TypeScript 5.8."
38
+ }
39
+ ],
40
+ "dependency": [
41
+ {
42
+ "comment": "Updating dependency \"@rushstack/eslint-patch\" to `1.11.0`"
43
+ },
44
+ {
45
+ "comment": "Updating dependency \"@rushstack/eslint-plugin\" to `0.18.0`"
46
+ },
47
+ {
48
+ "comment": "Updating dependency \"@rushstack/eslint-plugin-packlets\" to `0.11.0`"
49
+ },
50
+ {
51
+ "comment": "Updating dependency \"@rushstack/eslint-plugin-security\" to `0.10.0`"
52
+ }
53
+ ]
54
+ }
55
+ },
4
56
  {
5
57
  "version": "4.2.0",
6
58
  "tag": "@rushstack/eslint-config_v4.2.0",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Change Log - @rushstack/eslint-config
2
2
 
3
- This log was last generated on Sat, 01 Mar 2025 07:23:16 GMT and should not be manually modified.
3
+ This log was last generated on Thu, 26 Jun 2025 18:57:04 GMT and should not be manually modified.
4
+
5
+ ## 4.4.0
6
+ Thu, 26 Jun 2025 18:57:04 GMT
7
+
8
+ ### Minor changes
9
+
10
+ - Add flat config compatible versions of profiles and mixins. These are located under the `/flat/*` path.
11
+
12
+ ## 4.3.0
13
+ Tue, 11 Mar 2025 02:12:33 GMT
14
+
15
+ ### Minor changes
16
+
17
+ - Bump the `@typescript-eslint/*` packages to add support for TypeScript 5.8.
4
18
 
5
19
  ## 4.2.0
6
20
  Sat, 01 Mar 2025 07:23:16 GMT
@@ -0,0 +1,90 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ // For the first 5 years of Rush, our lint rules required explicit types for most declarations
5
+ // such as function parameters, function return values, and exported variables. Although more verbose,
6
+ // declaring types (instead of relying on type inference) encourages engineers to create interfaces
7
+ // that inspire discussions about data structure design. It also makes source files easier
8
+ // to understand for code reviewers who may be unfamiliar with a particular project. Once developers get
9
+ // used to the extra work of declaring types, it turns out to be a surprisingly popular practice.
10
+ //
11
+ // However in 2020, to make adoption easier for existing projects, this rule was relaxed. Explicit
12
+ // type declarations are now optional for local variables (although still required in other contexts).
13
+ // See this GitHub issue for background:
14
+ //
15
+ // https://github.com/microsoft/rushstack/issues/2206
16
+ //
17
+ // If you are onboarding a large existing code base, this new default will make adoption easier.
18
+ //
19
+ // On the other hand, if your top priority is to make source files more friendly for other
20
+ // people to read, enable the "@rushstack/eslint-config/mixins/friendly-locals" mixin.
21
+ // It will restore the requirement that local variables should have explicit type declarations.
22
+ //
23
+ // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile
24
+
25
+ const typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin');
26
+
27
+ module.exports = [
28
+ {
29
+ files: ['**/*.ts', '**/*.tsx'],
30
+ plugins: {
31
+ '@typescript-eslint': typescriptEslintPlugin
32
+ },
33
+ rules: {
34
+ '@rushstack/typedef-var': 'off', // <--- disabled by the mixin
35
+
36
+ '@typescript-eslint/typedef': [
37
+ 'warn',
38
+ {
39
+ arrayDestructuring: false,
40
+ arrowParameter: false,
41
+ memberVariableDeclaration: true,
42
+ objectDestructuring: false,
43
+ parameter: true,
44
+ propertyDeclaration: true,
45
+
46
+ variableDeclaration: true, // <--- reenabled by the mixin
47
+
48
+ variableDeclarationIgnoreFunction: true
49
+ }
50
+ ]
51
+ }
52
+ },
53
+ {
54
+ files: [
55
+ // Test files
56
+ '**/*.test.ts',
57
+ '**/*.test.tsx',
58
+ '**/*.spec.ts',
59
+ '**/*.spec.tsx',
60
+
61
+ // Facebook convention
62
+ '**/__mocks__/**/*.ts',
63
+ '**/__mocks__/**/*.tsx',
64
+ '**/__tests__/**/*.ts',
65
+ '**/__tests__/**/*.tsx',
66
+
67
+ // Microsoft convention
68
+ '**/test/**/*.ts',
69
+ '**/test/**/*.tsx'
70
+ ],
71
+ plugins: {
72
+ '@typescript-eslint': typescriptEslintPlugin
73
+ },
74
+ rules: {
75
+ '@typescript-eslint/typedef': [
76
+ 'warn',
77
+ {
78
+ arrayDestructuring: false,
79
+ arrowParameter: false,
80
+ memberVariableDeclaration: true,
81
+ objectDestructuring: false,
82
+ parameter: true,
83
+ propertyDeclaration: true,
84
+ variableDeclaration: false, // <--- special case for test files
85
+ variableDeclarationIgnoreFunction: true
86
+ }
87
+ ]
88
+ }
89
+ }
90
+ ];
@@ -0,0 +1,21 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ // This mixin implements the "packlet" formalism for organizing source files.
5
+ // For more information, see the documentation here:
6
+ // https://www.npmjs.com/package/@rushstack/eslint-plugin-packlets
7
+ //
8
+ // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile
9
+
10
+ const rushstackPackletsEslintPlugin = require('@rushstack/eslint-plugin-packlets');
11
+
12
+ module.exports = {
13
+ files: ['**/*.ts', '**/*.tsx'],
14
+ plugins: {
15
+ '@rushstack/packlets': rushstackPackletsEslintPlugin
16
+ },
17
+ rules: {
18
+ '@rushstack/packlets/mechanics': 'warn',
19
+ '@rushstack/packlets/circular-deps': 'warn'
20
+ }
21
+ };
@@ -0,0 +1,77 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ // This mixin applies some additional checks for projects using the React library. For more information,
5
+ // please see the README.md for "@rushstack/eslint-config".
6
+ //
7
+ // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile
8
+
9
+ const reactEslintPlugin = require('eslint-plugin-react');
10
+
11
+ module.exports = [
12
+ {
13
+ files: ['**/*.ts', '**/*.tsx'],
14
+ plugins: {
15
+ react: reactEslintPlugin
16
+ },
17
+ settings: {
18
+ react: {
19
+ // The default value is "detect". Automatic detection works by loading the entire React library
20
+ // into the linter's process, which is inefficient. It is recommended to specify the version
21
+ // explicity. For details, see README.md for "@rushstack/eslint-config".
22
+ version: 'detect'
23
+ }
24
+ },
25
+ rules: {
26
+ // RATIONALE: When React components are added to an array, they generally need a "key".
27
+ 'react/jsx-key': 'warn',
28
+
29
+ // RATIONALE: Catches a common coding practice that significantly impacts performance.
30
+ 'react/jsx-no-bind': 'warn',
31
+
32
+ // RATIONALE: Catches a common coding mistake.
33
+ 'react/jsx-no-comment-textnodes': 'warn',
34
+
35
+ // RATIONALE: Security risk.
36
+ 'react/jsx-no-target-blank': 'warn',
37
+
38
+ // RATIONALE: Fixes the no-unused-vars rule to make it compatible with React
39
+ 'react/jsx-uses-react': 'warn',
40
+
41
+ // RATIONALE: Fixes the no-unused-vars rule to make it compatible with React
42
+ 'react/jsx-uses-vars': 'warn',
43
+
44
+ // RATIONALE: Catches a common coding mistake.
45
+ 'react/no-children-prop': 'warn',
46
+
47
+ // RATIONALE: Catches a common coding mistake.
48
+ 'react/no-danger-with-children': 'warn',
49
+
50
+ // RATIONALE: Avoids usage of deprecated APIs.
51
+ //
52
+ // Note that the set of deprecated APIs is determined by the "react.version" setting.
53
+ 'react/no-deprecated': 'warn',
54
+
55
+ // RATIONALE: Catches a common coding mistake.
56
+ 'react/no-direct-mutation-state': 'warn',
57
+
58
+ // RATIONALE: Catches some common coding mistakes.
59
+ 'react/no-unescaped-entities': 'warn',
60
+
61
+ // RATIONALE: Avoids a potential performance problem.
62
+ 'react/no-find-dom-node': 'warn',
63
+
64
+ // RATIONALE: Deprecated API.
65
+ 'react/no-is-mounted': 'warn',
66
+
67
+ // RATIONALE: Deprecated API.
68
+ 'react/no-render-return-value': 'warn',
69
+
70
+ // RATIONALE: Deprecated API.
71
+ 'react/no-string-refs': 'warn',
72
+
73
+ // RATIONALE: Improves syntax for some cases that are not already handled by Prettier.
74
+ 'react/self-closing-comp': 'warn'
75
+ }
76
+ }
77
+ ];
@@ -0,0 +1,21 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ // This mixin validates code comments to ensure that they follow the TSDoc standard. For more
5
+ // information please see the README.md for @rushstack/eslint-config.
6
+ //
7
+ // IMPORTANT: Mixins must be included in your ESLint configuration AFTER the profile
8
+
9
+ const tsdocEslintPlugin = require('eslint-plugin-tsdoc');
10
+
11
+ module.exports = [
12
+ {
13
+ files: ['**/*.ts', '**/*.tsx'],
14
+ plugins: {
15
+ tsdoc: tsdocEslintPlugin
16
+ },
17
+ rules: {
18
+ 'tsdoc/syntax': 'warn'
19
+ }
20
+ }
21
+ ];
@@ -0,0 +1,4 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ require('@rushstack/eslint-patch/eslint-bulk-suppressions');
@@ -0,0 +1,777 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ // Rule severity guidelines
5
+ // ------------------------
6
+ //
7
+ // Errors are generally printed in red, and may prevent other build tasks from running (e.g. unit tests).
8
+ // Developers should never ignore errors. Warnings are generally printed in yellow, and do not block local
9
+ // development, although they must be fixed/suppressed before merging. Developers will commonly ignore warnings
10
+ // until their feature is working.
11
+ //
12
+ // Rules that should be a WARNING:
13
+ // - An issue that is very common in partially implemented work (e.g. missing type declaration)
14
+ // - An issue that "keeps things nice" but otherwise doesn't affect the meaning of the code (e.g. naming convention)
15
+ // - Security rules -- developers may need to temporarily introduce "insecure" expressions while debugging;
16
+ // if our policy forces them to suppress the lint rule, they may forget to reenable it later.
17
+ //
18
+ // Rules that should be an ERROR:
19
+ // - An issue that is very likely to be a typo (e.g. "x = x;")
20
+ // - An issue that catches code that is likely to malfunction (e.g. unterminated promise chain)
21
+ // - An obsolete language feature that nobody should be using for any good reason
22
+
23
+ const { globalIgnores } = require('eslint/config');
24
+ const promiseEslintPlugin = require('eslint-plugin-promise');
25
+ const typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin');
26
+ const typescriptEslintParser = require('@typescript-eslint/parser');
27
+ const rushstackEslintPlugin = require('@rushstack/eslint-plugin');
28
+ const rushstackSecurityEslintPlugin = require('@rushstack/eslint-plugin-security');
29
+ const { expandNamingConventionSelectors } = require('./_macros');
30
+
31
+ const commonNamingConventionSelectors = [
32
+ {
33
+ // We should be stricter about 'enumMember', but it often functions legitimately as an ad hoc namespace.
34
+ selectors: ['variable', 'enumMember', 'function'],
35
+
36
+ format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
37
+ leadingUnderscore: 'allow',
38
+
39
+ filter: {
40
+ regex: [
41
+ // This is a special exception for naming patterns that use an underscore to separate two camel-cased
42
+ // parts. Example: "checkBox1_onChanged" or "_checkBox1_onChanged"
43
+ '^_?[a-z][a-z0-9]*([A-Z][a-z]?[a-z0-9]*)*_[a-z][a-z0-9]*([A-Z][a-z]?[a-z0-9]*)*$'
44
+ ]
45
+ .map((x) => `(${x})`)
46
+ .join('|'),
47
+ match: false
48
+ }
49
+ },
50
+
51
+ {
52
+ selectors: ['parameter'],
53
+
54
+ format: ['camelCase'],
55
+
56
+ filter: {
57
+ regex: [
58
+ // Silently accept names with a double-underscore prefix; we would like to be more strict about this,
59
+ // pending a fix for https://github.com/typescript-eslint/typescript-eslint/issues/2240
60
+ '^__'
61
+ ]
62
+ .map((x) => `(${x})`)
63
+ .join('|'),
64
+ match: false
65
+ }
66
+ },
67
+
68
+ // Genuine properties
69
+ {
70
+ selectors: ['parameterProperty', 'accessor'],
71
+ enforceLeadingUnderscoreWhenPrivate: true,
72
+
73
+ format: ['camelCase', 'UPPER_CASE'],
74
+
75
+ filter: {
76
+ regex: [
77
+ // Silently accept names with a double-underscore prefix; we would like to be more strict about this,
78
+ // pending a fix for https://github.com/typescript-eslint/typescript-eslint/issues/2240
79
+ '^__',
80
+ // Ignore quoted identifiers such as { "X+Y": 123 }. Currently @typescript-eslint/naming-convention
81
+ // cannot detect whether an identifier is quoted or not, so we simply assume that it is quoted
82
+ // if-and-only-if it contains characters that require quoting.
83
+ '[^a-zA-Z0-9_]',
84
+ // This is a special exception for naming patterns that use an underscore to separate two camel-cased
85
+ // parts. Example: "checkBox1_onChanged" or "_checkBox1_onChanged"
86
+ '^_?[a-z][a-z0-9]*([A-Z][a-z]?[a-z0-9]*)*_[a-z][a-z0-9]*([A-Z][a-z]?[a-z0-9]*)*$'
87
+ ]
88
+ .map((x) => `(${x})`)
89
+ .join('|'),
90
+ match: false
91
+ }
92
+ },
93
+
94
+ // Properties that incorrectly match other contexts
95
+ // See issue https://github.com/typescript-eslint/typescript-eslint/issues/2244
96
+ {
97
+ selectors: ['property'],
98
+ enforceLeadingUnderscoreWhenPrivate: true,
99
+
100
+ // The @typescript-eslint/naming-convention "property" selector matches cases like this:
101
+ //
102
+ // someLegacyApiWeCannotChange.invokeMethod({ SomeProperty: 123 });
103
+ //
104
+ // and this:
105
+ //
106
+ // const { CONSTANT1, CONSTANT2 } = someNamespace.constants;
107
+ //
108
+ // Thus for now "property" is more like a variable than a class member.
109
+ format: ['camelCase', 'UPPER_CASE', 'PascalCase'],
110
+ leadingUnderscore: 'allow',
111
+
112
+ filter: {
113
+ regex: [
114
+ // Silently accept names with a double-underscore prefix; we would like to be more strict about this,
115
+ // pending a fix for https://github.com/typescript-eslint/typescript-eslint/issues/2240
116
+ '^__',
117
+ // Ignore quoted identifiers such as { "X+Y": 123 }. Currently @typescript-eslint/naming-convention
118
+ // cannot detect whether an identifier is quoted or not, so we simply assume that it is quoted
119
+ // if-and-only-if it contains characters that require quoting.
120
+ '[^a-zA-Z0-9_]',
121
+ // This is a special exception for naming patterns that use an underscore to separate two camel-cased
122
+ // parts. Example: "checkBox1_onChanged" or "_checkBox1_onChanged"
123
+ '^_?[a-z][a-z0-9]*([A-Z][a-z]?[a-z0-9]*)*_[a-z][a-z0-9]*([A-Z][a-z]?[a-z0-9]*)*$'
124
+ ]
125
+ .map((x) => `(${x})`)
126
+ .join('|'),
127
+ match: false
128
+ }
129
+ },
130
+
131
+ {
132
+ selectors: ['method'],
133
+ enforceLeadingUnderscoreWhenPrivate: true,
134
+
135
+ // A PascalCase method can arise somewhat legitimately in this way:
136
+ //
137
+ // class MyClass {
138
+ // public static MyReactButton(props: IButtonProps): JSX.Element {
139
+ // . . .
140
+ // }
141
+ // }
142
+ format: ['camelCase', 'PascalCase'],
143
+ leadingUnderscore: 'allow',
144
+
145
+ filter: {
146
+ regex: [
147
+ // Silently accept names with a double-underscore prefix; we would like to be more strict about this,
148
+ // pending a fix for https://github.com/typescript-eslint/typescript-eslint/issues/2240
149
+ '^__',
150
+ // This is a special exception for naming patterns that use an underscore to separate two camel-cased
151
+ // parts. Example: "checkBox1_onChanged" or "_checkBox1_onChanged"
152
+ '^_?[a-z][a-z0-9]*([A-Z][a-z]?[a-z0-9]*)*_[a-z][a-z0-9]*([A-Z][a-z]?[a-z0-9]*)*$'
153
+ ]
154
+ .map((x) => `(${x})`)
155
+ .join('|'),
156
+ match: false
157
+ }
158
+ },
159
+
160
+ // Types should use PascalCase
161
+ {
162
+ // Group selector for: class, interface, typeAlias, enum, typeParameter
163
+ selectors: ['class', 'typeAlias', 'enum', 'typeParameter'],
164
+ format: ['PascalCase'],
165
+ leadingUnderscore: 'allow'
166
+ },
167
+
168
+ {
169
+ selectors: ['interface'],
170
+
171
+ // It is very common for a class to implement an interface of the same name.
172
+ // For example, the Widget class may implement the IWidget interface. The "I" prefix
173
+ // avoids the need to invent a separate name such as "AbstractWidget" or "WidgetInterface".
174
+ // In TypeScript it is also common to declare interfaces that are implemented by primitive
175
+ // objects, here the "I" prefix also helps by avoiding spurious conflicts with classes
176
+ // by the same name.
177
+ format: ['PascalCase'],
178
+
179
+ custom: {
180
+ regex: '^_?I[A-Z]',
181
+ match: true
182
+ }
183
+ }
184
+ ];
185
+
186
+ const commonConfig = [
187
+ // Manually authored .d.ts files are generally used to describe external APIs that are not expected
188
+ // to follow our coding conventions. Linting those files tends to produce a lot of spurious suppressions,
189
+ // so we simply ignore them.
190
+ globalIgnores(['**/*.d.ts']),
191
+
192
+ {
193
+ files: ['**/*.ts', '**/*.tsx'],
194
+ languageOptions: {
195
+ parser: typescriptEslintParser,
196
+ parserOptions: {
197
+ // The "project" path is resolved relative to parserOptions.tsconfigRootDir.
198
+ // Your local .eslintrc.js must specify that parserOptions.tsconfigRootDir=__dirname.
199
+ project: './tsconfig.json',
200
+
201
+ // Allow parsing of newer ECMAScript constructs used in TypeScript source code. Although tsconfig.json
202
+ // may allow only a small subset of ES2018 features, this liberal setting ensures that ESLint will correctly
203
+ // parse whatever is encountered.
204
+ ecmaVersion: 2018,
205
+
206
+ sourceType: 'module'
207
+ }
208
+ },
209
+ plugins: {
210
+ '@rushstack': rushstackEslintPlugin,
211
+ '@rushstack/security': rushstackSecurityEslintPlugin,
212
+ '@typescript-eslint': typescriptEslintPlugin,
213
+ promise: promiseEslintPlugin
214
+ },
215
+ rules: {
216
+ // ====================================================================
217
+ // CUSTOM RULES
218
+ // ====================================================================
219
+
220
+ // RATIONALE: See the @rushstack/eslint-plugin documentation
221
+ '@rushstack/no-new-null': 'warn',
222
+
223
+ // RATIONALE: See the @rushstack/eslint-plugin documentation
224
+ '@rushstack/typedef-var': 'warn',
225
+
226
+ // RATIONALE: See the @rushstack/eslint-plugin documentation
227
+ // This is enabled and classified as an error because it is required when using Heft.
228
+ // It's not required when using ts-jest, but still a good practice.
229
+ '@rushstack/hoist-jest-mock': 'error',
230
+
231
+ // ====================================================================
232
+ // SECURITY RULES
233
+ // ====================================================================
234
+
235
+ // RATIONALE: This rule is used to prevent the use of insecure regular expressions, which can lead to
236
+ // security vulnerabilities such as ReDoS (Regular Expression Denial of Service).
237
+ '@rushstack/security/no-unsafe-regexp': 'warn',
238
+
239
+ // ====================================================================
240
+ // TYPESCRIPT RULES
241
+ // ====================================================================
242
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
243
+ '@typescript-eslint/adjacent-overload-signatures': 'warn',
244
+
245
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
246
+ '@typescript-eslint/no-unsafe-function-type': 'warn',
247
+
248
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
249
+ '@typescript-eslint/no-wrapper-object-types': 'warn',
250
+
251
+ // RATIONALE: We require "x as number" instead of "<number>x" to avoid conflicts with JSX.
252
+ '@typescript-eslint/consistent-type-assertions': 'warn',
253
+
254
+ // RATIONALE: We prefer "interface IBlah { x: number }" over "type Blah = { x: number }"
255
+ // because code is more readable when it is built from stereotypical forms
256
+ // (interfaces, enums, functions, etc.) instead of freeform type algebra.
257
+ '@typescript-eslint/consistent-type-definitions': 'warn',
258
+
259
+ // RATIONALE: Code is more readable when the type of every variable is immediately obvious.
260
+ // Even if the compiler may be able to infer a type, this inference will be unavailable
261
+ // to a person who is reviewing a GitHub diff. This rule makes writing code harder,
262
+ // but writing code is a much less important activity than reading it.
263
+ //
264
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
265
+ '@typescript-eslint/explicit-function-return-type': [
266
+ 'warn',
267
+ {
268
+ allowExpressions: true,
269
+ allowTypedFunctionExpressions: true,
270
+ allowHigherOrderFunctions: false
271
+ }
272
+ ],
273
+
274
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
275
+ '@typescript-eslint/explicit-member-accessibility': 'warn',
276
+
277
+ // RATIONALE: Object-oriented programming organizes code into "classes" that associate
278
+ // data structures (the class's fields) and the operations performed on those
279
+ // data structures (the class's members). Studying the fields often reveals the "idea"
280
+ // behind a class. The choice of which class a field belongs to may greatly impact
281
+ // the code readability and complexity. Thus, we group the fields prominently at the top
282
+ // of the class declaration. We do NOT enforce sorting based on public/protected/private
283
+ // or static/instance, because these designations tend to change as code evolves, and
284
+ // reordering methods produces spurious diffs that make PRs hard to read. For classes
285
+ // with lots of methods, alphabetization is probably a more useful secondary ordering.
286
+ '@typescript-eslint/member-ordering': [
287
+ 'warn',
288
+ {
289
+ default: 'never',
290
+ classes: ['field', 'constructor', 'method']
291
+ }
292
+ ],
293
+
294
+ // NOTE: This new rule replaces several deprecated rules from @typescript-eslint/eslint-plugin@2.3.3:
295
+ //
296
+ // - @typescript-eslint/camelcase
297
+ // - @typescript-eslint/class-name-casing
298
+ // - @typescript-eslint/interface-name-prefix
299
+ // - @typescript-eslint/member-naming
300
+ //
301
+ // Docs: https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/naming-convention.md
302
+ '@typescript-eslint/naming-convention': [
303
+ 'warn',
304
+ ...expandNamingConventionSelectors(commonNamingConventionSelectors)
305
+ ],
306
+
307
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
308
+ '@typescript-eslint/no-array-constructor': 'warn',
309
+
310
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
311
+ //
312
+ // RATIONALE: The "any" keyword disables static type checking, the main benefit of using TypeScript.
313
+ // This rule should be suppressed only in very special cases such as JSON.stringify()
314
+ // where the type really can be anything. Even if the type is flexible, another type
315
+ // may be more appropriate such as "unknown", "{}", or "Record<k,V>".
316
+ '@typescript-eslint/no-explicit-any': 'warn',
317
+
318
+ // RATIONALE: The #1 rule of promises is that every promise chain must be terminated by a catch()
319
+ // handler. Thus wherever a Promise arises, the code must either append a catch handler,
320
+ // or else return the object to a caller (who assumes this responsibility). Unterminated
321
+ // promise chains are a serious issue. Besides causing errors to be silently ignored,
322
+ // they can also cause a NodeJS process to terminate unexpectedly.
323
+ '@typescript-eslint/no-floating-promises': [
324
+ 'error',
325
+ {
326
+ checkThenables: true
327
+ }
328
+ ],
329
+
330
+ // RATIONALE: Catches a common coding mistake.
331
+ '@typescript-eslint/no-for-in-array': 'error',
332
+
333
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
334
+ '@typescript-eslint/no-misused-new': 'error',
335
+
336
+ // RATIONALE: The "namespace" keyword is not recommended for organizing code because JavaScript lacks
337
+ // a "using" statement to traverse namespaces. Nested namespaces prevent certain bundler
338
+ // optimizations. If you are declaring loose functions/variables, it's better to make them
339
+ // static members of a class, since classes support property getters and their private
340
+ // members are accessible by unit tests. Also, the exercise of choosing a meaningful
341
+ // class name tends to produce more discoverable APIs: for example, search+replacing
342
+ // the function "reverse()" is likely to return many false matches, whereas if we always
343
+ // write "Text.reverse()" is more unique. For large scale organization, it's recommended
344
+ // to decompose your code into separate NPM packages, which ensures that component
345
+ // dependencies are tracked more conscientiously.
346
+ //
347
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
348
+ '@typescript-eslint/no-namespace': [
349
+ 'warn',
350
+ {
351
+ // Discourage "namespace" in .ts and .tsx files
352
+ allowDeclarations: false,
353
+
354
+ // Allow it in .d.ts files that describe legacy libraries
355
+ allowDefinitionFiles: false
356
+ }
357
+ ],
358
+
359
+ // RATIONALE: Parameter properties provide a shorthand such as "constructor(public title: string)"
360
+ // that avoids the effort of declaring "title" as a field. This TypeScript feature makes
361
+ // code easier to write, but arguably sacrifices readability: In the notes for
362
+ // "@typescript-eslint/member-ordering" we pointed out that fields are central to
363
+ // a class's design, so we wouldn't want to bury them in a constructor signature
364
+ // just to save some typing.
365
+ //
366
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
367
+ '@typescript-eslint/parameter-properties': 'warn',
368
+
369
+ // RATIONALE: When left in shipping code, unused variables often indicate a mistake. Dead code
370
+ // may impact performance.
371
+ //
372
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
373
+ '@typescript-eslint/no-unused-vars': [
374
+ 'warn',
375
+ {
376
+ vars: 'all',
377
+ // Unused function arguments often indicate a mistake in JavaScript code. However in TypeScript code,
378
+ // the compiler catches most of those mistakes, and unused arguments are fairly common for type signatures
379
+ // that are overriding a base class method or implementing an interface.
380
+ args: 'none',
381
+ // Unused error arguments are common and useful for inspection when a debugger is attached.
382
+ caughtErrors: 'none'
383
+ }
384
+ ],
385
+
386
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
387
+ '@typescript-eslint/no-use-before-define': [
388
+ 'error',
389
+ {
390
+ // Base ESLint options
391
+
392
+ // We set functions=false so that functions can be ordered based on exported/local visibility
393
+ // similar to class methods. Also the base lint rule incorrectly flags a legitimate case like:
394
+ //
395
+ // function a(n: number): void {
396
+ // if (n > 0) {
397
+ // b(n-1); // lint error
398
+ // }
399
+ // }
400
+ // function b(n: number): void {
401
+ // if (n > 0) {
402
+ // a(n-1);
403
+ // }
404
+ // }
405
+ functions: false,
406
+ classes: true,
407
+ variables: true,
408
+
409
+ // TypeScript extensions
410
+
411
+ enums: true,
412
+ typedefs: true
413
+ // ignoreTypeReferences: true
414
+ }
415
+ ],
416
+
417
+ // TODO: This is a good rule for web browser apps, but it is commonly needed API for Node.js tools.
418
+ // '@typescript-eslint/no-var-requires': 'error',
419
+
420
+ // RATIONALE: The "module" keyword is deprecated except when describing legacy libraries.
421
+ //
422
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
423
+ '@typescript-eslint/prefer-namespace-keyword': 'warn',
424
+
425
+ // RATIONALE: We require explicit type annotations, even when the compiler could infer the type.
426
+ // This can be a controversial policy because it makes code more verbose. There are
427
+ // a couple downsides to type inference, however. First, it is not always available.
428
+ // For example, when reviewing a pull request or examining a Git history, we may see
429
+ // code like this:
430
+ //
431
+ // // What is the type of "y" here? The compiler knows, but the
432
+ // // person reading the code may have no clue.
433
+ // const x = f.();
434
+ // const y = x.z;
435
+ //
436
+ // Second, relying on implicit types also discourages design discussions and documentation.
437
+ // Consider this example:
438
+ //
439
+ // // Where's the documentation for "correlation" and "inventory"?
440
+ // // Where would you even write the TSDoc comments?
441
+ // function g() {
442
+ // return { correlation: 123, inventory: 'xyz' };
443
+ // }
444
+ //
445
+ // Implicit types make sense for small scale scenarios, where everyone is familiar with
446
+ // the project, and code should be "easy to write". Explicit types are preferable
447
+ // for large scale scenarios, where people regularly work with source files they've never
448
+ // seen before, and code should be "easy to read."
449
+ //
450
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
451
+ '@typescript-eslint/typedef': [
452
+ 'warn',
453
+ {
454
+ arrayDestructuring: false,
455
+ arrowParameter: false,
456
+ memberVariableDeclaration: true,
457
+ objectDestructuring: false,
458
+ parameter: true,
459
+ propertyDeclaration: true,
460
+
461
+ // This case is handled by our "@rushstack/typedef-var" rule
462
+ variableDeclaration: false,
463
+
464
+ // Normally we require type declarations for class members. However, that rule is relaxed
465
+ // for situations where we need to bind the "this" pointer for a callback. For example, consider
466
+ // this event handler for a React component:
467
+ //
468
+ // class MyComponent {
469
+ // public render(): React.ReactNode {
470
+ // return (
471
+ // <a href="#" onClick={this._onClick}> click me </a>
472
+ // );
473
+ // }
474
+ //
475
+ // // The assignment here avoids the need for "this._onClick.bind(this)"
476
+ // private _onClick = (event: React.MouseEvent<HTMLAnchorElement>): void => {
477
+ // console.log("Clicked! " + this.props.title);
478
+ // };
479
+ // }
480
+ //
481
+ // This coding style has limitations and should be used sparingly. For example, "_onClick"
482
+ // will not participate correctly in "virtual"/"override" inheritance.
483
+ //
484
+ // NOTE: This option affects both "memberVariableDeclaration" and "variableDeclaration" options.
485
+ variableDeclarationIgnoreFunction: true
486
+ }
487
+ ],
488
+
489
+ // ====================================================================
490
+ // RECOMMENDED RULES
491
+ // ====================================================================
492
+
493
+ // RATIONALE: This rule warns if setters are defined without getters, which is probably a mistake.
494
+ 'accessor-pairs': 'error',
495
+
496
+ // RATIONALE: In TypeScript, if you write x["y"] instead of x.y, it disables type checking.
497
+ 'dot-notation': [
498
+ 'warn',
499
+ {
500
+ allowPattern: '^_'
501
+ }
502
+ ],
503
+
504
+ // RATIONALE: Catches code that is likely to be incorrect
505
+ eqeqeq: 'error',
506
+
507
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
508
+ 'for-direction': 'warn',
509
+
510
+ // RATIONALE: Catches a common coding mistake.
511
+ 'guard-for-in': 'error',
512
+
513
+ // RATIONALE: If you have more than 2,000 lines in a single source file, it's probably time
514
+ // to split up your code.
515
+ 'max-lines': ['warn', { max: 2000 }],
516
+
517
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
518
+ 'no-async-promise-executor': 'error',
519
+
520
+ // RATIONALE: "|" and "&" are relatively rare, and are more likely to appear as a mistake when
521
+ // someone meant "||" or "&&". (But nobody types the other operators by mistake.)
522
+ 'no-bitwise': [
523
+ 'warn',
524
+ {
525
+ allow: [
526
+ '^',
527
+ // "|",
528
+ // "&",
529
+ '<<',
530
+ '>>',
531
+ '>>>',
532
+ '^=',
533
+ // "|=",
534
+ //"&=",
535
+ '<<=',
536
+ '>>=',
537
+ '>>>=',
538
+ '~'
539
+ ]
540
+ }
541
+ ],
542
+
543
+ // RATIONALE: Deprecated language feature.
544
+ 'no-caller': 'error',
545
+
546
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
547
+ 'no-compare-neg-zero': 'error',
548
+
549
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
550
+ 'no-cond-assign': 'error',
551
+
552
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
553
+ 'no-constant-condition': 'warn',
554
+
555
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
556
+ 'no-control-regex': 'error',
557
+
558
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
559
+ 'no-debugger': 'warn',
560
+
561
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
562
+ 'no-delete-var': 'error',
563
+
564
+ // RATIONALE: Catches code that is likely to be incorrect
565
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
566
+ 'no-duplicate-case': 'error',
567
+
568
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
569
+ 'no-empty': 'warn',
570
+
571
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
572
+ 'no-empty-character-class': 'error',
573
+
574
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
575
+ 'no-empty-pattern': 'warn',
576
+
577
+ // RATIONALE: Eval is a security concern and a performance concern.
578
+ 'no-eval': 'warn',
579
+
580
+ // RATIONALE: Catches code that is likely to be incorrect
581
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
582
+ 'no-ex-assign': 'error',
583
+
584
+ // RATIONALE: System types are global and should not be tampered with in a scalable code base.
585
+ // If two different libraries (or two versions of the same library) both try to modify
586
+ // a type, only one of them can win. Polyfills are acceptable because they implement
587
+ // a standardized interoperable contract, but polyfills are generally coded in plain
588
+ // JavaScript.
589
+ 'no-extend-native': 'error',
590
+
591
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
592
+ 'no-extra-boolean-cast': 'warn',
593
+
594
+ 'no-extra-label': 'warn',
595
+
596
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
597
+ 'no-fallthrough': 'error',
598
+
599
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
600
+ 'no-func-assign': 'warn',
601
+
602
+ // RATIONALE: Catches a common coding mistake.
603
+ 'no-implied-eval': 'error',
604
+
605
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
606
+ 'no-invalid-regexp': 'error',
607
+
608
+ // RATIONALE: Catches a common coding mistake.
609
+ 'no-label-var': 'error',
610
+
611
+ // RATIONALE: Eliminates redundant code.
612
+ 'no-lone-blocks': 'warn',
613
+
614
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
615
+ 'no-misleading-character-class': 'error',
616
+
617
+ // RATIONALE: Catches a common coding mistake.
618
+ 'no-multi-str': 'error',
619
+
620
+ // RATIONALE: It's generally a bad practice to call "new Thing()" without assigning the result to
621
+ // a variable. Either it's part of an awkward expression like "(new Thing()).doSomething()",
622
+ // or else implies that the constructor is doing nontrivial computations, which is often
623
+ // a poor class design.
624
+ 'no-new': 'warn',
625
+
626
+ // RATIONALE: Obsolete language feature that is deprecated.
627
+ 'no-new-func': 'error',
628
+
629
+ // RATIONALE: Obsolete language feature that is deprecated.
630
+ 'no-new-object': 'error',
631
+
632
+ // RATIONALE: Obsolete notation.
633
+ 'no-new-wrappers': 'warn',
634
+
635
+ // RATIONALE: Catches code that is likely to be incorrect
636
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
637
+ 'no-octal': 'error',
638
+
639
+ // RATIONALE: Catches code that is likely to be incorrect
640
+ 'no-octal-escape': 'error',
641
+
642
+ // RATIONALE: Catches code that is likely to be incorrect
643
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
644
+ 'no-regex-spaces': 'error',
645
+
646
+ // RATIONALE: Catches a common coding mistake.
647
+ 'no-return-assign': 'error',
648
+
649
+ // RATIONALE: Security risk.
650
+ 'no-script-url': 'warn',
651
+
652
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
653
+ 'no-self-assign': 'error',
654
+
655
+ // RATIONALE: Catches a common coding mistake.
656
+ 'no-self-compare': 'error',
657
+
658
+ // RATIONALE: This avoids statements such as "while (a = next(), a && a.length);" that use
659
+ // commas to create compound expressions. In general code is more readable if each
660
+ // step is split onto a separate line. This also makes it easier to set breakpoints
661
+ // in the debugger.
662
+ 'no-sequences': 'error',
663
+
664
+ // RATIONALE: Catches code that is likely to be incorrect
665
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
666
+ 'no-shadow-restricted-names': 'error',
667
+
668
+ // RATIONALE: Obsolete language feature that is deprecated.
669
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
670
+ 'no-sparse-arrays': 'error',
671
+
672
+ // RATIONALE: Although in theory JavaScript allows any possible data type to be thrown as an exception,
673
+ // such flexibility adds pointless complexity, by requiring every catch block to test
674
+ // the type of the object that it receives. Whereas if catch blocks can always assume
675
+ // that their object implements the "Error" contract, then the code is simpler, and
676
+ // we generally get useful additional information like a call stack.
677
+ 'no-throw-literal': 'error',
678
+
679
+ // RATIONALE: Catches a common coding mistake.
680
+ 'no-unmodified-loop-condition': 'warn',
681
+
682
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
683
+ 'no-unsafe-finally': 'error',
684
+
685
+ // RATIONALE: Catches a common coding mistake.
686
+ 'no-unused-expressions': 'warn',
687
+
688
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
689
+ 'no-unused-labels': 'warn',
690
+
691
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
692
+ 'no-useless-catch': 'warn',
693
+
694
+ // RATIONALE: Avoids a potential performance problem.
695
+ 'no-useless-concat': 'warn',
696
+
697
+ // RATIONALE: The "var" keyword is deprecated because of its confusing "hoisting" behavior.
698
+ // Always use "let" or "const" instead.
699
+ //
700
+ // STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
701
+ 'no-var': 'error',
702
+
703
+ // RATIONALE: Generally not needed in modern code.
704
+ 'no-void': 'error',
705
+
706
+ // RATIONALE: Obsolete language feature that is deprecated.
707
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
708
+ 'no-with': 'error',
709
+
710
+ // RATIONALE: Makes logic easier to understand, since constants always have a known value
711
+ // @typescript-eslint\eslint-plugin\dist\configs\eslint-recommended.js
712
+ 'prefer-const': 'warn',
713
+
714
+ // RATIONALE: Catches a common coding mistake where "resolve" and "reject" are confused.
715
+ 'promise/param-names': 'error',
716
+
717
+ // RATIONALE: Catches code that is likely to be incorrect
718
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
719
+ 'require-atomic-updates': 'error',
720
+
721
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
722
+ 'require-yield': 'warn',
723
+
724
+ // "Use strict" is redundant when using the TypeScript compiler.
725
+ strict: ['error', 'never'],
726
+
727
+ // RATIONALE: Catches code that is likely to be incorrect
728
+ // STANDARDIZED BY: eslint\conf\eslint-recommended.js
729
+ 'use-isnan': 'error'
730
+
731
+ // The "no-restricted-syntax" rule is a general purpose pattern matcher that we can use to experiment with
732
+ // new rules. If a rule works well, we should convert it to a proper rule so it gets its own name
733
+ // for suppressions and documentation.
734
+ // How it works: https://eslint.org/docs/rules/no-restricted-syntax
735
+ // AST visualizer: https://astexplorer.net/
736
+ // Debugger: http://estools.github.io/esquery/
737
+ //
738
+ // "no-restricted-syntax": [
739
+ // ],
740
+ }
741
+ },
742
+
743
+ // ====================================================================
744
+ // TESTING RULES
745
+ // ====================================================================
746
+ {
747
+ files: [
748
+ // Test files
749
+ '**/*.test.ts',
750
+ '**/*.test.tsx',
751
+ '**/*.spec.ts',
752
+ '**/*.spec.tsx',
753
+
754
+ // Facebook convention
755
+ '**/__mocks__/*.ts',
756
+ '**/__mocks__/*.tsx',
757
+ '**/__tests__/*.ts',
758
+ '**/__tests__/*.tsx',
759
+
760
+ // Microsoft convention
761
+ '**/test/*.ts',
762
+ '**/test/*.tsx'
763
+ ],
764
+ rules: {
765
+ // Unit tests sometimes use a standalone statement like "new Thing(123);" to test a constructor.
766
+ 'no-new': 'off',
767
+
768
+ // Jest's mocking API is designed in a way that produces compositional data types that often have
769
+ // no concise description. Since test code does not ship, and typically does not introduce new
770
+ // concepts or algorithms, the usual arguments for prioritizing readability over writability can be
771
+ // relaxed in this case.
772
+ '@rushstack/typedef-var': 'off'
773
+ }
774
+ }
775
+ ];
776
+
777
+ module.exports = { commonNamingConventionSelectors, commonConfig };
@@ -0,0 +1,104 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ // This is a workaround for the @typescript-eslint/naming-convention rule, whose options currently
5
+ // support a "selector" field that cannot match multiple selectors. This function receives an input
6
+ // array such as:
7
+ //
8
+ // [
9
+ // {
10
+ // selectors: ['class', 'typeAlias', 'enum'],
11
+ // format: ['PascalCase']
12
+ // },
13
+ // . . .
14
+ // ]
15
+ //
16
+ // ...and transforms "selectors" -> "selector, returning an array with expanded entries like this:
17
+ //
18
+ // [
19
+ // {
20
+ // selector: 'class',
21
+ // format: ['PascalCase']
22
+ // },
23
+ // {
24
+ // selector: 'typeAlias',
25
+ // format: ['PascalCase']
26
+ // },
27
+ // {
28
+ // selector: 'enum',
29
+ // format: ['PascalCase']
30
+ // },
31
+ // . . .
32
+ // ]
33
+ //
34
+ // It also supports a "enforceLeadingUnderscoreWhenPrivate" macro that expands this:
35
+ //
36
+ // [
37
+ // {
38
+ // selectors: ['property'],
39
+ // enforceLeadingUnderscoreWhenPrivate: true,
40
+ // format: ['camelCase']
41
+ // },
42
+ // . . .
43
+ // ]
44
+ //
45
+ // ...to produce this:
46
+ //
47
+ // [
48
+ // {
49
+ // selector: 'property',
50
+ //
51
+ // leadingUnderscore: 'allow',
52
+ // format: ['camelCase']
53
+ // },
54
+ // {
55
+ // selector: 'property',
56
+ // modifiers: ['private'],
57
+ //
58
+ // leadingUnderscore: 'require',
59
+ // format: ['camelCase']
60
+ // },
61
+ // . . .
62
+ // ]
63
+ function expandNamingConventionSelectors(inputBlocks) {
64
+ const firstPassBlocks = [];
65
+
66
+ // Expand "selectors" --> "selector"
67
+ for (const block of inputBlocks) {
68
+ for (const selector of block.selectors) {
69
+ const expandedBlock = { ...block };
70
+ delete expandedBlock.selectors;
71
+ expandedBlock.selector = selector;
72
+ firstPassBlocks.push(expandedBlock);
73
+ }
74
+ }
75
+
76
+ // Expand "enforceLeadingUnderscoreWhenPrivate" --> "leadingUnderscore"
77
+ const secondPassBlocks = [];
78
+ for (const block of firstPassBlocks) {
79
+ if (block.enforceLeadingUnderscoreWhenPrivate) {
80
+ const expandedBlock1 = {
81
+ ...block,
82
+ leadingUnderscore: 'allow'
83
+ };
84
+ delete expandedBlock1.enforceLeadingUnderscoreWhenPrivate;
85
+ secondPassBlocks.push(expandedBlock1);
86
+
87
+ const expandedBlock2 = {
88
+ ...block,
89
+ modifiers: [...(block.modifiers ?? []), 'private'],
90
+ leadingUnderscore: 'require'
91
+ };
92
+ delete expandedBlock2.enforceLeadingUnderscoreWhenPrivate;
93
+ secondPassBlocks.push(expandedBlock2);
94
+ } else {
95
+ secondPassBlocks.push(block);
96
+ }
97
+ }
98
+
99
+ return secondPassBlocks;
100
+ }
101
+
102
+ module.exports = {
103
+ expandNamingConventionSelectors: expandNamingConventionSelectors
104
+ };
@@ -0,0 +1,26 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ // This profile enables lint rules intended for a Node.js project whose inputs will always
5
+ // come from a developer or other trusted source. Most build system tasks are like this,
6
+ // since they operate on exclusively files prepared by a developer.
7
+ //
8
+ // This profile disables certain security rules that would otherwise prohibit APIs that could
9
+ // cause a denial-of-service by consuming too many resources, or which might interact with
10
+ // the filesystem in unsafe ways. Such activities are safe and commonplace for a trusted tool.
11
+ //
12
+ // DO NOT use this profile for a library project that might also be loaded by a Node.js service;
13
+ // use "@rushstack/eslint-config/profiles/node" instead.
14
+
15
+ const { commonConfig } = require('./_common');
16
+
17
+ module.exports = [
18
+ ...commonConfig,
19
+ {
20
+ files: ['**/*.ts', '**/*.tsx'],
21
+ rules: {
22
+ // This is disabled for trusted tools because the tool is known to be safe.
23
+ '@rushstack/security/no-unsafe-regexp': 'off'
24
+ }
25
+ }
26
+ ];
@@ -0,0 +1,10 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ // This profile enables lint rules intended for a general Node.js project, typically a web service.
5
+ // It enables security rules that assume the service could receive malicious inputs from an
6
+ // untrusted user. If that is not the case, consider using the "node-trusted-tool" profile instead.
7
+
8
+ const { commonConfig } = require('./_common');
9
+
10
+ module.exports = [...commonConfig];
@@ -0,0 +1,12 @@
1
+ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2
+ // See LICENSE in the project root for license information.
3
+
4
+ // This profile enables lint rules intended for a web application. It enables security rules
5
+ // that are relevant to web browser APIs such as DOM.
6
+ //
7
+ // Also use this profile if you are creating a library that can be consumed by both Node.js
8
+ // and web applications.
9
+
10
+ const { commonConfig } = require('./_common');
11
+
12
+ module.exports = [...commonConfig];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rushstack/eslint-config",
3
- "version": "4.2.0",
3
+ "version": "4.4.0",
4
4
  "description": "A TypeScript ESLint ruleset designed for large teams and projects",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -19,25 +19,25 @@
19
19
  "typescript"
20
20
  ],
21
21
  "peerDependencies": {
22
- "eslint": "^8.57.0",
22
+ "eslint": "^8.57.0 || ^9.25.1",
23
23
  "typescript": ">=4.7.0"
24
24
  },
25
25
  "dependencies": {
26
- "@typescript-eslint/eslint-plugin": "~8.24.0",
27
- "@typescript-eslint/utils": "~8.24.0",
28
- "@typescript-eslint/parser": "~8.24.0",
29
- "@typescript-eslint/typescript-estree": "~8.24.0",
30
- "eslint-plugin-promise": "~6.1.1",
31
- "eslint-plugin-react": "~7.33.2",
26
+ "@typescript-eslint/eslint-plugin": "~8.31.0",
27
+ "@typescript-eslint/utils": "~8.31.0",
28
+ "@typescript-eslint/parser": "~8.31.0",
29
+ "@typescript-eslint/typescript-estree": "~8.31.0",
30
+ "eslint-plugin-promise": "~7.2.1",
31
+ "eslint-plugin-react": "~7.37.5",
32
32
  "eslint-plugin-tsdoc": "~0.4.0",
33
- "@rushstack/eslint-patch": "1.10.5",
34
- "@rushstack/eslint-plugin": "0.17.0",
35
- "@rushstack/eslint-plugin-security": "0.9.0",
36
- "@rushstack/eslint-plugin-packlets": "0.10.0"
33
+ "@rushstack/eslint-patch": "1.12.0",
34
+ "@rushstack/eslint-plugin-packlets": "0.12.0",
35
+ "@rushstack/eslint-plugin-security": "0.11.0",
36
+ "@rushstack/eslint-plugin": "0.19.0"
37
37
  },
38
38
  "devDependencies": {
39
- "eslint": "~8.57.0",
40
- "typescript": "~5.7.3"
39
+ "eslint": "~9.25.1",
40
+ "typescript": "~5.8.2"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "",
@@ -337,7 +337,12 @@ function buildRules(profile) {
337
337
  // or else return the object to a caller (who assumes this responsibility). Unterminated
338
338
  // promise chains are a serious issue. Besides causing errors to be silently ignored,
339
339
  // they can also cause a NodeJS process to terminate unexpectedly.
340
- '@typescript-eslint/no-floating-promises': 'error',
340
+ '@typescript-eslint/no-floating-promises': [
341
+ 'error',
342
+ {
343
+ checkThenables: true
344
+ }
345
+ ],
341
346
 
342
347
  // RATIONALE: Catches a common coding mistake.
343
348
  '@typescript-eslint/no-for-in-array': 'error',