This course has been updated! We now recommend you take the Server-Side GraphQL in Node.js course.

Check out a free preview of the full Introduction to GraphQL course:
The "Create a Schema Solution" Lesson is part of the full, Introduction to GraphQL course featured in this preview video. Here's what you'd learn in this lesson:

Scott live codes the solution to the exercise.

Get Unlimited Access Now

Transcript from the "Create a Schema Solution" Lesson

[00:00:00]
>> Scott Moss: So now we get that out of the way, let's go ahead and get some of these test to pass. So product has base fields, well, the only way you would know what fields to put here is if you were to look at the test. So we're gonna look at product.type.spec, we'll see what base fields are and we'll try to imitate that.

[00:00:21]
>> Scott Moss: So it says baseFields are gonna be these fields, name, price, image, type, all this stuff. So I'm just gonna take a shortcut, I'm just gonna copy all that.
>> Scott Moss: Copy those baseFields, go over to product, I'm gonna make a type called product.
>> Scott Moss: And I'm gonna give it these fields.

[00:00:47] I get rid of all these quotes, parenthesis, there we go. So looks like I've got the fields in. Gotta get rid of these comments, too.
>> Scott Moss: There we go. So, got those filled in with the exact types that they need to be. So we can see here, if we're just taking a look, got a name, got the string, that's required, a price, that's a float that's required.

[00:01:13] An image, that's a string that's required, a type that's a product type. And if you scroll up, ProductType is an enum. Remember, I said enums are just like strings with hardcoded values, it must be one of these. So that basically means type can be either GAMING_PC, BIKE, or DRONE.

[00:01:32] createdBy is User type which does not exist anywhere in this file because it's in another file down here in user, so that's why that's there. Description is a string, liquidCooled, range, bite. So where did I get all this stuff from? Well, if you remember when I talked a while ago I said a good starting place for some of your types is gonna be your database models.

[00:01:52] So if you were curious, you clicked on product.model. And if you looked at the stuff in this Mongoose schema, it's mostly the same stuff that it's on our GraphQL type that we just made. Literally have the exact same types on there, they're all exactly the same. So that's where I got this from, it's a good place to start from.

[00:02:12]
>> Scott Moss: So now that we got that, and just a primer on the product, a product is basically like our e-commerce store only sells three things. It sells gaming PCs, bikes and drones. That's it, it's a Black Friday ecommerce website. It only sells the hot stuff for the kids.

[00:02:27] And each product is a different type and depending on the type, it will have a different property. For instance, if the product is a gaming PC, it will have a Boolean if its liquidCooled or not. If the product is a bike, it will have a BikeType. If the product is a drone, it will have a range field on it.

[00:02:43] And all that is dictated by the product model. If you go look at it, you can see liquidCooled is required if the type is GAMING_PC, bike type is required if the type is BIKE. Range is required if the type is DRONE. So that's how it's determining what type it is.

[00:02:58] And that's all happening on a database level, it's abstracted away from GraphQL. But that's where these fields came from, just so you have some background of where's this stuff coming from? That's where it came from. This is gonna make more sense when we get into interfaces and unions.

[00:03:12] It's gonna be more important there. Okay, so let's run this test.
>> Scott Moss: You can also do --watch which will keep the test running and rerun only the broken test. So that will speed things up, too.
>> Scott Moss: So it looks like that one passed, new product input has correct fields.

[00:03:31] So we can look at that one. What is that one? Looks like new product wants these fields, so I will go ahead and copy those. And we will head over to, and because it's an input, I need to make an input type, so I will say input NewProductInput.

[00:03:52]
>> Scott Moss: And I would put those fields in there like this. I'll get rid of these, I'll get rid of these and I'll fix the spacing. There we go. So now we have a new product input, that's mostly the same as the product. It's just added to input now, and there is no createdBy, on the input because the createdBy is going to be assigned by the resolvers after authentication.

[00:04:22] So you don't have to tell us who's created by, we'll add the created by by whoever sent in the request. So some of this stuff has taken off. So not only is it a slightly different field, but it's just an input and not a type. So if you run a test on that.

[00:04:42]
>> Scott Moss: So that passes, so then now we need to update product input has correct fields. So if we go back, scroll down to UpdateProductInput, let's grab this.
>> Scott Moss: Copy that, and we'll make a new input cuz this is also an input, so Update,
>> Scott Moss: ProductInput. And remember, I just like to use the word input as a suffix to my inputs so I know that they're inputs.

[00:05:09] You don't have to. You can just call this UpdateProduct if you want, but it's kind of, what is that? Is that a type, a query? I don't know. So I like to just do that. And I'll add these back here. And then get rid of the commas. And then fix the spacing.

[00:05:29]
>> Scott Moss: So I'll run the test for that. And you notice that none of these have required validations on them, and that's because if I made any of these required, that means whenever you do an update, you have to update one of these fields. That's not what you want.

[00:05:42] These fields aren't required cuz I don't know which fields you're gonna update, so you can add any ones that you want to update, whichever ones are updatable. So that's why they're not required. So if we go look at that, that's good to go. So now it looks like we need to make a product query.

[00:05:58] So remember what I said? When you make the queries, make sure you extend the type called Query cuz it's already created. If you didn't do that, you're gonna get an error saying, it was already created and that means you need to go extend it. Extend type query, just looking for a query called product, lower case p, singular, product.

[00:06:18] And if you go look at the spec, we can see that it looks like it's taken an id, and it returns a product type. So you would have to put the two and two together and look at my query to see that it's expecting an argument, and there's some random thing here.

[00:06:34] It's called id, so we can try the id type. So I'm gonna call it id, just like I see it there, and I'm gonna say id type, I'm gonna make it required. And I know it returns the Product type, so I'll do that.
>> Scott Moss: So this is saying, I have a query called product, lower case p.

[00:06:55] It takes one argument by the name of id. Its type is an ID, scala type that's not null or required. And it returns a product type that's not null. That's what that's saying there.
>> Scott Moss: If we run that, it looks like that passes, so the next one is a products type, so pluralized, products.

[00:07:21] And if you go look at the spec for that, it looks like this one is taking, it's not taking any arguments and it's returning just this objects here. So this test isn't very strict, so there's two ways you could have got this to pass. So we know it doesn't take any arguments.

[00:07:43] But you could also have just put products here, like this, and it would pass. But you can also wrap this in an array and it would still pass. And the reason that is, is because if this wasn't an array, you still have to do the same syntax like this in your query.

[00:07:59] You still say, okay, if this an array of product, I still only want the name, price, image, and type of those objects in any array. If this is not an array, you still would say, I want the name, price, image, and type. So your query doesn't change because something is in an array.

[00:08:12] And because my test is only testing this query, your schema would've worked for an array or not an array. Seeing how this is pluralized, an array would probably make more sense.
>> Scott Moss: So, you could do that.
>> Scott Moss: And I don't know if it's not null or not, but let's check it out.

[00:08:33]
>> Scott Moss: Scroll up. Yeah, so it satisfies that query. So like I said, you can put it in an array or not. It'll still satisfy the query cuz the test is not that strict. So now we have a new product mutation. Extend type Mutation, just like we did the query.

[00:08:51] And we need a newProduct. If you scroll up, we already created input for a new product. It's called a NewProductInput. So that's why we created it, cuz we're gonna use here on the new product. So if you look at the test, new product mutation, we'll talk about this in a minute, these names, these named operations in GraphQL, but the mutation is right here.

[00:09:14] It's a new product, it's expecting some variable called input, and its value's gonna be an input that's referenced here on the new product input. So I'm gonna say new product.
>> Scott Moss: I'm gonna give it a variable name called input, and I'm gonna say its type is going to be new product input, that's required.

[00:09:34] And it's gonna return a Product type, like that.
>> Scott Moss: So I'll run the test.
>> Scott Moss: And that satisfied the NewProductTest, so then I could go ahead and run the, or I can create the update product mutation. So updateProduct mutation. And if we go look at the test for that.

[00:10:06] That's taking in an ID and an input. So ID and and input. It's referencing a variable up here. It's type is ID, this is referencing a variable up there, its type is UpdateProductInput. So we didn't talk about variables yet inside of named operations. But if you look just here at the mutation itself where we did talk about args, you'll see that its name is ID, its name is input, and that's all we really need.

[00:10:30] So, we know it takes an id of type is ID. And I know it takes an input whose type is the one we already created up here, UpdateProductInput. So, I'll go ahead and put that in, and that's require, and it too returns a type of Product.
>> Scott Moss: So I'll go ahead and test that.

[00:10:59]
>> Scott Moss: And that satisfies that. And the last one is removeProduct.
>> Scott Moss: And if we just look at removeProduct, I'm sure it'll only takes one argument which should just be an ID. You only need an ID to remove something. So, we'll just say yep, just text an ID, and it returns a product that got removed.

[00:11:23]
>> Scott Moss: And we run those tests.
>> Scott Moss: And that's all the tests.