Coding

Learn Nest.js from Scratch by building an API

  • 00:00:01 hi and welcome to this video in this
  • 00:00:03 video we'll have a look at nest Jas a
  • 00:00:06 pretty fun note reyes framework which
  • 00:00:09 has been gaining some traction over the
  • 00:00:11 past months spin around for much longer
  • 00:00:13 than that though and it's fun to work
  • 00:00:16 with in my opinion in this video we'll
  • 00:00:18 have a look at it I'll introduce you to
  • 00:00:20 its core features will build an entire
  • 00:00:22 mini API with it and therefore by the
  • 00:00:25 end of the video you hopefully have a
  • 00:00:27 feeling for what it is what you can do
  • 00:00:29 with it and whether you might want to
  • 00:00:31 dive deeper into it so let's start
  • 00:00:38 so what is nest Jay s nest Reyes is a
  • 00:00:42 node.js framework so we use it on the
  • 00:00:45 backend on a server side it builds up on
  • 00:00:48 expressjs
  • 00:00:49 though it's flexible and theoretically
  • 00:00:51 you can also use other foundations so to
  • 00:00:54 say but in its base version and in the
  • 00:00:57 ocean you'll most commonly use it builds
  • 00:01:00 up on Express j/s so under the hood of
  • 00:01:02 nest JS were expressed J's which of
  • 00:01:06 course although is a node.js framework
  • 00:01:07 and therefore the question is what's the
  • 00:01:09 idea of that framework of a framework
  • 00:01:12 nest Reyes adds some cool ideas to the
  • 00:01:16 server side to know chess which we have
  • 00:01:19 had before in note reyes frameworks it
  • 00:01:23 embraces typescript so whilst you can
  • 00:01:25 actually also work with it without
  • 00:01:27 typescript it's definitely meant to be
  • 00:01:29 used with typescript and I know some
  • 00:01:32 people don't like typescript for some
  • 00:01:34 people this might be a reason to not use
  • 00:01:35 it and that's of course fine but if
  • 00:01:37 you're open to typescript or if you're a
  • 00:01:39 fan of typescript then you will
  • 00:01:42 definitely get a lot of benefits out of
  • 00:01:44 nest shares because it uses typescript
  • 00:01:46 because they're extra type safety and so
  • 00:01:48 on can save you some errors it also
  • 00:01:52 introduces the penalty injection and
  • 00:01:54 modularity and it's therefore a bit like
  • 00:01:57 angular for the back end indeed it's
  • 00:01:59 heavily inspired by angular the team or
  • 00:02:03 the founder of Nesta as the team behind
  • 00:02:05 SAS says that themselves and they
  • 00:02:07 borrowed many ideas from angular though
  • 00:02:10 it's really important to understand that
  • 00:02:12 of course nest raius solves a totally
  • 00:02:14 different problem it runs on the server
  • 00:02:17 side it's not an alternative to angular
  • 00:02:19 it's not yet an our front-end JavaScript
  • 00:02:22 framework which you would use to build
  • 00:02:24 user interfaces it's indeed a framework
  • 00:02:26 for the backend so it just borrowed some
  • 00:02:29 concepts from angular and where
  • 00:02:31 applicable transferred them to the back
  • 00:02:33 and so to say our concept of course are
  • 00:02:36 not taken over because they wouldn't
  • 00:02:38 make sense on the back end so typescript
  • 00:02:41 depends each action modularity some cool
  • 00:02:43 features uses a lot of decorators as you
  • 00:02:45 will see really nice to work with and
  • 00:02:47 you can use it to build MVC apps so
  • 00:02:50 where you also render your
  • 00:02:52 use on the server with templating
  • 00:02:54 engines like parkour handlebars you can
  • 00:02:56 use it to build a REST API and I would
  • 00:02:59 say that building REST API is maybe the
  • 00:03:01 the main thing of nest JS though that
  • 00:03:04 sounds like your things are hard to do
  • 00:03:06 they are not but building REST API is
  • 00:03:08 particularly easy let's put it that way
  • 00:03:10 but you can absolutely build MVC apps as
  • 00:03:13 a chess set and you can always use nest
  • 00:03:15 j/s to easily build graph QL ap is
  • 00:03:17 because nest is basically also provides
  • 00:03:21 a built-in wrapper around Apollo which
  • 00:03:23 is a popular graph QL server framework
  • 00:03:26 or library and that's easily integrate
  • 00:03:29 able into nest yes so you can build any
  • 00:03:31 server-side application with nest chess
  • 00:03:33 that's the key takeaway now because it
  • 00:03:36 uses typescript and forces modularity
  • 00:03:38 and so on
  • 00:03:39 it generally forces you to write clean
  • 00:03:42 code and forces a clear project
  • 00:03:44 structure and gives you some clear ideas
  • 00:03:47 on how you should structure your app
  • 00:03:49 where to put which code and therefore
  • 00:03:52 separating your concerns is particularly
  • 00:03:54 easy and hence nest J's can be used for
  • 00:03:58 applications of any size but especially
  • 00:04:01 more complex or larger applications
  • 00:04:03 might be a bit easier to build with nest
  • 00:04:06 chess because you are forced into
  • 00:04:07 certain patterns which make your code
  • 00:04:09 easier to manage easier to understand
  • 00:04:12 easier to reason about
  • 00:04:13 so that's nest chess in theory let's
  • 00:04:16 have a look at it in practice now nest
  • 00:04:19 Transcom is obviously a great starting
  • 00:04:21 point there you can dive into the
  • 00:04:23 documentation to learn all about nest
  • 00:04:25 chess and all about the many features it
  • 00:04:28 offers we're not going to cover them all
  • 00:04:30 in this video or on this channel but
  • 00:04:33 we'll cover the most important ones of
  • 00:04:34 course and for that let's start with
  • 00:04:37 creating an Astraeus project nest j/s
  • 00:04:40 gives you a CLI which you can install
  • 00:04:42 with this command and for this command
  • 00:04:44 and because it's a No Trace framework
  • 00:04:47 you of course need nodejs installed so
  • 00:04:50 make sure you have that installed from
  • 00:04:51 no chest or ik simply the latest version
  • 00:04:54 there so thereafter you can run this
  • 00:04:56 command and if you work with angular
  • 00:04:58 which by the way is absolutely not a
  • 00:05:00 prerequisite to work with nest chess
  • 00:05:02 then this might look familiar because an
  • 00:05:05 angular
  • 00:05:05 also have the add angular CLI which you
  • 00:05:08 installed similarly and there you would
  • 00:05:10 run ng new to create a new project here
  • 00:05:13 its nest new but again it borrowed some
  • 00:05:15 ideas it's not a copy it's not an
  • 00:05:18 alternative and it works with any
  • 00:05:20 front-end your either n during your
  • 00:05:21 views on the server anyways or if you're
  • 00:05:24 building an API you can connect your
  • 00:05:26 nest API with react apps with angular
  • 00:05:28 apps with view apps with when the let
  • 00:05:30 JavaScript apps whatever you have so it
  • 00:05:33 just borrowed ideas from angular so I
  • 00:05:35 already got no chance install so let me
  • 00:05:38 copy that command here and run it in my
  • 00:05:41 terminal here I can simply copy it in or
  • 00:05:44 paste it in here now if you're getting a
  • 00:05:45 permission error when running this you
  • 00:05:47 might want to add a sudo in front of
  • 00:05:49 this and thereafter enter your password
  • 00:05:51 if you prompted on Windows this should
  • 00:05:54 not be required and thereafter this will
  • 00:05:57 simply install this nest jsut lie once
  • 00:05:59 it is installed we can use it to create
  • 00:06:01 new nest chairs projects with it so here
  • 00:06:04 it finished installing now you can
  • 00:06:06 navigate into a folder where you want to
  • 00:06:08 create your new nest chess project and
  • 00:06:10 then simply run nest new and then any
  • 00:06:13 project name of your choice now limit
  • 00:06:15 nest chess in true but again the name is
  • 00:06:17 up to you and now this will create a new
  • 00:06:19 nest chess project in that folder in
  • 00:06:22 that nest chess in true folder which it
  • 00:06:24 will also create now if you've got
  • 00:06:26 multiple package managers installed as I
  • 00:06:28 have you're asked which one you want to
  • 00:06:30 use I'll stick to NPM um yarn would be
  • 00:06:33 an alternative if you have that
  • 00:06:35 installed you can of course use that as
  • 00:06:36 well and now it's setting up this folder
  • 00:06:38 installing all the dependencies
  • 00:06:40 this project has so all the NPM
  • 00:06:42 dependencies we have in there and once
  • 00:06:45 this is done it also shows us the
  • 00:06:47 commands we can run to start the nest as
  • 00:06:50 server and actually not the development
  • 00:06:52 server but the web server as we could
  • 00:06:55 serve it on the server we deploy to on
  • 00:06:58 the host we deploy it to will not use
  • 00:07:00 that instead I'll open it in an IDE and
  • 00:07:03 for that I will use Visual Studio code
  • 00:07:05 but of course here as well you can use
  • 00:07:07 any IDE you prefer and Dad is the
  • 00:07:11 project opened up in my IDE now I'm
  • 00:07:15 using the dart plus theme here and I
  • 00:07:17 also got the material I
  • 00:07:19 an extension installed which is totally
  • 00:07:22 optional but which leads to the I
  • 00:07:24 consider seeing here and then this is
  • 00:07:25 the project as the nest Eli creates it
  • 00:07:28 for you now on first look this can look
  • 00:07:30 overwhelming because we have so many
  • 00:07:32 files and and also some folders here but
  • 00:07:34 let me quickly walk you through them
  • 00:07:35 because code is simply a configuration
  • 00:07:37 folder for my ide has nothing to do with
  • 00:07:40 nest chess node modules holds all our
  • 00:07:42 dependencies all the installed
  • 00:07:44 dependencies so of course we're not
  • 00:07:46 going to change anything in here these
  • 00:07:47 dependencies are managed with the
  • 00:07:49 package.json file but that is something
  • 00:07:51 you should know because for this video I
  • 00:07:53 actually do expect that you have some
  • 00:07:55 basic understanding of how node and
  • 00:07:57 Express works and they offer you
  • 00:07:59 probably know what a package.json file
  • 00:08:01 does the source folder is more
  • 00:08:03 interesting in there we have the source
  • 00:08:04 files we are going to work on and they
  • 00:08:07 end with dot ts4 typescript and i'll
  • 00:08:09 walk through these files and what what's
  • 00:08:11 inside of these files in a second got
  • 00:08:13 the test folder where you could write
  • 00:08:15 your own and to end tests we're not
  • 00:08:16 going to do this here but of course
  • 00:08:18 Nastia supports this get ignore config
  • 00:08:21 file forget for a prettier which is for
  • 00:08:24 code formatting here nest Eli configures
  • 00:08:27 the nest is Eli and by default you can
  • 00:08:29 leave this as it is you could change the
  • 00:08:31 folder where your source code lives and
  • 00:08:33 if you want a to but I'll stick to SRC
  • 00:08:35 node Mon dad is actually a tool which is
  • 00:08:39 used under the hood by nest chest to
  • 00:08:41 launch the no it's server which we in
  • 00:08:43 the end have of course because it's an
  • 00:08:45 old framework and then automatically
  • 00:08:47 reload or relaunch that server whenever
  • 00:08:49 we change something in our code so node
  • 00:08:52 Mon makes developing easier because we
  • 00:08:54 don't have to manually restart our
  • 00:08:55 server and that's what this contact
  • 00:08:58 father also controls the package so
  • 00:09:01 Jason fall of course with all our
  • 00:09:02 dependencies and then a couple of
  • 00:09:04 scripts we can use to start various
  • 00:09:06 processes here and we'll have a look at
  • 00:09:08 this in a second and then some
  • 00:09:10 typescript configuration for linting and
  • 00:09:12 for the compilation of typescript unless
  • 00:09:15 you really know what you're doing you
  • 00:09:16 shouldn't change this because default
  • 00:09:19 here should actually be fine now in the
  • 00:09:21 source folder we have five files this
  • 00:09:24 file here the spec file that's just a
  • 00:09:26 testing file for unit tests I'll delete
  • 00:09:29 it here because we're not going to run
  • 00:09:31 unit tests here and then we're left with
  • 00:09:33 four
  • 00:09:33 files now the main TS file is actually
  • 00:09:37 the entry point of your nest reyes
  • 00:09:40 application so when you later execute a
  • 00:09:43 command to start your development server
  • 00:09:45 or to build your application so to say
  • 00:09:48 what will happen is that the code gets
  • 00:09:51 compiled to JavaScript because no J's
  • 00:09:53 can't run typescript so it gets compiled
  • 00:09:55 to JavaScript and of course then it also
  • 00:09:57 gets bundled it gets merged into a
  • 00:10:00 single or in a couple of JavaScript
  • 00:10:02 files as an output now the code in here
  • 00:10:04 in the main J's file will end up in the
  • 00:10:07 bundle as the code which actually runs
  • 00:10:09 first when you later start this entire
  • 00:10:12 app with your node server with the node
  • 00:10:14 command and in here we have the
  • 00:10:16 bootstrap function which gets called
  • 00:10:17 here and what we do here is we use the
  • 00:10:21 nest Factory which is a tool provided by
  • 00:10:23 nest Jas
  • 00:10:24 to create a new nest application you
  • 00:10:27 could say we're passing in the app
  • 00:10:28 module which is coming from another file
  • 00:10:31 and we'll have a look at this file in a
  • 00:10:32 second
  • 00:10:33 again if you work with angular this
  • 00:10:35 might look familiar to you and then here
  • 00:10:37 we start listening on port 3000 and if
  • 00:10:40 you work with Express trance which you
  • 00:10:42 all just show tour which is at least
  • 00:10:44 recommended then this might also look
  • 00:10:46 familiar to you in Express trace apps
  • 00:10:48 you also create a app by basically
  • 00:10:51 calling Express as a function of course
  • 00:10:55 here that wouldn't work because I'm not
  • 00:10:56 using Express here but in an Express app
  • 00:10:58 you would basically say Constable's
  • 00:11:01 Express like this and then on the
  • 00:11:04 Express app you could also call listen
  • 00:11:06 and because nest is under the hood wraps
  • 00:11:08 Express chess we indeed do you is
  • 00:11:11 expressed as here just with the extra
  • 00:11:13 nest chess layer in between but let's
  • 00:11:16 have a look at the app module then
  • 00:11:18 what's in there the app module in the
  • 00:11:20 app module here's foul that's an
  • 00:11:22 important thing in nest chest because as
  • 00:11:25 I said it embraces modularity and that
  • 00:11:28 simply means that nest Reyes doesn't by
  • 00:11:31 default take all the files you have in
  • 00:11:33 the air you have in your source folder
  • 00:11:35 and look into them to see what they do
  • 00:11:37 and compile them together instead you
  • 00:11:39 need to tell nest chess which features
  • 00:11:42 make up your application an important
  • 00:11:45 parts in an estrellas app are
  • 00:11:47 rollers and providers controllers are
  • 00:11:51 the meat of the app controllers control
  • 00:11:54 how you handle incoming requests they
  • 00:11:57 are responsible for accepting incoming
  • 00:11:59 requests then doing something and then
  • 00:12:02 to return a response that's the job of
  • 00:12:04 the controllers they handle requests and
  • 00:12:06 they send back responses providers on
  • 00:12:09 the other hand are extra services extra
  • 00:12:12 classes so to say which you can inject
  • 00:12:15 into controllers or also into other
  • 00:12:18 providers to provide certain
  • 00:12:20 functionalities for example you could
  • 00:12:22 have a service or a provider and the
  • 00:12:24 name is kind of exchangeable here so you
  • 00:12:28 could have a service which reaches out
  • 00:12:30 to a database to fetched item and then a
  • 00:12:32 controller can use that service to let
  • 00:12:35 the service get the data from the
  • 00:12:36 database so that the code in the
  • 00:12:38 controller is relatively lean and you
  • 00:12:40 don't have your database access code in
  • 00:12:42 the controller but instead you have that
  • 00:12:44 in the service and that's that
  • 00:12:46 modularity where you have a couple of
  • 00:12:48 different tools where each tool or each
  • 00:12:50 part of the app has its job and
  • 00:12:52 therefore each pot on its own stays
  • 00:12:54 relatively lean and focused and the
  • 00:12:56 module here the app module and you can
  • 00:12:59 indeed have multiple modules and bigger
  • 00:13:01 apps simply bundles up a couple of
  • 00:13:03 controllers a couple of providers which
  • 00:13:05 these controllers can use or which other
  • 00:13:07 providers can use as well and you can
  • 00:13:10 also if you had multiple modules import
  • 00:13:12 a module into a novel and that's how you
  • 00:13:14 link your entire app together
  • 00:13:16 youtell nests chess ok this module has
  • 00:13:19 these three controllers these five
  • 00:13:21 services and also depends on or wants to
  • 00:13:24 use some our module and that our module
  • 00:13:26 might also have 10 controllers and 5
  • 00:13:29 providers or anything like that and this
  • 00:13:31 is how this all is connected and modules
  • 00:13:34 are typically split by features in your
  • 00:13:37 app so if you're building an online shop
  • 00:13:39 you might have a module for products
  • 00:13:41 maybe one for the shopping card one for
  • 00:13:44 a user authentication something like
  • 00:13:46 that one important thing to note of
  • 00:13:47 course is that the module here is just
  • 00:13:50 an empty class all the magic happens
  • 00:13:52 because this at module thing is added to
  • 00:13:55 it
  • 00:13:56 that's a decorator and that's a feature
  • 00:13:58 provided by typescript module is coming
  • 00:14:01 from
  • 00:14:01 is the at thing here is important to
  • 00:14:04 attach it as a decorator and decorators
  • 00:14:06 can be attached to classes to methods
  • 00:14:09 and classes to properties to arguments
  • 00:14:12 and methods they can be attached to a
  • 00:14:14 broad variety of things and of course it
  • 00:14:16 depends on the decorator you're using
  • 00:14:17 where you can attach it module is a
  • 00:14:21 decorator that should be attached to a
  • 00:14:22 class and then you pass in an object to
  • 00:14:25 that decorator which you call like a
  • 00:14:26 function to configure that decorator
  • 00:14:28 basically and behind the scenes this
  • 00:14:31 will basically add some metadata or
  • 00:14:33 transform this class this this object
  • 00:14:36 that's created based on the class
  • 00:14:38 transformed it into something else into
  • 00:14:40 a more complex object that's some magic
  • 00:14:42 happening behind the scenes done by
  • 00:14:44 typescript and by nest Jas and this is
  • 00:14:47 simply a very convenient way of setting
  • 00:14:48 this app in the app controller if we
  • 00:14:51 have a look at this we also have a class
  • 00:14:53 they are we actually do have some
  • 00:14:55 content in the class but we're also
  • 00:14:57 using decorators here we have the add
  • 00:14:59 controller decorator which is coming
  • 00:15:01 from nest chess and the add get
  • 00:15:02 decorator coming from SJS and here we
  • 00:15:05 also see a decorator that's not added to
  • 00:15:07 a class but to a method instead now as I
  • 00:15:10 said controllers are important for
  • 00:15:12 handling incoming requests and sending
  • 00:15:14 back responses now if you have a
  • 00:15:17 controller like this with just add
  • 00:15:19 controller where you have no argument
  • 00:15:22 here in add controller then this
  • 00:15:24 controller will simply handle incoming
  • 00:15:26 requests to your domain comm slash
  • 00:15:31 nothing so to your route route so this
  • 00:15:34 controller by default will have a look
  • 00:15:37 at requests that reach your domain slash
  • 00:15:40 nothing if you had a request that
  • 00:15:42 reaches /pha or slash users it would
  • 00:15:45 also reach that controller because it
  • 00:15:47 still of course well starts here at this
  • 00:15:51 segment but then you would need a method
  • 00:15:53 in here which explicitly targets slash
  • 00:15:55 users because that's the our thing this
  • 00:15:58 controller has no filter regarding the
  • 00:16:01 path of the incoming request it wants to
  • 00:16:02 handle we could pass a filter here we
  • 00:16:05 could for example pass products in here
  • 00:16:07 and now only requests that start with
  • 00:16:10 your domain slash products would reach
  • 00:16:12 this controller and if you
  • 00:16:15 at products one it would all to reach
  • 00:16:17 this controller if you had users however
  • 00:16:19 it would not reach this controller
  • 00:16:21 because this clearly does not start with
  • 00:16:23 products so that's how this works but
  • 00:16:25 let's get rid of that to start with
  • 00:16:27 slash nothing and now this method here
  • 00:16:30 that's the second thing this method now
  • 00:16:32 can be named whatever you want but with
  • 00:16:34 this decorator this method will get
  • 00:16:36 executed automatically whenever a get
  • 00:16:39 request reaches just slash nothing with
  • 00:16:42 slash users this would not get executed
  • 00:16:45 because this here this controller thing
  • 00:16:48 doesn't filter the path at all as I just
  • 00:16:51 explained this year however does mean
  • 00:16:54 only nothing only an empty path triggers
  • 00:16:57 this method so really only requests to
  • 00:16:59 slash nothing if you would want to
  • 00:17:01 handle requests to slash users you would
  • 00:17:03 have to pass users here and if you had
  • 00:17:06 here products and here users then only
  • 00:17:11 products users would trigger this method
  • 00:17:14 and just products would not trigger it
  • 00:17:17 just users would also not trigger it
  • 00:17:19 because we are only handling requests
  • 00:17:21 that start with your domain.com slash
  • 00:17:23 user app products and then here we only
  • 00:17:26 have one method that looks for another
  • 00:17:28 path segment so to say what should be
  • 00:17:30 users
  • 00:17:31 so after this path segment the user
  • 00:17:32 segment therefore only products users
  • 00:17:37 would be handled so I hope that's clear
  • 00:17:40 at least a bit well of course see this
  • 00:17:42 in practice once we add our own routes
  • 00:17:45 or an additional path which you want to
  • 00:17:47 handle the idea here is that you route
  • 00:17:50 requests with decorators if you work
  • 00:17:52 with expressed as you are used to
  • 00:17:55 setting up the Express router or using
  • 00:17:57 middleware with path filters to handle
  • 00:17:59 incoming requests here you filter
  • 00:18:02 requests with at controller and then
  • 00:18:04 with at gaps and of course by the way
  • 00:18:06 you also have at post at patch at port
  • 00:18:09 at delete to also handle such requests
  • 00:18:12 with such words so a lot of talking
  • 00:18:16 let's have a look at the last building
  • 00:18:17 block we see here and that's the service
  • 00:18:19 this constructor thing here that's
  • 00:18:21 actually dependency injection in action
  • 00:18:24 and if you work with angular again this
  • 00:18:26 looks familiar
  • 00:18:28 what we're doing here is we're adding a
  • 00:18:30 constructor which every JavaScript in
  • 00:18:32 typescript class can have and we're
  • 00:18:34 specifying one argument which we expect
  • 00:18:36 to get which should be of type app
  • 00:18:37 service this is how you assign a type
  • 00:18:40 and typescript by the way : after the
  • 00:18:42 argument name and then the type name
  • 00:18:44 over here for example for this method a
  • 00:18:46 colon after the method and then this is
  • 00:18:48 the return type but here we're assigning
  • 00:18:51 a type of app service to this argument
  • 00:18:54 app service and now of course whoever is
  • 00:18:57 creating a new instance of this class
  • 00:18:58 needs to pass in this service
  • 00:19:00 now who is creating a new instance of
  • 00:19:02 this class well we are not nest chest
  • 00:19:05 Estes Nest Reyes will actually create an
  • 00:19:07 instance of this controller and
  • 00:19:09 therefore its nest Jas duty to pass us
  • 00:19:12 such a service object and that is
  • 00:19:15 possible because we added app service
  • 00:19:18 here as a provider with dead we're
  • 00:19:20 telling nest Reyes hey this class here
  • 00:19:24 app service is a class which I will
  • 00:19:27 probably use in some of my other classes
  • 00:19:29 I want to inject it there so please be
  • 00:19:32 aware of it here is the class name here
  • 00:19:36 is where you can find it be prepared to
  • 00:19:38 create a new instance of this class so
  • 00:19:40 that you can pass it to me when I
  • 00:19:42 request it in a constructor and that's
  • 00:19:44 exactly what's happening here
  • 00:19:45 we need a new app service object here
  • 00:19:48 when the controller gets created and s
  • 00:19:50 Ches creates such a App Store's object
  • 00:19:52 and gives it to us because we told it
  • 00:19:54 how to do that by adding app service to
  • 00:19:57 the providers here now side note if you
  • 00:19:59 are familiar with angular there whatever
  • 00:20:01 service you provide by default is
  • 00:20:04 available application wide in SaaS
  • 00:20:07 services are really scoped to the module
  • 00:20:09 you provide them in so if you had
  • 00:20:11 multiple modules and you provide a
  • 00:20:13 service in this module then in an error
  • 00:20:15 module you could not inject this service
  • 00:20:18 automatically you would have to provide
  • 00:20:20 it there as well but that's just a
  • 00:20:21 little side note
  • 00:20:22 so that's dependency injection in action
  • 00:20:25 this type definition year or declaration
  • 00:20:28 is very important because with just the
  • 00:20:30 argument name nest Reyes would have no
  • 00:20:33 idea which type of object it should give
  • 00:20:36 us right because the argument name well
  • 00:20:38 to us humans it's clear that we want the
  • 00:20:40 app service but you couldn't
  • 00:20:41 named as something and that would also
  • 00:20:43 be allowed and then there would be
  • 00:20:45 absolutely no chance of inferring what
  • 00:20:48 you mean so by adding the type here
  • 00:20:50 however Ness jeaious is able to find out
  • 00:20:53 which type of object it should give us
  • 00:20:56 then it looks in the providers list and
  • 00:20:58 if it finds to type there it can create
  • 00:21:00 that now and the app service itself is
  • 00:21:02 just a class with the ad injectable
  • 00:21:04 decorator which makes sure that this can
  • 00:21:06 be injected it's also imported from Ness
  • 00:21:08 Chasse
  • 00:21:09 and then here we have one method in the
  • 00:21:11 service and as I mentioned here in
  • 00:21:13 services you could be reaching out to a
  • 00:21:15 database you could be doing all kinds of
  • 00:21:18 stuff here you basically want to do your
  • 00:21:20 heavy lifting you want to have the logic
  • 00:21:22 so that your controllers can stay
  • 00:21:24 relatively lean and can focus on
  • 00:21:26 handling the incoming requests and then
  • 00:21:28 just putting together a response so
  • 00:21:30 these are the basics now I talked for
  • 00:21:36 minutes now and we still haven't written
  • 00:21:38 any code
  • 00:21:39 I hope the basics are clear though so
  • 00:21:41 for now let's start the development
  • 00:21:43 server by running this command here
  • 00:21:45 start death so I'll open up my terminal
  • 00:21:48 navigate it here into the project folder
  • 00:21:50 and then I run npm run start colon death
  • 00:21:53 and this is now starts a development
  • 00:21:54 server which watches our files and
  • 00:21:56 automatically recompiles and restarts
  • 00:21:58 the server whenever we change something
  • 00:22:00 now let's have a look at this remember
  • 00:22:04 that it was port 3000 where you can see
  • 00:22:06 this and if you visit this you should
  • 00:22:08 see hello world here because that is
  • 00:22:10 what the app controller in the end
  • 00:22:12 returns here it returns the result of
  • 00:22:14 GATT hello in the service and the
  • 00:22:16 service returns hello world that's
  • 00:22:18 another important thing by the way
  • 00:22:20 so what we're turning here is a string
  • 00:22:22 not a response object again if you work
  • 00:22:25 with expressjs you are used to getting a
  • 00:22:28 request and a response object here in
  • 00:22:30 the methods were in the functions that
  • 00:22:33 handle the incoming requests and then
  • 00:22:35 you would do something like response
  • 00:22:36 whoops
  • 00:22:37 response send or response jason-2 sent
  • 00:22:42 back responses right now here Ness
  • 00:22:44 Chasse does that work for you you just
  • 00:22:46 return the body of the response though
  • 00:22:50 there still are ways of setting extra
  • 00:22:52 headers if you need that but here by
  • 00:22:54 default you just were
  • 00:22:55 turn the body and then SJS has a look at
  • 00:22:58 the type of data you're returning and
  • 00:23:00 based on the data it sets some default
  • 00:23:03 headers for the response so here we're
  • 00:23:06 returning some text in the end and when
  • 00:23:08 you're returning text let's see which
  • 00:23:10 header nest is infers by opening up the
  • 00:23:14 developer tools going to the network tab
  • 00:23:17 there and now let's reload this page and
  • 00:23:19 inspect this request which is the
  • 00:23:21 request responsible for this page there
  • 00:23:24 at the response headers we see that the
  • 00:23:26 content type is text HTML so if you're
  • 00:23:29 returning some plain text nest Reyes
  • 00:23:31 automatically infer that this is text
  • 00:23:34 and that therefore probably should be
  • 00:23:36 HTML and hence it appends or it sets
  • 00:23:39 this content type header on the other
  • 00:23:41 hand if you would return a JavaScript
  • 00:23:43 object here like name max something like
  • 00:23:48 this and now I'm getting an error here
  • 00:23:50 because I'm actually stating that I want
  • 00:23:52 to return a string so the solution is to
  • 00:23:55 either set this to any which is quite
  • 00:23:57 forgiving or you can define an object
  • 00:23:59 type here by using curly braces here and
  • 00:24:02 then define that you'll have whoops
  • 00:24:05 without quotes here that you will have a
  • 00:24:07 name property in that object which will
  • 00:24:11 then be of type string then you are
  • 00:24:12 telling typescript that you'll be
  • 00:24:14 returning an object with a name property
  • 00:24:16 which is of type string and now we're
  • 00:24:18 alright and if you do that so if you
  • 00:24:20 return such an object here and you
  • 00:24:21 reload then you see it's getting printed
  • 00:24:25 here but if we inspect the response the
  • 00:24:27 content type is now automatically set to
  • 00:24:29 application Jason Sohn SJS automatically
  • 00:24:32 transforms this to Jason and sets the
  • 00:24:34 appropriate header so it's really smart
  • 00:24:36 regarding that and that's of course a
  • 00:24:38 huge help because typically that's
  • 00:24:40 exactly what you want if you still would
  • 00:24:42 want to set your own headers you can do
  • 00:24:44 that though you can import header here
  • 00:24:49 from nest a is common like this and then
  • 00:24:52 add an our decorator to this method he
  • 00:24:54 had a decorator and there you can set
  • 00:24:56 the name of the header like content type
  • 00:24:59 and then the value like text HTML and
  • 00:25:03 now this header would be a pendant or
  • 00:25:05 would be added to the response and it
  • 00:25:08 overrides to default
  • 00:25:09 headers nest chairs would otherwise set
  • 00:25:11 or it allows you to add brand new
  • 00:25:13 headers to the response and now we're
  • 00:25:15 saving this and we reload this let's
  • 00:25:18 have a look we see now this is the
  • 00:25:20 content type set here so this is how you
  • 00:25:22 can work with nest chairs how you can
  • 00:25:23 return data and with decorators you
  • 00:25:26 really control a lot so that's something
  • 00:25:28 you can get used to in SJS you'll use
  • 00:25:30 tons of decorators so that you don't
  • 00:25:32 have to write everything explicitly in
  • 00:25:34 code but that you instead simply you can
  • 00:25:37 set some configurations in different
  • 00:25:39 places and nest chairs will then
  • 00:25:40 automatically do the right thing now
  • 00:25:43 still it's a boring example let's build
  • 00:25:46 a little dummy API here let's say an API
  • 00:25:49 where you can add new products can then
  • 00:25:53 delete or update these products and of
  • 00:25:56 course also get a list of all products
  • 00:25:58 or a single product so a very simple API
  • 00:26:01 we could be using as part of a shop
  • 00:26:03 let's build this now for that to also
  • 00:26:06 work with multiple modules let's
  • 00:26:08 actually create a new subfolder here
  • 00:26:10 which is not required but just to keep
  • 00:26:12 our code organized and I'll name this
  • 00:26:15 product and in there let's add a product
  • 00:26:18 dot controller TS file that's the naming
  • 00:26:21 convention for these files you would
  • 00:26:22 describe the feature then the type of
  • 00:26:24 file or what you want to have in there
  • 00:26:26 and then of course dot TS as the
  • 00:26:28 extension now in there we export a class
  • 00:26:31 products controller that's the naming
  • 00:26:33 convention for the class you also have
  • 00:26:35 to the type of feature in there so it's
  • 00:26:41 for the products feature but then it's
  • 00:26:42 also a controller so you describe both
  • 00:26:44 in a class name and by the way we of
  • 00:26:46 course use a different import and export
  • 00:26:48 syntax then you normally do a note or
  • 00:26:51 Express Apps we're using DES modules
  • 00:26:53 imports index instead because typescript
  • 00:26:56 supports that so that's why we have that
  • 00:26:58 so if that we have that products
  • 00:27:01 controller now you learned that the
  • 00:27:03 thing that actually turns this into a
  • 00:27:04 controller is the add controller
  • 00:27:06 decorator so let's add at controller
  • 00:27:09 here and add controller needs to be
  • 00:27:12 added or imported from nest J's common
  • 00:27:14 and my IDE added is automatically in
  • 00:27:16 case yours doesn't you have to add this
  • 00:27:19 import manually so now of course this
  • 00:27:22 should be a controller that
  • 00:27:23 kicks in for requests that reach our
  • 00:27:25 page comm / products so let's add
  • 00:27:29 products here as argument – controller
  • 00:27:31 so that we filter for requests that
  • 00:27:34 start with / products and in here let's
  • 00:27:38 start with a method that allows us to
  • 00:27:40 add a new product now for the moment
  • 00:27:42 I'll by the way just manage my products
  • 00:27:44 here in memory but I'll just show you
  • 00:27:47 how to write them to the database no
  • 00:27:49 worries so here let's start by adding a
  • 00:27:52 new method maybe add product name is up
  • 00:27:55 to you and this should handle incoming
  • 00:27:57 post requests now because since we'll
  • 00:28:00 build a basic API here I want to follow
  • 00:28:02 the common rules where when you add a
  • 00:28:06 new item a new resource on the server
  • 00:28:08 you send a post request so here I want
  • 00:28:10 to handle a post request by the way you
  • 00:28:12 might want to check out my complete
  • 00:28:14 series where we build a REST API with
  • 00:28:17 node expressed from scratch there I dive
  • 00:28:19 way more into these API and rest basics
  • 00:28:22 and of course we all have a look at node
  • 00:28:24 and Express there in case that's
  • 00:28:26 something you're interested in – so here
  • 00:28:29 we need to import post and with that we
  • 00:28:31 can add at post here we could add a pop
  • 00:28:35 filter here if you wanted you but I'm
  • 00:28:37 actually fine with managing incoming
  • 00:28:39 requests to just products and add
  • 00:28:42 product now needs a function body of
  • 00:28:45 course but also a return type and here I
  • 00:28:48 want to return an object and for now
  • 00:28:51 I'll set this to any we can fine-tune
  • 00:28:53 this later once we have a clearer idea
  • 00:28:55 of what we want to return so here we now
  • 00:29:00 need to store the product as I said for
  • 00:29:03 the moment not in a database but simply
  • 00:29:05 in an array which we manage here in our
  • 00:29:07 nest chase application and which
  • 00:29:09 therefore of course is lost whenever we
  • 00:29:11 restart business chase application but
  • 00:29:14 for the moment this will do now we could
  • 00:29:16 manage everything in that controller
  • 00:29:18 class and it would work but that's
  • 00:29:20 exactly not the idea of nest Chasse
  • 00:29:22 instead you should split your code you
  • 00:29:25 should distribute your code and should
  • 00:29:27 have leaned focused parts in your app so
  • 00:29:32 let's add a products service a product
  • 00:29:35 service TS file
  • 00:29:37 and in their exporter class products
  • 00:29:39 service this is now a way better class
  • 00:29:42 for managing this now to make this
  • 00:29:45 injectable here we need to add at
  • 00:29:47 injectable and that's a decorator
  • 00:29:49 imported from nest a as common as well
  • 00:29:52 and now here we can have a list of
  • 00:29:54 products so we would probably have
  • 00:29:58 products here and yeah the type here
  • 00:30:03 should be an array but I wanna be more
  • 00:30:08 specific an array of what so let's
  • 00:30:10 define how a product should look like
  • 00:30:12 and here a good practice is to define a
  • 00:30:14 model for this so let's define a product
  • 00:30:17 model maybe in a product on Model T as
  • 00:30:19 file to be clear what's in that file and
  • 00:30:22 this is now a file which will be holding
  • 00:30:25 a plain vanilla typescript class so
  • 00:30:29 without any special decorators and I'll
  • 00:30:31 name this product like this you could
  • 00:30:36 name it product model but I want use
  • 00:30:38 this to create new products basically
  • 00:30:40 calling new product and I think it looks
  • 00:30:42 nicer than if you have just product and
  • 00:30:44 not product model because here we will
  • 00:30:47 be the ones creating that class or the
  • 00:30:49 instances based on the class now what do
  • 00:30:52 I want to have in that a constructor so
  • 00:30:55 that we can indeed call new product and
  • 00:30:58 now here which properties do we need
  • 00:31:01 well let's add a couple and then let's
  • 00:31:04 accept them in a constructor product
  • 00:31:07 will probably have an ID which could be
  • 00:31:11 a string it will have a title let's say
  • 00:31:16 maybe also a description which can be a
  • 00:31:19 string a price which could be a number
  • 00:31:21 and yeah doesn't look too bad you could
  • 00:31:25 of course add more like an image URL or
  • 00:31:27 anything like that but let's go with
  • 00:31:28 this basic set now let's accept all of
  • 00:31:31 that as arguments you can name these
  • 00:31:33 arguments like the properties here or
  • 00:31:35 name them differently that's up to you
  • 00:31:36 so we expect a string here a title an ID
  • 00:31:40 a title description and also a price and
  • 00:31:46 then in the constructor body here we can
  • 00:31:49 simply call
  • 00:31:50 this ID equals ID this title equals
  • 00:31:54 title this description equals desc this
  • 00:31:59 price equals price so that we store all
  • 00:32:01 the data we're getting in the
  • 00:32:02 constructor when people create new
  • 00:32:04 products in the properties here now this
  • 00:32:07 is such a common pattern that types
  • 00:32:09 could has a shortcut for this so that we
  • 00:32:10 don't have to write all this boilerplate
  • 00:32:13 code you can get rid of your properties
  • 00:32:15 up there and of your constructor body
  • 00:32:17 and instead you can simply add an
  • 00:32:20 accessor in front of your arguments like
  • 00:32:23 public or private defining whether this
  • 00:32:25 should be available only inside of this
  • 00:32:27 class or also accessible from outside I
  • 00:32:29 want to have it accessible from outside
  • 00:32:31 so I'll add public and by adding the
  • 00:32:34 successor in front of all these
  • 00:32:36 arguments and now I'll name this here
  • 00:32:39 description by adding this these are
  • 00:32:42 automatically stored in equally named
  • 00:32:45 properties of this class so types could
  • 00:32:47 automatically adds properties to the
  • 00:32:49 class with it which have the same name
  • 00:32:50 and stores the incoming values in these
  • 00:32:52 properties so that's a convenient
  • 00:32:54 shortcut typescript offers suppose that
  • 00:32:57 we define how a product should look like
  • 00:32:59 back in a product service I now want to
  • 00:33:01 manage a list of products and dad should
  • 00:33:03 now use our own product type so let's
  • 00:33:06 add an import here where we import
  • 00:33:08 product from dot slash product model and
  • 00:33:12 then here the type after the colon is
  • 00:33:15 product but then an array of products
  • 00:33:17 which you defined in typescript by
  • 00:33:19 adding square brackets there after so
  • 00:33:21 now we're saying that we'll have an
  • 00:33:22 array of products in here and initially
  • 00:33:24 that's an empty array and if you would
  • 00:33:26 now try to add a string to that array
  • 00:33:29 you would get an error by typescript
  • 00:33:30 because it only accepts products now
  • 00:33:34 here in the product service we can add
  • 00:33:37 an insert product method or whatever you
  • 00:33:40 want to call it name is totally up to
  • 00:33:42 you and that ends our product method
  • 00:33:44 should do just that it should simply
  • 00:33:46 insert a new product here into this
  • 00:33:48 array now you can either accept the
  • 00:33:51 finished product here as an input or the
  • 00:33:54 individual inputs so here you could
  • 00:33:56 expect let's say a title description and
  • 00:34:00 a price not the ID because the ID can be
  • 00:34:03 generated
  • 00:34:04 we pass here and then here you could
  • 00:34:07 create a new product by calling new
  • 00:34:11 product so using our product class now
  • 00:34:14 and there for the ID we now will need a
  • 00:34:17 ID and we have no real way of creating a
  • 00:34:20 unique ID
  • 00:34:21 so what I'll simply uses I'll use new
  • 00:34:23 date here Q string it's not a perfect ID
  • 00:34:27 because it's not not unique you could
  • 00:34:30 create two products at the exact same
  • 00:34:32 time stamp but here in this app this
  • 00:34:34 will not happen therefore as a dummy ID
  • 00:34:36 it will do if you needed a real ID there
  • 00:34:40 are packages which you can install note
  • 00:34:42 Express packages because you can by the
  • 00:34:44 way use any Express package in SaaS apps
  • 00:34:46 you could install packages that generate
  • 00:34:49 real unique IDs so for us this will do
  • 00:34:51 though let's now also forward the title
  • 00:34:53 the description and the price to the
  • 00:34:56 product constructor and price should be
  • 00:34:59 a number here of course so that the
  • 00:35:01 types match and with that we're
  • 00:35:03 generating a new product with that new
  • 00:35:05 product generated we can reach out to
  • 00:35:08 products and simply push our new product
  • 00:35:12 into that array like this so now with
  • 00:35:18 that we have a method to insert a
  • 00:35:20 product back to the controller now here
  • 00:35:23 I now want to inject that service so
  • 00:35:25 that we can use it to inject that we add
  • 00:35:28 a constructor here to the product
  • 00:35:30 controller now we won't create a
  • 00:35:32 products controller nest chess will do
  • 00:35:34 that for us and then the constructor we
  • 00:35:36 tell nest chess what we need here and
  • 00:35:38 here I want you have an instance of my
  • 00:35:43 products service the name is totally up
  • 00:35:45 to you but important it has to be of
  • 00:35:47 type products service and you need to
  • 00:35:50 import product service here so that you
  • 00:35:53 can use this class as a type otherwise
  • 00:35:56 typescript doesn't know where this is
  • 00:35:57 coming from and I'll again use the
  • 00:35:59 shortcut where I add private in front of
  • 00:36:01 this to make sure that this argument is
  • 00:36:03 automatically stored in an equally named
  • 00:36:05 property you can also add read-only
  • 00:36:08 which is another types good feature this
  • 00:36:10 makes clear that you will never replace
  • 00:36:13 product service with a new value which
  • 00:36:15 you of course don't plan to do we will
  • 00:36:17 stick to this
  • 00:36:18 product/service instance we are provided
  • 00:36:20 with so now an ad product we can use
  • 00:36:23 this product service and then call ins
  • 00:36:27 our product here now the question is
  • 00:36:30 where do I get my data from so the title
  • 00:36:32 the description and the price and the
  • 00:36:35 answer is probably from the incoming
  • 00:36:37 request that incoming requests should
  • 00:36:40 indeed have some data attached to it it
  • 00:36:43 will have a request body now again if
  • 00:36:46 you were using Express chase you would
  • 00:36:48 be getting a request and a response
  • 00:36:49 object here and then you could call
  • 00:36:52 request body and extract data from there
  • 00:36:56 this is not how it works in SJS whilst
  • 00:37:00 there actually is a way to get these
  • 00:37:02 requests and response objects that's not
  • 00:37:04 the way you should use instead you again
  • 00:37:07 use decorators there is a body decorator
  • 00:37:10 which you can import from nest as common
  • 00:37:13 and you used it here in your argument
  • 00:37:15 list there you can add add body and
  • 00:37:18 thereafter an argument like let's say
  • 00:37:21 prot title which will be a string and
  • 00:37:25 embody you now can specify the field in
  • 00:37:30 the incoming request body that should
  • 00:37:32 hold the value which nests chest will
  • 00:37:34 then extract for you from that body and
  • 00:37:36 give you in this argument and there
  • 00:37:38 let's say we're expecting a title field
  • 00:37:41 in the incoming request well then we
  • 00:37:43 would set up this decorate like this and
  • 00:37:46 now nest J's will look at the incoming
  • 00:37:47 request parse the incoming request body
  • 00:37:50 so converted from chase into a
  • 00:37:52 JavaScript object and then look in that
  • 00:37:54 object for a title property and take the
  • 00:37:56 value of that property and give it to us
  • 00:37:58 in this product I'll argument we can of
  • 00:38:01 course repeat this to also get our
  • 00:38:05 description let's say we expect this on
  • 00:38:07 a description here and then we have the
  • 00:38:09 prot desk here which is also a string
  • 00:38:11 and we do the same for the price and
  • 00:38:14 therefore here we would have prot price
  • 00:38:17 which is let's say a number now one
  • 00:38:21 important note you could also say at
  • 00:38:24 body and get the complete body here and
  • 00:38:27 then define how this object looks like
  • 00:38:30 so that this has
  • 00:38:31 title key which is a string a
  • 00:38:33 description key which is a string and so
  • 00:38:34 on you could do this it's totally up to
  • 00:38:36 you which approach you prefer I think
  • 00:38:38 this approach of having three different
  • 00:38:39 arguments is really clear and
  • 00:38:41 straightforward but you could use
  • 00:38:43 another approach if you wanted to so now
  • 00:38:45 we got all the data and hence we can
  • 00:38:47 therefore forward prod title now broad
  • 00:38:50 description and broad price and
  • 00:38:53 therefore we're now calling inter
  • 00:38:55 product in a correct way leaves us with
  • 00:38:58 one question what do we want to return
  • 00:39:00 here you can of course return any
  • 00:39:02 response body you want I want to return
  • 00:39:05 the idea of the product which was
  • 00:39:06 generated and of course that's a dummy
  • 00:39:09 ID but nonetheless so here I'll have my
  • 00:39:12 prod ID in the service which is the
  • 00:39:14 state and which I then use here and I'm
  • 00:39:16 just storing this in a constant because
  • 00:39:18 I want to reuse this and also return
  • 00:39:20 this year so here I return fraud ID now
  • 00:39:24 by the way we could now also add a colon
  • 00:39:26 after the argument list to be clear
  • 00:39:28 about what we're returning here which
  • 00:39:30 type of data and that would be a string
  • 00:39:31 but you actually don't need to do that
  • 00:39:33 because typescript has a feature called
  • 00:39:35 type inference which means it's actually
  • 00:39:37 able to infer that you're returning a
  • 00:39:39 string because you have a return step
  • 00:39:41 and here and there well you return a
  • 00:39:43 string so inner product returns a string
  • 00:39:45 returns the ID in the controller we can
  • 00:39:48 therefore return the result of insert
  • 00:39:50 product and return this ID back to the
  • 00:39:54 user however that would be a string and
  • 00:39:56 the effort would be treated as HTML
  • 00:39:58 typically in an API we want to return
  • 00:40:00 JSON data so of course we could set our
  • 00:40:02 own header but then a simple string
  • 00:40:06 would still not be valid jason so
  • 00:40:08 instead here I will return a new object
  • 00:40:10 where I have an ID key and that's then
  • 00:40:13 my generated ID which has store in this
  • 00:40:18 constant which I then set as a value
  • 00:40:20 here and now we're returning this and
  • 00:40:22 now we can always be more specific about
  • 00:40:24 what we return here or not the find
  • 00:40:27 return type at all because again
  • 00:40:29 typescript is able to infer this now
  • 00:40:32 since we're returning an object here and
  • 00:40:34 the same would be true for lists by the
  • 00:40:35 way nest Ches is able to infer that we
  • 00:40:38 want to set the jason the application
  • 00:40:40 chase and content type header now we
  • 00:40:43 have a post route
  • 00:40:45 one crucial thing is missing though do
  • 00:40:48 you know which one a module because as I
  • 00:40:51 said you need to tie your features
  • 00:40:53 together with modules so let's create a
  • 00:40:55 product start module dot ES file and in
  • 00:40:58 there export a class products module
  • 00:41:01 what's module written like this which
  • 00:41:04 needs to get the add module decorator
  • 00:41:07 which you import from nest as common you
  • 00:41:10 pass an object to this decorator and
  • 00:41:12 then you can setup imports so our
  • 00:41:14 modules you might be depending on which
  • 00:41:16 we don't have here but you certainly
  • 00:41:19 will set controllers there we have our
  • 00:41:22 products controller which you need to
  • 00:41:24 add so we'll need to import products
  • 00:41:27 controller as well and then pass the
  • 00:41:29 type so don't create a new instance of
  • 00:41:31 this class just pass the class name here
  • 00:41:33 two controllers and then for providers
  • 00:41:36 we also need to set this up otherwise
  • 00:41:37 dependency injection won't work and
  • 00:41:39 there we point at the product service
  • 00:41:42 and you also need to import that now we
  • 00:41:45 got this module set up and still it
  • 00:41:47 would not work because we need to let
  • 00:41:48 nest chess know about this module as I
  • 00:41:51 said earlier nest chess does not
  • 00:41:53 automatically scan all your files and
  • 00:41:55 then make some guesses instead you have
  • 00:41:58 to be really clear about how your app is
  • 00:41:59 structured now we got our app module and
  • 00:42:02 of course we could remove the app
  • 00:42:03 controller and service because they're
  • 00:42:05 not doing anything we would use here
  • 00:42:07 I'll leave them here though but one
  • 00:42:09 thing we need to do in the app module is
  • 00:42:11 in imports we now need to add the
  • 00:42:14 products controller because we kind of
  • 00:42:16 depend on this of course the app
  • 00:42:17 controller doesn't use anything from the
  • 00:42:19 mob from the products controller but the
  • 00:42:22 app module needs the products module
  • 00:42:25 because this makes up our entire app and
  • 00:42:28 you need to link your app module to the
  • 00:42:30 other modules that also make up parts of
  • 00:42:33 your app so here an app module we point
  • 00:42:35 at the products module now and with that
  • 00:42:40 and you also need to add an import for
  • 00:42:42 that so with steady imported with that
  • 00:42:44 added to imports here we're ready to
  • 00:42:47 test this now one side note about
  • 00:42:50 imports by the way this import statement
  • 00:42:53 here is a language feature which
  • 00:42:54 typescript needs to know where this
  • 00:42:57 products module
  • 00:42:58 I was coming from so this is required by
  • 00:43:00 the typescript to tie all your files
  • 00:43:02 together and bundle them together this
  • 00:43:04 year is an SKS feature it's named
  • 00:43:06 imports because the nest chess team
  • 00:43:08 chose to name it imports it has nothing
  • 00:43:10 to do with file imports it's just a nest
  • 00:43:13 race feature to link modules together so
  • 00:43:18 now let's test this let's save this this
  • 00:43:20 restarts our API and now we can send a
  • 00:43:22 post request to products now how can we
  • 00:43:26 send a post request there are different
  • 00:43:28 ways pretty convenient and easy one is
  • 00:43:31 to use postman which is a tool that
  • 00:43:33 allows you to send requests HTTP
  • 00:43:36 requests to api's you can download
  • 00:43:39 postman from this website I already got
  • 00:43:42 it installed so I'll just start it so
  • 00:43:45 here I started it by the way you don't
  • 00:43:47 need to sign in at the very bottom
  • 00:43:48 there's this small almost invisible text
  • 00:43:50 which allows you to skip sign in and
  • 00:43:55 then in here in this interface you can
  • 00:43:58 create your requests and here we can
  • 00:44:00 send a post request to a URL which is of
  • 00:44:03 course localhost 3000 slash products
  • 00:44:05 right because our server is running on
  • 00:44:07 localhost 3000 we're filtering for slash
  • 00:44:10 products and we don't need to set
  • 00:44:13 anything else here no special headers
  • 00:44:15 but of course a body now our body will
  • 00:44:19 actually be raw and then here in the
  • 00:44:23 drop-down you can choose Jason now Jason
  • 00:44:26 is written by adding curly braces and
  • 00:44:31 then your keys are between double quotes
  • 00:44:33 and your values are as well at least if
  • 00:44:35 they are text numbers are not between
  • 00:44:37 double quotes and then we'll need a
  • 00:44:39 title key because we're expecting a
  • 00:44:42 title here we're also expecting a
  • 00:44:44 description and a price so a title like
  • 00:44:46 test then the description key here which
  • 00:44:51 is this is first product and then a
  • 00:44:57 price key and this is a number of values
  • 00:44:59 so we don't put the value between quotes
  • 00:45:01 here with that let's hit Send here and
  • 00:45:06 that's looking good I'm getting back my
  • 00:45:08 ID and that simply my date here right
  • 00:45:10 because we're using that
  • 00:45:12 as an ID and therefore the requests
  • 00:45:15 definitely reached this end point and we
  • 00:45:17 had no error otherwise we wouldn't have
  • 00:45:18 gotten back this ID so that is working
  • 00:45:21 we're storing our product in memory at
  • 00:45:24 least the next step that would make
  • 00:45:26 sense is that we can also get all
  • 00:45:27 products and a single product so let's
  • 00:45:30 add a new method here in the product
  • 00:45:32 controller get all products and the
  • 00:45:35 names of the methods are completely up
  • 00:45:37 to you don't matter at all this will
  • 00:45:39 handle get requests so let's import get
  • 00:45:42 from Ness J's common
  • 00:45:43 that's this decorator which you now add
  • 00:45:45 here again we could filter for the path
  • 00:45:47 but we don't need to we want to handle a
  • 00:45:50 request to just slash products and then
  • 00:45:53 here we need a method in the service
  • 00:45:55 that gives us a handle to all these
  • 00:45:56 products in the service by the way we
  • 00:45:58 can also add private here in front of
  • 00:46:00 products so that the products array is
  • 00:46:02 really only usable from inside the
  • 00:46:04 service and our service methods are the
  • 00:46:07 only way of interacting with it this
  • 00:46:09 ensures that we can never added or
  • 00:46:11 directly tap into products without going
  • 00:46:14 through a method which allows us on the
  • 00:46:16 other hand to make sure that we always
  • 00:46:18 follow the same steps for adding data or
  • 00:46:20 for removing data for example that we
  • 00:46:22 always generate the ID in the same way
  • 00:46:24 so now here we could add fetch products
  • 00:46:29 or get products whatever name you would
  • 00:46:32 prefer and here I want to return this
  • 00:46:34 products but now we have to be careful
  • 00:46:36 if you return like this it will work but
  • 00:46:39 since arrays and objects are reference
  • 00:46:41 types in JavaScript and in case this
  • 00:46:43 doesn't tell you anything below the
  • 00:46:45 video you'll find another article in
  • 00:46:47 video by me where I explain this since
  • 00:46:49 they are reference types what we
  • 00:46:50 actually return here is not a copy of
  • 00:46:53 that list but a pointer to that same
  • 00:46:55 list memory so now we indirectly open up
  • 00:46:59 a door where the controller that returns
  • 00:47:01 our products or gets our products could
  • 00:47:03 edit the products now of course you
  • 00:47:05 might say I'm writing the code why would
  • 00:47:07 I mess with my own code well that's
  • 00:47:10 correct but consider that you're working
  • 00:47:13 in a team where other people might not
  • 00:47:15 know how you plant that this should be
  • 00:47:16 used or that you're coming back to your
  • 00:47:19 code after six months and you forgot how
  • 00:47:21 you wanted to use this you can introduce
  • 00:47:23 strange bugs if you start at
  • 00:47:25 products from outside this service and
  • 00:47:28 therefore here we should return a copy
  • 00:47:30 and we can create a copy is simply by
  • 00:47:32 calling slice here or now alternative by
  • 00:47:37 returning a new array by wrapping this
  • 00:47:39 into square brackets but now we would
  • 00:47:41 have an array with an array in there but
  • 00:47:43 by using the spread operator which is a
  • 00:47:44 modern JavaScript feature which is also
  • 00:47:47 supported by typescript we're pulling
  • 00:47:48 out all the elements off products and
  • 00:47:50 add them as new elements to this new
  • 00:47:52 array now the products themselves are
  • 00:47:55 objects and we don't copy those so these
  • 00:47:57 are technically be editable from outside
  • 00:47:59 if you would want to make sure that this
  • 00:48:02 also isn't the case you would have to
  • 00:48:03 call map here and transform every
  • 00:48:06 product to a new copy of the product
  • 00:48:08 I'll not do that here since it's way
  • 00:48:11 less likely that we start editing single
  • 00:48:13 products in the return list but if you
  • 00:48:15 want it to ensure that this can't happen
  • 00:48:17 that's a pattern you also might consider
  • 00:48:19 so now I'm returning my products list
  • 00:48:21 here in the products controller we can
  • 00:48:23 therefore simply well in the end
  • 00:48:25 returned this product service get
  • 00:48:28 products this will return a list of
  • 00:48:30 products and typescript is smart enough
  • 00:48:33 to infer this and this will
  • 00:48:35 automatically alter be converted to
  • 00:48:37 Jason just like if you return an object
  • 00:48:39 if you return a list that's treated as
  • 00:48:41 Jason because it makes up where it can
  • 00:48:43 be transformed to valid Jason and that
  • 00:48:46 should be all we need here you could of
  • 00:48:48 course wrap this into an object where
  • 00:48:50 you have like your products in a product
  • 00:48:54 key and then have some other key in case
  • 00:48:56 you need that but here I'm fine with
  • 00:48:58 just returning the list of products so
  • 00:49:00 I'll just return that and that's that
  • 00:49:02 really lean controller thing I was
  • 00:49:03 talking about right so let's save this
  • 00:49:06 and let's go back to postman and now
  • 00:49:09 send a get request to the same URL I'll
  • 00:49:12 open a new tab up there so that I can
  • 00:49:14 easily resend a post request because
  • 00:49:16 this is not all safe there
  • 00:49:17 send that to the same URL we don't need
  • 00:49:20 to set up a body because you can't have
  • 00:49:22 a body on get requests don't need to set
  • 00:49:24 up anything else let's just hit Send and
  • 00:49:26 I'm getting back an empty array now this
  • 00:49:29 makes sense because the server restarted
  • 00:49:31 when we changed the code and we're only
  • 00:49:33 managing our data in memory when the
  • 00:49:35 server restarts that memory is cleared
  • 00:49:37 it works however if I now add a new
  • 00:49:40 product with post and I'd then get my
  • 00:49:43 products again now the server wasn't
  • 00:49:45 restarted in between so our memory is
  • 00:49:47 still there and here therefore here we
  • 00:49:49 have our products list if I add another
  • 00:49:51 product second test this is a second
  • 00:49:56 product and I then get my products we
  • 00:49:58 see both products here
  • 00:50:00 now of course saving products in memory
  • 00:50:02 is not a production ready solution this
  • 00:50:04 is just so that we can focus on
  • 00:50:05 controllers and so on first I will show
  • 00:50:08 you how to also manage the data in a
  • 00:50:10 database so we can add products we can
  • 00:50:14 get all products how about getting a
  • 00:50:16 single product that would be nice too
  • 00:50:18 wouldn't it in a controller we could
  • 00:50:22 have a get product method and now here
  • 00:50:25 this of course all the handles get
  • 00:50:26 requests now one problem we have is if
  • 00:50:29 you have two methods in the same
  • 00:50:31 controller with the same decorator then
  • 00:50:34 the first one will win so this will
  • 00:50:35 never execute a get request to slash
  • 00:50:38 products will always execute this method
  • 00:50:41 this method has no chance but actually
  • 00:50:43 here I don't want to execute this method
  • 00:50:45 for just slash products because I want
  • 00:50:47 to get a single product so the incoming
  • 00:50:50 requests should actually contain some
  • 00:50:51 information about which product I want
  • 00:50:53 to return now you can't add a body to
  • 00:50:56 get requests as I mentioned so we can't
  • 00:50:58 put that information into the request
  • 00:51:00 body but we can put it into D URL so
  • 00:51:03 that we send a request a get request to
  • 00:51:06 something like products one if we had
  • 00:51:09 IDs that are that simple if we used that
  • 00:51:13 then we could look for that URL and
  • 00:51:15 return a product the problem is of
  • 00:51:18 course I can't look for one here or for
  • 00:51:20 queue because then I would only handle
  • 00:51:22 exactly that product we need to be more
  • 00:51:24 flexible if you know Express chest you
  • 00:51:27 know that you could set up dynamic
  • 00:51:29 segments by adding a colon and then any
  • 00:51:31 identifier of your choice like ID or
  • 00:51:33 prod ID but that's up to you and you can
  • 00:51:36 indeed do the exact same thing in SAS
  • 00:51:38 with this syntax you're saying well
  • 00:51:41 there should be an extra path after this
  • 00:51:43 one I don't know what the exact name of
  • 00:51:46 the path is because it's dynamic but I
  • 00:51:49 want to get the value that's in the path
  • 00:51:51 as an ID parameter and you can get that
  • 00:51:55 parameter now with the param decorator
  • 00:51:59 which you need to import here in your
  • 00:52:02 method argument list by adding at param
  • 00:52:05 and then again you can add it like this
  • 00:52:07 to get an object with all parents in
  • 00:52:09 there or just as for the body you add
  • 00:52:12 your param and here I used ID up there
  • 00:52:15 so we have to use ID down there and that
  • 00:52:17 gives you that parameter value and that
  • 00:52:19 will be a string and that's how we can
  • 00:52:22 extract data from the incoming URL from
  • 00:52:25 the parameter list and therefore now we
  • 00:52:27 can add a method to the service to get a
  • 00:52:30 single product here I expect to get the
  • 00:52:35 product ID which is a string as an
  • 00:52:37 argument and then I want to return that
  • 00:52:39 single product from my list of products
  • 00:52:42 so let's identify the product and store
  • 00:52:47 it in a constant by reaching out to this
  • 00:52:49 products and to get a product by ID
  • 00:52:52 there we can use find and fine takes a
  • 00:52:57 function where we get the product
  • 00:53:00 because this function we pass to find
  • 00:53:02 runs for every item in this array and
  • 00:53:05 then this function has to return true if
  • 00:53:06 it's the object or the item we're
  • 00:53:08 looking for and false otherwise and we
  • 00:53:10 want to return true if prod ID is equal
  • 00:53:13 to product ID now we got the product and
  • 00:53:17 now we can return product like this or
  • 00:53:20 also to copy it wrap it into square
  • 00:53:23 brackets into curly braces excuse me and
  • 00:53:26 use the spread operator there as well
  • 00:53:28 because just as you can use it for a
  • 00:53:30 list you can also use it for an object
  • 00:53:32 to create a new object then take all the
  • 00:53:34 key value pairs of the old object and
  • 00:53:36 add them as new key value pairs to the
  • 00:53:38 new object now we have a problem though
  • 00:53:41 and that should be free equal signs we
  • 00:53:44 have a problem we might not find a
  • 00:53:45 product for a given ID so add a check
  • 00:53:48 and check if product is null or to be
  • 00:53:54 precise if not product basically then I
  • 00:53:57 don't want to return my product
  • 00:54:00 now we could return a different response
  • 00:54:03 or we just throw
  • 00:54:05 a new error an S Ches can then send a
  • 00:54:08 error response however not if we throw
  • 00:54:11 an error like this instead we can now
  • 00:54:13 import not found exception for example
  • 00:54:17 and there are different base exceptions
  • 00:54:19 nest Ches offers for a common problems
  • 00:54:21 like you didn't find the data you got
  • 00:54:23 invalid client data for validation
  • 00:54:25 something like that so here we have a
  • 00:54:27 not found exception and we simply throw
  • 00:54:29 a new not found exception here an S Ches
  • 00:54:33 will then automatically send back a 404
  • 00:54:35 response which makes sense to also use
  • 00:54:38 that status code you can pass your own
  • 00:54:40 message here like could not find product
  • 00:54:44 and with that we're making sure that
  • 00:54:46 we're handling this case as well now to
  • 00:54:49 have a bit easier IDs to work with I'll
  • 00:54:53 use something else then new date I'll
  • 00:54:56 use math.random to string still not
  • 00:54:59 unique we can of course generate the
  • 00:55:01 same random number twice but at least a
  • 00:55:03 bit shorter than the date so now we have
  • 00:55:06 get single product here we're generating
  • 00:55:07 easier IDs we're hopefully finding
  • 00:55:09 products or throwing errors in the
  • 00:55:11 controller we now can return this
  • 00:55:14 product service get single product for
  • 00:55:17 the prod ID we extracted from the
  • 00:55:19 incoming requests so now let's save all
  • 00:55:22 of that let's go back and let's first of
  • 00:55:24 all add a new product because we
  • 00:55:26 restarted the server all data is lost
  • 00:55:28 therefore so now we should have that in
  • 00:55:31 there that's the ID so let's grab that
  • 00:55:33 and let's now look for for for all
  • 00:55:36 products first we can see it here and
  • 00:55:39 now for this specific product by adding
  • 00:55:41 that ID after slash products send a get
  • 00:55:45 request there and that's looking good
  • 00:55:47 now let's send a get request for some
  • 00:55:49 other ID which doesn't exist and we're
  • 00:55:52 getting a 404 error with our custom EMA
  • 00:55:54 error message so that's perfect that is
  • 00:55:57 working exactly as it should with dead
  • 00:55:59 we have a method for returning a single
  • 00:56:00 product as well now how about updating a
  • 00:56:05 product we can add it we can get it but
  • 00:56:07 we might also want to change it now for
  • 00:56:10 updating there are different strategies
  • 00:56:12 you could accept incoming requests which
  • 00:56:14 give you some an object with some
  • 00:56:17 updated property
  • 00:56:19 and then you merged that with the
  • 00:56:20 existing product or you expect to get a
  • 00:56:23 complete replacement so a complete new
  • 00:56:26 object I'll go for the merging strategy
  • 00:56:29 and therefore here we could have an
  • 00:56:31 update product method and our controller
  • 00:56:33 and parameter that now makes sense or a
  • 00:56:37 HTTP word
  • 00:56:38 excuse me HTV work that makes sense is
  • 00:56:40 patch you could use put but port would
  • 00:56:42 be better if you plan on replacing the
  • 00:56:44 current product with that product you're
  • 00:56:46 getting instead I will use patch because
  • 00:56:48 again I want to merge the changes with
  • 00:56:50 the existing product so I don't replace
  • 00:56:52 it I just replaced the fields that
  • 00:56:54 changed so add add patch here and just
  • 00:56:59 as with get product here we of course
  • 00:57:02 need to know which product to update so
  • 00:57:05 I expect to get that ID in the path here
  • 00:57:08 as well now a patch request also does
  • 00:57:10 have a body so we could also expect this
  • 00:57:13 in the request body but logically I'd
  • 00:57:15 say it makes more sense if the
  • 00:57:17 identification criteria is in the URL
  • 00:57:19 and the update data then is in the body
  • 00:57:22 so here we get the ID in the URL and we
  • 00:57:25 can therefore extract that just as we're
  • 00:57:27 doing it up there but as I said we'll
  • 00:57:29 also have some data in the body and
  • 00:57:31 there will have a title our broad title
  • 00:57:37 which is a string we'll have a
  • 00:57:40 description our products which is a
  • 00:57:44 string and we have our price and of
  • 00:57:48 course some of these fields might not be
  • 00:57:50 there but that shouldn't be a problem so
  • 00:57:54 with all that extracted some fields from
  • 00:57:56 the body and the parameter it's again
  • 00:57:58 time to go to the service and now add a
  • 00:58:00 method for updating a product here as
  • 00:58:02 well so here we can add a new method
  • 00:58:04 name it update product as well or name
  • 00:58:06 it differently whatever you want an
  • 00:58:08 update product expects to get the
  • 00:58:11 Product ID of course but we also will
  • 00:58:13 expect the title here the description
  • 00:58:19 and the price all of that is expected
  • 00:58:23 here as well and then we first of all
  • 00:58:25 need to find the product so we can
  • 00:58:27 repeat this and we actually also want to
  • 00:58:29 throw an exception if we don't find the
  • 00:58:31 product
  • 00:58:32 so since we'll run that exact same code
  • 00:58:35 we can of course also outsource this cut
  • 00:58:38 it from here and add a new private
  • 00:58:40 method in this service because we'll
  • 00:58:42 only call it from inside the service
  • 00:58:43 which we'll name find product there I
  • 00:58:47 want to have my ID as an input and now
  • 00:58:50 here we can have that logic just rename
  • 00:58:53 this to ID because I renamed the
  • 00:58:54 argument and then simply return the
  • 00:58:57 product here and then here we can just
  • 00:59:01 well in the end get our product by
  • 00:59:04 calling this find product and forwarding
  • 00:59:07 the product ID and that's the same thing
  • 00:59:09 we can do an update product now and this
  • 00:59:11 make sure that we get our product or fro
  • 00:59:14 the error if we don't find it and then
  • 00:59:17 here I want to update my product so
  • 00:59:19 actually what I'll also need is the idea
  • 00:59:23 of that product so I'll tweak does find
  • 00:59:26 product thing a little bit here
  • 00:59:27 and I'll actually use find index here
  • 00:59:30 which will give me the index of the
  • 00:59:32 product in the array so the position
  • 00:59:35 then here I can still get my product by
  • 00:59:38 using this products whoops
  • 00:59:41 products and then use the product index
  • 00:59:44 so this still works as before but here
  • 00:59:46 we can now return the product anti index
  • 00:59:49 maybe an array first element product
  • 00:59:52 second element product index and now
  • 00:59:54 here in get single product this year of
  • 00:59:58 course returns an array now not a single
  • 01:00:00 product anymore and in fine product we
  • 01:00:03 now can also add a return type here to
  • 01:00:06 make it clear that we'll have an array
  • 01:00:09 as a return value where the first
  • 01:00:11 element will always be a product and the
  • 01:00:12 second element will always be a number
  • 01:00:14 this is a so-called tuple type and type
  • 01:00:16 script so it's not an array where we can
  • 01:00:18 have an infinite amount of our elements
  • 01:00:20 or different types of data in different
  • 01:00:22 positions no it will have exactly two
  • 01:00:24 elements first element is a product
  • 01:00:26 second element is a number and now in
  • 01:00:28 get single product we can get our
  • 01:00:30 product by using the first element we're
  • 01:00:34 getting back here and an update product
  • 01:00:36 well there I get my first element which
  • 01:00:39 is my product and then also my index
  • 01:00:43 with this find product product idea
  • 01:00:47 then the first element or we use array
  • 01:00:51 destructuring in the end here to only
  • 01:00:53 have one line of code and then we make
  • 01:00:56 that call without extracting the value
  • 01:00:57 but here on the left side of the equal
  • 01:00:59 sign we put our variables or our
  • 01:01:02 constants here between square brackets
  • 01:01:04 and the first element is the product
  • 01:01:06 second is the index and that's simply a
  • 01:01:08 syntax supported by type script and also
  • 01:01:11 by modern JavaScript which if you have
  • 01:01:13 an array on the right side of the equal
  • 01:01:15 sign
  • 01:01:16 puts the array elements into constants
  • 01:01:19 with these names or variables can be
  • 01:01:21 variables as well with these names by
  • 01:01:23 simply wrapping them in square brackets
  • 01:01:25 here on the left side so if that I'm
  • 01:01:27 extracting my data from fine product we
  • 01:01:29 have the product we have to index now
  • 01:01:30 now here we just have to set this
  • 01:01:33 products for the given index equal queue
  • 01:01:37 and now I want to take the old product
  • 01:01:41 and merge it with my new product data so
  • 01:01:44 I'll create a new object here and get
  • 01:01:47 all my data from the existing product
  • 01:01:49 which is this product we're getting here
  • 01:01:51 but then I want to set title to my title
  • 01:01:54 I'm getting description to the
  • 01:01:55 description and price to the price I'm
  • 01:01:57 getting the only problem we have here is
  • 01:01:59 that we might not get all that data
  • 01:02:02 maybe the user just sent us a new title
  • 01:02:05 and no description word user send all
  • 01:02:07 fields so we need to make sure that we
  • 01:02:10 don't overwrite existing data with gnal
  • 01:02:12 or with undefined values now there are
  • 01:02:16 different ways of doing this
  • 01:02:17 I'll choose away which hopefully is
  • 01:02:18 relatively easy to understand I'll add a
  • 01:02:21 couple of if checks and there are
  • 01:02:23 shorter ways of achieving this but I'll
  • 01:02:24 use AF check and if we don't have a
  • 01:02:27 title and that will also by the way
  • 01:02:29 trigger if the title is empty which is
  • 01:02:32 good if we don't have a title then I
  • 01:02:34 don't want to set it or put in other
  • 01:02:35 words if we have a title I want to use
  • 01:02:38 it so add a new updated product will be
  • 01:02:41 a copy of the existing product here and
  • 01:02:44 then here I'll set my updated product
  • 01:02:46 title if we have a title I'll repeat the
  • 01:02:51 same for my other values so here we can
  • 01:02:55 check description and this will also
  • 01:02:58 basically not make it in here or
  • 01:03:00 desk is name if it's empty or undefined
  • 01:03:03 and we have no other validation in place
  • 01:03:05 by the way although for the price we're
  • 01:03:07 not checking whether that's negative or
  • 01:03:09 anything like that
  • 01:03:09 it's something you can add an SKS has
  • 01:03:12 some nice features for that but let's
  • 01:03:13 not worry about that for the moment so
  • 01:03:16 here for a description I'll set the
  • 01:03:18 description to desk if desk is set and
  • 01:03:20 also last but not least here if price so
  • 01:03:26 if that has a valid value then we'll set
  • 01:03:28 up that product up price equal to the
  • 01:03:31 incoming price so now we have our
  • 01:03:33 updated product and now dad's in the end
  • 01:03:35 what I'll use down there to overwrite
  • 01:03:37 the existing product again that's just
  • 01:03:40 one possible approach but hopefully one
  • 01:03:42 that's easy to understand so now we have
  • 01:03:45 some logic here to replace our existing
  • 01:03:46 product back in the products controller
  • 01:03:49 we can now call this product service dot
  • 01:03:51 update product and now forward our prod
  • 01:03:55 ID our prod title our prescription in
  • 01:03:59 our price and thereafter simply return
  • 01:04:03 null maybe because I don't really need
  • 01:04:04 to return anything else there it is
  • 01:04:06 there is really data I want to return of
  • 01:04:08 course you could return data but I don't
  • 01:04:10 see which data we would pass back let's
  • 01:04:13 give it a try let's save that and as
  • 01:04:15 before let's create a new product first
  • 01:04:17 of all because we restarted the server
  • 01:04:19 let's get that ID let's send a get
  • 01:04:22 request to that ID to verify that it's
  • 01:04:24 there and now let's create a new request
  • 01:04:27 here a patch request to localhost 3000
  • 01:04:31 slash products slash that ID in there in
  • 01:04:36 the body now set this to raw and then
  • 01:04:38 Jason and there add curly braces and
  • 01:04:42 then let's say we want to set an updated
  • 01:04:46 title but know our values if I send this
  • 01:04:49 I get back no response body which makes
  • 01:04:52 sense but it is a success response to a
  • 01:04:55 hundred status code so now let's check
  • 01:04:57 this item again here before we had a
  • 01:05:01 second test if I sent us again
  • 01:05:03 we now have an updated title and all the
  • 01:05:05 old data is still there so updating
  • 01:05:08 seems to work let's now also update
  • 01:05:10 let's say the price – oops should be
  • 01:05:12 between double quotes
  • 01:05:14 100 dot $0.99 this request here and now
  • 01:05:19 get this back and now we see that as
  • 01:05:22 well so this all seems to work we can
  • 01:05:24 update products as well so to come to an
  • 01:05:27 end now let's also add a delete method
  • 01:05:31 so here we import delete from nest is
  • 01:05:34 common and we've delete imported in the
  • 01:05:38 controller we can add a new method
  • 01:05:40 remove product and that method receives
  • 01:05:44 the delete decorator and just as patch
  • 01:05:50 and get single product we of course need
  • 01:05:52 the ID of the product here so let's
  • 01:05:55 accept it as a dynamic segment because
  • 01:05:57 delete requests don't accept a request
  • 01:06:00 body hence we need to get this from the
  • 01:06:03 parameters let's extract it as we did
  • 01:06:05 before and then in here I want to reach
  • 01:06:09 out to the product service to remove a
  • 01:06:11 product so in the product service we can
  • 01:06:14 add a delete product method that method
  • 01:06:17 expects to get the prod ID as a string
  • 01:06:21 and then in here well let's delete this
  • 01:06:24 product let me actually move that up
  • 01:06:26 above the private method doesn't make a
  • 01:06:28 difference it's just better style and
  • 01:06:30 now here first of all let's get our
  • 01:06:32 product with that array destructuring
  • 01:06:36 some text by calling this find product
  • 01:06:38 for the prod ID and let's also get the
  • 01:06:43 index because actually that is the thing
  • 01:06:45 I care about don't really care about the
  • 01:06:46 product we can use an underscore as a
  • 01:06:48 variable name to signal that we don't
  • 01:06:50 really care about that or of course as
  • 01:06:52 alternative simply retrieve that second
  • 01:06:55 value which the index is by accessing
  • 01:06:57 index one here like that so if that we
  • 01:06:59 get the index of the product we want to
  • 01:07:01 clear now we can call this products now
  • 01:07:04 there are different ways of removing a
  • 01:07:05 product we could all use the filter
  • 01:07:08 method to get a new list of products
  • 01:07:10 with which we could overwrite the
  • 01:07:11 existing one I will use splice which
  • 01:07:14 takes the index as a starting point and
  • 01:07:17 then splices which means removes one
  • 01:07:20 element so now we have two lead product
  • 01:07:22 back in remove product we can now call
  • 01:07:24 this product service delete product for
  • 01:07:27 word the prod ID here and we should be
  • 01:07:32 good to go and just as for patching I'll
  • 01:07:34 return now but of course you could
  • 01:07:35 return a different response so let's
  • 01:07:40 save this let's give it another try
  • 01:07:43 first of all let's add a product and
  • 01:07:46 let's it maybe add more than one so we
  • 01:07:48 have a second test we don't have have a
  • 01:07:50 first one so let's add a first test that
  • 01:07:53 first product and also a third one and I
  • 01:07:55 want to have multiple items here so that
  • 01:07:57 we can see that we actually delete the
  • 01:07:58 right one so now let's get all products
  • 01:08:01 that's looking good let's now get this
  • 01:08:05 one a first test which is in the middle
  • 01:08:06 actually get it here for a single
  • 01:08:09 product seems to work just for a quick
  • 01:08:12 check let's also update it maybe with
  • 01:08:14 the update data we still have in there
  • 01:08:17 get all products again this middle one
  • 01:08:19 should have changed now and it did and
  • 01:08:21 now let's send a delete request so a new
  • 01:08:24 request here with the little delete word
  • 01:08:26 to localhost 3000 slash products slash
  • 01:08:32 this ID and nothing else that should be
  • 01:08:34 all if we had send getting back status
  • 01:08:37 code 200 and if I now get all products
  • 01:08:40 the middle one should be gone and we
  • 01:08:42 only have a second and a third tests or
  • 01:08:44 the one which we had in the middle
  • 01:08:45 indeed is gone by the way if I try to
  • 01:08:48 delete this again we now will get the
  • 01:08:49 404 error because we couldn't find that
  • 01:08:52 product and that of course makes sense
  • 01:08:53 so now we have the basic crud
  • 01:08:56 functionality implemented here with
  • 01:08:58 in-memory data of course but still and
  • 01:09:01 with that we covered a lot of the core
  • 01:09:03 basics NESTA's offers now nest Reyes has
  • 01:09:07 loads of features of course if you visit
  • 01:09:10 their Docs you can learn so much more
  • 01:09:11 about it
  • 01:09:12 I will actually release another video
  • 01:09:14 which maybe is already available when
  • 01:09:16 you're watching this where I will dive
  • 01:09:17 into how to connect this to a database
  • 01:09:20 to MongoDB now to save our data not just
  • 01:09:22 in memory but in a real database so
  • 01:09:25 that's something I'll have a look at and
  • 01:09:26 then we'll see where we take it
  • 01:09:27 depending on whoever you like that what
  • 01:09:30 you think about this video I hope it was
  • 01:09:33 helpful and I hope I see you in future
  • 01:09:35 videos bye