create-fsd-architecture 1.0.1 → 1.0.2

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 (52) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/README.md +84 -0
  3. package/ashraf/README.md +122 -0
  4. package/ashraf/bun.lock +1347 -0
  5. package/ashraf/components.json +23 -0
  6. package/ashraf/eslint.config.js +23 -0
  7. package/ashraf/index.html +13 -0
  8. package/ashraf/package-lock.json +9886 -0
  9. package/ashraf/package.json +43 -0
  10. package/ashraf/src/app/App.tsx +12 -0
  11. package/ashraf/src/app/providers/axios-interceptor.tsx +0 -0
  12. package/ashraf/src/app/providers.tsx +0 -0
  13. package/ashraf/src/app/routing/auth-routes.tsx +0 -0
  14. package/ashraf/src/app/routing/dashboard-routes.tsx +0 -0
  15. package/ashraf/src/app/routing/guards/auth-guard.tsx +0 -0
  16. package/ashraf/src/app/routing/guards/dashboard-guard.tsx +0 -0
  17. package/ashraf/src/app/styles/index.css +190 -0
  18. package/ashraf/src/assets/index.ts +0 -0
  19. package/ashraf/src/entities/products/api/get-product-by-id.ts +8 -0
  20. package/ashraf/src/entities/products/api/get-products.ts +8 -0
  21. package/ashraf/src/entities/products/index.ts +5 -0
  22. package/ashraf/src/entities/products/model/query-keys.ts +5 -0
  23. package/ashraf/src/entities/products/model/types.ts +18 -0
  24. package/ashraf/src/entities/products/ui/product-card.tsx +25 -0
  25. package/ashraf/src/features/products/create-product/api/create-product.ts +7 -0
  26. package/ashraf/src/features/products/create-product/index.ts +2 -0
  27. package/ashraf/src/features/products/create-product/model/create-product-schema.ts +11 -0
  28. package/ashraf/src/features/products/create-product/model/use-create-product.ts +15 -0
  29. package/ashraf/src/features/products/create-product/ui/create-product-form.tsx +85 -0
  30. package/ashraf/src/features/products/update-product/api/update-product.ts +12 -0
  31. package/ashraf/src/features/products/update-product/index.ts +2 -0
  32. package/ashraf/src/features/products/update-product/model/update-product.schema.ts +11 -0
  33. package/ashraf/src/features/products/update-product/model/use-update-product.ts +17 -0
  34. package/ashraf/src/features/products/update-product/ui/update-product-form.tsx +69 -0
  35. package/ashraf/src/main.tsx +10 -0
  36. package/ashraf/src/pages/products/all-products.tsx +23 -0
  37. package/ashraf/src/pages/products/create-product-page.tsx +10 -0
  38. package/ashraf/src/pages/products/update-product-page.tsx +24 -0
  39. package/ashraf/src/shared/config/env.ts +1 -0
  40. package/ashraf/src/shared/lib/utils.ts +6 -0
  41. package/ashraf/src/shared/types/types.d.ts +0 -0
  42. package/ashraf/src/shared/ui/input.tsx +21 -0
  43. package/ashraf/src/shared/ui/label.tsx +22 -0
  44. package/ashraf/src/widgets/dashboard-header.tsx +0 -0
  45. package/ashraf/src/widgets/index.ts +0 -0
  46. package/ashraf/src/widgets/sidebar.tsx +0 -0
  47. package/ashraf/tsconfig.app.json +32 -0
  48. package/ashraf/tsconfig.json +21 -0
  49. package/ashraf/tsconfig.node.json +26 -0
  50. package/ashraf/vite.config.ts +14 -0
  51. package/bin/index.mjs +180 -39
  52. package/package.json +3 -1
@@ -0,0 +1,21 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/shared/lib/utils"
4
+
5
+ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
6
+ return (
7
+ <input
8
+ type={type}
9
+ data-slot="input"
10
+ className={cn(
11
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
12
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
13
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
14
+ className
15
+ )}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ export { Input }
@@ -0,0 +1,22 @@
1
+ import * as React from "react"
2
+ import { Label as LabelPrimitive } from "radix-ui"
3
+
4
+ import { cn } from "@/shared/lib/utils"
5
+
6
+ function Label({
7
+ className,
8
+ ...props
9
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
10
+ return (
11
+ <LabelPrimitive.Root
12
+ data-slot="label"
13
+ className={cn(
14
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
15
+ className
16
+ )}
17
+ {...props}
18
+ />
19
+ )
20
+ }
21
+
22
+ export { Label }
File without changes
File without changes
File without changes
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "baseUrl": ".",
4
+ "paths": {
5
+ "@/*": ["./src/*"]
6
+ },
7
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
8
+ "target": "ES2022",
9
+ "useDefineForClassFields": true,
10
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
11
+ "module": "ESNext",
12
+ "types": ["vite/client"],
13
+ "skipLibCheck": true,
14
+
15
+ /* Bundler mode */
16
+ "moduleResolution": "bundler",
17
+ "allowImportingTsExtensions": true,
18
+ "verbatimModuleSyntax": true,
19
+ "moduleDetection": "force",
20
+ "noEmit": true,
21
+ "jsx": "react-jsx",
22
+
23
+ /* Linting */
24
+ "strict": true,
25
+ "noUnusedLocals": true,
26
+ "noUnusedParameters": true,
27
+ "erasableSyntaxOnly": true,
28
+ "noFallthroughCasesInSwitch": true,
29
+ "noUncheckedSideEffectImports": true
30
+ },
31
+ "include": ["src"]
32
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "strict": true,
3
+ "noUncheckedIndexedAccess": true,
4
+ "files": [],
5
+ "references": [
6
+ {
7
+ "path": "./tsconfig.app.json"
8
+ },
9
+ {
10
+ "path": "./tsconfig.node.json"
11
+ }
12
+ ],
13
+ "compilerOptions": {
14
+ "baseUrl": ".",
15
+ "paths": {
16
+ "@/*": [
17
+ "./src/*"
18
+ ]
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2023",
5
+ "lib": ["ES2023"],
6
+ "module": "ESNext",
7
+ "types": ["node"],
8
+ "skipLibCheck": true,
9
+
10
+ /* Bundler mode */
11
+ "moduleResolution": "bundler",
12
+ "allowImportingTsExtensions": true,
13
+ "verbatimModuleSyntax": true,
14
+ "moduleDetection": "force",
15
+ "noEmit": true,
16
+
17
+ /* Linting */
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "erasableSyntaxOnly": true,
22
+ "noFallthroughCasesInSwitch": true,
23
+ "noUncheckedSideEffectImports": true
24
+ },
25
+ "include": ["vite.config.ts"]
26
+ }
@@ -0,0 +1,14 @@
1
+ import path from "path";
2
+ import { defineConfig } from 'vite';
3
+ import react from '@vitejs/plugin-react-swc';
4
+ import tailwindcss from '@tailwindcss/vite';
5
+
6
+ // https://vite.dev/config/
7
+ export default defineConfig({
8
+ plugins: [react(), tailwindcss()],
9
+ resolve: {
10
+ alias: {
11
+ "@": path.resolve(__dirname, "./src"),
12
+ },
13
+ },
14
+ })
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: "Coming Soon",
23
+ repo: null,
24
+ available: false,
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.2",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -12,7 +12,9 @@
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
  },
18
20
  "keywords": [],