
REST & GraphQL API Design in Node.js, v2 (using Express & MongoDB) Exercise: GraphQL & Express
This course has been updated! We now recommend you take the API Design in Node.js, v4 course.
Transcript from the "Exercise: GraphQL & Express" Lesson
[00:00:03]
>> Scott Moss: We're going to hook our Express server up, I'm sorry, we're going to hook our Graph QL implementation up to Express. And we should be able to run it and go to GraphiQL, so I'm going to walk through some stuff of what that looks like. And then you guys are going to be sent off and try to tackle it, so I'm going to check out to lesson-10.
[00:00:29]
>> Scott Moss: Yeah, lesson-10, what's this?
>> Scott Moss: Okay, so I'm on lesson-10 here. And then, you'll see a new file here on lesson-10, it's not an exact copy of the lesson-9 solution, so there's an added file here. And you'll see this file right here, so let's just walk through it.
[00:00:47] There's a lot that's happening in this file, but I needed this to be here so we can go through what I need you to do. So the file I'm talking about is called graphqlrouter.js. It's in the root of the API folder, source API.
>> Scott Moss: GraphQLRouter JS, so if you get there, follow along with me.
[00:01:10] So a couple things that's going on right here, let me close the double pane, the first thing to note is look at the imports we've got going on. We have this make executable schema from GraphQL tools. GraphQL tools is a library created from some individual and it's a really good library.
[00:01:28] This is what's going to allow us to combine our queries and have them know about each other. And do some really cool things like extending mutations in the extending queries, and we'll talk about that later. But this gives us that flexibility to build our schemas in the string format.
[00:01:43] Which I think is way more powerful than the JavaScript format, so that's going to do that. But we need to convert our string schemas into an executable schema that the GraphQL server can use to check the query against. By default, it doesn't know what to do with that string, it has to convert it to that AST.
[00:02:00] It has to convert it to that JavaScript type that we were trying to avoid, that's what that's going to do. It's going to convert it for us so we don't have to do it. And then we have this userType and these userResolvers, we haven't talked about resolvers, you don't need to know what they are.
[00:02:15] It's just an object with some methods on it, but we do know what a userType is. The userType is the GraphQL file that we wrote. That's what that is, it's just that string, this is just that string of that GraphQL file. If you were to log it, you would see the exact same thing that we wrote in that file, nothing more.
[00:02:30]
>> Scott Moss: We've got merge, we know what merge is at this point. And then we have graphqlExpress, graphqlExpress is a middleware that we use to mount a GraphQL server on an Express route. And that's what we're going to use to attach our GraphQL type definitions and resolvers to our root Express applications.
[00:02:52] Remember the root app that we made yesterday inside the ServerJS file that uses global middleware, we're going to attach our server. Our GraphQL implementation there. So the first thing is, we have this baseSchema, this baseSchema is basically, a GraphQL schema by default has to have one thing. The minimum it has to have is a query, that's the minimum.
[00:03:15] If it doesn't have a query, then it just won't work, unless you're using Relay, but again, we're not going to use Relay. I actually don't recommend using Relay, I think Apollo's better, but that's just my opinion. So by minimum, we need a query, we don't need a mutation, but you have to have a query, this syntax is, it's just a string.
[00:03:32] I just didn't feel like putting it in another file because it's so small. This is like the root, this is like the index of our query, of our schema basically. So like I say, you can think of GraphQL as a tree, right, so a tree, this is a root, this is where it starts, right here.
[00:03:46] If we make a query, so we make a schema, we give it a property called query, and we set its type to Query. I didn't just make this up, these aren't just made up words, this is something that it needs. [LAUGH] I didn't just like, I'm just going to use these words, no, it needs a schema, or a property called query, edit type is Query.
[00:04:06] We didn't make this type called Query, it's a built in type, we just have to explicitly define it. Even though pretty much every server needs this, you still have to explicitly define this right here, this root, okay? So we have this root, that's the base schema, everything is going to be a child of this.
[00:04:25]
>> Scott Moss: And then we have the mid executable schema, and it takes an object with, for us, just two properties. An array of our type definitions, and our type definitions are those GraphQL files that we wrote. They're just strings, so we have our baseSchema, that's up here, and then I went ahead and put our userType.
[00:04:41] Which, again, is just this user grab field box, it's just this turned into a string, that's all that is. And then we have our resolvers, which is an object of all the resolvers put together. Again, we haven't talked about resolvers yet, but for now, just think of them, they're just methods, they're objects with methods on them.
[00:05:00] Those methods correlate to mutations and queries. And then we go ahead and merge them in, and then down below here is where it's pretty cool. We use this graphqlExpress, where it's, in the way that we're using it, takes a call back. And a call back exposes that powerful thing I was talking about, the request object that we needed, that has the headers, the path.
[00:05:23] Everything associated with the incoming request, we want to pass that down to every single graphQL resolver that we have. So it has access to it, we want to give every resolver the best tools it needs to resolve the data. So, inside of our controllers yesterday, we were able to pass down the request to every single controller, right?
[00:05:40] We want to do the same thing for every single resolver, by default, it won't do that, so we have to do that. So we create this graphqlExpress using Apollo server Express, and it takes, basically it has to return an object that has a schema. Which we already created up here, an executable schema.
[00:05:57] And then this context, when we get to resolvers, we are going to see what context is. But context is basically just an object that's going to be passed down to every single resolver, that's all that is. It's like, this object is going to be, every time you make a resolver, it's going to get this object.
[00:06:11] And we want to make sure that we pass down the request that came in, the request object, so we can share it. And then there's a shortcut, we're just going to go ahead and attach the user here, which is going to be our req.user. If we're using that middleware that we used yesterday, the authentication middleware that attaches the user to the request.
[00:06:25] That I already had built out for you, that's going to attach it to the request for us, if we decide to use that middleware or not. If we don't decide to use that middleware or not, it won't be there, it's going to be up to us. So that's a lot of information, but it's going to make more sense once you start doing resolvers.
[00:06:43]
>> Scott Moss: So your task is to find some way to get this freely floating GraphQL router attached to our Express router. Then set up graphical documentation so we can look at it, and I'm going to give you a hint, you're going to do it in here.
>> Scott Moss: You're going to attach that GraphQL router, and I have it right here.
[00:07:05] You're going to mount that GraphQL router on the Express app at /graphql.
>> Scott Moss: And then you're going to create another route for, I'm sorry, you're going to mount to that graph, /graphql. Then you're going to create another graph for GraphiQL. At the path docs, I didn't show you how to make GraphiQL so I'm going to show you how to do that.
[00:07:23] And then you're going to start the server and go to the docs. So if you just follow the clues and I'm just going to give you another hint here, inside of GraphQL router, this GraphQL is being exported. Right next to it, there is an index where the restRouter is being exported.
[00:07:41] I would say this is a great place to export the GraphQL router as well. And then if you go to the server file, you can see the restRouter is being imported from the api. I would say this is also a great place to import the GraphQL router. And then you know how to mount routers, that GraphQL router, at this point, is the same thing as a restRouter.
[00:08:01] And you saw how we mounted that, you just need to mount your GraphQL router on the different path of /GraphQL. And then as far as GraphiQL, for GraphiQL, you want to use, there's a plug in here called, where is that?
>> Scott Moss: Apollo, apollo-server-express, there should be a graphiql, let me see this, I forgot the exact name of it.
[00:08:42]
>> Scott Moss: Sometimes, I guess I miss TypeScript, having that there.
>> Scott Moss: Okay, so I think it is graph-i, yeah, it's graphiqlExpress, that's what it's called, okay, so using graphiqlExpress.
>> Scott Moss: What is the exact same thing as an Express router, the same thing as an Express router like this. The same thing as the GraphQL router that you are going to be importing, you need to mount that on /docs.
[00:09:24]
>> Scott Moss: So I'll leave the task up.
>> Scott Moss: There's one option that you have to pass to GraphiQL that I'm not going to tell you about. It's either going to break or you're going to look it up, but you've got to tell it where, what's the route for your GraphQL API.
[00:09:38] By default, it doesn't know, it will mount itself, and like, cool, but I don't know what URL to hit to talk to GraphQL, right? Because what the GraphiQL endpoint, what it does is it's going to load that interactive docs, which is basically a react app. And that react app needs to know what URL to talk to to get the data, you have to tell it what URL in the options object.
[00:09:56] But, a quick look at the documentation, you'll see really fast how to do it or you'll just get an error.