dynoga
Version:
**Dynoga** is a light library for use DynamoDB with javascript objects
151 lines (129 loc) • 4.39 kB
text/coffeescript
typeUtil = require "./typeUtil"
AWS = require "aws-sdk"
_ = require "lodash"
Flat = require "flat"
flatten = Flat.flatten
unflatten = Flat.unflatten
class Dynoga
constructor: (options) ->
@dynamo = new AWS.DynamoDB options
# Create an item
#
# @param {String} table
# @param {Object} item - New item (with primary keys)
# @return {Error}
# @return {Object} new item
create: (table, item, callback) ->
# Generate an id if undefined
item.id = do Date.now().toString unless item.id
# Generate a private attribute for future array order
item._createTimeStamp = do Date.now
dynamoItem = typeUtil.packObjectOrArray item
@dynamo.putItem
TableName: table
Item: dynamoItem
(err, data) ->
delete item._createTimeStamp
callback? err, item
# Read one or many item(s)
#
# @param {String} table
# @param {Object} keys - ex: {key1: "plop", key2: "rafiki"}
# @return {Error}
# @return {Object|Array} one item or list of items
read: (table, keys, callback) ->
keysLength = _.toArray(keys).length
keyConditions = typeUtil.objectToQuery keys
@dynamo.query
TableName: table
KeyConditions: keyConditions
(err, data) ->
result = typeUtil.unpackObjectOrArray data
if result? and keysLength is 2 then result = result[0]
callback? err, typeUtil.sortAndClean result
# Update one item
#
# @param {String} table
# @param {Object} item to update (with primary keys)
# @return {Error}
# @return {Object} item after udpate
update: (table, item, callback) ->
# Extract keys from item
@_findKeys table, (err, keys) =>
if err
callback? err
return
objectKey = {}
objectKey[keys[0]] = item[keys[0]]
objectKey[keys[1]] = item[keys[1]]
dynamoKey = typeUtil.packObjectOrArray objectKey
delete item[keys[0]]
delete item[keys[1]]
dynamoItem = typeUtil.formatForUpdate item
@read table, objectKey, (err, data) =>
# Extract old objects key into database
oldKeys = [] # ex: toto.choco
for key, value of flatten data
if /\./.test key then oldKeys.push key
# Extract objects to update
updatedKeys = [] # ex: toto
for key, value of dynamoItem
if /\./.test key then updatedKeys.push key.split(".")[0]
updatedKeys = _.uniq updatedKeys
# Prepare with defaults objects to delete
updateQuery = {}
for i in updatedKeys
for j in oldKeys
regex = new RegExp "^" + i + "\." # string beginning by `{{key}}.`
if regex.test j
updateQuery[j] =
Action: "DELETE"
# Prepare final query
for key, value of dynamoItem
updateQuery[key] = value
@dynamo.updateItem
TableName: table
Key: dynamoKey
AttributeUpdates: updateQuery
ReturnValues: "ALL_NEW"
(err, data) =>
if err then callback err
callback? err, typeUtil.sortAndClean typeUtil.unpackObjectOrArray data
# Delete one item
#
# @param {String} table
# @param {Object} item or keys
# @return {Error}
# @return {Object} deleted item
delete: (table, item, callback) ->
# Extract keys from item
@_findKeys table, (err, keys) =>
if err
callback? err
return
objectKey = {}
objectKey[keys[0]] = item[keys[0]]
objectKey[keys[1]] = item[keys[1]]
dynamoKey = typeUtil.packObjectOrArray objectKey
# Stock item and delete it
@dynamo.deleteItem
TableName: table
Key: dynamoKey
ReturnValues: "ALL_OLD"
(err, data) ->
callback? err, typeUtil.sortAndClean typeUtil.unpackObjectOrArray data
# Extract primary keys of a given table
#
# @param {String} table
# @return {Error}
# @return {Array} list of primary keys
_findKeys: (table, callback) ->
@dynamo.describeTable
TableName: table
(err, data) ->
if data?
keySchema = data.Table.KeySchema
keys = _.map keySchema, (key) ->
key.AttributeName
callback? err, keys
module.exports = Dynoga