@open-mercato/core 0.4.5-develop-754ef4d2f0 → 0.4.5-develop-9f9549ebc8

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 (434) hide show
  1. package/dist/generated/entities/message/index.js +65 -0
  2. package/dist/generated/entities/message/index.js.map +7 -0
  3. package/dist/generated/entities/message_access_token/index.js +19 -0
  4. package/dist/generated/entities/message_access_token/index.js.map +7 -0
  5. package/dist/generated/entities/message_confirmation/index.js +21 -0
  6. package/dist/generated/entities/message_confirmation/index.js.map +7 -0
  7. package/dist/generated/entities/message_object/index.js +23 -0
  8. package/dist/generated/entities/message_object/index.js.map +7 -0
  9. package/dist/generated/entities/message_recipient/index.js +31 -0
  10. package/dist/generated/entities/message_recipient/index.js.map +7 -0
  11. package/dist/generated/entities.ids.generated.js +8 -0
  12. package/dist/generated/entities.ids.generated.js.map +2 -2
  13. package/dist/generated/entity-fields-registry.js +10 -0
  14. package/dist/generated/entity-fields-registry.js.map +2 -2
  15. package/dist/modules/auth/components/AclEditor.js +4 -2
  16. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  17. package/dist/modules/auth/frontend/reset.js +3 -3
  18. package/dist/modules/auth/frontend/reset.js.map +2 -2
  19. package/dist/modules/customers/backend/customers/deals/[id]/page.js +27 -8
  20. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  21. package/dist/modules/customers/lib/messageObjectPreviews.js +131 -0
  22. package/dist/modules/customers/lib/messageObjectPreviews.js.map +7 -0
  23. package/dist/modules/customers/message-objects.js +71 -0
  24. package/dist/modules/customers/message-objects.js.map +7 -0
  25. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js +51 -0
  26. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js.map +7 -0
  27. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js +35 -0
  28. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js.map +7 -0
  29. package/dist/modules/customers/widgets/messages/index.js +7 -0
  30. package/dist/modules/customers/widgets/messages/index.js.map +7 -0
  31. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +35 -6
  32. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  33. package/dist/modules/messages/acl.js +15 -0
  34. package/dist/modules/messages/acl.js.map +7 -0
  35. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js +92 -0
  36. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js.map +7 -0
  37. package/dist/modules/messages/api/[id]/archive/route.js +120 -0
  38. package/dist/modules/messages/api/[id]/archive/route.js.map +7 -0
  39. package/dist/modules/messages/api/[id]/attachments/route.js +195 -0
  40. package/dist/modules/messages/api/[id]/attachments/route.js.map +7 -0
  41. package/dist/modules/messages/api/[id]/confirmation/route.js +67 -0
  42. package/dist/modules/messages/api/[id]/confirmation/route.js.map +7 -0
  43. package/dist/modules/messages/api/[id]/conversation/archive/route.js +68 -0
  44. package/dist/modules/messages/api/[id]/conversation/archive/route.js.map +7 -0
  45. package/dist/modules/messages/api/[id]/conversation/read/route.js +68 -0
  46. package/dist/modules/messages/api/[id]/conversation/read/route.js.map +7 -0
  47. package/dist/modules/messages/api/[id]/conversation/route.js +68 -0
  48. package/dist/modules/messages/api/[id]/conversation/route.js.map +7 -0
  49. package/dist/modules/messages/api/[id]/forward/route.js +85 -0
  50. package/dist/modules/messages/api/[id]/forward/route.js.map +7 -0
  51. package/dist/modules/messages/api/[id]/forward-preview/route.js +70 -0
  52. package/dist/modules/messages/api/[id]/forward-preview/route.js.map +7 -0
  53. package/dist/modules/messages/api/[id]/read/route.js +120 -0
  54. package/dist/modules/messages/api/[id]/read/route.js.map +7 -0
  55. package/dist/modules/messages/api/[id]/reply/route.js +87 -0
  56. package/dist/modules/messages/api/[id]/reply/route.js.map +7 -0
  57. package/dist/modules/messages/api/[id]/route.js +350 -0
  58. package/dist/modules/messages/api/[id]/route.js.map +7 -0
  59. package/dist/modules/messages/api/object-types/route.js +54 -0
  60. package/dist/modules/messages/api/object-types/route.js.map +7 -0
  61. package/dist/modules/messages/api/openapi.js +261 -0
  62. package/dist/modules/messages/api/openapi.js.map +7 -0
  63. package/dist/modules/messages/api/route.js +262 -0
  64. package/dist/modules/messages/api/route.js.map +7 -0
  65. package/dist/modules/messages/api/token/[token]/route.js +99 -0
  66. package/dist/modules/messages/api/token/[token]/route.js.map +7 -0
  67. package/dist/modules/messages/api/types/route.js +40 -0
  68. package/dist/modules/messages/api/types/route.js.map +7 -0
  69. package/dist/modules/messages/api/unread-count/route.js +43 -0
  70. package/dist/modules/messages/api/unread-count/route.js.map +7 -0
  71. package/dist/modules/messages/backend/messages/[id]/page.js +10 -0
  72. package/dist/modules/messages/backend/messages/[id]/page.js.map +7 -0
  73. package/dist/modules/messages/backend/messages/[id]/page.meta.js +16 -0
  74. package/dist/modules/messages/backend/messages/[id]/page.meta.js.map +7 -0
  75. package/dist/modules/messages/backend/messages/compose/page.js +10 -0
  76. package/dist/modules/messages/backend/messages/compose/page.js.map +7 -0
  77. package/dist/modules/messages/backend/messages/compose/page.meta.js +17 -0
  78. package/dist/modules/messages/backend/messages/compose/page.meta.js.map +7 -0
  79. package/dist/modules/messages/backend/page.js +10 -0
  80. package/dist/modules/messages/backend/page.js.map +7 -0
  81. package/dist/modules/messages/backend/page.meta.js +33 -0
  82. package/dist/modules/messages/backend/page.meta.js.map +7 -0
  83. package/dist/modules/messages/commands/actions.js +265 -0
  84. package/dist/modules/messages/commands/actions.js.map +7 -0
  85. package/dist/modules/messages/commands/attachments.js +217 -0
  86. package/dist/modules/messages/commands/attachments.js.map +7 -0
  87. package/dist/modules/messages/commands/confirmations.js +151 -0
  88. package/dist/modules/messages/commands/confirmations.js.map +7 -0
  89. package/dist/modules/messages/commands/conversation.js +240 -0
  90. package/dist/modules/messages/commands/conversation.js.map +7 -0
  91. package/dist/modules/messages/commands/messages.js +748 -0
  92. package/dist/modules/messages/commands/messages.js.map +7 -0
  93. package/dist/modules/messages/commands/recipients.js +259 -0
  94. package/dist/modules/messages/commands/recipients.js.map +7 -0
  95. package/dist/modules/messages/commands/shared.js +258 -0
  96. package/dist/modules/messages/commands/shared.js.map +7 -0
  97. package/dist/modules/messages/commands/tokens.js +69 -0
  98. package/dist/modules/messages/commands/tokens.js.map +7 -0
  99. package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -0
  100. package/dist/modules/messages/components/ComposeMessagePageClient.js.map +7 -0
  101. package/dist/modules/messages/components/MessageDetailPageClient.js +261 -0
  102. package/dist/modules/messages/components/MessageDetailPageClient.js.map +7 -0
  103. package/dist/modules/messages/components/MessagesInboxPageClient.js +390 -0
  104. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +7 -0
  105. package/dist/modules/messages/components/confirmation/MessageConfirmationActions.js +31 -0
  106. package/dist/modules/messages/components/confirmation/MessageConfirmationActions.js.map +7 -0
  107. package/dist/modules/messages/components/confirmation/MessageConfirmationContent.js +69 -0
  108. package/dist/modules/messages/components/confirmation/MessageConfirmationContent.js.map +7 -0
  109. package/dist/modules/messages/components/defaults/DefaultMessageActions.js +31 -0
  110. package/dist/modules/messages/components/defaults/DefaultMessageActions.js.map +7 -0
  111. package/dist/modules/messages/components/defaults/DefaultMessageContent.js +19 -0
  112. package/dist/modules/messages/components/defaults/DefaultMessageContent.js.map +7 -0
  113. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js +90 -0
  114. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js.map +7 -0
  115. package/dist/modules/messages/components/defaults/MessageRecordObjectDetail.js +86 -0
  116. package/dist/modules/messages/components/defaults/MessageRecordObjectDetail.js.map +7 -0
  117. package/dist/modules/messages/components/defaults/MessageRecordObjectPreview.js +61 -0
  118. package/dist/modules/messages/components/defaults/MessageRecordObjectPreview.js.map +7 -0
  119. package/dist/modules/messages/components/message-detail/detail-panels.js +27 -0
  120. package/dist/modules/messages/components/message-detail/detail-panels.js.map +7 -0
  121. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js +52 -0
  122. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js.map +7 -0
  123. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js +289 -0
  124. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js.map +7 -0
  125. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js +103 -0
  126. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js.map +7 -0
  127. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js +78 -0
  128. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js.map +7 -0
  129. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js +94 -0
  130. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js.map +7 -0
  131. package/dist/modules/messages/components/message-detail/panels/MessageHeader.js +110 -0
  132. package/dist/modules/messages/components/message-detail/panels/MessageHeader.js.map +7 -0
  133. package/dist/modules/messages/components/message-detail/panels/MessageListComponent.js +58 -0
  134. package/dist/modules/messages/components/message-detail/panels/MessageListComponent.js.map +7 -0
  135. package/dist/modules/messages/components/message-detail/panels/actions-panel.js +51 -0
  136. package/dist/modules/messages/components/message-detail/panels/actions-panel.js.map +7 -0
  137. package/dist/modules/messages/components/message-detail/panels/attachments-panel.js +66 -0
  138. package/dist/modules/messages/components/message-detail/panels/attachments-panel.js.map +7 -0
  139. package/dist/modules/messages/components/message-detail/panels/body-panel.js +20 -0
  140. package/dist/modules/messages/components/message-detail/panels/body-panel.js.map +7 -0
  141. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js +36 -0
  142. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js.map +7 -0
  143. package/dist/modules/messages/components/message-detail/panels/dialogs.js +96 -0
  144. package/dist/modules/messages/components/message-detail/panels/dialogs.js.map +7 -0
  145. package/dist/modules/messages/components/message-detail/panels/index.js +25 -0
  146. package/dist/modules/messages/components/message-detail/panels/index.js.map +7 -0
  147. package/dist/modules/messages/components/message-detail/panels/meta-panel.js +14 -0
  148. package/dist/modules/messages/components/message-detail/panels/meta-panel.js.map +7 -0
  149. package/dist/modules/messages/components/message-detail/panels/objects-panel.js +51 -0
  150. package/dist/modules/messages/components/message-detail/panels/objects-panel.js.map +7 -0
  151. package/dist/modules/messages/components/message-detail/panels/thread-panel.js +54 -0
  152. package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +7 -0
  153. package/dist/modules/messages/components/message-detail/types.js +1 -0
  154. package/dist/modules/messages/components/message-detail/types.js.map +7 -0
  155. package/dist/modules/messages/components/message-detail/utils.js +54 -0
  156. package/dist/modules/messages/components/message-detail/utils.js.map +7 -0
  157. package/dist/modules/messages/components/utils/PriorityBadge.js +52 -0
  158. package/dist/modules/messages/components/utils/PriorityBadge.js.map +7 -0
  159. package/dist/modules/messages/components/utils/typeUiRegistry.js +77 -0
  160. package/dist/modules/messages/components/utils/typeUiRegistry.js.map +7 -0
  161. package/dist/modules/messages/data/entities.js +309 -0
  162. package/dist/modules/messages/data/entities.js.map +7 -0
  163. package/dist/modules/messages/data/validators.js +272 -0
  164. package/dist/modules/messages/data/validators.js.map +7 -0
  165. package/dist/modules/messages/emails/MessageEmail.js +108 -0
  166. package/dist/modules/messages/emails/MessageEmail.js.map +7 -0
  167. package/dist/modules/messages/events.js +24 -0
  168. package/dist/modules/messages/events.js.map +7 -0
  169. package/dist/modules/messages/frontend/messages/view/[token]/page.js +247 -0
  170. package/dist/modules/messages/frontend/messages/view/[token]/page.js.map +7 -0
  171. package/dist/modules/messages/frontend/messages/view/[token]/page.meta.js +9 -0
  172. package/dist/modules/messages/frontend/messages/view/[token]/page.meta.js.map +7 -0
  173. package/dist/modules/messages/index.js +21 -0
  174. package/dist/modules/messages/index.js.map +7 -0
  175. package/dist/modules/messages/lib/actions.js +141 -0
  176. package/dist/modules/messages/lib/actions.js.map +7 -0
  177. package/dist/modules/messages/lib/attachments.js +131 -0
  178. package/dist/modules/messages/lib/attachments.js.map +7 -0
  179. package/dist/modules/messages/lib/constants.js +7 -0
  180. package/dist/modules/messages/lib/constants.js.map +7 -0
  181. package/dist/modules/messages/lib/email-sender.js +201 -0
  182. package/dist/modules/messages/lib/email-sender.js.map +7 -0
  183. package/dist/modules/messages/lib/forwarding.js +179 -0
  184. package/dist/modules/messages/lib/forwarding.js.map +7 -0
  185. package/dist/modules/messages/lib/message-objects-registry.js +49 -0
  186. package/dist/modules/messages/lib/message-objects-registry.js.map +7 -0
  187. package/dist/modules/messages/lib/message-types-registry.js +41 -0
  188. package/dist/modules/messages/lib/message-types-registry.js.map +7 -0
  189. package/dist/modules/messages/lib/object-validation.js +20 -0
  190. package/dist/modules/messages/lib/object-validation.js.map +7 -0
  191. package/dist/modules/messages/lib/operationMetadata.js +21 -0
  192. package/dist/modules/messages/lib/operationMetadata.js.map +7 -0
  193. package/dist/modules/messages/lib/priorityUtils.js +61 -0
  194. package/dist/modules/messages/lib/priorityUtils.js.map +7 -0
  195. package/dist/modules/messages/lib/routeHelpers.js +44 -0
  196. package/dist/modules/messages/lib/routeHelpers.js.map +7 -0
  197. package/dist/modules/messages/message-objects.js +7 -0
  198. package/dist/modules/messages/message-objects.js.map +7 -0
  199. package/dist/modules/messages/message-types.js +67 -0
  200. package/dist/modules/messages/message-types.js.map +7 -0
  201. package/dist/modules/messages/migrations/Migration20260213181243.js +31 -0
  202. package/dist/modules/messages/migrations/Migration20260213181243.js.map +7 -0
  203. package/dist/modules/messages/migrations/Migration20260215165126.js +16 -0
  204. package/dist/modules/messages/migrations/Migration20260215165126.js.map +7 -0
  205. package/dist/modules/messages/notifications.js +27 -0
  206. package/dist/modules/messages/notifications.js.map +7 -0
  207. package/dist/modules/messages/setup.js +21 -0
  208. package/dist/modules/messages/setup.js.map +7 -0
  209. package/dist/modules/messages/subscribers/message-notification.js +108 -0
  210. package/dist/modules/messages/subscribers/message-notification.js.map +7 -0
  211. package/dist/modules/messages/workers/send-email.worker.js +253 -0
  212. package/dist/modules/messages/workers/send-email.worker.js.map +7 -0
  213. package/dist/modules/sales/backend/sales/documents/[id]/page.js +30 -11
  214. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  215. package/dist/modules/sales/commands/payments.js +12 -6
  216. package/dist/modules/sales/commands/payments.js.map +2 -2
  217. package/dist/modules/sales/lib/messageObjectPreviews.js +114 -0
  218. package/dist/modules/sales/lib/messageObjectPreviews.js.map +7 -0
  219. package/dist/modules/sales/message-objects.js +57 -0
  220. package/dist/modules/sales/message-objects.js.map +7 -0
  221. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js +51 -0
  222. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js.map +7 -0
  223. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js +36 -0
  224. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js.map +7 -0
  225. package/dist/modules/sales/widgets/messages/index.js +7 -0
  226. package/dist/modules/sales/widgets/messages/index.js.map +7 -0
  227. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +55 -1
  228. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  229. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +60 -1
  230. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  231. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +2 -19
  232. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  233. package/dist/modules/staff/components/LeaveRequestDetail.js +112 -0
  234. package/dist/modules/staff/components/LeaveRequestDetail.js.map +7 -0
  235. package/dist/modules/staff/components/LeaveRequestForm.js +3 -1
  236. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  237. package/dist/modules/staff/components/LeaveRequestPreview.js +43 -0
  238. package/dist/modules/staff/components/LeaveRequestPreview.js.map +7 -0
  239. package/dist/modules/staff/lib/messageObjectPreviews.js +148 -0
  240. package/dist/modules/staff/lib/messageObjectPreviews.js.map +7 -0
  241. package/dist/modules/staff/message-objects.js +104 -0
  242. package/dist/modules/staff/message-objects.js.map +7 -0
  243. package/dist/modules/staff/message-types.js +23 -0
  244. package/dist/modules/staff/message-types.js.map +7 -0
  245. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js +51 -0
  246. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js.map +7 -0
  247. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js +34 -0
  248. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js.map +7 -0
  249. package/dist/modules/staff/widgets/messages/index.js +7 -0
  250. package/dist/modules/staff/widgets/messages/index.js.map +7 -0
  251. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +6 -6
  252. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  253. package/generated/entities/message/index.ts +31 -0
  254. package/generated/entities/message_access_token/index.ts +8 -0
  255. package/generated/entities/message_confirmation/index.ts +9 -0
  256. package/generated/entities/message_object/index.ts +10 -0
  257. package/generated/entities/message_recipient/index.ts +14 -0
  258. package/generated/entities.ids.generated.ts +8 -0
  259. package/generated/entity-fields-registry.ts +10 -0
  260. package/jest.setup.ts +5 -0
  261. package/package.json +2 -2
  262. package/src/modules/attachments/i18n/de.json +4 -0
  263. package/src/modules/attachments/i18n/en.json +4 -0
  264. package/src/modules/attachments/i18n/es.json +4 -0
  265. package/src/modules/attachments/i18n/pl.json +4 -0
  266. package/src/modules/auth/components/AclEditor.tsx +4 -2
  267. package/src/modules/auth/frontend/reset.tsx +3 -3
  268. package/src/modules/auth/i18n/de.json +5 -0
  269. package/src/modules/auth/i18n/en.json +5 -0
  270. package/src/modules/auth/i18n/es.json +5 -0
  271. package/src/modules/auth/i18n/pl.json +5 -0
  272. package/src/modules/catalog/i18n/de.json +21 -0
  273. package/src/modules/catalog/i18n/en.json +21 -0
  274. package/src/modules/catalog/i18n/es.json +21 -0
  275. package/src/modules/catalog/i18n/pl.json +21 -0
  276. package/src/modules/currencies/i18n/de.json +6 -0
  277. package/src/modules/currencies/i18n/en.json +6 -0
  278. package/src/modules/currencies/i18n/es.json +6 -0
  279. package/src/modules/currencies/i18n/pl.json +6 -0
  280. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +20 -4
  281. package/src/modules/customers/i18n/de.json +26 -1
  282. package/src/modules/customers/i18n/en.json +25 -0
  283. package/src/modules/customers/i18n/es.json +25 -0
  284. package/src/modules/customers/i18n/pl.json +25 -0
  285. package/src/modules/customers/lib/messageObjectPreviews.ts +154 -0
  286. package/src/modules/customers/message-objects.ts +70 -0
  287. package/src/modules/customers/widgets/messages/CustomerMessageObjectDetail.tsx +57 -0
  288. package/src/modules/customers/widgets/messages/CustomerMessageObjectPreview.tsx +49 -0
  289. package/src/modules/customers/widgets/messages/index.ts +2 -0
  290. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +41 -5
  291. package/src/modules/dashboards/i18n/de.json +5 -1
  292. package/src/modules/dashboards/i18n/en.json +5 -1
  293. package/src/modules/dashboards/i18n/es.json +5 -1
  294. package/src/modules/dashboards/i18n/pl.json +5 -1
  295. package/src/modules/dictionaries/i18n/de.json +14 -1
  296. package/src/modules/dictionaries/i18n/en.json +14 -1
  297. package/src/modules/dictionaries/i18n/es.json +14 -1
  298. package/src/modules/dictionaries/i18n/pl.json +14 -1
  299. package/src/modules/feature_toggles/i18n/de.json +3 -0
  300. package/src/modules/feature_toggles/i18n/en.json +3 -0
  301. package/src/modules/feature_toggles/i18n/es.json +3 -0
  302. package/src/modules/feature_toggles/i18n/pl.json +3 -0
  303. package/src/modules/messages/acl.ts +11 -0
  304. package/src/modules/messages/api/[id]/actions/[actionId]/route.ts +103 -0
  305. package/src/modules/messages/api/[id]/archive/route.ts +138 -0
  306. package/src/modules/messages/api/[id]/attachments/route.ts +217 -0
  307. package/src/modules/messages/api/[id]/confirmation/route.ts +73 -0
  308. package/src/modules/messages/api/[id]/conversation/archive/route.ts +69 -0
  309. package/src/modules/messages/api/[id]/conversation/read/route.ts +69 -0
  310. package/src/modules/messages/api/[id]/conversation/route.ts +69 -0
  311. package/src/modules/messages/api/[id]/forward/route.ts +87 -0
  312. package/src/modules/messages/api/[id]/forward-preview/route.ts +75 -0
  313. package/src/modules/messages/api/[id]/read/route.ts +138 -0
  314. package/src/modules/messages/api/[id]/reply/route.ts +89 -0
  315. package/src/modules/messages/api/[id]/route.ts +401 -0
  316. package/src/modules/messages/api/object-types/route.ts +54 -0
  317. package/src/modules/messages/api/openapi.ts +261 -0
  318. package/src/modules/messages/api/route.ts +374 -0
  319. package/src/modules/messages/api/token/[token]/route.ts +103 -0
  320. package/src/modules/messages/api/types/route.ts +39 -0
  321. package/src/modules/messages/api/unread-count/route.ts +55 -0
  322. package/src/modules/messages/backend/messages/[id]/page.meta.ts +12 -0
  323. package/src/modules/messages/backend/messages/[id]/page.tsx +12 -0
  324. package/src/modules/messages/backend/messages/compose/page.meta.ts +13 -0
  325. package/src/modules/messages/backend/messages/compose/page.tsx +12 -0
  326. package/src/modules/messages/backend/page.meta.ts +31 -0
  327. package/src/modules/messages/backend/page.tsx +12 -0
  328. package/src/modules/messages/commands/actions.ts +307 -0
  329. package/src/modules/messages/commands/attachments.ts +227 -0
  330. package/src/modules/messages/commands/confirmations.ts +183 -0
  331. package/src/modules/messages/commands/conversation.ts +292 -0
  332. package/src/modules/messages/commands/messages.ts +845 -0
  333. package/src/modules/messages/commands/recipients.ts +281 -0
  334. package/src/modules/messages/commands/shared.ts +350 -0
  335. package/src/modules/messages/commands/tokens.ts +80 -0
  336. package/src/modules/messages/components/ComposeMessagePageClient.tsx +23 -0
  337. package/src/modules/messages/components/MessageDetailPageClient.tsx +287 -0
  338. package/src/modules/messages/components/MessagesInboxPageClient.tsx +469 -0
  339. package/src/modules/messages/components/confirmation/MessageConfirmationActions.tsx +35 -0
  340. package/src/modules/messages/components/confirmation/MessageConfirmationContent.tsx +88 -0
  341. package/src/modules/messages/components/defaults/DefaultMessageActions.tsx +37 -0
  342. package/src/modules/messages/components/defaults/DefaultMessageContent.tsx +21 -0
  343. package/src/modules/messages/components/defaults/DefaultMessageListItem.tsx +102 -0
  344. package/src/modules/messages/components/defaults/MessageRecordObjectDetail.tsx +114 -0
  345. package/src/modules/messages/components/defaults/MessageRecordObjectPreview.tsx +74 -0
  346. package/src/modules/messages/components/message-detail/detail-panels.ts +13 -0
  347. package/src/modules/messages/components/message-detail/hooks/useMessageDetails.ts +56 -0
  348. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsActions.ts +367 -0
  349. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.ts +134 -0
  350. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.ts +102 -0
  351. package/src/modules/messages/components/message-detail/panels/MainMessageHeader.tsx +108 -0
  352. package/src/modules/messages/components/message-detail/panels/MessageHeader.tsx +144 -0
  353. package/src/modules/messages/components/message-detail/panels/MessageListComponent.tsx +63 -0
  354. package/src/modules/messages/components/message-detail/panels/actions-panel.tsx +66 -0
  355. package/src/modules/messages/components/message-detail/panels/attachments-panel.tsx +86 -0
  356. package/src/modules/messages/components/message-detail/panels/body-panel.tsx +32 -0
  357. package/src/modules/messages/components/message-detail/panels/composer-dialogs.tsx +42 -0
  358. package/src/modules/messages/components/message-detail/panels/dialogs.tsx +107 -0
  359. package/src/modules/messages/components/message-detail/panels/index.ts +11 -0
  360. package/src/modules/messages/components/message-detail/panels/meta-panel.tsx +19 -0
  361. package/src/modules/messages/components/message-detail/panels/objects-panel.tsx +65 -0
  362. package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +65 -0
  363. package/src/modules/messages/components/message-detail/types.ts +114 -0
  364. package/src/modules/messages/components/message-detail/utils.ts +62 -0
  365. package/src/modules/messages/components/utils/PriorityBadge.tsx +63 -0
  366. package/src/modules/messages/components/utils/typeUiRegistry.ts +106 -0
  367. package/src/modules/messages/data/entities.ts +284 -0
  368. package/src/modules/messages/data/validators.ts +297 -0
  369. package/src/modules/messages/emails/MessageEmail.tsx +143 -0
  370. package/src/modules/messages/events.ts +24 -0
  371. package/src/modules/messages/frontend/messages/view/[token]/page.meta.ts +5 -0
  372. package/src/modules/messages/frontend/messages/view/[token]/page.tsx +389 -0
  373. package/src/modules/messages/i18n/de.json +240 -0
  374. package/src/modules/messages/i18n/en.json +240 -0
  375. package/src/modules/messages/i18n/es.json +240 -0
  376. package/src/modules/messages/i18n/pl.json +240 -0
  377. package/src/modules/messages/index.ts +19 -0
  378. package/src/modules/messages/lib/actions.ts +204 -0
  379. package/src/modules/messages/lib/attachments.ts +197 -0
  380. package/src/modules/messages/lib/constants.ts +2 -0
  381. package/src/modules/messages/lib/email-sender.ts +255 -0
  382. package/src/modules/messages/lib/forwarding.ts +240 -0
  383. package/src/modules/messages/lib/message-objects-registry.ts +60 -0
  384. package/src/modules/messages/lib/message-types-registry.ts +48 -0
  385. package/src/modules/messages/lib/object-validation.ts +26 -0
  386. package/src/modules/messages/lib/operationMetadata.ts +43 -0
  387. package/src/modules/messages/lib/priorityUtils.ts +76 -0
  388. package/src/modules/messages/lib/routeHelpers.ts +65 -0
  389. package/src/modules/messages/message-objects.ts +5 -0
  390. package/src/modules/messages/message-types.ts +65 -0
  391. package/src/modules/messages/migrations/.snapshot-open-mercato.json +957 -0
  392. package/src/modules/messages/migrations/Migration20260213181243.ts +34 -0
  393. package/src/modules/messages/migrations/Migration20260215165126.ts +16 -0
  394. package/src/modules/messages/notifications.ts +25 -0
  395. package/src/modules/messages/setup.ts +19 -0
  396. package/src/modules/messages/subscribers/message-notification.ts +138 -0
  397. package/src/modules/messages/workers/send-email.worker.ts +321 -0
  398. package/src/modules/query_index/i18n/es.json +2 -2
  399. package/src/modules/resources/i18n/de.json +57 -0
  400. package/src/modules/resources/i18n/en.json +57 -0
  401. package/src/modules/resources/i18n/es.json +57 -0
  402. package/src/modules/resources/i18n/pl.json +57 -0
  403. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +23 -7
  404. package/src/modules/sales/commands/payments.ts +12 -6
  405. package/src/modules/sales/i18n/de.json +26 -0
  406. package/src/modules/sales/i18n/en.json +26 -0
  407. package/src/modules/sales/i18n/es.json +26 -0
  408. package/src/modules/sales/i18n/pl.json +26 -0
  409. package/src/modules/sales/lib/messageObjectPreviews.ts +150 -0
  410. package/src/modules/sales/message-objects.ts +56 -0
  411. package/src/modules/sales/widgets/messages/SalesDocumentMessageDetail.tsx +57 -0
  412. package/src/modules/sales/widgets/messages/SalesDocumentMessagePreview.tsx +46 -0
  413. package/src/modules/sales/widgets/messages/index.ts +2 -0
  414. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +54 -0
  415. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +58 -0
  416. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +2 -32
  417. package/src/modules/staff/components/LeaveRequestDetail.tsx +135 -0
  418. package/src/modules/staff/components/LeaveRequestForm.tsx +3 -0
  419. package/src/modules/staff/components/LeaveRequestPreview.tsx +74 -0
  420. package/src/modules/staff/i18n/de.json +22 -0
  421. package/src/modules/staff/i18n/en.json +22 -0
  422. package/src/modules/staff/i18n/es.json +22 -0
  423. package/src/modules/staff/i18n/pl.json +22 -0
  424. package/src/modules/staff/lib/messageObjectPreviews.ts +182 -0
  425. package/src/modules/staff/message-objects.ts +102 -0
  426. package/src/modules/staff/message-types.ts +21 -0
  427. package/src/modules/staff/widgets/messages/StaffMessageObjectDetail.tsx +57 -0
  428. package/src/modules/staff/widgets/messages/StaffMessageObjectPreview.tsx +44 -0
  429. package/src/modules/staff/widgets/messages/index.ts +2 -0
  430. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +6 -6
  431. package/src/modules/workflows/i18n/de.json +41 -0
  432. package/src/modules/workflows/i18n/en.json +41 -0
  433. package/src/modules/workflows/i18n/es.json +41 -0
  434. package/src/modules/workflows/i18n/pl.json +41 -0
@@ -0,0 +1,141 @@
1
+ import { getMessageObjectType } from "./message-objects-registry.js";
2
+ import { getMessageType } from "./message-types-registry.js";
3
+ function normalizeActionLabel(action, fallback) {
4
+ if (typeof action.label === "string" && action.label.trim().length > 0) {
5
+ return action.label;
6
+ }
7
+ if (typeof fallback === "string" && fallback.trim().length > 0) {
8
+ return fallback.trim();
9
+ }
10
+ return action.id;
11
+ }
12
+ function isTerminalMessageAction(action) {
13
+ if (typeof action.isTerminal === "boolean") return action.isTerminal;
14
+ if (typeof action.commandId === "string" && action.commandId.trim().length > 0) return true;
15
+ if (typeof action.href === "string" && action.href.trim().length > 0) return false;
16
+ return true;
17
+ }
18
+ function buildMessageObjectActionId(objectId, actionId) {
19
+ return `object:${objectId}:${actionId}`;
20
+ }
21
+ function readActionDataExpiry(message) {
22
+ if (message.actionData?.expiresAt) return message.actionData.expiresAt;
23
+ const messageType = getMessageType(message.type);
24
+ if (!messageType?.actionsExpireAfterHours || !message.sentAt) return void 0;
25
+ return new Date(
26
+ message.sentAt.getTime() + messageType.actionsExpireAfterHours * 60 * 60 * 1e3
27
+ ).toISOString();
28
+ }
29
+ function buildResolvedMessageActions(message, objects) {
30
+ const resolved = [];
31
+ const usedIds = /* @__PURE__ */ new Set();
32
+ const pushAction = (action, source, objectRef, labelFallback) => {
33
+ const id = typeof action.id === "string" ? action.id.trim() : "";
34
+ if (!id || usedIds.has(id)) return;
35
+ usedIds.add(id);
36
+ resolved.push({
37
+ ...action,
38
+ id,
39
+ label: normalizeActionLabel(action, labelFallback),
40
+ source,
41
+ objectRef
42
+ });
43
+ };
44
+ for (const action of message.actionData?.actions ?? []) {
45
+ pushAction(action, "message");
46
+ }
47
+ const messageType = getMessageType(message.type);
48
+ for (const action of messageType?.defaultActions ?? []) {
49
+ pushAction(action, "type_default");
50
+ }
51
+ for (const object of objects) {
52
+ if (!object.actionRequired || !object.actionType) continue;
53
+ const objectType = getMessageObjectType(object.entityModule, object.entityType);
54
+ if (!objectType) continue;
55
+ const actionDef = objectType.actions.find((entry) => entry.id === object.actionType);
56
+ if (!actionDef) continue;
57
+ pushAction(
58
+ {
59
+ id: buildMessageObjectActionId(object.id, actionDef.id),
60
+ label: object.actionLabel ?? actionDef.id,
61
+ labelKey: actionDef.labelKey,
62
+ variant: actionDef.variant,
63
+ icon: actionDef.icon,
64
+ commandId: actionDef.commandId,
65
+ href: actionDef.href,
66
+ isTerminal: actionDef.isTerminal,
67
+ confirmRequired: actionDef.confirmRequired,
68
+ confirmMessage: actionDef.confirmMessage
69
+ },
70
+ "object",
71
+ {
72
+ objectId: object.id,
73
+ entityModule: object.entityModule,
74
+ entityType: object.entityType,
75
+ entityId: object.entityId
76
+ },
77
+ object.actionLabel ?? actionDef.id
78
+ );
79
+ }
80
+ const expiresAt = readActionDataExpiry(message);
81
+ if (resolved.length === 0 && !expiresAt) {
82
+ return null;
83
+ }
84
+ const configuredPrimaryActionId = message.actionData?.primaryActionId;
85
+ const primaryActionId = configuredPrimaryActionId && resolved.some((entry) => entry.id === configuredPrimaryActionId) ? configuredPrimaryActionId : resolved[0]?.id;
86
+ return {
87
+ actions: resolved,
88
+ primaryActionId,
89
+ expiresAt
90
+ };
91
+ }
92
+ function findResolvedMessageActionById(message, objects, actionId) {
93
+ const actionData = buildResolvedMessageActions(message, objects);
94
+ const match = actionData?.actions.find((entry) => entry.id === actionId);
95
+ return match ?? null;
96
+ }
97
+ function buildTemplateContext(message, resolutionContext, objectRef) {
98
+ return {
99
+ messageId: message.id,
100
+ sourceEntityId: message.sourceEntityId ?? message.id,
101
+ sourceEntityType: message.sourceEntityType ?? null,
102
+ threadId: message.threadId ?? null,
103
+ parentMessageId: message.parentMessageId ?? null,
104
+ messageType: message.type,
105
+ tenantId: resolutionContext.tenantId,
106
+ organizationId: resolutionContext.organizationId ?? null,
107
+ userId: resolutionContext.userId,
108
+ objectId: objectRef?.objectId ?? null,
109
+ entityId: objectRef?.entityId ?? null,
110
+ entityType: objectRef?.entityType ?? null,
111
+ entityModule: objectRef?.entityModule ?? null
112
+ };
113
+ }
114
+ function resolveTemplateString(template, context) {
115
+ return template.replace(/\{([a-zA-Z0-9_]+)\}/g, (fullMatch, key) => {
116
+ const value = context[key];
117
+ if (value == null) return fullMatch;
118
+ return String(value);
119
+ });
120
+ }
121
+ function resolveActionHref(action, message, resolutionContext) {
122
+ if (!action.href) return null;
123
+ const context = buildTemplateContext(message, resolutionContext, action.objectRef);
124
+ return resolveTemplateString(action.href, context);
125
+ }
126
+ function resolveActionCommandInput(action, message, _resolutionContext, requestInput) {
127
+ return {
128
+ ...requestInput,
129
+ messageId: message.id,
130
+ actionId: action.id
131
+ };
132
+ }
133
+ export {
134
+ buildMessageObjectActionId,
135
+ buildResolvedMessageActions,
136
+ findResolvedMessageActionById,
137
+ isTerminalMessageAction,
138
+ resolveActionCommandInput,
139
+ resolveActionHref
140
+ };
141
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/messages/lib/actions.ts"],
4
+ "sourcesContent": ["import type { Message, MessageAction, MessageActionData, MessageObject } from '../data/entities'\nimport { getMessageObjectType } from './message-objects-registry'\nimport { getMessageType } from './message-types-registry'\n\ntype MessageActionSource = 'message' | 'type_default' | 'object'\n\nexport type MessageActionObjectRef = {\n objectId: string\n entityModule: string\n entityType: string\n entityId: string\n}\n\nexport type ResolvedMessageAction = MessageAction & {\n source: MessageActionSource\n objectRef?: MessageActionObjectRef\n}\n\nexport type MessageActionResolutionContext = {\n tenantId: string\n organizationId?: string | null\n userId: string\n}\n\nfunction normalizeActionLabel(\n action: Pick<MessageAction, 'label' | 'id'>,\n fallback?: string | null,\n): string {\n if (typeof action.label === 'string' && action.label.trim().length > 0) {\n return action.label\n }\n if (typeof fallback === 'string' && fallback.trim().length > 0) {\n return fallback.trim()\n }\n return action.id\n}\n\nexport function isTerminalMessageAction(\n action: Pick<MessageAction, 'isTerminal' | 'commandId' | 'href'>,\n): boolean {\n if (typeof action.isTerminal === 'boolean') return action.isTerminal\n if (typeof action.commandId === 'string' && action.commandId.trim().length > 0) return true\n if (typeof action.href === 'string' && action.href.trim().length > 0) return false\n return true\n}\n\nexport function buildMessageObjectActionId(objectId: string, actionId: string): string {\n return `object:${objectId}:${actionId}`\n}\n\nfunction readActionDataExpiry(message: Message): string | undefined {\n if (message.actionData?.expiresAt) return message.actionData.expiresAt\n const messageType = getMessageType(message.type)\n if (!messageType?.actionsExpireAfterHours || !message.sentAt) return undefined\n return new Date(\n message.sentAt.getTime() + messageType.actionsExpireAfterHours * 60 * 60 * 1000,\n ).toISOString()\n}\n\nexport function buildResolvedMessageActions(\n message: Message,\n objects: MessageObject[],\n): MessageActionData | null {\n const resolved: ResolvedMessageAction[] = []\n const usedIds = new Set<string>()\n\n const pushAction = (\n action: MessageAction,\n source: MessageActionSource,\n objectRef?: MessageActionObjectRef,\n labelFallback?: string | null,\n ) => {\n const id = typeof action.id === 'string' ? action.id.trim() : ''\n if (!id || usedIds.has(id)) return\n usedIds.add(id)\n\n resolved.push({\n ...action,\n id,\n label: normalizeActionLabel(action, labelFallback),\n source,\n objectRef,\n })\n }\n\n for (const action of message.actionData?.actions ?? []) {\n pushAction(action, 'message')\n }\n\n const messageType = getMessageType(message.type)\n for (const action of messageType?.defaultActions ?? []) {\n pushAction(action, 'type_default')\n }\n\n for (const object of objects) {\n if (!object.actionRequired || !object.actionType) continue\n const objectType = getMessageObjectType(object.entityModule, object.entityType)\n if (!objectType) continue\n const actionDef = objectType.actions.find((entry) => entry.id === object.actionType)\n if (!actionDef) continue\n\n pushAction(\n {\n id: buildMessageObjectActionId(object.id, actionDef.id),\n label: object.actionLabel ?? actionDef.id,\n labelKey: actionDef.labelKey,\n variant: actionDef.variant,\n icon: actionDef.icon,\n commandId: actionDef.commandId,\n href: actionDef.href,\n isTerminal: actionDef.isTerminal,\n confirmRequired: actionDef.confirmRequired,\n confirmMessage: actionDef.confirmMessage,\n },\n 'object',\n {\n objectId: object.id,\n entityModule: object.entityModule,\n entityType: object.entityType,\n entityId: object.entityId,\n },\n object.actionLabel ?? actionDef.id,\n )\n }\n\n const expiresAt = readActionDataExpiry(message)\n if (resolved.length === 0 && !expiresAt) {\n return null\n }\n\n const configuredPrimaryActionId = message.actionData?.primaryActionId\n const primaryActionId = configuredPrimaryActionId && resolved.some((entry) => entry.id === configuredPrimaryActionId)\n ? configuredPrimaryActionId\n : resolved[0]?.id\n\n return {\n actions: resolved,\n primaryActionId,\n expiresAt,\n }\n}\n\nexport function findResolvedMessageActionById(\n message: Message,\n objects: MessageObject[],\n actionId: string,\n): ResolvedMessageAction | null {\n const actionData = buildResolvedMessageActions(message, objects)\n const match = actionData?.actions.find((entry) => entry.id === actionId)\n return (match as ResolvedMessageAction | undefined) ?? null\n}\n\nfunction buildTemplateContext(\n message: Message,\n resolutionContext: MessageActionResolutionContext,\n objectRef?: MessageActionObjectRef,\n): Record<string, unknown> {\n return {\n messageId: message.id,\n sourceEntityId: message.sourceEntityId ?? message.id,\n sourceEntityType: message.sourceEntityType ?? null,\n threadId: message.threadId ?? null,\n parentMessageId: message.parentMessageId ?? null,\n messageType: message.type,\n tenantId: resolutionContext.tenantId,\n organizationId: resolutionContext.organizationId ?? null,\n userId: resolutionContext.userId,\n objectId: objectRef?.objectId ?? null,\n entityId: objectRef?.entityId ?? null,\n entityType: objectRef?.entityType ?? null,\n entityModule: objectRef?.entityModule ?? null,\n }\n}\n\nfunction resolveTemplateString(template: string, context: Record<string, unknown>): string {\n return template.replace(/\\{([a-zA-Z0-9_]+)\\}/g, (fullMatch, key: string) => {\n const value = context[key]\n if (value == null) return fullMatch\n return String(value)\n })\n}\n\nexport function resolveActionHref(\n action: ResolvedMessageAction,\n message: Message,\n resolutionContext: MessageActionResolutionContext,\n): string | null {\n if (!action.href) return null\n const context = buildTemplateContext(message, resolutionContext, action.objectRef)\n return resolveTemplateString(action.href, context)\n}\n\nexport function resolveActionCommandInput(\n action: ResolvedMessageAction,\n message: Message,\n _resolutionContext: MessageActionResolutionContext,\n requestInput: Record<string, unknown>,\n): Record<string, unknown> {\n return {\n ...requestInput,\n messageId: message.id,\n actionId: action.id,\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,131 @@
1
+ import { MESSAGE_ATTACHMENT_ENTITY_ID } from "./constants.js";
2
+ const LIBRARY_ATTACHMENT_ENTITY_ID = "attachments:library";
3
+ function buildOrganizationScopeFilter(organizationId) {
4
+ if (!organizationId) {
5
+ return { organizationId: null };
6
+ }
7
+ return {
8
+ $or: [
9
+ { organizationId },
10
+ { organizationId: null }
11
+ ]
12
+ };
13
+ }
14
+ async function linkAttachmentsToMessage(em, messageId, attachmentIds, organizationId, tenantId) {
15
+ if (attachmentIds.length === 0) return;
16
+ const { Attachment } = await import("@open-mercato/core/modules/attachments/data/entities");
17
+ const attachments = await em.find(Attachment, {
18
+ id: { $in: attachmentIds },
19
+ tenantId,
20
+ ...buildOrganizationScopeFilter(organizationId)
21
+ });
22
+ for (const attachment of attachments) {
23
+ attachment.entityId = MESSAGE_ATTACHMENT_ENTITY_ID;
24
+ attachment.recordId = messageId;
25
+ }
26
+ await em.flush();
27
+ }
28
+ async function getMessageAttachments(em, messageId, organizationId, tenantId) {
29
+ const { Attachment } = await import("@open-mercato/core/modules/attachments/data/entities");
30
+ const attachments = await em.find(Attachment, {
31
+ entityId: MESSAGE_ATTACHMENT_ENTITY_ID,
32
+ recordId: messageId,
33
+ tenantId,
34
+ ...buildOrganizationScopeFilter(organizationId)
35
+ });
36
+ return attachments.map((attachment) => ({
37
+ id: attachment.id,
38
+ fileName: attachment.fileName,
39
+ fileSize: attachment.fileSize,
40
+ mimeType: attachment.mimeType,
41
+ url: attachment.url
42
+ }));
43
+ }
44
+ async function getMessageEmailAttachments(em, messageId, organizationId, tenantId) {
45
+ const { Attachment } = await import("@open-mercato/core/modules/attachments/data/entities");
46
+ const attachments = await em.find(Attachment, {
47
+ entityId: MESSAGE_ATTACHMENT_ENTITY_ID,
48
+ recordId: messageId,
49
+ tenantId,
50
+ ...buildOrganizationScopeFilter(organizationId)
51
+ });
52
+ return attachments.map((attachment) => ({
53
+ fileName: attachment.fileName,
54
+ fileSize: attachment.fileSize,
55
+ mimeType: attachment.mimeType,
56
+ partitionCode: attachment.partitionCode,
57
+ storagePath: attachment.storagePath,
58
+ storageDriver: attachment.storageDriver
59
+ }));
60
+ }
61
+ async function linkLibraryAttachmentsToMessage(em, messageId, sourceRecordId, organizationId, tenantId) {
62
+ if (!sourceRecordId.trim()) return;
63
+ const { Attachment } = await import("@open-mercato/core/modules/attachments/data/entities");
64
+ const attachments = await em.find(Attachment, {
65
+ entityId: LIBRARY_ATTACHMENT_ENTITY_ID,
66
+ recordId: sourceRecordId,
67
+ tenantId,
68
+ ...buildOrganizationScopeFilter(organizationId)
69
+ });
70
+ if (!attachments.length) return;
71
+ for (const attachment of attachments) {
72
+ attachment.entityId = MESSAGE_ATTACHMENT_ENTITY_ID;
73
+ attachment.recordId = messageId;
74
+ }
75
+ await em.flush();
76
+ }
77
+ async function copyAttachmentsForForward(em, sourceMessageId, targetMessageId, organizationId, tenantId) {
78
+ return copyAttachmentsForForwardMessages(
79
+ em,
80
+ [sourceMessageId],
81
+ targetMessageId,
82
+ organizationId,
83
+ tenantId
84
+ );
85
+ }
86
+ async function copyAttachmentsForForwardMessages(em, sourceMessageIds, targetMessageId, targetOrganizationId, tenantId) {
87
+ if (sourceMessageIds.length === 0) return 0;
88
+ const { Attachment } = await import("@open-mercato/core/modules/attachments/data/entities");
89
+ const sourceAttachments = await em.find(Attachment, {
90
+ entityId: MESSAGE_ATTACHMENT_ENTITY_ID,
91
+ recordId: { $in: sourceMessageIds },
92
+ tenantId
93
+ });
94
+ if (sourceAttachments.length === 0) {
95
+ return 0;
96
+ }
97
+ const dedupedById = /* @__PURE__ */ new Map();
98
+ for (const sourceAttachment of sourceAttachments) {
99
+ if (!dedupedById.has(sourceAttachment.id)) {
100
+ dedupedById.set(sourceAttachment.id, sourceAttachment);
101
+ }
102
+ }
103
+ for (const sourceAttachment of dedupedById.values()) {
104
+ const copy = em.create(Attachment, {
105
+ entityId: MESSAGE_ATTACHMENT_ENTITY_ID,
106
+ recordId: targetMessageId,
107
+ organizationId: targetOrganizationId,
108
+ tenantId,
109
+ fileName: sourceAttachment.fileName,
110
+ mimeType: sourceAttachment.mimeType,
111
+ fileSize: sourceAttachment.fileSize,
112
+ storageDriver: sourceAttachment.storageDriver,
113
+ storagePath: sourceAttachment.storagePath,
114
+ storageMetadata: sourceAttachment.storageMetadata,
115
+ url: sourceAttachment.url,
116
+ partitionCode: sourceAttachment.partitionCode
117
+ });
118
+ em.persist(copy);
119
+ }
120
+ await em.flush();
121
+ return dedupedById.size;
122
+ }
123
+ export {
124
+ copyAttachmentsForForward,
125
+ copyAttachmentsForForwardMessages,
126
+ getMessageAttachments,
127
+ getMessageEmailAttachments,
128
+ linkAttachmentsToMessage,
129
+ linkLibraryAttachmentsToMessage
130
+ };
131
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/messages/lib/attachments.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/core'\nimport { MESSAGE_ATTACHMENT_ENTITY_ID } from './constants'\nconst LIBRARY_ATTACHMENT_ENTITY_ID = 'attachments:library'\n\nfunction buildOrganizationScopeFilter(organizationId: string | null) {\n if (!organizationId) {\n return { organizationId: null }\n }\n return {\n $or: [\n { organizationId },\n { organizationId: null },\n ],\n }\n}\n\nexport async function linkAttachmentsToMessage(\n em: EntityManager,\n messageId: string,\n attachmentIds: string[],\n organizationId: string | null,\n tenantId: string,\n): Promise<void> {\n if (attachmentIds.length === 0) return\n\n const { Attachment } = await import('@open-mercato/core/modules/attachments/data/entities')\n\n const attachments = await em.find(Attachment, {\n id: { $in: attachmentIds },\n tenantId,\n ...buildOrganizationScopeFilter(organizationId),\n })\n\n for (const attachment of attachments) {\n attachment.entityId = MESSAGE_ATTACHMENT_ENTITY_ID\n attachment.recordId = messageId\n }\n\n await em.flush()\n}\n\nexport async function getMessageAttachments(\n em: EntityManager,\n messageId: string,\n organizationId: string | null,\n tenantId: string,\n): Promise<Array<{\n id: string\n fileName: string\n fileSize: number\n mimeType: string\n url: string\n}>> {\n const { Attachment } = await import('@open-mercato/core/modules/attachments/data/entities')\n\n const attachments = await em.find(Attachment, {\n entityId: MESSAGE_ATTACHMENT_ENTITY_ID,\n recordId: messageId,\n tenantId,\n ...buildOrganizationScopeFilter(organizationId),\n })\n\n return attachments.map((attachment) => ({\n id: attachment.id,\n fileName: attachment.fileName,\n fileSize: attachment.fileSize,\n mimeType: attachment.mimeType,\n url: attachment.url,\n }))\n}\n\nexport type MessageEmailAttachment = {\n fileName: string\n fileSize: number\n mimeType: string\n partitionCode: string\n storagePath: string\n storageDriver: string\n}\n\nexport async function getMessageEmailAttachments(\n em: EntityManager,\n messageId: string,\n organizationId: string | null,\n tenantId: string,\n): Promise<MessageEmailAttachment[]> {\n const { Attachment } = await import('@open-mercato/core/modules/attachments/data/entities')\n\n const attachments = await em.find(Attachment, {\n entityId: MESSAGE_ATTACHMENT_ENTITY_ID,\n recordId: messageId,\n tenantId,\n ...buildOrganizationScopeFilter(organizationId),\n })\n\n return attachments.map((attachment) => ({\n fileName: attachment.fileName,\n fileSize: attachment.fileSize,\n mimeType: attachment.mimeType,\n partitionCode: attachment.partitionCode,\n storagePath: attachment.storagePath,\n storageDriver: attachment.storageDriver,\n }))\n}\n\nexport async function linkLibraryAttachmentsToMessage(\n em: EntityManager,\n messageId: string,\n sourceRecordId: string,\n organizationId: string | null,\n tenantId: string,\n): Promise<void> {\n if (!sourceRecordId.trim()) return\n\n const { Attachment } = await import('@open-mercato/core/modules/attachments/data/entities')\n\n const attachments = await em.find(Attachment, {\n entityId: LIBRARY_ATTACHMENT_ENTITY_ID,\n recordId: sourceRecordId,\n tenantId,\n ...buildOrganizationScopeFilter(organizationId),\n })\n\n if (!attachments.length) return\n\n for (const attachment of attachments) {\n attachment.entityId = MESSAGE_ATTACHMENT_ENTITY_ID\n attachment.recordId = messageId\n }\n\n await em.flush()\n}\n\nexport async function copyAttachmentsForForward(\n em: EntityManager,\n sourceMessageId: string,\n targetMessageId: string,\n organizationId: string | null,\n tenantId: string,\n): Promise<number> {\n return copyAttachmentsForForwardMessages(\n em,\n [sourceMessageId],\n targetMessageId,\n organizationId,\n tenantId,\n )\n}\n\nexport async function copyAttachmentsForForwardMessages(\n em: EntityManager,\n sourceMessageIds: string[],\n targetMessageId: string,\n targetOrganizationId: string | null,\n tenantId: string,\n): Promise<number> {\n if (sourceMessageIds.length === 0) return 0\n\n const { Attachment } = await import('@open-mercato/core/modules/attachments/data/entities')\n const sourceAttachments = await em.find(Attachment, {\n entityId: MESSAGE_ATTACHMENT_ENTITY_ID,\n recordId: { $in: sourceMessageIds },\n tenantId,\n })\n if (sourceAttachments.length === 0) {\n return 0\n }\n\n const dedupedById = new Map<string, typeof sourceAttachments[number]>()\n for (const sourceAttachment of sourceAttachments) {\n if (!dedupedById.has(sourceAttachment.id)) {\n dedupedById.set(sourceAttachment.id, sourceAttachment)\n }\n }\n\n for (const sourceAttachment of dedupedById.values()) {\n const copy = em.create(Attachment, {\n entityId: MESSAGE_ATTACHMENT_ENTITY_ID,\n recordId: targetMessageId,\n organizationId: targetOrganizationId,\n tenantId,\n fileName: sourceAttachment.fileName,\n mimeType: sourceAttachment.mimeType,\n fileSize: sourceAttachment.fileSize,\n storageDriver: sourceAttachment.storageDriver,\n storagePath: sourceAttachment.storagePath,\n storageMetadata: sourceAttachment.storageMetadata,\n url: sourceAttachment.url,\n partitionCode: sourceAttachment.partitionCode,\n })\n\n em.persist(copy)\n }\n\n await em.flush()\n return dedupedById.size\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,7 @@
1
+ const MESSAGE_ATTACHMENT_ENTITY_ID = "messages:message";
2
+ const MESSAGE_ATTACHMENT_PARTITION = "messages";
3
+ export {
4
+ MESSAGE_ATTACHMENT_ENTITY_ID,
5
+ MESSAGE_ATTACHMENT_PARTITION
6
+ };
7
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/messages/lib/constants.ts"],
4
+ "sourcesContent": ["export const MESSAGE_ATTACHMENT_ENTITY_ID = 'messages:message'\nexport const MESSAGE_ATTACHMENT_PARTITION = 'messages'\n"],
5
+ "mappings": "AAAO,MAAM,+BAA+B;AACrC,MAAM,+BAA+B;",
6
+ "names": []
7
+ }
@@ -0,0 +1,201 @@
1
+ import * as React from "react";
2
+ import crypto from "node:crypto";
3
+ import { promises as fs } from "fs";
4
+ import { sendEmail } from "@open-mercato/shared/lib/email/send";
5
+ import { loadDictionary } from "@open-mercato/shared/lib/i18n/server";
6
+ import { defaultLocale } from "@open-mercato/shared/lib/i18n/config";
7
+ import { createFallbackTranslator } from "@open-mercato/shared/lib/i18n/translate";
8
+ import { MessageAccessToken } from "../data/entities.js";
9
+ import MessageEmail from "../emails/MessageEmail.js";
10
+ import { resolveAttachmentAbsolutePath } from "../../attachments/lib/storage.js";
11
+ const ACCESS_TOKEN_EXPIRY_HOURS = 24 * 7;
12
+ const DEBUG = process.env.MESSAGES_EMAIL_DEBUG === "true";
13
+ const MAX_EMAIL_ATTACHMENTS = 10;
14
+ const MAX_TOTAL_ATTACHMENT_BYTES = 20 * 1024 * 1024;
15
+ function logDebug(message, details) {
16
+ if (!DEBUG) return;
17
+ if (details) {
18
+ console.log(`[messages:email-sender] ${message}`, details);
19
+ return;
20
+ }
21
+ console.log(`[messages:email-sender] ${message}`);
22
+ }
23
+ function resolveAppUrl() {
24
+ const raw = process.env.APP_URL?.trim();
25
+ if (!raw) return null;
26
+ return raw.replace(/\/$/, "");
27
+ }
28
+ function buildSenderLabel(sender) {
29
+ const name = sender.name?.trim();
30
+ if (name) return name;
31
+ const email = sender.email?.trim();
32
+ if (email) return email;
33
+ return "System";
34
+ }
35
+ function generateAccessToken() {
36
+ return crypto.randomBytes(32).toString("hex");
37
+ }
38
+ function resolveObjectLabels(objects) {
39
+ return objects.map((item) => `${item.entityModule}.${item.entityType} (${item.entityId})`);
40
+ }
41
+ async function mapAttachmentsForEmail(messageId, attachments) {
42
+ const resendAttachments = [];
43
+ let totalBytes = 0;
44
+ for (const attachment of attachments.slice(0, MAX_EMAIL_ATTACHMENTS)) {
45
+ const absolutePath = resolveAttachmentAbsolutePath(
46
+ attachment.partitionCode,
47
+ attachment.storagePath,
48
+ attachment.storageDriver
49
+ );
50
+ let buffer;
51
+ try {
52
+ buffer = await fs.readFile(absolutePath);
53
+ } catch (error) {
54
+ logDebug("Attachment skipped: file read failed", {
55
+ messageId,
56
+ fileName: attachment.fileName,
57
+ error: error instanceof Error ? error.message : String(error)
58
+ });
59
+ continue;
60
+ }
61
+ if (totalBytes + buffer.length > MAX_TOTAL_ATTACHMENT_BYTES) {
62
+ logDebug("Attachment skipped: total size limit exceeded", {
63
+ messageId,
64
+ fileName: attachment.fileName,
65
+ nextTotalBytes: totalBytes + buffer.length
66
+ });
67
+ continue;
68
+ }
69
+ totalBytes += buffer.length;
70
+ resendAttachments.push({
71
+ filename: attachment.fileName,
72
+ content: buffer.toString("base64"),
73
+ contentType: attachment.mimeType || void 0
74
+ });
75
+ }
76
+ return resendAttachments;
77
+ }
78
+ async function renderMarkdownEmailBody(body) {
79
+ const ReactMarkdownModule = await import("react-markdown");
80
+ const remarkGfmModule = await import("remark-gfm");
81
+ const ReactMarkdown = ReactMarkdownModule.default ?? ReactMarkdownModule;
82
+ const remarkGfmPlugin = remarkGfmModule.default ?? remarkGfmModule;
83
+ const { renderToStaticMarkup } = await import("react-dom/server");
84
+ return renderToStaticMarkup(
85
+ React.createElement(ReactMarkdown, { remarkPlugins: [remarkGfmPlugin] }, body)
86
+ );
87
+ }
88
+ async function buildEmailBodyHtml(message) {
89
+ if (message.bodyFormat !== "markdown") return void 0;
90
+ if (!message.body) return void 0;
91
+ return renderMarkdownEmailBody(message.body);
92
+ }
93
+ async function buildEmailCopy(sentAt) {
94
+ const dict = await loadDictionary(defaultLocale);
95
+ const t = createFallbackTranslator(dict);
96
+ return {
97
+ preview: t("messages.email.preview", "You received a message in Open Mercato"),
98
+ heading: t("messages.email.heading", "New message"),
99
+ from: t("messages.email.from", "From"),
100
+ sentAt: t("messages.email.sentAt", "Sent"),
101
+ sentAtLabel: sentAt.toISOString(),
102
+ viewCta: t("messages.email.viewCta", "View message"),
103
+ attachmentsLabel: t("messages.email.attachments", "Attachments"),
104
+ objectsLabel: t("messages.email.objects", "Related records"),
105
+ footer: t("messages.email.footer", "Open Mercato messages")
106
+ };
107
+ }
108
+ async function createMessageAccessToken(em, messageId, recipientUserId) {
109
+ const token = generateAccessToken();
110
+ const expiresAt = new Date(Date.now() + ACCESS_TOKEN_EXPIRY_HOURS * 60 * 60 * 1e3);
111
+ const record = em.create(MessageAccessToken, {
112
+ messageId,
113
+ recipientUserId,
114
+ token,
115
+ expiresAt,
116
+ useCount: 0
117
+ });
118
+ await em.persistAndFlush(record);
119
+ logDebug("Created access token", {
120
+ messageId,
121
+ recipientUserId,
122
+ expiresAt: expiresAt.toISOString()
123
+ });
124
+ return token;
125
+ }
126
+ async function sendMessageEmailToRecipient(params) {
127
+ const { em, message, recipientUserId, recipientEmail, sender, objects, attachments } = params;
128
+ const token = await createMessageAccessToken(em, message.id, recipientUserId);
129
+ const appUrl = resolveAppUrl();
130
+ const viewUrl = appUrl ? `${appUrl}/messages/view/${token}` : null;
131
+ if (!appUrl) {
132
+ logDebug("APP_URL missing - email link omitted", { messageId: message.id });
133
+ }
134
+ const copy = await buildEmailCopy(message.sentAt ?? /* @__PURE__ */ new Date());
135
+ const bodyHtml = await buildEmailBodyHtml(message);
136
+ const resendAttachments = await mapAttachmentsForEmail(message.id, attachments);
137
+ logDebug("Sending recipient email via Resend", {
138
+ messageId: message.id,
139
+ recipientUserId,
140
+ recipientEmail,
141
+ hasViewUrl: Boolean(viewUrl),
142
+ attachmentsCount: resendAttachments.length,
143
+ hasApiKey: Boolean(process.env.RESEND_API_KEY),
144
+ from: process.env.EMAIL_FROM ?? null
145
+ });
146
+ await sendEmail({
147
+ to: recipientEmail,
148
+ subject: message.subject,
149
+ react: MessageEmail({
150
+ subject: message.subject,
151
+ body: message.body,
152
+ bodyHtml,
153
+ senderName: buildSenderLabel(sender),
154
+ sentAtLabel: copy.sentAtLabel,
155
+ viewUrl,
156
+ copy,
157
+ attachmentNames: attachments.map((item) => item.fileName),
158
+ objectLabels: resolveObjectLabels(objects)
159
+ }),
160
+ attachments: resendAttachments
161
+ });
162
+ }
163
+ async function sendMessageEmailToExternal(params) {
164
+ const { message, email, sender, objects, attachments } = params;
165
+ const copy = await buildEmailCopy(message.sentAt ?? /* @__PURE__ */ new Date());
166
+ const bodyHtml = await buildEmailBodyHtml(message);
167
+ const resendAttachments = await mapAttachmentsForEmail(message.id, attachments);
168
+ logDebug("Sending external email via Resend", {
169
+ messageId: message.id,
170
+ email,
171
+ attachmentsCount: resendAttachments.length,
172
+ hasApiKey: Boolean(process.env.RESEND_API_KEY),
173
+ from: process.env.EMAIL_FROM ?? null
174
+ });
175
+ await sendEmail({
176
+ to: email,
177
+ subject: message.subject,
178
+ react: MessageEmail({
179
+ subject: message.subject,
180
+ body: message.body,
181
+ bodyHtml,
182
+ senderName: buildSenderLabel(sender),
183
+ sentAtLabel: copy.sentAtLabel,
184
+ viewUrl: null,
185
+ copy,
186
+ attachmentNames: attachments.map((item) => item.fileName),
187
+ objectLabels: resolveObjectLabels(objects)
188
+ }),
189
+ attachments: resendAttachments
190
+ });
191
+ logDebug("External email sent via Resend", {
192
+ messageId: message.id,
193
+ email
194
+ });
195
+ }
196
+ export {
197
+ createMessageAccessToken,
198
+ sendMessageEmailToExternal,
199
+ sendMessageEmailToRecipient
200
+ };
201
+ //# sourceMappingURL=email-sender.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/messages/lib/email-sender.ts"],
4
+ "sourcesContent": ["import * as React from 'react'\nimport crypto from 'node:crypto'\nimport { promises as fs } from 'fs'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { sendEmail } from '@open-mercato/shared/lib/email/send'\nimport { loadDictionary } from '@open-mercato/shared/lib/i18n/server'\nimport { defaultLocale } from '@open-mercato/shared/lib/i18n/config'\nimport { createFallbackTranslator } from '@open-mercato/shared/lib/i18n/translate'\nimport type { Message, MessageObject } from '../data/entities'\nimport { MessageAccessToken } from '../data/entities'\nimport MessageEmail from '../emails/MessageEmail'\nimport { resolveAttachmentAbsolutePath } from '../../attachments/lib/storage'\nimport type { MessageEmailAttachment } from './attachments'\n\nconst ACCESS_TOKEN_EXPIRY_HOURS = 24 * 7\nconst DEBUG = process.env.MESSAGES_EMAIL_DEBUG === 'true'\nconst MAX_EMAIL_ATTACHMENTS = 10\nconst MAX_TOTAL_ATTACHMENT_BYTES = 20 * 1024 * 1024\n\nexport type SenderIdentity = {\n name: string | null\n email: string | null\n}\n\nfunction logDebug(message: string, details?: Record<string, unknown>) {\n if (!DEBUG) return\n if (details) {\n console.log(`[messages:email-sender] ${message}`, details)\n return\n }\n console.log(`[messages:email-sender] ${message}`)\n}\n\nfunction resolveAppUrl(): string | null {\n const raw = process.env.APP_URL?.trim()\n if (!raw) return null\n return raw.replace(/\\/$/, '')\n}\n\nfunction buildSenderLabel(sender: SenderIdentity): string {\n const name = sender.name?.trim()\n if (name) return name\n const email = sender.email?.trim()\n if (email) return email\n return 'System'\n}\n\nfunction generateAccessToken(): string {\n return crypto.randomBytes(32).toString('hex')\n}\n\nfunction resolveObjectLabels(objects: MessageObject[]): string[] {\n return objects.map((item) => `${item.entityModule}.${item.entityType} (${item.entityId})`)\n}\n\ntype ResendAttachment = {\n filename: string\n content: string\n contentType?: string\n}\n\nasync function mapAttachmentsForEmail(\n messageId: string,\n attachments: MessageEmailAttachment[],\n): Promise<ResendAttachment[]> {\n const resendAttachments: ResendAttachment[] = []\n let totalBytes = 0\n\n for (const attachment of attachments.slice(0, MAX_EMAIL_ATTACHMENTS)) {\n const absolutePath = resolveAttachmentAbsolutePath(\n attachment.partitionCode,\n attachment.storagePath,\n attachment.storageDriver,\n )\n\n let buffer: Buffer\n try {\n buffer = await fs.readFile(absolutePath)\n } catch (error) {\n logDebug('Attachment skipped: file read failed', {\n messageId,\n fileName: attachment.fileName,\n error: error instanceof Error ? error.message : String(error),\n })\n continue\n }\n\n if ((totalBytes + buffer.length) > MAX_TOTAL_ATTACHMENT_BYTES) {\n logDebug('Attachment skipped: total size limit exceeded', {\n messageId,\n fileName: attachment.fileName,\n nextTotalBytes: totalBytes + buffer.length,\n })\n continue\n }\n\n totalBytes += buffer.length\n resendAttachments.push({\n filename: attachment.fileName,\n content: buffer.toString('base64'),\n contentType: attachment.mimeType || undefined,\n })\n }\n\n return resendAttachments\n}\n\nasync function renderMarkdownEmailBody(body: string) {\n const ReactMarkdownModule = await import('react-markdown')\n const remarkGfmModule = await import('remark-gfm')\n const ReactMarkdown =\n (ReactMarkdownModule.default ?? ReactMarkdownModule) as React.ComponentType<{\n remarkPlugins?: unknown\n children?: React.ReactNode\n }>\n const remarkGfmPlugin = remarkGfmModule.default ?? remarkGfmModule\n const { renderToStaticMarkup } = await import('react-dom/server')\n\n return renderToStaticMarkup(\n React.createElement(ReactMarkdown, { remarkPlugins: [remarkGfmPlugin] }, body),\n )\n}\n\nasync function buildEmailBodyHtml(message: Message): Promise<string | undefined> {\n if (message.bodyFormat !== 'markdown') return undefined\n if (!message.body) return undefined\n return renderMarkdownEmailBody(message.body)\n}\n\nasync function buildEmailCopy(sentAt: Date) {\n const dict = await loadDictionary(defaultLocale)\n const t = createFallbackTranslator(dict)\n return {\n preview: t('messages.email.preview', 'You received a message in Open Mercato'),\n heading: t('messages.email.heading', 'New message'),\n from: t('messages.email.from', 'From'),\n sentAt: t('messages.email.sentAt', 'Sent'),\n sentAtLabel: sentAt.toISOString(),\n viewCta: t('messages.email.viewCta', 'View message'),\n attachmentsLabel: t('messages.email.attachments', 'Attachments'),\n objectsLabel: t('messages.email.objects', 'Related records'),\n footer: t('messages.email.footer', 'Open Mercato messages'),\n }\n}\n\nexport async function createMessageAccessToken(\n em: EntityManager,\n messageId: string,\n recipientUserId: string,\n): Promise<string> {\n const token = generateAccessToken()\n const expiresAt = new Date(Date.now() + ACCESS_TOKEN_EXPIRY_HOURS * 60 * 60 * 1000)\n const record = em.create(MessageAccessToken, {\n messageId,\n recipientUserId,\n token,\n expiresAt,\n useCount: 0,\n })\n await em.persistAndFlush(record)\n logDebug('Created access token', {\n messageId,\n recipientUserId,\n expiresAt: expiresAt.toISOString(),\n })\n return token\n}\n\nexport async function sendMessageEmailToRecipient(params: {\n em: EntityManager\n message: Message\n recipientUserId: string\n recipientEmail: string\n sender: SenderIdentity\n objects: MessageObject[]\n attachments: MessageEmailAttachment[]\n}): Promise<void> {\n const { em, message, recipientUserId, recipientEmail, sender, objects, attachments } = params\n const token = await createMessageAccessToken(em, message.id, recipientUserId)\n const appUrl = resolveAppUrl()\n const viewUrl = appUrl ? `${appUrl}/messages/view/${token}` : null\n if (!appUrl) {\n logDebug('APP_URL missing - email link omitted', { messageId: message.id })\n }\n const copy = await buildEmailCopy(message.sentAt ?? new Date())\n const bodyHtml = await buildEmailBodyHtml(message)\n const resendAttachments = await mapAttachmentsForEmail(message.id, attachments)\n logDebug('Sending recipient email via Resend', {\n messageId: message.id,\n recipientUserId,\n recipientEmail,\n hasViewUrl: Boolean(viewUrl),\n attachmentsCount: resendAttachments.length,\n hasApiKey: Boolean(process.env.RESEND_API_KEY),\n from: process.env.EMAIL_FROM ?? null,\n })\n\n await sendEmail({\n to: recipientEmail,\n subject: message.subject,\n react: MessageEmail({\n subject: message.subject,\n body: message.body,\n bodyHtml,\n senderName: buildSenderLabel(sender),\n sentAtLabel: copy.sentAtLabel,\n viewUrl,\n copy,\n attachmentNames: attachments.map((item) => item.fileName),\n objectLabels: resolveObjectLabels(objects),\n }),\n attachments: resendAttachments,\n })\n}\n\nexport async function sendMessageEmailToExternal(params: {\n message: Message\n email: string\n sender: SenderIdentity\n objects: MessageObject[]\n attachments: MessageEmailAttachment[]\n}): Promise<void> {\n const { message, email, sender, objects, attachments } = params\n const copy = await buildEmailCopy(message.sentAt ?? new Date())\n const bodyHtml = await buildEmailBodyHtml(message)\n const resendAttachments = await mapAttachmentsForEmail(message.id, attachments)\n logDebug('Sending external email via Resend', {\n messageId: message.id,\n email,\n attachmentsCount: resendAttachments.length,\n hasApiKey: Boolean(process.env.RESEND_API_KEY),\n from: process.env.EMAIL_FROM ?? null,\n })\n\n await sendEmail({\n to: email,\n subject: message.subject,\n react: MessageEmail({\n subject: message.subject,\n body: message.body,\n bodyHtml,\n senderName: buildSenderLabel(sender),\n sentAtLabel: copy.sentAtLabel,\n viewUrl: null,\n copy,\n attachmentNames: attachments.map((item) => item.fileName),\n objectLabels: resolveObjectLabels(objects),\n }),\n attachments: resendAttachments,\n })\n logDebug('External email sent via Resend', {\n messageId: message.id,\n email,\n })\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }