GraphQL advanced concepts 💥💥

(Feb Blog)

Introduction 🙋

Hi, this is my second blog about GraphQL (2020 Blogging challenge )

First ! Graphql subscriptions 💥💥:

While discovering GraphQL’s core concepts, I found out that if the client wants to fetch or send data to the server, there are queries and mutations that should be used, as for real-time messages and interactions there is “GraphQL subscriptions”.

Example Graphql subscriptions App design
subscription Message {
Message {
mutation
node {
id
createdAt
text
author
}
}
}

Validations in GraphQL🚩:

While adding or modifying data, it is important to validate user input.

type Query {
greeting:String
}

type Mutation {
signUp(input:SignUpInput):String
}

input SignUpInput {
email:String!,
password:String!,
firstName:String!
}
const Mutation ={
signUp:(root,args,context,info) => {

const {email,firstName,password} = args.input;

const emailExpression = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

const isValidEmail = emailExpression.test(String(email).toLowerCase())
if(!isValidEmail)
throw new Error("email not in proper format")

if(firstName.length > 15)
throw new Error("firstName should be less than 15 characters")

if(password.length < 8 )
throw new Error("password should be minimum 8 characters")

return "success";
}
}
module.exports = {Query,Mutation}
{
"input":{
"email": "abc@abc",
"firstName": "kannan",
"password": "pass@1234"
}
}
{
"data": {
"signUp": null
},

"errors": [
{
"message": "email not in proper format",
"locations": [
{
"line": 2,
"column": 4
}
],
"path": [
"signUp"
]
}
]
}
type SignUpInput {
email: String! @constraint(format: "email", maxLength: 255)
password: String! @constraint(maxLength: 255)
firstName: String! @constraint(pattern: "^[0-9a-zA-Z]*$", maxLength: 255)
lastName: String! @constraint(pattern: "^[0-9a-zA-Z]*$", maxLength: 255)
}

type Mutation {
signUp(input: SignUpInput!)
}

Authentication with GraphQL 🔓 🔏:

import { GraphQLServer } from 'graphql-yoga'
import * as jwt from 'jsonwebtoken'

const typeDefs = `type Query { hello(name: String): String! }`

const resolvers = {
Query: {
hello: (_, { name }) => `Hello ${name || 'World'}`,
},
}

const server = new GraphQLServer({ typeDefs, resolvers })
server.express.use((req, res, next) => {
const { authorization } = req.headers
jwt.verify(authorization, 'secret', (err, decodedToken) => {
if (err || !decodedToken) {
res.status(401).send('not authorized')
return
}
next()
})
})
server.start(() => console.log('Server is running on localhost:4000'))
context: ({ req }) => {
// get the user token from the headers
const token = req.headers.authorization || '';

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

// optionally block the user
// we could also check user roles/permissions here
if (!user) throw new AuthenticationError('you must be logged in');

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

Paginating and sorting with GraphQL 📃 📑:

type Query {
info: String!
feed(filter: String, skip: Int, first: Int): [Link!]!
}
async function feed(parent, args, context, info) {
const where = args.filter ? {
OR: [
{ description_contains: args.filter },
{ url_contains: args.filter },
],
} : {}

const links = await context.prisma.links({
where,
skip: args.skip,
first: args.first
})
return links
}
query {
feed(
first: 1
skip: 1
) {
id
description
url
}
}

sorting:

With Graphql API Design, it is possible to return lists of elements that are sorted (ordered) according to specific criteria

enum LinkOrderByInput {
description_ASC
description_DESC
url_ASC
url_DESC
createdAt_ASC
createdAt_DESC
}
type Query {
info: String!
feed(filter: String, skip: Int, first: Int, orderBy: LinkOrderByInput): [Link!]!
}
async function feed(parent, args, context, info) {
const where = args.filter ? {
OR: [
{ description_contains: args.filter },
{ url_contains: args.filter },
],
} : {}

const links = await context.prisma.links({
where,
skip: args.skip,
first: args.first,
orderBy: args.orderBy
})
return links
}
query {
feed(orderBy: createdAt_ASC) {
id
description
url
}
}

Fragments, Interfaces, and Unions in GraphQL 📀 📼:

“Reducing the schema complexity”

Error handling with GraphQL 🚫 ❌ :

  1. Client problems e.g. rate-limited, unauthorized, etc. (4xx HTTP codes)
  2. The query is missing/malformed
  3. The query fails GraphQL internal validation (syntax, schema logic, etc.)
  4. The user-supplied variables or context is bad and the resolve/subscribe function intentionally throws an error (e.g. not allowed to view requested user)
  5. An uncaught developer error occurred inside the resolve/subscribe function (e.g. poorly written database query)
const {
ApolloServer,
gql,
AuthenticationError,} = require('apollo-server');

const typeDefs = gql`
type Query {
authenticationError: String
}
`;

const resolvers = {
Query: {
authenticationError: (parent, args, context) => { throw new AuthenticationError('must authenticate'); }, },
};
const {
ApolloServer,
UserInputError,
gql,
} = require('apollo-server');

const typeDefs = gql`
type Mutation {
userInputError(input: String): String
}
`;

const resolvers = {
Mutation: {
userInputError: (parent, args, context, info) => { if (args.input !== 'expected') { throw new UserInputError('Form Arguments invalid', { invalidArgs: Object.keys(args), }); } }, },
};

Batching in GraphQL 📟:

Caching in GraphQL 💲:

  • Network Caching: they intercept requests that look the same (based on various configurable criteria), returning a response early straight out of memory, instead of hitting the application serve
  • Application Caching: It can be implemented in the application with tools like Memcache, Redis, etc… one of the advantages for example if the remote server is not available due to a crash or network partitioning, the client can obtain a cached copy at the proxy. Hence, the robustness of the Web service is enhanced.

Technical solution: “DataLoader” 📘 📙

GraphQL tools :

And before ending this Blog, This a lits of useful tools that can help you as a GraphQl developer to speed up your work or to tets it perfectly

  1. GraphQL Voyager : visualize your GraphQL
  2. GraphQL Docs : — auto-create your docs
  3. GraphQL IDE — the GraphQL playground
  4. Graphql-network: Chrome Devtool that provides a “network”-style tab for GraphQL requests to allow developers to debug more easily.
  5. Graphql-code-generator: GraphQL code generator with flexible support for custom plugins and templates
  6. swagger-to-graphql Swagger to GraphQL API adapter
  7. Prisma Modern DB toolkit to query, migrate and model your database

Conclusion :

For conclusion, GraphQL was one of the priority skills and technologies that I fixed to learn in 2020, I just started with core concepts, and discover the all whole ecosystem, in parallel, I’m trying to practice and implement some “POCS” by creating this repo: https://github.com/Rebaiahmed/Graphql-Learning

<script>alert('try your best')</script>