@abuhannaa/create-apptemplate 1.0.6 → 1.0.8

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
@@ -1,164 +1,272 @@
1
1
  # @abuhannaa/create-apptemplate
2
2
 
3
- Create fullstack applications with .NET/Spring/NestJS backends and Vue (Vuetify/PrimeVue) frontends.
3
+ A CLI tool to scaffold production-ready fullstack applications with your choice of backend and frontend frameworks.
4
4
 
5
5
  ## Quick Start
6
6
 
7
7
  ```bash
8
- # Using npm
9
8
  npm create @abuhannaa/apptemplate@latest
9
+ ```
10
10
 
11
- # Using npx
12
- npx @abuhannaa/create-apptemplate my-app
11
+ That's it! The interactive wizard will guide you through the setup.
13
12
 
14
- # Using pnpm
15
- pnpm create @abuhannaa/apptemplate
13
+ ## Stack Options
16
14
 
17
- # Using yarn
18
- yarn create @abuhannaa/apptemplate
15
+ | Backend | Frontend | UI Libraries |
16
+ |---------|----------|--------------|
17
+ | .NET 8 | Vue 3 | Vuetify (Material Design 3) |
18
+ | Spring Boot 3 | React 18 | PrimeVue |
19
+ | NestJS | | MUI (Material UI) |
20
+ | | | PrimeReact |
19
21
 
20
- # Using bun
21
- bun create @abuhannaa/apptemplate
22
- ```
22
+ Mix and match any backend with any frontend to create your ideal stack.
23
23
 
24
- ## Features
24
+ ## Installation Methods
25
25
 
26
- - **Multiple Backend Options**
27
- - .NET 8 (Clean Architecture, CQRS, Entity Framework)
28
- - Spring Boot 3 (Clean Architecture, Java 21)
29
- - NestJS (Clean Architecture, TypeScript)
26
+ ```bash
27
+ # npm
28
+ npm create @abuhannaa/apptemplate@latest
30
29
 
31
- - **Multiple Frontend Options**
32
- - Vuetify (Material Design 3)
33
- - PrimeVue (Aura Theme)
30
+ # npx
31
+ npx @abuhannaa/create-apptemplate my-app
34
32
 
35
- - **Project Types**
36
- - Fullstack (Backend + Frontend + Docker)
37
- - Backend only (API service)
38
- - Frontend only (SPA)
33
+ # pnpm
34
+ pnpm create @abuhannaa/apptemplate
39
35
 
40
- - **Production Ready**
41
- - Docker & Docker Compose setup
42
- - CI/CD with GitHub Actions
43
- - Environment configuration
44
- - JWT Authentication
45
- - Real-time notifications (SignalR/WebSocket)
36
+ # yarn
37
+ yarn create @abuhannaa/apptemplate
38
+
39
+ # bun
40
+ bun create @abuhannaa/apptemplate
41
+ ```
46
42
 
47
43
  ## Usage
48
44
 
49
45
  ### Interactive Mode (Recommended)
50
46
 
51
- Simply run the command without arguments:
52
-
53
47
  ```bash
54
48
  npm create @abuhannaa/apptemplate@latest
55
49
  ```
56
50
 
57
- The wizard will guide you through:
51
+ The wizard will prompt you for:
58
52
 
59
- 1. **Project location** - Where to create your project
53
+ 1. **Project location** - Directory name for your project
60
54
  2. **Project type** - Fullstack, Backend only, or Frontend only
61
55
  3. **Backend framework** - .NET 8, Spring Boot 3, or NestJS
62
- 4. **UI library** - Vuetify or PrimeVue
63
- 5. **Project name** - For namespaces (e.g., MyCompany.MyApp)
64
- 6. **Install dependencies** - Whether to install now
56
+ 4. **Frontend framework** - Vue 3 or React 18
57
+ 5. **UI library** - Vuetify, PrimeVue, MUI, or PrimeReact
58
+ 6. **Project name** - Namespace for .NET/Spring (e.g., `MyCompany.MyApp`)
59
+ 7. **Install dependencies** - Run install automatically
65
60
 
66
- ### Non-Interactive Mode
61
+ ### Command Line Mode
67
62
 
68
- Specify all options via command line:
63
+ Skip the prompts by providing options directly:
69
64
 
70
65
  ```bash
71
- # Fullstack project with .NET backend and Vuetify frontend
72
- npx @abuhannaa/create-apptemplate my-app -b dotnet -u vuetify -n "MyCompany.MyApp" -i
66
+ # Fullstack with .NET + Vuetify
67
+ npm create @abuhannaa/apptemplate@latest my-app -b dotnet -u vuetify -n "MyCompany.MyApp" -i
73
68
 
74
- # Backend-only project with Spring Boot
75
- npx @abuhannaa/create-apptemplate my-api -t backend -b spring -n "MyCompany.MyApi"
69
+ # Fullstack with Spring Boot + React MUI
70
+ npm create @abuhannaa/apptemplate@latest my-app -b spring -f react -u mui -n "com.mycompany.myapp" -i
76
71
 
77
- # Frontend-only project with PrimeVue
78
- npx @abuhannaa/create-apptemplate my-spa -t frontend -u primevue
72
+ # Fullstack with NestJS + PrimeVue
73
+ npm create @abuhannaa/apptemplate@latest my-app -b nestjs -u primevue -i
74
+
75
+ # Backend only (NestJS)
76
+ npm create @abuhannaa/apptemplate@latest my-api -t backend -b nestjs -i
77
+
78
+ # Frontend only (React + PrimeReact)
79
+ npm create @abuhannaa/apptemplate@latest my-spa -t frontend -f react -u primereact -i
80
+
81
+ # Place files in root (no subfolder)
82
+ npm create @abuhannaa/apptemplate@latest my-api -t backend -b nestjs --root
79
83
  ```
80
84
 
81
- ## Options
85
+ ## CLI Options
86
+
87
+ | Option | Alias | Description | Values | Default |
88
+ |--------|-------|-------------|--------|---------|
89
+ | `--type` | `-t` | Project type | `fullstack`, `backend`, `frontend` | `fullstack` |
90
+ | `--backend` | `-b` | Backend framework | `dotnet`, `spring`, `nestjs` | - |
91
+ | `--framework` | `-f` | Frontend framework | `vue`, `react` | `vue` |
92
+ | `--ui` | `-u` | UI library | `vuetify`, `primevue`, `mui`, `primereact` | Based on framework |
93
+ | `--name` | `-n` | Project namespace | `Company.Project` format | - |
94
+ | `--root` | `-r` | Place files in project root | - | `false` |
95
+ | `--install` | `-i` | Install dependencies | - | `false` |
96
+ | `--help` | `-h` | Show help | - | - |
97
+ | `--version` | `-v` | Show version | - | - |
82
98
 
83
- | Option | Alias | Description | Values |
84
- |--------|-------|-------------|--------|
85
- | `--type` | `-t` | Project type | `fullstack`, `backend`, `frontend` |
86
- | `--backend` | `-b` | Backend framework | `dotnet`, `spring`, `nestjs` |
87
- | `--ui` | `-u` | UI library | `vuetify`, `primevue` |
88
- | `--name` | `-n` | Project name (namespaces) | `Company.Project` format |
89
- | `--install` | `-i` | Install dependencies | - |
90
- | `--help` | `-h` | Show help | - |
91
- | `--version` | `-v` | Show version | - |
99
+ ### UI Library Compatibility
92
100
 
93
- ## After Creation
101
+ | Frontend | Compatible UI Libraries |
102
+ |----------|------------------------|
103
+ | Vue | `vuetify`, `primevue` |
104
+ | React | `mui`, `primereact` |
105
+
106
+ ## After Project Creation
107
+
108
+ ### Using Docker (Recommended)
94
109
 
95
110
  ```bash
96
- # Navigate to project
97
111
  cd my-app
98
-
99
- # Setup environment
100
112
  cp .env.example .env
101
-
102
- # Start with Docker (recommended)
103
113
  docker compose up -d --build
114
+ ```
104
115
 
105
- # Or run manually:
106
- # Backend (.NET)
107
- cd backend-dotnet/src/Presentation/App.Template.WebAPI && dotnet run
116
+ ### Running Manually
117
+
118
+ **Backend:**
119
+ ```bash
120
+ # .NET
121
+ cd backend/src/Presentation/*.WebAPI && dotnet run
122
+
123
+ # Spring Boot
124
+ cd backend && ./mvnw spring-boot:run
125
+
126
+ # NestJS
127
+ cd backend && npm run start:dev
128
+ ```
108
129
 
109
- # Frontend
110
- cd frontend-vuetify && npm run dev
130
+ **Frontend:**
131
+ ```bash
132
+ cd frontend && npm run dev
111
133
  ```
112
134
 
113
135
  ### Access Points
114
136
 
115
- - **Frontend**: http://localhost
116
- - **Backend API**: http://localhost:5100
117
- - **Swagger UI**: http://localhost:5100/swagger
137
+ | Service | URL |
138
+ |---------|-----|
139
+ | Frontend | http://localhost:3000 (dev) / http://localhost (Docker) |
140
+ | Backend API | http://localhost:5100 |
141
+ | Swagger UI | http://localhost:5100/swagger |
118
142
 
119
- ### Default Login
143
+ ### Default Credentials
120
144
 
121
- - **Username**: `admin`
122
- - **Password**: `Admin@123`
145
+ ```
146
+ Username: admin
147
+ Password: Admin@123
148
+ ```
123
149
 
124
150
  ## Project Structure
125
151
 
152
+ ### Fullstack Project
153
+
126
154
  ```
127
155
  my-app/
128
- ├── backend-dotnet/ # .NET 8 API (if selected)
156
+ ├── backend/ # Backend API
129
157
  │ ├── src/
130
158
  │ │ ├── Core/ # Domain & Application layers
131
- │ │ ├── Infrastructure/ # EF Core, Services
132
- │ │ └── Presentation/ # Controllers, Middleware
159
+ │ │ ├── Infrastructure/ # Database, External services
160
+ │ │ └── Presentation/ # Controllers, API endpoints
133
161
  │ └── tests/
134
- ├── frontend-vuetify/ # Vue 3 + Vuetify (if selected)
162
+ ├── frontend/ # Frontend SPA
135
163
  │ ├── src/
136
- │ │ ├── components/ # Vue components
137
- │ │ ├── pages/ # File-based routing
138
- │ │ ├── stores/ # Pinia state
164
+ │ │ ├── components/ # Reusable components
165
+ │ │ ├── pages/ # Route pages
166
+ │ │ ├── stores/ # State management
139
167
  │ │ └── services/ # API services
140
168
  │ └── ...
141
169
  ├── docker/ # Docker configurations
142
- ├── scripts/ # Utility scripts
143
- ├── Dockerfile # Unified container build
144
- ├── docker-compose.yml # Development setup
170
+ ├── docker-compose.yml # Development environment
145
171
  └── .env.example # Environment template
146
172
  ```
147
173
 
174
+ ### Backend Only (`-t backend`)
175
+
176
+ ```
177
+ my-api/
178
+ ├── backend/ # Or root with --root flag
179
+ │ ├── src/
180
+ │ └── tests/
181
+ └── ...
182
+ ```
183
+
184
+ ### Frontend Only (`-t frontend`)
185
+
186
+ ```
187
+ my-spa/
188
+ ├── frontend/ # Or root with --root flag
189
+ │ ├── src/
190
+ │ └── ...
191
+ └── ...
192
+ ```
193
+
194
+ ## Features Included
195
+
196
+ ### Backend Features
197
+
198
+ - **Clean Architecture** - Domain, Application, Infrastructure, Presentation layers
199
+ - **Authentication** - JWT with refresh token rotation
200
+ - **Authorization** - Role-based access control
201
+ - **Database** - PostgreSQL with migrations
202
+ - **Real-time** - SignalR (.NET) / WebSocket notifications
203
+ - **File Upload** - Multi-file upload with validation
204
+ - **Audit Logging** - Track all data changes
205
+ - **Health Checks** - Liveness and readiness endpoints
206
+ - **API Documentation** - Swagger/OpenAPI with auth support
207
+ - **Data Export** - CSV, Excel, PDF export
208
+ - **Pagination** - Server-side pagination with sorting and filtering
209
+
210
+ ### Frontend Features
211
+
212
+ - **Authentication** - Login, logout, token refresh
213
+ - **Responsive Layout** - Sidebar, header, breadcrumbs
214
+ - **Dark Mode** - Theme switching support
215
+ - **Data Tables** - Server-side pagination, sorting, filtering
216
+ - **Form Validation** - Client-side validation
217
+ - **Toast Notifications** - Success, error, info messages
218
+ - **Confirmation Dialogs** - For destructive actions
219
+ - **File Management** - Upload, download, preview
220
+ - **Internationalization** - i18n ready
221
+ - **State Management** - Pinia (Vue) / Zustand (React)
222
+
223
+ ### DevOps Features
224
+
225
+ - **Docker** - Multi-stage builds, docker-compose
226
+ - **CI/CD** - GitHub Actions workflows
227
+ - **Environment Config** - Validated environment variables
228
+ - **Scripts** - Project renaming, database setup
229
+
148
230
  ## Requirements
149
231
 
150
- - **Node.js** 18.0.0 or higher
151
- - **Docker** (recommended for running the app)
152
- - **.NET 8 SDK** (for .NET backend development)
153
- - **Java 21** (for Spring backend development)
232
+ | Tool | Version | Required For |
233
+ |------|---------|--------------|
234
+ | Node.js | 18+ | All projects |
235
+ | Docker | Latest | Running with containers |
236
+ | .NET SDK | 8.0+ | .NET backend development |
237
+ | Java | 21+ | Spring Boot development |
238
+
239
+ ## Example Stacks
240
+
241
+ ### Enterprise .NET Stack
242
+ ```bash
243
+ npm create @abuhannaa/apptemplate@latest enterprise-app \
244
+ -b dotnet -f react -u mui -n "Contoso.Enterprise" -i
245
+ ```
246
+
247
+ ### Startup Vue Stack
248
+ ```bash
249
+ npm create @abuhannaa/apptemplate@latest startup-app \
250
+ -b nestjs -f vue -u primevue -i
251
+ ```
154
252
 
155
- ## Documentation
253
+ ### Microservice Backend
254
+ ```bash
255
+ npm create @abuhannaa/apptemplate@latest user-service \
256
+ -t backend -b spring -n "com.mycompany.userservice" --root -i
257
+ ```
258
+
259
+ ### Admin Dashboard
260
+ ```bash
261
+ npm create @abuhannaa/apptemplate@latest admin-dashboard \
262
+ -t frontend -f react -u primereact -i
263
+ ```
156
264
 
157
- For detailed documentation, see:
265
+ ## Links
158
266
 
159
- - [Backend Guide](https://github.com/abuhanna/app-template/blob/main/backend-dotnet/README.md)
160
- - [Frontend Guide](https://github.com/abuhanna/app-template/blob/main/frontend-vuetify/README.md)
161
- - [Deployment Guide](https://github.com/abuhanna/app-template/blob/main/DEPLOYMENT.md)
267
+ - [GitHub Repository](https://github.com/abuhanna/app-template)
268
+ - [Report Issues](https://github.com/abuhanna/app-template/issues)
269
+ - [NPM Package](https://www.npmjs.com/package/@abuhannaa/create-apptemplate)
162
270
 
163
271
  ## License
164
272
 
package/dist/index.js CHANGED
@@ -7,7 +7,8 @@ import pc3 from "picocolors";
7
7
  // src/cli.ts
8
8
  var validProjectTypes = ["fullstack", "backend", "frontend"];
9
9
  var validBackends = ["dotnet", "spring", "nestjs"];
10
- var validUILibraries = ["vuetify", "primevue"];
10
+ var validFrontendFrameworks = ["vue", "react"];
11
+ var validUILibraries = ["vuetify", "primevue", "primereact", "mui"];
11
12
  function parseArgs() {
12
13
  const args = process.argv.slice(2);
13
14
  const result = {};
@@ -54,6 +55,16 @@ function parseArgs() {
54
55
  i++;
55
56
  continue;
56
57
  }
58
+ if (arg === "-f" || arg === "--framework") {
59
+ const value = args[++i];
60
+ if (isValidFrontendFramework(value)) {
61
+ result.framework = value;
62
+ } else {
63
+ console.warn(`Warning: Invalid frontend framework "${value}". Valid options: ${validFrontendFrameworks.join(", ")}`);
64
+ }
65
+ i++;
66
+ continue;
67
+ }
57
68
  if (arg === "-u" || arg === "--ui") {
58
69
  const value = args[++i];
59
70
  if (isValidUI(value)) {
@@ -87,6 +98,9 @@ function isValidProjectType(value) {
87
98
  function isValidBackend(value) {
88
99
  return value !== void 0 && validBackends.includes(value);
89
100
  }
101
+ function isValidFrontendFramework(value) {
102
+ return value !== void 0 && validFrontendFrameworks.includes(value);
103
+ }
90
104
  function isValidUI(value) {
91
105
  return value !== void 0 && validUILibraries.includes(value);
92
106
  }
@@ -170,24 +184,57 @@ async function runInteractivePrompts(cliArgs) {
170
184
  if (p.isCancel(result)) return result;
171
185
  backend = result;
172
186
  }
173
- let ui = cliArgs.ui || "vuetify";
174
- if (projectType !== "backend" && !cliArgs.ui) {
187
+ let frontendFramework = cliArgs.framework || "vue";
188
+ if (projectType !== "backend" && !cliArgs.framework) {
175
189
  const result = await p.select({
176
- message: "Which UI library would you like to use?",
190
+ message: "Which frontend framework would you like to use?",
177
191
  options: [
178
192
  {
179
- value: "vuetify",
180
- label: "Vuetify",
181
- hint: "Material Design 3, 80+ components"
193
+ value: "vue",
194
+ label: "Vue 3",
195
+ hint: "Composition API, Pinia, File-based routing"
182
196
  },
183
197
  {
184
- value: "primevue",
185
- label: "PrimeVue",
186
- hint: "Aura theme, 90+ components"
198
+ value: "react",
199
+ label: "React 18",
200
+ hint: "Zustand, React Router v6, TypeScript"
187
201
  }
188
202
  ]
189
203
  });
190
204
  if (p.isCancel(result)) return result;
205
+ frontendFramework = result;
206
+ }
207
+ let ui = cliArgs.ui || (frontendFramework === "vue" ? "vuetify" : "mui");
208
+ if (projectType !== "backend" && !cliArgs.ui) {
209
+ const vueOptions = [
210
+ {
211
+ value: "vuetify",
212
+ label: "Vuetify",
213
+ hint: "Material Design 3, 80+ components"
214
+ },
215
+ {
216
+ value: "primevue",
217
+ label: "PrimeVue",
218
+ hint: "Aura theme, 90+ components"
219
+ }
220
+ ];
221
+ const reactOptions = [
222
+ {
223
+ value: "mui",
224
+ label: "MUI (Material UI)",
225
+ hint: "Material Design, most popular React UI library"
226
+ },
227
+ {
228
+ value: "primereact",
229
+ label: "PrimeReact",
230
+ hint: "Enterprise-grade, 90+ components"
231
+ }
232
+ ];
233
+ const result = await p.select({
234
+ message: "Which UI library would you like to use?",
235
+ options: frontendFramework === "vue" ? vueOptions : reactOptions
236
+ });
237
+ if (p.isCancel(result)) return result;
191
238
  ui = result;
192
239
  }
193
240
  let projectName = cliArgs.projectName;
@@ -238,6 +285,7 @@ async function runInteractivePrompts(cliArgs) {
238
285
  summaryLines.push(`${pc.cyan("Backend:")} ${getBackendLabel(backend)}`);
239
286
  }
240
287
  if (projectType !== "backend") {
288
+ summaryLines.push(`${pc.cyan("Frontend:")} ${getFrontendLabel(frontendFramework)}`);
241
289
  summaryLines.push(`${pc.cyan("UI Library:")} ${getUILabel(ui)}`);
242
290
  }
243
291
  if (needsNamespace && projectName) {
@@ -259,6 +307,7 @@ async function runInteractivePrompts(cliArgs) {
259
307
  projectPath,
260
308
  projectType,
261
309
  backend,
310
+ frontendFramework,
262
311
  ui,
263
312
  projectName,
264
313
  installDeps,
@@ -276,10 +325,19 @@ function getBackendLabel(backend) {
276
325
  };
277
326
  return labels[backend];
278
327
  }
328
+ function getFrontendLabel(framework) {
329
+ const labels = {
330
+ vue: "Vue 3",
331
+ react: "React 18"
332
+ };
333
+ return labels[framework];
334
+ }
279
335
  function getUILabel(ui) {
280
336
  const labels = {
281
337
  vuetify: "Vuetify (Material Design)",
282
- primevue: "PrimeVue (Aura Theme)"
338
+ primevue: "PrimeVue (Aura Theme)",
339
+ mui: "MUI (Material UI)",
340
+ primereact: "PrimeReact"
283
341
  };
284
342
  return labels[ui];
285
343
  }
@@ -307,43 +365,8 @@ async function copyRootFiles(repo, destPath, config) {
307
365
  const commonFiles = [
308
366
  ".env.example",
309
367
  ".gitignore",
310
- "README.md",
311
368
  "CLAUDE.md"
312
369
  ];
313
- const fullstackFiles = [
314
- "Dockerfile",
315
- "docker-compose.yml",
316
- "docker-compose.staging.yml",
317
- "docker-compose.production.yml",
318
- "Makefile"
319
- ];
320
- const backendOnlyFiles = [
321
- "docker/Dockerfile.backend",
322
- "docker-compose.backend.yml"
323
- ];
324
- const frontendOnlyFiles = [
325
- "docker/Dockerfile.frontend",
326
- "docker/nginx/frontend-only.conf",
327
- "docker-compose.frontend.yml"
328
- ];
329
- let filesToDownload = [...commonFiles];
330
- switch (config.projectType) {
331
- case "fullstack":
332
- filesToDownload = [...filesToDownload, ...fullstackFiles];
333
- break;
334
- case "backend":
335
- filesToDownload = [...filesToDownload, ...backendOnlyFiles];
336
- break;
337
- case "frontend":
338
- filesToDownload = [...filesToDownload, ...frontendOnlyFiles];
339
- break;
340
- }
341
- const dockerFolder = "docker";
342
- const dockerDest = path2.join(destPath, dockerFolder);
343
- try {
344
- await downloadTemplate(repo, dockerFolder, dockerDest);
345
- } catch {
346
- }
347
370
  const tempDir = path2.join(destPath, ".temp-download");
348
371
  try {
349
372
  const emitter = degit(repo, {
@@ -352,16 +375,28 @@ async function copyRootFiles(repo, destPath, config) {
352
375
  verbose: false
353
376
  });
354
377
  await emitter.clone(tempDir);
355
- for (const file of filesToDownload) {
356
- const srcFile = path2.join(tempDir, file);
357
- const destFile = path2.join(destPath, file);
358
- if (fs2.existsSync(srcFile)) {
359
- const parentDir = path2.dirname(destFile);
360
- if (!fs2.existsSync(parentDir)) {
361
- fs2.mkdirSync(parentDir, { recursive: true });
362
- }
363
- fs2.copyFileSync(srcFile, destFile);
364
- }
378
+ for (const file of commonFiles) {
379
+ copyFileFromTemp(tempDir, file, destPath, file);
380
+ }
381
+ if (config.projectType === "fullstack") {
382
+ const readmeTemplate = `docker/templates/root/README.fullstack.${config.backend}.md`;
383
+ copyFileFromTemp(tempDir, readmeTemplate, destPath, "README.md");
384
+ } else if (!config.placeInRoot) {
385
+ const readmeTemplate = `docker/templates/root/README.multirepo.md`;
386
+ copyFileFromTemp(tempDir, readmeTemplate, destPath, "README.md");
387
+ }
388
+ if (config.projectType === "fullstack") {
389
+ copyDirectoryFromTemp(tempDir, "docker/nginx", path2.join(destPath, "docker/nginx"));
390
+ copyDirectoryFromTemp(tempDir, "docker/supervisor", path2.join(destPath, "docker/supervisor"));
391
+ const dockerfileTemplate = `docker/templates/root/Dockerfile.${config.backend}`;
392
+ copyFileFromTemp(tempDir, dockerfileTemplate, destPath, "Dockerfile");
393
+ const composeTemplate = `docker/templates/root/docker-compose.${config.backend}.yml`;
394
+ copyFileFromTemp(tempDir, composeTemplate, destPath, "docker-compose.yml");
395
+ const supervisorTemplate = `docker/templates/root/supervisord.${config.backend}.conf`;
396
+ copyFileFromTemp(tempDir, supervisorTemplate, destPath, "docker/supervisor/supervisord.conf");
397
+ copyFileFromTemp(tempDir, "Makefile", destPath, "Makefile");
398
+ copyFileFromTemp(tempDir, "docker-compose.staging.yml", destPath, "docker-compose.staging.yml");
399
+ copyFileFromTemp(tempDir, "docker-compose.production.yml", destPath, "docker-compose.production.yml");
365
400
  }
366
401
  } finally {
367
402
  if (fs2.existsSync(tempDir)) {
@@ -369,6 +404,26 @@ async function copyRootFiles(repo, destPath, config) {
369
404
  }
370
405
  }
371
406
  }
407
+ function copyFileFromTemp(tempDir, srcRelative, destBase, destRelative) {
408
+ const srcPath = path2.join(tempDir, srcRelative);
409
+ const destPath = path2.join(destBase, destRelative);
410
+ if (fs2.existsSync(srcPath)) {
411
+ const parentDir = path2.dirname(destPath);
412
+ if (!fs2.existsSync(parentDir)) {
413
+ fs2.mkdirSync(parentDir, { recursive: true });
414
+ }
415
+ fs2.copyFileSync(srcPath, destPath);
416
+ }
417
+ }
418
+ function copyDirectoryFromTemp(tempDir, srcRelative, destPath) {
419
+ const srcPath = path2.join(tempDir, srcRelative);
420
+ if (fs2.existsSync(srcPath)) {
421
+ if (!fs2.existsSync(destPath)) {
422
+ fs2.mkdirSync(destPath, { recursive: true });
423
+ }
424
+ fs2.cpSync(srcPath, destPath, { recursive: true });
425
+ }
426
+ }
372
427
 
373
428
  // src/utils/rename.ts
374
429
  import path3 from "path";
@@ -686,10 +741,33 @@ async function generateProject(config) {
686
741
  }
687
742
  }
688
743
  await setupEnvironmentFiles(absolutePath, config);
744
+ if (config.projectType === "fullstack") {
745
+ spinner2.start("Cleaning up Docker configuration...");
746
+ try {
747
+ cleanupFullstackDockerFiles(absolutePath);
748
+ spinner2.stop("Docker configuration cleaned up");
749
+ } catch {
750
+ spinner2.stop("Docker cleanup skipped");
751
+ }
752
+ }
689
753
  if (config.projectType !== "frontend" && config.backend === "dotnet") {
690
754
  await createAppSettingsFromExample(absolutePath, config);
691
755
  }
692
756
  }
757
+ function cleanupFullstackDockerFiles(projectPath) {
758
+ const filesToDelete = [
759
+ "backend/Dockerfile",
760
+ "backend/docker-compose.yml",
761
+ "frontend/Dockerfile",
762
+ "frontend/docker-compose.yml"
763
+ ];
764
+ for (const file of filesToDelete) {
765
+ const filePath = path5.join(projectPath, file);
766
+ if (fs5.existsSync(filePath)) {
767
+ fs5.rmSync(filePath);
768
+ }
769
+ }
770
+ }
693
771
  async function setupEnvironmentFiles(projectPath, config) {
694
772
  if (config.projectType !== "backend") {
695
773
  let frontendDir;
@@ -780,7 +858,7 @@ async function updateFolderReferences(projectPath, config) {
780
858
  content = content.replace(/backend-dotnet/g, backendReplace).replace(/backend-spring/g, backendReplace).replace(/backend-nestjs/g, backendReplace);
781
859
  }
782
860
  if (config.projectType !== "backend") {
783
- content = content.replace(/frontend-vuetify/g, frontendReplace).replace(/frontend-primevue/g, frontendReplace);
861
+ content = content.replace(/frontend-vuetify/g, frontendReplace).replace(/frontend-primevue/g, frontendReplace).replace(/frontend-primereact/g, frontendReplace).replace(/frontend-mui/g, frontendReplace);
784
862
  }
785
863
  fs5.writeFileSync(filePath, content);
786
864
  }
@@ -802,7 +880,7 @@ function updateDockerFolderFiles(dir, config, backendReplace, frontendReplace) {
802
880
  content = content.replace(/backend-dotnet/g, backendReplace).replace(/backend-spring/g, backendReplace).replace(/backend-nestjs/g, backendReplace);
803
881
  }
804
882
  if (config.projectType !== "backend") {
805
- content = content.replace(/frontend-vuetify/g, frontendReplace).replace(/frontend-primevue/g, frontendReplace);
883
+ content = content.replace(/frontend-vuetify/g, frontendReplace).replace(/frontend-primevue/g, frontendReplace).replace(/frontend-primereact/g, frontendReplace).replace(/frontend-mui/g, frontendReplace);
806
884
  }
807
885
  fs5.writeFileSync(fullPath, content);
808
886
  }
@@ -828,11 +906,13 @@ async function main() {
828
906
  const backend = cliArgs.backend || "dotnet";
829
907
  const needsNamespace = projectType !== "frontend" && (backend === "dotnet" || backend === "spring");
830
908
  if (cliArgs.projectPath && cliArgs.backend && (!needsNamespace || cliArgs.projectName)) {
909
+ const frontendFramework = cliArgs.framework || "vue";
831
910
  config = {
832
911
  projectPath: cliArgs.projectPath,
833
912
  projectType,
834
913
  backend,
835
- ui: cliArgs.ui || "vuetify",
914
+ frontendFramework,
915
+ ui: cliArgs.ui || (frontendFramework === "vue" ? "vuetify" : "mui"),
836
916
  projectName: cliArgs.projectName,
837
917
  installDeps: cliArgs.install || false,
838
918
  placeInRoot: cliArgs.root || false
@@ -866,7 +946,8 @@ ${pc3.bold("Usage:")}
866
946
  ${pc3.bold("Options:")}
867
947
  ${pc3.yellow("-t, --type")} Project type: fullstack, backend, frontend ${pc3.gray("(default: fullstack)")}
868
948
  ${pc3.yellow("-b, --backend")} Backend framework: dotnet, spring, nestjs
869
- ${pc3.yellow("-u, --ui")} UI library: vuetify, primevue ${pc3.gray("(default: vuetify)")}
949
+ ${pc3.yellow("-f, --framework")} Frontend framework: vue, react ${pc3.gray("(default: vue)")}
950
+ ${pc3.yellow("-u, --ui")} UI library: vuetify, primevue (Vue) | mui, primereact (React)
870
951
  ${pc3.yellow("-n, --name")} Project namespace (Company.Project format, .NET/Spring only)
871
952
  ${pc3.yellow("-r, --root")} Place files in project root ${pc3.gray("(backend/frontend-only)")}
872
953
  ${pc3.yellow("-i, --install")} Install dependencies after creation
@@ -886,6 +967,9 @@ ${pc3.bold("Examples:")}
886
967
  ${pc3.gray("# Create frontend-only project with PrimeVue")}
887
968
  npm create apptemplate@latest my-spa -t frontend -u primevue
888
969
 
970
+ ${pc3.gray("# Create fullstack project with React + MUI")}
971
+ npm create apptemplate@latest my-app -b dotnet -f react -u mui -n "MyCompany.MyApp"
972
+
889
973
  ${pc3.gray("# Create backend in project root (no subfolder)")}
890
974
  npm create apptemplate@latest my-api -t backend -b nestjs --root
891
975
  `);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/prompts.ts","../src/generator.ts","../src/utils/download.ts","../src/utils/rename.ts","../src/utils/package-manager.ts"],"sourcesContent":["import { intro, outro, isCancel } from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport { parseArgs } from './cli.js';\r\nimport { runInteractivePrompts } from './prompts.js';\r\nimport { generateProject } from './generator.js';\r\nimport type { ProjectConfig } from './types.js';\r\n\r\nasync function main(): Promise<void> {\r\n console.log();\r\n intro(pc.bgCyan(pc.black(' Create AppTemplate ')));\r\n\r\n try {\r\n // Parse CLI arguments\r\n const cliArgs = parseArgs();\r\n\r\n // Show help if requested\r\n if (cliArgs.help) {\r\n showHelp();\r\n process.exit(0);\r\n }\r\n\r\n // Show version if requested\r\n if (cliArgs.version) {\r\n console.log('create-apptemplate v1.0.0');\r\n process.exit(0);\r\n }\r\n\r\n // Get project configuration (interactive or from CLI args)\r\n let config: ProjectConfig;\r\n\r\n // Non-interactive mode - check if we have enough options\r\n const projectType = cliArgs.type || 'fullstack';\r\n const backend = cliArgs.backend || 'dotnet';\r\n const needsNamespace = projectType !== 'frontend' && (backend === 'dotnet' || backend === 'spring');\r\n\r\n if (cliArgs.projectPath && cliArgs.backend && (!needsNamespace || cliArgs.projectName)) {\r\n // Non-interactive mode - all required options provided\r\n config = {\r\n projectPath: cliArgs.projectPath,\r\n projectType,\r\n backend,\r\n ui: cliArgs.ui || 'vuetify',\r\n projectName: cliArgs.projectName,\r\n installDeps: cliArgs.install || false,\r\n placeInRoot: cliArgs.root || false,\r\n };\r\n } else {\r\n // Interactive mode\r\n const result = await runInteractivePrompts(cliArgs);\r\n if (isCancel(result)) {\r\n outro(pc.yellow('Operation cancelled'));\r\n process.exit(0);\r\n }\r\n config = result;\r\n }\r\n\r\n // Generate the project\r\n await generateProject(config);\r\n\r\n // Success message\r\n console.log();\r\n outro(pc.green('✓ Done! Your project is ready.'));\r\n\r\n // Show dynamic next steps based on project type\r\n showNextSteps(config);\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n console.error(pc.red(`Error: ${error.message}`));\r\n } else {\r\n console.error(pc.red('An unexpected error occurred'));\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n\r\nfunction showHelp(): void {\r\n console.log(`\r\n${pc.bold('Usage:')}\r\n ${pc.cyan('npm create apptemplate@latest')} ${pc.gray('[project-directory]')} ${pc.gray('[options]')}\r\n\r\n${pc.bold('Options:')}\r\n ${pc.yellow('-t, --type')} Project type: fullstack, backend, frontend ${pc.gray('(default: fullstack)')}\r\n ${pc.yellow('-b, --backend')} Backend framework: dotnet, spring, nestjs\r\n ${pc.yellow('-u, --ui')} UI library: vuetify, primevue ${pc.gray('(default: vuetify)')}\r\n ${pc.yellow('-n, --name')} Project namespace (Company.Project format, .NET/Spring only)\r\n ${pc.yellow('-r, --root')} Place files in project root ${pc.gray('(backend/frontend-only)')}\r\n ${pc.yellow('-i, --install')} Install dependencies after creation\r\n ${pc.yellow('-h, --help')} Show this help message\r\n ${pc.yellow('-v, --version')} Show version number\r\n\r\n${pc.bold('Examples:')}\r\n ${pc.gray('# Interactive mode')}\r\n npm create apptemplate@latest\r\n\r\n ${pc.gray('# Create fullstack project with .NET backend')}\r\n npm create apptemplate@latest my-app -b dotnet -n \"MyCompany.MyApp\" -i\r\n\r\n ${pc.gray('# Create backend-only project with Spring Boot')}\r\n npm create apptemplate@latest my-api -t backend -b spring -n \"MyCompany.MyApi\"\r\n\r\n ${pc.gray('# Create frontend-only project with PrimeVue')}\r\n npm create apptemplate@latest my-spa -t frontend -u primevue\r\n\r\n ${pc.gray('# Create backend in project root (no subfolder)')}\r\n npm create apptemplate@latest my-api -t backend -b nestjs --root\r\n`);\r\n}\r\n\r\nfunction showNextSteps(config: ProjectConfig): void {\r\n // Determine folder names based on project type and placeInRoot option\r\n let backendFolder: string;\r\n let frontendFolder: string;\r\n\r\n if (config.projectType === 'fullstack') {\r\n backendFolder = 'backend';\r\n frontendFolder = 'frontend';\r\n } else if (config.placeInRoot) {\r\n backendFolder = '.';\r\n frontendFolder = '.';\r\n } else {\r\n backendFolder = 'backend';\r\n frontendFolder = 'frontend';\r\n }\r\n\r\n console.log();\r\n console.log(pc.cyan('Next steps:'));\r\n console.log(` ${pc.gray('$')} cd ${config.projectPath}`);\r\n\r\n // Show install commands if deps weren't installed\r\n if (!config.installDeps) {\r\n if (config.projectType !== 'frontend') {\r\n const cdBackend = backendFolder === '.' ? '' : `cd ${backendFolder} && `;\r\n if (config.backend === 'dotnet') {\r\n console.log(` ${pc.gray('$')} ${cdBackend}dotnet restore`);\r\n } else if (config.backend === 'nestjs') {\r\n console.log(` ${pc.gray('$')} ${cdBackend}npm install`);\r\n } else if (config.backend === 'spring') {\r\n console.log(` ${pc.gray('$')} ${cdBackend}./mvnw install -DskipTests`);\r\n }\r\n }\r\n if (config.projectType !== 'backend') {\r\n const cdFrontend = frontendFolder === '.' ? '' : `cd ${frontendFolder} && `;\r\n console.log(` ${pc.gray('$')} ${cdFrontend}npm install`);\r\n }\r\n }\r\n\r\n // Docker compose option (for fullstack)\r\n if (config.projectType === 'fullstack') {\r\n console.log();\r\n console.log(pc.gray('Run with Docker:'));\r\n console.log(` ${pc.gray('$')} cp .env.example .env`);\r\n console.log(` ${pc.gray('$')} docker compose up -d --build`);\r\n }\r\n\r\n // Manual run instructions\r\n console.log();\r\n console.log(pc.gray('Run manually:'));\r\n\r\n if (config.projectType !== 'frontend') {\r\n const cdBackend = backendFolder === '.' ? '' : `cd ${backendFolder} && `;\r\n if (config.backend === 'dotnet') {\r\n console.log(` ${pc.gray('# Backend (.NET)')}`);\r\n if (backendFolder === '.') {\r\n console.log(` ${pc.gray('$')} cd src/Presentation/*.WebAPI && dotnet run`);\r\n } else {\r\n console.log(` ${pc.gray('$')} cd ${backendFolder}/src/Presentation/*.WebAPI && dotnet run`);\r\n }\r\n } else if (config.backend === 'nestjs') {\r\n console.log(` ${pc.gray('# Backend (NestJS)')}`);\r\n console.log(` ${pc.gray('$')} ${cdBackend}npm run start:dev`);\r\n } else if (config.backend === 'spring') {\r\n console.log(` ${pc.gray('# Backend (Spring Boot)')}`);\r\n console.log(` ${pc.gray('$')} ${cdBackend}./mvnw spring-boot:run`);\r\n }\r\n }\r\n\r\n if (config.projectType !== 'backend') {\r\n const cdFrontend = frontendFolder === '.' ? '' : `cd ${frontendFolder} && `;\r\n console.log(` ${pc.gray('# Frontend')}`);\r\n console.log(` ${pc.gray('$')} ${cdFrontend}npm run dev`);\r\n }\r\n\r\n // Access points\r\n console.log();\r\n console.log(pc.gray('Access points:'));\r\n\r\n if (config.projectType !== 'backend') {\r\n if (config.projectType === 'fullstack') {\r\n console.log(` Frontend: ${pc.cyan('http://localhost:3000')} ${pc.gray('(dev)')}`);\r\n } else {\r\n console.log(` Frontend: ${pc.cyan('http://localhost:3000')}`);\r\n }\r\n }\r\n\r\n if (config.projectType !== 'frontend') {\r\n console.log(` Backend: ${pc.cyan('http://localhost:5100')}`);\r\n console.log(` Swagger: ${pc.cyan('http://localhost:5100/swagger')}`);\r\n }\r\n\r\n // Default login (only for projects with backend)\r\n if (config.projectType !== 'frontend') {\r\n console.log();\r\n console.log(pc.gray('Default login:'));\r\n console.log(` Username: ${pc.cyan('admin')}`);\r\n console.log(` Password: ${pc.cyan('Admin@123')}`);\r\n }\r\n\r\n console.log();\r\n}\r\n\r\nmain();\r\n","import type { CLIArgs, ProjectType, BackendFramework, UILibrary } from './types.js';\r\n\r\nconst validProjectTypes: ProjectType[] = ['fullstack', 'backend', 'frontend'];\r\nconst validBackends: BackendFramework[] = ['dotnet', 'spring', 'nestjs'];\r\nconst validUILibraries: UILibrary[] = ['vuetify', 'primevue'];\r\n\r\nexport function parseArgs(): CLIArgs {\r\n const args = process.argv.slice(2);\r\n const result: CLIArgs = {};\r\n\r\n let i = 0;\r\n while (i < args.length) {\r\n const arg = args[i];\r\n\r\n // Handle flags\r\n if (arg === '-h' || arg === '--help') {\r\n result.help = true;\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-v' || arg === '--version') {\r\n result.version = true;\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-i' || arg === '--install') {\r\n result.install = true;\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-r' || arg === '--root') {\r\n result.root = true;\r\n i++;\r\n continue;\r\n }\r\n\r\n // Handle options with values\r\n if (arg === '-t' || arg === '--type') {\r\n const value = args[++i];\r\n if (isValidProjectType(value)) {\r\n result.type = value;\r\n } else {\r\n console.warn(`Warning: Invalid project type \"${value}\". Valid options: ${validProjectTypes.join(', ')}`);\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-b' || arg === '--backend') {\r\n const value = args[++i];\r\n if (isValidBackend(value)) {\r\n result.backend = value;\r\n } else {\r\n console.warn(`Warning: Invalid backend \"${value}\". Valid options: ${validBackends.join(', ')}`);\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-u' || arg === '--ui') {\r\n const value = args[++i];\r\n if (isValidUI(value)) {\r\n result.ui = value;\r\n } else {\r\n console.warn(`Warning: Invalid UI library \"${value}\". Valid options: ${validUILibraries.join(', ')}`);\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-n' || arg === '--name') {\r\n const value = args[++i];\r\n if (isValidProjectName(value)) {\r\n result.projectName = value;\r\n } else {\r\n console.warn(`Warning: Project name should be in \"Company.Project\" format`);\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n // If not a flag, treat as project path (first positional argument)\r\n if (!arg.startsWith('-') && !result.projectPath) {\r\n result.projectPath = arg;\r\n }\r\n\r\n i++;\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction isValidProjectType(value: string | undefined): value is ProjectType {\r\n return value !== undefined && validProjectTypes.includes(value as ProjectType);\r\n}\r\n\r\nfunction isValidBackend(value: string | undefined): value is BackendFramework {\r\n return value !== undefined && validBackends.includes(value as BackendFramework);\r\n}\r\n\r\nfunction isValidUI(value: string | undefined): value is UILibrary {\r\n return value !== undefined && validUILibraries.includes(value as UILibrary);\r\n}\r\n\r\nfunction isValidProjectName(value: string | undefined): boolean {\r\n if (!value) return false;\r\n // Validate Company.Project format\r\n const pattern = /^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)+$/;\r\n return pattern.test(value);\r\n}\r\n","import * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport type { CLIArgs, ProjectConfig, ProjectType, BackendFramework, UILibrary } from './types.js';\r\n\r\nexport async function runInteractivePrompts(cliArgs: CLIArgs): Promise<ProjectConfig | symbol> {\r\n // Project path\r\n let projectPath = cliArgs.projectPath;\r\n if (!projectPath) {\r\n const result = await p.text({\r\n message: 'Where should we create your project?',\r\n placeholder: './my-app',\r\n defaultValue: './my-app',\r\n validate: (value) => {\r\n if (!value) return 'Please enter a directory path';\r\n const resolvedPath = path.resolve(value);\r\n if (fs.existsSync(resolvedPath) && fs.readdirSync(resolvedPath).length > 0) {\r\n return 'Directory exists and is not empty';\r\n }\r\n return undefined;\r\n },\r\n });\r\n if (p.isCancel(result)) return result;\r\n projectPath = result;\r\n }\r\n\r\n // Project type\r\n let projectType = cliArgs.type;\r\n if (!projectType) {\r\n const result = await p.select({\r\n message: 'What type of project would you like to create?',\r\n options: [\r\n {\r\n value: 'fullstack' as ProjectType,\r\n label: 'Fullstack',\r\n hint: 'Backend + Frontend + Docker',\r\n },\r\n {\r\n value: 'backend' as ProjectType,\r\n label: 'Backend only',\r\n hint: 'API service or microservice',\r\n },\r\n {\r\n value: 'frontend' as ProjectType,\r\n label: 'Frontend only',\r\n hint: 'SPA with external API',\r\n },\r\n ],\r\n });\r\n if (p.isCancel(result)) return result;\r\n projectType = result;\r\n }\r\n\r\n // Backend framework (skip for frontend-only)\r\n let backend: BackendFramework = cliArgs.backend || 'dotnet';\r\n if (projectType !== 'frontend' && !cliArgs.backend) {\r\n const result = await p.select({\r\n message: 'Which backend framework would you like to use?',\r\n options: [\r\n {\r\n value: 'dotnet' as BackendFramework,\r\n label: '.NET 8',\r\n hint: 'Clean Architecture, CQRS, Entity Framework',\r\n },\r\n {\r\n value: 'spring' as BackendFramework,\r\n label: 'Spring Boot 3',\r\n hint: 'Clean Architecture, Java 21',\r\n },\r\n {\r\n value: 'nestjs' as BackendFramework,\r\n label: 'NestJS',\r\n hint: 'Clean Architecture, TypeScript',\r\n },\r\n ],\r\n });\r\n if (p.isCancel(result)) return result;\r\n backend = result;\r\n }\r\n\r\n // UI library (skip for backend-only)\r\n let ui: UILibrary = cliArgs.ui || 'vuetify';\r\n if (projectType !== 'backend' && !cliArgs.ui) {\r\n const result = await p.select({\r\n message: 'Which UI library would you like to use?',\r\n options: [\r\n {\r\n value: 'vuetify' as UILibrary,\r\n label: 'Vuetify',\r\n hint: 'Material Design 3, 80+ components',\r\n },\r\n {\r\n value: 'primevue' as UILibrary,\r\n label: 'PrimeVue',\r\n hint: 'Aura theme, 90+ components',\r\n },\r\n ],\r\n });\r\n if (p.isCancel(result)) return result;\r\n ui = result;\r\n }\r\n\r\n // Project name (for namespaces) - only for dotnet/spring backends\r\n let projectName: string | undefined = cliArgs.projectName;\r\n const needsNamespace = projectType !== 'frontend' && (backend === 'dotnet' || backend === 'spring');\r\n\r\n if (needsNamespace && !projectName) {\r\n // Generate default name from project path\r\n const dirName = path.basename(path.resolve(projectPath));\r\n const defaultName = `MyCompany.${toPascalCase(dirName)}`;\r\n\r\n const result = await p.text({\r\n message: 'Project namespace (for .NET/Java packages)',\r\n placeholder: defaultName,\r\n defaultValue: defaultName,\r\n validate: (value) => {\r\n if (!value) return 'Please enter a project namespace';\r\n const pattern = /^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)+$/;\r\n if (!pattern.test(value)) {\r\n return 'Namespace must be in \"Company.Project\" format (e.g., MyCompany.MyApp)';\r\n }\r\n return undefined;\r\n },\r\n });\r\n if (p.isCancel(result)) return result;\r\n projectName = result;\r\n }\r\n\r\n // Place in root option (for backend-only or frontend-only)\r\n let placeInRoot = cliArgs.root ?? false;\r\n if (projectType !== 'fullstack' && cliArgs.root === undefined) {\r\n const result = await p.confirm({\r\n message: 'Place files directly in project root? (No for subfolder)',\r\n initialValue: false,\r\n });\r\n if (p.isCancel(result)) return result;\r\n placeInRoot = result;\r\n }\r\n\r\n // Install dependencies\r\n let installDeps = cliArgs.install ?? false;\r\n if (cliArgs.install === undefined) {\r\n const result = await p.confirm({\r\n message: 'Install dependencies after creation?',\r\n initialValue: true,\r\n });\r\n if (p.isCancel(result)) return result;\r\n installDeps = result;\r\n }\r\n\r\n // Show summary\r\n console.log();\r\n const summaryLines = [\r\n `${pc.cyan('Project path:')} ${projectPath}`,\r\n `${pc.cyan('Project type:')} ${projectType}`,\r\n ];\r\n\r\n if (projectType !== 'frontend') {\r\n summaryLines.push(`${pc.cyan('Backend:')} ${getBackendLabel(backend)}`);\r\n }\r\n if (projectType !== 'backend') {\r\n summaryLines.push(`${pc.cyan('UI Library:')} ${getUILabel(ui)}`);\r\n }\r\n if (needsNamespace && projectName) {\r\n summaryLines.push(`${pc.cyan('Namespace:')} ${projectName}`);\r\n }\r\n if (projectType !== 'fullstack') {\r\n summaryLines.push(`${pc.cyan('Place in root:')} ${placeInRoot ? 'Yes' : 'No (subfolder)'}`);\r\n }\r\n summaryLines.push(`${pc.cyan('Install deps:')} ${installDeps ? 'Yes' : 'No'}`);\r\n\r\n p.note(summaryLines.join('\\n'), 'Configuration');\r\n\r\n const shouldContinue = await p.confirm({\r\n message: 'Create project with these settings?',\r\n initialValue: true,\r\n });\r\n if (p.isCancel(shouldContinue) || !shouldContinue) {\r\n return p.isCancel(shouldContinue) ? shouldContinue : Symbol('cancelled');\r\n }\r\n\r\n return {\r\n projectPath,\r\n projectType,\r\n backend,\r\n ui,\r\n projectName,\r\n installDeps,\r\n placeInRoot,\r\n };\r\n}\r\n\r\nfunction toPascalCase(str: string): string {\r\n return str\r\n .replace(/[-_\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\r\n .replace(/^(.)/, (c) => c.toUpperCase());\r\n}\r\n\r\nfunction getBackendLabel(backend: BackendFramework): string {\r\n const labels: Record<BackendFramework, string> = {\r\n dotnet: '.NET 8',\r\n spring: 'Spring Boot 3',\r\n nestjs: 'NestJS',\r\n };\r\n return labels[backend];\r\n}\r\n\r\nfunction getUILabel(ui: UILibrary): string {\r\n const labels: Record<UILibrary, string> = {\r\n vuetify: 'Vuetify (Material Design)',\r\n primevue: 'PrimeVue (Aura Theme)',\r\n };\r\n return labels[ui];\r\n}\r\n","import * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport type { ProjectConfig } from './types.js';\r\nimport { downloadTemplate, copyRootFiles } from './utils/download.js';\r\nimport { renameProject } from './utils/rename.js';\r\nimport { installDependencies } from './utils/package-manager.js';\r\n\r\n// GitHub repository for templates\r\nconst REPO = 'abuhanna/app-template';\r\n\r\nexport async function generateProject(config: ProjectConfig): Promise<void> {\r\n const absolutePath = path.resolve(config.projectPath);\r\n\r\n // Create project directory\r\n if (!fs.existsSync(absolutePath)) {\r\n fs.mkdirSync(absolutePath, { recursive: true });\r\n }\r\n\r\n const spinner = p.spinner();\r\n\r\n // Step 1: Download templates\r\n spinner.start('Downloading templates...');\r\n\r\n try {\r\n // Download backend (if not frontend-only)\r\n if (config.projectType !== 'frontend') {\r\n const sourceFolder = `backend-${config.backend}`;\r\n // For fullstack: use 'backend', for backend-only: use subfolder or root\r\n let destFolder: string;\r\n if (config.projectType === 'fullstack') {\r\n destFolder = 'backend';\r\n } else {\r\n destFolder = config.placeInRoot ? '' : 'backend';\r\n }\r\n const destPath = destFolder ? path.join(absolutePath, destFolder) : absolutePath;\r\n await downloadTemplate(REPO, sourceFolder, destPath);\r\n spinner.message(`Downloaded ${sourceFolder}`);\r\n }\r\n\r\n // Download frontend (if not backend-only)\r\n if (config.projectType !== 'backend') {\r\n const sourceFolder = `frontend-${config.ui}`;\r\n // For fullstack: use 'frontend', for frontend-only: use subfolder or root\r\n let destFolder: string;\r\n if (config.projectType === 'fullstack') {\r\n destFolder = 'frontend';\r\n } else {\r\n destFolder = config.placeInRoot ? '' : 'frontend';\r\n }\r\n const destPath = destFolder ? path.join(absolutePath, destFolder) : absolutePath;\r\n await downloadTemplate(REPO, sourceFolder, destPath);\r\n spinner.message(`Downloaded ${sourceFolder}`);\r\n }\r\n\r\n // Download common files (docker, scripts, etc.)\r\n await copyRootFiles(REPO, absolutePath, config);\r\n spinner.message('Downloaded configuration files');\r\n\r\n spinner.stop('Templates downloaded');\r\n } catch (error) {\r\n spinner.stop('Download failed');\r\n throw error;\r\n }\r\n\r\n // Step 2: Update folder references in common files\r\n spinner.start('Updating configuration files...');\r\n try {\r\n await updateFolderReferences(absolutePath, config);\r\n spinner.stop('Configuration updated');\r\n } catch (error) {\r\n spinner.stop('Configuration update failed');\r\n throw error;\r\n }\r\n\r\n // Step 3: Rename project namespaces (only for dotnet/spring)\r\n if (config.projectName && config.projectName !== 'App.Template') {\r\n spinner.start('Renaming project namespaces...');\r\n\r\n try {\r\n await renameProject(absolutePath, config);\r\n spinner.stop('Project namespaces updated');\r\n } catch (error) {\r\n spinner.stop('Namespace rename failed');\r\n throw error;\r\n }\r\n }\r\n\r\n // Step 4: Install dependencies (if requested)\r\n if (config.installDeps) {\r\n spinner.start('Installing dependencies (this may take a while)...');\r\n\r\n try {\r\n await installDependencies(absolutePath, config);\r\n spinner.stop('Dependencies installed');\r\n } catch (error) {\r\n spinner.stop('Installation failed');\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n console.log(pc.yellow(` Warning: Dependency installation failed: ${errorMessage}`));\r\n console.log(pc.gray(' You can install manually by running npm install in the project directory'));\r\n }\r\n }\r\n\r\n // Step 5: Setup environment files\r\n await setupEnvironmentFiles(absolutePath, config);\r\n\r\n // Step 6: Create appsettings.Development.json from example (for .NET projects)\r\n if (config.projectType !== 'frontend' && config.backend === 'dotnet') {\r\n await createAppSettingsFromExample(absolutePath, config);\r\n }\r\n}\r\n\r\n/**\r\n * Setup environment files based on project stack\r\n */\r\nasync function setupEnvironmentFiles(projectPath: string, config: ProjectConfig): Promise<void> {\r\n // 1. Frontend Environment\r\n if (config.projectType !== 'backend') {\r\n let frontendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n frontendDir = path.join(projectPath, 'frontend');\r\n } else {\r\n frontendDir = config.placeInRoot ? projectPath : path.join(projectPath, 'frontend');\r\n }\r\n\r\n const envExample = path.join(frontendDir, '.env.example');\r\n const envDest = path.join(frontendDir, '.env');\r\n\r\n if (fs.existsSync(envExample) && !fs.existsSync(envDest)) {\r\n fs.copyFileSync(envExample, envDest);\r\n\r\n // Update VITE_BACKEND_TYPE for fullstack projects\r\n if (config.projectType === 'fullstack') {\r\n let content = fs.readFileSync(envDest, 'utf-8');\r\n let backendType = 'dotnet';\r\n if (config.backend === 'nestjs') backendType = 'nest';\r\n if (config.backend === 'spring') backendType = 'spring';\r\n \r\n // Replace logical default 'dotnet' with actual selection\r\n // Also handle if .env.example doesn't have it set to dotnet by using regex\r\n content = content.replace(/^VITE_BACKEND_TYPE=.*$/m, `VITE_BACKEND_TYPE=${backendType}`);\r\n \r\n fs.writeFileSync(envDest, content);\r\n }\r\n }\r\n }\r\n\r\n // 2. Backend Environment\r\n if (config.projectType !== 'frontend') {\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else {\r\n backendDir = config.placeInRoot ? projectPath : path.join(projectPath, 'backend');\r\n }\r\n\r\n // NestJS\r\n if (config.backend === 'nestjs') {\r\n const envExample = path.join(backendDir, '.env.example');\r\n const envDest = path.join(backendDir, '.env');\r\n if (fs.existsSync(envExample) && !fs.existsSync(envDest)) {\r\n fs.copyFileSync(envExample, envDest);\r\n }\r\n }\r\n\r\n // Spring Boot\r\n if (config.backend === 'spring') {\r\n const ymlExample = path.join(backendDir, 'api', 'src', 'main', 'resources', 'application.example.yml');\r\n const ymlDest = path.join(backendDir, 'api', 'src', 'main', 'resources', 'application.yml');\r\n if (fs.existsSync(ymlExample) && !fs.existsSync(ymlDest)) {\r\n fs.copyFileSync(ymlExample, ymlDest);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Create appsettings.Development.json from appsettings.example.json for .NET projects\r\n */\r\nasync function createAppSettingsFromExample(projectPath: string, config: ProjectConfig): Promise<void> {\r\n // Determine backend directory\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else if (config.placeInRoot) {\r\n backendDir = projectPath;\r\n } else {\r\n backendDir = path.join(projectPath, 'backend');\r\n }\r\n\r\n // Find WebAPI project directory (it contains appsettings.example.json)\r\n const presentationDir = path.join(backendDir, 'src', 'Presentation');\r\n if (!fs.existsSync(presentationDir)) return;\r\n\r\n const entries = fs.readdirSync(presentationDir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (entry.isDirectory() && entry.name.endsWith('.WebAPI')) {\r\n const webApiDir = path.join(presentationDir, entry.name);\r\n const examplePath = path.join(webApiDir, 'appsettings.example.json');\r\n const devPath = path.join(webApiDir, 'appsettings.Development.json');\r\n\r\n if (fs.existsSync(examplePath) && !fs.existsSync(devPath)) {\r\n fs.copyFileSync(examplePath, devPath);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Update folder references in common files\r\n * Replaces backend-dotnet/backend-spring/backend-nestjs with backend\r\n * Replaces frontend-vuetify/frontend-primevue with frontend\r\n */\r\nasync function updateFolderReferences(projectPath: string, config: ProjectConfig): Promise<void> {\r\n const filesToUpdate = [\r\n 'Dockerfile',\r\n 'docker-compose.yml',\r\n 'docker-compose.staging.yml',\r\n 'docker-compose.production.yml',\r\n 'docker-compose.backend.yml',\r\n 'docker-compose.frontend.yml',\r\n 'Makefile',\r\n 'CLAUDE.md',\r\n 'README.md',\r\n ];\r\n\r\n // Determine the new folder names based on project type\r\n const backendReplace = config.placeInRoot && config.projectType === 'backend' ? '.' : 'backend';\r\n const frontendReplace = config.placeInRoot && config.projectType === 'frontend' ? '.' : 'frontend';\r\n\r\n for (const file of filesToUpdate) {\r\n const filePath = path.join(projectPath, file);\r\n if (fs.existsSync(filePath)) {\r\n let content = fs.readFileSync(filePath, 'utf-8');\r\n\r\n // Replace backend folder references\r\n if (config.projectType !== 'frontend') {\r\n content = content\r\n .replace(/backend-dotnet/g, backendReplace)\r\n .replace(/backend-spring/g, backendReplace)\r\n .replace(/backend-nestjs/g, backendReplace);\r\n }\r\n\r\n // Replace frontend folder references\r\n if (config.projectType !== 'backend') {\r\n content = content\r\n .replace(/frontend-vuetify/g, frontendReplace)\r\n .replace(/frontend-primevue/g, frontendReplace);\r\n }\r\n\r\n fs.writeFileSync(filePath, content);\r\n }\r\n }\r\n\r\n // Also update docker folder files\r\n const dockerFolder = path.join(projectPath, 'docker');\r\n if (fs.existsSync(dockerFolder)) {\r\n updateDockerFolderFiles(dockerFolder, config, backendReplace, frontendReplace);\r\n }\r\n}\r\n\r\n/**\r\n * Recursively update files in the docker folder\r\n */\r\nfunction updateDockerFolderFiles(\r\n dir: string,\r\n config: ProjectConfig,\r\n backendReplace: string,\r\n frontendReplace: string\r\n): void {\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n updateDockerFolderFiles(fullPath, config, backendReplace, frontendReplace);\r\n } else if (entry.isFile()) {\r\n let content = fs.readFileSync(fullPath, 'utf-8');\r\n\r\n if (config.projectType !== 'frontend') {\r\n content = content\r\n .replace(/backend-dotnet/g, backendReplace)\r\n .replace(/backend-spring/g, backendReplace)\r\n .replace(/backend-nestjs/g, backendReplace);\r\n }\r\n\r\n if (config.projectType !== 'backend') {\r\n content = content\r\n .replace(/frontend-vuetify/g, frontendReplace)\r\n .replace(/frontend-primevue/g, frontendReplace);\r\n }\r\n\r\n fs.writeFileSync(fullPath, content);\r\n }\r\n }\r\n}\r\n","import degit from 'degit';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport type { ProjectConfig } from '../types.js';\r\n\r\n/**\r\n * Download a specific folder from the GitHub repository\r\n */\r\nexport async function downloadTemplate(repo: string, folder: string, destPath: string): Promise<void> {\r\n const source = `${repo}/${folder}`;\r\n const emitter = degit(source, {\r\n cache: false,\r\n force: true,\r\n verbose: false,\r\n });\r\n\r\n await emitter.clone(destPath);\r\n}\r\n\r\n/**\r\n * Download root configuration files based on project type\r\n */\r\nexport async function copyRootFiles(repo: string, destPath: string, config: ProjectConfig): Promise<void> {\r\n // Files to download based on project type\r\n const commonFiles = [\r\n '.env.example',\r\n '.gitignore',\r\n 'README.md',\r\n 'CLAUDE.md',\r\n ];\r\n\r\n const fullstackFiles = [\r\n 'Dockerfile',\r\n 'docker-compose.yml',\r\n 'docker-compose.staging.yml',\r\n 'docker-compose.production.yml',\r\n 'Makefile',\r\n ];\r\n\r\n const backendOnlyFiles = [\r\n 'docker/Dockerfile.backend',\r\n 'docker-compose.backend.yml',\r\n ];\r\n\r\n const frontendOnlyFiles = [\r\n 'docker/Dockerfile.frontend',\r\n 'docker/nginx/frontend-only.conf',\r\n 'docker-compose.frontend.yml',\r\n ];\r\n\r\n // Determine which files to download\r\n let filesToDownload = [...commonFiles];\r\n\r\n switch (config.projectType) {\r\n case 'fullstack':\r\n filesToDownload = [...filesToDownload, ...fullstackFiles];\r\n break;\r\n case 'backend':\r\n filesToDownload = [...filesToDownload, ...backendOnlyFiles];\r\n break;\r\n case 'frontend':\r\n filesToDownload = [...filesToDownload, ...frontendOnlyFiles];\r\n break;\r\n }\r\n\r\n // Download docker folder for all project types\r\n const dockerFolder = 'docker';\r\n const dockerDest = path.join(destPath, dockerFolder);\r\n\r\n try {\r\n await downloadTemplate(repo, dockerFolder, dockerDest);\r\n } catch {\r\n // Docker folder might not exist for all project types, ignore error\r\n }\r\n\r\n // Note: We intentionally DO NOT download the scripts folder\r\n // The create-project and rename-project scripts are for manual repo cloning\r\n // Projects created via npm CLI don't need these scripts\r\n\r\n // Download individual root files\r\n // Note: degit doesn't support individual file downloads, so we download the whole repo\r\n // and then filter the files we need. This is a workaround.\r\n\r\n // Create a temporary directory for the full repo download\r\n const tempDir = path.join(destPath, '.temp-download');\r\n\r\n try {\r\n const emitter = degit(repo, {\r\n cache: false,\r\n force: true,\r\n verbose: false,\r\n });\r\n\r\n await emitter.clone(tempDir);\r\n\r\n // Copy only the files we need\r\n for (const file of filesToDownload) {\r\n const srcFile = path.join(tempDir, file);\r\n const destFile = path.join(destPath, file);\r\n\r\n if (fs.existsSync(srcFile)) {\r\n // Ensure parent directory exists\r\n const parentDir = path.dirname(destFile);\r\n if (!fs.existsSync(parentDir)) {\r\n fs.mkdirSync(parentDir, { recursive: true });\r\n }\r\n fs.copyFileSync(srcFile, destFile);\r\n }\r\n }\r\n } finally {\r\n // Clean up temp directory\r\n if (fs.existsSync(tempDir)) {\r\n fs.rmSync(tempDir, { recursive: true, force: true });\r\n }\r\n }\r\n}\r\n","import path from 'path';\r\nimport fs from 'fs';\r\nimport type { ProjectConfig } from '../types.js';\r\n\r\n/**\r\n * Rename project files and update namespaces\r\n * Only called when config.projectName is set (for dotnet/spring backends)\r\n */\r\nexport async function renameProject(projectPath: string, config: ProjectConfig): Promise<void> {\r\n if (!config.projectName) return;\r\n\r\n const newDotName = config.projectName;\r\n const newNamespace = config.projectName.replace(/\\./g, '');\r\n\r\n // Rename backend project files (for .NET)\r\n if (config.projectType !== 'frontend' && config.backend === 'dotnet') {\r\n await renameDotNetProject(projectPath, config, newDotName, newNamespace);\r\n }\r\n\r\n // Rename backend project files (for Spring)\r\n if (config.projectType !== 'frontend' && config.backend === 'spring') {\r\n await renameSpringProject(projectPath, config, newDotName);\r\n }\r\n\r\n // Update common files\r\n await updateCommonFiles(projectPath, config, newDotName, newNamespace);\r\n}\r\n\r\n/**\r\n * Rename .NET project structure\r\n */\r\nasync function renameDotNetProject(\r\n projectPath: string,\r\n config: ProjectConfig,\r\n newDotName: string,\r\n newNamespace: string\r\n): Promise<void> {\r\n // Determine backend directory based on project type and placeInRoot option\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else if (config.placeInRoot) {\r\n backendDir = projectPath;\r\n } else {\r\n backendDir = path.join(projectPath, 'backend');\r\n }\r\n\r\n if (!fs.existsSync(backendDir)) return;\r\n\r\n // Define folder mappings\r\n const folderMappings = [\r\n ['src/Core/App.Template.Domain', `src/Core/${newDotName}.Domain`],\r\n ['src/Core/App.Template.Application', `src/Core/${newDotName}.Application`],\r\n ['src/Infrastructure/App.Template.Infrastructure', `src/Infrastructure/${newDotName}.Infrastructure`],\r\n ['src/Presentation/App.Template.WebAPI', `src/Presentation/${newDotName}.WebAPI`],\r\n ['tests/App.Template.Domain.Tests', `tests/${newDotName}.Domain.Tests`],\r\n ['tests/App.Template.Application.Tests', `tests/${newDotName}.Application.Tests`],\r\n ];\r\n\r\n // Rename folders\r\n for (const [oldFolder, newFolder] of folderMappings) {\r\n const oldPath = path.join(backendDir, oldFolder);\r\n const newPath = path.join(backendDir, newFolder);\r\n\r\n if (fs.existsSync(oldPath)) {\r\n fs.renameSync(oldPath, newPath);\r\n }\r\n }\r\n\r\n // Rename .csproj files\r\n await renameFilesWithPattern(backendDir, /App\\.Template\\.(.*)\\.csproj$/, (match) => {\r\n return `${newDotName}.${match[1]}.csproj`;\r\n });\r\n\r\n // Rename solution file\r\n const oldSlnPath = path.join(backendDir, 'App.Template.sln');\r\n const newSlnPath = path.join(backendDir, `${newDotName}.sln`);\r\n if (fs.existsSync(oldSlnPath)) {\r\n fs.renameSync(oldSlnPath, newSlnPath);\r\n }\r\n\r\n // Update file contents in all relevant files\r\n const extensions = ['.cs', '.csproj', '.sln', '.json'];\r\n await updateFileContents(backendDir, extensions, (content) => {\r\n return content\r\n .replace(/App\\.Template/g, newDotName)\r\n .replace(/AppTemplate/g, newNamespace);\r\n });\r\n}\r\n\r\n/**\r\n * Rename Spring Boot project structure\r\n */\r\nasync function renameSpringProject(\r\n projectPath: string,\r\n config: ProjectConfig,\r\n newDotName: string\r\n): Promise<void> {\r\n // Determine backend directory based on project type and placeInRoot option\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else if (config.placeInRoot) {\r\n backendDir = projectPath;\r\n } else {\r\n backendDir = path.join(projectPath, 'backend');\r\n }\r\n\r\n if (!fs.existsSync(backendDir)) return;\r\n\r\n // Convert project name to Java package format\r\n const packageName = newDotName.toLowerCase().replace(/\\./g, '.');\r\n const artifactId = newDotName.toLowerCase().replace(/\\./g, '-');\r\n\r\n // Update pom.xml\r\n const pomPath = path.join(backendDir, 'pom.xml');\r\n if (fs.existsSync(pomPath)) {\r\n let content = fs.readFileSync(pomPath, 'utf-8');\r\n content = content\r\n .replace(/<groupId>com\\.apptemplate<\\/groupId>/g, `<groupId>${packageName}<\\/groupId>`)\r\n .replace(/<artifactId>apptemplate<\\/artifactId>/g, `<artifactId>${artifactId}<\\/artifactId>`)\r\n .replace(/com\\.apptemplate/g, packageName);\r\n fs.writeFileSync(pomPath, content);\r\n }\r\n\r\n // Update Java files\r\n await updateFileContents(backendDir, ['.java'], (content) => {\r\n return content.replace(/com\\.apptemplate/g, packageName);\r\n });\r\n}\r\n\r\n/**\r\n * Update common files (Dockerfile, docker-compose, etc.)\r\n */\r\nasync function updateCommonFiles(\r\n projectPath: string,\r\n _config: ProjectConfig,\r\n newDotName: string,\r\n newNamespace: string\r\n): Promise<void> {\r\n const filesToUpdate = [\r\n 'Dockerfile',\r\n 'docker-compose.yml',\r\n 'docker-compose.staging.yml',\r\n 'docker-compose.production.yml',\r\n 'docker-compose.backend.yml',\r\n 'docker-compose.frontend.yml',\r\n 'Makefile',\r\n 'CLAUDE.md',\r\n 'README.md',\r\n ];\r\n\r\n for (const file of filesToUpdate) {\r\n const filePath = path.join(projectPath, file);\r\n if (fs.existsSync(filePath)) {\r\n let content = fs.readFileSync(filePath, 'utf-8');\r\n content = content\r\n .replace(/App\\.Template/g, newDotName)\r\n .replace(/AppTemplate/g, newNamespace)\r\n .replace(/apptemplate/gi, newNamespace.toLowerCase());\r\n fs.writeFileSync(filePath, content);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Rename files matching a pattern in a directory\r\n */\r\nasync function renameFilesWithPattern(\r\n dir: string,\r\n pattern: RegExp,\r\n replacer: (match: RegExpMatchArray) => string\r\n): Promise<void> {\r\n const files = getAllFiles(dir);\r\n\r\n for (const file of files) {\r\n const fileName = path.basename(file);\r\n const match = fileName.match(pattern);\r\n\r\n if (match) {\r\n const newFileName = replacer(match);\r\n const newPath = path.join(path.dirname(file), newFileName);\r\n fs.renameSync(file, newPath);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Update file contents in a directory\r\n */\r\nasync function updateFileContents(\r\n dir: string,\r\n extensions: string[],\r\n updater: (content: string) => string\r\n): Promise<void> {\r\n const files = getAllFiles(dir);\r\n\r\n for (const file of files) {\r\n const ext = path.extname(file);\r\n if (extensions.includes(ext)) {\r\n let content = fs.readFileSync(file, 'utf-8');\r\n const updatedContent = updater(content);\r\n if (content !== updatedContent) {\r\n fs.writeFileSync(file, updatedContent);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Get all files in a directory recursively\r\n */\r\nfunction getAllFiles(dir: string): string[] {\r\n const files: string[] = [];\r\n\r\n if (!fs.existsSync(dir)) return files;\r\n\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // Skip node_modules and other common directories\r\n if (!['node_modules', '.git', 'bin', 'obj', 'dist', 'build'].includes(entry.name)) {\r\n files.push(...getAllFiles(fullPath));\r\n }\r\n } else {\r\n files.push(fullPath);\r\n }\r\n }\r\n\r\n return files;\r\n}\r\n","import spawn from 'cross-spawn';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport type { ProjectConfig } from '../types.js';\r\n\r\ntype PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';\r\n\r\n/**\r\n * Detect which package manager is being used\r\n */\r\nexport function detectPackageManager(): PackageManager {\r\n // Check for lockfiles in current directory\r\n const cwd = process.cwd();\r\n\r\n if (fs.existsSync(path.join(cwd, 'bun.lockb'))) return 'bun';\r\n if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';\r\n if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn';\r\n if (fs.existsSync(path.join(cwd, 'package-lock.json'))) return 'npm';\r\n\r\n // Check npm_config_user_agent environment variable\r\n const userAgent = process.env.npm_config_user_agent;\r\n if (userAgent) {\r\n if (userAgent.includes('bun')) return 'bun';\r\n if (userAgent.includes('pnpm')) return 'pnpm';\r\n if (userAgent.includes('yarn')) return 'yarn';\r\n }\r\n\r\n // Default to npm\r\n return 'npm';\r\n}\r\n\r\n/**\r\n * Install dependencies for the project\r\n */\r\nexport async function installDependencies(projectPath: string, config: ProjectConfig): Promise<void> {\r\n const pm = detectPackageManager();\r\n\r\n // Determine frontend directory\r\n let frontendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n frontendDir = path.join(projectPath, 'frontend');\r\n } else if (config.placeInRoot) {\r\n frontendDir = projectPath;\r\n } else {\r\n frontendDir = path.join(projectPath, 'frontend');\r\n }\r\n\r\n // Determine backend directory\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else if (config.placeInRoot) {\r\n backendDir = projectPath;\r\n } else {\r\n backendDir = path.join(projectPath, 'backend');\r\n }\r\n\r\n // Install frontend dependencies\r\n if (config.projectType !== 'backend') {\r\n const frontendPackageJson = path.join(frontendDir, 'package.json');\r\n if (fs.existsSync(frontendPackageJson)) {\r\n await runInstallCommand(frontendDir, pm);\r\n }\r\n }\r\n\r\n // Install/restore backend dependencies\r\n if (config.projectType !== 'frontend') {\r\n switch (config.backend) {\r\n case 'dotnet': {\r\n const slnFiles = fs.readdirSync(backendDir).filter(f => f.endsWith('.sln'));\r\n if (slnFiles.length > 0) {\r\n await runCommand('dotnet', ['restore'], backendDir);\r\n }\r\n break;\r\n }\r\n case 'spring': {\r\n const pomPath = path.join(backendDir, 'pom.xml');\r\n if (fs.existsSync(pomPath)) {\r\n const mvnwPath = path.join(backendDir, process.platform === 'win32' ? 'mvnw.cmd' : 'mvnw');\r\n if (fs.existsSync(mvnwPath)) {\r\n await runCommand(mvnwPath, ['install', '-DskipTests'], backendDir);\r\n } else {\r\n await runCommand('mvn', ['install', '-DskipTests'], backendDir);\r\n }\r\n }\r\n break;\r\n }\r\n case 'nestjs': {\r\n const backendPackageJson = path.join(backendDir, 'package.json');\r\n if (fs.existsSync(backendPackageJson)) {\r\n await runInstallCommand(backendDir, pm);\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Run package manager install command\r\n */\r\nasync function runInstallCommand(cwd: string, pm: PackageManager): Promise<void> {\r\n const installCommands: Record<PackageManager, string[]> = {\r\n npm: ['install'],\r\n yarn: ['install'],\r\n pnpm: ['install'],\r\n bun: ['install'],\r\n };\r\n\r\n await runCommand(pm, installCommands[pm], cwd);\r\n}\r\n\r\n/**\r\n * Run a command in a directory\r\n */\r\nfunction runCommand(command: string, args: string[], cwd: string): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const child = spawn(command, args, {\r\n cwd,\r\n stdio: 'pipe',\r\n shell: process.platform === 'win32',\r\n });\r\n\r\n let stderr = '';\r\n\r\n child.stderr?.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n child.on('close', (code) => {\r\n if (code === 0) {\r\n resolve();\r\n } else {\r\n reject(new Error(`Command \"${command} ${args.join(' ')}\" failed with code ${code}: ${stderr}`));\r\n }\r\n });\r\n\r\n child.on('error', (error) => {\r\n reject(error);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Check if a command exists\r\n */\r\nexport function commandExists(command: string): boolean {\r\n try {\r\n const result = spawn.sync(command, ['--version'], {\r\n stdio: 'pipe',\r\n shell: process.platform === 'win32',\r\n });\r\n return result.status === 0;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n"],"mappings":"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","names":["isCancel","pc","p","pc","path","fs","path","fs","path","fs","path","fs","path","fs","spinner","pc","pc","isCancel"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/prompts.ts","../src/generator.ts","../src/utils/download.ts","../src/utils/rename.ts","../src/utils/package-manager.ts"],"sourcesContent":["import { intro, outro, isCancel } from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport { parseArgs } from './cli.js';\r\nimport { runInteractivePrompts } from './prompts.js';\r\nimport { generateProject } from './generator.js';\r\nimport type { ProjectConfig } from './types.js';\r\n\r\nasync function main(): Promise<void> {\r\n console.log();\r\n intro(pc.bgCyan(pc.black(' Create AppTemplate ')));\r\n\r\n try {\r\n // Parse CLI arguments\r\n const cliArgs = parseArgs();\r\n\r\n // Show help if requested\r\n if (cliArgs.help) {\r\n showHelp();\r\n process.exit(0);\r\n }\r\n\r\n // Show version if requested\r\n if (cliArgs.version) {\r\n console.log('create-apptemplate v1.0.0');\r\n process.exit(0);\r\n }\r\n\r\n // Get project configuration (interactive or from CLI args)\r\n let config: ProjectConfig;\r\n\r\n // Non-interactive mode - check if we have enough options\r\n const projectType = cliArgs.type || 'fullstack';\r\n const backend = cliArgs.backend || 'dotnet';\r\n const needsNamespace = projectType !== 'frontend' && (backend === 'dotnet' || backend === 'spring');\r\n\r\n if (cliArgs.projectPath && cliArgs.backend && (!needsNamespace || cliArgs.projectName)) {\r\n // Non-interactive mode - all required options provided\r\n const frontendFramework = cliArgs.framework || 'vue';\r\n config = {\r\n projectPath: cliArgs.projectPath,\r\n projectType,\r\n backend,\r\n frontendFramework,\r\n ui: cliArgs.ui || (frontendFramework === 'vue' ? 'vuetify' : 'mui'),\r\n projectName: cliArgs.projectName,\r\n installDeps: cliArgs.install || false,\r\n placeInRoot: cliArgs.root || false,\r\n };\r\n } else {\r\n // Interactive mode\r\n const result = await runInteractivePrompts(cliArgs);\r\n if (isCancel(result)) {\r\n outro(pc.yellow('Operation cancelled'));\r\n process.exit(0);\r\n }\r\n config = result;\r\n }\r\n\r\n // Generate the project\r\n await generateProject(config);\r\n\r\n // Success message\r\n console.log();\r\n outro(pc.green('✓ Done! Your project is ready.'));\r\n\r\n // Show dynamic next steps based on project type\r\n showNextSteps(config);\r\n } catch (error) {\r\n if (error instanceof Error) {\r\n console.error(pc.red(`Error: ${error.message}`));\r\n } else {\r\n console.error(pc.red('An unexpected error occurred'));\r\n }\r\n process.exit(1);\r\n }\r\n}\r\n\r\nfunction showHelp(): void {\r\n console.log(`\r\n${pc.bold('Usage:')}\r\n ${pc.cyan('npm create apptemplate@latest')} ${pc.gray('[project-directory]')} ${pc.gray('[options]')}\r\n\r\n${pc.bold('Options:')}\r\n ${pc.yellow('-t, --type')} Project type: fullstack, backend, frontend ${pc.gray('(default: fullstack)')}\r\n ${pc.yellow('-b, --backend')} Backend framework: dotnet, spring, nestjs\r\n ${pc.yellow('-f, --framework')} Frontend framework: vue, react ${pc.gray('(default: vue)')}\r\n ${pc.yellow('-u, --ui')} UI library: vuetify, primevue (Vue) | mui, primereact (React)\r\n ${pc.yellow('-n, --name')} Project namespace (Company.Project format, .NET/Spring only)\r\n ${pc.yellow('-r, --root')} Place files in project root ${pc.gray('(backend/frontend-only)')}\r\n ${pc.yellow('-i, --install')} Install dependencies after creation\r\n ${pc.yellow('-h, --help')} Show this help message\r\n ${pc.yellow('-v, --version')} Show version number\r\n\r\n${pc.bold('Examples:')}\r\n ${pc.gray('# Interactive mode')}\r\n npm create apptemplate@latest\r\n\r\n ${pc.gray('# Create fullstack project with .NET backend')}\r\n npm create apptemplate@latest my-app -b dotnet -n \"MyCompany.MyApp\" -i\r\n\r\n ${pc.gray('# Create backend-only project with Spring Boot')}\r\n npm create apptemplate@latest my-api -t backend -b spring -n \"MyCompany.MyApi\"\r\n\r\n ${pc.gray('# Create frontend-only project with PrimeVue')}\r\n npm create apptemplate@latest my-spa -t frontend -u primevue\r\n\r\n ${pc.gray('# Create fullstack project with React + MUI')}\r\n npm create apptemplate@latest my-app -b dotnet -f react -u mui -n \"MyCompany.MyApp\"\r\n\r\n ${pc.gray('# Create backend in project root (no subfolder)')}\r\n npm create apptemplate@latest my-api -t backend -b nestjs --root\r\n`);\r\n}\r\n\r\nfunction showNextSteps(config: ProjectConfig): void {\r\n // Determine folder names based on project type and placeInRoot option\r\n let backendFolder: string;\r\n let frontendFolder: string;\r\n\r\n if (config.projectType === 'fullstack') {\r\n backendFolder = 'backend';\r\n frontendFolder = 'frontend';\r\n } else if (config.placeInRoot) {\r\n backendFolder = '.';\r\n frontendFolder = '.';\r\n } else {\r\n backendFolder = 'backend';\r\n frontendFolder = 'frontend';\r\n }\r\n\r\n console.log();\r\n console.log(pc.cyan('Next steps:'));\r\n console.log(` ${pc.gray('$')} cd ${config.projectPath}`);\r\n\r\n // Show install commands if deps weren't installed\r\n if (!config.installDeps) {\r\n if (config.projectType !== 'frontend') {\r\n const cdBackend = backendFolder === '.' ? '' : `cd ${backendFolder} && `;\r\n if (config.backend === 'dotnet') {\r\n console.log(` ${pc.gray('$')} ${cdBackend}dotnet restore`);\r\n } else if (config.backend === 'nestjs') {\r\n console.log(` ${pc.gray('$')} ${cdBackend}npm install`);\r\n } else if (config.backend === 'spring') {\r\n console.log(` ${pc.gray('$')} ${cdBackend}./mvnw install -DskipTests`);\r\n }\r\n }\r\n if (config.projectType !== 'backend') {\r\n const cdFrontend = frontendFolder === '.' ? '' : `cd ${frontendFolder} && `;\r\n console.log(` ${pc.gray('$')} ${cdFrontend}npm install`);\r\n }\r\n }\r\n\r\n // Docker compose option (for fullstack)\r\n if (config.projectType === 'fullstack') {\r\n console.log();\r\n console.log(pc.gray('Run with Docker:'));\r\n console.log(` ${pc.gray('$')} cp .env.example .env`);\r\n console.log(` ${pc.gray('$')} docker compose up -d --build`);\r\n }\r\n\r\n // Manual run instructions\r\n console.log();\r\n console.log(pc.gray('Run manually:'));\r\n\r\n if (config.projectType !== 'frontend') {\r\n const cdBackend = backendFolder === '.' ? '' : `cd ${backendFolder} && `;\r\n if (config.backend === 'dotnet') {\r\n console.log(` ${pc.gray('# Backend (.NET)')}`);\r\n if (backendFolder === '.') {\r\n console.log(` ${pc.gray('$')} cd src/Presentation/*.WebAPI && dotnet run`);\r\n } else {\r\n console.log(` ${pc.gray('$')} cd ${backendFolder}/src/Presentation/*.WebAPI && dotnet run`);\r\n }\r\n } else if (config.backend === 'nestjs') {\r\n console.log(` ${pc.gray('# Backend (NestJS)')}`);\r\n console.log(` ${pc.gray('$')} ${cdBackend}npm run start:dev`);\r\n } else if (config.backend === 'spring') {\r\n console.log(` ${pc.gray('# Backend (Spring Boot)')}`);\r\n console.log(` ${pc.gray('$')} ${cdBackend}./mvnw spring-boot:run`);\r\n }\r\n }\r\n\r\n if (config.projectType !== 'backend') {\r\n const cdFrontend = frontendFolder === '.' ? '' : `cd ${frontendFolder} && `;\r\n console.log(` ${pc.gray('# Frontend')}`);\r\n console.log(` ${pc.gray('$')} ${cdFrontend}npm run dev`);\r\n }\r\n\r\n // Access points\r\n console.log();\r\n console.log(pc.gray('Access points:'));\r\n\r\n if (config.projectType !== 'backend') {\r\n if (config.projectType === 'fullstack') {\r\n console.log(` Frontend: ${pc.cyan('http://localhost:3000')} ${pc.gray('(dev)')}`);\r\n } else {\r\n console.log(` Frontend: ${pc.cyan('http://localhost:3000')}`);\r\n }\r\n }\r\n\r\n if (config.projectType !== 'frontend') {\r\n console.log(` Backend: ${pc.cyan('http://localhost:5100')}`);\r\n console.log(` Swagger: ${pc.cyan('http://localhost:5100/swagger')}`);\r\n }\r\n\r\n // Default login (only for projects with backend)\r\n if (config.projectType !== 'frontend') {\r\n console.log();\r\n console.log(pc.gray('Default login:'));\r\n console.log(` Username: ${pc.cyan('admin')}`);\r\n console.log(` Password: ${pc.cyan('Admin@123')}`);\r\n }\r\n\r\n console.log();\r\n}\r\n\r\nmain();\r\n","import type { CLIArgs, ProjectType, BackendFramework, FrontendFramework, UILibrary } from './types.js';\r\n\r\nconst validProjectTypes: ProjectType[] = ['fullstack', 'backend', 'frontend'];\r\nconst validBackends: BackendFramework[] = ['dotnet', 'spring', 'nestjs'];\r\nconst validFrontendFrameworks: FrontendFramework[] = ['vue', 'react'];\r\nconst validUILibraries: UILibrary[] = ['vuetify', 'primevue', 'primereact', 'mui'];\r\n\r\nexport function parseArgs(): CLIArgs {\r\n const args = process.argv.slice(2);\r\n const result: CLIArgs = {};\r\n\r\n let i = 0;\r\n while (i < args.length) {\r\n const arg = args[i];\r\n\r\n // Handle flags\r\n if (arg === '-h' || arg === '--help') {\r\n result.help = true;\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-v' || arg === '--version') {\r\n result.version = true;\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-i' || arg === '--install') {\r\n result.install = true;\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-r' || arg === '--root') {\r\n result.root = true;\r\n i++;\r\n continue;\r\n }\r\n\r\n // Handle options with values\r\n if (arg === '-t' || arg === '--type') {\r\n const value = args[++i];\r\n if (isValidProjectType(value)) {\r\n result.type = value;\r\n } else {\r\n console.warn(`Warning: Invalid project type \"${value}\". Valid options: ${validProjectTypes.join(', ')}`);\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-b' || arg === '--backend') {\r\n const value = args[++i];\r\n if (isValidBackend(value)) {\r\n result.backend = value;\r\n } else {\r\n console.warn(`Warning: Invalid backend \"${value}\". Valid options: ${validBackends.join(', ')}`);\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-f' || arg === '--framework') {\r\n const value = args[++i];\r\n if (isValidFrontendFramework(value)) {\r\n result.framework = value;\r\n } else {\r\n console.warn(`Warning: Invalid frontend framework \"${value}\". Valid options: ${validFrontendFrameworks.join(', ')}`);\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-u' || arg === '--ui') {\r\n const value = args[++i];\r\n if (isValidUI(value)) {\r\n result.ui = value;\r\n } else {\r\n console.warn(`Warning: Invalid UI library \"${value}\". Valid options: ${validUILibraries.join(', ')}`);\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n if (arg === '-n' || arg === '--name') {\r\n const value = args[++i];\r\n if (isValidProjectName(value)) {\r\n result.projectName = value;\r\n } else {\r\n console.warn(`Warning: Project name should be in \"Company.Project\" format`);\r\n }\r\n i++;\r\n continue;\r\n }\r\n\r\n // If not a flag, treat as project path (first positional argument)\r\n if (!arg.startsWith('-') && !result.projectPath) {\r\n result.projectPath = arg;\r\n }\r\n\r\n i++;\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction isValidProjectType(value: string | undefined): value is ProjectType {\r\n return value !== undefined && validProjectTypes.includes(value as ProjectType);\r\n}\r\n\r\nfunction isValidBackend(value: string | undefined): value is BackendFramework {\r\n return value !== undefined && validBackends.includes(value as BackendFramework);\r\n}\r\n\r\nfunction isValidFrontendFramework(value: string | undefined): value is FrontendFramework {\r\n return value !== undefined && validFrontendFrameworks.includes(value as FrontendFramework);\r\n}\r\n\r\nfunction isValidUI(value: string | undefined): value is UILibrary {\r\n return value !== undefined && validUILibraries.includes(value as UILibrary);\r\n}\r\n\r\nfunction isValidProjectName(value: string | undefined): boolean {\r\n if (!value) return false;\r\n // Validate Company.Project format\r\n const pattern = /^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)+$/;\r\n return pattern.test(value);\r\n}\r\n","import * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport type { CLIArgs, ProjectConfig, ProjectType, BackendFramework, FrontendFramework, UILibrary } from './types.js';\r\n\r\nexport async function runInteractivePrompts(cliArgs: CLIArgs): Promise<ProjectConfig | symbol> {\r\n // Project path\r\n let projectPath = cliArgs.projectPath;\r\n if (!projectPath) {\r\n const result = await p.text({\r\n message: 'Where should we create your project?',\r\n placeholder: './my-app',\r\n defaultValue: './my-app',\r\n validate: (value) => {\r\n if (!value) return 'Please enter a directory path';\r\n const resolvedPath = path.resolve(value);\r\n if (fs.existsSync(resolvedPath) && fs.readdirSync(resolvedPath).length > 0) {\r\n return 'Directory exists and is not empty';\r\n }\r\n return undefined;\r\n },\r\n });\r\n if (p.isCancel(result)) return result;\r\n projectPath = result;\r\n }\r\n\r\n // Project type\r\n let projectType = cliArgs.type;\r\n if (!projectType) {\r\n const result = await p.select({\r\n message: 'What type of project would you like to create?',\r\n options: [\r\n {\r\n value: 'fullstack' as ProjectType,\r\n label: 'Fullstack',\r\n hint: 'Backend + Frontend + Docker',\r\n },\r\n {\r\n value: 'backend' as ProjectType,\r\n label: 'Backend only',\r\n hint: 'API service or microservice',\r\n },\r\n {\r\n value: 'frontend' as ProjectType,\r\n label: 'Frontend only',\r\n hint: 'SPA with external API',\r\n },\r\n ],\r\n });\r\n if (p.isCancel(result)) return result;\r\n projectType = result;\r\n }\r\n\r\n // Backend framework (skip for frontend-only)\r\n let backend: BackendFramework = cliArgs.backend || 'dotnet';\r\n if (projectType !== 'frontend' && !cliArgs.backend) {\r\n const result = await p.select({\r\n message: 'Which backend framework would you like to use?',\r\n options: [\r\n {\r\n value: 'dotnet' as BackendFramework,\r\n label: '.NET 8',\r\n hint: 'Clean Architecture, CQRS, Entity Framework',\r\n },\r\n {\r\n value: 'spring' as BackendFramework,\r\n label: 'Spring Boot 3',\r\n hint: 'Clean Architecture, Java 21',\r\n },\r\n {\r\n value: 'nestjs' as BackendFramework,\r\n label: 'NestJS',\r\n hint: 'Clean Architecture, TypeScript',\r\n },\r\n ],\r\n });\r\n if (p.isCancel(result)) return result;\r\n backend = result;\r\n }\r\n\r\n // Frontend framework (skip for backend-only)\r\n let frontendFramework: FrontendFramework = cliArgs.framework || 'vue';\r\n if (projectType !== 'backend' && !cliArgs.framework) {\r\n const result = await p.select({\r\n message: 'Which frontend framework would you like to use?',\r\n options: [\r\n {\r\n value: 'vue' as FrontendFramework,\r\n label: 'Vue 3',\r\n hint: 'Composition API, Pinia, File-based routing',\r\n },\r\n {\r\n value: 'react' as FrontendFramework,\r\n label: 'React 18',\r\n hint: 'Zustand, React Router v6, TypeScript',\r\n },\r\n ],\r\n });\r\n if (p.isCancel(result)) return result;\r\n frontendFramework = result;\r\n }\r\n\r\n // UI library (skip for backend-only, options depend on frontend framework)\r\n let ui: UILibrary = cliArgs.ui || (frontendFramework === 'vue' ? 'vuetify' : 'mui');\r\n if (projectType !== 'backend' && !cliArgs.ui) {\r\n const vueOptions = [\r\n {\r\n value: 'vuetify' as UILibrary,\r\n label: 'Vuetify',\r\n hint: 'Material Design 3, 80+ components',\r\n },\r\n {\r\n value: 'primevue' as UILibrary,\r\n label: 'PrimeVue',\r\n hint: 'Aura theme, 90+ components',\r\n },\r\n ];\r\n\r\n const reactOptions = [\r\n {\r\n value: 'mui' as UILibrary,\r\n label: 'MUI (Material UI)',\r\n hint: 'Material Design, most popular React UI library',\r\n },\r\n {\r\n value: 'primereact' as UILibrary,\r\n label: 'PrimeReact',\r\n hint: 'Enterprise-grade, 90+ components',\r\n },\r\n ];\r\n\r\n const result = await p.select({\r\n message: 'Which UI library would you like to use?',\r\n options: frontendFramework === 'vue' ? vueOptions : reactOptions,\r\n });\r\n if (p.isCancel(result)) return result;\r\n ui = result;\r\n }\r\n\r\n // Project name (for namespaces) - only for dotnet/spring backends\r\n let projectName: string | undefined = cliArgs.projectName;\r\n const needsNamespace = projectType !== 'frontend' && (backend === 'dotnet' || backend === 'spring');\r\n\r\n if (needsNamespace && !projectName) {\r\n // Generate default name from project path\r\n const dirName = path.basename(path.resolve(projectPath));\r\n const defaultName = `MyCompany.${toPascalCase(dirName)}`;\r\n\r\n const result = await p.text({\r\n message: 'Project namespace (for .NET/Java packages)',\r\n placeholder: defaultName,\r\n defaultValue: defaultName,\r\n validate: (value) => {\r\n if (!value) return 'Please enter a project namespace';\r\n const pattern = /^[A-Za-z][A-Za-z0-9]*(\\.[A-Za-z][A-Za-z0-9]*)+$/;\r\n if (!pattern.test(value)) {\r\n return 'Namespace must be in \"Company.Project\" format (e.g., MyCompany.MyApp)';\r\n }\r\n return undefined;\r\n },\r\n });\r\n if (p.isCancel(result)) return result;\r\n projectName = result;\r\n }\r\n\r\n // Place in root option (for backend-only or frontend-only)\r\n let placeInRoot = cliArgs.root ?? false;\r\n if (projectType !== 'fullstack' && cliArgs.root === undefined) {\r\n const result = await p.confirm({\r\n message: 'Place files directly in project root? (No for subfolder)',\r\n initialValue: false,\r\n });\r\n if (p.isCancel(result)) return result;\r\n placeInRoot = result;\r\n }\r\n\r\n // Install dependencies\r\n let installDeps = cliArgs.install ?? false;\r\n if (cliArgs.install === undefined) {\r\n const result = await p.confirm({\r\n message: 'Install dependencies after creation?',\r\n initialValue: true,\r\n });\r\n if (p.isCancel(result)) return result;\r\n installDeps = result;\r\n }\r\n\r\n // Show summary\r\n console.log();\r\n const summaryLines = [\r\n `${pc.cyan('Project path:')} ${projectPath}`,\r\n `${pc.cyan('Project type:')} ${projectType}`,\r\n ];\r\n\r\n if (projectType !== 'frontend') {\r\n summaryLines.push(`${pc.cyan('Backend:')} ${getBackendLabel(backend)}`);\r\n }\r\n if (projectType !== 'backend') {\r\n summaryLines.push(`${pc.cyan('Frontend:')} ${getFrontendLabel(frontendFramework)}`);\r\n summaryLines.push(`${pc.cyan('UI Library:')} ${getUILabel(ui)}`);\r\n }\r\n if (needsNamespace && projectName) {\r\n summaryLines.push(`${pc.cyan('Namespace:')} ${projectName}`);\r\n }\r\n if (projectType !== 'fullstack') {\r\n summaryLines.push(`${pc.cyan('Place in root:')} ${placeInRoot ? 'Yes' : 'No (subfolder)'}`);\r\n }\r\n summaryLines.push(`${pc.cyan('Install deps:')} ${installDeps ? 'Yes' : 'No'}`);\r\n\r\n p.note(summaryLines.join('\\n'), 'Configuration');\r\n\r\n const shouldContinue = await p.confirm({\r\n message: 'Create project with these settings?',\r\n initialValue: true,\r\n });\r\n if (p.isCancel(shouldContinue) || !shouldContinue) {\r\n return p.isCancel(shouldContinue) ? shouldContinue : Symbol('cancelled');\r\n }\r\n\r\n return {\r\n projectPath,\r\n projectType,\r\n backend,\r\n frontendFramework,\r\n ui,\r\n projectName,\r\n installDeps,\r\n placeInRoot,\r\n };\r\n}\r\n\r\nfunction toPascalCase(str: string): string {\r\n return str\r\n .replace(/[-_\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\r\n .replace(/^(.)/, (c) => c.toUpperCase());\r\n}\r\n\r\nfunction getBackendLabel(backend: BackendFramework): string {\r\n const labels: Record<BackendFramework, string> = {\r\n dotnet: '.NET 8',\r\n spring: 'Spring Boot 3',\r\n nestjs: 'NestJS',\r\n };\r\n return labels[backend];\r\n}\r\n\r\nfunction getFrontendLabel(framework: FrontendFramework): string {\r\n const labels: Record<FrontendFramework, string> = {\r\n vue: 'Vue 3',\r\n react: 'React 18',\r\n };\r\n return labels[framework];\r\n}\r\n\r\nfunction getUILabel(ui: UILibrary): string {\r\n const labels: Record<UILibrary, string> = {\r\n vuetify: 'Vuetify (Material Design)',\r\n primevue: 'PrimeVue (Aura Theme)',\r\n mui: 'MUI (Material UI)',\r\n primereact: 'PrimeReact',\r\n };\r\n return labels[ui];\r\n}\r\n","import * as p from '@clack/prompts';\r\nimport pc from 'picocolors';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport type { ProjectConfig } from './types.js';\r\nimport { downloadTemplate, copyRootFiles } from './utils/download.js';\r\nimport { renameProject } from './utils/rename.js';\r\nimport { installDependencies } from './utils/package-manager.js';\r\n\r\n// GitHub repository for templates\r\nconst REPO = 'abuhanna/app-template';\r\n\r\nexport async function generateProject(config: ProjectConfig): Promise<void> {\r\n const absolutePath = path.resolve(config.projectPath);\r\n\r\n // Create project directory\r\n if (!fs.existsSync(absolutePath)) {\r\n fs.mkdirSync(absolutePath, { recursive: true });\r\n }\r\n\r\n const spinner = p.spinner();\r\n\r\n // Step 1: Download templates\r\n spinner.start('Downloading templates...');\r\n\r\n try {\r\n // Download backend (if not frontend-only)\r\n if (config.projectType !== 'frontend') {\r\n const sourceFolder = `backend-${config.backend}`;\r\n // For fullstack: use 'backend', for backend-only: use subfolder or root\r\n let destFolder: string;\r\n if (config.projectType === 'fullstack') {\r\n destFolder = 'backend';\r\n } else {\r\n destFolder = config.placeInRoot ? '' : 'backend';\r\n }\r\n const destPath = destFolder ? path.join(absolutePath, destFolder) : absolutePath;\r\n await downloadTemplate(REPO, sourceFolder, destPath);\r\n spinner.message(`Downloaded ${sourceFolder}`);\r\n }\r\n\r\n // Download frontend (if not backend-only)\r\n if (config.projectType !== 'backend') {\r\n const sourceFolder = `frontend-${config.ui}`;\r\n // For fullstack: use 'frontend', for frontend-only: use subfolder or root\r\n let destFolder: string;\r\n if (config.projectType === 'fullstack') {\r\n destFolder = 'frontend';\r\n } else {\r\n destFolder = config.placeInRoot ? '' : 'frontend';\r\n }\r\n const destPath = destFolder ? path.join(absolutePath, destFolder) : absolutePath;\r\n await downloadTemplate(REPO, sourceFolder, destPath);\r\n spinner.message(`Downloaded ${sourceFolder}`);\r\n }\r\n\r\n // Download common files (docker, scripts, etc.)\r\n await copyRootFiles(REPO, absolutePath, config);\r\n spinner.message('Downloaded configuration files');\r\n\r\n spinner.stop('Templates downloaded');\r\n } catch (error) {\r\n spinner.stop('Download failed');\r\n throw error;\r\n }\r\n\r\n // Step 2: Update folder references in common files\r\n spinner.start('Updating configuration files...');\r\n try {\r\n await updateFolderReferences(absolutePath, config);\r\n spinner.stop('Configuration updated');\r\n } catch (error) {\r\n spinner.stop('Configuration update failed');\r\n throw error;\r\n }\r\n\r\n // Step 3: Rename project namespaces (only for dotnet/spring)\r\n if (config.projectName && config.projectName !== 'App.Template') {\r\n spinner.start('Renaming project namespaces...');\r\n\r\n try {\r\n await renameProject(absolutePath, config);\r\n spinner.stop('Project namespaces updated');\r\n } catch (error) {\r\n spinner.stop('Namespace rename failed');\r\n throw error;\r\n }\r\n }\r\n\r\n // Step 4: Install dependencies (if requested)\r\n if (config.installDeps) {\r\n spinner.start('Installing dependencies (this may take a while)...');\r\n\r\n try {\r\n await installDependencies(absolutePath, config);\r\n spinner.stop('Dependencies installed');\r\n } catch (error) {\r\n spinner.stop('Installation failed');\r\n const errorMessage = error instanceof Error ? error.message : String(error);\r\n console.log(pc.yellow(` Warning: Dependency installation failed: ${errorMessage}`));\r\n console.log(pc.gray(' You can install manually by running npm install in the project directory'));\r\n }\r\n }\r\n\r\n // Step 5: Setup environment files\r\n await setupEnvironmentFiles(absolutePath, config);\r\n\r\n // Step 6: Cleanup Docker files for Fullstack projects\r\n // (Fullstack uses root Dockerfile, so we remove the individual ones)\r\n if (config.projectType === 'fullstack') {\r\n spinner.start('Cleaning up Docker configuration...');\r\n try {\r\n cleanupFullstackDockerFiles(absolutePath);\r\n spinner.stop('Docker configuration cleaned up');\r\n } catch {\r\n // Ignore errors if files don't exist\r\n spinner.stop('Docker cleanup skipped');\r\n }\r\n }\r\n\r\n // Step 7: Create appsettings.Development.json from example (for .NET projects)\r\n if (config.projectType !== 'frontend' && config.backend === 'dotnet') {\r\n await createAppSettingsFromExample(absolutePath, config);\r\n }\r\n}\r\n\r\n/**\r\n * Remove individual Docker files from backend/frontend folders for fullstack projects\r\n */\r\nfunction cleanupFullstackDockerFiles(projectPath: string): void {\r\n const filesToDelete = [\r\n 'backend/Dockerfile',\r\n 'backend/docker-compose.yml',\r\n 'frontend/Dockerfile',\r\n 'frontend/docker-compose.yml',\r\n ];\r\n\r\n for (const file of filesToDelete) {\r\n const filePath = path.join(projectPath, file);\r\n if (fs.existsSync(filePath)) {\r\n fs.rmSync(filePath);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Setup environment files based on project stack\r\n */\r\nasync function setupEnvironmentFiles(projectPath: string, config: ProjectConfig): Promise<void> {\r\n // 1. Frontend Environment\r\n if (config.projectType !== 'backend') {\r\n let frontendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n frontendDir = path.join(projectPath, 'frontend');\r\n } else {\r\n frontendDir = config.placeInRoot ? projectPath : path.join(projectPath, 'frontend');\r\n }\r\n\r\n const envExample = path.join(frontendDir, '.env.example');\r\n const envDest = path.join(frontendDir, '.env');\r\n\r\n if (fs.existsSync(envExample) && !fs.existsSync(envDest)) {\r\n fs.copyFileSync(envExample, envDest);\r\n\r\n // Update VITE_BACKEND_TYPE for fullstack projects\r\n if (config.projectType === 'fullstack') {\r\n let content = fs.readFileSync(envDest, 'utf-8');\r\n let backendType = 'dotnet';\r\n if (config.backend === 'nestjs') backendType = 'nest';\r\n if (config.backend === 'spring') backendType = 'spring';\r\n \r\n // Replace logical default 'dotnet' with actual selection\r\n // Also handle if .env.example doesn't have it set to dotnet by using regex\r\n content = content.replace(/^VITE_BACKEND_TYPE=.*$/m, `VITE_BACKEND_TYPE=${backendType}`);\r\n \r\n fs.writeFileSync(envDest, content);\r\n }\r\n }\r\n }\r\n\r\n // 2. Backend Environment\r\n if (config.projectType !== 'frontend') {\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else {\r\n backendDir = config.placeInRoot ? projectPath : path.join(projectPath, 'backend');\r\n }\r\n\r\n // NestJS\r\n if (config.backend === 'nestjs') {\r\n const envExample = path.join(backendDir, '.env.example');\r\n const envDest = path.join(backendDir, '.env');\r\n if (fs.existsSync(envExample) && !fs.existsSync(envDest)) {\r\n fs.copyFileSync(envExample, envDest);\r\n }\r\n }\r\n\r\n // Spring Boot\r\n if (config.backend === 'spring') {\r\n const ymlExample = path.join(backendDir, 'api', 'src', 'main', 'resources', 'application.example.yml');\r\n const ymlDest = path.join(backendDir, 'api', 'src', 'main', 'resources', 'application.yml');\r\n if (fs.existsSync(ymlExample) && !fs.existsSync(ymlDest)) {\r\n fs.copyFileSync(ymlExample, ymlDest);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Create appsettings.Development.json from appsettings.example.json for .NET projects\r\n */\r\nasync function createAppSettingsFromExample(projectPath: string, config: ProjectConfig): Promise<void> {\r\n // Determine backend directory\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else if (config.placeInRoot) {\r\n backendDir = projectPath;\r\n } else {\r\n backendDir = path.join(projectPath, 'backend');\r\n }\r\n\r\n // Find WebAPI project directory (it contains appsettings.example.json)\r\n const presentationDir = path.join(backendDir, 'src', 'Presentation');\r\n if (!fs.existsSync(presentationDir)) return;\r\n\r\n const entries = fs.readdirSync(presentationDir, { withFileTypes: true });\r\n for (const entry of entries) {\r\n if (entry.isDirectory() && entry.name.endsWith('.WebAPI')) {\r\n const webApiDir = path.join(presentationDir, entry.name);\r\n const examplePath = path.join(webApiDir, 'appsettings.example.json');\r\n const devPath = path.join(webApiDir, 'appsettings.Development.json');\r\n\r\n if (fs.existsSync(examplePath) && !fs.existsSync(devPath)) {\r\n fs.copyFileSync(examplePath, devPath);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Update folder references in common files\r\n * Replaces backend-dotnet/backend-spring/backend-nestjs with backend\r\n * Replaces frontend-vuetify/frontend-primevue with frontend\r\n */\r\nasync function updateFolderReferences(projectPath: string, config: ProjectConfig): Promise<void> {\r\n const filesToUpdate = [\r\n 'Dockerfile',\r\n 'docker-compose.yml',\r\n 'docker-compose.staging.yml',\r\n 'docker-compose.production.yml',\r\n 'docker-compose.backend.yml',\r\n 'docker-compose.frontend.yml',\r\n 'Makefile',\r\n 'CLAUDE.md',\r\n 'README.md',\r\n ];\r\n\r\n // Determine the new folder names based on project type\r\n const backendReplace = config.placeInRoot && config.projectType === 'backend' ? '.' : 'backend';\r\n const frontendReplace = config.placeInRoot && config.projectType === 'frontend' ? '.' : 'frontend';\r\n\r\n for (const file of filesToUpdate) {\r\n const filePath = path.join(projectPath, file);\r\n if (fs.existsSync(filePath)) {\r\n let content = fs.readFileSync(filePath, 'utf-8');\r\n\r\n // Replace backend folder references\r\n if (config.projectType !== 'frontend') {\r\n content = content\r\n .replace(/backend-dotnet/g, backendReplace)\r\n .replace(/backend-spring/g, backendReplace)\r\n .replace(/backend-nestjs/g, backendReplace);\r\n }\r\n\r\n // Replace frontend folder references\r\n if (config.projectType !== 'backend') {\r\n content = content\r\n .replace(/frontend-vuetify/g, frontendReplace)\r\n .replace(/frontend-primevue/g, frontendReplace)\r\n .replace(/frontend-primereact/g, frontendReplace)\r\n .replace(/frontend-mui/g, frontendReplace);\r\n }\r\n\r\n fs.writeFileSync(filePath, content);\r\n }\r\n }\r\n\r\n // Also update docker folder files\r\n const dockerFolder = path.join(projectPath, 'docker');\r\n if (fs.existsSync(dockerFolder)) {\r\n updateDockerFolderFiles(dockerFolder, config, backendReplace, frontendReplace);\r\n }\r\n}\r\n\r\n/**\r\n * Recursively update files in the docker folder\r\n */\r\nfunction updateDockerFolderFiles(\r\n dir: string,\r\n config: ProjectConfig,\r\n backendReplace: string,\r\n frontendReplace: string\r\n): void {\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n updateDockerFolderFiles(fullPath, config, backendReplace, frontendReplace);\r\n } else if (entry.isFile()) {\r\n let content = fs.readFileSync(fullPath, 'utf-8');\r\n\r\n if (config.projectType !== 'frontend') {\r\n content = content\r\n .replace(/backend-dotnet/g, backendReplace)\r\n .replace(/backend-spring/g, backendReplace)\r\n .replace(/backend-nestjs/g, backendReplace);\r\n }\r\n\r\n if (config.projectType !== 'backend') {\r\n content = content\r\n .replace(/frontend-vuetify/g, frontendReplace)\r\n .replace(/frontend-primevue/g, frontendReplace)\r\n .replace(/frontend-primereact/g, frontendReplace)\r\n .replace(/frontend-mui/g, frontendReplace);\r\n }\r\n\r\n fs.writeFileSync(fullPath, content);\r\n }\r\n }\r\n}\r\n","import degit from 'degit';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport type { ProjectConfig } from '../types.js';\r\n\r\n/**\r\n * Download a specific folder from the GitHub repository\r\n */\r\nexport async function downloadTemplate(repo: string, folder: string, destPath: string): Promise<void> {\r\n const source = `${repo}/${folder}`;\r\n const emitter = degit(source, {\r\n cache: false,\r\n force: true,\r\n verbose: false,\r\n });\r\n\r\n await emitter.clone(destPath);\r\n}\r\n\r\n\r\n/**\r\n * Download root configuration files based on project type\r\n */\r\nexport async function copyRootFiles(repo: string, destPath: string, config: ProjectConfig): Promise<void> {\r\n // Common files for all projects\r\n // REMOVED 'README.md' from here\r\n const commonFiles = [\r\n '.env.example',\r\n '.gitignore',\r\n 'CLAUDE.md',\r\n ];\r\n\r\n // Create a temporary directory for the full repo download\r\n const tempDir = path.join(destPath, '.temp-download');\r\n\r\n try {\r\n // Download the entire repository to temp dir\r\n const emitter = degit(repo, {\r\n cache: false,\r\n force: true,\r\n verbose: false,\r\n });\r\n\r\n await emitter.clone(tempDir);\r\n\r\n // 1. Copy Common Files\r\n for (const file of commonFiles) {\r\n copyFileFromTemp(tempDir, file, destPath, file);\r\n }\r\n\r\n // 2. Dynamic README Selection\r\n if (config.projectType === 'fullstack') {\r\n // Fullstack README\r\n const readmeTemplate = `docker/templates/root/README.fullstack.${config.backend}.md`;\r\n copyFileFromTemp(tempDir, readmeTemplate, destPath, 'README.md');\r\n } else if (!config.placeInRoot) {\r\n // Split project (subdirectory) - generic README\r\n const readmeTemplate = `docker/templates/root/README.multirepo.md`;\r\n copyFileFromTemp(tempDir, readmeTemplate, destPath, 'README.md');\r\n } \r\n // If placeInRoot is true (Backend/Frontend Only in root), we do NOTHING.\r\n // The component's own README.md has already been downloaded to the root by downloadTemplate logic.\r\n // We effectively preserve it.\r\n\r\n // 3. Fullstack Specific Logic\r\n if (config.projectType === 'fullstack') {\r\n // Copy root docker folder (nginx, supervisor, etc.)\r\n // We exclude templates from the final copy implicitly by not copying the 'templates' subfolder if we iterate, \r\n // or we just copy 'docker' and then delete 'templates' later. \r\n // For simplicity, let's copy 'docker/nginx' and 'docker/supervisor' explicitly.\r\n copyDirectoryFromTemp(tempDir, 'docker/nginx', path.join(destPath, 'docker/nginx'));\r\n copyDirectoryFromTemp(tempDir, 'docker/supervisor', path.join(destPath, 'docker/supervisor'));\r\n\r\n // Select and copy root Dockerfile\r\n const dockerfileTemplate = `docker/templates/root/Dockerfile.${config.backend}`;\r\n copyFileFromTemp(tempDir, dockerfileTemplate, destPath, 'Dockerfile');\r\n\r\n // Select and copy root docker-compose.yml\r\n const composeTemplate = `docker/templates/root/docker-compose.${config.backend}.yml`;\r\n copyFileFromTemp(tempDir, composeTemplate, destPath, 'docker-compose.yml');\r\n\r\n // Select and copy root supervisord.conf\r\n const supervisorTemplate = `docker/templates/root/supervisord.${config.backend}.conf`;\r\n copyFileFromTemp(tempDir, supervisorTemplate, destPath, 'docker/supervisor/supervisord.conf');\r\n \r\n // Copy Makefile if it exists\r\n copyFileFromTemp(tempDir, 'Makefile', destPath, 'Makefile');\r\n copyFileFromTemp(tempDir, 'docker-compose.staging.yml', destPath, 'docker-compose.staging.yml');\r\n copyFileFromTemp(tempDir, 'docker-compose.production.yml', destPath, 'docker-compose.production.yml');\r\n }\r\n\r\n // 3. Non-Fullstack Logic\r\n // We do NOT copy root Dockerfile or docker-compose.yml.\r\n // We do NOT copy the 'docker' folder (standalone backends/frontends are self-contained).\r\n\r\n } finally {\r\n // Clean up temp directory\r\n if (fs.existsSync(tempDir)) {\r\n fs.rmSync(tempDir, { recursive: true, force: true });\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Helper to copy a file from temp dir to destination\r\n */\r\nfunction copyFileFromTemp(tempDir: string, srcRelative: string, destBase: string, destRelative: string): void {\r\n const srcPath = path.join(tempDir, srcRelative);\r\n const destPath = path.join(destBase, destRelative);\r\n\r\n if (fs.existsSync(srcPath)) {\r\n const parentDir = path.dirname(destPath);\r\n if (!fs.existsSync(parentDir)) {\r\n fs.mkdirSync(parentDir, { recursive: true });\r\n }\r\n fs.copyFileSync(srcPath, destPath);\r\n }\r\n}\r\n\r\n/**\r\n * Helper to copy a directory from temp dir to destination\r\n */\r\nfunction copyDirectoryFromTemp(tempDir: string, srcRelative: string, destPath: string): void {\r\n const srcPath = path.join(tempDir, srcRelative);\r\n\r\n if (fs.existsSync(srcPath)) {\r\n if (!fs.existsSync(destPath)) {\r\n fs.mkdirSync(destPath, { recursive: true });\r\n }\r\n fs.cpSync(srcPath, destPath, { recursive: true });\r\n }\r\n}\r\n","import path from 'path';\r\nimport fs from 'fs';\r\nimport type { ProjectConfig } from '../types.js';\r\n\r\n/**\r\n * Rename project files and update namespaces\r\n * Only called when config.projectName is set (for dotnet/spring backends)\r\n */\r\nexport async function renameProject(projectPath: string, config: ProjectConfig): Promise<void> {\r\n if (!config.projectName) return;\r\n\r\n const newDotName = config.projectName;\r\n const newNamespace = config.projectName.replace(/\\./g, '');\r\n\r\n // Rename backend project files (for .NET)\r\n if (config.projectType !== 'frontend' && config.backend === 'dotnet') {\r\n await renameDotNetProject(projectPath, config, newDotName, newNamespace);\r\n }\r\n\r\n // Rename backend project files (for Spring)\r\n if (config.projectType !== 'frontend' && config.backend === 'spring') {\r\n await renameSpringProject(projectPath, config, newDotName);\r\n }\r\n\r\n // Update common files\r\n await updateCommonFiles(projectPath, config, newDotName, newNamespace);\r\n}\r\n\r\n/**\r\n * Rename .NET project structure\r\n */\r\nasync function renameDotNetProject(\r\n projectPath: string,\r\n config: ProjectConfig,\r\n newDotName: string,\r\n newNamespace: string\r\n): Promise<void> {\r\n // Determine backend directory based on project type and placeInRoot option\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else if (config.placeInRoot) {\r\n backendDir = projectPath;\r\n } else {\r\n backendDir = path.join(projectPath, 'backend');\r\n }\r\n\r\n if (!fs.existsSync(backendDir)) return;\r\n\r\n // Define folder mappings\r\n const folderMappings = [\r\n ['src/Core/App.Template.Domain', `src/Core/${newDotName}.Domain`],\r\n ['src/Core/App.Template.Application', `src/Core/${newDotName}.Application`],\r\n ['src/Infrastructure/App.Template.Infrastructure', `src/Infrastructure/${newDotName}.Infrastructure`],\r\n ['src/Presentation/App.Template.WebAPI', `src/Presentation/${newDotName}.WebAPI`],\r\n ['tests/App.Template.Domain.Tests', `tests/${newDotName}.Domain.Tests`],\r\n ['tests/App.Template.Application.Tests', `tests/${newDotName}.Application.Tests`],\r\n ];\r\n\r\n // Rename folders\r\n for (const [oldFolder, newFolder] of folderMappings) {\r\n const oldPath = path.join(backendDir, oldFolder);\r\n const newPath = path.join(backendDir, newFolder);\r\n\r\n if (fs.existsSync(oldPath)) {\r\n fs.renameSync(oldPath, newPath);\r\n }\r\n }\r\n\r\n // Rename .csproj files\r\n await renameFilesWithPattern(backendDir, /App\\.Template\\.(.*)\\.csproj$/, (match) => {\r\n return `${newDotName}.${match[1]}.csproj`;\r\n });\r\n\r\n // Rename solution file\r\n const oldSlnPath = path.join(backendDir, 'App.Template.sln');\r\n const newSlnPath = path.join(backendDir, `${newDotName}.sln`);\r\n if (fs.existsSync(oldSlnPath)) {\r\n fs.renameSync(oldSlnPath, newSlnPath);\r\n }\r\n\r\n // Update file contents in all relevant files\r\n const extensions = ['.cs', '.csproj', '.sln', '.json'];\r\n await updateFileContents(backendDir, extensions, (content) => {\r\n return content\r\n .replace(/App\\.Template/g, newDotName)\r\n .replace(/AppTemplate/g, newNamespace);\r\n });\r\n}\r\n\r\n/**\r\n * Rename Spring Boot project structure\r\n */\r\nasync function renameSpringProject(\r\n projectPath: string,\r\n config: ProjectConfig,\r\n newDotName: string\r\n): Promise<void> {\r\n // Determine backend directory based on project type and placeInRoot option\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else if (config.placeInRoot) {\r\n backendDir = projectPath;\r\n } else {\r\n backendDir = path.join(projectPath, 'backend');\r\n }\r\n\r\n if (!fs.existsSync(backendDir)) return;\r\n\r\n // Convert project name to Java package format\r\n const packageName = newDotName.toLowerCase().replace(/\\./g, '.');\r\n const artifactId = newDotName.toLowerCase().replace(/\\./g, '-');\r\n\r\n // Update pom.xml\r\n const pomPath = path.join(backendDir, 'pom.xml');\r\n if (fs.existsSync(pomPath)) {\r\n let content = fs.readFileSync(pomPath, 'utf-8');\r\n content = content\r\n .replace(/<groupId>com\\.apptemplate<\\/groupId>/g, `<groupId>${packageName}<\\/groupId>`)\r\n .replace(/<artifactId>apptemplate<\\/artifactId>/g, `<artifactId>${artifactId}<\\/artifactId>`)\r\n .replace(/com\\.apptemplate/g, packageName);\r\n fs.writeFileSync(pomPath, content);\r\n }\r\n\r\n // Update Java files\r\n await updateFileContents(backendDir, ['.java'], (content) => {\r\n return content.replace(/com\\.apptemplate/g, packageName);\r\n });\r\n}\r\n\r\n/**\r\n * Update common files (Dockerfile, docker-compose, etc.)\r\n */\r\nasync function updateCommonFiles(\r\n projectPath: string,\r\n _config: ProjectConfig,\r\n newDotName: string,\r\n newNamespace: string\r\n): Promise<void> {\r\n const filesToUpdate = [\r\n 'Dockerfile',\r\n 'docker-compose.yml',\r\n 'docker-compose.staging.yml',\r\n 'docker-compose.production.yml',\r\n 'docker-compose.backend.yml',\r\n 'docker-compose.frontend.yml',\r\n 'Makefile',\r\n 'CLAUDE.md',\r\n 'README.md',\r\n ];\r\n\r\n for (const file of filesToUpdate) {\r\n const filePath = path.join(projectPath, file);\r\n if (fs.existsSync(filePath)) {\r\n let content = fs.readFileSync(filePath, 'utf-8');\r\n content = content\r\n .replace(/App\\.Template/g, newDotName)\r\n .replace(/AppTemplate/g, newNamespace)\r\n .replace(/apptemplate/gi, newNamespace.toLowerCase());\r\n fs.writeFileSync(filePath, content);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Rename files matching a pattern in a directory\r\n */\r\nasync function renameFilesWithPattern(\r\n dir: string,\r\n pattern: RegExp,\r\n replacer: (match: RegExpMatchArray) => string\r\n): Promise<void> {\r\n const files = getAllFiles(dir);\r\n\r\n for (const file of files) {\r\n const fileName = path.basename(file);\r\n const match = fileName.match(pattern);\r\n\r\n if (match) {\r\n const newFileName = replacer(match);\r\n const newPath = path.join(path.dirname(file), newFileName);\r\n fs.renameSync(file, newPath);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Update file contents in a directory\r\n */\r\nasync function updateFileContents(\r\n dir: string,\r\n extensions: string[],\r\n updater: (content: string) => string\r\n): Promise<void> {\r\n const files = getAllFiles(dir);\r\n\r\n for (const file of files) {\r\n const ext = path.extname(file);\r\n if (extensions.includes(ext)) {\r\n let content = fs.readFileSync(file, 'utf-8');\r\n const updatedContent = updater(content);\r\n if (content !== updatedContent) {\r\n fs.writeFileSync(file, updatedContent);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Get all files in a directory recursively\r\n */\r\nfunction getAllFiles(dir: string): string[] {\r\n const files: string[] = [];\r\n\r\n if (!fs.existsSync(dir)) return files;\r\n\r\n const entries = fs.readdirSync(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // Skip node_modules and other common directories\r\n if (!['node_modules', '.git', 'bin', 'obj', 'dist', 'build'].includes(entry.name)) {\r\n files.push(...getAllFiles(fullPath));\r\n }\r\n } else {\r\n files.push(fullPath);\r\n }\r\n }\r\n\r\n return files;\r\n}\r\n","import spawn from 'cross-spawn';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport type { ProjectConfig } from '../types.js';\r\n\r\ntype PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';\r\n\r\n/**\r\n * Detect which package manager is being used\r\n */\r\nexport function detectPackageManager(): PackageManager {\r\n // Check for lockfiles in current directory\r\n const cwd = process.cwd();\r\n\r\n if (fs.existsSync(path.join(cwd, 'bun.lockb'))) return 'bun';\r\n if (fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))) return 'pnpm';\r\n if (fs.existsSync(path.join(cwd, 'yarn.lock'))) return 'yarn';\r\n if (fs.existsSync(path.join(cwd, 'package-lock.json'))) return 'npm';\r\n\r\n // Check npm_config_user_agent environment variable\r\n const userAgent = process.env.npm_config_user_agent;\r\n if (userAgent) {\r\n if (userAgent.includes('bun')) return 'bun';\r\n if (userAgent.includes('pnpm')) return 'pnpm';\r\n if (userAgent.includes('yarn')) return 'yarn';\r\n }\r\n\r\n // Default to npm\r\n return 'npm';\r\n}\r\n\r\n/**\r\n * Install dependencies for the project\r\n */\r\nexport async function installDependencies(projectPath: string, config: ProjectConfig): Promise<void> {\r\n const pm = detectPackageManager();\r\n\r\n // Determine frontend directory\r\n let frontendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n frontendDir = path.join(projectPath, 'frontend');\r\n } else if (config.placeInRoot) {\r\n frontendDir = projectPath;\r\n } else {\r\n frontendDir = path.join(projectPath, 'frontend');\r\n }\r\n\r\n // Determine backend directory\r\n let backendDir: string;\r\n if (config.projectType === 'fullstack') {\r\n backendDir = path.join(projectPath, 'backend');\r\n } else if (config.placeInRoot) {\r\n backendDir = projectPath;\r\n } else {\r\n backendDir = path.join(projectPath, 'backend');\r\n }\r\n\r\n // Install frontend dependencies\r\n if (config.projectType !== 'backend') {\r\n const frontendPackageJson = path.join(frontendDir, 'package.json');\r\n if (fs.existsSync(frontendPackageJson)) {\r\n await runInstallCommand(frontendDir, pm);\r\n }\r\n }\r\n\r\n // Install/restore backend dependencies\r\n if (config.projectType !== 'frontend') {\r\n switch (config.backend) {\r\n case 'dotnet': {\r\n const slnFiles = fs.readdirSync(backendDir).filter(f => f.endsWith('.sln'));\r\n if (slnFiles.length > 0) {\r\n await runCommand('dotnet', ['restore'], backendDir);\r\n }\r\n break;\r\n }\r\n case 'spring': {\r\n const pomPath = path.join(backendDir, 'pom.xml');\r\n if (fs.existsSync(pomPath)) {\r\n const mvnwPath = path.join(backendDir, process.platform === 'win32' ? 'mvnw.cmd' : 'mvnw');\r\n if (fs.existsSync(mvnwPath)) {\r\n await runCommand(mvnwPath, ['install', '-DskipTests'], backendDir);\r\n } else {\r\n await runCommand('mvn', ['install', '-DskipTests'], backendDir);\r\n }\r\n }\r\n break;\r\n }\r\n case 'nestjs': {\r\n const backendPackageJson = path.join(backendDir, 'package.json');\r\n if (fs.existsSync(backendPackageJson)) {\r\n await runInstallCommand(backendDir, pm);\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Run package manager install command\r\n */\r\nasync function runInstallCommand(cwd: string, pm: PackageManager): Promise<void> {\r\n const installCommands: Record<PackageManager, string[]> = {\r\n npm: ['install'],\r\n yarn: ['install'],\r\n pnpm: ['install'],\r\n bun: ['install'],\r\n };\r\n\r\n await runCommand(pm, installCommands[pm], cwd);\r\n}\r\n\r\n/**\r\n * Run a command in a directory\r\n */\r\nfunction runCommand(command: string, args: string[], cwd: string): Promise<void> {\r\n return new Promise((resolve, reject) => {\r\n const child = spawn(command, args, {\r\n cwd,\r\n stdio: 'pipe',\r\n shell: process.platform === 'win32',\r\n });\r\n\r\n let stderr = '';\r\n\r\n child.stderr?.on('data', (data) => {\r\n stderr += data.toString();\r\n });\r\n\r\n child.on('close', (code) => {\r\n if (code === 0) {\r\n resolve();\r\n } else {\r\n reject(new Error(`Command \"${command} ${args.join(' ')}\" failed with code ${code}: ${stderr}`));\r\n }\r\n });\r\n\r\n child.on('error', (error) => {\r\n reject(error);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Check if a command exists\r\n */\r\nexport function commandExists(command: string): boolean {\r\n try {\r\n const result = spawn.sync(command, ['--version'], {\r\n stdio: 'pipe',\r\n shell: process.platform === 'win32',\r\n });\r\n return result.status === 0;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n"],"mappings":"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","names":["isCancel","pc","p","pc","path","fs","path","fs","path","fs","path","fs","path","fs","spinner","pc","pc","isCancel"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abuhannaa/create-apptemplate",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Create fullstack apps with .NET/Spring/NestJS + Vue (Vuetify/PrimeVue)",
5
5
  "author": "abuhanna",
6
6
  "license": "MIT",