eslint-config-agent 1.1.3 → 1.2.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/CHANGELOG.md +19 -0
- package/index.js +77 -17
- package/package.json +2 -2
- package/rules/index.js +3 -0
- package/rules/max-file-lines/examples/invalid/long-file.js +113 -0
- package/rules/max-file-lines/examples/invalid/medium-file.js +127 -0
- package/rules/max-file-lines/examples/invalid/very-long-file.ts +144 -0
- package/rules/max-file-lines/examples/valid/short-file.js +66 -0
- package/rules/max-file-lines/examples/valid/spec-file.spec.js +44 -0
- package/rules/max-file-lines/examples/valid/test-file.test.js +25 -0
- package/rules/no-empty-exports/examples/invalid/empty-export.js +2 -0
- package/rules/no-empty-exports/examples/invalid/multiple-exports.js +5 -0
- package/rules/no-empty-exports/examples/invalid/single-export.js +3 -0
- package/rules/no-empty-exports/examples/valid/default-export.js +3 -0
- package/rules/no-empty-exports/examples/valid/direct-class.js +6 -0
- package/rules/no-empty-exports/examples/valid/direct-const.js +2 -0
- package/rules/no-empty-exports/examples/valid/direct-function.js +4 -0
- package/rules/no-empty-exports/examples/valid/re-export-from.js +2 -0
- package/rules/no-empty-exports/examples/valid/re-export-star.js +2 -0
- package/rules/no-empty-exports/index.js +16 -0
- package/rules/no-empty-exports/no-empty-exports.spec.js +104 -0
- package/rules/plugin/import/group-exports/examples/invalid/mixed-declaration-styles.js +8 -0
- package/rules/plugin/import/group-exports/examples/invalid/multiple-export-statements.js +8 -0
- package/rules/plugin/import/group-exports/examples/invalid/scattered-exports.js +10 -0
- package/rules/plugin/import/group-exports/examples/valid/direct-exports.js +2 -0
- package/rules/plugin/import/group-exports/examples/valid/mixed-with-default.js +7 -0
- package/rules/plugin/import/group-exports/examples/valid/single-export-statement.js +6 -0
- package/rules/plugin/import/group-exports/index.js +3 -0
- package/rules/plugin/import/index.js +5 -1
- package/rules/plugin/import/no-unused-modules/examples/invalid/dead-code.js +2 -0
- package/rules/plugin/import/no-unused-modules/examples/invalid/unused-class.js +6 -0
- package/rules/plugin/import/no-unused-modules/examples/invalid/unused-export.js +2 -0
- package/rules/plugin/import/no-unused-modules/examples/invalid/unused-function.js +4 -0
- package/rules/plugin/import/no-unused-modules/examples/invalid/unused-module.js +4 -0
- package/rules/plugin/import/no-unused-modules/examples/valid/consumed-import.js +8 -0
- package/rules/plugin/import/no-unused-modules/examples/valid/entry-point.js +5 -0
- package/rules/plugin/import/no-unused-modules/examples/valid/used-class.js +6 -0
- package/rules/plugin/import/no-unused-modules/examples/valid/used-export.js +2 -0
- package/rules/plugin/import/no-unused-modules/examples/valid/used-function.js +4 -0
- package/rules/plugin/import/no-unused-modules/index.js +6 -0
- package/rules/plugin/typescript-eslint/index.js +3 -1
- package/rules/plugin/typescript-eslint/no-explicit-any/examples/invalid/any-array.ts +2 -0
- package/rules/plugin/typescript-eslint/no-explicit-any/examples/invalid/any-parameter.ts +4 -0
- package/rules/plugin/typescript-eslint/no-explicit-any/examples/invalid/any-return-type.ts +4 -0
- package/rules/plugin/typescript-eslint/no-explicit-any/examples/invalid/any-variable.ts +5 -0
- package/rules/plugin/typescript-eslint/no-explicit-any/examples/valid/generics.ts +16 -0
- package/rules/plugin/typescript-eslint/no-explicit-any/examples/valid/specific-types.ts +9 -0
- package/rules/plugin/typescript-eslint/no-explicit-any/examples/valid/unknown-type.ts +8 -0
- package/rules/plugin/typescript-eslint/no-explicit-any/index.js +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@ All notable changes to this project will be documented in this file. See [Conven
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
## [1.2.0](https://github.com/tupe12334/eslint-config/compare/v1.1.4...v1.2.0) (2025-09-11)
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* add examples for valid and invalid export patterns and update import rules configuration ([a78e03d](https://github.com/tupe12334/eslint-config/commit/a78e03d201e335b423c1830593c015ddd0346028))
|
|
12
|
+
* add no-explicit-any rule configuration and examples for valid/invalid usage ([2bc0ad8](https://github.com/tupe12334/eslint-config/commit/2bc0ad836ff42199456ebc7ebd0b6948cca1a7b1))
|
|
13
|
+
* add no-unused-modules rule configuration and examples for unused exports ([336db1b](https://github.com/tupe12334/eslint-config/commit/336db1b26bf4ac0d3e9bd56c95817748bfda4799))
|
|
14
|
+
* refine ESLint configuration to include specific index.js files and update CI test command ([5693dbc](https://github.com/tupe12334/eslint-config/commit/5693dbc65dc37cbddb6a41498b4886d360c17684))
|
|
15
|
+
* update ESLint configuration to disable size limits for test/spec files and add examples for valid/invalid file lengths ([ac57e22](https://github.com/tupe12334/eslint-config/commit/ac57e223f7d1cedab32976cee5f305ca197ca0c8))
|
|
16
|
+
* update export statements in test files to use default export syntax ([c4a846b](https://github.com/tupe12334/eslint-config/commit/c4a846bc78105f287fafcb4248c8de334c84b0fb))
|
|
17
|
+
|
|
18
|
+
## [1.1.4](https://github.com/tupe12334/eslint-config/compare/v1.1.3...v1.1.4) (2025-09-10)
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* add no-empty-exports rule to prevent empty export specifiers and include test cases ([7757007](https://github.com/tupe12334/eslint-config/commit/77570076e41bdab64dbed53ca7a40a935eda7e3a))
|
|
23
|
+
* enhance export specifier rules and update test configurations for improved validation ([fe64b9c](https://github.com/tupe12334/eslint-config/commit/fe64b9cb7f1bdf80b16a97db75a5fd04901c2e7f))
|
|
24
|
+
* remove package-specific ignores from ESLint config for cleaner configuration ([03cef75](https://github.com/tupe12334/eslint-config/commit/03cef75a6ad6d682ede5f4c5dc5d5e1a8d0a9aaa))
|
|
25
|
+
|
|
7
26
|
## [1.1.3](https://github.com/tupe12334/eslint-config/compare/v1.1.2...v1.1.3) (2025-09-10)
|
|
8
27
|
|
|
9
28
|
### Features
|
package/index.js
CHANGED
|
@@ -19,7 +19,6 @@ try {
|
|
|
19
19
|
// eslint-plugin-preact is not available
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
23
22
|
// Shared rules for both JS and TS files
|
|
24
23
|
const sharedRules = {
|
|
25
24
|
...allRules.pluginRules,
|
|
@@ -95,12 +94,14 @@ const sharedRestrictedSyntax = [
|
|
|
95
94
|
"Exporting from external libraries is not allowed. Only re-export from relative paths or scoped packages.",
|
|
96
95
|
},
|
|
97
96
|
allRules.noProcessEnvPropertiesConfig,
|
|
97
|
+
allRules.noExportSpecifiersConfig,
|
|
98
98
|
];
|
|
99
99
|
|
|
100
100
|
// Required export rules (always errors)
|
|
101
101
|
const requiredExportRules = [
|
|
102
102
|
{
|
|
103
|
-
selector:
|
|
103
|
+
selector:
|
|
104
|
+
"ClassDeclaration:not(ExportNamedDeclaration > ClassDeclaration):not(ExportDefaultDeclaration > ClassDeclaration)",
|
|
104
105
|
message:
|
|
105
106
|
"Classes must be exported. Use 'export class' or 'export default class'.",
|
|
106
107
|
},
|
|
@@ -199,9 +200,6 @@ const config = [
|
|
|
199
200
|
},
|
|
200
201
|
},
|
|
201
202
|
reactHooks.configs["recommended-latest"],
|
|
202
|
-
{
|
|
203
|
-
ignores: ["packages/auth-service-sdk/**"],
|
|
204
|
-
},
|
|
205
203
|
js.configs.recommended,
|
|
206
204
|
|
|
207
205
|
// TypeScript and TSX files
|
|
@@ -212,10 +210,6 @@ const config = [
|
|
|
212
210
|
"**/dist/**",
|
|
213
211
|
"**/build/**",
|
|
214
212
|
"pnpm-lock.yaml",
|
|
215
|
-
"packages/auth-service-sdk/**",
|
|
216
|
-
"packages/auth-service-sdk/src/core/**",
|
|
217
|
-
"packages/auth-service-sdk/src/client/**",
|
|
218
|
-
"packages/auth-service-sdk/src/*.gen.ts",
|
|
219
213
|
"**/*.stories.{js,jsx,ts,tsx}",
|
|
220
214
|
],
|
|
221
215
|
languageOptions: {
|
|
@@ -425,11 +419,11 @@ const config = [
|
|
|
425
419
|
"**/dist/**",
|
|
426
420
|
"**/build/**",
|
|
427
421
|
"pnpm-lock.yaml",
|
|
428
|
-
"packages/auth-service-sdk/**",
|
|
429
422
|
"**/*.umd.js",
|
|
430
423
|
"**/*.cjs",
|
|
431
424
|
"**/*.mjs",
|
|
432
425
|
"**/*.stories.{js,jsx,ts,tsx}",
|
|
426
|
+
"**/rules/**/index.js",
|
|
433
427
|
],
|
|
434
428
|
languageOptions: {
|
|
435
429
|
parserOptions: {
|
|
@@ -495,7 +489,6 @@ const config = [
|
|
|
495
489
|
"**/dist/**",
|
|
496
490
|
"**/build/**",
|
|
497
491
|
"pnpm-lock.yaml",
|
|
498
|
-
"packages/auth-service-sdk/**",
|
|
499
492
|
"**/*.stories.{js,jsx,ts,tsx}",
|
|
500
493
|
],
|
|
501
494
|
languageOptions: {
|
|
@@ -615,7 +608,6 @@ const config = [
|
|
|
615
608
|
"**/dist/**",
|
|
616
609
|
"**/build/**",
|
|
617
610
|
"pnpm-lock.yaml",
|
|
618
|
-
"packages/auth-service-sdk/**",
|
|
619
611
|
"**/*.stories.{js,jsx,ts,tsx}",
|
|
620
612
|
],
|
|
621
613
|
languageOptions: {
|
|
@@ -692,7 +684,7 @@ const config = [
|
|
|
692
684
|
},
|
|
693
685
|
},
|
|
694
686
|
|
|
695
|
-
// Disable function size limits for test and spec files
|
|
687
|
+
// Disable function and file size limits for test and spec files
|
|
696
688
|
{
|
|
697
689
|
files: [
|
|
698
690
|
"**/*.test.{js,jsx,ts,tsx}",
|
|
@@ -708,6 +700,7 @@ const config = [
|
|
|
708
700
|
],
|
|
709
701
|
rules: {
|
|
710
702
|
"max-lines-per-function": "off",
|
|
703
|
+
"max-lines": "off", // Ignore file length limits in test and spec files
|
|
711
704
|
// Allow multiple exports in test files for testing import/export patterns
|
|
712
705
|
"no-restricted-syntax": [
|
|
713
706
|
"warn",
|
|
@@ -716,7 +709,33 @@ const config = [
|
|
|
716
709
|
rule.selector !==
|
|
717
710
|
"ExportNamedDeclaration[specifiers.length>1]:not([source])" &&
|
|
718
711
|
rule.selector !==
|
|
719
|
-
"Program:has(ExportNamedDeclaration:not([source]) ~ ExportNamedDeclaration:not([source]))"
|
|
712
|
+
"Program:has(ExportNamedDeclaration:not([source]) ~ ExportNamedDeclaration:not([source]))" &&
|
|
713
|
+
rule.selector !==
|
|
714
|
+
"ExportNamedDeclaration:not([source]):not(:has(VariableDeclaration)):not(:has(FunctionDeclaration)):not(:has(ClassDeclaration)):not(:has(TSInterfaceDeclaration)):not(:has(TSTypeAliasDeclaration)):not(:has(TSEnumDeclaration))"
|
|
715
|
+
),
|
|
716
|
+
...tsOnlyRestrictedSyntax,
|
|
717
|
+
],
|
|
718
|
+
},
|
|
719
|
+
},
|
|
720
|
+
|
|
721
|
+
// Test files that should have ERROR level rules but exclude export specifier rule
|
|
722
|
+
{
|
|
723
|
+
files: [
|
|
724
|
+
"**/test/type-assertions/**",
|
|
725
|
+
"**/test/test-optional.ts",
|
|
726
|
+
"**/test/test-js-optional.js",
|
|
727
|
+
"**/test/test-record-literals.ts",
|
|
728
|
+
"**/test/no-env-access-test.ts",
|
|
729
|
+
"**/test/import-export-rules.ts",
|
|
730
|
+
],
|
|
731
|
+
rules: {
|
|
732
|
+
"max-lines-per-function": "off",
|
|
733
|
+
"no-restricted-syntax": [
|
|
734
|
+
"error", // Error level for these test files
|
|
735
|
+
...sharedRestrictedSyntax.filter(
|
|
736
|
+
(rule) =>
|
|
737
|
+
rule.selector !==
|
|
738
|
+
"ExportNamedDeclaration:not([source]):not(:has(VariableDeclaration)):not(:has(FunctionDeclaration)):not(:has(ClassDeclaration)):not(:has(TSInterfaceDeclaration)):not(:has(TSTypeAliasDeclaration)):not(:has(TSEnumDeclaration))"
|
|
720
739
|
),
|
|
721
740
|
...tsOnlyRestrictedSyntax,
|
|
722
741
|
],
|
|
@@ -727,6 +746,9 @@ const config = [
|
|
|
727
746
|
{
|
|
728
747
|
files: [
|
|
729
748
|
"**/test/invalid.tsx", // Special handling for the main test file
|
|
749
|
+
"**/test/single-export-valid.ts", // Allow export specifiers for import/group-exports testing
|
|
750
|
+
"**/test/typescript-rules.ts", // Allow export specifiers for typescript rules testing
|
|
751
|
+
"**/test/type-assertions/indexed-access-valid.ts", // Allow export specifiers for type assertions testing
|
|
730
752
|
],
|
|
731
753
|
rules: {
|
|
732
754
|
"max-lines-per-function": "off",
|
|
@@ -737,7 +759,9 @@ const config = [
|
|
|
737
759
|
rule.selector !==
|
|
738
760
|
"ExportNamedDeclaration[specifiers.length>1]:not([source])" &&
|
|
739
761
|
rule.selector !==
|
|
740
|
-
"Program:has(ExportNamedDeclaration:not([source]) ~ ExportNamedDeclaration:not([source]))"
|
|
762
|
+
"Program:has(ExportNamedDeclaration:not([source]) ~ ExportNamedDeclaration:not([source]))" &&
|
|
763
|
+
rule.selector !==
|
|
764
|
+
"ExportNamedDeclaration:not([source]):not(:has(VariableDeclaration)):not(:has(FunctionDeclaration)):not(:has(ClassDeclaration)):not(:has(TSInterfaceDeclaration)):not(:has(TSTypeAliasDeclaration)):not(:has(TSEnumDeclaration))"
|
|
741
765
|
),
|
|
742
766
|
...tsOnlyRestrictedSyntax,
|
|
743
767
|
// For TSX files, also include required export rules as warnings since we can't mix severities
|
|
@@ -777,7 +801,13 @@ const config = [
|
|
|
777
801
|
// Switch case rules as errors for all TypeScript/JSX files (must come last to override)
|
|
778
802
|
{
|
|
779
803
|
files: ["**/*.{ts,tsx,js,jsx}"],
|
|
780
|
-
ignores: [
|
|
804
|
+
ignores: [
|
|
805
|
+
"**/*.stories.{js,jsx,ts,tsx}",
|
|
806
|
+
"**/test/**",
|
|
807
|
+
"!**/test/export/**",
|
|
808
|
+
"!**/test/required-exports/**",
|
|
809
|
+
"**/rules/**/index.js",
|
|
810
|
+
],
|
|
781
811
|
rules: {
|
|
782
812
|
"no-restricted-syntax": [
|
|
783
813
|
"error",
|
|
@@ -860,6 +890,7 @@ const config = [
|
|
|
860
890
|
},
|
|
861
891
|
allRules.noTypeAssertionsConfig,
|
|
862
892
|
allRules.noProcessEnvPropertiesConfig,
|
|
893
|
+
allRules.noExportSpecifiersConfig,
|
|
863
894
|
// Export restriction rules
|
|
864
895
|
// Required export rules
|
|
865
896
|
...requiredExportRules,
|
|
@@ -886,7 +917,14 @@ const config = [
|
|
|
886
917
|
// Function and file length rules - strict error thresholds
|
|
887
918
|
{
|
|
888
919
|
files: ["**/*.{ts,tsx,js,jsx}"],
|
|
889
|
-
ignores: [
|
|
920
|
+
ignores: [
|
|
921
|
+
"**/*.stories.{js,jsx,ts,tsx}",
|
|
922
|
+
"**/*.test.{js,jsx,ts,tsx}",
|
|
923
|
+
"**/*.spec.{js,jsx,ts,tsx}",
|
|
924
|
+
"**/test/**/*.{js,jsx,ts,tsx}",
|
|
925
|
+
"**/tests/**/*.{js,jsx,ts,tsx}",
|
|
926
|
+
"**/__tests__/**/*.{js,jsx,ts,tsx}",
|
|
927
|
+
],
|
|
890
928
|
rules: {
|
|
891
929
|
// Function length: error at 70+ lines
|
|
892
930
|
"max-lines-per-function": allRules.maxFunctionLinesError,
|
|
@@ -946,6 +984,28 @@ const config = [
|
|
|
946
984
|
...storybookPlugin.configs.recommended.rules,
|
|
947
985
|
},
|
|
948
986
|
},
|
|
987
|
+
|
|
988
|
+
// Rules directory configuration - allow export specifiers for API definitions (but not examples)
|
|
989
|
+
{
|
|
990
|
+
files: ["**/rules/**/*.{js,ts}"],
|
|
991
|
+
ignores: ["**/rules/**/examples/**"],
|
|
992
|
+
languageOptions: {
|
|
993
|
+
globals: {
|
|
994
|
+
...globals.node,
|
|
995
|
+
},
|
|
996
|
+
},
|
|
997
|
+
rules: {
|
|
998
|
+
"no-restricted-syntax": [
|
|
999
|
+
"error",
|
|
1000
|
+
// Include all shared rules EXCEPT our export specifier rule
|
|
1001
|
+
...sharedRestrictedSyntax.filter(
|
|
1002
|
+
(rule) =>
|
|
1003
|
+
rule.selector !==
|
|
1004
|
+
"ExportNamedDeclaration:not([source]):not(:has(VariableDeclaration)):not(:has(FunctionDeclaration)):not(:has(ClassDeclaration)):not(:has(TSInterfaceDeclaration)):not(:has(TSTypeAliasDeclaration)):not(:has(TSEnumDeclaration))"
|
|
1005
|
+
),
|
|
1006
|
+
],
|
|
1007
|
+
},
|
|
1008
|
+
},
|
|
949
1009
|
];
|
|
950
1010
|
|
|
951
1011
|
export default config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-config-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "ESLint configuration package with TypeScript support",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"test:edge": "eslint test/edge-cases.tsx",
|
|
29
29
|
"test:performance": "eslint test/performance-test.tsx",
|
|
30
30
|
"test:comprehensive": "node scripts/test-runner.js",
|
|
31
|
-
"test:ci": "eslint . --ignore-pattern 'test/**' --ignore-pattern 'scripts/**' --max-warnings 0",
|
|
31
|
+
"test:ci": "eslint . --ignore-pattern 'test/**' --ignore-pattern 'scripts/**' --ignore-pattern 'rules/**/examples/**' --max-warnings 0",
|
|
32
32
|
"validate": "node scripts/validate-config.js",
|
|
33
33
|
"release": "dotenv -e .env -- release-it",
|
|
34
34
|
"release:patch": "dotenv -e .env -- release-it patch",
|
package/rules/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { maxFileLinesWarning, maxFileLinesError } from "./max-file-lines/index.j
|
|
|
13
13
|
// Custom restricted syntax rules
|
|
14
14
|
import { noProcessEnvPropertiesConfig } from "./no-process-env-properties/index.js";
|
|
15
15
|
import { noTypeAssertionsConfig } from "./no-type-assertions/index.js";
|
|
16
|
+
import { noExportSpecifiersConfig } from "./no-empty-exports/index.js";
|
|
16
17
|
|
|
17
18
|
// Plugin rule configurations
|
|
18
19
|
import { pluginRules } from "./plugin/index.js";
|
|
@@ -30,6 +31,7 @@ const allRules = {
|
|
|
30
31
|
// Custom restricted syntax rules
|
|
31
32
|
noProcessEnvPropertiesConfig,
|
|
32
33
|
noTypeAssertionsConfig,
|
|
34
|
+
noExportSpecifiersConfig,
|
|
33
35
|
|
|
34
36
|
// Plugin rule configurations
|
|
35
37
|
pluginRules,
|
|
@@ -50,6 +52,7 @@ export {
|
|
|
50
52
|
// Custom restricted syntax rules
|
|
51
53
|
noProcessEnvPropertiesConfig,
|
|
52
54
|
noTypeAssertionsConfig,
|
|
55
|
+
noExportSpecifiersConfig,
|
|
53
56
|
|
|
54
57
|
// Plugin rule configurations
|
|
55
58
|
pluginRules,
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Invalid: File with more than 100 lines (should trigger max-lines error)
|
|
2
|
+
const line1 = 1;
|
|
3
|
+
const line2 = 2;
|
|
4
|
+
const line3 = 3;
|
|
5
|
+
const line4 = 4;
|
|
6
|
+
const line5 = 5;
|
|
7
|
+
const line6 = 6;
|
|
8
|
+
const line7 = 7;
|
|
9
|
+
const line8 = 8;
|
|
10
|
+
const line9 = 9;
|
|
11
|
+
const line10 = 10;
|
|
12
|
+
const line11 = 11;
|
|
13
|
+
const line12 = 12;
|
|
14
|
+
const line13 = 13;
|
|
15
|
+
const line14 = 14;
|
|
16
|
+
const line15 = 15;
|
|
17
|
+
const line16 = 16;
|
|
18
|
+
const line17 = 17;
|
|
19
|
+
const line18 = 18;
|
|
20
|
+
const line19 = 19;
|
|
21
|
+
const line20 = 20;
|
|
22
|
+
const line21 = 21;
|
|
23
|
+
const line22 = 22;
|
|
24
|
+
const line23 = 23;
|
|
25
|
+
const line24 = 24;
|
|
26
|
+
const line25 = 25;
|
|
27
|
+
const line26 = 26;
|
|
28
|
+
const line27 = 27;
|
|
29
|
+
const line28 = 28;
|
|
30
|
+
const line29 = 29;
|
|
31
|
+
const line30 = 30;
|
|
32
|
+
const line31 = 31;
|
|
33
|
+
const line32 = 32;
|
|
34
|
+
const line33 = 33;
|
|
35
|
+
const line34 = 34;
|
|
36
|
+
const line35 = 35;
|
|
37
|
+
const line36 = 36;
|
|
38
|
+
const line37 = 37;
|
|
39
|
+
const line38 = 38;
|
|
40
|
+
const line39 = 39;
|
|
41
|
+
const line40 = 40;
|
|
42
|
+
const line41 = 41;
|
|
43
|
+
const line42 = 42;
|
|
44
|
+
const line43 = 43;
|
|
45
|
+
const line44 = 44;
|
|
46
|
+
const line45 = 45;
|
|
47
|
+
const line46 = 46;
|
|
48
|
+
const line47 = 47;
|
|
49
|
+
const line48 = 48;
|
|
50
|
+
const line49 = 49;
|
|
51
|
+
const line50 = 50;
|
|
52
|
+
const line51 = 51;
|
|
53
|
+
const line52 = 52;
|
|
54
|
+
const line53 = 53;
|
|
55
|
+
const line54 = 54;
|
|
56
|
+
const line55 = 55;
|
|
57
|
+
const line56 = 56;
|
|
58
|
+
const line57 = 57;
|
|
59
|
+
const line58 = 58;
|
|
60
|
+
const line59 = 59;
|
|
61
|
+
const line60 = 60;
|
|
62
|
+
const line61 = 61;
|
|
63
|
+
const line62 = 62;
|
|
64
|
+
const line63 = 63;
|
|
65
|
+
const line64 = 64;
|
|
66
|
+
const line65 = 65;
|
|
67
|
+
const line66 = 66;
|
|
68
|
+
const line67 = 67;
|
|
69
|
+
const line68 = 68;
|
|
70
|
+
const line69 = 69;
|
|
71
|
+
const line70 = 70;
|
|
72
|
+
const line71 = 71;
|
|
73
|
+
const line72 = 72;
|
|
74
|
+
const line73 = 73;
|
|
75
|
+
const line74 = 74;
|
|
76
|
+
const line75 = 75;
|
|
77
|
+
const line76 = 76;
|
|
78
|
+
const line77 = 77;
|
|
79
|
+
const line78 = 78;
|
|
80
|
+
const line79 = 79;
|
|
81
|
+
const line80 = 80;
|
|
82
|
+
const line81 = 81;
|
|
83
|
+
const line82 = 82;
|
|
84
|
+
const line83 = 83;
|
|
85
|
+
const line84 = 84;
|
|
86
|
+
const line85 = 85;
|
|
87
|
+
const line86 = 86;
|
|
88
|
+
const line87 = 87;
|
|
89
|
+
const line88 = 88;
|
|
90
|
+
const line89 = 89;
|
|
91
|
+
const line90 = 90;
|
|
92
|
+
const line91 = 91;
|
|
93
|
+
const line92 = 92;
|
|
94
|
+
const line93 = 93;
|
|
95
|
+
const line94 = 94;
|
|
96
|
+
const line95 = 95;
|
|
97
|
+
const line96 = 96;
|
|
98
|
+
const line97 = 97;
|
|
99
|
+
const line98 = 98;
|
|
100
|
+
const line99 = 99;
|
|
101
|
+
const line100 = 100;
|
|
102
|
+
const line101 = 101;
|
|
103
|
+
const line102 = 102;
|
|
104
|
+
const line103 = 103;
|
|
105
|
+
const line104 = 104;
|
|
106
|
+
const line105 = 105;
|
|
107
|
+
const line106 = 106;
|
|
108
|
+
const line107 = 107;
|
|
109
|
+
const line108 = 108;
|
|
110
|
+
const line109 = 109;
|
|
111
|
+
const line110 = 110;
|
|
112
|
+
|
|
113
|
+
export default line1;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// Invalid: File with 70-100 lines (should trigger max-lines warning)
|
|
2
|
+
// This file demonstrates what happens when a file grows beyond the recommended size
|
|
3
|
+
|
|
4
|
+
class ExtendedNumberUtils {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.cache = new Map();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
calculateSum(numbers) {
|
|
10
|
+
const key = numbers.join(',');
|
|
11
|
+
if (this.cache.has(key)) {
|
|
12
|
+
return this.cache.get(key);
|
|
13
|
+
}
|
|
14
|
+
const sum = numbers.reduce((acc, num) => acc + num, 0);
|
|
15
|
+
this.cache.set(key, sum);
|
|
16
|
+
return sum;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
calculateAverage(numbers) {
|
|
20
|
+
if (numbers.length === 0) return 0;
|
|
21
|
+
return this.calculateSum(numbers) / numbers.length;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
findMaxValue(numbers) {
|
|
25
|
+
if (numbers.length === 0) return null;
|
|
26
|
+
return Math.max(...numbers);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
findMinValue(numbers) {
|
|
30
|
+
if (numbers.length === 0) return null;
|
|
31
|
+
return Math.min(...numbers);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
sortNumbers(numbers) {
|
|
35
|
+
return [...numbers].sort((a, b) => a - b);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
filterEvenNumbers(numbers) {
|
|
39
|
+
return numbers.filter(num => num % 2 === 0);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
filterOddNumbers(numbers) {
|
|
43
|
+
return numbers.filter(num => num % 2 !== 0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
multiplyByTwo(numbers) {
|
|
47
|
+
return numbers.map(num => num * 2);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
containsNumber(numbers, target) {
|
|
51
|
+
return numbers.includes(target);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
removeNumber(numbers, target) {
|
|
55
|
+
return numbers.filter(num => num !== target);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
addNumber(numbers, newNumber) {
|
|
59
|
+
return [...numbers, newNumber];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
getNumberAtIndex(numbers, index) {
|
|
63
|
+
if (index < 0 || index >= numbers.length) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
return numbers[index];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getLastNumber(numbers) {
|
|
70
|
+
return numbers.length > 0 ? numbers[numbers.length - 1] : undefined;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
getFirstNumber(numbers) {
|
|
74
|
+
return numbers.length > 0 ? numbers[0] : undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
reverseNumbers(numbers) {
|
|
78
|
+
return [...numbers].reverse();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
shuffleNumbers(numbers) {
|
|
82
|
+
const shuffled = [...numbers];
|
|
83
|
+
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
84
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
85
|
+
const temp = shuffled[i];
|
|
86
|
+
shuffled[i] = shuffled[j];
|
|
87
|
+
shuffled[j] = temp;
|
|
88
|
+
}
|
|
89
|
+
return shuffled;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
getUniqueNumbers(numbers) {
|
|
93
|
+
return [...new Set(numbers)];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
getDuplicateNumbers(numbers) {
|
|
97
|
+
const seen = new Set();
|
|
98
|
+
const duplicates = new Set();
|
|
99
|
+
for (const num of numbers) {
|
|
100
|
+
if (seen.has(num)) {
|
|
101
|
+
duplicates.add(num);
|
|
102
|
+
} else {
|
|
103
|
+
seen.add(num);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return [...duplicates];
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
countOccurrences(numbers, target) {
|
|
110
|
+
return numbers.filter(num => num === target).length;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
getNumbersInRange(numbers, min, max) {
|
|
114
|
+
return numbers.filter(num => num >= min && num <= max);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
clearCache() {
|
|
118
|
+
this.cache.clear();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
getCacheSize() {
|
|
122
|
+
return this.cache.size;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// This file has between 70-100 lines and should trigger a max-lines warning
|
|
127
|
+
export default ExtendedNumberUtils;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// Invalid: TypeScript file with way more than 100 lines (should trigger max-lines error)
|
|
2
|
+
interface User { id: number; name: string; email: string; }
|
|
3
|
+
interface Product { id: number; title: string; price: number; }
|
|
4
|
+
interface Order { id: number; userId: number; products: Product[]; }
|
|
5
|
+
|
|
6
|
+
const user1: User = { id: 1, name: 'John', email: 'john@example.com' };
|
|
7
|
+
const user2: User = { id: 2, name: 'Jane', email: 'jane@example.com' };
|
|
8
|
+
const user3: User = { id: 3, name: 'Bob', email: 'bob@example.com' };
|
|
9
|
+
const user4: User = { id: 4, name: 'Alice', email: 'alice@example.com' };
|
|
10
|
+
const user5: User = { id: 5, name: 'Charlie', email: 'charlie@example.com' };
|
|
11
|
+
const user6: User = { id: 6, name: 'Diana', email: 'diana@example.com' };
|
|
12
|
+
const user7: User = { id: 7, name: 'Eve', email: 'eve@example.com' };
|
|
13
|
+
const user8: User = { id: 8, name: 'Frank', email: 'frank@example.com' };
|
|
14
|
+
const user9: User = { id: 9, name: 'Grace', email: 'grace@example.com' };
|
|
15
|
+
const user10: User = { id: 10, name: 'Henry', email: 'henry@example.com' };
|
|
16
|
+
|
|
17
|
+
const product1: Product = { id: 1, title: 'Laptop', price: 999 };
|
|
18
|
+
const product2: Product = { id: 2, title: 'Mouse', price: 25 };
|
|
19
|
+
const product3: Product = { id: 3, title: 'Keyboard', price: 75 };
|
|
20
|
+
const product4: Product = { id: 4, title: 'Monitor', price: 300 };
|
|
21
|
+
const product5: Product = { id: 5, title: 'Headphones', price: 150 };
|
|
22
|
+
const product6: Product = { id: 6, title: 'Webcam', price: 80 };
|
|
23
|
+
const product7: Product = { id: 7, title: 'Speakers', price: 120 };
|
|
24
|
+
const product8: Product = { id: 8, title: 'Microphone', price: 200 };
|
|
25
|
+
const product9: Product = { id: 9, title: 'Tablet', price: 500 };
|
|
26
|
+
const product10: Product = { id: 10, title: 'Phone', price: 700 };
|
|
27
|
+
const product11: Product = { id: 11, title: 'Charger', price: 30 };
|
|
28
|
+
const product12: Product = { id: 12, title: 'Cable', price: 15 };
|
|
29
|
+
const product13: Product = { id: 13, title: 'Case', price: 40 };
|
|
30
|
+
const product14: Product = { id: 14, title: 'Stand', price: 60 };
|
|
31
|
+
const product15: Product = { id: 15, title: 'Bag', price: 90 };
|
|
32
|
+
|
|
33
|
+
const order1: Order = { id: 1, userId: 1, products: [product1, product2] };
|
|
34
|
+
const order2: Order = { id: 2, userId: 2, products: [product3] };
|
|
35
|
+
const order3: Order = { id: 3, userId: 3, products: [product4, product5, product6] };
|
|
36
|
+
const order4: Order = { id: 4, userId: 4, products: [product7, product8] };
|
|
37
|
+
const order5: Order = { id: 5, userId: 5, products: [product9] };
|
|
38
|
+
const order6: Order = { id: 6, userId: 6, products: [product10, product11] };
|
|
39
|
+
const order7: Order = { id: 7, userId: 7, products: [product12, product13, product14] };
|
|
40
|
+
const order8: Order = { id: 8, userId: 8, products: [product15] };
|
|
41
|
+
const order9: Order = { id: 9, userId: 9, products: [product1, product3, product5] };
|
|
42
|
+
const order10: Order = { id: 10, userId: 10, products: [product2, product4] };
|
|
43
|
+
|
|
44
|
+
export class OrderManagementService {
|
|
45
|
+
private users = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10];
|
|
46
|
+
private products = [product1, product2, product3, product4, product5, product6, product7, product8, product9, product10, product11, product12, product13, product14, product15];
|
|
47
|
+
private orders = [order1, order2, order3, order4, order5, order6, order7, order8, order9, order10];
|
|
48
|
+
|
|
49
|
+
getUserById(id: number): User | undefined {
|
|
50
|
+
return this.users.find(user => user.id === id);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
getProductById(id: number): Product | undefined {
|
|
54
|
+
return this.products.find(product => product.id === id);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getOrderById(id: number): Order | undefined {
|
|
58
|
+
return this.orders.find(order => order.id === id);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
getUserOrders(userId: number): Order[] {
|
|
62
|
+
return this.orders.filter(order => order.userId === userId);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
calculateOrderTotal(order: Order): number {
|
|
66
|
+
return order.products.reduce((total, product) => total + product.price, 0);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
getExpensiveProducts(minPrice: number): Product[] {
|
|
70
|
+
return this.products.filter(product => product.price >= minPrice);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
getCheapProducts(maxPrice: number): Product[] {
|
|
74
|
+
return this.products.filter(product => product.price <= maxPrice);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
searchProductsByTitle(query: string): Product[] {
|
|
78
|
+
return this.products.filter(product => product.title.toLowerCase().includes(query.toLowerCase()));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
getUsersWithOrders(): User[] {
|
|
82
|
+
const userIdsWithOrders = new Set(this.orders.map(order => order.userId));
|
|
83
|
+
return this.users.filter(user => userIdsWithOrders.has(user.id));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
getMostExpensiveOrder(): Order | undefined {
|
|
87
|
+
let maxOrder: Order | undefined;
|
|
88
|
+
let maxTotal = 0;
|
|
89
|
+
|
|
90
|
+
for (const order of this.orders) {
|
|
91
|
+
const total = this.calculateOrderTotal(order);
|
|
92
|
+
if (total > maxTotal) {
|
|
93
|
+
maxTotal = total;
|
|
94
|
+
maxOrder = order;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return maxOrder;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
getOrdersByPriceRange(minPrice: number, maxPrice: number): Order[] {
|
|
102
|
+
return this.orders.filter(order => {
|
|
103
|
+
const total = this.calculateOrderTotal(order);
|
|
104
|
+
return total >= minPrice && total <= maxPrice;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
getPopularProducts(): Product[] {
|
|
109
|
+
const productCount = new Map<number, number>();
|
|
110
|
+
|
|
111
|
+
for (const order of this.orders) {
|
|
112
|
+
for (const product of order.products) {
|
|
113
|
+
productCount.set(product.id, (productCount.get(product.id) || 0) + 1);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return this.products.filter(product => (productCount.get(product.id) || 0) > 1).sort((a, b) => (productCount.get(b.id) || 0) - (productCount.get(a.id) || 0));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getAverageOrderValue(): number {
|
|
121
|
+
const totalValue = this.orders.reduce((sum, order) => sum + this.calculateOrderTotal(order), 0);
|
|
122
|
+
return totalValue / this.orders.length;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
getUserSpending(userId: number): number {
|
|
126
|
+
const userOrders = this.getUserOrders(userId);
|
|
127
|
+
return userOrders.reduce((total, order) => total + this.calculateOrderTotal(order), 0);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
getTopSpendingUsers(limit: number = 5): Array<{ user: User; totalSpent: number }> {
|
|
131
|
+
const userSpending = this.users.map(user => ({
|
|
132
|
+
user,
|
|
133
|
+
totalSpent: this.getUserSpending(user.id)
|
|
134
|
+
}));
|
|
135
|
+
|
|
136
|
+
return userSpending.sort((a, b) => b.totalSpent - a.totalSpent).slice(0, limit);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const data1 = 'extra'; const data2 = 'data'; const data3 = 'to'; const data4 = 'make'; const data5 = 'file';
|
|
141
|
+
const data6 = 'longer'; const data7 = 'than'; const data8 = '100'; const data9 = 'lines'; const data10 = 'for';
|
|
142
|
+
const data11 = 'testing'; const data12 = 'max'; const data13 = 'lines'; const data14 = 'rule'; const data15 = 'error';
|
|
143
|
+
|
|
144
|
+
// This file has way more than 100 lines and should trigger a max-lines error
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// Valid: Short file under 70 lines (no warnings or errors)
|
|
2
|
+
// This file demonstrates proper file length management
|
|
3
|
+
|
|
4
|
+
export class NumberUtils {
|
|
5
|
+
static calculateSum(numbers) {
|
|
6
|
+
return numbers.reduce((sum, num) => sum + num, 0);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
static calculateAverage(numbers) {
|
|
10
|
+
if (numbers.length === 0) return 0;
|
|
11
|
+
return this.calculateSum(numbers) / numbers.length;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static findMaxValue(numbers) {
|
|
15
|
+
if (numbers.length === 0) return null;
|
|
16
|
+
return Math.max(...numbers);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
static findMinValue(numbers) {
|
|
20
|
+
if (numbers.length === 0) return null;
|
|
21
|
+
return Math.min(...numbers);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static sortNumbers(numbers) {
|
|
25
|
+
return [...numbers].sort((a, b) => a - b);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static filterEvenNumbers(numbers) {
|
|
29
|
+
return numbers.filter((num) => num % 2 === 0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static filterOddNumbers(numbers) {
|
|
33
|
+
return numbers.filter((num) => num % 2 !== 0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static multiplyByTwo(numbers) {
|
|
37
|
+
return numbers.map((num) => num * 2);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static containsNumber(numbers, target) {
|
|
41
|
+
return numbers.includes(target);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static removeNumber(numbers, target) {
|
|
45
|
+
return numbers.filter((num) => num !== target);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
static addNumber(numbers, newNumber) {
|
|
49
|
+
return [...numbers, newNumber];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static getUniqueNumbers(numbers) {
|
|
53
|
+
return [...new Set(numbers)];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static reverseNumbers(numbers) {
|
|
57
|
+
return [...numbers].reverse();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static getNumbersInRange(numbers, min, max) {
|
|
61
|
+
return numbers.filter((num) => num >= min && num <= max);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// This file has less than 70 lines and should not trigger any max-lines warnings or errors
|
|
66
|
+
export default NumberUtils;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Valid: Spec file that ignores max-lines rule regardless of length
|
|
2
|
+
describe('Long spec file test', () => {
|
|
3
|
+
const testData1 = 'data1'; const testData2 = 'data2'; const testData3 = 'data3';
|
|
4
|
+
const testData4 = 'data4'; const testData5 = 'data5'; const testData6 = 'data6';
|
|
5
|
+
const testData7 = 'data7'; const testData8 = 'data8'; const testData9 = 'data9';
|
|
6
|
+
const testData10 = 'data10'; const testData11 = 'data11'; const testData12 = 'data12';
|
|
7
|
+
const testData13 = 'data13'; const testData14 = 'data14'; const testData15 = 'data15';
|
|
8
|
+
const testData16 = 'data16'; const testData17 = 'data17'; const testData18 = 'data18';
|
|
9
|
+
const testData19 = 'data19'; const testData20 = 'data20'; const testData21 = 'data21';
|
|
10
|
+
const testData22 = 'data22'; const testData23 = 'data23'; const testData24 = 'data24';
|
|
11
|
+
const testData25 = 'data25'; const testData26 = 'data26'; const testData27 = 'data27';
|
|
12
|
+
const testData28 = 'data28'; const testData29 = 'data29'; const testData30 = 'data30';
|
|
13
|
+
const testData31 = 'data31'; const testData32 = 'data32'; const testData33 = 'data33';
|
|
14
|
+
const testData34 = 'data34'; const testData35 = 'data35'; const testData36 = 'data36';
|
|
15
|
+
const testData37 = 'data37'; const testData38 = 'data38'; const testData39 = 'data39';
|
|
16
|
+
const testData40 = 'data40'; const testData41 = 'data41'; const testData42 = 'data42';
|
|
17
|
+
const testData43 = 'data43'; const testData44 = 'data44'; const testData45 = 'data45';
|
|
18
|
+
const testData46 = 'data46'; const testData47 = 'data47'; const testData48 = 'data48';
|
|
19
|
+
const testData49 = 'data49'; const testData50 = 'data50'; const testData51 = 'data51';
|
|
20
|
+
const testData52 = 'data52'; const testData53 = 'data53'; const testData54 = 'data54';
|
|
21
|
+
const testData55 = 'data55'; const testData56 = 'data56'; const testData57 = 'data57';
|
|
22
|
+
const testData58 = 'data58'; const testData59 = 'data59'; const testData60 = 'data60';
|
|
23
|
+
const testData61 = 'data61'; const testData62 = 'data62'; const testData63 = 'data63';
|
|
24
|
+
const testData64 = 'data64'; const testData65 = 'data65'; const testData66 = 'data66';
|
|
25
|
+
const testData67 = 'data67'; const testData68 = 'data68'; const testData69 = 'data69';
|
|
26
|
+
const testData70 = 'data70'; const testData71 = 'data71'; const testData72 = 'data72';
|
|
27
|
+
const testData73 = 'data73'; const testData74 = 'data74'; const testData75 = 'data75';
|
|
28
|
+
const testData76 = 'data76'; const testData77 = 'data77'; const testData78 = 'data78';
|
|
29
|
+
const testData79 = 'data79'; const testData80 = 'data80'; const testData81 = 'data81';
|
|
30
|
+
const testData82 = 'data82'; const testData83 = 'data83'; const testData84 = 'data84';
|
|
31
|
+
const testData85 = 'data85'; const testData86 = 'data86'; const testData87 = 'data87';
|
|
32
|
+
const testData88 = 'data88'; const testData89 = 'data89'; const testData90 = 'data90';
|
|
33
|
+
const testData91 = 'data91'; const testData92 = 'data92'; const testData93 = 'data93';
|
|
34
|
+
const testData94 = 'data94'; const testData95 = 'data95'; const testData96 = 'data96';
|
|
35
|
+
const testData97 = 'data97'; const testData98 = 'data98'; const testData99 = 'data99';
|
|
36
|
+
const testData100 = 'data100'; const testData101 = 'data101'; const testData102 = 'data102';
|
|
37
|
+
const testData103 = 'data103'; const testData104 = 'data104'; const testData105 = 'data105';
|
|
38
|
+
const testData106 = 'data106'; const testData107 = 'data107'; const testData108 = 'data108';
|
|
39
|
+
const testData109 = 'data109'; const testData110 = 'data110'; const testData111 = 'data111';
|
|
40
|
+
|
|
41
|
+
it('should handle long spec files without max-lines errors', () => {
|
|
42
|
+
expect(testData1).toBe('data1');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Valid: Test file that ignores max-lines rule regardless of length
|
|
2
|
+
const line1 = 1; const line2 = 2; const line3 = 3; const line4 = 4; const line5 = 5;
|
|
3
|
+
const line6 = 6; const line7 = 7; const line8 = 8; const line9 = 9; const line10 = 10;
|
|
4
|
+
const line11 = 11; const line12 = 12; const line13 = 13; const line14 = 14; const line15 = 15;
|
|
5
|
+
const line16 = 16; const line17 = 17; const line18 = 18; const line19 = 19; const line20 = 20;
|
|
6
|
+
const line21 = 21; const line22 = 22; const line23 = 23; const line24 = 24; const line25 = 25;
|
|
7
|
+
const line26 = 26; const line27 = 27; const line28 = 28; const line29 = 29; const line30 = 30;
|
|
8
|
+
const line31 = 31; const line32 = 32; const line33 = 33; const line34 = 34; const line35 = 35;
|
|
9
|
+
const line36 = 36; const line37 = 37; const line38 = 38; const line39 = 39; const line40 = 40;
|
|
10
|
+
const line41 = 41; const line42 = 42; const line43 = 43; const line44 = 44; const line45 = 45;
|
|
11
|
+
const line46 = 46; const line47 = 47; const line48 = 48; const line49 = 49; const line50 = 50;
|
|
12
|
+
const line51 = 51; const line52 = 52; const line53 = 53; const line54 = 54; const line55 = 55;
|
|
13
|
+
const line56 = 56; const line57 = 57; const line58 = 58; const line59 = 59; const line60 = 60;
|
|
14
|
+
const line61 = 61; const line62 = 62; const line63 = 63; const line64 = 64; const line65 = 65;
|
|
15
|
+
const line66 = 66; const line67 = 67; const line68 = 68; const line69 = 69; const line70 = 70;
|
|
16
|
+
const line71 = 71; const line72 = 72; const line73 = 73; const line74 = 74; const line75 = 75;
|
|
17
|
+
const line76 = 76; const line77 = 77; const line78 = 78; const line79 = 79; const line80 = 80;
|
|
18
|
+
const line81 = 81; const line82 = 82; const line83 = 83; const line84 = 84; const line85 = 85;
|
|
19
|
+
const line86 = 86; const line87 = 87; const line88 = 88; const line89 = 89; const line90 = 90;
|
|
20
|
+
const line91 = 91; const line92 = 92; const line93 = 93; const line94 = 94; const line95 = 95;
|
|
21
|
+
const line96 = 96; const line97 = 97; const line98 = 98; const line99 = 99; const line100 = 100;
|
|
22
|
+
const line101 = 101; const line102 = 102; const line103 = 103; const line104 = 104; const line105 = 105;
|
|
23
|
+
const line106 = 106; const line107 = 107; const line108 = 108; const line109 = 109; const line110 = 110;
|
|
24
|
+
|
|
25
|
+
export default line1;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Rule to prevent export { } statements of any length
|
|
2
|
+
|
|
3
|
+
const selector = 'ExportNamedDeclaration:not([source]):not(:has(VariableDeclaration)):not(:has(FunctionDeclaration)):not(:has(ClassDeclaration)):not(:has(TSInterfaceDeclaration)):not(:has(TSTypeAliasDeclaration)):not(:has(TSEnumDeclaration))';
|
|
4
|
+
const message = 'Export specifier syntax "export { ... }" is not allowed. Use direct exports instead.';
|
|
5
|
+
|
|
6
|
+
const rule = {
|
|
7
|
+
selector,
|
|
8
|
+
message,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const noExportSpecifiersConfig = {
|
|
12
|
+
selector,
|
|
13
|
+
message,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export { rule, selector, message, noExportSpecifiersConfig };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { RuleTester } from "eslint";
|
|
2
|
+
import { selector, message } from "./index.js";
|
|
3
|
+
|
|
4
|
+
const ruleTester = new RuleTester({
|
|
5
|
+
languageOptions: {
|
|
6
|
+
ecmaVersion: 2022,
|
|
7
|
+
sourceType: "module",
|
|
8
|
+
parserOptions: {
|
|
9
|
+
ecmaFeatures: {
|
|
10
|
+
jsx: true,
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Create a mock rule for testing
|
|
17
|
+
const mockRule = {
|
|
18
|
+
meta: {
|
|
19
|
+
type: "problem",
|
|
20
|
+
docs: {
|
|
21
|
+
description: "Disallow empty export statements",
|
|
22
|
+
},
|
|
23
|
+
schema: [],
|
|
24
|
+
},
|
|
25
|
+
create(context) {
|
|
26
|
+
return {
|
|
27
|
+
[selector]: (node) => {
|
|
28
|
+
context.report({
|
|
29
|
+
node,
|
|
30
|
+
message,
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
ruleTester.run("no-empty-exports", mockRule, {
|
|
38
|
+
valid: [
|
|
39
|
+
// Named exports with declarations
|
|
40
|
+
'export const foo = 1;',
|
|
41
|
+
'export function bar() {}',
|
|
42
|
+
'export class Baz {}',
|
|
43
|
+
|
|
44
|
+
// Default exports
|
|
45
|
+
'const foo = 1; export default foo;',
|
|
46
|
+
'export default function() {}',
|
|
47
|
+
'export default class {}',
|
|
48
|
+
|
|
49
|
+
// Re-exports from other modules (allowed)
|
|
50
|
+
'export { } from "./other";',
|
|
51
|
+
'export { foo } from "./other";',
|
|
52
|
+
'export * from "./other";',
|
|
53
|
+
'export * as namespace from "./other";',
|
|
54
|
+
|
|
55
|
+
// Regular exports
|
|
56
|
+
'const Bar = {}; export { Bar };',
|
|
57
|
+
|
|
58
|
+
// No exports at all
|
|
59
|
+
'const foo = 1;',
|
|
60
|
+
'function bar() {}',
|
|
61
|
+
'class Baz {}',
|
|
62
|
+
|
|
63
|
+
// Named exports with local variables
|
|
64
|
+
'const foo = 1; const bar = 2; export { foo };',
|
|
65
|
+
'const foo = 1; const bar = 2; export { foo, bar };',
|
|
66
|
+
'const foo = 1; export { foo as bar };',
|
|
67
|
+
],
|
|
68
|
+
invalid: [
|
|
69
|
+
{
|
|
70
|
+
code: 'export { };',
|
|
71
|
+
errors: [{ message }],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
code: 'export {\n};',
|
|
75
|
+
errors: [{ message }],
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
code: 'export { };',
|
|
79
|
+
errors: [{ message }],
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
code: `export {
|
|
83
|
+
};`,
|
|
84
|
+
errors: [{ message }],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
code: 'export { /* comment */ };',
|
|
88
|
+
errors: [{ message }],
|
|
89
|
+
},
|
|
90
|
+
// Multiple empty exports
|
|
91
|
+
{
|
|
92
|
+
code: `export { };
|
|
93
|
+
export { };`,
|
|
94
|
+
errors: [{ message }, { message }],
|
|
95
|
+
},
|
|
96
|
+
// Mixed with valid exports
|
|
97
|
+
{
|
|
98
|
+
code: `export const foo = 1;
|
|
99
|
+
export { };
|
|
100
|
+
export function bar() {}`,
|
|
101
|
+
errors: [{ message }],
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
});
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { noUnusedModulesConfig } from "./no-unused-modules/index.js";
|
|
2
|
+
import { groupExportsConfig } from "./group-exports/index.js";
|
|
3
|
+
|
|
1
4
|
export const importRules = {
|
|
2
5
|
// Import/export organization and restrictions
|
|
3
|
-
|
|
6
|
+
...groupExportsConfig,
|
|
4
7
|
"import/no-default-export": "off", // Allow default exports
|
|
5
8
|
"import/no-namespace": "error",
|
|
9
|
+
...noUnusedModulesConfig,
|
|
6
10
|
// Disabled import rules (keep existing behavior)
|
|
7
11
|
"import/extensions": ["off"],
|
|
8
12
|
"import/no-extraneous-dependencies": ["off"],
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Valid: This module consumes exports from other modules
|
|
2
|
+
import { apiUrl } from './used-export.js';
|
|
3
|
+
import { fetchData } from './used-function.js';
|
|
4
|
+
import { DataProcessor } from './used-class.js';
|
|
5
|
+
|
|
6
|
+
const processor = new DataProcessor();
|
|
7
|
+
fetchData().then(data => processor.process(data));
|
|
8
|
+
console.log(`API URL: ${apiUrl}`);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// Note: import/no-unused-modules has compatibility issues with ESLint flat config
|
|
2
|
+
// It requires an .eslintrc file and has complex setup requirements
|
|
3
|
+
// For now, this rule is disabled to avoid configuration conflicts
|
|
4
|
+
export const noUnusedModulesConfig = {
|
|
5
|
+
// "import/no-unused-modules": "off", // Disabled due to flat config compatibility issues
|
|
6
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Valid: Using generics instead of any
|
|
2
|
+
export function identity<T>(value: T): T {
|
|
3
|
+
return value;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export class Container<T> {
|
|
7
|
+
private value: T;
|
|
8
|
+
|
|
9
|
+
constructor(value: T) {
|
|
10
|
+
this.value = value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getValue(): T {
|
|
14
|
+
return this.value;
|
|
15
|
+
}
|
|
16
|
+
}
|