Angular 14 Apollo Client Setup

Angular 14 Apollo Client Setup

In this article, we'll take a look at the Apollo client and the Apollo library for Angular to see how we can integrate user authentication into our Angular frontend.

Let's start by defining GraphQL queries and mutations for user authentication.

Define the following import and two constants containing the keys for the access token and authenticated user that will be used to save the corresponding information in the local storage of the user’s browser:

import { gql } from 'apollo-angular'; 
export const ACCESS_TOKEN: string = "accessToken"; 
export const AUTH_USER: string = "authUser"; 

Next, define and export the register mutation that will be sent to the backend GraphQL API for registering users:

export const REGISTER_MUTATION = gql` 
    mutation register($fullName: String!, $username: String!, $email: String!, $password: String!){  
      register(fullName:$fullName, username:$username, email:$email, password:$password){  
        token, user { id, name, about, email, username, avatar, createdAt }  
      }  
    }  

`; 

The gql function is used to wrap query and mutation strings so that they can be processed into documents, i.e. an abstract syntax tree (AST) of objects. It is a template literal tag that should be used while providing queries and mutations to Apollo Client.

Because we needed to call a mutation on the GraphQL server, we utilized the mutation operation type, named it register, and gave the appropriate arguments using GraphQL variables. In this mutation, we must dynamically pass the user's full name, username, email address, and password in order to register an account for them.

We simply ask for the register field that we previously added to the Mutation type in our GraphQL server schema in the body of our mutation, and because the corresponding resolver will return an object with a nested authentication token and the user created in the database, we need to specify a sub-selection for selecting the required fields.

It is recommended that you specify an explicit name for your operation in order to facilitate server debugging and identify queries if any mistakes arise.

To inform the server what sort of operation you wish to do, you can specify query, mutation, or subscription for the operation type.

Then, for logging users in, define and export the signin mutation:

export const SIGNIN_MUTATION = gql` 
    mutation signIn($email: String!, $password: String! ){  
      signIn(email:$email, password:$password){  
        token, user { id, name, about, email, username, avatar, createdAt }  
      }  
    }  
`; 

We utilized the gql template literal once more to create the GraphQL mutation that would be delivered to the server to authenticate users. We utilized the mutation type to tell the server to call the signIn field on the top-level Mutation type, and we used variables to send dynamic arguments such as the user's name and password.

Because the signIn mutation field refers to an object containing a nested token string and a user object, we use a sub-selection on the client side to choose all of the relevant information, including the JWT token and the authorized user.

Next, define and export the user query for finding a user by ID:

export const USER_QUERY = gql` 
    query findUser($userId: ID!){  
      findUser(userId:$userId){         
          id, name, about, email, username, avatar, createdAt }  
    } 
`; 

In this case, we utilize the query operation type and pass the user ID as a parameter to the API server, asking it to retrieve an existent user with that ID. The query type on the server has the findUser field that we are querying, and because it returns a user object, we provide a sub-selection on the client side to choose the fields we are interested in.