- 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