dyno-table 0.1.7 → 0.1.8

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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -17
  3. package/dist/builders/condition-check-builder.cjs +394 -0
  4. package/dist/builders/condition-check-builder.cjs.map +1 -0
  5. package/dist/builders/condition-check-builder.js +392 -0
  6. package/dist/builders/condition-check-builder.js.map +1 -0
  7. package/dist/builders/delete-builder.cjs +422 -0
  8. package/dist/builders/delete-builder.cjs.map +1 -0
  9. package/dist/builders/delete-builder.js +420 -0
  10. package/dist/builders/delete-builder.js.map +1 -0
  11. package/dist/builders/paginator.cjs +199 -0
  12. package/dist/builders/paginator.cjs.map +1 -0
  13. package/dist/builders/paginator.js +197 -0
  14. package/dist/builders/paginator.js.map +1 -0
  15. package/dist/builders/put-builder.cjs +468 -0
  16. package/dist/builders/put-builder.cjs.map +1 -0
  17. package/dist/builders/put-builder.js +466 -0
  18. package/dist/builders/put-builder.js.map +1 -0
  19. package/dist/builders/query-builder.cjs +674 -0
  20. package/dist/builders/query-builder.cjs.map +1 -0
  21. package/dist/builders/query-builder.js +672 -0
  22. package/dist/builders/query-builder.js.map +1 -0
  23. package/dist/builders/transaction-builder.cjs +876 -0
  24. package/dist/builders/transaction-builder.cjs.map +1 -0
  25. package/dist/builders/transaction-builder.js +874 -0
  26. package/dist/builders/transaction-builder.js.map +1 -0
  27. package/dist/builders/update-builder.cjs +662 -0
  28. package/dist/builders/update-builder.cjs.map +1 -0
  29. package/dist/builders/update-builder.js +660 -0
  30. package/dist/builders/update-builder.js.map +1 -0
  31. package/dist/conditions.cjs +59 -0
  32. package/dist/conditions.cjs.map +1 -0
  33. package/dist/conditions.js +43 -0
  34. package/dist/conditions.js.map +1 -0
  35. package/dist/entity.cjs +169 -0
  36. package/dist/entity.cjs.map +1 -0
  37. package/dist/entity.js +165 -0
  38. package/dist/entity.js.map +1 -0
  39. package/dist/index.cjs +3333 -0
  40. package/dist/index.d.cts +2971 -0
  41. package/dist/index.d.ts +386 -338
  42. package/dist/index.js +247 -232
  43. package/dist/standard-schema.cjs +4 -0
  44. package/dist/standard-schema.cjs.map +1 -0
  45. package/dist/standard-schema.js +3 -0
  46. package/dist/standard-schema.js.map +1 -0
  47. package/dist/table.cjs +3265 -0
  48. package/dist/table.cjs.map +1 -0
  49. package/dist/table.js +3263 -0
  50. package/dist/table.js.map +1 -0
  51. package/dist/types.cjs +4 -0
  52. package/dist/types.cjs.map +1 -0
  53. package/dist/types.js +3 -0
  54. package/dist/types.js.map +1 -0
  55. package/dist/utils/key-template.cjs +19 -0
  56. package/dist/utils/key-template.cjs.map +1 -0
  57. package/dist/utils/key-template.js +17 -0
  58. package/dist/utils/key-template.js.map +1 -0
  59. package/dist/utils/sort-key-template.cjs +19 -0
  60. package/dist/utils/sort-key-template.cjs.map +1 -0
  61. package/dist/utils/sort-key-template.js +17 -0
  62. package/dist/utils/sort-key-template.js.map +1 -0
  63. package/package.json +24 -26
@@ -0,0 +1,660 @@
1
+ // src/conditions.ts
2
+ var createComparisonCondition = (type) => (attr, value) => ({
3
+ type,
4
+ attr,
5
+ value
6
+ });
7
+ var eq = createComparisonCondition("eq");
8
+ var ne = createComparisonCondition("ne");
9
+ var lt = createComparisonCondition("lt");
10
+ var lte = createComparisonCondition("lte");
11
+ var gt = createComparisonCondition("gt");
12
+ var gte = createComparisonCondition("gte");
13
+ var between = (attr, lower, upper) => ({
14
+ type: "between",
15
+ attr,
16
+ value: [lower, upper]
17
+ });
18
+ var beginsWith = createComparisonCondition("beginsWith");
19
+ var contains = createComparisonCondition("contains");
20
+ var attributeExists = (attr) => ({
21
+ type: "attributeExists",
22
+ attr
23
+ });
24
+ var attributeNotExists = (attr) => ({
25
+ type: "attributeNotExists",
26
+ attr
27
+ });
28
+ var and = (...conditions) => ({
29
+ type: "and",
30
+ conditions
31
+ });
32
+ var or = (...conditions) => ({
33
+ type: "or",
34
+ conditions
35
+ });
36
+ var not = (condition) => ({
37
+ type: "not",
38
+ condition
39
+ });
40
+
41
+ // src/expression.ts
42
+ var generateAttributeName = (params, attr) => {
43
+ for (const [existingName, existingAttr] of Object.entries(params.expressionAttributeNames)) {
44
+ if (existingAttr === attr) {
45
+ return existingName;
46
+ }
47
+ }
48
+ const attrName = `#${Object.keys(params.expressionAttributeNames).length}`;
49
+ params.expressionAttributeNames[attrName] = attr;
50
+ return attrName;
51
+ };
52
+ var generateValueName = (params, value) => {
53
+ const valueName = `:${params.valueCounter.count++}`;
54
+ params.expressionAttributeValues[valueName] = value;
55
+ return valueName;
56
+ };
57
+ var validateCondition = (condition, requiresAttr = true, requiresValue = true) => {
58
+ if (requiresAttr && !condition.attr) {
59
+ throw new Error(`Attribute is required for ${condition.type} condition`);
60
+ }
61
+ if (requiresValue && condition.value === void 0) {
62
+ throw new Error(`Value is required for ${condition.type} condition`);
63
+ }
64
+ };
65
+ var buildComparisonExpression = (condition, operator, params) => {
66
+ validateCondition(condition);
67
+ if (!condition.attr) {
68
+ throw new Error(`Attribute is required for ${condition.type} condition`);
69
+ }
70
+ const attrName = generateAttributeName(params, condition.attr);
71
+ const valueName = generateValueName(params, condition.value);
72
+ return `${attrName} ${operator} ${valueName}`;
73
+ };
74
+ var buildBetweenExpression = (condition, params) => {
75
+ validateCondition(condition);
76
+ if (!condition.attr) {
77
+ throw new Error(`Attribute is required for ${condition.type} condition`);
78
+ }
79
+ if (!Array.isArray(condition.value) || condition.value.length !== 2) {
80
+ throw new Error("Between condition requires an array of two values");
81
+ }
82
+ const attrName = generateAttributeName(params, condition.attr);
83
+ const lowerName = generateValueName(params, condition.value[0]);
84
+ const upperName = generateValueName(params, condition.value[1]);
85
+ return `${attrName} BETWEEN ${lowerName} AND ${upperName}`;
86
+ };
87
+ var buildFunctionExpression = (functionName, condition, params) => {
88
+ validateCondition(condition);
89
+ if (!condition.attr) {
90
+ throw new Error(`Attribute is required for ${condition.type} condition`);
91
+ }
92
+ const attrName = generateAttributeName(params, condition.attr);
93
+ const valueName = generateValueName(params, condition.value);
94
+ return `${functionName}(${attrName}, ${valueName})`;
95
+ };
96
+ var buildAttributeFunction = (functionName, condition, params) => {
97
+ validateCondition(condition, true, false);
98
+ if (!condition.attr) {
99
+ throw new Error(`Attribute is required for ${condition.type} condition`);
100
+ }
101
+ const attrName = generateAttributeName(params, condition.attr);
102
+ return `${functionName}(${attrName})`;
103
+ };
104
+ var buildLogicalExpression = (operator, conditions, params) => {
105
+ if (!conditions || conditions.length === 0) {
106
+ throw new Error(`At least one condition is required for ${operator} expression`);
107
+ }
108
+ const expressions = conditions.map((c) => buildExpression(c, params));
109
+ return `(${expressions.join(` ${operator} `)})`;
110
+ };
111
+ var buildExpression = (condition, params) => {
112
+ if (!condition) return "";
113
+ try {
114
+ const expressionBuilders = {
115
+ eq: () => buildComparisonExpression(condition, "=", params),
116
+ ne: () => buildComparisonExpression(condition, "<>", params),
117
+ lt: () => buildComparisonExpression(condition, "<", params),
118
+ lte: () => buildComparisonExpression(condition, "<=", params),
119
+ gt: () => buildComparisonExpression(condition, ">", params),
120
+ gte: () => buildComparisonExpression(condition, ">=", params),
121
+ between: () => buildBetweenExpression(condition, params),
122
+ beginsWith: () => buildFunctionExpression("begins_with", condition, params),
123
+ contains: () => buildFunctionExpression("contains", condition, params),
124
+ attributeExists: () => buildAttributeFunction("attribute_exists", condition, params),
125
+ attributeNotExists: () => buildAttributeFunction("attribute_not_exists", condition, params),
126
+ and: () => {
127
+ if (!condition.conditions) {
128
+ throw new Error("Conditions array is required for AND operator");
129
+ }
130
+ return buildLogicalExpression("AND", condition.conditions, params);
131
+ },
132
+ or: () => {
133
+ if (!condition.conditions) {
134
+ throw new Error("Conditions array is required for OR operator");
135
+ }
136
+ return buildLogicalExpression("OR", condition.conditions, params);
137
+ },
138
+ not: () => {
139
+ if (!condition.condition) {
140
+ throw new Error("Condition is required for NOT operator");
141
+ }
142
+ return `NOT (${buildExpression(condition.condition, params)})`;
143
+ }
144
+ };
145
+ const builder = expressionBuilders[condition.type];
146
+ if (!builder) {
147
+ throw new Error(`Unknown condition type: ${condition.type}`);
148
+ }
149
+ return builder();
150
+ } catch (error) {
151
+ if (error instanceof Error) {
152
+ console.error(`Error building expression for condition type ${condition.type}:`, error.message);
153
+ } else {
154
+ console.error(`Error building expression for condition type ${condition.type}:`, error);
155
+ }
156
+ throw error;
157
+ }
158
+ };
159
+
160
+ // src/utils/debug-expression.ts
161
+ function debugCommand(command) {
162
+ const result = {};
163
+ function replaceAliases(expressionString) {
164
+ if (!expressionString) {
165
+ return expressionString;
166
+ }
167
+ let replacedString = expressionString;
168
+ for (const alias in command.expressionAttributeNames) {
169
+ const attributeName = command.expressionAttributeNames[alias];
170
+ const regex = new RegExp(alias, "g");
171
+ replacedString = replacedString.replace(regex, attributeName);
172
+ }
173
+ for (const alias in command.expressionAttributeValues) {
174
+ let attributeValue = command.expressionAttributeValues[alias];
175
+ if (attributeValue instanceof Set) {
176
+ const array = Array.from(attributeValue);
177
+ attributeValue = `Set(${array.length}){${array.map((v) => JSON.stringify(v)).join(", ")}}`;
178
+ } else {
179
+ attributeValue = JSON.stringify(attributeValue);
180
+ }
181
+ const regex = new RegExp(alias, "g");
182
+ replacedString = replacedString.replace(regex, attributeValue);
183
+ }
184
+ return replacedString;
185
+ }
186
+ if (command.updateExpression) {
187
+ result.updateExpression = replaceAliases(command.updateExpression);
188
+ }
189
+ if (command.conditionExpression) {
190
+ result.conditionExpression = replaceAliases(command.conditionExpression);
191
+ }
192
+ if (command.filterExpression) {
193
+ result.filterExpression = replaceAliases(command.filterExpression);
194
+ }
195
+ if (command.keyConditionExpression) {
196
+ result.keyConditionExpression = replaceAliases(command.keyConditionExpression);
197
+ }
198
+ if (command.projectionExpression) {
199
+ result.projectionExpression = replaceAliases(command.projectionExpression);
200
+ }
201
+ return {
202
+ raw: command,
203
+ readable: result
204
+ };
205
+ }
206
+
207
+ // src/builders/update-builder.ts
208
+ var UpdateBuilder = class {
209
+ updates = [];
210
+ options = {
211
+ returnValues: "ALL_NEW"
212
+ };
213
+ executor;
214
+ tableName;
215
+ key;
216
+ constructor(executor, tableName, key) {
217
+ this.executor = executor;
218
+ this.tableName = tableName;
219
+ this.key = key;
220
+ }
221
+ set(valuesOrPath, value) {
222
+ if (typeof valuesOrPath === "object") {
223
+ for (const [key, value2] of Object.entries(valuesOrPath)) {
224
+ this.updates.push({
225
+ type: "SET",
226
+ path: key,
227
+ value: value2
228
+ });
229
+ }
230
+ } else {
231
+ this.updates.push({
232
+ type: "SET",
233
+ path: valuesOrPath,
234
+ value
235
+ });
236
+ }
237
+ return this;
238
+ }
239
+ /**
240
+ * Removes an attribute from the item.
241
+ * Use this method when you need to:
242
+ * - Delete attributes completely
243
+ * - Remove nested attributes
244
+ * - Clean up deprecated fields
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * // Remove simple attributes
249
+ * builder
250
+ * .remove('temporaryTag')
251
+ * .remove('previousLocation');
252
+ *
253
+ * // Remove nested attributes
254
+ * builder
255
+ * .remove('metadata.testData')
256
+ * .remove('stats.experimentalMetrics');
257
+ * ```
258
+ *
259
+ * @param path - The path to the attribute to remove
260
+ * @returns The builder instance for method chaining
261
+ */
262
+ remove(path) {
263
+ this.updates.push({
264
+ type: "REMOVE",
265
+ path
266
+ });
267
+ return this;
268
+ }
269
+ /**
270
+ * Adds a value to a number attribute or adds elements to a set.
271
+ * Use this method when you need to:
272
+ * - Increment counters
273
+ * - Add elements to a set atomically
274
+ * - Update numerical statistics
275
+ *
276
+ * @example
277
+ * ```typescript
278
+ * // Increment counters
279
+ * builder
280
+ * .add('escapeAttempts', 1)
281
+ * .add('feedingCount', 1);
282
+ *
283
+ * // Add to sets
284
+ * builder
285
+ * .add('knownBehaviors', new Set(['PACK_HUNTING', 'AMBUSH_TACTICS']))
286
+ * .add('visitedZones', new Set(['ZONE_A', 'ZONE_B']));
287
+ * ```
288
+ *
289
+ * @param path - The path to the attribute to update
290
+ * @param value - The value to add (number or set)
291
+ * @returns The builder instance for method chaining
292
+ */
293
+ add(path, value) {
294
+ this.updates.push({
295
+ type: "ADD",
296
+ path,
297
+ value
298
+ });
299
+ return this;
300
+ }
301
+ /**
302
+ * Removes elements from a set attribute.
303
+ * Use this method when you need to:
304
+ * - Remove specific elements from a set
305
+ * - Update set-based attributes atomically
306
+ * - Maintain set membership
307
+ *
308
+ * @example
309
+ * ```typescript
310
+ * // Remove from sets using arrays
311
+ * builder.deleteElementsFromSet(
312
+ * 'allowedHabitats',
313
+ * ['JUNGLE', 'COASTAL']
314
+ * );
315
+ *
316
+ * // Remove from sets using Set objects
317
+ * builder.deleteElementsFromSet(
318
+ * 'knownBehaviors',
319
+ * new Set(['NOCTURNAL', 'TERRITORIAL'])
320
+ * );
321
+ *
322
+ * // Remove from nested sets
323
+ * builder.deleteElementsFromSet(
324
+ * 'stats.compatibleSpecies',
325
+ * ['VELOCIRAPTOR', 'DILOPHOSAURUS']
326
+ * );
327
+ * ```
328
+ *
329
+ * @param path - The path to the set attribute
330
+ * @param value - Elements to remove (array or Set)
331
+ * @returns The builder instance for method chaining
332
+ */
333
+ deleteElementsFromSet(path, value) {
334
+ let valuesToDelete;
335
+ if (Array.isArray(value)) {
336
+ valuesToDelete = new Set(value);
337
+ } else {
338
+ valuesToDelete = value;
339
+ }
340
+ this.updates.push({
341
+ type: "DELETE",
342
+ path,
343
+ value: valuesToDelete
344
+ });
345
+ return this;
346
+ }
347
+ /**
348
+ * Adds a condition that must be satisfied for the update to succeed.
349
+ * Use this method when you need to:
350
+ * - Implement optimistic locking
351
+ * - Ensure item state before update
352
+ * - Validate business rules
353
+ * - Prevent concurrent modifications
354
+ *
355
+ * @example
356
+ * ```typescript
357
+ * // Simple condition
358
+ * builder.condition(op =>
359
+ * op.eq('status', 'ACTIVE')
360
+ * );
361
+ *
362
+ * // Health check condition
363
+ * builder.condition(op =>
364
+ * op.and([
365
+ * op.gt('health', 50),
366
+ * op.eq('status', 'HUNTING')
367
+ * ])
368
+ * );
369
+ *
370
+ * // Complex security condition
371
+ * builder.condition(op =>
372
+ * op.and([
373
+ * op.attributeExists('securitySystem'),
374
+ * op.eq('containmentStatus', 'SECURE'),
375
+ * op.lt('aggressionLevel', 8)
376
+ * ])
377
+ * );
378
+ *
379
+ * // Version check (optimistic locking)
380
+ * builder.condition(op =>
381
+ * op.eq('version', currentVersion)
382
+ * );
383
+ * ```
384
+ *
385
+ * @param condition - Either a Condition object or a callback function that builds the condition
386
+ * @returns The builder instance for method chaining
387
+ */
388
+ condition(condition) {
389
+ if (typeof condition === "function") {
390
+ const conditionOperator = {
391
+ eq,
392
+ ne,
393
+ lt,
394
+ lte,
395
+ gt,
396
+ gte,
397
+ between,
398
+ beginsWith,
399
+ contains,
400
+ attributeExists,
401
+ attributeNotExists,
402
+ and,
403
+ or,
404
+ not
405
+ };
406
+ this.options.condition = condition(conditionOperator);
407
+ } else {
408
+ this.options.condition = condition;
409
+ }
410
+ return this;
411
+ }
412
+ /**
413
+ * Sets which item attributes to include in the response.
414
+ * Use this method when you need to:
415
+ * - Get the complete updated item
416
+ * - Track changes to specific attributes
417
+ * - Compare old and new values
418
+ * - Monitor attribute modifications
419
+ *
420
+ * Available options:
421
+ * - ALL_NEW: All attributes after the update
422
+ * - UPDATED_NEW: Only updated attributes, new values
423
+ * - ALL_OLD: All attributes before the update
424
+ * - UPDATED_OLD: Only updated attributes, old values
425
+ * - NONE: No attributes returned (default)
426
+ *
427
+ * @example
428
+ * ```typescript
429
+ * // Get complete updated dinosaur
430
+ * const result = await builder
431
+ * .set('status', 'SLEEPING')
432
+ * .returnValues('ALL_NEW')
433
+ * .execute();
434
+ *
435
+ * // Track specific attribute changes
436
+ * const result = await builder
437
+ * .set({
438
+ * 'stats.health': 100,
439
+ * 'stats.energy': 95
440
+ * })
441
+ * .returnValues('UPDATED_OLD')
442
+ * .execute();
443
+ *
444
+ * if (result.item) {
445
+ * console.log('Previous health:', result.item.stats?.health);
446
+ * }
447
+ * ```
448
+ *
449
+ * @param returnValues - Which attributes to return in the response
450
+ * @returns The builder instance for method chaining
451
+ */
452
+ returnValues(returnValues) {
453
+ this.options.returnValues = returnValues;
454
+ return this;
455
+ }
456
+ /**
457
+ * Generate the DynamoDB command parameters
458
+ */
459
+ toDynamoCommand() {
460
+ if (this.updates.length === 0) {
461
+ throw new Error("No update actions specified");
462
+ }
463
+ const expressionParams = {
464
+ expressionAttributeNames: {},
465
+ expressionAttributeValues: {},
466
+ valueCounter: { count: 0 }
467
+ };
468
+ let updateExpression = "";
469
+ const setUpdates = [];
470
+ const removeUpdates = [];
471
+ const addUpdates = [];
472
+ const deleteUpdates = [];
473
+ for (const update of this.updates) {
474
+ switch (update.type) {
475
+ case "SET":
476
+ setUpdates.push(update);
477
+ break;
478
+ case "REMOVE":
479
+ removeUpdates.push(update);
480
+ break;
481
+ case "ADD":
482
+ addUpdates.push(update);
483
+ break;
484
+ case "DELETE":
485
+ deleteUpdates.push(update);
486
+ break;
487
+ }
488
+ }
489
+ if (setUpdates.length > 0) {
490
+ updateExpression += "SET ";
491
+ updateExpression += setUpdates.map((update) => {
492
+ const attrName = generateAttributeName(expressionParams, update.path);
493
+ const valueName = generateValueName(expressionParams, update.value);
494
+ expressionParams.expressionAttributeValues[valueName] = update.value;
495
+ return `${attrName} = ${valueName}`;
496
+ }).join(", ");
497
+ }
498
+ if (removeUpdates.length > 0) {
499
+ if (updateExpression) {
500
+ updateExpression += " ";
501
+ }
502
+ updateExpression += "REMOVE ";
503
+ updateExpression += removeUpdates.map((update) => {
504
+ return generateAttributeName(expressionParams, update.path);
505
+ }).join(", ");
506
+ }
507
+ if (addUpdates.length > 0) {
508
+ if (updateExpression) {
509
+ updateExpression += " ";
510
+ }
511
+ updateExpression += "ADD ";
512
+ updateExpression += addUpdates.map((update) => {
513
+ const attrName = generateAttributeName(expressionParams, update.path);
514
+ const valueName = generateValueName(expressionParams, update.value);
515
+ return `${attrName} ${valueName}`;
516
+ }).join(", ");
517
+ }
518
+ if (deleteUpdates.length > 0) {
519
+ if (updateExpression) {
520
+ updateExpression += " ";
521
+ }
522
+ updateExpression += "DELETE ";
523
+ updateExpression += deleteUpdates.map((update) => {
524
+ const attrName = generateAttributeName(expressionParams, update.path);
525
+ const valueName = generateValueName(expressionParams, update.value);
526
+ return `${attrName} ${valueName}`;
527
+ }).join(", ");
528
+ }
529
+ let conditionExpression;
530
+ if (this.options.condition) {
531
+ conditionExpression = buildExpression(this.options.condition, expressionParams);
532
+ }
533
+ const { expressionAttributeNames, expressionAttributeValues } = expressionParams;
534
+ return {
535
+ tableName: this.tableName,
536
+ key: this.key,
537
+ updateExpression,
538
+ conditionExpression,
539
+ expressionAttributeNames: Object.keys(expressionAttributeNames).length > 0 ? expressionAttributeNames : void 0,
540
+ expressionAttributeValues: Object.keys(expressionAttributeValues).length > 0 ? expressionAttributeValues : void 0,
541
+ returnValues: this.options.returnValues
542
+ };
543
+ }
544
+ /**
545
+ * Adds this update operation to a transaction.
546
+ * Use this method when you need to:
547
+ * - Update items as part of a larger transaction
548
+ * - Ensure multiple updates are atomic
549
+ * - Coordinate updates across multiple items
550
+ *
551
+ * @example
552
+ * ```typescript
553
+ * const transaction = new TransactionBuilder(executor);
554
+ *
555
+ * // Update dinosaur status and habitat occupancy atomically
556
+ * new UpdateBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
557
+ * .set('location', 'PADDOCK_A')
558
+ * .set('status', 'CONTAINED')
559
+ * .withTransaction(transaction);
560
+ *
561
+ * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
562
+ * .add('occupants', 1)
563
+ * .set('lastOccupied', new Date().toISOString())
564
+ * .withTransaction(transaction);
565
+ *
566
+ * // Execute all operations atomically
567
+ * await transaction.execute();
568
+ * ```
569
+ *
570
+ * @param transaction - The transaction builder to add this operation to
571
+ * @returns The builder instance for method chaining
572
+ */
573
+ withTransaction(transaction) {
574
+ const command = this.toDynamoCommand();
575
+ transaction.updateWithCommand(command);
576
+ }
577
+ /**
578
+ * Gets a human-readable representation of the update command.
579
+ * Use this method when you need to:
580
+ * - Debug complex update expressions
581
+ * - Verify attribute names and values
582
+ * - Log update operations
583
+ * - Troubleshoot condition expressions
584
+ *
585
+ * @example
586
+ * ```typescript
587
+ * // Create complex update
588
+ * const builder = new UpdateBuilder(executor, 'dinosaurs', { id: 'RAPTOR-001' })
589
+ * .set({
590
+ * status: 'HUNTING',
591
+ * 'stats.health': 95,
592
+ * 'behavior.lastObserved': new Date().toISOString()
593
+ * })
594
+ * .add('huntingSuccesses', 1)
595
+ * .condition(op => op.gt('health', 50));
596
+ *
597
+ * // Debug the update
598
+ * const debugInfo = builder.debug();
599
+ * console.log('Update operation:', debugInfo);
600
+ * ```
601
+ *
602
+ * @returns A readable representation of the update command with resolved expressions
603
+ */
604
+ debug() {
605
+ const command = this.toDynamoCommand();
606
+ return debugCommand(command);
607
+ }
608
+ /**
609
+ * Executes the update operation against DynamoDB.
610
+ * Use this method when you need to:
611
+ * - Apply updates immediately
612
+ * - Get the updated item values
613
+ * - Handle conditional update failures
614
+ *
615
+ * @example
616
+ * ```typescript
617
+ * try {
618
+ * // Update dinosaur status with conditions
619
+ * const result = await new UpdateBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
620
+ * .set({
621
+ * status: 'FEEDING',
622
+ * lastMeal: new Date().toISOString(),
623
+ * 'stats.hunger': 0
624
+ * })
625
+ * .add('feedingCount', 1)
626
+ * .condition(op =>
627
+ * op.and([
628
+ * op.gt('stats.hunger', 80),
629
+ * op.eq('status', 'HUNTING')
630
+ * ])
631
+ * )
632
+ * .returnValues('ALL_NEW')
633
+ * .execute();
634
+ *
635
+ * if (result.item) {
636
+ * console.log('Updated dinosaur:', result.item);
637
+ * }
638
+ * } catch (error) {
639
+ * // Handle condition check failure
640
+ * console.error('Failed to update dinosaur:', error);
641
+ * // Check if dinosaur wasn't hungry enough
642
+ * if (error.name === 'ConditionalCheckFailedException') {
643
+ * console.log('Dinosaur not ready for feeding');
644
+ * }
645
+ * }
646
+ * ```
647
+ *
648
+ * @returns A promise that resolves to an object containing the updated item (if returnValues is set)
649
+ * @throws {ConditionalCheckFailedException} If the condition check fails
650
+ * @throws {Error} If the update operation fails for other reasons
651
+ */
652
+ async execute() {
653
+ const params = this.toDynamoCommand();
654
+ return this.executor(params);
655
+ }
656
+ };
657
+
658
+ export { UpdateBuilder };
659
+ //# sourceMappingURL=update-builder.js.map
660
+ //# sourceMappingURL=update-builder.js.map