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.
- package/README.md +2 -0
- package/cli/index.js +2 -0
- package/cli.js +206 -0
- package/core/detector/detectAxios.js +107 -0
- package/core/detector/detectFetch.js +148 -0
- package/core/detector/detectForms.js +55 -0
- package/core/detector/detectSocket.js +341 -0
- package/core/generator/generateControllers.js +17 -0
- package/core/generator/generateModels.js +25 -0
- package/core/generator/generateRoutes.js +17 -0
- package/core/generator/generateServer.js +18 -0
- package/core/generator/generateSocket.js +160 -0
- package/core/index.js +14 -0
- package/core/ir/IRTypes.js +25 -0
- package/core/ir/buildIR.js +83 -0
- package/core/parser/parseJS.js +26 -0
- package/core/parser/parseTS.js +27 -0
- package/core/rules/relationRules.js +38 -0
- package/core/rules/resourceRules.js +32 -0
- package/core/rules/schemaInference.js +26 -0
- package/core/scanner/scanProject.js +58 -0
- package/deploy/cloudflare.js +41 -0
- package/deploy/cloudflareWorker.js +122 -0
- package/deploy/connect.js +198 -0
- package/deploy/flyio.js +51 -0
- package/deploy/index.js +322 -0
- package/deploy/netlify.js +29 -0
- package/deploy/railway.js +215 -0
- package/deploy/render.js +195 -0
- package/deploy/utils.js +383 -0
- package/deploy/vercel.js +29 -0
- package/index.js +18 -0
- package/lib/generator/advancedCrudGenerator.js +475 -0
- package/lib/generator/crudCodeGenerator.js +486 -0
- package/lib/generator/irBasedGenerator.js +360 -0
- package/lib/ir-builder/index.js +16 -0
- package/lib/ir-builder/irBuilder.js +330 -0
- package/lib/ir-builder/rulesEngine.js +353 -0
- package/lib/ir-builder/templateEngine.js +193 -0
- package/lib/ir-builder/templates/index.js +14 -0
- package/lib/ir-builder/templates/model.template.js +47 -0
- package/lib/ir-builder/templates/routes-generic.template.js +66 -0
- package/lib/ir-builder/templates/routes-user.template.js +105 -0
- package/lib/ir-builder/templates/routes.template.js +102 -0
- package/lib/ir-builder/templates/validation.template.js +15 -0
- package/lib/ir-integration.js +349 -0
- package/lib/modes/benchmark.js +162 -0
- package/lib/modes/configBasedGenerator.js +2258 -0
- package/lib/modes/connect.js +1125 -0
- package/lib/modes/doctorAi.js +172 -0
- package/lib/modes/generateApi.js +435 -0
- package/lib/modes/interactiveSetup.js +548 -0
- package/lib/modes/offline.clean.js +14 -0
- package/lib/modes/offline.enhanced.js +787 -0
- package/lib/modes/offline.js +295 -0
- package/lib/modes/offline.v2.js +13 -0
- package/lib/modes/sync.js +629 -0
- package/lib/scanner/apiEndpointExtractor.js +387 -0
- package/lib/scanner/authPatternDetector.js +54 -0
- package/lib/scanner/frontendScanner.js +642 -0
- package/lib/utils/apiClientGenerator.js +242 -0
- package/lib/utils/apiScanner.js +95 -0
- package/lib/utils/codeInjector.js +350 -0
- package/lib/utils/doctor.js +381 -0
- package/lib/utils/envGenerator.js +36 -0
- package/lib/utils/loadTester.js +61 -0
- package/lib/utils/performanceAnalyzer.js +298 -0
- package/lib/utils/resourceDetector.js +281 -0
- package/package.json +20 -0
- package/templates/.env.template +31 -0
- package/templates/advanced.model.template.js +201 -0
- package/templates/advanced.route.template.js +341 -0
- package/templates/auth.middleware.template.js +87 -0
- package/templates/auth.routes.template.js +238 -0
- package/templates/auth.user.model.template.js +78 -0
- package/templates/cache.middleware.js +34 -0
- package/templates/chat.models.template.js +260 -0
- package/templates/chat.routes.template.js +478 -0
- package/templates/compression.middleware.js +19 -0
- package/templates/database.config.js +74 -0
- package/templates/errorHandler.middleware.js +54 -0
- package/templates/express/controller.ejs +26 -0
- package/templates/express/model.ejs +9 -0
- package/templates/express/route.ejs +18 -0
- package/templates/express/server.ejs +16 -0
- package/templates/frontend.env.template +14 -0
- package/templates/model.template.js +86 -0
- package/templates/package.production.json +51 -0
- package/templates/package.template.json +41 -0
- package/templates/pagination.utility.js +110 -0
- package/templates/production.server.template.js +233 -0
- package/templates/rateLimiter.middleware.js +36 -0
- package/templates/requestLogger.middleware.js +19 -0
- package/templates/response.helper.js +179 -0
- package/templates/route.template.js +130 -0
- package/templates/security.middleware.js +78 -0
- package/templates/server.template.js +91 -0
- package/templates/socket.server.template.js +433 -0
- package/templates/utils.helper.js +157 -0
- package/templates/validation.middleware.js +63 -0
- package/templates/validation.schema.js +128 -0
- package/utils/fileWriter.js +15 -0
- package/utils/logger.js +18 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Offline Mode v2.0
|
|
3
|
+
* Production-Ready Backend Generation
|
|
4
|
+
* Auto-exports to enhanced generator
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { enhancedOfflineMode } from './offline.enhanced.js';
|
|
8
|
+
|
|
9
|
+
// Main entry point - uses enhanced production-ready generator
|
|
10
|
+
export async function offlineMode(projectPath) {
|
|
11
|
+
return enhancedOfflineMode(projectPath);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default offlineMode;
|
|
15
|
+
|
|
16
|
+
async function createBackendStructure(backendPath) {
|
|
17
|
+
const dirs = [
|
|
18
|
+
'routes',
|
|
19
|
+
'models',
|
|
20
|
+
'middleware',
|
|
21
|
+
'config'
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
for (const dir of dirs) {
|
|
25
|
+
const dirPath = path.join(backendPath, dir);
|
|
26
|
+
if (!fs.existsSync(dirPath)) {
|
|
27
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Recursively read all files in a directory
|
|
34
|
+
*/
|
|
35
|
+
function readAllFilesRecursive(dirPath) {
|
|
36
|
+
const files = [];
|
|
37
|
+
|
|
38
|
+
if (!fs.existsSync(dirPath)) {
|
|
39
|
+
return files;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const items = fs.readdirSync(dirPath);
|
|
43
|
+
|
|
44
|
+
for (const item of items) {
|
|
45
|
+
const fullPath = path.join(dirPath, item);
|
|
46
|
+
const stat = fs.statSync(fullPath);
|
|
47
|
+
|
|
48
|
+
if (stat.isDirectory()) {
|
|
49
|
+
// Skip node_modules and hidden directories
|
|
50
|
+
if (!item.startsWith('.') && item !== 'node_modules') {
|
|
51
|
+
files.push(...readAllFilesRecursive(fullPath));
|
|
52
|
+
}
|
|
53
|
+
} else if (
|
|
54
|
+
item.endsWith('.js') ||
|
|
55
|
+
item.endsWith('.jsx') ||
|
|
56
|
+
item.endsWith('.ts') ||
|
|
57
|
+
item.endsWith('.tsx') ||
|
|
58
|
+
item.endsWith('.json')
|
|
59
|
+
) {
|
|
60
|
+
try {
|
|
61
|
+
files.push(fs.readFileSync(fullPath, 'utf8'));
|
|
62
|
+
} catch {
|
|
63
|
+
// Ignore read errors
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return files;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function copyMiddlewareFiles(backendPath) {
|
|
72
|
+
const middlewareDir = path.join(backendPath, 'middleware');
|
|
73
|
+
|
|
74
|
+
// Copy error handler
|
|
75
|
+
const errorTemplate = fs.readFileSync(
|
|
76
|
+
path.join(TEMPLATES_DIR, 'errorHandler.middleware.js'),
|
|
77
|
+
'utf8'
|
|
78
|
+
);
|
|
79
|
+
fs.writeFileSync(path.join(middlewareDir, 'errorHandler.js'), errorTemplate);
|
|
80
|
+
|
|
81
|
+
// Copy request logger
|
|
82
|
+
const loggerTemplate = fs.readFileSync(
|
|
83
|
+
path.join(TEMPLATES_DIR, 'requestLogger.middleware.js'),
|
|
84
|
+
'utf8'
|
|
85
|
+
);
|
|
86
|
+
fs.writeFileSync(path.join(middlewareDir, 'requestLogger.js'), loggerTemplate);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
async function installDependencies(backendPath) {
|
|
92
|
+
const packageTemplate = fs.readFileSync(
|
|
93
|
+
path.join(TEMPLATES_DIR, 'package.template.json'),
|
|
94
|
+
'utf8'
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
fs.writeFileSync(
|
|
98
|
+
path.join(backendPath, 'package.json'),
|
|
99
|
+
packageTemplate
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Install npm packages
|
|
103
|
+
try {
|
|
104
|
+
await execAsync('npm install', { cwd: backendPath });
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.warn('⚠️ npm install had issues, but backend is ready');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Generate Auth Setup (User Model + Auth Middleware + Auth Routes)
|
|
112
|
+
*/
|
|
113
|
+
async function generateAuthSetup(backendPath) {
|
|
114
|
+
const middlewareDir = path.join(backendPath, 'middleware');
|
|
115
|
+
const modelsDir = path.join(backendPath, 'models');
|
|
116
|
+
const routesDir = path.join(backendPath, 'routes');
|
|
117
|
+
|
|
118
|
+
// Generate standard middleware (error handler, request logger)
|
|
119
|
+
await copyMiddlewareFiles(backendPath);
|
|
120
|
+
|
|
121
|
+
// Generate auth middleware
|
|
122
|
+
const authMiddlewareTemplate = fs.readFileSync(
|
|
123
|
+
path.join(TEMPLATES_DIR, 'auth.middleware.template.js'),
|
|
124
|
+
'utf8'
|
|
125
|
+
);
|
|
126
|
+
fs.writeFileSync(path.join(middlewareDir, 'auth.js'), authMiddlewareTemplate);
|
|
127
|
+
|
|
128
|
+
// Generate User model
|
|
129
|
+
const userModelTemplate = fs.readFileSync(
|
|
130
|
+
path.join(TEMPLATES_DIR, 'auth.user.model.template.js'),
|
|
131
|
+
'utf8'
|
|
132
|
+
);
|
|
133
|
+
fs.writeFileSync(path.join(modelsDir, 'User.js'), userModelTemplate);
|
|
134
|
+
|
|
135
|
+
// Generate auth routes
|
|
136
|
+
const authRoutesTemplate = fs.readFileSync(
|
|
137
|
+
path.join(TEMPLATES_DIR, 'auth.routes.template.js'),
|
|
138
|
+
'utf8'
|
|
139
|
+
);
|
|
140
|
+
fs.writeFileSync(path.join(routesDir, 'auth.routes.js'), authRoutesTemplate);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Generate .env file with JWT secret
|
|
145
|
+
*/
|
|
146
|
+
async function generateEnvFile(backendPath, hasAuth = false) {
|
|
147
|
+
const envContent = hasAuth
|
|
148
|
+
? generateAuthEnv()
|
|
149
|
+
: fs.readFileSync(path.join(TEMPLATES_DIR, '.env.template'), 'utf8');
|
|
150
|
+
|
|
151
|
+
fs.writeFileSync(path.join(backendPath, '.env'), envContent);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Generate package.json with proper dependencies
|
|
156
|
+
*/
|
|
157
|
+
async function generatePackageJson(backendPath, hasAuth = false) {
|
|
158
|
+
let packageJson = JSON.parse(
|
|
159
|
+
fs.readFileSync(path.join(TEMPLATES_DIR, 'package.template.json'), 'utf8')
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
if (hasAuth) {
|
|
163
|
+
// Ensure auth dependencies are present
|
|
164
|
+
packageJson.dependencies = packageJson.dependencies || {};
|
|
165
|
+
packageJson.dependencies['bcryptjs'] = '^2.4.3';
|
|
166
|
+
packageJson.dependencies['jsonwebtoken'] = '^9.1.0';
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
fs.writeFileSync(
|
|
170
|
+
path.join(backendPath, 'package.json'),
|
|
171
|
+
JSON.stringify(packageJson, null, 2)
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Generate server.js with all routes (auth + CRUD)
|
|
177
|
+
*/
|
|
178
|
+
async function generateServerFile(backendPath, hasAuth = false, nonAuthResources = {}) {
|
|
179
|
+
const serverTemplate = fs.readFileSync(
|
|
180
|
+
path.join(TEMPLATES_DIR, 'server.template.js'),
|
|
181
|
+
'utf8'
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
let routeImports = '';
|
|
185
|
+
let routeRegistrations = '';
|
|
186
|
+
|
|
187
|
+
// Add auth routes if auth is enabled
|
|
188
|
+
if (hasAuth) {
|
|
189
|
+
routeImports += `import authRoutes from './routes/auth.routes.js';\n`;
|
|
190
|
+
routeRegistrations += `app.use('/api/auth', authRoutes);\n\n`;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Add CRUD routes for all resources
|
|
194
|
+
for (const [resourceName] of Object.entries(nonAuthResources)) {
|
|
195
|
+
if (resourceName === 'api') continue;
|
|
196
|
+
|
|
197
|
+
const routesFile = `${resourceName}.routes.js`;
|
|
198
|
+
routeImports += `import ${resourceName}Routes from './routes/${routesFile}';\n`;
|
|
199
|
+
routeRegistrations += `app.use('/api/${resourceName}', ${resourceName}Routes);\n`;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const serverContent = serverTemplate.replace(
|
|
203
|
+
/\/\/\s*__ROUTES__|<ROUTES>/,
|
|
204
|
+
(routeImports + routeRegistrations).trim()
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
fs.writeFileSync(path.join(backendPath, 'server.js'), serverContent);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function printCompletionInfo(backendPath, hasAuth = false, generatedResources = [], allResources = {}) {
|
|
211
|
+
console.log(chalk.cyan('📦 Generated Backend Structure:\n'));
|
|
212
|
+
console.log(` 📁 ${chalk.bold('backend/')}`);
|
|
213
|
+
console.log(` ├── server.js (Main Express server)`);
|
|
214
|
+
console.log(` ├── .env (Environment config with JWT)`);
|
|
215
|
+
console.log(` ├── package.json (Dependencies)`);
|
|
216
|
+
console.log(` ├── 📁 routes/ (API endpoints)`);
|
|
217
|
+
console.log(` │ ${hasAuth ? '├── auth.routes.js' : ''} (Auth: signup, login, profile, logout)`.replace('├── (', '├── auth.routes.js (').trim());
|
|
218
|
+
|
|
219
|
+
for (const resource of generatedResources) {
|
|
220
|
+
const isLast = resource === generatedResources[generatedResources.length - 1];
|
|
221
|
+
console.log(` │ ${isLast ? '└' : '├'}── ${resource}.routes.js (CRUD: List, Create, Read, Update, Delete)`);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
console.log(` ├── 📁 models/ (MongoDB schemas)`);
|
|
225
|
+
console.log(` │ ${hasAuth ? '├── User.js' : ''} (User with bcryptjs)`.replace('├──', hasAuth ? '├──' : '└──').trim());
|
|
226
|
+
|
|
227
|
+
for (const resource of generatedResources) {
|
|
228
|
+
const isLast = resource === generatedResources[generatedResources.length - 1];
|
|
229
|
+
const modelName = resource.charAt(0).toUpperCase() + resource.slice(1).replace(/s$/, '');
|
|
230
|
+
console.log(` │ ${isLast && !hasAuth ? '└' : '├'}── ${modelName}.js`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
console.log(` ├── 📁 middleware/ (Error handling + Logging${hasAuth ? ' + Auth' : ''})`);
|
|
234
|
+
console.log(` │ ├── errorHandler.js`);
|
|
235
|
+
console.log(` │ ├── requestLogger.js`);
|
|
236
|
+
if (hasAuth) {
|
|
237
|
+
console.log(` │ └── auth.js (JWT verification)`);
|
|
238
|
+
}
|
|
239
|
+
console.log(` └── 📁 config/ (Configuration files)\n`);
|
|
240
|
+
|
|
241
|
+
console.log(chalk.cyan('🚀 Quick Start:\n'));
|
|
242
|
+
console.log(` ${chalk.gray('$')} cd backend`);
|
|
243
|
+
console.log(` ${chalk.gray('$')} npm install # If needed`);
|
|
244
|
+
console.log(` ${chalk.gray('$')} npm start\n`);
|
|
245
|
+
|
|
246
|
+
console.log(chalk.cyan('📝 Generated Features:\n'));
|
|
247
|
+
console.log(` ✅ Express.js server with middleware`);
|
|
248
|
+
console.log(` ✅ MongoDB + Mongoose integration`);
|
|
249
|
+
console.log(` ✅ Auto-generated REST API routes`);
|
|
250
|
+
console.log(` ✅ Complete CRUD operations for all resources`);
|
|
251
|
+
console.log(` ✅ Error handling & request logging`);
|
|
252
|
+
console.log(` ✅ CORS enabled by default`);
|
|
253
|
+
console.log(` ✅ Environment variable support`);
|
|
254
|
+
|
|
255
|
+
if (hasAuth) {
|
|
256
|
+
console.log(` ✅ JWT Authentication (7-day expiry)`);
|
|
257
|
+
console.log(` ✅ Bcrypt password hashing (10 rounds)`);
|
|
258
|
+
console.log(` ✅ User model with validation`);
|
|
259
|
+
console.log(` ✅ Auth middleware for protected routes`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
console.log(` ✅ Production-ready structure\n`);
|
|
263
|
+
|
|
264
|
+
if (generatedResources.length > 0) {
|
|
265
|
+
console.log(chalk.green('📊 Generated Resources:\n'));
|
|
266
|
+
for (const resource of generatedResources) {
|
|
267
|
+
const modelName = resource.charAt(0).toUpperCase() + resource.slice(1).replace(/s$/, '');
|
|
268
|
+
console.log(` 📦 ${modelName}`);
|
|
269
|
+
console.log(` Routes: GET /api/${resource}, POST /api/${resource}, GET /api/${resource}/:id`);
|
|
270
|
+
console.log(` PUT /api/${resource}/:id, DELETE /api/${resource}/:id`);
|
|
271
|
+
}
|
|
272
|
+
console.log();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
if (hasAuth) {
|
|
276
|
+
console.log(chalk.green('🔐 Auth Endpoints:\n'));
|
|
277
|
+
console.log(` POST /api/auth/signup (Register new user)`);
|
|
278
|
+
console.log(` POST /api/auth/login (Login with email & password)`);
|
|
279
|
+
console.log(` GET /api/auth/profile (Get user profile - Protected)`);
|
|
280
|
+
console.log(` PUT /api/auth/profile (Update profile - Protected)`);
|
|
281
|
+
console.log(` POST /api/auth/logout (Logout - Protected)\n`);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
console.log(chalk.yellow('⚠️ Important:\n'));
|
|
285
|
+
console.log(` 1. MongoDB must be running locally or use MongoDB Atlas`);
|
|
286
|
+
console.log(` 2. Update .env with your database URI if needed`);
|
|
287
|
+
console.log(` 3. Update MONGODB_URI in .env for production`);
|
|
288
|
+
if (hasAuth) {
|
|
289
|
+
console.log(` 4. JWT_SECRET is auto-generated in .env`);
|
|
290
|
+
}
|
|
291
|
+
console.log(` 5. Customize models in backend/models/`);
|
|
292
|
+
console.log(` 6. Update routes in backend/routes/\n`);
|
|
293
|
+
|
|
294
|
+
console.log(chalk.green.bold('🎉 Ready to Deploy!\n'));
|
|
295
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Offline Mode
|
|
3
|
+
* Exports the production-ready generator
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { enhancedOfflineMode } from './offline.enhanced.js';
|
|
7
|
+
|
|
8
|
+
// Main export - uses enhanced production-ready version
|
|
9
|
+
export async function offlineMode(projectPath) {
|
|
10
|
+
return enhancedOfflineMode(projectPath);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default offlineMode;
|