BinghamtonBetterBus-v2/src/server/index.ts
Levi Lesches c878d08c23
Move data parsing definitions out of the client (#11)
Makes a new (dart) package called `shared`, which contains: 
- the code needed to parse through OCCT and BC data
- any data definitions for types in that data (eg, stops)
- shared utils

The client will then import types from this package. This PR also re-generates the GET_STOPS json file to include OCCT
2025-05-02 02:10:57 -04:00

203 lines
6.5 KiB
TypeScript

import { Router } from "@oak/acorn";
import { db_setup, select_closest } from "./db.ts";
import { DatabaseSync } from "node:sqlite";
import { cors_add, json_mime_add, substitute_base_name_ } from "./utils.ts";
import { assert } from "@std/assert";
import neo4j from "https://deno.land/x/neo4j_driver_lite@5.28.1/mod.ts";
import { graph_setup } from "./graph.ts";
const usingDocker = !Deno.env.has("DISABLE_DOCKER");
const root_url: string = usingDocker
? Deno.env.get("ROOT_URL") as string
: "http://localhost:8080/api";
console.log(`Running in docker configuration? ${usingDocker}`);
assert(root_url, "ROOT_URL env var not defined");
// bind values we're actually using
const substitute_base_name = substitute_base_name_.bind(
null,
/\$base_domain/,
root_url,
);
const { hostname, port } = { hostname: "0.0.0.0", port: 80 };
const neo4jHost = usingDocker ? "neo4j" : "127.0.0.1"; // localhost does NOT work
const graph_driver = neo4j.driver(
`neo4j://${neo4jHost}:7687`,
neo4j.auth.basic("neo4j", "your_password"),
);
console.log("initializing graph with static data");
await graph_setup(graph_driver);
console.log("graph initialization complete");
const db = new DatabaseSync(":memory:");
db_setup(db);
const router = new Router();
const trip_list = (async () => {
let lst = [];
// could be a static file but I'm lazy
for await (const dirEntry of Deno.readDir("trips")) {
lst.push(dirEntry.name);
}
lst = lst.map((name) => URL.parse(root_url + `/trips/${name}`));
return lst;
})();
router.get(
"/trips",
async (_) => {
const headers = new Headers();
json_mime_add(headers);
cors_add(headers);
return new Response(JSON.stringify(await trip_list), { headers });
},
);
router.get(
"/trips/:id",
async (ctx) => {
const { params: { id } } = ctx;
try {
const bytes = await Deno.readFile(`trips/${id}`);
const body = substitute_base_name(bytes);
const headers = new Headers();
json_mime_add(headers);
cors_add(headers);
return new Response(body, { headers });
} catch (_) {
return new Response("", { status: 404 });
}
},
);
router.get(
"/stops",
async (_ctx) => {
try {
const bytes = await Deno.readFile(`GET_STOPS.json`);
const headers = new Headers();
json_mime_add(headers);
cors_add(headers);
return new Response(bytes, { headers });
} catch (_) {
return new Response("", { status: 404 });
}
},
);
router.get(
"/stops/:id",
async (ctx) => {
const { params: { id } } = ctx;
try {
const bytes = await Deno.readFile(`stops/${id}`);
const body = substitute_base_name(bytes);
const headers = new Headers();
json_mime_add(headers);
cors_add(headers);
return new Response(body, { headers });
} catch (_) {
return new Response("", { status: 404 });
}
},
);
const hub =
(db.prepare("select href from hub_stops where hub='BCT';").get() as {
href: string;
}).href;
assert(hub !== undefined, "hub please");
router.get(
"/path",
async (ctx) => {
const query = await ctx.queryParams();
if (!query) return new Response("no query params", { status: 400 });
const s_lattitude = query["start_lat"];
const s_longitude = query["start_lon"];
const e_lattitude = query["end_lat"];
const e_longitude = query["end_lon"];
const _time = query["time"];
if (
typeof s_lattitude != "string" || typeof s_longitude != "string" ||
typeof e_lattitude != "string" || typeof e_longitude != "string" ||
typeof _time != "string"
) {
return new Response("missing or invalid query params", { status: 400 });
}
const start = select_closest(db, {
lat: Number(s_lattitude),
lon: Number(s_longitude),
}, 1);
const mid = hub;
const end = select_closest(db, {
lat: Number(e_lattitude),
lon: Number(e_longitude),
}, 1);
const headers = new Headers();
json_mime_add(headers);
cors_add(headers);
const r = {
path: [
{
trip: {
href: `${root_url}/trips/BCT_R51_inb_T08`,
polyline:
"ivz_GtswmMEQo@P]Ko@_Dg@gByBfCcBjBWX]^Ua@[u@uFdGqErFoDxDiIrIaG|FwGlFyCvCo@r@{@tAq@vAu@vBy@~C_CbJaBhFgF`SY~@YNi@?cDuA_@u@NqAf@{@lAw@vAArBl@jGxB`DlARt@iAnF_BrCi@tBl@Vl@}BEw@p@iAPw@zAaHLYNG|BbArAp@XBNGPOb@{AtAiF@o@s@c@}E}Bg@QS~AzCnALe@X[t@\\r@\\RR?XKr@g@fB_AfDOR[B{@_@aAg@_Bs@_@PWV]FsLeEiCs@eAHaAd@w@xA]jAk@h@uAYKYDs@q@MMCGQ@O?c@_B_@Uj@]P[g@[q@YiAg@sHMmAy@_C}@wCuD{Ja@wA@mAbBkElAyDZuD\\iD^mAh@s@`DcCfBoDzA_DXeBr@iNZoHKkA}@kB{@i@}@QmERmBBw@Om@_@g@c@m@m@Y_AScAImABmAHs@RMFWIc@YIS^H`AGtBVhC^jA|@fAfAj@x@T`JSb@Pn@Zf@bA^tAQjFm@vLQhD]nAoAnCiBhDiDdCk@`ASv@y@fIUzAqBlFmA|BxF`QjHyFo@eAeAqBM{@Hu@Pe@|CaGhCwD\\_@bA}Ah@qAdAiDjAqDtAqDd@q@jAo@~Ce@`DE~CCjAl@hAzBl@pBd@xC@hCY~Co@fBeCrGgB~BcAjA}A|BoErIuBnEm@`Au@b@yANaASuAcA_DbEi@bASzACdBEbDo@pBLT|@b@rKrBbAf@\\^Jp@]~AsFdVqBfI_Kx_@sAlH}@xIk@dHOpCEjCAd@P|IXdLZlDf@tD`DnR\\vCLjDEpFa@~Fs@rI}CrVSdDKhG@pVR|Td@|k@BbQTj@|C~Cl@|DlD|TPjAfBpIp@~EvBhL|BpLxAnIaC|@gE`BL`A`@tB]t@SCaBu@iB{@iDqALhDFzC~Bb@nAg@hCh@p@J",
},
enter_bus: {
href: `${root_url}/stops/BCT_95103`,
latitude: 42.101991,
longitude: -75.83611,
time: "00:00",
},
exit_bus: {
href: `${root_url}/stops/BCT_1`,
latitude: 42.101354,
longitude: -75.910801,
time: "00:00",
},
},
{
trip: {
href: `${root_url}/trips/BCT_R28otb_T11`,
polyline:
"az}_GvjinM}KiBQsHw@y@oDiEmFeGgFcGyAcB_@c@HcA^qL^gL@w@UyFMcIEkBi@aTi@aREmBCeAi@D_Id@sJl@{GZsRnAw@DASUsLGgBI]MUc@a@UEWBw@Vw@j@y@Nc@FYBj@jFJfAkDx@qAVcA^UFFfCD`AnIc@jH]pIi@rDSzJk@vKo@fDQbF[Di@a@oN_@mNe@eMs@qSW_Ha@{L[}Ie@mL_@mJBoAPyA^iATm@T_@R]l@_@zCgA`@QrBfEVLlATN^D^HPL?XGLQN[CYQQUBS@W@SCoAUSSUc@wAaDkA`@{@^gA`@m@^g@hAa@z@Wv@MrABp@L~FPjDXbI^fLPbEHhDd@tMd@pMj@jNP~GLbFVnK\\pJVfJHpDJrERzGH`FJdENlHN`DCbCUbHEbBQ`GObDGr@|@hA|DlE`F`GvDhE`DnDRrHrDf@Xo@nCl@",
},
enter_bus: {
href: `${root_url}/stops/BCT_2802`,
latitude: 42.100982,
longitude: -75.91097,
time: "00:00",
},
exit_bus: {
href: `${root_url}/stops/BCT_2804`,
latitude: 42.105488,
longitude: -75.906281,
time: "00:00",
},
},
],
_legit: [
start,
mid,
end,
],
};
return new Response(
JSON.stringify(r),
{ headers },
);
},
);
console.log(`Ready! Listening on ${hostname}:${port}`);
router.listen({ hostname, port });