UNPKG

simple-dynamo

Version:

Abstraction of Amazons Dynamo DB Service. Usage of AWS DynamoDB incredible simple.

428 lines (409 loc) 13.5 kB
// 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);