DEV Community

Simon Bundgaard-Egeberg for IT Minds

Posted on

Why I think GraphQL is pretty neat, the implementation

In my last post, I wrote about why I think GraphQL as a concept is pretty neat. This time I will try, through implementation, to show that it is indeed pretty neat.

In my last blog post which you can find here, I teased about what stack I would be using, but just to reclarify, this is it:

  • Language: Typescript
  • Server: NexusJS
  • Frontend-UI: React
  • Frontend-Network: Apollo-client

Let's go!

I like to write less to do more. I know some might find this as magic, and I tend to agree. Sometimes. When it comes to decreasing the time to market with a product, I think it's good with a little magic.

Using NexusJS can very easily feel like magic. First of all, the actual file that starts the server can be as bare as this:

import { schema } from 'nexus'

  name: 'SupremeLeader',
  definition(t) {'id')            

Notice, how there I nowhere specify my server or what port to listen on.

Nexus will abstract this away and just let me run nexus dev in my terminal, and I will be hitting the ground running!

Now I know that some will say that this is the worst idea ever, but I would have to respectfully disagree. And just to point out, you can, though ENV variables choose which port nexus will use under the hood, and you can also hook into the underlying express server to add your own configuration middleware, should you be so inclined.

My experience with nexus has been: provides sensible defaults, but open for configuration.

Which I happen to think is a good standpoint to take no matter what type of library/framework you are creating.

Anyways, back to the code:

What the above code does for me is to create a single type on my schema. However, at this point, there is no way we can get any data from the server. Therefor, let's implement a query so that we can get some glorious posts from our graph!

  type: "Query",
  definition(t) {
    t.field("gloriusLeader", {
      type: "SupremeLeader",
      resolve(parent, args, context) {
          return {
              id: 0

Above we create a query to get ourselves a SupremeLeader through the gloriousLeader handle.

How about we see how this query works then?

Alt Text

This query is pretty useless since it's only returning 1, and only an id field, but from here you can grow the schema to whatever size you want. Pretty neat.

Let's see how we use this API to create our SupremeLeader a glorious frontend as well!

    type: "Mutation",
    definition(t) {
        t.field("birthNewSupremeLeader", {
            type: "String",
            resolve(parent, args, context) {
                return `All hail our new king`;

When manipulating data we call mutations - in essence this is just a name, and not a constraint.

That means that queries essentially can manipulate data. But to make sure that we as developers know if our interactions have side effects on the data, the GraphQL spec splits them up into these two.

The above mutation does nothing but return string indicating success, but whatever logic you would want can be put here.

Just for the fun, let's see how much code we need then to create a GraphQL service that has a SupremeLeader model a query to fetch it, and a mutation to add one.

file system

Okay, some pretty basic files here. The only part that really does something here is the app.ts. That's the file I have been showing snippets of.

So to make a small service that exposes a GraphQL API, with albeit slim to 0 functionality, you really only need 3 files, a app.ts containing the GraphQL code, a package.json file defining the project and its dependencies, and a tsconfig.json file with the typescript setup you need to 'typescript' away.

What you get, however, is an API, documentation (in the form of the types the schema provides), a playground to test your API in, and so much developer happiness that you could just burst.

I hope you liked this post and if you have any questions please let me know in the comments.

Top comments (0)