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,16 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const { asyncHandler } = require("../../auth/checkAuth");
4
+ const { authentication } = require("../../auth/authUtils");
5
+ const commentController = require("../../controllers/comment.controller");
6
+ const router = express.Router();
7
+
8
+ router.use(authentication);
9
+ router.post("/add-new", asyncHandler(commentController.createComment));
10
+ router.post("/delete", asyncHandler(commentController.deleteComments));
11
+ router.post(
12
+ "/get-list-by-parent-id",
13
+ asyncHandler(commentController.getCommentsByParentId)
14
+ );
15
+
16
+ module.exports = router;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const { asyncHandler } = require("../../auth/checkAuth");
4
+ const { authentication } = require("../../auth/authUtils");
5
+ const discountController = require("../../controllers/discount.controller");
6
+ const router = express.Router();
7
+ router.post(
8
+ "/get-discount-amount",
9
+ asyncHandler(discountController.getDiscountAmount)
10
+ );
11
+ router.get(
12
+ "/get-products-by-discount/:code/:shopId",
13
+ asyncHandler(discountController.getProductsByDiscount)
14
+ );
15
+
16
+ router.use(authentication);
17
+ router.post("/create", asyncHandler(discountController.createDiscount));
18
+ router.post("/delete", asyncHandler(discountController.deleteDiscount));
19
+ router.patch("/cancel", asyncHandler(discountController.cancelDiscount));
20
+ router.get(
21
+ "/get-all-discounts-by-shop",
22
+ asyncHandler(discountController.getAllDiscountCodeByShop)
23
+ );
24
+ router.patch("/update", asyncHandler(discountController.updateDiscount));
25
+
26
+ module.exports = router;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const router = express.Router();
4
+ const { checkApiKey, checkPermissions } = require("../auth/checkAuth.js");
5
+ const { pushToLogDiscord } = require("../middlewares/index.js");
6
+
7
+ // add log to discord
8
+ router.use(pushToLogDiscord);
9
+ router.use("/v1/api/upload", require("./upload/index.route.js"));
10
+ router.use("/v1/api/profile", require("./profile/index.route.js"));
11
+
12
+ // check api key
13
+ router.use(checkApiKey);
14
+ router.use(checkPermissions("0000"));
15
+
16
+ router.use("/v1/api", require("./access/index.route.js"));
17
+ router.use("/v1/api/template", require("./template/index.route.js"));
18
+ router.use("/v1/api/rbac", require("./rbac/index.route.js"));
19
+ router.use("/v1/api/product", require("./product/index.route.js"));
20
+ router.use("/v1/api/discount", require("./discount/index.route.js"));
21
+ router.use("/v1/api/cart", require("./cart/index.route.js"));
22
+ router.use("/v1/api/checkout", require("./checkout/index.route.js"));
23
+ router.use("/v1/api/inventory", require("./inventory/index.route.js"));
24
+ router.use("/v1/api/comment", require("./comment/index.route.js"));
25
+ router.use("/v1/api/notification", require("./notification/index.route.js"));
26
+
27
+ module.exports = router;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const { asyncHandler } = require("../../auth/checkAuth");
4
+ const { authentication } = require("../../auth/authUtils");
5
+ const inventoryController = require("../../controllers/inventory.controller");
6
+ const router = express.Router();
7
+
8
+ router.use(authentication);
9
+ router.post("/add-stock", asyncHandler(inventoryController.addStockToInventory));
10
+
11
+ module.exports = router;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const { asyncHandler } = require("../../auth/checkAuth");
4
+ const { authentication } = require("../../auth/authUtils");
5
+ const notificationController = require("../../controllers/notification.controller");
6
+ const router = express.Router();
7
+
8
+ router.use(authentication);
9
+ router.get(
10
+ "/list-noti-by-user",
11
+ asyncHandler(notificationController.getListNotiByUser)
12
+ );
13
+
14
+ module.exports = router;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const productController = require("../../controllers/product.controller");
4
+ const { asyncHandler } = require("../../auth/checkAuth");
5
+ const { authentication } = require("../../auth/authUtils");
6
+ const router = express.Router();
7
+
8
+ router.get(
9
+ "/search/:keySearch",
10
+ asyncHandler(productController.searchProductsByUser)
11
+ );
12
+ router.get("/all", asyncHandler(productController.findAllProducts));
13
+ router.get("/detail/:id", asyncHandler(productController.findDetailProduct));
14
+ router.get("/sku", asyncHandler(productController.getDetailSku));
15
+ router.get(
16
+ "/sku/listBySpuId",
17
+ asyncHandler(productController.getListSkuBySpuId)
18
+ );
19
+
20
+ // => /sku?sku_id=123&spu_id=123 => for example
21
+
22
+ // authentication
23
+ router.use(authentication);
24
+ // authentication
25
+
26
+ router.get("/spu", asyncHandler(productController.getDetailSpu));
27
+ router.post("/spu/create", asyncHandler(productController.createNewSpu));
28
+ router.post("/create", asyncHandler(productController.createNewProduct));
29
+ router.post("/publish/:id", asyncHandler(productController.publishProduct));
30
+ router.post("/unpublish/:id", asyncHandler(productController.unpublishProduct));
31
+ router.get("/drafts/all", asyncHandler(productController.getAllDraftProducts));
32
+ router.get(
33
+ "/published/all",
34
+ asyncHandler(productController.getAllPulishedProducts)
35
+ );
36
+ router.patch("/update/:id", asyncHandler(productController.updateProductById));
37
+
38
+ module.exports = router;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const { profiles, profile } = require("../../controllers/profile.controller");
4
+ const { grantAccess } = require("../../middlewares/rbac");
5
+ const router = express.Router();
6
+
7
+ // admin
8
+ router.get("/view-any", grantAccess("readAny", "profile"), profiles);
9
+
10
+ // shop
11
+ router.get("/view-own", grantAccess("readOwn", "profile"), profile);
12
+
13
+ // user
14
+
15
+ module.exports = router;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const { asyncHandler } = require("../../auth/checkAuth");
4
+ const { authentication } = require("../../auth/authUtils");
5
+ const rbacController = require("../../controllers/rbac.controller");
6
+ const router = express.Router();
7
+
8
+ router.use(authentication);
9
+
10
+ router.post("/create-new-role", asyncHandler(rbacController.createNewRole));
11
+ router.post(
12
+ "/create-new-resource",
13
+ asyncHandler(rbacController.createNewResource)
14
+ );
15
+ router.get("/get-resource-list", asyncHandler(rbacController.getResourceList));
16
+ router.get("/get-role-list", asyncHandler(rbacController.getRoleList));
17
+
18
+ module.exports = router;
19
+
20
+
21
+ // rbac => role based access control
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const { asyncHandler } = require("../../auth/checkAuth");
4
+ const { authentication } = require("../../auth/authUtils");
5
+ const router = express.Router();
6
+ const templateController = require("../../controllers/template.controller");
7
+ router.use(authentication);
8
+
9
+ router.post("/create", asyncHandler(templateController.createTemplate));
10
+
11
+ module.exports = router;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ const express = require("express");
3
+ const { asyncHandler } = require("../../auth/checkAuth");
4
+ const uploadController = require("../../controllers/upload.controller");
5
+ const { uploadToDisk, uploadToMemory } = require("../../config/config.multer");
6
+ // const { authentication } = require("../../auth/authUtils");
7
+ const router = express.Router();
8
+
9
+ // cloudinary
10
+ router.post("/fromUrl", asyncHandler(uploadController.uploadImgFromUrl));
11
+ router.post(
12
+ "/fromLocal",
13
+ uploadToDisk.single("file"),
14
+ asyncHandler(uploadController.uploadImgFromLocal)
15
+ );
16
+ router.post(
17
+ "/multiple/fromLocal",
18
+ uploadToDisk.array("files", 3),
19
+ asyncHandler(uploadController.uploadImagesFromLocal)
20
+ );
21
+ // aws-s3
22
+ router.post(
23
+ "/fromLocal/aws-s3-service-upload",
24
+ uploadToMemory.single("file"),
25
+ asyncHandler(uploadController.uploadImgFromLocalS3)
26
+ );
27
+
28
+ module.exports = router;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ const express = require("express");
4
+ const userController = require("../../controllers/user.controller");
5
+ const { asyncHandler } = require("../../auth/checkAuth");
6
+ const router = express.Router();
7
+
8
+ router.post("/new", asyncHandler(userController.newUser));
9
+ router.post(
10
+ "/verify-email",
11
+ asyncHandler(userController.checkRegisterEmailToken)
12
+ );
13
+ module.exports = router;
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+
3
+ const shopModel = require("../models/shop.model");
4
+ const bcrypt = require("bcrypt");
5
+ const crypto = require("crypto");
6
+ const KeyTokenService = require("./keyToken.service");
7
+ const { createTokenPair, verifyJWT } = require("../auth/authUtils");
8
+ const { getInfoData } = require("../utils");
9
+ const {
10
+ BadRequestError,
11
+ AuthFailureError,
12
+ ForbiddenError,
13
+ } = require("../core/error.response");
14
+ const { findByEmail } = require("./shop.service");
15
+ const RoleShop = {
16
+ SHOP: "SHOP",
17
+ WRITER: "WRITER",
18
+ EDITOR: "EDITOR",
19
+ ADMIN: "ADMIN",
20
+ };
21
+
22
+ class AccessService {
23
+ static handleRefreshToken = async (refreshToken) => {
24
+ // xem refreshToken gui len da het han hay chua
25
+ const foundToken = await KeyTokenService.findByRefreshTokenUsed(
26
+ refreshToken
27
+ );
28
+
29
+ if (foundToken) {
30
+ // decode ra xem may la thang nao?
31
+ const { userId, email } = await verifyJWT(
32
+ refreshToken,
33
+ foundToken.privateKey
34
+ );
35
+
36
+ if (userId && email) {
37
+ await KeyTokenService.deleteKeyByUserId(userId);
38
+ throw new ForbiddenError("Something wrong happened!! Please relogin");
39
+ }
40
+ }
41
+
42
+ // neu refreshToken chua het han, kiem tra xem refreshToken co phai do he thong tao hay khong
43
+ const holderToken = await KeyTokenService.findByRefreshToken(refreshToken);
44
+ if (!holderToken) {
45
+ throw new AuthFailureError("Shop not registerred");
46
+ }
47
+
48
+ // verify token
49
+ const { userId, email } = await verifyJWT(
50
+ refreshToken,
51
+ holderToken.privateKey
52
+ );
53
+
54
+ // check userId, email
55
+ const foundShop = await findByEmail({ email });
56
+ if (!foundShop) {
57
+ throw new AuthFailureError("Shop not registerred");
58
+ }
59
+
60
+ // neu thoa man hop le
61
+ // 1. create cap token moi
62
+ const { accessToken: newAccessToken, refreshToken: newRefreshToken } =
63
+ await createTokenPair(
64
+ {
65
+ userId,
66
+ email,
67
+ },
68
+ holderToken.privateKey,
69
+ holderToken.publicKey
70
+ );
71
+ // 2. dua refreshToken vua gui vao danh sach het han
72
+ await holderToken.updateOne({
73
+ $set: {
74
+ refreshToken: newRefreshToken,
75
+ },
76
+ $addToSet: {
77
+ refreshTokenUsed: refreshToken,
78
+ },
79
+ });
80
+ return {
81
+ user: { userId, email },
82
+ tokens: {
83
+ refreshToken: newRefreshToken,
84
+ accessToken: newAccessToken,
85
+ },
86
+ };
87
+ };
88
+
89
+ static handleRefreshTokenV2 = async ({ refreshToken, user, keyStore }) => {
90
+ const { userId, email } = user;
91
+
92
+ if (keyStore.refreshTokenUsed.includes(refreshToken)) {
93
+ await KeyTokenService.deleteKeyByUserId(userId);
94
+ throw new ForbiddenError("Something wrong happened!! Please relogin");
95
+ }
96
+
97
+ if (keyStore.refreshToken !== refreshToken) {
98
+ throw new AuthFailureError("Shop not registered");
99
+ }
100
+
101
+ // check userId, email
102
+ const foundShop = await findByEmail({ email });
103
+ if (!foundShop) {
104
+ throw new AuthFailureError("Shop not registerred");
105
+ }
106
+
107
+ // neu thoa man hop le
108
+ // 1. create cap token moi
109
+ const { accessToken: newAccessToken, refreshToken: newRefreshToken } =
110
+ await createTokenPair(
111
+ {
112
+ userId,
113
+ email,
114
+ },
115
+ keyStore.privateKey,
116
+ keyStore.publicKey
117
+ );
118
+ // 2. dua refreshToken vua gui vao danh sach het han
119
+ await keyStore.updateOne({
120
+ $set: {
121
+ refreshToken: newRefreshToken,
122
+ },
123
+ $addToSet: {
124
+ refreshTokenUsed: refreshToken,
125
+ },
126
+ });
127
+ return {
128
+ user: { userId, email },
129
+ tokens: {
130
+ refreshToken: newRefreshToken,
131
+ accessToken: newAccessToken,
132
+ },
133
+ };
134
+ };
135
+
136
+ static signUp = async ({ name, email, password }) => {
137
+ try {
138
+ // step 1: check su ton tai cua email
139
+ const holderShop = await shopModel.findOne({ email }).lean();
140
+ if (holderShop) {
141
+ throw new BadRequestError("Error: Shop already registered");
142
+ }
143
+
144
+ const hassPassword = await bcrypt.hash(password, 10);
145
+
146
+ const newShop = await shopModel.create({
147
+ name,
148
+ email,
149
+ password: hassPassword,
150
+ roles: [RoleShop.SHOP],
151
+ });
152
+
153
+ if (newShop) {
154
+ // create a pair of public/private key
155
+ // rsa => unsymetric cryptopancy algo
156
+ // const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
157
+ // modulusLength: 4096,
158
+ // publicKeyEncoding: {
159
+ // type: "pkcs1",
160
+ // format: "pem",
161
+ // },
162
+ // privateKeyEncoding: {
163
+ // type: "pkcs1",
164
+ // format: "pem",
165
+ // },
166
+ // });
167
+
168
+ const privateKey = crypto.randomBytes(64).toString("hex");
169
+ const publicKey = crypto.randomBytes(64).toString("hex");
170
+
171
+ const tokens = await createTokenPair(
172
+ {
173
+ userId: newShop._id,
174
+ email,
175
+ },
176
+ privateKey,
177
+ publicKey
178
+ );
179
+
180
+ const keyStore = await KeyTokenService.createKeyToken({
181
+ userId: newShop._id,
182
+ publicKey,
183
+ privateKey,
184
+ refreshToken: tokens.refreshToken,
185
+ });
186
+
187
+ if (!keyStore) {
188
+ throw new BadRequestError("Error: Public key string error");
189
+ }
190
+
191
+ return {
192
+ shop: getInfoData({
193
+ fields: ["_id", "name", "email"],
194
+ object: newShop,
195
+ }),
196
+ tokens,
197
+ };
198
+ }
199
+
200
+ return {
201
+ code: 200,
202
+ metadata: null,
203
+ };
204
+ } catch (error) {
205
+ throw new Error(error.message);
206
+ }
207
+ };
208
+
209
+ static login = async ({ email, password, refreshToken = null }) => {
210
+ try {
211
+ const foundShop = await findByEmail({ email });
212
+ if (!foundShop) {
213
+ throw new BadRequestError("Shop not registered");
214
+ }
215
+ const match = bcrypt.compare(password, foundShop.password);
216
+ if (!match) {
217
+ throw new AuthFailureError("Invalid credentials");
218
+ }
219
+
220
+ const privateKey = crypto.randomBytes(64).toString("hex");
221
+ const publicKey = crypto.randomBytes(64).toString("hex");
222
+
223
+ const tokens = await createTokenPair(
224
+ {
225
+ userId: foundShop._id,
226
+ email,
227
+ },
228
+ privateKey,
229
+ publicKey
230
+ );
231
+
232
+ await KeyTokenService.createKeyToken({
233
+ refreshToken: tokens.refreshToken,
234
+ privateKey,
235
+ publicKey,
236
+ userId: foundShop._id,
237
+ });
238
+
239
+ return {
240
+ shop: getInfoData({
241
+ fields: ["_id", "name", "email"],
242
+ object: foundShop,
243
+ }),
244
+ tokens,
245
+ };
246
+ } catch (error) {
247
+ throw new Error(error.message);
248
+ }
249
+ };
250
+
251
+ static logout = async (keyStore) => {
252
+ const delKey = await KeyTokenService.removeKeyTokenById(keyStore._id);
253
+ return delKey;
254
+ };
255
+ }
256
+
257
+ module.exports = AccessService;
@@ -0,0 +1,15 @@
1
+ const apiKeyModel = require("../models/apiKey.model");
2
+
3
+ const findById = async (key) => {
4
+ // const newKey = await apiKeyModel.create({
5
+ // key: "abcdefabcdefabcdefabcdef",
6
+ // permissions: ["0000"],
7
+ // });
8
+ // console.log(newKey);
9
+ const objKey = await apiKeyModel.findOne({ key, status: true }).lean();
10
+ return objKey;
11
+ };
12
+
13
+ module.exports = {
14
+ findById,
15
+ };
@@ -0,0 +1,115 @@
1
+ /**
2
+ * 1 - Add product to cart [User]
3
+ * 2 - Reduce / Increase product quantity [User]
4
+ * 3 - Get list products from cart [User]
5
+ * 4 - Delete cart [User]
6
+ * 5 - Delete cart item [User]
7
+ */
8
+
9
+ const { NotFoundError } = require("../core/error.response");
10
+ const cartModel = require("../models/cart.model");
11
+ const {
12
+ createUserCart,
13
+ updateCartItemQuantity,
14
+ removeItemFromCart,
15
+ } = require("../models/repository/cart.repo");
16
+ const { getProductById } = require("../models/repository/product.repo");
17
+ const { convertToObjectId } = require("../utils");
18
+
19
+ class CartService {
20
+ static async addProductToCart({ userId, product = {} }) {
21
+ // check cart ton tai hay khong
22
+ const userCart = await cartModel.findOne({
23
+ cart_user_id: convertToObjectId(userId),
24
+ });
25
+ if (!userCart) {
26
+ // tao gio hang moi neu gio hang chua ton tai
27
+ return await createUserCart({
28
+ userId,
29
+ product,
30
+ });
31
+ }
32
+ // neu gio hang ton tai nhung chua co san pham thi them san pham
33
+ if (!userCart.cart_products.length) {
34
+ userCart.cart_products = [product];
35
+ return await userCart.save();
36
+ }
37
+ // neu gio hang ton tai va ton tai san pham => cap nhat so luong
38
+ return await updateCartItemQuantity({
39
+ userId,
40
+ product,
41
+ });
42
+ }
43
+
44
+ /*
45
+ shop_order_ids:[
46
+ {
47
+ shop_id,
48
+ item_products: [
49
+ {
50
+ quantity,
51
+ price,
52
+ shop_id,
53
+ old_quantity,
54
+ product_id
55
+ }
56
+ ],
57
+ version
58
+ }
59
+ ]
60
+ */
61
+ // update quantity of each product
62
+ static async updateCart({ userId, shop_order_ids }) {
63
+ const { product_id, quantity, old_quantity } =
64
+ shop_order_ids[0]?.item_products[0];
65
+ // check product exists
66
+ const foundProduct = await getProductById({ productId: product_id });
67
+ if (!foundProduct) {
68
+ throw new NotFoundError("Product does not exist");
69
+ }
70
+ if (foundProduct.product_shop.toString() !== shop_order_ids[0]?.shop_id) {
71
+ throw new NotFoundError("Product does not belong to the shop");
72
+ }
73
+ if (quantity === 0) {
74
+ // remove item from cart
75
+ return await removeItemFromCart({
76
+ user_id: userId,
77
+ product_id,
78
+ });
79
+ }
80
+ return await updateCartItemQuantity({
81
+ userId,
82
+ product: {
83
+ product_id,
84
+ quantity: quantity - old_quantity,
85
+ },
86
+ });
87
+ }
88
+
89
+ static async getListProductsFromCart({ userId }) {
90
+ return await cartModel.findOne({
91
+ cart_user_id: convertToObjectId(userId),
92
+ });
93
+ }
94
+
95
+ static async removeItemFromCart({ user_id, product_id }) {
96
+ return await removeItemFromCart({
97
+ user_id,
98
+ product_id,
99
+ });
100
+ }
101
+
102
+ static async removeAllProductsFromCart({ cartId, userId }) {
103
+ const query = {
104
+ cart_user_id: convertToObjectId(userId),
105
+ };
106
+ const updateSet = {
107
+ $set: {
108
+ cart_products: [],
109
+ },
110
+ };
111
+ return await cartModel.findOneAndUpdate(query, updateSet);
112
+ }
113
+ }
114
+
115
+ module.exports = CartService;