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.
- package/CHANGELOG.md +30 -0
- package/README.md +10 -8
- package/bin/index.js +1 -0
- package/docs/generateCase.md +127 -76
- package/docs/generatorFlow.md +15 -3
- package/docs/ruleDevelop.md +25 -0
- package/lib/generator.js +9 -2
- package/lib/modules/app-setup.js +7 -2
- package/lib/modules/caching-setup.js +56 -0
- package/lib/modules/config-files.js +30 -5
- package/lib/modules/database-setup.js +13 -1
- package/lib/prompts.js +10 -2
- package/package.json +1 -1
- package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +1 -2
- package/templates/common/.env.example.ejs +39 -0
- package/templates/common/.gitlab-ci.yml.ejs +35 -0
- package/templates/common/Jenkinsfile.ejs +41 -0
- package/templates/common/README.md.ejs +121 -106
- package/templates/common/caching/clean/js/CreateUser.js.ejs +25 -0
- package/templates/common/caching/clean/js/GetAllUsers.js.ejs +33 -0
- package/templates/common/caching/clean/ts/createUser.ts.ejs +23 -0
- package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +30 -0
- package/templates/common/caching/js/redisClient.js.ejs +71 -0
- package/templates/common/caching/ts/redisClient.ts.ejs +76 -0
- package/templates/common/docker-compose.yml.ejs +156 -139
- package/templates/common/package.json.ejs +4 -0
- package/templates/mvc/js/src/controllers/userController.js.ejs +22 -0
- package/templates/mvc/ts/src/config/swagger.ts.ejs +1 -2
- package/templates/mvc/ts/src/controllers/userController.ts.ejs +22 -0
- /package/templates/clean-architecture/js/src/interfaces/controllers/{UserController.js → userController.js} +0 -0
- /package/templates/db/mysql/{V1__Initial_Setup.sql → V1__Initial_Setup.sql.ejs} +0 -0
- /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
|
-
- **
|
|
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
|
|
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
|
-
## 🧩
|
|
32
|
+
## 🧩 112+ Project Combinations
|
|
32
33
|
|
|
33
34
|
The CLI supports a massive number of configurations to fit your exact needs:
|
|
34
35
|
|
|
35
|
-
- **
|
|
36
|
-
- **MVC Architecture**:
|
|
37
|
-
- **Clean Architecture**:
|
|
38
|
-
- **
|
|
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. **
|
|
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) {
|
package/docs/generateCase.md
CHANGED
|
@@ -1,90 +1,141 @@
|
|
|
1
1
|
# NodeJS Quickstart Generator - Test Cases
|
|
2
2
|
|
|
3
|
-
This document lists the **
|
|
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
|
-
- **
|
|
7
|
-
|
|
8
|
-
- **
|
|
9
|
-
- (2
|
|
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:
|
|
14
|
+
**Total Core Combinations: 112**
|
|
12
15
|
|
|
13
|
-
> **Note on CI/CD**: Each
|
|
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 (
|
|
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 |
|
|
23
|
-
| 3 | JavaScript | MVC | None |
|
|
24
|
-
| 4 | JavaScript | MVC | None |
|
|
25
|
-
| 5 | JavaScript | MVC | None |
|
|
26
|
-
| 6 | JavaScript | MVC | None |
|
|
27
|
-
| 7 | JavaScript | MVC |
|
|
28
|
-
| 8 | JavaScript | MVC |
|
|
29
|
-
| 9 | JavaScript | MVC |
|
|
30
|
-
| 10 | JavaScript | MVC |
|
|
31
|
-
| 11 | JavaScript | MVC |
|
|
32
|
-
| 12 | JavaScript | MVC |
|
|
33
|
-
| 13 | JavaScript | MVC |
|
|
34
|
-
| 14 | JavaScript | MVC |
|
|
35
|
-
| 15 | JavaScript | MVC |
|
|
36
|
-
| 16 | JavaScript | MVC |
|
|
37
|
-
| 17 | JavaScript | MVC |
|
|
38
|
-
| 18 | JavaScript | MVC |
|
|
39
|
-
| 19 |
|
|
40
|
-
| 20 |
|
|
41
|
-
| 21 |
|
|
42
|
-
| 22 |
|
|
43
|
-
| 23 |
|
|
44
|
-
| 24 |
|
|
45
|
-
| 25 |
|
|
46
|
-
| 26 |
|
|
47
|
-
| 27 |
|
|
48
|
-
| 28 |
|
|
49
|
-
| 29 |
|
|
50
|
-
| 30 |
|
|
51
|
-
| 31 |
|
|
52
|
-
| 32 |
|
|
53
|
-
| 33 |
|
|
54
|
-
| 34 |
|
|
55
|
-
| 35 |
|
|
56
|
-
| 36 |
|
|
57
|
-
| 37 |
|
|
58
|
-
| 38 |
|
|
59
|
-
| 39 |
|
|
60
|
-
| 40 |
|
|
61
|
-
| 41 |
|
|
62
|
-
| 42 |
|
|
63
|
-
| 43 | TypeScript | MVC | None |
|
|
64
|
-
| 44 | TypeScript | MVC | None |
|
|
65
|
-
| 45 | TypeScript | MVC |
|
|
66
|
-
| 46 | TypeScript | MVC |
|
|
67
|
-
| 47 | TypeScript | MVC |
|
|
68
|
-
| 48 | TypeScript | MVC |
|
|
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
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
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 |
|
package/docs/generatorFlow.md
CHANGED
|
@@ -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. **
|
|
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
|
-
*
|
|
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:
|
package/lib/modules/app-setup.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|