@drfrost/bods-js
Version:
JavaScript client for the UK's Bus Open Data Service (BODS) API
430 lines (322 loc) β’ 11.4 kB
Markdown
# bods-js
[](https://badge.fury.io/js/@drfrost/bods-js)
[](http://www.typescriptlang.org/)
[](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