Build a RESTful API with Node.js, Express & TypeScript

Поделиться
HTML-код
  • Опубликовано: 9 окт 2024

Комментарии • 152

  • @TomDoesTech
    @TomDoesTech  3 года назад +14

    This video has been updated: ruclips.net/video/BWUi6BS9T5Y/видео.html
    The updated version is much better so please watch that one instead of this video.

    • @jessejulian9069
      @jessejulian9069 Год назад

      Hey Tom whats the difference between this video and the updated one? Is there anything wrongn with this one? The other one seems more complex and longer too

  • @swatireddy6822
    @swatireddy6822 3 года назад +5

    Hey Tom, doing great work.☺️ Please continue do such video which will help others to learn.

  • @rohitpandit3267
    @rohitpandit3267 3 года назад +2

    its been less than 5 minutes and already subscribed you, great video bro

    • @TomDoesTech
      @TomDoesTech  3 года назад +1

      Thank you so much! I am redoing this video and it's going to be 10 times better than this one, should be out next week :)

  • @degraphe8824
    @degraphe8824 3 года назад +18

    This is what I call typescript speed run. Great tutorial. I feel though, that it's better to type these things out for the more intermediate or junior Software Dev Folk. since it is an Auth lesson on Typescript majorly, most people coming here are probably intermediate or junior

    • @johnyepthomi892
      @johnyepthomi892 Год назад

      It is a speed run and juniors will have to sweat a bit to connect the dots.

  • @sandeepgamot4585
    @sandeepgamot4585 2 года назад

    Wow I've never seen such sophisticated use of Postman, maybe you can make a video of your workflow with Postman

  • @EduardoHernandez-ux6gg
    @EduardoHernandez-ux6gg 3 года назад +3

    The best tutorial of Node whit Ts, thx bro!! from Mexico

  • @bikramjeetsingh4943
    @bikramjeetsingh4943 3 года назад +2

    Great content, Brother!! Really like your typescript stuff

  • @bonarhymetechhub7786
    @bonarhymetechhub7786 2 года назад +1

    Hello @tomdoestech, thank you very much for the content.
    However, there is a suggestion I want to make:
    Say you want to build the login functionality please do not start from the routes, it creates some kind of confusion. Instead you could do this:
    1. Start from the various utilities
    2. Build your validation schema
    3. Build your service
    4. Then build the routes
    This way, it will be easy to grasp.

  • @yousuf4you
    @yousuf4you 2 года назад +2

    This is a very thankful and helpful video....Thanks

  • @bifdiogo
    @bifdiogo 3 года назад +1

    Greetings from Brazil! Great job!

  • @osaigbovoemmanuel1
    @osaigbovoemmanuel1 2 года назад +1

    Great tutorial! The tutor has a great understanding of RESTful APIs 👌

  • @noadevamshmanoj3618
    @noadevamshmanoj3618 3 года назад +4

    Hey tom love your work ❤❤

  • @akademidevid
    @akademidevid 3 года назад +6

    Awesome.
    You're doing great!
    Make another like this

  • @bkironas5473
    @bkironas5473 3 года назад +3

    Thanks for this video. I'm really new to Typescript coming from a C# background. I've been finding it hard to switch from OOP to functional programming, and I'm finding your video really helpful.
    One thing I noticed is that you dont really specify the return types for any of your functions. Is that standard practise with TS? Personally I believe that you should be able to look at a function and know exactly what's expected to go into it, and exactly what's expected to come out of it (obviously TS makes this a little less definitive with union types, but you still have an idea which type to expect).

    • @TomDoesTech
      @TomDoesTech  3 года назад

      I generally don't specify the output, which is probably bad practice. If your functions are pure and you specify the input, TS generally does a good job of implicitly specifying the output.
      I think it depends on the function and what you find useful.

    • @presidential-production
      @presidential-production 2 года назад

      B Kironas Thanks for the input! I'm coming to this video with the same background and your comment made me sure I would learn from this video.

  • @emekarr
    @emekarr 3 года назад +4

    Fingers crossed on this. Hope it helps me.

    • @TomDoesTech
      @TomDoesTech  3 года назад +2

      Let me know if you have any questions

  • @eternalprogramming3503
    @eternalprogramming3503 3 года назад +3

    Thanks for the informative video! I think I'll be using this controller-service type system now

  • @mehmetilhan6083
    @mehmetilhan6083 2 года назад +1

    Thanks a lot.I learned a lot ot things from this video.

  • @Jack1430.
    @Jack1430. 3 года назад +1

    Looks great, Im starting the project right now

    • @TomDoesTech
      @TomDoesTech  3 года назад

      Good luck Jackie! Please let me know how you get on with it.

    • @Jack1430.
      @Jack1430. 3 года назад

      @@TomDoesTech thanks for your quickly answer, Ill be back for comment how its going!
      Thanks another time!!

  • @akashshrestha01
    @akashshrestha01 3 года назад +1

    great
    more videos on ts + node plz

  • @Scetils
    @Scetils 3 года назад +2

    Solid again.
    Can you explain the reason why you set the newAccessToken generated from the expired refresh token to the "x-access-token" header but the initial access token uses the "authorization" header?

    • @TomDoesTech
      @TomDoesTech  3 года назад

      Hmmm that sounds like a mistake, the access token should always go in the authorization header.

    • @Scetils
      @Scetils 3 года назад

      @@TomDoesTech Yeah I know what was confusing me. My bad. You're attaching the token to the out going/response headers.

    • @TomDoesTech
      @TomDoesTech  3 года назад +1

      @@Scetils I'm glad you figured it out :)
      When I was first learning about REST APIs the concept of incoming and outgoing requests really confused me. Unfortunately, RUclips didn't have much good content on the topic then.

  • @muruganraja9
    @muruganraja9 2 года назад +1

    நன்றிகள் பல...

  • @viewer5099
    @viewer5099 3 года назад +1

    Hi Tom, could you explain why you assign posts their own postId fields and not use the automatically generated id from Mongoose instead?
    I would also like to know what you would advise to do to prevent a malicious user from saturating the database with fake users?
    thank you in advance

  • @alxz11
    @alxz11 3 года назад +1

    Great work dude!!
    i see u use yup in request validation, i have a question how to validate if requested email is already used (unique email)?

    • @TomDoesTech
      @TomDoesTech  3 года назад +1

      If you have a unique flag on the email field in the mongoose model, MongoDB will enforce unique emails.

  • @Krior07
    @Krior07 2 года назад +1

    any idea how to solve this: Namespace '"mongoose"' has no exported member 'HookNextFunction'.

    • @TomDoesTech
      @TomDoesTech  2 года назад +1

      Yeah, don't import or use HookNextFunction

  • @sandeepb8351
    @sandeepb8351 3 года назад

    Hi Tom, great tutorial, I have a question why we use DocumentDefinition?, Also when should we use curly braces({ }) like here, import Post, { PostDocument } from "../model/post.model";

    • @TomDoesTech
      @TomDoesTech  3 года назад +2

      DocumentDefinition with your interface best matches when the model.create method takes as arguments.
      As for the imports, the bit outside the {} is a default export, while the but property inside is a named export. It's like importing using object destructing.

  • @raymartpamplona9122
    @raymartpamplona9122 3 года назад

    I think you forgot the part to add a clip of creating the model for the Post collections hehe

  • @cali4484
    @cali4484 2 года назад

    17:22 Is there an advantage in calling method "hashSync" over method "hash" ?

  • @kittisakphatchaiphongsa3177
    @kittisakphatchaiphongsa3177 2 года назад +1

    if Error 36:12
    const accessToken = createAccessToken({ user, session});
    Change
    const accessToken = sign(
    {...user, session: session._id},
    { expiresIn: config.get("accessTokenTtl")}
    );

  • @muthukumarkamatchi1895
    @muthukumarkamatchi1895 2 года назад

    It’s very useful for me.. As I connect the database, it gives db error. Kindly help me solve this issue

  • @shaancodes
    @shaancodes 3 года назад +1

    This video made me subscribe your channel ❤️❤️

  • @fkarg10
    @fkarg10 3 года назад

    I'm trying to follow along, and I got a very weird error at 7:31 (console.log -> log.info), as log was undefined. I just couldn't figure it out. Seems like it was due to running `npm run build` at some point, and the only change needed was to remove an auto-generated src/app.js

  • @dominikwozniak4317
    @dominikwozniak4317 3 года назад +1

    Good job😎

  • @numericalwallah9174
    @numericalwallah9174 2 года назад +1

    If someone getting printPretty error just put this in logger
    transport:{
    target:"pino-pretty",
    options:{
    colorize:true
    }
    },

  • @lucasgabule
    @lucasgabule 3 года назад

    Awesome Tut.

    • @TomDoesTech
      @TomDoesTech  3 года назад

      Thank you so much :)

    • @lucasgabule
      @lucasgabule 3 года назад

      @@TomDoesTech Better than udemy :)

  • @mohammadandhika4028
    @mohammadandhika4028 2 года назад

    what font do you use in your vscode ?

  • @naufaldbei4234
    @naufaldbei4234 3 года назад

    Im on the delete section of the video, in the delete section part do you put the accessToken on the headers.authorization? im still confused in this part...

    • @naufaldbei4234
      @naufaldbei4234 3 года назад

      yep it turns out my accessToken is always undefined on deserializeUser.ts, where do you put the accessToken after giving it back to the user in createSessionHandler?

    • @TomDoesTech
      @TomDoesTech  3 года назад

      You put it in the authorization header. There is a special section for it in postman, or you can create a header called `Authorization`.

  • @manojrawat5756
    @manojrawat5756 7 месяцев назад

    Sir I am not able to import {DocumentDefination} from mongoose

  • @NathanielBabalola
    @NathanielBabalola 3 года назад

    Thanks a lot for this video, i am just trying to understand something.
    you said if(!accessToken) return next(); , why though? thought it should be access denied at that point if there is no accessToken in the request and return a 403

    • @TomDoesTech
      @TomDoesTech  3 года назад

      You need to consider the path that the data takes. That middleware is run first, so if there is no access token when it gets to the requireUser middleware, the user will be null and a 403 will be sent.
      You don't want to return a 403 in the deserializeUser middleware because then the user has to be logged in for every request, so how will they login or register in the first place.

    • @TomDoesTech
      @TomDoesTech  3 года назад

      If that doesn't make sense I can make you up a flow diagram to help visualize the flow.

    • @NathanielBabalola
      @NathanielBabalola 3 года назад

      @@TomDoesTech yes please, it'll surely help. Thanks

    • @TomDoesTech
      @TomDoesTech  3 года назад

      @@NathanielBabalola There is actually a diagram on the GitHub repo

    • @seanhuggins5382
      @seanhuggins5382 3 года назад

      @@TomDoesTech Do you need to have deserializeUser middleware for every route? Could you not combine requiresUser and deserializeUser into one middleware function and only place it on protected routes?

  • @bobvandoorn8761
    @bobvandoorn8761 3 года назад

    Did I misunderstood, or are u sending with every request the accessToken and the refreshToken? And not like only sending the refreshToken when de accessToken is invalid.

    • @TomDoesTech
      @TomDoesTech  3 года назад +1

      Yeah, send it with every request to make it as seamless for the user

    • @bobvandoorn8761
      @bobvandoorn8761 3 года назад

      ​@@TomDoesTech Can you explain why not just using 1 token? I have the feeling it doesn't make sense to use two different tokens in this manner. I understand it is not the main focus of this video, just wondering. (great video btw ;) )

    • @TomDoesTech
      @TomDoesTech  3 года назад +1

      @@bobvandoorn8761 The two tokens have two different purposes, one grants the user access to the resource, the other, given certain conditions, grants the user access to another access token.

  • @mehulmorker2291
    @mehulmorker2291 3 года назад

    HI @TomDoesTech I have use delete session api and that make my session valid: false. But with the same token I am able to call create post api. I think need to make some changes in deserialize middleware

    • @TomDoesTech
      @TomDoesTech  3 года назад

      When you delete the session or change valid to false, you're making sure the refresh token can't be used to generate another access token, but the current access token will still work. This is why the access tokens should have a short TTL.
      If you want to use the delete session like a logout, also remove the access token from the user.

  • @behroozsayah1679
    @behroozsayah1679 3 года назад

    I've faced to an issue with typescript and type checking.
    In "session.controller" I'm getting the following error: "Property '_d' does not exist on type 'false'"
    I've added the following type checking to the if clause but it did not help.
    if(typeof user === 'boolean) res.status(401).send('Invalid username or password')

    • @behroozsayah1679
      @behroozsayah1679 3 года назад

      I have added the following but I don't know that it is the best practice or not.
      const session = await createSession((user as UserDocument)._id, req.get('user-agent') || '')
      const accessToken = createAccessToken({ user: user as UserDocument, session})

    • @TomDoesTech
      @TomDoesTech  3 года назад

      That's a very weird problem. If you send me a link to the repo I can take a look.

  • @corentintruffaut7291
    @corentintruffaut7291 3 года назад

    Hi there ! First, ty for the content. It helps me to understand some stuff.
    However i got an issue adapting your exemple to my code. Something i never encounter comes to me ˆˆ
    -> I write service and model just as you can, but, when i call .create() method with input as parameters, datas disappear.. I got them in service function but they don't pass to .pre('save') method.
    I know it's small, but any idea what's going on ?

    • @TomDoesTech
      @TomDoesTech  3 года назад

      Interesting, if you can share a repository I am happy to take a look

    • @corentintruffaut7291
      @corentintruffaut7291 3 года назад +1

      @@TomDoesTech Ty for you'r concerne, i figure it out but i don't understand why it happened..
      I used arrow function for async function in .pre('save'). I just rewrite it with classic function and it finally works.
      Do you know the difference between this two ?

    • @TomDoesTech
      @TomDoesTech  3 года назад +1

      @@corentintruffaut7291 Yes, it has to do with scope and closures. Using the function keyword sets scope to the parent function, allowing you to get access to the `this` keyword.

    • @corentintruffaut7291
      @corentintruffaut7291 3 года назад

      @@TomDoesTech Ok, ty for the explanations !

  • @ilhamtanpasaldo
    @ilhamtanpasaldo Год назад +1

    27:15

  • @aliyyil9035
    @aliyyil9035 2 года назад

    bro why we need private kay? i did understand, can u explain this

    • @TomDoesTech
      @TomDoesTech  2 года назад

      Private keys are secrets for signing tokens. You then check with the public key to verify if the token was signed with the correct private key. Look up PGP encryption

    • @aliyyil9035
      @aliyyil9035 2 года назад

      @@TomDoesTech where to sign tokens. When we use it in rest ful api. Can it work without sing or private key?

  • @bhootuncle3269
    @bhootuncle3269 3 года назад

    Does all api are rest or soap api
    Is there nothing like only api (pure api without any type)

    • @TomDoesTech
      @TomDoesTech  3 года назад +2

      APIs are just interfaces that expose the internal workings of a system. They don't always communicate over a network like REST, SOAP & GraphQL APIs. Node.js for example has a standard library and you interact with it through its API. Another example is React, when you call useState for example that's part of React's API.

    • @bhootuncle3269
      @bhootuncle3269 3 года назад

      @@TomDoesTech thanks for your prompt reply

  • @Holaszyd1
    @Holaszyd1 3 года назад

    Help @TomDoesTech i keep getting this error: "mongoose"' has no exported member 'HookNextFunction'

    • @TomDoesTech
      @TomDoesTech  3 года назад

      Have you installed @types/mongoose?

    • @Holaszyd1
      @Holaszyd1 3 года назад

      @@TomDoesTech yes it is installed already

    • @glennmarkflores5198
      @glennmarkflores5198 3 года назад

      try this
      ...
      async function (
      this: UserDocument,
      next: (err?: Error | undefined) => void
      ) ....

  • @dhanushreddy4836
    @dhanushreddy4836 2 года назад

    import config from "config"
    this direct import did not work for me,,, how should i make it work

    • @TomDoesTech
      @TomDoesTech  2 года назад

      I have no idea, you haven't told me anything that would help me provide a solution

    • @dhanushreddy4836
      @dhanushreddy4836 2 года назад

      @@TomDoesTech can you please provide me your linkedin profile link.. so that i can connect there.

    • @TomDoesTech
      @TomDoesTech  2 года назад

      @@dhanushreddy4836 no?

  • @성이름-k4r8j
    @성이름-k4r8j 2 года назад

    3:41
    start setting

  • @Arun99178
    @Arun99178 3 года назад

    Not works with "mongoose": "^6.0.2", version. getting error.

    • @TomDoesTech
      @TomDoesTech  3 года назад

      That's a shame

    • @glennmarkflores5198
      @glennmarkflores5198 3 года назад

      works for me somehow, done some workaround also, uninstall @types/mongoose. the latest versions come with built-in types

  • @vinayaknaik9884
    @vinayaknaik9884 2 года назад +1

    great

  • @wahyuramadhan9316
    @wahyuramadhan9316 3 года назад

    is there anyone know why my get(req, "user") is returned undefined ? so i cant deleting session or anything passing requiresUser middleware ?

    • @TomDoesTech
      @TomDoesTech  3 года назад

      Have you tried logging the user object just before you do req.user = user?

    • @wahyuramadhan9316
      @wahyuramadhan9316 3 года назад

      @@TomDoesTech yes sir, I have log in then copy paste x-refresh from refresh token, what should I do next ?

    • @TomDoesTech
      @TomDoesTech  3 года назад

      @@wahyuramadhan9316 No, I mean using console.log to log the user object to make sure it's being deserialized properly.

    • @wahyuramadhan9316
      @wahyuramadhan9316 3 года назад

      in what file sir that i must logging the user object ?

    • @TomDoesTech
      @TomDoesTech  3 года назад

      @@wahyuramadhan9316 in the deserialize middleware

  • @ravincristiano
    @ravincristiano 3 года назад

    where can I get Private kEY?

    • @TomDoesTech
      @TomDoesTech  3 года назад

      Google "generate public and private keys online".

    • @ravincristiano
      @ravincristiano 3 года назад

      @@TomDoesTech is it okay if i work with the same key you used here?

    • @TomDoesTech
      @TomDoesTech  3 года назад

      @@ravincristiano Yup, I think I committed it to GH

  • @mdjahidulislam9205
    @mdjahidulislam9205 3 года назад

    how to deploy it?

    • @TomDoesTech
      @TomDoesTech  3 года назад

      That's a very broad question that has hundreds, if not thousands of answers. If it's a specific method you're after, the best thing I can point you to is this video: ruclips.net/video/2oNsjyaCIrI/видео.html

  • @audunhilden
    @audunhilden 2 года назад +2

    please man, stop copying everything all the time
    you've got some good tutorials, so please start typing them out or at least giving us 5 seconds to pause
    i need to pause and always skip backwards to see what you pasted

    • @TomDoesTech
      @TomDoesTech  2 года назад

      I've posted a lot of tutorials since this one and I haven't copied since this one, so I'm not sure how I stop doing something that I stopped doing over a year ago

    • @audunhilden
      @audunhilden 2 года назад

      @@TomDoesTech how would I know? just trying to give you a tip
      good work

  • @ravincristiano
    @ravincristiano 3 года назад

    getting 403 error while creating a post.

    • @TomDoesTech
      @TomDoesTech  3 года назад

      Perfect! The Auth system works

    • @ravincristiano
      @ravincristiano 3 года назад

      @@TomDoesTech how to solve this error??

    • @TomDoesTech
      @TomDoesTech  3 года назад

      @@ravincristiano Send the request with a valid JWT

    • @ravincristiano
      @ravincristiano 3 года назад

      @@TomDoesTech I tried with a refresh token but still the same error..
      post: localhost.../api/posts
      headers:
      key: x-refresh
      value: refreshToken
      send
      403 forbidden

    • @devMhamza007
      @devMhamza007 3 года назад

      @@ravincristiano add the access token in auth -> bearer token

  •  2 года назад

    literally first line of tutorial
    yarn : The term 'yarn' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    LMAO

    • @TomDoesTech
      @TomDoesTech  2 года назад

      You have to install yarn to be able to use it, otherwise you can use npm

    • @TomDoesTech
      @TomDoesTech  2 года назад

      This tutorial is not for beginners, it says at the start its for junior to mid-level devs

  • @binitrupakheti4246
    @binitrupakheti4246 3 года назад +1

    Dude you're going way too fast.

  • @shub226
    @shub226 Год назад

    Idk you edited this video yourself or from a editor but it was just a big mess

    • @TomDoesTech
      @TomDoesTech  Год назад

      Sorry to disappoint you. The pinned comment and description have a link to an updated version

  • @FutureIsAmazing569
    @FutureIsAmazing569 3 года назад +1

    editing is beyond terrible

    • @TomDoesTech
      @TomDoesTech  3 года назад +7

      Thanks for the feedback. I'm a software developer trying to learn how to make videos. So I know my editing skills are bad but I am trying to improve them. I'll keep working on it. Got any tips on how I can improve?

    • @noboss3736
      @noboss3736 3 года назад +5

      @@TomDoesTech I think he means that sometimes between cuts your voice is cut off a bit, like at 14:45 for example. But apart from that, I think the video is great! It must be annoying to have such a comment without any further explanation, when you are just trying to help other people and doing your best. So in my opinion great video and keep up the good work :)

    • @TomDoesTech
      @TomDoesTech  3 года назад

      @@noboss3736 Yeah i think I need to edit the noise gate I have setup

    • @poweredcity3704
      @poweredcity3704 3 года назад +3

      @@TomDoesTech Hey great video! But I believe it would be better if you typed it out instead of cutting the big code parts out, when you do that with a paste of big code it encourages me to copy/paste. And I rather actually learn stuff then do that.

    • @TomDoesTech
      @TomDoesTech  3 года назад

      @@poweredcity3704 Thanks for the feedback but I'm curious as to why you think that. It would be very boring watching me type and not talking while I typed everything out. I think it's much better if I paste the code and explain it, then you can copy it with an understanding of what it does.

  •  2 года назад

    I can't even connect to mongoose as i get an error on useNewUrlParser: true,
    TSError: ⨯ Unable to compile TypeScript:
    src/db/connect.ts:10:7 - error TS2769: No overload matches this call.
    Overload 1 of 3, '(uri: string, callback: CallbackWithoutResult): void', gave the following error.
    Argument of type '{ useNewUrlParser: boolean; useUnifiedTopology: boolean; }' is not assignable to parameter of type 'CallbackWithoutResult'.
    Object literal may only specify known properties, and 'useNewUrlParser' does not exist in type 'CallbackWithoutResult'.
    Overload 2 of 3, '(uri: string, options?: ConnectOptions | undefined): Promise', gave the following error.
    Argument of type '{ useNewUrlParser: boolean; useUnifiedTopology: boolean; }' is not assignable to parameter of type 'ConnectOptions'.
    Object literal may only specify known properties, and 'useNewUrlParser' does not exist in type 'ConnectOptions'.
    10 useNewUrlParser: true,
    ~~~~~~~~~~~~~~~~~~~~~
    at createTSError (F:\Programas\Coding\Mobile_Projects\BackEnd\BackEndAutoSense
    ode_modules\ts-node\src\index.ts:820:12)
    at reportTSError (F:\Programas\Coding\Mobile_Projects\BackEnd\BackEndAutoSense
    ode_modules\ts-node\src\index.ts:824:19)
    at getOutput (F:\Programas\Coding\Mobile_Projects\BackEnd\BackEndAutoSense
    ode_modules\ts-node\src\index.ts:1014:36)
    at Object.compile (F:\Programas\Coding\Mobile_Projects\BackEnd\BackEndAutoSense
    ode_modules\ts-node\src\index.ts:1322:43)
    at Module.m._compile (F:\Programas\Coding\Mobile_Projects\BackEnd\BackEndAutoSense
    ode_modules\ts-node\src\index.ts:1454:30)
    at Module._extensions..js (node:internal/modules/cjs/loader:1159:10)
    at Object.require.extensions. [as .ts] (F:\Programas\Coding\Mobile_Projects\BackEnd\BackEndAutoSense
    ode_modules\ts-node\src\index.ts:1458:12)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:827:12)
    at Module.require (node:internal/modules/cjs/loader:1005:19) {
    diagnosticCodes: [ 2769 ]
    }

    • @TomDoesTech
      @TomDoesTech  2 года назад

      Remove useNewUrlParser: true, you don't need it with the new version of mongoose

    •  2 года назад

      @@TomDoesTech thanks. i saw now you hyave an updated video, will watch that instead