mcp-react-toolkit 1.0.0 → 1.2.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 (235) hide show
  1. package/README.md +146 -42
  2. package/package.json +13 -5
  3. package/server.json +20 -0
  4. package/tools/accessibility-checker/build/index.js +9 -5
  5. package/tools/accessibility-checker/build/index.js.map +1 -1
  6. package/tools/accessibility-checker/build/rules.d.ts.map +1 -1
  7. package/tools/accessibility-checker/build/rules.js +325 -94
  8. package/tools/accessibility-checker/build/rules.js.map +1 -1
  9. package/tools/code-modernizer/build/tools/01-convert-to-typescript.d.ts.map +1 -1
  10. package/tools/code-modernizer/build/tools/01-convert-to-typescript.js +65 -50
  11. package/tools/code-modernizer/build/tools/01-convert-to-typescript.js.map +1 -1
  12. package/tools/code-modernizer/build/types.d.ts +1 -0
  13. package/tools/code-modernizer/build/types.d.ts.map +1 -1
  14. package/tools/code-modernizer/build/utils/ast-parser.d.ts.map +1 -1
  15. package/tools/code-modernizer/build/utils/ast-parser.js +30 -14
  16. package/tools/code-modernizer/build/utils/ast-parser.js.map +1 -1
  17. package/tools/code-modernizer/build/utils/type-generator.d.ts +1 -1
  18. package/tools/code-modernizer/build/utils/type-generator.d.ts.map +1 -1
  19. package/tools/code-modernizer/build/utils/type-generator.js +72 -23
  20. package/tools/code-modernizer/build/utils/type-generator.js.map +1 -1
  21. package/tools/component-factory/build/index.js +59 -7
  22. package/tools/component-factory/build/index.js.map +1 -1
  23. package/tools/component-fixer/README.md +44 -0
  24. package/tools/component-fixer/build/index.d.ts +3 -0
  25. package/tools/component-fixer/build/index.d.ts.map +1 -0
  26. package/tools/component-fixer/build/index.js +647 -0
  27. package/tools/component-fixer/build/index.js.map +1 -0
  28. package/tools/component-fixer/build/index.test.d.ts +2 -0
  29. package/tools/component-fixer/build/index.test.d.ts.map +1 -0
  30. package/tools/component-fixer/build/index.test.js.map +1 -0
  31. package/tools/component-fixer/package.json +20 -0
  32. package/tools/component-reviewer/README.md +54 -0
  33. package/tools/component-reviewer/build/index.d.ts +39 -0
  34. package/tools/component-reviewer/build/index.d.ts.map +1 -0
  35. package/tools/component-reviewer/build/index.js +946 -0
  36. package/tools/component-reviewer/build/index.js.map +1 -0
  37. package/tools/component-reviewer/build/index.test.d.ts +2 -0
  38. package/tools/component-reviewer/build/index.test.d.ts.map +1 -0
  39. package/tools/component-reviewer/build/index.test.js.map +1 -0
  40. package/tools/component-reviewer/package.json +20 -0
  41. package/tools/dep-auditor/build/index.d.ts +1 -0
  42. package/tools/dep-auditor/build/index.d.ts.map +1 -1
  43. package/tools/dep-auditor/build/index.js +71 -16
  44. package/tools/dep-auditor/build/index.js.map +1 -1
  45. package/tools/generate-tests/build/analyzer.d.ts +14 -0
  46. package/tools/generate-tests/build/analyzer.d.ts.map +1 -1
  47. package/tools/generate-tests/build/analyzer.js +96 -42
  48. package/tools/generate-tests/build/analyzer.js.map +1 -1
  49. package/tools/generate-tests/build/generators.d.ts.map +1 -1
  50. package/tools/generate-tests/build/generators.js +304 -79
  51. package/tools/generate-tests/build/generators.js.map +1 -1
  52. package/tools/generate-tests/build/index.js +29 -10
  53. package/tools/generate-tests/build/index.js.map +1 -1
  54. package/tools/json-viewer/build/index.js +29 -6
  55. package/tools/json-viewer/build/index.js.map +1 -1
  56. package/tools/legacy-analyzer/README.md +66 -0
  57. package/tools/legacy-analyzer/build/index.d.ts +3 -0
  58. package/tools/legacy-analyzer/build/index.d.ts.map +1 -0
  59. package/tools/legacy-analyzer/build/index.js +209 -0
  60. package/tools/legacy-analyzer/build/index.js.map +1 -0
  61. package/tools/legacy-analyzer/build/index.test.d.ts +2 -0
  62. package/tools/legacy-analyzer/build/index.test.d.ts.map +1 -0
  63. package/tools/legacy-analyzer/build/index.test.js.map +1 -0
  64. package/tools/legacy-analyzer/build/tools/01-detect-project-tech.d.ts +3 -0
  65. package/tools/legacy-analyzer/build/tools/01-detect-project-tech.d.ts.map +1 -0
  66. package/tools/legacy-analyzer/build/tools/01-detect-project-tech.js +115 -0
  67. package/tools/legacy-analyzer/build/tools/01-detect-project-tech.js.map +1 -0
  68. package/tools/legacy-analyzer/build/tools/02-analyze-folder-structure.d.ts +3 -0
  69. package/tools/legacy-analyzer/build/tools/02-analyze-folder-structure.d.ts.map +1 -0
  70. package/tools/legacy-analyzer/build/tools/02-analyze-folder-structure.js +85 -0
  71. package/tools/legacy-analyzer/build/tools/02-analyze-folder-structure.js.map +1 -0
  72. package/tools/legacy-analyzer/build/tools/03-analyze-components.d.ts +3 -0
  73. package/tools/legacy-analyzer/build/tools/03-analyze-components.d.ts.map +1 -0
  74. package/tools/legacy-analyzer/build/tools/03-analyze-components.js +87 -0
  75. package/tools/legacy-analyzer/build/tools/03-analyze-components.js.map +1 -0
  76. package/tools/legacy-analyzer/build/tools/04-analyze-state-management.d.ts +3 -0
  77. package/tools/legacy-analyzer/build/tools/04-analyze-state-management.d.ts.map +1 -0
  78. package/tools/legacy-analyzer/build/tools/04-analyze-state-management.js +133 -0
  79. package/tools/legacy-analyzer/build/tools/04-analyze-state-management.js.map +1 -0
  80. package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.d.ts +3 -0
  81. package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.d.ts.map +1 -0
  82. package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.js +160 -0
  83. package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.js.map +1 -0
  84. package/tools/legacy-analyzer/build/tools/06-analyze-routing.d.ts +3 -0
  85. package/tools/legacy-analyzer/build/tools/06-analyze-routing.d.ts.map +1 -0
  86. package/tools/legacy-analyzer/build/tools/06-analyze-routing.js +150 -0
  87. package/tools/legacy-analyzer/build/tools/06-analyze-routing.js.map +1 -0
  88. package/tools/legacy-analyzer/build/tools/07-analyze-styling.d.ts +3 -0
  89. package/tools/legacy-analyzer/build/tools/07-analyze-styling.d.ts.map +1 -0
  90. package/tools/legacy-analyzer/build/tools/07-analyze-styling.js +131 -0
  91. package/tools/legacy-analyzer/build/tools/07-analyze-styling.js.map +1 -0
  92. package/tools/legacy-analyzer/build/tools/08-analyze-assets.d.ts +3 -0
  93. package/tools/legacy-analyzer/build/tools/08-analyze-assets.d.ts.map +1 -0
  94. package/tools/legacy-analyzer/build/tools/08-analyze-assets.js +85 -0
  95. package/tools/legacy-analyzer/build/tools/08-analyze-assets.js.map +1 -0
  96. package/tools/legacy-analyzer/build/tools/09-detect-anti-patterns.d.ts +3 -0
  97. package/tools/legacy-analyzer/build/tools/09-detect-anti-patterns.d.ts.map +1 -0
  98. package/tools/legacy-analyzer/build/tools/09-detect-anti-patterns.js +329 -0
  99. package/tools/legacy-analyzer/build/tools/09-detect-anti-patterns.js.map +1 -0
  100. package/tools/legacy-analyzer/build/tools/10-detect-duplication.d.ts +3 -0
  101. package/tools/legacy-analyzer/build/tools/10-detect-duplication.d.ts.map +1 -0
  102. package/tools/legacy-analyzer/build/tools/10-detect-duplication.js +192 -0
  103. package/tools/legacy-analyzer/build/tools/10-detect-duplication.js.map +1 -0
  104. package/tools/legacy-analyzer/build/tools/11-analyze-dependencies-usage.d.ts +3 -0
  105. package/tools/legacy-analyzer/build/tools/11-analyze-dependencies-usage.d.ts.map +1 -0
  106. package/tools/legacy-analyzer/build/tools/11-analyze-dependencies-usage.js +232 -0
  107. package/tools/legacy-analyzer/build/tools/11-analyze-dependencies-usage.js.map +1 -0
  108. package/tools/legacy-analyzer/build/tools/12-analyze-legacy-app.d.ts +3 -0
  109. package/tools/legacy-analyzer/build/tools/12-analyze-legacy-app.d.ts.map +1 -0
  110. package/tools/legacy-analyzer/build/tools/12-analyze-legacy-app.js +247 -0
  111. package/tools/legacy-analyzer/build/tools/12-analyze-legacy-app.js.map +1 -0
  112. package/tools/legacy-analyzer/build/tools/13-detect-features.d.ts +3 -0
  113. package/tools/legacy-analyzer/build/tools/13-detect-features.d.ts.map +1 -0
  114. package/tools/legacy-analyzer/build/tools/13-detect-features.js +141 -0
  115. package/tools/legacy-analyzer/build/tools/13-detect-features.js.map +1 -0
  116. package/tools/legacy-analyzer/build/tools/14-classify-files.d.ts +3 -0
  117. package/tools/legacy-analyzer/build/tools/14-classify-files.d.ts.map +1 -0
  118. package/tools/legacy-analyzer/build/tools/14-classify-files.js +76 -0
  119. package/tools/legacy-analyzer/build/tools/14-classify-files.js.map +1 -0
  120. package/tools/legacy-analyzer/build/tools/15-detect-shared-modules.d.ts +3 -0
  121. package/tools/legacy-analyzer/build/tools/15-detect-shared-modules.d.ts.map +1 -0
  122. package/tools/legacy-analyzer/build/tools/15-detect-shared-modules.js +70 -0
  123. package/tools/legacy-analyzer/build/tools/15-detect-shared-modules.js.map +1 -0
  124. package/tools/legacy-analyzer/build/tools/16-design-target-structure.d.ts +3 -0
  125. package/tools/legacy-analyzer/build/tools/16-design-target-structure.d.ts.map +1 -0
  126. package/tools/legacy-analyzer/build/tools/16-design-target-structure.js +26 -0
  127. package/tools/legacy-analyzer/build/tools/16-design-target-structure.js.map +1 -0
  128. package/tools/legacy-analyzer/build/tools/17-map-files-to-target.d.ts +3 -0
  129. package/tools/legacy-analyzer/build/tools/17-map-files-to-target.d.ts.map +1 -0
  130. package/tools/legacy-analyzer/build/tools/17-map-files-to-target.js +108 -0
  131. package/tools/legacy-analyzer/build/tools/17-map-files-to-target.js.map +1 -0
  132. package/tools/legacy-analyzer/build/tools/18-detect-boundary-violations.d.ts +3 -0
  133. package/tools/legacy-analyzer/build/tools/18-detect-boundary-violations.d.ts.map +1 -0
  134. package/tools/legacy-analyzer/build/tools/18-detect-boundary-violations.js +137 -0
  135. package/tools/legacy-analyzer/build/tools/18-detect-boundary-violations.js.map +1 -0
  136. package/tools/legacy-analyzer/build/tools/19-suggest-module-splitting.d.ts +3 -0
  137. package/tools/legacy-analyzer/build/tools/19-suggest-module-splitting.d.ts.map +1 -0
  138. package/tools/legacy-analyzer/build/tools/19-suggest-module-splitting.js +160 -0
  139. package/tools/legacy-analyzer/build/tools/19-suggest-module-splitting.js.map +1 -0
  140. package/tools/legacy-analyzer/build/tools/20-naming-standardizer.d.ts +3 -0
  141. package/tools/legacy-analyzer/build/tools/20-naming-standardizer.d.ts.map +1 -0
  142. package/tools/legacy-analyzer/build/tools/20-naming-standardizer.js +162 -0
  143. package/tools/legacy-analyzer/build/tools/20-naming-standardizer.js.map +1 -0
  144. package/tools/legacy-analyzer/build/tools/21-generate-refactor-plan.d.ts +3 -0
  145. package/tools/legacy-analyzer/build/tools/21-generate-refactor-plan.d.ts.map +1 -0
  146. package/tools/legacy-analyzer/build/tools/21-generate-refactor-plan.js +108 -0
  147. package/tools/legacy-analyzer/build/tools/21-generate-refactor-plan.js.map +1 -0
  148. package/tools/legacy-analyzer/build/tools/22-refactor-folder-structure.d.ts +3 -0
  149. package/tools/legacy-analyzer/build/tools/22-refactor-folder-structure.d.ts.map +1 -0
  150. package/tools/legacy-analyzer/build/tools/22-refactor-folder-structure.js +98 -0
  151. package/tools/legacy-analyzer/build/tools/22-refactor-folder-structure.js.map +1 -0
  152. package/tools/legacy-analyzer/build/types.d.ts +413 -0
  153. package/tools/legacy-analyzer/build/types.d.ts.map +1 -0
  154. package/tools/legacy-analyzer/build/types.js +12 -0
  155. package/tools/legacy-analyzer/build/types.js.map +1 -0
  156. package/tools/legacy-analyzer/build/utils/ast-parser.d.ts +34 -0
  157. package/tools/legacy-analyzer/build/utils/ast-parser.d.ts.map +1 -0
  158. package/tools/legacy-analyzer/build/utils/ast-parser.js +394 -0
  159. package/tools/legacy-analyzer/build/utils/ast-parser.js.map +1 -0
  160. package/tools/legacy-analyzer/build/utils/file-scanner.d.ts +51 -0
  161. package/tools/legacy-analyzer/build/utils/file-scanner.d.ts.map +1 -0
  162. package/tools/legacy-analyzer/build/utils/file-scanner.js +174 -0
  163. package/tools/legacy-analyzer/build/utils/file-scanner.js.map +1 -0
  164. package/tools/legacy-analyzer/build/utils/import-tracker.d.ts +38 -0
  165. package/tools/legacy-analyzer/build/utils/import-tracker.d.ts.map +1 -0
  166. package/tools/legacy-analyzer/build/utils/import-tracker.js +194 -0
  167. package/tools/legacy-analyzer/build/utils/import-tracker.js.map +1 -0
  168. package/tools/legacy-analyzer/build/utils/refactor-helpers.d.ts +88 -0
  169. package/tools/legacy-analyzer/build/utils/refactor-helpers.d.ts.map +1 -0
  170. package/tools/legacy-analyzer/build/utils/refactor-helpers.js +538 -0
  171. package/tools/legacy-analyzer/build/utils/refactor-helpers.js.map +1 -0
  172. package/tools/legacy-analyzer/package.json +20 -0
  173. package/tools/lighthouse-runner/README.md +45 -0
  174. package/tools/lighthouse-runner/build/index.d.ts +6 -0
  175. package/tools/lighthouse-runner/build/index.d.ts.map +1 -0
  176. package/tools/lighthouse-runner/build/index.js +295 -0
  177. package/tools/lighthouse-runner/build/index.js.map +1 -0
  178. package/tools/lighthouse-runner/build/index.test.d.ts +2 -0
  179. package/tools/lighthouse-runner/build/index.test.d.ts.map +1 -0
  180. package/tools/lighthouse-runner/build/index.test.js.map +1 -0
  181. package/tools/lighthouse-runner/package.json +20 -0
  182. package/tools/monorepo-manager/build/utils.d.ts.map +1 -1
  183. package/tools/monorepo-manager/build/utils.js +12 -9
  184. package/tools/monorepo-manager/build/utils.js.map +1 -1
  185. package/tools/performance-audit/README.md +37 -0
  186. package/tools/performance-audit/build/index.d.ts +13 -0
  187. package/tools/performance-audit/build/index.d.ts.map +1 -0
  188. package/tools/performance-audit/build/index.js +311 -0
  189. package/tools/performance-audit/build/index.js.map +1 -0
  190. package/tools/performance-audit/build/index.test.d.ts +2 -0
  191. package/tools/performance-audit/build/index.test.d.ts.map +1 -0
  192. package/tools/performance-audit/build/index.test.js.map +1 -0
  193. package/tools/performance-audit/package.json +20 -0
  194. package/tools/quality-pipeline/build/index.js +55 -15
  195. package/tools/quality-pipeline/build/index.js.map +1 -1
  196. package/tools/render-analyzer/README.md +43 -0
  197. package/tools/render-analyzer/build/index.d.ts +25 -0
  198. package/tools/render-analyzer/build/index.d.ts.map +1 -0
  199. package/tools/render-analyzer/build/index.js +342 -0
  200. package/tools/render-analyzer/build/index.js.map +1 -0
  201. package/tools/render-analyzer/build/index.test.d.ts +2 -0
  202. package/tools/render-analyzer/build/index.test.d.ts.map +1 -0
  203. package/tools/render-analyzer/build/index.test.js.map +1 -0
  204. package/tools/render-analyzer/package.json +20 -0
  205. package/tools/shared/build/fs.d.ts +8 -0
  206. package/tools/shared/build/fs.d.ts.map +1 -0
  207. package/tools/shared/build/fs.js +45 -0
  208. package/tools/shared/build/fs.js.map +1 -0
  209. package/tools/shared/build/index.d.ts +1 -0
  210. package/tools/shared/build/index.d.ts.map +1 -1
  211. package/tools/shared/build/index.js +1 -0
  212. package/tools/shared/build/index.js.map +1 -1
  213. package/tools/storybook-generator/README.md +39 -0
  214. package/tools/storybook-generator/build/index.d.ts +13 -0
  215. package/tools/storybook-generator/build/index.d.ts.map +1 -0
  216. package/tools/storybook-generator/build/index.js +478 -0
  217. package/tools/storybook-generator/build/index.js.map +1 -0
  218. package/tools/storybook-generator/build/index.test.d.ts +2 -0
  219. package/tools/storybook-generator/build/index.test.d.ts.map +1 -0
  220. package/tools/storybook-generator/build/index.test.js.map +1 -0
  221. package/tools/storybook-generator/package.json +20 -0
  222. package/tools/test-gap-analyzer/README.md +41 -0
  223. package/tools/test-gap-analyzer/build/index.d.ts +20 -0
  224. package/tools/test-gap-analyzer/build/index.d.ts.map +1 -0
  225. package/tools/test-gap-analyzer/build/index.js +371 -0
  226. package/tools/test-gap-analyzer/build/index.js.map +1 -0
  227. package/tools/test-gap-analyzer/build/index.test.d.ts +2 -0
  228. package/tools/test-gap-analyzer/build/index.test.d.ts.map +1 -0
  229. package/tools/test-gap-analyzer/build/index.test.js.map +1 -0
  230. package/tools/test-gap-analyzer/package.json +20 -0
  231. package/tools/typescript-enforcer/build/scanner.d.ts.map +1 -1
  232. package/tools/typescript-enforcer/build/scanner.js +13 -1
  233. package/tools/typescript-enforcer/build/scanner.js.map +1 -1
  234. package/tools/typescript-enforcer/build/types.d.ts +1 -0
  235. package/tools/typescript-enforcer/build/types.d.ts.map +1 -1
@@ -0,0 +1,150 @@
1
+ // ============================================================================
2
+ // TOOL #6: analyze-routing
3
+ // Detects routing: react-router, Next.js file-based (pages/ and app/), Remix, Gatsby
4
+ // ============================================================================
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import { findSourceFiles, readFileContent } from '../utils/file-scanner.js';
8
+ import { parseFile, extractImports, extractJSX } from '../utils/ast-parser.js';
9
+ const ROUTING_LIBRARIES = ['react-router-dom', 'react-router', '@reach/router', 'wouter', 'preact-router', '@remix-run/react'];
10
+ export async function analyzeRouting(appPath, config) {
11
+ // Detect Next.js / Remix file-based routing before doing source file scan
12
+ const nextPagesDir = path.join(appPath, 'pages');
13
+ const nextAppDir = path.join(appPath, 'app');
14
+ const srcPagesDir = path.join(appPath, 'src', 'pages');
15
+ const srcAppDir = path.join(appPath, 'src', 'app');
16
+ const hasNextPages = fs.existsSync(nextPagesDir) || fs.existsSync(srcPagesDir);
17
+ const hasNextApp = fs.existsSync(nextAppDir) || fs.existsSync(srcAppDir);
18
+ if (hasNextPages || hasNextApp) {
19
+ const routerType = hasNextApp ? 'app-router' : 'pages-router';
20
+ const lib = hasNextApp ? 'next/navigation' : 'next/router';
21
+ const routeDir = hasNextApp
22
+ ? (fs.existsSync(nextAppDir) ? nextAppDir : srcAppDir)
23
+ : (fs.existsSync(nextPagesDir) ? nextPagesDir : srcPagesDir);
24
+ // Count page files (each file = one route in Next.js)
25
+ let routeCount = 0;
26
+ const countPages = (dir) => {
27
+ if (!fs.existsSync(dir))
28
+ return;
29
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
30
+ if (entry.isDirectory())
31
+ countPages(path.join(dir, entry.name));
32
+ else if (entry.name.match(/\.(tsx|ts|jsx|js)$/) && !entry.name.startsWith('_') && !entry.name.includes('.test.') && entry.name !== 'layout.tsx' && entry.name !== 'loading.tsx') {
33
+ routeCount++;
34
+ }
35
+ }
36
+ };
37
+ countPages(routeDir);
38
+ const issues = [];
39
+ if (routeCount > 20) {
40
+ issues.push(`${routeCount} route files. Consider using Next.js Route Groups to organize routes.`);
41
+ }
42
+ return {
43
+ routingLibrary: lib,
44
+ routingType: 'nested',
45
+ lazyLoading: true, // Next.js does automatic code splitting per page
46
+ routeCount,
47
+ issues,
48
+ };
49
+ }
50
+ const srcPath = path.join(appPath, 'src');
51
+ const files = await findSourceFiles(srcPath);
52
+ let routingLibrary = null;
53
+ let routeCount = 0;
54
+ let hasNestedRoutes = false;
55
+ let hasLazyLoading = false;
56
+ const issues = [];
57
+ const routeFiles = [];
58
+ for (const file of files) {
59
+ const content = readFileContent(file);
60
+ if (!content)
61
+ continue;
62
+ // Content-based routing library detection (works for .js files too)
63
+ for (const lib of ROUTING_LIBRARIES) {
64
+ if (content.includes(`from '${lib}'`) || content.includes(`from "${lib}"`) ||
65
+ content.includes(`require('${lib}')`) || content.includes(`require("${lib}")`)) {
66
+ routingLibrary = lib;
67
+ routeFiles.push(path.relative(appPath, file));
68
+ break;
69
+ }
70
+ }
71
+ // Content-based route counting via regex (reliable for both JS and TS)
72
+ const routeTagMatches = content.match(/<Route[\s/]/g) || [];
73
+ routeCount += routeTagMatches.length;
74
+ // Detect nested routes via content
75
+ if (content.includes('<Route') || content.includes('<route')) {
76
+ // Nested: Route inside Switch inside another Route, or Routes v6 pattern
77
+ if (content.includes('<Routes>') || (content.match(/<Route[\s\S]*?<Route/m))) {
78
+ hasNestedRoutes = true;
79
+ }
80
+ }
81
+ // Detect lazy loading
82
+ if (content.includes('React.lazy') || content.includes('lazy(') || content.includes('Suspense')) {
83
+ hasLazyLoading = true;
84
+ }
85
+ // Detect dynamic imports for routes
86
+ if (content.includes('import(') && (content.includes('Route') || content.includes('route'))) {
87
+ hasLazyLoading = true;
88
+ }
89
+ // Also try AST-based extraction for richer data (optional)
90
+ const parsed = parseFile(file);
91
+ if (parsed) {
92
+ const imports = extractImports(parsed.ast);
93
+ const importSources = imports.map((i) => i.source);
94
+ for (const lib of ROUTING_LIBRARIES) {
95
+ if (importSources.some((s) => s.includes(lib))) {
96
+ routingLibrary = lib;
97
+ }
98
+ }
99
+ // AST-based nested route detection via depth
100
+ const jsxElements = extractJSX(parsed.ast);
101
+ const routeAtDepth = jsxElements.filter((e) => (e.tagName === 'Route' || e.tagName === 'route') && e.depth > 2);
102
+ if (routeAtDepth.length > 0) {
103
+ hasNestedRoutes = true;
104
+ }
105
+ }
106
+ }
107
+ // Determine routing type
108
+ let routingType;
109
+ if (!routingLibrary || routeCount === 0) {
110
+ routingType = 'none';
111
+ }
112
+ else if (hasNestedRoutes) {
113
+ routingType = 'nested';
114
+ }
115
+ else {
116
+ routingType = 'flat';
117
+ }
118
+ // Issues
119
+ if (!routingLibrary && files.length > 5) {
120
+ issues.push('No routing library detected. App may be using custom routing or is a single-page view.');
121
+ }
122
+ if (routingLibrary && !hasLazyLoading && routeCount > 10) {
123
+ issues.push(`${routeCount} routes without lazy loading. Consider using React.lazy() for code splitting.`);
124
+ }
125
+ if (routingType === 'flat' && routeCount > 15) {
126
+ issues.push('Many flat routes detected. Consider organizing routes into nested groups.');
127
+ }
128
+ // Check for hardcoded route strings in components
129
+ let hardcodedRoutes = 0;
130
+ for (const file of files) {
131
+ const content = readFileContent(file);
132
+ if (!content)
133
+ continue;
134
+ // Look for navigate() calls or href patterns
135
+ const navMatches = content.match(/navigate\s*\(\s*['"`]\/[^'"`]*['"`]\)/g) || [];
136
+ const hrefMatches = content.match(/href\s*=\s*['"`]\/[^'"`]*['"`]/g) || [];
137
+ hardcodedRoutes += navMatches.length + hrefMatches.length;
138
+ }
139
+ if (hardcodedRoutes > 5) {
140
+ issues.push(`${hardcodedRoutes} hardcoded route strings found. Consider using route constants.`);
141
+ }
142
+ return {
143
+ routingLibrary,
144
+ routingType,
145
+ lazyLoading: hasLazyLoading,
146
+ routeCount,
147
+ issues,
148
+ };
149
+ }
150
+ //# sourceMappingURL=06-analyze-routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"06-analyze-routing.js","sourceRoot":"","sources":["../../src/tools/06-analyze-routing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AnalyzeStylingOutput, AnalyzerConfig } from '../types.js';
2
+ export declare function analyzeStyling(appPath: string, config?: Partial<AnalyzerConfig>): Promise<AnalyzeStylingOutput>;
3
+ //# sourceMappingURL=07-analyze-styling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"07-analyze-styling.d.ts","sourceRoot":"","sources":["../../src/tools/07-analyze-styling.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAiBxE,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAqHrH"}
@@ -0,0 +1,131 @@
1
+ // ============================================================================
2
+ // TOOL #7: analyze-styling
3
+ // Detects CSS/SCSS/Tailwind/styled-components, inline styles, hardcoded values
4
+ // ============================================================================
5
+ import { findSourceFiles, readFileContent, findStyleFiles, resolveSourceDir } from '../utils/file-scanner.js';
6
+ import { parseFile, extractImports } from '../utils/ast-parser.js';
7
+ const HEX_COLOR_REGEX = /#[0-9a-fA-F]{3,8}\b/g;
8
+ const RGB_REGEX = /rgba?\s*\([^)]+\)/g;
9
+ const INLINE_STYLE_REGEX = /style\s*=\s*\{\{/g;
10
+ const CLASSNAME_REGEX = /className\s*=\s*[{"'`]/g;
11
+ const STYLING_LIBS = [
12
+ 'styled-components',
13
+ '@emotion/react',
14
+ '@emotion/styled',
15
+ 'tailwindcss',
16
+ '@stitches/react',
17
+ 'linaria',
18
+ 'twin.macro',
19
+ ];
20
+ export async function analyzeStyling(appPath, config) {
21
+ const srcPath = resolveSourceDir(appPath);
22
+ const files = await findSourceFiles(srcPath);
23
+ const styleFiles = await findStyleFiles(appPath);
24
+ const stylingType = new Set();
25
+ const issues = [];
26
+ let inlineStylesCount = 0;
27
+ const hardcodedColors = new Set();
28
+ const classNameCounts = new Map();
29
+ // Check for CSS/SCSS files
30
+ if (styleFiles.length > 0) {
31
+ const hasCSS = styleFiles.some((f) => f.endsWith('.css'));
32
+ const hasSCSS = styleFiles.some((f) => f.endsWith('.scss') || f.endsWith('.sass') || f.endsWith('.less'));
33
+ const hasModules = styleFiles.some((f) => f.includes('.module.'));
34
+ if (hasCSS)
35
+ stylingType.add('CSS');
36
+ if (hasSCSS)
37
+ stylingType.add('SCSS/Less');
38
+ if (hasModules)
39
+ stylingType.add('CSS Modules');
40
+ }
41
+ // Analyze source files for styling patterns
42
+ for (const file of files) {
43
+ const content = readFileContent(file);
44
+ if (!content)
45
+ continue;
46
+ const parsed = parseFile(file);
47
+ if (!parsed)
48
+ continue;
49
+ const imports = extractImports(parsed.ast);
50
+ const importSources = imports.map((i) => i.source);
51
+ // Detect styling libraries
52
+ for (const lib of STYLING_LIBS) {
53
+ if (importSources.some((s) => s.includes(lib))) {
54
+ if (lib.includes('styled'))
55
+ stylingType.add('styled-components');
56
+ else if (lib.includes('emotion'))
57
+ stylingType.add('Emotion');
58
+ else if (lib.includes('tailwind'))
59
+ stylingType.add('Tailwind');
60
+ else if (lib.includes('stitches'))
61
+ stylingType.add('Stitches');
62
+ else if (lib.includes('linaria'))
63
+ stylingType.add('Linaria');
64
+ else
65
+ stylingType.add(lib);
66
+ }
67
+ }
68
+ // Count inline styles
69
+ const inlineMatches = content.match(INLINE_STYLE_REGEX);
70
+ if (inlineMatches) {
71
+ inlineStylesCount += inlineMatches.length;
72
+ }
73
+ // Extract hardcoded colors
74
+ const hexMatches = content.match(HEX_COLOR_REGEX);
75
+ if (hexMatches) {
76
+ for (const color of hexMatches) {
77
+ hardcodedColors.add(color.toLowerCase());
78
+ }
79
+ }
80
+ const rgbMatches = content.match(RGB_REGEX);
81
+ if (rgbMatches) {
82
+ for (const color of rgbMatches) {
83
+ hardcodedColors.add(color);
84
+ }
85
+ }
86
+ // Count className usage for duplicate detection
87
+ const classNameMatches = content.match(/className\s*=\s*["'`]([^"'`]+)["'`]/g);
88
+ if (classNameMatches) {
89
+ for (const match of classNameMatches) {
90
+ const classes = match.replace(/className\s*=\s*["'`]/, '').replace(/["'`]$/, '');
91
+ const classList = classes.split(/\s+/);
92
+ for (const cls of classList) {
93
+ if (cls.trim()) {
94
+ classNameCounts.set(cls, (classNameCounts.get(cls) || 0) + 1);
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
100
+ // Find duplicate classes (used in many files)
101
+ const duplicateClasses = [];
102
+ for (const [cls, count] of classNameCounts) {
103
+ if (count > 10) {
104
+ duplicateClasses.push(cls);
105
+ }
106
+ }
107
+ // Issues
108
+ if (stylingType.size === 0) {
109
+ issues.push('No styling solution detected. May be using inline styles only or a custom solution.');
110
+ }
111
+ if (stylingType.size > 2) {
112
+ issues.push(`Multiple styling solutions detected (${Array.from(stylingType).join(', ')}). Consider standardizing.`);
113
+ }
114
+ if (inlineStylesCount > 20) {
115
+ issues.push(`High inline styles usage (${inlineStylesCount} instances). Consider using CSS classes or styled-components.`);
116
+ }
117
+ if (hardcodedColors.size > 10) {
118
+ issues.push(`${hardcodedColors.size} hardcoded colors found. Consider using CSS variables or a theme system.`);
119
+ }
120
+ if (duplicateClasses.length > 0) {
121
+ issues.push(`Potential duplicate class definitions detected: ${duplicateClasses.slice(0, 5).join(', ')}${duplicateClasses.length > 5 ? '...' : ''}`);
122
+ }
123
+ return {
124
+ stylingType: Array.from(stylingType),
125
+ inlineStylesCount,
126
+ hardcodedColors: Array.from(hardcodedColors).slice(0, 20), // Limit output
127
+ duplicateClasses: duplicateClasses.slice(0, 10),
128
+ issues,
129
+ };
130
+ }
131
+ //# sourceMappingURL=07-analyze-styling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"07-analyze-styling.js","sourceRoot":"","sources":["../../src/tools/07-analyze-styling.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AnalyzeAssetsOutput, AnalyzerConfig } from '../types.js';
2
+ export declare function analyzeAssets(appPath: string, config?: Partial<AnalyzerConfig>): Promise<AnalyzeAssetsOutput>;
3
+ //# sourceMappingURL=08-analyze-assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"08-analyze-assets.d.ts","sourceRoot":"","sources":["../../src/tools/08-analyze-assets.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,mBAAmB,EAAa,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlF,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAkFnH"}
@@ -0,0 +1,85 @@
1
+ // ============================================================================
2
+ // TOOL #8: analyze-assets
3
+ // Detects large images/videos, assets inside src, unused assets
4
+ // ============================================================================
5
+ import * as path from 'path';
6
+ import { findAssetFiles, getFileSize, findSourceFiles, readFileContent } from '../utils/file-scanner.js';
7
+ import { DEFAULT_CONFIG } from '../types.js';
8
+ const IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico', '.bmp'];
9
+ const VIDEO_EXTENSIONS = ['.mp4', '.webm', '.ogg', '.avi', '.mov'];
10
+ export async function analyzeAssets(appPath, config) {
11
+ const mergedConfig = { ...DEFAULT_CONFIG, ...config };
12
+ const assetFiles = await findAssetFiles(appPath);
13
+ const sourceFiles = await findSourceFiles(appPath);
14
+ const largeAssets = [];
15
+ const assetIssues = [];
16
+ const referencedAssets = new Set();
17
+ // Analyze each asset
18
+ for (const asset of assetFiles) {
19
+ const sizeBytes = getFileSize(asset);
20
+ const sizeKB = sizeBytes / 1024;
21
+ const ext = path.extname(asset).toLowerCase();
22
+ const relPath = path.relative(appPath, asset);
23
+ let type = 'unknown';
24
+ if (IMAGE_EXTENSIONS.includes(ext))
25
+ type = 'image';
26
+ else if (VIDEO_EXTENSIONS.includes(ext))
27
+ type = 'video';
28
+ else
29
+ type = 'font';
30
+ // Check if large
31
+ if (type === 'image' && sizeKB > mergedConfig.largeAssetImageKB) {
32
+ largeAssets.push({ file: relPath, sizeKB: Math.round(sizeKB * 10) / 10, type });
33
+ }
34
+ else if (type === 'video' && sizeKB > mergedConfig.largeAssetVideoMB * 1024) {
35
+ largeAssets.push({ file: relPath, sizeKB: Math.round(sizeKB * 10) / 10, type });
36
+ }
37
+ }
38
+ // Check which assets are referenced in source files
39
+ for (const sourceFile of sourceFiles) {
40
+ const content = readFileContent(sourceFile);
41
+ if (!content)
42
+ continue;
43
+ for (const asset of assetFiles) {
44
+ const basename = path.basename(asset);
45
+ // Check if asset filename appears in source
46
+ if (content.includes(basename)) {
47
+ referencedAssets.add(asset);
48
+ }
49
+ }
50
+ }
51
+ // Find unused assets
52
+ const unusedAssets = [];
53
+ for (const asset of assetFiles) {
54
+ if (!referencedAssets.has(asset)) {
55
+ unusedAssets.push(path.relative(appPath, asset));
56
+ }
57
+ }
58
+ // Check for assets inside src/
59
+ const srcAssets = assetFiles.filter((f) => {
60
+ const rel = path.relative(appPath, f);
61
+ return rel.startsWith('src' + path.sep);
62
+ });
63
+ if (srcAssets.length > 0) {
64
+ assetIssues.push(`${srcAssets.length} assets found inside src/. Consider moving to public/ for better caching.`);
65
+ }
66
+ // Issues
67
+ if (largeAssets.length > 0) {
68
+ assetIssues.push(`${largeAssets.length} large assets detected. Consider optimizing or using CDN.`);
69
+ }
70
+ if (unusedAssets.length > 0) {
71
+ assetIssues.push(`${unusedAssets.length} potentially unused assets detected.`);
72
+ }
73
+ // Check for non-optimized formats
74
+ const pngAssets = assetFiles.filter((f) => f.endsWith('.png'));
75
+ if (pngAssets.length > 5) {
76
+ assetIssues.push(`${pngAssets.length} PNG files found. Consider converting to WebP for better performance.`);
77
+ }
78
+ return {
79
+ totalAssets: assetFiles.length,
80
+ largeAssets: largeAssets.sort((a, b) => b.sizeKB - a.sizeKB),
81
+ unusedAssets: unusedAssets.slice(0, 20), // Limit output
82
+ assetIssues,
83
+ };
84
+ }
85
+ //# sourceMappingURL=08-analyze-assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"08-analyze-assets.js","sourceRoot":"","sources":["../../src/tools/08-analyze-assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { DetectAntiPatternsOutput, AnalyzerConfig } from '../types.js';
2
+ export declare function detectAntiPatterns(appPath: string, config?: Partial<AnalyzerConfig>): Promise<DetectAntiPatternsOutput>;
3
+ //# sourceMappingURL=09-detect-anti-patterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"09-detect-anti-patterns.d.ts","sourceRoot":"","sources":["../../src/tools/09-detect-anti-patterns.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,wBAAwB,EAAe,cAAc,EAAE,MAAM,aAAa,CAAC;AAEzF,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAmU7H"}