@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.
- package/LICENSE +21 -0
- package/README.md +121 -0
- package/dist/generated/entities/terminal_config/index.js +53 -0
- package/dist/generated/entities/terminal_config/index.js.map +7 -0
- package/dist/generated/entities/terminal_event/index.js +59 -0
- package/dist/generated/entities/terminal_event/index.js.map +7 -0
- package/dist/generated/entities/terminal_tracking_job/index.js +37 -0
- package/dist/generated/entities/terminal_tracking_job/index.js.map +7 -0
- package/dist/generated/entities/terminal_vessel_visit/index.js +41 -0
- package/dist/generated/entities/terminal_vessel_visit/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +26 -0
- package/dist/generated/entities.ids.generated.js.map +7 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +7 -0
- package/dist/modules/terminal_tracking/acl.js +14 -0
- package/dist/modules/terminal_tracking/acl.js.map +7 -0
- package/dist/modules/terminal_tracking/api/openapi.js +27 -0
- package/dist/modules/terminal_tracking/api/openapi.js.map +7 -0
- package/dist/modules/terminal_tracking/api/terminal-configs/route.js +140 -0
- package/dist/modules/terminal_tracking/api/terminal-configs/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/terminal-configs/test/route.js +58 -0
- package/dist/modules/terminal_tracking/api/terminal-configs/test/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/details/route.js +109 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/details/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/poll/route.js +58 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/poll/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/route.js +189 -0
- package/dist/modules/terminal_tracking/api/tracking-jobs/route.js.map +7 -0
- package/dist/modules/terminal_tracking/api/utils.js +12 -0
- package/dist/modules/terminal_tracking/api/utils.js.map +7 -0
- package/dist/modules/terminal_tracking/api/vessel-visits/route.js +83 -0
- package/dist/modules/terminal_tracking/api/vessel-visits/route.js.map +7 -0
- package/dist/modules/terminal_tracking/backend/terminal-configs/page.js +669 -0
- package/dist/modules/terminal_tracking/backend/terminal-configs/page.js.map +7 -0
- package/dist/modules/terminal_tracking/backend/terminal-configs/page.meta.js +19 -0
- package/dist/modules/terminal_tracking/backend/terminal-configs/page.meta.js.map +7 -0
- package/dist/modules/terminal_tracking/backend/terminal-containers/page.js +275 -0
- package/dist/modules/terminal_tracking/backend/terminal-containers/page.js.map +7 -0
- package/dist/modules/terminal_tracking/backend/terminal-containers/page.meta.js +19 -0
- package/dist/modules/terminal_tracking/backend/terminal-containers/page.meta.js.map +7 -0
- package/dist/modules/terminal_tracking/ce.js +35 -0
- package/dist/modules/terminal_tracking/ce.js.map +7 -0
- package/dist/modules/terminal_tracking/commands/index.js +4 -0
- package/dist/modules/terminal_tracking/commands/index.js.map +7 -0
- package/dist/modules/terminal_tracking/commands/terminal-configs.js +107 -0
- package/dist/modules/terminal_tracking/commands/terminal-configs.js.map +7 -0
- package/dist/modules/terminal_tracking/commands/terminal-tracking.js +27 -0
- package/dist/modules/terminal_tracking/commands/terminal-tracking.js.map +7 -0
- package/dist/modules/terminal_tracking/commands/tracking-jobs.js +56 -0
- package/dist/modules/terminal_tracking/commands/tracking-jobs.js.map +7 -0
- package/dist/modules/terminal_tracking/components/ContainerDetailsDrawer.js +371 -0
- package/dist/modules/terminal_tracking/components/ContainerDetailsDrawer.js.map +7 -0
- package/dist/modules/terminal_tracking/data/entities.js +337 -0
- package/dist/modules/terminal_tracking/data/entities.js.map +7 -0
- package/dist/modules/terminal_tracking/data/validators.js +98 -0
- package/dist/modules/terminal_tracking/data/validators.js.map +7 -0
- package/dist/modules/terminal_tracking/di.js +39 -0
- package/dist/modules/terminal_tracking/di.js.map +7 -0
- package/dist/modules/terminal_tracking/encryption.js +14 -0
- package/dist/modules/terminal_tracking/encryption.js.map +7 -0
- package/dist/modules/terminal_tracking/events.js +45 -0
- package/dist/modules/terminal_tracking/events.js.map +7 -0
- package/dist/modules/terminal_tracking/i18n/de.json +175 -0
- package/dist/modules/terminal_tracking/i18n/en.json +178 -0
- package/dist/modules/terminal_tracking/i18n/es.json +175 -0
- package/dist/modules/terminal_tracking/i18n/pl.json +206 -0
- package/dist/modules/terminal_tracking/index.js +15 -0
- package/dist/modules/terminal_tracking/index.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/adapter.js +164 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/adapter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/auth/basic.js +23 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/auth/basic.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/incos-semantics.js +146 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/incos-semantics.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/types.js +1 -0
- package/dist/modules/terminal_tracking/lib/adapters/bct/types.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/adapter.js +106 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/adapter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/auth/token.js +120 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/auth/token.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/gct-semantics.js +77 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/gct-semantics.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/types.js +1 -0
- package/dist/modules/terminal_tracking/lib/adapters/gct/types.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/index.js +12 -0
- package/dist/modules/terminal_tracking/lib/adapters/index.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/adapter.js +121 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/adapter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/auth/ropc.js +81 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/auth/ropc.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/http.js +66 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/http.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/n4-semantics.js +95 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/n4-semantics.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/data-table.js +70 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/data-table.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/vessel-data-table.js +44 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/parsers/vessel-data-table.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/proxy.js +15 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/proxy.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/types.js +1 -0
- package/dist/modules/terminal_tracking/lib/adapters/n4/types.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/adapters/zoned-time.js +27 -0
- package/dist/modules/terminal_tracking/lib/adapters/zoned-time.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/availability.js +40 -0
- package/dist/modules/terminal_tracking/lib/availability.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/ensure-schedule.js +51 -0
- package/dist/modules/terminal_tracking/lib/ensure-schedule.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/holds.js +240 -0
- package/dist/modules/terminal_tracking/lib/holds.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/logger.js +19 -0
- package/dist/modules/terminal_tracking/lib/logger.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/rate-limiter.js +30 -0
- package/dist/modules/terminal_tracking/lib/rate-limiter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/stops.js +48 -0
- package/dist/modules/terminal_tracking/lib/stops.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/terminal-adapter.js +1 -0
- package/dist/modules/terminal_tracking/lib/terminal-adapter.js.map +7 -0
- package/dist/modules/terminal_tracking/lib/totp.js +41 -0
- package/dist/modules/terminal_tracking/lib/totp.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260609120000_terminal_tracking.js +101 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260609120000_terminal_tracking.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260610120000_terminal_vessel_visits.js +39 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260610120000_terminal_vessel_visits.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260611120000_terminal_config_proxy.js +13 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260611120000_terminal_config_proxy.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260707120000_terminal_job_availability_markers.js +15 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260707120000_terminal_job_availability_markers.js.map +7 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260805120000_terminal_event_loaded_at.js +13 -0
- package/dist/modules/terminal_tracking/migrations/Migration20260805120000_terminal_event_loaded_at.js.map +7 -0
- package/dist/modules/terminal_tracking/services/terminalMatcherService.js +61 -0
- package/dist/modules/terminal_tracking/services/terminalMatcherService.js.map +7 -0
- package/dist/modules/terminal_tracking/services/terminalRegistry.js +24 -0
- package/dist/modules/terminal_tracking/services/terminalRegistry.js.map +7 -0
- package/dist/modules/terminal_tracking/services/terminalTrackingService.js +687 -0
- package/dist/modules/terminal_tracking/services/terminalTrackingService.js.map +7 -0
- package/dist/modules/terminal_tracking/setup.js +23 -0
- package/dist/modules/terminal_tracking/setup.js.map +7 -0
- package/dist/modules/terminal_tracking/subscribers/terminal-tracking-job-initial-poll.js +22 -0
- package/dist/modules/terminal_tracking/subscribers/terminal-tracking-job-initial-poll.js.map +7 -0
- package/generated/entities/terminal_config/index.ts +36 -0
- package/generated/entities/terminal_event/index.ts +39 -0
- package/generated/entities/terminal_tracking_job/index.ts +28 -0
- package/generated/entities/terminal_vessel_visit/index.ts +30 -0
- package/generated/entities.ids.generated.ts +52 -0
- package/package.json +80 -0
- package/src/index.ts +44 -0
- package/src/modules/terminal_tracking/__integration__/TC-TRACK-301-gct-config-test-connection.spec.ts +66 -0
- package/src/modules/terminal_tracking/__integration__/TC-TRACK-317-bct-config-test-connection.spec.ts +68 -0
- package/src/modules/terminal_tracking/__integration__/helpers.ts +148 -0
- package/src/modules/terminal_tracking/__integration__/meta.ts +4 -0
- package/src/modules/terminal_tracking/acl.ts +10 -0
- package/src/modules/terminal_tracking/api/openapi.ts +28 -0
- package/src/modules/terminal_tracking/api/terminal-configs/route.ts +140 -0
- package/src/modules/terminal_tracking/api/terminal-configs/test/route.ts +64 -0
- package/src/modules/terminal_tracking/api/tracking-jobs/details/route.ts +116 -0
- package/src/modules/terminal_tracking/api/tracking-jobs/poll/route.ts +64 -0
- package/src/modules/terminal_tracking/api/tracking-jobs/route.ts +243 -0
- package/src/modules/terminal_tracking/api/utils.ts +10 -0
- package/src/modules/terminal_tracking/api/vessel-visits/route.ts +95 -0
- package/src/modules/terminal_tracking/backend/terminal-configs/page.meta.ts +16 -0
- package/src/modules/terminal_tracking/backend/terminal-configs/page.tsx +728 -0
- package/src/modules/terminal_tracking/backend/terminal-containers/page.meta.ts +16 -0
- package/src/modules/terminal_tracking/backend/terminal-containers/page.tsx +328 -0
- package/src/modules/terminal_tracking/ce.ts +31 -0
- package/src/modules/terminal_tracking/commands/index.ts +3 -0
- package/src/modules/terminal_tracking/commands/terminal-configs.ts +132 -0
- package/src/modules/terminal_tracking/commands/terminal-tracking.ts +34 -0
- package/src/modules/terminal_tracking/commands/tracking-jobs.ts +69 -0
- package/src/modules/terminal_tracking/components/ContainerDetailsDrawer.tsx +540 -0
- package/src/modules/terminal_tracking/data/entities.ts +386 -0
- package/src/modules/terminal_tracking/data/validators.ts +113 -0
- package/src/modules/terminal_tracking/di.ts +46 -0
- package/src/modules/terminal_tracking/encryption.ts +12 -0
- package/src/modules/terminal_tracking/events.ts +48 -0
- package/src/modules/terminal_tracking/i18n/de.json +175 -0
- package/src/modules/terminal_tracking/i18n/en.json +178 -0
- package/src/modules/terminal_tracking/i18n/es.json +175 -0
- package/src/modules/terminal_tracking/i18n/pl.json +206 -0
- package/src/modules/terminal_tracking/index.ts +13 -0
- package/src/modules/terminal_tracking/lib/__tests__/availability.test.ts +136 -0
- package/src/modules/terminal_tracking/lib/__tests__/ensure-schedule.test.ts +67 -0
- package/src/modules/terminal_tracking/lib/__tests__/holds.test.ts +73 -0
- package/src/modules/terminal_tracking/lib/__tests__/stops.test.ts +80 -0
- package/src/modules/terminal_tracking/lib/__tests__/totp.test.ts +38 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/__tests__/adapter.test.ts +196 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/__tests__/incos-semantics.test.ts +303 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/adapter.ts +219 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/auth/basic.ts +34 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/incos-semantics.ts +291 -0
- package/src/modules/terminal_tracking/lib/adapters/bct/types.ts +113 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/__tests__/adapter.test.ts +238 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/__tests__/gct-semantics.test.ts +133 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/adapter.ts +152 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/auth/token.ts +219 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/gct-semantics.ts +136 -0
- package/src/modules/terminal_tracking/lib/adapters/gct/types.ts +58 -0
- package/src/modules/terminal_tracking/lib/adapters/index.ts +16 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/adapter-proxy.test.ts +69 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/data-table.test.ts +179 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/http.test.ts +98 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/n4-semantics.test.ts +140 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/proxy.test.ts +19 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/__tests__/vessel-data-table.test.ts +67 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/adapter.ts +163 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/auth/ropc.ts +104 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/http.ts +127 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/n4-semantics.ts +156 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/parsers/data-table.ts +102 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/parsers/vessel-data-table.ts +60 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/proxy.ts +24 -0
- package/src/modules/terminal_tracking/lib/adapters/n4/types.ts +56 -0
- package/src/modules/terminal_tracking/lib/adapters/zoned-time.ts +65 -0
- package/src/modules/terminal_tracking/lib/availability.ts +119 -0
- package/src/modules/terminal_tracking/lib/ensure-schedule.ts +83 -0
- package/src/modules/terminal_tracking/lib/holds.ts +344 -0
- package/src/modules/terminal_tracking/lib/logger.ts +21 -0
- package/src/modules/terminal_tracking/lib/rate-limiter.ts +52 -0
- package/src/modules/terminal_tracking/lib/stops.ts +124 -0
- package/src/modules/terminal_tracking/lib/terminal-adapter.ts +136 -0
- package/src/modules/terminal_tracking/lib/totp.ts +63 -0
- package/src/modules/terminal_tracking/migrations/Migration20260609120000_terminal_tracking.ts +104 -0
- package/src/modules/terminal_tracking/migrations/Migration20260610120000_terminal_vessel_visits.ts +40 -0
- package/src/modules/terminal_tracking/migrations/Migration20260611120000_terminal_config_proxy.ts +11 -0
- package/src/modules/terminal_tracking/migrations/Migration20260707120000_terminal_job_availability_markers.ts +13 -0
- package/src/modules/terminal_tracking/migrations/Migration20260805120000_terminal_event_loaded_at.ts +16 -0
- package/src/modules/terminal_tracking/services/__tests__/availabilityEmit.test.ts +277 -0
- package/src/modules/terminal_tracking/services/__tests__/createJob.test.ts +59 -0
- package/src/modules/terminal_tracking/services/__tests__/pollAllBatch.test.ts +147 -0
- package/src/modules/terminal_tracking/services/__tests__/terminalMatcher.test.ts +70 -0
- package/src/modules/terminal_tracking/services/__tests__/vesselResolution.test.ts +453 -0
- package/src/modules/terminal_tracking/services/terminalMatcherService.ts +97 -0
- package/src/modules/terminal_tracking/services/terminalRegistry.ts +30 -0
- package/src/modules/terminal_tracking/services/terminalTrackingService.ts +912 -0
- package/src/modules/terminal_tracking/setup.ts +24 -0
- 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
|
+
}
|