@open-mercato/core 0.5.1-develop.2691.d8a0934b37 → 0.5.1-develop.2699.f8b50c8046

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 (414) hide show
  1. package/dist/modules/api_keys/data/entities.js +1 -1
  2. package/dist/modules/api_keys/data/entities.js.map +1 -1
  3. package/dist/modules/api_keys/services/apiKeyService.js +5 -5
  4. package/dist/modules/api_keys/services/apiKeyService.js.map +2 -2
  5. package/dist/modules/attachments/api/library/[id]/route.js +1 -1
  6. package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
  7. package/dist/modules/attachments/api/library/route.js +7 -9
  8. package/dist/modules/attachments/api/library/route.js.map +2 -2
  9. package/dist/modules/attachments/api/partitions/route.js +3 -3
  10. package/dist/modules/attachments/api/partitions/route.js.map +2 -2
  11. package/dist/modules/attachments/api/route.js +6 -5
  12. package/dist/modules/attachments/api/route.js.map +2 -2
  13. package/dist/modules/attachments/api/transfer/route.js +1 -1
  14. package/dist/modules/attachments/api/transfer/route.js.map +2 -2
  15. package/dist/modules/attachments/data/entities.js +2 -1
  16. package/dist/modules/attachments/data/entities.js.map +2 -2
  17. package/dist/modules/attachments/lib/ocrQueue.js +1 -1
  18. package/dist/modules/attachments/lib/ocrQueue.js.map +2 -2
  19. package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +2 -2
  20. package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
  21. package/dist/modules/audit_logs/data/entities.js +1 -1
  22. package/dist/modules/audit_logs/data/entities.js.map +1 -1
  23. package/dist/modules/audit_logs/services/actionLogService.js +77 -70
  24. package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
  25. package/dist/modules/auth/api/roles/acl/route.js +1 -1
  26. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  27. package/dist/modules/auth/api/users/acl/route.js +2 -2
  28. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  29. package/dist/modules/auth/api/users/resend-invite/route.js +1 -1
  30. package/dist/modules/auth/api/users/resend-invite/route.js.map +2 -2
  31. package/dist/modules/auth/cli.js +12 -6
  32. package/dist/modules/auth/cli.js.map +2 -2
  33. package/dist/modules/auth/commands/users.js +1 -1
  34. package/dist/modules/auth/commands/users.js.map +2 -2
  35. package/dist/modules/auth/data/entities.js +1 -1
  36. package/dist/modules/auth/data/entities.js.map +2 -2
  37. package/dist/modules/auth/lib/setup-app.js +3 -3
  38. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  39. package/dist/modules/auth/services/authService.js +2 -2
  40. package/dist/modules/auth/services/authService.js.map +2 -2
  41. package/dist/modules/business_rules/api/rules/route.js +3 -3
  42. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  43. package/dist/modules/business_rules/api/sets/[id]/members/route.js +7 -4
  44. package/dist/modules/business_rules/api/sets/[id]/members/route.js.map +2 -2
  45. package/dist/modules/business_rules/api/sets/route.js +3 -3
  46. package/dist/modules/business_rules/api/sets/route.js.map +2 -2
  47. package/dist/modules/business_rules/cli.js +1 -1
  48. package/dist/modules/business_rules/cli.js.map +2 -2
  49. package/dist/modules/business_rules/data/entities.js +2 -9
  50. package/dist/modules/business_rules/data/entities.js.map +2 -2
  51. package/dist/modules/business_rules/lib/rule-engine.js +1 -1
  52. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  53. package/dist/modules/catalog/api/option-schemas/route.js +0 -1
  54. package/dist/modules/catalog/api/option-schemas/route.js.map +2 -2
  55. package/dist/modules/catalog/data/entities.js +2 -11
  56. package/dist/modules/catalog/data/entities.js.map +2 -2
  57. package/dist/modules/configs/data/entities.js +2 -1
  58. package/dist/modules/configs/data/entities.js.map +2 -2
  59. package/dist/modules/currencies/commands/fetch-configs.js +3 -3
  60. package/dist/modules/currencies/commands/fetch-configs.js.map +2 -2
  61. package/dist/modules/currencies/data/entities.js +1 -1
  62. package/dist/modules/currencies/data/entities.js.map +2 -2
  63. package/dist/modules/customer_accounts/api/signup.js +1 -1
  64. package/dist/modules/customer_accounts/api/signup.js.map +2 -2
  65. package/dist/modules/customer_accounts/data/entities.js +1 -1
  66. package/dist/modules/customer_accounts/data/entities.js.map +2 -2
  67. package/dist/modules/customer_accounts/services/customerInvitationService.js +1 -1
  68. package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
  69. package/dist/modules/customer_accounts/services/customerSessionService.js +1 -1
  70. package/dist/modules/customer_accounts/services/customerSessionService.js.map +2 -2
  71. package/dist/modules/customer_accounts/services/customerTokenService.js +12 -7
  72. package/dist/modules/customer_accounts/services/customerTokenService.js.map +2 -2
  73. package/dist/modules/customers/api/interactions/conflicts/route.js +19 -17
  74. package/dist/modules/customers/api/interactions/conflicts/route.js.map +2 -2
  75. package/dist/modules/customers/api/interactions/counts/route.js +7 -6
  76. package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
  77. package/dist/modules/customers/api/interactions/route.js +28 -42
  78. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  79. package/dist/modules/customers/api/utils.js +29 -24
  80. package/dist/modules/customers/api/utils.js.map +2 -2
  81. package/dist/modules/customers/cli.js +45 -40
  82. package/dist/modules/customers/cli.js.map +2 -2
  83. package/dist/modules/customers/commands/dictionaries.js +1 -1
  84. package/dist/modules/customers/commands/dictionaries.js.map +2 -2
  85. package/dist/modules/customers/commands/tags.js +1 -1
  86. package/dist/modules/customers/commands/tags.js.map +2 -2
  87. package/dist/modules/customers/data/entities.js +2 -12
  88. package/dist/modules/customers/data/entities.js.map +2 -2
  89. package/dist/modules/customers/lib/interactionProjection.js +18 -15
  90. package/dist/modules/customers/lib/interactionProjection.js.map +2 -2
  91. package/dist/modules/customers/lib/personCompanyLinkTable.js +6 -8
  92. package/dist/modules/customers/lib/personCompanyLinkTable.js.map +2 -2
  93. package/dist/modules/dashboards/api/roles/widgets/route.js +1 -1
  94. package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
  95. package/dist/modules/dashboards/api/users/widgets/route.js +1 -1
  96. package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
  97. package/dist/modules/dashboards/data/entities.js +1 -1
  98. package/dist/modules/dashboards/data/entities.js.map +1 -1
  99. package/dist/modules/data_sync/api/mappings/route.js +1 -1
  100. package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
  101. package/dist/modules/data_sync/data/entities.js +2 -1
  102. package/dist/modules/data_sync/data/entities.js.map +2 -2
  103. package/dist/modules/data_sync/lib/id-mapping.js +1 -1
  104. package/dist/modules/data_sync/lib/id-mapping.js.map +2 -2
  105. package/dist/modules/data_sync/lib/sync-run-service.js +1 -1
  106. package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
  107. package/dist/modules/dictionaries/commands/factory.js +1 -1
  108. package/dist/modules/dictionaries/commands/factory.js.map +2 -2
  109. package/dist/modules/dictionaries/data/entities.js +2 -9
  110. package/dist/modules/dictionaries/data/entities.js.map +2 -2
  111. package/dist/modules/directory/commands/organizations.js +4 -4
  112. package/dist/modules/directory/commands/organizations.js.map +2 -2
  113. package/dist/modules/directory/data/entities.js +2 -1
  114. package/dist/modules/directory/data/entities.js.map +2 -2
  115. package/dist/modules/entities/api/definitions.js +2 -2
  116. package/dist/modules/entities/api/definitions.js.map +2 -2
  117. package/dist/modules/entities/api/encryption.js +2 -2
  118. package/dist/modules/entities/api/encryption.js.map +2 -2
  119. package/dist/modules/entities/api/relations/options.js +2 -2
  120. package/dist/modules/entities/api/relations/options.js.map +2 -2
  121. package/dist/modules/entities/cli.js +4 -4
  122. package/dist/modules/entities/cli.js.map +2 -2
  123. package/dist/modules/entities/data/entities.js +1 -1
  124. package/dist/modules/entities/data/entities.js.map +2 -2
  125. package/dist/modules/entities/lib/field-definitions.js +2 -2
  126. package/dist/modules/entities/lib/field-definitions.js.map +2 -2
  127. package/dist/modules/entities/lib/register.js +1 -1
  128. package/dist/modules/entities/lib/register.js.map +2 -2
  129. package/dist/modules/feature_toggles/data/entities.js +2 -9
  130. package/dist/modules/feature_toggles/data/entities.js.map +2 -2
  131. package/dist/modules/inbox_ops/api/proposals/counts/route.js +3 -6
  132. package/dist/modules/inbox_ops/api/proposals/counts/route.js.map +2 -2
  133. package/dist/modules/inbox_ops/data/entities.js +2 -8
  134. package/dist/modules/inbox_ops/data/entities.js.map +2 -2
  135. package/dist/modules/inbox_ops/lib/messagesIntegration.js +6 -6
  136. package/dist/modules/inbox_ops/lib/messagesIntegration.js.map +2 -2
  137. package/dist/modules/integrations/data/entities.js +2 -1
  138. package/dist/modules/integrations/data/entities.js.map +2 -2
  139. package/dist/modules/integrations/lib/credentials-service.js +1 -1
  140. package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
  141. package/dist/modules/integrations/lib/log-service.js +1 -1
  142. package/dist/modules/integrations/lib/log-service.js.map +2 -2
  143. package/dist/modules/integrations/lib/state-service.js +1 -1
  144. package/dist/modules/integrations/lib/state-service.js.map +2 -2
  145. package/dist/modules/messages/api/route.js +90 -93
  146. package/dist/modules/messages/api/route.js.map +2 -2
  147. package/dist/modules/messages/api/unread-count/route.js +8 -7
  148. package/dist/modules/messages/api/unread-count/route.js.map +2 -2
  149. package/dist/modules/messages/commands/confirmations.js +1 -1
  150. package/dist/modules/messages/commands/confirmations.js.map +2 -2
  151. package/dist/modules/messages/commands/messages.js +3 -3
  152. package/dist/modules/messages/commands/messages.js.map +2 -2
  153. package/dist/modules/messages/data/entities.js +2 -1
  154. package/dist/modules/messages/data/entities.js.map +2 -2
  155. package/dist/modules/messages/lib/email-sender.js +1 -1
  156. package/dist/modules/messages/lib/email-sender.js.map +2 -2
  157. package/dist/modules/messages/lib/searchLookup.js +8 -8
  158. package/dist/modules/messages/lib/searchLookup.js.map +2 -2
  159. package/dist/modules/messages/lib/tokenConsumption.js +9 -4
  160. package/dist/modules/messages/lib/tokenConsumption.js.map +2 -2
  161. package/dist/modules/notifications/data/entities.js +2 -1
  162. package/dist/modules/notifications/data/entities.js.map +2 -2
  163. package/dist/modules/notifications/lib/notificationRecipients.js +15 -5
  164. package/dist/modules/notifications/lib/notificationRecipients.js.map +2 -2
  165. package/dist/modules/notifications/lib/notificationService.js +39 -34
  166. package/dist/modules/notifications/lib/notificationService.js.map +2 -2
  167. package/dist/modules/notifications/workers/create-notification.worker.js +14 -13
  168. package/dist/modules/notifications/workers/create-notification.worker.js.map +2 -2
  169. package/dist/modules/payment_gateways/api/transactions/route.js +2 -2
  170. package/dist/modules/payment_gateways/api/transactions/route.js.map +2 -2
  171. package/dist/modules/payment_gateways/data/entities.js +2 -1
  172. package/dist/modules/payment_gateways/data/entities.js.map +2 -2
  173. package/dist/modules/payment_gateways/lib/gateway-service.js +1 -1
  174. package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
  175. package/dist/modules/payment_gateways/lib/webhook-utils.js +2 -2
  176. package/dist/modules/payment_gateways/lib/webhook-utils.js.map +2 -2
  177. package/dist/modules/perspectives/data/entities.js +1 -1
  178. package/dist/modules/perspectives/data/entities.js.map +2 -2
  179. package/dist/modules/planner/data/entities.js +1 -1
  180. package/dist/modules/planner/data/entities.js.map +2 -2
  181. package/dist/modules/progress/data/entities.js +2 -1
  182. package/dist/modules/progress/data/entities.js.map +2 -2
  183. package/dist/modules/progress/lib/progressServiceImpl.js +1 -1
  184. package/dist/modules/progress/lib/progressServiceImpl.js.map +2 -2
  185. package/dist/modules/query_index/api/status.js +66 -57
  186. package/dist/modules/query_index/api/status.js.map +2 -2
  187. package/dist/modules/query_index/cli.js +39 -24
  188. package/dist/modules/query_index/cli.js.map +2 -2
  189. package/dist/modules/query_index/data/entities.js +1 -1
  190. package/dist/modules/query_index/data/entities.js.map +2 -2
  191. package/dist/modules/query_index/di.js +25 -13
  192. package/dist/modules/query_index/di.js.map +2 -2
  193. package/dist/modules/query_index/lib/batch.js +31 -33
  194. package/dist/modules/query_index/lib/batch.js.map +2 -2
  195. package/dist/modules/query_index/lib/coverage.js +63 -50
  196. package/dist/modules/query_index/lib/coverage.js.map +2 -2
  197. package/dist/modules/query_index/lib/engine.js +592 -588
  198. package/dist/modules/query_index/lib/engine.js.map +2 -2
  199. package/dist/modules/query_index/lib/indexer.js +74 -47
  200. package/dist/modules/query_index/lib/indexer.js.map +2 -2
  201. package/dist/modules/query_index/lib/jobs.js +37 -24
  202. package/dist/modules/query_index/lib/jobs.js.map +2 -2
  203. package/dist/modules/query_index/lib/purge.js +19 -11
  204. package/dist/modules/query_index/lib/purge.js.map +2 -2
  205. package/dist/modules/query_index/lib/reindexer.js +47 -44
  206. package/dist/modules/query_index/lib/reindexer.js.map +2 -2
  207. package/dist/modules/query_index/lib/search-tokens.js +47 -25
  208. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  209. package/dist/modules/query_index/lib/stale.js +14 -12
  210. package/dist/modules/query_index/lib/stale.js.map +2 -2
  211. package/dist/modules/query_index/lib/subscriber-scope.js +2 -2
  212. package/dist/modules/query_index/lib/subscriber-scope.js.map +2 -2
  213. package/dist/modules/query_index/subscribers/delete_one.js +3 -2
  214. package/dist/modules/query_index/subscribers/delete_one.js.map +2 -2
  215. package/dist/modules/resources/commands/tag-assignments.js +1 -1
  216. package/dist/modules/resources/commands/tag-assignments.js.map +2 -2
  217. package/dist/modules/resources/commands/tags.js +1 -1
  218. package/dist/modules/resources/commands/tags.js.map +2 -2
  219. package/dist/modules/resources/data/entities.js +2 -1
  220. package/dist/modules/resources/data/entities.js.map +2 -2
  221. package/dist/modules/sales/commands/documentAddresses.js +2 -2
  222. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  223. package/dist/modules/sales/commands/notes.js.map +2 -2
  224. package/dist/modules/sales/commands/tags.js +1 -1
  225. package/dist/modules/sales/commands/tags.js.map +2 -2
  226. package/dist/modules/sales/data/enrichers.js +9 -8
  227. package/dist/modules/sales/data/enrichers.js.map +2 -2
  228. package/dist/modules/sales/data/entities.js +2 -11
  229. package/dist/modules/sales/data/entities.js.map +2 -2
  230. package/dist/modules/shipping_carriers/data/entities.js +2 -1
  231. package/dist/modules/shipping_carriers/data/entities.js.map +2 -2
  232. package/dist/modules/shipping_carriers/lib/shipping-service.js +1 -1
  233. package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
  234. package/dist/modules/shipping_carriers/lib/webhook-utils.js +2 -2
  235. package/dist/modules/shipping_carriers/lib/webhook-utils.js.map +2 -2
  236. package/dist/modules/staff/data/entities.js +1 -1
  237. package/dist/modules/staff/data/entities.js.map +2 -2
  238. package/dist/modules/translations/api/[entityType]/[entityId]/route.js +3 -5
  239. package/dist/modules/translations/api/[entityType]/[entityId]/route.js.map +2 -2
  240. package/dist/modules/translations/api/context.js +2 -2
  241. package/dist/modules/translations/api/context.js.map +2 -2
  242. package/dist/modules/translations/commands/translations.js +46 -39
  243. package/dist/modules/translations/commands/translations.js.map +2 -2
  244. package/dist/modules/translations/components/TranslationManager.js +19 -10
  245. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  246. package/dist/modules/translations/data/entities.js +1 -1
  247. package/dist/modules/translations/data/entities.js.map +2 -2
  248. package/dist/modules/translations/lib/apply.js +4 -4
  249. package/dist/modules/translations/lib/apply.js.map +2 -2
  250. package/dist/modules/translations/lib/batch.js +3 -2
  251. package/dist/modules/translations/lib/batch.js.map +2 -2
  252. package/dist/modules/translations/subscribers/cleanup.js +3 -5
  253. package/dist/modules/translations/subscribers/cleanup.js.map +2 -2
  254. package/dist/modules/workflows/api/definitions/route.js +1 -1
  255. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  256. package/dist/modules/workflows/cli.js +5 -5
  257. package/dist/modules/workflows/cli.js.map +2 -2
  258. package/dist/modules/workflows/data/entities.js +2 -1
  259. package/dist/modules/workflows/data/entities.js.map +2 -2
  260. package/dist/modules/workflows/lib/event-logger.js +2 -2
  261. package/dist/modules/workflows/lib/event-logger.js.map +2 -2
  262. package/dist/modules/workflows/lib/seeds.js +16 -1
  263. package/dist/modules/workflows/lib/seeds.js.map +2 -2
  264. package/dist/modules/workflows/lib/step-handler.js +3 -3
  265. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  266. package/dist/modules/workflows/lib/task-handler.js +1 -1
  267. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  268. package/dist/modules/workflows/lib/transition-handler.js +1 -1
  269. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  270. package/dist/modules/workflows/lib/workflow-executor.js +2 -2
  271. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  272. package/jest.config.cjs +4 -2
  273. package/package.json +3 -3
  274. package/src/modules/api_keys/data/entities.ts +1 -1
  275. package/src/modules/api_keys/services/apiKeyService.ts +5 -5
  276. package/src/modules/attachments/api/library/[id]/route.ts +1 -1
  277. package/src/modules/attachments/api/library/route.ts +10 -12
  278. package/src/modules/attachments/api/partitions/route.ts +3 -3
  279. package/src/modules/attachments/api/route.ts +10 -8
  280. package/src/modules/attachments/api/transfer/route.ts +1 -1
  281. package/src/modules/attachments/data/entities.ts +2 -1
  282. package/src/modules/attachments/lib/ocrQueue.ts +1 -1
  283. package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +4 -4
  284. package/src/modules/audit_logs/api/audit-logs/actions/route.ts +4 -4
  285. package/src/modules/audit_logs/data/entities.ts +1 -1
  286. package/src/modules/audit_logs/services/actionLogService.ts +96 -87
  287. package/src/modules/auth/api/roles/acl/route.ts +1 -1
  288. package/src/modules/auth/api/users/acl/route.ts +2 -2
  289. package/src/modules/auth/api/users/resend-invite/route.ts +1 -1
  290. package/src/modules/auth/cli.ts +46 -40
  291. package/src/modules/auth/commands/users.ts +1 -1
  292. package/src/modules/auth/data/entities.ts +1 -1
  293. package/src/modules/auth/lib/setup-app.ts +3 -3
  294. package/src/modules/auth/services/authService.ts +2 -2
  295. package/src/modules/business_rules/api/rules/route.ts +3 -3
  296. package/src/modules/business_rules/api/sets/[id]/members/route.ts +7 -4
  297. package/src/modules/business_rules/api/sets/route.ts +3 -3
  298. package/src/modules/business_rules/cli.ts +1 -1
  299. package/src/modules/business_rules/data/entities.ts +2 -9
  300. package/src/modules/business_rules/lib/rule-engine.ts +1 -1
  301. package/src/modules/catalog/api/option-schemas/route.ts +0 -1
  302. package/src/modules/catalog/data/entities.ts +2 -11
  303. package/src/modules/configs/data/entities.ts +2 -1
  304. package/src/modules/currencies/commands/fetch-configs.ts +3 -3
  305. package/src/modules/currencies/data/entities.ts +1 -1
  306. package/src/modules/customer_accounts/api/signup.ts +1 -1
  307. package/src/modules/customer_accounts/data/entities.ts +1 -1
  308. package/src/modules/customer_accounts/services/customerInvitationService.ts +1 -1
  309. package/src/modules/customer_accounts/services/customerSessionService.ts +1 -1
  310. package/src/modules/customer_accounts/services/customerTokenService.ts +26 -15
  311. package/src/modules/customers/api/interactions/conflicts/route.ts +26 -23
  312. package/src/modules/customers/api/interactions/counts/route.ts +13 -11
  313. package/src/modules/customers/api/interactions/route.ts +32 -44
  314. package/src/modules/customers/api/utils.ts +45 -37
  315. package/src/modules/customers/cli.ts +88 -67
  316. package/src/modules/customers/commands/dictionaries.ts +1 -1
  317. package/src/modules/customers/commands/tags.ts +1 -1
  318. package/src/modules/customers/data/entities.ts +2 -12
  319. package/src/modules/customers/lib/interactionProjection.ts +36 -25
  320. package/src/modules/customers/lib/personCompanyLinkTable.ts +13 -18
  321. package/src/modules/dashboards/api/roles/widgets/route.ts +1 -1
  322. package/src/modules/dashboards/api/users/widgets/route.ts +1 -1
  323. package/src/modules/dashboards/data/entities.ts +1 -1
  324. package/src/modules/data_sync/api/mappings/route.ts +1 -1
  325. package/src/modules/data_sync/data/entities.ts +2 -1
  326. package/src/modules/data_sync/lib/id-mapping.ts +1 -1
  327. package/src/modules/data_sync/lib/sync-run-service.ts +1 -1
  328. package/src/modules/dictionaries/commands/factory.ts +1 -1
  329. package/src/modules/dictionaries/data/entities.ts +2 -9
  330. package/src/modules/directory/commands/organizations.ts +4 -4
  331. package/src/modules/directory/data/entities.ts +2 -1
  332. package/src/modules/entities/api/definitions.ts +2 -2
  333. package/src/modules/entities/api/encryption.ts +2 -2
  334. package/src/modules/entities/api/relations/options.ts +8 -3
  335. package/src/modules/entities/cli.ts +4 -4
  336. package/src/modules/entities/data/entities.ts +1 -1
  337. package/src/modules/entities/lib/field-definitions.ts +2 -2
  338. package/src/modules/entities/lib/register.ts +1 -1
  339. package/src/modules/feature_toggles/data/entities.ts +2 -9
  340. package/src/modules/inbox_ops/api/proposals/counts/route.ts +10 -10
  341. package/src/modules/inbox_ops/data/entities.ts +2 -8
  342. package/src/modules/inbox_ops/lib/messagesIntegration.ts +12 -11
  343. package/src/modules/integrations/data/entities.ts +2 -1
  344. package/src/modules/integrations/lib/credentials-service.ts +1 -1
  345. package/src/modules/integrations/lib/log-service.ts +1 -1
  346. package/src/modules/integrations/lib/state-service.ts +1 -1
  347. package/src/modules/messages/api/route.ts +134 -123
  348. package/src/modules/messages/api/unread-count/route.ts +19 -16
  349. package/src/modules/messages/commands/confirmations.ts +1 -1
  350. package/src/modules/messages/commands/messages.ts +3 -3
  351. package/src/modules/messages/data/entities.ts +2 -1
  352. package/src/modules/messages/lib/email-sender.ts +1 -1
  353. package/src/modules/messages/lib/searchLookup.ts +16 -13
  354. package/src/modules/messages/lib/tokenConsumption.ts +16 -8
  355. package/src/modules/notifications/data/entities.ts +2 -1
  356. package/src/modules/notifications/lib/notificationRecipients.ts +42 -26
  357. package/src/modules/notifications/lib/notificationService.ts +53 -42
  358. package/src/modules/notifications/workers/create-notification.worker.ts +20 -17
  359. package/src/modules/payment_gateways/api/transactions/route.ts +2 -2
  360. package/src/modules/payment_gateways/data/entities.ts +2 -1
  361. package/src/modules/payment_gateways/lib/gateway-service.ts +1 -1
  362. package/src/modules/payment_gateways/lib/webhook-utils.ts +2 -2
  363. package/src/modules/perspectives/data/entities.ts +1 -1
  364. package/src/modules/planner/data/entities.ts +1 -1
  365. package/src/modules/progress/data/entities.ts +2 -1
  366. package/src/modules/progress/lib/progressServiceImpl.ts +1 -1
  367. package/src/modules/query_index/api/status.ts +85 -71
  368. package/src/modules/query_index/cli.ts +51 -31
  369. package/src/modules/query_index/data/entities.ts +1 -1
  370. package/src/modules/query_index/di.ts +41 -16
  371. package/src/modules/query_index/lib/batch.ts +68 -55
  372. package/src/modules/query_index/lib/coverage.ts +115 -88
  373. package/src/modules/query_index/lib/engine.ts +1036 -1096
  374. package/src/modules/query_index/lib/indexer.ts +115 -79
  375. package/src/modules/query_index/lib/jobs.ts +51 -31
  376. package/src/modules/query_index/lib/purge.ts +25 -19
  377. package/src/modules/query_index/lib/reindexer.ts +97 -84
  378. package/src/modules/query_index/lib/search-tokens.ts +67 -36
  379. package/src/modules/query_index/lib/stale.ts +14 -17
  380. package/src/modules/query_index/lib/subscriber-scope.ts +6 -5
  381. package/src/modules/query_index/subscribers/delete_one.ts +9 -6
  382. package/src/modules/resources/commands/tag-assignments.ts +1 -1
  383. package/src/modules/resources/commands/tags.ts +1 -1
  384. package/src/modules/resources/data/entities.ts +2 -1
  385. package/src/modules/sales/commands/documentAddresses.ts +2 -2
  386. package/src/modules/sales/commands/notes.ts +1 -1
  387. package/src/modules/sales/commands/tags.ts +1 -1
  388. package/src/modules/sales/data/enrichers.ts +17 -13
  389. package/src/modules/sales/data/entities.ts +2 -11
  390. package/src/modules/shipping_carriers/data/entities.ts +2 -1
  391. package/src/modules/shipping_carriers/lib/shipping-service.ts +1 -1
  392. package/src/modules/shipping_carriers/lib/webhook-utils.ts +2 -2
  393. package/src/modules/staff/data/entities.ts +1 -1
  394. package/src/modules/translations/api/[entityType]/[entityId]/route.ts +14 -11
  395. package/src/modules/translations/api/context.ts +4 -4
  396. package/src/modules/translations/commands/translations.ts +116 -81
  397. package/src/modules/translations/components/TranslationManager.tsx +23 -14
  398. package/src/modules/translations/data/entities.ts +1 -1
  399. package/src/modules/translations/i18n/de.json +1 -0
  400. package/src/modules/translations/i18n/en.json +1 -0
  401. package/src/modules/translations/i18n/es.json +1 -0
  402. package/src/modules/translations/i18n/pl.json +1 -0
  403. package/src/modules/translations/lib/apply.ts +6 -6
  404. package/src/modules/translations/lib/batch.ts +9 -7
  405. package/src/modules/translations/subscribers/cleanup.ts +10 -11
  406. package/src/modules/workflows/api/definitions/route.ts +1 -1
  407. package/src/modules/workflows/cli.ts +5 -5
  408. package/src/modules/workflows/data/entities.ts +2 -1
  409. package/src/modules/workflows/lib/event-logger.ts +2 -2
  410. package/src/modules/workflows/lib/seeds.ts +16 -1
  411. package/src/modules/workflows/lib/step-handler.ts +3 -3
  412. package/src/modules/workflows/lib/task-handler.ts +1 -1
  413. package/src/modules/workflows/lib/transition-handler.ts +1 -1
  414. package/src/modules/workflows/lib/workflow-executor.ts +2 -2
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { sql } from "kysely";
2
3
  import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
3
4
  import { hashForLookup } from "@open-mercato/shared/lib/encryption/aes";
4
5
  import { User } from "../../auth/data/entities.js";
@@ -17,8 +18,8 @@ import {
17
18
  messageListItemSchema
18
19
  } from "./openapi.js";
19
20
  const NO_MATCH_ID = "00000000-0000-0000-0000-000000000000";
20
- function getKnex(em) {
21
- return em.getConnection().getKnex();
21
+ function getDb(em) {
22
+ return em.getKysely();
22
23
  }
23
24
  const metadata = {
24
25
  GET: { requireAuth: true, requireFeatures: ["messages.view"] },
@@ -30,104 +31,100 @@ async function GET(req) {
30
31
  const url = new URL(req.url);
31
32
  const params = Object.fromEntries(url.searchParams);
32
33
  const input = listMessagesSchema.parse(params);
33
- const knex = getKnex(em);
34
- let query = knex("messages as m").where("m.tenant_id", scope.tenantId).whereNull("m.deleted_at");
35
- if (scope.organizationId) {
36
- query = query.where("m.organization_id", scope.organizationId);
37
- } else {
38
- query = query.whereNull("m.organization_id");
39
- }
40
- const joinRecipient = () => {
41
- query = query.leftJoin("message_recipients as r", function() {
42
- this.on("m.id", "=", "r.message_id").andOn("r.recipient_user_id", "=", knex.raw("?", [scope.userId]));
43
- });
44
- };
45
- switch (input.folder) {
46
- case "inbox":
47
- joinRecipient();
48
- query = query.whereNotNull("r.message_id").whereNull("r.deleted_at").whereNull("r.archived_at").where("m.is_draft", false);
49
- break;
50
- case "archived":
51
- joinRecipient();
52
- query = query.whereNotNull("r.message_id").whereNull("r.deleted_at").whereNotNull("r.archived_at");
53
- break;
54
- case "sent":
55
- query = query.where("m.sender_user_id", scope.userId).where("m.is_draft", false);
56
- joinRecipient();
57
- break;
58
- case "drafts":
59
- query = query.where("m.sender_user_id", scope.userId).where("m.is_draft", true);
60
- joinRecipient();
61
- break;
62
- case "all":
63
- joinRecipient();
64
- query = query.where(function() {
65
- this.where("m.sender_user_id", scope.userId).orWhereNotNull("r.message_id");
66
- });
67
- break;
68
- default: {
69
- const unsupportedFolder = input.folder;
70
- throw new Error(`Unsupported folder: ${String(unsupportedFolder)}`);
71
- }
72
- }
73
- if (input.status) {
74
- query = query.where("r.status", input.status);
75
- }
76
- if (input.type) {
77
- query = query.where("m.type", input.type);
78
- }
79
- if (input.visibility) {
80
- query = query.where("m.visibility", input.visibility);
81
- }
82
- if (input.sourceEntityType) {
83
- query = query.where("m.source_entity_type", input.sourceEntityType);
84
- }
85
- if (input.sourceEntityId) {
86
- query = query.where("m.source_entity_id", input.sourceEntityId);
87
- }
88
- if (input.externalEmail) {
89
- query = query.where("m.external_email_hash", hashForLookup(input.externalEmail));
90
- }
91
- if (input.senderId) {
92
- query = query.where("m.sender_user_id", input.senderId);
93
- }
94
- if (input.search) {
95
- const matchedIds = await findMessageIdsBySearchTokens({
96
- em,
97
- query: input.search,
98
- tenantId: scope.tenantId ?? null,
99
- organizationId: scope.organizationId
100
- });
101
- if (matchedIds === null || matchedIds.length === 0) {
102
- query = query.where("m.id", NO_MATCH_ID);
34
+ const db = getDb(em);
35
+ const searchIds = input.search ? await findMessageIdsBySearchTokens({
36
+ em,
37
+ query: input.search,
38
+ tenantId: scope.tenantId ?? null,
39
+ organizationId: scope.organizationId
40
+ }) : void 0;
41
+ const buildBaseQuery = () => {
42
+ let q = db.selectFrom("messages as m").where("m.tenant_id", "=", scope.tenantId).where("m.deleted_at", "is", null);
43
+ if (scope.organizationId) {
44
+ q = q.where("m.organization_id", "=", scope.organizationId);
103
45
  } else {
104
- query = query.whereIn("m.id", matchedIds);
46
+ q = q.where("m.organization_id", "is", null);
105
47
  }
106
- }
107
- if (input.since) {
108
- query = query.where("m.sent_at", ">", new Date(input.since));
109
- }
110
- if (input.hasObjects !== void 0) {
111
- const subquery = knex("message_objects").select(1).whereRaw("message_objects.message_id = m.id");
112
- query = input.hasObjects ? query.whereExists(subquery) : query.whereNotExists(subquery);
113
- }
114
- if (input.hasAttachments !== void 0) {
115
- const subquery = knex("attachments").select(1).where("attachments.entity_id", MESSAGE_ATTACHMENT_ENTITY_ID).whereRaw("attachments.record_id = m.id");
116
- query = input.hasAttachments ? query.whereExists(subquery) : query.whereNotExists(subquery);
117
- }
118
- if (input.hasActions !== void 0) {
119
- query = input.hasActions ? query.whereNotNull("m.action_data") : query.whereNull("m.action_data");
120
- }
121
- const countResult = await query.clone().count("* as count").first();
48
+ const joinRecipient = () => {
49
+ q = q.leftJoin("message_recipients as r", (jb) => jb.onRef("m.id", "=", "r.message_id").on("r.recipient_user_id", "=", scope.userId));
50
+ };
51
+ switch (input.folder) {
52
+ case "inbox":
53
+ joinRecipient();
54
+ q = q.where("r.message_id", "is not", null).where("r.deleted_at", "is", null).where("r.archived_at", "is", null).where("m.is_draft", "=", false);
55
+ break;
56
+ case "archived":
57
+ joinRecipient();
58
+ q = q.where("r.message_id", "is not", null).where("r.deleted_at", "is", null).where("r.archived_at", "is not", null);
59
+ break;
60
+ case "sent":
61
+ q = q.where("m.sender_user_id", "=", scope.userId).where("m.is_draft", "=", false);
62
+ joinRecipient();
63
+ break;
64
+ case "drafts":
65
+ q = q.where("m.sender_user_id", "=", scope.userId).where("m.is_draft", "=", true);
66
+ joinRecipient();
67
+ break;
68
+ case "all":
69
+ joinRecipient();
70
+ q = q.where((eb) => eb.or([
71
+ eb("m.sender_user_id", "=", scope.userId),
72
+ eb("r.message_id", "is not", null)
73
+ ]));
74
+ break;
75
+ default: {
76
+ const unsupportedFolder = input.folder;
77
+ throw new Error(`Unsupported folder: ${String(unsupportedFolder)}`);
78
+ }
79
+ }
80
+ if (input.status) q = q.where("r.status", "=", input.status);
81
+ if (input.type) q = q.where("m.type", "=", input.type);
82
+ if (input.visibility) q = q.where("m.visibility", "=", input.visibility);
83
+ if (input.sourceEntityType) q = q.where("m.source_entity_type", "=", input.sourceEntityType);
84
+ if (input.sourceEntityId) q = q.where("m.source_entity_id", "=", input.sourceEntityId);
85
+ if (input.externalEmail) q = q.where("m.external_email_hash", "=", hashForLookup(input.externalEmail));
86
+ if (input.senderId) q = q.where("m.sender_user_id", "=", input.senderId);
87
+ if (input.search) {
88
+ if (!searchIds || searchIds.length === 0) {
89
+ q = q.where("m.id", "=", NO_MATCH_ID);
90
+ } else {
91
+ q = q.where("m.id", "in", searchIds);
92
+ }
93
+ }
94
+ if (input.since) q = q.where("m.sent_at", ">", new Date(input.since));
95
+ if (input.hasObjects !== void 0) {
96
+ const existsFn = (eb) => eb.exists(
97
+ eb.selectFrom("message_objects").select(sql`1`.as("one")).whereRef("message_objects.message_id", "=", "m.id")
98
+ );
99
+ const notExistsFn = (eb) => eb.not(eb.exists(
100
+ eb.selectFrom("message_objects").select(sql`1`.as("one")).whereRef("message_objects.message_id", "=", "m.id")
101
+ ));
102
+ q = input.hasObjects ? q.where(existsFn) : q.where(notExistsFn);
103
+ }
104
+ if (input.hasAttachments !== void 0) {
105
+ const existsFn = (eb) => eb.exists(
106
+ eb.selectFrom("attachments").select(sql`1`.as("one")).where("attachments.entity_id", "=", MESSAGE_ATTACHMENT_ENTITY_ID).whereRef("attachments.record_id", "=", "m.id")
107
+ );
108
+ const notExistsFn = (eb) => eb.not(eb.exists(
109
+ eb.selectFrom("attachments").select(sql`1`.as("one")).where("attachments.entity_id", "=", MESSAGE_ATTACHMENT_ENTITY_ID).whereRef("attachments.record_id", "=", "m.id")
110
+ ));
111
+ q = input.hasAttachments ? q.where(existsFn) : q.where(notExistsFn);
112
+ }
113
+ if (input.hasActions !== void 0) {
114
+ q = input.hasActions ? q.where("m.action_data", "is not", null) : q.where("m.action_data", "is", null);
115
+ }
116
+ return q;
117
+ };
118
+ const countResult = await buildBaseQuery().select(sql`count(*)`.as("count")).executeTakeFirst();
122
119
  const total = Number(countResult?.count ?? 0);
123
120
  const offset = (input.page - 1) * input.pageSize;
124
- const scopeRows = await query.select(
121
+ const scopeRows = await buildBaseQuery().select([
125
122
  "m.id",
126
123
  "m.sender_user_id",
127
124
  "m.is_draft",
128
125
  "r.status as recipient_status",
129
126
  "r.read_at"
130
- ).orderBy("m.sent_at", "desc").offset(offset).limit(input.pageSize);
127
+ ]).orderBy("m.sent_at", "desc").offset(offset).limit(input.pageSize).execute();
131
128
  const typedRows = scopeRows;
132
129
  const messageIds = typedRows.map((row) => row.id);
133
130
  const messageEntities = messageIds.length > 0 ? await findWithDecryption(
@@ -147,12 +144,12 @@ async function GET(req) {
147
144
  acc[obj.messageId].push(obj);
148
145
  return acc;
149
146
  }, {});
150
- const attachmentCounts = messageIds.length > 0 ? await getKnex(em)("attachments").select("record_id").count("* as count").where("entity_id", MESSAGE_ATTACHMENT_ENTITY_ID).whereIn("record_id", messageIds).groupBy("record_id") : [];
147
+ const attachmentCounts = messageIds.length > 0 ? await getDb(em).selectFrom("attachments").select(["record_id", sql`count(*)`.as("count")]).where("entity_id", "=", MESSAGE_ATTACHMENT_ENTITY_ID).where("record_id", "in", messageIds).groupBy("record_id").execute() : [];
151
148
  const attachmentCountByMessage = attachmentCounts.reduce((acc, row) => {
152
149
  acc[row.record_id] = Number(row.count);
153
150
  return acc;
154
151
  }, {});
155
- const recipientCounts = messageIds.length > 0 ? await getKnex(em)("message_recipients").select("message_id").count("* as count").whereIn("message_id", messageIds).whereNull("deleted_at").groupBy("message_id") : [];
152
+ const recipientCounts = messageIds.length > 0 ? await getDb(em).selectFrom("message_recipients").select(["message_id", sql`count(*)`.as("count")]).where("message_id", "in", messageIds).where("deleted_at", "is", null).groupBy("message_id").execute() : [];
156
153
  const recipientCountByMessage = recipientCounts.reduce((acc, row) => {
157
154
  acc[row.message_id] = Number(row.count);
158
155
  return acc;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/messages/api/route.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { Knex } from 'knex'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { hashForLookup } from '@open-mercato/shared/lib/encryption/aes'\nimport { User } from '../../auth/data/entities'\nimport { Message, MessageObject } from '../data/entities'\nimport { composeMessageSchema, listMessagesSchema } from '../data/validators'\nimport { MESSAGE_ATTACHMENT_ENTITY_ID } from '../lib/constants'\nimport { getMessageType } from '../lib/message-types-registry'\nimport { validateMessageObjectsForType } from '../lib/object-validation'\nimport { attachOperationMetadataHeader } from '../lib/operationMetadata'\nimport { canUseMessageEmailFeature, resolveMessageContext } from '../lib/routeHelpers'\nimport { findMessageIdsBySearchTokens } from '../lib/searchLookup'\nimport { MessageCommandExecuteResult } from '../commands/shared'\nimport {\n composeMessageSchema as composeSchema,\n composeResponseSchema,\n listMessagesSchema as listSchema,\n messageListItemSchema,\n} from './openapi'\n\ntype MessageCommandExecuteResultWithThreadId = MessageCommandExecuteResult & {\n threadId: string\n}\n\nconst NO_MATCH_ID = '00000000-0000-0000-0000-000000000000'\n\nfunction getKnex(em: EntityManager): Knex {\n return (em.getConnection() as unknown as { getKnex: () => Knex }).getKnex()\n}\n\ntype MessageListScopeRow = {\n id: string\n sender_user_id: string\n is_draft: boolean\n recipient_status: string | null\n read_at: string | null\n}\n\ntype AttachmentCountRow = {\n record_id: string\n count: string | number\n}\n\ntype RecipientCountRow = {\n message_id: string\n count: string | number\n}\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['messages.view'] },\n POST: { requireAuth: true, requireFeatures: ['messages.compose'] },\n}\n\nexport async function GET(req: Request) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = ctx.container.resolve('em') as EntityManager\n const url = new URL(req.url)\n const params = Object.fromEntries(url.searchParams)\n const input = listMessagesSchema.parse(params)\n const knex = getKnex(em)\n\n let query = knex('messages as m')\n .where('m.tenant_id', scope.tenantId)\n .whereNull('m.deleted_at')\n\n if (scope.organizationId) {\n query = query.where('m.organization_id', scope.organizationId)\n } else {\n query = query.whereNull('m.organization_id')\n }\n\n const joinRecipient = () => {\n query = query.leftJoin('message_recipients as r', function () {\n this.on('m.id', '=', 'r.message_id').andOn('r.recipient_user_id', '=', knex.raw('?', [scope.userId]))\n })\n }\n\n switch (input.folder) {\n case 'inbox':\n joinRecipient()\n query = query\n .whereNotNull('r.message_id')\n .whereNull('r.deleted_at')\n .whereNull('r.archived_at')\n .where('m.is_draft', false)\n break\n case 'archived':\n joinRecipient()\n query = query\n .whereNotNull('r.message_id')\n .whereNull('r.deleted_at')\n .whereNotNull('r.archived_at')\n break\n case 'sent':\n query = query\n .where('m.sender_user_id', scope.userId)\n .where('m.is_draft', false)\n joinRecipient()\n break\n case 'drafts':\n query = query\n .where('m.sender_user_id', scope.userId)\n .where('m.is_draft', true)\n joinRecipient()\n break\n case 'all':\n joinRecipient()\n query = query.where(function () {\n this.where('m.sender_user_id', scope.userId).orWhereNotNull('r.message_id')\n })\n break\n default: {\n const unsupportedFolder: never = input.folder\n throw new Error(`Unsupported folder: ${String(unsupportedFolder)}`)\n }\n }\n\n if (input.status) {\n query = query.where('r.status', input.status)\n }\n\n if (input.type) {\n query = query.where('m.type', input.type)\n }\n\n if (input.visibility) {\n query = query.where('m.visibility', input.visibility)\n }\n\n if (input.sourceEntityType) {\n query = query.where('m.source_entity_type', input.sourceEntityType)\n }\n\n if (input.sourceEntityId) {\n query = query.where('m.source_entity_id', input.sourceEntityId)\n }\n\n if (input.externalEmail) {\n query = query.where('m.external_email_hash', hashForLookup(input.externalEmail))\n }\n\n if (input.senderId) {\n query = query.where('m.sender_user_id', input.senderId)\n }\n\n if (input.search) {\n const matchedIds = await findMessageIdsBySearchTokens({\n em,\n query: input.search,\n tenantId: scope.tenantId ?? null,\n organizationId: scope.organizationId,\n })\n if (matchedIds === null || matchedIds.length === 0) {\n query = query.where('m.id', NO_MATCH_ID)\n } else {\n query = query.whereIn('m.id', matchedIds)\n }\n }\n\n if (input.since) {\n query = query.where('m.sent_at', '>', new Date(input.since))\n }\n\n if (input.hasObjects !== undefined) {\n const subquery = knex('message_objects').select(1).whereRaw('message_objects.message_id = m.id')\n query = input.hasObjects ? query.whereExists(subquery) : query.whereNotExists(subquery)\n }\n\n if (input.hasAttachments !== undefined) {\n const subquery = knex('attachments')\n .select(1)\n .where('attachments.entity_id', MESSAGE_ATTACHMENT_ENTITY_ID)\n .whereRaw('attachments.record_id = m.id')\n query = input.hasAttachments ? query.whereExists(subquery) : query.whereNotExists(subquery)\n }\n\n if (input.hasActions !== undefined) {\n query = input.hasActions ? query.whereNotNull('m.action_data') : query.whereNull('m.action_data')\n }\n\n const countResult = await query.clone().count('* as count').first()\n const total = Number(countResult?.count ?? 0)\n\n const offset = (input.page - 1) * input.pageSize\n const scopeRows = await query\n .select(\n 'm.id',\n 'm.sender_user_id',\n 'm.is_draft',\n 'r.status as recipient_status',\n 'r.read_at',\n )\n .orderBy('m.sent_at', 'desc')\n .offset(offset)\n .limit(input.pageSize)\n\n const typedRows = scopeRows as MessageListScopeRow[]\n const messageIds = typedRows.map((row) => row.id)\n\n const messageEntities = messageIds.length > 0\n ? await findWithDecryption(\n em,\n Message,\n { id: { $in: messageIds } },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId }\n )\n : []\n\n const messagesById = new Map<string, Message>()\n for (const message of messageEntities) {\n messagesById.set(message.id, message)\n }\n\n const objects = messageIds.length > 0\n ? await em.find(MessageObject, { messageId: { $in: messageIds } })\n : []\n\n const objectsByMessage = objects.reduce((acc, obj) => {\n if (!acc[obj.messageId]) acc[obj.messageId] = []\n acc[obj.messageId].push(obj)\n return acc\n }, {} as Record<string, MessageObject[]>)\n\n const attachmentCounts: AttachmentCountRow[] = messageIds.length > 0\n ? await getKnex(em)('attachments')\n .select('record_id')\n .count('* as count')\n .where('entity_id', MESSAGE_ATTACHMENT_ENTITY_ID)\n .whereIn('record_id', messageIds)\n .groupBy('record_id')\n : []\n\n const attachmentCountByMessage = attachmentCounts.reduce((acc: Record<string, number>, row) => {\n acc[row.record_id] = Number(row.count)\n return acc\n }, {})\n\n const recipientCounts: RecipientCountRow[] = messageIds.length > 0\n ? await getKnex(em)('message_recipients')\n .select('message_id')\n .count('* as count')\n .whereIn('message_id', messageIds)\n .whereNull('deleted_at')\n .groupBy('message_id')\n : []\n\n const recipientCountByMessage = recipientCounts.reduce((acc: Record<string, number>, row) => {\n acc[row.message_id] = Number(row.count)\n return acc\n }, {})\n\n const senderUserIds = Array.from(new Set(typedRows.map((row) => row.sender_user_id).filter(Boolean)))\n const senderUsers = senderUserIds.length > 0\n ? await findWithDecryption(\n em,\n User,\n { id: { $in: senderUserIds } },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId }\n )\n : []\n\n const senderMetaById = new Map<string, { name: string | null; email: string | null }>()\n senderUsers.forEach((user) => {\n const name = typeof user.name === 'string' && user.name.trim().length ? user.name.trim() : null\n senderMetaById.set(user.id, { name, email: user.email ?? null })\n })\n\n return Response.json({\n items: typedRows\n .map((row) => {\n const message = messagesById.get(row.id)\n if (!message) return null\n const body = typeof message.body === 'string' ? message.body : ''\n const bodyPreview = body.substring(0, 150) + (body.length > 150 ? '...' : '')\n const actionData = message.actionData ?? null\n return {\n ...(senderMetaById.get(row.sender_user_id)\n ? {\n senderName: senderMetaById.get(row.sender_user_id)?.name ?? null,\n senderEmail: senderMetaById.get(row.sender_user_id)?.email ?? null,\n }\n : { senderName: null, senderEmail: null }),\n id: message.id,\n type: message.type,\n visibility: message.visibility ?? null,\n sourceEntityType: message.sourceEntityType ?? null,\n sourceEntityId: message.sourceEntityId ?? null,\n externalEmail: message.externalEmail ?? null,\n externalName: message.externalName ?? null,\n subject: message.subject,\n bodyPreview,\n senderUserId: message.senderUserId,\n priority: message.priority,\n status: row.recipient_status ?? (row.is_draft ? 'draft' : 'sent'),\n hasObjects: (objectsByMessage[message.id] || []).length > 0,\n objectCount: (objectsByMessage[message.id] || []).length,\n hasAttachments: (attachmentCountByMessage[message.id] || 0) > 0,\n attachmentCount: attachmentCountByMessage[message.id] || 0,\n recipientCount: recipientCountByMessage[message.id] || 0,\n hasActions:\n Boolean(actionData?.actions?.length)\n || Boolean(getMessageType(message.type)?.defaultActions?.length)\n || (objectsByMessage[message.id] || []).some((item) => item.actionRequired && Boolean(item.actionType)),\n actionTaken: message.actionTaken ?? null,\n sentAt: message.sentAt ? message.sentAt.toISOString() : null,\n readAt: row.read_at,\n threadId: message.threadId ?? null,\n }\n })\n .filter((item): item is NonNullable<typeof item> => item !== null),\n page: input.page,\n pageSize: input.pageSize,\n total,\n totalPages: Math.ceil(total / input.pageSize),\n })\n}\n\nexport async function POST(req: Request) {\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 = composeMessageSchema.parse(body)\n\n const isPublicVisibility = input.visibility === 'public'\n const sendViaEmail = isPublicVisibility ? true : input.sendViaEmail\n if (sendViaEmail && !(await canUseMessageEmailFeature(ctx, scope))) {\n return Response.json({ error: 'Missing feature: messages.email' }, { status: 403 })\n }\n\n if (input.objects?.length) {\n const objectValidationError = validateMessageObjectsForType(input.type, input.objects)\n if (objectValidationError) {\n return Response.json({ error: objectValidationError }, { status: 400 })\n }\n }\n\n const { result, logEntry } = await commandBus.execute('messages.messages.compose', {\n input: {\n ...input,\n sendViaEmail,\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 const { id: messageId, threadId: responseThreadId } = result as unknown as MessageCommandExecuteResultWithThreadId\n\n const response = Response.json({ id: messageId, threadId: responseThreadId }, { status: 201 })\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.message',\n resourceId: messageId,\n })\n return response\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n GET: {\n summary: 'List messages',\n query: listSchema,\n responses: [\n {\n status: 200,\n description: 'Message list',\n schema: z.object({\n items: z.array(messageListItemSchema),\n page: z.number(),\n pageSize: z.number(),\n total: z.number(),\n totalPages: z.number(),\n }),\n },\n ],\n },\n POST: {\n summary: 'Compose a message',\n requestBody: {\n schema: composeSchema,\n },\n responses: [\n {\n status: 201,\n description: 'Message created',\n schema: composeResponseSchema,\n },\n ],\n },\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { type Kysely, sql } from 'kysely'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands/command-bus'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { hashForLookup } from '@open-mercato/shared/lib/encryption/aes'\nimport { User } from '../../auth/data/entities'\nimport { Message, MessageObject } from '../data/entities'\nimport { composeMessageSchema, listMessagesSchema } from '../data/validators'\nimport { MESSAGE_ATTACHMENT_ENTITY_ID } from '../lib/constants'\nimport { getMessageType } from '../lib/message-types-registry'\nimport { validateMessageObjectsForType } from '../lib/object-validation'\nimport { attachOperationMetadataHeader } from '../lib/operationMetadata'\nimport { canUseMessageEmailFeature, resolveMessageContext } from '../lib/routeHelpers'\nimport { findMessageIdsBySearchTokens } from '../lib/searchLookup'\nimport { MessageCommandExecuteResult } from '../commands/shared'\nimport {\n composeMessageSchema as composeSchema,\n composeResponseSchema,\n listMessagesSchema as listSchema,\n messageListItemSchema,\n} from './openapi'\n\ntype MessageCommandExecuteResultWithThreadId = MessageCommandExecuteResult & {\n threadId: string\n}\n\nconst NO_MATCH_ID = '00000000-0000-0000-0000-000000000000'\n\nfunction getDb(em: EntityManager): Kysely<any> {\n return em.getKysely<any>()\n}\n\ntype MessageListScopeRow = {\n id: string\n sender_user_id: string\n is_draft: boolean\n recipient_status: string | null\n read_at: string | null\n}\n\ntype AttachmentCountRow = {\n record_id: string\n count: string | number\n}\n\ntype RecipientCountRow = {\n message_id: string\n count: string | number\n}\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['messages.view'] },\n POST: { requireAuth: true, requireFeatures: ['messages.compose'] },\n}\n\nexport async function GET(req: Request) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = ctx.container.resolve('em') as EntityManager\n const url = new URL(req.url)\n const params = Object.fromEntries(url.searchParams)\n const input = listMessagesSchema.parse(params)\n const db = getDb(em) as any\n\n const searchIds = input.search\n ? await findMessageIdsBySearchTokens({\n em,\n query: input.search,\n tenantId: scope.tenantId ?? null,\n organizationId: scope.organizationId,\n })\n : undefined\n\n const buildBaseQuery = () => {\n let q: any = db\n .selectFrom('messages as m')\n .where('m.tenant_id', '=', scope.tenantId)\n .where('m.deleted_at', 'is', null)\n\n if (scope.organizationId) {\n q = q.where('m.organization_id', '=', scope.organizationId)\n } else {\n q = q.where('m.organization_id', 'is', null)\n }\n\n const joinRecipient = () => {\n q = q.leftJoin('message_recipients as r', (jb: any) => jb\n .onRef('m.id', '=', 'r.message_id')\n .on('r.recipient_user_id', '=', scope.userId))\n }\n\n switch (input.folder) {\n case 'inbox':\n joinRecipient()\n q = q\n .where('r.message_id', 'is not', null)\n .where('r.deleted_at', 'is', null)\n .where('r.archived_at', 'is', null)\n .where('m.is_draft', '=', false)\n break\n case 'archived':\n joinRecipient()\n q = q\n .where('r.message_id', 'is not', null)\n .where('r.deleted_at', 'is', null)\n .where('r.archived_at', 'is not', null)\n break\n case 'sent':\n q = q\n .where('m.sender_user_id', '=', scope.userId)\n .where('m.is_draft', '=', false)\n joinRecipient()\n break\n case 'drafts':\n q = q\n .where('m.sender_user_id', '=', scope.userId)\n .where('m.is_draft', '=', true)\n joinRecipient()\n break\n case 'all':\n joinRecipient()\n q = q.where((eb: any) => eb.or([\n eb('m.sender_user_id', '=', scope.userId),\n eb('r.message_id', 'is not', null),\n ]))\n break\n default: {\n const unsupportedFolder: never = input.folder\n throw new Error(`Unsupported folder: ${String(unsupportedFolder)}`)\n }\n }\n\n if (input.status) q = q.where('r.status', '=', input.status)\n if (input.type) q = q.where('m.type', '=', input.type)\n if (input.visibility) q = q.where('m.visibility', '=', input.visibility)\n if (input.sourceEntityType) q = q.where('m.source_entity_type', '=', input.sourceEntityType)\n if (input.sourceEntityId) q = q.where('m.source_entity_id', '=', input.sourceEntityId)\n if (input.externalEmail) q = q.where('m.external_email_hash', '=', hashForLookup(input.externalEmail))\n if (input.senderId) q = q.where('m.sender_user_id', '=', input.senderId)\n\n if (input.search) {\n if (!searchIds || searchIds.length === 0) {\n q = q.where('m.id', '=', NO_MATCH_ID)\n } else {\n q = q.where('m.id', 'in', searchIds)\n }\n }\n\n if (input.since) q = q.where('m.sent_at', '>', new Date(input.since))\n\n if (input.hasObjects !== undefined) {\n const existsFn = (eb: any) => eb.exists(\n eb.selectFrom('message_objects')\n .select(sql<number>`1`.as('one'))\n .whereRef('message_objects.message_id', '=', 'm.id')\n )\n const notExistsFn = (eb: any) => eb.not(eb.exists(\n eb.selectFrom('message_objects')\n .select(sql<number>`1`.as('one'))\n .whereRef('message_objects.message_id', '=', 'm.id')\n ))\n q = input.hasObjects ? q.where(existsFn) : q.where(notExistsFn)\n }\n\n if (input.hasAttachments !== undefined) {\n const existsFn = (eb: any) => eb.exists(\n eb.selectFrom('attachments')\n .select(sql<number>`1`.as('one'))\n .where('attachments.entity_id', '=', MESSAGE_ATTACHMENT_ENTITY_ID)\n .whereRef('attachments.record_id', '=', 'm.id')\n )\n const notExistsFn = (eb: any) => eb.not(eb.exists(\n eb.selectFrom('attachments')\n .select(sql<number>`1`.as('one'))\n .where('attachments.entity_id', '=', MESSAGE_ATTACHMENT_ENTITY_ID)\n .whereRef('attachments.record_id', '=', 'm.id')\n ))\n q = input.hasAttachments ? q.where(existsFn) : q.where(notExistsFn)\n }\n\n if (input.hasActions !== undefined) {\n q = input.hasActions\n ? q.where('m.action_data', 'is not', null)\n : q.where('m.action_data', 'is', null)\n }\n\n return q\n }\n\n const countResult = await buildBaseQuery()\n .select(sql<number>`count(*)`.as('count'))\n .executeTakeFirst() as { count: string | number } | undefined\n const total = Number(countResult?.count ?? 0)\n\n const offset = (input.page - 1) * input.pageSize\n const scopeRows = await buildBaseQuery()\n .select([\n 'm.id',\n 'm.sender_user_id',\n 'm.is_draft',\n 'r.status as recipient_status',\n 'r.read_at',\n ])\n .orderBy('m.sent_at', 'desc')\n .offset(offset)\n .limit(input.pageSize)\n .execute()\n\n const typedRows = scopeRows as MessageListScopeRow[]\n const messageIds = typedRows.map((row) => row.id)\n\n const messageEntities = messageIds.length > 0\n ? await findWithDecryption(\n em,\n Message,\n { id: { $in: messageIds } },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId }\n )\n : []\n\n const messagesById = new Map<string, Message>()\n for (const message of messageEntities) {\n messagesById.set(message.id, message)\n }\n\n const objects = messageIds.length > 0\n ? await em.find(MessageObject, { messageId: { $in: messageIds } })\n : []\n\n const objectsByMessage = objects.reduce((acc, obj) => {\n if (!acc[obj.messageId]) acc[obj.messageId] = []\n acc[obj.messageId].push(obj)\n return acc\n }, {} as Record<string, MessageObject[]>)\n\n const attachmentCounts: AttachmentCountRow[] = messageIds.length > 0\n ? await (getDb(em) as any)\n .selectFrom('attachments')\n .select(['record_id', sql<string>`count(*)`.as('count')])\n .where('entity_id', '=', MESSAGE_ATTACHMENT_ENTITY_ID)\n .where('record_id', 'in', messageIds)\n .groupBy('record_id')\n .execute()\n : []\n\n const attachmentCountByMessage = attachmentCounts.reduce((acc: Record<string, number>, row) => {\n acc[row.record_id] = Number(row.count)\n return acc\n }, {})\n\n const recipientCounts: RecipientCountRow[] = messageIds.length > 0\n ? await (getDb(em) as any)\n .selectFrom('message_recipients')\n .select(['message_id', sql<string>`count(*)`.as('count')])\n .where('message_id', 'in', messageIds)\n .where('deleted_at', 'is', null)\n .groupBy('message_id')\n .execute()\n : []\n\n const recipientCountByMessage = recipientCounts.reduce((acc: Record<string, number>, row) => {\n acc[row.message_id] = Number(row.count)\n return acc\n }, {})\n\n const senderUserIds = Array.from(new Set(typedRows.map((row) => row.sender_user_id).filter(Boolean)))\n const senderUsers = senderUserIds.length > 0\n ? await findWithDecryption(\n em,\n User,\n { id: { $in: senderUserIds } },\n undefined,\n { tenantId: scope.tenantId, organizationId: scope.organizationId }\n )\n : []\n\n const senderMetaById = new Map<string, { name: string | null; email: string | null }>()\n senderUsers.forEach((user) => {\n const name = typeof user.name === 'string' && user.name.trim().length ? user.name.trim() : null\n senderMetaById.set(user.id, { name, email: user.email ?? null })\n })\n\n return Response.json({\n items: typedRows\n .map((row) => {\n const message = messagesById.get(row.id)\n if (!message) return null\n const body = typeof message.body === 'string' ? message.body : ''\n const bodyPreview = body.substring(0, 150) + (body.length > 150 ? '...' : '')\n const actionData = message.actionData ?? null\n return {\n ...(senderMetaById.get(row.sender_user_id)\n ? {\n senderName: senderMetaById.get(row.sender_user_id)?.name ?? null,\n senderEmail: senderMetaById.get(row.sender_user_id)?.email ?? null,\n }\n : { senderName: null, senderEmail: null }),\n id: message.id,\n type: message.type,\n visibility: message.visibility ?? null,\n sourceEntityType: message.sourceEntityType ?? null,\n sourceEntityId: message.sourceEntityId ?? null,\n externalEmail: message.externalEmail ?? null,\n externalName: message.externalName ?? null,\n subject: message.subject,\n bodyPreview,\n senderUserId: message.senderUserId,\n priority: message.priority,\n status: row.recipient_status ?? (row.is_draft ? 'draft' : 'sent'),\n hasObjects: (objectsByMessage[message.id] || []).length > 0,\n objectCount: (objectsByMessage[message.id] || []).length,\n hasAttachments: (attachmentCountByMessage[message.id] || 0) > 0,\n attachmentCount: attachmentCountByMessage[message.id] || 0,\n recipientCount: recipientCountByMessage[message.id] || 0,\n hasActions:\n Boolean(actionData?.actions?.length)\n || Boolean(getMessageType(message.type)?.defaultActions?.length)\n || (objectsByMessage[message.id] || []).some((item) => item.actionRequired && Boolean(item.actionType)),\n actionTaken: message.actionTaken ?? null,\n sentAt: message.sentAt ? message.sentAt.toISOString() : null,\n readAt: row.read_at,\n threadId: message.threadId ?? null,\n }\n })\n .filter((item): item is NonNullable<typeof item> => item !== null),\n page: input.page,\n pageSize: input.pageSize,\n total,\n totalPages: Math.ceil(total / input.pageSize),\n })\n}\n\nexport async function POST(req: Request) {\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 = composeMessageSchema.parse(body)\n\n const isPublicVisibility = input.visibility === 'public'\n const sendViaEmail = isPublicVisibility ? true : input.sendViaEmail\n if (sendViaEmail && !(await canUseMessageEmailFeature(ctx, scope))) {\n return Response.json({ error: 'Missing feature: messages.email' }, { status: 403 })\n }\n\n if (input.objects?.length) {\n const objectValidationError = validateMessageObjectsForType(input.type, input.objects)\n if (objectValidationError) {\n return Response.json({ error: objectValidationError }, { status: 400 })\n }\n }\n\n const { result, logEntry } = await commandBus.execute('messages.messages.compose', {\n input: {\n ...input,\n sendViaEmail,\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 const { id: messageId, threadId: responseThreadId } = result as unknown as MessageCommandExecuteResultWithThreadId\n\n const response = Response.json({ id: messageId, threadId: responseThreadId }, { status: 201 })\n attachOperationMetadataHeader(response, logEntry, {\n resourceKind: 'messages.message',\n resourceId: messageId,\n })\n return response\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n GET: {\n summary: 'List messages',\n query: listSchema,\n responses: [\n {\n status: 200,\n description: 'Message list',\n schema: z.object({\n items: z.array(messageListItemSchema),\n page: z.number(),\n pageSize: z.number(),\n total: z.number(),\n totalPages: z.number(),\n }),\n },\n ],\n },\n POST: {\n summary: 'Compose a message',\n requestBody: {\n schema: composeSchema,\n },\n responses: [\n {\n status: 201,\n description: 'Message created',\n schema: composeResponseSchema,\n },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAElB,SAAsB,WAAW;AAGjC,SAAS,0BAA0B;AACnC,SAAS,qBAAqB;AAC9B,SAAS,YAAY;AACrB,SAAS,SAAS,qBAAqB;AACvC,SAAS,sBAAsB,0BAA0B;AACzD,SAAS,oCAAoC;AAC7C,SAAS,sBAAsB;AAC/B,SAAS,qCAAqC;AAC9C,SAAS,qCAAqC;AAC9C,SAAS,2BAA2B,6BAA6B;AACjE,SAAS,oCAAoC;AAE7C;AAAA,EACE,wBAAwB;AAAA,EACxB;AAAA,EACA,sBAAsB;AAAA,EACtB;AAAA,OACK;AAMP,MAAM,cAAc;AAEpB,SAAS,MAAM,IAAgC;AAC7C,SAAO,GAAG,UAAe;AAC3B;AAoBO,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAAA,EAC7D,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,kBAAkB,EAAE;AACnE;AAEA,eAAsB,IAAI,KAAc;AACtC,QAAM,EAAE,KAAK,MAAM,IAAI,MAAM,sBAAsB,GAAG;AACtD,QAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,QAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,QAAM,SAAS,OAAO,YAAY,IAAI,YAAY;AAClD,QAAM,QAAQ,mBAAmB,MAAM,MAAM;AAC7C,QAAM,KAAK,MAAM,EAAE;AAEnB,QAAM,YAAY,MAAM,SACpB,MAAM,6BAA6B;AAAA,IACjC;AAAA,IACA,OAAO,MAAM;AAAA,IACb,UAAU,MAAM,YAAY;AAAA,IAC5B,gBAAgB,MAAM;AAAA,EACxB,CAAC,IACD;AAEJ,QAAM,iBAAiB,MAAM;AAC3B,QAAI,IAAS,GACV,WAAW,eAAe,EAC1B,MAAM,eAAe,KAAK,MAAM,QAAQ,EACxC,MAAM,gBAAgB,MAAM,IAAI;AAEnC,QAAI,MAAM,gBAAgB;AACxB,UAAI,EAAE,MAAM,qBAAqB,KAAK,MAAM,cAAc;AAAA,IAC5D,OAAO;AACL,UAAI,EAAE,MAAM,qBAAqB,MAAM,IAAI;AAAA,IAC7C;AAEA,UAAM,gBAAgB,MAAM;AAC1B,UAAI,EAAE,SAAS,2BAA2B,CAAC,OAAY,GACpD,MAAM,QAAQ,KAAK,cAAc,EACjC,GAAG,uBAAuB,KAAK,MAAM,MAAM,CAAC;AAAA,IACjD;AAEA,YAAQ,MAAM,QAAQ;AAAA,MACpB,KAAK;AACH,sBAAc;AACd,YAAI,EACD,MAAM,gBAAgB,UAAU,IAAI,EACpC,MAAM,gBAAgB,MAAM,IAAI,EAChC,MAAM,iBAAiB,MAAM,IAAI,EACjC,MAAM,cAAc,KAAK,KAAK;AACjC;AAAA,MACF,KAAK;AACH,sBAAc;AACd,YAAI,EACD,MAAM,gBAAgB,UAAU,IAAI,EACpC,MAAM,gBAAgB,MAAM,IAAI,EAChC,MAAM,iBAAiB,UAAU,IAAI;AACxC;AAAA,MACF,KAAK;AACH,YAAI,EACD,MAAM,oBAAoB,KAAK,MAAM,MAAM,EAC3C,MAAM,cAAc,KAAK,KAAK;AACjC,sBAAc;AACd;AAAA,MACF,KAAK;AACH,YAAI,EACD,MAAM,oBAAoB,KAAK,MAAM,MAAM,EAC3C,MAAM,cAAc,KAAK,IAAI;AAChC,sBAAc;AACd;AAAA,MACF,KAAK;AACH,sBAAc;AACd,YAAI,EAAE,MAAM,CAAC,OAAY,GAAG,GAAG;AAAA,UAC7B,GAAG,oBAAoB,KAAK,MAAM,MAAM;AAAA,UACxC,GAAG,gBAAgB,UAAU,IAAI;AAAA,QACnC,CAAC,CAAC;AACF;AAAA,MACF,SAAS;AACP,cAAM,oBAA2B,MAAM;AACvC,cAAM,IAAI,MAAM,uBAAuB,OAAO,iBAAiB,CAAC,EAAE;AAAA,MACpE;AAAA,IACF;AAEA,QAAI,MAAM,OAAQ,KAAI,EAAE,MAAM,YAAY,KAAK,MAAM,MAAM;AAC3D,QAAI,MAAM,KAAM,KAAI,EAAE,MAAM,UAAU,KAAK,MAAM,IAAI;AACrD,QAAI,MAAM,WAAY,KAAI,EAAE,MAAM,gBAAgB,KAAK,MAAM,UAAU;AACvE,QAAI,MAAM,iBAAkB,KAAI,EAAE,MAAM,wBAAwB,KAAK,MAAM,gBAAgB;AAC3F,QAAI,MAAM,eAAgB,KAAI,EAAE,MAAM,sBAAsB,KAAK,MAAM,cAAc;AACrF,QAAI,MAAM,cAAe,KAAI,EAAE,MAAM,yBAAyB,KAAK,cAAc,MAAM,aAAa,CAAC;AACrG,QAAI,MAAM,SAAU,KAAI,EAAE,MAAM,oBAAoB,KAAK,MAAM,QAAQ;AAEvE,QAAI,MAAM,QAAQ;AAChB,UAAI,CAAC,aAAa,UAAU,WAAW,GAAG;AACxC,YAAI,EAAE,MAAM,QAAQ,KAAK,WAAW;AAAA,MACtC,OAAO;AACL,YAAI,EAAE,MAAM,QAAQ,MAAM,SAAS;AAAA,MACrC;AAAA,IACF;AAEA,QAAI,MAAM,MAAO,KAAI,EAAE,MAAM,aAAa,KAAK,IAAI,KAAK,MAAM,KAAK,CAAC;AAEpE,QAAI,MAAM,eAAe,QAAW;AAClC,YAAM,WAAW,CAAC,OAAY,GAAG;AAAA,QAC/B,GAAG,WAAW,iBAAiB,EAC5B,OAAO,OAAe,GAAG,KAAK,CAAC,EAC/B,SAAS,8BAA8B,KAAK,MAAM;AAAA,MACvD;AACA,YAAM,cAAc,CAAC,OAAY,GAAG,IAAI,GAAG;AAAA,QACzC,GAAG,WAAW,iBAAiB,EAC5B,OAAO,OAAe,GAAG,KAAK,CAAC,EAC/B,SAAS,8BAA8B,KAAK,MAAM;AAAA,MACvD,CAAC;AACD,UAAI,MAAM,aAAa,EAAE,MAAM,QAAQ,IAAI,EAAE,MAAM,WAAW;AAAA,IAChE;AAEA,QAAI,MAAM,mBAAmB,QAAW;AACtC,YAAM,WAAW,CAAC,OAAY,GAAG;AAAA,QAC/B,GAAG,WAAW,aAAa,EACxB,OAAO,OAAe,GAAG,KAAK,CAAC,EAC/B,MAAM,yBAAyB,KAAK,4BAA4B,EAChE,SAAS,yBAAyB,KAAK,MAAM;AAAA,MAClD;AACA,YAAM,cAAc,CAAC,OAAY,GAAG,IAAI,GAAG;AAAA,QACzC,GAAG,WAAW,aAAa,EACxB,OAAO,OAAe,GAAG,KAAK,CAAC,EAC/B,MAAM,yBAAyB,KAAK,4BAA4B,EAChE,SAAS,yBAAyB,KAAK,MAAM;AAAA,MAClD,CAAC;AACD,UAAI,MAAM,iBAAiB,EAAE,MAAM,QAAQ,IAAI,EAAE,MAAM,WAAW;AAAA,IACpE;AAEA,QAAI,MAAM,eAAe,QAAW;AAClC,UAAI,MAAM,aACN,EAAE,MAAM,iBAAiB,UAAU,IAAI,IACvC,EAAE,MAAM,iBAAiB,MAAM,IAAI;AAAA,IACzC;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,cAAc,MAAM,eAAe,EACtC,OAAO,cAAsB,GAAG,OAAO,CAAC,EACxC,iBAAiB;AACpB,QAAM,QAAQ,OAAO,aAAa,SAAS,CAAC;AAE5C,QAAM,UAAU,MAAM,OAAO,KAAK,MAAM;AACxC,QAAM,YAAY,MAAM,eAAe,EACpC,OAAO;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,EACA,QAAQ,aAAa,MAAM,EAC3B,OAAO,MAAM,EACb,MAAM,MAAM,QAAQ,EACpB,QAAQ;AAEX,QAAM,YAAY;AAClB,QAAM,aAAa,UAAU,IAAI,CAAC,QAAQ,IAAI,EAAE;AAEhD,QAAM,kBAAkB,WAAW,SAAS,IACxC,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE;AAAA,IAC1B;AAAA,IACA,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,EACnE,IACA,CAAC;AAEL,QAAM,eAAe,oBAAI,IAAqB;AAC9C,aAAW,WAAW,iBAAiB;AACrC,iBAAa,IAAI,QAAQ,IAAI,OAAO;AAAA,EACtC;AAEA,QAAM,UAAU,WAAW,SAAS,IAChC,MAAM,GAAG,KAAK,eAAe,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,CAAC,IAC/D,CAAC;AAEL,QAAM,mBAAmB,QAAQ,OAAO,CAAC,KAAK,QAAQ;AACpD,QAAI,CAAC,IAAI,IAAI,SAAS,EAAG,KAAI,IAAI,SAAS,IAAI,CAAC;AAC/C,QAAI,IAAI,SAAS,EAAE,KAAK,GAAG;AAC3B,WAAO;AAAA,EACT,GAAG,CAAC,CAAoC;AAExC,QAAM,mBAAyC,WAAW,SAAS,IAC/D,MAAO,MAAM,EAAE,EACZ,WAAW,aAAa,EACxB,OAAO,CAAC,aAAa,cAAsB,GAAG,OAAO,CAAC,CAAC,EACvD,MAAM,aAAa,KAAK,4BAA4B,EACpD,MAAM,aAAa,MAAM,UAAU,EACnC,QAAQ,WAAW,EACnB,QAAQ,IACX,CAAC;AAEL,QAAM,2BAA2B,iBAAiB,OAAO,CAAC,KAA6B,QAAQ;AAC7F,QAAI,IAAI,SAAS,IAAI,OAAO,IAAI,KAAK;AACrC,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,kBAAuC,WAAW,SAAS,IAC7D,MAAO,MAAM,EAAE,EACZ,WAAW,oBAAoB,EAC/B,OAAO,CAAC,cAAc,cAAsB,GAAG,OAAO,CAAC,CAAC,EACxD,MAAM,cAAc,MAAM,UAAU,EACpC,MAAM,cAAc,MAAM,IAAI,EAC9B,QAAQ,YAAY,EACpB,QAAQ,IACX,CAAC;AAEL,QAAM,0BAA0B,gBAAgB,OAAO,CAAC,KAA6B,QAAQ;AAC3F,QAAI,IAAI,UAAU,IAAI,OAAO,IAAI,KAAK;AACtC,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgB,MAAM,KAAK,IAAI,IAAI,UAAU,IAAI,CAAC,QAAQ,IAAI,cAAc,EAAE,OAAO,OAAO,CAAC,CAAC;AACpG,QAAM,cAAc,cAAc,SAAS,IACvC,MAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,EAAE,IAAI,EAAE,KAAK,cAAc,EAAE;AAAA,IAC7B;AAAA,IACA,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAAA,EACnE,IACA,CAAC;AAEL,QAAM,iBAAiB,oBAAI,IAA2D;AACtF,cAAY,QAAQ,CAAC,SAAS;AAC5B,UAAM,OAAO,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,KAAK,EAAE,SAAS,KAAK,KAAK,KAAK,IAAI;AAC3F,mBAAe,IAAI,KAAK,IAAI,EAAE,MAAM,OAAO,KAAK,SAAS,KAAK,CAAC;AAAA,EACjE,CAAC;AAED,SAAO,SAAS,KAAK;AAAA,IACnB,OAAO,UACJ,IAAI,CAAC,QAAQ;AACZ,YAAM,UAAU,aAAa,IAAI,IAAI,EAAE;AACvC,UAAI,CAAC,QAAS,QAAO;AACrB,YAAM,OAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,OAAO;AAC/D,YAAM,cAAc,KAAK,UAAU,GAAG,GAAG,KAAK,KAAK,SAAS,MAAM,QAAQ;AAC1E,YAAM,aAAa,QAAQ,cAAc;AACzC,aAAO;AAAA,QACL,GAAI,eAAe,IAAI,IAAI,cAAc,IACrC;AAAA,UACE,YAAY,eAAe,IAAI,IAAI,cAAc,GAAG,QAAQ;AAAA,UAC5D,aAAa,eAAe,IAAI,IAAI,cAAc,GAAG,SAAS;AAAA,QAChE,IACA,EAAE,YAAY,MAAM,aAAa,KAAK;AAAA,QAC1C,IAAI,QAAQ;AAAA,QACZ,MAAM,QAAQ;AAAA,QACd,YAAY,QAAQ,cAAc;AAAA,QAClC,kBAAkB,QAAQ,oBAAoB;AAAA,QAC9C,gBAAgB,QAAQ,kBAAkB;AAAA,QAC1C,eAAe,QAAQ,iBAAiB;AAAA,QACxC,cAAc,QAAQ,gBAAgB;AAAA,QACtC,SAAS,QAAQ;AAAA,QACjB;AAAA,QACA,cAAc,QAAQ;AAAA,QACtB,UAAU,QAAQ;AAAA,QAClB,QAAQ,IAAI,qBAAqB,IAAI,WAAW,UAAU;AAAA,QAC1D,aAAa,iBAAiB,QAAQ,EAAE,KAAK,CAAC,GAAG,SAAS;AAAA,QAC1D,cAAc,iBAAiB,QAAQ,EAAE,KAAK,CAAC,GAAG;AAAA,QAClD,iBAAiB,yBAAyB,QAAQ,EAAE,KAAK,KAAK;AAAA,QAC9D,iBAAiB,yBAAyB,QAAQ,EAAE,KAAK;AAAA,QACzD,gBAAgB,wBAAwB,QAAQ,EAAE,KAAK;AAAA,QACvD,YACE,QAAQ,YAAY,SAAS,MAAM,KAChC,QAAQ,eAAe,QAAQ,IAAI,GAAG,gBAAgB,MAAM,MAC3D,iBAAiB,QAAQ,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC,SAAS,KAAK,kBAAkB,QAAQ,KAAK,UAAU,CAAC;AAAA,QACxG,aAAa,QAAQ,eAAe;AAAA,QACpC,QAAQ,QAAQ,SAAS,QAAQ,OAAO,YAAY,IAAI;AAAA,QACxD,QAAQ,IAAI;AAAA,QACZ,UAAU,QAAQ,YAAY;AAAA,MAChC;AAAA,IACF,CAAC,EACA,OAAO,CAAC,SAA2C,SAAS,IAAI;AAAA,IACnE,MAAM,MAAM;AAAA,IACZ,UAAU,MAAM;AAAA,IAChB;AAAA,IACA,YAAY,KAAK,KAAK,QAAQ,MAAM,QAAQ;AAAA,EAC9C,CAAC;AACH;AAEA,eAAsB,KAAK,KAAc;AACvC,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,qBAAqB,MAAM,IAAI;AAE7C,QAAM,qBAAqB,MAAM,eAAe;AAChD,QAAM,eAAe,qBAAqB,OAAO,MAAM;AACvD,MAAI,gBAAgB,CAAE,MAAM,0BAA0B,KAAK,KAAK,GAAI;AAClE,WAAO,SAAS,KAAK,EAAE,OAAO,kCAAkC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACpF;AAEA,MAAI,MAAM,SAAS,QAAQ;AACzB,UAAM,wBAAwB,8BAA8B,MAAM,MAAM,MAAM,OAAO;AACrF,QAAI,uBAAuB;AACzB,aAAO,SAAS,KAAK,EAAE,OAAO,sBAAsB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACxE;AAAA,EACF;AAEA,QAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,WAAW,QAAQ,6BAA6B;AAAA,IACjF,OAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,MACA,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;AACD,QAAM,EAAE,IAAI,WAAW,UAAU,iBAAiB,IAAI;AAEtD,QAAM,WAAW,SAAS,KAAK,EAAE,IAAI,WAAW,UAAU,iBAAiB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAC7F,gCAA8B,UAAU,UAAU;AAAA,IAChD,cAAc;AAAA,IACd,YAAY;AAAA,EACd,CAAC;AACD,SAAO;AACT;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,OAAO;AAAA,MACP,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,EAAE,OAAO;AAAA,YACf,OAAO,EAAE,MAAM,qBAAqB;AAAA,YACpC,MAAM,EAAE,OAAO;AAAA,YACf,UAAU,EAAE,OAAO;AAAA,YACnB,OAAO,EAAE,OAAO;AAAA,YAChB,YAAY,EAAE,OAAO;AAAA,UACvB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,SAAS;AAAA,MACT,aAAa;AAAA,QACX,QAAQ;AAAA,MACV;AAAA,MACA,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,22 +1,23 @@
1
+ import { sql } from "kysely";
1
2
  import { resolveMessageContext } from "../../lib/routeHelpers.js";
2
3
  import { unreadCountResponseSchema } from "../openapi.js";
3
4
  const metadata = {
4
5
  GET: { requireAuth: true, requireFeatures: ["messages.view"] }
5
6
  };
6
- function getKnex(em) {
7
- return em.getConnection().getKnex();
7
+ function getDb(em) {
8
+ return em.getKysely();
8
9
  }
9
10
  async function GET(req) {
10
11
  const { ctx, scope } = await resolveMessageContext(req);
11
12
  const em = ctx.container.resolve("em");
12
- const knex = getKnex(em);
13
- let query = knex("message_recipients as r").join("messages as m", "m.id", "r.message_id").where("r.recipient_user_id", scope.userId).where("r.status", "unread").whereNull("r.deleted_at").whereNull("r.archived_at").where("m.tenant_id", scope.tenantId).whereNull("m.deleted_at");
13
+ const db = getDb(em);
14
+ let query = db.selectFrom("message_recipients as r").innerJoin("messages as m", "m.id", "r.message_id").where("r.recipient_user_id", "=", scope.userId).where("r.status", "=", "unread").where("r.deleted_at", "is", null).where("r.archived_at", "is", null).where("m.tenant_id", "=", scope.tenantId).where("m.deleted_at", "is", null);
14
15
  if (scope.organizationId) {
15
- query = query.where("m.organization_id", scope.organizationId);
16
+ query = query.where("m.organization_id", "=", scope.organizationId);
16
17
  } else {
17
- query = query.whereNull("m.organization_id");
18
+ query = query.where("m.organization_id", "is", null);
18
19
  }
19
- const row = await query.count("* as count").first();
20
+ const row = await query.select(sql`count(*)`.as("count")).executeTakeFirst();
20
21
  const count = Number(row?.count ?? 0);
21
22
  return Response.json({ unreadCount: count });
22
23
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/messages/api/unread-count/route.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { Knex } from 'knex'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { resolveMessageContext } from '../../lib/routeHelpers'\nimport { unreadCountResponseSchema } from '../openapi'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['messages.view'] },\n}\n\nfunction getKnex(em: EntityManager): Knex {\n return (em.getConnection() as unknown as { getKnex: () => Knex }).getKnex()\n}\n\nexport async function GET(req: Request) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = ctx.container.resolve('em') as EntityManager\n const knex = getKnex(em)\n\n let query = knex('message_recipients as r')\n .join('messages as m', 'm.id', 'r.message_id')\n .where('r.recipient_user_id', scope.userId)\n .where('r.status', 'unread')\n .whereNull('r.deleted_at')\n .whereNull('r.archived_at')\n .where('m.tenant_id', scope.tenantId)\n .whereNull('m.deleted_at')\n\n if (scope.organizationId) {\n query = query.where('m.organization_id', scope.organizationId)\n } else {\n query = query.whereNull('m.organization_id')\n }\n\n const row = await query.count('* as count').first<{ count: string | number }>()\n const count = Number(row?.count ?? 0)\n\n return Response.json({ unreadCount: count })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n GET: {\n summary: 'Get unread message count',\n responses: [\n {\n status: 200,\n description: 'Unread count',\n schema: unreadCountResponseSchema,\n },\n ],\n },\n },\n}\n"],
5
- "mappings": "AAGA,SAAS,6BAA6B;AACtC,SAAS,iCAAiC;AAEnC,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAC/D;AAEA,SAAS,QAAQ,IAAyB;AACxC,SAAQ,GAAG,cAAc,EAAyC,QAAQ;AAC5E;AAEA,eAAsB,IAAI,KAAc;AACtC,QAAM,EAAE,KAAK,MAAM,IAAI,MAAM,sBAAsB,GAAG;AACtD,QAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,QAAM,OAAO,QAAQ,EAAE;AAEvB,MAAI,QAAQ,KAAK,yBAAyB,EACvC,KAAK,iBAAiB,QAAQ,cAAc,EAC5C,MAAM,uBAAuB,MAAM,MAAM,EACzC,MAAM,YAAY,QAAQ,EAC1B,UAAU,cAAc,EACxB,UAAU,eAAe,EACzB,MAAM,eAAe,MAAM,QAAQ,EACnC,UAAU,cAAc;AAE3B,MAAI,MAAM,gBAAgB;AACxB,YAAQ,MAAM,MAAM,qBAAqB,MAAM,cAAc;AAAA,EAC/D,OAAO;AACL,YAAQ,MAAM,UAAU,mBAAmB;AAAA,EAC7C;AAEA,QAAM,MAAM,MAAM,MAAM,MAAM,YAAY,EAAE,MAAkC;AAC9E,QAAM,QAAQ,OAAO,KAAK,SAAS,CAAC;AAEpC,SAAO,SAAS,KAAK,EAAE,aAAa,MAAM,CAAC;AAC7C;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { type Kysely, sql } from 'kysely'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi/types'\nimport { resolveMessageContext } from '../../lib/routeHelpers'\nimport { unreadCountResponseSchema } from '../openapi'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['messages.view'] },\n}\n\nfunction getDb(em: EntityManager): Kysely<any> {\n return em.getKysely<any>()\n}\n\nexport async function GET(req: Request) {\n const { ctx, scope } = await resolveMessageContext(req)\n const em = ctx.container.resolve('em') as EntityManager\n const db = getDb(em) as any\n\n let query = db\n .selectFrom('message_recipients as r')\n .innerJoin('messages as m', 'm.id', 'r.message_id')\n .where('r.recipient_user_id', '=', scope.userId)\n .where('r.status', '=', 'unread')\n .where('r.deleted_at', 'is', null)\n .where('r.archived_at', 'is', null)\n .where('m.tenant_id', '=', scope.tenantId)\n .where('m.deleted_at', 'is', null)\n\n if (scope.organizationId) {\n query = query.where('m.organization_id', '=', scope.organizationId)\n } else {\n query = query.where('m.organization_id', 'is', null)\n }\n\n const row = await query\n .select(sql<number>`count(*)`.as('count'))\n .executeTakeFirst() as { count: string | number } | undefined\n const count = Number(row?.count ?? 0)\n\n return Response.json({ unreadCount: count })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Messages',\n methods: {\n GET: {\n summary: 'Get unread message count',\n responses: [\n {\n status: 200,\n description: 'Unread count',\n schema: unreadCountResponseSchema,\n },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AACA,SAAsB,WAAW;AAEjC,SAAS,6BAA6B;AACtC,SAAS,iCAAiC;AAEnC,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,eAAe,EAAE;AAC/D;AAEA,SAAS,MAAM,IAAgC;AAC7C,SAAO,GAAG,UAAe;AAC3B;AAEA,eAAsB,IAAI,KAAc;AACtC,QAAM,EAAE,KAAK,MAAM,IAAI,MAAM,sBAAsB,GAAG;AACtD,QAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,QAAM,KAAK,MAAM,EAAE;AAEnB,MAAI,QAAQ,GACT,WAAW,yBAAyB,EACpC,UAAU,iBAAiB,QAAQ,cAAc,EACjD,MAAM,uBAAuB,KAAK,MAAM,MAAM,EAC9C,MAAM,YAAY,KAAK,QAAQ,EAC/B,MAAM,gBAAgB,MAAM,IAAI,EAChC,MAAM,iBAAiB,MAAM,IAAI,EACjC,MAAM,eAAe,KAAK,MAAM,QAAQ,EACxC,MAAM,gBAAgB,MAAM,IAAI;AAEnC,MAAI,MAAM,gBAAgB;AACxB,YAAQ,MAAM,MAAM,qBAAqB,KAAK,MAAM,cAAc;AAAA,EACpE,OAAO;AACL,YAAQ,MAAM,MAAM,qBAAqB,MAAM,IAAI;AAAA,EACrD;AAEA,QAAM,MAAM,MAAM,MACf,OAAO,cAAsB,GAAG,OAAO,CAAC,EACxC,iBAAiB;AACpB,QAAM,QAAQ,OAAO,KAAK,SAAS,CAAC;AAEpC,SAAO,SAAS,KAAK,EAAE,aAAa,MAAM,CAAC;AAC7C;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -71,7 +71,7 @@ const confirmMessageCommand = {
71
71
  confirmation.confirmed = input.confirmed;
72
72
  confirmation.confirmedByUserId = actorUserId;
73
73
  confirmation.confirmedAt = input.confirmed ? /* @__PURE__ */ new Date() : null;
74
- await em.persistAndFlush(confirmation);
74
+ await em.persist(confirmation).flush();
75
75
  return {
76
76
  messageId: confirmation.messageId,
77
77
  confirmed: confirmation.confirmed,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/messages/commands/confirmations.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { extractUndoPayload, type UndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { Message, MessageConfirmation, MessageRecipient } from '../data/entities'\nimport { confirmMessageSchema } from '../data/validators'\n\ntype ConfirmMessageResult = {\n messageId: string\n confirmed: boolean\n confirmedAt: string | null\n confirmedByUserId: string | null\n}\n\ntype ConfirmationSnapshot = {\n id: string | null\n messageId: string\n confirmed: boolean\n confirmedAt: string | null\n confirmedByUserId: string | null\n tenantId: string\n organizationId: string | null\n}\n\nfunction toIso(value: Date | null | undefined): string | null {\n return value ? value.toISOString() : null\n}\n\nfunction toDate(value: string | null | undefined): Date | null {\n if (!value) return null\n return new Date(value)\n}\n\nconst confirmMessageCommand: CommandHandler<unknown, ConfirmMessageResult> = {\n id: 'messages.confirmations.confirm',\n async prepare(rawInput, ctx) {\n const input = confirmMessageSchema.parse(rawInput)\n const tenantId = input.tenantId ?? ctx.auth?.tenantId ?? null\n if (!tenantId) throw new Error('Tenant scope is required')\n const organizationId = input.organizationId ?? ctx.selectedOrganizationId ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(MessageConfirmation, { messageId: input.messageId })\n return {\n before: {\n id: existing?.id ?? null,\n messageId: input.messageId,\n confirmed: existing?.confirmed ?? false,\n confirmedAt: toIso(existing?.confirmedAt),\n confirmedByUserId: existing?.confirmedByUserId ?? null,\n tenantId,\n organizationId,\n } satisfies ConfirmationSnapshot,\n }\n },\n async execute(rawInput, ctx) {\n const input = confirmMessageSchema.parse(rawInput)\n const tenantId = input.tenantId ?? ctx.auth?.tenantId ?? null\n\n if (!tenantId) {\n throw new Error('Tenant scope is required')\n }\n\n const organizationId = input.organizationId ?? ctx.selectedOrganizationId ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const message = await em.findOne(Message, {\n id: input.messageId,\n tenantId,\n organizationId,\n deletedAt: null,\n })\n\n if (!message) {\n throw new Error('Message not found')\n }\n\n const actorUserId = ctx.auth?.sub ?? null\n if (!actorUserId) {\n throw new Error('Authentication required')\n }\n\n const recipient = await em.findOne(MessageRecipient, {\n messageId: message.id,\n recipientUserId: actorUserId,\n deletedAt: null,\n })\n const isSender = message.senderUserId === actorUserId\n if (!isSender && !recipient) {\n throw new Error('Access denied')\n }\n\n let confirmation = await em.findOne(MessageConfirmation, { messageId: message.id })\n if (!confirmation) {\n confirmation = em.create(MessageConfirmation, {\n messageId: message.id,\n tenantId,\n organizationId,\n })\n }\n\n confirmation.confirmed = input.confirmed\n confirmation.confirmedByUserId = actorUserId\n confirmation.confirmedAt = input.confirmed ? new Date() : null\n\n await em.persistAndFlush(confirmation)\n\n return {\n messageId: confirmation.messageId,\n confirmed: confirmation.confirmed,\n confirmedAt: confirmation.confirmedAt ? confirmation.confirmedAt.toISOString() : null,\n confirmedByUserId: confirmation.confirmedByUserId ?? null,\n }\n },\n async captureAfter(rawInput, _result, ctx) {\n const input = confirmMessageSchema.parse(rawInput)\n const tenantId = input.tenantId ?? ctx.auth?.tenantId ?? null\n if (!tenantId) return null\n const organizationId = input.organizationId ?? ctx.selectedOrganizationId ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const confirmation = await em.findOne(MessageConfirmation, { messageId: input.messageId })\n return {\n id: confirmation?.id ?? null,\n messageId: input.messageId,\n confirmed: confirmation?.confirmed ?? false,\n confirmedAt: toIso(confirmation?.confirmedAt),\n confirmedByUserId: confirmation?.confirmedByUserId ?? null,\n tenantId,\n organizationId,\n } satisfies ConfirmationSnapshot\n },\n async buildLog({ input, snapshots }) {\n const parsed = confirmMessageSchema.parse(input)\n return {\n actionLabel: parsed.confirmed ? 'Confirm message' : 'Unconfirm message',\n resourceKind: 'messages.message',\n resourceId: parsed.messageId,\n tenantId: parsed.tenantId ?? null,\n organizationId: parsed.organizationId ?? null,\n payload: {\n undo: {\n before: (snapshots.before as ConfirmationSnapshot | undefined) ?? null,\n after: (snapshots.after as ConfirmationSnapshot | undefined) ?? null,\n } satisfies UndoPayload<ConfirmationSnapshot>,\n },\n snapshotBefore: snapshots.before ?? null,\n snapshotAfter: snapshots.after ?? null,\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<UndoPayload<ConfirmationSnapshot>>(logEntry)\n const before = undo?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(MessageConfirmation, { messageId: before.messageId })\n if (!before.id) {\n if (existing) {\n em.remove(existing)\n await em.flush()\n }\n return\n }\n if (!existing) {\n em.persist(em.create(MessageConfirmation, {\n id: before.id,\n messageId: before.messageId,\n confirmed: before.confirmed,\n confirmedAt: toDate(before.confirmedAt),\n confirmedByUserId: before.confirmedByUserId,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n }))\n } else {\n existing.confirmed = before.confirmed\n existing.confirmedAt = toDate(before.confirmedAt)\n existing.confirmedByUserId = before.confirmedByUserId\n existing.tenantId = before.tenantId\n existing.organizationId = before.organizationId\n }\n await em.flush()\n },\n}\n\nregisterCommand(confirmMessageCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { extractUndoPayload, type UndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { Message, MessageConfirmation, MessageRecipient } from '../data/entities'\nimport { confirmMessageSchema } from '../data/validators'\n\ntype ConfirmMessageResult = {\n messageId: string\n confirmed: boolean\n confirmedAt: string | null\n confirmedByUserId: string | null\n}\n\ntype ConfirmationSnapshot = {\n id: string | null\n messageId: string\n confirmed: boolean\n confirmedAt: string | null\n confirmedByUserId: string | null\n tenantId: string\n organizationId: string | null\n}\n\nfunction toIso(value: Date | null | undefined): string | null {\n return value ? value.toISOString() : null\n}\n\nfunction toDate(value: string | null | undefined): Date | null {\n if (!value) return null\n return new Date(value)\n}\n\nconst confirmMessageCommand: CommandHandler<unknown, ConfirmMessageResult> = {\n id: 'messages.confirmations.confirm',\n async prepare(rawInput, ctx) {\n const input = confirmMessageSchema.parse(rawInput)\n const tenantId = input.tenantId ?? ctx.auth?.tenantId ?? null\n if (!tenantId) throw new Error('Tenant scope is required')\n const organizationId = input.organizationId ?? ctx.selectedOrganizationId ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(MessageConfirmation, { messageId: input.messageId })\n return {\n before: {\n id: existing?.id ?? null,\n messageId: input.messageId,\n confirmed: existing?.confirmed ?? false,\n confirmedAt: toIso(existing?.confirmedAt),\n confirmedByUserId: existing?.confirmedByUserId ?? null,\n tenantId,\n organizationId,\n } satisfies ConfirmationSnapshot,\n }\n },\n async execute(rawInput, ctx) {\n const input = confirmMessageSchema.parse(rawInput)\n const tenantId = input.tenantId ?? ctx.auth?.tenantId ?? null\n\n if (!tenantId) {\n throw new Error('Tenant scope is required')\n }\n\n const organizationId = input.organizationId ?? ctx.selectedOrganizationId ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n const message = await em.findOne(Message, {\n id: input.messageId,\n tenantId,\n organizationId,\n deletedAt: null,\n })\n\n if (!message) {\n throw new Error('Message not found')\n }\n\n const actorUserId = ctx.auth?.sub ?? null\n if (!actorUserId) {\n throw new Error('Authentication required')\n }\n\n const recipient = await em.findOne(MessageRecipient, {\n messageId: message.id,\n recipientUserId: actorUserId,\n deletedAt: null,\n })\n const isSender = message.senderUserId === actorUserId\n if (!isSender && !recipient) {\n throw new Error('Access denied')\n }\n\n let confirmation = await em.findOne(MessageConfirmation, { messageId: message.id })\n if (!confirmation) {\n confirmation = em.create(MessageConfirmation, {\n messageId: message.id,\n tenantId,\n organizationId,\n })\n }\n\n confirmation.confirmed = input.confirmed\n confirmation.confirmedByUserId = actorUserId\n confirmation.confirmedAt = input.confirmed ? new Date() : null\n\n await em.persist(confirmation).flush()\n\n return {\n messageId: confirmation.messageId,\n confirmed: confirmation.confirmed,\n confirmedAt: confirmation.confirmedAt ? confirmation.confirmedAt.toISOString() : null,\n confirmedByUserId: confirmation.confirmedByUserId ?? null,\n }\n },\n async captureAfter(rawInput, _result, ctx) {\n const input = confirmMessageSchema.parse(rawInput)\n const tenantId = input.tenantId ?? ctx.auth?.tenantId ?? null\n if (!tenantId) return null\n const organizationId = input.organizationId ?? ctx.selectedOrganizationId ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const confirmation = await em.findOne(MessageConfirmation, { messageId: input.messageId })\n return {\n id: confirmation?.id ?? null,\n messageId: input.messageId,\n confirmed: confirmation?.confirmed ?? false,\n confirmedAt: toIso(confirmation?.confirmedAt),\n confirmedByUserId: confirmation?.confirmedByUserId ?? null,\n tenantId,\n organizationId,\n } satisfies ConfirmationSnapshot\n },\n async buildLog({ input, snapshots }) {\n const parsed = confirmMessageSchema.parse(input)\n return {\n actionLabel: parsed.confirmed ? 'Confirm message' : 'Unconfirm message',\n resourceKind: 'messages.message',\n resourceId: parsed.messageId,\n tenantId: parsed.tenantId ?? null,\n organizationId: parsed.organizationId ?? null,\n payload: {\n undo: {\n before: (snapshots.before as ConfirmationSnapshot | undefined) ?? null,\n after: (snapshots.after as ConfirmationSnapshot | undefined) ?? null,\n } satisfies UndoPayload<ConfirmationSnapshot>,\n },\n snapshotBefore: snapshots.before ?? null,\n snapshotAfter: snapshots.after ?? null,\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const undo = extractUndoPayload<UndoPayload<ConfirmationSnapshot>>(logEntry)\n const before = undo?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(MessageConfirmation, { messageId: before.messageId })\n if (!before.id) {\n if (existing) {\n em.remove(existing)\n await em.flush()\n }\n return\n }\n if (!existing) {\n em.persist(em.create(MessageConfirmation, {\n id: before.id,\n messageId: before.messageId,\n confirmed: before.confirmed,\n confirmedAt: toDate(before.confirmedAt),\n confirmedByUserId: before.confirmedByUserId,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n }))\n } else {\n existing.confirmed = before.confirmed\n existing.confirmedAt = toDate(before.confirmedAt)\n existing.confirmedByUserId = before.confirmedByUserId\n existing.tenantId = before.tenantId\n existing.organizationId = before.organizationId\n }\n await em.flush()\n },\n}\n\nregisterCommand(confirmMessageCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -161,7 +161,7 @@ const composeMessageCommand = {
161
161
  tenantId: input.tenantId,
162
162
  organizationId: input.organizationId
163
163
  });
164
- await trx.persistAndFlush(message);
164
+ await trx.persist(message).flush();
165
165
  if (!threadId && !input.isDraft && !message.threadId) {
166
166
  message.threadId = message.id;
167
167
  await trx.flush();
@@ -468,7 +468,7 @@ const replyMessageCommand = {
468
468
  tenantId: input.tenantId,
469
469
  organizationId: input.organizationId
470
470
  });
471
- await trx.persistAndFlush(message);
471
+ await trx.persist(message).flush();
472
472
  for (const recipientUserId of recipientIds) {
473
473
  trx.persist(trx.create(MessageRecipient, {
474
474
  messageId: message.id,
@@ -603,7 +603,7 @@ const forwardMessageCommand = {
603
603
  tenantId: input.tenantId,
604
604
  organizationId: input.organizationId
605
605
  });
606
- await trx.persistAndFlush(newMessage);
606
+ await trx.persist(newMessage).flush();
607
607
  for (const recipient of input.recipients) {
608
608
  trx.persist(trx.create(MessageRecipient, {
609
609
  messageId: newMessage.id,