@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,526 @@
1
+ /**
2
+ * POI NATS Subscriber Service
3
+ *
4
+ * Subscribes to POI proximity events from the AIS system via NATS JetStream
5
+ * and processes them to create tracking events and notifications.
6
+ */
7
+
8
+ import type { NatsConnection, JetStreamClient, JetStreamManager, Consumer, ConsumerMessages } from 'nats'
9
+ import { connect, JSONCodec, AckPolicy, DeliverPolicy, ReplayPolicy } from 'nats'
10
+ import type { EntityManager } from '@mikro-orm/postgresql'
11
+ import type { EventBus } from '@open-mercato/events'
12
+ import { loadPoiNatsConfig, validatePoiNatsConfig, isPoiNatsConfigured, type PoiNatsConfig } from '../lib/poi-nats-config'
13
+ import type { PoiProximityEvent } from '../lib/poi-types'
14
+ import { getJobPoiEventId } from '../lib/poi-types'
15
+ import { mapToOpenMercatoEventId } from '../lib/poi-event-processor'
16
+ import {
17
+ processPoiEvent,
18
+ isEventAlreadyProcessed,
19
+ createTrackingEventFromPoi,
20
+ } from '../lib/poi-event-processor'
21
+ import { Shipment } from '../data/entities'
22
+ import { trackingLogger } from '../lib/logger'
23
+ import type { TrackingService } from './trackingService'
24
+
25
+ const LOG_COMPONENT = 'poi-nats'
26
+
27
+ // ─── Types ───────────────────────────────────────────────────
28
+
29
+ type PoiNatsServiceDeps = {
30
+ em: () => EntityManager
31
+ eventBus: EventBus
32
+ trackingService: TrackingService
33
+ }
34
+
35
+ type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'draining' | 'closed'
36
+
37
+ export type PoiNatsServiceStats = {
38
+ status: ConnectionStatus
39
+ messagesReceived: number
40
+ messagesProcessed: number
41
+ eventsCreated: number
42
+ errors: number
43
+ lastMessageAt: Date | null
44
+ connectedAt: Date | null
45
+ }
46
+
47
+ // ─── Service ─────────────────────────────────────────────────
48
+
49
+ export class PoiNatsService {
50
+ private deps: PoiNatsServiceDeps
51
+ private config: PoiNatsConfig
52
+ private connection: NatsConnection | null = null
53
+ private jetstream: JetStreamClient | null = null
54
+ private consumer: Consumer | null = null
55
+ private consumerMessages: ConsumerMessages | null = null
56
+ private status: ConnectionStatus = 'disconnected'
57
+ private stats: PoiNatsServiceStats = {
58
+ status: 'disconnected',
59
+ messagesReceived: 0,
60
+ messagesProcessed: 0,
61
+ eventsCreated: 0,
62
+ errors: 0,
63
+ lastMessageAt: null,
64
+ connectedAt: null,
65
+ }
66
+
67
+ /**
68
+ * Track per-job events already emitted in this batch to avoid duplicates.
69
+ * Key format: `${trackingJobId}:${eventType}:${sourceEventId}`
70
+ */
71
+ private emittedJobEvents: Set<string> = new Set()
72
+
73
+ constructor(deps: PoiNatsServiceDeps) {
74
+ this.deps = deps
75
+ this.config = loadPoiNatsConfig()
76
+ }
77
+
78
+ /**
79
+ * Get current service statistics.
80
+ */
81
+ getStats(): PoiNatsServiceStats {
82
+ return { ...this.stats, status: this.status }
83
+ }
84
+
85
+ /**
86
+ * Check if the service is connected.
87
+ */
88
+ isConnected(): boolean {
89
+ return this.status === 'connected'
90
+ }
91
+
92
+ /**
93
+ * Check if POI NATS integration is configured.
94
+ */
95
+ isConfigured(): boolean {
96
+ return isPoiNatsConfigured()
97
+ }
98
+
99
+ /**
100
+ * Start the NATS subscriber.
101
+ */
102
+ async start(): Promise<void> {
103
+ if (!isPoiNatsConfigured()) {
104
+ trackingLogger.info('POI_NATS_URL not configured, skipping POI event subscription', {
105
+ component: LOG_COMPONENT,
106
+ })
107
+ return
108
+ }
109
+
110
+ if (this.status === 'connected' || this.status === 'connecting') {
111
+ trackingLogger.warn('Service is already started or connecting', {
112
+ component: LOG_COMPONENT,
113
+ status: this.status,
114
+ })
115
+ return
116
+ }
117
+
118
+ try {
119
+ validatePoiNatsConfig(this.config)
120
+ this.status = 'connecting'
121
+
122
+ trackingLogger.info('Connecting to NATS server', {
123
+ component: LOG_COMPONENT,
124
+ serverUrl: this.config.serverUrl,
125
+ })
126
+
127
+ this.connection = await connect({
128
+ servers: this.config.serverUrl,
129
+ name: this.config.connectionName,
130
+ reconnect: true,
131
+ maxReconnectAttempts: this.config.reconnect.maxAttempts,
132
+ reconnectTimeWait: this.config.reconnect.initialDelayMs,
133
+ reconnectJitter: this.config.reconnect.maxDelayMs - this.config.reconnect.initialDelayMs,
134
+ })
135
+
136
+ this.status = 'connected'
137
+ this.stats.connectedAt = new Date()
138
+
139
+ trackingLogger.info('Connected to NATS server', { component: LOG_COMPONENT })
140
+
141
+ // Set up connection event handlers
142
+ this.setupConnectionHandlers()
143
+
144
+ // Subscribe to POI events
145
+ await this.subscribe()
146
+
147
+ trackingLogger.info('Subscribed to POI subject', {
148
+ component: LOG_COMPONENT,
149
+ subject: this.config.subject,
150
+ })
151
+ } catch (error) {
152
+ this.status = 'disconnected'
153
+ trackingLogger.error('Failed to connect to NATS', {
154
+ component: LOG_COMPONENT,
155
+ error: error instanceof Error ? error.message : String(error),
156
+ stack: error instanceof Error ? error.stack : undefined,
157
+ })
158
+ throw error
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Stop the NATS subscriber gracefully.
164
+ */
165
+ async stop(): Promise<void> {
166
+ if (!this.connection) {
167
+ return
168
+ }
169
+
170
+ this.status = 'draining'
171
+ trackingLogger.info('Draining NATS connection', { component: LOG_COMPONENT })
172
+
173
+ try {
174
+ // Stop consuming messages first
175
+ if (this.consumerMessages) {
176
+ this.consumerMessages.stop()
177
+ this.consumerMessages = null
178
+ }
179
+
180
+ this.consumer = null
181
+ this.jetstream = null
182
+
183
+ // Drain and close connection
184
+ await this.connection.drain()
185
+ this.connection = null
186
+ this.status = 'closed'
187
+
188
+ trackingLogger.info('NATS connection closed', { component: LOG_COMPONENT })
189
+ } catch (error) {
190
+ trackingLogger.error('Error during NATS shutdown', {
191
+ component: LOG_COMPONENT,
192
+ error: error instanceof Error ? error.message : String(error),
193
+ stack: error instanceof Error ? error.stack : undefined,
194
+ })
195
+ this.status = 'disconnected'
196
+ throw error
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Subscribe to POI proximity events via JetStream.
202
+ *
203
+ * Auto-creates the durable consumer if it doesn't exist.
204
+ * Each instance gets a unique consumer name (based on JWT_SECRET hash)
205
+ * so multiple self-hosted installations can each receive all messages.
206
+ */
207
+ private async subscribe(): Promise<void> {
208
+ if (!this.connection) {
209
+ throw new Error('Not connected to NATS')
210
+ }
211
+
212
+ // Get JetStream manager for consumer management
213
+ const jsm = await this.connection.jetstreamManager()
214
+
215
+ // Ensure consumer exists (create if not)
216
+ await this.ensureConsumer(jsm)
217
+
218
+ // Get JetStream client for consuming
219
+ this.jetstream = this.connection.jetstream()
220
+
221
+ trackingLogger.debug('Binding to JetStream consumer', {
222
+ component: LOG_COMPONENT,
223
+ consumerName: this.config.consumerName,
224
+ streamName: this.config.streamName,
225
+ })
226
+
227
+ // Bind to the durable consumer
228
+ this.consumer = await this.jetstream.consumers.get(
229
+ this.config.streamName,
230
+ this.config.consumerName
231
+ )
232
+
233
+ trackingLogger.debug('Consumer bound, starting to consume messages', {
234
+ component: LOG_COMPONENT,
235
+ consumerName: this.config.consumerName,
236
+ })
237
+
238
+ // Start consuming messages
239
+ this.consumerMessages = await this.consumer.consume()
240
+
241
+ // Process messages asynchronously
242
+ this.processMessages()
243
+ }
244
+
245
+ /**
246
+ * Ensure the durable consumer exists on the stream.
247
+ * Creates it if it doesn't exist with the appropriate configuration.
248
+ */
249
+ private async ensureConsumer(jsm: JetStreamManager): Promise<void> {
250
+ const consumerConfig = {
251
+ durable_name: this.config.consumerName,
252
+ ack_policy: AckPolicy.Explicit,
253
+ deliver_policy: DeliverPolicy.All, // Replay all messages from stream start
254
+ replay_policy: ReplayPolicy.Instant, // Don't throttle replay
255
+ filter_subject: this.config.subject,
256
+ max_deliver: 5, // Prevent infinite redelivery of poison messages
257
+ }
258
+
259
+ try {
260
+ // Check if consumer exists
261
+ await jsm.consumers.info(this.config.streamName, this.config.consumerName)
262
+ trackingLogger.debug('Consumer exists', {
263
+ component: LOG_COMPONENT,
264
+ consumerName: this.config.consumerName,
265
+ })
266
+ } catch (error: unknown) {
267
+ // Consumer doesn't exist, create it
268
+ const errorCode = (error as { code?: string })?.code
269
+ if (errorCode === '404' || (error as { api_error?: { err_code?: number } })?.api_error?.err_code === 10014) {
270
+ trackingLogger.info('Creating JetStream consumer', {
271
+ component: LOG_COMPONENT,
272
+ consumerName: this.config.consumerName,
273
+ streamName: this.config.streamName,
274
+ })
275
+ await jsm.consumers.add(this.config.streamName, consumerConfig)
276
+ trackingLogger.info('JetStream consumer created', {
277
+ component: LOG_COMPONENT,
278
+ consumerName: this.config.consumerName,
279
+ })
280
+ } else {
281
+ // Some other error, rethrow
282
+ throw error
283
+ }
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Process incoming messages from the JetStream consumer.
289
+ */
290
+ private async processMessages(): Promise<void> {
291
+ if (!this.consumerMessages) {
292
+ return
293
+ }
294
+
295
+ const jsonCodec = JSONCodec<PoiProximityEvent>()
296
+
297
+ for await (const msg of this.consumerMessages) {
298
+ this.stats.messagesReceived++
299
+ this.stats.lastMessageAt = new Date()
300
+
301
+ try {
302
+ const event = jsonCodec.decode(msg.data)
303
+
304
+ // Validate required fields - skip malformed/test messages
305
+ if (!event || !event.type || !event.mmsi) {
306
+ trackingLogger.debug('Skipping invalid message (missing type or mmsi)', {
307
+ component: LOG_COMPONENT,
308
+ })
309
+ msg.ack() // Ack to prevent redelivery of bad messages
310
+ continue
311
+ }
312
+
313
+ await this.handlePoiEvent(event)
314
+
315
+ // Acknowledge successful processing
316
+ msg.ack()
317
+ this.stats.messagesProcessed++
318
+ } catch (error) {
319
+ this.stats.errors++
320
+ trackingLogger.error('Error processing NATS message', {
321
+ component: LOG_COMPONENT,
322
+ error: error instanceof Error ? error.message : String(error),
323
+ stack: error instanceof Error ? error.stack : undefined,
324
+ })
325
+
326
+ // Negative acknowledge - message will be redelivered
327
+ msg.nak()
328
+ }
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Handle a single POI proximity event.
334
+ */
335
+ private async handlePoiEvent(event: PoiProximityEvent): Promise<void> {
336
+ // Clear job event deduplication set at start of each message
337
+ // This ensures a clean slate and prevents silent event drops on retry
338
+ this.emittedJobEvents.clear()
339
+
340
+ trackingLogger.debug('Received POI event', {
341
+ component: LOG_COMPONENT,
342
+ eventType: event.type,
343
+ vesselName: event.shipName,
344
+ mmsi: event.mmsi,
345
+ })
346
+
347
+ // Fork a fresh, cleared EM per message: this worker resolves the container once
348
+ // and loops forever, so reusing the container EM would leak its identity map.
349
+ const em = this.deps.em().fork({ clear: true })
350
+
351
+ try {
352
+ // Process the event and find matching shipments
353
+ const processed = await processPoiEvent(em, event)
354
+
355
+ if (!processed) {
356
+ // No matching shipments found
357
+ return
358
+ }
359
+
360
+ trackingLogger.info('Matched shipments for POI event', {
361
+ component: LOG_COMPONENT,
362
+ mmsi: event.mmsi,
363
+ eventType: event.type,
364
+ matchedShipmentCount: processed.shipmentIds.length,
365
+ })
366
+
367
+ // Track which tracking jobs got a new event, so we can re-derive their shipments'
368
+ // denormalized state (Journey Timeline / status / ETA) afterwards. POI events are
369
+ // TRANSPORT (vessel) events that apply to every container on the job, and dedup means
370
+ // only the first container actually creates the TrackingEvent — so we refresh the
371
+ // WHOLE job, not just the container where the row was created.
372
+ const affectedJobIds = new Set<string>()
373
+
374
+ // Process each matched shipment
375
+ for (const shipmentId of processed.shipmentIds) {
376
+ const shipment = await em.findOne(
377
+ Shipment,
378
+ { id: shipmentId },
379
+ { populate: ['trackingJob'] }
380
+ )
381
+
382
+ if (!shipment?.trackingJob) {
383
+ continue
384
+ }
385
+
386
+ // Check for duplicates
387
+ const alreadyProcessed = await isEventAlreadyProcessed(
388
+ em,
389
+ shipment.trackingJob.id,
390
+ processed.sourceEventId
391
+ )
392
+
393
+ if (alreadyProcessed) {
394
+ trackingLogger.debug('Event already processed', {
395
+ component: LOG_COMPONENT,
396
+ sourceEventId: processed.sourceEventId,
397
+ trackingJobId: shipment.trackingJob.id,
398
+ })
399
+ continue
400
+ }
401
+
402
+ // Create TrackingEvent record
403
+ const trackingEvent = createTrackingEventFromPoi(processed, shipment.trackingJob)
404
+ em.persist(trackingEvent)
405
+ this.stats.eventsCreated++
406
+
407
+ affectedJobIds.add(shipment.trackingJob.id)
408
+
409
+ // Emit per-shipment event (for webhooks/external integrations)
410
+ const shipmentEventId = mapToOpenMercatoEventId(event.type)
411
+ await this.deps.eventBus.emit(shipmentEventId, {
412
+ shipmentId: shipment.id,
413
+ trackingEventId: trackingEvent.id,
414
+ organizationId: shipment.organizationId,
415
+ tenantId: shipment.tenantId,
416
+ vesselName: event.shipName,
417
+ vesselMmsi: event.mmsi,
418
+ vesselImo: processed.vesselImo,
419
+ eventType: event.type,
420
+ poiCode: processed.poiCode,
421
+ latitude: event.lat,
422
+ longitude: event.lng,
423
+ eventDateTime: processed.eventDateTime.toISOString(),
424
+ distanceToPoiMeters: event.distanceToPoiMeters,
425
+ })
426
+
427
+ // Emit per-job event (for in-app notifications) - only once per tracking job
428
+ // This avoids duplicate notifications for multi-container bookings
429
+ const trackingJobId = shipment.trackingJob.id
430
+ const jobEventKey = `${trackingJobId}:${event.type}:${processed.sourceEventId}`
431
+ if (!this.emittedJobEvents.has(jobEventKey)) {
432
+ this.emittedJobEvents.add(jobEventKey)
433
+
434
+ const jobEventId = getJobPoiEventId(event.type)
435
+ await this.deps.eventBus.emit(jobEventId, {
436
+ trackingJobId,
437
+ shipmentId: shipment.id,
438
+ trackingEventId: trackingEvent.id,
439
+ organizationId: shipment.organizationId,
440
+ tenantId: shipment.tenantId,
441
+ vesselName: event.shipName,
442
+ vesselMmsi: event.mmsi,
443
+ vesselImo: processed.vesselImo,
444
+ eventType: event.type,
445
+ poiCode: processed.poiCode,
446
+ latitude: event.lat,
447
+ longitude: event.lng,
448
+ eventDateTime: processed.eventDateTime.toISOString(),
449
+ distanceToPoiMeters: event.distanceToPoiMeters,
450
+ // Include shipment reference info for notification body
451
+ containerNumber: shipment.containerNumber,
452
+ bookingNumber: shipment.bookingNumber,
453
+ bolNumber: shipment.bolNumber,
454
+ })
455
+
456
+ trackingLogger.debug('Emitted per-job POI event', {
457
+ component: LOG_COMPONENT,
458
+ trackingJobId,
459
+ eventType: event.type,
460
+ })
461
+ }
462
+
463
+ trackingLogger.info('Created tracking event from POI', {
464
+ component: LOG_COMPONENT,
465
+ shipmentId,
466
+ eventType: event.type,
467
+ trackingEventId: trackingEvent.id,
468
+ })
469
+ }
470
+
471
+ await em.flush()
472
+
473
+ // Re-derive denormalized state so AIS arrivals appear in the Journey Timeline and
474
+ // update status/ETA in real time, instead of waiting for the next carrier poll.
475
+ for (const trackingJobId of affectedJobIds) {
476
+ await this.deps.trackingService.refreshShipmentsFromEvents(em, trackingJobId)
477
+ }
478
+ } catch (error) {
479
+ trackingLogger.error('Error handling POI event', {
480
+ component: LOG_COMPONENT,
481
+ eventType: event.type,
482
+ mmsi: event.mmsi,
483
+ error: error instanceof Error ? error.message : String(error),
484
+ stack: error instanceof Error ? error.stack : undefined,
485
+ })
486
+ throw error
487
+ }
488
+ }
489
+
490
+ /**
491
+ * Set up connection event handlers.
492
+ */
493
+ private setupConnectionHandlers(): void {
494
+ if (!this.connection) {
495
+ return
496
+ }
497
+
498
+ // Handle connection status changes
499
+ ;(async () => {
500
+ if (!this.connection) return
501
+
502
+ for await (const status of this.connection.status()) {
503
+ switch (status.type) {
504
+ case 'disconnect':
505
+ trackingLogger.warn('Disconnected from NATS server', { component: LOG_COMPONENT })
506
+ this.status = 'disconnected'
507
+ break
508
+ case 'reconnect':
509
+ trackingLogger.info('Reconnected to NATS server', { component: LOG_COMPONENT })
510
+ this.status = 'connected'
511
+ break
512
+ case 'reconnecting':
513
+ trackingLogger.info('Reconnecting to NATS server', { component: LOG_COMPONENT })
514
+ this.status = 'connecting'
515
+ break
516
+ case 'error':
517
+ trackingLogger.error('NATS connection error', {
518
+ component: LOG_COMPONENT,
519
+ data: status.data,
520
+ })
521
+ break
522
+ }
523
+ }
524
+ })()
525
+ }
526
+ }