@amalkrishnakp/mern_launcher 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 +249 -0
- package/bin/cli.js +21 -0
- package/package.json +30 -0
- package/src/generator/setupAxios.generator.js +25 -0
- package/src/generator/setupDotEnv.generator.js +14 -0
- package/src/generator/setupExpress.generator.js +51 -0
- package/src/generator/setupMongo.generator.js +28 -0
- package/src/generator/setupShadCN.generator.js +70 -0
- package/src/generator/setupTailwind.generator.js +45 -0
- package/src/generator/setupVite.generator.js +51 -0
- package/src/generator/structure.generator.js +101 -0
- package/src/prompts/question.prompt.js +54 -0
- package/src/setups/backend.setup.js +15 -0
- package/src/setups/frontend.setups.js +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# MERN Launcher 🚀
|
|
2
|
+
|
|
3
|
+
A powerful CLI tool that automates MERN stack project setup, specifically designed for development environments. Get from zero to production-ready development setup in minutes!
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
### 🎯 Complete MERN Stack Setup
|
|
8
|
+
- **MongoDB** with Mongoose ODM and environment configuration
|
|
9
|
+
- **Express.js** server with CORS and development settings
|
|
10
|
+
- **React** with Vite for lightning-fast development
|
|
11
|
+
- **Node.js** backend with modern ES modules
|
|
12
|
+
|
|
13
|
+
### 🔥 Development Optimized
|
|
14
|
+
- **Hot Reload Development** - Vite for frontend, Nodemon for backend
|
|
15
|
+
- **Development CORS** - Pre-configured for `http://localhost:5173`
|
|
16
|
+
- **Development Scripts** - Ready-to-run `npm run dev` commands
|
|
17
|
+
- **Local Environment** - Perfect for local development and testing
|
|
18
|
+
|
|
19
|
+
### 🛠️ Built-in Tools & Libraries
|
|
20
|
+
- **Tailwind CSS** - Utility-first CSS framework
|
|
21
|
+
- **shadcn/ui** - Beautiful, accessible UI components
|
|
22
|
+
- **Axios** - HTTP client with development baseURL
|
|
23
|
+
- **Dotenv** - Environment variable management
|
|
24
|
+
- **CORS** - Cross-origin resource sharing
|
|
25
|
+
|
|
26
|
+
### ⚡ Smart CLI Features
|
|
27
|
+
- **Flexible Setup** - Use current folder or create new project
|
|
28
|
+
- **Interactive Prompts** - User-friendly configuration
|
|
29
|
+
- **Robust Process Management** - Uses Execa for reliable command execution
|
|
30
|
+
- **Cross-Platform** - Works on Windows, Mac, and Linux
|
|
31
|
+
|
|
32
|
+
## 🚀 Quick Start
|
|
33
|
+
|
|
34
|
+
### Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx mern-launcher
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Usage
|
|
41
|
+
|
|
42
|
+
1. **Run the CLI tool:**
|
|
43
|
+
```bash
|
|
44
|
+
npx mern-launcher
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
2. **Answer the interactive prompts:**
|
|
48
|
+
- Choose to use current folder or create new one
|
|
49
|
+
- Enter your project name (if creating new folder)
|
|
50
|
+
- Provide your MongoDB connection string
|
|
51
|
+
|
|
52
|
+
3. **Start development:**
|
|
53
|
+
```bash
|
|
54
|
+
# Terminal 1 - Backend
|
|
55
|
+
cd backend
|
|
56
|
+
npm run dev
|
|
57
|
+
|
|
58
|
+
# Terminal 2 - Frontend
|
|
59
|
+
cd frontend
|
|
60
|
+
npm run dev
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
4. **Open your browser:**
|
|
64
|
+
- Frontend: `http://localhost:5173`
|
|
65
|
+
- Backend: `http://localhost:5000`
|
|
66
|
+
|
|
67
|
+
## 📁 Project Structure
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
your-project/
|
|
71
|
+
├── backend/
|
|
72
|
+
│ ├── src/
|
|
73
|
+
│ │ ├── lib/
|
|
74
|
+
│ │ │ └── db.js
|
|
75
|
+
│ │ └── server.js
|
|
76
|
+
│ ├── .env
|
|
77
|
+
│ └── package.json
|
|
78
|
+
└── frontend/
|
|
79
|
+
├── src/
|
|
80
|
+
│ ├── lib/
|
|
81
|
+
│ │ └── axios.js
|
|
82
|
+
│ ├── components/
|
|
83
|
+
│ │ └── ui/
|
|
84
|
+
│ ├── App.jsx
|
|
85
|
+
│ └── index.css
|
|
86
|
+
├── jsconfig.json
|
|
87
|
+
└── vite.config.js
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 🛠️ What Gets Installed
|
|
91
|
+
|
|
92
|
+
### Backend Dependencies
|
|
93
|
+
- `express` - Web framework
|
|
94
|
+
- `mongoose` - MongoDB ODM
|
|
95
|
+
- `cors` - Cross-origin resource sharing
|
|
96
|
+
- `dotenv` - Environment variables
|
|
97
|
+
- `nodemon` - Development hot reload
|
|
98
|
+
|
|
99
|
+
### Frontend Dependencies
|
|
100
|
+
- `react` - UI library
|
|
101
|
+
- `vite` - Build tool and dev server
|
|
102
|
+
- `tailwindcss` - CSS framework
|
|
103
|
+
- `@tailwindcss/vite` - Tailwind Vite integration
|
|
104
|
+
- `shadcn/ui` - UI components
|
|
105
|
+
- `axios` - HTTP client
|
|
106
|
+
- `@types/node` - Type definitions
|
|
107
|
+
|
|
108
|
+
## 🔧 Configuration
|
|
109
|
+
|
|
110
|
+
### Environment Variables (Backend/.env)
|
|
111
|
+
```env
|
|
112
|
+
NODE_ENV=development
|
|
113
|
+
MONGO_URL=your_mongodb_connection_string
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### API Client (Frontend)
|
|
117
|
+
```javascript
|
|
118
|
+
// Pre-configured Axios instance
|
|
119
|
+
import { axiosInstance } from '@/lib/axios'
|
|
120
|
+
|
|
121
|
+
// Usage in components
|
|
122
|
+
axiosInstance.get('/api/users')
|
|
123
|
+
axiosInstance.post('/api/users', data)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Development URLs
|
|
127
|
+
- **Frontend**: `http://localhost:5173`
|
|
128
|
+
- **Backend**: `http://localhost:5000`
|
|
129
|
+
- **API Base**: `http://localhost:5000` (in development)
|
|
130
|
+
|
|
131
|
+
## 🎯 Use Cases
|
|
132
|
+
|
|
133
|
+
### Perfect For:
|
|
134
|
+
- 🏗️ **Rapid Prototyping** - Quickly test ideas and concepts
|
|
135
|
+
- 🎓 **Learning & Education** - Perfect for students and tutorials
|
|
136
|
+
- 🔬 **Proof of Concepts** - Validate ideas without setup overhead
|
|
137
|
+
- 🚀 **Hackathons** - Get started coding immediately
|
|
138
|
+
- 💼 **Side Projects** - Focus on building, not configuring
|
|
139
|
+
|
|
140
|
+
### Development Workflow
|
|
141
|
+
1. **Idea** → Have a project idea
|
|
142
|
+
2. **Setup** → Run `npx mern-launcher`
|
|
143
|
+
3. **Develop** → Start coding immediately
|
|
144
|
+
4. **Test** → Both servers running with hot reload
|
|
145
|
+
5. **Deploy** → Ready for production deployment
|
|
146
|
+
|
|
147
|
+
## 🔄 Development Commands
|
|
148
|
+
|
|
149
|
+
### Backend
|
|
150
|
+
```bash
|
|
151
|
+
cd backend
|
|
152
|
+
npm run dev # Start development server with nodemon
|
|
153
|
+
npm start # Start production server
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Frontend
|
|
157
|
+
```bash
|
|
158
|
+
cd frontend
|
|
159
|
+
npm run dev # Start Vite development server
|
|
160
|
+
npm run build # Build for production
|
|
161
|
+
npm run preview # Preview production build
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## 🎨 UI Components
|
|
165
|
+
|
|
166
|
+
The setup includes **shadcn/ui** with pre-configured:
|
|
167
|
+
- Button components
|
|
168
|
+
- Tailwind CSS integration
|
|
169
|
+
- Path aliases (`@/*` for `./src/*`)
|
|
170
|
+
- Responsive design utilities
|
|
171
|
+
|
|
172
|
+
Example component usage:
|
|
173
|
+
```jsx
|
|
174
|
+
import { Button } from "@/components/ui/button"
|
|
175
|
+
|
|
176
|
+
function App() {
|
|
177
|
+
return (
|
|
178
|
+
<div className="flex min-h-svh flex-col items-center justify-center">
|
|
179
|
+
<Button>Click me</Button>
|
|
180
|
+
</div>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 🌟 Why Use MERN Launcher?
|
|
186
|
+
|
|
187
|
+
### Time Savings
|
|
188
|
+
- ⏱️ **Save 1-2 hours** per project on initial setup
|
|
189
|
+
- 🔧 **No configuration headaches** - everything just works
|
|
190
|
+
- 📚 **Best practices** built-in from start
|
|
191
|
+
|
|
192
|
+
### Developer Experience
|
|
193
|
+
- 🚀 **Instant hot reload** for both frontend and backend
|
|
194
|
+
- 🎯 **Consistent structure** across all projects
|
|
195
|
+
- 🔥 **Modern tooling** with latest versions
|
|
196
|
+
- 📱 **Mobile-responsive** from day one
|
|
197
|
+
|
|
198
|
+
### Production Ready
|
|
199
|
+
- ⚡ **Optimized build** configuration
|
|
200
|
+
- 🔒 **Security practices** implemented
|
|
201
|
+
- 📦 **Clean, maintainable** code structure
|
|
202
|
+
|
|
203
|
+
## 🐛 Troubleshooting
|
|
204
|
+
|
|
205
|
+
### Common Issues
|
|
206
|
+
|
|
207
|
+
1. **Port already in use**
|
|
208
|
+
- Check if ports 5173 or 5000 are occupied
|
|
209
|
+
- Kill existing processes or change ports in configuration
|
|
210
|
+
|
|
211
|
+
2. **MongoDB connection issues**
|
|
212
|
+
- Verify your connection string
|
|
213
|
+
- Ensure MongoDB is running and accessible
|
|
214
|
+
|
|
215
|
+
3. **Permission errors**
|
|
216
|
+
- Run with appropriate permissions
|
|
217
|
+
- Check file/folder permissions in project directory
|
|
218
|
+
|
|
219
|
+
### Getting Help
|
|
220
|
+
|
|
221
|
+
- Check the [GitHub Issues](https://github.com/AmalKrishnaKP/MERN_LAUNCHER/issues) page
|
|
222
|
+
- Verify all prerequisites are installed
|
|
223
|
+
- Ensure stable internet connection for package downloads
|
|
224
|
+
|
|
225
|
+
## 🤝 Contributing
|
|
226
|
+
|
|
227
|
+
We welcome contributions! Please feel free to submit pull requests, report bugs, or suggest new features.
|
|
228
|
+
|
|
229
|
+
1. Fork the repository
|
|
230
|
+
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
|
|
231
|
+
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
|
232
|
+
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
|
233
|
+
5. Open a Pull Request
|
|
234
|
+
|
|
235
|
+
## 📝 License
|
|
236
|
+
|
|
237
|
+
This project is licensed under the ISC License - see the [LICENSE](LICENSE) file for details.
|
|
238
|
+
|
|
239
|
+
## 🙏 Acknowledgments
|
|
240
|
+
|
|
241
|
+
- Built with amazing open-source tools
|
|
242
|
+
- Inspired by the need for faster project setup
|
|
243
|
+
- Thanks to all contributors and users
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
**Happy Coding!** 🚀
|
|
248
|
+
|
|
249
|
+
If you find this tool helpful, please give it a ⭐ on GitHub!
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createProjectStructure } from "../src/generator/structure.generator.js";
|
|
3
|
+
import { askQuestions } from "../src/prompts/question.prompt.js";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
console.log(process.cwd());
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const run=async()=>{
|
|
11
|
+
try {
|
|
12
|
+
const answer= await askQuestions(); //asking iniital questions
|
|
13
|
+
|
|
14
|
+
await createProjectStructure(answer)
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.log(error);
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
}
|
|
21
|
+
run();
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@amalkrishnakp/mern_launcher",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/AmalKrishnaKP/MERN_LAUNCHER.git"
|
|
11
|
+
},
|
|
12
|
+
"type": "module",
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"author": "",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/AmalKrishnaKP/MERN_LAUNCHER/issues"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"mern-launcher": "bin/cli.js"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/AmalKrishnaKP/MERN_LAUNCHER#readme",
|
|
23
|
+
"description": "",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"chalk": "^5.6.2",
|
|
26
|
+
"execa": "^9.6.0",
|
|
27
|
+
"fs": "^0.0.1-security",
|
|
28
|
+
"inquirer": "^13.0.1"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
export const setupAxios=async(frontPath)=>{
|
|
6
|
+
try {
|
|
7
|
+
await execa("npm",["install","axios"],{
|
|
8
|
+
cwd:frontPath,
|
|
9
|
+
stdio:"inherit"
|
|
10
|
+
})
|
|
11
|
+
fs.writeFileSync(path.join(frontPath,"src/lib/axios.js"),`
|
|
12
|
+
import axios from 'axios'
|
|
13
|
+
|
|
14
|
+
export const axiosInstance=axios.create({
|
|
15
|
+
baseURL: import.meta.env.MODE==="development"? "http://localhost:5000":"",
|
|
16
|
+
withCredentials:true,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
`)
|
|
20
|
+
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.log(error);
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
export const setupDotEnv=async(backPath,answer)=>{
|
|
5
|
+
try {
|
|
6
|
+
fs.writeFileSync(path.join(backPath,".env"),`
|
|
7
|
+
NODE_ENV=development
|
|
8
|
+
MONGO_URL=${answer.mongoURL}
|
|
9
|
+
`)
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.log(error);
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { match } from "assert";
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { inherits } from "util";
|
|
6
|
+
|
|
7
|
+
export const setupExpress=async(backPath)=>{
|
|
8
|
+
try {
|
|
9
|
+
await execa("npm",["install","express","cors"],{
|
|
10
|
+
cwd:backPath,
|
|
11
|
+
stdio:"inherit"
|
|
12
|
+
})
|
|
13
|
+
fs.writeFileSync(path.join(backPath,"src/server.js"),`import express from 'express'
|
|
14
|
+
import dotenv from "dotenv"
|
|
15
|
+
import cors from 'cors'
|
|
16
|
+
|
|
17
|
+
import { connectDB } from './lib/db.js';
|
|
18
|
+
|
|
19
|
+
dotenv.config()
|
|
20
|
+
|
|
21
|
+
const app=express()
|
|
22
|
+
|
|
23
|
+
app.use(cors({
|
|
24
|
+
origin: process.env.NODE_ENV==="development" ? "http://localhost:5173" || true:true,
|
|
25
|
+
credentials:true,
|
|
26
|
+
}))
|
|
27
|
+
const PORT = process.env.PORT || 5000
|
|
28
|
+
app.listen(PORT,()=>{
|
|
29
|
+
console.log("server listening on:" ,PORT);
|
|
30
|
+
connectDB()
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
`)
|
|
34
|
+
await execa("npm",["install","node","nodemon"],{
|
|
35
|
+
cwd:backPath,
|
|
36
|
+
stdio:"inherit"
|
|
37
|
+
})
|
|
38
|
+
const jsonCont=fs.readFileSync(path.join(backPath,"package.json"),'utf8')
|
|
39
|
+
const updatedJsonCon=jsonCont.replace(/"test": "echo \\"Error: no test specified\\" && exit 1"/,match=>`
|
|
40
|
+
${match},
|
|
41
|
+
"dev": "nodemon src/server.js"`)
|
|
42
|
+
const moduleUpdate=updatedJsonCon.replace(/{\s*/,`
|
|
43
|
+
{
|
|
44
|
+
"type": "module",`)
|
|
45
|
+
|
|
46
|
+
fs.writeFileSync(path.join(backPath,"package.json"),moduleUpdate)
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.log(error);
|
|
49
|
+
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
export const setupMongo=async(backPath,answer)=>{
|
|
6
|
+
try {
|
|
7
|
+
await execa("npm",["install","mongoose","dotenv"])
|
|
8
|
+
fs.mkdirSync(path.join(backPath,"src/lib"))
|
|
9
|
+
|
|
10
|
+
fs.writeFileSync(path.join(backPath,"src/lib/db.js"),`
|
|
11
|
+
import mongoose from 'mongoose'
|
|
12
|
+
|
|
13
|
+
export const connectDB=async()=>{
|
|
14
|
+
try {
|
|
15
|
+
const conn=await mongoose.connect(process.env.MONGO_URL)
|
|
16
|
+
console.log("connectd in "+ conn.connection.host);
|
|
17
|
+
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.log(error);
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
`)
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.log(error);
|
|
26
|
+
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { match } from 'assert';
|
|
2
|
+
import { execa } from 'execa';
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { exitCode } from 'process';
|
|
6
|
+
|
|
7
|
+
export const setupShadCN=async(frontPath)=>{
|
|
8
|
+
try {
|
|
9
|
+
const jsConfigPath=path.join(frontPath,"jsconfig.json")
|
|
10
|
+
const jsConfigContent=`{
|
|
11
|
+
"files": [],
|
|
12
|
+
"references": [
|
|
13
|
+
],
|
|
14
|
+
"compilerOptions": {
|
|
15
|
+
"baseUrl": ".",
|
|
16
|
+
"paths": {
|
|
17
|
+
"@/*": ["./src/*"]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}`
|
|
21
|
+
fs.writeFileSync(jsConfigPath,jsConfigContent)
|
|
22
|
+
await execa("npm",["install", "-D", "@types/node"],{
|
|
23
|
+
cwd:frontPath,
|
|
24
|
+
stdio:"inherit"
|
|
25
|
+
})
|
|
26
|
+
const viteConfigPath=path.join(frontPath,"vite.config.js")
|
|
27
|
+
const viteConfigContent=fs.readFileSync(viteConfigPath,'utf8')
|
|
28
|
+
const updatedCon=`import path from "path"\n`+viteConfigContent
|
|
29
|
+
const finalCont=updatedCon.replace(/plugins:\s*\[[^\]]*\]/,
|
|
30
|
+
match=>`
|
|
31
|
+
${match},
|
|
32
|
+
resolve: {
|
|
33
|
+
alias: {
|
|
34
|
+
"@": path.resolve(__dirname, "./src"),
|
|
35
|
+
},
|
|
36
|
+
}`
|
|
37
|
+
)
|
|
38
|
+
fs.writeFileSync(viteConfigPath,finalCont)
|
|
39
|
+
|
|
40
|
+
await execa("npx",["shadcn@latest", "init","--yes"],{
|
|
41
|
+
cwd:frontPath,
|
|
42
|
+
stdio:"inherit"
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
await execa("npx",[ "shadcn@latest" ,"add" ,"button"],{
|
|
46
|
+
cwd:frontPath,
|
|
47
|
+
stdio:"inherit"
|
|
48
|
+
})
|
|
49
|
+
fs.writeFileSync(path.join(frontPath,"src/App.jsx"),`import { Button } from "@/components/ui/button"
|
|
50
|
+
|
|
51
|
+
function App() {
|
|
52
|
+
return (
|
|
53
|
+
<div className="flex min-h-svh flex-col items-center justify-center">
|
|
54
|
+
<h1>This botton is created from shadcn</h1>
|
|
55
|
+
<h2>vite ,tailwind and shadcn are setted now just go and enjoy coding</h2>
|
|
56
|
+
<Button>Click me</Button>
|
|
57
|
+
</div>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default App`)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.log(error);
|
|
68
|
+
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { execa } from "execa"
|
|
2
|
+
import fs from "fs"
|
|
3
|
+
import path from "path"
|
|
4
|
+
|
|
5
|
+
export const setupTailwind=async(frontPath)=>{
|
|
6
|
+
try {
|
|
7
|
+
await execa("npm",["install", "tailwindcss", "@tailwindcss/vite"],{
|
|
8
|
+
cwd:frontPath,
|
|
9
|
+
stdio:"inherit"
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const cssFile= path.join(frontPath,"src/index.css")
|
|
13
|
+
const updatedCssCont=`@import "tailwindcss";`
|
|
14
|
+
fs.writeFileSync(cssFile,updatedCssCont)
|
|
15
|
+
|
|
16
|
+
console.log("css updated");
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const htmlFile= path.join(frontPath,"index.html")
|
|
21
|
+
const htmlContent= fs.readFileSync(htmlFile,'utf8')
|
|
22
|
+
|
|
23
|
+
const updatedHtmlCont= htmlContent.replace(/<\/title>\s*/i,`</title> \n \t <link href="/src/style.css" rel="stylesheet"> \n`)
|
|
24
|
+
// console.log(updatedHtmlCont);
|
|
25
|
+
fs.writeFileSync(htmlFile,updatedHtmlCont)
|
|
26
|
+
|
|
27
|
+
console.log("html updated \n \n");
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
const configFile= path.join(frontPath,"vite.config.js")
|
|
31
|
+
const configCont= fs.readFileSync(configFile,'utf8')
|
|
32
|
+
const updatedConfigCont= configCont.replace(/plugins: \[\s*/,`plugins: [tailwindcss(),`)
|
|
33
|
+
fs.writeFileSync(configFile,`import tailwindcss from '@tailwindcss/vite' \n`+updatedConfigCont)
|
|
34
|
+
// console.log(updatedConfigCont);
|
|
35
|
+
|
|
36
|
+
console.log("pluggin updated \n \n");
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
} catch (error) {
|
|
42
|
+
console.log(error);
|
|
43
|
+
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { execa } from "execa";
|
|
2
|
+
|
|
3
|
+
export const setupVite=async(frontPath)=>{
|
|
4
|
+
try {
|
|
5
|
+
const proc=execa("npm",["create","vite@latest",".","--","--template","react"],{
|
|
6
|
+
cwd:frontPath,
|
|
7
|
+
stdio: ["pipe", "inherit", "inherit"]})
|
|
8
|
+
proc.stdin.write("n\n")
|
|
9
|
+
await proc;
|
|
10
|
+
} catch (error) {
|
|
11
|
+
console.log(error);
|
|
12
|
+
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// import { execa } from "execa";
|
|
16
|
+
|
|
17
|
+
// export const setupVite=async(frontPath)=>{
|
|
18
|
+
// try {
|
|
19
|
+
// const proc=execa("npm",["create","vite@latest","."],{
|
|
20
|
+
// cwd:frontPath,
|
|
21
|
+
// stdio: ["pipe","pipe","inherit"]
|
|
22
|
+
// })
|
|
23
|
+
// proc.stdout.on("data",(data)=>{
|
|
24
|
+
// const text=data.toString()
|
|
25
|
+
// console.log(text);
|
|
26
|
+
// if(text.includes("Select a framework"))
|
|
27
|
+
// {
|
|
28
|
+
// proc.stdin.write("\x1B[C\x1B[C\n")
|
|
29
|
+
// }
|
|
30
|
+
// else if(text.includes("Select a variant"))
|
|
31
|
+
// {
|
|
32
|
+
// proc.stdin.write("\x1B[C\x1B[C\x1B[C\n")
|
|
33
|
+
// }
|
|
34
|
+
// else
|
|
35
|
+
// {
|
|
36
|
+
// proc.stdin.write("n\n")
|
|
37
|
+
// }
|
|
38
|
+
|
|
39
|
+
// })
|
|
40
|
+
// await proc;
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
// } catch (error) {
|
|
46
|
+
// console.log(error);
|
|
47
|
+
|
|
48
|
+
// }
|
|
49
|
+
// }
|
|
50
|
+
|
|
51
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { exit } from 'process';
|
|
5
|
+
|
|
6
|
+
import { frontendSetup } from '../setups/frontend.setups.js';
|
|
7
|
+
import { backendSetup } from '../setups/backend.setup.js';
|
|
8
|
+
import { execa } from 'execa';
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
export const createProjectStructure=async(answer)=>{
|
|
12
|
+
try {
|
|
13
|
+
let dirPath=''
|
|
14
|
+
if (answer.currentFolder){
|
|
15
|
+
dirPath= process.cwd()
|
|
16
|
+
console.log(dirPath);
|
|
17
|
+
|
|
18
|
+
await frontentFolder(dirPath,answer);
|
|
19
|
+
|
|
20
|
+
await backendFolder(dirPath,answer);
|
|
21
|
+
}
|
|
22
|
+
else
|
|
23
|
+
{
|
|
24
|
+
dirPath= path.join(process.cwd(),answer.ProjectName) // main_dir path
|
|
25
|
+
// console.log(dirPath);
|
|
26
|
+
|
|
27
|
+
await ProjectFolder(answer.ProjectName) // main_dir created
|
|
28
|
+
console.log("folder created successfully");
|
|
29
|
+
|
|
30
|
+
await frontentFolder(dirPath,answer);
|
|
31
|
+
|
|
32
|
+
await backendFolder(dirPath,answer);
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
console.log(`
|
|
36
|
+
api calls - use
|
|
37
|
+
-> axiosInstance
|
|
38
|
+
now in one terminal got to
|
|
39
|
+
-> ${dirPath}/frontend
|
|
40
|
+
run
|
|
41
|
+
-> npm run dev
|
|
42
|
+
in next terminal go to
|
|
43
|
+
->${dirPath}/backend
|
|
44
|
+
run
|
|
45
|
+
-> npm run dev`);
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.log(error);
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const ProjectFolder=async(name)=>{
|
|
57
|
+
try {
|
|
58
|
+
|
|
59
|
+
if(fs.existsSync(name))
|
|
60
|
+
{
|
|
61
|
+
console.log(chalk.red("folder already exist"));
|
|
62
|
+
process.exit(1)
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
fs.mkdirSync(name)
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.log(error);
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const frontentFolder=async(dirPath,answer)=>{
|
|
73
|
+
try {
|
|
74
|
+
fs.mkdirSync(path.join(dirPath,"frontend"))
|
|
75
|
+
const frontPath=path.join(dirPath,"frontend")
|
|
76
|
+
|
|
77
|
+
await frontendSetup(frontPath)
|
|
78
|
+
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.log(error);
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const backendFolder=async(dirPath,answer)=>{
|
|
85
|
+
try {
|
|
86
|
+
fs.mkdirSync(path.join(dirPath,"backend"))
|
|
87
|
+
fs.mkdirSync(path.join(dirPath,"backend/src"))
|
|
88
|
+
const backPath=path.join(dirPath,"backend")
|
|
89
|
+
|
|
90
|
+
await execa("npm",["init","-y"],{
|
|
91
|
+
cwd:backPath,
|
|
92
|
+
stdio:"inherit"
|
|
93
|
+
})
|
|
94
|
+
await backendSetup(backPath,answer)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.log(error);
|
|
99
|
+
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import inquirer from "inquirer";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export const askQuestions=async()=>{
|
|
6
|
+
try {
|
|
7
|
+
console.log(chalk.red("Project Details"));
|
|
8
|
+
console.log(chalk.white("------------------"));
|
|
9
|
+
const answer=await inquirer.prompt([
|
|
10
|
+
{
|
|
11
|
+
type:"confirm",
|
|
12
|
+
name:"currentFolder",
|
|
13
|
+
message:"use current folder as the project folder or create new one(yes/no)?",
|
|
14
|
+
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type:"input",
|
|
18
|
+
name:"ProjectName",
|
|
19
|
+
message:"If no Enter the project Name :",
|
|
20
|
+
when:(answer)=>!answer.currentFolder,
|
|
21
|
+
validate:(value)=>{
|
|
22
|
+
if (!value)
|
|
23
|
+
{
|
|
24
|
+
value=null
|
|
25
|
+
return "Cannot leave Empty"
|
|
26
|
+
}
|
|
27
|
+
return true
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
type:"input",
|
|
33
|
+
name:"mongoURL",
|
|
34
|
+
message:"Enter the mongoDB url (double check before pasting)",
|
|
35
|
+
validate:(value)=>{
|
|
36
|
+
if (!value)
|
|
37
|
+
{
|
|
38
|
+
value=null
|
|
39
|
+
return "Cannot leave Empty"
|
|
40
|
+
}
|
|
41
|
+
return true
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
])
|
|
46
|
+
console.log(answer);
|
|
47
|
+
|
|
48
|
+
return answer;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.log(error.message);
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { setupAxios } from "../generator/setupAxios.generator.js";
|
|
2
|
+
import { setupDotEnv } from "../generator/setupDotEnv.generator.js";
|
|
3
|
+
import { setupExpress } from "../generator/setupExpress.generator.js";
|
|
4
|
+
import { setupMongo } from "../generator/setupMongo.generator.js";
|
|
5
|
+
|
|
6
|
+
export const backendSetup=async(backPath,answer)=>{
|
|
7
|
+
try {
|
|
8
|
+
await setupExpress(backPath)
|
|
9
|
+
await setupMongo(backPath,answer)
|
|
10
|
+
await setupDotEnv(backPath,answer)
|
|
11
|
+
} catch (error) {
|
|
12
|
+
console.log(error);
|
|
13
|
+
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { execa } from "execa"
|
|
2
|
+
import { setupVite } from "../generator/setupVite.generator.js";
|
|
3
|
+
import { setupTailwind } from "../generator/setupTailwind.generator.js";
|
|
4
|
+
import { setupShadCN } from "../generator/setupShadCN.generator.js";
|
|
5
|
+
import { setupAxios } from "../generator/setupAxios.generator.js";
|
|
6
|
+
|
|
7
|
+
export const frontendSetup=async(frontPath)=>{
|
|
8
|
+
try {
|
|
9
|
+
|
|
10
|
+
await setupVite(frontPath)
|
|
11
|
+
await setupTailwind(frontPath)
|
|
12
|
+
await setupShadCN(frontPath)
|
|
13
|
+
await setupAxios(frontPath)
|
|
14
|
+
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.log(error);
|
|
17
|
+
|
|
18
|
+
}
|
|
19
|
+
}
|