nodejs-quickstart-structure 1.6.1 → 1.8.0

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 (32) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +10 -8
  3. package/bin/index.js +1 -0
  4. package/docs/generateCase.md +127 -76
  5. package/docs/generatorFlow.md +15 -3
  6. package/docs/ruleDevelop.md +25 -0
  7. package/lib/generator.js +9 -2
  8. package/lib/modules/app-setup.js +7 -2
  9. package/lib/modules/caching-setup.js +56 -0
  10. package/lib/modules/config-files.js +30 -5
  11. package/lib/modules/database-setup.js +13 -1
  12. package/lib/prompts.js +10 -2
  13. package/package.json +1 -1
  14. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +1 -2
  15. package/templates/common/.env.example.ejs +39 -0
  16. package/templates/common/.gitlab-ci.yml.ejs +35 -0
  17. package/templates/common/Jenkinsfile.ejs +41 -0
  18. package/templates/common/README.md.ejs +121 -106
  19. package/templates/common/caching/clean/js/CreateUser.js.ejs +25 -0
  20. package/templates/common/caching/clean/js/GetAllUsers.js.ejs +33 -0
  21. package/templates/common/caching/clean/ts/createUser.ts.ejs +23 -0
  22. package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +30 -0
  23. package/templates/common/caching/js/redisClient.js.ejs +71 -0
  24. package/templates/common/caching/ts/redisClient.ts.ejs +76 -0
  25. package/templates/common/docker-compose.yml.ejs +156 -139
  26. package/templates/common/package.json.ejs +4 -0
  27. package/templates/mvc/js/src/controllers/userController.js.ejs +22 -0
  28. package/templates/mvc/ts/src/config/swagger.ts.ejs +1 -2
  29. package/templates/mvc/ts/src/controllers/userController.ts.ejs +22 -0
  30. /package/templates/clean-architecture/js/src/interfaces/controllers/{UserController.js → userController.js} +0 -0
  31. /package/templates/db/mysql/{V1__Initial_Setup.sql → V1__Initial_Setup.sql.ejs} +0 -0
  32. /package/templates/db/postgres/{V1__Initial_Setup.sql → V1__Initial_Setup.sql.ejs} +0 -0
package/CHANGELOG.md CHANGED
@@ -5,6 +5,36 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.8.0] - 2026-02-18
9
+ ### Added
10
+ - Introduced **GitLab CI/CD pipeline support**:
11
+ - Preconfigured `.gitlab-ci.yml` for automated build, test, and deploy steps.
12
+ - End-to-end (e2e) test job included to ensure project reliability.
13
+ - Aligns with existing GitHub Actions and Jenkins workflows for consistent CI/CD coverage.
14
+
15
+ ### Improved
16
+ - Documentation updated to highlight GitLab CI/CD as a supported option.
17
+ - Enhanced CI/CD setup instructions in `README.md` for multi-platform pipelines.
18
+
19
+ ## [1.7.5] - 2026-02-17
20
+ > Happy Lunar New Year! This release coincides with Tet Vietnam. 🎆
21
+ ### Fixed
22
+ - Optimized `scripts/validate-windows.js` to use `--no-audit --no-fund --loglevel=error` during `npm install`, resolving intermittent CI failures on Windows.
23
+ - Fixed 7 failing test cases involving Kafka and Redis combinations.
24
+
25
+ ## [1.7.4] - 2026-02-17
26
+ ### Fixed
27
+ - Resolved `JSON.parse` error and incorrect Redis arguments in `getAllUsers` usecase for Clean Architecture templates.
28
+ - Fixed `SyntaxError` in `lib/modules/caching-setup.js` preventing project generation.
29
+
30
+ ### Added
31
+ - Implemented automatic cache invalidation in `createUser` usecase (Clean Architecture) to ensure data consistency.
32
+
33
+ ## [1.7.0]
34
+
35
+ ### Added
36
+ - Added support for Redis caching in both MVC and Clean Architecture.
37
+
8
38
  ## [1.6.1] - 2026-02-11
9
39
 
10
40
  ### Fixed
package/README.md CHANGED
@@ -13,7 +13,8 @@ A powerful CLI tool to scaffold production-ready Node.js microservices with buil
13
13
  - **Language Support**: Choose between **JavaScript** and **TypeScript**.
14
14
  - **Database Integration**: Pre-configured setup for **MySQL**, **PostgreSQL**, or **MongoDB**.
15
15
  - **Microservices Ready**: Optional **Kafka** integration for event-driven communication.
16
- - **Dockerized**: Automatically generates `docker-compose.yml` for DB, Kafka, and Zookeeper.
16
+ - **Caching Layer**: Optional **Redis** integration for high-performance data caching.
17
+ - **Dockerized**: Automatically generates `docker-compose.yml` for DB, Kafka, Redis, and Zookeeper.
17
18
  - **Database Migrations/Schemas**: Integrated **Flyway** for SQL migrations or **Mongoose** schemas for MongoDB.
18
19
  - **Professional Standards**: Generated projects come with highly professional, industry-standard tooling.
19
20
 
@@ -24,18 +25,18 @@ We don't just generate boilerplate; we generate **production-ready** foundations
24
25
  - **🔍 Code Quality**: Pre-configured `Eslint` and `Prettier` for consistent coding standards.
25
26
  - **🛡️ Security**: Built-in `Helmet`, `HPP`, `CORS`, and Rate-Limiting middleware.
26
27
  - **🧪 Testing Strategy**: Integrated `Jest` and `Supertest` setup for Unit and Integration testing.
27
- - **🔄 CI/CD Support**: Choice between **GitHub Actions** and **Jenkins**.
28
+ - **🔄 CI/CD Integration**: Pre-configured workflows for **GitHub Actions**, **Jenkins**, and **GitLab CI**.
28
29
  - **⚓ Git Hooks**: `Husky` and `Lint-Staged` to ensure no bad code is ever committed.
29
30
  - **🐳 DevOps**: Highly optimized **Multi-Stage Dockerfile** for small, secure production images.
30
31
 
31
- ## 🧩 64+ Project Combinations
32
+ ## 🧩 112+ Project Combinations
32
33
 
33
34
  The CLI supports a massive number of configurations to fit your exact needs:
34
35
 
35
- - **64 Core Combinations**:
36
- - **MVC Architecture**: 48 variants (Languages × View Engines × Databases × Communication Patterns)
37
- - **Clean Architecture**: 16 variants (Languages × Databases × Communication Patterns)
38
- - **128 Total Scenarios**:
36
+ - **112 Core Combinations**:
37
+ - **MVC Architecture**: 84 variants (Languages × View Engines × Databases × Communication Patterns × Caching)
38
+ - **Clean Architecture**: 28 variants (Languages × Databases × Communication Patterns × Caching)
39
+ - **224 Total Scenarios**:
39
40
  - Every combination can be generated with or without **GitHub Actions CI/CD**, doubling the possibilities.
40
41
 
41
42
  For a detailed list of all supported cases, check out [docs/generateCase.md](docs/generateCase.md).
@@ -66,7 +67,8 @@ The CLI will guide you through the following steps:
66
67
  4. **Database**: `MySQL`, `PostgreSQL`, or `MongoDB`.
67
68
  5. **Database Name**: The name of the initial database.
68
69
  6. **Communication**: `REST APIs` (default) or `Kafka`.
69
- 7. **CI/CD**: `GitHub Actions`, `Jenkins`, or `None`.
70
+ 7. **Caching**: `Redis` or `None`.
71
+ 8. **CI/CD**: `GitHub Actions`, `Jenkins`, `GitLab CI` or `None`.
70
72
 
71
73
  ## Generated Project Structure
72
74
 
package/bin/index.js CHANGED
@@ -33,6 +33,7 @@ program
33
33
  .option('--db-name <name>', 'Database name')
34
34
  .option('-c, --communication <communication>', 'Communication (REST APIs, Kafka)')
35
35
  .option('--ci-provider <provider>', 'CI/CD Provider (None, GitHub Actions, Jenkins)')
36
+ .option('--caching <type>', 'Caching Layer (None/Redis)')
36
37
  .action(async (options) => {
37
38
  // Fix for Commander camelCase conversion
38
39
  if (options.ciProvider) {
@@ -1,90 +1,141 @@
1
1
  # NodeJS Quickstart Generator - Test Cases
2
2
 
3
- This document lists the **48 possible project combinations** supported by the `nodejs-quickstart` CLI. These combinations cover all supported languages, architectures, databases (including MongoDB), and communication patterns.
3
+ This document lists the **112 possible project combinations** supported by the `nodejs-quickstart` CLI. These combinations cover all supported languages, architectures, databases, communication patterns, and caching options.
4
4
 
5
5
  ## Summary
6
- - **MVC Architecture**: 48 Combinations
7
- - (2 Languages × 3 View Engines × 4 Databases (incl. None) × 2 Patterns)
8
- - **Clean Architecture**: 16 Combinations
9
- - (2 Languages × 1 View Engine (None) × 4 Databases (incl. None) × 2 Patterns)
6
+ - **CI Providers**: `None`, `GitHub Actions`, `Jenkins`, `GitLab CI`
7
+ - **MVC Architecture**: 84 Combinations
8
+ - **With Database (36)**: 2 Lang × 3 View × 3 DB × 2 Comm = 36 * 2 (Caching: None/Redis) = 72
9
+ - **No Database (12)**: 2 Lang × 3 View × 1 DB × 2 Comm = 12 * 1 (Caching: None) = 12
10
+ - **Clean Architecture**: 28 Combinations
11
+ - **With Database (12)**: 2 Lang × 1 View (None) × 3 DB × 2 Comm = 12 * 2 (Caching: None/Redis) = 24
12
+ - **No Database (4)**: 2 Lang × 1 View (None) × 1 DB × 2 Comm = 4 * 1 (Caching: None) = 4
10
13
 
11
- **Total Core Combinations: 64**
14
+ **Total Core Combinations: 112**
12
15
 
13
- > **Note on CI/CD**: Each of these 48 combinations can be generated with or without the **GitHub Actions CI Workflow** (`--include-ci`). This effectively creates **96 possible project states**. The validation script currently defaults to *including* CI to verify the full "Professional Standards" feature set.
16
+ > **Note on CI/CD**: Each combination can be generated with or without CI/CD (`--ci-provider`), effectively doubling the state space.
14
17
 
15
18
  ---
16
19
 
17
- ## 1. MVC Architecture (36 Cases)
20
+ ## 1. MVC Architecture (84 Cases)
18
21
 
19
- | # | Language | Architecture | View Engine | Database | Communication |
20
- | :--- | :--- | :--- | :--- | :--- | :--- |
21
- | 1 | JavaScript | MVC | None | MySQL | REST APIs |
22
- | 2 | JavaScript | MVC | None | MySQL | Kafka |
23
- | 3 | JavaScript | MVC | None | PostgreSQL | REST APIs |
24
- | 4 | JavaScript | MVC | None | PostgreSQL | Kafka |
25
- | 5 | JavaScript | MVC | None | MongoDB | REST APIs |
26
- | 6 | JavaScript | MVC | None | MongoDB | Kafka |
27
- | 7 | JavaScript | MVC | EJS | MySQL | REST APIs |
28
- | 8 | JavaScript | MVC | EJS | MySQL | Kafka |
29
- | 9 | JavaScript | MVC | EJS | PostgreSQL | REST APIs |
30
- | 10 | JavaScript | MVC | EJS | PostgreSQL | Kafka |
31
- | 11 | JavaScript | MVC | EJS | MongoDB | REST APIs |
32
- | 12 | JavaScript | MVC | EJS | MongoDB | Kafka |
33
- | 13 | JavaScript | MVC | Pug | MySQL | REST APIs |
34
- | 14 | JavaScript | MVC | Pug | MySQL | Kafka |
35
- | 15 | JavaScript | MVC | Pug | PostgreSQL | REST APIs |
36
- | 16 | JavaScript | MVC | Pug | PostgreSQL | Kafka |
37
- | 17 | JavaScript | MVC | Pug | MongoDB | REST APIs |
38
- | 18 | JavaScript | MVC | Pug | MongoDB | Kafka |
39
- | 19 | TypeScript | MVC | None | MySQL | REST APIs |
40
- | 20 | TypeScript | MVC | None | MySQL | Kafka |
41
- | 21 | TypeScript | MVC | None | PostgreSQL | REST APIs |
42
- | 22 | TypeScript | MVC | None | PostgreSQL | Kafka |
43
- | 23 | TypeScript | MVC | None | MongoDB | REST APIs |
44
- | 24 | TypeScript | MVC | None | MongoDB | Kafka |
45
- | 25 | TypeScript | MVC | EJS | MySQL | REST APIs |
46
- | 26 | TypeScript | MVC | EJS | MySQL | Kafka |
47
- | 27 | TypeScript | MVC | EJS | PostgreSQL | REST APIs |
48
- | 28 | TypeScript | MVC | EJS | PostgreSQL | Kafka |
49
- | 29 | TypeScript | MVC | EJS | MongoDB | REST APIs |
50
- | 30 | TypeScript | MVC | EJS | MongoDB | Kafka |
51
- | 31 | TypeScript | MVC | Pug | MySQL | REST APIs |
52
- | 32 | TypeScript | MVC | Pug | MySQL | Kafka |
53
- | 33 | TypeScript | MVC | Pug | PostgreSQL | REST APIs |
54
- | 34 | TypeScript | MVC | Pug | PostgreSQL | Kafka |
55
- | 35 | TypeScript | MVC | Pug | MongoDB | REST APIs |
56
- | 36 | TypeScript | MVC | Pug | MongoDB | Kafka |
57
- | 37 | JavaScript | MVC | None | None | REST APIs |
58
- | 38 | JavaScript | MVC | None | None | Kafka |
59
- | 39 | JavaScript | MVC | EJS | None | REST APIs |
60
- | 40 | JavaScript | MVC | EJS | None | Kafka |
61
- | 41 | JavaScript | MVC | Pug | None | REST APIs |
62
- | 42 | JavaScript | MVC | Pug | None | Kafka |
63
- | 43 | TypeScript | MVC | None | None | REST APIs |
64
- | 44 | TypeScript | MVC | None | None | Kafka |
65
- | 45 | TypeScript | MVC | EJS | None | REST APIs |
66
- | 46 | TypeScript | MVC | EJS | None | Kafka |
67
- | 47 | TypeScript | MVC | Pug | None | REST APIs |
68
- | 48 | TypeScript | MVC | Pug | None | Kafka |
22
+ | # | Language | Architecture | View Engine | Database | Communication | Caching |
23
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
24
+ | 1 | JavaScript | MVC | None | MySQL | REST APIs | None |
25
+ | 2 | JavaScript | MVC | None | MySQL | REST APIs | Redis |
26
+ | 3 | JavaScript | MVC | None | MySQL | Kafka | None |
27
+ | 4 | JavaScript | MVC | None | MySQL | Kafka | Redis |
28
+ | 5 | JavaScript | MVC | None | PostgreSQL | REST APIs | None |
29
+ | 6 | JavaScript | MVC | None | PostgreSQL | REST APIs | Redis |
30
+ | 7 | JavaScript | MVC | None | PostgreSQL | Kafka | None |
31
+ | 8 | JavaScript | MVC | None | PostgreSQL | Kafka | Redis |
32
+ | 9 | JavaScript | MVC | None | MongoDB | REST APIs | None |
33
+ | 10 | JavaScript | MVC | None | MongoDB | REST APIs | Redis |
34
+ | 11 | JavaScript | MVC | None | MongoDB | Kafka | None |
35
+ | 12 | JavaScript | MVC | None | MongoDB | Kafka | Redis |
36
+ | 13 | JavaScript | MVC | EJS | MySQL | REST APIs | None |
37
+ | 14 | JavaScript | MVC | EJS | MySQL | REST APIs | Redis |
38
+ | 15 | JavaScript | MVC | EJS | MySQL | Kafka | None |
39
+ | 16 | JavaScript | MVC | EJS | MySQL | Kafka | Redis |
40
+ | 17 | JavaScript | MVC | EJS | PostgreSQL | REST APIs | None |
41
+ | 18 | JavaScript | MVC | EJS | PostgreSQL | REST APIs | Redis |
42
+ | 19 | JavaScript | MVC | EJS | PostgreSQL | Kafka | None |
43
+ | 20 | JavaScript | MVC | EJS | PostgreSQL | Kafka | Redis |
44
+ | 21 | JavaScript | MVC | EJS | MongoDB | REST APIs | None |
45
+ | 22 | JavaScript | MVC | EJS | MongoDB | REST APIs | Redis |
46
+ | 23 | JavaScript | MVC | EJS | MongoDB | Kafka | None |
47
+ | 24 | JavaScript | MVC | EJS | MongoDB | Kafka | Redis |
48
+ | 25 | JavaScript | MVC | Pug | MySQL | REST APIs | None |
49
+ | 26 | JavaScript | MVC | Pug | MySQL | REST APIs | Redis |
50
+ | 27 | JavaScript | MVC | Pug | MySQL | Kafka | None |
51
+ | 28 | JavaScript | MVC | Pug | MySQL | Kafka | Redis |
52
+ | 29 | JavaScript | MVC | Pug | PostgreSQL | REST APIs | None |
53
+ | 30 | JavaScript | MVC | Pug | PostgreSQL | REST APIs | Redis |
54
+ | 31 | JavaScript | MVC | Pug | PostgreSQL | Kafka | None |
55
+ | 32 | JavaScript | MVC | Pug | PostgreSQL | Kafka | Redis |
56
+ | 33 | JavaScript | MVC | Pug | MongoDB | REST APIs | None |
57
+ | 34 | JavaScript | MVC | Pug | MongoDB | REST APIs | Redis |
58
+ | 35 | JavaScript | MVC | Pug | MongoDB | Kafka | None |
59
+ | 36 | JavaScript | MVC | Pug | MongoDB | Kafka | Redis |
60
+ | 37 | TypeScript | MVC | None | MySQL | REST APIs | None |
61
+ | 38 | TypeScript | MVC | None | MySQL | REST APIs | Redis |
62
+ | 39 | TypeScript | MVC | None | MySQL | Kafka | None |
63
+ | 40 | TypeScript | MVC | None | MySQL | Kafka | Redis |
64
+ | 41 | TypeScript | MVC | None | PostgreSQL | REST APIs | None |
65
+ | 42 | TypeScript | MVC | None | PostgreSQL | REST APIs | Redis |
66
+ | 43 | TypeScript | MVC | None | PostgreSQL | Kafka | None |
67
+ | 44 | TypeScript | MVC | None | PostgreSQL | Kafka | Redis |
68
+ | 45 | TypeScript | MVC | None | MongoDB | REST APIs | None |
69
+ | 46 | TypeScript | MVC | None | MongoDB | REST APIs | Redis |
70
+ | 47 | TypeScript | MVC | None | MongoDB | Kafka | None |
71
+ | 48 | TypeScript | MVC | None | MongoDB | Kafka | Redis |
72
+ | 49 | TypeScript | MVC | EJS | MySQL | REST APIs | None |
73
+ | 50 | TypeScript | MVC | EJS | MySQL | REST APIs | Redis |
74
+ | 51 | TypeScript | MVC | EJS | MySQL | Kafka | None |
75
+ | 52 | TypeScript | MVC | EJS | MySQL | Kafka | Redis |
76
+ | 53 | TypeScript | MVC | EJS | PostgreSQL | REST APIs | None |
77
+ | 54 | TypeScript | MVC | EJS | PostgreSQL | REST APIs | Redis |
78
+ | 55 | TypeScript | MVC | EJS | PostgreSQL | Kafka | None |
79
+ | 56 | TypeScript | MVC | EJS | PostgreSQL | Kafka | Redis |
80
+ | 57 | TypeScript | MVC | EJS | MongoDB | REST APIs | None |
81
+ | 58 | TypeScript | MVC | EJS | MongoDB | REST APIs | Redis |
82
+ | 59 | TypeScript | MVC | EJS | MongoDB | Kafka | None |
83
+ | 60 | TypeScript | MVC | EJS | MongoDB | Kafka | Redis |
84
+ | 61 | TypeScript | MVC | Pug | MySQL | REST APIs | None |
85
+ | 62 | TypeScript | MVC | Pug | MySQL | REST APIs | Redis |
86
+ | 63 | TypeScript | MVC | Pug | MySQL | Kafka | None |
87
+ | 64 | TypeScript | MVC | Pug | MySQL | Kafka | Redis |
88
+ | 65 | TypeScript | MVC | Pug | PostgreSQL | REST APIs | None |
89
+ | 66 | TypeScript | MVC | Pug | PostgreSQL | REST APIs | Redis |
90
+ | 67 | TypeScript | MVC | Pug | PostgreSQL | Kafka | None |
91
+ | 68 | TypeScript | MVC | Pug | PostgreSQL | Kafka | Redis |
92
+ | 69 | TypeScript | MVC | Pug | MongoDB | REST APIs | None |
93
+ | 70 | TypeScript | MVC | Pug | MongoDB | REST APIs | Redis |
94
+ | 71 | TypeScript | MVC | Pug | MongoDB | Kafka | None |
95
+ | 72 | TypeScript | MVC | Pug | MongoDB | Kafka | Redis |
96
+ | 73 | JavaScript | MVC | None | None | REST APIs | None |
97
+ | 74 | JavaScript | MVC | None | None | Kafka | None |
98
+ | 75 | JavaScript | MVC | EJS | None | REST APIs | None |
99
+ | 76 | JavaScript | MVC | EJS | None | Kafka | None |
100
+ | 77 | JavaScript | MVC | Pug | None | REST APIs | None |
101
+ | 78 | JavaScript | MVC | Pug | None | Kafka | None |
102
+ | 79 | TypeScript | MVC | None | None | REST APIs | None |
103
+ | 80 | TypeScript | MVC | None | None | Kafka | None |
104
+ | 81 | TypeScript | MVC | EJS | None | REST APIs | None |
105
+ | 82 | TypeScript | MVC | EJS | None | Kafka | None |
106
+ | 83 | TypeScript | MVC | Pug | None | REST APIs | None |
107
+ | 84 | TypeScript | MVC | Pug | None | Kafka | None |
69
108
 
70
109
  ## 2. Clean Architecture (16 Cases)
71
110
  *Note: Clean Architecture does not use server-side view engines (EJS/Pug).*
72
111
 
73
- | # | Language | Architecture | View Engine | Database | Communication |
74
- | :--- | :--- | :--- | :--- | :--- | :--- |
75
- | 1 | JavaScript | Clean Architecture | N/A | MySQL | REST APIs |
76
- | 38 | JavaScript | Clean Architecture | N/A | MySQL | Kafka |
77
- | 39 | JavaScript | Clean Architecture | N/A | PostgreSQL | REST APIs |
78
- | 40 | JavaScript | Clean Architecture | N/A | PostgreSQL | Kafka |
79
- | 41 | JavaScript | Clean Architecture | N/A | MongoDB | REST APIs |
80
- | 42 | JavaScript | Clean Architecture | N/A | MongoDB | Kafka |
81
- | 43 | TypeScript | Clean Architecture | N/A | MySQL | REST APIs |
82
- | 44 | TypeScript | Clean Architecture | N/A | MySQL | Kafka |
83
- | 45 | TypeScript | Clean Architecture | N/A | PostgreSQL | REST APIs |
84
- | 46 | TypeScript | Clean Architecture | N/A | PostgreSQL | Kafka |
85
- | 47 | TypeScript | Clean Architecture | N/A | MongoDB | REST APIs |
86
- | 48 | TypeScript | Clean Architecture | N/A | MongoDB | Kafka |
87
- | 49 | JavaScript | Clean Architecture | N/A | None | REST APIs |
88
- | 50 | JavaScript | Clean Architecture | N/A | None | Kafka |
89
- | 51 | TypeScript | Clean Architecture | N/A | None | REST APIs |
90
- | 52 | TypeScript | Clean Architecture | N/A | None | Kafka |
112
+ | # | Language | Architecture | View Engine | Database | Communication | Caching |
113
+ | :--- | :--- | :--- | :--- | :--- | :--- | :--- |
114
+ | 85 | JavaScript | Clean Architecture | N/A | MySQL | REST APIs | None |
115
+ | 86 | JavaScript | Clean Architecture | N/A | MySQL | REST APIs | Redis |
116
+ | 87 | JavaScript | Clean Architecture | N/A | MySQL | Kafka | None |
117
+ | 88 | JavaScript | Clean Architecture | N/A | MySQL | Kafka | Redis |
118
+ | 89 | JavaScript | Clean Architecture | N/A | PostgreSQL | REST APIs | None |
119
+ | 90 | JavaScript | Clean Architecture | N/A | PostgreSQL | REST APIs | Redis |
120
+ | 91 | JavaScript | Clean Architecture | N/A | PostgreSQL | Kafka | None |
121
+ | 92 | JavaScript | Clean Architecture | N/A | PostgreSQL | Kafka | Redis |
122
+ | 93 | JavaScript | Clean Architecture | N/A | MongoDB | REST APIs | None |
123
+ | 94 | JavaScript | Clean Architecture | N/A | MongoDB | REST APIs | Redis |
124
+ | 95 | JavaScript | Clean Architecture | N/A | MongoDB | Kafka | None |
125
+ | 96 | JavaScript | Clean Architecture | N/A | MongoDB | Kafka | Redis |
126
+ | 97 | TypeScript | Clean Architecture | N/A | MySQL | REST APIs | None |
127
+ | 98 | TypeScript | Clean Architecture | N/A | MySQL | REST APIs | Redis |
128
+ | 99 | TypeScript | Clean Architecture | N/A | MySQL | Kafka | None |
129
+ | 100 | TypeScript | Clean Architecture | N/A | MySQL | Kafka | Redis |
130
+ | 101 | TypeScript | Clean Architecture | N/A | PostgreSQL | REST APIs | None |
131
+ | 102 | TypeScript | Clean Architecture | N/A | PostgreSQL | REST APIs | Redis |
132
+ | 103 | TypeScript | Clean Architecture | N/A | PostgreSQL | Kafka | None |
133
+ | 104 | TypeScript | Clean Architecture | N/A | PostgreSQL | Kafka | Redis |
134
+ | 105 | TypeScript | Clean Architecture | N/A | MongoDB | REST APIs | None |
135
+ | 106 | TypeScript | Clean Architecture | N/A | MongoDB | REST APIs | Redis |
136
+ | 107 | TypeScript | Clean Architecture | N/A | MongoDB | Kafka | None |
137
+ | 108 | TypeScript | Clean Architecture | N/A | MongoDB | Kafka | Redis |
138
+ | 109 | JavaScript | Clean Architecture | N/A | None | REST APIs | None |
139
+ | 110 | JavaScript | Clean Architecture | N/A | None | Kafka | None |
140
+ | 111 | TypeScript | Clean Architecture | N/A | None | REST APIs | None |
141
+ | 112 | TypeScript | Clean Architecture | N/A | None | Kafka | None |
@@ -26,6 +26,7 @@ The generator prompts the user for the following configurations. These determine
26
26
  | **Database** | `None`, `MySQL`, `PostgreSQL`, `MongoDB` | `None` | The primary database. |
27
27
  | **Database Name** | Input String | `demo` | The name of the database to use/create. |
28
28
  | **Communication**| `REST APIs`, `Kafka` | `REST APIs` | The primary communication method. |
29
+ | **Caching Layer**| `None`, `Redis` | `None` | (If DB selected) Caching solution. |
29
30
  | **CI/CD Provider**| `None`, `GitHub Actions`, `Jenkins`| `None` | Setup for Continuous Integration/Deployment. |
30
31
 
31
32
  ## 3. Main Generator Flow
@@ -67,7 +68,13 @@ The `generateProject` function in `lib/generator.js` executes the following step
67
68
  * **MongoDB**: Sets up `migrate-mongo-config.js` and initial migration script.
68
69
  * **SQL (MySQL/Postgres)**: Sets up `flyway/sql` directory and copies initial SQL migration files.
69
70
  * **None**: Skips migration setup.
70
- 11. **Database Connection Config**:
71
+ 11. **Caching Setup**:
72
+ * **Redis**:
73
+ * Injects `ioredis` dependency into `package.json`.
74
+ * Generates `redisClient.{js|ts}` config.
75
+ * **MVC**: Injects caching logic into `userController`.
76
+ * **Clean Architecture**: Overwrites `GetAllUsers` use case with caching-enabled version.
77
+ 12. **Database Connection Config**:
71
78
  * Renders `database.{js|ts}` or `mongoose.{js|ts}` based on DB selection.
72
79
  * Places it in `src/config` (MVC) or `src/infrastructure/database` (Clean Arch).
73
80
  * **None**: Skips this step.
@@ -83,7 +90,11 @@ The `generateProject` function in `lib/generator.js` executes the following step
83
90
  16. **Test Setup**:
84
91
  * Generates `jest.config.js` and a sample `health.test.{js|ts}`.
85
92
  17. **CI/CD Setup**:
86
- * Copies GitHub Actions workflow or renders `Jenkinsfile` if selected.
93
+ * Helper: `setupCiCd`
94
+ * Checks `config.ciProvider`:
95
+ * **GitHub Actions**: Copies `.github/workflows/ci.yml`.
96
+ * **Jenkins**: Renders `Jenkinsfile`.
97
+ * **GitLab CI**: Renders `.gitlab-ci.yml` if selected.
87
98
 
88
99
  ## 4. TypeScript vs JavaScript Generation Steps
89
100
 
@@ -109,7 +120,7 @@ Standard architecture for web APIs.
109
120
  ```text
110
121
  project-name/
111
122
  ├── src/
112
- │ ├── config/ # Database, Swagger, etc.
123
+ │ ├── config/ # Database, Redis, Swagger, etc.
113
124
  │ ├── controllers/ # Request handlers
114
125
  │ ├── models/ # Database models
115
126
  │ ├── routes/ # Express routes
@@ -149,6 +160,7 @@ project-name/
149
160
  │ │ └── routes/
150
161
  │ ├── infrastructure/ # Frameworks & Drivers
151
162
  │ │ ├── config/ # Environment config
163
+ │ │ ├── caching/ # Redis Client
152
164
  │ │ ├── database/ # DB connection & models
153
165
  │ │ ├── repositories/ # Data access implementation
154
166
  │ │ └── webserver/ # Express server setup
@@ -0,0 +1,25 @@
1
+ # Development Rules & Conventions
2
+
3
+ ## General Standards
4
+
5
+ ### File Naming
6
+ - **Controllers**: Use camelCase (e.g., `kafkaController.ts`, `userController.ts`).
7
+ - **Services**: Use camelCase (e.g., `kafkaService.ts`, `userService.ts`) or PascalCase depending on export type. Class-based services should generally match class name.
8
+ - **Routes**: Use camelCase (e.g., `userRoutes.ts`, `kafkaRoutes.ts`).
9
+ - **Utilities**: Use camelCase (e.g., `httpCodes.ts`).
10
+
11
+ ### Code Style
12
+ - **Status Codes**: ALWAYS use `HTTP_STATUS` constants from `@/utils/httpCodes` (TS) or `../../utils/httpCodes.js` (JS) instead of hardcoded numbers.
13
+ - Good: `res.status(HTTP_STATUS.OK).json(...)`
14
+ - Bad: `res.status(200).json(...)`
15
+ - **Imports**:
16
+ - **TypeScript**: Use path aliases (e.g., `@/services/...`, `@/utils/...`) instead of relative paths (e.g., `../../utils/...`).
17
+ - **JavaScript**: Use relative paths as configured by the project structure.
18
+
19
+ ### API Response Structure
20
+ - Success: `{ status: string, data: any }` or direct JSON object.
21
+ - Error: `{ error: string }`
22
+
23
+ ## Git Workflow
24
+ - Commit messages should be descriptive.
25
+ - Ensure all tests pass before pushing.
package/lib/generator.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import path from 'path';
2
2
  import { fileURLToPath } from 'url';
3
3
  import { setupProjectDirectory, copyBaseStructure, copyCommonFiles } from './modules/project-setup.js';
4
- import { renderPackageJson, renderDockerCompose, renderReadme, renderDockerfile, renderProfessionalConfig, setupCiCd, renderTestSample } from './modules/config-files.js';
4
+ import { renderPackageJson, renderDockerCompose, renderReadme, renderDockerfile, renderProfessionalConfig, setupCiCd, renderTestSample, renderEnvExample } from './modules/config-files.js';
5
5
  import { renderIndexFile, renderDynamicComponents, renderSwaggerConfig, setupViews as setupSrcViews } from './modules/app-setup.js';
6
6
  import { setupDatabase } from './modules/database-setup.js';
7
7
  import { setupKafka, setupViews } from './modules/kafka-setup.js';
8
+ import { setupCaching } from './modules/caching-setup.js';
8
9
 
9
10
  const __filename = fileURLToPath(import.meta.url);
10
11
  const __dirname = path.dirname(__filename);
@@ -48,6 +49,9 @@ export const generateProject = async (config) => {
48
49
  // In strict refactor, database-setup handles the content that was in the DB block.
49
50
  await setupDatabase(templatesDir, targetDir, config);
50
51
 
52
+ // 10a. Caching Setup
53
+ await setupCaching(templatesDir, targetDir, config);
54
+
51
55
  // 11. View Engine Public Assets (MVC)
52
56
  await setupViews(templatesDir, targetDir, config);
53
57
  // Copy src/views (MVC)
@@ -63,6 +67,9 @@ export const generateProject = async (config) => {
63
67
  // 14. CI/CD
64
68
  await setupCiCd(templatesDir, targetDir, config);
65
69
 
70
+ // 15. Env Example
71
+ await renderEnvExample(templatesDir, targetDir, config);
72
+
66
73
  console.log(`
67
74
  ====================================================
68
75
  Node.js Project Created Successfully!
@@ -72,7 +79,7 @@ export const generateProject = async (config) => {
72
79
  Architecture: ${architecture}
73
80
  Language: ${language}
74
81
  Database: ${config.database}
75
- Communication: ${config.communication}
82
+ Communication: ${config.communication}${config.caching && config.caching === 'Redis' ? `\n Caching: ${config.caching}` : ''}
76
83
 
77
84
  ----------------------------------------------------
78
85
  ✨ High-Quality Standards Applied:
@@ -23,7 +23,7 @@ export const renderIndexFile = async (templatePath, targetDir, config) => {
23
23
  };
24
24
 
25
25
  export const renderDynamicComponents = async (templatePath, targetDir, config) => {
26
- const { architecture, language, database } = config;
26
+ const { architecture, language, database, caching } = config;
27
27
 
28
28
  // MVC Controller
29
29
  if (architecture === 'MVC') {
@@ -32,7 +32,7 @@ export const renderDynamicComponents = async (templatePath, targetDir, config) =
32
32
  const userControllerTemplate = path.join(templatePath, 'src/controllers', `${userControllerName}.ejs`);
33
33
 
34
34
  if (await fs.pathExists(userControllerTemplate)) {
35
- const content = ejs.render(await fs.readFile(userControllerTemplate, 'utf-8'), { database });
35
+ const content = ejs.render(await fs.readFile(userControllerTemplate, 'utf-8'), { database, caching });
36
36
  await fs.writeFile(userControllerPath, content);
37
37
  await fs.remove(path.join(targetDir, 'src/controllers', `${userControllerName}.ejs`));
38
38
  }
@@ -68,9 +68,14 @@ export const renderSwaggerConfig = async (targetDir, config) => {
68
68
 
69
69
  // Check for Swagger config template (typically in src/config/swagger.ts.ejs)
70
70
  // This path is common for both MVC and Clean Arch TS templates based on current structure
71
+ // Check for Swagger config template (typically in src/config/swagger.ts.ejs)
71
72
  const swaggerTsTemplate = path.join(targetDir, 'src', 'config', 'swagger.ts.ejs');
72
73
 
74
+ // Ensure config directory exists
75
+ await fs.ensureDir(path.join(targetDir, 'src', 'config'));
76
+
73
77
  if (await fs.pathExists(swaggerTsTemplate)) {
78
+ // Render if REST APIs
74
79
  if (communication === 'REST APIs') {
75
80
  const content = ejs.render(await fs.readFile(swaggerTsTemplate, 'utf-8'), { communication });
76
81
  await fs.writeFile(path.join(targetDir, 'src', 'config', 'swagger.ts'), content);
@@ -0,0 +1,56 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import ejs from 'ejs';
4
+
5
+ export const setupCaching = async (templatesDir, targetDir, config) => {
6
+ const { caching, language, architecture } = config;
7
+ if (!caching || caching === 'None') return;
8
+
9
+ if (caching === 'Redis') {
10
+ const langExt = language === 'TypeScript' ? 'ts' : 'js';
11
+ const redisClientObj = language === 'TypeScript' ? 'redisClient.ts' : 'redisClient.js';
12
+ const redisSource = path.join(templatesDir, 'common', 'caching', langExt, `${redisClientObj}.ejs`);
13
+
14
+ let redisTarget;
15
+ let loggerPath;
16
+
17
+ if (architecture === 'MVC') {
18
+ await fs.ensureDir(path.join(targetDir, 'src/config'));
19
+ redisTarget = path.join(targetDir, 'src/config', redisClientObj);
20
+ loggerPath = language === 'TypeScript' ? '@/utils/logger' : '../utils/logger';
21
+ } else {
22
+ // Clean Architecture
23
+ await fs.ensureDir(path.join(targetDir, 'src/infrastructure/caching'));
24
+ redisTarget = path.join(targetDir, 'src/infrastructure/caching', redisClientObj);
25
+ loggerPath = language === 'TypeScript' ? '@/infrastructure/log/logger' : '../log/logger';
26
+
27
+ // Overwrite UseCase with Caching Enabled
28
+ const useCaseName = language === 'TypeScript' ? 'getAllUsers.ts' : 'GetAllUsers.js';
29
+ const useCaseSource = path.join(templatesDir, 'common', 'caching', 'clean', langExt, `${useCaseName}.ejs`);
30
+
31
+ // Both TS and JS templates use 'usecases' directory
32
+ const useCaseTargetDir = path.join(targetDir, 'src/usecases');
33
+ await fs.ensureDir(useCaseTargetDir);
34
+
35
+ if (await fs.pathExists(useCaseSource)) {
36
+ const ucContent = await fs.readFile(useCaseSource, 'utf-8');
37
+ await fs.writeFile(path.join(useCaseTargetDir, useCaseName), ucContent);
38
+ }
39
+
40
+ // Also Overwrite CreateUser with Caching (Invalidation) Enabled
41
+ const createUserParams = language === 'TypeScript' ? { name: 'createUser.ts', src: 'createUser.ts.ejs' } : { name: 'CreateUser.js', src: 'CreateUser.js.ejs' };
42
+ const createUserSource = path.join(templatesDir, 'common', 'caching', 'clean', langExt, createUserParams.src);
43
+
44
+ if (await fs.pathExists(createUserSource)) {
45
+ const createUserContent = await fs.readFile(createUserSource, 'utf-8');
46
+ await fs.writeFile(path.join(useCaseTargetDir, createUserParams.name), createUserContent);
47
+ }
48
+ }
49
+
50
+ if (await fs.pathExists(redisSource)) {
51
+ const redisTemplate = await fs.readFile(redisSource, 'utf-8');
52
+ const content = ejs.render(redisTemplate, { loggerPath });
53
+ await fs.writeFile(redisTarget, content);
54
+ }
55
+ }
56
+ };
@@ -3,7 +3,7 @@ import path from 'path';
3
3
  import ejs from 'ejs';
4
4
 
5
5
  export const renderPackageJson = async (templatesDir, targetDir, config) => {
6
- const { projectName, database, communication, language, viewEngine } = config;
6
+ const { projectName, database, communication, language, viewEngine, caching } = config;
7
7
  const packageJsonPath = path.join(targetDir, 'package.json');
8
8
  const packageTemplate = await fs.readFile(path.join(templatesDir, 'common', 'package.json.ejs'), 'utf-8');
9
9
  const packageContent = ejs.render(packageTemplate, {
@@ -11,26 +11,30 @@ export const renderPackageJson = async (templatesDir, targetDir, config) => {
11
11
  database,
12
12
  communication,
13
13
  language,
14
- viewEngine
14
+ communication,
15
+ language,
16
+ viewEngine,
17
+ caching
15
18
  });
16
19
  await fs.writeFile(packageJsonPath, packageContent);
17
20
  };
18
21
 
19
22
  export const renderDockerCompose = async (templatesDir, targetDir, config) => {
20
- const { projectName, database, dbName, communication } = config;
23
+ const { projectName, database, dbName, communication, caching } = config;
21
24
  const dockerComposePath = path.join(targetDir, 'docker-compose.yml');
22
25
  const dockerTemplate = await fs.readFile(path.join(templatesDir, 'common', 'docker-compose.yml.ejs'), 'utf-8');
23
26
  const dockerContent = ejs.render(dockerTemplate, {
24
27
  projectName,
25
28
  database,
26
29
  dbName,
27
- communication
30
+ communication,
31
+ caching
28
32
  });
29
33
  await fs.writeFile(dockerComposePath, dockerContent);
30
34
  };
31
35
 
32
36
  export const renderReadme = async (templatesDir, targetDir, config) => {
33
- const { projectName, architecture, database, communication, language, ciProvider } = config;
37
+ const { projectName, architecture, database, communication, language, ciProvider, caching } = config;
34
38
  const readmePath = path.join(targetDir, 'README.md');
35
39
  const readmeTemplate = await fs.readFile(path.join(templatesDir, 'common', 'README.md.ejs'), 'utf-8');
36
40
  const readmeContent = ejs.render(readmeTemplate, {
@@ -38,6 +42,7 @@ export const renderReadme = async (templatesDir, targetDir, config) => {
38
42
  architecture,
39
43
  database,
40
44
  communication,
45
+ caching,
41
46
  language,
42
47
  ciProvider
43
48
  });
@@ -76,6 +81,10 @@ export const setupCiCd = async (templatesDir, targetDir, config) => {
76
81
  const jenkinsTemplate = await fs.readFile(path.join(templatesDir, 'common', 'Jenkinsfile.ejs'), 'utf-8');
77
82
  const jenkinsContent = ejs.render(jenkinsTemplate, { projectName });
78
83
  await fs.writeFile(path.join(targetDir, 'Jenkinsfile'), jenkinsContent);
84
+ } else if (ciProvider === 'GitLab CI') {
85
+ const gitlabTemplate = await fs.readFile(path.join(templatesDir, 'common', '.gitlab-ci.yml.ejs'), 'utf-8');
86
+ const gitlabContent = ejs.render(gitlabTemplate, { projectName });
87
+ await fs.writeFile(path.join(targetDir, '.gitlab-ci.yml'), gitlabContent);
79
88
  }
80
89
  };
81
90
 
@@ -86,3 +95,19 @@ export const renderTestSample = async (templatesDir, targetDir, language) => {
86
95
  const testFileName = language === 'TypeScript' ? 'health.test.ts' : 'health.test.js';
87
96
  await fs.writeFile(path.join(targetDir, 'tests', testFileName), healthTestContent);
88
97
  };
98
+
99
+ export const renderEnvExample = async (templatesDir, targetDir, config) => {
100
+ const { database, dbName, communication, projectName, caching } = config;
101
+ const envPath = path.join(targetDir, '.env.example');
102
+ const envTemplate = await fs.readFile(path.join(templatesDir, 'common', '.env.example.ejs'), 'utf-8');
103
+
104
+ const envContent = ejs.render(envTemplate, {
105
+ database,
106
+ dbName,
107
+ communication,
108
+ projectName,
109
+ caching
110
+ });
111
+
112
+ await fs.writeFile(envPath, envContent);
113
+ };
@@ -25,7 +25,19 @@ export const setupDatabase = async (templatesDir, targetDir, config) => {
25
25
  // Flyway for SQL
26
26
  await fs.ensureDir(path.join(targetDir, 'flyway/sql'));
27
27
  const dbType = database === 'PostgreSQL' ? 'postgres' : 'mysql';
28
- await fs.copy(path.join(templatesDir, 'db', dbType), path.join(targetDir, 'flyway/sql'));
28
+ const sourceDir = path.join(templatesDir, 'db', dbType);
29
+
30
+ const files = await fs.readdir(sourceDir);
31
+ for (const file of files) {
32
+ if (file.endsWith('.ejs')) {
33
+ const template = await fs.readFile(path.join(sourceDir, file), 'utf-8');
34
+ const content = ejs.render(template, { ...config });
35
+ const targetFileName = file.replace('.ejs', '');
36
+ await fs.writeFile(path.join(targetDir, 'flyway/sql', targetFileName), content);
37
+ } else {
38
+ await fs.copy(path.join(sourceDir, file), path.join(targetDir, 'flyway/sql', file));
39
+ }
40
+ }
29
41
  }
30
42
 
31
43
  // 2. Database Config