feat: implement strong-typed-routes ESLint rule#105
Merged
M-jerez merged 9 commits intomion-run-typesfrom Aug 26, 2025
Merged
Conversation
- Add new ESLint rule to enforce explicit parameter and return type annotations for router handler functions - Target functions: route, hook, headersHook from @mionkit/router (rawHook is ignored) - Handler functions must have explicit return type annotations - All parameters except the first (CallContext) must have explicit type annotations - Support both arrow functions and regular function expressions - Include comprehensive test suite with 36 test cases - Add rule to recommended config but disable it initially to avoid breaking existing codebase - Rule can be enabled later by removing '@mionkit/strong-typed-routes': 'off' from .eslintrc.js
- Add support for handlers defined separately and passed by reference
- Handle function declarations: function sayHello(ctx, name: string): string { ... }
- Handle arrow function variables: const sayHello = (ctx, name: string): string => ...
- Handle function expression variables: const sayHello = function(ctx, name: string): string { ... }
- Add comprehensive test coverage for all function reference scenarios
- Maintain backward compatibility with inline function expressions
- Update function signatures to support TSESTree.FunctionDeclaration
- Add findFunctionByName utility to locate function definitions in the same file
Test coverage increased from 36 to 46 test cases covering:
- Valid function references with proper types
- Invalid function references missing parameter types
- Invalid function references missing return types
- Invalid function references missing both types
- All router functions: route, hook, headersHook
🎯 NEW FUNCTIONALITY: - Type annotations: const handler: Handler = (ctx, name: string): string => ... - Satisfies expressions: const handler = ((ctx, name: string): string => ...) satisfies Handler - JSDoc tags: @mion:route, @mion:hook, @mion:headersHook for explicit handler marking 🔧 IMPLEMENTATION DETAILS: - Added getHandlerTypeFromAnnotation() for Handler/HeaderHandler type checking - Added getHandlerTypeFromSatisfies() for satisfies expression support - Added getHandlerTypeFromJSDoc() for @mion:* JSDoc tag detection - Added isImportedFromMionRouter() to verify types are from @mionkit/router - Enhanced VariableDeclarator visitor to handle type annotations and JSDoc - Added TSSatisfiesExpression visitor for satisfies expressions - Added checkHandlerFunction() helper to centralize validation logic - Updated JSDoc function to handle VariableDeclaration nodes for arrow functions ✅ COMPREHENSIVE TESTING: - Test coverage increased from 46 to 60 test cases - All scenarios covered: type annotations, satisfies, JSDoc tags - Both valid and invalid cases for each approach - Maintains 100% backward compatibility with existing functionality 🚀 DEVELOPER EXPERIENCE: - Multiple ways to ensure type safety based on coding preferences - Clear, actionable error messages for each approach - Self-documenting code with JSDoc tags - Explicit developer intent with type annotations BREAKING CHANGES: None - all existing functionality preserved
🎯 CHANGES: - Remove disable rule from root .eslintrc.js since no existing violations found - Add comprehensive test file: packages/router/examples/eslint-rule-test.routes.ts - Test file demonstrates all rule functionality with valid/invalid examples 📋 TEST FILE INCLUDES: ✅ Valid examples (should NOT trigger errors): - Direct inline handlers with proper types - Function references with proper types - Type annotations: const handler: Handler = ... - Satisfies expressions: const handler = (...) satisfies Handler - JSDoc tags: @mion:route, @mion:hook, @mion:headersHook ❌ Invalid examples (SHOULD trigger errors): - Missing parameter types - Missing return types - Missing both types - All scenarios across different approaches 🧪 MANUAL TESTING INSTRUCTIONS: 1. Remove /* eslint-disable @mionkit/strong-typed-routes */ from test file 2. Run ESLint on the file to see rule violations 3. Verify valid examples don't error, invalid examples do error 4. Re-add disable comment to prevent CI failures 🚀 PRODUCTION READY: - Rule is now enabled by default - No existing violations in codebase - Comprehensive test coverage - Easy manual verification available
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements a new ESLint rule
strong-typed-routesthat enforces explicit parameter and return type annotations for router handler functions.Rule Purpose
Enforce that handler functions passed to specific router functions have explicitly defined parameter types (except the first parameter) and return types.
Target Functions
The rule checks calls to these functions from
@mionkit/router:routehookheadersHookrawHook(not type-checked)Rule Requirements
CallContextand is ignored by this ruleValid Examples
Invalid Examples
Implementation Details
Breaking Change Prevention
The rule is added to the recommended config but initially disabled in
.eslintrc.jsto avoid breaking the existing codebase:To enable the rule later, simply remove this line from the root ESLint configuration.
Files Changed
packages/eslint-plugin/src/rules/strong-typed-routes.ts- Main rule implementationpackages/eslint-plugin/src/rules/strong-typed-routes.spec.ts- Comprehensive test suitepackages/eslint-plugin/src/index.ts- Export rule and add to recommended config.eslintrc.js- Disable rule initially to prevent breaking changesTesting
✅ All tests pass (36 test cases)
✅ Build successful
✅ Linting passes
✅ Code formatted
Next Steps
Once this PR is merged, teams can gradually enable the rule by:
'@mionkit/strong-typed-routes': 'off'from.eslintrc.jsPull Request opened by Augment Code with guidance from the PR author