@open-mercato/core 0.6.6-develop.6460.1.f94c74174c → 0.6.6-develop.6471.1.9ab5bdd79a

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 (1256) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/bootstrap.js +13 -11
  3. package/dist/bootstrap.js.map +2 -2
  4. package/dist/helpers/integration/auth.js +148 -82
  5. package/dist/helpers/integration/auth.js.map +2 -2
  6. package/dist/helpers/integration/queue-runner.js +4 -2
  7. package/dist/helpers/integration/queue-runner.js.map +2 -2
  8. package/dist/modules/api_keys/services/apiKeyService.js +5 -3
  9. package/dist/modules/api_keys/services/apiKeyService.js.map +2 -2
  10. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +4 -2
  11. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
  12. package/dist/modules/attachments/api/library/[id]/route.js +3 -1
  13. package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
  14. package/dist/modules/attachments/api/route.js +8 -6
  15. package/dist/modules/attachments/api/route.js.map +2 -2
  16. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +5 -3
  17. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  18. package/dist/modules/attachments/lib/assignmentDetails.js +3 -1
  19. package/dist/modules/attachments/lib/assignmentDetails.js.map +2 -2
  20. package/dist/modules/attachments/lib/drivers/driverFactory.js +3 -1
  21. package/dist/modules/attachments/lib/drivers/driverFactory.js.map +2 -2
  22. package/dist/modules/attachments/lib/ocrQueue.js +10 -11
  23. package/dist/modules/attachments/lib/ocrQueue.js.map +2 -2
  24. package/dist/modules/attachments/lib/ocrService.js +6 -4
  25. package/dist/modules/attachments/lib/ocrService.js.map +2 -2
  26. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +3 -1
  27. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +2 -2
  28. package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js +3 -1
  29. package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js.map +2 -2
  30. package/dist/modules/audit_logs/backend/audit-logs/page.js +3 -1
  31. package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
  32. package/dist/modules/audit_logs/components/AuditLogsActions.js +4 -2
  33. package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
  34. package/dist/modules/audit_logs/services/accessLogService.js +4 -2
  35. package/dist/modules/audit_logs/services/accessLogService.js.map +2 -2
  36. package/dist/modules/audit_logs/services/actionLogService.js +7 -5
  37. package/dist/modules/audit_logs/services/actionLogService.js.map +3 -3
  38. package/dist/modules/auth/api/profile/route.js +4 -2
  39. package/dist/modules/auth/api/profile/route.js.map +2 -2
  40. package/dist/modules/auth/api/reset/confirm.js +3 -1
  41. package/dist/modules/auth/api/reset/confirm.js.map +2 -2
  42. package/dist/modules/auth/api/reset.js +4 -2
  43. package/dist/modules/auth/api/reset.js.map +2 -2
  44. package/dist/modules/auth/api/roles/route.js +3 -1
  45. package/dist/modules/auth/api/roles/route.js.map +2 -2
  46. package/dist/modules/auth/api/sidebar/variants/route.js +3 -1
  47. package/dist/modules/auth/api/sidebar/variants/route.js.map +2 -2
  48. package/dist/modules/auth/api/users/resend-invite/route.js +4 -2
  49. package/dist/modules/auth/api/users/resend-invite/route.js.map +2 -2
  50. package/dist/modules/auth/api/users/route.js +3 -1
  51. package/dist/modules/auth/api/users/route.js.map +2 -2
  52. package/dist/modules/auth/backend/auth/profile/page.js +3 -1
  53. package/dist/modules/auth/backend/auth/profile/page.js.map +2 -2
  54. package/dist/modules/auth/backend/profile/change-password/page.js +3 -1
  55. package/dist/modules/auth/backend/profile/change-password/page.js.map +2 -2
  56. package/dist/modules/auth/backend/users/[id]/edit/page.js +5 -3
  57. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  58. package/dist/modules/auth/backend/users/create/page.js +4 -2
  59. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  60. package/dist/modules/auth/cli.js +10 -0
  61. package/dist/modules/auth/cli.js.map +2 -2
  62. package/dist/modules/auth/commands/users.js +4 -2
  63. package/dist/modules/auth/commands/users.js.map +2 -2
  64. package/dist/modules/auth/lib/consentIntegrity.js +3 -3
  65. package/dist/modules/auth/lib/consentIntegrity.js.map +2 -2
  66. package/dist/modules/auth/lib/setup-app.js +9 -10
  67. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  68. package/dist/modules/auth/lib/tenantAccess.js +3 -1
  69. package/dist/modules/auth/lib/tenantAccess.js.map +2 -2
  70. package/dist/modules/auth/lib/tokenHash.js +3 -3
  71. package/dist/modules/auth/lib/tokenHash.js.map +2 -2
  72. package/dist/modules/business_rules/api/rules/route.js +4 -2
  73. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  74. package/dist/modules/business_rules/lib/expression-evaluator.js +7 -5
  75. package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
  76. package/dist/modules/business_rules/lib/rule-engine.js +5 -3
  77. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  78. package/dist/modules/business_rules/lib/rule-evaluator.js +11 -12
  79. package/dist/modules/business_rules/lib/rule-evaluator.js.map +2 -2
  80. package/dist/modules/business_rules/subscribers/crud-rule-trigger.js +3 -1
  81. package/dist/modules/business_rules/subscribers/crud-rule-trigger.js.map +2 -2
  82. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +3 -1
  83. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +2 -2
  84. package/dist/modules/catalog/ai-agents-context.js +4 -5
  85. package/dist/modules/catalog/ai-agents-context.js.map +2 -2
  86. package/dist/modules/catalog/ai-tools/_shared.js +3 -1
  87. package/dist/modules/catalog/ai-tools/_shared.js.map +2 -2
  88. package/dist/modules/catalog/ai-tools/authoring-pack.js +3 -1
  89. package/dist/modules/catalog/ai-tools/authoring-pack.js.map +2 -2
  90. package/dist/modules/catalog/ai-tools/merchandising-pack.js +3 -1
  91. package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
  92. package/dist/modules/catalog/api/dictionaries/[key]/route.js +3 -1
  93. package/dist/modules/catalog/api/dictionaries/[key]/route.js.map +2 -2
  94. package/dist/modules/catalog/api/prices/route.js +3 -1
  95. package/dist/modules/catalog/api/prices/route.js.map +2 -2
  96. package/dist/modules/catalog/api/products/route.js +5 -3
  97. package/dist/modules/catalog/api/products/route.js.map +2 -2
  98. package/dist/modules/catalog/api/settings/route.js +4 -2
  99. package/dist/modules/catalog/api/settings/route.js.map +2 -2
  100. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +14 -12
  101. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  102. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +8 -6
  103. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  104. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js +5 -3
  105. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js.map +2 -2
  106. package/dist/modules/catalog/backend/catalog/products/create/page.js +5 -6
  107. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  108. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js +3 -1
  109. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
  110. package/dist/modules/catalog/components/PriceKindSettings.js +5 -3
  111. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  112. package/dist/modules/catalog/components/UnitPriceDisplaySettings.js +4 -2
  113. package/dist/modules/catalog/components/UnitPriceDisplaySettings.js.map +2 -2
  114. package/dist/modules/catalog/inbox-actions.js +4 -2
  115. package/dist/modules/catalog/inbox-actions.js.map +2 -2
  116. package/dist/modules/catalog/seed/examples.js +4 -5
  117. package/dist/modules/catalog/seed/examples.js.map +2 -2
  118. package/dist/modules/catalog/subscribers/low-stock-notification.js +3 -1
  119. package/dist/modules/catalog/subscribers/low-stock-notification.js.map +2 -2
  120. package/dist/modules/catalog/widgets/injection/product-seo/state.js +3 -1
  121. package/dist/modules/catalog/widgets/injection/product-seo/state.js.map +2 -2
  122. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +12 -11
  123. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +2 -2
  124. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +3 -1
  125. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +2 -2
  126. package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js +3 -1
  127. package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js.map +2 -2
  128. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +5 -3
  129. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
  130. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +6 -6
  131. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
  132. package/dist/modules/communication_channels/commands/connect-credential-channel.js +4 -6
  133. package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +2 -2
  134. package/dist/modules/communication_channels/commands/delete-channel.js +3 -3
  135. package/dist/modules/communication_channels/commands/delete-channel.js.map +2 -2
  136. package/dist/modules/communication_channels/commands/deliver-outbound-message.js +4 -5
  137. package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +2 -2
  138. package/dist/modules/communication_channels/commands/disconnect-channel.js +3 -3
  139. package/dist/modules/communication_channels/commands/disconnect-channel.js.map +2 -2
  140. package/dist/modules/communication_channels/commands/ingest-inbound-message.js +5 -12
  141. package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
  142. package/dist/modules/communication_channels/commands/push-unregister.js +3 -3
  143. package/dist/modules/communication_channels/commands/push-unregister.js.map +2 -2
  144. package/dist/modules/communication_channels/commands/reassign-conversation.js +5 -3
  145. package/dist/modules/communication_channels/commands/reassign-conversation.js.map +2 -2
  146. package/dist/modules/communication_channels/lib/dead-letter.js +3 -3
  147. package/dist/modules/communication_channels/lib/dead-letter.js.map +2 -2
  148. package/dist/modules/communication_channels/lib/email-mime.js +4 -6
  149. package/dist/modules/communication_channels/lib/email-mime.js.map +2 -2
  150. package/dist/modules/communication_channels/lib/oauth-client-config.js +5 -3
  151. package/dist/modules/communication_channels/lib/oauth-client-config.js.map +2 -2
  152. package/dist/modules/communication_channels/lib/send-as-user.js +3 -1
  153. package/dist/modules/communication_channels/lib/send-as-user.js.map +2 -2
  154. package/dist/modules/communication_channels/lib/thread-token.js +4 -2
  155. package/dist/modules/communication_channels/lib/thread-token.js.map +2 -2
  156. package/dist/modules/communication_channels/setup.js +3 -4
  157. package/dist/modules/communication_channels/setup.js.map +2 -2
  158. package/dist/modules/communication_channels/workers/channel-import-history.js +4 -6
  159. package/dist/modules/communication_channels/workers/channel-import-history.js.map +2 -2
  160. package/dist/modules/communication_channels/workers/gmail-history-sync.js +8 -16
  161. package/dist/modules/communication_channels/workers/gmail-history-sync.js.map +2 -2
  162. package/dist/modules/communication_channels/workers/gmail-renew-watch.js +5 -7
  163. package/dist/modules/communication_channels/workers/gmail-renew-watch.js.map +2 -2
  164. package/dist/modules/communication_channels/workers/outbound-delivery.js +6 -12
  165. package/dist/modules/communication_channels/workers/outbound-delivery.js.map +2 -2
  166. package/dist/modules/communication_channels/workers/poll-channel.js +7 -15
  167. package/dist/modules/communication_channels/workers/poll-channel.js.map +2 -2
  168. package/dist/modules/communication_channels/workers/poll-tick.js +5 -6
  169. package/dist/modules/communication_channels/workers/poll-tick.js.map +2 -2
  170. package/dist/modules/communication_channels/workers/reaction-processor.js +5 -9
  171. package/dist/modules/communication_channels/workers/reaction-processor.js.map +2 -2
  172. package/dist/modules/configs/api/cache/route.js +4 -2
  173. package/dist/modules/configs/api/cache/route.js.map +2 -2
  174. package/dist/modules/configs/api/system-status/route.js +4 -2
  175. package/dist/modules/configs/api/system-status/route.js.map +2 -2
  176. package/dist/modules/configs/api/upgrade-actions/route.js +4 -2
  177. package/dist/modules/configs/api/upgrade-actions/route.js.map +2 -2
  178. package/dist/modules/configs/components/ModuleTelemetryPanel.js +3 -1
  179. package/dist/modules/configs/components/ModuleTelemetryPanel.js.map +2 -2
  180. package/dist/modules/configs/lib/touchGeneratedBarrels.js +2 -1
  181. package/dist/modules/configs/lib/touchGeneratedBarrels.js.map +2 -2
  182. package/dist/modules/configs/services/upgradeActionsService.js +6 -3
  183. package/dist/modules/configs/services/upgradeActionsService.js.map +2 -2
  184. package/dist/modules/currencies/components/CurrencyFetchingConfig.js +3 -1
  185. package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
  186. package/dist/modules/currencies/lib/exchangeRateFormConfig.js +3 -1
  187. package/dist/modules/currencies/lib/exchangeRateFormConfig.js.map +2 -2
  188. package/dist/modules/currencies/services/providers/nbp.js +6 -4
  189. package/dist/modules/currencies/services/providers/nbp.js.map +2 -2
  190. package/dist/modules/currencies/services/providers/raiffeisen.js +7 -7
  191. package/dist/modules/currencies/services/providers/raiffeisen.js.map +2 -2
  192. package/dist/modules/customer_accounts/api/domain-resolve/all.js +6 -5
  193. package/dist/modules/customer_accounts/api/domain-resolve/all.js.map +2 -2
  194. package/dist/modules/customer_accounts/api/signup.js +4 -2
  195. package/dist/modules/customer_accounts/api/signup.js.map +2 -2
  196. package/dist/modules/customer_accounts/lib/customerAuthServer.js +3 -1
  197. package/dist/modules/customer_accounts/lib/customerAuthServer.js.map +2 -2
  198. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +3 -1
  199. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
  200. package/dist/modules/customer_accounts/subscribers/autoLinkCrmReverse.js +3 -1
  201. package/dist/modules/customer_accounts/subscribers/autoLinkCrmReverse.js.map +2 -2
  202. package/dist/modules/customer_accounts/subscribers/unlinkOnCompanyDelete.js +3 -1
  203. package/dist/modules/customer_accounts/subscribers/unlinkOnCompanyDelete.js.map +2 -2
  204. package/dist/modules/customer_accounts/subscribers/unlinkOnPersonDelete.js +3 -1
  205. package/dist/modules/customer_accounts/subscribers/unlinkOnPersonDelete.js.map +2 -2
  206. package/dist/modules/customers/ai-agents-context.js +4 -5
  207. package/dist/modules/customers/ai-agents-context.js.map +2 -2
  208. package/dist/modules/customers/api/activities/route.js +6 -4
  209. package/dist/modules/customers/api/activities/route.js.map +2 -2
  210. package/dist/modules/customers/api/comments/route.js +3 -1
  211. package/dist/modules/customers/api/comments/route.js.map +2 -2
  212. package/dist/modules/customers/api/companies/[id]/people/route.js +3 -1
  213. package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
  214. package/dist/modules/customers/api/companies/[id]/route.js +5 -3
  215. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  216. package/dist/modules/customers/api/companies/route.js +5 -3
  217. package/dist/modules/customers/api/companies/route.js.map +2 -2
  218. package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js +3 -1
  219. package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js.map +2 -2
  220. package/dist/modules/customers/api/dashboard/widgets/new-customers/route.js +3 -1
  221. package/dist/modules/customers/api/dashboard/widgets/new-customers/route.js.map +2 -2
  222. package/dist/modules/customers/api/dashboard/widgets/new-deals/route.js +3 -1
  223. package/dist/modules/customers/api/dashboard/widgets/new-deals/route.js.map +2 -2
  224. package/dist/modules/customers/api/dashboard/widgets/next-interactions/route.js +3 -1
  225. package/dist/modules/customers/api/dashboard/widgets/next-interactions/route.js.map +2 -2
  226. package/dist/modules/customers/api/deals/[id]/companies/route.js +3 -1
  227. package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
  228. package/dist/modules/customers/api/deals/[id]/people/route.js +3 -1
  229. package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
  230. package/dist/modules/customers/api/deals/aggregate/route.js +3 -1
  231. package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
  232. package/dist/modules/customers/api/deals/bulk-update-owner/route.js +7 -5
  233. package/dist/modules/customers/api/deals/bulk-update-owner/route.js.map +2 -2
  234. package/dist/modules/customers/api/deals/bulk-update-stage/route.js +7 -5
  235. package/dist/modules/customers/api/deals/bulk-update-stage/route.js.map +2 -2
  236. package/dist/modules/customers/api/deals/route.js +3 -1
  237. package/dist/modules/customers/api/deals/route.js.map +2 -2
  238. package/dist/modules/customers/api/deals/summary/route.js +3 -1
  239. package/dist/modules/customers/api/deals/summary/route.js.map +2 -2
  240. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +4 -2
  241. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
  242. package/dist/modules/customers/api/dictionaries/[kind]/route.js +5 -3
  243. package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
  244. package/dist/modules/customers/api/dictionaries/cache.js +3 -1
  245. package/dist/modules/customers/api/dictionaries/cache.js.map +2 -2
  246. package/dist/modules/customers/api/dictionaries/context.js +3 -1
  247. package/dist/modules/customers/api/dictionaries/context.js.map +2 -2
  248. package/dist/modules/customers/api/dictionaries/currency/route.js +3 -1
  249. package/dist/modules/customers/api/dictionaries/currency/route.js.map +2 -2
  250. package/dist/modules/customers/api/dictionaries/kind-settings/route.js +4 -2
  251. package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +2 -2
  252. package/dist/modules/customers/api/entity-roles-factory.js +7 -5
  253. package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
  254. package/dist/modules/customers/api/interactions/cancel/route.js +3 -1
  255. package/dist/modules/customers/api/interactions/cancel/route.js.map +2 -2
  256. package/dist/modules/customers/api/interactions/complete/route.js +3 -1
  257. package/dist/modules/customers/api/interactions/complete/route.js.map +2 -2
  258. package/dist/modules/customers/api/interactions/conflicts/route.js +3 -1
  259. package/dist/modules/customers/api/interactions/conflicts/route.js.map +2 -2
  260. package/dist/modules/customers/api/interactions/counts/route.js +3 -1
  261. package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
  262. package/dist/modules/customers/api/interactions/route.js +7 -4
  263. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  264. package/dist/modules/customers/api/interactions/tasks/route.js +3 -1
  265. package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
  266. package/dist/modules/customers/api/labels/assign/route.js +3 -1
  267. package/dist/modules/customers/api/labels/assign/route.js.map +2 -2
  268. package/dist/modules/customers/api/labels/route.js +6 -3
  269. package/dist/modules/customers/api/labels/route.js.map +2 -2
  270. package/dist/modules/customers/api/labels/unassign/route.js +3 -1
  271. package/dist/modules/customers/api/labels/unassign/route.js.map +2 -2
  272. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +3 -1
  273. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
  274. package/dist/modules/customers/api/people/[id]/route.js +5 -3
  275. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  276. package/dist/modules/customers/api/people/route.js +5 -3
  277. package/dist/modules/customers/api/people/route.js.map +2 -2
  278. package/dist/modules/customers/api/pipeline-stages/reorder/route.js +3 -1
  279. package/dist/modules/customers/api/pipeline-stages/reorder/route.js.map +2 -2
  280. package/dist/modules/customers/api/pipeline-stages/route.js +6 -4
  281. package/dist/modules/customers/api/pipeline-stages/route.js.map +2 -2
  282. package/dist/modules/customers/api/pipelines/route.js +6 -4
  283. package/dist/modules/customers/api/pipelines/route.js.map +2 -2
  284. package/dist/modules/customers/api/settings/address-format/route.js +4 -2
  285. package/dist/modules/customers/api/settings/address-format/route.js.map +2 -2
  286. package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js +4 -2
  287. package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js.map +2 -2
  288. package/dist/modules/customers/api/settings/stuck-threshold/route.js +4 -2
  289. package/dist/modules/customers/api/settings/stuck-threshold/route.js.map +2 -2
  290. package/dist/modules/customers/api/tags/assign/route.js +3 -1
  291. package/dist/modules/customers/api/tags/assign/route.js.map +2 -2
  292. package/dist/modules/customers/api/tags/unassign/route.js +3 -1
  293. package/dist/modules/customers/api/tags/unassign/route.js.map +2 -2
  294. package/dist/modules/customers/api/todos/route.js +6 -4
  295. package/dist/modules/customers/api/todos/route.js.map +2 -2
  296. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +5 -3
  297. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  298. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +3 -1
  299. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +2 -2
  300. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js +3 -1
  301. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js.map +2 -2
  302. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js +4 -2
  303. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js.map +2 -2
  304. package/dist/modules/customers/backend/customers/deals/page.js +4 -2
  305. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  306. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +5 -3
  307. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  308. package/dist/modules/customers/commands/deals.js +3 -1
  309. package/dist/modules/customers/commands/deals.js.map +2 -2
  310. package/dist/modules/customers/commands/dictionaries.js +3 -1
  311. package/dist/modules/customers/commands/dictionaries.js.map +2 -2
  312. package/dist/modules/customers/commands/interactions.js +4 -2
  313. package/dist/modules/customers/commands/interactions.js.map +2 -2
  314. package/dist/modules/customers/commands/shared.js +4 -2
  315. package/dist/modules/customers/commands/shared.js.map +2 -2
  316. package/dist/modules/customers/commands/todos.js +3 -1
  317. package/dist/modules/customers/commands/todos.js.map +2 -2
  318. package/dist/modules/customers/components/DictionarySettings.js +5 -3
  319. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  320. package/dist/modules/customers/components/DictionarySortSettings.js +3 -1
  321. package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
  322. package/dist/modules/customers/components/detail/ActivitiesCard.js +3 -1
  323. package/dist/modules/customers/components/detail/ActivitiesCard.js.map +2 -2
  324. package/dist/modules/customers/components/detail/ActivitiesDayStrip.js +3 -1
  325. package/dist/modules/customers/components/detail/ActivitiesDayStrip.js.map +2 -2
  326. package/dist/modules/customers/components/detail/ActivitiesSection.js +6 -4
  327. package/dist/modules/customers/components/detail/ActivitiesSection.js.map +2 -2
  328. package/dist/modules/customers/components/detail/ActivityCard.js +3 -1
  329. package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
  330. package/dist/modules/customers/components/detail/ChangelogTab.js +3 -1
  331. package/dist/modules/customers/components/detail/ChangelogTab.js.map +2 -2
  332. package/dist/modules/customers/components/detail/CompanyCard.js +3 -1
  333. package/dist/modules/customers/components/detail/CompanyCard.js.map +2 -2
  334. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +3 -1
  335. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +2 -2
  336. package/dist/modules/customers/components/detail/EntityTagsDialog.js +3 -1
  337. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
  338. package/dist/modules/customers/components/detail/InlineActivityComposer.js +3 -1
  339. package/dist/modules/customers/components/detail/InlineActivityComposer.js.map +2 -2
  340. package/dist/modules/customers/components/detail/ManageTagsDialog.js +3 -1
  341. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
  342. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +5 -3
  343. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
  344. package/dist/modules/customers/components/detail/RolesSection.js +4 -2
  345. package/dist/modules/customers/components/detail/RolesSection.js.map +2 -2
  346. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +5 -3
  347. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
  348. package/dist/modules/customers/components/linking/LinkEntityDialog.js +4 -2
  349. package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +2 -2
  350. package/dist/modules/customers/inbox-actions.js +3 -1
  351. package/dist/modules/customers/inbox-actions.js.map +2 -2
  352. package/dist/modules/customers/lib/bulkDeals.js +3 -1
  353. package/dist/modules/customers/lib/bulkDeals.js.map +2 -2
  354. package/dist/modules/customers/lib/dealClosureNotification.js +4 -2
  355. package/dist/modules/customers/lib/dealClosureNotification.js.map +2 -2
  356. package/dist/modules/customers/lib/dealStageTransitionTable.js +3 -1
  357. package/dist/modules/customers/lib/dealStageTransitionTable.js.map +2 -2
  358. package/dist/modules/customers/lib/interactionFeatureFlags.js +3 -1
  359. package/dist/modules/customers/lib/interactionFeatureFlags.js.map +2 -2
  360. package/dist/modules/customers/lib/todoCompatibility.js +3 -1
  361. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  362. package/dist/modules/customers/search.js +14 -7
  363. package/dist/modules/customers/search.js.map +2 -2
  364. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js +3 -1
  365. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js.map +2 -2
  366. package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js +3 -1
  367. package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js.map +2 -2
  368. package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js +3 -1
  369. package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js.map +2 -2
  370. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js +3 -1
  371. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js.map +2 -2
  372. package/dist/modules/dashboards/api/widgets/data/batch/route.js +3 -1
  373. package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
  374. package/dist/modules/dashboards/api/widgets/data/route.js +3 -1
  375. package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
  376. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +5 -3
  377. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  378. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js +3 -1
  379. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js.map +2 -2
  380. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js +3 -1
  381. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js.map +2 -2
  382. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js +3 -1
  383. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js.map +2 -2
  384. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js +3 -1
  385. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js.map +2 -2
  386. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +3 -1
  387. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +2 -2
  388. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js +3 -1
  389. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js.map +2 -2
  390. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +3 -1
  391. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
  392. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +3 -1
  393. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
  394. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +3 -1
  395. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
  396. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +3 -1
  397. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
  398. package/dist/modules/data_sync/api/run.js +3 -1
  399. package/dist/modules/data_sync/api/run.js.map +2 -2
  400. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +1 -1
  401. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
  402. package/dist/modules/data_sync/lib/adapter-registry.js +11 -4
  403. package/dist/modules/data_sync/lib/adapter-registry.js.map +2 -2
  404. package/dist/modules/data_sync/lib/sync-engine.js +23 -2
  405. package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
  406. package/dist/modules/data_sync/workers/sync-export.js +3 -1
  407. package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
  408. package/dist/modules/data_sync/workers/sync-import.js +3 -1
  409. package/dist/modules/data_sync/workers/sync-import.js.map +2 -2
  410. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +4 -2
  411. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  412. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js +3 -1
  413. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js.map +2 -2
  414. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +4 -2
  415. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
  416. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js +3 -1
  417. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js.map +2 -2
  418. package/dist/modules/dictionaries/api/[dictionaryId]/route.js +5 -3
  419. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  420. package/dist/modules/dictionaries/api/context.js +3 -1
  421. package/dist/modules/dictionaries/api/context.js.map +2 -2
  422. package/dist/modules/dictionaries/api/route.js +4 -2
  423. package/dist/modules/dictionaries/api/route.js.map +2 -2
  424. package/dist/modules/dictionaries/components/DictionariesManager.js +5 -3
  425. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  426. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +4 -2
  427. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
  428. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +4 -2
  429. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
  430. package/dist/modules/dictionaries/components/DictionarySelectControl.js +3 -1
  431. package/dist/modules/dictionaries/components/DictionarySelectControl.js.map +2 -2
  432. package/dist/modules/dictionaries/fields/dictionary.js +3 -1
  433. package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
  434. package/dist/modules/directory/api/organization-branding/route.js +3 -1
  435. package/dist/modules/directory/api/organization-branding/route.js.map +2 -2
  436. package/dist/modules/directory/api/organization-switcher/route.js +3 -1
  437. package/dist/modules/directory/api/organization-switcher/route.js.map +2 -2
  438. package/dist/modules/directory/commands/tenants.js +5 -3
  439. package/dist/modules/directory/commands/tenants.js.map +2 -2
  440. package/dist/modules/directory/utils/organizationScope.js +6 -4
  441. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  442. package/dist/modules/entities/api/definitions.cache.js +3 -1
  443. package/dist/modules/entities/api/definitions.cache.js.map +2 -2
  444. package/dist/modules/entities/api/definitions.js +7 -5
  445. package/dist/modules/entities/api/definitions.js.map +2 -2
  446. package/dist/modules/entities/api/records.js +4 -8
  447. package/dist/modules/entities/api/records.js.map +2 -2
  448. package/dist/modules/entities/components/EncryptionManager.js +3 -1
  449. package/dist/modules/entities/components/EncryptionManager.js.map +2 -2
  450. package/dist/modules/entities/lib/makeActivityRoute.js +3 -1
  451. package/dist/modules/entities/lib/makeActivityRoute.js.map +2 -2
  452. package/dist/modules/feature_toggles/api/overrides/route.js +3 -1
  453. package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
  454. package/dist/modules/feature_toggles/lib/feature-flag-check.js +5 -9
  455. package/dist/modules/feature_toggles/lib/feature-flag-check.js.map +2 -2
  456. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js +4 -2
  457. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js.map +2 -2
  458. package/dist/modules/inbox_ops/api/emails/[id]/route.js +4 -2
  459. package/dist/modules/inbox_ops/api/emails/[id]/route.js.map +2 -2
  460. package/dist/modules/inbox_ops/api/emails/route.js +3 -1
  461. package/dist/modules/inbox_ops/api/emails/route.js.map +2 -2
  462. package/dist/modules/inbox_ops/api/extract/route.js +3 -1
  463. package/dist/modules/inbox_ops/api/extract/route.js.map +2 -2
  464. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js +3 -1
  465. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js.map +2 -2
  466. package/dist/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/route.js +4 -2
  467. package/dist/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/route.js.map +2 -2
  468. package/dist/modules/inbox_ops/api/proposals/counts/route.js +4 -2
  469. package/dist/modules/inbox_ops/api/proposals/counts/route.js.map +2 -2
  470. package/dist/modules/inbox_ops/api/proposals/route.js +3 -1
  471. package/dist/modules/inbox_ops/api/proposals/route.js.map +2 -2
  472. package/dist/modules/inbox_ops/api/routeHelpers.js +3 -1
  473. package/dist/modules/inbox_ops/api/routeHelpers.js.map +2 -2
  474. package/dist/modules/inbox_ops/api/settings/route.js +3 -1
  475. package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
  476. package/dist/modules/inbox_ops/api/webhook/inbound.js +7 -5
  477. package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
  478. package/dist/modules/inbox_ops/lib/cache.js +4 -2
  479. package/dist/modules/inbox_ops/lib/cache.js.map +2 -2
  480. package/dist/modules/inbox_ops/lib/catalogLookup.js +3 -1
  481. package/dist/modules/inbox_ops/lib/catalogLookup.js.map +2 -2
  482. package/dist/modules/inbox_ops/lib/eventBus.js +3 -4
  483. package/dist/modules/inbox_ops/lib/eventBus.js.map +2 -2
  484. package/dist/modules/inbox_ops/lib/messagesIntegration.js +4 -8
  485. package/dist/modules/inbox_ops/lib/messagesIntegration.js.map +2 -2
  486. package/dist/modules/inbox_ops/subscribers/executionAuditor.js +3 -1
  487. package/dist/modules/inbox_ops/subscribers/executionAuditor.js.map +2 -2
  488. package/dist/modules/inbox_ops/subscribers/extractionWorker.js +10 -8
  489. package/dist/modules/inbox_ops/subscribers/extractionWorker.js.map +2 -2
  490. package/dist/modules/inbox_ops/subscribers/proposalNotifier.js +3 -1
  491. package/dist/modules/inbox_ops/subscribers/proposalNotifier.js.map +2 -2
  492. package/dist/modules/messages/api/[id]/route.js +3 -4
  493. package/dist/modules/messages/api/[id]/route.js.map +2 -2
  494. package/dist/modules/messages/commands/actions.js +3 -1
  495. package/dist/modules/messages/commands/actions.js.map +2 -2
  496. package/dist/modules/messages/components/MessagesInboxPageClient.js +3 -1
  497. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  498. package/dist/modules/messages/lib/email-sender.js +3 -7
  499. package/dist/modules/messages/lib/email-sender.js.map +2 -2
  500. package/dist/modules/messages/lib/message-objects-registry.js +3 -1
  501. package/dist/modules/messages/lib/message-objects-registry.js.map +2 -2
  502. package/dist/modules/messages/lib/message-types-registry.js +3 -1
  503. package/dist/modules/messages/lib/message-types-registry.js.map +2 -2
  504. package/dist/modules/messages/workers/send-email.worker.js +6 -4
  505. package/dist/modules/messages/workers/send-email.worker.js.map +2 -2
  506. package/dist/modules/notifications/lib/notificationMapper.js +3 -4
  507. package/dist/modules/notifications/lib/notificationMapper.js.map +2 -2
  508. package/dist/modules/notifications/lib/notificationService.js +4 -5
  509. package/dist/modules/notifications/lib/notificationService.js.map +2 -2
  510. package/dist/modules/notifications/subscribers/deliver-notification.js +8 -13
  511. package/dist/modules/notifications/subscribers/deliver-notification.js.map +2 -2
  512. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +3 -1
  513. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
  514. package/dist/modules/perspectives/services/perspectiveService.js +3 -3
  515. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  516. package/dist/modules/planner/api/access.js +3 -3
  517. package/dist/modules/planner/api/access.js.map +2 -2
  518. package/dist/modules/planner/api/availability-date-specific.js +3 -1
  519. package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
  520. package/dist/modules/planner/api/availability-weekly.js +3 -1
  521. package/dist/modules/planner/api/availability-weekly.js.map +2 -2
  522. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
  523. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  524. package/dist/modules/planner/components/AvailabilityRulesEditor.js +3 -1
  525. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  526. package/dist/modules/progress/api/jobs/route.js +3 -1
  527. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  528. package/dist/modules/query_index/components/QueryIndexesTable.js +5 -3
  529. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  530. package/dist/modules/query_index/lib/batch.js +4 -2
  531. package/dist/modules/query_index/lib/batch.js.map +2 -2
  532. package/dist/modules/query_index/lib/coverage.js +3 -1
  533. package/dist/modules/query_index/lib/coverage.js.map +2 -2
  534. package/dist/modules/query_index/lib/engine.js +13 -18
  535. package/dist/modules/query_index/lib/engine.js.map +2 -2
  536. package/dist/modules/query_index/lib/reindexer.js +8 -6
  537. package/dist/modules/query_index/lib/reindexer.js.map +2 -2
  538. package/dist/modules/query_index/lib/search-tokens.js +3 -1
  539. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  540. package/dist/modules/query_index/subscribers/coverage_refresh.js +3 -1
  541. package/dist/modules/query_index/subscribers/coverage_refresh.js.map +2 -2
  542. package/dist/modules/resources/api/comments.js +3 -1
  543. package/dist/modules/resources/api/comments.js.map +2 -2
  544. package/dist/modules/resources/api/resources/tags/assign/route.js +3 -1
  545. package/dist/modules/resources/api/resources/tags/assign/route.js.map +2 -2
  546. package/dist/modules/resources/api/resources/tags/unassign/route.js +3 -1
  547. package/dist/modules/resources/api/resources/tags/unassign/route.js.map +2 -2
  548. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +3 -1
  549. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
  550. package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
  551. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  552. package/dist/modules/resources/commands/activities.js +6 -5
  553. package/dist/modules/resources/commands/activities.js.map +2 -2
  554. package/dist/modules/resources/commands/comments.js +6 -4
  555. package/dist/modules/resources/commands/comments.js.map +2 -2
  556. package/dist/modules/resources/commands/shared.js +24 -1
  557. package/dist/modules/resources/commands/shared.js.map +2 -2
  558. package/dist/modules/sales/api/channels/route.js +3 -1
  559. package/dist/modules/sales/api/channels/route.js.map +2 -2
  560. package/dist/modules/sales/api/document-addresses/route.js +96 -6
  561. package/dist/modules/sales/api/document-addresses/route.js.map +2 -2
  562. package/dist/modules/sales/api/document-history/route.js +3 -1
  563. package/dist/modules/sales/api/document-history/route.js.map +2 -2
  564. package/dist/modules/sales/api/document-numbers/route.js +3 -1
  565. package/dist/modules/sales/api/document-numbers/route.js.map +2 -2
  566. package/dist/modules/sales/api/quotes/accept/route.js +4 -2
  567. package/dist/modules/sales/api/quotes/accept/route.js.map +2 -2
  568. package/dist/modules/sales/api/quotes/convert/route.js +3 -1
  569. package/dist/modules/sales/api/quotes/convert/route.js.map +2 -2
  570. package/dist/modules/sales/api/quotes/public/[token]/route.js +3 -1
  571. package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
  572. package/dist/modules/sales/api/quotes/send/route.js +3 -1
  573. package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
  574. package/dist/modules/sales/api/returns/[id]/route.js +3 -1
  575. package/dist/modules/sales/api/returns/[id]/route.js.map +2 -2
  576. package/dist/modules/sales/api/settings/document-numbers/route.js +4 -2
  577. package/dist/modules/sales/api/settings/document-numbers/route.js.map +2 -2
  578. package/dist/modules/sales/api/settings/order-editing/route.js +4 -2
  579. package/dist/modules/sales/api/settings/order-editing/route.js.map +2 -2
  580. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
  581. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  582. package/dist/modules/sales/backend/sales/channels/offers/page.js +6 -4
  583. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  584. package/dist/modules/sales/backend/sales/channels/page.js +4 -2
  585. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  586. package/dist/modules/sales/backend/sales/documents/[id]/page.js +20 -18
  587. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  588. package/dist/modules/sales/commands/documentAddresses.js +7 -0
  589. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  590. package/dist/modules/sales/commands/documents.js +4 -8
  591. package/dist/modules/sales/commands/documents.js.map +2 -2
  592. package/dist/modules/sales/commands/payments.js +3 -1
  593. package/dist/modules/sales/commands/payments.js.map +2 -2
  594. package/dist/modules/sales/commands/shipments.js +3 -1
  595. package/dist/modules/sales/commands/shipments.js.map +2 -2
  596. package/dist/modules/sales/components/AdjustmentKindSettings.js +5 -3
  597. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  598. package/dist/modules/sales/components/DocumentNumberSettings.js +4 -2
  599. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  600. package/dist/modules/sales/components/OrderEditingSettings.js +4 -2
  601. package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
  602. package/dist/modules/sales/components/PaymentMethodsSettings.js +5 -3
  603. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  604. package/dist/modules/sales/components/ShippingMethodsSettings.js +5 -3
  605. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  606. package/dist/modules/sales/components/StatusSettings.js +5 -3
  607. package/dist/modules/sales/components/StatusSettings.js.map +2 -2
  608. package/dist/modules/sales/components/TaxRatesSettings.js +5 -3
  609. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  610. package/dist/modules/sales/components/channels/ChannelOfferForm.js +16 -14
  611. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  612. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +4 -2
  613. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  614. package/dist/modules/sales/components/documents/AddressesSection.js +5 -3
  615. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  616. package/dist/modules/sales/components/documents/AdjustmentDialog.js +3 -1
  617. package/dist/modules/sales/components/documents/AdjustmentDialog.js.map +2 -2
  618. package/dist/modules/sales/components/documents/AdjustmentsSection.js +5 -3
  619. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  620. package/dist/modules/sales/components/documents/ItemsSection.js +6 -4
  621. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  622. package/dist/modules/sales/components/documents/LineItemDialog.js +8 -6
  623. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  624. package/dist/modules/sales/components/documents/PaymentDialog.js +5 -3
  625. package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
  626. package/dist/modules/sales/components/documents/PaymentsSection.js +4 -2
  627. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  628. package/dist/modules/sales/components/documents/SalesDocumentForm.js +14 -12
  629. package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
  630. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +5 -3
  631. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  632. package/dist/modules/sales/components/documents/ShipmentDialog.js +9 -7
  633. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  634. package/dist/modules/sales/components/documents/ShipmentsSection.js +4 -2
  635. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  636. package/dist/modules/sales/frontend/quote/[token]/page.js +4 -2
  637. package/dist/modules/sales/frontend/quote/[token]/page.js.map +2 -2
  638. package/dist/modules/sales/seed/examples.js +7 -9
  639. package/dist/modules/sales/seed/examples.js.map +2 -2
  640. package/dist/modules/sales/subscribers/quote-expiring-notification.js +3 -1
  641. package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +2 -2
  642. package/dist/modules/sales/subscribers/reconcileOnAddressDelete.js +3 -1
  643. package/dist/modules/sales/subscribers/reconcileOnAddressDelete.js.map +2 -2
  644. package/dist/modules/sales/subscribers/reconcileOnCompanyDelete.js +3 -1
  645. package/dist/modules/sales/subscribers/reconcileOnCompanyDelete.js.map +2 -2
  646. package/dist/modules/sales/subscribers/reconcileOnCustomerDelete.js +3 -1
  647. package/dist/modules/sales/subscribers/reconcileOnCustomerDelete.js.map +2 -2
  648. package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js +5 -3
  649. package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js.map +2 -2
  650. package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js +3 -1
  651. package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js.map +2 -2
  652. package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js +3 -1
  653. package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js.map +2 -2
  654. package/dist/modules/shipping_carriers/api/tracking/route.js +5 -0
  655. package/dist/modules/shipping_carriers/api/tracking/route.js.map +2 -2
  656. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +3 -1
  657. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
  658. package/dist/modules/shipping_carriers/lib/shipping-service.js +41 -19
  659. package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
  660. package/dist/modules/shipping_carriers/lib/upstream-error-response.js +3 -1
  661. package/dist/modules/shipping_carriers/lib/upstream-error-response.js.map +2 -2
  662. package/dist/modules/shipping_carriers/workers/webhook-processor.js +3 -5
  663. package/dist/modules/shipping_carriers/workers/webhook-processor.js.map +2 -2
  664. package/dist/modules/staff/api/comments.js +3 -1
  665. package/dist/modules/staff/api/comments.js.map +2 -2
  666. package/dist/modules/staff/api/leave-requests/accept/route.js +3 -1
  667. package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
  668. package/dist/modules/staff/api/leave-requests/reject/route.js +3 -1
  669. package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
  670. package/dist/modules/staff/api/team-members/assignable/route.js +3 -1
  671. package/dist/modules/staff/api/team-members/assignable/route.js.map +2 -2
  672. package/dist/modules/staff/api/team-members/self/route.js +4 -2
  673. package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
  674. package/dist/modules/staff/api/team-members/tags/assign/route.js +3 -1
  675. package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
  676. package/dist/modules/staff/api/team-members/tags/unassign/route.js +3 -1
  677. package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
  678. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +3 -1
  679. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +2 -2
  680. package/dist/modules/staff/api/timesheets/my-projects/route.js +3 -1
  681. package/dist/modules/staff/api/timesheets/my-projects/route.js.map +2 -2
  682. package/dist/modules/staff/api/timesheets/projects/kpis/route.js +3 -1
  683. package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +2 -2
  684. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +3 -1
  685. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +2 -2
  686. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +4 -2
  687. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
  688. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +4 -2
  689. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +2 -2
  690. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +3 -1
  691. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +2 -2
  692. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +3 -1
  693. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +2 -2
  694. package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
  695. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  696. package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
  697. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  698. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +4 -2
  699. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  700. package/dist/modules/staff/backend/staff/teams/page.js +4 -2
  701. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  702. package/dist/modules/staff/backend/staff/timesheets/page.js +7 -5
  703. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  704. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +3 -1
  705. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
  706. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +4 -2
  707. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  708. package/dist/modules/staff/commands/activities.js +23 -12
  709. package/dist/modules/staff/commands/activities.js.map +2 -2
  710. package/dist/modules/staff/commands/addresses.js +20 -12
  711. package/dist/modules/staff/commands/addresses.js.map +2 -2
  712. package/dist/modules/staff/commands/comments.js +18 -11
  713. package/dist/modules/staff/commands/comments.js.map +2 -2
  714. package/dist/modules/staff/commands/job-histories.js +23 -12
  715. package/dist/modules/staff/commands/job-histories.js.map +2 -2
  716. package/dist/modules/staff/commands/leave-requests.js +37 -19
  717. package/dist/modules/staff/commands/leave-requests.js.map +2 -2
  718. package/dist/modules/staff/commands/shared.js +28 -1
  719. package/dist/modules/staff/commands/shared.js.map +2 -2
  720. package/dist/modules/staff/commands/tag-assignments.js +20 -3
  721. package/dist/modules/staff/commands/tag-assignments.js.map +2 -2
  722. package/dist/modules/staff/commands/team-members.js +21 -11
  723. package/dist/modules/staff/commands/team-members.js.map +2 -2
  724. package/dist/modules/staff/commands/team-roles.js +21 -11
  725. package/dist/modules/staff/commands/team-roles.js.map +2 -2
  726. package/dist/modules/staff/commands/teams.js +21 -11
  727. package/dist/modules/staff/commands/teams.js.map +2 -2
  728. package/dist/modules/staff/commands/timesheets-entries.js +27 -15
  729. package/dist/modules/staff/commands/timesheets-entries.js.map +2 -2
  730. package/dist/modules/staff/commands/timesheets-projects.js +34 -18
  731. package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
  732. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js +3 -1
  733. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js.map +2 -2
  734. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +5 -3
  735. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +2 -2
  736. package/dist/modules/sync_excel/api/import/route.js +3 -1
  737. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  738. package/dist/modules/translations/api/[entityType]/[entityId]/route.js +5 -3
  739. package/dist/modules/translations/api/[entityType]/[entityId]/route.js.map +2 -2
  740. package/dist/modules/translations/api/get/locales.js +3 -1
  741. package/dist/modules/translations/api/get/locales.js.map +2 -2
  742. package/dist/modules/translations/api/put/locales.js +3 -1
  743. package/dist/modules/translations/api/put/locales.js.map +2 -2
  744. package/dist/modules/translations/components/TranslationManager.js +3 -1
  745. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  746. package/dist/modules/translations/subscribers/cleanup.js +3 -1
  747. package/dist/modules/translations/subscribers/cleanup.js.map +2 -2
  748. package/dist/modules/workflows/api/definitions/[id]/customize/route.js +4 -2
  749. package/dist/modules/workflows/api/definitions/[id]/customize/route.js.map +2 -2
  750. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js +4 -2
  751. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js.map +2 -2
  752. package/dist/modules/workflows/api/definitions/[id]/route.js +6 -4
  753. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  754. package/dist/modules/workflows/api/definitions/route.js +4 -2
  755. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  756. package/dist/modules/workflows/api/events/[id]/route.js +3 -1
  757. package/dist/modules/workflows/api/events/[id]/route.js.map +2 -2
  758. package/dist/modules/workflows/api/events/route.js +3 -1
  759. package/dist/modules/workflows/api/events/route.js.map +2 -2
  760. package/dist/modules/workflows/api/instances/[id]/advance/route.js +3 -1
  761. package/dist/modules/workflows/api/instances/[id]/advance/route.js.map +2 -2
  762. package/dist/modules/workflows/api/instances/[id]/cancel/route.js +3 -1
  763. package/dist/modules/workflows/api/instances/[id]/cancel/route.js.map +2 -2
  764. package/dist/modules/workflows/api/instances/[id]/events/route.js +3 -1
  765. package/dist/modules/workflows/api/instances/[id]/events/route.js.map +2 -2
  766. package/dist/modules/workflows/api/instances/[id]/retry/route.js +3 -1
  767. package/dist/modules/workflows/api/instances/[id]/retry/route.js.map +2 -2
  768. package/dist/modules/workflows/api/instances/[id]/route.js +3 -1
  769. package/dist/modules/workflows/api/instances/[id]/route.js.map +2 -2
  770. package/dist/modules/workflows/api/instances/[id]/signal/route.js +5 -7
  771. package/dist/modules/workflows/api/instances/[id]/signal/route.js.map +2 -2
  772. package/dist/modules/workflows/api/instances/route.js +6 -4
  773. package/dist/modules/workflows/api/instances/route.js.map +2 -2
  774. package/dist/modules/workflows/api/instances/validate-start/route.js +3 -1
  775. package/dist/modules/workflows/api/instances/validate-start/route.js.map +2 -2
  776. package/dist/modules/workflows/api/signals/route.js +3 -1
  777. package/dist/modules/workflows/api/signals/route.js.map +2 -2
  778. package/dist/modules/workflows/api/tasks/[id]/claim/route.js +3 -1
  779. package/dist/modules/workflows/api/tasks/[id]/claim/route.js.map +2 -2
  780. package/dist/modules/workflows/api/tasks/[id]/complete/route.js +3 -1
  781. package/dist/modules/workflows/api/tasks/[id]/complete/route.js.map +2 -2
  782. package/dist/modules/workflows/api/tasks/[id]/route.js +3 -1
  783. package/dist/modules/workflows/api/tasks/[id]/route.js.map +2 -2
  784. package/dist/modules/workflows/api/tasks/route.js +3 -1
  785. package/dist/modules/workflows/api/tasks/route.js.map +2 -2
  786. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +4 -2
  787. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  788. package/dist/modules/workflows/backend/instances/[id]/page.js +5 -3
  789. package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
  790. package/dist/modules/workflows/backend/tasks/[id]/page.js +3 -1
  791. package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
  792. package/dist/modules/workflows/components/BusinessRulesSelector.js +5 -3
  793. package/dist/modules/workflows/components/BusinessRulesSelector.js.map +2 -2
  794. package/dist/modules/workflows/components/WorkflowSelector.js +5 -3
  795. package/dist/modules/workflows/components/WorkflowSelector.js.map +2 -2
  796. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +3 -1
  797. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
  798. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +3 -1
  799. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
  800. package/dist/modules/workflows/components/fields/WorkflowSelectorField.js +3 -1
  801. package/dist/modules/workflows/components/fields/WorkflowSelectorField.js.map +2 -2
  802. package/dist/modules/workflows/frontend/checkout-demo/page.js +8 -7
  803. package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
  804. package/dist/modules/workflows/lib/activity-executor.js +25 -21
  805. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  806. package/dist/modules/workflows/lib/activity-worker-handler.js +8 -15
  807. package/dist/modules/workflows/lib/activity-worker-handler.js.map +2 -2
  808. package/dist/modules/workflows/lib/code-registry.js +7 -7
  809. package/dist/modules/workflows/lib/code-registry.js.map +2 -2
  810. package/dist/modules/workflows/lib/compensation-handler.js +4 -2
  811. package/dist/modules/workflows/lib/compensation-handler.js.map +2 -2
  812. package/dist/modules/workflows/lib/edgeFormTransforms.js +3 -1
  813. package/dist/modules/workflows/lib/edgeFormTransforms.js.map +2 -2
  814. package/dist/modules/workflows/lib/event-trigger-service.js +5 -3
  815. package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
  816. package/dist/modules/workflows/lib/nodeFormTransforms.js +3 -1
  817. package/dist/modules/workflows/lib/nodeFormTransforms.js.map +2 -2
  818. package/dist/modules/workflows/lib/seeds.js +16 -2
  819. package/dist/modules/workflows/lib/seeds.js.map +2 -2
  820. package/dist/modules/workflows/lib/signal-handler.js +3 -1
  821. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  822. package/dist/modules/workflows/lib/start-validator.js +9 -3
  823. package/dist/modules/workflows/lib/start-validator.js.map +2 -2
  824. package/dist/modules/workflows/lib/step-handler.js +3 -1
  825. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  826. package/dist/modules/workflows/lib/task-handler.js +3 -1
  827. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  828. package/dist/modules/workflows/lib/transition-handler.js +5 -3
  829. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  830. package/dist/modules/workflows/lib/workflow-executor.js +27 -15
  831. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  832. package/dist/modules/workflows/subscribers/event-trigger.js +21 -18
  833. package/dist/modules/workflows/subscribers/event-trigger.js.map +2 -2
  834. package/dist/modules/workflows/subscribers/task-assigned-notification.js +3 -1
  835. package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +2 -2
  836. package/dist/modules/workflows/workers/workflow-activities.worker.js +30 -20
  837. package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
  838. package/package.json +7 -7
  839. package/src/bootstrap.ts +14 -11
  840. package/src/helpers/integration/auth.ts +178 -86
  841. package/src/helpers/integration/queue-runner.ts +2 -2
  842. package/src/modules/api_keys/services/apiKeyService.ts +6 -3
  843. package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +5 -2
  844. package/src/modules/attachments/api/library/[id]/route.ts +4 -1
  845. package/src/modules/attachments/api/route.ts +9 -6
  846. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +6 -3
  847. package/src/modules/attachments/lib/assignmentDetails.ts +4 -1
  848. package/src/modules/attachments/lib/drivers/driverFactory.ts +4 -1
  849. package/src/modules/attachments/lib/ocrQueue.ts +11 -11
  850. package/src/modules/attachments/lib/ocrService.ts +7 -4
  851. package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +4 -1
  852. package/src/modules/audit_logs/api/audit-logs/actions/undo/route.ts +4 -1
  853. package/src/modules/audit_logs/backend/audit-logs/page.tsx +4 -1
  854. package/src/modules/audit_logs/components/AuditLogsActions.tsx +5 -2
  855. package/src/modules/audit_logs/services/accessLogService.ts +5 -4
  856. package/src/modules/audit_logs/services/actionLogService.ts +5 -2
  857. package/src/modules/auth/api/profile/route.ts +5 -2
  858. package/src/modules/auth/api/reset/confirm.ts +4 -1
  859. package/src/modules/auth/api/reset.ts +5 -2
  860. package/src/modules/auth/api/roles/route.ts +4 -1
  861. package/src/modules/auth/api/sidebar/variants/route.ts +4 -2
  862. package/src/modules/auth/api/users/resend-invite/route.ts +5 -2
  863. package/src/modules/auth/api/users/route.ts +4 -1
  864. package/src/modules/auth/backend/auth/profile/page.tsx +4 -1
  865. package/src/modules/auth/backend/profile/change-password/page.tsx +4 -1
  866. package/src/modules/auth/backend/users/[id]/edit/page.tsx +6 -3
  867. package/src/modules/auth/backend/users/create/page.tsx +5 -2
  868. package/src/modules/auth/cli.ts +10 -0
  869. package/src/modules/auth/commands/users.ts +5 -2
  870. package/src/modules/auth/lib/consentIntegrity.ts +4 -4
  871. package/src/modules/auth/lib/setup-app.ts +10 -10
  872. package/src/modules/auth/lib/tenantAccess.ts +4 -1
  873. package/src/modules/auth/lib/tokenHash.ts +4 -4
  874. package/src/modules/business_rules/api/rules/route.ts +5 -2
  875. package/src/modules/business_rules/lib/expression-evaluator.ts +8 -6
  876. package/src/modules/business_rules/lib/rule-engine.ts +6 -3
  877. package/src/modules/business_rules/lib/rule-evaluator.ts +11 -11
  878. package/src/modules/business_rules/subscribers/crud-rule-trigger.ts +4 -1
  879. package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +4 -1
  880. package/src/modules/catalog/ai-agents-context.ts +5 -5
  881. package/src/modules/catalog/ai-tools/_shared.ts +4 -1
  882. package/src/modules/catalog/ai-tools/authoring-pack.ts +4 -1
  883. package/src/modules/catalog/ai-tools/merchandising-pack.ts +4 -1
  884. package/src/modules/catalog/api/dictionaries/[key]/route.ts +4 -1
  885. package/src/modules/catalog/api/prices/route.ts +4 -1
  886. package/src/modules/catalog/api/products/route.ts +6 -3
  887. package/src/modules/catalog/api/settings/route.ts +5 -2
  888. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +15 -12
  889. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +9 -6
  890. package/src/modules/catalog/backend/catalog/products/[productId]/variants/create/page.tsx +6 -3
  891. package/src/modules/catalog/backend/catalog/products/create/page.tsx +6 -6
  892. package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +4 -1
  893. package/src/modules/catalog/components/PriceKindSettings.tsx +6 -3
  894. package/src/modules/catalog/components/UnitPriceDisplaySettings.tsx +5 -2
  895. package/src/modules/catalog/inbox-actions.ts +5 -2
  896. package/src/modules/catalog/seed/examples.ts +5 -5
  897. package/src/modules/catalog/subscribers/low-stock-notification.ts +4 -1
  898. package/src/modules/catalog/widgets/injection/product-seo/state.ts +4 -1
  899. package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +13 -13
  900. package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +4 -1
  901. package/src/modules/communication_channels/api/post/channels/[id]/push/register/route.ts +4 -1
  902. package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +6 -3
  903. package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +7 -6
  904. package/src/modules/communication_channels/commands/connect-credential-channel.ts +5 -10
  905. package/src/modules/communication_channels/commands/delete-channel.ts +4 -5
  906. package/src/modules/communication_channels/commands/deliver-outbound-message.ts +5 -5
  907. package/src/modules/communication_channels/commands/disconnect-channel.ts +4 -5
  908. package/src/modules/communication_channels/commands/ingest-inbound-message.ts +6 -12
  909. package/src/modules/communication_channels/commands/push-unregister.ts +4 -3
  910. package/src/modules/communication_channels/commands/reassign-conversation.ts +6 -3
  911. package/src/modules/communication_channels/lib/dead-letter.ts +4 -5
  912. package/src/modules/communication_channels/lib/email-mime.ts +5 -6
  913. package/src/modules/communication_channels/lib/oauth-client-config.ts +7 -3
  914. package/src/modules/communication_channels/lib/send-as-user.ts +4 -1
  915. package/src/modules/communication_channels/lib/thread-token.ts +5 -2
  916. package/src/modules/communication_channels/setup.ts +4 -4
  917. package/src/modules/communication_channels/workers/channel-import-history.ts +5 -8
  918. package/src/modules/communication_channels/workers/gmail-history-sync.ts +9 -18
  919. package/src/modules/communication_channels/workers/gmail-renew-watch.ts +6 -9
  920. package/src/modules/communication_channels/workers/outbound-delivery.ts +7 -12
  921. package/src/modules/communication_channels/workers/poll-channel.ts +8 -15
  922. package/src/modules/communication_channels/workers/poll-tick.ts +6 -6
  923. package/src/modules/communication_channels/workers/reaction-processor.ts +6 -9
  924. package/src/modules/configs/api/cache/route.ts +5 -2
  925. package/src/modules/configs/api/system-status/route.ts +5 -2
  926. package/src/modules/configs/api/upgrade-actions/route.ts +5 -2
  927. package/src/modules/configs/components/ModuleTelemetryPanel.tsx +4 -1
  928. package/src/modules/configs/lib/touchGeneratedBarrels.ts +1 -1
  929. package/src/modules/configs/services/upgradeActionsService.ts +7 -3
  930. package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +4 -1
  931. package/src/modules/currencies/lib/exchangeRateFormConfig.ts +4 -1
  932. package/src/modules/currencies/services/providers/nbp.ts +7 -4
  933. package/src/modules/currencies/services/providers/raiffeisen.ts +8 -7
  934. package/src/modules/customer_accounts/api/domain-resolve/all.ts +7 -5
  935. package/src/modules/customer_accounts/api/signup.ts +5 -2
  936. package/src/modules/customer_accounts/lib/customerAuthServer.ts +4 -1
  937. package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +4 -1
  938. package/src/modules/customer_accounts/subscribers/autoLinkCrmReverse.ts +4 -1
  939. package/src/modules/customer_accounts/subscribers/unlinkOnCompanyDelete.ts +4 -1
  940. package/src/modules/customer_accounts/subscribers/unlinkOnPersonDelete.ts +4 -1
  941. package/src/modules/customers/ai-agents-context.ts +5 -5
  942. package/src/modules/customers/api/activities/route.ts +7 -4
  943. package/src/modules/customers/api/comments/route.ts +4 -1
  944. package/src/modules/customers/api/companies/[id]/people/route.ts +4 -1
  945. package/src/modules/customers/api/companies/[id]/route.ts +6 -3
  946. package/src/modules/customers/api/companies/route.ts +6 -3
  947. package/src/modules/customers/api/dashboard/widgets/customer-todos/route.ts +4 -1
  948. package/src/modules/customers/api/dashboard/widgets/new-customers/route.ts +4 -1
  949. package/src/modules/customers/api/dashboard/widgets/new-deals/route.ts +4 -1
  950. package/src/modules/customers/api/dashboard/widgets/next-interactions/route.ts +4 -1
  951. package/src/modules/customers/api/deals/[id]/companies/route.ts +4 -1
  952. package/src/modules/customers/api/deals/[id]/people/route.ts +4 -1
  953. package/src/modules/customers/api/deals/aggregate/route.ts +4 -1
  954. package/src/modules/customers/api/deals/bulk-update-owner/route.ts +8 -5
  955. package/src/modules/customers/api/deals/bulk-update-stage/route.ts +8 -5
  956. package/src/modules/customers/api/deals/route.ts +4 -1
  957. package/src/modules/customers/api/deals/summary/route.ts +4 -1
  958. package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +5 -2
  959. package/src/modules/customers/api/dictionaries/[kind]/route.ts +6 -3
  960. package/src/modules/customers/api/dictionaries/cache.ts +4 -1
  961. package/src/modules/customers/api/dictionaries/context.ts +4 -1
  962. package/src/modules/customers/api/dictionaries/currency/route.ts +4 -1
  963. package/src/modules/customers/api/dictionaries/kind-settings/route.ts +5 -2
  964. package/src/modules/customers/api/entity-roles-factory.ts +8 -5
  965. package/src/modules/customers/api/interactions/cancel/route.ts +4 -1
  966. package/src/modules/customers/api/interactions/complete/route.ts +4 -1
  967. package/src/modules/customers/api/interactions/conflicts/route.ts +4 -1
  968. package/src/modules/customers/api/interactions/counts/route.ts +4 -1
  969. package/src/modules/customers/api/interactions/route.ts +8 -4
  970. package/src/modules/customers/api/interactions/tasks/route.ts +4 -1
  971. package/src/modules/customers/api/labels/assign/route.ts +4 -1
  972. package/src/modules/customers/api/labels/route.ts +7 -3
  973. package/src/modules/customers/api/labels/unassign/route.ts +4 -1
  974. package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +4 -1
  975. package/src/modules/customers/api/people/[id]/route.ts +6 -3
  976. package/src/modules/customers/api/people/route.ts +6 -3
  977. package/src/modules/customers/api/pipeline-stages/reorder/route.ts +4 -1
  978. package/src/modules/customers/api/pipeline-stages/route.ts +7 -4
  979. package/src/modules/customers/api/pipelines/route.ts +7 -4
  980. package/src/modules/customers/api/settings/address-format/route.ts +5 -2
  981. package/src/modules/customers/api/settings/dictionary-sort-modes/route.ts +5 -2
  982. package/src/modules/customers/api/settings/stuck-threshold/route.ts +5 -2
  983. package/src/modules/customers/api/tags/assign/route.ts +4 -1
  984. package/src/modules/customers/api/tags/unassign/route.ts +4 -1
  985. package/src/modules/customers/api/todos/route.ts +7 -4
  986. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +6 -3
  987. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +4 -1
  988. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.ts +4 -1
  989. package/src/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.tsx +5 -3
  990. package/src/modules/customers/backend/customers/deals/page.tsx +5 -2
  991. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +6 -3
  992. package/src/modules/customers/commands/deals.ts +4 -1
  993. package/src/modules/customers/commands/dictionaries.ts +4 -1
  994. package/src/modules/customers/commands/interactions.ts +5 -2
  995. package/src/modules/customers/commands/shared.ts +5 -2
  996. package/src/modules/customers/commands/todos.ts +4 -1
  997. package/src/modules/customers/components/DictionarySettings.tsx +6 -3
  998. package/src/modules/customers/components/DictionarySortSettings.tsx +4 -1
  999. package/src/modules/customers/components/detail/ActivitiesCard.tsx +4 -1
  1000. package/src/modules/customers/components/detail/ActivitiesDayStrip.tsx +4 -1
  1001. package/src/modules/customers/components/detail/ActivitiesSection.tsx +7 -4
  1002. package/src/modules/customers/components/detail/ActivityCard.tsx +4 -1
  1003. package/src/modules/customers/components/detail/ChangelogTab.tsx +4 -1
  1004. package/src/modules/customers/components/detail/CompanyCard.tsx +4 -1
  1005. package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +4 -1
  1006. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +4 -1
  1007. package/src/modules/customers/components/detail/InlineActivityComposer.tsx +4 -1
  1008. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -1
  1009. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +6 -3
  1010. package/src/modules/customers/components/detail/RolesSection.tsx +5 -2
  1011. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +6 -3
  1012. package/src/modules/customers/components/linking/LinkEntityDialog.tsx +5 -2
  1013. package/src/modules/customers/inbox-actions.ts +4 -1
  1014. package/src/modules/customers/lib/bulkDeals.ts +4 -1
  1015. package/src/modules/customers/lib/dealClosureNotification.ts +5 -2
  1016. package/src/modules/customers/lib/dealStageTransitionTable.ts +4 -1
  1017. package/src/modules/customers/lib/interactionFeatureFlags.ts +5 -1
  1018. package/src/modules/customers/lib/todoCompatibility.ts +4 -1
  1019. package/src/modules/customers/search.ts +15 -7
  1020. package/src/modules/customers/widgets/dashboard/customer-todos/widget.client.tsx +4 -1
  1021. package/src/modules/customers/widgets/dashboard/new-customers/widget.client.tsx +4 -1
  1022. package/src/modules/customers/widgets/dashboard/new-deals/widget.client.tsx +4 -1
  1023. package/src/modules/customers/widgets/dashboard/next-interactions/widget.client.tsx +4 -1
  1024. package/src/modules/dashboards/api/widgets/data/batch/route.ts +4 -1
  1025. package/src/modules/dashboards/api/widgets/data/route.ts +4 -1
  1026. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +6 -3
  1027. package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.tsx +4 -1
  1028. package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.tsx +4 -1
  1029. package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.tsx +4 -1
  1030. package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.tsx +4 -1
  1031. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +4 -1
  1032. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.tsx +4 -1
  1033. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +4 -1
  1034. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +4 -1
  1035. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +4 -1
  1036. package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +4 -1
  1037. package/src/modules/data_sync/api/run.ts +4 -1
  1038. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +3 -1
  1039. package/src/modules/data_sync/lib/adapter-registry.ts +16 -4
  1040. package/src/modules/data_sync/lib/sync-engine.ts +31 -2
  1041. package/src/modules/data_sync/workers/sync-export.ts +4 -1
  1042. package/src/modules/data_sync/workers/sync-import.ts +4 -1
  1043. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +5 -2
  1044. package/src/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.ts +4 -1
  1045. package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +5 -2
  1046. package/src/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.ts +4 -1
  1047. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +6 -3
  1048. package/src/modules/dictionaries/api/context.ts +4 -1
  1049. package/src/modules/dictionaries/api/route.ts +5 -2
  1050. package/src/modules/dictionaries/components/DictionariesManager.tsx +6 -3
  1051. package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +5 -2
  1052. package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +5 -2
  1053. package/src/modules/dictionaries/components/DictionarySelectControl.tsx +4 -1
  1054. package/src/modules/dictionaries/fields/dictionary.tsx +4 -1
  1055. package/src/modules/directory/api/organization-branding/route.ts +4 -1
  1056. package/src/modules/directory/api/organization-switcher/route.ts +4 -1
  1057. package/src/modules/directory/commands/tenants.ts +6 -3
  1058. package/src/modules/directory/utils/organizationScope.ts +7 -4
  1059. package/src/modules/entities/api/definitions.cache.ts +4 -1
  1060. package/src/modules/entities/api/definitions.ts +8 -5
  1061. package/src/modules/entities/api/records.ts +5 -2
  1062. package/src/modules/entities/components/EncryptionManager.tsx +4 -1
  1063. package/src/modules/entities/lib/makeActivityRoute.ts +4 -1
  1064. package/src/modules/feature_toggles/api/overrides/route.ts +4 -1
  1065. package/src/modules/feature_toggles/lib/feature-flag-check.ts +6 -9
  1066. package/src/modules/inbox_ops/api/emails/[id]/reprocess/route.ts +5 -2
  1067. package/src/modules/inbox_ops/api/emails/[id]/route.ts +5 -2
  1068. package/src/modules/inbox_ops/api/emails/route.ts +4 -1
  1069. package/src/modules/inbox_ops/api/extract/route.ts +4 -1
  1070. package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.ts +4 -1
  1071. package/src/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/route.ts +5 -2
  1072. package/src/modules/inbox_ops/api/proposals/counts/route.ts +5 -2
  1073. package/src/modules/inbox_ops/api/proposals/route.ts +4 -1
  1074. package/src/modules/inbox_ops/api/routeHelpers.ts +4 -1
  1075. package/src/modules/inbox_ops/api/settings/route.ts +4 -1
  1076. package/src/modules/inbox_ops/api/webhook/inbound.ts +8 -5
  1077. package/src/modules/inbox_ops/lib/cache.ts +5 -2
  1078. package/src/modules/inbox_ops/lib/catalogLookup.ts +4 -1
  1079. package/src/modules/inbox_ops/lib/eventBus.ts +4 -4
  1080. package/src/modules/inbox_ops/lib/messagesIntegration.ts +5 -8
  1081. package/src/modules/inbox_ops/subscribers/executionAuditor.ts +5 -1
  1082. package/src/modules/inbox_ops/subscribers/extractionWorker.ts +11 -8
  1083. package/src/modules/inbox_ops/subscribers/proposalNotifier.ts +4 -1
  1084. package/src/modules/messages/api/[id]/route.ts +4 -4
  1085. package/src/modules/messages/commands/actions.ts +4 -1
  1086. package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -1
  1087. package/src/modules/messages/lib/email-sender.ts +4 -7
  1088. package/src/modules/messages/lib/message-objects-registry.ts +4 -1
  1089. package/src/modules/messages/lib/message-types-registry.ts +4 -1
  1090. package/src/modules/messages/workers/send-email.worker.ts +7 -4
  1091. package/src/modules/notifications/lib/notificationMapper.ts +4 -4
  1092. package/src/modules/notifications/lib/notificationService.ts +4 -5
  1093. package/src/modules/notifications/subscribers/deliver-notification.ts +9 -14
  1094. package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +4 -1
  1095. package/src/modules/perspectives/services/perspectiveService.ts +4 -3
  1096. package/src/modules/planner/api/access.ts +4 -3
  1097. package/src/modules/planner/api/availability-date-specific.ts +4 -1
  1098. package/src/modules/planner/api/availability-weekly.ts +4 -1
  1099. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +5 -2
  1100. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +4 -1
  1101. package/src/modules/progress/api/jobs/route.ts +4 -1
  1102. package/src/modules/query_index/components/QueryIndexesTable.tsx +6 -3
  1103. package/src/modules/query_index/lib/batch.ts +5 -2
  1104. package/src/modules/query_index/lib/coverage.ts +4 -1
  1105. package/src/modules/query_index/lib/engine.ts +14 -17
  1106. package/src/modules/query_index/lib/reindexer.ts +9 -6
  1107. package/src/modules/query_index/lib/search-tokens.ts +4 -2
  1108. package/src/modules/query_index/subscribers/coverage_refresh.ts +4 -1
  1109. package/src/modules/resources/api/comments.ts +4 -1
  1110. package/src/modules/resources/api/resources/tags/assign/route.ts +4 -1
  1111. package/src/modules/resources/api/resources/tags/unassign/route.ts +4 -1
  1112. package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +4 -1
  1113. package/src/modules/resources/backend/resources/resource-types/page.tsx +5 -2
  1114. package/src/modules/resources/commands/activities.ts +5 -4
  1115. package/src/modules/resources/commands/comments.ts +6 -4
  1116. package/src/modules/resources/commands/shared.ts +36 -0
  1117. package/src/modules/sales/api/channels/route.ts +4 -1
  1118. package/src/modules/sales/api/document-addresses/route.ts +140 -7
  1119. package/src/modules/sales/api/document-history/route.ts +4 -1
  1120. package/src/modules/sales/api/document-numbers/route.ts +4 -1
  1121. package/src/modules/sales/api/quotes/accept/route.ts +5 -2
  1122. package/src/modules/sales/api/quotes/convert/route.ts +4 -1
  1123. package/src/modules/sales/api/quotes/public/[token]/route.ts +4 -1
  1124. package/src/modules/sales/api/quotes/send/route.ts +4 -1
  1125. package/src/modules/sales/api/returns/[id]/route.ts +4 -1
  1126. package/src/modules/sales/api/settings/document-numbers/route.ts +5 -2
  1127. package/src/modules/sales/api/settings/order-editing/route.ts +5 -2
  1128. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +4 -1
  1129. package/src/modules/sales/backend/sales/channels/offers/page.tsx +7 -4
  1130. package/src/modules/sales/backend/sales/channels/page.tsx +5 -2
  1131. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +21 -18
  1132. package/src/modules/sales/commands/documentAddresses.ts +8 -0
  1133. package/src/modules/sales/commands/documents.ts +5 -8
  1134. package/src/modules/sales/commands/payments.ts +4 -1
  1135. package/src/modules/sales/commands/shipments.ts +4 -2
  1136. package/src/modules/sales/components/AdjustmentKindSettings.tsx +6 -3
  1137. package/src/modules/sales/components/DocumentNumberSettings.tsx +5 -2
  1138. package/src/modules/sales/components/OrderEditingSettings.tsx +5 -2
  1139. package/src/modules/sales/components/PaymentMethodsSettings.tsx +6 -3
  1140. package/src/modules/sales/components/ShippingMethodsSettings.tsx +6 -3
  1141. package/src/modules/sales/components/StatusSettings.tsx +6 -3
  1142. package/src/modules/sales/components/TaxRatesSettings.tsx +6 -3
  1143. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +17 -14
  1144. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +5 -2
  1145. package/src/modules/sales/components/documents/AddressesSection.tsx +6 -3
  1146. package/src/modules/sales/components/documents/AdjustmentDialog.tsx +4 -1
  1147. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +6 -3
  1148. package/src/modules/sales/components/documents/ItemsSection.tsx +7 -4
  1149. package/src/modules/sales/components/documents/LineItemDialog.tsx +9 -6
  1150. package/src/modules/sales/components/documents/PaymentDialog.tsx +6 -3
  1151. package/src/modules/sales/components/documents/PaymentsSection.tsx +5 -2
  1152. package/src/modules/sales/components/documents/SalesDocumentForm.tsx +15 -12
  1153. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +6 -3
  1154. package/src/modules/sales/components/documents/ShipmentDialog.tsx +10 -7
  1155. package/src/modules/sales/components/documents/ShipmentsSection.tsx +5 -2
  1156. package/src/modules/sales/frontend/quote/[token]/page.tsx +5 -2
  1157. package/src/modules/sales/seed/examples.ts +8 -9
  1158. package/src/modules/sales/subscribers/quote-expiring-notification.ts +4 -1
  1159. package/src/modules/sales/subscribers/reconcileOnAddressDelete.ts +4 -1
  1160. package/src/modules/sales/subscribers/reconcileOnCompanyDelete.ts +4 -1
  1161. package/src/modules/sales/subscribers/reconcileOnCustomerDelete.ts +4 -1
  1162. package/src/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.ts +6 -3
  1163. package/src/modules/sales/widgets/dashboard/new-orders/widget.client.tsx +274 -271
  1164. package/src/modules/sales/widgets/dashboard/new-quotes/widget.client.tsx +280 -277
  1165. package/src/modules/shipping_carriers/api/tracking/route.ts +5 -1
  1166. package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +4 -1
  1167. package/src/modules/shipping_carriers/lib/shipping-service.ts +47 -22
  1168. package/src/modules/shipping_carriers/lib/upstream-error-response.ts +4 -1
  1169. package/src/modules/shipping_carriers/workers/webhook-processor.ts +4 -5
  1170. package/src/modules/staff/api/comments.ts +4 -1
  1171. package/src/modules/staff/api/leave-requests/accept/route.ts +4 -1
  1172. package/src/modules/staff/api/leave-requests/reject/route.ts +4 -1
  1173. package/src/modules/staff/api/team-members/assignable/route.ts +4 -1
  1174. package/src/modules/staff/api/team-members/self/route.ts +5 -2
  1175. package/src/modules/staff/api/team-members/tags/assign/route.ts +4 -1
  1176. package/src/modules/staff/api/team-members/tags/unassign/route.ts +4 -1
  1177. package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +4 -1
  1178. package/src/modules/staff/api/timesheets/my-projects/route.ts +4 -1
  1179. package/src/modules/staff/api/timesheets/projects/kpis/route.ts +4 -1
  1180. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +4 -1
  1181. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +5 -2
  1182. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +5 -2
  1183. package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +4 -1
  1184. package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +4 -1
  1185. package/src/modules/staff/backend/staff/team-members/page.tsx +5 -2
  1186. package/src/modules/staff/backend/staff/team-roles/page.tsx +5 -2
  1187. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +5 -2
  1188. package/src/modules/staff/backend/staff/teams/page.tsx +5 -2
  1189. package/src/modules/staff/backend/staff/timesheets/page.tsx +8 -5
  1190. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -1
  1191. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +5 -2
  1192. package/src/modules/staff/commands/activities.ts +23 -11
  1193. package/src/modules/staff/commands/addresses.ts +20 -11
  1194. package/src/modules/staff/commands/comments.ts +18 -10
  1195. package/src/modules/staff/commands/job-histories.ts +27 -11
  1196. package/src/modules/staff/commands/leave-requests.ts +38 -19
  1197. package/src/modules/staff/commands/shared.ts +38 -0
  1198. package/src/modules/staff/commands/tag-assignments.ts +19 -2
  1199. package/src/modules/staff/commands/team-members.ts +21 -10
  1200. package/src/modules/staff/commands/team-roles.ts +21 -10
  1201. package/src/modules/staff/commands/teams.ts +21 -10
  1202. package/src/modules/staff/commands/timesheets-entries.ts +28 -14
  1203. package/src/modules/staff/commands/timesheets-projects.ts +34 -17
  1204. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx +4 -1
  1205. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +6 -3
  1206. package/src/modules/sync_excel/api/import/route.ts +4 -1
  1207. package/src/modules/translations/api/[entityType]/[entityId]/route.ts +6 -3
  1208. package/src/modules/translations/api/get/locales.ts +4 -1
  1209. package/src/modules/translations/api/put/locales.ts +4 -1
  1210. package/src/modules/translations/components/TranslationManager.tsx +4 -1
  1211. package/src/modules/translations/subscribers/cleanup.ts +4 -1
  1212. package/src/modules/workflows/api/definitions/[id]/customize/route.ts +5 -2
  1213. package/src/modules/workflows/api/definitions/[id]/reset-to-code/route.ts +5 -2
  1214. package/src/modules/workflows/api/definitions/[id]/route.ts +7 -4
  1215. package/src/modules/workflows/api/definitions/route.ts +5 -2
  1216. package/src/modules/workflows/api/events/[id]/route.ts +4 -1
  1217. package/src/modules/workflows/api/events/route.ts +4 -1
  1218. package/src/modules/workflows/api/instances/[id]/advance/route.ts +4 -1
  1219. package/src/modules/workflows/api/instances/[id]/cancel/route.ts +4 -1
  1220. package/src/modules/workflows/api/instances/[id]/events/route.ts +4 -1
  1221. package/src/modules/workflows/api/instances/[id]/retry/route.ts +4 -1
  1222. package/src/modules/workflows/api/instances/[id]/route.ts +4 -1
  1223. package/src/modules/workflows/api/instances/[id]/signal/route.ts +6 -7
  1224. package/src/modules/workflows/api/instances/route.ts +8 -5
  1225. package/src/modules/workflows/api/instances/validate-start/route.ts +4 -1
  1226. package/src/modules/workflows/api/signals/route.ts +4 -1
  1227. package/src/modules/workflows/api/tasks/[id]/claim/route.ts +4 -1
  1228. package/src/modules/workflows/api/tasks/[id]/complete/route.ts +4 -1
  1229. package/src/modules/workflows/api/tasks/[id]/route.ts +4 -1
  1230. package/src/modules/workflows/api/tasks/route.ts +4 -1
  1231. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +5 -2
  1232. package/src/modules/workflows/backend/instances/[id]/page.tsx +6 -3
  1233. package/src/modules/workflows/backend/tasks/[id]/page.tsx +4 -1
  1234. package/src/modules/workflows/components/BusinessRulesSelector.tsx +6 -3
  1235. package/src/modules/workflows/components/WorkflowSelector.tsx +6 -3
  1236. package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +4 -1
  1237. package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +4 -1
  1238. package/src/modules/workflows/components/fields/WorkflowSelectorField.tsx +4 -1
  1239. package/src/modules/workflows/frontend/checkout-demo/page.tsx +9 -7
  1240. package/src/modules/workflows/lib/activity-executor.ts +26 -21
  1241. package/src/modules/workflows/lib/activity-worker-handler.ts +9 -15
  1242. package/src/modules/workflows/lib/code-registry.ts +8 -7
  1243. package/src/modules/workflows/lib/compensation-handler.ts +5 -2
  1244. package/src/modules/workflows/lib/edgeFormTransforms.ts +4 -1
  1245. package/src/modules/workflows/lib/event-trigger-service.ts +6 -3
  1246. package/src/modules/workflows/lib/nodeFormTransforms.ts +4 -1
  1247. package/src/modules/workflows/lib/seeds.ts +17 -2
  1248. package/src/modules/workflows/lib/signal-handler.ts +4 -1
  1249. package/src/modules/workflows/lib/start-validator.ts +10 -3
  1250. package/src/modules/workflows/lib/step-handler.ts +4 -1
  1251. package/src/modules/workflows/lib/task-handler.ts +4 -1
  1252. package/src/modules/workflows/lib/transition-handler.ts +6 -3
  1253. package/src/modules/workflows/lib/workflow-executor.ts +28 -15
  1254. package/src/modules/workflows/subscribers/event-trigger.ts +22 -24
  1255. package/src/modules/workflows/subscribers/task-assigned-notification.ts +4 -1
  1256. package/src/modules/workflows/workers/workflow-activities.worker.ts +31 -20
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/currencies/components/CurrencyFetchingConfig.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader, extractOptimisticLockConflict } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { StatusBadge, type StatusBadgeVariant } from '@open-mercato/ui/primitives/status-badge'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { TimeInput } from '@open-mercato/ui/backend/inputs/TimeInput'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ninterface FetchConfig {\n id: string\n provider: string\n isEnabled: boolean\n syncTime: string | null\n lastSyncAt: string | null\n lastSyncStatus: string | null\n lastSyncMessage: string | null\n lastSyncCount: number | null\n updatedAt?: string | null\n}\n\nconst STATUS_BADGE_VARIANT: Record<string, StatusBadgeVariant> = {\n success: 'success',\n error: 'error',\n partial: 'warning',\n}\n\nexport default function CurrencyFetchingConfig() {\n const t = useT()\n const [configs, setConfigs] = useState<FetchConfig[]>([])\n const [loading, setLoading] = useState(true)\n const [fetching, setFetching] = useState<string | null>(null)\n const [initializing, setInitializing] = useState(false)\n\n // Available providers that should be configured\n const availableProviders = useMemo(() => ['NBP', 'Raiffeisen Bank Polska'], [])\n\n const mutationContextId = 'currencies-fetch-configs:mutation'\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId?: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const createProviderConfig = useCallback(async (provider: string) => {\n try {\n await runMutation({\n operation: () => apiCall('/api/currencies/fetch-configs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n provider,\n isEnabled: false,\n syncTime: '09:00',\n }),\n }),\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n retryLastMutation,\n },\n mutationPayload: { provider, isEnabled: false, syncTime: '09:00' },\n })\n } catch (err: any) {\n // Ignore errors for duplicate providers\n if (!err.message?.includes('already configured')) {\n throw err\n }\n }\n }, [mutationContextId, retryLastMutation, runMutation])\n\n const initializeMissingProviders = useCallback(async (providers: string[]) => {\n setInitializing(true)\n try {\n for (const provider of providers) {\n await createProviderConfig(provider)\n }\n // Reload configs after initialization\n const { result } = await apiCall('/api/currencies/fetch-configs')\n if (result?.configs) {\n setConfigs(result.configs as FetchConfig[])\n }\n } catch (err: any) {\n console.error('Failed to initialize providers:', err)\n } finally {\n setInitializing(false)\n }\n }, [createProviderConfig])\n\n const loadConfigs = useCallback(async () => {\n try {\n const { result } = await apiCall('/api/currencies/fetch-configs')\n\n if (result?.configs) {\n const existingConfigs = result.configs as FetchConfig[]\n setConfigs(existingConfigs)\n\n // Check if we need to initialize any missing providers\n const existingProviders = existingConfigs.map((c) => c.provider)\n const missingProviders = availableProviders.filter(\n (p) => !existingProviders.includes(p)\n )\n\n // Auto-initialize missing providers\n if (missingProviders.length > 0) {\n await initializeMissingProviders(missingProviders)\n }\n }\n } catch (err: any) {\n flash(err.message || t('currencies.fetch.error_load_configs'), 'error')\n } finally {\n setLoading(false)\n }\n }, [availableProviders, initializeMissingProviders, t])\n\n const toggleEnabled = useCallback(async (configId: string, currentValue: boolean, updatedAt?: string | null) => {\n try {\n const call = await runMutation({\n operation: async () => {\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt),\n () =>\n apiCall('/api/currencies/fetch-configs', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: configId,\n isEnabled: !currentValue,\n }),\n }),\n )\n if (!response.ok) {\n throw Object.assign(new Error('[internal] currencies.fetchConfig.toggle failed'), {\n status: response.status,\n ...((response.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return response\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n resourceId: configId,\n retryLastMutation,\n },\n mutationPayload: { id: configId, isEnabled: !currentValue },\n })\n\n const result = call.result as { config?: FetchConfig } | null\n if (result?.config) {\n setConfigs((prev) =>\n prev.map((c) => (c.id === configId ? (result.config as FetchConfig) : c))\n )\n flash(\n currentValue\n ? t('currencies.fetch.provider_disabled')\n : t('currencies.fetch.provider_enabled'),\n 'success'\n )\n }\n } catch (err: any) {\n if (extractOptimisticLockConflict(err)) return\n flash(err.message || t('currencies.fetch.error_update_config'), 'error')\n }\n }, [mutationContextId, retryLastMutation, runMutation, t])\n\n const updateSyncTime = useCallback(async (configId: string, syncTime: string, updatedAt?: string | null) => {\n try {\n const call = await runMutation({\n operation: async () => {\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt),\n () =>\n apiCall('/api/currencies/fetch-configs', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: configId,\n syncTime: syncTime || null,\n }),\n }),\n )\n if (!response.ok) {\n throw Object.assign(new Error('[internal] currencies.fetchConfig.updateSyncTime failed'), {\n status: response.status,\n ...((response.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return response\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n resourceId: configId,\n retryLastMutation,\n },\n mutationPayload: { id: configId, syncTime: syncTime || null },\n })\n\n const result = call.result as { config?: FetchConfig } | null\n if (result?.config) {\n setConfigs((prev) =>\n prev.map((c) => (c.id === configId ? (result.config as FetchConfig) : c))\n )\n }\n } catch (err: any) {\n if (extractOptimisticLockConflict(err)) return\n flash(err.message || t('currencies.fetch.error_update_sync_time'), 'error')\n }\n }, [mutationContextId, retryLastMutation, runMutation, t])\n\n const fetchNow = useCallback(async (provider: string) => {\n setFetching(provider)\n\n try {\n const call = await runMutation({\n operation: () => apiCall('/api/currencies/fetch-rates', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n providers: [provider],\n }),\n }),\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_rates',\n retryLastMutation,\n },\n mutationPayload: { providers: [provider] },\n })\n\n const result = call.result as { byProvider?: Record<string, { count: number; errors?: string[] }> } | null\n if (result) {\n const byProvider = result.byProvider as Record<string, { count: number; errors?: string[] }>\n const count = byProvider?.[provider]?.count || 0\n\n if (count === 0) {\n flash(t('currencies.fetch.sync_no_rates'), 'warning')\n } else {\n flash(t('currencies.fetch.sync_success', { count }), 'success')\n }\n await loadConfigs()\n }\n } catch (err: any) {\n flash(err.message || t('currencies.fetch.sync_error'), 'error')\n } finally {\n setFetching(null)\n }\n }, [mutationContextId, retryLastMutation, runMutation, t, loadConfigs])\n\n useEffect(() => {\n loadConfigs()\n }, [loadConfigs])\n\n function formatLastSync(date: string | null): string {\n if (!date) return t('currencies.fetch.last_sync_never')\n return new Date(date).toLocaleString()\n }\n\n function getStatusBadge(status: string | null) {\n if (!status) return null\n\n return (\n <StatusBadge variant={STATUS_BADGE_VARIANT[status] ?? 'neutral'}>\n {status}\n </StatusBadge>\n )\n }\n\n function getProviderName(provider: string): string {\n if (provider === 'NBP') return t('currencies.fetch.provider_nbp')\n if (provider === 'Raiffeisen Bank Polska') return t('currencies.fetch.provider_raiffeisen')\n return provider\n }\n\n function getProviderDescription(provider: string): string {\n if (provider === 'NBP') {\n return t('currencies.fetch.provider_nbp_description')\n }\n if (provider === 'Raiffeisen Bank Polska') {\n return t('currencies.fetch.provider_raiffeisen_description')\n }\n return ''\n }\n\n if (loading || initializing) {\n return (\n <section className=\"space-y-3 rounded-lg border bg-background p-4\">\n <header className=\"space-y-2\">\n <h2 className=\"text-xl font-semibold\">{t('currencies.fetch.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.description')}\n </p>\n </header>\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n {initializing ? t('currencies.fetch.initializing_providers') : t('currencies.fetch.loading')}\n </div>\n </section>\n )\n }\n\n return (\n <section className=\"space-y-6 rounded-lg border bg-background p-4\">\n <header className=\"space-y-2\">\n <h2 className=\"text-xl font-semibold\">{t('currencies.fetch.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.description')}\n </p>\n </header>\n\n <div className=\"space-y-3\">\n {configs.map((config) => (\n <div\n key={config.id}\n className=\"rounded-lg border bg-card p-4\"\n >\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1\">\n <h3 className=\"text-sm font-medium\">\n {getProviderName(config.provider)}\n </h3>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {getProviderDescription(config.provider)}\n </p>\n </div>\n\n <Switch\n checked={config.isEnabled}\n onCheckedChange={() => toggleEnabled(config.id, config.isEnabled, config.updatedAt)}\n />\n </div>\n\n {config.isEnabled && (\n <>\n <div className=\"flex items-baseline gap-3 flex-wrap mt-3\">\n <div className=\"flex items-baseline gap-2\">\n <label className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {t('currencies.fetch.sync_time')}:\n </label>\n <TimeInput\n value={config.syncTime || '09:00'}\n onChange={(time) => updateSyncTime(config.id, time, config.updatedAt)}\n />\n </div>\n\n <div className=\"flex items-baseline gap-2\">\n <label className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {t('currencies.fetch.last_sync')}:\n </label>\n <span className=\"text-xs text-muted-foreground\">\n {formatLastSync(config.lastSyncAt)}\n </span>\n {getStatusBadge(config.lastSyncStatus)}\n </div>\n\n <Button\n type=\"button\"\n onClick={() => fetchNow(config.provider)}\n disabled={fetching === config.provider}\n size=\"default\"\n className=\"ml-auto min-w-32\"\n >\n {fetching === config.provider ? (\n <div>\n <Spinner className=\"mr-1.5\" size='sm' />\n {t('currencies.fetch.fetching')}\n </div>\n ) : (\n t('currencies.fetch.fetch_now')\n )}\n </Button>\n </div>\n\n {config.lastSyncCount !== null && (\n <div className=\"text-xs text-muted-foreground mt-2\">\n {t('currencies.fetch.last_sync_count')}: <span className=\"font-medium\">{config.lastSyncCount}</span>\n </div>\n )}\n\n {config.lastSyncMessage && config.lastSyncStatus === 'error' && (\n <Alert status=\"error\" style=\"lighter\" size=\"xs\" className=\"mt-2\">\n {config.lastSyncMessage}\n </Alert>\n )}\n </>\n )}\n </div>\n ))}\n\n {configs.length === 0 && (\n <div className=\"rounded border bg-background/80 p-6 text-center\">\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.no_providers')}\n </p>\n <Button\n type=\"button\"\n onClick={() => initializeMissingProviders(availableProviders)}\n >\n {t('currencies.fetch.initialize_providers')}\n </Button>\n </div>\n )}\n </div>\n </section>\n )\n}\n"],
5
- "mappings": ";AAiRM,SAuEQ,UAvER,KAyBE,YAzBF;AA/QN,SAAS,UAAU,WAAW,aAAa,eAAe;AAC1D,SAAS,aAAa;AACtB,SAAS,SAAS,mCAAmC;AACrD,SAAS,2BAA2B,qCAAqC;AACzE,SAAS,0BAA0B;AACnC,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB,SAAS,mBAA4C;AACrD,SAAS,aAAa;AACtB,SAAS,iBAAiB;AAC1B,SAAS,YAAY;AAcrB,MAAM,uBAA2D;AAAA,EAC/D,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS;AACX;AAEe,SAAR,yBAA0C;AAC/C,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,SAAS,UAAU,IAAI,SAAwB,CAAC,CAAC;AACxD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwB,IAAI;AAC5D,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,KAAK;AAGtD,QAAM,qBAAqB,QAAQ,MAAM,CAAC,OAAO,wBAAwB,GAAG,CAAC,CAAC;AAE9E,QAAM,oBAAoB;AAC1B,QAAM,EAAE,aAAa,kBAAkB,IAAI,mBAKxC;AAAA,IACD,WAAW;AAAA,IACX,gBAAgB,EAAE,8BAA8B,4BAA4B;AAAA,EAC9E,CAAC;AAED,QAAM,uBAAuB,YAAY,OAAO,aAAqB;AACnE,QAAI;AACF,YAAM,YAAY;AAAA,QAChB,WAAW,MAAM,QAAQ,iCAAiC;AAAA,UACxD,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU;AAAA,YACnB;AAAA,YACA,WAAW;AAAA,YACX,UAAU;AAAA,UACZ,CAAC;AAAA,QACH,CAAC;AAAA,QACD,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,cAAc;AAAA,UACd;AAAA,QACF;AAAA,QACA,iBAAiB,EAAE,UAAU,WAAW,OAAO,UAAU,QAAQ;AAAA,MACnE,CAAC;AAAA,IACH,SAAS,KAAU;AAEjB,UAAI,CAAC,IAAI,SAAS,SAAS,oBAAoB,GAAG;AAChD,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,GAAG,CAAC,mBAAmB,mBAAmB,WAAW,CAAC;AAEtD,QAAM,6BAA6B,YAAY,OAAO,cAAwB;AAC5E,oBAAgB,IAAI;AACpB,QAAI;AACF,iBAAW,YAAY,WAAW;AAChC,cAAM,qBAAqB,QAAQ;AAAA,MACrC;AAEA,YAAM,EAAE,OAAO,IAAI,MAAM,QAAQ,+BAA+B;AAChE,UAAI,QAAQ,SAAS;AACnB,mBAAW,OAAO,OAAwB;AAAA,MAC5C;AAAA,IACF,SAAS,KAAU;AACjB,cAAQ,MAAM,mCAAmC,GAAG;AAAA,IACtD,UAAE;AACA,sBAAgB,KAAK;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,oBAAoB,CAAC;AAEzB,QAAM,cAAc,YAAY,YAAY;AAC1C,QAAI;AACF,YAAM,EAAE,OAAO,IAAI,MAAM,QAAQ,+BAA+B;AAEhE,UAAI,QAAQ,SAAS;AACnB,cAAM,kBAAkB,OAAO;AAC/B,mBAAW,eAAe;AAG1B,cAAM,oBAAoB,gBAAgB,IAAI,CAAC,MAAM,EAAE,QAAQ;AAC/D,cAAM,mBAAmB,mBAAmB;AAAA,UAC1C,CAAC,MAAM,CAAC,kBAAkB,SAAS,CAAC;AAAA,QACtC;AAGA,YAAI,iBAAiB,SAAS,GAAG;AAC/B,gBAAM,2BAA2B,gBAAgB;AAAA,QACnD;AAAA,MACF;AAAA,IACF,SAAS,KAAU;AACjB,YAAM,IAAI,WAAW,EAAE,qCAAqC,GAAG,OAAO;AAAA,IACxE,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,oBAAoB,4BAA4B,CAAC,CAAC;AAEtD,QAAM,gBAAgB,YAAY,OAAO,UAAkB,cAAuB,cAA8B;AAC9G,QAAI;AACF,YAAM,OAAO,MAAM,YAAY;AAAA,QAC7B,WAAW,YAAY;AACrB,gBAAM,WAAW,MAAM;AAAA,YACrB,0BAA0B,SAAS;AAAA,YACnC,MACE,QAAQ,iCAAiC;AAAA,cACvC,QAAQ;AAAA,cACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,cAC9C,MAAM,KAAK,UAAU;AAAA,gBACnB,IAAI;AAAA,gBACJ,WAAW,CAAC;AAAA,cACd,CAAC;AAAA,YACH,CAAC;AAAA,UACL;AACA,cAAI,CAAC,SAAS,IAAI;AAChB,kBAAM,OAAO,OAAO,IAAI,MAAM,iDAAiD,GAAG;AAAA,cAChF,QAAQ,SAAS;AAAA,cACjB,GAAK,SAAS,UAA6C,CAAC;AAAA,YAC9D,CAAC;AAAA,UACH;AACA,iBAAO;AAAA,QACT;AAAA,QACA,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,cAAc;AAAA,UACd,YAAY;AAAA,UACZ;AAAA,QACF;AAAA,QACA,iBAAiB,EAAE,IAAI,UAAU,WAAW,CAAC,aAAa;AAAA,MAC5D,CAAC;AAED,YAAM,SAAS,KAAK;AACpB,UAAI,QAAQ,QAAQ;AAClB;AAAA,UAAW,CAAC,SACV,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,WAAY,OAAO,SAAyB,CAAE;AAAA,QAC1E;AACA;AAAA,UACE,eACI,EAAE,oCAAoC,IACtC,EAAE,mCAAmC;AAAA,UACzC;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,KAAU;AACjB,UAAI,8BAA8B,GAAG,EAAG;AACxC,YAAM,IAAI,WAAW,EAAE,sCAAsC,GAAG,OAAO;AAAA,IACzE;AAAA,EACF,GAAG,CAAC,mBAAmB,mBAAmB,aAAa,CAAC,CAAC;AAEzD,QAAM,iBAAiB,YAAY,OAAO,UAAkB,UAAkB,cAA8B;AAC1G,QAAI;AACF,YAAM,OAAO,MAAM,YAAY;AAAA,QAC7B,WAAW,YAAY;AACrB,gBAAM,WAAW,MAAM;AAAA,YACrB,0BAA0B,SAAS;AAAA,YACnC,MACE,QAAQ,iCAAiC;AAAA,cACvC,QAAQ;AAAA,cACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,cAC9C,MAAM,KAAK,UAAU;AAAA,gBACnB,IAAI;AAAA,gBACJ,UAAU,YAAY;AAAA,cACxB,CAAC;AAAA,YACH,CAAC;AAAA,UACL;AACA,cAAI,CAAC,SAAS,IAAI;AAChB,kBAAM,OAAO,OAAO,IAAI,MAAM,yDAAyD,GAAG;AAAA,cACxF,QAAQ,SAAS;AAAA,cACjB,GAAK,SAAS,UAA6C,CAAC;AAAA,YAC9D,CAAC;AAAA,UACH;AACA,iBAAO;AAAA,QACT;AAAA,QACA,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,cAAc;AAAA,UACd,YAAY;AAAA,UACZ;AAAA,QACF;AAAA,QACA,iBAAiB,EAAE,IAAI,UAAU,UAAU,YAAY,KAAK;AAAA,MAC9D,CAAC;AAED,YAAM,SAAS,KAAK;AACpB,UAAI,QAAQ,QAAQ;AAClB;AAAA,UAAW,CAAC,SACV,KAAK,IAAI,CAAC,MAAO,EAAE,OAAO,WAAY,OAAO,SAAyB,CAAE;AAAA,QAC1E;AAAA,MACF;AAAA,IACF,SAAS,KAAU;AACjB,UAAI,8BAA8B,GAAG,EAAG;AACxC,YAAM,IAAI,WAAW,EAAE,yCAAyC,GAAG,OAAO;AAAA,IAC5E;AAAA,EACF,GAAG,CAAC,mBAAmB,mBAAmB,aAAa,CAAC,CAAC;AAEzD,QAAM,WAAW,YAAY,OAAO,aAAqB;AACvD,gBAAY,QAAQ;AAEpB,QAAI;AACF,YAAM,OAAO,MAAM,YAAY;AAAA,QAC7B,WAAW,MAAM,QAAQ,+BAA+B;AAAA,UACtD,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU;AAAA,YACnB,WAAW,CAAC,QAAQ;AAAA,UACtB,CAAC;AAAA,QACH,CAAC;AAAA,QACD,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,cAAc;AAAA,UACd;AAAA,QACF;AAAA,QACA,iBAAiB,EAAE,WAAW,CAAC,QAAQ,EAAE;AAAA,MAC3C,CAAC;AAED,YAAM,SAAS,KAAK;AACpB,UAAI,QAAQ;AACV,cAAM,aAAa,OAAO;AAC1B,cAAM,QAAQ,aAAa,QAAQ,GAAG,SAAS;AAE/C,YAAI,UAAU,GAAG;AACf,gBAAM,EAAE,gCAAgC,GAAG,SAAS;AAAA,QACtD,OAAO;AACL,gBAAM,EAAE,iCAAiC,EAAE,MAAM,CAAC,GAAG,SAAS;AAAA,QAChE;AACA,cAAM,YAAY;AAAA,MACpB;AAAA,IACF,SAAS,KAAU;AACjB,YAAM,IAAI,WAAW,EAAE,6BAA6B,GAAG,OAAO;AAAA,IAChE,UAAE;AACA,kBAAY,IAAI;AAAA,IAClB;AAAA,EACF,GAAG,CAAC,mBAAmB,mBAAmB,aAAa,GAAG,WAAW,CAAC;AAEtE,YAAU,MAAM;AACd,gBAAY;AAAA,EACd,GAAG,CAAC,WAAW,CAAC;AAEhB,WAAS,eAAe,MAA6B;AACnD,QAAI,CAAC,KAAM,QAAO,EAAE,kCAAkC;AACtD,WAAO,IAAI,KAAK,IAAI,EAAE,eAAe;AAAA,EACvC;AAEA,WAAS,eAAe,QAAuB;AAC7C,QAAI,CAAC,OAAQ,QAAO;AAEpB,WACE,oBAAC,eAAY,SAAS,qBAAqB,MAAM,KAAK,WACnD,kBACH;AAAA,EAEJ;AAEA,WAAS,gBAAgB,UAA0B;AACjD,QAAI,aAAa,MAAO,QAAO,EAAE,+BAA+B;AAChE,QAAI,aAAa,yBAA0B,QAAO,EAAE,sCAAsC;AAC1F,WAAO;AAAA,EACT;AAEA,WAAS,uBAAuB,UAA0B;AACxD,QAAI,aAAa,OAAO;AACtB,aAAO,EAAE,2CAA2C;AAAA,IACtD;AACA,QAAI,aAAa,0BAA0B;AACzC,aAAO,EAAE,kDAAkD;AAAA,IAC7D;AACA,WAAO;AAAA,EACT;AAEA,MAAI,WAAW,cAAc;AAC3B,WACE,qBAAC,aAAQ,WAAU,iDACjB;AAAA,2BAAC,YAAO,WAAU,aAChB;AAAA,4BAAC,QAAG,WAAU,yBAAyB,YAAE,wBAAwB,GAAE;AAAA,QACnE,oBAAC,OAAE,WAAU,iCACV,YAAE,8BAA8B,GACnC;AAAA,SACF;AAAA,MACA,qBAAC,SAAI,WAAU,yDACb;AAAA,4BAAC,WAAQ,WAAU,WAAU;AAAA,QAC5B,eAAe,EAAE,yCAAyC,IAAI,EAAE,0BAA0B;AAAA,SAC7F;AAAA,OACF;AAAA,EAEJ;AAEA,SACE,qBAAC,aAAQ,WAAU,iDACjB;AAAA,yBAAC,YAAO,WAAU,aAChB;AAAA,0BAAC,QAAG,WAAU,yBAAyB,YAAE,wBAAwB,GAAE;AAAA,MACnE,oBAAC,OAAE,WAAU,iCACV,YAAE,8BAA8B,GACnC;AAAA,OACF;AAAA,IAEA,qBAAC,SAAI,WAAU,aACZ;AAAA,cAAQ,IAAI,CAAC,WACZ;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAEV;AAAA,iCAAC,SAAI,WAAU,0CACb;AAAA,mCAAC,SAAI,WAAU,UACb;AAAA,oCAAC,QAAG,WAAU,uBACX,0BAAgB,OAAO,QAAQ,GAClC;AAAA,gBACA,oBAAC,OAAE,WAAU,wCACV,iCAAuB,OAAO,QAAQ,GACzC;AAAA,iBACF;AAAA,cAEA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAS,OAAO;AAAA,kBAChB,iBAAiB,MAAM,cAAc,OAAO,IAAI,OAAO,WAAW,OAAO,SAAS;AAAA;AAAA,cACpF;AAAA,eACF;AAAA,YAEC,OAAO,aACN,iCACE;AAAA,mCAAC,SAAI,WAAU,4CACb;AAAA,qCAAC,SAAI,WAAU,6BACb;AAAA,uCAAC,WAAM,WAAU,mDACd;AAAA,sBAAE,4BAA4B;AAAA,oBAAE;AAAA,qBACnC;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO,OAAO,YAAY;AAAA,sBAC1B,UAAU,CAAC,SAAS,eAAe,OAAO,IAAI,MAAM,OAAO,SAAS;AAAA;AAAA,kBACtE;AAAA,mBACF;AAAA,gBAEA,qBAAC,SAAI,WAAU,6BACb;AAAA,uCAAC,WAAM,WAAU,mDACd;AAAA,sBAAE,4BAA4B;AAAA,oBAAE;AAAA,qBACnC;AAAA,kBACA,oBAAC,UAAK,WAAU,iCACb,yBAAe,OAAO,UAAU,GACnC;AAAA,kBACC,eAAe,OAAO,cAAc;AAAA,mBACvC;AAAA,gBAEA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAM,SAAS,OAAO,QAAQ;AAAA,oBACvC,UAAU,aAAa,OAAO;AAAA,oBAC9B,MAAK;AAAA,oBACL,WAAU;AAAA,oBAET,uBAAa,OAAO,WACnB,qBAAC,SACC;AAAA,0CAAC,WAAQ,WAAU,UAAS,MAAK,MAAK;AAAA,sBACrC,EAAE,2BAA2B;AAAA,uBAChC,IAEA,EAAE,4BAA4B;AAAA;AAAA,gBAElC;AAAA,iBACF;AAAA,cAEC,OAAO,kBAAkB,QACxB,qBAAC,SAAI,WAAU,sCACZ;AAAA,kBAAE,kCAAkC;AAAA,gBAAE;AAAA,gBAAE,oBAAC,UAAK,WAAU,eAAe,iBAAO,eAAc;AAAA,iBAC/F;AAAA,cAGD,OAAO,mBAAmB,OAAO,mBAAmB,WACnD,oBAAC,SAAM,QAAO,SAAQ,OAAM,WAAU,MAAK,MAAK,WAAU,QACvD,iBAAO,iBACV;AAAA,eAEJ;AAAA;AAAA;AAAA,QAvEG,OAAO;AAAA,MAyEd,CACD;AAAA,MAEA,QAAQ,WAAW,KAClB,qBAAC,SAAI,WAAU,mDACb;AAAA,4BAAC,OAAE,WAAU,iCACV,YAAE,+BAA+B,GACpC;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM,2BAA2B,kBAAkB;AAAA,YAE3D,YAAE,uCAAuC;AAAA;AAAA,QAC5C;AAAA,SACF;AAAA,OAEJ;AAAA,KACF;AAEJ;",
4
+ "sourcesContent": ["'use client'\n\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader, extractOptimisticLockConflict } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { StatusBadge, type StatusBadgeVariant } from '@open-mercato/ui/primitives/status-badge'\nimport { Alert } from '@open-mercato/ui/primitives/alert'\nimport { TimeInput } from '@open-mercato/ui/backend/inputs/TimeInput'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('currencies').child({ component: 'CurrencyFetchingConfig' })\n\ninterface FetchConfig {\n id: string\n provider: string\n isEnabled: boolean\n syncTime: string | null\n lastSyncAt: string | null\n lastSyncStatus: string | null\n lastSyncMessage: string | null\n lastSyncCount: number | null\n updatedAt?: string | null\n}\n\nconst STATUS_BADGE_VARIANT: Record<string, StatusBadgeVariant> = {\n success: 'success',\n error: 'error',\n partial: 'warning',\n}\n\nexport default function CurrencyFetchingConfig() {\n const t = useT()\n const [configs, setConfigs] = useState<FetchConfig[]>([])\n const [loading, setLoading] = useState(true)\n const [fetching, setFetching] = useState<string | null>(null)\n const [initializing, setInitializing] = useState(false)\n\n // Available providers that should be configured\n const availableProviders = useMemo(() => ['NBP', 'Raiffeisen Bank Polska'], [])\n\n const mutationContextId = 'currencies-fetch-configs:mutation'\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId?: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: mutationContextId,\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const createProviderConfig = useCallback(async (provider: string) => {\n try {\n await runMutation({\n operation: () => apiCall('/api/currencies/fetch-configs', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n provider,\n isEnabled: false,\n syncTime: '09:00',\n }),\n }),\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n retryLastMutation,\n },\n mutationPayload: { provider, isEnabled: false, syncTime: '09:00' },\n })\n } catch (err: any) {\n // Ignore errors for duplicate providers\n if (!err.message?.includes('already configured')) {\n throw err\n }\n }\n }, [mutationContextId, retryLastMutation, runMutation])\n\n const initializeMissingProviders = useCallback(async (providers: string[]) => {\n setInitializing(true)\n try {\n for (const provider of providers) {\n await createProviderConfig(provider)\n }\n // Reload configs after initialization\n const { result } = await apiCall('/api/currencies/fetch-configs')\n if (result?.configs) {\n setConfigs(result.configs as FetchConfig[])\n }\n } catch (err: any) {\n logger.error('Failed to initialize providers', { err })\n } finally {\n setInitializing(false)\n }\n }, [createProviderConfig])\n\n const loadConfigs = useCallback(async () => {\n try {\n const { result } = await apiCall('/api/currencies/fetch-configs')\n\n if (result?.configs) {\n const existingConfigs = result.configs as FetchConfig[]\n setConfigs(existingConfigs)\n\n // Check if we need to initialize any missing providers\n const existingProviders = existingConfigs.map((c) => c.provider)\n const missingProviders = availableProviders.filter(\n (p) => !existingProviders.includes(p)\n )\n\n // Auto-initialize missing providers\n if (missingProviders.length > 0) {\n await initializeMissingProviders(missingProviders)\n }\n }\n } catch (err: any) {\n flash(err.message || t('currencies.fetch.error_load_configs'), 'error')\n } finally {\n setLoading(false)\n }\n }, [availableProviders, initializeMissingProviders, t])\n\n const toggleEnabled = useCallback(async (configId: string, currentValue: boolean, updatedAt?: string | null) => {\n try {\n const call = await runMutation({\n operation: async () => {\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt),\n () =>\n apiCall('/api/currencies/fetch-configs', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: configId,\n isEnabled: !currentValue,\n }),\n }),\n )\n if (!response.ok) {\n throw Object.assign(new Error('[internal] currencies.fetchConfig.toggle failed'), {\n status: response.status,\n ...((response.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return response\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n resourceId: configId,\n retryLastMutation,\n },\n mutationPayload: { id: configId, isEnabled: !currentValue },\n })\n\n const result = call.result as { config?: FetchConfig } | null\n if (result?.config) {\n setConfigs((prev) =>\n prev.map((c) => (c.id === configId ? (result.config as FetchConfig) : c))\n )\n flash(\n currentValue\n ? t('currencies.fetch.provider_disabled')\n : t('currencies.fetch.provider_enabled'),\n 'success'\n )\n }\n } catch (err: any) {\n if (extractOptimisticLockConflict(err)) return\n flash(err.message || t('currencies.fetch.error_update_config'), 'error')\n }\n }, [mutationContextId, retryLastMutation, runMutation, t])\n\n const updateSyncTime = useCallback(async (configId: string, syncTime: string, updatedAt?: string | null) => {\n try {\n const call = await runMutation({\n operation: async () => {\n const response = await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(updatedAt),\n () =>\n apiCall('/api/currencies/fetch-configs', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: configId,\n syncTime: syncTime || null,\n }),\n }),\n )\n if (!response.ok) {\n throw Object.assign(new Error('[internal] currencies.fetchConfig.updateSyncTime failed'), {\n status: response.status,\n ...((response.result as Record<string, unknown> | null) ?? {}),\n })\n }\n return response\n },\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_config',\n resourceId: configId,\n retryLastMutation,\n },\n mutationPayload: { id: configId, syncTime: syncTime || null },\n })\n\n const result = call.result as { config?: FetchConfig } | null\n if (result?.config) {\n setConfigs((prev) =>\n prev.map((c) => (c.id === configId ? (result.config as FetchConfig) : c))\n )\n }\n } catch (err: any) {\n if (extractOptimisticLockConflict(err)) return\n flash(err.message || t('currencies.fetch.error_update_sync_time'), 'error')\n }\n }, [mutationContextId, retryLastMutation, runMutation, t])\n\n const fetchNow = useCallback(async (provider: string) => {\n setFetching(provider)\n\n try {\n const call = await runMutation({\n operation: () => apiCall('/api/currencies/fetch-rates', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n providers: [provider],\n }),\n }),\n context: {\n formId: mutationContextId,\n resourceKind: 'currencies.fetch_rates',\n retryLastMutation,\n },\n mutationPayload: { providers: [provider] },\n })\n\n const result = call.result as { byProvider?: Record<string, { count: number; errors?: string[] }> } | null\n if (result) {\n const byProvider = result.byProvider as Record<string, { count: number; errors?: string[] }>\n const count = byProvider?.[provider]?.count || 0\n\n if (count === 0) {\n flash(t('currencies.fetch.sync_no_rates'), 'warning')\n } else {\n flash(t('currencies.fetch.sync_success', { count }), 'success')\n }\n await loadConfigs()\n }\n } catch (err: any) {\n flash(err.message || t('currencies.fetch.sync_error'), 'error')\n } finally {\n setFetching(null)\n }\n }, [mutationContextId, retryLastMutation, runMutation, t, loadConfigs])\n\n useEffect(() => {\n loadConfigs()\n }, [loadConfigs])\n\n function formatLastSync(date: string | null): string {\n if (!date) return t('currencies.fetch.last_sync_never')\n return new Date(date).toLocaleString()\n }\n\n function getStatusBadge(status: string | null) {\n if (!status) return null\n\n return (\n <StatusBadge variant={STATUS_BADGE_VARIANT[status] ?? 'neutral'}>\n {status}\n </StatusBadge>\n )\n }\n\n function getProviderName(provider: string): string {\n if (provider === 'NBP') return t('currencies.fetch.provider_nbp')\n if (provider === 'Raiffeisen Bank Polska') return t('currencies.fetch.provider_raiffeisen')\n return provider\n }\n\n function getProviderDescription(provider: string): string {\n if (provider === 'NBP') {\n return t('currencies.fetch.provider_nbp_description')\n }\n if (provider === 'Raiffeisen Bank Polska') {\n return t('currencies.fetch.provider_raiffeisen_description')\n }\n return ''\n }\n\n if (loading || initializing) {\n return (\n <section className=\"space-y-3 rounded-lg border bg-background p-4\">\n <header className=\"space-y-2\">\n <h2 className=\"text-xl font-semibold\">{t('currencies.fetch.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.description')}\n </p>\n </header>\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n {initializing ? t('currencies.fetch.initializing_providers') : t('currencies.fetch.loading')}\n </div>\n </section>\n )\n }\n\n return (\n <section className=\"space-y-6 rounded-lg border bg-background p-4\">\n <header className=\"space-y-2\">\n <h2 className=\"text-xl font-semibold\">{t('currencies.fetch.title')}</h2>\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.description')}\n </p>\n </header>\n\n <div className=\"space-y-3\">\n {configs.map((config) => (\n <div\n key={config.id}\n className=\"rounded-lg border bg-card p-4\"\n >\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1\">\n <h3 className=\"text-sm font-medium\">\n {getProviderName(config.provider)}\n </h3>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {getProviderDescription(config.provider)}\n </p>\n </div>\n\n <Switch\n checked={config.isEnabled}\n onCheckedChange={() => toggleEnabled(config.id, config.isEnabled, config.updatedAt)}\n />\n </div>\n\n {config.isEnabled && (\n <>\n <div className=\"flex items-baseline gap-3 flex-wrap mt-3\">\n <div className=\"flex items-baseline gap-2\">\n <label className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {t('currencies.fetch.sync_time')}:\n </label>\n <TimeInput\n value={config.syncTime || '09:00'}\n onChange={(time) => updateSyncTime(config.id, time, config.updatedAt)}\n />\n </div>\n\n <div className=\"flex items-baseline gap-2\">\n <label className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {t('currencies.fetch.last_sync')}:\n </label>\n <span className=\"text-xs text-muted-foreground\">\n {formatLastSync(config.lastSyncAt)}\n </span>\n {getStatusBadge(config.lastSyncStatus)}\n </div>\n\n <Button\n type=\"button\"\n onClick={() => fetchNow(config.provider)}\n disabled={fetching === config.provider}\n size=\"default\"\n className=\"ml-auto min-w-32\"\n >\n {fetching === config.provider ? (\n <div>\n <Spinner className=\"mr-1.5\" size='sm' />\n {t('currencies.fetch.fetching')}\n </div>\n ) : (\n t('currencies.fetch.fetch_now')\n )}\n </Button>\n </div>\n\n {config.lastSyncCount !== null && (\n <div className=\"text-xs text-muted-foreground mt-2\">\n {t('currencies.fetch.last_sync_count')}: <span className=\"font-medium\">{config.lastSyncCount}</span>\n </div>\n )}\n\n {config.lastSyncMessage && config.lastSyncStatus === 'error' && (\n <Alert status=\"error\" style=\"lighter\" size=\"xs\" className=\"mt-2\">\n {config.lastSyncMessage}\n </Alert>\n )}\n </>\n )}\n </div>\n ))}\n\n {configs.length === 0 && (\n <div className=\"rounded border bg-background/80 p-6 text-center\">\n <p className=\"text-sm text-muted-foreground\">\n {t('currencies.fetch.no_providers')}\n </p>\n <Button\n type=\"button\"\n onClick={() => initializeMissingProviders(availableProviders)}\n >\n {t('currencies.fetch.initialize_providers')}\n </Button>\n </div>\n )}\n </div>\n </section>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,6 @@
1
1
  import { createCrudFormError } from "@open-mercato/ui/backend/utils/serverErrors";
2
+ import { createLogger } from "@open-mercato/shared/lib/logger";
3
+ const logger = createLogger("currencies").child({ component: "exchange-rate-form" });
2
4
  async function loadCurrencyOptions(apiCallFn, query) {
3
5
  try {
4
6
  const params = new URLSearchParams();
@@ -17,7 +19,7 @@ async function loadCurrencyOptions(apiCallFn, query) {
17
19
  }));
18
20
  }
19
21
  } catch (error) {
20
- console.error("Failed to load currencies:", error);
22
+ logger.error("Failed to load currencies", { err: error });
21
23
  }
22
24
  return [];
23
25
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/currencies/lib/exchangeRateFormConfig.ts"],
4
- "sourcesContent": ["import type { CrudFormGroup, CrudFieldOption } from '@open-mercato/ui/backend/CrudForm'\nimport type { ApiCallResult } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\n\nexport type CurrencyOption = {\n id: string\n code: string\n name: string\n isActive: boolean\n}\n\ntype ApiCallFn = <T>(input: RequestInfo | URL, init?: RequestInit) => Promise<ApiCallResult<T>>\n\nexport async function loadCurrencyOptions(\n apiCallFn: ApiCallFn,\n query?: string,\n): Promise<CrudFieldOption[]> {\n try {\n const params = new URLSearchParams()\n if (query) {\n params.set('search', query)\n }\n params.set('isActive', 'true')\n params.set('pageSize', '100')\n\n const call = await apiCallFn<{ items: CurrencyOption[] }>(\n `/api/currencies/currencies?${params.toString()}`\n )\n\n if (call.ok && call.result?.items) {\n return call.result.items.map((c) => ({\n value: c.code,\n label: c.code,\n }))\n }\n } catch (error) {\n console.error('Failed to load currencies:', error)\n }\n return []\n}\n\nexport function exchangeRateGroups(\n t: (key: string) => string,\n loadOptions: (query?: string) => Promise<CrudFieldOption[]>,\n): CrudFormGroup[] {\n return [\n {\n id: 'rate-details',\n column: 1,\n fields: [\n {\n id: 'fromCurrencyCode',\n type: 'combobox',\n label: t('exchangeRates.form.field.fromCurrency'),\n placeholder: t('exchangeRates.form.field.fromCurrencyPlaceholder'),\n required: true,\n loadOptions,\n allowCustomValues: false,\n description: t('exchangeRates.form.field.fromCurrencyHelp'),\n },\n {\n id: 'toCurrencyCode',\n type: 'combobox',\n label: t('exchangeRates.form.field.toCurrency'),\n placeholder: t('exchangeRates.form.field.toCurrencyPlaceholder'),\n required: true,\n loadOptions,\n allowCustomValues: false,\n description: t('exchangeRates.form.field.toCurrencyHelp'),\n },\n {\n id: 'rate',\n type: 'number',\n label: t('exchangeRates.form.field.rate'),\n placeholder: '1.00000000',\n required: true,\n description: t('exchangeRates.form.field.rateHelp'),\n },\n {\n id: 'date',\n type: 'datetime-local',\n label: t('exchangeRates.form.field.date'),\n required: true,\n description: t('exchangeRates.form.field.dateHelp'),\n },\n ],\n },\n {\n id: 'metadata',\n column: 2,\n title: t('exchangeRates.form.group.metadata'),\n fields: [\n {\n id: 'source',\n type: 'text',\n label: t('exchangeRates.form.field.source'),\n placeholder: t('exchangeRates.form.field.sourcePlaceholder'),\n required: true,\n description: t('exchangeRates.form.field.sourceHelp'),\n },\n {\n id: 'type',\n type: 'select',\n label: t('exchangeRates.form.field.type'),\n placeholder: t('exchangeRates.form.field.typePlaceholder'),\n required: false,\n description: t('exchangeRates.form.field.typeHelp'),\n options: [\n { value: 'buy', label: t('exchangeRates.form.field.typeBuy') },\n { value: 'sell', label: t('exchangeRates.form.field.typeSell') },\n ],\n },\n {\n id: 'isActive',\n type: 'checkbox',\n label: t('exchangeRates.form.field.isActive'),\n },\n ],\n },\n ]\n}\n\nexport function validateExchangeRateForm(\n values: Record<string, unknown>,\n t: (key: string) => string,\n): { fromCode: string; toCode: string; rate: number; date: Date; source: string } {\n const fromCode = String(values.fromCurrencyCode || '').trim().toUpperCase()\n const toCode = String(values.toCurrencyCode || '').trim().toUpperCase()\n\n if (!/^[A-Z]{3}$/.test(fromCode)) {\n throw createCrudFormError(t('exchangeRates.form.errors.fromCurrencyFormat'), {\n fromCurrencyCode: t('exchangeRates.form.errors.currencyCodeFormat'),\n })\n }\n\n if (!/^[A-Z]{3}$/.test(toCode)) {\n throw createCrudFormError(t('exchangeRates.form.errors.toCurrencyFormat'), {\n toCurrencyCode: t('exchangeRates.form.errors.currencyCodeFormat'),\n })\n }\n\n if (fromCode === toCode) {\n throw createCrudFormError(t('exchangeRates.form.errors.sameCurrency'), {\n toCurrencyCode: t('exchangeRates.form.errors.sameCurrency'),\n })\n }\n\n const rate = parseFloat(String(values.rate || '0'))\n if (isNaN(rate) || rate <= 0) {\n throw createCrudFormError(t('exchangeRates.form.errors.invalidRate'), {\n rate: t('exchangeRates.form.errors.invalidRate'),\n })\n }\n\n const date = values.date ? new Date(String(values.date)) : null\n\n if (!date || isNaN(date.getTime())) {\n throw createCrudFormError(t('exchangeRates.form.errors.invalidDate'), {\n date: t('exchangeRates.form.errors.invalidDate'),\n })\n }\n\n const source = String(values.source || '').trim()\n if (!source || source.length < 2) {\n throw createCrudFormError(t('exchangeRates.form.errors.sourceTooShort'), {\n source: t('exchangeRates.form.errors.sourceTooShort'),\n })\n }\n if (source.length > 50) {\n throw createCrudFormError(t('exchangeRates.form.errors.sourceTooLong'), {\n source: t('exchangeRates.form.errors.sourceTooLong'),\n })\n }\n if (!/^[a-zA-Z0-9\\s\\-_]+$/.test(source)) {\n throw createCrudFormError(t('exchangeRates.form.errors.sourceInvalidFormat'), {\n source: t('exchangeRates.form.errors.sourceInvalidFormat'),\n })\n }\n\n return { fromCode, toCode, rate, date, source }\n}\n\nexport function buildExchangeRatePayload(values: Record<string, unknown>, validated: {\n fromCode: string\n toCode: string\n rate: number\n date: Date\n source: string\n}) {\n return {\n fromCurrencyCode: validated.fromCode,\n toCurrencyCode: validated.toCode,\n rate: validated.rate.toFixed(8),\n date: validated.date.toISOString(),\n source: validated.source,\n type: values.type && values.type !== '' ? values.type : null,\n isActive: values.isActive !== false,\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { CrudFormGroup, CrudFieldOption } from '@open-mercato/ui/backend/CrudForm'\nimport type { ApiCallResult } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('currencies').child({ component: 'exchange-rate-form' })\n\nexport type CurrencyOption = {\n id: string\n code: string\n name: string\n isActive: boolean\n}\n\ntype ApiCallFn = <T>(input: RequestInfo | URL, init?: RequestInit) => Promise<ApiCallResult<T>>\n\nexport async function loadCurrencyOptions(\n apiCallFn: ApiCallFn,\n query?: string,\n): Promise<CrudFieldOption[]> {\n try {\n const params = new URLSearchParams()\n if (query) {\n params.set('search', query)\n }\n params.set('isActive', 'true')\n params.set('pageSize', '100')\n\n const call = await apiCallFn<{ items: CurrencyOption[] }>(\n `/api/currencies/currencies?${params.toString()}`\n )\n\n if (call.ok && call.result?.items) {\n return call.result.items.map((c) => ({\n value: c.code,\n label: c.code,\n }))\n }\n } catch (error) {\n logger.error('Failed to load currencies', { err: error })\n }\n return []\n}\n\nexport function exchangeRateGroups(\n t: (key: string) => string,\n loadOptions: (query?: string) => Promise<CrudFieldOption[]>,\n): CrudFormGroup[] {\n return [\n {\n id: 'rate-details',\n column: 1,\n fields: [\n {\n id: 'fromCurrencyCode',\n type: 'combobox',\n label: t('exchangeRates.form.field.fromCurrency'),\n placeholder: t('exchangeRates.form.field.fromCurrencyPlaceholder'),\n required: true,\n loadOptions,\n allowCustomValues: false,\n description: t('exchangeRates.form.field.fromCurrencyHelp'),\n },\n {\n id: 'toCurrencyCode',\n type: 'combobox',\n label: t('exchangeRates.form.field.toCurrency'),\n placeholder: t('exchangeRates.form.field.toCurrencyPlaceholder'),\n required: true,\n loadOptions,\n allowCustomValues: false,\n description: t('exchangeRates.form.field.toCurrencyHelp'),\n },\n {\n id: 'rate',\n type: 'number',\n label: t('exchangeRates.form.field.rate'),\n placeholder: '1.00000000',\n required: true,\n description: t('exchangeRates.form.field.rateHelp'),\n },\n {\n id: 'date',\n type: 'datetime-local',\n label: t('exchangeRates.form.field.date'),\n required: true,\n description: t('exchangeRates.form.field.dateHelp'),\n },\n ],\n },\n {\n id: 'metadata',\n column: 2,\n title: t('exchangeRates.form.group.metadata'),\n fields: [\n {\n id: 'source',\n type: 'text',\n label: t('exchangeRates.form.field.source'),\n placeholder: t('exchangeRates.form.field.sourcePlaceholder'),\n required: true,\n description: t('exchangeRates.form.field.sourceHelp'),\n },\n {\n id: 'type',\n type: 'select',\n label: t('exchangeRates.form.field.type'),\n placeholder: t('exchangeRates.form.field.typePlaceholder'),\n required: false,\n description: t('exchangeRates.form.field.typeHelp'),\n options: [\n { value: 'buy', label: t('exchangeRates.form.field.typeBuy') },\n { value: 'sell', label: t('exchangeRates.form.field.typeSell') },\n ],\n },\n {\n id: 'isActive',\n type: 'checkbox',\n label: t('exchangeRates.form.field.isActive'),\n },\n ],\n },\n ]\n}\n\nexport function validateExchangeRateForm(\n values: Record<string, unknown>,\n t: (key: string) => string,\n): { fromCode: string; toCode: string; rate: number; date: Date; source: string } {\n const fromCode = String(values.fromCurrencyCode || '').trim().toUpperCase()\n const toCode = String(values.toCurrencyCode || '').trim().toUpperCase()\n\n if (!/^[A-Z]{3}$/.test(fromCode)) {\n throw createCrudFormError(t('exchangeRates.form.errors.fromCurrencyFormat'), {\n fromCurrencyCode: t('exchangeRates.form.errors.currencyCodeFormat'),\n })\n }\n\n if (!/^[A-Z]{3}$/.test(toCode)) {\n throw createCrudFormError(t('exchangeRates.form.errors.toCurrencyFormat'), {\n toCurrencyCode: t('exchangeRates.form.errors.currencyCodeFormat'),\n })\n }\n\n if (fromCode === toCode) {\n throw createCrudFormError(t('exchangeRates.form.errors.sameCurrency'), {\n toCurrencyCode: t('exchangeRates.form.errors.sameCurrency'),\n })\n }\n\n const rate = parseFloat(String(values.rate || '0'))\n if (isNaN(rate) || rate <= 0) {\n throw createCrudFormError(t('exchangeRates.form.errors.invalidRate'), {\n rate: t('exchangeRates.form.errors.invalidRate'),\n })\n }\n\n const date = values.date ? new Date(String(values.date)) : null\n\n if (!date || isNaN(date.getTime())) {\n throw createCrudFormError(t('exchangeRates.form.errors.invalidDate'), {\n date: t('exchangeRates.form.errors.invalidDate'),\n })\n }\n\n const source = String(values.source || '').trim()\n if (!source || source.length < 2) {\n throw createCrudFormError(t('exchangeRates.form.errors.sourceTooShort'), {\n source: t('exchangeRates.form.errors.sourceTooShort'),\n })\n }\n if (source.length > 50) {\n throw createCrudFormError(t('exchangeRates.form.errors.sourceTooLong'), {\n source: t('exchangeRates.form.errors.sourceTooLong'),\n })\n }\n if (!/^[a-zA-Z0-9\\s\\-_]+$/.test(source)) {\n throw createCrudFormError(t('exchangeRates.form.errors.sourceInvalidFormat'), {\n source: t('exchangeRates.form.errors.sourceInvalidFormat'),\n })\n }\n\n return { fromCode, toCode, rate, date, source }\n}\n\nexport function buildExchangeRatePayload(values: Record<string, unknown>, validated: {\n fromCode: string\n toCode: string\n rate: number\n date: Date\n source: string\n}) {\n return {\n fromCurrencyCode: validated.fromCode,\n toCurrencyCode: validated.toCode,\n rate: validated.rate.toFixed(8),\n date: validated.date.toISOString(),\n source: validated.source,\n type: values.type && values.type !== '' ? values.type : null,\n isActive: values.isActive !== false,\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,7 @@
1
1
  import { fromZonedTime } from "date-fns-tz";
2
2
  import { fetchWithTimeout, resolveTimeoutMs } from "@open-mercato/shared/lib/http/fetchWithTimeout";
3
+ import { createLogger } from "@open-mercato/shared/lib/logger";
4
+ const logger = createLogger("currencies").child({ component: "nbp" });
3
5
  const DEFAULT_RATE_FETCH_TIMEOUT_MS = 15e3;
4
6
  function resolveRateFetchTimeoutMs() {
5
7
  const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS;
@@ -18,7 +20,7 @@ class NBPProvider {
18
20
  }
19
21
  async fetchRates(date, scope, availableCurrencies) {
20
22
  if (!availableCurrencies.has(this.providerBaseCurrency)) {
21
- console.debug("[NBP] Skipping: PLN not found in available currencies");
23
+ logger.debug("Skipping: PLN not found in available currencies");
22
24
  return [];
23
25
  }
24
26
  const dateStr = this.formatDate(date);
@@ -26,7 +28,7 @@ class NBPProvider {
26
28
  try {
27
29
  const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() });
28
30
  if (response.status === 404) {
29
- console.log(`[NBP] No data available for ${dateStr}`);
31
+ logger.debug("No data available", { date: dateStr });
30
32
  return [];
31
33
  }
32
34
  if (!response.ok) {
@@ -62,10 +64,10 @@ class NBPProvider {
62
64
  // Bank buys foreign currency (from their perspective)
63
65
  });
64
66
  }
65
- console.log(`[NBP] Fetched ${results.length} rates for ${dateStr}`);
67
+ logger.info("Fetched rates", { count: results.length, date: dateStr });
66
68
  return results;
67
69
  } catch (err) {
68
- console.error(`[NBP] Fetch error for ${dateStr}:`, err.message);
70
+ logger.error("Fetch error", { date: dateStr, err });
69
71
  throw new Error(`Failed to fetch NBP rates: ${err.message}`);
70
72
  }
71
73
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/currencies/services/providers/nbp.ts"],
4
- "sourcesContent": ["import { RateProvider, RateProviderResult } from './base'\nimport { fromZonedTime } from 'date-fns-tz'\nimport { fetchWithTimeout, resolveTimeoutMs } from '@open-mercato/shared/lib/http/fetchWithTimeout'\n\nconst DEFAULT_RATE_FETCH_TIMEOUT_MS = 15_000\n\nfunction resolveRateFetchTimeoutMs(): number {\n const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS\n const parsed = raw ? Number.parseInt(raw, 10) : undefined\n return resolveTimeoutMs(parsed, DEFAULT_RATE_FETCH_TIMEOUT_MS)\n}\n\ninterface NBPTableCResponse {\n table: string\n no: string\n tradingDate: string\n effectiveDate: string\n rates: Array<{\n currency: string\n code: string\n bid: number\n ask: number\n }>\n}\n\nexport class NBPProvider implements RateProvider {\n readonly name = 'NBP (National Bank of Poland)'\n readonly source = 'NBP'\n readonly providerBaseCurrency = 'PLN'\n\n private readonly baseUrl = 'https://api.nbp.pl/api'\n\n isAvailable(): boolean {\n return true // Public API, always available\n }\n\n async fetchRates(\n date: Date,\n scope: { tenantId: string; organizationId: string },\n availableCurrencies: Set<string>\n ): Promise<RateProviderResult[]> {\n // Check if PLN is available (required as base currency for NBP)\n if (!availableCurrencies.has(this.providerBaseCurrency)) {\n console.debug('[NBP] Skipping: PLN not found in available currencies')\n return []\n }\n\n const dateStr = this.formatDate(date)\n const url = `${this.baseUrl}/exchangerates/tables/c/${dateStr}/?format=json`\n\n try {\n const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() })\n\n if (response.status === 404) {\n // No data for this date (weekend/holiday)\n console.log(`[NBP] No data available for ${dateStr}`)\n return []\n }\n\n if (!response.ok) {\n throw new Error(`NBP API error: ${response.status} ${response.statusText}`)\n }\n\n const data: NBPTableCResponse[] = await response.json()\n\n if (!data || data.length === 0) {\n return []\n }\n\n const table = data[0]\n const results: RateProviderResult[] = []\n \n // Parse as midnight Europe/Warsaw, then convert to UTC for DB storage\n const effectiveDate = fromZonedTime(\n `${table.effectiveDate} 00:00:00`,\n 'Europe/Warsaw'\n )\n\n for (const rate of table.rates) {\n // NBP rates are from bank's perspective:\n // - ASK (sprzeda\u017C): bank sells XXX for PLN \u2192 1 XXX = ask PLN\n // - BID (kupno): bank buys XXX for PLN \u2192 1 XXX = bid PLN\n \n // Rate 1: PLN \u2192 XXX (inverse of ASK) - this is when bank SELLS foreign currency\n // If ask = 4.5 (1 EUR costs 4.5 PLN), then 1 PLN = 1/4.5 EUR\n results.push({\n fromCurrencyCode: this.providerBaseCurrency,\n toCurrencyCode: rate.code,\n rate: (1 / rate.ask).toString(),\n source: this.source,\n date: effectiveDate,\n type: 'sell', // Bank sells foreign currency (from their perspective)\n })\n\n // Rate 2: XXX \u2192 PLN (using BID) - this is when bank BUYS foreign currency\n // If bid = 4.3 (1 EUR gives 4.3 PLN), then 1 EUR = 4.3 PLN\n results.push({\n fromCurrencyCode: rate.code,\n toCurrencyCode: this.providerBaseCurrency,\n rate: rate.bid.toString(),\n source: this.source,\n date: effectiveDate,\n type: 'buy', // Bank buys foreign currency (from their perspective)\n })\n }\n\n console.log(`[NBP] Fetched ${results.length} rates for ${dateStr}`)\n return results\n } catch (err: any) {\n console.error(`[NBP] Fetch error for ${dateStr}:`, err.message)\n throw new Error(`Failed to fetch NBP rates: ${err.message}`)\n }\n }\n\n private formatDate(date: Date): string {\n return date.toISOString().split('T')[0] // YYYY-MM-DD\n }\n}\n"],
5
- "mappings": "AACA,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB,wBAAwB;AAEnD,MAAM,gCAAgC;AAEtC,SAAS,4BAAoC;AAC3C,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,MAAM,OAAO,SAAS,KAAK,EAAE,IAAI;AAChD,SAAO,iBAAiB,QAAQ,6BAA6B;AAC/D;AAeO,MAAM,YAAoC;AAAA,EAA1C;AACL,SAAS,OAAO;AAChB,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAEhC,SAAiB,UAAU;AAAA;AAAA,EAE3B,cAAuB;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WACJ,MACA,OACA,qBAC+B;AAE/B,QAAI,CAAC,oBAAoB,IAAI,KAAK,oBAAoB,GAAG;AACvD,cAAQ,MAAM,uDAAuD;AACrE,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,UAAU,KAAK,WAAW,IAAI;AACpC,UAAM,MAAM,GAAG,KAAK,OAAO,2BAA2B,OAAO;AAE7D,QAAI;AACF,YAAM,WAAW,MAAM,iBAAiB,KAAK,EAAE,WAAW,0BAA0B,EAAE,CAAC;AAEvF,UAAI,SAAS,WAAW,KAAK;AAE3B,gBAAQ,IAAI,+BAA+B,OAAO,EAAE;AACpD,eAAO,CAAC;AAAA,MACV;AAEA,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,kBAAkB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,MAC5E;AAEA,YAAM,OAA4B,MAAM,SAAS,KAAK;AAEtD,UAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,eAAO,CAAC;AAAA,MACV;AAEA,YAAM,QAAQ,KAAK,CAAC;AACpB,YAAM,UAAgC,CAAC;AAGvC,YAAM,gBAAgB;AAAA,QACpB,GAAG,MAAM,aAAa;AAAA,QACtB;AAAA,MACF;AAEA,iBAAW,QAAQ,MAAM,OAAO;AAO9B,gBAAQ,KAAK;AAAA,UACX,kBAAkB,KAAK;AAAA,UACvB,gBAAgB,KAAK;AAAA,UACrB,OAAO,IAAI,KAAK,KAAK,SAAS;AAAA,UAC9B,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,QACR,CAAC;AAID,gBAAQ,KAAK;AAAA,UACX,kBAAkB,KAAK;AAAA,UACvB,gBAAgB,KAAK;AAAA,UACrB,MAAM,KAAK,IAAI,SAAS;AAAA,UACxB,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,QACR,CAAC;AAAA,MACH;AAEA,cAAQ,IAAI,iBAAiB,QAAQ,MAAM,cAAc,OAAO,EAAE;AAClE,aAAO;AAAA,IACT,SAAS,KAAU;AACjB,cAAQ,MAAM,yBAAyB,OAAO,KAAK,IAAI,OAAO;AAC9D,YAAM,IAAI,MAAM,8BAA8B,IAAI,OAAO,EAAE;AAAA,IAC7D;AAAA,EACF;AAAA,EAEQ,WAAW,MAAoB;AACrC,WAAO,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EACxC;AACF;",
4
+ "sourcesContent": ["import { RateProvider, RateProviderResult } from './base'\nimport { fromZonedTime } from 'date-fns-tz'\nimport { fetchWithTimeout, resolveTimeoutMs } from '@open-mercato/shared/lib/http/fetchWithTimeout'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('currencies').child({ component: 'nbp' })\n\nconst DEFAULT_RATE_FETCH_TIMEOUT_MS = 15_000\n\nfunction resolveRateFetchTimeoutMs(): number {\n const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS\n const parsed = raw ? Number.parseInt(raw, 10) : undefined\n return resolveTimeoutMs(parsed, DEFAULT_RATE_FETCH_TIMEOUT_MS)\n}\n\ninterface NBPTableCResponse {\n table: string\n no: string\n tradingDate: string\n effectiveDate: string\n rates: Array<{\n currency: string\n code: string\n bid: number\n ask: number\n }>\n}\n\nexport class NBPProvider implements RateProvider {\n readonly name = 'NBP (National Bank of Poland)'\n readonly source = 'NBP'\n readonly providerBaseCurrency = 'PLN'\n\n private readonly baseUrl = 'https://api.nbp.pl/api'\n\n isAvailable(): boolean {\n return true // Public API, always available\n }\n\n async fetchRates(\n date: Date,\n scope: { tenantId: string; organizationId: string },\n availableCurrencies: Set<string>\n ): Promise<RateProviderResult[]> {\n // Check if PLN is available (required as base currency for NBP)\n if (!availableCurrencies.has(this.providerBaseCurrency)) {\n logger.debug('Skipping: PLN not found in available currencies')\n return []\n }\n\n const dateStr = this.formatDate(date)\n const url = `${this.baseUrl}/exchangerates/tables/c/${dateStr}/?format=json`\n\n try {\n const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() })\n\n if (response.status === 404) {\n // No data for this date (weekend/holiday)\n logger.debug('No data available', { date: dateStr })\n return []\n }\n\n if (!response.ok) {\n throw new Error(`NBP API error: ${response.status} ${response.statusText}`)\n }\n\n const data: NBPTableCResponse[] = await response.json()\n\n if (!data || data.length === 0) {\n return []\n }\n\n const table = data[0]\n const results: RateProviderResult[] = []\n \n // Parse as midnight Europe/Warsaw, then convert to UTC for DB storage\n const effectiveDate = fromZonedTime(\n `${table.effectiveDate} 00:00:00`,\n 'Europe/Warsaw'\n )\n\n for (const rate of table.rates) {\n // NBP rates are from bank's perspective:\n // - ASK (sprzeda\u017C): bank sells XXX for PLN \u2192 1 XXX = ask PLN\n // - BID (kupno): bank buys XXX for PLN \u2192 1 XXX = bid PLN\n \n // Rate 1: PLN \u2192 XXX (inverse of ASK) - this is when bank SELLS foreign currency\n // If ask = 4.5 (1 EUR costs 4.5 PLN), then 1 PLN = 1/4.5 EUR\n results.push({\n fromCurrencyCode: this.providerBaseCurrency,\n toCurrencyCode: rate.code,\n rate: (1 / rate.ask).toString(),\n source: this.source,\n date: effectiveDate,\n type: 'sell', // Bank sells foreign currency (from their perspective)\n })\n\n // Rate 2: XXX \u2192 PLN (using BID) - this is when bank BUYS foreign currency\n // If bid = 4.3 (1 EUR gives 4.3 PLN), then 1 EUR = 4.3 PLN\n results.push({\n fromCurrencyCode: rate.code,\n toCurrencyCode: this.providerBaseCurrency,\n rate: rate.bid.toString(),\n source: this.source,\n date: effectiveDate,\n type: 'buy', // Bank buys foreign currency (from their perspective)\n })\n }\n\n logger.info('Fetched rates', { count: results.length, date: dateStr })\n return results\n } catch (err: any) {\n logger.error('Fetch error', { date: dateStr, err })\n throw new Error(`Failed to fetch NBP rates: ${err.message}`)\n }\n }\n\n private formatDate(date: Date): string {\n return date.toISOString().split('T')[0] // YYYY-MM-DD\n }\n}\n"],
5
+ "mappings": "AACA,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB,wBAAwB;AACnD,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,YAAY,EAAE,MAAM,EAAE,WAAW,MAAM,CAAC;AAEpE,MAAM,gCAAgC;AAEtC,SAAS,4BAAoC;AAC3C,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,MAAM,OAAO,SAAS,KAAK,EAAE,IAAI;AAChD,SAAO,iBAAiB,QAAQ,6BAA6B;AAC/D;AAeO,MAAM,YAAoC;AAAA,EAA1C;AACL,SAAS,OAAO;AAChB,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAEhC,SAAiB,UAAU;AAAA;AAAA,EAE3B,cAAuB;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WACJ,MACA,OACA,qBAC+B;AAE/B,QAAI,CAAC,oBAAoB,IAAI,KAAK,oBAAoB,GAAG;AACvD,aAAO,MAAM,iDAAiD;AAC9D,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,UAAU,KAAK,WAAW,IAAI;AACpC,UAAM,MAAM,GAAG,KAAK,OAAO,2BAA2B,OAAO;AAE7D,QAAI;AACF,YAAM,WAAW,MAAM,iBAAiB,KAAK,EAAE,WAAW,0BAA0B,EAAE,CAAC;AAEvF,UAAI,SAAS,WAAW,KAAK;AAE3B,eAAO,MAAM,qBAAqB,EAAE,MAAM,QAAQ,CAAC;AACnD,eAAO,CAAC;AAAA,MACV;AAEA,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,MAAM,kBAAkB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,MAC5E;AAEA,YAAM,OAA4B,MAAM,SAAS,KAAK;AAEtD,UAAI,CAAC,QAAQ,KAAK,WAAW,GAAG;AAC9B,eAAO,CAAC;AAAA,MACV;AAEA,YAAM,QAAQ,KAAK,CAAC;AACpB,YAAM,UAAgC,CAAC;AAGvC,YAAM,gBAAgB;AAAA,QACpB,GAAG,MAAM,aAAa;AAAA,QACtB;AAAA,MACF;AAEA,iBAAW,QAAQ,MAAM,OAAO;AAO9B,gBAAQ,KAAK;AAAA,UACX,kBAAkB,KAAK;AAAA,UACvB,gBAAgB,KAAK;AAAA,UACrB,OAAO,IAAI,KAAK,KAAK,SAAS;AAAA,UAC9B,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,QACR,CAAC;AAID,gBAAQ,KAAK;AAAA,UACX,kBAAkB,KAAK;AAAA,UACvB,gBAAgB,KAAK;AAAA,UACrB,MAAM,KAAK,IAAI,SAAS;AAAA,UACxB,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,QACR,CAAC;AAAA,MACH;AAEA,aAAO,KAAK,iBAAiB,EAAE,OAAO,QAAQ,QAAQ,MAAM,QAAQ,CAAC;AACrE,aAAO;AAAA,IACT,SAAS,KAAU;AACjB,aAAO,MAAM,eAAe,EAAE,MAAM,SAAS,IAAI,CAAC;AAClD,YAAM,IAAI,MAAM,8BAA8B,IAAI,OAAO,EAAE;AAAA,IAC7D;AAAA,EACF;AAAA,EAEQ,WAAW,MAAoB;AACrC,WAAO,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EACxC;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,7 @@
1
1
  import { fromZonedTime } from "date-fns-tz";
2
2
  import { fetchWithTimeout, resolveTimeoutMs } from "@open-mercato/shared/lib/http/fetchWithTimeout";
3
+ import { createLogger } from "@open-mercato/shared/lib/logger";
4
+ const logger = createLogger("currencies").child({ component: "raiffeisen" });
3
5
  const DEFAULT_RATE_FETCH_TIMEOUT_MS = 15e3;
4
6
  function resolveRateFetchTimeoutMs() {
5
7
  const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS;
@@ -18,7 +20,7 @@ class RaiffeisenPolandProvider {
18
20
  }
19
21
  async fetchRates(date, scope, availableCurrencies) {
20
22
  if (!availableCurrencies.has(this.providerBaseCurrency)) {
21
- console.debug("[Raiffeisen] Skipping: PLN not found in available currencies");
23
+ logger.debug("Skipping: PLN not found in available currencies");
22
24
  return [];
23
25
  }
24
26
  const dateStr = this.formatDate(date);
@@ -27,7 +29,7 @@ class RaiffeisenPolandProvider {
27
29
  const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() });
28
30
  if (!response.ok) {
29
31
  if (response.status === 404) {
30
- console.log(`[Raiffeisen] No data available for ${dateStr}`);
32
+ logger.debug("No data available", { date: dateStr });
31
33
  return [];
32
34
  }
33
35
  throw new Error(
@@ -44,7 +46,7 @@ class RaiffeisenPolandProvider {
44
46
  const results = [];
45
47
  const firstRate = rates[0];
46
48
  if (!firstRate) {
47
- console.log(`[Raiffeisen] No rates available in time slot ${firstTime}`);
49
+ logger.debug("No rates available in time slot", { timeSlot: firstTime });
48
50
  return [];
49
51
  }
50
52
  const rateDate = fromZonedTime(
@@ -72,12 +74,10 @@ class RaiffeisenPolandProvider {
72
74
  // Bank buys foreign currency (from their perspective)
73
75
  });
74
76
  }
75
- console.log(
76
- `[Raiffeisen] Fetched ${results.length} rates for ${dateStr} at ${firstRate.time} Warsaw time (${rateDate.toISOString()})`
77
- );
77
+ logger.info("Fetched rates", { count: results.length, date: dateStr, time: firstRate.time, rateDate: rateDate.toISOString() });
78
78
  return results;
79
79
  } catch (err) {
80
- console.error(`[Raiffeisen] Fetch error for ${dateStr}:`, err);
80
+ logger.error("Fetch error", { date: dateStr, err });
81
81
  throw new Error(`Failed to fetch Raiffeisen rates: ${err.message}`);
82
82
  }
83
83
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/currencies/services/providers/raiffeisen.ts"],
4
- "sourcesContent": ["import { RateProvider, RateProviderResult } from './base'\nimport { fromZonedTime } from 'date-fns-tz'\nimport { fetchWithTimeout, resolveTimeoutMs } from '@open-mercato/shared/lib/http/fetchWithTimeout'\n\nconst DEFAULT_RATE_FETCH_TIMEOUT_MS = 15_000\n\nfunction resolveRateFetchTimeoutMs(): number {\n const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS\n const parsed = raw ? Number.parseInt(raw, 10) : undefined\n return resolveTimeoutMs(parsed, DEFAULT_RATE_FETCH_TIMEOUT_MS)\n}\n\ninterface RaiffeisenResponse {\n date: string\n rates: Record<\n string,\n Array<{\n code: string\n units: number\n buy: string\n sell: string\n spread: string\n date: string\n time: string\n }>\n >\n range: {\n minRateDate: string\n maxRateDate: string\n }\n}\n\n// \nexport class RaiffeisenPolandProvider implements RateProvider {\n readonly name = 'Raiffeisen Bank Polska'\n readonly source = 'Raiffeisen Bank Polska'\n readonly providerBaseCurrency = 'PLN'\n\n private readonly baseUrl = 'https://www.rbinternational.com.pl/rest/rates/'\n\n isAvailable(): boolean {\n return true\n }\n\n async fetchRates(\n date: Date,\n scope: { tenantId: string; organizationId: string },\n availableCurrencies: Set<string>\n ): Promise<RateProviderResult[]> {\n // Check if PLN is available (required as base currency for Raiffeisen)\n if (!availableCurrencies.has(this.providerBaseCurrency)) {\n console.debug('[Raiffeisen] Skipping: PLN not found in available currencies')\n return []\n }\n\n const dateStr = this.formatDate(date)\n const url = `${this.baseUrl}?type=kursywalut&range=all&date=${dateStr}`\n\n try {\n const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() })\n\n if (!response.ok) {\n if (response.status === 404) {\n console.log(`[Raiffeisen] No data available for ${dateStr}`)\n return []\n }\n throw new Error(\n `Raiffeisen API error: ${response.status} ${response.statusText}`\n )\n }\n\n const data: RaiffeisenResponse = await response.json()\n\n if (!data.rates || Object.keys(data.rates).length === 0) {\n return []\n }\n\n // Get FIRST time slot (opening rates)\n const times = Object.keys(data.rates).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n const firstTime = times[0]\n const rates = data.rates[firstTime]\n\n const results: RateProviderResult[] = []\n \n // Extract time from first rate entry (all rates in same time slot have same time)\n const firstRate = rates[0]\n if (!firstRate) {\n console.log(`[Raiffeisen] No rates available in time slot ${firstTime}`)\n return []\n }\n\n // Combine date + time and parse as Europe/Warsaw timezone\n const rateDate = fromZonedTime(\n `${data.date} ${firstRate.time}`,\n 'Europe/Warsaw'\n )\n\n for (const rateData of rates) {\n // Raiffeisen rates are from bank's perspective:\n // - SELL: bank sells XXX for PLN \u2192 1 XXX = sell PLN\n // - BUY: bank buys XXX for PLN \u2192 1 XXX = buy PLN\n \n // Rate 1: PLN \u2192 XXX (inverse of SELL) - this is when bank SELLS foreign currency\n // If sell = 4.5 (1 EUR costs 4.5 PLN), then 1 PLN = 1/4.5 EUR\n const sellRate = parseFloat(rateData.sell)\n results.push({\n fromCurrencyCode: this.providerBaseCurrency,\n toCurrencyCode: rateData.code,\n rate: (1 / sellRate).toString(),\n source: this.source,\n date: rateDate,\n type: 'sell', // Bank sells foreign currency (from their perspective)\n })\n\n // Rate 2: XXX \u2192 PLN (using BUY) - this is when bank BUYS foreign currency\n // If buy = 4.3 (1 EUR gives 4.3 PLN), then 1 EUR = 4.3 PLN\n results.push({\n fromCurrencyCode: rateData.code,\n toCurrencyCode: this.providerBaseCurrency,\n rate: rateData.buy,\n source: this.source,\n date: rateDate,\n type: 'buy', // Bank buys foreign currency (from their perspective)\n })\n }\n\n console.log(\n `[Raiffeisen] Fetched ${results.length} rates for ${dateStr} at ${firstRate.time} Warsaw time (${rateDate.toISOString()})`\n )\n return results\n } catch (err: any) {\n console.error(`[Raiffeisen] Fetch error for ${dateStr}:`, err)\n throw new Error(`Failed to fetch Raiffeisen rates: ${err.message}`)\n }\n }\n\n private formatDate(date: Date): string {\n return date.toISOString().split('T')[0] // YYYY-MM-DD\n }\n}\n"],
5
- "mappings": "AACA,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB,wBAAwB;AAEnD,MAAM,gCAAgC;AAEtC,SAAS,4BAAoC;AAC3C,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,SAAS,MAAM,OAAO,SAAS,KAAK,EAAE,IAAI;AAChD,SAAO,iBAAiB,QAAQ,6BAA6B;AAC/D;AAuBO,MAAM,yBAAiD;AAAA,EAAvD;AACL,SAAS,OAAO;AAChB,SAAS,SAAS;AAClB,SAAS,uBAAuB;AAEhC,SAAiB,UAAU;AAAA;AAAA,EAE3B,cAAuB;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WACJ,MACA,OACA,qBAC+B;AAE/B,QAAI,CAAC,oBAAoB,IAAI,KAAK,oBAAoB,GAAG;AACvD,cAAQ,MAAM,8DAA8D;AAC5E,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,UAAU,KAAK,WAAW,IAAI;AACpC,UAAM,MAAM,GAAG,KAAK,OAAO,mCAAmC,OAAO;AAErE,QAAI;AACF,YAAM,WAAW,MAAM,iBAAiB,KAAK,EAAE,WAAW,0BAA0B,EAAE,CAAC;AAEvF,UAAI,CAAC,SAAS,IAAI;AAChB,YAAI,SAAS,WAAW,KAAK;AAC3B,kBAAQ,IAAI,sCAAsC,OAAO,EAAE;AAC3D,iBAAO,CAAC;AAAA,QACV;AACA,cAAM,IAAI;AAAA,UACR,yBAAyB,SAAS,MAAM,IAAI,SAAS,UAAU;AAAA,QACjE;AAAA,MACF;AAEA,YAAM,OAA2B,MAAM,SAAS,KAAK;AAErD,UAAI,CAAC,KAAK,SAAS,OAAO,KAAK,KAAK,KAAK,EAAE,WAAW,GAAG;AACvD,eAAO,CAAC;AAAA,MACV;AAGA,YAAM,QAAQ,OAAO,KAAK,KAAK,KAAK,EAAE,KAAK,CAAC,GAAG,MAAO,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAE;AACjF,YAAM,YAAY,MAAM,CAAC;AACzB,YAAM,QAAQ,KAAK,MAAM,SAAS;AAElC,YAAM,UAAgC,CAAC;AAGvC,YAAM,YAAY,MAAM,CAAC;AACzB,UAAI,CAAC,WAAW;AACd,gBAAQ,IAAI,gDAAgD,SAAS,EAAE;AACvE,eAAO,CAAC;AAAA,MACV;AAGA,YAAM,WAAW;AAAA,QACf,GAAG,KAAK,IAAI,IAAI,UAAU,IAAI;AAAA,QAC9B;AAAA,MACF;AAEA,iBAAW,YAAY,OAAO;AAO5B,cAAM,WAAW,WAAW,SAAS,IAAI;AACzC,gBAAQ,KAAK;AAAA,UACX,kBAAkB,KAAK;AAAA,UACvB,gBAAgB,SAAS;AAAA,UACzB,OAAO,IAAI,UAAU,SAAS;AAAA,UAC9B,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,QACR,CAAC;AAID,gBAAQ,KAAK;AAAA,UACX,kBAAkB,SAAS;AAAA,UAC3B,gBAAgB,KAAK;AAAA,UACrB,MAAM,SAAS;AAAA,UACf,QAAQ,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA;AAAA,QACR,CAAC;AAAA,MACH;AAEA,cAAQ;AAAA,QACN,wBAAwB,QAAQ,MAAM,cAAc,OAAO,OAAO,UAAU,IAAI,iBAAiB,SAAS,YAAY,CAAC;AAAA,MACzH;AACA,aAAO;AAAA,IACT,SAAS,KAAU;AACjB,cAAQ,MAAM,gCAAgC,OAAO,KAAK,GAAG;AAC7D,YAAM,IAAI,MAAM,qCAAqC,IAAI,OAAO,EAAE;AAAA,IACpE;AAAA,EACF;AAAA,EAEQ,WAAW,MAAoB;AACrC,WAAO,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,EACxC;AACF;",
4
+ "sourcesContent": ["import { RateProvider, RateProviderResult } from './base'\nimport { fromZonedTime } from 'date-fns-tz'\nimport { fetchWithTimeout, resolveTimeoutMs } from '@open-mercato/shared/lib/http/fetchWithTimeout'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('currencies').child({ component: 'raiffeisen' })\n\nconst DEFAULT_RATE_FETCH_TIMEOUT_MS = 15_000\n\nfunction resolveRateFetchTimeoutMs(): number {\n const raw = process.env.CURRENCY_RATE_FETCH_TIMEOUT_MS\n const parsed = raw ? Number.parseInt(raw, 10) : undefined\n return resolveTimeoutMs(parsed, DEFAULT_RATE_FETCH_TIMEOUT_MS)\n}\n\ninterface RaiffeisenResponse {\n date: string\n rates: Record<\n string,\n Array<{\n code: string\n units: number\n buy: string\n sell: string\n spread: string\n date: string\n time: string\n }>\n >\n range: {\n minRateDate: string\n maxRateDate: string\n }\n}\n\n// \nexport class RaiffeisenPolandProvider implements RateProvider {\n readonly name = 'Raiffeisen Bank Polska'\n readonly source = 'Raiffeisen Bank Polska'\n readonly providerBaseCurrency = 'PLN'\n\n private readonly baseUrl = 'https://www.rbinternational.com.pl/rest/rates/'\n\n isAvailable(): boolean {\n return true\n }\n\n async fetchRates(\n date: Date,\n scope: { tenantId: string; organizationId: string },\n availableCurrencies: Set<string>\n ): Promise<RateProviderResult[]> {\n // Check if PLN is available (required as base currency for Raiffeisen)\n if (!availableCurrencies.has(this.providerBaseCurrency)) {\n logger.debug('Skipping: PLN not found in available currencies')\n return []\n }\n\n const dateStr = this.formatDate(date)\n const url = `${this.baseUrl}?type=kursywalut&range=all&date=${dateStr}`\n\n try {\n const response = await fetchWithTimeout(url, { timeoutMs: resolveRateFetchTimeoutMs() })\n\n if (!response.ok) {\n if (response.status === 404) {\n logger.debug('No data available', { date: dateStr })\n return []\n }\n throw new Error(\n `Raiffeisen API error: ${response.status} ${response.statusText}`\n )\n }\n\n const data: RaiffeisenResponse = await response.json()\n\n if (!data.rates || Object.keys(data.rates).length === 0) {\n return []\n }\n\n // Get FIRST time slot (opening rates)\n const times = Object.keys(data.rates).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))\n const firstTime = times[0]\n const rates = data.rates[firstTime]\n\n const results: RateProviderResult[] = []\n \n // Extract time from first rate entry (all rates in same time slot have same time)\n const firstRate = rates[0]\n if (!firstRate) {\n logger.debug('No rates available in time slot', { timeSlot: firstTime })\n return []\n }\n\n // Combine date + time and parse as Europe/Warsaw timezone\n const rateDate = fromZonedTime(\n `${data.date} ${firstRate.time}`,\n 'Europe/Warsaw'\n )\n\n for (const rateData of rates) {\n // Raiffeisen rates are from bank's perspective:\n // - SELL: bank sells XXX for PLN \u2192 1 XXX = sell PLN\n // - BUY: bank buys XXX for PLN \u2192 1 XXX = buy PLN\n \n // Rate 1: PLN \u2192 XXX (inverse of SELL) - this is when bank SELLS foreign currency\n // If sell = 4.5 (1 EUR costs 4.5 PLN), then 1 PLN = 1/4.5 EUR\n const sellRate = parseFloat(rateData.sell)\n results.push({\n fromCurrencyCode: this.providerBaseCurrency,\n toCurrencyCode: rateData.code,\n rate: (1 / sellRate).toString(),\n source: this.source,\n date: rateDate,\n type: 'sell', // Bank sells foreign currency (from their perspective)\n })\n\n // Rate 2: XXX \u2192 PLN (using BUY) - this is when bank BUYS foreign currency\n // If buy = 4.3 (1 EUR gives 4.3 PLN), then 1 EUR = 4.3 PLN\n results.push({\n fromCurrencyCode: rateData.code,\n toCurrencyCode: this.providerBaseCurrency,\n rate: rateData.buy,\n source: this.source,\n date: rateDate,\n type: 'buy', // Bank buys foreign currency (from their perspective)\n })\n }\n\n logger.info('Fetched rates', { count: results.length, date: dateStr, time: firstRate.time, rateDate: rateDate.toISOString() })\n return results\n } catch (err: any) {\n logger.error('Fetch error', { date: dateStr, err })\n throw new Error(`Failed to fetch Raiffeisen rates: ${err.message}`)\n }\n }\n\n private formatDate(date: Date): string {\n return date.toISOString().split('T')[0] // YYYY-MM-DD\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -7,8 +7,9 @@ import {
7
7
  checkAuthRateLimit,
8
8
  domainResolveAllIpRateLimitConfig
9
9
  } from "@open-mercato/core/modules/customer_accounts/lib/rateLimiter";
10
+ import { createLogger } from "@open-mercato/shared/lib/logger";
11
+ const logger = createLogger("customer_accounts").child({ component: "domain-resolve-all" });
10
12
  const ORIGIN_HEADER_NAME = process.env.CUSTOMER_DOMAIN_ORIGIN_HEADER ?? "X-Open-Mercato-Origin";
11
- const LOG_PREFIX = "[domain-resolve/all]";
12
13
  const ENDPOINT_PATH = "/api/customer_accounts/domain-resolve/all";
13
14
  const metadata = {
14
15
  GET: { requireAuth: false }
@@ -31,7 +32,7 @@ async function GET(req) {
31
32
  const callerIp = readCallerIp(req);
32
33
  const expected = process.env.DOMAIN_RESOLVE_SECRET;
33
34
  if (!expected) {
34
- console.warn(`${LOG_PREFIX} rejected request \u2014 secret not configured`, {
35
+ logger.warn("Rejected request \u2014 secret not configured", {
35
36
  endpoint: ENDPOINT_PATH,
36
37
  ip: callerIp,
37
38
  outcome: "misconfigured"
@@ -48,7 +49,7 @@ async function GET(req) {
48
49
  ipConfig: domainResolveAllIpRateLimitConfig
49
50
  });
50
51
  if (rateLimitError) {
51
- console.warn(`${LOG_PREFIX} rate-limited`, {
52
+ logger.warn("Rate-limited", {
52
53
  endpoint: ENDPOINT_PATH,
53
54
  ip: callerIp,
54
55
  outcome: "rate_limited"
@@ -57,7 +58,7 @@ async function GET(req) {
57
58
  }
58
59
  const supplied = req.headers.get("x-domain-resolve-secret");
59
60
  if (!secretEqual(supplied, expected)) {
60
- console.warn(`${LOG_PREFIX} rejected request \u2014 invalid secret`, {
61
+ logger.warn("Rejected request \u2014 invalid secret", {
61
62
  endpoint: ENDPOINT_PATH,
62
63
  ip: callerIp,
63
64
  outcome: "forbidden"
@@ -67,7 +68,7 @@ async function GET(req) {
67
68
  const container = await createRequestContainer();
68
69
  const service = container.resolve("domainMappingService");
69
70
  const records = await service.resolveAll();
70
- console.info(`${LOG_PREFIX} authorized`, {
71
+ logger.info("Authorized", {
71
72
  endpoint: ENDPOINT_PATH,
72
73
  ip: callerIp,
73
74
  outcome: "ok",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customer_accounts/api/domain-resolve/all.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { secretEqual } from '@open-mercato/core/modules/customer_accounts/lib/secretCompare'\nimport { DomainMappingService } from '@open-mercato/core/modules/customer_accounts/services/domainMappingService'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n domainResolveAllIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\n\nconst ORIGIN_HEADER_NAME = process.env.CUSTOMER_DOMAIN_ORIGIN_HEADER ?? 'X-Open-Mercato-Origin'\nconst LOG_PREFIX = '[domain-resolve/all]'\nconst ENDPOINT_PATH = '/api/customer_accounts/domain-resolve/all'\n\nexport const metadata = {\n GET: { requireAuth: false },\n}\n\nfunction withOriginHeader(response: NextResponse): NextResponse {\n response.headers.set(ORIGIN_HEADER_NAME, '1')\n return response\n}\n\nfunction readCallerIp(req: Request): string {\n const forwardedFor = req.headers.get('x-forwarded-for')\n if (forwardedFor) {\n const firstHop = forwardedFor.split(',')[0]?.trim()\n if (firstHop) return firstHop\n }\n const realIp = req.headers.get('x-real-ip')\n if (realIp && realIp.trim().length > 0) return realIp.trim()\n return 'unknown'\n}\n\nexport async function GET(req: Request) {\n const callerIp = readCallerIp(req)\n const expected = process.env.DOMAIN_RESOLVE_SECRET\n if (!expected) {\n // Fail closed when the gating secret is not configured on the server.\n console.warn(`${LOG_PREFIX} rejected request \u2014 secret not configured`, {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'misconfigured',\n })\n return withOriginHeader(\n NextResponse.json(\n { ok: false, error: 'DOMAIN_RESOLVE_SECRET is not configured on the server' },\n { status: 503 },\n ),\n )\n }\n\n // Rate-limit by caller IP before the secret comparison to make leak-driven\n // enumeration noisy and bounded. Fails closed (returns the helper's 429\n // response) when the limit is exceeded.\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: domainResolveAllIpRateLimitConfig,\n })\n if (rateLimitError) {\n console.warn(`${LOG_PREFIX} rate-limited`, {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'rate_limited',\n })\n return withOriginHeader(rateLimitError)\n }\n\n const supplied = req.headers.get('x-domain-resolve-secret')\n if (!secretEqual(supplied, expected)) {\n console.warn(`${LOG_PREFIX} rejected request \u2014 invalid secret`, {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'forbidden',\n })\n return withOriginHeader(NextResponse.json({ ok: false, error: 'Forbidden' }, { status: 403 }))\n }\n\n const container = await createRequestContainer()\n const service = container.resolve('domainMappingService') as DomainMappingService\n const records = await service.resolveAll()\n console.info(`${LOG_PREFIX} authorized`, {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'ok',\n domains: records.length,\n })\n return withOriginHeader(\n NextResponse.json({\n ok: true,\n domains: records.map((r) => ({\n hostname: r.hostname,\n tenantId: r.tenantId,\n organizationId: r.organizationId,\n orgSlug: r.orgSlug,\n status: r.status,\n })),\n }),\n )\n}\n\nconst errorSchema = z.object({ ok: z.literal(false), error: z.string() })\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'CustomerAccounts',\n summary: 'Batch resolve all active custom domains',\n methods: {\n GET: {\n summary: 'Batch warm-up for the Node middleware',\n description:\n 'Returns every active domain mapping in a single payload so the middleware can populate its cache on process start. Requires X-Domain-Resolve-Secret header.',\n responses: [\n {\n status: 200,\n description: 'OK',\n schema: z.object({\n ok: z.literal(true),\n domains: z.array(\n z.object({\n hostname: z.string(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n orgSlug: z.string().nullable(),\n status: z.literal('active'),\n }),\n ),\n }),\n },\n ],\n errors: [\n { status: 403, description: 'Forbidden', schema: errorSchema },\n { status: 429, description: 'Too many requests', schema: rateLimitErrorSchema },\n { status: 503, description: 'Server misconfiguration', schema: errorSchema },\n ],\n },\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { secretEqual } from '@open-mercato/core/modules/customer_accounts/lib/secretCompare'\nimport { DomainMappingService } from '@open-mercato/core/modules/customer_accounts/services/domainMappingService'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n domainResolveAllIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customer_accounts').child({ component: 'domain-resolve-all' })\n\nconst ORIGIN_HEADER_NAME = process.env.CUSTOMER_DOMAIN_ORIGIN_HEADER ?? 'X-Open-Mercato-Origin'\nconst ENDPOINT_PATH = '/api/customer_accounts/domain-resolve/all'\n\nexport const metadata = {\n GET: { requireAuth: false },\n}\n\nfunction withOriginHeader(response: NextResponse): NextResponse {\n response.headers.set(ORIGIN_HEADER_NAME, '1')\n return response\n}\n\nfunction readCallerIp(req: Request): string {\n const forwardedFor = req.headers.get('x-forwarded-for')\n if (forwardedFor) {\n const firstHop = forwardedFor.split(',')[0]?.trim()\n if (firstHop) return firstHop\n }\n const realIp = req.headers.get('x-real-ip')\n if (realIp && realIp.trim().length > 0) return realIp.trim()\n return 'unknown'\n}\n\nexport async function GET(req: Request) {\n const callerIp = readCallerIp(req)\n const expected = process.env.DOMAIN_RESOLVE_SECRET\n if (!expected) {\n // Fail closed when the gating secret is not configured on the server.\n logger.warn('Rejected request \u2014 secret not configured', {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'misconfigured',\n })\n return withOriginHeader(\n NextResponse.json(\n { ok: false, error: 'DOMAIN_RESOLVE_SECRET is not configured on the server' },\n { status: 503 },\n ),\n )\n }\n\n // Rate-limit by caller IP before the secret comparison to make leak-driven\n // enumeration noisy and bounded. Fails closed (returns the helper's 429\n // response) when the limit is exceeded.\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: domainResolveAllIpRateLimitConfig,\n })\n if (rateLimitError) {\n logger.warn('Rate-limited', {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'rate_limited',\n })\n return withOriginHeader(rateLimitError)\n }\n\n const supplied = req.headers.get('x-domain-resolve-secret')\n if (!secretEqual(supplied, expected)) {\n logger.warn('Rejected request \u2014 invalid secret', {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'forbidden',\n })\n return withOriginHeader(NextResponse.json({ ok: false, error: 'Forbidden' }, { status: 403 }))\n }\n\n const container = await createRequestContainer()\n const service = container.resolve('domainMappingService') as DomainMappingService\n const records = await service.resolveAll()\n logger.info('Authorized', {\n endpoint: ENDPOINT_PATH,\n ip: callerIp,\n outcome: 'ok',\n domains: records.length,\n })\n return withOriginHeader(\n NextResponse.json({\n ok: true,\n domains: records.map((r) => ({\n hostname: r.hostname,\n tenantId: r.tenantId,\n organizationId: r.organizationId,\n orgSlug: r.orgSlug,\n status: r.status,\n })),\n }),\n )\n}\n\nconst errorSchema = z.object({ ok: z.literal(false), error: z.string() })\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'CustomerAccounts',\n summary: 'Batch resolve all active custom domains',\n methods: {\n GET: {\n summary: 'Batch warm-up for the Node middleware',\n description:\n 'Returns every active domain mapping in a single payload so the middleware can populate its cache on process start. Requires X-Domain-Resolve-Secret header.',\n responses: [\n {\n status: 200,\n description: 'OK',\n schema: z.object({\n ok: z.literal(true),\n domains: z.array(\n z.object({\n hostname: z.string(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n orgSlug: z.string().nullable(),\n status: z.literal('active'),\n }),\n ),\n }),\n },\n ],\n errors: [\n { status: 403, description: 'Forbidden', schema: errorSchema },\n { status: 429, description: 'Too many requests', schema: rateLimitErrorSchema },\n { status: 503, description: 'Server misconfiguration', schema: errorSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAE5B,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,mBAAmB,EAAE,MAAM,EAAE,WAAW,qBAAqB,CAAC;AAE1F,MAAM,qBAAqB,QAAQ,IAAI,iCAAiC;AACxE,MAAM,gBAAgB;AAEf,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM;AAC5B;AAEA,SAAS,iBAAiB,UAAsC;AAC9D,WAAS,QAAQ,IAAI,oBAAoB,GAAG;AAC5C,SAAO;AACT;AAEA,SAAS,aAAa,KAAsB;AAC1C,QAAM,eAAe,IAAI,QAAQ,IAAI,iBAAiB;AACtD,MAAI,cAAc;AAChB,UAAM,WAAW,aAAa,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AAClD,QAAI,SAAU,QAAO;AAAA,EACvB;AACA,QAAM,SAAS,IAAI,QAAQ,IAAI,WAAW;AAC1C,MAAI,UAAU,OAAO,KAAK,EAAE,SAAS,EAAG,QAAO,OAAO,KAAK;AAC3D,SAAO;AACT;AAEA,eAAsB,IAAI,KAAc;AACtC,QAAM,WAAW,aAAa,GAAG;AACjC,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,CAAC,UAAU;AAEb,WAAO,KAAK,iDAA4C;AAAA,MACtD,UAAU;AAAA,MACV,IAAI;AAAA,MACJ,SAAS;AAAA,IACX,CAAC;AACD,WAAO;AAAA,MACL,aAAa;AAAA,QACX,EAAE,IAAI,OAAO,OAAO,wDAAwD;AAAA,QAC5E,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAKA,QAAM,EAAE,OAAO,eAAe,IAAI,MAAM,mBAAmB;AAAA,IACzD;AAAA,IACA,UAAU;AAAA,EACZ,CAAC;AACD,MAAI,gBAAgB;AAClB,WAAO,KAAK,gBAAgB;AAAA,MAC1B,UAAU;AAAA,MACV,IAAI;AAAA,MACJ,SAAS;AAAA,IACX,CAAC;AACD,WAAO,iBAAiB,cAAc;AAAA,EACxC;AAEA,QAAM,WAAW,IAAI,QAAQ,IAAI,yBAAyB;AAC1D,MAAI,CAAC,YAAY,UAAU,QAAQ,GAAG;AACpC,WAAO,KAAK,0CAAqC;AAAA,MAC/C,UAAU;AAAA,MACV,IAAI;AAAA,MACJ,SAAS;AAAA,IACX,CAAC;AACD,WAAO,iBAAiB,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,YAAY,GAAG,EAAE,QAAQ,IAAI,CAAC,CAAC;AAAA,EAC/F;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,UAAU,UAAU,QAAQ,sBAAsB;AACxD,QAAM,UAAU,MAAM,QAAQ,WAAW;AACzC,SAAO,KAAK,cAAc;AAAA,IACxB,UAAU;AAAA,IACV,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,SAAS,QAAQ;AAAA,EACnB,CAAC;AACD,SAAO;AAAA,IACL,aAAa,KAAK;AAAA,MAChB,IAAI;AAAA,MACJ,SAAS,QAAQ,IAAI,CAAC,OAAO;AAAA,QAC3B,UAAU,EAAE;AAAA,QACZ,UAAU,EAAE;AAAA,QACZ,gBAAgB,EAAE;AAAA,QAClB,SAAS,EAAE;AAAA,QACX,QAAQ,EAAE;AAAA,MACZ,EAAE;AAAA,IACJ,CAAC;AAAA,EACH;AACF;AAEA,MAAM,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,KAAK,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC;AAEjE,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,aACE;AAAA,MACF,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,EAAE,OAAO;AAAA,YACf,IAAI,EAAE,QAAQ,IAAI;AAAA,YAClB,SAAS,EAAE;AAAA,cACT,EAAE,OAAO;AAAA,gBACP,UAAU,EAAE,OAAO;AAAA,gBACnB,UAAU,EAAE,OAAO,EAAE,KAAK;AAAA,gBAC1B,gBAAgB,EAAE,OAAO,EAAE,KAAK;AAAA,gBAChC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,gBAC7B,QAAQ,EAAE,QAAQ,QAAQ;AAAA,cAC5B,CAAC;AAAA,YACH;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,aAAa,QAAQ,YAAY;AAAA,QAC7D,EAAE,QAAQ,KAAK,aAAa,qBAAqB,QAAQ,qBAAqB;AAAA,QAC9E,EAAE,QAAQ,KAAK,aAAa,2BAA2B,QAAQ,YAAY;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -23,6 +23,8 @@ import {
23
23
  TenantResolutionError
24
24
  } from "@open-mercato/core/modules/customer_accounts/lib/resolveTenantContext";
25
25
  import { urlForCustomerOrg } from "@open-mercato/core/modules/customer_accounts/lib/customerUrl";
26
+ import { createLogger } from "@open-mercato/shared/lib/logger";
27
+ const logger = createLogger("customer_accounts").child({ component: "signup" });
26
28
  const metadata = { requireAuth: false };
27
29
  const TIMING_EQUALIZATION_HASH = "$2b$10$.F2A6UHFzk.d8trNdfqt4OLz05Nf3IOuMmN6VJKflhD4.rz.prR8i";
28
30
  function resolvePortalLoginUrl(baseUrl, organizationSlug) {
@@ -117,7 +119,7 @@ async function POST(req) {
117
119
  subject: subject2,
118
120
  react: CustomerExistingAccountEmail({ loginUrl, copy: copy2 })
119
121
  }).catch((error) => {
120
- console.error("[customer_accounts.signup] existing-account email failed", error);
122
+ logger.error("Existing-account email failed", { err: error });
121
123
  });
122
124
  return NextResponse.json({ ok: true }, { status: 202 });
123
125
  }
@@ -163,7 +165,7 @@ async function POST(req) {
163
165
  subject,
164
166
  react: CustomerSignupVerificationEmail({ verifyUrl, copy })
165
167
  }).catch((error) => {
166
- console.error("[customer_accounts.signup] verification email failed", error);
168
+ logger.error("Verification email failed", { err: error });
167
169
  });
168
170
  void emitCustomerAccountsEvent("customer_accounts.user.created", {
169
171
  id: user.id,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customer_accounts/api/signup.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { compare as bcryptCompare } from 'bcryptjs'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { sendEmail } from '@open-mercato/shared/lib/email/send'\nimport { signupSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CustomerUserService } from '@open-mercato/core/modules/customer_accounts/services/customerUserService'\nimport { CustomerTokenService } from '@open-mercato/core/modules/customer_accounts/services/customerTokenService'\nimport { CustomerRole, CustomerUserRole } from '@open-mercato/core/modules/customer_accounts/data/entities'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport CustomerSignupVerificationEmail from '@open-mercato/core/modules/customer_accounts/emails/CustomerSignupVerificationEmail'\nimport CustomerExistingAccountEmail from '@open-mercato/core/modules/customer_accounts/emails/CustomerExistingAccountEmail'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n customerSignupRateLimitConfig,\n customerSignupIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { readNormalizedEmailFromJsonRequest } from '@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier'\nimport { findOrganizationInTenant } from '@open-mercato/core/modules/customer_accounts/lib/organizationLookup'\nimport { getSecurityEmailBaseUrl, mapSecurityEmailUrlError } from '@open-mercato/shared/lib/url'\nimport {\n resolveTenantContext,\n TenantResolutionError,\n} from '@open-mercato/core/modules/customer_accounts/lib/resolveTenantContext'\nimport { urlForCustomerOrg } from '@open-mercato/core/modules/customer_accounts/lib/customerUrl'\n\nexport const metadata: { path?: string; requireAuth?: boolean } = { requireAuth: false }\n\n// Precomputed bcrypt cost-10 hash of an unknowable random 32-byte input; used to equalize\n// response latency between the existing-user and new-user signup branches so the endpoint's\n// 202-for-both contract is not undone by a timing side channel.\nconst TIMING_EQUALIZATION_HASH = '$2b$10$.F2A6UHFzk.d8trNdfqt4OLz05Nf3IOuMmN6VJKflhD4.rz.prR8i'\nfunction resolvePortalLoginUrl(baseUrl: string, organizationSlug?: string | null): string {\n return organizationSlug\n ? `${baseUrl}/${organizationSlug}/portal/login`\n : `${baseUrl}/portal/login`\n}\n\nfunction resolvePortalVerifyUrl(baseUrl: string, token: string, organizationSlug?: string | null): string {\n const route = organizationSlug\n ? `${baseUrl}/${organizationSlug}/portal/verify`\n : `${baseUrl}/portal/verify`\n return `${route}?token=${encodeURIComponent(token)}`\n}\n\nexport async function POST(req: Request) {\n const rateLimitEmail = await readNormalizedEmailFromJsonRequest(req)\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: customerSignupIpRateLimitConfig,\n compoundConfig: customerSignupRateLimitConfig,\n compoundIdentifier: rateLimitEmail,\n })\n if (rateLimitError) return rateLimitError\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = signupSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n const { email, password, displayName } = parsed.data\n let tenantId: string\n let organizationId: string | null\n try {\n const context = await resolveTenantContext(req, parsed.data.tenantId, {\n organizationId: parsed.data.organizationId ?? null,\n })\n tenantId = context.tenantId\n organizationId = context.organizationId ?? parsed.data.organizationId ?? null\n } catch (err) {\n if (err instanceof TenantResolutionError) {\n return NextResponse.json({ ok: false, error: err.message }, { status: err.status })\n }\n throw err\n }\n if (!organizationId) {\n return NextResponse.json({ ok: false, error: 'organizationId is required' }, { status: 400 })\n }\n\n let baseUrl: string\n try {\n baseUrl = getSecurityEmailBaseUrl(req)\n } catch (error) {\n const mapped = mapSecurityEmailUrlError(error, {\n scope: 'customer_accounts.signup',\n configMessage: 'Customer signup is not configured',\n })\n if (mapped) return NextResponse.json(mapped.body, { status: mapped.status })\n throw error\n }\n\n const container = await createRequestContainer()\n const customerUserService = container.resolve('customerUserService') as CustomerUserService\n const customerTokenService = container.resolve('customerTokenService') as CustomerTokenService\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n const { translate } = await resolveTranslations()\n\n const orgRow = await findOrganizationInTenant(em, organizationId, tenantId)\n if (!orgRow) {\n return NextResponse.json({ ok: false, error: 'Registration could not be completed' }, { status: 400 })\n }\n\n const existing = await customerUserService.findByEmail(email, tenantId)\n if (existing) {\n await bcryptCompare(password, TIMING_EQUALIZATION_HASH)\n const existingOrg = await findOrganizationInTenant(em, existing.organizationId, tenantId)\n // Prefer the org's active custom domain when available; fall back to the\n // platform login URL preserved by `resolvePortalLoginUrl`.\n let loginUrl = resolvePortalLoginUrl(baseUrl, existingOrg?.slug ?? null)\n try {\n loginUrl = await urlForCustomerOrg(existing.organizationId, '/login', { container })\n } catch {\n // Fall back to platform URL on any resolution issue.\n }\n const subject = translate('customer_accounts.signup.existing.subject', 'You already have a portal account')\n const copy = {\n preview: translate('customer_accounts.signup.existing.preview', 'A sign-up attempt was made for an email that already has a portal account.'),\n title: translate('customer_accounts.signup.existing.title', 'You already have a portal account'),\n body: translate(\n 'customer_accounts.signup.existing.body',\n 'A sign-up request was made for this email address. You can sign in with your existing account. If you forgot your password, use the password reset option on the sign-in page.',\n ),\n cta: translate('customer_accounts.signup.existing.cta', 'Open sign-in page'),\n hint: translate(\n 'customer_accounts.signup.existing.hint',\n 'If this was not you, you can ignore this message. No new portal account was created.',\n ),\n }\n\n void sendEmail({\n to: existing.email,\n subject,\n react: CustomerExistingAccountEmail({ loginUrl, copy }),\n }).catch((error) => {\n console.error('[customer_accounts.signup] existing-account email failed', error)\n })\n\n return NextResponse.json({ ok: true }, { status: 202 })\n }\n\n const user = await customerUserService.createUser(email, password, displayName, { tenantId, organizationId })\n\n const defaultRole = await em.findOne(CustomerRole, {\n tenantId,\n isDefault: true,\n deletedAt: null,\n })\n if (defaultRole) {\n const userRole = em.create(CustomerUserRole, {\n user,\n role: defaultRole,\n createdAt: new Date(),\n } as any)\n em.persist(userRole)\n }\n\n await em.persist(user).flush()\n\n const verificationToken = await customerTokenService.createEmailVerification(user.id, tenantId)\n let verifyUrl = resolvePortalVerifyUrl(baseUrl, verificationToken, orgRow.slug)\n try {\n verifyUrl = await urlForCustomerOrg(organizationId, `/verify?token=${encodeURIComponent(verificationToken)}`, {\n container,\n })\n } catch {\n // Fall back to the platform-derived URL on any resolution issue.\n }\n const subject = translate('customer_accounts.signup.created.subject', 'Verify your portal account')\n const copy = {\n preview: translate('customer_accounts.signup.created.preview', 'Verify your portal account to finish sign-up.'),\n title: translate('customer_accounts.signup.created.title', 'Verify your portal account'),\n body: translate(\n 'customer_accounts.signup.created.body',\n 'Your account request was accepted. Confirm your email address to finish setting up portal access.',\n ),\n cta: translate('customer_accounts.signup.created.cta', 'Verify email address'),\n hint: translate(\n 'customer_accounts.signup.created.hint',\n 'This verification link expires in 24 hours. If you did not request this, you can ignore this email.',\n ),\n }\n\n void sendEmail({\n to: user.email,\n subject,\n react: CustomerSignupVerificationEmail({ verifyUrl, copy }),\n }).catch((error) => {\n console.error('[customer_accounts.signup] verification email failed', error)\n })\n\n void emitCustomerAccountsEvent('customer_accounts.user.created', {\n id: user.id,\n email: user.email,\n tenantId,\n organizationId,\n }).catch(() => undefined)\n\n return NextResponse.json({ ok: true }, { status: 202 })\n}\n\nconst signupAcceptedSchema = z.object({ ok: z.literal(true) })\n\nconst errorSchema = z.object({\n ok: z.literal(false),\n error: z.string(),\n})\n\nconst methodDoc: OpenApiMethodDoc = {\n summary: 'Register a new customer account',\n description: 'Accepts a signup request and always returns 202 to prevent account enumeration.',\n tags: ['Customer Authentication'],\n requestBody: {\n schema: signupSchema,\n description: 'Signup payload with email, password, and display name.',\n },\n responses: [\n { status: 202, description: 'Signup accepted', schema: signupAcceptedSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed or invalid request origin', schema: errorSchema },\n { status: 429, description: 'Too many signup attempts', schema: rateLimitErrorSchema },\n { status: 500, description: 'Signup email origin is not configured', schema: errorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n summary: 'Customer account registration',\n description: 'Handles customer self-registration without revealing whether the email already exists.',\n methods: { POST: methodDoc },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { compare as bcryptCompare } from 'bcryptjs'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc, OpenApiMethodDoc } from '@open-mercato/shared/lib/openapi'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { sendEmail } from '@open-mercato/shared/lib/email/send'\nimport { signupSchema } from '@open-mercato/core/modules/customer_accounts/data/validators'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CustomerUserService } from '@open-mercato/core/modules/customer_accounts/services/customerUserService'\nimport { CustomerTokenService } from '@open-mercato/core/modules/customer_accounts/services/customerTokenService'\nimport { CustomerRole, CustomerUserRole } from '@open-mercato/core/modules/customer_accounts/data/entities'\nimport { emitCustomerAccountsEvent } from '@open-mercato/core/modules/customer_accounts/events'\nimport CustomerSignupVerificationEmail from '@open-mercato/core/modules/customer_accounts/emails/CustomerSignupVerificationEmail'\nimport CustomerExistingAccountEmail from '@open-mercato/core/modules/customer_accounts/emails/CustomerExistingAccountEmail'\nimport { rateLimitErrorSchema } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport {\n checkAuthRateLimit,\n customerSignupRateLimitConfig,\n customerSignupIpRateLimitConfig,\n} from '@open-mercato/core/modules/customer_accounts/lib/rateLimiter'\nimport { readNormalizedEmailFromJsonRequest } from '@open-mercato/core/modules/customer_accounts/lib/rateLimitIdentifier'\nimport { findOrganizationInTenant } from '@open-mercato/core/modules/customer_accounts/lib/organizationLookup'\nimport { getSecurityEmailBaseUrl, mapSecurityEmailUrlError } from '@open-mercato/shared/lib/url'\nimport {\n resolveTenantContext,\n TenantResolutionError,\n} from '@open-mercato/core/modules/customer_accounts/lib/resolveTenantContext'\nimport { urlForCustomerOrg } from '@open-mercato/core/modules/customer_accounts/lib/customerUrl'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('customer_accounts').child({ component: 'signup' })\n\nexport const metadata: { path?: string; requireAuth?: boolean } = { requireAuth: false }\n\n// Precomputed bcrypt cost-10 hash of an unknowable random 32-byte input; used to equalize\n// response latency between the existing-user and new-user signup branches so the endpoint's\n// 202-for-both contract is not undone by a timing side channel.\nconst TIMING_EQUALIZATION_HASH = '$2b$10$.F2A6UHFzk.d8trNdfqt4OLz05Nf3IOuMmN6VJKflhD4.rz.prR8i'\nfunction resolvePortalLoginUrl(baseUrl: string, organizationSlug?: string | null): string {\n return organizationSlug\n ? `${baseUrl}/${organizationSlug}/portal/login`\n : `${baseUrl}/portal/login`\n}\n\nfunction resolvePortalVerifyUrl(baseUrl: string, token: string, organizationSlug?: string | null): string {\n const route = organizationSlug\n ? `${baseUrl}/${organizationSlug}/portal/verify`\n : `${baseUrl}/portal/verify`\n return `${route}?token=${encodeURIComponent(token)}`\n}\n\nexport async function POST(req: Request) {\n const rateLimitEmail = await readNormalizedEmailFromJsonRequest(req)\n const { error: rateLimitError } = await checkAuthRateLimit({\n req,\n ipConfig: customerSignupIpRateLimitConfig,\n compoundConfig: customerSignupRateLimitConfig,\n compoundIdentifier: rateLimitEmail,\n })\n if (rateLimitError) return rateLimitError\n\n let body: unknown\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ ok: false, error: 'Invalid request body' }, { status: 400 })\n }\n\n const parsed = signupSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ ok: false, error: 'Validation failed', details: parsed.error.flatten().fieldErrors }, { status: 400 })\n }\n\n const { email, password, displayName } = parsed.data\n let tenantId: string\n let organizationId: string | null\n try {\n const context = await resolveTenantContext(req, parsed.data.tenantId, {\n organizationId: parsed.data.organizationId ?? null,\n })\n tenantId = context.tenantId\n organizationId = context.organizationId ?? parsed.data.organizationId ?? null\n } catch (err) {\n if (err instanceof TenantResolutionError) {\n return NextResponse.json({ ok: false, error: err.message }, { status: err.status })\n }\n throw err\n }\n if (!organizationId) {\n return NextResponse.json({ ok: false, error: 'organizationId is required' }, { status: 400 })\n }\n\n let baseUrl: string\n try {\n baseUrl = getSecurityEmailBaseUrl(req)\n } catch (error) {\n const mapped = mapSecurityEmailUrlError(error, {\n scope: 'customer_accounts.signup',\n configMessage: 'Customer signup is not configured',\n })\n if (mapped) return NextResponse.json(mapped.body, { status: mapped.status })\n throw error\n }\n\n const container = await createRequestContainer()\n const customerUserService = container.resolve('customerUserService') as CustomerUserService\n const customerTokenService = container.resolve('customerTokenService') as CustomerTokenService\n const em = container.resolve('em') as import('@mikro-orm/postgresql').EntityManager\n const { translate } = await resolveTranslations()\n\n const orgRow = await findOrganizationInTenant(em, organizationId, tenantId)\n if (!orgRow) {\n return NextResponse.json({ ok: false, error: 'Registration could not be completed' }, { status: 400 })\n }\n\n const existing = await customerUserService.findByEmail(email, tenantId)\n if (existing) {\n await bcryptCompare(password, TIMING_EQUALIZATION_HASH)\n const existingOrg = await findOrganizationInTenant(em, existing.organizationId, tenantId)\n // Prefer the org's active custom domain when available; fall back to the\n // platform login URL preserved by `resolvePortalLoginUrl`.\n let loginUrl = resolvePortalLoginUrl(baseUrl, existingOrg?.slug ?? null)\n try {\n loginUrl = await urlForCustomerOrg(existing.organizationId, '/login', { container })\n } catch {\n // Fall back to platform URL on any resolution issue.\n }\n const subject = translate('customer_accounts.signup.existing.subject', 'You already have a portal account')\n const copy = {\n preview: translate('customer_accounts.signup.existing.preview', 'A sign-up attempt was made for an email that already has a portal account.'),\n title: translate('customer_accounts.signup.existing.title', 'You already have a portal account'),\n body: translate(\n 'customer_accounts.signup.existing.body',\n 'A sign-up request was made for this email address. You can sign in with your existing account. If you forgot your password, use the password reset option on the sign-in page.',\n ),\n cta: translate('customer_accounts.signup.existing.cta', 'Open sign-in page'),\n hint: translate(\n 'customer_accounts.signup.existing.hint',\n 'If this was not you, you can ignore this message. No new portal account was created.',\n ),\n }\n\n void sendEmail({\n to: existing.email,\n subject,\n react: CustomerExistingAccountEmail({ loginUrl, copy }),\n }).catch((error) => {\n logger.error('Existing-account email failed', { err: error })\n })\n\n return NextResponse.json({ ok: true }, { status: 202 })\n }\n\n const user = await customerUserService.createUser(email, password, displayName, { tenantId, organizationId })\n\n const defaultRole = await em.findOne(CustomerRole, {\n tenantId,\n isDefault: true,\n deletedAt: null,\n })\n if (defaultRole) {\n const userRole = em.create(CustomerUserRole, {\n user,\n role: defaultRole,\n createdAt: new Date(),\n } as any)\n em.persist(userRole)\n }\n\n await em.persist(user).flush()\n\n const verificationToken = await customerTokenService.createEmailVerification(user.id, tenantId)\n let verifyUrl = resolvePortalVerifyUrl(baseUrl, verificationToken, orgRow.slug)\n try {\n verifyUrl = await urlForCustomerOrg(organizationId, `/verify?token=${encodeURIComponent(verificationToken)}`, {\n container,\n })\n } catch {\n // Fall back to the platform-derived URL on any resolution issue.\n }\n const subject = translate('customer_accounts.signup.created.subject', 'Verify your portal account')\n const copy = {\n preview: translate('customer_accounts.signup.created.preview', 'Verify your portal account to finish sign-up.'),\n title: translate('customer_accounts.signup.created.title', 'Verify your portal account'),\n body: translate(\n 'customer_accounts.signup.created.body',\n 'Your account request was accepted. Confirm your email address to finish setting up portal access.',\n ),\n cta: translate('customer_accounts.signup.created.cta', 'Verify email address'),\n hint: translate(\n 'customer_accounts.signup.created.hint',\n 'This verification link expires in 24 hours. If you did not request this, you can ignore this email.',\n ),\n }\n\n void sendEmail({\n to: user.email,\n subject,\n react: CustomerSignupVerificationEmail({ verifyUrl, copy }),\n }).catch((error) => {\n logger.error('Verification email failed', { err: error })\n })\n\n void emitCustomerAccountsEvent('customer_accounts.user.created', {\n id: user.id,\n email: user.email,\n tenantId,\n organizationId,\n }).catch(() => undefined)\n\n return NextResponse.json({ ok: true }, { status: 202 })\n}\n\nconst signupAcceptedSchema = z.object({ ok: z.literal(true) })\n\nconst errorSchema = z.object({\n ok: z.literal(false),\n error: z.string(),\n})\n\nconst methodDoc: OpenApiMethodDoc = {\n summary: 'Register a new customer account',\n description: 'Accepts a signup request and always returns 202 to prevent account enumeration.',\n tags: ['Customer Authentication'],\n requestBody: {\n schema: signupSchema,\n description: 'Signup payload with email, password, and display name.',\n },\n responses: [\n { status: 202, description: 'Signup accepted', schema: signupAcceptedSchema },\n ],\n errors: [\n { status: 400, description: 'Validation failed or invalid request origin', schema: errorSchema },\n { status: 429, description: 'Too many signup attempts', schema: rateLimitErrorSchema },\n { status: 500, description: 'Signup email origin is not configured', schema: errorSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n summary: 'Customer account registration',\n description: 'Handles customer self-registration without revealing whether the email already exists.',\n methods: { POST: methodDoc },\n}\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,WAAW,qBAAqB;AACzC,SAAS,SAAS;AAElB,SAAS,2BAA2B;AACpC,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AAGvC,SAAS,cAAc,wBAAwB;AAC/C,SAAS,iCAAiC;AAC1C,OAAO,qCAAqC;AAC5C,OAAO,kCAAkC;AACzC,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,0CAA0C;AACnD,SAAS,gCAAgC;AACzC,SAAS,yBAAyB,gCAAgC;AAClE;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,mBAAmB,EAAE,MAAM,EAAE,WAAW,SAAS,CAAC;AAEvE,MAAM,WAAqD,EAAE,aAAa,MAAM;AAKvF,MAAM,2BAA2B;AACjC,SAAS,sBAAsB,SAAiB,kBAA0C;AACxF,SAAO,mBACH,GAAG,OAAO,IAAI,gBAAgB,kBAC9B,GAAG,OAAO;AAChB;AAEA,SAAS,uBAAuB,SAAiB,OAAe,kBAA0C;AACxG,QAAM,QAAQ,mBACV,GAAG,OAAO,IAAI,gBAAgB,mBAC9B,GAAG,OAAO;AACd,SAAO,GAAG,KAAK,UAAU,mBAAmB,KAAK,CAAC;AACpD;AAEA,eAAsB,KAAK,KAAc;AACvC,QAAM,iBAAiB,MAAM,mCAAmC,GAAG;AACnE,QAAM,EAAE,OAAO,eAAe,IAAI,MAAM,mBAAmB;AAAA,IACzD;AAAA,IACA,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,oBAAoB;AAAA,EACtB,CAAC;AACD,MAAI,eAAgB,QAAO;AAE3B,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB,QAAQ;AACN,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,uBAAuB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACxF;AAEA,QAAM,SAAS,aAAa,UAAU,IAAI;AAC1C,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,qBAAqB,SAAS,OAAO,MAAM,QAAQ,EAAE,YAAY,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAClI;AAEA,QAAM,EAAE,OAAO,UAAU,YAAY,IAAI,OAAO;AAChD,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,MAAM,qBAAqB,KAAK,OAAO,KAAK,UAAU;AAAA,MACpE,gBAAgB,OAAO,KAAK,kBAAkB;AAAA,IAChD,CAAC;AACD,eAAW,QAAQ;AACnB,qBAAiB,QAAQ,kBAAkB,OAAO,KAAK,kBAAkB;AAAA,EAC3E,SAAS,KAAK;AACZ,QAAI,eAAe,uBAAuB;AACxC,aAAO,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,IAAI,QAAQ,GAAG,EAAE,QAAQ,IAAI,OAAO,CAAC;AAAA,IACpF;AACA,UAAM;AAAA,EACR;AACA,MAAI,CAAC,gBAAgB;AACnB,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,6BAA6B,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC9F;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,wBAAwB,GAAG;AAAA,EACvC,SAAS,OAAO;AACd,UAAM,SAAS,yBAAyB,OAAO;AAAA,MAC7C,OAAO;AAAA,MACP,eAAe;AAAA,IACjB,CAAC;AACD,QAAI,OAAQ,QAAO,aAAa,KAAK,OAAO,MAAM,EAAE,QAAQ,OAAO,OAAO,CAAC;AAC3E,UAAM;AAAA,EACR;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,sBAAsB,UAAU,QAAQ,qBAAqB;AACnE,QAAM,uBAAuB,UAAU,QAAQ,sBAAsB;AACrE,QAAM,KAAK,UAAU,QAAQ,IAAI;AACjC,QAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAEhD,QAAM,SAAS,MAAM,yBAAyB,IAAI,gBAAgB,QAAQ;AAC1E,MAAI,CAAC,QAAQ;AACX,WAAO,aAAa,KAAK,EAAE,IAAI,OAAO,OAAO,sCAAsC,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACvG;AAEA,QAAM,WAAW,MAAM,oBAAoB,YAAY,OAAO,QAAQ;AACtE,MAAI,UAAU;AACZ,UAAM,cAAc,UAAU,wBAAwB;AACtD,UAAM,cAAc,MAAM,yBAAyB,IAAI,SAAS,gBAAgB,QAAQ;AAGxF,QAAI,WAAW,sBAAsB,SAAS,aAAa,QAAQ,IAAI;AACvE,QAAI;AACF,iBAAW,MAAM,kBAAkB,SAAS,gBAAgB,UAAU,EAAE,UAAU,CAAC;AAAA,IACrF,QAAQ;AAAA,IAER;AACA,UAAMA,WAAU,UAAU,6CAA6C,mCAAmC;AAC1G,UAAMC,QAAO;AAAA,MACX,SAAS,UAAU,6CAA6C,4EAA4E;AAAA,MAC5I,OAAO,UAAU,2CAA2C,mCAAmC;AAAA,MAC/F,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,MACA,KAAK,UAAU,yCAAyC,mBAAmB;AAAA,MAC3E,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,SAAK,UAAU;AAAA,MACb,IAAI,SAAS;AAAA,MACb,SAAAD;AAAA,MACA,OAAO,6BAA6B,EAAE,UAAU,MAAAC,MAAK,CAAC;AAAA,IACxD,CAAC,EAAE,MAAM,CAAC,UAAU;AAClB,aAAO,MAAM,iCAAiC,EAAE,KAAK,MAAM,CAAC;AAAA,IAC9D,CAAC;AAED,WAAO,aAAa,KAAK,EAAE,IAAI,KAAK,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACxD;AAEA,QAAM,OAAO,MAAM,oBAAoB,WAAW,OAAO,UAAU,aAAa,EAAE,UAAU,eAAe,CAAC;AAE5G,QAAM,cAAc,MAAM,GAAG,QAAQ,cAAc;AAAA,IACjD;AAAA,IACA,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AACD,MAAI,aAAa;AACf,UAAM,WAAW,GAAG,OAAO,kBAAkB;AAAA,MAC3C;AAAA,MACA,MAAM;AAAA,MACN,WAAW,oBAAI,KAAK;AAAA,IACtB,CAAQ;AACR,OAAG,QAAQ,QAAQ;AAAA,EACrB;AAEA,QAAM,GAAG,QAAQ,IAAI,EAAE,MAAM;AAE7B,QAAM,oBAAoB,MAAM,qBAAqB,wBAAwB,KAAK,IAAI,QAAQ;AAC9F,MAAI,YAAY,uBAAuB,SAAS,mBAAmB,OAAO,IAAI;AAC9E,MAAI;AACF,gBAAY,MAAM,kBAAkB,gBAAgB,iBAAiB,mBAAmB,iBAAiB,CAAC,IAAI;AAAA,MAC5G;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AACA,QAAM,UAAU,UAAU,4CAA4C,4BAA4B;AAClG,QAAM,OAAO;AAAA,IACX,SAAS,UAAU,4CAA4C,+CAA+C;AAAA,IAC9G,OAAO,UAAU,0CAA0C,4BAA4B;AAAA,IACvF,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,IACF;AAAA,IACA,KAAK,UAAU,wCAAwC,sBAAsB;AAAA,IAC7E,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,OAAK,UAAU;AAAA,IACb,IAAI,KAAK;AAAA,IACT;AAAA,IACA,OAAO,gCAAgC,EAAE,WAAW,KAAK,CAAC;AAAA,EAC5D,CAAC,EAAE,MAAM,CAAC,UAAU;AAClB,WAAO,MAAM,6BAA6B,EAAE,KAAK,MAAM,CAAC;AAAA,EAC1D,CAAC;AAED,OAAK,0BAA0B,kCAAkC;AAAA,IAC/D,IAAI,KAAK;AAAA,IACT,OAAO,KAAK;AAAA,IACZ;AAAA,IACA;AAAA,EACF,CAAC,EAAE,MAAM,MAAM,MAAS;AAExB,SAAO,aAAa,KAAK,EAAE,IAAI,KAAK,GAAG,EAAE,QAAQ,IAAI,CAAC;AACxD;AAEA,MAAM,uBAAuB,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;AAE7D,MAAM,cAAc,EAAE,OAAO;AAAA,EAC3B,IAAI,EAAE,QAAQ,KAAK;AAAA,EACnB,OAAO,EAAE,OAAO;AAClB,CAAC;AAED,MAAM,YAA8B;AAAA,EAClC,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM,CAAC,yBAAyB;AAAA,EAChC,aAAa;AAAA,IACX,QAAQ;AAAA,IACR,aAAa;AAAA,EACf;AAAA,EACA,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,mBAAmB,QAAQ,qBAAqB;AAAA,EAC9E;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,QAAQ,KAAK,aAAa,+CAA+C,QAAQ,YAAY;AAAA,IAC/F,EAAE,QAAQ,KAAK,aAAa,4BAA4B,QAAQ,qBAAqB;AAAA,IACrF,EAAE,QAAQ,KAAK,aAAa,yCAAyC,QAAQ,YAAY;AAAA,EAC3F;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,SAAS;AAAA,EACT,aAAa;AAAA,EACb,SAAS,EAAE,MAAM,UAAU;AAC7B;",
6
6
  "names": ["subject", "copy"]
7
7
  }
@@ -5,6 +5,8 @@ import { CUSTOMER_JWT_AUDIENCE } from "@open-mercato/core/modules/customer_accou
5
5
  import { tryNormalizeHostname } from "@open-mercato/core/modules/customer_accounts/lib/hostname";
6
6
  import { platformDomains } from "@open-mercato/core/modules/customer_accounts/lib/platformDomains";
7
7
  import { validateUserState } from "./customerAuth.js";
8
+ import { createLogger } from "@open-mercato/shared/lib/logger";
9
+ const logger = createLogger("customer_accounts").child({ component: "customer-auth-server" });
8
10
  async function assertSessionStillActive(sessionId) {
9
11
  try {
10
12
  const container = await createRequestContainer();
@@ -66,7 +68,7 @@ async function getCustomerAuthForHost(host) {
66
68
  if (!resolved || resolved.status !== "active") return null;
67
69
  return getCustomerAuthFromCookies({ expectedTenantId: resolved.tenantId });
68
70
  } catch (err) {
69
- console.warn("[customer_accounts] getCustomerAuthForHost: domain resolve failed; falling back to platform cookie", err);
71
+ logger.warn("Domain resolve failed; falling back to platform cookie", { err });
70
72
  return getCustomerAuthFromCookies();
71
73
  }
72
74
  }