App Masters

App Masters

  • English
  • Português

›Database

App Masters - Core

  • Home
  • Content

Backend

  • Node Express
  • Node Worker Threads

Database

  • GraphQL

Javascript Fundamentals

  • Asynchronous Javascript
  • Typescript

Design Patterns

  • Presentational Container Design Pattern

Frontend

  • AMP (Accelerated Mobile Pages)
  • Bubblewrap
  • Gatsby.js
  • Next.js
  • PWA
  • Styled Components

Mobile

  • React Native
  • Store Testing

Server

  • Netlify

Testing

  • Cypress
  • Jest

Design

  • Human Interface
  • Material Design

Tools

  • Bitrise
  • Docker

GraphQL

What is it

GraphQL is a query language for API used to abstract the interaction between server and client. The language enables the use of declarative data fetching so that the client can specify exactly the data it's application needs and the server sends only the necessary data, avoiding the need for multiple HTTP requests to different endpoints or using bandwidth with unwanted data.

Some names to remember:

  • Schema - It is the server definition of the types, queries, mutations, and subscriptions it can provide to the client.
  • Query - Describes the data that the client wishes from the server. It's analogous to a GET request to a REST API.
  • Mutation - Describer the data manipulation within the server that the client wished to make. It's analogous to a POST request to a REST API.
  • Subscription - Used to listen for data update in the server using WebSocket.
  • Resolvers - Responsible for converting a GraphQL interaction (query, mutation, and subscription) in data. It's where the server implements the database access and business logic is implemented.

How we use

We currently use GraphQL for the API specification and data query between our backend and frontend projects. For the backend, we use the Apollo Server library to set up a graphql server and define the Schema and Resolvers. In the frontend, GraphQL is used with the Apollo Client, where each view defines the queries and mutations it needs.

We also use GraphQL in gatsby projects as it is its default mechanism of data querying.

How to learn

Usefull materials

  • Official Documentation
  • Overview of GraphQL and Diferences to REST
  • GraphQL Fundamentals: HowToGraphQL or YouTube Playlist from Prisma developers.
  • Backend Tutorial using Prisma and graphql-yoga (based in Apollo Server).
  • Frontend Tutorial using React and Apollo Client.
  • Creating a custom resolver using graphql-compose

Using Apollo to manage local state

  • Local state management - Apollo docs
  • Local State Management with Apollo - Video
  • Apollo Link State in Less than 30 Minutes - Video

Validating knowledge

  • Create a simple project consuming a ToDo API using the Apollo Client.

Simple Guides

Creating a custom resolver using graphql-compose

To simplify the schema creation process with the Apollo Server, we use the graphql-compose. Here is a simple guide on defining a custom resolver with graphql-compose:

Define a type for the result of the operation (Query/Mutation/Subscription)

import { schemaComposer } from 'graphql-compose';
...
const returnType = schemaComposer.createObjectTC({
  // Define the name of the type, this will appear in the schema and can be used
  // by other resolvers.
  name: 'AwesomeQueryResult',

  // Here we list the fields of the new type
  fields: {
    // You can use any type already defined in the schema by their name
    message: 'String',
    // It uses the same type notation as the GraphQL language, so for a required
    // list of numbers, you should use
    listOfNumbers: '[Int!]!',
    // You can also use already created types
    people: [myCustomPerson],
    // Or define new types in place
    proposals: schemaComposer.createObjectTC({ ... })
  }
})

If needed, create any custom type for the input of the operation

  // Inputs are defined in the same way as other types, it just uses a special
  // function `createInputTC`.
  //
  // (In the GraphQL definition, the input types have some limitations when
  // compared with other types, see the documentation for more details)
  const inputType = schemaComposer.createInputTC({
    name: 'AwesomeQueryInput',
    fields: {
      name: 'String!',
      filter: 'JSON'
    }
  });

Define the arguments for the operation

  // This is a simple object defined the same way as the `fields` property in the
  // `createInputTC` and `createObjectTC`
  const args = {
    searchTerm: 'String!',
    models: [inputType],
    pagination: 'Pagination'
  },

Define the resolver function

  // This is the function that will be executed when the operation needs to be
  // processed. The resolve function has an object with three property available:
  // - source: The properties of the parent field, used for some nested queries
  // - args: An object with the arguments passed into the field in the query
  // - context: An object shared by all resolvers in a query. May contain
  //            authentication information and dataloader instances.
  // - info: contains the information about the query state (we don't use it)
  const resolveFn = ({ source, args, context, info }) => {
    ...
    // The return of the resolve function must match the type defined earlier.
    // Pay attention to required `!` types as null values can cause strange errors
    // in the query result.
    return { ... };
  }

Create the schema resolver

  // The  key is the name of the query
  const customResolver = schemaComposer.createResolver({
    name: 'AwesomeQueryResolver',
    // The return type of the query
    type: returnType,
    // The parameters definition for the query
    args: args,
    // The resolve function executed when the operation is being processed
    resolve: resolveFn
  })

Register the custom resolver as a Query, Mutation or Subscription

  // The last step in the process is to register the custom operation in the
  // RootQuery.
  schemaComposer.Query.addFields({
    awesomeQuery: customResolver
  })
  // If it is a Mutation, you can use
  schemaCompose.Mutation.addFields({
    awesomeMutation: customResolver
  })
← Node Worker ThreadsAsynchronous Javascript →
  • What is it
  • How we use
  • How to learn
    • Usefull materials
    • Validating knowledge
  • Simple Guides
    • Creating a custom resolver using graphql-compose
App Masters
App masters
Content
More
BlogGitHub
Copyright © 2022 App Masters