@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,142 @@
1
+ import { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'
2
+ import { z } from 'zod'
3
+ import { CarrierConfig } from '../../data/entities'
4
+ import { carrierConfigListSchema, carrierConfigCreateSchema, carrierConfigUpdateSchema } from '../../data/validators'
5
+ import { parseBooleanToken } from '@open-mercato/shared/lib/boolean'
6
+ import {
7
+ createShipmentTrackingCrudOpenApi,
8
+ createPagedListResponseSchema,
9
+ defaultOkResponseSchema,
10
+ } from '../openapi'
11
+ import { withScopedPayload } from '../utils'
12
+ import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
13
+
14
+ const rawBodySchema = z.object({}).passthrough()
15
+
16
+ type CarrierConfigListQuery = z.infer<typeof carrierConfigListSchema>
17
+
18
+ const routeMetadata = {
19
+ GET: { requireAuth: true, requireFeatures: ['shipment_tracking.carrier_configs.view'] },
20
+ POST: { requireAuth: true, requireFeatures: ['shipment_tracking.carrier_configs.manage'] },
21
+ PUT: { requireAuth: true, requireFeatures: ['shipment_tracking.carrier_configs.manage'] },
22
+ DELETE: { requireAuth: true, requireFeatures: ['shipment_tracking.carrier_configs.manage'] },
23
+ }
24
+
25
+ const listFields = [
26
+ 'id',
27
+ 'carrierCode',
28
+ 'apiEndpoint',
29
+ 'authConfig',
30
+ 'rateLimitRequests',
31
+ 'rateLimitWindowSeconds',
32
+ 'isActive',
33
+ 'createdAt',
34
+ 'updatedAt',
35
+ ]
36
+
37
+ const buildFilters = (query: CarrierConfigListQuery): Record<string, unknown> => {
38
+ const filters: Record<string, unknown> = { deletedAt: null }
39
+
40
+ if (query.carrierCode) {
41
+ filters.carrierCode = query.carrierCode
42
+ }
43
+
44
+ if (query.isActive !== undefined) {
45
+ const parsed = parseBooleanToken(query.isActive)
46
+ if (parsed !== null) {
47
+ filters.isActive = parsed
48
+ }
49
+ }
50
+
51
+ return filters
52
+ }
53
+
54
+ const crud = makeCrudRoute({
55
+ metadata: routeMetadata,
56
+ orm: {
57
+ entity: CarrierConfig,
58
+ idField: 'id',
59
+ orgField: 'organizationId',
60
+ tenantField: 'tenantId',
61
+ softDeleteField: 'deletedAt',
62
+ },
63
+ list: {
64
+ schema: carrierConfigListSchema,
65
+ fields: listFields,
66
+ sortFieldMap: {
67
+ id: 'id',
68
+ carrierCode: 'carrier_code',
69
+ isActive: 'is_active',
70
+ createdAt: 'created_at',
71
+ },
72
+ buildFilters: async (query) => buildFilters(query),
73
+ },
74
+ actions: {
75
+ create: {
76
+ commandId: 'shipment_tracking.carrier_config.create',
77
+ schema: rawBodySchema,
78
+ mapInput: async ({ raw, ctx }) => {
79
+ const { translate } = await resolveTranslations()
80
+ const scoped = withScopedPayload(raw ?? {}, ctx, translate)
81
+ return carrierConfigCreateSchema.parse(scoped)
82
+ },
83
+ response: ({ result }) => ({ id: result?.id ?? null }),
84
+ status: 201,
85
+ },
86
+ update: {
87
+ commandId: 'shipment_tracking.carrier_config.update',
88
+ schema: rawBodySchema,
89
+ mapInput: async ({ raw, ctx }) => {
90
+ const { translate } = await resolveTranslations()
91
+ const scoped = withScopedPayload(raw ?? {}, ctx, translate)
92
+ return carrierConfigUpdateSchema.parse(scoped)
93
+ },
94
+ response: ({ result }) => ({ id: result?.id ?? null }),
95
+ status: 200,
96
+ },
97
+ delete: {
98
+ commandId: 'shipment_tracking.carrier_config.delete',
99
+ schema: rawBodySchema,
100
+ mapInput: async ({ raw, ctx }) => {
101
+ const { translate } = await resolveTranslations()
102
+ const body = (raw as any)?.body ?? raw ?? {}
103
+ const scoped = withScopedPayload(body, ctx, translate)
104
+ return { id: body.id, ...scoped }
105
+ },
106
+ response: ({ result }) => ({ id: result?.id ?? null }),
107
+ status: 200,
108
+ },
109
+ },
110
+ })
111
+
112
+ export const openApi = createShipmentTrackingCrudOpenApi({
113
+ resourceName: 'CarrierConfig',
114
+ pluralName: 'CarrierConfigs',
115
+ querySchema: carrierConfigListSchema,
116
+ listResponseSchema: createPagedListResponseSchema(z.object({
117
+ id: z.string().uuid(),
118
+ carrierCode: z.string(),
119
+ apiEndpoint: z.string().nullable(),
120
+ isActive: z.boolean(),
121
+ })),
122
+ create: {
123
+ schema: rawBodySchema,
124
+ description: 'Creates a new carrier configuration.',
125
+ },
126
+ update: {
127
+ schema: rawBodySchema,
128
+ responseSchema: defaultOkResponseSchema,
129
+ description: 'Updates an existing carrier configuration.',
130
+ },
131
+ del: {
132
+ schema: z.object({ id: z.string().uuid() }),
133
+ responseSchema: defaultOkResponseSchema,
134
+ description: 'Deletes a carrier configuration.',
135
+ },
136
+ })
137
+
138
+ export const metadata = crud.metadata
139
+ export const GET = crud.GET
140
+ export const POST = crud.POST
141
+ export const PUT = crud.PUT
142
+ export const DELETE = crud.DELETE
@@ -0,0 +1,246 @@
1
+ import { NextRequest, NextResponse } from 'next/server'
2
+ import { z } from 'zod'
3
+ import type { EntityManager } from '@mikro-orm/postgresql'
4
+ import type { FilterQuery } from '@mikro-orm/core'
5
+ import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
6
+ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
7
+ import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
8
+ import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
9
+ import { Shipment } from '../../../data/entities'
10
+ import { shipsMapQuerySchema, shipsMapResponseSchema } from '../../../data/validators'
11
+ import type { ShipsMapMarker, ShipsMapShipment } from '../../../data/validators'
12
+ import { getCurrentVessel } from '../../../lib/current-vessel'
13
+ import type { RouteStopEntry } from '../../../lib/route-extraction'
14
+ import { getVesselCached, mapWithConcurrency } from '../../../lib/vessel-cache'
15
+
16
+ // ─── Metadata ────────────────────────────────────────────────
17
+
18
+ export const metadata = {
19
+ GET: { requireAuth: true, requireFeatures: ['shipment_tracking.dashboard.ships_map.view'] },
20
+ }
21
+
22
+ // ─── Helpers ─────────────────────────────────────────────────
23
+
24
+ /** The subset of Shipment fields this route projects from the DB. */
25
+ type ShipmentLite = Pick<
26
+ Shipment,
27
+ | 'id'
28
+ | 'status'
29
+ | 'containerNumber'
30
+ | 'routeStops'
31
+ | 'cargoEvents'
32
+ | 'vesselName'
33
+ | 'vesselImo'
34
+ | 'destinationLocation'
35
+ | 'etaTimestamps'
36
+ >
37
+
38
+ /**
39
+ * Resolve the port coordinates for an `at_port` shipment. `getCurrentVessel` reports the
40
+ * port as a location name (`currentPort`); we look up the matching route stop (the one the
41
+ * cargo has arrived at but not departed) for its coords, then fall back to the shipment's
42
+ * destination coords. Returns `null` when nothing is plottable.
43
+ */
44
+ function resolveAtPortPosition(
45
+ routeStops: RouteStopEntry[] | null | undefined,
46
+ currentPort: string | undefined,
47
+ shipment: ShipmentLite,
48
+ ): { lat: number; lng: number; portName: string | null; unlocode: string | null } | null {
49
+ // Prefer the stop the cargo is resting at (arrived, not yet departed) that matches currentPort.
50
+ const stop = (routeStops ?? []).find(
51
+ (s) => s.location === currentPort && s.ata && !s.atd && s.coords,
52
+ )
53
+ ?? (routeStops ?? []).find((s) => s.ata && !s.atd && s.coords)
54
+
55
+ if (stop?.coords) {
56
+ return {
57
+ lat: stop.coords.latitude,
58
+ lng: stop.coords.longitude,
59
+ portName: stop.location ?? currentPort ?? null,
60
+ unlocode: stop.unlocode ?? null,
61
+ }
62
+ }
63
+
64
+ // Fallback: destination coords.
65
+ const dest = shipment.destinationLocation
66
+ if (dest?.coords) {
67
+ return {
68
+ lat: dest.coords.latitude,
69
+ lng: dest.coords.longitude,
70
+ portName: dest.name ?? currentPort ?? null,
71
+ unlocode: dest.unlocode ?? null,
72
+ }
73
+ }
74
+
75
+ return null
76
+ }
77
+
78
+ function toShipmentSummary(shipment: ShipmentLite): ShipsMapShipment {
79
+ const eta = shipment.etaTimestamps?.length
80
+ ? shipment.etaTimestamps[shipment.etaTimestamps.length - 1]?.value ?? null
81
+ : null
82
+ return {
83
+ id: shipment.id,
84
+ containerNumber: shipment.containerNumber ?? null,
85
+ status: shipment.status,
86
+ eta,
87
+ destinationLocation: shipment.destinationLocation?.name ?? null,
88
+ }
89
+ }
90
+
91
+ // ─── GET — Ships map aggregation ─────────────────────────────
92
+
93
+ export async function GET(request: NextRequest) {
94
+ const auth = await getAuthFromRequest(request)
95
+ if (!auth?.orgId || !auth?.tenantId) {
96
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
97
+ }
98
+
99
+ const url = new URL(request.url)
100
+ const parsedQuery = shipsMapQuerySchema.safeParse({
101
+ scope: url.searchParams.get('scope') ?? undefined,
102
+ })
103
+ if (!parsedQuery.success) {
104
+ return NextResponse.json({ error: 'Invalid query parameters' }, { status: 400 })
105
+ }
106
+ const { scope: scopeFilter } = parsedQuery.data
107
+
108
+ const container = await createRequestContainer()
109
+ const scope = await resolveOrganizationScopeForRequest({ container, auth, request })
110
+ const em = container.resolve('em') as EntityManager
111
+
112
+ const organizationId = scope?.selectedId ?? auth.orgId
113
+ const tenantId = auth.tenantId
114
+
115
+ // Coarse prefilter only: exclude DELIVERED. getCurrentVessel is the authoritative
116
+ // classifier — the denormalized `status` column can lag route-stop reality, so we must
117
+ // NOT narrow to a status allow-list here or we'd drop genuinely in-transit shipments.
118
+ const where: FilterQuery<Shipment> = {
119
+ organizationId,
120
+ tenantId,
121
+ deletedAt: null,
122
+ status: { $ne: 'DELIVERED' },
123
+ }
124
+
125
+ const shipments = await em.find(Shipment, where, {
126
+ fields: [
127
+ 'id',
128
+ 'status',
129
+ 'containerNumber',
130
+ 'routeStops',
131
+ 'cargoEvents',
132
+ 'vesselName',
133
+ 'vesselImo',
134
+ 'destinationLocation',
135
+ 'etaTimestamps',
136
+ ],
137
+ })
138
+
139
+ // Group in_transit shipments by the IMO of the vessel actually carrying them.
140
+ const byImo = new Map<string, ShipmentLite[]>()
141
+ // Group at_port shipments by a port key (unlocode|name + rounded coords).
142
+ const portGroups = new Map<
143
+ string,
144
+ { lat: number; lng: number; portName: string | null; unlocode: string | null; shipments: ShipmentLite[] }
145
+ >()
146
+ let unresolvedCount = 0
147
+
148
+ for (const shipment of shipments) {
149
+ const current = getCurrentVessel(shipment.routeStops, shipment.cargoEvents, {
150
+ vesselName: shipment.vesselName,
151
+ vesselImo: shipment.vesselImo,
152
+ })
153
+
154
+ if (current.status === 'in_transit') {
155
+ if (scopeFilter === 'at_port') continue
156
+ const imo = current.vesselImo
157
+ if (!imo) {
158
+ unresolvedCount += 1
159
+ continue
160
+ }
161
+ const list = byImo.get(imo) ?? []
162
+ list.push(shipment)
163
+ byImo.set(imo, list)
164
+ } else if (current.status === 'at_port') {
165
+ if (scopeFilter === 'in_transit') continue
166
+ const pos = resolveAtPortPosition(shipment.routeStops, current.currentPort, shipment)
167
+ if (!pos) {
168
+ unresolvedCount += 1
169
+ continue
170
+ }
171
+ const key = pos.unlocode ?? `${pos.portName ?? ''}:${pos.lat.toFixed(3)},${pos.lng.toFixed(3)}`
172
+ const group = portGroups.get(key)
173
+ if (group) {
174
+ group.shipments.push(shipment)
175
+ } else {
176
+ portGroups.set(key, { ...pos, shipments: [shipment] })
177
+ }
178
+ }
179
+ // not_departed / delivered → not plotted (no meaningful "where is it now").
180
+ }
181
+
182
+ const markers: ShipsMapMarker[] = []
183
+
184
+ // Fan out distinct IMOs through the bounded cache, concurrency-capped, fault-tolerant.
185
+ const imos = Array.from(byImo.keys())
186
+ const vesselResults = await mapWithConcurrency(imos, (imo) => getVesselCached(imo))
187
+
188
+ imos.forEach((imo, i) => {
189
+ const result = vesselResults[i]
190
+ const group = byImo.get(imo) ?? []
191
+ const vessel = result.status === 'fulfilled' ? result.value : null
192
+ if (!vessel || !vessel.lastPosition) {
193
+ // vessel-api miss / failure / positionless → fold its shipments into unresolved.
194
+ unresolvedCount += group.length
195
+ return
196
+ }
197
+ markers.push({
198
+ kind: 'vessel',
199
+ imo,
200
+ name: vessel.name ?? null,
201
+ position: { lat: vessel.lastPosition.lat, lng: vessel.lastPosition.lng },
202
+ heading: vessel.lastHeading ?? null,
203
+ destination: vessel.lastDestinationPort?.name ?? vessel.lastDestination ?? null,
204
+ updatedAt: vessel.updatedAt ?? null,
205
+ shipments: group.map(toShipmentSummary),
206
+ })
207
+ })
208
+
209
+ for (const group of portGroups.values()) {
210
+ markers.push({
211
+ kind: 'port',
212
+ portName: group.portName,
213
+ unlocode: group.unlocode,
214
+ position: { lat: group.lat, lng: group.lng },
215
+ shipments: group.shipments.map(toShipmentSummary),
216
+ })
217
+ }
218
+
219
+ return NextResponse.json({
220
+ markers,
221
+ unresolvedCount,
222
+ generatedAt: new Date().toISOString(),
223
+ })
224
+ }
225
+
226
+ // ─── OpenAPI ─────────────────────────────────────────────────
227
+
228
+ export const openApi: OpenApiRouteDoc = {
229
+ tag: 'Shipment Tracking',
230
+ summary: 'Ships map dashboard widget',
231
+ methods: {
232
+ GET: {
233
+ summary: 'Aggregate live vessel and at-port positions for active shipments',
234
+ description:
235
+ 'Returns one marker per distinct in-transit vessel (live AIS position) plus one port marker per port where at-rest cargo waits, scoped to the authenticated organization. Read-only projection over existing Shipment data + the external vessel-api.',
236
+ query: shipsMapQuerySchema,
237
+ responses: [
238
+ { status: 200, description: 'Ships map payload', schema: shipsMapResponseSchema },
239
+ ],
240
+ errors: [
241
+ { status: 400, description: 'Invalid query parameters', schema: z.object({ error: z.string() }) },
242
+ { status: 401, description: 'Unauthorized', schema: z.object({ error: z.string() }) },
243
+ ],
244
+ },
245
+ },
246
+ }
@@ -0,0 +1,185 @@
1
+ import { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'
2
+ import { z } from 'zod'
3
+ import { LocationOverride } from '../../data/entities'
4
+ import {
5
+ locationOverrideListSchema,
6
+ locationOverrideCreateSchema,
7
+ locationOverrideUpdateSchema,
8
+ } from '../../data/validators'
9
+ import { parseBooleanToken } from '@open-mercato/shared/lib/boolean'
10
+ import {
11
+ createShipmentTrackingCrudOpenApi,
12
+ createPagedListResponseSchema,
13
+ defaultOkResponseSchema,
14
+ } from '../openapi'
15
+ import { withScopedPayload } from '../utils'
16
+ import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
17
+
18
+ const rawBodySchema = z.object({}).passthrough()
19
+
20
+ type LocationOverrideListQuery = z.infer<typeof locationOverrideListSchema>
21
+
22
+ const routeMetadata = {
23
+ GET: { requireAuth: true, requireFeatures: ['shipment_tracking.location_overrides.view'] },
24
+ POST: { requireAuth: true, requireFeatures: ['shipment_tracking.location_overrides.manage'] },
25
+ PUT: { requireAuth: true, requireFeatures: ['shipment_tracking.location_overrides.manage'] },
26
+ DELETE: { requireAuth: true, requireFeatures: ['shipment_tracking.location_overrides.manage'] },
27
+ }
28
+
29
+ const listFields = [
30
+ 'id',
31
+ 'carrierCode',
32
+ 'unlocode',
33
+ 'facilityCode',
34
+ 'facilityCodeListProvider',
35
+ 'overrideData',
36
+ 'description',
37
+ 'isActive',
38
+ 'createdAt',
39
+ 'updatedAt',
40
+ 'createdByUserId',
41
+ 'updatedByUserId',
42
+ ]
43
+
44
+ const buildFilters = (query: LocationOverrideListQuery): Record<string, unknown> => {
45
+ const filters: Record<string, unknown> = {
46
+ deletedAt: null,
47
+ }
48
+
49
+ if (query.carrierCode) {
50
+ filters.carrierCode = { $eq: query.carrierCode }
51
+ }
52
+
53
+ if (query.unlocode) {
54
+ filters.unlocode = { $eq: query.unlocode.toUpperCase() }
55
+ }
56
+
57
+ if (query.facilityCode) {
58
+ filters.facilityCode = { $eq: query.facilityCode }
59
+ }
60
+
61
+ if (query.isActive !== undefined) {
62
+ const parsed = parseBooleanToken(query.isActive)
63
+ if (parsed !== null) {
64
+ filters.isActive = parsed
65
+ }
66
+ }
67
+
68
+ if (query.search) {
69
+ const searchTerm = query.search.trim()
70
+ if (searchTerm) {
71
+ filters.$or = [
72
+ { carrierCode: { $ilike: `%${searchTerm}%` } },
73
+ { unlocode: { $ilike: `%${searchTerm}%` } },
74
+ { facilityCode: { $ilike: `%${searchTerm}%` } },
75
+ { description: { $ilike: `%${searchTerm}%` } },
76
+ ]
77
+ }
78
+ }
79
+
80
+ return filters
81
+ }
82
+
83
+ const crud = makeCrudRoute({
84
+ metadata: routeMetadata,
85
+ orm: {
86
+ entity: LocationOverride,
87
+ idField: 'id',
88
+ orgField: 'organizationId',
89
+ tenantField: 'tenantId',
90
+ },
91
+ list: {
92
+ schema: locationOverrideListSchema,
93
+ fields: listFields,
94
+ sortFieldMap: {
95
+ id: 'id',
96
+ carrierCode: 'carrier_code',
97
+ unlocode: 'unlocode',
98
+ facilityCode: 'facility_code',
99
+ isActive: 'is_active',
100
+ createdAt: 'created_at',
101
+ },
102
+ buildFilters: async (query) => buildFilters(query),
103
+ },
104
+ actions: {
105
+ create: {
106
+ commandId: 'shipment_tracking.location_override.create',
107
+ schema: rawBodySchema,
108
+ mapInput: async ({ raw, ctx }) => {
109
+ const { translate } = await resolveTranslations()
110
+ const scoped = withScopedPayload(raw ?? {}, ctx, translate)
111
+ return locationOverrideCreateSchema.parse(scoped)
112
+ },
113
+ response: ({ result }) => ({ id: result?.id ?? null }),
114
+ status: 201,
115
+ },
116
+ update: {
117
+ commandId: 'shipment_tracking.location_override.update',
118
+ schema: rawBodySchema,
119
+ mapInput: async ({ raw, ctx }) => {
120
+ const { translate } = await resolveTranslations()
121
+ const scoped = withScopedPayload(raw ?? {}, ctx, translate)
122
+ return locationOverrideUpdateSchema.parse(scoped)
123
+ },
124
+ response: ({ result }) => ({ id: result?.id ?? null }),
125
+ status: 200,
126
+ },
127
+ delete: {
128
+ commandId: 'shipment_tracking.location_override.delete',
129
+ schema: rawBodySchema,
130
+ mapInput: async ({ raw, ctx }) => {
131
+ const { translate } = await resolveTranslations()
132
+ const scoped = withScopedPayload(raw ?? {}, ctx, translate)
133
+ return { id: (raw as Record<string, unknown>)?.id, ...scoped }
134
+ },
135
+ response: ({ result }) => ({ id: result?.id ?? null }),
136
+ status: 200,
137
+ },
138
+ },
139
+ })
140
+
141
+ export const openApi = createShipmentTrackingCrudOpenApi({
142
+ resourceName: 'LocationOverride',
143
+ pluralName: 'LocationOverrides',
144
+ querySchema: locationOverrideListSchema,
145
+ listResponseSchema: createPagedListResponseSchema(z.object({
146
+ id: z.string().uuid(),
147
+ carrierCode: z.string().nullable(),
148
+ unlocode: z.string(),
149
+ facilityCode: z.string(),
150
+ facilityCodeListProvider: z.enum(['BIC', 'SMDG']),
151
+ overrideData: z.object({
152
+ name: z.string(),
153
+ address: z.string().nullable().optional(),
154
+ operatorName: z.string().nullable().optional(),
155
+ countryCode: z.string().nullable().optional(),
156
+ facilityTypeCode: z.string().nullable().optional(),
157
+ coords: z.object({
158
+ latitude: z.number(),
159
+ longitude: z.number(),
160
+ }).nullable().optional(),
161
+ }),
162
+ description: z.string().nullable(),
163
+ isActive: z.boolean(),
164
+ })),
165
+ create: {
166
+ schema: rawBodySchema,
167
+ description: 'Creates a new location override for BIC/SMDG facility data correction.',
168
+ },
169
+ update: {
170
+ schema: rawBodySchema,
171
+ responseSchema: defaultOkResponseSchema,
172
+ description: 'Updates an existing location override.',
173
+ },
174
+ del: {
175
+ schema: z.object({ id: z.string().uuid() }),
176
+ responseSchema: defaultOkResponseSchema,
177
+ description: 'Deletes a location override (soft delete).',
178
+ },
179
+ })
180
+
181
+ export const metadata = crud.metadata
182
+ export const GET = crud.GET
183
+ export const POST = crud.POST
184
+ export const PUT = crud.PUT
185
+ export const DELETE = crud.DELETE
@@ -0,0 +1,28 @@
1
+ import { type ZodTypeAny } from 'zod'
2
+ import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
3
+ import {
4
+ createCrudOpenApiFactory,
5
+ createPagedListResponseSchema as createSharedPagedListResponseSchema,
6
+ defaultCreateResponseSchema as sharedDefaultCreateResponseSchema,
7
+ defaultOkResponseSchema as sharedDefaultOkResponseSchema,
8
+ type CrudOpenApiOptions,
9
+ } from '@open-mercato/shared/lib/openapi/crud'
10
+
11
+ export const defaultCreateResponseSchema = sharedDefaultCreateResponseSchema
12
+ export const defaultOkResponseSchema = sharedDefaultOkResponseSchema
13
+
14
+ export function createPagedListResponseSchema(itemSchema: ZodTypeAny) {
15
+ return createSharedPagedListResponseSchema(itemSchema, { paginationMetaOptional: true })
16
+ }
17
+
18
+ const buildShipmentTrackingCrudOpenApi = createCrudOpenApiFactory({
19
+ defaultTag: 'Shipment Tracking',
20
+ defaultCreateResponseSchema,
21
+ defaultOkResponseSchema,
22
+ makeListDescription: ({ pluralLower }) =>
23
+ `Returns a paginated collection of ${pluralLower} scoped to the authenticated organization.`,
24
+ })
25
+
26
+ export function createShipmentTrackingCrudOpenApi(options: CrudOpenApiOptions): OpenApiRouteDoc {
27
+ return buildShipmentTrackingCrudOpenApi(options)
28
+ }