NodeJS Swagger API Documentation Tutorial Using Swagger JSDoc

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey my name is maximivonov and last week i've made a video where i've shown how to create a react query crowd application and i was using a server which i wrote using express.js and then it was documented using swagger which is a tool to generate interactive documentation a lot of you have asked in the comments how to do this so here you go this is the tutorial as usually you will find the code for this video in the video description along with an interactive code sandbox where you can play around with this example press the like button subscribe and let's go first let's see what are we going to build it's going to be a library api where you can request a list of books it's going to be top programming books in the library if we click try it out and then execute we'll get the response from the server with the list of books you can also create new books using the post requests get the specific book by its id update the book and remove it we're going to be using express.js to build the application swagger to build the interactive docs for it and we're gonna use swagger js dock to write the specifications and swagger ui express to serve the ui that you see here now let's create the node project npm init the package name will be swagger api library version 1 we skip the description and everything else now that we have the project we're going to install a bunch of dependencies yarn add first of all we're going to need express it's going to be our server we'll use low db to store the data morgan to output the logs for each request nano id to generate the unique identifiers for each of the books course library to set up the cross origin policy swagger js dock to use the js dock syntax to write the swagger specification and swagger ui express to serve the swagger ui in our express application enter and then we wait until the packages are installed okay it's done now we can start working on our server we create a new file as our entry point is called index.js then we call it index dot js here we'll make a bunch of imports first of all we'll need the express const express equals require express we'll also import course equals require course will import morgan require morgan we'll import the low db let's call it low require low db we're going to store our data in the file so we'll need to use the file sync adapter const file sync equals require low db adapters file sync next we'll initialize the db and the adapter const adapter equals new file sync and then we specify the file where we'll store the data it's going to be db json and then we create the database instance db using low and passing the adapter to it then we're going to specify the default data for our storage db defaults and then we pass an object with the field books and it's going to be an empty array to record it into the file we use the method write next we need to initialize the express application const app equals express we specify the app.db to the db instance that we've just created this way we'll be able to access it in our routes which we'll use a bit later then we initialize the course up use course we'll need to parse the json body of the requests so we use app use express json then we connect morgan app use morgan with format dev next we can specify the default port constant const port equals process and port or 4000. so if we have the environment variable port provided then we'll use it otherwise the default port will be 4 000 and then we'll launch the server app listen port and when the app is launched we want to see a log console log the server is running on port and then the port number i also have a typo here it's required require and the port should be all caps port now let's launch the app and see if it works open the terminal node index.js open the browser and you should see cannot get root because we didn't specify any routes let's go back to the code stop the app and let's create a new folder new folder and call it routes in our app we're going to handle only the books routes so create a new file call it books.js here we're going to define the routes for our server first make the inputs const express equals require express then we need the router const router equals express router here we'll need the nano id const nano id equals require nano id we'll use it to generate the ids of our books we're going to create a constant of the id length and it's going to be 8. next let's define the books routes router get first we specify the root route request response and then inside of it we're first going to get the books equals request the request object has the reference to the app and remember how inside of the index.js file we've assigned the app.db to be our db instance now we can access it through the app here db get and we want to get the books record after we got the books we call res send and send the books there next we want to be able to get the book by the id let's define another get route router get and here we'll need to use the placeholder called id again request response inside of it we get the specific book const book equals request app db get books and then we need to find the book which has the id matching the id from the parameters so we call find we pass an options object with id request params id and then we want the value after we have it we can call response send book we also want to be able to create new books so we define the post route router post root request response and then here we try to create a new book it's going to be a new object with id that we generate using the nano id with id length that we've defined earlier and then the rest of the properties we'll take from the request body in real world application you don't want to do this and you should be very rigorous with everything that comes from the user or everything that comes from the request but here it is a learning project and we want to focus on swagger api rather than writing the server itself so just know that we've cut the corner here after we got the book then we call request app db get books and then we push a new item there which is a book and we call write if we got an error for some reason we couldn't record the book we catch it and then we response with status 500 and we send an error now we can create the new books we also want to be able to update the books using the put request so we define the router put slash column id request response and then we want to get the book by the id and we want to wrap everything into a try cage block we try to get the request up db get books where we find the book by its id that we get from request params id and then we assign this is the method of the load db that allows you to merge the objects so we only assign the properties that were sent with this request assign request body and then we write it to the database after we updated the database we send the response send request app db get books find and here we pass an id request params id so we write the data and then we send the newly updated book to the user if we catch an error then we return res status 500 send error and the last thing we want to do with our server is to be able to delete the books router delete slash column id we pass a callback request response we call request app db get books and then we call remove and we pass the id that we get from the request params id and then after we removed it we call right to remove it from the database after it's done we call response send status to 100. now we have all the routes defined so we can export the router module exports equals router format the document connect the router to the app go to index.js and say that app use slash books and it's going to be books router we're going to import using const books router equals require routes books for now the dbgson is empty and i'm gonna copy the prepared one from another project here we go now we have three great programming books here and we can start working on the swagger api documentation now let's go to index.js and connect the swagger ui first let's import it const swagger ui equals require swagger ui express and then we need to connect the swagger.js dock const swagger js dock equals require swagger js dock then right before we define the application create an options object for the swagger const options equals definition where we specify the version of the open api specification open api we're using 3.0.0 then we define the project info the title will be library api version 1.0 and that description will be a simple express library api then we can specify the servers we're going to have only one the localhost 4000 but you can also specify the staging or production server what it does it allows you to pick which server should you execute the requests against let's do it servers and then it's going to be an array with one item with url http localhost 4000 and then the last property is where to take the apis all our apis will be defined in the routes in our case it's only the books api but maybe we will add another one like users or subscriptions or whatever so we're gonna just say that our apis are located in the routes folder so add the apis field which is an array with one string routes and then everything that ends with js there then we can initialize the swagger.js dock const specs equals swagger js dock and then we pass in the options as we specified the api's location now swagger.js dock will know where to parse the jsdoc comments and it's in the routes folder and then after we've defined the app we can say app use the route api docs we pass swagger ui serve as a callback swagger ui serve and then we specify the specs that will be used to build that ui swagger ui setup and we specify the specs all right we have one little typo here the api's field should be on the top level of options after the definition so we move it down add the add a comma and then form the document now we can try launching the app node index.js open the browser the api docs url you should see this interface where you can pick the servers where only one is available and for now no operations are defined in spec so let's start adding those definitions go to books.js scroll up and first we'll begin by defining a book schema because all our endpoints all our routes work with the same model we have the books or the book that we need to return or accepting the post request or put request properties it's a good idea to define it as a separate entity so how you do it with spiger.js doc first of all you create a multi-line comment then you say add swagger or add open api we're gonna use the swagger version and then you specify the components field components in the swagger documentation you can see a good example why you might need it so for example we have two paths defined the users with user id where we get one specific user or we want to get all the users in both requests we're expecting to receive an object with an id which is an integer and a name which is a string you can see it in both requests and using the schema we can get rid of those duplicated definitions so we define the user model once and then using the ref property we reuse it in both paths definitions so we're going to do something similar in the components section we define the schemas and there we define a book schema it's going to have type object and then it's gonna have two required fields title and author required and then it's an array title and author after we've marked the required fields we can specify the descriptions of the fields we have here we do it using the field properties so each book will have an id the type will be string and the description will say that it's the order generated id of the book then we have the title type string description the book title and then the author is going to also have the type string and the description will be the book author we can also provide an example of the book object we do it using a field example here we specify the id and there would it would be some randomly generated hash d five f e underscore asd that title could be the new during omnibus and the author will be alexander k dooney all right now we have the book defined let's check if it worked relaunch the server node index.js go to the browser and you should see the schemas with the book defined there verify that it worked correctly if everything is fine let's move on after we've defined the book schema we can move on to the routes let's define another multi-line comment at swagger and then the first route is the root but when you define the routes in your swagger specification they're defined relative to the server url so in our case we'll have to say that it's books even though we're in the books routes and in our app they're mounted with books prefix in the specification we still have to define it manually and this is the get route so the next line is get next we can specify the summary the description of this request summary returns the list of all the books then we can specify the responses and here you can describe the response codes that you can request that you can receive from the server so for example 200 means that everything is fine and we got our list of the books description the list of the books content here we specify the type of the content it's going to be application json and then we can also set the schema of this response so here we are going to get an array of the books so we specify that the schema type is going to be an array and the items in this array will have the type of the book so we say items are going to use the ref dollar sign ref and here we use the following route hash components schemas book okay time to check if everything works relaunch the server open the browser and you should see the get all books route we can immediately try it out click execute and we got the list of the books it works but it's also a good idea to group your requests into tags so for example here all the requests we're gonna describe are going to be related to books so let's create a new tag go back to the code and before the root route definition let's have another multi-line comment at swagger and here we define the tags name is books and the description of the stack description the books managing api save it restart the server and reload the page now instead of the default block you see the tag with the annotation to mark the root route with the books tag we need to go back to the code and inside of the root route definition below the summary or actually anywhere else specify that tags and array with books let's relaunch the server again reload the page and now you can see that the root route or the books route is under the books tag let's move on the next route we're going to describe is another get request but now we want to specify the id so we're going to describe a route where you can pass a parameter create another multi-line comment at swagger and here we define the url books and if you have a placeholder like this one here in swagger you can specify it using the curly braces and you say id this way you tell swagger that there is a parameter in the url next we specify the method it's get we specify the summary it's gonna be get the book by id the tags should also be books and the parameters is going to be an array and as the parameter we have here is in the path we need to say that it's in path then name of the parameter is id and the schema is type string we also want to specify that it's required required true and the description of this parameter description should be that this is the book id now we can specify the responses for this request we have two potential responses 200 whenever the when everything is fine and we found the book with this id and 404 if the book was not found so let's start with the 200 responses 200 description the book description by id the content of this response is going to be in json format so we use application json and then the schema will be the book that we defined earlier so we say schema and then we use the ref that will refer to our components schemas book definition and then we also have the 404 response 404 which does not return anything so it will only have the description description the book was not found all right let's relaunch the server and see if it works if you go to api docs you should see another request get the book by id you have the required id field which is in the path and then you can get the book description by id let's test it first let's get all the books and for example we get the first id we copy it and then we try to use it in the get book by id route paste it here click execute and we get the book description let's try it with some id that does not exist and we didn't get the 404 so this documentation is also a good way to test your apis at least manually let's go back and make sure that if the book wasn't found we return the 404 status open the code and in the get by id request we specify if there was no book then yes send status 404 let's relaunch the server go back to the browser and try to execute this query again good now we get the 404 not found let's move on to the next requests here we specify the post request multi-line comment at swagger the route is books the method is post the summary is create a new book that tags are books the request body that we specify here because it's a post request and we have a body field in the request request body is going to be required you cannot create a new book without the data so required is true and the content should be in json format application slash json and here we can reuse this schema again because when we create a new book we send the same kind of object as we expect to receive when we get the book so we say schema and then we use the ref and we use the same path again components schemas book and now we can specify the responses we can get 200 if everything is fine description the book was successfully created and the content in this case is on is going to be the created book value so it's going to be a json application slash json and then the schema will again be this reference that we've created earlier ref hash components schemas book and it should start with the capital letter but something can go wrong because we have this tri cage block and we can possibly send the 500 if there was an error so we need to declare it as well and then the description will be some server error all right time to test it let's relaunch the server restart the page and here we go we have the post request we can now create new books let's try it out and we already have an example here because we've specified the example in the schema we don't need the id here so we remove it and we click execute okay and the server so some reason is not responding let's look at our post request handler here for some reason i forgot to actually respond with this data so instead of just returning the recorded book i need to send it using response send and then i send the book let's relaunch the server go back and try to execute it again execute and now we got the response with the id with which the book was actually created ok let's go and define the put request here the definition will be a little bit more complex because now we have both the id in the parameter we have the request body and we have more options for the responses we can get 200 if everything is was fine we can get 404 if the book was not found and something can go wrong and we can get the 500 status so let's define the swagger definition at swagger here we specify the path books id in the curly braces we define the put request the put method the summary is update the book by the id the tags should be books and then we specify the parameters in our case it's only one parameter in path it's the id so the name is id the schema of this parameter is just type it's a string it is required required true and the description is the book id now we also need to define the request body request body it's required so required is true the content is json so the content application json and then we reuse the book definition for the schema schema ref and then you already know how it goes components schemas book after we have the response body defined we can go on with the responses and here we'll have three 200 404 and 500. so if everything is fine then we're expecting to re to get to receive the updated book description the book was updated 404 the description is the book was not found and the 500 means that there was some server error description some error happened and then for 200 response we also want to specify the content the content is going to be application json the schema is the book so we use the ref components schemas book let's relaunch the server and check if it still works you should see the put request here now we have only one request left to describe and it's the delete as you can guess it's done exactly the same way as previous requests you use the add swagger then you specify the route books id you specify the delete method you set the summary remove the book by id set the tags it's going to be the books and then we set the parameters in path name id schema type string actually now that i'm looking at the parameters that we specify in path i believe that we could actually use the components section to define some parameters like reusable path query header and cookie parameters so i think it's a good homework for you to improve this code base and try to re to make a reusable parameter because you see it's all the same inside of the get put and delete requests we're using this parameter that's in the path the book id which is a string so i think it's a good idea to define it it's always required it's always a string acquired true and the description will always always be the same so it's definitely can vary it definitely can be reused description the book id and then we have the responses responses can be 200 if it worked and 404 if we didn't find such book description the book was deleted and the book was not found description the book was not found that's it let's relaunch the server take a look at the ui and it seems to be working thank you for watching if you watch till the end then it probably means that you like my videos and i'd like to ask you a question usually i make my videos using javascript as an example as the example language would you like it more would you prefer if i would use typescript examples because me personally i like typescript more it's more comfortable to me to write typescript than javascript what do you think let me know in the comments would it be better if i would use typescript for the code examples or should i stick to javascript see you next time
Info
Channel: Maksim Ivanov
Views: 44,410
Rating: undefined out of 5
Keywords:
Id: S8kmHtQeflo
Channel Id: undefined
Length: 27min 37sec (1657 seconds)
Published: Sat Jan 09 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.