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,179 @@
1
+ /**
2
+ * Response Helper Utility
3
+ * Standardizes API responses across the application
4
+ */
5
+ export class ResponseHelper {
6
+ /**
7
+ * Success response with data
8
+ */
9
+ static success(res, data, message = 'Success', statusCode = 200) {
10
+ return res.status(statusCode).json({
11
+ success: true,
12
+ message,
13
+ data
14
+ });
15
+ }
16
+
17
+ /**
18
+ * Paginated response
19
+ */
20
+ static paginated(res, data, pagination, message = 'Data retrieved successfully', statusCode = 200) {
21
+ return res.status(statusCode).json({
22
+ success: true,
23
+ message,
24
+ data,
25
+ pagination
26
+ });
27
+ }
28
+
29
+ /**
30
+ * Error response
31
+ */
32
+ static error(res, message = 'Internal server error', statusCode = 500, errors = null) {
33
+ const response = {
34
+ success: false,
35
+ message
36
+ };
37
+
38
+ if (errors) {
39
+ response.errors = errors;
40
+ }
41
+
42
+ return res.status(statusCode).json(response);
43
+ }
44
+
45
+ /**
46
+ * Validation error response
47
+ */
48
+ static validationError(res, errors, message = 'Validation failed') {
49
+ return res.status(400).json({
50
+ success: false,
51
+ message,
52
+ errors
53
+ });
54
+ }
55
+
56
+ /**
57
+ * Not found response
58
+ */
59
+ static notFound(res, message = 'Resource not found') {
60
+ return res.status(404).json({
61
+ success: false,
62
+ message
63
+ });
64
+ }
65
+
66
+ /**
67
+ * Unauthorized response
68
+ */
69
+ static unauthorized(res, message = 'Unauthorized access') {
70
+ return res.status(401).json({
71
+ success: false,
72
+ message
73
+ });
74
+ }
75
+
76
+ /**
77
+ * Forbidden response
78
+ */
79
+ static forbidden(res, message = 'Access forbidden') {
80
+ return res.status(403).json({
81
+ success: false,
82
+ message
83
+ });
84
+ }
85
+
86
+ /**
87
+ * Created response (201)
88
+ */
89
+ static created(res, data, message = 'Resource created successfully') {
90
+ return res.status(201).json({
91
+ success: true,
92
+ message,
93
+ data
94
+ });
95
+ }
96
+
97
+ /**
98
+ * Updated response
99
+ */
100
+ static updated(res, data, message = 'Resource updated successfully') {
101
+ return res.status(200).json({
102
+ success: true,
103
+ message,
104
+ data
105
+ });
106
+ }
107
+
108
+ /**
109
+ * Deleted response
110
+ */
111
+ static deleted(res, message = 'Resource deleted successfully') {
112
+ return res.status(200).json({
113
+ success: true,
114
+ message
115
+ });
116
+ }
117
+
118
+ /**
119
+ * Bad request response
120
+ */
121
+ static badRequest(res, message = 'Bad request', errors = null) {
122
+ const response = {
123
+ success: false,
124
+ message
125
+ };
126
+
127
+ if (errors) {
128
+ response.errors = errors;
129
+ }
130
+
131
+ return res.status(400).json(response);
132
+ }
133
+
134
+ /**
135
+ * Server error response
136
+ */
137
+ static serverError(res, error = null, message = 'Internal server error') {
138
+ const response = {
139
+ success: false,
140
+ message
141
+ };
142
+
143
+ // Only include error details in development
144
+ if (process.env.NODE_ENV === 'development' && error) {
145
+ response.error = {
146
+ message: error.message,
147
+ stack: error.stack
148
+ };
149
+ }
150
+
151
+ return res.status(500).json(response);
152
+ }
153
+
154
+ /**
155
+ * Format error details for response
156
+ */
157
+ static formatErrors(errorArray) {
158
+ return errorArray.map(err => ({
159
+ field: err.field || err.param,
160
+ message: err.message,
161
+ value: err.value
162
+ }));
163
+ }
164
+
165
+ /**
166
+ * Bulk success response
167
+ */
168
+ static bulkSuccess(res, successCount, failureCount, message = 'Bulk operation completed') {
169
+ return res.status(200).json({
170
+ success: true,
171
+ message,
172
+ data: {
173
+ total: successCount + failureCount,
174
+ successful: successCount,
175
+ failed: failureCount
176
+ }
177
+ });
178
+ }
179
+ }
@@ -0,0 +1,130 @@
1
+ import express from 'express';
2
+ import { body, param } from 'express-validator';
3
+ import { validateErrors } from '../middleware/validation.js';
4
+ import { authenticateToken } from '../middleware/auth.js';
5
+ import __MODEL_NAME__ from '../models/__MODEL_NAME__.model.js';
6
+
7
+ const router = express.Router();
8
+
9
+ // ========== GET - Fetch All / By Filter ==========
10
+ router.get('/', async (req, res, next) => {
11
+ try {
12
+ const data = await __MODEL_NAME__.find().limit(100);
13
+
14
+ if (!data || data.length === 0) {
15
+ return res.status(404).json({
16
+ success: false,
17
+ message: '__MODEL_NAME__ not found'
18
+ });
19
+ }
20
+
21
+ res.status(200).json({
22
+ success: true,
23
+ count: data.length,
24
+ data
25
+ });
26
+ } catch (error) {
27
+ next(error);
28
+ }
29
+ });
30
+
31
+ // ========== GET SINGLE ==========
32
+ router.get('/:id', async (req, res, next) => {
33
+ try {
34
+ const data = await __MODEL_NAME__.findById(req.params.id);
35
+
36
+ if (!data) {
37
+ return res.status(404).json({
38
+ success: false,
39
+ message: '__MODEL_NAME__ not found'
40
+ });
41
+ }
42
+
43
+ res.status(200).json({
44
+ success: true,
45
+ data
46
+ });
47
+ } catch (error) {
48
+ next(error);
49
+ }
50
+ });
51
+
52
+ // ========== POST - Create New ==========
53
+ router.post('/', authenticateToken, async (req, res, next) => {
54
+ try {
55
+ const newData = new __MODEL_NAME__(req.body);
56
+ const saved = await newData.save();
57
+
58
+ res.status(201).json({
59
+ success: true,
60
+ message: '__MODEL_NAME__ created successfully',
61
+ data: saved
62
+ });
63
+ } catch (error) {
64
+ if (error.name === 'ValidationError') {
65
+ return res.status(400).json({
66
+ success: false,
67
+ message: 'Validation Error',
68
+ errors: Object.values(error.errors).map(e => e.message)
69
+ });
70
+ }
71
+ next(error);
72
+ }
73
+ });
74
+
75
+ // ========== PUT - Update Entire Document ==========
76
+ router.put('/:id', authenticateToken, async (req, res, next) => {
77
+ try {
78
+ const updated = await __MODEL_NAME__.findByIdAndUpdate(
79
+ req.params.id,
80
+ req.body,
81
+ { new: true, runValidators: true }
82
+ );
83
+
84
+ if (!updated) {
85
+ return res.status(404).json({
86
+ success: false,
87
+ message: '__MODEL_NAME__ not found'
88
+ });
89
+ }
90
+
91
+ res.status(200).json({
92
+ success: true,
93
+ message: '__MODEL_NAME__ updated successfully',
94
+ data: updated
95
+ });
96
+ } catch (error) {
97
+ if (error.name === 'ValidationError') {
98
+ return res.status(400).json({
99
+ success: false,
100
+ message: 'Validation Error',
101
+ errors: Object.values(error.errors).map(e => e.message)
102
+ });
103
+ }
104
+ next(error);
105
+ }
106
+ });
107
+
108
+ // ========== DELETE ==========
109
+ router.delete('/:id', async (req, res, next) => {
110
+ try {
111
+ const deleted = await __MODEL_NAME__.findByIdAndDelete(req.params.id);
112
+
113
+ if (!deleted) {
114
+ return res.status(404).json({
115
+ success: false,
116
+ message: '__MODEL_NAME__ not found'
117
+ });
118
+ }
119
+
120
+ res.status(200).json({
121
+ success: true,
122
+ message: '__MODEL_NAME__ deleted successfully',
123
+ data: deleted
124
+ });
125
+ } catch (error) {
126
+ next(error);
127
+ }
128
+ });
129
+
130
+ export default router;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Security Middleware
3
+ * Implements security best practices
4
+ */
5
+
6
+ import helmet from 'helmet';
7
+ import mongoSanitize from 'express-mongo-sanitize';
8
+ import { body, validationResult } from 'express-validator';
9
+
10
+ // Helmet security headers
11
+ export const securityHeaders = helmet({
12
+ contentSecurityPolicy: {
13
+ directives: {
14
+ defaultSrc: ["'self'"],
15
+ styleSrc: ["'self'", "'unsafe-inline'"],
16
+ scriptSrc: ["'self'"],
17
+ imgSrc: ["'self'", 'data:', 'https:']
18
+ }
19
+ },
20
+ hsts: {
21
+ maxAge: 31536000, // 1 year
22
+ includeSubDomains: true,
23
+ preload: true
24
+ },
25
+ frameguard: {
26
+ action: 'deny'
27
+ },
28
+ referrerPolicy: {
29
+ policy: 'strict-origin-when-cross-origin'
30
+ }
31
+ });
32
+
33
+ // MongoDB injection prevention
34
+ export const sanitizeData = (req, res, next) => {
35
+ // Sanitize req.body
36
+ if (req.body) {
37
+ for (const key in req.body) {
38
+ if (typeof req.body[key] === 'string') {
39
+ req.body[key] = mongoSanitize.sanitize(req.body[key]);
40
+ }
41
+ }
42
+ }
43
+
44
+ // Sanitize req.query
45
+ if (req.query) {
46
+ for (const key in req.query) {
47
+ if (typeof req.query[key] === 'string') {
48
+ req.query[key] = mongoSanitize.sanitize(req.query[key]);
49
+ }
50
+ }
51
+ }
52
+
53
+ next();
54
+ };
55
+
56
+ // Validation error handler
57
+ export const validateErrors = (req, res, next) => {
58
+ const errors = validationResult(req);
59
+ if (!errors.isEmpty()) {
60
+ return res.status(400).json({
61
+ success: false,
62
+ errors: errors.array()
63
+ });
64
+ }
65
+ next();
66
+ };
67
+
68
+ // Common validation chains
69
+ export const validators = {
70
+ email: body('email').isEmail().normalizeEmail(),
71
+ password: body('password').isLength({ min: 8 }).withMessage('Password must be at least 8 characters'),
72
+ url: body('url').isURL(),
73
+ id: body('id').isMongoId().withMessage('Invalid ID'),
74
+ phone: body('phone').isMobilePhone().optional(),
75
+ date: body('date').isISO8601().optional()
76
+ };
77
+
78
+ export default { securityHeaders, sanitizeData, validateErrors, validators };
@@ -0,0 +1,91 @@
1
+ import 'dotenv/config';
2
+ import express from 'express';
3
+ import cors from 'cors';
4
+ import helmet from 'helmet';
5
+ import mongoose from 'mongoose';
6
+ import errorHandler from './middleware/errorHandler.js';
7
+ import requestLogger from './middleware/requestLogger.js';
8
+
9
+ const app = express();
10
+ const PORT = process.env.PORT || 5000;
11
+ const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/__DB_NAME__';
12
+
13
+ // ============ MIDDLEWARE ============
14
+ app.use(express.json({ limit: '10mb' }));
15
+ app.use(express.urlencoded({ limit: '10mb', extended: true }));
16
+ app.use(cors());
17
+ app.use(requestLogger);
18
+
19
+ // ============ ROUTES ============
20
+ // Routes should be registered with /api prefix in __ROUTES__
21
+ // Example: app.use(`/api/users`, usersRoutes);
22
+ //
23
+ // Frontend Configuration:
24
+ // āœ… CORRECT: VITE_API_URL = http://localhost:5000
25
+ // āŒ WRONG: VITE_API_URL = http://localhost:5000/api
26
+ // __ROUTES__
27
+
28
+ // ============ HEALTH CHECK ============
29
+ const healthHandler = (req, res) => {
30
+ res.status(200).json({
31
+ status: 'OK',
32
+ timestamp: new Date().toISOString(),
33
+ database: mongoose.connection.readyState ? 'Connected' : 'Disconnected'
34
+ });
35
+ };
36
+
37
+ app.get('/health', healthHandler);
38
+ app.get(`/api/health`, healthHandler);
39
+
40
+ // ============ ERROR HANDLER ============
41
+ app.use(errorHandler);
42
+
43
+ // ============ 404 HANDLER ============
44
+ app.use((req, res) => {
45
+ res.status(404).json({
46
+ error: 'Not Found',
47
+ path: req.path,
48
+ method: req.method
49
+ });
50
+ });
51
+
52
+ // ============ DATABASE CONNECTION ============
53
+ async function connectDB() {
54
+ try {
55
+ await mongoose.connect(MONGODB_URI, {
56
+ useNewUrlParser: true,
57
+ useUnifiedTopology: true,
58
+ serverSelectionTimeoutMS: 5000
59
+ });
60
+ console.log('āœ… MongoDB Connected');
61
+ } catch (error) {
62
+ console.error('āŒ MongoDB Connection Failed:', error.message);
63
+ process.exit(1);
64
+ }
65
+ }
66
+
67
+ // ============ START SERVER ============
68
+ async function startServer() {
69
+ await connectDB();
70
+
71
+ app.listen(PORT, () => {
72
+ console.log(`\nšŸš€ Backend Server Running`);
73
+ console.log(` URL: http://localhost:${PORT}`);
74
+ console.log(` Health: http://localhost:${PORT}/health`);
75
+ console.log(` API Health: http://localhost:${PORT}/api/health\n`);
76
+ });
77
+ }
78
+
79
+ // ============ GRACEFUL SHUTDOWN ============
80
+ process.on('SIGINT', async () => {
81
+ console.log('\nā›” Shutting down...');
82
+ await mongoose.disconnect();
83
+ process.exit(0);
84
+ });
85
+
86
+ startServer().catch(err => {
87
+ console.error(err);
88
+ process.exit(1);
89
+ });
90
+
91
+ export default app;