Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
One of my favorite parts of my job as a Developer Evangelist at Stream is building sample applications. It is an enthralling way to engage and interact with potential and existing customers, as well as show off the fun technology we use and build with every single day. The applications I build range from small code snippets outlining how to perform basic operations, such as marking an item as âreadâ in Stream, to large microservice based applications that generally require robust backend architectures, like Winds.
Last year, I created a post on how to build a RESTful API with Restify. Now that Express and Restify are nearly neck and neck in terms of requests per second, I thought it might be interesting to show you how I go about structuring my APIs with Express (just to toss in a little friendly competition / play devil-operâs advocate đ).
Structuring Your API
The way you choose to structure your API is one of the most important decisions youâll make. You must ensure that itâs smart, flexible, and easy to useâââthis is a must. If itâs not easy to use, other developers will not understand what youâre building nor will they be able to figure out how to build on top of it. Think before you build (I know. Planning sucks. Especially when you are excited to get going, but it *pays off*).
âââ build.sh âââ dist â âââ ⊠âââ package.json âââ src â âââ config â â âââ index.js â âââ controllers â â âââ ⊠â âââ models â â âââ ⊠â âââ package.json â âââ routes â â âââ ⊠â âââ server.js â âââ utils â â âââ âŠ
All source code is stored in /src. It compiles down from ES6+ to ES5 into the /dist directory for execution on the server. Youâre probably asking yourself why youâd take the extra step to write in something that is just going to be compiled down? Good question. ES6+ standards provide some pretty killer additional functionalities, such as arrow functions, modified scoping, destructuring, rest/spread parameter handling, and more!
Letâs have a look at the compilation that takes place in the build.sh file:
That is ALL you need to be able to write in a super awesome language while having it still be supported in all the usual places! That said, the code above *may* look like gibberish, so letâs break it down đ€:
- #!/bin/bash
- Denotes that this is an executable bash file
2. rm -rf dist && mkdir dist
- Removes the /dist directory if it exists (cleanup).
- Creates a new /dist directory.
3. npx babel srcâââout-dir distâââignore node_modules
- Compiles every file to ES5 and moves the files to the /dist directory, with the exception of node_modules (those are already compiled).
4. cp src/package.json dist
- By design, npx doesnât migrate json files, so we need to copy it ourselves using the cp command.
5. cd dist && yarn installâââproductionâââmodules-folder node_modules
Move into the /dist directory and install the npm modules using yarn
Running the build is as simple as running the following command from your terminal:
Note: You will need to ensure that the build.sh file is executable⊠OR if you are like me and enjoy automating everything, you can create an npm script like so:
Which can be executed by running the following from your terminal:
The Main File
The following file, server.js, contains the most important logic and sits on the top-level of our codebase. The beginning portion imports all of the necessary npm modules, followed by our config and logger utility.
Next, we take advantage of the Express use method to invoke several of our imported middleware libraries (cors, compression, and our body-parser). **Please note** that there are several other middleware libraries that we include for additional functionality (e.g. email, logging, jwt authentication, etc.). Last but not least, after a bit of initialization, we dynamically include all routes and pass the API context to the route for binding.
Note: The customer logger module can be used with most logging services (Papertrail, Loggly, etc.). For this demo, as well as other projects, I like to use Papertrail. You may need to adjust the settings and ENV variables if you use something other than Papertrail.
Routing
To keep things tidy and organized, all routing logic (e.g. GET /users) is kept in its own route file inside of a /routes directory.
As you can see, the contents of the route file above hold all references to the controllers for GET, POST, PUT, and DELETE operations. This works because we import and reference the User Controller, passing along the necessary parameters and/or data with every APIÂ call.
Controllers
Controllers include the database model associated with the data that they will be handling, receiving data from the routes, and then making an informed decision on how to handle the data. Finally, the controllers communicate through the models which then talk to the database, and return a status code with a payload.
If youâre a visual person, a production instance should look a little something like this:
And, the code for an example user controller would look like this:
Mongoose Models (MongoDB)
Mongoose is a wonderful ODM (Object Data Modeling) library for Node.js and MongoDB. If youâre familiar with the reference ORM (Object Resource Mapping) and libraries for Node.js, such as Sequelize and Bookshelf, Mongoose is pretty straightforward. The massive benefit with Mongoose is how easy it is to structure MongoDB schemasâââthereâs no need to fuss around with custom business logic.
Whatâs even more exciting are the many goodies like middleware, plugins, object population, and schema validation either baked in, or one yarn (I love yarn) or one npm install away. Itâs truly remarkable how popular the project has become among developers who use MongoDB.
When it comes to Mongoose models, I tend to keep things somewhat flat (or at least a maximum of 3 deeply nested objects) to avoid confusion. Hereâs an example of a user model pulled directly from a project currently under development here at Stream:
Note: When it comes to hosting and running MongoDB, I like to use MongoDB Atlas. Itâs a database as a service provided by the makers of MongoDB themselves. If you donât want to use a free MongoDB Atlas instance, youâre welcome to use a local version. Additionally, if you want to monitor your data, MongoDB Compass is an excellent choice!
Utilities
Custom utilities can be used for a variety of thingsâââbasically, anything you want. I generally reserve them for separating concerns and keeping my code clean. Some examples include establishing database connections, sending emails, logging to an external service, and even communicating with HTTP based service here at Stream.
Iâm often asked the question of when to turn something into a utility and my answer is always the same⊠When you find yourself 1) reusing code OR 2) jamming third-party services into code where it just doesnât feel right.
Hereâs an example of a utility I wrote to help called the Stream Personalization REST API. This integration was completed in about a dozen lines of code:
The code above can now be called from any file like so:
Final Thoughts
APIs are the building blocks of modern applications. They govern how an application can talk to another, as well as to the database. While we have other flavors of API structures (GraphQL, etc.), RESTful APIs continue to pull their own weight and arenât going anywhere soon.
If youâre interested in seeing a fully built out skeleton for a REST API built with Node.js, Express, Mongoose, and MongoDB, head over to this GitHub repo.
As always, if you have any questions, please donât hesitate to reach out to me on Twitter or below in the comments. Thank you!
Building a Node.js Powered API with Express, Mongoose & MongoDB was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.