# Core & API Client Reference This document provides a detailed reference for the internal packages: `@timetoleave/core` and `@timetoleave/api-client`. ## 📦 `@timetoleave/core` The core package contains all domain types, status calculation logic, HAFAS time parsing, and formatting utilities. It has zero runtime dependencies outside of the standard library. ### Types (`types.ts`) | Interface | Description | | :--- | :--- | | `Event` | Represents a calendar event with an assigned destination and event time. | | `CalendarEvent` | Raw calendar event data (typically `string` dates before conversion to `Event`). | | `Station` | A transport station with a name, HAFAS `extId`, and optional coordinates. | | `Journey` | A public transport connection including scheduled/real departure/arrival, delay, platform, and cancellation status. | | `BikeRoute` / `WalkRoute` | Routing data including total distance, duration, and step-by-step instructions. | | `CountdownInfo` | Output of the countdown utility containing a label, color code, and urgency flag. | | `ReminderSettings` | User preferences for buffers, walking/bike options, and reminder toggles. | | `WienerLinienDeparture` | Specific types for WienerLinien (Vienna public transport) monitor responses. | ### HAFAS Time Utilities (`hafas-time.ts`) HAFAS timestamps are strictly tied to the `Europe/Vienna` timezone (CET/CEST). These utilities handle the bi-directional conversion between UTC JavaScript `Date` objects and HAFAS strings, correctly handling Daylight Saving Time (DST) transitions. ```typescript import { parseHafasTime, hafasDateTime } from '@timetoleave/core'; // Parse HAFAS date ("YYYYMMDD") and time ("HHMMSS") into a UTC Date object const dateObj = parseHafasTime("20231027", "143000"); // Convert a UTC Date object back to HAFAS date and time strings const { date, time } = hafasDateTime(dateObj); // Returns: { date: "20231027", time: "143000" } ``` > **Note:** `getTimezoneOffsetMinutes` is designed exclusively for full-hour offsets like `Europe/Vienna`. It will produce incorrect results for fractional timezones (e.g., India +05:30). ### Countdown & Status Utilities #### `calculateCountdown(targetDate: Date): CountdownInfo` Calculates the time delta between `now` and `targetDate`, returning a human-readable label, a color code, and an urgency boolean. | Time Delta | Label | Color | Urgent | | :--- | :--- | :--- | :--- | | `<= 0 min` | `Now` | `red` | `true` | | `<= 10 min` | `[X]min` | `orange` | `true` | | `<= 30 min` | `[X]min` | `yellow` | `false` | | `<= 60 min` | `[X]min` | `green` | `false` | | `> 60 min` | `[X]h [Y]min` | `blue` | `false` | #### `getLeaveStatus(event: Event, journeys: Journey[]): string` Derives a human-readable leave-by status by finding the earliest non-cancelled journey and comparing its real departure time (`rD`) against the current time. **Possible Returns:** - `"No journey data"` - `"All journeys cancelled"` - `"Departure missed"` (if `rD` is in the past) - `"Delayed +[X] min"` (if delay exceeds 10 minutes) - `"Leave now"` (if departure is within 15 minutes) - `"On time"` ### Formatting Utilities (`formatting.ts`) All formatting functions default to the `de-AT` locale to match the primary target region. - `formatTime(date: Date)` -> `"14:30"` - `formatDate(date: Date)` -> `"Mi., 27. Oktober 2023"` - `formatDateTime(date: Date)` -> `"27. Oktober 2023, 14:30"` - `formatDuration(seconds: number)` -> `"1h 23min"` or `"45min"` - `formatDistance(meters: number)` -> `"1.2km"` or `"800m"` --- ## 🌐 `@timetoleave/api-client` The API client is a lightweight wrapper around the Web App's Next.js API routes. It handles URL construction, query parameters, and JSON serialization. ### Initialization ```typescript import { ApiClient } from '@timetoleave/api-client'; // Initialize with the base URL of the backend proxy const api = new ApiClient('http://localhost:3000'); ``` ### Methods #### `getHealth()` ```typescript getHealth(): Promise<{ status: 'ok'; uptime: number }> ``` Checks the `/api/health` endpoint to verify backend availability. #### `geocode(name: string, countrycodes?: string)` ```typescript geocode(name: string, countrycodes?: string): Promise ``` Performs forward geocoding via `/api/geocode`. #### `reverseGeocode(lat: number, lng: number)` ```typescript reverseGeocode(lat: number, lng: number): Promise ``` Performs reverse geocoding via `/api/geocode/reverse`. #### `fetchCalendar(url: string, days?: number)` ```typescript fetchCalendar(url: string, days?: number): Promise ``` Fetches and parses a remote `.ics` file via `/api/calendar`. The optional `days` parameter limits the fetch to upcoming events. #### `parseCalendarIcs(content: string)` ```typescript parseCalendarIcs(content: string): Promise ``` Parses raw `.ics` string content via `/api/calendar/parse`. #### `searchStation(query: string)` ```typescript searchStation(query: string): Promise ``` Searches for stations by name using the HAFAS `LocMatch` method. Returns up to 5 matches with valid `extId`s. #### `searchJourneys(fromStationExtId: string, toStationExtId: string, date: Date)` ```typescript searchJourneys(from: string, to: string, date: Date): Promise ``` Sends a HAFAS `TripSearch` request to find public transport connections between two stations. It automatically converts the `Date` to HAFAS-compatible strings. #### `getBikeRoute(fromLat, fromLng, toLat, toLng)` & `getWalkRoute(fromLat, fromLng, toLat, toLng)` ```typescript getBikeRoute(...): Promise getWalkRoute(...): Promise ``` Retrieves routing data for the "first mile / last mile" segment (e.g., biking from home to the train station). #### `findNearbyStops(lat: number, lng: number, radius?: number)` ```typescript findNearbyStops(lat: number, lng: number, radius: number = 1000): Promise ``` Finds public transport stops within a specific radius using the WienerLinien API (`/api/wienerlinien/stops`). #### `hafasRequest(body: unknown)` ```typescript hafasRequest(body: unknown): Promise ``` A generic method to send arbitrary HAFAS protocol bodies to `/api/hafas`. Useful for advanced use-cases not covered by the wrapper methods.