Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@begin/data

beginner-corp4.1kApache-2.05.0.5TypeScript support: definitely-typed

Begin Data is a durable and fast key/value document store built on top of DynamoDB

serverless, database, AWS, dynamodb, keyvalue, infrastructure, infra

readme

Begin Data

@begin/data

GitHub CI status

Begin Data is an easy to use, fast, and durable key/value and document store built on top of DynamoDB. Originally built for Begin serverless apps, Begin Data’s core API has three simple methods: get, set, and destroy.

Concepts

Begin Data organizes itself into tables. A table contain documents which are just collections of plain Objects. Documents stored in Begin Data always have the properties table and key.

Optionally a document can also have a ttl property with a UNIX epoch value representing the expiry time for the document.

Usage

Begin Data operates on one DynamoDB table named data with a partition key scopeID and a sort key of dataID (and, optionally, a ttl for expiring documents).

Example app.arc:

@app
myapp

@tables
data
  scopeID *String
  dataID **String
  ttl TTL

Or equivalent CloudFormation YAML:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
    BeginData:
        Type: "AWS::DynamoDB::Table"
        Properties:
            TableName: "data"
            BillingMode: "PAY_PER_REQUEST"
            KeySchema:
              -
                AttributeName: "scopeID"
                KeyType: "HASH"
              -
                AttributeName: "dataID"
                KeyType: "RANGE"
            SSESpecification:
                Enabled: "false"
            TimeToLiveSpecification:
                AttributeName: "ttl"
                Enabled: "TRUE"

Note: projects not based on Architect will need a BEGIN_DATA_TABLE_NAME environment variable. You can also use this env var to override and name the table anything you want. This also allows for multiple apps to share a single table.

API

let data = require('@begin/data')

The core API is three methods:

  • data.get(params[, callback])[Promise] for retreiving data
  • data.set(params[, callback])[Promise] for writing data
  • data.destroy(params[, callback])[Promise] for removing data

Additional helper methods are also made available:

  • data.incr(params[, callback])[Promise] increment an attribute on a document
  • data.decr(params[, callback])[Promise] decrement an attribute on a document
  • data.count(params[, callback])[Promise] get the number of documents for a given table

All methods accept a params object and, optionally, a Node-style errback. If no errback is supplied, a Promise is returned. All methods support async/await.

Writes

Save a document in a table by key. Remember: table is required; key is optional.

let taco = await data.set({
  table: 'tacos',
  key: 'al-pastor'
})

All documents have a key. If no key is given, set will generate a unique key.

let token = await data.set({
  table: 'tokens',
})
// {table:'tokens', key:'LCJkYX9jYWwidW50RhSU'}

Batch save multiple documents at once by passing an Array of Objects.

let collection = await data.set([
  {table: 'ppl', name:'brian', email:'b@brian.io'},
  {table: 'ppl', name:'sutr0', email:'sutr0@brian.io'},
  {table: 'tacos', key:'pollo'},
  {table: 'tacos', key:'carnitas'},
])

Reads

Read a document by key:

let yum = await data.get({
  table: 'tacos',
  key: 'baja'
})

Batch read by passing an Array of Objects. With these building blocks you can construct secondary indexes and joins, like one-to-many and many-to-many.

await data.get([
  {table:'tacos', key:'carnitas'},
  {table:'tacos', key:'al-pastor'},
])

Destroy

Delete a document by key.

await data.destroy({
  table: 'tacos',
  key: 'pollo'
})

Batch delete documents by passing an Array of Objects.

await data.destroy([
  {table:'tacos', key:'carnitas'},
  {table:'tacos', key:'al-pastor'},
])

Pagination

Large sets of data can not be retrieved in one call because the underlying get api paginates results. In this case use the for await syntax with a limit set to get paginated data.

let pages = data.page({ table:'ppl', limit:25 })
let count = 0  
for await (let page of pages) {
  console.log(page)
  count++
}

Additional Superpowers

  • Documents can be expired by setting ttl to an UNIX epoch in the future.
  • Atomic counters: data.incr and data.decr

See the tests for more examples!

Patterns

Coming soon! Detailed guides for various data persistence tasks:

  • Denormalizing
  • Pagination
  • Counters
  • Secondary indexes
  • One to many
  • Many to many

More

changelog

Begin Data changelog


[5.0.3 - 5.0.5] 2024-05-07

Changed

  • Updated dependencies

[5.0.2] 2024-02-08

Upgraded to new explicit plugin resolution with aws-lite!


[5.0.0 - 5.0.1] 2024-02-03

Begin Data just got a lot faster. Gone are the days of 500-1000ms cold starts due to instantiating the AWS SDK – Begin Data v5 is now between 2-5x faster, and uses 2-4x less memory, courtesy of aws-lite!


[4.0.0] 2022-02-07

Added

  • Added support for Sandbox dynamic port selection
    • Added best-effort attempt to find Sandbox ports via internal SSM

Changed

  • Deep require aws-sdk deps for a potentially large cold start perf boost
  • Breaking change: Begin Data no longer relies on or makes direct use of NODE_ENV or other legacy Architect env vars. @begin/data v4+ now requires Architect v10 / Sandbox v5 or later.
  • Improved table lookup performance

[3.0.4] 2021-10-18

Fixed

  • Fixed issue so that if present ARC_ENV takes precedence over NODE_ENV for stage.

[3.0.3] 2021-10-14

Fixed

  • Fixed issue where Begin Data may not work in unit tests with Sandbox >= 4.1

[3.0.1 - 3.0.2] 2021-09-20

Changed

  • Enforce minimum of Node 12
  • Updated dependencies

[3.0.0] 2021-07-22

Changed

  • Breaking change: Begin Data no longer supports Node.js 10 (now EOL, and no longer available to create / update in AWS Lambda)
  • Potentially breaking change: Begin Data now requires @architect/sandbox 4.0 or greater for local use
  • Removed Arc v5 deprecation warnings
  • Linted some stuff, tidied up project files
  • Updated dependencies

Fixed

  • Removed unnecessary dependency

[2.0.0 - 2.0.1] 2021-03-18

Added

  • Added lookup for Begin Data table in Architect Sandbox via new internal service discovery endpoint
  • Fixed local file path issue for loading Architect project manifests that aren't .arc (e.g. app.arc, arc.yaml, etc.)

Fixed

  • Fixed missing dependency

[1.2.0 - 1.2.2] 2020-02-12 - 2020-04-19

Added

  • Increase soft row size limit to 200KB
  • Added some nice performance improvements related to connection reuse in live AWS
  • incr and decr now set the default property value to be incremented or decremented to zero

Fixed

  • get will no longer return rows for tables with same leading characters (see smallwins/begin-issues#20)

Changed

Fixed

  • Fixed module instantiation issues in testing scenarios

[1.1.6 - 1.1.7] 2020-02-05

Added

  • Added support for dynamic local database port configuration in Sandbox (ARC_TABLES_PORT)

Fixed

  • Fixed issue with Begin Data not working correctly locally if you don't have an ~/.aws/credentials file; fixes @begin-issues#15, thanks @wesbos!

[1.1.5] 2020-02-01

Fixed

  • Fixes table lookup compatibility with Architect 6 projects running locally in Sandbox

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.