The basics of GraphQL and Apollo

Need Help in apollo-graphql

hi sir, I am Abhijeet from India. I just started working on graphql.I am trying to set reminder in apollo-graphql and I have no idea how it works in apollo. I am doing only backend graphql (nodejs) . help me for set a reminder in backend using apollo-graphql. This is urgent for me to create my new project.

hi sir, I am Abhijeet from India. I just started working on graphql.I am trying to set reminder in apollo-graphql and I have no idea how it works in apollo. I am doing only backend graphql (nodejs) . help me for set a reminder in backend using apollo-graphql. This is urgent for me to create my new project.

Tutorial To Apollo GraphQL Federation for Beginners

Tutorial To Apollo GraphQL Federation for Beginners

In this article, we will see what is Apollo Federation and what kind of problem that federation is trying to solve with a real-time example. Introduction to Apollo GraphQL Federation

If you are a beginner in GraphQL, I recommend you to learn the basics of GraphQL from something like this course.

Apollo Federation is an architecture of composing multiple GraphQL services into a single endpoint.

when you start to think about building a microservice, it would be difficult to divide the GraphQL layer for different services. For example, we are dividing it something like this –

This may seem to make sense at first. but, the problem is adding a new feature. Let’s say that we want to add top comments in Post. Post-service doesn’t know how to resolve a query for top comments because data about comment will be stored in the Comment Service.

On the other hand, Apollo Federation allows us to extend the Post type in Any Service, Here Comment service with a extend type functionality.

Therefore, this keeps all the code for a given feature in a single service and separated from unrelated concerns.

complete source code can be found here

Federation Core Concepts

Mainly, let us see the core concept of apollo federation which compiles different services together to form a single graph

Entities and keys

Firstly, It is a type which is referenced by another service. it creates a connection between services and form a federated graph. entities have a primary key which identifies the specific instance of the type.

entities can be declared by using a keyword @key in the Type

type User @key(fields: "_id") {
   _id : ID
   name : String
   email : String
}

External Type Reference

Once, the entity is declared, other services can reference this type from their own types. Let’s see how the Comment Service refer the User Service in our example

type Comment {
   user: User
}

extend type User @key(fields : "_id") {
   _id : ID @external
}

Likewise, In this example, we have Comment type with a field called user that return the User type. Since User is an entity that lives in another service, we define that type in this service with just enough information to enable composition.

  • extend keyword declares the User is an entity defined elsewhere, here it is User Service
  • The @Key declares the ‘name’. We will use _id to refer to a particular user.
  • The _id field with an @external directive declares the type of _id field(ID ) that is implemented in another service.

On the other hand, To get all the values of Referenced User in Comment Type Definition. we need to write some logic in the Resolver.

Comment: {
        user(comment) {
            return { __typename: "User",_id : comment.userId }
        }
    },
{ __typename: "User",_id : comment.userId }

object is a representation of a User entity. Representations are how services reference each other’s types.

As a result, the gateway will use the representation as an input to the service that owns the referenced entity. So to allow the gateway to get all the values in the referenced service. we need to reference resolver back in the User service.

User: {
        async __resolveReference(object) {
            return await UserModel.getUserById(object._id);
        }
    }

Now, we could get user details in the Comment Type using the reference of it which is a UserID

Extending external types

However, Extending external types solves the problem of one to many relationship use-cases. For example, Post can have many comments and a comment belongs to a post. In the previous section, we just saw external type reference. Here we will see Extending external type

For example, we want to add comments field to Post type

extend type Post @key(fields: "_id"){
        _id : ID @external
        comments : [ Comment! ]
    }

we can extend the Post type in the Comment service and extend the type with comments which are the type of Comment

Since the Comment service already had a concept of the Post type from returning it, adding additional fields to the overall type can be done just like it was a normal type.

query plan will fetch the _id field for each Post from the Post service and pass those to the comment service, where you can then access these fields on the object passed into your comments

resolver:

Post: {
        comments(post) {
            return CommentModel.getCommentByPost(post._id);
        }
    }
Building Microservice

complete source code can be found here

Let us build a blog application using apollo federation. it contains three services and an API gateway

You can get the source code for each of the services below –

User Service
Post Service
Comment Service

API Gateway

Firstly, we will create a gateway which connects all the services with a single GraphQL endpoint.

Initialize the project and create a file called gateway.js

npm init --yes
npm install @apollo/gateway apollo-server graphql

touch gateway.js

After that, add the following code in gateway.js

const { ApolloServer } = require('apollo-server');

const { ApolloGateway } = require('@apollo/gateway');

const gateway = new ApolloGateway({
    serviceList: [
      { name: "users", url: "http://localhost:4001/graphql" },
      { name: "posts", url: "http://localhost:4002/graphql" },
      { name: "comments", url: "http://localhost:4003/graphql" },
      // { name: "inventory", url: "http://localhost:4004/graphql" }
    ]
  });
  
  (async () => {
    const { schema, executor } = await gateway.load();
  
    const server = new ApolloServer({ schema, executor });
  
    server.listen().then(({ url }) => {
      console.log(` Server ready at ${url}`);
    });
  })();

we provide serviceList configuration to the Apollo gateway which provides the name and endpoint for each federated services. name is used for error messages and logging.

API Gateway – Authentication Across services

In Microservice architecture, it is important to authenticate request across different services. This blog explains Microservices Authentication in detail. To achieve this, Apollo Gateway shares the context across services.

@apollo/gateway makes it easy to reuse the context feature of Apollo to customize what information is sent to underlying services.

const { ApolloServer } = require('apollo-server');
const { ApolloGateway, RemoteGraphQLDataSource } = require('@apollo/gateway');

const gateway = new ApolloGateway({
  serviceList: [
     { name: "users", url: "http://localhost:4001/graphql" },
      { name: "posts", url: "http://localhost:4002/graphql" },
      { name: "comments", url: "http://localhost:4003/graphql" },
    // other services
  ],

  buildService({ name, url }) {
    return new RemoteGraphQLDataSource({
      url,
      willSendRequest({ request, context }) {
        // pass the user's id from the context to underlying services
        // as a header called `user-id`
        request.http.headers.set('x-user-id', context.userId);
      },
    });
  },
});

const server = new ApolloServer({
  gateway,
 
  context: ({ req }) => {
    // get the user token from the headers
    const token = req.headers.authorization || '';

    // try to retrieve a user with the token
    const userId = getUserId(token);

    // add the user to the context
    return { userId };
  },
});

server.listen().then(({ url }) => {
  console.log(` Server ready at ${url}`);
});

In this example, buildService return a custom RemoteGraphQLDataSource which allow us to modify the outgoing request with information from the Apollo Service context .request from gateway send x-user-id in the request header across services.

Moreover, To Learn more about buildService or RemoteGraphQLDataSource, read the API Docs

Summary

To sum up, we can build a Microservices using apollo federation which solves the problem of stitching GraphQL to a single endpoint. Several teams can work in different services without any dependency between services.

Originally published by Ganeshmani P at codewall.co.uk

Explore GraphQL with Apollo & React: Build a Superhero Database

Explore GraphQL with Apollo & React: Build a Superhero Database

In this article, We share some light on what GraphQL is and give you an opportunity for some hands-on experience with Apollo and React.

In this article, We share some light on what GraphQL is and give you an opportunity for some hands-on experience with Apollo and React.

Curious about all the buzz surrounding GraphQL, but not quite sure why you should be excited? You’re in the right place! We’ll shed some light on what GraphQL is and give you an opportunity for some hands-on experience.

Let’s start by clearing the air and answering the $20,000 question: what is GraphQL? No, it’s not an obscure function on your TI-89. It’s a query language at heart — or query specification more accurately — that can be used to fetch data from just about any data source.

Better yet, it allows you to fetch the exact data you need — no more, no less — in a single network request. While that may not sound like the sexiest tech to come out of the Facebook factory of innovation, you may just find yourself pleasantly surprised at how useful it can be.

All that’s needed is an Apollo server to act as our endpoint and a React app using the Apollo client to leverage any data within. We’ll tackle the server first.

Getting Started with Apollo Server

To get our Apollo server started, create a folder called apollo-server in your favorite working directory. Next, enter that directory and run the following npm command — you do have npm and Node installed, right? — to get the Apollo framework in place:

npm install apollo-server apollo-server-express graphql

Now that you’ve got the various bits and pieces of the Apollo server in place, it’s time to actually tell our server what to serve. Go ahead and create an empty index.js file in the apollo-server directory and add the following to it:

const { ApolloServer, gql } = require('apollo-server');

This line simply pulls in the required objects for starting an Apollo server and parsing our query strings into query documents for GraphQL.

Our First GraphQL Schema

Next up, let’s add our first schema:

// This will be our GraphQL schema
const typeDefs = gql`
  type User {
    id: ID!
    name: String
    superpowers: [Superpower]!
  }

  type Superpower {
    id: ID!
    text: String
  }

  type Query {
    users: [User]
    user(id: ID!): User
  }
`;

Here we add our type definitions. The first is of type User which we define as an object having an id, name, and superpowers field. The second is a simple id and text to describe each superpower. Finally, the third defines two acceptable queries — users and user — that, respectively, return all users or a single user that matches the provided id argument.

Pretty easy, right?

Adding a Dash of Data

Next, let’s add some mock data to bring our schema to life:

// This will be our mock data to query
const users = [{
  id: '1',
  name: 'Peter Parker',
  superpowers: [{
    id: '1',
    text: 'Web slinging'
  },{
    id: '2',
    text: 'Spidey sense'
  }]
},{
  id: '2',
  name: 'Tony Stark',
  superpowers: [{
    id: '3',
    text: 'Industrial design'
  },{
    id: '4',
    text: 'Robotic fashion'
  }]
}];

All we’re doing here is adding two users to our mock data. It’s worth pointing out that GraphQL isn’t relegated to only querying JavaScript arrays. This could be any database or other data construct. We’re just keeping things simple here to focus on the task at hand.

Don’t Forget Resolvers

Next up, we need to tell GraphQL how to interpret the queries we defined above. This is done with resolvers:

// This will be a map of functions to return the data described by our schema
const resolvers = {
  Query: {
    users: () => {
      return users
    },
    user: (root, { id }) => {
      return users.find(user => user.id === id);
    },
  },
};

You’ll notice the first query users requires no arguments and returns the entire users list (at least in theory, more on that later). The second query user accepts the ID of the user to be fetched and returns said user.

Putting It All Together

To finish off our Apollo server, we just need to instantiate a new instance and start listening for connections:

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen().then(({ url }) => {
  console.log(`Apollo server started at ${url}`)
});

Here we send the ApolloServer constructor our schema and resolvers created above. All that’s needed then is to actually start the server, but first, here’s what your index.js should look like:

const { ApolloServer, gql } = require('apollo-server');

// This will be our GraphQL schema
const typeDefs = gql`
  type User {
    id: ID!
    name: String
    superpowers: [Superpower]!
  }

  type Superpower {
    id: ID!
    text: String
  }

  type Query {
    users: [User]
    user(id: ID!): User
  }
`;

// This will be our mock data to query
const users = [{
  id: '1',
  name: 'Peter Parker',
  superpowers: [{
    id: '1',
    text: 'Web slinging'
  },{
    id: '2',
    text: 'Spidey sense'
  }]
},{
  id: '2',
  name: 'Tony Stark',
  superpowers: [{
    id: '3',
    text: 'Industrial design'
  },{
    id: '4',
    text: 'Robotic fashion'
  }]
}];

// This will be a map of functions to return the data described by our schema
const resolvers = {
  Query: {
    users: () => {
      return users
    },
    user: (root, { id }) => {
      return users.find(user => user.id === id);
    },
  },
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
});

server.listen().then(({ url }) => {
  console.log(`Apollo server started at ${url}`)
});

Go ahead and fire it up with node index.js and visit http://localhost:4000/ to see the fruit of your labor!

You should be greeted with a GraphQL playground that lets you try out interactive queries against the schema you’ve created.

Going Hands-on

Let’s test it out by entering this query in the left-hand pane:

query {
  user(id: 1) {
    name
  }
}

Here we use the user query we just set up, and pass it the id of 1. We’re also telling GraphQL that we only want to return the name of said user. The result in the left hand pane — after clicking the play-like button — should look like this:

{
  "data": {
    "user": {
      "name": "Peter Parker"
    }
  }
}

Let’s say you want to take a peek at his superpowers too. All you have to do is request that field:

query {
  user(id: 1) {
    name,
    superpowers {
      text
    }
  }
}

We added the superpowers field and, since we only care about the text and not the superpower ID, we specify as much. The result should now display each superpower for our first user:

{
  "data": {
    "user": {
      "name": "Peter Parker",
      "superpowers": [
        {
          "text": "Web slinging"
        },
        {
          "text": "Spidey sense"
        }
      ]
    }
  }
}

Say we want to grab all users and their superpowers, we can rely on the users query we defined:

query {
  users {
    id,
    name,
    superpowers {
      text
    }
  }
}

And the result:

{
  "data": {
    "users": [
      {
        "id": "1",
        "name": "Peter Parker",
        "superpowers": [
          {
            "text": "Web slinging"
          },
          {
            "text": "Spidey sense"
          }
        ]
      },
      {
        "id": "2",
        "name": "Tony Stark",
        "superpowers": [
          {
            "text": "Industrial design"
          },
          {
            "text": "Robotic fashion"
          }
        ]
      }
    ]
  }
}

Only care about superpowers? We can do that too:

query {
  users {
    superpowers {
      text
    }
  }
}

And you get:

{
  "data": {
    "users": [
      {
        "superpowers": [
          {
            "text": "Web slinging"
          },
          {
            "text": "Spidey sense"
          }
        ]
      },
      {
        "superpowers": [
          {
            "text": "Industrial design"
          },
          {
            "text": "Robotic fashion"
          }
        ]
      }
    ]
  }
}

At this point you should be able to appreciate the supreme flexibility and allure of GraphQL. With a single query and connection we can retrieve any slice of the data we desire. All that’s necessary is a well designed schema and the resolvers to support it.

Even better, back-end developers and front-end developers can do their thing almost independently. With the schema acting as a middle man, both groups can effectively avoid stepping on each other’s toes. And really, that’s GraphQL in a nutshell. Before we wrap this tutorial up however, let’s take a look at how to integrate these queries with an actual React app.

Introducing React to the Mix

Go back to your root working directory and run the following commands to set up a bootstrapped React app with the requisite GraphQL and Apollo libraries:

npm install -g create-react-app
create-react-app my-graphql
cd my-graphql
npm install apollo-boost react-apollo graphql

Next, replace the contents of src/index.js with the following:

index.js:

import React from 'react'
import ReactDOM from 'react-dom'
import { ApolloClient } from 'apollo-client'
import { HttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { ApolloProvider } from 'react-apollo'

import App from './App'

const client = new ApolloClient({
    link: new HttpLink({ uri: 'http://localhost:4000/graphql' }),
    cache: new InMemoryCache()
})

ReactDOM.render(
    <ApolloProvider client={client}>
    <App />
    </ApolloProvider>,
    document.getElementById('root')
)

All we need here are the usual imports for a React app along with the Apollo client to interface with our new Apollo server. To create the Apollo client we just need a link to the server http://localhost:4000/graphql and a way to cache our goods. With that, we simply render the app.

Next, we need to set up the app to query and display the data presented by our Apollo server. Go ahead and replace the default src/App.js with this:

App.js:

import React from 'react'
import { Query } from 'react-apollo'
import { gql } from 'apollo-boost'

const TEST_QUERY = gql`
  {
    user(id: 1) {
      id,
      name,
      superpowers {
        text
      }

  }}
`;

const App = () => (
  <Query query={TEST_QUERY}>
  {({ data: { user }, loading }) => {
      if (loading || !user) {
        return <div>Loading ...</div>;
      }
      return (
    <p>
        {user.name} ({user.id}) has the following superpowers:
        <ul>
        {user.superpowers.map(superpower => (
            <li>
                {superpower.text}
            </li>
        ))}
        </ul>
    </p>
      );
    }}
  </Query>
);

export default App

You should see some familiar patterns here. We first use gql to create a GraphQL query document that requests the user with ID 1 — more specifically, their ID, name and superpowers text. Then we pass the document to our server with the Query tag. It’s here that we can format the results in a pretty React app.

Go ahead and start the server with npm start and check out the beautiful results at http://localhost:3000/.

And with that, our tutorial is complete. You’ve created an Apollo server and fed it some simple data structures. You discovered how to write schemas and resolvers to define interactions with the data. You then practiced querying specific pieces of that data. Finally, you tied it all together with a React app that retrieves data from the server and presents it in a nicely formatted way.

While this should be enough to get you started with integrating GraphQL in your future projects, there’s lots still to learn. Mutations for adding and changing data is a great next step.