nodejs-quickstart-structure 2.0.1 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +64 -66
  3. package/bin/index.js +5 -2
  4. package/lib/generator.js +10 -4
  5. package/lib/modules/app-setup.js +76 -6
  6. package/lib/modules/auth-setup.js +143 -0
  7. package/lib/modules/caching-setup.js +8 -1
  8. package/lib/modules/config-files.js +6 -0
  9. package/lib/modules/database-setup.js +2 -1
  10. package/lib/modules/project-setup.js +1 -0
  11. package/lib/prompts.js +39 -0
  12. package/package.json +5 -4
  13. package/templates/clean-architecture/js/src/domain/models/User.js +3 -1
  14. package/templates/clean-architecture/js/src/index.js.ejs +2 -0
  15. package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +12 -3
  16. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +25 -2
  17. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +38 -1
  18. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +3 -0
  19. package/templates/clean-architecture/js/src/infrastructure/webserver/server.spec.js.ejs +51 -0
  20. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.spec.js.ejs +14 -0
  21. package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +41 -4
  22. package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +70 -5
  23. package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -6
  24. package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +55 -22
  25. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +10 -5
  26. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +32 -10
  27. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +1 -1
  28. package/templates/clean-architecture/js/src/interfaces/routes/api.js.ejs +15 -0
  29. package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +4 -0
  30. package/templates/clean-architecture/js/src/usecases/CreateUser.js.ejs +34 -0
  31. package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +12 -3
  32. package/templates/clean-architecture/js/src/usecases/DeleteUser.js.ejs +27 -0
  33. package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +9 -1
  34. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js.ejs +36 -0
  35. package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +23 -1
  36. package/templates/clean-architecture/js/src/usecases/GetUserById.js.ejs +36 -0
  37. package/templates/clean-architecture/js/src/usecases/GetUserById.spec.js.ejs +48 -0
  38. package/templates/clean-architecture/js/src/usecases/UpdateUser.js.ejs +28 -0
  39. package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +9 -1
  40. package/templates/clean-architecture/js/src/utils/errorMessages.js +1 -0
  41. package/templates/clean-architecture/js/src/utils/httpCodes.js +2 -0
  42. package/templates/clean-architecture/ts/src/config/env.ts.ejs +12 -3
  43. package/templates/clean-architecture/ts/src/domain/user.ts +3 -1
  44. package/templates/clean-architecture/ts/src/index.ts.ejs +4 -0
  45. package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +71 -10
  46. package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +32 -3
  47. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +43 -9
  48. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +57 -15
  49. package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +57 -24
  50. package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +14 -8
  51. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +33 -10
  52. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +15 -5
  53. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +1 -1
  54. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +9 -1
  55. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts.ejs +16 -0
  56. package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +12 -3
  57. package/templates/clean-architecture/ts/src/usecases/createUser.ts.ejs +35 -0
  58. package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +10 -1
  59. package/templates/clean-architecture/ts/src/usecases/deleteUser.ts.ejs +24 -0
  60. package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +9 -1
  61. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts.ejs +21 -0
  62. package/templates/clean-architecture/ts/src/usecases/getUserById.spec.ts.ejs +55 -0
  63. package/templates/clean-architecture/ts/src/usecases/getUserById.ts.ejs +23 -0
  64. package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +10 -1
  65. package/templates/clean-architecture/ts/src/usecases/updateUser.ts.ejs +25 -0
  66. package/templates/clean-architecture/ts/src/utils/errorMessages.ts +1 -0
  67. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +1 -0
  68. package/templates/common/.cursorrules.ejs +9 -0
  69. package/templates/common/.env.example.ejs +17 -10
  70. package/templates/common/README.md.ejs +63 -18
  71. package/templates/common/auth/js/controllers/authController.js.ejs +170 -0
  72. package/templates/common/auth/js/controllers/authController.spec.js.ejs +148 -0
  73. package/templates/common/auth/js/middleware/authMiddleware.js.ejs +58 -0
  74. package/templates/common/auth/js/middleware/authMiddleware.spec.js.ejs +108 -0
  75. package/templates/common/auth/js/routes/authRoutes.js.ejs +16 -0
  76. package/templates/common/auth/js/services/jwtService.js.ejs +54 -0
  77. package/templates/common/auth/js/services/jwtService.spec.js.ejs +84 -0
  78. package/templates/common/auth/ts/controllers/authController.spec.ts.ejs +161 -0
  79. package/templates/common/auth/ts/controllers/authController.ts.ejs +167 -0
  80. package/templates/common/auth/ts/middleware/authMiddleware.spec.ts.ejs +128 -0
  81. package/templates/common/auth/ts/middleware/authMiddleware.ts.ejs +59 -0
  82. package/templates/common/auth/ts/routes/authRoutes.ts.ejs +20 -0
  83. package/templates/common/auth/ts/services/jwtService.spec.ts.ejs +89 -0
  84. package/templates/common/auth/ts/services/jwtService.ts.ejs +60 -0
  85. package/templates/common/babel.config.js.ejs +5 -0
  86. package/templates/common/caching/clean/js/CreateUser.js.ejs +14 -5
  87. package/templates/common/caching/clean/js/DeleteUser.js.ejs +2 -1
  88. package/templates/common/caching/clean/js/GetUserById.js.ejs +39 -0
  89. package/templates/common/caching/clean/js/UpdateUser.js.ejs +2 -1
  90. package/templates/common/caching/clean/ts/createUser.ts.ejs +14 -6
  91. package/templates/common/caching/clean/ts/deleteUser.ts.ejs +2 -1
  92. package/templates/common/caching/clean/ts/getUserById.ts.ejs +32 -0
  93. package/templates/common/caching/clean/ts/updateUser.ts.ejs +2 -1
  94. package/templates/common/caching/js/memoryCache.spec.js.ejs +2 -0
  95. package/templates/common/caching/js/redisClient.spec.js.ejs +2 -0
  96. package/templates/common/caching/ts/memoryCache.spec.ts.ejs +2 -0
  97. package/templates/common/caching/ts/redisClient.spec.ts.ejs +2 -0
  98. package/templates/common/database/js/models/User.js.ejs +14 -1
  99. package/templates/common/database/js/models/User.js.mongoose.ejs +7 -0
  100. package/templates/common/database/js/models/User.spec.js.ejs +12 -0
  101. package/templates/common/database/js/mongoose.spec.js.ejs +2 -0
  102. package/templates/common/database/ts/models/User.spec.ts.ejs +10 -0
  103. package/templates/common/database/ts/models/User.ts.ejs +17 -0
  104. package/templates/common/database/ts/models/User.ts.mongoose.ejs +8 -0
  105. package/templates/common/database/ts/mongoose.spec.ts.ejs +2 -0
  106. package/templates/common/docker-compose.yml.ejs +12 -0
  107. package/templates/common/ecosystem.config.js.ejs +9 -3
  108. package/templates/common/eslint.config.mjs.ejs +3 -0
  109. package/templates/common/jest.config.js.ejs +13 -9
  110. package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +1 -1
  111. package/templates/common/kafka/js/services/kafkaService.js.ejs +1 -1
  112. package/templates/common/migrations/init.js.ejs +5 -4
  113. package/templates/common/package.json.ejs +11 -2
  114. package/templates/common/prompts/project-context.md.ejs +8 -1
  115. package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +149 -107
  116. package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +88 -47
  117. package/templates/common/swagger.yml.ejs +148 -0
  118. package/templates/common/tsconfig.eslint.json +15 -0
  119. package/templates/common/tsconfig.json +3 -1
  120. package/templates/common/views/ejs/index.ejs +264 -30
  121. package/templates/common/views/ejs/login.ejs.ejs +244 -0
  122. package/templates/common/views/ejs/signup.ejs.ejs +282 -0
  123. package/templates/common/views/pug/index.pug +269 -38
  124. package/templates/common/views/pug/login.pug.ejs +195 -0
  125. package/templates/common/views/pug/signup.pug.ejs +241 -0
  126. package/templates/db/mysql/V1__Initial_Setup.sql.ejs +6 -0
  127. package/templates/db/postgres/V1__Initial_Setup.sql.ejs +6 -0
  128. package/templates/mvc/js/src/config/env.js.ejs +12 -3
  129. package/templates/mvc/js/src/controllers/userController.js.ejs +29 -5
  130. package/templates/mvc/js/src/controllers/userController.spec.js.ejs +27 -12
  131. package/templates/mvc/js/src/graphql/context.js.ejs +14 -3
  132. package/templates/mvc/js/src/graphql/context.spec.js.ejs +36 -21
  133. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +10 -5
  134. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +32 -10
  135. package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +1 -1
  136. package/templates/mvc/js/src/index.js.ejs +16 -3
  137. package/templates/mvc/js/src/routes/api.js.ejs +14 -0
  138. package/templates/mvc/js/src/routes/api.spec.js.ejs +3 -0
  139. package/templates/mvc/js/src/utils/errorMessages.js +1 -0
  140. package/templates/mvc/js/src/utils/httpCodes.js +1 -0
  141. package/templates/mvc/ts/src/config/env.ts.ejs +12 -3
  142. package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +95 -7
  143. package/templates/mvc/ts/src/controllers/userController.ts.ejs +68 -11
  144. package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +36 -23
  145. package/templates/mvc/ts/src/graphql/context.ts.ejs +15 -6
  146. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +32 -10
  147. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +15 -5
  148. package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +1 -1
  149. package/templates/mvc/ts/src/index.ts.ejs +15 -3
  150. package/templates/mvc/ts/src/routes/api.spec.ts.ejs +6 -0
  151. package/templates/mvc/ts/src/routes/api.ts.ejs +15 -0
  152. package/templates/mvc/ts/src/utils/errorMessages.ts +1 -0
  153. package/templates/mvc/ts/src/utils/httpCodes.ts +1 -0
  154. package/templates/clean-architecture/js/src/interfaces/routes/api.js +0 -12
  155. package/templates/clean-architecture/js/src/usecases/CreateUser.js +0 -14
  156. package/templates/clean-architecture/js/src/usecases/DeleteUser.js +0 -11
  157. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +0 -12
  158. package/templates/clean-architecture/js/src/usecases/UpdateUser.js +0 -11
  159. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +0 -13
  160. package/templates/clean-architecture/ts/src/usecases/createUser.ts +0 -13
  161. package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +0 -9
  162. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +0 -10
  163. package/templates/clean-architecture/ts/src/usecases/updateUser.ts +0 -9
  164. package/templates/mvc/js/src/routes/api.js +0 -10
  165. package/templates/mvc/ts/src/routes/api.ts +0 -12
package/CHANGELOG.md CHANGED
@@ -1,4 +1,29 @@
1
1
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
2
+
3
+ ## [2.1.1] - 2026-04-24
4
+
5
+ ### Fixed
6
+ - **Template Security Hardening**: Resolved missing buffer bounds check vulnerability in `uuid` (GHSA-w5hq-g745-h8pq) by adding `"uuid": "^14.0.0"` to template `overrides`.
7
+ - **Template Formatting**: Fixed an issue in `package.json.ejs` causing unexpected empty lines between generated dependencies.
8
+ - **Unit Test Stability**: Resolved persistent `SyntaxError` and `TypeError` in Jest unit tests across all architecture permutations by implementing ESM-compatible transformation patterns for `uuid` and standardizing on `jest.clearAllMocks()` with factory mocks.
9
+
10
+ ### Changed
11
+ - **Documentation Refinement**: Remade `README.md` and removed emojis for a cleaner, more professional, text-only presentation across the VitePress-based site.
12
+
13
+ ## [2.1.0] - 2026-04-20
14
+
15
+
16
+ ### Added
17
+ - **Pluggable JWT Authentication**: Introduced a robust, production-ready authentication system.
18
+ - Supports **Access & Refresh Token Rotation** for enhanced security.
19
+ - Integrated **Token Revocation (Blacklisting)** via Redis or Memory Cache.
20
+ - Secure logout flows and theft detection for refresh tokens.
21
+ - Seamless integration with both REST and GraphQL protocols across all architectures.
22
+ - **VitePress Documentation Upgrade**: Detailed [Authentication Blueprint](https://paudang.github.io/nodejs-quickstart-structure/blueprints/authentication) and cross-feature documentation updates.
23
+ - **Security Hardening**: Resolved moderate vulnerabilities in `vite` and `vitepress` by implementing version overrides and dependency upgrades (VitePress v1.6.4+).
24
+ - **Interactive README 2.0**: Completely redesigned the project landing page with a "Choose Your Journey" dual-workflow (Web UI vs CLI) and visual action previews.
25
+
26
+ ---
2
27
 
3
28
  ## [2.0.1] - 2026-04-07
4
29
 
package/README.md CHANGED
@@ -1,65 +1,47 @@
1
1
  # Node.js Quickstart Generator
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/nodejs-quickstart-structure.svg?style=flat-square)](https://www.npmjs.com/package/nodejs-quickstart-structure)
4
+ ![Total Clones](https://img.shields.io/badge/dynamic/json?color=brightgreen&label=total%20clones&query=total_clones&url=https%3A%2F%2Fraw.githubusercontent.com%2Fpaudang%2Fnodejs-quickstart-structure%2Foutput%2Ftotal_stats.json&style=flat-square)
4
5
  [![npm total downloads](https://img.shields.io/npm/dt/nodejs-quickstart-structure?style=flat-square&color=emerald&label=Downloads)](https://www.npmjs.com/package/nodejs-quickstart-structure)
5
6
  [![npm monthly downloads](https://img.shields.io/npm/dm/nodejs-quickstart-structure.svg?style=flat-square)](https://www.npmjs.com/package/nodejs-quickstart-structure)
6
7
  [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg?style=flat-square)](https://opensource.org/licenses/ISC)
7
8
 
8
- ### 📈 Real-world Adoption
9
- | **Metric** | **Insight** |
10
- | :--- | :--- |
11
- | 🔥 **4,000+** | Downloads on npm |
12
- | 🚀 **1,200+** | Recent GitHub Clones |
13
- | 🌍 **Trusted by** | Devs from **Google**, **Viblo**, and global tech teams |
14
9
 
15
10
  ---
16
11
 
17
- A powerful CLI tool to scaffold production-ready Node.js microservices with built-in best practices. Choose between **MVC** or **Clean Architecture**, **JavaScript** or **TypeScript**, and your preferred tech stack in seconds.
18
-
19
- 🎯 **[Try the Next-Gen Web UI Configurator!](https://paudang.github.io/nodejs-quickstart-structure/)**
20
- *Generate your exact architecture in the browser with real-time folder simulation.*
21
-
22
- ![Demo](docs/demo.gif)
23
-
24
- ---
12
+ A powerful ecosystem to scaffold production-ready Node.js microservices with built-in best practices. Choose between **MVC** or **Clean Architecture**, **JavaScript** or **TypeScript**, and your preferred tech stack in seconds.
25
13
 
26
- ## 🆕 What's New in v2.0.0
27
-
28
- The v2.0.0 release is a major leap forward, turning the generator into a **Community Standard** for Node.js development:
29
-
30
- - **Next-Gen Web UI Configurator**: A modern, browser-based visual project simulator. Click your stack and copy the generated zero-prompt CLI command instantly! [Try it here](https://paudang.github.io/nodejs-quickstart-structure/).
31
- - **🦾 AI-Native Foundation**: Built-in `.cursorrules` and Agent skills optimized for **Cursor** & AI coding assistants.
32
- - **🏗️ Enterprise Clean Architecture**: High-fidelity structure for professional Microservices (TS/JS).
33
- - **🛡️ Hardened Security**: Integrated Snyk & SonarCloud logic in the core templates.
34
- - **⚡ Zero-Prompt Workflow**: Generate projects with a single CLI command—no more answering prompts manually.
35
-
36
- ---
14
+ ## Table of Contents
37
15
 
38
- ## 📌 Table of Contents
16
+ - [Quick Start](#choose-your-journey)
17
+ - [What's New](#whats-new-in-v21-the-authentication-release)
18
+ - [Key Features](#key-features)
19
+ - [Professional Standards](#professional-standards)
20
+ - [5,280+ Project Combinations](#5280-project-combinations)
21
+ - [Configuration Options](#configuration-options)
22
+ - [Generated Project Structure](#generated-project-structure)
23
+ - [Documentation](#documentation)
24
+ - [Support & Roadmap](#support--roadmap)
39
25
 
40
- - [🚀 Quick Start](#-quick-start)
41
- - [✨ Key Features](#-key-features)
42
- - [🛡️ Professional Standards](#-professional-standards)
43
- - [🧩 2,640+ Project Combinations](#-2640-project-combinations)
44
- - [⚙️ Configuration Options](#-configuration-options)
45
- - [🏗️ Generated Project Structure](#-generated-project-structure)
46
- - [📖 Documentation](#-documentation)
47
- - [🗺️ Support & Roadmap](#️-roadmap--support)
26
+ ## Choose Your Journey
27
+
28
+ | **Path A: Next-Gen Web UI** (Recommended) | **Path B: Interactive CLI** |
29
+ | :--- | :--- |
30
+ | <a href="https://paudang.github.io/nodejs-quickstart-structure/#configurator"><img src="docs/public/v2-preview.png" width="100%" alt="UI Preview"></a> | <img src="docs/demo.gif" width="100%" alt="CLI Demo"> |
31
+ | [Try Visual Configurator ](https://paudang.github.io/nodejs-quickstart-structure/#configurator) | [See CLI Commands ↓](#path-b-interactive-cli) |
32
+ | **Visual Preview**: Real-time folder simulation. | **Fast & Direct**: Quickly scaffold in terminal. |
33
+ | **Zero-Prompt**: Paste a tailored command. | **AI-Ready**: Generates `.cursorrules`. |
48
34
 
49
35
  ---
50
36
 
51
- ## 🚀 Quick Start
52
-
53
- Generate your professional Node.js project in seconds without installing anything globally:
37
+ ### Path B: Interactive CLI
38
+ **Scaffold your project directly from your terminal in seconds.**
54
39
 
55
40
  ```bash
56
41
  npx nodejs-quickstart-structure@latest init
57
42
  ```
58
43
 
59
- ### Installation (Optional)
60
-
61
- If you prefer to install it globally:
62
-
44
+ *Or install globally:*
63
45
  ```bash
64
46
  npm install -g nodejs-quickstart-structure
65
47
  # Then run:
@@ -68,7 +50,21 @@ nodejs-quickstart init
68
50
 
69
51
  ---
70
52
 
71
- ## Key Features
53
+ ## What's New in v2.1 (The Authentication Release)
54
+
55
+ The v2.1.0 release is a major leap forward, turning the generator into a **Community Standard**:
56
+
57
+ - **Pluggable JWT Authentication**: Production-ready access & refresh token patterns with automatic PM2/Environment configuration.
58
+ - **AI-Native Foundation**: Built-in `.cursorrules` optimized for **Cursor** & AI agents—projects are "Born to be Autonomously Coded."
59
+ - **Next-Gen Web UI**: A browser-based visual project simulator with real-time folder previews.
60
+ - **Enterprise Clean Architecture**: High-fidelity structure for professional Microservices (TS/JS).
61
+ - **Hardened Security**: Integrated Snyk & SonarCloud logic in core templates.
62
+ - **Zero-Prompt Workflow**: Generate projects with a single CLI command.
63
+
64
+ ---
65
+
66
+
67
+ ## Key Features
72
68
 
73
69
  - **Interactive CLI**: Smooth, guided configuration process.
74
70
  - **Multiple Architectures**: Supports both **MVC** and **Clean Architecture**.
@@ -76,38 +72,39 @@ nodejs-quickstart init
76
72
  - **Database Ready**: Pre-configured for **MySQL**, **PostgreSQL**, or **MongoDB**.
77
73
  - **Communication Patterns**: Supports **REST**, **GraphQL** (Apollo), and **Kafka** (Event-driven).
78
74
  - **Multi-layer Caching**: Integrated **Redis** or built-in **Memory Cache**.
79
- - **AI-Native Optimized**: specifically designed for **Cursor** and AI agents, including built-in `.cursorrules` and Agent Skill prompts. 🚀
75
+ - **Pluggable Authentication**: Built-in **JWT** support (Refresh/Access tokens).
76
+ - **AI-Native Optimized**: specifically designed for **Cursor** and AI agents, including built-in `.cursorrules` and Agent Skill prompts.
80
77
 
81
78
  ---
82
79
 
83
- ## 🛡️ Professional Standards
80
+ ## Professional Standards
84
81
 
85
82
  We don't just generate boilerplate; we generate **production-ready** foundations. Every project includes:
86
83
 
87
- - **🔍 Code Quality**: Pre-configured `Eslint` and `Prettier`.
88
- - **🛡️ Enterprise Security**: Integrated **Snyk (SCA)**, **SonarCloud (SAST)**, `Helmet`, `HPP`, and Rate-Limiting.
89
- - **🚨 Robust Error Handling**: Centralized global error middleware with custom error classes (`ApiError`, `NotFoundError`, etc.) — consistent across REST & GraphQL.
90
- - **🧪 Testing Excellence**: Integrated `Jest` and `Supertest` with **>80% Unit Test coverage** out of the box.
91
- - **🔄 DevOps & CI/CD**: Optimized **Multi-Stage Dockerfiles**, health checks, infrastructure retry logic, and workflows for **GitHub Actions**, **Jenkins**, **GitLab CI**, **CircleCI**, and **Bitbucket Pipelines**.
92
- - **🚀 Scalable Deployment**: Integrated **PM2 Ecosystem** config for zero-downtime reloads.
84
+ - **Code Quality**: Pre-configured `Eslint` and `Prettier`.
85
+ - **Enterprise Security**: Integrated **Snyk (SCA)**, **SonarCloud (SAST)**, `Helmet`, `HPP`, and Rate-Limiting.
86
+ - **Robust Error Handling**: Centralized global error middleware with custom error classes (`ApiError`, `NotFoundError`, etc.) — consistent across REST & GraphQL.
87
+ - **Testing Excellence**: Integrated `Jest` and `Supertest` with **>80% Unit Test coverage** out of the box.
88
+ - **DevOps & CI/CD**: Optimized **Multi-Stage Dockerfiles**, health checks, infrastructure retry logic, and workflows for **GitHub Actions**, **Jenkins**, **GitLab CI**, **CircleCI**, and **Bitbucket Pipelines**.
89
+ - **Scalable Deployment**: Integrated **PM2 Ecosystem** config for zero-downtime reloads.
93
90
 
94
91
  ---
95
92
 
96
- ## 🧩 2,640+ Project Combinations
93
+ ## 5,280+ Project Combinations
97
94
 
98
95
  The CLI supports a massive number of configurations to fit your exact needs:
99
96
 
100
- - **240 Core Combinations**:
101
- - **MVC Architecture**: 180 variants (Languages × View Engines × Databases × Communication Patterns × Caching)
102
- - **Clean Architecture**: 60 variants (Languages × Databases × Communication Patterns × Caching)
103
- - **2,640+ Total Scenarios**:
104
- - Every combination can be generated across 3 CI/CD providers.
97
+ - **480 Core Combinations**:
98
+ - **MVC Architecture**: 360 variants (Languages × View Engines × Databases × Communication Patterns × Caching × Auth)
99
+ - **Clean Architecture**: 120 variants (Languages × Databases × Communication Patterns × Caching × Auth)
100
+ - **5,280+ Total Scenarios**:
101
+ - Every combination can be generated across 5 CI/CD providers.
105
102
  - Optional **Enterprise-Grade Security Hardening** doubles the scenarios.
106
103
  - Every single scenario is verified to be compatible with our **80% Coverage Threshold** policy.
107
104
 
108
105
  ---
109
106
 
110
- ## ⚙️ Configuration Options
107
+ ## Configuration Options
111
108
 
112
109
  The CLI will guide you through:
113
110
  1. **Project Name**
@@ -117,12 +114,13 @@ The CLI will guide you through:
117
114
  5. **Database**: `MySQL` | `PostgreSQL` | `MongoDB`
118
115
  6. **Communication**: `REST` | `GraphQL` | `Kafka`
119
116
  7. **Caching**: `None` | `Redis` | `Memory Cache`
120
- 8. **CI/CD**: `GitHub Actions` | `Jenkins` | `GitLab CI` | `CircleCI` | `Bitbucket Pipelines`
121
- 9. **Security**: (Optional) Snyk & SonarCloud Hardening
117
+ 8. **Auth**: `None` | `JWT`
118
+ 9. **CI/CD**: `GitHub Actions` | `Jenkins` | `GitLab CI` | `CircleCI` | `Bitbucket Pipelines`
119
+ 10. **Security**: (Optional) Snyk & SonarCloud Hardening
122
120
 
123
121
  ---
124
122
 
125
- ## 🏗️ Generated Project Structure
123
+ ## Generated Project Structure
126
124
  Depending on your choices, the structure adapts. Here is a **TypeScript + Clean Architecture** preview:
127
125
 
128
126
  ```text
@@ -144,13 +142,13 @@ Depending on your choices, the structure adapts. Here is a **TypeScript + Clean
144
142
 
145
143
  ---
146
144
 
147
- ## 📖 Documentation
145
+ ## Documentation
148
146
 
149
- For full guides, architecture deep-dives, and feature references, visit our **[Official Documentation Site](https://paudang.github.io/nodejs-quickstart-structure/)**.
147
+ For full guides, architecture deep-dives, and feature references, visit our **[Official Documentation Site](https://paudang.github.io/nodejs-quickstart-structure/guide/getting-started.html)**.
150
148
 
151
149
  ---
152
150
 
153
- ## ❤️ Support & 🗺️ Roadmap
151
+ ## Support & Roadmap
154
152
 
155
153
  ### Support the Project
156
154
  If this tool helped you build your project faster, please support us:
@@ -159,11 +157,11 @@ If this tool helped you build your project faster, please support us:
159
157
 
160
158
  ### Roadmap
161
159
  Track our progress and vote for features on our public board:
162
- 👉 **[View our Public Roadmap on Trello](https://trello.com/b/TPTo8ylF/nodejs-quickstart-structure-product)**
160
+ **[View our Public Roadmap on Trello](https://trello.com/b/TPTo8ylF/nodejs-quickstart-structure-product)**
163
161
 
164
162
  ---
165
163
 
166
- ## Why Star us?
164
+ ## Why Star us?
167
165
 
168
166
  We are on a mission to build the best AI-Native Node.js scaffolding experience. Your star is not just a "like"—it's a vote of confidence that helps us:
169
167
 
@@ -171,7 +169,7 @@ We are on a mission to build the best AI-Native Node.js scaffolding experience.
171
169
  2. **AI Model Awareness**: Popular repositories are weighted higher by AI coding assistants (Cursor, Copilot, etc.), making the generated code even better.
172
170
  3. **Open Source Sustainability**: It motivates us to keep building and shipping "Enterprise-Grade" features for free.
173
171
 
174
- If this tool saved you hours of work, **[please give us a Star!](https://github.com/paudang/nodejs-quickstart-structure)** 🚀
172
+ If this tool saved you hours of work, **[please give us a Star!](https://github.com/paudang/nodejs-quickstart-structure)**
175
173
 
176
174
  ---
177
175
 
package/bin/index.js CHANGED
@@ -15,7 +15,7 @@ const program = new Command();
15
15
 
16
16
  program
17
17
  .name('nodejs-quickstart')
18
- .description('🚀 CLI to scaffold production-ready Node.js microservices.\n\nGenerates projects with:\n- MVC or Clean Architecture\n- REST or Kafka\n- MySQL, PostgreSQL, or MongoDB\n- Docker, Flyway & Mongoose support')
18
+ .description('🚀 CLI to scaffold production-ready Node.js microservices.\n\nGenerates projects with:\n- MVC or Clean Architecture\n- REST, GraphQL or Kafka\n- MySQL, PostgreSQL, or MongoDB\n- Auth (None, JWT)\n- Docker, Flyway & Mongoose support')
19
19
  .version(pkg.version, '-v, --version', 'Output the current version')
20
20
  .addHelpText('after', `\n${chalk.yellow('Example:')}\n $ nodejs-quickstart init ${chalk.gray('# Start the interactive setup')}\n`);
21
21
 
@@ -32,7 +32,10 @@ program
32
32
  .option('--ci-provider <provider>', 'CI/CD Provider (None, GitHub Actions, Jenkins, GitLab CI, Bitbucket Pipelines, CircleCI)')
33
33
  .option('--include-security', 'Include Enterprise Security Hardening')
34
34
  .option('--no-include-security', 'Exclude Enterprise Security Hardening')
35
- .option('--caching <type>', 'Caching Layer (None/Redis)')
35
+ .option('--caching <type>', 'Caching Layer (None/Redis/Memory Cache)')
36
+ .option('--auth <modes...>', 'Authentication Modes (None, JWT)')
37
+ .option('--advanced-options', 'Enable Advanced Options')
38
+ .option('--no-advanced-options', 'Disable Advanced Options')
36
39
  .action(async (options) => {
37
40
  // Fix for Commander camelCase conversion
38
41
  if (options.ciProvider) {
package/lib/generator.js CHANGED
@@ -10,6 +10,8 @@ import { setupCaching } from './modules/caching-setup.js';
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const __dirname = path.dirname(__filename);
12
12
 
13
+ import { setupAuth } from './modules/auth-setup.js';
14
+
13
15
  export const generateProject = async (config) => {
14
16
  // 0. Normalize configuration with defaults
15
17
  config = {
@@ -20,9 +22,11 @@ export const generateProject = async (config) => {
20
22
  communication: 'REST APIs',
21
23
  database: 'None',
22
24
  includeSecurity: false,
25
+ auth: ['None'],
23
26
  ...config
24
27
  };
25
28
 
29
+
26
30
  const { projectName, architecture, language } = config;
27
31
  const targetDir = path.resolve(process.cwd(), projectName);
28
32
  const templatesDir = path.join(__dirname, '../templates');
@@ -62,14 +66,15 @@ export const generateProject = async (config) => {
62
66
  await renderDockerfile(templatesDir, targetDir, config);
63
67
 
64
68
  // 10. Database Setup (Migrations, Config, Models)
65
- // Note: logic for detailed view copying is also handled nicely if we ensure setupDatabase checks correctly,
66
- // or we can move strict view logic to setupViews.
67
- // In strict refactor, database-setup handles the content that was in the DB block.
68
69
  await setupDatabase(templatesDir, targetDir, config);
69
70
 
71
+ // 10.1 Auth Setup
72
+ await setupAuth(templatesDir, targetDir, config);
73
+
70
74
  // 10a. Caching Setup
71
75
  await setupCaching(templatesDir, targetDir, config);
72
76
 
77
+
73
78
  // 11. View Engine Public Assets (MVC)
74
79
  await setupViews(templatesDir, targetDir, config);
75
80
  // Copy src/views (MVC)
@@ -106,7 +111,8 @@ export const generateProject = async (config) => {
106
111
  Architecture: ${architecture}
107
112
  Language: ${language}
108
113
  Database: ${config.database}
109
- Communication: ${config.communication}${config.caching && config.caching === 'Redis' ? `\n Caching: ${config.caching}` : ''}
114
+ Communication: ${config.communication}${config.caching && config.caching !== 'None' ? `\n Caching: ${config.caching}` : ''}
115
+ Authentication: ${config.auth.join(', ')}
110
116
 
111
117
  ----------------------------------------------------
112
118
  ✨ High-Quality Standards Applied:
@@ -104,9 +104,21 @@ export const renderDynamicComponents = async (templatePath, targetDir, config) =
104
104
  await fs.ensureDir(path.join(targetDir, 'tests/unit/controllers'));
105
105
  const content = ejs.render(await fs.readFile(userControllerSpecTemplate, 'utf-8'), { ...config });
106
106
  await fs.writeFile(userControllerSpecPath, content);
107
- await fs.remove(path.join(targetDir, 'src/controllers', `${userControllerSpecName}.ejs`));
107
+ await fs.remove(path.join(targetDir, 'tests/unit/controllers', `${userControllerSpecName}.ejs`));
108
+ }
109
+
110
+ // MVC Routes
111
+ const routeName = language === 'TypeScript' ? 'api.ts' : 'api.js';
112
+ const routePath = path.join(targetDir, 'src/routes', routeName);
113
+ const routeTemplate = path.join(templatePath, 'src/routes', `${routeName}.ejs`);
114
+
115
+ if (await fs.pathExists(routeTemplate)) {
116
+ const content = ejs.render(await fs.readFile(routeTemplate, 'utf-8'), { ...config });
117
+ await fs.writeFile(routePath, content);
118
+ await fs.remove(path.join(targetDir, 'src/routes', `${routeName}.ejs`));
108
119
  }
109
120
  }
121
+
110
122
  // Clean Architecture Repo
111
123
  else if (architecture === 'Clean Architecture') {
112
124
  const repoName = language === 'TypeScript' ? 'UserRepository.ts' : 'UserRepository.js';
@@ -151,7 +163,36 @@ export const renderDynamicComponents = async (templatePath, targetDir, config) =
151
163
  await fs.writeFile(controllerSpecPath, content);
152
164
  await fs.remove(path.join(targetDir, 'src/interfaces/controllers', `${controllerSpecName}.ejs`));
153
165
  }
166
+
167
+ // CA Routes
168
+ const routeName = language === 'TypeScript' ? 'userRoutes.ts' : 'api.js';
169
+ const routePath = path.join(targetDir, 'src/interfaces/routes', routeName);
170
+ const routeTemplate = path.join(templatePath, 'src/interfaces/routes', `${routeName}.ejs`);
171
+
172
+ if (await fs.pathExists(routeTemplate)) {
173
+ const content = ejs.render(await fs.readFile(routeTemplate, 'utf-8'), { ...config });
174
+ await fs.writeFile(routePath, content);
175
+ await fs.remove(path.join(targetDir, 'src/interfaces/routes', `${routeName}.ejs`));
176
+ }
177
+
178
+ // --- Render All Use Cases ---
179
+ const useCaseDir = path.join(targetDir, 'src/usecases');
180
+ if (await fs.pathExists(useCaseDir)) {
181
+ const useCaseFiles = await fs.readdir(useCaseDir);
182
+ for (const file of useCaseFiles) {
183
+ if (file.endsWith('.ejs')) {
184
+ const templatePathObj = path.join(useCaseDir, file);
185
+ const destPathObj = path.join(useCaseDir, file.replace('.ejs', ''));
186
+
187
+ const template = await fs.readFile(templatePathObj, 'utf-8');
188
+ const content = ejs.render(template, { ...config });
189
+ await fs.writeFile(destPathObj, content);
190
+ await fs.remove(templatePathObj);
191
+ }
192
+ }
193
+ }
154
194
  }
195
+
155
196
  // Render Server (Clean Arch JS only)
156
197
  if (architecture === 'Clean Architecture' && language === 'JavaScript') {
157
198
  const serverName = 'server.js';
@@ -270,7 +311,7 @@ export const renderDynamicComponents = async (templatePath, targetDir, config) =
270
311
  if (stat.isDirectory()) {
271
312
  await renderEjsDir(srcPath, destPath);
272
313
  } else if (item.endsWith('.ejs')) {
273
- const content = ejs.render(await fs.readFile(srcPath, 'utf-8'), { language, architecture, database, caching });
314
+ const content = ejs.render(await fs.readFile(srcPath, 'utf-8'), { ...config });
274
315
  // Remove .ejs extension
275
316
  const finalDestPath = destPath.slice(0, -4);
276
317
  await fs.writeFile(finalDestPath, content);
@@ -310,10 +351,11 @@ export const renderSwaggerConfig = async (templatesDir, targetDir, config) => {
310
351
  if (communication === 'REST APIs' || communication === 'Kafka') {
311
352
  const swaggerYmlTemplateSource = path.join(templatesDir, 'common', 'swagger.yml.ejs');
312
353
  if (await fs.pathExists(swaggerYmlTemplateSource)) {
313
- const ymlContent = ejs.render(await fs.readFile(swaggerYmlTemplateSource, 'utf-8'), { projectName });
354
+ const ymlContent = ejs.render(await fs.readFile(swaggerYmlTemplateSource, 'utf-8'), { ...config });
314
355
  await fs.writeFile(path.join(configDir, 'swagger.yml'), ymlContent);
315
356
  }
316
357
 
358
+
317
359
  if (await fs.pathExists(swaggerTsTemplate)) {
318
360
  const content = ejs.render(await fs.readFile(swaggerTsTemplate, 'utf-8'), { communication });
319
361
  await fs.writeFile(path.join(targetDir, 'src', 'config', 'swagger.ts'), content);
@@ -347,9 +389,35 @@ export const renderSwaggerConfig = async (templatesDir, targetDir, config) => {
347
389
  export const setupViews = async (templatesDir, targetDir, config) => {
348
390
  const { architecture, viewEngine } = config;
349
391
  if (architecture === 'MVC' && viewEngine && viewEngine !== 'None') {
350
- const viewsSource = path.join(templatesDir, 'common', 'views', viewEngine.toLowerCase());
392
+ const engine = viewEngine.toLowerCase();
393
+ const viewsSource = path.join(templatesDir, 'common', 'views', engine);
394
+ const destDir = path.join(targetDir, 'src/views');
395
+
351
396
  if (await fs.pathExists(viewsSource)) {
352
- await fs.copy(viewsSource, path.join(targetDir, 'src/views'));
397
+ await fs.ensureDir(destDir);
398
+ const items = await fs.readdir(viewsSource);
399
+ for (const item of items) {
400
+ // Skip auth views here; they are handled by auth-setup.js
401
+ if (item.startsWith('login.') || item.startsWith('signup.')) continue;
402
+
403
+ const srcPath = path.join(viewsSource, item);
404
+ const isTemplate = item.endsWith('.ejs');
405
+
406
+ // Determine target name: remove .ejs only if it's a double extension (e.g., .ejs.ejs or .pug.ejs)
407
+ // Otherwise keep the original name (e.g., index.ejs should remain index.ejs)
408
+ let targetName = item;
409
+ if (item.endsWith('.ejs.ejs') || item.endsWith('.pug.ejs')) {
410
+ targetName = item.slice(0, -4);
411
+ }
412
+ const destPath = path.join(destDir, targetName);
413
+
414
+ if (isTemplate) {
415
+ const content = ejs.render(await fs.readFile(srcPath, 'utf-8'), config);
416
+ await fs.writeFile(destPath, content);
417
+ } else {
418
+ await fs.copy(srcPath, destPath);
419
+ }
420
+ }
353
421
  }
354
422
  }
355
423
  };
@@ -392,7 +460,9 @@ export const processAllTests = async (targetDir, config) => {
392
460
  const template = await fs.readFile(itemPath, 'utf-8');
393
461
  const content = ejs.render(template, config);
394
462
 
395
- await fs.writeFile(targetTestPath, content);
463
+ if (content.trim()) {
464
+ await fs.writeFile(targetTestPath, content);
465
+ }
396
466
  await fs.remove(itemPath);
397
467
  }
398
468
  }
@@ -0,0 +1,143 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import ejs from 'ejs';
4
+
5
+ export const setupAuth = async (templatesDir, targetDir, config) => {
6
+ const { auth, architecture, language, communication, viewEngine } = config;
7
+ if (!auth || auth.includes('None') || !auth.includes('JWT')) return;
8
+
9
+ const langExt = language === 'TypeScript' ? 'ts' : 'js';
10
+ const authSource = path.join(templatesDir, 'common', 'auth', langExt);
11
+ const viewsSource = path.join(templatesDir, 'common', 'views');
12
+
13
+ // 1. JWT Service
14
+ await renderAuthComponent(authSource, targetDir, 'services', `jwtService.${langExt}`, config);
15
+
16
+ // 2. Auth Middleware
17
+ await renderAuthComponent(authSource, targetDir, 'middleware', `authMiddleware.${langExt}`, config);
18
+
19
+ // 3. Auth Controller (Login only)
20
+ await renderAuthComponent(authSource, targetDir, 'controllers', `authController.${langExt}`, config);
21
+
22
+ // 4. Auth Routes
23
+ await renderAuthComponent(authSource, targetDir, 'routes', `authRoutes.${langExt}`, config);
24
+
25
+ // 5. MVC Views (if applicable)
26
+ if (architecture === 'MVC' && viewEngine && viewEngine !== 'None') {
27
+ const engine = viewEngine.toLowerCase();
28
+ const views = ['login', 'signup'];
29
+ for (const view of views) {
30
+ const viewTemplate = path.join(viewsSource, engine, `${view}.${engine}.ejs`);
31
+ if (await fs.pathExists(viewTemplate)) {
32
+ const content = ejs.render(await fs.readFile(viewTemplate, 'utf-8'), config);
33
+ const destPath = path.join(targetDir, 'src', 'views', `${view}.${engine}`);
34
+ await fs.ensureDir(path.dirname(destPath));
35
+ await fs.writeFile(destPath, content);
36
+ }
37
+ }
38
+ }
39
+
40
+ // 6. Restructuring for Clean Architecture
41
+ if (architecture === 'Clean Architecture') {
42
+ await restructureAuthForCleanArch(targetDir, langExt);
43
+ }
44
+ };
45
+
46
+ async function renderAuthComponent(authSource, targetDir, subDir, fileName, config) {
47
+ const templatePath = path.join(authSource, subDir, `${fileName}.ejs`);
48
+ if (await fs.pathExists(templatePath)) {
49
+ const content = ejs.render(await fs.readFile(templatePath, 'utf-8'), config);
50
+ const destPath = path.join(targetDir, 'src', subDir, fileName);
51
+ await fs.ensureDir(path.dirname(destPath));
52
+ await fs.writeFile(destPath, content);
53
+
54
+ // Render Spec
55
+ const specName = fileName.replace(`.${config.language === 'TypeScript' ? 'ts' : 'js'}`, `.spec.${config.language === 'TypeScript' ? 'ts' : 'js'}`);
56
+ const specTemplate = path.join(authSource, subDir, `${specName}.ejs`);
57
+ if (await fs.pathExists(specTemplate)) {
58
+ const specContent = ejs.render(await fs.readFile(specTemplate, 'utf-8'), config);
59
+ const testDir = path.join(targetDir, 'tests', 'unit', subDir);
60
+ await fs.ensureDir(testDir);
61
+ await fs.writeFile(path.join(testDir, specName), specContent);
62
+ }
63
+ }
64
+ }
65
+
66
+ async function restructureAuthForCleanArch(targetDir, ext) {
67
+ // Services -> Infrastructure/Auth
68
+ await fs.ensureDir(path.join(targetDir, 'src/infrastructure/auth'));
69
+ await fs.ensureDir(path.join(targetDir, 'tests/unit/infrastructure/auth'));
70
+ if (await fs.pathExists(path.join(targetDir, `src/services/jwtService.${ext}`))) {
71
+ await fs.move(
72
+ path.join(targetDir, `src/services/jwtService.${ext}`),
73
+ path.join(targetDir, `src/infrastructure/auth/jwtService.${ext}`),
74
+ { overwrite: true }
75
+ );
76
+ if (await fs.pathExists(path.join(targetDir, `tests/unit/services/jwtService.spec.${ext}`))) {
77
+ await fs.move(
78
+ path.join(targetDir, `tests/unit/services/jwtService.spec.${ext}`),
79
+ path.join(targetDir, `tests/unit/infrastructure/auth/jwtService.spec.${ext}`),
80
+ { overwrite: true }
81
+ );
82
+ }
83
+ }
84
+
85
+ // Controllers -> Interfaces/Controllers/auth
86
+ await fs.ensureDir(path.join(targetDir, 'src/interfaces/controllers/auth'));
87
+ await fs.ensureDir(path.join(targetDir, 'tests/unit/interfaces/controllers/auth'));
88
+ if (await fs.pathExists(path.join(targetDir, `src/controllers/authController.${ext}`))) {
89
+ await fs.move(
90
+ path.join(targetDir, `src/controllers/authController.${ext}`),
91
+ path.join(targetDir, `src/interfaces/controllers/auth/authController.${ext}`),
92
+ { overwrite: true }
93
+ );
94
+ if (await fs.pathExists(path.join(targetDir, `tests/unit/controllers/authController.spec.${ext}`))) {
95
+ await fs.move(
96
+ path.join(targetDir, `tests/unit/controllers/authController.spec.${ext}`),
97
+ path.join(targetDir, `tests/unit/interfaces/controllers/auth/authController.spec.${ext}`),
98
+ { overwrite: true }
99
+ );
100
+ }
101
+ }
102
+
103
+ // Middleware -> Infrastructure/Webserver/Middleware
104
+ await fs.ensureDir(path.join(targetDir, 'src/infrastructure/webserver/middleware'));
105
+ await fs.ensureDir(path.join(targetDir, 'tests/unit/infrastructure/webserver/middleware'));
106
+ if (await fs.pathExists(path.join(targetDir, `src/middleware/authMiddleware.${ext}`))) {
107
+ await fs.move(
108
+ path.join(targetDir, `src/middleware/authMiddleware.${ext}`),
109
+ path.join(targetDir, `src/infrastructure/webserver/middleware/authMiddleware.${ext}`),
110
+ { overwrite: true }
111
+ );
112
+ if (await fs.pathExists(path.join(targetDir, `tests/unit/middleware/authMiddleware.spec.${ext}`))) {
113
+ await fs.move(
114
+ path.join(targetDir, `tests/unit/middleware/authMiddleware.spec.${ext}`),
115
+ path.join(targetDir, `tests/unit/infrastructure/webserver/middleware/authMiddleware.spec.${ext}`),
116
+ { overwrite: true }
117
+ );
118
+ }
119
+ }
120
+
121
+ // Routes -> Interfaces/Routes (No unit tests for routes normally, but move if exists)
122
+ await fs.ensureDir(path.join(targetDir, 'src/interfaces/routes'));
123
+ if (await fs.pathExists(path.join(targetDir, `src/routes/authRoutes.${ext}`))) {
124
+ await fs.move(
125
+ path.join(targetDir, `src/routes/authRoutes.${ext}`),
126
+ path.join(targetDir, `src/interfaces/routes/authRoutes.${ext}`),
127
+ { overwrite: true }
128
+ );
129
+ }
130
+
131
+ // Cleanup empty dirs in src and tests/unit
132
+ const dirsToCleanup = [
133
+ 'src/services', 'src/controllers', 'src/middleware', 'src/routes',
134
+ 'tests/unit/services', 'tests/unit/controllers', 'tests/unit/middleware'
135
+ ];
136
+ for (const dir of dirsToCleanup) {
137
+ const fullDir = path.join(targetDir, dir);
138
+ if (await fs.pathExists(fullDir) && (await fs.readdir(fullDir)).length === 0) {
139
+ await fs.remove(fullDir);
140
+ }
141
+ }
142
+ }
143
+
@@ -30,12 +30,14 @@ export const setupCaching = async (templatesDir, targetDir, config) => {
30
30
  const useCases = language === 'TypeScript'
31
31
  ? [
32
32
  { name: 'getAllUsers.ts', src: 'getAllUsers.ts.ejs' },
33
+ { name: 'getUserById.ts', src: 'getUserById.ts.ejs' },
33
34
  { name: 'createUser.ts', src: 'createUser.ts.ejs' },
34
35
  { name: 'updateUser.ts', src: 'updateUser.ts.ejs' },
35
36
  { name: 'deleteUser.ts', src: 'deleteUser.ts.ejs' }
36
37
  ]
37
38
  : [
38
39
  { name: 'GetAllUsers.js', src: 'GetAllUsers.js.ejs' },
40
+ { name: 'GetUserById.js', src: 'GetUserById.js.ejs' },
39
41
  { name: 'CreateUser.js', src: 'CreateUser.js.ejs' },
40
42
  { name: 'UpdateUser.js', src: 'UpdateUser.js.ejs' },
41
43
  { name: 'DeleteUser.js', src: 'DeleteUser.js.ejs' }
@@ -48,8 +50,13 @@ export const setupCaching = async (templatesDir, targetDir, config) => {
48
50
  const useCaseSource = path.join(templatesDir, 'common', 'caching', 'clean', langExt, uc.src);
49
51
  if (await fs.pathExists(useCaseSource)) {
50
52
  const ucContent = await fs.readFile(useCaseSource, 'utf-8');
51
- const renderedUc = ejs.render(ucContent, { caching });
53
+ const renderedUc = ejs.render(ucContent, { ...config });
52
54
  await fs.writeFile(path.join(useCaseTargetDir, uc.name), renderedUc);
55
+ // Cleanup the template in target dir
56
+ const templateInTarget = path.join(useCaseTargetDir, uc.src);
57
+ if (await fs.pathExists(templateInTarget)) {
58
+ await fs.remove(templateInTarget);
59
+ }
53
60
  }
54
61
  }
55
62
  }
@@ -53,6 +53,12 @@ export const renderProfessionalConfig = async (templatesDir, targetDir, config)
53
53
  const jestE2eContent = ejs.render(jestE2eTemplate, { ...config });
54
54
  await fs.writeFile(path.join(targetDir, 'jest.e2e.config.js'), jestE2eContent);
55
55
 
56
+ if (config.language === 'JavaScript') {
57
+ const babelTemplate = await fs.readFile(path.join(templatesDir, 'common', 'babel.config.js.ejs'), 'utf-8');
58
+ const babelContent = ejs.render(babelTemplate, { ...config });
59
+ await fs.writeFile(path.join(targetDir, 'babel.config.js'), babelContent);
60
+ }
61
+
56
62
  // 1. Setup Husky pre-commit (Always for Professional Standard)
57
63
  const huskyDir = path.join(targetDir, '.husky');
58
64
  await fs.ensureDir(huskyDir);