UNPKG

@drfrost/bods-js

Version:

JavaScript client for the UK's Bus Open Data Service (BODS) API

430 lines (322 loc) β€’ 11.4 kB
# bods-js [![npm version](https://badge.fury.io/js/@drfrost/bods-js.svg)](https://badge.fury.io/js/@drfrost/bods-js) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ## BODS JavaScript Client A comprehensive TypeScript/JavaScript client for the UK's **Bus Open Data Service (BODS) API**. This library provides a simple, type-safe interface to access bus timetables, fares, real-time vehicle locations, and service disruptions. ## πŸš€ Features - **🎯 Full TypeScript Support** - Complete type definitions for all API responses - **πŸ“… Timetables API** - Access to bus schedules and route information - **🎟️ Fares API** - Bus fare information by operator and area - **🚌 Real-time Vehicle Tracking** - Live bus locations in SIRI-VM and GTFS-RT formats - **⚠️ Service Disruptions** - Current and planned service disruptions - **πŸ—ΊοΈ Geographic Queries** - Search by bounding box with built-in utilities - **πŸ“„ Comprehensive Documentation** - JSDoc comments throughout - **πŸ›‘οΈ Error Handling** - Robust error handling with detailed error types - **⚑ Performance** - Built with modern fetch API and optimized for speed ## πŸ“¦ Installation ```bash # Using npm npm install @drfrost/bods-js # Using yarn yarn add @drfrost/bods-js # Using pnpm pnpm add @drfrost/bods-js # Using bun bun add @drfrost/bods-js ``` ## πŸ”‘ Getting Started ### 1. Get Your API Key First, register for a free API key at [data.bus-data.dft.gov.uk](https://data.bus-data.dft.gov.uk/account/). ### 2. Basic Usage ```typescript // Named import (recommended) import { BODSClient } from '@drfrost/bods-js'; // Default import (also supported) import BODSClient from '@drfrost/bods-js'; // Import specific clients import { TimetablesClient, AVLClient } from '@drfrost/bods-js'; const client = new BODSClient({ apiKey: 'your-api-key-here' }); // Search for timetables const timetables = await client.timetables.search({ noc: ['SCMN'], // Stagecoach Manchester status: 'published' }); console.log(`Found ${timetables.count} timetables`); ``` ## πŸ“š API Reference ### πŸ—οΈ Client Initialization ```typescript const client = new BODSClient({ apiKey: 'your-api-key', baseUrl: 'https://data.bus-data.dft.gov.uk', // optional timeout: 30000 // optional, in milliseconds }); ``` ### πŸ“… Timetables API Access bus schedules and route information. Data updated daily at 06:00 GMT. ```typescript // Search timetables const timetables = await client.timetables.search({ noc: ['SCMN', 'SCGH'], // Operator codes adminArea: ['060'], // Area codes status: 'published', // published | inactive dqRag: 'green', // red | amber | green bodsCompliance: true, // BODS compliant only limit: 50 // Max results }); // Get specific timetable const timetable = await client.timetables.getById(123); // Get by operator const operatorTimetables = await client.timetables.getByOperator('SCMN'); // Get high-quality timetables const quality = await client.timetables.getHighQuality(); // Get recently modified const recent = await client.timetables.getRecentlyModified( new Date('2023-01-01') ); ``` ### 🎟️ Fares API Access bus fare information. Data updated daily at 06:00 GMT. ```typescript // Search fares const fares = await client.fares.search({ noc: ['SCMN'], status: 'published', boundingBox: [-2.930, 53.374, -3.085, 53.453] // Liverpool area }); // Get specific fares dataset const fareData = await client.fares.getById(456); // Get by operator const operatorFares = await client.fares.getByOperator(['SCMN']); // Get by geographic area const areaFares = await client.fares.getByArea( [-2.930, 53.374, -3.085, 53.453] ); // Get published fares only const published = await client.fares.getPublished(); ``` ### 🚌 Real-time Vehicle Locations (AVL) Access live bus locations. Data updated every 10 seconds. ```typescript // Get vehicles in SIRI-VM format (XML) const vehicles = await client.avl.getSIRIVM({ operatorRef: ['SCMN'], boundingBox: [-2.930, 53.374, -3.085, 53.453], lineRef: '85A' }); // Get vehicles in GTFS-RT format (Protocol Buffers) const gtfsVehicles = await client.avl.getGTFSRT({ boundingBox: [-2.930, 53.374, -3.085, 53.453] }); // Get by operator const operatorVehicles = await client.avl.getByOperator(['SCMN']); // Get by line const lineVehicles = await client.avl.getByLine('85A'); // Get by vehicle const vehicle = await client.avl.getByVehicle('BUSC-001'); // Get by area in different formats const siriVehicles = await client.avl.getByArea(boundingBox, 'siri-vm'); const gtfsVehicles2 = await client.avl.getByArea(boundingBox, 'gtfs-rt'); ``` ### ⚠️ Service Disruptions Access current and planned service disruptions in SIRI-SX format. ```typescript // Get all current disruptions (raw XML) const disruptions = await client.disruptions.getCurrent(); // Get parsed disruptions const parsed = await client.disruptions.getCurrentParsed(); parsed.forEach(disruption => { console.log(`${disruption.summary}: ${disruption.description}`); console.log(`Planned: ${disruption.planned}`); console.log(`Severity: ${disruption.severity}`); }); // Filter disruptions const unplanned = client.disruptions.filterDisruptions(parsed, { planned: false }); const tfgmDisruptions = client.disruptions.filterDisruptions(parsed, { participantRef: 'TfGM' }); ``` ## �️ Utilities The library includes helpful utility functions: ```typescript import { createBoundingBox, calculateDistance, isValidNOC, UK_CITIES } from '@drfrost/bods-js'; // Create bounding box from center point and radius const bbox = createBoundingBox(53.4808, -2.2426, 10); // Manchester, 10km // Use predefined city bounding boxes const manchesterVehicles = await client.avl.getByArea(UK_CITIES.MANCHESTER); const londonFares = await client.fares.getByArea(UK_CITIES.LONDON); // Calculate distance between points const distance = calculateDistance(53.4808, -2.2426, 51.5074, -0.1278); // Validate NOC codes const isValid = isValidNOC('SCMN'); // true ``` ### Available City Bounding Boxes ```typescript UK_CITIES.LONDON // Greater London (30km radius) UK_CITIES.MANCHESTER // Greater Manchester (15km radius) UK_CITIES.BIRMINGHAM // Birmingham (15km radius) UK_CITIES.LEEDS // Leeds (15km radius) UK_CITIES.LIVERPOOL // Liverpool (15km radius) UK_CITIES.BRISTOL // Bristol (15km radius) UK_CITIES.SHEFFIELD // Sheffield (15km radius) UK_CITIES.LEICESTER // Leicester (10km radius) UK_CITIES.COVENTRY // Coventry (10km radius) UK_CITIES.BRADFORD // Bradford (10km radius) ``` ## πŸ”§ Error Handling The client provides detailed error handling: ```typescript import { HttpClientError } from '@drfrost/bods-js'; try { const timetables = await client.timetables.search({ noc: ['INVALID'] }); } catch (error) { if (error instanceof HttpClientError) { switch (error.status) { case 401: console.error('Invalid API key'); break; case 403: console.error('Access forbidden'); break; case 429: console.error('Rate limit exceeded'); break; default: console.error(`HTTP ${error.status}: ${error.message}`); } } } ``` ## 🌐 Environment Support - **Node.js** 18+ (with fetch support) - **Next.js** 13+ (App Router and Pages Router) - **React** (Client and Server Components) - **Browsers** (modern browsers with fetch support) - **Deno** (with compatibility layer) - **Bun** (native support) ### Using with Next.js The library is fully compatible with Next.js applications: ```typescript // app/page.tsx (App Router) import { BODSClient } from '@drfrost/bods-js'; export default async function HomePage() { const client = new BODSClient({ apiKey: process.env.BODS_API_KEY! }); const timetables = await client.timetables.search({ noc: ['SCMN'], limit: 10 }); return ( <div> <h1>Bus Timetables</h1> {/* Render timetables */} </div> ); } ``` ```typescript // pages/api/buses.ts (API Routes) import { BODSClient } from '@drfrost/bods-js'; import type { NextApiRequest, NextApiResponse } from 'next'; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { const client = new BODSClient({ apiKey: process.env.BODS_API_KEY! }); try { const vehicles = await client.avl.getSIRIVM({ operatorRef: ['SCMN'] }); res.status(200).json(vehicles); } catch (error) { res.status(500).json({ error: 'Failed to fetch vehicles' }); } } ``` ## πŸ“– Advanced Examples ### Monitoring Live Buses ```typescript // Monitor buses in real-time async function monitorBuses() { const interval = setInterval(async () => { try { const vehicles = await client.avl.getSIRIVM({ operatorRef: ['SCMN'], boundingBox: UK_CITIES.MANCHESTER }); // Parse and process vehicle locations console.log('Updated vehicle positions'); } catch (error) { console.error('Failed to fetch vehicles:', error); } }, 10000); // Every 10 seconds // Clean up setTimeout(() => clearInterval(interval), 60000); } ``` ### Building a Route Planner ```typescript async function getRouteInfo(operatorCode: string, routeNumber: string) { // Get timetable data const timetables = await client.timetables.search({ noc: [operatorCode], search: routeNumber, status: 'published' }); // Get fare information const fares = await client.fares.getByOperator(operatorCode); // Get live vehicle positions const vehicles = await client.avl.getSIRIVM({ operatorRef: [operatorCode], lineRef: routeNumber }); // Check for disruptions const disruptions = await client.disruptions.getCurrentParsed(); return { timetables: timetables.results, fares: fares.results, liveVehicles: vehicles.xmlData, disruptions: disruptions.filter(d => d.description?.includes(routeNumber) ) }; } ``` ## πŸ§ͺ Testing ```bash bun test ``` ## πŸ“„ License MIT License - see [LICENSE](LICENSE) for details. ## 🀝 Contributing Contributions are welcome! Please read our contributing guidelines and submit pull requests. ## πŸ“ž Support - **Documentation**: [GitHub Wiki](https://github.com/DRFR0ST/bods-js/wiki) - **Issues**: [GitHub Issues](https://github.com/DRFR0ST/bods-js/issues) - **BODS API Docs**: [data.bus-data.dft.gov.uk](https://data.bus-data.dft.gov.uk/guidance/) --- ## Bus Open Data Service (BODS) API Overview The Bus Open Data Service provides comprehensive data about UK bus services through four main APIs: ### **1. Timetables Data API** πŸ“… Detailed information about bus schedules and routes, updated daily at 06:00 GMT. ### **2. Fares Data API** 🎟️ Bus fare information by operator and geographic area, updated daily at 06:00 GMT. ### **3. Automatic Vehicle Location (AVL) API** 🚌 Real-time bus location data in SIRI-VM (XML) and GTFS-RT (Protocol Buffers) formats, updated every 10 seconds. ### **4. Disruptions Data API** ⚠️ Current and planned service disruptions in SIRI-SX format, updated as information becomes available. --- Made with ❀️ for the UK transport community