MaximeFrancoeur
3/30/2015 - 12:08 PM

sample.js


var AWS   = require("aws-sdk");
var DOC   = require("dynamodb-doc");
var path  = require('path');
var util  = require('util');
var _     = require('lodash');
var async = require('async');

var internals = {};

internals.tableName = "elasticauth-Accounts";

internals.createDynamoDocClient = function () {

  var config = path.resolve(__dirname, '..', 'credentials.json');
  AWS.config.loadFromPath(config);

  var awsClient = new AWS.DynamoDB();

  var service = new DOC.DynamoDB(awsClient);

  var setupLowLevelRequestListeners = service.setupRequestListeners;
  service.setupRequestListeners = function(request) {
    setupLowLevelRequestListeners.call(this, request);
    request._events.validate.unshift(internals.formatDateInput);
    request.on("extractData", internals.formatDateOutput);
  };

  return service;
};

internals.formatDateInput = function (request) {

  var formatter = function (data) {
    return _.mapValues(data, function(value) {
      var result = value;
      if(_.isPlainObject(value)) {
        result = formatter(value);
      } else if (_.isDate(value)) {
        result = value.toISOString();
      }

      return result;
    });
  };

  request.params = formatter(request.params);

  //console.log(util.inspect(request.params, { showHidden: true, depth: null }));
};

internals.isoDateTimeRegex = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/;

internals.formatDateOutput = function (response) {

  var formatter = function (data) {
    return _.mapValues(data, function(value) {
      var result = value;
      if(_.isPlainObject(value)) {
        result = formatter(value);
      } else if (_.isString(value) && internals.isoDateTimeRegex.exec(value)) {
        result = new Date(value);
      }

      return result;
    });
  };

  if(response.data) {
    response.data = formatter(response.data);
  }

  //console.log('output', util.inspect(response.data, { showHidden: true, depth: null }));
};


internals.debugOutput = function (action, callback) {
  callback = callback || _.noop;

  return function (err, data) {
    if (err) {
      console.log(action + ' failed', err, err.stack);
      return callback(err);
    } else {
      console.log(action + ' completed', util.inspect(data, { showHidden: true, depth: null }));
      return callback(null, data);
    }
  };
};

internals.insertAccount = function (db, callback) {
  var params = {};
  params.TableName = internals.tableName;
  params.Item = {
    AccountId : '12345',
    email     : 'foo@bar.com',
    pic       : db.StrToBin('http://example.com/pic.jpg'),
    totalLogins : 0,
    created : new Date()
  };

  //params.ConditionExpression =  "AccountId <> :a",
  //params.ExpressionAttributeValues = {":a" : '12345'};
  db.putItem(params, internals.debugOutput('insertAccount', callback));
};

internals.updateAccount = function (db, id, callback) {
  var params = {};
  params.TableName = internals.tableName;
  params.Key = {AccountId : id};

  params.ReturnValues = 'ALL_NEW';
  params.UpdateExpression = "add #a :x";
  params.ConditionExpression = "#a < :MAX OR attribute_not_exists(#a)";
  params.ExpressionAttributeNames = {"#a" : "totalLogins"};
  params.ExpressionAttributeValues = {
    ":x" : 1,
    ":MAX" : 5
  };

  db.updateItem(params, internals.debugOutput('updateAccount', callback));
};

internals.getAccount = function (db, id, callback) {
  var params = {};
  params.Key = {AccountId : id};
  params.TableName = internals.tableName;
  params.ConsistentRead = true;

  db.getItem(params, internals.debugOutput('getAccount', callback));
};

var db = internals.createDynamoDocClient();

async.series([
  async.apply(internals.insertAccount, db),
  async.apply(internals.getAccount, db, '12345'),
  async.apply(internals.updateAccount, db, '12345')
], function (err) {
  if(err) {
    console.log('database error', err);
  } else {
    console.log('database operations finished successfully');
  }
});