UNPKG

@drfrost/bods-js

Version:

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

161 lines (160 loc) 6.05 kB
/** * Client for interacting with the BODS Disruptions API * * The Disruptions API provides information about current and planned * disruptions to bus services in SIRI-SX format (XML). * Data is updated as new information becomes available. */ export class DisruptionsClient { constructor(httpClient) { this.httpClient = httpClient; } /** * Get all current service disruptions in SIRI-SX format * * @returns Promise resolving to SIRI-SX XML data containing all disruptions * * @example * ```typescript * // Get all current disruptions * const disruptions = await client.disruptions.getAll(); * console.log('Disruptions XML:', disruptions.xmlData); * * // You would typically parse the XML to extract specific disruption details * const parser = new DOMParser(); * const doc = parser.parseFromString(disruptions.xmlData, 'text/xml'); * ``` */ async getAll() { const response = await this.httpClient.get('/api/v1/siri-sx'); return { xmlData: response.data }; } /** * Get current service disruptions (alias for getAll) * * @returns Promise resolving to SIRI-SX XML data containing current disruptions * * @example * ```typescript * const currentDisruptions = await client.disruptions.getCurrent(); * ``` */ async getCurrent() { return this.getAll(); } /** * Helper method to parse SIRI-SX XML and extract basic disruption information * Note: This is a basic parser. For production use, consider a more robust XML parsing solution. * Requires a DOM environment (browser) or a polyfill like jsdom in Node.js. * * @param xmlData - Raw SIRI-SX XML data * @returns Array of parsed disruption objects * * @example * ```typescript * const disruptions = await client.disruptions.getAll(); * const parsed = client.disruptions.parseDisruptions(disruptions.xmlData); * * parsed.forEach(disruption => { * console.log(`${disruption.summary}: ${disruption.description}`); * }); * ``` */ parseDisruptions(xmlData) { try { // Check if DOMParser is available (browser environment) if (typeof DOMParser === 'undefined') { console.warn('DOMParser not available. XML parsing requires a DOM environment or polyfill.'); return []; } const parser = new DOMParser(); const doc = parser.parseFromString(xmlData, 'text/xml'); const situations = doc.querySelectorAll('PtSituationElement'); const results = []; situations.forEach((situation) => { const situationNumber = situation.querySelector('SituationNumber')?.textContent || undefined; const participantRef = situation.querySelector('ParticipantRef')?.textContent || undefined; const summary = situation.querySelector('Summary')?.textContent || undefined; const description = situation.querySelector('Description')?.textContent || undefined; const severity = situation.querySelector('Severity')?.textContent || undefined; const startTime = situation.querySelector('ValidityPeriod StartTime')?.textContent || undefined; const endTime = situation.querySelector('ValidityPeriod EndTime')?.textContent || undefined; const plannedText = situation.querySelector('Planned')?.textContent; const planned = plannedText ? plannedText.toLowerCase() === 'true' : undefined; results.push({ situationNumber, participantRef, summary, description, severity, startTime, endTime, planned }); }); return results; } catch (error) { console.warn('Failed to parse SIRI-SX XML:', error); return []; } } /** * Get and parse current disruptions in one call * * @returns Promise resolving to array of parsed disruption objects * * @example * ```typescript * const disruptions = await client.disruptions.getCurrentParsed(); * * disruptions.forEach(disruption => { * if (disruption.planned) { * console.log(`Planned disruption: ${disruption.summary}`); * } else { * console.log(`Unplanned disruption: ${disruption.summary}`); * } * }); * ``` */ async getCurrentParsed() { const disruptions = await this.getAll(); return this.parseDisruptions(disruptions.xmlData); } /** * Filter parsed disruptions by criteria * * @param disruptions - Array of parsed disruptions * @param filters - Filter criteria * @returns Filtered array of disruptions * * @example * ```typescript * const allDisruptions = await client.disruptions.getCurrentParsed(); * * // Get only unplanned disruptions * const unplanned = client.disruptions.filterDisruptions(allDisruptions, { * planned: false * }); * * // Get disruptions from specific participant * const tfgmDisruptions = client.disruptions.filterDisruptions(allDisruptions, { * participantRef: 'TfGM' * }); * ``` */ filterDisruptions(disruptions, filters) { return disruptions.filter(disruption => { if (filters.planned !== undefined && disruption.planned !== filters.planned) { return false; } if (filters.participantRef && disruption.participantRef !== filters.participantRef) { return false; } if (filters.severity && disruption.severity !== filters.severity) { return false; } return true; }); } }