Skip to content

Commit 2bad97e

Browse files
committed
Add helper methods to generate condition predicates
1 parent 8515fad commit 2bad97e

File tree

2 files changed

+192
-14
lines changed

2 files changed

+192
-14
lines changed

packages/dynamodb-expressions/src/ConditionExpression.spec.ts

+99-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,102 @@
1-
import {serializeConditionExpression} from "./ConditionExpression";
1+
import {
2+
equals,
3+
notEquals,
4+
lessThan,
5+
lessThanOrEqualTo,
6+
greaterThan,
7+
greaterThanOrEqualTo,
8+
between,
9+
inList,
10+
isConditionExpressionPredicate,
11+
serializeConditionExpression,
12+
} from "./ConditionExpression";
213
import {ExpressionAttributes} from "./ExpressionAttributes";
314
import {AttributePath} from "./AttributePath";
415

16+
describe('equals', () => {
17+
it('should return an equality condition predicate', () => {
18+
const pred = equals(new AttributePath('foo'));
19+
expect(isConditionExpressionPredicate(pred)).toBe(true);
20+
expect(pred.type).toBe('Equals');
21+
});
22+
});
23+
24+
describe('notEquals', () => {
25+
it('should return an inequality condition predicate', () => {
26+
const pred = notEquals(new AttributePath('foo'));
27+
expect(isConditionExpressionPredicate(pred)).toBe(true);
28+
expect(pred.type).toBe('NotEquals');
29+
});
30+
});
31+
32+
describe('lessThan', () => {
33+
it('should return an < condition predicate', () => {
34+
const pred = lessThan(new AttributePath('foo'));
35+
expect(isConditionExpressionPredicate(pred)).toBe(true);
36+
expect(pred.type).toBe('LessThan');
37+
});
38+
});
39+
40+
describe('lessThanOrEqualTo', () => {
41+
it('should return an <= condition predicate', () => {
42+
const pred = lessThanOrEqualTo(new AttributePath('foo'));
43+
expect(isConditionExpressionPredicate(pred)).toBe(true);
44+
expect(pred.type).toBe('LessThanOrEqualTo');
45+
});
46+
});
47+
48+
describe('greaterThan', () => {
49+
it('should return an > condition predicate', () => {
50+
const pred = greaterThan(new AttributePath('foo'));
51+
expect(isConditionExpressionPredicate(pred)).toBe(true);
52+
expect(pred.type).toBe('GreaterThan');
53+
});
54+
});
55+
56+
describe('greaterThanOrEqualTo', () => {
57+
it('should return an >= condition predicate', () => {
58+
const pred = greaterThanOrEqualTo(new AttributePath('foo'));
59+
expect(isConditionExpressionPredicate(pred)).toBe(true);
60+
expect(pred.type).toBe('GreaterThanOrEqualTo');
61+
});
62+
});
63+
64+
describe('between', () => {
65+
it('should return a bounded condition predicate', () => {
66+
const pred = between(1, 10);
67+
expect(isConditionExpressionPredicate(pred)).toBe(true);
68+
expect(pred).toEqual({
69+
type: 'Between',
70+
lowerBound: 1,
71+
upperBound: 10,
72+
});
73+
});
74+
});
75+
76+
describe('inList', () => {
77+
it('should return a membership condition predicate', () => {
78+
const pred = inList('foo', 'bar', 'baz', 'quux');
79+
expect(isConditionExpressionPredicate(pred)).toBe(true);
80+
expect(pred).toEqual({
81+
type: 'Membership',
82+
values: [
83+
'foo',
84+
'bar',
85+
'baz',
86+
'quux',
87+
]
88+
});
89+
});
90+
});
91+
592
describe('serializeConditionExpression', () => {
693
it('should serialize equality expressions', () => {
794
const attributes = new ExpressionAttributes();
895
const serialized = serializeConditionExpression(
996
{
1097
type: 'Equals',
1198
subject: 'foo',
12-
comparedAgainst: 'bar',
99+
object: 'bar',
13100
},
14101
attributes
15102
);
@@ -22,7 +109,7 @@ describe('serializeConditionExpression', () => {
22109
it('should serialize inequality expressions', () => {
23110
const attributes = new ExpressionAttributes();
24111
const serialized = serializeConditionExpression(
25-
{type: 'NotEquals', subject: 'foo', comparedAgainst: 'bar'},
112+
{type: 'NotEquals', subject: 'foo', object: 'bar'},
26113
attributes
27114
);
28115

@@ -34,7 +121,7 @@ describe('serializeConditionExpression', () => {
34121
it('should serialize less than expressions', () => {
35122
const attributes = new ExpressionAttributes();
36123
const serialized = serializeConditionExpression(
37-
{type: 'LessThan', subject: 'foo', comparedAgainst: 'bar'},
124+
{type: 'LessThan', subject: 'foo', object: 'bar'},
38125
attributes
39126
);
40127

@@ -49,7 +136,7 @@ describe('serializeConditionExpression', () => {
49136
{
50137
type: 'GreaterThan',
51138
subject: 'foo',
52-
comparedAgainst: 'bar',
139+
object: 'bar',
53140
},
54141
attributes
55142
);
@@ -65,7 +152,7 @@ describe('serializeConditionExpression', () => {
65152
{
66153
type: 'LessThanOrEqualTo',
67154
subject: 'foo',
68-
comparedAgainst: 'bar',
155+
object: 'bar',
69156
},
70157
attributes
71158
);
@@ -81,7 +168,7 @@ describe('serializeConditionExpression', () => {
81168
{
82169
type: 'GreaterThanOrEqualTo',
83170
subject: 'foo',
84-
comparedAgainst: new AttributePath('bar'),
171+
object: new AttributePath('bar'),
85172
},
86173
attributes
87174
);
@@ -170,17 +257,17 @@ describe('serializeConditionExpression', () => {
170257
{
171258
type: 'GreaterThanOrEqualTo',
172259
subject: 'foo',
173-
comparedAgainst: 1,
260+
object: 1,
174261
},
175262
{
176263
type: 'LessThan',
177264
subject: 'foo',
178-
comparedAgainst: 10,
265+
object: 10,
179266
},
180267
{
181268
type: 'Equals',
182269
subject: 'fizz',
183-
comparedAgainst: 'buzz',
270+
object: 'buzz',
184271
}
185272
]
186273
},
@@ -208,12 +295,12 @@ describe('serializeConditionExpression', () => {
208295
{
209296
type: 'GreaterThanOrEqualTo',
210297
subject: 'foo',
211-
comparedAgainst: 10,
298+
object: 10,
212299
},
213300
{
214301
type: 'LessThan',
215302
subject: 'foo',
216-
comparedAgainst: 1,
303+
object: 1,
217304
}
218305
]
219306
},

packages/dynamodb-expressions/src/ConditionExpression.ts

+93-2
Original file line numberDiff line numberDiff line change
@@ -9,44 +9,118 @@ import {
99
export type ComparisonOperand = AttributePath|any;
1010

1111
export interface BinaryComparisonPredicate {
12-
comparedAgainst: ComparisonOperand;
12+
object: ComparisonOperand;
1313
}
1414

1515
export interface EqualityExpressionPredicate extends BinaryComparisonPredicate {
1616
type: 'Equals';
1717
}
1818

19+
export function equals(
20+
operand: ComparisonOperand
21+
): EqualityExpressionPredicate {
22+
return {
23+
type: 'Equals',
24+
object: operand,
25+
};
26+
}
27+
1928
export interface InequalityExpressionPredicate extends BinaryComparisonPredicate {
2029
type: 'NotEquals';
2130
}
2231

32+
export function notEquals(
33+
operand: ComparisonOperand
34+
): InequalityExpressionPredicate {
35+
return {
36+
type: 'NotEquals',
37+
object: operand,
38+
}
39+
}
40+
2341
export interface LessThanExpressionPredicate extends BinaryComparisonPredicate {
2442
type: 'LessThan';
2543
}
2644

45+
export function lessThan(
46+
operand: ComparisonOperand
47+
): LessThanExpressionPredicate {
48+
return {
49+
type: 'LessThan',
50+
object: operand,
51+
}
52+
}
53+
2754
export interface LessThanOrEqualToExpressionPredicate extends BinaryComparisonPredicate {
2855
type: 'LessThanOrEqualTo';
2956
}
3057

58+
export function lessThanOrEqualTo(
59+
operand: ComparisonOperand
60+
): LessThanOrEqualToExpressionPredicate {
61+
return {
62+
type: 'LessThanOrEqualTo',
63+
object: operand,
64+
}
65+
}
66+
3167
export interface GreaterThanExpressionPredicate extends BinaryComparisonPredicate {
3268
type: 'GreaterThan';
3369
}
3470

71+
export function greaterThan(
72+
operand: ComparisonOperand
73+
): GreaterThanExpressionPredicate {
74+
return {
75+
type: 'GreaterThan',
76+
object: operand,
77+
}
78+
}
79+
3580
export interface GreaterThanOrEqualToExpressionPredicate extends BinaryComparisonPredicate {
3681
type: 'GreaterThanOrEqualTo';
3782
}
3883

84+
export function greaterThanOrEqualTo(
85+
operand: ComparisonOperand
86+
): GreaterThanOrEqualToExpressionPredicate {
87+
return {
88+
type: 'GreaterThanOrEqualTo',
89+
object: operand,
90+
}
91+
}
92+
3993
export interface BetweenExpressionPredicate {
4094
type: 'Between';
4195
lowerBound: ComparisonOperand;
4296
upperBound: ComparisonOperand;
4397
}
4498

99+
export function between(
100+
lowerBound: ComparisonOperand,
101+
upperBound: ComparisonOperand
102+
): BetweenExpressionPredicate {
103+
return {
104+
type: 'Between',
105+
lowerBound,
106+
upperBound,
107+
}
108+
}
109+
45110
export interface MembershipExpressionPredicate {
46111
type: 'Membership';
47112
values: Array<ComparisonOperand>;
48113
}
49114

115+
export function inList(
116+
...operands: Array<ComparisonOperand>
117+
): MembershipExpressionPredicate {
118+
return {
119+
type: 'Membership',
120+
values: operands,
121+
}
122+
}
123+
50124
export type ConditionExpressionPredicate =
51125
EqualityExpressionPredicate |
52126
InequalityExpressionPredicate |
@@ -58,6 +132,23 @@ export type ConditionExpressionPredicate =
58132
BetweenExpressionPredicate |
59133
MembershipExpressionPredicate;
60134

135+
export function isConditionExpressionPredicate(
136+
arg: any
137+
): arg is ConditionExpressionPredicate {
138+
return Boolean(arg)
139+
&& typeof arg === 'object'
140+
&& [
141+
'Equals',
142+
'NotEquals',
143+
'LessThan',
144+
'LessThanOrEqualTo',
145+
'GreaterThan',
146+
'GreaterThanOrEqualTo',
147+
'Between',
148+
'Membership',
149+
].indexOf(arg.type) > -1;
150+
}
151+
61152
export interface ConditionExpressionSubject {
62153
subject: AttributePath|string;
63154
}
@@ -140,7 +231,7 @@ function serializeBinaryComparison(
140231
return `${
141232
attributes.addName(cond.subject)
142233
} ${comparator} ${
143-
serializeOperand(cond.comparedAgainst, attributes)
234+
serializeOperand(cond.object, attributes)
144235
}`;
145236
}
146237

0 commit comments

Comments
 (0)