can do basic querys from digitransit

This commit is contained in:
Aaro Koivukangas
2024-02-26 14:42:48 +02:00
parent 458ddecb6f
commit 2dad5b19eb
9 changed files with 201 additions and 29 deletions
+1
View File
@@ -1,2 +1,3 @@
dist
node_modules
.env
+1
View File
@@ -6,6 +6,7 @@
"license": "MIT",
"devDependencies": {
"@types/express": "^4.17.21",
"dotenv": "^16.4.5",
"nodemon": "^3.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
+69
View File
@@ -0,0 +1,69 @@
export interface IResponseRoute {
code: string;
directionId: number;
headsign: string;
route: {
gtfsId: string;
shortName: string;
longName: string;
mode: string;
}
}
export interface IRoute {
gtfsId: string;
number: string;
name: string;
direction: number;
headsign: string;
mode: string;
}
export const parseRoute = (obj: IResponseRoute): IRoute | undefined => {
if (!("route" in obj)) {
console.error("No route in parsed object");
return;
}
const routeObj = obj.route;
const gtfsId = routeObj.gtfsId;
const number = routeObj.shortName;
const name = routeObj.longName;
const direction = obj.directionId;
const headsign = obj.headsign;
const mode = routeObj.mode;
const route: IRoute = {
gtfsId,
number,
name,
direction,
headsign,
mode
}
return route;
}
export const isRoute = (obj: any): obj is IRoute => {
if (
"code" in obj &&
"number" in obj &&
"name" in obj &&
"direction" in obj &&
"headsign" in obj &&
"mode" in obj
) {
return true;
}
return false;
}
export default {
parseRoute,
isRoute
}
+46
View File
@@ -0,0 +1,46 @@
import { IResponseRoute, IRoute, parseRoute } from "./route";
export interface IStop {
gtfsId: string;
name: string;
code: string;
routes: IRoute[];
}
export const isStop = (obj: any): obj is IStop => {
if (
"name" in obj &&
"gtfsId" in obj &&
"code" in obj &&
"routes" in obj
) {
return true;
}
return false;
}
export const parseStop = (obj: any): IStop | undefined => {
if (!obj.patterns) {
console.error("Incorrect query response, no patterns", obj);
return;
}
const patterns: IResponseRoute[] = obj.patterns;
const routes: IRoute[] = patterns.map(route => {
return parseRoute(route);
}).filter((route): route is IRoute => route != null);
// TODO all values are not typechecked
const stop: IStop = {
gtfsId: obj.gtfsId,
name: obj.name,
code: obj.code,
routes: routes
}
return stop;
}
export default {
isStop,
parseStop
}
View File
+19 -4
View File
@@ -1,5 +1,5 @@
import express from "express";
import { queryStop, IStop } from "./query";
import { queryStopById } from "./query";
const PORT: Number = 5000;
@@ -12,9 +12,24 @@ api.get("/", (_req: express.Request, res: express.Response) => {
res.send("Moi");
});
api.get("/stops", async (_req, res) => {
const stop: IStop = await queryStop(10);
res.send(stop);
api.get("/bus", async (_req, res) => {
const busStop = await queryStopById("HSL:1220106");
if (busStop) {
res.send(busStop);
return;
}
res.send({"message": "No stops found"});
return;
});
api.get("/tram", async (_req, res) => {
const tramStop = await queryStopById("HSL:1220419");
if (tramStop) {
res.send(tramStop);
return;
}
res.send({"message": "No stops found"});
return;
});
api.listen(PORT, () => {
+48 -25
View File
@@ -1,29 +1,14 @@
import config from "./utils/config";
import { IStop, parseStop } from "./controllers/stop";
const API_KEY: string = "25e625c8546141aa83b21b9ba94d4847";
const API_URL_BASE: string = "https://api.digitransit.fi/routing/v1/routers/hsl/index/graphql";
const API_URL: string = `${API_URL_BASE}?digitransit-subscription-key=${API_KEY}`;
export interface IStop {
id: number;
name: string;
}
const API_URL: string = `${API_URL_BASE}?digitransit-subscription-key=${config.API_KEY}`;
export const queryStop = async (stopId: number): Promise<IStop> => {
console.log("Querying the HSL-api for stop", stopId);
console.log(API_URL);
const query: string = `
{
stops(name: "mäkelänrinne") {
gtfsId
name
code
lat
lon
}
}`
const queryDigitransit = async (query: string) => {
console.log("Querying the HSL-api with query", query);
const response = await fetch(API_URL, {
method: "post",
@@ -32,15 +17,53 @@ export const queryStop = async (stopId: number): Promise<IStop> => {
},
body: JSON.stringify({ query })
});
const parsed_res = await response.json();
console.log(parsed_res);
return parsed_res.data;
}
export const queryStopById = async (stopId: string): Promise<IStop | undefined> => {
console.info("Querying the HSL-api for stop", stopId);
console.debug(API_URL);
const query: string = `
{
stop(id: "${stopId}") {
gtfsId
name
code
patterns {
code
directionId
headsign
route {
gtfsId
shortName
longName
mode
}
}
}
}`
const stop: IStop = {
id: stopId,
name: "TOOO"
const response = await queryDigitransit(query);
if (!response) {
console.error("No response from API");
return;
}
return stop;
if (!response.stop || !response.stop.patterns) {
console.error("Incorrect response from API", response);
return;
}
const stop: IStop | undefined = parseStop(response.stop);
if (stop) {
console.debug("Parsed stop:", stop);
return stop;
}
console.error("Failed parsing stop", stop);
return;
};
+12
View File
@@ -0,0 +1,12 @@
import "dotenv/config";
if (process.env.API_KEY == undefined) {
console.error("FATAL ERROR: API_KEY not set");
process.exit(1);
}
export const API_KEY = process.env.API_KEY;
export default { API_KEY };
+5
View File
@@ -316,6 +316,11 @@ diff@^4.0.1:
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
dotenv@^16.4.5:
version "16.4.5"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"