mcp-react-toolkit 1.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 (228) hide show
  1. package/CONTRIBUTING.md +157 -0
  2. package/HOW_IT_WORKS.md +270 -0
  3. package/README.md +259 -0
  4. package/demo/legacy-app/src/App.jsx +12 -0
  5. package/demo/legacy-app/src/components/Dashboard.jsx +51 -0
  6. package/demo/legacy-app/src/components/UserCard.jsx +32 -0
  7. package/demo/legacy-app/src/hooks/useUsers.js +38 -0
  8. package/demo/legacy-app/src/utils/api.js +30 -0
  9. package/glama.json +4 -0
  10. package/package.json +39 -0
  11. package/tools/accessibility-checker/build/index.d.ts +3 -0
  12. package/tools/accessibility-checker/build/index.d.ts.map +1 -0
  13. package/tools/accessibility-checker/build/index.js +112 -0
  14. package/tools/accessibility-checker/build/index.js.map +1 -0
  15. package/tools/accessibility-checker/build/rules.d.ts +22 -0
  16. package/tools/accessibility-checker/build/rules.d.ts.map +1 -0
  17. package/tools/accessibility-checker/build/rules.js +244 -0
  18. package/tools/accessibility-checker/build/rules.js.map +1 -0
  19. package/tools/accessibility-checker/build/rules.test.d.ts +2 -0
  20. package/tools/accessibility-checker/build/rules.test.d.ts.map +1 -0
  21. package/tools/accessibility-checker/build/rules.test.js.map +1 -0
  22. package/tools/accessibility-checker/package.json +20 -0
  23. package/tools/code-modernizer/build/index.d.ts +3 -0
  24. package/tools/code-modernizer/build/index.d.ts.map +1 -0
  25. package/tools/code-modernizer/build/index.js +58 -0
  26. package/tools/code-modernizer/build/index.js.map +1 -0
  27. package/tools/code-modernizer/build/tools/01-convert-to-typescript.d.ts +3 -0
  28. package/tools/code-modernizer/build/tools/01-convert-to-typescript.d.ts.map +1 -0
  29. package/tools/code-modernizer/build/tools/01-convert-to-typescript.js +110 -0
  30. package/tools/code-modernizer/build/tools/01-convert-to-typescript.js.map +1 -0
  31. package/tools/code-modernizer/build/types.d.ts +57 -0
  32. package/tools/code-modernizer/build/types.d.ts.map +1 -0
  33. package/tools/code-modernizer/build/types.js +5 -0
  34. package/tools/code-modernizer/build/types.js.map +1 -0
  35. package/tools/code-modernizer/build/utils/ast-parser.d.ts +6 -0
  36. package/tools/code-modernizer/build/utils/ast-parser.d.ts.map +1 -0
  37. package/tools/code-modernizer/build/utils/ast-parser.js +177 -0
  38. package/tools/code-modernizer/build/utils/ast-parser.js.map +1 -0
  39. package/tools/code-modernizer/build/utils/file-ops.d.ts +8 -0
  40. package/tools/code-modernizer/build/utils/file-ops.d.ts.map +1 -0
  41. package/tools/code-modernizer/build/utils/file-ops.js +63 -0
  42. package/tools/code-modernizer/build/utils/file-ops.js.map +1 -0
  43. package/tools/code-modernizer/build/utils/file-ops.test.d.ts +2 -0
  44. package/tools/code-modernizer/build/utils/file-ops.test.d.ts.map +1 -0
  45. package/tools/code-modernizer/build/utils/file-ops.test.js.map +1 -0
  46. package/tools/code-modernizer/build/utils/type-generator.d.ts +4 -0
  47. package/tools/code-modernizer/build/utils/type-generator.d.ts.map +1 -0
  48. package/tools/code-modernizer/build/utils/type-generator.js +37 -0
  49. package/tools/code-modernizer/build/utils/type-generator.js.map +1 -0
  50. package/tools/code-modernizer/package.json +23 -0
  51. package/tools/component-factory/build/index.d.ts +3 -0
  52. package/tools/component-factory/build/index.d.ts.map +1 -0
  53. package/tools/component-factory/build/index.js +534 -0
  54. package/tools/component-factory/build/index.js.map +1 -0
  55. package/tools/component-factory/build/utils.d.ts +6 -0
  56. package/tools/component-factory/build/utils.d.ts.map +1 -0
  57. package/tools/component-factory/build/utils.js +11 -0
  58. package/tools/component-factory/build/utils.js.map +1 -0
  59. package/tools/component-factory/build/utils.test.d.ts +2 -0
  60. package/tools/component-factory/build/utils.test.d.ts.map +1 -0
  61. package/tools/component-factory/build/utils.test.js.map +1 -0
  62. package/tools/component-factory/package.json +20 -0
  63. package/tools/component-factory/templates/accordion.tsx +57 -0
  64. package/tools/component-factory/templates/alert.tsx +59 -0
  65. package/tools/component-factory/templates/aspect-ratio.tsx +8 -0
  66. package/tools/component-factory/templates/avatar.tsx +51 -0
  67. package/tools/component-factory/templates/badge.tsx +37 -0
  68. package/tools/component-factory/templates/breadcrumb.tsx +116 -0
  69. package/tools/component-factory/templates/button.tsx +57 -0
  70. package/tools/component-factory/templates/calendar.tsx +66 -0
  71. package/tools/component-factory/templates/card.tsx +80 -0
  72. package/tools/component-factory/templates/checkbox.tsx +31 -0
  73. package/tools/component-factory/templates/collapsible.tsx +11 -0
  74. package/tools/component-factory/templates/command.tsx +150 -0
  75. package/tools/component-factory/templates/context-menu.tsx +199 -0
  76. package/tools/component-factory/templates/dialog.tsx +123 -0
  77. package/tools/component-factory/templates/drawer.tsx +118 -0
  78. package/tools/component-factory/templates/dropdown-menu.tsx +201 -0
  79. package/tools/component-factory/templates/form.tsx +178 -0
  80. package/tools/component-factory/templates/hover-card.tsx +29 -0
  81. package/tools/component-factory/templates/input-otp.tsx +71 -0
  82. package/tools/component-factory/templates/input.tsx +23 -0
  83. package/tools/component-factory/templates/label.tsx +27 -0
  84. package/tools/component-factory/templates/menubar.tsx +236 -0
  85. package/tools/component-factory/templates/navigation-menu.tsx +128 -0
  86. package/tools/component-factory/templates/pagination.tsx +120 -0
  87. package/tools/component-factory/templates/popover.tsx +31 -0
  88. package/tools/component-factory/templates/progress.tsx +28 -0
  89. package/tools/component-factory/templates/radio-group.tsx +44 -0
  90. package/tools/component-factory/templates/scroll-area.tsx +48 -0
  91. package/tools/component-factory/templates/select.tsx +159 -0
  92. package/tools/component-factory/templates/separator.tsx +32 -0
  93. package/tools/component-factory/templates/sheet.tsx +140 -0
  94. package/tools/component-factory/templates/skeleton.tsx +15 -0
  95. package/tools/component-factory/templates/slider.tsx +28 -0
  96. package/tools/component-factory/templates/sonner.tsx +31 -0
  97. package/tools/component-factory/templates/switch.tsx +29 -0
  98. package/tools/component-factory/templates/table.tsx +117 -0
  99. package/tools/component-factory/templates/tabs.tsx +56 -0
  100. package/tools/component-factory/templates/textarea.tsx +22 -0
  101. package/tools/component-factory/templates/toggle-group.tsx +61 -0
  102. package/tools/component-factory/templates/toggle.tsx +45 -0
  103. package/tools/component-factory/templates/tooltip.tsx +30 -0
  104. package/tools/dep-auditor/build/index.d.ts +18 -0
  105. package/tools/dep-auditor/build/index.d.ts.map +1 -0
  106. package/tools/dep-auditor/build/index.js +247 -0
  107. package/tools/dep-auditor/build/index.js.map +1 -0
  108. package/tools/dep-auditor/build/index.test.d.ts +2 -0
  109. package/tools/dep-auditor/build/index.test.d.ts.map +1 -0
  110. package/tools/dep-auditor/build/index.test.js.map +1 -0
  111. package/tools/dep-auditor/package.json +20 -0
  112. package/tools/generate-tests/build/analyzer.d.ts +31 -0
  113. package/tools/generate-tests/build/analyzer.d.ts.map +1 -0
  114. package/tools/generate-tests/build/analyzer.js +105 -0
  115. package/tools/generate-tests/build/analyzer.js.map +1 -0
  116. package/tools/generate-tests/build/analyzer.test.d.ts +2 -0
  117. package/tools/generate-tests/build/analyzer.test.d.ts.map +1 -0
  118. package/tools/generate-tests/build/analyzer.test.js.map +1 -0
  119. package/tools/generate-tests/build/generators.d.ts +6 -0
  120. package/tools/generate-tests/build/generators.d.ts.map +1 -0
  121. package/tools/generate-tests/build/generators.js +161 -0
  122. package/tools/generate-tests/build/generators.js.map +1 -0
  123. package/tools/generate-tests/build/index.d.ts +3 -0
  124. package/tools/generate-tests/build/index.d.ts.map +1 -0
  125. package/tools/generate-tests/build/index.js +148 -0
  126. package/tools/generate-tests/build/index.js.map +1 -0
  127. package/tools/generate-tests/package.json +20 -0
  128. package/tools/json-viewer/build/index.d.ts +3 -0
  129. package/tools/json-viewer/build/index.d.ts.map +1 -0
  130. package/tools/json-viewer/build/index.js +282 -0
  131. package/tools/json-viewer/build/index.js.map +1 -0
  132. package/tools/json-viewer/build/utils.d.ts +5 -0
  133. package/tools/json-viewer/build/utils.d.ts.map +1 -0
  134. package/tools/json-viewer/build/utils.js +40 -0
  135. package/tools/json-viewer/build/utils.js.map +1 -0
  136. package/tools/json-viewer/build/utils.test.d.ts +2 -0
  137. package/tools/json-viewer/build/utils.test.d.ts.map +1 -0
  138. package/tools/json-viewer/build/utils.test.js.map +1 -0
  139. package/tools/json-viewer/package.json +20 -0
  140. package/tools/monorepo-manager/build/index.d.ts +3 -0
  141. package/tools/monorepo-manager/build/index.d.ts.map +1 -0
  142. package/tools/monorepo-manager/build/index.js +318 -0
  143. package/tools/monorepo-manager/build/index.js.map +1 -0
  144. package/tools/monorepo-manager/build/types.d.ts +17 -0
  145. package/tools/monorepo-manager/build/types.d.ts.map +1 -0
  146. package/tools/monorepo-manager/build/types.js +2 -0
  147. package/tools/monorepo-manager/build/types.js.map +1 -0
  148. package/tools/monorepo-manager/build/utils.d.ts +9 -0
  149. package/tools/monorepo-manager/build/utils.d.ts.map +1 -0
  150. package/tools/monorepo-manager/build/utils.js +135 -0
  151. package/tools/monorepo-manager/build/utils.js.map +1 -0
  152. package/tools/monorepo-manager/build/utils.test.d.ts +2 -0
  153. package/tools/monorepo-manager/build/utils.test.d.ts.map +1 -0
  154. package/tools/monorepo-manager/build/utils.test.js.map +1 -0
  155. package/tools/monorepo-manager/package.json +20 -0
  156. package/tools/quality-pipeline/build/index.d.ts +3 -0
  157. package/tools/quality-pipeline/build/index.d.ts.map +1 -0
  158. package/tools/quality-pipeline/build/index.js +538 -0
  159. package/tools/quality-pipeline/build/index.js.map +1 -0
  160. package/tools/quality-pipeline/build/utils.d.ts +9 -0
  161. package/tools/quality-pipeline/build/utils.d.ts.map +1 -0
  162. package/tools/quality-pipeline/build/utils.js +15 -0
  163. package/tools/quality-pipeline/build/utils.js.map +1 -0
  164. package/tools/quality-pipeline/build/utils.test.d.ts +2 -0
  165. package/tools/quality-pipeline/build/utils.test.d.ts.map +1 -0
  166. package/tools/quality-pipeline/build/utils.test.js.map +1 -0
  167. package/tools/quality-pipeline/package.json +20 -0
  168. package/tools/shared/build/McpServerBase.d.ts +18 -0
  169. package/tools/shared/build/McpServerBase.d.ts.map +1 -0
  170. package/tools/shared/build/McpServerBase.js +74 -0
  171. package/tools/shared/build/McpServerBase.js.map +1 -0
  172. package/tools/shared/build/ToolRegistry.d.ts +9 -0
  173. package/tools/shared/build/ToolRegistry.d.ts.map +1 -0
  174. package/tools/shared/build/ToolRegistry.js +22 -0
  175. package/tools/shared/build/ToolRegistry.js.map +1 -0
  176. package/tools/shared/build/index.d.ts +4 -0
  177. package/tools/shared/build/index.d.ts.map +1 -0
  178. package/tools/shared/build/index.js +4 -0
  179. package/tools/shared/build/index.js.map +1 -0
  180. package/tools/shared/build/types.d.ts +36 -0
  181. package/tools/shared/build/types.d.ts.map +1 -0
  182. package/tools/shared/build/types.js +5 -0
  183. package/tools/shared/build/types.js.map +1 -0
  184. package/tools/shared/package.json +23 -0
  185. package/tools/typescript-enforcer/build/index.d.ts +3 -0
  186. package/tools/typescript-enforcer/build/index.d.ts.map +1 -0
  187. package/tools/typescript-enforcer/build/index.js +155 -0
  188. package/tools/typescript-enforcer/build/index.js.map +1 -0
  189. package/tools/typescript-enforcer/build/rules/branded-types.d.ts +3 -0
  190. package/tools/typescript-enforcer/build/rules/branded-types.d.ts.map +1 -0
  191. package/tools/typescript-enforcer/build/rules/branded-types.js +4 -0
  192. package/tools/typescript-enforcer/build/rules/branded-types.js.map +1 -0
  193. package/tools/typescript-enforcer/build/rules/discriminated-unions.d.ts +3 -0
  194. package/tools/typescript-enforcer/build/rules/discriminated-unions.d.ts.map +1 -0
  195. package/tools/typescript-enforcer/build/rules/discriminated-unions.js +4 -0
  196. package/tools/typescript-enforcer/build/rules/discriminated-unions.js.map +1 -0
  197. package/tools/typescript-enforcer/build/rules/generics.d.ts +3 -0
  198. package/tools/typescript-enforcer/build/rules/generics.d.ts.map +1 -0
  199. package/tools/typescript-enforcer/build/rules/generics.js +182 -0
  200. package/tools/typescript-enforcer/build/rules/generics.js.map +1 -0
  201. package/tools/typescript-enforcer/build/rules/modifiers.d.ts +3 -0
  202. package/tools/typescript-enforcer/build/rules/modifiers.d.ts.map +1 -0
  203. package/tools/typescript-enforcer/build/rules/modifiers.js +214 -0
  204. package/tools/typescript-enforcer/build/rules/modifiers.js.map +1 -0
  205. package/tools/typescript-enforcer/build/rules/no-any.d.ts +3 -0
  206. package/tools/typescript-enforcer/build/rules/no-any.d.ts.map +1 -0
  207. package/tools/typescript-enforcer/build/rules/no-any.js +138 -0
  208. package/tools/typescript-enforcer/build/rules/no-any.js.map +1 -0
  209. package/tools/typescript-enforcer/build/rules/type-guards.d.ts +3 -0
  210. package/tools/typescript-enforcer/build/rules/type-guards.d.ts.map +1 -0
  211. package/tools/typescript-enforcer/build/rules/type-guards.js +176 -0
  212. package/tools/typescript-enforcer/build/rules/type-guards.js.map +1 -0
  213. package/tools/typescript-enforcer/build/rules/utility-types.d.ts +3 -0
  214. package/tools/typescript-enforcer/build/rules/utility-types.d.ts.map +1 -0
  215. package/tools/typescript-enforcer/build/rules/utility-types.js +101 -0
  216. package/tools/typescript-enforcer/build/rules/utility-types.js.map +1 -0
  217. package/tools/typescript-enforcer/build/scanner.d.ts +4 -0
  218. package/tools/typescript-enforcer/build/scanner.d.ts.map +1 -0
  219. package/tools/typescript-enforcer/build/scanner.js +114 -0
  220. package/tools/typescript-enforcer/build/scanner.js.map +1 -0
  221. package/tools/typescript-enforcer/build/scanner.test.d.ts +2 -0
  222. package/tools/typescript-enforcer/build/scanner.test.d.ts.map +1 -0
  223. package/tools/typescript-enforcer/build/scanner.test.js.map +1 -0
  224. package/tools/typescript-enforcer/build/types.d.ts +55 -0
  225. package/tools/typescript-enforcer/build/types.d.ts.map +1 -0
  226. package/tools/typescript-enforcer/build/types.js +2 -0
  227. package/tools/typescript-enforcer/build/types.js.map +1 -0
  228. package/tools/typescript-enforcer/package.json +20 -0
@@ -0,0 +1,182 @@
1
+ export function checkGenerics(source, filePath) {
2
+ const violations = [];
3
+ const lines = source.split('\n');
4
+ for (let i = 0; i < lines.length; i++) {
5
+ const line = lines[i];
6
+ const trimmed = line.trim();
7
+ if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*'))
8
+ continue;
9
+ const hookNoTypeRegex = /\b(useRef|useMemo|useReducer|useContext)\s*\(/g;
10
+ let hookMatch;
11
+ while ((hookMatch = hookNoTypeRegex.exec(line)) !== null) {
12
+ const hookName = hookMatch[1];
13
+ const upToHook = line.slice(hookMatch.index);
14
+ if (upToHook.startsWith(`${hookName}<`))
15
+ continue;
16
+ let suggestion = '';
17
+ let why = '';
18
+ if (hookName === 'useRef') {
19
+ suggestion = `useRef<HTMLElement>(null) or useRef<ReturnType<typeof setTimeout>>(null)`;
20
+ why = 'Untyped useRef defaults to MutableRefObject<null>. Specify the ref target type for proper DOM/timer typing.';
21
+ }
22
+ else if (hookName === 'useMemo') {
23
+ suggestion = `useMemo<ReturnType>(() => ...)`;
24
+ why = 'Explicit type param on useMemo documents the intended memoized value type and catches computation errors.';
25
+ }
26
+ else if (hookName === 'useReducer') {
27
+ suggestion = `useReducer<State, Action>(reducer, initialState)`;
28
+ why = 'Typed reducers ensure state transitions are correct and action payloads are validated.';
29
+ }
30
+ else {
31
+ suggestion = `${hookName}<Type>(...)`;
32
+ why = 'React hooks benefit from explicit type parameters for better type safety and IDE support.';
33
+ }
34
+ violations.push({
35
+ rule: 'generics',
36
+ severity: 'warning',
37
+ line: i + 1,
38
+ column: hookMatch.index + 1,
39
+ current: `${hookName}(...)`,
40
+ suggestion,
41
+ fix: `// Add explicit type parameter:\n// ${suggestion}`,
42
+ why,
43
+ });
44
+ }
45
+ const castReturnRegex = /function\s+(\w+)\s*\([^)]*\):\s*(any|unknown)\s*\{/;
46
+ const castMatch = line.match(castReturnRegex);
47
+ if (castMatch) {
48
+ violations.push({
49
+ rule: 'generics',
50
+ severity: 'warning',
51
+ line: i + 1,
52
+ column: 1,
53
+ current: `function ${castMatch[1]}(...): ${castMatch[2]}`,
54
+ suggestion: `function ${castMatch[1]}<T>(...): T`,
55
+ fix: `// Make the function generic: function ${castMatch[1]}<T>(...): T {\n// Then call it with explicit type: ${castMatch[1]}<ReturnType>(...)`,
56
+ why: 'Generic functions preserve type information through the call chain. Returning any/unknown loses type safety.',
57
+ });
58
+ }
59
+ const assertReturnRegex = /return\s+(\w+)\s+as\s+(\w+)/g;
60
+ let assertMatch;
61
+ while ((assertMatch = assertReturnRegex.exec(line)) !== null) {
62
+ const funcContext = findFunctionContext(lines, i);
63
+ if (funcContext && !funcContext.includes('<')) {
64
+ violations.push({
65
+ rule: 'generics',
66
+ severity: 'info',
67
+ line: i + 1,
68
+ column: assertMatch.index + 1,
69
+ current: `return ${assertMatch[1]} as ${assertMatch[2]}`,
70
+ suggestion: `Make the enclosing function generic: <T>(): T`,
71
+ fix: `// Consider making the function generic instead of casting:\n// function parseResponse<T>(data: unknown): T { return data as T; }`,
72
+ why: 'Type assertions in returns indicate the function could be generic to preserve type information.',
73
+ });
74
+ }
75
+ }
76
+ const objEntriesRegex = /Object\.(entries|keys|values)\s*\(/g;
77
+ let objMatch;
78
+ while ((objMatch = objEntriesRegex.exec(line)) !== null) {
79
+ if (!line.includes('as ') && !line.includes('<')) {
80
+ violations.push({
81
+ rule: 'generics',
82
+ severity: 'info',
83
+ line: i + 1,
84
+ column: objMatch.index + 1,
85
+ current: `Object.${objMatch[1]}(...)`,
86
+ suggestion: `Use Object.${objMatch[1]}(obj) with type narrowing or Object.${objMatch[1]}<K extends keyof T>(obj: T)`,
87
+ fix: `// Add type parameter: Object.${objMatch[1]}<string, ValueType>(obj)`,
88
+ why: `Object.${objMatch[1]} returns string[] or [string, any][] without type information. Use generics or type assertions for type safety.`,
89
+ });
90
+ }
91
+ }
92
+ const collectionRegex = /new\s+(Array|Map|Set)\s*\(/g;
93
+ let collMatch;
94
+ while ((collMatch = collectionRegex.exec(line)) !== null) {
95
+ if (!line.includes('<')) {
96
+ violations.push({
97
+ rule: 'generics',
98
+ severity: 'warning',
99
+ line: i + 1,
100
+ column: collMatch.index + 1,
101
+ current: `new ${collMatch[1]}(...)`,
102
+ suggestion: `new ${collMatch[1]}<Type>(...)`,
103
+ fix: `// Add type parameter: new ${collMatch[1]}<SpecificType>(...)`,
104
+ why: `Untyped collections default to ${collMatch[1]}<any>. Always specify the element type.`,
105
+ });
106
+ }
107
+ }
108
+ const callbackRegex = /callback:\s*\([^)]*\)\s*=>\s*void/g;
109
+ let cbMatch;
110
+ while ((cbMatch = callbackRegex.exec(line)) !== null) {
111
+ violations.push({
112
+ rule: 'generics',
113
+ severity: 'info',
114
+ line: i + 1,
115
+ column: cbMatch.index + 1,
116
+ current: 'callback: (...) => void',
117
+ suggestion: 'callback: <T>(arg: T) => void or use a generic type parameter',
118
+ fix: '// Make callback generic: <T>(value: T) => void',
119
+ why: 'Generic callbacks preserve the type of the argument, enabling better type inference in the caller.',
120
+ });
121
+ }
122
+ const utilityPatterns = [
123
+ { regex: /function\s+(clone|deepClone|merge|assign|extend)\s*\(/, name: 'clone/merge' },
124
+ { regex: /function\s+(filter|find|map|reduce)\w*\s*\(/, name: 'collection operation' },
125
+ { regex: /function\s+(pick|omit|pluck|get|set)\s*\(/, name: 'property access' },
126
+ ];
127
+ for (const pattern of utilityPatterns) {
128
+ const utilMatch = line.match(pattern.regex);
129
+ if (utilMatch && !line.includes('<')) {
130
+ violations.push({
131
+ rule: 'generics',
132
+ severity: 'info',
133
+ line: i + 1,
134
+ column: 1,
135
+ current: line.trim(),
136
+ suggestion: `Make ${utilMatch[1]} generic: function ${utilMatch[1]}<T>(...): T`,
137
+ fix: `// Add generic type parameter: <T extends Record<string, unknown>>(obj: T)`,
138
+ why: `Utility functions like ${pattern.name} should be generic to work with any type while preserving type information.`,
139
+ });
140
+ }
141
+ }
142
+ const classMatch = line.match(/class\s+(\w+)/);
143
+ if (classMatch) {
144
+ const classEnd = findClassEnd(lines, i);
145
+ const classBody = lines.slice(i, classEnd).join('\n');
146
+ const assertionCount = (classBody.match(/\bas\s+\w+/g) || []).length;
147
+ const genericCount = (classBody.match(/<\w+>/g) || []).length;
148
+ if (assertionCount >= 3 && genericCount === 0) {
149
+ violations.push({
150
+ rule: 'generics',
151
+ severity: 'warning',
152
+ line: i + 1,
153
+ column: 1,
154
+ current: `class ${classMatch[1]} (has ${assertionCount} type assertions)`,
155
+ suggestion: `class ${classMatch[1]}<T> { ... }`,
156
+ fix: `// Consider making the class generic:\n// class ${classMatch[1]}<T> {\n// private data: T;\n// constructor(data: T) { this.data = data; }\n// }`,
157
+ why: `Class has ${assertionCount} type assertions but no generics. Generic classes avoid repeated assertions by maintaining type information.`,
158
+ });
159
+ }
160
+ }
161
+ }
162
+ return { violations };
163
+ }
164
+ function findFunctionContext(lines, currentLine) {
165
+ for (let i = currentLine; i >= 0; i--) {
166
+ const match = lines[i].match(/(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*(<[^>]*>)?\s*\(/);
167
+ if (match)
168
+ return match[0];
169
+ }
170
+ return null;
171
+ }
172
+ function findClassEnd(lines, startLine) {
173
+ let depth = 0;
174
+ for (let i = startLine; i < lines.length; i++) {
175
+ depth += (lines[i].match(/{/g) || []).length;
176
+ depth -= (lines[i].match(/}/g) || []).length;
177
+ if (depth === 0 && i > startLine)
178
+ return i;
179
+ }
180
+ return lines.length;
181
+ }
182
+ //# sourceMappingURL=generics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generics.js","sourceRoot":"","sources":["../../src/rules/generics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RuleCheckResult } from '../types.js';
2
+ export declare function checkModifiers(source: string, filePath: string): RuleCheckResult;
3
+ //# sourceMappingURL=modifiers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modifiers.d.ts","sourceRoot":"","sources":["../../src/rules/modifiers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CA0NhF"}
@@ -0,0 +1,214 @@
1
+ export function checkModifiers(source, filePath) {
2
+ const violations = [];
3
+ const lines = source.split('\n');
4
+ let insideInterface = false;
5
+ let interfaceName = '';
6
+ let interfaceDepth = 0;
7
+ for (let i = 0; i < lines.length; i++) {
8
+ const line = lines[i];
9
+ const trimmed = line.trim();
10
+ if (trimmed.startsWith('//') || trimmed.startsWith('*'))
11
+ continue;
12
+ const ifaceStart = line.match(/^(?:export\s+)?interface\s+(\w+)/);
13
+ if (ifaceStart) {
14
+ insideInterface = true;
15
+ interfaceName = ifaceStart[1];
16
+ interfaceDepth = 0;
17
+ }
18
+ if (insideInterface) {
19
+ interfaceDepth += (line.match(/\{/g) || []).length;
20
+ interfaceDepth -= (line.match(/\}/g) || []).length;
21
+ if (interfaceDepth <= 0 && line.includes('}')) {
22
+ insideInterface = false;
23
+ continue;
24
+ }
25
+ const propMatch = trimmed.match(/^(\w+)\s*\??\s*:\s*.+/);
26
+ if (propMatch && !trimmed.startsWith('readonly') && interfaceDepth > 0) {
27
+ const propName = propMatch[1];
28
+ violations.push({
29
+ rule: 'modifiers',
30
+ severity: 'info',
31
+ line: i + 1,
32
+ column: line.indexOf(propName) + 1,
33
+ current: trimmed.slice(0, 60),
34
+ suggestion: `readonly ${trimmed.slice(0, 60)}`,
35
+ fix: `// Mark interface property as readonly to prevent accidental mutation:\n// readonly ${propName}: ...`,
36
+ why: `Interface properties in '${interfaceName}' should be readonly unless they need to be mutated. Readonly props prevent accidental modification and communicate immutability intent.`,
37
+ });
38
+ }
39
+ }
40
+ }
41
+ for (let i = 0; i < lines.length; i++) {
42
+ const line = lines[i];
43
+ const trimmed = line.trim();
44
+ if (trimmed.startsWith('//'))
45
+ continue;
46
+ if (/^\s*return\s*\{/.test(line) && !line.includes('as const')) {
47
+ let depth = (line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length;
48
+ let endLine = i;
49
+ for (let j = i + 1; j < lines.length && depth > 0; j++) {
50
+ depth += (lines[j].match(/\{/g) || []).length;
51
+ depth -= (lines[j].match(/\}/g) || []).length;
52
+ if (depth <= 0) {
53
+ endLine = j;
54
+ break;
55
+ }
56
+ }
57
+ const closingLine = lines[endLine] || '';
58
+ if (!closingLine.includes('as const')) {
59
+ violations.push({
60
+ rule: 'modifiers',
61
+ severity: 'info',
62
+ line: i + 1,
63
+ column: line.indexOf('return') + 1,
64
+ current: 'return { ... }',
65
+ suggestion: 'return { ... } as const',
66
+ fix: `// Add 'as const' to preserve literal types:\n// return {\n// key: 'value',\n// } as const`,
67
+ why: "'as const' on returned object literals preserves literal types ('light' instead of string), enabling exhaustive checks and autocomplete.",
68
+ });
69
+ }
70
+ }
71
+ }
72
+ for (let i = 0; i < lines.length; i++) {
73
+ const line = lines[i];
74
+ const trimmed = line.trim();
75
+ if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*'))
76
+ continue;
77
+ const constArrayRegex = /(?:export\s+)?const\s+(\w+)\s*=\s*\[/g;
78
+ let match;
79
+ while ((match = constArrayRegex.exec(line)) !== null) {
80
+ const restOfLine = line.slice(match.index);
81
+ if (!restOfLine.includes('(') && !restOfLine.includes('map') && !restOfLine.includes('filter')) {
82
+ if (!restOfLine.includes('as const')) {
83
+ violations.push({
84
+ rule: 'modifiers',
85
+ severity: 'info',
86
+ line: i + 1,
87
+ column: match.index + 1,
88
+ current: `const ${match[1]} = [...]`,
89
+ suggestion: `const ${match[1]} = [...] as const`,
90
+ fix: `// Add 'as const' to make the array readonly with literal types:\n// const ${match[1]} = [...] as const`,
91
+ why: "'as const' makes the array readonly and infers literal types (e.g., ['a', 'b'] becomes readonly ['a', 'b'] instead of string[]).",
92
+ });
93
+ }
94
+ }
95
+ }
96
+ const constObjectRegex = /(?:export\s+)?const\s+(\w+)\s*=\s*\{/g;
97
+ while ((match = constObjectRegex.exec(line)) !== null) {
98
+ const restOfLine = line.slice(match.index);
99
+ if (!restOfLine.includes('(') && !restOfLine.includes('as const')) {
100
+ const objectEnd = findObjectEnd(lines, i);
101
+ const objectBody = lines.slice(i, objectEnd + 1).join('\n');
102
+ const hasFunctionCall = objectBody.includes('(');
103
+ const hasSpread = objectBody.includes('...');
104
+ if (!hasFunctionCall && !hasSpread) {
105
+ violations.push({
106
+ rule: 'modifiers',
107
+ severity: 'info',
108
+ line: i + 1,
109
+ column: match.index + 1,
110
+ current: `const ${match[1]} = { ... }`,
111
+ suggestion: `const ${match[1]} = { ... } as const`,
112
+ fix: `// Add 'as const' for deeply readonly with literal types:\n// const ${match[1]} = { ... } as const`,
113
+ why: "'as const' makes the entire object deeply readonly and preserves literal types for all properties.",
114
+ });
115
+ }
116
+ }
117
+ }
118
+ const interfacePropRegex = /^\s+(\w+)\s*\??\s*:\s*([^;]+);/g;
119
+ while ((match = interfacePropRegex.exec(line)) !== null) {
120
+ const propName = match[1];
121
+ const propType = match[2].trim();
122
+ if (line.includes('readonly'))
123
+ continue;
124
+ if (propName.toLowerCase().endsWith('id') || propName === 'id') {
125
+ violations.push({
126
+ rule: 'modifiers',
127
+ severity: 'info',
128
+ line: i + 1,
129
+ column: 1,
130
+ current: `${propName}: ${propType}`,
131
+ suggestion: `readonly ${propName}: ${propType}`,
132
+ fix: `// Make ID properties readonly - they shouldn't change after creation:\n// readonly ${propName}: ${propType}`,
133
+ why: "ID properties should be readonly since they're immutable identifiers set at creation time.",
134
+ });
135
+ }
136
+ if (propName.toLowerCase().includes('created') || propName.toLowerCase().includes('updated')) {
137
+ if (propType.includes('Date') || propType.includes('number')) {
138
+ violations.push({
139
+ rule: 'modifiers',
140
+ severity: 'info',
141
+ line: i + 1,
142
+ column: 1,
143
+ current: `${propName}: ${propType}`,
144
+ suggestion: `readonly ${propName}: ${propType}`,
145
+ fix: `// Make timestamp properties readonly:\n// readonly ${propName}: ${propType}`,
146
+ why: "Timestamp properties like createdAt/updatedAt should be readonly as they're set by the system.",
147
+ });
148
+ }
149
+ }
150
+ }
151
+ const letVariable = line.match(/let\s+(\w+)\s*=/);
152
+ if (letVariable) {
153
+ const varName = letVariable[1];
154
+ const restOfFile = lines.slice(i + 1).join('\n');
155
+ const reassignment = restOfFile.match(new RegExp(`${varName}\\s*=`));
156
+ if (!reassignment) {
157
+ violations.push({
158
+ rule: 'modifiers',
159
+ severity: 'warning',
160
+ line: i + 1,
161
+ column: 1,
162
+ current: `let ${varName} = ...`,
163
+ suggestion: `const ${varName} = ...`,
164
+ fix: `// Use 'const' instead of 'let' - variable is never reassigned:\n// const ${varName} = ...`,
165
+ why: "Use 'const' by default. Only use 'let' when the variable needs to be reassigned.",
166
+ });
167
+ }
168
+ }
169
+ const typeAlias = line.match(/const\s+(\w+)\s*:\s*(\w+)\s*=/);
170
+ if (typeAlias) {
171
+ const varName = typeAlias[1];
172
+ const typeName = typeAlias[2];
173
+ const nextLines = lines.slice(i + 1, Math.min(i + 10, lines.length)).join('\n');
174
+ const hasPropertyAccess = nextLines.includes(`${varName}.`);
175
+ if (hasPropertyAccess && !line.includes('satisfies')) {
176
+ violations.push({
177
+ rule: 'modifiers',
178
+ severity: 'info',
179
+ line: i + 1,
180
+ column: 1,
181
+ current: `const ${varName}: ${typeName} = ...`,
182
+ suggestion: `const ${varName} = ... satisfies ${typeName}`,
183
+ fix: `// Use 'satisfies' instead of type annotation for better inference:\n// const ${varName} = ... satisfies ${typeName}`,
184
+ why: "'satisfies' validates the type while preserving the narrower inferred type, enabling better autocomplete.",
185
+ });
186
+ }
187
+ }
188
+ const enumLike = line.match(/(?:export\s+)?const\s+(\w+_(?:TYPE|STATUS|MODE|STATE|KIND))\s*=\s*['"]([^'"]+)['"]/);
189
+ if (enumLike) {
190
+ violations.push({
191
+ rule: 'modifiers',
192
+ severity: 'info',
193
+ line: i + 1,
194
+ column: 1,
195
+ current: `const ${enumLike[1]} = '${enumLike[2]}'`,
196
+ suggestion: `const ${enumLike[1]} = '${enumLike[2]}' as const`,
197
+ fix: `// Use 'as const' for string literal types:\n// const ${enumLike[1]} = '${enumLike[2]}' as const`,
198
+ why: "'as const' creates a literal type ('value') instead of widening to string.",
199
+ });
200
+ }
201
+ }
202
+ return { violations };
203
+ }
204
+ function findObjectEnd(lines, startLine) {
205
+ let depth = 0;
206
+ for (let i = startLine; i < lines.length; i++) {
207
+ depth += (lines[i].match(/{/g) || []).length;
208
+ depth -= (lines[i].match(/}/g) || []).length;
209
+ if (depth === 0 && i > startLine)
210
+ return i;
211
+ }
212
+ return Math.min(startLine + 20, lines.length - 1);
213
+ }
214
+ //# sourceMappingURL=modifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modifiers.js","sourceRoot":"","sources":["../../src/rules/modifiers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RuleCheckResult } from '../types.js';
2
+ export declare function checkNoAny(source: string, filePath: string): RuleCheckResult;
3
+ //# sourceMappingURL=no-any.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-any.d.ts","sourceRoot":"","sources":["../../src/rules/no-any.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAsG5E"}
@@ -0,0 +1,138 @@
1
+ export function checkNoAny(source, filePath) {
2
+ const violations = [];
3
+ const lines = source.split('\n');
4
+ for (let i = 0; i < lines.length; i++) {
5
+ const line = lines[i];
6
+ const trimmed = line.trim();
7
+ if (trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('/*'))
8
+ continue;
9
+ const anyTypeRegex = /:\s*any\b/g;
10
+ let match;
11
+ while ((match = anyTypeRegex.exec(line)) !== null) {
12
+ const col = match.index;
13
+ const beforeColon = line.slice(0, col).trim();
14
+ const suggestion = suggestTypeForAny(beforeColon, line, lines, i);
15
+ const fix = generateFix(beforeColon, suggestion);
16
+ violations.push({
17
+ rule: 'no-any',
18
+ severity: 'error',
19
+ line: i + 1,
20
+ column: col + 1,
21
+ current: match[0].trim(),
22
+ suggestion,
23
+ fix,
24
+ why: "Using 'any' disables TypeScript's type checking entirely. This defeats the purpose of TypeScript and allows bugs to pass silently.",
25
+ });
26
+ }
27
+ const asAnyRegex = /\bas\s+any\b/g;
28
+ while ((match = asAnyRegex.exec(line)) !== null) {
29
+ violations.push({
30
+ rule: 'no-any',
31
+ severity: 'error',
32
+ line: i + 1,
33
+ column: match.index + 1,
34
+ current: 'as any',
35
+ suggestion: 'Use a proper type assertion or type guard instead',
36
+ fix: '// Replace with proper type: as SpecificType, or use type guard',
37
+ why: "'as any' is a type safety escape hatch that hides potential runtime errors.",
38
+ });
39
+ }
40
+ const anyArrayRegex = /(?:unknown\[\]|any\[\])/g;
41
+ while ((match = anyArrayRegex.exec(line)) !== null) {
42
+ violations.push({
43
+ rule: 'no-any',
44
+ severity: 'error',
45
+ line: i + 1,
46
+ column: match.index + 1,
47
+ current: match[0],
48
+ suggestion: 'Use Array<SpecificType> or SpecificType[]',
49
+ fix: '// Replace with proper type: unknown[] for truly unknown, or SpecificType[]',
50
+ why: "unknown[] allows any value in the array, losing all type safety for collection operations.",
51
+ });
52
+ }
53
+ const promiseAnyRegex = /Promise<unknown>/g;
54
+ while ((match = promiseAnyRegex.exec(line)) !== null) {
55
+ violations.push({
56
+ rule: 'no-any',
57
+ severity: 'error',
58
+ line: i + 1,
59
+ column: match.index + 1,
60
+ current: 'Promise<unknown>',
61
+ suggestion: 'Use Promise<SpecificType> or Promise<unknown>',
62
+ fix: '// Replace with Promise<unknown> if truly unknown, or specific type',
63
+ why: "Promise<unknown> loses type information for async operations. Use Promise<unknown> as a safer alternative.",
64
+ });
65
+ }
66
+ const recordAnyRegex = /Record<string,\s*any>/g;
67
+ while ((match = recordAnyRegex.exec(line)) !== null) {
68
+ violations.push({
69
+ rule: 'no-any',
70
+ severity: 'warning',
71
+ line: i + 1,
72
+ column: match.index + 1,
73
+ current: 'Record<string, unknown>',
74
+ suggestion: 'Use Record<string, unknown> or define a specific interface',
75
+ fix: '// Replace with Record<string, unknown> or a typed interface',
76
+ why: "Record<string, unknown> allows any value type. Use unknown for safer type narrowing, or define specific types.",
77
+ });
78
+ }
79
+ const genericAnyRegex = /<any[,\s>]/g;
80
+ while ((match = genericAnyRegex.exec(line)) !== null) {
81
+ violations.push({
82
+ rule: 'no-any',
83
+ severity: 'error',
84
+ line: i + 1,
85
+ column: match.index + 1,
86
+ current: match[0].trim(),
87
+ suggestion: 'Use unknown or a specific type parameter',
88
+ fix: '// Replace <any> with <unknown> or a specific type',
89
+ why: "Generic 'any' disables type checking for the generic parameter. Use unknown as a safer alternative.",
90
+ });
91
+ }
92
+ }
93
+ return { violations };
94
+ }
95
+ function suggestTypeForAny(beforeColon, fullLine, allLines, lineIdx) {
96
+ const context = beforeColon.toLowerCase();
97
+ if (context.includes('args') || context.includes('params') || context.includes('options')) {
98
+ return 'Define a specific interface for the parameters';
99
+ }
100
+ if (context.includes('error') || context.includes('err')) {
101
+ return 'Error | unknown';
102
+ }
103
+ if (context.includes('event') || context.includes('e)')) {
104
+ return 'Event | React.SyntheticEvent';
105
+ }
106
+ if (context.includes('callback') || context.includes('handler') || context.includes('fn')) {
107
+ return '(...args: unknown[]) => unknown';
108
+ }
109
+ if (context.includes('result') || context.includes('response') || context.includes('data')) {
110
+ return 'Define a specific type for the response';
111
+ }
112
+ if (context.includes('config') || context.includes('options')) {
113
+ return 'Define a specific config interface';
114
+ }
115
+ if (context.includes('props')) {
116
+ return 'Define a Props interface';
117
+ }
118
+ if (context.includes('ref')) {
119
+ return 'React.RefObject<SpecificElement>';
120
+ }
121
+ if (context.includes('children')) {
122
+ return 'React.ReactNode';
123
+ }
124
+ if (context.includes('const ') || context.includes('let ')) {
125
+ return 'Infer from assignment or define explicit type';
126
+ }
127
+ if (fullLine.includes('): unknown') || fullLine.includes('): any')) {
128
+ return 'Define specific return type';
129
+ }
130
+ return 'unknown (safer than any, requires type narrowing)';
131
+ }
132
+ function generateFix(beforeColon, suggestion) {
133
+ if (suggestion.includes('Define') || suggestion.includes('Infer')) {
134
+ return `// ${suggestion}`;
135
+ }
136
+ return `// Replace 'any' with '${suggestion}'`;
137
+ }
138
+ //# sourceMappingURL=no-any.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-any.js","sourceRoot":"","sources":["../../src/rules/no-any.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { RuleCheckResult } from '../types.js';
2
+ export declare function checkTypeGuards(source: string, filePath: string): RuleCheckResult;
3
+ //# sourceMappingURL=type-guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-guards.d.ts","sourceRoot":"","sources":["../../src/rules/type-guards.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9D,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CA+KjF"}