offbyt 1.0.0 โ†’ 1.0.2

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/cli.js CHANGED
@@ -9,6 +9,7 @@ import { connectFrontendBackend } from './lib/modes/connect.js';
9
9
  import { runDoctor } from './lib/utils/doctor.js';
10
10
  import { getInteractiveSetup, displaySetupSummary } from './lib/modes/interactiveSetup.js';
11
11
  import { generateWithConfig } from './lib/modes/configBasedGenerator.js';
12
+ import { printBanner, printSection, printSuccess, printStep, printSummary, printFooter } from './lib/utils/cliFormatter.js';
12
13
 
13
14
  const program = new Command();
14
15
 
@@ -21,6 +22,15 @@ function parsePort(value) {
21
22
  return port;
22
23
  }
23
24
 
25
+ function parsePositiveInteger(value) {
26
+ const parsed = Number.parseInt(value, 10);
27
+ if (Number.isNaN(parsed) || parsed < 1) {
28
+ throw new Error('Value must be a positive integer');
29
+ }
30
+
31
+ return parsed;
32
+ }
33
+
24
34
  program
25
35
  .name('offbyt')
26
36
  .description('Hybrid Backend Generator - Offline + AI Powered')
@@ -32,8 +42,12 @@ program
32
42
  .option('--no-auto-connect', 'Skip auto-connect after generation')
33
43
  .option('--quick', 'Use default configuration (no questions)')
34
44
  .option('--no-api-detect', 'Skip automatic API detection from frontend')
45
+ .option('--no-verify', 'Skip Phase-2 backend verification (startup + health check)')
46
+ .option('--verify-timeout <ms>', 'Health-check timeout in milliseconds', parsePositiveInteger, 45000)
47
+ .option('--strict-verify', 'Fail command if Phase-2 verification does not pass')
35
48
  .action(async (projectPath, options) => {
36
49
  try {
50
+ printBanner();
37
51
  const workingPath = projectPath || process.cwd();
38
52
  let config;
39
53
 
@@ -49,7 +63,8 @@ program
49
63
  enableCaching: false,
50
64
  enableLogging: true
51
65
  };
52
- console.log(chalk.cyan('Using default configuration...\n'));
66
+ printSection('Quick Mode: Using Default Configuration');
67
+ printSuccess('Configuration ready - MongoDB + Express + Auth enabled');
53
68
  } else {
54
69
  // Interactive setup
55
70
  config = await getInteractiveSetup();
@@ -64,7 +79,7 @@ program
64
79
 
65
80
  // AUTOMATIC: Smart API detection & generation
66
81
  if (options.apiDetect !== false) {
67
- console.log(chalk.cyan('\n\n๐ŸŽฏ Running Smart API Detection...\n'));
82
+ console.log(chalk.cyan('\n\n[PIPELINE] Running Smart API Detection...\n'));
68
83
  const { generateSmartAPI } = await import('./lib/modes/generateApi.js');
69
84
  try {
70
85
  await generateSmartAPI(workingPath, { inject: true, config });
@@ -78,6 +93,48 @@ program
78
93
  }
79
94
  }
80
95
 
96
+ let shouldRunVerify = options.verify !== false;
97
+ if (options.verify !== false) {
98
+ const verifyChoice = await inquirer.prompt([
99
+ {
100
+ type: 'confirm',
101
+ name: 'runVerify',
102
+ message: 'Run post-generation health check (Phase-2)?',
103
+ default: true
104
+ }
105
+ ]);
106
+ shouldRunVerify = verifyChoice.runVerify;
107
+ }
108
+
109
+ if (shouldRunVerify) {
110
+ console.log(chalk.cyan('\n\n[VERIFY] Running Phase-2 verification...\n'));
111
+ const { verifyGeneratedBackend } = await import('./lib/utils/postGenerationVerifier.js');
112
+ const verification = await verifyGeneratedBackend(workingPath, {
113
+ timeoutMs: options.verifyTimeout,
114
+ maxAttempts: 2
115
+ });
116
+
117
+ if (verification.ok) {
118
+ console.log(chalk.green(`\n[OK] Phase-2 passed at http://localhost:${verification.port}${verification.healthEndpoint}\n`));
119
+ } else {
120
+ console.log(chalk.yellow('\n[WARN] Phase-2 verification did not fully pass.'));
121
+ console.log(chalk.yellow(` Reason: ${verification.issue}`));
122
+ if (verification.fixesApplied.length > 0) {
123
+ console.log(chalk.gray(' Auto-fixes attempted:'));
124
+ for (const fix of verification.fixesApplied) {
125
+ console.log(chalk.gray(` - ${fix}`));
126
+ }
127
+ }
128
+ console.log(chalk.gray(' You can skip this step next time using --no-verify.\n'));
129
+
130
+ if (options.strictVerify) {
131
+ throw new Error(`Phase-2 verification failed: ${verification.issue}`);
132
+ }
133
+ }
134
+ } else {
135
+ console.log(chalk.gray('\n[SKIP] Post-generation health check skipped by user choice.\n'));
136
+ }
137
+
81
138
  // Auto-connect if enabled
82
139
  if (options.autoConnect) {
83
140
  console.log(chalk.cyan('Auto-connecting frontend & backend...\n'));
@@ -189,6 +246,64 @@ program
189
246
  }
190
247
  });
191
248
 
249
+ program
250
+ .command('industry-validate [path]')
251
+ .description('Run offline Industry Mode contract validation and print report')
252
+ .option('--json', 'Print JSON output')
253
+ .action(async (projectPath, options) => {
254
+ try {
255
+ const {
256
+ runIndustryContractCheck,
257
+ printIndustryReport
258
+ } = await import('./lib/utils/industryMode.js');
259
+
260
+ const report = await runIndustryContractCheck(projectPath || process.cwd());
261
+ if (options.json) {
262
+ console.log(JSON.stringify(report, null, 2));
263
+ } else {
264
+ printIndustryReport(report);
265
+ }
266
+
267
+ process.exit(report.ok ? 0 : 1);
268
+ } catch (error) {
269
+ console.error(chalk.red('Error:', error.message));
270
+ process.exit(1);
271
+ }
272
+ });
273
+
274
+ program
275
+ .command('industry-smoke [path]')
276
+ .description('Run offline Industry Mode smoke checks and save report file')
277
+ .option('--timeout <ms>', 'Smoke timeout in milliseconds', parsePositiveInteger, 45000)
278
+ .option('--json', 'Print JSON output')
279
+ .action(async (projectPath, options) => {
280
+ try {
281
+ const {
282
+ runIndustrySmoke,
283
+ writeIndustryReport,
284
+ printIndustryReport
285
+ } = await import('./lib/utils/industryMode.js');
286
+
287
+ const workingPath = projectPath || process.cwd();
288
+ const report = await runIndustrySmoke(workingPath, {
289
+ timeoutMs: options.timeout
290
+ });
291
+
292
+ const filePath = writeIndustryReport(workingPath, report);
293
+ if (options.json) {
294
+ console.log(JSON.stringify({ ...report, reportFile: filePath }, null, 2));
295
+ } else {
296
+ printIndustryReport(report);
297
+ console.log(chalk.cyan(`Report saved: ${filePath}`));
298
+ }
299
+
300
+ process.exit(report.ok ? 0 : 1);
301
+ } catch (error) {
302
+ console.error(chalk.red('Error:', error.message));
303
+ process.exit(1);
304
+ }
305
+ });
306
+
192
307
  program.parse(process.argv);
193
308
 
194
309
  if (!process.argv.slice(2).length) {
@@ -0,0 +1,22 @@
1
+ {
2
+ "requiredContract": [
3
+ "database",
4
+ "framework",
5
+ "auth",
6
+ "resources"
7
+ ],
8
+ "minResources": 1,
9
+ "requireAuth": true,
10
+ "requiredSecurity": [
11
+ "validation",
12
+ "rateLimit",
13
+ "helmet",
14
+ "cors"
15
+ ],
16
+ "smoke": {
17
+ "checkHealth": true,
18
+ "checkResourceList": true,
19
+ "maxResources": 10,
20
+ "timeoutMs": 45000
21
+ }
22
+ }
@@ -18,7 +18,7 @@ import {
18
18
  /**
19
19
  * Complete pipeline: Frontend รขโ€ โ€™ IR รขโ€ โ€™ Backend
20
20
  */
21
- export async function offbyteWithIR(frontendPath, outputPath, options = {}) {
21
+ export async function offbytWithIR(frontendPath, outputPath, options = {}) {
22
22
  console.log('\n' + '='.repeat(70));
23
23
  console.log('รฐลธลกโ‚ฌ offbyt - IR-Based Backend Generation');
24
24
  console.log('='.repeat(70) + '\n');
@@ -303,7 +303,7 @@ export async function quickGenerate(frontendPath, options = {}) {
303
303
  const projectName = path.basename(frontendPath);
304
304
  const outputPath = `./offbyt-${projectName}`;
305
305
 
306
- return offbyteWithIR(frontendPath, outputPath, {
306
+ return offbytWithIR(frontendPath, outputPath, {
307
307
  projectName,
308
308
  ...options
309
309
  });
@@ -331,7 +331,7 @@ export async function runFromCLI(args) {
331
331
  const out = outputPath || `./offbyt-${path.basename(frontendPath)}`;
332
332
 
333
333
  try {
334
- await offbyteWithIR(frontendPath, out, {
334
+ await offbytWithIR(frontendPath, out, {
335
335
  hasAuth: true,
336
336
  projectName: path.basename(frontendPath)
337
337
  });
@@ -345,5 +345,5 @@ if (import.meta.url === `file://${process.argv[1]}`) {
345
345
  runFromCLI(process.argv.slice(2));
346
346
  }
347
347
 
348
- export default offbyteWithIR;
348
+ export default offbytWithIR;
349
349
 
@@ -1,4 +1,4 @@
1
- ๏ปฟ/**
1
+ /**
2
2
  * Configuration-Based Backend Generator
3
3
  * Generates production-level backend for selected tech stack
4
4
  */
@@ -21,61 +21,61 @@ export async function generateWithConfig(projectPath, config) {
21
21
  // Step 1: Create structure
22
22
  const step1 = ora('Creating backend structure...').start();
23
23
  createBackendStructure(backendPath, config);
24
- step1.succeed('รขล“โ€ฆ Backend structure created');
24
+ step1.succeed('Backend structure created');
25
25
 
26
26
  // Step 2: Setup database
27
27
  const step2 = ora('Setting up database configuration...').start();
28
28
  setupDatabaseConfig(backendPath, config);
29
- step2.succeed('รขล“โ€ฆ Database configured');
29
+ step2.succeed('Database configured');
30
30
 
31
31
  // Step 3: Create middleware
32
32
  const step3 = ora('Setting up middleware...').start();
33
33
  setupMiddleware(backendPath, config);
34
- step3.succeed('รขล“โ€ฆ Middleware configured');
34
+ step3.succeed('Middleware configured');
35
35
 
36
36
  // Step 4: Create authentication (if enabled)
37
37
  if (config.enableAuth) {
38
38
  const step4 = ora('Setting up authentication system...').start();
39
39
  setupAuthentication(backendPath, config);
40
- step4.succeed('รขล“โ€ฆ Authentication configured');
40
+ step4.succeed('Authentication configured');
41
41
  }
42
42
 
43
43
  // Step 5: Create main server
44
44
  const step5 = ora('Creating main server file...').start();
45
45
  createServerFile(backendPath, config);
46
- step5.succeed('รขล“โ€ฆ Server created');
46
+ step5.succeed('Server created');
47
47
 
48
48
  // Step 6: Setup Socket.io (if enabled)
49
49
  if (config.enableSocket) {
50
50
  const step6 = ora('Setting up realtime sockets...').start();
51
51
  setupSockets(backendPath, config);
52
- step6.succeed('รขล“โ€ฆ Sockets configured');
52
+ step6.succeed('Sockets configured');
53
53
  }
54
54
 
55
55
  // Step 7: Create package.json
56
56
  const step7 = ora('Creating package.json...').start();
57
57
  createPackageJson(backendPath, config);
58
- step7.succeed('รขล“โ€ฆ Dependencies configured');
58
+ step7.succeed('Dependencies configured');
59
59
 
60
60
  // Step 8: Create .env
61
61
  const step8 = ora('Creating environment configuration...').start();
62
62
  createEnvFile(backendPath, config);
63
- step8.succeed('รขล“โ€ฆ Environment files created (.env, .env.example, .gitignore)');
63
+ step8.succeed('Environment files created (.env, .env.example, .gitignore)');
64
64
 
65
65
  // Step 9: Scan frontend and generate detected resources (skip - will be done by smart API)
66
66
  const step9 = ora('Skipping sample generation (using Smart API detection instead)...').start();
67
- step9.succeed('รขล“โ€ฆ Backend structure ready for Smart API generation');
67
+ step9.succeed('Backend structure ready for Smart API generation');
68
68
 
69
69
  // Step 10: Generate SQL files for SQL databases
70
70
  if (['mysql', 'postgresql', 'sqlite'].includes(config.database)) {
71
71
  const step10 = ora('Generating SQL scripts...').start();
72
- step10.succeed(`รขล“โ€ฆ SQL scripts created in backend/sql/ (ready for ${config.database.toUpperCase()})`);
72
+ step10.succeed(`SQL scripts created in backend/sql/ (ready for ${config.database.toUpperCase()})`);
73
73
  }
74
74
 
75
- console.log(chalk.cyan('\nรฐลธลฝโ€ฐ Backend structure created!\n'));
76
- console.log(chalk.cyan('รขล“โ€ฆ Smart API detection will run automatically next...\n'));
75
+ console.log(chalk.cyan('\n[OK] Backend structure created.\n'));
76
+ console.log(chalk.cyan('[OK] Smart API detection will run automatically next...\n'));
77
77
 
78
- console.log(chalk.yellow('รฐลธโ€œย Next steps:'));
78
+ console.log(chalk.yellow('Next steps:'));
79
79
  console.log(chalk.yellow(` 1. cd ${projectPath}/backend`));
80
80
  console.log(chalk.yellow(' 2. npm install'));
81
81
  console.log(chalk.yellow(' 3. Review & update .env file:'));
@@ -95,10 +95,10 @@ export async function generateWithConfig(projectPath, config) {
95
95
  console.log(chalk.yellow(' 4. npm run dev'));
96
96
  }
97
97
 
98
- console.log(chalk.cyan('\nรฐลธโ€™ยก Tip: Never commit .env to git! Use .env.example instead.\n'));
98
+ console.log(chalk.cyan('\nTip: Never commit .env to git! Use .env.example instead.\n'));
99
99
 
100
100
  } catch (error) {
101
- console.error(chalk.red('รขยล’ Error generating backend:'), error.message);
101
+ console.error(chalk.red('Error generating backend:'), error.message);
102
102
  throw error;
103
103
  }
104
104
  }
@@ -364,9 +364,9 @@ app.use(requestLogger);
364
364
 
365
365
  // Database Connection
366
366
  connectDatabase().then(() => {
367
- console.log('รขล“โ€ฆ Database connected');
367
+ console.log('[OK] Database connected');
368
368
  }).catch(error => {
369
- console.error('รขยล’ Database connection failed:', error);
369
+ console.error('[ERR] Database connection failed:', error);
370
370
  process.exit(1);
371
371
  });
372
372
 
@@ -397,11 +397,11 @@ io.on('connection', (socket) => {
397
397
  });
398
398
 
399
399
  server.listen(PORT, () => {
400
- console.log(\`รฐลธลกโ‚ฌ Server running on http://localhost:\${PORT}\`);
400
+ console.log(\`[OK] Server running on http://localhost:\${PORT}\`);
401
401
  });`;
402
402
  } else {
403
403
  serverContent += `app.listen(PORT, () => {
404
- console.log(\`รฐลธลกโ‚ฌ Server running on http://localhost:\${PORT}\`);
404
+ console.log(\`[OK] Server running on http://localhost:\${PORT}\`);
405
405
  });`;
406
406
  }
407
407
 
@@ -430,9 +430,9 @@ await fastify.register(fastifyCors, { origin: '*' });
430
430
 
431
431
  // Database Connection
432
432
  connectDatabase().then(() => {
433
- fastify.log.info('รขล“โ€ฆ Database connected');
433
+ fastify.log.info('[OK] Database connected');
434
434
  }).catch(error => {
435
- fastify.log.error('รขยล’ Database connection failed:', error);
435
+ fastify.log.error('[ERR] Database connection failed:', error);
436
436
  process.exit(1);
437
437
  });
438
438
 
@@ -468,7 +468,7 @@ io.on('connection', (socket) => {
468
468
  serverContent += `// Start server
469
469
  try {
470
470
  await fastify.listen({ port: PORT, host: '0.0.0.0' });
471
- console.log(\`รฐลธลกโ‚ฌ Fastify server running on http://localhost:\${PORT}\`);
471
+ console.log(\`[OK] Fastify server running on http://localhost:\${PORT}\`);
472
472
  } catch (err) {
473
473
  fastify.log.error(err);
474
474
  process.exit(1);
@@ -535,7 +535,7 @@ async function bootstrap() {
535
535
  });
536
536
  });
537
537
  ` : ''}
538
- console.log(\`รฐลธลกโ‚ฌ NestJS server running on http://localhost:\${PORT}\`);
538
+ console.log(\`[OK] NestJS server running on http://localhost:\${PORT}\`);
539
539
  }
540
540
 
541
541
  bootstrap();`;
@@ -815,7 +815,7 @@ async function detectAndGenerateResources(projectPath, backendPath, config) {
815
815
  generateRoute(backendPath, resourceName, resourceInfo, config, apiAnalysis);
816
816
  generatedResources.push(resourceName);
817
817
  } catch (e) {
818
- console.warn(`รขลกย รฏยธย Skipped ${resourceName}:`, e.message);
818
+ console.warn(`[WARN] Skipped ${resourceName}:`, e.message);
819
819
  }
820
820
  });
821
821
 
@@ -847,7 +847,7 @@ async function detectAndGenerateResources(projectPath, backendPath, config) {
847
847
 
848
848
  return { resources: generatedResources };
849
849
  } catch (error) {
850
- console.warn('รขลกย รฏยธย Auto-detection error:', error.message);
850
+ console.warn('[WARN] Auto-detection error:', error.message);
851
851
  createSampleResources(backendPath, config);
852
852
  return { resources: ['User (sample)'] };
853
853
  }
@@ -2251,7 +2251,7 @@ npm run dev
2251
2251
  ## Environment Variables
2252
2252
  See \`../.env\` for required environment variables.
2253
2253
 
2254
- Generated by offbyt รขลกยก`;
2254
+ Generated by offbyt`;
2255
2255
 
2256
2256
  fs.writeFileSync(path.join(backendPath, 'README.md'), readme);
2257
2257
  }
@@ -18,36 +18,38 @@ import ora from 'ora';
18
18
  // ============================================================
19
19
  export async function connectFrontendBackend(projectPath) {
20
20
  try {
21
- console.log(chalk.cyan('\n๐Ÿ”— offbyt Auto-Connection Engine\n'));
22
- console.log(chalk.gray('Scanner: Frontend โ†’ Backend Connection Analysis\n'));
21
+ console.log(chalk.cyan('\n============================================================'));
22
+ console.log(chalk.cyan('OFFBYT AUTO-CONNECTION ENGINE'));
23
+ console.log(chalk.cyan('============================================================\n'));
24
+ console.log(chalk.gray('Scanner: Frontend -> Backend Connection Analysis\n'));
23
25
 
24
26
  const backendPath = path.join(projectPath, 'backend');
25
27
 
26
28
  // Verify project structure
27
29
  if (!fs.existsSync(backendPath)) {
28
- console.error(chalk.red('โŒ Backend not found. Run "offbyt generate" first.\n'));
30
+ console.error(chalk.red('Backend not found. Run "offbyt generate" first.\n'));
29
31
  process.exit(1);
30
32
  }
31
33
 
32
34
  // Step 1: Scan React components
33
35
  const step1 = ora('Step 1/5: Scanning React components...').start();
34
36
  const reactAnalysis = scanReactComponents(projectPath);
35
- step1.succeed(`โœ… Found ${reactAnalysis.components.length} API components`);
37
+ step1.succeed(`Found ${reactAnalysis.components.length} API components`);
36
38
 
37
39
  // Step 2: Scan backend structure
38
40
  const step2 = ora('Step 2/5: Analyzing backend routes...').start();
39
41
  const backendAnalysis = scanBackendRoutes(backendPath);
40
- step2.succeed(`โœ… Found ${backendAnalysis.routes.length} backend routes`);
42
+ step2.succeed(`Found ${backendAnalysis.routes.length} backend routes`);
41
43
 
42
44
  // Step 3: Detect mismatches
43
45
  const step3 = ora('Step 3/5: Analyzing mismatches...').start();
44
46
  const mismatches = detectMismatches(reactAnalysis, backendAnalysis);
45
- step3.succeed(`โœ… Detected ${mismatches.issues.length} issues`);
47
+ step3.succeed(`Detected ${mismatches.issues.length} issues`);
46
48
 
47
49
  // Step 4: Auto-fix issues
48
50
  const step4 = ora('Step 4/5: Auto-fixing components...').start();
49
51
  const fixResults = applyAutoFixes(projectPath, backendPath, mismatches, reactAnalysis, backendAnalysis);
50
- step4.succeed(`โœ… Fixed ${fixResults.fixed} issues`);
52
+ step4.succeed(`Fixed ${fixResults.fixed} issues`);
51
53
 
52
54
  // Detect Vite
53
55
  let isVite = false;
@@ -64,18 +66,18 @@ export async function connectFrontendBackend(projectPath) {
64
66
  // Step 5: Create/Update .env
65
67
  const step5 = ora('Step 5/5: Configuring environment...').start();
66
68
  createFrontendEnv(projectPath, backendAnalysis.serverPort, isVite);
67
- step5.succeed('โœ… .env file configured');
69
+ step5.succeed('.env file configured');
68
70
 
69
71
  // Summary
70
- console.log(chalk.green('\nโœ… Auto-Connection Complete!\n'));
71
- console.log(chalk.gray('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”'));
72
+ console.log(chalk.green('\n[OK] Auto-Connection Complete!\n'));
73
+ console.log(chalk.gray('------------------------------------------------------------'));
72
74
  console.log(chalk.white(' Components Updated:'), reactAnalysis.components.length);
73
75
  console.log(chalk.white(' Issues Fixed:'), fixResults.fixed);
74
76
  console.log(chalk.white(' API URL Configured:'), `http://localhost:${backendAnalysis.serverPort}`);
75
- console.log(chalk.gray('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n'));
77
+ console.log(chalk.gray('------------------------------------------------------------\n'));
76
78
 
77
79
  if (mismatches.issues.length > 0) {
78
- console.log(chalk.yellow('โš ๏ธ Issues Found (Auto-Fixed):\n'));
80
+ console.log(chalk.yellow('[WARN] Issues Found (Auto-Fixed):\n'));
79
81
  mismatches.issues.forEach((issue, i) => {
80
82
  console.log(chalk.gray(` ${i+1}. ${issue.type}`));
81
83
  console.log(chalk.gray(` File: ${issue.file}`));
@@ -83,13 +85,13 @@ export async function connectFrontendBackend(projectPath) {
83
85
  });
84
86
  }
85
87
 
86
- console.log(chalk.cyan('๐Ÿš€ Ready to start:\n'));
88
+ console.log(chalk.cyan('Ready to start:\n'));
87
89
  console.log(chalk.white(' Frontend:', chalk.bold(`npm start`)));
88
90
  console.log(chalk.white(' Backend:', chalk.bold(`npm start`)));
89
91
  console.log(chalk.cyan('\n'));
90
92
 
91
93
  } catch (error) {
92
- console.error(chalk.red('โŒ Connection Error:', error.message));
94
+ console.error(chalk.red('Connection Error:'), error.message);
93
95
  process.exit(1);
94
96
  }
95
97
  }
@@ -152,7 +154,7 @@ function scanReactComponents(projectPath) {
152
154
  });
153
155
  }
154
156
  } catch (error) {
155
- console.warn(chalk.gray(` โš ๏ธ Skipped: ${path.relative(projectPath, file)}`));
157
+ console.warn(chalk.gray(` [WARN] Skipped: ${path.relative(projectPath, file)}`));
156
158
  }
157
159
  });
158
160
 
@@ -306,7 +308,7 @@ function scanBackendRoutes(backendPath) {
306
308
 
307
309
  return { routes, models, serverPort };
308
310
  } catch (error) {
309
- console.warn(chalk.yellow(`โš ๏ธ Backend scan error: ${error.message}`));
311
+ console.warn(chalk.yellow(`[WARN] Backend scan error: ${error.message}`));
310
312
  return { routes: [], models: [], serverPort: 5000 };
311
313
  }
312
314
  }
@@ -581,7 +583,7 @@ function applyAutoFixes(projectPath, backendPath, mismatches, reactAnalysis, bac
581
583
  }
582
584
  }
583
585
  } catch (error) {
584
- console.warn(chalk.gray(` โš ๏ธ Could not fix: ${issue.file} - ${error.message}`));
586
+ console.warn(chalk.gray(` [WARN] Could not fix: ${issue.file} - ${error.message}`));
585
587
  }
586
588
  });
587
589
 
@@ -613,10 +615,10 @@ function applyAutoFixes(projectPath, backendPath, mismatches, reactAnalysis, bac
613
615
  function fixResponseParsing(content) {
614
616
  // Fix common response parsing patterns
615
617
 
616
- // Pattern 1: res.data.data.token โ†’ res.data.token (if response is {data: {...}})
618
+ // Pattern 1: res.data.data.token รขโ€ โ€™ res.data.token (if response is {data: {...}})
617
619
  content = content.replace(/data\.data\.(\w+)/g, 'data.$1');
618
620
 
619
- // Pattern 2: response.data.data.user โ†’ response.data.user
621
+ // Pattern 2: response.data.data.user รขโ€ โ€™ response.data.user
620
622
  content = content.replace(/response\.data\.data\.(\w+)/g, 'response.data.$1');
621
623
 
622
624
  // Pattern 3: const x = await response.json();
@@ -639,7 +641,7 @@ function fixApiUrls(content, isVite = false) {
639
641
  // Ensure API calls use environment variables for base URL
640
642
  const API_URL = isVite ? 'import.meta.env.VITE_API_URL' : 'process.env.REACT_APP_API_URL';
641
643
 
642
- // Pattern 1: fetch('/api/... โ†’ fetch(`/api/...
644
+ // Pattern 1: fetch('/api/... รขโ€ โ€™ fetch(`/api/...
643
645
  content = content.replace(
644
646
  /fetch\s*\(\s*['"`](\/api\/[^'"`]+)['"`]/g,
645
647
  `fetch(\`\${${API_URL}}$1\``
@@ -661,7 +663,7 @@ function fixApiUrls(content, isVite = false) {
661
663
  `fetch(\`\${${API_URL}}$1\``
662
664
  );
663
665
 
664
- // Pattern 3: const url = '/api/... โ†’ const url = `/api/...
666
+ // Pattern 3: const url = '/api/... รขโ€ โ€™ const url = `/api/...
665
667
  content = content.replace(
666
668
  /(const|let|var)\s+(\w+)\s*=\s*['"`](\/api\/[^'"`]+)['"`]/g,
667
669
  `$1 $2 = \`\${${API_URL}}$3\``
@@ -1020,9 +1022,9 @@ function escapeRegex(string) {
1020
1022
  /**
1021
1023
  * Parse API path to extract resource name and route path
1022
1024
  * Examples:
1023
- * /api/admin/dashboard โ†’ {resourceName: 'admin', routePath: '/dashboard'}
1024
- * /api/user/invoices โ†’ {resourceName: 'user', routePath: '/invoices'}
1025
- * /api/products/:id โ†’ {resourceName: 'products', routePath: '/:id'}
1025
+ * /api/admin/dashboard รขโ€ โ€™ {resourceName: 'admin', routePath: '/dashboard'}
1026
+ * /api/user/invoices รขโ€ โ€™ {resourceName: 'user', routePath: '/invoices'}
1027
+ * /api/products/:id รขโ€ โ€™ {resourceName: 'products', routePath: '/:id'}
1026
1028
  */
1027
1029
  function parseApiPath(apiPath) {
1028
1030
  const normalizedPath = normalizeRoutePath(apiPath);
@@ -1122,4 +1124,3 @@ router.${methodLower}('${cleanPath}', async (req, res) => {
1122
1124
  }
1123
1125
  });`;
1124
1126
  }
1125
-