lint-suite 1.2.3 → 1.3.1

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/index.js CHANGED
@@ -30,6 +30,23 @@ var angularTemplate = defineConfig([
30
30
  "@angular-eslint/template/no-nested-tags": "error",
31
31
  "@angular-eslint/template/use-track-by-function": "error",
32
32
  "@angular-eslint/template/label-has-associated-control": "error",
33
+ "@angular-eslint/template/prefer-at-else": "error",
34
+ // v21: @if/@else syntax
35
+ "@angular-eslint/template/prefer-at-empty": "error",
36
+ // v21: @for/@empty syntax
37
+ "@angular-eslint/template/prefer-contextual-for-variables": "error",
38
+ // v21: Use $index, $first, etc.
39
+ "@angular-eslint/template/no-empty-control-flow": "error",
40
+ // v21: Catch incomplete refactoring
41
+ "@angular-eslint/template/prefer-class-binding": "error",
42
+ // v21.2.0: Prefer [class] over ngClass
43
+ "@angular-eslint/template/prefer-static-string-properties": "error",
44
+ // Reduce change detection
45
+ "@angular-eslint/template/conditional-complexity": [
46
+ "warn",
47
+ { maxComplexity: 5 }
48
+ ],
49
+ // Template readability
33
50
  "@angular-eslint/template/attributes-order": [
34
51
  "error",
35
52
  {
@@ -76,7 +93,17 @@ var angular = defineConfig2([
76
93
  "@angular-eslint/use-injectable-provided-in": "error",
77
94
  "@angular-eslint/prefer-signal-model": "error",
78
95
  "@angular-eslint/no-uncalled-signals": "error",
79
- "@angular-eslint/prefer-host-metadata-property": "error"
96
+ "@angular-eslint/prefer-host-metadata-property": "error",
97
+ "@angular-eslint/no-implicit-take-until-destroyed": "error",
98
+ // v21.2.0: Enforce explicit DestroyRef
99
+ "@angular-eslint/no-async-lifecycle-method": "error",
100
+ // Prevent async lifecycle hooks
101
+ "@angular-eslint/prefer-output-readonly": "warn",
102
+ // Prevent accidental reassignment
103
+ "@angular-eslint/prefer-output-emitter-ref": "warn",
104
+ // Modern output() function over @Output()
105
+ "@angular-eslint/sort-lifecycle-methods": "warn"
106
+ // Consistent lifecycle method ordering
80
107
  }
81
108
  }
82
109
  ]);
@@ -139,7 +166,10 @@ var base = defineConfig3([
139
166
  "no-useless-concat": "error",
140
167
  "prefer-template": "error",
141
168
  "no-nested-ternary": "error",
142
- "no-return-await": "error",
169
+ "no-useless-assignment": "error",
170
+ // NEW: Catch unused assignments (ESLint v9)
171
+ "no-object-constructor": "error",
172
+ // Disallow new Object() without arguments
143
173
  "no-else-return": ["error", { allowElseIf: false }],
144
174
  // Prefer early returns
145
175
  "no-multi-assign": "error",
@@ -321,9 +351,29 @@ import { defineConfig as defineConfig5 } from "eslint/config";
321
351
  var jest = defineConfig5([
322
352
  {
323
353
  files: ["**/*.spec.ts", "**/*.spec.js"],
324
- extends: [jestEslint.configs["flat/all"]],
354
+ extends: [jestEslint.configs["flat/recommended"]],
325
355
  rules: {
326
- "jest/no-done-callback": "off"
356
+ "jest/no-done-callback": "off",
357
+ // Elevated from recommended defaults
358
+ "jest/no-focused-tests": "error",
359
+ "jest/no-identical-title": "error",
360
+ "jest/valid-expect": "error",
361
+ // Style rules (selective additions from flat/style)
362
+ "jest/prefer-to-be": "warn",
363
+ "jest/prefer-to-contain": "warn",
364
+ "jest/prefer-to-have-length": "warn",
365
+ // Best practice additions
366
+ "jest/consistent-test-it": ["error", { fn: "it" }],
367
+ "jest/prefer-comparison-matcher": "error",
368
+ "jest/prefer-equality-matcher": "error",
369
+ "jest/prefer-hooks-on-top": "error",
370
+ "jest/prefer-spy-on": "error",
371
+ "jest/prefer-strict-equal": "warn",
372
+ "jest/prefer-mock-promise-shorthand": "error",
373
+ "jest/no-conditional-in-test": "warn",
374
+ "jest/no-duplicate-hooks": "error",
375
+ "jest/no-test-return-statement": "error",
376
+ "jest/require-to-throw-message": "warn"
327
377
  }
328
378
  }
329
379
  ]);
@@ -335,13 +385,22 @@ var json = defineConfig6([
335
385
  {
336
386
  files: ["**/*.json"],
337
387
  extends: [jsonEslint.configs.recommended]
388
+ },
389
+ {
390
+ files: ["**/tsconfig*.json", "**/.vscode/*.json"],
391
+ extends: [jsonEslint.configs["recommended-with-comments"]]
338
392
  }
339
393
  ]);
340
394
 
395
+ // packages/lint-suite/src/lib/prettier.ts
396
+ import eslintConfigPrettier from "eslint-config-prettier";
397
+ import { defineConfig as defineConfig7 } from "eslint/config";
398
+ var prettier = defineConfig7([eslintConfigPrettier]);
399
+
341
400
  // packages/lint-suite/src/lib/rxjs.ts
342
401
  import rxjsEslint from "@smarttools/eslint-plugin-rxjs";
343
- import { defineConfig as defineConfig7 } from "eslint/config";
344
- var rxjs = defineConfig7([
402
+ import { defineConfig as defineConfig8 } from "eslint/config";
403
+ var rxjs = defineConfig8([
345
404
  {
346
405
  files: [
347
406
  "**/*.js",
@@ -397,25 +456,38 @@ var rxjs = defineConfig7([
397
456
  "rxjs/no-unsafe-first": "error",
398
457
  "rxjs/no-topromise": "error",
399
458
  "rxjs/throw-error": "error",
400
- "rxjs/no-async-subscribe": "off"
459
+ "rxjs/no-async-subscribe": "off",
460
+ "rxjs/no-exposed-subjects": "error",
461
+ // Enforce subject encapsulation
462
+ "rxjs/no-cyclic-action": "error",
463
+ // Prevent infinite loops in NgRx effects
464
+ "rxjs/no-subscribe-handlers": "warn"
465
+ // Prefer observer objects (complements prefer-observer)
401
466
  }
402
467
  },
403
468
  {
404
469
  files: ["**/*.spec.ts", "**/*.test.ts", "**/*.spec.js", "**/*.test.js"],
405
470
  rules: {
406
- "rxjs/no-ignored-subscription": "off"
471
+ "rxjs/no-ignored-subscription": "off",
472
+ "rxjs/no-subscribe-handlers": "off"
407
473
  }
408
474
  }
409
475
  ]);
410
476
 
411
477
  // packages/lint-suite/src/lib/storybook.ts
412
478
  import storybookEslint from "eslint-plugin-storybook";
413
- import { defineConfig as defineConfig8 } from "eslint/config";
414
- var storybook = defineConfig8([
479
+ import { defineConfig as defineConfig9 } from "eslint/config";
480
+ var storybook = defineConfig9([
415
481
  {
416
482
  ignores: ["!.storybook"],
417
483
  files: ["**/*.stories.ts"],
418
- extends: [storybookEslint.configs["flat/recommended"]]
484
+ extends: [storybookEslint.configs["flat/recommended"]],
485
+ rules: {
486
+ "storybook/csf-component": "warn",
487
+ // Ensure component property is set
488
+ "storybook/no-stories-of": "error"
489
+ // Prevent deprecated storiesOf API
490
+ }
419
491
  }
420
492
  ]);
421
493
 
@@ -423,7 +495,7 @@ var storybook = defineConfig8([
423
495
  import { configs as configs5 } from "@nx/eslint-plugin";
424
496
  import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
425
497
  import importPluginX2 from "eslint-plugin-import-x";
426
- import { defineConfig as defineConfig9 } from "eslint/config";
498
+ import { defineConfig as defineConfig10 } from "eslint/config";
427
499
 
428
500
  // packages/lint-suite/src/lib/rules/explicit-accessibility.ts
429
501
  import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
@@ -564,7 +636,7 @@ var localTypescriptRules = {
564
636
  "explicit-accessibility": explicit_accessibility_default
565
637
  }
566
638
  };
567
- var typescript = defineConfig9([
639
+ var typescript = defineConfig10([
568
640
  // NOTE: Checks for 'prettier' and 'eslint-plugin-prettier'
569
641
  {
570
642
  files: ["**/*.ts", "**/*.tsx", "**/*.cts", "**/*.mts"],
@@ -590,6 +662,13 @@ var typescript = defineConfig9([
590
662
  "@typescript-eslint/no-unsafe-member-access": "error",
591
663
  "@typescript-eslint/no-unsafe-return": "error",
592
664
  "@typescript-eslint/no-unsafe-argument": "error",
665
+ // New v8 type-safety rules (replacements for deprecated ban-types)
666
+ "@typescript-eslint/no-empty-object-type": "error",
667
+ // Bans confusing {} type
668
+ "@typescript-eslint/no-unsafe-function-type": "error",
669
+ // Bans Function type
670
+ "@typescript-eslint/no-wrapper-object-types": "error",
671
+ // Bans Number, String, Boolean wrappers
593
672
  // B. Explicit Annotations (partially covered, explicit module boundaries is key)
594
673
  "@typescript-eslint/explicit-module-boundary-types": "error",
595
674
  // Consider enabling if maximum explicitness is desired, even if verbose:
@@ -610,8 +689,14 @@ var typescript = defineConfig9([
610
689
  // E. Best Practices & Potential Errors (Some covered by presets, fine-tuning here)
611
690
  "@typescript-eslint/no-inferrable-types": "warn",
612
691
  // Keep as warn or disable if inference is preferred
613
- "@typescript-eslint/no-var-requires": "error",
614
- // Use ES modules
692
+ "@typescript-eslint/no-require-imports": "error",
693
+ // Use ES modules (replaces deprecated no-var-requires)
694
+ "@typescript-eslint/only-throw-error": "error",
695
+ // Replaces deprecated no-throw-literal
696
+ "@typescript-eslint/no-array-delete": "error",
697
+ // Prevents delete arr[0]
698
+ "@typescript-eslint/return-await": ["error", "in-try-catch"],
699
+ // Better stack traces in try/catch
615
700
  "@typescript-eslint/require-await": "error",
616
701
  "@typescript-eslint/restrict-template-expressions": [
617
702
  "error",
@@ -631,6 +716,32 @@ var typescript = defineConfig9([
631
716
  "@typescript-eslint/no-useless-constructor": "error",
632
717
  "@typescript-eslint/dot-notation": ["error", { allowKeywords: true }],
633
718
  // Prefer dot notation where possible
719
+ // Strict type-checked rules
720
+ "@typescript-eslint/no-unnecessary-condition": "error",
721
+ // Catches always-true/false conditions
722
+ "@typescript-eslint/no-confusing-void-expression": "error",
723
+ // Prevent confusing void usage
724
+ "@typescript-eslint/no-dynamic-delete": "error",
725
+ // Use Map instead of delete obj[key]
726
+ "@typescript-eslint/no-extraneous-class": ["error", { allowWithDecorator: true }],
727
+ // Allow Angular classes
728
+ "@typescript-eslint/no-invalid-void-type": "error",
729
+ // Restrict void to return types
730
+ "@typescript-eslint/unified-signatures": "error",
731
+ // Merge overloads where possible
732
+ "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
733
+ // Forbids foo! ?? bar
734
+ // Stylistic type-checked rules
735
+ "@typescript-eslint/prefer-find": "error",
736
+ // Use find() instead of filter()[0]
737
+ "@typescript-eslint/prefer-for-of": "error",
738
+ // Modern iteration
739
+ "@typescript-eslint/prefer-includes": "error",
740
+ // indexOf() → includes()
741
+ "@typescript-eslint/prefer-string-starts-ends-with": "error",
742
+ // Modern string methods
743
+ "@typescript-eslint/prefer-regexp-exec": "error",
744
+ // Better regex performance
634
745
  // F. Consistency & Style (Some covered by stylistic-type-checked)
635
746
  "@typescript-eslint/consistent-type-assertions": [
636
747
  "error",
@@ -732,10 +843,18 @@ var typescript = defineConfig9([
732
843
  "import-x/no-unresolved": "error",
733
844
  "import-x/no-duplicates": "error",
734
845
  "import-x/prefer-default-export": "off",
735
- "import-x/no-useless-path-segments": "error",
846
+ "import-x/no-useless-path-segments": ["error", { noUselessIndex: true }],
736
847
  "import-x/newline-after-import": "error",
737
848
  "import-x/first": "error",
738
- "import-x/no-mutable-exports": "error"
849
+ "import-x/no-mutable-exports": "error",
850
+ "import-x/no-self-import": "error",
851
+ // Prevents modules importing themselves
852
+ "import-x/no-cycle": ["error", { maxDepth: 2, ignoreExternal: true }],
853
+ // Prevents circular dependencies
854
+ "import-x/consistent-type-specifier-style": ["error", "prefer-top-level"],
855
+ // Consistent type imports
856
+ "import-x/no-anonymous-default-export": "error"
857
+ // Improve code searchability
739
858
  },
740
859
  settings: {
741
860
  "import-x/resolver-next": [
@@ -760,7 +879,8 @@ var typescript = defineConfig9([
760
879
  {
761
880
  files: ["**/*.action.ts"],
762
881
  rules: {
763
- "@typescript-eslint/no-namespace": "off"
882
+ "@typescript-eslint/no-namespace": "off",
883
+ "@typescript-eslint/no-extraneous-class": "off"
764
884
  }
765
885
  },
766
886
  {
@@ -789,38 +909,62 @@ var typescript = defineConfig9([
789
909
 
790
910
  // packages/lint-suite/src/lib/vitest.ts
791
911
  import vitestEslint from "@vitest/eslint-plugin";
792
- import { defineConfig as defineConfig10 } from "eslint/config";
912
+ import { defineConfig as defineConfig11 } from "eslint/config";
793
913
  var vitestPlugin = {
794
914
  vitest: vitestEslint
795
915
  };
796
- var vitest = defineConfig10([
916
+ var vitest = defineConfig11([
797
917
  {
798
918
  files: ["**/*.spec.ts", "**/*.spec.js", "**/*.test.ts", "**/*.test.js"],
799
919
  plugins: vitestPlugin,
800
920
  rules: {
801
921
  ...vitestEslint.configs.recommended.rules,
802
- "vitest/max-nested-describe": ["error", { max: 3 }]
922
+ "vitest/max-nested-describe": ["error", { max: 3 }],
923
+ // Matcher improvements
924
+ "vitest/prefer-to-be": "error",
925
+ "vitest/prefer-to-contain": "error",
926
+ "vitest/prefer-to-have-length": "error",
927
+ "vitest/prefer-comparison-matcher": "error",
928
+ "vitest/prefer-strict-equal": "warn",
929
+ // Test quality
930
+ "vitest/prefer-spy-on": "error",
931
+ "vitest/prefer-hooks-on-top": "error",
932
+ "vitest/prefer-each": "warn",
933
+ "vitest/no-test-return-statement": "error",
934
+ "vitest/prefer-mock-promise-shorthand": "error"
803
935
  }
804
936
  }
805
937
  ]);
806
938
 
807
939
  // packages/lint-suite/src/lib/playwright.ts
808
940
  import playwrightEslint from "eslint-plugin-playwright";
809
- import { defineConfig as defineConfig11 } from "eslint/config";
810
- var playwright = defineConfig11([
941
+ import { defineConfig as defineConfig12 } from "eslint/config";
942
+ var playwright = defineConfig12([
811
943
  {
812
944
  ...playwrightEslint.configs["flat/recommended"],
813
945
  files: ["**/*.e2e.ts", "**/*.e2e.js"],
814
946
  rules: {
815
- ...playwrightEslint.configs["flat/recommended"].rules
947
+ ...playwrightEslint.configs["flat/recommended"].rules,
948
+ // Locator best practices
949
+ "playwright/prefer-locator": "error",
950
+ "playwright/prefer-native-locators": "error",
951
+ "playwright/no-nth-methods": "warn",
952
+ // Matcher improvements
953
+ "playwright/prefer-to-be": "error",
954
+ "playwright/prefer-to-have-count": "error",
955
+ "playwright/prefer-to-have-length": "error",
956
+ "playwright/prefer-comparison-matcher": "error",
957
+ // Test structure
958
+ "playwright/prefer-hooks-on-top": "error",
959
+ "playwright/require-top-level-describe": "warn"
816
960
  }
817
961
  }
818
962
  ]);
819
963
 
820
964
  // packages/lint-suite/src/lib/boundaries.ts
821
965
  import boundariesPlugin from "eslint-plugin-boundaries";
822
- import { defineConfig as defineConfig12 } from "eslint/config";
823
- var boundaries = defineConfig12([
966
+ import { defineConfig as defineConfig13 } from "eslint/config";
967
+ var boundaries = defineConfig13([
824
968
  {
825
969
  files: [
826
970
  "**/*.js",
@@ -924,7 +1068,9 @@ var recommended = [
924
1068
  ...boundaries,
925
1069
  ...storybook,
926
1070
  ...vitest,
927
- ...playwright
1071
+ ...playwright,
1072
+ ...prettier
1073
+ // Must be last to disable formatting rules that conflict with Prettier
928
1074
  ];
929
1075
  export {
930
1076
  angular,
@@ -935,6 +1081,7 @@ export {
935
1081
  jest,
936
1082
  json,
937
1083
  playwright,
1084
+ prettier,
938
1085
  recommended,
939
1086
  rxjs,
940
1087
  storybook,