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 });