exadev-eslint-config 2.12.3 → 2.13.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 CHANGED
@@ -170,6 +170,7 @@ Trailing arguments are arbitrary flat-config objects, appended in order after ev
170
170
  | `no-non-barrel-reexport` | ✓ | Re-exports belong only in a barrel. Catches the split form across two statements (`import { x } from './y'; export { x };` or `export default x;`) which no AST selector alone can match. Autofix deletes the export and the now-pointless import when it was the import's only use. Self-scopes away from any index file. |
171
171
  | `no-side-effects-in-index` | | A barrel file may contain only re-export statements -- nothing that could execute at import time. Self-scopes to any index file. |
172
172
  | `barrel-direct-siblings-only` | | A barrel may re-export only from a direct sibling (`./module`), never a nested path, parent, or bare package specifier (mode 3). |
173
+ | `no-control-flow` | | Bans `if`/`switch`/`for`/`for-in`/`for-of`/`while`/`do-while`/the ternary operator outright. Not part of `recommended` or `barrel` -- ordinary code legitimately needs control flow, so this is opt-in, wired via a consumer's own `files` glob for the specific packages that want it (a composition-root package selecting an adapter/strategy by a validated key, say): a lookup table replaces a branch, a declarative array method (`map`/`filter`/`some`/`every`/...) replaces a loop. Requires no type information. |
173
174
  | `no-pointless-reassignment` | ✓ | `const foo = bar` where both sides are plain identifiers and the alias adds no transformation. Autofix rewrites every read to the original name and deletes the declaration (including its `export` keyword, when exported). Still reported but deliberately not auto-fixable where collapsing the alias would change meaning: an explicit type annotation (`const exhaustive: never = item` -- the annotation is the point), a read where the original name is shadowed, a read as a shorthand object property, more than one declarator in the statement, or a source that is written to anywhere. |
174
175
  | `no-object-assign` | ✓/suggestion | `Object.assign` does not check a source object's properties against the target's declared types, unlike object spread. A fresh object-literal target autofixes to `{ ...target, ...source }`; mutating an existing reassignable binding offers a suggestion only (changes the object's identity); a `const` binding or a non-statement call site gets a plain report with no fix. |
175
176
  | `no-mutable-union-array-param` | ✓ | A function parameter typed as an array of a union (`(string \| number)[]`) accepts a narrower caller array (`number[]`) by covariance; calling `push`/`unshift`/`splice`/`fill`/`copyWithin` on it can then insert a value the caller's own array was never declared to hold. Autofix marks the parameter `readonly`, turning the mutating call into a real compile error to resolve deliberately. Requires no type information. |
package/dist/index.cjs CHANGED
@@ -159,7 +159,7 @@ function buildReactConfig(options = {}) {
159
159
  }
160
160
  //#endregion
161
161
  //#region package.json
162
- var version = "2.12.3";
162
+ var version = "2.13.0";
163
163
  //#endregion
164
164
  //#region src/rules/barrel-helpers.ts
165
165
  const INDEX_BASENAME$1 = /^index\.[cm]?[tj]sx?$/;
@@ -516,6 +516,76 @@ const noArrayIsArrayMutation = createRule$7({
516
516
  }
517
517
  });
518
518
  //#endregion
519
+ //#region src/rules/no-control-flow.ts
520
+ const noControlFlow = {
521
+ meta: {
522
+ type: "problem",
523
+ schema: [],
524
+ messages: {
525
+ ifStatement: "Use a lookup table, not an if/else branch.",
526
+ switchStatement: "Use a lookup table, not a switch branch.",
527
+ forStatement: "Use a lookup table or a declarative array method, not a for loop.",
528
+ forInStatement: "Use a lookup table or Object.entries, not a for-in loop.",
529
+ forOfStatement: "Use a declarative array method, not a for-of loop.",
530
+ whileStatement: "Use a lookup table or a declarative array method, not a while loop.",
531
+ doWhileStatement: "Use a lookup table or a declarative array method, not a do-while loop.",
532
+ conditionalExpression: "Use a lookup table, not a ternary."
533
+ }
534
+ },
535
+ create(context) {
536
+ return {
537
+ IfStatement(node) {
538
+ context.report({
539
+ node,
540
+ messageId: "ifStatement"
541
+ });
542
+ },
543
+ SwitchStatement(node) {
544
+ context.report({
545
+ node,
546
+ messageId: "switchStatement"
547
+ });
548
+ },
549
+ ForStatement(node) {
550
+ context.report({
551
+ node,
552
+ messageId: "forStatement"
553
+ });
554
+ },
555
+ ForInStatement(node) {
556
+ context.report({
557
+ node,
558
+ messageId: "forInStatement"
559
+ });
560
+ },
561
+ ForOfStatement(node) {
562
+ context.report({
563
+ node,
564
+ messageId: "forOfStatement"
565
+ });
566
+ },
567
+ WhileStatement(node) {
568
+ context.report({
569
+ node,
570
+ messageId: "whileStatement"
571
+ });
572
+ },
573
+ DoWhileStatement(node) {
574
+ context.report({
575
+ node,
576
+ messageId: "doWhileStatement"
577
+ });
578
+ },
579
+ ConditionalExpression(node) {
580
+ context.report({
581
+ node,
582
+ messageId: "conditionalExpression"
583
+ });
584
+ }
585
+ };
586
+ }
587
+ };
588
+ //#endregion
519
589
  //#region src/rules/no-enum-number-widening.ts
520
590
  const noEnumNumberWidening = _typescript_eslint_utils.ESLintUtils.RuleCreator((name) => `https://github.com/ExaDev/eslint-config/blob/main/src/rules/${name}.ts`)({
521
591
  name: "no-enum-number-widening",
@@ -1356,6 +1426,7 @@ const plugin = {
1356
1426
  "barrel-direct-siblings-only": barrelDirectSiblingsOnly,
1357
1427
  "barrel-policy": barrelPolicy,
1358
1428
  "no-array-isarray-mutation": noArrayIsArrayMutation,
1429
+ "no-control-flow": noControlFlow,
1359
1430
  "no-enum-number-widening": noEnumNumberWidening,
1360
1431
  "no-enum-reverse-lookup-widening": noEnumReverseLookupWidening,
1361
1432
  "no-index-files": noIndexFiles,
package/dist/index.js CHANGED
@@ -128,7 +128,7 @@ function buildReactConfig(options = {}) {
128
128
  }
129
129
  //#endregion
130
130
  //#region package.json
131
- var version = "2.12.3";
131
+ var version = "2.13.0";
132
132
  //#endregion
133
133
  //#region src/rules/barrel-helpers.ts
134
134
  const INDEX_BASENAME$1 = /^index\.[cm]?[tj]sx?$/;
@@ -485,6 +485,76 @@ const noArrayIsArrayMutation = createRule$7({
485
485
  }
486
486
  });
487
487
  //#endregion
488
+ //#region src/rules/no-control-flow.ts
489
+ const noControlFlow = {
490
+ meta: {
491
+ type: "problem",
492
+ schema: [],
493
+ messages: {
494
+ ifStatement: "Use a lookup table, not an if/else branch.",
495
+ switchStatement: "Use a lookup table, not a switch branch.",
496
+ forStatement: "Use a lookup table or a declarative array method, not a for loop.",
497
+ forInStatement: "Use a lookup table or Object.entries, not a for-in loop.",
498
+ forOfStatement: "Use a declarative array method, not a for-of loop.",
499
+ whileStatement: "Use a lookup table or a declarative array method, not a while loop.",
500
+ doWhileStatement: "Use a lookup table or a declarative array method, not a do-while loop.",
501
+ conditionalExpression: "Use a lookup table, not a ternary."
502
+ }
503
+ },
504
+ create(context) {
505
+ return {
506
+ IfStatement(node) {
507
+ context.report({
508
+ node,
509
+ messageId: "ifStatement"
510
+ });
511
+ },
512
+ SwitchStatement(node) {
513
+ context.report({
514
+ node,
515
+ messageId: "switchStatement"
516
+ });
517
+ },
518
+ ForStatement(node) {
519
+ context.report({
520
+ node,
521
+ messageId: "forStatement"
522
+ });
523
+ },
524
+ ForInStatement(node) {
525
+ context.report({
526
+ node,
527
+ messageId: "forInStatement"
528
+ });
529
+ },
530
+ ForOfStatement(node) {
531
+ context.report({
532
+ node,
533
+ messageId: "forOfStatement"
534
+ });
535
+ },
536
+ WhileStatement(node) {
537
+ context.report({
538
+ node,
539
+ messageId: "whileStatement"
540
+ });
541
+ },
542
+ DoWhileStatement(node) {
543
+ context.report({
544
+ node,
545
+ messageId: "doWhileStatement"
546
+ });
547
+ },
548
+ ConditionalExpression(node) {
549
+ context.report({
550
+ node,
551
+ messageId: "conditionalExpression"
552
+ });
553
+ }
554
+ };
555
+ }
556
+ };
557
+ //#endregion
488
558
  //#region src/rules/no-enum-number-widening.ts
489
559
  const noEnumNumberWidening = ESLintUtils.RuleCreator((name) => `https://github.com/ExaDev/eslint-config/blob/main/src/rules/${name}.ts`)({
490
560
  name: "no-enum-number-widening",
@@ -1325,6 +1395,7 @@ const plugin = {
1325
1395
  "barrel-direct-siblings-only": barrelDirectSiblingsOnly,
1326
1396
  "barrel-policy": barrelPolicy,
1327
1397
  "no-array-isarray-mutation": noArrayIsArrayMutation,
1398
+ "no-control-flow": noControlFlow,
1328
1399
  "no-enum-number-widening": noEnumNumberWidening,
1329
1400
  "no-enum-reverse-lookup-widening": noEnumReverseLookupWidening,
1330
1401
  "no-index-files": noIndexFiles,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exadev-eslint-config",
3
- "version": "2.12.3",
3
+ "version": "2.13.0",
4
4
  "description": "Shared custom ESLint rules and plugin for ExaDev projects",
5
5
  "type": "module",
6
6
  "sideEffects": false,