dynamodb-data-types
Version:
A utility to help represent Amazon DynamoDB Data Types.
225 lines (188 loc) • 5.19 kB
JavaScript
var isArray = require('./util').isArray;
var errs = require('./errs');
// var DEBUG = false;
var __preserveArrays = false;
function _preserveArrays() {
__preserveArrays = true;
}
function test(arr, fn) {
for (var i = 0; i < arr.length; i++) {
if (!fn(arr[i]))
return false;
}
return true;
}
function isnumber(el) {
return typeof el === 'number' || el instanceof Number;
}
function isstring(el) {
return typeof el === 'string' || el instanceof String;
}
function isbinary(el) {
if (el instanceof Buffer)
return true;
return false;
}
function detectType(val) {
if (isArray(val)) {
var arr = val;
if (test(arr, isnumber))
return 'NS';
if (test(arr, isstring))
return 'SS';
if (test(arr, isbinary))
return 'BS';
return 'L';
}
if (isstring(val))
return 'S';
if (isnumber(val))
return 'N';
if (isbinary(val))
return 'B';
if (val === null)
return 'NULL';
if (typeof val === 'boolean')
return 'BOOL';
if (typeof val === 'object') {
return 'M';
}
}
function explicit_type(opts, key) {
var type_specified = typeof opts === 'object' &&
typeof opts.types === 'object' &&
typeof key === 'string' &&
typeof opts.types[key] === 'string';
if (!type_specified)
return;
var type = opts.types[key];
if (typeExists(type))
return type;
}
var MULTIPLES = ['L', 'BS', 'NS', 'SS'];
function getType(val, opts, key) {
var explicit = explicit_type(opts, key);
var detected = detectType(val);
var type = detected;
if (isArray(val) && __preserveArrays)
type = 'L';
if (MULTIPLES.indexOf(explicit) > -1 && MULTIPLES.indexOf(detected) > -1)
type = explicit;
return type;
}
function eachToString(arr) {
return arr.map(function(v) {
return v.toString();
});
}
/**
* Wrap a single value into DynamoDB's AttributeValue.
* @param {String|Number|Array} val The value to wrap.
* @return {Object} DynamoDB AttributeValue.
*/
function wrap1(val, opts, key) {
switch(getType(val, opts, key)) {
case 'B': return {'B': val};
case 'BS': return {'BS': val};
case 'N': return {'N': val.toString()};
case 'NS': return {'NS': eachToString(val)};
case 'S': return {'S': val.toString()};
case 'SS': return {'SS': eachToString(val)};
case 'BOOL': return {'BOOL': val ? true: false};
case 'L': return {'L': val.map(function(obj){ return wrap1(obj, opts); })};
case 'M': return {'M': wrap(val, opts)};
case 'NULL': return {'NULL': true};
default: return;
}
}
/**
* Wrap object properties into DynamoDB's AttributeValue data type.
* @param {Object} obj The object to wrap.
* @return {Object} A DynamoDb AttributeValue.
*/
function wrap(obj, opts) {
var result = {};
for (var key in obj) {
if(obj.hasOwnProperty(key)) {
var wrapped = wrap1(obj[key], opts, key);
if (typeof wrapped !== 'undefined')
result[key] = wrapped;
}
}
return result;
}
var unwrapFns = {
'B': undefined,
'BS': undefined,
'N': function (o) { return Number(o); },
'NS':function (arr) { return arr.map(function(o) {return Number(o);}); },
'S': undefined,
'SS': undefined,
'BOOL': undefined,
'L': function(val) { return val.map(unwrap1); },
'M': function (val) { return unwrap(val); },
'NULL': function() { return null; }
};
function typeExists(type) {
return unwrapFns.hasOwnProperty(type);
}
/**
* Unwrap a single DynamoDB's AttributeValue to a value of the appropriate
* javascript type.
* @param {Object} attributeValue The DynamoDB AttributeValue.
* @return {String|Number|Array} The javascript value.
*/
function unwrap1(dynamoData) {
var keys = Object.keys(dynamoData);
if (keys.length !== 1)
throw new Error('Unexpected DynamoDB AttributeValue');
var typeStr = keys[0];
if (!unwrapFns.hasOwnProperty(typeStr))
throw errs.NoDatatype;
var val = dynamoData[typeStr];
return unwrapFns[typeStr] ? unwrapFns[typeStr](val) : val;
}
/**
* Unwrap DynamoDB AttributeValues to values of the appropriate types.
* @param {Object} attributeValue The DynamoDb AttributeValue to unwrap.
* @return {Object} Unwrapped object with properties.
*/
function unwrap(attrVal) {
var result = {};
for (var key in attrVal) {
if(attrVal.hasOwnProperty(key)) {
var value = attrVal[key];
if (value !== null && typeof value !== 'undefined')
result[key] = unwrap1(attrVal[key]);
}
}
return result;
}
// function printData(input, result, title) {
// if (DEBUG) {
// console.log(title + ' input:');
// console.log(JSON.stringify(input, undefined, 2));
// console.log(title + ' result:');
// console.log(JSON.stringify(result, undefined, 2));
// }
// return result;
// }
function wrapDebug(obj, opts) {
var wrapped = wrap(obj, opts);
// if (DEBUG)
// printData(obj, wrapped, 'wrap');
return wrapped;
}
function unwrapDebug(attrVal) {
var unwrapped = unwrap(attrVal);
// if (DEBUG)
// printData(attrVal, unwrapped, 'unwrap');
return unwrapped;
}
module.exports = {
wrap: wrapDebug,
unwrap: unwrapDebug,
wrap1: wrap1,
unwrap1: unwrap1,
_preserveArrays: _preserveArrays
};