nodejs-quickstart-structure 1.6.1 → 1.7.5
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 +19 -0
- package/README.md +9 -7
- package/bin/index.js +1 -0
- package/docs/generateCase.md +126 -76
- package/docs/generatorFlow.md +10 -2
- 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 +26 -5
- package/lib/modules/database-setup.js +13 -1
- package/lib/prompts.js +9 -1
- 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/Jenkinsfile.ejs +41 -0
- package/templates/common/README.md.ejs +113 -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/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,25 @@ 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.7.5] - 2026-02-17
|
|
9
|
+
> Happy Lunar New Year! This release coincides with Tet Vietnam. 🎆
|
|
10
|
+
### Fixed
|
|
11
|
+
- Optimized `scripts/validate-windows.js` to use `--no-audit --no-fund --loglevel=error` during `npm install`, resolving intermittent CI failures on Windows.
|
|
12
|
+
- Fixed 7 failing test cases involving Kafka and Redis combinations.
|
|
13
|
+
|
|
14
|
+
## [1.7.4] - 2026-02-17
|
|
15
|
+
### Fixed
|
|
16
|
+
- Resolved `JSON.parse` error and incorrect Redis arguments in `getAllUsers` usecase for Clean Architecture templates.
|
|
17
|
+
- Fixed `SyntaxError` in `lib/modules/caching-setup.js` preventing project generation.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- Implemented automatic cache invalidation in `createUser` usecase (Clean Architecture) to ensure data consistency.
|
|
21
|
+
|
|
22
|
+
## [1.7.0]
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- Added support for Redis caching in both MVC and Clean Architecture.
|
|
26
|
+
|
|
8
27
|
## [1.6.1] - 2026-02-11
|
|
9
28
|
|
|
10
29
|
### 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
|
|
|
@@ -28,14 +29,14 @@ We don't just generate boilerplate; we generate **production-ready** foundations
|
|
|
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`, 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,140 @@
|
|
|
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
|
-
- **MVC Architecture**:
|
|
7
|
-
- (2
|
|
8
|
-
- **
|
|
9
|
-
|
|
6
|
+
- **MVC Architecture**: 84 Combinations
|
|
7
|
+
- **With Database (36)**: 2 Lang × 3 View × 3 DB × 2 Comm = 36 * 2 (Caching: None/Redis) = 72
|
|
8
|
+
- **No Database (12)**: 2 Lang × 3 View × 1 DB × 2 Comm = 12 * 1 (Caching: None) = 12
|
|
9
|
+
- **Clean Architecture**: 28 Combinations
|
|
10
|
+
- **With Database (12)**: 2 Lang × 1 View (None) × 3 DB × 2 Comm = 12 * 2 (Caching: None/Redis) = 24
|
|
11
|
+
- **No Database (4)**: 2 Lang × 1 View (None) × 1 DB × 2 Comm = 4 * 1 (Caching: None) = 4
|
|
10
12
|
|
|
11
|
-
**Total Core Combinations:
|
|
13
|
+
**Total Core Combinations: 112**
|
|
12
14
|
|
|
13
|
-
> **Note on CI/CD**: Each
|
|
15
|
+
> **Note on CI/CD**: Each combination can be generated with or without CI/CD (`--ci-provider`), effectively doubling the state space.
|
|
14
16
|
|
|
15
17
|
---
|
|
16
18
|
|
|
17
|
-
## 1. MVC Architecture (
|
|
19
|
+
## 1. MVC Architecture (84 Cases)
|
|
18
20
|
|
|
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 |
|
|
21
|
+
| # | Language | Architecture | View Engine | Database | Communication | Caching |
|
|
22
|
+
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
|
23
|
+
| 1 | JavaScript | MVC | None | MySQL | REST APIs | None |
|
|
24
|
+
| 2 | JavaScript | MVC | None | MySQL | REST APIs | Redis |
|
|
25
|
+
| 3 | JavaScript | MVC | None | MySQL | Kafka | None |
|
|
26
|
+
| 4 | JavaScript | MVC | None | MySQL | Kafka | Redis |
|
|
27
|
+
| 5 | JavaScript | MVC | None | PostgreSQL | REST APIs | None |
|
|
28
|
+
| 6 | JavaScript | MVC | None | PostgreSQL | REST APIs | Redis |
|
|
29
|
+
| 7 | JavaScript | MVC | None | PostgreSQL | Kafka | None |
|
|
30
|
+
| 8 | JavaScript | MVC | None | PostgreSQL | Kafka | Redis |
|
|
31
|
+
| 9 | JavaScript | MVC | None | MongoDB | REST APIs | None |
|
|
32
|
+
| 10 | JavaScript | MVC | None | MongoDB | REST APIs | Redis |
|
|
33
|
+
| 11 | JavaScript | MVC | None | MongoDB | Kafka | None |
|
|
34
|
+
| 12 | JavaScript | MVC | None | MongoDB | Kafka | Redis |
|
|
35
|
+
| 13 | JavaScript | MVC | EJS | MySQL | REST APIs | None |
|
|
36
|
+
| 14 | JavaScript | MVC | EJS | MySQL | REST APIs | Redis |
|
|
37
|
+
| 15 | JavaScript | MVC | EJS | MySQL | Kafka | None |
|
|
38
|
+
| 16 | JavaScript | MVC | EJS | MySQL | Kafka | Redis |
|
|
39
|
+
| 17 | JavaScript | MVC | EJS | PostgreSQL | REST APIs | None |
|
|
40
|
+
| 18 | JavaScript | MVC | EJS | PostgreSQL | REST APIs | Redis |
|
|
41
|
+
| 19 | JavaScript | MVC | EJS | PostgreSQL | Kafka | None |
|
|
42
|
+
| 20 | JavaScript | MVC | EJS | PostgreSQL | Kafka | Redis |
|
|
43
|
+
| 21 | JavaScript | MVC | EJS | MongoDB | REST APIs | None |
|
|
44
|
+
| 22 | JavaScript | MVC | EJS | MongoDB | REST APIs | Redis |
|
|
45
|
+
| 23 | JavaScript | MVC | EJS | MongoDB | Kafka | None |
|
|
46
|
+
| 24 | JavaScript | MVC | EJS | MongoDB | Kafka | Redis |
|
|
47
|
+
| 25 | JavaScript | MVC | Pug | MySQL | REST APIs | None |
|
|
48
|
+
| 26 | JavaScript | MVC | Pug | MySQL | REST APIs | Redis |
|
|
49
|
+
| 27 | JavaScript | MVC | Pug | MySQL | Kafka | None |
|
|
50
|
+
| 28 | JavaScript | MVC | Pug | MySQL | Kafka | Redis |
|
|
51
|
+
| 29 | JavaScript | MVC | Pug | PostgreSQL | REST APIs | None |
|
|
52
|
+
| 30 | JavaScript | MVC | Pug | PostgreSQL | REST APIs | Redis |
|
|
53
|
+
| 31 | JavaScript | MVC | Pug | PostgreSQL | Kafka | None |
|
|
54
|
+
| 32 | JavaScript | MVC | Pug | PostgreSQL | Kafka | Redis |
|
|
55
|
+
| 33 | JavaScript | MVC | Pug | MongoDB | REST APIs | None |
|
|
56
|
+
| 34 | JavaScript | MVC | Pug | MongoDB | REST APIs | Redis |
|
|
57
|
+
| 35 | JavaScript | MVC | Pug | MongoDB | Kafka | None |
|
|
58
|
+
| 36 | JavaScript | MVC | Pug | MongoDB | Kafka | Redis |
|
|
59
|
+
| 37 | TypeScript | MVC | None | MySQL | REST APIs | None |
|
|
60
|
+
| 38 | TypeScript | MVC | None | MySQL | REST APIs | Redis |
|
|
61
|
+
| 39 | TypeScript | MVC | None | MySQL | Kafka | None |
|
|
62
|
+
| 40 | TypeScript | MVC | None | MySQL | Kafka | Redis |
|
|
63
|
+
| 41 | TypeScript | MVC | None | PostgreSQL | REST APIs | None |
|
|
64
|
+
| 42 | TypeScript | MVC | None | PostgreSQL | REST APIs | Redis |
|
|
65
|
+
| 43 | TypeScript | MVC | None | PostgreSQL | Kafka | None |
|
|
66
|
+
| 44 | TypeScript | MVC | None | PostgreSQL | Kafka | Redis |
|
|
67
|
+
| 45 | TypeScript | MVC | None | MongoDB | REST APIs | None |
|
|
68
|
+
| 46 | TypeScript | MVC | None | MongoDB | REST APIs | Redis |
|
|
69
|
+
| 47 | TypeScript | MVC | None | MongoDB | Kafka | None |
|
|
70
|
+
| 48 | TypeScript | MVC | None | MongoDB | Kafka | Redis |
|
|
71
|
+
| 49 | TypeScript | MVC | EJS | MySQL | REST APIs | None |
|
|
72
|
+
| 50 | TypeScript | MVC | EJS | MySQL | REST APIs | Redis |
|
|
73
|
+
| 51 | TypeScript | MVC | EJS | MySQL | Kafka | None |
|
|
74
|
+
| 52 | TypeScript | MVC | EJS | MySQL | Kafka | Redis |
|
|
75
|
+
| 53 | TypeScript | MVC | EJS | PostgreSQL | REST APIs | None |
|
|
76
|
+
| 54 | TypeScript | MVC | EJS | PostgreSQL | REST APIs | Redis |
|
|
77
|
+
| 55 | TypeScript | MVC | EJS | PostgreSQL | Kafka | None |
|
|
78
|
+
| 56 | TypeScript | MVC | EJS | PostgreSQL | Kafka | Redis |
|
|
79
|
+
| 57 | TypeScript | MVC | EJS | MongoDB | REST APIs | None |
|
|
80
|
+
| 58 | TypeScript | MVC | EJS | MongoDB | REST APIs | Redis |
|
|
81
|
+
| 59 | TypeScript | MVC | EJS | MongoDB | Kafka | None |
|
|
82
|
+
| 60 | TypeScript | MVC | EJS | MongoDB | Kafka | Redis |
|
|
83
|
+
| 61 | TypeScript | MVC | Pug | MySQL | REST APIs | None |
|
|
84
|
+
| 62 | TypeScript | MVC | Pug | MySQL | REST APIs | Redis |
|
|
85
|
+
| 63 | TypeScript | MVC | Pug | MySQL | Kafka | None |
|
|
86
|
+
| 64 | TypeScript | MVC | Pug | MySQL | Kafka | Redis |
|
|
87
|
+
| 65 | TypeScript | MVC | Pug | PostgreSQL | REST APIs | None |
|
|
88
|
+
| 66 | TypeScript | MVC | Pug | PostgreSQL | REST APIs | Redis |
|
|
89
|
+
| 67 | TypeScript | MVC | Pug | PostgreSQL | Kafka | None |
|
|
90
|
+
| 68 | TypeScript | MVC | Pug | PostgreSQL | Kafka | Redis |
|
|
91
|
+
| 69 | TypeScript | MVC | Pug | MongoDB | REST APIs | None |
|
|
92
|
+
| 70 | TypeScript | MVC | Pug | MongoDB | REST APIs | Redis |
|
|
93
|
+
| 71 | TypeScript | MVC | Pug | MongoDB | Kafka | None |
|
|
94
|
+
| 72 | TypeScript | MVC | Pug | MongoDB | Kafka | Redis |
|
|
95
|
+
| 73 | JavaScript | MVC | None | None | REST APIs | None |
|
|
96
|
+
| 74 | JavaScript | MVC | None | None | Kafka | None |
|
|
97
|
+
| 75 | JavaScript | MVC | EJS | None | REST APIs | None |
|
|
98
|
+
| 76 | JavaScript | MVC | EJS | None | Kafka | None |
|
|
99
|
+
| 77 | JavaScript | MVC | Pug | None | REST APIs | None |
|
|
100
|
+
| 78 | JavaScript | MVC | Pug | None | Kafka | None |
|
|
101
|
+
| 79 | TypeScript | MVC | None | None | REST APIs | None |
|
|
102
|
+
| 80 | TypeScript | MVC | None | None | Kafka | None |
|
|
103
|
+
| 81 | TypeScript | MVC | EJS | None | REST APIs | None |
|
|
104
|
+
| 82 | TypeScript | MVC | EJS | None | Kafka | None |
|
|
105
|
+
| 83 | TypeScript | MVC | Pug | None | REST APIs | None |
|
|
106
|
+
| 84 | TypeScript | MVC | Pug | None | Kafka | None |
|
|
69
107
|
|
|
70
108
|
## 2. Clean Architecture (16 Cases)
|
|
71
109
|
*Note: Clean Architecture does not use server-side view engines (EJS/Pug).*
|
|
72
110
|
|
|
73
|
-
| # | Language | Architecture | View Engine | Database | Communication |
|
|
74
|
-
| :--- | :--- | :--- | :--- | :--- | :--- |
|
|
75
|
-
|
|
|
76
|
-
|
|
|
77
|
-
|
|
|
78
|
-
|
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
|
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
111
|
+
| # | Language | Architecture | View Engine | Database | Communication | Caching |
|
|
112
|
+
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
|
113
|
+
| 85 | JavaScript | Clean Architecture | N/A | MySQL | REST APIs | None |
|
|
114
|
+
| 86 | JavaScript | Clean Architecture | N/A | MySQL | REST APIs | Redis |
|
|
115
|
+
| 87 | JavaScript | Clean Architecture | N/A | MySQL | Kafka | None |
|
|
116
|
+
| 88 | JavaScript | Clean Architecture | N/A | MySQL | Kafka | Redis |
|
|
117
|
+
| 89 | JavaScript | Clean Architecture | N/A | PostgreSQL | REST APIs | None |
|
|
118
|
+
| 90 | JavaScript | Clean Architecture | N/A | PostgreSQL | REST APIs | Redis |
|
|
119
|
+
| 91 | JavaScript | Clean Architecture | N/A | PostgreSQL | Kafka | None |
|
|
120
|
+
| 92 | JavaScript | Clean Architecture | N/A | PostgreSQL | Kafka | Redis |
|
|
121
|
+
| 93 | JavaScript | Clean Architecture | N/A | MongoDB | REST APIs | None |
|
|
122
|
+
| 94 | JavaScript | Clean Architecture | N/A | MongoDB | REST APIs | Redis |
|
|
123
|
+
| 95 | JavaScript | Clean Architecture | N/A | MongoDB | Kafka | None |
|
|
124
|
+
| 96 | JavaScript | Clean Architecture | N/A | MongoDB | Kafka | Redis |
|
|
125
|
+
| 97 | TypeScript | Clean Architecture | N/A | MySQL | REST APIs | None |
|
|
126
|
+
| 98 | TypeScript | Clean Architecture | N/A | MySQL | REST APIs | Redis |
|
|
127
|
+
| 99 | TypeScript | Clean Architecture | N/A | MySQL | Kafka | None |
|
|
128
|
+
| 100 | TypeScript | Clean Architecture | N/A | MySQL | Kafka | Redis |
|
|
129
|
+
| 101 | TypeScript | Clean Architecture | N/A | PostgreSQL | REST APIs | None |
|
|
130
|
+
| 102 | TypeScript | Clean Architecture | N/A | PostgreSQL | REST APIs | Redis |
|
|
131
|
+
| 103 | TypeScript | Clean Architecture | N/A | PostgreSQL | Kafka | None |
|
|
132
|
+
| 104 | TypeScript | Clean Architecture | N/A | PostgreSQL | Kafka | Redis |
|
|
133
|
+
| 105 | TypeScript | Clean Architecture | N/A | MongoDB | REST APIs | None |
|
|
134
|
+
| 106 | TypeScript | Clean Architecture | N/A | MongoDB | REST APIs | Redis |
|
|
135
|
+
| 107 | TypeScript | Clean Architecture | N/A | MongoDB | Kafka | None |
|
|
136
|
+
| 108 | TypeScript | Clean Architecture | N/A | MongoDB | Kafka | Redis |
|
|
137
|
+
| 109 | JavaScript | Clean Architecture | N/A | None | REST APIs | None |
|
|
138
|
+
| 110 | JavaScript | Clean Architecture | N/A | None | Kafka | None |
|
|
139
|
+
| 111 | TypeScript | Clean Architecture | N/A | None | REST APIs | None |
|
|
140
|
+
| 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.
|
|
@@ -109,7 +116,7 @@ Standard architecture for web APIs.
|
|
|
109
116
|
```text
|
|
110
117
|
project-name/
|
|
111
118
|
├── src/
|
|
112
|
-
│ ├── config/ # Database, Swagger, etc.
|
|
119
|
+
│ ├── config/ # Database, Redis, Swagger, etc.
|
|
113
120
|
│ ├── controllers/ # Request handlers
|
|
114
121
|
│ ├── models/ # Database models
|
|
115
122
|
│ ├── routes/ # Express routes
|
|
@@ -149,6 +156,7 @@ project-name/
|
|
|
149
156
|
│ │ └── routes/
|
|
150
157
|
│ ├── infrastructure/ # Frameworks & Drivers
|
|
151
158
|
│ │ ├── config/ # Environment config
|
|
159
|
+
│ │ ├── caching/ # Redis Client
|
|
152
160
|
│ │ ├── database/ # DB connection & models
|
|
153
161
|
│ │ ├── repositories/ # Data access implementation
|
|
154
162
|
│ │ └── webserver/ # Express server setup
|
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
|
});
|
|
@@ -86,3 +91,19 @@ export const renderTestSample = async (templatesDir, targetDir, language) => {
|
|
|
86
91
|
const testFileName = language === 'TypeScript' ? 'health.test.ts' : 'health.test.js';
|
|
87
92
|
await fs.writeFile(path.join(targetDir, 'tests', testFileName), healthTestContent);
|
|
88
93
|
};
|
|
94
|
+
|
|
95
|
+
export const renderEnvExample = async (templatesDir, targetDir, config) => {
|
|
96
|
+
const { database, dbName, communication, projectName, caching } = config;
|
|
97
|
+
const envPath = path.join(targetDir, '.env.example');
|
|
98
|
+
const envTemplate = await fs.readFile(path.join(templatesDir, 'common', '.env.example.ejs'), 'utf-8');
|
|
99
|
+
|
|
100
|
+
const envContent = ejs.render(envTemplate, {
|
|
101
|
+
database,
|
|
102
|
+
dbName,
|
|
103
|
+
communication,
|
|
104
|
+
projectName,
|
|
105
|
+
caching
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
await fs.writeFile(envPath, envContent);
|
|
109
|
+
};
|
|
@@ -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
|
package/lib/prompts.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import inquirer from 'inquirer';
|
|
2
2
|
|
|
3
3
|
const validateName = (name) => {
|
|
4
|
-
return /^[a-zA-Z0-9-_]+$/.test(name) ? true : 'Project name may only include letters, numbers, underscores and
|
|
4
|
+
return /^[a-zA-Z0-9-_]+$/.test(name) ? true : 'Project name may only include letters, numbers, underscores and dashes.';
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
export const getProjectDetails = async (options = {}) => {
|
|
@@ -62,6 +62,14 @@ export const getProjectDetails = async (options = {}) => {
|
|
|
62
62
|
default: 'REST APIs',
|
|
63
63
|
when: !options.communication
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
type: 'list',
|
|
67
|
+
name: 'caching',
|
|
68
|
+
message: 'Caching Layer:',
|
|
69
|
+
choices: ['None', 'Redis'],
|
|
70
|
+
default: 'None',
|
|
71
|
+
when: (answers) => !options.caching && (options.database || answers.database) !== 'None'
|
|
72
|
+
},
|
|
65
73
|
{
|
|
66
74
|
type: 'list',
|
|
67
75
|
name: 'ciProvider',
|
package/package.json
CHANGED