@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,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/inbox_ops/api/proposals/counts/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { runWithCacheTenant } from '@open-mercato/cache'\nimport { InboxProposal } from '../../../data/entities'\nimport { ALL_CATEGORIES } from '../../../data/validators'\nimport { resolveRequestContext, UnauthorizedError } from '../../routeHelpers'\nimport {\n resolveCache,\n createCountsCacheKey,\n createCountsCacheTag,\n COUNTS_CACHE_TTL_MS,\n} from '../../../lib/cache'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['inbox_ops.proposals.view'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const ctx = await resolveRequestContext(req)\n const cache = resolveCache(ctx.container)\n\n if (cache) {\n const cacheKey = createCountsCacheKey(ctx.tenantId)\n const cached = await runWithCacheTenant(ctx.tenantId, () => cache.get(cacheKey))\n if (cached) {\n return NextResponse.json(cached)\n }\n }\n\n const scope = {\n organizationId: ctx.organizationId,\n tenantId: ctx.tenantId,\n deletedAt: null,\n isActive: true,\n }\n\n // em.count() is safe here \u2014 filter fields (status, organizationId, tenantId,\n // deletedAt, isActive, category) are not encrypted, so decryption helpers are not needed.\n const [pending, partial, accepted, rejected] = await Promise.all([\n ctx.em.count(InboxProposal, { ...scope, status: 'pending' }),\n ctx.em.count(InboxProposal, { ...scope, status: 'partial' }),\n ctx.em.count(InboxProposal, { ...scope, status: 'accepted' }),\n ctx.em.count(InboxProposal, { ...scope, status: 'rejected' }),\n ])\n\n // Single GROUP BY query for category counts \u2014 O(1) queries\n const knex = ctx.em.getKnex()\n const categoryRows = await knex('inbox_proposals')\n .select('category')\n .count('* as count')\n .where({\n organization_id: ctx.organizationId,\n tenant_id: ctx.tenantId,\n is_active: true,\n })\n .whereNull('deleted_at')\n .groupBy('category')\n\n const byCategory: Record<string, number> = {}\n for (const cat of ALL_CATEGORIES) {\n byCategory[cat] = 0\n }\n for (const row of categoryRows) {\n const cat = row.category as string | null\n if (cat && cat in byCategory) {\n byCategory[cat] = Number(row.count)\n }\n }\n\n const responseBody = { pending, partial, accepted, rejected, byCategory }\n\n if (cache) {\n const cacheKey = createCountsCacheKey(ctx.tenantId)\n const tag = createCountsCacheTag(ctx.tenantId)\n try {\n await runWithCacheTenant(ctx.tenantId, () =>\n cache.set(cacheKey, responseBody, { ttl: COUNTS_CACHE_TTL_MS, tags: [tag] }),\n )\n } catch (err) {\n console.warn('[inbox_ops:proposals:counts] Failed to set cache', err)\n }\n }\n\n return NextResponse.json(responseBody)\n } catch (err) {\n if (err instanceof UnauthorizedError) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n console.error('[inbox_ops:proposals:counts] Error:', err)\n return NextResponse.json({ error: 'Failed to get counts' }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'InboxOps',\n summary: 'Proposal counts',\n methods: {\n GET: {\n summary: 'Get proposal status and category counts',\n description: 'Returns counts by status and by category for tab badges and filter dropdowns',\n responses: [\n { status: 200, description: 'Status and category counts object' },\n ],\n },\n },\n}\n"],
5
- "mappings": "AAAA,SAAS,oBAAoB;AAE7B,SAAS,0BAA0B;AACnC,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB,yBAAyB;AACzD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,0BAA0B,EAAE;AAC1E;AAEA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,MAAM,MAAM,sBAAsB,GAAG;AAC3C,UAAM,QAAQ,aAAa,IAAI,SAAS;AAExC,QAAI,OAAO;AACT,YAAM,WAAW,qBAAqB,IAAI,QAAQ;AAClD,YAAM,SAAS,MAAM,mBAAmB,IAAI,UAAU,MAAM,MAAM,IAAI,QAAQ,CAAC;AAC/E,UAAI,QAAQ;AACV,eAAO,aAAa,KAAK,MAAM;AAAA,MACjC;AAAA,IACF;AAEA,UAAM,QAAQ;AAAA,MACZ,gBAAgB,IAAI;AAAA,MACpB,UAAU,IAAI;AAAA,MACd,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AAIA,UAAM,CAAC,SAAS,SAAS,UAAU,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC/D,IAAI,GAAG,MAAM,eAAe,EAAE,GAAG,OAAO,QAAQ,UAAU,CAAC;AAAA,MAC3D,IAAI,GAAG,MAAM,eAAe,EAAE,GAAG,OAAO,QAAQ,UAAU,CAAC;AAAA,MAC3D,IAAI,GAAG,MAAM,eAAe,EAAE,GAAG,OAAO,QAAQ,WAAW,CAAC;AAAA,MAC5D,IAAI,GAAG,MAAM,eAAe,EAAE,GAAG,OAAO,QAAQ,WAAW,CAAC;AAAA,IAC9D,CAAC;AAGD,UAAM,OAAO,IAAI,GAAG,QAAQ;AAC5B,UAAM,eAAe,MAAM,KAAK,iBAAiB,EAC9C,OAAO,UAAU,EACjB,MAAM,YAAY,EAClB,MAAM;AAAA,MACL,iBAAiB,IAAI;AAAA,MACrB,WAAW,IAAI;AAAA,MACf,WAAW;AAAA,IACb,CAAC,EACA,UAAU,YAAY,EACtB,QAAQ,UAAU;AAErB,UAAM,aAAqC,CAAC;AAC5C,eAAW,OAAO,gBAAgB;AAChC,iBAAW,GAAG,IAAI;AAAA,IACpB;AACA,eAAW,OAAO,cAAc;AAC9B,YAAM,MAAM,IAAI;AAChB,UAAI,OAAO,OAAO,YAAY;AAC5B,mBAAW,GAAG,IAAI,OAAO,IAAI,KAAK;AAAA,MACpC;AAAA,IACF;AAEA,UAAM,eAAe,EAAE,SAAS,SAAS,UAAU,UAAU,WAAW;AAExE,QAAI,OAAO;AACT,YAAM,WAAW,qBAAqB,IAAI,QAAQ;AAClD,YAAM,MAAM,qBAAqB,IAAI,QAAQ;AAC7C,UAAI;AACF,cAAM;AAAA,UAAmB,IAAI;AAAA,UAAU,MACrC,MAAM,IAAI,UAAU,cAAc,EAAE,KAAK,qBAAqB,MAAM,CAAC,GAAG,EAAE,CAAC;AAAA,QAC7E;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,KAAK,oDAAoD,GAAG;AAAA,MACtE;AAAA,IACF;AAEA,WAAO,aAAa,KAAK,YAAY;AAAA,EACvC,SAAS,KAAK;AACZ,QAAI,eAAe,mBAAmB;AACpC,aAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACrE;AACA,YAAQ,MAAM,uCAAuC,GAAG;AACxD,WAAO,aAAa,KAAK,EAAE,OAAO,uBAAuB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC7E;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,oCAAoC;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { sql } from 'kysely'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { runWithCacheTenant } from '@open-mercato/cache'\nimport { InboxProposal } from '../../../data/entities'\nimport { ALL_CATEGORIES } from '../../../data/validators'\nimport { resolveRequestContext, UnauthorizedError } from '../../routeHelpers'\nimport {\n resolveCache,\n createCountsCacheKey,\n createCountsCacheTag,\n COUNTS_CACHE_TTL_MS,\n} from '../../../lib/cache'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['inbox_ops.proposals.view'] },\n}\n\nexport async function GET(req: Request) {\n try {\n const ctx = await resolveRequestContext(req)\n const cache = resolveCache(ctx.container)\n\n if (cache) {\n const cacheKey = createCountsCacheKey(ctx.tenantId)\n const cached = await runWithCacheTenant(ctx.tenantId, () => cache.get(cacheKey))\n if (cached) {\n return NextResponse.json(cached)\n }\n }\n\n const scope = {\n organizationId: ctx.organizationId,\n tenantId: ctx.tenantId,\n deletedAt: null,\n isActive: true,\n }\n\n // em.count() is safe here \u2014 filter fields (status, organizationId, tenantId,\n // deletedAt, isActive, category) are not encrypted, so decryption helpers are not needed.\n const [pending, partial, accepted, rejected] = await Promise.all([\n ctx.em.count(InboxProposal, { ...scope, status: 'pending' }),\n ctx.em.count(InboxProposal, { ...scope, status: 'partial' }),\n ctx.em.count(InboxProposal, { ...scope, status: 'accepted' }),\n ctx.em.count(InboxProposal, { ...scope, status: 'rejected' }),\n ])\n\n // Single GROUP BY query for category counts \u2014 O(1) queries\n const db = ctx.em.getKysely<any>() as any\n const categoryRows = await db\n .selectFrom('inbox_proposals')\n .select(['category', sql<string>`count(*)`.as('count')])\n .where('organization_id', '=', ctx.organizationId)\n .where('tenant_id', '=', ctx.tenantId)\n .where('is_active', '=', true)\n .where('deleted_at', 'is', null)\n .groupBy('category')\n .execute() as Array<{ category: string | null; count: string | number }>\n\n const byCategory: Record<string, number> = {}\n for (const cat of ALL_CATEGORIES) {\n byCategory[cat] = 0\n }\n for (const row of categoryRows) {\n const cat = row.category as string | null\n if (cat && cat in byCategory) {\n byCategory[cat] = Number(row.count)\n }\n }\n\n const responseBody = { pending, partial, accepted, rejected, byCategory }\n\n if (cache) {\n const cacheKey = createCountsCacheKey(ctx.tenantId)\n const tag = createCountsCacheTag(ctx.tenantId)\n try {\n await runWithCacheTenant(ctx.tenantId, () =>\n cache.set(cacheKey, responseBody, { ttl: COUNTS_CACHE_TTL_MS, tags: [tag] }),\n )\n } catch (err) {\n console.warn('[inbox_ops:proposals:counts] Failed to set cache', err)\n }\n }\n\n return NextResponse.json(responseBody)\n } catch (err) {\n if (err instanceof UnauthorizedError) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n console.error('[inbox_ops:proposals:counts] Error:', err)\n return NextResponse.json({ error: 'Failed to get counts' }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'InboxOps',\n summary: 'Proposal counts',\n methods: {\n GET: {\n summary: 'Get proposal status and category counts',\n description: 'Returns counts by status and by category for tab badges and filter dropdowns',\n responses: [\n { status: 200, description: 'Status and category counts object' },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,WAAW;AAEpB,SAAS,0BAA0B;AACnC,SAAS,qBAAqB;AAC9B,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB,yBAAyB;AACzD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,0BAA0B,EAAE;AAC1E;AAEA,eAAsB,IAAI,KAAc;AACtC,MAAI;AACF,UAAM,MAAM,MAAM,sBAAsB,GAAG;AAC3C,UAAM,QAAQ,aAAa,IAAI,SAAS;AAExC,QAAI,OAAO;AACT,YAAM,WAAW,qBAAqB,IAAI,QAAQ;AAClD,YAAM,SAAS,MAAM,mBAAmB,IAAI,UAAU,MAAM,MAAM,IAAI,QAAQ,CAAC;AAC/E,UAAI,QAAQ;AACV,eAAO,aAAa,KAAK,MAAM;AAAA,MACjC;AAAA,IACF;AAEA,UAAM,QAAQ;AAAA,MACZ,gBAAgB,IAAI;AAAA,MACpB,UAAU,IAAI;AAAA,MACd,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AAIA,UAAM,CAAC,SAAS,SAAS,UAAU,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC/D,IAAI,GAAG,MAAM,eAAe,EAAE,GAAG,OAAO,QAAQ,UAAU,CAAC;AAAA,MAC3D,IAAI,GAAG,MAAM,eAAe,EAAE,GAAG,OAAO,QAAQ,UAAU,CAAC;AAAA,MAC3D,IAAI,GAAG,MAAM,eAAe,EAAE,GAAG,OAAO,QAAQ,WAAW,CAAC;AAAA,MAC5D,IAAI,GAAG,MAAM,eAAe,EAAE,GAAG,OAAO,QAAQ,WAAW,CAAC;AAAA,IAC9D,CAAC;AAGD,UAAM,KAAK,IAAI,GAAG,UAAe;AACjC,UAAM,eAAe,MAAM,GACxB,WAAW,iBAAiB,EAC5B,OAAO,CAAC,YAAY,cAAsB,GAAG,OAAO,CAAC,CAAC,EACtD,MAAM,mBAAmB,KAAK,IAAI,cAAc,EAChD,MAAM,aAAa,KAAK,IAAI,QAAQ,EACpC,MAAM,aAAa,KAAK,IAAI,EAC5B,MAAM,cAAc,MAAM,IAAI,EAC9B,QAAQ,UAAU,EAClB,QAAQ;AAEX,UAAM,aAAqC,CAAC;AAC5C,eAAW,OAAO,gBAAgB;AAChC,iBAAW,GAAG,IAAI;AAAA,IACpB;AACA,eAAW,OAAO,cAAc;AAC9B,YAAM,MAAM,IAAI;AAChB,UAAI,OAAO,OAAO,YAAY;AAC5B,mBAAW,GAAG,IAAI,OAAO,IAAI,KAAK;AAAA,MACpC;AAAA,IACF;AAEA,UAAM,eAAe,EAAE,SAAS,SAAS,UAAU,UAAU,WAAW;AAExE,QAAI,OAAO;AACT,YAAM,WAAW,qBAAqB,IAAI,QAAQ;AAClD,YAAM,MAAM,qBAAqB,IAAI,QAAQ;AAC7C,UAAI;AACF,cAAM;AAAA,UAAmB,IAAI;AAAA,UAAU,MACrC,MAAM,IAAI,UAAU,cAAc,EAAE,KAAK,qBAAqB,MAAM,CAAC,GAAG,EAAE,CAAC;AAAA,QAC7E;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,KAAK,oDAAoD,GAAG;AAAA,MACtE;AAAA,IACF;AAEA,WAAO,aAAa,KAAK,YAAY;AAAA,EACvC,SAAS,KAAK;AACZ,QAAI,eAAe,mBAAmB;AACpC,aAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IACrE;AACA,YAAQ,MAAM,uCAAuC,GAAG;AACxD,WAAO,aAAa,KAAK,EAAE,OAAO,uBAAuB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC7E;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,aAAa;AAAA,MACb,WAAW;AAAA,QACT,EAAE,QAAQ,KAAK,aAAa,oCAAoC;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -8,14 +8,8 @@ var __decorateClass = (decorators, target, key, kind) => {
8
8
  if (kind && result) __defProp(target, key, result);
9
9
  return result;
10
10
  };
11
- import {
12
- Entity,
13
- PrimaryKey,
14
- Property,
15
- Index,
16
- Unique,
17
- OptionalProps
18
- } from "@mikro-orm/core";
11
+ import { OptionalProps } from "@mikro-orm/core";
12
+ import { Entity, Index, PrimaryKey, Property, Unique } from "@mikro-orm/decorators/legacy";
19
13
  OptionalProps;
20
14
  let InboxSettings = class {
21
15
  constructor() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/inbox_ops/data/entities.ts"],
4
- "sourcesContent": ["import {\n Entity,\n PrimaryKey,\n Property,\n Index,\n Unique,\n OptionalProps,\n} from '@mikro-orm/core'\n\n// ---------------------------------------------------------------------------\n// Shared Types\n// ---------------------------------------------------------------------------\n\nexport interface ThreadMessage {\n messageId?: string\n from: { name?: string; email: string }\n to: { name?: string; email: string }[]\n cc?: { name?: string; email: string }[]\n subject?: string\n date: string\n body: string\n contentType: 'text' | 'html'\n isForwarded: boolean\n}\n\nexport interface ProposalTranslationEntry {\n summary: string\n actions: Record<string, string>\n translatedAt: string\n}\n\nexport type ProposalTranslations = Record<string, ProposalTranslationEntry>\n\nexport interface ExtractedParticipant {\n name: string\n email: string\n role: 'buyer' | 'seller' | 'logistics' | 'finance' | 'other'\n matchedContactId?: string | null\n matchedContactType?: 'person' | 'company' | null\n matchConfidence?: number\n}\n\nexport type InboxEmailStatus = 'received' | 'processing' | 'processed' | 'needs_review' | 'failed'\nexport type InboxProposalStatus = 'pending' | 'partial' | 'accepted' | 'rejected'\nexport type InboxProposalCategory =\n | 'rfq'\n | 'order'\n | 'order_update'\n | 'complaint'\n | 'shipping_update'\n | 'inquiry'\n | 'payment'\n | 'other'\nexport type InboxActionType =\n | 'create_order'\n | 'create_quote'\n | 'update_order'\n | 'update_shipment'\n | 'create_contact'\n | 'create_product'\n | 'link_contact'\n | 'log_activity'\n | 'draft_reply'\nexport type InboxActionStatus = 'pending' | 'processing' | 'accepted' | 'rejected' | 'executed' | 'failed'\nexport type InboxDiscrepancyType =\n | 'price_mismatch'\n | 'quantity_mismatch'\n | 'unknown_contact'\n | 'currency_mismatch'\n | 'date_conflict'\n | 'product_not_found'\n | 'duplicate_order'\n | 'other'\n\n// ---------------------------------------------------------------------------\n// InboxSettings\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_settings' })\n@Index({ properties: ['organizationId', 'tenantId'] })\n@Unique({ properties: ['inboxAddress'] })\nexport class InboxSettings {\n [OptionalProps]?: 'isActive' | 'workingLanguage' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'inbox_address', type: 'text' })\n inboxAddress!: string\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'working_language', type: 'text', default: 'en' })\n workingLanguage: string = 'en'\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// ---------------------------------------------------------------------------\n// InboxEmail\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_emails' })\n@Index({ properties: ['organizationId', 'tenantId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'status'] })\n@Index({ properties: ['organizationId', 'tenantId', 'receivedAt'] })\n@Unique({\n properties: ['organizationId', 'tenantId', 'messageId'],\n options: { where: 'message_id IS NOT NULL' },\n})\n@Unique({\n properties: ['organizationId', 'tenantId', 'contentHash'],\n options: { where: 'content_hash IS NOT NULL' },\n})\nexport class InboxEmail {\n [OptionalProps]?: 'status' | 'isActive' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'message_id', type: 'text', nullable: true })\n messageId?: string | null\n\n @Property({ name: 'content_hash', type: 'text', nullable: true })\n contentHash?: string | null\n\n @Property({ name: 'forwarded_by_address', type: 'text' })\n forwardedByAddress!: string\n\n @Property({ name: 'forwarded_by_name', type: 'text', nullable: true })\n forwardedByName?: string | null\n\n @Property({ name: 'to_address', type: 'text' })\n toAddress!: string\n\n @Property({ name: 'subject', type: 'text' })\n subject!: string\n\n @Property({ name: 'reply_to', type: 'text', nullable: true })\n replyTo?: string | null\n\n @Property({ name: 'in_reply_to', type: 'text', nullable: true })\n inReplyTo?: string | null\n\n @Property({ name: 'references', type: 'json', nullable: true })\n emailReferences?: string[] | null\n\n @Property({ name: 'raw_text', type: 'text', nullable: true })\n rawText?: string | null\n\n @Property({ name: 'raw_html', type: 'text', nullable: true })\n rawHtml?: string | null\n\n @Property({ name: 'cleaned_text', type: 'text', nullable: true })\n cleanedText?: string | null\n\n @Property({ name: 'thread_messages', type: 'json', nullable: true })\n threadMessages?: ThreadMessage[] | null\n\n @Property({ name: 'detected_language', type: 'text', nullable: true })\n detectedLanguage?: string | null\n\n @Property({ name: 'attachment_ids', type: 'json', nullable: true })\n attachmentIds?: string[] | null\n\n @Property({ name: 'received_at', type: Date })\n receivedAt!: Date\n\n @Property({ name: 'status', type: 'text' })\n status: InboxEmailStatus = 'received'\n\n @Property({ name: 'processing_error', type: 'text', nullable: true })\n processingError?: string | null\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'metadata', type: 'json', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// ---------------------------------------------------------------------------\n// InboxProposal\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_proposals' })\n@Index({ properties: ['organizationId', 'tenantId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'status'] })\n@Index({ properties: ['organizationId', 'tenantId', 'category'] })\n@Index({ properties: ['inboxEmailId'] })\nexport class InboxProposal {\n [OptionalProps]?: 'status' | 'category' | 'possiblyIncomplete' | 'workingLanguage' | 'translations' | 'isActive' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'inbox_email_id', type: 'uuid' })\n inboxEmailId!: string\n\n @Property({ name: 'summary', type: 'text' })\n summary!: string\n\n @Property({ name: 'participants', type: 'json' })\n participants!: ExtractedParticipant[]\n\n @Property({ name: 'confidence', type: 'numeric', precision: 3, scale: 2 })\n confidence!: string\n\n @Property({ name: 'detected_language', type: 'text', nullable: true })\n detectedLanguage?: string | null\n\n @Property({ name: 'category', type: 'text', nullable: true })\n category?: InboxProposalCategory | null\n\n @Property({ name: 'status', type: 'text' })\n status: InboxProposalStatus = 'pending'\n\n @Property({ name: 'possibly_incomplete', type: 'boolean', default: false })\n possiblyIncomplete: boolean = false\n\n @Property({ name: 'reviewed_by_user_id', type: 'uuid', nullable: true })\n reviewedByUserId?: string | null\n\n @Property({ name: 'reviewed_at', type: Date, nullable: true })\n reviewedAt?: Date | null\n\n @Property({ name: 'llm_model', type: 'text', nullable: true })\n llmModel?: string | null\n\n @Property({ name: 'llm_tokens_used', type: 'integer', nullable: true })\n llmTokensUsed?: number | null\n\n @Property({ name: 'working_language', type: 'text', nullable: true })\n workingLanguage?: string | null\n\n @Property({ name: 'translations', type: 'json', nullable: true })\n translations?: ProposalTranslations | null\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'metadata', type: 'json', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// ---------------------------------------------------------------------------\n// InboxProposalAction\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_proposal_actions' })\n@Index({ properties: ['proposalId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'status'] })\nexport class InboxProposalAction {\n [OptionalProps]?: 'status' | 'isActive' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'proposal_id', type: 'uuid' })\n proposalId!: string\n\n @Property({ name: 'sort_order', type: 'integer' })\n sortOrder!: number\n\n @Property({ name: 'action_type', type: 'text' })\n actionType!: InboxActionType\n\n @Property({ name: 'description', type: 'text' })\n description!: string\n\n @Property({ name: 'payload', type: 'json' })\n payload!: Record<string, unknown>\n\n @Property({ name: 'status', type: 'text' })\n status: InboxActionStatus = 'pending'\n\n @Property({ name: 'confidence', type: 'numeric', precision: 3, scale: 2 })\n confidence!: string\n\n @Property({ name: 'required_feature', type: 'text', nullable: true })\n requiredFeature?: string | null\n\n @Property({ name: 'matched_entity_id', type: 'uuid', nullable: true })\n matchedEntityId?: string | null\n\n @Property({ name: 'matched_entity_type', type: 'text', nullable: true })\n matchedEntityType?: string | null\n\n @Property({ name: 'created_entity_id', type: 'uuid', nullable: true })\n createdEntityId?: string | null\n\n @Property({ name: 'created_entity_type', type: 'text', nullable: true })\n createdEntityType?: string | null\n\n @Property({ name: 'execution_error', type: 'text', nullable: true })\n executionError?: string | null\n\n @Property({ name: 'executed_at', type: Date, nullable: true })\n executedAt?: Date | null\n\n @Property({ name: 'executed_by_user_id', type: 'uuid', nullable: true })\n executedByUserId?: string | null\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'metadata', type: 'json', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// ---------------------------------------------------------------------------\n// InboxDiscrepancy\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_discrepancies' })\n@Index({ properties: ['organizationId', 'tenantId'] })\n@Index({ properties: ['proposalId'] })\nexport class InboxDiscrepancy {\n [OptionalProps]?: 'resolved' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'proposal_id', type: 'uuid' })\n proposalId!: string\n\n @Property({ name: 'action_id', type: 'uuid', nullable: true })\n actionId?: string | null\n\n @Property({ name: 'type', type: 'text' })\n type!: InboxDiscrepancyType\n\n @Property({ name: 'severity', type: 'text' })\n severity!: 'warning' | 'error'\n\n @Property({ name: 'description', type: 'text' })\n description!: string\n\n @Property({ name: 'expected_value', type: 'text', nullable: true })\n expectedValue?: string | null\n\n @Property({ name: 'found_value', type: 'text', nullable: true })\n foundValue?: string | null\n\n @Property({ name: 'resolved', type: 'boolean', default: false })\n resolved: boolean = false\n\n @Property({ name: 'metadata', type: 'json', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport { Entity, Index, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\n// ---------------------------------------------------------------------------\n// Shared Types\n// ---------------------------------------------------------------------------\n\nexport interface ThreadMessage {\n messageId?: string\n from: { name?: string; email: string }\n to: { name?: string; email: string }[]\n cc?: { name?: string; email: string }[]\n subject?: string\n date: string\n body: string\n contentType: 'text' | 'html'\n isForwarded: boolean\n}\n\nexport interface ProposalTranslationEntry {\n summary: string\n actions: Record<string, string>\n translatedAt: string\n}\n\nexport type ProposalTranslations = Record<string, ProposalTranslationEntry>\n\nexport interface ExtractedParticipant {\n name: string\n email: string\n role: 'buyer' | 'seller' | 'logistics' | 'finance' | 'other'\n matchedContactId?: string | null\n matchedContactType?: 'person' | 'company' | null\n matchConfidence?: number\n}\n\nexport type InboxEmailStatus = 'received' | 'processing' | 'processed' | 'needs_review' | 'failed'\nexport type InboxProposalStatus = 'pending' | 'partial' | 'accepted' | 'rejected'\nexport type InboxProposalCategory =\n | 'rfq'\n | 'order'\n | 'order_update'\n | 'complaint'\n | 'shipping_update'\n | 'inquiry'\n | 'payment'\n | 'other'\nexport type InboxActionType =\n | 'create_order'\n | 'create_quote'\n | 'update_order'\n | 'update_shipment'\n | 'create_contact'\n | 'create_product'\n | 'link_contact'\n | 'log_activity'\n | 'draft_reply'\nexport type InboxActionStatus = 'pending' | 'processing' | 'accepted' | 'rejected' | 'executed' | 'failed'\nexport type InboxDiscrepancyType =\n | 'price_mismatch'\n | 'quantity_mismatch'\n | 'unknown_contact'\n | 'currency_mismatch'\n | 'date_conflict'\n | 'product_not_found'\n | 'duplicate_order'\n | 'other'\n\n// ---------------------------------------------------------------------------\n// InboxSettings\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_settings' })\n@Index({ properties: ['organizationId', 'tenantId'] })\n@Unique({ properties: ['inboxAddress'] })\nexport class InboxSettings {\n [OptionalProps]?: 'isActive' | 'workingLanguage' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'inbox_address', type: 'text' })\n inboxAddress!: string\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'working_language', type: 'text', default: 'en' })\n workingLanguage: string = 'en'\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// ---------------------------------------------------------------------------\n// InboxEmail\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_emails' })\n@Index({ properties: ['organizationId', 'tenantId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'status'] })\n@Index({ properties: ['organizationId', 'tenantId', 'receivedAt'] })\n@Unique({\n properties: ['organizationId', 'tenantId', 'messageId'],\n options: { where: 'message_id IS NOT NULL' },\n})\n@Unique({\n properties: ['organizationId', 'tenantId', 'contentHash'],\n options: { where: 'content_hash IS NOT NULL' },\n})\nexport class InboxEmail {\n [OptionalProps]?: 'status' | 'isActive' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'message_id', type: 'text', nullable: true })\n messageId?: string | null\n\n @Property({ name: 'content_hash', type: 'text', nullable: true })\n contentHash?: string | null\n\n @Property({ name: 'forwarded_by_address', type: 'text' })\n forwardedByAddress!: string\n\n @Property({ name: 'forwarded_by_name', type: 'text', nullable: true })\n forwardedByName?: string | null\n\n @Property({ name: 'to_address', type: 'text' })\n toAddress!: string\n\n @Property({ name: 'subject', type: 'text' })\n subject!: string\n\n @Property({ name: 'reply_to', type: 'text', nullable: true })\n replyTo?: string | null\n\n @Property({ name: 'in_reply_to', type: 'text', nullable: true })\n inReplyTo?: string | null\n\n @Property({ name: 'references', type: 'json', nullable: true })\n emailReferences?: string[] | null\n\n @Property({ name: 'raw_text', type: 'text', nullable: true })\n rawText?: string | null\n\n @Property({ name: 'raw_html', type: 'text', nullable: true })\n rawHtml?: string | null\n\n @Property({ name: 'cleaned_text', type: 'text', nullable: true })\n cleanedText?: string | null\n\n @Property({ name: 'thread_messages', type: 'json', nullable: true })\n threadMessages?: ThreadMessage[] | null\n\n @Property({ name: 'detected_language', type: 'text', nullable: true })\n detectedLanguage?: string | null\n\n @Property({ name: 'attachment_ids', type: 'json', nullable: true })\n attachmentIds?: string[] | null\n\n @Property({ name: 'received_at', type: Date })\n receivedAt!: Date\n\n @Property({ name: 'status', type: 'text' })\n status: InboxEmailStatus = 'received'\n\n @Property({ name: 'processing_error', type: 'text', nullable: true })\n processingError?: string | null\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'metadata', type: 'json', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// ---------------------------------------------------------------------------\n// InboxProposal\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_proposals' })\n@Index({ properties: ['organizationId', 'tenantId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'status'] })\n@Index({ properties: ['organizationId', 'tenantId', 'category'] })\n@Index({ properties: ['inboxEmailId'] })\nexport class InboxProposal {\n [OptionalProps]?: 'status' | 'category' | 'possiblyIncomplete' | 'workingLanguage' | 'translations' | 'isActive' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'inbox_email_id', type: 'uuid' })\n inboxEmailId!: string\n\n @Property({ name: 'summary', type: 'text' })\n summary!: string\n\n @Property({ name: 'participants', type: 'json' })\n participants!: ExtractedParticipant[]\n\n @Property({ name: 'confidence', type: 'numeric', precision: 3, scale: 2 })\n confidence!: string\n\n @Property({ name: 'detected_language', type: 'text', nullable: true })\n detectedLanguage?: string | null\n\n @Property({ name: 'category', type: 'text', nullable: true })\n category?: InboxProposalCategory | null\n\n @Property({ name: 'status', type: 'text' })\n status: InboxProposalStatus = 'pending'\n\n @Property({ name: 'possibly_incomplete', type: 'boolean', default: false })\n possiblyIncomplete: boolean = false\n\n @Property({ name: 'reviewed_by_user_id', type: 'uuid', nullable: true })\n reviewedByUserId?: string | null\n\n @Property({ name: 'reviewed_at', type: Date, nullable: true })\n reviewedAt?: Date | null\n\n @Property({ name: 'llm_model', type: 'text', nullable: true })\n llmModel?: string | null\n\n @Property({ name: 'llm_tokens_used', type: 'integer', nullable: true })\n llmTokensUsed?: number | null\n\n @Property({ name: 'working_language', type: 'text', nullable: true })\n workingLanguage?: string | null\n\n @Property({ name: 'translations', type: 'json', nullable: true })\n translations?: ProposalTranslations | null\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'metadata', type: 'json', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// ---------------------------------------------------------------------------\n// InboxProposalAction\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_proposal_actions' })\n@Index({ properties: ['proposalId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'status'] })\nexport class InboxProposalAction {\n [OptionalProps]?: 'status' | 'isActive' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'proposal_id', type: 'uuid' })\n proposalId!: string\n\n @Property({ name: 'sort_order', type: 'integer' })\n sortOrder!: number\n\n @Property({ name: 'action_type', type: 'text' })\n actionType!: InboxActionType\n\n @Property({ name: 'description', type: 'text' })\n description!: string\n\n @Property({ name: 'payload', type: 'json' })\n payload!: Record<string, unknown>\n\n @Property({ name: 'status', type: 'text' })\n status: InboxActionStatus = 'pending'\n\n @Property({ name: 'confidence', type: 'numeric', precision: 3, scale: 2 })\n confidence!: string\n\n @Property({ name: 'required_feature', type: 'text', nullable: true })\n requiredFeature?: string | null\n\n @Property({ name: 'matched_entity_id', type: 'uuid', nullable: true })\n matchedEntityId?: string | null\n\n @Property({ name: 'matched_entity_type', type: 'text', nullable: true })\n matchedEntityType?: string | null\n\n @Property({ name: 'created_entity_id', type: 'uuid', nullable: true })\n createdEntityId?: string | null\n\n @Property({ name: 'created_entity_type', type: 'text', nullable: true })\n createdEntityType?: string | null\n\n @Property({ name: 'execution_error', type: 'text', nullable: true })\n executionError?: string | null\n\n @Property({ name: 'executed_at', type: Date, nullable: true })\n executedAt?: Date | null\n\n @Property({ name: 'executed_by_user_id', type: 'uuid', nullable: true })\n executedByUserId?: string | null\n\n @Property({ name: 'is_active', type: 'boolean', default: true })\n isActive: boolean = true\n\n @Property({ name: 'metadata', type: 'json', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n// ---------------------------------------------------------------------------\n// InboxDiscrepancy\n// ---------------------------------------------------------------------------\n\n@Entity({ tableName: 'inbox_discrepancies' })\n@Index({ properties: ['organizationId', 'tenantId'] })\n@Index({ properties: ['proposalId'] })\nexport class InboxDiscrepancy {\n [OptionalProps]?: 'resolved' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'proposal_id', type: 'uuid' })\n proposalId!: string\n\n @Property({ name: 'action_id', type: 'uuid', nullable: true })\n actionId?: string | null\n\n @Property({ name: 'type', type: 'text' })\n type!: InboxDiscrepancyType\n\n @Property({ name: 'severity', type: 'text' })\n severity!: 'warning' | 'error'\n\n @Property({ name: 'description', type: 'text' })\n description!: string\n\n @Property({ name: 'expected_value', type: 'text', nullable: true })\n expectedValue?: string | null\n\n @Property({ name: 'found_value', type: 'text', nullable: true })\n foundValue?: string | null\n\n @Property({ name: 'resolved', type: 'boolean', default: false })\n resolved: boolean = false\n\n @Property({ name: 'metadata', type: 'json', nullable: true })\n metadata?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -5,10 +5,10 @@ function asContainer(resolver) {
5
5
  const SYSTEM_USER_ID = "00000000-0000-0000-0000-000000000000";
6
6
  async function resolveMessageSenderUserId(em, forwardedByEmail, recipientUserIds, scope) {
7
7
  try {
8
- const knex = em.getKnex();
8
+ const db = em.getKysely();
9
9
  const normalizedEmail = forwardedByEmail.trim().toLowerCase();
10
10
  if (normalizedEmail) {
11
- const row = await knex("users").select("id").where("email", normalizedEmail).whereNull("deleted_at").first();
11
+ const row = await db.selectFrom("users").select("id").where("email", "=", normalizedEmail).where("deleted_at", "is", null).executeTakeFirst();
12
12
  if (row?.id) return row.id;
13
13
  }
14
14
  } catch {
@@ -29,9 +29,9 @@ async function createMessageRecordForEmail(email, ctx) {
29
29
  const commandBus = resolveCommandBus(ctx.container);
30
30
  if (!commandBus) return null;
31
31
  const em = ctx.container.resolve("em");
32
- const knex = em.getKnex();
32
+ const db = em.getKysely();
33
33
  const recipientUserIds = await getRecipientUserIdsForFeature(
34
- knex,
34
+ db,
35
35
  ctx.scope.tenantId,
36
36
  "inbox_ops.proposals.view"
37
37
  );
@@ -93,9 +93,9 @@ async function createMessageRecordForReply(reply, inboxEmailId, ctx) {
93
93
  const commandBus = resolveCommandBus(ctx.container);
94
94
  if (!commandBus) return null;
95
95
  const em = ctx.container.resolve("em");
96
- const knex = em.getKnex();
96
+ const db = em.getKysely();
97
97
  const recipientUserIds = await getRecipientUserIdsForFeature(
98
- knex,
98
+ db,
99
99
  ctx.scope.tenantId,
100
100
  "inbox_ops.proposals.view"
101
101
  );
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/inbox_ops/lib/messagesIntegration.ts"],
4
- "sourcesContent": ["import type { AwilixContainer } from 'awilix'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport { getRecipientUserIdsForFeature } from '../../notifications/lib/notificationRecipients'\n\ninterface ResolverLike {\n resolve: <T = unknown>(name: string) => T\n}\n\nfunction asContainer(resolver: ResolverLike): AwilixContainer {\n return resolver as unknown as AwilixContainer\n}\n\ninterface MessagesIntegrationScope {\n tenantId: string\n organizationId: string\n userId: string\n}\n\ninterface MessagesIntegrationContext {\n container: ResolverLike\n scope: MessagesIntegrationScope\n}\n\ninterface InboxEmailData {\n id: string\n subject: string\n cleanedText?: string | null\n rawText?: string | null\n forwardedByAddress: string\n forwardedByName?: string | null\n status: string\n}\n\ninterface DraftReplyData {\n to: string\n toName?: string | null\n subject: string\n body: string\n}\n\nconst SYSTEM_USER_ID = '00000000-0000-0000-0000-000000000000'\n\n/**\n * Resolve a real user ID to use as the message sender.\n * Tries to find the forwarding user by email in the auth users table,\n * then falls back to the first recipient (admin with proposals.view).\n * Last resort: SYSTEM_USER_ID (zero UUID).\n */\nexport async function resolveMessageSenderUserId(\n em: EntityManager,\n forwardedByEmail: string,\n recipientUserIds: string[],\n scope: { tenantId: string; organizationId: string },\n): Promise<string> {\n try {\n // Direct knex: users.email is a plaintext login field, not encrypted at\n // field level, so findOneWithDecryption is unnecessary here.\n const knex = em.getKnex()\n const normalizedEmail = forwardedByEmail.trim().toLowerCase()\n if (normalizedEmail) {\n const row = await knex('users')\n .select('id')\n .where('email', normalizedEmail)\n .whereNull('deleted_at')\n .first()\n if (row?.id) return row.id\n }\n } catch {\n // User lookup failed \u2014 fall through\n }\n if (recipientUserIds.length > 0) return recipientUserIds[0]\n return SYSTEM_USER_ID\n}\n\nfunction resolveCommandBus(container: ResolverLike): CommandBus | null {\n try {\n const bus = container.resolve('commandBus') as CommandBus\n return bus && typeof bus.execute === 'function' ? bus : null\n } catch {\n return null\n }\n}\n\n/**\n * Creates an internal message record for an incoming inbox email.\n *\n * The message is delivered to all users with the `inbox_ops.proposals.view`\n * feature in the tenant \u2014 mirroring the same audience that sees proposals\n * in the inbox_ops module. This follows the shared-queue pattern used by\n * all major ERP/CRM systems (Salesforce queues, Dynamics 365 queues,\n * HubSpot shared inboxes, Odoo team followers).\n */\nexport async function createMessageRecordForEmail(\n email: InboxEmailData,\n ctx: MessagesIntegrationContext,\n): Promise<string | null> {\n try {\n const commandBus = resolveCommandBus(ctx.container)\n if (!commandBus) return null\n\n const em = ctx.container.resolve('em') as EntityManager\n const knex = em.getKnex()\n const recipientUserIds = await getRecipientUserIdsForFeature(\n knex, ctx.scope.tenantId, 'inbox_ops.proposals.view',\n )\n\n const recipients = recipientUserIds.map((userId) => ({ userId, type: 'to' as const }))\n // Use rawText (full thread) instead of cleanedText (stripped quotes) so\n // the Messages module preserves the complete email conversation.\n const bodyText = email.rawText || email.cleanedText || ''\n\n // Resolve a real user as sender \u2014 prefer the forwarding user, fall back\n // to the first recipient (admin with proposals.view feature) so the\n // Messages UI can display an actual user name instead of the zero UUID.\n const senderUserId = await resolveMessageSenderUserId(\n em, email.forwardedByAddress, recipientUserIds, ctx.scope,\n )\n\n const { result } = await commandBus.execute('messages.messages.compose', {\n input: {\n type: 'inbox_ops.email',\n visibility: recipients.length > 0 ? 'internal' as const : 'public' as const,\n sourceEntityType: 'inbox_ops:inbox_email',\n sourceEntityId: email.id,\n externalEmail: email.forwardedByAddress,\n externalName: email.forwardedByName || undefined,\n recipients,\n subject: email.subject,\n body: bodyText.slice(0, 50000),\n bodyFormat: 'text' as const,\n priority: 'normal' as const,\n isDraft: false,\n sendViaEmail: false,\n objects: [\n {\n entityModule: 'inbox_ops',\n entityType: 'inbox_email',\n entityId: email.id,\n actionRequired: false,\n },\n ],\n tenantId: ctx.scope.tenantId,\n organizationId: ctx.scope.organizationId,\n userId: senderUserId,\n },\n ctx: {\n container: asContainer(ctx.container),\n auth: null,\n organizationScope: null,\n selectedOrganizationId: ctx.scope.organizationId,\n organizationIds: [ctx.scope.organizationId],\n },\n })\n\n const messageId = (result as { id: string })?.id ?? null\n return messageId\n } catch (err) {\n console.error(\n '[inbox_ops:messages] Failed to create message record for email:',\n err instanceof Error ? err.message : String(err),\n )\n return null\n }\n}\n\nexport async function createMessageRecordForReply(\n reply: DraftReplyData,\n inboxEmailId: string,\n ctx: MessagesIntegrationContext,\n): Promise<{ messageId: string } | null> {\n try {\n const commandBus = resolveCommandBus(ctx.container)\n if (!commandBus) return null\n\n const em = ctx.container.resolve('em') as EntityManager\n const knex = em.getKnex()\n const recipientUserIds = await getRecipientUserIdsForFeature(\n knex, ctx.scope.tenantId, 'inbox_ops.proposals.view',\n )\n if (recipientUserIds.length === 0) return null\n\n const recipients = recipientUserIds.map((userId) => ({ userId, type: 'to' as const }))\n\n const { result } = await commandBus.execute('messages.messages.compose', {\n input: {\n type: 'inbox_ops.reply',\n visibility: 'internal' as const,\n sourceEntityType: 'inbox_ops:inbox_email',\n sourceEntityId: inboxEmailId,\n externalEmail: reply.to,\n externalName: reply.toName ?? undefined,\n recipients,\n subject: reply.subject,\n body: reply.body,\n bodyFormat: 'text' as const,\n priority: 'normal' as const,\n isDraft: false,\n sendViaEmail: false,\n objects: [\n {\n entityModule: 'inbox_ops',\n entityType: 'inbox_email',\n entityId: inboxEmailId,\n actionRequired: false,\n },\n ],\n tenantId: ctx.scope.tenantId,\n organizationId: ctx.scope.organizationId,\n userId: ctx.scope.userId,\n },\n ctx: {\n container: asContainer(ctx.container),\n auth: null,\n organizationScope: null,\n selectedOrganizationId: ctx.scope.organizationId,\n organizationIds: [ctx.scope.organizationId],\n },\n })\n\n const messageId = (result as { id: string })?.id ?? null\n if (!messageId) return null\n return { messageId }\n } catch (err) {\n console.error(\n '[inbox_ops:messages] Failed to create reply message record:',\n err instanceof Error ? err.message : String(err),\n )\n return null\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { AwilixContainer } from 'awilix'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport { getRecipientUserIdsForFeature } from '../../notifications/lib/notificationRecipients'\n\ninterface ResolverLike {\n resolve: <T = unknown>(name: string) => T\n}\n\nfunction asContainer(resolver: ResolverLike): AwilixContainer {\n return resolver as unknown as AwilixContainer\n}\n\ninterface MessagesIntegrationScope {\n tenantId: string\n organizationId: string\n userId: string\n}\n\ninterface MessagesIntegrationContext {\n container: ResolverLike\n scope: MessagesIntegrationScope\n}\n\ninterface InboxEmailData {\n id: string\n subject: string\n cleanedText?: string | null\n rawText?: string | null\n forwardedByAddress: string\n forwardedByName?: string | null\n status: string\n}\n\ninterface DraftReplyData {\n to: string\n toName?: string | null\n subject: string\n body: string\n}\n\nconst SYSTEM_USER_ID = '00000000-0000-0000-0000-000000000000'\n\n/**\n * Resolve a real user ID to use as the message sender.\n * Tries to find the forwarding user by email in the auth users table,\n * then falls back to the first recipient (admin with proposals.view).\n * Last resort: SYSTEM_USER_ID (zero UUID).\n */\nexport async function resolveMessageSenderUserId(\n em: EntityManager,\n forwardedByEmail: string,\n recipientUserIds: string[],\n scope: { tenantId: string; organizationId: string },\n): Promise<string> {\n try {\n // users.email is a plaintext login field, not encrypted at field level,\n // so findOneWithDecryption is unnecessary here.\n const db = em.getKysely<any>() as any\n const normalizedEmail = forwardedByEmail.trim().toLowerCase()\n if (normalizedEmail) {\n const row = await db\n .selectFrom('users')\n .select('id')\n .where('email', '=', normalizedEmail)\n .where('deleted_at', 'is', null)\n .executeTakeFirst() as { id?: string } | undefined\n if (row?.id) return row.id\n }\n } catch {\n // User lookup failed \u2014 fall through\n }\n if (recipientUserIds.length > 0) return recipientUserIds[0]\n return SYSTEM_USER_ID\n}\n\nfunction resolveCommandBus(container: ResolverLike): CommandBus | null {\n try {\n const bus = container.resolve('commandBus') as CommandBus\n return bus && typeof bus.execute === 'function' ? bus : null\n } catch {\n return null\n }\n}\n\n/**\n * Creates an internal message record for an incoming inbox email.\n *\n * The message is delivered to all users with the `inbox_ops.proposals.view`\n * feature in the tenant \u2014 mirroring the same audience that sees proposals\n * in the inbox_ops module. This follows the shared-queue pattern used by\n * all major ERP/CRM systems (Salesforce queues, Dynamics 365 queues,\n * HubSpot shared inboxes, Odoo team followers).\n */\nexport async function createMessageRecordForEmail(\n email: InboxEmailData,\n ctx: MessagesIntegrationContext,\n): Promise<string | null> {\n try {\n const commandBus = resolveCommandBus(ctx.container)\n if (!commandBus) return null\n\n const em = ctx.container.resolve('em') as EntityManager\n const db = em.getKysely<any>()\n const recipientUserIds = await getRecipientUserIdsForFeature(\n db, ctx.scope.tenantId, 'inbox_ops.proposals.view',\n )\n\n const recipients = recipientUserIds.map((userId) => ({ userId, type: 'to' as const }))\n // Use rawText (full thread) instead of cleanedText (stripped quotes) so\n // the Messages module preserves the complete email conversation.\n const bodyText = email.rawText || email.cleanedText || ''\n\n // Resolve a real user as sender \u2014 prefer the forwarding user, fall back\n // to the first recipient (admin with proposals.view feature) so the\n // Messages UI can display an actual user name instead of the zero UUID.\n const senderUserId = await resolveMessageSenderUserId(\n em, email.forwardedByAddress, recipientUserIds, ctx.scope,\n )\n\n const { result } = await commandBus.execute('messages.messages.compose', {\n input: {\n type: 'inbox_ops.email',\n visibility: recipients.length > 0 ? 'internal' as const : 'public' as const,\n sourceEntityType: 'inbox_ops:inbox_email',\n sourceEntityId: email.id,\n externalEmail: email.forwardedByAddress,\n externalName: email.forwardedByName || undefined,\n recipients,\n subject: email.subject,\n body: bodyText.slice(0, 50000),\n bodyFormat: 'text' as const,\n priority: 'normal' as const,\n isDraft: false,\n sendViaEmail: false,\n objects: [\n {\n entityModule: 'inbox_ops',\n entityType: 'inbox_email',\n entityId: email.id,\n actionRequired: false,\n },\n ],\n tenantId: ctx.scope.tenantId,\n organizationId: ctx.scope.organizationId,\n userId: senderUserId,\n },\n ctx: {\n container: asContainer(ctx.container),\n auth: null,\n organizationScope: null,\n selectedOrganizationId: ctx.scope.organizationId,\n organizationIds: [ctx.scope.organizationId],\n },\n })\n\n const messageId = (result as { id: string })?.id ?? null\n return messageId\n } catch (err) {\n console.error(\n '[inbox_ops:messages] Failed to create message record for email:',\n err instanceof Error ? err.message : String(err),\n )\n return null\n }\n}\n\nexport async function createMessageRecordForReply(\n reply: DraftReplyData,\n inboxEmailId: string,\n ctx: MessagesIntegrationContext,\n): Promise<{ messageId: string } | null> {\n try {\n const commandBus = resolveCommandBus(ctx.container)\n if (!commandBus) return null\n\n const em = ctx.container.resolve('em') as EntityManager\n const db = em.getKysely<any>()\n const recipientUserIds = await getRecipientUserIdsForFeature(\n db, ctx.scope.tenantId, 'inbox_ops.proposals.view',\n )\n if (recipientUserIds.length === 0) return null\n\n const recipients = recipientUserIds.map((userId) => ({ userId, type: 'to' as const }))\n\n const { result } = await commandBus.execute('messages.messages.compose', {\n input: {\n type: 'inbox_ops.reply',\n visibility: 'internal' as const,\n sourceEntityType: 'inbox_ops:inbox_email',\n sourceEntityId: inboxEmailId,\n externalEmail: reply.to,\n externalName: reply.toName ?? undefined,\n recipients,\n subject: reply.subject,\n body: reply.body,\n bodyFormat: 'text' as const,\n priority: 'normal' as const,\n isDraft: false,\n sendViaEmail: false,\n objects: [\n {\n entityModule: 'inbox_ops',\n entityType: 'inbox_email',\n entityId: inboxEmailId,\n actionRequired: false,\n },\n ],\n tenantId: ctx.scope.tenantId,\n organizationId: ctx.scope.organizationId,\n userId: ctx.scope.userId,\n },\n ctx: {\n container: asContainer(ctx.container),\n auth: null,\n organizationScope: null,\n selectedOrganizationId: ctx.scope.organizationId,\n organizationIds: [ctx.scope.organizationId],\n },\n })\n\n const messageId = (result as { id: string })?.id ?? null\n if (!messageId) return null\n return { messageId }\n } catch (err) {\n console.error(\n '[inbox_ops:messages] Failed to create reply message record:',\n err instanceof Error ? err.message : String(err),\n )\n return null\n }\n}\n"],
5
+ "mappings": "AAGA,SAAS,qCAAqC;AAM9C,SAAS,YAAY,UAAyC;AAC5D,SAAO;AACT;AA8BA,MAAM,iBAAiB;AAQvB,eAAsB,2BACpB,IACA,kBACA,kBACA,OACiB;AACjB,MAAI;AAGF,UAAM,KAAK,GAAG,UAAe;AAC7B,UAAM,kBAAkB,iBAAiB,KAAK,EAAE,YAAY;AAC5D,QAAI,iBAAiB;AACnB,YAAM,MAAM,MAAM,GACf,WAAW,OAAO,EAClB,OAAO,IAAI,EACX,MAAM,SAAS,KAAK,eAAe,EACnC,MAAM,cAAc,MAAM,IAAI,EAC9B,iBAAiB;AACpB,UAAI,KAAK,GAAI,QAAO,IAAI;AAAA,IAC1B;AAAA,EACF,QAAQ;AAAA,EAER;AACA,MAAI,iBAAiB,SAAS,EAAG,QAAO,iBAAiB,CAAC;AAC1D,SAAO;AACT;AAEA,SAAS,kBAAkB,WAA4C;AACrE,MAAI;AACF,UAAM,MAAM,UAAU,QAAQ,YAAY;AAC1C,WAAO,OAAO,OAAO,IAAI,YAAY,aAAa,MAAM;AAAA,EAC1D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWA,eAAsB,4BACpB,OACA,KACwB;AACxB,MAAI;AACF,UAAM,aAAa,kBAAkB,IAAI,SAAS;AAClD,QAAI,CAAC,WAAY,QAAO;AAExB,UAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,UAAM,KAAK,GAAG,UAAe;AAC7B,UAAM,mBAAmB,MAAM;AAAA,MAC7B;AAAA,MAAI,IAAI,MAAM;AAAA,MAAU;AAAA,IAC1B;AAEA,UAAM,aAAa,iBAAiB,IAAI,CAAC,YAAY,EAAE,QAAQ,MAAM,KAAc,EAAE;AAGrF,UAAM,WAAW,MAAM,WAAW,MAAM,eAAe;AAKvD,UAAM,eAAe,MAAM;AAAA,MACzB;AAAA,MAAI,MAAM;AAAA,MAAoB;AAAA,MAAkB,IAAI;AAAA,IACtD;AAEA,UAAM,EAAE,OAAO,IAAI,MAAM,WAAW,QAAQ,6BAA6B;AAAA,MACvE,OAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY,WAAW,SAAS,IAAI,aAAsB;AAAA,QAC1D,kBAAkB;AAAA,QAClB,gBAAgB,MAAM;AAAA,QACtB,eAAe,MAAM;AAAA,QACrB,cAAc,MAAM,mBAAmB;AAAA,QACvC;AAAA,QACA,SAAS,MAAM;AAAA,QACf,MAAM,SAAS,MAAM,GAAG,GAAK;AAAA,QAC7B,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,cAAc;AAAA,QACd,SAAS;AAAA,UACP;AAAA,YACE,cAAc;AAAA,YACd,YAAY;AAAA,YACZ,UAAU,MAAM;AAAA,YAChB,gBAAgB;AAAA,UAClB;AAAA,QACF;AAAA,QACA,UAAU,IAAI,MAAM;AAAA,QACpB,gBAAgB,IAAI,MAAM;AAAA,QAC1B,QAAQ;AAAA,MACV;AAAA,MACA,KAAK;AAAA,QACH,WAAW,YAAY,IAAI,SAAS;AAAA,QACpC,MAAM;AAAA,QACN,mBAAmB;AAAA,QACnB,wBAAwB,IAAI,MAAM;AAAA,QAClC,iBAAiB,CAAC,IAAI,MAAM,cAAc;AAAA,MAC5C;AAAA,IACF,CAAC;AAED,UAAM,YAAa,QAA2B,MAAM;AACpD,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,YAAQ;AAAA,MACN;AAAA,MACA,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACjD;AACA,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,4BACpB,OACA,cACA,KACuC;AACvC,MAAI;AACF,UAAM,aAAa,kBAAkB,IAAI,SAAS;AAClD,QAAI,CAAC,WAAY,QAAO;AAExB,UAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,UAAM,KAAK,GAAG,UAAe;AAC7B,UAAM,mBAAmB,MAAM;AAAA,MAC7B;AAAA,MAAI,IAAI,MAAM;AAAA,MAAU;AAAA,IAC1B;AACA,QAAI,iBAAiB,WAAW,EAAG,QAAO;AAE1C,UAAM,aAAa,iBAAiB,IAAI,CAAC,YAAY,EAAE,QAAQ,MAAM,KAAc,EAAE;AAErF,UAAM,EAAE,OAAO,IAAI,MAAM,WAAW,QAAQ,6BAA6B;AAAA,MACvE,OAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,kBAAkB;AAAA,QAClB,gBAAgB;AAAA,QAChB,eAAe,MAAM;AAAA,QACrB,cAAc,MAAM,UAAU;AAAA,QAC9B;AAAA,QACA,SAAS,MAAM;AAAA,QACf,MAAM,MAAM;AAAA,QACZ,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,cAAc;AAAA,QACd,SAAS;AAAA,UACP;AAAA,YACE,cAAc;AAAA,YACd,YAAY;AAAA,YACZ,UAAU;AAAA,YACV,gBAAgB;AAAA,UAClB;AAAA,QACF;AAAA,QACA,UAAU,IAAI,MAAM;AAAA,QACpB,gBAAgB,IAAI,MAAM;AAAA,QAC1B,QAAQ,IAAI,MAAM;AAAA,MACpB;AAAA,MACA,KAAK;AAAA,QACH,WAAW,YAAY,IAAI,SAAS;AAAA,QACpC,MAAM;AAAA,QACN,mBAAmB;AAAA,QACnB,wBAAwB,IAAI,MAAM;AAAA,QAClC,iBAAiB,CAAC,IAAI,MAAM,cAAc;AAAA,MAC5C;AAAA,IACF,CAAC;AAED,UAAM,YAAa,QAA2B,MAAM;AACpD,QAAI,CAAC,UAAW,QAAO;AACvB,WAAO,EAAE,UAAU;AAAA,EACrB,SAAS,KAAK;AACZ,YAAQ;AAAA,MACN;AAAA,MACA,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACjD;AACA,WAAO;AAAA,EACT;AACF;",
6
6
  "names": []
7
7
  }
@@ -8,7 +8,8 @@ var __decorateClass = (decorators, target, key, kind) => {
8
8
  if (kind && result) __defProp(target, key, result);
9
9
  return result;
10
10
  };
11
- import { Entity, PrimaryKey, Property, Index, OptionalProps } from "@mikro-orm/core";
11
+ import { OptionalProps } from "@mikro-orm/core";
12
+ import { Entity, Index, PrimaryKey, Property } from "@mikro-orm/decorators/legacy";
12
13
  OptionalProps;
13
14
  let SyncExternalIdMapping = class {
14
15
  constructor() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/integrations/data/entities.ts"],
4
- "sourcesContent": ["import { Entity, PrimaryKey, Property, Index, OptionalProps } from '@mikro-orm/core'\n\n@Entity({ tableName: 'sync_external_id_mappings' })\n@Index({ properties: ['internalEntityType', 'internalEntityId', 'organizationId'] })\n@Index({ properties: ['integrationId', 'externalId', 'organizationId'] })\nexport class SyncExternalIdMapping {\n [OptionalProps]?: 'syncStatus' | 'lastSyncedAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'integration_id', type: 'text' })\n integrationId!: string\n\n @Property({ name: 'internal_entity_type', type: 'text' })\n internalEntityType!: string\n\n @Property({ name: 'internal_entity_id', type: 'uuid' })\n internalEntityId!: string\n\n @Property({ name: 'external_id', type: 'text' })\n externalId!: string\n\n @Property({ name: 'sync_status', type: 'text', default: 'not_synced' })\n syncStatus: 'synced' | 'pending' | 'error' | 'not_synced' = 'not_synced'\n\n @Property({ name: 'last_synced_at', type: Date, nullable: true })\n lastSyncedAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'integration_credentials' })\n@Index({ properties: ['integrationId', 'organizationId', 'tenantId'] })\nexport class IntegrationCredentials {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'deletedAt'\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'integration_id', type: 'text' })\n integrationId!: string\n\n @Property({ name: 'credentials', type: 'json' })\n credentials!: Record<string, unknown>\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'integration_states' })\n@Index({ properties: ['integrationId', 'organizationId', 'tenantId'] })\nexport class IntegrationState {\n [OptionalProps]?: 'isEnabled' | 'apiVersion' | 'reauthRequired' | 'lastHealthStatus' | 'lastHealthCheckedAt' | 'lastHealthLatencyMs' | 'enabledAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'integration_id', type: 'text' })\n integrationId!: string\n\n @Property({ name: 'is_enabled', type: 'boolean', default: true })\n isEnabled: boolean = true\n\n @Property({ name: 'api_version', type: 'text', nullable: true })\n apiVersion?: string | null\n\n @Property({ name: 'reauth_required', type: 'boolean', default: false })\n reauthRequired: boolean = false\n\n @Property({ name: 'last_health_status', type: 'text', nullable: true })\n lastHealthStatus?: 'healthy' | 'degraded' | 'unhealthy' | null\n\n @Property({ name: 'last_health_checked_at', type: Date, nullable: true })\n lastHealthCheckedAt?: Date | null\n\n @Property({ name: 'last_health_latency_ms', type: 'int', nullable: true })\n lastHealthLatencyMs?: number | null\n\n @Property({ name: 'enabled_at', type: Date, nullable: true })\n enabledAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'integration_logs' })\n@Index({ properties: ['integrationId', 'organizationId', 'tenantId', 'createdAt'] })\n@Index({ properties: ['level', 'organizationId', 'tenantId', 'createdAt'] })\nexport class IntegrationLog {\n [OptionalProps]?: 'runId' | 'scopeEntityType' | 'scopeEntityId' | 'code' | 'payload' | 'createdAt'\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'integration_id', type: 'text' })\n integrationId!: string\n\n @Property({ name: 'run_id', type: 'uuid', nullable: true })\n runId?: string | null\n\n @Property({ name: 'scope_entity_type', type: 'text', nullable: true })\n scopeEntityType?: string | null\n\n @Property({ name: 'scope_entity_id', type: 'uuid', nullable: true })\n scopeEntityId?: string | null\n\n @Property({ name: 'level', type: 'text' })\n level!: 'info' | 'warn' | 'error'\n\n @Property({ name: 'message', type: 'text' })\n message!: string\n\n @Property({ name: 'code', type: 'text', nullable: true })\n code?: string | null\n\n @Property({ name: 'payload', type: 'json', nullable: true })\n payload?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport { Entity, Index, PrimaryKey, Property } from '@mikro-orm/decorators/legacy'\n\n@Entity({ tableName: 'sync_external_id_mappings' })\n@Index({ properties: ['internalEntityType', 'internalEntityId', 'organizationId'] })\n@Index({ properties: ['integrationId', 'externalId', 'organizationId'] })\nexport class SyncExternalIdMapping {\n [OptionalProps]?: 'syncStatus' | 'lastSyncedAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'integration_id', type: 'text' })\n integrationId!: string\n\n @Property({ name: 'internal_entity_type', type: 'text' })\n internalEntityType!: string\n\n @Property({ name: 'internal_entity_id', type: 'uuid' })\n internalEntityId!: string\n\n @Property({ name: 'external_id', type: 'text' })\n externalId!: string\n\n @Property({ name: 'sync_status', type: 'text', default: 'not_synced' })\n syncStatus: 'synced' | 'pending' | 'error' | 'not_synced' = 'not_synced'\n\n @Property({ name: 'last_synced_at', type: Date, nullable: true })\n lastSyncedAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'integration_credentials' })\n@Index({ properties: ['integrationId', 'organizationId', 'tenantId'] })\nexport class IntegrationCredentials {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'deletedAt'\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'integration_id', type: 'text' })\n integrationId!: string\n\n @Property({ name: 'credentials', type: 'json' })\n credentials!: Record<string, unknown>\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'integration_states' })\n@Index({ properties: ['integrationId', 'organizationId', 'tenantId'] })\nexport class IntegrationState {\n [OptionalProps]?: 'isEnabled' | 'apiVersion' | 'reauthRequired' | 'lastHealthStatus' | 'lastHealthCheckedAt' | 'lastHealthLatencyMs' | 'enabledAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'integration_id', type: 'text' })\n integrationId!: string\n\n @Property({ name: 'is_enabled', type: 'boolean', default: true })\n isEnabled: boolean = true\n\n @Property({ name: 'api_version', type: 'text', nullable: true })\n apiVersion?: string | null\n\n @Property({ name: 'reauth_required', type: 'boolean', default: false })\n reauthRequired: boolean = false\n\n @Property({ name: 'last_health_status', type: 'text', nullable: true })\n lastHealthStatus?: 'healthy' | 'degraded' | 'unhealthy' | null\n\n @Property({ name: 'last_health_checked_at', type: Date, nullable: true })\n lastHealthCheckedAt?: Date | null\n\n @Property({ name: 'last_health_latency_ms', type: 'int', nullable: true })\n lastHealthLatencyMs?: number | null\n\n @Property({ name: 'enabled_at', type: Date, nullable: true })\n enabledAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'integration_logs' })\n@Index({ properties: ['integrationId', 'organizationId', 'tenantId', 'createdAt'] })\n@Index({ properties: ['level', 'organizationId', 'tenantId', 'createdAt'] })\nexport class IntegrationLog {\n [OptionalProps]?: 'runId' | 'scopeEntityType' | 'scopeEntityId' | 'code' | 'payload' | 'createdAt'\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'integration_id', type: 'text' })\n integrationId!: string\n\n @Property({ name: 'run_id', type: 'uuid', nullable: true })\n runId?: string | null\n\n @Property({ name: 'scope_entity_type', type: 'text', nullable: true })\n scopeEntityType?: string | null\n\n @Property({ name: 'scope_entity_id', type: 'uuid', nullable: true })\n scopeEntityId?: string | null\n\n @Property({ name: 'level', type: 'text' })\n level!: 'info' | 'warn' | 'error'\n\n @Property({ name: 'message', type: 'text' })\n message!: string\n\n @Property({ name: 'code', type: 'text', nullable: true })\n code?: string | null\n\n @Property({ name: 'payload', type: 'json', nullable: true })\n payload?: Record<string, unknown> | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -138,7 +138,7 @@ function createCredentialsService(em) {
138
138
  organizationId: scope.organizationId,
139
139
  tenantId: scope.tenantId
140
140
  });
141
- await em.persistAndFlush(created);
141
+ await em.persist(created).flush();
142
142
  },
143
143
  async saveField(integrationId, fieldKey, value, scope) {
144
144
  const current = await this.getRaw(integrationId, scope) ?? {};
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/integrations/lib/credentials-service.ts"],
4
- "sourcesContent": ["import crypto from 'node:crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { decryptWithAesGcm, encryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport {\n getBundle,\n getIntegration,\n resolveIntegrationCredentialsSchema,\n type IntegrationScope,\n} from '@open-mercato/shared/modules/integrations/types'\nimport { EncryptionMap } from '../../entities/data/entities'\nimport { IntegrationCredentials } from '../data/entities'\n\nconst ENCRYPTED_CREDENTIALS_BLOB_KEY = '__om_encrypted_credentials_blob_v1'\nconst DERIVED_KEY_CONTEXT = 'integrations.credentials'\n\nfunction resolveFallbackEncryptionSecret(): string {\n const candidates = [\n process.env.TENANT_DATA_ENCRYPTION_FALLBACK_KEY,\n process.env.TENANT_DATA_ENCRYPTION_KEY,\n process.env.AUTH_SECRET,\n process.env.NEXTAUTH_SECRET,\n ]\n\n for (const value of candidates) {\n const normalized = value?.trim()\n if (normalized) return normalized\n }\n\n if (process.env.NODE_ENV !== 'production') return 'om-dev-tenant-encryption'\n\n console.warn(\n '[integrations.credentials] No encryption secret configured; using emergency fallback secret. Configure TENANT_DATA_ENCRYPTION_FALLBACK_KEY immediately.',\n )\n return 'om-emergency-fallback-rotate-me'\n}\n\nfunction deriveDekFromSecret(secret: string, tenantId: string): string {\n return crypto\n .createHash('sha256')\n .update(`${DERIVED_KEY_CONTEXT}:${tenantId}:${secret}`)\n .digest()\n .toString('base64')\n}\n\nexport function createCredentialsService(em: EntityManager) {\n const credentialsEncryptionSpec = [{ field: 'credentials' }]\n\n async function ensureCredentialsEncryptionMap(scope: IntegrationScope): Promise<void> {\n const existing = await findOneWithDecryption(\n em,\n EncryptionMap,\n {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n if (!existing) {\n const created = em.create(EncryptionMap, {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n fieldsJson: credentialsEncryptionSpec,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(created)\n return\n }\n\n existing.fieldsJson = credentialsEncryptionSpec\n existing.isActive = true\n }\n\n async function resolveCredentialsDek(scope: IntegrationScope): Promise<string> {\n const kms = createKmsService()\n const existing = await kms.getTenantDek(scope.tenantId)\n if (existing?.key) return existing.key\n\n const created = await kms.createTenantDek(scope.tenantId)\n if (created?.key) return created.key\n\n return deriveDekFromSecret(resolveFallbackEncryptionSecret(), scope.tenantId)\n }\n\n async function encryptCredentialsBlob(\n credentials: Record<string, unknown>,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const dek = await resolveCredentialsDek(scope)\n const payload = encryptWithAesGcm(JSON.stringify(credentials), dek)\n return { [ENCRYPTED_CREDENTIALS_BLOB_KEY]: payload.value }\n }\n\n async function decryptCredentialsBlob(\n credentials: Record<string, unknown>,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const encrypted = credentials[ENCRYPTED_CREDENTIALS_BLOB_KEY]\n if (typeof encrypted !== 'string' || !encrypted) return credentials\n\n const dek = await resolveCredentialsDek(scope)\n const decryptedRaw = decryptWithAesGcm(encrypted, dek)\n if (!decryptedRaw) return {}\n\n try {\n const parsed = JSON.parse(decryptedRaw) as unknown\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {}\n } catch {\n return {}\n }\n }\n\n return {\n async getRaw(integrationId: string, scope: IntegrationScope): Promise<Record<string, unknown> | null> {\n const row = await findOneWithDecryption(\n em,\n IntegrationCredentials,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!row) return null\n return decryptCredentialsBlob(row.credentials, scope)\n },\n\n async resolve(integrationId: string, scope: IntegrationScope): Promise<Record<string, unknown> | null> {\n const direct = await this.getRaw(integrationId, scope)\n if (direct) return direct\n\n const definition = getIntegration(integrationId)\n if (!definition?.bundleId) return null\n return this.getRaw(definition.bundleId, scope)\n },\n\n async save(integrationId: string, credentials: Record<string, unknown>, scope: IntegrationScope): Promise<void> {\n await ensureCredentialsEncryptionMap(scope)\n const encryptedCredentials = await encryptCredentialsBlob(credentials, scope)\n\n const row = await findOneWithDecryption(\n em,\n IntegrationCredentials,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n if (row) {\n row.credentials = encryptedCredentials\n await em.flush()\n return\n }\n\n const created = em.create(IntegrationCredentials, {\n integrationId,\n credentials: encryptedCredentials,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persistAndFlush(created)\n },\n\n async saveField(\n integrationId: string,\n fieldKey: string,\n value: unknown,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const current = (await this.getRaw(integrationId, scope)) ?? {}\n const updated = { ...current, [fieldKey]: value }\n await this.save(integrationId, updated, scope)\n return updated\n },\n\n getSchema(integrationId: string) {\n const definition = getIntegration(integrationId)\n if (!definition) return undefined\n\n if (definition.bundleId) {\n const bundle = getBundle(definition.bundleId)\n return bundle?.credentials ?? resolveIntegrationCredentialsSchema(integrationId)\n }\n\n return definition.credentials ?? resolveIntegrationCredentialsSchema(integrationId)\n },\n }\n}\n\nexport type CredentialsService = ReturnType<typeof createCredentialsService>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import crypto from 'node:crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { decryptWithAesGcm, encryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport {\n getBundle,\n getIntegration,\n resolveIntegrationCredentialsSchema,\n type IntegrationScope,\n} from '@open-mercato/shared/modules/integrations/types'\nimport { EncryptionMap } from '../../entities/data/entities'\nimport { IntegrationCredentials } from '../data/entities'\n\nconst ENCRYPTED_CREDENTIALS_BLOB_KEY = '__om_encrypted_credentials_blob_v1'\nconst DERIVED_KEY_CONTEXT = 'integrations.credentials'\n\nfunction resolveFallbackEncryptionSecret(): string {\n const candidates = [\n process.env.TENANT_DATA_ENCRYPTION_FALLBACK_KEY,\n process.env.TENANT_DATA_ENCRYPTION_KEY,\n process.env.AUTH_SECRET,\n process.env.NEXTAUTH_SECRET,\n ]\n\n for (const value of candidates) {\n const normalized = value?.trim()\n if (normalized) return normalized\n }\n\n if (process.env.NODE_ENV !== 'production') return 'om-dev-tenant-encryption'\n\n console.warn(\n '[integrations.credentials] No encryption secret configured; using emergency fallback secret. Configure TENANT_DATA_ENCRYPTION_FALLBACK_KEY immediately.',\n )\n return 'om-emergency-fallback-rotate-me'\n}\n\nfunction deriveDekFromSecret(secret: string, tenantId: string): string {\n return crypto\n .createHash('sha256')\n .update(`${DERIVED_KEY_CONTEXT}:${tenantId}:${secret}`)\n .digest()\n .toString('base64')\n}\n\nexport function createCredentialsService(em: EntityManager) {\n const credentialsEncryptionSpec = [{ field: 'credentials' }]\n\n async function ensureCredentialsEncryptionMap(scope: IntegrationScope): Promise<void> {\n const existing = await findOneWithDecryption(\n em,\n EncryptionMap,\n {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n if (!existing) {\n const created = em.create(EncryptionMap, {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n fieldsJson: credentialsEncryptionSpec,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(created)\n return\n }\n\n existing.fieldsJson = credentialsEncryptionSpec\n existing.isActive = true\n }\n\n async function resolveCredentialsDek(scope: IntegrationScope): Promise<string> {\n const kms = createKmsService()\n const existing = await kms.getTenantDek(scope.tenantId)\n if (existing?.key) return existing.key\n\n const created = await kms.createTenantDek(scope.tenantId)\n if (created?.key) return created.key\n\n return deriveDekFromSecret(resolveFallbackEncryptionSecret(), scope.tenantId)\n }\n\n async function encryptCredentialsBlob(\n credentials: Record<string, unknown>,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const dek = await resolveCredentialsDek(scope)\n const payload = encryptWithAesGcm(JSON.stringify(credentials), dek)\n return { [ENCRYPTED_CREDENTIALS_BLOB_KEY]: payload.value }\n }\n\n async function decryptCredentialsBlob(\n credentials: Record<string, unknown>,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const encrypted = credentials[ENCRYPTED_CREDENTIALS_BLOB_KEY]\n if (typeof encrypted !== 'string' || !encrypted) return credentials\n\n const dek = await resolveCredentialsDek(scope)\n const decryptedRaw = decryptWithAesGcm(encrypted, dek)\n if (!decryptedRaw) return {}\n\n try {\n const parsed = JSON.parse(decryptedRaw) as unknown\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {}\n } catch {\n return {}\n }\n }\n\n return {\n async getRaw(integrationId: string, scope: IntegrationScope): Promise<Record<string, unknown> | null> {\n const row = await findOneWithDecryption(\n em,\n IntegrationCredentials,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!row) return null\n return decryptCredentialsBlob(row.credentials, scope)\n },\n\n async resolve(integrationId: string, scope: IntegrationScope): Promise<Record<string, unknown> | null> {\n const direct = await this.getRaw(integrationId, scope)\n if (direct) return direct\n\n const definition = getIntegration(integrationId)\n if (!definition?.bundleId) return null\n return this.getRaw(definition.bundleId, scope)\n },\n\n async save(integrationId: string, credentials: Record<string, unknown>, scope: IntegrationScope): Promise<void> {\n await ensureCredentialsEncryptionMap(scope)\n const encryptedCredentials = await encryptCredentialsBlob(credentials, scope)\n\n const row = await findOneWithDecryption(\n em,\n IntegrationCredentials,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n if (row) {\n row.credentials = encryptedCredentials\n await em.flush()\n return\n }\n\n const created = em.create(IntegrationCredentials, {\n integrationId,\n credentials: encryptedCredentials,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persist(created).flush()\n },\n\n async saveField(\n integrationId: string,\n fieldKey: string,\n value: unknown,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const current = (await this.getRaw(integrationId, scope)) ?? {}\n const updated = { ...current, [fieldKey]: value }\n await this.save(integrationId, updated, scope)\n return updated\n },\n\n getSchema(integrationId: string) {\n const definition = getIntegration(integrationId)\n if (!definition) return undefined\n\n if (definition.bundleId) {\n const bundle = getBundle(definition.bundleId)\n return bundle?.credentials ?? resolveIntegrationCredentialsSchema(integrationId)\n }\n\n return definition.credentials ?? resolveIntegrationCredentialsSchema(integrationId)\n },\n }\n}\n\nexport type CredentialsService = ReturnType<typeof createCredentialsService>\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -28,7 +28,7 @@ function createIntegrationLogService(em) {
28
28
  organizationId: scope.organizationId,
29
29
  tenantId: scope.tenantId
30
30
  });
31
- await em.persistAndFlush(row);
31
+ await em.persist(row).flush();
32
32
  return row;
33
33
  },
34
34
  scoped(integrationId, scope) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/integrations/lib/log-service.ts"],
4
- "sourcesContent": ["import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { IntegrationScope } from '@open-mercato/shared/modules/integrations/types'\nimport type { ListIntegrationLogsQuery } from '../data/validators'\nimport { IntegrationLog } from '../data/entities'\n\nexport type IntegrationLogAnalytics = {\n lastActivityAt: string | null\n totalCount: number\n errorCount: number\n errorRate: number\n dailyCounts: number[]\n}\n\nfunction startOfUtcDay(d: Date): Date {\n return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()))\n}\n\nfunction buildUtcDayKeys(windowDays: number): string[] {\n const end = startOfUtcDay(new Date())\n const keys: string[] = []\n for (let offset = windowDays - 1; offset >= 0; offset -= 1) {\n const t = new Date(end)\n t.setUTCDate(t.getUTCDate() - offset)\n keys.push(t.toISOString().slice(0, 10))\n }\n return keys\n}\n\ntype LogInput = {\n integrationId: string\n runId?: string | null\n scopeEntityType?: string | null\n scopeEntityId?: string | null\n level: 'info' | 'warn' | 'error'\n message: string\n code?: string | null\n payload?: Record<string, unknown> | null\n}\n\nexport function createIntegrationLogService(em: EntityManager) {\n return {\n async write(input: LogInput, scope: IntegrationScope): Promise<IntegrationLog> {\n const row = em.create(IntegrationLog, {\n integrationId: input.integrationId,\n runId: input.runId,\n scopeEntityType: input.scopeEntityType,\n scopeEntityId: input.scopeEntityId,\n level: input.level,\n message: input.message,\n code: input.code,\n payload: input.payload,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persistAndFlush(row)\n return row\n },\n\n scoped(integrationId: string, scope: IntegrationScope) {\n return {\n info: (message: string, payload?: Record<string, unknown>) => this.write({ integrationId, level: 'info', message, payload }, scope),\n warn: (message: string, payload?: Record<string, unknown>) => this.write({ integrationId, level: 'warn', message, payload }, scope),\n error: (message: string, payload?: Record<string, unknown>) => this.write({ integrationId, level: 'error', message, payload }, scope),\n }\n },\n\n async query(query: ListIntegrationLogsQuery, scope: IntegrationScope): Promise<{ items: IntegrationLog[]; total: number }> {\n const where: FilterQuery<IntegrationLog> = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }\n\n if (query.integrationId) where.integrationId = query.integrationId\n if (query.level) where.level = query.level\n if (query.runId) where.runId = query.runId\n if (query.entityType) where.scopeEntityType = query.entityType\n if (query.entityId) where.scopeEntityId = query.entityId\n\n const items = await findWithDecryption(\n em,\n IntegrationLog,\n where,\n {\n orderBy: { createdAt: 'DESC' },\n limit: query.pageSize,\n offset: (query.page - 1) * query.pageSize,\n },\n scope,\n )\n const total = await em.count(IntegrationLog, where)\n return { items, total }\n },\n\n async pruneOlderThan(days: number, scope: IntegrationScope): Promise<number> {\n const threshold = new Date(Date.now() - days * 24 * 60 * 60 * 1000)\n const deletedCount = await em.nativeDelete(IntegrationLog, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n createdAt: { $lt: threshold },\n })\n return deletedCount\n },\n\n async aggregateAnalytics(\n integrationIds: string[],\n scope: IntegrationScope,\n windowDays = 30,\n ): Promise<Map<string, IntegrationLogAnalytics>> {\n const dayKeys = buildUtcDayKeys(windowDays)\n const windowStartUtc = `${dayKeys[0]}T00:00:00.000Z`\n\n const empty = (): IntegrationLogAnalytics => ({\n lastActivityAt: null,\n totalCount: 0,\n errorCount: 0,\n errorRate: 0,\n dailyCounts: dayKeys.map(() => 0),\n })\n\n const result = new Map<string, IntegrationLogAnalytics>()\n for (const id of integrationIds) {\n result.set(id, empty())\n }\n if (integrationIds.length === 0) {\n return result\n }\n\n const conn = em.getConnection()\n const inList = integrationIds.map(() => '?').join(', ')\n\n type AggRow = {\n integration_id: string\n last_activity: Date | string | null\n total_count: string | number\n error_count: string | number | null\n }\n\n const aggRows = await conn.execute<AggRow[]>(\n `select integration_id,\n max(created_at) as last_activity,\n count(*)::int as total_count,\n coalesce(sum(case when level = 'error' then 1 else 0 end), 0)::int as error_count\n from integration_logs\n where organization_id = ? and tenant_id = ?\n and integration_id in (${inList})\n and created_at >= ?\n group by integration_id`,\n [scope.organizationId, scope.tenantId, ...integrationIds, windowStartUtc],\n )\n\n for (const row of aggRows) {\n const entry = result.get(row.integration_id)\n if (!entry) continue\n const total = Number(row.total_count)\n const errors = Number(row.error_count ?? 0)\n entry.totalCount = total\n entry.errorCount = errors\n entry.errorRate = total > 0 ? errors / total : 0\n if (row.last_activity) {\n const d = row.last_activity instanceof Date ? row.last_activity : new Date(row.last_activity)\n entry.lastActivityAt = d.toISOString()\n }\n }\n\n type DailyRow = { integration_id: string; day: string | Date; cnt: string | number }\n\n const dailyRows = await conn.execute<DailyRow[]>(\n `select integration_id,\n (created_at at time zone 'UTC')::date::text as day,\n count(*)::int as cnt\n from integration_logs\n where organization_id = ? and tenant_id = ?\n and integration_id in (${inList})\n and created_at >= ?\n group by integration_id, (created_at at time zone 'UTC')::date`,\n [scope.organizationId, scope.tenantId, ...integrationIds, windowStartUtc],\n )\n\n const dayIndex = new Map(dayKeys.map((key, index) => [key, index]))\n for (const row of dailyRows) {\n const entry = result.get(row.integration_id)\n if (!entry) continue\n const dayKey = typeof row.day === 'string' ? row.day : row.day.toISOString().slice(0, 10)\n const idx = dayIndex.get(dayKey)\n if (idx === undefined) continue\n entry.dailyCounts[idx] = Number(row.cnt)\n }\n\n return result\n },\n }\n}\n\nexport type IntegrationLogService = ReturnType<typeof createIntegrationLogService>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { IntegrationScope } from '@open-mercato/shared/modules/integrations/types'\nimport type { ListIntegrationLogsQuery } from '../data/validators'\nimport { IntegrationLog } from '../data/entities'\n\nexport type IntegrationLogAnalytics = {\n lastActivityAt: string | null\n totalCount: number\n errorCount: number\n errorRate: number\n dailyCounts: number[]\n}\n\nfunction startOfUtcDay(d: Date): Date {\n return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()))\n}\n\nfunction buildUtcDayKeys(windowDays: number): string[] {\n const end = startOfUtcDay(new Date())\n const keys: string[] = []\n for (let offset = windowDays - 1; offset >= 0; offset -= 1) {\n const t = new Date(end)\n t.setUTCDate(t.getUTCDate() - offset)\n keys.push(t.toISOString().slice(0, 10))\n }\n return keys\n}\n\ntype LogInput = {\n integrationId: string\n runId?: string | null\n scopeEntityType?: string | null\n scopeEntityId?: string | null\n level: 'info' | 'warn' | 'error'\n message: string\n code?: string | null\n payload?: Record<string, unknown> | null\n}\n\nexport function createIntegrationLogService(em: EntityManager) {\n return {\n async write(input: LogInput, scope: IntegrationScope): Promise<IntegrationLog> {\n const row = em.create(IntegrationLog, {\n integrationId: input.integrationId,\n runId: input.runId,\n scopeEntityType: input.scopeEntityType,\n scopeEntityId: input.scopeEntityId,\n level: input.level,\n message: input.message,\n code: input.code,\n payload: input.payload,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persist(row).flush()\n return row\n },\n\n scoped(integrationId: string, scope: IntegrationScope) {\n return {\n info: (message: string, payload?: Record<string, unknown>) => this.write({ integrationId, level: 'info', message, payload }, scope),\n warn: (message: string, payload?: Record<string, unknown>) => this.write({ integrationId, level: 'warn', message, payload }, scope),\n error: (message: string, payload?: Record<string, unknown>) => this.write({ integrationId, level: 'error', message, payload }, scope),\n }\n },\n\n async query(query: ListIntegrationLogsQuery, scope: IntegrationScope): Promise<{ items: IntegrationLog[]; total: number }> {\n const where: FilterQuery<IntegrationLog> = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }\n\n if (query.integrationId) where.integrationId = query.integrationId\n if (query.level) where.level = query.level\n if (query.runId) where.runId = query.runId\n if (query.entityType) where.scopeEntityType = query.entityType\n if (query.entityId) where.scopeEntityId = query.entityId\n\n const items = await findWithDecryption(\n em,\n IntegrationLog,\n where,\n {\n orderBy: { createdAt: 'DESC' },\n limit: query.pageSize,\n offset: (query.page - 1) * query.pageSize,\n },\n scope,\n )\n const total = await em.count(IntegrationLog, where)\n return { items, total }\n },\n\n async pruneOlderThan(days: number, scope: IntegrationScope): Promise<number> {\n const threshold = new Date(Date.now() - days * 24 * 60 * 60 * 1000)\n const deletedCount = await em.nativeDelete(IntegrationLog, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n createdAt: { $lt: threshold },\n })\n return deletedCount\n },\n\n async aggregateAnalytics(\n integrationIds: string[],\n scope: IntegrationScope,\n windowDays = 30,\n ): Promise<Map<string, IntegrationLogAnalytics>> {\n const dayKeys = buildUtcDayKeys(windowDays)\n const windowStartUtc = `${dayKeys[0]}T00:00:00.000Z`\n\n const empty = (): IntegrationLogAnalytics => ({\n lastActivityAt: null,\n totalCount: 0,\n errorCount: 0,\n errorRate: 0,\n dailyCounts: dayKeys.map(() => 0),\n })\n\n const result = new Map<string, IntegrationLogAnalytics>()\n for (const id of integrationIds) {\n result.set(id, empty())\n }\n if (integrationIds.length === 0) {\n return result\n }\n\n const conn = em.getConnection()\n const inList = integrationIds.map(() => '?').join(', ')\n\n type AggRow = {\n integration_id: string\n last_activity: Date | string | null\n total_count: string | number\n error_count: string | number | null\n }\n\n const aggRows = await conn.execute<AggRow[]>(\n `select integration_id,\n max(created_at) as last_activity,\n count(*)::int as total_count,\n coalesce(sum(case when level = 'error' then 1 else 0 end), 0)::int as error_count\n from integration_logs\n where organization_id = ? and tenant_id = ?\n and integration_id in (${inList})\n and created_at >= ?\n group by integration_id`,\n [scope.organizationId, scope.tenantId, ...integrationIds, windowStartUtc],\n )\n\n for (const row of aggRows) {\n const entry = result.get(row.integration_id)\n if (!entry) continue\n const total = Number(row.total_count)\n const errors = Number(row.error_count ?? 0)\n entry.totalCount = total\n entry.errorCount = errors\n entry.errorRate = total > 0 ? errors / total : 0\n if (row.last_activity) {\n const d = row.last_activity instanceof Date ? row.last_activity : new Date(row.last_activity)\n entry.lastActivityAt = d.toISOString()\n }\n }\n\n type DailyRow = { integration_id: string; day: string | Date; cnt: string | number }\n\n const dailyRows = await conn.execute<DailyRow[]>(\n `select integration_id,\n (created_at at time zone 'UTC')::date::text as day,\n count(*)::int as cnt\n from integration_logs\n where organization_id = ? and tenant_id = ?\n and integration_id in (${inList})\n and created_at >= ?\n group by integration_id, (created_at at time zone 'UTC')::date`,\n [scope.organizationId, scope.tenantId, ...integrationIds, windowStartUtc],\n )\n\n const dayIndex = new Map(dayKeys.map((key, index) => [key, index]))\n for (const row of dailyRows) {\n const entry = result.get(row.integration_id)\n if (!entry) continue\n const dayKey = typeof row.day === 'string' ? row.day : row.day.toISOString().slice(0, 10)\n const idx = dayIndex.get(dayKey)\n if (idx === undefined) continue\n entry.dailyCounts[idx] = Number(row.cnt)\n }\n\n return result\n },\n }\n}\n\nexport type IntegrationLogService = ReturnType<typeof createIntegrationLogService>\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -74,7 +74,7 @@ function createIntegrationStateService(em) {
74
74
  organizationId: scope.organizationId,
75
75
  tenantId: scope.tenantId
76
76
  });
77
- await em.persistAndFlush(created);
77
+ await em.persist(created).flush();
78
78
  return created;
79
79
  },
80
80
  async resolveApiVersion(integrationId, scope) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/integrations/lib/state-service.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { getIntegration, type IntegrationScope } from '@open-mercato/shared/modules/integrations/types'\nimport { IntegrationState } from '../data/entities'\n\nexport type ResolvedIntegrationState = {\n isEnabled: boolean\n apiVersion: string | null\n reauthRequired: boolean\n lastHealthStatus: string | null\n lastHealthCheckedAt: Date | null\n lastHealthLatencyMs: number | null\n enabledAt: Date | null\n}\n\nexport function createIntegrationStateService(em: EntityManager) {\n function resolveDefinitionDefaults(integrationId: string): ResolvedIntegrationState {\n const definition = getIntegration(integrationId)\n\n return {\n isEnabled: definition?.defaultState?.isEnabled ?? false,\n apiVersion: null,\n reauthRequired: false,\n lastHealthStatus: null,\n lastHealthCheckedAt: null,\n lastHealthLatencyMs: null,\n enabledAt: null,\n }\n }\n\n return {\n async get(integrationId: string, scope: IntegrationScope): Promise<IntegrationState | null> {\n return findOneWithDecryption(\n em,\n IntegrationState,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n },\n\n async resolveState(integrationId: string, scope: IntegrationScope): Promise<ResolvedIntegrationState> {\n const state = await this.get(integrationId, scope)\n const defaults = resolveDefinitionDefaults(integrationId)\n\n return {\n isEnabled: state?.isEnabled ?? defaults.isEnabled,\n apiVersion: state?.apiVersion ?? null,\n reauthRequired: state?.reauthRequired ?? false,\n lastHealthStatus: state?.lastHealthStatus ?? null,\n lastHealthCheckedAt: state?.lastHealthCheckedAt ?? null,\n lastHealthLatencyMs: state?.lastHealthLatencyMs ?? null,\n enabledAt: state?.enabledAt ?? null,\n }\n },\n\n async isEnabled(integrationId: string, scope: IntegrationScope): Promise<boolean> {\n const state = await this.resolveState(integrationId, scope)\n return state.isEnabled\n },\n\n async upsert(\n integrationId: string,\n input: Partial<\n Pick<\n IntegrationState,\n | 'isEnabled'\n | 'apiVersion'\n | 'reauthRequired'\n | 'lastHealthStatus'\n | 'lastHealthCheckedAt'\n | 'lastHealthLatencyMs'\n | 'enabledAt'\n >\n >,\n scope: IntegrationScope,\n ): Promise<IntegrationState> {\n const current = await this.get(integrationId, scope)\n const resolvedBefore = await this.resolveState(integrationId, scope)\n const enableTransition =\n input.isEnabled === true && resolvedBefore.isEnabled === false\n\n if (current) {\n if (input.isEnabled !== undefined) current.isEnabled = input.isEnabled\n if (input.apiVersion !== undefined) current.apiVersion = input.apiVersion\n if (input.reauthRequired !== undefined) current.reauthRequired = input.reauthRequired\n if (input.lastHealthStatus !== undefined) current.lastHealthStatus = input.lastHealthStatus\n if (input.lastHealthCheckedAt !== undefined) current.lastHealthCheckedAt = input.lastHealthCheckedAt\n if (input.lastHealthLatencyMs !== undefined) current.lastHealthLatencyMs = input.lastHealthLatencyMs\n if (input.enabledAt !== undefined) current.enabledAt = input.enabledAt\n else if (enableTransition) current.enabledAt = new Date()\n await em.flush()\n return current\n }\n\n const created = em.create(IntegrationState, {\n integrationId,\n isEnabled: input.isEnabled ?? false,\n apiVersion: input.apiVersion,\n reauthRequired: input.reauthRequired ?? false,\n lastHealthStatus: input.lastHealthStatus,\n lastHealthCheckedAt: input.lastHealthCheckedAt,\n lastHealthLatencyMs: input.lastHealthLatencyMs,\n enabledAt: input.enabledAt !== undefined ? input.enabledAt : enableTransition ? new Date() : undefined,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persistAndFlush(created)\n return created\n },\n\n async resolveApiVersion(integrationId: string, scope: IntegrationScope): Promise<string | undefined> {\n const state = await this.get(integrationId, scope)\n return state?.apiVersion ?? undefined\n },\n\n async setReauthRequired(integrationId: string, required: boolean, scope: IntegrationScope): Promise<IntegrationState> {\n return this.upsert(integrationId, { reauthRequired: required }, scope)\n },\n }\n}\n\nexport type IntegrationStateService = ReturnType<typeof createIntegrationStateService>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { getIntegration, type IntegrationScope } from '@open-mercato/shared/modules/integrations/types'\nimport { IntegrationState } from '../data/entities'\n\nexport type ResolvedIntegrationState = {\n isEnabled: boolean\n apiVersion: string | null\n reauthRequired: boolean\n lastHealthStatus: string | null\n lastHealthCheckedAt: Date | null\n lastHealthLatencyMs: number | null\n enabledAt: Date | null\n}\n\nexport function createIntegrationStateService(em: EntityManager) {\n function resolveDefinitionDefaults(integrationId: string): ResolvedIntegrationState {\n const definition = getIntegration(integrationId)\n\n return {\n isEnabled: definition?.defaultState?.isEnabled ?? false,\n apiVersion: null,\n reauthRequired: false,\n lastHealthStatus: null,\n lastHealthCheckedAt: null,\n lastHealthLatencyMs: null,\n enabledAt: null,\n }\n }\n\n return {\n async get(integrationId: string, scope: IntegrationScope): Promise<IntegrationState | null> {\n return findOneWithDecryption(\n em,\n IntegrationState,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n },\n\n async resolveState(integrationId: string, scope: IntegrationScope): Promise<ResolvedIntegrationState> {\n const state = await this.get(integrationId, scope)\n const defaults = resolveDefinitionDefaults(integrationId)\n\n return {\n isEnabled: state?.isEnabled ?? defaults.isEnabled,\n apiVersion: state?.apiVersion ?? null,\n reauthRequired: state?.reauthRequired ?? false,\n lastHealthStatus: state?.lastHealthStatus ?? null,\n lastHealthCheckedAt: state?.lastHealthCheckedAt ?? null,\n lastHealthLatencyMs: state?.lastHealthLatencyMs ?? null,\n enabledAt: state?.enabledAt ?? null,\n }\n },\n\n async isEnabled(integrationId: string, scope: IntegrationScope): Promise<boolean> {\n const state = await this.resolveState(integrationId, scope)\n return state.isEnabled\n },\n\n async upsert(\n integrationId: string,\n input: Partial<\n Pick<\n IntegrationState,\n | 'isEnabled'\n | 'apiVersion'\n | 'reauthRequired'\n | 'lastHealthStatus'\n | 'lastHealthCheckedAt'\n | 'lastHealthLatencyMs'\n | 'enabledAt'\n >\n >,\n scope: IntegrationScope,\n ): Promise<IntegrationState> {\n const current = await this.get(integrationId, scope)\n const resolvedBefore = await this.resolveState(integrationId, scope)\n const enableTransition =\n input.isEnabled === true && resolvedBefore.isEnabled === false\n\n if (current) {\n if (input.isEnabled !== undefined) current.isEnabled = input.isEnabled\n if (input.apiVersion !== undefined) current.apiVersion = input.apiVersion\n if (input.reauthRequired !== undefined) current.reauthRequired = input.reauthRequired\n if (input.lastHealthStatus !== undefined) current.lastHealthStatus = input.lastHealthStatus\n if (input.lastHealthCheckedAt !== undefined) current.lastHealthCheckedAt = input.lastHealthCheckedAt\n if (input.lastHealthLatencyMs !== undefined) current.lastHealthLatencyMs = input.lastHealthLatencyMs\n if (input.enabledAt !== undefined) current.enabledAt = input.enabledAt\n else if (enableTransition) current.enabledAt = new Date()\n await em.flush()\n return current\n }\n\n const created = em.create(IntegrationState, {\n integrationId,\n isEnabled: input.isEnabled ?? false,\n apiVersion: input.apiVersion,\n reauthRequired: input.reauthRequired ?? false,\n lastHealthStatus: input.lastHealthStatus,\n lastHealthCheckedAt: input.lastHealthCheckedAt,\n lastHealthLatencyMs: input.lastHealthLatencyMs,\n enabledAt: input.enabledAt !== undefined ? input.enabledAt : enableTransition ? new Date() : undefined,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persist(created).flush()\n return created\n },\n\n async resolveApiVersion(integrationId: string, scope: IntegrationScope): Promise<string | undefined> {\n const state = await this.get(integrationId, scope)\n return state?.apiVersion ?? undefined\n },\n\n async setReauthRequired(integrationId: string, required: boolean, scope: IntegrationScope): Promise<IntegrationState> {\n return this.upsert(integrationId, { reauthRequired: required }, scope)\n },\n }\n}\n\nexport type IntegrationStateService = ReturnType<typeof createIntegrationStateService>\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }