@open-mercato/core 0.6.6-develop.6551.1.1511bfa890 → 0.6.6

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 (304) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities.ids.generated.js +0 -1
  3. package/dist/generated/entities.ids.generated.js.map +2 -2
  4. package/dist/generated/entity-fields-registry.js +0 -12
  5. package/dist/generated/entity-fields-registry.js.map +2 -2
  6. package/dist/modules/api_keys/api/keys/route.js +13 -30
  7. package/dist/modules/api_keys/api/keys/route.js.map +2 -2
  8. package/dist/modules/api_keys/cli.js +1 -2
  9. package/dist/modules/api_keys/cli.js.map +2 -2
  10. package/dist/modules/attachments/api/file/[id]/route.js +7 -9
  11. package/dist/modules/attachments/api/file/[id]/route.js.map +2 -2
  12. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +7 -9
  13. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
  14. package/dist/modules/attachments/api/route.js +17 -21
  15. package/dist/modules/attachments/api/route.js.map +2 -2
  16. package/dist/modules/attachments/components/AttachmentContentPreview.js +35 -6
  17. package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
  18. package/dist/modules/audit_logs/backend/audit-logs/page.js +24 -14
  19. package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
  20. package/dist/modules/auth/api/users/route.js +2 -6
  21. package/dist/modules/auth/api/users/route.js.map +2 -2
  22. package/dist/modules/auth/cli.js +2 -3
  23. package/dist/modules/auth/cli.js.map +2 -2
  24. package/dist/modules/configs/lib/upgrade-actions.js +0 -22
  25. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  26. package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js +0 -1
  27. package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js.map +2 -2
  28. package/dist/modules/customer_accounts/api/admin/roles/[id].js +3 -17
  29. package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
  30. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +1 -6
  31. package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
  32. package/dist/modules/customer_accounts/api/portal/users-invite.js +1 -6
  33. package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
  34. package/dist/modules/customer_accounts/services/customerInvitationService.js +0 -1
  35. package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
  36. package/dist/modules/customer_accounts/services/customerRbacService.js +1 -6
  37. package/dist/modules/customer_accounts/services/customerRbacService.js.map +2 -2
  38. package/dist/modules/customer_accounts/widgets/injection-table.js +2 -0
  39. package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
  40. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +1 -7
  41. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  42. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +2 -2
  43. package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +2 -2
  44. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +43 -37
  45. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
  46. package/dist/modules/customers/components/detail/DealDetailTabs.js +35 -23
  47. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
  48. package/dist/modules/customers/components/detail/DetailTabsLayout.js +21 -6
  49. package/dist/modules/customers/components/detail/DetailTabsLayout.js.map +2 -2
  50. package/dist/modules/customers/components/detail/MobilePersonDetail.js +32 -26
  51. package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +2 -2
  52. package/dist/modules/customers/components/detail/PersonDetailTabs.js +39 -29
  53. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  54. package/dist/modules/dashboards/api/roles/widgets/route.js +3 -22
  55. package/dist/modules/dashboards/api/roles/widgets/route.js.map +2 -2
  56. package/dist/modules/dashboards/api/users/widgets/route.js +3 -22
  57. package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
  58. package/dist/modules/dashboards/cli.js +3 -4
  59. package/dist/modules/dashboards/cli.js.map +2 -2
  60. package/dist/modules/dashboards/lib/widgetAssignmentScope.js +1 -9
  61. package/dist/modules/dashboards/lib/widgetAssignmentScope.js.map +2 -2
  62. package/dist/modules/dictionaries/commands/entries.js +14 -7
  63. package/dist/modules/dictionaries/commands/entries.js.map +2 -2
  64. package/dist/modules/dictionaries/commands/entry-operations.js +16 -7
  65. package/dist/modules/dictionaries/commands/entry-operations.js.map +2 -2
  66. package/dist/modules/dictionaries/commands/factory.js +3 -9
  67. package/dist/modules/dictionaries/commands/factory.js.map +2 -2
  68. package/dist/modules/dictionaries/fields/dictionary.js +41 -56
  69. package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
  70. package/dist/modules/directory/utils/organizationScope.js +3 -10
  71. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  72. package/dist/modules/entities/api/records.js +4 -5
  73. package/dist/modules/entities/api/records.js.map +2 -2
  74. package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js +0 -1
  75. package/dist/modules/entities/backend/entities/system/[entityId]/page.meta.js.map +2 -2
  76. package/dist/modules/entities/backend/entities/user/[entityId]/page.js +49 -49
  77. package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
  78. package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js +0 -1
  79. package/dist/modules/entities/backend/entities/user/[entityId]/page.meta.js.map +2 -2
  80. package/dist/modules/entities/cli.js +1 -2
  81. package/dist/modules/entities/cli.js.map +2 -2
  82. package/dist/modules/feature_toggles/api/check/boolean/route.js +14 -0
  83. package/dist/modules/feature_toggles/api/check/boolean/route.js.map +2 -2
  84. package/dist/modules/feature_toggles/defaults.json +0 -8
  85. package/dist/modules/integrations/backend/integrations/[id]/page.js +80 -9
  86. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  87. package/dist/modules/payment_gateways/data/entities.js +0 -45
  88. package/dist/modules/payment_gateways/data/entities.js.map +2 -2
  89. package/dist/modules/payment_gateways/lib/gateway-service.js +38 -173
  90. package/dist/modules/payment_gateways/lib/gateway-service.js.map +3 -3
  91. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +14 -16
  92. package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +2 -2
  93. package/dist/modules/planner/components/AvailabilityRulesEditor.js +30 -18
  94. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  95. package/dist/modules/query_index/api/status.js +8 -2
  96. package/dist/modules/query_index/api/status.js.map +2 -2
  97. package/dist/modules/resources/backend/resources/resources/[id]/page.js +24 -24
  98. package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
  99. package/dist/modules/sales/backend/sales/channels/create/page.js +0 -6
  100. package/dist/modules/sales/backend/sales/channels/create/page.js.map +2 -2
  101. package/dist/modules/sales/backend/sales/channels/create/page.meta.js +0 -2
  102. package/dist/modules/sales/backend/sales/channels/create/page.meta.js.map +2 -2
  103. package/dist/modules/sales/backend/sales/channels/offers/page.js +0 -6
  104. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  105. package/dist/modules/sales/backend/sales/channels/offers/page.meta.js +0 -2
  106. package/dist/modules/sales/backend/sales/channels/offers/page.meta.js.map +2 -2
  107. package/dist/modules/sales/backend/sales/channels/page.js +0 -6
  108. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  109. package/dist/modules/sales/backend/sales/channels/page.meta.js +0 -2
  110. package/dist/modules/sales/backend/sales/channels/page.meta.js.map +2 -2
  111. package/dist/modules/sales/backend/sales/documents/[id]/page.js +4 -6
  112. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  113. package/dist/modules/sales/commands/documents.js +0 -44
  114. package/dist/modules/sales/commands/documents.js.map +2 -2
  115. package/dist/modules/sales/commands/returns.js +27 -2
  116. package/dist/modules/sales/commands/returns.js.map +2 -2
  117. package/dist/modules/sales/components/documents/AddressesSection.js +2 -6
  118. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  119. package/dist/modules/sales/components/documents/ItemsSection.js +0 -1
  120. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  121. package/dist/modules/sales/components/documents/LineItemDialog.js +0 -9
  122. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  123. package/dist/modules/sales/components/documents/SalesDocumentForm.js +3 -51
  124. package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
  125. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +8 -10
  126. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  127. package/dist/modules/sales/components/documents/ShipmentDialog.js +38 -59
  128. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  129. package/dist/modules/sales/lib/shipments/snapshots.js +1 -27
  130. package/dist/modules/sales/lib/shipments/snapshots.js.map +2 -2
  131. package/dist/modules/staff/backend/staff/team-members/[id]/page.js +25 -22
  132. package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
  133. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +14 -12
  134. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  135. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +29 -10
  136. package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +2 -2
  137. package/dist/modules/sync_excel/lib/adapters/customers.js +20 -19
  138. package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
  139. package/dist/modules/sync_excel/lib/parser.js +0 -185
  140. package/dist/modules/sync_excel/lib/parser.js.map +2 -2
  141. package/dist/modules/sync_excel/lib/upload-storage.js +1 -20
  142. package/dist/modules/sync_excel/lib/upload-storage.js.map +2 -2
  143. package/dist/modules/workflows/frontend/checkout-demo/page.js +8 -1
  144. package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
  145. package/dist/modules/workflows/lib/activity-executor.js +1 -1
  146. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  147. package/dist/modules/workflows/lib/find-definition.js +18 -2
  148. package/dist/modules/workflows/lib/find-definition.js.map +2 -2
  149. package/dist/modules/workflows/lib/signal-handler.js +3 -2
  150. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  151. package/dist/modules/workflows/lib/step-handler.js +4 -8
  152. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  153. package/dist/modules/workflows/lib/task-handler.js +3 -5
  154. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  155. package/dist/modules/workflows/lib/timer-handler.js +2 -1
  156. package/dist/modules/workflows/lib/timer-handler.js.map +2 -2
  157. package/dist/modules/workflows/lib/transition-handler.js +5 -13
  158. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  159. package/dist/modules/workflows/lib/workflow-executor.js +11 -9
  160. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  161. package/dist/modules/workflows/migrations/Migration20260715120000.js +68 -0
  162. package/dist/modules/workflows/migrations/Migration20260715120000.js.map +7 -0
  163. package/dist/modules/workflows/migrations/Migration20260716120000.js +24 -0
  164. package/dist/modules/workflows/migrations/Migration20260716120000.js.map +7 -0
  165. package/dist/modules/workflows/workflows.js +2 -0
  166. package/dist/modules/workflows/workflows.js.map +2 -2
  167. package/generated/entities.ids.generated.ts +0 -1
  168. package/generated/entity-fields-registry.ts +0 -12
  169. package/package.json +8 -9
  170. package/src/modules/api_keys/api/keys/route.ts +13 -36
  171. package/src/modules/api_keys/cli.ts +3 -2
  172. package/src/modules/attachments/api/file/[id]/route.ts +7 -11
  173. package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +7 -11
  174. package/src/modules/attachments/api/route.ts +21 -26
  175. package/src/modules/attachments/components/AttachmentContentPreview.tsx +44 -9
  176. package/src/modules/audit_logs/backend/audit-logs/page.tsx +22 -12
  177. package/src/modules/auth/api/users/route.ts +2 -11
  178. package/src/modules/auth/cli.ts +2 -3
  179. package/src/modules/configs/i18n/de.json +1 -5
  180. package/src/modules/configs/i18n/en.json +1 -5
  181. package/src/modules/configs/i18n/es.json +1 -5
  182. package/src/modules/configs/i18n/pl.json +1 -5
  183. package/src/modules/configs/lib/upgrade-actions.ts +0 -24
  184. package/src/modules/customer_accounts/AGENTS.md +6 -8
  185. package/src/modules/customer_accounts/api/admin/roles/[id]/acl.ts +0 -1
  186. package/src/modules/customer_accounts/api/admin/roles/[id].ts +3 -17
  187. package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +1 -6
  188. package/src/modules/customer_accounts/api/portal/users-invite.ts +1 -6
  189. package/src/modules/customer_accounts/services/customerInvitationService.ts +0 -1
  190. package/src/modules/customer_accounts/services/customerRbacService.ts +2 -9
  191. package/src/modules/customer_accounts/widgets/injection-table.ts +2 -0
  192. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +1 -11
  193. package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +2 -6
  194. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +55 -39
  195. package/src/modules/customers/components/detail/DealDetailTabs.tsx +49 -24
  196. package/src/modules/customers/components/detail/DetailTabsLayout.tsx +24 -13
  197. package/src/modules/customers/components/detail/MobilePersonDetail.tsx +31 -25
  198. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +50 -29
  199. package/src/modules/dashboards/api/roles/widgets/route.ts +3 -22
  200. package/src/modules/dashboards/api/users/widgets/route.ts +3 -22
  201. package/src/modules/dashboards/cli.ts +9 -4
  202. package/src/modules/dashboards/lib/widgetAssignmentScope.ts +0 -18
  203. package/src/modules/dictionaries/commands/entries.ts +16 -7
  204. package/src/modules/dictionaries/commands/entry-operations.ts +18 -8
  205. package/src/modules/dictionaries/commands/factory.ts +2 -8
  206. package/src/modules/dictionaries/fields/dictionary.tsx +32 -55
  207. package/src/modules/dictionaries/i18n/de.json +0 -2
  208. package/src/modules/dictionaries/i18n/en.json +0 -2
  209. package/src/modules/dictionaries/i18n/es.json +0 -2
  210. package/src/modules/dictionaries/i18n/pl.json +0 -2
  211. package/src/modules/directory/utils/organizationScope.ts +2 -36
  212. package/src/modules/entities/api/records.ts +7 -5
  213. package/src/modules/entities/backend/entities/system/[entityId]/page.meta.ts +0 -1
  214. package/src/modules/entities/backend/entities/user/[entityId]/page.meta.ts +0 -1
  215. package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +49 -51
  216. package/src/modules/entities/cli.ts +1 -2
  217. package/src/modules/entities/i18n/de.json +0 -34
  218. package/src/modules/entities/i18n/en.json +0 -34
  219. package/src/modules/entities/i18n/es.json +0 -34
  220. package/src/modules/entities/i18n/pl.json +0 -34
  221. package/src/modules/feature_toggles/api/check/boolean/route.ts +15 -0
  222. package/src/modules/feature_toggles/defaults.json +0 -8
  223. package/src/modules/integrations/backend/integrations/[id]/page.tsx +59 -16
  224. package/src/modules/payment_gateways/data/entities.ts +0 -39
  225. package/src/modules/payment_gateways/lib/gateway-service.ts +40 -211
  226. package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +0 -236
  227. package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +20 -14
  228. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +34 -16
  229. package/src/modules/query_index/api/status.ts +8 -2
  230. package/src/modules/resources/backend/resources/resources/[id]/page.tsx +37 -27
  231. package/src/modules/sales/backend/sales/channels/create/page.meta.ts +0 -3
  232. package/src/modules/sales/backend/sales/channels/create/page.tsx +0 -7
  233. package/src/modules/sales/backend/sales/channels/offers/page.meta.ts +0 -3
  234. package/src/modules/sales/backend/sales/channels/offers/page.tsx +0 -7
  235. package/src/modules/sales/backend/sales/channels/page.meta.ts +0 -4
  236. package/src/modules/sales/backend/sales/channels/page.tsx +0 -7
  237. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +5 -7
  238. package/src/modules/sales/commands/documents.ts +0 -65
  239. package/src/modules/sales/commands/returns.ts +32 -2
  240. package/src/modules/sales/components/documents/AddressesSection.tsx +2 -6
  241. package/src/modules/sales/components/documents/ItemsSection.tsx +0 -5
  242. package/src/modules/sales/components/documents/LineItemDialog.tsx +0 -10
  243. package/src/modules/sales/components/documents/SalesDocumentForm.tsx +3 -53
  244. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +8 -10
  245. package/src/modules/sales/components/documents/ShipmentDialog.tsx +40 -65
  246. package/src/modules/sales/i18n/de.json +0 -5
  247. package/src/modules/sales/i18n/en.json +0 -5
  248. package/src/modules/sales/i18n/es.json +0 -5
  249. package/src/modules/sales/i18n/pl.json +0 -5
  250. package/src/modules/sales/lib/shipments/snapshots.ts +0 -30
  251. package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +34 -25
  252. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +17 -11
  253. package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +28 -11
  254. package/src/modules/sync_excel/lib/adapters/customers.ts +22 -20
  255. package/src/modules/sync_excel/lib/parser.ts +0 -245
  256. package/src/modules/sync_excel/lib/upload-storage.ts +1 -23
  257. package/src/modules/workflows/frontend/checkout-demo/page.tsx +12 -1
  258. package/src/modules/workflows/lib/activity-executor.ts +22 -2
  259. package/src/modules/workflows/lib/find-definition.ts +53 -1
  260. package/src/modules/workflows/lib/signal-handler.ts +5 -4
  261. package/src/modules/workflows/lib/step-handler.ts +4 -8
  262. package/src/modules/workflows/lib/task-handler.ts +2 -4
  263. package/src/modules/workflows/lib/timer-handler.ts +3 -2
  264. package/src/modules/workflows/lib/transition-handler.ts +5 -13
  265. package/src/modules/workflows/lib/workflow-executor.ts +11 -8
  266. package/src/modules/workflows/migrations/Migration20260715120000.ts +114 -0
  267. package/src/modules/workflows/migrations/Migration20260716120000.ts +57 -0
  268. package/src/modules/workflows/workflows.ts +2 -0
  269. package/dist/generated/entities/gateway_session_initialization/index.js +0 -23
  270. package/dist/generated/entities/gateway_session_initialization/index.js.map +0 -7
  271. package/dist/modules/attachments/lib/reconcileOrganization.js +0 -110
  272. package/dist/modules/attachments/lib/reconcileOrganization.js.map +0 -7
  273. package/dist/modules/attachments/lib/requestScope.js +0 -10
  274. package/dist/modules/attachments/lib/requestScope.js.map +0 -7
  275. package/dist/modules/auth/api/autologin.js +0 -85
  276. package/dist/modules/auth/api/autologin.js.map +0 -7
  277. package/dist/modules/auth/lib/autologin.js +0 -19
  278. package/dist/modules/auth/lib/autologin.js.map +0 -7
  279. package/dist/modules/customers/components/detail/useDealsAccess.js +0 -16
  280. package/dist/modules/customers/components/detail/useDealsAccess.js.map +0 -7
  281. package/dist/modules/payment_gateways/lib/session-idempotency.js +0 -104
  282. package/dist/modules/payment_gateways/lib/session-idempotency.js.map +0 -7
  283. package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js +0 -11
  284. package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js.map +0 -7
  285. package/dist/modules/sales/components/SalesChannelsDisabledNotice.js +0 -15
  286. package/dist/modules/sales/components/SalesChannelsDisabledNotice.js.map +0 -7
  287. package/dist/modules/sales/components/useSalesChannelsEnabled.js +0 -44
  288. package/dist/modules/sales/components/useSalesChannelsEnabled.js.map +0 -7
  289. package/dist/modules/sales/lib/salesChannelsToggle.js +0 -18
  290. package/dist/modules/sales/lib/salesChannelsToggle.js.map +0 -7
  291. package/dist/modules/sales/lib/salesChannelsToggleId.js +0 -5
  292. package/dist/modules/sales/lib/salesChannelsToggleId.js.map +0 -7
  293. package/generated/entities/gateway_session_initialization/index.ts +0 -10
  294. package/src/modules/attachments/lib/reconcileOrganization.ts +0 -188
  295. package/src/modules/attachments/lib/requestScope.ts +0 -27
  296. package/src/modules/auth/api/autologin.ts +0 -100
  297. package/src/modules/auth/lib/autologin.ts +0 -36
  298. package/src/modules/customers/components/detail/useDealsAccess.ts +0 -19
  299. package/src/modules/payment_gateways/lib/session-idempotency.ts +0 -142
  300. package/src/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.ts +0 -10
  301. package/src/modules/sales/components/SalesChannelsDisabledNotice.tsx +0 -21
  302. package/src/modules/sales/components/useSalesChannelsEnabled.ts +0 -59
  303. package/src/modules/sales/lib/salesChannelsToggle.ts +0 -26
  304. package/src/modules/sales/lib/salesChannelsToggleId.ts +0 -1
@@ -0,0 +1,114 @@
1
+ import { Migration } from '@mikro-orm/migrations'
2
+
3
+ const LEGACY_WORKFLOW_ID = 'workflows.checkout-demo'
4
+ const LEGACY_WORKFLOW_NAME = 'Checkout with Payment Webhook'
5
+ const LEGACY_ACTIVITY_ID = 'reserve_inventory'
6
+ const LEGACY_ACTIVITY_URL = '{{env.INVENTORY_SERVICE_URL}}/api/inventory/reserve'
7
+ const TRANSITIONS_REPLACED_BY_CODE_DEFINITION = [
8
+ 'cart_to_customer_info',
9
+ 'customer_info_to_payment',
10
+ 'confirmation_to_order',
11
+ ] as const
12
+
13
+ /**
14
+ * SQL fragment (for the UPDATE `where` clause) that matches ONLY the exact
15
+ * legacy checkout seed: workflow id, name, version, and the presence of the
16
+ * obsolete `reserve_inventory` `CALL_WEBHOOK` activity with its exact env-based
17
+ * URL. The match is intentionally strict so the repair never touches a row that
18
+ * is not the known-broken seed. A tenant whose persisted row diverges from this
19
+ * fingerprint (renamed, re-versioned, or a different webhook URL) is left
20
+ * untouched — the trade-off is safety over coverage for an unknown variant.
21
+ */
22
+ export function legacyCheckoutPredicate(): string {
23
+ return `
24
+ "wf"."workflow_id" = '${LEGACY_WORKFLOW_ID}'
25
+ and "wf"."workflow_name" = '${LEGACY_WORKFLOW_NAME}'
26
+ and "wf"."version" = 1
27
+ and exists (
28
+ select 1
29
+ from jsonb_array_elements(coalesce("wf"."definition"->'transitions', '[]'::jsonb)) as "transition"("value")
30
+ cross join lateral jsonb_array_elements(coalesce("transition"."value"->'activities', '[]'::jsonb)) as "activity"("value")
31
+ where "activity"."value"->>'activityId' = '${LEGACY_ACTIVITY_ID}'
32
+ and "activity"."value"->>'activityType' = 'CALL_WEBHOOK'
33
+ and "activity"."value"#>>'{config,url}' = '${LEGACY_ACTIVITY_URL}'
34
+ )
35
+ `.trim()
36
+ }
37
+
38
+ /**
39
+ * The exact UPDATE the migration runs. Exported so the DB-level regression test
40
+ * (`__integration__/TC-WF-031`) executes the identical SQL against Postgres,
41
+ * making the jsonb transformation itself — not just its rendered string —
42
+ * the thing under test.
43
+ *
44
+ * It rebuilds the `transitions` array in original order, dropping the
45
+ * `activities` key from exactly the three transitions the maintained code
46
+ * definition made side-effect-free. All other keys (e.g. `preConditions`) and
47
+ * all other transitions — including `confirmation_to_end`, whose remaining
48
+ * activities are internal (`CALL_API`/`SEND_EMAIL`/`EMIT_EVENT`) and never trip
49
+ * the outbound URL guard — are preserved verbatim.
50
+ */
51
+ export function buildLegacyCheckoutRepairSql(): string {
52
+ const strippedTransitionList = TRANSITIONS_REPLACED_BY_CODE_DEFINITION
53
+ .map((id) => `'${id}'`)
54
+ .join(', ')
55
+ return `
56
+ update "workflow_definitions" as "wf"
57
+ set "definition" = jsonb_set(
58
+ "wf"."definition",
59
+ '{transitions}',
60
+ coalesce(
61
+ (
62
+ select jsonb_agg(
63
+ case
64
+ when "transition"."value"->>'transitionId' in (${strippedTransitionList})
65
+ then "transition"."value" - 'activities'
66
+ else "transition"."value"
67
+ end
68
+ order by "transition"."ordinality"
69
+ )
70
+ from jsonb_array_elements(
71
+ coalesce("wf"."definition"->'transitions', '[]'::jsonb)
72
+ ) with ordinality as "transition"("value", "ordinality")
73
+ ),
74
+ '[]'::jsonb
75
+ )
76
+ ),
77
+ "updated_at" = current_timestamp
78
+ where "wf"."code_workflow_id" is null
79
+ and "wf"."deleted_at" is null
80
+ and ${legacyCheckoutPredicate()};
81
+ `.trim()
82
+ }
83
+
84
+ /**
85
+ * Repairs the former seeded checkout demo after it was renamed to the same ID
86
+ * as the code-defined workflow. The DB-first lookup shadows the current code
87
+ * definition, including its obsolete external inventory webhook.
88
+ *
89
+ * The persisted row must remain active because historical and in-flight
90
+ * workflow instances reference it by definition_id — a random UUID the
91
+ * code-registry fallback in find-definition.ts deliberately never substitutes.
92
+ * The migration removes the activity arrays from the three transitions that
93
+ * the maintained code definition intentionally made side-effect-free,
94
+ * preserving the row and all instance references while keeping the demo
95
+ * self-contained. (Fresh installs never had this row; they execute the virtual
96
+ * code definition directly via findDefinitionForInstance.)
97
+ *
98
+ * `confirmation_to_end` is deliberately NOT rebuilt: unlike the three stripped
99
+ * transitions it still holds activities in the maintained code definition, and
100
+ * its legacy-only extra (`emit_order_completed`, an internal `EMIT_EVENT`) is
101
+ * harmless — it emits no external request, so leaving it costs nothing and
102
+ * avoids fragile per-activity surgery that could re-introduce a failure.
103
+ */
104
+ export class Migration20260715120000 extends Migration {
105
+ override async up(): Promise<void> {
106
+ this.addSql(buildLegacyCheckoutRepairSql())
107
+ }
108
+
109
+ override async down(): Promise<void> {
110
+ // Forward-only data repair. The removed demo-only activity payloads cannot
111
+ // be reconstructed safely, and restoring obsolete external webhooks would
112
+ // re-open issue #4179.
113
+ }
114
+ }
@@ -0,0 +1,57 @@
1
+ import { Migration } from '@mikro-orm/migrations'
2
+
3
+ const CODE_WORKFLOW_ID = 'workflows.checkout-demo'
4
+
5
+ /**
6
+ * Retires the persisted checkout-demo seed rows so runtime resolves the
7
+ * maintained CODE definition instead (issue #4211).
8
+ *
9
+ * Background: `workflows.checkout-demo` is now code-defined
10
+ * (`packages/core/src/modules/workflows/workflows.ts`), and only the code
11
+ * definition forwards the cart's line items + shipping/tax adjustments to
12
+ * `POST /api/sales/orders`. But existing tenants still carry a persisted
13
+ * `workflow_definitions` row from the old seed — originally seeded under ids
14
+ * like `checkout_simple_v1` / names like `Simple Checkout Flow` and later
15
+ * `Checkout with Payment Webhook`, then renamed to `workflows.checkout-demo`
16
+ * by Migration20260428102318. Its `create_order` body never sent `lines`, and
17
+ * because `findWorkflowDefinition` resolves the DB row first, that stale row
18
+ * SHADOWS the code definition — so orders come out with zero line items and
19
+ * $0.00 totals. Patching the persisted body is unreliable: the seed's name and
20
+ * body shape vary across historical versions, so a fingerprint on either misses
21
+ * whole cohorts of tenants (the defect QA hit).
22
+ *
23
+ * Instead, soft-delete the seeded rows. This is body/name-agnostic, so it fixes
24
+ * every historical seed variant:
25
+ * - New instances: `findWorkflowDefinition` filters `deleted_at IS NULL`, so
26
+ * the retired row is skipped and the code definition is used (correct body).
27
+ * - In-flight instances: `findDefinitionForInstance` loads the definition by
28
+ * `id` with no soft-delete filter (WorkflowDefinition has no global filter),
29
+ * so instances that reference the row keep resolving and advancing.
30
+ *
31
+ * Scope is limited to `code_workflow_id IS NULL` rows — user customizations of
32
+ * the code definition set `code_workflow_id` and MUST NOT be retired. The
33
+ * `deleted_at IS NULL` guard makes the migration idempotent.
34
+ */
35
+ export function buildRetireSeededCheckoutDemoSql(): string {
36
+ return `
37
+ update "workflow_definitions" as "wf"
38
+ set "deleted_at" = current_timestamp,
39
+ "updated_at" = current_timestamp
40
+ where "wf"."workflow_id" = '${CODE_WORKFLOW_ID}'
41
+ and "wf"."code_workflow_id" is null
42
+ and "wf"."deleted_at" is null;
43
+ `.trim()
44
+ }
45
+
46
+ export class Migration20260716120000 extends Migration {
47
+ override async up(): Promise<void> {
48
+ this.addSql(buildRetireSeededCheckoutDemoSql())
49
+ }
50
+
51
+ override async down(): Promise<void> {
52
+ // Forward-only. Restoring `deleted_at = null` would re-shadow the maintained
53
+ // code definition with the stale seed body and re-introduce zero-line orders
54
+ // (#4211). The code definition supersedes the seed, so there is nothing to
55
+ // restore.
56
+ }
57
+ }
@@ -239,6 +239,8 @@ const checkoutDemo = defineWorkflow({
239
239
  customerEntityId: '{{context.customer.id}}',
240
240
  currencyCode: '{{context.cart.currency}}',
241
241
  placedAt: '{{now}}',
242
+ lines: '{{context.cart.orderLines}}',
243
+ adjustments: '{{context.cart.orderAdjustments}}',
242
244
  grandTotalGrossAmount: '{{context.cart.total}}',
243
245
  },
244
246
  validateTenantMatch: true,
@@ -1,23 +0,0 @@
1
- const id = "id";
2
- const operation_key = "operation_key";
3
- const provider_key = "provider_key";
4
- const claim_token = "claim_token";
5
- const claimed_at = "claimed_at";
6
- const gateway_transaction_id = "gateway_transaction_id";
7
- const organization_id = "organization_id";
8
- const tenant_id = "tenant_id";
9
- const created_at = "created_at";
10
- const updated_at = "updated_at";
11
- export {
12
- claim_token,
13
- claimed_at,
14
- created_at,
15
- gateway_transaction_id,
16
- id,
17
- operation_key,
18
- organization_id,
19
- provider_key,
20
- tenant_id,
21
- updated_at
22
- };
23
- //# sourceMappingURL=index.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../generated/entities/gateway_session_initialization/index.ts"],
4
- "sourcesContent": ["export const id = \"id\";\nexport const operation_key = \"operation_key\";\nexport const provider_key = \"provider_key\";\nexport const claim_token = \"claim_token\";\nexport const claimed_at = \"claimed_at\";\nexport const gateway_transaction_id = \"gateway_transaction_id\";\nexport const organization_id = \"organization_id\";\nexport const tenant_id = \"tenant_id\";\nexport const created_at = \"created_at\";\nexport const updated_at = \"updated_at\";\n"],
5
- "mappings": "AAAO,MAAM,KAAK;AACX,MAAM,gBAAgB;AACtB,MAAM,eAAe;AACrB,MAAM,cAAc;AACpB,MAAM,aAAa;AACnB,MAAM,yBAAyB;AAC/B,MAAM,kBAAkB;AACxB,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,aAAa;",
6
- "names": []
7
- }
@@ -1,110 +0,0 @@
1
- import { createLogger } from "@open-mercato/shared/lib/logger";
2
- import { Attachment } from "../data/entities.js";
3
- const logger = createLogger("attachments").child({ component: "reconcileOrganization" });
4
- const LIBRARY_ENTITY_ID = "attachments:library";
5
- const DEFAULT_BATCH_SIZE = 500;
6
- function readParentOrganizationId(record) {
7
- const raw = record["organization_id"] ?? record["organizationId"];
8
- if (typeof raw === "string" && raw.trim().length) return raw.trim();
9
- return null;
10
- }
11
- function ensureBucket(report, entityId) {
12
- const existing = report.byEntity[entityId];
13
- if (existing) return existing;
14
- const bucket = { scanned: 0, updated: 0, unresolved: 0 };
15
- report.byEntity[entityId] = bucket;
16
- return bucket;
17
- }
18
- async function reconcileAttachmentOrganizations(opts) {
19
- const { em, queryEngine, tenantId } = opts;
20
- const batchSize = opts.batchSize && opts.batchSize > 0 ? opts.batchSize : DEFAULT_BATCH_SIZE;
21
- const report = {
22
- scanned: 0,
23
- updated: 0,
24
- unresolved: 0,
25
- skippedVirtual: 0,
26
- byEntity: {}
27
- };
28
- const rows = await em.getConnection().execute(
29
- "select id, entity_id, record_id, organization_id from attachments where tenant_id = ?",
30
- [tenantId]
31
- );
32
- report.scanned = rows.length;
33
- if (!rows.length) return report;
34
- const groups = /* @__PURE__ */ new Map();
35
- for (const row of rows) {
36
- if (!row.id || !row.entity_id || !row.record_id) continue;
37
- const list = groups.get(row.entity_id) ?? [];
38
- list.push(row);
39
- groups.set(row.entity_id, list);
40
- }
41
- const pendingUpdates = [];
42
- for (const [entityId, group] of groups) {
43
- const bucket = ensureBucket(report, entityId);
44
- bucket.scanned += group.length;
45
- if (entityId === LIBRARY_ENTITY_ID) {
46
- report.skippedVirtual += group.length;
47
- continue;
48
- }
49
- const recordIds = Array.from(
50
- new Set(group.map((row) => row.record_id).filter((value) => !!value))
51
- );
52
- const parentOrgByRecordId = /* @__PURE__ */ new Map();
53
- let resolvable = true;
54
- for (let index = 0; index < recordIds.length; index += batchSize) {
55
- const chunk = recordIds.slice(index, index + batchSize);
56
- try {
57
- const result = await queryEngine.query(entityId, {
58
- fields: ["id", "organization_id"],
59
- filters: { id: chunk.length === 1 ? { $eq: chunk[0] } : { $in: chunk } },
60
- tenantId,
61
- withDeleted: true,
62
- page: { pageSize: Math.max(chunk.length, 1) }
63
- });
64
- for (const item of result.items ?? []) {
65
- const record = item;
66
- const recordId = record.id != null ? String(record.id) : null;
67
- if (!recordId) continue;
68
- parentOrgByRecordId.set(recordId, readParentOrganizationId(record));
69
- }
70
- } catch (error) {
71
- resolvable = false;
72
- logger.warn("org reconcile: cannot resolve parent organization for entity", {
73
- entityId,
74
- error
75
- });
76
- break;
77
- }
78
- }
79
- if (!resolvable) {
80
- bucket.unresolved += group.length;
81
- report.unresolved += group.length;
82
- continue;
83
- }
84
- for (const row of group) {
85
- const target = row.record_id ? parentOrgByRecordId.get(row.record_id) : null;
86
- if (!target) {
87
- bucket.unresolved += 1;
88
- report.unresolved += 1;
89
- continue;
90
- }
91
- if ((row.organization_id ?? null) === target) continue;
92
- pendingUpdates.push({ id: row.id, organizationId: target });
93
- bucket.updated += 1;
94
- report.updated += 1;
95
- }
96
- }
97
- for (let index = 0; index < pendingUpdates.length; index += batchSize) {
98
- const chunk = pendingUpdates.slice(index, index + batchSize);
99
- for (const update of chunk) {
100
- const reference = em.getReference(Attachment, update.id);
101
- reference.organizationId = update.organizationId;
102
- }
103
- await em.flush();
104
- }
105
- return report;
106
- }
107
- export {
108
- reconcileAttachmentOrganizations
109
- };
110
- //# sourceMappingURL=reconcileOrganization.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/modules/attachments/lib/reconcileOrganization.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport { Attachment } from '../data/entities'\n\nconst logger = createLogger('attachments').child({ component: 'reconcileOrganization' })\n\n/**\n * Virtual entity id for library attachments \u2014 these are not attached to a\n * parent record that owns an organization, so there is nothing to reconcile\n * against. They are counted as skipped rather than unresolved.\n */\nconst LIBRARY_ENTITY_ID = 'attachments:library'\n\nconst DEFAULT_BATCH_SIZE = 500\n\nexport type AttachmentOrgReconcileEntityStat = {\n scanned: number\n updated: number\n unresolved: number\n}\n\nexport type AttachmentOrgReconcileReport = {\n scanned: number\n updated: number\n unresolved: number\n skippedVirtual: number\n byEntity: Record<string, AttachmentOrgReconcileEntityStat>\n}\n\ntype AttachmentScanRow = {\n id: string\n entity_id: string | null\n record_id: string | null\n organization_id: string | null\n}\n\nfunction readParentOrganizationId(record: Record<string, unknown>): string | null {\n const raw = record['organization_id'] ?? record['organizationId']\n if (typeof raw === 'string' && raw.trim().length) return raw.trim()\n return null\n}\n\nfunction ensureBucket(\n report: AttachmentOrgReconcileReport,\n entityId: string,\n): AttachmentOrgReconcileEntityStat {\n const existing = report.byEntity[entityId]\n if (existing) return existing\n const bucket: AttachmentOrgReconcileEntityStat = { scanned: 0, updated: 0, unresolved: 0 }\n report.byEntity[entityId] = bucket\n return bucket\n}\n\n/**\n * Reconcile the `organization_id` of existing attachments to the organization\n * of the record they are attached to.\n *\n * Background (#3765): before the upload route became selected-organization\n * aware, a multi-org admin who switched the header organization uploaded files\n * that were silently stored under their *home* organization instead of the\n * selected one (the organization of the parent record). Those rows are now\n * invisible to org-scoped reads and stay orphaned. This heals them forward.\n *\n * The parent record's organization is the ground truth: an attachment is not\n * distinguishable from a legitimately home-org one by looking at the attachment\n * alone. Parent organizations are resolved generically through the Query Engine\n * by `entityId` (works for both base and custom entities, tenant-scoped and\n * organization-agnostic so the parent's real org is returned regardless of\n * which org the caller sits in) \u2014 the same mechanism the attachments module\n * already uses to enrich assignment details.\n *\n * The reconciliation is:\n * - idempotent \u2014 rows already matching their parent are left untouched;\n * - conservative \u2014 when the parent org cannot be resolved (unregistered\n * entity id, hard-deleted parent, parent without an org column) the row is\n * counted as `unresolved` and left as-is rather than guessed at;\n * - tenant-scoped \u2014 it reconciles every attachment in the tenant across all\n * organizations (the whole point is moving rows between orgs).\n *\n * Writes go through the passed `EntityManager` (which the caller runs inside a\n * transaction) so the whole reconciliation commits atomically.\n */\nexport async function reconcileAttachmentOrganizations(opts: {\n em: EntityManager\n queryEngine: QueryEngine\n tenantId: string\n batchSize?: number\n}): Promise<AttachmentOrgReconcileReport> {\n const { em, queryEngine, tenantId } = opts\n const batchSize = opts.batchSize && opts.batchSize > 0 ? opts.batchSize : DEFAULT_BATCH_SIZE\n const report: AttachmentOrgReconcileReport = {\n scanned: 0,\n updated: 0,\n unresolved: 0,\n skippedVirtual: 0,\n byEntity: {},\n }\n\n const rows = (await em.getConnection().execute(\n 'select id, entity_id, record_id, organization_id from attachments where tenant_id = ?',\n [tenantId],\n )) as AttachmentScanRow[]\n report.scanned = rows.length\n if (!rows.length) return report\n\n const groups = new Map<string, AttachmentScanRow[]>()\n for (const row of rows) {\n if (!row.id || !row.entity_id || !row.record_id) continue\n const list = groups.get(row.entity_id) ?? []\n list.push(row)\n groups.set(row.entity_id, list)\n }\n\n const pendingUpdates: Array<{ id: string; organizationId: string }> = []\n\n for (const [entityId, group] of groups) {\n const bucket = ensureBucket(report, entityId)\n bucket.scanned += group.length\n\n if (entityId === LIBRARY_ENTITY_ID) {\n report.skippedVirtual += group.length\n continue\n }\n\n const recordIds = Array.from(\n new Set(group.map((row) => row.record_id).filter((value): value is string => !!value)),\n )\n const parentOrgByRecordId = new Map<string, string | null>()\n let resolvable = true\n\n for (let index = 0; index < recordIds.length; index += batchSize) {\n const chunk = recordIds.slice(index, index + batchSize)\n try {\n const result = await queryEngine.query(entityId as any, {\n fields: ['id', 'organization_id'],\n filters: { id: chunk.length === 1 ? { $eq: chunk[0] } : { $in: chunk } },\n tenantId,\n withDeleted: true,\n page: { pageSize: Math.max(chunk.length, 1) },\n })\n for (const item of result.items ?? []) {\n const record = item as Record<string, unknown>\n const recordId = record.id != null ? String(record.id) : null\n if (!recordId) continue\n parentOrgByRecordId.set(recordId, readParentOrganizationId(record))\n }\n } catch (error) {\n resolvable = false\n logger.warn('org reconcile: cannot resolve parent organization for entity', {\n entityId,\n error,\n })\n break\n }\n }\n\n if (!resolvable) {\n bucket.unresolved += group.length\n report.unresolved += group.length\n continue\n }\n\n for (const row of group) {\n const target = row.record_id ? parentOrgByRecordId.get(row.record_id) : null\n if (!target) {\n bucket.unresolved += 1\n report.unresolved += 1\n continue\n }\n if ((row.organization_id ?? null) === target) continue\n pendingUpdates.push({ id: row.id, organizationId: target })\n bucket.updated += 1\n report.updated += 1\n }\n }\n\n for (let index = 0; index < pendingUpdates.length; index += batchSize) {\n const chunk = pendingUpdates.slice(index, index + batchSize)\n for (const update of chunk) {\n const reference = em.getReference(Attachment, update.id)\n reference.organizationId = update.organizationId\n }\n await em.flush()\n }\n\n return report\n}\n"],
5
- "mappings": "AACA,SAAS,oBAAoB;AAE7B,SAAS,kBAAkB;AAE3B,MAAM,SAAS,aAAa,aAAa,EAAE,MAAM,EAAE,WAAW,wBAAwB,CAAC;AAOvF,MAAM,oBAAoB;AAE1B,MAAM,qBAAqB;AAuB3B,SAAS,yBAAyB,QAAgD;AAChF,QAAM,MAAM,OAAO,iBAAiB,KAAK,OAAO,gBAAgB;AAChE,MAAI,OAAO,QAAQ,YAAY,IAAI,KAAK,EAAE,OAAQ,QAAO,IAAI,KAAK;AAClE,SAAO;AACT;AAEA,SAAS,aACP,QACA,UACkC;AAClC,QAAM,WAAW,OAAO,SAAS,QAAQ;AACzC,MAAI,SAAU,QAAO;AACrB,QAAM,SAA2C,EAAE,SAAS,GAAG,SAAS,GAAG,YAAY,EAAE;AACzF,SAAO,SAAS,QAAQ,IAAI;AAC5B,SAAO;AACT;AA+BA,eAAsB,iCAAiC,MAKb;AACxC,QAAM,EAAE,IAAI,aAAa,SAAS,IAAI;AACtC,QAAM,YAAY,KAAK,aAAa,KAAK,YAAY,IAAI,KAAK,YAAY;AAC1E,QAAM,SAAuC;AAAA,IAC3C,SAAS;AAAA,IACT,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,OAAQ,MAAM,GAAG,cAAc,EAAE;AAAA,IACrC;AAAA,IACA,CAAC,QAAQ;AAAA,EACX;AACA,SAAO,UAAU,KAAK;AACtB,MAAI,CAAC,KAAK,OAAQ,QAAO;AAEzB,QAAM,SAAS,oBAAI,IAAiC;AACpD,aAAW,OAAO,MAAM;AACtB,QAAI,CAAC,IAAI,MAAM,CAAC,IAAI,aAAa,CAAC,IAAI,UAAW;AACjD,UAAM,OAAO,OAAO,IAAI,IAAI,SAAS,KAAK,CAAC;AAC3C,SAAK,KAAK,GAAG;AACb,WAAO,IAAI,IAAI,WAAW,IAAI;AAAA,EAChC;AAEA,QAAM,iBAAgE,CAAC;AAEvE,aAAW,CAAC,UAAU,KAAK,KAAK,QAAQ;AACtC,UAAM,SAAS,aAAa,QAAQ,QAAQ;AAC5C,WAAO,WAAW,MAAM;AAExB,QAAI,aAAa,mBAAmB;AAClC,aAAO,kBAAkB,MAAM;AAC/B;AAAA,IACF;AAEA,UAAM,YAAY,MAAM;AAAA,MACtB,IAAI,IAAI,MAAM,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,OAAO,CAAC,UAA2B,CAAC,CAAC,KAAK,CAAC;AAAA,IACvF;AACA,UAAM,sBAAsB,oBAAI,IAA2B;AAC3D,QAAI,aAAa;AAEjB,aAAS,QAAQ,GAAG,QAAQ,UAAU,QAAQ,SAAS,WAAW;AAChE,YAAM,QAAQ,UAAU,MAAM,OAAO,QAAQ,SAAS;AACtD,UAAI;AACF,cAAM,SAAS,MAAM,YAAY,MAAM,UAAiB;AAAA,UACtD,QAAQ,CAAC,MAAM,iBAAiB;AAAA,UAChC,SAAS,EAAE,IAAI,MAAM,WAAW,IAAI,EAAE,KAAK,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE;AAAA,UACvE;AAAA,UACA,aAAa;AAAA,UACb,MAAM,EAAE,UAAU,KAAK,IAAI,MAAM,QAAQ,CAAC,EAAE;AAAA,QAC9C,CAAC;AACD,mBAAW,QAAQ,OAAO,SAAS,CAAC,GAAG;AACrC,gBAAM,SAAS;AACf,gBAAM,WAAW,OAAO,MAAM,OAAO,OAAO,OAAO,EAAE,IAAI;AACzD,cAAI,CAAC,SAAU;AACf,8BAAoB,IAAI,UAAU,yBAAyB,MAAM,CAAC;AAAA,QACpE;AAAA,MACF,SAAS,OAAO;AACd,qBAAa;AACb,eAAO,KAAK,gEAAgE;AAAA,UAC1E;AAAA,UACA;AAAA,QACF,CAAC;AACD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,YAAY;AACf,aAAO,cAAc,MAAM;AAC3B,aAAO,cAAc,MAAM;AAC3B;AAAA,IACF;AAEA,eAAW,OAAO,OAAO;AACvB,YAAM,SAAS,IAAI,YAAY,oBAAoB,IAAI,IAAI,SAAS,IAAI;AACxE,UAAI,CAAC,QAAQ;AACX,eAAO,cAAc;AACrB,eAAO,cAAc;AACrB;AAAA,MACF;AACA,WAAK,IAAI,mBAAmB,UAAU,OAAQ;AAC9C,qBAAe,KAAK,EAAE,IAAI,IAAI,IAAI,gBAAgB,OAAO,CAAC;AAC1D,aAAO,WAAW;AAClB,aAAO,WAAW;AAAA,IACpB;AAAA,EACF;AAEA,WAAS,QAAQ,GAAG,QAAQ,eAAe,QAAQ,SAAS,WAAW;AACrE,UAAM,QAAQ,eAAe,MAAM,OAAO,QAAQ,SAAS;AAC3D,eAAW,UAAU,OAAO;AAC1B,YAAM,YAAY,GAAG,aAAa,YAAY,OAAO,EAAE;AACvD,gBAAU,iBAAiB,OAAO;AAAA,IACpC;AACA,UAAM,GAAG,MAAM;AAAA,EACjB;AAEA,SAAO;AACT;",
6
- "names": []
7
- }
@@ -1,10 +0,0 @@
1
- import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/directory/utils/organizationScope";
2
- async function resolveAttachmentOrganizationId(container, auth, request) {
3
- if (!auth) return null;
4
- const scope = await resolveOrganizationScopeForRequest({ container, auth, request });
5
- return scope?.selectedId ?? auth.orgId ?? null;
6
- }
7
- export {
8
- resolveAttachmentOrganizationId
9
- };
10
- //# sourceMappingURL=requestScope.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/modules/attachments/lib/requestScope.ts"],
4
- "sourcesContent": ["import type { AwilixContainer } from 'awilix'\nimport type { AuthContext } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\n\n/**\n * Resolve the organization an attachment request should act within.\n *\n * `auth.orgId` alone is NOT selected-organization aware for non-superadmin\n * principals: `applySuperAdminScope` only rewrites `orgId` from the\n * `om_selected_org` cookie for superadmins, so a regular multi-org admin who\n * switches the header organization keeps `auth.orgId` pinned to their own home\n * organization. The CRUD factory and other org-scoped routes derive the active\n * organization via `resolveOrganizationScopeForRequest` (cookie-driven and\n * RBAC-validated for ALL users, falling back to the home org when the selection\n * is absent or inaccessible). Attachments must do the same so uploaded files\n * land under \u2014 and are read back from \u2014 the currently selected organization\n * rather than the uploader's home organization (#3765).\n */\nexport async function resolveAttachmentOrganizationId(\n container: AwilixContainer,\n auth: AuthContext,\n request: Request,\n): Promise<string | null> {\n if (!auth) return null\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request })\n return scope?.selectedId ?? auth.orgId ?? null\n}\n"],
5
- "mappings": "AAEA,SAAS,0CAA0C;AAgBnD,eAAsB,gCACpB,WACA,MACA,SACwB;AACxB,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,QAAQ,MAAM,mCAAmC,EAAE,WAAW,MAAM,QAAQ,CAAC;AACnF,SAAO,OAAO,cAAc,KAAK,SAAS;AAC5C;",
6
- "names": []
7
- }
@@ -1,85 +0,0 @@
1
- import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
2
- import { createLogger } from "@open-mercato/shared/lib/logger";
3
- import { signJwt } from "@open-mercato/shared/lib/auth/jwt";
4
- import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
5
- import { buildSafeRedirectResponse, resolveTrustedRedirectBase } from "@open-mercato/core/modules/auth/lib/requestRedirect";
6
- import { sanitizeRedirectPath } from "@open-mercato/core/modules/auth/lib/safeRedirect";
7
- import { resolveAutoLoginCredentials } from "@open-mercato/core/modules/auth/lib/autologin";
8
- import { emitAuthEvent } from "@open-mercato/core/modules/auth/events";
9
- const metadata = { requireAuth: false };
10
- const accessTokenMaxAgeSeconds = 60 * 60 * 8;
11
- const logger = createLogger("auth").child({ component: "autologin" });
12
- async function GET(req) {
13
- const url = new URL(req.url);
14
- const baseUrl = resolveTrustedRedirectBase(req) ?? url.origin;
15
- const redirectTo = sanitizeRedirectPath(url.searchParams.get("redirect"), baseUrl, "/backend");
16
- const credentials = resolveAutoLoginCredentials();
17
- if (!credentials) {
18
- return buildSafeRedirectResponse(req, "/login");
19
- }
20
- const existing = await getAuthFromRequest(req);
21
- if (existing) {
22
- return buildSafeRedirectResponse(req, redirectTo);
23
- }
24
- const container = await createRequestContainer();
25
- const auth = container.resolve("authService");
26
- let user = null;
27
- if (credentials.tenantId) {
28
- user = await auth.findUserByEmailAndTenant(credentials.email, credentials.tenantId);
29
- } else {
30
- const users = await auth.findUsersByEmail(credentials.email);
31
- user = users.length === 1 ? users[0] : null;
32
- }
33
- const ok = await auth.verifyPassword(user, credentials.password);
34
- if (!user || !ok) {
35
- logger.warn("OM_AUTOLOGIN credentials did not resolve to a single valid user; falling back to login");
36
- return buildSafeRedirectResponse(req, "/login");
37
- }
38
- const resolvedTenantId = credentials.tenantId ?? (user.tenantId ? String(user.tenantId) : null);
39
- const roles = await auth.getUserRoles(user, resolvedTenantId);
40
- await auth.updateLastLoginAt(user);
41
- const expiresAt = new Date(Date.now() + accessTokenMaxAgeSeconds * 1e3);
42
- const { session } = await auth.createSession(user, expiresAt);
43
- const token = signJwt({
44
- sub: String(user.id),
45
- sid: String(session.id),
46
- tenantId: resolvedTenantId,
47
- orgId: user.organizationId ? String(user.organizationId) : null,
48
- email: user.email,
49
- roles
50
- });
51
- void emitAuthEvent("auth.login.success", {
52
- id: String(user.id),
53
- email: user.email,
54
- tenantId: resolvedTenantId,
55
- organizationId: user.organizationId ? String(user.organizationId) : null
56
- }).catch(() => void 0);
57
- const res = buildSafeRedirectResponse(req, redirectTo);
58
- res.cookies.set("auth_token", token, {
59
- httpOnly: true,
60
- path: "/",
61
- sameSite: "lax",
62
- secure: process.env.NODE_ENV === "production",
63
- maxAge: accessTokenMaxAgeSeconds
64
- });
65
- return res;
66
- }
67
- const openApi = {
68
- tag: "Authentication & Accounts",
69
- summary: "Demo autologin",
70
- methods: {
71
- GET: {
72
- summary: "Auto sign-in using env-configured demo credentials",
73
- description: "When OM_AUTOLOGIN_EMAIL / OM_AUTOLOGIN_PASSWORD are configured, signs the visitor in with those credentials and redirects into the app. Intended for single-tenant demo instances only. Falls back to the login page when disabled or misconfigured.",
74
- responses: [
75
- { status: 307, description: "Redirect into the app (or to /login on failure)", mediaType: "text/html" }
76
- ]
77
- }
78
- }
79
- };
80
- export {
81
- GET,
82
- metadata,
83
- openApi
84
- };
85
- //# sourceMappingURL=autologin.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/modules/auth/api/autologin.ts"],
4
- "sourcesContent": ["import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { AuthService } from '@open-mercato/core/modules/auth/services/authService'\nimport { signJwt } from '@open-mercato/shared/lib/auth/jwt'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { buildSafeRedirectResponse, resolveTrustedRedirectBase } from '@open-mercato/core/modules/auth/lib/requestRedirect'\nimport { sanitizeRedirectPath } from '@open-mercato/core/modules/auth/lib/safeRedirect'\nimport { resolveAutoLoginCredentials } from '@open-mercato/core/modules/auth/lib/autologin'\nimport { emitAuthEvent } from '@open-mercato/core/modules/auth/events'\n\nexport const metadata = { requireAuth: false }\n\nconst accessTokenMaxAgeSeconds = 60 * 60 * 8\nconst logger = createLogger('auth').child({ component: 'autologin' })\n\n// Demo-only convenience: when OM_AUTOLOGIN_* credentials are configured, sign the\n// visitor in with those credentials and redirect into the app. Gated entirely\n// behind env vars \u2014 the homepage only routes here when they are set. On any\n// failure (feature off, bad credentials) it falls back to the manual login form\n// so a misconfigured demo can never loop.\nexport async function GET(req: Request) {\n const url = new URL(req.url)\n const baseUrl = resolveTrustedRedirectBase(req) ?? url.origin\n const redirectTo = sanitizeRedirectPath(url.searchParams.get('redirect'), baseUrl, '/backend')\n\n const credentials = resolveAutoLoginCredentials()\n if (!credentials) {\n return buildSafeRedirectResponse(req, '/login')\n }\n\n // Already signed in \u2014 go straight to the app instead of re-issuing a session.\n const existing = await getAuthFromRequest(req)\n if (existing) {\n return buildSafeRedirectResponse(req, redirectTo)\n }\n\n const container = await createRequestContainer()\n const auth = container.resolve<AuthService>('authService')\n\n let user = null\n if (credentials.tenantId) {\n user = await auth.findUserByEmailAndTenant(credentials.email, credentials.tenantId)\n } else {\n const users = await auth.findUsersByEmail(credentials.email)\n user = users.length === 1 ? users[0] : null\n }\n\n const ok = await auth.verifyPassword(user, credentials.password)\n if (!user || !ok) {\n // Misconfigured demo credentials \u2014 never loop; drop to the manual form.\n logger.warn('OM_AUTOLOGIN credentials did not resolve to a single valid user; falling back to login')\n return buildSafeRedirectResponse(req, '/login')\n }\n\n const resolvedTenantId = credentials.tenantId ?? (user.tenantId ? String(user.tenantId) : null)\n const roles = await auth.getUserRoles(user, resolvedTenantId)\n await auth.updateLastLoginAt(user)\n const expiresAt = new Date(Date.now() + accessTokenMaxAgeSeconds * 1000)\n const { session } = await auth.createSession(user, expiresAt)\n const token = signJwt({\n sub: String(user.id),\n sid: String(session.id),\n tenantId: resolvedTenantId,\n orgId: user.organizationId ? String(user.organizationId) : null,\n email: user.email,\n roles,\n })\n void emitAuthEvent('auth.login.success', {\n id: String(user.id),\n email: user.email,\n tenantId: resolvedTenantId,\n organizationId: user.organizationId ? String(user.organizationId) : null,\n }).catch(() => undefined)\n\n const res = buildSafeRedirectResponse(req, redirectTo)\n res.cookies.set('auth_token', token, {\n httpOnly: true,\n path: '/',\n sameSite: 'lax',\n secure: process.env.NODE_ENV === 'production',\n maxAge: accessTokenMaxAgeSeconds,\n })\n return res\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Authentication & Accounts',\n summary: 'Demo autologin',\n methods: {\n GET: {\n summary: 'Auto sign-in using env-configured demo credentials',\n description:\n 'When OM_AUTOLOGIN_EMAIL / OM_AUTOLOGIN_PASSWORD are configured, signs the visitor in with those credentials and redirects into the app. Intended for single-tenant demo instances only. Falls back to the login page when disabled or misconfigured.',\n responses: [\n { status: 307, description: 'Redirect into the app (or to /login on failure)', mediaType: 'text/html' },\n ],\n },\n },\n}\n"],
5
- "mappings": "AACA,SAAS,8BAA8B;AACvC,SAAS,oBAAoB;AAE7B,SAAS,eAAe;AACxB,SAAS,0BAA0B;AACnC,SAAS,2BAA2B,kCAAkC;AACtE,SAAS,4BAA4B;AACrC,SAAS,mCAAmC;AAC5C,SAAS,qBAAqB;AAEvB,MAAM,WAAW,EAAE,aAAa,MAAM;AAE7C,MAAM,2BAA2B,KAAK,KAAK;AAC3C,MAAM,SAAS,aAAa,MAAM,EAAE,MAAM,EAAE,WAAW,YAAY,CAAC;AAOpE,eAAsB,IAAI,KAAc;AACtC,QAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,QAAM,UAAU,2BAA2B,GAAG,KAAK,IAAI;AACvD,QAAM,aAAa,qBAAqB,IAAI,aAAa,IAAI,UAAU,GAAG,SAAS,UAAU;AAE7F,QAAM,cAAc,4BAA4B;AAChD,MAAI,CAAC,aAAa;AAChB,WAAO,0BAA0B,KAAK,QAAQ;AAAA,EAChD;AAGA,QAAM,WAAW,MAAM,mBAAmB,GAAG;AAC7C,MAAI,UAAU;AACZ,WAAO,0BAA0B,KAAK,UAAU;AAAA,EAClD;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,OAAO,UAAU,QAAqB,aAAa;AAEzD,MAAI,OAAO;AACX,MAAI,YAAY,UAAU;AACxB,WAAO,MAAM,KAAK,yBAAyB,YAAY,OAAO,YAAY,QAAQ;AAAA,EACpF,OAAO;AACL,UAAM,QAAQ,MAAM,KAAK,iBAAiB,YAAY,KAAK;AAC3D,WAAO,MAAM,WAAW,IAAI,MAAM,CAAC,IAAI;AAAA,EACzC;AAEA,QAAM,KAAK,MAAM,KAAK,eAAe,MAAM,YAAY,QAAQ;AAC/D,MAAI,CAAC,QAAQ,CAAC,IAAI;AAEhB,WAAO,KAAK,wFAAwF;AACpG,WAAO,0BAA0B,KAAK,QAAQ;AAAA,EAChD;AAEA,QAAM,mBAAmB,YAAY,aAAa,KAAK,WAAW,OAAO,KAAK,QAAQ,IAAI;AAC1F,QAAM,QAAQ,MAAM,KAAK,aAAa,MAAM,gBAAgB;AAC5D,QAAM,KAAK,kBAAkB,IAAI;AACjC,QAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,2BAA2B,GAAI;AACvE,QAAM,EAAE,QAAQ,IAAI,MAAM,KAAK,cAAc,MAAM,SAAS;AAC5D,QAAM,QAAQ,QAAQ;AAAA,IACpB,KAAK,OAAO,KAAK,EAAE;AAAA,IACnB,KAAK,OAAO,QAAQ,EAAE;AAAA,IACtB,UAAU;AAAA,IACV,OAAO,KAAK,iBAAiB,OAAO,KAAK,cAAc,IAAI;AAAA,IAC3D,OAAO,KAAK;AAAA,IACZ;AAAA,EACF,CAAC;AACD,OAAK,cAAc,sBAAsB;AAAA,IACvC,IAAI,OAAO,KAAK,EAAE;AAAA,IAClB,OAAO,KAAK;AAAA,IACZ,UAAU;AAAA,IACV,gBAAgB,KAAK,iBAAiB,OAAO,KAAK,cAAc,IAAI;AAAA,EACtE,CAAC,EAAE,MAAM,MAAM,MAAS;AAExB,QAAM,MAAM,0BAA0B,KAAK,UAAU;AACrD,MAAI,QAAQ,IAAI,cAAc,OAAO;AAAA,IACnC,UAAU;AAAA,IACV,MAAM;AAAA,IACN,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,QAAQ;AAAA,EACV,CAAC;AACD,SAAO;AACT;AAEO,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,EAAE,QAAQ,KAAK,aAAa,mDAAmD,WAAW,YAAY;AAAA,MACxG;AAAA,IACF;AAAA,EACF;AACF;",
6
- "names": []
7
- }
@@ -1,19 +0,0 @@
1
- function readEnvValue(env, key) {
2
- const value = env[key];
3
- return typeof value === "string" ? value.trim() : "";
4
- }
5
- function resolveAutoLoginCredentials(env = process.env) {
6
- const email = readEnvValue(env, "OM_AUTOLOGIN_EMAIL");
7
- const password = env.OM_AUTOLOGIN_PASSWORD ?? "";
8
- if (!email || !password) return null;
9
- const tenantId = readEnvValue(env, "OM_AUTOLOGIN_TENANT");
10
- return { email, password, tenantId: tenantId || null };
11
- }
12
- function isAutoLoginEnabled(env = process.env) {
13
- return resolveAutoLoginCredentials(env) !== null;
14
- }
15
- export {
16
- isAutoLoginEnabled,
17
- resolveAutoLoginCredentials
18
- };
19
- //# sourceMappingURL=autologin.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/modules/auth/lib/autologin.ts"],
4
- "sourcesContent": ["export type AutoLoginCredentials = {\n email: string\n password: string\n tenantId: string | null\n}\n\nfunction readEnvValue(env: Record<string, string | undefined>, key: string): string {\n const value = env[key]\n return typeof value === 'string' ? value.trim() : ''\n}\n\n/**\n * Reads the optional demo-autologin credentials from env. When both\n * `OM_AUTOLOGIN_EMAIL` and `OM_AUTOLOGIN_PASSWORD` are set, the homepage hands\n * unauthenticated visitors to the autologin route which signs them in and drops\n * them into the app. Unset (the default) \u2192 `null` \u2192 normal login flow.\n *\n * `OM_AUTOLOGIN_TENANT` is optional and only needed when the same email exists\n * across multiple tenants. Pure: pass the env bag so it stays testable.\n */\nexport function resolveAutoLoginCredentials(\n env: Record<string, string | undefined> = process.env,\n): AutoLoginCredentials | null {\n const email = readEnvValue(env, 'OM_AUTOLOGIN_EMAIL')\n const password = env.OM_AUTOLOGIN_PASSWORD ?? ''\n if (!email || !password) return null\n const tenantId = readEnvValue(env, 'OM_AUTOLOGIN_TENANT')\n return { email, password, tenantId: tenantId || null }\n}\n\n/** True when demo autologin credentials are configured via env. */\nexport function isAutoLoginEnabled(\n env: Record<string, string | undefined> = process.env,\n): boolean {\n return resolveAutoLoginCredentials(env) !== null\n}\n"],
5
- "mappings": "AAMA,SAAS,aAAa,KAAyC,KAAqB;AAClF,QAAM,QAAQ,IAAI,GAAG;AACrB,SAAO,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI;AACpD;AAWO,SAAS,4BACd,MAA0C,QAAQ,KACrB;AAC7B,QAAM,QAAQ,aAAa,KAAK,oBAAoB;AACpD,QAAM,WAAW,IAAI,yBAAyB;AAC9C,MAAI,CAAC,SAAS,CAAC,SAAU,QAAO;AAChC,QAAM,WAAW,aAAa,KAAK,qBAAqB;AACxD,SAAO,EAAE,OAAO,UAAU,UAAU,YAAY,KAAK;AACvD;AAGO,SAAS,mBACd,MAA0C,QAAQ,KACzC;AACT,SAAO,4BAA4B,GAAG,MAAM;AAC9C;",
6
- "names": []
7
- }
@@ -1,16 +0,0 @@
1
- "use client";
2
- import * as React from "react";
3
- import { useBackendChrome } from "@open-mercato/ui/backend/BackendChromeProvider";
4
- import { hasFeature } from "@open-mercato/shared/security/features";
5
- function useDealsAccess() {
6
- const { payload, isReady } = useBackendChrome();
7
- const canViewDeals = React.useMemo(
8
- () => hasFeature(payload?.grantedFeatures ?? [], "customers.deals.view"),
9
- [payload?.grantedFeatures]
10
- );
11
- return { canViewDeals, isReady };
12
- }
13
- export {
14
- useDealsAccess
15
- };
16
- //# sourceMappingURL=useDealsAccess.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../src/modules/customers/components/detail/useDealsAccess.ts"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useBackendChrome } from '@open-mercato/ui/backend/BackendChromeProvider'\nimport { hasFeature } from '@open-mercato/shared/security/features'\n\nexport type DealsAccess = {\n canViewDeals: boolean\n isReady: boolean\n}\n\nexport function useDealsAccess(): DealsAccess {\n const { payload, isReady } = useBackendChrome()\n const canViewDeals = React.useMemo(\n () => hasFeature(payload?.grantedFeatures ?? [], 'customers.deals.view'),\n [payload?.grantedFeatures],\n )\n return { canViewDeals, isReady }\n}\n"],
5
- "mappings": ";AAEA,YAAY,WAAW;AACvB,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAOpB,SAAS,iBAA8B;AAC5C,QAAM,EAAE,SAAS,QAAQ,IAAI,iBAAiB;AAC9C,QAAM,eAAe,MAAM;AAAA,IACzB,MAAM,WAAW,SAAS,mBAAmB,CAAC,GAAG,sBAAsB;AAAA,IACvE,CAAC,SAAS,eAAe;AAAA,EAC3B;AACA,SAAO,EAAE,cAAc,QAAQ;AACjC;",
6
- "names": []
7
- }
@@ -1,104 +0,0 @@
1
- import { createHash, randomUUID } from "node:crypto";
2
- import { UniqueConstraintViolationException } from "@mikro-orm/core";
3
- import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
4
- import { GatewaySessionInitialization } from "../data/entities.js";
5
- function buildPaymentSessionOperationKey(input) {
6
- const digest = createHash("sha256").update(JSON.stringify([
7
- input.scope.tenantId,
8
- input.scope.organizationId,
9
- input.providerKey,
10
- input.paymentId,
11
- input.idempotencyKey
12
- ])).digest("hex");
13
- return `om-payment-session:${digest}`;
14
- }
15
- async function findPaymentSessionInitialization(em, operationKey, providerKey, scope) {
16
- return findOneWithDecryption(
17
- em.fork(),
18
- GatewaySessionInitialization,
19
- {
20
- operationKey,
21
- providerKey,
22
- organizationId: scope.organizationId,
23
- tenantId: scope.tenantId
24
- },
25
- void 0,
26
- scope
27
- );
28
- }
29
- async function claimPaymentSessionInitialization(em, operationKey, providerKey, scope, claimedAt) {
30
- const claimEm = em.fork();
31
- const claimToken = randomUUID();
32
- const record = claimEm.create(GatewaySessionInitialization, {
33
- operationKey,
34
- providerKey,
35
- claimToken,
36
- claimedAt,
37
- gatewayTransactionId: null,
38
- organizationId: scope.organizationId,
39
- tenantId: scope.tenantId
40
- });
41
- try {
42
- await claimEm.persist(record).flush();
43
- return { id: record.id, claimToken };
44
- } catch (error) {
45
- if (error instanceof UniqueConstraintViolationException) return null;
46
- throw error;
47
- }
48
- }
49
- async function reclaimPaymentSessionInitialization(em, claim, scope, claimedAt, staleBefore) {
50
- const claimToken = randomUUID();
51
- const claimedRows = await em.fork().nativeUpdate(
52
- GatewaySessionInitialization,
53
- {
54
- id: claim.id,
55
- operationKey: claim.operationKey,
56
- providerKey: claim.providerKey,
57
- organizationId: scope.organizationId,
58
- tenantId: scope.tenantId,
59
- gatewayTransactionId: null,
60
- $or: [
61
- { claimToken: null },
62
- { claimedAt: { $lt: staleBefore } }
63
- ]
64
- },
65
- { claimToken, claimedAt, updatedAt: claimedAt }
66
- );
67
- return claimedRows > 0 ? { id: claim.id, claimToken } : null;
68
- }
69
- async function releasePaymentSessionInitialization(em, ownership, scope) {
70
- await em.fork().nativeUpdate(
71
- GatewaySessionInitialization,
72
- {
73
- id: ownership.id,
74
- claimToken: ownership.claimToken,
75
- organizationId: scope.organizationId,
76
- tenantId: scope.tenantId,
77
- gatewayTransactionId: null
78
- },
79
- { claimToken: null, claimedAt: null, updatedAt: /* @__PURE__ */ new Date() }
80
- );
81
- }
82
- async function refreshPaymentSessionInitialization(em, ownership, scope, claimedAt) {
83
- const refreshedRows = await em.fork().nativeUpdate(
84
- GatewaySessionInitialization,
85
- {
86
- id: ownership.id,
87
- claimToken: ownership.claimToken,
88
- organizationId: scope.organizationId,
89
- tenantId: scope.tenantId,
90
- gatewayTransactionId: null
91
- },
92
- { claimedAt, updatedAt: claimedAt }
93
- );
94
- return refreshedRows > 0;
95
- }
96
- export {
97
- buildPaymentSessionOperationKey,
98
- claimPaymentSessionInitialization,
99
- findPaymentSessionInitialization,
100
- reclaimPaymentSessionInitialization,
101
- refreshPaymentSessionInitialization,
102
- releasePaymentSessionInitialization
103
- };
104
- //# sourceMappingURL=session-idempotency.js.map