90dc-core 1.19.2 → 1.19.4

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 (302) hide show
  1. package/dist/lib/dbmodels/index.d.ts +3 -2
  2. package/dist/lib/dbmodels/index.d.ts.map +1 -1
  3. package/dist/lib/dbmodels/{UserProgressPhoto.d.ts → user/UserProgressPhoto.d.ts} +1 -1
  4. package/dist/lib/dbmodels/user/UserProgressPhoto.d.ts.map +1 -0
  5. package/package.json +1 -1
  6. package/dist/index.js +0 -43
  7. package/dist/index.js.map +0 -1
  8. package/dist/lib/Errors/AppError.js +0 -104
  9. package/dist/lib/Errors/AppError.js.map +0 -1
  10. package/dist/lib/Errors/Errors.js +0 -42
  11. package/dist/lib/Errors/Errors.js.map +0 -1
  12. package/dist/lib/classes/Database.js +0 -154
  13. package/dist/lib/classes/Database.js.map +0 -1
  14. package/dist/lib/classes/Redis.js +0 -63
  15. package/dist/lib/classes/Redis.js.map +0 -1
  16. package/dist/lib/clients/EmailClient.js +0 -188
  17. package/dist/lib/clients/EmailClient.js.map +0 -1
  18. package/dist/lib/clients/FirebasePushNotificationClient.js +0 -688
  19. package/dist/lib/clients/FirebasePushNotificationClient.js.map +0 -1
  20. package/dist/lib/clients/ImagesClient.js +0 -271
  21. package/dist/lib/clients/ImagesClient.js.map +0 -1
  22. package/dist/lib/clients/MailingClient.js +0 -84
  23. package/dist/lib/clients/MailingClient.js.map +0 -1
  24. package/dist/lib/clients/PushNotificationClient.js +0 -478
  25. package/dist/lib/clients/PushNotificationClient.js.map +0 -1
  26. package/dist/lib/clients/types/email.types.js +0 -3
  27. package/dist/lib/clients/types/email.types.js.map +0 -1
  28. package/dist/lib/clients/types/images.types.js +0 -3
  29. package/dist/lib/clients/types/images.types.js.map +0 -1
  30. package/dist/lib/clients/types/mailing.types.js +0 -3
  31. package/dist/lib/clients/types/mailing.types.js.map +0 -1
  32. package/dist/lib/config/ConfigValidator.js +0 -162
  33. package/dist/lib/config/ConfigValidator.js.map +0 -1
  34. package/dist/lib/controllers/BaseController.js +0 -64
  35. package/dist/lib/controllers/BaseController.js.map +0 -1
  36. package/dist/lib/db/migrations/20260330000000-create-user-progress-photos.js +0 -60
  37. package/dist/lib/db/migrations/20260330000000-create-user-progress-photos.js.map +0 -1
  38. package/dist/lib/dbmodels/UserProgressPhoto.d.ts.map +0 -1
  39. package/dist/lib/dbmodels/UserProgressPhoto.js +0 -59
  40. package/dist/lib/dbmodels/UserProgressPhoto.js.map +0 -1
  41. package/dist/lib/dbmodels/coaching/Answer.js +0 -51
  42. package/dist/lib/dbmodels/coaching/Answer.js.map +0 -1
  43. package/dist/lib/dbmodels/coaching/ClientNote.js +0 -75
  44. package/dist/lib/dbmodels/coaching/ClientNote.js.map +0 -1
  45. package/dist/lib/dbmodels/coaching/ClientTag.js +0 -45
  46. package/dist/lib/dbmodels/coaching/ClientTag.js.map +0 -1
  47. package/dist/lib/dbmodels/coaching/Question.js +0 -60
  48. package/dist/lib/dbmodels/coaching/Question.js.map +0 -1
  49. package/dist/lib/dbmodels/coaching/Questionnaire.js +0 -39
  50. package/dist/lib/dbmodels/coaching/Questionnaire.js.map +0 -1
  51. package/dist/lib/dbmodels/coaching/QuestionnaireResponse.js +0 -42
  52. package/dist/lib/dbmodels/coaching/QuestionnaireResponse.js.map +0 -1
  53. package/dist/lib/dbmodels/coaching/WeeklyCheckIn.js +0 -69
  54. package/dist/lib/dbmodels/coaching/WeeklyCheckIn.js.map +0 -1
  55. package/dist/lib/dbmodels/coaching/WeightRecord.js +0 -49
  56. package/dist/lib/dbmodels/coaching/WeightRecord.js.map +0 -1
  57. package/dist/lib/dbmodels/diet/DietDay.js +0 -50
  58. package/dist/lib/dbmodels/diet/DietDay.js.map +0 -1
  59. package/dist/lib/dbmodels/diet/DietMeal.js +0 -74
  60. package/dist/lib/dbmodels/diet/DietMeal.js.map +0 -1
  61. package/dist/lib/dbmodels/diet/DietMealCompletion.js +0 -69
  62. package/dist/lib/dbmodels/diet/DietMealCompletion.js.map +0 -1
  63. package/dist/lib/dbmodels/diet/DietMealRecipe.js +0 -67
  64. package/dist/lib/dbmodels/diet/DietMealRecipe.js.map +0 -1
  65. package/dist/lib/dbmodels/diet/DietMealRecipeIngredient.js +0 -46
  66. package/dist/lib/dbmodels/diet/DietMealRecipeIngredient.js.map +0 -1
  67. package/dist/lib/dbmodels/diet/DietProgram.js +0 -98
  68. package/dist/lib/dbmodels/diet/DietProgram.js.map +0 -1
  69. package/dist/lib/dbmodels/diet/Ingredient.js +0 -88
  70. package/dist/lib/dbmodels/diet/Ingredient.js.map +0 -1
  71. package/dist/lib/dbmodels/diet/IngredientTag.js +0 -64
  72. package/dist/lib/dbmodels/diet/IngredientTag.js.map +0 -1
  73. package/dist/lib/dbmodels/diet/IngredientTags.js +0 -29
  74. package/dist/lib/dbmodels/diet/IngredientTags.js.map +0 -1
  75. package/dist/lib/dbmodels/diet/Recipe.js +0 -173
  76. package/dist/lib/dbmodels/diet/Recipe.js.map +0 -1
  77. package/dist/lib/dbmodels/diet/RecipeIngredient.js +0 -78
  78. package/dist/lib/dbmodels/diet/RecipeIngredient.js.map +0 -1
  79. package/dist/lib/dbmodels/diet/RecipeTag.js +0 -44
  80. package/dist/lib/dbmodels/diet/RecipeTag.js.map +0 -1
  81. package/dist/lib/dbmodels/diet/RecipeTags.js +0 -24
  82. package/dist/lib/dbmodels/diet/RecipeTags.js.map +0 -1
  83. package/dist/lib/dbmodels/diet/ShoppingList.js +0 -69
  84. package/dist/lib/dbmodels/diet/ShoppingList.js.map +0 -1
  85. package/dist/lib/dbmodels/diet/ShoppingListItem.js +0 -66
  86. package/dist/lib/dbmodels/diet/ShoppingListItem.js.map +0 -1
  87. package/dist/lib/dbmodels/diet/TranslatedRecipe.js +0 -122
  88. package/dist/lib/dbmodels/diet/TranslatedRecipe.js.map +0 -1
  89. package/dist/lib/dbmodels/diet/TranslatedRecipeTag.js +0 -47
  90. package/dist/lib/dbmodels/diet/TranslatedRecipeTag.js.map +0 -1
  91. package/dist/lib/dbmodels/diet/TranslatedRecipeTags.js +0 -24
  92. package/dist/lib/dbmodels/diet/TranslatedRecipeTags.js.map +0 -1
  93. package/dist/lib/dbmodels/diet/UserDietPreferences.js +0 -85
  94. package/dist/lib/dbmodels/diet/UserDietPreferences.js.map +0 -1
  95. package/dist/lib/dbmodels/gamification/Badge.js +0 -62
  96. package/dist/lib/dbmodels/gamification/Badge.js.map +0 -1
  97. package/dist/lib/dbmodels/gamification/StreaksLog.js +0 -37
  98. package/dist/lib/dbmodels/gamification/StreaksLog.js.map +0 -1
  99. package/dist/lib/dbmodels/gamification/TranslatedBadge.js +0 -45
  100. package/dist/lib/dbmodels/gamification/TranslatedBadge.js.map +0 -1
  101. package/dist/lib/dbmodels/gamification/xpAndLeaderboards/UserRankHistory.js +0 -48
  102. package/dist/lib/dbmodels/gamification/xpAndLeaderboards/UserRankHistory.js.map +0 -1
  103. package/dist/lib/dbmodels/gamification/xpAndLeaderboards/XpEvent.js +0 -53
  104. package/dist/lib/dbmodels/gamification/xpAndLeaderboards/XpEvent.js.map +0 -1
  105. package/dist/lib/dbmodels/gamification/xpAndLeaderboards/XpTransaction.js +0 -68
  106. package/dist/lib/dbmodels/gamification/xpAndLeaderboards/XpTransaction.js.map +0 -1
  107. package/dist/lib/dbmodels/index.js +0 -287
  108. package/dist/lib/dbmodels/index.js.map +0 -1
  109. package/dist/lib/dbmodels/nonconsprogram/NonConsumableProgram.d.ts +0 -32
  110. package/dist/lib/dbmodels/nonconsprogram/NonConsumableProgram.d.ts.map +0 -1
  111. package/dist/lib/dbmodels/nonconsprogram/NonConsumableProgram.js +0 -155
  112. package/dist/lib/dbmodels/nonconsprogram/NonConsumableProgram.js.map +0 -1
  113. package/dist/lib/dbmodels/nonconsprogram/NonConsumableProgramWebContent.d.ts +0 -22
  114. package/dist/lib/dbmodels/nonconsprogram/NonConsumableProgramWebContent.d.ts.map +0 -1
  115. package/dist/lib/dbmodels/nonconsprogram/NonConsumableProgramWebContent.js +0 -108
  116. package/dist/lib/dbmodels/nonconsprogram/NonConsumableProgramWebContent.js.map +0 -1
  117. package/dist/lib/dbmodels/nonconsprogram/TranslatedConsumableProgram.d.ts +0 -20
  118. package/dist/lib/dbmodels/nonconsprogram/TranslatedConsumableProgram.d.ts.map +0 -1
  119. package/dist/lib/dbmodels/nonconsprogram/TranslatedConsumableProgram.js +0 -97
  120. package/dist/lib/dbmodels/nonconsprogram/TranslatedConsumableProgram.js.map +0 -1
  121. package/dist/lib/dbmodels/nonconsprogram/TranslatedNonConsumableProgramWebContent.d.ts +0 -22
  122. package/dist/lib/dbmodels/nonconsprogram/TranslatedNonConsumableProgramWebContent.d.ts.map +0 -1
  123. package/dist/lib/dbmodels/nonconsprogram/TranslatedNonConsumableProgramWebContent.js +0 -115
  124. package/dist/lib/dbmodels/nonconsprogram/TranslatedNonConsumableProgramWebContent.js.map +0 -1
  125. package/dist/lib/dbmodels/nonconsprogram/UserNonConsumableProgram.d.ts +0 -7
  126. package/dist/lib/dbmodels/nonconsprogram/UserNonConsumableProgram.d.ts.map +0 -1
  127. package/dist/lib/dbmodels/nonconsprogram/UserNonConsumableProgram.js +0 -41
  128. package/dist/lib/dbmodels/nonconsprogram/UserNonConsumableProgram.js.map +0 -1
  129. package/dist/lib/dbmodels/notifications/NotificationModels.js +0 -38
  130. package/dist/lib/dbmodels/notifications/NotificationModels.js.map +0 -1
  131. package/dist/lib/dbmodels/notifications/TranslatedNotification.js +0 -45
  132. package/dist/lib/dbmodels/notifications/TranslatedNotification.js.map +0 -1
  133. package/dist/lib/dbmodels/program/Challenge.d.ts +0 -13
  134. package/dist/lib/dbmodels/program/Challenge.d.ts.map +0 -1
  135. package/dist/lib/dbmodels/program/Challenge.js +0 -63
  136. package/dist/lib/dbmodels/program/Challenge.js.map +0 -1
  137. package/dist/lib/dbmodels/program/ChallengeBlueprint.js +0 -75
  138. package/dist/lib/dbmodels/program/ChallengeBlueprint.js.map +0 -1
  139. package/dist/lib/dbmodels/program/CircularProgramDraft.js +0 -82
  140. package/dist/lib/dbmodels/program/CircularProgramDraft.js.map +0 -1
  141. package/dist/lib/dbmodels/program/CoachExerciseNote.js +0 -61
  142. package/dist/lib/dbmodels/program/CoachExerciseNote.js.map +0 -1
  143. package/dist/lib/dbmodels/program/CustomProgramBlueprint.js +0 -84
  144. package/dist/lib/dbmodels/program/CustomProgramBlueprint.js.map +0 -1
  145. package/dist/lib/dbmodels/program/CustomStrengthTest.js +0 -55
  146. package/dist/lib/dbmodels/program/CustomStrengthTest.js.map +0 -1
  147. package/dist/lib/dbmodels/program/CustomStrengthTestExercises.js +0 -69
  148. package/dist/lib/dbmodels/program/CustomStrengthTestExercises.js.map +0 -1
  149. package/dist/lib/dbmodels/program/CustomWorkoutBlueprint.js +0 -58
  150. package/dist/lib/dbmodels/program/CustomWorkoutBlueprint.js.map +0 -1
  151. package/dist/lib/dbmodels/program/Exercise.d.ts +0 -23
  152. package/dist/lib/dbmodels/program/Exercise.d.ts.map +0 -1
  153. package/dist/lib/dbmodels/program/Exercise.js +0 -101
  154. package/dist/lib/dbmodels/program/Exercise.js.map +0 -1
  155. package/dist/lib/dbmodels/program/ExerciseModels.d.ts +0 -28
  156. package/dist/lib/dbmodels/program/ExerciseModels.d.ts.map +0 -1
  157. package/dist/lib/dbmodels/program/ExerciseModels.js +0 -149
  158. package/dist/lib/dbmodels/program/ExerciseModels.js.map +0 -1
  159. package/dist/lib/dbmodels/program/Program.d.ts +0 -15
  160. package/dist/lib/dbmodels/program/Program.d.ts.map +0 -1
  161. package/dist/lib/dbmodels/program/Program.js +0 -76
  162. package/dist/lib/dbmodels/program/Program.js.map +0 -1
  163. package/dist/lib/dbmodels/program/ProgressEntry.d.ts +0 -26
  164. package/dist/lib/dbmodels/program/ProgressEntry.d.ts.map +0 -1
  165. package/dist/lib/dbmodels/program/ProgressEntry.js +0 -77
  166. package/dist/lib/dbmodels/program/ProgressEntry.js.map +0 -1
  167. package/dist/lib/dbmodels/program/RestDay.js +0 -33
  168. package/dist/lib/dbmodels/program/RestDay.js.map +0 -1
  169. package/dist/lib/dbmodels/program/StrengthTest.d.ts +0 -10
  170. package/dist/lib/dbmodels/program/StrengthTest.d.ts.map +0 -1
  171. package/dist/lib/dbmodels/program/StrengthTest.js +0 -39
  172. package/dist/lib/dbmodels/program/StrengthTest.js.map +0 -1
  173. package/dist/lib/dbmodels/program/StrengthTestExercise.d.ts +0 -15
  174. package/dist/lib/dbmodels/program/StrengthTestExercise.d.ts.map +0 -1
  175. package/dist/lib/dbmodels/program/StrengthTestExercise.js +0 -72
  176. package/dist/lib/dbmodels/program/StrengthTestExercise.js.map +0 -1
  177. package/dist/lib/dbmodels/program/StrengthTestSession.js +0 -73
  178. package/dist/lib/dbmodels/program/StrengthTestSession.js.map +0 -1
  179. package/dist/lib/dbmodels/program/Superset.d.ts +0 -13
  180. package/dist/lib/dbmodels/program/Superset.d.ts.map +0 -1
  181. package/dist/lib/dbmodels/program/Superset.js +0 -46
  182. package/dist/lib/dbmodels/program/Superset.js.map +0 -1
  183. package/dist/lib/dbmodels/program/ThirtyDayChallenge.js +0 -70
  184. package/dist/lib/dbmodels/program/ThirtyDayChallenge.js.map +0 -1
  185. package/dist/lib/dbmodels/program/ThirtyDayChallengeStrengthTest.js +0 -55
  186. package/dist/lib/dbmodels/program/ThirtyDayChallengeStrengthTest.js.map +0 -1
  187. package/dist/lib/dbmodels/program/TranslatedChallenge.d.ts +0 -15
  188. package/dist/lib/dbmodels/program/TranslatedChallenge.d.ts.map +0 -1
  189. package/dist/lib/dbmodels/program/TranslatedChallenge.js +0 -69
  190. package/dist/lib/dbmodels/program/TranslatedChallenge.js.map +0 -1
  191. package/dist/lib/dbmodels/program/TranslatedExerciseModel.d.ts +0 -25
  192. package/dist/lib/dbmodels/program/TranslatedExerciseModel.d.ts.map +0 -1
  193. package/dist/lib/dbmodels/program/TranslatedExerciseModel.js +0 -123
  194. package/dist/lib/dbmodels/program/TranslatedExerciseModel.js.map +0 -1
  195. package/dist/lib/dbmodels/program/TranslatedStrengthTest.d.ts +0 -12
  196. package/dist/lib/dbmodels/program/TranslatedStrengthTest.d.ts.map +0 -1
  197. package/dist/lib/dbmodels/program/TranslatedStrengthTest.js +0 -45
  198. package/dist/lib/dbmodels/program/TranslatedStrengthTest.js.map +0 -1
  199. package/dist/lib/dbmodels/program/TranslatedStrengthTestExercise.d.ts +0 -16
  200. package/dist/lib/dbmodels/program/TranslatedStrengthTestExercise.d.ts.map +0 -1
  201. package/dist/lib/dbmodels/program/TranslatedStrengthTestExercise.js +0 -78
  202. package/dist/lib/dbmodels/program/TranslatedStrengthTestExercise.js.map +0 -1
  203. package/dist/lib/dbmodels/program/UserChallenge.d.ts +0 -10
  204. package/dist/lib/dbmodels/program/UserChallenge.d.ts.map +0 -1
  205. package/dist/lib/dbmodels/program/UserChallenge.js +0 -47
  206. package/dist/lib/dbmodels/program/UserChallenge.js.map +0 -1
  207. package/dist/lib/dbmodels/program/UserExerciseNote.js +0 -61
  208. package/dist/lib/dbmodels/program/UserExerciseNote.js.map +0 -1
  209. package/dist/lib/dbmodels/program/UserStrengthTests.d.ts +0 -11
  210. package/dist/lib/dbmodels/program/UserStrengthTests.d.ts.map +0 -1
  211. package/dist/lib/dbmodels/program/UserStrengthTests.js +0 -54
  212. package/dist/lib/dbmodels/program/UserStrengthTests.js.map +0 -1
  213. package/dist/lib/dbmodels/program/Workout.d.ts +0 -14
  214. package/dist/lib/dbmodels/program/Workout.d.ts.map +0 -1
  215. package/dist/lib/dbmodels/program/Workout.js +0 -66
  216. package/dist/lib/dbmodels/program/Workout.js.map +0 -1
  217. package/dist/lib/dbmodels/program/WorkoutCompletion.js +0 -65
  218. package/dist/lib/dbmodels/program/WorkoutCompletion.js.map +0 -1
  219. package/dist/lib/dbmodels/program/WorkoutSession.js +0 -93
  220. package/dist/lib/dbmodels/program/WorkoutSession.js.map +0 -1
  221. package/dist/lib/dbmodels/subscription/Subscription.d.ts +0 -19
  222. package/dist/lib/dbmodels/subscription/Subscription.d.ts.map +0 -1
  223. package/dist/lib/dbmodels/subscription/Subscription.js +0 -91
  224. package/dist/lib/dbmodels/subscription/Subscription.js.map +0 -1
  225. package/dist/lib/dbmodels/subscription/SubscriptionEvent.js +0 -79
  226. package/dist/lib/dbmodels/subscription/SubscriptionEvent.js.map +0 -1
  227. package/dist/lib/dbmodels/subscription/SubscriptionLog.d.ts +0 -9
  228. package/dist/lib/dbmodels/subscription/SubscriptionLog.d.ts.map +0 -1
  229. package/dist/lib/dbmodels/subscription/SubscriptionLog.js +0 -42
  230. package/dist/lib/dbmodels/subscription/SubscriptionLog.js.map +0 -1
  231. package/dist/lib/dbmodels/subscription/SubscriptionRefund.js +0 -92
  232. package/dist/lib/dbmodels/subscription/SubscriptionRefund.js.map +0 -1
  233. package/dist/lib/dbmodels/user/DeviceTokens.js +0 -34
  234. package/dist/lib/dbmodels/user/DeviceTokens.js.map +0 -1
  235. package/dist/lib/dbmodels/user/PersistedUser.d.ts +0 -43
  236. package/dist/lib/dbmodels/user/PersistedUser.d.ts.map +0 -1
  237. package/dist/lib/dbmodels/user/PersistedUser.js +0 -237
  238. package/dist/lib/dbmodels/user/PersistedUser.js.map +0 -1
  239. package/dist/lib/dbmodels/user/UserAddons.js +0 -26
  240. package/dist/lib/dbmodels/user/UserAddons.js.map +0 -1
  241. package/dist/lib/dbmodels/user/UserBadges.js +0 -63
  242. package/dist/lib/dbmodels/user/UserBadges.js.map +0 -1
  243. package/dist/lib/dbmodels/user/UserCoach.js +0 -40
  244. package/dist/lib/dbmodels/user/UserCoach.js.map +0 -1
  245. package/dist/lib/dbmodels/user/UserDiscount.js +0 -24
  246. package/dist/lib/dbmodels/user/UserDiscount.js.map +0 -1
  247. package/dist/lib/dbmodels/user/UserOptions.js +0 -34
  248. package/dist/lib/dbmodels/user/UserOptions.js.map +0 -1
  249. package/dist/lib/dbmodels/user/UserStreaks.js +0 -64
  250. package/dist/lib/dbmodels/user/UserStreaks.js.map +0 -1
  251. package/dist/lib/dbmodels/user/UsersFriends.js +0 -46
  252. package/dist/lib/dbmodels/user/UsersFriends.js.map +0 -1
  253. package/dist/lib/enums/ProgramEnums.d.ts +0 -18
  254. package/dist/lib/enums/ProgramEnums.d.ts.map +0 -1
  255. package/dist/lib/enums/ProgramEnums.js +0 -22
  256. package/dist/lib/enums/ProgramEnums.js.map +0 -1
  257. package/dist/lib/enums/ProgramTemplates.js +0 -738
  258. package/dist/lib/enums/ProgramTemplates.js.map +0 -1
  259. package/dist/lib/middlewares/ErrorMiddleware.js +0 -141
  260. package/dist/lib/middlewares/ErrorMiddleware.js.map +0 -1
  261. package/dist/lib/middlewares/ValidationMiddleware.js +0 -24
  262. package/dist/lib/middlewares/ValidationMiddleware.js.map +0 -1
  263. package/dist/lib/models/BlueprintInterfaces.js +0 -3
  264. package/dist/lib/models/BlueprintInterfaces.js.map +0 -1
  265. package/dist/lib/models/ExerciseInterfaces.d.ts +0 -68
  266. package/dist/lib/models/ExerciseInterfaces.d.ts.map +0 -1
  267. package/dist/lib/models/ExerciseInterfaces.js +0 -3
  268. package/dist/lib/models/ExerciseInterfaces.js.map +0 -1
  269. package/dist/lib/models/NotificationInterfaces.js +0 -11
  270. package/dist/lib/models/NotificationInterfaces.js.map +0 -1
  271. package/dist/lib/models/ProgramInterfaces.js +0 -3
  272. package/dist/lib/models/ProgramInterfaces.js.map +0 -1
  273. package/dist/lib/models/UserInterfaces.js +0 -3
  274. package/dist/lib/models/UserInterfaces.js.map +0 -1
  275. package/dist/lib/models/WorkoutInterfaces.js +0 -3
  276. package/dist/lib/models/WorkoutInterfaces.js.map +0 -1
  277. package/dist/lib/scripts/cli.js +0 -82
  278. package/dist/lib/scripts/cli.js.map +0 -1
  279. package/dist/lib/scripts/populate-exercise-thumbnails.js +0 -64
  280. package/dist/lib/scripts/populate-exercise-thumbnails.js.map +0 -1
  281. package/dist/lib/scripts/setup-database.js +0 -43
  282. package/dist/lib/scripts/setup-database.js.map +0 -1
  283. package/dist/lib/scripts/verify-indexes.js +0 -94
  284. package/dist/lib/scripts/verify-indexes.js.map +0 -1
  285. package/dist/lib/testing/testFixtures.js +0 -520
  286. package/dist/lib/testing/testFixtures.js.map +0 -1
  287. package/dist/lib/testing/testHelpers.js +0 -149
  288. package/dist/lib/testing/testHelpers.js.map +0 -1
  289. package/dist/lib/utils/AuthenticationUtil.js +0 -481
  290. package/dist/lib/utils/AuthenticationUtil.js.map +0 -1
  291. package/dist/lib/utils/Logger.js +0 -242
  292. package/dist/lib/utils/Logger.js.map +0 -1
  293. package/dist/lib/utils/NotificationClient.js +0 -371
  294. package/dist/lib/utils/NotificationClient.js.map +0 -1
  295. package/dist/lib/utils/NotificationsUtil.js +0 -95
  296. package/dist/lib/utils/NotificationsUtil.js.map +0 -1
  297. package/dist/lib/utils/SecretManager.js +0 -107
  298. package/dist/lib/utils/SecretManager.js.map +0 -1
  299. package/dist/lib/utils/SentryUtil.js +0 -140
  300. package/dist/lib/utils/SentryUtil.js.map +0 -1
  301. package/dist/lib/utils/imageValidation.js +0 -31
  302. package/dist/lib/utils/imageValidation.js.map +0 -1
@@ -1,478 +0,0 @@
1
- import apn from "apn";
2
- import { google } from "googleapis";
3
- import { CommonSchemas } from "../config/ConfigValidator.js";
4
- import { ExternalAPIError } from "../Errors/AppError.js";
5
- import { Log } from "../utils/Logger.js";
6
- import { DeviceTokens } from "../dbmodels/user/DeviceTokens.js";
7
- import { PersistedUser } from "../dbmodels/user/PersistedUser.js";
8
- import { NotificationModels } from "../dbmodels/notifications/NotificationModels.js";
9
- import { TranslatedNotification } from "../dbmodels/notifications/TranslatedNotification.js";
10
- export class PushNotificationClient {
11
- static instance;
12
- config;
13
- logger = Log.getInstance().extend("push-client");
14
- apnProvider = null;
15
- fcmAccessToken = null;
16
- fcmTokenExpiry = 0;
17
- constructor(config){
18
- this.config = config;
19
- }
20
- static getInstance() {
21
- if (!PushNotificationClient.instance) {
22
- const config = CommonSchemas.pushNotification.parse(process.env);
23
- PushNotificationClient.instance = new PushNotificationClient(config);
24
- }
25
- return PushNotificationClient.instance;
26
- }
27
- static resetInstance() {
28
- PushNotificationClient.instance?.shutdown();
29
- PushNotificationClient.instance = undefined;
30
- }
31
- shutdown() {
32
- if (this.apnProvider) {
33
- this.apnProvider.shutdown();
34
- this.apnProvider = null;
35
- }
36
- }
37
- getApnProvider() {
38
- if (!this.apnProvider) {
39
- // Validate required APNs configuration
40
- if (!this.config.APNS_PRIVATE_KEY || !this.config.APNS_KEY_ID || !this.config.APNS_TEAM_ID || !this.config.APNS_TOPIC) {
41
- throw new ExternalAPIError("APNs configuration missing", "APNS_PRIVATE_KEY, APNS_KEY_ID, APNS_TEAM_ID, and APNS_TOPIC are required for APNs");
42
- }
43
- this.logger.info("Initializing APNs provider", {
44
- production: this.config.APNS_PRODUCTION,
45
- topic: this.config.APNS_TOPIC
46
- });
47
- this.apnProvider = new apn.Provider({
48
- token: {
49
- key: this.config.APNS_PRIVATE_KEY,
50
- keyId: this.config.APNS_KEY_ID,
51
- teamId: this.config.APNS_TEAM_ID
52
- },
53
- production: this.config.APNS_PRODUCTION ?? false
54
- });
55
- }
56
- return this.apnProvider;
57
- }
58
- async sendAppleNotification(deviceTokens, notification) {
59
- const provider = this.getApnProvider();
60
- if (!this.config.APNS_TOPIC) {
61
- throw new ExternalAPIError("APNs configuration missing", "APNS_TOPIC is required");
62
- }
63
- const apnNotification = new apn.Notification();
64
- apnNotification.alert = {
65
- title: notification.title,
66
- body: notification.body
67
- };
68
- apnNotification.sound = notification.sound || "default";
69
- if (notification.badge !== undefined) {
70
- apnNotification.badge = notification.badge;
71
- }
72
- apnNotification.topic = this.config.APNS_TOPIC;
73
- apnNotification.payload = notification.data || {};
74
- if (notification.redirectPath) {
75
- apnNotification.urlArgs = [
76
- notification.redirectPath
77
- ];
78
- }
79
- this.logger.info("Sending APNs notification", {
80
- tokenCount: deviceTokens.length,
81
- title: notification.title
82
- });
83
- try {
84
- const result = await provider.send(apnNotification, deviceTokens);
85
- if (result.failed.length > 0) {
86
- this.logger.warn("Some APNs notifications failed", {
87
- failedCount: result.failed.length,
88
- failures: result.failed
89
- });
90
- }
91
- this.logger.info("APNs notification sent", {
92
- sent: result.sent.length,
93
- failed: result.failed.length
94
- });
95
- } catch (error) {
96
- this.logger.error("APNs send error", {
97
- error
98
- });
99
- throw new ExternalAPIError("Failed to send APNs notification", `Service: APNs, Error: ${String(error)}`);
100
- }
101
- }
102
- async getFcmAccessToken() {
103
- const now = Date.now();
104
- if (this.fcmAccessToken && this.fcmTokenExpiry > now) {
105
- return this.fcmAccessToken;
106
- }
107
- // Validate required FCM configuration
108
- if (!this.config.FCM_CLIENT_EMAIL || !this.config.FCM_PRIVATE_KEY) {
109
- throw new ExternalAPIError("FCM configuration missing", "FCM_CLIENT_EMAIL and FCM_PRIVATE_KEY are required for FCM");
110
- }
111
- this.logger.info("Fetching new FCM access token");
112
- const jwtClient = new google.auth.JWT({
113
- email: this.config.FCM_CLIENT_EMAIL,
114
- key: this.config.FCM_PRIVATE_KEY,
115
- scopes: [
116
- "https://www.googleapis.com/auth/firebase.messaging"
117
- ]
118
- });
119
- try {
120
- const tokens = await jwtClient.authorize();
121
- this.fcmAccessToken = tokens.access_token;
122
- this.fcmTokenExpiry = now + 55 * 60 * 1000;
123
- return this.fcmAccessToken;
124
- } catch (error) {
125
- this.logger.error("FCM token fetch error", {
126
- error
127
- });
128
- throw new ExternalAPIError("Failed to get FCM access token", `Service: FCM, Error: ${String(error)}`);
129
- }
130
- }
131
- async sendAndroidNotification(deviceTokens, notification) {
132
- const accessToken = await this.getFcmAccessToken();
133
- this.logger.info("Sending FCM notification", {
134
- tokenCount: deviceTokens.length,
135
- title: notification.title
136
- });
137
- const messages = deviceTokens.map((token)=>({
138
- message: {
139
- token,
140
- notification: {
141
- title: notification.title,
142
- body: notification.body
143
- },
144
- data: notification.data || {},
145
- android: {
146
- priority: "high",
147
- notification: {
148
- sound: notification.sound || "default",
149
- channelId: "default"
150
- }
151
- }
152
- }
153
- }));
154
- const results = await Promise.allSettled(messages.map(async (msg)=>{
155
- const response = await fetch(`https://fcm.googleapis.com/v1/projects/${this.config.FCM_PROJECT_ID}/messages:send`, {
156
- method: "POST",
157
- headers: {
158
- Authorization: `Bearer ${accessToken}`,
159
- "Content-Type": "application/json"
160
- },
161
- body: JSON.stringify(msg)
162
- });
163
- if (!response.ok) {
164
- const error = await response.text();
165
- throw new Error(`FCM error: ${error}`);
166
- }
167
- return response.json();
168
- }));
169
- const failed = results.filter((r)=>r.status === "rejected").length;
170
- const succeeded = results.filter((r)=>r.status === "fulfilled").length;
171
- if (failed > 0) {
172
- this.logger.warn("Some FCM notifications failed", {
173
- succeeded,
174
- failed
175
- });
176
- }
177
- this.logger.info("FCM notification sent", {
178
- succeeded,
179
- failed
180
- });
181
- }
182
- async sendToTokens(tokens, platform, notification) {
183
- if (tokens.length === 0) {
184
- this.logger.warn("No tokens provided, skipping notification");
185
- return;
186
- }
187
- if (platform === "ios") {
188
- await this.sendAppleNotification(tokens, notification);
189
- } else {
190
- await this.sendAndroidNotification(tokens, notification);
191
- }
192
- }
193
- async sendToUser(params) {
194
- this.logger.info("Sending notification to user", {
195
- userUuid: params.userUuid
196
- });
197
- const deviceTokens = await DeviceTokens.findAll({
198
- where: {
199
- userUuid: params.userUuid
200
- },
201
- attributes: [
202
- "deviceToken",
203
- "platform"
204
- ]
205
- });
206
- if (deviceTokens.length === 0) {
207
- this.logger.warn("No device tokens found for user", {
208
- userUuid: params.userUuid
209
- });
210
- return;
211
- }
212
- const iosTokens = deviceTokens.filter((dt)=>dt.platform === "ios").map((dt)=>dt.deviceToken);
213
- const androidTokens = deviceTokens.filter((dt)=>dt.platform === "android").map((dt)=>dt.deviceToken);
214
- await Promise.all([
215
- iosTokens.length > 0 ? this.sendToTokens(iosTokens, "ios", params.notification) : Promise.resolve(),
216
- androidTokens.length > 0 ? this.sendToTokens(androidTokens, "android", params.notification) : Promise.resolve()
217
- ]);
218
- }
219
- async sendToUsers(params) {
220
- this.logger.info("Sending notification to multiple users", {
221
- count: params.userUuids.length
222
- });
223
- const deviceTokens = await DeviceTokens.findAll({
224
- where: {
225
- userUuid: params.userUuids
226
- },
227
- attributes: [
228
- "deviceToken",
229
- "platform"
230
- ]
231
- });
232
- if (deviceTokens.length === 0) {
233
- this.logger.warn("No device tokens found for users");
234
- return;
235
- }
236
- const iosTokens = deviceTokens.filter((dt)=>dt.platform === "ios").map((dt)=>dt.deviceToken);
237
- const androidTokens = deviceTokens.filter((dt)=>dt.platform === "android").map((dt)=>dt.deviceToken);
238
- await Promise.all([
239
- iosTokens.length > 0 ? this.sendToTokens(iosTokens, "ios", params.notification) : Promise.resolve(),
240
- androidTokens.length > 0 ? this.sendToTokens(androidTokens, "android", params.notification) : Promise.resolve()
241
- ]);
242
- }
243
- calculateScheduledTime(targetHour, targetMinute, userTimezone) {
244
- const now = new Date();
245
- const targetTime = new Date(now.toLocaleString("en-US", {
246
- timeZone: userTimezone
247
- }));
248
- targetTime.setHours(targetHour, targetMinute, 0, 0);
249
- if (targetTime <= now) {
250
- targetTime.setDate(targetTime.getDate() + 1);
251
- }
252
- return targetTime;
253
- }
254
- async scheduleForUser(params) {
255
- this.logger.info("Scheduling notification for user", {
256
- userUuid: params.userUuid,
257
- targetHour: params.targetHour,
258
- targetMinute: params.targetMinute
259
- });
260
- const user = await PersistedUser.findByPk(params.userUuid, {
261
- attributes: [
262
- "userUuid",
263
- "timeZone"
264
- ]
265
- });
266
- if (!user) {
267
- throw new ExternalAPIError("User not found", `Service: PushNotificationClient, UserUuid: ${params.userUuid}`);
268
- }
269
- const scheduledAt = this.calculateScheduledTime(params.targetHour, params.targetMinute, user.timeZone || "UTC");
270
- this.logger.info("Notification scheduled", {
271
- userUuid: params.userUuid,
272
- scheduledAt: scheduledAt.toISOString()
273
- });
274
- return {
275
- scheduledAt
276
- };
277
- }
278
- async scheduleForUsers(params) {
279
- this.logger.info("Scheduling notifications for multiple users", {
280
- count: params.userUuids.length,
281
- targetHour: params.targetHour
282
- });
283
- const users = await PersistedUser.findAll({
284
- where: {
285
- userUuid: params.userUuids
286
- },
287
- attributes: [
288
- "userUuid",
289
- "timeZone"
290
- ]
291
- });
292
- return users.map((user)=>({
293
- userUuid: user.userUuid,
294
- scheduledAt: this.calculateScheduledTime(params.targetHour, params.targetMinute, user.timeZone || "UTC")
295
- }));
296
- }
297
- async sendTemplateToUser(params) {
298
- this.logger.info("Sending template notification to user", {
299
- userUuid: params.userUuid,
300
- notificationType: params.notificationType,
301
- language: params.language
302
- });
303
- const includeOptions = {
304
- model: TranslatedNotification,
305
- as: "translations",
306
- required: false
307
- };
308
- if (params.language) {
309
- includeOptions.where = {
310
- language: params.language
311
- };
312
- }
313
- const template = await NotificationModels.findOne({
314
- where: {
315
- type: params.notificationType
316
- },
317
- include: [
318
- includeOptions
319
- ]
320
- });
321
- if (!template) {
322
- throw new ExternalAPIError("Notification template not found", `Service: PushNotificationClient, Type: ${params.notificationType}`);
323
- }
324
- const translation = template.translations?.find((t)=>t.language === params.language);
325
- let text = translation?.text || template.text;
326
- if (params.data) {
327
- Object.entries(params.data).forEach(([key, value])=>{
328
- text = text.replace(new RegExp(`{{${key}}}`, "g"), value);
329
- });
330
- }
331
- await this.sendToUser({
332
- userUuid: params.userUuid,
333
- notification: {
334
- title: params.notificationType,
335
- body: text,
336
- ...params.data && {
337
- data: params.data
338
- }
339
- }
340
- });
341
- }
342
- async sendTemplateToUsers(params) {
343
- this.logger.info("Sending template notification to multiple users", {
344
- count: params.userUuids.length,
345
- notificationType: params.notificationType
346
- });
347
- const includeOptions = {
348
- model: TranslatedNotification,
349
- as: "translations",
350
- required: false
351
- };
352
- if (params.language) {
353
- includeOptions.where = {
354
- language: params.language
355
- };
356
- }
357
- const template = await NotificationModels.findOne({
358
- where: {
359
- type: params.notificationType
360
- },
361
- include: [
362
- includeOptions
363
- ]
364
- });
365
- if (!template) {
366
- throw new ExternalAPIError("Notification template not found", `Service: PushNotificationClient, Type: ${params.notificationType}`);
367
- }
368
- const translation = template.translations?.find((t)=>t.language === params.language);
369
- let text = translation?.text || template.text;
370
- if (params.data) {
371
- Object.entries(params.data).forEach(([key, value])=>{
372
- text = text.replace(new RegExp(`{{${key}}}`, "g"), value);
373
- });
374
- }
375
- await this.sendToUsers({
376
- userUuids: params.userUuids,
377
- notification: {
378
- title: params.notificationType,
379
- body: text,
380
- ...params.data && {
381
- data: params.data
382
- }
383
- }
384
- });
385
- }
386
- async sendToAllUsers(params) {
387
- const batchSize = params.batchSize || 1000;
388
- let offset = 0;
389
- let totalSent = 0;
390
- this.logger.info("Starting broadcast notification", {
391
- batchSize
392
- });
393
- while(true){
394
- const deviceTokens = await DeviceTokens.findAll({
395
- limit: batchSize,
396
- offset,
397
- attributes: [
398
- "deviceToken",
399
- "platform"
400
- ]
401
- });
402
- if (deviceTokens.length === 0) {
403
- break;
404
- }
405
- const iosTokens = deviceTokens.filter((dt)=>dt.platform === "ios").map((dt)=>dt.deviceToken);
406
- const androidTokens = deviceTokens.filter((dt)=>dt.platform === "android").map((dt)=>dt.deviceToken);
407
- await Promise.all([
408
- iosTokens.length > 0 ? this.sendToTokens(iosTokens, "ios", params.notification) : Promise.resolve(),
409
- androidTokens.length > 0 ? this.sendToTokens(androidTokens, "android", params.notification) : Promise.resolve()
410
- ]);
411
- totalSent += deviceTokens.length;
412
- offset += batchSize;
413
- this.logger.info("Broadcast batch sent", {
414
- batchSent: deviceTokens.length,
415
- totalSent
416
- });
417
- }
418
- this.logger.info("Broadcast notification complete", {
419
- totalSent
420
- });
421
- return {
422
- totalSent
423
- };
424
- }
425
- async sendToGroup(params) {
426
- const batchSize = params.batchSize || 1000;
427
- let offset = 0;
428
- let totalSent = 0;
429
- this.logger.info("Starting group notification", {
430
- group: params.group,
431
- batchSize
432
- });
433
- while(true){
434
- const users = await PersistedUser.findAll({
435
- where: {
436
- subscriptionType: params.group
437
- },
438
- include: [
439
- {
440
- model: DeviceTokens,
441
- as: "deviceTokens",
442
- attributes: [
443
- "deviceToken",
444
- "platform"
445
- ]
446
- }
447
- ],
448
- limit: batchSize,
449
- offset
450
- });
451
- if (users.length === 0) {
452
- break;
453
- }
454
- const allTokens = users.flatMap((user)=>user.deviceTokens || []);
455
- const iosTokens = allTokens.filter((dt)=>dt.platform === "ios").map((dt)=>dt.deviceToken);
456
- const androidTokens = allTokens.filter((dt)=>dt.platform === "android").map((dt)=>dt.deviceToken);
457
- await Promise.all([
458
- iosTokens.length > 0 ? this.sendToTokens(iosTokens, "ios", params.notification) : Promise.resolve(),
459
- androidTokens.length > 0 ? this.sendToTokens(androidTokens, "android", params.notification) : Promise.resolve()
460
- ]);
461
- totalSent += allTokens.length;
462
- offset += batchSize;
463
- this.logger.info("Group batch sent", {
464
- batchSent: allTokens.length,
465
- totalSent
466
- });
467
- }
468
- this.logger.info("Group notification complete", {
469
- totalSent,
470
- group: params.group
471
- });
472
- return {
473
- totalSent
474
- };
475
- }
476
- }
477
-
478
- //# sourceMappingURL=PushNotificationClient.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/lib/clients/PushNotificationClient.ts"],"sourcesContent":["import apn from \"apn\";\nimport { google } from \"googleapis\";\nimport { z } from \"zod\";\nimport { CommonSchemas } from \"../config/ConfigValidator.js\";\nimport { ExternalAPIError } from \"../Errors/AppError.js\";\nimport { Log } from \"../utils/Logger.js\";\nimport { DeviceTokens } from \"../dbmodels/user/DeviceTokens.js\";\nimport { PersistedUser } from \"../dbmodels/user/PersistedUser.js\";\nimport { NotificationModels } from \"../dbmodels/notifications/NotificationModels.js\";\nimport { TranslatedNotification } from \"../dbmodels/notifications/TranslatedNotification.js\";\n\ntype PushNotificationConfig = z.infer<typeof CommonSchemas.pushNotification>;\n\nexport interface NotificationPayload {\n title: string;\n body: string;\n sound?: string;\n badge?: number;\n data?: Record<string, string>;\n redirectPath?: string;\n}\n\nexport class PushNotificationClient {\n private static instance: PushNotificationClient;\n private config: PushNotificationConfig;\n private logger = Log.getInstance().extend(\"push-client\");\n\n private apnProvider: apn.Provider | null = null;\n private fcmAccessToken: string | null = null;\n private fcmTokenExpiry: number = 0;\n\n private constructor(config: PushNotificationConfig) {\n this.config = config;\n }\n\n public static getInstance(): PushNotificationClient {\n if (!PushNotificationClient.instance) {\n const config = CommonSchemas.pushNotification.parse(process.env);\n PushNotificationClient.instance = new PushNotificationClient(config);\n }\n return PushNotificationClient.instance;\n }\n\n public static resetInstance(): void {\n PushNotificationClient.instance?.shutdown();\n PushNotificationClient.instance = undefined as any;\n }\n\n public shutdown(): void {\n if (this.apnProvider) {\n this.apnProvider.shutdown();\n this.apnProvider = null;\n }\n }\n\n private getApnProvider(): apn.Provider {\n if (!this.apnProvider) {\n // Validate required APNs configuration\n if (!this.config.APNS_PRIVATE_KEY || !this.config.APNS_KEY_ID || !this.config.APNS_TEAM_ID || !this.config.APNS_TOPIC) {\n throw new ExternalAPIError(\n \"APNs configuration missing\",\n \"APNS_PRIVATE_KEY, APNS_KEY_ID, APNS_TEAM_ID, and APNS_TOPIC are required for APNs\"\n );\n }\n\n this.logger.info(\"Initializing APNs provider\", {\n production: this.config.APNS_PRODUCTION,\n topic: this.config.APNS_TOPIC,\n });\n\n this.apnProvider = new apn.Provider({\n token: {\n key: this.config.APNS_PRIVATE_KEY,\n keyId: this.config.APNS_KEY_ID,\n teamId: this.config.APNS_TEAM_ID,\n },\n production: this.config.APNS_PRODUCTION ?? false,\n });\n }\n return this.apnProvider;\n }\n\n private async sendAppleNotification(deviceTokens: string[], notification: NotificationPayload): Promise<void> {\n const provider = this.getApnProvider();\n\n if (!this.config.APNS_TOPIC) {\n throw new ExternalAPIError(\"APNs configuration missing\", \"APNS_TOPIC is required\");\n }\n\n const apnNotification = new apn.Notification();\n apnNotification.alert = {\n title: notification.title,\n body: notification.body,\n };\n apnNotification.sound = notification.sound || \"default\";\n if (notification.badge !== undefined) {\n apnNotification.badge = notification.badge;\n }\n apnNotification.topic = this.config.APNS_TOPIC;\n apnNotification.payload = notification.data || {};\n\n if (notification.redirectPath) {\n apnNotification.urlArgs = [notification.redirectPath];\n }\n\n this.logger.info(\"Sending APNs notification\", {\n tokenCount: deviceTokens.length,\n title: notification.title,\n });\n\n try {\n const result = await provider.send(apnNotification, deviceTokens);\n\n if (result.failed.length > 0) {\n this.logger.warn(\"Some APNs notifications failed\", {\n failedCount: result.failed.length,\n failures: result.failed,\n });\n }\n\n this.logger.info(\"APNs notification sent\", {\n sent: result.sent.length,\n failed: result.failed.length,\n });\n } catch (error) {\n this.logger.error(\"APNs send error\", { error });\n throw new ExternalAPIError(\n \"Failed to send APNs notification\",\n `Service: APNs, Error: ${String(error)}`\n );\n }\n }\n\n private async getFcmAccessToken(): Promise<string> {\n const now = Date.now();\n\n if (this.fcmAccessToken && this.fcmTokenExpiry > now) {\n return this.fcmAccessToken;\n }\n\n // Validate required FCM configuration\n if (!this.config.FCM_CLIENT_EMAIL || !this.config.FCM_PRIVATE_KEY) {\n throw new ExternalAPIError(\n \"FCM configuration missing\",\n \"FCM_CLIENT_EMAIL and FCM_PRIVATE_KEY are required for FCM\"\n );\n }\n\n this.logger.info(\"Fetching new FCM access token\");\n\n const jwtClient = new google.auth.JWT({\n email: this.config.FCM_CLIENT_EMAIL,\n key: this.config.FCM_PRIVATE_KEY,\n scopes: [\"https://www.googleapis.com/auth/firebase.messaging\"],\n });\n\n try {\n const tokens = await jwtClient.authorize();\n this.fcmAccessToken = tokens.access_token!;\n this.fcmTokenExpiry = now + 55 * 60 * 1000;\n\n return this.fcmAccessToken;\n } catch (error) {\n this.logger.error(\"FCM token fetch error\", { error });\n throw new ExternalAPIError(\n \"Failed to get FCM access token\",\n `Service: FCM, Error: ${String(error)}`\n );\n }\n }\n\n private async sendAndroidNotification(deviceTokens: string[], notification: NotificationPayload): Promise<void> {\n const accessToken = await this.getFcmAccessToken();\n\n this.logger.info(\"Sending FCM notification\", {\n tokenCount: deviceTokens.length,\n title: notification.title,\n });\n\n const messages = deviceTokens.map((token) => ({\n message: {\n token,\n notification: {\n title: notification.title,\n body: notification.body,\n },\n data: notification.data || {},\n android: {\n priority: \"high\" as const,\n notification: {\n sound: notification.sound || \"default\",\n channelId: \"default\",\n },\n },\n },\n }));\n\n const results = await Promise.allSettled(\n messages.map(async (msg) => {\n const response = await fetch(\n `https://fcm.googleapis.com/v1/projects/${this.config.FCM_PROJECT_ID}/messages:send`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(msg),\n }\n );\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`FCM error: ${error}`);\n }\n\n return response.json();\n })\n );\n\n const failed = results.filter((r) => r.status === \"rejected\").length;\n const succeeded = results.filter((r) => r.status === \"fulfilled\").length;\n\n if (failed > 0) {\n this.logger.warn(\"Some FCM notifications failed\", {\n succeeded,\n failed,\n });\n }\n\n this.logger.info(\"FCM notification sent\", { succeeded, failed });\n }\n\n public async sendToTokens(tokens: string[], platform: \"ios\" | \"android\", notification: NotificationPayload): Promise<void> {\n if (tokens.length === 0) {\n this.logger.warn(\"No tokens provided, skipping notification\");\n return;\n }\n\n if (platform === \"ios\") {\n await this.sendAppleNotification(tokens, notification);\n } else {\n await this.sendAndroidNotification(tokens, notification);\n }\n }\n\n public async sendToUser(params: { userUuid: string; notification: NotificationPayload }): Promise<void> {\n this.logger.info(\"Sending notification to user\", { userUuid: params.userUuid });\n\n const deviceTokens = await DeviceTokens.findAll({\n where: { userUuid: params.userUuid },\n attributes: [\"deviceToken\", \"platform\"],\n });\n\n if (deviceTokens.length === 0) {\n this.logger.warn(\"No device tokens found for user\", { userUuid: params.userUuid });\n return;\n }\n\n const iosTokens = deviceTokens.filter((dt) => dt.platform === \"ios\").map((dt) => dt.deviceToken);\n const androidTokens = deviceTokens.filter((dt) => dt.platform === \"android\").map((dt) => dt.deviceToken);\n\n await Promise.all([\n iosTokens.length > 0 ? this.sendToTokens(iosTokens, \"ios\", params.notification) : Promise.resolve(),\n androidTokens.length > 0 ? this.sendToTokens(androidTokens, \"android\", params.notification) : Promise.resolve(),\n ]);\n }\n\n public async sendToUsers(params: { userUuids: string[]; notification: NotificationPayload }): Promise<void> {\n this.logger.info(\"Sending notification to multiple users\", { count: params.userUuids.length });\n\n const deviceTokens = await DeviceTokens.findAll({\n where: { userUuid: params.userUuids },\n attributes: [\"deviceToken\", \"platform\"],\n });\n\n if (deviceTokens.length === 0) {\n this.logger.warn(\"No device tokens found for users\");\n return;\n }\n\n const iosTokens = deviceTokens.filter((dt) => dt.platform === \"ios\").map((dt) => dt.deviceToken);\n const androidTokens = deviceTokens.filter((dt) => dt.platform === \"android\").map((dt) => dt.deviceToken);\n\n await Promise.all([\n iosTokens.length > 0 ? this.sendToTokens(iosTokens, \"ios\", params.notification) : Promise.resolve(),\n androidTokens.length > 0 ? this.sendToTokens(androidTokens, \"android\", params.notification) : Promise.resolve(),\n ]);\n }\n\n private calculateScheduledTime(targetHour: number, targetMinute: number, userTimezone: string): Date {\n const now = new Date();\n const targetTime = new Date(now.toLocaleString(\"en-US\", { timeZone: userTimezone }));\n\n targetTime.setHours(targetHour, targetMinute, 0, 0);\n\n if (targetTime <= now) {\n targetTime.setDate(targetTime.getDate() + 1);\n }\n\n return targetTime;\n }\n\n public async scheduleForUser(params: {\n userUuid: string;\n notification: NotificationPayload;\n targetHour: number;\n targetMinute: number;\n }): Promise<{ scheduledAt: Date }> {\n this.logger.info(\"Scheduling notification for user\", {\n userUuid: params.userUuid,\n targetHour: params.targetHour,\n targetMinute: params.targetMinute,\n });\n\n const user = await PersistedUser.findByPk(params.userUuid, {\n attributes: [\"userUuid\", \"timeZone\"],\n });\n\n if (!user) {\n throw new ExternalAPIError(\n \"User not found\",\n `Service: PushNotificationClient, UserUuid: ${params.userUuid}`\n );\n }\n\n const scheduledAt = this.calculateScheduledTime(\n params.targetHour,\n params.targetMinute,\n (user as any).timeZone || \"UTC\"\n );\n\n this.logger.info(\"Notification scheduled\", {\n userUuid: params.userUuid,\n scheduledAt: scheduledAt.toISOString(),\n });\n\n return { scheduledAt };\n }\n\n public async scheduleForUsers(params: {\n userUuids: string[];\n notification: NotificationPayload;\n targetHour: number;\n targetMinute: number;\n }): Promise<Array<{ userUuid: string; scheduledAt: Date }>> {\n this.logger.info(\"Scheduling notifications for multiple users\", {\n count: params.userUuids.length,\n targetHour: params.targetHour,\n });\n\n const users = await PersistedUser.findAll({\n where: { userUuid: params.userUuids },\n attributes: [\"userUuid\", \"timeZone\"],\n });\n\n return users.map((user) => ({\n userUuid: user.userUuid,\n scheduledAt: this.calculateScheduledTime(params.targetHour, params.targetMinute, (user as any).timeZone || \"UTC\"),\n }));\n }\n\n public async sendTemplateToUser(params: {\n userUuid: string;\n notificationType: string;\n language?: string;\n data?: Record<string, string>;\n }): Promise<void> {\n this.logger.info(\"Sending template notification to user\", {\n userUuid: params.userUuid,\n notificationType: params.notificationType,\n language: params.language,\n });\n\n const includeOptions: any = {\n model: TranslatedNotification,\n as: \"translations\",\n required: false,\n };\n\n if (params.language) {\n includeOptions.where = { language: params.language };\n }\n\n const template = await NotificationModels.findOne({\n where: { type: params.notificationType as any },\n include: [includeOptions],\n });\n\n if (!template) {\n throw new ExternalAPIError(\n \"Notification template not found\",\n `Service: PushNotificationClient, Type: ${params.notificationType}`\n );\n }\n\n const translation = template.translations?.find((t) => t.language === params.language);\n let text = translation?.text || template.text;\n\n if (params.data) {\n Object.entries(params.data).forEach(([key, value]) => {\n text = text.replace(new RegExp(`{{${key}}}`, \"g\"), value);\n });\n }\n\n await this.sendToUser({\n userUuid: params.userUuid,\n notification: {\n title: params.notificationType,\n body: text,\n ...(params.data && { data: params.data }),\n },\n });\n }\n\n public async sendTemplateToUsers(params: {\n userUuids: string[];\n notificationType: string;\n language?: string;\n data?: Record<string, string>;\n }): Promise<void> {\n this.logger.info(\"Sending template notification to multiple users\", {\n count: params.userUuids.length,\n notificationType: params.notificationType,\n });\n\n const includeOptions: any = {\n model: TranslatedNotification,\n as: \"translations\",\n required: false,\n };\n\n if (params.language) {\n includeOptions.where = { language: params.language };\n }\n\n const template = await NotificationModels.findOne({\n where: { type: params.notificationType as any },\n include: [includeOptions],\n });\n\n if (!template) {\n throw new ExternalAPIError(\n \"Notification template not found\",\n `Service: PushNotificationClient, Type: ${params.notificationType}`\n );\n }\n\n const translation = template.translations?.find((t) => t.language === params.language);\n let text = translation?.text || template.text;\n\n if (params.data) {\n Object.entries(params.data).forEach(([key, value]) => {\n text = text.replace(new RegExp(`{{${key}}}`, \"g\"), value);\n });\n }\n\n await this.sendToUsers({\n userUuids: params.userUuids,\n notification: {\n title: params.notificationType,\n body: text,\n ...(params.data && { data: params.data }),\n },\n });\n }\n\n public async sendToAllUsers(params: { notification: NotificationPayload; batchSize?: number }): Promise<{ totalSent: number }> {\n const batchSize = params.batchSize || 1000;\n let offset = 0;\n let totalSent = 0;\n\n this.logger.info(\"Starting broadcast notification\", {\n batchSize,\n });\n\n while (true) {\n const deviceTokens = await DeviceTokens.findAll({\n limit: batchSize,\n offset,\n attributes: [\"deviceToken\", \"platform\"],\n });\n\n if (deviceTokens.length === 0) {\n break;\n }\n\n const iosTokens = deviceTokens.filter((dt) => dt.platform === \"ios\").map((dt) => dt.deviceToken);\n const androidTokens = deviceTokens.filter((dt) => dt.platform === \"android\").map((dt) => dt.deviceToken);\n\n await Promise.all([\n iosTokens.length > 0 ? this.sendToTokens(iosTokens, \"ios\", params.notification) : Promise.resolve(),\n androidTokens.length > 0 ? this.sendToTokens(androidTokens, \"android\", params.notification) : Promise.resolve(),\n ]);\n\n totalSent += deviceTokens.length;\n offset += batchSize;\n\n this.logger.info(\"Broadcast batch sent\", {\n batchSent: deviceTokens.length,\n totalSent,\n });\n }\n\n this.logger.info(\"Broadcast notification complete\", { totalSent });\n return { totalSent };\n }\n\n public async sendToGroup(params: {\n notification: NotificationPayload;\n group: \"premium\" | \"free\" | \"trial\";\n batchSize?: number;\n }): Promise<{ totalSent: number }> {\n const batchSize = params.batchSize || 1000;\n let offset = 0;\n let totalSent = 0;\n\n this.logger.info(\"Starting group notification\", {\n group: params.group,\n batchSize,\n });\n\n while (true) {\n const users = await PersistedUser.findAll({\n where: { subscriptionType: params.group } as any,\n include: [\n {\n model: DeviceTokens,\n as: \"deviceTokens\",\n attributes: [\"deviceToken\", \"platform\"],\n },\n ],\n limit: batchSize,\n offset,\n });\n\n if (users.length === 0) {\n break;\n }\n\n const allTokens = users.flatMap((user) => (user as any).deviceTokens || []);\n const iosTokens = allTokens.filter((dt: any) => dt.platform === \"ios\").map((dt: any) => dt.deviceToken);\n const androidTokens = allTokens.filter((dt: any) => dt.platform === \"android\").map((dt: any) => dt.deviceToken);\n\n await Promise.all([\n iosTokens.length > 0 ? this.sendToTokens(iosTokens, \"ios\", params.notification) : Promise.resolve(),\n androidTokens.length > 0 ? this.sendToTokens(androidTokens, \"android\", params.notification) : Promise.resolve(),\n ]);\n\n totalSent += allTokens.length;\n offset += batchSize;\n\n this.logger.info(\"Group batch sent\", {\n batchSent: allTokens.length,\n totalSent,\n });\n }\n\n this.logger.info(\"Group notification complete\", { totalSent, group: params.group });\n return { totalSent };\n }\n}\n"],"names":["apn","google","CommonSchemas","ExternalAPIError","Log","DeviceTokens","PersistedUser","NotificationModels","TranslatedNotification","PushNotificationClient","instance","config","logger","getInstance","extend","apnProvider","fcmAccessToken","fcmTokenExpiry","pushNotification","parse","process","env","resetInstance","shutdown","undefined","getApnProvider","APNS_PRIVATE_KEY","APNS_KEY_ID","APNS_TEAM_ID","APNS_TOPIC","info","production","APNS_PRODUCTION","topic","Provider","token","key","keyId","teamId","sendAppleNotification","deviceTokens","notification","provider","apnNotification","Notification","alert","title","body","sound","badge","payload","data","redirectPath","urlArgs","tokenCount","length","result","send","failed","warn","failedCount","failures","sent","error","String","getFcmAccessToken","now","Date","FCM_CLIENT_EMAIL","FCM_PRIVATE_KEY","jwtClient","auth","JWT","email","scopes","tokens","authorize","access_token","sendAndroidNotification","accessToken","messages","map","message","android","priority","channelId","results","Promise","allSettled","msg","response","fetch","FCM_PROJECT_ID","method","headers","Authorization","JSON","stringify","ok","text","Error","json","filter","r","status","succeeded","sendToTokens","platform","sendToUser","params","userUuid","findAll","where","attributes","iosTokens","dt","deviceToken","androidTokens","all","resolve","sendToUsers","count","userUuids","calculateScheduledTime","targetHour","targetMinute","userTimezone","targetTime","toLocaleString","timeZone","setHours","setDate","getDate","scheduleForUser","user","findByPk","scheduledAt","toISOString","scheduleForUsers","users","sendTemplateToUser","notificationType","language","includeOptions","model","as","required","template","findOne","type","include","translation","translations","find","t","Object","entries","forEach","value","replace","RegExp","sendTemplateToUsers","sendToAllUsers","batchSize","offset","totalSent","limit","batchSent","sendToGroup","group","subscriptionType","allTokens","flatMap"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- export { };
2
-
3
- //# sourceMappingURL=email.types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/lib/clients/types/email.types.ts"],"sourcesContent":["import type { z } from \"zod\";\nimport type { CommonSchemas } from \"../../config/ConfigValidator.js\";\n\nexport type Config = z.infer<typeof CommonSchemas.postmark>;\n\nexport interface SendTemplateEmailRequest {\n to: string | string[];\n templateAlias: string | number;\n templateModel: Record<string, any>;\n cc?: string | string[];\n bcc?: string | string[];\n replyTo?: string;\n tag?: string;\n metadata?: Record<string, string>;\n trackOpens?: boolean;\n trackLinks?: \"None\" | \"HtmlAndText\" | \"HtmlOnly\" | \"TextOnly\";\n}\n\nexport interface BatchTemplateEmailRequest {\n emails: Array<{\n to: string;\n templateAlias: string | number;\n templateModel: Record<string, any>;\n tag?: string;\n metadata?: Record<string, string>;\n }>;\n}\n\nexport interface SendEmailRequest {\n to: string;\n subject: string;\n textBody: string;\n htmlBody?: string;\n tag?: string;\n metadata?: Record<string, string>;\n replyTo?: string;\n}\n\nexport interface EmailResponse {\n messageId: string;\n to: string;\n submittedAt: string;\n errorCode?: number;\n message?: string;\n}\n"],"names":[],"mappings":"AAsCA,WAMC"}
@@ -1,3 +0,0 @@
1
- export { };
2
-
3
- //# sourceMappingURL=images.types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/lib/clients/types/images.types.ts"],"sourcesContent":["import type admin from \"firebase-admin\";\n\nexport interface Config {\n storageBucket: string;\n firebaseApp?: admin.app.App;\n}\n\nexport interface ProgressPhoto {\n day: number;\n base64: string;\n}\n\nexport interface RecipePhotos {\n ingredientBase64: string;\n coverBase64: string;\n methodBase64: string;\n}\n\nexport interface SaveRecipePhotosInput {\n recipeUuid: string;\n ingredientBase64: string;\n coverBase64: string;\n methodBase64: string;\n}\n\nexport interface UserProgressPhotoInput {\n userUuid: string;\n base64: string;\n photoDate?: Date; // Optional, defaults to now\n programId?: string; // Optional, for legacy program association\n}\n\nexport interface UserProgressPhotoRecord {\n uuid: string;\n userUuid: string;\n firebasePath: string;\n photoDate: Date;\n programId: string | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface UpdateProgressPhotoDateInput {\n uuid: string;\n userUuid: string;\n photoDate: Date;\n}\n"],"names":[],"mappings":"AA0CA,WAIC"}
@@ -1,3 +0,0 @@
1
- export { };
2
-
3
- //# sourceMappingURL=mailing.types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/lib/clients/types/mailing.types.ts"],"sourcesContent":["import type { EmailClient } from \"../EmailClient.js\";\n\nexport interface Config {\n emailClient: EmailClient;\n receiverEmail: string;\n}\n\nexport interface ShopifyEmailInput {\n email: string;\n password: string;\n}\n"],"names":[],"mappings":"AAOA,WAGC"}