GraphQL without GraphQL

Juho Vepsäläinen

1/34
2/34

What to Expect

  • What is GraphQL?
  • My Experience with GraphQL
  • Schema First Design with GraphQL
  • GraphQL without GraphQL
  • Lessons Learned
3/34

What is GraphQL?

4/34

GraphQL

5/34

GraphQL Schema Definition Language (SDL)

  • A definition language is used to define an API
  • Separate language to describe types and their relations
  • In addition, code implementing Queries and Mutations is needed
6/34

My Experience with GraphQL

7/34

Why I Began to Use GraphQL

  1. Initially my content was tied to my website
  2. Mobile app needed to consume the same data
  3. A content API was needed and GraphQL fit the bill
8/34
9/34

React Finland API

10/34
11/34
12/34

Asset Generator

13/34
14/34

Asset Designer

15/34
16/34

Schema First Design with GraphQL

17/34

Schema First Design (SFD)

Define the Schema first and the rest will follow

18/34

SFD with GraphQL

  1. Think of the main concepts of your system (i.e., Conference, Contact, Location, Theme)
  2. Think of the fields and types the concepts have (i.e., name, description)
  3. Think of the nature of the fields (i.e. where does the data come from)
19/34

TypeGraphQL

20/34

Types as Classes

Conference.ts

...

@ObjectType()
export class Conference {
  @Field(_ => ID)
  public id!: string;

  @Field(_ => String)
  public name!: string;

  @Field(_ => Contact)
  public organizer!: Contact;

  ...
}

Generated schema:

type Conference {
  id: ID!
  name: String!
  organizer: Contact!
  ...
}

GraphQL/TypeScript definition at the same time!

21/34

Resolvers as Classes

ConferenceResolver.ts

...

@Resolver(_ => Conference)
class ConferenceResolver {
  @Query(_ => Conference)
  public conference(
    @Arg("id", _ => ID) id: string
  ) {
    return getConference(id);
  }

  ...
}

Generated schema:

type Query {
  conference(id: ID!): Conference
}

Resolve to data here (async possible too)

22/34

What else?

  • Dependency injection (inject db service for example)
  • Authorization (add more annotations)
  • Validations (GraphQL scalars and specific annotations)
  • Query complexity handling
  • And more
23/34

Why I use TypeGraphQL

  1. I don't have to think of GraphQL Schema
  2. I can consume types from my frontend
  3. I can generate GraphQL queries (WIP)
24/34

GraphQL without GraphQL

25/34

Is it possible to use GraphQL and TypeScript type systems to generate queries?

Spoiler: Yes

26/34

React Demo

Schedule.tsx

interface ScheduleProps {
  theme: Theme;
  intervals: Array<{
    begin: Interval["begin"];
    end: Interval["end"];
    sessions: Array<{
      title: Session["title"];
      type: Session["type"];
    }>;
  }>;
}

Schedule.tsx

function Schedule({
  theme, intervals
}: ScheduleProps) {
  ...
}

The types point to our schema (source of truth for GraphQL)

27/34

Approach

  1. Extract types from GraphQL schema and React components
  2. Implement connected(Schedule) finds the component by name and constructs the related queries

To work, the system expects to find matching root queries (i.e. theme and intervals in this case)

28/34

Constraints

  • Expects components to be strictly typed
  • Expects backend to implement queries matching to collections
  • Expects you to use TypeScript for now
29/34

Pros and Cons

Pros:

  • Eliminates the need to maintain separate GraphQL queries
  • Typechecking through TypeScript
  • No need for graphql-tag or similar solution?

Cons:

  • Additional abstraction to worry about (query generator)
  • Loses some power of GraphQL (directives through comments?)
30/34

Lessons Learned

31/34

Schema First Design ties frontend and backend together

32/34

Types lead to new possibilities (i.e. automating queries, testing)

33/34
34/34