fifteen/apps/web/lib/valhalla.ts

58 lines
1.6 KiB
TypeScript

const VALHALLA_BASE = process.env.VALHALLA_URL ?? "http://valhalla:8002";
export type ValhallaCosting = "pedestrian" | "bicycle" | "auto";
const COSTING_MAP: Record<string, ValhallaCosting> = {
walking: "pedestrian",
cycling: "bicycle",
driving: "auto",
};
export interface IsochroneOpts {
lng: number;
lat: number;
travelMode: string;
contourMinutes: number[];
polygons?: boolean;
}
export async function fetchIsochrone(opts: IsochroneOpts): Promise<object> {
const isTransit = opts.travelMode === "transit";
const costing = isTransit ? "multimodal" : (COSTING_MAP[opts.travelMode] ?? "pedestrian");
const body: Record<string, unknown> = {
locations: [{ lon: opts.lng, lat: opts.lat }],
costing,
contours: opts.contourMinutes.map((time) => ({ time })),
polygons: opts.polygons ?? true,
show_locations: false,
};
if (isTransit) {
body.costing_options = { transit: { use_bus: 1.0, use_rail: 1.0, use_transfers: 1.0 } };
body.date_time = { type: 0 }; // current time
}
const res = await fetch(`${VALHALLA_BASE}/isochrone`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
signal: AbortSignal.timeout(30_000),
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Valhalla error ${res.status}: ${text}`);
}
return res.json();
}
export async function checkValhalla(): Promise<boolean> {
try {
const res = await fetch(`${VALHALLA_BASE}/status`, {
signal: AbortSignal.timeout(3000),
});
return res.ok;
} catch {
return false;
}
}