From 87cbfe373218a43328d2dba3c41e6fcb7c6a8b56 Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Thu, 16 Nov 2023 16:44:00 -0500 Subject: [PATCH] Add methods to list versions and get by version --- src/index.ts | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/test.ts | 8 ++++++++ 2 files changed, 58 insertions(+) diff --git a/src/index.ts b/src/index.ts index 7485f3a..2a0a213 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { type PutCommandInput, PutCommand, GetCommand, + QueryCommand, } from '@aws-sdk/lib-dynamodb' import type { NativeAttributeValue } from '@aws-sdk/util-dynamodb' @@ -177,6 +178,55 @@ export class DynamoDBAutoIncrement extends BaseDynamoDBAutoIncrement { * ``` */ export class DynamoDBHistoryAutoIncrement extends BaseDynamoDBAutoIncrement { + async list(): Promise { + const { Items } = await this.props.doc.send( + new QueryCommand({ + TableName: this.props.tableName, + ExpressionAttributeNames: { + ...Object.fromEntries( + Object.keys(this.props.counterTableKey).map((key, i) => [ + `#${i}`, + key, + ]) + ), + '#counter': this.props.attributeName, + }, + ExpressionAttributeValues: Object.fromEntries( + Object.values(this.props.counterTableKey).map((value, i) => [ + `:${i}`, + value, + ]) + ), + KeyConditionExpression: Object.keys(this.props.counterTableKey) + .map((_, i) => `#${i} = :${i}`) + .join(' AND '), + ProjectionExpression: '#counter', + }) + ) + + return Items?.map((item) => item[this.props.attributeName]).sort() ?? [] + } + + async get(version?: number) { + const { Item } = await this.props.doc.send( + new GetCommand( + version === undefined + ? { + TableName: this.props.counterTableName, + Key: this.props.counterTableKey, + } + : { + TableName: this.props.tableName, + Key: { + ...this.props.counterTableKey, + [this.props.attributeName]: version, + }, + } + ) + ) + return Item + } + protected async next(item: Record) { let nextCounter diff --git a/src/test.ts b/src/test.ts index 6f1f719..d0296d3 100644 --- a/src/test.ts +++ b/src/test.ts @@ -207,6 +207,10 @@ describe('autoincrementVersion', () => { 'tracked attribute set to %s', (trackedAttributeValue) => { test('increments version on put', async () => { + expect(await autoincrement.list()).toEqual([]) + expect(await autoincrement.get()).toEqual(initialItem) + expect(await autoincrement.get(1)).toEqual(undefined) + // Create new version const newVersion = await autoincrement.put({ name: 'Handy Widget', @@ -228,6 +232,10 @@ describe('autoincrementVersion', () => { ).Items expect(historyItems?.length).toBe(Number(hasInitialItem)) + + expect(await autoincrement.list()).toEqual( + historyItems?.map((_, i) => i + 1) ?? [] + ) }) test('correctly handles a large number of parallel puts', async () => {