Connecting a GraphQL backend

Use an existing GraphQL API as a data source for your project. The @graphql directive connects your GraphQL API with other GraphQL APIs.

Connect to public APIs

This example connects to the public Rick and Morty GraphQL API using the @graphql directive. To connect to the public API, complete the following tasks:

  1. Create the project structure .

    Run the following commands to create a project called rick-and-morty with a single directory called schema for the types:

    mkdir -p rick-and-morty/schema
    cd rick-and-morty
  2. Create an index.graphql file.

    The index.graphql file describes how to assemble the various type definition files into a complete GraphQL schema.

    touch index.graphql

    This example only has a single file for now called characters.graphql:

    schema @sdl(
      files: [
        "schema/characters.graphql"
      ]
    ) {
      query: Query
    }
  3. Create a characters.graphql file.

    Create a file called characters.graphql for the Character object:

    touch schema/characters.graphql

    The Character object has three fields, as shown in Table 1:

    Table 1. Fields in the Character object
    Field Type Description
    id ID Identifier
    name String Character's name
    image String URL to a .jpeg image file of the character
    type Character {
      id: ID
      name: String
      image: String
    }

    To match the Rick and Morty API schema, return a results array containing the Character objects; call the type Characters:

    type Characters {
      results: [Character]
    }

    The Query type has a characters query that returns the Characters, as specified in the previous types. The @graphql directive takes the endpoint of the GraphQL API, which in this case is https://rickandmortyapi.com/graphql, with the URL enclosed in quotation marks:

    type Query {
      characters: Characters
        @graphql(
          endpoint: "https://rickandmortyapi.com/graphql"
        )
    }
  4. Run the CHARACTERS_QUERY test query.

    Run the following query called CHARACTERS_QUERY to test the new endpoint. This query executes the characters query and returns an array of Character objects with their id, name, and image:

    query CHARACTERS_QUERY {
      characters {
        results {
          id
          name
          image
        }
      }
    }

    The query returns a data object containing the id, name, and image of the characters contained within a results array.

    {
      "data": {
        "characters": {
          "results": [
            {
              "id": "1",
              "image": "https://rickandmortyapi.com/api/character/avatar/1.jpeg",
              "name": "Rick Sanchez"
            },
            {
              "id": "2",
              "image": "https://rickandmortyapi.com/api/character/avatar/2.jpeg",
              "name": "Morty Smith"
            }
          ]
        }
      }
    }

Connect to authenticated APIs

Now let's try a slightly more complex example. The Rick and Morty API is public, meaning that it does not require an API token to access. What if you wanted to use a headless CMS with the @graphql directive?

Complete the following steps to connect an authenticated API:

  1. Create a config.yaml file.

    Much like the @rest directive, pass your query a configuration contained in a config.yaml file:

    touch config.yaml

    The config.yaml file contains a token provided by Storyblok that requires the following values:

    • A name called storyblok_config.
    • A token provided by Storyblok. Replace xxxx in the example below with the actual token's value:
    configurationset:
      - configuration:
          name: storyblok_config
          token: xxxx
  2. Create a storyblok.graphql file.

    The storyblok.graphql file has the content types and queries:

    touch schema/storyblok.graphql

    Define the following types:

    • A PostItem type with a name of type String
    • A PostItems type with an array named items containing PostItem objects
    type PostItem {
      name: String
    }
    
    type PostItems {
      items: [PostItem]
    }

    The Query type has a postItems query that returns the PostItems as specified in previous types. The @graphql directive takes:

    • The endpoint of the GraphQL API (https://gapi.storyblok.com/v1/api).
    • The configuration named storyblok_config.
    • The headers, which is an array of objects each containing the name and value of a header:
    type Query {
      postItems: PostItems
        @graphql(
          endpoint: "https://gapi.storyblok.com/v1/api"
          headers: [
            { name:"Token" value:"$token" }
          ]
          configuration: "storyblok_config"
        )
    }

    Add schema/storyblok.graphql to your index.graphql file inside the files array:

    schema @sdl(
      files: [
        "schema/characters.graphql"
        "schema/storyblok.graphql"
      ]
    ) {
      query: Query
    }
  3. Run POSTS_QUERY Test Query.

    Run the following query called POSTS_QUERY to test the new endpoint and execute the PostItems query:

    query POSTS_QUERY {
      PostItems {
        items {
          name
        }
      }
    }

    This returns a data object containing the name of the PostItems contained within an items array:

    {
      "data": {
        "PostItems": {
          "items": [
            {
              "name": "my-super-awesome-post"
            }
          ]
        }
      }
    }

If you want to follow along with your own example, you can see how to authenticate with the Storyblok GraphQL API at the Storyblok website.

What else can you do with the @graphql directive?

The @graphql directive provides a variety of extra functionality that was not explored in this simple example. The following sections describe what else you can do with the @graphql directive:

Mutations
So far you have only seen how to run queries. But you can also use the @graphql directive with mutations that changee the data in the backend data source.

You can find examples for how to use mutations in the GraphQL mutations topic.

Fragments
Let's say you have a relatively complicated page in your app that looks at two characters side by side, along with their friends. For more complicated queries, GraphQL includes reusable units called fragments.

Fragments let you construct sets of fields to include in your queries. This is useful for queries where you need to repeat the fields. The GraphQL docs include the following example:

{
  leftComparison: hero(episode: EMPIRE) {
    ...comparisonFields
  }
  rightComparison: hero(episode: JEDI) {
    ...comparisonFields
  }
}

fragment comparisonFields on Character {
  name
  appearsIn
  friends {
    name
  }
}

This results in the following output:

{
  "data": {
    "leftComparison": {
      "name": "Luke Skywalker",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "friends": [
        {
          "name": "Han Solo"
        },
        {
          "name": "Leia Organa"
        },
        {
          "name": "C-3PO"
        },
        {
          "name": "R2-D2"
        }
      ]
    },
    "rightComparison": {
      "name": "R2-D2",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ],
      "friends": [
        {
          "name": "Luke Skywalker"
        },
        {
          "name": "Han Solo"
        },
        {
          "name": "Leia Organa"
        }
      ]
    }
  }
}
Prefixes
As your project grows, you might connect to multiple APIs, which can result in name collisions for the types and queries. For example, if you have multiple characters queries, you might want the characters from the Rick and Morty API instead of the Star Wars API.

In this example, add the prefix value rick_ to the types and queries. Instead of Character, write rick_Character, and so on:

type rick_Character {
  id: ID
  name: String
  image: String
}

type rick_Characters {
  results: [rick_Character]
}

Add a prefix by including an object containing a value with that prefix:

type Query {
  rick_characters: rick_Characters
    @graphql(
      endpoint: "https://rickandmortyapi.com/graphql"
      prefix: { value: "rick_", includeRootOperations: true }
    )
}