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,85 @@
1
+ // ============================================================================
2
+ // TOOL #2: analyze-folder-structure
3
+ // Analyzes directory structure: flat vs feature-based, folder presence, depth
4
+ // ============================================================================
5
+ import * as path from 'path';
6
+ import { getDirectoriesAtDepth, calculateMaxDepth, findSourceFiles, resolveSourceDir } from '../utils/file-scanner.js';
7
+ const COMMON_FOLDERS = [
8
+ 'components', 'component', 'ui',
9
+ 'utils', 'util', 'helpers', 'helper',
10
+ 'services', 'service', 'api',
11
+ 'hooks', 'hook', 'custom-hooks',
12
+ 'pages', 'page', 'views', 'screens',
13
+ 'store', 'stores', 'redux', 'state',
14
+ 'assets', 'static', 'public',
15
+ 'styles', 'css', 'scss',
16
+ 'constants', 'config',
17
+ 'types', 'interfaces', 'models',
18
+ 'features', 'modules',
19
+ 'contexts', 'providers',
20
+ ];
21
+ export async function analyzeFolderStructure(appPath, config) {
22
+ const srcPath = resolveSourceDir(appPath);
23
+ const allDirs = getDirectoriesAtDepth(srcPath, 5);
24
+ // Get top-level directories in src/
25
+ const topLevelDirs = allDirs.filter((d) => !d.includes(path.sep));
26
+ const secondLevelDirs = allDirs.filter((d) => d.split(path.sep).length === 2);
27
+ // Detect which common folders exist
28
+ const folders = [];
29
+ const foundFolders = new Set();
30
+ for (const dir of allDirs) {
31
+ const parts = dir.split(path.sep);
32
+ for (const part of parts) {
33
+ const lower = part.toLowerCase();
34
+ if (COMMON_FOLDERS.includes(lower) && !foundFolders.has(lower)) {
35
+ foundFolders.add(lower);
36
+ folders.push(dir);
37
+ }
38
+ }
39
+ }
40
+ // Classify structure type
41
+ let structureType;
42
+ const hasFeatures = topLevelDirs.some((d) => ['features', 'modules', 'pages', 'screens', 'views'].includes(d.toLowerCase()));
43
+ const hasFlatStructure = topLevelDirs.some((d) => ['components', 'utils', 'services', 'hooks'].includes(d.toLowerCase()));
44
+ if (hasFeatures && hasFlatStructure) {
45
+ structureType = 'mixed';
46
+ }
47
+ else if (hasFeatures) {
48
+ structureType = 'feature-based';
49
+ }
50
+ else {
51
+ structureType = 'flat';
52
+ }
53
+ // Calculate depth
54
+ const maxDepth = calculateMaxDepth(srcPath);
55
+ // Detect issues
56
+ const issues = [];
57
+ if (maxDepth > 5) {
58
+ issues.push(`Deep nesting detected (${maxDepth} levels). Consider flattening the structure.`);
59
+ }
60
+ if (!foundFolders.has('components') && !foundFolders.has('component')) {
61
+ issues.push('No dedicated components folder found.');
62
+ }
63
+ if (!foundFolders.has('utils') && !foundFolders.has('util') && !foundFolders.has('helpers')) {
64
+ issues.push('No dedicated utils/helpers folder found. Utility code may be scattered.');
65
+ }
66
+ if (structureType === 'mixed') {
67
+ issues.push('Mixed folder structure detected (both flat and feature-based). Consider standardizing.');
68
+ }
69
+ // Check for src at wrong level
70
+ const sourceFiles = await findSourceFiles(appPath);
71
+ const filesOutsideSrc = sourceFiles.filter((f) => {
72
+ const rel = path.relative(appPath, f);
73
+ return !rel.startsWith('src' + path.sep) && rel !== 'src';
74
+ });
75
+ if (filesOutsideSrc.length > 0) {
76
+ issues.push(`${filesOutsideSrc.length} source files found outside src/ directory.`);
77
+ }
78
+ return {
79
+ structureType,
80
+ folders: folders.sort(),
81
+ maxDepth,
82
+ issues,
83
+ };
84
+ }
85
+ //# sourceMappingURL=02-analyze-folder-structure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"02-analyze-folder-structure.js","sourceRoot":"","sources":["../../src/tools/02-analyze-folder-structure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AnalyzeComponentsOutput, AnalyzerConfig } from '../types.js';
2
+ export declare function analyzeComponents(appPath: string, config?: Partial<AnalyzerConfig>): Promise<AnalyzeComponentsOutput>;
3
+ //# sourceMappingURL=03-analyze-components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"03-analyze-components.d.ts","sourceRoot":"","sources":["../../src/tools/03-analyze-components.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,uBAAuB,EAAiB,cAAc,EAAE,MAAM,aAAa,CAAC;AAE1F,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAoF3H"}
@@ -0,0 +1,87 @@
1
+ // ============================================================================
2
+ // TOOL #3: analyze-components
3
+ // Scans all components: count, large components, complex components
4
+ // ============================================================================
5
+ import * as path from 'path';
6
+ import * as fs from 'fs';
7
+ import { findSourceFiles, resolveSourceDir } from '../utils/file-scanner.js';
8
+ import { analyzeComponent } from '../utils/ast-parser.js';
9
+ import { DEFAULT_CONFIG } from '../types.js';
10
+ export async function analyzeComponents(appPath, config) {
11
+ const mergedConfig = { ...DEFAULT_CONFIG, ...config };
12
+ const srcPath = resolveSourceDir(appPath);
13
+ const files = await findSourceFiles(srcPath);
14
+ // Include all JS/JSX/TS/TSX files — apps like CRA use lowercase App.js or index.js
15
+ const componentFiles = files;
16
+ const largeComponents = [];
17
+ const complexComponents = [];
18
+ for (const file of componentFiles) {
19
+ const relPath = path.relative(appPath, file);
20
+ // Read raw content first (works for both JS and TS)
21
+ let content;
22
+ try {
23
+ content = fs.readFileSync(file, 'utf8');
24
+ }
25
+ catch {
26
+ continue;
27
+ }
28
+ // Try AST analysis — may fail for plain JS files
29
+ const analysis = analyzeComponent(file);
30
+ const responsibilities = [];
31
+ const importSources = (analysis?.imports ?? []).map((i) => i.source.toLowerCase());
32
+ // All responsibility checks use regex on raw content (works for both JS and TS)
33
+ const hasState = /\buseState\s*\(|React\.useState\s*\(|\buseReducer\s*\(|React\.useReducer\s*\(/.test(content)
34
+ || (analysis?.hooks.some((h) => h.name === 'useState' || h.name === 'useReducer') ?? false);
35
+ if (hasState)
36
+ responsibilities.push('state-management');
37
+ const hasEffect = /\buseEffect\s*\(|React\.useEffect\s*\(/.test(content)
38
+ || (analysis?.hooks.some((h) => h.name === 'useEffect') ?? false);
39
+ if (hasEffect)
40
+ responsibilities.push('side-effects');
41
+ if (content.includes('fetch(') || content.includes('axios.') || importSources.some((s) => s.includes('api'))) {
42
+ responsibilities.push('api-calls');
43
+ }
44
+ if (importSources.some((s) => s.includes('router') || s.includes('navigate'))) {
45
+ responsibilities.push('routing');
46
+ }
47
+ if (content.includes('onSubmit') || content.includes('FormData') || content.includes('handleSubmit')) {
48
+ responsibilities.push('form-handling');
49
+ }
50
+ const jsxTagCount = (content.match(/<[A-Z][a-zA-Z]*|<[a-z]+[\s>]/g) || []).length;
51
+ const astJsxCount = analysis?.jsxElements.length ?? 0;
52
+ if (astJsxCount > 15 || jsxTagCount > 15)
53
+ responsibilities.push('heavy-rendering');
54
+ const lines = content.split('\n').length;
55
+ const stateVarCount = (content.match(/\buseState\s*\(|React\.useState\s*\(/g) || []).length;
56
+ const hookCount = analysis?.hooks.length ?? 0;
57
+ const jsxDepth = analysis?.jsxMaxDepth ?? 0;
58
+ const componentName = analysis?.name ?? path.basename(file, path.extname(file));
59
+ const componentInfo = {
60
+ name: componentName,
61
+ file: relPath,
62
+ lines,
63
+ jsxMaxDepth: jsxDepth,
64
+ responsibilities,
65
+ };
66
+ // Skip non-component files (no JSX, no hooks, not enough evidence)
67
+ const isLikelyComponent = jsxTagCount > 0 || hasState || hasEffect || content.includes('return (') || content.includes('return(');
68
+ if (!isLikelyComponent)
69
+ continue;
70
+ if (lines > mergedConfig.largeComponentLines) {
71
+ largeComponents.push(componentInfo);
72
+ }
73
+ // Complex: multiple responsibilities, or deep nesting, or many hooks, or many state vars
74
+ const isComplex = responsibilities.length >= 3 ||
75
+ jsxDepth > 6 ||
76
+ hookCount >= 5 ||
77
+ stateVarCount >= 3;
78
+ if (isComplex)
79
+ complexComponents.push(componentInfo);
80
+ }
81
+ return {
82
+ totalComponents: componentFiles.length,
83
+ largeComponents: largeComponents.sort((a, b) => b.lines - a.lines),
84
+ complexComponents: complexComponents.sort((a, b) => b.responsibilities.length - a.responsibilities.length),
85
+ };
86
+ }
87
+ //# sourceMappingURL=03-analyze-components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"03-analyze-components.js","sourceRoot":"","sources":["../../src/tools/03-analyze-components.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AnalyzeStateOutput, AnalyzerConfig } from '../types.js';
2
+ export declare function analyzeStateManagement(appPath: string, config?: Partial<AnalyzerConfig>): Promise<AnalyzeStateOutput>;
3
+ //# sourceMappingURL=04-analyze-state-management.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"04-analyze-state-management.d.ts","sourceRoot":"","sources":["../../src/tools/04-analyze-state-management.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,kBAAkB,EAAiB,cAAc,EAAE,MAAM,aAAa,CAAC;AAErF,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA+I3H"}
@@ -0,0 +1,133 @@
1
+ // ============================================================================
2
+ // TOOL #4: analyze-state-management
3
+ // Detects Redux, Context API, local state patterns, and advanced patterns
4
+ // ============================================================================
5
+ import * as path from 'path';
6
+ import { findSourceFiles, readFileContent, resolveSourceDir } from '../utils/file-scanner.js';
7
+ import { parseFile, extractImports, extractHooks } from '../utils/ast-parser.js';
8
+ export async function analyzeStateManagement(appPath, config) {
9
+ const srcPath = resolveSourceDir(appPath);
10
+ const files = await findSourceFiles(srcPath);
11
+ let reduxUsage = 0;
12
+ let contextUsage = 0;
13
+ let localStateUsage = 0;
14
+ const patterns = {
15
+ normalizedState: false,
16
+ derivedState: false,
17
+ reselectUsed: false,
18
+ };
19
+ const issues = [];
20
+ const stateHeavyComponents = [];
21
+ let hasEntitiesPattern = false;
22
+ let hasIdsPattern = false;
23
+ let hasDerivedState = false;
24
+ let hasCreateSelector = false;
25
+ let totalLocalStateCalls = 0;
26
+ for (const file of files) {
27
+ const content = readFileContent(file);
28
+ if (!content)
29
+ continue;
30
+ const relPath = path.relative(appPath, file);
31
+ // AST-based analysis (best effort)
32
+ let astHooks = [];
33
+ let astImportSources = [];
34
+ const parsed = parseFile(file);
35
+ if (parsed) {
36
+ const imports = extractImports(parsed.ast);
37
+ astHooks = extractHooks(parsed.ast);
38
+ astImportSources = imports.map((i) => i.source);
39
+ }
40
+ // Redux detection
41
+ const hasRedux = astImportSources.some((s) => s.includes('redux') || s.includes('@reduxjs/toolkit') || s.includes('react-redux')) || content.includes('useSelector') || content.includes('useDispatch') || content.includes('createStore');
42
+ if (hasRedux)
43
+ reduxUsage++;
44
+ // Context API detection
45
+ const hasContext = content.includes('createContext') || content.includes('useContext') || content.includes('React.createContext');
46
+ if (hasContext)
47
+ contextUsage++;
48
+ // Local state detection — covers both imported useState and React.useState namespace style
49
+ const astStateHooks = astHooks.filter((h) => h.name === 'useState' || h.name === 'useReducer');
50
+ const regexStateCount = (content.match(/\buseState\s*\(/g) || []).length
51
+ + (content.match(/React\.useState\s*\(/g) || []).length
52
+ + (content.match(/\buseReducer\s*\(/g) || []).length
53
+ + (content.match(/React\.useReducer\s*\(/g) || []).length;
54
+ const localStateCount = Math.max(astStateHooks.length, regexStateCount);
55
+ if (localStateCount > 0) {
56
+ localStateUsage++;
57
+ totalLocalStateCalls += localStateCount;
58
+ // Flag components with excessive local state (potential god component)
59
+ if (localStateCount >= 3) {
60
+ stateHeavyComponents.push(`${relPath} (${localStateCount} state variables)`);
61
+ }
62
+ }
63
+ // Reselect detection
64
+ if (content.includes('createSelector') || astImportSources.some((s) => s.includes('reselect'))) {
65
+ hasCreateSelector = true;
66
+ }
67
+ // Normalized state detection
68
+ if (content.includes('entities') && (content.includes('ids') || content.includes('allIds'))) {
69
+ hasEntitiesPattern = true;
70
+ hasIdsPattern = true;
71
+ }
72
+ if (content.includes('byId') || content.includes('entitiesById')) {
73
+ hasEntitiesPattern = true;
74
+ }
75
+ // Derived state detection
76
+ const hasMemo = content.includes('useMemo') || content.includes('React.useMemo');
77
+ if (hasMemo && localStateCount > 0)
78
+ hasDerivedState = true;
79
+ if (content.includes('getDerived') || content.includes('selectDerived'))
80
+ hasDerivedState = true;
81
+ // Mixed Redux + excessive local state
82
+ if (hasRedux && localStateCount > 5) {
83
+ issues.push(`${relPath}: Mix of Redux and excessive local state (${localStateCount} useState calls). Consider consolidating.`);
84
+ }
85
+ // Large Redux slices
86
+ if (content.includes('createSlice') && content.split('\n').length > 200) {
87
+ issues.push(`${relPath}: Large Redux slice. Consider splitting into smaller slices.`);
88
+ }
89
+ }
90
+ patterns.normalizedState = hasEntitiesPattern && hasIdsPattern;
91
+ patterns.derivedState = hasDerivedState;
92
+ patterns.reselectUsed = hasCreateSelector;
93
+ let stateType;
94
+ const hasRedux = reduxUsage > 0;
95
+ const hasContext = contextUsage > 0;
96
+ const hasLocal = localStateUsage > 0;
97
+ if (hasRedux && (hasContext || hasLocal)) {
98
+ stateType = 'mixed';
99
+ }
100
+ else if (hasRedux) {
101
+ stateType = 'redux';
102
+ }
103
+ else if (hasContext) {
104
+ stateType = 'context';
105
+ }
106
+ else if (hasLocal) {
107
+ stateType = 'local';
108
+ }
109
+ else {
110
+ stateType = 'none';
111
+ }
112
+ if (stateType === 'mixed') {
113
+ issues.push('Mixed state management detected (Redux + Context/Local). Consider standardizing on one approach.');
114
+ }
115
+ if (hasRedux && !hasCreateSelector) {
116
+ issues.push('Redux used without Reselect. Consider using memoized selectors for performance.');
117
+ }
118
+ if (contextUsage > 5) {
119
+ issues.push(`High Context API usage (${contextUsage} files). Consider if some contexts should be Redux stores or Zustand.`);
120
+ }
121
+ if (stateType === 'local' && totalLocalStateCalls > 5) {
122
+ issues.push(`All state is local useState (${totalLocalStateCalls} calls across ${localStateUsage} files). Consider extracting to Context or Zustand for complex shared state.`);
123
+ }
124
+ if (stateHeavyComponents.length > 0) {
125
+ issues.push(`Components with many state variables (potential god components): ${stateHeavyComponents.join(', ')}`);
126
+ }
127
+ return {
128
+ stateType,
129
+ patterns,
130
+ issues,
131
+ };
132
+ }
133
+ //# sourceMappingURL=04-analyze-state-management.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"04-analyze-state-management.js","sourceRoot":"","sources":["../../src/tools/04-analyze-state-management.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AnalyzeApiOutput, AnalyzerConfig } from '../types.js';
2
+ export declare function analyzeApiLayer(appPath: string, config?: Partial<AnalyzerConfig>): Promise<AnalyzeApiOutput>;
3
+ //# sourceMappingURL=05-analyze-api-layer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"05-analyze-api-layer.d.ts","sourceRoot":"","sources":["../../src/tools/05-analyze-api-layer.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKpE,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2JlH"}
@@ -0,0 +1,160 @@
1
+ // ============================================================================
2
+ // TOOL #5: analyze-api-layer
3
+ // Detects API patterns: axios/fetch/superagent usage, Next.js API routes,
4
+ // centralized vs scattered pattern, and duplicate endpoints
5
+ // ============================================================================
6
+ import * as path from 'path';
7
+ import { findSourceFiles, readFileContent, resolveSourceDir } from '../utils/file-scanner.js';
8
+ import { parseFile, extractImports } from '../utils/ast-parser.js';
9
+ const API_CLIENTS = ['axios', 'node-fetch', 'got', 'superagent', 'ky', 'undici'];
10
+ const API_INDICATORS = ['fetch(', 'axios.', 'api.', '/api/', 'useSWR', 'useQuery', 'useMutation'];
11
+ export async function analyzeApiLayer(appPath, config) {
12
+ const srcPath = resolveSourceDir(appPath);
13
+ const files = await findSourceFiles(srcPath);
14
+ const clients = new Set();
15
+ const issues = [];
16
+ const apiEndpoints = new Map(); // endpoint -> files
17
+ let centralizedFiles = 0;
18
+ let scatteredFiles = 0;
19
+ const duplicateEndpoints = [];
20
+ // Files that look like API service files
21
+ // Next.js API routes are inherently centralized (pages/api/ or app/api/)
22
+ const isNextJsApiRoute = (f) => {
23
+ const rel = f.replace(appPath, '');
24
+ return rel.includes('/pages/api/') || rel.includes('/app/api/');
25
+ };
26
+ const apiServiceFiles = files.filter((f) => {
27
+ if (isNextJsApiRoute(f))
28
+ return true;
29
+ const lower = f.toLowerCase();
30
+ const base = path.basename(lower, path.extname(lower));
31
+ const API_SERVICE_NAMES = ['agent', 'api', 'http', 'client', 'request', 'fetcher', 'axios', 'service'];
32
+ return lower.includes('/api/') || lower.includes('/service') || lower.includes('/services/') ||
33
+ lower.includes('client.') || lower.includes('/api-client') || API_SERVICE_NAMES.includes(base);
34
+ });
35
+ for (const file of files) {
36
+ const content = readFileContent(file);
37
+ if (!content)
38
+ continue;
39
+ const relPath = path.relative(appPath, file);
40
+ const isApiService = apiServiceFiles.includes(file);
41
+ // Content-based detection (works for both JS and TS files)
42
+ const hasFetch = content.includes('fetch(');
43
+ const hasAxios = content.includes('axios.get(') || content.includes('axios.post(') || content.includes('axios(');
44
+ const hasSuperagent = content.includes('superagent.') || content.includes('superagent-promise');
45
+ const hasGot = content.includes('got.get(') || content.includes('got.post(') || content.includes("from 'got'") || content.includes('from "got"');
46
+ const hasKy = content.includes('ky.get(') || content.includes('ky.post(') || content.includes("from 'ky'") || content.includes('from "ky"');
47
+ // Register clients detected by content
48
+ if (hasFetch && !content.includes('axios') && !hasSuperagent)
49
+ clients.add('fetch');
50
+ if (hasAxios)
51
+ clients.add('axios');
52
+ if (hasSuperagent)
53
+ clients.add('superagent');
54
+ if (hasGot)
55
+ clients.add('got');
56
+ if (hasKy)
57
+ clients.add('ky');
58
+ const hasApiIndicator = API_INDICATORS.some((indicator) => content.includes(indicator));
59
+ const hasApiCall = hasApiIndicator || hasFetch || hasAxios || hasSuperagent || hasGot || hasKy;
60
+ if (hasApiCall) {
61
+ if (isApiService)
62
+ centralizedFiles++;
63
+ else
64
+ scatteredFiles++;
65
+ }
66
+ // Extract API endpoints (skip CDN, schema, and asset URLs)
67
+ const EXCLUDED_URL_PATTERNS = ['w3.org', 'schemas.', 'xmlns', 'cdn.', 'fonts.', 'cdnjs.', 'unpkg.', 'jsdelivr.', 'cloudflare.com/ajax', 'localhost', '127.0.0.1', '0.0.0.0'];
68
+ const endpointRegex = /['"`](\/api\/[^'"`\s]+|https?:\/\/[^'"`\s]+)['"`]/g;
69
+ let endpointMatch;
70
+ while ((endpointMatch = endpointRegex.exec(content)) !== null) {
71
+ const endpoint = endpointMatch[1];
72
+ if (EXCLUDED_URL_PATTERNS.some((pat) => endpoint.includes(pat)))
73
+ continue;
74
+ if (!apiEndpoints.has(endpoint))
75
+ apiEndpoints.set(endpoint, []);
76
+ apiEndpoints.get(endpoint).push(relPath);
77
+ }
78
+ // Detect fetch without response handling (fire-and-forget)
79
+ if (hasFetch) {
80
+ const fetchMatches = [...content.matchAll(/fetch\s*\([^)]+\)/g)];
81
+ for (const m of fetchMatches) {
82
+ const idx = m.index ?? 0;
83
+ const after = content.slice(idx, idx + 200);
84
+ if (!after.includes('.then(') && !after.includes('await') && !after.includes('.json(')) {
85
+ issues.push(`${relPath}: fetch() result not handled — response never read or awaited.`);
86
+ break;
87
+ }
88
+ }
89
+ }
90
+ // Detect missing Content-Type on mutating requests
91
+ if (hasFetch && (content.includes("method: 'POST'") || content.includes('method: "POST"') ||
92
+ content.includes("method: 'PUT'") || content.includes("method: 'PATCH'"))) {
93
+ if (!content.includes('Content-Type') && !content.includes('content-type')) {
94
+ issues.push(`${relPath}: POST/PUT fetch call missing Content-Type header.`);
95
+ }
96
+ }
97
+ // AST-based: detect library imports (best effort, skip if AST fails for .js)
98
+ const parsed = parseFile(file);
99
+ if (parsed) {
100
+ const imports = extractImports(parsed.ast);
101
+ const importSources = imports.map((i) => i.source);
102
+ for (const client of API_CLIENTS) {
103
+ if (importSources.some((s) => s.includes(client)))
104
+ clients.add(client);
105
+ }
106
+ }
107
+ }
108
+ // Find duplicate endpoints
109
+ for (const [endpoint, filesUsingIt] of apiEndpoints) {
110
+ if (filesUsingIt.length > 1) {
111
+ duplicateEndpoints.push(`${endpoint} (used in ${filesUsingIt.length} files)`);
112
+ }
113
+ }
114
+ // Determine pattern
115
+ let apiPattern;
116
+ if (centralizedFiles === 0 && scatteredFiles === 0) {
117
+ apiPattern = 'none';
118
+ }
119
+ else if (centralizedFiles > 0 && scatteredFiles === 0) {
120
+ apiPattern = 'centralized';
121
+ }
122
+ else if (scatteredFiles > centralizedFiles) {
123
+ apiPattern = 'scattered';
124
+ }
125
+ else {
126
+ apiPattern = 'mixed';
127
+ }
128
+ // Issues
129
+ if (apiPattern === 'scattered') {
130
+ issues.push('API calls scattered across components. Consider creating a centralized API service layer.');
131
+ }
132
+ if (apiPattern === 'mixed') {
133
+ issues.push('Mixed API patterns. Some calls centralized, some scattered. Standardize for consistency.');
134
+ }
135
+ if (duplicateEndpoints.length > 0) {
136
+ issues.push(`Duplicate API endpoints detected: ${duplicateEndpoints.join(', ')}`);
137
+ }
138
+ if (clients.size > 1) {
139
+ issues.push(`Multiple HTTP clients detected (${Array.from(clients).join(', ')}). Consider using one consistently.`);
140
+ }
141
+ if (clients.size === 0 && apiPattern !== 'none') {
142
+ issues.push('API calls detected but no recognized HTTP client found. May be using a custom wrapper.');
143
+ }
144
+ // Check for missing error handling
145
+ for (const file of files) {
146
+ const content = readFileContent(file);
147
+ if (!content)
148
+ continue;
149
+ if ((content.includes('fetch(') || content.includes('axios.')) && !content.includes('.catch') && !content.includes('try {')) {
150
+ issues.push(`${path.relative(appPath, file)}: API calls without error handling.`);
151
+ }
152
+ }
153
+ return {
154
+ apiPattern,
155
+ clients: Array.from(clients),
156
+ duplicateEndpoints,
157
+ issues,
158
+ };
159
+ }
160
+ //# sourceMappingURL=05-analyze-api-layer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"05-analyze-api-layer.js","sourceRoot":"","sources":["../../src/tools/05-analyze-api-layer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AnalyzeRoutingOutput, AnalyzerConfig } from '../types.js';
2
+ export declare function analyzeRouting(appPath: string, config?: Partial<AnalyzerConfig>): Promise<AnalyzeRoutingOutput>;
3
+ //# sourceMappingURL=06-analyze-routing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"06-analyze-routing.d.ts","sourceRoot":"","sources":["../../src/tools/06-analyze-routing.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIxE,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA+JrH"}