offbyt 1.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 (103) hide show
  1. package/README.md +2 -0
  2. package/cli/index.js +2 -0
  3. package/cli.js +206 -0
  4. package/core/detector/detectAxios.js +107 -0
  5. package/core/detector/detectFetch.js +148 -0
  6. package/core/detector/detectForms.js +55 -0
  7. package/core/detector/detectSocket.js +341 -0
  8. package/core/generator/generateControllers.js +17 -0
  9. package/core/generator/generateModels.js +25 -0
  10. package/core/generator/generateRoutes.js +17 -0
  11. package/core/generator/generateServer.js +18 -0
  12. package/core/generator/generateSocket.js +160 -0
  13. package/core/index.js +14 -0
  14. package/core/ir/IRTypes.js +25 -0
  15. package/core/ir/buildIR.js +83 -0
  16. package/core/parser/parseJS.js +26 -0
  17. package/core/parser/parseTS.js +27 -0
  18. package/core/rules/relationRules.js +38 -0
  19. package/core/rules/resourceRules.js +32 -0
  20. package/core/rules/schemaInference.js +26 -0
  21. package/core/scanner/scanProject.js +58 -0
  22. package/deploy/cloudflare.js +41 -0
  23. package/deploy/cloudflareWorker.js +122 -0
  24. package/deploy/connect.js +198 -0
  25. package/deploy/flyio.js +51 -0
  26. package/deploy/index.js +322 -0
  27. package/deploy/netlify.js +29 -0
  28. package/deploy/railway.js +215 -0
  29. package/deploy/render.js +195 -0
  30. package/deploy/utils.js +383 -0
  31. package/deploy/vercel.js +29 -0
  32. package/index.js +18 -0
  33. package/lib/generator/advancedCrudGenerator.js +475 -0
  34. package/lib/generator/crudCodeGenerator.js +486 -0
  35. package/lib/generator/irBasedGenerator.js +360 -0
  36. package/lib/ir-builder/index.js +16 -0
  37. package/lib/ir-builder/irBuilder.js +330 -0
  38. package/lib/ir-builder/rulesEngine.js +353 -0
  39. package/lib/ir-builder/templateEngine.js +193 -0
  40. package/lib/ir-builder/templates/index.js +14 -0
  41. package/lib/ir-builder/templates/model.template.js +47 -0
  42. package/lib/ir-builder/templates/routes-generic.template.js +66 -0
  43. package/lib/ir-builder/templates/routes-user.template.js +105 -0
  44. package/lib/ir-builder/templates/routes.template.js +102 -0
  45. package/lib/ir-builder/templates/validation.template.js +15 -0
  46. package/lib/ir-integration.js +349 -0
  47. package/lib/modes/benchmark.js +162 -0
  48. package/lib/modes/configBasedGenerator.js +2258 -0
  49. package/lib/modes/connect.js +1125 -0
  50. package/lib/modes/doctorAi.js +172 -0
  51. package/lib/modes/generateApi.js +435 -0
  52. package/lib/modes/interactiveSetup.js +548 -0
  53. package/lib/modes/offline.clean.js +14 -0
  54. package/lib/modes/offline.enhanced.js +787 -0
  55. package/lib/modes/offline.js +295 -0
  56. package/lib/modes/offline.v2.js +13 -0
  57. package/lib/modes/sync.js +629 -0
  58. package/lib/scanner/apiEndpointExtractor.js +387 -0
  59. package/lib/scanner/authPatternDetector.js +54 -0
  60. package/lib/scanner/frontendScanner.js +642 -0
  61. package/lib/utils/apiClientGenerator.js +242 -0
  62. package/lib/utils/apiScanner.js +95 -0
  63. package/lib/utils/codeInjector.js +350 -0
  64. package/lib/utils/doctor.js +381 -0
  65. package/lib/utils/envGenerator.js +36 -0
  66. package/lib/utils/loadTester.js +61 -0
  67. package/lib/utils/performanceAnalyzer.js +298 -0
  68. package/lib/utils/resourceDetector.js +281 -0
  69. package/package.json +20 -0
  70. package/templates/.env.template +31 -0
  71. package/templates/advanced.model.template.js +201 -0
  72. package/templates/advanced.route.template.js +341 -0
  73. package/templates/auth.middleware.template.js +87 -0
  74. package/templates/auth.routes.template.js +238 -0
  75. package/templates/auth.user.model.template.js +78 -0
  76. package/templates/cache.middleware.js +34 -0
  77. package/templates/chat.models.template.js +260 -0
  78. package/templates/chat.routes.template.js +478 -0
  79. package/templates/compression.middleware.js +19 -0
  80. package/templates/database.config.js +74 -0
  81. package/templates/errorHandler.middleware.js +54 -0
  82. package/templates/express/controller.ejs +26 -0
  83. package/templates/express/model.ejs +9 -0
  84. package/templates/express/route.ejs +18 -0
  85. package/templates/express/server.ejs +16 -0
  86. package/templates/frontend.env.template +14 -0
  87. package/templates/model.template.js +86 -0
  88. package/templates/package.production.json +51 -0
  89. package/templates/package.template.json +41 -0
  90. package/templates/pagination.utility.js +110 -0
  91. package/templates/production.server.template.js +233 -0
  92. package/templates/rateLimiter.middleware.js +36 -0
  93. package/templates/requestLogger.middleware.js +19 -0
  94. package/templates/response.helper.js +179 -0
  95. package/templates/route.template.js +130 -0
  96. package/templates/security.middleware.js +78 -0
  97. package/templates/server.template.js +91 -0
  98. package/templates/socket.server.template.js +433 -0
  99. package/templates/utils.helper.js +157 -0
  100. package/templates/validation.middleware.js +63 -0
  101. package/templates/validation.schema.js +128 -0
  102. package/utils/fileWriter.js +15 -0
  103. package/utils/logger.js +18 -0
@@ -0,0 +1,787 @@
1
+ /**
2
+ * Enhanced Offline Mode v2.0
3
+ * Production-Ready Backend Generation with:
4
+ * - Advanced CRUD operations
5
+ * - Pagination, filtering, sorting, search
6
+ * - Multiple middleware layers
7
+ * - Proper validation and error handling
8
+ * - Database configuration
9
+ * - Bulk operations
10
+ */
11
+
12
+ import path from 'path';
13
+ import fs from 'fs';
14
+ import { fileURLToPath } from 'url';
15
+ import { exec } from 'child_process';
16
+ import { promisify } from 'util';
17
+ import chalk from 'chalk';
18
+ import ora from 'ora';
19
+ import { scanFrontendCode, generateRoutesFromAPICalls, buildHybridIR } from '../scanner/frontendScanner.js';
20
+ import { detectAuthPatterns } from '../scanner/authPatternDetector.js';
21
+ import { extractAllApiEndpoints, getDefaultFieldsForResource } from '../scanner/apiEndpointExtractor.js';
22
+ import { generateAdvancedCrudModel, generateAdvancedCrudRoutes } from '../generator/advancedCrudGenerator.js';
23
+ import { generateAuthEnv } from '../utils/envGenerator.js';
24
+ import { generateSocketBackend, generateServerWithSocket, addSocketDependencies } from '../../core/generator/generateSocket.js';
25
+ import { socketServerTemplate } from '../../templates/socket.server.template.js';
26
+ import { messageModelTemplate, conversationModelTemplate } from '../../templates/chat.models.template.js';
27
+ import { chatRoutesTemplate } from '../../templates/chat.routes.template.js';
28
+
29
+ const execAsync = promisify(exec);
30
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
31
+ const TEMPLATES_DIR = path.join(__dirname, '../../templates');
32
+
33
+ /**
34
+ * Main Enhanced Offline Mode Function
35
+ */
36
+ export async function enhancedOfflineMode(projectPath) {
37
+ try {
38
+ console.log(chalk.cyan('\n🚀 offbyt - Production-Ready Backend Generation v2.0\n'));
39
+ console.log(chalk.gray('Mode: Enterprise Full Auto-Generation\n'));
40
+
41
+ const backendPath = path.join(projectPath, 'backend');
42
+
43
+ // ========================================================
44
+ // STEP 1: CREATE BACKEND STRUCTURE
45
+ // ========================================================
46
+ const step1 = ora('Step 1/9: Creating production backend structure...').start();
47
+ createAdvancedBackendStructure(backendPath);
48
+ step1.succeed('✅ Backend structure created');
49
+
50
+ // ========================================================
51
+ // STEP 2: SCAN FRONTEND
52
+ // ========================================================
53
+ const step2 = ora('Step 2/9: Scanning frontend for APIs...').start();
54
+ const apiCalls = scanFrontendCode(projectPath);
55
+ step2.succeed(`✅ Found ${apiCalls.length} API calls`);
56
+
57
+ // ========================================================
58
+ // STEP 3: ANALYZE PATTERNS
59
+ // ========================================================
60
+ const step3 = ora('Step 3/9: Analyzing architecture patterns...').start();
61
+
62
+ const srcPath = path.join(projectPath, 'src');
63
+ const scanRoot = fs.existsSync(srcPath) ? srcPath : projectPath;
64
+ const frontendContent = readAllFilesRecursive(scanRoot).join('\n');
65
+
66
+ const authPatterns = detectAuthPatterns(frontendContent, apiCalls);
67
+ const hasAuth = authPatterns.hasSignup || authPatterns.hasLogin || authPatterns.hasProfile;
68
+
69
+ // Build hybrid IR with socket detection
70
+ const ir = await buildHybridIR(projectPath);
71
+ const socketDetection = ir.socketDetection || { hasSocket: false, hasChat: false };
72
+
73
+ const allResources = extractAllApiEndpoints(frontendContent, apiCalls);
74
+ const nonAuthResources = Object.fromEntries(
75
+ Object.entries(allResources).filter(([key]) => key !== 'auth' && key !== 'api' && key !== 'health' && key !== 'status' && key !== 'chat')
76
+ );
77
+
78
+ if (hasAuth) {
79
+ console.log(chalk.blue(` 🔐 Auth: ${authPatterns.hasSignup ? '✓Signup ' : ''}${authPatterns.hasLogin ? '✓Login ' : ''}${authPatterns.hasProfile ? '✓Profile' : ''}`));
80
+ }
81
+ if (socketDetection.hasSocket) {
82
+ console.log(chalk.magenta(` 💬 Real-time: ${socketDetection.socketType || 'Socket.io'}${socketDetection.hasChat ? ' + Chat' : ''}${socketDetection.rooms ? ' + Rooms' : ''}${socketDetection.presence ? ' + Presence' : ''}`));
83
+ }
84
+ if (Object.keys(nonAuthResources).length > 0) {
85
+ console.log(chalk.cyan(` 📊 Resources: ${Object.keys(nonAuthResources).join(', ')}`));
86
+ }
87
+ step3.succeed('✅ Architecture analyzed');
88
+
89
+ // ========================================================
90
+ // STEP 4: CREATE CONFIGURATIONS
91
+ // ========================================================
92
+ const step4 = ora('Step 4/9: Setting up configurations...').start();
93
+
94
+ // Copy config files
95
+ copyConfigFiles(backendPath);
96
+
97
+ // Copy utilities
98
+ copyUtilityFiles(backendPath);
99
+
100
+ step4.succeed('✅ Configuration files created');
101
+
102
+ // ========================================================
103
+ // STEP 5: SETUP MIDDLEWARE
104
+ // ========================================================
105
+ const step5 = ora('Step 5/9: Configuring middleware layers...').start();
106
+
107
+ copyAdvancedMiddleware(backendPath, hasAuth);
108
+
109
+ step5.succeed('✅ Middleware configured');
110
+
111
+ // ========================================================
112
+ // STEP 6: GENERATE MODELS & ROUTES
113
+ // ========================================================
114
+ const step6 = ora('Step 6/9: Generating CRUD models and routes...').start();
115
+ const generatedResources = [];
116
+
117
+ for (const [resourceName, resource] of Object.entries(nonAuthResources)) {
118
+ if (resourceName === 'api') continue;
119
+
120
+ try {
121
+ const fields = resource.fields && resource.fields.length > 0
122
+ ? Array.from(resource.fields)
123
+ : getDefaultFieldsForResource(resourceName);
124
+
125
+ // Generate Model
126
+ const modelContent = generateAdvancedCrudModel(
127
+ resourceName,
128
+ fields,
129
+ hasAuth,
130
+ resource.relations || []
131
+ );
132
+
133
+ const modelName = resourceName.charAt(0).toUpperCase() + resourceName.slice(1).replace(/s$/, '');
134
+ const modelPath = path.join(backendPath, 'models', `${modelName}.js`);
135
+ const modelsDir = path.dirname(modelPath);
136
+ if (!fs.existsSync(modelsDir)) fs.mkdirSync(modelsDir, { recursive: true });
137
+ fs.writeFileSync(modelPath, modelContent);
138
+
139
+ // Generate Routes
140
+ const actions = resource.actions || [];
141
+ const routesContent = generateAdvancedCrudRoutes(
142
+ resourceName,
143
+ fields,
144
+ hasAuth,
145
+ resource.relations || [],
146
+ actions
147
+ );
148
+
149
+ const routesPath = path.join(backendPath, 'routes', `${resourceName}.routes.js`);
150
+ const routesDir = path.dirname(routesPath);
151
+ if (!fs.existsSync(routesDir)) fs.mkdirSync(routesDir, { recursive: true });
152
+ fs.writeFileSync(routesPath, routesContent);
153
+
154
+ generatedResources.push(resourceName);
155
+ } catch (error) {
156
+ console.warn(`⚠️ Failed to generate ${resourceName}: ${error.message}`);
157
+ }
158
+ }
159
+
160
+ step6.succeed(`✅ Generated ${generatedResources.length} advanced CRUD resources`);
161
+
162
+ // ========================================================
163
+ // STEP 7: GENERATE AUTH SETUP (if needed)
164
+ // ========================================================
165
+ const step7 = ora('Step 7/10: Setting up authentication...').start();
166
+
167
+ if (hasAuth) {
168
+ generateAuthSetup(backendPath);
169
+ step7.succeed('✅ Authentication configured');
170
+ } else {
171
+ step7.succeed('✅ No authentication needed');
172
+ }
173
+
174
+ //========================================================
175
+ // STEP 7.5: GENERATE SOCKET.IO CHAT (if detected)
176
+ // ========================================================
177
+ let socketGenerated = false;
178
+
179
+ if (socketDetection.hasSocket || socketDetection.hasChat) {
180
+ const step7_5 = ora('Step 7.5/10: Generating Socket.io chat backend...').start();
181
+
182
+ try {
183
+ // Create socket directory
184
+ const socketDir = path.join(backendPath, 'socket');
185
+ if (!fs.existsSync(socketDir)) {
186
+ fs.mkdirSync(socketDir, { recursive: true });
187
+ }
188
+
189
+ // Generate Socket.io server
190
+ fs.writeFileSync(
191
+ path.join(socketDir, 'index.js'),
192
+ socketServerTemplate
193
+ );
194
+
195
+ // Generate chat models
196
+ fs.writeFileSync(
197
+ path.join(backendPath, 'models', 'Message.js'),
198
+ messageModelTemplate
199
+ );
200
+ fs.writeFileSync(
201
+ path.join(backendPath, 'models', 'Conversation.js'),
202
+ conversationModelTemplate
203
+ );
204
+
205
+ // Generate chat routes
206
+ fs.writeFileSync(
207
+ path.join(backendPath, 'routes', 'chat.routes.js'),
208
+ chatRoutesTemplate
209
+ );
210
+
211
+ socketGenerated = true;
212
+
213
+ const features = [];
214
+ if (socketDetection.hasChat) features.push('Messaging');
215
+ if (socketDetection.rooms) features.push('Rooms');
216
+ if (socketDetection.presence) features.push('Presence');
217
+ features.push('Real-time events');
218
+
219
+ step7_5.succeed(`✅ Socket.io generated (${features.join(', ')})`);
220
+ } catch (error) {
221
+ step7_5.fail(`❌ Failed to generate Socket.io: ${error.message}`);
222
+ }
223
+ }
224
+
225
+ // ========================================================
226
+ // STEP 8: GENERATE SERVER & CONFIGURATION
227
+ // ========================================================
228
+ const step8 = ora('Step 8/10: Generating production server...').start();
229
+
230
+ generateProductionServer(backendPath, generatedResources, hasAuth, socketGenerated);
231
+ generateEnvFile(backendPath, hasAuth, socketGenerated);
232
+ generatePackageJson(backendPath, socketGenerated);
233
+ generateReadme(backendPath, generatedResources, hasAuth, socketGenerated);
234
+
235
+ step8.succeed('✅ Server and configuration generated');
236
+
237
+ // ========================================================
238
+ // STEP 9: INSTALL DEPENDENCIES
239
+ // ========================================================
240
+ const step9 = ora('Step 9/10: Installing dependencies (this may take a minute)...').start();
241
+
242
+ try {
243
+ await installDependencies(backendPath);
244
+ step9.succeed('✅ Dependencies installed successfully');
245
+ } catch (error) {
246
+ step9.warn('⚠️ npm install completed with warnings (backend is ready)');
247
+ }
248
+
249
+ // ========================================================
250
+ // SUCCESS
251
+ // ========================================================
252
+ console.log(chalk.green.bold('\n✨ Production Backend Generated Successfully!\n'));
253
+ printCompletionInfo(backendPath, hasAuth, generatedResources, socketGenerated);
254
+
255
+ } catch (error) {
256
+ console.error(chalk.red('\n❌ Generation Failed:'), error.message);
257
+ process.exit(1);
258
+ }
259
+ }
260
+
261
+ /**
262
+ * Create Advanced Backend Directory Structure
263
+ */
264
+ function createAdvancedBackendStructure(backendPath) {
265
+ const dirs = [
266
+ 'models',
267
+ 'routes',
268
+ 'middleware',
269
+ 'config',
270
+ 'utils',
271
+ 'controllers', // For future use
272
+ 'validators', // For future use
273
+ 'services' // For future use
274
+ ];
275
+
276
+ for (const dir of dirs) {
277
+ const dirPath = path.join(backendPath, dir);
278
+ if (!fs.existsSync(dirPath)) {
279
+ fs.mkdirSync(dirPath, { recursive: true });
280
+ }
281
+ }
282
+ }
283
+
284
+ /**
285
+ * Copy Configuration Files
286
+ */
287
+ function copyConfigFiles(backendPath) {
288
+ const configDir = path.join(backendPath, 'config');
289
+
290
+ // Database config
291
+ const dbConfig = fs.readFileSync(
292
+ path.join(TEMPLATES_DIR, 'database.config.js'),
293
+ 'utf8'
294
+ );
295
+ fs.writeFileSync(path.join(configDir, 'database.js'), dbConfig);
296
+ }
297
+
298
+ /**
299
+ * Copy Utility Files
300
+ */
301
+ function copyUtilityFiles(backendPath) {
302
+ const utilsDir = path.join(backendPath, 'utils');
303
+
304
+ // Helpers
305
+ const helpers = fs.readFileSync(
306
+ path.join(TEMPLATES_DIR, 'utils.helper.js'),
307
+ 'utf8'
308
+ );
309
+ fs.writeFileSync(path.join(utilsDir, 'helper.js'), helpers);
310
+
311
+ // Pagination
312
+ const pagination = fs.readFileSync(
313
+ path.join(TEMPLATES_DIR, 'pagination.utility.js'),
314
+ 'utf8'
315
+ );
316
+ fs.writeFileSync(path.join(utilsDir, 'pagination.js'), pagination);
317
+ }
318
+
319
+ /**
320
+ * Copy Advanced Middleware
321
+ */
322
+ function copyAdvancedMiddleware(backendPath, hasAuth) {
323
+ const middlewareDir = path.join(backendPath, 'middleware');
324
+
325
+ const middlewares = [
326
+ 'errorHandler.middleware.js',
327
+ 'requestLogger.middleware.js',
328
+ 'security.middleware.js',
329
+ 'validation.schema.js',
330
+ 'cache.middleware.js',
331
+ 'rateLimiter.middleware.js',
332
+ 'compression.middleware.js'
333
+ ];
334
+
335
+ for (const mw of middlewares) {
336
+ try {
337
+ const source = fs.readFileSync(
338
+ path.join(TEMPLATES_DIR, mw),
339
+ 'utf8'
340
+ );
341
+ const target = mw.replace('.middleware', '').replace('.schema', '');
342
+ fs.writeFileSync(path.join(middlewareDir, target), source);
343
+ } catch (error) {
344
+ // File might not exist - that's okay
345
+ }
346
+ }
347
+
348
+ // Auth middleware
349
+ if (hasAuth) {
350
+ const authMiddleware = fs.readFileSync(
351
+ path.join(TEMPLATES_DIR, 'auth.middleware.template.js'),
352
+ 'utf8'
353
+ );
354
+ fs.writeFileSync(path.join(middlewareDir, 'auth.js'), authMiddleware);
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Generate Production Server
360
+ */
361
+ function generateProductionServer(backendPath, resources, hasAuth, hasSocket = false) {
362
+ let template = fs.readFileSync(
363
+ path.join(TEMPLATES_DIR, 'production.server.template.js'),
364
+ 'utf8'
365
+ );
366
+
367
+ // Generate route imports and registrations
368
+ let routeCode = '';
369
+
370
+ // Auth routes
371
+ if (hasAuth) {
372
+ routeCode += `import authRoutes from './routes/auth.routes.js';\n`;
373
+ }
374
+
375
+ // Chat routes (Socket.io imports will be added by generateServerWithSocket)
376
+ if (hasSocket) {
377
+ routeCode += `import chatRoutes from './routes/chat.routes.js';\n`;
378
+ }
379
+
380
+ // Resource routes
381
+ for (const resource of resources) {
382
+ routeCode += `import ${resource}Routes from './routes/${resource}.routes.js';\n`;
383
+ }
384
+
385
+ routeCode += '\n// Register routes\n';
386
+
387
+ if (hasAuth) {
388
+ routeCode += `app.use('/api/auth', authRoutes);\n`;
389
+ }
390
+
391
+ if (hasSocket) {
392
+ routeCode += `app.use('/api/chat', chatRoutes);\n`;
393
+ }
394
+
395
+ for (const resource of resources) {
396
+ routeCode += `app.use('/api/${resource}', ${resource}Routes);\n`;
397
+ }
398
+
399
+ template = template.replace(/\/\/\s*__ROUTES__|<ROUTES>/, routeCode);
400
+
401
+ // If socket is enabled, wrap server with HTTP and Socket.io
402
+ if (hasSocket) {
403
+ template = generateServerWithSocket(template, true);
404
+ }
405
+
406
+ fs.writeFileSync(path.join(backendPath, 'server.js'), template);
407
+ }
408
+
409
+ /**
410
+ * Generate Environment File
411
+ */
412
+ function generateEnvFile(backendPath, hasAuth, hasSocket = false) {
413
+ const envContent = `# ========== SERVER ==========
414
+ NODE_ENV=development
415
+ PORT=5000
416
+
417
+ # ========== DATABASE ==========
418
+ MONGODB_URI=mongodb://localhost:27017/offbyt_app
419
+ DB_NAME=offbyt_app
420
+
421
+ # ========== SECURITY ==========
422
+ ${hasAuth || hasSocket ? `JWT_SECRET=your_super_secret_jwt_key_change_this_in_production
423
+ JWT_EXPIRE=7d
424
+ JWT_EXPIRES_IN=7d
425
+ PASSWORD_SALT_ROUNDS=10` : `# JWT_SECRET=your_super_secret_jwt_key_change_this_in_production
426
+ # JWT_EXPIRE=7d
427
+ # JWT_EXPIRES_IN=7d
428
+ # PASSWORD_SALT_ROUNDS=10`}
429
+
430
+ # ========== CORS ==========
431
+ CORS_ORIGIN=http://localhost:3000,http://localhost:5173
432
+ ${hasSocket ? `CLIENT_URL=http://localhost:3000` : `# CLIENT_URL=http://localhost:3000`}
433
+
434
+ # ========== API ==========
435
+ API_VERSION=v1
436
+ API_RATE_LIMIT=100
437
+
438
+ # ========== LOGGING ==========
439
+ LOG_LEVEL=info
440
+ ENABLE_LOGGING=true
441
+ ENABLE_METRICS=false
442
+
443
+ # ========== CACHE ==========
444
+ CACHE_TTL=300
445
+
446
+ ${hasSocket ? `# ========== SOCKET.IO ==========
447
+ SOCKET_PING_TIMEOUT=60000
448
+ SOCKET_PING_INTERVAL=25000
449
+ ` : ''}
450
+ # ========== API KEYS (Optional) ==========
451
+ # API_KEY=your_api_key_here
452
+ `;
453
+
454
+ fs.writeFileSync(path.join(backendPath, '.env'), envContent);
455
+ fs.writeFileSync(path.join(backendPath, '.env.example'), envContent);
456
+ }
457
+
458
+ /**
459
+ * Generate Package.json
460
+ */
461
+ function generatePackageJson(backendPath, hasSocket = false) {
462
+ const templatePath = path.join(TEMPLATES_DIR, 'package.production.json');
463
+ let template = fs.readFileSync(templatePath, 'utf8');
464
+
465
+ // Parse and add socket dependencies if needed
466
+ if (hasSocket) {
467
+ const packageJson = JSON.parse(template);
468
+ addSocketDependencies(packageJson);
469
+ template = JSON.stringify(packageJson, null, 2);
470
+ }
471
+
472
+ fs.writeFileSync(path.join(backendPath, 'package.json'), template);
473
+ }
474
+
475
+ /**
476
+ * Generate README
477
+ */
478
+ function generateReadme(backendPath, resources, hasAuth, hasSocket = false) {
479
+ const readmeContent = `# Backend API - Generated by offbyt v2.0
480
+
481
+ ## Quick Start
482
+
483
+ \`\`\`bash
484
+ # Install dependencies
485
+ npm install
486
+
487
+ # Start development server
488
+ npm run dev
489
+
490
+ # Start production server
491
+ npm start
492
+ \`\`\`
493
+
494
+ ## API Endpoints
495
+
496
+ ### Base URL
497
+ \`http://localhost:5000/api\`
498
+
499
+ ### Health Check
500
+ - \`GET /health\` - Server health status
501
+
502
+ ### Resources
503
+ ${resources.map(r => `- \`/api/${r}\` - ${r.toUpperCase()} resource endpoints`).join('\n')}
504
+
505
+ ${hasAuth ? `### Authentication
506
+ - \`POST /api/auth/signup\` - Register new user
507
+ - \`POST /api/auth/login\` - Login user
508
+ - \`GET /api/auth/profile\` - Get user profile
509
+ ` : ''}
510
+
511
+ ${hasSocket ? `### Chat (Real-time)
512
+ - \`GET /api/chat/conversations\` - Get all conversations
513
+ - \`POST /api/chat/conversations\` - Create conversation
514
+ - \`GET /api/chat/conversations/:id/messages\` - Get messages
515
+ - \`POST /api/chat/conversations/:id/messages\` - Send message (REST fallback)
516
+
517
+ ### Socket.io Events
518
+ **Client → Server:**
519
+ - \`conversation:join\` - Join a conversation room
520
+ - \`message:send\` - Send a message
521
+ - \`typing:start\` - Start typing indicator
522
+ - \`typing:stop\` - Stop typing indicator
523
+ - \`message:read\` - Mark message as read
524
+
525
+ **Server → Client:**
526
+ - \`message:new\` - New message received
527
+ - \`typing:update\` - Someone is typing
528
+ - \`user:online\` - User came online
529
+ - \`user:offline\` - User went offline
530
+ - \`message:sent\` - Message sent confirmation
531
+
532
+ **Socket.io Connection:**
533
+ \`\`\`javascript
534
+ import io from 'socket.io-client';
535
+ const socket = io(process.env.REACT_APP_API_URL, {
536
+ auth: { token: 'YOUR_JWT_TOKEN' }
537
+ });
538
+ \`\`\`
539
+ ` : ''}
540
+
541
+ ## Features
542
+
543
+ ✅ Production-Ready Architecture
544
+ ✅ Advanced Pagination & Filtering
545
+ ✅ Comprehensive Error Handling
546
+ ✅ Security Headers & Rate Limiting
547
+ ✅ MongoDB Integration
548
+ ✅ Mongoose Validation
549
+ ✅ Soft Delete Support
550
+ ✅ Activity Logging
551
+ ✅ CORS Support
552
+ ${hasSocket ? '✅ Real-time Socket.io Chat\n✅ Typing Indicators\n✅ Online Presence\n✅ Read Receipts\n✅ Room/Channel Support' : ''}
553
+
554
+ ## Environment Variables
555
+
556
+ Copy \`.env.example\` to \`.env\` and update values:
557
+
558
+ \`\`\`
559
+ DATABASE_URL=mongodb://localhost:27017/app
560
+ PORT=5000
561
+ JWT_SECRET=your_secret_key
562
+ NODE_ENV=development
563
+ ${hasSocket ? 'CLIENT_URL=http://localhost:3000' : ''}
564
+ \`\`\`
565
+
566
+ ## Project Structure
567
+
568
+ \`\`\`
569
+ backend/
570
+ ├── config/ # Database & app config
571
+ ├── middleware/ # Express middleware
572
+ ├── models/ # Mongoose models
573
+ ├── routes/ # API routes
574
+ ${hasSocket ? '├── socket/ # Socket.io handlers\n' : ''}├── utils/ # Helper utilities
575
+ ├── server.js # Main server file
576
+ ├── package.json
577
+ ├── .env
578
+ └── .gitignore
579
+ \`\`\`
580
+
581
+ ## API Response Format
582
+
583
+ All endpoints return JSON in this format:
584
+
585
+ \`\`\`json
586
+ {
587
+ "success": true,
588
+ "message": "Request successful",
589
+ "data": {},
590
+ "timestamp": "2024-01-01T00:00:00.000Z"
591
+ }
592
+ \`\`\`
593
+
594
+ ## Database Models
595
+
596
+ ${resources.map(r => {
597
+ const Model = r.charAt(0).toUpperCase() + r.slice(1).replace(/s$/, '');
598
+ return `- \`${Model}\` - Stores ${r} data`;
599
+ }).join('\n')}
600
+
601
+ ## Security Features
602
+
603
+ - Helmet.js for security headers
604
+ - Rate limiting on all endpoints
605
+ - MongoDB injection prevention
606
+ - CORS protection
607
+ - Request validation
608
+
609
+ ## Performance
610
+
611
+ - Compression middleware
612
+ - Database indexes
613
+ - Caching headers
614
+ - Query optimization
615
+ - Bulk operations support
616
+
617
+ ## Error Handling
618
+
619
+ All errors are returned with appropriate HTTP status codes:
620
+
621
+ - \`400\` - Bad Request
622
+ - \`401\` - Unauthorized
623
+ - \`403\` - Forbidden
624
+ - \`404\` - Not Found
625
+ - \`409\` - Conflict (Duplicate)
626
+ - \`500\` - Server Error
627
+
628
+ ## Development
629
+
630
+ \`\`\`bash
631
+ # Start with file watching
632
+ npm run dev
633
+
634
+ # Run tests
635
+ npm test
636
+
637
+ # Check linting
638
+ npm run lint
639
+ \`\`\`
640
+
641
+ ## Production Deployment
642
+
643
+ 1. Set \`NODE_ENV=production\`
644
+ 2. Update database URL to production MongoDB
645
+ 3. Set strong JWT_SECRET
646
+ 4. Enable HTTPS in reverse proxy
647
+ 5. Use process manager (PM2)
648
+ 6. Set up monitoring
649
+
650
+ ## Support
651
+
652
+ Generated by offbyt v2.0
653
+ Full-stack backend generation for modern web applications
654
+ `;
655
+
656
+ fs.writeFileSync(path.join(backendPath, 'README.md'), readmeContent);
657
+ }
658
+
659
+ /**
660
+ * Helper: Read all files recursively
661
+ */
662
+ function readAllFilesRecursive(dirPath) {
663
+ const files = [];
664
+
665
+ if (!fs.existsSync(dirPath)) {
666
+ return files;
667
+ }
668
+
669
+ const items = fs.readdirSync(dirPath);
670
+
671
+ for (const item of items) {
672
+ const fullPath = path.join(dirPath, item);
673
+ const stat = fs.statSync(fullPath);
674
+
675
+ if (stat.isDirectory()) {
676
+ if (!item.startsWith('.') && item !== 'node_modules') {
677
+ files.push(...readAllFilesRecursive(fullPath));
678
+ }
679
+ } else if (
680
+ item.endsWith('.html') ||
681
+ item.endsWith('.js') ||
682
+ item.endsWith('.jsx') ||
683
+ item.endsWith('.ts') ||
684
+ item.endsWith('.tsx')
685
+ ) {
686
+ try {
687
+ files.push(fs.readFileSync(fullPath, 'utf8'));
688
+ } catch {
689
+ // Ignore read errors
690
+ }
691
+ }
692
+ }
693
+
694
+ return files;
695
+ }
696
+
697
+ /**
698
+ * Generate Auth Setup
699
+ */
700
+ function generateAuthSetup(backendPath) {
701
+ const middlewareDir = path.join(backendPath, 'middleware');
702
+ const modelsDir = path.join(backendPath, 'models');
703
+ const routesDir = path.join(backendPath, 'routes');
704
+
705
+ // Auth middleware
706
+ try {
707
+ const authMiddleware = fs.readFileSync(
708
+ path.join(TEMPLATES_DIR, 'auth.middleware.template.js'),
709
+ 'utf8'
710
+ );
711
+ fs.writeFileSync(path.join(middlewareDir, 'auth.js'), authMiddleware);
712
+ } catch (error) {
713
+ console.warn('⚠️ Could not copy auth middleware');
714
+ }
715
+
716
+ // User model
717
+ try {
718
+ const userModel = fs.readFileSync(
719
+ path.join(TEMPLATES_DIR, 'auth.user.model.template.js'),
720
+ 'utf8'
721
+ );
722
+ fs.writeFileSync(path.join(modelsDir, 'User.js'), userModel);
723
+ } catch (error) {
724
+ console.warn('⚠️ Could not copy user model');
725
+ }
726
+
727
+ // Auth routes
728
+ try {
729
+ const authRoutes = fs.readFileSync(
730
+ path.join(TEMPLATES_DIR, 'auth.routes.template.js'),
731
+ 'utf8'
732
+ );
733
+ fs.writeFileSync(path.join(routesDir, 'auth.routes.js'), authRoutes);
734
+ } catch (error) {
735
+ console.warn('⚠️ Could not copy auth routes');
736
+ }
737
+ }
738
+
739
+ /**
740
+ * Install Dependencies
741
+ */
742
+ async function installDependencies(backendPath) {
743
+ try {
744
+ await execAsync('npm install', { cwd: backendPath });
745
+ } catch (error) {
746
+ console.warn('⚠️ npm install had some warnings');
747
+ }
748
+ }
749
+
750
+ /**
751
+ * Print Completion Info
752
+ */
753
+ function printCompletionInfo(backendPath, hasAuth, resources, hasSocket = false) {
754
+ console.log(chalk.cyan('📦 Backend Package:'));
755
+ console.log(chalk.gray(` Path: ${backendPath}`));
756
+ console.log(chalk.gray(` Resources: ${resources.length}`));
757
+ console.log(chalk.gray(` Auth: ${hasAuth ? '✓ Enabled' : '✗ Disabled'}`));
758
+ console.log(chalk.gray(` Socket.io: ${hasSocket ? '✓ Enabled (Chat)' : '✗ Disabled'}\n`));
759
+
760
+ console.log(chalk.cyan('🚀 Next Steps:'));
761
+ console.log(chalk.white(` 1. cd backend`));
762
+ console.log(chalk.white(` 2. npm run dev # Start development server`));
763
+ console.log(chalk.white(` 3. Open http://localhost:5000/health\n`));
764
+
765
+ if (hasSocket) {
766
+ console.log(chalk.magenta('💬 Socket.io Endpoints:'));
767
+ console.log(chalk.gray(` • ws://localhost:5000 # Socket.io connection`));
768
+ console.log(chalk.gray(` • GET /api/chat/conversations`));
769
+ console.log(chalk.gray(` • GET /api/chat/conversations/:id/messages`));
770
+ console.log(chalk.gray(` • POST /api/chat/conversations\n`));
771
+ }
772
+
773
+ console.log(chalk.cyan('📚 API Resources:'));
774
+ resources.forEach(r => {
775
+ console.log(chalk.gray(` • GET /api/${r} # List all`));
776
+ console.log(chalk.gray(` • GET /api/${r}/:id # Get by ID`));
777
+ console.log(chalk.gray(` • POST /api/${r} # Create`));
778
+ console.log(chalk.gray(` • PUT /api/${r}/:id # Update`));
779
+ console.log(chalk.gray(` • DELETE /api/${r}/:id # Delete`));
780
+ });
781
+
782
+ console.log(chalk.green('\n✨ Your production-ready backend is ready!\n'));
783
+ }
784
+
785
+ export { enhancedOfflineMode as offlineMode };
786
+ export default enhancedOfflineMode;
787
+