Skip to content

Commit

Permalink
Added .returning()
Browse files Browse the repository at this point in the history
This MR allows callers to get the original object as it was before an update is made or the new object as it is after the update. Since TransactWriteItems does not support this feature, additional logic has been added to nodenamo to support this addition. Returning an old object does not incur additional cost. Returning a new object, however, involves an additional get query. The returned object, if any, is strongly consistent.
  • Loading branch information
Nithiwat Kampanya committed Jul 10, 2024
1 parent 3724d9a commit 684bd51
Show file tree
Hide file tree
Showing 28 changed files with 644 additions and 43 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nodenamo",
"version": "2.1.0",
"version": "2.2.0",
"description": "A powerful ORM for DynamoDb",
"main": "dist/index.js",
"typings": "dist/index",
Expand Down
31 changes: 29 additions & 2 deletions spec/acceptance/customNameTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {assert as assert} from 'chai';
import { DBTable, DBColumn } from '../../src';
import { NodeNamo } from '../../src/nodeNamo';
import Config from './config';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { ReturnValue } from '../../src/interfaces/returnValue';

@DBTable({name:'nodenamo_acceptance_targetNameTest'})
class User
Expand Down Expand Up @@ -261,7 +261,9 @@ describe('Custom-name tests', function ()

user.name = 'This Three';
user['extra'] = 'invalid';
await nodenamo.update(user).from(User).execute();
let result = await nodenamo.update(user).from(User).execute();

assert.isUndefined(result);

user = await nodenamo.get(3).from(User).execute();
assert.deepEqual(user, { id: 3, name: 'This Three', account: 2000, created: 2018, department: 'development', enabled: false });
Expand Down Expand Up @@ -300,6 +302,31 @@ describe('Custom-name tests', function ()
assert.deepEqual(user, { id: 6, name: '', account: 3000, created: 2020, department: 'hr', enabled: true });
});

it('Update an item - return AllOld', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Newer Two'}).from(User).returning(ReturnValue.AllOld).execute();

assert.deepEqual(result, originalUser);
});

it('Update an item - return AllNew', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Newest Two'}).from(User).returning(ReturnValue.AllNew).execute();

assert.deepEqual(result, {...originalUser, name: 'Newest Two'});
});

it('Update an item - return None', async () =>
{
let result = await nodenamo.update({id: 2, name: 'Newer Two'}).from(User).returning(ReturnValue.None).execute();

assert.isUndefined(result);
});

it('On item', async () =>
{
let user = await nodenamo.get(6).from(User).execute<User>();
Expand Down
4 changes: 3 additions & 1 deletion spec/acceptance/globalTableTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,9 @@ describe('Global table tests', function ()
assert.deepEqual(book, { id: 2, title: 'Another Book' });

user.name = 'This Two';
await nodenamo.update(user).from(User).execute();
let result = await nodenamo.update(user).from(User).execute();

assert.isUndefined(result);

user = await nodenamo.get(2).from(User).execute();
assert.deepEqual(user, { id: 2, name: 'This Two' });
Expand Down
45 changes: 43 additions & 2 deletions spec/acceptance/hashRangePairTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {assert as assert} from 'chai';
import { DBTable, DBColumn } from '../../src';
import { NodeNamo } from '../../src/nodeNamo';
import Config from './config';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { ReturnValue } from '../../src/interfaces/returnValue';

@DBTable({name:'nodenamo_acceptance_hashRangePairTest'})
class User
Expand Down Expand Up @@ -283,7 +283,9 @@ describe('Hash-range pair tests', function ()

user.name = 'This Three';
user['extra'] = 'invalid';
await nodenamo.update(user).from(User).execute();
let result = await nodenamo.update(user).from(User).execute();

assert.isUndefined(result);

user = await nodenamo.get(3).from(User).execute();
assert.deepEqual(user, { id: 3, name: 'This Three', account: 2000, created: 2018, parentId: 300 });
Expand Down Expand Up @@ -361,6 +363,45 @@ describe('Hash-range pair tests', function ()
assert.deepEqual(user, { id: 6, name: '', account: 3000, created: 2020, parentId: 600 });
});

it('Update an item - return AllOld', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Newer Two'}).from(User).returning(ReturnValue.AllOld).execute();

assert.deepEqual(result, originalUser);
});

it('Update an item - return AllNew', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Newest Two'}).from(User).returning(ReturnValue.AllNew).execute();

assert.deepEqual(result, {...originalUser, name: 'Newest Two'});
});

it('Update an item - return None', async () =>
{
let result = await nodenamo.update({id: 2, name: 'Newer Two'}).from(User).returning(ReturnValue.None).execute();

assert.isUndefined(result);
});

it('Update an item - with all combinations', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Another Two'})
.from(User)
.where('#account=:account', {'#account': 'account'}, {':account': originalUser.account})
.returning(ReturnValue.AllOld)
.withVersionCheck()
.execute();

assert.deepEqual(result, originalUser);
});

it('On item', async () =>
{
let user = await nodenamo.get(6).from(User).execute<User>();
Expand Down
45 changes: 43 additions & 2 deletions spec/acceptance/hashRangeTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {assert as assert} from 'chai';
import { DBTable, DBColumn } from '../../src';
import { NodeNamo } from '../../src/nodeNamo';
import Config from './config';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { ReturnValue } from '../../src/interfaces/returnValue';

@DBTable({name:'nodenamo_acceptance_hashRangeTest'})
class User
Expand Down Expand Up @@ -361,7 +361,9 @@ describe('Hash-range tests', function ()

user.name = 'This Three';
user['extra'] = 'invalid';
await nodenamo.update(user).from(User).execute();
let result = await nodenamo.update(user).from(User).execute();

assert.isUndefined(result);

user = await nodenamo.get(3).from(User).execute();
assert.deepEqual(user, { id: 3, name: 'This Three', account: 2000, created: 2018 });
Expand Down Expand Up @@ -440,6 +442,45 @@ describe('Hash-range tests', function ()
assert.deepEqual(user, { id: 6, name: '', account: 3000, created: 2020 });
});

it('Update an item - return AllOld', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Newer Two'}).from(User).returning(ReturnValue.AllOld).execute();

assert.deepEqual(result, originalUser);
});

it('Update an item - return AllNew', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Newest Two'}).from(User).returning(ReturnValue.AllNew).execute();

assert.deepEqual(result, {...originalUser, name: 'Newest Two'});
});

it('Update an item - return None', async () =>
{
let result = await nodenamo.update({id: 2, name: 'Newer Two'}).from(User).returning(ReturnValue.None).execute();

assert.isUndefined(result);
});

it('Update an item - with all combinations', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Another Two'})
.from(User)
.where('#account=:account', {'#account': 'account'}, {':account': originalUser.account})
.returning(ReturnValue.AllOld)
.withVersionCheck()
.execute();

assert.deepEqual(result, originalUser);
});

it('On item', async () =>
{
let user = await nodenamo.get(6).from(User).execute<User>();
Expand Down
45 changes: 43 additions & 2 deletions spec/acceptance/hashTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {assert as assert} from 'chai';
import { DBTable, DBColumn } from '../../src';
import { NodeNamo } from '../../src/nodeNamo';
import Config from './config';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { ReturnValue } from '../../src/interfaces/returnValue';

@DBTable({name:'nodenamo_acceptance_hashTest'})
class User
Expand Down Expand Up @@ -288,7 +288,9 @@ describe('Hash tests', function ()

user.name = 'This Three';
user['extra'] = 'invalid';
await nodenamo.update(user).from(User).execute();
let result = await nodenamo.update(user).from(User).execute();

assert.isUndefined(result);

user = await nodenamo.get(3).from(User).execute();
assert.deepEqual(user, { id: 3, name: 'This Three', account: 3000 });
Expand Down Expand Up @@ -367,6 +369,45 @@ describe('Hash tests', function ()
assert.deepEqual((await nodenamo.list().from(User).execute()).items.length, 6);
});

it('Update an item - return AllOld', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Newer Two'}).from(User).returning(ReturnValue.AllOld).execute();

assert.deepEqual(result, originalUser);
});

it('Update an item - return AllNew', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Newest Two'}).from(User).returning(ReturnValue.AllNew).execute();

assert.deepEqual(result, {...originalUser, name: 'Newest Two'});
});

it('Update an item - return None', async () =>
{
let result = await nodenamo.update({id: 2, name: 'Newer Two'}).from(User).returning(ReturnValue.None).execute();

assert.isUndefined(result);
});

it('Update an item - with all combinations', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Another Two'})
.from(User)
.where('#account=:account', {'#account': 'account'}, {':account': originalUser.account})
.returning(ReturnValue.AllOld)
.withVersionCheck()
.execute();

assert.deepEqual(result, originalUser);
});

it('On item', async () =>
{
let user = await nodenamo.get(6).from(User).execute<User>();
Expand Down
30 changes: 29 additions & 1 deletion spec/acceptance/idTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {assert as assert} from 'chai';
import { DBTable, DBColumn } from '../../src';
import { NodeNamo } from '../../src/nodeNamo';
import Config from './config';
import { ReturnValue } from '../../src/interfaces/returnValue';

@DBTable({name:'nodenamo_acceptance_idTest'})
class User
Expand Down Expand Up @@ -232,8 +233,10 @@ describe('ID tests', function ()

user3.name = 'This Three';
user3['extra'] = 'invalid';
await nodenamo.update(user3).from(User).execute();
let result = await nodenamo.update(user3).from(User).execute();

assert.isUndefined(result);

user = await nodenamo.get(3).from(User).execute();
assert.deepEqual(user, {id:3, name: 'This Three', description: 'Description 3', secret: undefined, obj:{array:[], bool:true, empty:'', num:1, obj:{n:1,e:''}, str:'string'}});
});
Expand Down Expand Up @@ -272,6 +275,31 @@ describe('ID tests', function ()
assert.deepEqual(user, {id:4, name: 'Some Four', description: '', secret: undefined, obj:undefined});
});

it('Update an item - return AllOld', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'New Two'}).from(User).returning(ReturnValue.AllOld).execute();

assert.deepEqual(result, originalUser);
});

it('Update an item - return AllNew', async () =>
{
let originalUser = await nodenamo.get(2).from(User).execute<User>();

let result = await nodenamo.update({id: 2, name: 'Newest Two'}).from(User).returning(ReturnValue.AllNew).execute();

assert.deepEqual(result, {...originalUser, name: 'Newest Two'});
});

it('Update an item - return None', async () =>
{
let result = await nodenamo.update({id: 2, name: 'Newer Two'}).from(User).returning(ReturnValue.None).execute();

assert.isUndefined(result);
});

it('On item', async () =>
{
let user = await nodenamo.get(4).from(User).execute<User>();
Expand Down
1 change: 0 additions & 1 deletion spec/acceptance/indexConsistentTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {assert as assert} from 'chai';
import { DBTable, DBColumn } from '../../src';
import { NodeNamo } from '../../src/nodeNamo';
import Config from './config';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { Const } from '../../src/const';

@DBTable({name:'nodenamo_acceptance_indexConsistentTest'})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {assert as assert} from 'chai';
import { DBTable, DBColumn } from '../../src';
import { NodeNamo } from '../../src/nodeNamo';
import Config from './config';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';

@DBTable({name:'nodenamo_acceptance_lastEvaluatedKeyWithFilterAndPagingTest'})
class User
Expand Down
4 changes: 3 additions & 1 deletion spec/acceptance/marshallTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ describe('Marshall tests', function ()

person.children.push(person2);

await nodenamo.update(person).from(Person).execute();
let result = await nodenamo.update(person).from(Person).execute();

assert.isUndefined(result);

person = await nodenamo.get(0).from(Person).execute();
assert.equal(person.children.length, 2);
Expand Down
5 changes: 3 additions & 2 deletions spec/acceptance/multiValuesHashRangeTest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {assert as assert} from 'chai';
import { DBTable, DBColumn } from '../../src';
import { NodeNamo } from '../../src/nodeNamo';
import Config from './config';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';

@DBTable({name:'nodenamo_acceptance_multiValuesHashRangeTest'})
class User
Expand Down Expand Up @@ -270,7 +269,9 @@ describe('Multi-values Hash/Range tests', function ()

user.name = 'This Three';
user['extra'] = 'invalid';
await nodenamo.update(user).from(User).execute();
let result = await nodenamo.update(user).from(User).execute();

assert.isUndefined(result);

user = await nodenamo.get(3).from(User).execute();
assert.deepEqual(user, new User({ id: 3, name: 'This Three', roles: ['user', 'admin'], departments: ['IT', 'HR'], createdTimestamp: 2014 }));
Expand Down
Loading

0 comments on commit 684bd51

Please sign in to comment.