@open-mercato/core 0.4.7-develop-0a657b411f → 0.4.7-develop-e249d3e7d0

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 (278) hide show
  1. package/dist/generated/entities/carrier_shipment/index.js +37 -0
  2. package/dist/generated/entities/carrier_shipment/index.js.map +7 -0
  3. package/dist/generated/entities/gateway_transaction/index.js +47 -0
  4. package/dist/generated/entities/gateway_transaction/index.js.map +7 -0
  5. package/dist/generated/entities/webhook_processed_event/index.js +17 -0
  6. package/dist/generated/entities/webhook_processed_event/index.js.map +7 -0
  7. package/dist/generated/entities.ids.generated.js +10 -1
  8. package/dist/generated/entities.ids.generated.js.map +2 -2
  9. package/dist/generated/entity-fields-registry.js +6 -0
  10. package/dist/generated/entity-fields-registry.js.map +2 -2
  11. package/dist/modules/data_sync/api/runs/[id]/cancel.js +14 -5
  12. package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
  13. package/dist/modules/data_sync/backend/data-sync/page.meta.js +2 -2
  14. package/dist/modules/data_sync/backend/data-sync/page.meta.js.map +1 -1
  15. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +37 -12
  16. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
  17. package/dist/modules/directory/api/get/tenants/lookup.js +1 -0
  18. package/dist/modules/directory/api/get/tenants/lookup.js.map +2 -2
  19. package/dist/modules/integrations/api/[id]/route.js +38 -11
  20. package/dist/modules/integrations/api/[id]/route.js.map +2 -2
  21. package/dist/modules/integrations/api/logs/route.js +52 -26
  22. package/dist/modules/integrations/api/logs/route.js.map +2 -2
  23. package/dist/modules/integrations/api/route.js +37 -7
  24. package/dist/modules/integrations/api/route.js.map +2 -2
  25. package/dist/modules/integrations/api/umes-read.js +121 -0
  26. package/dist/modules/integrations/api/umes-read.js.map +7 -0
  27. package/dist/modules/integrations/backend/integrations/[id]/page.js +715 -183
  28. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  29. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +30 -9
  30. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
  31. package/dist/modules/integrations/backend/integrations/detail-page-widgets.js +46 -0
  32. package/dist/modules/integrations/backend/integrations/detail-page-widgets.js.map +7 -0
  33. package/dist/modules/integrations/backend/integrations/page.js +78 -62
  34. package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
  35. package/dist/modules/integrations/backend/integrations/page.meta.js +2 -2
  36. package/dist/modules/integrations/backend/integrations/page.meta.js.map +1 -1
  37. package/dist/modules/integrations/setup.js +2 -2
  38. package/dist/modules/integrations/setup.js.map +2 -2
  39. package/dist/modules/payment_gateways/acl.js +12 -0
  40. package/dist/modules/payment_gateways/acl.js.map +7 -0
  41. package/dist/modules/payment_gateways/api/cancel/route.js +55 -0
  42. package/dist/modules/payment_gateways/api/cancel/route.js.map +7 -0
  43. package/dist/modules/payment_gateways/api/capture/route.js +55 -0
  44. package/dist/modules/payment_gateways/api/capture/route.js.map +7 -0
  45. package/dist/modules/payment_gateways/api/interceptors.js +24 -0
  46. package/dist/modules/payment_gateways/api/interceptors.js.map +7 -0
  47. package/dist/modules/payment_gateways/api/openapi.js +5 -0
  48. package/dist/modules/payment_gateways/api/openapi.js.map +7 -0
  49. package/dist/modules/payment_gateways/api/refund/route.js +56 -0
  50. package/dist/modules/payment_gateways/api/refund/route.js.map +7 -0
  51. package/dist/modules/payment_gateways/api/sessions/route.js +74 -0
  52. package/dist/modules/payment_gateways/api/sessions/route.js.map +7 -0
  53. package/dist/modules/payment_gateways/api/status/route.js +66 -0
  54. package/dist/modules/payment_gateways/api/status/route.js.map +7 -0
  55. package/dist/modules/payment_gateways/api/transactions/[id]/route.js +118 -0
  56. package/dist/modules/payment_gateways/api/transactions/[id]/route.js.map +7 -0
  57. package/dist/modules/payment_gateways/api/transactions/route.js +113 -0
  58. package/dist/modules/payment_gateways/api/transactions/route.js.map +7 -0
  59. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +136 -0
  60. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +7 -0
  61. package/dist/modules/payment_gateways/backend/payment-gateways/page.js +496 -0
  62. package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +7 -0
  63. package/dist/modules/payment_gateways/backend/payment-gateways/page.meta.js +23 -0
  64. package/dist/modules/payment_gateways/backend/payment-gateways/page.meta.js.map +7 -0
  65. package/dist/modules/payment_gateways/data/enrichers.js +5 -0
  66. package/dist/modules/payment_gateways/data/enrichers.js.map +7 -0
  67. package/dist/modules/payment_gateways/data/entities.js +131 -0
  68. package/dist/modules/payment_gateways/data/entities.js.map +7 -0
  69. package/dist/modules/payment_gateways/data/validators.js +57 -0
  70. package/dist/modules/payment_gateways/data/validators.js.map +7 -0
  71. package/dist/modules/payment_gateways/di.js +16 -0
  72. package/dist/modules/payment_gateways/di.js.map +7 -0
  73. package/dist/modules/payment_gateways/events.js +21 -0
  74. package/dist/modules/payment_gateways/events.js.map +7 -0
  75. package/dist/modules/payment_gateways/i18n/en.js +6 -0
  76. package/dist/modules/payment_gateways/i18n/en.js.map +7 -0
  77. package/dist/modules/payment_gateways/i18n/pl.js +6 -0
  78. package/dist/modules/payment_gateways/i18n/pl.js.map +7 -0
  79. package/dist/modules/payment_gateways/index.js +9 -0
  80. package/dist/modules/payment_gateways/index.js.map +7 -0
  81. package/dist/modules/payment_gateways/lib/gateway-service.js +378 -0
  82. package/dist/modules/payment_gateways/lib/gateway-service.js.map +7 -0
  83. package/dist/modules/payment_gateways/lib/queue.js +17 -0
  84. package/dist/modules/payment_gateways/lib/queue.js.map +7 -0
  85. package/dist/modules/payment_gateways/lib/status-machine.js +29 -0
  86. package/dist/modules/payment_gateways/lib/status-machine.js.map +7 -0
  87. package/dist/modules/payment_gateways/lib/webhook-processor.js +88 -0
  88. package/dist/modules/payment_gateways/lib/webhook-processor.js.map +7 -0
  89. package/dist/modules/payment_gateways/lib/webhook-utils.js +42 -0
  90. package/dist/modules/payment_gateways/lib/webhook-utils.js.map +7 -0
  91. package/dist/modules/payment_gateways/migrations/Migration20260305122155.js +19 -0
  92. package/dist/modules/payment_gateways/migrations/Migration20260305122155.js.map +7 -0
  93. package/dist/modules/payment_gateways/setup.js +13 -0
  94. package/dist/modules/payment_gateways/setup.js.map +7 -0
  95. package/dist/modules/payment_gateways/widgets/injection-table.js +7 -0
  96. package/dist/modules/payment_gateways/widgets/injection-table.js.map +7 -0
  97. package/dist/modules/payment_gateways/workers/status-poller.js +44 -0
  98. package/dist/modules/payment_gateways/workers/status-poller.js.map +7 -0
  99. package/dist/modules/payment_gateways/workers/webhook-processor.js +20 -0
  100. package/dist/modules/payment_gateways/workers/webhook-processor.js.map +7 -0
  101. package/dist/modules/sales/data/enrichers.js +72 -0
  102. package/dist/modules/sales/data/enrichers.js.map +7 -0
  103. package/dist/modules/sales/lib/makeSalesLineRoute.js +3 -0
  104. package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
  105. package/dist/modules/sales/widgets/injection/payment-gateway-config-field/widget.js +29 -0
  106. package/dist/modules/sales/widgets/injection/payment-gateway-config-field/widget.js.map +7 -0
  107. package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js +23 -0
  108. package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js.map +7 -0
  109. package/dist/modules/sales/widgets/injection-table.js +13 -1
  110. package/dist/modules/sales/widgets/injection-table.js.map +2 -2
  111. package/dist/modules/shipping_carriers/acl.js +10 -0
  112. package/dist/modules/shipping_carriers/acl.js.map +7 -0
  113. package/dist/modules/shipping_carriers/api/cancel/route.js +55 -0
  114. package/dist/modules/shipping_carriers/api/cancel/route.js.map +7 -0
  115. package/dist/modules/shipping_carriers/api/interceptors.js +21 -0
  116. package/dist/modules/shipping_carriers/api/interceptors.js.map +7 -0
  117. package/dist/modules/shipping_carriers/api/openapi.js +5 -0
  118. package/dist/modules/shipping_carriers/api/openapi.js.map +7 -0
  119. package/dist/modules/shipping_carriers/api/rates/route.js +55 -0
  120. package/dist/modules/shipping_carriers/api/rates/route.js.map +7 -0
  121. package/dist/modules/shipping_carriers/api/shipments/route.js +61 -0
  122. package/dist/modules/shipping_carriers/api/shipments/route.js.map +7 -0
  123. package/dist/modules/shipping_carriers/api/tracking/route.js +58 -0
  124. package/dist/modules/shipping_carriers/api/tracking/route.js.map +7 -0
  125. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +119 -0
  126. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +7 -0
  127. package/dist/modules/shipping_carriers/data/enrichers.js +82 -0
  128. package/dist/modules/shipping_carriers/data/enrichers.js.map +7 -0
  129. package/dist/modules/shipping_carriers/data/entities.js +80 -0
  130. package/dist/modules/shipping_carriers/data/entities.js.map +7 -0
  131. package/dist/modules/shipping_carriers/data/validators.js +49 -0
  132. package/dist/modules/shipping_carriers/data/validators.js.map +7 -0
  133. package/dist/modules/shipping_carriers/di.js +15 -0
  134. package/dist/modules/shipping_carriers/di.js.map +7 -0
  135. package/dist/modules/shipping_carriers/events.js +19 -0
  136. package/dist/modules/shipping_carriers/events.js.map +7 -0
  137. package/dist/modules/shipping_carriers/i18n/en.js +11 -0
  138. package/dist/modules/shipping_carriers/i18n/en.js.map +7 -0
  139. package/dist/modules/shipping_carriers/i18n/pl.js +11 -0
  140. package/dist/modules/shipping_carriers/i18n/pl.js.map +7 -0
  141. package/dist/modules/shipping_carriers/index.js +9 -0
  142. package/dist/modules/shipping_carriers/index.js.map +7 -0
  143. package/dist/modules/shipping_carriers/lib/adapter-registry.js +29 -0
  144. package/dist/modules/shipping_carriers/lib/adapter-registry.js.map +7 -0
  145. package/dist/modules/shipping_carriers/lib/adapter.js +1 -0
  146. package/dist/modules/shipping_carriers/lib/adapter.js.map +7 -0
  147. package/dist/modules/shipping_carriers/lib/queue.js +17 -0
  148. package/dist/modules/shipping_carriers/lib/queue.js.map +7 -0
  149. package/dist/modules/shipping_carriers/lib/shipping-service.js +155 -0
  150. package/dist/modules/shipping_carriers/lib/shipping-service.js.map +7 -0
  151. package/dist/modules/shipping_carriers/lib/status-sync.js +37 -0
  152. package/dist/modules/shipping_carriers/lib/status-sync.js.map +7 -0
  153. package/dist/modules/shipping_carriers/migrations/Migration20260305170000.js +16 -0
  154. package/dist/modules/shipping_carriers/migrations/Migration20260305170000.js.map +7 -0
  155. package/dist/modules/shipping_carriers/setup.js +13 -0
  156. package/dist/modules/shipping_carriers/setup.js.map +7 -0
  157. package/dist/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.js +25 -0
  158. package/dist/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.js.map +7 -0
  159. package/dist/modules/shipping_carriers/widgets/injection/tracking-column/widget.js +23 -0
  160. package/dist/modules/shipping_carriers/widgets/injection/tracking-column/widget.js.map +7 -0
  161. package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js +40 -0
  162. package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js.map +7 -0
  163. package/dist/modules/shipping_carriers/widgets/injection-table.js +24 -0
  164. package/dist/modules/shipping_carriers/widgets/injection-table.js.map +7 -0
  165. package/dist/modules/shipping_carriers/workers/status-poller.js +21 -0
  166. package/dist/modules/shipping_carriers/workers/status-poller.js.map +7 -0
  167. package/dist/modules/shipping_carriers/workers/webhook-processor.js +54 -0
  168. package/dist/modules/shipping_carriers/workers/webhook-processor.js.map +7 -0
  169. package/dist/modules/translations/api/get/locales.js +1 -0
  170. package/dist/modules/translations/api/get/locales.js.map +2 -2
  171. package/dist/modules/translations/api/put/locales.js +1 -0
  172. package/dist/modules/translations/api/put/locales.js.map +2 -2
  173. package/generated/entities/carrier_shipment/index.ts +17 -0
  174. package/generated/entities/gateway_transaction/index.ts +22 -0
  175. package/generated/entities/webhook_processed_event/index.ts +7 -0
  176. package/generated/entities.ids.generated.ts +10 -1
  177. package/generated/entity-fields-registry.ts +6 -0
  178. package/jest.config.cjs +1 -0
  179. package/package.json +5 -2
  180. package/src/modules/auth/i18n/de.json +1 -0
  181. package/src/modules/auth/i18n/en.json +1 -0
  182. package/src/modules/auth/i18n/es.json +1 -0
  183. package/src/modules/auth/i18n/pl.json +1 -0
  184. package/src/modules/data_sync/api/runs/[id]/cancel.ts +18 -5
  185. package/src/modules/data_sync/backend/data-sync/page.meta.ts +2 -2
  186. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +50 -12
  187. package/src/modules/directory/api/get/tenants/lookup.ts +1 -0
  188. package/src/modules/integrations/AGENTS.md +31 -0
  189. package/src/modules/integrations/api/[id]/route.ts +38 -11
  190. package/src/modules/integrations/api/logs/route.ts +53 -27
  191. package/src/modules/integrations/api/route.ts +31 -1
  192. package/src/modules/integrations/api/umes-read.ts +177 -0
  193. package/src/modules/integrations/backend/integrations/[id]/page.tsx +902 -202
  194. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +43 -9
  195. package/src/modules/integrations/backend/integrations/detail-page-widgets.ts +74 -0
  196. package/src/modules/integrations/backend/integrations/page.meta.ts +2 -2
  197. package/src/modules/integrations/backend/integrations/page.tsx +65 -54
  198. package/src/modules/integrations/i18n/de.json +15 -0
  199. package/src/modules/integrations/i18n/en.json +15 -0
  200. package/src/modules/integrations/i18n/es.json +15 -0
  201. package/src/modules/integrations/i18n/pl.json +15 -0
  202. package/src/modules/integrations/setup.ts +2 -2
  203. package/src/modules/payment_gateways/acl.ts +8 -0
  204. package/src/modules/payment_gateways/api/cancel/route.ts +56 -0
  205. package/src/modules/payment_gateways/api/capture/route.ts +56 -0
  206. package/src/modules/payment_gateways/api/interceptors.ts +22 -0
  207. package/src/modules/payment_gateways/api/openapi.ts +1 -0
  208. package/src/modules/payment_gateways/api/refund/route.ts +57 -0
  209. package/src/modules/payment_gateways/api/sessions/route.ts +76 -0
  210. package/src/modules/payment_gateways/api/status/route.ts +69 -0
  211. package/src/modules/payment_gateways/api/transactions/[id]/route.ts +123 -0
  212. package/src/modules/payment_gateways/api/transactions/route.ts +120 -0
  213. package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +161 -0
  214. package/src/modules/payment_gateways/backend/payment-gateways/page.meta.ts +19 -0
  215. package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +660 -0
  216. package/src/modules/payment_gateways/data/enrichers.ts +8 -0
  217. package/src/modules/payment_gateways/data/entities.ts +106 -0
  218. package/src/modules/payment_gateways/data/validators.ts +67 -0
  219. package/src/modules/payment_gateways/di.ts +26 -0
  220. package/src/modules/payment_gateways/events.ts +17 -0
  221. package/src/modules/payment_gateways/i18n/de.json +77 -0
  222. package/src/modules/payment_gateways/i18n/en.json +77 -0
  223. package/src/modules/payment_gateways/i18n/en.ts +4 -0
  224. package/src/modules/payment_gateways/i18n/es.json +77 -0
  225. package/src/modules/payment_gateways/i18n/pl.json +77 -0
  226. package/src/modules/payment_gateways/i18n/pl.ts +4 -0
  227. package/src/modules/payment_gateways/index.ts +5 -0
  228. package/src/modules/payment_gateways/lib/gateway-service.ts +486 -0
  229. package/src/modules/payment_gateways/lib/queue.ts +19 -0
  230. package/src/modules/payment_gateways/lib/status-machine.ts +28 -0
  231. package/src/modules/payment_gateways/lib/webhook-processor.ts +133 -0
  232. package/src/modules/payment_gateways/lib/webhook-utils.ts +52 -0
  233. package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +373 -0
  234. package/src/modules/payment_gateways/migrations/Migration20260305122155.ts +20 -0
  235. package/src/modules/payment_gateways/setup.ts +11 -0
  236. package/src/modules/payment_gateways/widgets/injection-table.ts +9 -0
  237. package/src/modules/payment_gateways/workers/status-poller.ts +58 -0
  238. package/src/modules/payment_gateways/workers/webhook-processor.ts +30 -0
  239. package/src/modules/sales/data/enrichers.ts +120 -0
  240. package/src/modules/sales/lib/makeSalesLineRoute.ts +3 -0
  241. package/src/modules/sales/widgets/injection/payment-gateway-config-field/widget.ts +28 -0
  242. package/src/modules/sales/widgets/injection/payment-gateway-status-column/widget.ts +22 -0
  243. package/src/modules/sales/widgets/injection-table.ts +12 -0
  244. package/src/modules/shipping_carriers/acl.ts +6 -0
  245. package/src/modules/shipping_carriers/api/cancel/route.ts +53 -0
  246. package/src/modules/shipping_carriers/api/interceptors.ts +19 -0
  247. package/src/modules/shipping_carriers/api/openapi.ts +1 -0
  248. package/src/modules/shipping_carriers/api/rates/route.ts +53 -0
  249. package/src/modules/shipping_carriers/api/shipments/route.ts +59 -0
  250. package/src/modules/shipping_carriers/api/tracking/route.ts +56 -0
  251. package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +134 -0
  252. package/src/modules/shipping_carriers/data/enrichers.ts +89 -0
  253. package/src/modules/shipping_carriers/data/entities.ts +60 -0
  254. package/src/modules/shipping_carriers/data/validators.ts +48 -0
  255. package/src/modules/shipping_carriers/di.ts +20 -0
  256. package/src/modules/shipping_carriers/events.ts +16 -0
  257. package/src/modules/shipping_carriers/i18n/de.json +7 -0
  258. package/src/modules/shipping_carriers/i18n/en.json +7 -0
  259. package/src/modules/shipping_carriers/i18n/en.ts +7 -0
  260. package/src/modules/shipping_carriers/i18n/es.json +7 -0
  261. package/src/modules/shipping_carriers/i18n/pl.json +7 -0
  262. package/src/modules/shipping_carriers/i18n/pl.ts +7 -0
  263. package/src/modules/shipping_carriers/index.ts +5 -0
  264. package/src/modules/shipping_carriers/lib/adapter-registry.ts +33 -0
  265. package/src/modules/shipping_carriers/lib/adapter.ts +93 -0
  266. package/src/modules/shipping_carriers/lib/queue.ts +19 -0
  267. package/src/modules/shipping_carriers/lib/shipping-service.ts +204 -0
  268. package/src/modules/shipping_carriers/lib/status-sync.ts +38 -0
  269. package/src/modules/shipping_carriers/migrations/Migration20260305170000.ts +14 -0
  270. package/src/modules/shipping_carriers/setup.ts +11 -0
  271. package/src/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.ts +24 -0
  272. package/src/modules/shipping_carriers/widgets/injection/tracking-column/widget.ts +22 -0
  273. package/src/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.tsx +44 -0
  274. package/src/modules/shipping_carriers/widgets/injection-table.ts +22 -0
  275. package/src/modules/shipping_carriers/workers/status-poller.ts +33 -0
  276. package/src/modules/shipping_carriers/workers/webhook-processor.ts +79 -0
  277. package/src/modules/translations/api/get/locales.ts +1 -0
  278. package/src/modules/translations/api/put/locales.ts +1 -0
@@ -0,0 +1,24 @@
1
+ const injectionTable = {
2
+ "data-table:sales.shipments:columns": [
3
+ {
4
+ widgetId: "shipping_carriers.injection.tracking-column",
5
+ priority: 40
6
+ },
7
+ {
8
+ widgetId: "shipping_carriers.injection.tracking-status-badge",
9
+ priority: 45
10
+ }
11
+ ],
12
+ "data-table:sales.orders:row-actions": [
13
+ {
14
+ widgetId: "shipping_carriers.injection.create-shipment-button",
15
+ priority: 30
16
+ }
17
+ ]
18
+ };
19
+ var injection_table_default = injectionTable;
20
+ export {
21
+ injection_table_default as default,
22
+ injectionTable
23
+ };
24
+ //# sourceMappingURL=injection-table.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/shipping_carriers/widgets/injection-table.ts"],
4
+ "sourcesContent": ["import type { ModuleInjectionTable } from '@open-mercato/shared/modules/widgets/injection'\n\nexport const injectionTable: ModuleInjectionTable = {\n 'data-table:sales.shipments:columns': [\n {\n widgetId: 'shipping_carriers.injection.tracking-column',\n priority: 40,\n },\n {\n widgetId: 'shipping_carriers.injection.tracking-status-badge',\n priority: 45,\n },\n ],\n 'data-table:sales.orders:row-actions': [\n {\n widgetId: 'shipping_carriers.injection.create-shipment-button',\n priority: 30,\n },\n ],\n}\n\nexport default injectionTable\n"],
5
+ "mappings": "AAEO,MAAM,iBAAuC;AAAA,EAClD,sCAAsC;AAAA,IACpC;AAAA,MACE,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA,uCAAuC;AAAA,IACrC;AAAA,MACE,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAEA,IAAO,0BAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,21 @@
1
+ const metadata = {
2
+ queue: "shipping-carriers-status-poller",
3
+ id: "shipping-carriers:status-poller",
4
+ concurrency: 2
5
+ };
6
+ async function handle(job, ctx) {
7
+ const service = ctx.resolve("shippingCarrierService");
8
+ for (const shipmentId of job.payload.shipmentIds) {
9
+ await service.getTracking({
10
+ providerKey: job.payload.providerKey,
11
+ shipmentId,
12
+ organizationId: job.payload.scope.organizationId,
13
+ tenantId: job.payload.scope.tenantId
14
+ });
15
+ }
16
+ }
17
+ export {
18
+ handle as default,
19
+ metadata
20
+ };
21
+ //# sourceMappingURL=status-poller.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/shipping_carriers/workers/status-poller.ts"],
4
+ "sourcesContent": ["import type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { ShippingCarrierService } from '../lib/shipping-service'\n\ntype PollerJobPayload = {\n providerKey: string\n shipmentIds: string[]\n scope: {\n organizationId: string\n tenantId: string\n }\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport const metadata: WorkerMeta = {\n queue: 'shipping-carriers-status-poller',\n id: 'shipping-carriers:status-poller',\n concurrency: 2,\n}\n\nexport default async function handle(job: QueuedJob<PollerJobPayload>, ctx: HandlerContext): Promise<void> {\n const service = ctx.resolve<ShippingCarrierService>('shippingCarrierService')\n for (const shipmentId of job.payload.shipmentIds) {\n await service.getTracking({\n providerKey: job.payload.providerKey,\n shipmentId,\n organizationId: job.payload.scope.organizationId,\n tenantId: job.payload.scope.tenantId,\n })\n }\n}\n"],
5
+ "mappings": "AAgBO,MAAM,WAAuB;AAAA,EAClC,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,aAAa;AACf;AAEA,eAAO,OAA8B,KAAkC,KAAoC;AACzG,QAAM,UAAU,IAAI,QAAgC,wBAAwB;AAC5E,aAAW,cAAc,IAAI,QAAQ,aAAa;AAChD,UAAM,QAAQ,YAAY;AAAA,MACxB,aAAa,IAAI,QAAQ;AAAA,MACzB;AAAA,MACA,gBAAgB,IAAI,QAAQ,MAAM;AAAA,MAClC,UAAU,IAAI,QAAQ,MAAM;AAAA,IAC9B,CAAC;AAAA,EACH;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,54 @@
1
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
2
+ import { CarrierShipment } from "../data/entities.js";
3
+ import { emitShippingEvent } from "../events.js";
4
+ import { getShippingAdapter } from "../lib/adapter-registry.js";
5
+ import { getTerminalShippingEvent, syncShipmentStatus, TERMINAL_SHIPPING_STATUSES } from "../lib/status-sync.js";
6
+ const metadata = {
7
+ queue: "shipping-carriers-webhook",
8
+ id: "shipping-carriers:webhook-processor",
9
+ concurrency: 5
10
+ };
11
+ async function handle(job, ctx) {
12
+ const em = ctx.resolve("em");
13
+ const adapter = getShippingAdapter(job.payload.providerKey);
14
+ if (!adapter) return;
15
+ const shipment = job.payload.shipmentId && job.payload.scope ? await findOneWithDecryption(
16
+ em,
17
+ CarrierShipment,
18
+ {
19
+ id: job.payload.shipmentId,
20
+ organizationId: job.payload.scope.organizationId,
21
+ tenantId: job.payload.scope.tenantId,
22
+ deletedAt: null
23
+ },
24
+ void 0,
25
+ job.payload.scope
26
+ ) : null;
27
+ if (!shipment) return;
28
+ const carrierStatus = typeof job.payload.event.data.status === "string" ? job.payload.event.data.status : job.payload.event.eventType;
29
+ const unifiedStatus = adapter.mapStatus(carrierStatus);
30
+ shipment.carrierStatus = carrierStatus;
31
+ shipment.lastWebhookAt = /* @__PURE__ */ new Date();
32
+ const transitionApplied = syncShipmentStatus(shipment, unifiedStatus);
33
+ if (!transitionApplied) return;
34
+ await em.flush();
35
+ const eventPayload = {
36
+ shipmentId: shipment.id,
37
+ providerKey: job.payload.providerKey,
38
+ previousStatus: carrierStatus,
39
+ newStatus: unifiedStatus,
40
+ organizationId: shipment.organizationId,
41
+ tenantId: shipment.tenantId
42
+ };
43
+ await emitShippingEvent("shipping_carriers.shipment.status_changed", eventPayload);
44
+ if (TERMINAL_SHIPPING_STATUSES.has(unifiedStatus)) {
45
+ const terminalEvent = getTerminalShippingEvent(unifiedStatus);
46
+ if (!terminalEvent) return;
47
+ await emitShippingEvent(terminalEvent, eventPayload);
48
+ }
49
+ }
50
+ export {
51
+ handle as default,
52
+ metadata
53
+ };
54
+ //# sourceMappingURL=webhook-processor.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/shipping_carriers/workers/webhook-processor.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CarrierShipment } from '../data/entities'\nimport { emitShippingEvent } from '../events'\nimport { getShippingAdapter } from '../lib/adapter-registry'\nimport { getTerminalShippingEvent, syncShipmentStatus, TERMINAL_SHIPPING_STATUSES } from '../lib/status-sync'\n\ntype WebhookJobPayload = {\n providerKey: string\n event: {\n eventType: string\n data: Record<string, unknown>\n }\n shipmentId?: string | null\n scope?: {\n organizationId: string\n tenantId: string\n } | null\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport const metadata: WorkerMeta = {\n queue: 'shipping-carriers-webhook',\n id: 'shipping-carriers:webhook-processor',\n concurrency: 5,\n}\n\nexport default async function handle(job: QueuedJob<WebhookJobPayload>, ctx: HandlerContext): Promise<void> {\n const em = ctx.resolve<EntityManager>('em')\n const adapter = getShippingAdapter(job.payload.providerKey)\n if (!adapter) return\n\n const shipment = job.payload.shipmentId && job.payload.scope\n ? await findOneWithDecryption(\n em,\n CarrierShipment,\n {\n id: job.payload.shipmentId,\n organizationId: job.payload.scope.organizationId,\n tenantId: job.payload.scope.tenantId,\n deletedAt: null,\n },\n undefined,\n job.payload.scope,\n )\n : null\n if (!shipment) return\n\n const carrierStatus = typeof job.payload.event.data.status === 'string'\n ? job.payload.event.data.status\n : job.payload.event.eventType\n const unifiedStatus = adapter.mapStatus(carrierStatus)\n shipment.carrierStatus = carrierStatus\n shipment.lastWebhookAt = new Date()\n\n const transitionApplied = syncShipmentStatus(shipment, unifiedStatus)\n if (!transitionApplied) return\n\n await em.flush()\n\n const eventPayload = {\n shipmentId: shipment.id,\n providerKey: job.payload.providerKey,\n previousStatus: carrierStatus,\n newStatus: unifiedStatus,\n organizationId: shipment.organizationId,\n tenantId: shipment.tenantId,\n }\n await emitShippingEvent('shipping_carriers.shipment.status_changed', eventPayload)\n if (TERMINAL_SHIPPING_STATUSES.has(unifiedStatus)) {\n const terminalEvent = getTerminalShippingEvent(unifiedStatus)\n if (!terminalEvent) return\n await emitShippingEvent(terminalEvent, eventPayload)\n }\n}\n"],
5
+ "mappings": "AAEA,SAAS,6BAA6B;AACtC,SAAS,uBAAuB;AAChC,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,SAAS,0BAA0B,oBAAoB,kCAAkC;AAmBlF,MAAM,WAAuB;AAAA,EAClC,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,aAAa;AACf;AAEA,eAAO,OAA8B,KAAmC,KAAoC;AAC1G,QAAM,KAAK,IAAI,QAAuB,IAAI;AAC1C,QAAM,UAAU,mBAAmB,IAAI,QAAQ,WAAW;AAC1D,MAAI,CAAC,QAAS;AAEd,QAAM,WAAW,IAAI,QAAQ,cAAc,IAAI,QAAQ,QACnD,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,MACE,IAAI,IAAI,QAAQ;AAAA,MAChB,gBAAgB,IAAI,QAAQ,MAAM;AAAA,MAClC,UAAU,IAAI,QAAQ,MAAM;AAAA,MAC5B,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA,IAAI,QAAQ;AAAA,EACd,IACE;AACJ,MAAI,CAAC,SAAU;AAEf,QAAM,gBAAgB,OAAO,IAAI,QAAQ,MAAM,KAAK,WAAW,WAC3D,IAAI,QAAQ,MAAM,KAAK,SACvB,IAAI,QAAQ,MAAM;AACtB,QAAM,gBAAgB,QAAQ,UAAU,aAAa;AACrD,WAAS,gBAAgB;AACzB,WAAS,gBAAgB,oBAAI,KAAK;AAElC,QAAM,oBAAoB,mBAAmB,UAAU,aAAa;AACpE,MAAI,CAAC,kBAAmB;AAExB,QAAM,GAAG,MAAM;AAEf,QAAM,eAAe;AAAA,IACnB,YAAY,SAAS;AAAA,IACrB,aAAa,IAAI,QAAQ;AAAA,IACzB,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,gBAAgB,SAAS;AAAA,IACzB,UAAU,SAAS;AAAA,EACrB;AACA,QAAM,kBAAkB,6CAA6C,YAAY;AACjF,MAAI,2BAA2B,IAAI,aAAa,GAAG;AACjD,UAAM,gBAAgB,yBAAyB,aAAa;AAC5D,QAAI,CAAC,cAAe;AACpB,UAAM,kBAAkB,eAAe,YAAY;AAAA,EACrD;AACF;",
6
+ "names": []
7
+ }
@@ -4,6 +4,7 @@ import { resolveTranslationsRouteContext } from "@open-mercato/core/modules/tran
4
4
  import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
5
5
  import { locales as defaultLocales } from "@open-mercato/shared/lib/i18n/config";
6
6
  const metadata = {
7
+ path: "/translations/locales",
7
8
  GET: { requireAuth: true, requireFeatures: ["translations.view"] }
8
9
  };
9
10
  async function GET(req) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/translations/api/get/locales.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { resolveTranslationsRouteContext } from '@open-mercato/core/modules/translations/api/context'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { locales as defaultLocales } from '@open-mercato/shared/lib/i18n/config'\nimport type { ModuleConfigService } from '@open-mercato/core/modules/configs/lib/module-config-service'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['translations.view'] },\n}\n\nasync function GET(req: Request) {\n try {\n const context = await resolveTranslationsRouteContext(req)\n\n const configService = context.container.resolve('moduleConfigService') as ModuleConfigService\n const locales = await configService.getValue<string[]>('translations', 'supported_locales', {\n defaultValue: [...defaultLocales],\n })\n\n return NextResponse.json({ locales: Array.isArray(locales) ? locales : [...defaultLocales] })\n } catch (err) {\n if (err instanceof CrudHttpError) {\n return NextResponse.json(err.body, { status: err.status })\n }\n console.error('[translations/locales.GET] Unexpected error', err)\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 })\n }\n}\n\nconst responseSchema = z.object({\n locales: z.array(z.string()),\n})\n\nconst getDoc: OpenApiMethodDoc = {\n summary: 'List supported translation locales',\n tags: ['Translations'],\n responses: [\n { status: 200, description: 'Supported locales list', schema: responseSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Translations',\n summary: 'List supported translation locales',\n methods: {\n GET: getDoc,\n },\n}\n\nexport default GET\n"],
5
- "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,uCAAuC;AAChD,SAAS,qBAAqB;AAC9B,SAAS,WAAW,sBAAsB;AAInC,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,mBAAmB,EAAE;AACnE;AAEA,eAAe,IAAI,KAAc;AAC/B,MAAI;AACF,UAAM,UAAU,MAAM,gCAAgC,GAAG;AAEzD,UAAM,gBAAgB,QAAQ,UAAU,QAAQ,qBAAqB;AACrE,UAAM,UAAU,MAAM,cAAc,SAAmB,gBAAgB,qBAAqB;AAAA,MAC1F,cAAc,CAAC,GAAG,cAAc;AAAA,IAClC,CAAC;AAED,WAAO,aAAa,KAAK,EAAE,SAAS,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,GAAG,cAAc,EAAE,CAAC;AAAA,EAC9F,SAAS,KAAK;AACZ,QAAI,eAAe,eAAe;AAChC,aAAO,aAAa,KAAK,IAAI,MAAM,EAAE,QAAQ,IAAI,OAAO,CAAC;AAAA,IAC3D;AACA,YAAQ,MAAM,+CAA+C,GAAG;AAChE,WAAO,aAAa,KAAK,EAAE,OAAO,wBAAwB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC9E;AACF;AAEA,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC;AAC7B,CAAC;AAED,MAAM,SAA2B;AAAA,EAC/B,SAAS;AAAA,EACT,MAAM,CAAC,cAAc;AAAA,EACrB,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,0BAA0B,QAAQ,eAAe;AAAA,EAC/E;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,EACP;AACF;AAEA,IAAO,kBAAQ;",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { resolveTranslationsRouteContext } from '@open-mercato/core/modules/translations/api/context'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { locales as defaultLocales } from '@open-mercato/shared/lib/i18n/config'\nimport type { ModuleConfigService } from '@open-mercato/core/modules/configs/lib/module-config-service'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\nexport const metadata = {\n path: '/translations/locales',\n GET: { requireAuth: true, requireFeatures: ['translations.view'] },\n}\n\nasync function GET(req: Request) {\n try {\n const context = await resolveTranslationsRouteContext(req)\n\n const configService = context.container.resolve('moduleConfigService') as ModuleConfigService\n const locales = await configService.getValue<string[]>('translations', 'supported_locales', {\n defaultValue: [...defaultLocales],\n })\n\n return NextResponse.json({ locales: Array.isArray(locales) ? locales : [...defaultLocales] })\n } catch (err) {\n if (err instanceof CrudHttpError) {\n return NextResponse.json(err.body, { status: err.status })\n }\n console.error('[translations/locales.GET] Unexpected error', err)\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 })\n }\n}\n\nconst responseSchema = z.object({\n locales: z.array(z.string()),\n})\n\nconst getDoc: OpenApiMethodDoc = {\n summary: 'List supported translation locales',\n tags: ['Translations'],\n responses: [\n { status: 200, description: 'Supported locales list', schema: responseSchema },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Translations',\n summary: 'List supported translation locales',\n methods: {\n GET: getDoc,\n },\n}\n\nexport default GET\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,uCAAuC;AAChD,SAAS,qBAAqB;AAC9B,SAAS,WAAW,sBAAsB;AAInC,MAAM,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,mBAAmB,EAAE;AACnE;AAEA,eAAe,IAAI,KAAc;AAC/B,MAAI;AACF,UAAM,UAAU,MAAM,gCAAgC,GAAG;AAEzD,UAAM,gBAAgB,QAAQ,UAAU,QAAQ,qBAAqB;AACrE,UAAM,UAAU,MAAM,cAAc,SAAmB,gBAAgB,qBAAqB;AAAA,MAC1F,cAAc,CAAC,GAAG,cAAc;AAAA,IAClC,CAAC;AAED,WAAO,aAAa,KAAK,EAAE,SAAS,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,GAAG,cAAc,EAAE,CAAC;AAAA,EAC9F,SAAS,KAAK;AACZ,QAAI,eAAe,eAAe;AAChC,aAAO,aAAa,KAAK,IAAI,MAAM,EAAE,QAAQ,IAAI,OAAO,CAAC;AAAA,IAC3D;AACA,YAAQ,MAAM,+CAA+C,GAAG;AAChE,WAAO,aAAa,KAAK,EAAE,OAAO,wBAAwB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC9E;AACF;AAEA,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC;AAC7B,CAAC;AAED,MAAM,SAA2B;AAAA,EAC/B,SAAS;AAAA,EACT,MAAM,CAAC,cAAc;AAAA,EACrB,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,0BAA0B,QAAQ,eAAe;AAAA,EAC/E;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,EACP;AACF;AAEA,IAAO,kBAAQ;",
6
6
  "names": []
7
7
  }
@@ -9,6 +9,7 @@ const bodySchema = z.object({
9
9
  ).min(1).max(50)
10
10
  });
11
11
  const metadata = {
12
+ path: "/translations/locales",
12
13
  PUT: { requireAuth: true, requireFeatures: ["translations.manage_locales"] }
13
14
  };
14
15
  async function PUT(req) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/translations/api/put/locales.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { resolveTranslationsRouteContext } from '@open-mercato/core/modules/translations/api/context'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { isValidIso639 } from '@open-mercato/shared/lib/i18n/iso639'\nimport type { ModuleConfigService } from '@open-mercato/core/modules/configs/lib/module-config-service'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\nconst bodySchema = z.object({\n locales: z.array(\n z.string().min(2).max(10).refine(isValidIso639, { message: 'Invalid ISO 639-1 language code' }),\n ).min(1).max(50),\n})\n\nexport const metadata = {\n PUT: { requireAuth: true, requireFeatures: ['translations.manage_locales'] },\n}\n\nasync function PUT(req: Request) {\n try {\n const context = await resolveTranslationsRouteContext(req)\n const body = bodySchema.parse(await req.json())\n const uniqueLocales = [...new Set(body.locales.map((l) => l.toLowerCase().trim()))]\n\n const configService = context.container.resolve('moduleConfigService') as ModuleConfigService\n await configService.setValue('translations', 'supported_locales', uniqueLocales)\n\n return NextResponse.json({ locales: uniqueLocales })\n } catch (err) {\n if (err instanceof CrudHttpError) {\n return NextResponse.json(err.body, { status: err.status })\n }\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: 'Invalid request', details: err.issues }, { status: 400 })\n }\n console.error('[translations/locales.PUT] Unexpected error', err)\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 })\n }\n}\n\nconst responseSchema = z.object({\n locales: z.array(z.string()),\n})\n\nconst putDoc: OpenApiMethodDoc = {\n summary: 'Update supported translation locales',\n tags: ['Translations'],\n requestBody: {\n schema: bodySchema,\n },\n responses: [\n { status: 200, description: 'Updated locales list', schema: responseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid request body' },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Translations',\n summary: 'Update supported translation locales',\n methods: {\n PUT: putDoc,\n },\n}\n\nexport default PUT\n"],
5
- "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,uCAAuC;AAChD,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAI9B,MAAM,aAAa,EAAE,OAAO;AAAA,EAC1B,SAAS,EAAE;AAAA,IACT,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,eAAe,EAAE,SAAS,kCAAkC,CAAC;AAAA,EAChG,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AACjB,CAAC;AAEM,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,6BAA6B,EAAE;AAC7E;AAEA,eAAe,IAAI,KAAc;AAC/B,MAAI;AACF,UAAM,UAAU,MAAM,gCAAgC,GAAG;AACzD,UAAM,OAAO,WAAW,MAAM,MAAM,IAAI,KAAK,CAAC;AAC9C,UAAM,gBAAgB,CAAC,GAAG,IAAI,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC;AAElF,UAAM,gBAAgB,QAAQ,UAAU,QAAQ,qBAAqB;AACrE,UAAM,cAAc,SAAS,gBAAgB,qBAAqB,aAAa;AAE/E,WAAO,aAAa,KAAK,EAAE,SAAS,cAAc,CAAC;AAAA,EACrD,SAAS,KAAK;AACZ,QAAI,eAAe,eAAe;AAChC,aAAO,aAAa,KAAK,IAAI,MAAM,EAAE,QAAQ,IAAI,OAAO,CAAC;AAAA,IAC3D;AACA,QAAI,eAAe,EAAE,UAAU;AAC7B,aAAO,aAAa,KAAK,EAAE,OAAO,mBAAmB,SAAS,IAAI,OAAO,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7F;AACA,YAAQ,MAAM,+CAA+C,GAAG;AAChE,WAAO,aAAa,KAAK,EAAE,OAAO,wBAAwB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC9E;AACF;AAEA,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC;AAC7B,CAAC;AAED,MAAM,SAA2B;AAAA,EAC/B,SAAS;AAAA,EACT,MAAM,CAAC,cAAc;AAAA,EACrB,aAAa;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,wBAAwB,QAAQ,eAAe;AAAA,EAC7E;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,QAAQ,KAAK,aAAa,uBAAuB;AAAA,EACrD;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,EACP;AACF;AAEA,IAAO,kBAAQ;",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { resolveTranslationsRouteContext } from '@open-mercato/core/modules/translations/api/context'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { isValidIso639 } from '@open-mercato/shared/lib/i18n/iso639'\nimport type { ModuleConfigService } from '@open-mercato/core/modules/configs/lib/module-config-service'\nimport type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\n\nconst bodySchema = z.object({\n locales: z.array(\n z.string().min(2).max(10).refine(isValidIso639, { message: 'Invalid ISO 639-1 language code' }),\n ).min(1).max(50),\n})\n\nexport const metadata = {\n path: '/translations/locales',\n PUT: { requireAuth: true, requireFeatures: ['translations.manage_locales'] },\n}\n\nasync function PUT(req: Request) {\n try {\n const context = await resolveTranslationsRouteContext(req)\n const body = bodySchema.parse(await req.json())\n const uniqueLocales = [...new Set(body.locales.map((l) => l.toLowerCase().trim()))]\n\n const configService = context.container.resolve('moduleConfigService') as ModuleConfigService\n await configService.setValue('translations', 'supported_locales', uniqueLocales)\n\n return NextResponse.json({ locales: uniqueLocales })\n } catch (err) {\n if (err instanceof CrudHttpError) {\n return NextResponse.json(err.body, { status: err.status })\n }\n if (err instanceof z.ZodError) {\n return NextResponse.json({ error: 'Invalid request', details: err.issues }, { status: 400 })\n }\n console.error('[translations/locales.PUT] Unexpected error', err)\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 })\n }\n}\n\nconst responseSchema = z.object({\n locales: z.array(z.string()),\n})\n\nconst putDoc: OpenApiMethodDoc = {\n summary: 'Update supported translation locales',\n tags: ['Translations'],\n requestBody: {\n schema: bodySchema,\n },\n responses: [\n { status: 200, description: 'Updated locales list', schema: responseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid request body' },\n ],\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Translations',\n summary: 'Update supported translation locales',\n methods: {\n PUT: putDoc,\n },\n}\n\nexport default PUT\n"],
5
+ "mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAClB,SAAS,uCAAuC;AAChD,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAI9B,MAAM,aAAa,EAAE,OAAO;AAAA,EAC1B,SAAS,EAAE;AAAA,IACT,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,OAAO,eAAe,EAAE,SAAS,kCAAkC,CAAC;AAAA,EAChG,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AACjB,CAAC;AAEM,MAAM,WAAW;AAAA,EACtB,MAAM;AAAA,EACN,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,6BAA6B,EAAE;AAC7E;AAEA,eAAe,IAAI,KAAc;AAC/B,MAAI;AACF,UAAM,UAAU,MAAM,gCAAgC,GAAG;AACzD,UAAM,OAAO,WAAW,MAAM,MAAM,IAAI,KAAK,CAAC;AAC9C,UAAM,gBAAgB,CAAC,GAAG,IAAI,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC;AAElF,UAAM,gBAAgB,QAAQ,UAAU,QAAQ,qBAAqB;AACrE,UAAM,cAAc,SAAS,gBAAgB,qBAAqB,aAAa;AAE/E,WAAO,aAAa,KAAK,EAAE,SAAS,cAAc,CAAC;AAAA,EACrD,SAAS,KAAK;AACZ,QAAI,eAAe,eAAe;AAChC,aAAO,aAAa,KAAK,IAAI,MAAM,EAAE,QAAQ,IAAI,OAAO,CAAC;AAAA,IAC3D;AACA,QAAI,eAAe,EAAE,UAAU;AAC7B,aAAO,aAAa,KAAK,EAAE,OAAO,mBAAmB,SAAS,IAAI,OAAO,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC7F;AACA,YAAQ,MAAM,+CAA+C,GAAG;AAChE,WAAO,aAAa,KAAK,EAAE,OAAO,wBAAwB,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC9E;AACF;AAEA,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC;AAC7B,CAAC;AAED,MAAM,SAA2B;AAAA,EAC/B,SAAS;AAAA,EACT,MAAM,CAAC,cAAc;AAAA,EACrB,aAAa;AAAA,IACX,QAAQ;AAAA,EACV;AAAA,EACA,WAAW;AAAA,IACT,EAAE,QAAQ,KAAK,aAAa,wBAAwB,QAAQ,eAAe;AAAA,EAC7E;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,QAAQ,KAAK,aAAa,uBAAuB;AAAA,EACrD;AACF;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,EACP;AACF;AAEA,IAAO,kBAAQ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,17 @@
1
+ export const id = 'id'
2
+ export const order_id = 'order_id'
3
+ export const provider_key = 'provider_key'
4
+ export const carrier_shipment_id = 'carrier_shipment_id'
5
+ export const tracking_number = 'tracking_number'
6
+ export const unified_status = 'unified_status'
7
+ export const carrier_status = 'carrier_status'
8
+ export const label_url = 'label_url'
9
+ export const label_data = 'label_data'
10
+ export const tracking_events = 'tracking_events'
11
+ export const organization_id = 'organization_id'
12
+ export const tenant_id = 'tenant_id'
13
+ export const last_webhook_at = 'last_webhook_at'
14
+ export const last_polled_at = 'last_polled_at'
15
+ export const created_at = 'created_at'
16
+ export const updated_at = 'updated_at'
17
+ export const deleted_at = 'deleted_at'
@@ -0,0 +1,22 @@
1
+ export const id = 'id'
2
+ export const payment_id = 'payment_id'
3
+ export const provider_key = 'provider_key'
4
+ export const provider_session_id = 'provider_session_id'
5
+ export const gateway_payment_id = 'gateway_payment_id'
6
+ export const gateway_refund_id = 'gateway_refund_id'
7
+ export const unified_status = 'unified_status'
8
+ export const gateway_status = 'gateway_status'
9
+ export const redirect_url = 'redirect_url'
10
+ export const client_secret = 'client_secret'
11
+ export const amount = 'amount'
12
+ export const currency_code = 'currency_code'
13
+ export const gateway_metadata = 'gateway_metadata'
14
+ export const webhook_log = 'webhook_log'
15
+ export const last_webhook_at = 'last_webhook_at'
16
+ export const last_polled_at = 'last_polled_at'
17
+ export const expires_at = 'expires_at'
18
+ export const organization_id = 'organization_id'
19
+ export const tenant_id = 'tenant_id'
20
+ export const created_at = 'created_at'
21
+ export const updated_at = 'updated_at'
22
+ export const deleted_at = 'deleted_at'
@@ -0,0 +1,7 @@
1
+ export const id = 'id'
2
+ export const provider_key = 'provider_key'
3
+ export const idempotency_key = 'idempotency_key'
4
+ export const event_type = 'event_type'
5
+ export const organization_id = 'organization_id'
6
+ export const tenant_id = 'tenant_id'
7
+ export const processed_at = 'processed_at'
@@ -28,7 +28,9 @@ export const M = {
28
28
  "data_sync": "data_sync",
29
29
  "messages": "messages",
30
30
  "translations": "translations",
31
- "inbox_ops": "inbox_ops"
31
+ "inbox_ops": "inbox_ops",
32
+ "payment_gateways": "payment_gateways",
33
+ "shipping_carriers": "shipping_carriers"
32
34
  } as const
33
35
  export const E = {
34
36
  "dashboards": {
@@ -228,6 +230,13 @@ export const E = {
228
230
  "inbox_proposal": "inbox_ops:inbox_proposal",
229
231
  "inbox_proposal_action": "inbox_ops:inbox_proposal_action",
230
232
  "inbox_discrepancy": "inbox_ops:inbox_discrepancy"
233
+ },
234
+ "payment_gateways": {
235
+ "gateway_transaction": "payment_gateways:gateway_transaction",
236
+ "webhook_processed_event": "payment_gateways:webhook_processed_event"
237
+ },
238
+ "shipping_carriers": {
239
+ "carrier_shipment": "shipping_carriers:carrier_shipment"
231
240
  }
232
241
  } as const
233
242
  export type KnownModuleId = keyof typeof M
@@ -6,6 +6,7 @@ import * as api_key from './entities/api_key/index'
6
6
  import * as attachment from './entities/attachment/index'
7
7
  import * as attachment_partition from './entities/attachment_partition/index'
8
8
  import * as business_rule from './entities/business_rule/index'
9
+ import * as carrier_shipment from './entities/carrier_shipment/index'
9
10
  import * as catalog_offer from './entities/catalog_offer/index'
10
11
  import * as catalog_option_schema_template from './entities/catalog_option_schema_template/index'
11
12
  import * as catalog_price_kind from './entities/catalog_price_kind/index'
@@ -54,6 +55,7 @@ import * as entity_translation from './entities/entity_translation/index'
54
55
  import * as exchange_rate from './entities/exchange_rate/index'
55
56
  import * as feature_toggle from './entities/feature_toggle/index'
56
57
  import * as feature_toggle_override from './entities/feature_toggle_override/index'
58
+ import * as gateway_transaction from './entities/gateway_transaction/index'
57
59
  import * as inbox_discrepancy from './entities/inbox_discrepancy/index'
58
60
  import * as inbox_email from './entities/inbox_email/index'
59
61
  import * as inbox_proposal from './entities/inbox_proposal/index'
@@ -138,6 +140,7 @@ import * as user_acl from './entities/user_acl/index'
138
140
  import * as user_role from './entities/user_role/index'
139
141
  import * as user_sidebar_preference from './entities/user_sidebar_preference/index'
140
142
  import * as user_task from './entities/user_task/index'
143
+ import * as webhook_processed_event from './entities/webhook_processed_event/index'
141
144
  import * as workflow_definition from './entities/workflow_definition/index'
142
145
  import * as workflow_event from './entities/workflow_event/index'
143
146
  import * as workflow_event_trigger from './entities/workflow_event_trigger/index'
@@ -150,6 +153,7 @@ export const entityFieldsRegistry: Record<string, Record<string, string>> = {
150
153
  attachment,
151
154
  attachment_partition,
152
155
  business_rule,
156
+ carrier_shipment,
153
157
  catalog_offer,
154
158
  catalog_option_schema_template,
155
159
  catalog_price_kind,
@@ -198,6 +202,7 @@ export const entityFieldsRegistry: Record<string, Record<string, string>> = {
198
202
  exchange_rate,
199
203
  feature_toggle,
200
204
  feature_toggle_override,
205
+ gateway_transaction,
201
206
  inbox_discrepancy,
202
207
  inbox_email,
203
208
  inbox_proposal,
@@ -282,6 +287,7 @@ export const entityFieldsRegistry: Record<string, Record<string, string>> = {
282
287
  user_role,
283
288
  user_sidebar_preference,
284
289
  user_task,
290
+ webhook_processed_event,
285
291
  workflow_definition,
286
292
  workflow_event,
287
293
  workflow_event_trigger,
package/jest.config.cjs CHANGED
@@ -9,6 +9,7 @@ module.exports = {
9
9
  '^#generated/(.*)$': '<rootDir>/generated/$1',
10
10
  '^@open-mercato/core/generated/(.*)$': '<rootDir>/generated/$1',
11
11
  '^@open-mercato/core/(.*)$': '<rootDir>/src/$1',
12
+ '^@open-mercato/shared/(.*)$': '<rootDir>/../shared/src/$1',
12
13
  '^@/\\.mercato/generated/inbox-actions\\.generated$': '<rootDir>/jest.mocks/inbox-actions.generated.js',
13
14
  '^react-markdown$': '<rootDir>/jest.mocks/react-markdown.js',
14
15
  '^remark-gfm$': '<rootDir>/jest.mocks/remark-gfm.js',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.4.7-develop-0a657b411f",
3
+ "version": "0.4.7-develop-e249d3e7d0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -207,7 +207,6 @@
207
207
  }
208
208
  },
209
209
  "dependencies": {
210
- "@open-mercato/shared": "0.4.7-develop-0a657b411f",
211
210
  "@types/html-to-text": "^9.0.4",
212
211
  "@types/semver": "^7.5.8",
213
212
  "@xyflow/react": "^12.6.0",
@@ -217,7 +216,11 @@
217
216
  "html-to-text": "^9.0.5",
218
217
  "semver": "^7.6.3"
219
218
  },
219
+ "peerDependencies": {
220
+ "@open-mercato/shared": "0.4.7-develop-e249d3e7d0"
221
+ },
220
222
  "devDependencies": {
223
+ "@open-mercato/shared": "0.4.7-develop-e249d3e7d0",
221
224
  "@testing-library/dom": "^10.4.1",
222
225
  "@testing-library/jest-dom": "^6.9.1",
223
226
  "@testing-library/react": "^16.3.1",
@@ -155,6 +155,7 @@
155
155
  "auth.users.widgets.mode.inherit": "Von Rollen übernehmen",
156
156
  "auth.users.widgets.mode.override": "Für diesen Benutzer überschreiben",
157
157
  "auth.usersRoles": "Benutzer und Rollen",
158
+ "backend.nav.externalSystems": "Externe Systeme",
158
159
  "backend.nav.settings": "Einstellungen",
159
160
  "backend.nav.settingsAdmin": "Administration",
160
161
  "profile.page.description": "Verwalte deine Kontoeinstellungen",
@@ -155,6 +155,7 @@
155
155
  "auth.users.widgets.mode.inherit": "Inherit from roles",
156
156
  "auth.users.widgets.mode.override": "Override for this user",
157
157
  "auth.usersRoles": "Users & Roles",
158
+ "backend.nav.externalSystems": "External systems",
158
159
  "backend.nav.settings": "Settings",
159
160
  "backend.nav.settingsAdmin": "Administration",
160
161
  "profile.page.description": "Manage your account settings",
@@ -155,6 +155,7 @@
155
155
  "auth.users.widgets.mode.inherit": "Heredar de las funciones",
156
156
  "auth.users.widgets.mode.override": "Sobrescribir para este usuario",
157
157
  "auth.usersRoles": "Usuarios y roles",
158
+ "backend.nav.externalSystems": "Sistemas externos",
158
159
  "backend.nav.settings": "Configuración",
159
160
  "backend.nav.settingsAdmin": "Administración",
160
161
  "profile.page.description": "Administra la configuración de tu cuenta",
@@ -155,6 +155,7 @@
155
155
  "auth.users.widgets.mode.inherit": "Dziedzicz z ról",
156
156
  "auth.users.widgets.mode.override": "Zastąp dla tego użytkownika",
157
157
  "auth.usersRoles": "Użytkownicy i role",
158
+ "backend.nav.externalSystems": "Systemy zewnetrzne",
158
159
  "backend.nav.settings": "Ustawienia",
159
160
  "backend.nav.settingsAdmin": "Administracja",
160
161
  "profile.page.description": "Zarządzaj ustawieniami konta",
@@ -44,12 +44,25 @@ export async function POST(req: Request, ctx: { params?: Promise<{ id?: string }
44
44
  return NextResponse.json({ error: 'Only pending or running runs can be cancelled' }, { status: 409 })
45
45
  }
46
46
 
47
+ const progressCtx = {
48
+ tenantId: auth.tenantId,
49
+ organizationId: auth.orgId,
50
+ userId: auth.sub,
51
+ }
52
+
47
53
  if (run.progressJobId) {
48
- await progressService.cancelJob(run.progressJobId, {
49
- tenantId: auth.tenantId,
50
- organizationId: auth.orgId,
51
- userId: auth.sub,
52
- })
54
+ try {
55
+ await progressService.cancelJob(run.progressJobId, progressCtx)
56
+ } catch (error) {
57
+ const job = await progressService.getJob(run.progressJobId, progressCtx)
58
+ const cancelRequested = job && job.status === 'running'
59
+ ? await progressService.isCancellationRequested(run.progressJobId)
60
+ : false
61
+
62
+ if (job?.status !== 'cancelled' && !cancelRequested) {
63
+ throw error
64
+ }
65
+ }
53
66
  }
54
67
 
55
68
  await syncRunService.markStatus(run.id, 'cancelled', scope)
@@ -12,8 +12,8 @@ export const metadata = {
12
12
  requireFeatures: ['data_sync.view'],
13
13
  pageTitle: 'Data Sync',
14
14
  pageTitleKey: 'data_sync.nav.title',
15
- pageGroup: 'Settings',
16
- pageGroupKey: 'settings.sections.general',
15
+ pageGroup: 'External systems',
16
+ pageGroupKey: 'backend.nav.externalSystems',
17
17
  pageOrder: 51,
18
18
  icon: syncIcon,
19
19
  pageContext: 'settings' as const,
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
  import * as React from 'react'
3
3
  import Link from 'next/link'
4
- import { useParams, useRouter } from 'next/navigation'
4
+ import { usePathname, useRouter } from 'next/navigation'
5
5
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
6
6
  import { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'
7
7
  import { Badge } from '@open-mercato/ui/primitives/badge'
@@ -62,10 +62,28 @@ const LOG_LEVEL_STYLES: Record<string, string> = {
62
62
  error: 'bg-red-100 text-red-800',
63
63
  }
64
64
 
65
- export default function SyncRunDetailPage() {
66
- const params = useParams<{ id: string }>()
65
+ type SyncRunDetailPageProps = {
66
+ params?: {
67
+ id?: string | string[]
68
+ }
69
+ }
70
+
71
+ function resolveRouteId(value: string | string[] | undefined): string | undefined {
72
+ if (Array.isArray(value)) return value[0]
73
+ return value
74
+ }
75
+
76
+ function resolvePathnameId(pathname: string): string | undefined {
77
+ const parts = pathname.split('/').filter(Boolean)
78
+ const runId = parts.at(-1)
79
+ if (!runId || runId === 'runs' || runId === 'data-sync') return undefined
80
+ return decodeURIComponent(runId)
81
+ }
82
+
83
+ export default function SyncRunDetailPage({ params }: SyncRunDetailPageProps) {
84
+ const pathname = usePathname()
67
85
  const router = useRouter()
68
- const runId = params.id
86
+ const runId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname)
69
87
  const t = useT()
70
88
 
71
89
  const [run, setRun] = React.useState<SyncRunDetail | null>(null)
@@ -74,9 +92,23 @@ export default function SyncRunDetailPage() {
74
92
  const [logs, setLogs] = React.useState<LogEntry[]>([])
75
93
  const [isLoadingLogs, setIsLoadingLogs] = React.useState(false)
76
94
 
95
+ const resolveCurrentRunId = React.useCallback(() => {
96
+ return runId ?? (
97
+ typeof window !== 'undefined'
98
+ ? resolvePathnameId(window.location.pathname)
99
+ : undefined
100
+ )
101
+ }, [runId])
102
+
77
103
  const loadRun = React.useCallback(async () => {
104
+ const currentRunId = resolveCurrentRunId()
105
+ if (!currentRunId) {
106
+ setError(t('data_sync.runs.detail.loadError'))
107
+ setIsLoading(false)
108
+ return
109
+ }
78
110
  const call = await apiCall<SyncRunDetail>(
79
- `/api/data_sync/runs/${encodeURIComponent(runId)}`,
111
+ `/api/data_sync/runs/${encodeURIComponent(currentRunId)}`,
80
112
  undefined,
81
113
  { fallback: null },
82
114
  )
@@ -87,11 +119,13 @@ export default function SyncRunDetailPage() {
87
119
  }
88
120
  setRun(call.result)
89
121
  setIsLoading(false)
90
- }, [runId, t])
122
+ }, [resolveCurrentRunId, t])
91
123
 
92
124
  const loadLogs = React.useCallback(async () => {
125
+ const currentRunId = resolveCurrentRunId()
126
+ if (!currentRunId) return
93
127
  setIsLoadingLogs(true)
94
- const params = new URLSearchParams({ runId, pageSize: '50' })
128
+ const params = new URLSearchParams({ runId: currentRunId, pageSize: '50' })
95
129
  const call = await apiCall<{ items: LogEntry[] }>(
96
130
  `/api/integrations/logs?${params.toString()}`,
97
131
  undefined,
@@ -101,7 +135,7 @@ export default function SyncRunDetailPage() {
101
135
  setLogs(call.result.items)
102
136
  }
103
137
  setIsLoadingLogs(false)
104
- }, [runId])
138
+ }, [resolveCurrentRunId])
105
139
 
106
140
  React.useEffect(() => {
107
141
  void loadRun()
@@ -115,7 +149,9 @@ export default function SyncRunDetailPage() {
115
149
  }, [run?.status, loadRun])
116
150
 
117
151
  const handleCancel = React.useCallback(async () => {
118
- const call = await apiCall(`/api/data_sync/runs/${encodeURIComponent(runId)}/cancel`, {
152
+ const currentRunId = resolveCurrentRunId()
153
+ if (!currentRunId) return
154
+ const call = await apiCall(`/api/data_sync/runs/${encodeURIComponent(currentRunId)}/cancel`, {
119
155
  method: 'POST',
120
156
  }, { fallback: null })
121
157
  if (call.ok) {
@@ -124,10 +160,12 @@ export default function SyncRunDetailPage() {
124
160
  } else {
125
161
  flash(t('data_sync.runs.detail.cancelError'), 'error')
126
162
  }
127
- }, [runId, t, loadRun])
163
+ }, [resolveCurrentRunId, t, loadRun])
128
164
 
129
165
  const handleRetry = React.useCallback(async () => {
130
- const call = await apiCall<{ id: string }>(`/api/data_sync/runs/${encodeURIComponent(runId)}/retry`, {
166
+ const currentRunId = resolveCurrentRunId()
167
+ if (!currentRunId) return
168
+ const call = await apiCall<{ id: string }>(`/api/data_sync/runs/${encodeURIComponent(currentRunId)}/retry`, {
131
169
  method: 'POST',
132
170
  headers: { 'Content-Type': 'application/json' },
133
171
  body: JSON.stringify({ fromBeginning: false }),
@@ -138,7 +176,7 @@ export default function SyncRunDetailPage() {
138
176
  } else {
139
177
  flash(t('data_sync.runs.detail.retryError'), 'error')
140
178
  }
141
- }, [router, runId, t])
179
+ }, [resolveCurrentRunId, router, t])
142
180
 
143
181
  if (isLoading) return <Page><PageBody><LoadingMessage label={t('data_sync.runs.detail.title')} /></PageBody></Page>
144
182
  if (error || !run) return <Page><PageBody><ErrorMessage label={error ?? t('data_sync.runs.detail.loadError')} /></PageBody></Page>
@@ -6,6 +6,7 @@ import { Tenant } from '@open-mercato/core/modules/directory/data/entities'
6
6
  import type { OpenApiMethodDoc, OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
7
7
 
8
8
  export const metadata = {
9
+ path: '/directory/tenants/lookup',
9
10
  GET: {
10
11
  requireAuth: false,
11
12
  },
@@ -119,6 +119,37 @@ Integration provider modules can leverage the full **Unified Module Extension Sy
119
119
  | **Notifications** | Emit in-app notifications on integration events | `notifications.ts`, `subscribers/` |
120
120
  | **DOM Event Bridge** | Push real-time events to browser (SSE) | Set `clientBroadcast: true` in event definitions |
121
121
 
122
+ ### Integration Detail Page Widget Spot
123
+
124
+ Provider modules can opt into a provider-scoped integration detail extension surface directly from `integration.ts`:
125
+
126
+ ```typescript
127
+ import { buildIntegrationDetailWidgetSpotId } from '@open-mercato/shared/modules/integrations/types'
128
+
129
+ export const integration = {
130
+ id: 'gateway_example',
131
+ detailPage: {
132
+ widgetSpotId: buildIntegrationDetailWidgetSpotId('gateway_example'),
133
+ },
134
+ } satisfies IntegrationDefinition
135
+ ```
136
+
137
+ - Register React widgets for that spot in `widgets/injection-table.ts`
138
+ - Use `placement.kind: 'tab'` to create additional detail tabs
139
+ - Use `placement.kind: 'group'` for card-style panels and `placement.kind: 'stack'` for inline sections
140
+ - Integration detail page writes run through `useGuardedMutation` with that same spot, so widget `onBeforeSave` / `onAfterSave` handlers apply to built-in credentials/state/version/health actions too
141
+ - Backward compatibility: legacy `integrations.detail:tabs` still works as the fallback when `detailPage.widgetSpotId` is omitted
142
+
143
+ ### Marketplace API UMES Hooks
144
+
145
+ The integrations marketplace read routes now support a safe subset of UMES:
146
+
147
+ - `GET /api/integrations` and `GET /api/integrations/:id` support response enrichers targeting `integrations.integration`
148
+ - `GET /api/integrations/logs` supports response enrichers targeting `integrations.log`
149
+ - These read routes also execute API interceptors for their route IDs (`integrations`, `integrations/detail`, `integrations/logs`)
150
+ - Safety rule: integrations read routes preserve built-in response keys and only accept additive fields from enrichers/interceptor-after hooks
151
+ - Write routes (`credentials`, `state`, `version`) already support mutation guards and events; they are not yet wired into the generic API interceptor/enricher pipeline
152
+
122
153
  ### Key UMES Imports for Providers
123
154
 
124
155
  ```typescript