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
283 lines (282 loc) • 10 kB
JavaScript
"use strict";
/**
* Mode API Module
*
* Provides access to transport mode information, active service types, and mode-specific arrivals.
* Transport modes include tube, bus, dlr, overground, tram, cable-car, cycle-hire, and more.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Modes = exports.Mode = void 0;
// Import generated metadata (NEVER hardcode!)
const Meta_1 = require("./generated/meta/Meta");
Object.defineProperty(exports, "Modes", { enumerable: true, get: function () { return Meta_1.Modes; } });
const stripTypes_1 = require("./utils/stripTypes");
/**
* Mode API client for transport mode information and arrivals
*
* The Mode API provides information about transport modes available in the TfL network,
* including service types and real-time arrival predictions for all stops of a given mode.
*
* @example
* ```typescript
* // Get all active service types (currently only supports tube)
* const serviceTypes = await client.mode.getActiveServiceTypes();
*
* // Get arrivals for all tube stops
* const tubeArrivals = await client.mode.getArrivals({ mode: 'tube', count: 5 });
*
* // Validate mode names
* const isValidMode = client.mode.MODE_NAMES.includes('elizabeth-line');
* ```
*/
class Mode {
constructor(api) {
this.api = api;
// 🚨 ALWAYS use generated metadata (never hardcode!)
this.MODE_NAMES = Meta_1.Modes.map(m => m.modeName);
this.SERVICE_TYPES = Meta_1.ServiceTypes;
this.DISRUPTION_CATEGORIES = Meta_1.DisruptionCategories;
this.PLACE_TYPES = Meta_1.PlaceTypes;
this.SEARCH_PROVIDERS = Meta_1.SearchProviders;
this.SORT_OPTIONS = Meta_1.Sorts;
this.STOP_TYPES = Meta_1.StopTypes;
this.CATEGORIES = Meta_1.Categories;
this.ALL_SEVERITY = Meta_1.Severity;
// Build derived metadata from generated data
this.MODES_BY_TYPE = this.buildModesByType();
this.TFL_OPERATED_MODES = this.buildTflOperatedModes();
this.FARE_PAYING_MODES = this.buildFarePayingModes();
this.SCHEDULED_SERVICE_MODES = this.buildScheduledServiceModes();
}
/**
* Gets the active service types for transport modes
*
* Returns the service type active for a mode. Currently only supports tube mode.
*
* @param options - Query options for getting active service types
* @returns Promise resolving to array of active service types
*
* @example
* ```typescript
* // Get all active service types
* const serviceTypes = await client.mode.getActiveServiceTypes();
* console.log(serviceTypes);
* // Output: [{ name: 'Regular', uri: '/Line/Route?serviceTypes=Regular' }, ...]
*
* // Check if service types are available
* if (serviceTypes.length > 0) {
* console.log('Active service types available');
* }
* ```
*/
async getActiveServiceTypes(options = {}) {
const { keepTflTypes = false } = options;
return this.api.mode.modeGetActiveServiceTypes().then(response => (0, stripTypes_1.stripTypeFields)(response.data, keepTflTypes));
}
/**
* Gets arrival predictions for all stops of a given mode
*
* Returns the next arrival predictions for all stops that serve the specified transport mode.
* This is useful for getting a comprehensive view of arrivals across an entire mode network.
*
* @param options - Query options including mode and count
* @returns Promise resolving to array of arrival predictions
*
* @example
* ```typescript
* // Get next 3 arrivals for all tube stops
* const tubeArrivals = await client.mode.getArrivals({
* mode: 'tube',
* count: 3
* });
*
* // Get all available arrivals for DLR
* const dlrArrivals = await client.mode.getArrivals({
* mode: 'dlr',
* count: -1
* });
*
* // Validate mode before making request
* const modeName = 'elizabeth-line';
* if (client.mode.MODE_NAMES.includes(modeName)) {
* const arrivals = await client.mode.getArrivals({ mode: modeName });
* } else {
* throw new Error(`Invalid mode: ${modeName}`);
* }
*
* // Filter arrivals by destination
* const filteredArrivals = tubeArrivals.filter(arrival =>
* arrival.towards?.includes('Central London')
* );
* ```
*/
async getArrivals(options) {
const { mode, count, keepTflTypes = false } = options;
const params = {
mode,
...(count !== undefined && { count })
};
return this.api.mode.modeArrivals(params).then(response => (0, stripTypes_1.stripTypeFields)(response.data, keepTflTypes));
}
// 🚨 Build derived metadata from generated data
buildModesByType() {
const modesByType = {
tflOperated: [],
farePaying: [],
scheduled: [],
nonTfl: []
};
Meta_1.Modes.forEach(mode => {
if (mode.isTflService) {
modesByType.tflOperated.push(mode.modeName);
}
else {
modesByType.nonTfl.push(mode.modeName);
}
if (mode.isFarePaying) {
modesByType.farePaying.push(mode.modeName);
}
if (mode.isScheduledService) {
modesByType.scheduled.push(mode.modeName);
}
});
return modesByType;
}
buildTflOperatedModes() {
return Meta_1.Modes
.filter(mode => mode.isTflService)
.map(mode => mode.modeName);
}
buildFarePayingModes() {
return Meta_1.Modes
.filter(mode => mode.isFarePaying)
.map(mode => mode.modeName);
}
buildScheduledServiceModes() {
return Meta_1.Modes
.filter(mode => mode.isScheduledService)
.map(mode => mode.modeName);
}
// Utility methods
/**
* Validates if a mode name is valid
*
* @param modeName - The mode name to validate
* @returns True if the mode is valid, false otherwise
*
* @example
* ```typescript
* const isValid = client.mode.isValidMode('tube'); // true
* const isInvalid = client.mode.isValidMode('invalid-mode'); // false
* ```
*/
isValidMode(modeName) {
return this.MODE_NAMES.includes(modeName);
}
/**
* Checks if a mode is operated by TfL
*
* @param modeName - The mode name to check
* @returns True if the mode is TfL operated, false otherwise
*
* @example
* ```typescript
* const isTflOperated = client.mode.isTflOperated('tube'); // true
* const isNotTflOperated = client.mode.isTflOperated('national-rail'); // false
* ```
*/
isTflOperated(modeName) {
return this.TFL_OPERATED_MODES.includes(modeName);
}
/**
* Checks if a mode requires fare payment
*
* @param modeName - The mode name to check
* @returns True if the mode requires fare payment, false otherwise
*
* @example
* ```typescript
* const requiresFare = client.mode.requiresFare('bus'); // true
* const isFree = client.mode.requiresFare('walking'); // false
* ```
*/
requiresFare(modeName) {
return this.FARE_PAYING_MODES.includes(modeName);
}
/**
* Checks if a mode operates on a scheduled service
*
* @param modeName - The mode name to check
* @returns True if the mode operates on a schedule, false otherwise
*
* @example
* ```typescript
* const isScheduled = client.mode.isScheduledService('tube'); // true
* const isNotScheduled = client.mode.isScheduledService('walking'); // false
* ```
*/
isScheduledService(modeName) {
return this.SCHEDULED_SERVICE_MODES.includes(modeName);
}
/**
* Gets mode information by name
*
* @param modeName - The mode name to get information for
* @returns Mode information or undefined if not found
*
* @example
* ```typescript
* const modeInfo = client.mode.getModeInfo('tube');
* console.log(modeInfo);
* // Output: { isTflService: true, isFarePaying: true, isScheduledService: true, modeName: 'tube' }
* ```
*/
getModeInfo(modeName) {
return Meta_1.Modes.find(mode => mode.modeName === modeName);
}
/**
* Gets all modes that match specific criteria
*
* @param criteria - Filter criteria for modes
* @returns Array of mode names matching the criteria
*
* @example
* ```typescript
* // Get all TfL operated modes
* const tflModes = client.mode.getModesByCriteria({ isTflService: true });
*
* // Get all free modes
* const freeModes = client.mode.getModesByCriteria({ isFarePaying: false });
*
* // Get all scheduled TfL services
* const scheduledTfl = client.mode.getModesByCriteria({
* isTflService: true,
* isScheduledService: true
* });
* ```
*/
getModesByCriteria(criteria) {
return Meta_1.Modes
.filter(mode => {
if (criteria.isTflService !== undefined && mode.isTflService !== criteria.isTflService) {
return false;
}
if (criteria.isFarePaying !== undefined && mode.isFarePaying !== criteria.isFarePaying) {
return false;
}
if (criteria.isScheduledService !== undefined && mode.isScheduledService !== criteria.isScheduledService) {
return false;
}
return true;
})
.map(mode => mode.modeName);
}
}
exports.Mode = Mode;
// Static metadata for API documentation
Mode.API_NAME = 'Mode API';
Mode.DESCRIPTION = 'Transport mode information and arrivals';
Mode.ENDPOINTS = {
getActiveServiceTypes: '/Mode/ActiveServiceTypes',
getArrivals: '/Mode/{mode}/Arrivals'
};