GraphQL Support (With Strawberry 🍓)

This is in a very early stage right now. We will have a much more stable version when we have a stable API for Views and View Controllers.

Step 1: Creating a virtualenv

To ensure that there are isolated dependencies, we will use virtual environments.

Virtual Environment

python3 -m venv venv

Step 2: Activate the virtualenv and install Robyn

Activating the virtualenv

source venv/bin/activate

Installing Robyn and Strawberry

pip install robyn strawberry-graphql

Step 3: Coding the App

Code

from typing import List, Optional
from robyn import Robyn, jsonify
import json

import dataclasses
import strawberry
import strawberry.utils.graphiql


@strawberry.type
class User:
  name: str


@strawberry.type
class Query:
  @strawberry.field
  def user(self) -> Optional[User]:
      return User(name="Hello")


schema = strawberry.Schema(Query)

app = Robyn(__file__)


@app.get("/", const=True)
async def get():
  return strawberry.utils.graphiql.get_graphiql_html()


@app.post("/")
async def post(request):
  body = request.json()
  query = body["query"]
  variables = body.get("variables", None)
  context_value = {"request": request}
  root_value = body.get("root_value", None)
  operation_name = body.get("operation_name", None)

  data = await schema.execute(
      query,
      variables,
      context_value,
      root_value,
      operation_name,
  )

  return jsonify(
      {
          "data": (data.data),
          **({"errors": data.errors} if data.errors else {}),
          **({"extensions": data.extensions} if data.extensions else {}),
      }
  )


if __name__ == "__main__":
  app.start(port=8080, host="0.0.0.0")

Let us try to decipher the usage line by line.

These statements just import the dependencies.

Section 1

from typing import List, Optional

from robyn import Robyn, jsonify
import json

import dataclasses
import strawberry
import strawberry.utils.graphiql

Here, we are creating a base User type with a name property.

We are then creating a GraphQl Query that returns the User.

Section 2

@strawberry.type
class User:
    name: str


@strawberry.type
class Query:
    @strawberry.field
    def user(self) -> Optional[User]:
        return User(name="Hello")


schema = strawberry.Schema(Query)

Now, we are initializing a Robyn app. For us, to serve a GraphQl app, we need to have a get route to return the GraphiQL(ide) and then a post route to process the GraphQl request.

Section 3

app = Robyn(__file__)

We are populating the html page with the GraphiQL IDE using strawberry. We are using const=True to precompute this population. Essentially, making it very fast and bypassing the execution overhead in this get request.

Section 4

  @app.get("/", const=True)
  async def get():
  return strawberry.utils.graphiql.get_graphiql_html()

Finally, we are getting params(body, query, variables, context_value, root_value, operation_name) from the request object.

Section 5

@app.post("/")
async def post(request):
body = request.json()
query = body["query"]
variables = body.get("variables", None)
context_value = {"request": request}
root_value = body.get("root_value", None)
operation_name = body.get("operation_name", None)

data = await schema.execute(
    query,
    variables,
    context_value,
    root_value,
    operation_name,
)

return jsonify(
    {
        "data": (data.data),
        **({"errors": data.errors} if data.errors else {}),
        **({"extensions": data.extensions} if data.extensions else {}),
    }
)

The above is the example for just one route. You can do the same for as many as you like. :)

What's next?

That's all folks. :D Keep an eye out for more updates on this page. We will be adding more examples and documentation as we go along.