import { ParkingRepositoryLoader } from "./ParkingRepositoryLoader"; import { ParkingGetterSetterRepository } from "../../repositories/ParkingGetterSetterRepository"; import { createHash } from "node:crypto"; import { ApiResponseError } from "../ApiResponseError"; import { IParkingStructure } from "../../entities/ParkingRepositoryEntities"; class ApiParseError extends Error { constructor(message: string) { super(message); this.name = "ApiParseError"; } } export class ChapmanApiBasedParkingRepositoryLoader implements ParkingRepositoryLoader { public static readonly id = "chapman-parking-loader"; private readonly fetchUrl = "https://webfarm.chapman.edu/ParkingService/ParkingService/counts"; constructor( public repository: ParkingGetterSetterRepository ) { this.fetchAndUpdateParkingStructures = this.fetchAndUpdateParkingStructures.bind(this); } async fetchAndUpdateParkingStructures(): Promise { let json: any; try { const response = await fetch(this.fetchUrl); json = await response.json(); } catch(e: any) { throw new ApiResponseError(e.message); } try { if (typeof json.Structures === "object") { const parkingStructures: IParkingStructure[] = json.Structures.map(this.constructIParkingStructureFromJson); await Promise.all(parkingStructures.map(async (structure: IParkingStructure) => { await this.repository.addOrUpdateParkingStructure(structure); })); } } catch(e: any) { throw new ApiParseError(e.message); } } private constructIParkingStructureFromJson(jsonStructure: any) { const structureToReturn: IParkingStructure = { capacity: jsonStructure.Capacity, coordinates: { latitude: jsonStructure.Latitude, longitude: jsonStructure.Longitude, }, id: ChapmanApiBasedParkingRepositoryLoader.generateId(jsonStructure.Address), name: jsonStructure.Name, spotsAvailable: jsonStructure.CurrentCount, address: jsonStructure.Address } return structureToReturn; } private static normalizeAddress(address: string): string { return address .toLowerCase() .split(/\s+/) .filter(part => part.length > 0) .join(' '); } public static generateId(address: string): string { const normalized = this.normalizeAddress(address); const hash = createHash('sha256') .update(normalized) .digest('hex'); return hash.substring(0, 32); } }