ryan-haskell / elm-graphql-server

Create a GraphQL API with Elm!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

@ryannhg/elm-graphql-server

Create a GraphQL API with Elm!

A screenshot of a demo query in the GraphQL playground

Playing around locally

You'll need Node.js to run this project on your local computer.

npm start
  • Visit http://localhost:4000 to use the GraphQL API
  • Mess with Elm files in src/Resolvers to change how the API responds

Overview

The server starts in a file called src/index.js. It is powered by an Elm program, compiled as a Platform.worker. That means you'll need to compile your Elm app first with npm run elm:build, or you can use the npm run dev script that automatically compiles things as you code!

Right now, the API server doesn't do too much. It listens for GraphQL requests at http://localhost:4000, and sends that request information to our Elm worker, so we can handle our resolvers with Elm code.

For now, you can modify the GraphQL schema by editing src/schema.gql, and add a new resolver in src/Worker.elm.

I have been making modules in src/Resolvers to organize the code, but that's just so you can easily follow what's going on!

This is not a production-ready thing, but I thought it would be a fun experiment to see what using the Elm language would be like for a backend GraphQL API.

A real implementation would require a nice way to talk to a database, a third-party HTTP service, or do things like application logging– but for now this is all we have 🙂

Talking to a SQL Database

I've been exploring communicating to a sqlite database. This project supports basic forms of:

Solving the N + 1 problem

This repo also features examples of queries that need to access data across multiple tables. For example, if a user creates a post, the database looks something like this:

users

id username avatarUrl
1 "ryan" NULL

posts

id caption imageUrls
3 "Elm conf 2019 was sweet!" [ ... ]

user_authored_post

id postId userId
5 3 1

A user of our GraphQL API might write a query like this, to get the id and username of the author of post #3:

query {
  post(id: 3) {
    id
    caption
    author {
      id
      username
    }
  }
}

When this GraphQL query comes through the Query.post resolver runs a few SQL statements:

-- Get the data stored for that post
SELECT id, caption FROM posts WHERE id = 3;
-- Check the "user_authored_post" table for any authors
SELECT userId FROM user_authored_post WHERE postId = 3;
-- The last query found a row with userId = 1,
-- so we pass that into the final SQL query that
-- fetches the `id` and `username` for our author
SELECT id, username FROM users WHERE id = 1;

If we need 3 SQL statements for one post and its author, how does this work when fetching multiple posts?

query {
  posts {
    id
    caption
    author {
      id
      username
    }
  }
}

This GraphQL request will be sent to our Query.posts resolver, which lists the first 25 posts in the system. If we repeated the previous strategy for each of those posts– that would mean 3 * 25... 75 SQL queries!?

Luckily for us, all our resolvers can access an info argument for the GraphQL query. This allows us to perform these queries in bulk– using a similar approach to Facebook's DataLoader!

Rather than making a query for each post, we use SQL's IN keyword to fetch author data for all 25 posts using only 3 SQL statements! (This would still only need 3 queries if we brought back 10, 100, or 1000 posts):

-- First, we ask for the first 25 posts
SELECT id, caption FROM posts LIMIT 25;
-- Now that we have all those posts, we use their IDs 
-- to query the `user_authored_post` table:
SELECT postId, userId FROM user_authored_post WHERE postId IN ( 1, 2, 3, ... 25 );
-- Once we have all those edges, we can use the userId column
-- to do one final SQL query for the author data for all those author ids
SELECT id, username FROM users WHERE id IN ( 1, 2, 3, 4, ... );

Using this WHERE id IN ... strategy helps us avoid a common GraphQL pitfall called the N + 1 problem. Try making nested queries, and see the SQL that is generated!

About

Create a GraphQL API with Elm!


Languages

Language:Elm 93.8%Language:JavaScript 6.2%