1 00:00:01,010 --> 00:00:02,650 Finally, let's now handle 2 00:00:02,650 --> 00:00:05,053 Mongoose's validation errors. 3 00:00:06,630 --> 00:00:09,750 So remember how we tried to update a tour 4 00:00:09,750 --> 00:00:11,410 with some invalid data here, 5 00:00:11,410 --> 00:00:13,890 and then got this kind of error? 6 00:00:13,890 --> 00:00:15,160 Okay. 7 00:00:15,160 --> 00:00:17,923 And let's actually try to add another one. 8 00:00:19,890 --> 00:00:24,350 So a name that's really short, okay? 9 00:00:24,350 --> 00:00:27,410 And because that's not allowed, again. 10 00:00:27,410 --> 00:00:30,680 Oh and now we actually no longer can see our error 11 00:00:30,680 --> 00:00:33,000 because we're now in production. 12 00:00:33,000 --> 00:00:34,750 And of course this error right now 13 00:00:34,750 --> 00:00:36,370 is not handled correctly. 14 00:00:36,370 --> 00:00:38,730 It is not marked as operational. 15 00:00:38,730 --> 00:00:39,580 And so therefore, 16 00:00:39,580 --> 00:00:44,020 remember we get this kind of generic error message back. 17 00:00:44,020 --> 00:00:45,040 Okay? 18 00:00:45,040 --> 00:00:49,530 So just to see the error that we had before, 19 00:00:49,530 --> 00:00:52,263 let's quickly switch back to development. 20 00:00:53,810 --> 00:00:55,253 So npm start. 21 00:00:58,950 --> 00:01:00,610 And, 22 00:01:00,610 --> 00:01:01,810 send it now again. 23 00:01:01,810 --> 00:01:05,220 And so now we get back our development errors, okay? 24 00:01:05,220 --> 00:01:06,590 Because now I want to show you 25 00:01:06,590 --> 00:01:10,410 how we can actually create a meaningful error message 26 00:01:10,410 --> 00:01:13,590 based on all of this, what we have here. 27 00:01:13,590 --> 00:01:14,670 Now right. 28 00:01:14,670 --> 00:01:16,690 So inside our error, 29 00:01:16,690 --> 00:01:19,280 we get an error properties. 30 00:01:19,280 --> 00:01:21,800 And that property itself is an object 31 00:01:21,800 --> 00:01:24,540 which has a lot of objects in there, 32 00:01:24,540 --> 00:01:28,770 and each of them is for one of the fields that has an error. 33 00:01:28,770 --> 00:01:29,790 All right? 34 00:01:29,790 --> 00:01:33,760 So the first one here is for the length of the tour. 35 00:01:33,760 --> 00:01:35,760 Then the second one is for the difficulty, 36 00:01:35,760 --> 00:01:37,310 that is also wrong. 37 00:01:37,310 --> 00:01:40,400 And the third one is for the rating, okay? 38 00:01:40,400 --> 00:01:44,520 So each of these actually has a nice error message, okay? 39 00:01:44,520 --> 00:01:48,210 So basically the one that we defined in our Mongoose schema. 40 00:01:48,210 --> 00:01:50,480 And so now we want to extract 41 00:01:50,480 --> 00:01:52,490 these three messages from here, 42 00:01:52,490 --> 00:01:55,920 and put them all into one string, all right? 43 00:01:55,920 --> 00:01:58,593 So let's go ahead and do that. 44 00:01:59,720 --> 00:02:00,553 Okay. 45 00:02:00,553 --> 00:02:01,740 And again, I'm gonna start 46 00:02:01,740 --> 00:02:05,363 by actually creating the conditional down here. 47 00:02:06,720 --> 00:02:07,553 So if(error), 48 00:02:09,210 --> 00:02:10,760 and actually let's take a look. 49 00:02:12,270 --> 00:02:14,290 So here we have the error. 50 00:02:14,290 --> 00:02:16,413 We have the errors, all of them. 51 00:02:17,510 --> 00:02:19,840 And I need to scroll here. 52 00:02:19,840 --> 00:02:22,320 And yeah, so here's the name. 53 00:02:22,320 --> 00:02:26,300 So error.name is ValidationError, all right? 54 00:02:26,300 --> 00:02:27,453 So let's grab that. 55 00:02:32,150 --> 00:02:32,983 Okay. 56 00:02:32,983 --> 00:02:36,010 And so this again, is an error created by Mongoose. 57 00:02:36,010 --> 00:02:37,440 So just like the first one, 58 00:02:37,440 --> 00:02:40,023 and so they look similar, okay. 59 00:02:41,150 --> 00:02:42,553 Now I don't want this here. 60 00:02:43,400 --> 00:02:45,410 But instead I want that the error 61 00:02:45,410 --> 00:02:48,863 should be equal to handleValidationErrorDB, 62 00:02:54,290 --> 00:02:57,123 and send in the error, okay? 63 00:02:59,400 --> 00:03:00,933 Now let's copy this again. 64 00:03:08,560 --> 00:03:09,840 All right. 65 00:03:09,840 --> 00:03:13,723 And let's again, simply start by creating our message. 66 00:03:19,090 --> 00:03:20,523 Invalid input data. 67 00:03:23,060 --> 00:03:25,043 And then let's also return the error. 68 00:03:27,520 --> 00:03:29,020 So new AppError(message, 400). 69 00:03:30,275 --> 00:03:31,860 So VS Code already recognized 70 00:03:31,860 --> 00:03:35,073 that I wanted to type just that, all right? 71 00:03:38,130 --> 00:03:40,280 Now in order to create one big string 72 00:03:40,280 --> 00:03:43,400 out of all the strings from all the errors, 73 00:03:43,400 --> 00:03:46,330 we basically have to loop over all of these objects, 74 00:03:46,330 --> 00:03:51,180 and then extract all the error messages into a new array. 75 00:03:51,180 --> 00:03:53,573 So let's again, take a look at that. 76 00:03:54,440 --> 00:03:55,320 Okay. 77 00:03:55,320 --> 00:03:58,430 So the object that has all of the objects 78 00:03:58,430 --> 00:04:01,290 in there is errors, okay? 79 00:04:01,290 --> 00:04:03,800 So we have one error for name, one for difficulty, 80 00:04:03,800 --> 00:04:05,870 and one for ratingsAverage. 81 00:04:05,870 --> 00:04:09,923 And so we're gonna basically loop over this errors object. 82 00:04:10,810 --> 00:04:11,660 Okay? 83 00:04:11,660 --> 00:04:14,190 And in JavaScript, we use Object.values 84 00:04:14,190 --> 00:04:17,290 in order to basically loop over an object. 85 00:04:17,290 --> 00:04:19,720 So the elements of an object. 86 00:04:19,720 --> 00:04:21,260 All right? 87 00:04:21,260 --> 00:04:25,000 So let's create a variable here called errors, 88 00:04:25,000 --> 00:04:26,700 which again will be an array 89 00:04:26,700 --> 00:04:28,583 of all the error messages for now, 90 00:04:29,640 --> 00:04:32,963 and now Object.values. 91 00:04:34,930 --> 00:04:38,863 And so we want the values of err.errors, all right? 92 00:04:41,540 --> 00:04:44,580 And now loop over them using a map. 93 00:04:44,580 --> 00:04:46,160 And then in each iteration, 94 00:04:46,160 --> 00:04:50,220 we are simply gonna return the error message, okay? 95 00:04:50,220 --> 00:04:54,540 So just to make sure we're all on the same page here, 96 00:04:54,540 --> 00:04:59,470 the Object.values are these objects, okay? 97 00:04:59,470 --> 00:05:04,190 So this object, and this object, and the next one, okay? 98 00:05:04,190 --> 00:05:05,730 So these are the values. 99 00:05:05,730 --> 00:05:06,930 And so now all we have to do 100 00:05:06,930 --> 00:05:09,110 in order to extract the message, 101 00:05:09,110 --> 00:05:12,210 is to say value.message, okay? 102 00:05:12,210 --> 00:05:13,533 So .message. 103 00:05:16,410 --> 00:05:18,380 So basically the current value, 104 00:05:18,380 --> 00:05:19,710 or let's say the current element, 105 00:05:19,710 --> 00:05:21,653 I like to use element for that, 106 00:05:22,640 --> 00:05:25,423 and we want to return el.message. 107 00:05:26,870 --> 00:05:27,703 Okay. 108 00:05:28,940 --> 00:05:32,040 And now, of course, this should not be here. 109 00:05:32,040 --> 00:05:34,140 And you had probably already noticed that. 110 00:05:35,260 --> 00:05:39,930 So in fact, this is where we want this, okay? 111 00:05:39,930 --> 00:05:41,280 And so now all we need to do 112 00:05:41,280 --> 00:05:45,163 is to pluck this into our message string, all right? 113 00:05:46,830 --> 00:05:51,700 So errors, and now we simply join all of them together 114 00:05:51,700 --> 00:05:56,700 into one string using period and then space, okay? 115 00:05:56,930 --> 00:05:59,263 And you will see, in a second, why that is. 116 00:06:00,350 --> 00:06:01,183 All right. 117 00:06:02,590 --> 00:06:05,130 So let's switch back to production here. 118 00:06:05,130 --> 00:06:07,483 So running our production start script. 119 00:06:08,960 --> 00:06:12,083 Try it again now and let's wait for it, 120 00:06:13,440 --> 00:06:14,310 and bam! 121 00:06:14,310 --> 00:06:15,470 Here we go! 122 00:06:15,470 --> 00:06:17,530 So invalid input data. 123 00:06:17,530 --> 00:06:19,990 Then the first error string, 124 00:06:19,990 --> 00:06:22,150 must have more or equal than 10 characters. 125 00:06:22,150 --> 00:06:23,810 Then the second one, 126 00:06:23,810 --> 00:06:26,040 and the third one. 127 00:06:26,040 --> 00:06:26,900 Perfect. 128 00:06:26,900 --> 00:06:30,210 And so that's why I used the period and space, okay? 129 00:06:30,210 --> 00:06:33,680 So to basically separate these three strings 130 00:06:33,680 --> 00:06:36,210 with a period and a space, all right? 131 00:06:36,210 --> 00:06:38,680 And now this looks like a very nicely formatted 132 00:06:38,680 --> 00:06:41,693 error message that everyone can easily understand. 133 00:06:42,870 --> 00:06:43,703 Right? 134 00:06:43,703 --> 00:06:46,180 So, we're basically done here. 135 00:06:46,180 --> 00:06:47,013 All right. 136 00:06:47,013 --> 00:06:49,890 Now we could've made this error, handling error, 137 00:06:49,890 --> 00:06:52,120 a lot more complete still. 138 00:06:52,120 --> 00:06:56,640 For example, we could define different error severity levels 139 00:06:56,640 --> 00:06:59,130 like saying, this error is not so important, 140 00:06:59,130 --> 00:07:01,130 this error is medium important, 141 00:07:01,130 --> 00:07:04,770 and this error is very important or even critical. 142 00:07:04,770 --> 00:07:08,400 And we could also then email some administrator 143 00:07:08,400 --> 00:07:10,430 about critical errors. 144 00:07:10,430 --> 00:07:14,120 And really, there's a lot of stuff that we could implement. 145 00:07:14,120 --> 00:07:18,300 But again, in a kind of small application like this one, 146 00:07:18,300 --> 00:07:21,810 what we have here is already really good, okay? 147 00:07:21,810 --> 00:07:24,410 So this is quite a robust strategy already 148 00:07:24,410 --> 00:07:25,970 that we have implemented here, 149 00:07:25,970 --> 00:07:29,150 and I'm really happy with it, okay? 150 00:07:29,150 --> 00:07:32,520 So all this logic here with the operational errors 151 00:07:32,520 --> 00:07:34,200 that we implemented here, 152 00:07:34,200 --> 00:07:36,393 so that's already quite sophisticated. 153 00:07:37,250 --> 00:07:38,083 Okay? 154 00:07:39,290 --> 00:07:42,190 Now if we were ever to find another error 155 00:07:42,190 --> 00:07:44,420 that we want to mark as operational, 156 00:07:44,420 --> 00:07:46,410 then of course all we would have to do 157 00:07:46,410 --> 00:07:50,120 is something similar to what we have here, okay? 158 00:07:50,120 --> 00:07:53,750 So basically implement another function for that one, 159 00:07:53,750 --> 00:07:56,630 and then return our own operational error 160 00:07:56,630 --> 00:07:58,620 so that the send error production 161 00:07:58,620 --> 00:08:01,580 can then actually send that operational error 162 00:08:01,580 --> 00:08:03,473 to the client, right? 163 00:08:04,320 --> 00:08:06,580 Okay, and with that being said, 164 00:08:06,580 --> 00:08:09,080 our error controller is actually finished. 165 00:08:09,080 --> 00:08:12,010 But there are still some other errors that we need to handle 166 00:08:12,010 --> 00:08:16,090 which are completely outside of Mongo or even of Express. 167 00:08:16,090 --> 00:08:19,123 And so we're doing that in the rest of this section.