Skip to content
Closed
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: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
"husky": "^3.0.4",
"jest": "^24.9.0",
"lint-staged": "^9.2.3",
"lodash": "^4.17.11",
"lodash.camelcase": "^4.3.0",
"prettier": "^1.18.2",
"reflect-metadata": "^0.1.13",
Expand All @@ -87,7 +86,6 @@
},
"peerDependencies": {
"aws-sdk": "^2.401.0",
"lodash": "^4.17.11",
"reflect-metadata": "^0.1.12",
"tslib": "^1.10.0",
"uuid": "^3.3.2"
Expand Down
2 changes: 1 addition & 1 deletion src/decorator/impl/model/model.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @module decorators
*/
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
import { kebabCase } from 'lodash'
import { kebabCase } from '../../../helper/kebab-case.function'
import { ModelMetadata } from '../../metadata/model-metadata.model'
import { PropertyMetadata } from '../../metadata/property-metadata.model'
import { SecondaryIndex } from '../index/secondary-index'
Expand Down
9 changes: 4 additions & 5 deletions src/dynamo/expression/condition-expression-builder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// tslint:disable:max-classes-per-file
import { has } from 'lodash'
import { ComplexModel } from '../../../test/models'
import { Form, FormId, formIdMapper, FormType } from '../../../test/models/real-world'
import { CollectionProperty } from '../../decorator/impl/collection/collection-property.decorator'
Expand Down Expand Up @@ -304,9 +303,9 @@ describe('expressions', () => {

expect(condition.attributeValues).toBeDefined()
expect(Object.keys(condition.attributeValues).length).toBe(2)
expect(has(condition.attributeValues, ':counter')).toBeTruthy()
expect(':counter' in condition.attributeValues).toBeTruthy()
expect(condition.attributeValues[':counter']).toEqual({ N: '2' })
expect(has(condition.attributeValues, ':counter_2')).toBeTruthy()
expect(':counter_2' in condition.attributeValues).toBeTruthy()
expect(condition.attributeValues[':counter_2']).toEqual({ N: '5' })
})

Expand All @@ -331,9 +330,9 @@ describe('expressions', () => {

expect(condition.attributeValues).toBeDefined()
expect(Object.keys(condition.attributeValues).length).toBe(2)
expect(has(condition.attributeValues, ':creationDate')).toBeTruthy()
expect(':creationDate' in condition.attributeValues).toBeTruthy()
expect(condition.attributeValues[':creationDate']).toEqual({ S: date1.toISOString() })
expect(has(condition.attributeValues, ':creationDate_2')).toBeTruthy()
expect(':creationDate_2' in condition.attributeValues).toBeTruthy()
expect(condition.attributeValues[':creationDate_2']).toEqual({ S: date2.toISOString() })
})
})
Expand Down
3 changes: 2 additions & 1 deletion src/dynamo/expression/condition-expression-builder.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/**
* @module expression
*/
import { curry, isPlainObject } from 'lodash'
import { Metadata } from '../../decorator/metadata/metadata'
import {
alterCollectionPropertyMetadataForSingleItem,
PropertyMetadata,
} from '../../decorator/metadata/property-metadata.model'
import { curry } from '../../helper/curry.function'
import { isPlainObject } from '../../helper/is-plain-object.function'
import { toDbOne } from '../../mapper/mapper'
import { Attribute, Attributes } from '../../mapper/type/attribute.type'
import { typeOf } from '../../mapper/util'
Expand Down
4 changes: 3 additions & 1 deletion src/dynamo/expression/param-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
* @module expression
*/
import * as DynamoDB from 'aws-sdk/clients/dynamodb'
import { isEmpty, isString } from 'lodash'
import { isEmpty } from '../../helper/is-empty.function'
import { isString } from '../../helper/is-string.function'
import { ConditionalParams } from '../operation-params.type'
import { resolveAttributeValueNameConflicts } from './functions/resolve-attribute-value-name-conflicts.function'
import { Expression } from './type/expression.type'
import { UpdateActionKeyword } from './type/update-action-keyword.type'

/**
* @hidden
*/
Expand Down
2 changes: 1 addition & 1 deletion src/dynamo/expression/request-expression-builder.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* @module expression
*/
import { curry } from 'lodash'
import { Metadata } from '../../decorator/metadata/metadata'
import { curry } from '../../helper/curry.function'
import { ConditionalParamsHost, UpdateParamsHost } from '../operation-params.type'
import { StandardRequest } from '../request/standard.request'
import { buildFilterExpression } from './condition-expression-builder'
Expand Down
17 changes: 17 additions & 0 deletions src/helper/curry.function.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { curry } from './curry.function'

function a(x: number, y: string, z: boolean | null) {
return [x, y, z]
}

describe('curry', () => {
it('should work (w/o arity)', () => {
expect(curry(a)(2)('ok')(true)).toEqual([2, 'ok', true])
expect(curry(a)(4, 'NOK')(false)).toEqual([4, 'NOK', false])
expect(curry(a)(6, 'FOO', null)).toEqual([6, 'FOO', null])
})

it('should work (w/ arity)', () => {
expect(typeof curry(a, 4)(6, 'FOO', null)).toEqual('function')
})
})
157 changes: 157 additions & 0 deletions src/helper/curry.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// copied from just-curry-it

interface CurriedFunction1<T1, R> {
(): CurriedFunction1<T1, R>

(t1: T1): R
}

interface CurriedFunction2<T1, T2, R> {
(): CurriedFunction2<T1, T2, R>

(t1: T1): CurriedFunction1<T2, R>

(t1: T1, t2: T2): R
}

interface CurriedFunction3<T1, T2, T3, R> {
(): CurriedFunction3<T1, T2, T3, R>

(t1: T1): CurriedFunction2<T2, T3, R>

(t1: T1, t2: T2): CurriedFunction1<T3, R>

(t1: T1, t2: T2, t3: T3): R
}

interface CurriedFunction4<T1, T2, T3, T4, R> {
(): CurriedFunction4<T1, T2, T3, T4, R>

(t1: T1): CurriedFunction3<T2, T3, T4, R>

(t1: T1, t2: T2): CurriedFunction2<T3, T4, R>

(t1: T1, t2: T2, t3: T3): CurriedFunction1<T4, R>

(t1: T1, t2: T2, t3: T3, t4: T4): R
}

interface CurriedFunction5<T1, T2, T3, T4, T5, R> {
(): CurriedFunction5<T1, T2, T3, T4, T5, R>

(t1: T1): CurriedFunction4<T2, T3, T4, T5, R>

(t1: T1, t2: T2): CurriedFunction3<T3, T4, T5, R>

(t1: T1, t2: T2, t3: T3): CurriedFunction2<T4, T5, R>

(t1: T1, t2: T2, t3: T3, t4: T4): CurriedFunction1<T5, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): R
}

interface CurriedFunction6<T1, T2, T3, T4, T5, T6, R> {
(): CurriedFunction6<T1, T2, T3, T4, T5, T6, R>

(t1: T1): CurriedFunction5<T2, T3, T4, T5, T6, R>

(t1: T1, t2: T2): CurriedFunction4<T3, T4, T5, T6, R>

(t1: T1, t2: T2, t3: T3): CurriedFunction3<T4, T5, T6, R>

(t1: T1, t2: T2, t3: T3, t4: T4): CurriedFunction2<T5, T6, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): CurriedFunction1<T6, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6): R
}

interface CurriedFunction7<T1, T2, T3, T4, T5, T6, T7, R> {
(): CurriedFunction7<T1, T2, T3, T4, T5, T6, T7, R>

(t1: T1): CurriedFunction6<T2, T3, T4, T5, T6, T7, R>

(t1: T1, t2: T2): CurriedFunction5<T3, T4, T5, T6, T7, R>

(t1: T1, t2: T2, t3: T3): CurriedFunction4<T4, T5, T6, T7, R>

(t1: T1, t2: T2, t3: T3, t4: T4): CurriedFunction3<T5, T6, T7, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): CurriedFunction2<T6, T7, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6): CurriedFunction1<T7, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7): R
}

interface CurriedFunction8<T1, T2, T3, T4, T5, T6, T7, T8, R> {
(): CurriedFunction8<T1, T2, T3, T4, T5, T6, T7, T8, R>

(t1: T1): CurriedFunction7<T2, T3, T4, T5, T6, T7, T8, R>

(t1: T1, t2: T2): CurriedFunction6<T3, T4, T5, T6, T7, T8, R>

(t1: T1, t2: T2, t3: T3): CurriedFunction5<T4, T5, T6, T7, T8, R>

(t1: T1, t2: T2, t3: T3, t4: T4): CurriedFunction4<T5, T6, T7, T8, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5): CurriedFunction3<T6, T7, T8, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6): CurriedFunction2<T7, T8, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7): CurriedFunction1<T8, R>

(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8): R
}

/**
* Creates a function that accepts one or more arguments of func that when called either invokes func returning
* its result, if all func arguments have been provided, or returns a function that accepts one or more of the
* remaining func arguments, and so on. The arity of func may be specified if func.length is not sufficient.
* @param func The function to curry.
* @param arity The arity of func.
* @return Returns the new curried function.
*/
export function curry<T1, R>(func: (t1: T1) => R, arity?: number): CurriedFunction1<T1, R>
export function curry<T1, T2, R>(func: (t1: T1, t2: T2) => R, arity?: number): CurriedFunction2<T1, T2, R>
export function curry<T1, T2, T3, R>(
func: (t1: T1, t2: T2, t3: T3) => R,
arity?: number,
): CurriedFunction3<T1, T2, T3, R>
export function curry<T1, T2, T3, T4, R>(
func: (t1: T1, t2: T2, t3: T3, t4: T4) => R,
arity?: number,
): CurriedFunction4<T1, T2, T3, T4, R>
export function curry<T1, T2, T3, T4, T5, R>(
func: (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => R,
arity?: number,
): CurriedFunction5<T1, T2, T3, T4, T5, R>
export function curry<T1, T2, T3, T4, T5, T6, R>(
func: (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6) => R,
arity?: number,
): CurriedFunction6<T1, T2, T3, T4, T5, T6, R>
export function curry<T1, T2, T3, T4, T5, T6, T7, R>(
func: (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7) => R,
arity?: number,
): CurriedFunction7<T1, T2, T3, T4, T5, T6, T7, R>
export function curry<T1, T2, T3, T4, T5, T6, T7, T8, R>(
func: (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7, t8: T8) => R,
arity?: number,
): CurriedFunction8<T1, T2, T3, T4, T5, T6, T7, T8, R>
export function curry(fn: (...args: any[]) => any, arity?: number) {
return function curried() {
if (arity == null) {
arity = fn.length
}
const args = [].slice.call(arguments)
if (args.length >= arity) {
// @ts-ignore
return fn.apply(this, args)
} else {
return function() {
// @ts-ignore
return curried.apply(this, args.concat([].slice.call(arguments)))
}
}
}
}
8 changes: 8 additions & 0 deletions src/helper/get-tag.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Tag } from './tag.enum'

/**
* @return Returns the value (we call it tag) returned by function call `value.toString`,
*/
export function getTag(value: any): Tag | string {
return Object.prototype.toString.call(value)
}
3 changes: 3 additions & 0 deletions src/helper/is-empty.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isEmpty(val?: object | string): boolean {
return Object.keys(val || {}).length === 0
}
11 changes: 11 additions & 0 deletions src/helper/is-empty.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { isEmpty } from './is-empty.function'

describe('isEmpty', () => {
it('should work', () => {
expect(isEmpty({})).toBeTruthy()
expect(isEmpty({ ok: true })).toBeFalsy()
expect(isEmpty('')).toBeTruthy()
expect(isEmpty('ok')).toBeFalsy()
expect(isEmpty()).toBeTruthy()
})
})
9 changes: 9 additions & 0 deletions src/helper/is-number.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { getTag } from './get-tag.function'
import { Tag } from './tag.enum'

/**
* @return Returns true for any value where typeof equals 'number' or an object created with Number constructor
*/
export function isNumber(value: any): boolean {
return typeof value === 'number' || getTag(value) === Tag.NUMBER
}
18 changes: 18 additions & 0 deletions src/helper/is-number.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { isNumber } from './is-number.function'

describe('is number', () => {
it('should be a number', () => {
expect(isNumber(3)).toBeTruthy()
expect(isNumber(NaN)).toBeTruthy()
expect(isNumber(Infinity)).toBeTruthy()
// tslint:disable:no-construct
expect(isNumber(new Number('2'))).toBeTruthy()
expect(isNumber(new Number('myNumber'))).toBeTruthy()
})

it('should not be a number', () => {
expect(isNumber('a')).toBeFalsy()
expect(isNumber({})).toBeFalsy()
expect(isNumber([])).toBeFalsy()
})
})
21 changes: 21 additions & 0 deletions src/helper/is-plain-object.function.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { isPlainObject } from './is-plain-object.function'

class Foo {
a = 1
}

describe('isPlainObject', () => {
it('should work', () => {
expect(isPlainObject({})).toBeTruthy()
expect(isPlainObject(Object.create({}))).toBeTruthy()
expect(isPlainObject(Object.create(Object.prototype))).toBeTruthy()
expect(isPlainObject({ x: 0, y: 0 })).toBeTruthy()

expect(isPlainObject([])).toBeFalsy()
expect(isPlainObject([1, 2, 3])).toBeFalsy()
expect(isPlainObject(1)).toBeFalsy()
expect(isPlainObject(null)).toBeFalsy()
expect(isPlainObject(Object.create(null))).toBeFalsy()
expect(isPlainObject(new Foo())).toBeFalsy()
})
})
20 changes: 20 additions & 0 deletions src/helper/is-plain-object.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// https://github.com/jonschlinkert/is-plain-object
import { getTag } from './get-tag.function'
import { Tag } from './tag.enum'

function isObject(val: any) {
return val != null && typeof val === 'object' && Array.isArray(val) === false
}

function isObjectObject(o: any): boolean {
return isObject(o) === true && getTag(o) === Tag.OBJECT
}

export function isPlainObject(o: any): boolean {
return !(
!isObjectObject(o) ||
typeof o.constructor !== 'function' ||
!isObjectObject(o.constructor.prototype) ||
!o.constructor.prototype.hasOwnProperty('isPrototypeOf')
)
}
9 changes: 9 additions & 0 deletions src/helper/is-string.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { getTag } from './get-tag.function'
import { Tag } from './tag.enum'

/**
* @return Returns true for any value where typeof equals 'string' or an object created with String constructor
*/
export function isString(value: any): boolean {
return typeof value === 'string' || getTag(value) === Tag.STRING
}
17 changes: 17 additions & 0 deletions src/helper/is-string.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { isString } from './is-string.function'

describe('is string', () => {
it('should be a string', () => {
expect(isString('myValue')).toBeTruthy()
// tslint:disable:no-construct
expect(isString(new String('2'))).toBeTruthy()
expect(isString(new String('someValue'))).toBeTruthy()
})

it('should not be a string', () => {
expect(isString(3)).toBeFalsy()
expect(isString(true)).toBeFalsy()
expect(isString({})).toBeFalsy()
expect(isString([])).toBeFalsy()
})
})
Loading