lint-suite 1.2.3 → 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
@@ -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,7 +456,13 @@ 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
  {
@@ -410,12 +475,18 @@ var rxjs = defineConfig7([
410
475
 
411
476
  // packages/lint-suite/src/lib/storybook.ts
412
477
  import storybookEslint from "eslint-plugin-storybook";
413
- import { defineConfig as defineConfig8 } from "eslint/config";
414
- var storybook = defineConfig8([
478
+ import { defineConfig as defineConfig9 } from "eslint/config";
479
+ var storybook = defineConfig9([
415
480
  {
416
481
  ignores: ["!.storybook"],
417
482
  files: ["**/*.stories.ts"],
418
- 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
+ }
419
490
  }
420
491
  ]);
421
492
 
@@ -423,7 +494,7 @@ var storybook = defineConfig8([
423
494
  import { configs as configs5 } from "@nx/eslint-plugin";
424
495
  import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
425
496
  import importPluginX2 from "eslint-plugin-import-x";
426
- import { defineConfig as defineConfig9 } from "eslint/config";
497
+ import { defineConfig as defineConfig10 } from "eslint/config";
427
498
 
428
499
  // packages/lint-suite/src/lib/rules/explicit-accessibility.ts
429
500
  import { ESLintUtils, TSESTree } from "@typescript-eslint/utils";
@@ -564,7 +635,7 @@ var localTypescriptRules = {
564
635
  "explicit-accessibility": explicit_accessibility_default
565
636
  }
566
637
  };
567
- var typescript = defineConfig9([
638
+ var typescript = defineConfig10([
568
639
  // NOTE: Checks for 'prettier' and 'eslint-plugin-prettier'
569
640
  {
570
641
  files: ["**/*.ts", "**/*.tsx", "**/*.cts", "**/*.mts"],
@@ -590,6 +661,13 @@ var typescript = defineConfig9([
590
661
  "@typescript-eslint/no-unsafe-member-access": "error",
591
662
  "@typescript-eslint/no-unsafe-return": "error",
592
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
593
671
  // B. Explicit Annotations (partially covered, explicit module boundaries is key)
594
672
  "@typescript-eslint/explicit-module-boundary-types": "error",
595
673
  // Consider enabling if maximum explicitness is desired, even if verbose:
@@ -610,8 +688,14 @@ var typescript = defineConfig9([
610
688
  // E. Best Practices & Potential Errors (Some covered by presets, fine-tuning here)
611
689
  "@typescript-eslint/no-inferrable-types": "warn",
612
690
  // Keep as warn or disable if inference is preferred
613
- "@typescript-eslint/no-var-requires": "error",
614
- // 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
615
699
  "@typescript-eslint/require-await": "error",
616
700
  "@typescript-eslint/restrict-template-expressions": [
617
701
  "error",
@@ -631,6 +715,32 @@ var typescript = defineConfig9([
631
715
  "@typescript-eslint/no-useless-constructor": "error",
632
716
  "@typescript-eslint/dot-notation": ["error", { allowKeywords: true }],
633
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
634
744
  // F. Consistency & Style (Some covered by stylistic-type-checked)
635
745
  "@typescript-eslint/consistent-type-assertions": [
636
746
  "error",
@@ -732,10 +842,18 @@ var typescript = defineConfig9([
732
842
  "import-x/no-unresolved": "error",
733
843
  "import-x/no-duplicates": "error",
734
844
  "import-x/prefer-default-export": "off",
735
- "import-x/no-useless-path-segments": "error",
845
+ "import-x/no-useless-path-segments": ["error", { noUselessIndex: true }],
736
846
  "import-x/newline-after-import": "error",
737
847
  "import-x/first": "error",
738
- "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
739
857
  },
740
858
  settings: {
741
859
  "import-x/resolver-next": [
@@ -789,38 +907,63 @@ var typescript = defineConfig9([
789
907
 
790
908
  // packages/lint-suite/src/lib/vitest.ts
791
909
  import vitestEslint from "@vitest/eslint-plugin";
792
- import { defineConfig as defineConfig10 } from "eslint/config";
910
+ import { defineConfig as defineConfig11 } from "eslint/config";
793
911
  var vitestPlugin = {
794
912
  vitest: vitestEslint
795
913
  };
796
- var vitest = defineConfig10([
914
+ var vitest = defineConfig11([
797
915
  {
798
916
  files: ["**/*.spec.ts", "**/*.spec.js", "**/*.test.ts", "**/*.test.js"],
799
917
  plugins: vitestPlugin,
800
918
  rules: {
801
919
  ...vitestEslint.configs.recommended.rules,
802
- "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"
803
934
  }
804
935
  }
805
936
  ]);
806
937
 
807
938
  // packages/lint-suite/src/lib/playwright.ts
808
939
  import playwrightEslint from "eslint-plugin-playwright";
809
- import { defineConfig as defineConfig11 } from "eslint/config";
810
- var playwright = defineConfig11([
940
+ import { defineConfig as defineConfig12 } from "eslint/config";
941
+ var playwright = defineConfig12([
811
942
  {
812
943
  ...playwrightEslint.configs["flat/recommended"],
813
944
  files: ["**/*.e2e.ts", "**/*.e2e.js"],
814
945
  rules: {
815
- ...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"
816
959
  }
817
960
  }
818
961
  ]);
819
962
 
820
963
  // packages/lint-suite/src/lib/boundaries.ts
821
964
  import boundariesPlugin from "eslint-plugin-boundaries";
822
- import { defineConfig as defineConfig12 } from "eslint/config";
823
- var boundaries = defineConfig12([
965
+ import { defineConfig as defineConfig13 } from "eslint/config";
966
+ var boundaries = defineConfig13([
824
967
  {
825
968
  files: [
826
969
  "**/*.js",
@@ -868,6 +1011,8 @@ var boundaries = defineConfig12([
868
1011
  },
869
1012
  rules: {
870
1013
  ...boundariesPlugin.configs.recommended.rules,
1014
+ "boundaries/no-unknown": "warn",
1015
+ // Warn on imports from uncategorized files
871
1016
  "boundaries/element-types": [
872
1017
  "error",
873
1018
  {
@@ -924,7 +1069,9 @@ var recommended = [
924
1069
  ...boundaries,
925
1070
  ...storybook,
926
1071
  ...vitest,
927
- ...playwright
1072
+ ...playwright,
1073
+ ...prettier
1074
+ // Must be last to disable formatting rules that conflict with Prettier
928
1075
  ];
929
1076
  export {
930
1077
  angular,
@@ -935,6 +1082,7 @@ export {
935
1082
  jest,
936
1083
  json,
937
1084
  playwright,
1085
+ prettier,
938
1086
  recommended,
939
1087
  rxjs,
940
1088
  storybook,