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,341 @@
1
+ import babelTraverse from '@babel/traverse';
2
+
3
+ const traverse = babelTraverse.default || babelTraverse;
4
+
5
+ /**
6
+ * Socket.io / WebSocket Pattern Detector
7
+ * Detects real-time communication patterns in frontend code
8
+ *
9
+ * Detects:
10
+ * - Socket.io client initialization
11
+ * - WebSocket connections
12
+ * - Chat UI components
13
+ * - Message sending/receiving
14
+ * - Presence/typing indicators
15
+ * - Room/channel patterns
16
+ */
17
+
18
+ const CHAT_PATTERNS = {
19
+ socketIo: [
20
+ /io\(['"].*['"]\)/gi,
21
+ /socket\.io-client/gi,
22
+ /new\s+Socket/gi,
23
+ /socketIOClient/gi,
24
+ ],
25
+ websocket: [
26
+ /new\s+WebSocket/gi,
27
+ /ws:\/\//gi,
28
+ /wss:\/\//gi,
29
+ ],
30
+ events: [
31
+ /on\(['"]message/gi,
32
+ /emit\(['"]message/gi,
33
+ /on\(['"]chat/gi,
34
+ /emit\(['"]chat/gi,
35
+ /socket\.send/gi,
36
+ /socket\.on/gi,
37
+ /socket\.emit/gi,
38
+ ],
39
+ chatUI: [
40
+ /sendMessage/gi,
41
+ /receiveMessage/gi,
42
+ /chatBox/gi,
43
+ /messageList/gi,
44
+ /conversation/gi,
45
+ /chat.*input/gi,
46
+ /message.*input/gi,
47
+ /typing.*indicator/gi,
48
+ ],
49
+ presence: [
50
+ /user.*online/gi,
51
+ /user.*offline/gi,
52
+ /presence/gi,
53
+ /is.*typing/gi,
54
+ ],
55
+ rooms: [
56
+ /join.*room/gi,
57
+ /leave.*room/gi,
58
+ /join.*channel/gi,
59
+ /room.*id/gi,
60
+ /channel.*id/gi,
61
+ ]
62
+ };
63
+
64
+ /**
65
+ * Main socket detection function
66
+ */
67
+ export function detectSocket(ast, sourceCode) {
68
+ const detections = {
69
+ hasSocket: false,
70
+ hasChat: false,
71
+ socketType: null, // 'socket.io' | 'websocket' | null
72
+ events: [],
73
+ rooms: false,
74
+ presence: false,
75
+ endpoints: []
76
+ };
77
+
78
+ // AST-based detection
79
+ traverse(ast, {
80
+ // Detect Socket.io initialization: io('http://...')
81
+ CallExpression(path) {
82
+ const { callee, arguments: args } = path.node;
83
+
84
+ // Socket.io: io(url)
85
+ if (callee.type === 'Identifier' && callee.name === 'io') {
86
+ detections.hasSocket = true;
87
+ detections.socketType = 'socket.io';
88
+
89
+ if (args.length > 0 && args[0].type === 'StringLiteral') {
90
+ detections.endpoints.push({
91
+ type: 'socket.io',
92
+ url: args[0].value
93
+ });
94
+ }
95
+ }
96
+
97
+ // Socket.io: socketIOClient(url)
98
+ if (callee.type === 'Identifier' && callee.name === 'socketIOClient') {
99
+ detections.hasSocket = true;
100
+ detections.socketType = 'socket.io';
101
+ }
102
+
103
+ // WebSocket: new WebSocket(url)
104
+ if (callee.type === 'NewExpression' &&
105
+ callee.callee?.name === 'WebSocket') {
106
+ detections.hasSocket = true;
107
+ detections.socketType = 'websocket';
108
+
109
+ if (args.length > 0 && args[0].type === 'StringLiteral') {
110
+ detections.endpoints.push({
111
+ type: 'websocket',
112
+ url: args[0].value
113
+ });
114
+ }
115
+ }
116
+
117
+ // Detect socket.emit('event', data)
118
+ if (callee.type === 'MemberExpression' &&
119
+ callee.property.type === 'Identifier' &&
120
+ callee.property.name === 'emit') {
121
+
122
+ if (args.length > 0 && args[0].type === 'StringLiteral') {
123
+ const eventName = args[0].value;
124
+ detections.events.push({
125
+ type: 'emit',
126
+ name: eventName
127
+ });
128
+
129
+ // Check for chat-related events
130
+ if (isChatEvent(eventName)) {
131
+ detections.hasChat = true;
132
+ }
133
+
134
+ // Check for room events
135
+ if (isRoomEvent(eventName)) {
136
+ detections.rooms = true;
137
+ }
138
+
139
+ // Check for presence events
140
+ if (isPresenceEvent(eventName)) {
141
+ detections.presence = true;
142
+ }
143
+ }
144
+ }
145
+
146
+ // Detect socket.on('event', callback)
147
+ if (callee.type === 'MemberExpression' &&
148
+ callee.property.type === 'Identifier' &&
149
+ callee.property.name === 'on') {
150
+
151
+ if (args.length > 0 && args[0].type === 'StringLiteral') {
152
+ const eventName = args[0].value;
153
+ detections.events.push({
154
+ type: 'on',
155
+ name: eventName
156
+ });
157
+
158
+ if (isChatEvent(eventName)) {
159
+ detections.hasChat = true;
160
+ }
161
+
162
+ if (isRoomEvent(eventName)) {
163
+ detections.rooms = true;
164
+ }
165
+
166
+ if (isPresenceEvent(eventName)) {
167
+ detections.presence = true;
168
+ }
169
+ }
170
+ }
171
+ },
172
+
173
+ // Detect import statements
174
+ ImportDeclaration(path) {
175
+ const source = path.node.source.value;
176
+
177
+ if (source === 'socket.io-client' || source.includes('socket.io')) {
178
+ detections.hasSocket = true;
179
+ detections.socketType = 'socket.io';
180
+ }
181
+ },
182
+
183
+ // Detect chat-related variable/function names
184
+ Identifier(path) {
185
+ const name = path.node.name;
186
+
187
+ if (isChatIdentifier(name)) {
188
+ detections.hasChat = true;
189
+ }
190
+ }
191
+ });
192
+
193
+ // Regex-based detection (fallback)
194
+ const regexDetections = detectSocketRegex(sourceCode);
195
+
196
+ if (regexDetections.hasSocket) {
197
+ detections.hasSocket = true;
198
+ detections.socketType = detections.socketType || regexDetections.socketType;
199
+ }
200
+
201
+ if (regexDetections.hasChat) {
202
+ detections.hasChat = true;
203
+ }
204
+
205
+ if (regexDetections.rooms) {
206
+ detections.rooms = true;
207
+ }
208
+
209
+ if (regexDetections.presence) {
210
+ detections.presence = true;
211
+ }
212
+
213
+ // Deduplicate events
214
+ detections.events = Array.from(
215
+ new Map(detections.events.map(e => [e.name, e])).values()
216
+ );
217
+
218
+ return detections;
219
+ }
220
+
221
+ /**
222
+ * Regex-based socket detection (fallback)
223
+ */
224
+ function detectSocketRegex(sourceCode) {
225
+ const result = {
226
+ hasSocket: false,
227
+ hasChat: false,
228
+ socketType: null,
229
+ rooms: false,
230
+ presence: false
231
+ };
232
+
233
+ // Check Socket.io patterns
234
+ for (const pattern of CHAT_PATTERNS.socketIo) {
235
+ if (pattern.test(sourceCode)) {
236
+ result.hasSocket = true;
237
+ result.socketType = 'socket.io';
238
+ break;
239
+ }
240
+ }
241
+
242
+ // Check WebSocket patterns
243
+ if (!result.hasSocket) {
244
+ for (const pattern of CHAT_PATTERNS.websocket) {
245
+ if (pattern.test(sourceCode)) {
246
+ result.hasSocket = true;
247
+ result.socketType = 'websocket';
248
+ break;
249
+ }
250
+ }
251
+ }
252
+
253
+ // Check chat UI patterns
254
+ for (const pattern of CHAT_PATTERNS.chatUI) {
255
+ if (pattern.test(sourceCode)) {
256
+ result.hasChat = true;
257
+ break;
258
+ }
259
+ }
260
+
261
+ // Check events
262
+ for (const pattern of CHAT_PATTERNS.events) {
263
+ if (pattern.test(sourceCode)) {
264
+ result.hasChat = true;
265
+ break;
266
+ }
267
+ }
268
+
269
+ // Check rooms
270
+ for (const pattern of CHAT_PATTERNS.rooms) {
271
+ if (pattern.test(sourceCode)) {
272
+ result.rooms = true;
273
+ break;
274
+ }
275
+ }
276
+
277
+ // Check presence
278
+ for (const pattern of CHAT_PATTERNS.presence) {
279
+ if (pattern.test(sourceCode)) {
280
+ result.presence = true;
281
+ break;
282
+ }
283
+ }
284
+
285
+ return result;
286
+ }
287
+
288
+ /**
289
+ * Helper: Check if event name is chat-related
290
+ */
291
+ function isChatEvent(eventName) {
292
+ const chatKeywords = [
293
+ 'message', 'chat', 'send', 'receive',
294
+ 'msg', 'text', 'conversation'
295
+ ];
296
+
297
+ const lowerName = eventName.toLowerCase();
298
+ return chatKeywords.some(kw => lowerName.includes(kw));
299
+ }
300
+
301
+ /**
302
+ * Helper: Check if event name is room-related
303
+ */
304
+ function isRoomEvent(eventName) {
305
+ const roomKeywords = [
306
+ 'room', 'channel', 'join', 'leave',
307
+ 'subscribe', 'unsubscribe'
308
+ ];
309
+
310
+ const lowerName = eventName.toLowerCase();
311
+ return roomKeywords.some(kw => lowerName.includes(kw));
312
+ }
313
+
314
+ /**
315
+ * Helper: Check if event name is presence-related
316
+ */
317
+ function isPresenceEvent(eventName) {
318
+ const presenceKeywords = [
319
+ 'online', 'offline', 'presence',
320
+ 'typing', 'active', 'idle'
321
+ ];
322
+
323
+ const lowerName = eventName.toLowerCase();
324
+ return presenceKeywords.some(kw => lowerName.includes(kw));
325
+ }
326
+
327
+ /**
328
+ * Helper: Check if identifier is chat-related
329
+ */
330
+ function isChatIdentifier(name) {
331
+ const chatKeywords = [
332
+ 'sendMessage', 'receiveMessage', 'chatBox',
333
+ 'messageList', 'messageInput', 'chatInput',
334
+ 'conversation', 'chatHistory', 'messageHistory'
335
+ ];
336
+
337
+ const lowerName = name.toLowerCase();
338
+ return chatKeywords.some(kw => lowerName.includes(kw.toLowerCase()));
339
+ }
340
+
341
+ export default detectSocket;
@@ -0,0 +1,17 @@
1
+ function pascalCase(name) {
2
+ return name.charAt(0).toUpperCase() + name.slice(1);
3
+ }
4
+
5
+ export function generateControllers(ir) {
6
+ const output = {};
7
+
8
+ for (const resource of ir.resources || []) {
9
+ const model = pascalCase(resource.name);
10
+
11
+ output[`controllers/${resource.name}Controller.js`] = `import ${model} from '../models/${model}.js';\n\nexport const list${model}s = async (req, res) => {\n const data = await ${model}.find();\n res.json({ success: true, data });\n};\n\nexport const get${model} = async (req, res) => {\n const data = await ${model}.findById(req.params.id);\n res.json({ success: true, data });\n};\n\nexport const create${model} = async (req, res) => {\n const data = await ${model}.create(req.body);\n res.status(201).json({ success: true, data });\n};\n\nexport const update${model} = async (req, res) => {\n const data = await ${model}.findByIdAndUpdate(req.params.id, req.body, { new: true });\n res.json({ success: true, data });\n};\n\nexport const delete${model} = async (req, res) => {\n await ${model}.findByIdAndDelete(req.params.id);\n res.json({ success: true });\n};\n`;
12
+ }
13
+
14
+ return output;
15
+ }
16
+
17
+ export default generateControllers;
@@ -0,0 +1,25 @@
1
+ function mapFieldToMongoose(field) {
2
+ if (field.type === 'ObjectId') {
3
+ return `${field.name}: { type: mongoose.Schema.Types.ObjectId${field.ref ? `, ref: '${field.ref}'` : ''}${field.required ? ', required: true' : ''} }`;
4
+ }
5
+ return `${field.name}: { type: ${field.type}${field.required ? ', required: true' : ''} }`;
6
+ }
7
+
8
+ function modelName(name) {
9
+ return name.charAt(0).toUpperCase() + name.slice(1);
10
+ }
11
+
12
+ export function generateModels(ir) {
13
+ const output = {};
14
+
15
+ for (const resource of ir.resources || []) {
16
+ const schemaFields = (resource.fields || []).map(mapFieldToMongoose).join(',\n ');
17
+ const className = modelName(resource.name);
18
+
19
+ output[`models/${className}.js`] = `import mongoose from 'mongoose';\n\nconst ${resource.name}Schema = new mongoose.Schema({\n ${schemaFields}\n}, { timestamps: true });\n\nexport default mongoose.model('${className}', ${resource.name}Schema);\n`;
20
+ }
21
+
22
+ return output;
23
+ }
24
+
25
+ export default generateModels;
@@ -0,0 +1,17 @@
1
+ function pascalCase(name) {
2
+ return name.charAt(0).toUpperCase() + name.slice(1);
3
+ }
4
+
5
+ export function generateRoutes(ir) {
6
+ const output = {};
7
+
8
+ for (const resource of ir.resources || []) {
9
+ const model = pascalCase(resource.name);
10
+
11
+ output[`routes/${resource.name}.routes.js`] = `import express from 'express';\nimport {\n list${model}s,\n get${model},\n create${model},\n update${model},\n delete${model}\n} from '../controllers/${resource.name}Controller.js';\n\nconst router = express.Router();\n\nrouter.get('/', list${model}s);\nrouter.get('/:id', get${model});\nrouter.post('/', create${model});\nrouter.put('/:id', update${model});\nrouter.delete('/:id', delete${model});\n\nexport default router;\n`;
12
+ }
13
+
14
+ return output;
15
+ }
16
+
17
+ export default generateRoutes;
@@ -0,0 +1,18 @@
1
+ export function generateServer(ir) {
2
+ const imports = (ir.resources || [])
3
+ .map((r) => `import ${r.name}Routes from './routes/${r.name}.routes.js';`)
4
+ .join('\n');
5
+
6
+ const routes = (ir.resources || [])
7
+ .map((r) => `app.use('/api/${r.name}s', ${r.name}Routes);`)
8
+ .join('\n');
9
+
10
+ const serverCode = `import 'dotenv/config';\nimport express from 'express';\nimport cors from 'cors';\nimport mongoose from 'mongoose';\n${imports}\n\nconst app = express();\nconst PORT = process.env.PORT || 3000;\nconst MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/offbyt';\n\napp.use(cors());\napp.use(express.json());\n\n${routes}\n\nconst healthHandler = (req, res) => {\n res.json({\n status: 'ok',\n timestamp: new Date().toISOString(),\n database: mongoose.connection.readyState === 1 ? 'Connected' : 'Disconnected'\n });\n};\n\napp.get('/health', healthHandler);\napp.get(`/api/health`, healthHandler);\n\napp.use((req, res) => {\n res.status(404).json({\n error: 'Not Found',\n path: req.path,\n method: req.method\n });\n});\n\nasync function connectDB() {\n try {\n await mongoose.connect(MONGODB_URI, {\n serverSelectionTimeoutMS: 5000\n });\n console.log('✅ MongoDB Connected');\n } catch (error) {\n console.error('❌ MongoDB Connection Failed:', error.message);\n process.exit(1);\n }\n}\n\nasync function startServer() {\n await connectDB();\n app.listen(PORT, () => {\n console.log(\`🚀 Server running on \${PORT}\`);\n });\n}\n\nstartServer().catch((error) => {\n console.error(error);\n process.exit(1);\n});\n`;
11
+
12
+ return {
13
+ 'server.js': serverCode
14
+ };
15
+ }
16
+
17
+ export default generateServer;
18
+
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Socket/Chat Backend Generator
3
+ *
4
+ * Generates complete Socket.io backend infrastructure including:
5
+ * - Socket.io server setup
6
+ * - Chat models (Message, Conversation)
7
+ * - REST API routes for chat
8
+ * - Authentication middleware
9
+ */
10
+
11
+ import { socketServerTemplate } from '../../templates/socket.server.template.js';
12
+ import { messageModelTemplate, conversationModelTemplate } from '../../templates/chat.models.template.js';
13
+ import { chatRoutesTemplate } from '../../templates/chat.routes.template.js';
14
+
15
+ /**
16
+ * Generate complete socket/chat backend
17
+ */
18
+ export function generateSocketBackend(socketDetection) {
19
+ const files = {};
20
+
21
+ // Only generate if socket is detected
22
+ if (!socketDetection || !socketDetection.hasSocket) {
23
+ return files;
24
+ }
25
+
26
+ // 1. Socket.io server setup
27
+ files['socket/index.js'] = socketServerTemplate;
28
+
29
+ // 2. Chat models
30
+ files['models/Message.js'] = messageModelTemplate;
31
+ files['models/Conversation.js'] = conversationModelTemplate;
32
+
33
+ // 3. Chat routes (REST API endpoints)
34
+ files['routes/chat.routes.js'] = chatRoutesTemplate;
35
+
36
+ // 4. Package.json dependencies
37
+ const socketDependencies = {
38
+ 'socket.io': '^4.6.1',
39
+ 'jsonwebtoken': '^9.0.2'
40
+ };
41
+
42
+ return {
43
+ files,
44
+ dependencies: socketDependencies,
45
+ instructions: generateSetupInstructions(socketDetection)
46
+ };
47
+ }
48
+
49
+ /**
50
+ * Generate setup instructions
51
+ */
52
+ function generateSetupInstructions(socketDetection) {
53
+ const instructions = {
54
+ title: '🔌 Socket.io Chat Backend Generated',
55
+ steps: [
56
+ '1. Install dependencies: npm install socket.io jsonwebtoken',
57
+ '2. Import socket initialization in server.js',
58
+ '3. Initialize Socket.io with HTTP server',
59
+ '4. Register chat routes at /api/chat',
60
+ '5. Set JWT_SECRET in .env file',
61
+ '6. Set CLIENT_URL in .env (for CORS)'
62
+ ],
63
+ features: []
64
+ };
65
+
66
+ if (socketDetection.hasChat) {
67
+ instructions.features.push('✅ Real-time messaging');
68
+ instructions.features.push('✅ Message history & persistence');
69
+ }
70
+
71
+ if (socketDetection.rooms) {
72
+ instructions.features.push('✅ Rooms/Channels support');
73
+ instructions.features.push('✅ Group conversations');
74
+ }
75
+
76
+ if (socketDetection.presence) {
77
+ instructions.features.push('✅ Online/Offline presence');
78
+ instructions.features.push('✅ Typing indicators');
79
+ }
80
+
81
+ instructions.features.push('✅ Read receipts');
82
+ instructions.features.push('✅ File sharing support');
83
+ instructions.features.push('✅ Message reactions');
84
+ instructions.features.push('✅ JWT Authentication');
85
+
86
+ return instructions;
87
+ }
88
+
89
+ /**
90
+ * Generate modified server.js with Socket.io integration
91
+ */
92
+ export function generateServerWithSocket(baseServerCode, hasSocket = false) {
93
+ if (!hasSocket) {
94
+ return baseServerCode;
95
+ }
96
+
97
+ let modifiedCode = baseServerCode;
98
+
99
+ // Check if already has Socket.io imports
100
+ if (modifiedCode.includes('socket.io') || modifiedCode.includes('initializeSocket')) {
101
+ return modifiedCode; // Already integrated
102
+ }
103
+
104
+ // Add Socket.io imports after express import
105
+ const socketImports = `import { createServer } from 'http';
106
+ import initializeSocket from './socket/index.js';
107
+ `;
108
+
109
+ // Insert imports after express import
110
+ modifiedCode = modifiedCode.replace(
111
+ /(import express from ['"]express['"];)/,
112
+ `$1\n${socketImports}`
113
+ );
114
+
115
+ // Create HTTP server and initialize Socket.io after app creation
116
+ const serverSetup = `
117
+ // ============================================
118
+ // SOCKET.IO SETUP
119
+ // ============================================
120
+ const httpServer = createServer(app);
121
+ const io = initializeSocket(httpServer);
122
+
123
+ // Make io accessible in routes via req.app.get('io')
124
+ app.set('io', io);
125
+ `;
126
+
127
+ // Add server setup after app initialization (after const app = express())
128
+ modifiedCode = modifiedCode.replace(
129
+ /(const app = express\(\);[\s\S]*?const API_VERSION[^;]*;)/,
130
+ `$1\n${serverSetup}`
131
+ );
132
+
133
+ // Replace app.listen with httpServer.listen at the end
134
+ modifiedCode = modifiedCode.replace(
135
+ /app\.listen\((PORT[^)]*)\)/g,
136
+ 'httpServer.listen($1)'
137
+ );
138
+
139
+ return modifiedCode;
140
+ }
141
+
142
+ /**
143
+ * Update package.json with socket dependencies
144
+ */
145
+ export function addSocketDependencies(packageJson) {
146
+ if (!packageJson.dependencies) {
147
+ packageJson.dependencies = {};
148
+ }
149
+
150
+ packageJson.dependencies['socket.io'] = '^4.6.1';
151
+ packageJson.dependencies['jsonwebtoken'] = '^9.0.2';
152
+
153
+ return packageJson;
154
+ }
155
+
156
+ export default {
157
+ generateSocketBackend,
158
+ generateServerWithSocket,
159
+ addSocketDependencies
160
+ };
package/core/index.js ADDED
@@ -0,0 +1,14 @@
1
+ export { scanProject } from './scanner/scanProject.js';
2
+ export { parseJS } from './parser/parseJS.js';
3
+ export { parseTS } from './parser/parseTS.js';
4
+ export { detectFetch } from './detector/detectFetch.js';
5
+ export { detectAxios } from './detector/detectAxios.js';
6
+ export { detectForms } from './detector/detectForms.js';
7
+ export { detectSocket } from './detector/detectSocket.js';
8
+ export { buildIRFromDetections } from './ir/buildIR.js';
9
+ export { applyRuleEngine } from './rules/resourceRules.js';
10
+ export { generateModels } from './generator/generateModels.js';
11
+ export { generateControllers } from './generator/generateControllers.js';
12
+ export { generateRoutes } from './generator/generateRoutes.js';
13
+ export { generateServer } from './generator/generateServer.js';
14
+ export { generateSocketBackend, generateServerWithSocket, addSocketDependencies } from './generator/generateSocket.js';
@@ -0,0 +1,25 @@
1
+ export function createField(name, type = 'String', required = false, extra = {}) {
2
+ return { name, type, required, ...extra };
3
+ }
4
+
5
+ export function createResource({ name, path, fields = [], methods = [] }) {
6
+ return {
7
+ name,
8
+ path,
9
+ fields,
10
+ methods: Array.from(new Set(methods)).sort()
11
+ };
12
+ }
13
+
14
+ export function createRelation({ from, to, type = 'many-to-one' }) {
15
+ return { from, to, type };
16
+ }
17
+
18
+ export function createIR({ resources = [], relations = [], auth = { enabled: false }, database = 'mongodb' } = {}) {
19
+ return {
20
+ resources,
21
+ relations,
22
+ auth,
23
+ database
24
+ };
25
+ }