UNPKG

slow-zone

Version:

A client & wrapper for CTA 'L' arrival data

76 lines (75 loc) 2.7 kB
import { readFileSync } from "node:fs"; import { request } from "node:https"; import { parseTrain } from "./parsers/train.js"; const API_BASE_URL = "lapi.transitchicago.com"; const API_BASE_PATH = "/api/1.0"; export const VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8")).version; export default class SlowZone { constructor(options) { this.apiKey = options.apiKey; } getArrivalsForStation(stationId, options = {}) { return this.getArrivals({ ...options, mapid: stationId }); } getArrivalsForStop(stopId, options = {}) { return this.getArrivals({ ...options, stpid: stopId }); } followTrain(runId) { return this.fetch("ttfollow.aspx", { runnumber: runId }); } getArrivals(options = {}) { return this.fetch("ttarrivals.aspx", options); } async fetch(endpoint, queryParams = {}) { const resp = await this.makeRequest(endpoint, queryParams); if (!resp) { throw new Error("invalid response"); } if (resp.ctatt.errCd != "0") { throw new Error(`[${resp.ctatt.errCd}] ${resp.ctatt.errNm}`); } return resp.ctatt.eta.map((trainData) => parseTrain(trainData)); } async makeRequest(endpoint, queryParams = {}) { const query = new URLSearchParams({ ...queryParams, key: this.apiKey, outputType: "json", }); const options = { hostname: API_BASE_URL, port: 443, path: `${API_BASE_PATH}/${endpoint}?${query.toString()}`, method: "GET", headers: { Accept: "application/json", "User-Agent": `slow-zone/${VERSION}`, }, }; return new Promise(function (resolve, reject) { const req = request(options, (res) => { if (res.statusCode && (res.statusCode < 200 || res.statusCode >= 300)) { return reject(new Error(res.statusCode.toString())); } const body = []; let json; res.on("data", (chunk) => { body.push(chunk); }); res.on("end", () => { try { json = JSON.parse(Buffer.concat(body).toString()); } catch (e) { return reject(e); } return resolve(json); }); }); req.on("error", (err) => { return reject(err); }); req.end(); }); } }