UNPKG

@drfrost/bods-js

Version:

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

208 lines (203 loc) • 6.76 kB
#!/usr/bin/env node /** * BODS CLI Tool * * Simple command-line interface for testing BODS API functionality * * Usage: * bun run cli.ts --help * bun run cli.ts timetables --noc SCMN * bun run cli.ts fares --area manchester * bun run cli.ts vehicles --operator SCMN * bun run cli.ts disruptions */ import { BODSClient, UK_CITIES } from './index.js'; const API_KEY = process.env.BODS_API_KEY; if (!API_KEY) { console.error('āŒ Please set BODS_API_KEY environment variable'); console.log('Example: BODS_API_KEY=your-api-key bun run cli.ts --help'); process.exit(1); } const client = new BODSClient({ apiKey: API_KEY }); function showHelp() { console.log(` 🚌 BODS CLI Tool Usage: bun run cli.ts <command> [options] Commands: timetables Search timetables fares Search fares vehicles Get vehicle locations disruptions Get service disruptions test Test API connectivity Options: --noc <codes> National Operator Codes (comma-separated) --area <city> Predefined city area (manchester, london, etc.) --bbox <coords> Custom bounding box (minLng,minLat,maxLng,maxLat) --line <ref> Line reference --limit <num> Limit results (default: 10) --help Show this help Examples: bun run cli.ts timetables --noc SCMN --limit 5 bun run cli.ts fares --area manchester bun run cli.ts vehicles --noc SCMN --area liverpool bun run cli.ts disruptions `); } async function handleTimetables(args) { console.log('šŸ” Searching timetables...\n'); const params = { limit: parseInt(args.limit) || 10 }; if (args.noc) { params.noc = args.noc.split(','); } try { const result = await client.timetables.search(params); console.log(`Found ${result.count} timetables (showing ${result.results.length}):\n`); result.results.forEach((timetable, i) => { console.log(`${i + 1}. ${timetable.operatorName}`); console.log(` Name: ${timetable.name}`); console.log(` Lines: ${timetable.lines.join(', ')}`); console.log(` Quality: ${timetable.dqRag} (${timetable.dqScore})`); console.log(` Status: ${timetable.status}`); console.log(''); }); } catch (error) { console.error('āŒ Error:', error); } } async function handleFares(args) { console.log('šŸ” Searching fares...\n'); const params = { limit: parseInt(args.limit) || 10 }; if (args.noc) { params.noc = args.noc.split(','); } if (args.area && args.area.toUpperCase() in UK_CITIES) { params.boundingBox = UK_CITIES[args.area.toUpperCase()]; } else if (args.bbox) { params.boundingBox = args.bbox.split(',').map(Number); } try { const result = await client.fares.search(params); console.log(`Found ${result.count} fare datasets (showing ${result.results.length}):\n`); result.results.forEach((fare, i) => { console.log(`${i + 1}. ${fare.operatorName}`); console.log(` Name: ${fare.name}`); console.log(` Fare zones: ${fare.numOfFareZones}`); console.log(` Products: ${fare.numOfFareProducts}`); console.log(` Status: ${fare.status}`); console.log(''); }); } catch (error) { console.error('āŒ Error:', error); } } async function handleVehicles(args) { console.log('šŸ” Getting vehicle locations...\n'); const params = {}; if (args.noc) { params.operatorRef = args.noc.split(','); } if (args.line) { params.lineRef = args.line; } if (args.area && args.area.toUpperCase() in UK_CITIES) { params.boundingBox = UK_CITIES[args.area.toUpperCase()]; } else if (args.bbox) { params.boundingBox = args.bbox.split(',').map(Number); } try { const result = await client.avl.getSIRIVM(params); console.log(`SIRI-VM Data received: ${result.xmlData.length} characters`); console.log(`First 500 characters:\n${result.xmlData.substring(0, 500)}...`); } catch (error) { console.error('āŒ Error:', error); } } async function handleDisruptions() { console.log('šŸ” Getting service disruptions...\n'); try { const parsed = await client.disruptions.getCurrentParsed(); console.log(`Found ${parsed.length} disruptions:\n`); parsed.forEach((disruption, i) => { console.log(`${i + 1}. ${disruption.planned ? '[PLANNED]' : '[UNPLANNED]'} ${disruption.participantRef}`); console.log(` Summary: ${disruption.summary}`); console.log(` Severity: ${disruption.severity}`); if (disruption.startTime) { console.log(` Start: ${new Date(disruption.startTime).toLocaleString()}`); } console.log(''); }); } catch (error) { console.error('āŒ Error:', error); } } async function handleTest() { console.log('šŸ” Testing API connectivity...\n'); try { const isConnected = await client.testConnection(); console.log(`API Status: ${isConnected ? 'āœ… Connected' : 'āŒ Failed'}`); if (isConnected) { const config = client.getConfig(); console.log(`Base URL: ${config.baseUrl}`); console.log(`Timeout: ${config.timeout}ms`); } } catch (error) { console.error('āŒ Error:', error); } } function parseArgs() { const argv = process.argv.slice(2); const command = argv[0] || 'help'; const args = {}; for (let i = 1; i < argv.length; i += 2) { const arg = argv[i]; if (arg?.startsWith('--')) { const key = arg.substring(2); const value = argv[i + 1]; args[key] = value; } } return { command, args }; } async function main() { const { command, args } = parseArgs(); if (command === 'help' || args.help) { showHelp(); return; } console.log('🚌 BODS CLI Tool\n'); switch (command) { case 'timetables': await handleTimetables(args); break; case 'fares': await handleFares(args); break; case 'vehicles': await handleVehicles(args); break; case 'disruptions': await handleDisruptions(); break; case 'test': await handleTest(); break; default: console.error(`āŒ Unknown command: ${command}`); showHelp(); process.exit(1); } } if (import.meta.main) { main().catch(console.error); }