GraphQL Playground

Write a schema, some data and a query, then run it. Mutations can change the data too. The engine checks the query against the schema, runs it, and shows the response with its errors: where each one happened, the path to the field, and which fields came back null. It is the same engine the mock server uses, compiled to WebAssembly, so it runs here in your browser. Nothing is uploaded. You can also send the query to a real GraphQL endpoint.

Try it

Response


  

Types in the schema

Object types and their fields, read from the schema text above.

Send the query to your own endpoint

The query and variables above are sent as a POST with a JSON body. The endpoint must answer, and must allow requests from this page (CORS). The mock server allows tinypdf.in by default.


  

How mutations work

A mutation is a field on the Mutation type. Unlike a query, it changes the data, and the fields run one after another in the order you write them. The playground and the mock use the same rules.

What each handler does

HandlerWhat it doesReturns
insert: name of a listAdds an item built from the arguments. defaults fills fields that were not given. An id is made when none is given.The new item
update: name of a list, with byFinds the item whose by field (default id) equals the argument of the same name, and sets the other arguments given.The changed item, or null if nothing matches
delete: name of a list, with byRemoves the item whose by field equals the argument.true, or false if nothing matched

Add your own mutation

  1. Add a Mutation type to the schema. Each field takes scalar arguments such as String, Int or ID:
    type Mutation {
      addUser(name: String!, email: String): User
      renameUser(id: ID!, name: String!): User
    }
  2. Name the list each field changes. Add a handler under mutations in mock.json, using the list name from your data:
    "mutations": {
      "addUser": { "insert": "users", "defaults": { "orders": [] } },
      "renameUser": { "update": "users", "by": "id" }
    }
  3. Restart the mock. It reads the schema and handlers only when it starts.
  4. Check the result. Send the mutation, then a query that reads the list. The next section shows the expected output.

What you should see

curl -s -X POST http://localhost:4747/graphql -H 'content-type: application/json' \
  -d '{"query":"mutation { addUser(name: \"Meera\") { id name orders { id } } }"}'
{"data":{"addUser":{"id":"new3","name":"Meera","orders":[]}}}

curl -s -X POST http://localhost:4747/graphql -H 'content-type: application/json' \
  -d '{"query":"{ users { id name } }"}'
{"data":{"users":[{"id":"u1","name":"Asha"},{"id":"u2","name":"Ravi"},{"id":"new3","name":"Meera"}]}}

The new id depends on how many items the list has, so yours may differ. If a mutation has no handler, its field returns null with the error No handler for mutation, and nothing is changed.

Limits

Try it against tinypdf-mock on your computer

The examples above can also run against a real server on your machine. You need Node.js 18 or newer. These steps set up the sample shop from this page, then send it queries from a terminal and from this page.

  1. Save the sample files. These buttons save the schema and data from the editors above. Change them first if you want your own shop.
  2. Create a routes file. Put the two files in one folder, and save this as mock.json in the same folder:
    {
      "graphql": {
        "path": "/graphql",
        "schemaFile": "schema.graphql",
        "dataFile": "data.json",
        "mutations": {
          "addUser": { "insert": "users", "defaults": { "orders": [] } },
          "renameUser": { "update": "users", "by": "id" },
          "deleteUser": { "delete": "users", "by": "id" },
          "setOrderStatus": { "update": "orders", "by": "id" }
        }
      }
    }
  3. Start the mock. In that folder, run:
    npx tinypdf-mock@0.3.0 mock.json
    It listens on http://localhost:4747 and prints the GraphQL address. Leave it running.
  4. Send a query from a terminal.
    curl -s -X POST http://localhost:4747/graphql \
      -H 'content-type: application/json' \
      -d '{"query":"{ users { id name } }"}'
    You should get the two users back. Next, try the Partial data example: send { products { sku title price } }. The response is still 200, the Mini plan's price is null, and the error explains why.
  5. See a validation error. Send { users { nickname } }. The status is 400 and there is no data, because the query failed validation before it ran. Then try a variable:
    curl -s -X POST http://localhost:4747/graphql \
      -H 'content-type: application/json' \
      -d '{"query":"query Find($id: ID!) { user(id: $id) { name } }","variables":{"id":"u2"}}'
  6. Send from this page. In the section "Send the query to your own endpoint" above, keep the address http://localhost:4747/graphql and press Send. The mock allows requests from tinypdf.in by default, so the browser can reach it.
  7. Make it fail on purpose. Stop the mock, then start it again with a fault:
    npx tinypdf-mock@0.3.0 mock.json --fault fail-first-n:n=2,status=503
    The first two requests get a 503, and later ones succeed. Faults apply to /graphql too, so you can check how your client handles a failed GraphQL call.
  8. Change data with a mutation. Mutations are sent with POST. This adds a user, and a query then returns her:
    curl -s -X POST http://localhost:4747/graphql \\
      -H 'content-type: application/json' \\
      -d '{"query":"mutation { addUser(name: \\"Meera\\") { id name } }"}'
    curl -s -X POST http://localhost:4747/graphql \\
      -H 'content-type: application/json' \\
      -d '{"query":"{ users { id name } }"}'
    Changes are kept in memory. They last until you stop the mock, and they do not change data.json.
  9. Change the sample. Edit schema.graphql or data.json, then restart the mock. It reads these files only when it starts.

Questions

Why does a query return data and errors together?

GraphQL returns what it could. A field that fails becomes null, and its error says where it happened. Only a non-null field that fails makes its parent null, and so on up the tree. The response has data and errors together in that case.

When is there no data at all?

When the query cannot run: a syntax error, a field or argument that is not in the schema, a required variable that is missing, or a non-null root value that is null. These come back with errors only.

How do the data values match the fields?

Each field reads the member of the same name. A list field with arguments is filtered: an element matches when each argument equals the element's property of the same name. A field that fails can be shown with {"$error": "message"} in the data.

What happens if I forget a handler?

The mutation field returns null with the error No handler for mutation. Nothing is changed, and the other fields of the same request still run.

Do mutation changes survive a restart?

No, not in the mock. Changes live in memory until it stops. The files you gave it are not changed. In this page, changes stay in the Data box until you reset the sample.

Can I change data with a mutation?

Yes. A mutation changes the data in this page, and the Data box shows the change. The next query sees it. Reset the sample to start again. Subscriptions, directives such as @include, interfaces, unions, enums and input types are not supported.

Is my schema or data sent anywhere?

No, unless you press Send. Running a query happens in your browser with the WebAssembly engine.