Go back to 8base Academy
June 30, 2022

Integrating a 3rd Party API into the GraphQL API

Sebastian Scholl
@SebScholl

Speaker 1 (00:03)
Hey everyone, this is Sebastian. Today, what we're going to be doing is looking at how you can use a resolver function to actually integrate a third-party API into your 8base graphical API. To kick things off, I'm going to explain a little bit about which API we're going to use and what we're going to be doing. In this workspace, what I did is I went to my Users table and I created a new field on the Users table called location. I just set this to a default value of the lat and long coordinates for Miami, Florida. Now, if you wanted to find a way of interacting with a Geocoding API and set up the actual location of users, you could do that. However, just think of it as starting with this data.

Speaker 1 (00:42)
Now, what we're going to be doing is we're going to be creating a custom resolver function on our graphical API to where you can get the current weather of the user for wherever that user is located. It will return a single response that gives you some of the user's data as well as the current weather data. This all gets access to the graphical API even though we're going to be interacting with the OpenWeather API, which I've created account for and got an API key. They have very clear docs on how to go about setting up the OpenWeather account so I'm going to let you go about that on your own. However, I think you'll be able to follow along really easily.

Speaker 1 (01:17)
The first thing that we need to do when we want to create a custom resolver function is go to our command line tool. Let me go ahead and open up my IDE where I have a command terminal running. Inside this project, this project is configured with my 8base workspace, which is the same one I just was looking in. If you need to check that, you can run 8base configure of whatever project you're working within, or if you need to create a new repository functions, run 8base knit. Here, I can just make sure that my sandbox-workspace-0001 is selected.

Speaker 1 (01:58)
The first step that we're going to do is go ahead… Actually, the first step that we're going to do is, yeah, go ahead and create a resolver function. 8base generate resolver and we're going to call this the userWithCurrentWeather resolver, and it's going to be JavaScript instead of Typescript. So we go ahead and generate that. That generated the declaration in our 8base.yml file that we needed, as well as the directory here, which has the function handler and all that different stuff in there. Now, when developing a resolver function, we have to provide it a schema. This is part of a graphical specifications. Essentially, what we have to tell it is what are the inputs that it's going to receive and what are the outputs we can expect. So by default, this is the default query that gets generated.

Speaker 1 (03:00)
Since we are going to want the user with their current weather data, we are only going to be passing one argument to this function, which is the idea of the user. So we can just say that id is the argument and ID is the type of that argument, it's mandatory since we have ! there. Now, we don't actually have to pass it any location data because location data is on the user record itself and we're going to have to query the user. That's how this is going to work in that regard. However, you could pass any type of data arguments that you want to pass it, as well as type those out.

Speaker 1 (03:35)
Now, in the response, what we really care about is, first off, we want some details about the user back. We're going to call this a BasicUser. In here, we're going to want the id of the user, their first name, their last name, and their email. We're just going to quickly go through and say the types. That's ID and this is String. I'm just going to copy that. That's our BasicUser. I think I deleted… No, that type is still there. Cool.

Speaker 1 (04:11)
I'm going to take this type, drop it right in here, and I'm going to update the results to be user, and then, here we're going to have BasicUser. All right. Let's start.

Speaker 1 (04:29)
Now, what we care about is typing out the response that we would be getting from the weather API. The first thing that we actually want to do is run a successful call to the weather API to see what the JSON response is. In order to accomplish that, I was playing around with the API already. What I'm going to do is I'm just going to clear out my terminal here. Per their API docs, which we can find here, we can see that you have to make a get request to this endpoint, providing an API key and lat long coordinates. This is just a free account so I don't really care about my API key, I'll delete it after the video. However, if I go back to my terminal here, I'm just going to run a curl request. I already had that in the copy. Run a curl request to that endpoint and we can see that we're getting the current weather data back. This JSON Blob that we just got back.

Speaker 1 (05:35)
I'm going to copy that and what I'm going to do is pull it over to a handy little tool, which is actually offered by Walmart Labs, that will take a JSON object and generate a GraphQL schema for it. If I drop that in there, we can see that it formats it out and then created these different objects, or types, excuse me, which represent the schema of the JSON. I'm going to copy that schema over to my schema.graphql file and I'm going to paste it above the rest of the information. Just go through a little formatting here.

Speaker 1 (06:21)
Here we go. Almost there. 1 second. I should have a GraphQL formatter but I don't think I do. Almost there. I'm going to leave those as that. We can't have an integer as the key name so I'm just going to change this name for oneh and then... boom. We really don't have to do that but keep it pretty. Awesome. That essentially types out our entire response structure. What I'm going to do is just rename this CurrentWeatherType. Now, inside that response, right next to the user, I'm going to say currentWeather is the object name, or the key name, and then the type associated with it. So now we know that to this query, we pass the ID of the user and then we get back a response object which has the basic user details in the current weather type. Awesome.

Speaker 1 (07:33)
What we're now going to do is go into the handler function. Now, something that's important here is we know that we need to pass it the ID, so we want to make sure that when we run our function, we pass it an ID as the mock data.

Speaker 1 (07:46)
So I'm going to go back into the workspace, go to the Users table, and just select a user Steve Jones. Steve Jones's ID. Drop it in there. We're not using the body but I just like to do it.

Speaker 1 (08:04)
Now that we have that there, if we go back to our—close that, close that, close that—handler.js file, we can invoke this function locally to make sure that we got the ID and that everything's wired up. Everything's wired up, we're good to start going.

Speaker 1 (08:31)
The first thing, we know that we're going to have to make a get request from this node environment. I'm going to npm install axios to the project so that we can use axios as HTTP Client. And then inside here, I'm going to put a constant call axios, I'm going to require it. Now we have that module.

Speaker 1 (09:06)
The first thing that we're going to want to do is actually get the user data. So let's just go ahead and do that. We are going to want to write a query, excuse me, a constant, which is going to be called QUERY_USER. That's going to be a GraphQL query, where the query that we get receives an argument, a variable called ID, which is of the type ID and that's mandatory. It's going to run the user query which accepts the ID; and then returns the ID of the user, the first name of the user, like we wanted, the last name of the user, like we wanted, and the email address of the user, like we wanted. But this is also going to get the location of the user, which we want the coordinates from.

Speaker 1 (09:59)
Now, in order to run that, we have the context module. So I'm going to say that the constant, and we're actually going to unpack this. The first thing that we want is the user object. And then from the user, we're going to do something here. We're going to say that we want the location and we want the coordinates from the location. The rest of the data, we're actually just going to throw into an object called user. That'll be perfect. And then we're going to wait the response from the ctx.api.gqlRequest. There we go. To that, what we want to pass is the QUERY_USER, query—probably should call it user query, but it didn't. And that's going to take the argument of id, or the variable ID, which we're going to get from the event.data.id.

Speaker 1 (11:05)
What we're going to do is let's just run this, really, console.log, the user argument and the coordinates, to make sure that we're getting those as we expect, invoke-local. Awesome. Yes, user data is there and coordinates are there, so we're good so far.

Speaker 1 (11:28)
Now, the next thing that we're going to want to do is run the API request to the weather API. What we can do is we can get a constant called… We're going to unpack the response so the axios response is going to be a key of data, that's what we're going to care about. We'll unpack that data and we're going to rename that currentWeather. To that, we're going to await axios.get, and we're going to then go snag—let's just snag it from the documentation—this right here and drop that in there.

Speaker 1 (12:23)
Actually, I'm going to use a string literal so that we can interpolate the variables in there as well as the API key. API key, for now, I'm just going to set as a constant even though we'll do as an environment variable soon. API_KEY. Cool. Let's go grab that API key. If I go to my account here, my API keys, and copy that in, got my API key.

Speaker 1 (12:59)
Now, let's form that URL fully. That's going to be coordinates returns in array, with lat and long as the first and second, the 0 and 1 index. So we're going to pull that from there. Awesome. That is good at this point. Here, what we're doing is we're getting our… Let me pull that out of the function. So we have, essentially, our API key here as well as our query here. We're importing axios. We're getting the ID of the user from the event data. Using that, we're querying the user data and just getting their basic information plus the coordinates of their current location. We're then using those coordinates as the input to the subsequent API call, which is hitting that weather API using our API key. And we're getting that data back and calling it currentWeather. Then, in the response, what we care about is making sure that we are returning the user and the currentWeather. If we look at our schema.graphql file, we can see that in that response to user and currentWeather, those need to match for this all to get wired up correctly.

Speaker 1 (14:15)
Now, what I'm going to do is I'm going to run the invoke-local request one more time, and we can see that we are getting the data back from the weather API showing that Steve Jones is in—where does it say—Miami. Makes sense, right? As well as the basic user data. And it's stripping out the location data as we did inside when we unpacked the response.

Speaker 1 (14:43)
Now, this is just running the function. It's passing the ID to the function and then returning all the data. This is going to behave differently when we deploy it to our GraphQL API because we will then be able to choose the data that we want back. So we want to make sure that everything works as expected.

Speaker 1 (15:03)
The one thing that I will do at this point is just, say… Let's just do it like this. I'm going to delete that API key there and I'm just going to say this is me called WEATHER_API_KEY, where you get it from process.env.WEATHER_API_KEY. We could deployed it just as we did, but I'll just show you how to set the environment variable. Now, what I'm going to do is I'm go run 8base deploy, and this is going to deploy it straight to my workspace. As that's deploying, let's go set that environment variable. Here I am in my workspace, settings, environment variables, WEATHER_API_KEY, and add that value, stripping away the strings. That's added. So now, when that function runs in production, it will access the WEATHER_API_KEY from the environment variable, rather than just appoint with the static string inside the code, which is never a good practice.

Speaker 1 (16:16)
Now, let's go back. It deployed. Awesome. Inside here now, what we can do is we can check out our API Explorer, delete that, run a query where we get the userWithCurrent Weather. And I'm going to go back to our node and just get the user ID here. We're going to pass the ID here. Now, we can get from our response object. So we're going to say from the user, in this case, we just want their ID and their first name. It looks like I had to type in there with email, so that would probably throw an error if I ran it, but we could correct that easily. CurrentWeather, and here's now where I can say, "Okay, I want the name." We're going to find out what that means. I want the coordinates, so I want the longitude and the latitude, and then I want the weather. The weather info I wanted, I want the main, whatever that means, the description; and let's also go for sys, which is the country, sunset, and sunrise times.

Speaker 1 (17:37)
So now if I run that resolver, we can see that it got all the data from both the 8base database as well as the API, and merged it into the response as we structured that response. Now, we kind of just did like a one-to-one mapping here. Just saying, "Hey, here's the response, here's the type word, boom, throw it in." But if you wanted to, of course, you could restructure this into any way that you need to, as well as reuse some of the API types that 8base exposes for you. So a lot of kind of different options in here that you get to play with.

Speaker 1 (18:08)
I hope that you found this video helpful in giving you some pointers, tips, and kind of strategies to integrating third-party APIs into your 8base workspaces, specifically, in this case, using and resolver function to do so. If you do find this video helpful, please subscribe to the channel for future updates, and looking forward to seeing you in future videos. Happy developing.

Share this post on social media!

Ready to try 8base?

We're excited about helping you achieve amazing results.