Skip to content

Commit 9157f14

Browse files
authored
Merge pull request #40 from blazejkustra/jsdoc
Jsdoc
2 parents ab81ad1 + f37ae13 commit 9157f14

26 files changed

Lines changed: 2713 additions & 94 deletions

File tree

lib/condition/index.ts

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,87 @@ import { transformValue } from '@lib/entity/helpers/transformValues';
44
import { EntityKey, EntityValue } from '@lib/entity/types';
55
import { BASE_OPERATOR, OPERATORS, Operators, ValidationError } from '@lib/utils';
66

7+
/**
8+
* Condition builder for DynamoDB condition expressions.
9+
*
10+
* This class provides a fluent interface for building complex condition expressions
11+
* that can be used in DynamoDB operations like PutItem, UpdateItem, and DeleteItem.
12+
* It supports all DynamoDB condition operators and functions with type safety.
13+
*
14+
* @template E - The entity class type
15+
*
16+
* @example
17+
* ```typescript
18+
* // Basic conditions
19+
* const condition = new Condition(User)
20+
* .attribute('status').eq('active')
21+
* .attribute('age').gt(18);
22+
*
23+
* // Complex conditions with grouping
24+
* const condition = new Condition(User)
25+
* .attribute('status').eq('active')
26+
* .parenthesis(
27+
* new Condition(User)
28+
* .attribute('age').gt(18)
29+
* .or
30+
* .attribute('role').eq('admin')
31+
* );
32+
*
33+
* // Using with entity manager
34+
* await UserManager.update(
35+
* { id: 'user-123' },
36+
* { status: 'inactive' },
37+
* { condition }
38+
* );
39+
* ```
40+
*
41+
* @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html} for DynamoDB condition expressions
42+
* @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html} for DynamoDB operators and functions
43+
*/
744
export default class Condition<E extends typeof Entity> {
45+
/** The entity class for type-safe attribute access */
846
protected entity: E;
47+
/** The current logical operator (AND or OR) for chaining conditions */
948
protected logicalOperator: typeof BASE_OPERATOR.and | typeof BASE_OPERATOR.or = BASE_OPERATOR.and;
49+
/** Array of operators that make up the condition expression */
1050
protected operators: Operators;
1151

52+
/**
53+
* Creates a new Condition instance for the specified entity.
54+
*
55+
* @param entity - The entity class to build conditions for
56+
*
57+
* @example
58+
* ```typescript
59+
* const condition = new Condition(User);
60+
* ```
61+
*/
1262
constructor(entity: E) {
1363
this.entity = entity;
1464
this.operators = [];
1565
}
1666

67+
/**
68+
* Starts building a condition for a specific attribute.
69+
*
70+
* This method returns an object with all available comparison operators
71+
* and functions for the specified attribute, providing a fluent interface
72+
* for building conditions.
73+
*
74+
* @template C - The condition instance type
75+
* @template K - The attribute key type
76+
* @param key - The attribute name to build a condition for
77+
* @returns An object with comparison operators and functions
78+
*
79+
* @example
80+
* ```typescript
81+
* const condition = new Condition(User)
82+
* .attribute('status').eq('active')
83+
* .attribute('age').gt(18)
84+
* .attribute('email').beginsWith('admin@')
85+
* .attribute('tags').contains('premium');
86+
* ```
87+
*/
1788
public attribute<C extends this, K extends EntityKey<E>>(this: C, key: K) {
1889
this.maybePushLogicalOperator();
1990

@@ -137,6 +208,25 @@ export default class Condition<E extends typeof Entity> {
137208
};
138209
}
139210

211+
/**
212+
* Wraps a condition in parentheses for grouping.
213+
*
214+
* @param condition - Optional condition to wrap in parentheses
215+
* @returns The condition instance for chaining
216+
*
217+
* @example
218+
* ```typescript
219+
* const condition = new Condition(User)
220+
* .attribute('status').eq('active')
221+
* .and
222+
* .parenthesis(
223+
* new Condition(User)
224+
* .attribute('age').gt(18)
225+
* .or
226+
* .attribute('role').eq('admin')
227+
* );
228+
* ```
229+
*/
140230
public parenthesis(condition?: Condition<E>): this {
141231
if (condition) {
142232
this.maybePushLogicalOperator();
@@ -145,10 +235,34 @@ export default class Condition<E extends typeof Entity> {
145235
return this;
146236
}
147237

238+
/**
239+
* Alias for parenthesis() method for grouping conditions.
240+
*
241+
* @param condition - Optional condition to wrap in parentheses
242+
* @returns The condition instance for chaining
243+
*/
148244
public group(condition?: Condition<E>): this {
149245
return this.parenthesis(condition);
150246
}
151247

248+
/**
249+
* Adds another condition to this condition.
250+
*
251+
* @param condition - The condition to add
252+
* @returns The condition instance for chaining
253+
*
254+
* @example
255+
* ```typescript
256+
* const baseCondition = new Condition(User)
257+
* .attribute('status').eq('active');
258+
*
259+
* const finalCondition = baseCondition
260+
* .condition(
261+
* new Condition(User)
262+
* .attribute('age').gt(18)
263+
* );
264+
* ```
265+
*/
152266
public condition(condition?: Condition<E>): this {
153267
if (condition) {
154268
this.maybePushLogicalOperator();
@@ -157,51 +271,108 @@ export default class Condition<E extends typeof Entity> {
157271
return this;
158272
}
159273

274+
/**
275+
* Sets the logical operator to AND for the next condition.
276+
*
277+
* @returns The condition instance for chaining
278+
*
279+
* @example
280+
* ```typescript
281+
* const condition = new Condition(User)
282+
* .attribute('status').eq('active')
283+
* .attribute('age').gt(18);
284+
* ```
285+
*/
160286
public get and(): this {
161287
this.logicalOperator = BASE_OPERATOR.and;
162288
return this;
163289
}
164290

291+
/**
292+
* Sets the logical operator to OR for the next condition.
293+
*
294+
* @returns The condition instance for chaining
295+
*
296+
* @example
297+
* ```typescript
298+
* const condition = new Condition(User)
299+
* .attribute('status').eq('active')
300+
* .or
301+
* .attribute('role').eq('admin');
302+
* ```
303+
*/
165304
public get or(): this {
166305
this.logicalOperator = BASE_OPERATOR.or;
167306
return this;
168307
}
169308

309+
/**
310+
* Adds an equality comparison operator.
311+
* @protected
312+
*/
170313
protected eq<K extends EntityKey<E>>(operators: Operators, key: K, value: EntityValue<E, K>): this {
171314
operators.push(...OPERATORS.eq(key, transformValue(this.entity, key, value)));
172315
return this;
173316
}
174317

318+
/**
319+
* Adds a not equal comparison operator.
320+
* @protected
321+
*/
175322
protected ne<K extends EntityKey<E>>(operators: Operators, key: K, value: EntityValue<E, K>): this {
176323
operators.push(...OPERATORS.ne(key, transformValue(this.entity, key, value)));
177324
return this;
178325
}
179326

327+
/**
328+
* Adds a less than comparison operator.
329+
* @protected
330+
*/
180331
protected lt<K extends EntityKey<E>>(operators: Operators, key: K, value: EntityValue<E, K>): this {
181332
operators.push(...OPERATORS.lt(key, transformValue(this.entity, key, value)));
182333
return this;
183334
}
184335

336+
/**
337+
* Adds a less than or equal comparison operator.
338+
* @protected
339+
*/
185340
protected le<K extends EntityKey<E>>(operators: Operators, key: K, value: EntityValue<E, K>): this {
186341
operators.push(...OPERATORS.le(key, transformValue(this.entity, key, value)));
187342
return this;
188343
}
189344

345+
/**
346+
* Adds a greater than comparison operator.
347+
* @protected
348+
*/
190349
protected gt<K extends EntityKey<E>>(operators: Operators, key: K, value: EntityValue<E, K>): this {
191350
operators.push(...OPERATORS.gt(key, transformValue(this.entity, key, value)));
192351
return this;
193352
}
194353

354+
/**
355+
* Adds a greater than or equal comparison operator.
356+
* @protected
357+
*/
195358
protected ge<K extends EntityKey<E>>(operators: Operators, key: K, value: EntityValue<E, K>): this {
196359
operators.push(...OPERATORS.ge(key, transformValue(this.entity, key, value)));
197360
return this;
198361
}
199362

363+
/**
364+
* Adds a begins_with function operator.
365+
* @protected
366+
*/
200367
protected beginsWith<K extends EntityKey<E>>(operators: Operators, key: K, value: EntityValue<E, K>): this {
201368
operators.push(...OPERATORS.beginsWith(key, transformValue(this.entity, key, value)));
202369
return this;
203370
}
204371

372+
/**
373+
* Adds a BETWEEN operator.
374+
* @protected
375+
*/
205376
protected between<K extends EntityKey<E>>(
206377
operators: Operators,
207378
key: K,
@@ -214,6 +385,10 @@ export default class Condition<E extends typeof Entity> {
214385
return this;
215386
}
216387

388+
/**
389+
* Conditionally adds a logical operator between conditions.
390+
* @protected
391+
*/
217392
protected maybePushLogicalOperator(): void {
218393
if (this.operators.length > 0) {
219394
this.operators.push(BASE_OPERATOR.space, this.logicalOperator, BASE_OPERATOR.space);
@@ -222,4 +397,9 @@ export default class Condition<E extends typeof Entity> {
222397
}
223398
}
224399

400+
/**
401+
* DynamoDB attribute types enumeration.
402+
*
403+
* @see {@link AttributeType} for the full enumeration
404+
*/
225405
export { AttributeType };

lib/condition/types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
1+
/**
2+
* DynamoDB attribute types enumeration.
3+
*
4+
* These correspond to the attribute types used in DynamoDB operations
5+
* and condition expressions.
6+
*/
17
export enum AttributeType {
8+
/** String attribute type */
29
String = 'S',
10+
/** String set attribute type */
311
StringSet = 'SS',
12+
/** Number attribute type */
413
Number = 'N',
14+
/** Number set attribute type */
515
NumberSet = 'NS',
16+
/** Binary attribute type */
617
Binary = 'B',
18+
/** Binary set attribute type */
719
BinarySet = 'BS',
20+
/** Boolean attribute type */
821
Boolean = 'BOOL',
22+
/** Null attribute type */
923
Null = 'NULL',
24+
/** List attribute type */
1025
List = 'L',
26+
/** Map attribute type */
1127
Map = 'M',
1228
}

0 commit comments

Comments
 (0)