Update for August 2017: This guide has been updated for Restify 5 and Mongo 3.4 with modern Javascript practices. Clone the Github repo to get the full working project.

Choosing the Technology

With the multitude of JavaScript frameworks and databases available nowadays, there are countless options for building APIs. For this guide, we're working with Restify and Mongo. There are a few reasons to choose Restify and Mongo. In essence, we're avoiding potential pitfalls with picking the "shiny new thing" and focussing on the most important factors when it comes to building a REST API: developer experience, performance (and the software -ilities), along with support and availability of knowledge/experience within the JavaScript community. API performance is clearly of high priority and deserves special mention. In this recent performance benchmark, we see Hapi, Express, Koa, and Restify are all in a similar ballpark. This guide uses Restify but it's always worthwhile considering a range of the options and ideally designing and running tests that consider the specific characteristics of the system you're building.

Before we start

Please note that this tutorial assumes that you have an understanding of git, the command line, Node.js and the Node Package Manager (npm). For those of you who would like to see the boilerplate codebase, you can clone the repository from GitHub. If you happen to find any issues, please submit a pull request. You can follow the steps below in order, or deviate away as you’d like… just don’t get lost ;). With that said, let’s get started!

1. Create Your Directory

Inside of a directory of your choice, create a new directory called API. For this tutorial, we’re going to build the API in the user's home directory.

$ cd ~ $ mkdir api && cd api

2. Install Required Dependencies

In addition to the Restify framework, we’ll use a couple of popular Node modules available from the Node Package Manager (npm):

Mongoose: an ODM for MongoDB

Mongoose String Query: lightweight Mongoose plugin to help query your REST API

Mongoose Timestamp: lightweight Mongoose plugin that adds support for createdAt and updatedAt timestamps

Restify Errors: HTTP and REST errors abstracted from Restify

For the rest of the API, we’ll use native Node.js API’s so to keep things nice and clean. First, let’s initialize our own Node.js package. Run the following command and answer the prompts (accepting the default is fine for this demo):

$ npm init

Woohoo! On completion, a file name package.json will be created in the current directory, /api. This file serves as the manifest for your NPM package. Next up, let’s add those Node module dependencies listed above to our package. The following command retrieves and installs the packages in the /node_modules directory. This allows our application to reference and make use of the modules at runtime. Additionally, the modules are added to the 'dependencies' section of our package.json manifest so that our application is 'portable' and can be installed and will run on other machines.

$ npm install restify restify-plugins mongoose mongoose-timestamp mongoose-string-query restify-errors --save

Once the installation is complete, you’ll notice that your package.json is now populated with your dependencies and a new directory called node_modules now exists. You can easily check the contents of the package.json file with the following command:

$ cat package.json

3. Lay the Foundation

Now that we’ve covered the basics, let’s start to lay the foundation for our application. First off, we’ll need to create a MongoDB database to house or data and connect our API to. You have a couple of options here:

Host locally and use a database manager such as Robo 3T (formerly known as Robomongo)

Compose: A cloud platform for MongoDB deployments

MongoDB Atlas: Another cloud service operated by the creators of MongoDB.

Self-host on Google, AWS, or another provider

For sake of simplicity and cost, we’re going to be using a local version of MongoDB and Robo 3T to manage our database. I’m running OS X, so I’ll be using Homebrew to install MongoDB and Robo 3T.

$ brew install mongodb $ brew cask install robo-3t

There are a few additional steps that you’ll need to take in order to get MongoDB up and running 100%. With that said, please have a look at this tutorial by Treehouse. Robo 3T, on the other hand, will be installed in your /Applications directory on your computer. One thing that isn’t covered in the tutorial by Treehouse is how to configure your database settings, so let’s go ahead and do that now:

$ mongo ... MongoDB shell version v3.4.7 connecting to: mongodb://127.0.0.1:27017 MongoDB server version: 3.4.7 > use api > exit

Now that we have MongoDB setup to use the database api, let’s go ahead and get our config.js file created (this will house all of our configuration data for the REST API):

$ touch config.js

Open your config.js file in an editor of your choice, and add the following contents to your file:

module.exports = { name: 'API', env: process.env.NODE_ENV || 'development', port: process.env.PORT || 3000, base_url: process.env.BASE_URL || 'http://localhost:3000', db: { uri: process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/api', }, };

Next, let’s create our index.js file, the entry point for our REST API.

$ touch index.js

Open your index.js and add the following contents to your file:

/** * Module Dependencies */ const config = require('./config'); const restify = require('restify'); const mongoose = require('mongoose'); const restifyPlugins = require('restify-plugins'); /** * Initialize Server */ const server = restify.createServer({ name: config.name, version: config.version, }); /** * Middleware */ server.use(restifyPlugins.jsonBodyParser({ mapParams: true })); server.use(restifyPlugins.acceptParser(server.acceptable)); server.use(restifyPlugins.queryParser({ mapParams: true })); server.use(restifyPlugins.fullResponse()); /** * Start Server, Connect to DB & Require Routes */ server.listen(config.port, () => { // establish connection to mongodb mongoose.Promise = global.Promise; mongoose.connect(config.db.uri, { useMongoClient: true }); const db = mongoose.connection; db.on('error', (err) => { console.error(err); process.exit(1); }); db.once('open', () => { require('./routes')(server); console.log( Server is listening on port ${config.port} ); }); });

As you can see from the entry point code above, we are very specific in the order that we include resources.

1. Module dependencies (These are our NPM modules that we installed) 2. Server initialization (Where we setup the server instance using values from our config) 3. Middleware (Standard middleware, included by default by Restify. More documentation can be found on the Restify website at:



http://restify.com/docs/plugins-api/

4. Start server and require in routes (Bind to port, initialize database connection and require in routes for route handling)

4. Create Your Database Models

Models are fancy constructors compiled from our Schema definitions. Basically, they allow us to tell the database what to store and instances of these models represent documents which can be saved and retrieved from our database via Mongoose. All document creation and retrieval from the database is handled by these models, so let’s go ahead and create our todo model:

$ mkdir models && cd models $ touch todo.js

Next up, let’s define our schema:

const mongoose = require('mongoose'); const mongooseStringQuery = require('mongoose-string-query'); const timestamps = require('mongoose-timestamp'); const TodoSchema = new mongoose.Schema( { task: { type: String, required: true, trim: true, }, status: { type: String, required: true, enum: ['pending', 'complete', 'in progress', 'overdue'], default: 'pending', }, }, { minimize: false }, ); TodoSchema.plugin(timestamps); TodoSchema.plugin(mongooseStringQuery); const Todo = mongoose.model('Todo', TodoSchema); module.exports = Todo;