Skip to content

Commit bebee7e

Browse files
Merge pull request #180 from shiftcode/#179-various
#179 write requests execFullResponse does not map items
2 parents dd26341 + 1c10d76 commit bebee7e

File tree

12 files changed

+223
-83
lines changed

12 files changed

+223
-83
lines changed

src/dynamo/request/delete/delete.request.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
22
import { ComplexModel, SimpleWithPartitionKeyModel } from '../../../../test/models'
33
import { updateDynamoEasyConfig } from '../../../config/update-config.function'
4+
import { DynamoDbWrapper } from '../../dynamo-db-wrapper'
45
import { DeleteRequest } from './delete.request'
56

67
describe('delete request', () => {
@@ -72,4 +73,28 @@ describe('delete request', () => {
7273
expect(logInfoData.includes(sampleResponse)).toBeTruthy()
7374
})
7475
})
76+
77+
describe('typings', () => {
78+
// tests basically only exists to be not valid when typings would be wrong
79+
let req: DeleteRequest<SimpleWithPartitionKeyModel>
80+
let dynamoDbWrapperMock: DynamoDbWrapper
81+
82+
beforeEach(() => {
83+
dynamoDbWrapperMock = <any>{
84+
deleteItem: () =>
85+
Promise.resolve({
86+
Attributes: {
87+
id: { S: 'myId' },
88+
age: { N: '20' },
89+
},
90+
}),
91+
}
92+
req = new DeleteRequest(<any>dynamoDbWrapperMock, SimpleWithPartitionKeyModel, 'myKey')
93+
})
94+
95+
it('exec, ALL_OLD', async () => {
96+
const result: SimpleWithPartitionKeyModel = await req.returnValues('ALL_OLD').exec()
97+
expect(result).toEqual({ id: 'myId', age: 20 })
98+
})
99+
})
75100
})
Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
2-
import { promiseTap } from '../../../helper/promise-tap.function'
32
import { createLogger, Logger } from '../../../logger/logger'
43
import { createKeyAttributes } from '../../../mapper/mapper'
54
import { ModelConstructor } from '../../../model/model-constructor'
65
import { Omit } from '../../../model/omit.type'
76
import { DynamoDbWrapper } from '../../dynamo-db-wrapper'
87
import { WriteRequest } from '../write.request'
8+
import { DeleteResponse } from './delete.response'
99

10-
type DeleteRequestReturnT<T> = Omit<DeleteRequest<T>, 'exec'> & { exec(): Promise<T> }
10+
type DeleteRequestReturnT<T> = Omit<Omit<DeleteRequest<T>, 'exec'>,'execFullResponse'> & {
11+
exec(): Promise<T>
12+
execFullResponse(): Promise<DeleteResponse<T>>
13+
}
1114

12-
export class DeleteRequest<T> extends WriteRequest<T, DynamoDB.DeleteItemInput, DeleteRequest<T>> {
15+
/**
16+
* Request class for the DeleteItem operation.
17+
*/
18+
export class DeleteRequest<T> extends WriteRequest<T, DynamoDB.DeleteItemInput, DynamoDB.DeleteItemOutput, DeleteRequest<T>> {
1319
protected readonly logger: Logger
1420

1521
constructor(dynamoDBWrapper: DynamoDbWrapper, modelClazz: ModelConstructor<T>, partitionKey: any, sortKey?: any) {
@@ -26,20 +32,7 @@ export class DeleteRequest<T> extends WriteRequest<T, DynamoDB.DeleteItemInput,
2632
return this
2733
}
2834

29-
/*
30-
* kind a hacky - this is just for typing reasons so Promise<void> is the default return type when not defining a
31-
* returnValues other than NONE
32-
*
33-
* const valueVoid = new DeleteRequest(...).exec()
34-
* const valueMyModel = new DeleteRequest(...).returnValues('ALL_OLD').exec()
35-
*/
36-
exec(): Promise<void> {
37-
return <Promise<void>>super.exec()
38-
}
39-
40-
execFullResponse(): Promise<DynamoDB.DeleteItemOutput> {
41-
this.logger.debug('request', this.params)
42-
return this.dynamoDBWrapper.deleteItem(this.params)
43-
.then(promiseTap(response => this.logger.debug('response', response)))
35+
protected doRequest(params: DynamoDB.DeleteItemInput): Promise<DynamoDB.DeleteItemOutput> {
36+
return this.dynamoDBWrapper.deleteItem(params)
4437
}
4538
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
2+
3+
export interface DeleteResponse<T> {
4+
ConsumedCapacity?: DynamoDB.ConsumedCapacity
5+
ItemCollectionMetrics?: DynamoDB.ItemCollectionMetrics
6+
Item: T
7+
}
8+

src/dynamo/request/public-api.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
export * from './delete/delete.request'
2+
export * from './delete/delete.response'
23
export * from './get/get.request'
34
export * from './get/get.response'
45
export * from './put/put.request'
6+
export * from './put/put.response'
57
export * from './query/query.request'
68
export * from './query/query.response'
79
export * from './scan/scan.request'
810
export * from './scan/scan.response'
911
export * from './update/update.request'
12+
export * from './update/update.response'
1013
export * from './batchgetsingletable/batch-get-single-table.request'
1114
export * from './batchgetsingletable/batch-get-single-table.response'
1215
export * from './read-many.request'

src/dynamo/request/put/put.request.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
22
import { SimpleWithPartitionKeyModel } from '../../../../test/models'
33
import { updateDynamoEasyConfig } from '../../../config/update-config.function'
4+
import { DynamoDbWrapper } from '../../dynamo-db-wrapper'
45
import { PutRequest } from './put.request'
56

67
describe('put request', () => {
@@ -67,4 +68,28 @@ describe('put request', () => {
6768
expect(logInfoData.includes(sampleResponse)).toBeTruthy()
6869
})
6970
})
71+
72+
describe('typings', () => {
73+
// tests basically only exists to be not valid when typings would be wrong
74+
let req: PutRequest<SimpleWithPartitionKeyModel>
75+
let dynamoDbWrapperMock: DynamoDbWrapper
76+
77+
beforeEach(() => {
78+
dynamoDbWrapperMock = <any>{
79+
putItem: () =>
80+
Promise.resolve({
81+
Attributes: {
82+
id: { S: 'myId' },
83+
age: { N: '20' },
84+
},
85+
}),
86+
}
87+
req = new PutRequest(<any>dynamoDbWrapperMock, SimpleWithPartitionKeyModel, { id: 'myKey', age: 20 })
88+
})
89+
90+
it('exec, ALL_OLD', async () => {
91+
const result: SimpleWithPartitionKeyModel = await req.returnValues('ALL_OLD').exec()
92+
expect(result).toEqual({ id: 'myId', age: 20 })
93+
})
94+
})
7095
})
Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
2-
import { promiseTap } from '../../../helper/promise-tap.function'
32
import { createLogger, Logger } from '../../../logger/logger'
43
import { toDb } from '../../../mapper/mapper'
54
import { ModelConstructor } from '../../../model/model-constructor'
65
import { Omit } from '../../../model/omit.type'
76
import { DynamoDbWrapper } from '../../dynamo-db-wrapper'
87
import { createIfNotExistsCondition } from '../../expression/create-if-not-exists-condition.function'
98
import { WriteRequest } from '../write.request'
9+
import { PutResponse } from './put.response'
1010

11-
type PutRequestReturnT<T> = Omit<PutRequest<T>, 'exec'> & { exec(): Promise<DynamoDB.AttributeMap> }
12-
11+
type PutRequestReturnT<T> = Omit<Omit<PutRequest<T>, 'exec'>, 'execFullResponse'> & {
12+
exec(): Promise<T>
13+
execFullResponse(): Promise<PutResponse<T>>
14+
}
1315

14-
export class PutRequest<T> extends WriteRequest<T, DynamoDB.PutItemInput, PutRequest<T>> {
16+
/**
17+
* Request class for the PutItem operation.
18+
*/
19+
export class PutRequest<T> extends WriteRequest<T, DynamoDB.PutItemInput, DynamoDB.PutItemOutput, PutRequest<T>> {
1520
protected readonly logger: Logger
1621

1722
constructor(dynamoDBWrapper: DynamoDbWrapper, modelClazz: ModelConstructor<T>, item: T) {
@@ -22,7 +27,6 @@ export class PutRequest<T> extends WriteRequest<T, DynamoDB.PutItemInput, PutReq
2227

2328
/**
2429
* Adds a condition expression to the request, which makes sure the item will only be saved if the id does not exist
25-
* @returns {PutRequest<T>}
2630
*/
2731
ifNotExists(predicate: boolean = true): PutRequest<T> {
2832
if (predicate) {
@@ -38,20 +42,7 @@ export class PutRequest<T> extends WriteRequest<T, DynamoDB.PutItemInput, PutReq
3842
return this
3943
}
4044

41-
/*
42-
* kind a hacky - this is just for typing reasons so Promise<void> is the default return type when not defining a
43-
* returnValues other than NONE
44-
*
45-
* const valueVoid = new DeleteRequest(...).exec()
46-
* const valueMyModel = new DeleteRequest(...).returnValues('ALL_OLD').exec()
47-
*/
48-
exec(): Promise<void> {
49-
return <Promise<void>>super.exec()
50-
}
51-
52-
execFullResponse(): Promise<DynamoDB.PutItemOutput> {
53-
this.logger.debug('request', this.params)
54-
return this.dynamoDBWrapper.putItem(this.params)
55-
.then(promiseTap(response => this.logger.debug('response', response)))
45+
protected doRequest(params: DynamoDB.PutItemInput): Promise<DynamoDB.PutItemOutput> {
46+
return this.dynamoDBWrapper.putItem(params)
5647
}
5748
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
2+
3+
export interface PutResponse<T> {
4+
ConsumedCapacity?: DynamoDB.ConsumedCapacity
5+
ItemCollectionMetrics?: DynamoDB.ItemCollectionMetrics
6+
Item: T
7+
}
8+

src/dynamo/request/update/update.request.spec.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { Duration } from '../../../../test/models/duration.model'
1010
import { SpecialCasesModel } from '../../../../test/models/special-cases-model.model'
1111
import { updateDynamoEasyConfig } from '../../../config/update-config.function'
1212
import { dateToStringMapper } from '../../../mapper/custom/date-to-string.mapper'
13+
import { DynamoDbWrapper } from '../../dynamo-db-wrapper'
1314
import { update, update2 } from '../../expression/logical-operator/update.function'
1415
import { UpdateRequest } from './update.request'
1516

@@ -220,4 +221,33 @@ describe('update request', () => {
220221
expect(logInfoData.includes(sampleResponse)).toBeTruthy()
221222
})
222223
})
224+
225+
describe('typings', () => {
226+
// tests basically only exists to be not valid when typings would be wrong
227+
let req: UpdateRequest<SimpleWithPartitionKeyModel>
228+
let dynamoDbWrapperMock: DynamoDbWrapper
229+
230+
beforeEach(() => {
231+
dynamoDbWrapperMock = <any>{
232+
updateItem: () =>
233+
Promise.resolve({
234+
Attributes: {
235+
id: { S: 'myId' },
236+
age: { N: '20' },
237+
},
238+
}),
239+
}
240+
req = new UpdateRequest(<any>dynamoDbWrapperMock, SimpleWithPartitionKeyModel, 'myKey')
241+
})
242+
243+
it('exec, ALL_OLD', async () => {
244+
const result: SimpleWithPartitionKeyModel = await req.returnValues('ALL_OLD').exec()
245+
expect(result).toEqual({ id: 'myId', age: 20 })
246+
})
247+
248+
it('exec, UPDATED_OLD', async () => {
249+
const result: Partial<SimpleWithPartitionKeyModel> = await req.returnValues('UPDATED_OLD').exec()
250+
expect(result).toEqual({ id: 'myId', age: 20 })
251+
})
252+
})
223253
})
Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
2-
import { promiseTap } from '../../../helper/promise-tap.function'
32
import { createLogger, Logger } from '../../../logger/logger'
43
import { createKeyAttributes } from '../../../mapper/mapper'
54
import { ModelConstructor } from '../../../model/model-constructor'
@@ -10,11 +9,22 @@ import { addUpdate } from '../../expression/request-expression-builder'
109
import { RequestUpdateFunction } from '../../expression/type/update-expression-definition-chain'
1110
import { UpdateExpressionDefinitionFunction } from '../../expression/type/update-expression-definition-function'
1211
import { WriteRequest } from '../write.request'
12+
import { UpdateResponse } from './update.response'
1313

14-
type UpdateRequestReturnT<T> = Omit<UpdateRequest<T>, 'exec'> & { exec(): Promise<T> }
15-
type UpdateRequestReturnPartialT<T> = Omit<UpdateRequest<T>, 'exec'> & { exec(): Promise<Partial<T>> }
14+
type UpdateRequestReturnT<T> = Omit<Omit<UpdateRequest<T>, 'exec'>, 'execFullResponse'> & {
15+
exec(): Promise<T>
16+
execFullResponse(): Promise<UpdateResponse<T>>
17+
}
18+
type UpdateRequestReturnPartialT<T> = Omit<Omit<UpdateRequest<T>, 'exec'>, 'execFullResponse'> & {
19+
exec(): Promise<Partial<T>>
20+
execFullResponse(): Promise<UpdateResponse<T>>
21+
}
22+
23+
/**
24+
* Request class for the UpdateItem operation.
25+
*/
26+
export class UpdateRequest<T> extends WriteRequest<T, DynamoDB.UpdateItemInput, DynamoDB.UpdateItemOutput, UpdateRequest<T>> {
1627

17-
export class UpdateRequest<T> extends WriteRequest<T, DynamoDB.UpdateItemInput, UpdateRequest<T>> {
1828
protected readonly logger: Logger
1929

2030
constructor(dynamoDBWrapper: DynamoDbWrapper, modelClazz: ModelConstructor<T>, partitionKey: any, sortKey?: any) {
@@ -23,10 +33,18 @@ export class UpdateRequest<T> extends WriteRequest<T, DynamoDB.UpdateItemInput,
2333
this.params.Key = createKeyAttributes(this.metadata, partitionKey, sortKey)
2434
}
2535

36+
/**
37+
* create and add a single update operation
38+
* @example req.updateAttribute('path.to.attr').set('newVal')
39+
*/
2640
updateAttribute<K extends keyof T>(attributePath: K): RequestUpdateFunction<UpdateRequest<T>, T, K> {
2741
return addUpdate(attributePath, this, this.metadata)
2842
}
2943

44+
/**
45+
* add multiple update operations comma separated
46+
* @example req.operations(update('path.to.attr).set('newVal'), ... )
47+
*/
3048
operations(...updateDefFns: UpdateExpressionDefinitionFunction[]): UpdateRequest<T> {
3149
prepareAndAddUpdateExpressions(this.metadata, this.params, updateDefFns)
3250
return this
@@ -40,20 +58,7 @@ export class UpdateRequest<T> extends WriteRequest<T, DynamoDB.UpdateItemInput,
4058
return this
4159
}
4260

43-
/*
44-
* kind a hacky - this is just for typing reasons so Promise<void> is the default return type when not defining a
45-
* returnValues other than NONE
46-
*
47-
* const valueVoid = new DeleteRequest(...).exec()
48-
* const valueMyModel = new DeleteRequest(...).returnValues('ALL_OLD').exec()
49-
*/
50-
exec(): Promise<void> {
51-
return <Promise<void>>super.exec()
52-
}
53-
54-
execFullResponse(): Promise<DynamoDB.UpdateItemOutput> {
55-
this.logger.debug('request', this.params)
61+
protected doRequest(params: DynamoDB.UpdateItemInput): Promise<DynamoDB.UpdateItemOutput> {
5662
return this.dynamoDBWrapper.updateItem(this.params)
57-
.then(promiseTap(response => this.logger.debug('response', response)))
5863
}
5964
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
2+
3+
export interface UpdateResponse<T> {
4+
ConsumedCapacity?: DynamoDB.ConsumedCapacity
5+
ItemCollectionMetrics?: DynamoDB.ItemCollectionMetrics
6+
Item: T
7+
}
8+

0 commit comments

Comments
 (0)