### GraphQL Federation Steps Source: https://graphql.org/learn/federation Steps to get started with GraphQL federation, from identifying service boundaries to using a schema registry. ```graphql 1. Identify Service Boundaries 2. Design Schemas 3. Implement Subgraphs 4. Set Up a Gateway 5. Use a Schema Registry ``` -------------------------------- ### GraphQL Type System Example Source: https://graphql.org/learn/execution An example GraphQL schema defining types like Query, Human, Episode, and Starship, used to illustrate the execution process. ```graphql type Query { human(id: ID!): Human } type Human { name: String appearsIn: [Episode] starships: [Starship] } enum Episode { NEWHOPE EMPIRE JEDI } type Starship { name: String } ``` -------------------------------- ### JavaScript Resolver Example (Conceptual) Source: https://graphql.org/learn/execution A conceptual JavaScript example of a resolver function for the 'human' field, demonstrating how data might be fetched. ```javascript const resolvers = { Query: { human: (obj, args, context, info) => { // Fetch human data based on args.id from a data source return fetchHumanById(args.id); } }, Human: { name: (human) => human.name, appearsIn: (human) => human.appearsIn, starships: (human) => fetchStarshipsForHuman(human.id) }, Starship: { name: (starship) => starship.name } }; // Placeholder functions for data fetching function fetchHumanById(id) { // ... implementation to get human data ... return { id: id, name: 'Han Solo', appearsIn: ['NEWHOPE', 'EMPIRE', 'JEDI'] }; } function fetchStarshipsForHuman(humanId) { // ... implementation to get starships for a human ... return [{ name: 'Millenium Falcon' }, { name: 'Imperial shuttle' }]; } ``` -------------------------------- ### GraphQL Query Example Source: https://graphql.org/learn/execution An example GraphQL query requesting specific fields for a 'human' and their associated 'starships'. ```graphql query { human(id: 1002) { name appearsIn starships { name } } } ``` -------------------------------- ### Interactive GraphQL Query Example Source: https://graphql.org/learn/index An interactive example showing how to query hero details and add additional fields. The response structure is also provided. ```graphql { hero{ name # add additional fields here! } } ``` ```json { "data":{ "hero":{ "name":"R2-D2" } } } ``` -------------------------------- ### GraphQL Query and Response Example Source: https://graphql.org/learn/execution Presents a sample GraphQL query for a 'human' object and its corresponding JSON response. This showcases how the resolved fields, including nested objects and lists, are structured to match the query. ```graphql query{ human(id:1002){ name appearsIn starships{ name } } } ``` ```json { "data":{ "human":{ "name":"Han Solo", "appearsIn":[ "NEWHOPE", "EMPIRE", "JEDI" ], "starships":[ { "name":"Millenium Falcon" }, { "name":"Imperial shuttle" } ] } } } ``` -------------------------------- ### GraphQL Response Example Source: https://graphql.org/learn/execution The expected JSON response structure mirroring the GraphQL query, containing the requested data for 'human' and their 'starships'. ```json { "data": { "human": { "name": "Han Solo", "appearsIn": [ "NEWHOPE", "EMPIRE", "JEDI" ], "starships": [ { "name": "Millenium Falcon" }, { "name": "Imperial shuttle" } ] } } } ``` -------------------------------- ### GraphQL Root Query Resolver Example Source: https://graphql.org/learn/execution Example of a JavaScript resolver function for a 'human' query field. It takes arguments, context (including a database), and info to load human data by ID and return a Human type. ```javascript function resolveHumanQuery(obj, args, context, info) { return context.db.loadHumanByID(args.id).then(userData => new Human(userData)); } ``` -------------------------------- ### GraphQL Connection Pagination Query Example Source: https://graphql.org/learn/pagination An example GraphQL query demonstrating how to fetch paginated data using the friendsConnection field, specifying the number of items and an after cursor. ```graphql query{ hero{ name friendsConnection(first:2, after:"Y3Vyc29yMQ=="){ totalCount edges{ node{ name } cursor } pageInfo{ endCursor hasNextPage } } } } ``` -------------------------------- ### Initiating a GraphQL Subscription Operation Source: https://graphql.org/learn/subscriptions Shows how to start a subscription by using the 'subscription' keyword and specifying the operation name and fields to receive. ```graphql subscription NewReviewCreated { reviewCreated { rating commentary } } ``` -------------------------------- ### GraphQL Connection Pagination Response Example Source: https://graphql.org/learn/pagination An example JSON response for a GraphQL query using the connection model, showing the total count, edges with nodes and cursors, and page information. ```json { "data":{ "hero":{ "name":"R2-D2", "friendsConnection":{ "totalCount":3, "edges":[ { "node":{ "name":"Han Solo" }, "cursor":"Y3Vyc29yMg==" }, { "node":{ "name":"Leia Organa" }, "cursor":"Y3Vyc29yMw==" } ], "pageInfo":{ "endCursor":"Y3Vyc29yMw==", "hasNextPage":false } } } } } ``` -------------------------------- ### GraphQL Node Query Example Source: https://graphql.org/learn/global-object-identification An example GraphQL query demonstrating how to fetch a node by its ID and use interface fragments to retrieve type-specific fields. ```graphql { node(id: "4") { id ... on User { name } } } ``` -------------------------------- ### GraphQL Performance Optimization Guide Source: https://graphql.org/learn/performance This documentation outlines various strategies for optimizing GraphQL performance. It covers client-side caching, server-side optimizations, and transport layer improvements. Key topics include handling GET requests for queries, addressing the N+1 problem, implementing demand control, utilizing GZIP compression, and performance monitoring. ```APIDOC GraphQL Performance Optimization: Overview: GraphQL requests can be optimized for performance through various client-side, server-side, and transport layer strategies. Despite serving through a single endpoint, GraphQL is cacheable similar to REST APIs with parameterized requests. Key Optimization Tactics: 1. Client-side Caching: - Implement caching strategies to improve performance and ensure a consistent, responsive user interface. - Refer to detailed client-side caching documentation for implementation. 2. GET Requests for Queries: - Utilize GET requests for queries to leverage HTTP caching mechanisms. - Ensure queries are properly formatted as URL parameters. 3. The N+1 Problem: - Address the N+1 problem, which occurs when fetching related data inefficiently. - Implement techniques like DataLoader to batch requests and reduce redundant database queries. 4. Demand Control: - Implement mechanisms to control the rate and complexity of incoming requests. - This can include query depth limiting, complexity scoring, and rate limiting. 5. JSON (with GZIP): - Compress JSON responses using GZIP to reduce payload size and improve transfer speed. - Ensure both client and server support GZIP compression. 6. Performance Monitoring: - Implement monitoring tools to track request latency, error rates, and resource utilization. - Analyze performance metrics to identify bottlenecks and areas for improvement. 7. Best Practices: - Follow GraphQL best practices for schema design, query optimization, and efficient data fetching. - Consider strategies like pagination, authorization, and federation for scalable applications. ``` -------------------------------- ### GraphQL Query Response Example Source: https://graphql.org/learn/queries Illustrates a typical response from a GraphQL server for the given query and variables. ```json { "data": { "hero": { "name": "R2-D2" } } } ``` -------------------------------- ### GraphQL Object Equality Response Example Source: https://graphql.org/learn/global-object-identification This JSON response illustrates the expected output for the GraphQL object equality example, showing consistent data for objects with the same ID. ```json { "fourNode": { "id": "4", "name": "Mark Zuckerberg", "userWithIdOneGreater": { "id": "5", "name": "Chris Hughes" } }, "fiveNode": { "id": "5", "name": "Chris Hughes", "userWithIdOneLess": { "id": "4", "name": "Mark Zuckerberg" } } } ``` -------------------------------- ### GraphQL Query Example Source: https://graphql.org/learn/schema Demonstrates a basic GraphQL query to fetch hero data, including name and appearsIn fields. ```graphql { hero { name appearsIn } } ``` -------------------------------- ### GraphQL Query Variables Example Source: https://graphql.org/learn/queries Provides an example of variables that can be passed to a GraphQL query to alter its execution. ```json { "episode": "JEDI", "withFriends": false } ``` -------------------------------- ### GraphQL HTTP Method Selection Source: https://graphql.org/learn/serving-over-http Explains the considerations for choosing HTTP methods for GraphQL requests. GET is suitable for queries and caching, while POST is required for mutations. Server support for GET varies. ```APIDOC HTTP Method Considerations: GET: Primarily for 'query' operations. Facilitates HTTP caching. May exceed URL length limits for complex queries. POST: Required for 'mutation' operations. Can handle longer requests. Server Discretion: Support for methods other than POST is server-dependent. Persisted Documents: Clients can send document identifiers instead of full query text for long operations. ``` -------------------------------- ### GraphQL Query Response Example Source: https://graphql.org/learn/schema Illustrates the JSON response structure for a GraphQL query, showing the fetched hero data. ```json { "data": { "hero": { "name": "R2-D2", "appearsIn": [ "NEWHOPE", "EMPIRE", "JEDI" ] } } } ``` -------------------------------- ### GraphQL Cursor-Based Pagination Example Source: https://graphql.org/learn/pagination Demonstrates a GraphQL query using cursor-based pagination to fetch a list of friends, including their nodes and cursors. ```graphql query { hero { name friends(first: 2) { edges { node { name } cursor } } } } ``` -------------------------------- ### GraphQL Operation Example Source: https://graphql.org/learn/security Demonstrates a GraphQL operation query to fetch starship data, including its width. ```graphql query{ starship(id:3000){ width } } ``` -------------------------------- ### GraphQL Deprecated Directive Example Source: https://graphql.org/learn/schema Demonstrates the usage of the built-in @deprecated directive to mark schema fields as deprecated, providing a reason for the deprecation. This helps in guiding users to use newer fields. ```graphql type User { fullName: String name: String @deprecated(reason: "Use `fullName`.") } ``` -------------------------------- ### GraphQL HTTP Request Methods Source: https://graphql.org/learn/serving-over-http Defines the recommended HTTP methods for GraphQL operations, prioritizing POST for complex queries and GET for simple queries. ```APIDOC HTTP Methods for GraphQL: POST: Use for: Queries and Mutations, especially those with complex operations or large payloads. Request Body: Contains the GraphQL query, variables, and operation name. GET: Use for: Simple queries that can be represented in the URL. URL Parameters: `query`, `variables`, `operationName`. Choosing an HTTP Method: POST is generally preferred for its flexibility and ability to handle larger requests. GET is suitable for simple, idempotent queries that can be easily cached or bookmarked. ``` -------------------------------- ### JavaScript Resolver for Post Body Authorization (Direct) Source: https://graphql.org/learn/authorization An example of implementing authorization logic directly within a GraphQL field resolver. It checks if the requesting user is the author of the post before returning the body. This approach is discouraged for production due to potential duplication. ```javascript function Post_body(obj, args, context, info) { // Return the post body only if the user is the post's author if (context.user && context.user.id === obj.authorId) { return obj.body; } return null; } ``` -------------------------------- ### GraphQL GET Request URL Structure Source: https://graphql.org/learn/serving-over-http Illustrates how to send a GraphQL query via an HTTP GET request using query parameters for the query, variables, and operationName. ```http http://myapi/graphql?query={me{name}} ``` -------------------------------- ### Asynchronous Resolver with Promise Handling Source: https://graphql.org/learn/execution Illustrates an asynchronous JavaScript resolver that loads data from a database using a Promise. GraphQL execution waits for the Promise to resolve before proceeding. ```javascript function resolveHuman(obj, args, context, info) { return context.db.loadHumanByID(args.id).then(userData => new Human(userData)); } ``` -------------------------------- ### GraphQL Username Query Source: https://graphql.org/learn/global-object-identification Example of a GraphQL root field 'username' that takes a username string and returns a user object with an ID. ```graphql { username(username: "zuck") { id } } ``` -------------------------------- ### GraphQL Schema Descriptions Example Source: https://graphql.org/learn/schema Illustrates how to add Markdown-formatted descriptions to types, fields, and enum values in a GraphQL schema. These descriptions enhance clarity and are accessible via introspection. ```graphql """ A character from the Star Wars universe """ type Character { "The name of the character." name: String! } """ The episodes in the Star Wars trilogy """ enum Episode { "Star Wars Episode IV: A New Hope, released in 1977." NEWHOPE "Star Wars Episode V: The Empire Strikes Back, released in 1980." EMPIRE "Star Wars Episode VI: Return of the Jedi, released in 1983." JEDI } """ The query type, represents all of the entry points into our object graph """ type Query { """ Fetches the hero of a specified Star Wars film. """ hero( "The name of the film that the hero appears in." episode: Episode ): Character } ``` -------------------------------- ### GraphQL Usernames Response Source: https://graphql.org/learn/global-object-identification Example JSON response for a GraphQL 'usernames' query, returning a list of user objects with IDs, corresponding to the input list. ```json { "usernames": [ { "id": "4" }, { "id": "6" } ] } ``` -------------------------------- ### GraphQL Resolver Arguments Explanation Source: https://graphql.org/learn/execution Details the four arguments provided to every GraphQL resolver function: obj (previous object), args (field arguments), context (contextual information), and info (field-specific details). ```graphql Resolver Arguments: * obj: The previous object (for a field on the root `Query` type, this argument is often not used). * args: The arguments provided to the field in the GraphQL operation. * context: A value provided to every resolver that may hold important contextual information like the currently logged in user, or access to a database. * info: generally only used in advanced use-cases, this is a value holding field-specific information relevant to the current operation as well as the schema details; refer to [type GraphQLResolveInfo](https://graphql.org/graphql-js/type/#graphqlobjecttype) for more details. ``` -------------------------------- ### GraphQL Query Comments Example Source: https://graphql.org/learn/schema Shows how to include single-line comments within a GraphQL query. These comments are useful for explaining parts of the query to other developers and are ignored during execution. ```graphql { hero{ name # Queries can have comments! friends{ name } } } ``` -------------------------------- ### GraphQL N+1 Problem Response Example Source: https://graphql.org/learn/performance A sample response for the GraphQL query demonstrating the nested data structure. The N+1 problem arises from the repeated fetching of starship data for each friend. ```json { "data": { "hero": { "name": "R2-D2", "friends": [ { "name": "Luke Skywalker", "starships": [ { "name": "X-Wing" }, { "name": "Imperial shuttle" } ] }, { "name": "Han Solo", "starships": [ { "name": "Millenium Falcon" }, { "name": "Imperial shuttle" } ] }, { "name": "Leia Organa", "starships": [] } ] } } } ``` -------------------------------- ### GraphQL Post Type Schema Source: https://graphql.org/learn/authorization Defines a GraphQL 'Post' type with an authorId and body. This serves as a basic data structure for demonstrating authorization. ```graphql type Post { authorId: ID! body: String } ``` -------------------------------- ### GraphQL Username Response Source: https://graphql.org/learn/global-object-identification Example JSON response for a GraphQL 'username' query, returning a user object with an ID. ```json { "username": { "id": "4" } } ``` -------------------------------- ### GraphQL User Type Implementing Node Interface Source: https://graphql.org/learn/global-object-identification An example of a 'User' type in GraphQL that implements the 'Node' interface, including its ID and name fields. ```graphql type User implements Node { id: ID! # Full name name: String! } ``` -------------------------------- ### GraphQL Object Equality Example Source: https://graphql.org/learn/global-object-identification This GraphQL query demonstrates how objects implementing the Node interface should behave when queried with identical IDs, ensuring field stability. ```graphql { fourNode: node(id: "4") { id ... on User { name userWithIdOneGreater { id name } } } fiveNode: node(id: "5") { id ... on User { name userWithIdOneLess { id name } } } } ``` -------------------------------- ### GraphQL Usernames Query Source: https://graphql.org/learn/global-object-identification Example of a GraphQL 'plural identifying root field' named 'usernames' that accepts a list of usernames and returns a list of user objects with IDs. ```graphql { usernames(usernames: ["zuck", "moskov"]) { id } } ``` -------------------------------- ### GraphQL Mutation Operation for Creating a Review Source: https://graphql.org/learn/mutations An example GraphQL mutation operation to create a review for a specific episode, including the selection of fields to return. ```graphql mutationCreateReviewForEpisode($ep:Episode!, $review:ReviewInput!){ createReview(episode:$ep, review:$review){ stars commentary } } ``` -------------------------------- ### GraphQL Operation Example Source: https://graphql.org/learn/security Demonstrates a GraphQL query with nested fields and a paginated field (friendsConnection) compared to an unbounded field (friends). This illustrates how pagination limits the data returned. ```graphql query{ hero{ name friends{ name } friendsConnection(first:1){ edges{ node{ name } } } } } ``` -------------------------------- ### GraphQL Batching Example Source: https://graphql.org/learn/security Illustrates a GraphQL request containing multiple independent query operations. This highlights the need for batching limits to prevent excessive round trips and resource consumption. ```graphql query NewHopeHero { hero(episode: NEWHOPE) { name } } query EmpireHero { hero(episode: EMPIRE) { name } } # ... query JediHero { hero(episode: JEDI) { name } } ``` -------------------------------- ### JavaScript Business Logic for Post Body Authorization Source: https://graphql.org/learn/authorization Demonstrates how to implement authorization logic within a business logic layer (e.g., a repository). This promotes reusability and maintainability by centralizing authorization checks. ```javascript // Authorization logic lives inside `postRepository` export const postRepository = { getBody({ user, post }) { const isAuthor = user?.id === post.authorId; return isAuthor ? post.body : null; }, }; import { postRepository } from "postRepository"; function resolvePostBody(obj, args, context, info) { // Return the post body only if the user is the post's author return postRepository.getBody({ user: context.user, post: obj, }); } ``` -------------------------------- ### GraphQL Schema Comments Example Source: https://graphql.org/learn/schema Demonstrates how to add single-line comments within a GraphQL schema definition. These comments are ignored by the GraphQL parser and are not exposed through introspection. ```graphql # This line is treated like whitespace and ignored by GraphQL type Character { name: String! } ``` -------------------------------- ### Multiple Starship Deletions Source: https://graphql.org/learn/mutations This example demonstrates executing multiple mutation fields in series within a single request. It shows how fields are executed sequentially, ensuring one completes before the next begins. ```graphql mutation{ firstShip:deleteStarship(id:"3001") secondShip:deleteStarship(id:"3002") } ``` ```json { "data":{ "firstShip":"3001", "secondShip":"3002" } } ``` -------------------------------- ### Trivial Resolver for Object Property Source: https://graphql.org/learn/execution A simple JavaScript resolver that returns a property ('name') from the parent object. Many GraphQL libraries allow omitting such trivial resolvers. ```javascript function resolveHumanName(obj, args, context, info) { return obj.name; } ``` -------------------------------- ### GraphQL N+1 Problem Example Source: https://graphql.org/learn/performance Illustrates the N+1 problem in GraphQL where fetching a hero and their friends leads to multiple database requests for each friend's starships. This is typically solved using batching techniques like DataLoader. ```graphql query HeroWithFriends { hero { name friends { name ... on Human { starships { name } } } } } ``` -------------------------------- ### GraphQL Query with Fragments Source: https://graphql.org/learn/queries This example demonstrates how to use GraphQL fragments to avoid repeating fields when querying data for two heroes side-by-side. It defines a fragment 'comparisonFields' and uses it in the main query to fetch hero details and their friends. ```graphql query { leftComparison: hero(episode: EMPIRE) { ...comparisonFields } rightComparison: hero(episode: JEDI) { ...comparisonFields } } fragment comparisonFields on Character { name appearsIn friends { name } } ``` -------------------------------- ### Example Federated GraphQL Query Source: https://graphql.org/learn/federation A client query that spans across multiple subgraphs (User, Orders, Product) through the federated gateway. The gateway resolves fields from different services. ```graphql query { user(id: "123") { # Resolved by Users subgraph name orders { # Resolved by Orders subgraph id products { # Resolved by Products subgraph title price } } } } ``` -------------------------------- ### GraphQL Error Response Example (200 OK) Source: https://graphql.org/learn/debug-errors Illustrates a typical GraphQL error response when the HTTP request succeeds (200 OK) but the GraphQL operation encounters issues. This includes the 'errors' array with detailed error messages and locations. ```graphql { "errors": [ { "message": "Cannot query field \"foo\" on type \"Query\".", "locations": [{ "line": 1, "column": 3 }] } ] } ``` -------------------------------- ### GraphQL Breadth Limiting Example Source: https://graphql.org/learn/security Demonstrates a GraphQL query with multiple aliased fields to illustrate the concept of breadth limiting. This query, while shallow in depth, can overload the data source due to numerous top-level fields. ```graphql query { viewer { friends1: friends(limit: 1) { name } friends2: friends(limit: 2) { name } friends3: friends(limit: 3) { name } # ... friends100: friends(limit: 100) { name } } } ``` -------------------------------- ### GraphQL Query with Fragments and Variables Source: https://graphql.org/learn/queries This example shows how to use variables within GraphQL fragments. The 'queryHeroComparison' operation accepts a 'first' variable to limit the number of friends displayed, demonstrating dynamic data fetching with fragments. ```graphql query HeroComparison($first: Int = 3) { leftComparison: hero(episode: EMPIRE) { ...comparisonFields } rightComparison: hero(episode: JEDI) { ...comparisonFields } } fragment comparisonFields on Character { name friendsConnection(first: $first) { totalCount edges { node { name } } } } ``` -------------------------------- ### Basic GraphQL Query Source: https://graphql.org/learn/index Demonstrates a simple GraphQL query to fetch a user's name and the corresponding JSON response. ```graphql { me { name } } ``` ```json { "data": { "me": { "name": "Luke Skywalker" } } } ``` -------------------------------- ### GraphQL Query for Object Data Source: https://graphql.org/learn/caching This GraphQL query demonstrates how to fetch specific fields for a 'starship' and a 'droid', including its friends. It utilizes the 'id' field for object identification, which is crucial for client-side caching. ```graphql query{ starship(id:"3003"){ id name } droid(id:"2001"){ id name friends{ id name } } } ``` -------------------------------- ### GraphQL Introspection Reference Implementation (JavaScript) Source: https://graphql.org/learn/introspection This link points to the reference implementation of a specification-compliant GraphQL query introspection system in JavaScript, located in the graphql-js library. It serves as an example for developers building their own introspection systems. ```javascript https://github.com/graphql/graphql-js/blob/e9b6b626f6f6aa379bb8f8c48df40d0c02a26082/src/type/introspection.ts ``` -------------------------------- ### GraphQL Schema Directive for Authorization Source: https://graphql.org/learn/authorization Defines a custom GraphQL directive '@auth' to enforce authorization rules at the schema level. This example shows how to specify that only an author can access the 'body' field of a 'Post'. ```graphql directive @auth(rule: Rule) on FIELD_DEFINITION enum Rule { IS_AUTHOR } type Post { authorId: ID! body: String @auth(rule: IS_AUTHOR) } ``` -------------------------------- ### GraphQL Authorization Overview Source: https://graphql.org/learn/authorization This section explains the fundamental concepts of authorization in GraphQL, emphasizing the delegation of logic to the business layer and the integration with authentication middleware. It covers how to determine if an authenticated user has permission to access specific fields within a GraphQL request. ```graphql Delegate authorization logic to the business logic layer Most APIs will need to secure access to certain types of data depending on who requested it, and GraphQL is no different. GraphQL execution should begin after [authentication](https://graphql.org/graphql-js/authentication-and-express-middleware/) middleware confirms the user’s identity and passes that information to the GraphQL layer. But after that, you still need to determine if the authenticated user is allowed to view the data provided by the specific fields that were included in the request. On this page, we’ll explore how a GraphQL schema can support authorization. ``` -------------------------------- ### GraphQL Query Basics Source: https://graphql.org/learn/queries Demonstrates the fundamental structure of a GraphQL query, including selecting fields and arguments. ```graphql query GetUserData { user(id: "123") { id name email } } ``` -------------------------------- ### GraphQL Type Name Introspection Example Source: https://graphql.org/learn/introspection Demonstrates how to use the `__typename` meta-field to get the string value of the names of different types returned by a search query. This field is automatically provided by GraphQL implementations for Object, Interface, or Union types. ```graphql query{ search(text:"an"){ __typename ...on Character{ name } ...on Starship{ name } } } ``` ```json { "data":{ "search":[ { "__typename":"Human", "name":"Han Solo" }, { "__typename":"Human", "name":"Leia Organa" }, { "__typename":"Starship", "name":"TIE Advanced x1" } ] } } ``` -------------------------------- ### JavaScript Resolver for Enum List Source: https://graphql.org/learn/execution Demonstrates a JavaScript resolver function for a field that returns a list of Enum values. It shows how the resolver returns raw data (numbers) which are then coerced by the GraphQL type system into the expected Enum types (e.g., 'NEWHOPE'). ```javascript const Human = { appearsIn(obj) { return obj.appearsIn; // e.g. [4, 5, 6] }, }; ``` -------------------------------- ### GraphQL Schema Evolution with Deprecation Source: https://graphql.org/learn/index Illustrates how to evolve a GraphQL API by adding new fields and marking existing fields as deprecated. ```graphql type User { fullName: String nickname: String name: String @deprecated(reason: "Use `fullName`.") } ``` -------------------------------- ### GraphQL Best Practices Overview Source: https://graphql.org/learn/best-practices This section provides an overview of key GraphQL best practices, linking to detailed articles on specific topics. It covers modeling business domains as graphs, serving GraphQL over HTTP, authorization strategies, pagination, schema design, global object identification, caching, performance optimization, security, and common HTTP errors. ```graphql # GraphQL Best Practices # Thinking in Graphs: Model your business domain as a graph # Serving over HTTP: Handle GraphQL requests on HTTP servers # Authorization: Delegate authorization logic to the business logic layer # Pagination: Allow clients to traverse lists of objects with a consistent field pagination model # Schema Design: Design and evolve a type system over time without versions # Global Object Identification: Consistent object access enables simple caching and object lookups # Caching: Provide Object Identifiers so clients can build rich caches # Performance: Optimize the execution and delivery of GraphQL responses # Security: Protect GraphQL APIs from malicious operations # Common Errors: Learn about common `graphql-http` errors and how to debug them. ``` -------------------------------- ### GraphQL Subscription Basics Source: https://graphql.org/learn/subscriptions Demonstrates the fundamental structure of a GraphQL subscription operation. Subscriptions allow clients to receive real-time updates from the server, similar to how queries fetch data. ```graphql subscription OnNewMessage { newMessage { id text sender { name } } } ``` -------------------------------- ### GraphQL GET Request for Queries Source: https://graphql.org/learn/performance GraphQL can support GET requests for queries, which are cacheable by default and can improve performance when used with caching headers. However, URL size limits may require using persisted queries with hashes for complex operations. ```http GET /graphql?query={hero{name}} Host: example.com Accept: application/json ``` -------------------------------- ### GraphQL HTTP Error: 405 Method Not Allowed Source: https://graphql.org/learn/debug-errors This error signifies that the HTTP method used to access the GraphQL endpoint is not supported. GraphQL APIs typically expect POST requests for queries and mutations, but GET requests might be used for specific scenarios like Apollo Server's GET requests for queries. ```APIDOC HTTP Status Code: 405 Method Not Allowed Description: The HTTP method used for the request is not allowed for the target resource. GraphQL APIs commonly use POST for queries and mutations. Common Causes: - Using GET when POST is required (or vice-versa, depending on server configuration). - Incorrectly configured server routing. How to Debug: - Verify the expected HTTP method for your GraphQL endpoint (usually POST). - Ensure your client is sending the correct method. - Check server-side configurations for allowed HTTP methods. ``` -------------------------------- ### GraphQL Schema Definition Source: https://graphql.org/learn/index Defines the types and fields for a GraphQL service, specifying the data structure and relationships. ```graphql type Query { me: User } type User { name: String } ``` -------------------------------- ### GraphQL Built-in Directives Source: https://graphql.org/learn/queries Details the core executable directives provided by the GraphQL specification: @include and @skip. ```APIDOC @include(if: Boolean) - Only include this field in the result if the argument is true. @skip(if: Boolean) - Skip this field if the argument is true. ``` -------------------------------- ### GraphQL Response Error Example Source: https://graphql.org/learn/security Illustrates a GraphQL response containing an error message indicating an invalid field 'width' and suggesting 'id' as an alternative. ```json { "errors":[ { "message":"Cannot query field \"width\" on type \"Starship\". Did you mean \"id\"?", "locations":[ { "line":3, "column":5 } ] } ] } ``` -------------------------------- ### GraphQL HTTP Headers Source: https://graphql.org/learn/serving-over-http Specifies the required and recommended HTTP headers for GraphQL clients and servers, including Accept and Content-Type. ```http Accept: application/graphql-response+json, application/json Content-Type: application/json ``` -------------------------------- ### GraphQL Mutation Operation for Updating Human Name Source: https://graphql.org/learn/mutations An example GraphQL mutation operation to update a human's name, including the fields to retrieve after the update. ```graphql mutationUpdateHumanName($id:ID!, $name:String!){ updateHumanName(id:$id, name:$name){ id name } } ``` -------------------------------- ### GraphQL Response: Data with Inline Fragment Source: https://graphql.org/learn/validation Example JSON response for a valid GraphQL query using an inline fragment, successfully retrieving the 'name' and 'primaryFunction' for the hero. ```json { "data":{ "hero":{ "name":"R2-D2", "primaryFunction":"Astromech" } } } ``` -------------------------------- ### GraphQL Response: Data with Named Fragment Source: https://graphql.org/learn/validation Example JSON response for a valid GraphQL query using a named fragment, successfully retrieving the 'name' and 'primaryFunction' for the hero. ```json { "data":{ "hero":{ "name":"R2-D2", "primaryFunction":"Astromech" } } } ``` -------------------------------- ### GraphQL Resolver Functions (JavaScript) Source: https://graphql.org/learn/index Provides the data for fields defined in the GraphQL schema. These functions interact with data sources like databases or external services. ```javascript // Resolver for the `me` field on the `Query` type function resolveQueryMe(_parent, _args, context, _info) { return context.request.auth.user; } // Resolver for the `name` field on the `User` type function resolveUserName(user, _args, context, _info) { return context.db.getUserFullName(user.id); } ``` -------------------------------- ### GraphQL Connection Object with PageInfo Source: https://graphql.org/learn/pagination Illustrates a GraphQL query that utilizes a connection object to retrieve total count, edges, and page information (endCursor, hasNextPage) for pagination. ```graphql query { hero { name friends(first: 2) { totalCount edges { node { name } cursor } pageInfo { endCursor hasNextPage } } } } ``` -------------------------------- ### GraphQL Response: Error for Missing Selection Set Source: https://graphql.org/learn/validation Example JSON response for an invalid GraphQL query, indicating that the 'hero' field of type 'Character' requires a selection of subfields. ```json { "errors":[ { "message":"Field \"hero\" of type \"Character\" must have a selection of subfields. Did you mean \"hero { ... }\"?", "locations":[ { "line":3, "column":3 } ] } ] } ``` -------------------------------- ### GraphQL Fragments Source: https://graphql.org/learn/queries Demonstrates the use of fragments to define reusable sets of fields in GraphQL queries, promoting DRY principles. ```graphql fragment UserFields on User { id name email } query GetUsers { users { ...UserFields } } ``` -------------------------------- ### Deeply Nested GraphQL Query Source: https://graphql.org/learn/security An example of a deeply nested GraphQL query that could potentially place excessive load on server resources. This highlights the need for depth limiting. ```graphql query { hero { name friends { name friends { name friends { name friends { name } } } } } } ``` -------------------------------- ### GraphQL Hero Friends Query with Slicing Source: https://graphql.org/learn/pagination A GraphQL query demonstrating slicing by requesting only the first two friends of a hero. This introduces the 'first' argument for pagination. ```graphql query { hero { name friends(first: 2) { name } } } ``` -------------------------------- ### GraphQL Connection Model Schema Source: https://graphql.org/learn/pagination Defines the GraphQL schema for a connection model, including interfaces, types for characters, connections, edges, and page information, enabling cursor-based pagination. ```graphql interface Character { id: ID! name: String! friends: [Character] friendsConnection(first: Int, after: ID): FriendsConnection! appearsIn: [Episode]! } type FriendsConnection { totalCount: Int edges: [FriendsEdge] friends: [Character] pageInfo: PageInfo! } type FriendsEdge { cursor: ID! node: Character } type PageInfo { startCursor: ID endCursor: ID hasNextPage: Boolean! } ``` -------------------------------- ### GraphQL HTTP Request/Response Conventions Source: https://graphql.org/learn/serving-over-http Defines standard practices for GraphQL requests and responses over HTTP, including endpoint structure, supported methods, media types, and the format of data and errors in the response body. ```APIDOC GraphQL HTTP Conventions: Endpoint: - Typically exposed at a single endpoint, e.g., `/graphql`. Request Methods: - `POST`: Primary method for GraphQL requests. - `GET`: May be used for query operations. Media Types: - Request `Accept` Header: `application/graphql-response+json` (client should indicate). - Request `Content-Type` Header (for POST): `application/json`. - Response Body: - `data`: Contains the full or partial result of a GraphQL operation. - `errors`: Contains information about validation or execution errors. Response Status Codes: - `2xx`: For valid GraphQL operations that succeed or fail gracefully (e.g., when `data` is non-null). Authentication & Authorization: - Authentication: Should be handled by the server before GraphQL request validation. - Authorization: Should be handled within business logic during GraphQL request execution. ``` -------------------------------- ### GraphQL Mutation Response for Creating a Review Source: https://graphql.org/learn/mutations The expected response structure after successfully executing the createReview mutation. ```graphql { "data":{ "createReview":{ "stars":5, "commentary":"This is a great movie!" } } } ``` -------------------------------- ### GraphQL Type System Overview Source: https://graphql.org/learn/schema Explains the fundamental concepts of the GraphQL type system, which defines the data that can be queried from an API. It covers the six kinds of named type definitions and other features used to describe data and relationships. ```graphql The GraphQL [type system](https://spec.graphql.org/draft/#sec-Type-System) describes what data can be queried from the API. The collection of those capabilities is referred to as the service’s _schema_ and clients can use that schema to send queries to the API that return predictable results. On this page, we’ll explore GraphQL’s [six kinds of named type definitions](https://spec.graphql.org/draft/#sec-Types) as well as other features of the type system to learn how they may be used to describe your data and the relationships between them. Since GraphQL can be used with any backend framework or programming language, we’ll avoid implementation-specific details and talk only about the concepts. ``` -------------------------------- ### GraphQL Introspection: Get Type Fields Source: https://graphql.org/learn/introspection This GraphQL query retrieves the fields available for a given Object type. It lists the name of each field and the type it returns, providing insight into the data that can be accessed. ```graphql query { __type(name: "Droid") { name fields { name type { ``` -------------------------------- ### GraphQL Introspection: Get Root Query Type Source: https://graphql.org/learn/introspection This GraphQL query identifies the entry point for all queries in the schema. It specifically asks for the name of the root query type, which is conventionally named 'Query'. ```graphql query { __schema { queryType { name } } } ``` -------------------------------- ### GraphQL Introspection: Get Type Name and Kind Source: https://graphql.org/learn/introspection This GraphQL query fetches both the name and the kind (e.g., OBJECT, INTERFACE, SCALAR) of a specified type. This helps in understanding the nature and structure of the type. ```graphql query { __type(name: "Droid") { name kind } } ``` -------------------------------- ### GraphQL Response Media Types Source: https://graphql.org/learn/debug-errors Demonstrates the use of `application/graphql-response+json` and `application/json` for GraphQL server responses. It also shows how clients can request these types using the `Accept` header, prioritizing the newer format. ```http Accept: application/graphql-response+json, application/json;q=0.9 ``` -------------------------------- ### GraphQL Response: Error for Field Not on Interface Source: https://graphql.org/learn/validation Example JSON response for an invalid GraphQL query attempting to fetch 'primaryFunction' on the 'Character' type. The error suggests using an inline fragment on 'Droid' for this field. ```json { "errors":[ { "message":"Cannot query field \"primaryFunction\" on type \"Character\". Did you mean to use an inline fragment on \"Droid\"?", "locations":[ { "line":5, "column":5 } ] } ] } ``` -------------------------------- ### GraphQL Hero Friends Query Source: https://graphql.org/learn/pagination A basic GraphQL query to fetch the name of a hero and the names of their friends. This demonstrates a simple plural list retrieval. ```graphql query { hero { name friends { name } } } ``` -------------------------------- ### GraphQL over HTTP Specification Source: https://graphql.org/learn/serving-over-http Details how to expose and consume a GraphQL API using an HTTP transport. This draft specification aims to maximize interoperability between clients and libraries. ```APIDOC GraphQL over HTTP Specification: URL: https://graphql.github.io/graphql-over-http/draft/ Purpose: Standardizes GraphQL API exposure and consumption over HTTP. Status: Draft specification, aims for interoperability. Applies to: Stateless query and mutation operations. Excludes: Subscriptions (refer to Subscriptions page for protocols). ``` -------------------------------- ### Client-Side Global Identifier Derivation Source: https://graphql.org/learn/caching Explains how clients can derive a globally unique identifier by combining the object's type (queried with `__typename`) with a type-unique identifier. This is an alternative to the server deriving the ID. ```graphql query GetObjectWithTypename($id: ID!) { myObject(id: $id) { __typename ... on MyObject { typeSpecificId } # ... other fields } } // Client-side logic to combine __typename and typeSpecificId for caching key. ``` -------------------------------- ### GraphQL Querying with Arguments Source: https://graphql.org/learn/queries Illustrates how to pass arguments to fields in GraphQL queries. It shows querying a 'human' by 'id' and also demonstrates using an Enum argument ('unit') to transform the 'height' field. ```graphql type Query { human(id: ID!): Human } ``` ```graphql { human(id:"1000") { name height } } ``` ```graphql { human(id:"1000") { name height(unit:FOOT) } } ```