create-stackflow 1.0.7 ā 1.0.9
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 +9 -17
- package/cli.js +1 -1
- package/package.json +1 -1
- package/src/commands/create.js +18 -4
- package/src/generators/frontend.js +28 -11
package/README.md
CHANGED
|
@@ -230,9 +230,17 @@ npx create-stackflow
|
|
|
230
230
|
|
|
231
231
|
## Start Project
|
|
232
232
|
|
|
233
|
+
### Start Backend
|
|
234
|
+
|
|
233
235
|
```bash
|
|
234
|
-
cd my-app
|
|
236
|
+
cd my-app/backend
|
|
237
|
+
npm run dev
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Start Frontend
|
|
235
241
|
|
|
242
|
+
```bash
|
|
243
|
+
cd my-app/frontend
|
|
236
244
|
npm run dev
|
|
237
245
|
```
|
|
238
246
|
|
|
@@ -248,22 +256,6 @@ MONGO_URI=mongodb://127.0.0.1:27017/myapp
|
|
|
248
256
|
|
|
249
257
|
---
|
|
250
258
|
|
|
251
|
-
# Root Development Scripts
|
|
252
|
-
|
|
253
|
-
StackFlow automatically configures:
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
npm run dev
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
This starts:
|
|
260
|
-
- frontend
|
|
261
|
-
- backend
|
|
262
|
-
|
|
263
|
-
simultaneously using `concurrently`.
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
259
|
# CLI Architecture
|
|
268
260
|
|
|
269
261
|
```text
|
package/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ const program = new Command();
|
|
|
8
8
|
program
|
|
9
9
|
.name("create-stackflow")
|
|
10
10
|
.description("Generate a production-minded MERN starter with frontend, backend, auth, CRUD, and dashboard UI.")
|
|
11
|
-
.version("1.0.
|
|
11
|
+
.version("1.0.9")
|
|
12
12
|
.argument("[project-name]", "project folder name")
|
|
13
13
|
.option("--skip-install", "generate files without installing dependencies")
|
|
14
14
|
.option("--yes", "use recommended defaults")
|
package/package.json
CHANGED
package/src/commands/create.js
CHANGED
|
@@ -5,6 +5,7 @@ import fs from "fs-extra";
|
|
|
5
5
|
import ora from "ora";
|
|
6
6
|
import validatePackageName from "validate-npm-package-name";
|
|
7
7
|
import { execa } from "execa";
|
|
8
|
+
import concurrently from "concurrently";
|
|
8
9
|
import { askQuestions } from "../utils/prompts.js";
|
|
9
10
|
import { createRootFiles } from "../generators/root.js";
|
|
10
11
|
import { createBackend } from "../generators/backend.js";
|
|
@@ -47,9 +48,9 @@ export async function createStackFlow(options) {
|
|
|
47
48
|
|
|
48
49
|
await fs.ensureDir(projectDir);
|
|
49
50
|
|
|
50
|
-
await step("Creating root workspace", () => createRootFiles(context));
|
|
51
51
|
await createFrontend(context);
|
|
52
52
|
await createBackend(context);
|
|
53
|
+
await step("Writing project gitignore files", () => createRootFiles(context));
|
|
53
54
|
|
|
54
55
|
if (!context.skipInstall) {
|
|
55
56
|
await step("Installing dependencies (root node_modules)", () =>
|
|
@@ -62,7 +63,16 @@ export async function createStackFlow(options) {
|
|
|
62
63
|
if (context.runProject) {
|
|
63
64
|
console.log(chalk.cyan("\nš Starting the project..."));
|
|
64
65
|
try {
|
|
65
|
-
|
|
66
|
+
const { result } = concurrently(
|
|
67
|
+
[
|
|
68
|
+
{ command: "npm run dev", name: "backend", cwd: context.backendDir, prefixColor: "blue" },
|
|
69
|
+
{ command: "npm run dev", name: "frontend", cwd: context.frontendDir, prefixColor: "green" },
|
|
70
|
+
],
|
|
71
|
+
{
|
|
72
|
+
killOthers: ["failure", "success"],
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
await result;
|
|
66
76
|
} catch (error) {
|
|
67
77
|
console.error(chalk.red("\nFailed to start the project."));
|
|
68
78
|
console.error(chalk.dim(error.message));
|
|
@@ -164,8 +174,12 @@ function printSuccess(context) {
|
|
|
164
174
|
console.log(chalk.green.bold("StackFlow app created successfully."));
|
|
165
175
|
console.log();
|
|
166
176
|
console.log(chalk.white("Next steps:"));
|
|
167
|
-
console.log(chalk.
|
|
168
|
-
console.log(chalk.cyan(
|
|
177
|
+
console.log(chalk.white(" Start Backend:"));
|
|
178
|
+
console.log(chalk.cyan(` cd ${context.projectName}/${backend}`));
|
|
179
|
+
console.log(chalk.cyan(" npm run dev"));
|
|
180
|
+
console.log(chalk.white(" Start Frontend:"));
|
|
181
|
+
console.log(chalk.cyan(` cd ${context.projectName}/${frontend}`));
|
|
182
|
+
console.log(chalk.cyan(" npm run dev"));
|
|
169
183
|
console.log();
|
|
170
184
|
console.log(chalk.dim(`Frontend: ${frontend}`));
|
|
171
185
|
console.log(chalk.dim(`Backend: ${backend}`));
|
|
@@ -27,14 +27,25 @@ async function scaffoldOfficialFrontend(context) {
|
|
|
27
27
|
"--import-alias",
|
|
28
28
|
"@/*"
|
|
29
29
|
];
|
|
30
|
-
await execa("npx", args, { cwd: context.projectDir, stdio: "
|
|
30
|
+
await execa("npx", args, { cwd: context.projectDir, stdio: "inherit" });
|
|
31
31
|
} else {
|
|
32
32
|
const template = context.language === "typescript" ? "react-ts" : "react";
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const frontendName = path.basename(context.frontendDir);
|
|
34
|
+
if (await fs.pathExists(context.frontendDir)) {
|
|
35
|
+
const existing = await fs.readdir(context.frontendDir);
|
|
36
|
+
if (existing.length > 0) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`Frontend folder "${frontendName}" already exists and is not empty. Remove it or choose another frontend folder name.`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
await execa(
|
|
43
|
+
"npm",
|
|
44
|
+
["create", "vite@latest", frontendName, "--", "--template", template, "--no-interactive"],
|
|
45
|
+
{ cwd: context.projectDir, stdio: "inherit" },
|
|
46
|
+
);
|
|
37
47
|
}
|
|
48
|
+
await assertFrontendScaffolded(context);
|
|
38
49
|
spinner.succeed("Creating frontend with official generator");
|
|
39
50
|
} catch (error) {
|
|
40
51
|
spinner.fail("Creating frontend with official generator");
|
|
@@ -42,6 +53,16 @@ async function scaffoldOfficialFrontend(context) {
|
|
|
42
53
|
}
|
|
43
54
|
}
|
|
44
55
|
|
|
56
|
+
async function assertFrontendScaffolded(context) {
|
|
57
|
+
const packageFile = path.join(context.frontendDir, "package.json");
|
|
58
|
+
if (!(await fs.pathExists(packageFile))) {
|
|
59
|
+
throw new Error(
|
|
60
|
+
`Frontend scaffold did not create package.json at ${packageFile}. ` +
|
|
61
|
+
"The official generator may have been cancelled or failed. Try again in an empty project folder.",
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
45
66
|
async function installFrontendDependencies(context) {
|
|
46
67
|
await updateFrontendPackage(context);
|
|
47
68
|
}
|
|
@@ -73,20 +94,16 @@ async function updateFrontendPackage(context) {
|
|
|
73
94
|
pkg.devDependencies["@tailwindcss/vite"] = "latest";
|
|
74
95
|
}
|
|
75
96
|
|
|
76
|
-
const backendName = path.basename(context.backendDir);
|
|
77
|
-
pkg.devDependencies = pkg.devDependencies || {};
|
|
78
|
-
pkg.devDependencies.concurrently = "latest";
|
|
79
|
-
|
|
80
97
|
if (context.frontend === "react") {
|
|
81
98
|
pkg.scripts = {
|
|
82
99
|
...(pkg.scripts || {}),
|
|
83
100
|
build: "vite build",
|
|
84
|
-
dev:
|
|
101
|
+
dev: "vite",
|
|
85
102
|
};
|
|
86
103
|
} else {
|
|
87
104
|
pkg.scripts = {
|
|
88
105
|
...(pkg.scripts || {}),
|
|
89
|
-
dev:
|
|
106
|
+
dev: "next dev",
|
|
90
107
|
};
|
|
91
108
|
}
|
|
92
109
|
|