exadev-eslint-config 2.6.2 → 2.7.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/README.md +3 -3
- package/dist/index.cjs +18 -13
- package/dist/index.js +18 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Consumers need `eslint >=10.0.0` and `typescript-eslint >=8.0.0` as required pee
|
|
|
16
16
|
pnpm add -D @exadev/eslint-config typescript-eslint eslint
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
The default export is the full, type-checked ruleset: typescript-eslint's `
|
|
19
|
+
The default export is the full, type-checked ruleset: typescript-eslint's `strictTypeChecked` + `stylisticTypeChecked` presets (`strictTypeChecked` subsumes `recommendedTypeChecked`, so it already includes `no-deprecated`, `no-misused-spread`, `no-mixed-enums`, `no-unnecessary-condition`, `use-unknown-in-catch-callback-variable`, `return-await`, `related-getter-setter-pairs`, `no-unnecessary-type-parameters`, and more -- those are no longer re-listed below), `exadev/barrel-policy` at `mode: 'banned'` (see [Barrel policy](#barrel-policy)), `exadev/no-object-assign`, `exadev/no-mutable-union-array-param`, `exadev/no-array-isarray-mutation`, `exadev/no-enum-number-widening`, `exadev/no-enum-reverse-lookup-widening`, `exadev/no-map-instanceof-mutation`, `exadev/no-set-instanceof-mutation`, `exadev/prefer-readonly-array-param`, `exadev/prefer-readonly-object-param`, `exadev/prefer-numeric-sort-compare`, `exadev/no-pointless-reassignment`, `linterOptions.noInlineConfig`, `@typescript-eslint/consistent-type-assertions` banning all type assertions, `@typescript-eslint/consistent-type-imports`, `@typescript-eslint/consistent-type-exports`, `@typescript-eslint/no-non-null-assertion` banning the `!` operator (the same manual-override escape hatch as a type assertion, under a different spelling), `@typescript-eslint/ban-ts-comment` banning `@ts-expect-error` outright, `@typescript-eslint/method-signature-style` set to `'property'` (method-shorthand signatures are checked bivariantly under `strictFunctionTypes`, which is unsound), `@typescript-eslint/prefer-readonly`, `@typescript-eslint/promise-function-async`, `@typescript-eslint/require-array-sort-compare`, `@typescript-eslint/switch-exhaustiveness-check`, `@typescript-eslint/strict-boolean-expressions` at the rule's own bare defaults (an unambiguous non-nullable truthy check stays allowed; an ambiguous nullable check does not), and `@typescript-eslint/no-magic-numbers` tuned to exempt array indexes, enum members, readonly class properties, default parameter values, and the handful of universally-idiomatic bare numbers (`-1`, `0`, `1`, `2`) -- the type-assertion and ts-comment rules are relaxed in test files, and `no-magic-numbers` is not (see below). Spread it directly into `tseslint.config(...)`:
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
22
|
// eslint.config.ts
|
|
@@ -41,7 +41,7 @@ export default tseslint.config(
|
|
|
41
41
|
{ rules: { 'exadev/barrel-policy': ['error', { mode: 'single' }] } }, // this package keeps its barrel
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
`
|
|
44
|
+
`strictTypeChecked` subsumes both typescript-eslint's plain `recommended` and `recommendedTypeChecked` outright (every rule in each is also present in `strictTypeChecked`), and its base config registers the `@typescript-eslint` plugin and sets `languageOptions.parser` itself. That is why **you must remove your own `...tseslint.configs.recommended`/`recommendedTypeChecked`/`strictTypeChecked`/`stylisticTypeChecked` spreads** -- flat config rejects two different plugin object instances registered under the same namespace. You still supply `languageOptions.parserOptions.project`/`projectService` pointing at your own tsconfig(s).
|
|
45
45
|
|
|
46
46
|
**Test files (`**/*.{test,spec}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}`) get two narrow relaxations of this package's own additions, and only those two.** `@ts-expect-error` reverts to `allow-with-description` (a compile-time-only assertion of a type failure is a legitimate test pattern; `@ts-ignore`/`@ts-nocheck` stay banned since `@ts-expect-error` is strictly better). `consistent-type-assertions` relaxes to `assertionStyle: 'as'` (the legacy `<Type>value` form stays banned everywhere). Nothing inherited from the presets is relaxed.
|
|
47
47
|
|
|
@@ -157,7 +157,7 @@ The `lint`/`typecheck`/`test`/`build` npm scripts wrap turbo tasks named `_lint`
|
|
|
157
157
|
|
|
158
158
|
`src/plugin.ts` builds an `ESLint.Plugin` (ESLint's own type) combining `src/rules/` into a flat `rules` map. `configs.recommended` and `configs.barrel` are getters in the object literal -- each references the fully-built `plugin` (`plugins: { exadev: plugin }`), which a plain property initializer can't do mid-construction. `recommended` ships `barrel-policy` at `mode: 'banned'`; `barrel` at `mode: 'single'`.
|
|
159
159
|
|
|
160
|
-
`src/recommended-type-checked.ts` bundles typescript-eslint's `
|
|
160
|
+
`src/recommended-type-checked.ts` bundles typescript-eslint's `strictTypeChecked` + `stylisticTypeChecked` alongside this plugin's rules into a flat config array. Its value is typed as `ConfigArrayValue = Extract<ConfigValue, unknown[]>` (the array-only member of ESLint's own config-value union), because annotating with the wider union broke `...exadev` with `TS2488`.
|
|
161
161
|
|
|
162
162
|
`src/index.ts` is the entry point: `export { default } from './recommended-type-checked'; export { default as plugin } from './plugin';`. Both exports share one root module, so importing `{ plugin }` alone still resolves `typescript-eslint` via the sibling re-export -- an accepted trade-off (an earlier separate-subpath split proved more awkward in practice).
|
|
163
163
|
|
package/dist/index.cjs
CHANGED
|
@@ -32,7 +32,7 @@ let typescript = require("typescript");
|
|
|
32
32
|
typescript = __toESM(typescript, 1);
|
|
33
33
|
let ts_api_utils = require("ts-api-utils");
|
|
34
34
|
//#region package.json
|
|
35
|
-
var version = "2.
|
|
35
|
+
var version = "2.7.0";
|
|
36
36
|
//#endregion
|
|
37
37
|
//#region src/rules/barrel-helpers.ts
|
|
38
38
|
const INDEX_BASENAME$1 = /^index\.[cm]?[tj]sx?$/;
|
|
@@ -220,7 +220,9 @@ const barrelPolicy = {
|
|
|
220
220
|
});
|
|
221
221
|
}
|
|
222
222
|
},
|
|
223
|
-
ImportDeclaration: (node) =>
|
|
223
|
+
ImportDeclaration: (node) => {
|
|
224
|
+
detector.visitImport(node);
|
|
225
|
+
},
|
|
224
226
|
ExportNamedDeclaration(node) {
|
|
225
227
|
detector.visitExportNamed(node);
|
|
226
228
|
if (hasSource(node)) {
|
|
@@ -248,7 +250,9 @@ const barrelPolicy = {
|
|
|
248
250
|
data: { source }
|
|
249
251
|
});
|
|
250
252
|
},
|
|
251
|
-
ExportDefaultDeclaration: (node) =>
|
|
253
|
+
ExportDefaultDeclaration: (node) => {
|
|
254
|
+
detector.visitExportDefault(node);
|
|
255
|
+
},
|
|
252
256
|
"Program:exit"() {
|
|
253
257
|
for (const violation of detector.violations()) if (isPermittedBarrel(filename, mode)) {
|
|
254
258
|
if (mode === "siblings") {
|
|
@@ -702,9 +706,15 @@ const noNonBarrelReexport = {
|
|
|
702
706
|
if (isIndexFile(context.filename)) return {};
|
|
703
707
|
const detector = createSplitReexportDetector();
|
|
704
708
|
return {
|
|
705
|
-
ImportDeclaration: (node) =>
|
|
706
|
-
|
|
707
|
-
|
|
709
|
+
ImportDeclaration: (node) => {
|
|
710
|
+
detector.visitImport(node);
|
|
711
|
+
},
|
|
712
|
+
ExportNamedDeclaration: (node) => {
|
|
713
|
+
detector.visitExportNamed(node);
|
|
714
|
+
},
|
|
715
|
+
ExportDefaultDeclaration: (node) => {
|
|
716
|
+
detector.visitExportDefault(node);
|
|
717
|
+
},
|
|
708
718
|
"Program:exit"() {
|
|
709
719
|
const { sourceCode } = context;
|
|
710
720
|
for (const violation of detector.violations()) if (violation.kind === "named") {
|
|
@@ -1245,7 +1255,7 @@ const plugin = {
|
|
|
1245
1255
|
//#region src/recommended-type-checked.ts
|
|
1246
1256
|
const TEST_FILE_PATTERNS = "**/*.{test,spec}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}";
|
|
1247
1257
|
const recommendedTypeChecked = [
|
|
1248
|
-
...typescript_eslint.default.configs.
|
|
1258
|
+
...typescript_eslint.default.configs.strictTypeChecked,
|
|
1249
1259
|
...typescript_eslint.default.configs.stylisticTypeChecked,
|
|
1250
1260
|
{
|
|
1251
1261
|
plugins: { exadev: plugin },
|
|
@@ -1268,7 +1278,6 @@ const recommendedTypeChecked = [
|
|
|
1268
1278
|
"@typescript-eslint/consistent-type-exports": "error",
|
|
1269
1279
|
"@typescript-eslint/consistent-type-imports": "error",
|
|
1270
1280
|
"@typescript-eslint/method-signature-style": ["error", "property"],
|
|
1271
|
-
"@typescript-eslint/no-deprecated": "error",
|
|
1272
1281
|
"@typescript-eslint/no-magic-numbers": ["error", {
|
|
1273
1282
|
ignore: [
|
|
1274
1283
|
-1,
|
|
@@ -1281,16 +1290,12 @@ const recommendedTypeChecked = [
|
|
|
1281
1290
|
ignoreReadonlyClassProperties: true,
|
|
1282
1291
|
ignoreDefaultValues: true
|
|
1283
1292
|
}],
|
|
1284
|
-
"@typescript-eslint/no-misused-spread": "error",
|
|
1285
|
-
"@typescript-eslint/no-mixed-enums": "error",
|
|
1286
1293
|
"@typescript-eslint/no-non-null-assertion": "error",
|
|
1287
|
-
"@typescript-eslint/no-unnecessary-condition": "error",
|
|
1288
1294
|
"@typescript-eslint/prefer-readonly": "error",
|
|
1289
1295
|
"@typescript-eslint/promise-function-async": "error",
|
|
1290
1296
|
"@typescript-eslint/require-array-sort-compare": "error",
|
|
1291
1297
|
"@typescript-eslint/strict-boolean-expressions": "error",
|
|
1292
|
-
"@typescript-eslint/switch-exhaustiveness-check": "error"
|
|
1293
|
-
"@typescript-eslint/use-unknown-in-catch-callback-variable": "error"
|
|
1298
|
+
"@typescript-eslint/switch-exhaustiveness-check": "error"
|
|
1294
1299
|
}
|
|
1295
1300
|
},
|
|
1296
1301
|
{
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { AST_NODE_TYPES, ESLintUtils, TSESLint } from "@typescript-eslint/utils"
|
|
|
4
4
|
import * as ts from "typescript";
|
|
5
5
|
import { isPropertyReadonlyInType, isTypeReference } from "ts-api-utils";
|
|
6
6
|
//#region package.json
|
|
7
|
-
var version = "2.
|
|
7
|
+
var version = "2.7.0";
|
|
8
8
|
//#endregion
|
|
9
9
|
//#region src/rules/barrel-helpers.ts
|
|
10
10
|
const INDEX_BASENAME$1 = /^index\.[cm]?[tj]sx?$/;
|
|
@@ -192,7 +192,9 @@ const barrelPolicy = {
|
|
|
192
192
|
});
|
|
193
193
|
}
|
|
194
194
|
},
|
|
195
|
-
ImportDeclaration: (node) =>
|
|
195
|
+
ImportDeclaration: (node) => {
|
|
196
|
+
detector.visitImport(node);
|
|
197
|
+
},
|
|
196
198
|
ExportNamedDeclaration(node) {
|
|
197
199
|
detector.visitExportNamed(node);
|
|
198
200
|
if (hasSource(node)) {
|
|
@@ -220,7 +222,9 @@ const barrelPolicy = {
|
|
|
220
222
|
data: { source }
|
|
221
223
|
});
|
|
222
224
|
},
|
|
223
|
-
ExportDefaultDeclaration: (node) =>
|
|
225
|
+
ExportDefaultDeclaration: (node) => {
|
|
226
|
+
detector.visitExportDefault(node);
|
|
227
|
+
},
|
|
224
228
|
"Program:exit"() {
|
|
225
229
|
for (const violation of detector.violations()) if (isPermittedBarrel(filename, mode)) {
|
|
226
230
|
if (mode === "siblings") {
|
|
@@ -674,9 +678,15 @@ const noNonBarrelReexport = {
|
|
|
674
678
|
if (isIndexFile(context.filename)) return {};
|
|
675
679
|
const detector = createSplitReexportDetector();
|
|
676
680
|
return {
|
|
677
|
-
ImportDeclaration: (node) =>
|
|
678
|
-
|
|
679
|
-
|
|
681
|
+
ImportDeclaration: (node) => {
|
|
682
|
+
detector.visitImport(node);
|
|
683
|
+
},
|
|
684
|
+
ExportNamedDeclaration: (node) => {
|
|
685
|
+
detector.visitExportNamed(node);
|
|
686
|
+
},
|
|
687
|
+
ExportDefaultDeclaration: (node) => {
|
|
688
|
+
detector.visitExportDefault(node);
|
|
689
|
+
},
|
|
680
690
|
"Program:exit"() {
|
|
681
691
|
const { sourceCode } = context;
|
|
682
692
|
for (const violation of detector.violations()) if (violation.kind === "named") {
|
|
@@ -1217,7 +1227,7 @@ const plugin = {
|
|
|
1217
1227
|
//#region src/recommended-type-checked.ts
|
|
1218
1228
|
const TEST_FILE_PATTERNS = "**/*.{test,spec}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}";
|
|
1219
1229
|
const recommendedTypeChecked = [
|
|
1220
|
-
...tseslint.configs.
|
|
1230
|
+
...tseslint.configs.strictTypeChecked,
|
|
1221
1231
|
...tseslint.configs.stylisticTypeChecked,
|
|
1222
1232
|
{
|
|
1223
1233
|
plugins: { exadev: plugin },
|
|
@@ -1240,7 +1250,6 @@ const recommendedTypeChecked = [
|
|
|
1240
1250
|
"@typescript-eslint/consistent-type-exports": "error",
|
|
1241
1251
|
"@typescript-eslint/consistent-type-imports": "error",
|
|
1242
1252
|
"@typescript-eslint/method-signature-style": ["error", "property"],
|
|
1243
|
-
"@typescript-eslint/no-deprecated": "error",
|
|
1244
1253
|
"@typescript-eslint/no-magic-numbers": ["error", {
|
|
1245
1254
|
ignore: [
|
|
1246
1255
|
-1,
|
|
@@ -1253,16 +1262,12 @@ const recommendedTypeChecked = [
|
|
|
1253
1262
|
ignoreReadonlyClassProperties: true,
|
|
1254
1263
|
ignoreDefaultValues: true
|
|
1255
1264
|
}],
|
|
1256
|
-
"@typescript-eslint/no-misused-spread": "error",
|
|
1257
|
-
"@typescript-eslint/no-mixed-enums": "error",
|
|
1258
1265
|
"@typescript-eslint/no-non-null-assertion": "error",
|
|
1259
|
-
"@typescript-eslint/no-unnecessary-condition": "error",
|
|
1260
1266
|
"@typescript-eslint/prefer-readonly": "error",
|
|
1261
1267
|
"@typescript-eslint/promise-function-async": "error",
|
|
1262
1268
|
"@typescript-eslint/require-array-sort-compare": "error",
|
|
1263
1269
|
"@typescript-eslint/strict-boolean-expressions": "error",
|
|
1264
|
-
"@typescript-eslint/switch-exhaustiveness-check": "error"
|
|
1265
|
-
"@typescript-eslint/use-unknown-in-catch-callback-variable": "error"
|
|
1270
|
+
"@typescript-eslint/switch-exhaustiveness-check": "error"
|
|
1266
1271
|
}
|
|
1267
1272
|
},
|
|
1268
1273
|
{
|