From f6be6244abe1a1f1e2861e627b26dfce4711cee9 Mon Sep 17 00:00:00 2001 From: 7222e800-c703-472d-a787-71b6b5cba4ef Date: Sun, 14 Sep 2025 17:22:46 +0000 Subject: feat: more types --- src/lib/motis-types.ts | 440 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 410 insertions(+), 30 deletions(-) (limited to 'src/lib') diff --git a/src/lib/motis-types.ts b/src/lib/motis-types.ts index 2f05229..e62746f 100644 --- a/src/lib/motis-types.ts +++ b/src/lib/motis-types.ts @@ -169,79 +169,71 @@ export type Alert = { cause?: AlertCause; /** - * * Description of the cause of the alert that allows for agency-specific language; + * Description of the cause of the alert that allows for agency-specific language; * more specific than the Cause. - * */ causeDetail?: string; effect?: AlertEffect; /** - * * Description of the effect of the alert that allows for agency-specific language; + * Description of the effect of the alert that allows for agency-specific language; * more specific than the Effect. - * */ effectDetail?: string; /** - * * The URL which provides additional information about the alert. + * The URL which provides additional information about the alert. */ url?: string; /** - * * Header for the alert. This plain-text string will be highlighted, for example in boldface. - * + * Header for the alert. This plain-text string will be highlighted, for example in boldface. */ headerText: string; /** - * * Description for the alert. + * Description for the alert. * This plain-text string will be formatted as the body of the alert (or shown on an explicit "expand" request by the user). * The information in the description should add to the information of the header. - * */ descriptionText: string; /** - * * Text containing the alert's header to be used for text-to-speech implementations. + * Text containing the alert's header to be used for text-to-speech implementations. * This field is the text-to-speech version of header_text. * It should contain the same information as headerText but formatted such that it can read as text-to-speech * (for example, abbreviations removed, numbers spelled out, etc.) - * */ ttsHeaderText?: string; /** - * * Text containing a description for the alert to be used for text-to-speech implementations. + * Text containing a description for the alert to be used for text-to-speech implementations. * This field is the text-to-speech version of description_text. * It should contain the same information as description_text but formatted such that it can be read as text-to-speech * (for example, abbreviations removed, numbers spelled out, etc.) - * */ ttsDescriptionText?: string; /** - * * Severity of the alert. + * Severity of the alert. */ severityLevel?: AlertSeverityLevel; /** - * * String containing an URL linking to an image. + * String containing an URL linking to an image. */ imageUrl?: string; /** - * * IANA media type as to specify the type of image to be displayed. The type must start with "image/" - * + * IANA media type as to specify the type of image to be displayed. The type must start with "image/" */ imageMediaType?: string; /** - * * Text describing the appearance of the linked image in the image field + * Text describing the appearance of the linked image in the image field * (e.g., in case the image can't be displayed or the user can't see the image for accessibility reasons). * See the HTML spec for alt image text. - * */ imageAlternativeText?: string; }; @@ -300,7 +292,6 @@ export type Place = { /** * The current track/platform information, updated with real-time updates if available. * Can be missing if neither real-time updates nor the schedule timetable contains track information. - * */ track?: string; @@ -370,7 +361,6 @@ export type StopTime = { /** * For transit legs, the headsign of the bus or train being used. * For non-transit legs, null - * */ headsign: string; agencyId: string; @@ -409,13 +399,11 @@ export type StoptimesResponse = { /** * Use the cursor to get the previous page of results. Insert the cursor into the request and post it to get the previous page. * The previous page is a set of stop times BEFORE the first stop time in the result. - * */ previousPageCursor: string; /** * Use the cursor to get the next page of results. Insert the cursor into the request and post it to get the next page. * The next page is a set of stop times AFTER the last stop time in this result. - * */ nextPageCursor: string; }; @@ -426,7 +414,6 @@ export type StoptimesResponse = { // * // * - `arriveBy=true`: the parameters `date` and `time` refer to the arrival time // * - `arriveBy=false`: the parameters `date` and `time` refer to the departure time -// * // */ // arriveBy?: boolean; // /** @@ -439,7 +426,6 @@ export type StoptimesResponse = { // * The response will contain the next `n` arrivals / departures // * in case `EARLIER` is selected and the previous `n` // * arrivals / departures if `LATER` is selected. -// * // */ // direction?: 'EARLIER' | 'LATER'; // /** @@ -447,14 +433,12 @@ export type StoptimesResponse = { // * // * If set to `true`, only stations that are phyiscally in the radius are considered. // * If set to `false`, additionally to the stations in the radius, equivalences with the same name and children are considered. -// * // */ // exactRadius?: boolean; // /** // * Optional. Default is all transit modes. // * // * Only return arrivals/departures of the given modes. -// * // */ // mode?: Array; // /** @@ -465,7 +449,6 @@ export type StoptimesResponse = { // * Use the cursor to go to the next "page" of stop times. // * Copy the cursor from the last response and keep the original request as is. // * This will enable you to search for stop times in the next or previous time-window. -// * // */ // pageCursor?: string; // /** @@ -476,7 +459,6 @@ export type StoptimesResponse = { // * // * If set, all stops at parent stations and their child stops in the specified radius // * are returned. -// * // */ // radius?: number; // /** @@ -485,7 +467,6 @@ export type StoptimesResponse = { // stopId: string; // /** // * Optional. Defaults to the current time. -// * // */ // time?: string; // /** @@ -494,3 +475,402 @@ export type StoptimesResponse = { // withScheduledSkippedStops?: boolean; // }; // }; + +// TODO: Enum +export type Direction = + | 'DEPART' + | 'HARD_LEFT' + | 'LEFT' + | 'SLIGHTLY_LEFT' + | 'CONTINUE' + | 'SLIGHTLY_RIGHT' + | 'RIGHT' + | 'HARD_RIGHT' + | 'CIRCLE_CLOCKWISE' + | 'CIRCLE_COUNTERCLOCKWISE' + | 'STAIRS' + | 'ELEVATOR' + | 'UTURN_LEFT' + | 'UTURN_RIGHT'; +export type EncodedPolyline = { + /** + * The encoded points of the polyline using the Google polyline encoding. + */ + points: string; + /** + * The precision of the returned polyline (7 for /v1, 6 for /v2) + * Be aware that with precision 7, coordinates with |longitude| > 107.37 are undefined/will overflow. + */ + precision: number; + /** + * The number of points in the string + */ + length: number; +}; +export type StepInstruction = { + relativeDirection: Direction; + /** + * The distance in meters that this step takes. + */ + distance: number; + /** + * level where this segment starts, based on OpenStreetMap data + */ + fromLevel: number; + /** + * level where this segment starts, based on OpenStreetMap data + */ + toLevel: number; + /** + * OpenStreetMap way index + */ + osmWay?: number; + polyline: EncodedPolyline; + /** + * The name of the street. + */ + streetName: string; + /** + * Not implemented! + * When exiting a highway or traffic circle, the exit name/number. + */ + exit: string; + /** + * Not implemented! + * Indicates whether or not a street changes direction at an intersection. + */ + stayOn: boolean; + /** + * Not implemented! + * This step is on an open area, such as a plaza or train platform, + * and thus the directions should say something like "cross" + */ + area: boolean; + /** + * Indicates that a fee must be paid by general traffic to use a road, road bridge or road tunnel. + */ + toll?: boolean; + /** + * Experimental. Indicates whether access to this part of the route is restricted. + * See: https://wiki.openstreetmap.org/wiki/Conditional_restrictions + */ + accessRestriction?: string; + /** + * incline in meters across this path segment + */ + elevationUp?: number; + /** + * decline in meters across this path segment + */ + elevationDown?: number; +}; +export enum RentalFormFactor { + Velo = 'BICYCLE', + CargoVelo = 'CARGO_BICYCLE', + Car = 'CAR', + Moped = 'MOPED', + StandingScooter = 'SCOOTER_STANDING', + SeatedScooter = 'SCOOTER_SEATED', + Other = 'OTHER', +} +export enum RentalPropulsionType { + Creature = 'HUMAN', + ElectricAssist = 'ELECTRIC_ASSIST', + Electric = 'ELECTRIC', + Combustion = 'COMBUSTION', + CombustionDiesel = 'COMBUSTION_DIESEL', + Hybrid = 'HYBRID', + PlugInHybrid = 'PLUG_IN_HYBRID', + HydrogenFuelCell = 'HYDROGEN_FUEL_CELL', +} +export enum RentalReturnConstraint { + None = 'NONE', + AnyStation = 'ANY_STATION', + RoundtripStation = 'ROUNDTRIP_STATION', +} +/** + * Vehicle rental + */ +export type Rental = { + /** + * Vehicle share system ID + */ + systemId: string; + /** + * Vehicle share system name + */ + systemName?: string; + /** + * URL of the vehicle share system + */ + url?: string; + /** + * Name of the station + */ + stationName?: string; + /** + * Name of the station where the vehicle is picked up (empty for free floating vehicles) + */ + fromStationName?: string; + /** + * Name of the station where the vehicle is returned (empty for free floating vehicles) + */ + toStationName?: string; + /** + * Rental URI for Android (deep link to the specific station or vehicle) + */ + rentalUriAndroid?: string; + /** + * Rental URI for iOS (deep link to the specific station or vehicle) + */ + rentalUriIOS?: string; + /** + * Rental URI for web (deep link to the specific station or vehicle) + */ + rentalUriWeb?: string; + formFactor?: RentalFormFactor; + propulsionType?: RentalPropulsionType; + returnConstraint?: RentalReturnConstraint; +}; +export type Leg = { + /** + * Transport mode for this leg + */ + mode: Mode; + from: Place; + to: Place; + /** + * Leg duration in seconds + * + * If leg is footpath: + * The footpath duration is derived from the default footpath + * duration using the query parameters `transferTimeFactor` and + * `additionalTransferTime` as follows: + * `leg.duration = defaultDuration * transferTimeFactor + additionalTransferTime.` + * In case the defaultDuration is needed, it can be calculated by + * `defaultDuration = (leg.duration - additionalTransferTime) / transferTimeFactor`. + * Note that the default values are `transferTimeFactor = 1` and + * `additionalTransferTime = 0` in case they are not explicitly + * provided in the query. + */ + duration: number; + /** + * leg departure time + */ + startTime: string; + /** + * leg arrival time + */ + endTime: string; + /** + * scheduled leg departure time + */ + scheduledStartTime: string; + /** + * scheduled leg arrival time + */ + scheduledEndTime: string; + /** + * Whether there is real-time data about this leg + */ + realTime: boolean; + /** + * Whether this leg was originally scheduled to run or is an additional service. + * Scheduled times will equal realtime times in this case. + */ + scheduled: boolean; + /** + * For non-transit legs the distance traveled while traversing this leg in meters. + */ + distance?: number; + /** + * For transit legs, if the rider should stay on the vehicle as it changes route names. + */ + interlineWithPreviousLeg?: boolean; + /** + * For transit legs, the headsign of the bus or train being used. + * For non-transit legs, null + */ + headsign?: string; + routeColor?: string; + routeTextColor?: string; + routeType?: string | number; + agencyName?: string; + agencyUrl?: string; + agencyId?: string; + tripId?: string; + routeShortName?: string; + /** + * Whether this trip is cancelled + */ + cancelled?: boolean; + /** + * Filename and line number where this trip is from + */ + source?: string; + /** + * For transit legs, intermediate stops between the Place where the leg originates + * and the Place where the leg ends. For non-transit legs, null. + */ + intermediateStops?: Place[]; + legGeometry: EncodedPolyline; + /** + * A series of turn by turn instructions + * used for walking, biking and driving. + */ + steps?: StepInstruction[]; + rental?: Rental; + /** + * Index into `Itinerary.fareTransfers` array + * to identify which fare transfer this leg belongs to + */ + fareTransferIndex?: number; + /** + * Index into the `Itinerary.fareTransfers[fareTransferIndex].effectiveFareLegProducts` array + * to identify which effective fare leg this itinerary leg belongs to + */ + effectiveFareLegIndex?: number; + /** + * Alerts for this stop. + */ + alerts?: Alert[]; + /** + * If set, this attribute indicates that this trip has been expanded + * beyond the feed end date (enabled by config flag `timetable.dataset.extend_calendar`) + * by looping active weekdays, e.g. from calendar.txt in GTFS. + */ + loopedCalendarSince?: string; +}; +/** + * The type of media used for the {@link FareMedia fare payment medium} + */ +export enum FareMediaType { + /** No fare media involved (e.g., cash payment) */ + None = 'NONE', + /** Physical paper ticket */ + PaperTicket = 'PAPER_TICKET', + /** Physical transit card with stored value */ + TransitCard = 'TRANSIT_CARD', + /** cEMV (contactless payment) */ + ContactlessPayment = 'CONTACTLESS_EMV', + /** Mobile app with virtual transit cards/passes */ + MobileAppshit = 'MOBILE_APP', +} +export type FareMedia = + | { + /** + * Name of the fare media. Required for transit cards and mobile apps. + */ + fareMediaName: string; + /** + * The type of fare media. + */ + fareMediaType: FareMediaType.TransitCard | FareMediaType.MobileAppshit; + } + | { + /** + * Name of the fare media. Required for transit cards and mobile apps. + */ + fareMediaName?: string; + /** + * The type of fare media. + */ + fareMediaType: Omit< + FareMediaType, + FareMediaType.TransitCard | FareMediaType.MobileAppshit + >; + }; +export type RiderCategory = { + /** + * Rider category name as displayed to the rider. + */ + riderCategoryName: string; + /** + * Specifies if this category should be considered the default (i.e. the main category displayed to riders). + */ + isDefaultFareCategory: boolean; + /** + * URL to a web page providing detailed information about the rider category and/or its eligibility criteria. + */ + eligibilityUrl?: string; +}; +export type FareProduct = { + /** + * The name of the fare product as displayed to riders. + */ + name: string; + /** + * The cost of the fare product. May be negative to represent transfer discounts. May be zero to represent a fare product that is free. + */ + amount: number; + /** + * ISO 4217 currency code. The currency of the cost of the fare product. + */ + currency: string; + riderCategory?: RiderCategory; + media?: FareMedia; +}; +export enum FareTransferRule { + 'A_AB', + 'A_AB_B', + 'AB', +} +/** + * The concept is derived from: https://gtfs.org/documentation/schedule/reference/#fare_transfer_rulestxt + * + * Terminology: + * - **Leg**: An itinerary leg as described by the `Leg` type of this API description. + * - **Effective Fare Leg**: Itinerary legs can be joined together to form one *effective fare leg*. + * - **Fare Transfer**: A fare transfer groups two or more effective fare legs. + * - **A** is the first *effective fare leg* of potentially multiple consecutive legs contained in a fare transfer + * - **B** is any *effective fare leg* following the first *effective fare leg* in this transfer + * - **AB** are all changes between *effective fare legs* contained in this transfer + * + * The fare transfer rule is used to derive the final set of products of the itinerary legs contained in this transfer: + * - A_AB means that any product from the first effective fare leg combined with the product attached to the transfer itself (AB) which can be empty (= free). Note that all subsequent effective fare leg products need to be ignored in this case. + * - A_AB_B mean that a product for each effective fare leg needs to be purchased in a addition to the product attached to the transfer itself (AB) which can be empty (= free) + * - AB only the transfer product itself has to be purchased. Note that all fare products attached to the contained effective fare legs need to be ignored in this case. + * + * An itinerary `Leg` references the index of the fare transfer and the index of the effective fare leg in this transfer it belongs to. + * + */ +export type FareTransfer = { + rule?: FareTransferRule; + transferProducts?: FareProduct[]; + /** + * Lists all valid fare products for the effective fare legs. + * This is an `array>` where the inner array + * lists all possible fare products that would cover this effective fare leg. + * Each "effective fare leg" can have multiple options for adult/child/weekly/monthly/day/one-way tickets etc. + * You can see the outer array as AND (you need one ticket for each effective fare leg (`A_AB_B`), the first effective fare leg (`A_AB`) or no fare leg at all but only the transfer product (`AB`) + * and the inner array as OR (you can choose which ticket to buy) + * + */ + effectiveFareLegProducts: FareProduct[][][]; +}; +export type Itinerary = { + /** + * journey duration in seconds + */ + duration: number; + /** + * journey departure time + */ + startTime: string; + /** + * journey arrival time + */ + endTime: string; + /** + * The number of transfers this trip has. + */ + transfers: number; + /** + * Journey legs + */ + legs: Leg[]; + /** + * Fare information + */ + fareTransfers?: FareTransfer[]; +}; -- cgit v1.2.3