<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ GraphQL - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ GraphQL - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 05 May 2026 22:19:52 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/graphql/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use GraphQL in Flutter: A Handbook for Developers ]]>
                </title>
                <description>
                    <![CDATA[ There's a moment that most Flutter developers experience at some point in their careers. You're building a screen that needs a user's name, their latest five posts, and the like count on each post. Se ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-graphql-in-flutter-a-handbook-for-developers/</link>
                <guid isPermaLink="false">69d3bf4140c9cabf4431fc13</guid>
                
                    <category>
                        <![CDATA[ Flutter ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Dart ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Atuoha Anthony ]]>
                </dc:creator>
                <pubDate>Mon, 06 Apr 2026 14:12:17 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/66d879b4-18e0-4ebd-9e36-320cdb9b1ac2.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>There's a moment that most Flutter developers experience at some point in their careers.</p>
<p>You're building a screen that needs a user's name, their latest five posts, and the like count on each post. Seems simple enough. You make a request to <code>/users/42</code>, and the server sends back twenty fields you didn't ask for.</p>
<p>You make another request to <code>/users/42/posts</code>, and again the server sends back everything it knows about those posts, including fields your UI will never display.</p>
<p>Then you realize you also need the comment count per post, so you loop through the posts and fire five more requests, one per post.</p>
<p>By the time the screen loads, your Flutter app has made seven network requests, downloaded kilobytes of data it immediately discarded, and your users on slower networks are staring at a spinner, wondering if the app is broken.</p>
<p>This isn't a rare edge case. This is the everyday reality of building complex UIs on top of conventional REST APIs, and every developer who has shipped a serious mobile app has felt this friction.</p>
<p>The data you need and the data the API gives you are almost never a perfect match. You either get too much or not enough, and the cost is measured in wasted bandwidth, slower screens, more complex client-side code, and frustrated users.</p>
<p>GraphQL was invented to solve exactly this. Not theoretically, not as an academic exercise, but because the engineers at Facebook in 2012 were building a News Feed that needed data from dozens of resources simultaneously, on mobile devices running on 2G networks, and the REST approach was simply not good enough.</p>
<p>Their answer was to give the client full control over the shape of the data it receives. Instead of the server deciding what you get, you tell the server exactly what you need and it gives you precisely that, in one trip.</p>
<p>This handbook is a complete, engineering-depth guide to understanding GraphQL from first principles and using it confidently inside Flutter applications with the <code>graphql_flutter</code> package.</p>
<p>You won't just learn what the APIs look like. You'll understand why the library is designed the way it is, how the pieces fit together architecturally, what the normalized cache does and why it matters, and how to structure a real production app around GraphQL so that it stays maintainable as it grows.</p>
<p>By the end, you'll be able to build real-world Flutter apps backed by GraphQL. You'll also be able to reason clearly about when GraphQL is and is not the right tool and avoid the pitfalls that trip up most developers making this transition for the first time.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-what-is-graphql">What is GraphQL</a>?</p>
<ul>
<li><a href="#heading-why-facebook-built-it">Why Facebook Built It</a></li>
</ul>
</li>
<li><p><a href="#heading-understanding-the-problem-life-before-graphql">Understanding the Problem: Life Before GraphQL</a></p>
<ul>
<li><p><a href="#heading-how-rest-works">How REST Works</a></p>
</li>
<li><p><a href="#heading-over-fetching-too-much-data">Over-fetching: Too Much Data</a></p>
</li>
<li><p><a href="#heading-under-fetching-not-enough-data">Under-fetching: Not Enough Data</a></p>
</li>
<li><p><a href="#heading-versioning-when-apis-cant-evolve-cleanly">Versioning: When APIs Can't Evolve Cleanly</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-the-single-endpoint-approach">The Single Endpoint Approach</a></p>
<ul>
<li><p><a href="#heading-one-endpoint-client-defined-data">One Endpoint, Client-Defined Data</a></p>
</li>
<li><p><a href="#heading-why-graphql-doesnt-need-versioning">Why GraphQL Doesn't Need Versioning</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-core-graphql-concepts-a-deep-dive">Core GraphQL Concepts: A Deep Dive</a></p>
<ul>
<li><p><a href="#heading-the-schema-the-contract-between-client-and-server">The Schema: The Contract Between Client and Server</a></p>
</li>
<li><p><a href="#heading-types-the-building-blocks">Types: The Building Blocks</a></p>
</li>
<li><p><a href="#heading-queries-reading-data">Queries: Reading Data</a></p>
</li>
<li><p><a href="#heading-mutations-changing-data">Mutations: Changing Data</a></p>
</li>
<li><p><a href="#heading-subscriptions-real-time-data">Subscriptions: Real-Time Data</a></p>
</li>
<li><p><a href="#heading-variables-making-queries-safe-and-reusable">Variables: Making Queries Safe and Reusable</a></p>
</li>
<li><p><a href="#heading-fragments-reusable-field-sets">Fragments: Reusable Field Sets</a></p>
</li>
<li><p><a href="#heading-resolvers-how-the-server-fulfills-queries">Resolvers: How the Server Fulfills Queries</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-graphql-architecture-in-flutter">GraphQL Architecture in Flutter</a></p>
<ul>
<li><p><a href="#heading-how-the-pieces-connect">How the Pieces Connect</a></p>
</li>
<li><p><a href="#heading-the-normalized-cache-graphqls-secret-weapon">The Normalized Cache: GraphQL's Secret Weapon</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-setting-up-graphql-in-flutter">Setting Up GraphQL in Flutter</a></p>
<ul>
<li><p><a href="#heading-adding-the-dependency">Adding the Dependency</a></p>
</li>
<li><p><a href="#heading-android-build-configuration">Android Build Configuration</a></p>
</li>
<li><p><a href="#heading-initializing-hive-for-persistent-caching">Initializing Hive for Persistent Caching</a></p>
</li>
<li><p><a href="#heading-creating-the-graphql-client">Creating the GraphQL Client</a></p>
</li>
<li><p><a href="#heading-adding-websocket-support-for-subscriptions">Adding WebSocket Support for Subscriptions</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-using-graphql-in-flutter-queries-mutations-and-subscriptions">Using GraphQL in Flutter: Queries, Mutations, and Subscriptions</a></p>
<ul>
<li><p><a href="#heading-queries-fetching-and-displaying-data">Queries: Fetching and Displaying Data</a></p>
</li>
<li><p><a href="#heading-using-hooks-for-queries">Using Hooks for Queries</a></p>
</li>
<li><p><a href="#heading-mutations-triggering-data-changes">Mutations: Triggering Data Changes</a></p>
</li>
<li><p><a href="#heading-subscriptions-receiving-real-time-events">Subscriptions: Receiving Real-Time Events</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-advanced-concepts">Advanced Concepts</a></p>
<ul>
<li><p><a href="#heading-caching-strategies-choosing-the-right-policy">Caching Strategies: Choosing the Right Policy</a></p>
</li>
<li><p><a href="#heading-pagination-with-fetchmore">Pagination with fetchMore</a></p>
</li>
<li><p><a href="#heading-optimistic-ui-updates">Optimistic UI Updates</a></p>
</li>
<li><p><a href="#heading-error-handling-a-production-grade-approach">Error Handling: A Production-Grade Approach</a></p>
</li>
<li><p><a href="#heading-authentication-transparent-token-refresh">Authentication: Transparent Token Refresh</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-best-practices-in-real-apps">Best Practices in Real Apps</a></p>
<ul>
<li><p><a href="#heading-project-structure-that-scales">Project Structure That Scales</a></p>
</li>
<li><p><a href="#heading-composing-queries-from-fragments">Composing Queries from Fragments</a></p>
</li>
<li><p><a href="#heading-parsing-graphql-data-into-typed-models">Parsing GraphQL Data into Typed Models</a></p>
</li>
<li><p><a href="#heading-integrating-with-bloc-and-a-repository-layer">Integrating with Bloc and a Repository Layer</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-when-to-use-graphql-and-when-not-to">When to Use GraphQL and When Not To</a></p>
<ul>
<li><p><a href="#heading-where-graphql-excels">Where GraphQL Excels</a></p>
</li>
<li><p><a href="#heading-where-graphql-is-the-wrong-choice">Where GraphQL is the Wrong Choice</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-common-mistakes">Common Mistakes</a></p>
<ul>
<li><p><a href="#heading-ignoring-how-the-normalized-cache-works">Ignoring How the Normalized Cache Works</a></p>
</li>
<li><p><a href="#heading-defining-query-strings-inside-the-build-method">Defining Query Strings Inside the Build Method</a></p>
</li>
<li><p><a href="#heading-using-networkonly-for-everything">Using networkOnly for Everything</a></p>
</li>
<li><p><a href="#heading-forgetting-to-cancel-subscriptions">Forgetting to Cancel Subscriptions</a></p>
</li>
<li><p><a href="#heading-not-handling-partial-graphql-results">Not Handling Partial GraphQL Results</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-mini-end-to-end-example">Mini End-to-End Example</a></p>
<ul>
<li><p><a href="#heading-the-graphql-client">The GraphQL Client</a></p>
</li>
<li><p><a href="#heading-the-queries">The Queries</a></p>
</li>
<li><p><a href="#heading-the-mutations">The Mutations</a></p>
</li>
<li><p><a href="#heading-the-entry-point">The Entry Point</a></p>
</li>
<li><p><a href="#heading-the-repos-screen">The Repos Screen</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-conclusion">Conclusion</a></p>
</li>
<li><p><a href="#heading-references">References</a></p>
<ul>
<li><p><a href="#heading-official-package-documentation">Official Package Documentation</a></p>
</li>
<li><p><a href="#heading-graphql-language-and-specification">GraphQL Language and Specification</a></p>
</li>
<li><p><a href="#heading-tooling-and-ecosystem">Tooling and Ecosystem</a></p>
</li>
<li><p><a href="#heading-related-flutter-packages">Related Flutter Packages</a></p>
</li>
<li><p><a href="#heading-learning-resources">Learning Resources</a></p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before diving into GraphQL and <code>graphql_flutter</code>, you should be comfortable with a few foundational areas. This guide doesn't assume you're an expert in any of them, but it builds on these skills throughout.</p>
<ol>
<li><p><strong>Flutter and Dart fundamentals.</strong> You should be able to build a multi-screen Flutter app with <code>StatefulWidget</code> and <code>StatelessWidget</code>. Understanding widget trees, <code>BuildContext</code>, <code>setState</code>, and Dart's async/await model is essential. If you have built a weather app or a to-do list app in Flutter, you have everything you need to follow along.</p>
</li>
<li><p><strong>HTTP and APIs.</strong> You should understand what an API is, what an HTTP request is, and how JSON flows between a client and a server. You don't need to know the internals of HTTP, but knowing that a client sends a request and a server responds with structured data is the baseline assumption this guide builds on.</p>
</li>
<li><p><strong>Basic state management.</strong> Familiarity with at least one state management approach such as Provider, Bloc, or Riverpod will help you understand the architecture discussions in later sections. You can follow the guide without it, but those sections will make more sense if you have seen how Flutter apps separate UI from business logic.</p>
</li>
<li><p><strong>Tools for the project.</strong> Make sure your development environment includes the following before you begin:</p>
<ul>
<li><p>Flutter SDK 3.x or higher</p>
</li>
<li><p>A code editor such as VS Code or Android Studio</p>
</li>
<li><p>The flutter and dart CLIs accessible from your terminal</p>
</li>
<li><p>An Android emulator, iOS simulator, or physical device for testing</p>
</li>
</ul>
</li>
<li><p><strong>Java 17 for Android builds.</strong> Because graphql_flutter ^5.3.0 requires Java 17 for Android, you need to confirm your JDK version before adding the package. Run <code>java -version</code> in your terminal and verify the output shows version 17. If not, install JDK 17 before proceeding. Android builds will fail with confusing errors if this requirement is not met.</p>
</li>
<li><p><strong>Packages this guide uses.</strong> Your <code>pubspec.yaml</code> will include:</p>
</li>
</ol>
<pre><code class="language-yaml">dependencies:
  flutter:
    sdk: flutter
  graphql_flutter: ^5.3.0
  flutter_hooks: ^0.20.0
</code></pre>
<p>The <code>flutter_hooks</code> dependency is needed only if you want to use the hooks-based API (<code>useQuery</code>, <code>useMutation</code>). This guide covers both the widget-based and hooks-based styles side by side.</p>
<h2 id="heading-what-is-graphql">What is GraphQL?</h2>
<p>Imagine two restaurants. In the first restaurant, you sit down and the waiter brings you a fixed platter. The kitchen decides what goes on it: a burger, fries, a side salad, and a drink. You wanted just the burger with ketchup, but that's not how this restaurant works. You take the whole platter or you leave. If you also want dessert, you have to flag the waiter down for a second trip.</p>
<p>In the second restaurant, the waiter hands you a blank piece of paper. You write exactly what you want: one burger patty on a toasted bun, only ketchup, and a chocolate lava cake alongside it. You hand the note to the kitchen, and they bring you precisely that in one trip. No waste. No second journey.</p>
<p>The first restaurant is a REST API. The second is GraphQL.</p>
<p>That analogy captures the core idea well, but there's more depth to it. The blank piece of paper in the second restaurant isn't unlimited freedom. The kitchen still has a menu of ingredients they know how to prepare. You can only request things that exist in their kitchen.</p>
<p>In GraphQL terms, that menu of available ingredients is called the schema, and it's the formal contract between the server and every client that talks to it.</p>
<p>GraphQL is a query language for APIs and a runtime for executing those queries against your data. It was created by Facebook (now Meta) in 2012 and open-sourced in 2015. Unlike REST, which maps operations to specific URLs and HTTP verbs, GraphQL exposes a single endpoint where every operation is sent as a structured document in the request body.</p>
<p>The critical shift is this: in REST, the server decides what data you get. In GraphQL, the client decides. The server exposes a schema describing everything that's available. The client sends a query describing exactly what subset of that data it needs. The server resolves the query and returns precisely that shape – nothing added, nothing withheld.</p>
<p>Here's a simple GraphQL query:</p>
<pre><code class="language-graphql">query GetUser($userId: ID!) {
  user(id: $userId) {
    id
    name
    profilePic
  }
}
</code></pre>
<p>And the response:</p>
<pre><code class="language-json">{
  "data": {
    "user": {
      "id": "42",
      "name": "Atuoha Anthony",
      "profilePic": "https://cdn.example.com/atuoha.jpg"
    }
  }
}
</code></pre>
<p>The server didn't include <code>email</code>, <code>createdAt</code>, <code>followersCount</code>, or any other field it stores. It returned exactly and only what the query asked for.</p>
<h3 id="heading-why-facebook-built-it">Why Facebook Built It</h3>
<p>GraphQL was created to solve three specific, well-documented pain points at Facebook in 2012. Understanding these problems in concrete terms matters because they're the same problems you've likely already encountered in your own apps.</p>
<p>The first problem was too many network requests. The Facebook News Feed required data from dozens of resources: posts, comments, likes, profiles, media attachments, and advertisements. With REST, each resource lived at a different endpoint, and assembling a single screen required hitting many of them, either sequentially (slow) or in parallel with complex client-side merging logic (also slow and fragile to maintain).</p>
<p>The second problem was data bloat. REST endpoints returned fixed response shapes defined by the server. The mobile client received everything the server thought might be useful, but mobile apps on 2G and 3G networks in 2012 couldn't afford to download kilobytes of fields that would never be displayed. Wasted bytes meant slower load times, higher data bills for users, and faster battery drain on their devices.</p>
<p>The third problem was API evolution velocity. Every time the News Feed team wanted to show a new piece of information, they either had to modify an existing API endpoint (risking breakage for other clients) or create a new one (bloating the API surface and creating versioning debt). The server and client were too tightly coupled, and every product iteration required a backend change to precede it.</p>
<p>GraphQL solved all three problems simultaneously: one request for any combination of data, client-defined field selection to eliminate waste, and schema evolution without endpoint versioning.</p>
<p>When Facebook open-sourced it in 2015, the broader developer community recognized immediately that these were not Facebook-specific problems. They were universal API problems, and GraphQL was a universal solution.</p>
<h2 id="heading-understanding-the-problem-life-before-graphql">Understanding the Problem: Life Before GraphQL</h2>
<h3 id="heading-how-rest-works">How REST Works</h3>
<p>REST (Representational State Transfer) is the architectural style that dominated API design for the better part of a decade and remains the most common approach in the industry today.</p>
<p>The core idea is straightforward: every resource lives at a specific URL called an endpoint. You interact with it using HTTP verbs: GET to read, POST to create, PUT or PATCH to update, and DELETE to remove.</p>
<p>For a typical social app, the REST API might look like this:</p>
<pre><code class="language-plaintext">GET  /users/42            -- fetch user #42
GET  /users/42/posts      -- fetch posts by user #42
GET  /posts/17/comments   -- fetch comments on post #17
POST /posts               -- create a new post
</code></pre>
<p>Each endpoint has a fixed response shape defined by the server. When you call <code>GET /users/42</code>, you always receive the same fields regardless of which screen you are building or what data you actually need in that moment.</p>
<img src="https://cdn.hashnode.com/uploads/covers/63a47b24490dd1c9cd9c32ff/d4ed65e9-5605-4eb7-8857-fe49cc9a63c2.png" alt="REST Request/Response Lifecycle" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>This works. For many applications and many teams, it works well. But it carries structural limitations that become increasingly painful as the application and its data requirements grow in complexity.</p>
<h3 id="heading-over-fetching-too-much-data">Over-fetching: Too Much Data</h3>
<p>Over-fetching happens when the API returns more data than the client needs for a given screen. Your profile screen needs a user's name and profile picture, but the server sends fifteen fields.</p>
<p>On a desktop with a fast connection, the extra bytes barely register. On a mobile device on a congested network, they add latency, drain the battery faster, and cost users on metered data plans real money.</p>
<p>Multiply this across every API call in a complex app, and the cumulative waste becomes a meaningful performance problem.</p>
<h3 id="heading-under-fetching-not-enough-data">Under-fetching: Not Enough Data</h3>
<p>Under-fetching is the opposite. A single endpoint doesn't return enough data for a screen, so the client must make multiple requests to assemble the full picture. The scenario in the diagram above is a classic example: two requests just to render one screen.</p>
<p>This problem becomes dramatically worse with lists. If you need to display ten posts, each with its author's profile picture, and the posts endpoint doesn't include author details, you make one request to get the posts and then ten more requests to fetch each author's data.</p>
<p>This is the N+1 problem: one request to get N items, followed by N additional requests to enrich them. For a list of ten items, that is eleven network calls for a single screen.</p>
<h3 id="heading-versioning-when-apis-cant-evolve-cleanly">Versioning: When APIs Can't Evolve Cleanly</h3>
<p>As your app evolves, different screens need different shapes of the same data. You can't simply change an existing endpoint because other clients depend on its current response shape.</p>
<p>So you create <code>/v2/users</code>, then <code>/v3/users</code>, and soon you're maintaining multiple versions of the same endpoints, afraid to delete old ones because you cannot be certain which clients still use them.</p>
<p>Your API documentation becomes a graveyard of deprecated routes, and your backend team spends engineering time maintaining things that serve no active user need.</p>
<h2 id="heading-the-single-endpoint-approach">The Single Endpoint Approach</h2>
<h3 id="heading-one-endpoint-client-defined-data">One Endpoint, Client-Defined Data</h3>
<p>GraphQL replaces the many-endpoints model with a single endpoint, typically <code>/graphql</code>. Instead of the URL encoding what you want, the <strong>request body</strong> encodes it. Every operation (reading data, changing data, or listening to real-time events) is sent as a structured document to that same endpoint.</p>
<p>Here's the profile screen scenario from above, rewritten as a single GraphQL operation:</p>
<pre><code class="language-graphql">query GetUserProfile($userId: ID!) {
  user(id: $userId) {
    id
    name
    profilePic
    posts(last: 5) {
      id
      title
      likeCount
    }
  }
}
</code></pre>
<p>One request. One response. The data arrives in exactly the shape the query described:</p>
<pre><code class="language-json">{
  "data": {
    "user": {
      "id": "42",
      "name": "Atuoha Anthony",
      "profilePic": "https://cdn.example.com/atuoha.jpg",
      "posts": [
        { "id": "101", "title": "My First Post", "likeCount": 42 },
        { "id": "102", "title": "Flutter Tips", "likeCount": 118 }
      ]
    }
  }
}
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/63a47b24490dd1c9cd9c32ff/f1dd4d6e-6de7-49b4-9551-085899a4f1dd.png" alt="REST vs GraphQL: Side by Side" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<h3 id="heading-why-graphql-doesnt-need-versioning">Why GraphQL Doesn't Need Versioning</h3>
<p>GraphQL's schema-first design eliminates the versioning problem almost entirely. When you add new fields or types to the schema, existing clients that don't request those new fields continue working without modification. When you want to deprecate a field, you mark it with the <code>@deprecated</code> directive in the schema.</p>
<p>Developer tooling surfaces that deprecation to client developers, giving them time to migrate away from it. Meanwhile, the field continues serving data until you are confident all clients have moved on. You never need to maintain parallel versions of the same endpoint.</p>
<h2 id="heading-core-graphql-concepts-a-deep-dive">Core GraphQL Concepts: A Deep Dive</h2>
<h3 id="heading-the-schema-the-contract-between-client-and-server">The Schema: The Contract Between Client and Server</h3>
<p>The schema is the foundation of every GraphQL API. Written in the Schema Definition Language (SDL), it's a formal declaration of every type of data your server can provide and every operation a client can perform. Both the server and the client read from it.</p>
<p>When you write a query in your Flutter app, your tooling validates it against the schema before a single network request is made. If you request a field that doesn't exist in the schema, the error is caught immediately at the query level, not at runtime in production.</p>
<p>Here is what a schema for a blog application looks like:</p>
<pre><code class="language-graphql">type User {
  id: ID!
  name: String!
  email: String!
  bio: String
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
  likeCount: Int!
  comments: [Comment!]!
  publishedAt: String!
}

type Comment {
  id: ID!
  text: String!
  author: User!
}

type Query {
  user(id: ID!): User
  post(id: ID!): Post
  allPosts(page: Int, limit: Int): [Post!]!
}

type Mutation {
  createPost(title: String!, content: String!): Post!
  likePost(postId: ID!): Post!
  deletePost(postId: ID!): Boolean!
}

type Subscription {
  postAdded: Post!
  commentAdded(postId: ID!): Comment!
}
</code></pre>
<p>The <code>!</code> after a type name means the field is non-nullable: it will never return null. <code>[Post!]!</code> means a non-null list of non-null <code>Post</code> objects. <code>Query</code>, <code>Mutation</code>, and <code>Subscription</code> are the root types: special types that define the entry points into the API.</p>
<p>As a Flutter developer you won't write the schema (that is the backend's job). But you must be able to read it fluently, because it tells you exactly what you can query and what shape the response will carry.</p>
<h3 id="heading-types-the-building-blocks">Types: The Building Blocks</h3>
<p>GraphQL has two broad categories of types: scalar types and object types.</p>
<p><strong>Scalar types</strong> are the leaf values in a query. They have no sub-fields and can't be broken down further.</p>
<p>The five built-in scalars are <code>String</code>, <code>Int</code>, <code>Float</code>, <code>Boolean</code>, and <code>ID</code>. <code>ID</code> is special in that it represents a unique identifier and is serialized as a string. Servers can also define custom scalars like <code>DateTime</code>, <code>URL</code>, or <code>JSON</code> to represent domain-specific value types.</p>
<p><strong>Object types</strong> have named fields that resolve to either scalars or other object types. They form the graph in GraphQL, where you traverse relationships by nesting your field selections:</p>
<pre><code class="language-graphql">query {
  post(id: "17") {
    title       # scalar
    author {    # object type -- traversing a relationship
      name      # scalar nested inside the relationship
    }
  }
}
</code></pre>
<p><strong>Enum types</strong> constrain a field to a defined set of values, preventing arbitrary strings from being used where only specific values are valid:</p>
<pre><code class="language-graphql">enum PostStatus {
  DRAFT
  PUBLISHED
  ARCHIVED
}
</code></pre>
<p><strong>Input types</strong> are used specifically as complex arguments in mutations. Because regular object types can't be used as arguments, you define separate input types for structured mutation inputs:</p>
<pre><code class="language-graphql">input CreatePostInput {
  title: String!
  content: String!
  status: PostStatus!
}

type Mutation {
  createPost(input: CreatePostInput!): Post!
}
</code></pre>
<h3 id="heading-queries-reading-data">Queries: Reading Data</h3>
<p>A query is the GraphQL operation for reading data. It's the GET of the GraphQL world. You declare the exact fields you want and the server returns exactly those.</p>
<pre><code class="language-graphql">query GetPostDetails($postId: ID!) {
  post(id: $postId) {
    id
    title
    content
    publishedAt
    author {
      id
      name
    }
    comments {
      id
      text
      author {
        name
      }
    }
    likeCount
  }
}
</code></pre>
<p>Let's break this down line by line so the structure is clear:</p>
<p>The word <code>query</code> declares the operation type, telling the server you're reading data, not writing it.</p>
<p><code>GetPostDetails</code> is the operation name. It's optional but strongly recommended for debugging, logging, and code generation.</p>
<p><code>(\(postId: ID!)</code> is the variable declaration: <code>\)postId</code> is a placeholder of type <code>ID!</code> whose actual value will be supplied at runtime when the query is executed. <code>post(id: $postId)</code> calls the <code>post</code> field on the root <code>Query</code> type, passing the variable as the argument.</p>
<p>Everything inside curly braces is the selection set, the exact fields you want the server to return. Notice how <code>author</code> and <code>comments</code> are nested with their own selection sets. You're traversing the graph, following relationships declared in the schema, and the server resolves each relationship and includes it in the single response.</p>
<p>The response mirrors your query's shape exactly:</p>
<pre><code class="language-json">{
  "data": {
    "post": {
      "id": "17",
      "title": "Getting Started With GraphQL",
      "content": "GraphQL is a query language for APIs...",
      "publishedAt": "2024-01-15T10:30:00Z",
      "author": { "id": "42", "name": "Franklin Oladipo" },
      "comments": [
        {
          "id": "201",
          "text": "Great article!",
          "author": { "name": "Bede Hampo" }
        }
      ],
      "likeCount": 247
    }
  }
}
</code></pre>
<h3 id="heading-mutations-changing-data">Mutations: Changing Data</h3>
<p>A mutation is the GraphQL operation for modifying data: creating, updating, or deleting records. The syntax is identical to a query, with the single difference that you use the <code>mutation</code> keyword instead of <code>query</code>.</p>
<pre><code class="language-graphql">mutation CreateNewPost(\(title: String!, \)content: String!) {
  createPost(title: \(title, content: \)content) {
    id
    title
    publishedAt
    author {
      name
    }
  }
}
</code></pre>
<p>One of the most powerful aspects of mutations is that they return data. After creating a post, you can immediately ask for any fields from the newly created object within the same operation. Your UI can then update with the server's authoritative data without making a separate query afterward.</p>
<p>Unlike queries, <strong>mutations execute serially by default</strong>. If you send multiple mutations in a single request, they run one after another, not in parallel. This prevents race conditions when one mutation depends on the result of the previous one.</p>
<h3 id="heading-subscriptions-real-time-data">Subscriptions: Real-Time Data</h3>
<p>A subscription is GraphQL's built-in mechanism for real-time updates. Instead of the client polling for new data, the server <strong>pushes</strong> data to the client whenever a relevant event occurs. Subscriptions are implemented over WebSockets and are a first-class part of the GraphQL specification.</p>
<pre><code class="language-graphql">subscription OnNewComment($postId: ID!) {
  commentAdded(postId: $postId) {
    id
    text
    author {
      name
      profilePic
    }
  }
}
</code></pre>
<p>When a client subscribes to <code>commentAdded</code> for a specific post, the server keeps the WebSocket connection open. Every time a new comment is added to that post, the server pushes the comment data to all connected subscribers instantly.</p>
<p>This is the right tool for chat applications, live notification feeds, real-time collaboration features, or any scenario where users expect the UI to react to server-side events without manually refreshing.</p>
<h3 id="heading-variables-making-queries-safe-and-reusable">Variables: Making Queries Safe and Reusable</h3>
<p>Variables are how you pass dynamic values into a GraphQL operation without embedding them directly in the query string. This separation is not just a convention but a strict requirement enforced by every GraphQL library for safety and efficiency reasons.</p>
<p>Without variables, dynamic values would have to be interpolated into the query string, which opens the door to injection attacks and prevents query-level caching. With variables, the query string is a fixed, immutable template. Only the variables change per request:</p>
<pre><code class="language-graphql"># The query is always this exact string. It never changes.
query GetUser($userId: ID!) {
  user(id: $userId) {
    name
  }
}
</code></pre>
<pre><code class="language-json">// The variables object changes per request.
{ "userId": "42" }
</code></pre>
<p>The server receives both and processes them separately. It never interpolates your variable values into the query string. This is the safe, correct pattern for dynamic data, and the <code>graphql_flutter</code> library enforces it throughout its API.</p>
<h3 id="heading-fragments-reusable-field-sets">Fragments: Reusable Field Sets</h3>
<p>As queries grow in complexity, you'll find yourself selecting the same set of fields from the same type across multiple queries. Fragments solve this with named, reusable chunks of a selection set:</p>
<pre><code class="language-graphql"># Define the fragment once on a specific type
fragment UserBasicInfo on User {
  id
  name
  profilePic
}

# Use it in as many queries as needed
query GetPost($postId: ID!) {
  post(id: $postId) {
    title
    author {
      ...UserBasicInfo   # spread the fragment here
    }
    comments {
      text
      author {
        ...UserBasicInfo  # and here
      }
    }
  }
}
</code></pre>
<p>The <code>...UserBasicInfo</code> spread tells the server to replace that spread with the full set of fields defined in the fragment. Fragments are especially valuable in component-driven UIs like Flutter, where each widget can define a fragment for the exact data it needs, and screen-level queries can be assembled by composing fragments from their child widgets.</p>
<h3 id="heading-resolvers-how-the-server-fulfills-queries">Resolvers: How the Server Fulfills Queries</h3>
<p>You won't write resolvers as a Flutter developer, but understanding them conceptually makes you a more effective consumer of GraphQL APIs and helps you reason about performance implications.</p>
<p>A resolver is a function on the server that knows how to fetch the data for one specific field. Every field in the schema has a resolver. When a query arrives, the GraphQL runtime walks through the selection set and calls the appropriate resolver for each requested field, assembling the results into the shape the client declared.</p>
<pre><code class="language-graphql">Query: { user(id: "42") { name posts { title } } }

Server execution:
  1. Call resolver for Query.user("42")  -&gt; { id: "42", name: "Tony" }
  2. Call resolver for User.posts("42") -&gt; [{ title: "Post 1" }]
  3. Assemble result                    -&gt; { user: { name: "Tony", posts: [...] } }
</code></pre>
<p>Each resolver independently fetches its piece of data, which might come from a relational database, a microservice, a third-party API, or an in-memory cache. The GraphQL runtime stitches all the pieces together. The client never knows or cares about the implementation details. It declares what it wants and receives the assembled result.</p>
<h2 id="heading-graphql-architecture-in-flutter">GraphQL Architecture in Flutter</h2>
<h3 id="heading-how-the-pieces-connect">How the Pieces Connect</h3>
<p>When you use GraphQL in a Flutter app, four distinct layers work together. Understanding their roles and the boundaries between them is essential before writing a single line of application code.</p>
<ol>
<li><p><strong>The Flutter UI layer</strong> contains your widgets. They declare what data they need using <code>Query</code>, <code>Mutation</code>, and <code>Subscription</code> widgets (or hooks). They know nothing about HTTP, WebSockets, or caching. They describe their data requirements and react to results.</p>
</li>
<li><p><strong>The GraphQL Client</strong> is the engine at the center of everything. The <code>graphql_flutter</code> package manages the connection to your server, the normalized cache, request queuing, deduplication, and reactive result broadcasting to widgets.</p>
</li>
<li><p><strong>The Link Chain</strong> is a composable middleware pipeline that every request passes through before reaching the server. Links can add authentication headers, log requests, handle errors, retry failed requests, and route traffic between HTTP and WebSocket connections based on operation type.</p>
</li>
<li><p><strong>The GraphQL Server</strong> receives the operation, validates it against the schema, executes the resolvers, and returns the JSON response.</p>
</li>
</ol>
<img src="https://cdn.hashnode.com/uploads/covers/63a47b24490dd1c9cd9c32ff/e565bad8-985f-48e1-b3c9-aa1974ea4709.png" alt="Flutter GraphQL Architecture: Request/Response Lifecycle" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<h3 id="heading-the-normalized-cache-graphqls-secret-weapon">The Normalized Cache: GraphQL's Secret Weapon</h3>
<p>The GraphQL client's cache is one of its most powerful features and one of the most commonly misunderstood.</p>
<p>Unlike a simple HTTP cache that stores raw response blobs, the GraphQL cache is a <strong>normalized object store</strong>. Every object is stored once, identified by its type and ID. The cache key for a post with id "17" of type <code>Post</code> is <code>Post:17</code>. If that same post appears in ten different query results across ten different screens, it's stored only once.</p>
<p>The consequence of this is significant. When a mutation updates that post, the cache updates its single stored copy. Every widget in your app that previously fetched that post immediately receives the updated data and rebuilds. A like count updated on a post detail screen is reflected on the feed screen, the user profile screen, and anywhere else that post was displayed, all without re-fetching, all automatically, triggered by a single cache write.</p>
<p>This shared, reactive normalized store is what makes well-built GraphQL apps feel so fluid. It's also what enables optimistic UI updates to work across the entire widget tree simultaneously.</p>
<h2 id="heading-setting-up-graphql-in-flutter">Setting Up GraphQL in Flutter</h2>
<h3 id="heading-adding-the-dependency">Adding the Dependency</h3>
<p>Open your <code>pubspec.yaml</code> and add the package:</p>
<pre><code class="language-yaml">dependencies:
  flutter:
    sdk: flutter
  graphql_flutter: ^5.3.0
</code></pre>
<p>Then run:</p>
<pre><code class="language-bash">flutter pub get
</code></pre>
<h3 id="heading-android-build-configuration">Android Build Configuration</h3>
<p>This step is non-negotiable for Android targets and is easy to miss. Open <code>android/app/build.gradle</code> and ensure the Java compatibility settings are present:</p>
<pre><code class="language-groovy">android {
    compileSdkVersion 34

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = "17"
    }
}
</code></pre>
<p>Also update <code>android/gradle/wrapper/gradle-wrapper.properties</code> to use Gradle 8.4:</p>
<pre><code class="language-properties">distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
</code></pre>
<p>Skipping this step results in cryptic Java compatibility errors at build time that are difficult to diagnose if you don't know to look here.</p>
<h3 id="heading-initializing-hive-for-persistent-caching">Initializing Hive for Persistent Caching</h3>
<p><code>graphql_flutter</code> uses Hive (via <code>hive_ce</code>) for on-disk persistent caching. This means the cache survives app restarts: a user who opens your app without an internet connection will still see previously loaded data rather than an empty screen.</p>
<p>To enable this, you must call <code>initHiveForFlutter()</code> before <code>runApp()</code>, and it must be awaited:</p>
<pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

void main() async {
  // Required before calling any Flutter plugin code before runApp().
  // initHiveForFlutter() uses platform channels internally to locate
  // the correct storage directory on each platform.
  WidgetsFlutterBinding.ensureInitialized();

  // Sets up the Hive storage directory and registers necessary adapters.
  // After this call, HiveStore is ready to be used inside GraphQLCache.
  await initHiveForFlutter();

  runApp(const MyApp());
}
</code></pre>
<p>If you prefer not to persist the cache across sessions, you can skip this initialization and use <code>InMemoryStore</code> instead of <code>HiveStore</code> when creating the cache. For production apps, <code>HiveStore</code> is almost always the right choice.</p>
<h3 id="heading-creating-the-graphql-client">Creating the GraphQL Client</h3>
<p>The <code>GraphQLClient</code> is the central object in the entire system. It's created once and provided to the widget tree through <code>GraphQLProvider</code>.</p>
<p>Here is a full setup with a line-by-line explanation of every decision:</p>
<pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    // HttpLink is the terminating link: the final link in the chain
    // that actually sends the HTTP POST request to your server.
    // It takes your GraphQL endpoint URL as its only required argument.
    final HttpLink httpLink = HttpLink(
      'https://api.yourapp.com/graphql',
    );

    // AuthLink is a non-terminating link that runs before HttpLink.
    // Its sole job is to attach an Authorization header to every request.
    // getToken is async, so you can read from secure storage, a token
    // refresh service, or any other async source.
    final AuthLink authLink = AuthLink(
      getToken: () async {
        // In production, read this from FlutterSecureStorage or
        // your auth state management layer, never from plain storage.
        final token = await _getTokenFromStorage();
        return 'Bearer $token';
      },
    );

    // concat() assembles the link chain. Requests flow left to right:
    // AuthLink runs first (attaching the header), then HttpLink runs
    // (sending the actual HTTP request). You can insert as many
    // non-terminating links as needed between them.
    final Link link = authLink.concat(httpLink);

    // ValueNotifier&lt;GraphQLClient&gt; is required by GraphQLProvider.
    // Wrapping the client in a ValueNotifier allows you to replace
    // the entire client at runtime (for example, on user logout to
    // clear the cache) and GraphQLProvider will rebuild all its
    // descendants automatically with the new client.
    final ValueNotifier&lt;GraphQLClient&gt; client = ValueNotifier(
      GraphQLClient(
        link: link,
        // HiveStore provides persistent on-disk caching.
        // Swap HiveStore() for InMemoryStore() if you want the
        // cache to be cleared on every app restart.
        cache: GraphQLCache(store: HiveStore()),
      ),
    );

    // GraphQLProvider injects the client into the widget tree via
    // InheritedWidget. Any descendant can access the client through
    // GraphQLProvider.of(context). Wrapping MaterialApp means the
    // client is available on every screen in your app.
    return GraphQLProvider(
      client: client,
      child: MaterialApp(
        title: 'My GraphQL App',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
          useMaterial3: true,
        ),
        home: const HomePage(),
      ),
    );
  }

  Future&lt;String&gt; _getTokenFromStorage() async {
    // Replace with your actual secure storage implementation.
    return 'your-auth-token';
  }
}
</code></pre>
<h3 id="heading-adding-websocket-support-for-subscriptions">Adding WebSocket Support for Subscriptions</h3>
<p>If your app uses real-time subscriptions, you need a <code>WebSocketLink</code> alongside the <code>HttpLink</code>. The two are joined using <code>Link.split</code>, which routes each request to the correct transport based on its operation type:</p>
<pre><code class="language-dart">final HttpLink httpLink = HttpLink('https://api.yourapp.com/graphql');

final WebSocketLink webSocketLink = WebSocketLink(
  // Use wss:// for secure WebSockets in production.
  // Use ws:// only for local development.
  'wss://api.yourapp.com/graphql',
  config: const SocketClientConfig(
    autoReconnect: true,
    delayBetweenConnectAttempts: Duration(seconds: 5),
  ),
);

// Link.split evaluates its predicate for each incoming request.
// If the predicate returns true, the first (left) link handles it.
// If false, the second (right) link handles it.
// request.isSubscription is true for subscription operations.
final Link link = authLink.concat(
  Link.split(
    (request) =&gt; request.isSubscription,
    webSocketLink,  // subscriptions go here
    httpLink,       // queries and mutations go here
  ),
);
</code></pre>
<p>The <code>authLink</code> sits before the split so it runs for all operation types. Both HTTP and WebSocket transports typically require authentication.</p>
<h2 id="heading-using-graphql-in-flutter-queries-mutations-and-subscriptions">Using GraphQL in Flutter: Queries, Mutations, and Subscriptions</h2>
<h3 id="heading-queries-fetching-and-displaying-data">Queries: Fetching and Displaying Data</h3>
<p>The <code>Query</code> widget executes a GraphQL query and rebuilds whenever the result state changes. It's the primary mechanism for loading data on a screen.</p>
<pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

// Always define query strings as top-level constants, never inside build().
// The `r` prefix creates a raw string so dollar signs and backslashes
// are not treated as Dart escape sequences or string interpolations.
// gql() parses this string into a DocumentNode AST that the client executes.
const String fetchPostsQuery = r'''
  query FetchPosts(\(limit: Int!, \)page: Int!) {
    allPosts(limit: \(limit, page: \)page) {
      id
      title
      publishedAt
      likeCount
      author {
        name
        profilePic
      }
    }
  }
''';

class PostListScreen extends StatelessWidget {
  const PostListScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Posts')),
      body: Query(
        options: QueryOptions(
          document: gql(fetchPostsQuery),

          // Variables are passed as a plain Dart Map&lt;String, dynamic&gt;.
          // The library serializes them to JSON and sends them alongside
          // the query string as a separate field in the request body.
          variables: const {'limit': 10, 'page': 1},

          // cacheAndNetwork: return cached data immediately if available,
          // then fire a background network request and rebuild with fresh
          // data when it arrives. Users get instant perceived load time
          // from the cache while staying current with the server.
          fetchPolicy: FetchPolicy.cacheAndNetwork,
        ),

        // The builder function is called on every state change:
        // when loading begins, when data arrives, when an error occurs,
        // and when cached data is updated by another operation.
        //
        // result  -- current state: loading status, data, exceptions
        // refetch -- callback to manually re-execute the query
        // fetchMore -- callback for pagination (covered later)
        builder: (QueryResult result, {VoidCallback? refetch, FetchMore? fetchMore}) {

          // Always check for exceptions first.
          // OperationException wraps both network-level and GraphQL-level errors.
          if (result.hasException) {
            return Center(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  const Icon(Icons.error_outline, size: 48, color: Colors.red),
                  const SizedBox(height: 12),
                  Text(
                    result.exception?.graphqlErrors.firstOrNull?.message
                        ?? result.exception?.linkException.toString()
                        ?? 'An error occurred',
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 16),
                  ElevatedButton(
                    onPressed: refetch,
                    child: const Text('Try Again'),
                  ),
                ],
              ),
            );
          }

          // isLoading is true only on the initial load when no cached data
          // exists. With cacheAndNetwork, if cache data is available,
          // isLoading is false even while a background request is running.
          if (result.isLoading &amp;&amp; result.data == null) {
            return const Center(child: CircularProgressIndicator());
          }

          // result.data is a Map&lt;String, dynamic&gt; that mirrors
          // the shape you declared in your query's selection set.
          final List&lt;dynamic&gt;? posts =
              result.data?['allPosts'] as List&lt;dynamic&gt;?;

          if (posts == null || posts.isEmpty) {
            return const Center(child: Text('No posts found.'));
          }

          return RefreshIndicator(
            onRefresh: () async =&gt; refetch?.call(),
            child: ListView.builder(
              itemCount: posts.length,
              itemBuilder: (context, index) {
                final post = posts[index] as Map&lt;String, dynamic&gt;;
                return PostCard(post: post);
              },
            ),
          );
        },
      ),
    );
  }
}

class PostCard extends StatelessWidget {
  final Map&lt;String, dynamic&gt; post;

  const PostCard({super.key, required this.post});

  @override
  Widget build(BuildContext context) {
    final author = post['author'] as Map&lt;String, dynamic&gt;?;

    return Card(
      margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
      child: ListTile(
        leading: author?['profilePic'] != null
            ? CircleAvatar(
                backgroundImage:
                    NetworkImage(author!['profilePic'] as String),
              )
            : const CircleAvatar(child: Icon(Icons.person)),
        title: Text(post['title'] as String? ?? ''),
        subtitle: Text('By ${author?['name'] ?? 'Unknown'}'),
        trailing: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Icon(Icons.favorite, color: Colors.red, size: 16),
            const SizedBox(width: 4),
            Text('${post['likeCount'] ?? 0}'),
          ],
        ),
      ),
    );
  }
}
</code></pre>
<p>The <code>cacheAndNetwork</code> fetch policy is worth emphasizing. When a user navigates to this screen for the second time, the cached data renders with zero network wait. Simultaneously, a network request runs in the background. When it completes, the widget rebuilds with the fresh data.</p>
<p>The builder is called twice: once with the cached data and once with the updated network data. For most feed-style screens, this produces the best user experience: instant perceived performance combined with freshness.</p>
<h3 id="heading-using-hooks-for-queries">Using Hooks for Queries</h3>
<p>If your team prefers a more functional style, <code>graphql_flutter</code> provides the <code>useQuery</code> hook that works with <code>flutter_hooks</code>. The behavior is identical to the <code>Query</code> widget, but the API avoids deeply nested builder functions:</p>
<pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

// HookWidget replaces StatelessWidget when using hooks.
class PostListScreen extends HookWidget {
  const PostListScreen({super.key});

  @override
  Widget build(BuildContext context) {
    // useQuery returns a QueryHookResult containing the result and helpers.
    final queryResult = useQuery(
      QueryOptions(
        document: gql(fetchPostsQuery),
        variables: const {'limit': 10, 'page': 1},
        fetchPolicy: FetchPolicy.cacheAndNetwork,
      ),
    );

    final result = queryResult.result;
    final refetch = queryResult.refetch;

    if (result.hasException) {
      return Scaffold(
        body: Center(child: Text(result.exception.toString())),
      );
    }

    if (result.isLoading &amp;&amp; result.data == null) {
      return const Scaffold(
        body: Center(child: CircularProgressIndicator()),
      );
    }

    final posts = result.data?['allPosts'] as List&lt;dynamic&gt;? ?? [];

    return Scaffold(
      appBar: AppBar(title: const Text('Posts')),
      body: RefreshIndicator(
        onRefresh: () async =&gt; refetch(),
        child: ListView.builder(
          itemCount: posts.length,
          itemBuilder: (context, index) {
            final post = posts[index] as Map&lt;String, dynamic&gt;;
            return PostCard(post: post);
          },
        ),
      ),
    );
  }
}
</code></pre>
<p>Both styles are fully supported and functionally equivalent. The widget-based API is more approachable for developers coming from non-React backgrounds. The hooks API produces cleaner code when a widget composes multiple operations, because it avoids the callback nesting that builders introduce.</p>
<h3 id="heading-mutations-triggering-data-changes">Mutations: Triggering Data Changes</h3>
<p>The <code>Mutation</code> widget gives you a <code>RunMutation</code> function in its builder. Unlike <code>Query</code>, which executes automatically on render, <code>Mutation</code> waits for you to call <code>runMutation</code>. Mutations are triggered by user actions, not automatically on widget construction.</p>
<pre><code class="language-dart">const String likePostMutation = r'''
  mutation LikePost($postId: ID!) {
    likePost(postId: $postId) {
      id
      likeCount
      viewerHasLiked
    }
  }
''';

class LikeButton extends StatelessWidget {
  final String postId;
  final bool initiallyLiked;
  final int likeCount;

  const LikeButton({
    super.key,
    required this.postId,
    required this.initiallyLiked,
    required this.likeCount,
  });

  @override
  Widget build(BuildContext context) {
    return Mutation(
      options: MutationOptions(
        document: gql(likePostMutation),

        // update runs after the mutation completes.
        // Because our mutation returns the updated post with its id,
        // likeCount, and viewerHasLiked, the cache can normalize the result.
        // It updates the cached Post:postId object automatically, and any
        // Query widget that previously fetched this post rebuilds with the
        // new like count. Manual cache writes are only needed when you are
        // adding or removing items from cached lists.
        update: (GraphQLDataProxy cache, QueryResult? result) {
          // Automatic normalization handles this case cleanly.
        },

        // onCompleted runs after a successful mutation.
        // Use it for side effects: snackbars, navigation, analytics events.
        onCompleted: (dynamic resultData) {
          if (resultData != null) {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Post liked!')),
            );
          }
        },

        // onError handles mutation failures.
        onError: (OperationException? error) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(
              content: Text(
                error?.graphqlErrors.firstOrNull?.message
                    ?? 'Failed to like post',
              ),
            ),
          );
        },
      ),

      // runMutation: call this to fire the mutation.
      // result: the state of the last mutation run, null before the first call.
      builder: (RunMutation runMutation, QueryResult? result) {
        final isLoading = result?.isLoading ?? false;
        final hasLiked = result?.data?['likePost']?['viewerHasLiked'] as bool?
            ?? initiallyLiked;
        final currentCount =
            result?.data?['likePost']?['likeCount'] as int? ?? likeCount;

        return GestureDetector(
          onTap: isLoading
              ? null
              : () =&gt; runMutation({'postId': postId}),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              isLoading
                  ? const SizedBox(
                      width: 20,
                      height: 20,
                      child: CircularProgressIndicator(strokeWidth: 2),
                    )
                  : Icon(
                      hasLiked ? Icons.favorite : Icons.favorite_border,
                      color: hasLiked ? Colors.red : Colors.grey,
                    ),
              const SizedBox(width: 4),
              Text('$currentCount'),
            ],
          ),
        );
      },
    );
  }
}
</code></pre>
<p>The relationship between <code>update</code>, <code>onCompleted</code>, and <code>onError</code> is a frequent source of confusion. Think of them this way: <code>update</code> is for cache operations and runs even for optimistic results, <code>onCompleted</code> is for side effects after success, and <code>onError</code> is for side effects after failure.</p>
<p>Never put navigation logic inside <code>update</code> because it runs before the widget rebuild cycle is complete, which leads to navigation errors.</p>
<h3 id="heading-subscriptions-receiving-real-time-events">Subscriptions: Receiving Real-Time Events</h3>
<p>The <code>Subscription</code> widget opens a WebSocket connection and calls its builder function every time the server pushes a new event. Each call to the builder receives the latest single event, not an accumulated history of all past events. Accumulating and managing state over time is your responsibility as the developer.</p>
<pre><code class="language-dart">const String commentAddedSubscription = r'''
  subscription CommentAdded($postId: ID!) {
    commentAdded(postId: $postId) {
      id
      text
      author {
        id
        name
        profilePic
      }
    }
  }
''';

class CommentsSection extends StatefulWidget {
  final String postId;
  const CommentsSection({super.key, required this.postId});

  @override
  State&lt;CommentsSection&gt; createState() =&gt; _CommentsSectionState();
}

class _CommentsSectionState extends State&lt;CommentsSection&gt; {
  final List&lt;Map&lt;String, dynamic&gt;&gt; _comments = [];

  @override
  Widget build(BuildContext context) {
    return Subscription(
      options: SubscriptionOptions(
        document: gql(commentAddedSubscription),
        variables: {'postId': widget.postId},
      ),
      builder: (QueryResult result) {
        if (result.isLoading) {
          // For subscriptions, isLoading means the WebSocket connection
          // is being established, not that server data is loading.
          return const Center(child: CircularProgressIndicator());
        }

        if (result.hasException) {
          return Text('Subscription error: ${result.exception}');
        }

        if (result.data != null) {
          final newComment =
              result.data!['commentAdded'] as Map&lt;String, dynamic&gt;?;
          if (newComment != null) {
            // addPostFrameCallback prevents calling setState during
            // the current build phase, which would throw a Flutter error.
            WidgetsBinding.instance.addPostFrameCallback((_) {
              if (mounted) {
                setState(() {
                  final exists =
                      _comments.any((c) =&gt; c['id'] == newComment['id']);
                  if (!exists) _comments.insert(0, newComment);
                });
              }
            });
          }
        }

        if (_comments.isEmpty) {
          return const Center(child: Text('No comments yet. Be the first!'));
        }

        return ListView.builder(
          itemCount: _comments.length,
          itemBuilder: (context, index) {
            final comment = _comments[index];
            final author = comment['author'] as Map&lt;String, dynamic&gt;?;
            return ListTile(
              leading: CircleAvatar(
                backgroundImage: author?['profilePic'] != null
                    ? NetworkImage(author!['profilePic'] as String)
                    : null,
                child: author?['profilePic'] == null
                    ? const Icon(Icons.person)
                    : null,
              ),
              title: Text(author?['name'] as String? ?? 'Anonymous'),
              subtitle: Text(comment['text'] as String? ?? ''),
            );
          },
        );
      },
    );
  }
}
</code></pre>
<p>In production code, you wouldn't manage subscription state in a <code>StatefulWidget</code>. Instead, you would stream subscription events into a Bloc or provider that accumulates them, and the widget would simply render the state emitted by that Bloc.</p>
<h2 id="heading-advanced-concepts">Advanced Concepts</h2>
<h3 id="heading-caching-strategies-choosing-the-right-policy">Caching Strategies: Choosing the Right Policy</h3>
<p>Picking the correct fetch policy for each query is one of the most impactful decisions you make in a GraphQL Flutter app. The wrong policy makes your app feel slow or shows stale data at the wrong moment. The right policy makes it feel native.</p>
<p><code>FetchPolicy.cacheFirst</code> checks the cache before touching the network. If the data is already cached, it returns immediately without making a network request. A network call only happens if the cache has nothing.</p>
<p>Use this for data that almost never changes during a session, like a list of countries, a user's account settings, or configuration values loaded at startup.</p>
<p><code>FetchPolicy.cacheAndNetwork</code> returns cached data immediately while firing a background network request simultaneously. When the network response arrives, the cache updates and the widget rebuilds with fresh data.</p>
<p>This is the right default for most content screens: fast perceived load from the cache, with freshness guaranteed by the background fetch.</p>
<p><code>FetchPolicy.networkOnly</code> always goes to the network and ignores the cache completely for reading. The response is still written to the cache for future use.</p>
<p>Use this when data freshness is non-negotiable, such as a bank balance, live inventory count, or the result of a payment operation.</p>
<p><code>FetchPolicy.cacheOnly</code> reads exclusively from the cache and never makes a network request. If the data isn't cached, it returns null.</p>
<p>This is primarily useful in offline-first apps where you have pre-populated the cache and want to guarantee no network calls.</p>
<p><code>FetchPolicy.noCache</code> always goes to the network and does not read from or write to the cache. Use this for one-time operations where caching would be actively harmful.</p>
<pre><code class="language-dart">// Account settings -- loaded once, changes rarely during a session
QueryOptions(
  document: gql(getUserSettingsQuery),
  fetchPolicy: FetchPolicy.cacheFirst,
)

// News feed -- instant load from cache, background refresh for freshness
QueryOptions(
  document: gql(getNewsFeedQuery),
  fetchPolicy: FetchPolicy.cacheAndNetwork,
)

// Payment history -- must always reflect the server's current state
QueryOptions(
  document: gql(getPaymentHistoryQuery),
  fetchPolicy: FetchPolicy.networkOnly,
)
</code></pre>
<h3 id="heading-pagination-with-fetchmore">Pagination with fetchMore</h3>
<p>Most real apps deal with lists too large to load at once. The <code>fetchMore</code> function exposed in the <code>Query</code> builder handles pagination by executing a new query and merging its results with the existing ones.</p>
<pre><code class="language-dart">const String fetchPostsWithPaginationQuery = r'''
  query FetchPosts(\(cursor: String, \)limit: Int!) {
    postsConnection(after: \(cursor, first: \)limit) {
      edges {
        node {
          id
          title
          likeCount
        }
        cursor
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
''';

class PaginatedPostList extends StatelessWidget {
  const PaginatedPostList({super.key});

  @override
  Widget build(BuildContext context) {
    return Query(
      options: QueryOptions(
        document: gql(fetchPostsWithPaginationQuery),
        variables: const {'limit': 10, 'cursor': null},
        fetchPolicy: FetchPolicy.cacheAndNetwork,
      ),
      builder: (QueryResult result, {VoidCallback? refetch, FetchMore? fetchMore}) {
        if (result.isLoading &amp;&amp; result.data == null) {
          return const Center(child: CircularProgressIndicator());
        }

        final connection =
            result.data?['postsConnection'] as Map&lt;String, dynamic&gt;?;
        final edges = connection?['edges'] as List&lt;dynamic&gt;? ?? [];
        final pageInfo =
            connection?['pageInfo'] as Map&lt;String, dynamic&gt;?;
        final hasNextPage = pageInfo?['hasNextPage'] as bool? ?? false;
        final endCursor = pageInfo?['endCursor'] as String?;

        return ListView.builder(
          itemCount: edges.length + (hasNextPage ? 1 : 0),
          itemBuilder: (context, index) {
            if (index == edges.length) {
              return Padding(
                padding: const EdgeInsets.all(16),
                child: ElevatedButton(
                  onPressed: () {
                    final FetchMoreOptions opts = FetchMoreOptions(
                      variables: {'cursor': endCursor, 'limit': 10},

                      // updateQuery merges the new page with all previous data.
                      // You must return the merged dataset from this function.
                      // previousResultData: everything fetched so far.
                      // fetchMoreResultData: the data from this new page only.
                      updateQuery: (previousResultData, fetchMoreResultData) {
                        final List&lt;dynamic&gt; allEdges = [
                          ...previousResultData['postsConnection']['edges']
                              as List&lt;dynamic&gt;,
                          ...fetchMoreResultData['postsConnection']['edges']
                              as List&lt;dynamic&gt;,
                        ];
                        // Assign the merged list into fetchMoreResultData
                        // and return it. The library uses the returned
                        // value as the new authoritative result for the query.
                        fetchMoreResultData['postsConnection']['edges'] = allEdges;
                        return fetchMoreResultData;
                      },
                    );

                    fetchMore!(opts);
                  },
                  child: const Text('Load More'),
                ),
              );
            }

            final node = edges[index]['node'] as Map&lt;String, dynamic&gt;;
            return PostCard(post: node);
          },
        );
      },
    );
  }
}
</code></pre>
<p>The most common mistake with <code>fetchMore</code> is mutating <code>previousResultData</code> directly instead of building a new list. Always treat both arguments as read-only, construct the merged list as a new object, assign it into <code>fetchMoreResultData</code>, and return <code>fetchMoreResultData</code>.</p>
<h3 id="heading-optimistic-ui-updates">Optimistic UI Updates</h3>
<p><a href="https://www.freecodecamp.org/news/how-to-use-the-optimistic-ui-pattern-with-the-useoptimistic-hook-in-react/">Optimistic UI</a> is a pattern where the interface updates immediately after a user action, before the server has confirmed the change. If the server confirms, the optimistic data is silently replaced with the authoritative server data. If the server rejects the change, the cache rolls back to its pre-mutation state automatically.</p>
<p>The result is an app that feels dramatically faster. The user taps a like button, the heart turns red, and the count increments instantly. No spinner, no wait. If the network request fails, the UI reverts cleanly without any manual rollback code.</p>
<pre><code class="language-dart">Mutation(
  options: MutationOptions(
    document: gql(likePostMutation),
    update: (GraphQLDataProxy cache, QueryResult? result) {
      // When the real server response arrives, the cache normalizes
      // it automatically, replacing the optimistic values with the
      // server's authoritative data.
    },
  ),
  builder: (RunMutation runMutation, QueryResult? result) {
    return IconButton(
      onPressed: () {
        runMutation(
          {'postId': postId},
          // optimisticResult must exactly match the shape of your
          // mutation's return type, including __typename.
          // The cache uses __typename + id as the normalization key.
          optimisticResult: {
            'likePost': {
              '__typename': 'Post',
              'id': postId,
              'likeCount': currentLikeCount + 1,
              'viewerHasLiked': true,
            }
          },
        );
      },
      icon: const Icon(Icons.favorite_border),
    );
  },
);
</code></pre>
<p>When <code>runMutation</code> is called with an <code>optimisticResult</code>, the cache immediately applies those values and broadcasts updates to every widget that holds data for that cached object. When the real network response arrives moments later, the cache updates once more with the server's values, triggering a final rebuild.</p>
<h3 id="heading-error-handling-a-production-grade-approach">Error Handling: A Production-Grade Approach</h3>
<p>GraphQL errors come in two distinct categories, and handling both correctly is essential for a reliable production app.</p>
<p><strong>Network errors</strong> occur at the transport layer: no internet connection, DNS failure, server unreachable, or connection timeout. These surface as a <code>LinkException</code> inside <code>result.exception</code>.</p>
<p><strong>GraphQL errors</strong> occur inside the GraphQL execution layer: authentication failures, authorization violations, schema validation errors, or custom business logic errors defined by your server team. These surface as a list of <code>GraphQLError</code> objects.</p>
<p>Importantly, GraphQL allows partial results where a response contains both <code>data</code> and <code>errors</code> simultaneously, if some fields resolved successfully and some failed.</p>
<pre><code class="language-dart">Widget _buildFromResult(
    BuildContext context, QueryResult result, VoidCallback? refetch) {
  if (result.hasException) {
    final exception = result.exception!;

    // Check for network-level errors first
    if (exception.linkException != null) {
      if (exception.linkException is NetworkException) {
        return _NoInternetWidget(onRetry: refetch);
      }
      return _ServerErrorWidget(onRetry: refetch);
    }

    // Check for GraphQL-level errors
    if (exception.graphqlErrors.isNotEmpty) {
      final firstError = exception.graphqlErrors.first;
      // Many servers include a machine-readable code in the extensions map
      final errorCode = firstError.extensions?['code'] as String?;

      switch (errorCode) {
        case 'UNAUTHENTICATED':
          WidgetsBinding.instance.addPostFrameCallback((_) {
            Navigator.of(context).pushReplacementNamed('/login');
          });
          return const SizedBox.shrink();

        case 'FORBIDDEN':
          return const _AccessDeniedWidget();

        case 'NOT_FOUND':
          return const _NotFoundWidget();

        default:
          return _GenericErrorWidget(
            message: firstError.message,
            onRetry: refetch,
          );
      }
    }
  }

  // success state handled here...
  return const SizedBox.shrink();
}
</code></pre>
<h3 id="heading-authentication-transparent-token-refresh">Authentication: Transparent Token Refresh</h3>
<p>In production apps, access tokens expire. Rather than letting expired tokens cause request failures that users must recover from manually, you can build a custom link that intercepts authentication errors and refreshes the token transparently before retrying the original request.</p>
<pre><code class="language-dart">class AuthRefreshLink extends Link {
  final Future&lt;String?&gt; Function() refreshToken;
  final Future&lt;void&gt; Function() onAuthFailure;

  AuthRefreshLink({required this.refreshToken, required this.onAuthFailure});

  @override
  Stream&lt;Response&gt; request(Request request, [NextLink? forward]) async* {
    await for (final result in forward!(request)) {
      final isAuthError = (result.errors ?? [])
          .any((e) =&gt; e.extensions?['code'] == 'UNAUTHENTICATED');

      if (isAuthError) {
        final newToken = await refreshToken();

        if (newToken == null) {
          await onAuthFailure(); // Trigger logout
          return;
        }

        // Retry the original request with the new token
        final retryRequest = request.updateContextEntry&lt;HttpLinkHeaders&gt;(
          (headers) =&gt; HttpLinkHeaders(
            headers: {
              ...headers?.headers ?? {},
              'Authorization': 'Bearer $newToken',
            },
          ),
        );

        yield* forward(retryRequest);
      } else {
        yield result;
      }
    }
  }
}
</code></pre>
<p>This link sits in the chain before <code>HttpLink</code>. When an <code>UNAUTHENTICATED</code> error arrives, it refreshes the token, replays the original request, and the widget receives the successful data as if nothing unusual occurred. If the token refresh itself fails, <code>onAuthFailure</code> is called, which triggers a logout flow.</p>
<h2 id="heading-best-practices-in-real-apps">Best Practices in Real Apps</h2>
<h3 id="heading-project-structure-that-scales">Project Structure That Scales</h3>
<p>Scattering query strings across widget files is one of the fastest ways to create an unmaintainable codebase. Here's a folder structure that keeps GraphQL operations organized and consistently discoverable:</p>
<pre><code class="language-plaintext">lib/
  graphql/
    client.dart              -- GraphQLClient setup, exported globally
    queries/
      post_queries.dart      -- All post-related queries
      user_queries.dart      -- All user-related queries
    mutations/
      post_mutations.dart
      auth_mutations.dart
    subscriptions/
      comment_subs.dart
    fragments/
      post_fragments.dart    -- Reusable post field sets
      user_fragments.dart    -- Reusable user field sets

  models/
    post.dart                -- Typed Dart models parsed from GraphQL data
    user.dart

  repositories/
    post_repository.dart     -- Data access abstraction layer

  blocs/
    post_bloc.dart           -- Business logic and state

  screens/
    post_list/
      post_list_screen.dart
      widgets/
        post_card.dart
        like_button.dart
</code></pre>
<h3 id="heading-composing-queries-from-fragments">Composing Queries from Fragments</h3>
<p>Define fragments in dedicated files and compose queries by string interpolation. This ensures that field sets stay consistent across queries and schema changes propagate from a single definition:</p>
<pre><code class="language-dart">// lib/graphql/fragments/post_fragments.dart

const String postBasicFieldsFragment = r'''
  fragment PostBasicFields on Post {
    id
    title
    publishedAt
    likeCount
  }
''';

const String postAuthorFragment = r'''
  fragment PostAuthorFields on Post {
    author {
      id
      name
      profilePic
    }
  }
''';
</code></pre>
<pre><code class="language-dart">// lib/graphql/queries/post_queries.dart

import 'package:your_app/graphql/fragments/post_fragments.dart';

const String fetchPostsQuery = '''
  $postBasicFieldsFragment
  $postAuthorFragment

  query FetchPosts(\\(limit: Int!, \\)page: Int!) {
    allPosts(limit: \\(limit, page: \\)page) {
      ...PostBasicFields
      ...PostAuthorFields
    }
  }
''';
</code></pre>
<h3 id="heading-parsing-graphql-data-into-typed-models">Parsing GraphQL Data into Typed Models</h3>
<p>Working directly with <code>Map&lt;String, dynamic&gt;</code> throughout your business logic is fragile and error-prone. A typo in a string key causes a silent null at runtime, not a compile-time error. Define typed model classes and parse the GraphQL response at the data layer boundary:</p>
<pre><code class="language-dart">// lib/models/post.dart

class Post {
  final String id;
  final String title;
  final String content;
  final int likeCount;
  final DateTime publishedAt;
  final User author;

  const Post({
    required this.id,
    required this.title,
    required this.content,
    required this.likeCount,
    required this.publishedAt,
    required this.author,
  });

  factory Post.fromMap(Map&lt;String, dynamic&gt; map) {
    return Post(
      id: map['id'] as String,
      title: map['title'] as String,
      content: map['content'] as String,
      likeCount: map['likeCount'] as int? ?? 0,
      publishedAt: DateTime.parse(map['publishedAt'] as String),
      author: User.fromMap(map['author'] as Map&lt;String, dynamic&gt;),
    );
  }
}
</code></pre>
<h3 id="heading-integrating-with-bloc-and-a-repository-layer">Integrating with Bloc and a Repository Layer</h3>
<p>For production apps, placing <code>Query</code> and <code>Mutation</code> widgets directly in your screens couples your UI tightly to GraphQL. Introducing a repository layer that wraps GraphQL operations, with Bloc mediating between the repository and the UI, gives you proper separation of concerns:</p>
<pre><code class="language-dart">// lib/repositories/post_repository.dart

class PostRepository {
  final GraphQLClient _client;

  PostRepository(this._client);

  Future&lt;List&lt;Post&gt;&gt; fetchPosts({int page = 1, int limit = 10}) async {
    final result = await _client.query(
      QueryOptions(
        document: gql(fetchPostsQuery),
        variables: {'page': page, 'limit': limit},
        fetchPolicy: FetchPolicy.cacheAndNetwork,
      ),
    );

    if (result.hasException) throw _mapException(result.exception!);

    return (result.data!['allPosts'] as List&lt;dynamic&gt;)
        .cast&lt;Map&lt;String, dynamic&gt;&gt;()
        .map(Post.fromMap)
        .toList();
  }

  Future&lt;Post&gt; likePost(String postId) async {
    final result = await _client.mutate(
      MutationOptions(
        document: gql(likePostMutation),
        variables: {'postId': postId},
      ),
    );

    if (result.hasException) throw _mapException(result.exception!);

    return Post.fromMap(
      result.data!['likePost'] as Map&lt;String, dynamic&gt;,
    );
  }

  Stream&lt;Post&gt; watchNewPosts() {
    return _client
        .subscribe(
            SubscriptionOptions(document: gql(postAddedSubscription)))
        .where((result) =&gt; !result.hasException &amp;&amp; result.data != null)
        .map((result) =&gt; Post.fromMap(
              result.data!['postAdded'] as Map&lt;String, dynamic&gt;,
            ));
  }

  Exception _mapException(OperationException e) {
    if (e.linkException != null) {
      return NetworkException('No internet connection');
    }
    return ApiException(
      e.graphqlErrors.firstOrNull?.message ?? 'Unknown error',
    );
  }
}
</code></pre>
<p>With this architecture, your Bloc knows nothing about GraphQL. Your screens know nothing about GraphQL. GraphQL is an implementation detail of the repository. Your UI and business logic can be unit tested without mocking GraphQL at all, which is the mark of a well-structured data layer.</p>
<h2 id="heading-when-to-use-graphql-and-when-not-to">When to Use GraphQL and When Not To</h2>
<h3 id="heading-where-graphql-excels">Where GraphQL Excels</h3>
<p>GraphQL is the right choice when your application is genuinely complex and data-intensive. If your screens need data from multiple related entities simultaneously, and different screens need different subsets of the same underlying data, client-driven fetching pays for itself almost immediately.</p>
<p>Mobile apps are a particularly strong fit because bandwidth and battery are constrained resources, and the precision of GraphQL queries has a direct, measurable impact on both.</p>
<p>It also makes excellent sense when you serve multiple client types: a web app, a mobile app, a tablet layout, and perhaps a smartwatch companion, all consuming the same API. With REST, you either build bespoke endpoints for each client or force every client to over-fetch from a generic endpoint. With GraphQL, each client queries precisely what it needs from a single unified schema.</p>
<p>Real-time features are a natural fit as well. Subscriptions are a first-class part of the GraphQL protocol, not an afterthought. Combined with the normalized cache, new data arriving over a subscription can update cached objects that multiple screens share simultaneously.</p>
<p>And if your team values strong typing and self-documenting APIs, GraphQL delivers in a way that REST can't match without substantial additional tooling. The schema is a living, explorable contract. Combined with code generation tools like <code>graphql_codegen</code>, you can achieve end-to-end type safety from the schema definition all the way to your Dart widgets.</p>
<h3 id="heading-where-graphql-is-the-wrong-choice">Where GraphQL is the Wrong Choice</h3>
<p>GraphQL adds genuine complexity: a schema to maintain, resolvers to write, a link chain to configure, and a normalized cache whose behavior you must understand deeply to use correctly.</p>
<p>For simple CRUD applications like a settings screen, a contact form, or a basic registration flow, that complexity rarely pays off. REST is simpler to set up, simpler to debug, and more familiar to a wider range of developers.</p>
<p>If your team has no prior GraphQL experience and you're under a tight delivery deadline, the learning curve is real and legitimate. GraphQL can slow a team down before it speeds them up. That tradeoff deserves honest consideration before committing to the technology.</p>
<p>File uploads, while technically possible in GraphQL via the multipart request spec, are more complex to implement than a straightforward multipart POST to a REST endpoint. If uploading files is a core part of your app's functionality, REST handles it more naturally.</p>
<p>GraphQL is also harder to explore for third-party developers who want to test your API with simple curl commands. For public-facing developer APIs intended to be accessible to a broad audience with diverse tooling, REST is the more approachable and conventional choice.</p>
<h2 id="heading-common-mistakes">Common Mistakes</h2>
<h3 id="heading-ignoring-how-the-normalized-cache-works">Ignoring How the Normalized Cache Works</h3>
<p>The most widespread mistake among developers new to GraphQL is not understanding normalization and then fighting the cache. You run a mutation, the server updates the data, but the UI doesn't refresh.</p>
<p>This typically happens for one of three reasons:</p>
<ol>
<li><p>The mutation doesn't return the updated fields, so the cache receives no new data to normalize. Always return the full set of fields your UI needs from every mutation response.</p>
</li>
<li><p>The returned object doesn't include an <code>id</code> field, and often <code>__typename</code> as well, so the cache can't identify which stored object to update. The cache uses <code>__typename</code> concatenated with <code>id</code> as the cache key. If either is missing, normalization fails silently and the update has no visible effect.</p>
</li>
<li><p>The mutation adds or removes an item from a list, and the cache doesn't update the list automatically. The cache only updates objects it can identify by their key. It has no mechanism for knowing that a new comment should be appended to a post's comment list. You must handle list mutations manually in the <code>update</code> callback using <code>cache.writeQuery</code> or <code>cache.writeFragment</code>.</p>
</li>
</ol>
<h3 id="heading-defining-query-strings-inside-the-build-method">Defining Query Strings Inside the Build Method</h3>
<p>When a query string is defined as a local variable inside <code>build()</code>, Dart recreates it on every rebuild, and <code>gql()</code> re-parses the string into an AST document object on every call. For simple widgets this is inconsequential in isolation, but it's unnecessary work that compounds across a complex widget tree. Always define query strings as top-level <code>const</code> values:</p>
<pre><code class="language-dart">// Wrong -- recreated and re-parsed on every build() call
Widget build(BuildContext context) {
  final query = '''
    query { ... }
  ''';
  return Query(options: QueryOptions(document: gql(query)), ...);
}

// Right -- parsed once at startup, reused across every rebuild
const String myQuery = r'''
  query { ... }
''';

Widget build(BuildContext context) {
  return Query(options: QueryOptions(document: gql(myQuery)), ...);
}
</code></pre>
<h3 id="heading-using-networkonly-for-everything">Using <code>networkOnly</code> for Everything</h3>
<p>Some developers, burned by stale cache bugs, set every single query to <code>networkOnly</code>. This solves the staleness problem by creating several others: slower perceived performance (no instant cached data), higher data consumption, faster battery drain, and a broken offline experience where every screen shows an error instead of previously loaded content.</p>
<p>The correct approach is to choose the appropriate fetch policy for each query based on how time-sensitive that data is. Don't apply a blanket policy across all queries.</p>
<h3 id="heading-forgetting-to-cancel-subscriptions">Forgetting to Cancel Subscriptions</h3>
<p>The <code>Subscription</code> widget manages its WebSocket connection automatically: it opens when the widget enters the tree and closes when the widget leaves.</p>
<p>But if you use the client's <code>subscribe()</code> method directly inside a Bloc or any long-lived object, you receive a <code>Stream</code> that you must manage yourself. Subscriptions that are never cancelled are memory leaks that accumulate silently with every navigation event:</p>
<pre><code class="language-dart">class PostBloc extends Bloc&lt;PostEvent, PostState&gt; {
  StreamSubscription? _commentSubscription;

  void startListeningToComments(String postId) {
    _commentSubscription = _repository
        .watchNewComments(postId)
        .listen((comment) =&gt; add(CommentReceived(comment)));
  }

  @override
  Future&lt;void&gt; close() {
    _commentSubscription?.cancel(); // Always cancel before closing
    return super.close();
  }
}
</code></pre>
<h3 id="heading-not-handling-partial-graphql-results">Not Handling Partial GraphQL Results</h3>
<p>A GraphQL response can carry both <code>data</code> and <code>errors</code> simultaneously. This is a partial result: some resolvers succeeded and some failed. If you check only <code>result.hasException</code>, you may miss GraphQL errors that accompanied successfully resolved data.</p>
<p>Always inspect both <code>result.data</code> and <code>result.exception</code> and decide explicitly how your UI should behave in each combination.</p>
<h2 id="heading-mini-end-to-end-example">Mini End-to-End Example</h2>
<p>Let's build a complete, runnable application to put everything in context. We'll use the GitHub GraphQL API so you can run this immediately without setting up your own server. The app fetches the authenticated user's repositories and allows starring and unstarring them, demonstrating queries, mutations, and optimistic UI together in a single working codebase.</p>
<p>Generate a GitHub personal access token at <code>https://github.com/settings/tokens</code> with at least <code>read:user</code> and <code>repo</code> scopes before running the example.</p>
<h3 id="heading-the-graphql-client">The GraphQL Client</h3>
<pre><code class="language-dart">// lib/graphql/client.dart

import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';

// Never hardcode tokens in production.
// Use flutter_secure_storage or an equivalent secure mechanism.
const _githubToken = 'YOUR_GITHUB_TOKEN_HERE';

ValueNotifier&lt;GraphQLClient&gt; buildGitHubClient() {
  final httpLink = HttpLink('https://api.github.com/graphql');

  final authLink = AuthLink(
    getToken: () =&gt; 'Bearer $_githubToken',
  );

  return ValueNotifier(
    GraphQLClient(
      link: authLink.concat(httpLink),
      cache: GraphQLCache(store: HiveStore()),
    ),
  );
}
</code></pre>
<p>This file sets up a <strong>GraphQL client</strong> that our Flutter app will use to talk to GitHub’s GraphQL API.</p>
<p>It creates an HTTP connection to <code>https://api.github.com/graphql</code>, then adds an authentication layer using your GitHub token so every request includes a <code>Bearer</code> token.</p>
<p>These two parts are combined so requests are both authenticated and correctly sent to GitHub.</p>
<p>Finally, it enables caching using <code>GraphQLCache</code> with <code>HiveStore</code>, so data can be stored locally and reused instead of always fetching from the network.</p>
<p>In simple terms: it connects our app to GitHub, attaches our login token, and adds local caching for performance.</p>
<h3 id="heading-the-queries">The Queries</h3>
<pre><code class="language-dart">// lib/graphql/queries/repo_queries.dart

const String fetchViewerReposQuery = r'''
  query FetchViewerRepos($count: Int!) {
    viewer {
      login
      name
      avatarUrl
      repositories(
        first: $count
        orderBy: { field: STARGAZERS, direction: DESC }
        ownerAffiliations: [OWNER]
      ) {
        nodes {
          id
          name
          description
          stargazerCount
          primaryLanguage {
            name
            color
          }
          viewerHasStarred
        }
      }
    }
  }
''';
</code></pre>
<p>This file defines a <strong>GraphQL query</strong> that fetches data from GitHub about the currently authenticated user and their repositories.</p>
<p>The query is named <code>FetchViewerRepos</code> and it takes one variable, <code>$count</code>, which controls how many repositories to return.</p>
<p>It starts by asking for the <code>viewer</code>, which represents the logged-in user. From the viewer, it retrieves basic profile information like <code>login</code>, <code>name</code>, and <code>avatarUrl</code>.</p>
<p>Then it fetches the user’s <code>repositories</code>, limited by the <code>$count</code> variable. The repositories are sorted by the number of stars in descending order, and it only includes repositories where the user is the owner.</p>
<p>For each repository, it requests:</p>
<ul>
<li><p><code>id</code> (used for identifying and caching),</p>
</li>
<li><p><code>name</code>,</p>
</li>
<li><p><code>description</code>,</p>
</li>
<li><p><code>stargazerCount</code> (number of stars),</p>
</li>
<li><p><code>primaryLanguage</code> (including its name and color),</p>
</li>
<li><p><code>viewerHasStarred</code> (whether the current user has starred it).</p>
</li>
</ul>
<p>In simple terms, this query is asking: “Give me the logged-in user’s profile and a list of their most popular repositories, along with key details for each one.”</p>
<h3 id="heading-the-mutations">The Mutations</h3>
<pre><code class="language-dart">// lib/graphql/mutations/repo_mutations.dart

const String addStarMutation = r'''
  mutation AddStar($repoId: ID!) {
    addStar(input: { starrableId: $repoId }) {
      starrable {
        ... on Repository {
          id
          stargazerCount
          viewerHasStarred
        }
      }
    }
  }
''';

const String removeStarMutation = r'''
  mutation RemoveStar($repoId: ID!) {
    removeStar(input: { starrableId: $repoId }) {
      starrable {
        ... on Repository {
          id
          stargazerCount
          viewerHasStarred
        }
      }
    }
  }
''';
</code></pre>
<p>This file defines two <strong>GraphQL mutations</strong> that let our app star and unstar repositories on GitHub.</p>
<p>The first mutation, <code>addStarMutation</code>, is used to <strong>star a repository</strong>. It takes a variable called <code>$repoId</code>, which is the unique ID of the repository. When executed, it calls <code>addStar</code> with that ID. The response returns the updated repository data, specifically:</p>
<ul>
<li><p>the <code>id</code>,</p>
</li>
<li><p>the updated <code>stargazerCount</code> (number of stars),</p>
</li>
<li><p>and <code>viewerHasStarred</code> (which becomes <code>true</code> after starring).</p>
</li>
</ul>
<p>The second mutation, <code>removeStarMutation</code>, does the opposite. It <strong>removes a star</strong> from a repository using the same <code>$repoId</code>. It calls <code>removeStar</code>, and the response again returns:</p>
<ul>
<li><p><code>id</code>,</p>
</li>
<li><p>updated <code>stargazerCount</code>,</p>
</li>
<li><p>and <code>viewerHasStarred</code> (which becomes <code>false</code> after unstarring).</p>
</li>
</ul>
<p>Both mutations use a GraphQL concept called <strong>inline fragments</strong> (<code>... on Repository</code>) to ensure the returned data is specifically treated as a <code>Repository</code> type.</p>
<p>In simple terms: one mutation adds a star, the other removes it, and both return the updated repository state so your UI can update immediately.</p>
<h3 id="heading-the-entry-point">The Entry Point</h3>
<pre><code class="language-dart">// lib/main.dart

import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'graphql/client.dart';
import 'screens/repos_screen.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await initHiveForFlutter();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return GraphQLProvider(
      client: buildGitHubClient(),
      child: MaterialApp(
        title: 'GitHub Repos',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
          useMaterial3: true,
        ),
        home: const ReposScreen(),
      ),
    );
  }
}
</code></pre>
<p>This is the <strong>entry point of our Flutter app</strong>, and it wires everything together.</p>
<p>The <code>main()</code> function first ensures Flutter is initialized with <code>WidgetsFlutterBinding.ensureInitialized()</code>, which is required before doing any async setup. Then it calls <code>initHiveForFlutter()</code>, which prepares Hive for local storage. This is needed because our GraphQL client uses Hive for caching. After that, it runs the app by calling <code>runApp()</code>.</p>
<p>The <code>MyApp</code> widget sets up the app’s structure. The most important part here is the <code>GraphQLProvider</code>, which injects your GraphQL client (from <code>buildGitHubClient()</code>) into the entire widget tree. This allows any widget in the app to make GraphQL queries and mutations without manually passing the client around.</p>
<p>Inside the <code>GraphQLProvider</code>, you define a <code>MaterialApp</code> with basic app settings like the title, theme, and disabling the debug banner. The home screen is set to <code>ReposScreen</code>, which means that screen will be the first thing users see when the app launches.</p>
<h3 id="heading-the-repos-screen">The Repos Screen</h3>
<pre><code class="language-dart">// lib/screens/repos_screen.dart

import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import '../graphql/queries/repo_queries.dart';
import '../graphql/mutations/repo_mutations.dart';

class ReposScreen extends StatelessWidget {
  const ReposScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Query(
      options: QueryOptions(
        document: gql(fetchViewerReposQuery),
        variables: const {'count': 15},
        fetchPolicy: FetchPolicy.cacheAndNetwork,
      ),
      builder: (QueryResult result,
          {VoidCallback? refetch, FetchMore? fetchMore}) {
        if (result.isLoading &amp;&amp; result.data == null) {
          return const Scaffold(
            body: Center(child: CircularProgressIndicator()),
          );
        }

        if (result.hasException) {
          return Scaffold(
            body: Center(
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  const Icon(Icons.error_outline,
                      size: 48, color: Colors.red),
                  const SizedBox(height: 12),
                  Text(
                    result.exception?.graphqlErrors.firstOrNull?.message
                        ?? 'An error occurred',
                    textAlign: TextAlign.center,
                  ),
                  const SizedBox(height: 16),
                  ElevatedButton(
                    onPressed: refetch,
                    child: const Text('Retry'),
                  ),
                ],
              ),
            ),
          );
        }

        final viewer =
            result.data?['viewer'] as Map&lt;String, dynamic&gt;?;
        final repos =
            (viewer?['repositories']?['nodes'] as List&lt;dynamic&gt;?)
                    ?.cast&lt;Map&lt;String, dynamic&gt;&gt;() ??
                [];

        return Scaffold(
          appBar: AppBar(
            title: Row(
              children: [
                if (viewer?['avatarUrl'] != null)
                  CircleAvatar(
                    backgroundImage:
                        NetworkImage(viewer!['avatarUrl'] as String),
                    radius: 16,
                  ),
                const SizedBox(width: 8),
                Text(viewer?['name'] as String? ??
                    viewer?['login'] as String? ??
                    ''),
              ],
            ),
            // A subtle indicator that a background refresh is running
            bottom: result.isLoading
                ? const PreferredSize(
                    preferredSize: Size.fromHeight(2),
                    child: LinearProgressIndicator(),
                  )
                : null,
          ),
          body: RefreshIndicator(
            onRefresh: () async =&gt; refetch?.call(),
            child: ListView.separated(
              padding: const EdgeInsets.all(16),
              itemCount: repos.length,
              separatorBuilder: (_, __) =&gt; const SizedBox(height: 8),
              itemBuilder: (context, index) =&gt;
                  RepoCard(repo: repos[index]),
            ),
          ),
        );
      },
    );
  }
}

class RepoCard extends StatelessWidget {
  final Map&lt;String, dynamic&gt; repo;

  const RepoCard({super.key, required this.repo});

  @override
  Widget build(BuildContext context) {
    final language =
        repo['primaryLanguage'] as Map&lt;String, dynamic&gt;?;
    final isStarred = repo['viewerHasStarred'] as bool? ?? false;
    final starCount = repo['stargazerCount'] as int? ?? 0;
    final repoId = repo['id'] as String;
    final mutationDoc = isStarred ? removeStarMutation : addStarMutation;
    final mutationKey = isStarred ? 'removeStar' : 'addStar';

    return Mutation(
      options: MutationOptions(
        document: gql(mutationDoc),
        // The mutation returns id, stargazerCount, and viewerHasStarred.
        // The cache normalizes the updated repository by id and broadcasts
        // the change to all widgets holding data for this repository.
        onError: (error) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(
              content: Text(
                error?.graphqlErrors.firstOrNull?.message
                    ?? 'Action failed',
              ),
            ),
          );
        },
      ),
      builder: (RunMutation runMutation, QueryResult? mutationResult) {
        final isMutating = mutationResult?.isLoading ?? false;

        // Prefer values from the mutation result (including optimistic)
        // over the original query data so the UI reflects the latest state.
        final starrable =
            (mutationResult?.data?[mutationKey] as Map&lt;String, dynamic&gt;?)?[
                'starrable'] as Map&lt;String, dynamic&gt;?;

        final currentStarred =
            starrable?['viewerHasStarred'] as bool? ?? isStarred;
        final currentCount =
            starrable?['stargazerCount'] as int? ?? starCount;

        return Card(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  children: [
                    Expanded(
                      child: Text(
                        repo['name'] as String? ?? '',
                        style: Theme.of(context)
                            .textTheme
                            .titleMedium
                            ?.copyWith(fontWeight: FontWeight.bold),
                      ),
                    ),
                    isMutating
                        ? const SizedBox(
                            width: 24,
                            height: 24,
                            child: CircularProgressIndicator(
                                strokeWidth: 2),
                          )
                        : IconButton(
                            onPressed: () =&gt; runMutation(
                              {'repoId': repoId},
                              // Optimistic result: update the UI instantly
                              // before the server responds.
                              optimisticResult: {
                                mutationKey: {
                                  'starrable': {
                                    '__typename': 'Repository',
                                    'id': repoId,
                                    'stargazerCount': isStarred
                                        ? starCount - 1
                                        : starCount + 1,
                                    'viewerHasStarred': !isStarred,
                                  }
                                }
                              },
                            ),
                            icon: Icon(
                              currentStarred
                                  ? Icons.star
                                  : Icons.star_border,
                              color: currentStarred
                                  ? Colors.amber
                                  : Colors.grey,
                            ),
                            tooltip:
                                currentStarred ? 'Unstar' : 'Star',
                          ),
                  ],
                ),
                if (repo['description'] != null)
                  Padding(
                    padding: const EdgeInsets.only(top: 4),
                    child: Text(
                      repo['description'] as String,
                      style: Theme.of(context).textTheme.bodySmall,
                      maxLines: 2,
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                const SizedBox(height: 12),
                Row(
                  children: [
                    if (language != null) ...[
                      Container(
                        width: 12,
                        height: 12,
                        decoration: BoxDecoration(
                          shape: BoxShape.circle,
                          color: _parseColor(
                              language['color'] as String?),
                        ),
                      ),
                      const SizedBox(width: 4),
                      Text(
                        language['name'] as String? ?? '',
                        style: Theme.of(context).textTheme.bodySmall,
                      ),
                      const SizedBox(width: 16),
                    ],
                    const Icon(Icons.star, size: 14, color: Colors.amber),
                    const SizedBox(width: 4),
                    Text(
                      _formatCount(currentCount),
                      style: Theme.of(context).textTheme.bodySmall,
                    ),
                  ],
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Color _parseColor(String? hex) {
    if (hex == null) return Colors.grey;
    final hexValue = hex.replaceFirst('#', '');
    return Color(int.parse('FF$hexValue', radix: 16));
  }

  String _formatCount(int count) {
    if (count &gt;= 1000) return '${(count / 1000).toStringAsFixed(1)}k';
    return count.toString();
  }
}
</code></pre>
<p>This code is building a GitHub-like repository screen in Flutter using <code>graphql_flutter</code>, and it relies heavily on GraphQL queries, mutations, and caching behavior to keep the UI in sync with remote data.</p>
<p>At the top level, the <code>ReposScreen</code> widget uses a <code>Query</code> widget from <code>graphql_flutter</code> to fetch data from a GraphQL endpoint. The query (<code>fetchViewerReposQuery</code>) requests the current user (the “viewer”) and a list of their repositories. It passes a variable (<code>count: 15</code>) to limit how many repositories are returned. The fetch policy <code>cacheAndNetwork</code> means it first tries to show cached data immediately, then updates it with fresh data from the network.</p>
<p>When the query is still loading and there's no cached data, the screen shows a loading spinner. If an error occurs, it displays an error message and a retry button that triggers <code>refetch</code>, which re-runs the query.</p>
<p>Once data is available, the screen extracts the <code>viewer</code> object and the list of repositories from the response. It then renders a <code>Scaffold</code> with an <code>AppBar</code> showing the user’s avatar and name, and a <code>ListView</code> that displays each repository using a <code>RepoCard</code>.</p>
<p>Each <code>RepoCard</code> represents a single repository and wraps its UI in a <code>Mutation</code> widget. This mutation handles starring and unstarring a repository. Depending on whether the repo is already starred (<code>viewerHasStarred</code>), it dynamically chooses either the “add star” or “remove star” mutation.</p>
<p>When the star button is pressed, the <code>runMutation</code> function is called with the repository ID. At the same time, an <code>optimisticResult</code> is provided so the UI updates immediately before the server responds. This is why the star count and icon change instantly, giving a smooth user experience.</p>
<p>The mutation also defines an <code>onError</code> handler that shows a <code>SnackBar</code> if something goes wrong during the mutation.</p>
<p>Inside the <code>Mutation</code> builder, the UI prefers data from the mutation result (if available) instead of the original query data. This ensures that once the mutation completes (or even during optimistic updates), the UI reflects the most recent state.</p>
<p>The repository card itself displays the repository name, optional description, primary language (with a colored dot), and star count. The star count is formatted to show values like “1.2k” for large numbers.</p>
<p>There's also a loading indicator on the star button while the mutation is in progress, so the user gets feedback that something is happening.</p>
<p>Finally, the key idea in this code is that GraphQL’s normalized cache is doing a lot of work behind the scenes. When a mutation updates a repository, the cache automatically updates all parts of the UI that depend on that repository’s <code>id</code>, keeping everything consistent without manually refreshing the entire list.</p>
<p>This complete, runnable application demonstrates every major concept in one cohesive codebase:</p>
<ul>
<li><p>client setup with <code>AuthLink</code> and <code>HiveStore</code>,</p>
</li>
<li><p>a <code>Query</code> widget with proper loading, error, and data states with both pull-to-refresh and a background refresh indicator,</p>
</li>
<li><p>a <code>Mutation</code> widget inside each list item with optimistic UI that makes starring feel instant,</p>
</li>
<li><p>and the normalized cache propagating updates across the list automatically when a star operation completes.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>GraphQL is not simply a different way to write APIs. It's a different philosophy about the relationship between a server and the clients that consume it.</p>
<p>The shift from server-driven to client-driven data fetching has real, measurable consequences: less bandwidth consumed, fewer network round trips, faster perceived screen loads, and more autonomy for frontend teams to build the UIs they need without waiting for backend changes.</p>
<p>For Flutter developers specifically, these benefits are amplified by the mobile context. Every saved byte is real bandwidth. Every eliminated round trip is real latency on the user's device. Every cache hit that avoids a re-fetch is real battery life preserved.</p>
<p>These aren't theoretical improvements. They show up in app metrics, in crash rates on poor connections, and in the reviews users leave when an app feels fast versus when it makes them wait.</p>
<p>The <code>graphql_flutter</code> package brings GraphQL into Flutter in a way that respects Flutter's reactive, widget-tree-based architecture. The <code>Query</code>, <code>Mutation</code>, and <code>Subscription</code> widgets fit naturally into how Flutter apps are built. The normalized cache, the composable link chain, and optimistic UI support provide the building blocks for the full complexity of production apps, not just toy examples.</p>
<p>Understanding the problem first is what makes everything else click. GraphQL's design decisions only make sense once you've felt the friction of over-fetching and the N+1 request problem.</p>
<p>Respecting the schema as the source of truth, rather than skimming it as documentation, gives you a development feedback loop that catches errors before they reach production. Embracing the normalized cache rather than fighting it with blanket network-only policies unlocks the reactive, fluid UX that separates great apps from merely functional ones. And structuring your codebase with a clean repository layer, combined with a proper state management solution, produces a system that stays maintainable as the product and the team grow.</p>
<p>GraphQL isn't the right tool for every project. Simple apps, small teams with tight timelines, and file-heavy workflows are all legitimate reasons to stay with REST. But for the right project, a data-intensive Flutter app with complex entity relationships, multiple screen types, and real-time requirements, GraphQL is an exceptionally strong choice.</p>
<p>With the foundations this handbook has built, you have everything you need to make that judgment confidently and to implement GraphQL correctly when it earns its place in your stack.</p>
<h2 id="heading-references">References</h2>
<h3 id="heading-official-package-documentation">Official Package Documentation</h3>
<ul>
<li><p><strong>graphql_flutter on pub.dev:</strong> The official package page, covering installation, Android build requirements, migration guides, and the complete widget API. <a href="https://pub.dev/packages/graphql%5C_flutter">https://pub.dev/packages/graphql\_flutter</a></p>
</li>
<li><p><strong>graphql_flutter GitHub Repository:</strong> Source code, open issues, end-to-end working examples, and the full changelog. <a href="https://github.com/zino-app/graphql-flutter/tree/main/packages/graphql%5C_flutter">https://github.com/zino-app/graphql-flutter/tree/main/packages/graphql\_flutter</a></p>
</li>
<li><p><strong>graphql Dart package README:</strong> In-depth documentation for the underlying Dart GraphQL client, covering the full link system, cache write strictness, direct cache access, AWS AppSync support, and file upload. <a href="https://github.com/zino-app/graphql-flutter/blob/main/packages/graphql/README.md">https://github.com/zino-app/graphql-flutter/blob/main/packages/graphql/README.md</a></p>
</li>
<li><p><strong>GraphQLCache API Docs:</strong> Detailed reference for cache configuration, normalization behavior, and write policies. <a href="https://pub.dev/documentation/graphql/latest/graphql/GraphQLCache-class.html">https://pub.dev/documentation/graphql/latest/graphql/GraphQLCache-class.html</a></p>
</li>
<li><p><strong>GraphQLDataProxy API Docs:</strong> Reference for the direct cache access API, covering <code>readQuery</code>, <code>writeQuery</code>, <code>readFragment</code>, and <code>writeFragment</code>. <a href="https://pub.dev/documentation/graphql/latest/graphql/GraphQLDataProxy-class.html">https://pub.dev/documentation/graphql/latest/graphql/GraphQLDataProxy-class.html</a></p>
</li>
</ul>
<h3 id="heading-graphql-language-and-specification">GraphQL Language and Specification</h3>
<ul>
<li><p><strong>GraphQL Official Specification:</strong> The formal language specification maintained by the GraphQL Foundation. <a href="https://spec.graphql.org/">https://spec.graphql.org/</a></p>
</li>
<li><p><strong>GraphQL.org Learn:</strong> The official introductory documentation for GraphQL concepts, written and maintained by the GraphQL Foundation. <a href="https://graphql.org/learn/">https://graphql.org/learn/</a></p>
</li>
<li><p><strong>GraphQL: A Query Language for APIs:</strong> Meta's original technical introduction to GraphQL, explaining its design goals, the problems it was built to solve, and its fundamental philosophy. <a href="https://graphql.org/blog/graphql-a-query-language/">https://graphql.org/blog/graphql-a-query-language/</a></p>
</li>
</ul>
<h3 id="heading-tooling-and-ecosystem">Tooling and Ecosystem</h3>
<ul>
<li><p><strong>graphql_codegen:</strong> Code generation for <code>graphql_flutter</code> that produces type-safe hooks and option classes directly from your <code>.graphql</code> schema files. <a href="https://pub.dev/packages/graphql%5C_codegen">https://pub.dev/packages/graphql\_codegen</a></p>
</li>
<li><p><strong>Altair GraphQL Client:</strong> A powerful desktop and browser-based GraphQL IDE for exploring and testing your API interactively. <a href="https://altair.sirmuel.design/">https://altair.sirmuel.design/</a></p>
</li>
<li><p><strong>hive_ce:</strong> The Hive community edition package used by <code>graphql_flutter</code> for persistent on-disk cache storage. <a href="https://pub.dev/packages/hive%5C_ce">https://pub.dev/packages/hive\_ce</a></p>
</li>
</ul>
<h3 id="heading-related-flutter-packages">Related Flutter Packages</h3>
<ul>
<li><p><strong>flutter_hooks:</strong> Required for the hooks-based API (<code>useQuery</code>, <code>useMutation</code>, <code>useSubscription</code>) in <code>graphql_flutter</code>. <a href="https://pub.dev/packages/flutter%5C_hooks">https://pub.dev/packages/flutter\_hooks</a></p>
</li>
<li><p><strong>flutter_bloc:</strong> A widely used state management library that integrates cleanly with the repository pattern described in this guide. <a href="https://pub.dev/packages/flutter%5C_bloc">https://pub.dev/packages/flutter\_bloc</a></p>
</li>
<li><p><strong>flutter_secure_storage:</strong> For securely storing authentication tokens on device rather than using insecure storage mechanisms. <a href="https://pub.dev/packages/flutter%5C_secure%5C_storage">https://pub.dev/packages/flutter\_secure\_storage</a></p>
</li>
</ul>
<h3 id="heading-learning-resources">Learning Resources</h3>
<ul>
<li><p><strong>How to GraphQL:</strong> A comprehensive, free tutorial platform covering GraphQL from fundamentals through advanced topics, with examples in multiple languages and runtimes. <a href="https://www.howtographql.com/">https://www.howtographql.com/</a></p>
</li>
<li><p><strong>GitHub GraphQL API Explorer:</strong> An in-browser GraphQL IDE for the GitHub API. Ideal for practicing queries and mutations against a real production GraphQL endpoint without needing your own server. <a href="https://docs.github.com/en/graphql/overview/explorer">https://docs.github.com/en/graphql/overview/explorer</a></p>
</li>
<li><p><strong>GitHub GraphQL API Documentation:</strong> Complete reference for all types, queries, mutations, and subscriptions available in the GitHub GraphQL API, which this handbook's end-to-end example uses. <a href="https://docs.github.com/en/graphql">https://docs.github.com/en/graphql</a></p>
</li>
</ul>
<p><em>This handbook was written for</em> <code>graphql_flutter: ^5.3.0</code> <em>with Flutter 3.x and Dart 3.x. API details may differ in earlier or later versions. Always refer to the official package documentation for the most current information.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a GraphQL API in Django ]]>
                </title>
                <description>
                    <![CDATA[ If you're building an app with Django and thinking about using GraphQL, you're not alone. REST has been the go-to for years, but GraphQL is quickly becoming a favourite option for developers who want more flexibility and less back-and-forth between f... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-graphql-api-in-django/</link>
                <guid isPermaLink="false">67ffaf1dde58821be3496dfb</guid>
                
                    <category>
                        <![CDATA[ Django ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Udemezue John ]]>
                </dc:creator>
                <pubDate>Wed, 16 Apr 2025 13:22:37 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1744809748866/9a626cc9-4e67-4d63-bdde-1834180db645.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you're building an app with Django and thinking about using GraphQL, you're not alone.</p>
<p>REST has been the go-to for years, but GraphQL is quickly becoming a favourite option for developers who want more flexibility and less back-and-forth between frontend and backend.</p>
<p>I’ve spent a lot of time working with Django and playing around with different ways to make APIS smoother, and I get why people are switching to GraphQL.</p>
<p>You ask for exactly the data you need, and you get just that. No extra fluff, no multiple requests to stitch together data — it’s like ordering off a menu and getting exactly what you wanted, every single time.</p>
<p>So, if you’re curious about how to build a GraphQL API using Django, I’ve got you covered.</p>
<p>I’ll walk you through what GraphQL is, why it might be a better fit than REST in some cases, and how you can get started from scratch — even if you’re not a GraphQL expert (yet).</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-graphql-and-why-does-it-matter">What Is GraphQL, and Why Does It Matter?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-youll-need-before-you-start">What You’ll Need Before You Start</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-a-graphql-api-in-django">How to Build a GraphQL API in Django)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-mutations-also-known-as-writing-data">How to Add Mutations (Also Known As Writing Data)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-code-walkthrough-creating-a-post-via-mutation-in-graphql">Code Walkthrough: Creating a Post via Mutation in GraphQL)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-a-client-would-use-this">How a Client Would Use This</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pros-and-cons-of-using-graphql-in-django">Pros and Cons of Using GraphQL in Django</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-faqs">FAQs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-whats-next">What's Next?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-final-thoughts">Final Thoughts</a></p>
</li>
</ol>
<h2 id="heading-what-is-graphql-and-why-does-it-matter">What Is GraphQL, and Why Does It Matter?</h2>
<p>GraphQL is a query language for APIs — and more importantly, it’s a runtime for fulfilling those queries with your data.</p>
<p>It was developed by Facebook in 2012 and made public in 2015. Since then, it's been used by companies like GitHub, Shopify, Twitter, and Pinterest.</p>
<p>Unlike REST, where you often have to make multiple requests to get all the data you need, GraphQL lets you fetch all your data in a single request.</p>
<p>This is a big deal, especially for mobile apps or slow networks where fewer requests mean better performance.</p>
<p>Let’s say you want a user’s name, profile picture, and their 3 most recent blog posts. With REST, you might need to hit 2-3 different endpoints. With GraphQL? One request, done.</p>
<p>It’s also great for frontend devs because they can shape the data they get back without waiting for backend devs to create new endpoints.</p>
<h2 id="heading-what-youll-need-before-you-start">What You’ll Need Before You Start</h2>
<p>Before jumping in, here’s what you should already have:</p>
<ul>
<li><p>Basic knowledge of Django (models, views, and so on)</p>
</li>
<li><p>Python installed (3.8+ is best)</p>
</li>
<li><p>A Django project set up</p>
</li>
<li><p>pip or pipenv for package management</p>
</li>
</ul>
<p>If you're starting fresh, you can spin up a new Django project with:</p>
<pre><code class="lang-bash">django-admin startproject myproject
<span class="hljs-built_in">cd</span> myproject
python manage.py startapp myapp
</code></pre>
<h2 id="heading-how-to-build-a-graphql-api-in-django">How to Build a GraphQL API in Django</h2>
<p>Let’s get into it.</p>
<h3 id="heading-1-install-graphene-django">1. Install Graphene-Django</h3>
<p>Graphene is the most popular library for using GraphQL with Python. For Django specifically, there's a package called <code>graphene-django</code>.</p>
<p>You can install it like this:</p>
<pre><code class="lang-bash">pip install graphene-django
</code></pre>
<p>Then, add it to your <code>INSTALLED_APPS</code>:</p>
<pre><code class="lang-python">INSTALLED_APPS = [
    ...
    <span class="hljs-string">'graphene_django'</span>,
]
</code></pre>
<h3 id="heading-2-add-a-simple-model">2. Add a Simple Model</h3>
<p>Here’s a quick model to work with. In <code>myapp/models.py</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Post</span>(<span class="hljs-params">models.Model</span>):</span>
    title = models.CharField(max_length=<span class="hljs-number">100</span>)
    content = models.TextField()
    published = models.DateTimeField(auto_now_add=<span class="hljs-literal">True</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.title
</code></pre>
<p>Then run your migrations:</p>
<pre><code class="lang-bash">python manage.py makemigrations
python manage.py migrate
</code></pre>
<h3 id="heading-3-create-a-schema">3. Create a Schema</h3>
<p>In <code>myapp/schema.py</code>, start with:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> graphene
<span class="hljs-keyword">from</span> graphene_django.types <span class="hljs-keyword">import</span> DjangoObjectType
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Post

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PostType</span>(<span class="hljs-params">DjangoObjectType</span>):</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Meta</span>:</span>
        model = Post

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Query</span>(<span class="hljs-params">graphene.ObjectType</span>):</span>
    all_posts = graphene.List(PostType)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">resolve_all_posts</span>(<span class="hljs-params">root, info</span>):</span>
        <span class="hljs-keyword">return</span> Post.objects.all()

schema = graphene.Schema(query=Query)
</code></pre>
<p>Then, in your Django project settings, add:</p>
<pre><code class="lang-python">GRAPHENE = {
    <span class="hljs-string">"SCHEMA"</span>: <span class="hljs-string">"myapp.schema.schema"</span>
}
</code></pre>
<p>And finally, in your <code>urls.py</code>:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path
<span class="hljs-keyword">from</span> graphene_django.views <span class="hljs-keyword">import</span> GraphQLView
<span class="hljs-keyword">from</span> django.views.decorators.csrf <span class="hljs-keyword">import</span> csrf_exempt

urlpatterns = [
    path(<span class="hljs-string">"graphql"</span>, csrf_exempt(GraphQLView.as_view(graphiql=<span class="hljs-literal">True</span>))),
]
</code></pre>
<p>Now, visit <code>http://localhost:8000/graphql</code> and try this query:</p>
<pre><code class="lang-graphql">{
  allPosts {
    title
    content
    published
  }
}
</code></pre>
<p>Boom. You just queried your database using GraphQL.</p>
<p>Here is what your GraphQL playground should look like.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1744454293412/8820e7dd-ff86-4c7d-9c8c-ec21dc43b09b.png" alt="8820e7dd-ff86-4c7d-9c8c-ec21dc43b09b" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-add-mutations-also-known-as-writing-data">How to Add Mutations (Also Known As Writing Data)</h2>
<p>GraphQL isn’t just for reading data. You can also create, update, and delete. Here’s how to add a mutation for creating a post:</p>
<p>In <code>myapp/schema.py</code>:</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreatePost</span>(<span class="hljs-params">graphene.Mutation</span>):</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Arguments</span>:</span>
        title = graphene.String(required=<span class="hljs-literal">True</span>)
        content = graphene.String(required=<span class="hljs-literal">True</span>)

    post = graphene.Field(PostType)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mutate</span>(<span class="hljs-params">self, info, title, content</span>):</span>
        post = Post(title=title, content=content)
        post.save()
        <span class="hljs-keyword">return</span> CreatePost(post=post)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mutation</span>(<span class="hljs-params">graphene.ObjectType</span>):</span>
    create_post = CreatePost.Field()

schema = graphene.Schema(query=Query, mutation=Mutation)
</code></pre>
<p>Now, in the GraphiQL playground, you can run:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">mutation</span> {
  createPost(<span class="hljs-symbol">title:</span> <span class="hljs-string">"My First Post"</span>, <span class="hljs-symbol">content:</span> <span class="hljs-string">"Hello GraphQL!"</span>) {
    post {
      id
      title
    }
  }
}
</code></pre>
<p>Pretty clean, right?</p>
<h2 id="heading-code-walkthrough-creating-a-post-via-mutation-in-graphql">Code Walkthrough: Creating a Post via Mutation in GraphQL</h2>
<p>Let me walk you through the code, explain what it does, and how GraphQL makes it work.</p>
<h3 id="heading-step-1-the-createpost-mutation-class">Step 1: The <code>CreatePost</code> Mutation Class</h3>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreatePost</span>(<span class="hljs-params">graphene.Mutation</span>):</span>
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Arguments</span>:</span>
        title = graphene.String(required=<span class="hljs-literal">True</span>)
        content = graphene.String(required=<span class="hljs-literal">True</span>)

    post = graphene.Field(PostType)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mutate</span>(<span class="hljs-params">self, info, title, content</span>):</span>
        post = Post(title=title, content=content)
        post.save()
        <span class="hljs-keyword">return</span> CreatePost(post=post)
</code></pre>
<p>Here’s what’s going on in this part:</p>
<ul>
<li><p><code>graphene.Mutation</code>: This defines a custom <strong>mutation</strong>, which in GraphQL is how we modify server-side data (similar to POST, PUT, and DELETE in REST).</p>
</li>
<li><p><code>class Arguments</code>: Think of this as the "input" part of the mutation. We're requiring a <code>title</code> and <code>content</code>, both as strings. These are what the client must provide when calling the mutation.</p>
</li>
<li><p><code>post = graphene.Field(PostType)</code>: This defines the return type of the mutation. In this case, once a post is created, we return it using a custom GraphQL type called <code>PostType</code>.</p>
</li>
<li><p><code>mutate(self, info, title, content)</code>: This method is called when the mutation is executed. Inside it:</p>
<ul>
<li><p>We create a new <code>Post</code> model instance.</p>
</li>
<li><p>We save it to the database.</p>
</li>
<li><p>We return the mutation result as an <code>CreatePost</code> object with the new post attached.</p>
</li>
</ul>
</li>
<li><p>This keeps the logic tight, readable, and testable – a great example of clean API design.</p>
</li>
</ul>
<h3 id="heading-step-2-wiring-the-mutation-into-the-schema">Step 2: Wiring the Mutation into the Schema</h3>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Mutation</span>(<span class="hljs-params">graphene.ObjectType</span>):</span>
    create_post = CreatePost.Field()
</code></pre>
<p>This is where we <strong>register</strong> our mutation. In GraphQL, all operations (queries and mutations) must be part of the schema. By adding <code>create_post</code> to the <code>Mutation</code> class, we expose it to the GraphQL endpoint.</p>
<h3 id="heading-step-3-the-final-schema">Step 3: The Final Schema</h3>
<pre><code class="lang-python">schema = graphene.Schema(query=Query, mutation=Mutation)
</code></pre>
<p>In this code,</p>
<ul>
<li><p>We’re creating a new <code>graphene.Schema</code>.</p>
</li>
<li><p>We pass in a <code>Query</code> class (assumed to be defined elsewhere for read operations) and our <code>Mutation</code> class for write operations.</p>
</li>
</ul>
<p>This is the GraphQL equivalent of wiring up Django's <a target="_blank" href="http://urls.py"><code>urls.py</code></a> – it's what gets exposed to clients when they hit your <code>/graphql/</code> endpoint.</p>
<h2 id="heading-how-a-client-would-use-this">How a Client Would Use This</h2>
<p>A client (frontend or API testing tool like Insomnia/Postman) would send a mutation like this:</p>
<pre><code class="lang-python">mutation {
  createPost(title: <span class="hljs-string">"GraphQL is Awesome"</span>, content: <span class="hljs-string">"Let's build APIs with it!"</span>) {
    post {
      id
      title
      content
    }
  }
}
</code></pre>
<p>And get a response like:</p>
<pre><code class="lang-python">{
  <span class="hljs-string">"data"</span>: {
    <span class="hljs-string">"createPost"</span>: {
      <span class="hljs-string">"post"</span>: {
        <span class="hljs-string">"id"</span>: <span class="hljs-string">"1"</span>,
        <span class="hljs-string">"title"</span>: <span class="hljs-string">"GraphQL is Awesome"</span>,
        <span class="hljs-string">"content"</span>: <span class="hljs-string">"Let's build APIs with it!"</span>
      }
    }
  }
}
</code></pre>
<h2 id="heading-bonus-why-this-is-awesome-for-developers">Bonus: Why This Is Awesome for Developers</h2>
<ul>
<li><p><strong>Frontend teams</strong> can now build forms and instantly see the structure of the response.</p>
</li>
<li><p><strong>Backend devs</strong> define what’s allowed and handle only necessary logic.</p>
</li>
<li><p><strong>No more over-fetching or under-fetching data</strong> — GraphQL gives you just what you ask for.</p>
</li>
<li><p>Easy to test, debug, and scale.</p>
</li>
</ul>
<h2 id="heading-make-sure-you-have-the-following-in-place">Make Sure You Have the Following in Place</h2>
<ul>
<li><p>Ensure you have <code>graphene-django</code> installed.</p>
</li>
<li><p>Add <code>'graphene_django'</code> to your <code>INSTALLED_APPS</code>.</p>
</li>
<li><p>Wire up the schema in your Django project’s <a target="_blank" href="http://urls.py"><code>urls.py</code></a>.</p>
</li>
</ul>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path
<span class="hljs-keyword">from</span> graphene_django.views <span class="hljs-keyword">import</span> GraphQLView
<span class="hljs-keyword">from</span> myapp.schema <span class="hljs-keyword">import</span> schema

urlpatterns = [
    path(<span class="hljs-string">"graphql/"</span>, GraphQLView.as_view(graphiql=<span class="hljs-literal">True</span>, schema=schema)),
]
</code></pre>
<h2 id="heading-pros-and-cons-of-using-graphql-in-django">Pros and Cons of Using GraphQL in Django</h2>
<h3 id="heading-pros">Pros:</h3>
<ul>
<li><p>Flexible queries</p>
</li>
<li><p>Great for frontend devs</p>
</li>
<li><p>Fewer API calls</p>
</li>
<li><p>Strongly typed schema</p>
</li>
<li><p>Better performance on slower networks</p>
</li>
</ul>
<h3 id="heading-cons">Cons:</h3>
<ul>
<li><p>Slightly steeper learning curve</p>
</li>
<li><p>More setup than REST</p>
</li>
<li><p>Can be overkill for simple APIS</p>
</li>
</ul>
<h2 id="heading-faqs">FAQs</h2>
<h3 id="heading-is-graphql-better-than-rest">Is GraphQL better than REST?</h3>
<p>It depends. GraphQL gives you more control and flexibility, but REST is easier to cache and simpler to set up for small projects.</p>
<h3 id="heading-is-graphene-the-only-way-to-use-graphql-with-django">Is Graphene the only way to use GraphQL with Django?</h3>
<p>Nope. You can also use Ariadne or Strawberry. But Graphene is the most mature and widely used right now.</p>
<h3 id="heading-does-graphql-work-well-with-django-rest-framework">Does GraphQL work well with Django REST Framework?</h3>
<p>They can live side-by-side. If you already have a REST API and want to add GraphQL, you don’t need to throw anything away.</p>
<h2 id="heading-whats-next">What’s Next?</h2>
<p>Once you’ve got the basics down, you can:</p>
<ul>
<li><p>Add authentication with JWT or sessions</p>
</li>
<li><p>Use Relay if you need pagination and filtering</p>
</li>
<li><p>Connect your GraphQL API to React, Vue, or any frontend</p>
</li>
</ul>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>If you’ve been using Django for a while and want to give your API a little more power and flexibility, GraphQL is 100% worth checking out.</p>
<h3 id="heading-further-resources">Further Resources</h3>
<ul>
<li><p><a target="_blank" href="https://docs.graphene-python.org/projects/django/en/latest/">Graphene-Django Docs</a></p>
</li>
<li><p><a target="_blank" href="https://graphql.org/learn/">Official GraphQL Docs</a></p>
</li>
<li><p><a target="_blank" href="https://ariadnegraphql.org/">Ariadne – A schema-first GraphQL library for Python</a></p>
</li>
<li><p><a target="_blank" href="https://www.apollographql.com/blog/graphql/basics/graphql-vs-rest/">GraphQL vs REST: Key Differences</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Orchestrating AWS Lambda with GraphQL and Apollo Connectors ]]>
                </title>
                <description>
                    <![CDATA[ AWS Lambda is a computing service that enables you to run arbitrary code functions without needing to provision, manage, or scale servers. It’s often used in the logic tier of a multi-tier architecture to handle tasks such as processing files in S3 o... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-orchestrate-aws-lambda-with-graphql-and-apollo-connectors/</link>
                <guid isPermaLink="false">67e2d5e080e11112e050be00</guid>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ aws lambda ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Apollo GraphQL ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rob Walters ]]>
                </dc:creator>
                <pubDate>Tue, 25 Mar 2025 16:12:16 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742917115054/07184be6-5384-4861-a676-b72c06ff7c65.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>AWS Lambda is a computing service that enables you to run arbitrary code functions without needing to provision, manage, or scale servers. It’s often used in the logic tier of a multi-tier architecture to handle tasks such as processing files in S3 or performing CRUD operations on a database.</p>
<p>AWS also offers an API Gateway, allowing developers to invoke AWS Lambda functions, which provides enhanced security and performance features like rate limiting. But even with the API Gateway, you have to coordinate these microservices, as your client applications likely each have unique data needs. Data might need to be transformed, filtered, or combined before it is returned to the client. </p>
<p>These orchestration tasks can reduce your productivity and take time and effort away from solving the business problem your application is trying to solve. </p>
<p>Apollo GraphQL is an API orchestration layer that helps teams ship new features faster and more independently by composing any number of underlying services and data sources into a single endpoint. This allows clients on-demand access to precisely what the experience needs, regardless of the source of that data.</p>
<p>This article will teach you how to orchestrate AWS Lambda functions using Apollo GraphQL. Specifically, here’s what we will cover:</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-graphql-primer">GraphQL Primer</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tutorial-overview">Tutorial Overview</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-1-create-the-aws-resources">Section 1: Create the AWS Resources</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-2-create-an-apollo-connector">Section 2: Create an Apollo Connector</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-section-3-how-to-use-apollo-sandbox">Section 3: How to Use Apollo Sandbox</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
</ul>
<h2 id="heading-graphql-primer">GraphQL Primer</h2>
<p>For those unfamiliar with GraphQL, here’s a primer that offers some background on the challenges GraphQL addresses and how data is typically managed through REST APIs in GraphQL before the emergence of Apollo Connectors. If you’re familiar with GraphQL, feel free to skip this section.</p>
<p>GraphQL is a query language for APIs. This query language and corresponding runtime enable clients to specify exactly the data they require, minimizing over-fetching and under-fetching.</p>
<p>In contrast to REST, which necessitates multiple endpoints for various data requirements, GraphQL streamlines queries into a single request, enhancing performance and reducing network latency.</p>
<p>GraphQL also uses a strongly typed schema. This improves API documentation and makes validation, early error detection, and immersive developer tooling easy. </p>
<p>To illustrate the difference between REST APIs and GraphQL, consider the following REST API call: /user/123</p>
<p>Response:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"id"</span>: <span class="hljs-number">123</span>,
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Alice Johnson"</span>,
  <span class="hljs-attr">"email"</span>: <span class="hljs-string">"alice@example.com"</span>,
  <span class="hljs-attr">"phone"</span>: <span class="hljs-string">"555-1234"</span>,
  <span class="hljs-attr">"address"</span>: {
    <span class="hljs-attr">"street"</span>: <span class="hljs-string">"123 Main St"</span>,
    <span class="hljs-attr">"city"</span>: <span class="hljs-string">"Springfield"</span>,
    <span class="hljs-attr">"state"</span>: <span class="hljs-string">"IL"</span>,
    <span class="hljs-attr">"zip"</span>: <span class="hljs-string">"62704"</span>
  },
  <span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"2022-01-01T12:00:00Z"</span>,
  <span class="hljs-attr">"updatedAt"</span>: <span class="hljs-string">"2022-05-15T14:30:00Z"</span>,
  <span class="hljs-attr">"isAdmin"</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<p>If you were only interested in the name and email, using REST would be a lot of data returned from the network to the client for no reason. Using GraphQL, the GraphQL query to return the name and email would be the following:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">query</span> {
  user(<span class="hljs-symbol">id:</span> <span class="hljs-number">123</span>) {
    name
    email
  }
}
</code></pre>
<p>The result set is just the data the client needs:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"data"</span>: {
    <span class="hljs-attr">"user"</span>: {
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Alice Johnson"</span>,
      <span class="hljs-attr">"email"</span>: <span class="hljs-string">"alice@example.com"</span>
    }
  }
}
</code></pre>
<p>This is a simple example showing the benefit of not over-fetching data, but GraphQL has many other advantages. One of them is the separation between client and server. Since both parties leverage and respect the GraphQL type schema, both teams can operate more independently with the back end defining where the data resides and the front end only asking for data it needs.    </p>
<p>So how does GraphQL know how to populate data for every field in your schema? It does this through <a target="_blank" href="https://www.apollographql.com/docs/apollo-server/data/resolvers">resolvers</a>. Resolvers can fetch data from a back-end databases or third-party API such as REST APIs, gRPC, and so on. These functions comprise procedural code compiled and maintained for each field in the schema. Thus, one field can have a resolver that queries a REST API and another can query a gRPC endpoint.</p>
<p>To illustrate resolvers, consider the example above. Let’s add a field, status, that queries a REST API to determine if the user is full-time, part-time, or terminated. </p>
<p>First we have defined our schema as:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">type</span> User {
  <span class="hljs-symbol">id:</span> ID!
  <span class="hljs-symbol">name:</span> String!
  <span class="hljs-symbol">email:</span> String!
  <span class="hljs-symbol">status:</span> String!  <span class="hljs-comment"># Need this from an external REST API</span>
}

<span class="hljs-keyword">type</span> Query {
  user(<span class="hljs-symbol">id:</span> ID!): User
}
</code></pre>
<p>The user query in this case will accept a user id and return a type User. The resolver function to support the data fetching resembles the following:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> resolvers = {
  <span class="hljs-attr">Query</span>: {
    <span class="hljs-attr">user</span>: <span class="hljs-keyword">async</span> (_, { id }) =&gt; {
      <span class="hljs-comment">// Fetch user details from one REST API</span>
      <span class="hljs-keyword">const</span> userResponse = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`https://api.company.com/users/<span class="hljs-subst">${id}</span>`</span>);
      <span class="hljs-keyword">const</span> userData = <span class="hljs-keyword">await</span> userResponse.json();

      <span class="hljs-comment">// Fetch employee status from another REST API</span>
      <span class="hljs-keyword">const</span> statusResponse = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`https://api.company.com/employees/<span class="hljs-subst">${id}</span>/status`</span>);
      <span class="hljs-keyword">const</span> statusData = <span class="hljs-keyword">await</span> statusResponse.json();

      <span class="hljs-keyword">return</span> {
        <span class="hljs-attr">id</span>: userData.id,
        <span class="hljs-attr">name</span>: userData.name,
        <span class="hljs-attr">email</span>: userData.email,
        <span class="hljs-attr">status</span>: statusData.status, <span class="hljs-comment">// e.g., "Full-Time", "Part-Time", "Terminated"</span>
      };
    },
  },
};
</code></pre>
<p>Notice that not only are there two fetches needed to obtain the information the query requires, but we also need to write procedural code and deploy it.</p>
<p>A better approach would be to declaratively specify to GraphQL where the REST API is located and what data to return. Apollo Connectors is the solution to this challenge, simplifying the process and allowing you to declaratively integrate REST API data without requiring code compilation and maintenance.</p>
<p>Now that you have a general idea of GraphQL and the challenges it addresses, let’s delve into the example we will build out.</p>
<h2 id="heading-tutorial-overview">Tutorial Overview</h2>
<p>In this tutorial, you will create two AWS Lambda functions that return product information, which are described as follows:</p>
<p>Products Request:</p>
<p>POST /2015-03-31/functions/products/invocations</p>
<p>Response:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"statusCode"</span>: <span class="hljs-number">200</span>,
  <span class="hljs-attr">"body"</span>: [
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-string">"RANQi6AZkUXCbZ"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"OG Olive Putter - Blade"</span>,
      <span class="hljs-attr">"description"</span>: <span class="hljs-string">"The traditional Block in a blade shape is made from a solid block of Olive wood. The head weight is approximately 360 grams with the addition of pure tungsten weights. Paired with a walnut center-line and white accents colors."</span>,
      <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://keynote-strapi-production.up.railway.app/uploads/thumbnail_IMG_9102_3119483fac.png"</span>
    },
    {
      <span class="hljs-attr">"id"</span>: <span class="hljs-string">"RANYrWRy876AA5"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Butter Knife Olive Putter- Blade"</span>,
      <span class="hljs-attr">"description"</span>: <span class="hljs-string">"The traditional Block in a extremely thin blade shape (~1\") is made from a solid block of Olive wood. The head weight is approximately 330 grams with the addition of pure tungsten weights."</span>,
      <span class="hljs-attr">"image"</span>: <span class="hljs-string">"https://keynote-strapi-production.up.railway.app/uploads/thumbnail_IMG_9104_97c221e79c.png"</span>
    },...
</code></pre>
<p>Product-price request:</p>
<p>POST: /2015-03-31/functions/product-price/invocations</p>
<p>Response:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"default_price"</span>: <span class="hljs-number">49900</span>,
  <span class="hljs-attr">"is_active"</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">"currency"</span>: <span class="hljs-string">"usd"</span>,
  <span class="hljs-attr">"billing_schema"</span>: <span class="hljs-string">"per_unit"</span>,
  <span class="hljs-attr">"recurring"</span>: {
    <span class="hljs-attr">"interval"</span>: <span class="hljs-number">0</span>,
    <span class="hljs-attr">"interval_count"</span>: <span class="hljs-number">3</span>
  }
}
</code></pre>
<p>To expose these two lambda microservices, you need to create API Gateway triggers. This involves either setting up a distinct API Gateway for each lambda or consolidating them under one or a few API Gateway instances with specified routes for each lambda.</p>
<p>Creating a trigger may feel tedious and repetitive in a microservices setup. But there is an alternative available. You could directly invoke those functions via REST using the InvokeFunction permission assigned to an IAM user. This article will show you this method and guide you through function creation, necessary AWS IAM permissions, and configuring the Apollo Connector to invoke the function.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along in this tutorial, you will need to have a basic understanding of AWS Lambda functions as well as AWS security. You’ll also need access to the following:</p>
<ul>
<li><p>An AWS account with permissions to create IAM Users and Policies</p>
</li>
<li><p>An Apollo GraphQL account, you can <a target="_blank" href="https://studio.apollographql.com/signup">sign up for a free plan here</a>.</p>
</li>
</ul>
<p>We will also use the following tools:</p>
<ul>
<li><p><a target="_blank" href="https://code.visualstudio.com/">VS Code</a>: Microsoft VS Code is a free source code editor from Microsoft</p>
</li>
<li><p><a target="_blank" href="https://www.apollographql.com/docs/rover/getting-started?utm_campaign=2025-03-20_installing-rover-doc-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">Apollo Rover CLI</a>: Rover is the command-line interface for managing and maintaining graphs</p>
</li>
<li><p><a target="_blank" href="https://studio.apollographql.com/signup?utm_campaign=2025-03-19_studio-signup-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">Apollo Studio</a>: A web-based portal used for managing all aspects of your graph </p>
</li>
<li><p><a target="_blank" href="https://www.apollographql.com/connectors-mapping-playground?utm_campaign=2025-03-20_connectors-mapping-playground-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">Apollo Connectors Mapping Playground</a>: A website that takes a JSON document and helps developers create the selection mapping used with Apollo Connectors</p>
</li>
</ul>
<h2 id="heading-section-1-create-the-aws-resources">Section 1: Create the AWS Resources</h2>
<p>First, let’s configure our AWS environment, starting with security. In our scenario, we will create an IAM User, “ConnectorUser,” with access to an AWS Policy, “ConnectorLambdaPolicy,” with the minimum permissions needed to access the AWS Lambda functions.</p>
<p>Note that you could create user groups and assign permission policies to those groups in a production environment. But for this article, we are reducing the number of administrative steps to focus on the core integration with GraphQL.</p>
<h3 id="heading-step-1-create-an-aws-policy">Step 1: Create an AWS Policy</h3>
<p>To create a policy, navigate to IAM within the AWS Management console, then select “Policies” under Access Management. Click “Create Policy”. This will open the policy editor page, as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742755417676/1025d04f-a712-4311-9669-ac38bd2fee50.jpeg" alt="specify permissions" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Choose the “Lambda” service and under the Access level select “InvokeFunction” from the Write drop down menu as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742755482285/1be204db-7b39-4c8f-ac7c-d461032f6887.jpeg" alt="InvokeFunction checkmarked" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Under the Resources menu, you can choose either All ARNs or a specific option. It's a best practice to be as granular as possible when defining security configurations. In this example, let’s limit our selection to the “us-east-1” region by clicking on the “Specific” option and then “Add ARNs.” Enter “us-east-1” in the resource region and select “Any function name.”</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742755564740/99e47ac8-4ce9-4ff3-94b6-105308526f56.jpeg" alt="Specify ARN dialog" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>With the policy created, we can assign an IAM user to that policy.</p>
<h3 id="heading-step-2-create-the-iam-user-and-attach-a-policy">Step 2: Create the IAM User and Attach a Policy</h3>
<p>Click on Users under “Access Management” then Create User. Provide a name for the user, “ConnectorUser”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742755638499/ad782c39-a78f-4d68-b834-4e58dea9e35b.jpeg" alt="Permission policy" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Next, select “Attach policies directly,” choose the policy we just created, “ConnectorLambdaPolicy,” and click “Create User.”</p>
<h3 id="heading-step-3-create-aws-lambda-functions">Step 3: Create AWS Lambda Functions</h3>
<p>In your AWS console, create a new NodeJS AWS Lambda function, “products”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742754922858/b2a307c2-8b43-4417-b022-0113803a3b5d.jpeg" alt="AWS create function dialog" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Select “Node.JS” for the runtime then click “Create function”. Once created, paste in the the function code <a target="_blank" href="https://gist.github.com/RWaltersMA/25264ff22a5cbc26814a00dbb78a16e2">from this Gist</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742755096066/90e96036-41cd-4b45-8841-0bb3acb5af6b.jpeg" alt="AWS function showing code source" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Repeat this process, creating another function for, “product-price” and use the function code <a target="_blank" href="https://gist.github.com/RWaltersMA/d75d9eb02264829c1392dbdf7f238bad">from this Gist</a>.</p>
<h2 id="heading-section-2-create-an-apollo-connector">Section 2: Create an Apollo Connector</h2>
<p>In this section, we will install the Apollo Rover CLI tool, create an Apollo Studio free tier account, and clone the Apollo Connectors repository. If you already have an Apollo environment available, you can skip steps 1 and 2.</p>
<h3 id="heading-step-1-install-rover">Step 1: Install Rover</h3>
<p>Rover is the command-line interface for managing and maintaining graphs. It also provides a modern hot-reloading experience for developing and running your connectors locally. If you don’t have Rover installed, install it by <a target="_blank" href="https://www.apollographql.com/docs/rover/getting-started?utm_campaign=2025-03-20_installing-rover-doc-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">following the steps here</a>.</p>
<h3 id="heading-step-2-create-an-apollo-studio-free-tier-account">Step 2: Create an Apollo Studio Free Tier Account</h3>
<p>Apollo Studio is a cloud-based management platform designed to explore, deliver, and collaborate on graphs. If you do not have an Apollo Studio account, create one on a free plan <a target="_blank" href="https://studio.apollographql.com/signup?utm_campaign=2025-03-19_studio-signup-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">by navigating here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742755870123/4b38b025-064c-4a9a-b836-53a563152e43.jpeg" alt="Apollo Studio" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-3-clone-the-apollo-connectors-repository">Step 3: Clone the Apollo Connectors Repository</h3>
<p>To help you start your first Apollo Connector, a GitHub repository provides sample connectors and a template script. When run, this script will create all the necessary files and configurations you need to begin. </p>
<p>Go ahead and <a target="_blank" href="https://github.com/apollographql/connectors-community">clone the repository from here</a>.</p>
<p>Note: While not required, I recommended using VS Code, as this repo leverages VS Code-specific settings files.</p>
<h3 id="heading-step-4-create-a-env-file">Step 4: Create a .env File</h3>
<p>Before you run the Create Connectors template script, create a .env locally with a user API key from your Apollo Studio. You can <a target="_blank" href="https://studio.apollographql.com/user-settings/api-keys">create and obtain this key here</a>. Populating this .env file will add this API key to the connector template you create in the next step.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742755977271/860ef610-e802-4ec1-9cca-e881881a0968.jpeg" alt=".env file" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h3 id="heading-step-5-create-your-new-connector-from-a-template">Step 5: Create Your New Connector from a Template</h3>
<p>Execute <code>npm start</code> and provide a location to create the connector template. You can use default values for the remaining questions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742756030015/e6c3b535-8657-4a77-b353-b8546cfa9ac5.jpeg" alt="npmstart" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>This script will create all the necessary files to run a local Apollo GraphQL instance in the specified directory. Load the newly created connector using VS Code or your preferred code editor. You will return to this editor soon, but first, we need to obtain some access keys from AWS.</p>
<h3 id="heading-step-6-create-an-aws-access-key">Step 6: Create an AWS Access Key</h3>
<p>Since we connect to AWS using SigV4, we must create an AWS access key and enter the KEY values in the settings.json file. Return to the AWS IAM Console and select the <em>ConnectorUser</em> you created in Step 1.  Create a new access key by clicking on “Create access key”. </p>
<p>You will be presented with multiple options as far as where the use of this key will originate. Since we are first running locally, select “Third-party service” and then continue the wizard until you are presented with the key and secret key as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742756092209/e7b33bd2-f6ca-4e78-bf83-8ed357860abd.jpeg" alt="retrieve access key dialog" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Add the access key and secret access key to the settings.json file as “AWS_ACCESS_KEY_ID” and “AWS_SECRET_ACCESS_KEY” respectively.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742756152443/31906e19-625d-446f-adde-b9618e8df61a.jpeg" alt="vscode settings file" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>You'll need to reload the window since VS Code only loads these files under the .vscode directory once. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742756203631/8fb467fc-e8de-4f16-8907-622a12017d4f.jpeg" alt="vscode task window showing reload option" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Note: In this step, we saved the key to the settings.json file. While this is acceptable for development, consider saving environment variables in .env files.</p>
<h3 id="heading-step-7-configure-the-graph">Step 7: Configure the Graph</h3>
<p>The supergraph.yaml file is used to define all the subgraphs that are part of this federation. Modify the <strong>supergraph.yaml</strong> file as follows:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">federation_version:</span> <span class="hljs-string">=2.10.0</span>
<span class="hljs-attr">subgraphs:</span>
  <span class="hljs-attr">awsconnector:</span>
    <span class="hljs-attr">routing_url:</span> <span class="hljs-string">http://lambda</span>
    <span class="hljs-attr">schema:</span>
      <span class="hljs-attr">file:</span> <span class="hljs-string">connector.graphql</span>
</code></pre>
<h3 id="heading-step-8-configure-apollo-router">Step 8: Configure Apollo Router</h3>
<p>Apollo Router supports AWS SigV4 authentication. To configure the connector to use this, modify the <strong>router.yaml</strong> file and add an authentication section as follows:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">authentication:</span>
  <span class="hljs-attr">connector:</span>
    <span class="hljs-attr">sources:</span>
      <span class="hljs-attr">awsconnector.lambda:</span>   <span class="hljs-comment"># subgraph name . connector source name</span>
        <span class="hljs-attr">aws_sig_v4:</span>
          <span class="hljs-attr">default_chain:</span>
            <span class="hljs-attr">region:</span> <span class="hljs-string">"us-east-1"</span>
            <span class="hljs-attr">service_name:</span> <span class="hljs-string">"lambda"</span>
</code></pre>
<p>There are other AWS security configuration options available, including using assume role. The full documentation for subgraph authentication <a target="_blank" href="https://www.apollographql.com/docs/graphos/routing/security/subgraph-authentication">is available here</a>. </p>
<h3 id="heading-step-9-build-the-connector">Step 9: Build the connector</h3>
<p>Now that we have configured the environment variables and authentication information, we are ready to build the connector. Open the <code>connector.graphql</code> file and erase the contents. Next, copy the following extend schema:</p>
<pre><code class="lang-graphql">extend <span class="hljs-keyword">schema</span>
  <span class="hljs-meta">@link</span>(
    <span class="hljs-symbol">url:</span> <span class="hljs-string">"https://specs.apollo.dev/federation/v2.10"</span>
    <span class="hljs-symbol">import:</span> [<span class="hljs-string">"@key"</span>]
  )
  <span class="hljs-meta">@link</span>(
    <span class="hljs-symbol">url:</span> <span class="hljs-string">"https://specs.apollo.dev/connect/v0.1"</span>
    <span class="hljs-symbol">import:</span> [<span class="hljs-string">"@source"</span>, <span class="hljs-string">"@connect"</span>]
  )

  <span class="hljs-meta">@source</span>(
    <span class="hljs-symbol">name:</span> <span class="hljs-string">"lambda"</span>
    <span class="hljs-symbol">http:</span> { <span class="hljs-symbol">baseURL:</span> <span class="hljs-string">"https://lambda.us-east-1.amazonaws.com"</span> }
  )
</code></pre>
<p><strong>Extend schema</strong> is used to link the Apollo Connectors directives into the current schema. In this article we are defining the base URL of our lambda function. If your REST API has HTTP headers that apply to all references of this source, such as Content-Length restrictions, you can add them here in the @source declaration. Next, let’s define the Product schema:</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">type</span> Product {
  <span class="hljs-symbol">id:</span> ID!
  <span class="hljs-symbol">name:</span> String
  <span class="hljs-symbol">description:</span> String
  <span class="hljs-symbol">image:</span> String
  <span class="hljs-symbol">price:</span> Price
    <span class="hljs-meta">@connect</span>(
      <span class="hljs-symbol">source:</span> <span class="hljs-string">"lambda"</span>
      <span class="hljs-symbol">http:</span> {
        <span class="hljs-symbol">POST:</span> <span class="hljs-string">"/2015-03-31/functions/product-price/invocations"</span>
        <span class="hljs-symbol">body:</span> <span class="hljs-string">""</span><span class="hljs-string">"
        product_id: $this.id
        "</span><span class="hljs-string">""</span>
      }
      <span class="hljs-symbol">selection:</span> <span class="hljs-string">""</span><span class="hljs-string">"
      amount: default_price
      isActive: is_active
      currency
      recurringInterval: recurring.interval -&gt; match(
        [0,"</span>ONE_TIME<span class="hljs-string">"],
        [1,"</span>DAILY<span class="hljs-string">"],
        [2,"</span>MONTHLY<span class="hljs-string">"],
        [3,"</span>ANNUALLY<span class="hljs-string">"],
      )
      recurringCount: recurring.interval_count
      "</span><span class="hljs-string">""</span>
    )
}
</code></pre>
<p>Notice our query Products has an @connect directive that defines, at a minimum, the source name. Here, you can add the HTTP-specific configuration you need for this field, such as Authorizations headers. In this scenario, since we only defined a baseUrl in the extend schema section, we need to put the specific URL for the InvokeFunction, which is <strong>/2015-03-31/functions/product-price/invocations</strong>.</p>
<p>The selection field allows you to transform and map values returned from the REST API using the mapping definition defined in the selection field. While a complete discussion of selection mapping is beyond the scope of this article, check out the documentation for a detailed look at <a target="_blank" href="https://www.apollographql.com/docs/graphos/schema-design/connectors/responses?utm_campaign=2025-03-20_mapping-graphql-responses-doc-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">Mapping GraphQL Responses</a>.  Apollo <a target="_blank" href="https://www.apollographql.com/connectors-mapping-playground?utm_campaign=2025-03-20_connectors-mapping-playground-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">provides a free online tool</a> that makes building mappings intuitive and fast.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742756290237/91d17c59-a2d0-4a22-8acf-1faec0c0f36f.jpeg" alt="connectors mapping playground" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>Next, let’s define the Price schema and products Query.</p>
<pre><code class="lang-graphql"><span class="hljs-keyword">type</span> Price {
  <span class="hljs-symbol">amount:</span> Float
  <span class="hljs-symbol">isActive:</span> Boolean
  <span class="hljs-symbol">currency:</span> String
  <span class="hljs-symbol">recurringInterval:</span> RecurringInterval
  <span class="hljs-symbol">recurringCount:</span> Int
}
<span class="hljs-keyword">enum</span> RecurringInterval {
  ONE_TIME
  DAILY
  MONTHLY
  ANNUALLY
}

<span class="hljs-keyword">type</span> Query {
  <span class="hljs-symbol">products:</span> [Product]
    <span class="hljs-comment"># https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html</span>
    <span class="hljs-meta">@connect</span>(
      <span class="hljs-symbol">source:</span> <span class="hljs-string">"lambda"</span>
      <span class="hljs-symbol">http:</span> { <span class="hljs-symbol">POST:</span> <span class="hljs-string">"/2015-03-31/functions/products/invocations"</span> }
      <span class="hljs-symbol">selection:</span> <span class="hljs-string">""</span><span class="hljs-string">"
      $.body {
        id
        name
        description
        image
      }
      "</span><span class="hljs-string">""</span>
    )
}
</code></pre>
<p>Now we're ready to run our connector and issue queries to our graph! The complete configuration script is available <a target="_blank" href="https://gist.github.com/RWaltersMA/e44813a89c748e175d6997f659162b33.">at this Gist</a>.</p>
<h3 id="heading-step-10-run-the-connector">Step 10: Run the Connector</h3>
<p>If you're using VS Code, the repository includes a tasks.json file that adds a “rover dev” task, which launches Rover locally. </p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"version"</span>: <span class="hljs-string">"2.0.0"</span>,
    <span class="hljs-attr">"tasks"</span>: [{
        <span class="hljs-attr">"label"</span>: <span class="hljs-string">"rover dev"</span>,
        <span class="hljs-attr">"command"</span>: <span class="hljs-string">"rover"</span>, <span class="hljs-comment">// Could be any other shell command</span>
        <span class="hljs-attr">"args"</span>: [<span class="hljs-string">"dev"</span>, <span class="hljs-string">"--supergraph-config"</span>,<span class="hljs-string">"supergraph.yaml"</span>, <span class="hljs-string">"--router-config"</span>,<span class="hljs-string">"router.yaml"</span>],
        <span class="hljs-attr">"type"</span>: <span class="hljs-string">"shell"</span>,
        <span class="hljs-attr">"problemMatcher"</span>: [],
    }]
}
</code></pre>
<p> If you are not using VS Code, you can start your graph by executing <code>rover dev –supergraph-config supergraph.yaml –router-config router.yaml</code> from a terminal window.</p>
<p>If everything is configured correctly, you’ll see the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742756354078/9fab875a-d064-4723-be91-8ca0d6243b59.jpeg" alt="running rover dev command " class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<h2 id="heading-section-3-how-to-use-apollo-sandbox">Section 3: How to Use Apollo Sandbox</h2>
<p>The <code>rover dev</code> command you launched in the previous step configures a local Apollo Router instance for <a target="_blank" href="https://www.apollographql.com/docs/graphos/reference/router/configuration?utm_campaign=2025-03-20_router-configuration-doc-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp#-dev">development mode</a>. This mode makes it easy for developers to create, execute, and debug ad-hoc GraphQL queries using the Apollo Sandbox web portal. This portal is located at <a target="_blank" href="http://localhost:4000">http://localhost:4000</a> by default.</p>
<p>Launch the portal and click on the products field. This will populate the Operation pane with all the available fields in the schema. In the operation pane, you can modify and build your GraphQL query. Clicking the Run button (which displays the query name, Products, in our example) will execute the query and show the results in the Response panel, as illustrated in the figure above.</p>
<p>In this example, you can see that data has been returned from our AWS Lambda function. To confirm, you can view the query plan by selecting "Query Plan” from the Response drop-down menu.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742756499055/822467d7-0694-423e-baef-450a8d0dd64e.jpeg" alt="query plan menu item" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The query plan illustrates the orchestration of our two AWS Lambda functions that fetch product and product price data.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742756540147/af32d615-029a-4f6f-a489-96ee9950e630.jpeg" alt="query plan" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>A helpful debugging feature is the Connectors Debugger, available in the drop-down as shown in the previous figure.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742756614481/c9b311e3-ab5d-4927-9457-e9a7d242fbdf.jpeg" alt="debugger showing request overview" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p>The Connection Debugger provides a comprehensive view of the HTTP request, including headers, body, response code, and the selection mapping used in the query. If you’re experiencing difficulties running queries, use this debugger – it will save you a lot of time.</p>
<h2 id="heading-summary">Summary</h2>
<p>In this article, you learned how to: </p>
<ul>
<li><p>Set up AWS IAM User, Policies, and Lambda functions</p>
</li>
<li><p>Create an Apollo Connector to obtain data from an AWS Lambda function</p>
</li>
<li><p>Configure the Apollo Router </p>
</li>
<li><p>Execute and debug queries using Apollo Sandbox</p>
</li>
</ul>
<p>Integrating AWS Lambda with Apollo Connectors offers a simplified, resolver-free method for incorporating cloud functions into your GraphQL API. By utilizing Apollo Connectors, you can declaratively link REST-based Lambda functions to your supergraph while ensuring secure authentication with AWS SigV4.</p>
<p>You can learn more about Apollo Connectors from the following resources:</p>
<ol>
<li><p>Tutorial: <a target="_blank" href="https://www.apollographql.com/tutorials/connectors-intro-rest?utm_campaign=2025-03-20_connectors-intro-rest-odyssey-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">GraphQL meets REST, with Apollo Connectors</a></p>
</li>
<li><p>Blog: Discover how Apollo Connectors integrate with Apollo Federation through insights from Apollo's Founder &amp; CTO: <a target="_blank" href="https://www.apollographql.com/blog/api-orchestration-with-graphql?utm_campaign=2025-03-20_api-orchestration-with-graphql-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">REST API Orchestration with GraphQL</a>.</p>
</li>
<li><p>Blog: Delve into the engineering journey behind Apollo Connectors and the process of their creation: <a target="_blank" href="https://www.apollographql.com/blog/our-journey-to-apollo-connectors?utm_campaign=2025-03-20_our-journey-to-apollo-connectors-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">Our Journey to Apollo Connectors</a></p>
</li>
<li><p>Webinar: <a target="_blank" href="https://www.apollographql.com/events/new-innovations-from-apollo-dont-miss-out?utm_campaign=2025-03-20_new-innovations-from-apollo-dont-miss-out-march2025awareness&amp;utm_medium=blog&amp;utm_source=freecodecamp">Apollo Connectors GA Launch Webinar</a></p>
</li>
</ol>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Pokemon App with GraphQL and Apollo ]]>
                </title>
                <description>
                    <![CDATA[ Pokemon is a Japanese media franchise consisting of video games, animated series and films, a trading card game, and other related media. In this blog, we will be building with a Pokemon GraphQL API that gives us data about different Pokemons. We wil... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-pokemon-app-with-graphql-and-apollo/</link>
                <guid isPermaLink="false">66c8c949e9e57963a5d82ad0</guid>
                
                    <category>
                        <![CDATA[ Apollo GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ projects ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Segun Ajibola ]]>
                </dc:creator>
                <pubDate>Wed, 03 Apr 2024 12:28:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/Parameters-vs-Arguments--2-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Pokemon is a Japanese media franchise consisting of video games, animated series and films, a trading card game, and other related media.</p>
<p>In this blog, we will be building with a Pokemon GraphQL API that gives us data about different Pokemons.</p>
<p>We will be using Apollo and GraphQL to handle the data fetching, and React for building our front-end application.</p>
<p>No worries if you don't know these technologies, I will be walking you through the basics as you read on.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>You should have these in your computer to follow along:</p>
<ul>
<li>Nodejs v18+</li>
<li>A code editor</li>
<li>A web browser</li>
</ul>
<p>Let's create our React app.</p>
<h3 id="heading-react-application-setup">React Application Setup</h3>
<p>To create your React app, navigate to your terminal, and use the Command Prompt. Open your Command Prompt and choose your preferred location for creating your React project. Let's go with Desktop.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> Desktop
</code></pre>
<p>The above command will navigate to your Desktop.</p>
<pre><code class="lang-bash">npm create vite@latest pokemon-app -- --template react
</code></pre>
<p><code>npm create vite@latest</code> will start to build a new project using Vite. But we attached the name of our project (<code>pokemon-app</code>) and the technology or framework our app will be using (<code>-- -- template react</code>). </p>
<p>You can set another template like <code>svelte</code>, <code>vanilla</code> or <code>vue</code> and the project will be created using that framework. Read more about Vite on <a target="_blank" href="https://vitejs.dev/guide/">its official website</a>.</p>
<p>After the Vite installation, run the following commands:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> pokemon-app
npm install
npm run dev
</code></pre>
<p>We'll use the commands above to finish the React setup.</p>
<p>Run the first command, <code>cd pokemon-app</code>, to navigate to the <strong>pokeman-app</strong> folder.</p>
<p>Run <code>code .</code> to open the folder in your code editor.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711666709423/593e293d-af0b-4cbd-b4ac-83d0c8213446.png" alt="Image" width="600" height="400" loading="lazy">
<em>modal displaying over VSCode to accept that you trust the authors of the files opened in VSCode</em></p>
<p>Mark the trust the author checkbox if that pops up.</p>
<p>Open your code editor's terminal. If you are running VSCode on Windows, the shortcut is `Ctrl + `` .</p>
<p>Run the other 2 commands in the terminal one after the other.</p>
<pre><code class="lang-bash">npm install
</code></pre>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>Your project should be running in the browser now.</p>
<p>We will be managing our data fetching using GraphQL and Apollo.</p>
<h2 id="heading-how-to-use-graphql-and-apollo">How to Use GraphQL and Apollo</h2>
<p>GraphQL is a query language for APIs and a runtime for fulfilling queries with your existing data. It allows you to request only the data you need in your application and nothing more, making it very efficient and flexible.</p>
<p>Apollo is a state management library that allows you to manage local and remote data with GraphQL. It can be used to fetch, cache, and modify application data, all while automatically updating your UI.</p>
<p>Let's install the packages you need.</p>
<h3 id="heading-installing-packages">Installing Packages</h3>
<p>Run the command below in your terminal to install the Apollo client.</p>
<pre><code class="lang-bash">npm install @apollo/client
</code></pre>
<p>Navigate to your <strong>main.jsx</strong> file and import these:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App.jsx"</span>;
<span class="hljs-keyword">import</span> {
  ApolloProvider,
  ApolloClient,
  InMemoryCache,
} <span class="hljs-keyword">from</span> <span class="hljs-string">"@apollo/client"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;
</code></pre>
<p>You have imported React and ReactDOM for DOM manipulation.</p>
<p><code>ApolloClient</code> is responsible for managing your application's data fetching and state management. It handles sending GraphQL queries and mutations to your GraphQL server and caching the results.</p>
<p><code>ApolloProvider</code> will be used to wrap your React application to provide the Apollo Client instance to all your components so that your application can access data fetched through Apollo Client.</p>
<p><code>InMemoryCache</code> is a cache implementation to store the results of GraphQL queries in memory for efficient access and retrieval.</p>
<p>You have also imported <strong>index.css</strong> to style your application.</p>
<h3 id="heading-how-to-create-an-apollo-client">How to Create an Apollo Client</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApolloClient({
  <span class="hljs-attr">uri</span>: <span class="hljs-string">"https://graphql-pokemon2.vercel.app/"</span>,
  <span class="hljs-attr">cache</span>: <span class="hljs-keyword">new</span> InMemoryCache(),
});
</code></pre>
<p>The code above creates a new instance of <code>ApolloClient</code> with the some configurations:</p>
<ol>
<li><code>uri</code>: This specifies the URL of your GraphQL API endpoint. This is the endpoint where your Apollo Client will send GraphQL queries and mutations.</li>
<li><code>cache</code>: This configures the cache implementation for Apollo Client to use an in-memory cache to access data and store the result of GraphQL queries, reducing the need to re-fetch data from the server.</li>
</ol>
<p>You can now wrap your <code>&lt;App /&gt;</code> component with <code>ApolloProvider</code>:</p>
<pre><code class="lang-javascript">ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ApolloProvider</span> <span class="hljs-attr">client</span>=<span class="hljs-string">{client}</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ApolloProvider</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
);
</code></pre>
<p>Note that <code>client</code> props was also passed to provide your application with <code>ApolloClient</code> configuration.</p>
<p>Go to your <strong>App.jsx</strong> component and input this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { PokemonsContainer } <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/PokemonsContainer"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">PokemonsContainer</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  );
}
</code></pre>
<p>You imported React and <code>PokemonsContainer</code> will be created. The <code>PokemonsContainer</code> component was wrapped in main tag and will be rendered when the component is pasted in the DOM.</p>
<p>Let's create the <code>PokemonsContainer</code> component in a file located in <strong>components</strong> folder. That is:</p>
<p>📂 src/components/PokemonsContainer.jsx</p>
<h3 id="heading-pokemons-container-component">Pokemons Container Component</h3>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { useQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">"@apollo/client"</span>;
<span class="hljs-keyword">import</span> { Pokemon } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Pokemon"</span>;
<span class="hljs-keyword">import</span> { GET_POKEMONS } <span class="hljs-keyword">from</span> <span class="hljs-string">"../graphql/get-pokemons"</span>;
</code></pre>
<p>The <code>useQuery</code> from <code>@apollo/client</code> is used for executing queries in an Apollo application. To do that, <code>useQuery()</code> is called and a GraphQL query string is passed as a argument. When your component renders, <code>useQuery</code> returns an object from Apollo Client that contains <code>loading</code>, <code>error</code>, and <code>data</code> properties that you can use to render your UI.</p>
<p><code>Pokemon</code> component was imported to render a user interface for a Pokemon, this will be built shortly.</p>
<p><code>GET_POKEMONS</code> was also imported. This will contain a GraphQL query.</p>
<p>After importing the above functions, continue building your page.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PokemonsContainer</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> { loading, error, data } = useQuery(GET_POKEMONS, {
    <span class="hljs-attr">variables</span>: { <span class="hljs-attr">first</span>: <span class="hljs-number">5</span> },
  });

  <span class="hljs-keyword">if</span> (loading) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;
  <span class="hljs-keyword">if</span> (error) <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Error: {error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>;

  <span class="hljs-keyword">const</span> pokemons = data?.pokemons || [];
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"container"</span>&gt;</span>
      {pokemons &amp;&amp;
        pokemons.map((pokemon) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">Pokemon</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{pokemon.id}</span> <span class="hljs-attr">pokemon</span>=<span class="hljs-string">{pokemon}</span> /&gt;</span>
        ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>As mentioned earlier, <code>useQuery</code> returns an object from Apollo Client that contains <code>loading</code>, <code>error</code>, and <code>data</code> properties. They are destructured here so you can access them in the page.</p>
<p>Notice that we're providing a configuration option (<code>variables</code>) to the <code>useQuery</code> hook. <code>{ variables: { first: 5 } }</code> was also passed as the second argument. The <code>variables</code> option is an object that contains all of the variables we want to pass to our GraphQL query. In this case, we passed an object <code>{ first: 5 }</code> to specify that we want the first five Pokemons.</p>
<p>If the query is still loading, <code>&lt;p&gt;Loading...&lt;/p&gt;</code> is returned to signify the user while <code>&lt;p&gt;Error: {error.message}&lt;/p&gt;</code> will be returned if there is an error.</p>
<p>The <code>pokemons</code> constant was created to hold the value of the Pokemons property of the data object. If <code>data.pokemons</code> is not available, the <code>pokemons</code> constant will be an empty array.</p>
<p>A div is returned with a <code>classname</code> of <code>container</code> which checks if <code>pokemons</code> is available and maps the array over the <code>Pokemon</code> component.</p>
<p>Let's create the <code>Pokemon</code> component:</p>
<p>📂src/components/Pokemon.jsx</p>
<h2 id="heading-pokemon-component">Pokemon Component</h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">Pokemon</span>(<span class="hljs-params">{ pokemon }</span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"pokemon"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"pokemon__name"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{pokemon.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"pokemon__meta"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{pokemon.maxHP}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>{pokemon.maxCP}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"pokemon__image"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{pokemon.image}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">{pokemon.name}</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"pokemon__attacks"</span>&gt;</span>
        {pokemon.attacks.special.slice(0, 3).map((attack) =&gt; (
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">attack.name</span>}<span class="hljs-attr">-</span>${<span class="hljs-attr">attack.damage</span>}`}&gt;</span>{attack.name}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
        ))}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
}
</code></pre>
<p>The structure of an instance of a Pokemon is defined here with the classname for styling. The <code>name</code>, <code>maxHP</code>, <code>maxCP</code>, <code>image</code> and <code>attacks</code> array will be rendered.</p>
<p>Let's create the <code>GET_POKEMONS</code> GraphQL query.</p>
<p>📂src/graphql/get-pokemons</p>
<h2 id="heading-graphql-query">GraphQL Query</h2>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> gql <span class="hljs-keyword">from</span> <span class="hljs-string">"graphql-tag"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> GET_POKEMONS = gql<span class="hljs-string">`
  query pokemons($first: Int!) {
    pokemons(first: $first) {
      id
      name
      image
      maxHP
      maxCP
      attacks {
        special {
          name
          damage
        }
      }
    }
  }
`</span>;
</code></pre>
<p>You imported <code>gql</code> from <code>graphql-tag</code> and created a GraphQL query named <code>GET_POKEMONS</code>.</p>
<p>The <code>pokemons</code> query function was wrapped in strings for the <code>gql</code> function to parse them into query documents.</p>
<p><code>$first: Int!</code> means that your query is expecting a variable called <code>first</code>, which is an integer, and the <code>!</code> symbol after the <code>Int</code> means that the variable is required.</p>
<p>Recall that we created the <code>variables</code> object in the <code>PokemonsContainer</code> component, it's here below.</p>
<pre><code class="lang-javascript"> <span class="hljs-keyword">const</span> { loading, error, data } = useQuery(GET_POKEMONS, {
   <span class="hljs-attr">variables</span>: { <span class="hljs-attr">first</span>: <span class="hljs-number">5</span> },
 });
</code></pre>
<p><code>pokemons(first: $first)</code> was also declared. <code>$first</code> will be assigned to 5 here (we passed in 9 in the above code snippet). Thus, the array will contain only 5 objects. Each object will contain <code>id</code>, <code>name</code>, <code>image</code>, <code>maxHP</code>, <code>maxCP</code>, and attacks object which will contain the special object containing name and damage.</p>
<p>The GraphQL server might contain more properties but will only return the properties listed above. That is one of the cool functionalities of GraqhQL – it gives you only the data you request for.</p>
<h2 id="heading-styling-our-application">Styling our Application</h2>
<p>Your <strong>index.css</strong> should contain this:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* RESETS
=========================================== */</span>
<span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">-webkit-box-sizing</span>: border-box;
  <span class="hljs-attribute">box-sizing</span>: border-box;
}

*,
*<span class="hljs-selector-pseudo">:before</span>,
*<span class="hljs-selector-pseudo">:after</span> {
  <span class="hljs-attribute">-webkit-box-sizing</span>: inherit;
  <span class="hljs-attribute">box-sizing</span>: inherit;
}

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">20px</span> <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1</span>;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Segoe UI"</span>, Tahoma, Geneva, Verdana, sans-serif;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#202020</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#fbfbfb</span>;
  <span class="hljs-attribute">font-smooth</span>: always;
  <span class="hljs-attribute">-webkit-font-smoothing</span>: antialiased;
  <span class="hljs-attribute">-moz-osx-font-smoothing</span>: grayscale;
}

<span class="hljs-comment">/* POKEMON APPLICATION
=========================================== */</span>
<span class="hljs-selector-class">.container</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">80%</span>;
  <span class="hljs-attribute">margin</span>: auto;
  <span class="hljs-attribute">height</span>: <span class="hljs-number">100vh</span>;
  <span class="hljs-attribute">justify-content</span>: space-between;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">gap</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-class">.pokemon</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">20%</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">background-clip</span>: border-box;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.125</span>);
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">0.25rem</span>;
  <span class="hljs-attribute">box-shadow</span>: <span class="hljs-number">0</span> <span class="hljs-number">0.125rem</span> <span class="hljs-number">0.25rem</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.075</span>);
  <span class="hljs-attribute">overflow</span>: hidden;
  <span class="hljs-comment">/* margin: 5px; */</span>
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-class">.pokemon__name</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#ecd018</span>;
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-class">.pokemon__name</span> <span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">text-transform</span>: uppercase;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">letter-spacing</span>: <span class="hljs-number">4px</span>;
  <span class="hljs-attribute">text-shadow</span>: <span class="hljs-number">0px</span> <span class="hljs-number">1px</span> <span class="hljs-number">2px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.4</span>);
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-class">.pokemon__image</span> {
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">min-height</span>: <span class="hljs-number">300px</span>;
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">align-items</span>: center;
  <span class="hljs-attribute">justify-content</span>: center;
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-class">.pokemon__image</span> <span class="hljs-selector-tag">img</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">100%</span>;
  <span class="hljs-attribute">height</span>: auto;
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-class">.pokemon__attacks</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">justify-content</span>: space-between;
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-class">.pokemon__attacks</span> <span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">32%</span>;
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f16820</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">3px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">7px</span>;
  <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">700</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">padding-left</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">padding-right</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">12px</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">word-wrap</span>: break-word;
  <span class="hljs-attribute">text-align</span>: center;
  <span class="hljs-attribute">line-height</span>: <span class="hljs-number">15px</span>;
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-class">.pokemon__meta</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">justify-content</span>: space-between;
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">10px</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">10px</span>;
}

<span class="hljs-selector-class">.container</span> <span class="hljs-selector-class">.pokemon__meta</span> <span class="hljs-selector-tag">span</span> {
  <span class="hljs-attribute">color</span>: white;
  <span class="hljs-attribute">text-shadow</span>: <span class="hljs-number">0px</span> <span class="hljs-number">1px</span> <span class="hljs-number">2px</span> <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0.4</span>);
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#7bb7b7</span>;
  <span class="hljs-attribute">font-weight</span>: bold;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">5px</span> <span class="hljs-number">20px</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">5px</span>;
}
</code></pre>
<p>All things done right, you should have this in your browser:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1712103327205/94a0fc27-6e6e-4441-b7e7-c3e3df005383.png" alt="Image" width="600" height="400" loading="lazy">
<em>a picture showing the five pokemons data in the browser</em></p>
<p>You can get the GitHub code here: <a target="_blank" href="https://github.com/segunajibola/pokemon-graphql">https://github.com/segunajibola/pokemon-graphql</a></p>
<p>You can also view the live site hosted on Vercel here: <a target="_blank" href="http://pokemonsapp.vercel.app"><strong>pokemonsapp.vercel.app</strong></a></p>
<p>Check my portfolio of projects: <a target="_blank" href="https://segunajibola.com">segunajibola.com</a></p>
<h2 id="heading-conclusionhttpspokemonsappvercelapp"><a target="_blank" href="https://pokemonsapp.vercel.app/">Conclusion</a></h2>
<p>That will be all. I hope you found value here as you learn more about the web.</p>
<p>If you enjoyed this article and want to see more content related to JavaScript and web development, then follow me here, <a target="_blank" href="https://x.com/intent/follow?screen_name=iamsegunajibola">Twitter (X)</a> or connect on <a target="_blank" href="https://www.linkedin.com/mwlite/in/segun-ajibola-511502175">LinkedIn</a>. I'd be happy to count you as one of my ever-growing group of awesome friends on the internet.</p>
<p>You can also join my <a target="_blank" href="https://chat.whatsapp.com/E57KqFYQK9B1woySXTaqKr">WhatsApp developer community</a> and <a target="_blank" href="https://chat.whatsapp.com/KH7r2EA6kMgHuHwVfM4VFB">OpenSource community</a> of 330+ developers learning and building cool projects.</p>
<p>If you also want to support me, you can also <a target="_blank" href="https://www.buymeacoffee.com/segunajibola">buy me a cup of coffee</a>.</p>
<p>Thanks and bye. 👋</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ API Integration Patterns – The Difference between REST, RPC, GraphQL, Polling, WebSockets and WebHooks ]]>
                </title>
                <description>
                    <![CDATA[ API stands for Application Programming Interface. The “I” in API is the key part that explains its purpose. The interface is what the software presents to other humans or programs, allowing them to interact with it. A good analogy for an interface is... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/api-integration-patterns/</link>
                <guid isPermaLink="false">66d45e037df3a1f32ee7f7f9</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webhooks ]]>
                    </category>
                
                    <category>
                        <![CDATA[ websocket ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Adetunji ]]>
                </dc:creator>
                <pubDate>Mon, 09 Oct 2023 15:14:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/FCC-cover--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>API stands for Application Programming Interface. The “I” in API is the key part that explains its purpose.</p>
<p>The <em>interface</em> is what the software presents to other humans or programs, allowing them to interact with it.</p>
<p>A good analogy for an interface is a remote control. Imagine you have a universal remote that can control your TV, lights, and fan.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F28286169-80d5-49f6-b302-65c8cb10fdcb_1762x1070.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Image showing a remote control and a TV, light fixture, and fan.</em></p>
<p>Let’s break down what a universal remote control can do:</p>
<ol>
<li><p>The remote control has various buttons, each serving a different purpose. One button might change the channel, while another can dim the lights of the chandelier, and another can turn on the fan.</p>
</li>
<li><p>When you press a button, it sends a specific signal via infrared, bluetooth, or wifi to the object you are controlling, instructing it to perform a particular action.</p>
</li>
<li><p>The key thing about the remote is that it allows you to interact with the TV, chandelier, and the fan without understanding the internal workings of these objects. All that complexity is abstracted away from you. You simply press a button, and you get a response that you can observe straight away.</p>
</li>
</ol>
<p>APIs work in a similar way.</p>
<ol>
<li><p>APIs can have various endpoints, each designed to perform a specific action. One endpoint might retrieve data, while another updates or deletes it.</p>
</li>
<li><p>When you send a request to an endpoint, it communicates with the server using HTTP methods – GET, POST, PUT, DELETE to instruct it to perform a particular action (like retrieving, sending, updating, or deleting data).</p>
</li>
<li><p>The key thing about APIs, as with remote controls, is that APIs abstract away the inner workings of the server and the database behind the API. The API allows users, developers and applications to interact with a software application or platform without needing to understand its internal code or database structure. You simply send a request, the server processes it and provides a response.</p>
</li>
</ol>
<p>This analogy only holds true for so long, as APIs are more complex than a remote control. But the basic principles of operation between an API and a universal remote are quite similar.</p>
<p>This article will explain API integration patterns, which can be split into two broad groups: Request-response (REST, RPC &amp; GraphQL) and event driven APIs (Polling, WebSockets &amp; WebHooks).</p>
<h2 id="heading-request-response-integration">Request-Response Integration</h2>
<p>In a request-response integration, the client initiates the action by sending a request to the server and then waits for a response.</p>
<p>Different patterns of the request-response integration exist, but at a high level, they all conform to the same rule of the client initiating a request and waiting for a response from the server.</p>
<h3 id="heading-1-rest">1. REST</h3>
<p>Rest stands for Representational State Transfer – the acronym is a combination of the first one or two letters from these three words. This is the simplest and most popular form of a request-response integration.</p>
<p>REST APIs use a <a target="_blank" href="https://lightcloud.substack.com/i/104443280/stateless-architecture">stateless</a>, client-server communication model, wherein each message contains all the information necessary to understand and process the message.</p>
<p>REST is all about resources. Resources are entities that the API exposes, which can be accessed and manipulated using URL paths.</p>
<p>To understand REST APIs, consider the following analogy. Imagine you go into a restaurant to order some food. The menu is extensive and items are categorically organised. Each item on the menu can be equated to a resource.</p>
<p>First, you call the waiter to get their attention, then you place an order. Each request receives a response, before you proceed with another request, like ordering a dish.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F267e1809-4111-43dc-8c6d-aa7bdf764c54_1102x1022.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Restaurant analogy for REST API</em></p>
<p>In REST API terms, the client initiates requests to the server by specifying exactly what it wants using HTTP methods (such as GET, POST, PUT, DELETE) on specific URLs (the menu items). Each interaction is stateless, meaning that each request from the client to the server must contain all the information needed to understand and process the request.</p>
<p>The server then processes the request and returns the appropriate response – in our analogy, bringing the ordered item to the table.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd86ab699-f5a2-4c93-9ac8-ee0af83df14d_1174x916.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Simple sequence diagram for REST API</em></p>
<h3 id="heading-2-rpc">2. RPC</h3>
<p>RPC stands for Remote Procedure Call. Unlike REST APIs which are all about resources, RPC is all about actions. With RPC, the client executes a block of code on the server</p>
<p>Think of a restaurant without a menu. There is no dish you can request in this restaurant. Instead, you request a specific action to be performed by the restaurant.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9a0ce7-d263-4932-b159-a3234677cf71_1518x926.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Restaurant analogy for RPC</em></p>
<p>With a REST API, the guest would have simply asked for some fish and chips. With RPC, they have to give instructions on what they want the kitchen to prepare.</p>
<p>In the RPC pattern, the client calls a specific procedure on the server and waits for the result. The procedure to prepare and what gets prepared are tightly bound together. This might give the client very specific and tailored results, but lacks the flexibility and ease of use of REST.</p>
<p>There is a reason most restaurants use menus, instead of following the custom requests of their customers. This partly explains why RPC is a less popular integration pattern compared to REST.</p>
<h3 id="heading-3-graphql">3. GraphQL</h3>
<p>With GraphQL, the client specifies exactly what data it needs, which can include specific fields from various resources. The server processes this query, retrieves the exact data, and returns it to the client.</p>
<p>This enables the client to have a high degree of flexibility and only retrieve exactly the data it needs. It also requires the server to be capable of handling more complex and unique queries.</p>
<p>In this way, GraphQL is a more customisable form of REST. You still deal with resources (unlike actions in RPC) but you can customise how you want the resource returned to you.</p>
<p>Think of a restaurant that allows you to customise your own dish by specifying exact quantities or ingredients you want.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9327807-033d-4e21-b649-0de8e33272bd_1518x858.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Restaurant analogy for GraphQL</em></p>
<p>This may look similar to the RPC pattern, but notice that the customer is not saying how the food should be made, they're just customising their order by removing some ingredients (no salt) and reducing the number of some items (two pieces of fish instead of four).</p>
<p>One of the drawbacks of GraphQL is that it adds complexity to the API since the server needs to do additional processing to parse complex queries. This additional complexity would also apply to the restaurant analogy, since each order would need to be customised to the guest.</p>
<p>GraphQL has one clear benefit over REST and RPC. Since clients can specify exactly what they need, the response payload sizes are typically smaller, which means faster response times.</p>
<h2 id="heading-event-driven-integration">Event Driven Integration</h2>
<p>This integration pattern is ideal for services with fast changing data.</p>
<p>Some of these integration patterns are also <a target="_blank" href="https://lightcloud.substack.com/p/synchronous-and-asynchronous-communication">asynchronous</a> and initiated by the server, unlike the request-response patterns which are <a target="_blank" href="https://lightcloud.substack.com/p/synchronous-and-asynchronous-communication">synchronous</a> and initiated by the client.</p>
<h3 id="heading-1-polling">1. Polling</h3>
<p>Let’s bring back the restaurant analogy. When you order food, it will take some time for it to be prepared.</p>
<p>You can get updates on your order by asking the waiter if it is ready yet. The more frequently you ask, the closer you will be to having real-time information about your order.</p>
<p>This, however, puts unnecessary strain on the waiter since they have to constantly check the status of your order and have them update you whenever you ask.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F661f8761-5b3e-426f-aa55-fbadc25bd226_892x888.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Restaurant analogy for polling</em></p>
<p>Polling is when the client continuously asks the server if there is new data available, with a set frequency. It's not efficient because many requests may return no new data, thus unnecessarily consuming resources.</p>
<p>The more frequently you poll (make requests) the closer the client gets to real-time communication with the server.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a8467fc-580f-46e4-b134-7dc3128f044a_1174x954.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Simple sequence diagram showing polling in action</em></p>
<p>Most of the requests during polling are wasted, since they only return something useful to the client once there is a change on the server.</p>
<p>There is, however, another version of polling called long polling. With long polling, the waiter does not respond to the guest straightaway about the status of the order. Instead, the waiter only responds if there is an update.</p>
<p>Naturally, this only works if the guest and the waiter agree beforehand that a slow response from the waiter does not mean that the waiter is being rude and the guest is being ignored.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff76ea285-2629-4aea-8b89-81d500484835_892x888.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Restaurant analogy for long polling</em></p>
<p>With long polling, the server does not respond to the client immediately. It waits until something has changed before responding.</p>
<p>As long as the client and server agree that the server will hold on to the client’s request, and the connection between the client and server remains open, this pattern works and can be more efficient than simply polling.</p>
<p>These two assumptions for long polling may be unrealistic, though – the server can lose the client's request and/or the connection can be broken.</p>
<p>To address these limitations, long polling adds extra complexity to the process by requiring a directory of which server contains the connection to the client, which is used to send data to the client whenever the server is ready.</p>
<p>Standard polling on the other hand can remain <a target="_blank" href="https://lightcloud.substack.com/i/104443280/stateless-architecture">stateless</a>, making it more <a target="_blank" href="https://lightcloud.substack.com/i/59017006/fault-tolerance">fault tolerant</a> and scalable.</p>
<h3 id="heading-2-websockets">2. WebSockets</h3>
<p>WebSockets provide a persistent, two-way communication channel between the client and server. Once a WebSocket connection is established, both parties can communicate freely, which enables real-time data flows and is more resource-efficient than polling.</p>
<p>Using the restaurant analogy again, a guest orders a meal and then establishes a dedicated communication channel with the waiter so they can freely communicate back and forth about updates or changes to the order until the meal is ready. This means the waiter can also initiate the communication with the guest, which is not the case for the other integration patterns mentioned so far.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffebdcac2-f175-4ea1-bd19-1234702def98_892x888.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Restaurant analogy for WebSockets</em></p>
<p>WebSockets are similar to long polling. They both avoid the wasteful requests of polling, but WebSockets have the added benefit of having a persistent connection between the client and the server.</p>
<p>WebSockets are ideal for fast, live streaming data, like real-time chat applications. The downside of WebSockets is that the persistent connection consumes bandwidth, so may not be ideal for mobile applications or in areas with poor connectivity</p>
<h3 id="heading-3-webhooks">3. WebHooks</h3>
<p>WebHooks allow the server to notify the client when there's new data available. The client registers a callback URL with the server and the server sends a message to that URL when there is data to send.</p>
<p>With WebHooks, the client sends requests as usual, but can also listen for and receive requests like a server.</p>
<p><img src="https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7d687228-bff2-45d4-a7ac-8ebe2bb07094_1458x954.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Simple sequence diagram showing WebHooks in action</em></p>
<p>Using the restaurant analogy, when the guest orders a meal, they give the waiter a bell (analogous to the callback URL). The waiter goes to the kitchen and rings the bell as soon as the meal is ready. This allows the client to know, in real-time, about the progress of his order.</p>
<p>WebHooks are superior to polling because you get real-time updates from the server once something changes, without having to make frequent, wasteful requests to the server about that change.</p>
<p>They're also superior to long polling because long polling can consume more client and server resources as it involves keeping connections open, potentially resulting in many open connections.</p>
<h2 id="heading-bringing-it-together">Bringing it Together</h2>
<p>In conclusion, APIs are crucial tools in software development, allowing users and applications to interact with software without understanding its inner workings.</p>
<p>They come in different integration patterns, such as REST, RPC, GraphQL, Polling, WebSockets, and WebHooks.</p>
<p>If you need a simple request-response integration, then REST, RPC or GraphQL could be ideal. For real-time or near-real-time applications, polling, WebScokets, or WebHooks are ideal.</p>
<p>As with any design problem, the right choice depends on the business case and what tradeoffs you are willing to tolerate.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use GraphQL ]]>
                </title>
                <description>
                    <![CDATA[ GraphQL has been transforming the way that developers interact with APIs and data-driven applications. And there is a good chance you will need to know about it as a developer. We just posted a full GraphQL course on the freeCodeCamp.org YouTube chan... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/graphql-database-tutorial/</link>
                <guid isPermaLink="false">66b202b1125aeccef6f65cb5</guid>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Fri, 01 Sep 2023 20:47:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/graphql.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>GraphQL has been transforming the way that developers interact with APIs and data-driven applications. And there is a good chance you will need to know about it as a developer.</p>
<p>We just posted a full GraphQL course on the freeCodeCamp.org YouTube channel. In this comprehensive course, designed especially for those new to GraphQL, you will learn the knowledge and skills to create robust and efficient data-driven applications.</p>
<p>The Net Ninja created this course. He is a prolific technical course creator and is also one of the most viewed GraphQL instructors on the Internet. So he is the perfect person to teach this new GraphQL course.</p>
<p>GraphQL is a query language for your API, and a runtime for executing those queries by using a type system that you define for your data. Developed by Facebook in 2012 and released as an open-source project in 2015, GraphQL provides a more efficient, powerful, and flexible alternative to the traditional REST API. Instead of having multiple endpoints for different data needs, with GraphQL, you can request exactly what you need, all in one query. This can result in faster and more precise data retrieval.</p>
<p>This course will provide you with a solid foundation in GraphQL, allowing you to fully grasp its core principles and understand how it differs from traditional REST APIs.</p>
<p>Here are the sections in this course:</p>
<ul>
<li>What is GraphQL?</li>
<li>Query Basics</li>
<li>Making a GraphQL Server (with Apollo)</li>
<li>Schema &amp; Types</li>
<li>Resolver Functions</li>
<li>Query Variables</li>
<li>Related Data</li>
<li>Mutations (Adding &amp; Deleting Data)</li>
<li>Update Mutation</li>
</ul>
<p>By the time you complete this course, you'll be equipped with the practical skills needed to design, implement, and optimize data-driven applications using GraphQL. The Net Ninja's engaging teaching style and step-by-step tutorials ensure that you'll be able to follow along and apply what you've learned immediately.</p>
<p>Watch the full course on <a target="_blank" href="https://www.youtube.com/watch?v=5199E50O7SI">the freeCodeCamp.org YouTube channel</a> (1.5 hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/5199E50O7SI" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Avoid the N+1 Query Problem in GraphQL and REST APIs [with Benchmarks] ]]>
                </title>
                <description>
                    <![CDATA[ By Mohamed Mayallo The N+1 query problem is a performance issue you might face while building APIs, regardless of whether they're GraphQL or REST APIs. In fact, this problem occurs when your application needs to return a set of data that includes rel... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/n-plus-one-query-problem/</link>
                <guid isPermaLink="false">66d46013a326133d12440a21</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                    <category>
                        <![CDATA[ web performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 07 Jul 2023 17:59:59 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/N-1-Query-Problem.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Mohamed Mayallo</p>
<p>The N+1 query problem is a performance issue you might face while building APIs, regardless of whether they're GraphQL or REST APIs.</p>
<p>In fact, this problem occurs when your application needs to return a set of data that includes related nested data – for example, a post that includes comments.</p>
<p>But how can you fix this problem? To avoid this issue, you should understand what is it and how it occurs.</p>
<p>So in this tutorial, you'll learn what the N+1 query problem is, why it is easy to fall into it, and how you can avoid it.</p>
<p>Before starting, it is good to know:</p>
<ul>
<li>The examples in this article are just for the sake of simplicity.</li>
<li><code>SELECT *</code> is very bad, and you should avoid it.</li>
<li>You should care about pagination if you’re working with large data sets.</li>
</ul>
<p>You can find the examples in this article in this <a target="_blank" href="https://github.com/Mohamed-Mayallo/n_plus_one_problem_benchmarks">repo</a>. Let's dive in.</p>
<h2 id="heading-understanding-the-n1-query-problem">Understanding the N+1 Query Problem</h2>
<p>The N+1 problem occurs when your application needs to return a set of data that includes related data that exists in:</p>
<ul>
<li>Another table.</li>
<li>Another database (in the case of microservices, for example)</li>
<li>Or even another third-party service.</li>
</ul>
<p>In other words, you need to execute extra database queries or external requests to return the nested data.</p>
<p>If you are wondering about what the name means (N+1), follow the below example, which uses a single database:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/related-data.drawio.png" alt="Post and Comment tables | By Author" width="600" height="400" loading="lazy">
<em>Illustration of N+1 problem</em></p>
<p>As you can see, the relationship between <code>Post</code> and <code>Comment</code> is one-to-many, respectively.</p>
<p>So, if your application needs to return a list of posts and their related comments, you might end up with this code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">'SELECT * FROM "Post"'</span>); <span class="hljs-comment">// Get all posts (1 database query)</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> post <span class="hljs-keyword">in</span> posts) {
    <span class="hljs-comment">// For sure, you can replace the following query with an external request if you need to retrieve the post's comments from another service</span>
    <span class="hljs-keyword">const</span> comments = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">`SELECT * FROM "Comment" WHERE "post_id" = <span class="hljs-subst">${post.id}</span>`</span>); <span class="hljs-comment">// Get all comments for every post (n database query for n posts)</span>
    post.comments = comments;
}
</code></pre>
<p>So, you have executed <strong>N</strong> queries to retrieve every post’s comments and <strong>1</strong> query to retrieve all posts <strong>(N comments queries + 1 posts query).</strong></p>
<p>But, why you should be aware of this problem?</p>
<h2 id="heading-why-is-the-n1-query-problem-a-serious-issue">Why Is the N+1 Query Problem a Serious Issue?</h2>
<p>Here are some reasons why the N+1 query problem can cause serious performance issues in your application:</p>
<ol>
<li>Your application makes a lot of database queries or external requests to retrieve a list of data like posts.</li>
<li>The more data your application retrieves, the slower your request is going to be and the more resources your application is going to consume.</li>
<li>A large data set might end up with notable network latency.</li>
<li>It is going to be challenging to scale the application to handle larger data sets.</li>
</ol>
<p>On top of that, you are going to see the performance impact in numbers in the benchmarks section later in this article.</p>
<p>Now that you understand the N+1 query problem and its impact on your application, let’s introduce some effective ways you can avoid this problem.</p>
<h2 id="heading-strategies-to-avoid-the-n1-query-problem">Strategies to Avoid the N+1 Query Problem</h2>
<p>Fortunately, there are a few simple strategies you can follow to avoid the N+1 query problem.</p>
<p>Let’s apply them to our previous example.</p>
<h3 id="heading-1-eager-loading-using-sql-joins-for-example">1) Eager Loading (Using SQL Joins, for example)</h3>
<p>In this strategy, instead of returning the post’s comments separately for every post, you can use <strong>SQL Joins</strong>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> postsAndComments = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">`
    SELECT * 
    FROM "Post"
    JOIN "Comment"
    ON "Comment"."post_id" = "Post"."post_id"
`</span>);
</code></pre>
<p>When you're using this strategy, it's good to know that:</p>
<ul>
<li>It is only one database query to return all posts and their nested comments.</li>
<li>You can't apply this strategy if you are consuming your data sets from a different database or service.</li>
</ul>
<h3 id="heading-2-batch-loading">2) Batch Loading</h3>
<p>In this strategy, your code should follow the below steps:</p>
<ul>
<li>Execute one request to retrieve all posts.</li>
<li>Execute another request to load a batch of posts’ comments instead of loading every post’s comments separately.</li>
<li>Map every comment to its corresponding parent post.</li>
</ul>
<p>Let’s jump into an example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">'SELECT * FROM "Post"'</span>), <span class="hljs-comment">// 1- Retrieve all posts in one request</span>
    postsIds = posts.map(<span class="hljs-function"><span class="hljs-params">post</span> =&gt;</span> post.id),
    postsComments = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">`SELECT * FROM "Comment" WHERE "post_id" IN (<span class="hljs-subst">${postsIds}</span>)`</span>); <span class="hljs-comment">// 2- retrieve all posts’ comments in another request</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> post <span class="hljs-keyword">in</span> posts) { <span class="hljs-comment">// 3- Map every comment to its parent post</span>
    <span class="hljs-keyword">const</span> comments = postsComments.filter(<span class="hljs-function"><span class="hljs-params">comment</span> =&gt;</span> comment.post_id === post.id);
    post.comments = comments;
}
</code></pre>
<p>As you see, in this strategy, there are just two requests: one to retrieve all posts and another one to retrieve their comments.</p>
<h3 id="heading-3-caching">3) Caching</h3>
<p>You may be familiar with caching and its impact on any application's performance.</p>
<p>You can implement caching on your client side or server side using <a target="_blank" href="https://redis.io/">Redis</a>, <a target="_blank" href="https://memcached.org/">Memcached</a>, or any other similar tool. Wherever you can properly use caching, it significantly pushes your application's performance.</p>
<p>Let’s get back to our example and cache the posts’ comments in a Redis store.</p>
<pre><code class="lang-js">    <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">'SELECT * FROM "Post"'</span>),
        postsIds = posts.map(<span class="hljs-function"><span class="hljs-params">post</span> =&gt;</span> post.id),
        cachedPostsComments = getPostsCommentsFromRedis(postsIds);

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> post <span class="hljs-keyword">in</span> posts) {
    <span class="hljs-keyword">const</span> comments = cachedPostsComments.filter(<span class="hljs-function"><span class="hljs-params">comment</span> =&gt;</span> comment.post_id === post.id);
    post.comments = comments;
}
</code></pre>
<p>As you might guess, you can cache the posts’ comments or even the posts themselves which significantly minimizes the load on databases.</p>
<h3 id="heading-4-lazy-loading">4) Lazy Loading</h3>
<p>In this strategy, you are distributing the responsibility between the server side and the client side.</p>
<p>You shouldn’t return all data at once from the server side. Instead, you prepare two endpoints for the client side like this:</p>
<ul>
<li><code>GET /api/posts</code>: Retrieves all posts.</li>
<li><code>GET /api/comments/:postId</code>: Retrieves a post’s comments on demand.</li>
</ul>
<p>And now, the data retrieval is up to the client side.</p>
<p>This strategy is very useful because:</p>
<ul>
<li>It enables the client side to load the parent post first and display its content, and then load its related comments lazily. So users don't have to wait for the entire data set to be returned from the server side.</li>
<li>You have full control over sorting, filtering, pagination and so on over every endpoint.</li>
</ul>
<p>The key point of this strategy is that it gets rid of nested data like comments and flattens all data sets in their own endpoint.</p>
<h3 id="heading-5-graphql-dataloader">5) GraphQL Dataloader</h3>
<p>As you might guess, this strategy works with GraphQL APIs.</p>
<p>Dataloader is a GraphQL utility that works by batching multiple database queries into one request. So, it uses the Batch Loading strategy under the hood.</p>
<p>Let’s jump into our example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> DataLoader = <span class="hljs-built_in">require</span>(<span class="hljs-string">'dataloader'</span>);

<span class="hljs-comment">// 1- GraphQL Schema Definition</span>
<span class="hljs-keyword">const</span> typeDefs = gql<span class="hljs-string">`
  type Post {
    post_id: ID!
        comments: [Comment]
  }

    type Comment {
        comment_id: ID!
    post_id: ID!
  }

  type Query {
    posts: [Post]
  }
`</span>;

<span class="hljs-comment">// 2- Resolve the GraphQL Schema</span>
<span class="hljs-keyword">const</span> resolvers = {
  <span class="hljs-attr">Query</span>: {
    <span class="hljs-attr">posts</span>: <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> posts = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">'SELECT * FROM "Post"'</span>);
            <span class="hljs-keyword">return</span> posts;
    }
  },

  <span class="hljs-attr">Post</span>: {
    <span class="hljs-attr">comments</span>: <span class="hljs-function">(<span class="hljs-params">post, args, { dataLoaders }</span>) =&gt;</span> {
      <span class="hljs-keyword">return</span> dataLoaders.commentsLoader.load(post.id);
    }
  }
};

<span class="hljs-comment">// 3- Define Dataloaders</span>
<span class="hljs-keyword">const</span> commentsBatchFunction = <span class="hljs-keyword">async</span> postsIds =&gt; {
      <span class="hljs-keyword">const</span> comments = <span class="hljs-keyword">await</span> rawSql(<span class="hljs-string">`SELECT * FROM "Comment" WHERE "post_id" IN (<span class="hljs-subst">${postsIds}</span>)`</span>);
        <span class="hljs-keyword">const</span> groupedComments = comments.reduce(<span class="hljs-function">(<span class="hljs-params">tot, cur</span>) =&gt;</span> {
      <span class="hljs-keyword">if</span> (!tot[cur.post_id]) {
        tot[cur.post_id] = [cur];
      } <span class="hljs-keyword">else</span> {
        tot[cur.post_id].push(cur);
      }
      <span class="hljs-keyword">return</span> tot;
    }, {});
        <span class="hljs-keyword">return</span> postsIds.map(<span class="hljs-function">(<span class="hljs-params">postId</span>) =&gt;</span> groupedComments[postId]);
    },
    createCommentsLoader = <span class="hljs-keyword">new</span> DataLoader(commentsBatchFunction),
    createDataloaders = <span class="hljs-function">() =&gt;</span> ({
        <span class="hljs-attr">commentsLoader</span>: createCommentsLoader()
    });

<span class="hljs-comment">// 4- Inject Dataloaders in the GraphQL Context</span>
<span class="hljs-keyword">const</span> server = <span class="hljs-keyword">new</span> ApolloServer({
    typeDefs,
    resolvers,
    <span class="hljs-attr">context</span>: <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">dataLoaders</span>: createDataloaders(),
    }
  }
});
</code></pre>
<p>So how does it work? To get more detailed information, you can check out the <a target="_blank" href="https://github.com/graphql/dataloader">documentation</a>. But we'll go through the basics here.</p>
<p>The key point of the Dataloader is the <a target="_blank" href="https://github.com/graphql/dataloader#batch-function">Batch Function</a>. Here, the batch function <code>commentsBatchFunction</code> takes an array of keys <code>postsIds</code> and returns a <a target="_blank" href="https://mayallo.com/asynchronous-javascript/">Promise which resolves</a> to an array of values <code>comments</code>, <code>[ [post1comment1, post1comment2], [post2comment1], ... ]</code>.</p>
<p>On top of that, the batch function has two constraints:</p>
<ul>
<li>The size of the keys array <code>postsIds</code> must equal the values array <code>comments</code>. In other words, this expression must be true: <code>postsIds.length === comments.length</code>.</li>
<li>Each index in the keys array <code>postsIds</code> must correspond to the values array <code>comments</code>. So you might note that I looped over the <code>postsIds</code> to map each corresponding comment.</li>
</ul>
<p>As a result, you can see that GraphQL Dataloader uses the second strategy (Batch Loading) under the hood.</p>
<p>Let’s get back to our example to walk through its implementation:</p>
<ol>
<li>First, we defined the GraphQL schema.</li>
<li>Then we resolved the GraphQL schema. Keep in mind, if you resolved the comments in the <code>Post</code> type using this query <code>await rawSql('SELECT * FROM "Comment" WHERE "post_id" = ' + post.id);</code>, you’re going to fall into the N+1 query problem.</li>
<li>Next, we defined the comments batch function and then created the comments dataloader.</li>
<li>Finally, we injected dataloaders in the <a target="_blank" href="https://www.apollographql.com/docs/apollo-server/data/context/">GraphQL Context</a> to be able to use them in resolvers.</li>
</ol>
<p>So, by using GraphQL Dataloader, if you have 10 posts and every post has 5 comments, you would end up with two queries – one to retrieve the 10 posts and another one to retrieve their comments.</p>
<p>Take a look at the following screenshot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Code_1K9XMH0CHB.png" alt="Database queries with GraphQL Dataloader and without it" width="600" height="400" loading="lazy">
<em>Illustration of process with and without Dataloader</em></p>
<h2 id="heading-benchmarks-about-n1-query-problem">Benchmarks About N+1 Query Problem</h2>
<p>In this section, let’s compare each strategy in terms of performance.</p>
<table>
<thead>
<tr>
<th>N+1 in REST API</th>
<th>Eager Loading Strategy</th>
<th>Batch Loading Strategy</th>
<th>Caching Strategy</th>
<th>N+1 in GraphQL API</th>
<th>GraphQL Dataloader</th>
</tr>
</thead>
<tbody>
<tr>
<td>2.139</td>
<td>0.065</td>
<td>0.048</td>
<td>0.019</td>
<td>2.44</td>
<td>0.397</td>
</tr>
<tr>
<td>2.147</td>
<td>0.081</td>
<td>0.068</td>
<td>0.024</td>
<td>2.38</td>
<td>0.483</td>
</tr>
<tr>
<td>2.152</td>
<td>0.062</td>
<td>0.065</td>
<td>0.035</td>
<td>2.67</td>
<td>0.372</td>
</tr>
<tr>
<td>2.17</td>
<td>0.053</td>
<td>0.047</td>
<td>0.031</td>
<td>2.71</td>
<td>0.377</td>
</tr>
<tr>
<td>2.181</td>
<td>0.052</td>
<td>0.069</td>
<td>0.031</td>
<td>2.38</td>
<td>0.364</td>
</tr>
<tr>
<td>2.14</td>
<td>0.076</td>
<td>0.043</td>
<td>0.017</td>
<td>2.53</td>
<td>0.346</td>
</tr>
<tr>
<td>2.321</td>
<td>0.073</td>
<td>0.045</td>
<td>0.018</td>
<td>2.60</td>
<td>0.451</td>
</tr>
<tr>
<td>2.13</td>
<td>0.061</td>
<td>0.06</td>
<td>0.015</td>
<td>2.35</td>
<td>0.369</td>
</tr>
<tr>
<td>2.149</td>
<td>0.064</td>
<td>0.04</td>
<td>0.015</td>
<td>2.65</td>
<td>0.368</td>
</tr>
<tr>
<td>2.361</td>
<td>0.065</td>
<td>0.045</td>
<td>0.016</td>
<td>2.54</td>
<td>0.424</td>
</tr>
<tr>
<td>2.190</td>
<td>0.065</td>
<td>0.053</td>
<td>0.022</td>
<td>2.525</td>
<td>0.395</td>
</tr>
</tbody>
</table>

<p><em>Note that the results of the Cache strategy are coming just after caching the data set. The first query is ignored as caching is missed.</em></p>
<p>These results were generated from the following environment:</p>
<ul>
<li>Seeded data: 1000 posts and 50 comments for every post.</li>
<li>CPU: AMD Ryzen 5 3600 6-Core Processor 3.60 GHz.</li>
<li>RAM: 32.0 GB.</li>
<li>OS: Windows 10 Pro.</li>
</ul>
<p>To be able to retest these strategies in your environment, follow these steps:</p>
<ul>
<li>Clone this <a target="_blank" href="https://github.com/Mohamed-Mayallo/n_plus_one_problem_benchmarks">repo</a>.</li>
<li>Then run <code>docker-compose up</code>.</li>
<li>For GraphQL, open <code>http://localhost:3000/graphql</code>.</li>
<li><strong>A query suffers from the N+1 problem:</strong> query only <strong><code>commentsWithNPlusOne</code></strong> in the <code>Post</code> type<strong>.</strong></li>
<li><strong>Dataloader strategy</strong>: query only <code>commentsWithDataloader</code> in the <code>Post</code> type.</li>
<li>For REST, follow these endpoints:</li>
<li><strong>A query suffers from the N+1 problem</strong>: <code>http://localhost:3000/api/postsWithNPlusOne</code>.</li>
<li><strong>Eager Loading strategy</strong>: <code>http://localhost:3000/api/postsWithEagerLoading</code>.</li>
<li><strong>Batch Loading strategy</strong>: <code>http://localhost:3000/api/postsWithBatchLoading</code>.</li>
<li><strong>Caching strategy</strong>: <code>http://localhost:3000/api/postsWithCache</code>.</li>
</ul>
<p>My notes about these benchmarks:</p>
<ul>
<li>These strategies are way too efficient.</li>
<li>You may notice that the slower strategy in REST, the Eager Loading strategy, is <strong>about 34 times faster</strong> than the N+1 query in the REST API.</li>
<li>The Dataloader strategy is <strong>about 6.4 times faster</strong> than the N+1 query in the GraphQL API.</li>
<li>If you compared the results of REST and GraphQL APIs, you may notice that REST is faster than GraphQL. I think this is because of the internal implementations of GraphQL, which makes sense.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned that the N+1 query problem is a performance issue you might encounter when working with APIs.</p>
<p>You then learned about some strategies you can follow to avoid this problem like:</p>
<ul>
<li>Eager Loading using SQL Joins</li>
<li>Batch Loading by executing fewer requests and then mapping each corresponding item to its parent.</li>
<li>Caching using Redis</li>
<li>Dataloader in the GraphQL world.</li>
</ul>
<p>Finally, we created some benchmarks about the N+1 query problem so we could see how efficiently these strategies improve our API performance.</p>
<h2 id="heading-before-you-leave">Before you leave</h2>
<p>If you found this article useful, you can <a target="_blank" href="https://mayallo.com/blog/">check out some of my other articles on my personal blog as well</a>.</p>
<p>Thanks a lot for staying with me up till this point. I hope you enjoy reading this article.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ GraphQL Tutorial – How to Query The Rick and Morty API ]]>
                </title>
                <description>
                    <![CDATA[ I enjoy fictional books about greek gods, demigods, the oracle, and prophecies.  I am a huge fan of Rick Riordan's books. I recently came across Apollo's Trials, based on the greek god Apollo.  When I hear any mention of Apollo, my mind goes to the g... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/graphql-queries-for-everyone/</link>
                <guid isPermaLink="false">66ba554e256e9dbeab31aa96</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Velda Kiara ]]>
                </dc:creator>
                <pubDate>Tue, 30 May 2023 18:07:33 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/cover-image--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I enjoy fictional books about greek gods, demigods, the oracle, and prophecies. </p>
<p>I am a huge fan of Rick Riordan's books. I recently came across Apollo's Trials, based on the greek god Apollo. </p>
<p>When I hear any mention of Apollo, my mind goes to the greek god who was the god of practically everything – including but not limited to music, poetry, art, prophecy, truth, archery, plague, healing, sun, and light.</p>
<p><a target="_blank" href="https://www.apollo%5BGraphQL%5D(https://graphql.org/).com/tutorials/">Apollo client</a>, just like the god Apollo, can do many things. For example, it lets you fetch and manage data from a <a target="_blank" href="https://graphql.org/">GraphQL</a> API on your client-side application. It is also simple, flexible, and compatible with any data source.</p>
<p>In this article, we will use the Apollo client to fetch data from the <a target="_blank" href="https://rickandmortyapi.com/%5BGraphQL%5D(https://graphql.org/)">Rick and  Morty API</a>, named after the animated TV show with the same name. We will write a <a target="_blank" href="https://www.freecodecamp.org/news/5-ways-to-fetch-data-React-GraphQL/">GraphQL query</a> to fetch the data we need. The data will then be displayed using React.</p>
<p>Before we get started with the project, let's go over the use cases of GraphQL, and how it differs to REST APIs.</p>
<h2 id="heading-what-are-the-use-cases-of-graphql">What Are The Use Cases of GraphQL?</h2>
<p>GraphQL is used to build applications that require real-time data synchronization, like chat applications. It allows developers to fetch necessary data, reducing data transfer over the network, and improving application performance.</p>
<p>Microservices handle specific functionality or feature of the application, which poses a challenge to developers to work with multiple APIs individually. </p>
<p>GraphQL allows developers to create a single API that acts as a gateway to numerous microservices. It also improves performance since one query retrieves various microservices in a single request.</p>
<p>GraphQL provides a self-documenting schema, making it easy for developers to understand the data model and relationships between data. It also eases the process of creating, testing, and maintaining API, reducing time and cost.</p>
<p>Finally, GraphQL provides versioning capabilities to allow the evolution of the API schema without breaking existing clients. Versioning is possible since clients specify the exact data they need, making it easy to add new fields and remove depreciated ones without affecting existing clients.</p>
<h2 id="heading-what-are-the-differences-between-graphql-and-rest-apis">What Are The Differences Between GraphQL and REST APIs?</h2>
<p>With GraphQL, the client sends a query with the data it needs, and the server responds with that data alone. On the other hand, with <a target="_blank" href="https://www.freecodecamp.org/news/build-consume-and-document-a-rest-api/">REST APIs</a>, the client sends a request to an endpoint, and the server responds with all the data/response related to the endpoint.</p>
<p>REST APIs are resource-based, where the endpoints represent data that can be accessed, created, updated, or deleted. On the other hand, GraphQL is graph-based, where each node represents a relationship between objects.</p>
<p>REST APIs, return data in a JSON (JavaScript Object Notation) or XML (Extensible Markup Language) format. At the same time, GraphQL allows the client to specify the data they need and responds with a JSON object matching the query.</p>
<p>GraphQL provides versioning to enable the API's evolution without disrupting the existing clients, while REST APIs create new endpoints for each version.</p>
<p>In some cases, REST APIs, can suffer from over-fetching or under-fetching, where the server may send much or little data. GraphQL accounts for this by allowing clients to request the data they need, thus reducing the amount of data transferred over a network.</p>
<h2 id="heading-project-setup">Project Setup</h2>
<p>Now that you are familiar with what you can do with GraphQL, let's start building the project.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Fundamentals on <a target="_blank" href="https://react.dev/">React</a></li>
<li>Know about how <a target="_blank" href="https://www.freecodecamp.org/news/how-apis-work/">APIs work</a> and <a target="_blank" href="https://www.freecodecamp.org/news/learn-css-in-this-free-6-hour-video-course/">CSS (Cascading Style Sheets)</a></li>
</ul>
<h3 id="heading-dependencies-installation">Dependencies Installation</h3>
<p>Create a new React App named "rickandmorty".</p>
<pre><code class="lang-js"> npm init [React](https:<span class="hljs-comment">//react.dev/)-app rickandmorty</span>
</code></pre>
<p>or</p>
<pre><code class="lang-js">npx create-[React](https:<span class="hljs-comment">//react.dev/)-app rickandmorty</span>
</code></pre>
<p>Install Apollo Client and GraphQL. The code below installs two dependencies:</p>
<ol>
<li>@apollo/client contains everything you need, like an in-memory cache, local state management, error handling, and a React-based view layer.</li>
<li>GraphQL provides logic for parsing the queries.</li>
</ol>
<pre><code class="lang-js">npm install @apollo/client [GraphQL](https:<span class="hljs-comment">//graphql.org/)</span>
</code></pre>
<h3 id="heading-rick-amp-morty-api-and-apollo-client-setup">Rick &amp; Morty API and Apollo Client Setup</h3>
<p>Once the project is setup, we need to start using it in our files. Next, navigate to  your <code>index.js</code> file using the <code>cd</code> command, and add the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> [React](https:<span class="hljs-comment">//react.dev/)DOM from '[React](https://react.dev/)-dom/client';</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>;
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>;
<span class="hljs-keyword">import</span> reportWebVitals <span class="hljs-keyword">from</span> <span class="hljs-string">'./reportWebVitals'</span>;
<span class="hljs-keyword">import</span> { ApolloClient, InMemoryCache, ApolloProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>;

<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApolloClient({
  <span class="hljs-attr">uri</span>: <span class="hljs-string">'https://rickandmortyapi.com/[GraphQL](https://graphql.org/)'</span>,
  <span class="hljs-attr">cache</span>: <span class="hljs-keyword">new</span> InMemoryCache(),
});

<span class="hljs-keyword">const</span> root = [React](https:<span class="hljs-comment">//react.dev/)DOM.createRoot(document.getElementById('root'));</span>
root.render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ApolloProvider</span> <span class="hljs-attr">client</span>=<span class="hljs-string">{client}</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">ApolloProvider</span>&gt;</span></span>,
);
</code></pre>
<p>The code above creates an instance of the Apollo client with the URL (Uniform Resource Locator) of the Rick and Morty API GraphQL endpoint. </p>
<p>The App component is wrapped with the Apollo provider component to pass the client to all child components.</p>
<h3 id="heading-query-implementation">Query Implementation</h3>
<p>Now, create a file called <code>characters.js</code> inside the <code>src</code> folder. The file will contain the query and any other functions that you want to add.</p>
<p>Inside the file, add the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> GET_CHARACTERS = gql<span class="hljs-string">`
query Characters{
    characters{
      results {
        name
        species
        status
        type
        gender
        origin{name}
        location {name}
        image
      },
    },
  }
`</span>;
</code></pre>
<p>In the code above, we import <code>gql</code> from the <code>@apollo/client</code> to define our query.</p>
<p>We create and export the variable <code>GET_CHARACTERS</code> as a string with capitalized letters. Capitalization is considered a best practice when defining queries in GraphQL. It is also considered a best practice to wrap strings with a template literal.</p>
<p>Objects in Javascript are collections or containers filled with key-value pairs. A key-value pair is referred to as a property.</p>
<p>The query, in our case, searches for the characters in Rick and Morty. It returns an object with the <code>results</code> property, which is an array of character objects. </p>
<p>Each character has properties like name, species, status, type, gender, and image- you can choose what you want to fetch 😉. </p>
<p>The other properties, origin and location, are objects with a name property for each character’s origin and location.</p>
<h4 id="heading-character-function-definition">Character Function Definition</h4>
<p>In the <code>character.js</code> file, add the following code below the <code>GET_CHARACTERS</code> query after modifying it as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { useQuery, gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>;
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"[React](https://react.dev/)"</span>;
<span class="hljs-keyword">import</span>  { RandomCharacter } <span class="hljs-keyword">from</span> <span class="hljs-string">'./randomcharacters'</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> GET_CHARACTERS = gql<span class="hljs-string">`
query Characters($name: String){
    characters ( filter: {name: $name}){
      results {
        name
        species
        status
        type
        gender
        origin{name}
        location {name}
        image
      },
    },
  }
`</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">CharacterList</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> [searchTerm, setSearchTerm] = useState(<span class="hljs-string">""</span>);
  <span class="hljs-keyword">const</span> {loading, error, data }   = useQuery(GET_CHARACTERS, {<span class="hljs-attr">variables</span>: {<span class="hljs-attr">name</span>: searchTerm}});
  <span class="hljs-keyword">const</span> handleChange = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
    setSearchTerm(event.target.value);
  };
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"search"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"search for Rick and Morty characters..."</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{searchTerm}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{handleChange}</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"search-input"</span>  /&gt;</span> 
      {loading &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"loader-container"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"loader"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
       )}
      {error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> error <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> }
      {data?.characters.results.length === 0 &amp;&amp; (<span class="hljs-tag">&lt;&gt;</span>   <span class="hljs-tag">&lt;<span class="hljs-name">RandomCharacter</span>/&gt;</span> <span class="hljs-tag">&lt;/&gt;</span></span>)}
      {data &amp;&amp; data.characters.results.map(<span class="hljs-function">(<span class="hljs-params">character</span>) =&gt;</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{character.name}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">backgroundImage:</span> `<span class="hljs-attr">url</span>(${<span class="hljs-attr">character.image</span>})`,<span class="hljs-attr">backgroundRepeat:</span> '<span class="hljs-attr">no-repeat</span>'}}&gt;</span> 
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"info"</span>&gt;</span> 
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"h3"</span>&gt;</span> {character.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Status: {character.status}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Species: {character.species} <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Type: {character.type}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Gender: {character.gender}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Origin: {character.origin.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Location: {character.location.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> 
      ))}
    &lt;/div&gt; 
  );
}
</code></pre>
<p>The <code>export function CharacterList()</code> creates a function that is also exported to and can be used by other parts of the code. </p>
<p>The <code>searchTerm</code> variable initializes the search state  to an empty string and creates a function <code>setSearchTerm</code> to update the value. </p>
<p>The <code>useQuery</code> hook from <code>@apollo/client</code> library fetches data from the API. </p>
<p>The query passes <code>GET_CHARACTERS</code>  and a variable named <code>searchTerm</code> which is a variable to hold the character names being searched. </p>
<p>The <code>handleChange</code>   variable sets <code>searchTerm</code> 's value to the input field's current value. The <code>input</code> field is the search bar that the user will use to search the names of the characters they want to view. The state is handled by <code>handleChange</code>.</p>
<p>We also need to account for issues with loading the site, as well as for any bugs that may occur. </p>
<p><code>loading</code> is dynamically rendered with a spinner  if loading is set to <code>True</code>. An error message is displayed if the error is set to <code>True</code>. </p>
<p>When the user is searching for a character that doesn't exist, we want to present a message and an alternate character they can find more information about – this is where the <code>RandomCharacter</code> comes in. We will define this later on. For now, let's keep it as is.</p>
<p>Once we  fetch the data, we map the <code>data.characters.results</code> array to each character's card. </p>
<p>We also want to change the background of the cards to represent the character the information is for. The <code>backgroundImage</code> in the <code>style</code> property handles the dynamic change of the images. The rest of the items are displayed as text on the card.</p>
<h3 id="heading-how-to-display-data">How To Display Data</h3>
<p>Now that we have a function working, we need to view what is being displayed in the browser, and whether we can make queries and get the data we need. </p>
<p>In your <code>App.js</code> file, add the following code:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">textAlign:</span> '<span class="hljs-attr">center</span>' }} &gt;</span>Rick and Morty Characters<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">CharacterList</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      );
    }
</code></pre><p><code>&lt;CharacterList /&gt;</code> component displays the information about the characters we are getting from the API.</p>
<h3 id="heading-how-to-randomize-the-characters">How to Randomize The Characters</h3>
<p>Remember that we called the <code>RandomCharacter</code> component but we have yet to define it. </p>
<p>Create a file called <code>randomcharacters.js</code> in <code>src</code> and add the following code:</p>
<pre><code><span class="hljs-keyword">import</span> { useQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">"@apollo/client"</span>;
<span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>;
<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"[React](https://react.dev/)"</span>;
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> GET_SINGLE_CHARACTER = gql<span class="hljs-string">`
query Character($id: ID!){
    character   (id: $id) {
        name
        species
        status
        type
        gender
        origin{name}
        location {name}
        image
      },
    },
`</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> RandomCharacter = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> [randomNumber, setRandomNumber] = useState(<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">200</span>));
    <span class="hljs-keyword">const</span> { loading, error, data } = useQuery(GET_SINGLE_CHARACTER, {<span class="hljs-attr">variables</span>: {<span class="hljs-attr">id</span>: randomNumber } });


  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"intro"</span> &gt;</span>
         Sorry, we couldn't find that character 😞  
         <span class="hljs-tag">&lt;<span class="hljs-name">br</span>/&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">br</span>/&gt;</span>
         How about this one instead? 😉 <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

      {/* {loading &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>} */}
      {loading &amp;&amp; (
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"loader-container"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"loader"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
       )}
      {error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> error <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span> }
      {data &amp;&amp; (<span class="hljs-tag">&lt;&gt;</span> 
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{data.character.name}</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">backgroundImage:</span> `<span class="hljs-attr">url</span>(${<span class="hljs-attr">data.character.image</span>})`,<span class="hljs-attr">backgroundRepeat:</span> '<span class="hljs-attr">no-repeat</span>'}}&gt;</span> 
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"info"</span>&gt;</span> 
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"h3"</span>&gt;</span>{data.character.name}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Status: {data.character.status}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Species: {data.character.species}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Type: {data.character.type}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Gender: {data.character.gender}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Origin: {data.character.origin.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Location: {data.character.location.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/&gt;</span></span>
      )}
    &lt;/div&gt;
  );
};
</code></pre><p>We will replicate the query we created in the <code>characters.js</code> file,  and rename it to <code>GET_SINGLE_CHARACTER</code>.  Instead of looking for names, we will look for <code>ID</code>s. </p>
<p>We look for <code>ID</code>s because they are unique, and we want to randomize the characters that will be picked once a user does not get the character they are looking for.</p>
<p><code>randomNumber</code> initializes state to the <code>Math.floor</code> function which generates a random number between 0 and 199 inclusive, using the <code>Math.random()</code> method and multiplying it by 200. </p>
<p>The <code>Math.floor</code> function rounds the result of the expression to the nearest integer. Every time the <code>randomNumber</code> needs to be updated the  <code>setRandomNumber</code> function takes a new value as its argument and updates the state.</p>
<p>We have a message to alert the user that the character they are looking for is not found, but they can check out a new character. </p>
<p>The loading spinner is also implemented in this component, and the errors are there in case any issues occur. The images and cards are similar to the <code>characters.js</code> format since we want consistency with how everything looks.</p>
<h3 id="heading-how-to-style-the-display">How to Style the Display</h3>
<p>We will use CSS to style how the cards will look, along with the search bar and the general page.</p>
<p>Having defined the functions and components, we will be adding <code>className</code> attributes to what needs to be styled.</p>
<p>Add the following code:</p>
<pre><code class="lang-js">@<span class="hljs-keyword">import</span> url(https:<span class="hljs-comment">//fonts.googleapis.com/css?family=Roboto:400,500,700);</span>
body{
  <span class="hljs-attr">background</span>: navajowhite;
  font-family: Roboto, veranda;
  padding-bottom: <span class="hljs-number">4</span>em;
}
.card{
  <span class="hljs-attr">position</span>: relative;
  width: <span class="hljs-number">22</span>em;
  height: <span class="hljs-number">30</span>em;
  background-size: <span class="hljs-number">22</span>em <span class="hljs-number">30</span>em;
  box-shadow: <span class="hljs-number">3</span>px <span class="hljs-number">3</span>px <span class="hljs-number">20</span>px rgba(<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0.5</span>);
  margin: auto;
  overflow: hidden;
  margin-bottom: <span class="hljs-number">2</span>em;
}
.card *{
  <span class="hljs-attr">position</span>: relative;
  z-index: <span class="hljs-number">2</span>;
}
.card:hover .info{
  <span class="hljs-attr">bottom</span>: <span class="hljs-number">-3</span>em;
  opacity: <span class="hljs-number">1</span>;
  padding: <span class="hljs-number">2</span>px <span class="hljs-number">1</span>px;
  background-color: navajowhite;
}
.info{
  font-family: <span class="hljs-string">'Droid Serif'</span>, serif;
  font-size: <span class="hljs-number">1.2</span>em;
  color: black;

  line-height: <span class="hljs-number">1.1</span>em;
  padding: <span class="hljs-number">0</span> <span class="hljs-number">2</span>em;
  position: relative;
  bottom: <span class="hljs-number">-4</span>em;
  opacity: <span class="hljs-number">0</span>;
  background: transparent;
  transition: opacity <span class="hljs-number">0.3</span>s, bottom <span class="hljs-number">0.3</span>s;
  text-align: center;
}
<span class="hljs-comment">/* search  bar*/</span>
input[type=<span class="hljs-string">"text"</span>] {
  <span class="hljs-attr">border</span>: none;
  border-radius: <span class="hljs-number">10</span>px;
  background-color: #f2f2f2;
  padding: <span class="hljs-number">10</span>px;
  width: <span class="hljs-number">500</span>px;
  margin: <span class="hljs-number">0</span> auto;
  display: block;
  font-size: <span class="hljs-number">16</span>px;
  font-family: <span class="hljs-string">'Roboto'</span>, sans-serif;
  box-shadow: <span class="hljs-number">2</span>px <span class="hljs-number">2</span>px <span class="hljs-number">5</span>px rgba(<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0.2</span>);
  margin-bottom: <span class="hljs-number">2</span>em;
}

input[type=<span class="hljs-string">"text"</span>]::placeholder {
  <span class="hljs-attr">color</span>: #<span class="hljs-number">999</span>;
  font-style: italic;
}
<span class="hljs-comment">/* no result */</span>
.intro{
<span class="hljs-comment">/* width: 10px; */</span>
text-align: center;
margin: <span class="hljs-number">0</span> auto;
color:black;
font-family: <span class="hljs-string">'Droid Serif'</span>, serif;
font-size: <span class="hljs-number">23</span>px;
font-style: italic;
line-height: <span class="hljs-number">20</span>px;
padding-bottom: <span class="hljs-number">15</span>px;
}
<span class="hljs-comment">/* spinner */</span>
.loader-container {
  <span class="hljs-attr">display</span>: flex;
  justify-content: center;
  align-items: center;
  height: <span class="hljs-number">100</span>px;
}

.loader {
  <span class="hljs-attr">border</span>: <span class="hljs-number">8</span>px solid #f3f3f3; 
  border-top: <span class="hljs-number">8</span>px solid black;
  border-radius: <span class="hljs-number">50</span>%;
  width: <span class="hljs-number">50</span>px;
  height: <span class="hljs-number">50</span>px;
  animation: spin <span class="hljs-number">1</span>s linear infinite;
}

@keyframes spin {
  <span class="hljs-number">0</span>% { <span class="hljs-attr">transform</span>: rotate(<span class="hljs-number">0</span>deg); }
  <span class="hljs-number">100</span>% { <span class="hljs-attr">transform</span>: rotate(<span class="hljs-number">360</span>deg); }
}
</code></pre>
<p>Things to note:</p>
<ul>
<li>The class <code>.card</code> represents what the card will look like.</li>
<li>The class <code>.info</code> represents the body text for the characters, such as the species.</li>
<li>The class <code>.intro</code> represents the text that appears if the character is not found.</li>
<li>The class <code>.loader</code> represents the spinner  that shows before the results are displayed.</li>
</ul>
<p>Your website should now look like <a target="_blank" href="https://graphymorty.netlify.app/">this</a>.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, you learned how to use GraphQL queries with React, manage state using the useState hook, and style the different components of the web application.</p>
<p>May your keyboard be swift, your bugs be few, and your fun meter be off the charts as you code away!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The GraphQL API Handbook – How to Build, Test, Consume and Document GraphQL APIs ]]>
                </title>
                <description>
                    <![CDATA[ Hi everyone! In this tutorial we're going to take a deep dive into GraphQL APIs. I recently wrote this article where I explained the main differences between common API types nowadays. And this tutorial aims to show you an example of how you can full... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/building-consuming-and-documenting-a-graphql-api/</link>
                <guid isPermaLink="false">66d45ef1230dff0166905805</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ German Cocca ]]>
                </dc:creator>
                <pubDate>Tue, 02 May 2023 13:23:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/jj-ying-8bghKxNU1j0-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi everyone! In this tutorial we're going to take a deep dive into GraphQL APIs.</p>
<p>I recently wrote <a target="_blank" href="https://www.freecodecamp.org/news/rest-vs-graphql-apis/">this article</a> where I explained the main differences between common API types nowadays. And this tutorial aims to show you an example of how you can fully implement a GraphQL API.</p>
<p>We'll cover basic setup and architecture with Node and Apollo GraphQL, unit testing with Supertest, seeing how we can consume the API from a React front-end app using Apollo client and finally documenting the API using Apollo sandbox.</p>
<p>Keep in mind we won't go too deep into how each technology works. The goal here is to give you a general overview of how a GraphQL API works, how its pieces interact, and what a full implementation might consist of.</p>
<p>Let's go!</p>
<h1 id="heading-table-of-contents"><strong>Table of Contents</strong></h1>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-graphql">What is GraphQL?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-core-graphql-concepts">Core GraphQL concepts</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-object-types">Object Types</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-queries">Queries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-mutations">Mutations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-resolvers">Resolvers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-schemas">Schemas</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tldr-and-comparison-with-equivalent-rest-concepts">TLDR and comparison with equivalent REST concepts</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-a-graphql-api-with-node-and-apollo-graphql">How to Build a GraphQL API with Node and Apollo GraphQL</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-a-graphql-api-with-supertest">How to Test a GraphQL API with Supertest</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-consume-a-graphql-api-on-a-front-end-react-app">How to Consume a GraphQL API on a Front-end React App</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-document-a-graphql-api-with-apollo-sandbox">How to Document a GraphQL API with Apollo sandbox</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping up</a></p>
</li>
</ul>
<h1 id="heading-what-is-graphql">What is GraphQL?</h1>
<p><a target="_blank" href="https://graphql.org/">GraphQL</a> is a query language and runtime for APIs that was developed by Facebook in 2012. It was released to the public in 2015 and has since gained popularity as an alternative to REST APIs.</p>
<p>GraphQL was originally developed by Facebook as a way to simplify data fetching for their mobile applications. They needed a way to make complex data requests from the server without causing performance issues or over-fetching data. GraphQL was born out of the need to solve these problems.</p>
<p>GraphQL was released as an open-source project in 2015 and has since gained popularity in the developer community. It is now supported by many development tools and frameworks, including Apollo, Prisma, and Hasura.</p>
<p><strong>Main Characteristics:</strong></p>
<ol>
<li><p><strong>Strongly Typed:</strong> GraphQL APIs are strongly typed, which means that each field has a specific data type. This makes it easier to validate and handle data on the client and server sides.</p>
</li>
<li><p><strong>Query Language:</strong> GraphQL has its own query language that allows clients to specify exactly what data they need. This reduces over-fetching of data and improves performance.</p>
</li>
<li><p><strong>Single Endpoint:</strong> GraphQL APIs have a single endpoint, which means that clients can fetch all the data they need from a single request.</p>
</li>
<li><p><strong>Declarative:</strong> GraphQL APIs are declarative, which means that clients specify what they want, not how to get it. This allows for more efficient and flexible data fetching.</p>
</li>
<li><p><strong>Schema-Driven:</strong> GraphQL APIs are schema-driven, which means that the schema defines the structure of the data and the available queries and mutations. This makes it easier for developers to understand and work with the API.</p>
</li>
</ol>
<p><strong>Pros:</strong></p>
<ul>
<li><p><strong>Efficient Data Fetching:</strong> GraphQL APIs allow clients to fetch only the data they need, reducing over-fetching and improving performance.</p>
</li>
<li><p><strong>Strongly Typed:</strong> GraphQL APIs are strongly typed, making it easier to validate and handle data.</p>
</li>
<li><p><strong>Single Endpoint:</strong> GraphQL APIs have a single endpoint, reducing the complexity of the API and making it easier to work with.</p>
</li>
<li><p><strong>Schema-Driven:</strong> GraphQL APIs are schema-driven, which makes it easier for developers to understand and work with the API.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p><strong>Complexity:</strong> GraphQL APIs can be more complex to set up and work with compared to REST APIs.</p>
</li>
<li><p><strong>Caching:</strong> Caching can be more challenging with GraphQL APIs due to the flexible nature of the API.</p>
</li>
<li><p><strong>Learning Curve:</strong> GraphQL requires a learning curve for both developers and clients, as it has its own query language and approach to data fetching.</p>
</li>
</ul>
<p><strong>Best for:</strong></p>
<ul>
<li><p><strong>Efficient and flexible needs:</strong> GraphQL is well-suited for building applications that require efficient and flexible data fetching, such as mobile and web applications.</p>
</li>
<li><p><strong>Complex data requirements:</strong> It is particularly useful in situations where there are complex data requirements and where over-fetching data can cause performance issues.</p>
</li>
</ul>
<p>So to recap, GraphQL is a query language and runtime for APIs that provides efficient and flexible data fetching capabilities.</p>
<p>While it can be more complex to set up and work with compared to REST APIs, it offers benefits such as strongly typed data, single endpoints, and schema-driven development. It is well-suited for building applications with complex data requirements and where efficient data fetching is important.</p>
<h1 id="heading-core-graphql-concepts">Core GraphQL Concepts</h1>
<p>Before we jump into building stuff, there are some core GraphQL concepts you need to understand in order to know what you're doing and how the code will work.</p>
<h2 id="heading-object-types">Object Types</h2>
<p>In GraphQL, an Object Type is a complex type that represents a collection of fields. <strong>Object Types are used to define the structure of data that can be queried and mutated</strong> through a GraphQL API.</p>
<p>Each Object Type has a unique name and a set of fields, where each field has a name and a type. The type of a field can be a scalar type (such as Int, String, or Boolean), another Object Type, or a list of another type.</p>
<p>If you're familiar with <a target="_blank" href="https://www.freecodecamp.org/news/an-introduction-to-typescript/#interfaces">Typescript and interfaces</a>, this might ring a bell or two for you.</p>
<p>Here's an example of an Object Type that represents a "User" in a social media application:</p>
<pre><code class="lang-yaml"><span class="hljs-string">type</span> <span class="hljs-string">User</span> {
  <span class="hljs-attr">id:</span> <span class="hljs-string">ID!</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">email:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">friends:</span> [<span class="hljs-string">User!</span>]<span class="hljs-string">!</span>
}
</code></pre>
<p>The <code>!</code> sign means the field is mandatory.</p>
<p>In this example, the "User" Object Type has four fields: "id", "name", "email", and "friends". The "id" field has a type of ID, which is a built-in scalar type in GraphQL that represents a unique identifier. The "name" and "email" fields have a type of String, and the "friends" field has a type of a list of "User" Objects.</p>
<p>Here's another example of an Object Type that represents a "Book" in a library application:</p>
<pre><code class="lang-yaml"><span class="hljs-string">type</span> <span class="hljs-string">Book</span> {
  <span class="hljs-attr">id:</span> <span class="hljs-string">ID!</span>
  <span class="hljs-attr">title:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">author:</span> <span class="hljs-string">Author!</span>
  <span class="hljs-attr">genre:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">published:</span> <span class="hljs-string">Int!</span>
}
</code></pre>
<p>In this example, the "Book" Object Type has five fields: "id", "title", "author", "genre", and "published". The "id" field has a type of ID, the "title" and "genre" fields have a type of String, the "published" field has a type of Int, and the "author" field has a type of an "Author" Object.</p>
<p>Object Types can be used to define the structure of data that is returned from a query or mutation in a GraphQL API. For example, a query that returns a list of users might look like this:</p>
<pre><code class="lang-yaml"><span class="hljs-string">query</span> {
  <span class="hljs-string">users</span> {
    <span class="hljs-string">id</span>
    <span class="hljs-string">name</span>
    <span class="hljs-string">email</span>
    <span class="hljs-string">friends</span> {
      <span class="hljs-string">id</span>
      <span class="hljs-string">name</span>
    }
  }
}
</code></pre>
<p>In this query, the "users" field returns a list of "User" Objects, and the query specifies which fields to include in the response.</p>
<h2 id="heading-queries">Queries</h2>
<p>In GraphQL, <strong>a query is a request for specific data from the server</strong>. The query specifies the shape of the data that the client wants to receive, and the server responds with the requested data in the same shape.</p>
<p>A query in GraphQL follows a similar structure to the shape of the data it expects to receive. It consists of a set of fields that correspond to the properties of the data the client wants to retrieve. Each field can also have arguments that modify the data returned.</p>
<p>Here's an example of a simple query in GraphQL:</p>
<pre><code class="lang-yaml"><span class="hljs-string">query</span> {
  <span class="hljs-string">user(id:</span> <span class="hljs-string">"1"</span><span class="hljs-string">)</span> {
    <span class="hljs-string">name</span>
    <span class="hljs-string">email</span>
    <span class="hljs-string">age</span>
  }
}
</code></pre>
<p>In this example, the query is requesting information about a user with the ID of "1". The fields specified in the query are "name", "email", and "age", which correspond to the properties of the user object.</p>
<p>The response from the server would be in the same shape as the query, with the requested data returned in the corresponding fields:</p>
<pre><code class="lang-yaml">{
  <span class="hljs-attr">"data":</span> {
    <span class="hljs-attr">"user":</span> {
      <span class="hljs-attr">"name":</span> <span class="hljs-string">"John Doe"</span>,
      <span class="hljs-attr">"email":</span> <span class="hljs-string">"johndoe@example.com"</span>,
      <span class="hljs-attr">"age":</span> <span class="hljs-number">25</span>
    }
  }
}
</code></pre>
<p>Here, the server has returned the requested data about the user in the "name", "email", and "age" fields. The data is contained in a "data" object to differentiate it from any errors or other metadata that may be included in the response.</p>
<h2 id="heading-mutations">Mutations</h2>
<p>In GraphQL, mutations are used to modify or create data on the server. Like queries, mutations specify the shape of the data being sent to and received from the server. The main difference is that while <strong>queries only read data, mutations can both read and write data</strong>.</p>
<p>Here's an example of a simple mutation in GraphQL:</p>
<pre><code class="lang-yaml"><span class="hljs-string">mutation</span> {
  <span class="hljs-string">createUser(name:</span> <span class="hljs-string">"Jane Doe"</span>, <span class="hljs-attr">email:</span> <span class="hljs-string">"janedoe@example.com"</span>, <span class="hljs-attr">age:</span> <span class="hljs-number">30</span><span class="hljs-string">)</span> {
    <span class="hljs-string">id</span>
    <span class="hljs-string">name</span>
    <span class="hljs-string">email</span>
    <span class="hljs-string">age</span>
  }
}
</code></pre>
<p>In this example, the mutation is creating a new user on the server with the name "Jane Doe", email "janedoe@example.com", and age 30. The fields specified in the mutation are "id", "name", "email", and "age", which correspond to the properties of the user object.</p>
<p>The response from the server would be in the same shape as the mutation, with the newly created user data returned in the corresponding fields:</p>
<pre><code class="lang-yaml">{
  <span class="hljs-attr">"data":</span> {
    <span class="hljs-attr">"createUser":</span> {
      <span class="hljs-attr">"id":</span> <span class="hljs-string">"123"</span>,
      <span class="hljs-attr">"name":</span> <span class="hljs-string">"Jane Doe"</span>,
      <span class="hljs-attr">"email":</span> <span class="hljs-string">"janedoe@example.com"</span>,
      <span class="hljs-attr">"age":</span> <span class="hljs-number">30</span>
    }
  }
}
</code></pre>
<p>Here, the server has returned the data about the newly created user in the "id", "name", "email", and "age" fields.</p>
<p>Mutations can also be used to update or delete data on the server. Here's an example of a mutation that updates a user's name:</p>
<pre><code class="lang-yaml"><span class="hljs-string">mutation</span> {
  <span class="hljs-string">updateUser(id:</span> <span class="hljs-string">"123"</span>, <span class="hljs-attr">name:</span> <span class="hljs-string">"Jane Smith"</span><span class="hljs-string">)</span> {
    <span class="hljs-string">id</span>
    <span class="hljs-string">name</span>
    <span class="hljs-string">email</span>
    <span class="hljs-string">age</span>
  }
}
</code></pre>
<p>In this example, the mutation is updating the user with the ID of "123" to have the name "Jane Smith". The fields specified in the mutation are the same as in the previous example.</p>
<p>The response from the server would be the updated user data:</p>
<pre><code class="lang-yaml">{
  <span class="hljs-attr">"data":</span> {
    <span class="hljs-attr">"updateUser":</span> {
      <span class="hljs-attr">"id":</span> <span class="hljs-string">"123"</span>,
      <span class="hljs-attr">"name":</span> <span class="hljs-string">"Jane Smith"</span>,
      <span class="hljs-attr">"email":</span> <span class="hljs-string">"janedoe@example.com"</span>,
      <span class="hljs-attr">"age":</span> <span class="hljs-number">30</span>
    }
  }
}
</code></pre>
<p>Mutations in GraphQL are designed to be composable, meaning that multiple mutations can be combined into a single request. This allows clients to perform complex operations with a single network round-trip.</p>
<h2 id="heading-resolvers">Resolvers</h2>
<p>In GraphQL, a resolver is a function responsible for fetching the data for a specific field defined in a GraphQL schema. Resolvers are the bridge between the schema and the data source. The resolver function receives four parameters: parent, args, context, and info.</p>
<ul>
<li><p><code>parent</code>: The parent object for the current field. In nested queries, it refers to the parent field's value.</p>
</li>
<li><p><code>args</code>: The arguments passed to the current field. It is an object with key-value pairs of the argument names and their values.</p>
</li>
<li><p><code>context</code>: An object shared across all resolvers for a particular request. It contains information about the request such as the currently authenticated user, database connection, etc.</p>
</li>
<li><p><code>info</code>: Contains information about the query including the field name, alias, and the query document AST.</p>
</li>
</ul>
<p>Here's an example of a resolver function for a <code>User</code> type's <code>posts</code> field:</p>
<pre><code class="lang-yaml"><span class="hljs-string">const</span> <span class="hljs-string">resolvers</span> <span class="hljs-string">=</span> {
  <span class="hljs-attr">User:</span> {
    <span class="hljs-attr">posts:</span> <span class="hljs-string">(parent</span>, <span class="hljs-string">args</span>, <span class="hljs-string">context</span>, <span class="hljs-string">info)</span> <span class="hljs-string">=&gt;</span> {
      <span class="hljs-string">return</span> <span class="hljs-string">getPostsByUserId(parent.id);</span>
    },
  },
}<span class="hljs-string">;</span>
</code></pre>
<p>In this example, <code>User</code> is a GraphQL object type with a <code>posts</code> field. When the <code>posts</code> field is queried, the resolver function is called with the parent object <code>User</code>, any arguments passed, the context object, and query information. In this example, the resolver function calls a function <code>getPostsByUserId</code> to fetch the posts for the current user.</p>
<p>Resolvers can also be used for mutations to create, update or delete data. Here's an example of a resolver function for a <code>createUser</code> mutation:</p>
<pre><code class="lang-yaml"><span class="hljs-string">const</span> <span class="hljs-string">resolvers</span> <span class="hljs-string">=</span> {
  <span class="hljs-attr">Mutation:</span> {
    <span class="hljs-attr">createUser:</span> <span class="hljs-string">(parent</span>, <span class="hljs-string">args</span>, <span class="hljs-string">context</span>, <span class="hljs-string">info)</span> <span class="hljs-string">=&gt;</span> {
      <span class="hljs-string">const</span> <span class="hljs-string">user</span> <span class="hljs-string">=</span> { <span class="hljs-attr">name:</span> <span class="hljs-string">args.name</span>, <span class="hljs-attr">email:</span> <span class="hljs-string">args.email</span> }<span class="hljs-string">;</span>
      <span class="hljs-string">const</span> <span class="hljs-string">createdUser</span> <span class="hljs-string">=</span> <span class="hljs-string">createUser(user);</span>
      <span class="hljs-string">return</span> <span class="hljs-string">createdUser;</span>
    },
  },
}<span class="hljs-string">;</span>
</code></pre>
<p>In this example, <code>Mutation</code> is a GraphQL object type with a <code>createUser</code> mutation field. When the mutation is invoked, the resolver function is called with the parent object, arguments passed, context object, and query information. In this example, the resolver function calls a function <code>createUser</code> to create a new user with the given name and email, and returns the newly created user.</p>
<h2 id="heading-schemas">Schemas</h2>
<p>In GraphQL, a schema is a blueprint that defines the structure of the data that can be queried in the API. It defines the available types, fields, and operations that can be performed on those types.</p>
<p>GraphQL schemas are written in the GraphQL Schema Definition Language (SDL), which uses a simple syntax to define the types and fields available in the API. The schema is typically defined in the server-side code and then used to validate and execute incoming queries.</p>
<p>Here's an example of a simple GraphQL schema definition:</p>
<pre><code class="lang-yaml"><span class="hljs-string">type</span> <span class="hljs-string">Book</span> {
  <span class="hljs-attr">id:</span> <span class="hljs-string">ID!</span>
  <span class="hljs-attr">title:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">author:</span> <span class="hljs-string">String!</span>
  <span class="hljs-attr">published:</span> <span class="hljs-string">Int!</span>
}

<span class="hljs-string">type</span> <span class="hljs-string">Query</span> {
  <span class="hljs-attr">books:</span> [<span class="hljs-string">Book!</span>]<span class="hljs-string">!</span>
  <span class="hljs-string">book(id:</span> <span class="hljs-string">ID!):</span> <span class="hljs-string">Book</span>
}

<span class="hljs-string">type</span> <span class="hljs-string">Mutation</span> {
  <span class="hljs-string">addBook(title:</span> <span class="hljs-string">String!</span>, <span class="hljs-attr">author:</span> <span class="hljs-string">String!</span>, <span class="hljs-attr">published:</span> <span class="hljs-string">Int!):</span> <span class="hljs-string">Book!</span>
  <span class="hljs-string">updateBook(id:</span> <span class="hljs-string">ID!</span>, <span class="hljs-attr">title:</span> <span class="hljs-string">String</span>, <span class="hljs-attr">author:</span> <span class="hljs-string">String</span>, <span class="hljs-attr">published:</span> <span class="hljs-string">Int):</span> <span class="hljs-string">Book</span>
  <span class="hljs-string">deleteBook(id:</span> <span class="hljs-string">ID!):</span> <span class="hljs-string">Book</span>
}
</code></pre>
<p>In this schema, we have three types: <code>Book</code>, <code>Query</code>, and <code>Mutation</code>. The <code>Book</code> type has four fields: <code>id</code>, <code>title</code>, <code>author</code>, and <code>published</code>. The <code>Query</code> type has two fields: <code>books</code> and <code>book</code>, which can be used to retrieve a list of books or a specific book by ID, respectively. The <code>Mutation</code> type has three fields: <code>addBook</code>, <code>updateBook</code>, and <code>deleteBook</code>, which can be used to create, update, or delete books.</p>
<p>Note that each field has a type, which can be a built-in scalar type like <code>String</code> or <code>Int</code>, or a custom type like <code>Book</code>. The <code>!</code> after a type indicates that the field is non-nullable, meaning it must always return a value (that is, it cannot be null).</p>
<h2 id="heading-tldr-and-comparison-with-equivalent-rest-concepts">TLDR and Comparison with Equivalent REST Concepts</h2>
<ul>
<li><p><strong>Object Types:</strong> In GraphQL, Object Types are used to define the data that can be queried from an API, similar to how the response data model is defined in REST APIs. However, unlike REST, where data models are often defined in different formats (for example, JSON or XML), GraphQL Object Types are defined using a single language-agnostic syntax.</p>
</li>
<li><p><strong>Queries:</strong> In GraphQL, queries are used to fetch data from an API, similar to HTTP GET requests in REST APIs. However, unlike REST APIs, where multiple requests may be required to fetch nested data, GraphQL queries can be used to fetch nested data in a single request.</p>
</li>
<li><p><strong>Mutations:</strong> In GraphQL, mutations are used to modify data in an API, similar to HTTP POST, PUT, and DELETE requests in REST APIs. However, unlike REST APIs, where different endpoints may be required to perform different modifications, GraphQL mutations are performed through a single endpoint.</p>
</li>
<li><p><strong>Resolvers:</strong> In GraphQL, resolvers are used to specify how to fetch data for a particular field in a query or mutation. Resolvers are similar to controller methods in REST APIs, which are used to fetch data from a database and return it as a response.</p>
</li>
<li><p><strong>Schemas:</strong> In GraphQL, a schema is used to define the data that can be queried or mutated from an API. It specifies the types of data that can be requested, how they can be queried, and what mutations are allowed. In REST APIs, schemas are often defined using OpenAPI or Swagger, which specify the endpoints, request and response types, and other metadata for an API.</p>
</li>
</ul>
<p>Overall, GraphQL and REST APIs differ in how they handle data fetching and modification.</p>
<p>REST APIs rely on multiple endpoints and HTTP methods to fetch and modify data, whereas GraphQL uses a single endpoint and queries/mutations to accomplish the same.</p>
<p>GraphQL's use of a single schema to define the data model of an API makes it easier to understand and maintain compared to REST APIs, which often require multiple documentation formats to describe the same data model.</p>
<h1 id="heading-how-to-build-a-graphql-api-with-node-and-apollo-graphql">How to Build a GraphQL API with Node and Apollo GraphQL</h1>
<h2 id="heading-our-tools">Our Tools</h2>
<p><a target="_blank" href="https://nodejs.org/"><strong>Node.js</strong></a> is an open-source, cross-platform, back-end JavaScript runtime environment that allows developers to execute JavaScript code outside of a web browser. It was created by Ryan Dahl in 2009 and has since become a popular choice for building web applications, APIs, and servers.</p>
<p>Node.js provides an event-driven, non-blocking I/O model that makes it lightweight and efficient, allowing it to handle large amounts of data with high performance. It also has a large and active community, with many libraries and modules available to help developers build their applications more quickly and easily.</p>
<p><a target="_blank" href="https://www.apollographql.com/"><strong>Apollo GraphQL</strong></a> is a full-stack platform for building GraphQL APIs. It provides tools and libraries that simplify the process of building, managing, and consuming GraphQL APIs.</p>
<p>The core of the Apollo GraphQL platform is the Apollo Server, a lightweight and flexible server that makes it easy to build scalable and performant GraphQL APIs. The Apollo Server supports a wide range of data sources, including databases, REST APIs, and other services, making it easy to integrate with existing systems.</p>
<p>Apollo also provides a number of client libraries, including the Apollo Client for web and mobile, which simplifies the process of consuming GraphQL APIs. The Apollo Client makes it easy to query and mutate data, and provides advanced features like caching, optimistic UI, and real-time updates.</p>
<p>In addition to the Apollo Server and Apollo Client, Apollo provides a number of other tools and services, including a schema management platform, a GraphQL analytics service, and a set of developer tools for building and debugging GraphQL APIs.</p>
<p>If you're new to GraphQL or to Apollo itself, I really recommend you <a target="_blank" href="https://www.apollographql.com/docs/">check out their docs</a>. They're some of the best out there in my opinion.</p>
<h2 id="heading-our-architecture">Our Architecture</h2>
<p>For this project we'll follow a layers architecture in our codebase. Layers architecture is about dividing concerns and responsibilities into different folders and files, and allowing direct communication only between certain folders and files.</p>
<p>The matter of how many layers should your project have, what names should each layer have, and what actions should it handle is all a matter of discussion. So let's see what I think is a good approach for our example.</p>
<p>Our application will have five different layers, which will be ordered in this way:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Untitled-Diagram.drawio.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Application layers</em></p>
<ul>
<li><p>The application layer will have the basic setup of our server and the connection to our schema and resolvers (the next layer).</p>
</li>
<li><p>The schema and resolvers layer will have the type definitions for our data and the connection to our queries and mutations (the next layer).</p>
</li>
<li><p>The queries and mutations layer will have the actual logic we want to perform in each of our queries and mutations and the connection to the model layer (the next layer, you get the idea...)</p>
</li>
<li><p>The model layer will hold the logic for interacting with our mock database.</p>
</li>
<li><p>Finally, the persistence layer is where our database will be.</p>
</li>
</ul>
<p>An important thing to keep in mind is that in these kinds of architectures, <strong>there's a defined communication flow</strong> between the layers that has to be followed for it to make sense.</p>
<p>This means that a request first has to go through the first layer, then the second, then the third and so on. No request should skip layers because that would mess with the logic of the architecture and the benefits of organization and modularity it gives us.</p>
<p>If you'd like to know some other API architecture options, I recommend <a target="_blank" href="https://www.freecodecamp.org/news/an-introduction-to-software-architecture-patterns/">this software architecture article</a> I wrote a while ago.</p>
<h2 id="heading-the-code">The Code</h2>
<p>Before jumping to the code, let's mention what we'll actually build. We'll be building an API for a pet shelter business. This pet shelter needs to register the pets that are staying in the shelter, and for that we'll perform basic CRUD operations (create, read, update and delete).</p>
<p>We're using the exact same example we used in <a target="_blank" href="https://www.freecodecamp.org/news/build-consume-and-document-a-rest-api/">my article about fully implementing a REST API.</a> If you're interested in reading that too, this should help to compare concepts between REST and GraphQL, and understand its differences and similarities. ;)</p>
<p>Now let's get this thing going. Create a new directory, hop in to it and start a new Node project by running <code>npm init -y</code>. For our GraphQL server we'll need two more dependencies, so run <code>npm i @apollo/server</code> and <code>npm i graphql</code> too.</p>
<h3 id="heading-appjs">App.js</h3>
<p>In the root of your project, create an <code>app.js</code> file and drop this code in it:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { ApolloServer } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/server'</span>
<span class="hljs-keyword">import</span> { startStandaloneServer } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/server/standalone'</span>
<span class="hljs-keyword">import</span> { typeDefs, resolvers } <span class="hljs-keyword">from</span> <span class="hljs-string">'./pets/index.js'</span>

<span class="hljs-comment">// The ApolloServer constructor requires two parameters: your schema</span>
<span class="hljs-comment">// definition and your set of resolvers.</span>
<span class="hljs-keyword">const</span> server = <span class="hljs-keyword">new</span> ApolloServer({
    typeDefs,
    resolvers
})

<span class="hljs-comment">// Passing an ApolloServer instance to the `startStandaloneServer` function:</span>
<span class="hljs-comment">//  1. creates an Express app</span>
<span class="hljs-comment">//  2. installs your ApolloServer instance as middleware</span>
<span class="hljs-comment">//  3. prepares your app to handle incoming requests</span>
<span class="hljs-keyword">const</span> { url } = <span class="hljs-keyword">await</span> startStandaloneServer(server, {
    <span class="hljs-attr">listen</span>: { <span class="hljs-attr">port</span>: <span class="hljs-number">4000</span> }
})

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`🚀  Server ready at: <span class="hljs-subst">${url}</span>`</span>)
</code></pre>
<p>Here we're setting up our Apollo server, by passing it our typeDefs and resolvers (we'll explain those in a sec), and then starting the server in port 4000.</p>
<p>Next, go ahead and create this folder structure in your project:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Our folder structure</em></p>
<h3 id="heading-indexjs">index.js</h3>
<p>Within the <code>index.js</code> file put this code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { addPet, editPet, deletePet } <span class="hljs-keyword">from</span> <span class="hljs-string">'./mutations/pets.mutations.js'</span>
<span class="hljs-keyword">import</span> { listPets, getPet } <span class="hljs-keyword">from</span> <span class="hljs-string">'./queries/pets.queries.js'</span>

<span class="hljs-comment">// A schema is a collection of type definitions (hence "typeDefs")</span>
<span class="hljs-comment">// that together define the "shape" of queries that are executed against your data.</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> typeDefs = <span class="hljs-string">`#graphql
  # OBJECT TYPES
  # This "Pet" type defines the queryable fields for every pet in our data source.
  type Pet {
    id: ID!
    name: String!
    type: String!
    age: Int!
    breed: String!
  }

  # INPUT TYPES
  # Define the input objects for addPet and editPet mutations
  input PetToEdit {
    id: ID!
    name: String!
    type: String!
    age: Int!
    breed: String!
  }

  input PetToAdd {
    name: String!
    type: String!
    age: Int!
    breed: String!
  }

  # The "Query" type is special: it lists all of the available queries that
  # clients can execute, along with the return type for each. In this
  # case, the "pets" query returns an array of zero or more pets.
  # QUERY TYPES
  type Query {
    pets: [Pet],
    pet(id: ID!): Pet
  }

  # MUTATION TYPES
  type Mutation {
    addPet(petToAdd: PetToAdd!): Pet,
    editPet(petToEdit: PetToEdit!): Pet,
    deletePet(id: ID!): [Pet],
  }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> resolvers = {
    <span class="hljs-comment">// Resolvers for Queries</span>
    <span class="hljs-attr">Query</span>: {
        <span class="hljs-attr">pets</span>: <span class="hljs-function">() =&gt;</span> listPets(),
        <span class="hljs-attr">pet</span>: <span class="hljs-function">(<span class="hljs-params">_, { id }</span>) =&gt;</span> getPet(id)
    },

    <span class="hljs-comment">// Resolvers for Mutations</span>
    <span class="hljs-attr">Mutation</span>: {
        <span class="hljs-attr">addPet</span>: <span class="hljs-function">(<span class="hljs-params">_, { petToAdd }</span>) =&gt;</span> addPet(petToAdd),
        <span class="hljs-attr">editPet</span>: <span class="hljs-function">(<span class="hljs-params">_, { petToEdit }</span>) =&gt;</span> editPet(petToEdit),
        <span class="hljs-attr">deletePet</span>: <span class="hljs-function">(<span class="hljs-params">_, { id }</span>) =&gt;</span> deletePet(id)
    }
}
</code></pre>
<p>Here we have two main things: typeDefs and resolvers.</p>
<p><strong>typeDefs</strong> defines the types for the data that can be queried in our API (in our case that's the <code>pet</code> object), as well as the input for queries/mutations (in our case that's <code>PetToEdit</code> and <code>PetToAdd</code>).</p>
<p>Lastly, it also defines the available queries and mutations for our API, declaring their names, as well as their input and return values. In our case we have two queries (<code>pets</code> and <code>pet</code>) and three mutations (<code>addPet</code>, <code>editPet</code> and <code>deletePet</code>).</p>
<p><strong>resolvers</strong> contain the actual implementation of our queries and mutations types. Here we're declaring each query and mutation, and indicating what each should do. In our case, we're linking them with the queries/mutations we're importing from our queries/mutations layer.</p>
<h3 id="heading-petsqueriesjs">pets.queries.js</h3>
<p>In your <code>pets.queries.js</code> file drop this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { getItem, listItems } <span class="hljs-keyword">from</span> <span class="hljs-string">'../models/pets.models.js'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getPet = <span class="hljs-function"><span class="hljs-params">id</span> =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> resp = getItem(id)
        <span class="hljs-keyword">return</span> resp
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> err
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> listPets = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> resp = listItems()
        <span class="hljs-keyword">return</span> resp
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> err
    }
}
</code></pre>
<p>As you can see, this file is very simple. It declares the functions that are imported in the <code>index.js</code> file and links them to the functions declared in the models layer.</p>
<h3 id="heading-petsmutationsjs">pets.mutations.js</h3>
<p>Same goes for our <code>pets.mutations.js</code> file, but with mutations now.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { editItem, addItem, deleteItem } <span class="hljs-keyword">from</span> <span class="hljs-string">'../models/pets.models.js'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addPet = <span class="hljs-function"><span class="hljs-params">petToAdd</span> =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> resp = addItem(petToAdd)
        <span class="hljs-keyword">return</span> resp
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> err
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> editPet = <span class="hljs-function"><span class="hljs-params">petToEdit</span> =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> resp = editItem(petToEdit?.id, petToEdit)
        <span class="hljs-keyword">return</span> resp
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> err
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> deletePet = <span class="hljs-function"><span class="hljs-params">id</span> =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> resp = deleteItem(id)
        <span class="hljs-keyword">return</span> resp
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-keyword">return</span> err
    }
}
</code></pre>
<h3 id="heading-petsmodelsjs">pets.models.js</h3>
<p>Now go to the models folder and create a <code>pets.models.js</code> file with this code in it:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> db <span class="hljs-keyword">from</span> <span class="hljs-string">'../../db/db.js'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getItem = <span class="hljs-function"><span class="hljs-params">id</span> =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> pet = db?.pets?.filter(<span class="hljs-function"><span class="hljs-params">pet</span> =&gt;</span> pet?.id === <span class="hljs-built_in">parseInt</span>(id))[<span class="hljs-number">0</span>]
        <span class="hljs-keyword">return</span> pet
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error'</span>, err)
        <span class="hljs-keyword">return</span> err
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> listItems = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">return</span> db?.pets
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error'</span>, err)
        <span class="hljs-keyword">return</span> err
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> editItem = <span class="hljs-function">(<span class="hljs-params">id, data</span>) =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> index = db.pets.findIndex(<span class="hljs-function"><span class="hljs-params">pet</span> =&gt;</span> pet.id === <span class="hljs-built_in">parseInt</span>(id))

        <span class="hljs-keyword">if</span> (index === <span class="hljs-number">-1</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Pet not found'</span>)
        <span class="hljs-keyword">else</span> {
            data.id = <span class="hljs-built_in">parseInt</span>(data.id)
            db.pets[index] = data
            <span class="hljs-keyword">return</span> db.pets[index]
        }
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error'</span>, err)
        <span class="hljs-keyword">return</span> err
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> addItem = <span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> newPet = { <span class="hljs-attr">id</span>: db.pets.length + <span class="hljs-number">1</span>, ...data }
        db.pets.push(newPet)
        <span class="hljs-keyword">return</span> newPet
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error'</span>, err)
        <span class="hljs-keyword">return</span> err
    }
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> deleteItem = <span class="hljs-function"><span class="hljs-params">id</span> =&gt;</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// delete item from db</span>
        <span class="hljs-keyword">const</span> index = db.pets.findIndex(<span class="hljs-function"><span class="hljs-params">pet</span> =&gt;</span> pet.id === <span class="hljs-built_in">parseInt</span>(id))

        <span class="hljs-keyword">if</span> (index === <span class="hljs-number">-1</span>) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Pet not found'</span>)
        <span class="hljs-keyword">else</span> {
            db.pets.splice(index, <span class="hljs-number">1</span>)
            <span class="hljs-keyword">return</span> db.pets
        }
    } <span class="hljs-keyword">catch</span> (err) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'Error'</span>, err)
        <span class="hljs-keyword">return</span> err
    }
}
</code></pre>
<p>These are the functions responsible for interacting with our data layer (database) and returning the corresponding information to our controllers.</p>
<h3 id="heading-database"><strong>Database</strong></h3>
<p>We wont use a real database for this example. Instead we'll just use a simple array that will work just fine for example purposes, though our data will of course reset every time our server does.</p>
<p>In the root of our project, create a <code>db</code> folder and a <code>db.js</code> file with this code in it:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> db = {
    <span class="hljs-attr">pets</span>: [
        {
            <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
            <span class="hljs-attr">name</span>: <span class="hljs-string">'Rex'</span>,
            <span class="hljs-attr">type</span>: <span class="hljs-string">'dog'</span>,
            <span class="hljs-attr">age</span>: <span class="hljs-number">3</span>,
            <span class="hljs-attr">breed</span>: <span class="hljs-string">'labrador'</span>,
        },
        {
            <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>,
            <span class="hljs-attr">name</span>: <span class="hljs-string">'Fido'</span>,
            <span class="hljs-attr">type</span>: <span class="hljs-string">'dog'</span>,
            <span class="hljs-attr">age</span>: <span class="hljs-number">1</span>,
            <span class="hljs-attr">breed</span>: <span class="hljs-string">'poodle'</span>,
        },
        {
            <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>,
            <span class="hljs-attr">name</span>: <span class="hljs-string">'Mittens'</span>,
            <span class="hljs-attr">type</span>: <span class="hljs-string">'cat'</span>,
            <span class="hljs-attr">age</span>: <span class="hljs-number">2</span>,
            <span class="hljs-attr">breed</span>: <span class="hljs-string">'tabby'</span>,
        },
    ]
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> db
</code></pre>
<p>As you can see, our <code>db</code> object contains a <code>pets</code> property whose value is an array of objects, each object being a pet. For each pet, we store an id, name, type, age and breed.</p>
<p>Now go to your terminal and run <code>nodemon app.js</code>. You should see this message confirming your server is alive: <code>🚀 Server ready at: [http://localhost:4000/](http://localhost:4000/)</code>.</p>
<h1 id="heading-how-to-test-a-graphql-api-with-supertest">How to Test a GraphQL API with Supertest</h1>
<p>Now that our server is up and running, let's implement a simple test suit to check if our queries and mutations behave as expected.</p>
<p>If you're not familiar with automated testing, I recommend you read <a target="_blank" href="https://www.freecodecamp.org/news/test-a-react-app-with-jest-testing-library-and-cypress/">this introductory article I wrote a while ago</a>.</p>
<h2 id="heading-our-tools-1"><strong>Our Tools</strong></h2>
<p><a target="_blank" href="https://www.npmjs.com/package/supertest"><strong>SuperTest</strong></a> is a JavaScript library that is used for testing HTTP servers or web applications that make HTTP requests. It provides a high-level abstraction for testing HTTP, allowing developers to send HTTP requests and make assertions about the responses received, making it easier to write automated tests for web applications.</p>
<p>SuperTest works with any JavaScript testing framework, such as <a target="_blank" href="https://mochajs.org/">Mocha</a> or <a target="_blank" href="https://jestjs.io/">Jest</a>, and can be used with any HTTP server or web application framework, such as Express.</p>
<p>SuperTest is built on top of the popular testing library Mocha, and uses the <a target="_blank" href="https://www.chaijs.com/">Chai</a> assertion library to make assertions about the responses received. It provides an easy-to-use API for making HTTP requests, including support for authentication, headers, and request bodies.</p>
<p>SuperTest also allows developers to test the entire request/response cycle, including middleware and error handling, making it a powerful tool for testing web applications.</p>
<p>Overall, SuperTest is a valuable tool for developers who want to write automated tests for their web applications. It helps ensure that their applications are functioning correctly and that any changes they make to the codebase do not introduce new bugs or issues.</p>
<h2 id="heading-the-code-1"><strong>The Code</strong></h2>
<p>First we'll need to install some dependencies. To save up terminal commands, go to your <code>package.json</code> file and replace your <code>devDependencies</code> section with the code below. Then run <code>npm install</code>.</p>
<pre><code class="lang-javascript">  <span class="hljs-string">"devDependencies"</span>: {
    <span class="hljs-string">"@babel/core"</span>: <span class="hljs-string">"^7.21.4"</span>,
    <span class="hljs-string">"@babel/preset-env"</span>: <span class="hljs-string">"^7.21.4"</span>,
    <span class="hljs-string">"babel-jest"</span>: <span class="hljs-string">"^29.5.0"</span>,
    <span class="hljs-string">"jest"</span>: <span class="hljs-string">"^29.5.0"</span>,
    <span class="hljs-string">"jest-babel"</span>: <span class="hljs-string">"^1.0.1"</span>,
    <span class="hljs-string">"nodemon"</span>: <span class="hljs-string">"^2.0.22"</span>,
    <span class="hljs-string">"supertest"</span>: <span class="hljs-string">"^6.3.3"</span>
  }
</code></pre>
<p>Here we're installing the <code>supertest</code> and <code>jest</code> libraries, which we need for our tests to run, plus some <code>babel</code> stuff we need for our project to correctly identify which files are test files.</p>
<p>Still in your <code>package.json</code>, add this script:</p>
<pre><code class="lang-javascript">  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-string">"test"</span>: <span class="hljs-string">"jest"</span>
  },
</code></pre>
<p>To end with the boilerplate, in the root of your project, create a <code>babel.config.cjs</code> file and drop this code in it:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//babel.config.cjs</span>
<span class="hljs-built_in">module</span>.exports = {
    <span class="hljs-attr">presets</span>: [
      [
        <span class="hljs-string">'@babel/preset-env'</span>,
        {
          <span class="hljs-attr">targets</span>: {
            <span class="hljs-attr">node</span>: <span class="hljs-string">'current'</span>,
          },
        },
      ],
    ],
  };
</code></pre>
<p>Now let's write some actual tests! Within your pets folder, create a <code>pets.test.js</code> file with this code in it:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> request <span class="hljs-keyword">from</span> <span class="hljs-string">'supertest'</span>

<span class="hljs-keyword">const</span> graphQLEndpoint = <span class="hljs-string">'http://localhost:4000/'</span>

describe(<span class="hljs-string">'Get all pets'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> postData = {
        <span class="hljs-attr">query</span>: <span class="hljs-string">`query Pets {
            pets {
                id
                name
                type
                age
                breed
            }
        }`</span>
    }

    test(<span class="hljs-string">'returns all pets'</span>, <span class="hljs-keyword">async</span> () =&gt; {
        request(graphQLEndpoint)
            .post(<span class="hljs-string">'?'</span>)
            .send(postData)
            .expect(<span class="hljs-number">200</span>)
            .end(<span class="hljs-function">(<span class="hljs-params">error, response</span>) =&gt;</span> {
                <span class="hljs-keyword">if</span> (error) <span class="hljs-built_in">console</span>.error(error)

                <span class="hljs-keyword">const</span> res = <span class="hljs-built_in">JSON</span>.parse(response.text)

                expect(res.data.pets).toEqual([
                    {
                        <span class="hljs-attr">id</span>: <span class="hljs-string">'1'</span>,
                        <span class="hljs-attr">name</span>: <span class="hljs-string">'Rex'</span>,
                        <span class="hljs-attr">type</span>: <span class="hljs-string">'dog'</span>,
                        <span class="hljs-attr">age</span>: <span class="hljs-number">3</span>,
                        <span class="hljs-attr">breed</span>: <span class="hljs-string">'labrador'</span>
                    },
                    {
                        <span class="hljs-attr">id</span>: <span class="hljs-string">'2'</span>,
                        <span class="hljs-attr">name</span>: <span class="hljs-string">'Fido'</span>,
                        <span class="hljs-attr">type</span>: <span class="hljs-string">'dog'</span>,
                        <span class="hljs-attr">age</span>: <span class="hljs-number">1</span>,
                        <span class="hljs-attr">breed</span>: <span class="hljs-string">'poodle'</span>
                    },
                    {
                        <span class="hljs-attr">id</span>: <span class="hljs-string">'3'</span>,
                        <span class="hljs-attr">name</span>: <span class="hljs-string">'Mittens'</span>,
                        <span class="hljs-attr">type</span>: <span class="hljs-string">'cat'</span>,
                        <span class="hljs-attr">age</span>: <span class="hljs-number">2</span>,
                        <span class="hljs-attr">breed</span>: <span class="hljs-string">'tabby'</span>
                    }
                ])
            })
    })
})

describe(<span class="hljs-string">'Get pet detail'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> postData = {
        <span class="hljs-attr">query</span>: <span class="hljs-string">`query Pet {
            pet(id: 1) {
                id
                name
                type
                age
                breed
            }
        }`</span>
    }

    test(<span class="hljs-string">'Return pet detail information'</span>, <span class="hljs-keyword">async</span> () =&gt; {
        request(graphQLEndpoint)
            .post(<span class="hljs-string">'?'</span>)
            .send(postData)
            .expect(<span class="hljs-number">200</span>)
            .end(<span class="hljs-function">(<span class="hljs-params">error, response</span>) =&gt;</span> {
                <span class="hljs-keyword">if</span> (error) <span class="hljs-built_in">console</span>.error(error)

                <span class="hljs-keyword">const</span> res = <span class="hljs-built_in">JSON</span>.parse(response.text)

                expect(res.data.pet).toEqual({
                    <span class="hljs-attr">id</span>: <span class="hljs-string">'1'</span>,
                    <span class="hljs-attr">name</span>: <span class="hljs-string">'Rex'</span>,
                    <span class="hljs-attr">type</span>: <span class="hljs-string">'dog'</span>,
                    <span class="hljs-attr">age</span>: <span class="hljs-number">3</span>,
                    <span class="hljs-attr">breed</span>: <span class="hljs-string">'labrador'</span>
                })
            })
    })
})

describe(<span class="hljs-string">'Edit pet'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> postData = {
        <span class="hljs-attr">query</span>: <span class="hljs-string">`mutation EditPet($petToEdit: PetToEdit!) {
            editPet(petToEdit: $petToEdit) {
                id
                name
                type
                age
                breed
            }
        }`</span>,
        <span class="hljs-attr">variables</span>: {
            <span class="hljs-attr">petToEdit</span>: {
                <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>,
                <span class="hljs-attr">name</span>: <span class="hljs-string">'Rexo'</span>,
                <span class="hljs-attr">type</span>: <span class="hljs-string">'dogo'</span>,
                <span class="hljs-attr">age</span>: <span class="hljs-number">4</span>,
                <span class="hljs-attr">breed</span>: <span class="hljs-string">'doberman'</span>
            }
        }
    }

    test(<span class="hljs-string">'Updates pet and returns it'</span>, <span class="hljs-keyword">async</span> () =&gt; {
        request(graphQLEndpoint)
            .post(<span class="hljs-string">'?'</span>)
            .send(postData)
            .expect(<span class="hljs-number">200</span>)
            .end(<span class="hljs-function">(<span class="hljs-params">error, response</span>) =&gt;</span> {
                <span class="hljs-keyword">if</span> (error) <span class="hljs-built_in">console</span>.error(error)

                <span class="hljs-keyword">const</span> res = <span class="hljs-built_in">JSON</span>.parse(response.text)

                expect(res.data.editPet).toEqual({
                    <span class="hljs-attr">id</span>: <span class="hljs-string">'1'</span>,
                    <span class="hljs-attr">name</span>: <span class="hljs-string">'Rexo'</span>,
                    <span class="hljs-attr">type</span>: <span class="hljs-string">'dogo'</span>,
                    <span class="hljs-attr">age</span>: <span class="hljs-number">4</span>,
                    <span class="hljs-attr">breed</span>: <span class="hljs-string">'doberman'</span>
                })
            })
    })
})

describe(<span class="hljs-string">'Add pet'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> postData = {
        <span class="hljs-attr">query</span>: <span class="hljs-string">`mutation AddPet($petToAdd: PetToAdd!) {
            addPet(petToAdd: $petToAdd) {
                id
                name
                type
                age
                breed
            }
        }`</span>,
        <span class="hljs-attr">variables</span>: {
            <span class="hljs-attr">petToAdd</span>: {
                <span class="hljs-attr">name</span>: <span class="hljs-string">'Salame'</span>,
                <span class="hljs-attr">type</span>: <span class="hljs-string">'cat'</span>,
                <span class="hljs-attr">age</span>: <span class="hljs-number">6</span>,
                <span class="hljs-attr">breed</span>: <span class="hljs-string">'pinky'</span>
            }
        }
    }

    test(<span class="hljs-string">'Adds new pet and returns the added item'</span>, <span class="hljs-keyword">async</span> () =&gt; {
        request(graphQLEndpoint)
            .post(<span class="hljs-string">'?'</span>)
            .send(postData)
            .expect(<span class="hljs-number">200</span>)
            .end(<span class="hljs-function">(<span class="hljs-params">error, response</span>) =&gt;</span> {
                <span class="hljs-keyword">if</span> (error) <span class="hljs-built_in">console</span>.error(error)

                <span class="hljs-keyword">const</span> res = <span class="hljs-built_in">JSON</span>.parse(response.text)

                expect(res.data.addPet).toEqual({
                    <span class="hljs-attr">id</span>: <span class="hljs-string">'4'</span>,
                    <span class="hljs-attr">name</span>: <span class="hljs-string">'Salame'</span>,
                    <span class="hljs-attr">type</span>: <span class="hljs-string">'cat'</span>,
                    <span class="hljs-attr">age</span>: <span class="hljs-number">6</span>,
                    <span class="hljs-attr">breed</span>: <span class="hljs-string">'pinky'</span>
                })
            })
    })
})

describe(<span class="hljs-string">'Delete pet'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> postData = {
        <span class="hljs-attr">query</span>: <span class="hljs-string">`mutation DeletePet {
            deletePet(id: 2) {
                id,
                name,
                type,
                age,
                breed
            }
        }`</span>
    }

    test(<span class="hljs-string">'Deletes given pet and returns updated list'</span>, <span class="hljs-keyword">async</span> () =&gt; {
        request(graphQLEndpoint)
            .post(<span class="hljs-string">'?'</span>)
            .send(postData)
            .expect(<span class="hljs-number">200</span>)
            .end(<span class="hljs-function">(<span class="hljs-params">error, response</span>) =&gt;</span> {
                <span class="hljs-keyword">if</span> (error) <span class="hljs-built_in">console</span>.error(error)

                <span class="hljs-keyword">const</span> res = <span class="hljs-built_in">JSON</span>.parse(response.text)

                expect(res.data.deletePet).toEqual([
                    {
                        <span class="hljs-attr">id</span>: <span class="hljs-string">'1'</span>,
                        <span class="hljs-attr">name</span>: <span class="hljs-string">'Rexo'</span>,
                        <span class="hljs-attr">type</span>: <span class="hljs-string">'dogo'</span>,
                        <span class="hljs-attr">age</span>: <span class="hljs-number">4</span>,
                        <span class="hljs-attr">breed</span>: <span class="hljs-string">'doberman'</span>
                    },
                    {
                        <span class="hljs-attr">id</span>: <span class="hljs-string">'3'</span>,
                        <span class="hljs-attr">name</span>: <span class="hljs-string">'Mittens'</span>,
                        <span class="hljs-attr">type</span>: <span class="hljs-string">'cat'</span>,
                        <span class="hljs-attr">age</span>: <span class="hljs-number">2</span>,
                        <span class="hljs-attr">breed</span>: <span class="hljs-string">'tabby'</span>
                    },
                    {
                        <span class="hljs-attr">id</span>: <span class="hljs-string">'4'</span>,
                        <span class="hljs-attr">name</span>: <span class="hljs-string">'Salame'</span>,
                        <span class="hljs-attr">type</span>: <span class="hljs-string">'cat'</span>,
                        <span class="hljs-attr">age</span>: <span class="hljs-number">6</span>,
                        <span class="hljs-attr">breed</span>: <span class="hljs-string">'pinky'</span>
                    }
                ])
            })
    })
})
</code></pre>
<p>This a test suite for our GraphQL API. It uses the <code>supertest</code> library to make HTTP requests to the API endpoint (<code>http://localhost:4000/</code>) and verifies that the API responds correctly to various queries and mutations.</p>
<p>The code has five different test cases:</p>
<ol>
<li><p><code>Get all pets</code>: This test queries the API for all pets and verifies that the response matches an expected list of pets.</p>
</li>
<li><p><code>Get pet detail</code>: This test queries the API for the details of a specific pet and verifies that the response matches the expected details for that pet.</p>
</li>
<li><p><code>Edit pet</code>: This test performs a mutation to edit the details of a specific pet and verifies that the response matches the expected edited details for that pet.</p>
</li>
<li><p><code>Add pet</code>: This test performs a mutation to add a new pet and verifies that the response matches the expected details for the newly added pet.</p>
</li>
<li><p><code>Delete pet</code>: This test performs a mutation to delete a specific pet and verifies that the response matches the expected list of pets after the deletion.</p>
</li>
</ol>
<p>Each test case includes a <code>postData</code> object that contains the GraphQL query or mutation to be sent to the API endpoint as well as any necessary variables.</p>
<p>The actual HTTP request is made using the <code>request</code> function from the <code>supertest</code> library, which sends a POST request to the API endpoint with the <code>postData</code> object in the request body. The response is then parsed as JSON and the test case verifies that the response matches the expected result using the <code>expect</code> function from the Jest testing framework.</p>
<p>Now go to your terminal, run <code>npm test</code>, and you should see all your tests passing:</p>
<pre><code class="lang-javascript">&gt; jest

 PASS  pets/pets.test.js
  Get all pets
    ✓ returns all pets (<span class="hljs-number">15</span> ms)
  Get pet detail
    ✓ Return pet detail information (<span class="hljs-number">2</span> ms)
  Edit pet
    ✓ Updates pet and returns it (<span class="hljs-number">1</span> ms)
  Add pet
    ✓ Adds <span class="hljs-keyword">new</span> pet and returns the added item (<span class="hljs-number">1</span> ms)
  Delete pet
    ✓ Deletes given pet and returns updated list (<span class="hljs-number">1</span> ms)

Test Suites: <span class="hljs-number">1</span> passed, <span class="hljs-number">1</span> total
<span class="hljs-attr">Tests</span>:       <span class="hljs-number">5</span> passed, <span class="hljs-number">5</span> total
<span class="hljs-attr">Snapshots</span>:   <span class="hljs-number">0</span> total
<span class="hljs-attr">Time</span>:        <span class="hljs-number">0.607</span> s, estimated <span class="hljs-number">1</span> s
Ran all test suites.
</code></pre>
<h1 id="heading-how-to-consume-a-graphql-api-on-a-front-end-react-app">How to Consume a GraphQL API on a Front-end React App</h1>
<p>Now we know our server is running and behaving as expected. Let's see some more realistic example of how our API might be consumed by a front end app.</p>
<p>For this example, we'll use a React application, and <a target="_blank" href="https://www.apollographql.com/docs/react/">Apollo client</a> to send and process our requests.</p>
<h2 id="heading-our-tools-2">Our Tools</h2>
<p><a target="_blank" href="https://react.dev/"><strong>React</strong></a> is a popular JavaScript library for building user interfaces. It allows developers to create reusable UI components and efficiently update and render them in response to changes in application state.</p>
<p>Regarding <strong>Apollo client</strong>, we've introduced it already.</p>
<p>Side comment – we're using Apollo client here since it's a very popular tool and it makes sense to use the same set of libraries both in front and back-end. If you're interested in other possible ways a GraphQL API can be consumed from a front-end React App, <a target="_blank" href="https://www.freecodecamp.org/news/5-ways-to-fetch-data-react-graphql/">Reed Barger has a pretty cool article on this topic</a>.</p>
<h2 id="heading-the-code-2">The Code</h2>
<p>Let's create our React app by running <code>yarn create vite</code> and following the terminal prompts. Once that's done, run <code>yarn add react-router-dom</code> (which we'll use to setup basic routing in our app).</p>
<h3 id="heading-appjsx"><strong>App.jsx</strong></h3>
<p>Put this code within your <code>App.jsx</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Suspense, lazy, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { BrowserRouter <span class="hljs-keyword">as</span> Router, Routes, Route } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./App.css'</span>

<span class="hljs-keyword">const</span> PetList = lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/PetList'</span>))
<span class="hljs-keyword">const</span> PetDetail = lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/PetDetail'</span>))
<span class="hljs-keyword">const</span> EditPet = lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/EditPet'</span>))
<span class="hljs-keyword">const</span> AddPet = lazy(<span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./pages/AddPet'</span>))

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [petToEdit, setPetToEdit] = useState(<span class="hljs-literal">null</span>)

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">'App'</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">Router</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Pet shelter<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

                <span class="hljs-tag">&lt;<span class="hljs-name">Routes</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span>
                        <span class="hljs-attr">path</span>=<span class="hljs-string">'/'</span>
                        <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>
                            &lt;<span class="hljs-attr">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;&gt;</span><span class="hljs-tag">&lt;/&gt;</span>}&gt;
                                <span class="hljs-tag">&lt;<span class="hljs-name">PetList</span> /&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
                        }
                    /&gt;

                    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span>
                        <span class="hljs-attr">path</span>=<span class="hljs-string">'/:petId'</span>
                        <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>
                            &lt;<span class="hljs-attr">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;&gt;</span><span class="hljs-tag">&lt;/&gt;</span>}&gt;
                                <span class="hljs-tag">&lt;<span class="hljs-name">PetDetail</span> <span class="hljs-attr">setPetToEdit</span>=<span class="hljs-string">{setPetToEdit}</span> /&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
                        }
                    /&gt;

                    <span class="hljs-tag">&lt;<span class="hljs-name">Route</span>
                        <span class="hljs-attr">path</span>=<span class="hljs-string">'/:petId/edit'</span>
                        <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>
                            &lt;<span class="hljs-attr">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;&gt;</span><span class="hljs-tag">&lt;/&gt;</span>}&gt;
                                <span class="hljs-tag">&lt;<span class="hljs-name">EditPet</span> <span class="hljs-attr">petToEdit</span>=<span class="hljs-string">{petToEdit}</span> /&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span>
                        }
                    /&gt;</span>

                    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Route</span>
                        <span class="hljs-attr">path</span>=<span class="hljs-string">'/add'</span>
                        <span class="hljs-attr">element</span>=<span class="hljs-string">{</span>
                            &lt;<span class="hljs-attr">Suspense</span> <span class="hljs-attr">fallback</span>=<span class="hljs-string">{</span>&lt;&gt;</span><span class="hljs-tag">&lt;/&gt;</span>}&gt;
                                <span class="hljs-tag">&lt;<span class="hljs-name">AddPet</span> /&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">Suspense</span>&gt;</span></span>
                        }
                    /&gt;
                &lt;/Routes&gt;
            &lt;/Router&gt;
        &lt;/div&gt;
    )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> App
</code></pre>
<p>Here we're just defining our routes. We'll have 4 main routes in our app, each corresponding to a different view:</p>
<ul>
<li><p>One to see the whole list of pets.</p>
</li>
<li><p>One to see the detail of a single pet.</p>
</li>
<li><p>One to edit a single pet.</p>
</li>
<li><p>One to add a new pet to the list.</p>
</li>
</ul>
<p>Besides, we have a button to add a new pet and a state that will store the information of the pet we want to edit.</p>
<p>Next, create a <code>pages</code> directory with these files in it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/image-281.png" alt="image-281" width="600" height="400" loading="lazy"></p>
<p><em>Folder structure</em></p>
<h3 id="heading-mainjs">main.js</h3>
<p>Before jumping into our pages, we have to set up the Apollo client library. Run <code>yarn add @apollo/client</code> and <code>yarn add graphql</code> to install the necessary dependencies.</p>
<p>The go to the <code>main.js</code> file and drop this code in it:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">'react-dom/client'</span>
<span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">'./App'</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./index.css'</span>
<span class="hljs-keyword">import</span> { ApolloClient, InMemoryCache, ApolloProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>

<span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApolloClient({
  <span class="hljs-attr">uri</span>: <span class="hljs-string">'http://localhost:4000/'</span>,
  <span class="hljs-attr">cache</span>: <span class="hljs-keyword">new</span> InMemoryCache(),
})

ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'root'</span>)).render(
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ApolloProvider</span> <span class="hljs-attr">client</span>=<span class="hljs-string">{client}</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ApolloProvider</span>&gt;</span></span>
)
</code></pre>
<p>Here we're initializing the <code>ApolloClient</code>, passing its constructor a configuration object with the <code>uri</code> and <code>cache</code> fields:</p>
<ul>
<li><p><code>uri</code> specifies the URL of our GraphQL server.</p>
</li>
<li><p><code>cache</code> is an instance of <code>InMemoryCache</code>, which Apollo Client uses to cache query results after fetching them.</p>
</li>
</ul>
<p>Then we wrap our <code>App</code> component with our ApolloProvider. This allows any component in our component tree to use the hooks provided by Apollo client, much like React Context works. ;)</p>
<h3 id="heading-mutations-and-queries">Mutations and queries</h3>
<p>In the root of your project, create this folder structure:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Folder structure</em></p>
<p>In these two files we'll declare the request bodies we'll use for our queries and mutations. I like to separate this into different files because it gives use a clear view of the different kinds of request we have in our app, and it also keeps our component's code cleaner.</p>
<p>In the <code>queries.js</code> file drop this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> GET_PETS = gql<span class="hljs-string">`
    query Pets {
        pets {
            id
            name
            type
            breed
        }
    }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> GET_PET = gql<span class="hljs-string">`
    query Pet($petId: ID!) {
        pet(id: $petId) {
            id
            name
            type
            age
            breed
        }
    }
`</span>
</code></pre>
<p>And in the <code>mutations.js</code> file drop this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { gql } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> DELETE_PET = gql<span class="hljs-string">`
    mutation DeletePet($deletePetId: ID!) {
        deletePet(id: $deletePetId) {
            id
        }
    }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ADD_PET = gql<span class="hljs-string">`
    mutation AddPet($petToAdd: PetToAdd!) {
        addPet(petToAdd: $petToAdd) {
            id
            name
            type
            age
            breed
        }
    }
`</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> EDIT_PET = gql<span class="hljs-string">`
    mutation EditPet($petToEdit: PetToEdit!) {
        editPet(petToEdit: $petToEdit) {
            id
            name
            type
            age
            breed
        }
    }
`</span>
</code></pre>
<p>As you can see, the syntax for queries and mutations is fairly similar. Request bodies are written in GraphQL query language, which is used to define the structure and data types of data that can be requested from a GraphQL API.</p>
<ul>
<li>GraphQL Query Syntax:</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> GET_PETS = gql<span class="hljs-string">`
    query Pets {
        pets {
            id
            name
            type
            breed
        }
    }
`</span>
</code></pre>
<p>This query is named <code>Pets</code> and it requests data from the <code>pets</code> field. The fields <code>id</code>, <code>name</code>, <code>type</code>, and <code>breed</code> are requested from each <code>Pet</code> object returned by the API.</p>
<p>In GraphQL, queries always start with the keyword <code>query</code> and are followed by the name of the query, if provided. The fields requested are enclosed in curly braces and can be nested to request data from related fields.</p>
<ul>
<li>GraphQL Mutation Syntax:</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> ADD_PET = gql<span class="hljs-string">`
    mutation AddPet($petToAdd: PetToAdd!) {
        addPet(petToAdd: $petToAdd) {
            id
            name
            type
            age
            breed
        }
    }
`</span>
</code></pre>
<p>This mutation is named <code>AddPet</code> and sends a new <code>Pet</code> object to be added to the API via the <code>addPet</code> mutation. The <code>$petToAdd</code> variable is defined as a required input of type <code>PetToAdd</code>. When the mutation is executed, the input variable will be passed in as an argument to the <code>addPet</code> mutation. The mutation then returns the <code>id</code>, <code>name</code>, <code>type</code>, <code>age</code>, and <code>breed</code> fields for the newly created <code>Pet</code> object.</p>
<p>In GraphQL, mutations always start with the keyword <code>mutation</code> and are followed by the name of the mutation, if provided. The fields requested in the mutation response are also enclosed in curly braces.</p>
<p>Note that both queries and mutations in GraphQL can accept variables as input, which are defined in the query or mutation body using a special syntax (<code>$variableName: variableType!</code>). These variables can be passed in when the query or mutation is executed, allowing for more dynamic and reusable queries and mutations.</p>
<h3 id="heading-petlistjsx"><strong>PetList.jsx</strong></h3>
<p>Let's start with the file responsible for rendering the whole list of pets:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>
<span class="hljs-keyword">import</span> { useQuery } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>
<span class="hljs-keyword">import</span> { GET_PETS } <span class="hljs-keyword">from</span> <span class="hljs-string">'../api/queries'</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PetList</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> { loading, error, data } = useQuery(GET_PETS)

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Pet List<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/add'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Add new pet<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

            {loading &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
            {error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Error: {error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}

            {data?.pets?.map(pet =&gt; {
                return (
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{pet?.id}</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
                            {pet?.name} - {pet?.type} - {pet?.breed}
                        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>`/${<span class="hljs-attr">pet</span>?<span class="hljs-attr">.id</span>}`}&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Pet detail<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                )
            })}
        <span class="hljs-tag">&lt;/&gt;</span></span>
    )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> PetList
</code></pre>
<p>This code defines a React functional component called <code>PetList</code> that fetches a list of pets from a GraphQL API using the <code>useQuery</code> hook provided by the <code>@apollo/client</code> library. The query used to fetch the pets is defined in a separate file called <code>queries.js</code>, which exports a GraphQL query called <code>GET_PETS</code>.</p>
<p>The <code>useQuery</code> hook returns an object with three properties: <code>loading</code>, <code>error</code>, and <code>data</code>. These properties are destructured from the object and used to conditionally render different UI elements depending on the status of the API request.</p>
<p>If <code>loading</code> is true, a loading message is displayed on the screen. If <code>error</code> is defined, an error message is displayed with the specific error message returned by the API. If <code>data</code> is defined and contains an array of <code>pets</code>, each <code>pet</code> is displayed in a div with their <code>name</code>, <code>type</code>, and <code>breed</code>. Each pet div also contains a link to view more details about the pet.</p>
<p>The <code>useQuery</code> hook works by executing the <code>GET_PETS</code> query and returning the result as an object with the <code>loading</code>, <code>error</code>, and <code>data</code> properties. When the component first renders, <code>loading</code> is true while the query is being executed. If the query is successful, <code>loading</code> is false and <code>data</code> is populated with the results. If the query encounters an error, <code>error</code> is populated with the specific error message.</p>
<p>As you can see, managing requests with Apollo client is really nice and simple. And the hooks it provides, save us quite a bit of code normally used to execute requests, store it's response and handle errors.</p>
<p>Remember that to make calls to our server, we must have it up and running by running <code>nodemon app.js</code> in our server project terminal.</p>
<p>Just to show there's no weird magic going on here, if we go to our browser, open the dev tools and go to the network tab, we could see our app is making a POST request to our server endpoint. And that the payload is our request body in the form of a string.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-7.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The POST request</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-8.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Request body</em></p>
<p>This means that if we wanted to, we could also consume our GraphQL API by using fetch, like following:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>
<span class="hljs-keyword">import</span> { useEffect, useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PetList</span>(<span class="hljs-params"></span>) </span>{

    <span class="hljs-keyword">const</span> [pets, setPets] = useState([])

    <span class="hljs-keyword">const</span> getPets = <span class="hljs-function">() =&gt;</span> {
        fetch(<span class="hljs-string">'http://localhost:4000/'</span>, {
            <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
            <span class="hljs-attr">headers</span>: {
                <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
            },
            <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
                <span class="hljs-attr">query</span>: <span class="hljs-string">`
                query Pets {
                    pets {
                    id
                    name
                    type
                    breed
                    }
                }
                `</span>
            })
        })
            .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
            .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> setPets(data?.data?.pets))
            .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(error))
    }

    useEffect(<span class="hljs-function">() =&gt;</span> {
        getPets()
    }, [])

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Pet List<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/add'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Add new pet<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

            {pets?.map(pet =&gt; {
                return (
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{pet?.id}</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
                            {pet?.name} - {pet?.type} - {pet?.breed}
                        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>`/${<span class="hljs-attr">pet</span>?<span class="hljs-attr">.id</span>}`}&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Pet detail<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                )
            })}
        <span class="hljs-tag">&lt;/&gt;</span></span>
    )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> PetList
</code></pre>
<p>If you check your network tab again, you should see still the same POST request with the some request body.</p>
<p>Of course this approach is not very practical as it requires more lines of code to perform the same thing. But it's important to know that libraries like Apollo only give us a <a target="_blank" href="https://www.freecodecamp.org/news/an-introduction-to-programming-paradigms/#declarative-programming">declarative API</a> to work with and simplify our code. Beneath it all we're still working with regular HTTP requests.</p>
<h3 id="heading-petdetailjsx"><strong>PetDetail.jsx</strong></h3>
<p>Now let's go to the <code>PetDetail.jsx</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { useParams, Link } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>
<span class="hljs-keyword">import</span> { useQuery, useMutation } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>
<span class="hljs-keyword">import</span> { GET_PET } <span class="hljs-keyword">from</span> <span class="hljs-string">'../api/queries'</span>
<span class="hljs-keyword">import</span> { DELETE_PET } <span class="hljs-keyword">from</span> <span class="hljs-string">'../api/mutations'</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">PetDetail</span>(<span class="hljs-params">{ setPetToEdit }</span>) </span>{
    <span class="hljs-keyword">const</span> { petId } = useParams()

    <span class="hljs-keyword">const</span> { loading, error, data } = useQuery(GET_PET, {
        <span class="hljs-attr">variables</span>: { petId }
    })

    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (data &amp;&amp; data?.pet) setPetToEdit(data?.pet)
    }, [data])

    <span class="hljs-keyword">const</span> [deletePet, { <span class="hljs-attr">loading</span>: deleteLoading, <span class="hljs-attr">error</span>: deleteError, <span class="hljs-attr">data</span>: deleteData }] = useMutation(DELETE_PET, {
        <span class="hljs-attr">variables</span>: { <span class="hljs-attr">deletePetId</span>: petId }
    })

    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (deleteData &amp;&amp; deleteData?.deletePet) <span class="hljs-built_in">window</span>.location.href = <span class="hljs-string">'/'</span>
    }, [deleteData])

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">justifyContent:</span> '<span class="hljs-attr">center</span>', <span class="hljs-attr">aligniItems:</span> '<span class="hljs-attr">center</span>' }}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Pet Detail<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Back to list<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

            {(loading || deleteLoading) &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}

            {error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Error: {error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
            {deleteError &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>deleteError: {deleteError.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}

            {data?.pet &amp;&amp; (
                <span class="hljs-tag">&lt;&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Pet name: {data?.pet?.name}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Pet type: {data?.pet?.type}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Pet age: {data?.pet?.age}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Pet breed: {data?.pet?.breed}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">justifyContent:</span> '<span class="hljs-attr">center</span>', <span class="hljs-attr">aligniItems:</span> '<span class="hljs-attr">center</span>' }}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">{</span>`/${<span class="hljs-attr">data</span>?<span class="hljs-attr">.pet</span>?<span class="hljs-attr">.id</span>}/<span class="hljs-attr">edit</span>`}&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginRight:</span> <span class="hljs-attr">10</span> }}&gt;</span>Edit pet<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

                        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginLeft:</span> <span class="hljs-attr">10</span> }} <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> deletePet()}&gt;
                            Delete pet
                        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/&gt;</span></span>
            )}
        &lt;/div&gt;
    )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> PetDetail
</code></pre>
<p>This component loads the detail info of the pet by executing a query in a very similar way than the previous component.</p>
<p>Moreover, it executes the mutation needed to delete the pet register. You can see that for this we're using the <code>useMutation</code> hook. It's quite similar to <code>useQuery</code>, but besides the <code>loading, error and data</code> values it also provides a function to execute our query after a given event.</p>
<p>You can see that for this mutation hook we're passing an object as second parameter, containing the variables this mutation requires. In this case, it's the id of the pet register we want to delete.</p>
<pre><code class="lang-plaintext">const [deletePet, { loading: deleteLoading, error: deleteError, data: deleteData }] = useMutation(DELETE_PET, {
    variables: { deletePetId: petId }
})
</code></pre>
<p>Remember that when we declared our mutation in <code>mutations.js</code> we had already declared the variables this mutation would use.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> DELETE_PET = gql<span class="hljs-string">`
    mutation DeletePet($deletePetId: ID!) {
        deletePet(id: $deletePetId) {
            id
        }
    }
`</span>
</code></pre>
<h3 id="heading-addpetjsx"><strong>AddPet.jsx</strong></h3>
<p>This is the file responsible for adding a new pet to our register:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>
<span class="hljs-keyword">import</span> { useMutation } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>
<span class="hljs-keyword">import</span> { ADD_PET } <span class="hljs-keyword">from</span> <span class="hljs-string">'../api/mutations'</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">AddPet</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> [petName, setPetName] = useState()
    <span class="hljs-keyword">const</span> [petType, setPetType] = useState()
    <span class="hljs-keyword">const</span> [petAge, setPetAge] = useState()
    <span class="hljs-keyword">const</span> [petBreed, setPetBreed] = useState()

    <span class="hljs-keyword">const</span> [addPet, { loading, error, data }] = useMutation(ADD_PET, {
        <span class="hljs-attr">variables</span>: {
            <span class="hljs-attr">petToAdd</span>: {
                <span class="hljs-attr">name</span>: petName,
                <span class="hljs-attr">type</span>: petType,
                <span class="hljs-attr">age</span>: <span class="hljs-built_in">parseInt</span>(petAge),
                <span class="hljs-attr">breed</span>: petBreed
            }
        }
    })

    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (data &amp;&amp; data?.addPet) <span class="hljs-built_in">window</span>.location.href = <span class="hljs-string">`/<span class="hljs-subst">${data?.addPet?.id}</span>`</span>
    }, [data])

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">justifyContent:</span> '<span class="hljs-attr">center</span>', <span class="hljs-attr">aligniItems:</span> '<span class="hljs-attr">center</span>' }}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Add Pet<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Back to list<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

            {loading || error ? (
                <span class="hljs-tag">&lt;&gt;</span>
                    {loading &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
                    {error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Error: {error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
                <span class="hljs-tag">&lt;/&gt;</span></span>
            ) : (
                <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">margin:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Pet name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{petName}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setPetName(e.target.value)} /&gt;
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">margin:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Pet type<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{petType}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setPetType(e.target.value)} /&gt;
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">margin:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Pet age<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{petAge}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setPetAge(e.target.value)} /&gt;
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">margin:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Pet breed<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{petBreed}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setPetBreed(e.target.value)} /&gt;
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                        <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginTop:</span> <span class="hljs-attr">30</span> }}
                        <span class="hljs-attr">disabled</span>=<span class="hljs-string">{!petName</span> || !<span class="hljs-attr">petType</span> || !<span class="hljs-attr">petAge</span> || !<span class="hljs-attr">petBreed</span>}
                        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> addPet()}
                    &gt;
                        Add pet
                    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/&gt;</span></span>
            )}
        &lt;/div&gt;
    )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> AddPet
</code></pre>
<p>Here we have a component that loads a form to add a new pet and performs a mutation when the data is sent. It accepts the new pet info as parameter, in a similar way that the <code>deletePet</code> mutation accepted the pet id.</p>
<h3 id="heading-editpetjsx"><strong>EditPet.jsx</strong></h3>
<p>Finally, the file responsible for editing a pet register:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React, { useState, useEffect } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>
<span class="hljs-keyword">import</span> { Link } <span class="hljs-keyword">from</span> <span class="hljs-string">'react-router-dom'</span>
<span class="hljs-keyword">import</span> { useMutation } <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>
<span class="hljs-keyword">import</span> { EDIT_PET } <span class="hljs-keyword">from</span> <span class="hljs-string">'../api/mutations'</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">EditPet</span>(<span class="hljs-params">{ petToEdit }</span>) </span>{
    <span class="hljs-keyword">const</span> [petName, setPetName] = useState(petToEdit?.name)
    <span class="hljs-keyword">const</span> [petType, setPetType] = useState(petToEdit?.type)
    <span class="hljs-keyword">const</span> [petAge, setPetAge] = useState(petToEdit?.age)
    <span class="hljs-keyword">const</span> [petBreed, setPetBreed] = useState(petToEdit?.breed)

    <span class="hljs-keyword">const</span> [editPet, { loading, error, data }] = useMutation(EDIT_PET, {
        <span class="hljs-attr">variables</span>: {
            <span class="hljs-attr">petToEdit</span>: {
                <span class="hljs-attr">id</span>: <span class="hljs-built_in">parseInt</span>(petToEdit.id),
                <span class="hljs-attr">name</span>: petName,
                <span class="hljs-attr">type</span>: petType,
                <span class="hljs-attr">age</span>: <span class="hljs-built_in">parseInt</span>(petAge),
                <span class="hljs-attr">breed</span>: petBreed
            }
        }
    })

    useEffect(<span class="hljs-function">() =&gt;</span> {
        <span class="hljs-keyword">if</span> (data &amp;&amp; data?.editPet?.id) <span class="hljs-built_in">window</span>.location.href = <span class="hljs-string">`/<span class="hljs-subst">${data?.editPet?.id}</span>`</span>
    }, [data])

    <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">justifyContent:</span> '<span class="hljs-attr">center</span>', <span class="hljs-attr">aligniItems:</span> '<span class="hljs-attr">center</span>' }}&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Edit Pet<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">Link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">'/'</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Back to list<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">Link</span>&gt;</span>

            {loading || error ? (
                <span class="hljs-tag">&lt;&gt;</span>
                    {loading &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Loading...<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
                    {error &amp;&amp; <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Error: {error.message}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>}
                <span class="hljs-tag">&lt;/&gt;</span></span>
            ) : (
                <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">margin:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Pet name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{petName}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setPetName(e.target.value)} /&gt;
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">margin:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Pet type<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{petType}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setPetType(e.target.value)} /&gt;
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">margin:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Pet age<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{petAge}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setPetAge(e.target.value)} /&gt;
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">display:</span> '<span class="hljs-attr">flex</span>', <span class="hljs-attr">flexDirection:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">margin:</span> <span class="hljs-attr">20</span> }}&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span>&gt;</span>Pet breed<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">'text'</span> <span class="hljs-attr">value</span>=<span class="hljs-string">{petBreed}</span> <span class="hljs-attr">onChange</span>=<span class="hljs-string">{e</span> =&gt;</span> setPetBreed(e.target.value)} /&gt;
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
                        <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">marginTop:</span> <span class="hljs-attr">30</span> }}
                        <span class="hljs-attr">disabled</span>=<span class="hljs-string">{!petName</span> || !<span class="hljs-attr">petType</span> || !<span class="hljs-attr">petAge</span> || !<span class="hljs-attr">petBreed</span>}
                        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> editPet()}
                    &gt;
                        Save changes
                    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/&gt;</span></span>
            )}
        &lt;/div&gt;
    )
}

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> EditPet
</code></pre>
<p>Last, we have a component to edit a pet register through a form. It performs a mutation when the data is sent, and as parameters it accepts the new pet info.</p>
<p>And that's it! We're using all of our API queries and mutations in our front end app. =)</p>
<h1 id="heading-how-to-document-a-graphql-api-with-apollo-sandbox">How to Document a GraphQL API with Apollo Sandbox</h1>
<p>One of Apollo's coolest features is that it comes with a built-in sandbox you can use to test and document your API.</p>
<p>Apollo Sandbox is a web-based GraphQL IDE that provides a sandbox environment for testing GraphQL queries, mutations, and subscriptions. It is a free, online tool provided by Apollo that allows you to interact with your GraphQL API and explore its schema, data, and capabilities.</p>
<p>Here are some of the main features of Apollo Sandbox:</p>
<ol>
<li><p>Query Editor: A feature-rich GraphQL query editor that provides syntax highlighting, autocompletion, validation, and error highlighting.</p>
</li>
<li><p>Schema Explorer: A graphical interface that allows you to explore your GraphQL schema and see its types, fields, and relationships.</p>
</li>
<li><p>Mocking: Apollo Sandbox allows you to easily generate mock data based on your schema, which is useful for testing your queries and mutations without connecting to a real data source.</p>
</li>
<li><p>Collaboration: You can share your sandbox with others, collaborate on queries, and see real-time changes.</p>
</li>
<li><p>Documentation: You can add documentation to your schema and query results to help others understand your API.</p>
</li>
</ol>
<p>To use our sandbox, simply open your browser at <a target="_blank" href="http://localhost:4000/"><code>http://localhost:4000/</code></a>. You should see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Apollo sandbox</em></p>
<p>From here you can see the API data schema and available mutations and queries, and also execute them and see how your API responds. For example, by executing the <code>pets</code> query, we can see that response on the right side panel.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Executing a query</em></p>
<p>If you hop on to the schema section you could see a whole detail of the available queries, mutations object and input types in our API.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/image-9.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>The schema section</em></p>
<p>Apollo sandbox is a great tool that can be used both as self-documentation for our API and a great development and testing tool.</p>
<h1 id="heading-wrapping-up"><strong>Wrapping Up</strong></h1>
<p>Well everyone, as always, I hope you enjoyed the article and learned something new.</p>
<p>If you want, you can also follow me on <a target="_blank" href="https://www.linkedin.com/in/germancocca/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/CoccaGerman">Twitter</a>. See you in the next one!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/tumblr_6eb166181e857e65bb472a1ba4bd450c_d935c3d9_500.gif" alt="Image" width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Different Types of APIs – SOAP vs REST vs GraphQL ]]>
                </title>
                <description>
                    <![CDATA[ Hi everyone! In this article we're going to take a good look at APIs, a core concept in modern software development. We're going to talk about the main kinds of APIs used nowadays (SOAP, REST and GraphQL), their characteristics, pros and cons, and si... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/rest-vs-graphql-apis/</link>
                <guid isPermaLink="false">66d45f1fd1ffc3d3eb89ddfc</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ German Cocca ]]>
                </dc:creator>
                <pubDate>Tue, 07 Mar 2023 23:24:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/john-towner-p-rN-n6Miag-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Hi everyone! In this article we're going to take a good look at APIs, a core concept in modern software development.</p>
<p>We're going to talk about the main kinds of APIs used nowadays (SOAP, REST and GraphQL), their characteristics, pros and cons, and situations in which each of them might be more beneficial.</p>
<p>Let's go! 🙃</p>
<h1 id="heading-table-of-contents">Table of Contents</h1>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-soap-apis-work">How SOAP APIs Work</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-about-xml">About XML</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-consume-a-soap-api">How to Consume a SOAP API</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-rest-apis-work">How REST APIs Work</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-how-to-consume-a-rest-api">How to Consume a REST API</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-graphql-apis-work">How GraphQL APIs work</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-how-to-consume-a-graphql-api">How to Consume a GraphQL API</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ul>
<h2 id="heading-intro">Intro</h2>
<p>In <a target="_blank" href="https://www.freecodecamp.org/news/an-introduction-to-software-architecture-patterns/">a recent article</a> I talked briefly about two very important concepts in modern software development: the client-server model and APIs.</p>
<p><strong>Client-server</strong> is a model that structures the tasks or workloads of an application between a resource or service <strong>provider</strong> (server) and a service or resource requester (client).</p>
<p>Put simply, the client is the application that requests some kind of information or performs actions, and the server is the program that sends information or performs actions according to what the client does.</p>
<p>Most applications nowadays use a client-server model. The most important concept to remember about it is that <strong>clients request resources or services</strong> that <strong>the server performs</strong>. The way in which these two parts usually communicate is through an <strong>API</strong> (application programming interface).</p>
<p>An API is nothing more than a <strong>set of defined rules that establishes how one application can communicate with another</strong>. It's like a contract between the two parts that says "If you send A, I'll always respond B. If you send C, I'll always respond D..." and so on.</p>
<p>Having this set of rules, the client knows exactly what it has to require in order to complete a certain task, and the server knows exactly what the client will require when a certain action has to be performed.</p>
<p>APIs are absolutely everywhere in current software development. Almost any kind of application will use a client-server model enabled by API communication. That's why I think it's a very good idea for us as developers to get to know them well.</p>
<p>The most popular ways to implement APIs nowadays are REST and GraphQl. We'll also take a look at SOAP, which was quite popular some years ago and is still used in some niche sectors.</p>
<p>If you'd like a deeper intro to what APIs are, <a target="_blank" href="https://www.youtube.com/watch?v=yBZO5Rb4ibo">here's an awesome video about it</a>.</p>
<p>With all this in mind, let's get into the details of how SOAP, REST and GraphQL APIs work.</p>
<h1 id="heading-how-soap-apis-work">How SOAP APIs Work</h1>
<p>Simple Object Access Protocol (SOAP) is a messaging protocol used for exchanging structured data between different systems over the internet. SOAP is an XML-based protocol and is considered one of the earliest web service protocols.</p>
<p>SOAP was first introduced in 1998 by Microsoft as a successor to Common Object Request Broker Architecture (CORBA) and Distributed Component Object Model (DCOM).</p>
<p>SOAP was designed to provide a platform-independent way to exchange data between different systems over the internet. SOAP was later standardized by the World Wide Web Consortium (W3C) in 2003.</p>
<p><strong>Main Characteristics:</strong></p>
<ol>
<li><p><strong>Protocol-Independent:</strong> SOAP is designed to work with any protocol that supports the transmission of messages over the internet, including HTTP, SMTP, and FTP.</p>
</li>
<li><p><strong>Platform-Independent:</strong> SOAP is designed to work with any programming language or platform that supports XML and can send and receive HTTP messages.</p>
</li>
<li><p><strong>Messaging:</strong> SOAP is a messaging protocol and defines a set of rules for exchanging structured data between different systems.</p>
</li>
<li><p><strong>Security:</strong> SOAP supports several security standards, including encryption, digital signatures, and authentication.</p>
</li>
<li><p><strong>Extensibility:</strong> SOAP allows for the creation of custom extensions to the protocol to support specific requirements.</p>
</li>
</ol>
<p><strong>Pros:</strong></p>
<ol>
<li><p><strong>Standardization:</strong> SOAP is a well-established and standardized protocol, making it a reliable choice for exchanging data between different systems.</p>
</li>
<li><p><strong>Security:</strong> SOAP provides built-in support for several security standards, making it a secure choice for transmitting sensitive data.</p>
</li>
<li><p><strong>Extensibility:</strong> SOAP is highly extensible and allows for the creation of custom extensions to support specific requirements.</p>
</li>
</ol>
<p><strong>Cons:</strong></p>
<ol>
<li><p><strong>Complexity:</strong> SOAP can be complex to implement and may require specialized expertise.</p>
</li>
<li><p><strong>Overhead:</strong> SOAP messages can be large and can require significant processing resources, resulting in increased overhead.</p>
</li>
<li><p><strong>Performance:</strong> SOAP can be slower compared to other API protocols due to its messaging nature.</p>
</li>
</ol>
<p><strong>Best for:</strong></p>
<ol>
<li><p><strong>When you need to transmit sensitive data:</strong> SOAP supports several security standards, making it a secure choice for transmitting sensitive data.</p>
</li>
<li><p><strong>When you need to support complex data structures:</strong> SOAP supports complex data structures, making it a good choice for transmitting and exchanging data between different systems.</p>
</li>
<li><p><strong>When you need a reliable and standardized protocol:</strong> SOAP is a well-established and standardized protocol, making it a reliable choice for exchanging data between different systems.</p>
</li>
</ol>
<p>SOAP APIs were widely used in the early days of web services and are still used in several industries and sectors today, although REST and GraphQL have become more popular in recent years.</p>
<p>Here are some industries, sectors, and types of applications in which SOAP is still the main option:</p>
<ol>
<li><p><strong>Healthcare:</strong> SOAP is still widely used in healthcare applications, especially in electronic health records (EHR) and health information exchanges (HIE). This is because SOAP provides a secure and reliable way to transmit sensitive patient information between different systems.</p>
</li>
<li><p><strong>Finance:</strong> SOAP is still used in financial applications, such as payment gateways and trading platforms, because it provides a secure and reliable way to transmit financial data.</p>
</li>
<li><p><strong>Enterprise applications:</strong> SOAP is still used in enterprise applications, such as customer relationship management (CRM) and enterprise resource planning (ERP) systems, because it provides a standardized and reliable way to exchange data between different systems.</p>
</li>
<li><p><strong>Legacy systems:</strong> Many older systems and applications still use SOAP APIs, and it can be costly and time-consuming to migrate them to newer technologies.</p>
</li>
</ol>
<p>In conclusion, SOAP APIs have been around for a long time and are still used in several industries to exchange data between different systems.</p>
<p>SOAP might be the most beneficial option for developing an API when you need to transmit sensitive data, support complex data structures, or need a reliable and standardized protocol.</p>
<h2 id="heading-about-xml">About XML</h2>
<p>As mentioned, SOAP APIs use XML as the main format for data transmission, so let's explain how XML works.</p>
<p>XML stands for Extensible Markup Language. It is a markup language that allows users to create custom tags and attributes to describe the structure and content of data.</p>
<p>XML uses a set of rules for encoding documents in a format that is both human-readable and machine-readable. This is achieved by using tags to define elements of a document, similar to HTML.</p>
<p>For example, an XML document may have a tag called <code>&lt;person&gt;</code> to define an element representing a person, with nested tags for properties such as <code>&lt;name&gt;</code>, <code>&lt;age&gt;</code>, and <code>&lt;address&gt;</code>. XML also allows users to define custom tags to describe their data in a way that is specific to their needs.</p>
<p>XML is widely used in various industries, including finance, healthcare, and government. It is often used for data exchange between different applications and systems, as it provides a standardized way of representing data that can be easily parsed by computers. XML is also used for storing configuration files and metadata for various applications.</p>
<p>Overall, XML provides a flexible and extensible way of describing and exchanging data that can be easily processed by computers. However, its use has declined in recent years with the rise of more modern formats such as JSON and YAML, which are more lightweight and easier to use for many applications.</p>
<h2 id="heading-how-to-consume-a-soap-api">How to Consume a SOAP API</h2>
<p>Here's an example of how you can make a simple request to a SOAP API from a JavaScript front-end application:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// specify the URL of the SOAP API endpoint</span>
<span class="hljs-keyword">const</span> url = <span class="hljs-string">'http://www.example.com/soap-api'</span>;

<span class="hljs-comment">// specify the SOAP message to send</span>
<span class="hljs-keyword">const</span> soapMessage = <span class="hljs-string">'&lt;?xml version="1.0" encoding="UTF-8"?&gt;'</span> +
                    <span class="hljs-string">'&lt;SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://example.com"&gt;'</span> +
                    <span class="hljs-string">'&lt;SOAP-ENV:Header/&gt;'</span> +
                    <span class="hljs-string">'&lt;SOAP-ENV:Body&gt;'</span> +
                    <span class="hljs-string">'&lt;ns1:GetData&gt;'</span> +
                    <span class="hljs-string">'&lt;ns1:Id&gt;123&lt;/ns1:Id&gt;'</span> +
                    <span class="hljs-string">'&lt;/ns1:GetData&gt;'</span> +
                    <span class="hljs-string">'&lt;/SOAP-ENV:Body&gt;'</span> +
                    <span class="hljs-string">'&lt;/SOAP-ENV:Envelope&gt;'</span>;

<span class="hljs-comment">// set the content type of the SOAP message</span>
<span class="hljs-keyword">const</span> contentType = <span class="hljs-string">'text/xml'</span>;

<span class="hljs-comment">// make the fetch request</span>
fetch(url, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>, <span class="hljs-comment">// SOAP uses the HTTP POST method to send requests to a server.</span>
  <span class="hljs-attr">headers</span>: {
    <span class="hljs-string">'Content-Type'</span>: contentType,
    <span class="hljs-string">'SOAPAction'</span>: <span class="hljs-string">'http://example.com/GetData'</span>
  },
  <span class="hljs-attr">body</span>: soapMessage
})
  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.text())
  .then(<span class="hljs-function"><span class="hljs-params">xml</span> =&gt;</span> {
    <span class="hljs-comment">// handle the XML response</span>
    <span class="hljs-keyword">const</span> parser = <span class="hljs-keyword">new</span> DOMParser();
    <span class="hljs-keyword">const</span> xmlDoc = parser.parseFromString(xml, <span class="hljs-string">'text/xml'</span>);
    <span class="hljs-keyword">const</span> value = xmlDoc.getElementsByTagName(<span class="hljs-string">'Value'</span>)[<span class="hljs-number">0</span>].childNodes[<span class="hljs-number">0</span>].nodeValue;
    <span class="hljs-built_in">console</span>.log(value);
  })
  .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(error));
</code></pre>
<p>Let's break down what each line does:</p>
<ol>
<li><p><code>const url = 'http://www.example.com/soap-api';</code> specifies the URL of the SOAP API endpoint.</p>
</li>
<li><p><code>const soapMessage = '&lt;?xml version="1.0" encoding="UTF-8"?&gt;' + ...</code> specifies the SOAP message to send to the API endpoint. This is a string that contains the XML markup for the SOAP message.</p>
</li>
<li><p><code>const contentType = 'text/xml';</code> specifies the content type of the SOAP message.</p>
</li>
<li><p><code>fetch(url, { ... })</code> makes a fetch request to the API endpoint using the specified URL and options.</p>
</li>
<li><p><code>method: 'POST',</code> specifies the HTTP method to use for the request.</p>
</li>
<li><p><code>headers: { ... }</code> specifies the headers to include in the request.</p>
</li>
<li><p><code>'Content-Type': contentType,</code> sets the content type of the request header to the value of <code>contentType</code>.</p>
</li>
<li><p><code>'SOAPAction': 'http://example.com/GetData'</code> sets the SOAPAction header to the value of the SOAP action that corresponds to the API method being called.</p>
</li>
<li><p><code>body: soapMessage</code> sets the body of the request to the value of <code>soapMessage</code>.</p>
</li>
<li><p><code>.then(response =&gt; response.text())</code> converts the response to text format.</p>
</li>
<li><p><code>.then(xml =&gt; { ... })</code> handles the response from the server.</p>
</li>
</ol>
<p>A typical response might look like this:</p>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">SOAP-ENV:Envelope</span> <span class="hljs-attr">xmlns:SOAP-ENV</span>=<span class="hljs-string">"http://schemas.xmlsoap.org/soap/envelope/"</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">SOAP-ENV:Body</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ns1:GetDataResponse</span> <span class="hljs-attr">xmlns:ns1</span>=<span class="hljs-string">"http://example.com"</span>&gt;</span>
         <span class="hljs-tag">&lt;<span class="hljs-name">ns1:Result</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ns1:Id</span>&gt;</span>123<span class="hljs-tag">&lt;/<span class="hljs-name">ns1:Id</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ns1:Value</span>&gt;</span>42<span class="hljs-tag">&lt;/<span class="hljs-name">ns1:Value</span>&gt;</span>
         <span class="hljs-tag">&lt;/<span class="hljs-name">ns1:Result</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ns1:GetDataResponse</span>&gt;</span>
   <span class="hljs-tag">&lt;/<span class="hljs-name">SOAP-ENV:Body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">SOAP-ENV:Envelope</span>&gt;</span>
</code></pre>
<p>To access the values in the XML response, you can use the DOMParser API to parse the response into an XML document object, and then use DOM traversal methods to navigate the document and extract the values.</p>
<p>For example, the following code extracts the value of the <code>Value</code> element from the XML document object:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> parser = <span class="hljs-keyword">new</span> DOMParser();
<span class="hljs-keyword">const</span> xmlDoc = parser.parseFromString(xml, <span class="hljs-string">'text/xml'</span>);
<span class="hljs-keyword">const</span> value = xmlDoc.getElementsByTagName(<span class="hljs-string">'Value'</span>)[<span class="hljs-number">0</span>].childNodes[<span class="hljs-number">0</span>].nodeValue;
<span class="hljs-built_in">console</span>.log(value); <span class="hljs-comment">// output: 42</span>
</code></pre>
<p>Here's what each line does:</p>
<ol>
<li><p><code>const parser = new DOMParser();</code> creates a new instance of the DOMParser object, which is used to parse the XML response.</p>
</li>
<li><p><code>const xmlDoc = parser.parseFromString(xml, 'text/xml');</code> parses the XML response into an XML document object.</p>
</li>
<li><p><code>const value = xmlDoc.getElementsByTagName('Value')[0].childNodes[0].nodeValue;</code> retrieves the value of the <code>Value</code> element from the XML document object. This line uses the <code>getElementsByTagName()</code> method to get all elements with the tag name <code>Value</code>, and then accesses the first element (assuming there's only one), and gets the value of its first child node. The value is then assigned to the <code>value</code> variable.</p>
</li>
<li><p><code>console.log(value); // output: 42</code> logs the value of the <code>Value</code> element to the console.</p>
</li>
</ol>
<p>Overall, SOAP responses tend to be more verbose and complex than responses from REST or GraphQL APIs, due to their use of XML and the envelope format. But this format provides a standardized way of exchanging information that can be useful in certain industries and use cases.</p>
<h1 id="heading-how-rest-apis-work">How REST APIs Work</h1>
<p>Representational State Transfer (REST) is a widely used architectural style for building web services and APIs.</p>
<p>REST was first introduced in 2000 by Roy Fielding in his doctoral dissertation, "Architectural Styles and the Design of Network-based Software Architectures." Fielding, who was also one of the primary authors of the HTTP protocol, defined REST as an architectural style that is based on the principles of the web.</p>
<p>RESTful APIs are designed to be simple, scalable, and flexible. They are often used in web and mobile applications, as well as in Internet of Things (IoT) and microservices architectures.</p>
<p><strong>Main Characteristics:</strong></p>
<ol>
<li><p><strong>Stateless:</strong> REST APIs are stateless, which means that each request contains all the necessary information to process it. This makes it easier to scale the API and improves performance by reducing the need to store and manage session data on the server.</p>
</li>
<li><p><strong>Resource-based:</strong> REST APIs are resource-based, which means that each resource is identified by a unique URI (Uniform Resource Identifier) and can be accessed using standard HTTP methods such as GET, POST, PUT, and DELETE.</p>
</li>
<li><p><strong>Uniform Interface:</strong> REST APIs have a uniform interface that allows clients to interact with resources using a standardized set of methods and response formats. This makes it easier for developers to build and maintain APIs, and for clients to consume them.</p>
</li>
<li><p><strong>Cacheable:</strong> REST APIs are cacheable, which means that responses can be cached to improve performance and reduce network traffic.</p>
</li>
<li><p><strong>Layered System:</strong> REST APIs are designed to be layered, which means that intermediaries such as proxies and gateways can be added between the client and server without affecting the overall system.</p>
</li>
</ol>
<p><strong>Pros:</strong></p>
<ul>
<li><p><strong>Easy to learn and use:</strong> REST APIs are relatively simple and easy to learn compared to other APIs.</p>
</li>
<li><p><strong>Scalability:</strong> The stateless nature of REST APIs makes them highly scalable and efficient.</p>
</li>
<li><p><strong>Flexibility:</strong> REST APIs are flexible and can be used to build a wide range of applications and systems.</p>
</li>
<li><p><strong>Wide support:</strong> REST APIs are widely supported by development tools and frameworks, making it easy to integrate them into existing systems.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p><strong>Lack of standards:</strong> The lack of strict standards for REST APIs can lead to inconsistencies and interoperability issues.</p>
</li>
<li><p><strong>Limited functionality:</strong> REST APIs are designed to handle simple requests and responses and may not be suitable for more complex use cases.</p>
</li>
<li><p><strong>Security concerns:</strong> REST APIs can be vulnerable to security attacks such as cross-site scripting (XSS) and cross-site request forgery (CSRF) if not implemented properly.</p>
</li>
</ul>
<p><strong>Best for:</strong></p>
<ul>
<li><p>REST APIs are well-suited for building web and mobile applications, as well as microservices architectures and IoT systems.</p>
</li>
<li><p>They are particularly useful in situations where scalability and flexibility are important, and where developers need to integrate with existing systems and technologies.</p>
</li>
</ul>
<p>In summary, REST APIs are a popular and widely used architectural style for building web services and APIs. They are simple, scalable, and flexible, and can be used to build a wide range of applications and systems.</p>
<p>While there are some limitations and concerns with REST APIs, they remain a popular and effective option for building APIs in many different industries and sectors.</p>
<h2 id="heading-how-to-consume-a-rest-api">How to Consume a REST API</h2>
<p>Here's an example of how to make a simple GET request to a REST API from a JavaScript front-end application, and how to access the values within the response:</p>
<pre><code class="lang-javascript">fetch(<span class="hljs-string">'https://jsonplaceholder.typicode.com/todos/1'</span>)
  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
  .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(data);
    <span class="hljs-comment">// Access the values within the response here</span>
  })
  .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(error));
</code></pre>
<p>Here's what each line does:</p>
<ol>
<li><p><code>fetch('https://jsonplaceholder.typicode.com/todos/1')</code> initiates a GET request to the specified URL.</p>
</li>
<li><p><code>.then(response =&gt; response.json())</code> converts the response from JSON format to a JavaScript object.</p>
</li>
<li><p><code>.then(data =&gt; { ... })</code> defines a function that will be executed when the response has been successfully converted to a JavaScript object. This function will have access to the JavaScript object containing the response data.</p>
</li>
<li><p><code>console.log(data);</code> logs the response data to the console. You can inspect the response data to determine how to access the values within the response.</p>
</li>
</ol>
<p>To access the values within the response, you can use standard JavaScript object traversal techniques, such as dot notation or bracket notation. For example, if the response from the REST API is in the following format:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"userId"</span>: <span class="hljs-number">1</span>,
  <span class="hljs-string">"id"</span>: <span class="hljs-number">1</span>,
  <span class="hljs-string">"title"</span>: <span class="hljs-string">"delectus aut autem"</span>,
  <span class="hljs-string">"completed"</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<p>You can access the <code>title</code> value using dot or bracket notation like this:</p>
<pre><code class="lang-plaintext">console.log(data.title); // output: "delectus aut autem"
console.log(data['title']); // output: "delectus aut autem"
</code></pre>
<p>Here, <code>data</code> refers to the JavaScript object that contains the response data.</p>
<p>REST API responses are generally simpler and more lightweight than SOAP responses, and they are often formatted in either JSON or XML. The use of standard formats makes it easier for clients to parse the response and extract the relevant data.</p>
<p>Additionally, REST APIs often use standard HTTP status codes to indicate the success or failure of a request, which can simplify error handling on the client side.</p>
<p>Overall, REST APIs are a popular and widely used approach to building web APIs due to their simplicity, flexibility, and ease of use.</p>
<h1 id="heading-how-graphql-apis-work">How GraphQL APIs Work</h1>
<p>GraphQL is a query language and runtime for APIs that was developed by Facebook in 2012. It was released to the public in 2015 and has since gained popularity as an alternative to REST APIs.</p>
<p>GraphQL was originally developed by Facebook as a way to simplify data fetching for their mobile applications. They needed a way to make complex data requests from the server without causing performance issues or over-fetching data. GraphQL was born out of the need to solve these problems.</p>
<p>GraphQL was released as an open-source project in 2015 and has since gained popularity in the developer community. It is now supported by many development tools and frameworks, including Apollo, Prisma, and Hasura.</p>
<p><strong>Main Characteristics:</strong></p>
<ol>
<li><p><strong>Strongly Typed:</strong> GraphQL APIs are strongly typed, which means that each field has a specific data type. This makes it easier to validate and handle data on the client and server sides.</p>
</li>
<li><p><strong>Query Language:</strong> GraphQL has its own query language that allows clients to specify exactly what data they need. This reduces over-fetching of data and improves performance.</p>
</li>
<li><p><strong>Single Endpoint:</strong> GraphQL APIs have a single endpoint, which means that clients can fetch all the data they need from a single request.</p>
</li>
<li><p><strong>Declarative:</strong> GraphQL APIs are declarative, which means that clients specify what they want, not how to get it. This allows for more efficient and flexible data fetching.</p>
</li>
<li><p><strong>Schema-Driven:</strong> GraphQL APIs are schema-driven, which means that the schema defines the structure of the data and the available queries and mutations. This makes it easier for developers to understand and work with the API.</p>
</li>
</ol>
<p><strong>Pros:</strong></p>
<ul>
<li><p><strong>Efficient Data Fetching:</strong> GraphQL APIs allow clients to fetch only the data they need, reducing over-fetching and improving performance.</p>
</li>
<li><p><strong>Strongly Typed:</strong> GraphQL APIs are strongly typed, making it easier to validate and handle data.</p>
</li>
<li><p><strong>Single Endpoint:</strong> GraphQL APIs have a single endpoint, reducing the complexity of the API and making it easier to work with.</p>
</li>
<li><p><strong>Schema-Driven:</strong> GraphQL APIs are schema-driven, which makes it easier for developers to understand and work with the API.</p>
</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><p><strong>Complexity:</strong> GraphQL APIs can be more complex to set up and work with compared to REST APIs.</p>
</li>
<li><p><strong>Caching:</strong> Caching can be more challenging with GraphQL APIs due to the flexible nature of the API.</p>
</li>
<li><p><strong>Learning Curve:</strong> GraphQL requires a learning curve for both developers and clients, as it has its own query language and approach to data fetching.</p>
</li>
</ul>
<p><strong>Best for:</strong></p>
<ul>
<li><p><strong>Efficient and flexible needs:</strong> GraphQL is well-suited for building applications that require efficient and flexible data fetching, such as mobile and web applications.</p>
</li>
<li><p><strong>Complex data requirements:</strong> It is particularly useful in situations where there are complex data requirements and where over-fetching data can cause performance issues.</p>
</li>
</ul>
<p>In conclusion, GraphQL is a query language and runtime for APIs that provides efficient and flexible data fetching capabilities.</p>
<p>While it can be more complex to set up and work with compared to REST APIs, it offers benefits such as strongly typed data, single endpoints, and schema-driven development. It is well-suited for building applications with complex data requirements and where efficient data fetching is important.</p>
<h2 id="heading-how-to-consume-a-graphql-api">How to Consume a GraphQL API</h2>
<p>Here's an example of how to make a simple request to retrieve information from a GraphQL API from a JavaScript front-end application, and how to access the values within the response:</p>
<pre><code class="lang-javascript">fetch(<span class="hljs-string">'https://api.example.com/graphql'</span>, {
  <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
  <span class="hljs-attr">headers</span>: { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span> },
  <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
    <span class="hljs-attr">query</span>: <span class="hljs-string">`
      query {
        user(id: 123) {
          name
          email
          posts {
            title
          }
        }
      }
    `</span>
  })
})
.then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> response.json())
.then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(data);
  <span class="hljs-comment">// Access the values within the response here</span>
})
.catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> <span class="hljs-built_in">console</span>.error(error));
</code></pre>
<p>Here's what each line does:</p>
<ol>
<li><p><code>fetch('https://api.example.com/graphql', { ... })</code> initiates a POST request to the specified GraphQL API endpoint. The second argument to the <code>fetch()</code> function is an options object that specifies the HTTP method, headers, and request body.</p>
</li>
<li><p><code>method: 'POST'</code> specifies that the HTTP method for the request is <code>POST</code>.</p>
</li>
<li><p><code>headers: { 'Content-Type': 'application/json' }</code> specifies the <code>Content-Type</code> header for the request, which is <code>application/json</code> to indicate that the request body is in JSON format.</p>
</li>
<li><p><code>body: JSON.stringify({ ... })</code> specifies the request body as a JSON-encoded string. In this example, the request body is a GraphQL query that retrieves information about a user with the ID <code>123</code>.</p>
</li>
<li><p><code>.then(response =&gt; response.json())</code> converts the response from JSON format to a JavaScript object.</p>
</li>
<li><p><code>.then(data =&gt; { ... })</code> defines a function that will be executed when the response has been successfully converted to a JavaScript object. This function will have access to the JavaScript object containing the response data.</p>
</li>
<li><p><code>console.log(data);</code> logs the response data to the console. You can inspect the response data to determine how to access the values within the response.</p>
</li>
</ol>
<p>To access the values within the response, you can use standard JavaScript object traversal techniques, such as dot notation or bracket notation. For example, if the response from the GraphQL API is in the following format:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"data"</span>: {
    <span class="hljs-string">"user"</span>: {
      <span class="hljs-string">"name"</span>: <span class="hljs-string">"John Doe"</span>,
      <span class="hljs-string">"email"</span>: <span class="hljs-string">"john.doe@example.com"</span>,
      <span class="hljs-string">"posts"</span>: [
        { <span class="hljs-string">"title"</span>: <span class="hljs-string">"Post 1"</span> },
        { <span class="hljs-string">"title"</span>: <span class="hljs-string">"Post 2"</span> }
      ]
    }
  }
}
</code></pre>
<p>You can access the <code>name</code> value using dot or bracket notation like this:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">console</span>.log(data.data.user.name); <span class="hljs-comment">// output: "John Doe"</span>
<span class="hljs-built_in">console</span>.log(data[<span class="hljs-string">'data'</span>][<span class="hljs-string">'user'</span>][<span class="hljs-string">'name'</span>]); <span class="hljs-comment">// output: "John Doe"</span>
</code></pre>
<p>Here, <code>data</code> refers to the JavaScript object that contains the response data. The response data is wrapped in a <code>data</code> object, and the values can be accessed by traversing the object using dot notation or bracket notation.</p>
<p>GraphQL API responses are typically more focused and specific than REST API responses because the client can specify exactly what data they want to receive. This makes it easier to avoid overfetching or underfetching data, and can improve performance by reducing the amount of data transferred over the network.</p>
<p>Additionally, GraphQL APIs can provide a more flexible schema that can be easily modified over time without breaking existing clients. Overall, GraphQL APIs are a popular choice for building modern web applications due to their flexibility, efficiency, and ease of use.</p>
<h1 id="heading-wrapping-up"><strong>Wrapping Up</strong></h1>
<p>Well everyone, as always, I hope you enjoyed the article and learned something new.</p>
<p>If you want, you can also follow me on <a target="_blank" href="https://www.linkedin.com/in/germancocca/">LinkedIn</a> or <a target="_blank" href="https://twitter.com/CoccaGerman">Twitter</a>. See you in the next one!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/giphy.gif" alt="Image" width="600" height="400" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use TypeScript with GraphQL using TypeGraphQL ]]>
                </title>
                <description>
                    <![CDATA[ By Dillion Megida In this tutorial, I'll explain what TypeScript and GraphQL are, and the benefits of using them. Then I'll show you how you can use them together using TypeGrapQL, and why you'd want to do this. What is TypeScript? TypeScript is a su... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-typescript-with-graphql/</link>
                <guid isPermaLink="false">66d84f234540581f645440f1</guid>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 13 Apr 2022 00:18:19 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/pexels-reagan-787642.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Dillion Megida</p>
<p>In this tutorial, I'll explain what TypeScript and GraphQL are, and the benefits of using them.</p>
<p>Then I'll show you how you can use them together using TypeGrapQL, and why you'd want to do this.</p>
<h2 id="heading-what-is-typescript">What is TypeScript?</h2>
<p>TypeScript is a superset of JavaScript that compiles to JavaScript for production. It's like JavaScript, but with powers – type powers.</p>
<p>TypeScript helps you build typed applications that help you avoid static type errors in those apps and make predictable code. </p>
<p>Without TypeScript, a function declared to receive a string typed argument may receive a number typed argument during execution, and you may get a runtime error. This can be bad for production code.</p>
<p>With TypeScript, such a function will result in a compile-time error unless the appropriate type is passed.</p>
<p>TypeScript can handle more than primitive types. It can also ensure that correct, expected, structured objects are typed. This means a missing object property can also result in an error.</p>
<p>TypeScript helps us build more predictable JavaScript code during development through type-checking. It is also integrated into editors like VSCode, which makes it easier to spot type errors while writing code.</p>
<p>TypeScript takes an extra step to compile to JavaScript for use. While some libraries like React do this internally for you, you may have to set it up yourself if you're building without such tools. But I'd say it is worth it.</p>
<h2 id="heading-what-is-graphql">What is GraphQL?</h2>
<p>GraphQL is another method for managing APIs. It's an alternative to Rest APIs that allows you to request "only the data you need". This helps reduce the amount of data that needs to be sent to the client from the server.</p>
<p>For example, with a Rest API, an endpoint may return all users' data when only their email and phone number are needed at that point. This is termed "over-fetching". With GraphQL, the client can request such specific data.</p>
<p>GraphQL also comes with type definitions, which exist in schema objects. GraphQL uses Schema objects to know what properties are query-able, and basically, the type of queries that are accepted. It also throws an error when an unaccepted query is executed.</p>
<p>However, these type definitions to limited to schema objects. They do not give you overall static typing in your application. And that's why TypeScript is an excellent addition, as we'll see in the rest of this article.</p>
<h2 id="heading-advantages-of-using-typescript-and-graphql">Advantages of Using TypeScript and GraphQL</h2>
<p>Using TypeScript and GraphQL ensures that static typing exists all through your application.</p>
<p>Without TypeScript, you can still create query types with GraphQL. But there's a limitation to this.</p>
<p>GraphQL types only exist in the GraphQL schema. The <code>buildSchema</code> function from the GraphQL library is used to create the schema object:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> schema = buildSchema(<span class="hljs-string">`
    type Query {
        name(firstname: String!, lastname: String!): String
    }
`</span>)
</code></pre>
<p>We've created the schema object, and now we need a resolver:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> root = {
    <span class="hljs-attr">name</span>: <span class="hljs-function"><span class="hljs-params">variables</span> =&gt;</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-string">`My name is <span class="hljs-subst">${firstname}</span> <span class="hljs-subst">${lastname}</span>!`</span>
    },
}
</code></pre>
<p>On executing the query with wrongly typed variables in a GraphQL playground, we would get errors:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>GraphQL playground showing error for wrong type provided to query</em></p>
<p>But the resolvers are not aware of the type definition in the schema object. As you can see, the resolver is a regular JavaScript function. This means, we don't get static typing in the resolver. </p>
<p>Say, for example, we provide the wrong argument types to the resolver, or we return a different type from the resolver that the schema did not expect. We may introduce bugs to our code without knowing it.</p>
<p>And this is why TypeScript is beneficial. With TypeScript, we have type definitions in the schema object and in the resolvers, thereby synchronizing both of them and making our code much more predictable.</p>
<h2 id="heading-how-to-use-typescript-and-graphql">How to Use TypeScript and GraphQL</h2>
<p>In this section, we'll be using TypeScript and GraphQL to create a simple GraphQL API on an Express server.</p>
<h3 id="heading-step-1-create-a-project-folder">Step 1: Create a project folder</h3>
<p>You can name it whatever you want, but we'll be using the <code>graphql-ts-example</code> folder for this tutorial:</p>
<pre><code class="lang-bash">mkdir graphql-ts-example
<span class="hljs-built_in">cd</span> graphql-ts-example
npm init -y
</code></pre>
<h3 id="heading-step-2-install-dependencies">Step 2: Install dependencies</h3>
<p>We'll use the following dependencies for this tutorial:</p>
<ul>
<li><a target="_blank" href="https://www.npmjs.com/package/graphql">graphql</a>: the JavaScript library for GraphQL</li>
<li><a target="_blank" href="https://www.npmjs.com/package/express">express</a>: a web framework for Node that allows us to create APIs and a backend server</li>
<li><a target="_blank" href="https://www.npmjs.com/package/express-graphql">express-graphql</a>: for creating a GraphQL server for the APIs</li>
<li><a target="_blank" href="https://www.npmjs.com/package/ts-node">ts-node</a>: for executing TypeScript code in Node</li>
<li><a target="_blank" href="https://www.npmjs.com/package/typescript">typescript</a>: for compiling TypeScript code to JavaScript</li>
<li><a target="_blank" href="https://www.npmjs.com/package/@types/express">@types/express</a>: for using Express in TypeScript</li>
<li><a target="_blank" href="https://www.npmjs.com/package/nodemon">nodemon</a>: for restarting the server when changes are made</li>
</ul>
<p>In your terminal, run:</p>
<pre><code class="lang-bash">npm install graphql express express-graphql
npm install -D nodemon ts-node @types/express typescript
</code></pre>
<p>For testing our API, we'll be using the GraphQL playground provided by express-graphql.</p>
<h3 id="heading-step-3-setting-up-our-scripts">Step 3: Setting up our scripts</h3>
<p>In <code>package.json</code>, update the <code>scripts</code> object to this:</p>
<pre><code class="lang-json"><span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"nodemon --exec ts-node src/index.ts"</span>,
}
</code></pre>
<p>Also, add a configuration file for TypeScript, <code>tsconfig.json</code>:</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"compilerOptions"</span>: {
        <span class="hljs-attr">"target"</span>: <span class="hljs-string">"es2018"</span>,
        <span class="hljs-attr">"module"</span>: <span class="hljs-string">"commonjs"</span>,
        <span class="hljs-attr">"jsx"</span>: <span class="hljs-string">"preserve"</span>,
        <span class="hljs-attr">"strict"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">"esModuleInterop"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">"lib"</span>: [<span class="hljs-string">"es2018"</span>, <span class="hljs-string">"esnext.asynciterable"</span>]
    },
    <span class="hljs-attr">"exclude"</span>: [<span class="hljs-string">"node_modules"</span>]
}
</code></pre>
<p>With this, we can run our server with <code>npm start</code>.</p>
<h3 id="heading-step-4-write-the-code">Step 4: Write the code</h3>
<p>We'll create an Express server with a GraphQL API that allows us to fetch users, create a user, and update a user's data.</p>
<p>Create a new directory called "src" and add the <code>index.ts</code> file into it. We have our imports in the file as follows:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { buildSchema } <span class="hljs-keyword">from</span> <span class="hljs-string">"graphql"</span>
<span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">"express"</span>
<span class="hljs-keyword">import</span> { graphqlHTTP } <span class="hljs-keyword">from</span> <span class="hljs-string">"express-graphql"</span>
</code></pre>
<p>Then we need our users list. Ideally, this would come from a database, but we'll hardcode it here:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> users = [
    { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"John Doe"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"johndoe@gmail.com"</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"Jane Doe"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"janedoe@gmail.com"</span> },
    { <span class="hljs-attr">id</span>: <span class="hljs-number">3</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"Mike Doe"</span>, <span class="hljs-attr">email</span>: <span class="hljs-string">"mikedoe@gmail.com"</span> },
]
</code></pre>
<p>Next, we build the GraphQL schema:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> schema = buildSchema(<span class="hljs-string">`
    input UserInput {
        email: String!
        name: String!

    }

    type User {
        id: Int!
        name: String!
        email: String!
    }

    type Mutation {
        createUser(input: UserInput): User
        updateUser(id: Int!, input: UserInput): User
    }

    type Query {
        getUser(id: String): User
        getUsers: [User]
    }
`</span>)
</code></pre>
<p>From our schema, we've defined:</p>
<ul>
<li>a user input with two required properties, which is required when creating a user</li>
<li>a user type with three required properties</li>
<li>a GraphQL mutation where we create users and update users</li>
<li>and a GraphQL query for getting a particular user or all users.</li>
</ul>
<p>Now, we need to define our TypeScript types for static typing:</p>
<pre><code class="lang-ts">
<span class="hljs-keyword">type</span> User = {
    id: <span class="hljs-built_in">number</span>
    name: <span class="hljs-built_in">string</span>
    email: <span class="hljs-built_in">string</span>
}

<span class="hljs-keyword">type</span> UserInput = Pick&lt;User, <span class="hljs-string">"email"</span> | <span class="hljs-string">"name"</span>&gt;
</code></pre>
<p>Next, our resolvers:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> getUser = (args: { id: <span class="hljs-built_in">number</span> }): User | <span class="hljs-function"><span class="hljs-params">undefined</span> =&gt;</span>
    users.find(<span class="hljs-function"><span class="hljs-params">u</span> =&gt;</span> u.id === args.id)

<span class="hljs-keyword">const</span> getUsers = (): User[] =&gt; users

<span class="hljs-keyword">const</span> createUser = (args: { input: UserInput }): <span class="hljs-function"><span class="hljs-params">User</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> user = {
        id: users.length + <span class="hljs-number">1</span>,
        ...args.input,
    }
    users.push(user)

    <span class="hljs-keyword">return</span> user
}

<span class="hljs-keyword">const</span> updateUser = (args: { user: User }): <span class="hljs-function"><span class="hljs-params">User</span> =&gt;</span> {
    <span class="hljs-keyword">const</span> index = users.findIndex(<span class="hljs-function"><span class="hljs-params">u</span> =&gt;</span> u.id === args.user.id)
    <span class="hljs-keyword">const</span> targetUser = users[index]

    <span class="hljs-keyword">if</span> (targetUser) users[index] = args.user

    <span class="hljs-keyword">return</span> targetUser
}

<span class="hljs-keyword">const</span> root = {
    getUser,
    getUsers,
    createUser,
    updateUser,
}
</code></pre>
<p>And finally, our Express route and server:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">const</span> app = express()

app.use(
    <span class="hljs-string">"/graphql"</span>,
    graphqlHTTP({
        schema: schema,
        rootValue: root,
        graphiql: <span class="hljs-literal">true</span>,
    })
)

<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">8000</span>

app.listen(PORT)

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Running a GraphQL API server at http://localhost:<span class="hljs-subst">${PORT}</span>/graphql`</span>)
</code></pre>
<p>With what we have above, our resolvers are typed following the schema definition. This way, our resolvers are in sync. On <code>localhost:4000/graphql</code>, we can see the GraphQL playground:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-5.png" alt="Image" width="600" height="400" loading="lazy">
<em>GraphQL playground showing working queries</em></p>
<p>Although we can see how beneficial TypeScript is, we also cannot deny the hassle of writing type definitions after creating a schema object. </p>
<p>This codebase is small, so that can be easier, but imagine something big, with many resolvers and having to create type definitions for each one 😩</p>
<p>We need a better way of doing this. We need something that allows us to create type definitions in one place, as the main source of truth, and then use them in our resolvers and schema objects.</p>
<h2 id="heading-how-to-use-typegraphql-to-improve-your-typed-graphql">How to Use TypeGraphQL to Improve Your Typed GraphQL</h2>
<p>The goal of <a target="_blank" href="https://typegraphql.com/">TypeGraphQL</a> is to make it seamless to enjoy static typing in your resolvers and create your schemas from one place. </p>
<p>It comes with its syntax, which is another learning process. But it's not so steep – it's a step in the right direction.</p>
<p>Let's improve our codebase by using TypeGraphQL.</p>
<p>We'd need a couple of dependencies:</p>
<ul>
<li><a target="_blank" href="https://www.npmjs.com/package/class-validator">class-validator</a>: allows the use of <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/decorators.html">decorators</a> for validation</li>
<li><a target="_blank" href="https://www.npmjs.com/package/type-graphql">type-graphql</a>: the TypeGraphQL library itself, that allows you to create schemas and resolvers with TypeSCript, using classes and decorators</li>
<li><a target="_blank" href="https://www.npmjs.com/package/reflect-metadata">reflect-metadata</a>: for runtime reflection of types (learn more about this here: <a target="_blank" href="http://blog.wolksoftware.com/decorators-metadata-reflection-in-typescript-from-novice-to-expert-part-4">Metadata reflection in TypeScript</a>)</li>
</ul>
<p>In your terminal, run:</p>
<pre><code class="lang-bash">npm install class-validator type-graphql reflect-metadata
</code></pre>
<p>In your <code>tsconfig.json</code>, add the following to the <code>compilerOptions</code> object:</p>
<pre><code class="lang-json"><span class="hljs-string">"compilerOptions"</span>: {
    <span class="hljs-comment">// ...</span>
    <span class="hljs-attr">"emitDecoratorMetadata"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">"experimentalDecorators"</span>: <span class="hljs-literal">true</span>,
}
</code></pre>
<p>These are important so that TypeScript doesn't complain about the use of decorators. They are still in experimental mode.</p>
<p>Now, let's update our codebase using TypeGraphQL. Create a new directory called "users". In it, we'll have the schema and resolvers.</p>
<p>Create a new file in "users" called "users.schema.ts":</p>
<pre><code class="lang-ts"><span class="hljs-comment">// users.schema.ts</span>

<span class="hljs-keyword">import</span> { Field, ObjectType, InputType } <span class="hljs-keyword">from</span> <span class="hljs-string">"type-graphql"</span>

<span class="hljs-meta">@ObjectType</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> User {
    <span class="hljs-meta">@Field</span>()
    id!: <span class="hljs-built_in">number</span>
    <span class="hljs-meta">@Field</span>()
    name!: <span class="hljs-built_in">string</span>
    <span class="hljs-meta">@Field</span>()
    email!: <span class="hljs-built_in">string</span>
}

<span class="hljs-meta">@InputType</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UserInput <span class="hljs-keyword">implements</span> Pick&lt;User, <span class="hljs-string">"name"</span> | <span class="hljs-string">"email"</span>&gt; {
    <span class="hljs-meta">@Field</span>()
    name!: <span class="hljs-built_in">string</span>
    <span class="hljs-meta">@Field</span>()
    email!: <span class="hljs-built_in">string</span>
}
</code></pre>
<p>First, we have the <code>User</code> class, which is decorated with the <code>ObjectType</code> decorator. This tells GraphQL that this class is a GraphQL type. In GraphQL, this is interpreted as:</p>
<pre><code class="lang-ts">buildSchema(<span class="hljs-string">`
    type User {
        id: Int!
        name: String!
        email: String!
    }

    input UserInput {
        name: String!
        email: String!
    }
`</span>)
</code></pre>
<p>Next, our resolvers. Create a <code>users.resolvers.ts</code> file in the "users" directory:</p>
<pre><code class="lang-ts">
<span class="hljs-comment">// users.resolvers.ts</span>

<span class="hljs-keyword">import</span> { Query, Resolver, Mutation, Arg } <span class="hljs-keyword">from</span> <span class="hljs-string">"type-graphql"</span>
<span class="hljs-keyword">import</span> { UserInput, User } <span class="hljs-keyword">from</span> <span class="hljs-string">"./users.schema"</span>

<span class="hljs-meta">@Resolver</span>(<span class="hljs-function">() =&gt;</span> User)
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> UsersResolver {
    <span class="hljs-keyword">private</span> users: User[] = [
        { id: <span class="hljs-number">1</span>, name: <span class="hljs-string">"John Doe"</span>, email: <span class="hljs-string">"johndoe@gmail.com"</span> },
        { id: <span class="hljs-number">2</span>, name: <span class="hljs-string">"Jane Doe"</span>, email: <span class="hljs-string">"janedoe@gmail.com"</span> },
        { id: <span class="hljs-number">3</span>, name: <span class="hljs-string">"Mike Doe"</span>, email: <span class="hljs-string">"mikedoe@gmail.com"</span> },
    ]

    <span class="hljs-meta">@Query</span>(<span class="hljs-function">() =&gt;</span> [User])
    <span class="hljs-keyword">async</span> getUsers(): <span class="hljs-built_in">Promise</span>&lt;User[]&gt; {
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.users
    }

    <span class="hljs-meta">@Query</span>(<span class="hljs-function">() =&gt;</span> User)
    <span class="hljs-keyword">async</span> getUser(<span class="hljs-meta">@Arg</span>(<span class="hljs-string">"id"</span>) id: <span class="hljs-built_in">number</span>): <span class="hljs-built_in">Promise</span>&lt;User | <span class="hljs-literal">undefined</span>&gt; {
        <span class="hljs-keyword">const</span> user = <span class="hljs-built_in">this</span>.users.find(<span class="hljs-function"><span class="hljs-params">u</span> =&gt;</span> u.id === id)
        <span class="hljs-keyword">return</span> user
    }

    <span class="hljs-meta">@Mutation</span>(<span class="hljs-function">() =&gt;</span> User)
    <span class="hljs-keyword">async</span> createUser(<span class="hljs-meta">@Arg</span>(<span class="hljs-string">"input"</span>) input: UserInput): <span class="hljs-built_in">Promise</span>&lt;User&gt; {
        <span class="hljs-keyword">const</span> user = {
            id: <span class="hljs-built_in">this</span>.users.length + <span class="hljs-number">1</span>,
            ...input,
        }

        <span class="hljs-built_in">this</span>.users.push(user)
        <span class="hljs-keyword">return</span> user
    }

    <span class="hljs-meta">@Mutation</span>(<span class="hljs-function">() =&gt;</span> User)
    <span class="hljs-keyword">async</span> updateUser(
        <span class="hljs-meta">@Arg</span>(<span class="hljs-string">"id"</span>) id: <span class="hljs-built_in">number</span>,
        <span class="hljs-meta">@Arg</span>(<span class="hljs-string">"input"</span>) input: UserInput
    ): <span class="hljs-built_in">Promise</span>&lt;User&gt; {
        <span class="hljs-keyword">const</span> user = <span class="hljs-built_in">this</span>.users.find(<span class="hljs-function"><span class="hljs-params">u</span> =&gt;</span> u.id === id)

        <span class="hljs-keyword">if</span> (!user) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"User not found"</span>)
        }

        <span class="hljs-keyword">const</span> updatedUser = {
            ...user,
            ...input,
        }

        <span class="hljs-built_in">this</span>.users = <span class="hljs-built_in">this</span>.users.map(<span class="hljs-function"><span class="hljs-params">u</span> =&gt;</span> (u.id === id ? updatedUser : u))

        <span class="hljs-keyword">return</span> updatedUser
    }
}
</code></pre>
<p>There are a few decorators to take note of here:</p>
<ul>
<li>there's the <code>Resolver</code> decorator, which decorates the class as an object with many query and mutation resolve methods. The beauty here is we're defining the queries and mutations and the resolve methods in the same class.</li>
<li>there's the <code>Query</code> decorator, which tells GraphQL that this is a query and the respective resolve method</li>
<li>there's the <code>Mutation</code> decorator, which tells GraphQL that this is a mutation and the respective resolve method</li>
<li>there's the <code>Arg</code> decorator, which tells GraphQL that this argument is a GraphQL argument for the resolver.</li>
</ul>
<p>As you'll notice, without creating a type definition for the <code>User</code> object, we could simply use the class exported from the schema file.</p>
<p>The above code will be interpreted to GraphQL as:</p>
<pre><code class="lang-ts">buildSchema(<span class="hljs-string">`
    type Query {
        getUsers: [User]
        getUser(id: Int!): User
    }

    type Mutation {
        createUser(input: UserInput): User
        updateUser(id: Int!, input: UserInput): User
    }
`</span>)

<span class="hljs-comment">// resolvers</span>
</code></pre>
<p>Back in <code>src/index.ts</code>, here's what the code looks like:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> <span class="hljs-string">"reflect-metadata"</span>
<span class="hljs-keyword">import</span> { buildSchema } <span class="hljs-keyword">from</span> <span class="hljs-string">"type-graphql"</span>
<span class="hljs-keyword">import</span> express <span class="hljs-keyword">from</span> <span class="hljs-string">"express"</span>
<span class="hljs-keyword">import</span> { graphqlHTTP } <span class="hljs-keyword">from</span> <span class="hljs-string">"express-graphql"</span>

<span class="hljs-keyword">import</span> { UsersResolver } <span class="hljs-keyword">from</span> <span class="hljs-string">"./users/users.resolver"</span>

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">main</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> schema = <span class="hljs-keyword">await</span> buildSchema({
        resolvers: [UsersResolver],
        emitSchemaFile: <span class="hljs-literal">true</span>,
    })

    <span class="hljs-keyword">const</span> app = express()

    app.use(
        <span class="hljs-string">"/graphql"</span>,
        graphqlHTTP({
            schema: schema,
            graphiql: <span class="hljs-literal">true</span>,
        })
    )

    app.listen(<span class="hljs-number">8000</span>)

    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Running a GraphQL API server at http://localhost:8000/graphql"</span>)
}

main()
</code></pre>
<p>The <code>buildSchema</code> function comes from the <code>type-graphql</code> library this time around. Back in the GraphQL playground, our queries work as expected:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-6.png" alt="Image" width="600" height="400" loading="lazy">
<em>GraphQL playground showing GraphQL mutation for creating user</em></p>
<p>Here's the GitHub repository for this project: <a target="_blank" href="https://github.com/dillionmegida/graphql-typescript-example">graphql-typescript-example</a></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this article, we've learnt what GraphQL and TypeScript are, and seen the limitations of using GraphQL without TypeScript. </p>
<p>We've also seen a beautiful way to use GraphQL and TypeScript together – TypeGraphQL.</p>
<p>If you found this helpful, kindly share it with others : )</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ GraphQL vs REST API – Which Should You Use for Back End API Development? ]]>
                </title>
                <description>
                    <![CDATA[ By Aagam Vadecha REST and GraphQL are both standard ways to develop backend APIs. But over the past decade REST APIs have dominated as a choice for developing backend API's. And many companies and developers use it actively in their projects.    But ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/graphql-vs-rest-api/</link>
                <guid isPermaLink="false">66d45d5951f567b42d9f8409</guid>
                
                    <category>
                        <![CDATA[ Back end development  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ REST API ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 25 Oct 2021 15:02:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/08/landing.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Aagam Vadecha</p>
<p>REST and GraphQL are both standard ways to develop backend APIs. But over the past decade REST APIs have dominated as a choice for developing backend API's. And many companies and developers use it actively in their projects.   </p>
<p>But REST has some limitations, and there's another alternative available – GraphQL. GraphQL is a great choice for developing APIs in large codebases.</p>
<h2 id="heading-what-is-graphql">What is GraphQL?</h2>
<p><a target="_blank" href="https://graphql.org/">GraphQL</a> was developed by Facebook in 2012 for internal usage and made public in 2015. It is a query language for APIs and a runtime for fulfilling those queries with your existing data. Many companies <a target="_blank" href="https://graphql.org/users/.">use it in production</a>. </p>
<p>The official website introduces GraphQL like this:</p>
<blockquote>
<p>GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.</p>
</blockquote>
<p>And we'll see how all this works in this blog.</p>
<h2 id="heading-issues-with-rest-apis">Issues With REST APIs</h2>
<ul>
<li>Querying Multiple Endpoints</li>
<li>OverFetching</li>
<li>UnderFetching and n+1 Request Problem</li>
<li>Not super fast to cope up with changing client end requirements</li>
<li>High Coupling between Backend Controllers and Frontend Views</li>
</ul>
<p>So, what are these issues and how does GraphQL solve them? Well, we'll learn more going forward. But first we'll need to make sure you're comfortable with the <a target="_blank" href="https://graphql.org/learn/">basic</a> concepts of GraphQL like the type system, schema, queries, mutations, and so on.</p>
<p>Now we'll look at some examples to better understand the disadvantages of using REST APIs.</p>
<h3 id="heading-overfetching">Overfetching</h3>
<p>Let's assume that we need to show this User Card in the UI. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/UserCard-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>With REST, the request is going to be a <strong>GET</strong> at <code>/users/1</code>.</p>
<p>The problem here is that the server returns a fixed data-structure, something like this:</p>
<pre><code class="lang-javascript">{
    <span class="hljs-string">"_id"</span>: <span class="hljs-string">"1"</span>,
    <span class="hljs-string">"name"</span>: <span class="hljs-string">"Aagam Vadecha"</span>,
    <span class="hljs-string">"username"</span>: <span class="hljs-string">"aagam"</span>,
    <span class="hljs-string">"email"</span>: <span class="hljs-string">"testemail@gmail.com"</span>,
    <span class="hljs-string">"currentJobTitle"</span>: <span class="hljs-string">"Software Engineer"</span>,
    <span class="hljs-string">"phone"</span>: <span class="hljs-string">"9876543210"</span>,
    <span class="hljs-string">"intro"</span>: <span class="hljs-string">"As a software engineer my daily routine revolves around writing cleancode, maintaining infrastructure, and building scalable softwaresystems. In my free time I love to write tech blogs, freelance, listenmusic, and watch thrillers."</span>,
    <span class="hljs-string">"website"</span>: <span class="hljs-string">"https://www.aagam.tech"</span>,
    <span class="hljs-string">"gender"</span>: <span class="hljs-string">"MALE"</span>,
    <span class="hljs-string">"city"</span>: <span class="hljs-string">"Surat"</span>,
    <span class="hljs-string">"state"</span>: <span class="hljs-string">"Gujarat"</span>,
    <span class="hljs-string">"country"</span>: <span class="hljs-string">"India"</span>,
    <span class="hljs-string">"display_picture"</span>: <span class="hljs-string">"8ba58af0-1212-4938-8b4a-t3m9c4371952"</span>,
    <span class="hljs-string">"phone_verified"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"email_verified"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"_created_at"</span>: <span class="hljs-string">"2021-03-08T14:13:41Z"</span>,
    <span class="hljs-string">"_updated_at"</span>: <span class="hljs-string">"2021-03-08T14:13:41Z"</span>,
    <span class="hljs-string">"_deleted"</span>: <span class="hljs-literal">false</span>
}
</code></pre>
<p>The server returns extra data (aside from the Name, Intro, and Job Designation) which is not required at the client-end to build the card at this point – but the response still has it. This is called <strong>overfetching</strong>.   </p>
<p>Overfetching brings extra data in each request which is not required by the client. And this increases the payload size and eventually that has an effect on the overall response time of the query. </p>
<p>What's worse, the situation escalates when a query is bringing data from multiple tables even though the client doesn't require it right then. So if we can avoid it, we definitely should</p>
<p>With GraphQL, the query inside the request body would look something like this: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-33.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>It will only return the <code>name</code>, <code>intro</code>, and <code>currentJobTitle</code> as required by the client, so the overfetching problem is solved.</p>
<h3 id="heading-underfetching-and-the-n1-request-problem">Underfetching and the n+1 request problem</h3>
<p>Now let's assume this UserList needs to be shown in the UI.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-46.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>With REST, considering "experience" is a table which has a foreign key of user_id, there are three possible options</p>
<ol>
<li>One is to send some exact fixed data-structure from all foreign-key linked tables to the users table in the GET /users request, and many frameworks provide this option.  </li>
</ol>
<pre><code class="lang-javascript">{
    <span class="hljs-string">"_id"</span>: <span class="hljs-string">"1"</span>,
    <span class="hljs-string">"name"</span>: <span class="hljs-string">"Aagam Vadecha"</span>,
    <span class="hljs-string">"username"</span>: <span class="hljs-string">"aagam"</span>,
    <span class="hljs-string">"email"</span>: <span class="hljs-string">"testemail@gmail.com"</span>,
    <span class="hljs-string">"currentJobTitle"</span>: <span class="hljs-string">"Software Engineer"</span>,
    <span class="hljs-string">"phone"</span>: <span class="hljs-string">"9876543210"</span>,
    <span class="hljs-string">"intro"</span>: <span class="hljs-string">"As a software engineer my daily routine revolves around writing cleancode, maintaining infrastructure, and building scalable softwaresystems. In my free time I love to write tech blogs, freelance, listenmusic, and watch thrillers."</span>,
    <span class="hljs-string">"website"</span>: <span class="hljs-string">"https://www.aagam.tech"</span>,
    <span class="hljs-string">"gender"</span>: <span class="hljs-string">"MALE"</span>,
    <span class="hljs-string">"city"</span>: <span class="hljs-string">"Surat"</span>,
    <span class="hljs-string">"state"</span>: <span class="hljs-string">"Gujarat"</span>,
    <span class="hljs-string">"country"</span>: <span class="hljs-string">"India"</span>,
    <span class="hljs-string">"display_picture"</span>: <span class="hljs-string">"8ba58af0-1212-4938-8b4a-t3m9c4371952"</span>,
    <span class="hljs-string">"phone_verified"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"email_verified"</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-string">"_created_at"</span>: <span class="hljs-string">"2021-03-08T14:13:41Z"</span>,
    <span class="hljs-string">"_updated_at"</span>: <span class="hljs-string">"2021-03-08T14:13:41Z"</span>,
    <span class="hljs-string">"_deleted"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-string">"experience"</span>: [
        {
            <span class="hljs-string">"organizationName"</span>: <span class="hljs-string">"Bharat Tech Labs"</span>,
            <span class="hljs-string">"jobTitle"</span>: <span class="hljs-string">"Software Engineer"</span>,
            <span class="hljs-string">"totalDuration"</span>: <span class="hljs-string">"1 Year"</span>
        }
    ],
    <span class="hljs-string">"address"</span>: [
        {
            <span class="hljs-string">"street"</span>: <span class="hljs-string">"Kulas Light"</span>,
            <span class="hljs-string">"suite"</span>: <span class="hljs-string">"Apt. 556"</span>,
            <span class="hljs-string">"city"</span>: <span class="hljs-string">"Gwenborough"</span>,
            <span class="hljs-string">"zipcode"</span>: <span class="hljs-string">"929983874"</span>,
            <span class="hljs-string">"geo"</span>: {
                <span class="hljs-string">"lat"</span>: <span class="hljs-string">"-37,3159"</span>,
                <span class="hljs-string">"lng"</span>: <span class="hljs-string">"81.1496"</span>
            }
        }
    ]
}
</code></pre>
<p>But this method makes expensive queries, overfetches all other /users requests as well, and ends up bringing back a lot of data from all foreign tables (address, experience) which is not required in most cases. </p>
<p>For example, you want user data somewhere else in the frontend where you just need to show user's website so you make a <strong>GET user/1</strong> request. But it overfetches data from the experience table as well as the address table, which you don't need at all.</p>
<ol start="2">
<li>The second option is that the client can make multiple trips to the server like this:</li>
</ol>
<pre><code>GET /users 
GET users/<span class="hljs-number">1</span>/experience
</code></pre><p>This is an example of underfetching, as one endpoint doesn't have enough data. But multiple network calls slows down the process and affects the user experience. :(</p>
<p>Also, in this specific case of a <strong>List</strong>, underfetching escalates and we run into the n+1 request problem.</p>
<p>You need to make an API call to get all users and then individual API calls for each user to get their experience, something like this:  </p>
<pre><code> GET /users 
 GET /users/<span class="hljs-number">1</span>/experience 
 GET /users/<span class="hljs-number">2</span>/experience 
 ...
 GET /users/n/experience.
</code></pre><p>This is known as the n+1 request problem. To solve this issue, what we generally do is the third option, which we'll discuss now.</p>
<ol start="3">
<li>Another option is to make a custom controller on the server which returns the data-structure that meets the client requirements at that point in time. <pre><code>GET /user-experience
</code></pre>This is what is done in major real world REST API cases.</li>
</ol>
<p>On the other hand, a simple GraphQL request which would seamlessly work without any development required on the server end, would look something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-45.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>No overfetching, no underfetching, and no development on the server. Simply fantastic!</p>
<h3 id="heading-tight-coupling-between-front-end-views-and-back-end-apis">Tight coupling between front end views and back end APIs</h3>
<p>Okay, so you might argue that you can just use REST, make the server controller with a one time initial development effort, and be happy – right? </p>
<p>But there's a major drawback which comes along with using custom controllers.</p>
<p>We have formed a tight coupling with the front-end view and the back-end controller, so overall it needs more effort to cope with changes on the client end. It also gives us less flexibility.</p>
<p>As Software Engineers, we know how often requirements change. The custom controller at this point <strong>GET /user-experience</strong> is returning data depending on what the front-end view wants to display (user-name and current-role). So when a requirement changes, we need to refactor both the client and server.  </p>
<p>For example, after a considerable amount of time, requirements change and instead of the experience data the UI needs to show a user's last transaction info.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-47.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>With Rest, we would need to make the relevant changes in the front end layer. Additionally, in order to return transaction data instead of experience data from the back end, the custom controller will either need to be refactored (data sent, route, etc) or we'll need to make a new controller in case we want to preserve the old one.  </p>
<p>So basically, a change in client requirements greatly influences what is to be returned by the server – which means we have tight coupling between the front end and the back end!</p>
<p>It would be better not to have to make any changes on the server but only the front end.</p>
<p>With GraphQL we won't need to make any changes in the server side. The change in the front end query would be as minimal as this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/08/image-44.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>No server API refactoring, deployment, testing – this means time and effort saved!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As I hope you can see from this article, GraphQL has a number of advantages over REST in many areas. </p>
<p>It might take more time to set up GraphQL initially, but there are many scaffolders which make that job easier. And even if it takes more time in the beginning, it gives you long term advantages and is totally worth it.</p>
<p><strong>Thanks for reading</strong>!<br>I hope you liked this article, and that it gave you more insights to help you make your next choice. If you need some help, feel free to reach out to me on <a target="_blank" href="https://www.linkedin.com/in/aagamvadecha/">LinkedIn</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ GraphQL for Front End Developers ]]>
                </title>
                <description>
                    <![CDATA[ By Gaurav Tewari If you are a front end developer who is new to the world of GraphQL and you're thinking about getting started with it, this article is for you.  In this article, we will explore GraphQL basics and kick start our journey with it by bu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/graphql-for-front-end-developers/</link>
                <guid isPermaLink="false">66d45edb4a7504b7409c33d1</guid>
                
                    <category>
                        <![CDATA[ apollo client ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Front-end Development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 19 Oct 2021 17:19:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/10/Getting-Started-in-GraphQL-for-front-end-developers--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Gaurav Tewari</p>
<p>If you are a front end developer who is new to the world of GraphQL and you're thinking about getting started with it, this article is for you. </p>
<p>In this article, we will explore GraphQL basics and kick start our journey with it by building a simple project. </p>
<h2 id="heading-what-is-graphql">What is GraphQL?</h2>
<p>GraphQL is a query language that lets apps fetch data from the API's. But what it does differently is that is allows clients to specify how to structure the data when it is returned by the server. This means that the client only asks for the data it needs and even specifies the format in which it needs the data. </p>
<p>But what problem does it actually solve?</p>
<p>It solves the problem of under fetching and over fetching. Ok but what's that? Well, let me tell you.</p>
<p>Let's say you only need to display a userName, userImage, and Name in your profile page on your website or app. But when you request the data you are getting lots of other information about the user which you don't need. </p>
<p>This is called <strong>over fetching</strong> – you are fetching a lot of data, even the data you don't need. On the other hand, <strong>under fetching</strong> is when we get less data than you need. So neither one is great. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/sketch1634455883941.png" alt="Image" width="600" height="400" loading="lazy">
<em>under Fetching example</em></p>
<p>You might think ok, that's not a problem at all. Well, it's not a big problem in small scale applications. But what about in large scale applications that have millions of users? In those cases, over fetching and under fetching waste a lot of resources, which is where GraphQL comes in. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/d666aceb-62c2-4482-9c42-cbd12d2d42b6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h1 id="heading-how-to-get-started-with-graphql">How to Get Started With GraphQL</h1>
<p>Here we'll cover some key concepts you need to know before getting started with graphQL </p>
<h3 id="heading-graphql-playground">GraphQL PlayGround</h3>
<p>GraphQL playground is an interactive, Graphical IDE for GraphQL where you can visually explore the server. In it you can test various GraphQL queries and see their results in front of your eyes. </p>
<p><a target="_blank" href="https://graphqlpokemon.favware.tech/">Here is a link to GraphQL playground you can check out.</a></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/Screenshot-2021-10-17-at-1.57.04-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>GraphQL playground</em></p>
<p>If you click on the play button it will run the query. </p>
<h3 id="heading-how-do-you-request-write-or-post-data-in-graphql">How do you request, write, or post data in GraphQL?</h3>
<p>You request data through a query in GraphQL. And to write or post data, you use mutations. </p>
<p>Whenever we perform a GraphQL operation, we specify whether it is a mutation or a query. Then we name that operation, and this is the basic way of performing a GraphQL query. </p>
<pre><code>
GraphQLOperatoinType Name {
 ....
 ........
 .....
 ...
}
</code></pre><p>To make a simple query, the syntax would be:</p>
<pre><code>query getData {
...
}
</code></pre><p>Similarly, to add a mutation we would write <code>mutation</code> in place of <code>query</code>.</p>
<p>Now since we know the basics, let's get our hands dirty. We will be using the <a target="_blank" href="https://studio.apollographql.com/sandbox/explorer?endpoint=https%3A%2F%2Fgraphql.anilist.co&amp;explorerURLState=N4IgJg9gxgrgtgUwHYBcQC4TADpIAR4AKAhgOYJ474F6JgCWxluNNAzvSggKoBOANi1Z4UnfhSrCayUv3psAFkKlJiogG4JlNAL7aCYBGyi96AB1EQk2vdVs6QAGhDrip4gCNxbDFmy9cBx0gA&amp;_gl=1*1sgkza2*_ga*MTg1Mzg5MTM4Ni4xNjM0MjExNTMz*_ga_0BGG5V2W2K*MTYzNDM2NTQxMS43LjEuMTYzNDM2ODk5Ny4w">Anilist API</a> to get a list of  anime shows. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/Screenshot-2021-10-17-at-2.25.53-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Apollo studio</em></p>
<h3 id="heading-how-to-use-apollo-studio">How to Use Apollo Studio</h3>
<p>You've gotten a small taste of GraphQL playground, but there's something even more awesome called Apollo Studio. It makes life easier as a front end developer. In it, you just need select the fields you want and it writes a query for you. </p>
<p>From the left hand side select the fields you want in your Query, and that's it. GraphQL will automatically create a query for you. Now you've made the query, but how do you use it in your application? </p>
<p>Well let's get started building a simple Anime App with it.</p>
<p>We'll use React in this project, but you can choose any framework or library you'd like.</p>
<p>Firstly, create a new project in React:</p>
<pre><code>npx create-react-app graphql-example
</code></pre><p>Now once the project is created go inside the project directory and install the Apollo client.</p>
<pre><code>npm install graphql @apollo/client
</code></pre><p>Once it's done, go the src/index.js and import ApolloClient, InMemoryCache, and ApolloProvider:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> {ApolloClient, InMemoryCache, ApolloProvider} <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>;
</code></pre>
<p>Apollo Client is a class which represents the Apollo client itself, and we use it to create a new client instance.</p>
<p>Here we need to provide a couple of things to it. One is the URI where we specify the URL of our GraphQL server. Also every instance of our Apollo client needs a cache so it can reduce the network requests and can make our app much faster.</p>
<p>This is what our new client look like:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> client = <span class="hljs-keyword">new</span> ApolloClient({
  <span class="hljs-attr">uri</span> : <span class="hljs-string">'https://graphql.anilist.co/'</span>,
  <span class="hljs-attr">cache</span>: <span class="hljs-keyword">new</span> InMemoryCache(),
})
</code></pre>
<p>Now we need to make this client available throughout our component tree so we wrap our app's top level component in ApolloProvider. </p>
<p>Now we are done with the initial setup, so it's time to make a query and ask our API for the data – but how do we do that?</p>
<p>We can do so using the useQuery hook. But before that we need to define a query, which we can do using the GQL (we need to wrap our query inside it). So now, import these two from the Apollo client:</p>
<pre><code><span class="hljs-keyword">import</span> {useQuery, gql} <span class="hljs-keyword">from</span> <span class="hljs-string">'@apollo/client'</span>;
</code></pre><p>After importing them, we'll wrap our query inside GQL:</p>
<pre><code> <span class="hljs-keyword">const</span> AnimeList = gql<span class="hljs-string">`
 query Query {
  Page {
    media {
      siteUrl
      title {
        english
        native
      }
      description
      coverImage {
        medium
      }
      bannerImage
      volumes
      episodes
    }
  }
}
}



`</span>;
</code></pre><p>At this point you must be wondering if the query part is done, how do we get data from it now?</p>
<p>That's where the useQuery hook comes handy. It returns <code>loading</code>, <code>error</code>, and <code>data</code> properties we can use.</p>
<pre><code>  <span class="hljs-keyword">const</span> {loading, error, data} = useQuery(AnimeList);
</code></pre><p>For now we can just display the data to check whether our app works or not:</p>
<pre><code><span class="hljs-keyword">if</span>(loading) <span class="hljs-keyword">return</span>(<span class="xml"><span class="hljs-tag">&lt;&gt;</span> Loading<span class="hljs-tag">&lt;/&gt;</span></span>);
  <span class="hljs-keyword">if</span>(error) <span class="hljs-keyword">return</span>(<span class="xml"><span class="hljs-tag">&lt;&gt;</span>{JSON.stringify(error)}<span class="hljs-tag">&lt;/&gt;</span></span>)
  <span class="hljs-keyword">return</span> (
   <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
   {JSON.stringify(data)}
   <span class="hljs-tag">&lt;/&gt;</span></span>);
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2021/10/Screenshot-2021-10-16-at-5.42.06-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Well it works for now – time to style it.</p>
<p>Maybe we can use object chaining to implement that nicely:</p>
<pre><code> &lt;div className=<span class="hljs-string">"container"</span>&gt; 
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> 🐈 Anime List <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">hr</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"80%"</span> /&gt;</span></span>
   {data?.Page?.media.map(<span class="hljs-function"><span class="hljs-params">anime</span> =&gt;</span> (
     <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"card"</span> &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span>    <span class="hljs-attr">src</span>=<span class="hljs-string">{anime.coverImage.medium}/</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
         <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{anime.title.english} <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
           <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"episodes"</span> &gt;</span>Episodes  <span class="hljs-tag">&lt;<span class="hljs-name">b</span>&gt;</span>{anime.episodes} <span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>  <span class="hljs-attr">dangerouslySetInnerHTML</span>=<span class="hljs-string">{{__html:</span> <span class="hljs-attr">anime.description</span>}} &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> 
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> 
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">hr</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"75%"</span>/&gt;</span>
 <span class="hljs-tag">&lt;/&gt;</span></span>
   ))}
   &lt;div className=<span class="hljs-string">"buttonContainer"</span>&gt;
    { page != <span class="hljs-number">1</span> &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span> Previous Page<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span> } 
     &lt;div className=<span class="hljs-string">"pageText"</span>&gt; {page}&lt;/div&gt;
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{NextPage}</span>&gt;</span>  Next Page <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span> 
   &lt;/div&gt;
   &lt;/div&gt;);
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2021/10/Screenshot-2021-10-17-at-6.02.20-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>minimistic styled app</em></p>
<p>You can check out this <a target="_blank" href="https://github.com/tewarig/graphql-Example/blob/7df5c7c199878484e36742287e513d5a249b466b/src/App.css">GitHub repo for the CSS file</a>.</p>
<p>Now we are able to get a list of anime films from the API. So what do we need to get them from the next page of the app? </p>
<p>We need to pass a variable that has a page name into the query. That's where variables in GraphQL come into the picture. </p>
<p>First, go to Apollo Studio and click on the arguments on the left hand side (first go to root &gt; query &gt;page and you'll see it):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/Screenshot-2021-10-17-at-6.06.58-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Click on page and it'll add an argument to your query.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/10/Screenshot-2021-10-17-at-6.09.46-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Also notice that in the variable page in the variables section, you can change its value and play around a little bit with it. But the data will only change according to the page.</p>
<p>Now we need to pass this variable into the query – and then we'll be able to display next page's anime in our app.</p>
<p>For that we'll be using the useState hook to keep a track of our current page's value. We also need to make a function to increment and decrement that as well.</p>
<pre><code>  <span class="hljs-keyword">const</span> [page, setPage] = useState(<span class="hljs-number">1</span>);
  <span class="hljs-comment">//this is how we would be passing the page in the query.</span>
  <span class="hljs-keyword">const</span> {loading, error, data} = useQuery(AnimeList , {  <span class="hljs-attr">variables</span>: { <span class="hljs-string">"page"</span> : page } });

<span class="hljs-keyword">const</span> NextPage = <span class="hljs-function">() =&gt;</span> {
    setPage(page+<span class="hljs-number">1</span>);
  }
  <span class="hljs-keyword">const</span> PreviousPage = <span class="hljs-function">() =&gt;</span> {
    setPage(page - <span class="hljs-number">1</span>);
  }

   &lt;div className=<span class="hljs-string">"buttonContainer"</span>&gt;
    { page != <span class="hljs-number">1</span> &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{PreviousPage}</span>&gt;</span> Previous Page<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span> } 
     &lt;div className=<span class="hljs-string">"pageText"</span>&gt; {page}&lt;/div&gt;
     <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=<span class="hljs-string">{NextPage}</span>&gt;</span>  Next Page <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span> 
   &lt;/div&gt;
</code></pre><p>And now we're done building our simple app with GraphQL. If you want to check out the codebase, <a target="_blank" href="https://github.com/tewarig/graphql-Example">here is the link</a>. </p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>In this article, we have covered some of the basic concepts to help you get started using GraphQL. Thank you for reading, and happy coding. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a GraphQL Server with Laravel GraphQL and Test It with Postman ]]>
                </title>
                <description>
                    <![CDATA[ GraphQL is a query language for your API. It simplifies the process of requesting the server by providing convenient ways to query objects.  For instance, if you're using a REST API and you need a list of books, you might hit the GET /books/list endp... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-graphql-server-with-laravel/</link>
                <guid isPermaLink="false">66ba2fb0de9370f66eeb0a99</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Laravel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sule-Balogun Olanrewaju ]]>
                </dc:creator>
                <pubDate>Tue, 13 Jul 2021 07:54:34 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/07/ben-4wxWBy8Jo1I-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://graphql.org/">GraphQL</a> is a query language for your API. It simplifies the process of requesting the server by providing convenient ways to query objects. </p>
<p>For instance, if you're using a REST API and you need a list of books, you might hit the <code>GET /books/list</code> endpoint for all books. Then if you need a specific book by ID, you would hit <code>GET /book?id={id}</code>, which means you'll be making multiple requests to the server.</p>
<p>But GraphQL does something called declarative data fetching, where you can ask for what you want and get a predictable result in a single request. </p>
<p>Awesome right? Let's see how it all works.</p>
<h3 id="heading-what-we-will-be-learning">What we will be learning?</h3>
<p>In this article, you'll learn the basics of GraphQL by using the <a target="_blank" href="https://github.com/rebing/graphql-laravel">Laravel GraphQL package</a> to build a server that does the following:</p>
<ol>
<li>Register users </li>
<li>Fetch all users</li>
<li>Get a user by ID</li>
<li>Fetch all posts</li>
<li>Fetch all posts with user relationships</li>
<li>Finally, as a bonus, you'll also learn how to use the super awesome Postman tool to run your query and get a real-time response</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Here are a few things you'll need for this tutorial:</p>
<ol>
<li>A local server (<a target="_blank" href="https://www.apachefriends.org/download.html">XAMPP</a> or <a target="_blank" href="https://www.wampserver.com/en/download-wampserver-64bits/">WAMP</a>)</li>
<li>A code editor (<a target="_blank" href="https://www.sublimetext.com/3">Sublime Text</a>,  <a target="_blank" href="https://atom.io/">VS</a> <a target="_blank" href="https://code.visualstudio.com/download">Code</a>, or <a target="_blank" href="https://atom.io/">Atom</a>)</li>
<li>A version control system (<a target="_blank" href="https://git-scm.com/downloads">Git</a>)</li>
<li>A dependency Manager (<a target="_blank" href="https://getcomposer.org/download/">Composer</a>)</li>
<li>The <a target="_blank" href="https://github.com/rebing/graphql-laravel">Laravel GraphQL package</a></li>
</ol>
<h2 id="heading-graphql-basics">GraphQL Basics</h2>
<p>Before we get started, let's go over some GraphQL fundamentals.</p>
<h3 id="heading-what-is-a-graphql-schema">What is a GraphQL Schema?</h3>
<p>A GraphQL schema describes queries, mutations, and types associated with it:</p>
<pre><code class="lang-php">type User {
    id: ID !
    name : <span class="hljs-keyword">String</span> !
    email : <span class="hljs-keyword">String</span> !
    age : <span class="hljs-keyword">Int</span>
    hobbies: [<span class="hljs-keyword">String</span>]
    created_at : DateTime 
    updated_at : DateTime
}
</code></pre>
<p>In the code above, the exclamation mark on column names such as <code>id</code>, <code>name</code>, and <code>email</code> means that they are required fields.</p>
<p>You can also define various data types such as <code>Int</code>, <code>String</code>, and so on. You can also include list types and define the data type it should contain like with <code>hobbies</code>. </p>
<h3 id="heading-what-are-graphql-queries">What are GraphQL Queries?</h3>
<p>GraphQL makes it convenient to interact with data on an object. You use methods to ask for specific fields on objects and then get the expected results:</p>
<pre><code class="lang-php">{
  user {
    name
  }
}
</code></pre>
<pre><code class="lang-php">{
  <span class="hljs-string">"data"</span>: {
    <span class="hljs-string">"user"</span>: {
      <span class="hljs-string">"name"</span>: <span class="hljs-string">"John doe"</span>
    }
  }
}
</code></pre>
<h3 id="heading-what-are-graphql-resolvers">What are GraphQL Resolvers?</h3>
<p>Every time you request data from a GraphQL server, it gets <code>resolved</code>.</p>
<p>Resolvers contain arguments such as an <code>object</code>, <code>args</code>, <code>context</code>, and <code>info</code>. You'll see how resolvers work while building this project.</p>
<h2 id="heading-how-to-get-started-with-graphql">How to Get Started with GraphQL</h2>
<h3 id="heading-installation">Installation</h3>
<p>Set up a Laravel environment by running this command in the terminal:</p>
<pre><code class="lang-php">composer create-project laravel/laravel graphql-laravel
</code></pre>
<p>If you don't have composer installed, you can get it from <a target="_blank" href="https://getcomposer.org/">here</a>.</p>
<p>Install the open-source <a target="_blank" href="https://github.com/rebing/graphql-laravel">graphql-laravel server</a> package:</p>
<pre><code class="lang-php">composer <span class="hljs-keyword">require</span> rebing/graphql-laravel
</code></pre>
<p>Once the installation is finished, publish <code>config/graphql.php</code>:</p>
<pre><code class="lang-php">php artisan vendor:publish --provider=<span class="hljs-string">"Rebing\GraphQL\GraphQLServiceProvider"</span>
</code></pre>
<p>And start the development server with <code>php artisan serve</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/Screenshot-2021-05-08-at-16.14.36.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Laravel homepage</em></p>
<h3 id="heading-how-to-create-the-migration-controllers-and-resource">How to Create the Migration, Controllers, and Resource</h3>
<h4 id="heading-post">Post</h4>
<p>In this section, you'll create a relationship between users and posts.</p>
<p>To do this, you'll need to create models where you define the relationship between the entities, create migrations, and define database schemas.</p>
<pre><code class="lang-php">php artisan make:model Post -mcr
</code></pre>
<p>In <code>app/Models/User</code>, create a <code>hasMany</code> relationship between users and posts:</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">posts</span>(<span class="hljs-params"></span>)
</span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;hasMany(Post::class);
}
</code></pre>
<p>And in <code>app/models/Post</code>, define a relationship to map users to posts:</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">user</span>(<span class="hljs-params"></span>)
</span>{
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;belongsTo(User::class);
}
</code></pre>
<h3 id="heading-how-to-create-the-migration">How to Create the Migration</h3>
<p>In this section you'll create the migration.</p>
<p>Laravel already ships with a default User migration. All you need to do now is add a migration for posts:</p>
<pre><code class="lang-php">php artisan make:migration create_post_table
</code></pre>
<p>This creates a migration file with the <code>database/migrations</code> direction. Within the migration file, define the schema:</p>
<pre><code class="lang-php">Schema::create(<span class="hljs-string">'posts'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Blueprint $table</span>) </span>{
            $table-&gt;id();
             $table-&gt;integer(<span class="hljs-string">'user_id'</span>)-&gt;unsigned();
            $table-&gt;string(<span class="hljs-string">'title'</span>);
            $table-&gt;text(<span class="hljs-string">'comment'</span>);
            $table-&gt;timestamps();
        });
</code></pre>
<p>Next, modify the existing <code>.env</code> to name the database and establish a connection:</p>
<pre><code class="lang-php">DB_CONNECTION=mysql
DB_HOST=<span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span>
DB_PORT=<span class="hljs-number">3306</span>
DB_DATABASE=graphql-laravel
DB_USERNAME=root
DB_PASSWORD=
</code></pre>
<p>Run the migrate command to create the <code>User</code> and <code>Post</code> tables:</p>
<pre><code class="lang-php"> php artisan migrate
</code></pre>
<p>You can generate random records for the <code>User</code> and <code>Post</code> tables using Laravel factories.</p>
<p>Since Laravel ships with a default <code>User</code> factory, you can use that and focus on creating a <code>Post</code> factory.</p>
<h3 id="heading-how-to-create-a-post-factory">How to Create a Post Factory</h3>
<pre><code class="lang-php">php artisan make:factory PostFactory
</code></pre>
<p>Once <code>PostFactory</code> gets created within the <code>database &gt; factories</code> directory, you'll have to define the column names and the fakers you need within the <code>definition method</code>:</p>
<pre><code class="lang-php"><span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Str</span>;


<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">definition</span>(<span class="hljs-params"></span>)
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'user_id'</span> =&gt; rand(<span class="hljs-number">1</span>,<span class="hljs-number">5</span>),
            <span class="hljs-string">'title'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;faker-&gt;name(),
            <span class="hljs-string">'comment'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;faker-&gt;realText(<span class="hljs-number">180</span>)
        ];
    }
</code></pre>
<h3 id="heading-how-to-make-the-database-seeder">How to Make the Database Seeder</h3>
<p>Within the seeder class, create an execution instance for both <code>User</code> and <code>Post</code> factories.</p>
<p>This will create five users and five posts with corresponding <code>user_id</code>'s:</p>
<pre><code class="lang-php"><span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run</span>(<span class="hljs-params"></span>)
    </span>{
        \App\Models\User::factory(<span class="hljs-number">5</span>)-&gt;create();

        \App\Models\Post::factory(<span class="hljs-number">5</span>)-&gt;create();
    }
</code></pre>
<p>Then run the artisan seeder command:</p>
<pre><code class="lang-php">php artisan db:seed
</code></pre>
<p>Once you run that command in the terminal, check the database tables (<code>User</code> and <code>Post</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/Screenshot-2021-05-26-at-02.40.17.png" alt="Image" width="600" height="400" loading="lazy">
<em>Post table</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/Screenshot-2021-05-25-at-18.32.11.png" alt="Image" width="600" height="400" loading="lazy">
<em>User table</em></p>
<h3 id="heading-how-to-create-a-user-query">How to Create a User Query</h3>
<p>As of the time of writing this article, the Laravel GraphQL package doesn't support creating a scaffold for queries via the terminal.</p>
<p>So add the following to <code>app &gt; GraphQL &gt; Type &gt; UserType.php</code>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">User</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>\<span class="hljs-title">Definition</span>\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Type</span> <span class="hljs-title">as</span> <span class="hljs-title">GraphQLType</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserType</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">GraphQLType</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span>          =&gt; <span class="hljs-string">'User'</span>,
        <span class="hljs-string">'description'</span>   =&gt; <span class="hljs-string">'A user'</span>,
        <span class="hljs-string">'model'</span>         =&gt; User::class,
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fields</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'The id of the user'</span>,
            ],
            <span class="hljs-string">'name'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'The name of user'</span>,
            ],
            <span class="hljs-string">'email'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'The email of user'</span>
            ],
        ];
    }
}
</code></pre>
<p>In the code snippet above, you add the namespace you need to the <code>User</code> model. You also include a <code>protected $attributes array</code> that describes the model.</p>
<p>You also added a public <code>field</code> function that returns an array.</p>
<p>Within this function, you define the schema to include columns you specified in the user table <code>(id, name, email)</code>.</p>
<p><code>Type::nonNull(Type::string())</code> is the exclamation mark indicating the required fields and string data type.</p>
<h3 id="heading-how-to-add-a-type-to-the-config">How to Add a Type to the Config</h3>
<p>Add the <code>UserType</code> to the config file you created earlier: <code>app &gt; config &gt; graphql.php</code>:</p>
<pre><code class="lang-php"><span class="hljs-string">'types'</span> =&gt; [
        App\GraphQL\Type\UserType::class
    ],
</code></pre>
<h3 id="heading-how-to-define-the-user-query">How to Define the User Query</h3>
<p>Next, you'll need to define a query that returns the <code>UserType</code> or a list. You also need to specify the arguments you'll use within the resolve method:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">User</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>\<span class="hljs-title">Definition</span>\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Type</span> <span class="hljs-title">as</span> <span class="hljs-title">GraphQLType</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserType</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">GraphQLType</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span>          =&gt; <span class="hljs-string">'User'</span>,
        <span class="hljs-string">'description'</span>   =&gt; <span class="hljs-string">'A user'</span>,
        <span class="hljs-string">'model'</span>         =&gt; User::class,
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> Type::nonNull(Type::listOf(Type::nonNull(GraphQL::type(<span class="hljs-string">'User'</span>))));
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'The id of the user'</span>,
            ],
            <span class="hljs-string">'name'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'The name of user'</span>,
            ],
            <span class="hljs-string">'email'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'The email of user'</span>,
            ]
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{        
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>($args[<span class="hljs-string">'id'</span>])) {
            <span class="hljs-keyword">return</span> User::whereId($args[<span class="hljs-string">'id'</span>])-&gt;get();
        }

        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>($args[<span class="hljs-string">'name'</span>])) {
            <span class="hljs-keyword">return</span> User::whereName($args[<span class="hljs-string">'name'</span>])-&gt;get();
        }

        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>($args[<span class="hljs-string">'email'</span>])) {
            <span class="hljs-keyword">return</span> User::whereEmail($args[<span class="hljs-string">'email'</span>])-&gt;get();
        }

        <span class="hljs-keyword">return</span> User::all();
    }
}
</code></pre>
<p>In the snippet above, you use the required namespace the package ships with together with <code>App\Models\User</code>.</p>
<p>You also extend the <code>GraphQLType</code> from the Laravel package, and define the <code>attributes</code> as a protected array.</p>
<p>The <code>args</code> method returns an ID, name, and email from the <code>User</code> model.</p>
<p>The resolve method is used to retrieve the data from the database. If there are <code>args</code>, then the <code>if</code> block gets executed and helps you filter based on user requests.</p>
<p>Otherwise, all the data from the <code>User</code> model is retrieved.</p>
<h3 id="heading-how-to-add-a-query-to-the-config">How to Add a Query to the Config</h3>
<p>Add the following query to the <code>app &gt; config &gt; graphql.php</code> configurations file:</p>
<pre><code class="lang-php"><span class="hljs-string">'schemas'</span> =&gt; [
        <span class="hljs-string">'default'</span> =&gt; [
            <span class="hljs-string">'query'</span> =&gt; [
                App\GraphQL\Query\UsersQuery::class,
            ],
            <span class="hljs-string">'mutation'</span> =&gt; [
                <span class="hljs-comment">// ExampleMutation::class,</span>
            ],
            <span class="hljs-string">'types'</span> =&gt; [
                <span class="hljs-comment">// ExampleType::class,</span>
            ],
            <span class="hljs-string">'middleware'</span> =&gt; [],
            <span class="hljs-string">'method'</span> =&gt; [<span class="hljs-string">'get'</span>, <span class="hljs-string">'post'</span>],
        ],
    ],
</code></pre>
<p>You should now be able to query data from this endpoint: <a target="_blank" href="http://localhost:8000/graphql">http://localhost:8000/graphql</a>.</p>
<p>And in case you're curious, <code>/graphql</code> is the prefix for the route.</p>
<h3 id="heading-how-to-query-to-fetch-all-users">How to Query to Fetch all Users</h3>
<p>For this query:</p>
<pre><code class="lang-php">query {
    users {
        id, name , email
    }
}
</code></pre>
<p>Here's the expected output with Postman:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/Screenshot-2021-05-26-at-01.13.22.png" alt="Image" width="600" height="400" loading="lazy">
<em>Fetch all Users</em></p>
<h3 id="heading-how-to-create-a-post-relationship-with-the-user">How to Create a Post Relationship with the User</h3>
<p>Now you need to define a <code>PostType</code>.</p>
<p>This approach follows what you defined earlier for <code>UserType</code>.</p>
<p>Navigate to <code>app &gt; Type &gt; PostType.php</code> and add the following:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">Post</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>\<span class="hljs-title">Definition</span>\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Type</span> <span class="hljs-title">as</span> <span class="hljs-title">GraphQLType</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PostType</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">GraphQLType</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span>          =&gt; <span class="hljs-string">'Post'</span>,
        <span class="hljs-string">'description'</span>   =&gt; <span class="hljs-string">'A post'</span>,
        <span class="hljs-string">'model'</span>         =&gt; Post::class,
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'The id of the post'</span>,
            ],
            <span class="hljs-string">'title'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'The title of post'</span>,
            ],
        ];
    }
}
</code></pre>
<p><code>Post</code> follows the specification defined for <code>User</code>. Here you also used the namespace of the query, and also used the <code>Post</code> model.</p>
<p>With the code above, you extend the Query on the <code>PostQuery</code> class and set the <code>$attributes</code> array to be protected. And you have a <code>fields</code> function that returns and array with the ID, title, and comment.</p>
<p>Finally, you have a <code>type</code> within the <code>args</code> function that shows their various data types <code>int</code> or <code>string</code> with a description that tells you what they do at a glance.</p>
<h3 id="heading-how-to-create-a-postsquery">How to Create a PostsQuery</h3>
<p>Add the following to <code>app &gt; GraphQL &gt; Query &gt; PostsQuery.php</code>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span> 

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Query</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Closure</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">Post</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Facades</span>\<span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>\<span class="hljs-title">Definition</span>\<span class="hljs-title">ResolveInfo</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>\<span class="hljs-title">Definition</span>\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Query</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PostsQuery</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Query</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'posts'</span>,
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> Type::nonNull(Type::listOf(Type::nonNull(GraphQL::type(<span class="hljs-string">'Post'</span>))));
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'id'</span>, 
                <span class="hljs-string">'type'</span> =&gt; Type::int(),
            ],
            <span class="hljs-string">'title'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'title'</span>, 
                <span class="hljs-string">'type'</span> =&gt; Type::string(),
            ]
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{        
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>($args[<span class="hljs-string">'id'</span>])) {
            <span class="hljs-keyword">return</span> Post::whereId($args[<span class="hljs-string">'id'</span>])-&gt;get();
        }

        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">isset</span>($args[<span class="hljs-string">'title'</span>])) {
            <span class="hljs-keyword">return</span> Post::whereTitle($args[<span class="hljs-string">'title'</span>])-&gt;get();
        }

        <span class="hljs-keyword">return</span> Post::all();
    }
}
</code></pre>
<p>In the code above, you use the resolve method to retrieve data from the database like I mentioned earlier.</p>
<p>If there are <code>args</code>, then the <code>if</code> block gets executed and helps you filter based on the user request. Otherwise, all the data from the <code>Post</code> model is returned.</p>
<h3 id="heading-how-to-add-postsquery-and-posttype-to-config">How to Add PostsQuery and PostType to Config</h3>
<pre><code class="lang-php"><span class="hljs-string">'schemas'</span> =&gt; [
        <span class="hljs-string">'default'</span> =&gt; [
            <span class="hljs-string">'query'</span> =&gt; [
                App\GraphQL\Query\UsersQuery::class,
                App\GraphQL\Query\PostsQuery::class
            ],
            <span class="hljs-string">'mutation'</span> =&gt; [
                <span class="hljs-comment">// ExampleMutation::class,</span>
            ],
            <span class="hljs-string">'types'</span> =&gt; [
                <span class="hljs-comment">// ExampleType::class,</span>
            ],
            <span class="hljs-string">'middleware'</span> =&gt; [],
            <span class="hljs-string">'method'</span> =&gt; [<span class="hljs-string">'get'</span>, <span class="hljs-string">'post'</span>],
        ],
    ],
</code></pre>
<pre><code class="lang-php"><span class="hljs-string">'types'</span> =&gt; [
        App\GraphQL\Type\UserType::class,
        App\GraphQL\Type\PostType::class
    ],
</code></pre>
<p>Now you can use the following query to get all posts:</p>
<pre><code class="lang-php">query{
    posts{
        id
        user_id
        title
        comment
    }
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/Screenshot-2021-05-26-at-03.00.41.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image of Fetch all post</em></p>
<p>You can also fetch users with post relationships with this query:</p>
<pre><code class="lang-php">query{
    users{
        id 
        name
        posts {
            title
        }
    }
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/07/Screenshot-2021-07-11-at-15.40.05.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image to fetch users with post relationship</em></p>
<h3 id="heading-how-to-create-a-mutation">How to Create a Mutation</h3>
<p>Now you'll set up a mutation to create a user. This mutation will help with operations that involve modifying state on the server.</p>
<p>In your case you'll be mutating the state of the server by creating a user.</p>
<p>Create a mutation folder within the app directory, <code>app &gt; Mutation &gt; CreateUserMutation.php</code>.</p>
<p>Then add the following code to <code>CreateUserMutation.php</code>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Mutation</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Closure</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\<span class="hljs-title">Models</span>\<span class="hljs-title">User</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>\<span class="hljs-title">Definition</span>\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\<span class="hljs-title">Type</span>\<span class="hljs-title">Definition</span>\<span class="hljs-title">ResolveInfo</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\<span class="hljs-title">GraphQL</span>\<span class="hljs-title">Support</span>\<span class="hljs-title">Mutation</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreateUserMutation</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mutation</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'users'</span>
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> Type::nonNull(GraphQL::type(<span class="hljs-string">'User'</span>));
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'name'</span> =&gt; [<span class="hljs-string">'
                name'</span> =&gt; <span class="hljs-string">'name'</span>, 
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
            ],
            <span class="hljs-string">'email'</span> =&gt; [<span class="hljs-string">'
                name'</span> =&gt; <span class="hljs-string">'email'</span>, 
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
            ],
            <span class="hljs-string">'password'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'password'</span>, 
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
            ]
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args, $context, ResolveInfo $resolveInfo, <span class="hljs-built_in">Closure</span> $getSelectFields</span>)
    </span>{
        <span class="hljs-keyword">return</span> User::firstOrCreate(
            [   <span class="hljs-string">'email'</span> =&gt; $args[<span class="hljs-string">'email'</span>]],
            [   <span class="hljs-string">'name'</span> =&gt; $args[<span class="hljs-string">'name'</span>],
                <span class="hljs-string">'password'</span> =&gt; bcrypt($args[<span class="hljs-string">'password'</span>])
            ]);
    }
}
</code></pre>
<p>The <code>resolve</code> method helps users of the application sign up and create their record. <code>resolve</code> accepts <code>args</code> as a parameter and then uses the <code>firstOrCreate</code> method to ensure all users registering have a unique identifier, in this case, their email address.</p>
<p>In the config, you'll also need to include the mutation you just created:</p>
<pre><code class="lang-php"><span class="hljs-string">'schemas'</span> =&gt; [
        <span class="hljs-string">'default'</span> =&gt; [
            <span class="hljs-string">'query'</span> =&gt; [
                App\GraphQL\Query\UsersQuery::class,
                App\GraphQL\Query\PostsQuery::class
            ],
            <span class="hljs-string">'mutation'</span> =&gt; [
                App\GraphQL\Mutation\CreateUserMutation::class,
            ],
            <span class="hljs-string">'types'</span> =&gt; [],
            <span class="hljs-string">'middleware'</span> =&gt; [],
            <span class="hljs-string">'method'</span> =&gt; [<span class="hljs-string">'get'</span>, <span class="hljs-string">'post'</span>],
        ],
    ],
</code></pre>
<p>And here's how to create a user:</p>
<pre><code class="lang-php">mutation{
    users(name : <span class="hljs-string">"John Doe"</span>, email : <span class="hljs-string">"Johndoe@gmail.com"</span>, password : <span class="hljs-string">"John1234"</span>){
        id
        name
    }
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/Screenshot-2021-05-26-at-03.50.14.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image of user creation</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congrats! You've successfully built a GraphQL server using Laravel, and ran queries with Postman to get responses. Now that you know the basics of GraphQL, I hope you use it in your projects going forward.</p>
<p>All the code in this tutorial is available on <a target="_blank" href="https://github.com/LarrySul/GraphQL-Laravel">GitHub</a>, which also includes the Postman collection.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li><a target="_blank" href="https://graphql.org/">GraphQL website</a> </li>
<li><a target="_blank" href="https://github.com/rebing/graphql-laravel">Laravel GraphQL</a></li>
<li><a target="_blank" href="https://www.apollographql.com/blog/tooling/graphql-ide/how-to-use-graphql-with-postman/">How to use GraphQL with Postman</a></li>
<li></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a GraphQL API Using Laravel ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I'll walk you through how to set up your own GraphQL API using PHP and Laravel. Two years ago, I started working professionally as a backend developer. And I was very intimidated by all the technology I didn't yet know. Words like Do... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-graphql-api-using-laravel/</link>
                <guid isPermaLink="false">66bb8c8e2108ff2ab9af167c</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GraphQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Laravel ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tamerlan Gudabayev ]]>
                </dc:creator>
                <pubDate>Wed, 26 May 2021 16:34:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/05/graphql-article-image.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I'll walk you through how to set up your own GraphQL API using PHP and Laravel.</p>
<p>Two years ago, I started working professionally as a backend developer. And I was very intimidated by all the technology I didn't yet know. Words like Docker, Kubernetes, and GraphQL seemed quite scary.</p>
<p>But I mustered up the courage and started to learn them all one by one.</p>
<p>It was actually easier than I thought, so I would like to share with you what I've learned about GraphQL by creating a simple demo project together.</p>
<p>You can find the final project on GitHub <a target="_blank" href="https://github.com/TamerlanG/GraphQL-using-Laravel">here</a>.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we begin, make sure to have these installed on your system:</p>
<ul>
<li>PHP 7+</li>
<li>Composer 2.0</li>
<li>Docker 20.10.6 (Any other version should be fine)</li>
<li>Docker-Compose 1.29.1 (Any other version should be fine)</li>
</ul>
<p>I also assume that you have:</p>
<ul>
<li>Basic knowledge of Laravel (Eloquent, Migrations, MVC, Routes, and so on)</li>
<li>Knowledge of PHP (Syntax, OOP, and so on)</li>
<li>Basic knowledge of GraphQL (in theory)</li>
</ul>
<h2 id="heading-what-were-going-to-build">What We're Going to Build</h2>
<p>I like RPG games like the Elder Scrolls Series or Final Fantasy, so of course our app will be about games. The project will consist of only two models called <strong>Quests</strong> and <strong>Categories</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/1-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Database Schema</em></p>
<p>By the end of this post we will create a CRUD GraphQL API for each model.</p>
<h2 id="heading-how-to-initialize-the-project">How to Initialize the Project</h2>
<p>Create a Laravel project using this command:</p>
<pre><code class="lang-bash">composer create-project laravel/laravel quest_journal
</code></pre>
<p>This will create a new project in a new directory called <code>quest_journal</code>.</p>
<p>Next let's setup sail like this:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Move into the project</span>
<span class="hljs-built_in">cd</span> quest_journal

<span class="hljs-comment"># Install and configure laravel sail</span>
php artisan sail:install
</code></pre>
<p>It's gonna ask you which services to install. Just press <code>enter</code> to only install MySQL.</p>
<p>If all goes well, you should now see a <code>docker-compose.yml</code> file in your project directory.</p>
<p>Let's then run the containers using sail:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Run the containers</span>
./vendor/bin/sail up -d

<span class="hljs-comment"># Check if the containers are running</span>
docker ps
</code></pre>
<p>At this point I suggest you alias <code>sail</code> to <code>./vendor/bin/sail</code>. You can do that by adding this piece of code to your <code>bashrc</code> or <code>zshrc</code>:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># in ~./zshrc or ~./bashrc</span>

<span class="hljs-built_in">alias</span> sail = <span class="hljs-string">'bash vendor/bin/sail'</span>
</code></pre>
<p>Moving on, if you go to <a target="_blank" href="http://localhost/">localhost</a> you should see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Default Laravel Home Page</em></p>
<p>But before we move on, there are some packages that we need to install first:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># IDE helper for laravel, always useful to have.</span>
sail composer require --dev barryvdh/laravel-ide-helper

<span class="hljs-comment"># GraphQL library which we are going to use</span>
sail composer require rebing/graphql-laravel
</code></pre>
<p>Next we have to publish the GraphQL library like this:</p>
<pre><code class="lang-bash">sail artisan vendor:publish --provider=<span class="hljs-string">"Rebing\\GraphQL\\GraphQLServiceProvider"</span>
</code></pre>
<p>This should create a GraphQL config file that we will use in <code>config/graphql.php</code>.</p>
<h2 id="heading-how-to-create-the-migrations-and-models">How to Create the Migrations and Models</h2>
<p>This isn't a Laravel tutorial, so we'll quickly create the models with the appropriate migrations.</p>
<p>Let's start with category model:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create model with migrations</span>
sail artisan make:model -m Category
</code></pre>
<p>This will create the Category model with it's migration file.</p>
<p>Our category will consist of four fields:</p>
<ul>
<li>ID</li>
<li>Title</li>
<li>Created_At</li>
<li>Updated_At</li>
</ul>
<p>Our category migrations file should look like this:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// database/migrations/yyyy_mm_dd_hhMMss_create_categories_table.php</span>

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Migrations</span>\\<span class="hljs-title">Migration</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Schema</span>\\<span class="hljs-title">Blueprint</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">Schema</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreateCategoriesTable</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Migration</span>
</span>{
    <span class="hljs-comment">/**
     * Run the migrations.
     *
     * <span class="hljs-doctag">@return</span> void
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span>(<span class="hljs-params"></span>)
    </span>{
        Schema::create(<span class="hljs-string">'categories'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Blueprint $table</span>) </span>{
            $table-&gt;id();
            $table-&gt;text(<span class="hljs-string">'title'</span>);
            $table-&gt;timestamps();
        });
    }

    <span class="hljs-comment">/**
     * Reverse the migrations.
     *
     * <span class="hljs-doctag">@return</span> void
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">down</span>(<span class="hljs-params"></span>)
    </span>{
        Schema::dropIfExists(<span class="hljs-string">'categories'</span>);
    }
}
</code></pre>
<p>Next let's configure the category model class.</p>
<p>We will do two things here:</p>
<ul>
<li>Make the field <code>title</code> editable, so we will add it to our <code>$fillable</code> array.</li>
<li>Define the relationship between category model and quest model.</li>
</ul>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// App\\Models\\Category</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Eloquent</span>\\<span class="hljs-title">Factories</span>\\<span class="hljs-title">HasFactory</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Eloquent</span>\\<span class="hljs-title">Model</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Category</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span>
</span>{
    <span class="hljs-keyword">use</span> <span class="hljs-title">HasFactory</span>;

    <span class="hljs-keyword">protected</span> $fillable = [<span class="hljs-string">'title'</span>];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">quests</span>(<span class="hljs-params"></span>)</span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;hasMany(Quest::class);
    }
}
</code></pre>
<p>You will have some errors concerning the Quest model, but no worries – we will handle that next.</p>
<p>Run the command to make a model and migration file for quest:</p>
<pre><code class="lang-bash">sail artisan make:model -m Quest
</code></pre>
<p>This will create a model named Quest and a migration file for it.</p>
<p>Our quest will have the fields:</p>
<ul>
<li>ID</li>
<li>Title</li>
<li>Description</li>
<li>Reward</li>
<li>Category_ID</li>
<li>Created_At</li>
<li>Updated_At</li>
</ul>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>
<span class="hljs-comment">// database/migrations/yyyy_mm_dd_hhMMss_create_quests_table.php</span>

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Migrations</span>\\<span class="hljs-title">Migration</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Schema</span>\\<span class="hljs-title">Blueprint</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">Schema</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreateQuestsTable</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Migration</span>
</span>{
    <span class="hljs-comment">/**
     * Run the migrations.
     *
     * <span class="hljs-doctag">@return</span> void
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">up</span>(<span class="hljs-params"></span>)
    </span>{
        Schema::create(<span class="hljs-string">'quests'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Blueprint $table</span>) </span>{
            $table-&gt;id();
            $table-&gt;text(<span class="hljs-string">'title'</span>);
            $table-&gt;text(<span class="hljs-string">'description'</span>);
            $table-&gt;integer(<span class="hljs-string">'reward'</span>);
            $table-&gt;foreignId(<span class="hljs-string">'category_id'</span>)-&gt;constrained();
            $table-&gt;timestamps();
        });
    }

    <span class="hljs-comment">/**
     * Reverse the migrations.
     *
     * <span class="hljs-doctag">@return</span> void
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">down</span>(<span class="hljs-params"></span>)
    </span>{
        Schema::dropIfExists(<span class="hljs-string">'quests'</span>);
    }
}
</code></pre>
<p>As you can see, we declared the <code>category_id</code> to be a <code>foreignId</code>. This way Laravel will automatically create a foreign key relationship between the tables <code>categories</code> and <code>quests</code>.</p>
<p>Next let's configure the quest model class. </p>
<p>Here we will:</p>
<ul>
<li>Make the appropriate fields editable by adding them to the <code>$fillable</code> array.</li>
<li>Define the relationship between category model and quest model.</li>
</ul>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// App\\Models\\Quest</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Eloquent</span>\\<span class="hljs-title">Factories</span>\\<span class="hljs-title">HasFactory</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Eloquent</span>\\<span class="hljs-title">Model</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Quest</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Model</span>
</span>{
    <span class="hljs-keyword">use</span> <span class="hljs-title">HasFactory</span>;

    <span class="hljs-keyword">protected</span> $fillable = [<span class="hljs-string">'title'</span>, <span class="hljs-string">'category_id'</span>, <span class="hljs-string">'description'</span>,                               <span class="hljs-string">'reward'</span>];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">category</span>(<span class="hljs-params"></span>)</span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">$this</span>-&gt;belongsTo(Category::class);
    }
}
</code></pre>
<p>With both the migrations and models ready, we can apply the changes to the database.</p>
<p>Run this command:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Apply migrations</span>
sail artisan migrate
</code></pre>
<p>Our database should be updated! Next we should put some data into our tables.</p>
<h2 id="heading-how-to-seed-the-database">How to Seed the Database</h2>
<p>We need data to work with, but as developers we are too lazy to manually do it. </p>
<p>This is where factories come.</p>
<p>First, we'll create the factory classes for both the quest and category model.</p>
<p>Run the following commands:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Create a factory class for quest model</span>
sail artisan make:factory QuestFactory --model=Quest

<span class="hljs-comment"># Create a factory class for category model</span>
sail artisan make:factory CategoryFactory --model=Category
</code></pre>
<p>This will create for us two new classes:</p>
<ul>
<li><code>QuestFactory</code> – a class that helps us generate quests.</li>
<li><code>CategoryFactory</code> – a class that helps us generate categories.</li>
</ul>
<p>Let's start with the <code>QuestFactory</code>. In our <code>definitions</code> function we will tell Laravel how each field should be generated. For the field <code>category_id</code>, we will pick a random category.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// database/factories/QuestFactory.php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Database</span>\\<span class="hljs-title">Factories</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Category</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Quest</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Eloquent</span>\\<span class="hljs-title">Factories</span>\\<span class="hljs-title">Factory</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QuestFactory</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Factory</span>
</span>{
    <span class="hljs-comment">/**
     * The name of the factory's corresponding model.
     *
     * <span class="hljs-doctag">@var</span> string
     */</span>
    <span class="hljs-keyword">protected</span> $model = Quest::class;

    <span class="hljs-comment">/**
     * Define the model's default state.
     *
     * <span class="hljs-doctag">@return</span> array
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">definition</span>(<span class="hljs-params"></span>)
    </span>{
        $categoryIDs = Category::all()-&gt;pluck(<span class="hljs-string">'id'</span>)-&gt;toArray();

        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'title'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;faker-&gt;title(),
            <span class="hljs-string">'description'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;faker-&gt;text(),
            <span class="hljs-string">'reward'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;faker-&gt;numberBetween(<span class="hljs-number">1</span> , <span class="hljs-number">100</span>),
            <span class="hljs-string">'category_id'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;faker-&gt;randomElement($categoryIDs)
        ];
    }
}
</code></pre>
<p><code>CategoryFactory</code> is much simpler, as we simply have to generate a title.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// database/factories/CategoryFactory.php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Database</span>\\<span class="hljs-title">Factories</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Category</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Eloquent</span>\\<span class="hljs-title">Factories</span>\\<span class="hljs-title">Factory</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CategoryFactory</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Factory</span>
</span>{
    <span class="hljs-comment">/**
     * The name of the factory's corresponding model.
     *
     * <span class="hljs-doctag">@var</span> string
     */</span>
    <span class="hljs-keyword">protected</span> $model = Category::class;

    <span class="hljs-comment">/**
     * Define the model's default state.
     *
     * <span class="hljs-doctag">@return</span> array
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">definition</span>(<span class="hljs-params"></span>)
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'title'</span> =&gt; <span class="hljs-keyword">$this</span>-&gt;faker-&gt;title()
        ];
    }
}
</code></pre>
<p>Now instead of creating seeders, we will simply run the factory create method inside <code>DatabaseSeeder.php</code>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// database/seeders/DatabaseSeeder.php</span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">Database</span>\\<span class="hljs-title">Seeders</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Category</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Quest</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Illuminate</span>\\<span class="hljs-title">Database</span>\\<span class="hljs-title">Seeder</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DatabaseSeeder</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Seeder</span>
</span>{
    <span class="hljs-comment">/**
     * Seed the application's database.
     *
     * <span class="hljs-doctag">@return</span> void
     */</span>
    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">run</span>(<span class="hljs-params"></span>)
    </span>{
        Category::factory(<span class="hljs-number">10</span>)-&gt;create();
        Quest::factory(<span class="hljs-number">10</span>)-&gt;create();
    }
}
</code></pre>
<p>Finally run the command to seed the database.</p>
<pre><code class="lang-php">sail artisan db:seed
</code></pre>
<h2 id="heading-folder-structure">Folder Structure</h2>
<p>At this point we are ready to create our GraphQL APIs. To do that let's first create a new folder in the <code>app</code> directory called <code>GraphQL</code>.</p>
<p>Inside the GraphQL folder, create three new folders:</p>
<ul>
<li>Mutations</li>
<li>Queries</li>
<li>Types</li>
</ul>
<p>It will look something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/3.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>This is where the bulk of our code will be. As you might be able to tell, it's very different from REST architecture. Before we begin writing the code, let me quickly explain the purpose of each folder.</p>
<ul>
<li><strong>Mutations</strong>: This folder will contain classes that manage the insert, update, and delete operations.</li>
<li><strong>Queries</strong>: This folder will contain the classes that fetch data from the database.</li>
<li><strong>Types</strong>: You can think of this as a model, or a model resource. Basically types are objects that can be fetched from the database. For example, we are going to have a <code>QuestType</code> and a <code>CategoryType</code>.</li>
</ul>
<h2 id="heading-how-to-define-the-category-and-quest-types">How to Define the Category and Quest Types</h2>
<p>Let's first start with types. We'll create two new classes in our types folder called:</p>
<ol>
<li><code>CategoryType</code></li>
<li><code>QuestType</code></li>
</ol>
<p>Here is where we will use the <code>rebing/graphql-laravel</code> package which basically helps us create types, queries, and mutations.</p>
<p>Our types will inherit the <code>Type</code> class from <code>Rebing\\GraphQL\\Support\\Type</code>. There's also another class called <code>Type</code> in the package but it's used to declare the type of field (like string, int, and so on).</p>
<p>Let's begin with the <code>CategoryType</code> class:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/types/CategoryType </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Types</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Category</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Type</span> <span class="hljs-title">as</span> <span class="hljs-title">GraphQLType</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CategoryType</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">GraphQLType</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'Category'</span>,
        <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Collection of categories'</span>,
        <span class="hljs-string">'model'</span> =&gt; Category::class
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fields</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'ID of quest'</span>
            ],
            <span class="hljs-string">'title'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Title of the quest'</span>
            ],
            <span class="hljs-string">'quests'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::listOf(GraphQL::type(<span class="hljs-string">'Quest'</span>)),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'List of quests'</span>
            ]
        ];
    }
}
</code></pre>
<p>Let's break this down:</p>
<ul>
<li><strong>Attributes</strong>: This is your type configuration. It has core information about your type, and to which model it associates.</li>
<li><strong>Fields</strong>: This method returns the fields that your client can ask for.</li>
</ul>
<p>You may have noticed that we have a field called <code>quests</code> which is a list of <code>QuestType</code>. But we don't associate the class directly – we instead use its <code>name</code> from its attribute.</p>
<p>Next is the <code>QuestType</code> class:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/types/QuestType </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Types</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Quest</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Type</span> <span class="hljs-title">as</span> <span class="hljs-title">GraphQLType</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QuestType</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">GraphQLType</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'Quest'</span>,
        <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Collection of quests with their respective category'</span>,
        <span class="hljs-string">'model'</span> =&gt; Quest::class
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fields</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'ID of quest'</span>
            ],
            <span class="hljs-string">'title'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Title of the quest'</span>
            ],
            <span class="hljs-string">'description'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::string()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Description of quest'</span>
            ],
            <span class="hljs-string">'reward'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Quest reward'</span>
            ],
            <span class="hljs-string">'category'</span> =&gt; [
                <span class="hljs-string">'type'</span> =&gt; GraphQL::type(<span class="hljs-string">'Category'</span>),
                <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'The category of the quest'</span>
            ]
        ];
    }
}
</code></pre>
<h2 id="heading-how-to-define-the-queries-for-your-model">How to Define the Queries for Your Model</h2>
<p>Now that we have defined our types, we can move on to queries.</p>
<p>For each model we will have two queries:</p>
<ul>
<li>A class to query a single model</li>
<li>A class to query a list of models</li>
</ul>
<p>To keep stuff organized, create two new folders in your <code>Queries</code> folder:</p>
<ul>
<li>Category</li>
<li>Quest</li>
</ul>
<p>Let's create our classes:</p>
<ul>
<li><code>QuestQuery</code></li>
<li><code>QuestsQuery</code></li>
<li><code>CategoryQuery</code></li>
<li><code>CategoriesQuery</code></li>
</ul>
<p>Your file structure should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let's start with the <code>QuestQuery</code> class:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/queries/quest/QuestQuery </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Queries</span>\\<span class="hljs-title">Quest</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Quest</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Query</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QuestQuery</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Query</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'quest'</span>,
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> GraphQL::type(<span class="hljs-string">'Quest'</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'id'</span>,
                <span class="hljs-string">'type'</span> =&gt; Type::int(),
                <span class="hljs-string">'rules'</span> =&gt; [<span class="hljs-string">'required'</span>]
            ]
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        <span class="hljs-keyword">return</span> Quest::findOrFail($args[<span class="hljs-string">'id'</span>]);
    }
}
</code></pre>
<p>Let's break this down:</p>
<ul>
<li>Our query classes will inherit from <code>Rebing\\GraphQL\\Support\\Query</code></li>
<li>The <code>attributes</code> function is used as the query configuration.</li>
<li>The <code>type</code> function is used to declare what type of object this query will return.</li>
<li>The <code>args</code> function is used to declare what arguments this query will accept. In our case we only need the <code>id</code> of the quest.</li>
<li>The <code>resolve</code> function does the bulk of the work – it returns the actual object using eloquent.</li>
</ul>
<p>The rest of the classes have a similar format, so it's pretty much self explanatory.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/queries/quest/QuestsQuery </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Queries</span>\\<span class="hljs-title">Quest</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Quest</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Query</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">QuestsQuery</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Query</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'quests'</span>,
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> Type::listOf(GraphQL::type(<span class="hljs-string">'Quest'</span>));
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        <span class="hljs-keyword">return</span> Quest::all();
    }
}
</code></pre>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/queries/category/CategoryQuery </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Queries</span>\\<span class="hljs-title">Category</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Category</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Query</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CategoryQuery</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Query</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'category'</span>,
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> GraphQL::type(<span class="hljs-string">'Category'</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'id'</span>,
                <span class="hljs-string">'type'</span> =&gt; Type::int(),
                <span class="hljs-string">'rules'</span> =&gt; [<span class="hljs-string">'required'</span>]
            ]
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        <span class="hljs-keyword">return</span> Category::findOrFail($args[<span class="hljs-string">'id'</span>]);
    }
}
</code></pre>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/queries/category/CategoriesQuery </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Queries</span>\\<span class="hljs-title">Category</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Category</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Query</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CategoriesQuery</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Query</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'categories'</span>,
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> Type::listOf(GraphQL::type(<span class="hljs-string">'Category'</span>));
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        <span class="hljs-keyword">return</span> Category::all();
    }
}
</code></pre>
<h2 id="heading-how-to-create-the-mutation-classes">How to Create the Mutation Classes</h2>
<p>Mutations will house our classes that control the insertion/deletion of our models. So for each model we will have three classes:</p>
<ul>
<li>A class to create a model</li>
<li>A class to update a model</li>
<li>A class to delete a model</li>
</ul>
<p>We have two models in our app, so we will have 6 mutation classes.</p>
<p>To keep things organized, create two new folders in your <code>Mutations</code> folder:</p>
<ul>
<li>Category</li>
<li>Quest</li>
</ul>
<p>Let's create our mutation classes:</p>
<ul>
<li><code>CreateCategoryMutation</code></li>
<li><code>DeleteCategoryMutation</code></li>
<li><code>UpdateCategoryMutation</code></li>
<li><code>CreateQuestMutation</code></li>
<li><code>DeleteQuestMutation</code></li>
<li><code>UpdateQuestMutation</code></li>
</ul>
<p>Your file structure should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let's start with <code>CreateCategoryMutation</code>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/mutations/category/CreateCategoryMutation </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Mutations</span>\\<span class="hljs-title">Category</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Category</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Mutation</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreateCategoryMutation</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mutation</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'createCategory'</span>,
        <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Creates a category'</span>
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> GraphQL::type(<span class="hljs-string">'Category'</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'title'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'title'</span>,
                <span class="hljs-string">'type'</span> =&gt;  Type::nonNull(Type::string()),
            ],
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        $category = <span class="hljs-keyword">new</span> Category();
        $category-&gt;fill($args);
        $category-&gt;save();

        <span class="hljs-keyword">return</span> $category;
    }
}
</code></pre>
<p>As you can see, the structure is very similar to our queries.</p>
<p>Once again let's break down this class:</p>
<ul>
<li>Our mutation classes will inherit from <code>Rebing\\GraphQL\\Support\\Mutation</code></li>
<li>The <code>attributes</code> function is used as mutation configuration.</li>
<li>The <code>type</code> function is used to declare what type of object this query will return.</li>
<li>The <code>args</code> function is used to declare what arguments this mutation will accept. In our case we only need the <code>title</code> field.</li>
<li>The <code>resolve</code> function does the bulk of the work – it does the actual mutation using eloquent.</li>
</ul>
<p>The rest of the mutations have a similar format, so they should be self-explanatory.</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/mutations/category/DeleteCategoryMutation </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Mutations</span>\\<span class="hljs-title">Category</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Category</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Mutation</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeleteCategoryMutation</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mutation</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'deleteCategory'</span>,
        <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'deletes a category'</span>
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> Type::boolean();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'id'</span>,
                <span class="hljs-string">'type'</span> =&gt; Type::int(),
                <span class="hljs-string">'rules'</span> =&gt; [<span class="hljs-string">'required'</span>]
            ]
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        $category = Category::findOrFail($args[<span class="hljs-string">'id'</span>]);

        <span class="hljs-keyword">return</span>  $category-&gt;delete() ? <span class="hljs-literal">true</span> : <span class="hljs-literal">false</span>;
    }
}
</code></pre>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/mutations/category/UpdateCategoryMutation </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Mutations</span>\\<span class="hljs-title">Category</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Category</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Mutation</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UpdateCategoryMutation</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mutation</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'updateCategory'</span>,
        <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Updates a category'</span>
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> GraphQL::type(<span class="hljs-string">'Category'</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'id'</span>,
                <span class="hljs-string">'type'</span> =&gt;  Type::nonNull(Type::int()),
            ],
            <span class="hljs-string">'title'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'title'</span>,
                <span class="hljs-string">'type'</span> =&gt;  Type::nonNull(Type::string()),
            ],
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        $category = Category::findOrFail($args[<span class="hljs-string">'id'</span>]);
        $category-&gt;fill($args);
        $category-&gt;save();

        <span class="hljs-keyword">return</span> $category;
    }
}
</code></pre>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/mutations/quest/CreateQuestMutation </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Mutations</span>\\<span class="hljs-title">Quest</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Quest</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Mutation</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreateQuestMutation</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mutation</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'createQuest'</span>,
        <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Creates a quest'</span>
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> GraphQL::type(<span class="hljs-string">'Quest'</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'title'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'title'</span>,
                <span class="hljs-string">'type'</span> =&gt;  Type::nonNull(Type::string()),
            ],
            <span class="hljs-string">'description'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'description'</span>,
                <span class="hljs-string">'type'</span> =&gt;  Type::nonNull(Type::string()),
            ],
            <span class="hljs-string">'reward'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'reward'</span>,
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
            ],
            <span class="hljs-string">'category_id'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'category_id'</span>,
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
                <span class="hljs-string">'rules'</span> =&gt; [<span class="hljs-string">'exists:categories,id'</span>]
            ]
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        $quest = <span class="hljs-keyword">new</span> Quest();
        $quest-&gt;fill($args);
        $quest-&gt;save();

        <span class="hljs-keyword">return</span> $quest;
    }
}
</code></pre>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/mutations/quest/DeleteQuestMutation </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Mutations</span>\\<span class="hljs-title">Quest</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Quest</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Mutation</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeleteQuestMutation</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mutation</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'deleteQuest'</span>,
        <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Deletes a quest'</span>
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> Type::boolean();
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'id'</span>,
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
                <span class="hljs-string">'rules'</span> =&gt; [<span class="hljs-string">'exists:quests'</span>]
            ]
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        $category = Quest::findOrFail($args[<span class="hljs-string">'id'</span>]);

        <span class="hljs-keyword">return</span>  $category-&gt;delete() ? <span class="hljs-literal">true</span> : <span class="hljs-literal">false</span>;
    }
}
</code></pre>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-comment">// app/graphql/mutations/quest/UpdateQuestMutation </span>

<span class="hljs-keyword">namespace</span> <span class="hljs-title">App</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Mutations</span>\\<span class="hljs-title">Quest</span>;

<span class="hljs-keyword">use</span> <span class="hljs-title">App</span>\\<span class="hljs-title">Models</span>\\<span class="hljs-title">Quest</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Type</span>\\<span class="hljs-title">Definition</span>\\<span class="hljs-title">Type</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Facades</span>\\<span class="hljs-title">GraphQL</span>;
<span class="hljs-keyword">use</span> <span class="hljs-title">Rebing</span>\\<span class="hljs-title">GraphQL</span>\\<span class="hljs-title">Support</span>\\<span class="hljs-title">Mutation</span>;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UpdateQuestMutation</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Mutation</span>
</span>{
    <span class="hljs-keyword">protected</span> $attributes = [
        <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'updateQuest'</span>,
        <span class="hljs-string">'description'</span> =&gt; <span class="hljs-string">'Updates a quest'</span>
    ];

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">type</span>(<span class="hljs-params"></span>): <span class="hljs-title">Type</span>
    </span>{
        <span class="hljs-keyword">return</span> GraphQL::type(<span class="hljs-string">'Quest'</span>);
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">args</span>(<span class="hljs-params"></span>): <span class="hljs-title">array</span>
    </span>{
        <span class="hljs-keyword">return</span> [
            <span class="hljs-string">'id'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'id'</span>,
                <span class="hljs-string">'type'</span> =&gt;  Type::nonNull(Type::int()),
            ],
            <span class="hljs-string">'title'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'title'</span>,
                <span class="hljs-string">'type'</span> =&gt;  Type::nonNull(Type::string()),
            ],
            <span class="hljs-string">'description'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'description'</span>,
                <span class="hljs-string">'type'</span> =&gt;  Type::nonNull(Type::string()),
            ],
            <span class="hljs-string">'reward'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'reward'</span>,
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
            ],
            <span class="hljs-string">'category_id'</span> =&gt; [
                <span class="hljs-string">'name'</span> =&gt; <span class="hljs-string">'category_id'</span>,
                <span class="hljs-string">'type'</span> =&gt; Type::nonNull(Type::int()),
                <span class="hljs-string">'rules'</span> =&gt; [<span class="hljs-string">'exists:categories,id'</span>]
            ]
        ];
    }

    <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">resolve</span>(<span class="hljs-params">$root, $args</span>)
    </span>{
        $quest = Quest::findOrFail($args[<span class="hljs-string">'id'</span>]);
        $quest-&gt;fill($args);
        $quest-&gt;save();

        <span class="hljs-keyword">return</span> $quest;
    }
}
</code></pre>
<h2 id="heading-schemas">Schemas</h2>
<p>All the hard work is done! Now we have to put everything together.</p>
<p>We have to register our queries, mutations, and types in our <code>config/graphql</code>:</p>
<pre><code class="lang-php"><span class="hljs-meta">&lt;?php</span>

<span class="hljs-keyword">return</span> [
    <span class="hljs-comment">// ... some code</span>

    <span class="hljs-string">'schemas'</span> =&gt; [
        <span class="hljs-string">'default'</span> =&gt; [
            <span class="hljs-string">'query'</span> =&gt; [
                <span class="hljs-string">'quest'</span> =&gt; \\App\\GraphQL\\Queries\\Quest\\QuestQuery::class,
                <span class="hljs-string">'quests'</span> =&gt; \\App\\GraphQL\\Queries\\Quest\\QuestsQuery::class,
                <span class="hljs-string">'category'</span> =&gt; \\App\\GraphQL\\Queries\\Category\\CategoryQuery::class,
                <span class="hljs-string">'categories'</span> =&gt; \\App\\GraphQL\\Queries\\Category\\CategoriesQuery::class,
            ],
            <span class="hljs-string">'mutation'</span> =&gt; [
                <span class="hljs-string">'createQuest'</span> =&gt; \\App\\GraphQL\\Mutations\\Quest\\CreateQuestMutation::class,
                <span class="hljs-string">'updateQuest'</span> =&gt; \\App\\GraphQL\\Mutations\\Quest\\UpdateQuestMutation::class,
                <span class="hljs-string">'deleteQuest'</span> =&gt; \\App\\GraphQL\\Mutations\\Quest\\DeleteQuestMutation::class,
                <span class="hljs-string">'createCategory'</span> =&gt; \\App\\GraphQL\\Mutations\\Category\\CreateCategoryMutation::class,
                <span class="hljs-string">'updateCategory'</span> =&gt; \\App\\GraphQL\\Mutations\\Category\\UpdateCategoryMutation::class,
                <span class="hljs-string">'deleteCategory'</span> =&gt; \\App\\GraphQL\\Mutations\\Category\\DeleteCategoryMutation::class,
            ],
            <span class="hljs-string">'middleware'</span> =&gt; [],
            <span class="hljs-string">'method'</span> =&gt; [<span class="hljs-string">'get'</span>, <span class="hljs-string">'post'</span>],
        ],
    ],

        <span class="hljs-string">'types'</span> =&gt; [
       <span class="hljs-string">'Quest'</span> =&gt; \\App\\GraphQL\\Types\\QuestType::class,
       <span class="hljs-string">'Category'</span> =&gt; \\App\\GraphQL\\Types\\CategoryType::class
    ],

    <span class="hljs-comment">// some code </span>
];
</code></pre>
<p>Now that all that's done, let's try out our APIs.</p>
<h2 id="heading-how-to-test-the-queries">How to Test the Queries</h2>
<p>Our GraphQL library provides us with an IDE.</p>
<p>So make sure your Docker containers are running and head into <a target="_blank" href="http://localhost/graphiql">http://localhost/graphiql</a>.</p>
<p>You should see something like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/6.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Let us test our queries:</p>
<h3 id="heading-fetch-a-single-quest">Fetch a Single Quest</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/7.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-fetch-a-list-of-quests">Fetch a List of Quests</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/8.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-insert-a-quest-into-the-database">Insert a Quest into the Database</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/9.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-update-a-quest">Update a Quest</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/10.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-delete-a-quest-from-the-database">Delete a Quest from the Database</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/05/11.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Congratulations, you have created your first GraphQL API.</p>
<p>In summary:</p>
<ul>
<li>A GraphQL API consists of three parts: Queries, Types, and Mutations.</li>
<li>Mutations manage your CRUD operations.</li>
<li>Queries fetch from the database.</li>
<li>Types are the model resource that gets returned to the client.</li>
</ul>
<p>Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
