mvc-faststart-express 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 (2) hide show
  1. package/index.js +117 -0
  2. package/package.json +17 -0
package/index.js ADDED
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { execSync } from 'node:child_process';
6
+
7
+ /**
8
+ * MernMvcGenerator - A zero-dependency CLI for scaffolding MERN backends.
9
+ * Uses native node:fs and ANSI colors for maximum performance and portability.
10
+ */
11
+ class MernMvcGenerator {
12
+ constructor(projectName) {
13
+ this.projectName = projectName || 'mern-api-service';
14
+ this.targetDir = path.join(process.cwd(), this.projectName);
15
+
16
+ this.colors = {
17
+ reset: "\x1b[0m",
18
+ bold: "\x1b[1m",
19
+ cyan: "\x1b[36m",
20
+ green: "\x1b[32m",
21
+ yellow: "\x1b[33m",
22
+ red: "\x1b[31m",
23
+ };
24
+ }
25
+
26
+ log(color, message, isBold = false) {
27
+ const style = isBold ? this.colors.bold : "";
28
+ console.log(`${style}${color}${message}${this.colors.reset}`);
29
+ }
30
+
31
+ getTemplates() {
32
+ return {
33
+ ".env": `PORT=5000\nMONGODB_URL=mongodb://127.0.0.1:27017/${this.projectName}\nNODE_ENV=development`,
34
+
35
+ "package.json": JSON.stringify({
36
+ name: this.projectName,
37
+ version: "1.0.0",
38
+ type: "module",
39
+ main: "src/server.js",
40
+ scripts: {
41
+ "start": "node src/server.js",
42
+ "dev": "nodemon src/server.js"
43
+ }
44
+ }, null, 2),
45
+
46
+ "src/server.js": `import mongoose from 'mongoose';\nimport app from './app.js';\nimport './config/db.js';\n\nconst PORT = process.env.PORT || 5000;\n\napp.listen(PORT, () => {\n console.log(\`šŸš€ Server running in \${process.env.NODE_ENV} mode on port \${PORT}\`);\n});`,
47
+
48
+ "src/app.js": `import express from 'express';\nimport cors from 'cors';\nimport helmet from 'helmet';\nimport routes from './routes/index.js';\nimport { errorConverter, errorHandler } from './middlewares/error.js';\nimport ApiError from './utils/ApiError.js';\n\nconst app = express();\napp.use(helmet());\napp.use(express.json());\napp.use(cors());\napp.use('/v1', routes);\n\napp.use((req, res, next) => {\n next(new ApiError(404, 'Not found'));\n});\n\napp.use(errorConverter);\napp.use(errorHandler);\n\nexport default app;`,
49
+
50
+ "src/config/db.js": `import mongoose from 'mongoose';\nimport dotenv from 'dotenv';\ndotenv.config();\n\nmongoose.connect(process.env.MONGODB_URL)\n .then(() => console.log('āœ… Connected to MongoDB'))\n .catch((err) => console.error('āŒ MongoDB connection error:', err));`,
51
+
52
+ // --- NEW: MODELS FOLDER ---
53
+ "src/models/user.model.js": `import mongoose from 'mongoose';\n\nconst userSchema = mongoose.Schema(\n {\n name: { type: String, required: true },\n email: { type: String, required: true, unique: true },\n password: { type: String, required: true },\n },\n { timestamps: true }\n);\n\nconst User = mongoose.model('User', userSchema);\nexport default User;`,
54
+
55
+ "src/models/index.js": `export { default as User } from './user.model.js';`,
56
+
57
+ "src/utils/catchAsync.js": `export default (fn) => (req, res, next) => {\n Promise.resolve(fn(req, res, next)).catch((err) => next(err));\n};`,
58
+
59
+ "src/utils/ApiError.js": `class ApiError extends Error {\n constructor(statusCode, message, isOperational = true, stack = '') {\n super(message);\n this.statusCode = statusCode;\n this.isOperational = isOperational;\n if (stack) { this.stack = stack; } else { Error.captureStackTrace(this, this.constructor); }\n }\n}\nexport default ApiError;`,
60
+
61
+ "src/middlewares/error.js": `import ApiError from '../utils/ApiError.js';\n\nexport const errorConverter = (err, req, res, next) => {\n let error = err;\n if (!(error instanceof ApiError)) {\n const statusCode = error.statusCode || 500;\n const message = error.message || 'Internal Server Error';\n error = new ApiError(statusCode, message, false, err.stack);\n }\n next(error);\n};\n\nexport const errorHandler = (err, req, res, next) => {\n let { statusCode, message } = err;\n res.status(statusCode).send({\n code: statusCode, \n message, \n ...(process.env.NODE_ENV === 'development' && { stack: err.stack }),\n });\n};`,
62
+
63
+ "src/routes/index.js": `import express from 'express';\nimport userRoute from './user.route.js';\nconst router = express.Router();\nrouter.use('/users', userRoute);\nexport default router;`,
64
+
65
+ "src/routes/user.route.js": `import express from 'express';\nimport { userController } from '../controllers/index.js';\nconst router = express.Router();\nrouter.get('/', userController.getUsers);\nexport default router;`,
66
+
67
+ "src/controllers/index.js": `export * as userController from './user.controller.js';`,
68
+
69
+ "src/controllers/user.controller.js": `import catchAsync from '../utils/catchAsync.js';\nimport { userService } from '../services/index.js';\nexport const getUsers = catchAsync(async (req, res) => {\n const users = await userService.queryUsers();\n res.send(users);\n});`,
70
+
71
+ "src/services/index.js": `export * as userService from './user.service.js';`,
72
+
73
+ // --- UPDATED: SERVICE LAYER CALLING MODEL ---
74
+ "src/services/user.service.js": `import User from '../models/user.model.js';\n\nexport const queryUsers = async () => {\n // Logic to fetch users from MongoDB\n return await User.find({});\n};`,
75
+ };
76
+ }
77
+
78
+ generate() {
79
+ this.log(this.colors.cyan, `\nšŸ›  Building Professional MERN Backend: ${this.projectName}\n`, true);
80
+
81
+ if (fs.existsSync(this.targetDir)) {
82
+ this.log(this.colors.red, `āŒ Error: Directory "${this.projectName}" already exists.`);
83
+ process.exit(1);
84
+ }
85
+
86
+ try {
87
+ const templates = this.getTemplates();
88
+
89
+ Object.entries(templates).forEach(([filePath, content]) => {
90
+ const fullPath = path.join(this.targetDir, filePath);
91
+ const folderPath = path.dirname(fullPath);
92
+
93
+ if (!fs.existsSync(folderPath)) {
94
+ fs.mkdirSync(folderPath, { recursive: true });
95
+ }
96
+
97
+ fs.writeFileSync(fullPath, content, 'utf8');
98
+ });
99
+
100
+ this.log(this.colors.green, "āœ… File structure and templates created.");
101
+
102
+ this.log(this.colors.yellow, "šŸ“¦ Running npm install...");
103
+ execSync(`cd "${this.targetDir}" && npm install express mongoose dotenv cors helmet`, { stdio: 'inherit' });
104
+ execSync(`cd "${this.targetDir}" && npm install -D nodemon`, { stdio: 'inherit' });
105
+
106
+ this.log(this.colors.green, `\n✨ Successfully created ${this.projectName}!`, true);
107
+ this.log(this.colors.white, `\nNext steps:\n 1. cd ${this.projectName}\n 2. npm run dev\n`);
108
+
109
+ } catch (error) {
110
+ this.log(this.colors.red, `šŸ’„ Fatal Error: ${error.message}`);
111
+ process.exit(1);
112
+ }
113
+ }
114
+ }
115
+
116
+ const generator = new MernMvcGenerator(process.argv[2]);
117
+ generator.generate();
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "mvc-faststart-express",
3
+ "version": "1.0.0",
4
+ "description": "A zero-dependency CLI for scaffolding production-ready MERN MVC architecture",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "bin": {
8
+ "mvc-faststart-express": "index.js"
9
+ },
10
+ "keywords": ["express", "mvc", "mern", "boilerplate", "cli", "generator"],
11
+ "author": "Vinay Kumar",
12
+ "license": "MIT",
13
+ "engines": {
14
+ "node": ">=16.0.0"
15
+ },
16
+ "dependencies": {}
17
+ }