@drfrost/bods-js
Version:
JavaScript client for the UK's Bus Open Data Service (BODS) API
142 lines (141 loc) • 4.35 kB
JavaScript
/**
* Client for interacting with the BODS Fares API
*
* The Fares API provides access to bus fare information.
* Data is updated every 24 hours around 06:00 GMT.
*/
export class FaresClient {
constructor(httpClient) {
this.httpClient = httpClient;
}
/**
* Search for fares datasets
*
* @param params - Search parameters to filter fares
* @returns Promise resolving to paginated fares results
*
* @example
* ```typescript
* // Find all fares for a specific operator
* const fares = await client.fares.search({
* noc: ['SCMN'],
* status: 'published'
* });
*
* // Search by geographic area (Liverpool area example)
* const areaFares = await client.fares.search({
* boundingBox: [-2.930, 53.374, -3.085, 53.453]
* });
* ```
*/
async search(params = {}) {
const response = await this.httpClient.get('/api/v1/fares/dataset', params);
return response.data;
}
/**
* Get a specific fares dataset by ID
*
* @param datasetId - The unique dataset identifier
* @returns Promise resolving to the fares dataset
*
* @example
* ```typescript
* const fares = await client.fares.getById(86);
* console.log(fares.operatorName, fares.numOfFareZones);
* ```
*/
async getById(datasetId) {
const response = await this.httpClient.get(`/api/v1/fares/dataset/${datasetId}`);
return response.data;
}
/**
* Get all fares for a specific operator
*
* @param noc - National Operator Code(s)
* @param additionalParams - Additional search parameters
* @returns Promise resolving to paginated fares results
*
* @example
* ```typescript
* const operatorFares = await client.fares.getByOperator(['SCMN', 'SCGH']);
* ```
*/
async getByOperator(noc, additionalParams = {}) {
return this.search({
...additionalParams,
noc: Array.isArray(noc) ? noc : [noc]
});
}
/**
* Get fares for a specific geographic area
*
* @param boundingBox - Geographic bounding box [minLng, minLat, maxLng, maxLat]
* @param additionalParams - Additional search parameters
* @returns Promise resolving to paginated fares results
*
* @example
* ```typescript
* // Liverpool area
* const liverpoolFares = await client.fares.getByArea(
* [-2.930, 53.374, -3.085, 53.453]
* );
*
* // Manchester area
* const manchesterFares = await client.fares.getByArea(
* [-2.3, 53.4, -2.2, 53.5]
* );
* ```
*/
async getByArea(boundingBox, additionalParams = {}) {
return this.search({
...additionalParams,
boundingBox
});
}
/**
* Get published fares datasets only
*
* @param additionalParams - Additional search parameters
* @returns Promise resolving to paginated fares results
*
* @example
* ```typescript
* const publishedFares = await client.fares.getPublished({
* limit: 100
* });
* ```
*/
async getPublished(additionalParams = {}) {
return this.search({
...additionalParams,
status: 'published'
});
}
/**
* Helper method to create bounding box from center point and radius
*
* @param centerLat - Center latitude
* @param centerLng - Center longitude
* @param radiusKm - Radius in kilometers
* @returns Bounding box coordinates
*
* @example
* ```typescript
* const bbox = client.fares.createBoundingBox(53.4808, -2.2426, 10); // Manchester, 10km radius
* const nearbyFares = await client.fares.getByArea(bbox);
* ```
*/
createBoundingBox(centerLat, centerLng, radiusKm) {
// Approximate degrees per kilometer
const latDegPerKm = 1 / 111;
const lngDegPerKm = 1 / (111 * Math.cos(centerLat * Math.PI / 180));
const latOffset = radiusKm * latDegPerKm;
const lngOffset = radiusKm * lngDegPerKm;
return [
centerLng - lngOffset, // minLng
centerLat - latOffset, // minLat
centerLng + lngOffset, // maxLng
centerLat + latOffset // maxLat
];
}
}