UNPKG

tfl-ts

Version:

🚇 Fully-typed TypeScript client for Transport for London (TfL) API • Zero dependencies • Auto-generated types • Real-time arrivals • Journey planning • Universal compatibility

507 lines (506 loc) 18 kB
import { Api, BikePointSearchParams, TflApiPresentationEntitiesAdditionalProperties, TflApiPresentationEntitiesPlace } from './generated/tfl'; /** * Bike point information returned by the TfL API * @example * { * id: "BikePoints_1", * url: "/Place/BikePoints_1", * commonName: "River Street , Clerkenwell", * placeType: "BikePoint", * additionalProperties: [ * { * category: "NumberOfBikes", * key: "NbBikes", * sourceSystemKey: "BikePoints", * value: "5", * modified: "2023-01-01T12:00:00Z" * }, * { * category: "NumberOfDocks", * key: "NbDocks", * sourceSystemKey: "BikePoints", * value: "15", * modified: "2023-01-01T12:00:00Z" * }, * { * category: "NumberOfEmptyDocks", * key: "NbSpaces", * sourceSystemKey: "BikePoints", * value: "10", * modified: "2023-01-01T12:00:00Z" * } * ], * lat: 51.529163, * lon: -0.10997 * } */ export interface BikePointInfo extends TflApiPresentationEntitiesPlace { /** Unique identifier for the bike point */ id?: string; /** URL to the bike point resource */ url?: string; /** Human-readable name of the bike point */ commonName?: string; /** Type of place (always "BikePoint") */ placeType?: string; /** Additional properties containing bike point status */ additionalProperties?: BikePointProperty[]; /** WGS84 latitude of the location */ lat?: number; /** WGS84 longitude of the location */ lon?: number; /** Distance from search point (if applicable) */ distance?: number; } /** * Bike point property containing status information * @example * { * category: "NumberOfBikes", * key: "NbBikes", * sourceSystemKey: "BikePoints", * value: "5", * modified: "2023-01-01T12:00:00Z" * } */ export interface BikePointProperty extends TflApiPresentationEntitiesAdditionalProperties { /** Category of the property */ category?: string; /** Property key */ key?: string; /** Source system key */ sourceSystemKey?: string; /** Property value */ value?: string; /** Last modified timestamp */ modified?: string; } /** * Bike point status information * @example * { * id: "BikePoints_1", * name: "River Street , Clerkenwell", * bikes: 5, * docks: 15, * spaces: 10, * brokenDocks: 0, * lat: 51.529163, * lon: -0.10997, * terminalName: "001023", * isInstalled: true, * isLocked: false, * installDate: "2023-01-01T12:00:00Z", * removalDate: null, * isTemporary: false, * standardBikes: 4, * eBikes: 1, * additionalProperties: [ * { * category: "NumberOfBikes", * key: "NbBikes", * sourceSystemKey: "BikePoints", * value: "5", * modified: "2023-01-01T12:00:00Z" * } * ] * } */ export interface BikePointStatus { /** Bike point ID */ id: string; /** Bike point name */ name: string; /** Number of bikes available */ bikes: number; /** Total number of docks */ docks: number; /** Number of empty spaces */ spaces: number; /** Number of broken docks (calculated) */ brokenDocks: number; /** Latitude coordinate */ lat?: number; /** Longitude coordinate */ lon?: number; /** Terminal name/ID */ terminalName?: string; /** Whether the bike point is installed */ isInstalled?: boolean; /** Whether the bike point is locked */ isLocked?: boolean; /** Installation date */ installDate?: string; /** Removal date (if applicable) */ removalDate?: string | null; /** Whether this is a temporary bike point */ isTemporary?: boolean; /** Number of standard bikes */ standardBikes?: number; /** Number of electric bikes */ eBikes?: number; /** Original additional properties (preserved when keepTflTypes is true) */ additionalProperties?: BikePointProperty[]; } /** * Query options for bike point search * @example * // Search for bike points near a location * const bikePoints = await client.bikePoint.search({ * query: "St. James", * keepTflTypes: false * }); */ interface BikePointSearchQuery extends BikePointSearchParams { /** The search term (e.g., "St. James") */ query: string; /** Whether to keep $type fields in the response */ keepTflTypes?: boolean; } /** * Query options for bike point radius search * @example * // Search for bike points within 500m of a location * const bikePoints = await client.bikePoint.getByRadius({ * lat: 51.508418, * lon: -0.067048, * radius: 500, * keepTflTypes: false * }); */ interface BikePointRadiusQuery { /** Latitude of the center point */ lat: number; /** Longitude of the center point */ lon: number; /** Radius in meters (default: 200) */ radius?: number; /** Whether to keep $type fields in the response */ keepTflTypes?: boolean; } /** * Query options for bike point bounding box search * @example * // Search for bike points within a bounding box * const bikePoints = await client.bikePoint.getByBounds({ * point1: { lat: 51.516027, lon: -0.119842 }, * point2: { lat: 51.513089, lon: -0.115669 }, * keepTflTypes: false * }); */ interface BikePointBoundsQuery { /** First point of the bounding box */ point1: { lat: number; lon: number; }; /** Second point of the bounding box */ point2: { lat: number; lon: number; }; /** Whether to keep $type fields in the response */ keepTflTypes?: boolean; } /** * Response from radius-based bike point search * @example * { * centrePoint: [51.508, -0.067], * places: [ * { * id: "BikePoints_46", * name: "Nesham Street, Wapping", * distance: 96.91253333568288, * lat: 51.507131, * lon: -0.06691, * bikes: 5, * docks: 15, * spaces: 10 * } * ] * } */ export interface BikePointRadiusResponse { /** Center point coordinates [lat, lon] */ centrePoint: [number, number]; /** Array of bike points within the radius */ places: (BikePointStatus & { distance?: number; })[]; } /** * Bike point class for interacting with TfL Bike Point API endpoints * @example * // Get all bike points * const allBikePoints = await client.bikePoint.get(); * * // Get specific bike point by ID * const bikePoint = await client.bikePoint.getById('BikePoints_1'); * * // Get bike point with original additional properties preserved * const bikePointWithTypes = await client.bikePoint.getById('BikePoints_1', { keepTflTypes: true }); * console.log('Original properties:', bikePointWithTypes.additionalProperties); * * // Search for bike points * const searchResults = await client.bikePoint.search({ query: 'St. James' }); * * // Get bike points within radius * const nearbyBikePoints = await client.bikePoint.getByRadius({ * lat: 51.508418, * lon: -0.067048, * radius: 500 * }); * * // Get bike points within bounding box * const areaBikePoints = await client.bikePoint.getByBounds({ * point1: { lat: 51.516027, lon: -0.119842 }, * point2: { lat: 51.513089, lon: -0.115669 } * }); * * // Access static metadata (no HTTP request) * const endpoints = client.bikePoint.ENDPOINTS; * const totalEndpoints = client.bikePoint.TOTAL_ENDPOINTS; * * // Validate user input before making API calls * const userInput = ['BikePoints_1', 'invalid-id']; * const validIds = userInput.filter(id => id.startsWith('BikePoints_')); * if (validIds.length !== userInput.length) { * throw new Error(`Invalid bike point IDs: ${userInput.filter(id => !id.startsWith('BikePoints_')).join(', ')}`); * } */ export declare class BikePoint { private api; /** Transport mode for bike points */ readonly MODE: "cycle-hire"; /** Bike point property categories */ readonly PROPERTY_CATEGORIES: readonly ["Description"]; /** Bike point property keys */ readonly PROPERTY_KEYS: readonly ["NbBikes", "NbDocks", "NbEmptyDocks"]; constructor(api: Api<{}>); /** * Gets all bike point locations with their current status * * This method returns all bike point locations in London with their current status. * The response includes structured status information with bikes, docks, spaces, and broken docks. * * @param options - Options for the request * @returns Promise resolving to an array of bike point status information * @example * // Get all bike points with status * const allBikePoints = await client.bikePoint.get(); * * // Process bike point data * allBikePoints.forEach(status => { * console.log(`${status.name}: ${status.bikes} bikes, ${status.spaces} spaces available`); * * if (status.brokenDocks > 0) { * console.log(`⚠️ ${status.brokenDocks} broken docks detected`); * } * }); * * // Find bike points with available bikes * const availableBikePoints = allBikePoints.filter(status => status.bikes > 0); * * // Find bike points with available spaces * const availableSpaces = allBikePoints.filter(status => status.spaces > 0); * * // Find bike points with electric bikes * const eBikePoints = allBikePoints.filter(status => status.eBikes > 0); * * // Get all bike points with original additional properties preserved * const allBikePointsWithTypes = await client.bikePoint.get({ keepTflTypes: true }); * * // Access original properties for debugging or advanced processing * allBikePointsWithTypes.forEach(status => { * if (status.additionalProperties) { * console.log(`${status.name} has ${status.additionalProperties.length} original properties`); * status.additionalProperties.forEach(prop => { * console.log(` ${prop.key}: ${prop.value} (${prop.category})`); * }); * } * }); */ get(options?: { keepTflTypes?: boolean; }): Promise<BikePointStatus[]>; /** * Gets the bike point with the given id * * This method returns detailed information about a specific bike point, * including its current status (number of bikes, docks, and spaces). * * @param id - A bike point id (a list of ids can be obtained from the get() method) * @param options - Options for the request * @returns Promise resolving to bike point status information * @example * // Get specific bike point by ID * const bikePoint = await client.bikePoint.getById('BikePoints_1'); * * // Display status information * console.log(`Bike Point: ${bikePoint.name}`); * console.log(`Available bikes: ${bikePoint.bikes}`); * console.log(`Available spaces: ${bikePoint.spaces}`); * console.log(`Total docks: ${bikePoint.docks}`); * * if (bikePoint.brokenDocks > 0) { * console.log(`Broken docks: ${bikePoint.brokenDocks}`); * } * * if (bikePoint.eBikes > 0) { * console.log(`Electric bikes: ${bikePoint.eBikes}`); * } * * // Get bike point with original additional properties preserved * const bikePointWithTypes = await client.bikePoint.getById('BikePoints_1', { keepTflTypes: true }); * * // Access all original properties for advanced processing * if (bikePointWithTypes.additionalProperties) { * console.log('All original properties:'); * bikePointWithTypes.additionalProperties.forEach(prop => { * console.log(` ${prop.key}: ${prop.value} (${prop.category}) - Modified: ${prop.modified}`); * }); * } */ getById(id: string, options?: { keepTflTypes?: boolean; }): Promise<BikePointStatus>; /** * Search for bike stations by their name * * This method searches for bike stations by their name. A bike point's name often * contains information about the name of the street or nearby landmarks. * Note that the search result does not contain the PlaceProperties i.e. the status * or occupancy of the BikePoint. To get that information, you should retrieve * the BikePoint by its id using getById(). * * @param options - Query options for bike point search * @returns Promise resolving to an array of bike point information * @example * // Search for bike points by name * const searchResults = await client.bikePoint.search({ query: 'St. James' }); * * // Search with type fields preserved * const searchResults = await client.bikePoint.search({ * query: 'River Street', * keepTflTypes: true * }); * * // Process search results * searchResults.forEach(bikePoint => { * console.log(`Found: ${bikePoint.commonName} (${bikePoint.id})`); * console.log(`Location: ${bikePoint.lat}, ${bikePoint.lon}`); * * // Get detailed status for each result * client.bikePoint.getById(bikePoint.id!).then(detailedBikePoint => { * console.log(`Status: ${detailedBikePoint.bikes} bikes, ${detailedBikePoint.spaces} spaces`); * }); * }); * * // Search for bike points near landmarks * const nearLandmarks = await client.bikePoint.search({ query: 'Tower Bridge' }); * const nearStations = await client.bikePoint.search({ query: 'Kings Cross' }); */ search(options: BikePointSearchQuery): Promise<BikePointInfo[]>; /** * Gets bike points within a radius of a location * * This method returns bike points within a specified radius of a given location. * Uses the TfL API endpoint: /BikePoint?lat={lat}&lon={lon}&radius={radius} * * @param options - Query options for radius-based bike point search * @returns Promise resolving to bike point radius response * @example * // Get bike points within 500m of a location * const nearbyBikePoints = await client.bikePoint.getByRadius({ * lat: 51.508418, * lon: -0.067048, * radius: 500 * }); * * console.log(`Found ${nearbyBikePoints.places.length} bike points within ${options.radius}m`); * console.log(`Center point: ${nearbyBikePoints.centrePoint[0]}, ${nearbyBikePoints.centrePoint[1]}`); * * // Process each bike point * nearbyBikePoints.places.forEach(bikePoint => { * console.log(`${bikePoint.name}: ${bikePoint.bikes} bikes, ${bikePoint.spaces} spaces (${bikePoint.distance?.toFixed(0)}m away)`); * }); * * // Find closest bike point with available bikes * const closestWithBikes = nearbyBikePoints.places * .filter(bikePoint => bikePoint.bikes > 0) * .sort((a, b) => (a.distance || 0) - (b.distance || 0))[0]; * * if (closestWithBikes) { * console.log(`Closest bike point with bikes: ${closestWithBikes.name} (${closestWithBikes.distance?.toFixed(0)}m)`); * } * * // Get bike points with original additional properties preserved * const nearbyBikePointsWithTypes = await client.bikePoint.getByRadius({ * lat: 51.508418, * lon: -0.067048, * radius: 500, * keepTflTypes: true * }); * * // Access original properties for each bike point * nearbyBikePointsWithTypes.places.forEach(bikePoint => { * if (bikePoint.additionalProperties) { * console.log(`${bikePoint.name} has ${bikePoint.additionalProperties.length} original properties`); * } * }); */ getByRadius(options: BikePointRadiusQuery): Promise<BikePointRadiusResponse>; /** * Gets bike points within a bounding box * * This method returns bike points within a bounding box defined by two points. * Uses the TfL API endpoint: /BikePoint?swLat={swLat}&swLon={swLon}&neLat={neLat}&neLon={neLon} * * @param options - Query options for bounding box bike point search * @returns Promise resolving to an array of bike point status information * @example * // Get bike points within a bounding box * const areaBikePoints = await client.bikePoint.getByBounds({ * point1: { lat: 51.516027, lon: -0.119842 }, * point2: { lat: 51.513089, lon: -0.115669 } * }); * * console.log(`Found ${areaBikePoints.length} bike points in the area`); * * // Process each bike point * areaBikePoints.forEach(bikePoint => { * console.log(`${bikePoint.name}: ${bikePoint.bikes} bikes, ${bikePoint.spaces} spaces`); * console.log(`Location: ${bikePoint.lat}, ${bikePoint.lon}`); * }); * * // Find bike points with most available bikes in the area * const topBikePoints = areaBikePoints * .sort((a, b) => b.bikes - a.bikes) * .slice(0, 3); * * console.log('Top 3 bike points with most bikes:'); * topBikePoints.forEach((bikePoint, index) => { * console.log(`${index + 1}. ${bikePoint.name}: ${bikePoint.bikes} bikes`); * }); * * // Get bike points with original additional properties preserved * const areaBikePointsWithTypes = await client.bikePoint.getByBounds({ * point1: { lat: 51.516027, lon: -0.119842 }, * point2: { lat: 51.513089, lon: -0.115669 }, * keepTflTypes: true * }); * * // Access original properties for debugging * areaBikePointsWithTypes.forEach(bikePoint => { * if (bikePoint.additionalProperties) { * const lastModified = bikePoint.additionalProperties * .map(prop => new Date(prop.modified || '')) * .sort((a, b) => b.getTime() - a.getTime())[0]; * console.log(`${bikePoint.name} last updated: ${lastModified}`); * } * }); */ getByBounds(options: BikePointBoundsQuery): Promise<BikePointStatus[]>; } export { BikePointSearchQuery, BikePointRadiusQuery, BikePointBoundsQuery };