Edit on GitHub

Build a Server Plugin

Be Hapi and Build a server plugin #

At WalmartLabs, we use Hapi because of its flexible and robust plugin system. It allows us to modularize our application into isolated pieces of business logic and reusable utilities.

Let's make a deal! Actually, scratch that, let's make a plugin! Plugins are way to extend our server's functionality. Building upon our open source theme, let's make a plugin that retrieves our Tech Friends for our "resource party." Let's head back to Your Awesome App.

We are going to use the GitHub Api to grab the latest 10 contributors of our Open Source friends and display them in Your Awesome App.

The GitHub site has great documentation and awesome libraries to help jumpstart our plugin. Let's begin there by installing a Node.js wrapper for the GitHub Api called node-github in Your Awesome App:

$ npm install github

At their core, plugins are a simple register object that has the signature function (server, options, next). Read more about building plugins from scratch in the Hapi documentation.

Navigate to the <your-awesome-app>/server/plugins folder. Make a folder called friends, cd into your new friends folder, and create an empty index.js file:

$ touch index.js

Your Server file pattern should now look like this:

    ├── index.js
    ├── plugins
    │   ├── friends
    │   │   └── index.js
    │   └── webapp
    │       ├── index.html
    │       └── index.js
    └── views
        └── index-view.jsx

Navigate to <your-awesome-app>/server/plugins/friends/index.js. This is where we will make an external API call to Github and request the last ten contributors of our selected Open Source 'friend' using a URL https://api.github.com/ + /repos/:user/:repo/contributors. Our GitHub wrapper library will allow us to use a built in method, github.repos.getContributors({}), to streamline this process and return an array of Open Source contributors. We will also use Bluebird, a Promise library that makes working with our async API calls much more manageable. Copy, paste and save the code below:

"use strict";

//a very simple plugin

const Promise = require("bluebird");
const GitHubApi = require("github");
const github = new GitHubApi();
const AUTH_TOKEN = process.env.token;
  type: "oauth",
  token: AUTH_TOKEN

const githubGetContributors = Promise.promisify(github.repos.getContributors);

exports.register = (server, options, next) => {

  const friendsArr = [ /*eslint-disable max-len */
    {name: "Electrode", img: "//goo.gl/I9utJF", size: 8, github: "https://github.com/electrode-io/electrode"},
    {name: "React", img: "//goo.gl/xwbqlB", size: 8, github: "https://github.com/facebook/react"},
    {name: "Redux", img: "//goo.gl/MGQ3lp", size: 8, github: "https://github.com/reactjs/redux"},
    {name: "node", img: "//goo.gl/hxmCEE", size: 8, github: "https://github.com/nodejs/node"}
  ]; /*eslint-enable max-len */

  const getContributorsPromises = friendsArr.map((friend) => { /*eslint-disable camelcase */
    const githubUrl = friend.github.split("/");
    const githubInfo = {
      repo: githubUrl.pop(),
      owner: githubUrl.pop(),
      anon: true,
      page: 1,
      per_page: 10
    return githubGetContributors(githubInfo)
      .then((response) => {
        friend.friends = response.map(({ login, avatar_url, html_url }) => (
          {name: login, img: avatar_url, profile: html_url}
        return friend;
  }); /*eslint-enable camelcase */

  const getFriendsAndContributors = (reply) => {
    return Promise.all(getContributorsPromises)
      .then((response) => reply(null, JSON.stringify({friends: response})))
      .catch((err) => reply(err));

    method: "GET",
    path: "/friends",
    handler: (request, reply) => getFriendsAndContributors(reply)


exports.register.attributes = {
  name: "getFriends",
  version: "1.0.0"

If you are like us, and you plan on building out Your Awesome App even further, you will need to generate a GitHup Api oAuth token to remove the preset limit for API requests. We have already added the code to accept and use the token in our Hapi server plugin above const AUTH_TOKEN = process.env.token.

Click here to set a new personal access token (you may be prompted to login to your GitHub account if you have not already). Create your own token description in the form given and for Select scopes simply check: public repo. Then hit the green Generate token button.

You will be redirected to the next page where your new token is. Keep your token private and secure; do not copy and paste it directly into your app. Instead, we will set your token as a Node environment variable. Copy and save this token in a secure place; we will use it several times. Use this token in your command line as follows:

Set the token locally:

$ token='your-token-here'

Set your token for heroku deployment:

heroku config:set token='your-token-here'

A great tool for testing your server requests (its user interface for view response objects and errors is incredible) is Postman. For now, you will have to trust as we build out Your Awesome App. Navigate to Intermediate: Add Routes, to add routing to the app and also extend our UI to display our contributor array.