@open-mercato/core 0.5.1-develop.2691.d8a0934b37 → 0.5.1-develop.2694.732417c5ec

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
@@ -6,11 +6,12 @@
6
6
  * always reflect the latest product image, even when the underlying attachment
7
7
  * changes. The snapshot serves as fallback for deleted products.
8
8
  *
9
- * Uses raw Knex queries because cross-module ORM entity class references
9
+ * Uses raw Kysely queries because cross-module ORM entity class references
10
10
  * do not resolve correctly at runtime (the imported class does not match the
11
11
  * entity registered in MikroORM's metadata by the app bootstrap).
12
12
  */
13
13
 
14
+ import type { Kysely } from 'kysely'
14
15
  import type { ResponseEnricher, EnricherContext } from '@open-mercato/shared/lib/crud/response-enricher'
15
16
  import { buildAttachmentImageUrl } from '../../attachments/lib/imageUrls'
16
17
 
@@ -19,12 +20,13 @@ type LineRecord = Record<string, unknown> & { id: string }
19
20
  type SnapshotNode = { thumbnailUrl?: string | null; [key: string]: unknown }
20
21
  type CatalogSnapshot = { product?: SnapshotNode; variant?: SnapshotNode; [key: string]: unknown }
21
22
 
22
- function getKnex(em: unknown): unknown {
23
- return (em as any).getConnection?.()?.getKnex?.()
23
+ function getDb(em: unknown): Kysely<any> | null {
24
+ const getter = (em as any)?.getKysely
25
+ return typeof getter === 'function' ? getter.call(em) : null
24
26
  }
25
27
 
26
28
  async function fetchMediaIds(
27
- knex: unknown,
29
+ db: Kysely<any>,
28
30
  table: string,
29
31
  ids: Set<string>,
30
32
  organizationId: string,
@@ -32,11 +34,13 @@ async function fetchMediaIds(
32
34
  const map = new Map<string, string | null>()
33
35
  if (ids.size === 0) return map
34
36
 
35
- const rows: Array<{ id: string; default_media_id: string | null }> = await (knex as any)(table)
36
- .select('id', 'default_media_id')
37
- .whereIn('id', [...ids])
38
- .where('organization_id', organizationId)
39
- .whereNull('deleted_at')
37
+ const rows = await (db as any)
38
+ .selectFrom(table)
39
+ .select(['id', 'default_media_id'])
40
+ .where('id', 'in', [...ids])
41
+ .where('organization_id', '=', organizationId)
42
+ .where('deleted_at', 'is', null)
43
+ .execute() as Array<{ id: string; default_media_id: string | null }>
40
44
 
41
45
  for (const row of rows) {
42
46
  map.set(row.id, row.default_media_id ? buildAttachmentImageUrl(row.default_media_id) : null)
@@ -93,8 +97,8 @@ function createCatalogImageEnricher(targetEntity: string): ResponseEnricher<Line
93
97
  async enrichMany(records, context: EnricherContext) {
94
98
  if (records.length === 0) return records
95
99
 
96
- const knex = getKnex(context.em)
97
- if (!knex) return records
100
+ const db = getDb(context.em)
101
+ if (!db) return records
98
102
 
99
103
  const productIds = new Set<string>()
100
104
  const variantIds = new Set<string>()
@@ -105,8 +109,8 @@ function createCatalogImageEnricher(targetEntity: string): ResponseEnricher<Line
105
109
  if (productIds.size === 0 && variantIds.size === 0) return records
106
110
 
107
111
  const [productMedia, variantMedia] = await Promise.all([
108
- fetchMediaIds(knex, 'catalog_products', productIds, context.organizationId),
109
- fetchMediaIds(knex, 'catalog_product_variants', variantIds, context.organizationId),
112
+ fetchMediaIds(db, 'catalog_products', productIds, context.organizationId),
113
+ fetchMediaIds(db, 'catalog_product_variants', variantIds, context.organizationId),
110
114
  ])
111
115
 
112
116
  return enrichRecords(records, productMedia, variantMedia)
@@ -1,14 +1,5 @@
1
- import {
2
- Collection,
3
- Entity,
4
- Index,
5
- ManyToOne,
6
- OneToMany,
7
- OptionalProps,
8
- PrimaryKey,
9
- Property,
10
- Unique,
11
- } from '@mikro-orm/core'
1
+ import { Collection, OptionalProps } from '@mikro-orm/core'
2
+ import { Entity, Index, ManyToOne, OneToMany, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'
12
3
  import { DEFAULT_ORDER_NUMBER_FORMAT, DEFAULT_QUOTE_NUMBER_FORMAT, type SalesDocumentNumberKind } from '../lib/documentNumberTokens'
13
4
  import type { ShipmentItemSnapshot } from '../lib/shipments/types'
14
5
  import type { SalesLineUomSnapshot } from '../lib/types'
@@ -1,4 +1,5 @@
1
- import { Entity, Index, OptionalProps, PrimaryKey, Property, Unique } from '@mikro-orm/core'
1
+ import { OptionalProps } from '@mikro-orm/core'
2
+ import { Entity, Index, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'
2
3
 
3
4
  @Entity({ tableName: 'carrier_shipments' })
4
5
  @Index({ properties: ['orderId', 'organizationId', 'tenantId'] })
@@ -120,7 +120,7 @@ export function createShippingCarrierService(deps: {
120
120
  organizationId: input.organizationId,
121
121
  tenantId: input.tenantId,
122
122
  })
123
- await em.persistAndFlush(shipment)
123
+ await em.persist(shipment).flush()
124
124
  await emitShippingEvent('shipping_carriers.shipment.created', {
125
125
  shipmentId: shipment.id,
126
126
  orderId: input.orderId,
@@ -19,7 +19,7 @@ export async function claimWebhookProcessing(
19
19
  })
20
20
 
21
21
  try {
22
- await em.persistAndFlush(record)
22
+ await em.persist(record).flush()
23
23
  return true
24
24
  } catch (error: unknown) {
25
25
  if (error instanceof UniqueConstraintViolationException) {
@@ -48,5 +48,5 @@ export async function releaseWebhookClaim(
48
48
  scope,
49
49
  )
50
50
  if (!existing) return
51
- await em.removeAndFlush(existing)
51
+ await em.remove(existing).flush()
52
52
  }
@@ -1,4 +1,4 @@
1
- import { Entity, PrimaryKey, Property, Index, ManyToOne, Enum } from '@mikro-orm/core'
1
+ import { Entity, Enum, Index, ManyToOne, PrimaryKey, Property } from '@mikro-orm/decorators/legacy'
2
2
 
3
3
  export type StaffLeaveRequestStatus = 'pending' | 'approved' | 'rejected'
4
4
 
@@ -1,5 +1,6 @@
1
1
  import { NextResponse } from 'next/server'
2
2
  import { z } from 'zod'
3
+ import { sql } from 'kysely'
3
4
  import { resolveTranslationsRouteContext, requireTranslationFeatures } from '@open-mercato/core/modules/translations/api/context'
4
5
  import { translationBodySchema, entityTypeParamSchema, entityIdParamSchema } from '@open-mercato/core/modules/translations/data/validators'
5
6
  import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
@@ -27,14 +28,14 @@ export async function GET(req: Request, ctx: { params?: { entityType?: string; e
27
28
  entityId: ctx.params?.entityId,
28
29
  })
29
30
 
30
- const row = await context.knex('entity_translations')
31
- .where({
32
- entity_type: entityType,
33
- entity_id: entityId,
34
- })
35
- .andWhereRaw('tenant_id is not distinct from ?', [context.tenantId])
36
- .andWhereRaw('organization_id is not distinct from ?', [context.organizationId])
37
- .first()
31
+ const row = await (context.db as any)
32
+ .selectFrom('entity_translations')
33
+ .selectAll()
34
+ .where('entity_type', '=', entityType)
35
+ .where('entity_id', '=', entityId)
36
+ .where(sql<boolean>`tenant_id is not distinct from ${context.tenantId}`)
37
+ .where(sql<boolean>`organization_id is not distinct from ${context.organizationId}`)
38
+ .executeTakeFirst() as Record<string, any> | undefined
38
39
 
39
40
  if (!row) {
40
41
  return NextResponse.json({ error: 'Not found' }, { status: 404 })
@@ -86,9 +87,11 @@ export async function PUT(req: Request, ctx: { params?: { entityType?: string; e
86
87
  ctx: context.commandCtx,
87
88
  })
88
89
 
89
- const row = await context.knex('entity_translations')
90
- .where({ id: result.rowId })
91
- .first()
90
+ const row = await (context.db as any)
91
+ .selectFrom('entity_translations')
92
+ .selectAll()
93
+ .where('id', '=', result.rowId)
94
+ .executeTakeFirst() as Record<string, any>
92
95
 
93
96
  const response = NextResponse.json({
94
97
  entityType: row.entity_type,
@@ -5,13 +5,13 @@ import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
5
5
  import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
6
6
  import type { EntityManager } from '@mikro-orm/postgresql'
7
7
  import type { AwilixContainer } from 'awilix'
8
- import type { Knex } from 'knex'
8
+ import type { Kysely } from 'kysely'
9
9
 
10
10
  export type TranslationsRouteContext = {
11
11
  container: AwilixContainer
12
12
  auth: NonNullable<Awaited<ReturnType<typeof getAuthFromRequest>>>
13
13
  em: EntityManager
14
- knex: Knex
14
+ db: Kysely<any>
15
15
  organizationId: string | null
16
16
  tenantId: string
17
17
  commandCtx: CommandRuntimeContext
@@ -26,7 +26,7 @@ export async function resolveTranslationsRouteContext(req: Request): Promise<Tra
26
26
 
27
27
  const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })
28
28
  const em = container.resolve('em') as EntityManager
29
- const knex = (em as unknown as { getConnection(): { getKnex(): Knex } }).getConnection().getKnex()
29
+ const db = em.getKysely<any>()
30
30
  const tenantId: string = scope?.tenantId ?? auth.tenantId
31
31
  const organizationId = scope?.selectedId ?? auth.orgId ?? null
32
32
 
@@ -43,7 +43,7 @@ export async function resolveTranslationsRouteContext(req: Request): Promise<Tra
43
43
  container,
44
44
  auth,
45
45
  em,
46
- knex,
46
+ db,
47
47
  organizationId,
48
48
  tenantId,
49
49
  commandCtx,
@@ -3,7 +3,7 @@ import type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared
3
3
  import { ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'
4
4
  import { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'
5
5
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
6
- import type { Knex } from 'knex'
6
+ import { type Kysely, sql } from 'kysely'
7
7
  import type { EntityManager } from '@mikro-orm/postgresql'
8
8
  import { emitTranslationsEvent } from '../events'
9
9
 
@@ -36,23 +36,26 @@ type DeleteInput = {
36
36
  tenantId: string
37
37
  }
38
38
 
39
- function resolveKnex(ctx: CommandRuntimeContext): Knex {
39
+ function resolveDb(ctx: CommandRuntimeContext): Kysely<any> {
40
40
  const em = ctx.container.resolve('em') as EntityManager
41
- return (em as unknown as { getConnection(): { getKnex(): Knex } }).getConnection().getKnex()
41
+ return em.getKysely<any>()
42
42
  }
43
43
 
44
44
  async function loadTranslationSnapshot(
45
- knex: Knex,
45
+ db: Kysely<any>,
46
46
  entityType: string,
47
47
  entityId: string,
48
48
  tenantId: string,
49
49
  organizationId: string | null,
50
50
  ): Promise<TranslationSnapshot | null> {
51
- const row = await knex('entity_translations')
52
- .where({ entity_type: entityType, entity_id: entityId })
53
- .andWhereRaw('tenant_id is not distinct from ?', [tenantId])
54
- .andWhereRaw('organization_id is not distinct from ?', [organizationId])
55
- .first()
51
+ const row = await (db as any)
52
+ .selectFrom('entity_translations')
53
+ .selectAll()
54
+ .where('entity_type', '=', entityType)
55
+ .where('entity_id', '=', entityId)
56
+ .where(sql<boolean>`tenant_id is not distinct from ${tenantId}`)
57
+ .where(sql<boolean>`organization_id is not distinct from ${organizationId}`)
58
+ .executeTakeFirst() as Record<string, any> | undefined
56
59
 
57
60
  if (!row) return null
58
61
  return {
@@ -70,35 +73,44 @@ const saveTranslationCommand: CommandHandler<SaveInput, { rowId: string }> = {
70
73
 
71
74
  async prepare(input, ctx) {
72
75
  ensureTenantScope(ctx, input.tenantId)
73
- const knex = resolveKnex(ctx)
74
- const snapshot = await loadTranslationSnapshot(knex, input.entityType, input.entityId, input.tenantId, input.organizationId)
76
+ const db = resolveDb(ctx)
77
+ const snapshot = await loadTranslationSnapshot(db, input.entityType, input.entityId, input.tenantId, input.organizationId)
75
78
  return { before: snapshot }
76
79
  },
77
80
 
78
81
  async execute(input, ctx) {
79
- const knex = resolveKnex(ctx)
80
- const existing = await knex('entity_translations')
81
- .where({ entity_type: input.entityType, entity_id: input.entityId })
82
- .andWhereRaw('tenant_id is not distinct from ?', [input.tenantId])
83
- .andWhereRaw('organization_id is not distinct from ?', [input.organizationId])
84
- .first()
85
-
86
- const now = knex.fn.now()
82
+ const db = resolveDb(ctx) as any
83
+ const existing = await db
84
+ .selectFrom('entity_translations')
85
+ .select(['id'])
86
+ .where('entity_type', '=', input.entityType)
87
+ .where('entity_id', '=', input.entityId)
88
+ .where(sql<boolean>`tenant_id is not distinct from ${input.tenantId}`)
89
+ .where(sql<boolean>`organization_id is not distinct from ${input.organizationId}`)
90
+ .executeTakeFirst() as { id: string } | undefined
87
91
 
88
92
  if (existing) {
89
- await knex('entity_translations')
90
- .where({ id: existing.id })
91
- .update({ translations: input.translations, updated_at: now })
93
+ await db
94
+ .updateTable('entity_translations')
95
+ .set({
96
+ translations: sql`${JSON.stringify(input.translations)}::jsonb`,
97
+ updated_at: sql`now()`,
98
+ } as any)
99
+ .where('id', '=', existing.id)
100
+ .execute()
92
101
  } else {
93
- await knex('entity_translations').insert({
94
- entity_type: input.entityType,
95
- entity_id: input.entityId,
96
- organization_id: input.organizationId,
97
- tenant_id: input.tenantId,
98
- translations: input.translations,
99
- created_at: now,
100
- updated_at: now,
101
- })
102
+ await db
103
+ .insertInto('entity_translations')
104
+ .values({
105
+ entity_type: input.entityType,
106
+ entity_id: input.entityId,
107
+ organization_id: input.organizationId,
108
+ tenant_id: input.tenantId,
109
+ translations: sql`${JSON.stringify(input.translations)}::jsonb`,
110
+ created_at: sql`now()`,
111
+ updated_at: sql`now()`,
112
+ } as any)
113
+ .execute()
102
114
  }
103
115
 
104
116
  await emitTranslationsEvent('translations.translation.updated', {
@@ -108,18 +120,21 @@ const saveTranslationCommand: CommandHandler<SaveInput, { rowId: string }> = {
108
120
  tenantId: input.tenantId,
109
121
  }, { persistent: true }).catch(() => undefined)
110
122
 
111
- const saved = await knex('entity_translations')
112
- .where({ entity_type: input.entityType, entity_id: input.entityId })
113
- .andWhereRaw('tenant_id is not distinct from ?', [input.tenantId])
114
- .andWhereRaw('organization_id is not distinct from ?', [input.organizationId])
115
- .first()
123
+ const saved = await db
124
+ .selectFrom('entity_translations')
125
+ .select(['id'])
126
+ .where('entity_type', '=', input.entityType)
127
+ .where('entity_id', '=', input.entityId)
128
+ .where(sql<boolean>`tenant_id is not distinct from ${input.tenantId}`)
129
+ .where(sql<boolean>`organization_id is not distinct from ${input.organizationId}`)
130
+ .executeTakeFirst() as { id: string } | undefined
116
131
 
117
- return { rowId: saved.id }
132
+ return { rowId: saved?.id ?? '' }
118
133
  },
119
134
 
120
135
  async captureAfter(input, _result, ctx) {
121
- const knex = resolveKnex(ctx)
122
- return await loadTranslationSnapshot(knex, input.entityType, input.entityId, input.tenantId, input.organizationId)
136
+ const db = resolveDb(ctx)
137
+ return await loadTranslationSnapshot(db, input.entityType, input.entityId, input.tenantId, input.organizationId)
123
138
  },
124
139
 
125
140
  async buildLog({ snapshots, result }) {
@@ -143,36 +158,47 @@ const saveTranslationCommand: CommandHandler<SaveInput, { rowId: string }> = {
143
158
  async undo({ logEntry, ctx }) {
144
159
  const payload = extractUndoPayload<TranslationUndoPayload>(logEntry)
145
160
  const before = payload?.before ?? null
146
- const knex = resolveKnex(ctx)
161
+ const db = resolveDb(ctx) as any
147
162
 
148
163
  if (!before || !before.translations) {
149
164
  // Was a create — delete the record
150
165
  const resourceId = logEntry?.resourceId
151
166
  if (resourceId) {
152
- await knex('entity_translations').where({ id: resourceId }).del()
167
+ await db.deleteFrom('entity_translations').where('id', '=', resourceId).execute()
153
168
  }
154
169
  } else {
155
170
  // Was an update — restore previous translations
156
- const existing = await knex('entity_translations')
157
- .where({ entity_type: before.entityType, entity_id: before.entityId })
158
- .andWhereRaw('tenant_id is not distinct from ?', [before.tenantId])
159
- .andWhereRaw('organization_id is not distinct from ?', [before.organizationId])
160
- .first()
171
+ const existing = await db
172
+ .selectFrom('entity_translations')
173
+ .select(['id'])
174
+ .where('entity_type', '=', before.entityType)
175
+ .where('entity_id', '=', before.entityId)
176
+ .where(sql<boolean>`tenant_id is not distinct from ${before.tenantId}`)
177
+ .where(sql<boolean>`organization_id is not distinct from ${before.organizationId}`)
178
+ .executeTakeFirst() as { id: string } | undefined
161
179
 
162
180
  if (existing) {
163
- await knex('entity_translations')
164
- .where({ id: existing.id })
165
- .update({ translations: before.translations, updated_at: knex.fn.now() })
181
+ await db
182
+ .updateTable('entity_translations')
183
+ .set({
184
+ translations: sql`${JSON.stringify(before.translations)}::jsonb`,
185
+ updated_at: sql`now()`,
186
+ } as any)
187
+ .where('id', '=', existing.id)
188
+ .execute()
166
189
  } else {
167
- await knex('entity_translations').insert({
168
- entity_type: before.entityType,
169
- entity_id: before.entityId,
170
- organization_id: before.organizationId,
171
- tenant_id: before.tenantId,
172
- translations: before.translations,
173
- created_at: knex.fn.now(),
174
- updated_at: knex.fn.now(),
175
- })
190
+ await db
191
+ .insertInto('entity_translations')
192
+ .values({
193
+ entity_type: before.entityType,
194
+ entity_id: before.entityId,
195
+ organization_id: before.organizationId,
196
+ tenant_id: before.tenantId,
197
+ translations: sql`${JSON.stringify(before.translations)}::jsonb`,
198
+ created_at: sql`now()`,
199
+ updated_at: sql`now()`,
200
+ } as any)
201
+ .execute()
176
202
  }
177
203
  }
178
204
  },
@@ -183,18 +209,21 @@ const deleteTranslationCommand: CommandHandler<DeleteInput, { deleted: boolean }
183
209
 
184
210
  async prepare(input, ctx) {
185
211
  ensureTenantScope(ctx, input.tenantId)
186
- const knex = resolveKnex(ctx)
187
- const snapshot = await loadTranslationSnapshot(knex, input.entityType, input.entityId, input.tenantId, input.organizationId)
212
+ const db = resolveDb(ctx)
213
+ const snapshot = await loadTranslationSnapshot(db, input.entityType, input.entityId, input.tenantId, input.organizationId)
188
214
  return { before: snapshot }
189
215
  },
190
216
 
191
217
  async execute(input, ctx) {
192
- const knex = resolveKnex(ctx)
193
- const count = await knex('entity_translations')
194
- .where({ entity_type: input.entityType, entity_id: input.entityId })
195
- .andWhereRaw('tenant_id is not distinct from ?', [input.tenantId])
196
- .andWhereRaw('organization_id is not distinct from ?', [input.organizationId])
197
- .del()
218
+ const db = resolveDb(ctx) as any
219
+ const result = await db
220
+ .deleteFrom('entity_translations')
221
+ .where('entity_type', '=', input.entityType)
222
+ .where('entity_id', '=', input.entityId)
223
+ .where(sql<boolean>`tenant_id is not distinct from ${input.tenantId}`)
224
+ .where(sql<boolean>`organization_id is not distinct from ${input.organizationId}`)
225
+ .executeTakeFirst() as { numDeletedRows?: bigint | number } | undefined
226
+ const count = Number(result?.numDeletedRows ?? 0)
198
227
 
199
228
  await emitTranslationsEvent('translations.translation.deleted', {
200
229
  entityType: input.entityType,
@@ -227,24 +256,30 @@ const deleteTranslationCommand: CommandHandler<DeleteInput, { deleted: boolean }
227
256
  const payload = extractUndoPayload<TranslationUndoPayload>(logEntry)
228
257
  const before = payload?.before
229
258
  if (!before || !before.translations) return
230
- const knex = resolveKnex(ctx)
259
+ const db = resolveDb(ctx) as any
231
260
 
232
- const existing = await knex('entity_translations')
233
- .where({ entity_type: before.entityType, entity_id: before.entityId })
234
- .andWhereRaw('tenant_id is not distinct from ?', [before.tenantId])
235
- .andWhereRaw('organization_id is not distinct from ?', [before.organizationId])
236
- .first()
261
+ const existing = await db
262
+ .selectFrom('entity_translations')
263
+ .select(['id'])
264
+ .where('entity_type', '=', before.entityType)
265
+ .where('entity_id', '=', before.entityId)
266
+ .where(sql<boolean>`tenant_id is not distinct from ${before.tenantId}`)
267
+ .where(sql<boolean>`organization_id is not distinct from ${before.organizationId}`)
268
+ .executeTakeFirst() as { id: string } | undefined
237
269
 
238
270
  if (!existing) {
239
- await knex('entity_translations').insert({
240
- entity_type: before.entityType,
241
- entity_id: before.entityId,
242
- organization_id: before.organizationId,
243
- tenant_id: before.tenantId,
244
- translations: before.translations,
245
- created_at: knex.fn.now(),
246
- updated_at: knex.fn.now(),
247
- })
271
+ await db
272
+ .insertInto('entity_translations')
273
+ .values({
274
+ entity_type: before.entityType,
275
+ entity_id: before.entityId,
276
+ organization_id: before.organizationId,
277
+ tenant_id: before.tenantId,
278
+ translations: sql`${JSON.stringify(before.translations)}::jsonb`,
279
+ created_at: sql`now()`,
280
+ updated_at: sql`now()`,
281
+ } as any)
282
+ .execute()
248
283
  }
249
284
  },
250
285
  }
@@ -226,6 +226,10 @@ export function TranslationManager({
226
226
  }
227
227
  if (hasValues) body[locale] = localeFields
228
228
  }
229
+ if (Object.keys(body).length === 0) {
230
+ console.warn('[translations] Save skipped: payload is empty — no locale contains any non-empty field')
231
+ throw new Error(t('translations.manager.errors.nothingToSave', 'Nothing to save — enter a translation first'))
232
+ }
229
233
  const res = await apiCall(
230
234
  `/api/translations/${encodeURIComponent(entityType)}/${encodeURIComponent(recordId)}`,
231
235
  {
@@ -289,20 +293,25 @@ export function TranslationManager({
289
293
 
290
294
  const renderLocaleTabs = () => (
291
295
  <div className="flex gap-1 border-b">
292
- {locales.map((locale) => (
293
- <button
294
- key={locale}
295
- type="button"
296
- className={`px-3 py-1.5 text-sm font-medium transition-colors ${
297
- activeLocale === locale
298
- ? 'border-b-2 border-primary text-primary'
299
- : 'text-muted-foreground hover:text-foreground'
300
- }`}
301
- onClick={() => setActiveLocale(locale)}
302
- >
303
- {locale.toUpperCase()}
304
- </button>
305
- ))}
296
+ {locales.map((locale) => {
297
+ const isActive = activeLocale === locale
298
+ return (
299
+ <button
300
+ key={locale}
301
+ type="button"
302
+ data-state={isActive ? 'active' : 'inactive'}
303
+ data-locale={locale}
304
+ className={`px-3 py-1.5 text-sm font-medium transition-colors ${
305
+ isActive
306
+ ? 'border-b-2 border-primary text-primary'
307
+ : 'text-muted-foreground hover:text-foreground'
308
+ }`}
309
+ onClick={() => setActiveLocale(locale)}
310
+ >
311
+ {locale.toUpperCase()}
312
+ </button>
313
+ )
314
+ })}
306
315
  </div>
307
316
  )
308
317
 
@@ -1,4 +1,4 @@
1
- import { Entity, PrimaryKey, Property, Index } from '@mikro-orm/core'
1
+ import { Entity, Index, PrimaryKey, Property } from '@mikro-orm/decorators/legacy'
2
2
 
3
3
  @Entity({ tableName: 'entity_translations' })
4
4
  @Index({ name: 'entity_translations_type_tenant_idx', properties: ['entityType', 'tenantId'] })
@@ -13,6 +13,7 @@
13
13
  "translations.manager.description": "Verwalte Übersetzungen für Entitätsdatensätze in unterstützten Sprachen.",
14
14
  "translations.manager.errors.loadEntities": "Fehler beim Laden der Entitäten",
15
15
  "translations.manager.errors.loadTranslation": "Fehler beim Laden der Übersetzungen",
16
+ "translations.manager.errors.nothingToSave": "Nichts zu speichern — gib zuerst eine Übersetzung ein",
16
17
  "translations.manager.errors.save": "Fehler beim Speichern der Übersetzungen",
17
18
  "translations.manager.errors.selectRecord": "Wähle eine Entität und einen Datensatz vor dem Speichern",
18
19
  "translations.manager.fields.baseValue": "Basiswert",
@@ -13,6 +13,7 @@
13
13
  "translations.manager.description": "Manage translations for entity records across supported locales.",
14
14
  "translations.manager.errors.loadEntities": "Failed to load entities",
15
15
  "translations.manager.errors.loadTranslation": "Failed to load translations",
16
+ "translations.manager.errors.nothingToSave": "Nothing to save — enter a translation first",
16
17
  "translations.manager.errors.save": "Failed to save translations",
17
18
  "translations.manager.errors.selectRecord": "Select an entity and record before saving",
18
19
  "translations.manager.fields.baseValue": "Base value",
@@ -13,6 +13,7 @@
13
13
  "translations.manager.description": "Gestiona las traducciones de registros de entidades en los idiomas soportados.",
14
14
  "translations.manager.errors.loadEntities": "Error al cargar las entidades",
15
15
  "translations.manager.errors.loadTranslation": "Error al cargar las traducciones",
16
+ "translations.manager.errors.nothingToSave": "Nada que guardar — introduce primero una traducción",
16
17
  "translations.manager.errors.save": "Error al guardar las traducciones",
17
18
  "translations.manager.errors.selectRecord": "Selecciona una entidad y un registro antes de guardar",
18
19
  "translations.manager.fields.baseValue": "Valor base",
@@ -13,6 +13,7 @@
13
13
  "translations.manager.description": "Zarządzaj tłumaczeniami rekordów encji w obsługiwanych językach.",
14
14
  "translations.manager.errors.loadEntities": "Nie udało się załadować encji",
15
15
  "translations.manager.errors.loadTranslation": "Nie udało się załadować tłumaczeń",
16
+ "translations.manager.errors.nothingToSave": "Nic do zapisania — najpierw wprowadź tłumaczenie",
16
17
  "translations.manager.errors.save": "Nie udało się zapisać tłumaczeń",
17
18
  "translations.manager.errors.selectRecord": "Wybierz encję i rekord przed zapisaniem",
18
19
  "translations.manager.fields.baseValue": "Wartość bazowa",
@@ -1,11 +1,11 @@
1
1
  import type { AwilixContainer } from 'awilix'
2
- import type { Knex } from 'knex'
2
+ import type { Kysely } from 'kysely'
3
3
  import { applyLocalizedContent } from '@open-mercato/shared/lib/localization/resolver'
4
4
  import { batchLoadTranslations } from './batch'
5
5
 
6
- function resolveKnex(container: AwilixContainer): Knex {
7
- const em = container.resolve('em') as { getConnection(): { getKnex(): Knex } }
8
- return em.getConnection().getKnex()
6
+ function resolveDb(container: AwilixContainer): Kysely<any> {
7
+ const em = container.resolve('em') as { getKysely<T = any>(): Kysely<T> }
8
+ return em.getKysely<any>()
9
9
  }
10
10
 
11
11
  export async function applyTranslationOverlays(
@@ -18,9 +18,9 @@ export async function applyTranslationOverlays(
18
18
  container: AwilixContainer
19
19
  },
20
20
  ): Promise<Record<string, unknown>[]> {
21
- const knex = resolveKnex(options.container)
21
+ const db = resolveDb(options.container)
22
22
  const entityIds = items.map((item) => String(item.id)).filter(Boolean)
23
- const translationsMap = await batchLoadTranslations(knex, options.entityType, entityIds, {
23
+ const translationsMap = await batchLoadTranslations(db, options.entityType, entityIds, {
24
24
  tenantId: options.tenantId,
25
25
  organizationId: options.organizationId,
26
26
  })