45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
import { shippingLanes } from "../data/shipping-lanes/shipping-lanes.js";
|
|
import { PortsLaneNotFoundError } from "../error-codes/error-codes.js";
|
|
import { recordLaneLookup } from "../otel/otel.js";
|
|
import type { LaneMode, ShippingLane } from "../types/port.types.js";
|
|
|
|
let laneIndex: Map<string, ShippingLane> | null = null;
|
|
|
|
function getIndex(): Map<string, ShippingLane> {
|
|
if (laneIndex === null) {
|
|
const map = new Map<string, ShippingLane>();
|
|
for (const lane of shippingLanes) map.set(lane.id, lane);
|
|
laneIndex = map;
|
|
}
|
|
return laneIndex;
|
|
}
|
|
|
|
/** Get a shipping lane by its ID, or `undefined` when no match exists. */
|
|
export function getShippingLane(id: string): ShippingLane | undefined {
|
|
const lane = getIndex().get(id);
|
|
recordLaneLookup(lane?.mode ?? "all");
|
|
return lane;
|
|
}
|
|
|
|
/** Strict variant; throws `PortsLaneNotFoundError` (`PORTS.LANE_NOT_FOUND`) on miss. */
|
|
export function getShippingLaneStrict(id: string): ShippingLane {
|
|
const lane = getShippingLane(id);
|
|
if (lane === undefined) throw new PortsLaneNotFoundError({ laneId: id });
|
|
return lane;
|
|
}
|
|
|
|
/** Filter shipping lanes by transport mode. */
|
|
export function getShippingLanesByMode(
|
|
mode: LaneMode,
|
|
lanes: readonly ShippingLane[] = shippingLanes
|
|
): ShippingLane[] {
|
|
recordLaneLookup(mode);
|
|
return lanes.filter((l) => l.mode === mode);
|
|
}
|
|
|
|
/** Get every shipping lane in the curated registry. */
|
|
export function getAllShippingLanes(): readonly ShippingLane[] {
|
|
recordLaneLookup("all");
|
|
return shippingLanes;
|
|
}
|