@arcgis/eslint-config 5.2.0-next.99 → 6.0.0-next.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.
@@ -1,12 +1,172 @@
1
- import markdown from "@eslint/markdown";
1
+ import { d as disabledRules } from "../chunks/disabledRules.js";
2
2
  import jsdocPlugin from "eslint-plugin-jsdoc";
3
3
  import perfectionistPlugin from "eslint-plugin-perfectionist";
4
4
  import reactJsxPlugin from "eslint-plugin-react-jsx";
5
5
  import regexpPlugin from "eslint-plugin-regexp";
6
6
  import unicornPlugin from "eslint-plugin-unicorn";
7
7
  import { join } from "node:path";
8
- import tsEslint from "typescript-eslint";
9
8
  import { corePlugin } from "../plugins/core/index.js";
9
+ const disabledCorePackageJsonRules = [
10
+ // @typescript/native-preview temporarily uses the `beta` tag rather than a semver range.
11
+ "package-json/valid-devDependencies"
12
+ ];
13
+ const disabledCoreDeclarationRules = [
14
+ // We can't enforce names in third-party libraries
15
+ "@typescript-eslint/naming-convention"
16
+ ];
17
+ const disabledCoreOverrides = [
18
+ "@typescript-eslint/adjacent-overload-signatures",
19
+ "@typescript-eslint/array-type",
20
+ "@typescript-eslint/await-thenable",
21
+ "@typescript-eslint/consistent-generic-constructors",
22
+ "@typescript-eslint/consistent-indexed-object-style",
23
+ "@typescript-eslint/consistent-type-assertions",
24
+ "@typescript-eslint/consistent-type-exports",
25
+ "@typescript-eslint/dot-notation",
26
+ "@typescript-eslint/max-params",
27
+ // Core is not yet using strictFunctionTypes so can't use this rule yet
28
+ "@typescript-eslint/method-signature-style",
29
+ "@typescript-eslint/no-confusing-non-null-assertion",
30
+ "@typescript-eslint/no-duplicate-type-constituents",
31
+ "@typescript-eslint/no-dynamic-delete",
32
+ "@typescript-eslint/no-empty-function",
33
+ "@typescript-eslint/no-empty-object-type",
34
+ "@typescript-eslint/no-explicit-any",
35
+ "@typescript-eslint/no-extra-non-null-assertion",
36
+ "@typescript-eslint/no-extraneous-class",
37
+ "@typescript-eslint/no-implied-eval",
38
+ "@typescript-eslint/no-inferrable-types",
39
+ "@typescript-eslint/no-misused-new",
40
+ "@typescript-eslint/no-misused-spread",
41
+ "@typescript-eslint/no-non-null-asserted-nullish-coalescing",
42
+ "@typescript-eslint/no-non-null-asserted-optional-chain",
43
+ "@typescript-eslint/no-redundant-type-constituents",
44
+ "@typescript-eslint/no-unnecessary-boolean-literal-compare",
45
+ "@typescript-eslint/no-unnecessary-condition",
46
+ "@typescript-eslint/no-unnecessary-template-expression",
47
+ "@typescript-eslint/no-unnecessary-type-constraint",
48
+ "@typescript-eslint/no-unnecessary-type-conversion",
49
+ "@typescript-eslint/no-unsafe-argument",
50
+ "@typescript-eslint/no-unsafe-assignment",
51
+ "@typescript-eslint/no-unsafe-call",
52
+ "@typescript-eslint/no-unsafe-function-type",
53
+ "@typescript-eslint/no-unsafe-member-access",
54
+ "@typescript-eslint/no-useless-empty-export",
55
+ "@typescript-eslint/no-wrapper-object-types",
56
+ "@typescript-eslint/non-nullable-type-assertion-style",
57
+ "@typescript-eslint/only-throw-error",
58
+ "@typescript-eslint/prefer-as-const",
59
+ "@typescript-eslint/prefer-function-type",
60
+ "@typescript-eslint/prefer-promise-reject-errors",
61
+ "@typescript-eslint/prefer-reduce-type-parameter",
62
+ "@typescript-eslint/prefer-return-this-type",
63
+ "@typescript-eslint/promise-function-async",
64
+ "@typescript-eslint/related-getter-setter-pairs",
65
+ "@typescript-eslint/require-array-sort-compare",
66
+ "@typescript-eslint/require-await",
67
+ "@typescript-eslint/restrict-plus-operands",
68
+ "@typescript-eslint/restrict-template-expressions",
69
+ "@typescript-eslint/sort-type-constituents",
70
+ "@typescript-eslint/switch-exhaustiveness-check",
71
+ "@typescript-eslint/triple-slash-reference",
72
+ "@typescript-eslint/unified-signatures",
73
+ "array-callback-return",
74
+ "default-case-last",
75
+ "func-names",
76
+ "func-style",
77
+ "grouped-accessor-pairs",
78
+ "id-denylist",
79
+ "lumina/add-missing-jsx-import",
80
+ "lumina/auto-add-type",
81
+ "lumina/component-placement-rules",
82
+ "lumina/consistent-event-naming",
83
+ "lumina/decorators-context",
84
+ "lumina/explicit-setter-type",
85
+ "lumina/member-ordering",
86
+ "lumina/no-create-element-component",
87
+ "lumina/no-ignore-jsdoc-tag",
88
+ "lumina/no-incorrect-dynamic-tag-name",
89
+ "lumina/no-inline-arrow-in-ref",
90
+ "lumina/no-inline-exposure-jsdoc-tag",
91
+ "lumina/no-invalid-directives-prop",
92
+ "lumina/no-jsdoc-xref-links",
93
+ "lumina/no-jsx-spread",
94
+ "lumina/no-listen-in-connected-callback",
95
+ "lumina/no-non-component-exports",
96
+ "lumina/no-property-name-start-with-on",
97
+ "lumina/no-render-false",
98
+ "lumina/no-unnecessary-assertion-on-event",
99
+ "lumina/no-unnecessary-attribute-name",
100
+ "lumina/no-unnecessary-bind-this",
101
+ "lumina/no-unnecessary-key",
102
+ "lumina/tag-name-rules",
103
+ "no-alert",
104
+ "no-constructor-return",
105
+ "no-extend-native",
106
+ "no-extra-bind",
107
+ "no-loss-of-precision",
108
+ "no-multi-assign",
109
+ "no-object-constructor",
110
+ "no-restricted-syntax",
111
+ "no-return-assign",
112
+ "no-script-url",
113
+ "no-self-compare",
114
+ "no-sequences",
115
+ "no-unneeded-ternary",
116
+ "no-unreachable-loop",
117
+ "no-unsafe-negation",
118
+ "no-useless-call",
119
+ "no-useless-concat",
120
+ "no-warning-comments",
121
+ "prefer-arrow-callback",
122
+ "prefer-numeric-literals",
123
+ "prefer-object-has-own",
124
+ "prefer-object-spread",
125
+ "prefer-regex-literals",
126
+ "prefer-rest-params",
127
+ "prefer-spread",
128
+ "prefer-template",
129
+ "require-atomic-updates",
130
+ "require-unicode-regexp",
131
+ "strict",
132
+ "symbol-description",
133
+ "unicode-bom",
134
+ "webgis/no-dts-files",
135
+ "webgis/no-import-outside-src",
136
+ "webgis/require-await-for-async-screenshot-assert",
137
+ "webgis/require-js-in-imports",
138
+ "yoda"
139
+ ];
140
+ const disabledCoreMarkdownOverrides = [
141
+ "markdown/fenced-code-language",
142
+ "markdown/heading-increment",
143
+ "markdown/no-duplicate-definitions",
144
+ "markdown/no-empty-definitions",
145
+ "markdown/no-empty-images",
146
+ "markdown/no-empty-links",
147
+ "markdown/no-invalid-label-refs",
148
+ "markdown/no-missing-atx-heading-space",
149
+ "markdown/no-missing-link-fragments",
150
+ "markdown/no-multiple-h1",
151
+ "markdown/no-reference-like-urls",
152
+ "markdown/no-reversed-media-syntax",
153
+ "markdown/no-space-in-emphasis",
154
+ "markdown/no-unused-definitions",
155
+ "markdown/require-alt-text",
156
+ "markdown/table-column-count"
157
+ ];
158
+ const disabledCoreTypedOverrides = [
159
+ "@typescript-eslint/no-array-delete",
160
+ "@typescript-eslint/no-floating-promises",
161
+ "@typescript-eslint/no-meaningless-void-operator",
162
+ "@typescript-eslint/no-misused-promises",
163
+ "@typescript-eslint/no-unsafe-unary-minus",
164
+ "@typescript-eslint/prefer-find",
165
+ "@typescript-eslint/prefer-includes",
166
+ "@typescript-eslint/prefer-optional-chain",
167
+ "@typescript-eslint/prefer-string-starts-ends-with",
168
+ "@typescript-eslint/return-await"
169
+ ];
10
170
  const noRestrictedSyntax = [
11
171
  "error",
12
172
  "AccessorProperty",
@@ -36,9 +196,6 @@ const noRestrictedSyntax = [
36
196
  message: "Use const objects or static classes instead. See https://devtopia.esri.com/WebGIS/arcgis-js-api/discussions/72194"
37
197
  }
38
198
  ];
39
- const disabledMarkdownRules = Object.fromEntries(
40
- Object.keys(markdown.rules).map((ruleName) => [`markdown/${ruleName}`, "off"])
41
- );
42
199
  const coreTypedRulesIgnoredFiles = [
43
200
  // We didn't run typed rules on these files before
44
201
  "packages/core-packages/core/*.{ts,tsx}",
@@ -46,13 +203,6 @@ const coreTypedRulesIgnoredFiles = [
46
203
  // This folder runs in node, so uses a separate tsconfig.json
47
204
  "packages/core-packages/core/tests/support/vitest/node/**/*.ts"
48
205
  ];
49
- const coreTypeCheckedRuleNames = new Set(Object.keys(tsEslint.configs.disableTypeChecked.rules ?? {})).union(
50
- corePlugin.meta.typeCheckedRules
51
- );
52
- coreTypeCheckedRuleNames.delete("@typescript-eslint/naming-convention");
53
- const disabledCoreTypeCheckedRules = Object.fromEntries(
54
- Array.from(coreTypeCheckedRuleNames, (ruleName) => [ruleName, "off"])
55
- );
56
206
  const eslintConfigCore = [
57
207
  {
58
208
  files: ["packages/core-packages/**/*.{ts,tsx}"],
@@ -70,10 +220,12 @@ const eslintConfigCore = [
70
220
  tagNamePreference: {
71
221
  // Our tags
72
222
  "public": "public",
223
+ "internal": "internal",
73
224
  "copyDoc": "copyDoc",
74
225
  // Flags
75
226
  "beta": "beta",
76
227
  "experimental": "experimental",
228
+ "knipIgnore": "knipIgnore",
77
229
  "readonly": "readonly",
78
230
  // Metadata
79
231
  "deprecated": "deprecated",
@@ -83,6 +235,8 @@ const eslintConfigCore = [
83
235
  "returns": "returns",
84
236
  "see": "see",
85
237
  "esriCompatibilityName": "esriCompatibilityName",
238
+ // Not yet officially supported, but not forbidden
239
+ "throws": "throws",
86
240
  // Long descriptions
87
241
  "example": "example",
88
242
  "privateRemarks": "privateRemarks",
@@ -91,156 +245,98 @@ const eslintConfigCore = [
91
245
  "constant": "readonly",
92
246
  "defaultvalue": "default",
93
247
  "return": "returns",
94
- // Obsolete tags. Do not use in new code. These are retained for
95
- // compatibility with existing non-public Core JSDoc.
96
- "amdalias": "amdalias",
97
- "autocast": "autocast",
98
- "noautocast": "noautocast",
99
- "constructonly": "constructonly",
100
- "tag constructor": "constructor",
101
- "deprecatedParameters": "deprecatedParameters",
102
- "deprecatedProperties": "deprecatedProperties",
103
- "esmimport": "esmimport",
104
- "extends": "extends",
105
- "method": "method",
106
- "moduletype": "moduletype",
107
- "ignoreNilOnly": "ignoreNilOnly"
248
+ // Forbid JSDoc tags that are redundant with TypeScript or not used by the docs ui
249
+ // eslint-plugin-jsdoc allows all these by default, so we need to explicitly disable them
250
+ "abstract": false,
251
+ "access": false,
252
+ "alias": false,
253
+ "arg": false,
254
+ "argument": false,
255
+ "async": false,
256
+ "augments": false,
257
+ "author": false,
258
+ "borrows": false,
259
+ "callback": false,
260
+ "class": false,
261
+ "classdesc": false,
262
+ "collectionItemType": false,
263
+ "constructor": false,
264
+ "constructs": false,
265
+ "copyright": false,
266
+ "deprecatedParameters": false,
267
+ "deprecatedProperties": false,
268
+ "desc": false,
269
+ "description": false,
270
+ "emits": false,
271
+ "enum": false,
272
+ "esmimport": false,
273
+ "event": false,
274
+ "exception": false,
275
+ "exports": false,
276
+ "extends": false,
277
+ "external": false,
278
+ "file": false,
279
+ "fileoverview": false,
280
+ "fires": false,
281
+ "func": false,
282
+ "function": false,
283
+ "generator": false,
284
+ "global": false,
285
+ "hideconstructor": false,
286
+ "host": false,
287
+ "ignore": false,
288
+ "implements": false,
289
+ "inheritDoc": false,
290
+ "inheritdoc": false,
291
+ "inner": false,
292
+ "instance": false,
293
+ "interface": false,
294
+ "kind": false,
295
+ "lends": false,
296
+ "license": false,
297
+ "listens": false,
298
+ "member": false,
299
+ "memberof!": false,
300
+ "memberof": false,
301
+ "method": false,
302
+ "mixes": false,
303
+ "mixin": false,
304
+ "modifies": false,
305
+ "module": false,
306
+ "moduletype": false,
307
+ "name": false,
308
+ "namespace": false,
309
+ "override": false,
310
+ "overview": false,
311
+ "package": false,
312
+ "private": false,
313
+ "prop": false,
314
+ "property": false,
315
+ "protected": false,
316
+ "requires": false,
317
+ "static": false,
318
+ "summary": false,
319
+ "tag constructor": false,
320
+ "this": false,
321
+ "tstype": false,
322
+ "tutorial": false,
323
+ "type": false,
324
+ "typedef": false,
325
+ "var": false,
326
+ "variation": false,
327
+ "version": false,
328
+ "virtual": false,
329
+ "yield": false,
330
+ "yields": false,
331
+ "import": false,
332
+ "overload": false,
333
+ "satisfies": false,
334
+ "template": false
108
335
  }
109
336
  }
110
337
  },
111
338
  rules: {
112
- //#region Temporary Disable monorepo-exclusive rules
113
- "@typescript-eslint/adjacent-overload-signatures": "off",
114
- "@typescript-eslint/array-type": "off",
115
- "@typescript-eslint/await-thenable": "off",
116
- "@typescript-eslint/consistent-generic-constructors": "off",
117
- "@typescript-eslint/consistent-indexed-object-style": "off",
118
- "@typescript-eslint/consistent-type-assertions": "off",
119
- "@typescript-eslint/consistent-type-exports": "off",
120
- "@typescript-eslint/dot-notation": "off",
121
- "@typescript-eslint/max-params": "off",
122
- "@typescript-eslint/method-signature-style": "off",
123
- "@typescript-eslint/no-confusing-non-null-assertion": "off",
124
- "@typescript-eslint/no-deprecated": "off",
125
- "@typescript-eslint/no-duplicate-type-constituents": "off",
126
- "@typescript-eslint/no-dynamic-delete": "off",
127
- "@typescript-eslint/no-empty-function": "off",
128
- "@typescript-eslint/no-empty-object-type": "off",
129
- "@typescript-eslint/no-explicit-any": "off",
130
- "@typescript-eslint/no-extra-non-null-assertion": "off",
131
- "@typescript-eslint/no-extraneous-class": "off",
132
- "@typescript-eslint/no-implied-eval": "off",
133
- "@typescript-eslint/no-inferrable-types": "off",
134
- "@typescript-eslint/no-misused-new": "off",
135
- "@typescript-eslint/no-misused-spread": "off",
136
- "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "off",
137
- "@typescript-eslint/no-non-null-asserted-optional-chain": "off",
138
- "@typescript-eslint/no-redundant-type-constituents": "off",
139
- "@typescript-eslint/no-unnecessary-boolean-literal-compare": "off",
140
- "@typescript-eslint/no-unnecessary-condition": "off",
141
- "@typescript-eslint/no-unnecessary-template-expression": "off",
142
- "@typescript-eslint/no-unnecessary-type-assertion": "off",
143
- "@typescript-eslint/no-unnecessary-type-constraint": "off",
144
- "@typescript-eslint/no-unnecessary-type-conversion": "off",
145
- "@typescript-eslint/no-unsafe-argument": "off",
146
- "@typescript-eslint/no-unsafe-assignment": "off",
147
- "@typescript-eslint/no-unsafe-call": "off",
148
- "@typescript-eslint/no-unsafe-enum-comparison": "off",
149
- "@typescript-eslint/no-unsafe-function-type": "off",
150
- "@typescript-eslint/no-unsafe-member-access": "off",
151
- "@typescript-eslint/no-useless-empty-export": "off",
152
- "@typescript-eslint/no-wrapper-object-types": "off",
153
- "@typescript-eslint/non-nullable-type-assertion-style": "off",
154
- "@typescript-eslint/only-throw-error": "off",
155
- "@typescript-eslint/prefer-as-const": "off",
156
- "@typescript-eslint/prefer-function-type": "off",
157
- "@typescript-eslint/prefer-promise-reject-errors": "off",
158
- "@typescript-eslint/prefer-reduce-type-parameter": "off",
159
- "@typescript-eslint/prefer-return-this-type": "off",
160
- "@typescript-eslint/promise-function-async": "off",
161
- "@typescript-eslint/related-getter-setter-pairs": "off",
162
- "@typescript-eslint/require-array-sort-compare": "off",
163
- "@typescript-eslint/require-await": "off",
164
- "@typescript-eslint/restrict-plus-operands": "off",
165
- "@typescript-eslint/restrict-template-expressions": "off",
166
- "@typescript-eslint/sort-type-constituents": "off",
167
- "@typescript-eslint/switch-exhaustiveness-check": "off",
168
- "@typescript-eslint/triple-slash-reference": "off",
169
- "@typescript-eslint/unified-signatures": "off",
170
- "array-callback-return": "off",
171
- "default-case-last": "off",
172
- "func-names": "off",
173
- "func-style": "off",
174
- "grouped-accessor-pairs": "off",
175
- "id-denylist": "off",
176
- "lumina/add-missing-jsx-import": "off",
177
- "lumina/auto-add-type": "off",
178
- "lumina/component-placement-rules": "off",
179
- "lumina/consistent-event-naming": "off",
180
- "lumina/consistent-nullability": "off",
181
- "lumina/decorators-context": "off",
182
- "lumina/explicit-setter-type": "off",
183
- "lumina/member-ordering": "off",
184
- "lumina/no-create-element-component": "off",
185
- "lumina/no-ignore-jsdoc-tag": "off",
186
- "lumina/no-incorrect-dynamic-tag-name": "off",
187
- "lumina/no-inline-arrow-in-ref": "off",
188
- "lumina/no-inline-exposure-jsdoc-tag": "off",
189
- "lumina/no-invalid-directives-prop": "off",
190
- "lumina/no-jsdoc-xref-links": "off",
191
- "lumina/no-jsx-spread": "off",
192
- "lumina/no-listen-in-connected-callback": "off",
193
- "lumina/no-non-component-exports": "off",
194
- "lumina/no-property-name-start-with-on": "off",
195
- "lumina/no-render-false": "off",
196
- "lumina/no-unnecessary-assertion-on-event": "off",
197
- "lumina/no-unnecessary-attribute-name": "off",
198
- "lumina/no-unnecessary-bind-this": "off",
199
- "lumina/no-unnecessary-key": "off",
200
- "lumina/tag-name-rules": "off",
201
- "no-alert": "off",
202
- "no-await-in-loop": "off",
203
- "no-constructor-return": "off",
204
- "no-extend-native": "off",
205
- "no-extra-bind": "off",
206
- "no-loss-of-precision": "off",
207
- "no-multi-assign": "off",
208
- "no-object-constructor": "off",
209
- "no-restricted-syntax": "off",
210
- "no-return-assign": "off",
211
- "no-script-url": "off",
212
- "no-self-compare": "off",
213
- "no-sequences": "off",
214
- "no-unneeded-ternary": "off",
215
- "no-unreachable-loop": "off",
216
- "no-unsafe-negation": "off",
217
- "no-useless-call": "off",
218
- "no-useless-concat": "off",
219
- "no-warning-comments": "off",
220
- "prefer-arrow-callback": "off",
221
- "prefer-numeric-literals": "off",
222
- "prefer-object-has-own": "off",
223
- "prefer-object-spread": "off",
224
- "prefer-regex-literals": "off",
225
- "prefer-rest-params": "off",
226
- "prefer-spread": "off",
227
- "prefer-template": "off",
228
- "require-atomic-updates": "off",
229
- "require-unicode-regexp": "off",
230
- "strict": "off",
231
- "symbol-description": "off",
232
- "unicode-bom": "off",
233
- "unicorn/number-literal-case": "off",
234
- "webgis/consistent-logging": "off",
235
- "webgis/no-dts-files": "off",
236
- "webgis/no-import-outside-src": "off",
237
- "webgis/no-touching-jsdoc": "off",
238
- "webgis/no-unsafe-hash-links": "off",
239
- "webgis/require-await-for-async-screenshot-assert": "off",
240
- "webgis/require-js-in-imports": "off",
241
- "yoda": "off",
242
- //#endregion
243
- //#region Temporary enable core-exclusive rules
339
+ ...disabledRules(disabledCoreOverrides),
244
340
  "@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": false, "ts-nocheck": false }],
245
341
  "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
246
342
  "@typescript-eslint/explicit-function-return-type": ["error", { allowExpressions: true }],
@@ -274,8 +370,6 @@ const eslintConfigCore = [
274
370
  ],
275
371
  "@typescript-eslint/no-array-constructor": "error",
276
372
  "@typescript-eslint/no-import-type-side-effects": "error",
277
- "@typescript-eslint/no-redeclare": "off",
278
- // turn on when this doesn't error on mixins
279
373
  "@typescript-eslint/no-require-imports": "error",
280
374
  "@typescript-eslint/no-restricted-imports": [
281
375
  "error",
@@ -381,21 +475,26 @@ const eslintConfigCore = [
381
475
  ]
382
476
  }
383
477
  ],
478
+ // Catch redundant import path segments
384
479
  "import-x/no-useless-path-segments": "error",
480
+ // Forbid unknown JSDoc tags and catch typos. Adopt in AWC now that we are using API Extractor
385
481
  "jsdoc/check-tag-names": [
386
482
  "error",
387
483
  { definedTags: ["tstype", "ignoreNilOnly", "noautocast", "collectionItemType"] }
388
484
  ],
485
+ // TODO: drop because we don't specify types in JSDoc anymore
389
486
  "jsdoc/check-types": "error",
487
+ // Forbid value after JSDoc tags that don't expect a value.
390
488
  // Ensure @readonly and @public is used without any content
391
489
  "jsdoc/empty-tags": "error",
392
- // Avoid /**\n ** something */
490
+ // Avoid /**\n ** something */ - likely typo
393
491
  "jsdoc/no-multi-asterisks": ["error", { allowWhitespace: true }],
394
492
  // Enforce each JSDoc line starts with *
395
493
  "jsdoc/require-asterisk-prefix": "error",
396
494
  // Enforce @param has param name
495
+ // TODO: consider dropping. This rule requires ... for rest params -
496
+ // that data should come from the AST, not JSDoc
397
497
  "jsdoc/require-param-name": "error",
398
- "no-array-constructor": "off",
399
498
  "no-async-promise-executor": "error",
400
499
  "no-caller": "error",
401
500
  "no-case-declarations": "error",
@@ -412,15 +511,12 @@ const eslintConfigCore = [
412
511
  "no-labels": ["error", { allowLoop: true, allowSwitch: true }],
413
512
  "no-new-func": "error",
414
513
  "no-new-wrappers": "error",
415
- "no-redeclare": "off",
416
514
  "no-regex-spaces": "error",
417
515
  "no-restricted-globals": ["error", "event", "name", "origin"],
418
516
  "no-shadow-restricted-names": "error",
419
517
  "no-throw-literal": "error",
420
518
  "no-unsafe-finally": "error",
421
519
  "no-unsafe-optional-chaining": "error",
422
- "no-unused-expressions": "off",
423
- "no-unused-vars": "off",
424
520
  "no-useless-escape": "error",
425
521
  "no-useless-rename": "error",
426
522
  "no-var": "error",
@@ -429,102 +525,177 @@ const eslintConfigCore = [
429
525
  "prefer-const": ["error", { destructuring: "all" }],
430
526
  "prefer-exponentiation-operator": "error",
431
527
  "radix": "error",
528
+ // Improve readability for \n and \t usages in regexes. Note this adds 0.5s to lint time
432
529
  "regexp/control-character-escape": "error",
530
+ // Catch redundant regex syntax
433
531
  "regexp/no-dupe-characters-character-class": "error",
532
+ // Catch redundant regex syntax
434
533
  "regexp/no-dupe-disjunctions": "error",
534
+ // Catch potential typos in regexes
435
535
  "regexp/no-empty-alternative": "error",
536
+ // Catch redundant regex syntax
436
537
  "regexp/no-empty-capturing-group": "error",
538
+ // Catch redundant regex syntax
437
539
  "regexp/no-empty-character-class": "error",
540
+ // Catch redundant regex syntax
438
541
  "regexp/no-empty-group": "error",
542
+ // Catch redundant regex syntax
439
543
  "regexp/no-empty-lookarounds-assertion": "error",
544
+ // Avoid confusion between \b and [\b]
440
545
  "regexp/no-escape-backspace": "error",
546
+ // Catch redundant regex syntax
441
547
  "regexp/no-extra-lookaround-assertions": "error",
548
+ // Detect regex syntax errors before it causes a runtime error
442
549
  "regexp/no-invalid-regexp": "error",
550
+ // Prefer escape codes over invisible characters for readability
443
551
  "regexp/no-invisible-character": "error",
552
+ // Catch redundant regex syntax
444
553
  "regexp/no-lazy-ends": "error",
554
+ // Catch unicode regexes that never match
445
555
  "regexp/no-misleading-unicode-character": "error",
556
+ // Detect when .matchAll() regex is missing /g in a way that catches runtime error
446
557
  "regexp/no-missing-g-flag": "error",
558
+ // Catch misleading usages of - in regex
447
559
  "regexp/no-obscure-range": "error",
560
+ // Catch redundant regex syntax
448
561
  "regexp/no-optional-assertion": "error",
562
+ // Catch redundant regex syntax
449
563
  "regexp/no-trivially-nested-assertion": "error",
564
+ // Catch redundant regex syntax
450
565
  "regexp/no-trivially-nested-quantifier": "error",
566
+ // Catch redundant regex syntax
451
567
  "regexp/no-useless-assertions": "error",
568
+ // Catch redundant regex syntax
452
569
  "regexp/no-useless-backreference": "error",
570
+ // Catch redundant regex syntax
453
571
  "regexp/no-useless-character-class": "error",
572
+ // Catch redundant regex syntax
454
573
  "regexp/no-useless-dollar-replacements": "error",
574
+ // Adds auto-fix and additional checks compared to `no-useless-escape`
455
575
  "regexp/no-useless-escape": "error",
456
- // adds auto-fix and additional checks compared to `no-useless-escape`
576
+ // Catch redundant regex syntax
457
577
  "regexp/no-useless-lazy": "error",
578
+ // Catch redundant regex syntax
458
579
  "regexp/no-useless-quantifier": "error",
580
+ // Catch redundant regex syntax
459
581
  "regexp/no-useless-range": "error",
582
+ // Catch redundant regex syntax
460
583
  "regexp/no-useless-set-operand": "error",
584
+ // Catch redundant regex syntax
461
585
  "regexp/no-useless-string-literal": "error",
586
+ // Catch redundant regex syntax
462
587
  "regexp/no-useless-two-nums-quantifier": "error",
588
+ // Catch redundant regex syntax
463
589
  "regexp/optimal-quantifier-concatenation": "error",
590
+ // Catch redundant regex syntax
464
591
  "regexp/prefer-predefined-assertion": "error",
592
+ // Catch redundant regex syntax
465
593
  "regexp/prefer-range": "error",
594
+ // Encourage usage of modern regex features
466
595
  "regexp/prefer-set-operation": "error",
596
+ // Catch redundant date cloning syntax
467
597
  "unicorn/consistent-date-clone": "error",
598
+ // Use [] over '' when spreading in arrays (readability only - no runtime difference)
468
599
  "unicorn/consistent-empty-array-spread": "error",
600
+ // If need to disable ESLint, encourage disabling a single rule rather than all
469
601
  "unicorn/no-abusive-eslint-disable": "error",
602
+ // Detect getter accessing itself - causes a runtime loop
470
603
  "unicorn/no-accessor-recursion": "error",
604
+ // Detect Promise.all([await a]) when await Promise.all([a]) was meant
471
605
  "unicorn/no-await-in-promise-methods": "error",
606
+ // Forbid unsafe usage of instanceof
472
607
  "unicorn/no-instanceof-builtins": "error",
608
+ // Catch .removeEventListener usages that don't work
473
609
  "unicorn/no-invalid-remove-event-listener": "error",
610
+ // Detect !a==b when a!=b was meant.
611
+ // TODO: drop because TypeScript detects this. And it misses
612
+ // cases that @typescript-eslint/no-confusing-non-null-assertion detects
474
613
  "unicorn/no-negation-in-equality-check": "error",
614
+ // Catch redundant promise syntax
475
615
  "unicorn/no-single-promise-in-promise-methods": "error",
616
+ // Prefer === undefined over typeof bar === 'undefined'
476
617
  "unicorn/no-typeof-undefined": "error",
618
+ // Prefer .flat() over .flat(1)
477
619
  "unicorn/no-unnecessary-array-flat-depth": "error",
620
+ // Prefer .splice(1) over .splice(1, string.length);
478
621
  "unicorn/no-unnecessary-array-splice-count": "error",
622
+ // Catch redundant .slice() syntax
479
623
  "unicorn/no-unnecessary-slice-end": "error",
624
+ // Catch redundant spread syntax
480
625
  "unicorn/no-useless-fallback-in-spread": "error",
626
+ // Replace .some() with .every() or the opposite when it simplifies the code
481
627
  "unicorn/no-useless-length-check": "error",
628
+ // Catch redundant promise syntax
482
629
  "unicorn/no-useless-promise-resolve-reject": "error",
630
+ // Catch redundant spread syntax usage
483
631
  "unicorn/no-useless-spread": "error",
632
+ // Do not initialize variables with =undefined as that is the default
484
633
  "unicorn/no-useless-undefined": ["error", { checkArguments: false, checkArrowFunctionBody: false }],
634
+ // Prefer .find() over .filter()[0]
485
635
  "unicorn/prefer-array-find": "error",
636
+ // Use .flat() over older workaround syntaxes
486
637
  "unicorn/prefer-array-flat": "error",
638
+ // Prefer .flatMap() over .map().flat()
487
639
  "unicorn/prefer-array-flat-map": "error",
640
+ // Prefer .indexOf() over .findIndex() where possible
488
641
  "unicorn/prefer-array-index-of": "error",
642
+ // Use .some() over .filter().length>0
489
643
  "unicorn/prefer-array-some": "error",
644
+ // Use newer methods when working with blobs
490
645
  "unicorn/prefer-blob-reading-methods": "error",
646
+ // Prefer Date.now() over older longer but equivalent variants
491
647
  "unicorn/prefer-date-now": "error",
648
+ // Catch legacy default-values syntax
492
649
  "unicorn/prefer-default-parameters": "error",
650
+ // Use .includes() over .indexOf() where possible for readability
493
651
  "unicorn/prefer-includes": "error",
652
+ // Prefer `a ?? b` over `a ? a : b`
494
653
  "unicorn/prefer-logical-operator-over-ternary": "error",
654
+ // Prefer simpler syntax for .slice() from the end
495
655
  "unicorn/prefer-negative-index": "error",
656
+ // Require `node:` in node.js imports. Improves compatibility with non-node engines
496
657
  "unicorn/prefer-node-protocol": "error",
658
+ // TODO: consider dropping - string.match(regex) is more readable
497
659
  "unicorn/prefer-regexp-test": "error",
660
+ // Prefer sets over arrays when using the array only for .includes() check
498
661
  "unicorn/prefer-set-has": "error",
662
+ // Simplify code when set .size is needed
499
663
  "unicorn/prefer-set-size": "error",
664
+ // Use .replaceAll() over .replace() when replaceAll was meant. Readability.
500
665
  "unicorn/prefer-string-replace-all": "error",
666
+ // Use .slice() over legacy .substring() and .substr()
501
667
  "unicorn/prefer-string-slice": "error",
668
+ // Prefer .startsWith() over regex when they are equivalent for readability
502
669
  "unicorn/prefer-string-starts-ends-with": "error",
670
+ // Require `new Error` over `Error`.
671
+ // TODO: dro because they are equivalent and `new ` adds bytes (not minified by esbuild)
503
672
  "unicorn/throw-new-error": "error",
673
+ // See https://devtopia.esri.com/WebGIS/webgis-sdk/pull/15335#discussion_r1683898
504
674
  "webgis/consistent-constructor-arguments": "error",
505
675
  "webgis/consistent-mixin-syntax": "error",
506
676
  "webgis/no-empty-catch": "error",
677
+ // Use JSX props over attributes because TypeScript does not type check attributes
507
678
  "webgis/no-kebab-case-props": "error",
679
+ // Require type="" parameter on buttons to avoid unexpected button behavior inside forms
508
680
  "webgis/require-button-type": "error"
509
- //#endregion
510
681
  }
511
682
  },
512
683
  {
513
684
  files: ["packages/core-packages/**/*.md"],
514
- rules: disabledMarkdownRules
685
+ rules: {
686
+ ...disabledRules(disabledCoreMarkdownOverrides)
687
+ }
515
688
  },
516
689
  {
517
690
  files: ["packages/core-packages/core/package.json"],
518
691
  rules: {
519
- // @typescript/native-preview temporarily uses the `beta` tag rather than a semver range.
520
- "package-json/valid-devDependencies": "off"
692
+ ...disabledRules(disabledCorePackageJsonRules)
521
693
  }
522
694
  },
523
695
  {
524
696
  files: ["packages/core-packages/**/*.d.ts"],
525
697
  rules: {
526
- "@typescript-eslint/naming-convention": "off"
527
- // we can't enforce names in libraries
698
+ ...disabledRules(disabledCoreDeclarationRules)
528
699
  }
529
700
  },
530
701
  {
@@ -532,8 +703,6 @@ const eslintConfigCore = [
532
703
  files: ["packages/core-packages/**/*.{ts,tsx}"],
533
704
  ignores: [...coreTypedRulesIgnoredFiles],
534
705
  rules: {
535
- // Disabled until https://github.com/typescript-eslint/typescript-eslint/pull/11267 is available.
536
- "@typescript-eslint/await-thenable": "off",
537
706
  "@typescript-eslint/no-array-delete": "error",
538
707
  "@typescript-eslint/no-floating-promises": "error",
539
708
  "@typescript-eslint/no-for-in-array": "error",
@@ -557,7 +726,9 @@ const eslintConfigCore = [
557
726
  projectService: false
558
727
  }
559
728
  },
560
- rules: disabledCoreTypeCheckedRules
729
+ rules: {
730
+ ...disabledRules(disabledCoreTypedOverrides)
731
+ }
561
732
  },
562
733
  {
563
734
  files: ["packages/core-packages/**/*.tsx"],
@@ -566,6 +737,7 @@ const eslintConfigCore = [
566
737
  "react-jsx": reactJsxPlugin
567
738
  },
568
739
  rules: {
740
+ // Sort JSX props consistently. Improves readability for large JSX blocks
569
741
  "perfectionist/sort-jsx-props": [
570
742
  "error",
571
743
  {
@@ -573,8 +745,14 @@ const eslintConfigCore = [
573
745
  customGroups: [{ groupName: "callback", elementNamePattern: "^on.+" }]
574
746
  }
575
747
  ],
748
+ // Require passing JSX children as content rather than as children={} prop
576
749
  "react-jsx/no-children-prop": "error",
750
+ // Catch JSX comment syntax error
577
751
  "react-jsx/no-comment-textnodes": "error",
752
+ // Report needless <>
753
+ // TODO: consider dropping this rule rule because this has no runtime cost
754
+ // in Lumina, and it is not always autofixable. This rule also errors for
755
+ // return <></>; which is sometimes needed in astro
578
756
  "react-jsx/no-useless-fragment": "error"
579
757
  }
580
758
  },
@@ -601,7 +779,6 @@ const eslintConfigCore = [
601
779
  {
602
780
  files: ["packages/core-packages/core/tests/**/*.{ts,tsx}"],
603
781
  rules: {
604
- "webgis/no-instanceof": "off",
605
782
  "@typescript-eslint/no-restricted-imports": [
606
783
  "error",
607
784
  {
@@ -637,6 +814,7 @@ const eslintConfigCore = [
637
814
  message: "Avoid adding has flags manually. Instead use the suite/test-level options to set has flags."
638
815
  }
639
816
  ],
817
+ // Require awaiting assert.screenshot() in tests
640
818
  "webgis/require-await-for-async-screenshot-assert": "error"
641
819
  }
642
820
  }