11import { AttributeMap , AttributeValue } from 'aws-sdk/clients/dynamodb'
2- import { curryRight } from 'lodash'
32import { Metadata } from '../../decorator/metadata/metadata'
43import { PropertyMetadata } from '../../decorator/metadata/property-metadata.model'
54import { Mapper } from '../../mapper/mapper'
5+ import { Util } from '../../mapper/util'
66import { resolveAttributeNames } from './functions/attribute-names.function'
7- import { isFunctionOperator } from './functions/is-function-operator.function'
8- import { isNoParamFunctionOperator } from './functions/is-no-param-function-operator.function'
97import { uniqAttributeValueName } from './functions/unique-attribute-value-name.function'
108import { Expression } from './type/expression.type'
11- import { UpdateAction , UpdateActionDef } from './type/update-action.type'
9+ import { UpdateActionDef } from './type/update-action-def'
10+ import { UpdateAction } from './type/update-action.type'
1211import { UpdateExpression } from './type/update-expression.type'
1312
1413export class UpdateExpressionBuilder {
@@ -32,6 +31,7 @@ export class UpdateExpressionBuilder {
3231 ) : UpdateExpression {
3332 // TODO investigate is there a use case for undefined desired to be a value
3433 // get rid of undefined values
34+ // FIXME should this not be a deep filter?
3535 values = values . filter ( value => value !== undefined )
3636
3737 // TODO check if provided values are valid for given operation
@@ -83,22 +83,61 @@ export class UpdateExpressionBuilder {
8383 ) : UpdateExpression {
8484 let statement : string
8585 switch ( operator . action ) {
86- case 'set' :
87- statement = `${ namePlaceholder } = ${ valuePlaceholder } `
88- break
8986 case 'incrementBy' :
9087 statement = `${ namePlaceholder } = ${ namePlaceholder } + ${ valuePlaceholder } `
9188 break
9289 case 'decrementBy' :
9390 statement = `${ namePlaceholder } = ${ namePlaceholder } - ${ valuePlaceholder } `
9491 break
92+ case 'set' :
93+ statement = `${ namePlaceholder } = ${ valuePlaceholder } `
94+ break
95+ case 'appendToList' :
96+ const position = values . length > 1 ? values [ values . length - 1 ] || 'END' : 'END'
97+ switch ( position ) {
98+ case 'END' :
99+ statement = `${ namePlaceholder } = list_append(${ namePlaceholder } , ${ valuePlaceholder } )`
100+ break
101+ case 'START' :
102+ statement = `${ namePlaceholder } = list_append(${ valuePlaceholder } , ${ namePlaceholder } )`
103+ break
104+ default :
105+ throw new Error ( "make sure to provide either 'START' or 'END' as value for position argument" )
106+ }
107+ break
108+ case 'remove' :
109+ statement = `${ namePlaceholder } `
110+ break
111+ case 'removeFromListAt' :
112+ const positions : number [ ] = values
113+ statement = values . map ( pos => `${ namePlaceholder } [${ pos } ]` ) . join ( ', ' )
114+ break
115+ case 'add' :
116+ // TODO add validation to make sure expressionAttributeValue to be N(umber) or S(et)
117+ statement = `${ namePlaceholder } ${ valuePlaceholder } `
118+ // TODO won't work for numbers, is always gonna be mapped to a collectio type
119+ if ( ( values . length === 1 && Array . isArray ( values [ 0 ] ) ) || Util . isSet ( values [ 0 ] ) ) {
120+ // dealing with arr | set as single argument
121+ } else {
122+ // dealing with vararg
123+ values [ 0 ] = [ ...values ]
124+ }
125+ break
126+ case 'removeFromSet' :
127+ // TODO add validation to make sure expressionAttributeValue to be S(et)
128+ statement = `${ namePlaceholder } ${ valuePlaceholder } `
129+ if ( ( values . length === 1 && Array . isArray ( values [ 0 ] ) ) || Util . isSet ( values [ 0 ] ) ) {
130+ // dealing with arr | set as single argument
131+ } else {
132+ // dealing with vararg
133+ values [ 0 ] = [ ...values ]
134+ }
135+ break
95136 default :
96- throw new Error ( ' no implementation' )
137+ throw new Error ( ` no implementation for action ${ operator . action } ` )
97138 }
98139
99- // = [namePlaceholder, operator, valuePlaceholder].join(' ')
100- // FIXME add hasValue logic
101- const hasValue = true
140+ const hasValue = ! UpdateExpressionBuilder . isNoValueAction ( operator . action )
102141
103142 const attributeValues : AttributeMap = { }
104143 if ( hasValue ) {
@@ -116,4 +155,12 @@ export class UpdateExpressionBuilder {
116155 attributeValues,
117156 }
118157 }
158+
159+ private static isNoValueAction ( action : UpdateAction ) {
160+ return (
161+ action === 'remove' ||
162+ // special cases: values are used in statement instaed of expressionValues
163+ action === 'removeFromListAt'
164+ )
165+ }
119166}
0 commit comments