nodejs-quickstart-structure 1.18.1 → 1.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (235) hide show
  1. package/CHANGELOG.md +309 -294
  2. package/LICENSE +15 -15
  3. package/README.md +2 -1
  4. package/lib/generator.js +139 -139
  5. package/lib/modules/app-setup.js +401 -401
  6. package/lib/modules/caching-setup.js +76 -73
  7. package/lib/modules/config-files.js +151 -151
  8. package/lib/modules/database-setup.js +116 -116
  9. package/lib/modules/kafka-setup.js +249 -191
  10. package/lib/modules/project-setup.js +32 -31
  11. package/lib/prompts.js +100 -100
  12. package/package.json +78 -67
  13. package/templates/clean-architecture/js/src/domain/models/User.js +9 -9
  14. package/templates/clean-architecture/js/src/errors/ApiError.js +14 -14
  15. package/templates/clean-architecture/js/src/errors/BadRequestError.js +11 -10
  16. package/templates/clean-architecture/js/src/errors/BadRequestError.spec.js.ejs +22 -21
  17. package/templates/clean-architecture/js/src/errors/NotFoundError.js +11 -10
  18. package/templates/clean-architecture/js/src/errors/NotFoundError.spec.js.ejs +22 -21
  19. package/templates/clean-architecture/js/src/index.js.ejs +55 -55
  20. package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +47 -47
  21. package/templates/clean-architecture/js/src/infrastructure/log/logger.js +36 -36
  22. package/templates/clean-architecture/js/src/infrastructure/log/logger.spec.js.ejs +63 -63
  23. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +69 -39
  24. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +142 -81
  25. package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +30 -30
  26. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +89 -89
  27. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +6 -6
  28. package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +156 -75
  29. package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +234 -138
  30. package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -13
  31. package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +31 -31
  32. package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -5
  33. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -6
  34. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +27 -21
  35. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +66 -49
  36. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -6
  37. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +19 -17
  38. package/templates/clean-architecture/js/src/interfaces/routes/api.js +12 -10
  39. package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +38 -38
  40. package/templates/clean-architecture/js/src/usecases/CreateUser.js +14 -14
  41. package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +51 -51
  42. package/templates/clean-architecture/js/src/usecases/DeleteUser.js +11 -0
  43. package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +47 -0
  44. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -12
  45. package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +61 -61
  46. package/templates/clean-architecture/js/src/usecases/UpdateUser.js +11 -0
  47. package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +48 -0
  48. package/templates/clean-architecture/js/src/utils/errorMessages.js +14 -0
  49. package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -9
  50. package/templates/clean-architecture/ts/src/config/env.ts.ejs +46 -46
  51. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +6 -6
  52. package/templates/clean-architecture/ts/src/domain/user.ts +7 -7
  53. package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -15
  54. package/templates/clean-architecture/ts/src/errors/BadRequestError.spec.ts.ejs +22 -21
  55. package/templates/clean-architecture/ts/src/errors/BadRequestError.ts +9 -8
  56. package/templates/clean-architecture/ts/src/errors/NotFoundError.spec.ts.ejs +22 -21
  57. package/templates/clean-architecture/ts/src/errors/NotFoundError.ts +9 -8
  58. package/templates/clean-architecture/ts/src/index.ts.ejs +139 -139
  59. package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +63 -63
  60. package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +36 -36
  61. package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +175 -85
  62. package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +74 -0
  63. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +331 -185
  64. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +173 -84
  65. package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +32 -32
  66. package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -17
  67. package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -3
  68. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -4
  69. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -51
  70. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +29 -21
  71. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -4
  72. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +17 -15
  73. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +40 -40
  74. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +13 -11
  75. package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +51 -51
  76. package/templates/clean-architecture/ts/src/usecases/createUser.ts +13 -13
  77. package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +47 -0
  78. package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +9 -0
  79. package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +63 -63
  80. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -10
  81. package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +48 -0
  82. package/templates/clean-architecture/ts/src/usecases/updateUser.ts +9 -0
  83. package/templates/clean-architecture/ts/src/utils/errorMessages.ts +12 -0
  84. package/templates/clean-architecture/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  85. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -7
  86. package/templates/common/.cursorrules.ejs +60 -60
  87. package/templates/common/.dockerignore +12 -12
  88. package/templates/common/.env.example.ejs +41 -41
  89. package/templates/common/.gitattributes +46 -0
  90. package/templates/common/.gitlab-ci.yml.ejs +86 -86
  91. package/templates/common/.lintstagedrc +6 -6
  92. package/templates/common/.prettierrc +7 -7
  93. package/templates/common/Dockerfile +73 -73
  94. package/templates/common/Jenkinsfile.ejs +87 -87
  95. package/templates/common/README.md.ejs +294 -270
  96. package/templates/common/SECURITY.md +20 -20
  97. package/templates/common/_github/workflows/ci.yml.ejs +46 -46
  98. package/templates/common/_github/workflows/security.yml.ejs +36 -36
  99. package/templates/common/_gitignore +5 -5
  100. package/templates/common/_husky/pre-commit +4 -4
  101. package/templates/common/caching/clean/js/CreateUser.js.ejs +29 -29
  102. package/templates/common/caching/clean/js/DeleteUser.js.ejs +27 -0
  103. package/templates/common/caching/clean/js/GetAllUsers.js.ejs +37 -37
  104. package/templates/common/caching/clean/js/UpdateUser.js.ejs +27 -0
  105. package/templates/common/caching/clean/ts/createUser.ts.ejs +27 -27
  106. package/templates/common/caching/clean/ts/deleteUser.ts.ejs +24 -0
  107. package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +34 -34
  108. package/templates/common/caching/clean/ts/updateUser.ts.ejs +25 -0
  109. package/templates/common/caching/js/memoryCache.js.ejs +60 -60
  110. package/templates/common/caching/js/memoryCache.spec.js.ejs +101 -101
  111. package/templates/common/caching/js/redisClient.js.ejs +75 -75
  112. package/templates/common/caching/js/redisClient.spec.js.ejs +147 -147
  113. package/templates/common/caching/ts/memoryCache.spec.ts.ejs +102 -102
  114. package/templates/common/caching/ts/memoryCache.ts.ejs +73 -64
  115. package/templates/common/caching/ts/redisClient.spec.ts.ejs +157 -157
  116. package/templates/common/caching/ts/redisClient.ts.ejs +89 -80
  117. package/templates/common/database/js/database.js.ejs +19 -19
  118. package/templates/common/database/js/database.spec.js.ejs +56 -56
  119. package/templates/common/database/js/models/User.js.ejs +79 -53
  120. package/templates/common/database/js/models/User.js.mongoose.ejs +23 -19
  121. package/templates/common/database/js/models/User.spec.js.ejs +94 -84
  122. package/templates/common/database/js/mongoose.js.ejs +33 -33
  123. package/templates/common/database/js/mongoose.spec.js.ejs +43 -43
  124. package/templates/common/database/ts/database.spec.ts.ejs +56 -56
  125. package/templates/common/database/ts/database.ts.ejs +21 -21
  126. package/templates/common/database/ts/models/User.spec.ts.ejs +100 -84
  127. package/templates/common/database/ts/models/User.ts.ejs +87 -61
  128. package/templates/common/database/ts/models/User.ts.mongoose.ejs +30 -25
  129. package/templates/common/database/ts/mongoose.spec.ts.ejs +42 -42
  130. package/templates/common/database/ts/mongoose.ts.ejs +28 -28
  131. package/templates/common/docker-compose.yml.ejs +159 -159
  132. package/templates/common/ecosystem.config.js.ejs +40 -40
  133. package/templates/common/eslint.config.mjs.ejs +77 -77
  134. package/templates/common/health/js/healthRoute.js.ejs +50 -47
  135. package/templates/common/health/js/healthRoute.spec.js.ejs +70 -70
  136. package/templates/common/health/ts/healthRoute.spec.ts.ejs +76 -76
  137. package/templates/common/health/ts/healthRoute.ts.ejs +49 -46
  138. package/templates/common/jest.config.js.ejs +32 -32
  139. package/templates/common/jest.e2e.config.js.ejs +8 -8
  140. package/templates/common/kafka/js/config/kafka.js +9 -9
  141. package/templates/common/kafka/js/config/kafka.spec.js.ejs +27 -27
  142. package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +30 -30
  143. package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -58
  144. package/templates/common/kafka/js/messaging/userEventSchema.js.ejs +12 -11
  145. package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -27
  146. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.js.ejs +44 -31
  147. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.spec.js.ejs +86 -49
  148. package/templates/common/kafka/js/services/kafkaService.js.ejs +93 -93
  149. package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +106 -106
  150. package/templates/common/kafka/js/utils/kafkaEvents.js.ejs +7 -0
  151. package/templates/common/kafka/ts/config/kafka.spec.ts.ejs +27 -27
  152. package/templates/common/kafka/ts/config/kafka.ts +7 -7
  153. package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -50
  154. package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -27
  155. package/templates/common/kafka/ts/messaging/userEventSchema.spec.ts.ejs +51 -51
  156. package/templates/common/kafka/ts/messaging/userEventSchema.ts.ejs +12 -11
  157. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.spec.ts.ejs +86 -49
  158. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.ts.ejs +38 -25
  159. package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +81 -81
  160. package/templates/common/kafka/ts/services/kafkaService.ts.ejs +95 -95
  161. package/templates/common/kafka/ts/utils/kafkaEvents.ts.ejs +5 -0
  162. package/templates/common/migrate-mongo-config.js.ejs +31 -31
  163. package/templates/common/migrations/init.js.ejs +23 -23
  164. package/templates/common/package.json.ejs +119 -118
  165. package/templates/common/prompts/add-feature.md.ejs +26 -26
  166. package/templates/common/prompts/project-context.md.ejs +43 -43
  167. package/templates/common/prompts/troubleshoot.md.ejs +28 -28
  168. package/templates/common/public/css/style.css +147 -147
  169. package/templates/common/scripts/run-e2e.js.ejs +63 -63
  170. package/templates/common/shutdown/js/gracefulShutdown.js.ejs +65 -61
  171. package/templates/common/shutdown/js/gracefulShutdown.spec.js.ejs +149 -160
  172. package/templates/common/shutdown/ts/gracefulShutdown.spec.ts.ejs +179 -158
  173. package/templates/common/shutdown/ts/gracefulShutdown.ts.ejs +59 -55
  174. package/templates/common/sonar-project.properties.ejs +27 -27
  175. package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +120 -49
  176. package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +120 -49
  177. package/templates/common/src/utils/errorMiddleware.spec.js.ejs +79 -79
  178. package/templates/common/src/utils/errorMiddleware.spec.ts.ejs +94 -94
  179. package/templates/common/swagger.yml.ejs +118 -66
  180. package/templates/common/tsconfig.json +22 -22
  181. package/templates/common/views/ejs/index.ejs +55 -55
  182. package/templates/common/views/pug/index.pug +40 -40
  183. package/templates/db/mysql/V1__Initial_Setup.sql.ejs +10 -9
  184. package/templates/db/postgres/V1__Initial_Setup.sql.ejs +10 -9
  185. package/templates/mvc/js/src/config/env.js.ejs +46 -46
  186. package/templates/mvc/js/src/config/swagger.js.ejs +6 -6
  187. package/templates/mvc/js/src/controllers/userController.js.ejs +246 -105
  188. package/templates/mvc/js/src/controllers/userController.spec.js.ejs +481 -209
  189. package/templates/mvc/js/src/errors/ApiError.js +14 -14
  190. package/templates/mvc/js/src/errors/BadRequestError.js +11 -10
  191. package/templates/mvc/js/src/errors/BadRequestError.spec.js.ejs +22 -21
  192. package/templates/mvc/js/src/errors/NotFoundError.js +11 -10
  193. package/templates/mvc/js/src/errors/NotFoundError.spec.js.ejs +22 -21
  194. package/templates/mvc/js/src/graphql/context.js.ejs +7 -7
  195. package/templates/mvc/js/src/graphql/context.spec.js.ejs +29 -29
  196. package/templates/mvc/js/src/graphql/index.js.ejs +5 -5
  197. package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -6
  198. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +25 -19
  199. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +64 -47
  200. package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -6
  201. package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +19 -17
  202. package/templates/mvc/js/src/index.js.ejs +136 -136
  203. package/templates/mvc/js/src/routes/api.js +10 -8
  204. package/templates/mvc/js/src/routes/api.spec.js.ejs +41 -36
  205. package/templates/mvc/js/src/utils/errorMessages.js +14 -0
  206. package/templates/mvc/js/src/utils/errorMiddleware.js +29 -29
  207. package/templates/mvc/js/src/utils/httpCodes.js +9 -9
  208. package/templates/mvc/js/src/utils/logger.js +40 -40
  209. package/templates/mvc/js/src/utils/logger.spec.js.ejs +63 -63
  210. package/templates/mvc/ts/src/config/env.ts.ejs +45 -45
  211. package/templates/mvc/ts/src/config/swagger.ts.ejs +6 -6
  212. package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +481 -203
  213. package/templates/mvc/ts/src/controllers/userController.ts.ejs +248 -107
  214. package/templates/mvc/ts/src/errors/ApiError.ts +15 -15
  215. package/templates/mvc/ts/src/errors/BadRequestError.spec.ts.ejs +22 -21
  216. package/templates/mvc/ts/src/errors/BadRequestError.ts +9 -8
  217. package/templates/mvc/ts/src/errors/NotFoundError.spec.ts.ejs +27 -21
  218. package/templates/mvc/ts/src/errors/NotFoundError.ts +9 -8
  219. package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +30 -30
  220. package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -12
  221. package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -3
  222. package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -4
  223. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -51
  224. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +29 -21
  225. package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -4
  226. package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +17 -15
  227. package/templates/mvc/ts/src/index.ts.ejs +156 -153
  228. package/templates/mvc/ts/src/routes/api.spec.ts.ejs +59 -40
  229. package/templates/mvc/ts/src/routes/api.ts +12 -10
  230. package/templates/mvc/ts/src/utils/errorMessages.ts +12 -0
  231. package/templates/mvc/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  232. package/templates/mvc/ts/src/utils/httpCodes.ts +7 -7
  233. package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +63 -63
  234. package/templates/mvc/ts/src/utils/logger.ts +36 -36
  235. package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.ts.ejs +0 -37
@@ -1,84 +1,173 @@
1
- <% if (communication !== 'GraphQL') { -%>
2
- import { Request, Response, NextFunction } from 'express';
3
- import { HTTP_STATUS } from '@/utils/httpCodes';
4
- <% } -%>
5
- import { UserRepository } from '@/infrastructure/repositories/UserRepository';
6
- import CreateUser from '@/usecases/createUser';
7
- import GetAllUsers from '@/usecases/getAllUsers';
8
- import logger from '@/infrastructure/log/logger';
9
- <%_ if (communication === 'Kafka') { -%>
10
- import { kafkaService } from '@/infrastructure/messaging/kafkaClient';
11
- <%_ } -%>
12
-
13
- export class UserController {
14
- private createUserUseCase: CreateUser;
15
- private getAllUsersUseCase: GetAllUsers;
16
-
17
- constructor() {
18
- const userRepository = new UserRepository();
19
- this.createUserUseCase = new CreateUser(userRepository);
20
- this.getAllUsersUseCase = new GetAllUsers(userRepository);
21
- }
22
-
23
- <% if (communication === 'GraphQL') { -%>
24
- async createUser(data: { name: string, email: string }) {
25
- try {
26
- const { name, email } = data;
27
- const user = await this.createUserUseCase.execute(name, email);
28
- <%_ if (communication === 'Kafka') { -%>
29
- await kafkaService.sendMessage('user-topic', JSON.stringify({
30
- action: 'USER_CREATED',
31
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
- payload: { id: (user as any).id || (user as any)._id, email: user.email }
33
- }));
34
- <%_ } -%>
35
- return user;
36
- } catch (error: unknown) {
37
- const message = error instanceof Error ? error.message : 'Unknown error';
38
- logger.error('UserController CreateUser Error:', message);
39
- throw error;
40
- }
41
- }
42
-
43
- async getUsers() {
44
- try {
45
- const users = await this.getAllUsersUseCase.execute();
46
- return users;
47
- } catch (error: unknown) {
48
- const message = error instanceof Error ? error.message : 'Unknown error';
49
- logger.error('UserController GetUsers Error:', message);
50
- throw error;
51
- }
52
- }
53
- <% } else { -%>
54
- async createUser(req: Request, res: Response, next: NextFunction) {
55
- try {
56
- const { name, email } = req.body;
57
- const user = await this.createUserUseCase.execute(name, email);
58
- <%_ if (communication === 'Kafka') { -%>
59
- await kafkaService.sendMessage('user-topic', JSON.stringify({
60
- action: 'USER_CREATED',
61
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
62
- payload: { id: (user as any).id || (user as any)._id, email: user.email }
63
- }));
64
- <%_ } -%>
65
- res.status(HTTP_STATUS.CREATED).json(user);
66
- } catch (error: unknown) {
67
- const message = error instanceof Error ? error.message : 'Unknown error';
68
- logger.error('UserController CreateUser Error:', message);
69
- next(error);
70
- }
71
- }
72
-
73
- async getUsers(req: Request, res: Response, next: NextFunction) {
74
- try {
75
- const users = await this.getAllUsersUseCase.execute();
76
- res.json(users);
77
- } catch (error: unknown) {
78
- const message = error instanceof Error ? error.message : 'Unknown error';
79
- logger.error('UserController GetUsers Error:', message);
80
- next(error);
81
- }
82
- }
83
- <% } -%>
84
- }
1
+ import { ERROR_MESSAGES } from '@/utils/errorMessages';
2
+ <% if (communication !== 'GraphQL') { -%>
3
+ import { Request, Response, NextFunction } from 'express';
4
+ import { HTTP_STATUS } from '@/utils/httpCodes';
5
+ <% } -%>
6
+ import { UserRepository } from '@/infrastructure/repositories/UserRepository';
7
+ import CreateUser from '@/usecases/createUser';
8
+ import GetAllUsers from '@/usecases/getAllUsers';
9
+ import UpdateUser from '@/usecases/updateUser';
10
+ import DeleteUser from '@/usecases/deleteUser';
11
+ import logger from '@/infrastructure/log/logger';
12
+ <%_ if (communication === 'Kafka') { -%>
13
+ import { kafkaService } from '@/infrastructure/messaging/kafkaClient';
14
+ import { KAFKA_ACTIONS } from '@/utils/kafkaEvents';
15
+ <%_ } -%>
16
+
17
+ export class UserController {
18
+ private createUserUseCase: CreateUser;
19
+ private getAllUsersUseCase: GetAllUsers;
20
+ private updateUserUseCase: UpdateUser;
21
+ private deleteUserUseCase: DeleteUser;
22
+
23
+ constructor() {
24
+ const userRepository = new UserRepository();
25
+ this.createUserUseCase = new CreateUser(userRepository);
26
+ this.getAllUsersUseCase = new GetAllUsers(userRepository);
27
+ this.updateUserUseCase = new UpdateUser(userRepository);
28
+ this.deleteUserUseCase = new DeleteUser(userRepository);
29
+ }
30
+
31
+ <% if (communication === 'GraphQL') { -%>
32
+ async createUser(data: { name: string, email: string }) {
33
+ try {
34
+ const { name, email } = data;
35
+ const user = await this.createUserUseCase.execute(name, email);
36
+ <%_ if (communication === 'Kafka') { -%>
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ const userId = (user as any).id || (user as any)._id;
39
+ await kafkaService.sendMessage('user-topic', JSON.stringify({
40
+ action: KAFKA_ACTIONS.USER_CREATED,
41
+ payload: { id: userId, email: user.email }
42
+ }), userId?.toString() || '');
43
+ <%_ } -%>
44
+ return user;
45
+ } catch (error: unknown) {
46
+ const message = error instanceof Error ? error.message : 'Unknown error';
47
+ logger.error(`${ERROR_MESSAGES.CREATE_USER_ERROR}:`, message);
48
+ throw error;
49
+ }
50
+ }
51
+
52
+ async getUsers() {
53
+ try {
54
+ const users = await this.getAllUsersUseCase.execute();
55
+ return users;
56
+ } catch (error: unknown) {
57
+ const message = error instanceof Error ? error.message : 'Unknown error';
58
+ logger.error(`${ERROR_MESSAGES.FETCH_USERS_ERROR}:`, message);
59
+ throw error;
60
+ }
61
+ }
62
+
63
+ async updateUser(id: string, data: { name?: string, email?: string }) {
64
+ try {
65
+ const user = await this.updateUserUseCase.execute(id, data);
66
+ if (!user) throw new Error(ERROR_MESSAGES.USER_NOT_FOUND);
67
+ <%_ if (communication === 'Kafka') { -%>
68
+ await kafkaService.sendMessage('user-topic', JSON.stringify({
69
+ action: KAFKA_ACTIONS.USER_UPDATED,
70
+ payload: { id, email: user.email }
71
+ }), id);
72
+ <%_ } -%>
73
+ return user;
74
+ } catch (error: unknown) {
75
+ const message = error instanceof Error ? error.message : 'Unknown error';
76
+ logger.error(`${ERROR_MESSAGES.UPDATE_USER_ERROR}:`, message);
77
+ throw error;
78
+ }
79
+ }
80
+
81
+ async deleteUser(id: string) {
82
+ try {
83
+ const deleted = await this.deleteUserUseCase.execute(id);
84
+ if (!deleted) throw new Error(ERROR_MESSAGES.USER_NOT_FOUND);
85
+ <%_ if (communication === 'Kafka') { -%>
86
+ await kafkaService.sendMessage('user-topic', JSON.stringify({
87
+ action: KAFKA_ACTIONS.USER_DELETED,
88
+ payload: { id }
89
+ }), id);
90
+ <%_ } -%>
91
+ return true;
92
+ } catch (error: unknown) {
93
+ const message = error instanceof Error ? error.message : 'Unknown error';
94
+ logger.error(`${ERROR_MESSAGES.DELETE_USER_ERROR}:`, message);
95
+ throw error;
96
+ }
97
+ }
98
+ <% } else { -%>
99
+ async createUser(req: Request, res: Response, next: NextFunction) {
100
+ try {
101
+ const { name, email } = req.body || {};
102
+ const user = await this.createUserUseCase.execute(name, email);
103
+ <%_ if (communication === 'Kafka') { -%>
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ const userId = (user as any).id || (user as any)._id;
106
+ await kafkaService.sendMessage('user-topic', JSON.stringify({
107
+ action: KAFKA_ACTIONS.USER_CREATED,
108
+ payload: { id: userId, email: user.email }
109
+ }), userId?.toString() || '');
110
+ <%_ } -%>
111
+ res.status(HTTP_STATUS.CREATED).json(user);
112
+ } catch (error: unknown) {
113
+ const message = error instanceof Error ? error.message : 'Unknown error';
114
+ logger.error(`${ERROR_MESSAGES.CREATE_USER_ERROR}:`, message);
115
+ next(error);
116
+ }
117
+ }
118
+
119
+ async getUsers(req: Request, res: Response, next: NextFunction) {
120
+ try {
121
+ const users = await this.getAllUsersUseCase.execute();
122
+ res.json(users);
123
+ } catch (error: unknown) {
124
+ const message = error instanceof Error ? error.message : 'Unknown error';
125
+ logger.error(`${ERROR_MESSAGES.FETCH_USERS_ERROR}:`, message);
126
+ next(error);
127
+ }
128
+ }
129
+
130
+ async updateUser(req: Request, res: Response, next: NextFunction) {
131
+ try {
132
+ const { id } = req.params;
133
+ const { name, email } = req.body || {};
134
+ const user = await this.updateUserUseCase.execute(id, { name, email });
135
+ if (!user) {
136
+ return res.status(HTTP_STATUS.NOT_FOUND).json({ error: ERROR_MESSAGES.USER_NOT_FOUND });
137
+ }
138
+ <%_ if (communication === 'Kafka') { -%>
139
+ await kafkaService.sendMessage('user-topic', JSON.stringify({
140
+ action: KAFKA_ACTIONS.USER_UPDATED,
141
+ payload: { id, email: user.email }
142
+ }), id);
143
+ <%_ } -%>
144
+ res.json(user);
145
+ } catch (error: unknown) {
146
+ const message = error instanceof Error ? error.message : 'Unknown error';
147
+ logger.error(`${ERROR_MESSAGES.UPDATE_USER_ERROR}:`, message);
148
+ next(error);
149
+ }
150
+ }
151
+
152
+ async deleteUser(req: Request, res: Response, next: NextFunction) {
153
+ try {
154
+ const { id } = req.params;
155
+ const deleted = await this.deleteUserUseCase.execute(id);
156
+ if (!deleted) {
157
+ return res.status(HTTP_STATUS.NOT_FOUND).json({ error: ERROR_MESSAGES.USER_NOT_FOUND });
158
+ }
159
+ <%_ if (communication === 'Kafka') { -%>
160
+ await kafkaService.sendMessage('user-topic', JSON.stringify({
161
+ action: KAFKA_ACTIONS.USER_DELETED,
162
+ payload: { id }
163
+ }), id);
164
+ <%_ } -%>
165
+ res.status(HTTP_STATUS.OK).json({ message: 'User deleted successfully' });
166
+ } catch (error: unknown) {
167
+ const message = error instanceof Error ? error.message : 'Unknown error';
168
+ logger.error(`${ERROR_MESSAGES.DELETE_USER_ERROR}:`, message);
169
+ next(error);
170
+ }
171
+ }
172
+ <% } -%>
173
+ }
@@ -1,32 +1,32 @@
1
- import { gqlContext } from '@/interfaces/graphql/context';
2
- import { Request } from 'express';
3
- import { resolvers } from '@/interfaces/graphql/resolvers';
4
- import { typeDefs } from '@/interfaces/graphql/typeDefs';
5
-
6
- jest.mock('@/infrastructure/repositories/UserRepository');
7
-
8
- describe('GraphQL Context', () => {
9
- it('should exercise GraphQL index entry points', () => {
10
- expect(resolvers).toBeDefined();
11
- expect(typeDefs).toBeDefined();
12
- });
13
- it('should return context with token when authorization header is present', async () => {
14
- const mockRequest = {
15
- headers: {
16
- authorization: 'Bearer token123',
17
- },
18
- } as Request;
19
-
20
- const context = await gqlContext({ req: mockRequest });
21
- expect(context.token).toBe('Bearer token123');
22
- });
23
-
24
- it('should return context with empty token when authorization header is missing', async () => {
25
- const mockRequest = {
26
- headers: {},
27
- } as Request;
28
-
29
- const context = await gqlContext({ req: mockRequest });
30
- expect(context.token).toBe('');
31
- });
32
- });
1
+ import { gqlContext } from '@/interfaces/graphql/context';
2
+ import { Request } from 'express';
3
+ import { resolvers } from '@/interfaces/graphql/resolvers';
4
+ import { typeDefs } from '@/interfaces/graphql/typeDefs';
5
+
6
+ jest.mock('@/infrastructure/repositories/UserRepository');
7
+
8
+ describe('GraphQL Context', () => {
9
+ it('should exercise GraphQL index entry points', () => {
10
+ expect(resolvers).toBeDefined();
11
+ expect(typeDefs).toBeDefined();
12
+ });
13
+ it('should return context with token when authorization header is present', async () => {
14
+ const mockRequest = {
15
+ headers: {
16
+ authorization: 'Bearer token123',
17
+ },
18
+ } as Request;
19
+
20
+ const context = await gqlContext({ req: mockRequest });
21
+ expect(context.token).toBe('Bearer token123');
22
+ });
23
+
24
+ it('should return context with empty token when authorization header is missing', async () => {
25
+ const mockRequest = {
26
+ headers: {},
27
+ } as Request;
28
+
29
+ const context = await gqlContext({ req: mockRequest });
30
+ expect(context.token).toBe('');
31
+ });
32
+ });
@@ -1,17 +1,17 @@
1
- import { Request } from 'express';
2
- import { UserRepository } from '@/infrastructure/repositories/UserRepository';
3
-
4
- export interface MyContext {
5
- token?: string;
6
- userRepository: UserRepository;
7
- }
8
-
9
- export const gqlContext = async ({ req }: { req: Request }): Promise<MyContext> => {
10
- const token = req.headers.authorization || '';
11
- const userRepository = new UserRepository();
12
-
13
- return {
14
- token,
15
- userRepository
16
- };
17
- };
1
+ import { Request } from 'express';
2
+ import { UserRepository } from '@/infrastructure/repositories/UserRepository';
3
+
4
+ export interface MyContext {
5
+ token?: string;
6
+ userRepository: UserRepository;
7
+ }
8
+
9
+ export const gqlContext = async ({ req }: { req: Request }): Promise<MyContext> => {
10
+ const token = req.headers.authorization || '';
11
+ const userRepository = new UserRepository();
12
+
13
+ return {
14
+ token,
15
+ userRepository
16
+ };
17
+ };
@@ -1,3 +1,3 @@
1
- export { typeDefs } from '@/interfaces/graphql/typeDefs';
2
- export { resolvers } from '@/interfaces/graphql/resolvers';
3
- export { gqlContext, MyContext } from '@/interfaces/graphql/context';
1
+ export { typeDefs } from '@/interfaces/graphql/typeDefs';
2
+ export { resolvers } from '@/interfaces/graphql/resolvers';
3
+ export { gqlContext, MyContext } from '@/interfaces/graphql/context';
@@ -1,4 +1,4 @@
1
- import { mergeResolvers } from '@graphql-tools/merge';
2
- import { userResolvers } from '@/interfaces/graphql/resolvers/user.resolvers';
3
-
4
- export const resolvers = mergeResolvers([userResolvers]);
1
+ import { mergeResolvers } from '@graphql-tools/merge';
2
+ import { userResolvers } from '@/interfaces/graphql/resolvers/user.resolvers';
3
+
4
+ export const resolvers = mergeResolvers([userResolvers]);
@@ -1,51 +1,68 @@
1
- import { userResolvers } from '@/interfaces/graphql/resolvers/user.resolvers';
2
-
3
- const mockGetUsers = jest.fn().mockResolvedValue([{ id: '1', name: 'John Doe', email: 'john@example.com' }]);
4
- const mockCreateUser = jest.fn().mockResolvedValue({ id: '1', name: 'Jane', email: 'jane@example.com' });
5
-
6
- jest.mock('@/interfaces/controllers/userController', () => {
7
- return {
8
- UserController: jest.fn().mockImplementation(() => ({
9
- getUsers: (...args: unknown[]) => mockGetUsers(...args),
10
- createUser: (...args: unknown[]) => mockCreateUser(...args)
11
- }))
12
- };
13
- });
14
-
15
- describe('User Resolvers', () => {
16
- afterEach(() => {
17
- jest.clearAllMocks();
18
- });
19
-
20
- describe('Query.getAllUsers', () => {
21
- it('should return all users', async () => {
22
- const result = await userResolvers.Query.getAllUsers();
23
- expect(result).toEqual([{ id: '1', name: 'John Doe', email: 'john@example.com' }]);
24
- expect(mockGetUsers).toHaveBeenCalledTimes(1);
25
- });
26
- });
27
-
28
- describe('Mutation.createUser', () => {
29
- it('should create and return a new user', async () => {
30
- const result = await userResolvers.Mutation.createUser(null, { name: 'Jane', email: 'jane@example.com' });
31
- expect(result).toEqual({ id: '1', name: 'Jane', email: 'jane@example.com' });
32
- expect(mockCreateUser).toHaveBeenCalledWith({ name: 'Jane', email: 'jane@example.com' });
33
- expect(mockCreateUser).toHaveBeenCalledTimes(1);
34
- });
35
- });
36
- <%_ if (database === 'MongoDB') { -%>
37
- describe('User.id', () => {
38
- it('should return parent.id if available', () => {
39
- const parent = { id: '123' };
40
- const result = userResolvers.User.id(parent as { id?: string; _id?: unknown });
41
- expect(result).toBe('123');
42
- });
43
-
44
- it('should fallback to parent._id if id is not available', () => {
45
- const parent = { _id: '456' };
46
- const result = userResolvers.User.id(parent as { id?: string; _id?: unknown });
47
- expect(result).toBe('456');
48
- });
49
- });
50
- <%_ } -%>
51
- });
1
+ import { userResolvers } from '@/interfaces/graphql/resolvers/user.resolvers';
2
+
3
+ const mockGetUsers = jest.fn().mockResolvedValue([{ id: '1', name: 'John Doe', email: 'john@example.com' }]);
4
+ const mockCreateUser = jest.fn().mockResolvedValue({ id: '1', name: 'Jane', email: 'jane@example.com' });
5
+
6
+ jest.mock('@/interfaces/controllers/userController', () => {
7
+ return {
8
+ UserController: jest.fn().mockImplementation(() => ({
9
+ getUsers: (...args: unknown[]) => mockGetUsers(...args),
10
+ createUser: (...args: unknown[]) => mockCreateUser(...args),
11
+ updateUser: jest.fn().mockImplementation((id, data) => Promise.resolve({ id, ...data })),
12
+ deleteUser: jest.fn().mockImplementation(() => Promise.resolve(true))
13
+ }))
14
+ };
15
+ });
16
+
17
+ describe('User Resolvers', () => {
18
+ afterEach(() => {
19
+ jest.clearAllMocks();
20
+ });
21
+
22
+ describe('Query.getAllUsers', () => {
23
+ it('should return all users', async () => {
24
+ const result = await userResolvers.Query.getAllUsers();
25
+ expect(result).toEqual([{ id: '1', name: 'John Doe', email: 'john@example.com' }]);
26
+ expect(mockGetUsers).toHaveBeenCalledTimes(1);
27
+ });
28
+ });
29
+
30
+ describe('Mutation.createUser', () => {
31
+ it('should create and return a new user', async () => {
32
+ const result = await userResolvers.Mutation.createUser(null, { name: 'Jane', email: 'jane@example.com' });
33
+ expect(result).toEqual({ id: '1', name: 'Jane', email: 'jane@example.com' });
34
+ expect(mockCreateUser).toHaveBeenCalledWith({ name: 'Jane', email: 'jane@example.com' });
35
+ expect(mockCreateUser).toHaveBeenCalledTimes(1);
36
+ });
37
+ });
38
+
39
+ describe('Mutation.updateUser', () => {
40
+ it('should update and return the user', async () => {
41
+ const payload = { name: 'Updated' };
42
+ const result = await userResolvers.Mutation.updateUser(null, { id: '1', ...payload });
43
+ expect(result).toMatchObject(payload);
44
+ });
45
+ });
46
+
47
+ describe('Mutation.deleteUser', () => {
48
+ it('should delete and return true', async () => {
49
+ const result = await userResolvers.Mutation.deleteUser(null, { id: '1' });
50
+ expect(result).toBe(true);
51
+ });
52
+ });
53
+ <%_ if (database === 'MongoDB') { -%>
54
+ describe('User.id', () => {
55
+ it('should return parent.id if available', () => {
56
+ const parent = { id: '123' };
57
+ const result = userResolvers.User.id(parent as { id?: string; _id?: unknown });
58
+ expect(result).toBe('123');
59
+ });
60
+
61
+ it('should fallback to parent._id if id is not available', () => {
62
+ const parent = { _id: '456' };
63
+ const result = userResolvers.User.id(parent as { id?: string; _id?: unknown });
64
+ expect(result).toBe('456');
65
+ });
66
+ });
67
+ <%_ } -%>
68
+ });
@@ -1,21 +1,29 @@
1
- import { UserController } from '@/interfaces/controllers/userController';
2
-
3
- const userController = new UserController();
4
-
5
- export const userResolvers = {
6
- Query: {
7
- getAllUsers: async () => {
8
- const users = await userController.getUsers();
9
- return users;
10
- }
11
- },
12
- Mutation: {
13
- createUser: async (_: unknown, { name, email }: { name: string, email: string }) => {
14
- const user = await userController.createUser({ name, email });
15
- return user;
16
- }
17
- }<%_ if (database === 'MongoDB') { -%>,
18
- User: {
19
- id: (parent: { id?: string; _id?: unknown }) => parent.id || parent._id
20
- }<%_ } %>
21
- };
1
+ import { UserController } from '@/interfaces/controllers/userController';
2
+
3
+ const userController = new UserController();
4
+
5
+ export const userResolvers = {
6
+ Query: {
7
+ getAllUsers: async () => {
8
+ const users = await userController.getUsers();
9
+ return users;
10
+ }
11
+ },
12
+ Mutation: {
13
+ createUser: async (_: unknown, { name, email }: { name: string, email: string }) => {
14
+ const user = await userController.createUser({ name, email });
15
+ return user;
16
+ },
17
+ updateUser: async (_: unknown, { id, name, email }: { id: string, name?: string, email?: string }) => {
18
+ const user = await userController.updateUser(id, { name, email });
19
+ return user;
20
+ },
21
+ deleteUser: async (_: unknown, { id }: { id: string }) => {
22
+ const result = await userController.deleteUser(id);
23
+ return result;
24
+ }
25
+ }<%_ if (database === 'MongoDB') { -%>,
26
+ User: {
27
+ id: (parent: { id?: string; _id?: unknown }) => parent.id || parent._id
28
+ }<%_ } %>
29
+ };
@@ -1,4 +1,4 @@
1
- import { mergeTypeDefs } from '@graphql-tools/merge';
2
- import { userTypes } from './user.types';
3
-
4
- export const typeDefs = mergeTypeDefs([userTypes]);
1
+ import { mergeTypeDefs } from '@graphql-tools/merge';
2
+ import { userTypes } from './user.types';
3
+
4
+ export const typeDefs = mergeTypeDefs([userTypes]);
@@ -1,15 +1,17 @@
1
- export const userTypes = `#graphql
2
- type User {
3
- id: ID!
4
- name: String!
5
- email: String!
6
- }
7
-
8
- type Query {
9
- getAllUsers: [User]
10
- }
11
-
12
- type Mutation {
13
- createUser(name: String!, email: String!): User
14
- }
15
- `;
1
+ export const userTypes = `#graphql
2
+ type User {
3
+ id: ID!
4
+ name: String!
5
+ email: String!
6
+ }
7
+
8
+ type Query {
9
+ getAllUsers: [User]
10
+ }
11
+
12
+ type Mutation {
13
+ createUser(name: String!, email: String!): User
14
+ updateUser(id: ID!, name: String, email: String): User
15
+ deleteUser(id: ID!): Boolean
16
+ }
17
+ `;