@freighttech/shipment-tracking 0.6.0

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 (456) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +25 -0
  3. package/dist/generated/entities/bic_config/index.js +21 -0
  4. package/dist/generated/entities/bic_config/index.js.map +7 -0
  5. package/dist/generated/entities/carrier_config/index.js +27 -0
  6. package/dist/generated/entities/carrier_config/index.js.map +7 -0
  7. package/dist/generated/entities/location_override/index.js +33 -0
  8. package/dist/generated/entities/location_override/index.js.map +7 -0
  9. package/dist/generated/entities/shipment/index.js +73 -0
  10. package/dist/generated/entities/shipment/index.js.map +7 -0
  11. package/dist/generated/entities/ships_go_config/index.js +31 -0
  12. package/dist/generated/entities/ships_go_config/index.js.map +7 -0
  13. package/dist/generated/entities/tracking_event/index.js +101 -0
  14. package/dist/generated/entities/tracking_event/index.js.map +7 -0
  15. package/dist/generated/entities/tracking_job/index.js +47 -0
  16. package/dist/generated/entities/tracking_job/index.js.map +7 -0
  17. package/dist/generated/entities/webhook/index.js +25 -0
  18. package/dist/generated/entities/webhook/index.js.map +7 -0
  19. package/dist/generated/entities/webhook_delivery/index.js +25 -0
  20. package/dist/generated/entities/webhook_delivery/index.js.map +7 -0
  21. package/dist/generated/entities.ids.generated.js +21 -0
  22. package/dist/generated/entities.ids.generated.js.map +7 -0
  23. package/dist/index.js +41 -0
  24. package/dist/index.js.map +7 -0
  25. package/dist/modules/shipment_tracking/acl.js +22 -0
  26. package/dist/modules/shipment_tracking/acl.js.map +7 -0
  27. package/dist/modules/shipment_tracking/api/bic-configs/route.js +176 -0
  28. package/dist/modules/shipment_tracking/api/bic-configs/route.js.map +7 -0
  29. package/dist/modules/shipment_tracking/api/bic-configs/test/route.js +95 -0
  30. package/dist/modules/shipment_tracking/api/bic-configs/test/route.js.map +7 -0
  31. package/dist/modules/shipment_tracking/api/cargo-events/route.js +93 -0
  32. package/dist/modules/shipment_tracking/api/cargo-events/route.js.map +7 -0
  33. package/dist/modules/shipment_tracking/api/carrier-configs/route.js +139 -0
  34. package/dist/modules/shipment_tracking/api/carrier-configs/route.js.map +7 -0
  35. package/dist/modules/shipment_tracking/api/dashboard/ships-map/route.js +177 -0
  36. package/dist/modules/shipment_tracking/api/dashboard/ships-map/route.js.map +7 -0
  37. package/dist/modules/shipment_tracking/api/location-overrides/route.js +179 -0
  38. package/dist/modules/shipment_tracking/api/location-overrides/route.js.map +7 -0
  39. package/dist/modules/shipment_tracking/api/openapi.js +27 -0
  40. package/dist/modules/shipment_tracking/api/openapi.js.map +7 -0
  41. package/dist/modules/shipment_tracking/api/shipments/route.js +192 -0
  42. package/dist/modules/shipment_tracking/api/shipments/route.js.map +7 -0
  43. package/dist/modules/shipment_tracking/api/shipsgo-configs/route.js +185 -0
  44. package/dist/modules/shipment_tracking/api/shipsgo-configs/route.js.map +7 -0
  45. package/dist/modules/shipment_tracking/api/tracking-jobs/route.js +144 -0
  46. package/dist/modules/shipment_tracking/api/tracking-jobs/route.js.map +7 -0
  47. package/dist/modules/shipment_tracking/api/tracking-jobs/sync/route.js +107 -0
  48. package/dist/modules/shipment_tracking/api/tracking-jobs/sync/route.js.map +7 -0
  49. package/dist/modules/shipment_tracking/api/utils.js +12 -0
  50. package/dist/modules/shipment_tracking/api/utils.js.map +7 -0
  51. package/dist/modules/shipment_tracking/api/webhooks/deliveries/route.js +76 -0
  52. package/dist/modules/shipment_tracking/api/webhooks/deliveries/route.js.map +7 -0
  53. package/dist/modules/shipment_tracking/api/webhooks/route.js +135 -0
  54. package/dist/modules/shipment_tracking/api/webhooks/route.js.map +7 -0
  55. package/dist/modules/shipment_tracking/api/webhooks/test/route.js +71 -0
  56. package/dist/modules/shipment_tracking/api/webhooks/test/route.js.map +7 -0
  57. package/dist/modules/shipment_tracking/assets/carriers/cma_cgm.png +0 -0
  58. package/dist/modules/shipment_tracking/assets/carriers/cosco.png +0 -0
  59. package/dist/modules/shipment_tracking/assets/carriers/evergreen.png +0 -0
  60. package/dist/modules/shipment_tracking/assets/carriers/hapag_lloyd.png +0 -0
  61. package/dist/modules/shipment_tracking/assets/carriers/maersk.png +0 -0
  62. package/dist/modules/shipment_tracking/assets/carriers/msc.png +0 -0
  63. package/dist/modules/shipment_tracking/assets/carriers/one.png +0 -0
  64. package/dist/modules/shipment_tracking/assets/carriers/oocl.png +0 -0
  65. package/dist/modules/shipment_tracking/assets/carriers/yang_ming.png +0 -0
  66. package/dist/modules/shipment_tracking/assets/carriers/zim.png +0 -0
  67. package/dist/modules/shipment_tracking/assets/index.js +52 -0
  68. package/dist/modules/shipment_tracking/assets/index.js.map +7 -0
  69. package/dist/modules/shipment_tracking/backend/carrier-configs/page.js +621 -0
  70. package/dist/modules/shipment_tracking/backend/carrier-configs/page.js.map +7 -0
  71. package/dist/modules/shipment_tracking/backend/carrier-configs/page.meta.js +19 -0
  72. package/dist/modules/shipment_tracking/backend/carrier-configs/page.meta.js.map +7 -0
  73. package/dist/modules/shipment_tracking/backend/location-overrides/page.js +198 -0
  74. package/dist/modules/shipment_tracking/backend/location-overrides/page.js.map +7 -0
  75. package/dist/modules/shipment_tracking/backend/location-overrides/page.meta.js +19 -0
  76. package/dist/modules/shipment_tracking/backend/location-overrides/page.meta.js.map +7 -0
  77. package/dist/modules/shipment_tracking/backend/shipment-tracking/page.js +279 -0
  78. package/dist/modules/shipment_tracking/backend/shipment-tracking/page.js.map +7 -0
  79. package/dist/modules/shipment_tracking/backend/shipment-tracking/page.meta.js +19 -0
  80. package/dist/modules/shipment_tracking/backend/shipment-tracking/page.meta.js.map +7 -0
  81. package/dist/modules/shipment_tracking/backend/tracking-jobs/page.js +10 -0
  82. package/dist/modules/shipment_tracking/backend/tracking-jobs/page.js.map +7 -0
  83. package/dist/modules/shipment_tracking/backend/tracking-jobs/page.meta.js +19 -0
  84. package/dist/modules/shipment_tracking/backend/tracking-jobs/page.meta.js.map +7 -0
  85. package/dist/modules/shipment_tracking/backend/webhooks/page.js +198 -0
  86. package/dist/modules/shipment_tracking/backend/webhooks/page.js.map +7 -0
  87. package/dist/modules/shipment_tracking/backend/webhooks/page.meta.js +19 -0
  88. package/dist/modules/shipment_tracking/backend/webhooks/page.meta.js.map +7 -0
  89. package/dist/modules/shipment_tracking/ce.js +52 -0
  90. package/dist/modules/shipment_tracking/ce.js.map +7 -0
  91. package/dist/modules/shipment_tracking/cli.js +229 -0
  92. package/dist/modules/shipment_tracking/cli.js.map +7 -0
  93. package/dist/modules/shipment_tracking/commands/bic-configs.js +66 -0
  94. package/dist/modules/shipment_tracking/commands/bic-configs.js.map +7 -0
  95. package/dist/modules/shipment_tracking/commands/carrier-configs.js +65 -0
  96. package/dist/modules/shipment_tracking/commands/carrier-configs.js.map +7 -0
  97. package/dist/modules/shipment_tracking/commands/index.js +9 -0
  98. package/dist/modules/shipment_tracking/commands/index.js.map +7 -0
  99. package/dist/modules/shipment_tracking/commands/location-overrides.js +93 -0
  100. package/dist/modules/shipment_tracking/commands/location-overrides.js.map +7 -0
  101. package/dist/modules/shipment_tracking/commands/shipments.js +200 -0
  102. package/dist/modules/shipment_tracking/commands/shipments.js.map +7 -0
  103. package/dist/modules/shipment_tracking/commands/shipsgo-configs.js +75 -0
  104. package/dist/modules/shipment_tracking/commands/shipsgo-configs.js.map +7 -0
  105. package/dist/modules/shipment_tracking/commands/tracking-jobs.js +120 -0
  106. package/dist/modules/shipment_tracking/commands/tracking-jobs.js.map +7 -0
  107. package/dist/modules/shipment_tracking/commands/tracking.js +140 -0
  108. package/dist/modules/shipment_tracking/commands/tracking.js.map +7 -0
  109. package/dist/modules/shipment_tracking/commands/webhooks.js +115 -0
  110. package/dist/modules/shipment_tracking/commands/webhooks.js.map +7 -0
  111. package/dist/modules/shipment_tracking/components/CombinedTimestampCell.js +168 -0
  112. package/dist/modules/shipment_tracking/components/CombinedTimestampCell.js.map +7 -0
  113. package/dist/modules/shipment_tracking/components/FacilityLocationInput.js +202 -0
  114. package/dist/modules/shipment_tracking/components/FacilityLocationInput.js.map +7 -0
  115. package/dist/modules/shipment_tracking/components/LocationOverrideDrawer.js +501 -0
  116. package/dist/modules/shipment_tracking/components/LocationOverrideDrawer.js.map +7 -0
  117. package/dist/modules/shipment_tracking/components/ShipmentDetailsDrawer.js +818 -0
  118. package/dist/modules/shipment_tracking/components/ShipmentDetailsDrawer.js.map +7 -0
  119. package/dist/modules/shipment_tracking/components/ShipmentDrawer.js +404 -0
  120. package/dist/modules/shipment_tracking/components/ShipmentDrawer.js.map +7 -0
  121. package/dist/modules/shipment_tracking/components/ShipsGoConfigSection.js +200 -0
  122. package/dist/modules/shipment_tracking/components/ShipsGoConfigSection.js.map +7 -0
  123. package/dist/modules/shipment_tracking/components/TimestampCell.js +108 -0
  124. package/dist/modules/shipment_tracking/components/TimestampCell.js.map +7 -0
  125. package/dist/modules/shipment_tracking/components/TrackingJobDrawer.js +343 -0
  126. package/dist/modules/shipment_tracking/components/TrackingJobDrawer.js.map +7 -0
  127. package/dist/modules/shipment_tracking/components/VesselTrackingMap.js +496 -0
  128. package/dist/modules/shipment_tracking/components/VesselTrackingMap.js.map +7 -0
  129. package/dist/modules/shipment_tracking/components/WebhookDrawer.js +332 -0
  130. package/dist/modules/shipment_tracking/components/WebhookDrawer.js.map +7 -0
  131. package/dist/modules/shipment_tracking/data/entities.js +686 -0
  132. package/dist/modules/shipment_tracking/data/entities.js.map +7 -0
  133. package/dist/modules/shipment_tracking/data/validators.js +434 -0
  134. package/dist/modules/shipment_tracking/data/validators.js.map +7 -0
  135. package/dist/modules/shipment_tracking/di.js +60 -0
  136. package/dist/modules/shipment_tracking/di.js.map +7 -0
  137. package/dist/modules/shipment_tracking/encryption.js +12 -0
  138. package/dist/modules/shipment_tracking/encryption.js.map +7 -0
  139. package/dist/modules/shipment_tracking/events.js +87 -0
  140. package/dist/modules/shipment_tracking/events.js.map +7 -0
  141. package/dist/modules/shipment_tracking/hooks/useVesselTracking.js +137 -0
  142. package/dist/modules/shipment_tracking/hooks/useVesselTracking.js.map +7 -0
  143. package/dist/modules/shipment_tracking/i18n/de.json +327 -0
  144. package/dist/modules/shipment_tracking/i18n/en.json +327 -0
  145. package/dist/modules/shipment_tracking/i18n/es.json +327 -0
  146. package/dist/modules/shipment_tracking/i18n/pl.json +327 -0
  147. package/dist/modules/shipment_tracking/index.js +15 -0
  148. package/dist/modules/shipment_tracking/index.js.map +7 -0
  149. package/dist/modules/shipment_tracking/lib/adapters/cma-cgm.js +66 -0
  150. package/dist/modules/shipment_tracking/lib/adapters/cma-cgm.js.map +7 -0
  151. package/dist/modules/shipment_tracking/lib/adapters/cosco-types.js +1 -0
  152. package/dist/modules/shipment_tracking/lib/adapters/cosco-types.js.map +7 -0
  153. package/dist/modules/shipment_tracking/lib/adapters/cosco.js +236 -0
  154. package/dist/modules/shipment_tracking/lib/adapters/cosco.js.map +7 -0
  155. package/dist/modules/shipment_tracking/lib/adapters/evergreen.js +87 -0
  156. package/dist/modules/shipment_tracking/lib/adapters/evergreen.js.map +7 -0
  157. package/dist/modules/shipment_tracking/lib/adapters/hapag-lloyd.js +68 -0
  158. package/dist/modules/shipment_tracking/lib/adapters/hapag-lloyd.js.map +7 -0
  159. package/dist/modules/shipment_tracking/lib/adapters/index.js +20 -0
  160. package/dist/modules/shipment_tracking/lib/adapters/index.js.map +7 -0
  161. package/dist/modules/shipment_tracking/lib/adapters/maersk.js +84 -0
  162. package/dist/modules/shipment_tracking/lib/adapters/maersk.js.map +7 -0
  163. package/dist/modules/shipment_tracking/lib/adapters/msc.js +170 -0
  164. package/dist/modules/shipment_tracking/lib/adapters/msc.js.map +7 -0
  165. package/dist/modules/shipment_tracking/lib/adapters/zim.js +85 -0
  166. package/dist/modules/shipment_tracking/lib/adapters/zim.js.map +7 -0
  167. package/dist/modules/shipment_tracking/lib/audit-helpers.js +20 -0
  168. package/dist/modules/shipment_tracking/lib/audit-helpers.js.map +7 -0
  169. package/dist/modules/shipment_tracking/lib/auth/base64url.js +8 -0
  170. package/dist/modules/shipment_tracking/lib/auth/base64url.js.map +7 -0
  171. package/dist/modules/shipment_tracking/lib/auth/oauth-client.js +38 -0
  172. package/dist/modules/shipment_tracking/lib/auth/oauth-client.js.map +7 -0
  173. package/dist/modules/shipment_tracking/lib/background.js +15 -0
  174. package/dist/modules/shipment_tracking/lib/background.js.map +7 -0
  175. package/dist/modules/shipment_tracking/lib/bic-api-client.js +106 -0
  176. package/dist/modules/shipment_tracking/lib/bic-api-client.js.map +7 -0
  177. package/dist/modules/shipment_tracking/lib/carrier-adapter.js +17 -0
  178. package/dist/modules/shipment_tracking/lib/carrier-adapter.js.map +7 -0
  179. package/dist/modules/shipment_tracking/lib/current-vessel.js +149 -0
  180. package/dist/modules/shipment_tracking/lib/current-vessel.js.map +7 -0
  181. package/dist/modules/shipment_tracking/lib/dcsa-event-mapping.js +124 -0
  182. package/dist/modules/shipment_tracking/lib/dcsa-event-mapping.js.map +7 -0
  183. package/dist/modules/shipment_tracking/lib/dcsa-event-parser.js +112 -0
  184. package/dist/modules/shipment_tracking/lib/dcsa-event-parser.js.map +7 -0
  185. package/dist/modules/shipment_tracking/lib/dcsa-params.js +16 -0
  186. package/dist/modules/shipment_tracking/lib/dcsa-params.js.map +7 -0
  187. package/dist/modules/shipment_tracking/lib/empty-return.js +48 -0
  188. package/dist/modules/shipment_tracking/lib/empty-return.js.map +7 -0
  189. package/dist/modules/shipment_tracking/lib/location-overrides.js +85 -0
  190. package/dist/modules/shipment_tracking/lib/location-overrides.js.map +7 -0
  191. package/dist/modules/shipment_tracking/lib/location-types.js +59 -0
  192. package/dist/modules/shipment_tracking/lib/location-types.js.map +7 -0
  193. package/dist/modules/shipment_tracking/lib/logger.js +113 -0
  194. package/dist/modules/shipment_tracking/lib/logger.js.map +7 -0
  195. package/dist/modules/shipment_tracking/lib/poi-event-processor.js +183 -0
  196. package/dist/modules/shipment_tracking/lib/poi-event-processor.js.map +7 -0
  197. package/dist/modules/shipment_tracking/lib/poi-nats-config.js +52 -0
  198. package/dist/modules/shipment_tracking/lib/poi-nats-config.js.map +7 -0
  199. package/dist/modules/shipment_tracking/lib/poi-types.js +43 -0
  200. package/dist/modules/shipment_tracking/lib/poi-types.js.map +7 -0
  201. package/dist/modules/shipment_tracking/lib/rate-limiter.js +31 -0
  202. package/dist/modules/shipment_tracking/lib/rate-limiter.js.map +7 -0
  203. package/dist/modules/shipment_tracking/lib/route-extraction.js +187 -0
  204. package/dist/modules/shipment_tracking/lib/route-extraction.js.map +7 -0
  205. package/dist/modules/shipment_tracking/lib/route-inference.js +106 -0
  206. package/dist/modules/shipment_tracking/lib/route-inference.js.map +7 -0
  207. package/dist/modules/shipment_tracking/lib/schedule-generator.js +63 -0
  208. package/dist/modules/shipment_tracking/lib/schedule-generator.js.map +7 -0
  209. package/dist/modules/shipment_tracking/lib/shipsgo-client.js +143 -0
  210. package/dist/modules/shipment_tracking/lib/shipsgo-client.js.map +7 -0
  211. package/dist/modules/shipment_tracking/lib/shipsgo-mapper.js +204 -0
  212. package/dist/modules/shipment_tracking/lib/shipsgo-mapper.js.map +7 -0
  213. package/dist/modules/shipment_tracking/lib/status-machine.js +131 -0
  214. package/dist/modules/shipment_tracking/lib/status-machine.js.map +7 -0
  215. package/dist/modules/shipment_tracking/lib/time-extraction.js +41 -0
  216. package/dist/modules/shipment_tracking/lib/time-extraction.js.map +7 -0
  217. package/dist/modules/shipment_tracking/lib/timestamp-utils.js +100 -0
  218. package/dist/modules/shipment_tracking/lib/timestamp-utils.js.map +7 -0
  219. package/dist/modules/shipment_tracking/lib/vessel-api.js +111 -0
  220. package/dist/modules/shipment_tracking/lib/vessel-api.js.map +7 -0
  221. package/dist/modules/shipment_tracking/lib/vessel-cache.js +50 -0
  222. package/dist/modules/shipment_tracking/lib/vessel-cache.js.map +7 -0
  223. package/dist/modules/shipment_tracking/lib/vessel-extraction.js +13 -0
  224. package/dist/modules/shipment_tracking/lib/vessel-extraction.js.map +7 -0
  225. package/dist/modules/shipment_tracking/lib/webhook-dispatcher.js +62 -0
  226. package/dist/modules/shipment_tracking/lib/webhook-dispatcher.js.map +7 -0
  227. package/dist/modules/shipment_tracking/migrations/Migration20260422161208_shipment_tracking.js +48 -0
  228. package/dist/modules/shipment_tracking/migrations/Migration20260422161208_shipment_tracking.js.map +7 -0
  229. package/dist/modules/shipment_tracking/migrations/Migration20260529120000_shipment_tracking_poi_region_names.js +15 -0
  230. package/dist/modules/shipment_tracking/migrations/Migration20260529120000_shipment_tracking_poi_region_names.js.map +7 -0
  231. package/dist/modules/shipment_tracking/migrations/Migration20260821120000_shipment_tracking_shipsgo.js +47 -0
  232. package/dist/modules/shipment_tracking/migrations/Migration20260821120000_shipment_tracking_shipsgo.js.map +7 -0
  233. package/dist/modules/shipment_tracking/notifications.js +145 -0
  234. package/dist/modules/shipment_tracking/notifications.js.map +7 -0
  235. package/dist/modules/shipment_tracking/services/carrierRegistry.js +24 -0
  236. package/dist/modules/shipment_tracking/services/carrierRegistry.js.map +7 -0
  237. package/dist/modules/shipment_tracking/services/poiNatsService.js +397 -0
  238. package/dist/modules/shipment_tracking/services/poiNatsService.js.map +7 -0
  239. package/dist/modules/shipment_tracking/services/shipsGoProvider.js +163 -0
  240. package/dist/modules/shipment_tracking/services/shipsGoProvider.js.map +7 -0
  241. package/dist/modules/shipment_tracking/services/trackingService.js +1283 -0
  242. package/dist/modules/shipment_tracking/services/trackingService.js.map +7 -0
  243. package/dist/modules/shipment_tracking/services/webhookService.js +263 -0
  244. package/dist/modules/shipment_tracking/services/webhookService.js.map +7 -0
  245. package/dist/modules/shipment_tracking/setup.js +72 -0
  246. package/dist/modules/shipment_tracking/setup.js.map +7 -0
  247. package/dist/modules/shipment_tracking/subscribers/cargo-event-created.js +60 -0
  248. package/dist/modules/shipment_tracking/subscribers/cargo-event-created.js.map +7 -0
  249. package/dist/modules/shipment_tracking/subscribers/dcsa-event-webhook-dispatch.js +58 -0
  250. package/dist/modules/shipment_tracking/subscribers/dcsa-event-webhook-dispatch.js.map +7 -0
  251. package/dist/modules/shipment_tracking/subscribers/poi-event-notification.js +82 -0
  252. package/dist/modules/shipment_tracking/subscribers/poi-event-notification.js.map +7 -0
  253. package/dist/modules/shipment_tracking/subscribers/poi-event-webhook-dispatch.js +53 -0
  254. package/dist/modules/shipment_tracking/subscribers/poi-event-webhook-dispatch.js.map +7 -0
  255. package/dist/modules/shipment_tracking/subscribers/shipment-status-changed.js +28 -0
  256. package/dist/modules/shipment_tracking/subscribers/shipment-status-changed.js.map +7 -0
  257. package/dist/modules/shipment_tracking/subscribers/terminal-event-ingest.js +67 -0
  258. package/dist/modules/shipment_tracking/subscribers/terminal-event-ingest.js.map +7 -0
  259. package/dist/modules/shipment_tracking/subscribers/tracking-job-initial-poll.js +30 -0
  260. package/dist/modules/shipment_tracking/subscribers/tracking-job-initial-poll.js.map +7 -0
  261. package/dist/modules/shipment_tracking/subscribers/tracking-job-webhook-dispatch.js +19 -0
  262. package/dist/modules/shipment_tracking/subscribers/tracking-job-webhook-dispatch.js.map +7 -0
  263. package/dist/modules/shipment_tracking/tables/index.js +6 -0
  264. package/dist/modules/shipment_tracking/tables/index.js.map +7 -0
  265. package/dist/modules/shipment_tracking/tables/tracking_job/table.client.js +284 -0
  266. package/dist/modules/shipment_tracking/tables/tracking_job/table.client.js.map +7 -0
  267. package/dist/modules/shipment_tracking/tables/tracking_job/table.js +36 -0
  268. package/dist/modules/shipment_tracking/tables/tracking_job/table.js.map +7 -0
  269. package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/config.js +25 -0
  270. package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/config.js.map +7 -0
  271. package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/widget.client.js +355 -0
  272. package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/widget.client.js.map +7 -0
  273. package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/widget.js +26 -0
  274. package/dist/modules/shipment_tracking/widgets/dashboard/ships-map/widget.js.map +7 -0
  275. package/dist/types/assets.d.js +1 -0
  276. package/dist/types/assets.d.js.map +7 -0
  277. package/generated/entities/bic_config/index.ts +20 -0
  278. package/generated/entities/carrier_config/index.ts +23 -0
  279. package/generated/entities/location_override/index.ts +26 -0
  280. package/generated/entities/shipment/index.ts +46 -0
  281. package/generated/entities/ships_go_config/index.ts +25 -0
  282. package/generated/entities/tracking_event/index.ts +60 -0
  283. package/generated/entities/tracking_job/index.ts +33 -0
  284. package/generated/entities/webhook/index.ts +22 -0
  285. package/generated/entities/webhook_delivery/index.ts +22 -0
  286. package/generated/entities.ids.generated.ts +47 -0
  287. package/package.json +81 -0
  288. package/src/index.ts +39 -0
  289. package/src/modules/shipment_tracking/__integration__/TC-TRACK-410-shipsgo-config-api.spec.ts +133 -0
  290. package/src/modules/shipment_tracking/__integration__/meta.ts +4 -0
  291. package/src/modules/shipment_tracking/__tests__/empty-return-stop.test.ts +231 -0
  292. package/src/modules/shipment_tracking/__tests__/fixtures/hapag-lloyd-transship-container.json +702 -0
  293. package/src/modules/shipment_tracking/__tests__/fixtures/index.ts +434 -0
  294. package/src/modules/shipment_tracking/__tests__/fixtures/maersk-multi-transship-completed.json +1518 -0
  295. package/src/modules/shipment_tracking/__tests__/fixtures/maersk-transship-intransit.json +558 -0
  296. package/src/modules/shipment_tracking/__tests__/fixtures/msc-direct.json +222 -0
  297. package/src/modules/shipment_tracking/__tests__/fixtures/msc-multi-transship-completed.json +974 -0
  298. package/src/modules/shipment_tracking/__tests__/fixtures/msc-multi.json +4846 -0
  299. package/src/modules/shipment_tracking/__tests__/fixtures/msc-transship.json +409 -0
  300. package/src/modules/shipment_tracking/__tests__/fixtures/poi-events.json +240 -0
  301. package/src/modules/shipment_tracking/__tests__/fixtures/synthetic/index.ts +138 -0
  302. package/src/modules/shipment_tracking/__tests__/fixtures/synthetic-eta-updates.json +288 -0
  303. package/src/modules/shipment_tracking/__tests__/fixtures/synthetic-route-inference.json +201 -0
  304. package/src/modules/shipment_tracking/__tests__/fixtures/synthetic-voyage-progression.json +410 -0
  305. package/src/modules/shipment_tracking/__tests__/shipsgo-air-mapper.test.ts +157 -0
  306. package/src/modules/shipment_tracking/__tests__/shipsgo-client.test.ts +155 -0
  307. package/src/modules/shipment_tracking/__tests__/shipsgo-mapper.test.ts +201 -0
  308. package/src/modules/shipment_tracking/__tests__/shipsgo-poll.test.ts +357 -0
  309. package/src/modules/shipment_tracking/__tests__/shipsgo-provider.test.ts +364 -0
  310. package/src/modules/shipment_tracking/__tests__/trackingService.integration.test.ts +2248 -0
  311. package/src/modules/shipment_tracking/__tests__/webhookPayload.test.ts +151 -0
  312. package/src/modules/shipment_tracking/acl.ts +18 -0
  313. package/src/modules/shipment_tracking/api/bic-configs/route.ts +206 -0
  314. package/src/modules/shipment_tracking/api/bic-configs/test/route.ts +108 -0
  315. package/src/modules/shipment_tracking/api/cargo-events/route.ts +101 -0
  316. package/src/modules/shipment_tracking/api/carrier-configs/route.ts +142 -0
  317. package/src/modules/shipment_tracking/api/dashboard/ships-map/route.ts +246 -0
  318. package/src/modules/shipment_tracking/api/location-overrides/route.ts +185 -0
  319. package/src/modules/shipment_tracking/api/openapi.ts +28 -0
  320. package/src/modules/shipment_tracking/api/shipments/route.ts +197 -0
  321. package/src/modules/shipment_tracking/api/shipsgo-configs/route.ts +215 -0
  322. package/src/modules/shipment_tracking/api/tracking-jobs/route.ts +149 -0
  323. package/src/modules/shipment_tracking/api/tracking-jobs/sync/route.ts +116 -0
  324. package/src/modules/shipment_tracking/api/utils.ts +10 -0
  325. package/src/modules/shipment_tracking/api/webhooks/deliveries/route.ts +82 -0
  326. package/src/modules/shipment_tracking/api/webhooks/route.ts +138 -0
  327. package/src/modules/shipment_tracking/api/webhooks/test/route.ts +84 -0
  328. package/src/modules/shipment_tracking/assets/carriers/cma_cgm.png +0 -0
  329. package/src/modules/shipment_tracking/assets/carriers/cosco.png +0 -0
  330. package/src/modules/shipment_tracking/assets/carriers/evergreen.png +0 -0
  331. package/src/modules/shipment_tracking/assets/carriers/hapag_lloyd.png +0 -0
  332. package/src/modules/shipment_tracking/assets/carriers/maersk.png +0 -0
  333. package/src/modules/shipment_tracking/assets/carriers/msc.png +0 -0
  334. package/src/modules/shipment_tracking/assets/carriers/one.png +0 -0
  335. package/src/modules/shipment_tracking/assets/carriers/oocl.png +0 -0
  336. package/src/modules/shipment_tracking/assets/carriers/yang_ming.png +0 -0
  337. package/src/modules/shipment_tracking/assets/carriers/zim.png +0 -0
  338. package/src/modules/shipment_tracking/assets/index.ts +66 -0
  339. package/src/modules/shipment_tracking/backend/carrier-configs/page.meta.ts +16 -0
  340. package/src/modules/shipment_tracking/backend/carrier-configs/page.tsx +782 -0
  341. package/src/modules/shipment_tracking/backend/location-overrides/page.meta.ts +16 -0
  342. package/src/modules/shipment_tracking/backend/location-overrides/page.tsx +241 -0
  343. package/src/modules/shipment_tracking/backend/shipment-tracking/page.meta.ts +16 -0
  344. package/src/modules/shipment_tracking/backend/shipment-tracking/page.tsx +340 -0
  345. package/src/modules/shipment_tracking/backend/tracking-jobs/page.meta.ts +16 -0
  346. package/src/modules/shipment_tracking/backend/tracking-jobs/page.tsx +16 -0
  347. package/src/modules/shipment_tracking/backend/webhooks/page.meta.ts +16 -0
  348. package/src/modules/shipment_tracking/backend/webhooks/page.tsx +228 -0
  349. package/src/modules/shipment_tracking/ce.ts +48 -0
  350. package/src/modules/shipment_tracking/cli.ts +321 -0
  351. package/src/modules/shipment_tracking/commands/bic-configs.ts +94 -0
  352. package/src/modules/shipment_tracking/commands/carrier-configs.ts +89 -0
  353. package/src/modules/shipment_tracking/commands/index.ts +8 -0
  354. package/src/modules/shipment_tracking/commands/location-overrides.ts +119 -0
  355. package/src/modules/shipment_tracking/commands/shipments.ts +247 -0
  356. package/src/modules/shipment_tracking/commands/shipsgo-configs.ts +101 -0
  357. package/src/modules/shipment_tracking/commands/tracking-jobs.ts +158 -0
  358. package/src/modules/shipment_tracking/commands/tracking.ts +230 -0
  359. package/src/modules/shipment_tracking/commands/webhooks.ts +159 -0
  360. package/src/modules/shipment_tracking/components/CombinedTimestampCell.tsx +236 -0
  361. package/src/modules/shipment_tracking/components/FacilityLocationInput.tsx +235 -0
  362. package/src/modules/shipment_tracking/components/LocationOverrideDrawer.tsx +586 -0
  363. package/src/modules/shipment_tracking/components/ShipmentDetailsDrawer.tsx +1364 -0
  364. package/src/modules/shipment_tracking/components/ShipmentDrawer.tsx +498 -0
  365. package/src/modules/shipment_tracking/components/ShipsGoConfigSection.tsx +266 -0
  366. package/src/modules/shipment_tracking/components/TimestampCell.tsx +146 -0
  367. package/src/modules/shipment_tracking/components/TrackingJobDrawer.tsx +467 -0
  368. package/src/modules/shipment_tracking/components/VesselTrackingMap.tsx +761 -0
  369. package/src/modules/shipment_tracking/components/WebhookDrawer.tsx +434 -0
  370. package/src/modules/shipment_tracking/data/entities.ts +748 -0
  371. package/src/modules/shipment_tracking/data/validators.ts +523 -0
  372. package/src/modules/shipment_tracking/di.ts +73 -0
  373. package/src/modules/shipment_tracking/encryption.ts +17 -0
  374. package/src/modules/shipment_tracking/events.ts +122 -0
  375. package/src/modules/shipment_tracking/hooks/useVesselTracking.ts +297 -0
  376. package/src/modules/shipment_tracking/i18n/de.json +327 -0
  377. package/src/modules/shipment_tracking/i18n/en.json +327 -0
  378. package/src/modules/shipment_tracking/i18n/es.json +327 -0
  379. package/src/modules/shipment_tracking/i18n/pl.json +327 -0
  380. package/src/modules/shipment_tracking/index.ts +13 -0
  381. package/src/modules/shipment_tracking/lib/__tests__/dcsa-event-mapping.test.ts +385 -0
  382. package/src/modules/shipment_tracking/lib/__tests__/dcsa-event-parser.test.ts +398 -0
  383. package/src/modules/shipment_tracking/lib/__tests__/empty-return.test.ts +174 -0
  384. package/src/modules/shipment_tracking/lib/__tests__/poi-event-processor.test.ts +699 -0
  385. package/src/modules/shipment_tracking/lib/__tests__/route-inference.test.ts +402 -0
  386. package/src/modules/shipment_tracking/lib/__tests__/status-machine.test.ts +447 -0
  387. package/src/modules/shipment_tracking/lib/__tests__/time-extraction.test.ts +331 -0
  388. package/src/modules/shipment_tracking/lib/__tests__/timestamp-utils.test.ts +260 -0
  389. package/src/modules/shipment_tracking/lib/__tests__/vessel-api.test.ts +125 -0
  390. package/src/modules/shipment_tracking/lib/__tests__/vessel-extraction.test.ts +108 -0
  391. package/src/modules/shipment_tracking/lib/adapters/cma-cgm.ts +84 -0
  392. package/src/modules/shipment_tracking/lib/adapters/cosco-types.ts +145 -0
  393. package/src/modules/shipment_tracking/lib/adapters/cosco.ts +314 -0
  394. package/src/modules/shipment_tracking/lib/adapters/evergreen.ts +107 -0
  395. package/src/modules/shipment_tracking/lib/adapters/hapag-lloyd.ts +88 -0
  396. package/src/modules/shipment_tracking/lib/adapters/index.ts +18 -0
  397. package/src/modules/shipment_tracking/lib/adapters/maersk.ts +104 -0
  398. package/src/modules/shipment_tracking/lib/adapters/msc.ts +223 -0
  399. package/src/modules/shipment_tracking/lib/adapters/zim.ts +106 -0
  400. package/src/modules/shipment_tracking/lib/audit-helpers.ts +29 -0
  401. package/src/modules/shipment_tracking/lib/auth/base64url.ts +4 -0
  402. package/src/modules/shipment_tracking/lib/auth/oauth-client.ts +53 -0
  403. package/src/modules/shipment_tracking/lib/background.ts +24 -0
  404. package/src/modules/shipment_tracking/lib/bic-api-client.ts +199 -0
  405. package/src/modules/shipment_tracking/lib/carrier-adapter.ts +136 -0
  406. package/src/modules/shipment_tracking/lib/current-vessel.ts +274 -0
  407. package/src/modules/shipment_tracking/lib/dcsa-event-mapping.ts +202 -0
  408. package/src/modules/shipment_tracking/lib/dcsa-event-parser.ts +163 -0
  409. package/src/modules/shipment_tracking/lib/dcsa-params.ts +14 -0
  410. package/src/modules/shipment_tracking/lib/empty-return.ts +122 -0
  411. package/src/modules/shipment_tracking/lib/location-overrides.ts +150 -0
  412. package/src/modules/shipment_tracking/lib/location-types.ts +154 -0
  413. package/src/modules/shipment_tracking/lib/logger.ts +195 -0
  414. package/src/modules/shipment_tracking/lib/poi-event-processor.ts +302 -0
  415. package/src/modules/shipment_tracking/lib/poi-nats-config.ts +134 -0
  416. package/src/modules/shipment_tracking/lib/poi-types.ts +198 -0
  417. package/src/modules/shipment_tracking/lib/rate-limiter.ts +58 -0
  418. package/src/modules/shipment_tracking/lib/route-extraction.ts +439 -0
  419. package/src/modules/shipment_tracking/lib/route-inference.ts +238 -0
  420. package/src/modules/shipment_tracking/lib/schedule-generator.ts +92 -0
  421. package/src/modules/shipment_tracking/lib/shipsgo-client.ts +350 -0
  422. package/src/modules/shipment_tracking/lib/shipsgo-mapper.ts +296 -0
  423. package/src/modules/shipment_tracking/lib/status-machine.ts +230 -0
  424. package/src/modules/shipment_tracking/lib/time-extraction.ts +85 -0
  425. package/src/modules/shipment_tracking/lib/timestamp-utils.ts +244 -0
  426. package/src/modules/shipment_tracking/lib/vessel-api.ts +299 -0
  427. package/src/modules/shipment_tracking/lib/vessel-cache.ts +102 -0
  428. package/src/modules/shipment_tracking/lib/vessel-extraction.ts +39 -0
  429. package/src/modules/shipment_tracking/lib/webhook-dispatcher.ts +93 -0
  430. package/src/modules/shipment_tracking/migrations/.snapshot-open-mercato.json +2914 -0
  431. package/src/modules/shipment_tracking/migrations/Migration20260422161208_shipment_tracking.ts +60 -0
  432. package/src/modules/shipment_tracking/migrations/Migration20260529120000_shipment_tracking_poi_region_names.ts +22 -0
  433. package/src/modules/shipment_tracking/migrations/Migration20260821120000_shipment_tracking_shipsgo.ts +65 -0
  434. package/src/modules/shipment_tracking/notifications.ts +151 -0
  435. package/src/modules/shipment_tracking/services/carrierRegistry.ts +29 -0
  436. package/src/modules/shipment_tracking/services/poiNatsService.ts +526 -0
  437. package/src/modules/shipment_tracking/services/shipsGoProvider.ts +231 -0
  438. package/src/modules/shipment_tracking/services/trackingService.ts +1777 -0
  439. package/src/modules/shipment_tracking/services/webhookService.ts +347 -0
  440. package/src/modules/shipment_tracking/setup.ts +99 -0
  441. package/src/modules/shipment_tracking/subscribers/__tests__/terminal-event-ingest.test.ts +141 -0
  442. package/src/modules/shipment_tracking/subscribers/cargo-event-created.ts +115 -0
  443. package/src/modules/shipment_tracking/subscribers/dcsa-event-webhook-dispatch.ts +115 -0
  444. package/src/modules/shipment_tracking/subscribers/poi-event-notification.ts +144 -0
  445. package/src/modules/shipment_tracking/subscribers/poi-event-webhook-dispatch.ts +94 -0
  446. package/src/modules/shipment_tracking/subscribers/shipment-status-changed.ts +41 -0
  447. package/src/modules/shipment_tracking/subscribers/terminal-event-ingest.ts +109 -0
  448. package/src/modules/shipment_tracking/subscribers/tracking-job-initial-poll.ts +53 -0
  449. package/src/modules/shipment_tracking/subscribers/tracking-job-webhook-dispatch.ts +50 -0
  450. package/src/modules/shipment_tracking/tables/index.ts +4 -0
  451. package/src/modules/shipment_tracking/tables/tracking_job/table.client.tsx +337 -0
  452. package/src/modules/shipment_tracking/tables/tracking_job/table.ts +34 -0
  453. package/src/modules/shipment_tracking/widgets/dashboard/ships-map/config.ts +32 -0
  454. package/src/modules/shipment_tracking/widgets/dashboard/ships-map/widget.client.tsx +448 -0
  455. package/src/modules/shipment_tracking/widgets/dashboard/ships-map/widget.ts +25 -0
  456. package/src/types/assets.d.ts +5 -0
@@ -0,0 +1,223 @@
1
+ import crypto from 'node:crypto'
2
+ import fs, { writeFileSync } from 'node:fs'
3
+ import os from 'node:os'
4
+ import path from 'node:path'
5
+ import { execFileSync } from 'node:child_process'
6
+ import type { CarrierAdapter, CarrierFetchResult, CarrierAdapterTestResult } from '../carrier-adapter'
7
+ import { extractDocumentReferences } from '../carrier-adapter'
8
+ import type { TrackingReferenceType } from '../../data/entities'
9
+ import { base64UrlEncode } from '../auth/base64url'
10
+ import { buildDcsaQueryParams } from '../dcsa-params'
11
+ import { parseDcsaEvents } from '../dcsa-event-parser'
12
+ import { withCarrierApiSpan } from '../logger'
13
+
14
+ // MSC's public track-and-trace events endpoint (DCSA). Overridable per carrier
15
+ // config via `apiEndpoint`.
16
+ const EVENTS_URL = 'https://api.tech.msc.com/msc/trackandtrace/v2.2/events'
17
+
18
+ /**
19
+ * MSC OAuth account identity. These values are specific to the API account MSC
20
+ * issues to each integrator (Azure AD tenant, registered client_id and API
21
+ * scope) and are NOT shipped as defaults — supply them, together with the PFX
22
+ * certificate, through the carrier config's `authConfig`.
23
+ */
24
+ type MscAuthConfig = {
25
+ certificate_base64: string
26
+ clientId: string
27
+ scope: string
28
+ tokenUrl: string
29
+ aud: string
30
+ }
31
+
32
+ function getAuth(authConfig: Record<string, unknown> | null | undefined): MscAuthConfig {
33
+ const certBase64 = authConfig?.certificate_base64 as string | undefined
34
+ const clientId = authConfig?.client_id as string | undefined
35
+ const scope = authConfig?.scope as string | undefined
36
+ const tokenUrl = authConfig?.token_url as string | undefined
37
+ const aud = (authConfig?.aud as string | undefined) || tokenUrl
38
+ const missing = [
39
+ !certBase64 && 'certificate_base64',
40
+ !clientId && 'client_id',
41
+ !scope && 'scope',
42
+ !tokenUrl && 'token_url',
43
+ ].filter(Boolean)
44
+ if (missing.length) {
45
+ throw new Error(`MSC authConfig requires: ${missing.join(', ')}`)
46
+ }
47
+ return {
48
+ certificate_base64: certBase64!,
49
+ clientId: clientId!,
50
+ scope: scope!,
51
+ tokenUrl: tokenUrl!,
52
+ aud: aud!,
53
+ }
54
+ }
55
+
56
+ function extractPfxComponents(pfxBuffer: Buffer): { privateKeyPem: string; certPem: string } {
57
+ const tempDir = os.tmpdir()
58
+ const uid = crypto.randomUUID()
59
+ const pfxPath = path.join(tempDir, `msc_${uid}.pfx`)
60
+ const certPath = path.join(tempDir, `msc_cert_${uid}.pem`)
61
+ const keyPath = path.join(tempDir, `msc_key_${uid}.pem`)
62
+
63
+ try {
64
+ fs.writeFileSync(pfxPath, pfxBuffer)
65
+
66
+ execFileSync('openssl', ['pkcs12', '-in', pfxPath, '-nokeys', '-out', certPath, '-passin', 'pass:'])
67
+ execFileSync('openssl', ['pkcs12', '-in', pfxPath, '-nocerts', '-nodes', '-out', keyPath, '-passin', 'pass:'])
68
+
69
+ const certPem = fs.readFileSync(certPath, 'utf8')
70
+ const privateKeyPem = fs.readFileSync(keyPath, 'utf8')
71
+
72
+ return { privateKeyPem, certPem }
73
+ } finally {
74
+ for (const filePath of [pfxPath, certPath, keyPath]) {
75
+ try { fs.unlinkSync(filePath) } catch { /* ignore cleanup errors */ }
76
+ }
77
+ }
78
+ }
79
+
80
+ function createMscJwt(auth: MscAuthConfig): string {
81
+ const pfxBuffer = Buffer.from(auth.certificate_base64, 'base64')
82
+ const { privateKeyPem, certPem } = extractPfxComponents(pfxBuffer)
83
+
84
+ // Extract the last certificate from the chain for x5t thumbprint
85
+ const certMatches = certPem.match(/-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g)
86
+ if (!certMatches?.length) {
87
+ throw new Error('No certificates found in PFX')
88
+ }
89
+
90
+ const lastCert = certMatches[certMatches.length - 1]
91
+ const certDerBase64 = lastCert
92
+ .replace(/-----BEGIN CERTIFICATE-----/g, '')
93
+ .replace(/-----END CERTIFICATE-----/g, '')
94
+ .replace(/\r?\n/g, '')
95
+ .trim()
96
+
97
+ const certDer = Buffer.from(certDerBase64, 'base64')
98
+ const sha1Hash = crypto.createHash('sha1').update(certDer).digest()
99
+ const x5t = base64UrlEncode(sha1Hash)
100
+
101
+ const now = Math.floor(Date.now() / 1000)
102
+
103
+ const header = { alg: 'RS256', typ: 'JWT', x5t }
104
+ const payload = {
105
+ aud: auth.aud,
106
+ exp: now + 120,
107
+ iss: auth.clientId,
108
+ jti: crypto.randomUUID(),
109
+ nbf: now,
110
+ sub: auth.clientId,
111
+ }
112
+
113
+ const encodedHeader = base64UrlEncode(JSON.stringify(header))
114
+ const encodedPayload = base64UrlEncode(JSON.stringify(payload))
115
+ const unsignedToken = `${encodedHeader}.${encodedPayload}`
116
+
117
+ const sign = crypto.createSign('RSA-SHA256')
118
+ sign.update(unsignedToken)
119
+ const signature = sign.sign(privateKeyPem)
120
+ const encodedSignature = base64UrlEncode(signature)
121
+
122
+ return `${unsignedToken}.${encodedSignature}`
123
+ }
124
+
125
+ async function authenticate(auth: MscAuthConfig): Promise<string> {
126
+ return withCarrierApiSpan(
127
+ { carrierCode: 'msc', operation: 'authenticate' },
128
+ async (span) => {
129
+ const jwt = createMscJwt(auth)
130
+
131
+ const body = new URLSearchParams({
132
+ client_id: auth.clientId,
133
+ client_assertion: jwt,
134
+ client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
135
+ scope: auth.scope,
136
+ grant_type: 'client_credentials',
137
+ })
138
+
139
+ const response = await fetch(auth.tokenUrl, {
140
+ method: 'POST',
141
+ headers: {
142
+ 'Authorization': `Bearer ${jwt}`,
143
+ 'Content-Type': 'application/x-www-form-urlencoded',
144
+ },
145
+ body: body.toString(),
146
+ })
147
+
148
+ span.setAttribute('http.status_code', response.status)
149
+
150
+ if (!response.ok) {
151
+ const errorText = await response.text().catch(() => 'unknown')
152
+ throw new Error(`MSC token request failed (${response.status}): ${errorText}`)
153
+ }
154
+
155
+ const data = await response.json() as { access_token: string }
156
+ return data.access_token
157
+ },
158
+ )
159
+ }
160
+
161
+ export class MscAdapter implements CarrierAdapter {
162
+ readonly carrierCode = 'msc'
163
+ readonly supportedReferenceTypes: TrackingReferenceType[] = ['container', 'booking', 'bol']
164
+
165
+ async fetchEvents(input: {
166
+ referenceType: TrackingReferenceType
167
+ referenceValue: string
168
+ apiEndpoint?: string | null
169
+ authConfig?: Record<string, unknown> | null
170
+ }): Promise<CarrierFetchResult> {
171
+ return withCarrierApiSpan(
172
+ {
173
+ carrierCode: this.carrierCode,
174
+ operation: 'fetchEvents',
175
+ referenceType: input.referenceType,
176
+ referenceValue: input.referenceValue,
177
+ },
178
+ async (span) => {
179
+ const auth = getAuth(input.authConfig)
180
+ const token = await authenticate(auth)
181
+ const params = buildDcsaQueryParams(input.referenceValue, input.referenceType)
182
+ const url = `${input.apiEndpoint || EVENTS_URL}?${params}`
183
+
184
+ const response = await fetch(url, {
185
+ headers: {
186
+ 'Authorization': `Bearer ${token}`,
187
+ 'Content-Type': 'application/json',
188
+ },
189
+ })
190
+
191
+ span.setAttribute('http.status_code', response.status)
192
+
193
+ if (!response.ok) {
194
+ const errorText = await response.text().catch(() => 'unknown')
195
+ throw new Error(`MSC API error (${response.status}): ${errorText}`)
196
+ }
197
+
198
+ const data = await response.json()
199
+ const events = parseDcsaEvents(data, 'MSC')
200
+
201
+ const { bookingNumber, bolNumber } = extractDocumentReferences(events)
202
+
203
+ span.setAttribute('events.count', events.length)
204
+ return { events, bookingNumber, bolNumber }
205
+ },
206
+ )
207
+ }
208
+
209
+ async testConnection(input: {
210
+ apiEndpoint?: string | null
211
+ authConfig?: Record<string, unknown> | null
212
+ }): Promise<CarrierAdapterTestResult> {
213
+ const start = Date.now()
214
+ try {
215
+ const auth = getAuth(input.authConfig)
216
+ await authenticate(auth)
217
+ return { success: true, message: 'MSC authentication successful', latencyMs: Date.now() - start }
218
+ } catch (error) {
219
+ const message = error instanceof Error ? error.message : 'Unknown error'
220
+ return { success: false, message: `MSC connection failed: ${message}`, latencyMs: Date.now() - start }
221
+ }
222
+ }
223
+ }
@@ -0,0 +1,106 @@
1
+ import type { CarrierAdapter, CarrierFetchResult, CarrierAdapterTestResult } from '../carrier-adapter'
2
+ import { extractDocumentReferences } from '../carrier-adapter'
3
+ import type { TrackingReferenceType } from '../../data/entities'
4
+ import { fetchOAuthToken } from '../auth/oauth-client'
5
+ import { buildDcsaQueryParams } from '../dcsa-params'
6
+ import { parseDcsaEvents } from '../dcsa-event-parser'
7
+ import { withCarrierApiSpan } from '../logger'
8
+
9
+ const TOKEN_URL = 'https://apigw.zim.com/authorize/v1'
10
+ const EVENTS_URL = 'https://apigw.zim.com/trackAndTrace/v1'
11
+
12
+ type ZimAuthConfig = {
13
+ client_id: string
14
+ client_secret: string
15
+ subscription_key: string
16
+ }
17
+
18
+ function getAuth(authConfig: Record<string, unknown> | null | undefined): ZimAuthConfig {
19
+ const clientId = authConfig?.client_id as string | undefined
20
+ const clientSecret = authConfig?.client_secret as string | undefined
21
+ const subscriptionKey = authConfig?.subscription_key as string | undefined
22
+ if (!clientId || !clientSecret || !subscriptionKey) {
23
+ throw new Error('ZIM authConfig requires client_id, client_secret, and subscription_key')
24
+ }
25
+ return { client_id: clientId, client_secret: clientSecret, subscription_key: subscriptionKey }
26
+ }
27
+
28
+ async function authenticate(auth: ZimAuthConfig): Promise<string> {
29
+ return withCarrierApiSpan(
30
+ { carrierCode: 'zim', operation: 'authenticate' },
31
+ async (span) => {
32
+ const token = await fetchOAuthToken({
33
+ tokenUrl: TOKEN_URL,
34
+ clientId: auth.client_id,
35
+ clientSecret: auth.client_secret,
36
+ authMethod: 'body',
37
+ extraBody: { scope: 'tracing' },
38
+ })
39
+ return token
40
+ },
41
+ )
42
+ }
43
+
44
+ export class ZimAdapter implements CarrierAdapter {
45
+ readonly carrierCode = 'zim'
46
+ readonly supportedReferenceTypes: TrackingReferenceType[] = ['container', 'booking', 'bol']
47
+
48
+ async fetchEvents(input: {
49
+ referenceType: TrackingReferenceType
50
+ referenceValue: string
51
+ apiEndpoint?: string | null
52
+ authConfig?: Record<string, unknown> | null
53
+ }): Promise<CarrierFetchResult> {
54
+ return withCarrierApiSpan(
55
+ {
56
+ carrierCode: this.carrierCode,
57
+ operation: 'fetchEvents',
58
+ referenceType: input.referenceType,
59
+ referenceValue: input.referenceValue,
60
+ },
61
+ async (span) => {
62
+ const auth = getAuth(input.authConfig)
63
+ const token = await authenticate(auth)
64
+ const params = buildDcsaQueryParams(input.referenceValue, input.referenceType)
65
+ const url = `${input.apiEndpoint || EVENTS_URL}?${params}`
66
+
67
+ const response = await fetch(url, {
68
+ headers: {
69
+ 'Authorization': `Bearer ${token}`,
70
+ 'Ocp-Apim-Subscription-Key': auth.subscription_key,
71
+ 'Content-Type': 'application/json',
72
+ },
73
+ })
74
+
75
+ span.setAttribute('http.status_code', response.status)
76
+
77
+ if (!response.ok) {
78
+ const errorText = await response.text().catch(() => 'unknown')
79
+ throw new Error(`ZIM API error (${response.status}): ${errorText}`)
80
+ }
81
+
82
+ const data = await response.json()
83
+ const events = parseDcsaEvents(data, 'ZIM')
84
+ const { bookingNumber, bolNumber } = extractDocumentReferences(events)
85
+
86
+ span.setAttribute('events.count', events.length)
87
+ return { events, bookingNumber, bolNumber }
88
+ },
89
+ )
90
+ }
91
+
92
+ async testConnection(input: {
93
+ apiEndpoint?: string | null
94
+ authConfig?: Record<string, unknown> | null
95
+ }): Promise<CarrierAdapterTestResult> {
96
+ const start = Date.now()
97
+ try {
98
+ const auth = getAuth(input.authConfig)
99
+ await authenticate(auth)
100
+ return { success: true, message: 'ZIM authentication successful', latencyMs: Date.now() - start }
101
+ } catch (error) {
102
+ const message = error instanceof Error ? error.message : 'Unknown error'
103
+ return { success: false, message: `ZIM connection failed: ${message}`, latencyMs: Date.now() - start }
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,29 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql'
2
+ import { ActionLog } from '@open-mercato/core/modules/audit_logs/data/entities'
3
+
4
+ /**
5
+ * Get the user ID of who created a tracking job by querying audit logs.
6
+ *
7
+ * This is used for notifications where we need to notify the user who created
8
+ * the tracking job, but the TrackingJob entity doesn't store createdByUserId.
9
+ */
10
+ export async function getTrackingJobCreator(
11
+ em: EntityManager,
12
+ trackingJobId: string,
13
+ tenantId: string,
14
+ ): Promise<string | null> {
15
+ const createLog = await em.findOne(
16
+ ActionLog,
17
+ {
18
+ tenantId,
19
+ resourceKind: 'shipment_tracking.tracking_job',
20
+ resourceId: trackingJobId,
21
+ commandId: 'shipment_tracking.tracking_job.create',
22
+ executionState: 'done',
23
+ deletedAt: null,
24
+ },
25
+ { orderBy: { createdAt: 'asc' } },
26
+ )
27
+
28
+ return createLog?.actorUserId ?? null
29
+ }
@@ -0,0 +1,4 @@
1
+ export function base64UrlEncode(data: string | Buffer): string {
2
+ const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data)
3
+ return buffer.toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
4
+ }
@@ -0,0 +1,53 @@
1
+ type OAuthConfig = {
2
+ tokenUrl: string
3
+ clientId: string
4
+ clientSecret: string
5
+ scope?: string
6
+ extraHeaders?: Record<string, string>
7
+ extraBody?: Record<string, string>
8
+ authMethod?: 'body' | 'basic'
9
+ }
10
+
11
+ export async function fetchOAuthToken(config: OAuthConfig): Promise<string> {
12
+ const { tokenUrl, clientId, clientSecret, scope, extraHeaders, extraBody, authMethod = 'body' } = config
13
+
14
+ const body = new URLSearchParams({ grant_type: 'client_credentials' })
15
+
16
+ if (authMethod === 'body') {
17
+ body.set('client_id', clientId)
18
+ body.set('client_secret', clientSecret)
19
+ }
20
+
21
+ if (scope) {
22
+ body.set('scope', scope)
23
+ }
24
+
25
+ if (extraBody) {
26
+ for (const [key, value] of Object.entries(extraBody)) {
27
+ body.set(key, value)
28
+ }
29
+ }
30
+
31
+ const headers: Record<string, string> = {
32
+ 'Content-Type': 'application/x-www-form-urlencoded',
33
+ ...extraHeaders,
34
+ }
35
+
36
+ if (authMethod === 'basic') {
37
+ headers['Authorization'] = `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`
38
+ }
39
+
40
+ const response = await fetch(tokenUrl, {
41
+ method: 'POST',
42
+ headers,
43
+ body: body.toString(),
44
+ })
45
+
46
+ if (!response.ok) {
47
+ const errorText = await response.text().catch(() => 'unknown')
48
+ throw new Error(`OAuth token request failed (${response.status}): ${errorText}`)
49
+ }
50
+
51
+ const data = await response.json() as { access_token: string }
52
+ return data.access_token
53
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Runs a function in the background without blocking the caller.
3
+ * Errors are logged but not propagated.
4
+ *
5
+ * Uses setImmediate to defer execution to the next event loop iteration,
6
+ * allowing the caller to return immediately (non-blocking).
7
+ *
8
+ * @param fn - Async function to run in background
9
+ * @param label - Optional label for error logging
10
+ */
11
+ export function runInBackground(fn: () => Promise<void>, label?: string): void {
12
+ setImmediate(() => {
13
+ fn().catch((err) => {
14
+ console.error(`[background${label ? `:${label}` : ''}] Error:`, err)
15
+ })
16
+ })
17
+ }
18
+
19
+ /**
20
+ * Sleep helper for retry delays
21
+ */
22
+ export function sleep(ms: number): Promise<void> {
23
+ return new Promise((resolve) => setTimeout(resolve, ms))
24
+ }
@@ -0,0 +1,199 @@
1
+ /**
2
+ * BIC Facility Code API v2 Client
3
+ *
4
+ * Provides facility enrichment data (coordinates, addresses, operator names)
5
+ * from the BIC Facility Code Database.
6
+ *
7
+ * API Documentation: https://app.swaggerhub.com/apis/BIC-ORG/Facility-Codes/2.0.1
8
+ */
9
+
10
+ // ─── Types ───────────────────────────────────────────────────
11
+
12
+ export interface BicTokenResponse {
13
+ accessToken: string
14
+ access_token: string // Also provided for compatibility
15
+ accessTokenExpiresAt: string // ISO datetime
16
+ }
17
+
18
+ export interface BicAddress {
19
+ street?: string
20
+ city?: string
21
+ postcode?: string
22
+ state?: string
23
+ country?: string
24
+ }
25
+
26
+ export interface BicCoordinates {
27
+ latitude: string // Note: strings in BIC API, need to parse
28
+ longitude: string
29
+ }
30
+
31
+ export interface BicFacilityDetails {
32
+ name: string
33
+ address?: BicAddress
34
+ formattedAddress?: string
35
+ geographicalCoordinate?: BicCoordinates
36
+ }
37
+
38
+ export interface BicOperator {
39
+ name: string
40
+ }
41
+
42
+ export interface BicFacility {
43
+ code: string
44
+ codeProvider: 'BIC' | 'SMDG'
45
+ countryCode: string
46
+ unLocode: string
47
+ aliasCode?: string // If this code is deprecated
48
+ codeListProviderCode?: string // Short code for SMDG
49
+ operator?: BicOperator
50
+ facility?: BicFacilityDetails
51
+ }
52
+
53
+ export interface BicClientConfig {
54
+ baseUrl: string
55
+ username: string
56
+ password: string
57
+ }
58
+
59
+ // ─── Client ──────────────────────────────────────────────────
60
+
61
+ export class BicApiClient {
62
+ private baseUrl: string
63
+ private username: string
64
+ private password: string
65
+ private accessToken: string | null = null
66
+ private tokenExpiresAt: Date | null = null
67
+
68
+ constructor(config: BicClientConfig) {
69
+ this.baseUrl = config.baseUrl.replace(/\/$/, '') // Remove trailing slash
70
+ this.username = config.username
71
+ this.password = config.password
72
+ }
73
+
74
+ /**
75
+ * Get OAuth2 token via Basic Auth
76
+ */
77
+ private async getToken(): Promise<string> {
78
+ const now = new Date()
79
+ // Refresh if token expires in less than 60 seconds
80
+ if (this.accessToken && this.tokenExpiresAt && this.tokenExpiresAt > new Date(now.getTime() + 60_000)) {
81
+ return this.accessToken
82
+ }
83
+
84
+ const credentials = Buffer.from(`${this.username}:${this.password}`).toString('base64')
85
+
86
+ const response = await fetch(`${this.baseUrl}/v2/oauth/token`, {
87
+ method: 'POST',
88
+ headers: {
89
+ 'Authorization': `Basic ${credentials}`,
90
+ 'Content-Type': 'application/json',
91
+ },
92
+ })
93
+
94
+ if (!response.ok) {
95
+ const text = await response.text()
96
+ throw new Error(`BIC OAuth failed: ${response.status} - ${text}`)
97
+ }
98
+
99
+ const data: BicTokenResponse = await response.json()
100
+ this.accessToken = data.accessToken || data.access_token
101
+ this.tokenExpiresAt = new Date(data.accessTokenExpiresAt)
102
+ return this.accessToken
103
+ }
104
+
105
+ /**
106
+ * Look up facility by code
107
+ *
108
+ * @param facilityCode - The facility code (BIC: 9 chars, SMDG: varies)
109
+ * @param codeProvider - 'BIC' or 'SMDG'
110
+ * @param unlocode - Required for SMDG codes to build the full lookup code
111
+ * @returns Facility data or null if not found
112
+ */
113
+ async getFacility(
114
+ facilityCode: string,
115
+ codeProvider: 'BIC' | 'SMDG',
116
+ unlocode?: string
117
+ ): Promise<BicFacility | null> {
118
+ const token = await this.getToken()
119
+
120
+ // Build lookup code:
121
+ // - BIC codes are already complete (9 chars)
122
+ // - SMDG codes need unlocode prefix (e.g., "PLGDY" + "DCT" = "PLGDYDCT")
123
+ const lookupCode = codeProvider === 'SMDG' && unlocode
124
+ ? `${unlocode}${facilityCode}`
125
+ : facilityCode
126
+
127
+ const url = `${this.baseUrl}/v2/facilities/${lookupCode}?codeProvider=${codeProvider}`
128
+
129
+ const response = await fetch(url, {
130
+ headers: { 'Authorization': `Bearer ${token}` },
131
+ })
132
+
133
+ if (response.status === 404) {
134
+ return null
135
+ }
136
+
137
+ if (!response.ok) {
138
+ const text = await response.text()
139
+ throw new Error(`BIC API error: ${response.status} - ${text}`)
140
+ }
141
+
142
+ return response.json()
143
+ }
144
+
145
+ /**
146
+ * Test connection by fetching a token
147
+ * @returns true if authentication succeeds
148
+ */
149
+ async testConnection(): Promise<boolean> {
150
+ await this.getToken()
151
+ return true
152
+ }
153
+
154
+ // ─── Static Helpers ──────────────────────────────────────────
155
+
156
+ /**
157
+ * Parse coordinates from BIC response (strings to numbers)
158
+ */
159
+ static parseCoordinates(facility: BicFacility): { latitude: number; longitude: number } | null {
160
+ const coords = facility.facility?.geographicalCoordinate
161
+ if (!coords?.latitude || !coords?.longitude) return null
162
+
163
+ const lat = parseFloat(coords.latitude)
164
+ const lng = parseFloat(coords.longitude)
165
+
166
+ if (isNaN(lat) || isNaN(lng)) return null
167
+ return { latitude: lat, longitude: lng }
168
+ }
169
+
170
+ /**
171
+ * Format address from BIC response
172
+ */
173
+ static formatAddress(facility: BicFacility): string | null {
174
+ // Prefer formatted address if available
175
+ if (facility.facility?.formattedAddress) {
176
+ return facility.facility.formattedAddress
177
+ }
178
+
179
+ const addr = facility.facility?.address
180
+ if (!addr) return null
181
+
182
+ const parts = [addr.street, addr.city, addr.state, addr.postcode, addr.country]
183
+ return parts.filter(Boolean).join(', ') || null
184
+ }
185
+
186
+ /**
187
+ * Get facility name from BIC response
188
+ */
189
+ static getFacilityName(facility: BicFacility): string | null {
190
+ return facility.facility?.name || null
191
+ }
192
+
193
+ /**
194
+ * Get operator name from BIC response
195
+ */
196
+ static getOperatorName(facility: BicFacility): string | null {
197
+ return facility.operator?.name || null
198
+ }
199
+ }