From 2edc8579ed5d07c583d743b4cc8d0b73a1adda98 Mon Sep 17 00:00:00 2001 From: Asgeir Jacobsen Date: Thu, 8 Oct 2026 12:03:32 +0200 Subject: [PATCH 1/3] Feat: add sighting types and queries to schema Defines the Sighting type, a query for one sighting by id and a query for a list with search, filter, sort and cursor pagination. Documents the pagination choice in the README. --- README.md | 23 +++++++++++++-- backend/src/schema.ts | 69 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 84 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 0558ad5..f082b1b 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,10 @@ Repository for team IT2810-H26-T25 in IT2810-H26. 2. [Working in this repository](#working-in-this-repository) 3. [Project Description](#project-description) 4. [Planned Functionality](#planned-functionality) -5. [Stored User-Generated Data](#stored-user-generated-data) -6. [Technology Choices](#technology-choices) -7. [AI Usage](#ai-usage) +5. [GraphQL API Design](#graphql-api-design) +6. [Stored User-Generated Data](#stored-user-generated-data) +7. [Technology Choices](#technology-choices) +8. [AI Usage](#ai-usage) ## Running the Project @@ -108,6 +109,22 @@ replaced by GraphQL queries against the backend, so that sorting and filtering always cover the whole dataset and not only what has been loaded in the browser. +## GraphQL API Design + +The schema is in `backend/src/schema.ts`. It is a proposal: the resolvers and +database connection are not written yet, so only `health` returns data. + +- `sighting(id)` returns one sighting, or null if it does not exist. +- `sightings(search, filter, sort, first, after)` returns a page of sightings + with `totalCount` and `pageInfo`. Search matches city, shape and comments. + Filters are shape, country, state and a date range. Sort is date (newest or + oldest), city or shape. All of it runs in the database. + +**Pagination: cursor based "load more".** With about 80,000 rows, `LIMIT/OFFSET` +gets slower the further you page, while a cursor continues from where the last +page ended. It also fits a "load more" button, so the client only downloads +what it shows, and Apollo Client can merge the pages into one list. The trade-off is that users cannot jump to a specific page. + ## Stored User-Generated Data The main data users create are their own sighting reports. A report will have diff --git a/backend/src/schema.ts b/backend/src/schema.ts index 40df036..c22667a 100644 --- a/backend/src/schema.ts +++ b/backend/src/schema.ts @@ -1,12 +1,71 @@ -/** - * Placeholder schema that only proves the server is running. The real - * Sighting types and queries will be agreed on by the group and added - * in a separate issue. - */ export const typeDefs = `#graphql + "A single UFO sighting report." + type Sighting { + id: ID! + "ISO 8601, treated as UTC." + datetime: String + city: String! + state: String + country: String + shape: String + durationSeconds: Int + comments: String + datePosted: String + latitude: Float + longitude: Float + } + + enum SightingSort { + DATE_DESC + DATE_ASC + CITY_ASC + SHAPE_ASC + } + + "All fields are optional and combined with AND." + input SightingFilter { + shape: String + country: String + state: String + "ISO 8601 date, inclusive." + dateFrom: String + "ISO 8601 date, inclusive." + dateTo: String + } + + type SightingEdge { + "Opaque. Pass it as \`after\` to get the next page." + cursor: String! + node: Sighting! + } + + type PageInfo { + hasNextPage: Boolean! + endCursor: String + } + + type SightingConnection { + edges: [SightingEdge!]! + pageInfo: PageInfo! + "Number of matches across all pages." + totalCount: Int! + } + type Query { "Returns \\"ok\\" when the server is up." health: String! + + "Returns null if the id does not exist." + sighting(id: ID!): Sighting + + "\`search\` matches city, shape and comments. \`first\` is limited to 1-100." + sightings( + search: String + filter: SightingFilter + sort: SightingSort = DATE_DESC + first: Int = 20 + after: String + ): SightingConnection! } ` From 70ecb702fde6b8be66791f5dbdc00b28105fd23f Mon Sep 17 00:00:00 2001 From: Asgeir Jacobsen Date: Thu, 8 Oct 2026 12:21:37 +0200 Subject: [PATCH 2/3] Fix: make Sighting.city nullable --- backend/src/schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/schema.ts b/backend/src/schema.ts index c22667a..16e6da1 100644 --- a/backend/src/schema.ts +++ b/backend/src/schema.ts @@ -4,7 +4,7 @@ export const typeDefs = `#graphql id: ID! "ISO 8601, treated as UTC." datetime: String - city: String! + city: String state: String country: String shape: String From 78d3ca4fb155e8a1bf3836c5b082370231a0865c Mon Sep 17 00:00:00 2001 From: Asgeir Jacobsen Date: Thu, 8 Oct 2026 12:24:33 +0200 Subject: [PATCH 3/3] Fix: make city nullable and datetime local time --- backend/src/schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/schema.ts b/backend/src/schema.ts index 16e6da1..1ac4e56 100644 --- a/backend/src/schema.ts +++ b/backend/src/schema.ts @@ -2,7 +2,7 @@ export const typeDefs = `#graphql "A single UFO sighting report." type Sighting { id: ID! - "ISO 8601, treated as UTC." + "Local time where it was seen, no timezone, e.g. 2005-01-01T00:30:00." datetime: String city: String state: String