instant-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.
- package/README.md +166 -0
- package/index.js +258 -0
- package/package.json +47 -0
- package/templates/.env.example +4 -0
- package/templates/app.js +25 -0
- package/templates/config/db.js +17 -0
- package/templates/controllers/authController.js +61 -0
- package/templates/middlewares/authMiddleware.js +31 -0
- package/templates/models/User.js +36 -0
- package/templates/routes/authRoutes.js +11 -0
- package/templates/server.js +12 -0
package/README.md
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<h1 align="center">⚡ instant-express</h1>
|
|
3
|
+
<p align="center">Generate a production-ready Express.js + MongoDB backend in seconds.</p>
|
|
4
|
+
</p>
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="https://www.npmjs.com/package/instant-express"><img src="https://img.shields.io/npm/v/instant-express?color=blue&label=npm" alt="npm version"></a>
|
|
8
|
+
<a href="https://www.npmjs.com/package/instant-express"><img src="https://img.shields.io/npm/dm/instant-express?color=green" alt="npm downloads"></a>
|
|
9
|
+
<a href="https://github.com/prashantdevelopment/gen-server/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/instant-express?color=yellow" alt="license"></a>
|
|
10
|
+
<a href="https://github.com/prashantdevelopment/gen-server"><img src="https://img.shields.io/github/stars/prashantdevelopment/gen-server?style=social" alt="GitHub stars"></a>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🚀 Quick Start
|
|
16
|
+
|
|
17
|
+
No installation needed. Just run:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx instant-express my-project
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
That's it! Your backend is ready. 🎉
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 🎬 Demo
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
$ npx instant-express my-app
|
|
31
|
+
|
|
32
|
+
🚀 Instant-Express CLI
|
|
33
|
+
|
|
34
|
+
? Enter port number: 5000
|
|
35
|
+
? Include JWT Authentication? Yes
|
|
36
|
+
? Run npm install automatically? Yes
|
|
37
|
+
|
|
38
|
+
📁 Folder created: my-app/
|
|
39
|
+
✅ Core files generated!
|
|
40
|
+
✅ Auth files generated (User model, controller, routes, middleware)!
|
|
41
|
+
✅ package.json created!
|
|
42
|
+
✅ .env file created!
|
|
43
|
+
📦 Installing dependencies...
|
|
44
|
+
✅ Dependencies installed successfully!
|
|
45
|
+
|
|
46
|
+
🎉 my-app successfully generated!
|
|
47
|
+
|
|
48
|
+
Next steps:
|
|
49
|
+
cd my-app
|
|
50
|
+
npm run dev
|
|
51
|
+
|
|
52
|
+
Happy coding! 🚀
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## ✨ Features
|
|
58
|
+
|
|
59
|
+
| Feature | Description |
|
|
60
|
+
|---------|-------------|
|
|
61
|
+
| ⚡ **One Command Setup** | `npx instant-express my-app` — full backend ready in seconds |
|
|
62
|
+
| 🔐 **Optional JWT Auth** | Signup, Login, Logout with protected routes — choose at runtime |
|
|
63
|
+
| 🧠 **Smart Dependencies** | Auth packages (`bcryptjs`, `jsonwebtoken`) only install when needed |
|
|
64
|
+
| 🛡️ **DNS Fix Built-in** | MongoDB Atlas DNS issues auto-resolved with Google & Cloudflare DNS |
|
|
65
|
+
| 📦 **Auto npm install** | Dependencies installed automatically — skip if you prefer manual |
|
|
66
|
+
| 🗂️ **MVC Architecture** | Clean folder structure — config, controllers, routes, middlewares, models, services, utils |
|
|
67
|
+
| 🎯 **Interactive CLI** | No config files needed — just answer simple prompts |
|
|
68
|
+
| 📝 **Auto-generated files** | `.env`, `.env.example`, `.gitignore`, `package.json` — all ready |
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 🎯 Generated Project Structure
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
my-project/
|
|
76
|
+
├── config/
|
|
77
|
+
│ └── db.js # MongoDB connection with DNS fix
|
|
78
|
+
├── controllers/
|
|
79
|
+
│ └── authController.js # Signup, Login, Logout (if auth selected)
|
|
80
|
+
├── middlewares/
|
|
81
|
+
│ └── authMiddleware.js # JWT token verification (if auth selected)
|
|
82
|
+
├── models/
|
|
83
|
+
│ └── User.js # User schema with bcrypt (if auth selected)
|
|
84
|
+
├── routes/
|
|
85
|
+
│ └── authRoutes.js # Auth API routes (if auth selected)
|
|
86
|
+
├── services/ # Business logic (empty — ready for you)
|
|
87
|
+
├── utils/ # Helper functions (empty — ready for you)
|
|
88
|
+
├── app.js # Express app setup with middlewares
|
|
89
|
+
├── server.js # Server entry point
|
|
90
|
+
├── .env # Environment variables (auto-generated)
|
|
91
|
+
├── .env.example # Environment template for reference
|
|
92
|
+
├── .gitignore # Git ignore rules
|
|
93
|
+
└── package.json # Project config with all dependencies
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## ⚙️ CLI Options
|
|
99
|
+
|
|
100
|
+
| Prompt | Description | Default |
|
|
101
|
+
|--------|-------------|---------|
|
|
102
|
+
| Port number | Server will run on this port | `5000` |
|
|
103
|
+
| JWT Authentication | Include signup/login/logout with JWT | `Yes` |
|
|
104
|
+
| Auto npm install | Install dependencies automatically | `Yes` |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## 🛡️ MongoDB DNS Fix (Built-in)
|
|
109
|
+
|
|
110
|
+
Many developers face `querySrv ESERVFAIL` or `ENOTFOUND` errors when connecting to **MongoDB Atlas** — especially on certain ISPs.
|
|
111
|
+
|
|
112
|
+
instant-express **automatically configures** reliable DNS resolvers in the generated `db.js`:
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
import dns from 'dns';
|
|
116
|
+
dns.setServers(['1.1.1.1', '8.8.8.8']); // Cloudflare + Google DNS
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
No more connection issues. It just works. ✅
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🚀 After Generation
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
cd my-project
|
|
127
|
+
npm run dev
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Output:**
|
|
131
|
+
```
|
|
132
|
+
✅ MongoDB Connected: localhost
|
|
133
|
+
🚀 Server running on port 5000
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### API Endpoints (if auth selected)
|
|
137
|
+
|
|
138
|
+
| Method | Endpoint | Description |
|
|
139
|
+
|--------|----------|-------------|
|
|
140
|
+
| POST | `/api/auth/signup` | Register a new user |
|
|
141
|
+
| POST | `/api/auth/login` | Login and get JWT token |
|
|
142
|
+
| POST | `/api/auth/logout` | Logout (protected route) |
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## 🤝 Contributing
|
|
147
|
+
|
|
148
|
+
Contributions, issues and feature requests are welcome!
|
|
149
|
+
|
|
150
|
+
1. Fork the repo
|
|
151
|
+
2. Create your branch (`git checkout -b feature/awesome-feature`)
|
|
152
|
+
3. Commit changes (`git commit -m 'Add awesome feature'`)
|
|
153
|
+
4. Push (`git push origin feature/awesome-feature`)
|
|
154
|
+
5. Open a Pull Request
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 📄 License
|
|
159
|
+
|
|
160
|
+
MIT © [Prashant](https://github.com/prashantdevelopment)
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
<p align="center">
|
|
165
|
+
Made with ❤️ by <a href="https://github.com/prashantdevelopment">Prashant</a>
|
|
166
|
+
</p>
|
package/index.js
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { execSync } from 'child_process';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
|
|
11
|
+
const projectName = process.argv[2];
|
|
12
|
+
|
|
13
|
+
// ES modules support for __dirname
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
|
|
17
|
+
// Project name validation
|
|
18
|
+
function isValidProjectName(name) {
|
|
19
|
+
const validPattern = /^[a-z0-9_-]+$/;
|
|
20
|
+
return validPattern.test(name) && name.length > 0 && name.length <= 50;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (!projectName) {
|
|
24
|
+
console.log(chalk.red("Please provide a project name!"));
|
|
25
|
+
console.log(chalk.yellow("Usage: npx instant-express <project-name>"));
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!isValidProjectName(projectName)) {
|
|
30
|
+
console.log(chalk.red("\n Invalid project name!"));
|
|
31
|
+
console.log(chalk.yellow("Rules:"));
|
|
32
|
+
console.log(chalk.yellow(" - Only lowercase letters, numbers, hyphens (-), underscores (_)"));
|
|
33
|
+
console.log(chalk.yellow(" - No spaces allowed"));
|
|
34
|
+
console.log(chalk.yellow(" - Example: my-cool-project, backend_v2"));
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Interactive prompts
|
|
39
|
+
const questions = [
|
|
40
|
+
{
|
|
41
|
+
type: 'input',
|
|
42
|
+
name: 'port',
|
|
43
|
+
message: 'Enter port number:',
|
|
44
|
+
default: '5000',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: 'confirm',
|
|
48
|
+
name: 'useAuth',
|
|
49
|
+
message: 'Include JWT Authentication?',
|
|
50
|
+
default: true,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
type: 'confirm',
|
|
54
|
+
name: 'runInstall',
|
|
55
|
+
message: 'Run npm install automatically?',
|
|
56
|
+
default: true,
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
// Replace placeholders with actual values in template content
|
|
61
|
+
function replacePlaceholders(content, replacements) {
|
|
62
|
+
let result = content;
|
|
63
|
+
for (const [placeholder, value] of Object.entries(replacements)) {
|
|
64
|
+
// Handle commented placeholders (// {{KEY}}) as well
|
|
65
|
+
const commentedRegex = new RegExp(`//\\s*{{${placeholder}}}`, 'g');
|
|
66
|
+
if (commentedRegex.test(result)) {
|
|
67
|
+
result = result.replace(commentedRegex, value);
|
|
68
|
+
} else {
|
|
69
|
+
const regex = new RegExp(`{{${placeholder}}}`, 'g');
|
|
70
|
+
result = result.replace(regex, value);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Read template file, replace placeholders, and write to target
|
|
77
|
+
function processTemplate(templatePath, targetPath, replacements) {
|
|
78
|
+
const content = fs.readFileSync(
|
|
79
|
+
path.join(__dirname, 'templates', templatePath),
|
|
80
|
+
'utf-8'
|
|
81
|
+
);
|
|
82
|
+
const finalContent = replacePlaceholders(content, replacements);
|
|
83
|
+
fs.ensureFileSync(targetPath);
|
|
84
|
+
fs.writeFileSync(targetPath, finalContent);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Package.json structure for the generated project
|
|
88
|
+
function createProjectPackageJson(projectName, dependencies) {
|
|
89
|
+
return {
|
|
90
|
+
name: projectName,
|
|
91
|
+
version: "1.0.0",
|
|
92
|
+
description: `${projectName} - Generated by instant-express`,
|
|
93
|
+
main: "server.js",
|
|
94
|
+
type: "module",
|
|
95
|
+
scripts: {
|
|
96
|
+
start: "node server.js",
|
|
97
|
+
dev: "nodemon server.js",
|
|
98
|
+
},
|
|
99
|
+
keywords: [],
|
|
100
|
+
author: "",
|
|
101
|
+
license: "ISC",
|
|
102
|
+
dependencies: dependencies,
|
|
103
|
+
devDependencies: {
|
|
104
|
+
nodemon: "^3.0.0",
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Main function
|
|
110
|
+
async function main() {
|
|
111
|
+
const targetDir = path.join(process.cwd(), projectName);
|
|
112
|
+
|
|
113
|
+
// Check if folder already exists
|
|
114
|
+
if (fs.existsSync(targetDir)) {
|
|
115
|
+
console.log(chalk.red(`\n Error: Folder "${projectName}" already exists!`));
|
|
116
|
+
console.log(chalk.yellow("Solutions:"));
|
|
117
|
+
console.log(chalk.yellow(" 1. Choose a different project name"));
|
|
118
|
+
console.log(chalk.yellow(" 2. Delete the existing folder: rm -rf " + projectName));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.log(chalk.blue.bold("\n🚀 Instant-Express CLI\n"));
|
|
123
|
+
|
|
124
|
+
// Collect user answers
|
|
125
|
+
const answers = await inquirer.prompt(questions);
|
|
126
|
+
|
|
127
|
+
// Placeholders mapping
|
|
128
|
+
const replacements = {
|
|
129
|
+
PROJECT_NAME: projectName,
|
|
130
|
+
PORT: answers.port,
|
|
131
|
+
AUTH_IMPORT: answers.useAuth
|
|
132
|
+
? "import authRoutes from './routes/authRoutes.js';"
|
|
133
|
+
: '// No auth routes (auth was not selected)',
|
|
134
|
+
AUTH_ROUTE: answers.useAuth
|
|
135
|
+
? "app.use('/api/auth', authRoutes);"
|
|
136
|
+
: '// No auth routes configured',
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// Create target folder
|
|
140
|
+
fs.ensureDirSync(targetDir);
|
|
141
|
+
console.log(chalk.green(`\n📁 Folder created: ${projectName}/`));
|
|
142
|
+
|
|
143
|
+
// Generate core files
|
|
144
|
+
const coreFiles = [
|
|
145
|
+
{ template: 'server.js', target: 'server.js' },
|
|
146
|
+
{ template: 'app.js', target: 'app.js' },
|
|
147
|
+
{ template: 'config/db.js', target: 'config/db.js' },
|
|
148
|
+
{ template: '.env.example', target: '.env.example' },
|
|
149
|
+
{ template: '.gitignore', target: '.gitignore' },
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
for (const file of coreFiles) {
|
|
153
|
+
const targetPath = path.join(targetDir, file.target);
|
|
154
|
+
processTemplate(file.template, targetPath, replacements);
|
|
155
|
+
}
|
|
156
|
+
console.log(chalk.green("✅ Core files generated!"));
|
|
157
|
+
|
|
158
|
+
// Create empty folders with .gitkeep
|
|
159
|
+
const emptyFolders = ['services', 'utils'];
|
|
160
|
+
for (const folder of emptyFolders) {
|
|
161
|
+
const folderPath = path.join(targetDir, folder);
|
|
162
|
+
fs.ensureDirSync(folderPath);
|
|
163
|
+
fs.writeFileSync(path.join(folderPath, '.gitkeep'), '');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Define dependencies
|
|
167
|
+
const baseDependencies = {
|
|
168
|
+
"express": "^4.18.2",
|
|
169
|
+
"mongoose": "^8.0.0",
|
|
170
|
+
"dotenv": "^16.3.1",
|
|
171
|
+
"cors": "^2.8.5",
|
|
172
|
+
"cookie-parser": "^1.4.6",
|
|
173
|
+
"morgan": "^1.10.0",
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const authDependencies = {
|
|
177
|
+
"bcryptjs": "^2.4.3",
|
|
178
|
+
"jsonwebtoken": "^9.0.2",
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const allDependencies = answers.useAuth
|
|
182
|
+
? { ...baseDependencies, ...authDependencies }
|
|
183
|
+
: baseDependencies;
|
|
184
|
+
|
|
185
|
+
if (answers.useAuth) {
|
|
186
|
+
const authFiles = [
|
|
187
|
+
{ template: 'models/User.js', target: 'models/User.js' },
|
|
188
|
+
{ template: 'controllers/authController.js', target: 'controllers/authController.js' },
|
|
189
|
+
{ template: 'routes/authRoutes.js', target: 'routes/authRoutes.js' },
|
|
190
|
+
{ template: 'middlewares/authMiddleware.js', target: 'middlewares/authMiddleware.js' },
|
|
191
|
+
];
|
|
192
|
+
|
|
193
|
+
for (const file of authFiles) {
|
|
194
|
+
const targetPath = path.join(targetDir, file.target);
|
|
195
|
+
processTemplate(file.template, targetPath, replacements);
|
|
196
|
+
}
|
|
197
|
+
console.log(chalk.green("✅ Auth files generated (User model, controller, routes, middleware)!"));
|
|
198
|
+
} else {
|
|
199
|
+
console.log(chalk.yellow("ℹ️ Auth skipped."));
|
|
200
|
+
fs.ensureDirSync(path.join(targetDir, 'models'));
|
|
201
|
+
fs.ensureDirSync(path.join(targetDir, 'controllers'));
|
|
202
|
+
fs.ensureDirSync(path.join(targetDir, 'routes'));
|
|
203
|
+
fs.ensureDirSync(path.join(targetDir, 'middlewares'));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Write package.json for generated project
|
|
207
|
+
const projectPkg = createProjectPackageJson(projectName, allDependencies);
|
|
208
|
+
const pkgPath = path.join(targetDir, 'package.json');
|
|
209
|
+
fs.writeJsonSync(pkgPath, projectPkg, { spaces: 2 });
|
|
210
|
+
console.log(chalk.green("✅ package.json created!"));
|
|
211
|
+
|
|
212
|
+
// Generate .env file
|
|
213
|
+
const envContent = `PORT=${answers.port}
|
|
214
|
+
MONGO_URI=mongodb://localhost:27017/${projectName}
|
|
215
|
+
${answers.useAuth ? 'JWT_SECRET=change_this_to_a_random_secret_string\nJWT_EXPIRE=7d' : ''}
|
|
216
|
+
`;
|
|
217
|
+
fs.writeFileSync(path.join(targetDir, '.env'), envContent.trim());
|
|
218
|
+
console.log(chalk.green("✅ .env file created!"));
|
|
219
|
+
|
|
220
|
+
// Auto run npm install
|
|
221
|
+
if (answers.runInstall) {
|
|
222
|
+
console.log(chalk.blue("\n📦 Installing dependencies..."));
|
|
223
|
+
const spinner = ora('Running npm install...').start();
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
execSync('npm install', {
|
|
227
|
+
cwd: targetDir,
|
|
228
|
+
stdio: 'pipe',
|
|
229
|
+
});
|
|
230
|
+
spinner.succeed(chalk.green('Dependencies installed successfully! ✅'));
|
|
231
|
+
} catch (error) {
|
|
232
|
+
spinner.fail(chalk.red('npm install failed! ❌'));
|
|
233
|
+
console.log(chalk.yellow("Manual fix: cd " + projectName + " && npm install"));
|
|
234
|
+
}
|
|
235
|
+
} else {
|
|
236
|
+
console.log(chalk.yellow("\nℹ️ npm install skipped."));
|
|
237
|
+
console.log(chalk.yellow(` Run manually: cd ${projectName} && npm install`));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Success message
|
|
241
|
+
console.log(chalk.green.bold(`\n🎉 ${projectName} successfully generated!\n`));
|
|
242
|
+
console.log(chalk.white("Next steps:"));
|
|
243
|
+
console.log(chalk.cyan(` cd ${projectName}`));
|
|
244
|
+
if (!answers.runInstall) {
|
|
245
|
+
console.log(chalk.cyan(" npm install"));
|
|
246
|
+
}
|
|
247
|
+
console.log(chalk.cyan(" npm run dev"));
|
|
248
|
+
console.log(chalk.white("\nHappy coding! 🚀\n"));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
main().catch((err) => {
|
|
252
|
+
console.log(chalk.red(`\n❌ Unexpected error: ${err.message}`));
|
|
253
|
+
console.log(chalk.yellow("\nIf this error persists:"));
|
|
254
|
+
console.log(chalk.yellow(" 1. Check if you have write permissions"));
|
|
255
|
+
console.log(chalk.yellow(" 2. Restart your terminal"));
|
|
256
|
+
console.log(chalk.yellow(" 3. Open an issue on GitHub with this error message"));
|
|
257
|
+
process.exit(1);
|
|
258
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "instant-express",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool to instantly generate a production-ready Express.js + MongoDB backend with optional JWT authentication, folder structure, and auto dependency installation",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"instant-express": "index.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"files": [
|
|
11
|
+
"index.js",
|
|
12
|
+
"templates/",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"cli",
|
|
17
|
+
"express",
|
|
18
|
+
"mongodb",
|
|
19
|
+
"mongoose",
|
|
20
|
+
"boilerplate",
|
|
21
|
+
"generator",
|
|
22
|
+
"backend",
|
|
23
|
+
"nodejs",
|
|
24
|
+
"scaffold",
|
|
25
|
+
"starter",
|
|
26
|
+
"jwt",
|
|
27
|
+
"authentication",
|
|
28
|
+
"rest-api",
|
|
29
|
+
"api",
|
|
30
|
+
"express-generator",
|
|
31
|
+
"create-backend",
|
|
32
|
+
"project-generator"
|
|
33
|
+
],
|
|
34
|
+
"author": "Prashant <imprashant16006@gmail.com> (https://github.com/prashantdevelopment)",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/prashantdevelopment/instant-express.git"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://github.com/prashantdevelopment/instant-express#readme",
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"chalk": "^5.6.2",
|
|
43
|
+
"fs-extra": "^11.3.5",
|
|
44
|
+
"inquirer": "^14.0.2",
|
|
45
|
+
"ora": "^9.4.0"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/templates/app.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import cors from 'cors';
|
|
3
|
+
import cookieParser from 'cookie-parser';
|
|
4
|
+
import morgan from 'morgan';
|
|
5
|
+
|
|
6
|
+
// {{AUTH_IMPORT}}
|
|
7
|
+
|
|
8
|
+
const app = express();
|
|
9
|
+
|
|
10
|
+
// Built-in middlewares
|
|
11
|
+
app.use(express.json()); // JSON body parse karne ke liye
|
|
12
|
+
app.use(express.urlencoded({ extended: true })); // Form data ke liye
|
|
13
|
+
app.use(cors()); // Cross-origin requests allow karne ke liye
|
|
14
|
+
app.use(cookieParser()); // Cookies read karne ke liye
|
|
15
|
+
app.use(morgan('dev')); // HTTP request logging ke liye
|
|
16
|
+
|
|
17
|
+
// Routes
|
|
18
|
+
// {{AUTH_ROUTE}}
|
|
19
|
+
|
|
20
|
+
// Health check route
|
|
21
|
+
app.get('/', (req, res) => {
|
|
22
|
+
res.json({ message: '{{PROJECT_NAME}} API is running 🚀' });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export default app;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
import dns from 'dns';
|
|
3
|
+
|
|
4
|
+
// DNS resolver set karo taaki MongoDB Atlas ke DNS issues na aayein
|
|
5
|
+
dns.setServers(['1.1.1.1', '8.8.8.8']);
|
|
6
|
+
|
|
7
|
+
const connectDB = async () => {
|
|
8
|
+
try {
|
|
9
|
+
const conn = await mongoose.connect(process.env.MONGO_URI);
|
|
10
|
+
console.log(`✅ MongoDB Connected: ${conn.connection.host}`);
|
|
11
|
+
} catch (error) {
|
|
12
|
+
console.error(`❌ MongoDB Connection Error: ${error.message}`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default connectDB;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import User from '../models/User.js';
|
|
2
|
+
import jwt from 'jsonwebtoken';
|
|
3
|
+
|
|
4
|
+
// JWT token generate karne ka helper
|
|
5
|
+
const generateToken = (userId) => {
|
|
6
|
+
return jwt.sign({ id: userId }, process.env.JWT_SECRET, {
|
|
7
|
+
expiresIn: process.env.JWT_EXPIRE || '7d',
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// Signup
|
|
12
|
+
export const signup = async (req, res) => {
|
|
13
|
+
try {
|
|
14
|
+
const { name, email, password } = req.body;
|
|
15
|
+
|
|
16
|
+
// Check agar user already exist karta hai
|
|
17
|
+
const existingUser = await User.findOne({ email });
|
|
18
|
+
if (existingUser) {
|
|
19
|
+
return res.status(400).json({ message: 'User already exists' });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const user = await User.create({ name, email, password });
|
|
23
|
+
const token = generateToken(user._id);
|
|
24
|
+
|
|
25
|
+
res.status(201).json({
|
|
26
|
+
success: true,
|
|
27
|
+
token,
|
|
28
|
+
user: { id: user._id, name: user.name, email: user.email },
|
|
29
|
+
});
|
|
30
|
+
} catch (error) {
|
|
31
|
+
res.status(500).json({ message: error.message });
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Login
|
|
36
|
+
export const login = async (req, res) => {
|
|
37
|
+
try {
|
|
38
|
+
const { email, password } = req.body;
|
|
39
|
+
|
|
40
|
+
// User dhoondho aur password bhi laao (+password kyunki select: false hai)
|
|
41
|
+
const user = await User.findOne({ email }).select('+password');
|
|
42
|
+
if (!user || !(await user.comparePassword(password))) {
|
|
43
|
+
return res.status(401).json({ message: 'Invalid email or password' });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const token = generateToken(user._id);
|
|
47
|
+
|
|
48
|
+
res.status(200).json({
|
|
49
|
+
success: true,
|
|
50
|
+
token,
|
|
51
|
+
user: { id: user._id, name: user.name, email: user.email },
|
|
52
|
+
});
|
|
53
|
+
} catch (error) {
|
|
54
|
+
res.status(500).json({ message: error.message });
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Logout
|
|
59
|
+
export const logout = async (req, res) => {
|
|
60
|
+
res.status(200).json({ success: true, message: 'Logged out successfully' });
|
|
61
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import jwt from 'jsonwebtoken';
|
|
2
|
+
import User from '../models/User.js';
|
|
3
|
+
|
|
4
|
+
export const protect = async (req, res, next) => {
|
|
5
|
+
const token = req.cookies.token;
|
|
6
|
+
|
|
7
|
+
if (!token) {
|
|
8
|
+
return res.status(401).json({ message: 'Unauthorized: No token provided' });
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (!process.env.JWT_SECRET) {
|
|
12
|
+
console.error('CRITICAL ERROR: JWT_SECRET is not defined in environment variables');
|
|
13
|
+
return res.status(500).json({ message: 'Internal server error' });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const user = await User.findById(decoded.id);
|
|
21
|
+
if (!user) {
|
|
22
|
+
return res.status(401).json({ message: 'Unauthorized: User not found' });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
req.user = user; // User mil gaya! Usse request object mein save kar do
|
|
26
|
+
next();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error('JWT Verification Error:', error.message);
|
|
29
|
+
res.status(401).json({ message: 'Unauthorized: Invalid token' });
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
|
+
import bcrypt from 'bcryptjs';
|
|
3
|
+
|
|
4
|
+
const userSchema = new mongoose.Schema({
|
|
5
|
+
name: {
|
|
6
|
+
type: String,
|
|
7
|
+
required: [true, 'Name is required'],
|
|
8
|
+
},
|
|
9
|
+
email: {
|
|
10
|
+
type: String,
|
|
11
|
+
required: [true, 'Email is required'],
|
|
12
|
+
unique: true,
|
|
13
|
+
lowercase: true,
|
|
14
|
+
},
|
|
15
|
+
password: {
|
|
16
|
+
type: String,
|
|
17
|
+
required: [true, 'Password is required'],
|
|
18
|
+
minlength: 6,
|
|
19
|
+
select: false, // Password default mein query result mein nahi aayega
|
|
20
|
+
},
|
|
21
|
+
}, { timestamps: true });
|
|
22
|
+
|
|
23
|
+
// Password hash karo save se pehle
|
|
24
|
+
userSchema.pre('save', async function(next) {
|
|
25
|
+
if (!this.isModified('password')) return next();
|
|
26
|
+
this.password = await bcrypt.hash(this.password, 12);
|
|
27
|
+
next();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Password compare method
|
|
31
|
+
userSchema.methods.comparePassword = async function(candidatePassword) {
|
|
32
|
+
return await bcrypt.compare(candidatePassword, this.password);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const User = mongoose.model('User', userSchema);
|
|
36
|
+
export default User;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { signup, login, logout } from '../controllers/authController.js';
|
|
3
|
+
import { protect } from '../middlewares/authMiddleware.js';
|
|
4
|
+
|
|
5
|
+
const router = express.Router();
|
|
6
|
+
|
|
7
|
+
router.post('/signup', signup);
|
|
8
|
+
router.post('/login', login);
|
|
9
|
+
router.post('/logout', protect, logout); // Sirf logged-in user logout kar sake
|
|
10
|
+
|
|
11
|
+
export default router;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import 'dotenv/config';
|
|
2
|
+
import app from './app.js';
|
|
3
|
+
import connectDB from './config/db.js';
|
|
4
|
+
|
|
5
|
+
const PORT = process.env.PORT || '{{PORT}}';
|
|
6
|
+
|
|
7
|
+
// Pehle database connect karo, phir server start karo
|
|
8
|
+
connectDB().then(() => {
|
|
9
|
+
app.listen(PORT, () => {
|
|
10
|
+
console.log(`🚀 Server running on port ${PORT}`);
|
|
11
|
+
});
|
|
12
|
+
});
|