nodejs-structure-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (243) hide show
  1. package/README.md +32 -0
  2. package/bin/index.js +143 -0
  3. package/lib/generator.js +145 -0
  4. package/lib/modules/app-setup.js +479 -0
  5. package/lib/modules/caching-setup.js +76 -0
  6. package/lib/modules/config-files.js +151 -0
  7. package/lib/modules/database-setup.js +116 -0
  8. package/lib/modules/kafka-setup.js +249 -0
  9. package/lib/modules/project-setup.js +32 -0
  10. package/lib/prompts.js +128 -0
  11. package/package.json +66 -0
  12. package/templates/clean-architecture/js/src/domain/models/User.js.ejs +11 -0
  13. package/templates/clean-architecture/js/src/errors/ApiError.js +14 -0
  14. package/templates/clean-architecture/js/src/errors/BadRequestError.js +11 -0
  15. package/templates/clean-architecture/js/src/errors/BadRequestError.spec.js.ejs +22 -0
  16. package/templates/clean-architecture/js/src/errors/NotFoundError.js +11 -0
  17. package/templates/clean-architecture/js/src/errors/NotFoundError.spec.js.ejs +22 -0
  18. package/templates/clean-architecture/js/src/index.js.ejs +56 -0
  19. package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +47 -0
  20. package/templates/clean-architecture/js/src/infrastructure/log/logger.js +36 -0
  21. package/templates/clean-architecture/js/src/infrastructure/log/logger.spec.js.ejs +63 -0
  22. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +88 -0
  23. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +142 -0
  24. package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +30 -0
  25. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +93 -0
  26. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +6 -0
  27. package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +190 -0
  28. package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +234 -0
  29. package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -0
  30. package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +31 -0
  31. package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -0
  32. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -0
  33. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +27 -0
  34. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +66 -0
  35. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -0
  36. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +19 -0
  37. package/templates/clean-architecture/js/src/interfaces/routes/api.js.ejs +17 -0
  38. package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +38 -0
  39. package/templates/clean-architecture/js/src/usecases/CreateUser.js.ejs +14 -0
  40. package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +51 -0
  41. package/templates/clean-architecture/js/src/usecases/DeleteUser.js +11 -0
  42. package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +47 -0
  43. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -0
  44. package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +61 -0
  45. package/templates/clean-architecture/js/src/usecases/UpdateUser.js.ejs +11 -0
  46. package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +48 -0
  47. package/templates/clean-architecture/js/src/utils/errorMessages.js +14 -0
  48. package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -0
  49. package/templates/clean-architecture/ts/src/config/env.ts.ejs +46 -0
  50. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +6 -0
  51. package/templates/clean-architecture/ts/src/domain/user.ts.ejs +9 -0
  52. package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -0
  53. package/templates/clean-architecture/ts/src/errors/BadRequestError.spec.ts.ejs +22 -0
  54. package/templates/clean-architecture/ts/src/errors/BadRequestError.ts +9 -0
  55. package/templates/clean-architecture/ts/src/errors/NotFoundError.spec.ts.ejs +22 -0
  56. package/templates/clean-architecture/ts/src/errors/NotFoundError.ts +9 -0
  57. package/templates/clean-architecture/ts/src/index.ts.ejs +144 -0
  58. package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +63 -0
  59. package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +36 -0
  60. package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +175 -0
  61. package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +125 -0
  62. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +331 -0
  63. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +208 -0
  64. package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +32 -0
  65. package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -0
  66. package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -0
  67. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -0
  68. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -0
  69. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +29 -0
  70. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -0
  71. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +17 -0
  72. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +40 -0
  73. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts.ejs +18 -0
  74. package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +51 -0
  75. package/templates/clean-architecture/ts/src/usecases/createUser.ts.ejs +11 -0
  76. package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +47 -0
  77. package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +9 -0
  78. package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +63 -0
  79. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -0
  80. package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +48 -0
  81. package/templates/clean-architecture/ts/src/usecases/updateUser.ts.ejs +10 -0
  82. package/templates/clean-architecture/ts/src/utils/errorMessages.ts +12 -0
  83. package/templates/clean-architecture/ts/src/utils/errorMiddleware.ts.ejs +27 -0
  84. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -0
  85. package/templates/common/.cursorrules.ejs +60 -0
  86. package/templates/common/.dockerignore +12 -0
  87. package/templates/common/.env.example.ejs +60 -0
  88. package/templates/common/.gitattributes +46 -0
  89. package/templates/common/.gitlab-ci.yml.ejs +86 -0
  90. package/templates/common/.lintstagedrc +6 -0
  91. package/templates/common/.prettierrc +7 -0
  92. package/templates/common/.snyk.ejs +45 -0
  93. package/templates/common/Dockerfile +73 -0
  94. package/templates/common/Jenkinsfile.ejs +87 -0
  95. package/templates/common/README.md.ejs +148 -0
  96. package/templates/common/_github/workflows/ci.yml.ejs +46 -0
  97. package/templates/common/_github/workflows/security.yml.ejs +36 -0
  98. package/templates/common/_gitignore +5 -0
  99. package/templates/common/_husky/pre-commit +4 -0
  100. package/templates/common/caching/clean/js/CreateUser.js.ejs +29 -0
  101. package/templates/common/caching/clean/js/DeleteUser.js.ejs +27 -0
  102. package/templates/common/caching/clean/js/GetAllUsers.js.ejs +37 -0
  103. package/templates/common/caching/clean/js/UpdateUser.js.ejs +27 -0
  104. package/templates/common/caching/clean/ts/createUser.ts.ejs +27 -0
  105. package/templates/common/caching/clean/ts/deleteUser.ts.ejs +24 -0
  106. package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +34 -0
  107. package/templates/common/caching/clean/ts/updateUser.ts.ejs +25 -0
  108. package/templates/common/caching/js/memoryCache.js.ejs +60 -0
  109. package/templates/common/caching/js/memoryCache.spec.js.ejs +101 -0
  110. package/templates/common/caching/js/redisClient.js.ejs +75 -0
  111. package/templates/common/caching/js/redisClient.spec.js.ejs +147 -0
  112. package/templates/common/caching/ts/memoryCache.spec.ts.ejs +102 -0
  113. package/templates/common/caching/ts/memoryCache.ts.ejs +73 -0
  114. package/templates/common/caching/ts/redisClient.spec.ts.ejs +157 -0
  115. package/templates/common/caching/ts/redisClient.ts.ejs +89 -0
  116. package/templates/common/database/js/database.js.ejs +19 -0
  117. package/templates/common/database/js/database.spec.js.ejs +56 -0
  118. package/templates/common/database/js/models/User.js.ejs +91 -0
  119. package/templates/common/database/js/models/User.js.mongoose.ejs +35 -0
  120. package/templates/common/database/js/models/User.spec.js.ejs +94 -0
  121. package/templates/common/database/js/mongoose.js.ejs +33 -0
  122. package/templates/common/database/js/mongoose.spec.js.ejs +43 -0
  123. package/templates/common/database/ts/database.spec.ts.ejs +56 -0
  124. package/templates/common/database/ts/database.ts.ejs +21 -0
  125. package/templates/common/database/ts/models/User.spec.ts.ejs +100 -0
  126. package/templates/common/database/ts/models/User.ts.ejs +102 -0
  127. package/templates/common/database/ts/models/User.ts.mongoose.ejs +34 -0
  128. package/templates/common/database/ts/mongoose.spec.ts.ejs +42 -0
  129. package/templates/common/database/ts/mongoose.ts.ejs +28 -0
  130. package/templates/common/docker-compose.yml.ejs +159 -0
  131. package/templates/common/ecosystem.config.js.ejs +40 -0
  132. package/templates/common/eslint.config.mjs.ejs +77 -0
  133. package/templates/common/health/js/healthRoute.js.ejs +50 -0
  134. package/templates/common/health/js/healthRoute.spec.js.ejs +70 -0
  135. package/templates/common/health/ts/healthRoute.spec.ts.ejs +76 -0
  136. package/templates/common/health/ts/healthRoute.ts.ejs +49 -0
  137. package/templates/common/jest.config.js.ejs +32 -0
  138. package/templates/common/jest.e2e.config.js.ejs +8 -0
  139. package/templates/common/kafka/js/config/kafka.js +9 -0
  140. package/templates/common/kafka/js/config/kafka.spec.js.ejs +27 -0
  141. package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +30 -0
  142. package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -0
  143. package/templates/common/kafka/js/messaging/userEventSchema.js.ejs +12 -0
  144. package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -0
  145. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.js.ejs +44 -0
  146. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.spec.js.ejs +86 -0
  147. package/templates/common/kafka/js/services/kafkaService.js.ejs +93 -0
  148. package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +106 -0
  149. package/templates/common/kafka/js/utils/kafkaEvents.js.ejs +7 -0
  150. package/templates/common/kafka/ts/config/kafka.spec.ts.ejs +27 -0
  151. package/templates/common/kafka/ts/config/kafka.ts +7 -0
  152. package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -0
  153. package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -0
  154. package/templates/common/kafka/ts/messaging/userEventSchema.spec.ts.ejs +51 -0
  155. package/templates/common/kafka/ts/messaging/userEventSchema.ts.ejs +12 -0
  156. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.spec.ts.ejs +86 -0
  157. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.ts.ejs +38 -0
  158. package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +81 -0
  159. package/templates/common/kafka/ts/services/kafkaService.ts.ejs +95 -0
  160. package/templates/common/kafka/ts/utils/kafkaEvents.ts.ejs +5 -0
  161. package/templates/common/migrate-mongo-config.js.ejs +31 -0
  162. package/templates/common/migrations/init.js.ejs +23 -0
  163. package/templates/common/package.json.ejs +137 -0
  164. package/templates/common/prompts/add-feature.md.ejs +26 -0
  165. package/templates/common/prompts/project-context.md.ejs +43 -0
  166. package/templates/common/prompts/troubleshoot.md.ejs +28 -0
  167. package/templates/common/public/css/style.css +147 -0
  168. package/templates/common/scripts/run-e2e.js.ejs +63 -0
  169. package/templates/common/shutdown/js/gracefulShutdown.js.ejs +65 -0
  170. package/templates/common/shutdown/js/gracefulShutdown.spec.js.ejs +149 -0
  171. package/templates/common/shutdown/ts/gracefulShutdown.spec.ts.ejs +179 -0
  172. package/templates/common/shutdown/ts/gracefulShutdown.ts.ejs +59 -0
  173. package/templates/common/sonar-project.properties.ejs +27 -0
  174. package/templates/common/src/config/auth.js.ejs +19 -0
  175. package/templates/common/src/config/auth.ts.ejs +19 -0
  176. package/templates/common/src/controllers/authController.js.ejs +101 -0
  177. package/templates/common/src/controllers/authController.ts.ejs +101 -0
  178. package/templates/common/src/middleware/auth.js.ejs +20 -0
  179. package/templates/common/src/middleware/auth.ts.ejs +25 -0
  180. package/templates/common/src/middleware/upload.js.ejs +31 -0
  181. package/templates/common/src/middleware/upload.ts.ejs +32 -0
  182. package/templates/common/src/routes/authRoutes.js.ejs +20 -0
  183. package/templates/common/src/routes/authRoutes.ts.ejs +20 -0
  184. package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +120 -0
  185. package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +120 -0
  186. package/templates/common/src/utils/errorMiddleware.spec.js.ejs +79 -0
  187. package/templates/common/src/utils/errorMiddleware.spec.ts.ejs +94 -0
  188. package/templates/common/swagger.yml.ejs +118 -0
  189. package/templates/common/tsconfig.json +23 -0
  190. package/templates/common/views/ejs/index.ejs +55 -0
  191. package/templates/common/views/pug/index.pug +40 -0
  192. package/templates/db/mysql/V1__Initial_Setup.sql.ejs +10 -0
  193. package/templates/db/postgres/V1__Initial_Setup.sql.ejs +10 -0
  194. package/templates/mvc/js/src/config/env.js.ejs +46 -0
  195. package/templates/mvc/js/src/config/swagger.js.ejs +6 -0
  196. package/templates/mvc/js/src/controllers/userController.js.ejs +288 -0
  197. package/templates/mvc/js/src/controllers/userController.spec.js.ejs +481 -0
  198. package/templates/mvc/js/src/errors/ApiError.js +14 -0
  199. package/templates/mvc/js/src/errors/BadRequestError.js +11 -0
  200. package/templates/mvc/js/src/errors/BadRequestError.spec.js.ejs +22 -0
  201. package/templates/mvc/js/src/errors/NotFoundError.js +11 -0
  202. package/templates/mvc/js/src/errors/NotFoundError.spec.js.ejs +22 -0
  203. package/templates/mvc/js/src/graphql/context.js.ejs +7 -0
  204. package/templates/mvc/js/src/graphql/context.spec.js.ejs +29 -0
  205. package/templates/mvc/js/src/graphql/index.js.ejs +5 -0
  206. package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -0
  207. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +25 -0
  208. package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +64 -0
  209. package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -0
  210. package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +19 -0
  211. package/templates/mvc/js/src/index.js.ejs +141 -0
  212. package/templates/mvc/js/src/routes/api.js.ejs +15 -0
  213. package/templates/mvc/js/src/routes/api.spec.js.ejs +41 -0
  214. package/templates/mvc/js/src/utils/errorMessages.js +14 -0
  215. package/templates/mvc/js/src/utils/errorMiddleware.js +29 -0
  216. package/templates/mvc/js/src/utils/httpCodes.js +9 -0
  217. package/templates/mvc/js/src/utils/logger.js +40 -0
  218. package/templates/mvc/js/src/utils/logger.spec.js.ejs +63 -0
  219. package/templates/mvc/ts/src/config/env.ts.ejs +45 -0
  220. package/templates/mvc/ts/src/config/swagger.ts.ejs +6 -0
  221. package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +481 -0
  222. package/templates/mvc/ts/src/controllers/userController.ts.ejs +292 -0
  223. package/templates/mvc/ts/src/errors/ApiError.ts +15 -0
  224. package/templates/mvc/ts/src/errors/BadRequestError.spec.ts.ejs +22 -0
  225. package/templates/mvc/ts/src/errors/BadRequestError.ts +9 -0
  226. package/templates/mvc/ts/src/errors/NotFoundError.spec.ts.ejs +27 -0
  227. package/templates/mvc/ts/src/errors/NotFoundError.ts +9 -0
  228. package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +30 -0
  229. package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -0
  230. package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -0
  231. package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -0
  232. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +68 -0
  233. package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +29 -0
  234. package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -0
  235. package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +17 -0
  236. package/templates/mvc/ts/src/index.ts.ejs +157 -0
  237. package/templates/mvc/ts/src/routes/api.spec.ts.ejs +59 -0
  238. package/templates/mvc/ts/src/routes/api.ts.ejs +17 -0
  239. package/templates/mvc/ts/src/utils/errorMessages.ts +12 -0
  240. package/templates/mvc/ts/src/utils/errorMiddleware.ts.ejs +27 -0
  241. package/templates/mvc/ts/src/utils/httpCodes.ts +7 -0
  242. package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +63 -0
  243. package/templates/mvc/ts/src/utils/logger.ts +36 -0
@@ -0,0 +1,19 @@
1
+ import { betterAuth } from "better-auth";
2
+ <% if (database === 'MongoDB') { %>import { mongodbAdapter } from "better-auth/adapters/mongodb";
3
+ import mongoose from "mongoose";<% } else if (database === 'MySQL' || database === 'PostgreSQL') { %>import { sequelizeAdapter } from "better-auth/adapters/sequelize";
4
+ import sequelize from "./database";<% } %>
5
+
6
+ export const auth = betterAuth({
7
+ database: <% if (database === 'MongoDB') { %>mongodbAdapter(mongoose.connection.db)<% } else if (database === 'MySQL' || database === 'PostgreSQL') { %>sequelizeAdapter(sequelize)<% } else { %>null // Better-Auth requires a database adapter<% } %>,
8
+ emailAndPassword: {
9
+ enabled: true
10
+ },
11
+ socialProviders: {
12
+ <% if (googleLogin === 'Google Login') { %>
13
+ google: {
14
+ clientId: process.env.GOOGLE_CLIENT_ID,
15
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET,
16
+ },
17
+ <% } %>
18
+ },
19
+ });
@@ -0,0 +1,19 @@
1
+ import { betterAuth } from "better-auth";
2
+ <% if (database === 'MongoDB') { %>import { mongodbAdapter } from "better-auth/adapters/mongodb";
3
+ import mongoose from "mongoose";<% } else if (database === 'MySQL' || database === 'PostgreSQL') { %>import { sequelizeAdapter } from "better-auth/adapters/sequelize";
4
+ import sequelize from "./database";<% } %>
5
+
6
+ export const auth = betterAuth({
7
+ database: <% if (database === 'MongoDB') { %>mongodbAdapter(mongoose.connection.db)<% } else if (database === 'MySQL' || database === 'PostgreSQL') { %>sequelizeAdapter(sequelize)<% } else { %>null<% } %>,
8
+ emailAndPassword: {
9
+ enabled: true
10
+ },
11
+ socialProviders: {
12
+ <% if (googleLogin === 'Google Login') { %>
13
+ google: {
14
+ clientId: process.env.GOOGLE_CLIENT_ID,
15
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET,
16
+ },
17
+ <% } %>
18
+ },
19
+ });
@@ -0,0 +1,101 @@
1
+ <% if (auth === 'Better-Auth') { %>
2
+ import { auth } from '../config/auth<% if (language === 'TypeScript') { %>.ts<% } %>';
3
+
4
+ export const register = async (req, res, next) => {
5
+ try {
6
+ const { email, password, name } = req.body;
7
+ const user = await auth.api.signUpEmail({
8
+ body: {
9
+ email,
10
+ password,
11
+ name,
12
+ },
13
+ });
14
+ res.status(201).json({ message: 'User registered successfully', user });
15
+ } catch (error) {
16
+ next(error);
17
+ }
18
+ };
19
+
20
+ export const login = async (req, res, next) => {
21
+ try {
22
+ const { email, password } = req.body;
23
+ const session = await auth.api.signInEmail({
24
+ body: {
25
+ email,
26
+ password,
27
+ },
28
+ });
29
+ res.status(200).json({ message: 'Login successful', session });
30
+ } catch (error) {
31
+ next(error);
32
+ }
33
+ };
34
+ <% } else if (auth === 'JWT') { %>
35
+ import jwt from 'jsonwebtoken';
36
+ import bcrypt from 'bcryptjs';
37
+ import { ApiError } from '../utils/errorMiddleware<% if (language === 'TypeScript') { %>.ts<% } %>';
38
+
39
+ // Mock User database (In production, use your database models)
40
+ const users = [];
41
+
42
+ export const register = async (req, res, next) => {
43
+ try {
44
+ const { email, password, name } = req.body;
45
+
46
+ const existingUser = users.find(u => u.email === email);
47
+ if (existingUser) {
48
+ throw new ApiError(400, 'User already exists');
49
+ }
50
+
51
+ const hashedPassword = await bcrypt.hash(password, 10);
52
+ const newUser = { id: Date.now(), email, password: hashedPassword, name };
53
+ users.push(newUser);
54
+
55
+ res.status(201).json({
56
+ message: 'User registered successfully',
57
+ user: { id: newUser.id, email: newUser.email, name: newUser.name }
58
+ });
59
+ } catch (error) {
60
+ next(error);
61
+ }
62
+ };
63
+
64
+ export const login = async (req, res, next) => {
65
+ try {
66
+ const { email, password } = req.body;
67
+
68
+ const user = users.find(u => u.email === email);
69
+ if (!user) {
70
+ throw new ApiError(401, 'Invalid credentials');
71
+ }
72
+
73
+ const isMatch = await bcrypt.compare(password, user.password);
74
+ if (!isMatch) {
75
+ throw new ApiError(401, 'Invalid credentials');
76
+ }
77
+
78
+ const token = jwt.sign(
79
+ { id: user.id, email: user.email },
80
+ process.env.JWT_SECRET || 'secret',
81
+ { expiresIn: process.env.JWT_EXPIRES_IN || '1d' }
82
+ );
83
+
84
+ res.status(200).json({
85
+ message: 'Login successful',
86
+ token,
87
+ user: { id: user.id, email: user.email, name: user.name }
88
+ });
89
+ } catch (error) {
90
+ next(error);
91
+ }
92
+ };
93
+ <% } else if (auth === 'OAuth' || googleLogin === 'Google Login') { %>
94
+ export const googleCallback = (req, res) => {
95
+ // Passport handles the authentication, we just redirect or respond
96
+ res.status(200).json({
97
+ message: 'Google login successful',
98
+ user: req.user
99
+ });
100
+ };
101
+ <% } %>
@@ -0,0 +1,101 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ <% if (auth === 'Better-Auth') { %>
3
+ import { auth } from '../config/auth';
4
+
5
+ export const register = async (req: Request, res: Response, next: NextFunction) => {
6
+ try {
7
+ const { email, password, name } = req.body;
8
+ const user = await auth.api.signUpEmail({
9
+ body: {
10
+ email,
11
+ password,
12
+ name,
13
+ },
14
+ });
15
+ res.status(201).json({ message: 'User registered successfully', user });
16
+ } catch (error: any) {
17
+ next(error);
18
+ }
19
+ };
20
+
21
+ export const login = async (req: Request, res: Response, next: NextFunction) => {
22
+ try {
23
+ const { email, password } = req.body;
24
+ const session = await auth.api.signInEmail({
25
+ body: {
26
+ email,
27
+ password,
28
+ },
29
+ });
30
+ res.status(200).json({ message: 'Login successful', session });
31
+ } catch (error: any) {
32
+ next(error);
33
+ }
34
+ };
35
+ <% } else if (auth === 'JWT') { %>
36
+ import jwt from 'jsonwebtoken';
37
+ import bcrypt from 'bcryptjs';
38
+ import { ApiError } from '../utils/errorMiddleware';
39
+
40
+ // Mock User database (In production, use your database models)
41
+ const users: any[] = [];
42
+
43
+ export const register = async (req: Request, res: Response, next: NextFunction) => {
44
+ try {
45
+ const { email, password, name } = req.body;
46
+
47
+ const existingUser = users.find(u => u.email === email);
48
+ if (existingUser) {
49
+ throw new ApiError(400, 'User already exists');
50
+ }
51
+
52
+ const hashedPassword = await bcrypt.hash(password, 10);
53
+ const newUser = { id: Date.now(), email, password: hashedPassword, name };
54
+ users.push(newUser);
55
+
56
+ res.status(201).json({
57
+ message: 'User registered successfully',
58
+ user: { id: newUser.id, email: newUser.email, name: newUser.name }
59
+ });
60
+ } catch (error: any) {
61
+ next(error);
62
+ }
63
+ };
64
+
65
+ export const login = async (req: Request, res: Response, next: NextFunction) => {
66
+ try {
67
+ const { email, password } = req.body;
68
+
69
+ const user = users.find(u => u.email === email);
70
+ if (!user) {
71
+ throw new ApiError(401, 'Invalid credentials');
72
+ }
73
+
74
+ const isMatch = await bcrypt.compare(password, user.password);
75
+ if (!isMatch) {
76
+ throw new ApiError(401, 'Invalid credentials');
77
+ }
78
+
79
+ const token = jwt.sign(
80
+ { id: user.id, email: user.email },
81
+ process.env.JWT_SECRET || 'secret',
82
+ { expiresIn: process.env.JWT_EXPIRES_IN || '1d' }
83
+ );
84
+
85
+ res.status(200).json({
86
+ message: 'Login successful',
87
+ token,
88
+ user: { id: user.id, email: user.email, name: user.name }
89
+ });
90
+ } catch (error: any) {
91
+ next(error);
92
+ }
93
+ };
94
+ <% } else if (auth === 'OAuth' || googleLogin === 'Google Login') { %>
95
+ export const googleCallback = (req: Request, res: Response) => {
96
+ res.status(200).json({
97
+ message: 'Google login successful',
98
+ user: req.user
99
+ });
100
+ };
101
+ <% } %>
@@ -0,0 +1,20 @@
1
+ import jwt from 'jsonwebtoken';
2
+ import { ApiError } from '../utils/errorMiddleware<% if (language === 'TypeScript') { %>.ts<% } %>';
3
+
4
+ export const authMiddleware = (req, res, next) => {
5
+ const authHeader = req.headers.authorization;
6
+
7
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
8
+ return next(new ApiError(401, 'No token provided'));
9
+ }
10
+
11
+ const token = authHeader.split(' ')[1];
12
+
13
+ try {
14
+ const decoded = jwt.verify(token, process.env.JWT_SECRET || 'secret');
15
+ req.user = decoded;
16
+ next();
17
+ } catch (error) {
18
+ return next(new ApiError(401, 'Invalid or expired token'));
19
+ }
20
+ };
@@ -0,0 +1,25 @@
1
+ import jwt from 'jsonwebtoken';
2
+ import { Request, Response, NextFunction } from 'express';
3
+ import { ApiError } from '../utils/errorMiddleware';
4
+
5
+ export interface AuthRequest extends Request {
6
+ user?: any;
7
+ }
8
+
9
+ export const authMiddleware = (req: AuthRequest, res: Response, next: NextFunction) => {
10
+ const authHeader = req.headers.authorization;
11
+
12
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
13
+ return next(new ApiError(401, 'No token provided'));
14
+ }
15
+
16
+ const token = authHeader.split(' ')[1];
17
+
18
+ try {
19
+ const decoded = jwt.verify(token, process.env.JWT_SECRET || 'secret');
20
+ req.user = decoded;
21
+ next();
22
+ } catch (error) {
23
+ return next(new ApiError(401, 'Invalid or expired token'));
24
+ }
25
+ };
@@ -0,0 +1,31 @@
1
+ import multer from 'multer';
2
+ import path from 'path';
3
+ import { ApiError } from '../utils/errorMiddleware<% if (language === 'TypeScript') { %>.ts<% } %>';
4
+
5
+ // Storage configuration
6
+ const storage = multer.diskStorage({
7
+ destination: (req, file, cb) => {
8
+ cb(null, 'uploads/');
9
+ },
10
+ filename: (req, file, cb) => {
11
+ const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
12
+ cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
13
+ }
14
+ });
15
+
16
+ // File filter (optional)
17
+ const fileFilter = (req, file, cb) => {
18
+ if (file.mimetype.startsWith('image/')) {
19
+ cb(null, true);
20
+ } else {
21
+ cb(new ApiError(400, 'Only images are allowed'), false);
22
+ }
23
+ };
24
+
25
+ export const upload = multer({
26
+ storage: storage,
27
+ fileFilter: fileFilter,
28
+ limits: {
29
+ fileSize: 5 * 1024 * 1024 // 5MB limit
30
+ }
31
+ });
@@ -0,0 +1,32 @@
1
+ import multer from 'multer';
2
+ import path from 'path';
3
+ import { Request } from 'express';
4
+ import { ApiError } from '../utils/errorMiddleware';
5
+
6
+ // Storage configuration
7
+ const storage = multer.diskStorage({
8
+ destination: (req, file, cb) => {
9
+ cb(null, 'uploads/');
10
+ },
11
+ filename: (req, file, cb) => {
12
+ const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
13
+ cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
14
+ }
15
+ });
16
+
17
+ // File filter
18
+ const fileFilter = (req: Request, file: Express.Multer.File, cb: multer.FileFilterCallback) => {
19
+ if (file.mimetype.startsWith('image/')) {
20
+ cb(null, true);
21
+ } else {
22
+ cb(new ApiError(400, 'Only images are allowed'));
23
+ }
24
+ };
25
+
26
+ export const upload = multer({
27
+ storage: storage,
28
+ fileFilter: fileFilter,
29
+ limits: {
30
+ fileSize: 5 * 1024 * 1024 // 5MB limit
31
+ }
32
+ });
@@ -0,0 +1,20 @@
1
+ import express from 'express';
2
+ <% if (auth === 'OAuth' || googleLogin === 'Google Login') { %>import passport from 'passport';<% } %>
3
+ import * as authController from '../controllers/authController<% if (language === 'TypeScript') { %>.ts<% } %>';
4
+
5
+ const router = express.Router();
6
+
7
+ <% if (auth === 'Better-Auth' || auth === 'JWT') { %>
8
+ router.post('/register', authController.register);
9
+ router.post('/login', authController.login);
10
+ <% } %>
11
+
12
+ <% if (auth === 'OAuth' || googleLogin === 'Google Login') { %>
13
+ router.get('/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
14
+ router.get('/google/callback',
15
+ passport.authenticate('google', { failureRedirect: '/login' }),
16
+ authController.googleCallback
17
+ );
18
+ <% } %>
19
+
20
+ export default router;
@@ -0,0 +1,20 @@
1
+ import express, { Router } from 'express';
2
+ <% if (auth === 'OAuth' || googleLogin === 'Google Login') { %>import passport from 'passport';<% } %>
3
+ import * as authController from '../controllers/authController';
4
+
5
+ const router: Router = express.Router();
6
+
7
+ <% if (auth === 'Better-Auth' || auth === 'JWT') { %>
8
+ router.post('/register', authController.register);
9
+ router.post('/login', authController.login);
10
+ <% } %>
11
+
12
+ <% if (auth === 'OAuth' || googleLogin === 'Google Login') { %>
13
+ router.get('/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
14
+ router.get('/google/callback',
15
+ passport.authenticate('google', { failureRedirect: '/login' }),
16
+ authController.googleCallback
17
+ );
18
+ <% } %>
19
+
20
+ export default router;
@@ -0,0 +1,120 @@
1
+ const request = require('supertest');
2
+
3
+ const SERVER_URL = process.env.TEST_URL || `http://127.0.0.1:${process.env.PORT || 3001}`;
4
+
5
+ describe('E2E User Tests', () => {
6
+ // Global setup and teardown hooks can be added here
7
+ // typically for database seeding or external authentication checks prior to E2E.
8
+ let userId;
9
+ const uniqueEmail = `test_${Date.now()}@example.com`;
10
+
11
+ <%_ if (communication === 'GraphQL') { -%>
12
+ it('should create a user via GraphQL', async () => {
13
+ const query = `
14
+ mutation {
15
+ createUser(name: "Test User", email: "${uniqueEmail}") {
16
+ id
17
+ name
18
+ email
19
+ }
20
+ }
21
+ `;
22
+ const response = await request(SERVER_URL)
23
+ .post('/graphql')
24
+ .send({ query });
25
+
26
+ expect(response.statusCode).toBe(200);
27
+ userId = response.body.data.createUser.id;
28
+ expect(userId).toBeDefined();
29
+ });
30
+
31
+ it('should update a user via GraphQL', async () => {
32
+ const query = `
33
+ mutation {
34
+ updateUser(id: "${userId}", name: "Updated User") {
35
+ id
36
+ name
37
+ }
38
+ }
39
+ `;
40
+ const response = await request(SERVER_URL)
41
+ .post('/graphql')
42
+ .send({ query });
43
+
44
+ expect(response.statusCode).toBe(200);
45
+ expect(response.body.data.updateUser.name).toBe("Updated User");
46
+ });
47
+
48
+ it('should delete a user via GraphQL', async () => {
49
+ const query = `
50
+ mutation {
51
+ deleteUser(id: "${userId}")
52
+ }
53
+ `;
54
+ const response = await request(SERVER_URL)
55
+ .post('/graphql')
56
+ .send({ query });
57
+
58
+ expect(response.statusCode).toBe(200);
59
+ expect(response.body.data.deleteUser).toBe(true);
60
+ });
61
+ <%_ } else if (communication === 'Kafka') { -%>
62
+ it('should trigger Kafka event for user creation', async () => {
63
+ const response = await request(SERVER_URL)
64
+ .post('/api/users')
65
+ .send({ name: 'Test User', email: uniqueEmail });
66
+
67
+ expect([201, 202]).toContain(response.statusCode);
68
+ userId = response.body.id || response.body._id;
69
+ expect(userId).toBeDefined();
70
+
71
+ // Wait for Kafka to process...
72
+ await new Promise(resolve => setTimeout(resolve, 500));
73
+ });
74
+
75
+ it('should trigger Kafka event for user update', async () => {
76
+ const response = await request(SERVER_URL)
77
+ .patch(`/api/users/${userId}`)
78
+ .send({ name: 'Updated User' });
79
+
80
+ expect([200, 202, 204]).toContain(response.statusCode);
81
+
82
+ // Wait for Kafka to process...
83
+ await new Promise(resolve => setTimeout(resolve, 500));
84
+ });
85
+
86
+ it('should trigger Kafka event for user deletion', async () => {
87
+ const response = await request(SERVER_URL)
88
+ .delete(`/api/users/${userId}`);
89
+
90
+ expect([200, 202, 204]).toContain(response.statusCode);
91
+
92
+ // Wait for Kafka to process...
93
+ await new Promise(resolve => setTimeout(resolve, 500));
94
+ });
95
+ <%_ } else { -%>
96
+ it('should create a user successfully via REST', async () => {
97
+ const response = await request(SERVER_URL)
98
+ .post('/api/users')
99
+ .send({ name: 'Test User', email: uniqueEmail });
100
+
101
+ expect(response.statusCode).toBe(201);
102
+ userId = response.body.id || response.body._id;
103
+ });
104
+
105
+ it('should update a user successfully via REST', async () => {
106
+ const response = await request(SERVER_URL)
107
+ .patch(`/api/users/${userId}`)
108
+ .send({ name: 'Updated User' });
109
+
110
+ expect(response.statusCode).toBe(200);
111
+ });
112
+
113
+ it('should delete a user successfully via REST', async () => {
114
+ const response = await request(SERVER_URL)
115
+ .delete(`/api/users/${userId}`);
116
+
117
+ expect(response.statusCode).toBe(200);
118
+ });
119
+ <%_ } -%>
120
+ });
@@ -0,0 +1,120 @@
1
+ import request from 'supertest';
2
+
3
+ const SERVER_URL = process.env.TEST_URL || `http://127.0.0.1:${process.env.PORT || 3001}`;
4
+
5
+ describe('E2E User Tests', () => {
6
+ // Global setup and teardown hooks can be added here
7
+ // typically for database seeding or external authentication checks prior to E2E.
8
+ let userId: string;
9
+ const uniqueEmail = `test_${Date.now()}@example.com`;
10
+
11
+ <%_ if (communication === 'GraphQL') { -%>
12
+ it('should create a user via GraphQL', async () => {
13
+ const query = `
14
+ mutation {
15
+ createUser(name: "Test User", email: "${uniqueEmail}") {
16
+ id
17
+ name
18
+ email
19
+ }
20
+ }
21
+ `;
22
+ const response = await request(SERVER_URL)
23
+ .post('/graphql')
24
+ .send({ query });
25
+
26
+ expect(response.statusCode).toBe(200);
27
+ userId = response.body.data.createUser.id;
28
+ expect(userId).toBeDefined();
29
+ });
30
+
31
+ it('should update a user via GraphQL', async () => {
32
+ const query = `
33
+ mutation {
34
+ updateUser(id: "${userId}", name: "Updated User") {
35
+ id
36
+ name
37
+ }
38
+ }
39
+ `;
40
+ const response = await request(SERVER_URL)
41
+ .post('/graphql')
42
+ .send({ query });
43
+
44
+ expect(response.statusCode).toBe(200);
45
+ expect(response.body.data.updateUser.name).toBe("Updated User");
46
+ });
47
+
48
+ it('should delete a user via GraphQL', async () => {
49
+ const query = `
50
+ mutation {
51
+ deleteUser(id: "${userId}")
52
+ }
53
+ `;
54
+ const response = await request(SERVER_URL)
55
+ .post('/graphql')
56
+ .send({ query });
57
+
58
+ expect(response.statusCode).toBe(200);
59
+ expect(response.body.data.deleteUser).toBe(true);
60
+ });
61
+ <%_ } else if (communication === 'Kafka') { -%>
62
+ it('should trigger Kafka event for user creation', async () => {
63
+ const response = await request(SERVER_URL)
64
+ .post('/api/users')
65
+ .send({ name: 'Test User', email: uniqueEmail });
66
+
67
+ expect([201, 202]).toContain(response.statusCode);
68
+ userId = response.body.id || response.body._id;
69
+ expect(userId).toBeDefined();
70
+
71
+ // Wait for Kafka to process...
72
+ await new Promise(resolve => setTimeout(resolve, 500));
73
+ });
74
+
75
+ it('should trigger Kafka event for user update', async () => {
76
+ const response = await request(SERVER_URL)
77
+ .patch(`/api/users/${userId}`)
78
+ .send({ name: 'Updated User' });
79
+
80
+ expect([200, 202, 204]).toContain(response.statusCode);
81
+
82
+ // Wait for Kafka to process...
83
+ await new Promise(resolve => setTimeout(resolve, 500));
84
+ });
85
+
86
+ it('should trigger Kafka event for user deletion', async () => {
87
+ const response = await request(SERVER_URL)
88
+ .delete(`/api/users/${userId}`);
89
+
90
+ expect([200, 202, 204]).toContain(response.statusCode);
91
+
92
+ // Wait for Kafka to process...
93
+ await new Promise(resolve => setTimeout(resolve, 500));
94
+ });
95
+ <%_ } else { -%>
96
+ it('should create a user successfully via REST', async () => {
97
+ const response = await request(SERVER_URL)
98
+ .post('/api/users')
99
+ .send({ name: 'Test User', email: uniqueEmail });
100
+
101
+ expect(response.statusCode).toBe(201);
102
+ userId = response.body.id || response.body._id;
103
+ });
104
+
105
+ it('should update a user successfully via REST', async () => {
106
+ const response = await request(SERVER_URL)
107
+ .patch(`/api/users/${userId}`)
108
+ .send({ name: 'Updated User' });
109
+
110
+ expect(response.statusCode).toBe(200);
111
+ });
112
+
113
+ it('should delete a user successfully via REST', async () => {
114
+ const response = await request(SERVER_URL)
115
+ .delete(`/api/users/${userId}`);
116
+
117
+ expect(response.statusCode).toBe(200);
118
+ });
119
+ <%_ } -%>
120
+ });