@arcgis/eslint-config 5.2.0-next.6 → 5.2.0-next.60

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/README.md CHANGED
@@ -8,5 +8,5 @@ It is not intended to be used directly, but rather used as a dependency by other
8
8
 
9
9
  ## License
10
10
 
11
- This package is licensed under the terms described in the `LICENSE.md` file, located in the root of the package, and at https://js.arcgis.com/5.1/LICENSE.txt.
12
- For third party notices, see https://js.arcgis.com/5.1/third-party-notices.txt.
11
+ This package is licensed under the terms described in the `LICENSE.md` file, located in the root of the package, and at https://js.arcgis.com/5.2/LICENSE.txt.
12
+ For third party notices, see https://js.arcgis.com/5.2/third-party-notices.txt.
@@ -28,8 +28,6 @@ const config = [
28
28
  "func-names": "off",
29
29
  // This rule is for consistency between library developers - less important for monolith apps.
30
30
  "id-denylist": "off",
31
- // Some cases actually require sequential async loops
32
- "no-await-in-loop": "off",
33
31
  // More important for library-exposed symbols than apps
34
32
  "symbol-description": "off"
35
33
  }
@@ -0,0 +1,647 @@
1
+ import markdown from "@eslint/markdown";
2
+ import jsdocPlugin from "eslint-plugin-jsdoc";
3
+ import perfectionistPlugin from "eslint-plugin-perfectionist";
4
+ import reactJsxPlugin from "eslint-plugin-react-jsx";
5
+ import regexpPlugin from "eslint-plugin-regexp";
6
+ import unicornPlugin from "eslint-plugin-unicorn";
7
+ import { join } from "node:path";
8
+ import tsEslint from "typescript-eslint";
9
+ import { corePlugin } from "../plugins/core/index.js";
10
+ const noRestrictedSyntax = [
11
+ "error",
12
+ "AccessorProperty",
13
+ "PrivateIdentifier",
14
+ {
15
+ selector: "CallExpression[callee.property.name='concat'][arguments.length=0]",
16
+ message: "Use slice() instead of concat()."
17
+ },
18
+ {
19
+ selector: "CallExpression[callee.property.name='slice'][arguments.length=1] > .arguments[value=0]",
20
+ message: "Use slice() instead of slice(0)."
21
+ },
22
+ {
23
+ selector: "TSAbstractPropertyDefinition[decorators.length>0]",
24
+ message: "Decorators are not supported on abstract properties."
25
+ },
26
+ {
27
+ selector: "TSEnumDeclaration:not([const=true])",
28
+ message: "Don't declare non-const enums. Use `const enum` instead, or an object with `as const`. See https://www.typescriptlang.org/docs/handbook/enums.html#objects-vs-enums"
29
+ },
30
+ {
31
+ selector: "VariableDeclarator > CallExpression > MemberExpression[property.name='getLogger']",
32
+ message: "Get a logger as needed instead of assigning it for future use."
33
+ },
34
+ {
35
+ selector: "TSModuleDeclaration[id.type='Identifier']",
36
+ message: "Use const objects or static classes instead. See https://devtopia.esri.com/WebGIS/arcgis-js-api/discussions/72194"
37
+ }
38
+ ];
39
+ const disabledMarkdownRules = Object.fromEntries(
40
+ Object.keys(markdown.rules).map((ruleName) => [`markdown/${ruleName}`, "off"])
41
+ );
42
+ const coreTypedRulesIgnoredFiles = [
43
+ // We didn't run typed rules on these files before
44
+ "packages/core-packages/core/*.{ts,tsx}",
45
+ "packages/core-packages/core/{.github,build,scripts,tasks,test-apps,typings}/**/*.{ts,tsx}",
46
+ // This folder runs in node, so uses a separate tsconfig.json
47
+ "packages/core-packages/core/tests/support/vitest/node/**/*.ts"
48
+ ];
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
+ const eslintConfigCore = [
57
+ {
58
+ files: ["packages/core-packages/**/*.{ts,tsx}"],
59
+ linterOptions: {
60
+ reportUnusedDisableDirectives: "off"
61
+ },
62
+ plugins: {
63
+ core: corePlugin,
64
+ jsdoc: jsdocPlugin,
65
+ regexp: regexpPlugin,
66
+ unicorn: unicornPlugin
67
+ },
68
+ settings: {
69
+ jsdoc: {
70
+ tagNamePreference: {
71
+ // Our tags
72
+ "public": "public",
73
+ "copyDoc": "copyDoc",
74
+ // Flags
75
+ "beta": "beta",
76
+ "experimental": "experimental",
77
+ "readonly": "readonly",
78
+ // Metadata
79
+ "deprecated": "deprecated",
80
+ "default": "default",
81
+ "since": "since",
82
+ "param": "param",
83
+ "returns": "returns",
84
+ "see": "see",
85
+ "esriCompatibilityName": "esriCompatibilityName",
86
+ // Long descriptions
87
+ "example": "example",
88
+ "privateRemarks": "privateRemarks",
89
+ // Legacy replacements
90
+ "const": "readonly",
91
+ "constant": "readonly",
92
+ "defaultvalue": "default",
93
+ "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"
108
+ }
109
+ }
110
+ },
111
+ 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-computed-key": "off",
219
+ "no-useless-concat": "off",
220
+ "no-warning-comments": "off",
221
+ "prefer-arrow-callback": "off",
222
+ "prefer-numeric-literals": "off",
223
+ "prefer-object-has-own": "off",
224
+ "prefer-object-spread": "off",
225
+ "prefer-regex-literals": "off",
226
+ "prefer-rest-params": "off",
227
+ "prefer-spread": "off",
228
+ "prefer-template": "off",
229
+ "require-atomic-updates": "off",
230
+ "require-unicode-regexp": "off",
231
+ "strict": "off",
232
+ "symbol-description": "off",
233
+ "unicode-bom": "off",
234
+ "unicorn/number-literal-case": "off",
235
+ "webgis/consistent-logging": "off",
236
+ "webgis/no-dts-files": "off",
237
+ "webgis/no-import-outside-src": "off",
238
+ "webgis/no-touching-jsdoc": "off",
239
+ "webgis/no-unsafe-hash-links": "off",
240
+ "webgis/require-await-for-async-screenshot-assert": "off",
241
+ "webgis/require-js-in-imports": "off",
242
+ "yoda": "off",
243
+ //#endregion
244
+ //#region Temporary enable core-exclusive rules
245
+ "@typescript-eslint/ban-ts-comment": ["error", { "ts-expect-error": false, "ts-nocheck": false }],
246
+ "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
247
+ "@typescript-eslint/explicit-function-return-type": ["error", { allowExpressions: true }],
248
+ "@typescript-eslint/explicit-member-accessibility": ["error", { accessibility: "no-public" }],
249
+ "@typescript-eslint/naming-convention": [
250
+ "error",
251
+ { selector: ["typeLike"], format: ["PascalCase"] },
252
+ {
253
+ selector: ["function", "classMethod", "classProperty", "typeMethod"],
254
+ format: ["camelCase"],
255
+ leadingUnderscore: "allow"
256
+ },
257
+ {
258
+ selector: ["memberLike", "classProperty"],
259
+ modifiers: ["private"],
260
+ format: ["camelCase"],
261
+ leadingUnderscore: "require"
262
+ },
263
+ {
264
+ selector: ["classProperty"],
265
+ modifiers: ["static"],
266
+ format: ["UPPER_CASE", "PascalCase", "camelCase"],
267
+ leadingUnderscore: "allow"
268
+ },
269
+ {
270
+ selector: ["classProperty"],
271
+ modifiers: ["private", "static"],
272
+ format: ["UPPER_CASE", "PascalCase", "camelCase"],
273
+ leadingUnderscore: "allow"
274
+ }
275
+ ],
276
+ "@typescript-eslint/no-array-constructor": "error",
277
+ "@typescript-eslint/no-import-type-side-effects": "error",
278
+ "@typescript-eslint/no-redeclare": "off",
279
+ // turn on when this doesn't error on mixins
280
+ "@typescript-eslint/no-require-imports": "error",
281
+ "@typescript-eslint/no-restricted-imports": [
282
+ "error",
283
+ {
284
+ paths: [
285
+ { name: "esri/identity/IdentityManager", message: "Use `esri/kernel.id` or the `authMode` option." },
286
+ {
287
+ name: "esri/layers/support/rasterFunctionUtils",
288
+ message: "Import raster function creators directly instead."
289
+ },
290
+ {
291
+ name: "esri/TimeExtent",
292
+ message: "Use `esri/time/TimeExtent` instead. See https://devtopia.esri.com/WebGIS/arcgis-js-api/issues/49223."
293
+ },
294
+ {
295
+ name: "esri/TimeInterval",
296
+ message: "Use `esri/time/TimeInterval` instead. See https://devtopia.esri.com/WebGIS/arcgis-js-api/issues/49223."
297
+ },
298
+ { name: "esri/rest/geometryService", message: "Import geometry services directly instead" },
299
+ { name: "esri/rest/geoprocessor", message: "Import geoprocessor exports directly instead" },
300
+ { name: "esri/rest/locator", message: "Import locator exports directly instead" },
301
+ { name: "esri/rest/query", message: "use individual files instead" }
302
+ ],
303
+ patterns: [
304
+ {
305
+ group: ["@esri/calcite-components/dist/components/*"],
306
+ message: "Pass a dynamic import to `loadCalciteComponents` inside `loadDependencies` instead.",
307
+ allowTypeImports: true
308
+ }
309
+ ]
310
+ }
311
+ ],
312
+ "@typescript-eslint/no-unnecessary-parameter-property-assignment": "error",
313
+ "@typescript-eslint/no-unused-expressions": ["error", { allowShortCircuit: true, allowTernary: true }],
314
+ "@typescript-eslint/no-unused-vars": [
315
+ "error",
316
+ {
317
+ args: "all",
318
+ argsIgnorePattern: "^_",
319
+ caughtErrors: "none",
320
+ destructuredArrayIgnorePattern: "^_",
321
+ varsIgnorePattern: "^_|^tsx",
322
+ ignoreRestSiblings: true,
323
+ enableAutofixRemoval: { imports: true }
324
+ }
325
+ ],
326
+ "@typescript-eslint/prefer-namespace-keyword": "error",
327
+ "arrow-body-style": "error",
328
+ "core/glsl-whitespace": "error",
329
+ "core/imports-format": "error",
330
+ "core/no-duplicate-import-comments": "error",
331
+ "core/no-empty-jsdoc-todo": "error",
332
+ "core/no-redundant-checked-in-files": "error",
333
+ "core/prefer-relative-imports": "error",
334
+ "core/require-calcite-import": "error",
335
+ "curly": "error",
336
+ "eqeqeq": ["error", "smart"],
337
+ "import-x/no-duplicates": "error",
338
+ "import-x/no-dynamic-require": ["error", { esmodule: true }],
339
+ "import-x/no-restricted-paths": [
340
+ "error",
341
+ {
342
+ // This is temporary. Once most of this config is merged with the
343
+ // root @arcgis/eslint-config, the core-specific rules can be moved
344
+ // into @webgis/monorepo-config
345
+ basePath: join(import.meta.dirname, "../../../../core-packages/core"),
346
+ zones: [
347
+ {
348
+ target: "src",
349
+ from: "src/identity/IdentityManager.ts",
350
+ message: "Use `kernel.id` or the `authMode` request option."
351
+ },
352
+ {
353
+ target: "src",
354
+ from: "src/layers/support/rasterFunctionUtils.ts",
355
+ message: "Import raster function creators directly instead."
356
+ },
357
+ {
358
+ target: "src",
359
+ from: "src/rest/geometryService.ts",
360
+ message: "Import the `geometryService` exports directly instead."
361
+ },
362
+ {
363
+ target: "src",
364
+ from: "src/rest/geoprocessor.ts",
365
+ message: "Import the geoprocessor exports directly instead."
366
+ },
367
+ {
368
+ target: "src",
369
+ from: "src/rest/locator.ts",
370
+ message: "Import the locator exports directly instead."
371
+ },
372
+ {
373
+ target: "src",
374
+ from: "src/rest/query.ts",
375
+ message: "Import the query exports directly instead"
376
+ },
377
+ {
378
+ target: "src",
379
+ from: "tests",
380
+ message: "Modules in /src should not import modules in /tests."
381
+ }
382
+ ]
383
+ }
384
+ ],
385
+ "import-x/no-useless-path-segments": "error",
386
+ "jsdoc/check-tag-names": [
387
+ "error",
388
+ { definedTags: ["tstype", "ignoreNilOnly", "noautocast", "collectionItemType"] }
389
+ ],
390
+ "jsdoc/check-types": "error",
391
+ // Ensure @readonly and @public is used without any content
392
+ "jsdoc/empty-tags": "error",
393
+ // Avoid /**\n ** something */
394
+ "jsdoc/no-multi-asterisks": ["error", { allowWhitespace: true }],
395
+ // Enforce each JSDoc line starts with *
396
+ "jsdoc/require-asterisk-prefix": "error",
397
+ // Enforce @param has param name
398
+ "jsdoc/require-param-name": "error",
399
+ "no-array-constructor": "off",
400
+ "no-async-promise-executor": "error",
401
+ "no-caller": "error",
402
+ "no-case-declarations": "error",
403
+ "no-cond-assign": "error",
404
+ "no-constant-binary-expression": "error",
405
+ "no-control-regex": "error",
406
+ "no-debugger": "error",
407
+ "no-duplicate-case": "error",
408
+ "no-else-return": "error",
409
+ "no-eval": "error",
410
+ "no-fallthrough": ["error", { reportUnusedFallthroughComment: false }],
411
+ "no-implied-eval": "error",
412
+ "no-inner-declarations": "error",
413
+ "no-labels": ["error", { allowLoop: true, allowSwitch: true }],
414
+ "no-new-func": "error",
415
+ "no-new-wrappers": "error",
416
+ "no-redeclare": "off",
417
+ "no-regex-spaces": "error",
418
+ "no-restricted-globals": ["error", "event", "name", "origin"],
419
+ "no-shadow-restricted-names": "error",
420
+ "no-throw-literal": "error",
421
+ "no-unsafe-finally": "error",
422
+ "no-unsafe-optional-chaining": "error",
423
+ "no-unused-expressions": "off",
424
+ "no-unused-vars": "off",
425
+ "no-useless-escape": "error",
426
+ "no-useless-rename": "error",
427
+ "no-var": "error",
428
+ "object-shorthand": "error",
429
+ "one-var": ["error", { initialized: "never" }],
430
+ "prefer-const": ["error", { destructuring: "all" }],
431
+ "prefer-exponentiation-operator": "error",
432
+ "radix": "error",
433
+ "regexp/control-character-escape": "error",
434
+ "regexp/no-dupe-characters-character-class": "error",
435
+ "regexp/no-dupe-disjunctions": "error",
436
+ "regexp/no-empty-alternative": "error",
437
+ "regexp/no-empty-capturing-group": "error",
438
+ "regexp/no-empty-character-class": "error",
439
+ "regexp/no-empty-group": "error",
440
+ "regexp/no-empty-lookarounds-assertion": "error",
441
+ "regexp/no-escape-backspace": "error",
442
+ "regexp/no-extra-lookaround-assertions": "error",
443
+ "regexp/no-invalid-regexp": "error",
444
+ "regexp/no-invisible-character": "error",
445
+ "regexp/no-lazy-ends": "error",
446
+ "regexp/no-misleading-unicode-character": "error",
447
+ "regexp/no-missing-g-flag": "error",
448
+ "regexp/no-obscure-range": "error",
449
+ "regexp/no-optional-assertion": "error",
450
+ "regexp/no-trivially-nested-assertion": "error",
451
+ "regexp/no-trivially-nested-quantifier": "error",
452
+ "regexp/no-useless-assertions": "error",
453
+ "regexp/no-useless-backreference": "error",
454
+ "regexp/no-useless-character-class": "error",
455
+ "regexp/no-useless-dollar-replacements": "error",
456
+ "regexp/no-useless-escape": "error",
457
+ // adds auto-fix and additional checks compared to `no-useless-escape`
458
+ "regexp/no-useless-lazy": "error",
459
+ "regexp/no-useless-quantifier": "error",
460
+ "regexp/no-useless-range": "error",
461
+ "regexp/no-useless-set-operand": "error",
462
+ "regexp/no-useless-string-literal": "error",
463
+ "regexp/no-useless-two-nums-quantifier": "error",
464
+ "regexp/optimal-quantifier-concatenation": "error",
465
+ "regexp/prefer-predefined-assertion": "error",
466
+ "regexp/prefer-range": "error",
467
+ "regexp/prefer-set-operation": "error",
468
+ "unicorn/consistent-date-clone": "error",
469
+ "unicorn/consistent-empty-array-spread": "error",
470
+ "unicorn/no-abusive-eslint-disable": "error",
471
+ "unicorn/no-accessor-recursion": "error",
472
+ "unicorn/no-await-in-promise-methods": "error",
473
+ "unicorn/no-instanceof-builtins": "error",
474
+ "unicorn/no-invalid-remove-event-listener": "error",
475
+ "unicorn/no-negation-in-equality-check": "error",
476
+ "unicorn/no-single-promise-in-promise-methods": "error",
477
+ "unicorn/no-typeof-undefined": "error",
478
+ "unicorn/no-unnecessary-array-flat-depth": "error",
479
+ "unicorn/no-unnecessary-array-splice-count": "error",
480
+ "unicorn/no-unnecessary-slice-end": "error",
481
+ "unicorn/no-useless-fallback-in-spread": "error",
482
+ "unicorn/no-useless-length-check": "error",
483
+ "unicorn/no-useless-promise-resolve-reject": "error",
484
+ "unicorn/no-useless-spread": "error",
485
+ "unicorn/no-useless-undefined": ["error", { checkArguments: false, checkArrowFunctionBody: false }],
486
+ "unicorn/prefer-array-find": "error",
487
+ "unicorn/prefer-array-flat": "error",
488
+ "unicorn/prefer-array-flat-map": "error",
489
+ "unicorn/prefer-array-index-of": "error",
490
+ "unicorn/prefer-array-some": "error",
491
+ "unicorn/prefer-blob-reading-methods": "error",
492
+ "unicorn/prefer-date-now": "error",
493
+ "unicorn/prefer-default-parameters": "error",
494
+ "unicorn/prefer-includes": "error",
495
+ "unicorn/prefer-logical-operator-over-ternary": "error",
496
+ "unicorn/prefer-negative-index": "error",
497
+ "unicorn/prefer-node-protocol": "error",
498
+ "unicorn/prefer-regexp-test": "error",
499
+ "unicorn/prefer-set-has": "error",
500
+ "unicorn/prefer-set-size": "error",
501
+ "unicorn/prefer-string-replace-all": "error",
502
+ "unicorn/prefer-string-slice": "error",
503
+ "unicorn/prefer-string-starts-ends-with": "error",
504
+ "unicorn/throw-new-error": "error",
505
+ "webgis/consistent-constructor-arguments": "error",
506
+ "webgis/consistent-mixin-syntax": "error",
507
+ "webgis/no-empty-catch": "error",
508
+ "webgis/no-kebab-case-props": "error",
509
+ "webgis/require-button-type": "error"
510
+ //#endregion
511
+ }
512
+ },
513
+ {
514
+ files: ["packages/core-packages/**/*.md"],
515
+ rules: disabledMarkdownRules
516
+ },
517
+ {
518
+ files: ["packages/core-packages/core/package.json"],
519
+ rules: {
520
+ // @typescript/native-preview temporarily uses the `beta` tag rather than a semver range.
521
+ "package-json/valid-devDependencies": "off"
522
+ }
523
+ },
524
+ {
525
+ files: ["packages/core-packages/**/*.d.ts"],
526
+ rules: {
527
+ "@typescript-eslint/naming-convention": "off"
528
+ // we can't enforce names in libraries
529
+ }
530
+ },
531
+ {
532
+ // Type-aware rules
533
+ files: ["packages/core-packages/**/*.{ts,tsx}"],
534
+ ignores: [...coreTypedRulesIgnoredFiles],
535
+ rules: {
536
+ // Disabled until https://github.com/typescript-eslint/typescript-eslint/pull/11267 is available.
537
+ "@typescript-eslint/await-thenable": "off",
538
+ "@typescript-eslint/no-array-delete": "error",
539
+ "@typescript-eslint/no-floating-promises": "error",
540
+ "@typescript-eslint/no-for-in-array": "error",
541
+ "@typescript-eslint/no-meaningless-void-operator": "error",
542
+ "@typescript-eslint/no-misused-promises": ["error", { checksVoidReturn: false }],
543
+ "@typescript-eslint/no-unsafe-unary-minus": "error",
544
+ "@typescript-eslint/prefer-find": "error",
545
+ "@typescript-eslint/prefer-includes": "error",
546
+ "@typescript-eslint/prefer-optional-chain": ["error", { requireNullish: true }],
547
+ "@typescript-eslint/prefer-string-starts-ends-with": "error",
548
+ "@typescript-eslint/return-await": ["error", "error-handling-correctness-only"]
549
+ }
550
+ },
551
+ {
552
+ // The base config enables typed rules for all .ts files.
553
+ // Core has .ts files that are not typed rules ready.
554
+ // Disable the typed rules for those.
555
+ files: [...coreTypedRulesIgnoredFiles],
556
+ languageOptions: {
557
+ parserOptions: {
558
+ projectService: false
559
+ }
560
+ },
561
+ rules: disabledCoreTypeCheckedRules
562
+ },
563
+ {
564
+ files: ["packages/core-packages/**/*.tsx"],
565
+ plugins: {
566
+ "perfectionist": perfectionistPlugin,
567
+ "react-jsx": reactJsxPlugin
568
+ },
569
+ rules: {
570
+ "perfectionist/sort-jsx-props": [
571
+ "error",
572
+ {
573
+ groups: ["unknown", "callback"],
574
+ customGroups: [{ groupName: "callback", elementNamePattern: "^on.+" }]
575
+ }
576
+ ],
577
+ "react-jsx/no-children-prop": "error",
578
+ "react-jsx/no-comment-textnodes": "error",
579
+ "react-jsx/no-useless-fragment": "error"
580
+ }
581
+ },
582
+ {
583
+ files: ["packages/core-packages/core/src/**/*.{ts,tsx}"],
584
+ rules: {
585
+ "core/no-invalid-declared-class": "error"
586
+ }
587
+ },
588
+ {
589
+ files: ["packages/core-packages/core/src/**/*.{ts,tsx}"],
590
+ ignores: ["packages/core-packages/core/src/**/*.d.ts"],
591
+ rules: {
592
+ "no-restricted-syntax": noRestrictedSyntax
593
+ }
594
+ },
595
+ {
596
+ files: ["packages/core-packages/core/src/**/*.{ts,tsx}"],
597
+ ignores: ["packages/core-packages/core/src/arcade/**", "packages/core-packages/core/src/widgets/**"],
598
+ rules: {
599
+ "webgis/no-instanceof": "error"
600
+ }
601
+ },
602
+ {
603
+ files: ["packages/core-packages/core/tests/**/*.{ts,tsx}"],
604
+ rules: {
605
+ "webgis/no-instanceof": "off",
606
+ "@typescript-eslint/no-restricted-imports": [
607
+ "error",
608
+ {
609
+ patterns: [
610
+ {
611
+ group: ["*.spec", "*.spec.*", "**/*.spec", "**/*.spec.*"],
612
+ message: "Do not import test suites (.spec) from other tests. Move shared helpers to tests/support (use the test-support/* alias)."
613
+ }
614
+ ]
615
+ }
616
+ ],
617
+ "core/spec-suite-filename": "error",
618
+ "no-restricted-syntax": [
619
+ ...noRestrictedSyntax,
620
+ {
621
+ message: "The { only: true } test option may be used during local testing, but can not be committed.",
622
+ selector: "CallExpression ObjectExpression Property[key.name='only'][value.value='true']"
623
+ },
624
+ {
625
+ message: "test.only may be used during local testing, but can not be committed.",
626
+ selector: "CallExpression[callee.type='MemberExpression'][callee.object.name='test'] > MemberExpression.callee > Identifier.property[name='only']"
627
+ },
628
+ {
629
+ message: "The { repeatUntilFailure: true } test option may be used during local testing, but can not be committed.",
630
+ selector: "CallExpression ObjectExpression Property[key.name='repeatUntilFailure'][value.value='true']"
631
+ },
632
+ {
633
+ message: "test.repeatUntilFailure may be used during local testing, but can not be committed.",
634
+ selector: "CallExpression[callee.type='MemberExpression'][callee.object.name='test'] > MemberExpression.callee > Identifier.property[name='repeatUntilFailure']"
635
+ },
636
+ {
637
+ selector: "CallExpression MemberExpression[object.name='has'][property.name='add']",
638
+ message: "Avoid adding has flags manually. Instead use the suite/test-level options to set has flags."
639
+ }
640
+ ],
641
+ "webgis/require-await-for-async-screenshot-assert": "error"
642
+ }
643
+ }
644
+ ];
645
+ export {
646
+ eslintConfigCore as default
647
+ };