Giter Site home page Giter Site logo

graphql / graphql.github.io Goto Github PK

View Code? Open in Web Editor NEW
816.0 816.0 1.4K 545.12 MB

GraphQL Documentation at graphql.org

Home Page: https://graphql.org

License: MIT License

Less 2.13% TypeScript 34.03% JavaScript 0.99% CSS 1.14% Python 0.29% MDX 61.43%
graphql

graphql.github.io's Introduction

GraphQL

GraphQL Logo

The GraphQL specification is edited in the markdown files found in /spec the latest release of which is published at https://graphql.github.io/graphql-spec/.

The latest draft specification can be found at https://graphql.github.io/graphql-spec/draft/ which tracks the latest commit to the main branch in this repository.

Previous releases of the GraphQL specification can be found at permalinks that match their release tag. For example, https://graphql.github.io/graphql-spec/October2016/. If you are linking directly to the GraphQL specification, it's best to link to a tagged permalink for the particular referenced version.

Overview

This is a Working Draft of the Specification for GraphQL, a query language for APIs created by Facebook.

The target audience for this specification is not the client developer, but those who have, or are actively interested in, building their own GraphQL implementations and tools.

In order to be broadly adopted, GraphQL will have to target a wide variety of backend environments, frameworks, and languages, which will necessitate a collaborative effort across projects and organizations. This specification serves as a point of coordination for this effort.

Looking for help? Find resources from the community.

Getting Started

GraphQL consists of a type system, query language and execution semantics, static validation, and type introspection, each outlined below. To guide you through each of these components, we've written an example designed to illustrate the various pieces of GraphQL.

This example is not comprehensive, but it is designed to quickly introduce the core concepts of GraphQL, to provide some context before diving into the more detailed specification or the GraphQL.js reference implementation.

The premise of the example is that we want to use GraphQL to query for information about characters and locations in the original Star Wars trilogy.

Type System

At the heart of any GraphQL implementation is a description of what types of objects it can return, described in a GraphQL type system and returned in the GraphQL Schema.

For our Star Wars example, the starWarsSchema.ts file in GraphQL.js defines this type system.

The most basic type in the system will be Human, representing characters like Luke, Leia, and Han. All humans in our type system will have a name, so we define the Human type to have a field called "name". This returns a String, and we know that it is not null (since all Humans have a name), so we will define the "name" field to be a non-nullable String. Using a shorthand notation that we will use throughout the spec and documentation, we would describe the human type as:

type Human {
  name: String
}

This shorthand is convenient for describing the basic shape of a type system; the JavaScript implementation is more full-featured, and allows types and fields to be documented. It also sets up the mapping between the type system and the underlying data; for a test case in GraphQL.js, the underlying data is a set of JavaScript objects, but in most cases the backing data will be accessed through some service, and this type system layer will be responsible for mapping from types and fields to that service.

A common pattern in many APIs, and indeed in GraphQL is to give objects an ID that can be used to refetch the object. So let's add that to our Human type. We'll also add a string for their home planet.

type Human {
  id: String
  name: String
  homePlanet: String
}

Since we're talking about the Star Wars trilogy, it would be useful to describe the episodes in which each character appears. To do so, we'll first define an enum, which lists the three episodes in the trilogy:

enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}

Now we want to add a field to Human describing what episodes they were in. This will return a list of Episodes:

type Human {
  id: String
  name: String
  appearsIn: [Episode]
  homePlanet: String
}

Now, let's introduce another type, Droid:

type Droid {
  id: String
  name: String
  appearsIn: [Episode]
  primaryFunction: String
}

Now we have two types! Let's add a way of going between them: humans and droids both have friends. But humans can be friends with both humans and droids. How do we refer to either a human or a droid?

If we look, we note that there's common functionality between humans and droids; they both have IDs, names, and episodes in which they appear. So we'll add an interface, Character, and make both Human and Droid implement it. Once we have that, we can add the friends field, that returns a list of Characters.

Our type system so far is:

enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}

interface Character {
  id: String
  name: String
  friends: [Character]
  appearsIn: [Episode]
}

type Human implements Character {
  id: String
  name: String
  friends: [Character]
  appearsIn: [Episode]
  homePlanet: String
}

type Droid implements Character {
  id: String
  name: String
  friends: [Character]
  appearsIn: [Episode]
  primaryFunction: String
}

One question we might ask, though, is whether any of those fields can return null. By default, null is a permitted value for any type in GraphQL, since fetching data to fulfill a GraphQL query often requires talking to different services that may or may not be available. However, if the type system can guarantee that a type is never null, then we can mark it as Non Null in the type system. We indicate that in our shorthand by adding an "!" after the type. We can update our type system to note that the id is never null.

Note that while in our current implementation, we can guarantee that more fields are non-null (since our current implementation has hard-coded data), we didn't mark them as non-null. One can imagine we would eventually replace our hardcoded data with a backend service, which might not be perfectly reliable; by leaving these fields as nullable, we allow ourselves the flexibility to eventually return null to indicate a backend error, while also telling the client that the error occurred.

enum Episode {
  NEWHOPE
  EMPIRE
  JEDI
}

interface Character {
  id: String!
  name: String
  friends: [Character]
  appearsIn: [Episode]
}

type Human implements Character {
  id: String!
  name: String
  friends: [Character]
  appearsIn: [Episode]
  homePlanet: String
}

type Droid implements Character {
  id: String!
  name: String
  friends: [Character]
  appearsIn: [Episode]
  primaryFunction: String
}

We're missing one last piece: an entry point into the type system.

When we define a schema, we define an object type that is the basis for all query operations. The name of this type is Query by convention, and it describes our public, top-level API. Our Query type for this example will look like this:

type Query {
  hero(episode: Episode): Character
  human(id: String!): Human
  droid(id: String!): Droid
}

In this example, there are three top-level operations that can be done on our schema:

  • hero returns the Character who is the hero of the Star Wars trilogy; it takes an optional argument that allows us to fetch the hero of a specific episode instead.
  • human accepts a non-null string as a query argument, a human's ID, and returns the human with that ID.
  • droid does the same for droids.

These fields demonstrate another feature of the type system, the ability for a field to specify arguments that configure their behavior.

When we package the whole type system together, defining the Query type above as our entry point for queries, this creates a GraphQL Schema.

This example just scratched the surface of the type system. The specification goes into more detail about this topic in the "Type System" section, and the type directory in GraphQL.js contains code implementing a specification-compliant GraphQL type system.

Query Syntax

GraphQL queries declaratively describe what data the issuer wishes to fetch from whoever is fulfilling the GraphQL query.

For our Star Wars example, the starWarsQueryTests.js file in the GraphQL.js repository contains a number of queries and responses. That file is a test file that uses the schema discussed above and a set of sample data, located in starWarsData.js. This test file can be run to exercise the reference implementation.

An example query on the above schema would be:

query HeroNameQuery {
  hero {
    name
  }
}

The initial line, query HeroNameQuery, defines a query with the operation name HeroNameQuery that starts with the schema's root query type; in this case, Query. As defined above, Query has a hero field that returns a Character, so we'll query for that. Character then has a name field that returns a String, so we query for that, completing our query. The result of this query would then be:

{
  "hero": {
    "name": "R2-D2"
  }
}

Specifying the query keyword and an operation name is only required when a GraphQL document defines multiple operations. We therefore could have written the previous query with the query shorthand:

{
  hero {
    name
  }
}

Assuming that the backing data for the GraphQL server identified R2-D2 as the hero. The response continues to vary based on the request; if we asked for R2-D2's ID and friends with this query:

query HeroNameAndFriendsQuery {
  hero {
    id
    name
    friends {
      id
      name
    }
  }
}

then we'll get back a response like this:

{
  "hero": {
    "id": "2001",
    "name": "R2-D2",
    "friends": [
      {
        "id": "1000",
        "name": "Luke Skywalker"
      },
      {
        "id": "1002",
        "name": "Han Solo"
      },
      {
        "id": "1003",
        "name": "Leia Organa"
      }
    ]
  }
}

One of the key aspects of GraphQL is its ability to nest queries. In the above query, we asked for R2-D2's friends, but we can ask for more information about each of those objects. So let's construct a query that asks for R2-D2's friends, gets their name and episode appearances, then asks for each of their friends.

query NestedQuery {
  hero {
    name
    friends {
      name
      appearsIn
      friends {
        name
      }
    }
  }
}

which will give us the nested response

{
  "hero": {
    "name": "R2-D2",
    "friends": [
      {
        "name": "Luke Skywalker",
        "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
        "friends": [
          { "name": "Han Solo" },
          { "name": "Leia Organa" },
          { "name": "C-3PO" },
          { "name": "R2-D2" }
        ]
      },
      {
        "name": "Han Solo",
        "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
        "friends": [
          { "name": "Luke Skywalker" },
          { "name": "Leia Organa" },
          { "name": "R2-D2" }
        ]
      },
      {
        "name": "Leia Organa",
        "appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
        "friends": [
          { "name": "Luke Skywalker" },
          { "name": "Han Solo" },
          { "name": "C-3PO" },
          { "name": "R2-D2" }
        ]
      }
    ]
  }
}

The Query type above defined a way to fetch a human given their ID. We can use it by hard-coding the ID in the query:

query FetchLukeQuery {
  human(id: "1000") {
    name
  }
}

to get

{
  "human": {
    "name": "Luke Skywalker"
  }
}

Alternately, we could have defined the query to have a query parameter:

query FetchSomeIDQuery($someId: String!) {
  human(id: $someId) {
    name
  }
}

This query is now parameterized by $someId; to run it, we must provide that ID. If we ran it with $someId set to "1000", we would get Luke; set to "1002", we would get Han. If we passed an invalid ID here, we would get null back for the human, indicating that no such object exists.

Notice that the key in the response is the name of the field, by default. It is sometimes useful to change this key, for clarity or to avoid key collisions when fetching the same field with different arguments.

We can do that with field aliases, as demonstrated in this query:

query FetchLukeAliased {
  luke: human(id: "1000") {
    name
  }
}

We aliased the result of the human field to the key luke. Now the response is:

{
  "luke": {
    "name": "Luke Skywalker"
  }
}

Notice the key is "luke" and not "human", as it was in our previous example where we did not use the alias.

This is particularly useful if we want to use the same field twice with different arguments, as in the following query:

query FetchLukeAndLeiaAliased {
  luke: human(id: "1000") {
    name
  }
  leia: human(id: "1003") {
    name
  }
}

We aliased the result of the first human field to the key luke, and the second to leia. So the result will be:

{
  "luke": {
    "name": "Luke Skywalker"
  },
  "leia": {
    "name": "Leia Organa"
  }
}

Now imagine we wanted to ask for Luke and Leia's home planets. We could do so with this query:

query DuplicateFields {
  luke: human(id: "1000") {
    name
    homePlanet
  }
  leia: human(id: "1003") {
    name
    homePlanet
  }
}

but we can already see that this could get unwieldy, since we have to add new fields to both parts of the query. Instead, we can extract out the common fields into a fragment, and include the fragment in the query, like this:

query UseFragment {
  luke: human(id: "1000") {
    ...HumanFragment
  }
  leia: human(id: "1003") {
    ...HumanFragment
  }
}

fragment HumanFragment on Human {
  name
  homePlanet
}

Both of those queries give this result:

{
  "luke": {
    "name": "Luke Skywalker",
    "homePlanet": "Tatooine"
  },
  "leia": {
    "name": "Leia Organa",
    "homePlanet": "Alderaan"
  }
}

The UseFragment and DuplicateFields queries will both get the same result, but UseFragment is less verbose; if we wanted to add more fields, we could add it to the common fragment rather than copying it into multiple places.

We defined the type system above, so we know the type of each object in the output; the query can ask for that type using the special field __typename, defined on every object.

query CheckTypeOfR2 {
  hero {
    __typename
    name
  }
}

Since R2-D2 is a droid, this will return

{
  "hero": {
    "__typename": "Droid",
    "name": "R2-D2"
  }
}

This was particularly useful because hero was defined to return a Character, which is an interface; we might want to know what concrete type was actually returned. If we instead asked for the hero of Episode V:

query CheckTypeOfLuke {
  hero(episode: EMPIRE) {
    __typename
    name
  }
}

We would find that it was Luke, who is a Human:

{
  "hero": {
    "__typename": "Human",
    "name": "Luke Skywalker"
  }
}

As with the type system, this example just scratched the surface of the query language. The specification goes into more detail about this topic in the "Language" section, and the language directory in GraphQL.js contains code implementing a specification-compliant GraphQL query language parser and lexer.

Validation

By using the type system, it can be predetermined whether a GraphQL query is valid or not. This allows servers and clients to effectively inform developers when an invalid query has been created, without having to rely on runtime checks.

For our Star Wars example, the file starWarsValidationTests.js contains a number of demonstrations of invalid operations, and is a test file that can be run to exercise the reference implementation's validator.

To start, let's take a complex valid query. This is the NestedQuery example from the above section, but with the duplicated fields factored out into a fragment:

query NestedQueryWithFragment {
  hero {
    ...NameAndAppearances
    friends {
      ...NameAndAppearances
      friends {
        ...NameAndAppearances
      }
    }
  }
}

fragment NameAndAppearances on Character {
  name
  appearsIn
}

And this query is valid. Let's take a look at some invalid queries!

When we query for fields, we have to query for a field that exists on the given type. So as hero returns a Character, we have to query for a field on Character. That type does not have a favoriteSpaceship field, so this query:

# INVALID: favoriteSpaceship does not exist on Character
query HeroSpaceshipQuery {
  hero {
    favoriteSpaceship
  }
}

is invalid.

Whenever we query for a field and it returns something other than a scalar or an enum, we need to specify what data we want to get back from the field. Hero returns a Character, and we've been requesting fields like name and appearsIn on it; if we omit that, the query will not be valid:

# INVALID: hero is not a scalar, so fields are needed
query HeroNoFieldsQuery {
  hero
}

Similarly, if a field is a scalar, it doesn't make sense to query for additional fields on it, and doing so will make the query invalid:

# INVALID: name is a scalar, so fields are not permitted
query HeroFieldsOnScalarQuery {
  hero {
    name {
      firstCharacterOfName
    }
  }
}

Earlier, it was noted that a query can only query for fields on the type in question; when we query for hero which returns a Character, we can only query for fields that exist on Character. What happens if we want to query for R2-D2s primary function, though?

# INVALID: primaryFunction does not exist on Character
query DroidFieldOnCharacter {
  hero {
    name
    primaryFunction
  }
}

That query is invalid, because primaryFunction is not a field on Character. We want some way of indicating that we wish to fetch primaryFunction if the Character is a Droid, and to ignore that field otherwise. We can use the fragments we introduced earlier to do this. By setting up a fragment defined on Droid and including it, we ensure that we only query for primaryFunction where it is defined.

query DroidFieldInFragment {
  hero {
    name
    ...DroidFields
  }
}

fragment DroidFields on Droid {
  primaryFunction
}

This query is valid, but it's a bit verbose; named fragments were valuable above when we used them multiple times, but we're only using this one once. Instead of using a named fragment, we can use an inline fragment; this still allows us to indicate the type we are querying on, but without naming a separate fragment:

query DroidFieldInInlineFragment {
  hero {
    name
    ... on Droid {
      primaryFunction
    }
  }
}

This has just scratched the surface of the validation system; there are a number of validation rules in place to ensure that a GraphQL query is semantically meaningful. The specification goes into more detail about this topic in the "Validation" section, and the validation directory in GraphQL.js contains code implementing a specification-compliant GraphQL validator.

Introspection

It's often useful to ask a GraphQL schema for information about what queries it supports. GraphQL allows us to do so using the introspection system!

For our Star Wars example, the file starWarsIntrospectionTests.js contains a number of queries demonstrating the introspection system, and is a test file that can be run to exercise the reference implementation's introspection system.

We designed the type system, so we know what types are available, but if we didn't, we can ask GraphQL, by querying the __schema field, always available on the root type of a Query. Let's do so now, and ask what types are available.

query IntrospectionTypeQuery {
  __schema {
    types {
      name
    }
  }
}

and we get back:

{
  "__schema": {
    "types": [
      {
        "name": "Query"
      },
      {
        "name": "Character"
      },
      {
        "name": "Human"
      },
      {
        "name": "String"
      },
      {
        "name": "Episode"
      },
      {
        "name": "Droid"
      },
      {
        "name": "__Schema"
      },
      {
        "name": "__Type"
      },
      {
        "name": "__TypeKind"
      },
      {
        "name": "Boolean"
      },
      {
        "name": "__Field"
      },
      {
        "name": "__InputValue"
      },
      {
        "name": "__EnumValue"
      },
      {
        "name": "__Directive"
      }
    ]
  }
}

Wow, that's a lot of types! What are they? Let's group them:

  • Query, Character, Human, Episode, Droid - These are the ones that we defined in our type system.
  • String, Boolean - These are built-in scalars that the type system provided.
  • __Schema, __Type, __TypeKind, __Field, __InputValue, __EnumValue, __Directive - These all are preceded with a double underscore, indicating that they are part of the introspection system.

Now, let's try and figure out a good place to start exploring what queries are available. When we designed our type system, we specified what type all queries would start at; let's ask the introspection system about that!

query IntrospectionQueryTypeQuery {
  __schema {
    queryType {
      name
    }
  }
}

and we get back:

{
  "__schema": {
    "queryType": {
      "name": "Query"
    }
  }
}

And that matches what we said in the type system section, that the Query type is where we will start! Note that the naming here was just by convention; we could have named our Query type anything else, and it still would have been returned here if we had specified it as the starting type for queries. Naming it Query, though, is a useful convention.

It is often useful to examine one specific type. Let's take a look at the Droid type:

query IntrospectionDroidTypeQuery {
  __type(name: "Droid") {
    name
  }
}

and we get back:

{
  "__type": {
    "name": "Droid"
  }
}

What if we want to know more about Droid, though? For example, is it an interface or an object?

query IntrospectionDroidKindQuery {
  __type(name: "Droid") {
    name
    kind
  }
}

and we get back:

{
  "__type": {
    "name": "Droid",
    "kind": "OBJECT"
  }
}

kind returns a __TypeKind enum, one of whose values is OBJECT. If we asked about Character instead:

query IntrospectionCharacterKindQuery {
  __type(name: "Character") {
    name
    kind
  }
}

and we get back:

{
  "__type": {
    "name": "Character",
    "kind": "INTERFACE"
  }
}

We'd find that it is an interface.

It's useful for an object to know what fields are available, so let's ask the introspection system about Droid:

query IntrospectionDroidFieldsQuery {
  __type(name: "Droid") {
    name
    fields {
      name
      type {
        name
        kind
      }
    }
  }
}

and we get back:

{
  "__type": {
    "name": "Droid",
    "fields": [
      {
        "name": "id",
        "type": {
          "name": null,
          "kind": "NON_NULL"
        }
      },
      {
        "name": "name",
        "type": {
          "name": "String",
          "kind": "SCALAR"
        }
      },
      {
        "name": "friends",
        "type": {
          "name": null,
          "kind": "LIST"
        }
      },
      {
        "name": "appearsIn",
        "type": {
          "name": null,
          "kind": "LIST"
        }
      },
      {
        "name": "primaryFunction",
        "type": {
          "name": "String",
          "kind": "SCALAR"
        }
      }
    ]
  }
}

Those are our fields that we defined on Droid!

id looks a bit weird there, it has no name for the type. That's because it's a "wrapper" type of kind NON_NULL. If we queried for ofType on that field's type, we would find the String type there, telling us that this is a non-null String.

Similarly, both friends and appearsIn have no name, since they are the LIST wrapper type. We can query for ofType on those types, which will tell us what these are lists of.

query IntrospectionDroidWrappedFieldsQuery {
  __type(name: "Droid") {
    name
    fields {
      name
      type {
        name
        kind
        ofType {
          name
          kind
        }
      }
    }
  }
}

and we get back:

{
  "__type": {
    "name": "Droid",
    "fields": [
      {
        "name": "id",
        "type": {
          "name": null,
          "kind": "NON_NULL",
          "ofType": {
            "name": "String",
            "kind": "SCALAR"
          }
        }
      },
      {
        "name": "name",
        "type": {
          "name": "String",
          "kind": "SCALAR",
          "ofType": null
        }
      },
      {
        "name": "friends",
        "type": {
          "name": null,
          "kind": "LIST",
          "ofType": {
            "name": "Character",
            "kind": "INTERFACE"
          }
        }
      },
      {
        "name": "appearsIn",
        "type": {
          "name": null,
          "kind": "LIST",
          "ofType": {
            "name": "Episode",
            "kind": "ENUM"
          }
        }
      },
      {
        "name": "primaryFunction",
        "type": {
          "name": "String",
          "kind": "SCALAR",
          "ofType": null
        }
      }
    ]
  }
}

Let's end with a feature of the introspection system particularly useful for tooling; let's ask the system for documentation!

query IntrospectionDroidDescriptionQuery {
  __type(name: "Droid") {
    name
    description
  }
}

yields

{
  "__type": {
    "name": "Droid",
    "description": "A mechanical creature in the Star Wars universe."
  }
}

So we can access the documentation about the type system using introspection, and create documentation browsers, or rich IDE experiences.

This has just scratched the surface of the introspection system; we can query for enum values, what interfaces a type implements, and more. We can even introspect on the introspection system itself. The specification goes into more detail about this topic in the "Introspection" section, and the introspection file in GraphQL.js contains code implementing a specification-compliant GraphQL query introspection system.

Additional Content

This README walked through the GraphQL.js reference implementation's type system, query execution, validation, and introspection systems. There's more in both GraphQL.js and specification, including a description and implementation for executing queries, how to format a response, explaining how a type system maps to an underlying implementation, and how to format a GraphQL response, as well as the grammar for GraphQL.

Contributing to this repo

This repository is managed by EasyCLA. Project participants must sign the free (GraphQL Specification Membership agreement before making a contribution. You only need to do this one time, and it can be signed by individual contributors or their employers.

To initiate the signature process please open a PR against this repo. The EasyCLA bot will block the merge if we still need a membership agreement from you.

You can find detailed information here. If you have issues, please email [email protected].

If your company benefits from GraphQL and you would like to provide essential financial support for the systems and people that power our community, please also consider membership in the GraphQL Foundation.

graphql.github.io's People

Contributors

acao avatar ardatan avatar babyfish-ct avatar beerose avatar benjie avatar brianwarner avatar caniszczyk avatar carolstran avatar cometkim avatar dimamachina avatar dschafer avatar gsans avatar lacker avatar leebyron avatar leoloso avatar michaelstaib avatar nikolasburk avatar olegilyenko avatar orta avatar praveenweb avatar renovate-bot avatar renovate[bot] avatar robzhu avatar setchy avatar tuvalsimha avatar urigo avatar vning93 avatar wincent avatar yassineldeeb avatar zpao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql.github.io's Issues

Set up automatic GraphiQL-ization of code snippets

Ideally, you can just write markdown code snippets, and they will get converted to interactive editors automatically. That way, you can still read the files in markdown format.

This means we need a way to tag which ones need to be interactive, since the schema examples probably won't be.

[documentation] Possibly incorrect example in pagination docs

I'm just getting familiar with GraphQL, so forgive me if I'm missing something. But I found the following snippet confusing in the documentation on pagination.

"our friends field should give us a list of edges, and an edge has both a cursor and the underlying node:"

...but in the associated example, the GraphQL request does not mention edges:

{
  hero {
    name
    friends(first:2) {
      node {
        name
      }
      cursor
    }
  }
}

Should the example be something like this?:

{
  hero {
    name
    friends(first:2) {
      edges {
        node {
          name
        }
        cursor
      }
    }
  }
}

Btw many thanks for releasing this impressive library!

graphql.js custom scalar type docs are very vague

I was trying to create a custom scalar type by reading the docs, but what's there is very vague and confusing:

  • What are the semantics of the three required functions? Only names are listed right now.
  • The example doesn't compensate for the lack of descriptions, since it uses the same function for two of the fields
  • The example type is strange: it... returns the value if odd and null otherwise? That seems like a completely fanciful type with no practical use. Perhaps a Date type would be more useful?

I think the GraphQL docs are fantastic overall, but this section was not clear at all.

List public GraphQL APIs on website

... aka "enough about Star Wars". ;-)

I want to know about real-world GraphQL APIs, which can hopefully inspire my own API design and demonstrate best practices.

Facebook, and indeed most of the companies on the "Whoโ€™s using GraphQL?" page, seem to only use it internally, and that's great for them but doesn't really teach me anything. GitHub has a publicly documented API. Are there others?

If so, it might be helpful to separate that page into "companies with public APIs" (and link to API docs) and "companies using it internally".

[Master] New graphql.org

This is a master task for all the various work necessary for the graphql.org relaunch with inline assignees by page.

  • /index.html * @leebyron
  • /learn/
    • Core Concepts
    • Best Practices
      • learn/domain-modeling/ @robzhu
      • learn/serving-over-http/ * @robzhu
      • learn/authorization/ * @robzhu
      • learn/pagination/
      • learn/versioning/ *
      • learn/performance/
      • learn/security/
      • learn/design-guidelines/
      • learn/using-variables/
      • learn/colocated-queries/
      • learn/client-caching/ *
      • learn/persisted-queries/
      • learn/code-generation/
      • learn/migrating-from-rest/
  • /code/ * @lacker
  • /community/ * @theadactyl
    • Links out to places for help
    • Calendar of upcoming events
    • Grid of conference talks
  • /blog/ @leebyron

* indicates a goal for content complete by relaunch day (Sept 13th), though all content should be completed in Q3 (these are open to change).

documentation should include `__resolveType` requirement for Union Type to return interface

There's no mention in the documentation that Union Types require a __resolveType field in the Resolver for the Union.

a good example of helpful information can be found at Apollo's Documentation

When you have a field in your schema that returns a union or interface type, you will need to specify an extra __resolveType field in your resolver map, which tells the GraphQL executor which type the result is, out of the available options.

For translation

Can I translate this documents to korean on this blog or cloned repository?

Confused about how to merge fields in field selection

Currently the GrapgQL spec at https://facebook.github.io/graphql/#sec-Field-Selection-Merging only mention conditions that have to apply in order for fields in a selection to merge. While discussing a fix to an issue ( youshido-php/GraphQL#138 ) the specification was brought up.

It is pretty confusing to infer how to actually merge fields in a selection just from the specs alone, because they only seem to be talking about how to know when multiple fields can merge, and not about how to actually do the merging.

Can we get some more specific documentation on how to merge fields? Can we get some examples of how to merge fields of object types and array types?

Add graphql-tools reference to GraphQL.js tutorial

Right now a lot of people are running into confusion with the buildSchema approach in the getting started guide, there are a few things that are confusing about it:

  1. The root object isn't the same as the usual resolvers. Resolvers have a signature of (root, args, context), but with the rootValue object instead you get (args, context).
  2. You get stuck as soon as you need interfaces or unions. SO question that reminded me here.
  3. There isn't a clear way to scale up to multiple files.

For a bit over a year we've had the graphql-tools package which addresses exactly these concerns but doesn't introduce any additional opinions: http://dev.apollodata.com/tools/graphql-tools/generate-schema.html

It would be pretty much a drop-in replacement for buildSchema in the tutorial, would be happy to make the switch if people think this could be a good idea.

Here's an example of how the code would change:

With buildSchema, currently

var { graphql, buildSchema } = require('graphql');

// Construct a schema, using GraphQL schema language
var schema = buildSchema(`
  type Query {
    hello: String
  }
`);

// The root provides a resolver function for each API endpoint
var root = {
  hello: () => {
    return 'Hello world!';
  },
};

// Run the GraphQL query '{ hello }' and print out the response
graphql(schema, '{ hello }', root).then((response) => {
  console.log(response);
});

With graphql-tools

var { graphql } = require('graphql');
var { makeExecutableSchema } = require('graphql-tools');

// Construct a schema, using GraphQL schema language
var typeDefs = `
  type Query {
    hello: String
  }
`;

// The provide a resolver function for each query field
var resolvers = {
  hello: () => {
    return 'Hello world!';
  },
};

var schema = makeExecutableSchema({
  typeDefs: typeDefs,
  resolvers: resolvers
});

// Run the GraphQL query '{ hello }' and print out the response
graphql(schema, '{ hello }').then((response) => {
  console.log(response);
});

Also looking at that snippet there are some oddities like the text "resolver function for each API endpoint", which I'd be happy to fix while I'm there.

Documentation about adding a mutation was hard to follow

I was looking into how to add a "Create User" mutation to my graphql-js server. It took me a while to end up at the right code, so just documenting where I got confused:

  1. Searched for "Mutation" on the site. There are two sections ostensibly about mutation:
    a. http://graphql.org/learn/queries/#mutations
    b. http://graphql.org/learn/schema/#the-query-and-mutation-types
  2. Skimming each page, it was hard to figure out how to actually define a mutation in the schema. The code talking about mutations wasn't clear if it was showing how to do them in the query or in the schema.
  3. I found the operative sentence is in (b): "Mutations work in a similar way - you define fields on the Mutation type, and those are available as the root mutation fields you can call in your query." and was able to write the correct schema:
  input CreatePersonInput {
    name: String
  }
  type Mutation {
    createPerson(person: CreatePersonInput!): Person
  }

Suggestions:

  • I was thinking it would be better to just put an example of the schema changes necessary to make a mutation right into the schema (b) section to avoid confusion
  • Make it clearer when a block of code in the docs is in GraphQL query language or schema language (maybe even show "Query" and "Response" labels next to the left and right sides)

GraphQL Union and Interface Example - help needed

I am looking for an example on GraphQL Union and Interface. Appreciate if any one can help by providing an example or link that shows how to define a query and resolvers for Union and Interface. Thanks and regards, Ram

Pagination alternative

Merry christmas everyone ๐ŸŽ

Here's an alternative to the recommended approach regarding pagination.

type Query {
  allPeople(first: Int = 0, after: String = ""): [Person]
  allPeoplePage: PageInfo!
}

type PageInfo {
  nextCursor: String
  prevCursor: String
  startCursor: String
  endCursor: String
  cursors: [String]
  totalCount: Int
}

The idea is a basic convention: Any list field x may have pagination info at xPage. hasNextPage/hasPrevPage would be nextCursor/prevCursor !== null, respectively.
cursors would hold a list of cursors aligned to the returned items.

Pros:

  • Much less types. For example, no PersonConnection, no PersonEdge, etc.
  • Data structure is not dictated by "has to support pagination (or not)"
  • Orthogonal: We can evolve from "pagination for x not supported" to "x can now be paginated by requesting xPage" without breaking x or introducing "pagedX { edges: { node: { name } } pageInfo: { ... } }"
  • Shallow data is easier to consume

Cons:

  • Cannot add edge-specific information like "friendship time". You'll have to introduce a "Friendship" thing in that case anyway, though.
  • Data-wise, cursors are only indirectly coupled with their items (by index)

What do you think? If it could be useful to the community, I'd be happy to write it up for graphql.org. I'm looking to use this pattern next year and come back with real-world feedback.

Cheers

Extend Versioning paragraph in Best Practises

The Versioning in the Best Practises section is explaining why traditional REST APIs need Versioning to deal with breaking changes. But later sentences don't explain what are the best practises with GraphQL do deal with breaking changes. For example how should I handle the case when I want to remove or rename a field of a type?

operationName is hard to grasp

The current section about operation names, here: http://graphql.org/learn/queries/#operation-name
reads like this:

One thing we also saw in the example above is that our query has acquired an operation name. Up until now, we have been using a shorthand syntax where we omit both the query keyword and the query name, but in production apps it's useful to use these to make our code less ambiguous.

Think of this just like a function name in your favorite programming language. For example, in JavaScript we can easily work only with anonymous functions, but when we give a function a name, it's easier to track it down, debug our code, and log when it's called. In the same way, GraphQL query and mutation names, along with fragment names, can be a useful debugging tool on the server side to identify different GraphQL requests.

The problem is that after reading this section there is no example or other hint on the shape in which the operation's name should be specified or where to look up the spec. It would be nice to be pointed to somewhere in this section.

Aside from that: Thank you for your great work!

Missing mutation result type in the doc "Mutations and Input Types"

Referred doc: http://graphql.org/graphql-js/mutations-and-input-types/
Source: https://github.com/graphql/graphql.github.io/blob/c22ba1a/site/graphql-js/Tutorial-Mutations.md

The result type of createMessage and updateMessage is missing in the schema and the "runnable code" example.
I was expecting the doc to specify the result of mutation types -- a simple boolean that indicates success/fail of the mutation? or just return the newly updated message instance?

Although it may not be the main concern of the article "Mutations and Input Types", but some insights on the design of return type of mutations would be great.

how to config algolia

we forked this repo and translate it into chinese.

algolia has already setup. index has been added. but cannot get search result.

is there anything must be config?

Easier navigation to graphql-js tutorial

The entire section of http://graphql.org/graphql-js/ which contain the node.js tutorials isn't mentioned in the header or the footer of graphql.org. I think that's a shame since this section is very well written and frankly pure gold for anyone implementing with node.js.

I could only find links to the page though http://graphql.org/code/ and it's not that clear in there you're going to see a thorough tutorial. I think a link at least at the footer could be beneficial.

I found it only by googling.

I'll add that https://github.com/graphql/graphql-js readme clearly refers to this documentation.
references https://github.com/graphql/express-graphql readme file are a little more obscure.

printable docs

Hello,
I'd like to print myself a handbook, but the layout of the docs is making this somewhat difficult. I forked and managed to get rid of the sidebar, but each section tag is limited to one page- so even if try to make a PDF of a really long page, I get exactly three pages: one for the header, one for the truncated body, and one for the footer. Can someone please fix this?

Super feature request: one-page version of the docs. For now, I'll just manually merge the markdown files.

Transfer of graphql.training

Hi!

I'm presently the owner of graphql.training (and its respective github organisation, @GraphQL-Training). I'd like to transfer this domain across to the GraphQL Community, as I have no real use for it (context)

I've tried to get in contact with people from the community in the past, but to no responses other than likes on twitter. If I don't find an entity to transfer the domain to, I'll likely just let it lapse at the end of it's current registration period, but that'd mean it'd likely be picked up by someone with the community's best interests not at heart.

If you see this and you're a company, you're welcome to pitch an idea either publicly or privately (email's on my github profile or website)

Resolver parameter order documented incorrectly

According to the documentation, resolver functions are written as follows:

function someField(obj, args, context) {
  // Return something...
}

However, when I build resolver functions, the parameters provided by GraphQL are

  • args
  • context
  • obj

So I end up having to build resolvers as follows:

function someField(args, context, obj) {
   // Return something...
}

My understanding of these parameters is as follows:

  • obj - the parent object, if any
  • args - contains the arguments passed to the field in the query (e.g. when executing the query query { someField(foo: "bar") }, args is set to {foo: 'bar'}
  • context - the object provided as the 4th parameter to the graphql function

Am I missing something or are is the documentation incorrect?

[New-Source] Missing hrefs in Learn landing page

Most of the links in the table of contents at https://github.com/graphql/graphql.github.io/blob/new-source/site/learn/index.html.js are missing hrefs:

            <ul>
              <li><a>Query Language</a></li>
              <li><a>Type System</a></li>
              <li><a>Validation</a></li>
              <li><a>Execution</a></li>
              <li><a>Introspection</a></li>
            </ul>
            <ul>
              <li><a href="/learn/serving-over-http/">Serving Over HTTP</a></li>
              <li><a href="/learn/authorization/">Authorization</a></li>
              <li><a>Domain Modeling</a></li>
              <li><a>Pagination</a></li>
              <li><a>Versioning</a></li>
              <li><a>Performance</a></li>
              <li><a>Security</a></li>

This page is linked to from the "Learn" navigation item in the header.

Infinite redirection loop at graphql.org

The page seems to be redirecting in an infinite loop between the HTTP and HTTPS version

$ wget http://graphql.org/index.html 
--2018-05-27 14:29:13--  http://graphql.org/index.html
Resolving graphql.org (graphql.org)... 54.192.7.25, 2600:9000:2008:da00:5:5ca6:5c40:93a1
Connecting to graphql.org (graphql.org)|54.192.7.25|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://graphql.org/index.html [following]
--2018-05-27 14:29:13--  https://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://graphql.org/index.html [following]
--2018-05-27 14:29:15--  http://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://graphql.org/index.html [following]
--2018-05-27 14:29:16--  https://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://graphql.org/index.html [following]
--2018-05-27 14:29:17--  http://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://graphql.org/index.html [following]
--2018-05-27 14:29:18--  https://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://graphql.org/index.html [following]
--2018-05-27 14:29:20--  http://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://graphql.org/index.html [following]
--2018-05-27 14:29:21--  https://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://graphql.org/index.html [following]
--2018-05-27 14:29:22--  http://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://graphql.org/index.html [following]
--2018-05-27 14:29:23--  https://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://graphql.org/index.html [following]
--2018-05-27 14:29:25--  http://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://graphql.org/index.html [following]
--2018-05-27 14:29:25--  https://graphql.org/index.html
Connecting to graphql.org (graphql.org)|54.192.7.25|:443... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://graphql.org/index.html [following]
--2018-05-27 14:29:27--  http://graphql.org/index.html

BSD or MIT

I visited the website and to my surprise I saw this

Copyright ยฉ2017 Facebook Inc. The contents of this page are licensed BSD-3-Clause.

Graphql-js is MIT but when I read the docs I see as above. I almost submitted a PR but then I checked the graphql repo and found out some projects are licensed MIT while others are BSD.

Did you do it on purpose? I'm a little confused

Figure out a schema for all query examples

That way, we can set up all of the examples with the interactive query editor, instead of having static code snippets. But we need to make sure the schema has all of the features we want to demonstrate. Opening the issue here to keep track of this need.

Todos for learn section

  • Cover __typename
  • Cover non-root field arguments in queries
  • Cover input objects
  • Defining operations for arguments
  • Default values for arguments
  • Convert index.html to match new schema

Is this being maintained?

Beyond being just an informative site, there are pull requests since November of last year. Can I help with this?

none of the example can be run on standard graphiql

I tryed to past them in http://graphql.org/swapi-graphql and non of them worked. Why ? Is that not the obvious thing to do? examples from starwars. Here is a star wars standard simple hello world api. No none of the examples can be used to experiment with. "message": "Cannot query field "hero" on type "Root". Did you mean "person"?". This is supposed to be a fun intro to GraphQl not a sudoku puzzle

Human Type under interfaces

Steps to reproduce:
Visit: http://graphql.github.io/learn/schema/

Under Interfaces where we have

... on Droid {
      primaryFunction
    }

add

... on Human {
      totalCredits
     }

After that, change totalCredits to height and the error goes away.

screen shot 2018-08-15 at 1 54 05 pm 2

screen shot 2018-08-15 at 1 54 17 pm 2

This is probably happening because this query is using the type 'Human' from one of the previous pages that have the field height

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.