-
Notifications
You must be signed in to change notification settings - Fork 1
Api round trip endpoint #121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import { createZodDto } from 'nestjs-zod'; | ||
| import { z } from 'zod'; | ||
|
|
||
| const RoundTripQuerySchema = z.object({ | ||
| orgStopId: z.string().min(1, 'Origin stop ID is required'), | ||
| destStopId: z.string().min(1, 'Destination stop ID is required'), | ||
| date: z | ||
| .string() | ||
| .regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be in YYYY-MM-DD format'), | ||
| }); | ||
|
|
||
| export class RoundTripQueryDto extends createZodDto(RoundTripQuerySchema) {} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import { Controller, Get, Query } from '@nestjs/common'; | ||
| import { InjectRepository } from '@mikro-orm/nestjs'; | ||
| import { EntityRepository } from '@mikro-orm/postgresql'; | ||
| import { GTFSStopTime } from '../entities'; | ||
| import { RoundTripQueryDto } from './dto/round-trip.dto'; | ||
| import { ApiTags, ApiOkResponse } from '@nestjs/swagger'; | ||
|
|
||
| @Controller('round_trip') | ||
| @ApiTags('GTFS - Round Trip') | ||
| export class RoundTripController { | ||
| constructor( | ||
| @InjectRepository(GTFSStopTime) | ||
| private readonly stopTimeRepository: EntityRepository<GTFSStopTime>, | ||
| ) {} | ||
|
|
||
| @Get() | ||
| @ApiOkResponse({ | ||
| description: 'Returns stop times for origin and destination stops', | ||
| }) | ||
| async getRoundTrip(@Query() query: RoundTripQueryDto) { | ||
| const targetDate = new Date(query.date); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct me if I'm wrong, but it seems like the logic here would be just getting any time of any bus/train that is stopped at the specified stop, regardless of direction and where it's headed.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Parsing the YYYY-MM-DD string with |
||
|
|
||
| const orgStopTimes = await this.stopTimeRepository.find( | ||
| { | ||
| stop: { stopid: query.orgStopId }, | ||
| trip: { | ||
| calendarDate: { | ||
| date: targetDate, | ||
| }, | ||
| }, | ||
| }, | ||
| { | ||
| populate: ['trip', 'stop'], | ||
| orderBy: { departureTime: 'ASC' }, | ||
| }, | ||
| ); | ||
|
|
||
| const destStopTimes = await this.stopTimeRepository.find( | ||
| { | ||
| stop: { stopid: query.destStopId }, | ||
| trip: { | ||
| calendarDate: { | ||
| date: targetDate, | ||
| }, | ||
| }, | ||
| }, | ||
| { | ||
| populate: ['trip', 'stop'], | ||
| orderBy: { departureTime: 'ASC' }, | ||
| }, | ||
| ); | ||
|
Comment on lines
+23
to
+51
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right now we fetch origin and destination stop times separately, so the client could accidentally pair different trips or the wrong direction. Could we query trips that contain both stops, ensure the origin stop_sequence is before the destination’s, and (if available) match direction/headsign? Also, we should skip trips canceled for that date (exceptionType=2). |
||
|
|
||
| return { | ||
| orgStopTimes: orgStopTimes.map((st) => ({ | ||
| id: st.id, | ||
| trip_id: st.trip.trip_id, | ||
| arrival_time: st.arrivalTime as unknown as string, | ||
| departure_time: st.departureTime as unknown as string, | ||
| stop_id: st.stop.stopid, | ||
| })), | ||
| destStopTimes: destStopTimes.map((st) => ({ | ||
| id: st.id, | ||
| trip_id: st.trip.trip_id, | ||
| arrival_time: st.arrivalTime as unknown as string, | ||
| departure_time: st.departureTime as unknown as string, | ||
| stop_id: st.stop.stopid, | ||
| })), | ||
| }; | ||
|
Comment on lines
+53
to
+68
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We return two arrays and the client has to match them up. Could we instead return a list of matched trips, each with its origin/destination times, sorted by origin departure? That would make the endpoint easier to use. |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should block origin and destination from being the same stop. Zod can do this with a refine/superRefine. We could also add a safer date parse/validation so we don’t accept a bad date that later becomes
Invalid Date.