UNPKG

@setho/dynamodb-repository

Version:

DynamoDB repository for hash-key and hash-key/range indexed tables. Designed for Lambda use. Handles nice-to-haves like created and updated timestamps and default id creation.

133 lines (102 loc) 4.17 kB
# dynamodb-repository [![](https://img.shields.io/npm/v/@setho/dynamodb-repository.svg)](https://www.npmjs.com/package/@setho/dynamodb-repository) ![CI & Test](https://github.com/SethO/dynamodb-repository/workflows/CI%20&%20Test/badge.svg) DynamoDB repository for key-value indexed tables. Designed for Lambda use. Handles niceties like created and updated timestamps and default id creation. ## Install `$ npm install @setho/dynamodb-repository --save` ## Usage ### TypeScript/ES6 ```typescript import { KeyValueRepository } from '@setho/dynamodb-repository'; const myRepo = new KeyValueRepository({ tableName: 'Items', // Required keyName: 'id', // Required idOptions: { // Optional prefix: 'ITEM_', // Default is empty string }, documentClient, // Required - V3 DynamoDBDocumentClient from @aws-sdk/lib-dynamodb }); ``` ### JavaScript ```javascript const { KeyValueRepository } = require('@setho/dynamodb-repository'); const myRepo = new KeyValueRepository({ tableName: 'Items', // Required keyName: 'id', // Required idOptions: { // Optional prefix: 'ITEM#', // Default is empty string }, documentClient, // Required - V3 DynamoDBDocumentClient from @aws-sdk/lib-dynamodb }); ``` #### Constructor Use the optional `idOptions` constructor parameter to set an optional `prefix` to give your ids some human-readable context. The remainder of the key is a ULID, which is both unique and lexicographically sortable. See an explanation of and motivation for ULIDs [here](https://github.com/ulid/spec). ## Create - Requires action `dynamodb:PutItem` - Automatically adds a string key (this will overwrite any you may try to provide). Use constructor options to specify length and optional prefix. - Automatically provides a `createdAt` and `updatedAt` timestamp in ISO-8601 - Returns what was saved; does not mutate the item passed in. ```javascript const mySavedItem = await myRepo.create(myItem); mySavedItem.id; // itm_a4d02890b7174730b4bbbc mySavedItem.createdAt; // 1979-11-04T09:00:00.000Z mySavedItem.updatedAt; // 1979-11-04T09:00:00.000Z ``` ## Get by Key - Requires action `dynamodb:GetItem`. - Throws `404` if item not found using [http-errors](https://npmjs.com/package/http-errors). ```javascript const myItem = await myRepo.get(id); ``` ## Get Many - Requires action `dynamodb:Scan` - Accepts optional parameter fields `limit` and `cursor` - `limit` defaults to 100 - Returns object with `items` (Array) and `cursor` (String) - `items` will always be an array; if nothing found, it will be empty - `cursor` will be present if there are more items to fetch, otherwise it will be undefined ```javascript // Example to pull 100 at time until you have all items const allItems = []; const getAllItems = async ({ limit, cursor = null }) => { const getResult = await myRepo.getMany({ limit, cursor }); allItems.push(...getResult.items); if (getResult.cursor) { await getAllItems({ cursor: getResult.cursor }); } }; await getAllItems(); // The array allItems now has all your items. Go nuts. ``` ## Remove by Key - Requires action `dynamodb:DeleteItem` ```javascript await myRepo.remove(id); ``` ## Update - Requires `dynamodb:UpdateItem` - Honors revision check; it will only update if the revision on disk is the one you are updating. Will return a `409` if the revision has changed underneath you. - Will perform a partial update if you don't pass in all properties. Think of this as a "patch" vs. a replacement update. The `key` and `revision` properties are always required. - Returns the entire entity, including both new and unchanged properties ```js const person = await myRepo.create({ name: 'Joe', age: 28, favoriteColor: 'blue', }); // Full item update person.favoriteColor = 'teal'; const newPerson1 = await myRepo.update(person); console.log(newPerson1.favoriteColor); // 'teal' // Partial update const partial = { favoriteColor: 'aquamarine', key: person.key, revision: newPerson1.revision, }; const newPerson2 = await myRepo.update(partial); console.log(newPerson2.favoriteColor); // 'aquamarine' console.log(newPerson2.age); // 28 ``` // More Coming Soon...