@freighttech/terminal-tracking 0.7.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 (236) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +121 -0
  3. package/dist/generated/entities/terminal_config/index.js +53 -0
  4. package/dist/generated/entities/terminal_config/index.js.map +7 -0
  5. package/dist/generated/entities/terminal_event/index.js +59 -0
  6. package/dist/generated/entities/terminal_event/index.js.map +7 -0
  7. package/dist/generated/entities/terminal_tracking_job/index.js +37 -0
  8. package/dist/generated/entities/terminal_tracking_job/index.js.map +7 -0
  9. package/dist/generated/entities/terminal_vessel_visit/index.js +41 -0
  10. package/dist/generated/entities/terminal_vessel_visit/index.js.map +7 -0
  11. package/dist/generated/entities.ids.generated.js +26 -0
  12. package/dist/generated/entities.ids.generated.js.map +7 -0
  13. package/dist/index.js +20 -0
  14. package/dist/index.js.map +7 -0
  15. package/dist/modules/terminal_tracking/acl.js +14 -0
  16. package/dist/modules/terminal_tracking/acl.js.map +7 -0
  17. package/dist/modules/terminal_tracking/api/openapi.js +27 -0
  18. package/dist/modules/terminal_tracking/api/openapi.js.map +7 -0
  19. package/dist/modules/terminal_tracking/api/terminal-configs/route.js +140 -0
  20. package/dist/modules/terminal_tracking/api/terminal-configs/route.js.map +7 -0
  21. package/dist/modules/terminal_tracking/api/terminal-configs/test/route.js +58 -0
  22. package/dist/modules/terminal_tracking/api/terminal-configs/test/route.js.map +7 -0
  23. package/dist/modules/terminal_tracking/api/tracking-jobs/details/route.js +109 -0
  24. package/dist/modules/terminal_tracking/api/tracking-jobs/details/route.js.map +7 -0
  25. package/dist/modules/terminal_tracking/api/tracking-jobs/poll/route.js +58 -0
  26. package/dist/modules/terminal_tracking/api/tracking-jobs/poll/route.js.map +7 -0
  27. package/dist/modules/terminal_tracking/api/tracking-jobs/route.js +189 -0
  28. package/dist/modules/terminal_tracking/api/tracking-jobs/route.js.map +7 -0
  29. package/dist/modules/terminal_tracking/api/utils.js +12 -0
  30. package/dist/modules/terminal_tracking/api/utils.js.map +7 -0
  31. package/dist/modules/terminal_tracking/api/vessel-visits/route.js +83 -0
  32. package/dist/modules/terminal_tracking/api/vessel-visits/route.js.map +7 -0
  33. package/dist/modules/terminal_tracking/backend/terminal-configs/page.js +669 -0
  34. package/dist/modules/terminal_tracking/backend/terminal-configs/page.js.map +7 -0
  35. package/dist/modules/terminal_tracking/backend/terminal-configs/page.meta.js +19 -0
  36. package/dist/modules/terminal_tracking/backend/terminal-configs/page.meta.js.map +7 -0
  37. package/dist/modules/terminal_tracking/backend/terminal-containers/page.js +275 -0
  38. package/dist/modules/terminal_tracking/backend/terminal-containers/page.js.map +7 -0
  39. package/dist/modules/terminal_tracking/backend/terminal-containers/page.meta.js +19 -0
  40. package/dist/modules/terminal_tracking/backend/terminal-containers/page.meta.js.map +7 -0
  41. package/dist/modules/terminal_tracking/ce.js +35 -0
  42. package/dist/modules/terminal_tracking/ce.js.map +7 -0
  43. package/dist/modules/terminal_tracking/commands/index.js +4 -0
  44. package/dist/modules/terminal_tracking/commands/index.js.map +7 -0
  45. package/dist/modules/terminal_tracking/commands/terminal-configs.js +107 -0
  46. package/dist/modules/terminal_tracking/commands/terminal-configs.js.map +7 -0
  47. package/dist/modules/terminal_tracking/commands/terminal-tracking.js +27 -0
  48. package/dist/modules/terminal_tracking/commands/terminal-tracking.js.map +7 -0
  49. package/dist/modules/terminal_tracking/commands/tracking-jobs.js +56 -0
  50. package/dist/modules/terminal_tracking/commands/tracking-jobs.js.map +7 -0
  51. package/dist/modules/terminal_tracking/components/ContainerDetailsDrawer.js +371 -0
  52. package/dist/modules/terminal_tracking/components/ContainerDetailsDrawer.js.map +7 -0
  53. package/dist/modules/terminal_tracking/data/entities.js +337 -0
  54. package/dist/modules/terminal_tracking/data/entities.js.map +7 -0
  55. package/dist/modules/terminal_tracking/data/validators.js +98 -0
  56. package/dist/modules/terminal_tracking/data/validators.js.map +7 -0
  57. package/dist/modules/terminal_tracking/di.js +39 -0
  58. package/dist/modules/terminal_tracking/di.js.map +7 -0
  59. package/dist/modules/terminal_tracking/encryption.js +14 -0
  60. package/dist/modules/terminal_tracking/encryption.js.map +7 -0
  61. package/dist/modules/terminal_tracking/events.js +45 -0
  62. package/dist/modules/terminal_tracking/events.js.map +7 -0
  63. package/dist/modules/terminal_tracking/i18n/de.json +175 -0
  64. package/dist/modules/terminal_tracking/i18n/en.json +178 -0
  65. package/dist/modules/terminal_tracking/i18n/es.json +175 -0
  66. package/dist/modules/terminal_tracking/i18n/pl.json +206 -0
  67. package/dist/modules/terminal_tracking/index.js +15 -0
  68. package/dist/modules/terminal_tracking/index.js.map +7 -0
  69. package/dist/modules/terminal_tracking/lib/adapters/bct/adapter.js +164 -0
  70. package/dist/modules/terminal_tracking/lib/adapters/bct/adapter.js.map +7 -0
  71. package/dist/modules/terminal_tracking/lib/adapters/bct/auth/basic.js +23 -0
  72. package/dist/modules/terminal_tracking/lib/adapters/bct/auth/basic.js.map +7 -0
  73. package/dist/modules/terminal_tracking/lib/adapters/bct/incos-semantics.js +146 -0
  74. package/dist/modules/terminal_tracking/lib/adapters/bct/incos-semantics.js.map +7 -0
  75. package/dist/modules/terminal_tracking/lib/adapters/bct/types.js +1 -0
  76. package/dist/modules/terminal_tracking/lib/adapters/bct/types.js.map +7 -0
  77. package/dist/modules/terminal_tracking/lib/adapters/gct/adapter.js +106 -0
  78. package/dist/modules/terminal_tracking/lib/adapters/gct/adapter.js.map +7 -0
  79. package/dist/modules/terminal_tracking/lib/adapters/gct/auth/token.js +120 -0
  80. package/dist/modules/terminal_tracking/lib/adapters/gct/auth/token.js.map +7 -0
  81. package/dist/modules/terminal_tracking/lib/adapters/gct/gct-semantics.js +77 -0
  82. package/dist/modules/terminal_tracking/lib/adapters/gct/gct-semantics.js.map +7 -0
  83. package/dist/modules/terminal_tracking/lib/adapters/gct/types.js +1 -0
  84. package/dist/modules/terminal_tracking/lib/adapters/gct/types.js.map +7 -0
  85. package/dist/modules/terminal_tracking/lib/adapters/index.js +12 -0
  86. package/dist/modules/terminal_tracking/lib/adapters/index.js.map +7 -0
  87. package/dist/modules/terminal_tracking/lib/adapters/n4/adapter.js +121 -0
  88. package/dist/modules/terminal_tracking/lib/adapters/n4/adapter.js.map +7 -0
  89. package/dist/modules/terminal_tracking/lib/adapters/n4/auth/ropc.js +81 -0
  90. package/dist/modules/terminal_tracking/lib/adapters/n4/auth/ropc.js.map +7 -0
  91. package/dist/modules/terminal_tracking/lib/adapters/n4/http.js +66 -0
  92. package/dist/modules/terminal_tracking/lib/adapters/n4/http.js.map +7 -0
  93. package/dist/modules/terminal_tracking/lib/adapters/n4/n4-semantics.js +95 -0
  94. package/dist/modules/terminal_tracking/lib/adapters/n4/n4-semantics.js.map +7 -0
  95. package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/data-table.js +70 -0
  96. package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/data-table.js.map +7 -0
  97. package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/vessel-data-table.js +44 -0
  98. package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/vessel-data-table.js.map +7 -0
  99. package/dist/modules/terminal_tracking/lib/adapters/n4/proxy.js +15 -0
  100. package/dist/modules/terminal_tracking/lib/adapters/n4/proxy.js.map +7 -0
  101. package/dist/modules/terminal_tracking/lib/adapters/n4/types.js +1 -0
  102. package/dist/modules/terminal_tracking/lib/adapters/n4/types.js.map +7 -0
  103. package/dist/modules/terminal_tracking/lib/adapters/zoned-time.js +27 -0
  104. package/dist/modules/terminal_tracking/lib/adapters/zoned-time.js.map +7 -0
  105. package/dist/modules/terminal_tracking/lib/availability.js +40 -0
  106. package/dist/modules/terminal_tracking/lib/availability.js.map +7 -0
  107. package/dist/modules/terminal_tracking/lib/ensure-schedule.js +51 -0
  108. package/dist/modules/terminal_tracking/lib/ensure-schedule.js.map +7 -0
  109. package/dist/modules/terminal_tracking/lib/holds.js +240 -0
  110. package/dist/modules/terminal_tracking/lib/holds.js.map +7 -0
  111. package/dist/modules/terminal_tracking/lib/logger.js +19 -0
  112. package/dist/modules/terminal_tracking/lib/logger.js.map +7 -0
  113. package/dist/modules/terminal_tracking/lib/rate-limiter.js +30 -0
  114. package/dist/modules/terminal_tracking/lib/rate-limiter.js.map +7 -0
  115. package/dist/modules/terminal_tracking/lib/stops.js +48 -0
  116. package/dist/modules/terminal_tracking/lib/stops.js.map +7 -0
  117. package/dist/modules/terminal_tracking/lib/terminal-adapter.js +1 -0
  118. package/dist/modules/terminal_tracking/lib/terminal-adapter.js.map +7 -0
  119. package/dist/modules/terminal_tracking/lib/totp.js +41 -0
  120. package/dist/modules/terminal_tracking/lib/totp.js.map +7 -0
  121. package/dist/modules/terminal_tracking/migrations/Migration20260609120000_terminal_tracking.js +101 -0
  122. package/dist/modules/terminal_tracking/migrations/Migration20260609120000_terminal_tracking.js.map +7 -0
  123. package/dist/modules/terminal_tracking/migrations/Migration20260610120000_terminal_vessel_visits.js +39 -0
  124. package/dist/modules/terminal_tracking/migrations/Migration20260610120000_terminal_vessel_visits.js.map +7 -0
  125. package/dist/modules/terminal_tracking/migrations/Migration20260611120000_terminal_config_proxy.js +13 -0
  126. package/dist/modules/terminal_tracking/migrations/Migration20260611120000_terminal_config_proxy.js.map +7 -0
  127. package/dist/modules/terminal_tracking/migrations/Migration20260707120000_terminal_job_availability_markers.js +15 -0
  128. package/dist/modules/terminal_tracking/migrations/Migration20260707120000_terminal_job_availability_markers.js.map +7 -0
  129. package/dist/modules/terminal_tracking/migrations/Migration20260805120000_terminal_event_loaded_at.js +13 -0
  130. package/dist/modules/terminal_tracking/migrations/Migration20260805120000_terminal_event_loaded_at.js.map +7 -0
  131. package/dist/modules/terminal_tracking/services/terminalMatcherService.js +61 -0
  132. package/dist/modules/terminal_tracking/services/terminalMatcherService.js.map +7 -0
  133. package/dist/modules/terminal_tracking/services/terminalRegistry.js +24 -0
  134. package/dist/modules/terminal_tracking/services/terminalRegistry.js.map +7 -0
  135. package/dist/modules/terminal_tracking/services/terminalTrackingService.js +687 -0
  136. package/dist/modules/terminal_tracking/services/terminalTrackingService.js.map +7 -0
  137. package/dist/modules/terminal_tracking/setup.js +23 -0
  138. package/dist/modules/terminal_tracking/setup.js.map +7 -0
  139. package/dist/modules/terminal_tracking/subscribers/terminal-tracking-job-initial-poll.js +22 -0
  140. package/dist/modules/terminal_tracking/subscribers/terminal-tracking-job-initial-poll.js.map +7 -0
  141. package/generated/entities/terminal_config/index.ts +36 -0
  142. package/generated/entities/terminal_event/index.ts +39 -0
  143. package/generated/entities/terminal_tracking_job/index.ts +28 -0
  144. package/generated/entities/terminal_vessel_visit/index.ts +30 -0
  145. package/generated/entities.ids.generated.ts +52 -0
  146. package/package.json +80 -0
  147. package/src/index.ts +44 -0
  148. package/src/modules/terminal_tracking/__integration__/TC-TRACK-301-gct-config-test-connection.spec.ts +66 -0
  149. package/src/modules/terminal_tracking/__integration__/TC-TRACK-317-bct-config-test-connection.spec.ts +68 -0
  150. package/src/modules/terminal_tracking/__integration__/helpers.ts +148 -0
  151. package/src/modules/terminal_tracking/__integration__/meta.ts +4 -0
  152. package/src/modules/terminal_tracking/acl.ts +10 -0
  153. package/src/modules/terminal_tracking/api/openapi.ts +28 -0
  154. package/src/modules/terminal_tracking/api/terminal-configs/route.ts +140 -0
  155. package/src/modules/terminal_tracking/api/terminal-configs/test/route.ts +64 -0
  156. package/src/modules/terminal_tracking/api/tracking-jobs/details/route.ts +116 -0
  157. package/src/modules/terminal_tracking/api/tracking-jobs/poll/route.ts +64 -0
  158. package/src/modules/terminal_tracking/api/tracking-jobs/route.ts +243 -0
  159. package/src/modules/terminal_tracking/api/utils.ts +10 -0
  160. package/src/modules/terminal_tracking/api/vessel-visits/route.ts +95 -0
  161. package/src/modules/terminal_tracking/backend/terminal-configs/page.meta.ts +16 -0
  162. package/src/modules/terminal_tracking/backend/terminal-configs/page.tsx +728 -0
  163. package/src/modules/terminal_tracking/backend/terminal-containers/page.meta.ts +16 -0
  164. package/src/modules/terminal_tracking/backend/terminal-containers/page.tsx +328 -0
  165. package/src/modules/terminal_tracking/ce.ts +31 -0
  166. package/src/modules/terminal_tracking/commands/index.ts +3 -0
  167. package/src/modules/terminal_tracking/commands/terminal-configs.ts +132 -0
  168. package/src/modules/terminal_tracking/commands/terminal-tracking.ts +34 -0
  169. package/src/modules/terminal_tracking/commands/tracking-jobs.ts +69 -0
  170. package/src/modules/terminal_tracking/components/ContainerDetailsDrawer.tsx +540 -0
  171. package/src/modules/terminal_tracking/data/entities.ts +386 -0
  172. package/src/modules/terminal_tracking/data/validators.ts +113 -0
  173. package/src/modules/terminal_tracking/di.ts +46 -0
  174. package/src/modules/terminal_tracking/encryption.ts +12 -0
  175. package/src/modules/terminal_tracking/events.ts +48 -0
  176. package/src/modules/terminal_tracking/i18n/de.json +175 -0
  177. package/src/modules/terminal_tracking/i18n/en.json +178 -0
  178. package/src/modules/terminal_tracking/i18n/es.json +175 -0
  179. package/src/modules/terminal_tracking/i18n/pl.json +206 -0
  180. package/src/modules/terminal_tracking/index.ts +13 -0
  181. package/src/modules/terminal_tracking/lib/__tests__/availability.test.ts +136 -0
  182. package/src/modules/terminal_tracking/lib/__tests__/ensure-schedule.test.ts +67 -0
  183. package/src/modules/terminal_tracking/lib/__tests__/holds.test.ts +73 -0
  184. package/src/modules/terminal_tracking/lib/__tests__/stops.test.ts +80 -0
  185. package/src/modules/terminal_tracking/lib/__tests__/totp.test.ts +38 -0
  186. package/src/modules/terminal_tracking/lib/adapters/bct/__tests__/adapter.test.ts +196 -0
  187. package/src/modules/terminal_tracking/lib/adapters/bct/__tests__/incos-semantics.test.ts +303 -0
  188. package/src/modules/terminal_tracking/lib/adapters/bct/adapter.ts +219 -0
  189. package/src/modules/terminal_tracking/lib/adapters/bct/auth/basic.ts +34 -0
  190. package/src/modules/terminal_tracking/lib/adapters/bct/incos-semantics.ts +291 -0
  191. package/src/modules/terminal_tracking/lib/adapters/bct/types.ts +113 -0
  192. package/src/modules/terminal_tracking/lib/adapters/gct/__tests__/adapter.test.ts +238 -0
  193. package/src/modules/terminal_tracking/lib/adapters/gct/__tests__/gct-semantics.test.ts +133 -0
  194. package/src/modules/terminal_tracking/lib/adapters/gct/adapter.ts +152 -0
  195. package/src/modules/terminal_tracking/lib/adapters/gct/auth/token.ts +219 -0
  196. package/src/modules/terminal_tracking/lib/adapters/gct/gct-semantics.ts +136 -0
  197. package/src/modules/terminal_tracking/lib/adapters/gct/types.ts +58 -0
  198. package/src/modules/terminal_tracking/lib/adapters/index.ts +16 -0
  199. package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/adapter-proxy.test.ts +69 -0
  200. package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/data-table.test.ts +179 -0
  201. package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/http.test.ts +98 -0
  202. package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/n4-semantics.test.ts +140 -0
  203. package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/proxy.test.ts +19 -0
  204. package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/vessel-data-table.test.ts +67 -0
  205. package/src/modules/terminal_tracking/lib/adapters/n4/adapter.ts +163 -0
  206. package/src/modules/terminal_tracking/lib/adapters/n4/auth/ropc.ts +104 -0
  207. package/src/modules/terminal_tracking/lib/adapters/n4/http.ts +127 -0
  208. package/src/modules/terminal_tracking/lib/adapters/n4/n4-semantics.ts +156 -0
  209. package/src/modules/terminal_tracking/lib/adapters/n4/parsers/data-table.ts +102 -0
  210. package/src/modules/terminal_tracking/lib/adapters/n4/parsers/vessel-data-table.ts +60 -0
  211. package/src/modules/terminal_tracking/lib/adapters/n4/proxy.ts +24 -0
  212. package/src/modules/terminal_tracking/lib/adapters/n4/types.ts +56 -0
  213. package/src/modules/terminal_tracking/lib/adapters/zoned-time.ts +65 -0
  214. package/src/modules/terminal_tracking/lib/availability.ts +119 -0
  215. package/src/modules/terminal_tracking/lib/ensure-schedule.ts +83 -0
  216. package/src/modules/terminal_tracking/lib/holds.ts +344 -0
  217. package/src/modules/terminal_tracking/lib/logger.ts +21 -0
  218. package/src/modules/terminal_tracking/lib/rate-limiter.ts +52 -0
  219. package/src/modules/terminal_tracking/lib/stops.ts +124 -0
  220. package/src/modules/terminal_tracking/lib/terminal-adapter.ts +136 -0
  221. package/src/modules/terminal_tracking/lib/totp.ts +63 -0
  222. package/src/modules/terminal_tracking/migrations/Migration20260609120000_terminal_tracking.ts +104 -0
  223. package/src/modules/terminal_tracking/migrations/Migration20260610120000_terminal_vessel_visits.ts +40 -0
  224. package/src/modules/terminal_tracking/migrations/Migration20260611120000_terminal_config_proxy.ts +11 -0
  225. package/src/modules/terminal_tracking/migrations/Migration20260707120000_terminal_job_availability_markers.ts +13 -0
  226. package/src/modules/terminal_tracking/migrations/Migration20260805120000_terminal_event_loaded_at.ts +16 -0
  227. package/src/modules/terminal_tracking/services/__tests__/availabilityEmit.test.ts +277 -0
  228. package/src/modules/terminal_tracking/services/__tests__/createJob.test.ts +59 -0
  229. package/src/modules/terminal_tracking/services/__tests__/pollAllBatch.test.ts +147 -0
  230. package/src/modules/terminal_tracking/services/__tests__/terminalMatcher.test.ts +70 -0
  231. package/src/modules/terminal_tracking/services/__tests__/vesselResolution.test.ts +453 -0
  232. package/src/modules/terminal_tracking/services/terminalMatcherService.ts +97 -0
  233. package/src/modules/terminal_tracking/services/terminalRegistry.ts +30 -0
  234. package/src/modules/terminal_tracking/services/terminalTrackingService.ts +912 -0
  235. package/src/modules/terminal_tracking/setup.ts +24 -0
  236. package/src/modules/terminal_tracking/subscribers/terminal-tracking-job-initial-poll.ts +32 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 FreightTech
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # @freighttech/terminal-tracking
2
+
3
+ Container-terminal tracking for the FreightTech FMS. Polls container terminal
4
+ APIs (Navis **N4** family; Baltic Hub / BCT Gdańsk first), normalizes the
5
+ results into events, and emits them — with per-terminal runtime configuration,
6
+ periodic polling, and terminal matching.
7
+
8
+ ## Features
9
+
10
+ - **Per-terminal config** (`TerminalConfig`) — base URL, OAuth, encrypted
11
+ credentials, rate limits, and matching identifiers (UN/LOCODE, BIC, SMDG,
12
+ name aliases). One row per tenant per terminal. Optional `proxyUrl` routes
13
+ that terminal's API calls through an HTTP forward proxy (to egress from a
14
+ whitelisted IP); empty = direct.
15
+ - **Config-driven N4 adapter** — a single `N4TerminalAdapter` serves all N4
16
+ terminals; endpoint paths default from the adapter. Auth via Azure B2C ROPC
17
+ (password grant) or client-credentials.
18
+ - **GCT adapter** (`adapterType: 'gct'`) — Gdynia Container Terminal's bespoke
19
+ FastAPI. Path-minted token replayed in the `Authorization` header; a container
20
+ *snapshot* mapped to gate-in (`GTIN`) / departed (`DEPA`) milestones.
21
+ - **BCT adapter** (`adapterType: 'bct'`) — Bałtycki Terminal Kontenerowy (Gdynia)
22
+ via the **INCOS** platform (`https://incos.pl`). Plain HTTP **Basic** auth
23
+ (`authType: 'basic'`, `auth_config: { username, password }`). Read-only Phase 1:
24
+ the `GET /rest-container/container/{nbr}` snapshot is mapped to the container's
25
+ **current** milestone (mirroring N4's `/unit` current-state row). The arrival is
26
+ refined by `in_yard_type` to match N4's vocabulary: a vessel arrival is a
27
+ discharge (`in_yard_date` → `DISC` / `equipment.discharged`), a truck/rail
28
+ arrival is a gate-in (→ `GTIN` / `equipment.gate_in`); once the box leaves,
29
+ `out_yard_date` → `DEPA`. Emitting only the current milestone (not both arrival
30
+ and departure every poll) lets a departed job reach `completed` and drop from
31
+ the poll set — otherwise `isFullyDeparted` never trips and the box is polled
32
+ forever, burning the daily budget. Each event carries an explicit import/export
33
+ direction (`category`) and a real mode of transport (`in/out_yard_type`: T/V/R →
34
+ TRUCK/VESSEL/RAIL). **Holds:** INCOS flags customs status binarily, so a
35
+ customs `HOLD` is mapped by direction to the shared `lib/holds` catalogue code
36
+ (`CUSTOMS IMPORT HOLD` / `CUSTOMS EXPORT HOLD` — both `critical`) instead of an
37
+ unclassified raw string; the `;`-separated `constraint` codes (e.g. `STOPUC`)
38
+ pass through and stay unclassified until INCOS documents them. This is coarser
39
+ than N4 (which distinguishes ~20 impediment codes incl. permission-vs-hold),
40
+ but flows through the same `impediments[]` field, availability logic, and hold
41
+ badges.
42
+ **Data parity with N4:** TimeIn (`in_yard_date`), TimeOut (`out_yard_date`),
43
+ seals (`seal1..4`), holds (`customs_status`+`constraint`), and VGM are all
44
+ present. The one gap is a separate **Loaded** timestamp — the INCOS container
45
+ lookup has no dedicated load-onto-transport time (N4's "Loaded" column), so no
46
+ `LOAD` event / `loadedAt` is emitted (it lives only in the rail endpoint).
47
+ **Vessel ETA/ATA (Phase 2, done):** INCOS keys a visit by (vessel, voyage), so
48
+ the mapping packs both into the visit ref (`CODE/VOY`) and `fetchVesselVisit`
49
+ resolves it via `GET /rest-vesselvisit/vesselvisit/{code}/{voyage}` (dates there
50
+ are `YYYY-MM-DD HH:MM:SS`, unlike the container endpoint). Enable it by setting
51
+ `endpoints.vessel: /rest-vesselvisit/vesselvisit` on the config; the shared
52
+ `TerminalVesselVisit` TTL cache then serves ETA/ETD/ATA/ATD per leg. Still
53
+ deferred: the **rail** endpoints (and the Loaded time they carry). The dedup key
54
+ is the container number (the lookup carries no per-visit gkey).
55
+ **Rate limit:** INCOS caps BCT at **10 000 requests/day**. Set the config's
56
+ `rateLimitRequests: 10000` + `rateLimitWindowSeconds: 86400` (the token bucket
57
+ refills the full allowance over the window) — the entity defaults (200/60 s)
58
+ do not model a daily cap. Because BCT has no batch endpoint, **each container
59
+ poll costs one request**, so the daily budget bounds `containers × polls/day`
60
+ (e.g. 100 containers every 15 min ≈ 9 600/day — near the ceiling).
61
+ **⚠ TLS deployment prerequisite:** `incos.pl` serves an **incomplete
62
+ certificate chain** — only the leaf, omitting its intermediate
63
+ (`RapidSSL TLS RSA CA G1`, issued by the already-trusted DigiCert Global Root
64
+ G2). Browsers (and Bruno) fetch the missing intermediate via AIA, but
65
+ **Node/undici does not**, so the adapter fails with `fetch failed`
66
+ (TLS "unable to get local issuer certificate") unless the intermediate is
67
+ supplied via `NODE_EXTRA_CA_CERTS`. **This is already handled in production:**
68
+ `apps/web/Dockerfile` fetches `RapidSSL TLS RSA CA G1` (and the GeoTrust
69
+ intermediate for the Raiffeisen API) fresh at build time and bundles them into
70
+ `/app/certs/extra-ca-bundle.pem`. For local dev outside Docker, build the same
71
+ bundle yourself (see `apps/web/.env.example`). Verified live: with the
72
+ intermediate present the adapter validates the chain and polls containers. The
73
+ durable fix is for BCT/INCOS to serve the full chain.
74
+ - **Module-owned jobs** (`TerminalTrackingJob`) — track a container at a
75
+ terminal; poll on a configurable schedule (`@open-mercato/scheduler`) or on
76
+ demand. The scheduler **batches** due jobs per terminal into a single
77
+ comma-separated `/unit` request (up to 100 containers) to minimise API calls.
78
+ A job whose every current leg has **departed** moves to a terminal
79
+ `completed` status (dropped from the poll set); `/VESSEL` is also skipped for
80
+ departed legs (their visit is historic). A container that returns later is
81
+ tracked as a **new** job with clean history.
82
+ - **Vessel visits** (`TerminalVesselVisit`) — resolves the leg's vessel via
83
+ `/VESSEL` (Import → I/B visit, Export → O/B visit) and stores ETA/ETD/ATA/ATD,
84
+ phase, voyages, and the receive/cutoff window. The table doubles as a
85
+ TTL cache (default 1h, per-config override) so containers sharing a vessel
86
+ cost one lookup. Exposed at `GET /api/terminal_tracking/vessel-visits` and
87
+ shown per leg in the container details drawer.
88
+ - **Events** — emits `terminal_tracking.terminal_event.created` (and
89
+ `…​.updated` when an existing event's container or vessel data changes on a
90
+ re-poll) plus semantic `equipment.*` / `transport.*` events. Dedup keyed on
91
+ `{terminalCode}:{Ufv_Gkey}:{eventCode}` so multiple Unit Facility Visits
92
+ (import/export legs) per container stay distinct. The payload carries the
93
+ nested `vesselVisit` (ETA/ATA/…) when resolved.
94
+ - **Terminal matching** — `TerminalMatcherService` resolves a facility to a
95
+ configured terminal by exact BIC / SMDG / UN/LOCODE, or fuzzy name (fuse.js).
96
+ - **Admin UI** — Settings → Terminal Tracking: Terminals (CRUD + Test
97
+ connection) and Tracked Containers (with a container details drawer showing
98
+ milestones, holds, and vessel ETA/ATA).
99
+
100
+ ## Module id
101
+
102
+ `terminal_tracking` — enable in the host app's `src/modules.ts`:
103
+
104
+ ```ts
105
+ { id: 'terminal_tracking', from: '@freighttech/terminal-tracking' }
106
+ ```
107
+
108
+ ## Timeline bridge
109
+
110
+ A subscriber in `@freighttech/shipment-tracking` consumes
111
+ `terminal_tracking.terminal_event.created` and surfaces terminal events on the
112
+ existing shipment Journey Timeline as `source:'port'` events (event-string
113
+ coupling only — no cross-module imports).
114
+
115
+ ## Notes
116
+
117
+ - IP-whitelisted terminals must be reached from a whitelisted egress IP
118
+ (deployment prerequisite; for local dev, route through a SOCKS tunnel).
119
+ - The OAuth token endpoint is public and stays direct.
120
+
121
+ See the spec: `.ai/specs/2026-06-08-n4-terminal-tracking-adapter.md`.
@@ -0,0 +1,53 @@
1
+ const id = "id";
2
+ const organization_id = "organization_id";
3
+ const tenant_id = "tenant_id";
4
+ const terminal_code = "terminal_code";
5
+ const adapter_type = "adapter_type";
6
+ const display_name = "display_name";
7
+ const base_url = "base_url";
8
+ const proxy_url = "proxy_url";
9
+ const endpoints = "endpoints";
10
+ const auth_type = "auth_type";
11
+ const token_url = "token_url";
12
+ const scope = "scope";
13
+ const client_id = "client_id";
14
+ const auth_config = "auth_config";
15
+ const rate_limit_requests = "rate_limit_requests";
16
+ const rate_limit_window_seconds = "rate_limit_window_seconds";
17
+ const vessel_cache_ttl_seconds = "vessel_cache_ttl_seconds";
18
+ const unlocode = "unlocode";
19
+ const bic_codes = "bic_codes";
20
+ const smdg_codes = "smdg_codes";
21
+ const name_aliases = "name_aliases";
22
+ const is_active = "is_active";
23
+ const created_at = "created_at";
24
+ const updated_at = "updated_at";
25
+ const deleted_at = "deleted_at";
26
+ export {
27
+ adapter_type,
28
+ auth_config,
29
+ auth_type,
30
+ base_url,
31
+ bic_codes,
32
+ client_id,
33
+ created_at,
34
+ deleted_at,
35
+ display_name,
36
+ endpoints,
37
+ id,
38
+ is_active,
39
+ name_aliases,
40
+ organization_id,
41
+ proxy_url,
42
+ rate_limit_requests,
43
+ rate_limit_window_seconds,
44
+ scope,
45
+ smdg_codes,
46
+ tenant_id,
47
+ terminal_code,
48
+ token_url,
49
+ unlocode,
50
+ updated_at,
51
+ vessel_cache_ttl_seconds
52
+ };
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../generated/entities/terminal_config/index.ts"],
4
+ "sourcesContent": ["// AUTO-GENERATED by scripts/generate-entity-fields.mjs (HEDGE-168). Do not edit.\n//\n// One file per entity, named `toSnake(ClassName)` \u2014 NOT the table name. Each\n// export is a database column name, mirroring what `mercato generate` writes\n// for `@open-mercato/*` packages. `loadStandaloneGeneratedPackageEntities()`\n// reads these back to build the host app's `entity-fields-registry.ts`, which\n// is what the Encryption and Translation managers list fields from.\n//\n// Regenerate with `node scripts/generate-entity-fields.mjs --all`; the package\n// build does it for you. Guarded by\n// `apps/web/src/__tests__/entity-fields-registry-contract.test.ts`.\nexport const id = \"id\";\nexport const organization_id = \"organization_id\";\nexport const tenant_id = \"tenant_id\";\nexport const terminal_code = \"terminal_code\";\nexport const adapter_type = \"adapter_type\";\nexport const display_name = \"display_name\";\nexport const base_url = \"base_url\";\nexport const proxy_url = \"proxy_url\";\nexport const endpoints = \"endpoints\";\nexport const auth_type = \"auth_type\";\nexport const token_url = \"token_url\";\nexport const scope = \"scope\";\nexport const client_id = \"client_id\";\nexport const auth_config = \"auth_config\";\nexport const rate_limit_requests = \"rate_limit_requests\";\nexport const rate_limit_window_seconds = \"rate_limit_window_seconds\";\nexport const vessel_cache_ttl_seconds = \"vessel_cache_ttl_seconds\";\nexport const unlocode = \"unlocode\";\nexport const bic_codes = \"bic_codes\";\nexport const smdg_codes = \"smdg_codes\";\nexport const name_aliases = \"name_aliases\";\nexport const is_active = \"is_active\";\nexport const created_at = \"created_at\";\nexport const updated_at = \"updated_at\";\nexport const deleted_at = \"deleted_at\";\n"],
5
+ "mappings": "AAWO,MAAM,KAAK;AACX,MAAM,kBAAkB;AACxB,MAAM,YAAY;AAClB,MAAM,gBAAgB;AACtB,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,WAAW;AACjB,MAAM,YAAY;AAClB,MAAM,YAAY;AAClB,MAAM,YAAY;AAClB,MAAM,YAAY;AAClB,MAAM,QAAQ;AACd,MAAM,YAAY;AAClB,MAAM,cAAc;AACpB,MAAM,sBAAsB;AAC5B,MAAM,4BAA4B;AAClC,MAAM,2BAA2B;AACjC,MAAM,WAAW;AACjB,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,eAAe;AACrB,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,aAAa;AACnB,MAAM,aAAa;",
6
+ "names": []
7
+ }
@@ -0,0 +1,59 @@
1
+ const id = "id";
2
+ const organization_id = "organization_id";
3
+ const tenant_id = "tenant_id";
4
+ const job = "job";
5
+ const source = "source";
6
+ const source_event_id = "source_event_id";
7
+ const event_type = "event_type";
8
+ const event_code = "event_code";
9
+ const event_classifier_code = "event_classifier_code";
10
+ const event_date_time = "event_date_time";
11
+ const container_number = "container_number";
12
+ const ufv_gkey = "ufv_gkey";
13
+ const transit_state = "transit_state";
14
+ const visit_state = "visit_state";
15
+ const facility_code = "facility_code";
16
+ const facility_code_list_provider = "facility_code_list_provider";
17
+ const unlocode = "unlocode";
18
+ const visit_ref_in = "visit_ref_in";
19
+ const visit_ref_out = "visit_ref_out";
20
+ const vessel_name = "vessel_name";
21
+ const voyage_number = "voyage_number";
22
+ const mode_of_transport = "mode_of_transport";
23
+ const seals = "seals";
24
+ const vgm_weight_kg = "vgm_weight_kg";
25
+ const impediments = "impediments";
26
+ const loaded_at = "loaded_at";
27
+ const raw_data = "raw_data";
28
+ const created_at = "created_at";
29
+ export {
30
+ container_number,
31
+ created_at,
32
+ event_classifier_code,
33
+ event_code,
34
+ event_date_time,
35
+ event_type,
36
+ facility_code,
37
+ facility_code_list_provider,
38
+ id,
39
+ impediments,
40
+ job,
41
+ loaded_at,
42
+ mode_of_transport,
43
+ organization_id,
44
+ raw_data,
45
+ seals,
46
+ source,
47
+ source_event_id,
48
+ tenant_id,
49
+ transit_state,
50
+ ufv_gkey,
51
+ unlocode,
52
+ vessel_name,
53
+ vgm_weight_kg,
54
+ visit_ref_in,
55
+ visit_ref_out,
56
+ visit_state,
57
+ voyage_number
58
+ };
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../generated/entities/terminal_event/index.ts"],
4
+ "sourcesContent": ["// AUTO-GENERATED by scripts/generate-entity-fields.mjs (HEDGE-168). Do not edit.\n//\n// One file per entity, named `toSnake(ClassName)` \u2014 NOT the table name. Each\n// export is a database column name, mirroring what `mercato generate` writes\n// for `@open-mercato/*` packages. `loadStandaloneGeneratedPackageEntities()`\n// reads these back to build the host app's `entity-fields-registry.ts`, which\n// is what the Encryption and Translation managers list fields from.\n//\n// Regenerate with `node scripts/generate-entity-fields.mjs --all`; the package\n// build does it for you. Guarded by\n// `apps/web/src/__tests__/entity-fields-registry-contract.test.ts`.\nexport const id = \"id\";\nexport const organization_id = \"organization_id\";\nexport const tenant_id = \"tenant_id\";\nexport const job = \"job\";\nexport const source = \"source\";\nexport const source_event_id = \"source_event_id\";\nexport const event_type = \"event_type\";\nexport const event_code = \"event_code\";\nexport const event_classifier_code = \"event_classifier_code\";\nexport const event_date_time = \"event_date_time\";\nexport const container_number = \"container_number\";\nexport const ufv_gkey = \"ufv_gkey\";\nexport const transit_state = \"transit_state\";\nexport const visit_state = \"visit_state\";\nexport const facility_code = \"facility_code\";\nexport const facility_code_list_provider = \"facility_code_list_provider\";\nexport const unlocode = \"unlocode\";\nexport const visit_ref_in = \"visit_ref_in\";\nexport const visit_ref_out = \"visit_ref_out\";\nexport const vessel_name = \"vessel_name\";\nexport const voyage_number = \"voyage_number\";\nexport const mode_of_transport = \"mode_of_transport\";\nexport const seals = \"seals\";\nexport const vgm_weight_kg = \"vgm_weight_kg\";\nexport const impediments = \"impediments\";\nexport const loaded_at = \"loaded_at\";\nexport const raw_data = \"raw_data\";\nexport const created_at = \"created_at\";\n"],
5
+ "mappings": "AAWO,MAAM,KAAK;AACX,MAAM,kBAAkB;AACxB,MAAM,YAAY;AAClB,MAAM,MAAM;AACZ,MAAM,SAAS;AACf,MAAM,kBAAkB;AACxB,MAAM,aAAa;AACnB,MAAM,aAAa;AACnB,MAAM,wBAAwB;AAC9B,MAAM,kBAAkB;AACxB,MAAM,mBAAmB;AACzB,MAAM,WAAW;AACjB,MAAM,gBAAgB;AACtB,MAAM,cAAc;AACpB,MAAM,gBAAgB;AACtB,MAAM,8BAA8B;AACpC,MAAM,WAAW;AACjB,MAAM,eAAe;AACrB,MAAM,gBAAgB;AACtB,MAAM,cAAc;AACpB,MAAM,gBAAgB;AACtB,MAAM,oBAAoB;AAC1B,MAAM,QAAQ;AACd,MAAM,gBAAgB;AACtB,MAAM,cAAc;AACpB,MAAM,YAAY;AAClB,MAAM,WAAW;AACjB,MAAM,aAAa;",
6
+ "names": []
7
+ }
@@ -0,0 +1,37 @@
1
+ const id = "id";
2
+ const organization_id = "organization_id";
3
+ const tenant_id = "tenant_id";
4
+ const terminal_code = "terminal_code";
5
+ const container_number = "container_number";
6
+ const status = "status";
7
+ const schedule = "schedule";
8
+ const next_poll_at = "next_poll_at";
9
+ const last_poll_at = "last_poll_at";
10
+ const retry_count = "retry_count";
11
+ const error_history = "error_history";
12
+ const empty_ready_at = "empty_ready_at";
13
+ const holds_cleared_at = "holds_cleared_at";
14
+ const created_at = "created_at";
15
+ const updated_at = "updated_at";
16
+ const deleted_at = "deleted_at";
17
+ const events = "events";
18
+ export {
19
+ container_number,
20
+ created_at,
21
+ deleted_at,
22
+ empty_ready_at,
23
+ error_history,
24
+ events,
25
+ holds_cleared_at,
26
+ id,
27
+ last_poll_at,
28
+ next_poll_at,
29
+ organization_id,
30
+ retry_count,
31
+ schedule,
32
+ status,
33
+ tenant_id,
34
+ terminal_code,
35
+ updated_at
36
+ };
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../generated/entities/terminal_tracking_job/index.ts"],
4
+ "sourcesContent": ["// AUTO-GENERATED by scripts/generate-entity-fields.mjs (HEDGE-168). Do not edit.\n//\n// One file per entity, named `toSnake(ClassName)` \u2014 NOT the table name. Each\n// export is a database column name, mirroring what `mercato generate` writes\n// for `@open-mercato/*` packages. `loadStandaloneGeneratedPackageEntities()`\n// reads these back to build the host app's `entity-fields-registry.ts`, which\n// is what the Encryption and Translation managers list fields from.\n//\n// Regenerate with `node scripts/generate-entity-fields.mjs --all`; the package\n// build does it for you. Guarded by\n// `apps/web/src/__tests__/entity-fields-registry-contract.test.ts`.\nexport const id = \"id\";\nexport const organization_id = \"organization_id\";\nexport const tenant_id = \"tenant_id\";\nexport const terminal_code = \"terminal_code\";\nexport const container_number = \"container_number\";\nexport const status = \"status\";\nexport const schedule = \"schedule\";\nexport const next_poll_at = \"next_poll_at\";\nexport const last_poll_at = \"last_poll_at\";\nexport const retry_count = \"retry_count\";\nexport const error_history = \"error_history\";\nexport const empty_ready_at = \"empty_ready_at\";\nexport const holds_cleared_at = \"holds_cleared_at\";\nexport const created_at = \"created_at\";\nexport const updated_at = \"updated_at\";\nexport const deleted_at = \"deleted_at\";\nexport const events = \"events\";\n"],
5
+ "mappings": "AAWO,MAAM,KAAK;AACX,MAAM,kBAAkB;AACxB,MAAM,YAAY;AAClB,MAAM,gBAAgB;AACtB,MAAM,mBAAmB;AACzB,MAAM,SAAS;AACf,MAAM,WAAW;AACjB,MAAM,eAAe;AACrB,MAAM,eAAe;AACrB,MAAM,cAAc;AACpB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,aAAa;AACnB,MAAM,aAAa;AACnB,MAAM,aAAa;AACnB,MAAM,SAAS;",
6
+ "names": []
7
+ }
@@ -0,0 +1,41 @@
1
+ const id = "id";
2
+ const organization_id = "organization_id";
3
+ const tenant_id = "tenant_id";
4
+ const terminal_code = "terminal_code";
5
+ const visit_ref = "visit_ref";
6
+ const vessel_name = "vessel_name";
7
+ const ib_voyage = "ib_voyage";
8
+ const ob_voyage = "ob_voyage";
9
+ const line = "line";
10
+ const phase = "phase";
11
+ const eta = "eta";
12
+ const etd = "etd";
13
+ const ata = "ata";
14
+ const atd = "atd";
15
+ const begin_receive = "begin_receive";
16
+ const dry_cutoff = "dry_cutoff";
17
+ const raw_data = "raw_data";
18
+ const created_at = "created_at";
19
+ const updated_at = "updated_at";
20
+ export {
21
+ ata,
22
+ atd,
23
+ begin_receive,
24
+ created_at,
25
+ dry_cutoff,
26
+ eta,
27
+ etd,
28
+ ib_voyage,
29
+ id,
30
+ line,
31
+ ob_voyage,
32
+ organization_id,
33
+ phase,
34
+ raw_data,
35
+ tenant_id,
36
+ terminal_code,
37
+ updated_at,
38
+ vessel_name,
39
+ visit_ref
40
+ };
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../generated/entities/terminal_vessel_visit/index.ts"],
4
+ "sourcesContent": ["// AUTO-GENERATED by scripts/generate-entity-fields.mjs (HEDGE-168). Do not edit.\n//\n// One file per entity, named `toSnake(ClassName)` \u2014 NOT the table name. Each\n// export is a database column name, mirroring what `mercato generate` writes\n// for `@open-mercato/*` packages. `loadStandaloneGeneratedPackageEntities()`\n// reads these back to build the host app's `entity-fields-registry.ts`, which\n// is what the Encryption and Translation managers list fields from.\n//\n// Regenerate with `node scripts/generate-entity-fields.mjs --all`; the package\n// build does it for you. Guarded by\n// `apps/web/src/__tests__/entity-fields-registry-contract.test.ts`.\nexport const id = \"id\";\nexport const organization_id = \"organization_id\";\nexport const tenant_id = \"tenant_id\";\nexport const terminal_code = \"terminal_code\";\nexport const visit_ref = \"visit_ref\";\nexport const vessel_name = \"vessel_name\";\nexport const ib_voyage = \"ib_voyage\";\nexport const ob_voyage = \"ob_voyage\";\nexport const line = \"line\";\nexport const phase = \"phase\";\nexport const eta = \"eta\";\nexport const etd = \"etd\";\nexport const ata = \"ata\";\nexport const atd = \"atd\";\nexport const begin_receive = \"begin_receive\";\nexport const dry_cutoff = \"dry_cutoff\";\nexport const raw_data = \"raw_data\";\nexport const created_at = \"created_at\";\nexport const updated_at = \"updated_at\";\n"],
5
+ "mappings": "AAWO,MAAM,KAAK;AACX,MAAM,kBAAkB;AACxB,MAAM,YAAY;AAClB,MAAM,gBAAgB;AACtB,MAAM,YAAY;AAClB,MAAM,cAAc;AACpB,MAAM,YAAY;AAClB,MAAM,YAAY;AAClB,MAAM,OAAO;AACb,MAAM,QAAQ;AACd,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,MAAM;AACZ,MAAM,gBAAgB;AACtB,MAAM,aAAa;AACnB,MAAM,WAAW;AACjB,MAAM,aAAa;AACnB,MAAM,aAAa;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ const M = {
2
+ terminal_tracking: "terminal_tracking"
3
+ };
4
+ const E = {
5
+ terminal_tracking: {
6
+ terminal_config: "terminal_tracking:terminal_config",
7
+ // HEDGE-164: `tracking_job` matches NO class in `data/entities.ts`. The
8
+ // real entity is `TerminalTrackingJob` -> `terminal_tracking_job`, added
9
+ // below; this key is a hand-written guess that has been reaching the host
10
+ // registry as a phantom id ever since. It is left in place rather than
11
+ // deleted because `ce.ts` registers a custom-entity record against
12
+ // `terminal_tracking:tracking_job`, and removing the id could orphan
13
+ // custom-field definitions already configured against it in a customer
14
+ // database. Removal needs a production check of `custom_field_def` /
15
+ // `custom_field_value` first and is tracked separately from this fix.
16
+ tracking_job: "terminal_tracking:tracking_job",
17
+ terminal_event: "terminal_tracking:terminal_event",
18
+ terminal_tracking_job: "terminal_tracking:terminal_tracking_job",
19
+ terminal_vessel_visit: "terminal_tracking:terminal_vessel_visit"
20
+ }
21
+ };
22
+ export {
23
+ E,
24
+ M
25
+ };
26
+ //# sourceMappingURL=entities.ids.generated.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../generated/entities.ids.generated.ts"],
4
+ "sourcesContent": ["// Entity ids for `@freighttech/terminal-tracking` \u2014 HAND-MAINTAINED and AUTHORITATIVE.\n//\n// This header used to say \"local typecheck stub\", owned at runtime by apps/web.\n// Both halves were false, and HEDGE-164 is what that cost. Nothing regenerates\n// this file \u2014 `yarn generate` rewrites `generated/` only for modules declared\n// `from: '@app'`. And it is not merely a typecheck aid: because\n// `@open-mercato/core` installs as a real directory rather than a workspace\n// symlink, `@open-mercato/cli` runs in STANDALONE mode, where\n// `loadStandaloneGeneratedPackageEntities()` reads THIS file as the package's\n// entity list and uses it INSTEAD of parsing `data/entities.ts`.\n//\n// An entity missing here is therefore missing from the host app's `E`, and `E`\n// is a runtime registry rather than a bag of types: it backs the custom-field\n// entity picker, query-index coverage and reindex, attachment assignment,\n// dashboard widget sources and encryption field resolution. The entity's table,\n// migrations and repositories keep working the whole time, which is why the\n// failure reads as \"the feature was never built\" instead of as an error.\n//\n// One key per exported class in `data/entities.ts`, keyed `toSnake(ClassName)`\n// with NO pluralisation \u2014 `InvoiceOrderLine` is `invoice_order_line`, never the\n// `tableName`. Namespaces for OTHER modules are typecheck-only; the generator\n// reads `E['<this module id>']` and ignores the rest.\n//\n// The mechanism in full, and the guard that fails the gate when this file and\n// `data/entities.ts` drift apart:\n// `apps/web/src/__tests__/entity-ids-registry-contract.test.ts`.\n\nexport const M = {\n terminal_tracking: 'terminal_tracking',\n} as const\n\nexport const E = {\n terminal_tracking: {\n terminal_config: 'terminal_tracking:terminal_config',\n // HEDGE-164: `tracking_job` matches NO class in `data/entities.ts`. The\n // real entity is `TerminalTrackingJob` -> `terminal_tracking_job`, added\n // below; this key is a hand-written guess that has been reaching the host\n // registry as a phantom id ever since. It is left in place rather than\n // deleted because `ce.ts` registers a custom-entity record against\n // `terminal_tracking:tracking_job`, and removing the id could orphan\n // custom-field definitions already configured against it in a customer\n // database. Removal needs a production check of `custom_field_def` /\n // `custom_field_value` first and is tracked separately from this fix.\n tracking_job: 'terminal_tracking:tracking_job',\n terminal_event: 'terminal_tracking:terminal_event',\n terminal_tracking_job: 'terminal_tracking:terminal_tracking_job',\n terminal_vessel_visit: 'terminal_tracking:terminal_vessel_visit',\n },\n} as const\n\nexport type KnownModuleId = keyof typeof M\nexport type KnownEntities = typeof E\n"],
5
+ "mappings": "AA2BO,MAAM,IAAI;AAAA,EACf,mBAAmB;AACrB;AAEO,MAAM,IAAI;AAAA,EACf,mBAAmB;AAAA,IACjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUjB,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,uBAAuB;AAAA,IACvB,uBAAuB;AAAA,EACzB;AACF;",
6
+ "names": []
7
+ }
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ import {
2
+ TerminalConfig,
3
+ TerminalTrackingJob,
4
+ TerminalEvent
5
+ } from "./modules/terminal_tracking/data/entities.js";
6
+ import { TerminalRegistry } from "./modules/terminal_tracking/services/terminalRegistry.js";
7
+ import { TerminalTrackingService } from "./modules/terminal_tracking/services/terminalTrackingService.js";
8
+ import { TerminalMatcherService } from "./modules/terminal_tracking/services/terminalMatcherService.js";
9
+ import { eventsConfig, emitTerminalTrackingEvent } from "./modules/terminal_tracking/events.js";
10
+ export {
11
+ TerminalConfig,
12
+ TerminalEvent,
13
+ TerminalMatcherService,
14
+ TerminalRegistry,
15
+ TerminalTrackingJob,
16
+ TerminalTrackingService,
17
+ emitTerminalTrackingEvent,
18
+ eventsConfig
19
+ };
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": ["/**\n * @freighttech/terminal-tracking\n *\n * Container terminal (Navis N4) tracking: per-terminal config, periodic\n * polling, container event emission, and terminal matching.\n */\n\n// Entities\nexport {\n TerminalConfig,\n TerminalTrackingJob,\n TerminalEvent,\n} from './modules/terminal_tracking/data/entities'\n\n// Types\nexport type {\n TerminalEventType,\n TerminalEventClassifierCode,\n TerminalEventSource,\n FacilityCodeProvider,\n TerminalModeOfTransport,\n TerminalAuthType,\n TerminalTrackingJobStatus,\n TerminalEndpoints,\n TerminalSealInfo,\n} from './modules/terminal_tracking/data/entities'\n\n// Adapter contract\nexport type {\n TerminalAdapter,\n TerminalFetchedEvent,\n TerminalFetchResult,\n TerminalAdapterTestResult,\n ResolvedTerminalConfig,\n} from './modules/terminal_tracking/lib/terminal-adapter'\n\n// Services\nexport { TerminalRegistry } from './modules/terminal_tracking/services/terminalRegistry'\nexport { TerminalTrackingService } from './modules/terminal_tracking/services/terminalTrackingService'\nexport { TerminalMatcherService } from './modules/terminal_tracking/services/terminalMatcherService'\n\n// Events\nexport { eventsConfig, emitTerminalTrackingEvent } from './modules/terminal_tracking/events'\nexport type { TerminalTrackingEventId } from './modules/terminal_tracking/events'\n"],
5
+ "mappings": "AAQA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAyBP,SAAS,wBAAwB;AACjC,SAAS,+BAA+B;AACxC,SAAS,8BAA8B;AAGvC,SAAS,cAAc,iCAAiC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ const features = [
2
+ { id: "terminal_tracking.terminal_configs.view", title: "View Terminal Configs", module: "terminal_tracking" },
3
+ { id: "terminal_tracking.terminal_configs.manage", title: "Manage Terminal Configs", module: "terminal_tracking" },
4
+ { id: "terminal_tracking.tracking_jobs.view", title: "View Terminal Tracking Jobs", module: "terminal_tracking" },
5
+ { id: "terminal_tracking.tracking_jobs.manage", title: "Manage Terminal Tracking Jobs", module: "terminal_tracking" },
6
+ { id: "terminal_tracking.events.view", title: "View Terminal Events", module: "terminal_tracking" },
7
+ { id: "terminal_tracking.settings.manage", title: "Manage Terminal Tracking Settings", module: "terminal_tracking" }
8
+ ];
9
+ var acl_default = features;
10
+ export {
11
+ acl_default as default,
12
+ features
13
+ };
14
+ //# sourceMappingURL=acl.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/terminal_tracking/acl.ts"],
4
+ "sourcesContent": ["export const features = [\n { id: 'terminal_tracking.terminal_configs.view', title: 'View Terminal Configs', module: 'terminal_tracking' },\n { id: 'terminal_tracking.terminal_configs.manage', title: 'Manage Terminal Configs', module: 'terminal_tracking' },\n { id: 'terminal_tracking.tracking_jobs.view', title: 'View Terminal Tracking Jobs', module: 'terminal_tracking' },\n { id: 'terminal_tracking.tracking_jobs.manage', title: 'Manage Terminal Tracking Jobs', module: 'terminal_tracking' },\n { id: 'terminal_tracking.events.view', title: 'View Terminal Events', module: 'terminal_tracking' },\n { id: 'terminal_tracking.settings.manage', title: 'Manage Terminal Tracking Settings', module: 'terminal_tracking' },\n]\n\nexport default features\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,EAAE,IAAI,2CAA2C,OAAO,yBAAyB,QAAQ,oBAAoB;AAAA,EAC7G,EAAE,IAAI,6CAA6C,OAAO,2BAA2B,QAAQ,oBAAoB;AAAA,EACjH,EAAE,IAAI,wCAAwC,OAAO,+BAA+B,QAAQ,oBAAoB;AAAA,EAChH,EAAE,IAAI,0CAA0C,OAAO,iCAAiC,QAAQ,oBAAoB;AAAA,EACpH,EAAE,IAAI,iCAAiC,OAAO,wBAAwB,QAAQ,oBAAoB;AAAA,EAClG,EAAE,IAAI,qCAAqC,OAAO,qCAAqC,QAAQ,oBAAoB;AACrH;AAEA,IAAO,cAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,27 @@
1
+ import {
2
+ createCrudOpenApiFactory,
3
+ createPagedListResponseSchema as createSharedPagedListResponseSchema,
4
+ defaultCreateResponseSchema as sharedDefaultCreateResponseSchema,
5
+ defaultOkResponseSchema as sharedDefaultOkResponseSchema
6
+ } from "@open-mercato/shared/lib/openapi/crud";
7
+ const defaultCreateResponseSchema = sharedDefaultCreateResponseSchema;
8
+ const defaultOkResponseSchema = sharedDefaultOkResponseSchema;
9
+ function createPagedListResponseSchema(itemSchema) {
10
+ return createSharedPagedListResponseSchema(itemSchema, { paginationMetaOptional: true });
11
+ }
12
+ const buildTerminalTrackingCrudOpenApi = createCrudOpenApiFactory({
13
+ defaultTag: "Terminal Tracking",
14
+ defaultCreateResponseSchema,
15
+ defaultOkResponseSchema,
16
+ makeListDescription: ({ pluralLower }) => `Returns a paginated collection of ${pluralLower} scoped to the authenticated organization.`
17
+ });
18
+ function createTerminalTrackingCrudOpenApi(options) {
19
+ return buildTerminalTrackingCrudOpenApi(options);
20
+ }
21
+ export {
22
+ createPagedListResponseSchema,
23
+ createTerminalTrackingCrudOpenApi,
24
+ defaultCreateResponseSchema,
25
+ defaultOkResponseSchema
26
+ };
27
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/terminal_tracking/api/openapi.ts"],
4
+ "sourcesContent": ["import { type ZodTypeAny } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport {\n createCrudOpenApiFactory,\n createPagedListResponseSchema as createSharedPagedListResponseSchema,\n defaultCreateResponseSchema as sharedDefaultCreateResponseSchema,\n defaultOkResponseSchema as sharedDefaultOkResponseSchema,\n type CrudOpenApiOptions,\n} from '@open-mercato/shared/lib/openapi/crud'\n\nexport const defaultCreateResponseSchema = sharedDefaultCreateResponseSchema\nexport const defaultOkResponseSchema = sharedDefaultOkResponseSchema\n\nexport function createPagedListResponseSchema(itemSchema: ZodTypeAny) {\n return createSharedPagedListResponseSchema(itemSchema, { paginationMetaOptional: true })\n}\n\nconst buildTerminalTrackingCrudOpenApi = createCrudOpenApiFactory({\n defaultTag: 'Terminal Tracking',\n defaultCreateResponseSchema,\n defaultOkResponseSchema,\n makeListDescription: ({ pluralLower }) =>\n `Returns a paginated collection of ${pluralLower} scoped to the authenticated organization.`,\n})\n\nexport function createTerminalTrackingCrudOpenApi(options: CrudOpenApiOptions): OpenApiRouteDoc {\n return buildTerminalTrackingCrudOpenApi(options)\n}\n"],
5
+ "mappings": "AAEA;AAAA,EACE;AAAA,EACA,iCAAiC;AAAA,EACjC,+BAA+B;AAAA,EAC/B,2BAA2B;AAAA,OAEtB;AAEA,MAAM,8BAA8B;AACpC,MAAM,0BAA0B;AAEhC,SAAS,8BAA8B,YAAwB;AACpE,SAAO,oCAAoC,YAAY,EAAE,wBAAwB,KAAK,CAAC;AACzF;AAEA,MAAM,mCAAmC,yBAAyB;AAAA,EAChE,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,qBAAqB,CAAC,EAAE,YAAY,MAClC,qCAAqC,WAAW;AACpD,CAAC;AAEM,SAAS,kCAAkC,SAA8C;AAC9F,SAAO,iCAAiC,OAAO;AACjD;",
6
+ "names": []
7
+ }