From 5fe66c15174758dc86c9d6ec020f20840dc6b869 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 23 Jan 2025 03:23:15 -0800 Subject: [PATCH 1/5] create updated schema with required IDs --- schema.graphqls | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/schema.graphqls b/schema.graphqls index d2105a3..3d26683 100644 --- a/schema.graphqls +++ b/schema.graphqls @@ -26,8 +26,10 @@ type Route { type OrderedStop { nextStop: OrderedStop previousStop: OrderedStop - route: Route! - stop: Stop! + route: Route + routeId: ID! + stop: Stop + stopId: ID! } type Stop { @@ -44,8 +46,10 @@ type Coordinates { } type ETA { - stop: Stop! - shuttle: Shuttle! + stop: Stop + stopId: ID! + shuttle: Shuttle + shuttleId: ID! secondsRemaining: Float! } @@ -54,6 +58,7 @@ type Shuttle { id: ID!, coordinates: Coordinates! route: Route + routeId: ID! etas: [ETA!] eta(forStopId: ID): ETA } From 36d1a24484e9fc15801dc2d460a7513e123e3028 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 23 Jan 2025 03:26:59 -0800 Subject: [PATCH 2/5] update resolvers for updated schema --- src/resolvers.ts | 135 +++++++++++++++-------------------------------- 1 file changed, 43 insertions(+), 92 deletions(-) diff --git a/src/resolvers.ts b/src/resolvers.ts index 29cf156..24718ac 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -1,4 +1,4 @@ -import { Coordinates, Eta, OrderedStop, Resolvers, Route, Shuttle, Stop, System } from "./generated/graphql"; +import { Coordinates, Eta, OrderedStop, Resolvers } from "./generated/graphql"; import { ServerContext } from "./ServerContext"; export const resolvers: Resolvers = { @@ -26,18 +26,7 @@ export const resolvers: Resolvers = { }, System: { routes: async (parent, args, contextValue, info) => { - const routes = await contextValue.repository.getRoutesBySystemId(parent.id); - return routes.map(({ - color, - id, - name, - polylineCoordinates, - }) => ({ - color, - id, - name, - polylineCoordinates, - })); + return await contextValue.repository.getRoutesBySystemId(parent.id); }, stops: async (parent, args, contextValue, info) => { const stops = await contextValue.repository.getStopsBySystemId(parent.id); @@ -80,11 +69,7 @@ export const resolvers: Resolvers = { const shuttle = await contextValue.repository.getShuttleById(args.id); if (shuttle === null) return null; - return { - coordinates: shuttle.coordinates as Coordinates, - id: shuttle.id, - name: shuttle.name, - }; + return shuttle; }, shuttles: async (parent, args, contextValue, info) => { const shuttles = await contextValue.repository.getShuttlesBySystemId(parent.id); @@ -93,6 +78,7 @@ export const resolvers: Resolvers = { coordinates: shuttle.coordinates, name: shuttle.name, id: shuttle.id, + routeId: shuttle.routeId, })); } }, @@ -108,6 +94,7 @@ export const resolvers: Resolvers = { coordinates: coordinates as Coordinates, name, route: parent, + routeId: parent.id, id, })); }, @@ -120,11 +107,8 @@ export const resolvers: Resolvers = { if (!stop) return null; return { - stop: { - id: stop.id, - name: stop.name, - coordinates: stop.coordinates as Coordinates, - }, + stopId: args.forStopId, + routeId: parent.id, route: parent, } }, @@ -135,16 +119,10 @@ export const resolvers: Resolvers = { const etaForStopId = await contextValue.repository.getEtaForShuttleAndStopId(parent.id, args.forStopId); if (etaForStopId === null) return null; - const stop = await contextValue.repository.getStopById(etaForStopId.stopId); - if (stop === null) return null; - return { - stop: { - coordinates: stop.coordinates, - id: stop.id, - name: stop.name, - }, + stopId: args.forStopId, secondsRemaining: etaForStopId.secondsRemaining, + shuttleId: parent.id, shuttle: parent, }; }, @@ -156,17 +134,11 @@ export const resolvers: Resolvers = { secondsRemaining, stopId, }): Promise => { - const stop = await contextValue.repository.getStopById(stopId); - if (stop === null) return null; - return { secondsRemaining, - stop: { - coordinates: stop.coordinates, - id: stop.id, - name: stop.name, - }, + stopId, shuttle: parent, + shuttleId: parent.id, } })); @@ -177,10 +149,7 @@ export const resolvers: Resolvers = { return []; }, route: async (parent, args, contextValue, info) => { - const shuttle = await contextValue.repository.getShuttleById(parent.id); - if (shuttle === null) return null; - - const route = await contextValue.repository.getRouteById(shuttle?.routeId); + const route = await contextValue.repository.getRouteById(parent.routeId); if (route === null) return null; return { @@ -193,42 +162,16 @@ export const resolvers: Resolvers = { }, Stop: { orderedStops: async (parent, args, contextValue, info) => { - const orderedStops = await contextValue.repository.getOrderedStopsByStopId(parent.id); - - const computedOrderedStops = await Promise.all(orderedStops.map(async ({ - routeId, - stopId, - }): Promise => { - const stop = await contextValue.repository.getStopById(stopId); - const route = await contextValue.repository.getRouteById(routeId); - if (stop === null || route === null) return null; - - return { - stop: { - coordinates: stop.coordinates, - id: stop.id, - name: stop.name, - }, - route: { - name: route.name, - id: route.id, - polylineCoordinates: route.polylineCoordinates, - color: route.color, - }, - }; - })); - - if (computedOrderedStops.every((value) => value !== null)) { - return computedOrderedStops as OrderedStop[]; - } - - return []; - } + return await contextValue.repository.getOrderedStopsByStopId(parent.id); + }, + etas: async (parent, args, contextValue, info) => { + return await contextValue.repository.getEtasForStopId(parent.id); + }, }, OrderedStop: { nextStop: async (parent, args, contextValue, info): Promise => { - const routeId = parent.route.id; - const stopId = parent.stop.id; + const routeId = parent.routeId; + const stopId = parent.stopId; const currentOrderedStop = await contextValue.repository.getOrderedStopByRouteAndStopId(routeId, stopId); if (!currentOrderedStop) return null; @@ -236,21 +179,18 @@ export const resolvers: Resolvers = { const nextOrderedStop = currentOrderedStop.nextStop; if (!nextOrderedStop) return null; - const nextStopObject = await contextValue.repository.getStopById(nextOrderedStop.stopId); - if (!nextStopObject) return null; + const nextOrderedStopObject = await contextValue.repository.getStopById(nextOrderedStop.stopId); + if (!nextOrderedStopObject) return null; return { route: parent.route, - stop: { - coordinates: nextStopObject.coordinates as Coordinates, - id: nextStopObject.id, - name: nextStopObject.name, - } + routeId: parent.routeId, + stopId: nextOrderedStopObject.id, } }, previousStop: async (parent, args, contextValue, info): Promise => { - const routeId = parent.route.id; - const stopId = parent.stop.id; + const routeId = parent.routeId; + const stopId = parent.stopId; const currentOrderedStop = await contextValue.repository.getOrderedStopByRouteAndStopId(routeId, stopId); if (!currentOrderedStop) return null; @@ -258,17 +198,28 @@ export const resolvers: Resolvers = { const previousOrderedStop = currentOrderedStop.previousStop; if (!previousOrderedStop) return null; - const nextStopObject = await contextValue.repository.getStopById(previousOrderedStop.stopId); - if (!nextStopObject) return null; + const previousOrderedStopObject = await contextValue.repository.getStopById(previousOrderedStop.stopId); + if (!previousOrderedStopObject) return null; return { route: parent.route, - stop: { - coordinates: nextStopObject.coordinates as Coordinates, - id: nextStopObject.id, - name: nextStopObject.name, - } + routeId: parent.routeId, + stopId: previousOrderedStopObject.id, } }, + stop: async (parent, args, contextValue, info) => { + return await contextValue.repository.getStopById(parent.stopId); + }, + route: async (parent, args, contextValue, info) => { + return await contextValue.repository.getRouteById(parent.routeId); + }, + }, + ETA: { + stop: async (parent, args, contextValue, info) => { + return await contextValue.repository.getStopById(parent.stopId); + }, + shuttle: async (parent, args, contextValue, info) => { + return await contextValue.repository.getShuttleById(parent.shuttleId); + }, }, }; \ No newline at end of file From d506f9bbfe7083d823505203c47619c86c3a3af0 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 23 Jan 2025 03:33:43 -0800 Subject: [PATCH 3/5] split query resolvers into separate files --- src/index.ts | 4 ++-- src/{resolvers.ts => mergedResolvers.ts} | 26 +++--------------------- src/resolvers/QueryResolvers.ts | 20 ++++++++++++++++++ 3 files changed, 25 insertions(+), 25 deletions(-) rename src/{resolvers.ts => mergedResolvers.ts} (91%) create mode 100644 src/resolvers/QueryResolvers.ts diff --git a/src/index.ts b/src/index.ts index 925c9bc..a515826 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import { readFileSync } from "fs"; import { ApolloServer } from "@apollo/server"; import { startStandaloneServer } from "@apollo/server/standalone"; -import { resolvers } from "./resolvers"; +import { MergedResolvers } from "./resolvers"; import { ServerContext } from "./ServerContext"; import { UnoptimizedInMemoryRepository } from "./repositories/UnoptimizedInMemoryRepository"; import { TimedApiBasedRepositoryLoader } from "./loaders/TimedApiBasedRepositoryLoader"; @@ -11,7 +11,7 @@ const typeDefs = readFileSync("./schema.graphqls", "utf8"); async function main() { const server = new ApolloServer({ typeDefs, - resolvers, + resolvers: MergedResolvers, introspection: process.env.NODE_ENV !== "production", }); diff --git a/src/resolvers.ts b/src/mergedResolvers.ts similarity index 91% rename from src/resolvers.ts rename to src/mergedResolvers.ts index 24718ac..b5b56b2 100644 --- a/src/resolvers.ts +++ b/src/mergedResolvers.ts @@ -1,29 +1,9 @@ import { Coordinates, Eta, OrderedStop, Resolvers } from "./generated/graphql"; import { ServerContext } from "./ServerContext"; +import { QueryResolvers } from "./resolvers/QueryResolvers"; -export const resolvers: Resolvers = { - Query: { - systems: async (parent, args, contextValue, info) => { - const systems = await contextValue.repository.getSystems(); - return systems.map(({ - name, - id - }) => ({ - name, - id - })); - }, - system: async (parent, args, contextValue, info) => { - if (!args.id) return null; - const system = await contextValue.repository.getSystemById(args.id); - if (system === null) return null; - - return { - name: system.name, - id: system.id, - }; - } - }, +export const MergedResolvers: Resolvers = { + ...QueryResolvers, System: { routes: async (parent, args, contextValue, info) => { return await contextValue.repository.getRoutesBySystemId(parent.id); diff --git a/src/resolvers/QueryResolvers.ts b/src/resolvers/QueryResolvers.ts new file mode 100644 index 0000000..8bb439d --- /dev/null +++ b/src/resolvers/QueryResolvers.ts @@ -0,0 +1,20 @@ +import { ServerContext } from "../ServerContext"; +import { Resolvers } from "../generated/graphql"; + +export const QueryResolvers: Resolvers = { + Query: { + systems: async (parent, args, contextValue, info) => { + return await contextValue.repository.getSystems(); + }, + system: async (parent, args, contextValue, info) => { + if (!args.id) return null; + const system = await contextValue.repository.getSystemById(args.id); + if (system === null) return null; + + return { + name: system.name, + id: system.id, + }; + } + }, +} \ No newline at end of file From 718677d6dd44a58050727d0aed2049d1e8830b03 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 23 Jan 2025 03:34:56 -0800 Subject: [PATCH 4/5] fix import error --- src/{mergedResolvers.ts => MergedResolvers.ts} | 0 src/index.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{mergedResolvers.ts => MergedResolvers.ts} (100%) diff --git a/src/mergedResolvers.ts b/src/MergedResolvers.ts similarity index 100% rename from src/mergedResolvers.ts rename to src/MergedResolvers.ts diff --git a/src/index.ts b/src/index.ts index a515826..b90d962 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import { readFileSync } from "fs"; import { ApolloServer } from "@apollo/server"; import { startStandaloneServer } from "@apollo/server/standalone"; -import { MergedResolvers } from "./resolvers"; +import { MergedResolvers } from "./MergedResolvers"; import { ServerContext } from "./ServerContext"; import { UnoptimizedInMemoryRepository } from "./repositories/UnoptimizedInMemoryRepository"; import { TimedApiBasedRepositoryLoader } from "./loaders/TimedApiBasedRepositoryLoader"; From 5813408a36548e3db50ab706f77d0b79ff26ac9d Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Thu, 23 Jan 2025 03:39:50 -0800 Subject: [PATCH 5/5] move other resolvers into their own files --- src/MergedResolvers.ts | 210 ++------------------------ src/resolvers/EtaResolvers.ts | 13 ++ src/resolvers/OrderedStopResolvers.ts | 52 +++++++ src/resolvers/RouteResolvers.ts | 36 +++++ src/resolvers/ShuttleResolvers.ts | 52 +++++++ src/resolvers/StopResolvers.ts | 13 ++ src/resolvers/SystemResolvers.ts | 63 ++++++++ 7 files changed, 241 insertions(+), 198 deletions(-) create mode 100644 src/resolvers/EtaResolvers.ts create mode 100644 src/resolvers/OrderedStopResolvers.ts create mode 100644 src/resolvers/RouteResolvers.ts create mode 100644 src/resolvers/ShuttleResolvers.ts create mode 100644 src/resolvers/StopResolvers.ts create mode 100644 src/resolvers/SystemResolvers.ts diff --git a/src/MergedResolvers.ts b/src/MergedResolvers.ts index b5b56b2..bfa40eb 100644 --- a/src/MergedResolvers.ts +++ b/src/MergedResolvers.ts @@ -1,205 +1,19 @@ import { Coordinates, Eta, OrderedStop, Resolvers } from "./generated/graphql"; import { ServerContext } from "./ServerContext"; import { QueryResolvers } from "./resolvers/QueryResolvers"; +import { SystemResolvers } from "./resolvers/SystemResolvers"; +import { EtaResolvers } from "./resolvers/EtaResolvers"; +import { OrderedStopResolvers } from "./resolvers/OrderedStopResolvers"; +import { StopResolvers } from "./resolvers/StopResolvers"; +import { ShuttleResolvers } from "./resolvers/ShuttleResolvers"; +import { RouteResolvers } from "./resolvers/RouteResolvers"; export const MergedResolvers: Resolvers = { ...QueryResolvers, - System: { - routes: async (parent, args, contextValue, info) => { - return await contextValue.repository.getRoutesBySystemId(parent.id); - }, - stops: async (parent, args, contextValue, info) => { - const stops = await contextValue.repository.getStopsBySystemId(parent.id); - return stops.map(({ - id, - name, - coordinates - }) => ({ - id, - name, - // Both ICoordinates and Coordinates have the same definition - coordinates: coordinates as Coordinates, - })); - }, - stop: async (parent, args, contextValue, info) => { - if (!args.id) return null; - const stop = await contextValue.repository.getStopById(args.id); - if (stop === null) return null; - - return { - id: stop.id, - name: stop.name, - coordinates: stop.coordinates as Coordinates, - }; - }, - route: async (parent, args, contextValue, info) => { - if (!args.id) return null; - const route = await contextValue.repository.getRouteById(args.id); - if (route === null) return null; - - return { - color: route.color, - id: route.id, - name: route.name, - polylineCoordinates: route.polylineCoordinates as Coordinates[], - }; - }, - shuttle: async (parent, args, contextValue, info) => { - if (!args.id) return null; - const shuttle = await contextValue.repository.getShuttleById(args.id); - if (shuttle === null) return null; - - return shuttle; - }, - shuttles: async (parent, args, contextValue, info) => { - const shuttles = await contextValue.repository.getShuttlesBySystemId(parent.id); - - return shuttles.map(shuttle => ({ - coordinates: shuttle.coordinates, - name: shuttle.name, - id: shuttle.id, - routeId: shuttle.routeId, - })); - } - }, - Route: { - shuttles: async (parent, args, contextValue, info) => { - const shuttles = await contextValue.repository.getShuttlesByRouteId(parent.id); - - return shuttles.map(({ - coordinates, - name, - id, - }) => ({ - coordinates: coordinates as Coordinates, - name, - route: parent, - routeId: parent.id, - id, - })); - }, - orderedStop: async (parent, args, contextValue, info) => { - if (!args.forStopId) return null; - const orderedStop = await contextValue.repository.getOrderedStopByRouteAndStopId(parent.id, args.forStopId); - if (!orderedStop) return null; - - const stop = await contextValue.repository.getStopById(orderedStop.stopId); - if (!stop) return null; - - return { - stopId: args.forStopId, - routeId: parent.id, - route: parent, - } - }, - }, - Shuttle: { - eta: async (parent, args, contextValue, info) => { - if (!args.forStopId) return null; - const etaForStopId = await contextValue.repository.getEtaForShuttleAndStopId(parent.id, args.forStopId); - if (etaForStopId === null) return null; - - return { - stopId: args.forStopId, - secondsRemaining: etaForStopId.secondsRemaining, - shuttleId: parent.id, - shuttle: parent, - }; - }, - etas: async (parent, args, contextValue, info) => { - const etasForShuttle = await contextValue.repository.getEtasForShuttleId(parent.id); - if (!etasForShuttle) return null; - - const computedEtas = await Promise.all(etasForShuttle.map(async ({ - secondsRemaining, - stopId, - }): Promise => { - return { - secondsRemaining, - stopId, - shuttle: parent, - shuttleId: parent.id, - } - })); - - if (computedEtas.every((eta) => eta !== null)) { - return computedEtas; - } - - return []; - }, - route: async (parent, args, contextValue, info) => { - const route = await contextValue.repository.getRouteById(parent.routeId); - if (route === null) return null; - - return { - color: route.color, - id: route.id, - name: route.name, - polylineCoordinates: route.polylineCoordinates, - } - } - }, - Stop: { - orderedStops: async (parent, args, contextValue, info) => { - return await contextValue.repository.getOrderedStopsByStopId(parent.id); - }, - etas: async (parent, args, contextValue, info) => { - return await contextValue.repository.getEtasForStopId(parent.id); - }, - }, - OrderedStop: { - nextStop: async (parent, args, contextValue, info): Promise => { - const routeId = parent.routeId; - const stopId = parent.stopId; - - const currentOrderedStop = await contextValue.repository.getOrderedStopByRouteAndStopId(routeId, stopId); - if (!currentOrderedStop) return null; - - const nextOrderedStop = currentOrderedStop.nextStop; - if (!nextOrderedStop) return null; - - const nextOrderedStopObject = await contextValue.repository.getStopById(nextOrderedStop.stopId); - if (!nextOrderedStopObject) return null; - - return { - route: parent.route, - routeId: parent.routeId, - stopId: nextOrderedStopObject.id, - } - }, - previousStop: async (parent, args, contextValue, info): Promise => { - const routeId = parent.routeId; - const stopId = parent.stopId; - - const currentOrderedStop = await contextValue.repository.getOrderedStopByRouteAndStopId(routeId, stopId); - if (!currentOrderedStop) return null; - - const previousOrderedStop = currentOrderedStop.previousStop; - if (!previousOrderedStop) return null; - - const previousOrderedStopObject = await contextValue.repository.getStopById(previousOrderedStop.stopId); - if (!previousOrderedStopObject) return null; - - return { - route: parent.route, - routeId: parent.routeId, - stopId: previousOrderedStopObject.id, - } - }, - stop: async (parent, args, contextValue, info) => { - return await contextValue.repository.getStopById(parent.stopId); - }, - route: async (parent, args, contextValue, info) => { - return await contextValue.repository.getRouteById(parent.routeId); - }, - }, - ETA: { - stop: async (parent, args, contextValue, info) => { - return await contextValue.repository.getStopById(parent.stopId); - }, - shuttle: async (parent, args, contextValue, info) => { - return await contextValue.repository.getShuttleById(parent.shuttleId); - }, - }, + ...SystemResolvers, + ...RouteResolvers, + ...ShuttleResolvers, + ...StopResolvers, + ...OrderedStopResolvers, + ...EtaResolvers, }; \ No newline at end of file diff --git a/src/resolvers/EtaResolvers.ts b/src/resolvers/EtaResolvers.ts new file mode 100644 index 0000000..96bd426 --- /dev/null +++ b/src/resolvers/EtaResolvers.ts @@ -0,0 +1,13 @@ +import { Resolvers } from "../generated/graphql"; +import { ServerContext } from "../ServerContext"; + +export const EtaResolvers: Resolvers = { + ETA: { + stop: async (parent, args, contextValue, info) => { + return await contextValue.repository.getStopById(parent.stopId); + }, + shuttle: async (parent, args, contextValue, info) => { + return await contextValue.repository.getShuttleById(parent.shuttleId); + }, + }, +} \ No newline at end of file diff --git a/src/resolvers/OrderedStopResolvers.ts b/src/resolvers/OrderedStopResolvers.ts new file mode 100644 index 0000000..ad6c8e6 --- /dev/null +++ b/src/resolvers/OrderedStopResolvers.ts @@ -0,0 +1,52 @@ +import { OrderedStop, Resolvers } from "../generated/graphql"; +import { ServerContext } from "../ServerContext"; + +export const OrderedStopResolvers: Resolvers = { + OrderedStop: { + nextStop: async (parent, args, contextValue, info): Promise => { + const routeId = parent.routeId; + const stopId = parent.stopId; + + const currentOrderedStop = await contextValue.repository.getOrderedStopByRouteAndStopId(routeId, stopId); + if (!currentOrderedStop) return null; + + const nextOrderedStop = currentOrderedStop.nextStop; + if (!nextOrderedStop) return null; + + const nextOrderedStopObject = await contextValue.repository.getStopById(nextOrderedStop.stopId); + if (!nextOrderedStopObject) return null; + + return { + route: parent.route, + routeId: parent.routeId, + stopId: nextOrderedStopObject.id, + } + }, + previousStop: async (parent, args, contextValue, info): Promise => { + const routeId = parent.routeId; + const stopId = parent.stopId; + + const currentOrderedStop = await contextValue.repository.getOrderedStopByRouteAndStopId(routeId, stopId); + if (!currentOrderedStop) return null; + + const previousOrderedStop = currentOrderedStop.previousStop; + if (!previousOrderedStop) return null; + + const previousOrderedStopObject = await contextValue.repository.getStopById(previousOrderedStop.stopId); + if (!previousOrderedStopObject) return null; + + return { + route: parent.route, + routeId: parent.routeId, + stopId: previousOrderedStopObject.id, + } + }, + stop: async (parent, args, contextValue, info) => { + return await contextValue.repository.getStopById(parent.stopId); + }, + route: async (parent, args, contextValue, info) => { + return await contextValue.repository.getRouteById(parent.routeId); + }, + }, + +} \ No newline at end of file diff --git a/src/resolvers/RouteResolvers.ts b/src/resolvers/RouteResolvers.ts new file mode 100644 index 0000000..94dc13f --- /dev/null +++ b/src/resolvers/RouteResolvers.ts @@ -0,0 +1,36 @@ +import { Coordinates, Resolvers } from "../generated/graphql"; +import { ServerContext } from "../ServerContext"; + +export const RouteResolvers: Resolvers = { + Route: { + shuttles: async (parent, args, contextValue, info) => { + const shuttles = await contextValue.repository.getShuttlesByRouteId(parent.id); + + return shuttles.map(({ + coordinates, + name, + id, + }) => ({ + coordinates: coordinates as Coordinates, + name, + route: parent, + routeId: parent.id, + id, + })); + }, + orderedStop: async (parent, args, contextValue, info) => { + if (!args.forStopId) return null; + const orderedStop = await contextValue.repository.getOrderedStopByRouteAndStopId(parent.id, args.forStopId); + if (!orderedStop) return null; + + const stop = await contextValue.repository.getStopById(orderedStop.stopId); + if (!stop) return null; + + return { + stopId: args.forStopId, + routeId: parent.id, + route: parent, + } + }, + }, +} \ No newline at end of file diff --git a/src/resolvers/ShuttleResolvers.ts b/src/resolvers/ShuttleResolvers.ts new file mode 100644 index 0000000..2350987 --- /dev/null +++ b/src/resolvers/ShuttleResolvers.ts @@ -0,0 +1,52 @@ +import { Eta, Resolvers } from "../generated/graphql"; +import { ServerContext } from "../ServerContext"; + +export const ShuttleResolvers: Resolvers = { + Shuttle: { + eta: async (parent, args, contextValue, info) => { + if (!args.forStopId) return null; + const etaForStopId = await contextValue.repository.getEtaForShuttleAndStopId(parent.id, args.forStopId); + if (etaForStopId === null) return null; + + return { + stopId: args.forStopId, + secondsRemaining: etaForStopId.secondsRemaining, + shuttleId: parent.id, + shuttle: parent, + }; + }, + etas: async (parent, args, contextValue, info) => { + const etasForShuttle = await contextValue.repository.getEtasForShuttleId(parent.id); + if (!etasForShuttle) return null; + + const computedEtas = await Promise.all(etasForShuttle.map(async ({ + secondsRemaining, + stopId, + }): Promise => { + return { + secondsRemaining, + stopId, + shuttle: parent, + shuttleId: parent.id, + } + })); + + if (computedEtas.every((eta) => eta !== null)) { + return computedEtas; + } + + return []; + }, + route: async (parent, args, contextValue, info) => { + const route = await contextValue.repository.getRouteById(parent.routeId); + if (route === null) return null; + + return { + color: route.color, + id: route.id, + name: route.name, + polylineCoordinates: route.polylineCoordinates, + } + } + }, +} \ No newline at end of file diff --git a/src/resolvers/StopResolvers.ts b/src/resolvers/StopResolvers.ts new file mode 100644 index 0000000..6ccbdf1 --- /dev/null +++ b/src/resolvers/StopResolvers.ts @@ -0,0 +1,13 @@ +import { Resolvers } from "../generated/graphql"; +import { ServerContext } from "../ServerContext"; + +export const StopResolvers: Resolvers = { + Stop: { + orderedStops: async (parent, args, contextValue, info) => { + return await contextValue.repository.getOrderedStopsByStopId(parent.id); + }, + etas: async (parent, args, contextValue, info) => { + return await contextValue.repository.getEtasForStopId(parent.id); + }, + }, +} \ No newline at end of file diff --git a/src/resolvers/SystemResolvers.ts b/src/resolvers/SystemResolvers.ts new file mode 100644 index 0000000..b78e922 --- /dev/null +++ b/src/resolvers/SystemResolvers.ts @@ -0,0 +1,63 @@ +import { Coordinates, Resolvers } from "../generated/graphql"; +import { ServerContext } from "../ServerContext"; + +export const SystemResolvers: Resolvers = { + System: { + routes: async (parent, args, contextValue, info) => { + return await contextValue.repository.getRoutesBySystemId(parent.id); + }, + stops: async (parent, args, contextValue, info) => { + const stops = await contextValue.repository.getStopsBySystemId(parent.id); + return stops.map(({ + id, + name, + coordinates + }) => ({ + id, + name, + // Both ICoordinates and Coordinates have the same definition + coordinates: coordinates as Coordinates, + })); + }, + stop: async (parent, args, contextValue, info) => { + if (!args.id) return null; + const stop = await contextValue.repository.getStopById(args.id); + if (stop === null) return null; + + return { + id: stop.id, + name: stop.name, + coordinates: stop.coordinates as Coordinates, + }; + }, + route: async (parent, args, contextValue, info) => { + if (!args.id) return null; + const route = await contextValue.repository.getRouteById(args.id); + if (route === null) return null; + + return { + color: route.color, + id: route.id, + name: route.name, + polylineCoordinates: route.polylineCoordinates as Coordinates[], + }; + }, + shuttle: async (parent, args, contextValue, info) => { + if (!args.id) return null; + const shuttle = await contextValue.repository.getShuttleById(args.id); + if (shuttle === null) return null; + + return shuttle; + }, + shuttles: async (parent, args, contextValue, info) => { + const shuttles = await contextValue.repository.getShuttlesBySystemId(parent.id); + + return shuttles.map(shuttle => ({ + coordinates: shuttle.coordinates, + name: shuttle.name, + id: shuttle.id, + routeId: shuttle.routeId, + })); + } + }, +} \ No newline at end of file