create-easy-stack 1.0.3

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 (327) hide show
  1. package/bin/create.mjs +244 -0
  2. package/infra/email/files/src/core/config/email.env.ts +73 -0
  3. package/infra/email/files/src/core/infrastructure/email/email-dispatcher.port.ts +13 -0
  4. package/infra/email/files/src/core/infrastructure/email/email-layout.spec.ts +83 -0
  5. package/infra/email/files/src/core/infrastructure/email/email-layout.ts +88 -0
  6. package/infra/email/files/src/core/infrastructure/email/email-sender.factory.spec.ts +87 -0
  7. package/infra/email/files/src/core/infrastructure/email/email-sender.factory.ts +35 -0
  8. package/infra/email/files/src/core/infrastructure/email/email-sender.port.ts +19 -0
  9. package/infra/email/files/src/core/infrastructure/email/email.job.spec.ts +101 -0
  10. package/infra/email/files/src/core/infrastructure/email/email.job.ts +64 -0
  11. package/infra/email/files/src/core/infrastructure/email/email.module.spec.ts +60 -0
  12. package/infra/email/files/src/core/infrastructure/email/email.module.ts +34 -0
  13. package/infra/email/files/src/core/infrastructure/email/log-email-sender.spec.ts +34 -0
  14. package/infra/email/files/src/core/infrastructure/email/log-email-sender.ts +17 -0
  15. package/infra/email/files/src/core/infrastructure/email/smtp-email-sender.spec.ts +99 -0
  16. package/infra/email/files/src/core/infrastructure/email/smtp-email-sender.ts +63 -0
  17. package/infra/email/infra.json +58 -0
  18. package/infra/prisma-postgres/docker.service.yml +12 -0
  19. package/infra/prisma-postgres/files/prisma/schema.prisma +10 -0
  20. package/infra/prisma-postgres/files/prisma.config.mjs +10 -0
  21. package/infra/prisma-postgres/files/src/core/config/database.env.ts +13 -0
  22. package/infra/prisma-postgres/files/src/core/infrastructure/database/database.module.ts +9 -0
  23. package/infra/prisma-postgres/files/src/core/infrastructure/database/prisma.service.ts +26 -0
  24. package/infra/prisma-postgres/infra.json +60 -0
  25. package/infra/rabbitmq/docker.service.yml +16 -0
  26. package/infra/rabbitmq/files/src/core/config/messaging.env.ts +29 -0
  27. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/inline-job-queue.spec.ts +60 -0
  28. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/inline-job-queue.ts +33 -0
  29. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/job-failure.spec.ts +23 -0
  30. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/job-failure.ts +19 -0
  31. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/job-payload-cipher.spec.ts +80 -0
  32. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/job-payload-cipher.ts +66 -0
  33. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/job-queue.boundary.spec.ts +34 -0
  34. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/job-queue.factory.ts +21 -0
  35. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/job-queue.module.spec.ts +75 -0
  36. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/job-queue.module.ts +30 -0
  37. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/job-queue.port.ts +59 -0
  38. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/rabbitmq-job-queue.spec.ts +510 -0
  39. package/infra/rabbitmq/files/src/core/infrastructure/messaging/jobs/rabbitmq-job-queue.ts +353 -0
  40. package/infra/rabbitmq/files/src/core/infrastructure/messaging/rabbitmq/rabbitmq.module.ts +9 -0
  41. package/infra/rabbitmq/files/src/core/infrastructure/messaging/rabbitmq/rabbitmq.service.spec.ts +289 -0
  42. package/infra/rabbitmq/files/src/core/infrastructure/messaging/rabbitmq/rabbitmq.service.ts +207 -0
  43. package/infra/rabbitmq/infra.json +55 -0
  44. package/infra/redis/docker.service.yml +10 -0
  45. package/infra/redis/files/src/core/http/decorators/rate-limit.decorator.ts +26 -0
  46. package/infra/redis/files/src/core/http/interceptors/rate-limit.interceptor.spec.ts +180 -0
  47. package/infra/redis/files/src/core/http/interceptors/rate-limit.interceptor.ts +105 -0
  48. package/infra/redis/files/src/core/infrastructure/redis/cache.constants.ts +67 -0
  49. package/infra/redis/files/src/core/infrastructure/redis/idempotency/idempotency.module.ts +9 -0
  50. package/infra/redis/files/src/core/infrastructure/redis/idempotency/idempotency.service.spec.ts +146 -0
  51. package/infra/redis/files/src/core/infrastructure/redis/idempotency/idempotency.service.ts +131 -0
  52. package/infra/redis/files/src/core/infrastructure/redis/lock/lock.module.ts +9 -0
  53. package/infra/redis/files/src/core/infrastructure/redis/lock/lock.service.integration-spec.ts +111 -0
  54. package/infra/redis/files/src/core/infrastructure/redis/lock/lock.service.ts +82 -0
  55. package/infra/redis/files/src/core/infrastructure/redis/rate-limit/rate-limit.module.ts +15 -0
  56. package/infra/redis/files/src/core/infrastructure/redis/rate-limit/rate-limit.service.spec.ts +45 -0
  57. package/infra/redis/files/src/core/infrastructure/redis/rate-limit/rate-limit.service.ts +38 -0
  58. package/infra/redis/files/src/core/infrastructure/redis/redis.module.ts +9 -0
  59. package/infra/redis/files/src/core/infrastructure/redis/redis.service.ts +196 -0
  60. package/infra/redis/infra.json +53 -0
  61. package/infra/storage-cloudinary/files/src/core/config/storage.env.ts +43 -0
  62. package/infra/storage-cloudinary/files/src/core/infrastructure/storage/cloudinary-image-storage.spec.ts +275 -0
  63. package/infra/storage-cloudinary/files/src/core/infrastructure/storage/cloudinary-image-storage.ts +158 -0
  64. package/infra/storage-cloudinary/files/src/core/infrastructure/storage/image-storage.factory.ts +30 -0
  65. package/infra/storage-cloudinary/files/src/core/infrastructure/storage/image-storage.module.ts +17 -0
  66. package/infra/storage-cloudinary/files/src/core/infrastructure/storage/image-storage.port.ts +38 -0
  67. package/infra/storage-cloudinary/files/src/core/infrastructure/storage/image-type.spec.ts +48 -0
  68. package/infra/storage-cloudinary/files/src/core/infrastructure/storage/image-type.ts +25 -0
  69. package/infra/storage-cloudinary/files/src/core/infrastructure/storage/unconfigured-image-storage.ts +19 -0
  70. package/infra/storage-cloudinary/infra.json +73 -0
  71. package/lib/fs-utils.mjs +115 -0
  72. package/lib/registry.mjs +50 -0
  73. package/lib/scaffold.mjs +157 -0
  74. package/package.json +37 -0
  75. package/templates/nest-ddd/files/.env.example +5 -0
  76. package/templates/nest-ddd/files/.husky/commit-msg +1 -0
  77. package/templates/nest-ddd/files/.husky/pre-commit +1 -0
  78. package/templates/nest-ddd/files/.oxlintrc.json +10 -0
  79. package/templates/nest-ddd/files/.prettierrc +4 -0
  80. package/templates/nest-ddd/files/_gitignore +40 -0
  81. package/templates/nest-ddd/files/commitlint.config.js +3 -0
  82. package/templates/nest-ddd/files/nest-cli.json +8 -0
  83. package/templates/nest-ddd/files/package.json +66 -0
  84. package/templates/nest-ddd/files/plop-templates/command/command.ts.hbs +5 -0
  85. package/templates/nest-ddd/files/plop-templates/command/handler.ts.hbs +30 -0
  86. package/templates/nest-ddd/files/plop-templates/module/application/commands/create-{{kebab}}.command.ts.hbs +5 -0
  87. package/templates/nest-ddd/files/plop-templates/module/application/commands/create-{{kebab}}.handler.spec.ts.hbs +35 -0
  88. package/templates/nest-ddd/files/plop-templates/module/application/commands/create-{{kebab}}.handler.ts.hbs +25 -0
  89. package/templates/nest-ddd/files/plop-templates/module/application/index.ts.hbs +5 -0
  90. package/templates/nest-ddd/files/plop-templates/module/application/queries/get-{{kebab}}-by-id.handler.ts.hbs +29 -0
  91. package/templates/nest-ddd/files/plop-templates/module/application/queries/get-{{kebab}}-by-id.query.ts.hbs +5 -0
  92. package/templates/nest-ddd/files/plop-templates/module/domain/entities/{{kebab}}.entity.ts.hbs +37 -0
  93. package/templates/nest-ddd/files/plop-templates/module/domain/events/{{kebab}}-created.event.ts.hbs +10 -0
  94. package/templates/nest-ddd/files/plop-templates/module/domain/exceptions/{{kebab}}.exception.ts.hbs +11 -0
  95. package/templates/nest-ddd/files/plop-templates/module/domain/index.ts.hbs +4 -0
  96. package/templates/nest-ddd/files/plop-templates/module/domain/repositories/{{kebab}}.repository.ts.hbs +7 -0
  97. package/templates/nest-ddd/files/plop-templates/module/presentation/controllers/{{kebab}}.controller.ts.hbs +53 -0
  98. package/templates/nest-ddd/files/plop-templates/module/presentation/dtos/create-{{kebab}}.dto.ts.hbs +10 -0
  99. package/templates/nest-ddd/files/plop-templates/module/presentation/dtos/{{kebab}}-response.dto.ts.hbs +15 -0
  100. package/templates/nest-ddd/files/plop-templates/module/presentation/index.ts.hbs +4 -0
  101. package/templates/nest-ddd/files/plop-templates/module/presentation/mappers/{{kebab}}.mapper.ts.hbs +13 -0
  102. package/templates/nest-ddd/files/plop-templates/module/{{kebab}}.module.ts.hbs +40 -0
  103. package/templates/nest-ddd/files/plop-templates/persistence-memory/infrastructure/database/repositories/in-memory-{{kebab}}.repository.ts.hbs +17 -0
  104. package/templates/nest-ddd/files/plop-templates/persistence-memory/infrastructure/index.ts.hbs +1 -0
  105. package/templates/nest-ddd/files/plop-templates/persistence-prisma/infrastructure/database/mappers/{{kebab}}.mapper.ts.hbs +29 -0
  106. package/templates/nest-ddd/files/plop-templates/persistence-prisma/infrastructure/database/repositories/prisma-{{kebab}}.repository.ts.hbs +28 -0
  107. package/templates/nest-ddd/files/plop-templates/persistence-prisma/infrastructure/index.ts.hbs +2 -0
  108. package/templates/nest-ddd/files/plop-templates/query/handler.ts.hbs +28 -0
  109. package/templates/nest-ddd/files/plop-templates/query/query.ts.hbs +5 -0
  110. package/templates/nest-ddd/files/plop-templates/snippets/error-codes.hbs +14 -0
  111. package/templates/nest-ddd/files/plop-templates/snippets/prisma-model.hbs +7 -0
  112. package/templates/nest-ddd/files/plopfile.mjs +186 -0
  113. package/templates/nest-ddd/files/src/app.controller.ts +13 -0
  114. package/templates/nest-ddd/files/src/app.module.ts +26 -0
  115. package/templates/nest-ddd/files/src/core/config/app.config.ts +9 -0
  116. package/templates/nest-ddd/files/src/core/config/env.validation.ts +30 -0
  117. package/templates/nest-ddd/files/src/core/domain/base/aggregate-root.base.ts +18 -0
  118. package/templates/nest-ddd/files/src/core/domain/base/domain-event.base.ts +7 -0
  119. package/templates/nest-ddd/files/src/core/domain/base/entity.base.ts +36 -0
  120. package/templates/nest-ddd/files/src/core/domain/base/value-object.base.ts +17 -0
  121. package/templates/nest-ddd/files/src/core/domain/exceptions/domain.exception.ts +16 -0
  122. package/templates/nest-ddd/files/src/core/domain/exceptions/error-codes.ts +28 -0
  123. package/templates/nest-ddd/files/src/core/domain/types/pagination.ts +9 -0
  124. package/templates/nest-ddd/files/src/core/http/decorators/client-info.decorator.ts +24 -0
  125. package/templates/nest-ddd/files/src/core/http/decorators/current-user.decorator.ts +19 -0
  126. package/templates/nest-ddd/files/src/core/http/dtos/paginated-response.dto.ts +29 -0
  127. package/templates/nest-ddd/files/src/core/http/dtos/pagination-query.dto.ts +17 -0
  128. package/templates/nest-ddd/files/src/core/http/filters/all-exceptions.filter.spec.ts +163 -0
  129. package/templates/nest-ddd/files/src/core/http/filters/all-exceptions.filter.ts +97 -0
  130. package/templates/nest-ddd/files/src/core/http/guards/max-body-size.guard.spec.ts +47 -0
  131. package/templates/nest-ddd/files/src/core/http/guards/max-body-size.guard.ts +31 -0
  132. package/templates/nest-ddd/files/src/core/http/interceptors/logging.interceptor.ts +37 -0
  133. package/templates/nest-ddd/files/src/core/http/interceptors/response.interceptor.ts +53 -0
  134. package/templates/nest-ddd/files/src/core/http/logging/app.logger.ts +34 -0
  135. package/templates/nest-ddd/files/src/core/index.ts +33 -0
  136. package/templates/nest-ddd/files/src/core/utils/correlation-id.util.spec.ts +29 -0
  137. package/templates/nest-ddd/files/src/core/utils/correlation-id.util.ts +15 -0
  138. package/templates/nest-ddd/files/src/core/utils/hash.util.spec.ts +61 -0
  139. package/templates/nest-ddd/files/src/core/utils/hash.util.ts +47 -0
  140. package/templates/nest-ddd/files/src/core/utils/snowflake.util.spec.ts +40 -0
  141. package/templates/nest-ddd/files/src/core/utils/snowflake.util.ts +99 -0
  142. package/templates/nest-ddd/files/src/core/utils/string.util.spec.ts +20 -0
  143. package/templates/nest-ddd/files/src/core/utils/string.util.ts +21 -0
  144. package/templates/nest-ddd/files/src/core/utils/time.util.spec.ts +25 -0
  145. package/templates/nest-ddd/files/src/core/utils/time.util.ts +25 -0
  146. package/templates/nest-ddd/files/src/core/utils/ttl.util.ts +22 -0
  147. package/templates/nest-ddd/files/src/main.ts +61 -0
  148. package/templates/nest-ddd/files/test/setup.ts +6 -0
  149. package/templates/nest-ddd/files/tsconfig.build.json +9 -0
  150. package/templates/nest-ddd/files/tsconfig.json +28 -0
  151. package/templates/nest-ddd/files/vitest.config.e2e.ts +15 -0
  152. package/templates/nest-ddd/files/vitest.config.ts +16 -0
  153. package/templates/nest-ddd/template.json +8 -0
  154. package/templates/node-express/files/.env.example +28 -0
  155. package/templates/node-express/files/docker-compose.yml +52 -0
  156. package/templates/node-express/files/package-lock.json +11880 -0
  157. package/templates/node-express/files/package.json +43 -0
  158. package/templates/node-express/files/server.js +13 -0
  159. package/templates/node-express/files/src/app.js +72 -0
  160. package/templates/node-express/files/src/auth/authUtils.js +116 -0
  161. package/templates/node-express/files/src/auth/checkAuth.js +61 -0
  162. package/templates/node-express/files/src/bucket_pattern/comment.model.js +27 -0
  163. package/templates/node-express/files/src/bucket_pattern/comment.service.js +50 -0
  164. package/templates/node-express/files/src/config/config.aws-s3.js +28 -0
  165. package/templates/node-express/files/src/config/config.cloudinary.js +13 -0
  166. package/templates/node-express/files/src/config/config.mongodb.js +25 -0
  167. package/templates/node-express/files/src/config/config.multer.js +25 -0
  168. package/templates/node-express/files/src/config/config.nodemailer.js +16 -0
  169. package/templates/node-express/files/src/controllers/access.controller.js +49 -0
  170. package/templates/node-express/files/src/controllers/cart.controller.js +38 -0
  171. package/templates/node-express/files/src/controllers/checkout.controller.js +15 -0
  172. package/templates/node-express/files/src/controllers/comment.controller.js +29 -0
  173. package/templates/node-express/files/src/controllers/discount.controller.js +68 -0
  174. package/templates/node-express/files/src/controllers/email.controller.js +16 -0
  175. package/templates/node-express/files/src/controllers/inventory.controller.js +15 -0
  176. package/templates/node-express/files/src/controllers/notification.controller.js +15 -0
  177. package/templates/node-express/files/src/controllers/product.controller.js +175 -0
  178. package/templates/node-express/files/src/controllers/profile.controller.js +65 -0
  179. package/templates/node-express/files/src/controllers/rbac.controller.js +41 -0
  180. package/templates/node-express/files/src/controllers/template.controller.js +20 -0
  181. package/templates/node-express/files/src/controllers/upload.controller.js +56 -0
  182. package/templates/node-express/files/src/controllers/user.controller.js +36 -0
  183. package/templates/node-express/files/src/core/error.response.js +84 -0
  184. package/templates/node-express/files/src/core/success.response.js +44 -0
  185. package/templates/node-express/files/src/database/init.mongodb.level0.js +16 -0
  186. package/templates/node-express/files/src/database/init.mongodb.level1.js +36 -0
  187. package/templates/node-express/files/src/database/init.redis.js +119 -0
  188. package/templates/node-express/files/src/helpers/asyncHandler.js +7 -0
  189. package/templates/node-express/files/src/helpers/check.connect.js +29 -0
  190. package/templates/node-express/files/src/keys/private_key.pem +28 -0
  191. package/templates/node-express/files/src/keys/public_key.pem +9 -0
  192. package/templates/node-express/files/src/logger/discord.log.js +26 -0
  193. package/templates/node-express/files/src/logger/discord.log.v2.js +56 -0
  194. package/templates/node-express/files/src/logger/mylogger.log.js +130 -0
  195. package/templates/node-express/files/src/logger/winston.log.js +27 -0
  196. package/templates/node-express/files/src/middlewares/index.js +21 -0
  197. package/templates/node-express/files/src/middlewares/rbac.js +37 -0
  198. package/templates/node-express/files/src/middlewares/role.middleware.js +12 -0
  199. package/templates/node-express/files/src/models/KeyToken.model.js +37 -0
  200. package/templates/node-express/files/src/models/apiKey.model.js +31 -0
  201. package/templates/node-express/files/src/models/cart.model.js +47 -0
  202. package/templates/node-express/files/src/models/comment.model.js +43 -0
  203. package/templates/node-express/files/src/models/discount.model.js +92 -0
  204. package/templates/node-express/files/src/models/inventory.model.js +42 -0
  205. package/templates/node-express/files/src/models/notification.model.js +52 -0
  206. package/templates/node-express/files/src/models/order.model.js +68 -0
  207. package/templates/node-express/files/src/models/otp.model.js +32 -0
  208. package/templates/node-express/files/src/models/product.model.js +144 -0
  209. package/templates/node-express/files/src/models/repository/cart.repo.js +71 -0
  210. package/templates/node-express/files/src/models/repository/discount.repo.js +63 -0
  211. package/templates/node-express/files/src/models/repository/inventory.repo.js +45 -0
  212. package/templates/node-express/files/src/models/repository/product.repo.js +145 -0
  213. package/templates/node-express/files/src/models/repository/shop.repo.js +18 -0
  214. package/templates/node-express/files/src/models/repository/spu.repo.js +18 -0
  215. package/templates/node-express/files/src/models/repository/user.repo.js +20 -0
  216. package/templates/node-express/files/src/models/resource.model.js +32 -0
  217. package/templates/node-express/files/src/models/role.model.js +57 -0
  218. package/templates/node-express/files/src/models/shop.model.js +43 -0
  219. package/templates/node-express/files/src/models/sku.model.js +81 -0
  220. package/templates/node-express/files/src/models/spu.model.js +101 -0
  221. package/templates/node-express/files/src/models/template.model.js +25 -0
  222. package/templates/node-express/files/src/models/user.model.js +82 -0
  223. package/templates/node-express/files/src/postman/access.post.http +22 -0
  224. package/templates/node-express/files/src/routes/access/index.route.js +21 -0
  225. package/templates/node-express/files/src/routes/cart/index.route.js +20 -0
  226. package/templates/node-express/files/src/routes/checkout/index.route.js +10 -0
  227. package/templates/node-express/files/src/routes/comment/index.route.js +16 -0
  228. package/templates/node-express/files/src/routes/discount/index.route.js +26 -0
  229. package/templates/node-express/files/src/routes/index.route.js +27 -0
  230. package/templates/node-express/files/src/routes/inventory/index.route.js +11 -0
  231. package/templates/node-express/files/src/routes/notification/index.route.js +14 -0
  232. package/templates/node-express/files/src/routes/product/index.route.js +38 -0
  233. package/templates/node-express/files/src/routes/profile/index.route.js +15 -0
  234. package/templates/node-express/files/src/routes/rbac/index.route.js +21 -0
  235. package/templates/node-express/files/src/routes/template/index.route.js +11 -0
  236. package/templates/node-express/files/src/routes/upload/index.route.js +28 -0
  237. package/templates/node-express/files/src/routes/user/index.route.js +13 -0
  238. package/templates/node-express/files/src/services/access.service.js +257 -0
  239. package/templates/node-express/files/src/services/apiKey.service.js +15 -0
  240. package/templates/node-express/files/src/services/cart.service.js +115 -0
  241. package/templates/node-express/files/src/services/checkout.service.js +218 -0
  242. package/templates/node-express/files/src/services/comment.service.js +185 -0
  243. package/templates/node-express/files/src/services/discount.service.js +282 -0
  244. package/templates/node-express/files/src/services/email.service.js +71 -0
  245. package/templates/node-express/files/src/services/inventory.service.js +35 -0
  246. package/templates/node-express/files/src/services/keyToken.service.js +77 -0
  247. package/templates/node-express/files/src/services/notification.service.js +58 -0
  248. package/templates/node-express/files/src/services/otp.service.js +36 -0
  249. package/templates/node-express/files/src/services/product.service.js +228 -0
  250. package/templates/node-express/files/src/services/rbac.service.js +143 -0
  251. package/templates/node-express/files/src/services/redis.service.js +57 -0
  252. package/templates/node-express/files/src/services/redisPubSub.service.js +72 -0
  253. package/templates/node-express/files/src/services/shop.service.js +21 -0
  254. package/templates/node-express/files/src/services/sku.service.js +52 -0
  255. package/templates/node-express/files/src/services/spu.service.js +89 -0
  256. package/templates/node-express/files/src/services/template.service.js +41 -0
  257. package/templates/node-express/files/src/services/upload.s3.service.js +55 -0
  258. package/templates/node-express/files/src/services/upload.service.js +74 -0
  259. package/templates/node-express/files/src/services/user.service.js +92 -0
  260. package/templates/node-express/files/src/temp/1734420604996-ci-cd.png +0 -0
  261. package/templates/node-express/files/src/temp/1734421222213-cover-fb.jpg +0 -0
  262. package/templates/node-express/files/src/temp/1734421222214-cover-fb-01.jpg +0 -0
  263. package/templates/node-express/files/src/temp/1734421293437-cover-fb-01.jpg +0 -0
  264. package/templates/node-express/files/src/temp/1734421293437-cover-fb.jpg +0 -0
  265. package/templates/node-express/files/src/tests/inventory.test.js +21 -0
  266. package/templates/node-express/files/src/tests/message_queue/kafka/consumer.js +23 -0
  267. package/templates/node-express/files/src/tests/message_queue/kafka/producer.js +21 -0
  268. package/templates/node-express/files/src/tests/message_queue/rabbitMQ/consumer.js +28 -0
  269. package/templates/node-express/files/src/tests/message_queue/rabbitMQ/ordered.consumer.js +26 -0
  270. package/templates/node-express/files/src/tests/message_queue/rabbitMQ/ordered.producer.js +31 -0
  271. package/templates/node-express/files/src/tests/message_queue/rabbitMQ/producer.js +26 -0
  272. package/templates/node-express/files/src/tests/message_queue/rabbitMQ/producerDLX.js +44 -0
  273. package/templates/node-express/files/src/tests/mysql/connect.js +59 -0
  274. package/templates/node-express/files/src/tests/product.test.js +14 -0
  275. package/templates/node-express/files/src/utils/index.js +78 -0
  276. package/templates/node-express/files/src/utils/reasonPhrases.js +344 -0
  277. package/templates/node-express/files/src/utils/statusCodes.js +344 -0
  278. package/templates/node-express/files/src/utils/template.html.js +38 -0
  279. package/templates/node-express/template.json +11 -0
  280. package/templates/react-fsd/files/index.html +13 -0
  281. package/templates/react-fsd/files/package.json +15 -0
  282. package/templates/react-fsd/files/public/favicon.svg +1 -0
  283. package/templates/react-fsd/files/public/icons.svg +24 -0
  284. package/templates/react-fsd/files/src/assets/hero.png +0 -0
  285. package/templates/react-fsd/files/src/assets/typescript.svg +1 -0
  286. package/templates/react-fsd/files/src/assets/vite.svg +1 -0
  287. package/templates/react-fsd/files/src/counter.ts +9 -0
  288. package/templates/react-fsd/files/src/main.ts +60 -0
  289. package/templates/react-fsd/files/src/style.css +296 -0
  290. package/templates/react-fsd/files/tsconfig.json +24 -0
  291. package/templates/react-fsd/template.json +11 -0
  292. package/templates/react-monolithic/files/index.html +13 -0
  293. package/templates/react-monolithic/files/package.json +15 -0
  294. package/templates/react-monolithic/files/public/favicon.svg +1 -0
  295. package/templates/react-monolithic/files/public/icons.svg +24 -0
  296. package/templates/react-monolithic/files/src/assets/hero.png +0 -0
  297. package/templates/react-monolithic/files/src/assets/typescript.svg +1 -0
  298. package/templates/react-monolithic/files/src/assets/vite.svg +1 -0
  299. package/templates/react-monolithic/files/src/counter.ts +9 -0
  300. package/templates/react-monolithic/files/src/main.ts +60 -0
  301. package/templates/react-monolithic/files/src/style.css +296 -0
  302. package/templates/react-monolithic/files/tsconfig.json +24 -0
  303. package/templates/react-monolithic/template.json +11 -0
  304. package/templates/vue-fsd/files/index.html +13 -0
  305. package/templates/vue-fsd/files/package.json +15 -0
  306. package/templates/vue-fsd/files/public/favicon.svg +1 -0
  307. package/templates/vue-fsd/files/public/icons.svg +24 -0
  308. package/templates/vue-fsd/files/src/assets/hero.png +0 -0
  309. package/templates/vue-fsd/files/src/assets/typescript.svg +1 -0
  310. package/templates/vue-fsd/files/src/assets/vite.svg +1 -0
  311. package/templates/vue-fsd/files/src/counter.ts +9 -0
  312. package/templates/vue-fsd/files/src/main.ts +60 -0
  313. package/templates/vue-fsd/files/src/style.css +296 -0
  314. package/templates/vue-fsd/files/tsconfig.json +24 -0
  315. package/templates/vue-fsd/template.json +11 -0
  316. package/templates/vue-monolithic/files/index.html +13 -0
  317. package/templates/vue-monolithic/files/package.json +15 -0
  318. package/templates/vue-monolithic/files/public/favicon.svg +1 -0
  319. package/templates/vue-monolithic/files/public/icons.svg +24 -0
  320. package/templates/vue-monolithic/files/src/assets/hero.png +0 -0
  321. package/templates/vue-monolithic/files/src/assets/typescript.svg +1 -0
  322. package/templates/vue-monolithic/files/src/assets/vite.svg +1 -0
  323. package/templates/vue-monolithic/files/src/counter.ts +9 -0
  324. package/templates/vue-monolithic/files/src/main.ts +60 -0
  325. package/templates/vue-monolithic/files/src/style.css +296 -0
  326. package/templates/vue-monolithic/files/tsconfig.json +24 -0
  327. package/templates/vue-monolithic/template.json +11 -0
@@ -0,0 +1,47 @@
1
+ import * as argon2 from 'argon2';
2
+ import { createHash, createHmac, randomBytes, randomInt } from 'crypto';
3
+
4
+ export class HashUtil {
5
+ /** Deterministic hex digest for high-entropy values (tokens), where a slow password hash isn't needed. */
6
+ static sha256(value: string): string {
7
+ return createHash('sha256').update(value).digest('hex');
8
+ }
9
+
10
+ static async hashPassword(plainText: string): Promise<string> {
11
+ // Standard config: Cân bằng tốc độ và bảo mật cho web (Khoảng 200-300ms)
12
+ return argon2.hash(plainText, {
13
+ type: argon2.argon2id,
14
+ memoryCost: 19456, // 19 MB RAM
15
+ timeCost: 2, // 2 iterations
16
+ parallelism: 1, // 1 thread
17
+ });
18
+ }
19
+
20
+ static async comparePassword(
21
+ plainText: string,
22
+ hash: string,
23
+ ): Promise<boolean> {
24
+ try {
25
+ return await argon2.verify(hash, plainText);
26
+ } catch {
27
+ return false;
28
+ }
29
+ }
30
+
31
+ static generateRandomToken(length = 32): string {
32
+ return randomBytes(length).toString('hex');
33
+ }
34
+
35
+ /** Keyed hex digest: unlike a plain hash, it can't be brute-forced offline without the key. */
36
+ static hmacSha256(key: string | Buffer, value: string): string {
37
+ return createHmac('sha256', key).update(value).digest('hex');
38
+ }
39
+
40
+ /**
41
+ * A numeric one-time code of `length` digits (leading zeros allowed), drawn from
42
+ * the OS CSPRNG so it can't be predicted from earlier codes.
43
+ */
44
+ static generateOTP(length = 6): string {
45
+ return randomInt(0, Math.pow(10, length)).toString().padStart(length, '0');
46
+ }
47
+ }
@@ -0,0 +1,40 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { SnowflakeGenerator, snowflake } from './snowflake.util.js';
3
+
4
+ describe('SnowflakeGenerator', () => {
5
+ it('should generate a string ID', () => {
6
+ const id = snowflake.nextId();
7
+ expect(typeof id).toBe('string');
8
+ expect(id.length).toBeGreaterThan(0);
9
+ });
10
+
11
+ it('should generate unique IDs (10000 items)', () => {
12
+ const ids = new Set<string>();
13
+ const count = 10000;
14
+ for (let i = 0; i < count; i++) {
15
+ ids.add(snowflake.nextId());
16
+ }
17
+ expect(ids.size).toBe(count);
18
+ });
19
+
20
+ it('should construct with specific machine ID', () => {
21
+ const customSnowflake = new SnowflakeGenerator(5);
22
+ const id = customSnowflake.nextId();
23
+ expect(typeof id).toBe('string');
24
+ });
25
+
26
+ it('should throw error if machine ID is out of bounds', () => {
27
+ expect(() => new SnowflakeGenerator(2000)).toThrow();
28
+ expect(() => new SnowflakeGenerator(-1)).toThrow();
29
+ });
30
+
31
+ it('should derive a machine ID within valid bounds when PROCESS_ID is unset', () => {
32
+ const original = process.env.PROCESS_ID;
33
+ delete process.env.PROCESS_ID;
34
+ try {
35
+ expect(() => new SnowflakeGenerator()).not.toThrow();
36
+ } finally {
37
+ if (original !== undefined) process.env.PROCESS_ID = original;
38
+ }
39
+ });
40
+ });
@@ -0,0 +1,99 @@
1
+ import { hostname } from 'os';
2
+ import { createHash } from 'crypto';
3
+
4
+ /**
5
+ * Derives a machine id from the host's hostname when PROCESS_ID isn't set
6
+ * explicitly, so different containers/instances don't silently collide on
7
+ * the same default id (each container gets a distinct hostname in
8
+ * Docker/Kubernetes, unlike a fixed literal default).
9
+ */
10
+ function deriveMachineIdFromHostname(maxMachineId: number): number {
11
+ const hash = createHash('sha256').update(hostname()).digest();
12
+ const value = hash.readUInt32BE(0);
13
+ return value % (maxMachineId + 1);
14
+ }
15
+
16
+ /**
17
+ * Trình tạo Snowflake ID.
18
+ * Cấu trúc (64 bit) trả về dưới dạng string:
19
+ * - 41 bits: Timestamp (mili-giây) từ một epoch cố định.
20
+ * - 10 bits: Machine/Worker ID (0 - 1023).
21
+ * - 12 bits: Sequence number (0 - 4095).
22
+ */
23
+ export class SnowflakeGenerator {
24
+ private readonly EPOCH = 1704067200000n; // 2024-01-01T00:00:00.000Z
25
+ private readonly MACHINE_ID_BITS = 10n;
26
+ private readonly SEQUENCE_BITS = 12n;
27
+
28
+ private readonly MAX_MACHINE_ID = -1n ^ (-1n << this.MACHINE_ID_BITS);
29
+ private readonly MAX_SEQUENCE = -1n ^ (-1n << this.SEQUENCE_BITS);
30
+
31
+ private readonly MACHINE_ID_SHIFT = this.SEQUENCE_BITS;
32
+ private readonly TIMESTAMP_SHIFT = this.SEQUENCE_BITS + this.MACHINE_ID_BITS;
33
+
34
+ private machineId: bigint;
35
+ private sequence: bigint = 0n;
36
+ private lastTimestamp: bigint = -1n;
37
+
38
+ constructor(machineId?: number) {
39
+ let id = machineId;
40
+ if (id === undefined) {
41
+ // PROCESS_ID lets an operator pin an explicit id (e.g. from a k8s
42
+ // pod ordinal). Without it, every instance would otherwise fall back
43
+ // to the same hardcoded default and risk generating colliding ids —
44
+ // so instead each host derives its own id from its hostname.
45
+ id = process.env.PROCESS_ID
46
+ ? parseInt(process.env.PROCESS_ID, 10)
47
+ : deriveMachineIdFromHostname(Number(this.MAX_MACHINE_ID));
48
+ }
49
+
50
+ this.machineId = BigInt(id);
51
+ if (this.machineId < 0n || this.machineId > this.MAX_MACHINE_ID) {
52
+ throw new Error(
53
+ `Machine ID phải nằm trong khoảng từ 0 đến ${this.MAX_MACHINE_ID}`,
54
+ );
55
+ }
56
+ }
57
+
58
+ private currentTimestamp(): bigint {
59
+ return BigInt(Date.now());
60
+ }
61
+
62
+ private waitNextMillis(currentTimestamp: bigint): bigint {
63
+ let timestamp = this.currentTimestamp();
64
+ while (timestamp <= currentTimestamp) {
65
+ timestamp = this.currentTimestamp();
66
+ }
67
+ return timestamp;
68
+ }
69
+
70
+ public nextId(): string {
71
+ let timestamp = this.currentTimestamp();
72
+
73
+ if (timestamp < this.lastTimestamp) {
74
+ throw new Error('Đồng hồ hệ thống bị lùi lại. Không thể sinh ID.');
75
+ }
76
+
77
+ if (timestamp === this.lastTimestamp) {
78
+ this.sequence = (this.sequence + 1n) & this.MAX_SEQUENCE;
79
+ if (this.sequence === 0n) {
80
+ // Hết sequence trong 1 mili-giây, đợi sang mili-giây tiếp theo
81
+ timestamp = this.waitNextMillis(this.lastTimestamp);
82
+ }
83
+ } else {
84
+ this.sequence = 0n;
85
+ }
86
+
87
+ this.lastTimestamp = timestamp;
88
+
89
+ const id =
90
+ ((timestamp - this.EPOCH) << this.TIMESTAMP_SHIFT) |
91
+ (this.machineId << this.MACHINE_ID_SHIFT) |
92
+ this.sequence;
93
+
94
+ return id.toString();
95
+ }
96
+ }
97
+
98
+ // Khởi tạo Singleton để dùng chung toàn app
99
+ export const snowflake = new SnowflakeGenerator();
@@ -0,0 +1,20 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { StringUtil } from './string.util.js';
3
+
4
+ describe('StringUtil', () => {
5
+ it('should slugify vietnamese string correctly', () => {
6
+ const input = 'Áo thun Nam Đẹp 2024!@#';
7
+ const slug = StringUtil.slugify(input);
8
+
9
+ expect(slug).toBe('ao-thun-nam-dep-2024');
10
+ });
11
+
12
+ it('should generate an order code with given prefix', () => {
13
+ const code = StringUtil.generateOrderCode('SHOPEE');
14
+ expect(code.startsWith('SHOPEE-')).toBe(true);
15
+
16
+ const parts = code.split('-');
17
+ expect(parts.length).toBe(3);
18
+ expect(parts[0]).toBe('SHOPEE');
19
+ });
20
+ });
@@ -0,0 +1,21 @@
1
+ import slugify from 'slugify';
2
+ import { randomBytes } from 'crypto';
3
+
4
+ export class StringUtil {
5
+ static slugify(text: string): string {
6
+ return slugify(text, {
7
+ replacement: '-',
8
+ remove: undefined,
9
+ lower: true,
10
+ strict: true,
11
+ locale: 'vi',
12
+ trim: true,
13
+ });
14
+ }
15
+
16
+ static generateOrderCode(prefix = 'ORD'): string {
17
+ const timestamp = Date.now().toString(36).toUpperCase();
18
+ const random = randomBytes(2).toString('hex').toUpperCase();
19
+ return `${prefix}-${timestamp}-${random}`;
20
+ }
21
+ }
@@ -0,0 +1,25 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { TimeUtil } from './time.util.js';
3
+ import dayjs from 'dayjs';
4
+
5
+ describe('TimeUtil', () => {
6
+ it('should get current time in UTC ISO format', () => {
7
+ const time = TimeUtil.getCurrentUtc();
8
+ expect(time.endsWith('Z')).toBe(true);
9
+ });
10
+
11
+ it('should add minutes correctly', () => {
12
+ const baseDate = '2024-01-01T12:00:00Z';
13
+ const newDate = TimeUtil.addMinutes(15, baseDate);
14
+
15
+ expect(newDate).toBe('2024-01-01T12:15:00.000Z');
16
+ });
17
+
18
+ it('should correctly identify expired time', () => {
19
+ const pastDate = dayjs().subtract(1, 'minute').toISOString();
20
+ const futureDate = dayjs().add(1, 'minute').toISOString();
21
+
22
+ expect(TimeUtil.isExpired(pastDate)).toBe(true);
23
+ expect(TimeUtil.isExpired(futureDate)).toBe(false);
24
+ });
25
+ });
@@ -0,0 +1,25 @@
1
+ import dayjs from 'dayjs';
2
+ import utc from 'dayjs/plugin/utc.js';
3
+ import timezone from 'dayjs/plugin/timezone.js';
4
+
5
+ dayjs.extend(utc);
6
+ dayjs.extend(timezone);
7
+
8
+ export class TimeUtil {
9
+ static getCurrentUtc(): string {
10
+ return dayjs().utc().toISOString();
11
+ }
12
+
13
+ static addMinutes(minutes: number, fromDate?: string | Date): string {
14
+ const base = fromDate ? dayjs(fromDate) : dayjs();
15
+ return base.add(minutes, 'minute').utc().toISOString();
16
+ }
17
+
18
+ static isExpired(targetDate: string | Date): boolean {
19
+ return dayjs().isAfter(dayjs(targetDate));
20
+ }
21
+
22
+ static toUtcDate(dateString: string): Date {
23
+ return dayjs(dateString).utc().toDate();
24
+ }
25
+ }
@@ -0,0 +1,22 @@
1
+ const DAY = 24;
2
+ const HOUR = 60;
3
+ const MINUTE = 60;
4
+ const SECOND = 1; // Hệ thống này lưu TTL vào Redis dưới dạng Giây (Seconds)
5
+
6
+ export const buildTTL = (
7
+ unit: 'DAY' | 'HOUR' | 'MINUTE' | 'SECOND',
8
+ value: number,
9
+ ) => {
10
+ switch (unit) {
11
+ case 'DAY':
12
+ return value * DAY * HOUR * MINUTE * SECOND;
13
+ case 'HOUR':
14
+ return value * HOUR * MINUTE * SECOND;
15
+ case 'MINUTE':
16
+ return value * MINUTE * SECOND;
17
+ case 'SECOND':
18
+ return value * SECOND;
19
+ default:
20
+ return value * DAY * HOUR * MINUTE * SECOND;
21
+ }
22
+ };
@@ -0,0 +1,61 @@
1
+ import { NestFactory } from '@nestjs/core';
2
+ import { ValidationPipe } from '@nestjs/common';
3
+ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
4
+ import { ClsService } from 'nestjs-cls';
5
+ import { json } from 'express';
6
+ import helmet from 'helmet';
7
+ import { AppModule } from './app.module.js';
8
+ import { AllExceptionsFilter } from './core/http/filters/all-exceptions.filter.js';
9
+ import { ResponseInterceptor } from './core/http/interceptors/response.interceptor.js';
10
+ import { LoggingInterceptor } from './core/http/interceptors/logging.interceptor.js';
11
+ import { AppLogger } from './core/http/logging/app.logger.js';
12
+
13
+ async function bootstrap() {
14
+ const app = await NestFactory.create(AppModule, {
15
+ bufferLogs: true, // Buffer logs until custom logger is attached
16
+ });
17
+ app.useLogger(new AppLogger());
18
+
19
+ // Security headers
20
+ app.use(helmet());
21
+
22
+ // CORS — restrict origins in production via CORS_ORIGINS (comma separated)
23
+ const rawOrigins = process.env.CORS_ORIGINS;
24
+ app.enableCors({
25
+ origin: rawOrigins ? rawOrigins.split(',').map((o) => o.trim()) : '*',
26
+ methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
27
+ allowedHeaders: ['Content-Type', 'Authorization', 'Idempotency-Key'],
28
+ credentials: false,
29
+ });
30
+
31
+ app.enableShutdownHooks();
32
+ app.setGlobalPrefix('api/v1');
33
+
34
+ // Reject oversized payloads before they hit any handler
35
+ app.use(json({ limit: '1mb' }));
36
+
37
+ app.useGlobalPipes(
38
+ new ValidationPipe({
39
+ whitelist: true, // strip unknown fields silently
40
+ forbidNonWhitelisted: true, // AND reject the request if unknown fields are present
41
+ transform: true,
42
+ }),
43
+ );
44
+ app.useGlobalFilters(new AllExceptionsFilter(app.get(ClsService)));
45
+ app.useGlobalInterceptors(new LoggingInterceptor(), new ResponseInterceptor());
46
+
47
+ // Swagger documentation
48
+ const config = new DocumentBuilder()
49
+ .setTitle('{{PROJECT_NAME}} API')
50
+ .setVersion('1.0')
51
+ .addBearerAuth()
52
+ .build();
53
+ SwaggerModule.setup(
54
+ 'api/v1/docs',
55
+ app,
56
+ SwaggerModule.createDocument(app, config),
57
+ );
58
+
59
+ await app.listen(process.env.PORT ?? 3000);
60
+ }
61
+ void bootstrap();
@@ -0,0 +1,6 @@
1
+ import dotenv from 'dotenv';
2
+ dotenv.config({ path: '.env.test' });
3
+
4
+ // Background jobs run inside the request here, so e2e tests need no broker.
5
+ // (Only read when the rabbitmq infra is installed.)
6
+ process.env.JOB_QUEUE ??= 'inline';
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "ignoreDeprecations": "6.0",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src"],
8
+ "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
9
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "compilerOptions": {
3
+ "ignoreDeprecations": "6.0",
4
+ "module": "nodenext",
5
+ "moduleResolution": "nodenext",
6
+ "resolvePackageJsonExports": true,
7
+ "esModuleInterop": true,
8
+ "isolatedModules": true,
9
+ "declaration": true,
10
+ "removeComments": true,
11
+ "emitDecoratorMetadata": true,
12
+ "experimentalDecorators": true,
13
+ "allowSyntheticDefaultImports": true,
14
+ "target": "ES2023",
15
+ "sourceMap": true,
16
+ "outDir": "./dist",
17
+ "rootDir": ".",
18
+ "incremental": true,
19
+ "skipLibCheck": true,
20
+ "strict": true,
21
+ "strictPropertyInitialization": false,
22
+ "types": ["vitest/globals", "node"],
23
+ "baseUrl": "./",
24
+ "paths": {
25
+ "@/*": ["src/*"]
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ resolve: {
5
+ tsconfigPaths: true,
6
+ },
7
+ test: {
8
+ globals: true,
9
+ root: './',
10
+ include: ['**/*.e2e-spec.ts'],
11
+ exclude: ['**/node_modules/**', '**/dist/**'],
12
+ setupFiles: ['./test/setup.ts'],
13
+ fileParallelism: false,
14
+ },
15
+ });
@@ -0,0 +1,16 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ // Vite natively supports tsconfig paths
5
+ resolve: {
6
+ tsconfigPaths: true,
7
+ },
8
+ test: {
9
+ globals: true,
10
+ root: './',
11
+ fileParallelism: false,
12
+ include: ['**/*.spec.ts', '**/*.integration-spec.ts', '**/*.e2e-spec.ts'],
13
+ exclude: ['**/node_modules/**', '**/dist/**'],
14
+ setupFiles: ['./test/setup.ts'],
15
+ },
16
+ });
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "nest-ddd",
3
+ "label": "NestJS · DDD + CQRS (Clean Architecture)",
4
+ "group": "backend",
5
+ "description": "core/ + modules/<context>/{domain,application,infrastructure,presentation}",
6
+ "supportsInfra": true,
7
+ "nextSteps": ["start:dev"]
8
+ }
@@ -0,0 +1,28 @@
1
+ MONGO_URI=mongodb+srv://thuyphuocthinhtpt1:09122003@cluster0.j97zc.mongodb.net/ecommerce-tipsjs?retryWrites=true&w=majority&appName=Cluster0
2
+ PORT=5000
3
+ DEV_APP_PORT=3000
4
+ DEV_DB_HOST=localhost
5
+ DEV_DB_PORT=27017
6
+ DEV_DB_NAME=dbDev
7
+ PRO_APP_PORT=3000
8
+ PRO_DB_HOST=localhost
9
+ PRO_DB_PORT=27017
10
+ PRO_DB_NAME=dbProduct
11
+ NODE_ENV=dev
12
+ CHANNEL_ID=1314221126024560653
13
+ TOKEN_DISCORD=your_discord_token
14
+
15
+ CLOUDINARY_CLOUD_NAME=dy0m9udjz
16
+ CLOUDINARY_API_KEY=your_cloudinary_api_key
17
+ CLOUDINARY_API_SECRET=your_cloudinary_api_secret
18
+
19
+ AWS_REGION=ap-southeast-1
20
+ AWS_BUCKET_NAME=shopdev-ecom-bucket-s3
21
+ AWS_BUCKET_ACCESS_KEY=your_aws_access_key
22
+ AWS_BUCKET_SECRET_KEY=your_aws_secret_key
23
+ AWS_CLOUDFRONT_DOMAIN=https://d2bueawcnwe0if.cloudfront.net
24
+ AWS_CLOUDFRONT_PUBLIC_KEY_ID=K10XVU65Z0IGBU
25
+ AWS_CLOUDFRONT_PRIVATE_KEY=your_cloudfront_private_key"
26
+
27
+ AWS_EMAIL_APP_USER=your_aws_email_app_user
28
+ AWS_EMAIL_APP_PASSWORD=your_aws_email_app_password
@@ -0,0 +1,52 @@
1
+ version: '3.8'
2
+ services:
3
+ zookeeper:
4
+ image: bitnami/zookeeper:latest
5
+ container_name: zookeeper
6
+ environment:
7
+ - ALLOW_ANONYMOUS_LOGIN=yes
8
+ ports:
9
+ - "2181:2181"
10
+
11
+ kafka:
12
+ image: bitnami/kafka:latest
13
+ container_name: kafka
14
+ environment:
15
+ - KAFKA_BROKER_ID=1
16
+ - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181
17
+ - KAFKA_LISTENERS=PLAINTEXT://:9092
18
+ - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://localhost:9092
19
+ - KAFKA_LISTENER_SECURITY_PROTOCOL=PLAINTEXT
20
+ ports:
21
+ - "9092:9092"
22
+ depends_on:
23
+ - zookeeper
24
+
25
+ elasticsearch:
26
+ image: docker.elastic.co/elasticsearch/elasticsearch:7.10.0
27
+ container_name: shopdev_es
28
+ environment:
29
+ - node.name=shopdev_es
30
+ - cluster.name=docker-cluster
31
+ - bootstrap.memory_lock=true
32
+ - discovery.type=single-node
33
+ ulimits:
34
+ memlock:
35
+ soft: -1
36
+ hard: -1
37
+ volumes:
38
+ - esdata:/usr/share/elasticsearch/data
39
+ ports:
40
+ - "9200:9200"
41
+
42
+ kibana:
43
+ image: docker.elastic.co/kibana/kibana:7.10.0
44
+ container_name: shopdev_kibana
45
+ ports:
46
+ - "5601:5601"
47
+ depends_on:
48
+ - elasticsearch
49
+
50
+ volumes:
51
+ esdata:
52
+ driver: local