From 24d8d58aabb2f29b59873e65359cff224a51d41d Mon Sep 17 00:00:00 2001 From: Snehit Velma Date: Mon, 17 Nov 2025 13:40:03 +1100 Subject: [PATCH 1/3] fix: correct the transaction write for put correctly. --- src/mutation/expressionBuilder.ts | 8 +++++ src/mutation/putItem.ts | 47 ++----------------------- src/mutation/transactWriteItems.spec.ts | 11 +++--- src/mutation/transactWriteItems.ts | 5 +-- 4 files changed, 18 insertions(+), 53 deletions(-) diff --git a/src/mutation/expressionBuilder.ts b/src/mutation/expressionBuilder.ts index 41ff7f94..00866063 100644 --- a/src/mutation/expressionBuilder.ts +++ b/src/mutation/expressionBuilder.ts @@ -34,6 +34,14 @@ export const buildConditionExpressions = ( expression += `${expressionName} ${operator} :val${i}_1 AND :val${i}_2`; attrValues[`:val${i}_1`] = value[0]; attrValues[`:val${i}_2`] = value[1]; + } else if (operator === 'EXISTS') { + // For EXISTS, we don't need a value, just check if attribute exists or not + const existsValue = value as boolean; + if (existsValue) { + expression += `attribute_exists(${expressionName})`; + } else { + expression += `attribute_not_exists(${expressionName})`; + } } else { expression += `${expressionName} ${operator} :val${i}`; attrValues[`:val${i}`] = value; diff --git a/src/mutation/putItem.ts b/src/mutation/putItem.ts index 463cff3d..0689cc28 100644 --- a/src/mutation/putItem.ts +++ b/src/mutation/putItem.ts @@ -1,51 +1,8 @@ -import { AnyObject, TableConfig, ConditionExpressionInput, ConditionExpressionKind } from '../types'; +import { AnyObject, TableConfig, ConditionExpressionInput } from '../types'; import { DynamoDBDocumentClient, PutCommand, PutCommandOutput, PutCommandInput } from '@aws-sdk/lib-dynamodb'; -import { keyOperatorLookup } from '../query/queryBuilder'; +import { buildConditionExpressions } from './expressionBuilder'; -const buildConditionExpressions = ( - conditionExpression: ConditionExpressionInput[], -): { expression: string; attrValues: Record; attrNames: Record } => { - let expression = ''; - const attrValues: Record = {}; - const attrNames: Record = {}; - for (let i = 0; i < conditionExpression.length; i++) { - const currentExpression = conditionExpression[i]; - if (currentExpression.kind === ConditionExpressionKind.AndOr) { - if (i > 0) { - expression += ` ${currentExpression.value} `; - } - continue; - } - if (currentExpression.kind === ConditionExpressionKind.Comparison) { - const key = currentExpression.key; - const comparator = currentExpression.comparator; - const value = currentExpression.value; - - if (!comparator) continue; - const operator = keyOperatorLookup(comparator); - const expressionName = `#key_${key}`; - attrNames[expressionName] = key; - if (operator === 'BETWEEN') { - expression += `${expressionName} ${operator} :val${i}_1 AND :val${i}_2`; - attrValues[`:val${i}_1`] = value[0]; - attrValues[`:val${i}_2`] = value[1]; - } else if (operator === 'EXISTS') { - // For EXISTS, we don't need a value, just check if attribute exists or not - const existsValue = value as boolean; - if (existsValue) { - expression += `attribute_exists(${expressionName})`; - } else { - expression += `attribute_not_exists(${expressionName})`; - } - } else { - expression += `${expressionName} ${operator} :val${i}`; - attrValues[`:val${i}`] = value; - } - } - } - return { expression, attrValues, attrNames }; -}; /** * Writes item in database. diff --git a/src/mutation/transactWriteItems.spec.ts b/src/mutation/transactWriteItems.spec.ts index 86a9a092..43435d34 100644 --- a/src/mutation/transactWriteItems.spec.ts +++ b/src/mutation/transactWriteItems.spec.ts @@ -138,9 +138,9 @@ describe('transactWriteItems', () => { ConditionCheck: { Key: { pk: '1', sk: 'a' }, TableName: testTableConf.name, - ConditionExpression: '#key_pk EXISTS :val0', + ConditionExpression: 'attribute_exists(#key_pk)', ExpressionAttributeNames: { '#key_pk': 'pk' }, - ExpressionAttributeValues: { ':val0': true }, + ExpressionAttributeValues: {}, }, }, ], @@ -214,9 +214,8 @@ describe('transactWriteItems', () => { { Put: { Item: { pk: '1', sk: 'a', name: 'Alice' }, - ConditionExpression: '#key_pk EXISTS :val0', + ConditionExpression: 'attribute_not_exists(#key_pk)', ExpressionAttributeNames: { '#key_pk': 'pk' }, - ExpressionAttributeValues: { ':val0': false }, TableName: testTableConf.name, }, }, @@ -250,9 +249,9 @@ describe('transactWriteItems', () => { { Delete: { Key: { pk: '1', sk: 'a' }, - ConditionExpression: '#key_pk EXISTS :val0', + ConditionExpression: 'attribute_exists(#key_pk)', ExpressionAttributeNames: { '#key_pk': 'pk' }, - ExpressionAttributeValues: { ':val0': true }, + ExpressionAttributeValues: {}, TableName: testTableConf.name, }, }, diff --git a/src/mutation/transactWriteItems.ts b/src/mutation/transactWriteItems.ts index 81a086f5..6f211ff5 100644 --- a/src/mutation/transactWriteItems.ts +++ b/src/mutation/transactWriteItems.ts @@ -62,9 +62,10 @@ export function transactWriteItems( const conditionExpr = buildConditionExpressions(item.Put.conditions); putItem.ConditionExpression = conditionExpr.expression; putItem.ExpressionAttributeNames = conditionExpr.attrNames; - putItem.ExpressionAttributeValues = conditionExpr.attrValues; + if (Object.keys(conditionExpr.attrValues).length > 0) { + putItem.ExpressionAttributeValues = conditionExpr.attrValues; + } } - return { Put: putItem }; } From b2c3dead5edeeb3f8e197802da98d2f0419293f3 Mon Sep 17 00:00:00 2001 From: Snehit Date: Mon, 17 Nov 2025 13:41:51 +1100 Subject: [PATCH 2/3] chore: update the package version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e00aa1ce..261313a4 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "dynamo", "nosql" ], - "version": "0.6.2", + "version": "0.6.3", "files": [ "lib", "LICENSE", From 043440ae30225d35296d6e075fd20cfef7caa147 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 17 Nov 2025 02:42:19 +0000 Subject: [PATCH 3/3] Initial plan