create-fsd-architecture 1.0.1 → 1.0.3

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.
Files changed (3) hide show
  1. package/README.md +84 -0
  2. package/bin/index.mjs +180 -39
  3. package/package.json +8 -2
package/README.md CHANGED
@@ -0,0 +1,84 @@
1
+ # create-fsd-architecture
2
+
3
+ Scaffold production-ready projects with [Feature-Sliced Design](https://feature-sliced.design/) architecture in seconds.
4
+
5
+ ## Features
6
+
7
+ - **FSD Architecture** — Pre-configured layers: app, pages, widgets, features, entities, shared
8
+ - **Interactive CLI** — Guided setup with project name, template selection, and dependency installation
9
+ - **Multiple Templates** — Choose from available project templates (more coming soon)
10
+ - **Zero Config** — Start coding immediately with sensible defaults
11
+ - **TypeScript** — Full TypeScript support out of the box
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ npx create-fsd-architecture my-app
17
+ ```
18
+
19
+ Or with a specific package manager:
20
+
21
+ ```bash
22
+ npm create fsd-architecture my-app
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Interactive Mode
28
+
29
+ ```bash
30
+ npx create-fsd-architecture
31
+ ```
32
+
33
+ The CLI will guide you through:
34
+
35
+ 1. **Project name** — Name your project
36
+ 2. **Template selection** — Choose your framework
37
+ 3. **Install dependencies** — Optionally install packages
38
+ 4. **Start dev server** — Optionally launch the development server
39
+
40
+ ### With Arguments
41
+
42
+ ```bash
43
+ npx create-fsd-architecture my-app
44
+ ```
45
+
46
+ Pass the project name directly to skip the name prompt.
47
+
48
+ ## Available Templates
49
+
50
+ | Template | Status |
51
+ | --- | --- |
52
+ | React + Vite | Available |
53
+ | Next.js | Coming Soon |
54
+
55
+ ## Project Structure
56
+
57
+ Projects are scaffolded with the FSD architecture:
58
+
59
+ ```
60
+ src/
61
+ ├── app/ # App-level setup: providers, routing, styles
62
+ ├── pages/ # Full pages composed from widgets and features
63
+ ├── widgets/ # Large self-contained UI blocks
64
+ ├── features/ # User interactions and actions
65
+ ├── entities/ # Business entities and their representations
66
+ └── shared/ # Reusable utilities, UI kit, configs
67
+ ```
68
+
69
+ ## Roadmap
70
+
71
+ - [x] React + Vite template
72
+ - [ ] Next.js template
73
+ - [ ] Vue + Vite template
74
+ - [ ] Custom template support
75
+ - [ ] Git initialization option
76
+ - [ ] Package manager detection (npm, yarn, pnpm, bun)
77
+
78
+ ## Requirements
79
+
80
+ - Node.js 18 or later
81
+
82
+ ## License
83
+
84
+ ISC
package/bin/index.mjs CHANGED
@@ -3,58 +3,199 @@
3
3
  import degit from "degit";
4
4
  import prompts from "prompts";
5
5
  import chalk from "chalk";
6
+ import ora from "ora";
6
7
  import fs from "fs";
7
8
  import path from "path";
8
- import { execSync } from "child_process";
9
+ import { execSync, spawn } from "child_process";
9
10
 
10
- const repo = "https://github.com/ashrafmo-1/FSD";
11
+ const TEMPLATES = [
12
+ {
13
+ title: "React + Vite",
14
+ value: "react-vite",
15
+ description: "React with Vite and FSD architecture",
16
+ repo: "ashrafmo-1/FSD",
17
+ available: true,
18
+ },
19
+ {
20
+ title: "Next.js",
21
+ value: "nextjs",
22
+ description: "Next.js — Full-stack React framework with SSR, SSG, and App Router.",
23
+ repo: "ashrafmo-1/FSD-NEXTJS",
24
+ available: true,
25
+ },
26
+ ];
11
27
 
12
- const argName = process.argv[2];
13
-
14
- const response = argName
15
- ? { projectName: argName }
16
- : await prompts({
17
- type: "text",
18
- name: "projectName",
19
- message: "Project name?",
20
- initial: "my-fsd-app"
21
- });
28
+ function showBanner() {
29
+ const line = chalk.cyan("─".repeat(39));
30
+ console.log();
31
+ console.log(` ${chalk.cyan("╭")}${line}${chalk.cyan("╮")}`);
32
+ console.log(` ${chalk.cyan("│")}${" ".repeat(39)}${chalk.cyan("│")}`);
33
+ console.log(` ${chalk.cyan("│")}${" ".repeat(7)}${chalk.bold.white("create-fsd-architecture")}${" ".repeat(9)}${chalk.cyan("│")}`);
34
+ console.log(` ${chalk.cyan("│")}${" ".repeat(3)}${chalk.dim("Feature-Sliced Design Scaffolding")}${" ".repeat(3)}${chalk.cyan("│")}`);
35
+ console.log(` ${chalk.cyan("│")}${" ".repeat(39)}${chalk.cyan("│")}`);
36
+ console.log(` ${chalk.cyan("")}${line}${chalk.cyan("╯")}`);
37
+ console.log();
38
+ }
22
39
 
23
- const projectName = response.projectName;
40
+ function showNextSteps(projectName, depsInstalled) {
41
+ console.log();
42
+ console.log(chalk.bold.white(" Next steps:"));
43
+ console.log();
44
+ console.log(` ${chalk.cyan("$")} cd ${projectName}`);
45
+ if (!depsInstalled) {
46
+ console.log(` ${chalk.cyan("$")} npm install`);
47
+ }
48
+ console.log(` ${chalk.cyan("$")} npm run dev`);
49
+ console.log();
50
+ }
24
51
 
25
- if (!projectName) {
26
- console.log(chalk.red("Project name is required"));
27
- process.exit(1);
52
+ function handleCancel() {
53
+ console.log();
54
+ console.log(chalk.yellow(" Cancelled."));
55
+ console.log();
56
+ process.exit(0);
28
57
  }
29
58
 
30
- const targetDir = path.resolve(process.cwd(), projectName);
59
+ const onCancel = { onCancel: handleCancel };
31
60
 
32
- if (fs.existsSync(targetDir)) {
33
- console.log(chalk.red(`Folder "${projectName}" already exists`));
34
- process.exit(1);
35
- }
61
+ async function main() {
62
+ showBanner();
36
63
 
37
- console.log(chalk.cyan("Downloading FSD template..."));
64
+ const argName = process.argv[2];
38
65
 
39
- const emitter = degit(repo, {
40
- cache: false,
41
- force: true,
42
- verbose: true
43
- });
66
+ const { projectName } = argName
67
+ ? { projectName: argName }
68
+ : await prompts(
69
+ {
70
+ type: "text",
71
+ name: "projectName",
72
+ message: "Project name",
73
+ initial: "my-fsd-app",
74
+ },
75
+ onCancel
76
+ );
44
77
 
45
- await emitter.clone(targetDir);
78
+ if (!projectName) {
79
+ console.log(chalk.red(" Project name is required."));
80
+ process.exit(1);
81
+ }
46
82
 
47
- console.log(chalk.green("Template downloaded successfully."));
83
+ const targetDir = path.resolve(process.cwd(), projectName);
48
84
 
49
- console.log(chalk.cyan("Installing dependencies..."));
85
+ if (fs.existsSync(targetDir)) {
86
+ console.log(chalk.red(` Folder "${projectName}" already exists.`));
87
+ process.exit(1);
88
+ }
50
89
 
51
- execSync("npm install", {
52
- cwd: targetDir,
53
- stdio: "inherit"
54
- });
90
+ const { template } = await prompts(
91
+ {
92
+ type: "select",
93
+ name: "template",
94
+ message: "Select project type",
95
+ choices: TEMPLATES.map((t) => ({
96
+ title: t.available
97
+ ? t.title
98
+ : `${t.title} ${chalk.dim("(Coming Soon)")}`,
99
+ value: t.value,
100
+ })),
101
+ },
102
+ onCancel
103
+ );
104
+
105
+ const selected = TEMPLATES.find((t) => t.value === template);
106
+
107
+ if (!selected || !selected.available) {
108
+ console.log();
109
+ console.log(
110
+ chalk.yellow(` ${selected ? selected.title : "Template"} support is coming soon!`)
111
+ );
112
+ console.log(chalk.dim(" Stay tuned for updates."));
113
+ console.log();
114
+ process.exit(0);
115
+ }
116
+
117
+ console.log();
118
+
119
+ const spinner = ora({
120
+ text: "Downloading template...",
121
+ color: "cyan",
122
+ }).start();
123
+
124
+ try {
125
+ const emitter = degit(selected.repo, { cache: false, force: true });
126
+ await emitter.clone(targetDir);
127
+ spinner.succeed(chalk.green("Template downloaded."));
128
+ } catch (err) {
129
+ spinner.fail(chalk.red("Failed to download template."));
130
+ console.error(chalk.dim(` ${err.message}`));
131
+ process.exit(1);
132
+ }
55
133
 
56
- console.log(chalk.green("Project created successfully."));
57
- console.log(`
58
- cd ${projectName}
59
- npm run dev
60
- `);
134
+ const { installDeps } = await prompts(
135
+ {
136
+ type: "confirm",
137
+ name: "installDeps",
138
+ message: "Install dependencies now?",
139
+ initial: true,
140
+ },
141
+ onCancel
142
+ );
143
+
144
+ let depsInstalled = false;
145
+
146
+ if (installDeps) {
147
+ const installSpinner = ora({
148
+ text: "Installing dependencies...",
149
+ color: "cyan",
150
+ }).start();
151
+
152
+ try {
153
+ execSync("npm install", { cwd: targetDir, stdio: "pipe" });
154
+ installSpinner.succeed(chalk.green("Dependencies installed."));
155
+ depsInstalled = true;
156
+ } catch (err) {
157
+ installSpinner.fail(chalk.red("Failed to install dependencies."));
158
+ console.log(chalk.dim(" You can install them manually later."));
159
+ }
160
+ }
161
+
162
+ if (depsInstalled) {
163
+ const { startDev } = await prompts(
164
+ {
165
+ type: "confirm",
166
+ name: "startDev",
167
+ message: "Start development server now?",
168
+ initial: true,
169
+ },
170
+ onCancel
171
+ );
172
+
173
+ if (startDev) {
174
+ console.log();
175
+ console.log(chalk.cyan(" Starting development server..."));
176
+ console.log();
177
+
178
+ const child = spawn("npm", ["run", "dev"], {
179
+ cwd: targetDir,
180
+ stdio: "inherit",
181
+ shell: true,
182
+ });
183
+
184
+ child.on("error", (err) => {
185
+ console.log(chalk.red(` Failed to start dev server: ${err.message}`));
186
+ showNextSteps(projectName, true);
187
+ });
188
+
189
+ return;
190
+ }
191
+ }
192
+
193
+ console.log();
194
+ console.log(chalk.green.bold(" Project created successfully!"));
195
+ showNextSteps(projectName, depsInstalled);
196
+ }
197
+
198
+ main().catch((err) => {
199
+ console.error(chalk.red(` Error: ${err.message}`));
200
+ process.exit(1);
201
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-fsd-architecture",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -12,11 +12,17 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "chalk": "^5.3.0",
15
+ "create-fsd-architecture": "^1.0.1",
15
16
  "degit": "^2.8.4",
17
+ "ora": "^9.4.0",
16
18
  "prompts": "^2.4.2"
17
19
  },
20
+ "files": [
21
+ "bin",
22
+ "README.md"
23
+ ],
18
24
  "keywords": [],
19
25
  "author": "",
20
26
  "license": "ISC",
21
27
  "type": "commonjs"
22
- }
28
+ }