Skip to content

Commit 283686a

Browse files
add CLI tool to scaffold a Node.js + Express backend with optional features
1 parent 7aa5d72 commit 283686a

File tree

2 files changed

+239
-0
lines changed

2 files changed

+239
-0
lines changed

bin/index.js

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#!/usr/bin/env node
2+
import { createInterface } from "readline";
3+
import { execSync } from "child_process";
4+
import fs from "fs";
5+
import path from "path";
6+
import { fileURLToPath } from "url";
7+
8+
const __filename = fileURLToPath(import.meta.url);
9+
const __dirname = path.dirname(__filename);
10+
11+
const rl = createInterface({
12+
input: process.stdin,
13+
output: process.stdout,
14+
});
15+
16+
const ask = (q) => new Promise((res) => rl.question(q, res));
17+
18+
async function main() {
19+
console.log("🚀 Welcome to create-node-backend!");
20+
21+
const projectName = await ask("Project name: ");
22+
const useAuth = await ask("Include auth? (y/n): ");
23+
const useMulter = await ask("Include Multer (file uploads)? (y/n): ");
24+
25+
rl.close();
26+
27+
const projectPath = path.join(process.cwd(), projectName);
28+
if (fs.existsSync(projectPath)) {
29+
console.error(`❌ Project folder already exists. Choose a different name.`);
30+
process.exit(1);
31+
}
32+
fs.mkdirSync(projectPath);
33+
34+
process.chdir(projectPath);
35+
36+
// Step 1: Initialize npm and Install Dependencies
37+
console.log("📦 Initializing npm...");
38+
execSync("npm init -y", { stdio: "inherit" });
39+
40+
// Step 2: Install Dependencies
41+
console.log("📥 Installing required packages...");
42+
execSync("npm install express dotenv", { stdio: "inherit" });
43+
44+
if (useAuth.toLowerCase() === "y") {
45+
console.log("🔐 Adding auth dependencies...");
46+
execSync("npm install argon2 jsonwebtoken", { stdio: "inherit" });
47+
}
48+
49+
if (useMulter.toLowerCase() === "y") {
50+
console.log("📂 Adding Multer...");
51+
execSync("npm install multer", { stdio: "inherit" });
52+
}
53+
54+
console.log("⚙️ Installing dev dependencies...");
55+
execSync("npm install --save-dev nodemon", { stdio: "inherit" });
56+
57+
// Step 3: Modify package.json for ES Modules
58+
const packageJsonPath = path.join(projectPath, "package.json");
59+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
60+
packageJson.type = "module"; // Set the project to use ES Modules
61+
62+
packageJson.scripts = {
63+
...packageJson.scripts,
64+
dev: "nodemon src/index.js", // Add this line for dev script
65+
};
66+
67+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
68+
69+
// Step 4: Setup Folder Structure
70+
console.log("📁 Creating project structure...");
71+
72+
// Create necessary directories
73+
fs.mkdirSync(path.join(projectPath, "src"));
74+
fs.mkdirSync(path.join(projectPath, "src", "controllers"));
75+
fs.mkdirSync(path.join(projectPath, "src", "models"));
76+
fs.mkdirSync(path.join(projectPath, "src", "routes"));
77+
fs.mkdirSync(path.join(projectPath, "src", "middlewares"));
78+
fs.mkdirSync(path.join(projectPath, "src", "config"));
79+
80+
// Step 5: Write environment configuration
81+
const envContent = `
82+
PORT=3000
83+
JWT_SECRET=your_jwt_secret
84+
`;
85+
86+
fs.writeFileSync(path.join(projectPath, ".env"), envContent.trim());
87+
88+
// Step 6: Write basic project files
89+
90+
// src/index.js (updated to reflect src folder)
91+
const indexContent = `
92+
import express from 'express';
93+
import dotenv from 'dotenv';
94+
import routes from './routes/userRoutes.js';
95+
96+
dotenv.config();
97+
98+
const app = express();
99+
app.use(express.json());
100+
101+
// Basic route for health check
102+
app.get('/', (req, res) => res.send('Hello from ${projectName} backend!'));
103+
104+
// Use Routes
105+
app.use('/api', routes);
106+
107+
const port = process.env.PORT || 3000;
108+
app.listen(port, () => console.log('🚀 Server running on ' + 'http://localhost:' + port));
109+
`;
110+
111+
fs.writeFileSync(
112+
path.join(projectPath, "src", "index.js"),
113+
indexContent.trim()
114+
);
115+
116+
// Create controllers, routes, and models for an example user API
117+
118+
const userController = `
119+
export const getUsers = (req, res) => {
120+
res.json({ message: "List of users" });
121+
};
122+
`;
123+
124+
fs.writeFileSync(
125+
path.join(projectPath, "src", "controllers", "userController.js"),
126+
userController.trim()
127+
);
128+
129+
const userRoutes = `
130+
import express from 'express';
131+
import { getUsers } from '../controllers/userController.js';
132+
133+
const router = express.Router();
134+
135+
router.get('/users', getUsers);
136+
137+
export default router;
138+
`;
139+
140+
fs.writeFileSync(
141+
path.join(projectPath, "src", "routes", "userRoutes.js"),
142+
userRoutes.trim()
143+
);
144+
145+
// Step 7: Optionally Add Auth (JWT)
146+
if (useAuth.toLowerCase() === "yes") {
147+
const authMiddleware = `
148+
import jwt from 'jsonwebtoken';
149+
150+
export const authenticate = (req, res, next) => {
151+
const token = req.header('x-auth-token');
152+
if (!token) {
153+
return res.status(401).json({ msg: 'No token, authorization denied' });
154+
}
155+
try {
156+
const decoded = jwt.verify(token, process.env.JWT_SECRET);
157+
req.user = decoded.user;
158+
next();
159+
} catch (err) {
160+
res.status(401).json({ msg: 'Token is not valid' });
161+
}
162+
};
163+
`;
164+
165+
fs.writeFileSync(
166+
path.join(projectPath, "src", "middlewares", "authMiddleware.js"),
167+
authMiddleware.trim()
168+
);
169+
}
170+
171+
console.log(`👉 Project "${projectName}" created!`);
172+
console.log(`👉 Run: cd ${projectName} && npm run dev`);
173+
}
174+
175+
main();

readme.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# create-node-spark
2+
3+
A CLI tool to scaffold a basic Node.js + Express backend. This open-source tool simplifies the setup of a Node.js project with optional features such as authentication and file uploads using Multer.
4+
5+
## Usage
6+
7+
```bash
8+
npx create-node-spark
9+
```
10+
11+
## Features
12+
13+
- **Optional Authentication**: Seamlessly integrates argon2 and JWT for user authentication.
14+
- **Multer Integration**: Easily add file upload capabilities.
15+
- **Quick Setup**: Scaffolds a ready-to-use Node.js project in seconds.
16+
17+
## Installation
18+
19+
To install and use the CLI tool locally, follow these steps:
20+
21+
1. Clone the repository:
22+
```bash
23+
git clone https://github.com/talhabilal-dev/create-node-spark.git
24+
cd create-node-spark
25+
```
26+
27+
2. Link the package globally:
28+
```bash
29+
npm link
30+
```
31+
32+
3. Run the CLI tool:
33+
```bash
34+
create-node-spark
35+
```
36+
37+
## Getting Started
38+
39+
1. **Run the CLI**: Execute the command `create-node-spark` and follow the prompts. You can choose to include authentication and file upload functionalities.
40+
41+
2. **Navigate to Your Project**: After generation, move into your new project directory:
42+
```bash
43+
cd your-project-name
44+
```
45+
46+
3. **Start the Development Server**: Use Node.js to run the server:
47+
```bash
48+
npm run dev
49+
```
50+
51+
## Contributing
52+
53+
Contributions are welcome! If you have suggestions for improvements or new features, feel free to submit a pull request or open an issue.
54+
55+
## License
56+
57+
This project is licensed under the MIT License.
58+
59+
---
60+
61+
### Future Enhancements
62+
63+
We are considering adding a **template system** to automatically generate folders such as `/routes`, `/controllers`, and `/middlewares`. If you have any ideas or requests, let us know! 🌟
64+

0 commit comments

Comments
 (0)