@merlean/analyzer 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/analyzer.js +134 -26
  2. package/package.json +1 -1
package/lib/analyzer.js CHANGED
@@ -1,23 +1,32 @@
1
1
  /**
2
- * Codebase Scanner
2
+ * Frontend-focused Codebase Scanner
3
3
  *
4
- * Scans codebase and prepares file contents for backend analysis.
5
- * NO LLM calls here - that happens on the backend.
4
+ * Scans FRONTEND code to learn how it communicates with the backend.
5
+ * Extracts: fetch(), axios, $.ajax, API calls, form submissions
6
+ *
7
+ * This is what the bot needs - it runs in the browser and should know
8
+ * what API calls the frontend already makes.
6
9
  */
7
10
 
8
11
  const fs = require('fs');
9
12
  const path = require('path');
10
13
  const { glob } = require('glob');
11
14
 
12
- // File patterns to scan
13
- const SCAN_PATTERNS = [
15
+ // Frontend file patterns (prioritize frontend code)
16
+ const FRONTEND_PATTERNS = [
14
17
  '**/*.js',
15
- '**/*.ts',
16
18
  '**/*.jsx',
19
+ '**/*.ts',
17
20
  '**/*.tsx',
18
- '**/*.php',
19
- '**/*.py',
20
- '**/*.rb'
21
+ '**/*.vue',
22
+ '**/*.svelte',
23
+ '**/app.js',
24
+ '**/main.js',
25
+ '**/index.js',
26
+ '**/*api*.js',
27
+ '**/*service*.js',
28
+ '**/*fetch*.js',
29
+ '**/*http*.js'
21
30
  ];
22
31
 
23
32
  // Directories to ignore
@@ -30,23 +39,28 @@ const IGNORE_PATTERNS = [
30
39
  '**/__pycache__/**',
31
40
  '**/venv/**',
32
41
  '**/*.min.js',
33
- '**/*.map'
42
+ '**/*.map',
43
+ '**/server.js', // Skip backend files
44
+ '**/server/**',
45
+ '**/backend/**',
46
+ '**/api/**', // Skip backend API folders
47
+ '**/controllers/**'
34
48
  ];
35
49
 
36
50
  // Keywords to prioritize files
37
51
  const PRIORITY_KEYWORDS = [
38
- 'route', 'router', 'controller', 'api', 'endpoint',
39
- 'form', 'submit', 'action', 'handler', 'service'
52
+ 'fetch', 'axios', 'api', 'service', 'http', 'request',
53
+ 'ajax', 'client', 'frontend', 'app', 'main', 'store'
40
54
  ];
41
55
 
42
56
  /**
43
- * Scan codebase and collect file contents
57
+ * Scan codebase and collect frontend API patterns
44
58
  */
45
59
  async function scanCodebase(codebasePath) {
46
- console.log(' Scanning files...');
60
+ console.log(' Scanning frontend files...');
47
61
 
48
62
  // Get files to scan
49
- const files = await glob(SCAN_PATTERNS, {
63
+ const files = await glob(FRONTEND_PATTERNS, {
50
64
  cwd: codebasePath,
51
65
  ignore: IGNORE_PATTERNS,
52
66
  absolute: true
@@ -54,42 +68,136 @@ async function scanCodebase(codebasePath) {
54
68
 
55
69
  console.log(` Found ${files.length} files`);
56
70
 
57
- // Prioritize and limit files
71
+ // Prioritize frontend-focused files
58
72
  const prioritizedFiles = prioritizeFiles(files, codebasePath);
59
- const filesToAnalyze = prioritizedFiles.slice(0, 50); // Limit for performance
73
+ const filesToAnalyze = prioritizedFiles.slice(0, 30); // Fewer files, but more content
60
74
 
61
- console.log(` Preparing ${filesToAnalyze.length} priority files...`);
75
+ console.log(` Analyzing ${filesToAnalyze.length} frontend files...`);
62
76
 
63
- // Read and prepare file contents
77
+ // Read and extract API patterns from files
64
78
  const fileContents = [];
65
79
  for (const file of filesToAnalyze) {
66
80
  try {
67
81
  const content = fs.readFileSync(file, 'utf-8');
68
82
  const relativePath = path.relative(codebasePath, file);
69
83
 
70
- // Limit content per file
71
- const truncatedContent = content.slice(0, 3000);
84
+ // Extract API calls from the file
85
+ const extracted = extractApiPatterns(content, relativePath);
72
86
 
73
- fileContents.push({
74
- path: relativePath,
75
- content: truncatedContent
76
- });
87
+ if (extracted.hasApiCalls) {
88
+ fileContents.push({
89
+ path: relativePath,
90
+ content: extracted.content
91
+ });
92
+ }
77
93
  } catch (error) {
78
94
  // Skip files that can't be read
79
95
  }
80
96
  }
81
97
 
98
+ console.log(` Found API patterns in ${fileContents.length} files`);
99
+
82
100
  return fileContents;
83
101
  }
84
102
 
85
103
  /**
86
- * Prioritize files based on keywords in path/name
104
+ * Extract API call patterns from file content
105
+ */
106
+ function extractApiPatterns(content, filePath) {
107
+ const apiPatterns = [];
108
+ const lines = content.split('\n');
109
+
110
+ // Patterns that indicate API calls
111
+ const patterns = [
112
+ // fetch() calls
113
+ { regex: /fetch\s*\(\s*[`'"](.*?)[`'"]/g, type: 'fetch' },
114
+ { regex: /fetch\s*\(\s*`([^`]*)`/g, type: 'fetch-template' },
115
+ { regex: /fetch\s*\(\s*(['"])?\/api\//g, type: 'fetch-api' },
116
+
117
+ // axios calls
118
+ { regex: /axios\.(get|post|put|patch|delete)\s*\(\s*[`'"](.*?)[`'"]/g, type: 'axios' },
119
+ { regex: /axios\s*\(\s*\{[^}]*url\s*:\s*[`'"](.*?)[`'"]/g, type: 'axios-config' },
120
+
121
+ // jQuery ajax
122
+ { regex: /\$\.(ajax|get|post)\s*\(\s*[`'"](.*?)[`'"]/g, type: 'jquery' },
123
+
124
+ // Generic API URLs
125
+ { regex: /['"`](\/api\/[^'"`\s]+)['"`]/g, type: 'api-url' },
126
+ { regex: /['"`](https?:\/\/[^'"`\s]*\/api[^'"`\s]*)['"`]/g, type: 'full-url' },
127
+
128
+ // Method + URL patterns
129
+ { regex: /(GET|POST|PUT|PATCH|DELETE)\s*[,:]?\s*['"`](\/[^'"`]+)['"`]/gi, type: 'method-url' },
130
+ ];
131
+
132
+ let hasApiCalls = false;
133
+ const extractedBlocks = [];
134
+
135
+ // Line-by-line extraction with context
136
+ for (let i = 0; i < lines.length; i++) {
137
+ const line = lines[i];
138
+
139
+ // Check for API patterns
140
+ const hasPattern = patterns.some(p => p.regex.test(line));
141
+ // Reset regex lastIndex
142
+ patterns.forEach(p => p.regex.lastIndex = 0);
143
+
144
+ // Also check for common API keywords
145
+ const hasKeyword = /fetch|axios|\.ajax|\.get\(|\.post\(|\.put\(|\.delete\(|\/api\/|endpoint|baseURL/i.test(line);
146
+
147
+ if (hasPattern || hasKeyword) {
148
+ hasApiCalls = true;
149
+
150
+ // Get context: 3 lines before and 5 lines after
151
+ const startLine = Math.max(0, i - 3);
152
+ const endLine = Math.min(lines.length - 1, i + 5);
153
+
154
+ const block = lines.slice(startLine, endLine + 1)
155
+ .map((l, idx) => `${startLine + idx + 1}: ${l}`)
156
+ .join('\n');
157
+
158
+ extractedBlocks.push(block);
159
+
160
+ // Skip ahead to avoid duplicates
161
+ i = endLine;
162
+ }
163
+ }
164
+
165
+ // If we found API patterns, return extracted content
166
+ if (hasApiCalls && extractedBlocks.length > 0) {
167
+ return {
168
+ hasApiCalls: true,
169
+ content: `// File: ${filePath}\n// API patterns found:\n\n${extractedBlocks.join('\n\n// ---\n\n')}`
170
+ };
171
+ }
172
+
173
+ // Fallback: include first 5000 chars if file looks relevant
174
+ if (/api|fetch|axios|service|http/i.test(filePath)) {
175
+ return {
176
+ hasApiCalls: true,
177
+ content: `// File: ${filePath}\n${content.slice(0, 5000)}`
178
+ };
179
+ }
180
+
181
+ return { hasApiCalls: false, content: '' };
182
+ }
183
+
184
+ /**
185
+ * Prioritize frontend files based on keywords
87
186
  */
88
187
  function prioritizeFiles(files, basePath) {
89
188
  return files.sort((a, b) => {
90
189
  const aPath = path.relative(basePath, a).toLowerCase();
91
190
  const bPath = path.relative(basePath, b).toLowerCase();
92
191
 
192
+ // Deprioritize test files
193
+ if (aPath.includes('test') || aPath.includes('spec')) return 1;
194
+ if (bPath.includes('test') || bPath.includes('spec')) return -1;
195
+
196
+ // Prioritize src/frontend folders
197
+ if (aPath.includes('src/') || aPath.includes('frontend/')) {
198
+ if (!bPath.includes('src/') && !bPath.includes('frontend/')) return -1;
199
+ }
200
+
93
201
  const aScore = PRIORITY_KEYWORDS.reduce((score, kw) =>
94
202
  aPath.includes(kw) ? score + 1 : score, 0);
95
203
  const bScore = PRIORITY_KEYWORDS.reduce((score, kw) =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@merlean/analyzer",
3
- "version": "1.1.1",
3
+ "version": "2.0.0",
4
4
  "description": "AI Bot codebase analyzer - generates site maps for AI assistant integration",
5
5
  "keywords": ["ai", "bot", "analyzer", "claude", "anthropic", "widget"],
6
6
  "author": "zmaren",