express-backend-starter 1.0.1

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 ADDED
@@ -0,0 +1,236 @@
1
+ # 🚀 Express Backend Starter CLI
2
+
3
+ A production-ready CLI tool to scaffold Express.js/Node.js backend projects in seconds.
4
+
5
+ ![Version](https://img.shields.io/badge/version-1.0.0-blue.svg)
6
+ ![License](https://img.shields.io/badge/license-MIT-green.svg)
7
+
8
+ ## ✨ Features
9
+
10
+ - 🎯 **Interactive Setup** - Guided prompts for project configuration
11
+ - 🗄️ **Multiple Databases** - MongoDB, PostgreSQL, or MySQL support
12
+ - 📚 **Swagger Docs** - Auto-generated API documentation
13
+ - ✅ **Zod Validation** - Type-safe request validation
14
+ - 📧 **Email Support** - Nodemailer integration
15
+ - 🔒 **Security First** - Helmet, CORS, rate limiting, JWT auth
16
+ - 📁 **Clean Architecture** - Professional folder structure
17
+ - ⚡ **Production Ready** - Best practices built-in
18
+
19
+ ## 🚀 Quick Start
20
+
21
+ ### Using npx (Recommended)
22
+
23
+ ```bash
24
+ npx express-backend-starter
25
+ ```
26
+
27
+ ### Or Install Globally
28
+
29
+ ```bash
30
+ npm install -g express-backend-starter
31
+ express-backend-starter
32
+ ```
33
+
34
+ ## 📋 What Gets Generated?
35
+
36
+ ### Always Included
37
+
38
+ - ✅ Express.js server setup
39
+ - ✅ JWT authentication middleware
40
+ - ✅ Error handling middleware
41
+ - ✅ CORS configuration
42
+ - ✅ Rate limiting
43
+ - ✅ Helmet security headers
44
+ - ✅ Cookie parser
45
+ - ✅ Bcrypt password hashing
46
+ - ✅ File upload with Multer
47
+ - ✅ Environment configuration
48
+ - ✅ Professional folder structure
49
+
50
+ ### Database Options
51
+
52
+ - **MongoDB** → Mongoose ORM
53
+ - **PostgreSQL** → Prisma ORM
54
+ - **MySQL** → Prisma ORM
55
+
56
+ ### Optional Features
57
+
58
+ - 📚 **Swagger** → API documentation UI
59
+ - ✅ **Zod** → Runtime validation
60
+ - 📧 **Nodemailer** → Email functionality
61
+
62
+ ## 🎬 Demo
63
+
64
+ ```bash
65
+ $ npx express-backend-starter
66
+
67
+ 🚀 Welcome to Express Backend Starter CLI
68
+
69
+ Let's scaffold your backend project...
70
+
71
+ ? What is your project name? my-awesome-api
72
+ ? Which database do you want to use? MongoDB
73
+ ? Include Swagger documentation? Yes
74
+ ? Include Zod validation? Yes
75
+ ? Include Nodemailer for email functionality? No
76
+
77
+ ✅ Project created successfully!
78
+
79
+ Next steps:
80
+ cd my-awesome-api
81
+ npm run dev
82
+
83
+ Happy coding! 🎉
84
+ ```
85
+
86
+ ## 📁 Generated Project Structure
87
+
88
+ ```
89
+ my-awesome-api/
90
+ ├── .env.example
91
+ ├── .gitignore
92
+ ├── README.md
93
+ ├── package.json
94
+ └── src/
95
+ ├── app.js # Main application
96
+ ├── config/
97
+ │ ├── db.js # Database connection
98
+ │ └── swagger.js # Swagger config (optional)
99
+ ├── controllers/
100
+ │ └── healthController.js # Sample controller
101
+ ├── middleware/
102
+ │ ├── auth.js # JWT authentication
103
+ │ └── errorHandler.js # Global error handler
104
+ ├── models/
105
+ │ └── User.js # Sample model
106
+ ├── routes/
107
+ │ └── healthRoutes.js # Sample routes
108
+ ├── services/ # Business logic
109
+ └── utils/
110
+ └── validation.js # Zod schemas (optional)
111
+ ```
112
+
113
+ ## 🛠️ Tech Stack
114
+
115
+ - **Framework:** Express.js
116
+ - **Authentication:** JWT (jsonwebtoken)
117
+ - **Security:** Helmet, CORS, express-rate-limit
118
+ - **Password Hashing:** bcryptjs
119
+ - **File Upload:** Multer
120
+ - **Database ORMs:** Mongoose (MongoDB) or Prisma (PostgreSQL/MySQL)
121
+ - **Documentation:** Swagger (optional)
122
+ - **Validation:** Zod (optional)
123
+ - **Email:** Nodemailer (optional)
124
+
125
+ ## 📖 Usage
126
+
127
+ ### 1. Run the CLI
128
+
129
+ ```bash
130
+ npx express-backend-starter
131
+ ```
132
+
133
+ ### 2. Answer the Prompts
134
+
135
+ The CLI will ask you:
136
+ - Project name
137
+ - Database choice (MongoDB/PostgreSQL/MySQL)
138
+ - Include Swagger? (y/n)
139
+ - Include Zod? (y/n)
140
+ - Include Nodemailer? (y/n)
141
+
142
+ ### 3. Navigate to Your Project
143
+
144
+ ```bash
145
+ cd your-project-name
146
+ ```
147
+
148
+ ### 4. Configure Environment
149
+
150
+ ```bash
151
+ cp .env.example .env
152
+ # Edit .env with your settings
153
+ ```
154
+
155
+ ### 5. For Prisma (PostgreSQL/MySQL)
156
+
157
+ ```bash
158
+ npx prisma migrate dev
159
+ npx prisma generate
160
+ ```
161
+
162
+ ### 6. Start Development
163
+
164
+ ```bash
165
+ npm run dev
166
+ ```
167
+
168
+ Your server will be running at `http://localhost:5000`
169
+
170
+ ## 🌐 API Endpoints
171
+
172
+ Generated project includes:
173
+
174
+ - `GET /` - Welcome message
175
+ - `GET /api/health` - Health check
176
+ - `GET /api/health/info` - Server info
177
+ - `GET /api-docs` - Swagger UI (if enabled)
178
+
179
+ ## 🔧 Available Scripts
180
+
181
+ ```json
182
+ {
183
+ "dev": "nodemon src/app.js", // Development with auto-reload
184
+ "start": "node src/app.js" // Production start
185
+ }
186
+ ```
187
+
188
+ ## 🔐 Environment Variables
189
+
190
+ The generated `.env.example` includes:
191
+
192
+ ```env
193
+ PORT=5000
194
+ NODE_ENV=development
195
+ JWT_SECRET=your_secret_key
196
+ JWT_EXPIRE=7d
197
+
198
+ # Database URLs (based on your choice)
199
+ MONGO_URI=mongodb://localhost:27017/dbname
200
+ # or
201
+ DATABASE_URL=postgresql://user:pass@localhost:5432/dbname
202
+
203
+ # Optional
204
+ EMAIL_HOST=smtp.gmail.com
205
+ EMAIL_USER=your@email.com
206
+ # ... and more
207
+ ```
208
+
209
+ ## 📚 Documentation
210
+
211
+ For detailed development guide, see [devGuide.md](./devGuide.md)
212
+
213
+ ## 🤝 Contributing
214
+
215
+ Contributions are welcome! Please feel free to submit a Pull Request.
216
+
217
+ ## 📄 License
218
+
219
+ MIT License - see LICENSE file for details
220
+
221
+ ## 🙏 Credits
222
+
223
+ Built with:
224
+ - [Commander.js](https://github.com/tj/commander.js)
225
+ - [Inquirer.js](https://github.com/SBoudrias/Inquirer.js)
226
+ - [Chalk](https://github.com/chalk/chalk)
227
+ - [Ora](https://github.com/sindresorhus/ora)
228
+ - [Execa](https://github.com/sindresorhus/execa)
229
+
230
+ ## 💬 Support
231
+
232
+ If you have any questions or issues, please open an issue on GitHub.
233
+
234
+ ---
235
+
236
+ **Made with ❤️ for the Node.js community**
package/bin/cli.js ADDED
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Express Backend Starter CLI
5
+ * Main entry point for the CLI tool
6
+ */
7
+
8
+ import { Command } from 'commander';
9
+ import chalk from 'chalk';
10
+ import { getUserInput } from '../src/prompts.js';
11
+ import { installDependencies } from '../src/installers.js';
12
+ import { generateProject } from '../src/generators.js';
13
+ import ora from 'ora';
14
+ import path from 'path';
15
+ import { fileURLToPath } from 'url';
16
+ import fs from 'fs-extra';
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+
21
+ // Read package.json for version
22
+ const packageJson = JSON.parse(
23
+ await fs.readFile(path.join(__dirname, '../package.json'), 'utf-8')
24
+ );
25
+
26
+ const program = new Command();
27
+
28
+ program
29
+ .name('express-backend-starter')
30
+ .description('Scaffold a production-ready Express.js/Node.js backend project')
31
+ .version(packageJson.version)
32
+ .action(async () => {
33
+ console.log(chalk.cyan.bold('\n🚀 Welcome to Express Backend Starter CLI\n'));
34
+ console.log(chalk.gray('Let\'s scaffold your backend project...\n'));
35
+
36
+ try {
37
+ // Step 1: Get user input through interactive prompts
38
+ const spinner = ora('Preparing questions...').start();
39
+ spinner.succeed('Ready!');
40
+
41
+ const answers = await getUserInput();
42
+
43
+ // Step 2: Create project directory
44
+ const projectPath = path.join(process.cwd(), answers.projectName);
45
+
46
+ const creatingSpinner = ora('Creating project directory...').start();
47
+
48
+ if (await fs.pathExists(projectPath)) {
49
+ creatingSpinner.fail(chalk.red(`Directory "${answers.projectName}" already exists!`));
50
+ process.exit(1);
51
+ }
52
+
53
+ await fs.ensureDir(projectPath);
54
+ creatingSpinner.succeed(chalk.green('Project directory created'));
55
+
56
+ // Step 3: Initialize npm project
57
+ const initSpinner = ora('Initializing npm project...').start();
58
+ await fs.writeJSON(path.join(projectPath, 'package.json'), {
59
+ name: answers.projectName,
60
+ version: '1.0.0',
61
+ description: 'Backend project generated by Express Backend Starter CLI',
62
+ main: 'src/app.js',
63
+ type: 'module',
64
+ scripts: {
65
+ dev: 'nodemon src/app.js',
66
+ start: 'node src/app.js'
67
+ },
68
+ keywords: [],
69
+ author: '',
70
+ license: 'ISC'
71
+ }, { spaces: 2 });
72
+ initSpinner.succeed(chalk.green('npm project initialized'));
73
+
74
+ // Step 4: Install dependencies
75
+ await installDependencies(projectPath, answers);
76
+
77
+ // Step 5: Generate project structure and files
78
+ await generateProject(projectPath, answers);
79
+
80
+ // Success message
81
+ console.log(chalk.green.bold('\n✅ Project created successfully!\n'));
82
+ console.log(chalk.cyan('Next steps:'));
83
+ console.log(chalk.white(` cd ${answers.projectName}`));
84
+
85
+ // Special instructions for Prisma databases
86
+ if (answers.database === 'postgresql' || answers.database === 'mysql') {
87
+ console.log(chalk.yellow('\n 📝 Configure your database:'));
88
+ console.log(chalk.white(' 1. Update DATABASE_URL in .env file'));
89
+ console.log(chalk.white(' 2. Run: npx prisma migrate dev'));
90
+ console.log(chalk.white(' 3. Then: npm run dev\n'));
91
+ } else {
92
+ console.log(chalk.white(' npm run dev\n'));
93
+ }
94
+
95
+ console.log(chalk.gray('Happy coding! 🎉\n'));
96
+
97
+ } catch (error) {
98
+ console.error(chalk.red.bold('\n❌ Error:'), error.message);
99
+ process.exit(1);
100
+ }
101
+ });
102
+
103
+ program.parse(process.argv);
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "express-backend-starter",
3
+ "version": "1.0.1",
4
+ "description": "A production-ready CLI tool to scaffold Express.js/Node.js backend projects",
5
+ "license": "MIT",
6
+ "author": "Aayush Sah",
7
+ "type": "module",
8
+ "main": "index.js",
9
+ "bin": {
10
+ "express-backend-starter": "./bin/cli.js"
11
+ },
12
+ "keywords": [
13
+ "express",
14
+ "backend",
15
+ "cli",
16
+ "scaffold",
17
+ "nodejs",
18
+ "generator",
19
+ "starter"
20
+ ],
21
+ "scripts": {
22
+ "test": "echo \"Error: no test specified\" && exit 1"
23
+ },
24
+ "dependencies": {
25
+ "chalk": "^5.6.2",
26
+ "commander": "^14.0.2",
27
+ "execa": "^9.6.1",
28
+ "fs-extra": "^11.3.3",
29
+ "inquirer": "^8.2.6",
30
+ "ora": "^9.1.0"
31
+ },
32
+ "files": [
33
+ "bin",
34
+ "src"
35
+ ],
36
+ "engines": {
37
+ "node": ">=18"
38
+ }
39
+ }
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Database configuration templates
3
+ * Provides database connection setup for different databases
4
+ */
5
+
6
+ /**
7
+ * Get database configuration based on database type
8
+ * @param {string} database - Database type (mongodb, postgresql, mysql)
9
+ * @returns {string} Database configuration code
10
+ */
11
+ export function getDbConfig(database) {
12
+ switch (database) {
13
+ case 'mongodb':
14
+ return getMongoDbConfig();
15
+
16
+ case 'postgresql':
17
+ return getPostgreSQLConfig();
18
+
19
+ case 'mysql':
20
+ return getMySQLConfig();
21
+
22
+ default:
23
+ return getMongoDbConfig();
24
+ }
25
+ }
26
+
27
+ /**
28
+ * MongoDB configuration with Mongoose
29
+ */
30
+ function getMongoDbConfig() {
31
+ return `/**
32
+ * MongoDB Database Configuration
33
+ * Using Mongoose ORM
34
+ */
35
+
36
+ import mongoose from 'mongoose';
37
+ import chalk from 'chalk';
38
+
39
+ /**
40
+ * Connect to MongoDB database
41
+ */
42
+ export async function connectDB() {
43
+ try {
44
+ const conn = await mongoose.connect(process.env.MONGO_URI, {
45
+ // Mongoose 6+ no longer needs these options:
46
+ // useNewUrlParser: true,
47
+ // useUnifiedTopology: true,
48
+ });
49
+
50
+ console.log(chalk.green.bold(\`✅ MongoDB Connected: \${conn.connection.host}\`));
51
+
52
+ // Connection events
53
+ mongoose.connection.on('error', (err) => {
54
+ console.error(chalk.red('MongoDB connection error:'), err);
55
+ });
56
+
57
+ mongoose.connection.on('disconnected', () => {
58
+ console.log(chalk.yellow('MongoDB disconnected'));
59
+ });
60
+
61
+ // Graceful shutdown
62
+ process.on('SIGINT', async () => {
63
+ await mongoose.connection.close();
64
+ console.log(chalk.yellow('MongoDB connection closed due to app termination'));
65
+ process.exit(0);
66
+ });
67
+
68
+ } catch (error) {
69
+ console.error(chalk.red.bold('❌ MongoDB connection failed:'), error.message);
70
+ process.exit(1);
71
+ }
72
+ }
73
+ `;
74
+ }
75
+
76
+ /**
77
+ * PostgreSQL configuration with Prisma
78
+ */
79
+ function getPostgreSQLConfig() {
80
+ return `/**
81
+ * PostgreSQL Database Configuration
82
+ * Using Prisma ORM
83
+ */
84
+
85
+ import { PrismaClient } from '@prisma/client';
86
+ import chalk from 'chalk';
87
+
88
+ // Initialize Prisma Client
89
+ const prisma = new PrismaClient({
90
+ log: ['query', 'info', 'warn', 'error'],
91
+ });
92
+
93
+ /**
94
+ * Connect to PostgreSQL database
95
+ */
96
+ export async function connectDB() {
97
+ try {
98
+ await prisma.$connect();
99
+ console.log(chalk.green.bold('✅ PostgreSQL Connected via Prisma'));
100
+
101
+ // Graceful shutdown
102
+ process.on('SIGINT', async () => {
103
+ await prisma.$disconnect();
104
+ console.log(chalk.yellow('PostgreSQL connection closed due to app termination'));
105
+ process.exit(0);
106
+ });
107
+
108
+ process.on('SIGTERM', async () => {
109
+ await prisma.$disconnect();
110
+ process.exit(0);
111
+ });
112
+
113
+ } catch (error) {
114
+ console.error(chalk.red.bold('❌ PostgreSQL connection failed:'), error.message);
115
+ await prisma.$disconnect();
116
+ process.exit(1);
117
+ }
118
+ }
119
+
120
+ // Export prisma instance for use in other modules
121
+ export { prisma };
122
+ `;
123
+ }
124
+
125
+ /**
126
+ * MySQL configuration with Prisma
127
+ */
128
+ function getMySQLConfig() {
129
+ return `/**
130
+ * MySQL Database Configuration
131
+ * Using Prisma ORM
132
+ */
133
+
134
+ import { PrismaClient } from '@prisma/client';
135
+ import chalk from 'chalk';
136
+
137
+ // Initialize Prisma Client
138
+ const prisma = new PrismaClient({
139
+ log: ['query', 'info', 'warn', 'error'],
140
+ });
141
+
142
+ /**
143
+ * Connect to MySQL database
144
+ */
145
+ export async function connectDB() {
146
+ try {
147
+ await prisma.$connect();
148
+ console.log(chalk.green.bold('✅ MySQL Connected via Prisma'));
149
+
150
+ // Graceful shutdown
151
+ process.on('SIGINT', async () => {
152
+ await prisma.$disconnect();
153
+ console.log(chalk.yellow('MySQL connection closed due to app termination'));
154
+ process.exit(0);
155
+ });
156
+
157
+ process.on('SIGTERM', async () => {
158
+ await prisma.$disconnect();
159
+ process.exit(0);
160
+ });
161
+
162
+ } catch (error) {
163
+ console.error(chalk.red.bold('❌ MySQL connection failed:'), error.message);
164
+ await prisma.$disconnect();
165
+ process.exit(1);
166
+ }
167
+ }
168
+
169
+ // Export prisma instance for use in other modules
170
+ export { prisma };
171
+ `;
172
+ }
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Project structure and file generation
3
+ * Creates folders and files for the new project
4
+ */
5
+
6
+ import fs from 'fs-extra';
7
+ import path from 'path';
8
+ import ora from 'ora';
9
+ import chalk from 'chalk';
10
+ import { getDbConfig } from './db-config.js';
11
+ import * as templates from './templates/index.js';
12
+
13
+ /**
14
+ * Generate the complete project structure
15
+ * @param {string} projectPath - Path to the project directory
16
+ * @param {Object} answers - User's answers from prompts
17
+ */
18
+ export async function generateProject(projectPath, answers) {
19
+ const spinner = ora('Generating project structure...').start();
20
+
21
+ try {
22
+ // Create folder structure
23
+ await createFolderStructure(projectPath);
24
+ spinner.text = 'Folder structure created';
25
+
26
+ // Generate configuration files
27
+ await generateConfigFiles(projectPath, answers);
28
+ spinner.text = 'Configuration files created';
29
+
30
+ // Generate source files
31
+ await generateSourceFiles(projectPath, answers);
32
+ spinner.text = 'Source files created';
33
+
34
+ // Generate README
35
+ await generateReadme(projectPath, answers);
36
+
37
+ spinner.succeed(chalk.green('Project structure generated'));
38
+ } catch (error) {
39
+ spinner.fail(chalk.red('Failed to generate project structure'));
40
+ throw error;
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Create the folder structure
46
+ * @param {string} projectPath - Path to the project directory
47
+ */
48
+ async function createFolderStructure(projectPath) {
49
+ const folders = [
50
+ 'src',
51
+ 'src/controllers',
52
+ 'src/routes',
53
+ 'src/middleware',
54
+ 'src/config',
55
+ 'src/services',
56
+ 'src/models',
57
+ 'src/utils'
58
+ ];
59
+
60
+ for (const folder of folders) {
61
+ await fs.ensureDir(path.join(projectPath, folder));
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Generate configuration files
67
+ * @param {string} projectPath - Path to the project directory
68
+ * @param {Object} answers - User's answers
69
+ */
70
+ async function generateConfigFiles(projectPath, answers) {
71
+ // .env.example
72
+ const envExample = templates.generateEnvExample(answers);
73
+ await fs.writeFile(path.join(projectPath, '.env.example'), envExample);
74
+
75
+ // .gitignore
76
+ const gitignore = templates.generateGitignore();
77
+ await fs.writeFile(path.join(projectPath, '.gitignore'), gitignore);
78
+
79
+ // Database configuration
80
+ const dbConfig = getDbConfig(answers.database);
81
+ await fs.writeFile(path.join(projectPath, 'src/config/db.js'), dbConfig);
82
+ }
83
+
84
+ /**
85
+ * Generate source files
86
+ * @param {string} projectPath - Path to the project directory
87
+ * @param {Object} answers - User's answers
88
+ */
89
+ async function generateSourceFiles(projectPath, answers) {
90
+ // Main app.js
91
+ const appJs = templates.generateAppJs(answers);
92
+ await fs.writeFile(path.join(projectPath, 'src/app.js'), appJs);
93
+
94
+ // Sample controller
95
+ const sampleController = templates.generateSampleController();
96
+ await fs.writeFile(path.join(projectPath, 'src/controllers/healthController.js'), sampleController);
97
+
98
+ // Sample route
99
+ const sampleRoute = templates.generateSampleRoute();
100
+ await fs.writeFile(path.join(projectPath, 'src/routes/healthRoutes.js'), sampleRoute);
101
+
102
+ // Error middleware
103
+ const errorMiddleware = templates.generateErrorMiddleware();
104
+ await fs.writeFile(path.join(projectPath, 'src/middleware/errorHandler.js'), errorMiddleware);
105
+
106
+ // Auth middleware (JWT)
107
+ const authMiddleware = templates.generateAuthMiddleware();
108
+ await fs.writeFile(path.join(projectPath, 'src/middleware/auth.js'), authMiddleware);
109
+
110
+ // Swagger configuration (if selected)
111
+ if (answers.includeSwagger) {
112
+ const swaggerConfig = templates.generateSwaggerConfig(answers);
113
+ await fs.writeFile(path.join(projectPath, 'src/config/swagger.js'), swaggerConfig);
114
+ }
115
+
116
+ // Nodemailer configuration (if selected)
117
+ if (answers.includeNodemailer) {
118
+ const nodemailerConfig = templates.generateNodemailerConfig();
119
+ await fs.writeFile(path.join(projectPath, 'src/config/nodemailer.js'), nodemailerConfig);
120
+ }
121
+
122
+ // Zod validation example (if selected)
123
+ if (answers.includeZod) {
124
+ const zodExample = templates.generateZodValidation();
125
+ await fs.writeFile(path.join(projectPath, 'src/utils/validation.js'), zodExample);
126
+ }
127
+
128
+ // Sample model (database-specific)
129
+ if (answers.database === 'mongodb') {
130
+ const userModel = templates.generateMongooseModel();
131
+ await fs.writeFile(path.join(projectPath, 'src/models/User.js'), userModel);
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Generate README.md
137
+ * @param {string} projectPath - Path to the project directory
138
+ * @param {Object} answers - User's answers
139
+ */
140
+ async function generateReadme(projectPath, answers) {
141
+ const readme = templates.generateReadme(answers);
142
+ await fs.writeFile(path.join(projectPath, 'README.md'), readme);
143
+ }