eslint-plugin-functype 1.4.0 → 2.0.1
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/dist/cli/list-rules.d.ts +1 -1
- package/dist/cli/list-rules.js +15 -239
- package/dist/cli/list-rules.js.map +1 -1
- package/dist/configs/recommended.d.ts +15 -0
- package/dist/configs/recommended.js +2 -0
- package/dist/configs/recommended.js.map +1 -0
- package/dist/configs/strict.d.ts +15 -0
- package/dist/configs/strict.js +2 -0
- package/dist/configs/strict.js.map +1 -0
- package/dist/dependency-validator-BBxa9-7D.js +4 -0
- package/dist/dependency-validator-BBxa9-7D.js.map +1 -0
- package/dist/index.d.ts +20 -17
- package/dist/index.js +1 -1364
- package/dist/index.js.map +1 -1
- package/dist/rules/index.d.ts +24 -32
- package/dist/rules/index.js +1 -1357
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/no-get-unsafe.d.ts +7 -0
- package/dist/rules/no-get-unsafe.js +2 -0
- package/dist/rules/no-get-unsafe.js.map +1 -0
- package/dist/rules/no-imperative-loops.d.ts +7 -0
- package/dist/rules/no-imperative-loops.js +2 -0
- package/dist/rules/no-imperative-loops.js.map +1 -0
- package/dist/rules/prefer-do-notation.d.ts +7 -0
- package/dist/rules/prefer-do-notation.js +5 -0
- package/dist/rules/prefer-do-notation.js.map +1 -0
- package/dist/rules/prefer-either.d.ts +7 -0
- package/dist/rules/prefer-either.js +2 -0
- package/dist/rules/prefer-either.js.map +1 -0
- package/dist/rules/prefer-flatmap.d.ts +7 -0
- package/dist/rules/prefer-flatmap.js +2 -0
- package/dist/rules/prefer-flatmap.js.map +1 -0
- package/dist/rules/prefer-fold.d.ts +7 -0
- package/dist/rules/prefer-fold.js +2 -0
- package/dist/rules/prefer-fold.js.map +1 -0
- package/dist/rules/prefer-list.d.ts +7 -0
- package/dist/rules/prefer-list.js +2 -0
- package/dist/rules/prefer-list.js.map +1 -0
- package/dist/rules/prefer-map.d.ts +7 -0
- package/dist/rules/prefer-map.js +2 -0
- package/dist/rules/prefer-map.js.map +1 -0
- package/dist/rules/prefer-option.d.ts +7 -0
- package/dist/rules/prefer-option.js +2 -0
- package/dist/rules/prefer-option.js.map +1 -0
- package/dist/types/ast.d.ts +12 -0
- package/dist/types/ast.js +1 -0
- package/dist/utils/dependency-validator.d.ts +13 -11
- package/dist/utils/dependency-validator.js +1 -109
- package/dist/utils/functype-detection.d.ts +69 -0
- package/dist/utils/functype-detection.js +2 -0
- package/dist/utils/functype-detection.js.map +1 -0
- package/package.json +48 -52
- package/LICENSE +0 -21
- package/README.md +0 -325
- package/dist/utils/dependency-validator.js.map +0 -1
package/README.md
DELETED
|
@@ -1,325 +0,0 @@
|
|
|
1
|
-
# eslint-plugin-functype
|
|
2
|
-
|
|
3
|
-
Custom ESLint rules for functional TypeScript programming with [functype](https://github.com/jordanburke/functype) library patterns. Enforces immutability, type safety, and functional programming best practices for ESLint 9+.
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/eslint-plugin-functype)
|
|
6
|
-
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
|
|
8
|
-
## Features
|
|
9
|
-
|
|
10
|
-
- 🔧 **9 Custom ESLint Rules** - Purpose-built for functional TypeScript patterns
|
|
11
|
-
- 🎭 **Do Notation Support** - New rule suggests functype's Do notation for complex monadic chains
|
|
12
|
-
- 🏗️ **Functype Library Integration** - Smart detection when functype is already being used properly
|
|
13
|
-
- 🛠️ **Auto-Fixable** - Most violations can be automatically fixed with `--fix`
|
|
14
|
-
- ⚡ **ESLint 9+ Flat Config** - Modern ESLint configuration format
|
|
15
|
-
- 🎯 **TypeScript Native** - Built specifically for TypeScript AST patterns
|
|
16
|
-
- 🎨 **Visual Test Output** - Beautiful before/after transformations with colorized diffs
|
|
17
|
-
- 📊 **100+ Tests** - Comprehensive test coverage including real functype integration
|
|
18
|
-
|
|
19
|
-
## Rules
|
|
20
|
-
|
|
21
|
-
| Rule | Description | Auto-Fix |
|
|
22
|
-
| --------------------- | ----------------------------------------------------------------- | -------- |
|
|
23
|
-
| `prefer-option` | Prefer `Option<T>` over nullable types (`T \| null \| undefined`) | ✅ |
|
|
24
|
-
| `prefer-either` | Prefer `Either<E, T>` over try/catch and throw statements | ✅ |
|
|
25
|
-
| `prefer-list` | Prefer `List<T>` over native arrays for immutable collections | ✅ |
|
|
26
|
-
| `prefer-fold` | Prefer `.fold()` over complex if/else chains | ✅ |
|
|
27
|
-
| `prefer-map` | Prefer `.map()` over imperative transformations | ✅ |
|
|
28
|
-
| `prefer-flatmap` | Prefer `.flatMap()` over `.map().flat()` patterns | ✅ |
|
|
29
|
-
| `no-get-unsafe` | Disallow unsafe `.get()` calls on Option/Either types | ❌ |
|
|
30
|
-
| `no-imperative-loops` | Prefer functional iteration over imperative loops | ✅ |
|
|
31
|
-
| `prefer-do-notation` | Prefer Do notation for complex monadic compositions | ✅ |
|
|
32
|
-
|
|
33
|
-
## Installation
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
npm install --save-dev eslint-plugin-functype
|
|
37
|
-
# or
|
|
38
|
-
pnpm add -D eslint-plugin-functype
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
**Optional:** Install functype library for enhanced integration:
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
npm install functype
|
|
45
|
-
# or
|
|
46
|
-
pnpm add functype
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Usage
|
|
50
|
-
|
|
51
|
-
### ESLint 9+ Flat Config (Recommended)
|
|
52
|
-
|
|
53
|
-
```javascript
|
|
54
|
-
// eslint.config.mjs
|
|
55
|
-
import functypePlugin from "eslint-plugin-functype"
|
|
56
|
-
import tsParser from "@typescript-eslint/parser"
|
|
57
|
-
|
|
58
|
-
export default [
|
|
59
|
-
{
|
|
60
|
-
files: ["**/*.ts", "**/*.tsx"],
|
|
61
|
-
plugins: {
|
|
62
|
-
functype: functypePlugin,
|
|
63
|
-
},
|
|
64
|
-
languageOptions: {
|
|
65
|
-
parser: tsParser,
|
|
66
|
-
parserOptions: {
|
|
67
|
-
ecmaVersion: 2022,
|
|
68
|
-
sourceType: "module",
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
rules: {
|
|
72
|
-
// All rules as errors
|
|
73
|
-
"functype/prefer-option": "error",
|
|
74
|
-
"functype/prefer-either": "error",
|
|
75
|
-
"functype/prefer-list": "error",
|
|
76
|
-
"functype/prefer-fold": "error",
|
|
77
|
-
"functype/prefer-map": "error",
|
|
78
|
-
"functype/prefer-flatmap": "error",
|
|
79
|
-
"functype/no-get-unsafe": "error",
|
|
80
|
-
"functype/no-imperative-loops": "error",
|
|
81
|
-
"functype/prefer-do-notation": "error",
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
]
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
### Individual Rule Configuration
|
|
88
|
-
|
|
89
|
-
```javascript
|
|
90
|
-
// eslint.config.mjs - Selective rules
|
|
91
|
-
export default [
|
|
92
|
-
{
|
|
93
|
-
files: ["**/*.ts"],
|
|
94
|
-
plugins: { functype: functypePlugin },
|
|
95
|
-
rules: {
|
|
96
|
-
// Start with just type safety rules
|
|
97
|
-
"functype/prefer-option": "warn",
|
|
98
|
-
"functype/no-get-unsafe": "error",
|
|
99
|
-
|
|
100
|
-
// Add more as your codebase evolves
|
|
101
|
-
"functype/prefer-list": "off", // Disable for gradual adoption
|
|
102
|
-
"functype/prefer-do-notation": "warn", // New: suggest Do notation
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
]
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Examples
|
|
109
|
-
|
|
110
|
-
### ❌ Before (violations flagged)
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
// prefer-option: nullable types
|
|
114
|
-
const user: User | null = findUser(id)
|
|
115
|
-
function getAge(): number | undefined {
|
|
116
|
-
/* ... */
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// prefer-either: try/catch blocks
|
|
120
|
-
try {
|
|
121
|
-
const result = riskyOperation()
|
|
122
|
-
return result
|
|
123
|
-
} catch (error) {
|
|
124
|
-
console.error(error)
|
|
125
|
-
return null
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// prefer-list: native arrays
|
|
129
|
-
const items: number[] = [1, 2, 3]
|
|
130
|
-
const readonlyItems: ReadonlyArray<string> = ["a", "b"]
|
|
131
|
-
|
|
132
|
-
// no-imperative-loops: for/while loops
|
|
133
|
-
for (let i = 0; i < items.length; i++) {
|
|
134
|
-
console.log(items[i])
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// prefer-fold: complex if/else chains
|
|
138
|
-
if (condition1) {
|
|
139
|
-
return value1
|
|
140
|
-
} else if (condition2) {
|
|
141
|
-
return value2
|
|
142
|
-
} else {
|
|
143
|
-
return defaultValue
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// prefer-do-notation: nested null checks
|
|
147
|
-
const city = (user && user.address && user.address.city) || "Unknown"
|
|
148
|
-
|
|
149
|
-
// prefer-do-notation: chained flatMap operations
|
|
150
|
-
const result = option1
|
|
151
|
-
.flatMap((x) => getOption2(x))
|
|
152
|
-
.flatMap((y) => getOption3(y))
|
|
153
|
-
.flatMap((z) => getOption4(z))
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
### ✅ After (auto-fixed or manually corrected)
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
import { Option, Either, List, Do, $ } from "functype"
|
|
160
|
-
|
|
161
|
-
// prefer-option: use Option<T>
|
|
162
|
-
const user: Option<User> = Option.fromNullable(findUser(id))
|
|
163
|
-
function getAge(): Option<number> {
|
|
164
|
-
/* ... */
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// prefer-either: use Either<E, T>
|
|
168
|
-
function safeOperation(): Either<Error, Result> {
|
|
169
|
-
try {
|
|
170
|
-
const result = riskyOperation()
|
|
171
|
-
return Either.right(result)
|
|
172
|
-
} catch (error) {
|
|
173
|
-
return Either.left(error as Error)
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// prefer-list: use List<T>
|
|
178
|
-
const items: List<number> = List.from([1, 2, 3])
|
|
179
|
-
const readonlyItems: List<string> = List.from(["a", "b"])
|
|
180
|
-
|
|
181
|
-
// no-imperative-loops: use functional methods
|
|
182
|
-
items.forEach((item) => console.log(item))
|
|
183
|
-
|
|
184
|
-
// prefer-fold: use fold for conditional logic
|
|
185
|
-
const result = Option.fromBoolean(condition1)
|
|
186
|
-
.map(() => value1)
|
|
187
|
-
.orElse(() => Option.fromBoolean(condition2).map(() => value2))
|
|
188
|
-
.getOrElse(defaultValue)
|
|
189
|
-
|
|
190
|
-
// prefer-do-notation: use Do notation for nested checks
|
|
191
|
-
const city = Do(function* () {
|
|
192
|
-
const u = yield* $(Option(user))
|
|
193
|
-
const addr = yield* $(Option(u.address))
|
|
194
|
-
return yield* $(Option(addr.city))
|
|
195
|
-
}).getOrElse("Unknown")
|
|
196
|
-
|
|
197
|
-
// prefer-do-notation: use Do for complex chains
|
|
198
|
-
const result = Do(function* () {
|
|
199
|
-
const x = yield* $(option1)
|
|
200
|
-
const y = yield* $(getOption2(x))
|
|
201
|
-
const z = yield* $(getOption3(y))
|
|
202
|
-
return yield* $(getOption4(z))
|
|
203
|
-
})
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
## Functype Integration
|
|
207
|
-
|
|
208
|
-
The plugin is **functype-aware** and won't flag code that's already using functype properly:
|
|
209
|
-
|
|
210
|
-
```typescript
|
|
211
|
-
import { Option, List } from "functype"
|
|
212
|
-
|
|
213
|
-
// ✅ These won't be flagged - already using functype correctly
|
|
214
|
-
const user = Option.some({ name: "Alice" })
|
|
215
|
-
const items = List.from([1, 2, 3])
|
|
216
|
-
const result = user.map((u) => u.name).getOrElse("Unknown")
|
|
217
|
-
|
|
218
|
-
// ❌ These will still be flagged - bad patterns even with functype available
|
|
219
|
-
const badUser: User | null = null // prefer-option
|
|
220
|
-
const badItems = [1, 2, 3] // prefer-list
|
|
221
|
-
```
|
|
222
|
-
|
|
223
|
-
## CLI Tools
|
|
224
|
-
|
|
225
|
-
### List All Rules
|
|
226
|
-
|
|
227
|
-
```bash
|
|
228
|
-
# After installation
|
|
229
|
-
npx functype-list-rules
|
|
230
|
-
|
|
231
|
-
# During development
|
|
232
|
-
pnpm run list-rules
|
|
233
|
-
|
|
234
|
-
# Verbose output with configurations
|
|
235
|
-
pnpm run list-rules:verbose
|
|
236
|
-
|
|
237
|
-
# Usage examples
|
|
238
|
-
pnpm run list-rules:usage
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### Development Commands
|
|
242
|
-
|
|
243
|
-
```bash
|
|
244
|
-
# Install dependencies
|
|
245
|
-
pnpm install
|
|
246
|
-
|
|
247
|
-
# Build plugin
|
|
248
|
-
pnpm run build
|
|
249
|
-
|
|
250
|
-
# Run tests (100+ tests)
|
|
251
|
-
pnpm test
|
|
252
|
-
|
|
253
|
-
# Visual transformation demo
|
|
254
|
-
pnpm test tests/rules/visual-transformation-demo.test.ts
|
|
255
|
-
|
|
256
|
-
# Lint codebase
|
|
257
|
-
pnpm run lint
|
|
258
|
-
|
|
259
|
-
# Type check
|
|
260
|
-
pnpm run typecheck
|
|
261
|
-
|
|
262
|
-
# Run all quality checks
|
|
263
|
-
pnpm run check
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
## Architecture
|
|
267
|
-
|
|
268
|
-
### Philosophy: Custom Rules for Precise Control
|
|
269
|
-
|
|
270
|
-
This plugin provides **custom ESLint rules** specifically designed for functional TypeScript patterns, rather than composing existing rules. This approach offers:
|
|
271
|
-
|
|
272
|
-
- 🎯 **Precise AST Analysis** - Rules understand TypeScript-specific patterns
|
|
273
|
-
- 🔧 **Smart Auto-Fixing** - Context-aware fixes that maintain code intent
|
|
274
|
-
- 📚 **Functype Integration** - Built-in detection of functype library usage
|
|
275
|
-
- 🚀 **Better Performance** - Single-pass analysis instead of multiple rule evaluations
|
|
276
|
-
|
|
277
|
-
### ESLint 9+ Flat Config Only
|
|
278
|
-
|
|
279
|
-
- **Modern Configuration** - Uses ESLint 9.x flat config format
|
|
280
|
-
- **No Legacy Support** - Clean architecture without backwards compatibility burden
|
|
281
|
-
- **Plugin-First Design** - Designed specifically as an ESLint plugin
|
|
282
|
-
|
|
283
|
-
### Test Coverage
|
|
284
|
-
|
|
285
|
-
- **100+ Tests Total** across 11 test suites (including visual tests)
|
|
286
|
-
- **Integration Tests** with real functype library usage
|
|
287
|
-
- **Auto-Fix Verification** ensures fixes produce valid code
|
|
288
|
-
- **Visual Test Output** with colorized before/after transformations
|
|
289
|
-
- **False Positive Prevention** tests ensure proper functype patterns aren't flagged
|
|
290
|
-
|
|
291
|
-
## Contributing
|
|
292
|
-
|
|
293
|
-
1. **Fork** the repository
|
|
294
|
-
2. **Create** a feature branch: `git checkout -b feature-name`
|
|
295
|
-
3. **Make** your changes and add tests
|
|
296
|
-
4. **Ensure** all quality checks pass: `pnpm run check`
|
|
297
|
-
5. **Submit** a pull request
|
|
298
|
-
|
|
299
|
-
### Development Setup
|
|
300
|
-
|
|
301
|
-
**Requirements:**
|
|
302
|
-
|
|
303
|
-
- Node.js 22.0.0 or higher
|
|
304
|
-
- pnpm (recommended package manager)
|
|
305
|
-
|
|
306
|
-
```bash
|
|
307
|
-
git clone https://github.com/jordanburke/eslint-plugin-functype.git
|
|
308
|
-
cd eslint-plugin-functype
|
|
309
|
-
pnpm install
|
|
310
|
-
pnpm run build
|
|
311
|
-
pnpm test
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
## License
|
|
315
|
-
|
|
316
|
-
[MIT](LICENSE) © [Jordan Burke](https://github.com/jordanburke)
|
|
317
|
-
|
|
318
|
-
## Related
|
|
319
|
-
|
|
320
|
-
- **[functype](https://github.com/jordanburke/functype)** - Functional programming library for TypeScript
|
|
321
|
-
- **[eslint-config-functype](https://github.com/jordanburke/eslint-config-functype)** - Complete ESLint config for functional TypeScript projects
|
|
322
|
-
|
|
323
|
-
---
|
|
324
|
-
|
|
325
|
-
**Need help?** [Open an issue](https://github.com/jordanburke/eslint-plugin-functype/issues) or check the [functype documentation](https://jordanburke.github.io/functype/).
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/dependency-validator.ts"],"names":[],"mappings":"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","file":"dependency-validator.js","sourcesContent":["// Utility to validate peer dependencies and provide helpful error messages\n\ninterface PeerDependency {\n name: string\n packageName: string\n description: string\n required: boolean\n}\n\nconst PEER_DEPENDENCIES: PeerDependency[] = [\n {\n name: \"@typescript-eslint/eslint-plugin\",\n packageName: \"@typescript-eslint/eslint-plugin\",\n description: \"TypeScript-aware ESLint rules\",\n required: true,\n },\n {\n name: \"@typescript-eslint/parser\",\n packageName: \"@typescript-eslint/parser\",\n description: \"TypeScript parser for ESLint\",\n required: true,\n },\n {\n name: \"eslint-plugin-functional\",\n packageName: \"eslint-plugin-functional\",\n description: \"Functional programming ESLint rules\",\n required: true,\n },\n {\n name: \"eslint-plugin-prettier\",\n packageName: \"eslint-plugin-prettier\",\n description: \"Code formatting rules\",\n required: false,\n },\n {\n name: \"eslint-plugin-simple-import-sort\",\n packageName: \"eslint-plugin-simple-import-sort\",\n description: \"Import sorting rules\",\n required: false,\n },\n {\n name: \"prettier\",\n packageName: \"prettier\",\n description: \"Code formatter\",\n required: false,\n },\n]\n\nexport interface ValidationResult {\n isValid: boolean\n missing: PeerDependency[]\n available: PeerDependency[]\n installCommand: string\n warnings: string[]\n}\n\nfunction tryRequire(packageName: string): boolean {\n try {\n require.resolve(packageName)\n return true\n } catch {\n return false\n }\n}\n\nexport function validatePeerDependencies(): ValidationResult {\n const missing: PeerDependency[] = []\n const available: PeerDependency[] = []\n const warnings: string[] = []\n\n for (const dep of PEER_DEPENDENCIES) {\n if (tryRequire(dep.packageName)) {\n available.push(dep)\n } else {\n missing.push(dep)\n if (dep.required) {\n // Required dependency is missing - this will cause errors\n } else {\n // Optional dependency is missing - add warning\n warnings.push(`Optional plugin '${dep.name}' not found. Some rules will be skipped.`)\n }\n }\n }\n\n const requiredMissing = missing.filter((dep) => dep.required)\n const isValid = requiredMissing.length === 0\n\n // Generate install command for missing dependencies\n const missingPackageNames = missing.map((dep) => dep.packageName)\n const installCommand = missingPackageNames.length > 0 ? `pnpm add -D ${missingPackageNames.join(\" \")}` : \"\"\n\n return {\n isValid,\n missing,\n available,\n installCommand,\n warnings,\n }\n}\n\nexport function createValidationError(result: ValidationResult): Error {\n const requiredMissing = result.missing.filter((dep) => dep.required)\n\n if (requiredMissing.length === 0) {\n return new Error(\"No validation errors\")\n }\n\n const missingList = requiredMissing.map((dep) => ` • ${dep.name} - ${dep.description}`).join(\"\\n\")\n\n const message = [\n \"❌ Missing required peer dependencies for eslint-plugin-functype:\",\n \"\",\n missingList,\n \"\",\n \"📦 Install missing dependencies:\",\n ` ${result.installCommand}`,\n \"\",\n \"📖 See installation guide: https://github.com/jordanburke/eslint-plugin-functype#installation\",\n ].join(\"\\n\")\n\n return new Error(message)\n}\n\nexport function shouldValidateDependencies(): boolean {\n // Skip validation in test environments or when explicitly disabled\n return process.env.NODE_ENV !== \"test\" && process.env.FUNCTYPE_SKIP_VALIDATION !== \"true\"\n}\n"]}
|