create-stackflow 1.0.4 → 1.0.7

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.
@@ -1,62 +1,7 @@
1
1
  import path from "node:path";
2
2
  import fs from "fs-extra";
3
- import { writeTemplate } from "../utils/template.js";
4
3
 
5
- export async function createRootFiles(context) {
6
- const frontendName = path.basename(context.frontendDir);
7
- const backendName = path.basename(context.backendDir);
8
-
9
- await writeTemplate(
10
- path.join(context.projectDir, "package.json"),
11
- `{
12
- "name": "{{projectName}}",
13
- "version": "1.0.0",
14
- "private": true,
15
- "scripts": {
16
- "dev": "concurrently \\"npm run dev --workspace {{backendName}}\\" \\"npm run dev --workspace {{frontendName}}\\"",
17
- "dev:frontend": "npm run dev --workspace {{frontendName}}",
18
- "dev:backend": "npm run dev --workspace {{backendName}}"
19
- },
20
- "workspaces": [
21
- "{{frontendName}}",
22
- "{{backendName}}"
23
- ],
24
- "devDependencies": {
25
- "concurrently": "latest"
26
- }
27
- }
28
- `,
29
- { ...context, frontendName, backendName }
30
- );
31
-
32
- await writeTemplate(
33
- path.join(context.projectDir, "README.md"),
34
- `# {{projectName}}
35
-
36
- Generated with \`create-stackflow\`.
37
-
38
- ## Development
39
-
40
- \`\`\`bash
41
- npm run dev
42
- \`\`\`
43
-
44
- Frontend runs on Vite/Next.js. Backend runs on Express at \`http://localhost:5000\`.
45
-
46
- ## Environment
47
-
48
- MongoDB local connection:
49
-
50
- \`\`\`
51
- mongodb://127.0.0.1:27017/{{databaseName}}
52
- \`\`\`
53
- `,
54
- context
55
- );
56
-
57
- await fs.outputFile(
58
- path.join(context.projectDir, ".gitignore"),
59
- `node_modules
4
+ const GITIGNORE = `node_modules
60
5
  .env
61
6
  .env.*
62
7
  dist
@@ -65,6 +10,9 @@ build
65
10
  coverage
66
11
  uploads/*
67
12
  !uploads/.gitkeep
68
- `
69
- );
13
+ `;
14
+
15
+ export async function createRootFiles(context) {
16
+ await fs.outputFile(path.join(context.frontendDir, ".gitignore"), GITIGNORE);
17
+ await fs.outputFile(path.join(context.backendDir, ".gitignore"), GITIGNORE);
70
18
  }
@@ -0,0 +1,42 @@
1
+ import path from "node:path";
2
+ import fs from "fs-extra";
3
+ import { execa } from "execa";
4
+
5
+ /**
6
+ * Hoist dependencies into project-root/node_modules via a temporary workspace
7
+ * package.json, then remove root package.json and lockfile so only
8
+ * frontend/, backend/, and node_modules/ remain at the project root.
9
+ */
10
+ export async function installHoistedWorkspace(context) {
11
+ const frontendName = path.basename(context.frontendDir);
12
+ const backendName = path.basename(context.backendDir);
13
+ const rootPkgPath = path.join(context.projectDir, "package.json");
14
+ const rootLockPath = path.join(context.projectDir, "package-lock.json");
15
+
16
+ await fs.writeJson(
17
+ rootPkgPath,
18
+ {
19
+ name: context.projectName,
20
+ private: true,
21
+ workspaces: [frontendName, backendName],
22
+ },
23
+ { spaces: 2 },
24
+ );
25
+
26
+ await execa("npm", ["install"], { cwd: context.projectDir, stdio: "ignore" });
27
+
28
+ await fs.remove(rootPkgPath);
29
+ if (await fs.pathExists(rootLockPath)) {
30
+ await fs.remove(rootLockPath);
31
+ }
32
+
33
+ await removeNestedNodeModules(context.frontendDir);
34
+ await removeNestedNodeModules(context.backendDir);
35
+ }
36
+
37
+ async function removeNestedNodeModules(dir) {
38
+ const nested = path.join(dir, "node_modules");
39
+ if (await fs.pathExists(nested)) {
40
+ await fs.remove(nested);
41
+ }
42
+ }
@@ -143,7 +143,6 @@ export async function askQuestions(projectName) {
143
143
  choices: [
144
144
  { name: "Zod", value: "zod" },
145
145
  { name: "Yup", value: "yup" },
146
- { name: "Joi", value: "joi" },
147
146
  { name: "None", value: "none" },
148
147
  ],
149
148
  default: "zod",
@@ -247,6 +246,16 @@ export async function askQuestions(projectName) {
247
246
  ],
248
247
  default: "javascript",
249
248
  },
249
+ {
250
+ type: "list",
251
+ name: "backendModule",
252
+ message: "Backend module system?",
253
+ choices: [
254
+ { name: "ES Modules (import/export)", value: "esm" },
255
+ { name: "CommonJS (require/module.exports)", value: "cjs" },
256
+ ],
257
+ default: "esm",
258
+ },
250
259
  {
251
260
  type: "list",
252
261
  name: "database",
@@ -311,6 +320,19 @@ export async function askQuestions(projectName) {
311
320
  { name: "hpp", value: "hpp" },
312
321
  ],
313
322
  },
323
+ {
324
+ type: "confirm",
325
+ name: "swagger",
326
+ message: "Add Swagger API documentation?",
327
+ default: false,
328
+ },
329
+ {
330
+ type: "confirm",
331
+ name: "socketio",
332
+ message:
333
+ "Add real-time chat (Socket.IO)? Includes WhatsApp-style chat requests + 1:1 messaging",
334
+ default: false,
335
+ },
314
336
  {
315
337
  type: "confirm",
316
338
  name: "runProject",
@@ -327,6 +349,7 @@ export async function askQuestions(projectName) {
327
349
  tailwind: frontendAnswers.styling === "tailwind",
328
350
  shadcn: frontendAnswers.uiLibrary === "shadcn",
329
351
  axios: frontendAnswers.dataFetching === "axios",
352
+ form: frontendAnswers.formLibrary,
330
353
  reactHookForm: frontendAnswers.formLibrary === "react-hook-form",
331
354
 
332
355
  helmet: backendAnswers.securityPackages.includes("helmet"),
@@ -336,6 +359,8 @@ export async function askQuestions(projectName) {
336
359
 
337
360
  multer: backendAnswers.fileUpload === "Multer",
338
361
  cloudinary: backendAnswers.fileUpload === "Cloudinary",
362
+ swagger: backendAnswers.swagger,
363
+ socketio: backendAnswers.socketio,
339
364
  runProject: backendAnswers.runProject,
340
365
  };
341
366
  }