mcp-react-toolkit 1.0.1 → 1.3.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.
- package/README.md +194 -44
- package/bin/cli.mjs +59 -0
- package/node_modules/@mcp-showcase/shared/build/McpServerBase.d.ts +18 -0
- package/node_modules/@mcp-showcase/shared/build/McpServerBase.d.ts.map +1 -0
- package/node_modules/@mcp-showcase/shared/build/McpServerBase.js +74 -0
- package/node_modules/@mcp-showcase/shared/build/McpServerBase.js.map +1 -0
- package/node_modules/@mcp-showcase/shared/build/ToolRegistry.d.ts +9 -0
- package/node_modules/@mcp-showcase/shared/build/ToolRegistry.d.ts.map +1 -0
- package/node_modules/@mcp-showcase/shared/build/ToolRegistry.js +22 -0
- package/node_modules/@mcp-showcase/shared/build/ToolRegistry.js.map +1 -0
- package/node_modules/@mcp-showcase/shared/build/fs.d.ts +8 -0
- package/node_modules/@mcp-showcase/shared/build/fs.d.ts.map +1 -0
- package/node_modules/@mcp-showcase/shared/build/fs.js +45 -0
- package/node_modules/@mcp-showcase/shared/build/fs.js.map +1 -0
- package/node_modules/@mcp-showcase/shared/build/index.d.ts +5 -0
- package/node_modules/@mcp-showcase/shared/build/index.d.ts.map +1 -0
- package/node_modules/@mcp-showcase/shared/build/index.js +5 -0
- package/node_modules/@mcp-showcase/shared/build/index.js.map +1 -0
- package/node_modules/@mcp-showcase/shared/build/types.d.ts +36 -0
- package/node_modules/@mcp-showcase/shared/build/types.d.ts.map +1 -0
- package/node_modules/@mcp-showcase/shared/build/types.js +5 -0
- package/node_modules/@mcp-showcase/shared/build/types.js.map +1 -0
- package/node_modules/@mcp-showcase/shared/package.json +24 -0
- package/node_modules/@mcp-showcase/shared/src/McpServerBase.ts +100 -0
- package/node_modules/@mcp-showcase/shared/src/ToolRegistry.ts +38 -0
- package/node_modules/@mcp-showcase/shared/src/fs.ts +49 -0
- package/node_modules/@mcp-showcase/shared/src/index.ts +12 -0
- package/node_modules/@mcp-showcase/shared/src/types.ts +44 -0
- package/node_modules/@mcp-showcase/shared/tsconfig.json +8 -0
- package/package.json +38 -4
- package/tools/accessibility-checker/build/index.js +9 -5
- package/tools/accessibility-checker/build/index.js.map +1 -1
- package/tools/accessibility-checker/build/rules.d.ts.map +1 -1
- package/tools/accessibility-checker/build/rules.js +325 -94
- package/tools/accessibility-checker/build/rules.js.map +1 -1
- package/tools/code-modernizer/build/tools/01-convert-to-typescript.d.ts.map +1 -1
- package/tools/code-modernizer/build/tools/01-convert-to-typescript.js +65 -50
- package/tools/code-modernizer/build/tools/01-convert-to-typescript.js.map +1 -1
- package/tools/code-modernizer/build/types.d.ts +1 -0
- package/tools/code-modernizer/build/types.d.ts.map +1 -1
- package/tools/code-modernizer/build/utils/ast-parser.d.ts.map +1 -1
- package/tools/code-modernizer/build/utils/ast-parser.js +30 -14
- package/tools/code-modernizer/build/utils/ast-parser.js.map +1 -1
- package/tools/code-modernizer/build/utils/type-generator.d.ts +1 -1
- package/tools/code-modernizer/build/utils/type-generator.d.ts.map +1 -1
- package/tools/code-modernizer/build/utils/type-generator.js +72 -23
- package/tools/code-modernizer/build/utils/type-generator.js.map +1 -1
- package/tools/component-factory/build/index.js +59 -7
- package/tools/component-factory/build/index.js.map +1 -1
- package/tools/component-fixer/README.md +44 -0
- package/tools/component-fixer/build/index.d.ts +3 -0
- package/tools/component-fixer/build/index.d.ts.map +1 -0
- package/tools/component-fixer/build/index.js +647 -0
- package/tools/component-fixer/build/index.js.map +1 -0
- package/tools/component-fixer/package.json +20 -0
- package/tools/component-reviewer/README.md +54 -0
- package/tools/component-reviewer/build/index.d.ts +39 -0
- package/tools/component-reviewer/build/index.d.ts.map +1 -0
- package/tools/component-reviewer/build/index.js +946 -0
- package/tools/component-reviewer/build/index.js.map +1 -0
- package/tools/component-reviewer/package.json +20 -0
- package/tools/dep-auditor/build/index.d.ts +1 -0
- package/tools/dep-auditor/build/index.d.ts.map +1 -1
- package/tools/dep-auditor/build/index.js +71 -16
- package/tools/dep-auditor/build/index.js.map +1 -1
- package/tools/generate-tests/build/analyzer.d.ts +14 -0
- package/tools/generate-tests/build/analyzer.d.ts.map +1 -1
- package/tools/generate-tests/build/analyzer.js +96 -42
- package/tools/generate-tests/build/analyzer.js.map +1 -1
- package/tools/generate-tests/build/generators.d.ts.map +1 -1
- package/tools/generate-tests/build/generators.js +304 -79
- package/tools/generate-tests/build/generators.js.map +1 -1
- package/tools/generate-tests/build/index.js +29 -10
- package/tools/generate-tests/build/index.js.map +1 -1
- package/tools/json-viewer/build/index.js +29 -6
- package/tools/json-viewer/build/index.js.map +1 -1
- package/tools/legacy-analyzer/README.md +66 -0
- package/tools/legacy-analyzer/build/index.d.ts +3 -0
- package/tools/legacy-analyzer/build/index.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/index.js +209 -0
- package/tools/legacy-analyzer/build/index.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/01-detect-project-tech.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/01-detect-project-tech.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/01-detect-project-tech.js +115 -0
- package/tools/legacy-analyzer/build/tools/01-detect-project-tech.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/02-analyze-folder-structure.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/02-analyze-folder-structure.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/02-analyze-folder-structure.js +85 -0
- package/tools/legacy-analyzer/build/tools/02-analyze-folder-structure.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/03-analyze-components.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/03-analyze-components.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/03-analyze-components.js +87 -0
- package/tools/legacy-analyzer/build/tools/03-analyze-components.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/04-analyze-state-management.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/04-analyze-state-management.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/04-analyze-state-management.js +133 -0
- package/tools/legacy-analyzer/build/tools/04-analyze-state-management.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.js +160 -0
- package/tools/legacy-analyzer/build/tools/05-analyze-api-layer.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/06-analyze-routing.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/06-analyze-routing.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/06-analyze-routing.js +150 -0
- package/tools/legacy-analyzer/build/tools/06-analyze-routing.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/07-analyze-styling.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/07-analyze-styling.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/07-analyze-styling.js +131 -0
- package/tools/legacy-analyzer/build/tools/07-analyze-styling.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/08-analyze-assets.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/08-analyze-assets.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/08-analyze-assets.js +85 -0
- package/tools/legacy-analyzer/build/tools/08-analyze-assets.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/09-detect-anti-patterns.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/09-detect-anti-patterns.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/09-detect-anti-patterns.js +329 -0
- package/tools/legacy-analyzer/build/tools/09-detect-anti-patterns.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/10-detect-duplication.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/10-detect-duplication.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/10-detect-duplication.js +192 -0
- package/tools/legacy-analyzer/build/tools/10-detect-duplication.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/11-analyze-dependencies-usage.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/11-analyze-dependencies-usage.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/11-analyze-dependencies-usage.js +232 -0
- package/tools/legacy-analyzer/build/tools/11-analyze-dependencies-usage.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/12-analyze-legacy-app.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/12-analyze-legacy-app.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/12-analyze-legacy-app.js +247 -0
- package/tools/legacy-analyzer/build/tools/12-analyze-legacy-app.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/13-detect-features.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/13-detect-features.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/13-detect-features.js +141 -0
- package/tools/legacy-analyzer/build/tools/13-detect-features.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/14-classify-files.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/14-classify-files.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/14-classify-files.js +76 -0
- package/tools/legacy-analyzer/build/tools/14-classify-files.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/15-detect-shared-modules.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/15-detect-shared-modules.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/15-detect-shared-modules.js +70 -0
- package/tools/legacy-analyzer/build/tools/15-detect-shared-modules.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/16-design-target-structure.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/16-design-target-structure.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/16-design-target-structure.js +26 -0
- package/tools/legacy-analyzer/build/tools/16-design-target-structure.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/17-map-files-to-target.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/17-map-files-to-target.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/17-map-files-to-target.js +108 -0
- package/tools/legacy-analyzer/build/tools/17-map-files-to-target.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/18-detect-boundary-violations.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/18-detect-boundary-violations.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/18-detect-boundary-violations.js +137 -0
- package/tools/legacy-analyzer/build/tools/18-detect-boundary-violations.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/19-suggest-module-splitting.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/19-suggest-module-splitting.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/19-suggest-module-splitting.js +160 -0
- package/tools/legacy-analyzer/build/tools/19-suggest-module-splitting.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/20-naming-standardizer.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/20-naming-standardizer.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/20-naming-standardizer.js +162 -0
- package/tools/legacy-analyzer/build/tools/20-naming-standardizer.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/21-generate-refactor-plan.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/21-generate-refactor-plan.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/21-generate-refactor-plan.js +108 -0
- package/tools/legacy-analyzer/build/tools/21-generate-refactor-plan.js.map +1 -0
- package/tools/legacy-analyzer/build/tools/22-refactor-folder-structure.d.ts +3 -0
- package/tools/legacy-analyzer/build/tools/22-refactor-folder-structure.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/tools/22-refactor-folder-structure.js +98 -0
- package/tools/legacy-analyzer/build/tools/22-refactor-folder-structure.js.map +1 -0
- package/tools/legacy-analyzer/build/types.d.ts +413 -0
- package/tools/legacy-analyzer/build/types.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/types.js +12 -0
- package/tools/legacy-analyzer/build/types.js.map +1 -0
- package/tools/legacy-analyzer/build/utils/ast-parser.d.ts +34 -0
- package/tools/legacy-analyzer/build/utils/ast-parser.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/utils/ast-parser.js +394 -0
- package/tools/legacy-analyzer/build/utils/ast-parser.js.map +1 -0
- package/tools/legacy-analyzer/build/utils/file-scanner.d.ts +51 -0
- package/tools/legacy-analyzer/build/utils/file-scanner.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/utils/file-scanner.js +174 -0
- package/tools/legacy-analyzer/build/utils/file-scanner.js.map +1 -0
- package/tools/legacy-analyzer/build/utils/import-tracker.d.ts +38 -0
- package/tools/legacy-analyzer/build/utils/import-tracker.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/utils/import-tracker.js +194 -0
- package/tools/legacy-analyzer/build/utils/import-tracker.js.map +1 -0
- package/tools/legacy-analyzer/build/utils/refactor-helpers.d.ts +88 -0
- package/tools/legacy-analyzer/build/utils/refactor-helpers.d.ts.map +1 -0
- package/tools/legacy-analyzer/build/utils/refactor-helpers.js +538 -0
- package/tools/legacy-analyzer/build/utils/refactor-helpers.js.map +1 -0
- package/tools/legacy-analyzer/package.json +20 -0
- package/tools/lighthouse-runner/README.md +45 -0
- package/tools/lighthouse-runner/build/index.d.ts +6 -0
- package/tools/lighthouse-runner/build/index.d.ts.map +1 -0
- package/tools/lighthouse-runner/build/index.js +295 -0
- package/tools/lighthouse-runner/build/index.js.map +1 -0
- package/tools/lighthouse-runner/package.json +20 -0
- package/tools/monorepo-manager/build/utils.d.ts.map +1 -1
- package/tools/monorepo-manager/build/utils.js +12 -9
- package/tools/monorepo-manager/build/utils.js.map +1 -1
- package/tools/performance-audit/README.md +37 -0
- package/tools/performance-audit/build/index.d.ts +13 -0
- package/tools/performance-audit/build/index.d.ts.map +1 -0
- package/tools/performance-audit/build/index.js +311 -0
- package/tools/performance-audit/build/index.js.map +1 -0
- package/tools/performance-audit/package.json +20 -0
- package/tools/quality-pipeline/build/index.js +55 -15
- package/tools/quality-pipeline/build/index.js.map +1 -1
- package/tools/render-analyzer/README.md +43 -0
- package/tools/render-analyzer/build/index.d.ts +25 -0
- package/tools/render-analyzer/build/index.d.ts.map +1 -0
- package/tools/render-analyzer/build/index.js +342 -0
- package/tools/render-analyzer/build/index.js.map +1 -0
- package/tools/render-analyzer/package.json +20 -0
- package/tools/shared/build/fs.d.ts +8 -0
- package/tools/shared/build/fs.d.ts.map +1 -0
- package/tools/shared/build/fs.js +45 -0
- package/tools/shared/build/fs.js.map +1 -0
- package/tools/shared/build/index.d.ts +1 -0
- package/tools/shared/build/index.d.ts.map +1 -1
- package/tools/shared/build/index.js +1 -0
- package/tools/shared/build/index.js.map +1 -1
- package/tools/shared/package.json +2 -1
- package/tools/storybook-generator/README.md +39 -0
- package/tools/storybook-generator/build/index.d.ts +13 -0
- package/tools/storybook-generator/build/index.d.ts.map +1 -0
- package/tools/storybook-generator/build/index.js +478 -0
- package/tools/storybook-generator/build/index.js.map +1 -0
- package/tools/storybook-generator/package.json +20 -0
- package/tools/test-gap-analyzer/README.md +41 -0
- package/tools/test-gap-analyzer/build/index.d.ts +20 -0
- package/tools/test-gap-analyzer/build/index.d.ts.map +1 -0
- package/tools/test-gap-analyzer/build/index.js +371 -0
- package/tools/test-gap-analyzer/build/index.js.map +1 -0
- package/tools/test-gap-analyzer/package.json +20 -0
- package/tools/typescript-enforcer/build/scanner.d.ts.map +1 -1
- package/tools/typescript-enforcer/build/scanner.js +13 -1
- package/tools/typescript-enforcer/build/scanner.js.map +1 -1
- package/tools/typescript-enforcer/build/types.d.ts +1 -0
- package/tools/typescript-enforcer/build/types.d.ts.map +1 -1
- package/CONTRIBUTING.md +0 -157
- package/demo/legacy-app/src/App.jsx +0 -12
- package/demo/legacy-app/src/components/Dashboard.jsx +0 -51
- package/demo/legacy-app/src/components/UserCard.jsx +0 -32
- package/demo/legacy-app/src/hooks/useUsers.js +0 -38
- package/demo/legacy-app/src/utils/api.js +0 -30
- package/glama.json +0 -4
- package/mcp-publisher +0 -0
- package/server.json +0 -20
- package/tools/accessibility-checker/build/rules.test.d.ts +0 -2
- package/tools/accessibility-checker/build/rules.test.d.ts.map +0 -1
- package/tools/accessibility-checker/build/rules.test.js.map +0 -1
- package/tools/code-modernizer/build/utils/file-ops.test.d.ts +0 -2
- package/tools/code-modernizer/build/utils/file-ops.test.d.ts.map +0 -1
- package/tools/code-modernizer/build/utils/file-ops.test.js.map +0 -1
- package/tools/component-factory/build/utils.test.d.ts +0 -2
- package/tools/component-factory/build/utils.test.d.ts.map +0 -1
- package/tools/component-factory/build/utils.test.js.map +0 -1
- package/tools/dep-auditor/build/index.test.d.ts +0 -2
- package/tools/dep-auditor/build/index.test.d.ts.map +0 -1
- package/tools/dep-auditor/build/index.test.js.map +0 -1
- package/tools/generate-tests/build/analyzer.test.d.ts +0 -2
- package/tools/generate-tests/build/analyzer.test.d.ts.map +0 -1
- package/tools/generate-tests/build/analyzer.test.js.map +0 -1
- package/tools/json-viewer/build/utils.test.d.ts +0 -2
- package/tools/json-viewer/build/utils.test.d.ts.map +0 -1
- package/tools/json-viewer/build/utils.test.js.map +0 -1
- package/tools/monorepo-manager/build/utils.test.d.ts +0 -2
- package/tools/monorepo-manager/build/utils.test.d.ts.map +0 -1
- package/tools/monorepo-manager/build/utils.test.js.map +0 -1
- package/tools/quality-pipeline/build/utils.test.d.ts +0 -2
- package/tools/quality-pipeline/build/utils.test.d.ts.map +0 -1
- package/tools/quality-pipeline/build/utils.test.js.map +0 -1
- package/tools/typescript-enforcer/build/scanner.test.d.ts +0 -2
- package/tools/typescript-enforcer/build/scanner.test.d.ts.map +0 -1
- package/tools/typescript-enforcer/build/scanner.test.js.map +0 -1
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|
|
@@ -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":"AAAA,+EAA+E;AAC/E,2BAA2B;AAC3B,qFAAqF;AACrF,+EAA+E;AAE/E,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAG/E,MAAM,iBAAiB,GAAG,CAAC,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,kBAAkB,CAAU,CAAC;AAExI,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe,EAAE,MAAgC;IACpF,0EAA0E;IAC1E,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAEnD,MAAM,YAAY,GAAG,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC/E,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAEzE,IAAI,YAAY,IAAI,UAAU,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC;QAC9D,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa,CAAC;QAC3D,MAAM,QAAQ,GAAG,UAAU;YACzB,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;YACtD,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QAE/D,sDAAsD;QACtD,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE;YACjC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,OAAO;YAChC,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;gBACjE,IAAI,KAAK,CAAC,WAAW,EAAE;oBAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;qBAC3D,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;oBAChL,UAAU,EAAE,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QACF,UAAU,CAAC,QAAQ,CAAC,CAAC;QAErB,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,uEAAuE,CAAC,CAAC;QACpG,CAAC;QAED,OAAO;YACL,cAAc,EAAE,GAAG;YACnB,WAAW,EAAE,QAAQ;YACrB,WAAW,EAAE,IAAI,EAAE,iDAAiD;YACpE,UAAU;YACV,MAAM;SACP,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;IAE7C,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,eAAe,GAAG,KAAK,CAAC;IAC5B,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO;YAAE,SAAS;QAEvB,oEAAoE;QACpE,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;YACpC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,GAAG,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,GAAG,GAAG,CAAC;gBACtE,OAAO,CAAC,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAC,EAAE,CAAC;gBACnF,cAAc,GAAG,GAAG,CAAC;gBACrB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;gBAC9C,MAAM;YACR,CAAC;QACH,CAAC;QAED,uEAAuE;QACvE,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAC5D,UAAU,IAAI,eAAe,CAAC,MAAM,CAAC;QAErC,mCAAmC;QACnC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7D,yEAAyE;YACzE,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,EAAE,CAAC;gBAC7E,eAAe,GAAG,IAAI,CAAC;YACzB,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAChG,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC;QAED,oCAAoC;QACpC,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YAC5F,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC;QAED,2DAA2D;QAC3D,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACnD,KAAK,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAC;gBACpC,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBAC/C,cAAc,GAAG,GAAG,CAAC;gBACvB,CAAC;YACH,CAAC;YAED,6CAA6C;YAC7C,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3C,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAC5C,CAAC,CAAC,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAChE,CAAC;YACF,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,eAAe,GAAG,IAAI,CAAC;YACzB,CAAC;QACH,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,IAAI,WAAgD,CAAC;IACrD,IAAI,CAAC,cAAc,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;QACxC,WAAW,GAAG,MAAM,CAAC;IACvB,CAAC;SAAM,IAAI,eAAe,EAAE,CAAC;QAC3B,WAAW,GAAG,QAAQ,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,WAAW,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,SAAS;IACT,IAAI,CAAC,cAAc,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,wFAAwF,CAAC,CAAC;IACxG,CAAC;IAED,IAAI,cAAc,IAAI,CAAC,cAAc,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;QACzD,MAAM,CAAC,IAAI,CAAC,GAAG,UAAU,+EAA+E,CAAC,CAAC;IAC5G,CAAC;IAED,IAAI,WAAW,KAAK,MAAM,IAAI,UAAU,GAAG,EAAE,EAAE,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;IAC3F,CAAC;IAED,kDAAkD;IAClD,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO;YAAE,SAAS;QAEvB,6CAA6C;QAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,wCAAwC,CAAC,IAAI,EAAE,CAAC;QACjF,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,IAAI,EAAE,CAAC;QAC3E,eAAe,IAAI,UAAU,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC;IAC5D,CAAC;IAED,IAAI,eAAe,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,GAAG,eAAe,iEAAiE,CAAC,CAAC;IACnG,CAAC;IAED,OAAO;QACL,cAAc;QACd,WAAW;QACX,WAAW,EAAE,cAAc;QAC3B,UAAU;QACV,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -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"}
|