eslint-config-agent 1.1.2 → 1.1.3

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 CHANGED
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. See [Conven
4
4
 
5
5
 
6
6
 
7
+ ## [1.1.3](https://github.com/tupe12334/eslint-config/compare/v1.1.2...v1.1.3) (2025-09-10)
8
+
9
+ ### Features
10
+
11
+ * add no-type-assertions rule to disallow TypeScript type assertions using "as" keyword ([39b708f](https://github.com/tupe12334/eslint-config/commit/39b708f9da6eb0c491b0e53248af78821f4b3598))
12
+ * consolidate ESLint rule imports into a single index file for better organization ([37be460](https://github.com/tupe12334/eslint-config/commit/37be46083350d151a5803b9c230c538caa9eb857))
13
+ * refactor ESLint rule imports to use a consolidated allRules object for improved organization ([47c3eea](https://github.com/tupe12334/eslint-config/commit/47c3eea5f02dd204bf86ab6150d319eed07440da))
14
+
7
15
  ## [1.1.2](https://github.com/tupe12334/eslint-config/compare/v1.1.1...v1.1.2) (2025-09-10)
8
16
 
9
17
  ### Features
package/index.js CHANGED
@@ -9,12 +9,7 @@ import nPlugin from "eslint-plugin-n";
9
9
  import classExportPlugin from "eslint-plugin-class-export";
10
10
  import storybookPlugin from "eslint-plugin-storybook";
11
11
  import globals from "globals";
12
- import noTrailingSpacesConfig from "./rules/no-trailing-spaces/index.js";
13
- import { maxFunctionLinesWarning, maxFunctionLinesError } from "./rules/max-function-lines/index.js";
14
- import { maxFileLinesWarning, maxFileLinesError } from "./rules/max-file-lines/index.js";
15
- import { pluginRules } from "./rules/plugin/index.js";
16
- import { typescriptEslintRules } from "./rules/plugin/typescript-eslint/index.js";
17
- import { noProcessEnvPropertiesConfig } from "./rules/no-process-env-properties/index.js";
12
+ import allRules from "./rules/index.js";
18
13
 
19
14
  // Conditionally import preact plugin if available
20
15
  let preactPlugin = null;
@@ -27,18 +22,18 @@ try {
27
22
 
28
23
  // Shared rules for both JS and TS files
29
24
  const sharedRules = {
30
- ...pluginRules,
25
+ ...allRules.pluginRules,
31
26
  "object-curly-newline": "off",
32
27
  "no-shadow": "off",
33
28
  "comma-dangle": "off",
34
29
  "function-paren-newline": "off",
35
30
  quotes: "off",
36
31
  "no-unused-vars": "off",
37
- "max-lines-per-function": maxFunctionLinesWarning,
38
- "max-lines": maxFileLinesWarning,
32
+ "max-lines-per-function": allRules.maxFunctionLinesWarning,
33
+ "max-lines": allRules.maxFileLinesWarning,
39
34
  semi: "off",
40
35
  complexity: "off",
41
- "no-trailing-spaces": noTrailingSpacesConfig,
36
+ "no-trailing-spaces": allRules.noTrailingSpacesConfig,
42
37
  "operator-linebreak": "off",
43
38
  "implicit-arrow-linebreak": "off",
44
39
  "arrow-body-style": "off",
@@ -99,7 +94,7 @@ const sharedRestrictedSyntax = [
99
94
  message:
100
95
  "Exporting from external libraries is not allowed. Only re-export from relative paths or scoped packages.",
101
96
  },
102
- noProcessEnvPropertiesConfig,
97
+ allRules.noProcessEnvPropertiesConfig,
103
98
  ];
104
99
 
105
100
  // Required export rules (always errors)
@@ -148,11 +143,7 @@ const tsOnlyRestrictedSyntax = [
148
143
  message:
149
144
  "Class properties with literal unions should use a named type declaration.",
150
145
  },
151
- {
152
- selector:
153
- 'TSAsExpression:not(:has(TSTypeReference[typeName.name="const"]))',
154
- message: 'Type assertions with "as" are not allowed except for "as const".',
155
- },
146
+ allRules.noTypeAssertionsConfig,
156
147
  {
157
148
  selector: "TSAsExpression:has(> TSIndexedAccessType > TSTypeQuery)",
158
149
  message:
@@ -257,7 +248,7 @@ const config = [
257
248
  },
258
249
  rules: {
259
250
  ...sharedRules,
260
- ...typescriptEslintRules,
251
+ ...allRules.typescriptEslintRules,
261
252
  "no-undef": "off", // TypeScript handles this
262
253
  "no-restricted-syntax": [
263
254
  "error",
@@ -867,7 +858,8 @@ const config = [
867
858
  message:
868
859
  'Type assertions with indexed access types like "as (typeof X)[number]" are not allowed. Use a named type instead.',
869
860
  },
870
- noProcessEnvPropertiesConfig,
861
+ allRules.noTypeAssertionsConfig,
862
+ allRules.noProcessEnvPropertiesConfig,
871
863
  // Export restriction rules
872
864
  // Required export rules
873
865
  ...requiredExportRules,
@@ -897,9 +889,9 @@ const config = [
897
889
  ignores: ["**/*.stories.{js,jsx,ts,tsx}"],
898
890
  rules: {
899
891
  // Function length: error at 70+ lines
900
- "max-lines-per-function": maxFunctionLinesError,
892
+ "max-lines-per-function": allRules.maxFunctionLinesError,
901
893
  // File length: error at 100+ lines
902
- "max-lines": maxFileLinesError,
894
+ "max-lines": allRules.maxFileLinesError,
903
895
  },
904
896
  },
905
897
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-config-agent",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "ESLint configuration package with TypeScript support",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/rules/index.js ADDED
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Aggregated exports for all custom ESLint rules
3
+ *
4
+ * This file centralizes imports from all rule modules in the rules/ directory
5
+ * and re-exports them for easier consumption by the main configuration.
6
+ */
7
+
8
+ // Core rule configurations
9
+ import noTrailingSpacesConfig from "./no-trailing-spaces/index.js";
10
+ import { maxFunctionLinesWarning, maxFunctionLinesError } from "./max-function-lines/index.js";
11
+ import { maxFileLinesWarning, maxFileLinesError } from "./max-file-lines/index.js";
12
+
13
+ // Custom restricted syntax rules
14
+ import { noProcessEnvPropertiesConfig } from "./no-process-env-properties/index.js";
15
+ import { noTypeAssertionsConfig } from "./no-type-assertions/index.js";
16
+
17
+ // Plugin rule configurations
18
+ import { pluginRules } from "./plugin/index.js";
19
+ import { typescriptEslintRules } from "./plugin/typescript-eslint/index.js";
20
+
21
+ // Consolidated exports
22
+ const allRules = {
23
+ // Core rule configurations
24
+ noTrailingSpacesConfig,
25
+ maxFunctionLinesWarning,
26
+ maxFunctionLinesError,
27
+ maxFileLinesWarning,
28
+ maxFileLinesError,
29
+
30
+ // Custom restricted syntax rules
31
+ noProcessEnvPropertiesConfig,
32
+ noTypeAssertionsConfig,
33
+
34
+ // Plugin rule configurations
35
+ pluginRules,
36
+ typescriptEslintRules,
37
+ };
38
+
39
+ export default allRules;
40
+
41
+ // Named exports for backward compatibility
42
+ export {
43
+ // Core rule configurations
44
+ noTrailingSpacesConfig,
45
+ maxFunctionLinesWarning,
46
+ maxFunctionLinesError,
47
+ maxFileLinesWarning,
48
+ maxFileLinesError,
49
+
50
+ // Custom restricted syntax rules
51
+ noProcessEnvPropertiesConfig,
52
+ noTypeAssertionsConfig,
53
+
54
+ // Plugin rule configurations
55
+ pluginRules,
56
+ typescriptEslintRules,
57
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Rule configuration for no-type-assertions
3
+ *
4
+ * This rule disallows TypeScript type assertions using the "as" keyword,
5
+ * except for "as const" which is allowed for creating readonly literal types.
6
+ *
7
+ * Examples:
8
+ * - ❌ value as string
9
+ * - ❌ value as User
10
+ * - ❌ obj as { name: string }
11
+ * - ✅ { mode: 'prod' } as const
12
+ * - ✅ ['a', 'b'] as const
13
+ *
14
+ * @see https://eslint.org/docs/latest/rules/no-restricted-syntax
15
+ */
16
+
17
+ const rule = "error";
18
+
19
+ const selector =
20
+ 'TSAsExpression:not(:has(TSTypeReference[typeName.name="const"]))';
21
+
22
+ const message =
23
+ 'Type assertions with "as" are not allowed except for "as const".';
24
+
25
+ /**
26
+ * Export the complete rule configuration for no-restricted-syntax
27
+ * Can be used in ESLint config as part of no-restricted-syntax rules:
28
+ * "no-restricted-syntax": ["error", ...otherRules, noTypeAssertionsConfig]
29
+ */
30
+ const noTypeAssertionsConfig = {
31
+ selector,
32
+ message,
33
+ };
34
+
35
+ // Consolidated exports
36
+ export { rule, selector, message, noTypeAssertionsConfig };
37
+
38
+ export default noTypeAssertionsConfig;
@@ -0,0 +1,246 @@
1
+ import { RuleTester } from "eslint";
2
+ import { noTypeAssertionsConfig } from "./index.js";
3
+
4
+ /**
5
+ * Test suite for no-type-assertions rule
6
+ *
7
+ * This tests the no-restricted-syntax configuration that prevents
8
+ * TypeScript type assertions using "as" keyword except for "as const".
9
+ */
10
+
11
+ // Create a custom rule for testing our selector
12
+ const noTypeAssertionsRule = {
13
+ meta: {
14
+ type: "problem",
15
+ docs: {
16
+ description: "Disallow type assertions except 'as const'",
17
+ },
18
+ messages: {
19
+ noTypeAssertions: noTypeAssertionsConfig.message,
20
+ },
21
+ schema: [],
22
+ },
23
+ create(context) {
24
+ return {
25
+ [noTypeAssertionsConfig.selector](node) {
26
+ context.report({
27
+ node,
28
+ messageId: "noTypeAssertions",
29
+ });
30
+ },
31
+ };
32
+ },
33
+ };
34
+
35
+ const ruleTester = new RuleTester({
36
+ languageOptions: {
37
+ ecmaVersion: 2022,
38
+ sourceType: "module",
39
+ parser: (await import("@typescript-eslint/parser")).default,
40
+ parserOptions: {
41
+ ecmaFeatures: {
42
+ jsx: true,
43
+ },
44
+ },
45
+ },
46
+ });
47
+
48
+ ruleTester.run("no-type-assertions", noTypeAssertionsRule, {
49
+ valid: [
50
+ // Valid: "as const" usage
51
+ {
52
+ code: "const config = { mode: 'production' } as const;",
53
+ name: "object as const",
54
+ },
55
+ {
56
+ code: "const colors = ['red', 'green', 'blue'] as const;",
57
+ name: "array as const",
58
+ },
59
+ {
60
+ code: "const status = 'loading' as const;",
61
+ name: "string literal as const",
62
+ },
63
+ {
64
+ code: "const numbers = [1, 2, 3] as const;",
65
+ name: "number array as const",
66
+ },
67
+ {
68
+ code: "const tuple = ['name', 42, true] as const;",
69
+ name: "mixed tuple as const",
70
+ },
71
+ {
72
+ code: "const nested = { items: [{ id: 1 }] as const } as const;",
73
+ name: "nested as const",
74
+ },
75
+
76
+ // Valid: No type assertions at all
77
+ {
78
+ code: "const value: string = 'hello';",
79
+ name: "type annotation instead of assertion",
80
+ },
81
+ {
82
+ code: "function getValue(): string { return 'test'; }",
83
+ name: "function with return type",
84
+ },
85
+ {
86
+ code: "interface User { name: string; } const user: User = { name: 'John' };",
87
+ name: "interface with proper typing",
88
+ },
89
+ {
90
+ code: "const element = document.getElementById('test');",
91
+ name: "no type assertion on DOM access",
92
+ },
93
+ ],
94
+
95
+ invalid: [
96
+ // Invalid: Basic type assertions
97
+ {
98
+ code: "declare const value: unknown; const str = value as string;",
99
+ errors: [{ messageId: "noTypeAssertions" }],
100
+ name: "basic string assertion",
101
+ },
102
+ {
103
+ code: "declare const value: unknown; const num = value as number;",
104
+ errors: [{ messageId: "noTypeAssertions" }],
105
+ name: "basic number assertion",
106
+ },
107
+ {
108
+ code: "declare const value: unknown; const bool = value as boolean;",
109
+ errors: [{ messageId: "noTypeAssertions" }],
110
+ name: "basic boolean assertion",
111
+ },
112
+
113
+ // Invalid: Interface and type assertions
114
+ {
115
+ code: "interface User { name: string; } declare const value: unknown; const user = value as User;",
116
+ errors: [{ messageId: "noTypeAssertions" }],
117
+ name: "interface assertion",
118
+ },
119
+ {
120
+ code: "type Status = 'loading' | 'success'; declare const value: unknown; const status = value as Status;",
121
+ errors: [{ messageId: "noTypeAssertions" }],
122
+ name: "type alias assertion",
123
+ },
124
+
125
+ // Invalid: DOM element assertions
126
+ {
127
+ code: "const element = document.getElementById('test') as HTMLInputElement;",
128
+ errors: [{ messageId: "noTypeAssertions" }],
129
+ name: "DOM element assertion",
130
+ },
131
+ {
132
+ code: "const button = document.querySelector('.btn') as HTMLButtonElement;",
133
+ errors: [{ messageId: "noTypeAssertions" }],
134
+ name: "DOM querySelector assertion",
135
+ },
136
+
137
+ // Invalid: Object and array assertions
138
+ {
139
+ code: "declare const data: unknown; const obj = data as { name: string };",
140
+ errors: [{ messageId: "noTypeAssertions" }],
141
+ name: "object literal type assertion",
142
+ },
143
+ {
144
+ code: "declare const data: unknown; const arr = data as string[];",
145
+ errors: [{ messageId: "noTypeAssertions" }],
146
+ name: "array type assertion",
147
+ },
148
+ {
149
+ code: "declare const data: unknown; const tuple = data as [string, number];",
150
+ errors: [{ messageId: "noTypeAssertions" }],
151
+ name: "tuple type assertion",
152
+ },
153
+
154
+ // Invalid: Function parameter and return assertions
155
+ {
156
+ code: "function test(param: unknown) { return param as string; }",
157
+ errors: [{ messageId: "noTypeAssertions" }],
158
+ name: "return value assertion",
159
+ },
160
+ {
161
+ code: "const fn = (value: unknown) => value as number;",
162
+ errors: [{ messageId: "noTypeAssertions" }],
163
+ name: "arrow function assertion",
164
+ },
165
+
166
+ // Invalid: Complex expressions
167
+ {
168
+ code: "declare const api: any; const result = api.getData() as Promise<User>;",
169
+ errors: [{ messageId: "noTypeAssertions" }],
170
+ name: "method call assertion",
171
+ },
172
+ {
173
+ code: "declare const obj: any; const prop = obj.property as string;",
174
+ errors: [{ messageId: "noTypeAssertions" }],
175
+ name: "property access assertion",
176
+ },
177
+ {
178
+ code: "declare const arr: any[]; const first = arr[0] as string;",
179
+ errors: [{ messageId: "noTypeAssertions" }],
180
+ name: "array access assertion",
181
+ },
182
+
183
+ // Invalid: Generic type assertions
184
+ {
185
+ code: "declare const value: unknown; const generic = value as Array<string>;",
186
+ errors: [{ messageId: "noTypeAssertions" }],
187
+ name: "generic type assertion",
188
+ },
189
+ {
190
+ code: "declare const value: unknown; const promise = value as Promise<number>;",
191
+ errors: [{ messageId: "noTypeAssertions" }],
192
+ name: "Promise generic assertion",
193
+ },
194
+
195
+ // Invalid: Any type assertions
196
+ {
197
+ code: "declare const value: unknown; const anything = value as any;",
198
+ errors: [{ messageId: "noTypeAssertions" }],
199
+ name: "any type assertion",
200
+ },
201
+
202
+ // Invalid: Chained assertions
203
+ {
204
+ code: "declare const value: unknown; const result = (value as any).prop as string;",
205
+ errors: [
206
+ { messageId: "noTypeAssertions" },
207
+ { messageId: "noTypeAssertions" }
208
+ ],
209
+ name: "chained assertions",
210
+ },
211
+
212
+ // Invalid: Template literal expressions
213
+ {
214
+ code: "declare const id: unknown; const message = `User ID: ${id as string}`;",
215
+ errors: [{ messageId: "noTypeAssertions" }],
216
+ name: "assertion in template literal",
217
+ },
218
+
219
+ // Invalid: Conditional expressions
220
+ {
221
+ code: "declare const value: unknown; const result = value ? value as string : 'default';",
222
+ errors: [{ messageId: "noTypeAssertions" }],
223
+ name: "assertion in conditional",
224
+ },
225
+
226
+ // Invalid: Object property values
227
+ {
228
+ code: "declare const name: unknown; const user = { name: name as string, age: 30 };",
229
+ errors: [{ messageId: "noTypeAssertions" }],
230
+ name: "assertion in object property",
231
+ },
232
+
233
+ // Invalid: Array elements
234
+ {
235
+ code: "declare const item: unknown; const items = [item as string, 'other'];",
236
+ errors: [{ messageId: "noTypeAssertions" }],
237
+ name: "assertion in array element",
238
+ },
239
+ ],
240
+ });
241
+
242
+ console.log("✅ All no-type-assertions tests passed!");
243
+ console.log(` Selector: ${noTypeAssertionsConfig.selector}`);
244
+ console.log(` Message: ${noTypeAssertionsConfig.message}`);
245
+
246
+ export { noTypeAssertionsRule };
@@ -1,10 +1,4 @@
1
1
  export const typescriptEslintRules = {
2
2
  "@typescript-eslint/no-explicit-any": "error",
3
- "@typescript-eslint/consistent-type-assertions": [
4
- "error",
5
- {
6
- assertionStyle: "as",
7
- objectLiteralTypeAssertions: "allow-as-parameter",
8
- },
9
- ],
3
+ "@typescript-eslint/consistent-type-assertions": "off",
10
4
  };