Add JSDoc documentation to all TypeScript files

This commit is contained in:
2026-05-14 13:53:12 +02:00
parent 09b5e7725d
commit 498958a27c
86 changed files with 728 additions and 16 deletions
+10 -1
View File
@@ -1,6 +1,15 @@
// Countdown utilities for TimeToLeave
import { CountdownInfo } from "./types";
/**
* Determine the countdown label, color and urgency for a target time.
*
* Thresholds (minutes until target):
* - 0 → red, "Now"
* - ≤10 → orange (urgent)
* - ≤30 → yellow
* - ≤60 → green
* - >60 → blue ("Xh Ymin")
*/
export function calculateCountdown(targetDate: Date): CountdownInfo {
const now = new Date();
const diffMs = targetDate.getTime() - now.getTime();
+5
View File
@@ -1,3 +1,7 @@
// ── Defaults ──
// Fallback origin station (Mödling, Austria) used when geolocation is
// unavailable or the user hasn't set a custom origin.
import type { Station } from "./types";
export const DEFAULT_ORIGIN_ADDRESS = "Goethegasse 36, 2340 Moedling";
@@ -6,6 +10,7 @@ export const DEFAULT_ORIGIN_LNG = 16.2908052;
export const DEFAULT_ORIGIN_STATION_NAME = "Mödling Bahnhof";
export const DEFAULT_ORIGIN_STATION_EXT_ID = "1231701";
/** Pre-assembled default station object for convenience. */
export const DEFAULT_ORIGIN_STATION: Station = {
name: DEFAULT_ORIGIN_ADDRESS,
extId: DEFAULT_ORIGIN_STATION_EXT_ID,
+7 -1
View File
@@ -1,9 +1,12 @@
// Formatting utilities for TimeToLeave
// ── Formatting utilities ──
// All formatters use Austrian locale (de-AT) for consistency with the target market.
/** Format a Date as a 24h clock time string (HH:mm). */
export function formatTime(date: Date): string {
return date.toLocaleTimeString("de-AT", { hour: "2-digit", minute: "2-digit" });
}
/** Format a Date as a localized date string (weekday, day, month, year). */
export function formatDate(date: Date): string {
return date.toLocaleDateString("de-AT", {
weekday: "short",
@@ -13,6 +16,7 @@ export function formatDate(date: Date): string {
});
}
/** Format a Date as a full date+time string for display. */
export function formatDateTime(date: Date): string {
return date.toLocaleString("de-AT", {
day: "numeric",
@@ -23,6 +27,7 @@ export function formatDateTime(date: Date): string {
});
}
/** Convert seconds to a human-readable duration (e.g. "1h 30min"). */
export function formatDuration(seconds: number): string {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
@@ -33,6 +38,7 @@ export function formatDuration(seconds: number): string {
return `${minutes}min`;
}
/** Convert meters to a human-readable distance (meters or km). */
export function formatDistance(meters: number): string {
if (meters < 1000) {
return `${meters}m`;
+16
View File
@@ -1,9 +1,25 @@
// ── HAFAS Response Parser ──
// Transforms raw HAFAS protocol JSON into clean `Journey` objects.
// HAFAS encodes times relative to a date boundary (day wraps at 00:00),
// so the caller must provide the original query date for correct parsing.
import type { Journey } from "./types";
import { parseHafasTime } from "./hafas-time";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type RawJson = any;
/**
* Parse the `outConL` array from a HAFAS TripSearch response into Journey objects.
*
* Each connection (`con`) contains a list of sections (`secL`). The first section's
* departure and the last section's arrival define the journey boundaries. Train names
* are extracted from the first stop of each train leg.
*
* @param json - Raw HAFAS response body
* @param hafasDate - The HAFAS date string ("YYYYMMDD") used for the query
* @param queryDate - The original JavaScript Date used for the query (fallback for missing times)
*/
export function parseHafasJourneys(json: RawJson, hafasDate: string, queryDate: Date): Journey[] {
const outConL: RawJson[] = json?.svcResL?.[0]?.res?.outConL ?? [];
+3 -1
View File
@@ -1,4 +1,6 @@
// Re-export everything for clean imports
// ── Re-exports ──
// Barrel file: import everything from `@timetoleave/core` in one go.
export * from './types';
export * from './countdown-utils';
export * from './formatting';
+2 -1
View File
@@ -1,6 +1,7 @@
// Status utilities for TimeToLeave
// ── Status utilities ──
import type { ServerStatus, Event, Journey } from "./types";
/** Utility class for server health checks. */
export class StatusUtils {
static async checkServerStatus(url: string): Promise<ServerStatus> {
try {
+21 -2
View File
@@ -1,5 +1,6 @@
// Core domain types
// Core domain types for TimeToLeave
/** Event stored in the application (eventTime as Date). */
export interface Event {
id: string;
title: string;
@@ -8,6 +9,7 @@ export interface Event {
source: string;
}
/** Calendar event from an ICS feed (eventTime as ISO string for serialization). */
export interface CalendarEvent {
id: string;
title: string;
@@ -16,6 +18,7 @@ export interface CalendarEvent {
source: string;
}
/** HAFAS station with optional GPS coordinates. */
export interface Station {
name: string;
extId: string;
@@ -23,6 +26,7 @@ export interface Station {
lng?: number;
}
/** A single transit journey with schedule vs. real-time data. */
export interface Journey {
id: string;
sD: Date; // scheduled departure
@@ -36,6 +40,7 @@ export interface Journey {
cancelled: boolean;
}
/** Bike routing step from OSRM. */
export interface BikeStep {
name: string;
distance: number;
@@ -43,18 +48,21 @@ export interface BikeStep {
instruction: string;
}
/** Complete bike route with step-by-step directions. */
export interface BikeRoute {
distance: number;
duration: number;
steps: BikeStep[];
}
/** Walking route from OSRM with turn-by-turn steps. */
export interface WalkRoute {
distance: number;
duration: number;
steps: WalkStep[];
}
/** Walking step from OSRM route data. */
export interface WalkStep {
name: string;
distance: number;
@@ -62,17 +70,21 @@ export interface WalkStep {
instruction: string;
}
/** Countdown display info derived from the time remaining until an event. */
export interface CountdownInfo {
label: string;
color: string;
urgent: boolean;
}
/** Geolocation permission state. */
export type LocState = "pending" | "granted" | "denied";
/** Calendar sync status. */
export type CalStatus = null | "loading" | "ok" | "error";
// ── Reminder Settings ──────────────────────────────────
/** Persistent reminder preferences stored in localStorage. */
export interface ReminderSettings {
bufferMinutes: number;
enabled: boolean;
@@ -81,21 +93,25 @@ export interface ReminderSettings {
showBikeOption: boolean; // show bike route section (default true)
}
/** Server health check result. */
export type ServerStatus = boolean | null;
/** Result from Nominatim geocoding. */
export interface GeocodeResult {
lat: number;
lng: number;
display_name: string;
}
// WienerLinien types
// ── WienerLinien (Vienna public transport) types ──
/** A WienerLinien vehicle line. */
export interface WienerLinienLine {
name: string;
type?: string;
}
/** A WienerLinien stop with GPS coordinates. */
export interface WienerLinienStop {
id: string;
name: string;
@@ -103,6 +119,7 @@ export interface WienerLinienStop {
lng: number;
}
/** Departure from a WienerLinien stop. */
export interface WienerLinienDeparture {
stopId: string;
line: WienerLinienLine;
@@ -111,6 +128,7 @@ export interface WienerLinienDeparture {
delay?: number;
}
/** Response from the WienerLinien monitor endpoint. */
export interface WienerLinienMonitorResponse {
stops: {
stopId: string;
@@ -118,6 +136,7 @@ export interface WienerLinienMonitorResponse {
}[];
}
/** Stop found nearby the user's location. */
export interface NearbyStop {
id: string;
name: string;