@open-mercato/core 0.4.5-develop-5191db4ef3 → 0.4.5-develop-033a719bf2

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 (385) 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/customers/backend/customers/deals/[id]/page.js +27 -8
  16. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  17. package/dist/modules/customers/lib/messageObjectPreviews.js +131 -0
  18. package/dist/modules/customers/lib/messageObjectPreviews.js.map +7 -0
  19. package/dist/modules/customers/message-objects.js +71 -0
  20. package/dist/modules/customers/message-objects.js.map +7 -0
  21. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js +51 -0
  22. package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js.map +7 -0
  23. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js +35 -0
  24. package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js.map +7 -0
  25. package/dist/modules/customers/widgets/messages/index.js +7 -0
  26. package/dist/modules/customers/widgets/messages/index.js.map +7 -0
  27. package/dist/modules/messages/acl.js +15 -0
  28. package/dist/modules/messages/acl.js.map +7 -0
  29. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js +92 -0
  30. package/dist/modules/messages/api/[id]/actions/[actionId]/route.js.map +7 -0
  31. package/dist/modules/messages/api/[id]/archive/route.js +120 -0
  32. package/dist/modules/messages/api/[id]/archive/route.js.map +7 -0
  33. package/dist/modules/messages/api/[id]/attachments/route.js +195 -0
  34. package/dist/modules/messages/api/[id]/attachments/route.js.map +7 -0
  35. package/dist/modules/messages/api/[id]/confirmation/route.js +67 -0
  36. package/dist/modules/messages/api/[id]/confirmation/route.js.map +7 -0
  37. package/dist/modules/messages/api/[id]/conversation/archive/route.js +68 -0
  38. package/dist/modules/messages/api/[id]/conversation/archive/route.js.map +7 -0
  39. package/dist/modules/messages/api/[id]/conversation/read/route.js +68 -0
  40. package/dist/modules/messages/api/[id]/conversation/read/route.js.map +7 -0
  41. package/dist/modules/messages/api/[id]/conversation/route.js +68 -0
  42. package/dist/modules/messages/api/[id]/conversation/route.js.map +7 -0
  43. package/dist/modules/messages/api/[id]/forward/route.js +85 -0
  44. package/dist/modules/messages/api/[id]/forward/route.js.map +7 -0
  45. package/dist/modules/messages/api/[id]/forward-preview/route.js +70 -0
  46. package/dist/modules/messages/api/[id]/forward-preview/route.js.map +7 -0
  47. package/dist/modules/messages/api/[id]/read/route.js +120 -0
  48. package/dist/modules/messages/api/[id]/read/route.js.map +7 -0
  49. package/dist/modules/messages/api/[id]/reply/route.js +87 -0
  50. package/dist/modules/messages/api/[id]/reply/route.js.map +7 -0
  51. package/dist/modules/messages/api/[id]/route.js +350 -0
  52. package/dist/modules/messages/api/[id]/route.js.map +7 -0
  53. package/dist/modules/messages/api/object-types/route.js +54 -0
  54. package/dist/modules/messages/api/object-types/route.js.map +7 -0
  55. package/dist/modules/messages/api/openapi.js +261 -0
  56. package/dist/modules/messages/api/openapi.js.map +7 -0
  57. package/dist/modules/messages/api/route.js +262 -0
  58. package/dist/modules/messages/api/route.js.map +7 -0
  59. package/dist/modules/messages/api/token/[token]/route.js +99 -0
  60. package/dist/modules/messages/api/token/[token]/route.js.map +7 -0
  61. package/dist/modules/messages/api/types/route.js +40 -0
  62. package/dist/modules/messages/api/types/route.js.map +7 -0
  63. package/dist/modules/messages/api/unread-count/route.js +43 -0
  64. package/dist/modules/messages/api/unread-count/route.js.map +7 -0
  65. package/dist/modules/messages/backend/messages/[id]/page.js +10 -0
  66. package/dist/modules/messages/backend/messages/[id]/page.js.map +7 -0
  67. package/dist/modules/messages/backend/messages/[id]/page.meta.js +16 -0
  68. package/dist/modules/messages/backend/messages/[id]/page.meta.js.map +7 -0
  69. package/dist/modules/messages/backend/messages/compose/page.js +10 -0
  70. package/dist/modules/messages/backend/messages/compose/page.js.map +7 -0
  71. package/dist/modules/messages/backend/messages/compose/page.meta.js +17 -0
  72. package/dist/modules/messages/backend/messages/compose/page.meta.js.map +7 -0
  73. package/dist/modules/messages/backend/page.js +10 -0
  74. package/dist/modules/messages/backend/page.js.map +7 -0
  75. package/dist/modules/messages/backend/page.meta.js +33 -0
  76. package/dist/modules/messages/backend/page.meta.js.map +7 -0
  77. package/dist/modules/messages/commands/actions.js +265 -0
  78. package/dist/modules/messages/commands/actions.js.map +7 -0
  79. package/dist/modules/messages/commands/attachments.js +217 -0
  80. package/dist/modules/messages/commands/attachments.js.map +7 -0
  81. package/dist/modules/messages/commands/confirmations.js +151 -0
  82. package/dist/modules/messages/commands/confirmations.js.map +7 -0
  83. package/dist/modules/messages/commands/conversation.js +240 -0
  84. package/dist/modules/messages/commands/conversation.js.map +7 -0
  85. package/dist/modules/messages/commands/messages.js +748 -0
  86. package/dist/modules/messages/commands/messages.js.map +7 -0
  87. package/dist/modules/messages/commands/recipients.js +259 -0
  88. package/dist/modules/messages/commands/recipients.js.map +7 -0
  89. package/dist/modules/messages/commands/shared.js +258 -0
  90. package/dist/modules/messages/commands/shared.js.map +7 -0
  91. package/dist/modules/messages/commands/tokens.js +69 -0
  92. package/dist/modules/messages/commands/tokens.js.map +7 -0
  93. package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -0
  94. package/dist/modules/messages/components/ComposeMessagePageClient.js.map +7 -0
  95. package/dist/modules/messages/components/MessageDetailPageClient.js +261 -0
  96. package/dist/modules/messages/components/MessageDetailPageClient.js.map +7 -0
  97. package/dist/modules/messages/components/MessagesInboxPageClient.js +390 -0
  98. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +7 -0
  99. package/dist/modules/messages/components/confirmation/MessageConfirmationActions.js +31 -0
  100. package/dist/modules/messages/components/confirmation/MessageConfirmationActions.js.map +7 -0
  101. package/dist/modules/messages/components/confirmation/MessageConfirmationContent.js +69 -0
  102. package/dist/modules/messages/components/confirmation/MessageConfirmationContent.js.map +7 -0
  103. package/dist/modules/messages/components/defaults/DefaultMessageActions.js +31 -0
  104. package/dist/modules/messages/components/defaults/DefaultMessageActions.js.map +7 -0
  105. package/dist/modules/messages/components/defaults/DefaultMessageContent.js +19 -0
  106. package/dist/modules/messages/components/defaults/DefaultMessageContent.js.map +7 -0
  107. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js +90 -0
  108. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js.map +7 -0
  109. package/dist/modules/messages/components/defaults/MessageRecordObjectDetail.js +86 -0
  110. package/dist/modules/messages/components/defaults/MessageRecordObjectDetail.js.map +7 -0
  111. package/dist/modules/messages/components/defaults/MessageRecordObjectPreview.js +61 -0
  112. package/dist/modules/messages/components/defaults/MessageRecordObjectPreview.js.map +7 -0
  113. package/dist/modules/messages/components/message-detail/detail-panels.js +27 -0
  114. package/dist/modules/messages/components/message-detail/detail-panels.js.map +7 -0
  115. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js +52 -0
  116. package/dist/modules/messages/components/message-detail/hooks/useMessageDetails.js.map +7 -0
  117. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js +289 -0
  118. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsActions.js.map +7 -0
  119. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js +103 -0
  120. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js.map +7 -0
  121. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js +78 -0
  122. package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.js.map +7 -0
  123. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js +94 -0
  124. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js.map +7 -0
  125. package/dist/modules/messages/components/message-detail/panels/MessageHeader.js +110 -0
  126. package/dist/modules/messages/components/message-detail/panels/MessageHeader.js.map +7 -0
  127. package/dist/modules/messages/components/message-detail/panels/MessageListComponent.js +58 -0
  128. package/dist/modules/messages/components/message-detail/panels/MessageListComponent.js.map +7 -0
  129. package/dist/modules/messages/components/message-detail/panels/actions-panel.js +51 -0
  130. package/dist/modules/messages/components/message-detail/panels/actions-panel.js.map +7 -0
  131. package/dist/modules/messages/components/message-detail/panels/attachments-panel.js +66 -0
  132. package/dist/modules/messages/components/message-detail/panels/attachments-panel.js.map +7 -0
  133. package/dist/modules/messages/components/message-detail/panels/body-panel.js +20 -0
  134. package/dist/modules/messages/components/message-detail/panels/body-panel.js.map +7 -0
  135. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js +36 -0
  136. package/dist/modules/messages/components/message-detail/panels/composer-dialogs.js.map +7 -0
  137. package/dist/modules/messages/components/message-detail/panels/dialogs.js +96 -0
  138. package/dist/modules/messages/components/message-detail/panels/dialogs.js.map +7 -0
  139. package/dist/modules/messages/components/message-detail/panels/index.js +25 -0
  140. package/dist/modules/messages/components/message-detail/panels/index.js.map +7 -0
  141. package/dist/modules/messages/components/message-detail/panels/meta-panel.js +14 -0
  142. package/dist/modules/messages/components/message-detail/panels/meta-panel.js.map +7 -0
  143. package/dist/modules/messages/components/message-detail/panels/objects-panel.js +51 -0
  144. package/dist/modules/messages/components/message-detail/panels/objects-panel.js.map +7 -0
  145. package/dist/modules/messages/components/message-detail/panels/thread-panel.js +54 -0
  146. package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +7 -0
  147. package/dist/modules/messages/components/message-detail/types.js +1 -0
  148. package/dist/modules/messages/components/message-detail/types.js.map +7 -0
  149. package/dist/modules/messages/components/message-detail/utils.js +54 -0
  150. package/dist/modules/messages/components/message-detail/utils.js.map +7 -0
  151. package/dist/modules/messages/components/utils/PriorityBadge.js +52 -0
  152. package/dist/modules/messages/components/utils/PriorityBadge.js.map +7 -0
  153. package/dist/modules/messages/components/utils/typeUiRegistry.js +77 -0
  154. package/dist/modules/messages/components/utils/typeUiRegistry.js.map +7 -0
  155. package/dist/modules/messages/data/entities.js +309 -0
  156. package/dist/modules/messages/data/entities.js.map +7 -0
  157. package/dist/modules/messages/data/validators.js +272 -0
  158. package/dist/modules/messages/data/validators.js.map +7 -0
  159. package/dist/modules/messages/emails/MessageEmail.js +108 -0
  160. package/dist/modules/messages/emails/MessageEmail.js.map +7 -0
  161. package/dist/modules/messages/events.js +24 -0
  162. package/dist/modules/messages/events.js.map +7 -0
  163. package/dist/modules/messages/frontend/messages/view/[token]/page.js +247 -0
  164. package/dist/modules/messages/frontend/messages/view/[token]/page.js.map +7 -0
  165. package/dist/modules/messages/frontend/messages/view/[token]/page.meta.js +9 -0
  166. package/dist/modules/messages/frontend/messages/view/[token]/page.meta.js.map +7 -0
  167. package/dist/modules/messages/index.js +21 -0
  168. package/dist/modules/messages/index.js.map +7 -0
  169. package/dist/modules/messages/lib/actions.js +141 -0
  170. package/dist/modules/messages/lib/actions.js.map +7 -0
  171. package/dist/modules/messages/lib/attachments.js +131 -0
  172. package/dist/modules/messages/lib/attachments.js.map +7 -0
  173. package/dist/modules/messages/lib/constants.js +7 -0
  174. package/dist/modules/messages/lib/constants.js.map +7 -0
  175. package/dist/modules/messages/lib/email-sender.js +201 -0
  176. package/dist/modules/messages/lib/email-sender.js.map +7 -0
  177. package/dist/modules/messages/lib/forwarding.js +179 -0
  178. package/dist/modules/messages/lib/forwarding.js.map +7 -0
  179. package/dist/modules/messages/lib/message-objects-registry.js +49 -0
  180. package/dist/modules/messages/lib/message-objects-registry.js.map +7 -0
  181. package/dist/modules/messages/lib/message-types-registry.js +41 -0
  182. package/dist/modules/messages/lib/message-types-registry.js.map +7 -0
  183. package/dist/modules/messages/lib/object-validation.js +20 -0
  184. package/dist/modules/messages/lib/object-validation.js.map +7 -0
  185. package/dist/modules/messages/lib/operationMetadata.js +21 -0
  186. package/dist/modules/messages/lib/operationMetadata.js.map +7 -0
  187. package/dist/modules/messages/lib/priorityUtils.js +61 -0
  188. package/dist/modules/messages/lib/priorityUtils.js.map +7 -0
  189. package/dist/modules/messages/lib/routeHelpers.js +44 -0
  190. package/dist/modules/messages/lib/routeHelpers.js.map +7 -0
  191. package/dist/modules/messages/message-objects.js +7 -0
  192. package/dist/modules/messages/message-objects.js.map +7 -0
  193. package/dist/modules/messages/message-types.js +67 -0
  194. package/dist/modules/messages/message-types.js.map +7 -0
  195. package/dist/modules/messages/migrations/Migration20260213181243.js +31 -0
  196. package/dist/modules/messages/migrations/Migration20260213181243.js.map +7 -0
  197. package/dist/modules/messages/migrations/Migration20260215165126.js +16 -0
  198. package/dist/modules/messages/migrations/Migration20260215165126.js.map +7 -0
  199. package/dist/modules/messages/notifications.js +27 -0
  200. package/dist/modules/messages/notifications.js.map +7 -0
  201. package/dist/modules/messages/setup.js +21 -0
  202. package/dist/modules/messages/setup.js.map +7 -0
  203. package/dist/modules/messages/subscribers/message-notification.js +108 -0
  204. package/dist/modules/messages/subscribers/message-notification.js.map +7 -0
  205. package/dist/modules/messages/workers/send-email.worker.js +253 -0
  206. package/dist/modules/messages/workers/send-email.worker.js.map +7 -0
  207. package/dist/modules/sales/backend/sales/documents/[id]/page.js +30 -11
  208. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  209. package/dist/modules/sales/commands/payments.js +12 -6
  210. package/dist/modules/sales/commands/payments.js.map +2 -2
  211. package/dist/modules/sales/lib/messageObjectPreviews.js +114 -0
  212. package/dist/modules/sales/lib/messageObjectPreviews.js.map +7 -0
  213. package/dist/modules/sales/message-objects.js +57 -0
  214. package/dist/modules/sales/message-objects.js.map +7 -0
  215. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js +51 -0
  216. package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js.map +7 -0
  217. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js +36 -0
  218. package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js.map +7 -0
  219. package/dist/modules/sales/widgets/messages/index.js +7 -0
  220. package/dist/modules/sales/widgets/messages/index.js.map +7 -0
  221. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +55 -1
  222. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  223. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +60 -1
  224. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  225. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +2 -19
  226. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  227. package/dist/modules/staff/components/LeaveRequestDetail.js +112 -0
  228. package/dist/modules/staff/components/LeaveRequestDetail.js.map +7 -0
  229. package/dist/modules/staff/components/LeaveRequestForm.js +3 -1
  230. package/dist/modules/staff/components/LeaveRequestForm.js.map +2 -2
  231. package/dist/modules/staff/components/LeaveRequestPreview.js +43 -0
  232. package/dist/modules/staff/components/LeaveRequestPreview.js.map +7 -0
  233. package/dist/modules/staff/lib/messageObjectPreviews.js +148 -0
  234. package/dist/modules/staff/lib/messageObjectPreviews.js.map +7 -0
  235. package/dist/modules/staff/message-objects.js +104 -0
  236. package/dist/modules/staff/message-objects.js.map +7 -0
  237. package/dist/modules/staff/message-types.js +23 -0
  238. package/dist/modules/staff/message-types.js.map +7 -0
  239. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js +51 -0
  240. package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js.map +7 -0
  241. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js +34 -0
  242. package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js.map +7 -0
  243. package/dist/modules/staff/widgets/messages/index.js +7 -0
  244. package/dist/modules/staff/widgets/messages/index.js.map +7 -0
  245. package/generated/entities/message/index.ts +31 -0
  246. package/generated/entities/message_access_token/index.ts +8 -0
  247. package/generated/entities/message_confirmation/index.ts +9 -0
  248. package/generated/entities/message_object/index.ts +10 -0
  249. package/generated/entities/message_recipient/index.ts +14 -0
  250. package/generated/entities.ids.generated.ts +8 -0
  251. package/generated/entity-fields-registry.ts +10 -0
  252. package/jest.setup.ts +5 -0
  253. package/package.json +2 -2
  254. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +20 -4
  255. package/src/modules/customers/i18n/de.json +4 -0
  256. package/src/modules/customers/i18n/en.json +4 -0
  257. package/src/modules/customers/i18n/es.json +4 -0
  258. package/src/modules/customers/i18n/pl.json +4 -0
  259. package/src/modules/customers/lib/messageObjectPreviews.ts +154 -0
  260. package/src/modules/customers/message-objects.ts +70 -0
  261. package/src/modules/customers/widgets/messages/CustomerMessageObjectDetail.tsx +57 -0
  262. package/src/modules/customers/widgets/messages/CustomerMessageObjectPreview.tsx +49 -0
  263. package/src/modules/customers/widgets/messages/index.ts +2 -0
  264. package/src/modules/messages/acl.ts +11 -0
  265. package/src/modules/messages/api/[id]/actions/[actionId]/route.ts +103 -0
  266. package/src/modules/messages/api/[id]/archive/route.ts +138 -0
  267. package/src/modules/messages/api/[id]/attachments/route.ts +217 -0
  268. package/src/modules/messages/api/[id]/confirmation/route.ts +73 -0
  269. package/src/modules/messages/api/[id]/conversation/archive/route.ts +69 -0
  270. package/src/modules/messages/api/[id]/conversation/read/route.ts +69 -0
  271. package/src/modules/messages/api/[id]/conversation/route.ts +69 -0
  272. package/src/modules/messages/api/[id]/forward/route.ts +87 -0
  273. package/src/modules/messages/api/[id]/forward-preview/route.ts +75 -0
  274. package/src/modules/messages/api/[id]/read/route.ts +138 -0
  275. package/src/modules/messages/api/[id]/reply/route.ts +89 -0
  276. package/src/modules/messages/api/[id]/route.ts +401 -0
  277. package/src/modules/messages/api/object-types/route.ts +54 -0
  278. package/src/modules/messages/api/openapi.ts +261 -0
  279. package/src/modules/messages/api/route.ts +374 -0
  280. package/src/modules/messages/api/token/[token]/route.ts +103 -0
  281. package/src/modules/messages/api/types/route.ts +39 -0
  282. package/src/modules/messages/api/unread-count/route.ts +55 -0
  283. package/src/modules/messages/backend/messages/[id]/page.meta.ts +12 -0
  284. package/src/modules/messages/backend/messages/[id]/page.tsx +12 -0
  285. package/src/modules/messages/backend/messages/compose/page.meta.ts +13 -0
  286. package/src/modules/messages/backend/messages/compose/page.tsx +12 -0
  287. package/src/modules/messages/backend/page.meta.ts +31 -0
  288. package/src/modules/messages/backend/page.tsx +12 -0
  289. package/src/modules/messages/commands/actions.ts +307 -0
  290. package/src/modules/messages/commands/attachments.ts +227 -0
  291. package/src/modules/messages/commands/confirmations.ts +183 -0
  292. package/src/modules/messages/commands/conversation.ts +292 -0
  293. package/src/modules/messages/commands/messages.ts +845 -0
  294. package/src/modules/messages/commands/recipients.ts +281 -0
  295. package/src/modules/messages/commands/shared.ts +350 -0
  296. package/src/modules/messages/commands/tokens.ts +80 -0
  297. package/src/modules/messages/components/ComposeMessagePageClient.tsx +23 -0
  298. package/src/modules/messages/components/MessageDetailPageClient.tsx +287 -0
  299. package/src/modules/messages/components/MessagesInboxPageClient.tsx +469 -0
  300. package/src/modules/messages/components/confirmation/MessageConfirmationActions.tsx +35 -0
  301. package/src/modules/messages/components/confirmation/MessageConfirmationContent.tsx +88 -0
  302. package/src/modules/messages/components/defaults/DefaultMessageActions.tsx +37 -0
  303. package/src/modules/messages/components/defaults/DefaultMessageContent.tsx +21 -0
  304. package/src/modules/messages/components/defaults/DefaultMessageListItem.tsx +102 -0
  305. package/src/modules/messages/components/defaults/MessageRecordObjectDetail.tsx +114 -0
  306. package/src/modules/messages/components/defaults/MessageRecordObjectPreview.tsx +74 -0
  307. package/src/modules/messages/components/message-detail/detail-panels.ts +13 -0
  308. package/src/modules/messages/components/message-detail/hooks/useMessageDetails.ts +56 -0
  309. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsActions.ts +367 -0
  310. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.ts +134 -0
  311. package/src/modules/messages/components/message-detail/hooks/useMessageDetailsQueries.ts +102 -0
  312. package/src/modules/messages/components/message-detail/panels/MainMessageHeader.tsx +108 -0
  313. package/src/modules/messages/components/message-detail/panels/MessageHeader.tsx +144 -0
  314. package/src/modules/messages/components/message-detail/panels/MessageListComponent.tsx +63 -0
  315. package/src/modules/messages/components/message-detail/panels/actions-panel.tsx +66 -0
  316. package/src/modules/messages/components/message-detail/panels/attachments-panel.tsx +86 -0
  317. package/src/modules/messages/components/message-detail/panels/body-panel.tsx +32 -0
  318. package/src/modules/messages/components/message-detail/panels/composer-dialogs.tsx +42 -0
  319. package/src/modules/messages/components/message-detail/panels/dialogs.tsx +107 -0
  320. package/src/modules/messages/components/message-detail/panels/index.ts +11 -0
  321. package/src/modules/messages/components/message-detail/panels/meta-panel.tsx +19 -0
  322. package/src/modules/messages/components/message-detail/panels/objects-panel.tsx +65 -0
  323. package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +65 -0
  324. package/src/modules/messages/components/message-detail/types.ts +114 -0
  325. package/src/modules/messages/components/message-detail/utils.ts +62 -0
  326. package/src/modules/messages/components/utils/PriorityBadge.tsx +63 -0
  327. package/src/modules/messages/components/utils/typeUiRegistry.ts +106 -0
  328. package/src/modules/messages/data/entities.ts +284 -0
  329. package/src/modules/messages/data/validators.ts +297 -0
  330. package/src/modules/messages/emails/MessageEmail.tsx +143 -0
  331. package/src/modules/messages/events.ts +24 -0
  332. package/src/modules/messages/frontend/messages/view/[token]/page.meta.ts +5 -0
  333. package/src/modules/messages/frontend/messages/view/[token]/page.tsx +389 -0
  334. package/src/modules/messages/i18n/de.json +240 -0
  335. package/src/modules/messages/i18n/en.json +240 -0
  336. package/src/modules/messages/i18n/es.json +240 -0
  337. package/src/modules/messages/i18n/pl.json +240 -0
  338. package/src/modules/messages/index.ts +19 -0
  339. package/src/modules/messages/lib/actions.ts +204 -0
  340. package/src/modules/messages/lib/attachments.ts +197 -0
  341. package/src/modules/messages/lib/constants.ts +2 -0
  342. package/src/modules/messages/lib/email-sender.ts +255 -0
  343. package/src/modules/messages/lib/forwarding.ts +240 -0
  344. package/src/modules/messages/lib/message-objects-registry.ts +60 -0
  345. package/src/modules/messages/lib/message-types-registry.ts +48 -0
  346. package/src/modules/messages/lib/object-validation.ts +26 -0
  347. package/src/modules/messages/lib/operationMetadata.ts +43 -0
  348. package/src/modules/messages/lib/priorityUtils.ts +76 -0
  349. package/src/modules/messages/lib/routeHelpers.ts +65 -0
  350. package/src/modules/messages/message-objects.ts +5 -0
  351. package/src/modules/messages/message-types.ts +65 -0
  352. package/src/modules/messages/migrations/.snapshot-open-mercato.json +957 -0
  353. package/src/modules/messages/migrations/Migration20260213181243.ts +34 -0
  354. package/src/modules/messages/migrations/Migration20260215165126.ts +16 -0
  355. package/src/modules/messages/notifications.ts +25 -0
  356. package/src/modules/messages/setup.ts +19 -0
  357. package/src/modules/messages/subscribers/message-notification.ts +138 -0
  358. package/src/modules/messages/workers/send-email.worker.ts +321 -0
  359. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +23 -7
  360. package/src/modules/sales/commands/payments.ts +12 -6
  361. package/src/modules/sales/i18n/de.json +3 -0
  362. package/src/modules/sales/i18n/en.json +3 -0
  363. package/src/modules/sales/i18n/es.json +3 -0
  364. package/src/modules/sales/i18n/pl.json +3 -0
  365. package/src/modules/sales/lib/messageObjectPreviews.ts +150 -0
  366. package/src/modules/sales/message-objects.ts +56 -0
  367. package/src/modules/sales/widgets/messages/SalesDocumentMessageDetail.tsx +57 -0
  368. package/src/modules/sales/widgets/messages/SalesDocumentMessagePreview.tsx +46 -0
  369. package/src/modules/sales/widgets/messages/index.ts +2 -0
  370. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +54 -0
  371. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +58 -0
  372. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +2 -32
  373. package/src/modules/staff/components/LeaveRequestDetail.tsx +135 -0
  374. package/src/modules/staff/components/LeaveRequestForm.tsx +3 -0
  375. package/src/modules/staff/components/LeaveRequestPreview.tsx +74 -0
  376. package/src/modules/staff/i18n/de.json +8 -0
  377. package/src/modules/staff/i18n/en.json +8 -0
  378. package/src/modules/staff/i18n/es.json +8 -0
  379. package/src/modules/staff/i18n/pl.json +8 -0
  380. package/src/modules/staff/lib/messageObjectPreviews.ts +182 -0
  381. package/src/modules/staff/message-objects.ts +102 -0
  382. package/src/modules/staff/message-types.ts +21 -0
  383. package/src/modules/staff/widgets/messages/StaffMessageObjectDetail.tsx +57 -0
  384. package/src/modules/staff/widgets/messages/StaffMessageObjectPreview.tsx +44 -0
  385. package/src/modules/staff/widgets/messages/index.ts +2 -0
@@ -0,0 +1,68 @@
1
+ import { attachOperationMetadataHeader } from "../../../../lib/operationMetadata.js";
2
+ import { resolveMessageContext } from "../../../../lib/routeHelpers.js";
3
+ import {
4
+ conversationMutationResponseSchema,
5
+ errorResponseSchema
6
+ } from "../../../openapi.js";
7
+ const metadata = {
8
+ DELETE: { requireAuth: true, requireFeatures: ["messages.view"] }
9
+ };
10
+ async function DELETE(req, { params }) {
11
+ const { ctx, scope } = await resolveMessageContext(req);
12
+ const commandBus = ctx.container.resolve("commandBus");
13
+ try {
14
+ const { result, logEntry } = await commandBus.execute("messages.conversation.mark_unread_for_actor", {
15
+ input: {
16
+ anchorMessageId: params.id,
17
+ tenantId: scope.tenantId,
18
+ organizationId: scope.organizationId,
19
+ userId: scope.userId
20
+ },
21
+ ctx: {
22
+ container: ctx.container,
23
+ auth: ctx.auth ?? null,
24
+ organizationScope: null,
25
+ selectedOrganizationId: scope.organizationId,
26
+ organizationIds: scope.organizationId ? [scope.organizationId] : null,
27
+ request: req
28
+ }
29
+ });
30
+ const response = Response.json(result);
31
+ attachOperationMetadataHeader(response, logEntry, {
32
+ resourceKind: "messages.conversation",
33
+ resourceId: params.id
34
+ });
35
+ return response;
36
+ } catch (error) {
37
+ if (error instanceof Error) {
38
+ if (error.message === "Message not found") {
39
+ return Response.json({ error: error.message }, { status: 404 });
40
+ }
41
+ if (error.message === "Access denied") {
42
+ return Response.json({ error: error.message }, { status: 403 });
43
+ }
44
+ }
45
+ throw error;
46
+ }
47
+ }
48
+ const openApi = {
49
+ tag: "Messages",
50
+ methods: {
51
+ DELETE: {
52
+ summary: "Mark entire conversation as unread for current actor",
53
+ responses: [
54
+ { status: 200, description: "Conversation marked unread", schema: conversationMutationResponseSchema }
55
+ ],
56
+ errors: [
57
+ { status: 403, description: "Access denied", schema: errorResponseSchema },
58
+ { status: 404, description: "Message not found", schema: errorResponseSchema }
59
+ ]
60
+ }
61
+ }
62
+ };
63
+ export {
64
+ DELETE,
65
+ metadata,
66
+ openApi
67
+ };
68
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../../src/modules/messages/api/%5Bid%5D/conversation/read/route.ts"],
4
+ "sourcesContent": ["import type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { attachOperationMetadataHeader } from '../../../../lib/operationMetadata'\nimport { resolveMessageContext } from '../../../../lib/routeHelpers'\nimport {\n conversationMutationResponseSchema,\n errorResponseSchema,\n} from '../../../openapi'\n\nexport const metadata = {\n DELETE: { requireAuth: true, requireFeatures: ['messages.view'] },\n}\n\nexport async function DELETE(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n\n try {\n const { result, logEntry } = await commandBus.execute('messages.conversation.mark_unread_for_actor', {\n input: {\n anchorMessageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n\n const response = Response.json(result)\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.conversation',\n resourceId: params.id,\n })\n return response\n } catch (error) {\n if (error instanceof Error) {\n if (error.message === 'Message not found') {\n return Response.json({ error: error.message }, { status: 404 })\n }\n if (error.message === 'Access denied') {\n return Response.json({ error: error.message }, { status: 403 })\n }\n }\n throw error\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n DELETE: {\n summary: 'Mark entire conversation as unread for current actor',\n responses: [\n { status: 200, description: 'Conversation marked unread', schema: conversationMutationResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAEA,SAAS,qCAAqC;AAC9C,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAClE;AAEA,eAAsB,OAAO,KAAc,EAAE,OAAO,GAA+B;AACjF,QAAM,EAAE,KAAK,MAAM,IAAI,MAAM,sBAAsB,GAAG;AACtD,QAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AAErD,MAAI;AACF,UAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,WAAW,QAAQ,+CAA+C;AAAA,MACnG,OAAO;AAAA,QACL,iBAAiB,OAAO;AAAA,QACxB,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,QACtB,QAAQ,MAAM;AAAA,MAChB;AAAA,MACA,KAAK;AAAA,QACH,WAAW,IAAI;AAAA,QACf,MAAM,IAAI,QAAQ;AAAA,QAClB,mBAAmB;AAAA,QACnB,wBAAwB,MAAM;AAAA,QAC9B,iBAAiB,MAAM,iBAAiB,CAAC,MAAM,cAAc,IAAI;AAAA,QACjE,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAED,UAAM,WAAW,SAAS,KAAK,MAAM;AACrC,kCAA8B,UAAU,UAAU;AAAA,MAChD,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,IACrB,CAAC;AACD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,UAAI,MAAM,YAAY,qBAAqB;AACzC,eAAO,SAAS,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAChE;AACA,UAAI,MAAM,YAAY,iBAAiB;AACrC,eAAO,SAAS,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAChE;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,8BAA8B,QAAQ,mCAAmC;AAAA,MACvG;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,iBAAiB,QAAQ,oBAAoB;AAAA,QACzE,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,oBAAoB;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,68 @@
1
+ import { attachOperationMetadataHeader } from "../../../lib/operationMetadata.js";
2
+ import { resolveMessageContext } from "../../../lib/routeHelpers.js";
3
+ import {
4
+ conversationMutationResponseSchema,
5
+ errorResponseSchema
6
+ } from "../../openapi.js";
7
+ const metadata = {
8
+ DELETE: { requireAuth: true, requireFeatures: ["messages.view"] }
9
+ };
10
+ async function DELETE(req, { params }) {
11
+ const { ctx, scope } = await resolveMessageContext(req);
12
+ const commandBus = ctx.container.resolve("commandBus");
13
+ try {
14
+ const { result, logEntry } = await commandBus.execute("messages.conversation.delete_for_actor", {
15
+ input: {
16
+ anchorMessageId: params.id,
17
+ tenantId: scope.tenantId,
18
+ organizationId: scope.organizationId,
19
+ userId: scope.userId
20
+ },
21
+ ctx: {
22
+ container: ctx.container,
23
+ auth: ctx.auth ?? null,
24
+ organizationScope: null,
25
+ selectedOrganizationId: scope.organizationId,
26
+ organizationIds: scope.organizationId ? [scope.organizationId] : null,
27
+ request: req
28
+ }
29
+ });
30
+ const response = Response.json(result);
31
+ attachOperationMetadataHeader(response, logEntry, {
32
+ resourceKind: "messages.conversation",
33
+ resourceId: params.id
34
+ });
35
+ return response;
36
+ } catch (error) {
37
+ if (error instanceof Error) {
38
+ if (error.message === "Message not found") {
39
+ return Response.json({ error: error.message }, { status: 404 });
40
+ }
41
+ if (error.message === "Access denied") {
42
+ return Response.json({ error: error.message }, { status: 403 });
43
+ }
44
+ }
45
+ throw error;
46
+ }
47
+ }
48
+ const openApi = {
49
+ tag: "Messages",
50
+ methods: {
51
+ DELETE: {
52
+ summary: "Delete conversation for current actor",
53
+ responses: [
54
+ { status: 200, description: "Conversation deleted", schema: conversationMutationResponseSchema }
55
+ ],
56
+ errors: [
57
+ { status: 403, description: "Access denied", schema: errorResponseSchema },
58
+ { status: 404, description: "Message not found", schema: errorResponseSchema }
59
+ ]
60
+ }
61
+ }
62
+ };
63
+ export {
64
+ DELETE,
65
+ metadata,
66
+ openApi
67
+ };
68
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/messages/api/%5Bid%5D/conversation/route.ts"],
4
+ "sourcesContent": ["import type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { attachOperationMetadataHeader } from '../../../lib/operationMetadata'\nimport { resolveMessageContext } from '../../../lib/routeHelpers'\nimport {\n conversationMutationResponseSchema,\n errorResponseSchema,\n} from '../../openapi'\n\nexport const metadata = {\n DELETE: { requireAuth: true, requireFeatures: ['messages.view'] },\n}\n\nexport async function DELETE(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n\n try {\n const { result, logEntry } = await commandBus.execute('messages.conversation.delete_for_actor', {\n input: {\n anchorMessageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n\n const response = Response.json(result)\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.conversation',\n resourceId: params.id,\n })\n return response\n } catch (error) {\n if (error instanceof Error) {\n if (error.message === 'Message not found') {\n return Response.json({ error: error.message }, { status: 404 })\n }\n if (error.message === 'Access denied') {\n return Response.json({ error: error.message }, { status: 403 })\n }\n }\n throw error\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n DELETE: {\n summary: 'Delete conversation for current actor',\n responses: [\n { status: 200, description: 'Conversation deleted', schema: conversationMutationResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAEA,SAAS,qCAAqC;AAC9C,SAAS,6BAA6B;AACtC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAClE;AAEA,eAAsB,OAAO,KAAc,EAAE,OAAO,GAA+B;AACjF,QAAM,EAAE,KAAK,MAAM,IAAI,MAAM,sBAAsB,GAAG;AACtD,QAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AAErD,MAAI;AACF,UAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,WAAW,QAAQ,0CAA0C;AAAA,MAC9F,OAAO;AAAA,QACL,iBAAiB,OAAO;AAAA,QACxB,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,QACtB,QAAQ,MAAM;AAAA,MAChB;AAAA,MACA,KAAK;AAAA,QACH,WAAW,IAAI;AAAA,QACf,MAAM,IAAI,QAAQ;AAAA,QAClB,mBAAmB;AAAA,QACnB,wBAAwB,MAAM;AAAA,QAC9B,iBAAiB,MAAM,iBAAiB,CAAC,MAAM,cAAc,IAAI;AAAA,QACjE,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAED,UAAM,WAAW,SAAS,KAAK,MAAM;AACrC,kCAA8B,UAAU,UAAU;AAAA,MAChD,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,IACrB,CAAC;AACD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,UAAI,MAAM,YAAY,qBAAqB;AACzC,eAAO,SAAS,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAChE;AACA,UAAI,MAAM,YAAY,iBAAiB;AACrC,eAAO,SAAS,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAChE;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,wBAAwB,QAAQ,mCAAmC;AAAA,MACjG;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,iBAAiB,QAAQ,oBAAoB;AAAA,QACzE,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,oBAAoB;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,85 @@
1
+ import { forwardMessageSchema } from "../../../data/validators.js";
2
+ import { attachOperationMetadataHeader } from "../../../lib/operationMetadata.js";
3
+ import { canUseMessageEmailFeature, parseRequestBodySafe, resolveMessageContext } from "../../../lib/routeHelpers.js";
4
+ import { forwardResponseSchema, forwardMessageSchema as forwardSchema } from "../../openapi.js";
5
+ const metadata = {
6
+ POST: { requireAuth: true, requireFeatures: ["messages.compose"] }
7
+ };
8
+ async function POST(req, { params }) {
9
+ const { ctx, scope } = await resolveMessageContext(req);
10
+ const commandBus = ctx.container.resolve("commandBus");
11
+ const body = await parseRequestBodySafe(req);
12
+ const input = forwardMessageSchema.parse(body);
13
+ if (input.sendViaEmail && !await canUseMessageEmailFeature(ctx, scope)) {
14
+ return Response.json({ error: "Missing feature: messages.email" }, { status: 403 });
15
+ }
16
+ let commandResult;
17
+ try {
18
+ commandResult = await commandBus.execute("messages.messages.forward", {
19
+ input: {
20
+ ...input,
21
+ messageId: params.id,
22
+ tenantId: scope.tenantId,
23
+ organizationId: scope.organizationId,
24
+ userId: scope.userId
25
+ },
26
+ ctx: {
27
+ container: ctx.container,
28
+ auth: ctx.auth ?? null,
29
+ organizationScope: null,
30
+ selectedOrganizationId: scope.organizationId,
31
+ organizationIds: scope.organizationId ? [scope.organizationId] : null,
32
+ request: req
33
+ }
34
+ });
35
+ } catch (error) {
36
+ if (error instanceof Error) {
37
+ if (error.message === "Message not found") {
38
+ return Response.json({ error: "Message not found" }, { status: 404 });
39
+ }
40
+ if (error.message === "Access denied") {
41
+ return Response.json({ error: "Access denied" }, { status: 403 });
42
+ }
43
+ if (error.message === "Forward is not allowed for this message type") {
44
+ return Response.json({ error: "Forward is not allowed for this message type" }, { status: 409 });
45
+ }
46
+ if (error.message === "Forward body exceeds maximum length") {
47
+ return Response.json({ error: "Forward body exceeds maximum length" }, { status: 413 });
48
+ }
49
+ }
50
+ throw error;
51
+ }
52
+ const newMessageId = commandResult.result.id;
53
+ const response = Response.json({ id: newMessageId }, { status: 201 });
54
+ attachOperationMetadataHeader(response, commandResult.logEntry, {
55
+ resourceKind: "messages.message",
56
+ resourceId: newMessageId
57
+ });
58
+ return response;
59
+ }
60
+ const openApi = {
61
+ tag: "Messages",
62
+ methods: {
63
+ POST: {
64
+ summary: "Forward a message and optionally include attachments from the forwarded conversation slice",
65
+ requestBody: { schema: forwardSchema },
66
+ responses: [
67
+ {
68
+ status: 201,
69
+ description: "Message forwarded",
70
+ schema: forwardResponseSchema
71
+ },
72
+ { status: 403, description: "Access denied" },
73
+ { status: 404, description: "Message not found" },
74
+ { status: 409, description: "Forward not allowed for message type" },
75
+ { status: 413, description: "Forward body exceeds maximum length" }
76
+ ]
77
+ }
78
+ }
79
+ };
80
+ export {
81
+ POST,
82
+ metadata,
83
+ openApi
84
+ };
85
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/messages/api/%5Bid%5D/forward/route.ts"],
4
+ "sourcesContent": ["import type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport { forwardMessageSchema } from '../../../data/validators'\nimport { attachOperationMetadataHeader, OperationLogEntryLike } from '../../../lib/operationMetadata'\nimport { canUseMessageEmailFeature, parseRequestBodySafe, resolveMessageContext } from '../../../lib/routeHelpers'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { forwardResponseSchema, forwardMessageSchema as forwardSchema } from '../../openapi'\nimport { MessageCommandExecuteResult } from '../../../commands/shared'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['messages.compose'] },\n}\n\nexport async function POST(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n const body = await parseRequestBodySafe(req)\n const input = forwardMessageSchema.parse(body)\n if (input.sendViaEmail && !(await canUseMessageEmailFeature(ctx, scope))) {\n return Response.json({ error: 'Missing feature: messages.email' }, { status: 403 })\n }\n\n let commandResult: { result: MessageCommandExecuteResult; logEntry: unknown }\n try {\n commandResult = await commandBus.execute<unknown, MessageCommandExecuteResult>('messages.messages.forward', {\n input: {\n ...input,\n messageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n } catch (error) {\n if (error instanceof Error) {\n if (error.message === 'Message not found') {\n return Response.json({ error: 'Message not found' }, { status: 404 })\n }\n if (error.message === 'Access denied') {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n if (error.message === 'Forward is not allowed for this message type') {\n return Response.json({ error: 'Forward is not allowed for this message type' }, { status: 409 })\n }\n if (error.message === 'Forward body exceeds maximum length') {\n return Response.json({ error: 'Forward body exceeds maximum length' }, { status: 413 })\n }\n }\n throw error\n }\n const newMessageId = commandResult.result.id\n\n const response = Response.json({ id: newMessageId }, { status: 201 })\n attachOperationMetadataHeader(response, commandResult.logEntry as OperationLogEntryLike, {\n resourceKind: 'messages.message',\n resourceId: newMessageId,\n })\n return response\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n POST: {\n summary: 'Forward a message and optionally include attachments from the forwarded conversation slice',\n requestBody: { schema: forwardSchema },\n responses: [\n {\n status: 201,\n description: 'Message forwarded',\n schema: forwardResponseSchema,\n },\n { status: 403, description: 'Access denied' },\n { status: 404, description: 'Message not found' },\n { status: 409, description: 'Forward not allowed for message type' },\n { status: 413, description: 'Forward body exceeds maximum length' },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AACA,SAAS,4BAA4B;AACrC,SAAS,qCAA4D;AACrE,SAAS,2BAA2B,sBAAsB,6BAA6B;AAEvF,SAAS,uBAAuB,wBAAwB,qBAAqB;AAGtE,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,kBAAkB,EAAE;AACnE;AAEA,eAAsB,KAAK,KAAc,EAAE,OAAO,GAA+B;AAC/E,QAAM,EAAE,KAAK,MAAM,IAAI,MAAM,sBAAsB,GAAG;AACtD,QAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,QAAM,OAAO,MAAM,qBAAqB,GAAG;AAC3C,QAAM,QAAQ,qBAAqB,MAAM,IAAI;AAC7C,MAAI,MAAM,gBAAgB,CAAE,MAAM,0BAA0B,KAAK,KAAK,GAAI;AACxE,WAAO,SAAS,KAAK,EAAE,OAAO,kCAAkC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACpF;AAEA,MAAI;AACJ,MAAI;AACF,oBAAgB,MAAM,WAAW,QAA8C,6BAA6B;AAAA,MAC1G,OAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW,OAAO;AAAA,QAClB,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,QACtB,QAAQ,MAAM;AAAA,MAChB;AAAA,MACA,KAAK;AAAA,QACH,WAAW,IAAI;AAAA,QACf,MAAM,IAAI,QAAQ;AAAA,QAClB,mBAAmB;AAAA,QACnB,wBAAwB,MAAM;AAAA,QAC9B,iBAAiB,MAAM,iBAAiB,CAAC,MAAM,cAAc,IAAI;AAAA,QACjE,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,UAAI,MAAM,YAAY,qBAAqB;AACzC,eAAO,SAAS,KAAK,EAAE,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MACtE;AACA,UAAI,MAAM,YAAY,iBAAiB;AACrC,eAAO,SAAS,KAAK,EAAE,OAAO,gBAAgB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAClE;AACA,UAAI,MAAM,YAAY,gDAAgD;AACpE,eAAO,SAAS,KAAK,EAAE,OAAO,+CAA+C,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MACjG;AACA,UAAI,MAAM,YAAY,uCAAuC;AAC3D,eAAO,SAAS,KAAK,EAAE,OAAO,sCAAsC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MACxF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACA,QAAM,eAAe,cAAc,OAAO;AAE1C,QAAM,WAAW,SAAS,KAAK,EAAE,IAAI,aAAa,GAAG,EAAE,QAAQ,IAAI,CAAC;AACpE,gCAA8B,UAAU,cAAc,UAAmC;AAAA,IACvF,cAAc;AAAA,IACd,YAAY;AAAA,EACd,CAAC;AACD,SAAO;AACT;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa,EAAE,QAAQ,cAAc;AAAA,MACrC,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ;AAAA,QACV;AAAA,QACA,EAAE,QAAQ,KAAK,aAAa,gBAAgB;AAAA,QAC5C,EAAE,QAAQ,KAAK,aAAa,oBAAoB;AAAA,QAChD,EAAE,QAAQ,KAAK,aAAa,uCAAuC;AAAA,QACnE,EAAE,QAAQ,KAAK,aAAa,sCAAsC;AAAA,MACpE;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,70 @@
1
+ import { Message, MessageRecipient } from "../../../data/entities.js";
2
+ import { buildForwardPreview } from "../../../lib/forwarding.js";
3
+ import { hasOrganizationAccess, resolveMessageContext } from "../../../lib/routeHelpers.js";
4
+ import {
5
+ errorResponseSchema,
6
+ forwardPreviewResponseSchema
7
+ } from "../../openapi.js";
8
+ const metadata = {
9
+ GET: { requireAuth: true, requireFeatures: ["messages.compose"] }
10
+ };
11
+ async function GET(req, { params }) {
12
+ const { ctx, scope } = await resolveMessageContext(req);
13
+ const em = ctx.container.resolve("em").fork();
14
+ const message = await em.findOne(Message, {
15
+ id: params.id,
16
+ tenantId: scope.tenantId,
17
+ deletedAt: null
18
+ });
19
+ if (!message) {
20
+ return Response.json({ error: "Message not found" }, { status: 404 });
21
+ }
22
+ if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {
23
+ return Response.json({ error: "Access denied" }, { status: 403 });
24
+ }
25
+ const recipient = await em.findOne(MessageRecipient, {
26
+ messageId: params.id,
27
+ recipientUserId: scope.userId,
28
+ deletedAt: null
29
+ });
30
+ const isSender = message.senderUserId === scope.userId;
31
+ const isRecipient = Boolean(recipient);
32
+ if (!isSender && !isRecipient) {
33
+ return Response.json({ error: "Access denied" }, { status: 403 });
34
+ }
35
+ try {
36
+ const preview = await buildForwardPreview(em, {
37
+ tenantId: scope.tenantId,
38
+ organizationId: scope.organizationId,
39
+ userId: scope.userId
40
+ }, message);
41
+ return Response.json(preview);
42
+ } catch (error) {
43
+ if (error instanceof Error && error.message === "Forward body exceeds maximum length") {
44
+ return Response.json({ error: error.message }, { status: 413 });
45
+ }
46
+ throw error;
47
+ }
48
+ }
49
+ const openApi = {
50
+ tag: "Messages",
51
+ methods: {
52
+ GET: {
53
+ summary: "Get forward preview for a message",
54
+ responses: [
55
+ { status: 200, description: "Forward preview generated", schema: forwardPreviewResponseSchema }
56
+ ],
57
+ errors: [
58
+ { status: 403, description: "Access denied", schema: errorResponseSchema },
59
+ { status: 404, description: "Message not found", schema: errorResponseSchema },
60
+ { status: 413, description: "Forward body exceeds maximum length", schema: errorResponseSchema }
61
+ ]
62
+ }
63
+ }
64
+ };
65
+ export {
66
+ GET,
67
+ metadata,
68
+ openApi
69
+ };
70
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/messages/api/%5Bid%5D/forward-preview/route.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { Message, MessageRecipient } from '../../../data/entities'\nimport { buildForwardPreview } from '../../../lib/forwarding'\nimport { hasOrganizationAccess, resolveMessageContext } from '../../../lib/routeHelpers'\nimport {\n errorResponseSchema,\n forwardPreviewResponseSchema,\n} from '../../openapi'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['messages.compose'] },\n}\n\nexport async function GET(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const message = await em.findOne(Message, {\n id: params.id,\n tenantId: scope.tenantId,\n deletedAt: null,\n })\n\n if (!message) {\n return Response.json({ error: 'Message not found' }, { status: 404 })\n }\n\n if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n const recipient = await em.findOne(MessageRecipient, {\n messageId: params.id,\n recipientUserId: scope.userId,\n deletedAt: null,\n })\n\n const isSender = message.senderUserId === scope.userId\n const isRecipient = Boolean(recipient)\n if (!isSender && !isRecipient) {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n\n try {\n const preview = await buildForwardPreview(em, {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n }, message)\n return Response.json(preview)\n } catch (error) {\n if (error instanceof Error && error.message === 'Forward body exceeds maximum length') {\n return Response.json({ error: error.message }, { status: 413 })\n }\n throw error\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n GET: {\n summary: 'Get forward preview for a message',\n responses: [\n { status: 200, description: 'Forward preview generated', schema: forwardPreviewResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n { status: 413, description: 'Forward body exceeds maximum length', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAEA,SAAS,SAAS,wBAAwB;AAC1C,SAAS,2BAA2B;AACpC,SAAS,uBAAuB,6BAA6B;AAC7D;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,kBAAkB,EAAE;AAClE;AAEA,eAAsB,IAAI,KAAc,EAAE,OAAO,GAA+B;AAC9E,QAAM,EAAE,KAAK,MAAM,IAAI,MAAM,sBAAsB,GAAG;AACtD,QAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAE/D,QAAM,UAAU,MAAM,GAAG,QAAQ,SAAS;AAAA,IACxC,IAAI,OAAO;AAAA,IACX,UAAU,MAAM;AAAA,IAChB,WAAW;AAAA,EACb,CAAC;AAED,MAAI,CAAC,SAAS;AACZ,WAAO,SAAS,KAAK,EAAE,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACtE;AAEA,MAAI,CAAC,sBAAsB,MAAM,gBAAgB,QAAQ,cAAc,GAAG;AACxE,WAAO,SAAS,KAAK,EAAE,OAAO,gBAAgB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAClE;AAEA,QAAM,YAAY,MAAM,GAAG,QAAQ,kBAAkB;AAAA,IACnD,WAAW,OAAO;AAAA,IAClB,iBAAiB,MAAM;AAAA,IACvB,WAAW;AAAA,EACb,CAAC;AAED,QAAM,WAAW,QAAQ,iBAAiB,MAAM;AAChD,QAAM,cAAc,QAAQ,SAAS;AACrC,MAAI,CAAC,YAAY,CAAC,aAAa;AAC7B,WAAO,SAAS,KAAK,EAAE,OAAO,gBAAgB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAClE;AAEA,MAAI;AACF,UAAM,UAAU,MAAM,oBAAoB,IAAI;AAAA,MAC5C,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,QAAQ,MAAM;AAAA,IAChB,GAAG,OAAO;AACV,WAAO,SAAS,KAAK,OAAO;AAAA,EAC9B,SAAS,OAAO;AACd,QAAI,iBAAiB,SAAS,MAAM,YAAY,uCAAuC;AACrF,aAAO,SAAS,KAAK,EAAE,OAAO,MAAM,QAAQ,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAChE;AACA,UAAM;AAAA,EACR;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,6BAA6B,QAAQ,6BAA6B;AAAA,MAChG;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,iBAAiB,QAAQ,oBAAoB;AAAA,QACzE,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,oBAAoB;AAAA,QAC7E,EAAE,QAAQ,KAAK,aAAa,uCAAuC,QAAQ,oBAAoB;AAAA,MACjG;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,120 @@
1
+ import { Message, MessageRecipient } from "../../../data/entities.js";
2
+ import { attachOperationMetadataHeader } from "../../../lib/operationMetadata.js";
3
+ import { hasOrganizationAccess, resolveMessageContext } from "../../../lib/routeHelpers.js";
4
+ import { errorResponseSchema, okResponseSchema } from "../../openapi.js";
5
+ const metadata = {
6
+ PUT: { requireAuth: true, requireFeatures: ["messages.view"] },
7
+ DELETE: { requireAuth: true, requireFeatures: ["messages.view"] }
8
+ };
9
+ async function resolveRecipientContext(req, id) {
10
+ const { ctx, scope } = await resolveMessageContext(req);
11
+ const em = ctx.container.resolve("em").fork();
12
+ const message = await em.findOne(Message, {
13
+ id,
14
+ tenantId: scope.tenantId,
15
+ deletedAt: null
16
+ });
17
+ if (!message) {
18
+ return { response: Response.json({ error: "Message not found" }, { status: 404 }) };
19
+ }
20
+ if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {
21
+ return { response: Response.json({ error: "Access denied" }, { status: 403 }) };
22
+ }
23
+ const recipient = await em.findOne(MessageRecipient, {
24
+ messageId: id,
25
+ recipientUserId: scope.userId,
26
+ deletedAt: null
27
+ });
28
+ if (!recipient) {
29
+ return { response: Response.json({ error: "Access denied" }, { status: 403 }) };
30
+ }
31
+ return { ctx, scope, em, recipient };
32
+ }
33
+ async function PUT(req, { params }) {
34
+ const context = await resolveRecipientContext(req, params.id);
35
+ if ("response" in context) return context.response;
36
+ const { ctx, scope } = context;
37
+ const commandBus = ctx.container.resolve("commandBus");
38
+ const { logEntry } = await commandBus.execute("messages.recipients.mark_read", {
39
+ input: {
40
+ messageId: params.id,
41
+ tenantId: scope.tenantId,
42
+ organizationId: scope.organizationId,
43
+ userId: scope.userId
44
+ },
45
+ ctx: {
46
+ container: ctx.container,
47
+ auth: ctx.auth ?? null,
48
+ organizationScope: null,
49
+ selectedOrganizationId: scope.organizationId,
50
+ organizationIds: scope.organizationId ? [scope.organizationId] : null,
51
+ request: req
52
+ }
53
+ });
54
+ const response = Response.json({ ok: true });
55
+ attachOperationMetadataHeader(response, logEntry, {
56
+ resourceKind: "messages.message",
57
+ resourceId: params.id
58
+ });
59
+ return response;
60
+ }
61
+ async function DELETE(req, { params }) {
62
+ const context = await resolveRecipientContext(req, params.id);
63
+ if ("response" in context) return context.response;
64
+ const { ctx, scope } = context;
65
+ const commandBus = ctx.container.resolve("commandBus");
66
+ const { logEntry } = await commandBus.execute("messages.recipients.mark_unread", {
67
+ input: {
68
+ messageId: params.id,
69
+ tenantId: scope.tenantId,
70
+ organizationId: scope.organizationId,
71
+ userId: scope.userId
72
+ },
73
+ ctx: {
74
+ container: ctx.container,
75
+ auth: ctx.auth ?? null,
76
+ organizationScope: null,
77
+ selectedOrganizationId: scope.organizationId,
78
+ organizationIds: scope.organizationId ? [scope.organizationId] : null,
79
+ request: req
80
+ }
81
+ });
82
+ const response = Response.json({ ok: true });
83
+ attachOperationMetadataHeader(response, logEntry, {
84
+ resourceKind: "messages.message",
85
+ resourceId: params.id
86
+ });
87
+ return response;
88
+ }
89
+ const openApi = {
90
+ tag: "Messages",
91
+ methods: {
92
+ PUT: {
93
+ summary: "Mark message as read",
94
+ responses: [
95
+ { status: 200, description: "Message marked read", schema: okResponseSchema }
96
+ ],
97
+ errors: [
98
+ { status: 403, description: "Access denied", schema: errorResponseSchema },
99
+ { status: 404, description: "Message not found", schema: errorResponseSchema }
100
+ ]
101
+ },
102
+ DELETE: {
103
+ summary: "Mark message as unread",
104
+ responses: [
105
+ { status: 200, description: "Message marked unread", schema: okResponseSchema }
106
+ ],
107
+ errors: [
108
+ { status: 403, description: "Access denied", schema: errorResponseSchema },
109
+ { status: 404, description: "Message not found", schema: errorResponseSchema }
110
+ ]
111
+ }
112
+ }
113
+ };
114
+ export {
115
+ DELETE,
116
+ PUT,
117
+ metadata,
118
+ openApi
119
+ };
120
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/messages/api/%5Bid%5D/read/route.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/core'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { Message, MessageRecipient } from '../../../data/entities'\nimport { attachOperationMetadataHeader } from '../../../lib/operationMetadata'\nimport { hasOrganizationAccess, resolveMessageContext } from '../../../lib/routeHelpers'\nimport type { MessageScope } from '../../../lib/routeHelpers'\nimport { errorResponseSchema, okResponseSchema } from '../../openapi'\n\nexport const metadata = {\n PUT: { requireAuth: true, requireFeatures: ['messages.view'] },\n DELETE: { requireAuth: true, requireFeatures: ['messages.view'] },\n}\n\ntype ResolvedCtx = Awaited<ReturnType<typeof resolveMessageContext>>['ctx']\n\nasync function resolveRecipientContext(\n req: Request,\n id: string,\n): Promise<\n | { ctx: ResolvedCtx; scope: MessageScope; em: EntityManager; recipient: MessageRecipient }\n | { response: Response }\n> {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const message = await em.findOne(Message, {\n id,\n tenantId: scope.tenantId,\n deletedAt: null,\n })\n\n if (!message) {\n return { response: Response.json({ error: 'Message not found' }, { status: 404 }) }\n }\n\n if (!hasOrganizationAccess(scope.organizationId, message.organizationId)) {\n return { response: Response.json({ error: 'Access denied' }, { status: 403 }) }\n }\n\n const recipient = await em.findOne(MessageRecipient, {\n messageId: id,\n recipientUserId: scope.userId,\n deletedAt: null,\n })\n\n if (!recipient) {\n return { response: Response.json({ error: 'Access denied' }, { status: 403 }) }\n }\n\n return { ctx, scope, em, recipient }\n}\n\nexport async function PUT(req: Request, { params }: { params: { id: string } }) {\n const context = await resolveRecipientContext(req, params.id)\n if ('response' in context) return context.response\n const { ctx, scope } = context\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n const { logEntry } = await commandBus.execute('messages.recipients.mark_read', {\n input: {\n messageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n\n const response = Response.json({ ok: true })\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.message',\n resourceId: params.id,\n })\n return response\n}\n\nexport async function DELETE(req: Request, { params }: { params: { id: string } }) {\n const context = await resolveRecipientContext(req, params.id)\n if ('response' in context) return context.response\n const { ctx, scope } = context\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n const { logEntry } = await commandBus.execute('messages.recipients.mark_unread', {\n input: {\n messageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n\n const response = Response.json({ ok: true })\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.message',\n resourceId: params.id,\n })\n return response\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n PUT: {\n summary: 'Mark message as read',\n responses: [\n { status: 200, description: 'Message marked read', schema: okResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n DELETE: {\n summary: 'Mark message as unread',\n responses: [\n { status: 200, description: 'Message marked unread', schema: okResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAGA,SAAS,SAAS,wBAAwB;AAC1C,SAAS,qCAAqC;AAC9C,SAAS,uBAAuB,6BAA6B;AAE7D,SAAS,qBAAqB,wBAAwB;AAE/C,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAAA,EAC7D,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAClE;AAIA,eAAe,wBACb,KACA,IAIA;AACA,QAAM,EAAE,KAAK,MAAM,IAAI,MAAM,sBAAsB,GAAG;AACtD,QAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAE/D,QAAM,UAAU,MAAM,GAAG,QAAQ,SAAS;AAAA,IACxC;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,WAAW;AAAA,EACb,CAAC;AAED,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,UAAU,SAAS,KAAK,EAAE,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC,EAAE;AAAA,EACpF;AAEA,MAAI,CAAC,sBAAsB,MAAM,gBAAgB,QAAQ,cAAc,GAAG;AACxE,WAAO,EAAE,UAAU,SAAS,KAAK,EAAE,OAAO,gBAAgB,GAAG,EAAE,QAAQ,IAAI,CAAC,EAAE;AAAA,EAChF;AAEA,QAAM,YAAY,MAAM,GAAG,QAAQ,kBAAkB;AAAA,IACnD,WAAW;AAAA,IACX,iBAAiB,MAAM;AAAA,IACvB,WAAW;AAAA,EACb,CAAC;AAED,MAAI,CAAC,WAAW;AACd,WAAO,EAAE,UAAU,SAAS,KAAK,EAAE,OAAO,gBAAgB,GAAG,EAAE,QAAQ,IAAI,CAAC,EAAE;AAAA,EAChF;AAEA,SAAO,EAAE,KAAK,OAAO,IAAI,UAAU;AACrC;AAEA,eAAsB,IAAI,KAAc,EAAE,OAAO,GAA+B;AAC9E,QAAM,UAAU,MAAM,wBAAwB,KAAK,OAAO,EAAE;AAC5D,MAAI,cAAc,QAAS,QAAO,QAAQ;AAC1C,QAAM,EAAE,KAAK,MAAM,IAAI;AACvB,QAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,QAAM,EAAE,SAAS,IAAI,MAAM,WAAW,QAAQ,iCAAiC;AAAA,IAC7E,OAAO;AAAA,MACL,WAAW,OAAO;AAAA,MAClB,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,QAAQ,MAAM;AAAA,IAChB;AAAA,IACA,KAAK;AAAA,MACH,WAAW,IAAI;AAAA,MACf,MAAM,IAAI,QAAQ;AAAA,MAClB,mBAAmB;AAAA,MACnB,wBAAwB,MAAM;AAAA,MAC9B,iBAAiB,MAAM,iBAAiB,CAAC,MAAM,cAAc,IAAI;AAAA,MACjE,SAAS;AAAA,IACX;AAAA,EACF,CAAC;AAED,QAAM,WAAW,SAAS,KAAK,EAAE,IAAI,KAAK,CAAC;AAC3C,gCAA8B,UAAU,UAAU;AAAA,IAChD,cAAc;AAAA,IACd,YAAY,OAAO;AAAA,EACrB,CAAC;AACD,SAAO;AACT;AAEA,eAAsB,OAAO,KAAc,EAAE,OAAO,GAA+B;AACjF,QAAM,UAAU,MAAM,wBAAwB,KAAK,OAAO,EAAE;AAC5D,MAAI,cAAc,QAAS,QAAO,QAAQ;AAC1C,QAAM,EAAE,KAAK,MAAM,IAAI;AACvB,QAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,QAAM,EAAE,SAAS,IAAI,MAAM,WAAW,QAAQ,mCAAmC;AAAA,IAC/E,OAAO;AAAA,MACL,WAAW,OAAO;AAAA,MAClB,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,QAAQ,MAAM;AAAA,IAChB;AAAA,IACA,KAAK;AAAA,MACH,WAAW,IAAI;AAAA,MACf,MAAM,IAAI,QAAQ;AAAA,MAClB,mBAAmB;AAAA,MACnB,wBAAwB,MAAM;AAAA,MAC9B,iBAAiB,MAAM,iBAAiB,CAAC,MAAM,cAAc,IAAI;AAAA,MACjE,SAAS;AAAA,IACX;AAAA,EACF,CAAC;AAED,QAAM,WAAW,SAAS,KAAK,EAAE,IAAI,KAAK,CAAC;AAC3C,gCAA8B,UAAU,UAAU;AAAA,IAChD,cAAc;AAAA,IACd,YAAY,OAAO;AAAA,EACrB,CAAC;AACD,SAAO;AACT;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,uBAAuB,QAAQ,iBAAiB;AAAA,MAC9E;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,iBAAiB,QAAQ,oBAAoB;AAAA,QACzE,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,oBAAoB;AAAA,MAC/E;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,yBAAyB,QAAQ,iBAAiB;AAAA,MAChF;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,iBAAiB,QAAQ,oBAAoB;AAAA,QACzE,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,oBAAoB;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,87 @@
1
+ import { replyMessageSchema } from "../../../data/validators.js";
2
+ import { attachOperationMetadataHeader } from "../../../lib/operationMetadata.js";
3
+ import { canUseMessageEmailFeature, resolveMessageContext } from "../../../lib/routeHelpers.js";
4
+ import {
5
+ errorResponseSchema,
6
+ forwardResponseSchema,
7
+ replyMessageSchema as replyOpenApiSchema
8
+ } from "../../openapi.js";
9
+ const metadata = {
10
+ POST: { requireAuth: true, requireFeatures: ["messages.compose"] }
11
+ };
12
+ async function POST(req, { params }) {
13
+ const { ctx, scope } = await resolveMessageContext(req);
14
+ const commandBus = ctx.container.resolve("commandBus");
15
+ const body = await req.json().catch(() => ({}));
16
+ const input = replyMessageSchema.parse(body);
17
+ if (input.sendViaEmail && !await canUseMessageEmailFeature(ctx, scope)) {
18
+ return Response.json({ error: "Missing feature: messages.email" }, { status: 403 });
19
+ }
20
+ let commandResult;
21
+ try {
22
+ commandResult = await commandBus.execute("messages.messages.reply", {
23
+ input: {
24
+ ...input,
25
+ messageId: params.id,
26
+ tenantId: scope.tenantId,
27
+ organizationId: scope.organizationId,
28
+ userId: scope.userId
29
+ },
30
+ ctx: {
31
+ container: ctx.container,
32
+ auth: ctx.auth ?? null,
33
+ organizationScope: null,
34
+ selectedOrganizationId: scope.organizationId,
35
+ organizationIds: scope.organizationId ? [scope.organizationId] : null,
36
+ request: req
37
+ }
38
+ });
39
+ } catch (error) {
40
+ if (error instanceof Error) {
41
+ if (error.message === "Message not found") {
42
+ return Response.json({ error: "Message not found" }, { status: 404 });
43
+ }
44
+ if (error.message === "Access denied") {
45
+ return Response.json({ error: "Access denied" }, { status: 403 });
46
+ }
47
+ if (error.message === "Reply is not allowed for this message type") {
48
+ return Response.json({ error: "Reply is not allowed for this message type" }, { status: 409 });
49
+ }
50
+ if (error.message === "No recipients available for reply") {
51
+ return Response.json({ error: "No recipients available for reply" }, { status: 409 });
52
+ }
53
+ }
54
+ throw error;
55
+ }
56
+ const messageId = commandResult.result.id;
57
+ const response = Response.json({ id: messageId }, { status: 201 });
58
+ attachOperationMetadataHeader(response, commandResult.logEntry, {
59
+ resourceKind: "messages.message",
60
+ resourceId: messageId
61
+ });
62
+ return response;
63
+ }
64
+ const openApi = {
65
+ tag: "Messages",
66
+ methods: {
67
+ POST: {
68
+ summary: "Reply to message",
69
+ requestBody: { schema: replyOpenApiSchema },
70
+ responses: [
71
+ { status: 201, description: "Reply created", schema: forwardResponseSchema }
72
+ ],
73
+ errors: [
74
+ { status: 403, description: "Access denied", schema: errorResponseSchema },
75
+ { status: 404, description: "Message not found", schema: errorResponseSchema },
76
+ { status: 409, description: "Reply not allowed for message type", schema: errorResponseSchema },
77
+ { status: 409, description: "No recipients available for reply", schema: errorResponseSchema }
78
+ ]
79
+ }
80
+ }
81
+ };
82
+ export {
83
+ POST,
84
+ metadata,
85
+ openApi
86
+ };
87
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/messages/api/%5Bid%5D/reply/route.ts"],
4
+ "sourcesContent": ["import type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { replyMessageSchema } from '../../../data/validators'\nimport { attachOperationMetadataHeader } from '../../../lib/operationMetadata'\nimport { canUseMessageEmailFeature, resolveMessageContext } from '../../../lib/routeHelpers'\nimport {\n errorResponseSchema,\n forwardResponseSchema,\n replyMessageSchema as replyOpenApiSchema,\n} from '../../openapi'\nimport { MessageCommandExecuteResult } from '../../../commands/shared'\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['messages.compose'] },\n}\n\nexport async function POST(req: Request, { params }: { params: { id: string } }) {\n const { ctx, scope } = await resolveMessageContext(req)\n const commandBus = ctx.container.resolve('commandBus') as CommandBus\n const body = await req.json().catch(() => ({}))\n const input = replyMessageSchema.parse(body)\n if (input.sendViaEmail && !(await canUseMessageEmailFeature(ctx, scope))) {\n return Response.json({ error: 'Missing feature: messages.email' }, { status: 403 })\n }\n\n let commandResult\n try {\n commandResult = await commandBus.execute<unknown, MessageCommandExecuteResult>('messages.messages.reply', {\n input: {\n ...input,\n messageId: params.id,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n },\n ctx: {\n container: ctx.container,\n auth: ctx.auth ?? null,\n organizationScope: null,\n selectedOrganizationId: scope.organizationId,\n organizationIds: scope.organizationId ? [scope.organizationId] : null,\n request: req,\n },\n })\n } catch (error) {\n if (error instanceof Error) {\n if (error.message === 'Message not found') {\n return Response.json({ error: 'Message not found' }, { status: 404 })\n }\n if (error.message === 'Access denied') {\n return Response.json({ error: 'Access denied' }, { status: 403 })\n }\n if (error.message === 'Reply is not allowed for this message type') {\n return Response.json({ error: 'Reply is not allowed for this message type' }, { status: 409 })\n }\n if (error.message === 'No recipients available for reply') {\n return Response.json({ error: 'No recipients available for reply' }, { status: 409 })\n }\n }\n throw error\n }\n const messageId = commandResult.result.id\n\n const response = Response.json({ id: messageId }, { status: 201 })\n attachOperationMetadataHeader(response, commandResult.logEntry, {\n resourceKind: 'messages.message',\n resourceId: messageId,\n })\n return response\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n POST: {\n summary: 'Reply to message',\n requestBody: { schema: replyOpenApiSchema },\n responses: [\n { status: 201, description: 'Reply created', schema: forwardResponseSchema },\n ],\n errors: [\n { status: 403, description: 'Access denied', schema: errorResponseSchema },\n { status: 404, description: 'Message not found', schema: errorResponseSchema },\n { status: 409, description: 'Reply not allowed for message type', schema: errorResponseSchema },\n { status: 409, description: 'No recipients available for reply', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAEA,SAAS,0BAA0B;AACnC,SAAS,qCAAqC;AAC9C,SAAS,2BAA2B,6BAA6B;AACjE;AAAA,EACE;AAAA,EACA;AAAA,EACA,sBAAsB;AAAA,OACjB;AAGA,MAAM,WAAW;AAAA,EACtB,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,kBAAkB,EAAE;AACnE;AAEA,eAAsB,KAAK,KAAc,EAAE,OAAO,GAA+B;AAC/E,QAAM,EAAE,KAAK,MAAM,IAAI,MAAM,sBAAsB,GAAG;AACtD,QAAM,aAAa,IAAI,UAAU,QAAQ,YAAY;AACrD,QAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAC9C,QAAM,QAAQ,mBAAmB,MAAM,IAAI;AAC3C,MAAI,MAAM,gBAAgB,CAAE,MAAM,0BAA0B,KAAK,KAAK,GAAI;AACxE,WAAO,SAAS,KAAK,EAAE,OAAO,kCAAkC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACpF;AAEA,MAAI;AACJ,MAAI;AACF,oBAAgB,MAAM,WAAW,QAA8C,2BAA2B;AAAA,MACxG,OAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW,OAAO;AAAA,QAClB,UAAU,MAAM;AAAA,QAChB,gBAAgB,MAAM;AAAA,QACtB,QAAQ,MAAM;AAAA,MAChB;AAAA,MACA,KAAK;AAAA,QACH,WAAW,IAAI;AAAA,QACf,MAAM,IAAI,QAAQ;AAAA,QAClB,mBAAmB;AAAA,QACnB,wBAAwB,MAAM;AAAA,QAC9B,iBAAiB,MAAM,iBAAiB,CAAC,MAAM,cAAc,IAAI;AAAA,QACjE,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,UAAI,MAAM,YAAY,qBAAqB;AACzC,eAAO,SAAS,KAAK,EAAE,OAAO,oBAAoB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MACtE;AACA,UAAI,MAAM,YAAY,iBAAiB;AACrC,eAAO,SAAS,KAAK,EAAE,OAAO,gBAAgB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAClE;AACA,UAAI,MAAM,YAAY,8CAA8C;AAClE,eAAO,SAAS,KAAK,EAAE,OAAO,6CAA6C,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC/F;AACA,UAAI,MAAM,YAAY,qCAAqC;AACzD,eAAO,SAAS,KAAK,EAAE,OAAO,oCAAoC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MACtF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACA,QAAM,YAAY,cAAc,OAAO;AAEvC,QAAM,WAAW,SAAS,KAAK,EAAE,IAAI,UAAU,GAAG,EAAE,QAAQ,IAAI,CAAC;AACjE,gCAA8B,UAAU,cAAc,UAAU;AAAA,IAC9D,cAAc;AAAA,IACd,YAAY;AAAA,EACd,CAAC;AACD,SAAO;AACT;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa,EAAE,QAAQ,mBAAmB;AAAA,MAC1C,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,iBAAiB,QAAQ,sBAAsB;AAAA,MAC7E;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,iBAAiB,QAAQ,oBAAoB;AAAA,QACzE,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,oBAAoB;AAAA,QAC7E,EAAE,QAAQ,KAAK,aAAa,sCAAsC,QAAQ,oBAAoB;AAAA,QAC9F,EAAE,QAAQ,KAAK,aAAa,qCAAqC,QAAQ,oBAAoB;AAAA,MAC/F;AAAA,IACF;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }