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 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.7")
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-stackflow",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Interactive CLI for generating modern full-stack MERN applications.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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
- await execa("npm", ["run", "dev"], { cwd: context.frontendDir, stdio: "inherit" });
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.cyan(` cd ${context.projectName}/${frontend}`));
168
- console.log(chalk.cyan(" npm run dev"));
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: "ignore" });
30
+ await execa("npx", args, { cwd: context.projectDir, stdio: "inherit" });
31
31
  } else {
32
32
  const template = context.language === "typescript" ? "react-ts" : "react";
33
- await execa("npm", ["create", "vite@latest", path.basename(context.frontendDir), "--", "--template", template], {
34
- cwd: context.projectDir,
35
- stdio: "ignore"
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: `concurrently -n backend,frontend -c blue,green "npm run dev --prefix ../${backendName}" "vite"`,
101
+ dev: "vite",
85
102
  };
86
103
  } else {
87
104
  pkg.scripts = {
88
105
  ...(pkg.scripts || {}),
89
- dev: `concurrently -n backend,frontend -c blue,green "npm run dev --prefix ../${backendName}" "next dev"`,
106
+ dev: "next dev",
90
107
  };
91
108
  }
92
109