lint-suite 1.2.2 → 1.3.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/index.js CHANGED
@@ -26,11 +26,27 @@ var angularTemplate = defineConfig([
26
26
  "@angular-eslint/template/prefer-self-closing-tags": "error",
27
27
  "@angular-eslint/template/prefer-ngsrc": "error",
28
28
  "@angular-eslint/template/prefer-built-in-pipes": "error",
29
- "@angular-eslint/template/no-call-expression": "error",
30
29
  "@angular-eslint/template/no-interpolation-in-attributes": "error",
31
30
  "@angular-eslint/template/no-nested-tags": "error",
32
31
  "@angular-eslint/template/use-track-by-function": "error",
33
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
34
50
  "@angular-eslint/template/attributes-order": [
35
51
  "error",
36
52
  {
@@ -77,7 +93,17 @@ var angular = defineConfig2([
77
93
  "@angular-eslint/use-injectable-provided-in": "error",
78
94
  "@angular-eslint/prefer-signal-model": "error",
79
95
  "@angular-eslint/no-uncalled-signals": "error",
80
- "@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
81
107
  }
82
108
  }
83
109
  ]);
@@ -140,7 +166,10 @@ var base = defineConfig3([
140
166
  "no-useless-concat": "error",
141
167
  "prefer-template": "error",
142
168
  "no-nested-ternary": "error",
143
- "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
144
173
  "no-else-return": ["error", { allowElseIf: false }],
145
174
  // Prefer early returns
146
175
  "no-multi-assign": "error",
@@ -322,9 +351,29 @@ import { defineConfig as defineConfig5 } from "eslint/config";
322
351
  var jest = defineConfig5([
323
352
  {
324
353
  files: ["**/*.spec.ts", "**/*.spec.js"],
325
- extends: [jestEslint.configs["flat/all"]],
354
+ extends: [jestEslint.configs["flat/recommended"]],
326
355
  rules: {
327
- "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"
328
377
  }
329
378
  }
330
379
  ]);
@@ -336,13 +385,22 @@ var json = defineConfig6([
336
385
  {
337
386
  files: ["**/*.json"],
338
387
  extends: [jsonEslint.configs.recommended]
388
+ },
389
+ {
390
+ files: ["**/tsconfig*.json", "**/.vscode/*.json"],
391
+ extends: [jsonEslint.configs["recommended-with-comments"]]
339
392
  }
340
393
  ]);
341
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
+
342
400
  // packages/lint-suite/src/lib/rxjs.ts
343
401
  import rxjsEslint from "@smarttools/eslint-plugin-rxjs";
344
- import { defineConfig as defineConfig7 } from "eslint/config";
345
- var rxjs = defineConfig7([
402
+ import { defineConfig as defineConfig8 } from "eslint/config";
403
+ var rxjs = defineConfig8([
346
404
  {
347
405
  files: [
348
406
  "**/*.js",
@@ -398,7 +456,13 @@ var rxjs = defineConfig7([
398
456
  "rxjs/no-unsafe-first": "error",
399
457
  "rxjs/no-topromise": "error",
400
458
  "rxjs/throw-error": "error",
401
- "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)
402
466
  }
403
467
  },
404
468
  {
@@ -411,12 +475,18 @@ var rxjs = defineConfig7([
411
475
 
412
476
  // packages/lint-suite/src/lib/storybook.ts
413
477
  import storybookEslint from "eslint-plugin-storybook";
414
- import { defineConfig as defineConfig8 } from "eslint/config";
415
- var storybook = defineConfig8([
478
+ import { defineConfig as defineConfig9 } from "eslint/config";
479
+ var storybook = defineConfig9([
416
480
  {
417
481
  ignores: ["!.storybook"],
418
482
  files: ["**/*.stories.ts"],
419
- extends: [storybookEslint.configs["flat/recommended"]]
483
+ extends: [storybookEslint.configs["flat/recommended"]],
484
+ rules: {
485
+ "storybook/csf-component": "warn",
486
+ // Ensure component property is set
487
+ "storybook/no-stories-of": "error"
488
+ // Prevent deprecated storiesOf API
489
+ }
420
490
  }
421
491
  ]);
422
492
 
@@ -424,7 +494,7 @@ var storybook = defineConfig8([
424
494
  import { configs as configs5 } from "@nx/eslint-plugin";
425
495
  import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
426
496
  import importPluginX2 from "eslint-plugin-import-x";
427
- import { defineConfig as defineConfig9 } from "eslint/config";
497
+ import { defineConfig as defineConfig10 } from "eslint/config";
428
498
 
429
499
  // packages/lint-suite/src/lib/rules/explicit-accessibility.ts
430
500
  import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
@@ -565,7 +635,7 @@ var localTypescriptRules = {
565
635
  "explicit-accessibility": explicit_accessibility_default
566
636
  }
567
637
  };
568
- var typescript = defineConfig9([
638
+ var typescript = defineConfig10([
569
639
  // NOTE: Checks for 'prettier' and 'eslint-plugin-prettier'
570
640
  {
571
641
  files: ["**/*.ts", "**/*.tsx", "**/*.cts", "**/*.mts"],
@@ -591,6 +661,13 @@ var typescript = defineConfig9([
591
661
  "@typescript-eslint/no-unsafe-member-access": "error",
592
662
  "@typescript-eslint/no-unsafe-return": "error",
593
663
  "@typescript-eslint/no-unsafe-argument": "error",
664
+ // New v8 type-safety rules (replacements for deprecated ban-types)
665
+ "@typescript-eslint/no-empty-object-type": "error",
666
+ // Bans confusing {} type
667
+ "@typescript-eslint/no-unsafe-function-type": "error",
668
+ // Bans Function type
669
+ "@typescript-eslint/no-wrapper-object-types": "error",
670
+ // Bans Number, String, Boolean wrappers
594
671
  // B. Explicit Annotations (partially covered, explicit module boundaries is key)
595
672
  "@typescript-eslint/explicit-module-boundary-types": "error",
596
673
  // Consider enabling if maximum explicitness is desired, even if verbose:
@@ -611,8 +688,14 @@ var typescript = defineConfig9([
611
688
  // E. Best Practices & Potential Errors (Some covered by presets, fine-tuning here)
612
689
  "@typescript-eslint/no-inferrable-types": "warn",
613
690
  // Keep as warn or disable if inference is preferred
614
- "@typescript-eslint/no-var-requires": "error",
615
- // Use ES modules
691
+ "@typescript-eslint/no-require-imports": "error",
692
+ // Use ES modules (replaces deprecated no-var-requires)
693
+ "@typescript-eslint/only-throw-error": "error",
694
+ // Replaces deprecated no-throw-literal
695
+ "@typescript-eslint/no-array-delete": "error",
696
+ // Prevents delete arr[0]
697
+ "@typescript-eslint/return-await": ["error", "in-try-catch"],
698
+ // Better stack traces in try/catch
616
699
  "@typescript-eslint/require-await": "error",
617
700
  "@typescript-eslint/restrict-template-expressions": [
618
701
  "error",
@@ -632,6 +715,32 @@ var typescript = defineConfig9([
632
715
  "@typescript-eslint/no-useless-constructor": "error",
633
716
  "@typescript-eslint/dot-notation": ["error", { allowKeywords: true }],
634
717
  // Prefer dot notation where possible
718
+ // Strict type-checked rules
719
+ "@typescript-eslint/no-unnecessary-condition": "error",
720
+ // Catches always-true/false conditions
721
+ "@typescript-eslint/no-confusing-void-expression": "error",
722
+ // Prevent confusing void usage
723
+ "@typescript-eslint/no-dynamic-delete": "error",
724
+ // Use Map instead of delete obj[key]
725
+ "@typescript-eslint/no-extraneous-class": ["error", { allowWithDecorator: true }],
726
+ // Allow Angular classes
727
+ "@typescript-eslint/no-invalid-void-type": "error",
728
+ // Restrict void to return types
729
+ "@typescript-eslint/unified-signatures": "error",
730
+ // Merge overloads where possible
731
+ "@typescript-eslint/no-non-null-asserted-nullish-coalescing": "error",
732
+ // Forbids foo! ?? bar
733
+ // Stylistic type-checked rules
734
+ "@typescript-eslint/prefer-find": "error",
735
+ // Use find() instead of filter()[0]
736
+ "@typescript-eslint/prefer-for-of": "error",
737
+ // Modern iteration
738
+ "@typescript-eslint/prefer-includes": "error",
739
+ // indexOf() → includes()
740
+ "@typescript-eslint/prefer-string-starts-ends-with": "error",
741
+ // Modern string methods
742
+ "@typescript-eslint/prefer-regexp-exec": "error",
743
+ // Better regex performance
635
744
  // F. Consistency & Style (Some covered by stylistic-type-checked)
636
745
  "@typescript-eslint/consistent-type-assertions": [
637
746
  "error",
@@ -733,10 +842,18 @@ var typescript = defineConfig9([
733
842
  "import-x/no-unresolved": "error",
734
843
  "import-x/no-duplicates": "error",
735
844
  "import-x/prefer-default-export": "off",
736
- "import-x/no-useless-path-segments": "error",
845
+ "import-x/no-useless-path-segments": ["error", { noUselessIndex: true }],
737
846
  "import-x/newline-after-import": "error",
738
847
  "import-x/first": "error",
739
- "import-x/no-mutable-exports": "error"
848
+ "import-x/no-mutable-exports": "error",
849
+ "import-x/no-self-import": "error",
850
+ // Prevents modules importing themselves
851
+ "import-x/no-cycle": ["error", { maxDepth: 2, ignoreExternal: true }],
852
+ // Prevents circular dependencies
853
+ "import-x/consistent-type-specifier-style": ["error", "prefer-top-level"],
854
+ // Consistent type imports
855
+ "import-x/no-anonymous-default-export": "error"
856
+ // Improve code searchability
740
857
  },
741
858
  settings: {
742
859
  "import-x/resolver-next": [
@@ -790,38 +907,63 @@ var typescript = defineConfig9([
790
907
 
791
908
  // packages/lint-suite/src/lib/vitest.ts
792
909
  import vitestEslint from "@vitest/eslint-plugin";
793
- import { defineConfig as defineConfig10 } from "eslint/config";
910
+ import { defineConfig as defineConfig11 } from "eslint/config";
794
911
  var vitestPlugin = {
795
912
  vitest: vitestEslint
796
913
  };
797
- var vitest = defineConfig10([
914
+ var vitest = defineConfig11([
798
915
  {
799
916
  files: ["**/*.spec.ts", "**/*.spec.js", "**/*.test.ts", "**/*.test.js"],
800
917
  plugins: vitestPlugin,
801
918
  rules: {
802
919
  ...vitestEslint.configs.recommended.rules,
803
- "vitest/max-nested-describe": ["error", { max: 3 }]
920
+ "vitest/max-nested-describe": ["error", { max: 3 }],
921
+ // Matcher improvements
922
+ "vitest/prefer-to-be": "error",
923
+ "vitest/prefer-to-contain": "error",
924
+ "vitest/prefer-to-have-length": "error",
925
+ "vitest/prefer-comparison-matcher": "error",
926
+ "vitest/prefer-strict-equal": "warn",
927
+ // Test quality
928
+ "vitest/prefer-spy-on": "error",
929
+ "vitest/prefer-hooks-on-top": "error",
930
+ "vitest/prefer-each": "warn",
931
+ "vitest/no-conditional-in-test": "error",
932
+ "vitest/no-test-return-statement": "error",
933
+ "vitest/prefer-mock-promise-shorthand": "error"
804
934
  }
805
935
  }
806
936
  ]);
807
937
 
808
938
  // packages/lint-suite/src/lib/playwright.ts
809
939
  import playwrightEslint from "eslint-plugin-playwright";
810
- import { defineConfig as defineConfig11 } from "eslint/config";
811
- var playwright = defineConfig11([
940
+ import { defineConfig as defineConfig12 } from "eslint/config";
941
+ var playwright = defineConfig12([
812
942
  {
813
943
  ...playwrightEslint.configs["flat/recommended"],
814
944
  files: ["**/*.e2e.ts", "**/*.e2e.js"],
815
945
  rules: {
816
- ...playwrightEslint.configs["flat/recommended"].rules
946
+ ...playwrightEslint.configs["flat/recommended"].rules,
947
+ // Locator best practices
948
+ "playwright/prefer-locator": "error",
949
+ "playwright/prefer-native-locators": "error",
950
+ "playwright/no-nth-methods": "warn",
951
+ // Matcher improvements
952
+ "playwright/prefer-to-be": "error",
953
+ "playwright/prefer-to-have-count": "error",
954
+ "playwright/prefer-to-have-length": "error",
955
+ "playwright/prefer-comparison-matcher": "error",
956
+ // Test structure
957
+ "playwright/prefer-hooks-on-top": "error",
958
+ "playwright/require-top-level-describe": "warn"
817
959
  }
818
960
  }
819
961
  ]);
820
962
 
821
963
  // packages/lint-suite/src/lib/boundaries.ts
822
964
  import boundariesPlugin from "eslint-plugin-boundaries";
823
- import { defineConfig as defineConfig12 } from "eslint/config";
824
- var boundaries = defineConfig12([
965
+ import { defineConfig as defineConfig13 } from "eslint/config";
966
+ var boundaries = defineConfig13([
825
967
  {
826
968
  files: [
827
969
  "**/*.js",
@@ -869,6 +1011,8 @@ var boundaries = defineConfig12([
869
1011
  },
870
1012
  rules: {
871
1013
  ...boundariesPlugin.configs.recommended.rules,
1014
+ "boundaries/no-unknown": "warn",
1015
+ // Warn on imports from uncategorized files
872
1016
  "boundaries/element-types": [
873
1017
  "error",
874
1018
  {
@@ -925,7 +1069,9 @@ var recommended = [
925
1069
  ...boundaries,
926
1070
  ...storybook,
927
1071
  ...vitest,
928
- ...playwright
1072
+ ...playwright,
1073
+ ...prettier
1074
+ // Must be last to disable formatting rules that conflict with Prettier
929
1075
  ];
930
1076
  export {
931
1077
  angular,
@@ -936,6 +1082,7 @@ export {
936
1082
  jest,
937
1083
  json,
938
1084
  playwright,
1085
+ prettier,
939
1086
  recommended,
940
1087
  rxjs,
941
1088
  storybook,