Single Page Application Demo With Hapi.js, AngularJS And Azure Table
In my previous post Building an API in Node.js Using Hapi.js and Azure Table, we discussed about building an API in Node.js using Hapi.js as web development framework and Azure Table as the storage mechanism. This app has been updated with a Single Page Application (SPA) client, built with AngularJS. The updated app is available on github at https://github.com/shijuvar/HapiAzure.
About the Demo App
I have developed this simple app for my personal use for just adding bookmarks with priority range from 1 to 5. I mainly created this for following github repositories with a priority so tat I can look on these bookmarks and evaluate it later based on the priority.
Here’s the technology stack used for the demo app:
- REST API – Node.js and Hapi.js
- Data Persistence – Microsoft Azure Table
- Web App – AngularJS
The following Node.js modules are using for building the REST API.
- hapi – HTTP Server framework, used for building the REST API app.
- azure - Windows Azure Client Library for node, used for persisting data onto Azure Table storage.
- joi - Object schema validation module for Hapi.js.
- node-uuid – Generating unique id for Node.
Here’s the few screenshots of the app running as a Chrome app
API Endpoints
Currently, the API provides the following endpoints:
Path | Method | Functionality |
/bookmarks | Get | Returns all bookmarks information from the Azure Table storage |
/bookmarks/{rowkey} | Get | Get a single bookmark data for the given rowkey of Azure Table |
/bookmarks | Post | Create new bookmark item onto Azure Table |
/bookmarks/{rowkey} | Put | Update an existing bookmark item |
/bookmarks/{rowkey} | Delete | Delete a bookmark item from the Azure Table |
In the API project, the API endpoints are defined in the app.js file of routes folder
var Joi = require("joi");
var azure = require('azure');
var BookmarkController=require('./../controllers/bookmark');
var AzureTable=require('./../lib/azuretable');
var nconf = require('nconf');
nconf.env().file({ file: 'config.json'});
var tableName = nconf.get("TABLE_NAME");
var partitionKey = nconf.get("PARTITION_KEY");
var accountName = nconf.get("STORAGE_NAME");
var accountKey = nconf.get("STORAGE_KEY");
var tableService = azure.createTableService
(accountName, accountKey);
var azureTable = new AzureTable(azure.createTableService(
accountName, accountKey), tableName, partitionKey);
var bookmarkController = new BookmarkController(azureTable);
var routes =
[
{
method: 'GET',
path: '/bookmarks',
config: {
handler: bookmarkController.getBookmarks
.bind(bookmarkController)
}
},
{
method: 'GET',
path: '/bookmarks/{rowkey}',
config: {
handler: bookmarkController.getBookmarkById
.bind(bookmarkController)
}
},
{
method: 'POST',
path: '/bookmarks',
config: {
handler: bookmarkController.insertBookmark
.bind(bookmarkController),
validate: {
payload: {
title: Joi.string(),
desc: Joi.string(),
location: Joi.string(),
priority: Joi.number().integer().min(1).max(5)
} }
}
},
{
method: 'PUT',
path: '/bookmarks/{rowkey}',
config: {
handler: bookmarkController.updateBookmark
.bind(bookmarkController),
validate: {
payload: {
title: Joi.string(),
desc: Joi.string(),
location: Joi.string(),
priority: Joi.number().integer().min(1).max(5)
} }
}
},
{
method: 'DELETE',
path: '/bookmarks/{rowkey}',
config: {
handler: bookmarkController.deleteBookmark
.bind(bookmarkController)
}
}
];
module.exports.routes = function (server) {
server.route(routes);
};
REST API Mapping with AngularJS
The AngularJS service $resource is used for interacting with REST API services. The Angular service $resource is designed for working REST endpoints which lets the developers easily consuming RESTful server-side data sources.
bookmarkApp.factory("bookmarkService", ["$resource",
function ($resource) {
var baseUri='http://localhost:3000/bookmarks/';
var Bookmarks = $resource(baseUri+':rowkey',
{ rowkey: '@RowKey' }, { 'update': { method: 'PUT'} });
var getAllBookmarks = function () {
return Bookmarks.query();
};
var addNewBookmark = function (newBookmark) {
return Bookmarks.save(newBookmark);
};
var updateBookmark = function (bookmark) {
return Bookmarks.update(bookmark);
};
var getBookmarkByRowKey = function (rowKey) {
return Bookmarks.get({rowkey:rowKey});
};
var deleteBookmark = function (rowKey) {
return Bookmarks.delete({rowkey:rowKey});
};
return {
getAll: getAllBookmarks,
addNew: addNewBookmark,
update: updateBookmark,
getByKey: getBookmarkByRowKey,
remove: deleteBookmark
};
} ]);
Data Persistence with Microsoft Azure Table Storage
The Node.js module azure uses for working Azure Table storage. The code block below provides the implementations of CRUD operations against the Azure Table storage.
"use strict";
var azure = require('azure');
var uuid = require('node-uuid');
module.exports = AzureTable;
function AzureTable(storageClient, tableName, partitionKey) {
this.storageClient = storageClient;
this.tableName = tableName;
this.partitionKey = partitionKey;
this.storageClient.createTableIfNotExists(tableName,
function tableCreated(error) {
if(error) {
throw error;
}
});
};
AzureTable.prototype = {
find: function (query, callback) {
var self = this;
self.storageClient.queryEntities(query,
function entitiesQueried(error, entities) {
if (error) {
callback(error);
} else {
callback(null, entities);
}
});
},
addItem: function (item, callback) {
var self = this;
item.RowKey = uuid();
item.PartitionKey = self.partitionKey;
self.storageClient.insertEntity(self.tableName, item,
function entityInserted(error) {
if (error) {
callback(error);
}
callback(null);
});
},
updateItem: function (item, callback) {
var self = this;
self.storageClient.updateEntity(self.tableName, item,
function entityUpdated(error) {
if (error) {
callback(error);
}
callback(null);
});
},
deleteItem: function (rowKey, callback) {
var self = this;
self.storageClient.deleteEntity(self.tableName
, {
PartitionKey : self.partitionKey
, RowKey : rowKey
}
,function entityDeleted(error) {
if (error) {
callback(error);
}
callback(null);
});
}
}
Source Code
The demo app is available at https://github.com/shijuvar/HapiAzure
Creating Free Trial Account in Microsoft Azure
This demo app uses Microsoft Azure Storage which need a subscription in Azure. You will get free one month trial account in Azure which also provides free $200 credits to spending on all Azure services. You will get the free trial account from here.
You can follow me on Twitter @shijucv