Video details

Zack Chapple - Adventures in Node and Nest - angularday 2019


Zack Chapple

Our story begins after you’ve created your Angular frontend: up until this point you’ve been using mock data and now you’re wondering “How in the world do I create the backend to power this application?” and “How can I leverage my existing Angular and TypeScript skills to do it”. In this talk we will go through setting up your perfect companion Backend. A Node server with Nest then extending the functionality to be ready for production.
Next edition: Friday 12th June 2020
Keep in touch!
Follow us on Twitter @angularday
Subscribe to our newsletter:


They also say, I had a little bit of an adventure yesterday, so I actually the day before yesterday, I was supposed to be on my plane to Italy and I get to the airport and they're like, you can't go. And I'm like, well, why can't I go? And they're like, oh, your passport is going to expire in 56 days. I'm like, Yeah, I'm going to Italy for five days. What's wrong with my passport? No, like, yeah, you need to have at least 90 days on your passport in order to be able to go to Italy. So tomorrow you need to go get a new passport. So I go to the passport office yesterday. I stand in line for three hours. I get a new passport and then I go to the airport to get them. I'll get ready to go. And I guess it costs fourteen hundred dollars more to go to Italy. And I'm like, Really? Yeah, that's not going to happen. So, you know, as much as I wanted to be their person, you know, there's a lot of things that worked against me being there. But I wanted to make sure everyone got this talk because it's something I really enjoy. It's something that I had a lot of fun building. And, you know, I there's a lot of cats in it, too. So hopefully everybody in this talk likes cats because there's going to be some cat meems and some cat pictures in it. And the entire project is literally about cats. So when you download the code, everything is cat related. So something a little I had a little bit fun building. Can everybody see my screen? OK, fantastic. So everybody, I would be talking about adventures in Node and Nest a little bit about myself. So I'm actually a principle architect at a company called Ultimate Software. We're based out of Florida in the United States. But believe it or not, we actually have an office in Paris. We have some folks who work in London and we have some folks who work in Amsterdam as well. And I think we might have one or two people that work in Italy remote. But if anyone is looking for a new job, ultimate software is a fantastic place to work. Angela, Web GDP, which means I get to do all kinds of really fun stuff with the community. I've actually I'm the founder of two other conferences. So Engy Atlanta, which is an angular conference here in Atlanta, Georgia, and Noad Atlanta, which we're starting for 2020. And I'm first time I've ever mentioning this. I'm actually a adviser for a react conference, so please don't judge me. There's a telegram and Twitter right there, too. So make sure if you guys have any questions after this talk, I'm 100 percent available on telegram, so I will let you know that I am very quick to reply as long as I'm awake a little bit. But Ultimate. So they they do something called optimization where they literally get everybody in a room for a week and teach you about the company and the culture, something that I think a lot of companies should do. And I really enjoyed. This is actually our chief people officer towards the end of the event. That was actually really fun. So what am I here to talk about? So throughout the day, you've heard a lot about building applications. After you build your application, you're ready like. Yes, fantastic. Everything is good to go now. I have this wonderful application, but wait. Right. You know, there's kind of something you that's missing other than just your front end. You need to have a back end. So now that you've built this application, you're kind of sitting there like what? How do we get to the next step? How do we get to where we actually want to go? So there's a couple of things I'm going to be covering in this I'm going to do. Don't worry about the slide, because I won't be sharing the slides as long along with the code afterwards. But there's a lot of stuff that we're going to cover in this talk, and it's going to be pretty quick. And I know after seeing this list, you're sitting here like, just give it to me. Give it to me. Right now, I want to see all this wonderful stuff, but I want to make sure you know that there's one thing I'm not going to cover. I'm not going to cover how to test. I'm not going to cover how note is better or worse than other topics, because, you know, first of all, nobody really tests anyway, so we don't need to learn about testing. All. That's really not why we're here to learn about why note is better than anything else. We're here to learn about something amazing. And I'm going to show you the world literally. I'll go I'll go back to that guy in the green who is try to take a picture of this Dega. I'm watching. I'm watching him. I'll let him know when he's that. So it's OK. So I'm assuring the world this is going to be a very quick talk about everything in Nest. So for those of you who don't know what Nest is, who knows what Nest is? Cool. OK. It is not the thermostat. For those of you who know the Nest thermostat is it is not the thermostat. Jazz getting. So. Nest was actually created by a guy named Camille. Camille is actually from Poland. He's actually in Florida right now giving a talk on a nest. And the nest is a progressive, no just framework built on top of typescript. So it's on top of typescript that you could use express with it. And the way I like to think about Nest is if anyone's done spring, I'm assuming everybody here has an angular and is familiar with Node and TypeScript. I like to think of it as a baby of all four of them. All right. How do you get nest, nest is really easy. They have a CLIA, you could use it very easily with an X workspaces, even if you're familiar with the Project X Plat by Nathan Walker and his crew. Nest comes bundled with that as well. The NSCLC is really easy to use. And what's really nice is that once you get it installed, it's really easy for you to start building your back application, right. So now you can go through and you can create a module, right. Just like you do with ANGULAR. You're gonna go ahead and create your module. You're going to build your little. I use this. Now, you talked in China as well. You're going to build your ravioli of code here. And this is going to be what's going to encapsulate all of your controllers and services. And the controllers are just a nice little annotation here that's going to start everything up. And that's that decorator's gonna be what really gives you all of the magic inside of Nest. So once you have a controller, it's really easy to begin to create your endpoints. You're just another annotation. You could do it. I get. You can have your parameter and then you could actually go ahead and use that parameter throughout your code. And you could see this controllers literally doing nothing, just returning the object. But you could see that they get users beginning to build out a little bit here. So there's a couple different ways that you could actually handle the response. So the annotation is actually pretty smart in that it can actually just take the default response and pass that. Jason, back to your application really easily. At the same time, if you're trying to do something a little bit more complicated, like setting custom headers, setting response codes, Peiping streams that actually have another annotation here that you can put on the function that allows you to hook into that response itself, that allows you to do a little bit more advanced stuff that we're going to cover a little bit later. At the same time, they also make it really easy for you to be able to catch and throw errors a little bit more if anything was ever thrown in there inside of a note application, had your application die. That's usually not something that you want to do, right. So we have something here that we can add another annotation for catch. And then once we do that, we can actually start to begin to throw HGP exceptions and those will actually be caught and passed down to the user. So this, for example, is going to throw a forum for all the way down to my user with this error message. So I don't have to worry about custom handling. I don't need to grab anything on the response here. Nest is smart enough to handle that for me. But I had this I had this controller. I don't actually go about persisting data. Right. Because, you know, that's great that, yes, we could send and receive information. But how do we actually persist something and we do that through something called a service. So very much like you do with ANGULAR, you could actually just provide a service. And that service is an injectable, just like you have an angular. And once you have that, you can begin to do things with it. So in this case, I have that same controller that I have. I've injected my cat service. I said there would be cats. There's plenty of cats. And what we're gonna do is we're actually going to do make turn this into an async function and we're going to wait for this cat service to actually do that find by breed. And we're going to take that and we're going to return that now or Darkthrone exception. So that's great. We're doing something from the actual persistance layer. But at the same time, that's not really everything we need because, you know, that's great returning from a service. But how do we actually had real persistence? Right. How do we actually put something all the way to the database? And with that, I like to use something called type O or M for for those of you who are not familiar with type or if you use in our arm in any of your existing back ends around like Java or dot net or anything like that, you'll be very familiar with this concept. There's a really nice one for typescript called Typo, or it takes added entities just like you would expect. And it does a lot of magic for you. And what that allows you to do is things like this. Right. So I'm going to specify a cat entity. It's going to have an owner. It's going to have a breed. And there's something interesting here, too, that I'll talk about later a little bit. But there's actually some lifecycle hooks on paper around where you can say, you know what, before I actually insert this to the database. If there is a hideout specified, let's go ahead and add that super secret hideout. So there is some interesting lifecycle hooks that you can use with a type or. And that'll make your life a little bit easier. And it's magic. Right. So it's going to go through and scaffold your database for you. It's going to do everything in terms of structuring the queries. It does all of that for you. And it's going to make your life, for the most part, easy. As long as you have a fairly simple application, you can get pretty advanced, but then you'll start having to do some custom sequel stuff. Once I've created that entity, I need to actually imported into my user my cat's model. There's a typo there. This used to be users. I need to import it into my cats module. Let's go ahead and do that again because I'm using typescript. I could just go ahead and pull it elements. Emma, pull the sense that the feature and I have my my cat entity and then Nest is going to know what to do from there. It's going to actually go through and make that available as something that is injectable. So I'm actually going to inject this repository. And once I do that, I get some really interesting stuff. Right? I get the value of that or immediately. So I get a promise. I'd promise. I'd call that I can make this a hey, you know what? Let's find all the entities where the owner is. This name. Right. That's really cool, because now I don't have to worry about understanding a sequel or Mongo or all these different data structures. I could just use my arm, Manisha. And then if I decide to in different environments, switch would datastore arm switch, which connection I'm on. That's OK, because my or code's going to stay the same. Right. And then at the same time, I get the ability to save. There is some interesting stuff there. I'll get on in a second here about why I'm doing this, because there's some there's some fun stuff that's going to be coming up. Now, what happens when your users send you something that you're not expecting, right? For those of you who are taking a second, one of these is not a cat. So what happens is that our users don't always do what we expect them to do. So one of the things that we want to do is we want to validate the requests that they send us. Right. That's something that is really nice to do. You don't want to be putting in a bunch of data that you don't expect. So we could do that with data transfer objects. Right. So with data transfer objects, you could go through and you can say, you know what? I'm expecting this field not to be empty. I can expect, you know, any of these different requirements. You could put on it for in this case, I'm just saying I expect these two fields not to be empty. And what happens is, is that when the user actually makes a request, you can see I added it through my pipes here. It is a pipe. So if you you're familiar with angular pipes, the validation on your request objects is a pipe. You can send us a global pipe. And then when you select it or when you put it as the body for your post requests, it automatically we'll start using it as a pipe. And you can see that, OK, passed in the user name of Zack. But I didn't pass in any rolls. So my API is actually going to automatically respond with a bad request for me. I don't have to build any of that logic just by using the data transfer object and the validation pipe. I get all of this automatically and it makes it a lot easier because I don't have to write a bunch of code for that. So let's go ahead and move the next thing so I can see. Now here's how I'd actually use it. This is our Finnish controller. We have our injected service. We're waiting for the or m to return our breeds. We have our HGP exceptions and we don't find stuff in that cart. And at the same time, we have our validation of our objects for the cat. It's getting past it. So that's actually a really nice completed controller we have there. Right. So what's next? Right. Field over permissions. How many people have ever tried to have like a password or some secure field on an object before Johannes Quix Johann's. Literally two people. There we go. OK, awesome. So, you know, it's really nice because, you know, you have all this wonderful data that you used to make sure things work correctly, but sometimes you're oversharing a little bit. Right. You send all that information all the way down to the user. Anyway, looks at your J sound response that comes back like, oh, look at all this wonderful stuff that I want to hack now because you decided to send it down to the user. And that's what happens sometimes. That's right. Maybe you send the cat tree down to the user. That's not necessarily a good thing, right? You don't want to send out where your secret hideout is because that's not that's not a good thing. So what could you do about that? Right. No, do not send that information to the user. Do not manually have to cut all that out. Every single response, because you're going to end up with some user or some developer that doesn't do the right thing. So let's make it a little bit automatic. Right. So now there's something called class transformer that you can use. That's actually you put this on your data transfer object that says, hey, you know what? I'm only going to expose the hide out. To users who are part of the Admon group. Right. So now what happens is as that that transfer object comes through your controller, it's going to go through and it's going to sanitize itself. Right. That's a lot better. Right. You're not sending that secure information down to the user. They're getting exactly what they expect. And exactly what you want them to see. So next thing I told you guys about fast, all these slides will be available. Next thing that's really fun to do, file uploads. I don't know how many folks have actually tried to do a file upload before, but it's usually a pain. You usually have to go get like five times and even then you screw something up and then you have to go back and refactor it. This is probably the. There. So this is the smallest bar of what I've ever said. It's literally two lines. Right. If you see this line here, we're going to use a file interceptor. And then we're gonna have a file upload file that then you can do whatever you want with it, right? You want to create a file stream. You want to, you know, go pass it through an antivirus, whatever it is you want to do. That's it. Right. You don't have to worry about the buffer. You don't have to worry about any of that. It's going to take care of all of that for you. That's one of the things that NASA does that makes it really nice to work with because Camille and the team went through and created stuff like this to make our lives really easy. And then as they begin to enhance things on the back end, you don't have to worry about keeping up to date with all the new hotness. They're going to take care of that for you. Something else that's a really common thing that I've seen and had to do is pass through A-P eyes. What do I mean by that? You have another API downstream that you have to collect information from and you want to pass that through to your user. Right. This is where that that response comes in. That's really handy because this is where I could actually pipe that information through. Right. So I'm going to say, you know what? I'm going to take the cats by breed. I'm going to go ahead and get that information. I have some catching here that that's in my my code so you can see how I do caching. And this example I have read is caching with an in-memory, a fallback. So the other way I have an in-memory cache with a red is fall-back. So if you get a cache, miss, on your in-memory dictionary, it will actually fall back to red. So that's going to be in the report that you could take a look at. So in this case, we're going to call this API. We're going to do a request and then we're going to grab the JSF from that. And then that's actually going to get sent down to the user. So that we could do that. Health checks. So health checks are kind of important, you want to know when your service is actually upright? Maybe you have GCP or maybe you're on a W.S.. You know, you need some kind of health check. Health checks are easy. You just write a very simple get request. There's some interesting stuff you could put on there, like, you know, in your uptime, your memory usage. But one of the things I found out is every time you do a health check. It's kind of not a real health check, right? Because just because you're your notary researcher is able to reply doesn't mean your database is available. It doesn't mean Radice is available. It doesn't mean that anything you actually need to do is there. And we'll show you real quick how to do that. Something else that I find really helpful to add to my health check is my version of my application. Right. So those people who do a continuous integration, continuous deployment. It's really helpful if you grab that Jason file that has your version number there and make that part, your health check helps, you know, what version you have it running in production without having to do a bunch of other craziness. But let's go ahead and see something else. So I talked about how if if your application has any dependencies, you know, like a file system. Right. How much space is left on your desk? How much space is left in memory? When's the last time you actually got a response from your database? Right. Just because it's two a.m. and no users are hitting your system doesn't mean your database is actually up. Right. So there's a really nice package that comes with maps that you can use. It's part of I think it's digital ocean. Put it together or no, it wasn't digital, so I forgot to put it together. No good at it. Yeah. So go ahead. He made this package called Terminus and Nesse wrapped it. And what that does is it allows you to actually implement other asynchronous processes that show you the true status of your application. Right. Is my memory OK? Is my database up? Is my desk. It does my desk have enough space? And you can add any thing to this health check to give you that true health check. And it'll actually there's a case here. If my desk gets more 90 percent full, it's going to actually start to throw errors. And yes, by API is still responding. Yes, my API is still up, but I may want to have New Relic or something when this disk starts to fail in this check. I weren't my one to wake somebody up and say, hey, you know what? We need to go clean up the disk a little bit before it has a problem. Right. So next thing, compression. So something that's really precious to me is data, right? You know, a lot of times my users are all over the world and they may not have the best connection in the world. If you're sending a ton of bytes over the wire, A, you're killing their data plan because not everybody has an unlimited data plan and B, you're slowing down your application for any race. And so data data's precious. Right. Depression is easy. It's one life. Right. You can't get any easier than that. If you're not adding compression to your application, you're probably doing it wrong. Right. And there is one line you can handle that authentication. I saw there was a talk earlier about JWT. I'm not going to get into the complexities of JWT. I am a huge fan of JWT, though, so we're going to show you how to create an off module. OK. So, again, another module, another ravioli of functionality. And in this case, I'm going to be using JWT. We have a super secret code here that we're going to have as part of our registry, the JWT. There is a deputy controller as well as a JWT strategy. I'm not going to get into the complexities of those. I am going to show them to you, though, and highlight a couple of things. So, again, with assignment, we have a wonderful data transfer object. We're going to take that. We're going to generate a JWT payload. We're going to validate that user. And then we're going to say, you know, what is this a valid user and what identity provider are they using? Because they use case that I'm demonstrating in the GitHub repo is something that I had to do at my day job, where we had a combination of simple off as well as a domain entity that we had to authenticate. So I can get out people. I show how you could use Firebase for, you know, your users. But at the same time, support a username and password that doesn't have anything backing it other than your own database. And that's really good when you're migrating systems or you're acquiring another company and you need to be able to support two types of OSS so that that is a valid use case that a lot of people have been running into lately. So what you you do with that, right? So this is going to be the JWT strategy. We're gonna be extracting legitimacy, token from the header and then we're able to pass it around. We have our validating user, which is going to go ahead and go called database. And then we this is how we would just log in. Right. So it's just another service that we're injecting into an off controller and handling our site in there. But once we have that, we can start to do some really cool things. Right. So I shot I showed you earlier how you could add a role that's going to sanitize your object. But what if you want to start protecting some of your roots? Right. So just by adding another annotations, say, you know, I want to use this Rose Garden and then I'm going to go ahead and authenticate that entire that entire controller. So everything in that controller is now has an off checks. Not only do you have to be signed in, but you have to pass that Rose Garden that's now available on your controller. So now we could do things like this. Right. So here's our Rose Garden. It's going to go ahead and grab the execution context of every single request that comes in. And it's going to reflect on that because, hey, you know what? I want to get the roles off that context. And I want to see what the names of those roles are. And then I'm going to validate whether or not the user has that role. Right. So we're going to check that. And then what Ballhaus has to do is, you know what? This entire response is only available for ADMET. Right. That's a really easy check. And all I had to do was add an invitation to it. And now I'm able to guard that entire request. So next thing, logging. It's going to be easy, right? You don't have to do a council log. You don't have to do add a bunch of logging libraries. There's a default one that comes with nest. It's really easy to do. I suggest hitting the easy button because I'm lazy and I don't like to do extra stuff. Right. So just use the one that comes with this. It's wonderful. It's easy. Graph you out, who does graph you up? Anybody? I feel like the four same hands, like there's a couple of people that do everything and they were just hanging out. OK, cool draft, you know. Really easy. So, again, import, right. All you have to do is import the draft fuel module that this provides the specify my type parts. I'm going to get. Five minute warning. That's really subtle. Great. So yeah, just after that, that as as the graph QOL module and then instead of having controllers that are provided I'm just saying resolvers. Right. So once I go and import those resolvers then I get the ability to add cat resolvers that cat guards and cat mutations, which is kind of weird because not to mutate cats, but once you have all those things, you're good to go and you can actually go ahead and inject those cat services into the cat. Resolvers and you could do things and then you get your cat to graft you all definitions and now you actually have the ability to use the built in courage. Visualizer here that lets you see what you get from RFQ up. So you have this API. You've built it. You've done all these wonderful things, how do you tested for scalability? One of the best things that I like to talk about is siege. Siege is a tool that I've used in the past to beat up my API. Right. What's he just going to do? It's going to execute any query that you want. I guess your application and it's going to beat it up. So in this case, I'm going to do two hundred and fifty concurrent users heading my application, tracking the health check, for example. And you can see for the cross the five seconds that was headed of twenty three hundred times a hundred percent of uptime. It took four point nine, six seconds. So I did what I expected it to do. I find this to be very useful when I'm doing regression tests. Right. I'm testing a new a new methodology of testing a new Aurum. I'm testing, you know, a new deployment or I'm testing a new container, whatever it is that I want to do. I use S.J to go ahead and go check to say, is my API so responding the same speed? Am I sending more bytes? So you can see here that same time, it also tells you how much data was transferred. So if you're adding compression, for example, how much does that really affect your application? Right. And we're see you're able to check that out documentation because everyone loves documentation, even though we don't ever do it. Swagger's is really easy to add to your application if you wanted to add swagger. So in this case, you just add a new document builder and it's going to go through and scaffold the swagger inserts itself and it's going to make it available on the slash docs of your out of your API. And then once you do that, you can begin to annotate with a extremely verbose annotations on exactly what that API does. It does do a little introspection as well. If you have any tapings on here, Sudworth put everything, but it does go through and actually take the annotations off your controllers. So next thing, sockets, I promise I'd get the sockets because everybody loves sockets. That's a good way to spend way too much data across the street. But this time it's sometimes necessary. So in this case, I did something really interesting. Adding sockets is really easy. You just get a simple annotation. You add you as WebSocket Gateway. You can specify what origins because I was being lazy on this one. I just want to let anybody connect to my socket. I don't care where you're coming from. And then you have your WebSocket server that you use. And then from there, you can begin to do whatever you want. And in this case, what I did is I showed a couple of things. One of the things I wanted to be able to do is keep track of how many concurrent users are connected to my socket because there's things that I like to do with that. And then I want to make sure that whenever someone else subscribes that we can to the events topic, we could go ahead and just send them copies of any events that come across. It was nice that you could you could do things with those around tracking how many users, which I just mentioned. And then from there, you can actually add that to your health check. Right. Now, I have a list of how many concurrent users around. You know, maybe that's something you want to bubble back to your health check. So, you know, how many people are actively connected to your sockets? And then you could also broadcast many messages. Right. So you have that list of WebSocket clients that are connected to your API. And you can get any kind of message to them with just a simple broadcast. Right. So that's a lot of stuff. Oh, that's him, I get Hubb Repo all that you can go check out. I am going to be doing some cleanup on it because I've been going through and doing some refactoring since last time. So I am updating that. I'm going to be updating it regularly as it as I go ahead, make clean up. So go ahead and follow that repo. There you are. I will be in the slide deck, which I will tweet out momentarily. And thank you all very much.