diff --git a/src/index.ts b/src/index.ts index 174cc4e..f6fe1aa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { resolvers } from "./resolvers"; import { loadTestData } from "./testData"; import { ServerContext } from "./serverContext"; import { UnoptimizedInMemoryRepository } from "./unoptimizedInMemoryRepository"; +import { RepositoryDataLoader } from "./repositoryDataLoader"; const typeDefs = readFileSync("./schema.graphql", "utf8"); @@ -15,8 +16,12 @@ async function main() { }); const repository = new UnoptimizedInMemoryRepository(); - await loadTestData(repository); - // startDataUpdater(); + // await loadTestData(repository); + + const repositoryDataUpdater = new RepositoryDataLoader( + repository + ); + await repositoryDataUpdater.start(); const { url } = await startStandaloneServer(server, { listen: { diff --git a/src/repositoryDataLoader.ts b/src/repositoryDataLoader.ts new file mode 100644 index 0000000..3bac63f --- /dev/null +++ b/src/repositoryDataLoader.ts @@ -0,0 +1,117 @@ +import { IRoute, ISystem, Repository } from "./repository"; + +const timeout = 10000; +const systemIdsToSupport = ["263"] +const baseUrl = "https://passiogo.com/mapGetData.php"; + +export class RepositoryDataLoader { + private shouldBeRunning: boolean = false; + + constructor( + private repository: Repository, + ) {} + + public async start() { + if (this.shouldBeRunning) { + console.warn("DataLoader timer is already running"); + return; + } + + this.shouldBeRunning = true; + await this.startFetchDataAndUpdate(); + } + + public stop() { + this.shouldBeRunning = false; + } + + private async startFetchDataAndUpdate() { + if (!this.shouldBeRunning) return; + + try { + await this.fetchAndUpdateSystemData(); + await this.fetchAndUpdateRouteDataForExistingSystems(); + await this.fetchAndUpdateStopAndOrderedStopData(); + await this.fetchAndUpdateShuttleData(); + await this.fetchAndUpdateEtaData(); + } catch (e) { + console.error(e); + } finally { + // TODO test if memoization of shouldBeRunning works as intended, + // I have no idea how JavaScript works + setTimeout(this.startFetchDataAndUpdate, timeout); + } + } + + private async fetchAndUpdateSystemData() { + const params = { + getSystems: "2", + }; + const query = new URLSearchParams(params).toString(); + const response = await fetch(`${baseUrl}?${query}`); + const json = await response.json() + + if (typeof json.all === "object") { + // filter down to supported systems + const filteredSystems = json.all.filter((jsonSystem: any) => systemIdsToSupport.includes(jsonSystem.id)); + await Promise.all(filteredSystems.map(async (system: any) => { + const constructedSystem: ISystem = { + id: system.id, + name: system.fullname, + }; + + await this.repository.addOrUpdateSystem(constructedSystem); + })); + } + } + + private async fetchAndUpdateRouteDataForExistingSystems() { + const systems = await this.repository.getSystems(); + await Promise.all(systems.map(async (system) => { + const params = { + getRoutes: "2", + }; + + const formDataJsonObject = { + "systemSelected0": system.id, + "amount": "1", + } + const formData = new FormData(); + formData.set("json", JSON.stringify(formDataJsonObject)); + + const query = new URLSearchParams(params).toString(); + const response = await fetch(`${baseUrl}?${query}`, { + method: "POST", + body: formData, + }); + const json = await response.json(); + + if (typeof json.all === "object") { + await Promise.all(json.all.map(async (jsonRoute: any) => { + const constructedRoute: IRoute = { + name: jsonRoute.name, + color: jsonRoute.color, + id: jsonRoute.myid, + // TODO associate polyline coordinates with routes + polylineCoordinates: [], + systemId: system.id, + }; + + await this.repository.addOrUpdateRoute(constructedRoute); + })) + } + })); + } + + private async fetchAndUpdateStopAndOrderedStopData() { + + } + + private async fetchAndUpdateShuttleData() { + + } + + private async fetchAndUpdateEtaData() { + + } +} \ No newline at end of file