@prover-coder-ai/eslint-plugin-suggest-members 0.0.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.
Files changed (80) hide show
  1. package/.jscpd.json +16 -0
  2. package/README.md +104 -0
  3. package/biome.json +37 -0
  4. package/docs/rules/no-loop-over-enums.md +29 -0
  5. package/docs/rules/suggest-exports.md +15 -0
  6. package/docs/rules/suggest-imports.md +15 -0
  7. package/docs/rules/suggest-members.md +15 -0
  8. package/docs/rules/suggest-missing-names.md +13 -0
  9. package/docs/rules/suggest-module-paths.md +15 -0
  10. package/eslint.config.mts +265 -0
  11. package/eslint.effect-ts-check.config.mjs +220 -0
  12. package/linter.config.json +32 -0
  13. package/package.json +79 -0
  14. package/scripts/checkFunctionalCore.ts +488 -0
  15. package/src/core/axioms.ts +23 -0
  16. package/src/core/effects/index.ts +39 -0
  17. package/src/core/formatting/messages.ts +315 -0
  18. package/src/core/index.ts +71 -0
  19. package/src/core/plugin-meta.ts +12 -0
  20. package/src/core/similarity/composite.ts +69 -0
  21. package/src/core/similarity/helpers.ts +34 -0
  22. package/src/core/similarity/index.ts +10 -0
  23. package/src/core/similarity/jaro-winkler.ts +25 -0
  24. package/src/core/similarity/jaro.ts +99 -0
  25. package/src/core/suggestion/engine.ts +35 -0
  26. package/src/core/types/domain.ts +28 -0
  27. package/src/core/types/eslint-nodes.ts +62 -0
  28. package/src/core/types/validation.ts +185 -0
  29. package/src/core/validation/candidates.ts +29 -0
  30. package/src/core/validation/module-path-utils.ts +33 -0
  31. package/src/core/validation/node-builtin-exports.ts +46 -0
  32. package/src/core/validators/index.ts +14 -0
  33. package/src/core/validators/node-predicates.ts +92 -0
  34. package/src/index.ts +56 -0
  35. package/src/rules/index.ts +25 -0
  36. package/src/rules/suggest-exports/index.ts +121 -0
  37. package/src/rules/suggest-imports/index.ts +25 -0
  38. package/src/rules/suggest-members/index.ts +154 -0
  39. package/src/rules/suggest-missing-names/index.ts +116 -0
  40. package/src/rules/suggest-module-paths/index.ts +101 -0
  41. package/src/shell/effects/errors.ts +80 -0
  42. package/src/shell/services/filesystem.ts +136 -0
  43. package/src/shell/services/typescript-compiler-effects.ts +85 -0
  44. package/src/shell/services/typescript-compiler-helpers.ts +89 -0
  45. package/src/shell/services/typescript-compiler-module-effects.ts +296 -0
  46. package/src/shell/services/typescript-compiler.ts +112 -0
  47. package/src/shell/services/typescript-effect-utils.ts +123 -0
  48. package/src/shell/shared/effect-utils.ts +18 -0
  49. package/src/shell/shared/import-validation-base.ts +181 -0
  50. package/src/shell/shared/import-validation-rule-factory.ts +116 -0
  51. package/src/shell/shared/validation-helpers.ts +94 -0
  52. package/src/shell/shared/validation-runner.ts +45 -0
  53. package/src/shell/validation/export-validation-effect.ts +54 -0
  54. package/src/shell/validation/import-validation-effect.ts +49 -0
  55. package/src/shell/validation/local-export-validation-effect.ts +10 -0
  56. package/src/shell/validation/member-validation-effect.ts +307 -0
  57. package/src/shell/validation/missing-name-validation-base.ts +153 -0
  58. package/src/shell/validation/missing-name-validation-effect.ts +10 -0
  59. package/src/shell/validation/missing-name-validators.ts +52 -0
  60. package/src/shell/validation/module-path-index.ts +144 -0
  61. package/src/shell/validation/module-validation-effect.ts +220 -0
  62. package/src/shell/validation/suggestion-signatures.ts +63 -0
  63. package/src/shell/validation/validation-base-effect.ts +165 -0
  64. package/tests/core/message-formatting.test.ts +121 -0
  65. package/tests/core/suggestion-engine.test.ts +34 -0
  66. package/tests/fixtures/consumer.ts +1 -0
  67. package/tests/fixtures/module-paths/alpha.ts +1 -0
  68. package/tests/fixtures/module-paths/beta.ts +1 -0
  69. package/tests/fixtures/modules/exports.ts +9 -0
  70. package/tests/plugin-signature.test.ts +69 -0
  71. package/tests/rules/suggest-imports-exports.test.ts +91 -0
  72. package/tests/rules/suggest-members.test.ts +98 -0
  73. package/tests/rules/suggest-missing-names.test.ts +35 -0
  74. package/tests/rules/suggest-module-paths.test.ts +54 -0
  75. package/tests/utils/rule-tester.ts +41 -0
  76. package/tsconfig.build.json +13 -0
  77. package/tsconfig.json +22 -0
  78. package/types/eslint-plugins.d.ts +15 -0
  79. package/vite.config.ts +33 -0
  80. package/vitest.config.ts +87 -0
package/.jscpd.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "threshold": 0,
3
+ "minTokens": 30,
4
+ "minLines": 5,
5
+ "ignore": [
6
+ "**/node_modules/**",
7
+ "**/build/**",
8
+ "**/dist/**",
9
+ "**/*.min.js",
10
+ "**/reports/**"
11
+ ],
12
+ "skipComments": true,
13
+ "ignorePattern": [
14
+ "private readonly \\w+: \\w+;\\s*private readonly \\w+: \\w+;\\s*private \\w+: \\w+ \\| null = null;\\s*private \\w+: \\w+ \\| null = null;"
15
+ ]
16
+ }
package/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # `@prover-coder-ai/eslint-plugin-suggest-members`
2
+
3
+ Production‑ready ESLint plugin that suggests corrections for typos in TypeScript/JavaScript code. Built with Functional Core / Imperative Shell and Effect‑TS.
4
+
5
+ ## ✨ Key Features
6
+
7
+ - Smart suggestions for typos (similarity scoring)
8
+ - TypeScript‑aware diagnostics with signatures
9
+ - Filesystem‑based module path suggestions
10
+ - Fully typed, Effect‑TS based architecture
11
+
12
+ ## ⚙️ Configuration (ESLint v9+ Flat Config)
13
+
14
+ ```js
15
+ // eslint.config.js
16
+ import suggestMembers from "@prover-coder-ai/eslint-plugin-suggest-members"
17
+
18
+ export default [
19
+ {
20
+ files: ["**/*.{ts,tsx,js,jsx}"],
21
+ plugins: {
22
+ "suggest-members": suggestMembers
23
+ },
24
+ rules: {
25
+ "suggest-members/suggest-exports": "error",
26
+ "suggest-members/suggest-imports": "error",
27
+ "suggest-members/suggest-members": "error",
28
+ "suggest-members/suggest-missing-names": "error",
29
+ "suggest-members/suggest-module-paths": "error"
30
+ }
31
+ }
32
+ ]
33
+ ```
34
+
35
+ ## ✅ Example Diagnostics
36
+
37
+ ### Export Suggestions (`suggest-exports`)
38
+ ```ts
39
+ // ❌ Typo in React hook import
40
+ export { useStae, useEffect } from "react"
41
+ // ✅ ESLint Error: Export 'useStae' does not exist on type 'typeof import("react")'. Did you mean:
42
+ // - useState
43
+ // - useRef
44
+ // - useMemo
45
+ // - useCallback
46
+ ```
47
+
48
+ ### Member Suggestions (`suggest-members`)
49
+ ```ts
50
+ // ❌ Typo in localStorage method
51
+ localStorage.get1Item("token")
52
+ // ✅ ESLint Error: Property 'get1Item' does not exist on type 'Storage'. Did you mean:
53
+ // - getItem(key: string): string | null
54
+ // - setItem(key: string, value: string)
55
+ // - removeItem(key: string)
56
+ // - clear(): void
57
+ ```
58
+
59
+ ### Module Path Suggestions (`suggest-module-paths`)
60
+ ```ts
61
+ // ❌ Typo in file path
62
+ import styles from "./HamsterKo1mbatPage.css"
63
+ // ✅ ESLint Error: Cannot find module "./HamsterKo1mbatPage.css". Did you mean:
64
+ // - ./HamsterKombatPage.css
65
+ // - ./HamsterKombatPage.tsx
66
+ // - ./HamsterKombatPage
67
+ // - ../ThemeParamsPage.css
68
+ ```
69
+
70
+ ### Import Suggestions (`suggest-imports`)
71
+ ```ts
72
+ // ❌ Typo in named import
73
+ import { saveRe1f } from "./hooks"
74
+ // ✅ ESLint Error: Export 'saveRe1f' does not exist on type 'typeof import("./hooks")'. Did you mean:
75
+ // - saveRef
76
+ // - saveState
77
+ // - useRef
78
+ // - useState
79
+ ```
80
+
81
+ ### Missing Name Suggestions (`suggest-missing-names`)
82
+ ```ts
83
+ // ❌ Typo in local identifier
84
+ const formatGree1ting = () => "ok"
85
+ formatGreeting()
86
+ // ✅ ESLint Error: Cannot find name 'formatGreeting'. Did you mean:
87
+ // - formatGree1ting(): string
88
+ ```
89
+
90
+ ## 📚 Rules
91
+
92
+ | Name | Description | TS Required |
93
+ | --- | --- | --- |
94
+ | [suggest-exports](docs/rules/suggest-exports.md) | Suggests corrections for missing exports | ✅ |
95
+ | [suggest-imports](docs/rules/suggest-imports.md) | Suggests corrections for missing imports | ✅ |
96
+ | [suggest-members](docs/rules/suggest-members.md) | Suggests corrections for missing members | ✅ |
97
+ | [suggest-missing-names](docs/rules/suggest-missing-names.md) | Suggests corrections for unresolved identifiers | ✅ |
98
+ | [suggest-module-paths](docs/rules/suggest-module-paths.md) | Suggests corrections for missing module paths | ❌ |
99
+
100
+ ## Development
101
+
102
+ ```sh
103
+ pnpm --filter @prover-coder-ai/eslint-plugin-suggest-members test
104
+ ```
package/biome.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "vcs": {
3
+ "enabled": false,
4
+ "clientKind": "git",
5
+ "useIgnoreFile": false
6
+ },
7
+ "files": {
8
+ "ignoreUnknown": false
9
+ },
10
+ "formatter": {
11
+ "enabled": false,
12
+ "indentStyle": "tab"
13
+ },
14
+ "assist": {
15
+ "actions": {
16
+ "source": {
17
+ "organizeImports": "off"
18
+ }
19
+ }
20
+ },
21
+ "linter": {
22
+ "enabled": false,
23
+ "rules": {
24
+ "recommended": false,
25
+ "suspicious": {
26
+ "noExplicitAny": "off"
27
+ }
28
+ }
29
+ },
30
+ "javascript": {
31
+ "formatter": {
32
+ "enabled": false,
33
+ "quoteStyle": "double",
34
+ "semicolons": "asNeeded"
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,29 @@
1
+ # Avoid looping over enums (`example-typed-linting/no-loop-over-enums`)
2
+
3
+ 💭 This rule requires [type information](https://typescript-eslint.io/linting/typed-linting).
4
+
5
+ <!-- end auto-generated rule header -->
6
+
7
+ Example rule that demonstrates banning `for-in` looping over `enum`s.
8
+
9
+ ## Valid
10
+
11
+ ```ts
12
+ const values = {};
13
+ for (const a in values) {
14
+ }
15
+ ```
16
+
17
+ ```ts
18
+ const values = [];
19
+ for (const a of values) {
20
+ }
21
+ ```
22
+
23
+ ## Invalid
24
+
25
+ ```ts
26
+ enum Values {}
27
+ for (const a of values) {
28
+ }
29
+ ```
@@ -0,0 +1,15 @@
1
+ # Suggest export names (`suggest-exports`)
2
+
3
+ Reports when a re-export targets a missing export and suggests the closest matches.
4
+
5
+ Example:
6
+
7
+ ```ts
8
+ // ❌ Typo in React hook import
9
+ export { useStae, useEffect } from "react"
10
+ // ✅ ESLint Error: Export 'useStae' does not exist on type 'typeof import("react")'. Did you mean:
11
+ // - useState
12
+ // - useRef
13
+ // - useMemo
14
+ // - useCallback
15
+ ```
@@ -0,0 +1,15 @@
1
+ # Suggest import names (`suggest-imports`)
2
+
3
+ Reports when a named import does not exist and suggests similar exports.
4
+
5
+ Example:
6
+
7
+ ```ts
8
+ // ❌ Typo in named import
9
+ import { saveRe1f } from "./hooks"
10
+ // ✅ ESLint Error: Export 'saveRe1f' does not exist on type 'typeof import("./hooks")'. Did you mean:
11
+ // - saveRef
12
+ // - saveState
13
+ // - useRef
14
+ // - useState
15
+ ```
@@ -0,0 +1,15 @@
1
+ # Suggest member names (`suggest-members`)
2
+
3
+ Reports when accessing a missing member and suggests similar properties/methods with signatures.
4
+
5
+ Example:
6
+
7
+ ```ts
8
+ // ❌ Typo in localStorage method
9
+ localStorage.get1Item("token")
10
+ // ✅ ESLint Error: Property 'get1Item' does not exist on type 'Storage'. Did you mean:
11
+ // - getItem(key: string): string | null
12
+ // - setItem(key: string, value: string)
13
+ // - removeItem(key: string)
14
+ // - clear(): void
15
+ ```
@@ -0,0 +1,13 @@
1
+ # Suggest missing names (`suggest-missing-names`)
2
+
3
+ Reports unresolved identifiers and suggests similar in-scope names with signatures.
4
+
5
+ Example:
6
+
7
+ ```ts
8
+ // ❌ Typo in local identifier
9
+ const formatGree1ting = () => "ok"
10
+ formatGreeting()
11
+ // ✅ ESLint Error: Cannot find name 'formatGreeting'. Did you mean:
12
+ // - formatGree1ting(): string
13
+ ```
@@ -0,0 +1,15 @@
1
+ # Suggest module paths (`suggest-module-paths`)
2
+
3
+ Reports when a module path cannot be resolved and suggests similar paths.
4
+
5
+ Example:
6
+
7
+ ```ts
8
+ // ❌ Typo in file path
9
+ import styles from "./HamsterKo1mbatPage.css"
10
+ // ✅ ESLint Error: Cannot find module "./HamsterKo1mbatPage.css". Did you mean:
11
+ // - ./HamsterKombatPage.css
12
+ // - ./HamsterKombatPage.tsx
13
+ // - ./HamsterKombatPage
14
+ // - ../ThemeParamsPage.css
15
+ ```
@@ -0,0 +1,265 @@
1
+ // eslint.config.mjs
2
+ // @ts-check
3
+ import eslint from '@eslint/js';
4
+ import eslintPlugin from "eslint-plugin-eslint-plugin";
5
+ import tseslint from 'typescript-eslint';
6
+ import vitest from "eslint-plugin-vitest";
7
+ import suggestMembers from "@ton-ai-core/eslint-plugin-suggest-members";
8
+ import sonarjs from "eslint-plugin-sonarjs";
9
+ import unicorn from "eslint-plugin-unicorn";
10
+ import * as effectEslint from "@effect/eslint-plugin";
11
+ import { fixupPluginRules } from "@eslint/compat";
12
+ import codegen from "eslint-plugin-codegen";
13
+ import importPlugin from "eslint-plugin-import";
14
+ import simpleImportSort from "eslint-plugin-simple-import-sort";
15
+ import sortDestructureKeys from "eslint-plugin-sort-destructure-keys";
16
+ import globals from "globals";
17
+ import eslintCommentsConfigs from "@eslint-community/eslint-plugin-eslint-comments/configs";
18
+
19
+ const codegenPlugin = fixupPluginRules(
20
+ codegen as unknown as Parameters<typeof fixupPluginRules>[0],
21
+ );
22
+ const suggestMembersRecommended = suggestMembers.configs["recommended"];
23
+
24
+ export default tseslint.config(
25
+ { ignores: ["lib"] },
26
+ eslint.configs.recommended,
27
+ tseslint.configs.recommendedTypeChecked,
28
+ eslintPlugin.configs.recommended,
29
+ tseslint.configs.strictTypeChecked,
30
+ effectEslint.configs.dprint,
31
+ ...(suggestMembersRecommended ? [suggestMembersRecommended] : []),
32
+ eslintCommentsConfigs.recommended,
33
+ {
34
+ name: "analyzers",
35
+ languageOptions: {
36
+ parser: tseslint.parser,
37
+ globals: { ...globals.node, ...globals.browser },
38
+ parserOptions: {
39
+ projectService: {
40
+ allowDefaultProject: ["*.config.*"],
41
+ defaultProject: "tsconfig.json",
42
+ },
43
+ tsconfigRootDir: import.meta.dirname,
44
+ },
45
+ },
46
+ plugins: {
47
+ sonarjs,
48
+ unicorn,
49
+ import: fixupPluginRules(importPlugin),
50
+ "sort-destructure-keys": sortDestructureKeys,
51
+ "simple-import-sort": simpleImportSort,
52
+ codegen: codegenPlugin,
53
+ },
54
+ files: ["**/*.ts", '**/*.{test,spec}.{ts,tsx}', '**/tests/**', '**/__tests__/**'],
55
+ settings: {
56
+ "import/parsers": {
57
+ "@typescript-eslint/parser": [".ts", ".tsx"],
58
+ },
59
+ "import/resolver": {
60
+ typescript: {
61
+ alwaysTryTypes: true,
62
+ },
63
+ },
64
+ },
65
+ rules: {
66
+ ...sonarjs.configs.recommended.rules,
67
+ ...unicorn.configs.recommended.rules,
68
+ "no-restricted-imports": ["error", {
69
+ paths: [
70
+ {
71
+ name: "ts-pattern",
72
+ message: "Use Effect.Match instead of ts-pattern.",
73
+ },
74
+ {
75
+ name: "zod",
76
+ message: "Use @effect/schema for schemas and validation.",
77
+ },
78
+ ],
79
+ }],
80
+ "codegen/codegen": "error",
81
+ "import/first": "error",
82
+ "import/newline-after-import": "error",
83
+ "import/no-duplicates": "error",
84
+ "import/no-unresolved": "off",
85
+ "import/order": "off",
86
+ "simple-import-sort/imports": "off",
87
+ "sort-destructure-keys/sort-destructure-keys": "error",
88
+ "no-fallthrough": "off",
89
+ "no-irregular-whitespace": "off",
90
+ "object-shorthand": "error",
91
+ "prefer-destructuring": "off",
92
+ "sort-imports": "off",
93
+ "no-unused-vars": "off",
94
+ "prefer-rest-params": "off",
95
+ "prefer-spread": "off",
96
+ "unicorn/prefer-top-level-await": "off",
97
+ "unicorn/prevent-abbreviations": "off",
98
+ "unicorn/no-null": "off",
99
+ complexity: ["error", 8],
100
+ "max-lines-per-function": [
101
+ "error",
102
+ { max: 50, skipBlankLines: true, skipComments: true },
103
+ ],
104
+ "max-params": ["error", 5],
105
+ "max-depth": ["error", 4],
106
+ "max-lines": [
107
+ "error",
108
+ { max: 300, skipBlankLines: true, skipComments: true },
109
+ ],
110
+
111
+ "@typescript-eslint/restrict-template-expressions": ["error", {
112
+ allowNumber: true,
113
+ allowBoolean: true,
114
+ allowNullish: false,
115
+ allowAny: false,
116
+ allowRegExp: false
117
+ }],
118
+ "@eslint-community/eslint-comments/no-use": "error",
119
+ "@eslint-community/eslint-comments/no-unlimited-disable": "error",
120
+ "@eslint-community/eslint-comments/disable-enable-pair": "error",
121
+ "@eslint-community/eslint-comments/no-unused-disable": "error",
122
+ "no-restricted-syntax": [
123
+ "error",
124
+ {
125
+ selector: "TSUnknownKeyword",
126
+ message: "Запрещено 'unknown'.",
127
+ },
128
+ {
129
+ selector: "TryStatement",
130
+ message: "Используй Effect.try / catchAll вместо try/catch в core/app/domain.",
131
+ },
132
+ {
133
+ selector: "SwitchStatement",
134
+ message: [
135
+ "Switch statements are forbidden in functional programming paradigm.",
136
+ "How to fix: Use Effect.Match instead.",
137
+ "Example:",
138
+ " import { Match } from 'effect';",
139
+ " type Item = { type: 'this' } | { type: 'that' };",
140
+ " const result = Match.value(item).pipe(",
141
+ " Match.when({ type: 'this' }, (it) => processThis(it)),",
142
+ " Match.when({ type: 'that' }, (it) => processThat(it)),",
143
+ " Match.exhaustive,",
144
+ " );",
145
+ ].join("\n"),
146
+ },
147
+ {
148
+ selector: 'CallExpression[callee.name="require"]',
149
+ message: "Avoid using require(). Use ES6 imports instead.",
150
+ },
151
+ {
152
+ selector: "ThrowStatement > Literal:not([value=/^\\w+Error:/])",
153
+ message:
154
+ 'Do not throw string literals or non-Error objects. Throw new Error("...") instead.',
155
+ },
156
+ {
157
+ selector:
158
+ "FunctionDeclaration[async=true], FunctionExpression[async=true], ArrowFunctionExpression[async=true]",
159
+ message:
160
+ "Запрещён async/await — используй Effect.gen / Effect.tryPromise.",
161
+ },
162
+ {
163
+ selector: "NewExpression[callee.name='Promise']",
164
+ message:
165
+ "Запрещён new Promise — используй Effect.async / Effect.tryPromise.",
166
+ },
167
+ {
168
+ selector: "CallExpression[callee.object.name='Promise']",
169
+ message:
170
+ "Запрещены Promise.* — используй комбинаторы Effect (all, forEach, etc.).",
171
+ },
172
+ {
173
+ selector: "CallExpression[callee.property.name='push'] > SpreadElement.arguments",
174
+ message: "Do not use spread arguments in Array.push",
175
+ },
176
+ ],
177
+ "no-throw-literal": "error",
178
+ "@typescript-eslint/no-restricted-types": [
179
+ "error",
180
+ {
181
+ types: {
182
+ unknown: {
183
+ message:
184
+ "Не используем 'unknown'. Уточни тип или наведи порядок в источнике данных.",
185
+ },
186
+ Promise: {
187
+ message: "Запрещён Promise — используй Effect.Effect<A, E, R>.",
188
+ suggest: ["Effect.Effect"],
189
+ },
190
+ "Promise<*>": {
191
+ message:
192
+ "Запрещён Promise<T> — используй Effect.Effect<T, E, R>.",
193
+ suggest: ["Effect.Effect<T, E, R>"],
194
+ },
195
+ },
196
+ },
197
+ ],
198
+ "@typescript-eslint/use-unknown-in-catch-callback-variable": "off",
199
+ // "no-throw-literal": "off",
200
+ "@typescript-eslint/only-throw-error": [
201
+ "error",
202
+ { allowThrowingUnknown: false, allowThrowingAny: false },
203
+ ],
204
+ "@typescript-eslint/array-type": ["warn", {
205
+ default: "generic",
206
+ readonly: "generic"
207
+ }],
208
+ "@typescript-eslint/member-delimiter-style": 0,
209
+ "@typescript-eslint/no-non-null-assertion": "off",
210
+ "@typescript-eslint/ban-types": "off",
211
+ "@typescript-eslint/no-explicit-any": "off",
212
+ "@typescript-eslint/no-empty-interface": "off",
213
+ "@typescript-eslint/consistent-type-imports": "warn",
214
+ "@typescript-eslint/no-unused-vars": ["error", {
215
+ argsIgnorePattern: "^_",
216
+ varsIgnorePattern: "^_"
217
+ }],
218
+ "@typescript-eslint/ban-ts-comment": "off",
219
+ "@typescript-eslint/camelcase": "off",
220
+ "@typescript-eslint/explicit-function-return-type": "off",
221
+ "@typescript-eslint/explicit-module-boundary-types": "off",
222
+ "@typescript-eslint/interface-name-prefix": "off",
223
+ "@typescript-eslint/no-array-constructor": "off",
224
+ "@typescript-eslint/no-use-before-define": "off",
225
+ "@typescript-eslint/no-namespace": "off",
226
+ "@effect/dprint": ["error", {
227
+ config: {
228
+ indentWidth: 2,
229
+ lineWidth: 120,
230
+ semiColons: "asi",
231
+ quoteStyle: "alwaysDouble",
232
+ trailingCommas: "never",
233
+ operatorPosition: "maintain",
234
+ "arrowFunction.useParentheses": "force"
235
+ }
236
+ }]
237
+ }
238
+ },
239
+ {
240
+ files: ['**/*.{test,spec}.{ts,tsx}', 'tests/**', '**/__tests__/**'],
241
+ ...vitest.configs.all,
242
+ languageOptions: {
243
+ globals: {
244
+ ...vitest.environments.env.globals,
245
+ },
246
+ },
247
+ rules: {
248
+ // Allow eslint-disable/enable comments in test files for fine-grained control
249
+ '@eslint-community/eslint-comments/no-use': 'off',
250
+ // Disable line count limit for E2E tests that contain multiple test cases
251
+ 'max-lines-per-function': 'off',
252
+ // `it.effect` is not recognized by sonar rule; disable to avoid false positives
253
+ 'sonarjs/no-empty-test-file': 'off',
254
+ },
255
+ },
256
+
257
+ // 3) Для JS-файлов отключим типо-зависимые проверки
258
+ {
259
+ files: ['**/*.{js,cjs,mjs}'],
260
+ extends: [tseslint.configs.disableTypeChecked],
261
+ },
262
+
263
+ // 4) Глобальные игноры
264
+ { ignores: ['dist/**', 'build/**', 'coverage/**', '**/dist/**'] },
265
+ );