import { type DeleteItemInput, type TransactWriteItem, type TransactWriteItemsOutput, type BatchWriteItemOutput, type UpdateItemInput, type PutItemInput, type UpdateItemCommandOutput, type PutItemCommandOutput, type DeleteItemCommandOutput, } from '@aws-sdk/client-dynamodb' import { HelpfulError } from './errors' import { batchWrite, type WriteRequestMap } from './query/batch-write' import { buildQueryExpression } from './query/expression' import { type UpdateConditions } from './query/filters' import { transactWrite } from './query/transact-write' import { getUpdateItemInput, type UpdateItemInputParams } from './query/update-item-input' import { type ITable, type Table } from './table' interface PutItemInputParams extends UpdateItemInputParams { } export class DocumentClient { constructor(private readonly tableClass: ITable) { } public getPutInput(record: T, params?: PutItemInputParams): PutItemInput { const input: PutItemInput = { TableName: this.tableClass.schema.name, Item: record.toDynamo(true), } if (params?.returnValues != null) { input.ReturnValues = params.returnValues } if (params?.conditions != null) { const conditionExpression = buildQueryExpression(this.tableClass.schema, params.conditions) input.ConditionExpression = conditionExpression.FilterExpression input.ExpressionAttributeNames = conditionExpression.ExpressionAttributeNames input.ExpressionAttributeValues = conditionExpression.ExpressionAttributeValues } return input } public async put(record: T, params?: PutItemInputParams): Promise { const input = this.getPutInput(record, params) try { return await this.tableClass.schema.dynamo.putItem(input) } catch (ex) { throw new HelpfulError(ex, this.tableClass, input) } } public getUpdateInput(record: T, params?: UpdateItemInputParams): UpdateItemInput { return getUpdateItemInput(record, params) } public async update(record: T, params?: UpdateItemInputParams): Promise { const input = this.getUpdateInput(record, params) try { return await this.tableClass.schema.dynamo.updateItem(input) } catch (ex) { throw new HelpfulError(ex, this.tableClass, input) } } public async batchPut(records: T[]): Promise { return await batchWrite( this.tableClass.schema.dynamo, records.map((record) => { const request: WriteRequestMap = { [this.tableClass.schema.name]: [ { PutRequest: { Item: record.toDynamo(), }, }, ], } return request }), ) } public getDeleteInput(record: T, conditions?: UpdateConditions): DeleteItemInput { const input: DeleteItemInput = { TableName: this.tableClass.schema.name, Key: record.getDynamoKey(), } if (conditions != null) { const conditionExpression = buildQueryExpression(this.tableClass.schema, conditions) input.ConditionExpression = conditionExpression.FilterExpression input.ExpressionAttributeNames = conditionExpression.ExpressionAttributeNames input.ExpressionAttributeValues = conditionExpression.ExpressionAttributeValues } return input } public async transactPut(records: T[]): Promise { return await transactWrite( this.tableClass.schema.dynamo, records.map((record) => { const writeRequest: TransactWriteItem = { Put: { TableName: this.tableClass.schema.name, Item: record.toDynamo(), }, } return writeRequest }), ) } public async delete(record: T, conditions?: UpdateConditions): Promise { const input = this.getDeleteInput(record, conditions) try { return await this.tableClass.schema.dynamo.deleteItem(input) } catch (ex) { throw new HelpfulError(ex, this.tableClass, input) } } }