dyno-table 0.0.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/README.md +785 -0
  2. package/dist/index.d.ts +2869 -274
  3. package/dist/index.js +3145 -939
  4. package/package.json +21 -26
  5. package/readme.md +0 -132
package/dist/index.d.ts CHANGED
@@ -1,323 +1,2918 @@
1
- import * as _aws_sdk_lib_dynamodb from '@aws-sdk/lib-dynamodb';
2
- import { DynamoDBDocument } from '@aws-sdk/lib-dynamodb';
3
- import { z } from 'zod';
1
+ import { DynamoDBDocument, TransactWriteCommandInput } from '@aws-sdk/lib-dynamodb';
4
2
 
5
- interface ExpressionAttributes {
6
- names?: Record<string, string>;
7
- values?: Record<string, unknown>;
3
+ interface Index {
4
+ partitionKey: string;
5
+ sortKey?: string;
8
6
  }
9
- interface ExpressionResult {
10
- expression?: string;
11
- attributes: ExpressionAttributes;
7
+ interface IndexConfig$1 {
8
+ partitionKey: string;
9
+ sortKey?: string;
10
+ gsis?: Record<string, Index>;
12
11
  }
13
- type FunctionOperator = "attribute_exists" | "attribute_not_exists" | "begins_with" | "contains" | "not_contains" | "attribute_type";
14
- type ComparisonOperator = "=" | "<" | "<=" | ">" | ">=" | "<>";
15
- type SpecialOperator = "BETWEEN" | "IN" | "size";
16
- type ConditionOperator = FunctionOperator | ComparisonOperator | SpecialOperator;
17
- type FilterOperator = "=" | "<" | "<=" | ">" | ">=" | "<>" | "BETWEEN" | "IN" | "contains" | "begins_with";
18
- interface FilterCondition {
19
- field: string;
20
- operator: FilterOperator;
21
- value: unknown;
12
+ interface TableConfig {
13
+ client: DynamoDBDocument;
14
+ tableName: string;
15
+ indexes: IndexConfig$1;
22
16
  }
17
+ type GSINames<T extends TableConfig> = keyof NonNullable<T["indexes"]["gsis"]>;
18
+ interface EntityConfig<T> {
19
+ name: string;
20
+ partitionKeyPrefix?: string;
21
+ sortKeyPrefix?: string;
22
+ timestamps?: boolean;
23
+ discriminator?: string;
24
+ }
25
+
26
+ type Primitive = null | undefined | string | number | boolean | symbol | bigint;
27
+ type IsEqual<T1, T2> = T1 extends T2 ? (<G>() => G extends T1 ? 1 : 2) extends <G>() => G extends T2 ? 1 : 2 ? true : false : false;
28
+ interface File extends Blob {
29
+ readonly lastModified: number;
30
+ readonly name: string;
31
+ }
32
+ interface FileList {
33
+ readonly length: number;
34
+ item(index: number): File | null;
35
+ [index: number]: File;
36
+ }
37
+ type BrowserNativeObject = Date | FileList | File;
38
+ type IsTuple<T extends ReadonlyArray<any>> = number extends T["length"] ? false : true;
39
+ type TupleKeys<T extends ReadonlyArray<any>> = Exclude<keyof T, keyof any[]>;
40
+ type AnyIsEqual<T1, T2> = T1 extends T2 ? (IsEqual<T1, T2> extends true ? true : never) : never;
41
+ type PathImpl<K extends string | number, V, TraversedTypes> = V extends Primitive | BrowserNativeObject ? `${K}` : true extends AnyIsEqual<TraversedTypes, V> ? `${K}` : `${K}` | `${K}.${PathInternal<V, TraversedTypes | V>}`;
42
+ type ArrayKey = number;
43
+ type PathInternal<T, TraversedTypes = T> = T extends ReadonlyArray<infer V> ? IsTuple<T> extends true ? {
44
+ [K in TupleKeys<T>]-?: PathImpl<K & string, T[K], TraversedTypes>;
45
+ }[TupleKeys<T>] : PathImpl<ArrayKey, V, TraversedTypes> : {
46
+ [K in keyof T]-?: PathImpl<K & string, T[K], TraversedTypes>;
47
+ }[keyof T];
48
+ type Path<T> = T extends any ? PathInternal<T> : never;
49
+ type PathType<T, K extends keyof any> = K extends `${infer Key}.${infer Rest}` ? Key extends keyof T ? Rest extends keyof any ? PathType<T[Key], Rest> : never : never : K extends keyof T ? T[K] : never;
50
+
51
+ /**
52
+ * Supported comparison operators for DynamoDB conditions.
53
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html AWS DynamoDB - Comparison Operator Reference}
54
+ *
55
+ * - eq: Equals (=)
56
+ * - ne: Not equals (≠ / <>)
57
+ * - lt: Less than (<)
58
+ * - lte: Less than or equal to (≤)
59
+ * - gt: Greater than (>)
60
+ * - gte: Greater than or equal to (≥)
61
+ * - between: Between two values (inclusive)
62
+ * - beginsWith: Checks if string attribute begins with specified substring
63
+ * - contains: Checks if string/set attribute contains specified value
64
+ * - attributeExists: Checks if attribute exists
65
+ * - attributeNotExists: Checks if attribute does not exist
66
+ */
67
+ type ComparisonOperator = "eq" | "ne" | "lt" | "lte" | "gt" | "gte" | "between" | "beginsWith" | "contains" | "attributeExists" | "attributeNotExists";
68
+ /**
69
+ * Logical operators for combining multiple conditions.
70
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Logical AWS DynamoDB - Logical Operator Reference}
71
+ *
72
+ * - and: Evaluates to true if all conditions are true
73
+ * - or: Evaluates to true if any condition is true
74
+ * - not: Negate the result of a condition
75
+ */
76
+ type LogicalOperator = "and" | "or" | "not";
77
+ /**
78
+ * Represents a DynamoDB condition expression.
79
+ * Can be either a comparison condition or a logical combination of conditions.
80
+ *
81
+ * @example
82
+ * // Simple comparison condition
83
+ * const condition: Condition = {
84
+ * type: "eq",
85
+ * attr: "status",
86
+ * value: "ACTIVE"
87
+ * };
88
+ *
89
+ * @example
90
+ * // Logical combination of conditions
91
+ * const condition: Condition = {
92
+ * type: "and",
93
+ * conditions: [
94
+ * { type: "eq", attr: "status", value: "ACTIVE" },
95
+ * { type: "gt", attr: "age", value: 5 }
96
+ * ]
97
+ * };
98
+ */
23
99
  interface Condition {
24
- field: string;
25
- operator: ConditionOperator;
100
+ /** The type of condition (comparison or logical operator) */
101
+ type: ComparisonOperator | LogicalOperator;
102
+ /** The attribute name for comparison conditions */
103
+ attr?: string;
104
+ /** The value to compare against for comparison conditions */
26
105
  value?: unknown;
106
+ /** Array of conditions for logical operators (and/or) */
107
+ conditions?: Condition[];
108
+ /** Single condition for the 'not' operator */
109
+ condition?: Condition;
27
110
  }
28
- type SKCondition = {
29
- operator: FilterOperator;
30
- value: string;
111
+ /**
112
+ * Creates an equals (=) condition
113
+ * @example
114
+ * eq("status", "ACTIVE") // status = "ACTIVE"
115
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}
116
+ */
117
+ declare const eq: (attr: string, value: unknown) => Condition;
118
+ /**
119
+ * Creates a not equals (≠) condition
120
+ * @example
121
+ * ne("status", "DELETED") // status <> "DELETED"
122
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}
123
+ */
124
+ declare const ne: (attr: string, value: unknown) => Condition;
125
+ /**
126
+ * Creates a less than (<) condition
127
+ * @example
128
+ * lt("age", 18) // age < 18
129
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}
130
+ */
131
+ declare const lt: (attr: string, value: unknown) => Condition;
132
+ /**
133
+ * Creates a less than or equal to (≤) condition
134
+ * @example
135
+ * lte("age", 18) // age <= 18
136
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}
137
+ */
138
+ declare const lte: (attr: string, value: unknown) => Condition;
139
+ /**
140
+ * Creates a greater than (>) condition
141
+ * @example
142
+ * gt("price", 100) // price > 100
143
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}
144
+ */
145
+ declare const gt: (attr: string, value: unknown) => Condition;
146
+ /**
147
+ * Creates a greater than or equal to (≥) condition
148
+ * @example
149
+ * gte("price", 100) // price >= 100
150
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html}
151
+ */
152
+ declare const gte: (attr: string, value: unknown) => Condition;
153
+ /**
154
+ * Creates a between condition that checks if a value is within a range (inclusive)
155
+ * @example
156
+ * between("age", 18, 65) // age BETWEEN 18 AND 65
157
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Comparators AWS DynamoDB - BETWEEN}
158
+ */
159
+ declare const between: (attr: string, lower: unknown, upper: unknown) => Condition;
160
+ /**
161
+ * Creates a begins_with condition that checks if a string attribute starts with a substring
162
+ * @example
163
+ * beginsWith("email", "@example.com") // begins_with(email, "@example.com")
164
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions AWS DynamoDB - begins_with}
165
+ */
166
+ declare const beginsWith: (attr: string, value: unknown) => Condition;
167
+ /**
168
+ * Creates a contains condition that checks if a string contains a substring or if a set contains an element
169
+ * @example
170
+ * contains("tags", "important") // contains(tags, "important")
171
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions AWS DynamoDB - contains}
172
+ */
173
+ declare const contains: (attr: string, value: unknown) => Condition;
174
+ /**
175
+ * Creates a condition that checks if an attribute exists
176
+ * @example
177
+ * attributeExists("email") // attribute_exists(email)
178
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions AWS DynamoDB - attribute_exists}
179
+ */
180
+ declare const attributeExists: (attr: string) => Condition;
181
+ /**
182
+ * Creates a condition that checks if an attribute does not exist
183
+ * @example
184
+ * attributeNotExists("deletedAt") // attribute_not_exists(deletedAt)
185
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions AWS DynamoDB - attribute_not_exists}
186
+ */
187
+ declare const attributeNotExists: (attr: string) => Condition;
188
+ /**
189
+ * Combines multiple conditions with AND operator
190
+ * @example
191
+ * and(
192
+ * eq("status", "ACTIVE"),
193
+ * gt("age", 18)
194
+ * ) // status = "ACTIVE" AND age > 18
195
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Logical AWS DynamoDB - AND}
196
+ */
197
+ declare const and: (...conditions: Condition[]) => Condition;
198
+ /**
199
+ * Combines multiple conditions with OR operator
200
+ * @example
201
+ * or(
202
+ * eq("status", "PENDING"),
203
+ * eq("status", "PROCESSING")
204
+ * ) // status = "PENDING" OR status = "PROCESSING"
205
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Logical AWS DynamoDB - OR}
206
+ */
207
+ declare const or: (...conditions: Condition[]) => Condition;
208
+ /**
209
+ * Negates a condition
210
+ * @example
211
+ * not(eq("status", "DELETED")) // NOT status = "DELETED"
212
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Logical AWS DynamoDB - NOT}
213
+ */
214
+ declare const not: (condition: Condition) => Condition;
215
+ /**
216
+ * Type-safe operators for building key conditions in DynamoDB queries.
217
+ * Only includes operators that are valid for key conditions.
218
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html#Query.KeyConditionExpressions AWS DynamoDB - Key Condition Expressions}
219
+ *
220
+ * @example
221
+ * // Using with sort key conditions
222
+ * table.query({
223
+ * pk: "USER#123",
224
+ * sk: op => op.beginsWith("ORDER#")
225
+ * })
226
+ */
227
+ type KeyConditionOperator = {
228
+ /** Equals comparison for key attributes */
229
+ eq: (value: unknown) => Condition;
230
+ /** Less than comparison for key attributes */
231
+ lt: (value: unknown) => Condition;
232
+ /** Less than or equal comparison for key attributes */
233
+ lte: (value: unknown) => Condition;
234
+ /** Greater than comparison for key attributes */
235
+ gt: (value: unknown) => Condition;
236
+ /** Greater than or equal comparison for key attributes */
237
+ gte: (value: unknown) => Condition;
238
+ /** Between range comparison for key attributes */
239
+ between: (lower: unknown, upper: unknown) => Condition;
240
+ /** Begins with comparison for key attributes */
241
+ beginsWith: (value: unknown) => Condition;
242
+ /** Combines multiple key conditions with AND */
243
+ and: (...conditions: Condition[]) => Condition;
244
+ };
245
+ /**
246
+ * Type-safe operators for building conditions in DynamoDB operations.
247
+ * Includes all available condition operators with proper type inference.
248
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html AWS DynamoDB - Condition Expressions}
249
+ *
250
+ * @example
251
+ * // Using with type-safe conditions
252
+ * interface User {
253
+ * status: string;
254
+ * age: number;
255
+ * email?: string;
256
+ * }
257
+ *
258
+ * table.scan<User>()
259
+ * .where(op => op.and(
260
+ * op.eq("status", "ACTIVE"),
261
+ * op.gt("age", 18),
262
+ * op.attributeExists("email")
263
+ * ))
264
+ *
265
+ * @template T The type of the item being operated on
266
+ */
267
+ type ConditionOperator<T extends Record<string, unknown>> = {
268
+ eq: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;
269
+ ne: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;
270
+ lt: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;
271
+ lte: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;
272
+ gt: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;
273
+ gte: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;
274
+ between: <K extends Path<T>>(attr: K, lower: PathType<T, K>, upper: PathType<T, K>) => Condition;
275
+ beginsWith: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;
276
+ contains: <K extends Path<T>>(attr: K, value: PathType<T, K>) => Condition;
277
+ attributeExists: <K extends Path<T>>(attr: K) => Condition;
278
+ attributeNotExists: <K extends Path<T>>(attr: K) => Condition;
279
+ and: (...conditions: Condition[]) => Condition;
280
+ or: (...conditions: Condition[]) => Condition;
281
+ not: (condition: Condition) => Condition;
31
282
  };
283
+ /**
284
+ * Primary key type for QUERY operations.
285
+ * Allows building complex key conditions for the sort key.
286
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html AWS DynamoDB - Query Operations}
287
+ *
288
+ * @example
289
+ * // Query items with a specific partition key and sort key prefix
290
+ * table.query({
291
+ * pk: "USER#123",
292
+ * sk: op => op.beginsWith("ORDER#2023")
293
+ * })
294
+ *
295
+ * @example
296
+ * // Query items within a specific sort key range
297
+ * table.query({
298
+ * pk: "USER#123",
299
+ * sk: op => op.between("ORDER#2023-01", "ORDER#2023-12")
300
+ * })
301
+ */
32
302
  type PrimaryKey = {
303
+ /** Partition key value */
33
304
  pk: string;
34
- sk?: SKCondition | string;
305
+ /** Optional sort key condition builder */
306
+ sk?: (op: KeyConditionOperator) => Condition;
307
+ };
308
+ /**
309
+ * Primary key type for GET and DELETE operations.
310
+ * Used when you need to specify exact key values without conditions.
311
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html AWS DynamoDB - Working with Items}
312
+ *
313
+ * @example
314
+ * // Get a specific item by its complete primary key
315
+ * table.get({
316
+ * pk: "USER#123",
317
+ * sk: "PROFILE#123"
318
+ * })
319
+ *
320
+ * @example
321
+ * // Delete a specific item by its complete primary key
322
+ * table.delete({
323
+ * pk: "USER#123",
324
+ * sk: "ORDER#456"
325
+ * })
326
+ */
327
+ type PrimaryKeyWithoutExpression = {
328
+ /** Partition key value */
329
+ pk: string;
330
+ /** Optional sort key value */
331
+ sk?: string;
35
332
  };
36
- interface TableIndexConfig {
37
- pkName: string;
38
- skName?: string;
39
- }
40
333
 
41
- interface IExpressionBuilder {
42
- buildKeyCondition(key: PrimaryKey, indexConfig: TableIndexConfig): ExpressionResult;
43
- createExpression(filters: Condition[]): ExpressionResult;
44
- buildUpdateExpression(updates: Record<string, unknown>): ExpressionResult;
334
+ /**
335
+ * Represents the result of a single page query operation.
336
+ * This interface provides all necessary information about the current page
337
+ * and the availability of subsequent pages.
338
+ */
339
+ interface PaginationResult<T> {
340
+ /** The items (dinosaurs, habitats, etc.) retrieved for the current page */
341
+ items: T[];
342
+ /** DynamoDB's last evaluated key, used internally for pagination */
343
+ lastEvaluatedKey?: Record<string, unknown>;
344
+ /** Indicates whether there are more pages available */
345
+ hasNextPage: boolean;
346
+ /** The current page number (1-indexed) */
347
+ page: number;
45
348
  }
46
- declare class ExpressionBuilder implements IExpressionBuilder {
47
- private nameCount;
48
- private valueCount;
49
- private generateAlias;
50
- private reset;
51
- private createAttributePath;
52
- private addValue;
53
- private buildComparison;
54
- createExpression(conditions: Array<{
55
- field: string;
56
- operator: ConditionOperator;
57
- value?: unknown;
58
- }>): ExpressionResult;
59
- private formatAttributes;
60
- buildKeyCondition(key: PrimaryKey, indexConfig: TableIndexConfig): ExpressionResult;
61
- buildUpdateExpression(updates: Record<string, unknown>): ExpressionResult;
349
+ /**
350
+ * A utility class for handling DynamoDB pagination.
351
+ * Use this class when you need to:
352
+ * - Browse large collections of dinosaurs
353
+ * - Review extensive security logs
354
+ * - Analyze habitat inspection history
355
+ * - Process feeding schedules
356
+ *
357
+ * The paginator maintains internal state and automatically handles:
358
+ * - Page boundaries
359
+ * - Result set limits
360
+ * - Continuation tokens
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * // List all velociraptors with pagination
365
+ * const paginator = new QueryBuilder(executor, eq('species', 'Velociraptor'))
366
+ * .filter(op => op.eq('status', 'ACTIVE'))
367
+ * .paginate(10);
368
+ *
369
+ * // Process each page of dinosaurs
370
+ * while (paginator.hasNextPage()) {
371
+ * const page = await paginator.getNextPage();
372
+ * console.log(`Processing page ${page.page} of velociraptors`);
373
+ *
374
+ * for (const raptor of page.items) {
375
+ * console.log(`- ${raptor.id}: Health=${raptor.stats.health}`);
376
+ * }
377
+ * }
378
+ * ```
379
+ *
380
+ * @typeParam T - The type of items being paginated
381
+ * @typeParam TConfig - The table configuration type
382
+ */
383
+ declare class Paginator<T extends Record<string, unknown>, TConfig extends TableConfig = TableConfig> {
384
+ private queryBuilder;
385
+ private readonly pageSize;
386
+ private currentPage;
387
+ private lastEvaluatedKey?;
388
+ private hasMorePages;
389
+ private totalItemsRetrieved;
390
+ private readonly overallLimit?;
391
+ constructor(queryBuilder: QueryBuilder<T, TConfig>, pageSize: number);
392
+ /**
393
+ * Gets the current page number (1-indexed).
394
+ * Use this method when you need to:
395
+ * - Track progress through dinosaur lists
396
+ * - Display habitat inspection status
397
+ * - Monitor security sweep progress
398
+ *
399
+ * @example
400
+ * ```ts
401
+ * const paginator = new QueryBuilder(executor, eq('species', 'Tyrannosaurus'))
402
+ * .paginate(5);
403
+ *
404
+ * await paginator.getNextPage();
405
+ * console.log(`Reviewing T-Rex group ${paginator.getCurrentPage()}`);
406
+ * ```
407
+ *
408
+ * @returns The current page number, starting from 1
409
+ */
410
+ getCurrentPage(): number;
411
+ /**
412
+ * Checks if there are more pages of dinosaurs or habitats to process.
413
+ * Use this method when you need to:
414
+ * - Check for more dinosaurs to review
415
+ * - Continue habitat inspections
416
+ * - Process security incidents
417
+ * - Complete feeding schedules
418
+ *
419
+ * This method takes into account both:
420
+ * - DynamoDB's lastEvaluatedKey mechanism
421
+ * - Any overall limit set on the query
422
+ *
423
+ * @example
424
+ * ```ts
425
+ * // Process all security incidents
426
+ * const paginator = new QueryBuilder(executor, eq('type', 'SECURITY_BREACH'))
427
+ * .sortDescending()
428
+ * .paginate(10);
429
+ *
430
+ * while (paginator.hasNextPage()) {
431
+ * const page = await paginator.getNextPage();
432
+ * for (const incident of page.items) {
433
+ * await processSecurityBreach(incident);
434
+ * }
435
+ * console.log(`Processed incidents page ${page.page}`);
436
+ * }
437
+ * ```
438
+ *
439
+ * @returns true if there are more pages available, false otherwise
440
+ */
441
+ hasNextPage(): boolean;
442
+ /**
443
+ * Retrieves the next page of dinosaurs or habitats from DynamoDB.
444
+ * Use this method when you need to:
445
+ * - Process dinosaur groups systematically
446
+ * - Review habitat inspections in batches
447
+ * - Monitor security incidents in sequence
448
+ * - Schedule feeding rotations
449
+ *
450
+ * This method handles:
451
+ * - Automatic continuation between groups
452
+ * - Respect for park capacity limits
453
+ * - Group size adjustments for safety
454
+ *
455
+ * @example
456
+ * ```ts
457
+ * const paginator = new QueryBuilder(executor, eq('species', 'Velociraptor'))
458
+ * .filter(op => op.eq('status', 'ACTIVE'))
459
+ * .paginate(5);
460
+ *
461
+ * // Check first raptor group
462
+ * const page1 = await paginator.getNextPage();
463
+ * console.log(`Found ${page1.items.length} active raptors`);
464
+ *
465
+ * // Continue inspection if more groups exist
466
+ * if (page1.hasNextPage) {
467
+ * const page2 = await paginator.getNextPage();
468
+ * console.log(`Inspecting raptor group ${page2.page}`);
469
+ *
470
+ * for (const raptor of page2.items) {
471
+ * await performHealthCheck(raptor);
472
+ * }
473
+ * }
474
+ * ```
475
+ *
476
+ * @returns A promise that resolves to a PaginationResult containing:
477
+ * - items: The dinosaurs/habitats for this page
478
+ * - hasNextPage: Whether more groups exist
479
+ * - page: The current group number
480
+ * - lastEvaluatedKey: DynamoDB's continuation token
481
+ */
482
+ getNextPage(): Promise<PaginationResult<T>>;
483
+ /**
484
+ * Gets all remaining dinosaurs or habitats and combines them into a single array.
485
+ * Use this method when you need to:
486
+ * - Generate complete park inventory
487
+ * - Perform full security audit
488
+ * - Create comprehensive feeding schedule
489
+ * - Run park-wide health checks
490
+ *
491
+ * Note: Use with caution! This method:
492
+ * - Could overwhelm systems with large dinosaur populations
493
+ * - Makes multiple database requests
494
+ * - May cause system strain during peak hours
495
+ *
496
+ * @example
497
+ * ```ts
498
+ * // Get complete carnivore inventory
499
+ * const paginator = new QueryBuilder(executor, eq('diet', 'CARNIVORE'))
500
+ * .filter(op => op.eq('status', 'ACTIVE'))
501
+ * .paginate(10);
502
+ *
503
+ * try {
504
+ * const allCarnivores = await paginator.getAllPages();
505
+ * console.log(`Park contains ${allCarnivores.length} active carnivores`);
506
+ *
507
+ * // Calculate total threat level
508
+ * const totalThreat = allCarnivores.reduce(
509
+ * (sum, dino) => sum + dino.stats.threatLevel,
510
+ * 0
511
+ * );
512
+ * console.log(`Total threat level: ${totalThreat}`);
513
+ * } catch (error) {
514
+ * console.error('Failed to complete carnivore census:', error);
515
+ * }
516
+ * ```
517
+ *
518
+ * @returns A promise that resolves to an array containing all remaining items
519
+ */
520
+ getAllPages(): Promise<T[]>;
62
521
  }
63
522
 
64
- type DynamoKey = Record<string, unknown>;
65
- interface DynamoExpression {
66
- expression?: string;
67
- names?: Record<string, string>;
68
- values?: Record<string, unknown>;
69
- }
70
- interface DynamoBatchWriteItem {
71
- put?: Record<string, unknown>;
72
- delete?: DynamoKey;
73
- }
74
- interface DynamoPutOperation {
75
- type: "put";
76
- item: Record<string, unknown>;
77
- condition?: DynamoExpression;
78
- }
79
- interface DynamoUpdateOperation {
80
- type: "update";
81
- key: PrimaryKeyWithoutExpression;
82
- update: DynamoExpression;
83
- condition?: DynamoExpression;
84
- }
85
- interface DynamoQueryOperation {
86
- type: "query";
87
- keyCondition?: DynamoExpression;
88
- filter?: DynamoExpression;
523
+ /**
524
+ * Configuration options for DynamoDB query operations.
525
+ */
526
+ interface QueryOptions {
527
+ /** Condition for the sort key in the table or index */
528
+ sortKeyCondition?: Condition;
529
+ /** Additional filter conditions applied after the key condition */
530
+ filter?: Condition;
531
+ /** Maximum number of items to return */
89
532
  limit?: number;
533
+ /** Name of the Global Secondary Index to query */
90
534
  indexName?: string;
535
+ /** Whether to use strongly consistent reads */
536
+ consistentRead?: boolean;
537
+ /** Direction of sort key traversal (true for ascending, false for descending) */
538
+ scanIndexForward?: boolean;
539
+ /** List of attributes to return in the result */
540
+ projection?: string[];
541
+ /** Number of items to fetch per page when using pagination */
542
+ paginationSize?: number;
543
+ /** Token for starting the query from a specific point */
544
+ lastEvaluatedKey?: Record<string, unknown>;
91
545
  }
92
- interface DynamoDeleteOperation {
93
- type: "delete";
94
- key: PrimaryKeyWithoutExpression;
95
- condition?: DynamoExpression;
96
- }
97
- interface DynamoBatchWriteOperation {
98
- type: "batchWrite";
99
- operations: DynamoBatchWriteItem[];
100
- }
101
- interface DynamoTransactOperation {
102
- type: "transactWrite";
103
- operations: Array<{
104
- put?: {
105
- item: Record<string, unknown>;
106
- condition?: DynamoExpression;
107
- };
108
- delete?: {
109
- key: PrimaryKeyWithoutExpression;
110
- condition?: DynamoExpression;
111
- };
112
- update?: {
113
- key: PrimaryKeyWithoutExpression;
114
- update: DynamoExpression;
115
- condition?: DynamoExpression;
116
- };
546
+ /**
547
+ * Function type for executing DynamoDB query operations.
548
+ * @typeParam T - The type of items being queried
549
+ */
550
+ type QueryExecutor<T extends Record<string, unknown>> = (keyCondition: Condition, options: QueryOptions) => Promise<{
551
+ items: T[];
552
+ lastEvaluatedKey?: Record<string, unknown>;
553
+ }>;
554
+ /**
555
+ * Builder for creating DynamoDB query operations.
556
+ * Use this builder when you need to:
557
+ * - Query items using partition key (and optionally sort key)
558
+ * - Filter results based on non-key attributes
559
+ * - Use Global Secondary Indexes (GSIs)
560
+ * - Implement pagination
561
+ * - Control result ordering
562
+ * - Project specific attributes
563
+ *
564
+ * The builder supports:
565
+ * - Type-safe GSI selection
566
+ * - Complex filter conditions
567
+ * - Automatic pagination handling
568
+ * - Consistent reads
569
+ * - Forward and reverse sorting
570
+ *
571
+ * @example
572
+ * ```ts
573
+ * // Simple query
574
+ * const result = await new QueryBuilder(executor, eq('userId', '123'))
575
+ * .execute();
576
+ *
577
+ * // Complex query with GSI and filtering
578
+ * const result = await new QueryBuilder(executor, eq('status', 'ACTIVE'))
579
+ * .useIndex('status-index')
580
+ * .filter(op => op.beginsWith('name', 'John'))
581
+ * .select(['id', 'name', 'email'])
582
+ * .sortDescending()
583
+ * .limit(10)
584
+ * .execute();
585
+ *
586
+ * // Query with pagination
587
+ * const paginator = new QueryBuilder(executor, eq('type', 'order'))
588
+ * .paginate(25);
589
+ *
590
+ * while (paginator.hasNextPage()) {
591
+ * const page = await paginator.getNextPage();
592
+ * // Process page.items
593
+ * }
594
+ * ```
595
+ *
596
+ * @typeParam T - The type of items being queried
597
+ * @typeParam TConfig - The table configuration type for type-safe GSI selection
598
+ */
599
+ /**
600
+ * Builder for creating DynamoDB query operations.
601
+ * Use this builder when you need to:
602
+ * - Find dinosaurs by species or status
603
+ * - Search habitats by type or region
604
+ * - List incidents by date range
605
+ * - Retrieve feeding schedules
606
+ *
607
+ * The builder supports:
608
+ * - Complex filtering conditions
609
+ * - Sorting and pagination
610
+ * - Global Secondary Indexes
611
+ * - Attribute projection
612
+ *
613
+ * @example
614
+ * ```typescript
615
+ * // Find active carnivores
616
+ * const result = await new QueryBuilder(executor, eq('species', 'Tyrannosaurus'))
617
+ * .filter(op => op.eq('status', 'ACTIVE'))
618
+ * .execute();
619
+ *
620
+ * // Search habitats by security level
621
+ * const result = await new QueryBuilder(executor, eq('type', 'CARNIVORE'))
622
+ * .useIndex('security-level-index')
623
+ * .filter(op => op.gt('securityLevel', 8))
624
+ * .select(['id', 'capacity', 'currentOccupants'])
625
+ * .sortDescending()
626
+ * .execute();
627
+ *
628
+ * // List recent incidents
629
+ * const result = await new QueryBuilder(executor, eq('type', 'INCIDENT'))
630
+ * .useIndex('date-index')
631
+ * .filter(op => op.gt('severityLevel', 5))
632
+ * .paginate(10);
633
+ * ```
634
+ *
635
+ * @typeParam T - The type of items being queried
636
+ * @typeParam TConfig - The table configuration type for type-safe GSI selection
637
+ */
638
+ declare class QueryBuilder<T extends Record<string, unknown>, TConfig extends TableConfig = TableConfig> {
639
+ private readonly keyCondition;
640
+ private options;
641
+ private selectedFields;
642
+ private readonly executor;
643
+ constructor(executor: QueryExecutor<T>, keyCondition: Condition);
644
+ /**
645
+ * Sets the maximum number of items to return from the query.
646
+ * Use this method when you need to:
647
+ * - Limit the result set size
648
+ * - Implement manual pagination
649
+ * - Control data transfer size
650
+ *
651
+ * Note: This limit applies to the items that match the key condition
652
+ * before any filter expressions are applied.
653
+ *
654
+ * @example
655
+ * ```ts
656
+ * // Get first 10 orders for a user
657
+ * const result = await new QueryBuilder(executor, eq('userId', '123'))
658
+ * .limit(10)
659
+ * .execute();
660
+ * ```
661
+ *
662
+ * @param limit - Maximum number of items to return
663
+ * @returns The builder instance for method chaining
664
+ */
665
+ limit(limit: number): QueryBuilder<T>;
666
+ /**
667
+ * Gets the current limit set on the query.
668
+ * This is used internally by the paginator to manage result sets.
669
+ *
670
+ * @returns The current limit or undefined if no limit is set
671
+ */
672
+ getLimit(): number | undefined;
673
+ /**
674
+ * Specifies a Global Secondary Index (GSI) to use for the query.
675
+ * Use this method when you need to:
676
+ * - Query data using non-primary key attributes
677
+ * - Access data through alternate access patterns
678
+ * - Optimize query performance for specific access patterns
679
+ *
680
+ * This method provides type safety by only allowing valid GSI names
681
+ * defined in your table configuration.
682
+ *
683
+ * @example
684
+ * ```ts
685
+ * // Query by status using a GSI
686
+ * const result = await new QueryBuilder(executor, eq('status', 'ACTIVE'))
687
+ * .useIndex('status-index')
688
+ * .execute();
689
+ *
690
+ * // Query by category and date range
691
+ * const result = await new QueryBuilder(executor, eq('category', 'books'))
692
+ * .useIndex('category-date-index')
693
+ * .filter(op => op.between('date', startDate, endDate))
694
+ * .execute();
695
+ * ```
696
+ *
697
+ * Note: Be aware that GSIs:
698
+ * - May have different projected attributes
699
+ * - Have eventually consistent reads only
700
+ * - May have different provisioned throughput
701
+ *
702
+ * @param indexName - The name of the GSI to use (type-safe based on table configuration)
703
+ * @returns The builder instance for method chaining
704
+ */
705
+ /**
706
+ * Specifies a Global Secondary Index (GSI) to use for the query.
707
+ * Use this method when you need to:
708
+ * - Query dinosaurs by species or status
709
+ * - Search habitats by security level
710
+ * - Find incidents by date
711
+ * - List feeding schedules by time
712
+ *
713
+ * @example
714
+ * ```typescript
715
+ * // Find all dinosaurs of a specific species
716
+ * builder
717
+ * .useIndex('species-status-index')
718
+ * .filter(op => op.eq('status', 'ACTIVE'));
719
+ *
720
+ * // Search high-security habitats
721
+ * builder
722
+ * .useIndex('security-level-index')
723
+ * .filter(op =>
724
+ * op.and([
725
+ * op.gt('securityLevel', 8),
726
+ * op.eq('status', 'OPERATIONAL')
727
+ * ])
728
+ * );
729
+ * ```
730
+ *
731
+ * @param indexName - The name of the GSI to use (type-safe based on table configuration)
732
+ * @returns The builder instance for method chaining
733
+ */
734
+ useIndex<I extends GSINames<TConfig>>(indexName: I): QueryBuilder<T, TConfig>;
735
+ /**
736
+ * Sets whether to use strongly consistent reads for the query.
737
+ * Use this method when you need to:
738
+ * - Get real-time dinosaur status updates
739
+ * - Monitor critical security systems
740
+ * - Track immediate habitat changes
741
+ * - Verify containment protocols
742
+ *
743
+ * Note:
744
+ * - Consistent reads are not available on GSIs
745
+ * - Consistent reads consume twice the throughput
746
+ * - Default is eventually consistent reads
747
+ *
748
+ * @example
749
+ * ```ts
750
+ * // Check immediate dinosaur status
751
+ * const result = await new QueryBuilder(executor, eq('species', 'Velociraptor'))
752
+ * .filter(op => op.eq('status', 'ACTIVE'))
753
+ * .consistentRead()
754
+ * .execute();
755
+ *
756
+ * // Monitor security breaches
757
+ * const result = await new QueryBuilder(executor, eq('type', 'SECURITY_ALERT'))
758
+ * .useIndex('primary-index')
759
+ * .consistentRead(isEmergencyMode)
760
+ * .execute();
761
+ * ```
762
+ *
763
+ * @param consistentRead - Whether to use consistent reads (defaults to true)
764
+ * @returns The builder instance for method chaining
765
+ */
766
+ consistentRead(consistentRead?: boolean): QueryBuilder<T>;
767
+ /**
768
+ * Adds a filter expression to the query.
769
+ * Use this method when you need to:
770
+ * - Filter results based on non-key attributes
771
+ * - Apply complex filtering conditions
772
+ * - Combine multiple filter conditions
773
+ *
774
+ * Note: Filter expressions are applied after the key condition,
775
+ * so they don't reduce the amount of data read from DynamoDB.
776
+ *
777
+ * @example
778
+ * ```ts
779
+ * // Simple filter
780
+ * builder.filter(op => op.eq('status', 'ACTIVE'))
781
+ *
782
+ * // Complex filter with multiple conditions
783
+ * builder.filter(op =>
784
+ * op.and([
785
+ * op.gt('amount', 1000),
786
+ * op.beginsWith('category', 'ELECTRONICS'),
787
+ * op.attributeExists('reviewDate')
788
+ * ])
789
+ * )
790
+ * ```
791
+ *
792
+ * @param condition - Either a Condition object or a callback function that builds the condition
793
+ * @returns The builder instance for method chaining
794
+ */
795
+ /**
796
+ * Adds a filter expression to refine the query results.
797
+ * Use this method when you need to:
798
+ * - Filter dinosaurs by behavior patterns
799
+ * - Find habitats with specific conditions
800
+ * - Search for security incidents
801
+ * - Monitor feeding patterns
802
+ *
803
+ * @example
804
+ * ```typescript
805
+ * // Find aggressive carnivores
806
+ * builder.filter(op =>
807
+ * op.and([
808
+ * op.eq('diet', 'CARNIVORE'),
809
+ * op.gt('aggressionLevel', 7),
810
+ * op.eq('status', 'ACTIVE')
811
+ * ])
812
+ * );
813
+ *
814
+ * // Search suitable breeding habitats
815
+ * builder.filter(op =>
816
+ * op.and([
817
+ * op.between('temperature', 25, 30),
818
+ * op.lt('currentOccupants', 3),
819
+ * op.eq('quarantineStatus', 'CLEAR')
820
+ * ])
821
+ * );
822
+ * ```
823
+ *
824
+ * @param condition - Either a Condition object or a callback function that builds the condition
825
+ * @returns The builder instance for method chaining
826
+ */
827
+ filter(condition: Condition | ((op: ConditionOperator<T>) => Condition)): QueryBuilder<T>;
828
+ /**
829
+ * Specifies which attributes to return in the query results.
830
+ * Use this method when you need to:
831
+ * - Reduce data transfer by selecting specific attributes
832
+ * - Optimize response size
833
+ * - Focus on relevant attributes only
834
+ *
835
+ * Note: Using projection can significantly reduce the amount
836
+ * of data returned and lower your costs.
837
+ *
838
+ * @example
839
+ * ```ts
840
+ * // Select single attribute
841
+ * builder.select('email')
842
+ *
843
+ * // Select multiple attributes
844
+ * builder.select(['id', 'name', 'email'])
845
+ *
846
+ * // Chain multiple select calls
847
+ * builder
848
+ * .select('id')
849
+ * .select(['name', 'email'])
850
+ * ```
851
+ *
852
+ * @param fields - A single field name or an array of field names to return
853
+ * @returns The builder instance for method chaining
854
+ */
855
+ /**
856
+ * Specifies which attributes to return in the query results.
857
+ * Use this method when you need to:
858
+ * - Get specific dinosaur attributes
859
+ * - Retrieve habitat statistics
860
+ * - Monitor security metrics
861
+ * - Optimize response size
862
+ *
863
+ * @example
864
+ * ```typescript
865
+ * // Get basic dinosaur info
866
+ * builder.select([
867
+ * 'species',
868
+ * 'status',
869
+ * 'stats.health',
870
+ * 'stats.aggressionLevel'
871
+ * ]);
872
+ *
873
+ * // Monitor habitat conditions
874
+ * builder
875
+ * .select('securityStatus')
876
+ * .select([
877
+ * 'currentOccupants',
878
+ * 'temperature',
879
+ * 'lastInspectionDate'
880
+ * ]);
881
+ * ```
882
+ *
883
+ * @param fields - A single field name or an array of field names to return
884
+ * @returns The builder instance for method chaining
885
+ */
886
+ select(fields: string | string[]): QueryBuilder<T>;
887
+ /**
888
+ * Sets the query to return items in ascending order by sort key.
889
+ * Use this method when you need to:
890
+ * - Retrieve items in natural order (e.g., timestamps, versions)
891
+ * - Implement chronological ordering
892
+ * - Get oldest items first
893
+ *
894
+ * Note: This is the default behavior if no sort order is specified.
895
+ *
896
+ * @example
897
+ * ```typescript
898
+ * // Get orders in chronological order
899
+ * const result = await new QueryBuilder(executor, eq('userId', '123'))
900
+ * .sortAscending()
901
+ * .execute();
902
+ *
903
+ * // Get events from oldest to newest
904
+ * const result = await new QueryBuilder(executor, eq('entityId', 'order-123'))
905
+ * .useIndex('entity-timestamp-index')
906
+ * .sortAscending()
907
+ * .execute();
908
+ * ```
909
+ *
910
+ * @returns The builder instance for method chaining
911
+ */
912
+ /**
913
+ * Sets the query to return items in ascending order by sort key.
914
+ * Use this method when you need to:
915
+ * - List dinosaurs by age (youngest first)
916
+ * - View incidents chronologically
917
+ * - Track feeding schedule progression
918
+ * - Monitor habitat inspections
919
+ *
920
+ * @example
921
+ * ```typescript
922
+ * // List dinosaurs by age
923
+ * const result = await new QueryBuilder(executor, eq('species', 'Velociraptor'))
924
+ * .useIndex('age-index')
925
+ * .sortAscending()
926
+ * .execute();
927
+ *
928
+ * // View incidents chronologically
929
+ * const result = await new QueryBuilder(executor, eq('type', 'SECURITY_BREACH'))
930
+ * .useIndex('date-index')
931
+ * .sortAscending()
932
+ * .execute();
933
+ * ```
934
+ *
935
+ * @returns The builder instance for method chaining
936
+ */
937
+ sortAscending(): QueryBuilder<T>;
938
+ /**
939
+ * Sets the query to return items in descending order by sort key.
940
+ * Use this method when you need to:
941
+ * - Get most recent security breaches
942
+ * - Find oldest dinosaurs first
943
+ * - Check latest habitat modifications
944
+ * - Monitor recent feeding events
945
+ *
946
+ * @example
947
+ * ```typescript
948
+ * // Get most recent security incidents
949
+ * const result = await new QueryBuilder(executor, eq('type', 'SECURITY_BREACH'))
950
+ * .useIndex('date-index')
951
+ * .sortDescending()
952
+ * .limit(10)
953
+ * .execute();
954
+ *
955
+ * // Check latest dinosaur activities
956
+ * const result = await new QueryBuilder(executor, eq('species', 'Velociraptor'))
957
+ * .useIndex('activity-time-index')
958
+ * .filter(op => op.eq('status', 'ACTIVE'))
959
+ * .sortDescending()
960
+ * .execute();
961
+ * ```
962
+ *
963
+ * @returns The builder instance for method chaining
964
+ */
965
+ sortDescending(): QueryBuilder<T>;
966
+ /**
967
+ * Creates a paginator that handles DynamoDB pagination automatically.
968
+ * Use this method when you need to:
969
+ * - Browse large dinosaur collections
970
+ * - View habitat inspection history
971
+ * - Monitor security incidents
972
+ * - Track feeding patterns
973
+ *
974
+ * The paginator handles:
975
+ * - Tracking the last evaluated key
976
+ * - Managing page boundaries
977
+ * - Respecting overall query limits
978
+ *
979
+ * @example
980
+ * ```typescript
981
+ * // List dinosaurs by species
982
+ * const paginator = new QueryBuilder(executor, eq('species', 'Velociraptor'))
983
+ * .filter(op => op.eq('status', 'ACTIVE'))
984
+ * .useIndex('species-index')
985
+ * .paginate(10);
986
+ *
987
+ * // Process pages of security incidents
988
+ * const paginator = new QueryBuilder(executor, eq('type', 'SECURITY_BREACH'))
989
+ * .filter(op => op.gt('severityLevel', 7))
990
+ * .sortDescending()
991
+ * .paginate(25);
992
+ *
993
+ * while (paginator.hasNextPage()) {
994
+ * const page = await paginator.getNextPage();
995
+ * console.log(`Processing incidents page ${page.page}, count: ${page.items.length}`);
996
+ * // Handle security incidents
997
+ * }
998
+ * ```
999
+ *
1000
+ * @param pageSize - The number of items to return per page
1001
+ * @returns A Paginator instance that manages the pagination state
1002
+ * @see Paginator for more pagination control options
1003
+ */
1004
+ paginate(pageSize: number): Paginator<T, TConfig>;
1005
+ /**
1006
+ * Sets the starting point for the query using a previous lastEvaluatedKey.
1007
+ * Use this method when you need to:
1008
+ * - Implement manual dinosaur list pagination
1009
+ * - Resume habitat inspection reviews
1010
+ * - Continue security incident analysis
1011
+ * - Store query position between sessions
1012
+ *
1013
+ * Note: This method is typically used for manual pagination.
1014
+ * For automatic pagination, use the paginate() method instead.
1015
+ *
1016
+ * @example
1017
+ * ```typescript
1018
+ * // First batch of dinosaurs
1019
+ * const result1 = await new QueryBuilder(executor, eq('species', 'Velociraptor'))
1020
+ * .filter(op => op.eq('status', 'ACTIVE'))
1021
+ * .limit(5)
1022
+ * .execute();
1023
+ *
1024
+ * if (result1.lastEvaluatedKey) {
1025
+ * // Continue listing dinosaurs
1026
+ * const result2 = await new QueryBuilder(executor, eq('species', 'Velociraptor'))
1027
+ * .filter(op => op.eq('status', 'ACTIVE'))
1028
+ * .startFrom(result1.lastEvaluatedKey)
1029
+ * .limit(5)
1030
+ * .execute();
1031
+ *
1032
+ * console.log('Additional dinosaurs:', result2.items);
1033
+ * }
1034
+ * ```
1035
+ *
1036
+ * @param lastEvaluatedKey - The exclusive start key from a previous query result
1037
+ * @returns The builder instance for method chaining
1038
+ */
1039
+ startFrom(lastEvaluatedKey: Record<string, unknown>): QueryBuilder<T>;
1040
+ /**
1041
+ * Creates a deep clone of this QueryBuilder instance.
1042
+ * Use this method when you need to:
1043
+ * - Query different dinosaur statuses
1044
+ * - Check multiple habitat conditions
1045
+ * - Monitor various security levels
1046
+ * - Create report templates
1047
+ *
1048
+ * This is particularly useful when:
1049
+ * - Implementing pagination (used internally by paginate())
1050
+ * - Creating query templates
1051
+ * - Running multiple variations of a query
1052
+ *
1053
+ * @example
1054
+ * ```typescript
1055
+ * // Create base dinosaur query
1056
+ * const baseQuery = new QueryBuilder(executor, eq('species', 'Velociraptor'))
1057
+ * .useIndex('status-index')
1058
+ * .select(['id', 'status', 'location']);
1059
+ *
1060
+ * // Check active dinosaurs
1061
+ * const activeRaptors = baseQuery.clone()
1062
+ * .filter(op => op.eq('status', 'HUNTING'))
1063
+ * .execute();
1064
+ *
1065
+ * // Check contained dinosaurs
1066
+ * const containedRaptors = baseQuery.clone()
1067
+ * .filter(op => op.eq('status', 'CONTAINED'))
1068
+ * .execute();
1069
+ *
1070
+ * // Check sedated dinosaurs
1071
+ * const sedatedRaptors = baseQuery.clone()
1072
+ * .filter(op => op.eq('status', 'SEDATED'))
1073
+ * .execute();
1074
+ * ```
1075
+ *
1076
+ * @returns A new QueryBuilder instance with the same configuration
1077
+ */
1078
+ clone(): QueryBuilder<T, TConfig>;
1079
+ /**
1080
+ * Executes the query against DynamoDB.
1081
+ * Use this method when you need to:
1082
+ * - Find specific dinosaur groups
1083
+ * - Check habitat conditions
1084
+ * - Monitor security incidents
1085
+ * - Track feeding patterns
1086
+ *
1087
+ * The method returns both the matched items and, if there are more results,
1088
+ * a lastEvaluatedKey that can be used with startFrom() to continue the query.
1089
+ *
1090
+ * @example
1091
+ * ```typescript
1092
+ * try {
1093
+ * // Find active carnivores in specific habitat
1094
+ * const result = await new QueryBuilder(executor, eq('habitatId', 'PADDOCK-A'))
1095
+ * .useIndex('species-status-index')
1096
+ * .filter(op =>
1097
+ * op.and([
1098
+ * op.eq('diet', 'CARNIVORE'),
1099
+ * op.eq('status', 'ACTIVE'),
1100
+ * op.gt('aggressionLevel', 7)
1101
+ * ])
1102
+ * )
1103
+ * .sortDescending()
1104
+ * .limit(5)
1105
+ * .execute();
1106
+ *
1107
+ * console.log(`Found ${result.items.length} dangerous dinosaurs`);
1108
+ *
1109
+ * if (result.lastEvaluatedKey) {
1110
+ * console.log('Additional threats detected');
1111
+ * }
1112
+ * } catch (error) {
1113
+ * console.error('Security scan failed:', error);
1114
+ * }
1115
+ * ```
1116
+ *
1117
+ * @returns A promise that resolves to an object containing:
1118
+ * - items: Array of items matching the query
1119
+ * - lastEvaluatedKey: Token for continuing the query, if more items exist
1120
+ */
1121
+ execute(): Promise<{
1122
+ items: T[];
1123
+ lastEvaluatedKey?: Record<string, unknown>;
117
1124
  }>;
118
1125
  }
119
- type DynamoOperation = DynamoPutOperation | DynamoUpdateOperation | DynamoQueryOperation | DynamoDeleteOperation | DynamoBatchWriteOperation | DynamoTransactOperation;
120
- type PrimaryKeyWithoutExpression = {
121
- pk: string;
122
- sk?: string;
123
- };
124
- type BatchWriteOperation = {
125
- type: "put";
126
- item: Record<string, unknown>;
127
- } | {
128
- type: "delete";
129
- key: PrimaryKeyWithoutExpression;
130
- };
131
1126
 
132
- declare abstract class OperationBuilder<T extends DynamoOperation> {
133
- protected expressionBuilder: IExpressionBuilder;
134
- protected conditions: Array<{
135
- field: string;
136
- operator: ConditionOperator;
137
- value?: unknown;
138
- }>;
139
- constructor(expressionBuilder: IExpressionBuilder);
140
- where(field: string, operator: FilterOperator, value: unknown): this;
141
- whereExists(field: string): this;
142
- whereNotExists(field: string): this;
143
- whereEquals(field: string, value: unknown): this;
144
- whereBetween(field: string, start: unknown, end: unknown): this;
145
- whereIn(field: string, values: unknown[]): this;
146
- protected buildConditionExpression(): ExpressionResult;
147
- abstract build(): T;
1127
+ /**
1128
+ * Interface for DynamoDB command objects that can contain expressions
1129
+ */
1130
+ interface DynamoCommandWithExpressions {
1131
+ conditionExpression?: string;
1132
+ updateExpression?: string;
1133
+ filterExpression?: string;
1134
+ keyConditionExpression?: string;
1135
+ projectionExpression?: string;
1136
+ expressionAttributeNames?: Record<string, string>;
1137
+ expressionAttributeValues?: Record<string, unknown>;
1138
+ [key: string]: unknown;
148
1139
  }
149
1140
 
150
- declare class PutBuilder extends OperationBuilder<DynamoPutOperation> {
151
- private readonly item;
152
- private readonly onBuild;
153
- constructor(item: Record<string, unknown>, expressionBuilder: IExpressionBuilder, onBuild: (operation: DynamoPutOperation) => Promise<void>);
154
- build(): DynamoPutOperation;
155
- execute(): Promise<void>;
1141
+ /**
1142
+ * Parameters for the DynamoDB update command.
1143
+ * These parameters are used when executing the operation against DynamoDB.
1144
+ */
1145
+ interface UpdateCommandParams extends DynamoCommandWithExpressions {
1146
+ /** The name of the DynamoDB table */
1147
+ tableName: string;
1148
+ /** The primary key of the item to update */
1149
+ key: PrimaryKeyWithoutExpression;
1150
+ /** The update expression (SET, REMOVE, ADD, DELETE clauses) */
1151
+ updateExpression: string;
1152
+ /** Optional condition expression that must be satisfied */
1153
+ conditionExpression?: string;
1154
+ /** Map of expression attribute name placeholders to actual names */
1155
+ expressionAttributeNames?: Record<string, string>;
1156
+ /** Map of expression attribute value placeholders to actual values */
1157
+ expressionAttributeValues?: Record<string, unknown>;
1158
+ /** Which item attributes to include in the response */
1159
+ returnValues?: "ALL_NEW" | "UPDATED_NEW" | "ALL_OLD" | "UPDATED_OLD" | "NONE";
156
1160
  }
157
-
158
- declare class QueryBuilder extends OperationBuilder<DynamoQueryOperation> {
1161
+ /**
1162
+ * Function type for executing DynamoDB update operations.
1163
+ * @typeParam T - The type of the item being updated
1164
+ */
1165
+ type UpdateExecutor<T extends Record<string, unknown>> = (params: UpdateCommandParams) => Promise<{
1166
+ item?: T;
1167
+ }>;
1168
+ /**
1169
+ * Type utility to get the element type of a set.
1170
+ * Extracts the element type from either a Set or Array type.
1171
+ * @typeParam T - The set or array type
1172
+ */
1173
+ type SetElementType<T> = T extends Set<infer U> ? U : T extends Array<infer U> ? U : never;
1174
+ /**
1175
+ * Type utility to get the element type from a path that points to a set.
1176
+ * Combines PathType and SetElementType to get the element type at a specific path.
1177
+ * @typeParam T - The type of the item
1178
+ * @typeParam K - The path within the item
1179
+ */
1180
+ type PathSetElementType<T, K extends Path<T>> = SetElementType<PathType<T, K>>;
1181
+ /**
1182
+ * Builder for creating DynamoDB update operations.
1183
+ * Use this builder when you need to:
1184
+ * - Modify existing items in DynamoDB
1185
+ * - Update multiple attributes atomically
1186
+ * - Perform conditional updates
1187
+ * - Work with nested attributes
1188
+ * - Update sets and lists
1189
+ *
1190
+ * The builder supports all DynamoDB update operations:
1191
+ * - SET: Modify or add attributes
1192
+ * - REMOVE: Delete attributes
1193
+ * - ADD: Update numbers and sets
1194
+ * - DELETE: Remove elements from a set
1195
+ *
1196
+ * @example
1197
+ * ```typescript
1198
+ * // Simple update
1199
+ * const result = await new UpdateBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
1200
+ * .set('status', 'HUNTING')
1201
+ * .set('lastFed', new Date().toISOString())
1202
+ * .execute();
1203
+ *
1204
+ * // Complex update with multiple operations
1205
+ * const result = await new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
1206
+ * .set({
1207
+ * status: 'OCCUPIED',
1208
+ * occupants: 3,
1209
+ * 'metadata.lastInspection': new Date().toISOString()
1210
+ * })
1211
+ * .add('securityBreaches', 1)
1212
+ * .deleteElementsFromSet('suitableDinosaurs', ['VELOCIRAPTOR'])
1213
+ * .condition(op => op.gt('securityLevel', 8))
1214
+ * .returnValues('ALL_NEW')
1215
+ * .execute();
1216
+ * ```
1217
+ *
1218
+ * @typeParam T - The type of item being updated
1219
+ */
1220
+ declare class UpdateBuilder<T extends Record<string, unknown>> {
1221
+ private updates;
1222
+ private options;
1223
+ private readonly executor;
1224
+ private readonly tableName;
159
1225
  private readonly key;
160
- private readonly indexConfig;
161
- private readonly onBuild;
162
- private limitValue?;
163
- private indexNameValue?;
164
- constructor(key: PrimaryKey, indexConfig: TableIndexConfig, expressionBuilder: IExpressionBuilder, onBuild: (operation: DynamoQueryOperation) => Promise<{
165
- Items?: Record<string, unknown>[];
166
- Count?: number;
167
- ScannedCount?: number;
168
- LastEvaluatedKey?: Record<string, unknown>;
169
- }>);
170
- limit(value: number): this;
171
- useIndex(indexName: string): this;
172
- build(): DynamoQueryOperation;
1226
+ constructor(executor: UpdateExecutor<T>, tableName: string, key: PrimaryKeyWithoutExpression);
1227
+ /**
1228
+ * Sets multiple attributes of an item using an object.
1229
+ * Use this method when you need to:
1230
+ * - Update multiple attributes at once
1231
+ * - Set nested attribute values
1232
+ * - Modify complex data structures
1233
+ *
1234
+ * @example
1235
+ * ```typescript
1236
+ * // Update multiple attributes
1237
+ * builder.set({
1238
+ * species: 'Tyrannosaurus Rex',
1239
+ * height: 20,
1240
+ * diet: 'CARNIVORE',
1241
+ * 'stats.threatLevel': 10
1242
+ * });
1243
+ * ```
1244
+ */
1245
+ set(values: Partial<T>): UpdateBuilder<T>;
1246
+ /**
1247
+ * Sets a single attribute to a specific value.
1248
+ * Use this method when you need to:
1249
+ * - Update one attribute at a time
1250
+ * - Set values with type safety
1251
+ * - Update nested attributes
1252
+ *
1253
+ * @example
1254
+ * ```typescript
1255
+ * // Set simple attributes
1256
+ * builder
1257
+ * .set('status', 'SLEEPING')
1258
+ * .set('lastFeeding', new Date().toISOString());
1259
+ *
1260
+ * // Set nested attributes
1261
+ * builder
1262
+ * .set('location.zone', 'RESTRICTED')
1263
+ * .set('stats.health', 100);
1264
+ * ```
1265
+ */
1266
+ set<K extends Path<T>>(path: K, value: PathType<T, K>): UpdateBuilder<T>;
1267
+ /**
1268
+ * Removes an attribute from the item.
1269
+ * Use this method when you need to:
1270
+ * - Delete attributes completely
1271
+ * - Remove nested attributes
1272
+ * - Clean up deprecated fields
1273
+ *
1274
+ * @example
1275
+ * ```typescript
1276
+ * // Remove simple attributes
1277
+ * builder
1278
+ * .remove('temporaryTag')
1279
+ * .remove('previousLocation');
1280
+ *
1281
+ * // Remove nested attributes
1282
+ * builder
1283
+ * .remove('metadata.testData')
1284
+ * .remove('stats.experimentalMetrics');
1285
+ * ```
1286
+ *
1287
+ * @param path - The path to the attribute to remove
1288
+ * @returns The builder instance for method chaining
1289
+ */
1290
+ remove<K extends Path<T>>(path: K): UpdateBuilder<T>;
1291
+ /**
1292
+ * Adds a value to a number attribute or adds elements to a set.
1293
+ * Use this method when you need to:
1294
+ * - Increment counters
1295
+ * - Add elements to a set atomically
1296
+ * - Update numerical statistics
1297
+ *
1298
+ * @example
1299
+ * ```typescript
1300
+ * // Increment counters
1301
+ * builder
1302
+ * .add('escapeAttempts', 1)
1303
+ * .add('feedingCount', 1);
1304
+ *
1305
+ * // Add to sets
1306
+ * builder
1307
+ * .add('knownBehaviors', new Set(['PACK_HUNTING', 'AMBUSH_TACTICS']))
1308
+ * .add('visitedZones', new Set(['ZONE_A', 'ZONE_B']));
1309
+ * ```
1310
+ *
1311
+ * @param path - The path to the attribute to update
1312
+ * @param value - The value to add (number or set)
1313
+ * @returns The builder instance for method chaining
1314
+ */
1315
+ add<K extends Path<T>>(path: K, value: PathType<T, K>): UpdateBuilder<T>;
1316
+ /**
1317
+ * Removes elements from a set attribute.
1318
+ * Use this method when you need to:
1319
+ * - Remove specific elements from a set
1320
+ * - Update set-based attributes atomically
1321
+ * - Maintain set membership
1322
+ *
1323
+ * @example
1324
+ * ```typescript
1325
+ * // Remove from sets using arrays
1326
+ * builder.deleteElementsFromSet(
1327
+ * 'allowedHabitats',
1328
+ * ['JUNGLE', 'COASTAL']
1329
+ * );
1330
+ *
1331
+ * // Remove from sets using Set objects
1332
+ * builder.deleteElementsFromSet(
1333
+ * 'knownBehaviors',
1334
+ * new Set(['NOCTURNAL', 'TERRITORIAL'])
1335
+ * );
1336
+ *
1337
+ * // Remove from nested sets
1338
+ * builder.deleteElementsFromSet(
1339
+ * 'stats.compatibleSpecies',
1340
+ * ['VELOCIRAPTOR', 'DILOPHOSAURUS']
1341
+ * );
1342
+ * ```
1343
+ *
1344
+ * @param path - The path to the set attribute
1345
+ * @param value - Elements to remove (array or Set)
1346
+ * @returns The builder instance for method chaining
1347
+ */
1348
+ deleteElementsFromSet<K extends Path<T>>(path: K, value: PathSetElementType<T, K>[] | Set<PathSetElementType<T, K>>): UpdateBuilder<T>;
1349
+ /**
1350
+ * Adds a condition that must be satisfied for the update to succeed.
1351
+ * Use this method when you need to:
1352
+ * - Implement optimistic locking
1353
+ * - Ensure item state before update
1354
+ * - Validate business rules
1355
+ * - Prevent concurrent modifications
1356
+ *
1357
+ * @example
1358
+ * ```typescript
1359
+ * // Simple condition
1360
+ * builder.condition(op =>
1361
+ * op.eq('status', 'ACTIVE')
1362
+ * );
1363
+ *
1364
+ * // Health check condition
1365
+ * builder.condition(op =>
1366
+ * op.and([
1367
+ * op.gt('health', 50),
1368
+ * op.eq('status', 'HUNTING')
1369
+ * ])
1370
+ * );
1371
+ *
1372
+ * // Complex security condition
1373
+ * builder.condition(op =>
1374
+ * op.and([
1375
+ * op.attributeExists('securitySystem'),
1376
+ * op.eq('containmentStatus', 'SECURE'),
1377
+ * op.lt('aggressionLevel', 8)
1378
+ * ])
1379
+ * );
1380
+ *
1381
+ * // Version check (optimistic locking)
1382
+ * builder.condition(op =>
1383
+ * op.eq('version', currentVersion)
1384
+ * );
1385
+ * ```
1386
+ *
1387
+ * @param condition - Either a Condition object or a callback function that builds the condition
1388
+ * @returns The builder instance for method chaining
1389
+ */
1390
+ condition(condition: Condition | ((op: ConditionOperator<T>) => Condition)): UpdateBuilder<T>;
1391
+ /**
1392
+ * Sets which item attributes to include in the response.
1393
+ * Use this method when you need to:
1394
+ * - Get the complete updated item
1395
+ * - Track changes to specific attributes
1396
+ * - Compare old and new values
1397
+ * - Monitor attribute modifications
1398
+ *
1399
+ * Available options:
1400
+ * - ALL_NEW: All attributes after the update
1401
+ * - UPDATED_NEW: Only updated attributes, new values
1402
+ * - ALL_OLD: All attributes before the update
1403
+ * - UPDATED_OLD: Only updated attributes, old values
1404
+ * - NONE: No attributes returned (default)
1405
+ *
1406
+ * @example
1407
+ * ```typescript
1408
+ * // Get complete updated dinosaur
1409
+ * const result = await builder
1410
+ * .set('status', 'SLEEPING')
1411
+ * .returnValues('ALL_NEW')
1412
+ * .execute();
1413
+ *
1414
+ * // Track specific attribute changes
1415
+ * const result = await builder
1416
+ * .set({
1417
+ * 'stats.health': 100,
1418
+ * 'stats.energy': 95
1419
+ * })
1420
+ * .returnValues('UPDATED_OLD')
1421
+ * .execute();
1422
+ *
1423
+ * if (result.item) {
1424
+ * console.log('Previous health:', result.item.stats?.health);
1425
+ * }
1426
+ * ```
1427
+ *
1428
+ * @param returnValues - Which attributes to return in the response
1429
+ * @returns The builder instance for method chaining
1430
+ */
1431
+ returnValues(returnValues: "ALL_NEW" | "UPDATED_NEW" | "ALL_OLD" | "UPDATED_OLD" | "NONE"): UpdateBuilder<T>;
1432
+ /**
1433
+ * Generate the DynamoDB command parameters
1434
+ */
1435
+ toDynamoCommand(): UpdateCommandParams;
1436
+ /**
1437
+ * Adds this update operation to a transaction.
1438
+ * Use this method when you need to:
1439
+ * - Update items as part of a larger transaction
1440
+ * - Ensure multiple updates are atomic
1441
+ * - Coordinate updates across multiple items
1442
+ *
1443
+ * @example
1444
+ * ```typescript
1445
+ * const transaction = new TransactionBuilder(executor);
1446
+ *
1447
+ * // Update dinosaur status and habitat occupancy atomically
1448
+ * new UpdateBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
1449
+ * .set('location', 'PADDOCK_A')
1450
+ * .set('status', 'CONTAINED')
1451
+ * .withTransaction(transaction);
1452
+ *
1453
+ * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
1454
+ * .add('occupants', 1)
1455
+ * .set('lastOccupied', new Date().toISOString())
1456
+ * .withTransaction(transaction);
1457
+ *
1458
+ * // Execute all operations atomically
1459
+ * await transaction.execute();
1460
+ * ```
1461
+ *
1462
+ * @param transaction - The transaction builder to add this operation to
1463
+ * @returns The builder instance for method chaining
1464
+ */
1465
+ withTransaction(transaction: TransactionBuilder): void;
1466
+ /**
1467
+ * Gets a human-readable representation of the update command.
1468
+ * Use this method when you need to:
1469
+ * - Debug complex update expressions
1470
+ * - Verify attribute names and values
1471
+ * - Log update operations
1472
+ * - Troubleshoot condition expressions
1473
+ *
1474
+ * @example
1475
+ * ```typescript
1476
+ * // Create complex update
1477
+ * const builder = new UpdateBuilder(executor, 'dinosaurs', { id: 'RAPTOR-001' })
1478
+ * .set({
1479
+ * status: 'HUNTING',
1480
+ * 'stats.health': 95,
1481
+ * 'behavior.lastObserved': new Date().toISOString()
1482
+ * })
1483
+ * .add('huntingSuccesses', 1)
1484
+ * .condition(op => op.gt('health', 50));
1485
+ *
1486
+ * // Debug the update
1487
+ * const debugInfo = builder.debug();
1488
+ * console.log('Update operation:', debugInfo);
1489
+ * ```
1490
+ *
1491
+ * @returns A readable representation of the update command with resolved expressions
1492
+ */
1493
+ debug(): Record<string, unknown>;
1494
+ /**
1495
+ * Executes the update operation against DynamoDB.
1496
+ * Use this method when you need to:
1497
+ * - Apply updates immediately
1498
+ * - Get the updated item values
1499
+ * - Handle conditional update failures
1500
+ *
1501
+ * @example
1502
+ * ```typescript
1503
+ * try {
1504
+ * // Update dinosaur status with conditions
1505
+ * const result = await new UpdateBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
1506
+ * .set({
1507
+ * status: 'FEEDING',
1508
+ * lastMeal: new Date().toISOString(),
1509
+ * 'stats.hunger': 0
1510
+ * })
1511
+ * .add('feedingCount', 1)
1512
+ * .condition(op =>
1513
+ * op.and([
1514
+ * op.gt('stats.hunger', 80),
1515
+ * op.eq('status', 'HUNTING')
1516
+ * ])
1517
+ * )
1518
+ * .returnValues('ALL_NEW')
1519
+ * .execute();
1520
+ *
1521
+ * if (result.item) {
1522
+ * console.log('Updated dinosaur:', result.item);
1523
+ * }
1524
+ * } catch (error) {
1525
+ * // Handle condition check failure
1526
+ * console.error('Failed to update dinosaur:', error);
1527
+ * // Check if dinosaur wasn't hungry enough
1528
+ * if (error.name === 'ConditionalCheckFailedException') {
1529
+ * console.log('Dinosaur not ready for feeding');
1530
+ * }
1531
+ * }
1532
+ * ```
1533
+ *
1534
+ * @returns A promise that resolves to an object containing the updated item (if returnValues is set)
1535
+ * @throws {ConditionalCheckFailedException} If the condition check fails
1536
+ * @throws {Error} If the update operation fails for other reasons
1537
+ */
173
1538
  execute(): Promise<{
174
- Items?: Record<string, unknown>[];
175
- Count?: number;
176
- ScannedCount?: number;
177
- LastEvaluatedKey?: Record<string, unknown>;
1539
+ item?: T;
178
1540
  }>;
179
1541
  }
180
1542
 
181
- declare class UpdateBuilder extends OperationBuilder<DynamoUpdateOperation> {
1543
+ interface DeleteCommandParams extends DynamoCommandWithExpressions {
1544
+ tableName: string;
1545
+ key: PrimaryKeyWithoutExpression;
1546
+ conditionExpression?: string;
1547
+ expressionAttributeNames?: Record<string, string>;
1548
+ expressionAttributeValues?: Record<string, unknown>;
1549
+ returnValues?: "ALL_OLD";
1550
+ }
1551
+ type DeleteExecutor = (params: DeleteCommandParams) => Promise<{
1552
+ item?: Record<string, unknown>;
1553
+ }>;
1554
+ /**
1555
+ * Builder for creating DynamoDB delete operations.
1556
+ * Use this builder when you need to:
1557
+ * - Delete items from a DynamoDB table
1558
+ * - Conditionally delete items based on attribute values
1559
+ * - Delete items as part of a transaction
1560
+ * - Retrieve the old item values after deletion
1561
+ *
1562
+ * @example
1563
+ * ```ts
1564
+ * const result = await new DeleteBuilder(executor, 'myTable', { id: '123' })
1565
+ * .condition(op => op.attributeExists('status'))
1566
+ * .returnValues('ALL_OLD')
1567
+ * .execute();
1568
+ * ```
1569
+ */
1570
+ /**
1571
+ * Builder for creating DynamoDB delete operations.
1572
+ * Use this builder when you need to:
1573
+ * - Remove dinosaurs from the registry
1574
+ * - Clean up abandoned habitats
1575
+ * - Delete historical tracking data
1576
+ * - Remove deprecated classifications
1577
+ *
1578
+ * @example
1579
+ * ```typescript
1580
+ * // Simple delete
1581
+ * const result = await new DeleteBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
1582
+ * .execute();
1583
+ *
1584
+ * // Conditional delete with old value retrieval
1585
+ * const result = await new DeleteBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
1586
+ * .condition(op =>
1587
+ * op.and([
1588
+ * op.eq('status', 'DECOMMISSIONED'),
1589
+ * op.eq('occupants', 0),
1590
+ * op.lt('securityIncidents', 1)
1591
+ * ])
1592
+ * )
1593
+ * .returnValues('ALL_OLD')
1594
+ * .execute();
1595
+ * ```
1596
+ */
1597
+ declare class DeleteBuilder {
1598
+ private options;
1599
+ private readonly executor;
1600
+ private readonly tableName;
182
1601
  private readonly key;
183
- private readonly onBuild;
184
- private updates;
185
- constructor(key: PrimaryKeyWithoutExpression, expressionBuilder: IExpressionBuilder, onBuild: (operation: DynamoUpdateOperation) => Promise<{
186
- Attributes?: Record<string, unknown>;
187
- }>);
188
- set(field: string, value: unknown): this;
189
- setMany(attribtues: Record<string, unknown>): this;
190
- remove(...fields: string[]): this;
191
- increment(field: string, by?: number): this;
192
- build(): DynamoUpdateOperation;
1602
+ constructor(executor: DeleteExecutor, tableName: string, key: PrimaryKeyWithoutExpression);
1603
+ /**
1604
+ * Adds a condition that must be satisfied for the delete operation to succeed.
1605
+ * Use this method when you need to:
1606
+ * - Implement optimistic locking (e.g., version check)
1607
+ * - Ensure item exists before deletion
1608
+ * - Validate item state before deletion
1609
+ *
1610
+ * @example
1611
+ * ```ts
1612
+ * // Simple condition
1613
+ * builder.condition(op => op.attributeExists('id'))
1614
+ *
1615
+ * // Complex condition with version check
1616
+ * builder.condition(op =>
1617
+ * op.and([
1618
+ * op.eq('version', 1),
1619
+ * op.eq('status', 'ACTIVE')
1620
+ * ])
1621
+ * )
1622
+ * ```
1623
+ *
1624
+ * @param condition - Either a Condition object or a callback function that builds the condition
1625
+ * @returns The builder instance for method chaining
1626
+ */
1627
+ /**
1628
+ * Adds a condition that must be satisfied for the delete operation to succeed.
1629
+ * Use this method when you need to:
1630
+ * - Ensure safe removal conditions
1631
+ * - Verify habitat status before deletion
1632
+ * - Implement safety protocols
1633
+ *
1634
+ * @example
1635
+ * ```typescript
1636
+ * // Ensure dinosaur can be safely removed
1637
+ * builder.condition(op =>
1638
+ * op.and([
1639
+ * op.eq('status', 'SEDATED'),
1640
+ * op.eq('location', 'MEDICAL_BAY'),
1641
+ * op.attributeExists('lastCheckup')
1642
+ * ])
1643
+ * );
1644
+ *
1645
+ * // Verify habitat is empty
1646
+ * builder.condition(op =>
1647
+ * op.and([
1648
+ * op.eq('occupants', 0),
1649
+ * op.eq('maintenanceStatus', 'COMPLETE'),
1650
+ * op.not(op.attributeExists('activeAlerts'))
1651
+ * ])
1652
+ * );
1653
+ * ```
1654
+ *
1655
+ * @param condition - Either a Condition object or a callback function that builds the condition
1656
+ * @returns The builder instance for method chaining
1657
+ */
1658
+ condition<T extends Record<string, unknown>>(condition: Condition | ((op: ConditionOperator<T>) => Condition)): DeleteBuilder;
1659
+ /**
1660
+ * Sets whether to return the item's attribute values before deletion.
1661
+ * Use this method when you need to:
1662
+ * - Archive removed dinosaur data
1663
+ * - Track habitat decommissioning history
1664
+ * - Maintain removal audit logs
1665
+ *
1666
+ * @example
1667
+ * ```ts
1668
+ * // Archive dinosaur data before removal
1669
+ * const result = await builder
1670
+ * .returnValues('ALL_OLD')
1671
+ * .execute();
1672
+ *
1673
+ * if (result.item) {
1674
+ * console.log('Removed dinosaur data:', {
1675
+ * species: result.item.species,
1676
+ * age: result.item.age,
1677
+ * lastLocation: result.item.location
1678
+ * });
1679
+ * }
1680
+ * ```
1681
+ *
1682
+ * @param returnValues - Use 'ALL_OLD' to return all attributes of the deleted item
1683
+ * @returns The builder instance for method chaining
1684
+ */
1685
+ returnValues(returnValues: "ALL_OLD"): DeleteBuilder;
1686
+ /**
1687
+ * Generate the DynamoDB command parameters
1688
+ */
1689
+ private toDynamoCommand;
1690
+ /**
1691
+ * Adds this delete operation to a transaction.
1692
+ * Use this method when you need to:
1693
+ * - Coordinate dinosaur transfers
1694
+ * - Manage habitat decommissioning
1695
+ * - Handle species relocations
1696
+ *
1697
+ * @example
1698
+ * ```ts
1699
+ * const transaction = new TransactionBuilder();
1700
+ *
1701
+ * // Remove dinosaur from old habitat
1702
+ * new DeleteBuilder(executor, 'dinosaurs', { id: 'RAPTOR-001' })
1703
+ * .condition(op => op.eq('status', 'SEDATED'))
1704
+ * .withTransaction(transaction);
1705
+ *
1706
+ * // Update old habitat occupancy
1707
+ * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
1708
+ * .add('occupants', -1)
1709
+ * .withTransaction(transaction);
1710
+ *
1711
+ * // Execute transfer atomically
1712
+ * await transaction.execute();
1713
+ * ```
1714
+ *
1715
+ * @param transaction - The transaction builder to add this operation to
1716
+ */
1717
+ withTransaction(transaction: TransactionBuilder): void;
1718
+ /**
1719
+ * Executes the delete operation against DynamoDB.
1720
+ *
1721
+ * @example
1722
+ * ```ts
1723
+ * // Delete with condition and retrieve old values
1724
+ * const result = await new DeleteBuilder(executor, 'myTable', { id: '123' })
1725
+ * .condition(op => op.eq('status', 'INACTIVE'))
1726
+ * .returnValues('ALL_OLD')
1727
+ * .execute();
1728
+ *
1729
+ * if (result.item) {
1730
+ * console.log('Deleted item:', result.item);
1731
+ * }
1732
+ * ```
1733
+ *
1734
+ * @returns A promise that resolves to an object containing the deleted item's attributes (if returnValues is 'ALL_OLD')
1735
+ */
193
1736
  execute(): Promise<{
194
- Attributes?: Record<string, unknown>;
1737
+ item?: Record<string, unknown>;
195
1738
  }>;
1739
+ /**
1740
+ * Gets a human-readable representation of the delete command
1741
+ * with all expression placeholders replaced by their actual values.
1742
+ * Use this method when you need to:
1743
+ * - Debug complex deletion conditions
1744
+ * - Verify safety checks
1745
+ * - Log removal operations
1746
+ * - Troubleshoot failed deletions
1747
+ *
1748
+ * @example
1749
+ * ```ts
1750
+ * const debugInfo = new DeleteBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
1751
+ * .condition(op => op.and([
1752
+ * op.eq('status', 'SEDATED'),
1753
+ * op.eq('location', 'MEDICAL_BAY'),
1754
+ * op.gt('sedationLevel', 8)
1755
+ * op.eq('version', 1),
1756
+ * op.attributeExists('status')
1757
+ * ]))
1758
+ * .debug();
1759
+ *
1760
+ * console.log('Delete command:', debugInfo);
1761
+ * ```
1762
+ *
1763
+ * @returns A readable representation of the delete command with resolved expressions
1764
+ */
1765
+ debug(): Record<string, unknown>;
196
1766
  }
197
1767
 
198
- declare class Table {
199
- private readonly dynamoService;
200
- private readonly expressionBuilder;
201
- private readonly indexes;
202
- constructor({ client, tableName, tableIndexes, expressionBuilder, }: {
203
- client: DynamoDBDocument;
204
- tableName: string;
205
- tableIndexes: Record<string, TableIndexConfig>;
206
- expressionBuilder?: ExpressionBuilder;
207
- });
208
- getIndexConfig(indexName?: string): TableIndexConfig;
209
- put(item: Record<string, unknown>): PutBuilder;
210
- update(key: PrimaryKeyWithoutExpression, data?: Record<string, unknown>): UpdateBuilder;
211
- query(key: PrimaryKey): QueryBuilder;
212
- get(key: PrimaryKeyWithoutExpression, options?: {
213
- indexName?: string;
214
- }): Promise<Record<string, any> | undefined>;
215
- delete(key: PrimaryKeyWithoutExpression): Promise<unknown>;
216
- scan(filters?: FilterCondition[], options?: {
217
- limit?: number;
218
- pageKey?: Record<string, unknown>;
219
- indexName?: string;
220
- }): Promise<_aws_sdk_lib_dynamodb.ScanCommandOutput>;
221
- batchWrite(operations: BatchWriteOperation[]): Promise<unknown>;
222
- transactWrite(operations: Array<{
223
- put?: {
224
- item: Record<string, unknown>;
225
- condition?: {
226
- expression: string;
227
- names?: Record<string, string>;
228
- values?: Record<string, unknown>;
229
- };
230
- };
231
- delete?: {
232
- key: PrimaryKeyWithoutExpression;
233
- condition?: {
234
- expression: string;
235
- names?: Record<string, string>;
236
- values?: Record<string, unknown>;
237
- };
238
- };
239
- update?: {
240
- key: PrimaryKeyWithoutExpression;
241
- update: {
242
- expression: string;
243
- names?: Record<string, string>;
244
- values?: Record<string, unknown>;
245
- };
246
- condition?: {
247
- expression: string;
248
- names?: Record<string, string>;
249
- values?: Record<string, unknown>;
250
- };
251
- };
252
- }>): Promise<unknown>;
253
- private executeOperation;
254
- private buildKeyFromIndex;
255
- private validateKey;
1768
+ interface ConditionCheckCommandParams extends DynamoCommandWithExpressions {
1769
+ tableName: string;
1770
+ key: PrimaryKeyWithoutExpression;
1771
+ conditionExpression: string;
1772
+ expressionAttributeNames?: Record<string, string>;
1773
+ expressionAttributeValues?: Record<string, unknown>;
256
1774
  }
257
-
258
- type InferZodSchema<T extends z.ZodType> = z.infer<T>;
259
- declare abstract class BaseRepository<TSchema extends z.ZodType> {
260
- protected readonly table: Table;
261
- protected readonly schema: TSchema;
262
- constructor(table: Table, schema: TSchema);
263
- protected abstract createPrimaryKey(data: InferZodSchema<TSchema>): PrimaryKeyWithoutExpression;
264
- protected abstract getIndexKeys(): {
265
- pk: string;
266
- sk?: string;
267
- };
268
- /**
269
- * Default attribute applied to ALL records that get stored in DDB
270
- */
271
- protected abstract getType(): string;
272
- protected abstract getTypeAttributeName(): string;
273
- protected beforeInsert(data: InferZodSchema<TSchema>): InferZodSchema<TSchema>;
274
- protected beforeUpdate(data: InferZodSchema<TSchema>): InferZodSchema<TSchema>;
275
- create(data: InferZodSchema<TSchema>): Promise<InferZodSchema<TSchema>>;
276
- update(key: PrimaryKeyWithoutExpression, updates: Partial<InferZodSchema<TSchema>>): Promise<InferZodSchema<TSchema>>;
277
- delete(key: PrimaryKeyWithoutExpression): Promise<void>;
278
- findOne(key: PrimaryKeyWithoutExpression): Promise<InferZodSchema<TSchema> | null>;
279
- findOrFail(key: PrimaryKeyWithoutExpression): Promise<InferZodSchema<TSchema>>;
280
- protected query(key: PrimaryKeyWithoutExpression): QueryBuilder;
1775
+ /**
1776
+ * Builder for creating DynamoDB condition check operations.
1777
+ * Use this builder when you need to:
1778
+ * - Verify item state without modifying it
1779
+ * - Ensure preconditions in transactions
1780
+ * - Implement optimistic locking patterns
1781
+ * - Validate business rules
1782
+ *
1783
+ * @example
1784
+ * ```typescript
1785
+ * // Check if dinosaur is ready for feeding
1786
+ * const check = new ConditionCheckBuilder('dinosaurs', { id: 'TREX-001' })
1787
+ * .condition(op =>
1788
+ * op.and([
1789
+ * op.eq('status', 'HUNTING'),
1790
+ * op.gt('stats.hunger', 80),
1791
+ * op.lt('stats.health', 100)
1792
+ * ])
1793
+ * )
1794
+ * .toDynamoCommand();
1795
+ *
1796
+ * // Check habitat security status
1797
+ * const securityCheck = new ConditionCheckBuilder('habitats', { id: 'PADDOCK-A' })
1798
+ * .condition(op =>
1799
+ * op.and([
1800
+ * op.eq('securityStatus', 'ACTIVE'),
1801
+ * op.attributeExists('lastInspection'),
1802
+ * op.lt('threatLevel', 5)
1803
+ * ])
1804
+ * )
1805
+ * .toDynamoCommand();
1806
+ * ```
1807
+ */
1808
+ declare class ConditionCheckBuilder {
1809
+ private readonly key;
1810
+ private readonly tableName;
1811
+ private conditionExpression?;
1812
+ constructor(tableName: string, key: PrimaryKeyWithoutExpression);
1813
+ /**
1814
+ * Adds a condition that must be satisfied for the check to succeed.
1815
+ * Use this method when you need to:
1816
+ * - Validate complex item states
1817
+ * - Check multiple attributes together
1818
+ * - Ensure safety conditions are met
1819
+ *
1820
+ * @example
1821
+ * ```typescript
1822
+ * // Check dinosaur health and behavior
1823
+ * builder.condition(op =>
1824
+ * op.and([
1825
+ * op.gt('stats.health', 50),
1826
+ * op.not(op.eq('status', 'SEDATED')),
1827
+ * op.lt('aggressionLevel', 8)
1828
+ * ])
1829
+ * );
1830
+ *
1831
+ * // Verify habitat conditions
1832
+ * builder.condition(op =>
1833
+ * op.and([
1834
+ * op.eq('powerStatus', 'ONLINE'),
1835
+ * op.between('temperature', 20, 30),
1836
+ * op.attributeExists('lastMaintenance')
1837
+ * ])
1838
+ * );
1839
+ *
1840
+ * // Check breeding conditions
1841
+ * builder.condition(op =>
1842
+ * op.and([
1843
+ * op.eq('species', 'VELOCIRAPTOR'),
1844
+ * op.gte('age', 3),
1845
+ * op.eq('geneticPurity', 100)
1846
+ * ])
1847
+ * );
1848
+ * ```
1849
+ *
1850
+ * @param condition - Either a Condition object or a callback function that builds the condition
1851
+ * @returns The builder instance for method chaining
1852
+ */
1853
+ condition<T extends Record<string, unknown>>(condition: Condition | ((op: ConditionOperator<T>) => Condition)): ConditionCheckBuilder;
1854
+ /**
1855
+ * Generates the DynamoDB command parameters for direct execution.
1856
+ * Use this method when you want to:
1857
+ * - Execute the condition check as a standalone operation
1858
+ * - Get the raw DynamoDB command for custom execution
1859
+ * - Inspect the generated command parameters
1860
+ *
1861
+ * @example
1862
+ * ```ts
1863
+ * const command = new ConditionCheckBuilder('myTable', { id: '123' })
1864
+ * .condition(op => op.attributeExists('status'))
1865
+ * .toDynamoCommand();
1866
+ * // Use command with DynamoDB client
1867
+ * ```
1868
+ *
1869
+ * @throws {Error} If no condition has been set
1870
+ * @returns The DynamoDB command parameters
1871
+ */
1872
+ private toDynamoCommand;
1873
+ /**
1874
+ * Adds this condition check operation to a transaction.
1875
+ * Use this method when you need to:
1876
+ * - Verify habitat safety before transfers
1877
+ * - Ensure proper feeding conditions
1878
+ * - Validate security protocols
1879
+ *
1880
+ * @example
1881
+ * ```ts
1882
+ * const transaction = new TransactionBuilder();
1883
+ * new ConditionCheckBuilder('habitats', { id: 'PADDOCK-B' })
1884
+ * .condition(op => op.and([
1885
+ * op.eq('securityStatus', 'ACTIVE'),
1886
+ * op.lt('currentOccupants', 3),
1887
+ * op.eq('habitatType', 'CARNIVORE')
1888
+ * ]))
1889
+ * .withTransaction(transaction);
1890
+ * // Add dinosaur transfer operations
1891
+ * ```
1892
+ *
1893
+ * @param transaction - The transaction builder to add this operation to
1894
+ * @throws {Error} If no condition has been set
1895
+ * @returns The builder instance for method chaining
1896
+ */
1897
+ withTransaction(transaction: TransactionBuilder): ConditionCheckBuilder;
1898
+ /**
1899
+ * Gets a human-readable representation of the condition check command
1900
+ * with all expression placeholders replaced by their actual values.
1901
+ * Use this method when you need to:
1902
+ * - Debug complex condition expressions
1903
+ * - Verify condition parameters
1904
+ * - Log safety checks
1905
+ * - Troubleshoot condition failures
1906
+ *
1907
+ * @example
1908
+ * ```ts
1909
+ * const debugInfo = new ConditionCheckBuilder('dinosaurs', { id: 'TREX-001' })
1910
+ * .condition(op => op.and([
1911
+ * op.between('stats.health', 50, 100),
1912
+ * op.not(op.eq('status', 'SEDATED')),
1913
+ * op.attributeExists('lastFeedingTime')
1914
+ * op.eq('version', 1)
1915
+ * ]))
1916
+ * .debug();
1917
+ * console.log(debugInfo);
1918
+ * ```
1919
+ *
1920
+ * @returns A readable representation of the condition check command with resolved expressions
1921
+ */
1922
+ debug(): Record<string, unknown>;
281
1923
  }
282
1924
 
283
- interface RetryStrategy {
284
- maxAttempts: number;
285
- baseDelay: number;
1925
+ /**
1926
+ * Configuration options for DynamoDB transactions.
1927
+ */
1928
+ interface TransactionOptions {
1929
+ /** Unique identifier for the transaction request (idempotency token) */
1930
+ clientRequestToken?: string;
1931
+ /** Level of consumed capacity details to return */
1932
+ returnConsumedCapacity?: "INDEXES" | "TOTAL" | "NONE";
1933
+ /** Whether to return item collection metrics */
1934
+ returnItemCollectionMetrics?: "SIZE" | "NONE";
1935
+ }
1936
+ /**
1937
+ * Configuration for table indexes used in duplicate detection.
1938
+ * Defines the key structure for checking uniqueness constraints.
1939
+ */
1940
+ interface IndexConfig {
1941
+ /** The partition key attribute name */
1942
+ partitionKey: string;
1943
+ /** Optional sort key attribute name */
1944
+ sortKey?: string;
1945
+ }
1946
+ /**
1947
+ * Function type for executing DynamoDB transaction operations.
1948
+ * @param params - The complete transaction command input
1949
+ * @returns A promise that resolves when the transaction completes
1950
+ */
1951
+ type TransactionExecutor = (params: TransactWriteCommandInput) => Promise<void>;
1952
+ /**
1953
+ * Builder for creating and executing DynamoDB transactions.
1954
+ * Use this builder when you need to:
1955
+ * - Perform multiple operations atomically
1956
+ * - Ensure data consistency across operations
1957
+ * - Implement complex business logic that requires atomic updates
1958
+ * - Prevent duplicate items across tables
1959
+ *
1960
+ * The builder supports:
1961
+ * - Put operations (insert/replace items)
1962
+ * - Delete operations
1963
+ * - Update operations
1964
+ * - Condition checks
1965
+ * - Duplicate detection
1966
+ * - Transaction-wide options
1967
+ *
1968
+ * @example
1969
+ * ```typescript
1970
+ * // Create a transaction with multiple operations
1971
+ * const transaction = new TransactionBuilder(executor, {
1972
+ * partitionKey: 'id',
1973
+ * sortKey: 'type'
1974
+ * });
1975
+ *
1976
+ * // Add a new order
1977
+ * transaction.put('orders', {
1978
+ * orderId: '123',
1979
+ * status: 'PENDING'
1980
+ * });
1981
+ *
1982
+ * // Update inventory with condition
1983
+ * transaction.update(
1984
+ * 'inventory',
1985
+ * { productId: 'ABC' },
1986
+ * 'set quantity = quantity - :amount',
1987
+ * { ':amount': 1 },
1988
+ * op => op.gte('quantity', 1)
1989
+ * );
1990
+ *
1991
+ * // Execute the transaction atomically
1992
+ * await transaction.execute();
1993
+ * ```
1994
+ *
1995
+ * Note: DynamoDB transactions have some limitations:
1996
+ * - Maximum 25 operations per transaction
1997
+ * - All operations must be in the same AWS region
1998
+ * - Cannot include table scans or queries
1999
+ */
2000
+ declare class TransactionBuilder {
2001
+ private items;
2002
+ private options;
2003
+ private indexConfig;
2004
+ private readonly executor;
2005
+ constructor(executor: TransactionExecutor, indexConfig: IndexConfig);
2006
+ /**
2007
+ * Checks if an item with the same primary key already exists in the transaction
2008
+ * @private
2009
+ */
2010
+ private checkForDuplicateItem;
2011
+ /**
2012
+ * Adds a put operation to the transaction.
2013
+ * Use this method when you need to:
2014
+ * - Insert new items as part of a transaction
2015
+ * - Replace existing items atomically
2016
+ * - Ensure items meet certain conditions before insertion
2017
+ *
2018
+ * The method automatically checks for duplicate items within the transaction
2019
+ * to prevent multiple operations on the same item.
2020
+ *
2021
+ * @example
2022
+ * ```typescript
2023
+ * // Simple put operation
2024
+ * transaction.put('orders', {
2025
+ * orderId: '123',
2026
+ * status: 'PENDING',
2027
+ * amount: 100
2028
+ * });
2029
+ *
2030
+ * // Conditional put operation
2031
+ * transaction.put(
2032
+ * 'inventory',
2033
+ * { productId: 'ABC', quantity: 50 },
2034
+ * op => op.attributeNotExists('productId')
2035
+ * );
2036
+ *
2037
+ * // Put with complex condition
2038
+ * transaction.put(
2039
+ * 'users',
2040
+ * { userId: '123', status: 'ACTIVE' },
2041
+ * op => op.and([
2042
+ * op.attributeNotExists('userId'),
2043
+ * op.beginsWith('status', 'ACTIVE')
2044
+ * ])
2045
+ * );
2046
+ * ```
2047
+ *
2048
+ * @param tableName - The name of the DynamoDB table
2049
+ * @param item - The item to put into the table
2050
+ * @param condition - Optional condition that must be satisfied
2051
+ * @returns The transaction builder for method chaining
2052
+ * @throws {Error} If a duplicate item is detected in the transaction
2053
+ */
2054
+ put<T extends Record<string, unknown>>(tableName: string, item: T, condition?: Condition): TransactionBuilder;
2055
+ /**
2056
+ * Adds a pre-configured put operation to the transaction.
2057
+ * Use this method when you need to:
2058
+ * - Reuse put commands from PutBuilder
2059
+ * - Add complex put operations with pre-configured parameters
2060
+ * - Integrate with existing put command configurations
2061
+ *
2062
+ * This method is particularly useful when working with PutBuilder
2063
+ * to maintain consistency in put operations across your application.
2064
+ *
2065
+ * @example
2066
+ * ```typescript
2067
+ * // Create a put command with PutBuilder
2068
+ * const putCommand = new PutBuilder(executor, newItem, 'users')
2069
+ * .condition(op => op.attributeNotExists('userId'))
2070
+ * .toDynamoCommand();
2071
+ *
2072
+ * // Add the command to the transaction
2073
+ * transaction.putWithCommand(putCommand);
2074
+ * ```
2075
+ *
2076
+ * @param command - The complete put command configuration
2077
+ * @returns The transaction builder for method chaining
2078
+ * @throws {Error} If a duplicate item is detected in the transaction
2079
+ * @see PutBuilder for creating put commands
2080
+ */
2081
+ putWithCommand(command: PutCommandParams): TransactionBuilder;
2082
+ /**
2083
+ * Adds a delete operation to the transaction.
2084
+ * Use this method when you need to:
2085
+ * - Remove items as part of a transaction
2086
+ * - Conditionally delete items
2087
+ * - Ensure items exist before deletion
2088
+ *
2089
+ * The method automatically checks for duplicate items within the transaction
2090
+ * to prevent multiple operations on the same item.
2091
+ *
2092
+ * @example
2093
+ * ```typescript
2094
+ * // Simple delete operation
2095
+ * transaction.delete('orders', {
2096
+ * pk: 'ORDER#123',
2097
+ * sk: 'METADATA'
2098
+ * });
2099
+ *
2100
+ * // Conditional delete operation
2101
+ * transaction.delete(
2102
+ * 'users',
2103
+ * { pk: 'USER#123' },
2104
+ * op => op.eq('status', 'INACTIVE')
2105
+ * );
2106
+ *
2107
+ * // Delete with complex condition
2108
+ * transaction.delete(
2109
+ * 'products',
2110
+ * { pk: 'PROD#ABC' },
2111
+ * op => op.and([
2112
+ * op.eq('status', 'DRAFT'),
2113
+ * op.lt('version', 5)
2114
+ * ])
2115
+ * );
2116
+ * ```
2117
+ *
2118
+ * @param tableName - The name of the DynamoDB table
2119
+ * @param key - The primary key of the item to delete
2120
+ * @param condition - Optional condition that must be satisfied
2121
+ * @returns The transaction builder for method chaining
2122
+ * @throws {Error} If a duplicate item is detected in the transaction
2123
+ */
2124
+ delete(tableName: string, key: PrimaryKeyWithoutExpression, condition?: Condition): TransactionBuilder;
2125
+ /**
2126
+ * Adds a pre-configured delete operation to the transaction.
2127
+ * Use this method when you need to:
2128
+ * - Reuse delete commands from DeleteBuilder
2129
+ * - Add complex delete operations with pre-configured parameters
2130
+ * - Integrate with existing delete command configurations
2131
+ *
2132
+ * This method is particularly useful when working with DeleteBuilder
2133
+ * to maintain consistency in delete operations across your application.
2134
+ *
2135
+ * @example
2136
+ * ```typescript
2137
+ * // Create a delete command with DeleteBuilder
2138
+ * const deleteCommand = new DeleteBuilder(executor, 'users', { pk: 'USER#123' })
2139
+ * .condition(op => op.and([
2140
+ * op.attributeExists('pk'),
2141
+ * op.eq('status', 'INACTIVE')
2142
+ * ]))
2143
+ * .toDynamoCommand();
2144
+ *
2145
+ * // Add the command to the transaction
2146
+ * transaction.deleteWithCommand(deleteCommand);
2147
+ * ```
2148
+ *
2149
+ * @param command - The complete delete command configuration
2150
+ * @returns The transaction builder for method chaining
2151
+ * @throws {Error} If a duplicate item is detected in the transaction
2152
+ * @see DeleteBuilder for creating delete commands
2153
+ */
2154
+ deleteWithCommand(command: DeleteCommandParams): TransactionBuilder;
2155
+ /**
2156
+ * Adds an update operation to the transaction.
2157
+ * Use this method when you need to:
2158
+ * - Modify existing items as part of a transaction
2159
+ * - Update multiple attributes atomically
2160
+ * - Apply conditional updates
2161
+ * - Perform complex attribute manipulations
2162
+ *
2163
+ * The method supports all DynamoDB update expressions:
2164
+ * - SET: Modify or add attributes
2165
+ * - REMOVE: Delete attributes
2166
+ * - ADD: Update numbers and sets
2167
+ * - DELETE: Remove elements from a set
2168
+ *
2169
+ * @example
2170
+ * ```typescript
2171
+ * // Simple update
2172
+ * transaction.update(
2173
+ * 'orders',
2174
+ * { pk: 'ORDER#123' },
2175
+ * 'SET #status = :status',
2176
+ * { '#status': 'status' },
2177
+ * { ':status': 'PROCESSING' }
2178
+ * );
2179
+ *
2180
+ * // Complex update with multiple operations
2181
+ * transaction.update(
2182
+ * 'products',
2183
+ * { pk: 'PROD#ABC' },
2184
+ * 'SET #qty = #qty - :amount, #status = :status REMOVE #oldAttr',
2185
+ * { '#qty': 'quantity', '#status': 'status', '#oldAttr': 'deprecated_field' },
2186
+ * { ':amount': 1, ':status': 'LOW_STOCK' }
2187
+ * );
2188
+ *
2189
+ * // Conditional update
2190
+ * transaction.update(
2191
+ * 'users',
2192
+ * { pk: 'USER#123' },
2193
+ * 'SET #lastLogin = :now',
2194
+ * { '#lastLogin': 'lastLoginDate' },
2195
+ * { ':now': new Date().toISOString() },
2196
+ * op => op.attributeExists('pk')
2197
+ * );
2198
+ * ```
2199
+ *
2200
+ * @param tableName - The name of the DynamoDB table
2201
+ * @param key - The primary key of the item to update
2202
+ * @param updateExpression - The update expression (SET, REMOVE, ADD, DELETE)
2203
+ * @param expressionAttributeNames - Map of attribute name placeholders to actual names
2204
+ * @param expressionAttributeValues - Map of value placeholders to actual values
2205
+ * @param condition - Optional condition that must be satisfied
2206
+ * @returns The transaction builder for method chaining
2207
+ * @throws {Error} If a duplicate item is detected in the transaction
2208
+ */
2209
+ update<T extends Record<string, unknown>>(tableName: string, key: PrimaryKeyWithoutExpression, updateExpression: string, expressionAttributeNames?: Record<string, string>, expressionAttributeValues?: Record<string, unknown>, condition?: Condition): TransactionBuilder;
286
2210
  /**
287
- * Check if the error should be retried
288
- * @param error The error that was thrown
289
- * @param attempt The amount of attempts this action has made to run the action
290
- * @returns Whether the action should be retried
2211
+ * Adds a pre-configured update operation to the transaction.
2212
+ * Use this method when you need to:
2213
+ * - Reuse update commands from UpdateBuilder
2214
+ * - Add complex update operations with pre-configured parameters
2215
+ * - Integrate with existing update command configurations
2216
+ *
2217
+ * This method is particularly useful when working with UpdateBuilder
2218
+ * to maintain consistency in update operations across your application.
2219
+ *
2220
+ * @example
2221
+ * ```typescript
2222
+ * // Create an update command with UpdateBuilder
2223
+ * const updateCommand = new UpdateBuilder(executor, 'inventory', { pk: 'PROD#ABC' })
2224
+ * .set('quantity', ':qty')
2225
+ * .set('lastUpdated', ':now')
2226
+ * .values({
2227
+ * ':qty': 100,
2228
+ * ':now': new Date().toISOString()
2229
+ * })
2230
+ * .condition(op => op.gt('quantity', 0))
2231
+ * .toDynamoCommand();
2232
+ *
2233
+ * // Add the command to the transaction
2234
+ * transaction.updateWithCommand(updateCommand);
2235
+ * ```
2236
+ *
2237
+ * @param command - The complete update command configuration
2238
+ * @returns The transaction builder for method chaining
2239
+ * @throws {Error} If a duplicate item is detected in the transaction
2240
+ * @see UpdateBuilder for creating update commands
291
2241
  */
292
- shouldRetry: (error: unknown, attempt: number) => boolean;
2242
+ updateWithCommand(command: UpdateCommandParams): TransactionBuilder;
293
2243
  /**
294
- * Get the delay in milliseconds for the next retry attempt
295
- * @param attempt The amount of attempts this action has made to run the action
296
- * @returns The delay in milliseconds
2244
+ * Adds a condition check operation to the transaction.
2245
+ * Use this method when you need to:
2246
+ * - Validate item state without modifying it
2247
+ * - Ensure data consistency across tables
2248
+ * - Implement complex business rules
2249
+ * - Verify preconditions for other operations
2250
+ *
2251
+ * Condition checks are particularly useful for:
2252
+ * - Implementing optimistic locking
2253
+ * - Ensuring referential integrity
2254
+ * - Validating business rules atomically
2255
+ *
2256
+ * @example
2257
+ * ```typescript
2258
+ * // Check if order is in correct state
2259
+ * transaction.conditionCheck(
2260
+ * 'orders',
2261
+ * { pk: 'ORDER#123' },
2262
+ * op => op.eq('status', 'PENDING')
2263
+ * );
2264
+ *
2265
+ * // Complex condition check
2266
+ * transaction.conditionCheck(
2267
+ * 'inventory',
2268
+ * { pk: 'PROD#ABC' },
2269
+ * op => op.and([
2270
+ * op.gt('quantity', 0),
2271
+ * op.eq('status', 'ACTIVE'),
2272
+ * op.attributeExists('lastRestockDate')
2273
+ * ])
2274
+ * );
2275
+ *
2276
+ * // Check with multiple attributes
2277
+ * transaction.conditionCheck(
2278
+ * 'users',
2279
+ * { pk: 'USER#123' },
2280
+ * op => op.or([
2281
+ * op.eq('status', 'PREMIUM'),
2282
+ * op.gte('credits', 100)
2283
+ * ])
2284
+ * );
2285
+ * ```
2286
+ *
2287
+ * @param tableName - The name of the DynamoDB table
2288
+ * @param key - The primary key of the item to check
2289
+ * @param condition - The condition that must be satisfied
2290
+ * @returns The transaction builder for method chaining
2291
+ * @throws {Error} If a duplicate item is detected in the transaction
2292
+ * @throws {Error} If condition expression generation fails
297
2293
  */
298
- getDelay: (attempt: number) => number;
2294
+ conditionCheck(tableName: string, key: PrimaryKeyWithoutExpression, condition: Condition): TransactionBuilder;
2295
+ /**
2296
+ * Adds a pre-configured condition check operation to the transaction.
2297
+ * Use this method when you need to:
2298
+ * - Reuse condition checks from ConditionCheckBuilder
2299
+ * - Add complex condition checks with pre-configured parameters
2300
+ * - Integrate with existing condition check configurations
2301
+ *
2302
+ * This method is particularly useful when working with ConditionCheckBuilder
2303
+ * to maintain consistency in condition checks across your application.
2304
+ *
2305
+ * @example
2306
+ * ```typescript
2307
+ * // Create a condition check with ConditionCheckBuilder
2308
+ * const checkCommand = new ConditionCheckBuilder('inventory', { pk: 'PROD#ABC' })
2309
+ * .condition(op => op.and([
2310
+ * op.between('quantity', 10, 100),
2311
+ * op.beginsWith('category', 'ELECTRONICS'),
2312
+ * op.attributeExists('lastAuditDate')
2313
+ * ]))
2314
+ * .toDynamoCommand();
2315
+ *
2316
+ * // Add the command to the transaction
2317
+ * transaction.conditionCheckWithCommand(checkCommand);
2318
+ * ```
2319
+ *
2320
+ * @param command - The complete condition check command configuration
2321
+ * @returns The transaction builder for method chaining
2322
+ * @throws {Error} If a duplicate item is detected in the transaction
2323
+ * @see ConditionCheckBuilder for creating condition check commands
2324
+ */
2325
+ conditionCheckWithCommand(command: ConditionCheckCommandParams): TransactionBuilder;
2326
+ /**
2327
+ * Sets options for the transaction execution.
2328
+ * Use this method when you need to:
2329
+ * - Enable idempotent transactions
2330
+ * - Track consumed capacity
2331
+ * - Monitor item collection metrics
2332
+ *
2333
+ * @example
2334
+ * ```typescript
2335
+ * // Enable idempotency and capacity tracking
2336
+ * transaction.withOptions({
2337
+ * clientRequestToken: 'unique-request-id-123',
2338
+ * returnConsumedCapacity: 'TOTAL'
2339
+ * });
2340
+ *
2341
+ * // Track item collection metrics
2342
+ * transaction.withOptions({
2343
+ * returnItemCollectionMetrics: 'SIZE'
2344
+ * });
2345
+ * ```
2346
+ *
2347
+ * Note: ClientRequestToken can be used to make transactions idempotent,
2348
+ * ensuring the same transaction is not executed multiple times.
2349
+ *
2350
+ * @param options - Configuration options for the transaction
2351
+ * @returns The transaction builder for method chaining
2352
+ */
2353
+ withOptions(options: TransactionOptions): TransactionBuilder;
2354
+ /**
2355
+ * Gets a human-readable representation of the transaction items.
2356
+ * Use this method when you need to:
2357
+ * - Debug complex transactions
2358
+ * - Verify operation parameters
2359
+ * - Log transaction details
2360
+ * - Troubleshoot condition expressions
2361
+ *
2362
+ * The method resolves all expression placeholders with their actual values,
2363
+ * making it easier to understand the transaction's operations.
2364
+ *
2365
+ * @example
2366
+ * ```typescript
2367
+ * // Add multiple operations
2368
+ * transaction
2369
+ * .put('orders', { orderId: '123', status: 'PENDING' })
2370
+ * .update('inventory',
2371
+ * { productId: 'ABC' },
2372
+ * 'SET quantity = quantity - :amount',
2373
+ * undefined,
2374
+ * { ':amount': 1 }
2375
+ * );
2376
+ *
2377
+ * // Debug the transaction
2378
+ * const debugInfo = transaction.debug();
2379
+ * console.log('Transaction operations:', debugInfo);
2380
+ * ```
2381
+ *
2382
+ * @returns An array of readable representations of the transaction items
2383
+ */
2384
+ debug(): Record<string, unknown>[];
2385
+ /**
2386
+ * Executes all operations in the transaction atomically.
2387
+ * Use this method when you need to:
2388
+ * - Perform multiple operations atomically
2389
+ * - Ensure all-or-nothing execution
2390
+ * - Maintain data consistency across operations
2391
+ *
2392
+ * The transaction will only succeed if all operations succeed.
2393
+ * If any operation fails, the entire transaction is rolled back.
2394
+ *
2395
+ * @example
2396
+ * ```typescript
2397
+ * try {
2398
+ * // Build and execute transaction
2399
+ * await transaction
2400
+ * .put('orders', newOrder)
2401
+ * .update('inventory',
2402
+ * { productId: 'ABC' },
2403
+ * 'SET quantity = quantity - :qty',
2404
+ * undefined,
2405
+ * { ':qty': 1 }
2406
+ * )
2407
+ * .conditionCheck('products',
2408
+ * { productId: 'ABC' },
2409
+ * op => op.eq('status', 'ACTIVE')
2410
+ * )
2411
+ * .execute();
2412
+ *
2413
+ * console.log('Transaction completed successfully');
2414
+ * } catch (error) {
2415
+ * // Handle transaction failure
2416
+ * console.error('Transaction failed:', error);
2417
+ * }
2418
+ * ```
2419
+ *
2420
+ * @throws {Error} If no transaction items are specified
2421
+ * @throws {Error} If any operation in the transaction fails
2422
+ * @returns A promise that resolves when the transaction completes
2423
+ */
2424
+ execute(): Promise<void>;
299
2425
  }
300
2426
 
301
- declare class ExponentialBackoffStrategy implements RetryStrategy {
302
- maxAttempts: number;
303
- baseDelay: number;
304
- private maxDelay;
305
- private jitter;
306
- constructor(maxAttempts?: number, baseDelay?: number, maxDelay?: number, jitter?: boolean);
307
- shouldRetry(error: unknown, attempt: number): boolean;
308
- getDelay(attempt: number): number;
2427
+ /**
2428
+ * Parameters for the DynamoDB put command.
2429
+ * These parameters are used when executing the operation against DynamoDB.
2430
+ */
2431
+ interface PutCommandParams extends DynamoCommandWithExpressions {
2432
+ tableName: string;
2433
+ item: Record<string, unknown>;
2434
+ conditionExpression?: string;
2435
+ expressionAttributeNames?: Record<string, string>;
2436
+ expressionAttributeValues?: Record<string, unknown>;
2437
+ returnValues?: "ALL_OLD" | "NONE";
2438
+ }
2439
+ type PutExecutor<T extends Record<string, unknown>> = (params: PutCommandParams) => Promise<T>;
2440
+ /**
2441
+ * Builder for creating DynamoDB put operations.
2442
+ * Use this builder when you need to:
2443
+ * - Insert new items into a DynamoDB table
2444
+ * - Replace existing items completely
2445
+ * - Conditionally put items based on their current state
2446
+ * - Put items as part of a transaction
2447
+ *
2448
+ * The builder supports:
2449
+ * - Conditional puts with complex conditions
2450
+ * - Retrieving old item values
2451
+ * - Transaction integration
2452
+ *
2453
+ * @example
2454
+ * ```ts
2455
+ * // Simple put
2456
+ * const result = await new PutBuilder(executor, { id: '123', status: 'ACTIVE' }, 'myTable')
2457
+ * .execute();
2458
+ *
2459
+ * // Conditional put with old value retrieval
2460
+ * const result = await new PutBuilder(executor, newItem, 'myTable')
2461
+ * .condition(op => op.attributeNotExists('id'))
2462
+ * .returnValues('ALL_OLD')
2463
+ * .execute();
2464
+ * ```
2465
+ *
2466
+ * @typeParam T - The type of item being put into the table
2467
+ */
2468
+ /**
2469
+ * Builder for creating DynamoDB put operations.
2470
+ * Use this builder when you need to:
2471
+ * - Add new dinosaurs to the registry
2472
+ * - Create new habitats
2473
+ * - Update dinosaur profiles completely
2474
+ * - Initialize tracking records
2475
+ *
2476
+ * @example
2477
+ * ```typescript
2478
+ * // Add new dinosaur
2479
+ * const result = await new PutBuilder(executor, {
2480
+ * id: 'RAPTOR-001',
2481
+ * species: 'Velociraptor',
2482
+ * status: 'ACTIVE',
2483
+ * stats: {
2484
+ * health: 100,
2485
+ * age: 5,
2486
+ * threatLevel: 8
2487
+ * }
2488
+ * }, 'dinosaurs').execute();
2489
+ *
2490
+ * // Create new habitat with conditions
2491
+ * const result = await new PutBuilder(executor, {
2492
+ * id: 'PADDOCK-C',
2493
+ * type: 'CARNIVORE',
2494
+ * securityLevel: 'MAXIMUM',
2495
+ * capacity: 3,
2496
+ * environmentType: 'TROPICAL'
2497
+ * }, 'habitats')
2498
+ * .condition(op => op.attributeNotExists('id'))
2499
+ * .execute();
2500
+ * ```
2501
+ *
2502
+ * @typeParam T - The type of item being put into the table
2503
+ */
2504
+ declare class PutBuilder<T extends Record<string, unknown>> {
2505
+ private readonly item;
2506
+ private options;
2507
+ private readonly executor;
2508
+ private readonly tableName;
2509
+ constructor(executor: PutExecutor<T>, item: T, tableName: string);
2510
+ /**
2511
+ * Adds a condition that must be satisfied for the put operation to succeed.
2512
+ * Use this method when you need to:
2513
+ * - Prevent overwriting existing items (optimistic locking)
2514
+ * - Ensure items meet certain criteria before replacement
2515
+ * - Implement complex business rules for item updates
2516
+ *
2517
+ * @example
2518
+ * ```ts
2519
+ * // Ensure item doesn't exist (insert only)
2520
+ * builder.condition(op => op.attributeNotExists('id'))
2521
+ *
2522
+ * // Complex condition with version check
2523
+ * builder.condition(op =>
2524
+ * op.and([
2525
+ * op.attributeExists('id'),
2526
+ * op.eq('version', currentVersion),
2527
+ * op.eq('status', 'ACTIVE')
2528
+ * ])
2529
+ * )
2530
+ * ```
2531
+ *
2532
+ * @param condition - Either a Condition object or a callback function that builds the condition
2533
+ * @returns The builder instance for method chaining
2534
+ */
2535
+ /**
2536
+ * Adds a condition that must be satisfied for the put operation to succeed.
2537
+ * Use this method when you need to:
2538
+ * - Prevent duplicate dinosaur entries
2539
+ * - Ensure habitat requirements
2540
+ * - Validate security protocols
2541
+ *
2542
+ * @example
2543
+ * ```typescript
2544
+ * // Ensure unique dinosaur ID
2545
+ * builder.condition(op =>
2546
+ * op.attributeNotExists('id')
2547
+ * );
2548
+ *
2549
+ * // Verify habitat requirements
2550
+ * builder.condition(op =>
2551
+ * op.and([
2552
+ * op.eq('securityStatus', 'READY'),
2553
+ * op.attributeExists('lastInspection'),
2554
+ * op.gt('securityLevel', 5)
2555
+ * ])
2556
+ * );
2557
+ *
2558
+ * // Check breeding facility conditions
2559
+ * builder.condition(op =>
2560
+ * op.and([
2561
+ * op.between('temperature', 25, 30),
2562
+ * op.between('humidity', 60, 80),
2563
+ * op.eq('quarantineStatus', 'CLEAR')
2564
+ * ])
2565
+ * );
2566
+ * ```
2567
+ *
2568
+ * @param condition - Either a Condition object or a callback function that builds the condition
2569
+ * @returns The builder instance for method chaining
2570
+ */
2571
+ condition(condition: Condition | ((op: ConditionOperator<T>) => Condition)): PutBuilder<T>;
2572
+ /**
2573
+ * Sets whether to return the item's previous values (if it existed).
2574
+ * Use this method when you need to:
2575
+ * - Track dinosaur profile updates
2576
+ * - Monitor habitat modifications
2577
+ * - Maintain change history
2578
+ *
2579
+ * @example
2580
+ * ```ts
2581
+ * // Get previous dinosaur state
2582
+ * const result = await builder
2583
+ * .returnValues('ALL_OLD')
2584
+ * .execute();
2585
+ *
2586
+ * if (result) {
2587
+ * console.log('Previous profile:', {
2588
+ * species: result.species,
2589
+ * status: result.status,
2590
+ * stats: {
2591
+ * health: result.stats.health,
2592
+ * threatLevel: result.stats.threatLevel
2593
+ * }
2594
+ * });
2595
+ * }
2596
+ * ```
2597
+ *
2598
+ * @param returnValues - Use 'ALL_OLD' to return previous values, or 'NONE' (default)
2599
+ * @returns The builder instance for method chaining
2600
+ */
2601
+ returnValues(returnValues: "ALL_OLD" | "NONE"): PutBuilder<T>;
2602
+ /**
2603
+ * Generate the DynamoDB command parameters
2604
+ */
2605
+ private toDynamoCommand;
2606
+ /**
2607
+ * Adds this put operation to a transaction.
2608
+ * Use this method when you need to:
2609
+ * - Transfer dinosaurs between habitats
2610
+ * - Initialize new breeding programs
2611
+ * - Update multiple facility records
2612
+ *
2613
+ * @example
2614
+ * ```ts
2615
+ * const transaction = new TransactionBuilder();
2616
+ *
2617
+ * // Add dinosaur to new habitat
2618
+ * new PutBuilder(executor, {
2619
+ * id: 'TREX-002',
2620
+ * location: 'PADDOCK-B',
2621
+ * status: 'ACTIVE',
2622
+ * transferDate: new Date().toISOString()
2623
+ * }, 'dinosaurs')
2624
+ * .withTransaction(transaction);
2625
+ *
2626
+ * // Update habitat records
2627
+ * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-B' })
2628
+ * .add('occupants', 1)
2629
+ * .set('lastTransfer', new Date().toISOString())
2630
+ * .withTransaction(transaction);
2631
+ *
2632
+ * // Execute transfer atomically
2633
+ * await transaction.execute();
2634
+ * ```
2635
+ *
2636
+ * @param transaction - The transaction builder to add this operation to
2637
+ * @returns The builder instance for method chaining
2638
+ */
2639
+ withTransaction(transaction: TransactionBuilder): PutBuilder<T>;
2640
+ /**
2641
+ * Executes the put operation against DynamoDB.
2642
+ *
2643
+ * @example
2644
+ * ```ts
2645
+ * try {
2646
+ * // Put with condition and return old values
2647
+ * const result = await new PutBuilder(executor, newItem, 'myTable')
2648
+ * .condition(op => op.eq('version', 1))
2649
+ * .returnValues('ALL_OLD')
2650
+ * .execute();
2651
+ *
2652
+ * console.log('Put successful, old item:', result);
2653
+ * } catch (error) {
2654
+ * // Handle condition check failure or other errors
2655
+ * console.error('Put failed:', error);
2656
+ * }
2657
+ * ```
2658
+ *
2659
+ * @returns A promise that resolves to the operation result (type depends on returnValues setting)
2660
+ * @throws Will throw an error if the condition check fails or other DynamoDB errors occur
2661
+ */
2662
+ execute(): Promise<T>;
2663
+ /**
2664
+ * Gets a human-readable representation of the put command
2665
+ * with all expression placeholders replaced by their actual values.
2666
+ * Use this method when you need to:
2667
+ * - Debug complex dinosaur transfers
2668
+ * - Verify habitat assignments
2669
+ * - Log security protocols
2670
+ * - Troubleshoot breeding program conditions
2671
+ *
2672
+ * @example
2673
+ * ```ts
2674
+ * const debugInfo = new PutBuilder(executor, {
2675
+ * id: 'RAPTOR-003',
2676
+ * species: 'Velociraptor',
2677
+ * status: 'QUARANTINE',
2678
+ * stats: {
2679
+ * health: 100,
2680
+ * aggressionLevel: 7,
2681
+ * age: 2
2682
+ * }
2683
+ * }, 'dinosaurs')
2684
+ * .condition(op =>
2685
+ * op.and([
2686
+ * op.attributeNotExists('id'),
2687
+ * op.eq('quarantineStatus', 'READY'),
2688
+ * op.gt('securityLevel', 8)
2689
+ * ])
2690
+ * )
2691
+ * .debug();
2692
+ *
2693
+ * console.log('Dinosaur transfer command:', debugInfo);
2694
+ * ```
2695
+ *
2696
+ * @returns A readable representation of the put command with resolved expressions
2697
+ */
2698
+ debug(): Record<string, unknown>;
309
2699
  }
310
2700
 
311
- declare class DynamoError extends Error {
312
- readonly originalError: Error;
313
- readonly context?: Record<string, unknown> | undefined;
314
- constructor(message: string, originalError: Error, context?: Record<string, unknown> | undefined);
2701
+ type BatchWriteOperation<T extends Record<string, unknown>> = {
2702
+ type: "put";
2703
+ item: T;
2704
+ } | {
2705
+ type: "delete";
2706
+ key: PrimaryKeyWithoutExpression;
2707
+ };
2708
+
2709
+ /**
2710
+ * Parameters for the DynamoDB get command.
2711
+ */
2712
+ interface GetCommandParams {
2713
+ /** The name of the DynamoDB table */
2714
+ tableName: string;
2715
+ /** The primary key of the item to get */
2716
+ key: PrimaryKeyWithoutExpression;
2717
+ /** Comma-separated list of attributes to return */
2718
+ projectionExpression?: string;
2719
+ /** Map of expression attribute name placeholders to actual names */
2720
+ expressionAttributeNames?: Record<string, string>;
2721
+ /** Whether to use strongly consistent reads */
2722
+ consistentRead?: boolean;
315
2723
  }
316
- declare class ConditionalCheckFailedError extends DynamoError {
317
- constructor(message: string, originalError: Error, context?: Record<string, unknown>);
2724
+ /**
2725
+ * Function type for executing DynamoDB get operations.
2726
+ * @typeParam T - The type of item being retrieved
2727
+ */
2728
+ type GetExecutor<T extends Record<string, unknown>> = (params: GetCommandParams) => Promise<{
2729
+ item: T | undefined;
2730
+ }>;
2731
+ /**
2732
+ * Builder for creating DynamoDB get operations.
2733
+ * Use this builder when you need to:
2734
+ * - Retrieve a single dinosaur by its primary key
2735
+ * - Project specific dinosaur attributes
2736
+ * - Use consistent reads for critical dinosaur data
2737
+ *
2738
+ * @example
2739
+ * ```typescript
2740
+ * // Simple get
2741
+ * const result = await new GetBuilder(executor, { pk: 'dinosaur#123', sk: 'profile' })
2742
+ * .execute();
2743
+ *
2744
+ * // Get with projection and consistent read
2745
+ * const result = await new GetBuilder(executor, { pk: 'dinosaur#123', sk: 'profile' })
2746
+ * .select(['species', 'name', 'diet'])
2747
+ * .consistentRead()
2748
+ * .execute();
2749
+ * ```
2750
+ *
2751
+ * @typeParam T - The type of item being retrieved
2752
+ */
2753
+ declare class GetBuilder<T extends Record<string, unknown>> {
2754
+ private readonly executor;
2755
+ private readonly params;
2756
+ private options;
2757
+ private selectedFields;
2758
+ /**
2759
+ * Creates a new GetBuilder instance.
2760
+ *
2761
+ * @param executor - Function that executes the get operation
2762
+ * @param key - Primary key of the item to retrieve
2763
+ * @param tableName - Name of the DynamoDB table
2764
+ */
2765
+ constructor(executor: GetExecutor<T>, key: PrimaryKeyWithoutExpression, tableName: string);
2766
+ /**
2767
+ * Specifies which attributes to return in the get results.
2768
+ * Use this method when you need to:
2769
+ * - Reduce data transfer by selecting specific dinosaur attributes
2770
+ * - Optimize response size for dinosaur records
2771
+ * - Focus on relevant dinosaur characteristics only
2772
+ *
2773
+ * @example
2774
+ * ```typescript
2775
+ * // Select single attribute
2776
+ * builder.select('species')
2777
+ *
2778
+ * // Select multiple attributes
2779
+ * builder.select(['id', 'species', 'diet'])
2780
+ *
2781
+ * // Chain multiple select calls
2782
+ * builder
2783
+ * .select('id')
2784
+ * .select(['species', 'diet'])
2785
+ * ```
2786
+ *
2787
+ * @param fields - A single field name or an array of field names to return
2788
+ * @returns The builder instance for method chaining
2789
+ */
2790
+ select(fields: string | string[]): GetBuilder<T>;
2791
+ /**
2792
+ * Sets whether to use strongly consistent reads for the get operation.
2793
+ * Use this method when you need:
2794
+ * - The most up-to-date dinosaur data
2795
+ * - To ensure you're reading the latest dinosaur status
2796
+ * - Critical safety information about dangerous species
2797
+ *
2798
+ * Note: Consistent reads consume twice the throughput
2799
+ *
2800
+ * @example
2801
+ * ```typescript
2802
+ * // Get the latest T-Rex data
2803
+ * const result = await new GetBuilder(executor, { pk: 'dinosaur#123', sk: 'profile' })
2804
+ * .consistentRead()
2805
+ * .execute();
2806
+ * ```
2807
+ *
2808
+ * @param consistentRead - Whether to use consistent reads (defaults to true)
2809
+ * @returns The builder instance for method chaining
2810
+ */
2811
+ consistentRead(consistentRead?: boolean): GetBuilder<T>;
2812
+ /**
2813
+ * Executes the get operation against DynamoDB.
2814
+ *
2815
+ * @example
2816
+ * ```typescript
2817
+ * try {
2818
+ * const result = await new GetBuilder(executor, { pk: 'dinosaur#123', sk: 'profile' })
2819
+ * .select(['species', 'name', 'diet'])
2820
+ * .consistentRead()
2821
+ * .execute();
2822
+ *
2823
+ * if (result.item) {
2824
+ * console.log('Dinosaur found:', result.item);
2825
+ * } else {
2826
+ * console.log('Dinosaur not found');
2827
+ * }
2828
+ * } catch (error) {
2829
+ * console.error('Error getting dinosaur:', error);
2830
+ * }
2831
+ * ```
2832
+ *
2833
+ * @returns A promise that resolves to an object containing:
2834
+ * - item: The retrieved dinosaur or undefined if not found
2835
+ */
2836
+ execute(): Promise<{
2837
+ item: T | undefined;
2838
+ }>;
318
2839
  }
319
- declare class ResourceNotFoundError extends DynamoError {
320
- constructor(message: string, originalError: Error, context?: Record<string, unknown>);
2840
+
2841
+ declare class Table<TConfig extends TableConfig = TableConfig> {
2842
+ private dynamoClient;
2843
+ readonly tableName: string;
2844
+ readonly partitionKey: string;
2845
+ readonly sortKey?: string;
2846
+ readonly gsis: Record<string, Index>;
2847
+ constructor(config: TConfig);
2848
+ /**
2849
+ * Creates a new item in the table, it will fail if the item already exists
2850
+ *
2851
+ * @param item The item to create
2852
+ * @returns A PutBuilder instance for chaining conditions and executing the put operation
2853
+ */
2854
+ create<T extends Record<string, unknown>>(item: T): PutBuilder<T>;
2855
+ get<T extends Record<string, unknown>>(keyCondition: PrimaryKeyWithoutExpression): GetBuilder<T>;
2856
+ /**
2857
+ * Updates an item in the table
2858
+ *
2859
+ * @param item The item to update
2860
+ * @returns A PutBuilder instance for chaining conditions and executing the put operation
2861
+ */
2862
+ put<T extends Record<string, unknown>>(item: T): PutBuilder<T>;
2863
+ /**
2864
+ * Creates a query builder for complex queries
2865
+ * If useIndex is called on the returned QueryBuilder, it will use the GSI configuration
2866
+ */
2867
+ query<T extends Record<string, unknown>>(keyCondition: PrimaryKey): QueryBuilder<T, TConfig>;
2868
+ delete(keyCondition: PrimaryKeyWithoutExpression): DeleteBuilder;
2869
+ /**
2870
+ * Updates an item in the table
2871
+ *
2872
+ * @param keyCondition The primary key of the item to update
2873
+ * @returns An UpdateBuilder instance for chaining update operations and conditions
2874
+ */
2875
+ update<T extends Record<string, unknown>>(keyCondition: PrimaryKeyWithoutExpression): UpdateBuilder<T>;
2876
+ /**
2877
+ * Creates a transaction builder for performing multiple operations atomically
2878
+ */
2879
+ transactionBuilder(): TransactionBuilder;
2880
+ /**
2881
+ * Executes a transaction using a callback function
2882
+ *
2883
+ * @param callback A function that receives a transaction context and performs operations on it
2884
+ * @param options Optional transaction options
2885
+ * @returns A promise that resolves when the transaction is complete
2886
+ */
2887
+ transaction<T>(callback: (tx: TransactionBuilder) => Promise<T>, options?: TransactionOptions): Promise<T>;
2888
+ /**
2889
+ * Creates a condition check operation for use in transactions
2890
+ *
2891
+ * This is useful for when you require a transaction to succeed only when a specific condition is met on a
2892
+ * a record within the database that you are not directly updating.
2893
+ *
2894
+ * For example, you are updating a record and you want to ensure that another record exists and/or has a specific value before proceeding.
2895
+ */
2896
+ conditionCheck(keyCondition: PrimaryKeyWithoutExpression): ConditionCheckBuilder;
2897
+ /**
2898
+ * Performs a batch get operation to retrieve multiple items at once
2899
+ *
2900
+ * @param keys Array of primary keys to retrieve
2901
+ * @returns A promise that resolves to the retrieved items
2902
+ */
2903
+ batchGet<T extends Record<string, unknown>>(keys: Array<PrimaryKeyWithoutExpression>): Promise<{
2904
+ items: T[];
2905
+ unprocessedKeys: PrimaryKeyWithoutExpression[];
2906
+ }>;
2907
+ /**
2908
+ * Performs a batch write operation to put or delete multiple items at once
2909
+ *
2910
+ * @param operations Array of put or delete operations
2911
+ * @returns A promise that resolves to any unprocessed operations
2912
+ */
2913
+ batchWrite<T extends Record<string, unknown>>(operations: Array<BatchWriteOperation<T>>): Promise<{
2914
+ unprocessedItems: Array<BatchWriteOperation<T>>;
2915
+ }>;
321
2916
  }
322
2917
 
323
- export { BaseRepository, ConditionalCheckFailedError, DynamoError, ExponentialBackoffStrategy, type FilterCondition, type FilterOperator, type PrimaryKey, ResourceNotFoundError, type RetryStrategy, Table, type TableIndexConfig };
2918
+ export { type Condition, ConditionCheckBuilder, type ConditionOperator, DeleteBuilder, type EntityConfig, type GSINames, type Index, type PaginationResult, Paginator, PutBuilder, QueryBuilder, Table, type TableConfig, TransactionBuilder, UpdateBuilder, and, attributeExists, attributeNotExists, beginsWith, between, contains, eq, gt, gte, lt, lte, ne, not, or };