Runtime Type Checking and Parsing in Prisma with Raw Queries
00:00 So let's make a schema for a individual user here. We're going to call this our user search results schema. And we'll just do an individual search result. So each one of these individual users. We're going to bring in Z from Zod. This is going to be an object, and it's going to have an ID.
00:19 It's not a number copilot. I don't know why copilot really wants IDs to be numbers, but they're super duper not. And then we've got our username and our name is nullable, because our name could possibly not be defined. That's an optional field.
00:33 And then we're going to make our user search results schema, which is going to be an array of those things. Okay, great. Then down here, we're going to say these are our raw users. This is the unknown thing that we've got. And the question is, okay, Kent, so we're the ones who are controlling the database.
00:52 We're the ones who are controlling the query. And so why should we do runtime type checking of something that we have total control over? And the answer is that it's very possible that somebody could change the schema so that name is now first name and last name.
01:11 So they could change the schema in that way, but there would be no checking here to say whether this query is still accurate, right? So you change the schema, but have no protection on this particular query. And then you would end up with our parsing
01:31 not working properly, or if we don't parse at all, you wouldn't get a useful error. You'd get like a totally useless error. And so by forcing ourselves to parse our own stuff, we're at least giving ourselves a nicer error for when those sorts of things do happen. And hopefully if you have tests,
01:51 you'll catch that before you actually deploy to production. So parsing will help with that as well. So let's go get our result from our user search results schema, safe parse on the raw users. And then we can say, if result.success, if it's not successful,
02:09 then we're going to want to return an error. So we'll say, yep, status is error. The error is the result error message. And we'll set that as const. And then also let's give it a status of 400. So browsers behave properly
02:27 as far as whatever it is that they do on these different pages. Browsers do all sorts of things based on this status code. So always a good idea to keep the proper status code. And then if there's not an error, then we can return a status of idle and the users is now going to be result.data.
02:44 And just like that, we've got those type issues are gone. We have a new one because of this image. We actually don't have that image there yet. So we're going to just ignore this for now. We'll get to it very soon. And yeah, we're pretty well taken care of.
03:03 We got a couple of other things that we want to do here, but let's just double check. I can search for Co and there's Cody. So we're in a good place there and everything is nice and type safe. If I miss the username, then we're going to get our error and we need to display that error message. So I'm going to leave that error state right there
03:23 and let's get our error message displayed. So first off, I'm going to console log the error for my own debugging purposes. We can take a look at our console here and we'll see we've got this error, which should hopefully be helpful in our debugging of whatever the problem was. And then down here,
03:42 we're going to do something useful for the user. So we'll say, let's bring in this error list and just provide the error. There was an error parsing the results. So the user is not going to be able to do much if this error does happen. So we're not going to give them what the error message was. That's why we log it to the console ourselves.
04:01 And there we go. There was an error parsing the results. And then you could say like, please report this or whatever, like here's the report email or whatever. But yeah, so now if I restore this to its previous glory, then our users load properly. So we get everything, it's nice and type safe,
04:18 result.data. and now it's an array at zero. And then, well, yeah, let's come down here. We'll see what that type safe stuff looks like. So we've got the ID and the name and the username. So we are all set there.
04:38 Again, not my favorite part of Prisma, to be perfectly frank, but I am willing to deal with this because it's such a rare thing that you have to do raw queries. And the workaround for dealing with that, it's not even really a workaround. Like this is a legit API. You can actually use it. You can use regular SQL.
04:57 And so it's not necessarily a workaround, but the way that you make it type safe with this runtime type checking stuff is, in my mind, is perfectly fine. Now, if you really wanted to, you could, like if you were worried about, oh, like we've got 10,000 results coming back from this, I cannot be parsing that
05:17 because it's gonna be a performance problem. Then you can, in fact, make this so that you only run this in a development environment. And then in production, you can still get the type safety and all of that, but you, in production, won't actually parse the results and it will still work just the same.
05:36 So if that's a concern for you in parsing those results, then that's certainly something that you could consider. This tiny bit of extra work is worth it for all of the awesome benefits that Prisma gives us, which is why I'm teaching you Prisma. And that's why I think Prisma is epic. And potentially in the future, I don't think that there's any reason
05:55 Prisma couldn't itself implement the same types of APIs that some of the other ORMs do offer as well. So if any of you are interested in implementing something like that, that would be a pretty awesome feature to work on. So anyway, hopefully that was a fun exercise for you. Let's keep going.