@merlean/analyzer 2.1.0 → 2.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.
Files changed (3) hide show
  1. package/bin/cli.js +47 -12
  2. package/lib/analyzer.js +1231 -123
  3. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -23,7 +23,8 @@ function parseArgs() {
23
23
  path: null,
24
24
  name: null,
25
25
  backend: DEFAULT_BACKEND,
26
- output: null
26
+ output: null,
27
+ mergeWith: null // Existing siteId to merge into
27
28
  };
28
29
 
29
30
  for (let i = 0; i < args.length; i++) {
@@ -35,6 +36,8 @@ function parseArgs() {
35
36
  options.backend = args[++i];
36
37
  } else if (arg === '--output' || arg === '-o') {
37
38
  options.output = args[++i];
39
+ } else if (arg === '--merge-with' || arg === '-m') {
40
+ options.mergeWith = args[++i];
38
41
  } else if (arg === '--help' || arg === '-h') {
39
42
  printHelp();
40
43
  process.exit(0);
@@ -58,7 +61,8 @@ Arguments:
58
61
  <path> Path to codebase (default: current directory)
59
62
 
60
63
  Options:
61
- --name, -n <name> Site name (required)
64
+ --name, -n <name> Site name (required for new analysis)
65
+ --merge-with, -m <siteId> Merge into existing site map (appends routes/forms/actions)
62
66
  --backend, -b <url> Backend URL (default: ${DEFAULT_BACKEND})
63
67
  --output, -o <file> Save site map locally (optional)
64
68
  --help, -h Show this help
@@ -70,6 +74,9 @@ Examples:
70
74
  # Analyze specific path
71
75
  npx @merlean/analyzer ./my-app --name "My App"
72
76
 
77
+ # Merge another frontend into existing site map
78
+ npx @merlean/analyzer ./admin-panel --merge-with site_abc123
79
+
73
80
  # Use custom backend (for local dev)
74
81
  npx @merlean/analyzer --name "My App" --backend http://localhost:3004
75
82
  `);
@@ -81,8 +88,8 @@ async function main() {
81
88
  const options = parseArgs();
82
89
 
83
90
  // Validate required args
84
- if (!options.name) {
85
- console.error('❌ Error: --name is required');
91
+ if (!options.name && !options.mergeWith) {
92
+ console.error('❌ Error: --name is required (or use --merge-with to merge into existing site)');
86
93
  console.log(' Run with --help for usage');
87
94
  process.exit(1);
88
95
  }
@@ -96,22 +103,41 @@ async function main() {
96
103
  }
97
104
 
98
105
  console.log(`📁 Scanning: ${codebasePath}`);
99
- console.log(`📛 Site name: ${options.name}`);
106
+ if (options.mergeWith) {
107
+ console.log(`🔗 Merging into: ${options.mergeWith}`);
108
+ if (options.name) {
109
+ console.log(`📛 Site name: ${options.name} (will update existing)`);
110
+ }
111
+ } else {
112
+ console.log(`📛 Site name: ${options.name}`);
113
+ }
100
114
 
101
115
  try {
102
116
  // Scan codebase locally
103
- const fileContents = await scanCodebase(codebasePath);
117
+ const scanResult = await scanCodebase(codebasePath);
118
+ // Handle both old format (array) and new format (object with files + preExtractedRoutes)
119
+ const fileContents = Array.isArray(scanResult) ? scanResult : scanResult.files;
120
+ const preExtractedRoutes = Array.isArray(scanResult) ? [] : (scanResult.preExtractedRoutes || []);
104
121
 
105
122
  console.log(`\n📤 Uploading to backend for analysis...`);
106
123
 
124
+ // Build request body
125
+ const requestBody = {
126
+ siteName: options.name,
127
+ files: fileContents,
128
+ preExtractedRoutes // Include convention-based routes
129
+ };
130
+
131
+ // Add merge parameter if specified
132
+ if (options.mergeWith) {
133
+ requestBody.mergeWithSiteId = options.mergeWith;
134
+ }
135
+
107
136
  // Send to backend for LLM analysis
108
137
  const response = await fetch(`${options.backend}/api/analyze`, {
109
138
  method: 'POST',
110
139
  headers: { 'Content-Type': 'application/json' },
111
- body: JSON.stringify({
112
- siteName: options.name,
113
- files: fileContents
114
- })
140
+ body: JSON.stringify(requestBody)
115
141
  });
116
142
 
117
143
  if (!response.ok) {
@@ -121,13 +147,22 @@ async function main() {
121
147
 
122
148
  const result = await response.json();
123
149
 
124
- console.log('\n✅ Analysis complete!');
125
- console.log('\n📊 Summary:');
150
+ if (options.mergeWith) {
151
+ console.log('\n Merge complete!');
152
+ console.log('\n📊 Updated Summary:');
153
+ } else {
154
+ console.log('\n✅ Analysis complete!');
155
+ console.log('\n📊 Summary:');
156
+ }
126
157
  console.log(` Site ID: ${result.siteId}`);
127
158
  console.log(` Framework: ${result.framework || 'Unknown'}`);
128
159
  console.log(` Routes: ${result.routes?.length || 0}`);
129
160
  console.log(` Forms: ${result.forms?.length || 0}`);
130
161
  console.log(` Actions: ${result.actions?.length || 0}`);
162
+
163
+ if (result.merged) {
164
+ console.log(`\n 📎 Merged from: ${result.merged.sourcesCount} source(s)`);
165
+ }
131
166
 
132
167
  // Save locally if requested
133
168
  if (options.output) {