simple-dynamo
Version:
Abstraction of Amazons Dynamo DB Service. Usage of AWS DynamoDB incredible simple.
428 lines (409 loc) • 13.5 kB
JavaScript
// Generated by CoffeeScript 1.10.0
(function() {
var Attributes, Helper, _, exports, type, utils,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
_ = require("underscore");
utils = require("./utils");
type = require("type-detect");
Helper = {
val2dyn: function(value) {
var _v, _vs, i, len;
switch (type(value)) {
case "number":
return {
N: String(value)
};
case "string":
return {
S: value
};
case "object":
case "map":
return {
M: Helper.obj2dyn(value)
};
case "boolean":
return {
BOOL: value.toString()
};
case "buffer":
return {
B: value.toString('base64')
};
}
if ((value != null ? value[0] : void 0) != null) {
switch (type(value[0])) {
case "number":
return {
NN: value.map(String)
};
case "string":
return {
SS: value
};
default:
_vs = [];
for (i = 0, len = value.length; i < len; i++) {
_v = value[i];
_vs.push(Helper.val2dyn(_v));
}
return {
L: _vs
};
}
}
throw new Error("Invalid key value type.");
},
dyn2val: function(data) {
var _v, _vs, i, len, name, value;
name = Object.keys(data)[0];
value = data[name];
switch (name) {
case "S":
case "SS":
return value;
case "N":
return Number(value);
case "NS":
return value.map(Number);
case "BOOL":
case "NULL":
if (["true", "TRUE", "True", "t", "T", "1", "ok", "OK", "yes", "YES", "Yes", true, 1].indexOf(value) >= 0) {
return true;
} else {
return false;
}
break;
case "B":
return new Buffer(value, "base64");
case "M":
return Helper.dyn2obj(value);
case "L":
_vs = [];
for (i = 0, len = value.length; i < len; i++) {
_v = value[i];
_vs.push(Helper.dyn2val(_v));
}
return _vs;
default:
throw new Error("Invalid data type: " + name);
}
},
obj2dyn: function(attrs) {
var obj;
obj = {};
Object.keys(attrs).forEach(function(key) {
return obj[key] = Helper.val2dyn(attrs[key]);
});
return obj;
},
dyn2obj: function(data) {
var obj;
obj = {};
Object.keys(data).forEach(function(key) {
return obj[key] = Helper.dyn2val(data[key]);
});
return obj;
}
};
Attributes = (function() {
function Attributes(raw, table1) {
this.raw = raw;
this.table = table1;
this._fixPredicate = bind(this._fixPredicate, this);
this.fixPredicates = bind(this.fixPredicates, this);
this.getQuery = bind(this.getQuery, this);
this.updateAttrsFn = bind(this.updateAttrsFn, this);
this.validateAttributes = bind(this.validateAttributes, this);
this.get = bind(this.get, this);
this.prepare = bind(this.prepare, this);
this.prepare();
return;
}
Attributes.prototype.prepare = function() {
var _attr, _hKey, _outE, _rKey, i, len, ref;
this.attrs || (this.attrs = {});
this._required_attrs = [];
_hKey = this.table.hashKey;
_rKey = this.table.rangeKey;
ref = this.raw;
for (i = 0, len = ref.length; i < len; i++) {
_attr = ref[i];
if (_attr.required) {
this._required_attrs.push(_attr.key);
}
_outE = _.clone(_attr);
if (_outE.key === _hKey) {
_outE.isHash = true;
}
if (_outE.key === _rKey) {
_outE.isRange = true;
}
this.attrs[_outE.key] = _outE;
}
if (!this.attrs[_hKey]) {
this.attrs[_hKey] = {
key: _hKey,
isHash: true,
type: this.table.hashKeyType,
required: true
};
}
if (this.table.hasRange && !this.attrs[_rKey]) {
this.attrs[_rKey] = {
key: _rKey,
isRange: true,
type: this.table.rangeKeyType,
required: true
};
}
};
Attributes.prototype.get = function(key) {
return this.attrs[key] || null;
};
Attributes.prototype.validateAttributes = function(isCreate, attrs, cb) {
var _attr, error, key, val;
if (!utils.params(attrs, this._required_attrs)) {
error = new Error;
error.name = "validation-error";
error.message = "Missing key. Please make sure to add all required keys ( " + this._required_attrs + " )";
this.table._error(cb, error);
} else {
for (key in attrs) {
val = attrs[key];
_attr = this.get(key);
if (_attr) {
switch (_attr.type) {
case "map":
case "object":
if ((!isCreate && val !== null) && !_.isObject(val)) {
error = new Error;
error.name = "validation-error";
error.message = "Wrong type of `" + key + "`. Please pass this key as a `Object`";
this.table._error(cb, error);
return;
}
break;
case "string":
if ((!isCreate && val !== null) && !_.isString(val)) {
error = new Error;
error.name = "validation-error";
error.message = "Wrong type of `" + key + "`. Please pass this key as a `String`";
this.table._error(cb, error);
return;
}
break;
case "number":
if ((!isCreate && val !== null) && !(_.isNumber(val) || (val["$add"] != null))) {
error = new Error;
error.name = "validation-error";
error.message = "Wrong type of `" + key + "`. Please pass this key as a `Number`";
this.table._error(cb, error);
return;
}
break;
case "array":
if (isCreate) {
if (val === null) {
delete attrs[key];
} else if (!_.isArray(val)) {
error = new Error;
error.name = "validation-error";
error.message = "Wrong type of `" + key + "`. Please pass this key as an `Array`";
this.table._error(cb, error);
return;
} else if (val.length === 0) {
delete attrs[key];
}
} else {
if (val !== null && !((val["$add"] != null) || (val["$rem"] != null) || (val["$reset"] != null)) && !_.isArray(val)) {
error = new Error;
error.name = "validation-error";
error.message = "Wrong type of `" + key + "`. Please pass this key as an `Array` or an Object of actions";
this.table._error(cb, error);
return;
}
}
}
}
}
cb(null, attrs);
}
};
Attributes.prototype.updateAttrsFn = function(_new, options) {
var self;
if (options == null) {
options = {};
}
self = this;
return function() {
var _attr, _k, _tbl, _v, _vA;
_tbl = self.table;
for (_k in _new) {
_v = _new[_k];
if (!(_k !== _tbl.hashKey)) {
continue;
}
_attr = self.get(_k);
if (((_attr != null ? _attr.type : void 0) === "array" || (!_attr && (_v != null) && ((_v["$add"] != null) || (_v["$rem"] != null) || (_v["$reset"] != null)))) && !_.isArray(_v)) {
if (_v === null) {
this.remove(_k);
} else {
if (_v["$add"] != null) {
_vA = (_.isArray(_v["$add"]) ? _v["$add"] : [_v["$add"]]);
if (_vA.length) {
this.add(_k, _vA);
}
}
if (_v["$rem"] != null) {
_vA = (_.isArray(_v["$rem"]) ? _v["$rem"] : [_v["$rem"]]);
if (_vA.length) {
this.remove(_k, _vA);
}
}
if (_v["$reset"] != null) {
_vA = (_.isArray(_v["$reset"]) ? _v["$reset"] : [_v["$reset"]]);
if (_vA.length) {
this.put(_k, _vA);
}
}
}
} else if ((_attr != null ? _attr.type : void 0) === "number" && ((_v != null ? _v["$add"] : void 0) != null)) {
if ((_v != null ? _v["$add"] : void 0) != null) {
this.add(_k, _v["$add"]);
}
} else {
if ((_attr != null ? _attr.type : void 0) === "string" && _.isString(_v) && !_v.length) {
this.remove(_k);
} else if (_v === null || (_.isArray(_v) && !_v.length)) {
this.remove(_k);
} else {
this.put(_k, _v);
}
}
}
};
};
Attributes.prototype.getQuery = function(table, query, startAt, options) {
var _q, isScan, ref, ref1;
if (options == null) {
options = {};
}
ref = this.fixPredicates(query), _q = ref[0], isScan = ref[1];
if (isScan) {
if (this.table.mng.options.scanWarning) {
console.warn("WARNING! Dynamo-Scan on `" + table.TableName + "`. Query:", _q);
}
_q = table.scan(_q);
} else {
_q = table.query(_q);
if (!(options != null ? options.forward : void 0)) {
_q.reverse();
}
}
if (startAt != null) {
_q.startAt(startAt);
}
if ((options != null ? options.limit : void 0) != null) {
_q.limit(options.limit);
}
if (options != null ? (ref1 = options.fields) != null ? ref1.length : void 0 : void 0) {
_q.get(options != null ? options.fields : void 0);
}
return [_q, isScan];
};
Attributes.prototype.fixPredicates = function(predicates) {
var _attr, _fixed, _predCount, isScan, key, predicate;
if (predicates == null) {
predicates = {};
}
_fixed = {};
isScan = !this.table.hasRange;
_predCount = Object.keys(predicates).length;
if (_predCount) {
for (key in predicates) {
predicate = predicates[key];
_attr = this.get(key);
if (_attr) {
if (!_attr.isHash && !_attr.isRange) {
isScan = true;
}
_fixed[key] = this._fixPredicate(predicate, _attr);
}
}
if (!isScan && !utils.params(_fixed, [this.table.hashKey, this.table.rangeKey])) {
isScan = true;
}
} else {
isScan = true;
}
return [_fixed, isScan];
};
Attributes.prototype._fixPredicate = function(predicate, _attr) {
var _a, _arrayAcceptOps, _op, _ops, _v, i, len, ref, val;
_ops = Object.keys(predicate);
_arrayAcceptOps = ["<=", ">=", "in"];
if (_ops.length === 1) {
_op = _ops[0];
if (_.isArray(predicate[_op]) && indexOf.call(_arrayAcceptOps, _op) >= 0) {
_a = [];
ref = predicate[_op];
for (i = 0, len = ref.length; i < len; i++) {
val = ref[i];
_v = this._fixPredicateValue(val, _attr.type);
if (_v) {
_a.push(_v);
}
}
predicate[_op] = _a;
} else if (!_.isArray(predicate[_op])) {
_v = this._fixPredicateValue(predicate[_op], _attr.type);
if (_v) {
predicate[_op] = _v;
}
} else {
throw new Error("Malformed query. Arrays only allowed for `" + _arrayAcceptOps);
}
} else {
throw new Error("Malformed query. Only exact one query operator will be accepted per key");
}
return predicate;
};
Attributes.prototype._fixPredicateValue = function(value, type) {
var _vt;
if (type == null) {
type = "string";
}
_vt = typeof value;
switch (type) {
case "string":
case "S":
if ((value != null) && (_vt !== "string" && _vt !== "undefined")) {
return value.toString();
} else {
return value;
}
break;
case "number":
case "N":
if ((value != null) && (_vt !== "number" && _vt !== "undefined")) {
return parseFloat(value, 10);
} else {
return value;
}
break;
case "boolean":
case "B":
if (_vt !== "boolean" && _vt !== "undefined") {
return Boolean(value);
} else {
return value;
}
}
};
return Attributes;
})();
exports = module.exports = Attributes;
exports.helper = Helper;
}).call(this);