Skip to content

Latest commit

 

History

History
311 lines (256 loc) · 7.77 KB

loopback.md

File metadata and controls

311 lines (256 loc) · 7.77 KB

LoopBack and OpenAPI-to-GraphQL tutorial

The purpose of this tutorial is to give an in-depth look into using OpenAPI-to-GraphQL together with LoopBack v4.

We will use a pre-made API created with LoopBack v4 to describe how OpenAPI-to-GraphQL can be used on said API and what OpenAPI-to-GraphQL will do to the API in order to produce a GraphQL interface. In addition, we will describes the steps needed to change the OAS to get the most out of the produced GraphQL interface.

Clone LoopBack API

OpenAPI-to-GraphQL will create a GraphQL interface that will resolve on, or query, an API.

In this tutorial we will be providing a LoopBack API, the Example Family Tree API, that you can run locally. The purpose of this API is to not only showcase the compatibility between LoopBack and OpenAPI-to-GraphQL but also to demonstrate the capabilities of OpenAPI-to-GraphQL.


To clone the Example Family Tree API, follow the proceeding steps.

git clone git@github.com:strongloop/loopback4-example-family-tree.git
cd loopback4-example-family-tree
npm i

To give some background, the Example Family Tree API simulates the relationship between parent and child. There is only one model in this API, the Person model, and here is what it looks like:

Person {
	id : number
	name : String
	generation: number
	motherId : number
	fatherId : number
}

In addition, the API is preloaded with some data that we will query for. Here is what the data looks like:

Data diagram

Save OAS

Start the API by running the following:

# in the LoopBack project folder:
npm start

Next, access the API's OAS at http://localhost:3001/openapi.json and save it to disk.

Install OpenAPI-to-GraphQL

To install OpenAPI-to-GraphQL, clone the repository and link the library (for the CLI commands to work) using the indicated steps.

npm i -g openapi-to-graphql-cli

Please note that OpenAPI-to-GraphQL can be used either as a library, or via its Command Line Interface (CLI). In this case, we will be using the CLI tool, which will start a server in addition to creating the GraphQL interface.

Start GraphQL server

Start the GraphQL server by running the following command.

openapi-to-graphql <OAS JSON file path or remote url>

The created GraphQL server is then accessible at http://localhost:3000/graphql.

Try simple queries

Congratulations! You have created your first GraphQL interface with OpenAPI-to-GraphQL.

We can explore the GraphQL interface through the GraphiQL IDE that will show at the previously provided link.

Try to run a simple query like the following:

GraphQL query

query {
  person(id: 15) {
    name
  }
}

Expected output

{
  "data": {
    "person": {
      "name": "Daron"
    }
  }
}

Although this is a fully-fledged GraphQL interface, we can still improve it.

For instance, this GraphQL interface does not provide nested queries. Recall that the Person object also stores the motherId and fatherId which can be used to query other People. In GraphQL, we can make it so that a user can query the mother and father objects from within the child object. To do so, we will need to make slight additions to the OAS, which will be discussed in the following sections.

For now, in the Documentation Explorer on the right hand side, click Query and then the return type, Person, in person(id: Float!): person. Note that the Person object can only return the following fields. With our nested query changes, we will see new fields that will let us query the mother and father objects.

id: Float
name: String
generation: Float
motherId: Float
fatherId: Float

Adding links

Link objects are constructs in OAS that allow you to explicitly define relationships between different models and operations. For example, when you query for a Person, you will receive a motherId and a fatherId, which can be used to query for other People. When you have actions that naturally lead to the next, you use Link objects to describe this flow.

While Link objects (and OAS in general) are useful for documenting APIs, links are especially important for OpenAPI-to-GraphQL. Even though OpenAPI-to-GraphQL can wrap any API with a valid OAS, it needs Link objects in order to create GraphQL interfaces that can conduct the powerful nested queries they are famous for. If we try to use the OAS now, the GraphQL interface OpenAPI-to-GraphQL will create will only be able to handle simple queries that are no different than the ones the original API is capable of. Luckily, Link objects are easy to define.


Here are the Link objects we will be adding to the OAS.

"links": {
  "mother": {
    "operationId": "PersonController.findById",
    "parameters": {
      "id": "$response.body#/motherId"
    }
  },
  "father": {
    "operationId": "PersonController.findById",
    "parameters": {
      "id": "$response.body#/fatherId"
    }
  }
}

After you have saved your changes to the OAS, restart the GraphQL server.

openapi-to-graphql <OAS JSON file path or remote url> 

Try complex queries

In the Documentation Explorer, click Query and then the return type, Person, in person(id: Float!): person.

You should see the following fields.

id: Float
name: String
generation: Float
motherId: Float
fatherId: Float
mother: person
father: person

Note that there are two new fields, mother and father. These are from the links we just added to the OAS and will allow us to write nested queries.

Now we can write much complex queries like the following.

GraphQL query

query {
  person(id: 15) {
    name
    generation
    father {
      name
      id
      generation
      mother {
        name
        id
        generation
        father {
          name
          id
          generation
        }
      }
    }
  }
}

Expected output

{
  "data": {
    "person": {
      "name": "Daron",
      "generation": 4,
      "father": {
        "name": "Charles",
        "id": 13,
        "generation": 3,
        "mother": {
          "name": "Brigitte",
          "id": 10,
          "generation": 2,
          "father": {
            "name": "Aaron",
            "id": 3,
            "generation": 1
          }
        }
      }
    }
  }
}

GraphQL query

query{
  person(id: 15) {
    mother {
        mother {
          mother {
            name
          }
          father {
            name
          }
        }
        father {
          mother {
            name
          }
          father {
            name
          }
        }
      }
    father {
      mother {
        mother {
          id
        }
        father {
          id
        }
      }
      father {
        mother {
          id
        }
        father {
          id
        }
      }
    }
  }
}

Expected output

{
  "data": {
    "person": {
      "mother": {
        "mother": {
          "mother": {
            "name": "Ava"
          },
          "father": {
            "name": "Archie"
          }
        },
        "father": {
          "mother": {
            "name": "Abigail"
          },
          "father": {
            "name": "Adrian"
          }
        }
      },
      "father": {
        "mother": {
          "mother": {
            "id": 4
          },
          "father": {
            "id": 3
          }
        },
        "father": {
          "mother": {
            "id": 2
          },
          "father": {
            "id": 1
          }
        }
      }
    }
  }
}