2.0.1 • Published 7 months ago

optimus-ddb-client v2.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
7 months ago

optimus-ddb-client

About

OptimusDdbClient is a TypeScript/JavaScript DynamoDB client with the following abstractions:

  • JavaScript attribute types instead of DynamoDB JSON. Your items' attributes are represented by JavaScript types like number and string instead of DynamoDB JSON.
  • Strong typing. All items, key parameters, and query conditions are statically typed for each table's specific indexes and items. Runtime type validation is performed when pulling items out of DynamoDB and committing items into DynamoDB.
  • Built-in transactions and optimistic locking. An abstracted version number attribute facilitates optimistic locking. When you commit changes OptimusDdbClient does a TransactWriteItems with the items' version attribute values as conditions of the transaction. That guarentees that either all of the items in the transaction change exactly as they did in your code, or the transaction is cancelled and OptimusDdbClient throws an error.
  • Managed expressions. Instead of a string, expression name mappings, and expression value mappings, OptimusDdbClient's Query and Scan conditions are specified with statically typed tuples. Because of that you can be confident that your conditions are valid and you don't have to worry about mapping expression names and expression values.
  • Table relationships. When you specify a relationship between two tables, OptimusDdbClient will make sure that any item changes made on those tables must not violate the relationship. If a commitItems call does not include the items necessary to transactionally maintain all tables' relationships, it will throw a TableRelationshipViolationError. One-to-one, one-to-many, and many-to-many relationships are supported.
  • No size limits for BatchGetItem, Query, or Scan. OptimusDdbClient's getItems method will call BatchGetItem until all requested items are fetched. OptimusDdbClient's queryItems and scanItems methods will call Query or Scan respectively until the optional limit you specify is reached or it hits the end of the index.

Requirements

  1. Any existing items of tables to be used with OptimusDdbClient should have an N attribute to use for optimistic locking. It should be specified in the Table constructor's versionAttribute parameter. The default is "version".

2.x.x major version breaking changes

  • Switch from shape-tape to zod
  • Rename itemShape to itemSchema, ItemShapeValidationError to ItemValidationError
  • Change to more flexible way of defining table relationship foreign keys
  • Start depending on structuredClone

Installation

npm install optimus-ddb-client zod

zod is a peer dependency of optimus-ddb-client

Usage

import { Table, OptimusDdbClient } from "optimus-ddb-client"
import * as z from "zod"

// Create Table class instances based on your DynamoDB tables.
const blogPostsTable = new Table({
	tableName: "BlogPosts",
	itemSchema: z.strictObject({
		id: z.string(),
		name: z.string(),
		content: z.string(),
		numComments: z.number().int()
	}),
	partitionKey: "id"
})
const commentsTable = new Table({
	tableName: "Comments",
	itemSchema: z.strictObject({
		blogPostId: z.string(),
		id: z.string(),
		content: z.string()
	}),
	partitionKey: "blogPostId",
	sortKey: "id"
})

const optimus = new OptimusDdbClient()

// Perform operations on items in those tables.
// Example scenario - Handling an API request for adding a comment to a blog post:
async function handleCreateBlogPostComment(blogPostId, commentContent) {
	// Get the blog post
	const blogPost = await optimus.getItem({
		table: blogPostsTable,
		key: { id: blogPostId }
	})

	// Prepare a change to increase the blog post's numComments.
	blogPost.numComments = blogPost.numComments + 1

	// Prepare a new comment.
	const comment = optimus.draftItem({
		table: commentsTable,
		item: {
			blogPostId: blogPostId,
			id: crypto.randomUUID(),
			content: commentContent
		}
	})

	// Commit those changes in a transaction.
	await optimus.commitItems({ items: [blogPost, comment] })

	return { id: comment.id }
}

In TypeScript use zod's infer function to get a named type for your items

import * as z from "zod"

type BlogPost = z.infer<typeof blogPostsTable.itemSchema>
const blogPost: BlogPost = await optimus.getItem({
	table: blogPostsTable,
	key: { id: blogPostId }
})

Please see the unit test demonstrating this example.

Tests

The GitHub repo's tst directory has unit tests and integ tests using DynamoDB local. You can run the tests by cloning the repo and running npm install then npm run test. You need to have java installed to run the tests because DynamoDB local requires java.

Documentation

Please see the low level documentation for more details.

2.0.1

7 months ago

2.0.0

7 months ago

1.0.48

1 year ago

1.0.47

1 year ago

1.0.49

1 year ago

1.0.51

11 months ago

1.0.50

1 year ago

1.0.46

1 year ago

1.0.45

1 year ago

1.0.44

1 year ago

1.0.43

1 year ago

1.0.42

1 year ago

1.0.41

1 year ago

1.0.40

1 year ago

1.0.39

2 years ago

1.0.38

2 years ago

1.0.37

2 years ago

1.0.36

2 years ago

1.0.35

2 years ago

1.0.34

2 years ago

1.0.33

2 years ago

1.0.32

2 years ago

1.0.31

2 years ago

1.0.30

2 years ago

1.0.29

2 years ago

1.0.28

2 years ago

1.0.27

2 years ago

1.0.26

2 years ago

1.0.25

2 years ago

1.0.24

2 years ago

1.0.23

2 years ago

1.0.22

2 years ago

1.0.21

2 years ago

1.0.20

2 years ago

1.0.19

2 years ago

1.0.18

2 years ago

1.0.17

2 years ago

1.0.16

2 years ago

1.0.15

2 years ago

1.0.14

2 years ago

1.0.12

2 years ago

1.0.11

2 years ago

1.0.10

2 years ago