stack-starter-cli 1.0.0 → 1.1.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 +174 -21
- package/bin/index.js +220 -63
- package/package.json +20 -7
package/README.md
CHANGED
|
@@ -1,33 +1,186 @@
|
|
|
1
|
-
# starter-cli
|
|
1
|
+
# stack-starter-cli
|
|
2
2
|
|
|
3
|
-
A simple CLI tool to quickly create full stack
|
|
3
|
+
A simple CLI tool to quickly create starter projects for frontend, backend, or full stack development.
|
|
4
|
+
|
|
5
|
+
It helps you create project folders, install dependencies, and generate starter files in a few commands.
|
|
6
|
+
|
|
7
|
+
---
|
|
4
8
|
|
|
5
9
|
## Features
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
* HTML / CSS / JavaScript starter
|
|
12
|
+
* React starter using Vite
|
|
13
|
+
* Node.js backend using Express
|
|
14
|
+
* Custom backend port support
|
|
15
|
+
* Automatic `.env` file creation
|
|
16
|
+
* Package manager choice: npm, yarn, or pnpm
|
|
17
|
+
* Ready-to-use starter folder structure
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
Install globally from npm:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g stack-starter-cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
After installing, use the command:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
stack-starter
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Basic Usage
|
|
38
|
+
|
|
39
|
+
### Interactive mode
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
stack-starter
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The CLI will ask for project details step by step.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### Create a project with only project name
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
stack-starter my-app
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The CLI will ask the remaining questions.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Frontend and Backend Commands
|
|
60
|
+
|
|
61
|
+
### React + Node.js
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
stack-starter my-app --react --node
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### HTML + Node.js
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
stack-starter my-app --html --node
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### React only
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
stack-starter my-app --react
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### HTML only
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
stack-starter my-app --html
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Node.js only
|
|
11
86
|
|
|
12
|
-
|
|
87
|
+
```bash
|
|
88
|
+
stack-starter my-app --node
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Version 1.1.0 Features
|
|
94
|
+
|
|
95
|
+
### Custom backend port
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
stack-starter my-app --react --node --port 8000
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
If no port is given, the default port is `5000`.
|
|
102
|
+
|
|
103
|
+
If the selected port is invalid or already in use, the CLI shows a clear message.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
### Package manager selection
|
|
108
|
+
|
|
109
|
+
### npm
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
stack-starter my-app --react --node --pm npm
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### yarn
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
stack-starter my-app --react --node --pm yarn
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### pnpm
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
stack-starter my-app --react --node --pm pnpm
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If the selected package manager is not installed, the CLI will stop and show a message.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Generated Project Structure
|
|
132
|
+
|
|
133
|
+
Example for full stack projects:
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
my-app/
|
|
137
|
+
client/
|
|
138
|
+
server/
|
|
139
|
+
.gitignore
|
|
140
|
+
README.md
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Help
|
|
146
|
+
|
|
147
|
+
Show help:
|
|
13
148
|
|
|
14
149
|
```bash
|
|
15
|
-
|
|
16
|
-
|
|
150
|
+
stack-starter --help
|
|
151
|
+
```
|
|
17
152
|
|
|
18
|
-
|
|
153
|
+
Show version:
|
|
19
154
|
|
|
20
|
-
|
|
21
|
-
|
|
155
|
+
```bash
|
|
156
|
+
stack-starter --version
|
|
22
157
|
```
|
|
23
158
|
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Example Commands
|
|
162
|
+
|
|
24
163
|
```bash
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
164
|
+
stack-starter
|
|
165
|
+
stack-starter my-app
|
|
166
|
+
stack-starter my-app --react
|
|
167
|
+
stack-starter my-app --html
|
|
168
|
+
stack-starter my-app --react --node
|
|
169
|
+
stack-starter my-app --html --node
|
|
170
|
+
stack-starter my-app --react --node --port 8000
|
|
171
|
+
stack-starter my-app --react --node --pm npm
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Notes
|
|
177
|
+
|
|
178
|
+
* The project folder name must be unique.
|
|
179
|
+
* If the folder already exists, the CLI will stop before asking setup questions.
|
|
180
|
+
* For backend projects, a `.env` file is created automatically.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
package/bin/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// -----------------------------
|
|
4
4
|
// Required packages
|
|
@@ -6,22 +6,25 @@
|
|
|
6
6
|
const inquirer = require("inquirer").default;
|
|
7
7
|
const fs = require("fs");
|
|
8
8
|
const path = require("path");
|
|
9
|
+
const net = require("net");
|
|
9
10
|
const { execSync } = require("child_process");
|
|
10
11
|
|
|
11
12
|
// -----------------------------
|
|
12
|
-
//
|
|
13
|
+
// Help / Version
|
|
13
14
|
// -----------------------------
|
|
14
15
|
const packageJson = require("../package.json");
|
|
15
16
|
|
|
16
17
|
if (process.argv.includes("--help") || process.argv.includes("-h")) {
|
|
17
18
|
console.log(`
|
|
18
|
-
starter - project scaffolding CLI
|
|
19
|
+
stack-starter - project scaffolding CLI
|
|
19
20
|
|
|
20
21
|
Usage:
|
|
21
|
-
starter
|
|
22
|
-
starter my-app
|
|
23
|
-
starter my-app --react --node
|
|
24
|
-
starter my-app --html
|
|
22
|
+
stack-starter
|
|
23
|
+
stack-starter my-app
|
|
24
|
+
stack-starter my-app --react --node
|
|
25
|
+
stack-starter my-app --html
|
|
26
|
+
stack-starter my-app --react --node --port 8000
|
|
27
|
+
stack-starter my-app --react --node --pm pnpm
|
|
25
28
|
|
|
26
29
|
Options:
|
|
27
30
|
--help, -h Show help
|
|
@@ -29,11 +32,8 @@ Options:
|
|
|
29
32
|
--react Use React.js (Vite)
|
|
30
33
|
--html Use HTML / CSS / JavaScript
|
|
31
34
|
--node Use Node.js (Express)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
• HTML / CSS / JavaScript starter
|
|
35
|
-
• React.js (Vite) starter
|
|
36
|
-
• Node.js (Express) backend
|
|
35
|
+
--port Custom backend port
|
|
36
|
+
--pm Package manager (npm, yarn, pnpm)
|
|
37
37
|
`);
|
|
38
38
|
process.exit(0);
|
|
39
39
|
}
|
|
@@ -55,8 +55,14 @@ const useReact = process.argv.includes("--react");
|
|
|
55
55
|
const useHtml = process.argv.includes("--html");
|
|
56
56
|
const useNode = process.argv.includes("--node");
|
|
57
57
|
|
|
58
|
+
const portIndex = process.argv.indexOf("--port");
|
|
59
|
+
const cliPort = portIndex !== -1 ? process.argv[portIndex + 1] : null;
|
|
60
|
+
|
|
61
|
+
const pmIndex = process.argv.indexOf("--pm");
|
|
62
|
+
const cliPackageManager = pmIndex !== -1 ? process.argv[pmIndex + 1] : null;
|
|
63
|
+
|
|
58
64
|
// -----------------------------
|
|
59
|
-
// Resolve
|
|
65
|
+
// Resolve frontend/backend
|
|
60
66
|
// -----------------------------
|
|
61
67
|
let cliFrontend = null;
|
|
62
68
|
let cliBackend = null;
|
|
@@ -65,8 +71,30 @@ if (useReact) cliFrontend = "React.js (Vite)";
|
|
|
65
71
|
if (useHtml) cliFrontend = "HTML / CSS / JavaScript";
|
|
66
72
|
if (useNode) cliBackend = "Node.js (Express)";
|
|
67
73
|
|
|
74
|
+
// if user explicitly chooses only frontend
|
|
75
|
+
if ((useReact || useHtml) && !useNode) {
|
|
76
|
+
cliBackend = "None";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// if user explicitly chooses only backend
|
|
80
|
+
if (useNode && !useReact && !useHtml) {
|
|
81
|
+
cliFrontend = "None";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// -----------------------------
|
|
85
|
+
// Early duplicate folder check
|
|
86
|
+
// -----------------------------
|
|
87
|
+
if (cliProjectName) {
|
|
88
|
+
const earlyProjectPath = path.join(process.cwd(), cliProjectName);
|
|
89
|
+
|
|
90
|
+
if (fs.existsSync(earlyProjectPath)) {
|
|
91
|
+
console.log("\nA project with this name already exists.");
|
|
92
|
+
process.exit(0);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
68
96
|
// -----------------------------
|
|
69
|
-
// Helper: copy template
|
|
97
|
+
// Helper: copy template
|
|
70
98
|
// -----------------------------
|
|
71
99
|
function copyTemplate(source, destination) {
|
|
72
100
|
const content = fs.readFileSync(source, "utf-8");
|
|
@@ -74,7 +102,54 @@ function copyTemplate(source, destination) {
|
|
|
74
102
|
}
|
|
75
103
|
|
|
76
104
|
// -----------------------------
|
|
77
|
-
//
|
|
105
|
+
// Helper: package manager installed?
|
|
106
|
+
// -----------------------------
|
|
107
|
+
function isPackageManagerInstalled(pm) {
|
|
108
|
+
try {
|
|
109
|
+
execSync(`${pm} --version`, {
|
|
110
|
+
stdio: "ignore",
|
|
111
|
+
shell: process.env.ComSpec,
|
|
112
|
+
});
|
|
113
|
+
return true;
|
|
114
|
+
} catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// -----------------------------
|
|
120
|
+
// Early package manager check
|
|
121
|
+
// -----------------------------
|
|
122
|
+
if (cliPackageManager) {
|
|
123
|
+
if (!["npm", "yarn", "pnpm"].includes(cliPackageManager)) {
|
|
124
|
+
console.log("\nInvalid package manager. Use npm, yarn, or pnpm.");
|
|
125
|
+
process.exit(0);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!isPackageManagerInstalled(cliPackageManager)) {
|
|
129
|
+
console.log(`\n${cliPackageManager} is not installed on this machine.`);
|
|
130
|
+
process.exit(0);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// -----------------------------
|
|
135
|
+
// Helper: check free port
|
|
136
|
+
// -----------------------------
|
|
137
|
+
function isPortFree(port) {
|
|
138
|
+
return new Promise((resolve) => {
|
|
139
|
+
const server = net.createServer();
|
|
140
|
+
|
|
141
|
+
server.once("error", () => resolve(false));
|
|
142
|
+
|
|
143
|
+
server.once("listening", () => {
|
|
144
|
+
server.close(() => resolve(true));
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
server.listen(port);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// -----------------------------
|
|
152
|
+
// Prompt
|
|
78
153
|
// -----------------------------
|
|
79
154
|
inquirer
|
|
80
155
|
.prompt([
|
|
@@ -113,46 +188,87 @@ inquirer
|
|
|
113
188
|
default: 1,
|
|
114
189
|
when: !cliBackend,
|
|
115
190
|
},
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
191
|
+
{
|
|
192
|
+
name: "port",
|
|
193
|
+
message: "Enter backend port:",
|
|
194
|
+
default: cliPort || "5000",
|
|
195
|
+
when(answers) {
|
|
196
|
+
return (
|
|
197
|
+
!cliPort &&
|
|
198
|
+
(cliBackend === "Node.js (Express)" ||
|
|
199
|
+
answers.backend === "Node.js (Express)")
|
|
200
|
+
);
|
|
201
|
+
},
|
|
202
|
+
validate(input) {
|
|
203
|
+
if (!/^[0-9]+$/.test(input)) {
|
|
204
|
+
return "Entered wrong port number format. Example: 8000";
|
|
205
|
+
}
|
|
121
206
|
|
|
122
|
-
|
|
123
|
-
answers.frontend = cliFrontend;
|
|
124
|
-
}
|
|
207
|
+
const port = Number(input);
|
|
125
208
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
209
|
+
if (port < 1 || port > 65535) {
|
|
210
|
+
return "Port must be between 1 and 65535.";
|
|
211
|
+
}
|
|
129
212
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
213
|
+
return true;
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: "packageManager",
|
|
218
|
+
message: "Choose package manager:",
|
|
219
|
+
type: "rawlist",
|
|
220
|
+
choices: ["npm", "yarn", "pnpm"],
|
|
221
|
+
default: 0,
|
|
222
|
+
when: !cliPackageManager,
|
|
223
|
+
},
|
|
224
|
+
])
|
|
225
|
+
.then(async (answers) => {
|
|
226
|
+
if (cliProjectName) answers.projectName = cliProjectName;
|
|
227
|
+
if (cliFrontend) answers.frontend = cliFrontend;
|
|
228
|
+
if (cliBackend) answers.backend = cliBackend;
|
|
133
229
|
|
|
134
|
-
if (!answers.
|
|
135
|
-
|
|
136
|
-
}
|
|
230
|
+
if (!answers.frontend) answers.frontend = "None";
|
|
231
|
+
if (!answers.backend) answers.backend = "None";
|
|
137
232
|
|
|
138
|
-
|
|
233
|
+
answers.packageManager =
|
|
234
|
+
cliPackageManager || answers.packageManager || "npm";
|
|
139
235
|
|
|
140
236
|
// -----------------------------
|
|
141
|
-
//
|
|
237
|
+
// Late duplicate check (manual prompt project name)
|
|
142
238
|
// -----------------------------
|
|
239
|
+
const projectPath = path.join(process.cwd(), answers.projectName);
|
|
240
|
+
|
|
143
241
|
if (fs.existsSync(projectPath)) {
|
|
144
242
|
console.log("\nA project with this name already exists.");
|
|
145
243
|
return;
|
|
146
244
|
}
|
|
147
245
|
|
|
148
246
|
// -----------------------------
|
|
149
|
-
//
|
|
247
|
+
// Port validation
|
|
150
248
|
// -----------------------------
|
|
151
|
-
|
|
249
|
+
if (answers.backend === "Node.js (Express)") {
|
|
250
|
+
answers.port = Number(cliPort || answers.port || 5000);
|
|
251
|
+
|
|
252
|
+
if (!/^[0-9]+$/.test(String(answers.port))) {
|
|
253
|
+
console.log("\nEntered wrong port number format. Example: 8000");
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const free = await isPortFree(answers.port);
|
|
258
|
+
|
|
259
|
+
if (!free) {
|
|
260
|
+
console.log(
|
|
261
|
+
`\nSomething is already running on port ${answers.port}. Choose another port.`
|
|
262
|
+
);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
152
266
|
|
|
153
267
|
// -----------------------------
|
|
154
|
-
//
|
|
268
|
+
// Create project root
|
|
155
269
|
// -----------------------------
|
|
270
|
+
fs.mkdirSync(projectPath);
|
|
271
|
+
|
|
156
272
|
fs.writeFileSync(
|
|
157
273
|
path.join(projectPath, ".gitignore"),
|
|
158
274
|
"node_modules\n.env\ndist\n.vite\n.DS_Store\ncoverage"
|
|
@@ -164,7 +280,7 @@ inquirer
|
|
|
164
280
|
);
|
|
165
281
|
|
|
166
282
|
// =====================================================
|
|
167
|
-
// BACKEND
|
|
283
|
+
// BACKEND
|
|
168
284
|
// =====================================================
|
|
169
285
|
if (answers.backend === "Node.js (Express)") {
|
|
170
286
|
const serverPath = path.join(projectPath, "server");
|
|
@@ -174,6 +290,8 @@ inquirer
|
|
|
174
290
|
console.log("\nSetting up backend...");
|
|
175
291
|
|
|
176
292
|
try {
|
|
293
|
+
const pm = answers.packageManager;
|
|
294
|
+
|
|
177
295
|
execSync("npm init -y", {
|
|
178
296
|
cwd: serverPath,
|
|
179
297
|
stdio: "inherit",
|
|
@@ -191,35 +309,68 @@ inquirer
|
|
|
191
309
|
};
|
|
192
310
|
|
|
193
311
|
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
312
|
+
}
|
|
194
313
|
|
|
195
|
-
|
|
314
|
+
if (pm === "npm") {
|
|
315
|
+
execSync("npm install express cors dotenv", {
|
|
316
|
+
cwd: serverPath,
|
|
317
|
+
stdio: "inherit",
|
|
318
|
+
shell: process.env.ComSpec,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
execSync("npm install -D nodemon", {
|
|
322
|
+
cwd: serverPath,
|
|
323
|
+
stdio: "inherit",
|
|
324
|
+
shell: process.env.ComSpec,
|
|
325
|
+
});
|
|
196
326
|
}
|
|
197
327
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
328
|
+
if (pm === "yarn") {
|
|
329
|
+
execSync("yarn add express cors dotenv", {
|
|
330
|
+
cwd: serverPath,
|
|
331
|
+
stdio: "inherit",
|
|
332
|
+
shell: process.env.ComSpec,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
execSync("yarn add -D nodemon", {
|
|
336
|
+
cwd: serverPath,
|
|
337
|
+
stdio: "inherit",
|
|
338
|
+
shell: process.env.ComSpec,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
203
341
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
342
|
+
if (pm === "pnpm") {
|
|
343
|
+
execSync("pnpm add express cors dotenv", {
|
|
344
|
+
cwd: serverPath,
|
|
345
|
+
stdio: "inherit",
|
|
346
|
+
shell: process.env.ComSpec,
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
execSync("pnpm add -D nodemon", {
|
|
350
|
+
cwd: serverPath,
|
|
351
|
+
stdio: "inherit",
|
|
352
|
+
shell: process.env.ComSpec,
|
|
353
|
+
});
|
|
354
|
+
}
|
|
209
355
|
|
|
210
356
|
copyTemplate(
|
|
211
357
|
path.join(__dirname, "..", "templates", "server", "index.js"),
|
|
212
358
|
path.join(serverPath, "index.js")
|
|
213
359
|
);
|
|
360
|
+
|
|
361
|
+
fs.writeFileSync(
|
|
362
|
+
path.join(serverPath, ".env"),
|
|
363
|
+
`PORT=${answers.port}`
|
|
364
|
+
);
|
|
214
365
|
} catch (error) {
|
|
215
366
|
console.log("\n❌ Backend setup failed.");
|
|
216
|
-
console.log("Check
|
|
367
|
+
console.log("Check package manager installation or internet connection.");
|
|
217
368
|
return;
|
|
218
369
|
}
|
|
219
370
|
}
|
|
220
371
|
|
|
221
372
|
// =====================================================
|
|
222
|
-
//
|
|
373
|
+
// HTML FRONTEND
|
|
223
374
|
// =====================================================
|
|
224
375
|
if (answers.frontend === "HTML / CSS / JavaScript") {
|
|
225
376
|
const clientPath = path.join(projectPath, "client");
|
|
@@ -267,10 +418,14 @@ inquirer
|
|
|
267
418
|
);
|
|
268
419
|
|
|
269
420
|
if (answers.backend === "Node.js (Express)") {
|
|
270
|
-
|
|
421
|
+
let script = fs.readFileSync(
|
|
271
422
|
path.join(__dirname, "..", "templates", "html", "script.js"),
|
|
272
|
-
|
|
423
|
+
"utf8"
|
|
273
424
|
);
|
|
425
|
+
|
|
426
|
+
script = script.replace(/5000/g, answers.port);
|
|
427
|
+
|
|
428
|
+
fs.writeFileSync(path.join(clientPath, "script.js"), script);
|
|
274
429
|
} else {
|
|
275
430
|
fs.writeFileSync(
|
|
276
431
|
path.join(clientPath, "script.js"),
|
|
@@ -286,7 +441,7 @@ messageEl.textContent = "No backend selected. Frontend is ready.";`
|
|
|
286
441
|
}
|
|
287
442
|
|
|
288
443
|
// =====================================================
|
|
289
|
-
// FRONTEND
|
|
444
|
+
// REACT FRONTEND
|
|
290
445
|
// =====================================================
|
|
291
446
|
else if (answers.frontend === "React.js (Vite)") {
|
|
292
447
|
const clientPath = path.join(projectPath, "client");
|
|
@@ -308,13 +463,15 @@ messageEl.textContent = "No backend selected. Frontend is ready.";`
|
|
|
308
463
|
shell: process.env.ComSpec,
|
|
309
464
|
});
|
|
310
465
|
|
|
311
|
-
console.log("✅ React installation complete!");
|
|
312
|
-
|
|
313
466
|
if (answers.backend === "Node.js (Express)") {
|
|
314
|
-
|
|
467
|
+
let appCode = fs.readFileSync(
|
|
315
468
|
path.join(__dirname, "..", "templates", "react", "App.jsx"),
|
|
316
|
-
|
|
469
|
+
"utf8"
|
|
317
470
|
);
|
|
471
|
+
|
|
472
|
+
appCode = appCode.replace(/5000/g, answers.port);
|
|
473
|
+
|
|
474
|
+
fs.writeFileSync(path.join(clientPath, "src", "App.jsx"), appCode);
|
|
318
475
|
}
|
|
319
476
|
} catch (error) {
|
|
320
477
|
console.log("\n❌ React setup failed.");
|
|
@@ -324,7 +481,7 @@ messageEl.textContent = "No backend selected. Frontend is ready.";`
|
|
|
324
481
|
}
|
|
325
482
|
|
|
326
483
|
// =====================================================
|
|
327
|
-
// FINAL
|
|
484
|
+
// FINAL
|
|
328
485
|
// =====================================================
|
|
329
486
|
console.log(`\n✅ Project "${answers.projectName}" created successfully!`);
|
|
330
487
|
|
|
@@ -334,7 +491,7 @@ messageEl.textContent = "No backend selected. Frontend is ready.";`
|
|
|
334
491
|
) {
|
|
335
492
|
console.log("\nRun backend:");
|
|
336
493
|
console.log(`cd ${answers.projectName}/server`);
|
|
337
|
-
console.log(
|
|
494
|
+
console.log(`${answers.packageManager} run dev`);
|
|
338
495
|
|
|
339
496
|
console.log("\nThen open frontend:");
|
|
340
497
|
console.log(`${answers.projectName}/client/index.html`);
|
|
@@ -344,7 +501,7 @@ messageEl.textContent = "No backend selected. Frontend is ready.";`
|
|
|
344
501
|
) {
|
|
345
502
|
console.log("\nRun backend:");
|
|
346
503
|
console.log(`cd ${answers.projectName}/server`);
|
|
347
|
-
console.log(
|
|
504
|
+
console.log(`${answers.packageManager} run dev`);
|
|
348
505
|
|
|
349
506
|
console.log("\nOpen another terminal and run frontend:");
|
|
350
507
|
console.log(`cd ${answers.projectName}/client`);
|
|
@@ -359,6 +516,6 @@ messageEl.textContent = "No backend selected. Frontend is ready.";`
|
|
|
359
516
|
} else if (answers.backend === "Node.js (Express)") {
|
|
360
517
|
console.log("\nRun backend:");
|
|
361
518
|
console.log(`cd ${answers.projectName}/server`);
|
|
362
|
-
console.log(
|
|
519
|
+
console.log(`${answers.packageManager} run dev`);
|
|
363
520
|
}
|
|
364
|
-
});
|
|
521
|
+
});
|
package/package.json
CHANGED
|
@@ -1,30 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stack-starter-cli",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "CLI to
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "CLI tool to quickly scaffold HTML, React, and Node.js starter projects.",
|
|
5
5
|
"main": "bin/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"stack-starter": "./bin/index.js"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"bin",
|
|
11
|
-
"templates"
|
|
11
|
+
"templates",
|
|
12
|
+
"README.md"
|
|
12
13
|
],
|
|
13
14
|
"scripts": {
|
|
14
15
|
"start": "node bin/index.js"
|
|
15
16
|
},
|
|
16
17
|
"keywords": [
|
|
17
18
|
"cli",
|
|
18
|
-
"starter",
|
|
19
19
|
"scaffold",
|
|
20
|
-
"
|
|
20
|
+
"starter",
|
|
21
|
+
"boilerplate",
|
|
22
|
+
"fullstack",
|
|
23
|
+
"frontend",
|
|
24
|
+
"backend",
|
|
21
25
|
"react",
|
|
22
|
-
"
|
|
26
|
+
"vite",
|
|
27
|
+
"express",
|
|
28
|
+
"node"
|
|
23
29
|
],
|
|
24
30
|
"author": "SACHITH KASA",
|
|
25
31
|
"license": "MIT",
|
|
26
32
|
"type": "commonjs",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "https://github.com/SACHITH31/starter_cli"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18"
|
|
39
|
+
},
|
|
27
40
|
"dependencies": {
|
|
28
41
|
"inquirer": "^13.4.2"
|
|
29
42
|
}
|
|
30
|
-
}
|
|
43
|
+
}
|