Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .lintstagedrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ linters:
- git add
"(src/**/*.spec.ts|test/**/*.ts)":
- prettier --write --config ./.prettierrc.yml
# FIXME tslint will not work because of the following error
# TODO LOW tslint will not work because of the following error
# ✖ tslint --project ./tsconfig.jest.json -t codeFrame --fix found some errors. Please fix them and try committing again.
#'/Users/michaelwittwer/dev/shiftcode/dynamo-easy/test/models/complex.model.ts' is not included in project.
# - tslint --project ./tsconfig.jest.json -t codeFrame --fix
Expand Down
16 changes: 0 additions & 16 deletions src/decorator/decorators.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@ import {
ModelWithABunchOfIndexes,
ModelWithCustomMapperModel,
ModelWithEnum,
ModelWithEnumDeclared,
ModelWithGSI,
NestedObject,
SimpleModel,
} from '../../test/models'
import { Form } from '../../test/models/real-world'
import { EnumType } from '../mapper'
import { GSIPartitionKey, GSISortKey, LSISortKey, PartitionKey, Property, SortedSet, SortKey, Transient } from './impl'
import { Model } from './impl/model/model.decorator'
import { Metadata, metadataForClass, metadataForModel, ModelMetadata } from './index'
Expand Down Expand Up @@ -336,20 +334,6 @@ describe('Decorators should add correct metadata', () => {
})
})

describe('enum', () => {
let metadata: Metadata<ModelWithEnumDeclared>

beforeEach(() => {
metadata = metadataForClass(ModelWithEnumDeclared)
})

it('should add enum type to property', () => {
const enumPropertyMetadata = metadata.forProperty('type')!
expect(enumPropertyMetadata.typeInfo).toBeDefined()
expect(enumPropertyMetadata.typeInfo).toEqual({ type: EnumType, isCustom: true })
})
})

describe('with inheritance', () => {
it('should override the table name', () => {
@Model({ tableName: 'super-table-name' })
Expand Down
11 changes: 0 additions & 11 deletions src/decorator/impl/enum/enum.decorator.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/decorator/impl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ export * from './collection/typed-set.decorator'
export * from './collection/typed-array.decorator'
// date
export * from './date/date.decorator'
// enum
export * from './enum/enum.decorator'
// index
export * from './index/secondary-index'
export * from './index/gsi-partition-key.decorator'
Expand Down
5 changes: 0 additions & 5 deletions src/decorator/metadata/property-metadata.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ export interface PropertyMetadata<T, R extends Attribute = Attribute> {
transient?: boolean
}

// todo: fixme
// export function hasSortKey(propertyMetadata: PropertyMetadata<any, any>): propertyMetadata is PropertyMetadata<any, any> & {} {
// return propertyMetadata.getSortKey() !== null
// }

export function hasGenericType(
propertyMetadata?: PropertyMetadata<any, any>,
): propertyMetadata is PropertyMetadata<any, any> & { typeInfo: { genericType: ModelConstructor<any> } } {
Expand Down
9 changes: 4 additions & 5 deletions src/dynamo/expression/condition-expression-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,7 @@ export function buildFilterExpression(
existingValueNames: string[] | undefined,
metadata: Metadata<any> | undefined,
): Expression {
// TODO LOW:INVESTIGATE is there a use case for undefined desired to be a value
// metadata rid of undefined values
// metadata get rid of undefined values
values = deepFilter(values, value => value !== undefined)

// check if provided values are valid for given operator
Expand Down Expand Up @@ -229,7 +228,7 @@ function buildDefaultConditionExpression(
let attribute: Attribute | null
switch (operator) {
case 'contains':
// TODO think about validation
// TODO LOW:VALIDATION think about concept
// validateValueForContains(values[0], propertyMetadata)
attribute = toDbOne(values[0], propertyMetadata)
break
Expand Down Expand Up @@ -301,14 +300,14 @@ function validateValues(operator: ConditionOperator, values?: any[]) {
}
}

// TODO should we support other types than String, Number, Binary (can we search a boolean set for example with boolean as string?)
// TODO LOW:VALIDATION should we support other types than String, Number, Binary (can we search a boolean set for example with boolean as string?)
// private static validateValueForContains(value: any, propertyMetadata?: PropertyMetadata<any>): { S: string } {
// let finalValue: { S: string }
// if (propertyMetadata && propertyMetadata.typeInfo) {
// switch (propertyMetadata.typeInfo.type) {
// case Array:
// case Set:
// // FIXME REVIEW the validation logic
// // TODO LOW:VALIDATION REVIEW the validation logic
// // const genericType = propertyMetadata.typeInfo.genericType
// // if ((!genericType && (typeof value === 'number' || typeof value === 'string' || typeof value === '')) || (
// // genericType &&
Expand Down
8 changes: 4 additions & 4 deletions src/dynamo/expression/request-expression-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { ConditionOperator } from './type/condition-operator.type'
import { ExpressionType } from './type/expression-type.type'
import { Expression } from './type/expression.type'
import { RequestConditionFunction } from './type/request-condition-function'
import { RequestSortKeyConditionFunction } from './type/sort-key-condition-function'
import { SortKeyConditionFunction } from './type/sort-key-condition-function'
import { UpdateActionDef } from './type/update-action-def'
import { UPDATE_ACTION_DEFS } from './type/update-action-defs.const'
import {
Expand Down Expand Up @@ -44,19 +44,19 @@ export function addCondition<R extends ConditionalParamsHost>(
export function addSortKeyCondition<R extends ConditionalParamsHost>(
keyName: keyof any,
request: R,
): RequestSortKeyConditionFunction<R>
): SortKeyConditionFunction<R>

export function addSortKeyCondition<T, R extends ConditionalParamsHost>(
keyName: keyof T,
request: R,
metadata: Metadata<T>,
): RequestSortKeyConditionFunction<R>
): SortKeyConditionFunction<R>

export function addSortKeyCondition<T, R extends ConditionalParamsHost>(
keyName: keyof T,
request: R,
metadata?: Metadata<T>,
): RequestSortKeyConditionFunction<R> {
): SortKeyConditionFunction<R> {
const f = (operator: ConditionOperator) => {
return (...values: any[]): R => {
return doAddCondition('KeyConditionExpression', <string>keyName, request, metadata, operator, ...values)
Expand Down
1 change: 0 additions & 1 deletion src/dynamo/expression/type/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export * from './expression-type.type'
export * from './function-operator.type'
export * from './request-condition-function'
export * from './sort-key-condition-function'
export * from './sort-key-condition-function.type'
export * from './update-action.type'
export * from './update-action-def'
export * from './update-action-defs.const'
Expand Down
6 changes: 1 addition & 5 deletions src/dynamo/expression/type/sort-key-condition-function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@ import { ConditionalParamsHost } from '../../operation-params.type'
* begins_with ( sortKeyName, :sortkeyval ) - true if the sort key value begins with a particular operand.
* (You cannot use this function with a sort key that is of formType Number.) Note that the function name begins_with is case-sensitive.
*/

export interface RequestSortKeyConditionFunction<R extends ConditionalParamsHost> {
// TODO LOW:TYPINGS narrow typing when possible -> https://github.com/Microsoft/TypeScript/issues/13573
// [key in OperatorAlias]: (...value: any[]) => R;
[key: string]: (...value: any[]) => R
export interface SortKeyConditionFunction<R extends ConditionalParamsHost> {
equals: (value: any) => R
eq: (value: any) => R
lt: (value: any) => R
Expand Down
15 changes: 0 additions & 15 deletions src/dynamo/expression/type/sort-key-condition-function.type.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { UpdateExpressionDefinitionFunction } from './update-expression-definiti
*/
export interface UpdateExpressionDefinitionChainTyped<T, K extends keyof T> {
/* ----------------------------------------------------------------
SET operation TODO add support for ifNotExists
SET operation TODO add support for ifNotExists (#16)
---------------------------------------------------------------- */
incrementBy: (value: number) => UpdateExpressionDefinitionFunction
decrementBy: (value: number) => UpdateExpressionDefinitionFunction
Expand Down Expand Up @@ -67,7 +67,7 @@ export interface UpdateExpressionDefinitionChainTyped<T, K extends keyof T> {
*/
export interface UpdateExpressionDefinitionChain {
/* ----------------------------------------------------------------
SET operation TODO add support for ifNotExists
SET operation TODO add support for ifNotExists (#16)
---------------------------------------------------------------- */
incrementBy: (value: number) => UpdateExpressionDefinitionFunction
decrementBy: (value: number) => UpdateExpressionDefinitionFunction
Expand Down
13 changes: 6 additions & 7 deletions src/dynamo/expression/update-expression-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,13 @@ export function buildUpdateExpression(
existingValueNames: string[] | undefined,
metadata: Metadata<any> | undefined,
): UpdateExpression {
// TODO LOW:INVESTIGATE is there a use case for undefined desired to be a value
// metadata rid of undefined values
// metadata get rid of undefined values
values = deepFilter(values, value => value !== undefined)

// TODO check if provided values are valid for given operation
// TODO LOW:VALIDATION check if provided values are valid for given operation
// validateValues(operation, values)

// load property metadat if model metadata was provided
// load property metadata if model metadata was provided
let propertyMetadata: PropertyMetadata<any> | undefined
if (metadata) {
propertyMetadata = metadata.forProperty(attributePath)
Expand Down Expand Up @@ -107,9 +106,9 @@ function buildDefaultExpression(
statement = values.map(pos => `${namePlaceholder}[${pos}]`).join(', ')
break
case 'add':
// TODO add validation to make sure expressionAttributeValue to be N(umber) or S(et)
// TODO LOW:VALIDATION add validation to make sure expressionAttributeValue to be N(umber) or S(et)
statement = `${namePlaceholder} ${valuePlaceholder}`
// TODO won't work for numbers, is always gonna be mapped to a collection type
// TODO LOW:VALIDATION won't work for numbers, is always gonna be mapped to a collection type
if ((values.length === 1 && Array.isArray(values[0])) || isSet(values[0])) {
// dealing with arr | set as single argument
} else {
Expand All @@ -118,7 +117,7 @@ function buildDefaultExpression(
}
break
case 'removeFromSet':
// TODO add validation to make sure expressionAttributeValue to be S(et)
// TODO LOW:VALIDATION add validation to make sure expressionAttributeValue to be S(et)
statement = `${namePlaceholder} ${valuePlaceholder}`
if ((values.length === 1 && Array.isArray(values[0])) || isSet(values[0])) {
// dealing with arr | set as single argument
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { BatchGetSingleTableResponse } from './batch-get-single-table.response'
const MAX_REQUEST_ITEM_COUNT = 100
const DEFAULT_TIME_SLOT = 1000

// TODO add support for indexes
export class BatchGetSingleTableRequest<T> {
readonly dynamoRx: DynamoRx
readonly params: BatchGetItemInput
Expand Down
4 changes: 2 additions & 2 deletions src/dynamo/request/query/query.request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Attributes, fromDb } from '../../../mapper'
import { ModelConstructor } from '../../../model'
import { DynamoRx } from '../../dynamo-rx'
import { addSortKeyCondition } from '../../expression/request-expression-builder'
import { RequestSortKeyConditionFunction } from '../../expression/type'
import { SortKeyConditionFunction } from '../../expression/type'
import { Request } from '../request.model'
import { QueryResponse } from './query.response'

Expand Down Expand Up @@ -41,7 +41,7 @@ export class QueryRequest<T> extends Request<T, QueryRequest<T>, QueryInput, Que
* used to define some condition for the sort key, use the secondary index to query based on a custom index
* @returns {RequestConditionFunction<T>}
*/
whereSortKey(): RequestSortKeyConditionFunction<QueryRequest<T>> {
whereSortKey(): SortKeyConditionFunction<QueryRequest<T>> {
let sortKey: keyof T | null
if (this.params.IndexName) {
const index = this.metadata.getIndex(this.params.IndexName)
Expand Down
2 changes: 1 addition & 1 deletion src/dynamo/request/request.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export abstract class Request<T,
return <any>this
}

// TODO TYPING how can we improve the typing to define the accepted value for condition function (see
// TODO LOW:TYPING how can we improve the typing to define the accepted value for condition function (see
// update2.function)
whereAttribute(attributePath: keyof T): RequestConditionFunction<R> {
return addCondition('FilterExpression', <string>attributePath, <any>this, this.metadata)
Expand Down
7 changes: 3 additions & 4 deletions src/dynamo/request/scan/scan.request.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,9 @@ describe('scan request', () => {

it('execSingle', async () => {
const res = await scanRequest.execSingle().toPromise()
// todo: uncomment when todo in scanRequest::execSingle was done
// expect(scanSpy).toHaveBeenCalled()
// expect(scanSpy.calls.mostRecent().args[0]).toBeDefined()
// expect(scanSpy.calls.mostRecent().args[0].Limit).toBe(1)
expect(scanSpy).toHaveBeenCalled()
expect(scanSpy.calls.mostRecent().args[0]).toBeDefined()
expect(scanSpy.calls.mostRecent().args[0].Limit).toBe(1)
expect(res).toEqual(jsItem)
})

Expand Down
2 changes: 1 addition & 1 deletion src/dynamo/request/scan/scan.request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class ScanRequest<T> extends Request<T, ScanRequest<T>, ScanInput, ScanRe
}

this.logger.debug('single request', params)
return this.dynamoRx.scan(this.params).pipe(
return this.dynamoRx.scan(params).pipe(
tap(response => this.logger.debug('response', response)),
map(this.mapFromDb),
map(r => r.Items && r.Items.length ? r.Items[0] : null),
Expand Down
1 change: 0 additions & 1 deletion src/mapper/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ export * from './type/attribute.type'
export * from './type/attribute-value-type.type'
export * from './type/attribute-type.type'
export * from './mapper'
export * from './type/enum.type'
export * from './type/null.type'
export * from './type/undefined.type'
export * from './type/binary.type'
Expand Down
20 changes: 9 additions & 11 deletions src/mapper/mapper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
OrganizationEvent,
Product,
ProductNested,
StringType,
Type,
} from '../../test/models'
import { IdMapper } from '../../test/models/model-with-custom-mapper.model'
Expand All @@ -45,7 +46,6 @@ import {
StringAttribute,
StringSetAttribute,
} from './type/attribute.type'
import { EnumType } from './type/enum.type'

describe('Mapper', () => {
describe('should map single values', () => {
Expand Down Expand Up @@ -83,13 +83,20 @@ describe('Mapper', () => {
expect(attrValue.NULL).toBe(true)
})

it('enum (no enum decorator)', () => {
it('enum (number)', () => {
const attrValue = <NumberAttribute>toDbOne(Type.FirstType)!
expect(attrValue).toBeDefined()
expect(keyOf(attrValue)).toBe('N')
expect(attrValue.N).toBe('0')
})

it('enum (string)', () => {
const attrValue = <StringAttribute>toDbOne(StringType.FirstType)!
expect(attrValue).toBeDefined()
expect(keyOf(attrValue)).toBe('S')
expect(attrValue.S).toBe('first')
})

it('enum (propertyMetadata -> no enum decorator)', () => {
const attrValue: Attribute = <MapAttribute>toDbOne(Type.FirstType, <any>{
typeInfo: { type: Object, isCustom: true },
Expand All @@ -99,15 +106,6 @@ describe('Mapper', () => {
expect(attrValue.M).toEqual({})
})

it('enum (with decorator)', () => {
const attrValue = <NumberAttribute>toDbOne(Type.FirstType, <any>{
typeInfo: { type: EnumType, isCustom: true },
})!
expect(attrValue).toBeDefined()
expect(keyOf(attrValue)).toBe('N')
expect(attrValue.N).toBe('0')
})

it('array -> SS (homogen, no duplicates)', () => {
const attrValue = <StringSetAttribute>toDbOne(['foo', 'bar'])!
expect(attrValue).toBeDefined()
Expand Down
Loading