From 8d144ff6cfc8069a0a0f90470e3ba2d1141b3d2c Mon Sep 17 00:00:00 2001 From: Michael Wittwer Date: Mon, 16 Oct 2017 13:50:57 +0200 Subject: [PATCH] fix(batchRequest): make sure the response can be mapped --- src/dynamo/batchget/batch-get.request.ts | 47 +++++++++---------- src/dynamo/batchget/batch-get.response.ts | 2 + src/dynamo/primary-key.type.ts | 4 ++ .../batch-get-single-table.request.ts | 9 +--- 4 files changed, 28 insertions(+), 34 deletions(-) create mode 100644 src/dynamo/batchget/batch-get.response.ts create mode 100644 src/dynamo/primary-key.type.ts diff --git a/src/dynamo/batchget/batch-get.request.ts b/src/dynamo/batchget/batch-get.request.ts index 386903a16..82ed4198c 100644 --- a/src/dynamo/batchget/batch-get.request.ts +++ b/src/dynamo/batchget/batch-get.request.ts @@ -1,5 +1,5 @@ import { AttributeMap, BatchGetItemInput } from 'aws-sdk/clients/dynamodb' -import { isObject } from 'lodash' +import { isObject, isString } from 'lodash' import { Observable } from 'rxjs/Observable' import { MetadataHelper } from '../../decorator/metadata/metadata-helper' import { Mapper } from '../../mapper/mapper' @@ -7,23 +7,17 @@ import { ModelConstructor } from '../../model/model-constructor' import { DEFAULT_SESSION_VALIDITY_ENSURER } from '../default-session-validity-ensurer.const' import { DEFAULT_TABLE_NAME_RESOLVER } from '../default-table-name-resolver.const' import { DynamoRx } from '../dynamo-rx' +import { PrimaryKey } from '../primary-key.type' import { REGEX_TABLE_NAME } from '../request/regex' import { SessionValidityEnsurer } from '../session-validity-ensurer.type' import { TableNameResolver } from '../table-name-resolver.type' +import { BatchGetResponse } from './batch-get.response' -interface TableConfig { - tableName: string - modelClazz: ModelConstructor - keys: any[] -} - -// tslint:disable-next-line:interface-over-type-literal -export type BatchGetItemResponse = { [tableName: string]: any[] } - +// TODO add support for indexes export class BatchGetRequest { private readonly dynamoRx: DynamoRx - private tables: Map> = new Map() + private tables: Map> = new Map() readonly params: BatchGetItemInput constructor( @@ -41,11 +35,12 @@ export class BatchGetRequest { * @param {any[]} keys either a simple string for partition key or an object with partitionKey and sortKey * @returns {BatchGetSingleTableRequest} */ - forModel(modelClazz: ModelConstructor, keys: any[]): BatchGetRequest { + forModel(modelClazz: ModelConstructor, keys: Array): BatchGetRequest { const tableName = this.getTableName(modelClazz, this.tableNameResolver) if (this.tables.has(tableName)) { throw new Error('table name already exists, please provide all the keys for the same table at once') } + this.tables.set(tableName, modelClazz) const metadata = MetadataHelper.get(modelClazz) const attributeMaps: AttributeMap[] = [] @@ -54,8 +49,15 @@ export class BatchGetRequest { keys.forEach(key => { const idOb: AttributeMap = {} - if (isObject(key)) { - // TODO add some more checks + if (isString(key)) { + // got a simple primary key + const value = Mapper.toDbOne(key) + if (value === null) { + throw Error('please provide an actual value for partition key') + } + + idOb[metadata.getPartitionKey()] = value + } else if (isObject(key) && key.partitionKey !== undefined && key.partitionKey !== null) { // got a composite primary key // partition key @@ -73,13 +75,7 @@ export class BatchGetRequest { idOb[metadata.getSortKey()!] = mappedSortKey } else { - // got a simple primary key - const value = Mapper.toDbOne(key) - if (value === null) { - throw Error('please provide an actual value for partition key') - } - - idOb[metadata.getPartitionKey()] = value + throw new Error('a key must either be a string or a PrimaryKey') } attributeMaps.push(idOb) @@ -88,21 +84,20 @@ export class BatchGetRequest { this.params.RequestItems[tableName] = { Keys: attributeMaps, } + return this } execFullResponse() {} - // TODO fix any - // TODO add support for indexes - exec(): Observable { + exec(): Observable { return this.dynamoRx.batchGetItems(this.params).map(response => { - const r = {} + const r = {} if (response.Responses && Object.keys(response.Responses).length) { const responses: { [key: string]: AttributeMap } = {} Object.keys(response.Responses).forEach(tableName => { const mapped = response.Responses![tableName].map(attributeMap => - Mapper.fromDb(attributeMap, this.tables.get(tableName)!.modelClazz) + Mapper.fromDb(attributeMap, this.tables.get(tableName)) ) r[tableName] = mapped }) diff --git a/src/dynamo/batchget/batch-get.response.ts b/src/dynamo/batchget/batch-get.response.ts new file mode 100644 index 000000000..d104fb824 --- /dev/null +++ b/src/dynamo/batchget/batch-get.response.ts @@ -0,0 +1,2 @@ +// tslint:disable-next-line:interface-over-type-literal +export type BatchGetResponse = { [tableName: string]: any[] } diff --git a/src/dynamo/primary-key.type.ts b/src/dynamo/primary-key.type.ts new file mode 100644 index 000000000..4d74dd3ab --- /dev/null +++ b/src/dynamo/primary-key.type.ts @@ -0,0 +1,4 @@ +export interface PrimaryKey { + partitionKey: any + sortKey?: any +} diff --git a/src/dynamo/request/batchgetsingletable/batch-get-single-table.request.ts b/src/dynamo/request/batchgetsingletable/batch-get-single-table.request.ts index 4706e9a2f..9e0ebf875 100644 --- a/src/dynamo/request/batchgetsingletable/batch-get-single-table.request.ts +++ b/src/dynamo/request/batchgetsingletable/batch-get-single-table.request.ts @@ -8,12 +8,7 @@ import { ModelConstructor } from '../../../model/model-constructor' import { DynamoRx } from '../../dynamo-rx' import { BatchGetSingleTableResponse } from './batch-get-single-table.response' -interface TableConfig { - tableName: string - modelClazz: ModelConstructor - keys: any[] -} - +// TODO add support for indexes export class BatchGetSingleTableRequest { readonly dynamoRx: DynamoRx readonly params: BatchGetItemInput @@ -67,8 +62,6 @@ export class BatchGetSingleTableRequest { }) } - // TODO fix any - // TODO add support for indexes exec(): Observable { return this.dynamoRx.batchGetItems(this.params).map(response => { if (response.Responses && Object.keys(response.Responses).length && response.Responses[this.tableName]) {