#Apollo Server + GraphQL + MySQL and TypeScript

5 messages · Page 1 of 1 (latest)

fervent vessel
#

I'm struggling to wrap my head around how exactly type safety can be implemented in a GraphQL Apollo Server

I've used @eddeee888/gcg-typescript-resolver-files to generate a bunch of resolver files using predefined schemas in my project and actually implementing them seems impossible

For example, given a schema like so

type Ticket {
    id: ID!
    ticket_number: Int!
    user: User!
}

type User {
    id: ID!
    first_name: String!
}

type Query {
    ticket(ticket_number: Int!): Ticket
}

and an MySQL database that is

CREATE TABLE ticket (
  id INT NOT NULL,
  ticket_number INT NOT NULL,
  user_id INT NOT NULL,
  PRIMARY KEY (ID)
)

CREATE TABLE user (
  id INT NOT NULL,
  first_name VARCHAR(255) NOT NULL,
  PRIMARY KEY (id)
)

How do I, while maintaining type safety, write the resolvers?? The codegen provides me with a bunch of files for writing my resolvers and I understand what they represent and how I would normally write them - however:

import type { QueryResolvers } from './../../../types.generated';
export const ticket: NonNullable<QueryResolvers['ticket']> = async (_parent, _arg, _ctx) => {
    // expects { id: number, ticket_number: number, user: User } 
};

how can I fulfill the user constraint? I can't use user_id from the database, its a number - not User. I can't leave it empty, its can't be undefined. I don't want to have to get the user data from the database in the ticket resolver - that's not scaleable.
Furthermore, the codegen created a simple User.ts resolver file

import type { UserResolvers } from './../../types.generated';
export const User: UserResolvers = {
    /* Implement User resolver logic here */
};

which I know what it's for, but there's no function of sorts that takes an ID and returns a User.

Am I missing something here, or is this just a standard pain point that I need to overcome somehow? I don't want to remove TypeScript at all

#

What's even more frustrating is the Apollo docs on how nested resolvers work. https://www.apollographql.com/docs/apollo-server/data/resolvers#resolver-chains
The "nested resolver chain" its showing only works because a property that is never null has been annotated as nullable in the schema, allowing the topmost query resolver to leave the field undefined even though it never is.
Since the resolver can leave it undefined, typescript doesn't complain and the resolver for that field can kick in and resolve the the value.
Even more annoying is another "type" they've declared in the schema is actually just a property and not some sort of relationship between two objects at all

thin slate
#

Ur not supposed to build nested objects in the ticket resolver

#

Just return the ticket row (including user_id)

#

let Ticket.user resolve the user separately via the field resolver