move repositories and loaders to directories

This commit is contained in:
2025-01-06 18:13:09 -08:00
parent a1f4beb762
commit 588a2b18ad
6 changed files with 6 additions and 6 deletions

View File

@@ -0,0 +1,101 @@
// If types match closely, we can use TypeScript "casting"
// to convert from data repo to GraphQL schema
export interface IEntityWithId {
id: string;
}
export interface ISystem extends IEntityWithId {
name: string;
}
export interface ICoordinates {
latitude: number;
longitude: number;
}
export interface IRoute extends IEntityWithId {
name: string;
color: string;
polylineCoordinates: ICoordinates[];
systemId: string;
}
export interface IStop extends IEntityWithId {
name: string;
systemId: string;
coordinates: ICoordinates;
}
export interface IShuttle extends IEntityWithId {
coordinates: ICoordinates;
name: string;
routeId: string;
systemId: string;
}
export interface IEta {
secondsRemaining: number;
shuttleId: string;
stopId: string;
}
export interface IOrderedStop {
nextStop?: IOrderedStop;
previousStop?: IOrderedStop;
routeId: string;
stopId: string;
position: number;
}
/**
* Repository interface for data derived from Passio API.
* The repository is not designed to have write locks in place.
* Objects passed from/to the repository should be treated
* as disposable.
*/
export interface Repository {
// Getter methods
getSystems(): Promise<ISystem[]>;
getSystemById(systemId: string): Promise<ISystem | null>;
getStopsBySystemId(systemId: string): Promise<IStop[]>;
getStopById(stopId: string): Promise<IStop | null>;
getRoutesBySystemId(systemId: string): Promise<IRoute[]>;
getRouteById(routeId: string): Promise<IRoute | null>;
getShuttlesBySystemId(systemId: string): Promise<IShuttle[]>;
getShuttleById(shuttleId: string): Promise<IShuttle | null>;
getShuttlesByRouteId(routeId: string): Promise<IShuttle[]>;
getEtasForShuttleId(shuttleId: string): Promise<IEta[]>;
getEtasForStopId(stopId: string): Promise<IEta[]>;
getEtaForShuttleAndStopId(shuttleId: string, stopId: string): Promise<IEta | null>;
getOrderedStopByRouteAndStopId(routeId: string, stopId: string): Promise<IOrderedStop | null>;
/**
* Get ordered stops with the given stop ID.
* Returns an empty array if no ordered stops found.
* @param stopId
*/
getOrderedStopsByStopId(stopId: string): Promise<IOrderedStop[]>;
/**
* Get ordered stops with the given route ID.
* Returns an empty array if no ordered stops found.
* @param routeId
*/
getOrderedStopsByRouteId(routeId: string): Promise<IOrderedStop[]>;
// Setter methods
addOrUpdateSystem(system: ISystem): Promise<void>;
addOrUpdateRoute(route: IRoute): Promise<void>;
addOrUpdateShuttle(shuttle: IShuttle): Promise<void>;
addOrUpdateStop(stop: IStop): Promise<void>;
addOrUpdateOrderedStop(orderedStop: IOrderedStop): Promise<void>;
addOrUpdateEta(eta: IEta): Promise<void>;
}

View File

@@ -0,0 +1,141 @@
import { IEntityWithId, IEta, IOrderedStop, IRoute, IShuttle, IStop, ISystem, Repository } from "./repository";
/**
* An unoptimized in memory repository.
* (I would optimize it with actual data structures, but I'm
* switching to another data store later anyways)
*/
export class UnoptimizedInMemoryRepository implements Repository {
private systems: ISystem[] = [];
private stops: IStop[] = [];
private routes: IRoute[] = [];
private shuttles: IShuttle[] = [];
private etas: IEta[] = [];
private orderedStops: IOrderedStop[] = [];
public async getSystems() {
return this.systems;
}
public async getSystemById(systemId: string) {
return this.findEntityById(systemId, this.systems);
}
public async getStopsBySystemId(systemId: string) {
return this.stops.filter(stop => stop.systemId === systemId);
}
public async getStopById(stopId: string) {
return this.findEntityById(stopId, this.stops);
}
public async getRoutesBySystemId(systemId: string) {
return this.routes.filter(route => route.systemId === systemId);
}
public async getRouteById(routeId: string) {
return this.findEntityById(routeId, this.routes);
}
public async getShuttlesBySystemId(systemId: string) {
return this.shuttles.filter(shuttle => shuttle.systemId === systemId);
}
public async getShuttlesByRouteId(routeId: string) {
return this.shuttles.filter(shuttle => shuttle.routeId === routeId);
}
public async getShuttleById(shuttleId: string) {
return this.findEntityById(shuttleId, this.shuttles);
}
public async getEtasForShuttleId(shuttleId: string) {
return this.etas.filter(eta => eta.shuttleId === shuttleId);
}
public async getEtasForStopId(stopId: string) {
return this.etas.filter(eta => eta.stopId === stopId);
}
public async getEtaForShuttleAndStopId(shuttleId: string, stopId: string) {
return this.findEntityByMatcher<IEta>((value) => value.stopId === stopId && value.shuttleId === shuttleId, this.etas);
}
public async getOrderedStopByRouteAndStopId(routeId: string, stopId: string) {
return this.findEntityByMatcher<IOrderedStop>((value) => value.routeId === routeId && value.stopId === stopId, this.orderedStops)
}
public async getOrderedStopsByStopId(stopId: string) {
return this.orderedStops.filter((value) => value.stopId === stopId);
}
public async getOrderedStopsByRouteId(routeId: string) {
return this.orderedStops.filter((value) => value.routeId === routeId);
}
private findEntityById<T extends IEntityWithId>(entityId: string, arrayToSearchIn: T[]) {
return this.findEntityByMatcher((value) => value.id === entityId, arrayToSearchIn);
}
private findEntityByMatcher<T>(callback: (value: T) => boolean, arrayToSearchIn: T[]): T | null {
const entity = arrayToSearchIn.find(callback);
if (!entity) {
return null;
}
return entity;
}
public async addOrUpdateSystem(system: ISystem): Promise<void> {
const index = this.systems.findIndex((s) => s.id === system.id);
if (index !== -1) {
this.systems[index] = system; // Update existing
} else {
this.systems.push(system); // Add new
}
}
public async addOrUpdateRoute(route: IRoute): Promise<void> {
const index = this.routes.findIndex((r) => r.id === route.id);
if (index !== -1) {
this.routes[index] = route;
} else {
this.routes.push(route);
}
}
public async addOrUpdateShuttle(shuttle: IShuttle): Promise<void> {
const index = this.shuttles.findIndex((s) => s.id === shuttle.id);
if (index !== -1) {
this.shuttles[index] = shuttle;
} else {
this.shuttles.push(shuttle);
}
}
public async addOrUpdateStop(stop: IStop): Promise<void> {
const index = this.stops.findIndex((s) => s.id === stop.id);
if (index !== -1) {
this.stops[index] = stop;
} else {
this.stops.push(stop);
}
}
public async addOrUpdateOrderedStop(orderedStop: IOrderedStop): Promise<void> {
const index = this.orderedStops.findIndex((value) => value.stopId === orderedStop.stopId && value.routeId === orderedStop.routeId);
if (index !== -1) {
this.orderedStops[index] = orderedStop;
} else {
this.orderedStops.push(orderedStop);
}
}
public async addOrUpdateEta(eta: IEta): Promise<void> {
const index = this.etas.findIndex((e) => e.stopId === eta.stopId && e.shuttleId === eta.shuttleId);
if (index !== -1) {
this.etas[index] = eta;
} else {
this.etas.push(eta);
}
}
}