dynamodb-quickly
v0.8.1
Published
Lightweight client library for working with DynamoDB in Node.js. Written in Typescript with a Promise-based API.
Downloads
3
Readme
dynamodb-quickly
Lightweight client library for working with DynamoDB in Node.js. Written in Typescript with a Promise-based API.
This library tries to expose the natural DynamoDB way of doing things as directly as possible, while adding a few convenient helpers and shortcuts.
Things it does:
- Supports reading and writing items as plain Javascript objects. (more details below)
- Adds a few convenience patterns and shortcuts.
- Handles some common patterns for you, like using
attribute_not_exists()
expressions.
Things it does NOT do:
- Doesn't have a schema or do any data validation.
- Doesn't provide a DAO style interface.
Also note, so far this library is just a partial implementation of the DynamoDB API. Some big features missing are: no helpers for Query or Scan.
Javascript data mapping
One thing this library does is automatically map from Javascript to Dynamo's AttributeValue tagging scheme. The mapping looks like:
| plain Javascript object | AttributeValue |
| ----------------------- | -------------- |
| null
or undefined
| { NULL: true }
|
| typeof
is string
| { S: ... }
|
| typeof
is boolean
| { BOOL: ... }
|
| typeof
is number
| { N: ... }
|
| Array.isArray
is true | { L: [ ... ] }
(aka List) |
| all other values | { M: { ... } }
(aka Map) |
Usage
Connecting to the database
To get started, you should install and initialize the aws-sdk
library seperately (version 2.322.0 or later should work),
then create a new DynamoDB service object. Example:
import AWS from 'aws-sdk';
const client = new AWS.DynamoDB({
apiVersion: '2012-08-10',
region: 'us-east-1'
endpoint: endpoint
});
Setting up the table
Once you have the client instance, create one or more Table instances.
import { Table } from 'minimal-dynamodb-client'
const table = new Table({
client,
tableName: 'my-table',
primaryKey: 'key'
});
The primaryKey
is optional but highly recommended, This should be the field name for the table's
primary key. (or one of them, if there are multiple). If provided, this library will use it for
some convenient patterns.
Local development
When running locally it's recommended that devs launch this awesome Docker container:
docker run -p 7042:8000 -it --rm instructure/dynamo-local-admin
Once running you can use the web interface at http://localhost:7042 to browse your data.
Setting up tables
This library adds a CreateTable helper. It's recommended to call this when the app is running locally, to set up all your table(s) on the local DynamoDB instance.
Example:
if (localMode) {
await table.createTable();
}
It's not recommended to use createTable
in production. Instead your production tables should be
configured by a seperate process. (using Terraform or CDK or etc)
API
async table.getItem(key)
Calls GetItem.
The 'key' can either be a string or an object.
If the key is a string, then we fetch the item with that primary key value. (using the table's 'primaryKey')
If the key is an object, then it's converted to an AttributeValue map (see below) and then used as the "Key" value
Examples:
data = await table.getItem("user-123");
data = await table.getItem({ specificPrimaryKey: "value-123" });
async table.putItem(itemData, options?)
Calls PutItem.
itemData
is the object to set. This object should include one of the table's primary keys, or else Dynamo
will complain.
Available options:
| option | description |
| ------ | ----------- |
| noOverwrite | Don't overwrite this item if it already exists. (using an attribute_not_exists
expression) |
| primaryKey | Key to use with noOverwrite
(defaults to the table's primaryKey) |
Examples:
await table.putItem({
key: 'user-123',
name: 'Name',
address: '123 Address'
})
await table.putItem(userData, { noOverwrite: true });
async table.updateItem(key: string | object, changes: array | object)
Calls UpdateItem
key
is either a string or object, and works the same as the key in getItem
. If it's a string then the table's primaryKey is used.
changes
is either an Array of {field, value}
objects, or a single object of fields to set. Dynamo allows
you to change multiple fields in a single item with one operation.
Example - object format
// Set a single field "name" to value "Alice":
await table.updateItem(key, { name: 'Alice' })
// Set "name" to "Alice" and "city" to "Denver"
await table.updateItem(key, { name: 'Alice' city: 'Denver' })
Example - array format
// Set a single field "name" to value "Alice":
await table.updateItem(key, [{ field: 'name', value: 'Alice' }])
// Set "name" to "Alice" and "city" to "Denver"
await table.updateItem(key, [{ field: 'name', value: 'Alice' },{ field: 'city', value: 'Denver' }])
Advanced example - array format with nested field
If the item has nested Map values, then we can update the contents of those maps. For this,
you can call updateItem
with an array of changes, and pass a list as the field
.
For example, let's say that the item is:
{
key: 'user123',
name: 'Alice',
friends: {
user456: {
accepted: false
}
}
}
We can update the nested "accepted" value with:
await table.updateItem(key, [{
field: [ 'friends', 'user456', 'accepted' ],
value: true
}])
table.deleteItem(key)
Calls DeleteItem
The key
takes the same values as getItem().
Example:
await table.deleteItem(key);
table.deleteFields(key, fields: string[])
Deletes one or more fields out of an item. This uses UpdateItem with a REMOVE expression. The key
takes the same values as getItem().
await table.deleteFields(key, [ "needsMigration" ]);
table.deleteField(key, field: string)
Deletes one field from an item. Convenience method for calling deleteFields with a single item.
await table.deleteField(key, "needsMigration");
table.listAppend(key, field: string, value)
Appends an item onto a list value. This uses UpdateItem with a list_append()
expression. The key
takes the same values as getItem().
Example:
If the item is equal to:
{
key: 'key1',
list: ['a', 'b']
}
Then we can add an item with
await table.listAppend('key1', 'list', 'c')