The Firebase Realtime Database is a NoSQL database hosted in the cloud. Data is synchronized in real time with every client on all platforms (Web, iOS, and Android). The data is stored as JSON and is shared by all of your customers when you create cross-platform apps. This ensures that all of your clients always have the most recent data available, even when offline.
Firebase is a cloud-based platform from Google that allows you to build web and mobile applications quickly. It offers authentication, data storage, monitoring, logging, and deployment services. The Realtime Database is one of the services offered to developers. You can access the data from a Firebase Realtime Database using a REST API. But it lacks a GraphQL API, which we'll be creating using IBM API Connect Essentials (formerly StepZen).
Notice: StepZen was acquired by IBM in 2023 and renamed to API Connect Essentials. Some artifacts still use the StepZen name.
Set up a Firebase Realtime Database
The first step to using a Firebase service is to create a free account in the Firebase console if you haven't already. You receive a brand-new Firebase app with a unique URL that ends in firebaseio.com. This URL is used to store and sync data to the app's database and authenticate users.
You need to create a new project within the Firebase console; let's name it "GraphQL demo". The setup asks you several configuration questions, which you can ignore for the sake of this demo. Within a few minutes, your new Firebase project is ready, and you can continue by adding a "Realtime Database" by using the navigation on the page.
When you press "Create database," you need to select the region, for example, the United States, Europe, Asia or any region you want the database to be created in. Also, you need to configure the security settings for the Realtime Database. At first, you need to enable "test mode" to make it easier to create and read our first data:
By pressing "Enable" your database is created in the region that you selected. Depending on the region of your database the URL is either YOUR_FIREBASE_PROJECT_ID.firebaseio.com (for databases located in us-central1) or YOUR_FIREBASE_PROJECT_ID.REGION.firebasedatabase.app for databases in all the other locations.
The final step is adding data to the database, which you can do from the Firebase console or through the REST API. To get initial data into the database, we'll be using the Firebase console to upload the JSON file init.json that you can find in the Github repository for this post here. By pressing the three dots on the right side of the screen, you can select "Import JSON".
After uploading the data, you can see in the Firebase console that there are customers and orders in the database. Your Firebase Realtime database is ready to go.
Generate a GraphQL schema
You can retrieve data from the Firebase Realtime database using their REST API. An example curl request to get a single customer would be:
With API Connect Essentials, we can use the same curl command to create a GraphQL API that retrieves the same data. First, you need to install the API Connect Essentials CLI using:
npm i -g stepzen
Show more
Run the command to convert the Firebase REST API to GraphQL. In this command, you can see the initial curl is used together with a few flags to name the generated query and response type:
In the file customer/index.graphql, you can find the generated GraphQL schema.
To deploy this GraphQL schema and query your new GraphQL API, you need to run
stepzen deploy
Show more
The CLI then deploys the GraphQL schema and return your endpoint directly in the terminal. This is shaped like https://YOUR_USERNAME.stepzen.net/api/with-firebase/__graphql. You can use this endpoint from the API Connect Essentials dashboard or by using a tool like GraphiQL (see screenshot below):
Now, you can query the GraphQL API and inspect what the response types in the schema looks like.
Transform API responses
Besides getting a single customer, you can also get all customers from the Firebase Realtime Database. But it has one caveat, as you'll learn once we get the data using the REST API.
The curl to get this list is similar to the request we've used in the previous section:
And we can add it to the GraphQL schema in customer/index.graphql manually or by running another stepzen import curl command. The second option has a caveat as the imported schema shows the message:
Result typed as JSON since it has fields ['-N6rOmxa7vOOTpZZSllL', ...] that are invalid graphql identifiers
Show more
The request response to the REST API returns JSON in an unsupported format. The REST API returns a list of key-value pairs with field names representing the key instead of an array.
Therefore, you need to transform this object into an array to get a list of customers. If you've used the API Connect Essentials CLI to import the endpoint, you need to add the transforms field to the getCustomers query. Or, if you haven't, you can add the getCustomers query from the code block below to the schema in customers/index.graphql
The response type for this query is now [JSON] as the CLI couldn't generate the GraphQL type automatically as GraphQL doesn't support key-value pair lists. On the GraphiQL IDE for your endpoint, you can already query the results for getCustomers, but you won't be able to select any fields.
Therefore, we need to add the GraphQL response type manually. Type Customer was already generated when you imported the Firebase REST API endpoint to get a single customer and add a second type for the transformed key-value pair with the type CustomerList:
type Customer {email: String
name: String
}type CustomerList {name: ID
value: Customer
}typeQuery{
getCustomerById(id: ID!): Customer
@rest(## ...)getCustomers:[CustomerList]@rest(endpoint:"https://YOUR_FIREBASE_PROJECT_ID.firebaseio.com/customers.json"transforms:[{pathpattern:[], editor:"objectToArray"}])}
Show more
When you go back to the GraphiQL browser, you can now also query the list of customers and determine the fields that the GraphQL API should return:
query{
getCustomers {
name
value {
email
name
}}}
Show more
Even though the response is the same as the previous query, you now have complete control over which fields are returned. If you'd run the same query and remove the field email in value, only the name of the customer will be returned.
Combine data in GraphQL
Next to customer data, we also have order data in the Firebase Realtime Database. To combine the customer data with the order data, we need to create the query to get the orders from the Firebase Realtime Database.
Again you can use the API Connect Essentials CLI to convert the REST API to a GraphQL API. We'll start by importing a single order so that the return type is autogenerated:
You can see that this query also returns customerId. This field references the customers we also have in our database. With the @materializer directive, you can use this value to retrieve the customer and link it to the response type.
type Order {carrier: String
createdAt: Date
customerId: String
customer: Customer
@materializer(query:"getCustomerById"arguments:[{name:"id", field:"customerId"}])shippingCost: Int
trackingId: String
}
Show more
With this addition, you can retrieve the customer information for every order by adding the field customer and the subfields you want to include:
Using @materializer you can combine any available data to query in your GraphQL schema. Not only data which is coming from the same database, but also data from external sources - such as another database, third-party REST APIs, and more.
Use mutations to add and update data
Finally, we'll add new data to the Firebase Realtime Database using GraphQL. The REST API from Firebase allows you to both insert and update data. The request returns the ID of the updated or inserted value when successful.
Let's try to insert a new customer to the database by adding the mutation and response type below to your GraphQL schema in customer/index.graphql:
type Response {name: ID
}typeMutation{
insertCustomer(name: String!, email: String!): Customer
@rest(endpoint:"https://$project_id.firebaseio.com/customers.json"method: POST
postbody:"""
{
"name": "{{.Get "name"}}",
"email": "{{.Get "email"}}"
}
"""configuration:"firebase_config")}
Show more
This mutation requires the query parameters name and string and passes their values to the underlying REST API using the postbody field. The syntax {{.Get "VARIABLE_NAME"}} is used here to get the value that's passed to the GrapQL Query.
When you use the following query:
mutation{
insertCustomer(name:"Peter", email:"peter.parker@avengers.com"){
name
}}
Show more
The response should look like the following code snippet:
You can validate if the customer with the name "Peter" has been added with the getCustomerById query and the returned ID. Also, you can find this new customer in the Firebase console:
Not only can you insert new data, but you can also update existing data. You have two options when updating specific fields or replacing the entire JSON data for an ID. In this article, we'll use PATCH as PUT to overwrite the data at the specified location, including any child nodes.
Adding the new mutation to your schema in customer/index.graphql:
Now update the name of the customer. Follow the code snippet to change the name of the customer from "Peter" to "Peter Parker" :
mutation{
updateCustomerName(id:"-N7WtNDgHYjCrED--Bq3", name:"Peter Parker"){
name
}}
Show more
Note: that the response type of the query updateCustomerName is Customer instead of Response, as PATCH requests to the Firebase REST API returns the updated value.
You have now created a GraphQL schema for a Firebase Realtime Database. When you want to take this into production, don't forget to enable authentication for your REST API endpoint from Firebase.
Summary
In this article, we have created a GraphQL API for a Firebase Realtime Database using REST APIs. This GraphQL API helps to query, mutate data and make combinations between different entities. You can find the complete code in our Github examples repository, and watch the video on our Youtube channel. We would love to hear what project you start building with API Connect Essentials and Firebase. Join our Discord to stay updated with our community.
About cookies on this siteOur websites require some cookies to function properly (required). In addition, other cookies may be used with your consent to analyze site usage, improve the user experience and for advertising.For more information, please review your cookie preferences options. By visiting our website, you agree to our processing of information as described in IBM’sprivacy statement. To provide a smooth navigation, your cookie preferences will be shared across the IBM web domains listed here.