dyno-table 0.1.6 → 0.1.7

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 (3) hide show
  1. package/dist/index.d.ts +1129 -1056
  2. package/dist/index.js +154 -153
  3. package/package.json +22 -15
package/dist/index.d.ts CHANGED
@@ -108,6 +108,26 @@ interface Condition {
108
108
  /** Single condition for the 'not' operator */
109
109
  condition?: Condition;
110
110
  }
111
+ /**
112
+ * Parameters used to build DynamoDB expression strings.
113
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeNames.html Expression Attribute Names}
114
+ * @see {@link https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ExpressionAttributeValues.html Expression Attribute Values}
115
+ */
116
+ interface ExpressionParams {
117
+ /** Map of attribute name placeholders to actual attribute names */
118
+ expressionAttributeNames: Record<string, string>;
119
+ /** Map of value placeholders to actual values */
120
+ expressionAttributeValues: Record<string, unknown>;
121
+ /** Counter for generating unique value placeholders */
122
+ valueCounter: {
123
+ count: number;
124
+ };
125
+ }
126
+ /**
127
+ * Creates a comparison condition builder function for the specified operator.
128
+ * @internal
129
+ */
130
+ declare const createComparisonCondition: (type: ComparisonOperator) => (attr: string, value: unknown) => Condition;
111
131
  /**
112
132
  * Creates an equals (=) condition
113
133
  * @example
@@ -331,6 +351,81 @@ type PrimaryKeyWithoutExpression = {
331
351
  sk?: string;
332
352
  };
333
353
 
354
+ /**
355
+ * Interface for DynamoDB command objects that can contain expressions
356
+ */
357
+ interface DynamoCommandWithExpressions {
358
+ conditionExpression?: string;
359
+ updateExpression?: string;
360
+ filterExpression?: string;
361
+ keyConditionExpression?: string;
362
+ projectionExpression?: string;
363
+ expressionAttributeNames?: Record<string, string>;
364
+ expressionAttributeValues?: Record<string, unknown>;
365
+ [key: string]: unknown;
366
+ }
367
+
368
+ interface DeleteCommandParams extends DynamoCommandWithExpressions {
369
+ tableName: string;
370
+ key: PrimaryKeyWithoutExpression;
371
+ conditionExpression?: string;
372
+ expressionAttributeNames?: Record<string, string>;
373
+ expressionAttributeValues?: Record<string, unknown>;
374
+ returnValues?: "ALL_OLD";
375
+ }
376
+ /**
377
+ * Parameters for the DynamoDB put command.
378
+ * These parameters are used when executing the operation against DynamoDB.
379
+ */
380
+ interface PutCommandParams extends DynamoCommandWithExpressions {
381
+ tableName: string;
382
+ item: Record<string, unknown>;
383
+ conditionExpression?: string;
384
+ expressionAttributeNames?: Record<string, string>;
385
+ expressionAttributeValues?: Record<string, unknown>;
386
+ returnValues?: "ALL_OLD" | "NONE";
387
+ }
388
+ /**
389
+ * Parameters for the DynamoDB update command.
390
+ * These parameters are used when executing the operation against DynamoDB.
391
+ */
392
+ interface UpdateCommandParams extends DynamoCommandWithExpressions {
393
+ /** The name of the DynamoDB table */
394
+ tableName: string;
395
+ /** The primary key of the item to update */
396
+ key: PrimaryKeyWithoutExpression;
397
+ /** The update expression (SET, REMOVE, ADD, DELETE clauses) */
398
+ updateExpression: string;
399
+ /** Optional condition expression that must be satisfied */
400
+ conditionExpression?: string;
401
+ /** Map of expression attribute name placeholders to actual names */
402
+ expressionAttributeNames?: Record<string, string>;
403
+ /** Map of expression attribute value placeholders to actual values */
404
+ expressionAttributeValues?: Record<string, unknown>;
405
+ /** Which item attributes to include in the response */
406
+ returnValues?: "ALL_NEW" | "UPDATED_NEW" | "ALL_OLD" | "UPDATED_OLD" | "NONE";
407
+ }
408
+ interface ConditionCheckCommandParams extends DynamoCommandWithExpressions {
409
+ tableName: string;
410
+ key: PrimaryKeyWithoutExpression;
411
+ conditionExpression: string;
412
+ expressionAttributeNames?: Record<string, string>;
413
+ expressionAttributeValues?: Record<string, unknown>;
414
+ }
415
+ /**
416
+ * Interface for the QueryBuilder class to be used by Paginator
417
+ * without creating a circular dependency.
418
+ */
419
+ interface QueryBuilderInterface<T extends Record<string, unknown>, TConfig extends TableConfig = TableConfig> {
420
+ clone(): QueryBuilderInterface<T, TConfig>;
421
+ limit(limit: number): QueryBuilderInterface<T, TConfig>;
422
+ getLimit(): number | undefined;
423
+ startFrom(lastEvaluatedKey: Record<string, unknown>): QueryBuilderInterface<T, TConfig>;
424
+ execute(): Promise<{
425
+ items: T[];
426
+ lastEvaluatedKey?: Record<string, unknown>;
427
+ }>;
428
+ }
334
429
  /**
335
430
  * Represents the result of a single page query operation.
336
431
  * This interface provides all necessary information about the current page
@@ -346,6 +441,7 @@ interface PaginationResult<T> {
346
441
  /** The current page number (1-indexed) */
347
442
  page: number;
348
443
  }
444
+
349
445
  /**
350
446
  * A utility class for handling DynamoDB pagination.
351
447
  * Use this class when you need to:
@@ -388,7 +484,7 @@ declare class Paginator<T extends Record<string, unknown>, TConfig extends Table
388
484
  private hasMorePages;
389
485
  private totalItemsRetrieved;
390
486
  private readonly overallLimit?;
391
- constructor(queryBuilder: QueryBuilder<T, TConfig>, pageSize: number);
487
+ constructor(queryBuilder: QueryBuilderInterface<T, TConfig>, pageSize: number);
392
488
  /**
393
489
  * Gets the current page number (1-indexed).
394
490
  * Use this method when you need to:
@@ -635,7 +731,7 @@ type QueryExecutor<T extends Record<string, unknown>> = (keyCondition: Condition
635
731
  * @typeParam T - The type of items being queried
636
732
  * @typeParam TConfig - The table configuration type for type-safe GSI selection
637
733
  */
638
- declare class QueryBuilder<T extends Record<string, unknown>, TConfig extends TableConfig = TableConfig> {
734
+ declare class QueryBuilder<T extends Record<string, unknown>, TConfig extends TableConfig = TableConfig> implements QueryBuilderInterface<T, TConfig> {
639
735
  private readonly keyCondition;
640
736
  private options;
641
737
  private selectedFields;
@@ -1125,489 +1221,613 @@ declare class QueryBuilder<T extends Record<string, unknown>, TConfig extends Ta
1125
1221
  }
1126
1222
 
1127
1223
  /**
1128
- * Interface for DynamoDB command objects that can contain expressions
1224
+ * Configuration options for DynamoDB transactions.
1129
1225
  */
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;
1226
+ interface TransactionOptions {
1227
+ /** Unique identifier for the transaction request (idempotency token) */
1228
+ clientRequestToken?: string;
1229
+ /** Level of consumed capacity details to return */
1230
+ returnConsumedCapacity?: "INDEXES" | "TOTAL" | "NONE";
1231
+ /** Whether to return item collection metrics */
1232
+ returnItemCollectionMetrics?: "SIZE" | "NONE";
1139
1233
  }
1140
-
1141
1234
  /**
1142
- * Parameters for the DynamoDB update command.
1143
- * These parameters are used when executing the operation against DynamoDB.
1235
+ * Configuration for table indexes used in duplicate detection.
1236
+ * Defines the key structure for checking uniqueness constraints.
1144
1237
  */
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";
1238
+ interface IndexConfig {
1239
+ /** The partition key attribute name */
1240
+ partitionKey: string;
1241
+ /** Optional sort key attribute name */
1242
+ sortKey?: string;
1160
1243
  }
1161
1244
  /**
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
1245
+ * Function type for executing DynamoDB transaction operations.
1246
+ * @param params - The complete transaction command input
1247
+ * @returns A promise that resolves when the transaction completes
1179
1248
  */
1180
- type PathSetElementType<T, K extends Path<T>> = SetElementType<PathType<T, K>>;
1249
+ type TransactionExecutor = (params: TransactWriteCommandInput) => Promise<void>;
1181
1250
  /**
1182
- * Builder for creating DynamoDB update operations.
1251
+ * Builder for creating and executing DynamoDB transactions.
1183
1252
  * 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
1253
+ * - Perform multiple operations atomically
1254
+ * - Ensure data consistency across operations
1255
+ * - Implement complex business logic that requires atomic updates
1256
+ * - Prevent duplicate items across tables
1189
1257
  *
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
1258
+ * The builder supports:
1259
+ * - Put operations (insert/replace items)
1260
+ * - Delete operations
1261
+ * - Update operations
1262
+ * - Condition checks
1263
+ * - Duplicate detection
1264
+ * - Transaction-wide options
1195
1265
  *
1196
1266
  * @example
1197
1267
  * ```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();
1268
+ * // Create a transaction with multiple operations
1269
+ * const transaction = new TransactionBuilder(executor, {
1270
+ * partitionKey: 'id',
1271
+ * sortKey: 'type'
1272
+ * });
1203
1273
  *
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();
1274
+ * // Add a new order
1275
+ * transaction.put('orders', {
1276
+ * orderId: '123',
1277
+ * status: 'PENDING'
1278
+ * });
1279
+ *
1280
+ * // Update inventory with condition
1281
+ * transaction.update(
1282
+ * 'inventory',
1283
+ * { productId: 'ABC' },
1284
+ * 'set quantity = quantity - :amount',
1285
+ * { ':amount': 1 },
1286
+ * op => op.gte('quantity', 1)
1287
+ * );
1288
+ *
1289
+ * // Execute the transaction atomically
1290
+ * await transaction.execute();
1216
1291
  * ```
1217
1292
  *
1218
- * @typeParam T - The type of item being updated
1293
+ * Note: DynamoDB transactions have some limitations:
1294
+ * - Maximum 25 operations per transaction
1295
+ * - All operations must be in the same AWS region
1296
+ * - Cannot include table scans or queries
1219
1297
  */
1220
- declare class UpdateBuilder<T extends Record<string, unknown>> {
1221
- private updates;
1298
+ declare class TransactionBuilder {
1299
+ private items;
1222
1300
  private options;
1301
+ private indexConfig;
1223
1302
  private readonly executor;
1224
- private readonly tableName;
1225
- private readonly key;
1226
- constructor(executor: UpdateExecutor<T>, tableName: string, key: PrimaryKeyWithoutExpression);
1303
+ constructor(executor: TransactionExecutor, indexConfig: IndexConfig);
1227
1304
  /**
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
- * ```
1305
+ * Checks if an item with the same primary key already exists in the transaction
1306
+ * @private
1244
1307
  */
1245
- set(values: Partial<T>): UpdateBuilder<T>;
1308
+ private checkForDuplicateItem;
1246
1309
  /**
1247
- * Sets a single attribute to a specific value.
1310
+ * Adds a put operation to the transaction.
1248
1311
  * Use this method when you need to:
1249
- * - Update one attribute at a time
1250
- * - Set values with type safety
1251
- * - Update nested attributes
1312
+ * - Insert new items as part of a transaction
1313
+ * - Replace existing items atomically
1314
+ * - Ensure items meet certain conditions before insertion
1315
+ *
1316
+ * The method automatically checks for duplicate items within the transaction
1317
+ * to prevent multiple operations on the same item.
1252
1318
  *
1253
1319
  * @example
1254
1320
  * ```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);
1321
+ * // Simple put operation
1322
+ * transaction.put('orders', {
1323
+ * orderId: '123',
1324
+ * status: 'PENDING',
1325
+ * amount: 100
1326
+ * });
1327
+ *
1328
+ * // Conditional put operation
1329
+ * transaction.put(
1330
+ * 'inventory',
1331
+ * { productId: 'ABC', quantity: 50 },
1332
+ * op => op.attributeNotExists('productId')
1333
+ * );
1334
+ *
1335
+ * // Put with complex condition
1336
+ * transaction.put(
1337
+ * 'users',
1338
+ * { userId: '123', status: 'ACTIVE' },
1339
+ * op => op.and([
1340
+ * op.attributeNotExists('userId'),
1341
+ * op.beginsWith('status', 'ACTIVE')
1342
+ * ])
1343
+ * );
1264
1344
  * ```
1345
+ *
1346
+ * @param tableName - The name of the DynamoDB table
1347
+ * @param item - The item to put into the table
1348
+ * @param condition - Optional condition that must be satisfied
1349
+ * @returns The transaction builder for method chaining
1350
+ * @throws {Error} If a duplicate item is detected in the transaction
1265
1351
  */
1266
- set<K extends Path<T>>(path: K, value: PathType<T, K>): UpdateBuilder<T>;
1352
+ put<T extends Record<string, unknown>>(tableName: string, item: T, condition?: Condition): TransactionBuilder;
1267
1353
  /**
1268
- * Removes an attribute from the item.
1354
+ * Adds a pre-configured put operation to the transaction.
1269
1355
  * Use this method when you need to:
1270
- * - Delete attributes completely
1271
- * - Remove nested attributes
1272
- * - Clean up deprecated fields
1356
+ * - Reuse put commands from PutBuilder
1357
+ * - Add complex put operations with pre-configured parameters
1358
+ * - Integrate with existing put command configurations
1359
+ *
1360
+ * This method is particularly useful when working with PutBuilder
1361
+ * to maintain consistency in put operations across your application.
1273
1362
  *
1274
1363
  * @example
1275
1364
  * ```typescript
1276
- * // Remove simple attributes
1277
- * builder
1278
- * .remove('temporaryTag')
1279
- * .remove('previousLocation');
1365
+ * // Create a put command with PutBuilder
1366
+ * const putCommand = new PutBuilder(executor, newItem, 'users')
1367
+ * .condition(op => op.attributeNotExists('userId'))
1368
+ * .toDynamoCommand();
1280
1369
  *
1281
- * // Remove nested attributes
1282
- * builder
1283
- * .remove('metadata.testData')
1284
- * .remove('stats.experimentalMetrics');
1370
+ * // Add the command to the transaction
1371
+ * transaction.putWithCommand(putCommand);
1285
1372
  * ```
1286
1373
  *
1287
- * @param path - The path to the attribute to remove
1288
- * @returns The builder instance for method chaining
1374
+ * @param command - The complete put command configuration
1375
+ * @returns The transaction builder for method chaining
1376
+ * @throws {Error} If a duplicate item is detected in the transaction
1377
+ * @see PutBuilder for creating put commands
1289
1378
  */
1290
- remove<K extends Path<T>>(path: K): UpdateBuilder<T>;
1379
+ putWithCommand(command: PutCommandParams): TransactionBuilder;
1291
1380
  /**
1292
- * Adds a value to a number attribute or adds elements to a set.
1381
+ * Adds a delete operation to the transaction.
1293
1382
  * Use this method when you need to:
1294
- * - Increment counters
1295
- * - Add elements to a set atomically
1296
- * - Update numerical statistics
1383
+ * - Remove items as part of a transaction
1384
+ * - Conditionally delete items
1385
+ * - Ensure items exist before deletion
1386
+ *
1387
+ * The method automatically checks for duplicate items within the transaction
1388
+ * to prevent multiple operations on the same item.
1297
1389
  *
1298
1390
  * @example
1299
1391
  * ```typescript
1300
- * // Increment counters
1301
- * builder
1302
- * .add('escapeAttempts', 1)
1303
- * .add('feedingCount', 1);
1392
+ * // Simple delete operation
1393
+ * transaction.delete('orders', {
1394
+ * pk: 'ORDER#123',
1395
+ * sk: 'METADATA'
1396
+ * });
1304
1397
  *
1305
- * // Add to sets
1306
- * builder
1307
- * .add('knownBehaviors', new Set(['PACK_HUNTING', 'AMBUSH_TACTICS']))
1308
- * .add('visitedZones', new Set(['ZONE_A', 'ZONE_B']));
1398
+ * // Conditional delete operation
1399
+ * transaction.delete(
1400
+ * 'users',
1401
+ * { pk: 'USER#123' },
1402
+ * op => op.eq('status', 'INACTIVE')
1403
+ * );
1404
+ *
1405
+ * // Delete with complex condition
1406
+ * transaction.delete(
1407
+ * 'products',
1408
+ * { pk: 'PROD#ABC' },
1409
+ * op => op.and([
1410
+ * op.eq('status', 'DRAFT'),
1411
+ * op.lt('version', 5)
1412
+ * ])
1413
+ * );
1309
1414
  * ```
1310
1415
  *
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
1416
+ * @param tableName - The name of the DynamoDB table
1417
+ * @param key - The primary key of the item to delete
1418
+ * @param condition - Optional condition that must be satisfied
1419
+ * @returns The transaction builder for method chaining
1420
+ * @throws {Error} If a duplicate item is detected in the transaction
1314
1421
  */
1315
- add<K extends Path<T>>(path: K, value: PathType<T, K>): UpdateBuilder<T>;
1422
+ delete(tableName: string, key: PrimaryKeyWithoutExpression, condition?: Condition): TransactionBuilder;
1316
1423
  /**
1317
- * Removes elements from a set attribute.
1424
+ * Adds a pre-configured delete operation to the transaction.
1318
1425
  * Use this method when you need to:
1319
- * - Remove specific elements from a set
1320
- * - Update set-based attributes atomically
1321
- * - Maintain set membership
1426
+ * - Reuse delete commands from DeleteBuilder
1427
+ * - Add complex delete operations with pre-configured parameters
1428
+ * - Integrate with existing delete command configurations
1429
+ *
1430
+ * This method is particularly useful when working with DeleteBuilder
1431
+ * to maintain consistency in delete operations across your application.
1322
1432
  *
1323
1433
  * @example
1324
1434
  * ```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
- * );
1435
+ * // Create a delete command with DeleteBuilder
1436
+ * const deleteCommand = new DeleteBuilder(executor, 'users', { pk: 'USER#123' })
1437
+ * .condition(op => op.and([
1438
+ * op.attributeExists('pk'),
1439
+ * op.eq('status', 'INACTIVE')
1440
+ * ]))
1441
+ * .toDynamoCommand();
1336
1442
  *
1337
- * // Remove from nested sets
1338
- * builder.deleteElementsFromSet(
1339
- * 'stats.compatibleSpecies',
1340
- * ['VELOCIRAPTOR', 'DILOPHOSAURUS']
1341
- * );
1443
+ * // Add the command to the transaction
1444
+ * transaction.deleteWithCommand(deleteCommand);
1342
1445
  * ```
1343
1446
  *
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
1447
+ * @param command - The complete delete command configuration
1448
+ * @returns The transaction builder for method chaining
1449
+ * @throws {Error} If a duplicate item is detected in the transaction
1450
+ * @see DeleteBuilder for creating delete commands
1347
1451
  */
1348
- deleteElementsFromSet<K extends Path<T>>(path: K, value: PathSetElementType<T, K>[] | Set<PathSetElementType<T, K>>): UpdateBuilder<T>;
1452
+ deleteWithCommand(command: DeleteCommandParams): TransactionBuilder;
1349
1453
  /**
1350
- * Adds a condition that must be satisfied for the update to succeed.
1454
+ * Adds an update operation to the transaction.
1351
1455
  * 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
1456
+ * - Modify existing items as part of a transaction
1457
+ * - Update multiple attributes atomically
1458
+ * - Apply conditional updates
1459
+ * - Perform complex attribute manipulations
1460
+ *
1461
+ * The method supports all DynamoDB update expressions:
1462
+ * - SET: Modify or add attributes
1463
+ * - REMOVE: Delete attributes
1464
+ * - ADD: Update numbers and sets
1465
+ * - DELETE: Remove elements from a set
1356
1466
  *
1357
1467
  * @example
1358
1468
  * ```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
- * ])
1469
+ * // Simple update
1470
+ * transaction.update(
1471
+ * 'orders',
1472
+ * { pk: 'ORDER#123' },
1473
+ * 'SET #status = :status',
1474
+ * { '#status': 'status' },
1475
+ * { ':status': 'PROCESSING' }
1370
1476
  * );
1371
1477
  *
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
- * ])
1478
+ * // Complex update with multiple operations
1479
+ * transaction.update(
1480
+ * 'products',
1481
+ * { pk: 'PROD#ABC' },
1482
+ * 'SET #qty = #qty - :amount, #status = :status REMOVE #oldAttr',
1483
+ * { '#qty': 'quantity', '#status': 'status', '#oldAttr': 'deprecated_field' },
1484
+ * { ':amount': 1, ':status': 'LOW_STOCK' }
1379
1485
  * );
1380
1486
  *
1381
- * // Version check (optimistic locking)
1382
- * builder.condition(op =>
1383
- * op.eq('version', currentVersion)
1487
+ * // Conditional update
1488
+ * transaction.update(
1489
+ * 'users',
1490
+ * { pk: 'USER#123' },
1491
+ * 'SET #lastLogin = :now',
1492
+ * { '#lastLogin': 'lastLoginDate' },
1493
+ * { ':now': new Date().toISOString() },
1494
+ * op => op.attributeExists('pk')
1384
1495
  * );
1385
1496
  * ```
1386
1497
  *
1387
- * @param condition - Either a Condition object or a callback function that builds the condition
1388
- * @returns The builder instance for method chaining
1498
+ * @param tableName - The name of the DynamoDB table
1499
+ * @param key - The primary key of the item to update
1500
+ * @param updateExpression - The update expression (SET, REMOVE, ADD, DELETE)
1501
+ * @param expressionAttributeNames - Map of attribute name placeholders to actual names
1502
+ * @param expressionAttributeValues - Map of value placeholders to actual values
1503
+ * @param condition - Optional condition that must be satisfied
1504
+ * @returns The transaction builder for method chaining
1505
+ * @throws {Error} If a duplicate item is detected in the transaction
1389
1506
  */
1390
- condition(condition: Condition | ((op: ConditionOperator<T>) => Condition)): UpdateBuilder<T>;
1507
+ update<T extends Record<string, unknown>>(tableName: string, key: PrimaryKeyWithoutExpression, updateExpression: string, expressionAttributeNames?: Record<string, string>, expressionAttributeValues?: Record<string, unknown>, condition?: Condition): TransactionBuilder;
1391
1508
  /**
1392
- * Sets which item attributes to include in the response.
1509
+ * Adds a pre-configured update operation to the transaction.
1393
1510
  * 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
1511
+ * - Reuse update commands from UpdateBuilder
1512
+ * - Add complex update operations with pre-configured parameters
1513
+ * - Integrate with existing update command configurations
1398
1514
  *
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)
1515
+ * This method is particularly useful when working with UpdateBuilder
1516
+ * to maintain consistency in update operations across your application.
1405
1517
  *
1406
1518
  * @example
1407
1519
  * ```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
1520
+ * // Create an update command with UpdateBuilder
1521
+ * const updateCommand = new UpdateBuilder(executor, 'inventory', { pk: 'PROD#ABC' })
1522
+ * .set('quantity', ':qty')
1523
+ * .set('lastUpdated', ':now')
1524
+ * .values({
1525
+ * ':qty': 100,
1526
+ * ':now': new Date().toISOString()
1419
1527
  * })
1420
- * .returnValues('UPDATED_OLD')
1421
- * .execute();
1528
+ * .condition(op => op.gt('quantity', 0))
1529
+ * .toDynamoCommand();
1422
1530
  *
1423
- * if (result.item) {
1424
- * console.log('Previous health:', result.item.stats?.health);
1425
- * }
1531
+ * // Add the command to the transaction
1532
+ * transaction.updateWithCommand(updateCommand);
1426
1533
  * ```
1427
1534
  *
1428
- * @param returnValues - Which attributes to return in the response
1429
- * @returns The builder instance for method chaining
1535
+ * @param command - The complete update command configuration
1536
+ * @returns The transaction builder for method chaining
1537
+ * @throws {Error} If a duplicate item is detected in the transaction
1538
+ * @see UpdateBuilder for creating update commands
1430
1539
  */
1431
- returnValues(returnValues: "ALL_NEW" | "UPDATED_NEW" | "ALL_OLD" | "UPDATED_OLD" | "NONE"): UpdateBuilder<T>;
1540
+ updateWithCommand(command: UpdateCommandParams): TransactionBuilder;
1432
1541
  /**
1433
- * Generate the DynamoDB command parameters
1542
+ * Adds a condition check operation to the transaction.
1543
+ * Use this method when you need to:
1544
+ * - Validate item state without modifying it
1545
+ * - Ensure data consistency across tables
1546
+ * - Implement complex business rules
1547
+ * - Verify preconditions for other operations
1548
+ *
1549
+ * Condition checks are particularly useful for:
1550
+ * - Implementing optimistic locking
1551
+ * - Ensuring referential integrity
1552
+ * - Validating business rules atomically
1553
+ *
1554
+ * @example
1555
+ * ```typescript
1556
+ * // Check if order is in correct state
1557
+ * transaction.conditionCheck(
1558
+ * 'orders',
1559
+ * { pk: 'ORDER#123' },
1560
+ * op => op.eq('status', 'PENDING')
1561
+ * );
1562
+ *
1563
+ * // Complex condition check
1564
+ * transaction.conditionCheck(
1565
+ * 'inventory',
1566
+ * { pk: 'PROD#ABC' },
1567
+ * op => op.and([
1568
+ * op.gt('quantity', 0),
1569
+ * op.eq('status', 'ACTIVE'),
1570
+ * op.attributeExists('lastRestockDate')
1571
+ * ])
1572
+ * );
1573
+ *
1574
+ * // Check with multiple attributes
1575
+ * transaction.conditionCheck(
1576
+ * 'users',
1577
+ * { pk: 'USER#123' },
1578
+ * op => op.or([
1579
+ * op.eq('status', 'PREMIUM'),
1580
+ * op.gte('credits', 100)
1581
+ * ])
1582
+ * );
1583
+ * ```
1584
+ *
1585
+ * @param tableName - The name of the DynamoDB table
1586
+ * @param key - The primary key of the item to check
1587
+ * @param condition - The condition that must be satisfied
1588
+ * @returns The transaction builder for method chaining
1589
+ * @throws {Error} If a duplicate item is detected in the transaction
1590
+ * @throws {Error} If condition expression generation fails
1434
1591
  */
1435
- toDynamoCommand(): UpdateCommandParams;
1592
+ conditionCheck(tableName: string, key: PrimaryKeyWithoutExpression, condition: Condition): TransactionBuilder;
1436
1593
  /**
1437
- * Adds this update operation to a transaction.
1594
+ * Adds a pre-configured condition check operation to the transaction.
1438
1595
  * 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
1596
+ * - Reuse condition checks from ConditionCheckBuilder
1597
+ * - Add complex condition checks with pre-configured parameters
1598
+ * - Integrate with existing condition check configurations
1599
+ *
1600
+ * This method is particularly useful when working with ConditionCheckBuilder
1601
+ * to maintain consistency in condition checks across your application.
1442
1602
  *
1443
1603
  * @example
1444
1604
  * ```typescript
1445
- * const transaction = new TransactionBuilder(executor);
1605
+ * // Create a condition check with ConditionCheckBuilder
1606
+ * const checkCommand = new ConditionCheckBuilder('inventory', { pk: 'PROD#ABC' })
1607
+ * .condition(op => op.and([
1608
+ * op.between('quantity', 10, 100),
1609
+ * op.beginsWith('category', 'ELECTRONICS'),
1610
+ * op.attributeExists('lastAuditDate')
1611
+ * ]))
1612
+ * .toDynamoCommand();
1446
1613
  *
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);
1614
+ * // Add the command to the transaction
1615
+ * transaction.conditionCheckWithCommand(checkCommand);
1616
+ * ```
1452
1617
  *
1453
- * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
1454
- * .add('occupants', 1)
1455
- * .set('lastOccupied', new Date().toISOString())
1456
- * .withTransaction(transaction);
1618
+ * @param command - The complete condition check command configuration
1619
+ * @returns The transaction builder for method chaining
1620
+ * @throws {Error} If a duplicate item is detected in the transaction
1621
+ * @see ConditionCheckBuilder for creating condition check commands
1622
+ */
1623
+ conditionCheckWithCommand(command: ConditionCheckCommandParams): TransactionBuilder;
1624
+ /**
1625
+ * Sets options for the transaction execution.
1626
+ * Use this method when you need to:
1627
+ * - Enable idempotent transactions
1628
+ * - Track consumed capacity
1629
+ * - Monitor item collection metrics
1457
1630
  *
1458
- * // Execute all operations atomically
1459
- * await transaction.execute();
1631
+ * @example
1632
+ * ```typescript
1633
+ * // Enable idempotency and capacity tracking
1634
+ * transaction.withOptions({
1635
+ * clientRequestToken: 'unique-request-id-123',
1636
+ * returnConsumedCapacity: 'TOTAL'
1637
+ * });
1638
+ *
1639
+ * // Track item collection metrics
1640
+ * transaction.withOptions({
1641
+ * returnItemCollectionMetrics: 'SIZE'
1642
+ * });
1460
1643
  * ```
1461
1644
  *
1462
- * @param transaction - The transaction builder to add this operation to
1463
- * @returns The builder instance for method chaining
1645
+ * Note: ClientRequestToken can be used to make transactions idempotent,
1646
+ * ensuring the same transaction is not executed multiple times.
1647
+ *
1648
+ * @param options - Configuration options for the transaction
1649
+ * @returns The transaction builder for method chaining
1464
1650
  */
1465
- withTransaction(transaction: TransactionBuilder): void;
1651
+ withOptions(options: TransactionOptions): TransactionBuilder;
1466
1652
  /**
1467
- * Gets a human-readable representation of the update command.
1653
+ * Gets a human-readable representation of the transaction items.
1468
1654
  * Use this method when you need to:
1469
- * - Debug complex update expressions
1470
- * - Verify attribute names and values
1471
- * - Log update operations
1655
+ * - Debug complex transactions
1656
+ * - Verify operation parameters
1657
+ * - Log transaction details
1472
1658
  * - Troubleshoot condition expressions
1473
1659
  *
1660
+ * The method resolves all expression placeholders with their actual values,
1661
+ * making it easier to understand the transaction's operations.
1662
+ *
1474
1663
  * @example
1475
1664
  * ```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));
1665
+ * // Add multiple operations
1666
+ * transaction
1667
+ * .put('orders', { orderId: '123', status: 'PENDING' })
1668
+ * .update('inventory',
1669
+ * { productId: 'ABC' },
1670
+ * 'SET quantity = quantity - :amount',
1671
+ * undefined,
1672
+ * { ':amount': 1 }
1673
+ * );
1485
1674
  *
1486
- * // Debug the update
1487
- * const debugInfo = builder.debug();
1488
- * console.log('Update operation:', debugInfo);
1675
+ * // Debug the transaction
1676
+ * const debugInfo = transaction.debug();
1677
+ * console.log('Transaction operations:', debugInfo);
1489
1678
  * ```
1490
1679
  *
1491
- * @returns A readable representation of the update command with resolved expressions
1680
+ * @returns An array of readable representations of the transaction items
1492
1681
  */
1493
- debug(): Record<string, unknown>;
1682
+ debug(): Record<string, unknown>[];
1494
1683
  /**
1495
- * Executes the update operation against DynamoDB.
1684
+ * Executes all operations in the transaction atomically.
1496
1685
  * Use this method when you need to:
1497
- * - Apply updates immediately
1498
- * - Get the updated item values
1499
- * - Handle conditional update failures
1686
+ * - Perform multiple operations atomically
1687
+ * - Ensure all-or-nothing execution
1688
+ * - Maintain data consistency across operations
1689
+ *
1690
+ * The transaction will only succeed if all operations succeed.
1691
+ * If any operation fails, the entire transaction is rolled back.
1500
1692
  *
1501
1693
  * @example
1502
1694
  * ```typescript
1503
1695
  * 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
- * ])
1696
+ * // Build and execute transaction
1697
+ * await transaction
1698
+ * .put('orders', newOrder)
1699
+ * .update('inventory',
1700
+ * { productId: 'ABC' },
1701
+ * 'SET quantity = quantity - :qty',
1702
+ * undefined,
1703
+ * { ':qty': 1 }
1704
+ * )
1705
+ * .conditionCheck('products',
1706
+ * { productId: 'ABC' },
1707
+ * op => op.eq('status', 'ACTIVE')
1517
1708
  * )
1518
- * .returnValues('ALL_NEW')
1519
1709
  * .execute();
1520
1710
  *
1521
- * if (result.item) {
1522
- * console.log('Updated dinosaur:', result.item);
1523
- * }
1711
+ * console.log('Transaction completed successfully');
1524
1712
  * } 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
- * }
1713
+ * // Handle transaction failure
1714
+ * console.error('Transaction failed:', error);
1531
1715
  * }
1532
1716
  * ```
1533
1717
  *
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
1718
+ * @throws {Error} If no transaction items are specified
1719
+ * @throws {Error} If any operation in the transaction fails
1720
+ * @returns A promise that resolves when the transaction completes
1537
1721
  */
1538
- execute(): Promise<{
1539
- item?: T;
1540
- }>;
1722
+ execute(): Promise<void>;
1541
1723
  }
1542
1724
 
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";
1725
+ /**
1726
+ * Configuration options for DynamoDB put operations.
1727
+ */
1728
+ interface PutOptions {
1729
+ /** Optional condition that must be satisfied for the put operation to succeed */
1730
+ condition?: Condition;
1731
+ /** Determines whether to return the item's previous state (if it existed) */
1732
+ returnValues?: "ALL_OLD" | "NONE";
1550
1733
  }
1551
- type DeleteExecutor = (params: DeleteCommandParams) => Promise<{
1552
- item?: Record<string, unknown>;
1553
- }>;
1734
+ type PutExecutor<T extends Record<string, unknown>> = (params: PutCommandParams) => Promise<T>;
1554
1735
  /**
1555
- * Builder for creating DynamoDB delete operations.
1736
+ * Builder for creating DynamoDB put operations.
1556
1737
  * Use this builder when you need to:
1557
- * - Remove dinosaurs from the registry
1558
- * - Clean up abandoned habitats
1559
- * - Delete historical tracking data
1560
- * - Remove deprecated classifications
1738
+ * - Add new dinosaurs to the registry
1739
+ * - Create new habitats
1740
+ * - Update dinosaur profiles completely
1741
+ * - Initialize tracking records
1561
1742
  *
1562
1743
  * @example
1563
1744
  * ```typescript
1564
- * // Simple delete
1565
- * const result = await new DeleteBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
1566
- * .execute();
1745
+ * // Add new dinosaur
1746
+ * const result = await new PutBuilder(executor, {
1747
+ * id: 'RAPTOR-001',
1748
+ * species: 'Velociraptor',
1749
+ * status: 'ACTIVE',
1750
+ * stats: {
1751
+ * health: 100,
1752
+ * age: 5,
1753
+ * threatLevel: 8
1754
+ * }
1755
+ * }, 'dinosaurs').execute();
1567
1756
  *
1568
- * // Conditional delete with old value retrieval
1569
- * const result = await new DeleteBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
1570
- * .condition(op =>
1571
- * op.and([
1572
- * op.eq('status', 'DECOMMISSIONED'),
1573
- * op.eq('occupants', 0),
1574
- * op.lt('securityIncidents', 1)
1575
- * ])
1576
- * )
1577
- * .returnValues('ALL_OLD')
1757
+ * // Create new habitat with conditions
1758
+ * const result = await new PutBuilder(executor, {
1759
+ * id: 'PADDOCK-C',
1760
+ * type: 'CARNIVORE',
1761
+ * securityLevel: 'MAXIMUM',
1762
+ * capacity: 3,
1763
+ * environmentType: 'TROPICAL'
1764
+ * }, 'habitats')
1765
+ * .condition(op => op.attributeNotExists('id'))
1578
1766
  * .execute();
1579
1767
  * ```
1768
+ *
1769
+ * @typeParam T - The type of item being put into the table
1580
1770
  */
1581
- declare class DeleteBuilder {
1771
+ declare class PutBuilder<T extends Record<string, unknown>> {
1772
+ private readonly item;
1582
1773
  private options;
1583
1774
  private readonly executor;
1584
1775
  private readonly tableName;
1585
- private readonly key;
1586
- constructor(executor: DeleteExecutor, tableName: string, key: PrimaryKeyWithoutExpression);
1776
+ constructor(executor: PutExecutor<T>, item: T, tableName: string);
1587
1777
  /**
1588
- * Adds a condition that must be satisfied for the delete operation to succeed.
1778
+ * Adds a condition that must be satisfied for the put operation to succeed.
1589
1779
  * Use this method when you need to:
1590
- * - Ensure safe removal conditions
1591
- * - Verify habitat status before deletion
1592
- * - Implement safety protocols
1780
+ * - Prevent overwriting existing items (optimistic locking)
1781
+ * - Ensure items meet certain criteria before replacement
1782
+ * - Implement complex business rules for item updates
1783
+ *
1784
+ * @example
1785
+ * ```ts
1786
+ * // Ensure item doesn't exist (insert only)
1787
+ * builder.condition(op => op.attributeNotExists('id'))
1788
+ *
1789
+ * // Complex condition with version check
1790
+ * builder.condition(op =>
1791
+ * op.and([
1792
+ * op.attributeExists('id'),
1793
+ * op.eq('version', currentVersion),
1794
+ * op.eq('status', 'ACTIVE')
1795
+ * ])
1796
+ * )
1797
+ * ```
1798
+ *
1799
+ * @param condition - Either a Condition object or a callback function that builds the condition
1800
+ * @returns The builder instance for method chaining
1801
+ */
1802
+ /**
1803
+ * Adds a condition that must be satisfied for the put operation to succeed.
1804
+ * Use this method when you need to:
1805
+ * - Prevent duplicate dinosaur entries
1806
+ * - Ensure habitat requirements
1807
+ * - Validate security protocols
1593
1808
  *
1594
1809
  * @example
1595
1810
  * ```typescript
1596
- * // Ensure dinosaur can be safely removed
1811
+ * // Ensure unique dinosaur ID
1812
+ * builder.condition(op =>
1813
+ * op.attributeNotExists('id')
1814
+ * );
1815
+ *
1816
+ * // Verify habitat requirements
1597
1817
  * builder.condition(op =>
1598
1818
  * op.and([
1599
- * op.eq('status', 'SEDATED'),
1600
- * op.eq('location', 'MEDICAL_BAY'),
1601
- * op.attributeExists('lastCheckup')
1819
+ * op.eq('securityStatus', 'READY'),
1820
+ * op.attributeExists('lastInspection'),
1821
+ * op.gt('securityLevel', 5)
1602
1822
  * ])
1603
1823
  * );
1604
1824
  *
1605
- * // Verify habitat is empty
1825
+ * // Check breeding facility conditions
1606
1826
  * builder.condition(op =>
1607
1827
  * op.and([
1608
- * op.eq('occupants', 0),
1609
- * op.eq('maintenanceStatus', 'COMPLETE'),
1610
- * op.not(op.attributeExists('activeAlerts'))
1828
+ * op.between('temperature', 25, 30),
1829
+ * op.between('humidity', 60, 80),
1830
+ * op.eq('quarantineStatus', 'CLEAR')
1611
1831
  * ])
1612
1832
  * );
1613
1833
  * ```
@@ -1615,57 +1835,65 @@ declare class DeleteBuilder {
1615
1835
  * @param condition - Either a Condition object or a callback function that builds the condition
1616
1836
  * @returns The builder instance for method chaining
1617
1837
  */
1618
- condition<T extends Record<string, unknown>>(condition: Condition | ((op: ConditionOperator<T>) => Condition)): DeleteBuilder;
1838
+ condition(condition: Condition | ((op: ConditionOperator<T>) => Condition)): PutBuilder<T>;
1619
1839
  /**
1620
- * Sets whether to return the item's attribute values before deletion.
1840
+ * Sets whether to return the item's previous values (if it existed).
1621
1841
  * Use this method when you need to:
1622
- * - Archive removed dinosaur data
1623
- * - Track habitat decommissioning history
1624
- * - Maintain removal audit logs
1842
+ * - Track dinosaur profile updates
1843
+ * - Monitor habitat modifications
1844
+ * - Maintain change history
1625
1845
  *
1626
1846
  * @example
1627
1847
  * ```ts
1628
- * // Archive dinosaur data before removal
1848
+ * // Get previous dinosaur state
1629
1849
  * const result = await builder
1630
1850
  * .returnValues('ALL_OLD')
1631
1851
  * .execute();
1632
1852
  *
1633
- * if (result.item) {
1634
- * console.log('Removed dinosaur data:', {
1635
- * species: result.item.species,
1636
- * age: result.item.age,
1637
- * lastLocation: result.item.location
1853
+ * if (result) {
1854
+ * console.log('Previous profile:', {
1855
+ * species: result.species,
1856
+ * status: result.status,
1857
+ * stats: {
1858
+ * health: result.stats.health,
1859
+ * threatLevel: result.stats.threatLevel
1860
+ * }
1638
1861
  * });
1639
1862
  * }
1640
1863
  * ```
1641
1864
  *
1642
- * @param returnValues - Use 'ALL_OLD' to return all attributes of the deleted item
1865
+ * @param returnValues - Use 'ALL_OLD' to return previous values, or 'NONE' (default)
1643
1866
  * @returns The builder instance for method chaining
1644
1867
  */
1645
- returnValues(returnValues: "ALL_OLD"): DeleteBuilder;
1868
+ returnValues(returnValues: "ALL_OLD" | "NONE"): PutBuilder<T>;
1646
1869
  /**
1647
1870
  * Generate the DynamoDB command parameters
1648
1871
  */
1649
1872
  private toDynamoCommand;
1650
1873
  /**
1651
- * Adds this delete operation to a transaction.
1874
+ * Adds this put operation to a transaction.
1652
1875
  * Use this method when you need to:
1653
- * - Coordinate dinosaur transfers
1654
- * - Manage habitat decommissioning
1655
- * - Handle species relocations
1876
+ * - Transfer dinosaurs between habitats
1877
+ * - Initialize new breeding programs
1878
+ * - Update multiple facility records
1656
1879
  *
1657
1880
  * @example
1658
1881
  * ```ts
1659
1882
  * const transaction = new TransactionBuilder();
1660
1883
  *
1661
- * // Remove dinosaur from old habitat
1662
- * new DeleteBuilder(executor, 'dinosaurs', { id: 'RAPTOR-001' })
1663
- * .condition(op => op.eq('status', 'SEDATED'))
1884
+ * // Add dinosaur to new habitat
1885
+ * new PutBuilder(executor, {
1886
+ * id: 'TREX-002',
1887
+ * location: 'PADDOCK-B',
1888
+ * status: 'ACTIVE',
1889
+ * transferDate: new Date().toISOString()
1890
+ * }, 'dinosaurs')
1664
1891
  * .withTransaction(transaction);
1665
1892
  *
1666
- * // Update old habitat occupancy
1667
- * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
1668
- * .add('occupants', -1)
1893
+ * // Update habitat records
1894
+ * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-B' })
1895
+ * .add('occupants', 1)
1896
+ * .set('lastTransfer', new Date().toISOString())
1669
1897
  * .withTransaction(transaction);
1670
1898
  *
1671
1899
  * // Execute transfer atomically
@@ -1673,136 +1901,134 @@ declare class DeleteBuilder {
1673
1901
  * ```
1674
1902
  *
1675
1903
  * @param transaction - The transaction builder to add this operation to
1904
+ * @returns The builder instance for method chaining
1676
1905
  */
1677
- withTransaction(transaction: TransactionBuilder): void;
1906
+ withTransaction(transaction: TransactionBuilder): PutBuilder<T>;
1678
1907
  /**
1679
- * Executes the delete operation against DynamoDB.
1908
+ * Executes the put operation against DynamoDB.
1680
1909
  *
1681
1910
  * @example
1682
1911
  * ```ts
1683
- * // Delete with condition and retrieve old values
1684
- * const result = await new DeleteBuilder(executor, 'myTable', { id: '123' })
1685
- * .condition(op => op.eq('status', 'INACTIVE'))
1686
- * .returnValues('ALL_OLD')
1687
- * .execute();
1912
+ * try {
1913
+ * // Put with condition and return old values
1914
+ * const result = await new PutBuilder(executor, newItem, 'myTable')
1915
+ * .condition(op => op.eq('version', 1))
1916
+ * .returnValues('ALL_OLD')
1917
+ * .execute();
1688
1918
  *
1689
- * if (result.item) {
1690
- * console.log('Deleted item:', result.item);
1919
+ * console.log('Put successful, old item:', result);
1920
+ * } catch (error) {
1921
+ * // Handle condition check failure or other errors
1922
+ * console.error('Put failed:', error);
1691
1923
  * }
1692
1924
  * ```
1693
1925
  *
1694
- * @returns A promise that resolves to an object containing the deleted item's attributes (if returnValues is 'ALL_OLD')
1926
+ * @returns A promise that resolves to the operation result (type depends on returnValues setting)
1927
+ * @throws Will throw an error if the condition check fails or other DynamoDB errors occur
1695
1928
  */
1696
- execute(): Promise<{
1697
- item?: Record<string, unknown>;
1698
- }>;
1929
+ execute(): Promise<T>;
1699
1930
  /**
1700
- * Gets a human-readable representation of the delete command
1931
+ * Gets a human-readable representation of the put command
1701
1932
  * with all expression placeholders replaced by their actual values.
1702
1933
  * Use this method when you need to:
1703
- * - Debug complex deletion conditions
1704
- * - Verify safety checks
1705
- * - Log removal operations
1706
- * - Troubleshoot failed deletions
1934
+ * - Debug complex dinosaur transfers
1935
+ * - Verify habitat assignments
1936
+ * - Log security protocols
1937
+ * - Troubleshoot breeding program conditions
1707
1938
  *
1708
1939
  * @example
1709
1940
  * ```ts
1710
- * const debugInfo = new DeleteBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
1711
- * .condition(op => op.and([
1712
- * op.eq('status', 'SEDATED'),
1713
- * op.eq('location', 'MEDICAL_BAY'),
1714
- * op.gt('sedationLevel', 8)
1715
- * op.eq('version', 1),
1716
- * op.attributeExists('status')
1717
- * ]))
1941
+ * const debugInfo = new PutBuilder(executor, {
1942
+ * id: 'RAPTOR-003',
1943
+ * species: 'Velociraptor',
1944
+ * status: 'QUARANTINE',
1945
+ * stats: {
1946
+ * health: 100,
1947
+ * aggressionLevel: 7,
1948
+ * age: 2
1949
+ * }
1950
+ * }, 'dinosaurs')
1951
+ * .condition(op =>
1952
+ * op.and([
1953
+ * op.attributeNotExists('id'),
1954
+ * op.eq('quarantineStatus', 'READY'),
1955
+ * op.gt('securityLevel', 8)
1956
+ * ])
1957
+ * )
1718
1958
  * .debug();
1719
1959
  *
1720
- * console.log('Delete command:', debugInfo);
1960
+ * console.log('Dinosaur transfer command:', debugInfo);
1721
1961
  * ```
1722
1962
  *
1723
- * @returns A readable representation of the delete command with resolved expressions
1963
+ * @returns A readable representation of the put command with resolved expressions
1724
1964
  */
1725
1965
  debug(): Record<string, unknown>;
1726
1966
  }
1727
1967
 
1728
- interface ConditionCheckCommandParams extends DynamoCommandWithExpressions {
1729
- tableName: string;
1730
- key: PrimaryKeyWithoutExpression;
1731
- conditionExpression: string;
1732
- expressionAttributeNames?: Record<string, string>;
1733
- expressionAttributeValues?: Record<string, unknown>;
1968
+ interface DeleteOptions {
1969
+ condition?: Condition;
1970
+ returnValues?: "ALL_OLD";
1734
1971
  }
1972
+ type DeleteExecutor = (params: DeleteCommandParams) => Promise<{
1973
+ item?: Record<string, unknown>;
1974
+ }>;
1735
1975
  /**
1736
- * Builder for creating DynamoDB condition check operations.
1976
+ * Builder for creating DynamoDB delete operations.
1737
1977
  * Use this builder when you need to:
1738
- * - Verify item state without modifying it
1739
- * - Ensure preconditions in transactions
1740
- * - Implement optimistic locking patterns
1741
- * - Validate business rules
1978
+ * - Remove dinosaurs from the registry
1979
+ * - Clean up abandoned habitats
1980
+ * - Delete historical tracking data
1981
+ * - Remove deprecated classifications
1742
1982
  *
1743
1983
  * @example
1744
1984
  * ```typescript
1745
- * // Check if dinosaur is ready for feeding
1746
- * const check = new ConditionCheckBuilder('dinosaurs', { id: 'TREX-001' })
1747
- * .condition(op =>
1748
- * op.and([
1749
- * op.eq('status', 'HUNTING'),
1750
- * op.gt('stats.hunger', 80),
1751
- * op.lt('stats.health', 100)
1752
- * ])
1753
- * )
1754
- * .toDynamoCommand();
1985
+ * // Simple delete
1986
+ * const result = await new DeleteBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
1987
+ * .execute();
1755
1988
  *
1756
- * // Check habitat security status
1757
- * const securityCheck = new ConditionCheckBuilder('habitats', { id: 'PADDOCK-A' })
1989
+ * // Conditional delete with old value retrieval
1990
+ * const result = await new DeleteBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
1758
1991
  * .condition(op =>
1759
1992
  * op.and([
1760
- * op.eq('securityStatus', 'ACTIVE'),
1761
- * op.attributeExists('lastInspection'),
1762
- * op.lt('threatLevel', 5)
1993
+ * op.eq('status', 'DECOMMISSIONED'),
1994
+ * op.eq('occupants', 0),
1995
+ * op.lt('securityIncidents', 1)
1763
1996
  * ])
1764
1997
  * )
1765
- * .toDynamoCommand();
1998
+ * .returnValues('ALL_OLD')
1999
+ * .execute();
1766
2000
  * ```
1767
2001
  */
1768
- declare class ConditionCheckBuilder {
1769
- private readonly key;
2002
+ declare class DeleteBuilder {
2003
+ private options;
2004
+ private readonly executor;
1770
2005
  private readonly tableName;
1771
- private conditionExpression?;
1772
- constructor(tableName: string, key: PrimaryKeyWithoutExpression);
2006
+ private readonly key;
2007
+ constructor(executor: DeleteExecutor, tableName: string, key: PrimaryKeyWithoutExpression);
1773
2008
  /**
1774
- * Adds a condition that must be satisfied for the check to succeed.
2009
+ * Adds a condition that must be satisfied for the delete operation to succeed.
1775
2010
  * Use this method when you need to:
1776
- * - Validate complex item states
1777
- * - Check multiple attributes together
1778
- * - Ensure safety conditions are met
2011
+ * - Ensure safe removal conditions
2012
+ * - Verify habitat status before deletion
2013
+ * - Implement safety protocols
1779
2014
  *
1780
2015
  * @example
1781
2016
  * ```typescript
1782
- * // Check dinosaur health and behavior
1783
- * builder.condition(op =>
1784
- * op.and([
1785
- * op.gt('stats.health', 50),
1786
- * op.not(op.eq('status', 'SEDATED')),
1787
- * op.lt('aggressionLevel', 8)
1788
- * ])
1789
- * );
1790
- *
1791
- * // Verify habitat conditions
2017
+ * // Ensure dinosaur can be safely removed
1792
2018
  * builder.condition(op =>
1793
2019
  * op.and([
1794
- * op.eq('powerStatus', 'ONLINE'),
1795
- * op.between('temperature', 20, 30),
1796
- * op.attributeExists('lastMaintenance')
2020
+ * op.eq('status', 'SEDATED'),
2021
+ * op.eq('location', 'MEDICAL_BAY'),
2022
+ * op.attributeExists('lastCheckup')
1797
2023
  * ])
1798
2024
  * );
1799
2025
  *
1800
- * // Check breeding conditions
2026
+ * // Verify habitat is empty
1801
2027
  * builder.condition(op =>
1802
2028
  * op.and([
1803
- * op.eq('species', 'VELOCIRAPTOR'),
1804
- * op.gte('age', 3),
1805
- * op.eq('geneticPurity', 100)
2029
+ * op.eq('occupants', 0),
2030
+ * op.eq('maintenanceStatus', 'COMPLETE'),
2031
+ * op.not(op.attributeExists('activeAlerts'))
1806
2032
  * ])
1807
2033
  * );
1808
2034
  * ```
@@ -1810,689 +2036,602 @@ declare class ConditionCheckBuilder {
1810
2036
  * @param condition - Either a Condition object or a callback function that builds the condition
1811
2037
  * @returns The builder instance for method chaining
1812
2038
  */
1813
- condition<T extends Record<string, unknown>>(condition: Condition | ((op: ConditionOperator<T>) => Condition)): ConditionCheckBuilder;
2039
+ condition<T extends Record<string, unknown>>(condition: Condition | ((op: ConditionOperator<T>) => Condition)): DeleteBuilder;
1814
2040
  /**
1815
- * Generates the DynamoDB command parameters for direct execution.
1816
- * Use this method when you want to:
1817
- * - Execute the condition check as a standalone operation
1818
- * - Get the raw DynamoDB command for custom execution
1819
- * - Inspect the generated command parameters
2041
+ * Sets whether to return the item's attribute values before deletion.
2042
+ * Use this method when you need to:
2043
+ * - Archive removed dinosaur data
2044
+ * - Track habitat decommissioning history
2045
+ * - Maintain removal audit logs
1820
2046
  *
1821
2047
  * @example
1822
2048
  * ```ts
1823
- * const command = new ConditionCheckBuilder('myTable', { id: '123' })
1824
- * .condition(op => op.attributeExists('status'))
1825
- * .toDynamoCommand();
1826
- * // Use command with DynamoDB client
2049
+ * // Archive dinosaur data before removal
2050
+ * const result = await builder
2051
+ * .returnValues('ALL_OLD')
2052
+ * .execute();
2053
+ *
2054
+ * if (result.item) {
2055
+ * console.log('Removed dinosaur data:', {
2056
+ * species: result.item.species,
2057
+ * age: result.item.age,
2058
+ * lastLocation: result.item.location
2059
+ * });
2060
+ * }
1827
2061
  * ```
1828
2062
  *
1829
- * @throws {Error} If no condition has been set
1830
- * @returns The DynamoDB command parameters
2063
+ * @param returnValues - Use 'ALL_OLD' to return all attributes of the deleted item
2064
+ * @returns The builder instance for method chaining
2065
+ */
2066
+ returnValues(returnValues: "ALL_OLD"): DeleteBuilder;
2067
+ /**
2068
+ * Generate the DynamoDB command parameters
1831
2069
  */
1832
2070
  private toDynamoCommand;
1833
2071
  /**
1834
- * Adds this condition check operation to a transaction.
2072
+ * Adds this delete operation to a transaction.
1835
2073
  * Use this method when you need to:
1836
- * - Verify habitat safety before transfers
1837
- * - Ensure proper feeding conditions
1838
- * - Validate security protocols
2074
+ * - Coordinate dinosaur transfers
2075
+ * - Manage habitat decommissioning
2076
+ * - Handle species relocations
1839
2077
  *
1840
2078
  * @example
1841
2079
  * ```ts
1842
2080
  * const transaction = new TransactionBuilder();
1843
- * new ConditionCheckBuilder('habitats', { id: 'PADDOCK-B' })
1844
- * .condition(op => op.and([
1845
- * op.eq('securityStatus', 'ACTIVE'),
1846
- * op.lt('currentOccupants', 3),
1847
- * op.eq('habitatType', 'CARNIVORE')
1848
- * ]))
2081
+ *
2082
+ * // Remove dinosaur from old habitat
2083
+ * new DeleteBuilder(executor, 'dinosaurs', { id: 'RAPTOR-001' })
2084
+ * .condition(op => op.eq('status', 'SEDATED'))
1849
2085
  * .withTransaction(transaction);
1850
- * // Add dinosaur transfer operations
2086
+ *
2087
+ * // Update old habitat occupancy
2088
+ * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
2089
+ * .add('occupants', -1)
2090
+ * .withTransaction(transaction);
2091
+ *
2092
+ * // Execute transfer atomically
2093
+ * await transaction.execute();
1851
2094
  * ```
1852
2095
  *
1853
2096
  * @param transaction - The transaction builder to add this operation to
1854
- * @throws {Error} If no condition has been set
1855
- * @returns The builder instance for method chaining
1856
2097
  */
1857
- withTransaction(transaction: TransactionBuilder): ConditionCheckBuilder;
2098
+ withTransaction(transaction: TransactionBuilder): void;
1858
2099
  /**
1859
- * Gets a human-readable representation of the condition check command
2100
+ * Executes the delete operation against DynamoDB.
2101
+ *
2102
+ * @example
2103
+ * ```ts
2104
+ * // Delete with condition and retrieve old values
2105
+ * const result = await new DeleteBuilder(executor, 'myTable', { id: '123' })
2106
+ * .condition(op => op.eq('status', 'INACTIVE'))
2107
+ * .returnValues('ALL_OLD')
2108
+ * .execute();
2109
+ *
2110
+ * if (result.item) {
2111
+ * console.log('Deleted item:', result.item);
2112
+ * }
2113
+ * ```
2114
+ *
2115
+ * @returns A promise that resolves to an object containing the deleted item's attributes (if returnValues is 'ALL_OLD')
2116
+ */
2117
+ execute(): Promise<{
2118
+ item?: Record<string, unknown>;
2119
+ }>;
2120
+ /**
2121
+ * Gets a human-readable representation of the delete command
1860
2122
  * with all expression placeholders replaced by their actual values.
1861
2123
  * Use this method when you need to:
1862
- * - Debug complex condition expressions
1863
- * - Verify condition parameters
1864
- * - Log safety checks
1865
- * - Troubleshoot condition failures
2124
+ * - Debug complex deletion conditions
2125
+ * - Verify safety checks
2126
+ * - Log removal operations
2127
+ * - Troubleshoot failed deletions
1866
2128
  *
1867
2129
  * @example
1868
2130
  * ```ts
1869
- * const debugInfo = new ConditionCheckBuilder('dinosaurs', { id: 'TREX-001' })
2131
+ * const debugInfo = new DeleteBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
1870
2132
  * .condition(op => op.and([
1871
- * op.between('stats.health', 50, 100),
1872
- * op.not(op.eq('status', 'SEDATED')),
1873
- * op.attributeExists('lastFeedingTime')
1874
- * op.eq('version', 1)
2133
+ * op.eq('status', 'SEDATED'),
2134
+ * op.eq('location', 'MEDICAL_BAY'),
2135
+ * op.gt('sedationLevel', 8)
2136
+ * op.eq('version', 1),
2137
+ * op.attributeExists('status')
1875
2138
  * ]))
1876
2139
  * .debug();
1877
- * console.log(debugInfo);
2140
+ *
2141
+ * console.log('Delete command:', debugInfo);
1878
2142
  * ```
1879
2143
  *
1880
- * @returns A readable representation of the condition check command with resolved expressions
2144
+ * @returns A readable representation of the delete command with resolved expressions
1881
2145
  */
1882
2146
  debug(): Record<string, unknown>;
1883
2147
  }
1884
2148
 
1885
2149
  /**
1886
- * Configuration options for DynamoDB transactions.
2150
+ * Configuration options for DynamoDB update operations.
1887
2151
  */
1888
- interface TransactionOptions {
1889
- /** Unique identifier for the transaction request (idempotency token) */
1890
- clientRequestToken?: string;
1891
- /** Level of consumed capacity details to return */
1892
- returnConsumedCapacity?: "INDEXES" | "TOTAL" | "NONE";
1893
- /** Whether to return item collection metrics */
1894
- returnItemCollectionMetrics?: "SIZE" | "NONE";
2152
+ interface UpdateOptions {
2153
+ /** Optional condition that must be satisfied for the update to succeed */
2154
+ condition?: Condition;
2155
+ /** Determines which item attributes to include in the response */
2156
+ returnValues?: "ALL_NEW" | "UPDATED_NEW" | "ALL_OLD" | "UPDATED_OLD" | "NONE";
1895
2157
  }
1896
2158
  /**
1897
- * Configuration for table indexes used in duplicate detection.
1898
- * Defines the key structure for checking uniqueness constraints.
2159
+ * Function type for executing DynamoDB update operations.
2160
+ * @typeParam T - The type of the item being updated
1899
2161
  */
1900
- interface IndexConfig {
1901
- /** The partition key attribute name */
1902
- partitionKey: string;
1903
- /** Optional sort key attribute name */
1904
- sortKey?: string;
1905
- }
2162
+ type UpdateExecutor<T extends Record<string, unknown>> = (params: UpdateCommandParams) => Promise<{
2163
+ item?: T;
2164
+ }>;
1906
2165
  /**
1907
- * Function type for executing DynamoDB transaction operations.
1908
- * @param params - The complete transaction command input
1909
- * @returns A promise that resolves when the transaction completes
2166
+ * Represents a single update action within an update operation.
2167
+ * Each action modifies the item in a specific way:
2168
+ * - SET: Modify or add attributes
2169
+ * - REMOVE: Delete attributes
2170
+ * - ADD: Update numbers and sets
2171
+ * - DELETE: Remove elements from a set
1910
2172
  */
1911
- type TransactionExecutor = (params: TransactWriteCommandInput) => Promise<void>;
2173
+ type UpdateAction = {
2174
+ /** The type of update action */
2175
+ type: "SET" | "REMOVE" | "ADD" | "DELETE";
2176
+ /** The attribute path to update */
2177
+ path: string;
2178
+ /** The value to use in the update (not used for REMOVE actions) */
2179
+ value?: unknown;
2180
+ };
1912
2181
  /**
1913
- * Builder for creating and executing DynamoDB transactions.
2182
+ * Type utility to get the element type of a set.
2183
+ * Extracts the element type from either a Set or Array type.
2184
+ * @typeParam T - The set or array type
2185
+ */
2186
+ type SetElementType<T> = T extends Set<infer U> ? U : T extends Array<infer U> ? U : never;
2187
+ /**
2188
+ * Type utility to get the element type from a path that points to a set.
2189
+ * Combines PathType and SetElementType to get the element type at a specific path.
2190
+ * @typeParam T - The type of the item
2191
+ * @typeParam K - The path within the item
2192
+ */
2193
+ type PathSetElementType<T, K extends Path<T>> = SetElementType<PathType<T, K>>;
2194
+ /**
2195
+ * Builder for creating DynamoDB update operations.
1914
2196
  * Use this builder when you need to:
1915
- * - Perform multiple operations atomically
1916
- * - Ensure data consistency across operations
1917
- * - Implement complex business logic that requires atomic updates
1918
- * - Prevent duplicate items across tables
2197
+ * - Modify existing items in DynamoDB
2198
+ * - Update multiple attributes atomically
2199
+ * - Perform conditional updates
2200
+ * - Work with nested attributes
2201
+ * - Update sets and lists
1919
2202
  *
1920
- * The builder supports:
1921
- * - Put operations (insert/replace items)
1922
- * - Delete operations
1923
- * - Update operations
1924
- * - Condition checks
1925
- * - Duplicate detection
1926
- * - Transaction-wide options
2203
+ * The builder supports all DynamoDB update operations:
2204
+ * - SET: Modify or add attributes
2205
+ * - REMOVE: Delete attributes
2206
+ * - ADD: Update numbers and sets
2207
+ * - DELETE: Remove elements from a set
1927
2208
  *
1928
2209
  * @example
1929
2210
  * ```typescript
1930
- * // Create a transaction with multiple operations
1931
- * const transaction = new TransactionBuilder(executor, {
1932
- * partitionKey: 'id',
1933
- * sortKey: 'type'
1934
- * });
1935
- *
1936
- * // Add a new order
1937
- * transaction.put('orders', {
1938
- * orderId: '123',
1939
- * status: 'PENDING'
1940
- * });
1941
- *
1942
- * // Update inventory with condition
1943
- * transaction.update(
1944
- * 'inventory',
1945
- * { productId: 'ABC' },
1946
- * 'set quantity = quantity - :amount',
1947
- * { ':amount': 1 },
1948
- * op => op.gte('quantity', 1)
1949
- * );
2211
+ * // Simple update
2212
+ * const result = await new UpdateBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
2213
+ * .set('status', 'HUNTING')
2214
+ * .set('lastFed', new Date().toISOString())
2215
+ * .execute();
1950
2216
  *
1951
- * // Execute the transaction atomically
1952
- * await transaction.execute();
2217
+ * // Complex update with multiple operations
2218
+ * const result = await new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
2219
+ * .set({
2220
+ * status: 'OCCUPIED',
2221
+ * occupants: 3,
2222
+ * 'metadata.lastInspection': new Date().toISOString()
2223
+ * })
2224
+ * .add('securityBreaches', 1)
2225
+ * .deleteElementsFromSet('suitableDinosaurs', ['VELOCIRAPTOR'])
2226
+ * .condition(op => op.gt('securityLevel', 8))
2227
+ * .returnValues('ALL_NEW')
2228
+ * .execute();
1953
2229
  * ```
1954
2230
  *
1955
- * Note: DynamoDB transactions have some limitations:
1956
- * - Maximum 25 operations per transaction
1957
- * - All operations must be in the same AWS region
1958
- * - Cannot include table scans or queries
2231
+ * @typeParam T - The type of item being updated
1959
2232
  */
1960
- declare class TransactionBuilder {
1961
- private items;
2233
+ declare class UpdateBuilder<T extends Record<string, unknown>> {
2234
+ private updates;
1962
2235
  private options;
1963
- private indexConfig;
1964
2236
  private readonly executor;
1965
- constructor(executor: TransactionExecutor, indexConfig: IndexConfig);
1966
- /**
1967
- * Checks if an item with the same primary key already exists in the transaction
1968
- * @private
1969
- */
1970
- private checkForDuplicateItem;
1971
- /**
1972
- * Adds a put operation to the transaction.
1973
- * Use this method when you need to:
1974
- * - Insert new items as part of a transaction
1975
- * - Replace existing items atomically
1976
- * - Ensure items meet certain conditions before insertion
1977
- *
1978
- * The method automatically checks for duplicate items within the transaction
1979
- * to prevent multiple operations on the same item.
1980
- *
1981
- * @example
1982
- * ```typescript
1983
- * // Simple put operation
1984
- * transaction.put('orders', {
1985
- * orderId: '123',
1986
- * status: 'PENDING',
1987
- * amount: 100
1988
- * });
1989
- *
1990
- * // Conditional put operation
1991
- * transaction.put(
1992
- * 'inventory',
1993
- * { productId: 'ABC', quantity: 50 },
1994
- * op => op.attributeNotExists('productId')
1995
- * );
1996
- *
1997
- * // Put with complex condition
1998
- * transaction.put(
1999
- * 'users',
2000
- * { userId: '123', status: 'ACTIVE' },
2001
- * op => op.and([
2002
- * op.attributeNotExists('userId'),
2003
- * op.beginsWith('status', 'ACTIVE')
2004
- * ])
2005
- * );
2006
- * ```
2007
- *
2008
- * @param tableName - The name of the DynamoDB table
2009
- * @param item - The item to put into the table
2010
- * @param condition - Optional condition that must be satisfied
2011
- * @returns The transaction builder for method chaining
2012
- * @throws {Error} If a duplicate item is detected in the transaction
2013
- */
2014
- put<T extends Record<string, unknown>>(tableName: string, item: T, condition?: Condition): TransactionBuilder;
2237
+ private readonly tableName;
2238
+ private readonly key;
2239
+ constructor(executor: UpdateExecutor<T>, tableName: string, key: PrimaryKeyWithoutExpression);
2015
2240
  /**
2016
- * Adds a pre-configured put operation to the transaction.
2241
+ * Sets multiple attributes of an item using an object.
2017
2242
  * Use this method when you need to:
2018
- * - Reuse put commands from PutBuilder
2019
- * - Add complex put operations with pre-configured parameters
2020
- * - Integrate with existing put command configurations
2021
- *
2022
- * This method is particularly useful when working with PutBuilder
2023
- * to maintain consistency in put operations across your application.
2243
+ * - Update multiple attributes at once
2244
+ * - Set nested attribute values
2245
+ * - Modify complex data structures
2024
2246
  *
2025
2247
  * @example
2026
2248
  * ```typescript
2027
- * // Create a put command with PutBuilder
2028
- * const putCommand = new PutBuilder(executor, newItem, 'users')
2029
- * .condition(op => op.attributeNotExists('userId'))
2030
- * .toDynamoCommand();
2031
- *
2032
- * // Add the command to the transaction
2033
- * transaction.putWithCommand(putCommand);
2249
+ * // Update multiple attributes
2250
+ * builder.set({
2251
+ * species: 'Tyrannosaurus Rex',
2252
+ * height: 20,
2253
+ * diet: 'CARNIVORE',
2254
+ * 'stats.threatLevel': 10
2255
+ * });
2034
2256
  * ```
2035
- *
2036
- * @param command - The complete put command configuration
2037
- * @returns The transaction builder for method chaining
2038
- * @throws {Error} If a duplicate item is detected in the transaction
2039
- * @see PutBuilder for creating put commands
2040
2257
  */
2041
- putWithCommand(command: PutCommandParams): TransactionBuilder;
2258
+ set(values: Partial<T>): UpdateBuilder<T>;
2042
2259
  /**
2043
- * Adds a delete operation to the transaction.
2260
+ * Sets a single attribute to a specific value.
2044
2261
  * Use this method when you need to:
2045
- * - Remove items as part of a transaction
2046
- * - Conditionally delete items
2047
- * - Ensure items exist before deletion
2048
- *
2049
- * The method automatically checks for duplicate items within the transaction
2050
- * to prevent multiple operations on the same item.
2262
+ * - Update one attribute at a time
2263
+ * - Set values with type safety
2264
+ * - Update nested attributes
2051
2265
  *
2052
2266
  * @example
2053
2267
  * ```typescript
2054
- * // Simple delete operation
2055
- * transaction.delete('orders', {
2056
- * pk: 'ORDER#123',
2057
- * sk: 'METADATA'
2058
- * });
2059
- *
2060
- * // Conditional delete operation
2061
- * transaction.delete(
2062
- * 'users',
2063
- * { pk: 'USER#123' },
2064
- * op => op.eq('status', 'INACTIVE')
2065
- * );
2268
+ * // Set simple attributes
2269
+ * builder
2270
+ * .set('status', 'SLEEPING')
2271
+ * .set('lastFeeding', new Date().toISOString());
2066
2272
  *
2067
- * // Delete with complex condition
2068
- * transaction.delete(
2069
- * 'products',
2070
- * { pk: 'PROD#ABC' },
2071
- * op => op.and([
2072
- * op.eq('status', 'DRAFT'),
2073
- * op.lt('version', 5)
2074
- * ])
2075
- * );
2273
+ * // Set nested attributes
2274
+ * builder
2275
+ * .set('location.zone', 'RESTRICTED')
2276
+ * .set('stats.health', 100);
2076
2277
  * ```
2077
- *
2078
- * @param tableName - The name of the DynamoDB table
2079
- * @param key - The primary key of the item to delete
2080
- * @param condition - Optional condition that must be satisfied
2081
- * @returns The transaction builder for method chaining
2082
- * @throws {Error} If a duplicate item is detected in the transaction
2083
2278
  */
2084
- delete(tableName: string, key: PrimaryKeyWithoutExpression, condition?: Condition): TransactionBuilder;
2279
+ set<K extends Path<T>>(path: K, value: PathType<T, K>): UpdateBuilder<T>;
2085
2280
  /**
2086
- * Adds a pre-configured delete operation to the transaction.
2281
+ * Removes an attribute from the item.
2087
2282
  * Use this method when you need to:
2088
- * - Reuse delete commands from DeleteBuilder
2089
- * - Add complex delete operations with pre-configured parameters
2090
- * - Integrate with existing delete command configurations
2091
- *
2092
- * This method is particularly useful when working with DeleteBuilder
2093
- * to maintain consistency in delete operations across your application.
2283
+ * - Delete attributes completely
2284
+ * - Remove nested attributes
2285
+ * - Clean up deprecated fields
2094
2286
  *
2095
2287
  * @example
2096
2288
  * ```typescript
2097
- * // Create a delete command with DeleteBuilder
2098
- * const deleteCommand = new DeleteBuilder(executor, 'users', { pk: 'USER#123' })
2099
- * .condition(op => op.and([
2100
- * op.attributeExists('pk'),
2101
- * op.eq('status', 'INACTIVE')
2102
- * ]))
2103
- * .toDynamoCommand();
2289
+ * // Remove simple attributes
2290
+ * builder
2291
+ * .remove('temporaryTag')
2292
+ * .remove('previousLocation');
2104
2293
  *
2105
- * // Add the command to the transaction
2106
- * transaction.deleteWithCommand(deleteCommand);
2294
+ * // Remove nested attributes
2295
+ * builder
2296
+ * .remove('metadata.testData')
2297
+ * .remove('stats.experimentalMetrics');
2107
2298
  * ```
2108
2299
  *
2109
- * @param command - The complete delete command configuration
2110
- * @returns The transaction builder for method chaining
2111
- * @throws {Error} If a duplicate item is detected in the transaction
2112
- * @see DeleteBuilder for creating delete commands
2300
+ * @param path - The path to the attribute to remove
2301
+ * @returns The builder instance for method chaining
2113
2302
  */
2114
- deleteWithCommand(command: DeleteCommandParams): TransactionBuilder;
2303
+ remove<K extends Path<T>>(path: K): UpdateBuilder<T>;
2115
2304
  /**
2116
- * Adds an update operation to the transaction.
2305
+ * Adds a value to a number attribute or adds elements to a set.
2117
2306
  * Use this method when you need to:
2118
- * - Modify existing items as part of a transaction
2119
- * - Update multiple attributes atomically
2120
- * - Apply conditional updates
2121
- * - Perform complex attribute manipulations
2122
- *
2123
- * The method supports all DynamoDB update expressions:
2124
- * - SET: Modify or add attributes
2125
- * - REMOVE: Delete attributes
2126
- * - ADD: Update numbers and sets
2127
- * - DELETE: Remove elements from a set
2307
+ * - Increment counters
2308
+ * - Add elements to a set atomically
2309
+ * - Update numerical statistics
2128
2310
  *
2129
2311
  * @example
2130
2312
  * ```typescript
2131
- * // Simple update
2132
- * transaction.update(
2133
- * 'orders',
2134
- * { pk: 'ORDER#123' },
2135
- * 'SET #status = :status',
2136
- * { '#status': 'status' },
2137
- * { ':status': 'PROCESSING' }
2138
- * );
2139
- *
2140
- * // Complex update with multiple operations
2141
- * transaction.update(
2142
- * 'products',
2143
- * { pk: 'PROD#ABC' },
2144
- * 'SET #qty = #qty - :amount, #status = :status REMOVE #oldAttr',
2145
- * { '#qty': 'quantity', '#status': 'status', '#oldAttr': 'deprecated_field' },
2146
- * { ':amount': 1, ':status': 'LOW_STOCK' }
2147
- * );
2313
+ * // Increment counters
2314
+ * builder
2315
+ * .add('escapeAttempts', 1)
2316
+ * .add('feedingCount', 1);
2148
2317
  *
2149
- * // Conditional update
2150
- * transaction.update(
2151
- * 'users',
2152
- * { pk: 'USER#123' },
2153
- * 'SET #lastLogin = :now',
2154
- * { '#lastLogin': 'lastLoginDate' },
2155
- * { ':now': new Date().toISOString() },
2156
- * op => op.attributeExists('pk')
2157
- * );
2318
+ * // Add to sets
2319
+ * builder
2320
+ * .add('knownBehaviors', new Set(['PACK_HUNTING', 'AMBUSH_TACTICS']))
2321
+ * .add('visitedZones', new Set(['ZONE_A', 'ZONE_B']));
2158
2322
  * ```
2159
2323
  *
2160
- * @param tableName - The name of the DynamoDB table
2161
- * @param key - The primary key of the item to update
2162
- * @param updateExpression - The update expression (SET, REMOVE, ADD, DELETE)
2163
- * @param expressionAttributeNames - Map of attribute name placeholders to actual names
2164
- * @param expressionAttributeValues - Map of value placeholders to actual values
2165
- * @param condition - Optional condition that must be satisfied
2166
- * @returns The transaction builder for method chaining
2167
- * @throws {Error} If a duplicate item is detected in the transaction
2324
+ * @param path - The path to the attribute to update
2325
+ * @param value - The value to add (number or set)
2326
+ * @returns The builder instance for method chaining
2168
2327
  */
2169
- update<T extends Record<string, unknown>>(tableName: string, key: PrimaryKeyWithoutExpression, updateExpression: string, expressionAttributeNames?: Record<string, string>, expressionAttributeValues?: Record<string, unknown>, condition?: Condition): TransactionBuilder;
2328
+ add<K extends Path<T>>(path: K, value: PathType<T, K>): UpdateBuilder<T>;
2170
2329
  /**
2171
- * Adds a pre-configured update operation to the transaction.
2330
+ * Removes elements from a set attribute.
2172
2331
  * Use this method when you need to:
2173
- * - Reuse update commands from UpdateBuilder
2174
- * - Add complex update operations with pre-configured parameters
2175
- * - Integrate with existing update command configurations
2176
- *
2177
- * This method is particularly useful when working with UpdateBuilder
2178
- * to maintain consistency in update operations across your application.
2332
+ * - Remove specific elements from a set
2333
+ * - Update set-based attributes atomically
2334
+ * - Maintain set membership
2179
2335
  *
2180
2336
  * @example
2181
2337
  * ```typescript
2182
- * // Create an update command with UpdateBuilder
2183
- * const updateCommand = new UpdateBuilder(executor, 'inventory', { pk: 'PROD#ABC' })
2184
- * .set('quantity', ':qty')
2185
- * .set('lastUpdated', ':now')
2186
- * .values({
2187
- * ':qty': 100,
2188
- * ':now': new Date().toISOString()
2189
- * })
2190
- * .condition(op => op.gt('quantity', 0))
2191
- * .toDynamoCommand();
2338
+ * // Remove from sets using arrays
2339
+ * builder.deleteElementsFromSet(
2340
+ * 'allowedHabitats',
2341
+ * ['JUNGLE', 'COASTAL']
2342
+ * );
2192
2343
  *
2193
- * // Add the command to the transaction
2194
- * transaction.updateWithCommand(updateCommand);
2344
+ * // Remove from sets using Set objects
2345
+ * builder.deleteElementsFromSet(
2346
+ * 'knownBehaviors',
2347
+ * new Set(['NOCTURNAL', 'TERRITORIAL'])
2348
+ * );
2349
+ *
2350
+ * // Remove from nested sets
2351
+ * builder.deleteElementsFromSet(
2352
+ * 'stats.compatibleSpecies',
2353
+ * ['VELOCIRAPTOR', 'DILOPHOSAURUS']
2354
+ * );
2195
2355
  * ```
2196
2356
  *
2197
- * @param command - The complete update command configuration
2198
- * @returns The transaction builder for method chaining
2199
- * @throws {Error} If a duplicate item is detected in the transaction
2200
- * @see UpdateBuilder for creating update commands
2357
+ * @param path - The path to the set attribute
2358
+ * @param value - Elements to remove (array or Set)
2359
+ * @returns The builder instance for method chaining
2201
2360
  */
2202
- updateWithCommand(command: UpdateCommandParams): TransactionBuilder;
2361
+ deleteElementsFromSet<K extends Path<T>>(path: K, value: PathSetElementType<T, K>[] | Set<PathSetElementType<T, K>>): UpdateBuilder<T>;
2203
2362
  /**
2204
- * Adds a condition check operation to the transaction.
2363
+ * Adds a condition that must be satisfied for the update to succeed.
2205
2364
  * Use this method when you need to:
2206
- * - Validate item state without modifying it
2207
- * - Ensure data consistency across tables
2208
- * - Implement complex business rules
2209
- * - Verify preconditions for other operations
2210
- *
2211
- * Condition checks are particularly useful for:
2212
- * - Implementing optimistic locking
2213
- * - Ensuring referential integrity
2214
- * - Validating business rules atomically
2365
+ * - Implement optimistic locking
2366
+ * - Ensure item state before update
2367
+ * - Validate business rules
2368
+ * - Prevent concurrent modifications
2215
2369
  *
2216
2370
  * @example
2217
2371
  * ```typescript
2218
- * // Check if order is in correct state
2219
- * transaction.conditionCheck(
2220
- * 'orders',
2221
- * { pk: 'ORDER#123' },
2222
- * op => op.eq('status', 'PENDING')
2372
+ * // Simple condition
2373
+ * builder.condition(op =>
2374
+ * op.eq('status', 'ACTIVE')
2223
2375
  * );
2224
- *
2225
- * // Complex condition check
2226
- * transaction.conditionCheck(
2227
- * 'inventory',
2228
- * { pk: 'PROD#ABC' },
2229
- * op => op.and([
2230
- * op.gt('quantity', 0),
2231
- * op.eq('status', 'ACTIVE'),
2232
- * op.attributeExists('lastRestockDate')
2376
+ *
2377
+ * // Health check condition
2378
+ * builder.condition(op =>
2379
+ * op.and([
2380
+ * op.gt('health', 50),
2381
+ * op.eq('status', 'HUNTING')
2233
2382
  * ])
2234
2383
  * );
2235
2384
  *
2236
- * // Check with multiple attributes
2237
- * transaction.conditionCheck(
2238
- * 'users',
2239
- * { pk: 'USER#123' },
2240
- * op => op.or([
2241
- * op.eq('status', 'PREMIUM'),
2242
- * op.gte('credits', 100)
2385
+ * // Complex security condition
2386
+ * builder.condition(op =>
2387
+ * op.and([
2388
+ * op.attributeExists('securitySystem'),
2389
+ * op.eq('containmentStatus', 'SECURE'),
2390
+ * op.lt('aggressionLevel', 8)
2243
2391
  * ])
2244
2392
  * );
2393
+ *
2394
+ * // Version check (optimistic locking)
2395
+ * builder.condition(op =>
2396
+ * op.eq('version', currentVersion)
2397
+ * );
2245
2398
  * ```
2246
2399
  *
2247
- * @param tableName - The name of the DynamoDB table
2248
- * @param key - The primary key of the item to check
2249
- * @param condition - The condition that must be satisfied
2250
- * @returns The transaction builder for method chaining
2251
- * @throws {Error} If a duplicate item is detected in the transaction
2252
- * @throws {Error} If condition expression generation fails
2400
+ * @param condition - Either a Condition object or a callback function that builds the condition
2401
+ * @returns The builder instance for method chaining
2253
2402
  */
2254
- conditionCheck(tableName: string, key: PrimaryKeyWithoutExpression, condition: Condition): TransactionBuilder;
2403
+ condition(condition: Condition | ((op: ConditionOperator<T>) => Condition)): UpdateBuilder<T>;
2255
2404
  /**
2256
- * Adds a pre-configured condition check operation to the transaction.
2405
+ * Sets which item attributes to include in the response.
2257
2406
  * Use this method when you need to:
2258
- * - Reuse condition checks from ConditionCheckBuilder
2259
- * - Add complex condition checks with pre-configured parameters
2260
- * - Integrate with existing condition check configurations
2407
+ * - Get the complete updated item
2408
+ * - Track changes to specific attributes
2409
+ * - Compare old and new values
2410
+ * - Monitor attribute modifications
2261
2411
  *
2262
- * This method is particularly useful when working with ConditionCheckBuilder
2263
- * to maintain consistency in condition checks across your application.
2412
+ * Available options:
2413
+ * - ALL_NEW: All attributes after the update
2414
+ * - UPDATED_NEW: Only updated attributes, new values
2415
+ * - ALL_OLD: All attributes before the update
2416
+ * - UPDATED_OLD: Only updated attributes, old values
2417
+ * - NONE: No attributes returned (default)
2264
2418
  *
2265
2419
  * @example
2266
2420
  * ```typescript
2267
- * // Create a condition check with ConditionCheckBuilder
2268
- * const checkCommand = new ConditionCheckBuilder('inventory', { pk: 'PROD#ABC' })
2269
- * .condition(op => op.and([
2270
- * op.between('quantity', 10, 100),
2271
- * op.beginsWith('category', 'ELECTRONICS'),
2272
- * op.attributeExists('lastAuditDate')
2273
- * ]))
2274
- * .toDynamoCommand();
2421
+ * // Get complete updated dinosaur
2422
+ * const result = await builder
2423
+ * .set('status', 'SLEEPING')
2424
+ * .returnValues('ALL_NEW')
2425
+ * .execute();
2275
2426
  *
2276
- * // Add the command to the transaction
2277
- * transaction.conditionCheckWithCommand(checkCommand);
2427
+ * // Track specific attribute changes
2428
+ * const result = await builder
2429
+ * .set({
2430
+ * 'stats.health': 100,
2431
+ * 'stats.energy': 95
2432
+ * })
2433
+ * .returnValues('UPDATED_OLD')
2434
+ * .execute();
2435
+ *
2436
+ * if (result.item) {
2437
+ * console.log('Previous health:', result.item.stats?.health);
2438
+ * }
2278
2439
  * ```
2279
2440
  *
2280
- * @param command - The complete condition check command configuration
2281
- * @returns The transaction builder for method chaining
2282
- * @throws {Error} If a duplicate item is detected in the transaction
2283
- * @see ConditionCheckBuilder for creating condition check commands
2441
+ * @param returnValues - Which attributes to return in the response
2442
+ * @returns The builder instance for method chaining
2284
2443
  */
2285
- conditionCheckWithCommand(command: ConditionCheckCommandParams): TransactionBuilder;
2444
+ returnValues(returnValues: "ALL_NEW" | "UPDATED_NEW" | "ALL_OLD" | "UPDATED_OLD" | "NONE"): UpdateBuilder<T>;
2286
2445
  /**
2287
- * Sets options for the transaction execution.
2446
+ * Generate the DynamoDB command parameters
2447
+ */
2448
+ toDynamoCommand(): UpdateCommandParams;
2449
+ /**
2450
+ * Adds this update operation to a transaction.
2288
2451
  * Use this method when you need to:
2289
- * - Enable idempotent transactions
2290
- * - Track consumed capacity
2291
- * - Monitor item collection metrics
2452
+ * - Update items as part of a larger transaction
2453
+ * - Ensure multiple updates are atomic
2454
+ * - Coordinate updates across multiple items
2292
2455
  *
2293
2456
  * @example
2294
2457
  * ```typescript
2295
- * // Enable idempotency and capacity tracking
2296
- * transaction.withOptions({
2297
- * clientRequestToken: 'unique-request-id-123',
2298
- * returnConsumedCapacity: 'TOTAL'
2299
- * });
2458
+ * const transaction = new TransactionBuilder(executor);
2300
2459
  *
2301
- * // Track item collection metrics
2302
- * transaction.withOptions({
2303
- * returnItemCollectionMetrics: 'SIZE'
2304
- * });
2305
- * ```
2460
+ * // Update dinosaur status and habitat occupancy atomically
2461
+ * new UpdateBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
2462
+ * .set('location', 'PADDOCK_A')
2463
+ * .set('status', 'CONTAINED')
2464
+ * .withTransaction(transaction);
2306
2465
  *
2307
- * Note: ClientRequestToken can be used to make transactions idempotent,
2308
- * ensuring the same transaction is not executed multiple times.
2466
+ * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-A' })
2467
+ * .add('occupants', 1)
2468
+ * .set('lastOccupied', new Date().toISOString())
2469
+ * .withTransaction(transaction);
2309
2470
  *
2310
- * @param options - Configuration options for the transaction
2311
- * @returns The transaction builder for method chaining
2471
+ * // Execute all operations atomically
2472
+ * await transaction.execute();
2473
+ * ```
2474
+ *
2475
+ * @param transaction - The transaction builder to add this operation to
2476
+ * @returns The builder instance for method chaining
2312
2477
  */
2313
- withOptions(options: TransactionOptions): TransactionBuilder;
2478
+ withTransaction(transaction: TransactionBuilder): void;
2314
2479
  /**
2315
- * Gets a human-readable representation of the transaction items.
2480
+ * Gets a human-readable representation of the update command.
2316
2481
  * Use this method when you need to:
2317
- * - Debug complex transactions
2318
- * - Verify operation parameters
2319
- * - Log transaction details
2482
+ * - Debug complex update expressions
2483
+ * - Verify attribute names and values
2484
+ * - Log update operations
2320
2485
  * - Troubleshoot condition expressions
2321
2486
  *
2322
- * The method resolves all expression placeholders with their actual values,
2323
- * making it easier to understand the transaction's operations.
2324
- *
2325
2487
  * @example
2326
2488
  * ```typescript
2327
- * // Add multiple operations
2328
- * transaction
2329
- * .put('orders', { orderId: '123', status: 'PENDING' })
2330
- * .update('inventory',
2331
- * { productId: 'ABC' },
2332
- * 'SET quantity = quantity - :amount',
2333
- * undefined,
2334
- * { ':amount': 1 }
2335
- * );
2489
+ * // Create complex update
2490
+ * const builder = new UpdateBuilder(executor, 'dinosaurs', { id: 'RAPTOR-001' })
2491
+ * .set({
2492
+ * status: 'HUNTING',
2493
+ * 'stats.health': 95,
2494
+ * 'behavior.lastObserved': new Date().toISOString()
2495
+ * })
2496
+ * .add('huntingSuccesses', 1)
2497
+ * .condition(op => op.gt('health', 50));
2336
2498
  *
2337
- * // Debug the transaction
2338
- * const debugInfo = transaction.debug();
2339
- * console.log('Transaction operations:', debugInfo);
2499
+ * // Debug the update
2500
+ * const debugInfo = builder.debug();
2501
+ * console.log('Update operation:', debugInfo);
2340
2502
  * ```
2341
2503
  *
2342
- * @returns An array of readable representations of the transaction items
2504
+ * @returns A readable representation of the update command with resolved expressions
2343
2505
  */
2344
- debug(): Record<string, unknown>[];
2506
+ debug(): Record<string, unknown>;
2345
2507
  /**
2346
- * Executes all operations in the transaction atomically.
2508
+ * Executes the update operation against DynamoDB.
2347
2509
  * Use this method when you need to:
2348
- * - Perform multiple operations atomically
2349
- * - Ensure all-or-nothing execution
2350
- * - Maintain data consistency across operations
2351
- *
2352
- * The transaction will only succeed if all operations succeed.
2353
- * If any operation fails, the entire transaction is rolled back.
2510
+ * - Apply updates immediately
2511
+ * - Get the updated item values
2512
+ * - Handle conditional update failures
2354
2513
  *
2355
2514
  * @example
2356
2515
  * ```typescript
2357
2516
  * try {
2358
- * // Build and execute transaction
2359
- * await transaction
2360
- * .put('orders', newOrder)
2361
- * .update('inventory',
2362
- * { productId: 'ABC' },
2363
- * 'SET quantity = quantity - :qty',
2364
- * undefined,
2365
- * { ':qty': 1 }
2366
- * )
2367
- * .conditionCheck('products',
2368
- * { productId: 'ABC' },
2369
- * op => op.eq('status', 'ACTIVE')
2517
+ * // Update dinosaur status with conditions
2518
+ * const result = await new UpdateBuilder(executor, 'dinosaurs', { id: 'TREX-001' })
2519
+ * .set({
2520
+ * status: 'FEEDING',
2521
+ * lastMeal: new Date().toISOString(),
2522
+ * 'stats.hunger': 0
2523
+ * })
2524
+ * .add('feedingCount', 1)
2525
+ * .condition(op =>
2526
+ * op.and([
2527
+ * op.gt('stats.hunger', 80),
2528
+ * op.eq('status', 'HUNTING')
2529
+ * ])
2370
2530
  * )
2531
+ * .returnValues('ALL_NEW')
2371
2532
  * .execute();
2372
2533
  *
2373
- * console.log('Transaction completed successfully');
2534
+ * if (result.item) {
2535
+ * console.log('Updated dinosaur:', result.item);
2536
+ * }
2374
2537
  * } catch (error) {
2375
- * // Handle transaction failure
2376
- * console.error('Transaction failed:', error);
2538
+ * // Handle condition check failure
2539
+ * console.error('Failed to update dinosaur:', error);
2540
+ * // Check if dinosaur wasn't hungry enough
2541
+ * if (error.name === 'ConditionalCheckFailedException') {
2542
+ * console.log('Dinosaur not ready for feeding');
2543
+ * }
2377
2544
  * }
2378
2545
  * ```
2379
2546
  *
2380
- * @throws {Error} If no transaction items are specified
2381
- * @throws {Error} If any operation in the transaction fails
2382
- * @returns A promise that resolves when the transaction completes
2547
+ * @returns A promise that resolves to an object containing the updated item (if returnValues is set)
2548
+ * @throws {ConditionalCheckFailedException} If the condition check fails
2549
+ * @throws {Error} If the update operation fails for other reasons
2383
2550
  */
2384
- execute(): Promise<void>;
2551
+ execute(): Promise<{
2552
+ item?: T;
2553
+ }>;
2385
2554
  }
2386
2555
 
2556
+ type BatchWriteOperation<T extends Record<string, unknown>> = {
2557
+ type: "put";
2558
+ item: T;
2559
+ } | {
2560
+ type: "delete";
2561
+ key: PrimaryKeyWithoutExpression;
2562
+ };
2563
+
2387
2564
  /**
2388
- * Parameters for the DynamoDB put command.
2389
- * These parameters are used when executing the operation against DynamoDB.
2390
- */
2391
- interface PutCommandParams extends DynamoCommandWithExpressions {
2392
- tableName: string;
2393
- item: Record<string, unknown>;
2394
- conditionExpression?: string;
2395
- expressionAttributeNames?: Record<string, string>;
2396
- expressionAttributeValues?: Record<string, unknown>;
2397
- returnValues?: "ALL_OLD" | "NONE";
2398
- }
2399
- type PutExecutor<T extends Record<string, unknown>> = (params: PutCommandParams) => Promise<T>;
2400
- /**
2401
- * Builder for creating DynamoDB put operations.
2402
- * Use this builder when you need to:
2403
- * - Add new dinosaurs to the registry
2404
- * - Create new habitats
2405
- * - Update dinosaur profiles completely
2406
- * - Initialize tracking records
2565
+ * Builder for creating DynamoDB condition check operations.
2566
+ * Use this builder when you need to:
2567
+ * - Verify item state without modifying it
2568
+ * - Ensure preconditions in transactions
2569
+ * - Implement optimistic locking patterns
2570
+ * - Validate business rules
2407
2571
  *
2408
2572
  * @example
2409
2573
  * ```typescript
2410
- * // Add new dinosaur
2411
- * const result = await new PutBuilder(executor, {
2412
- * id: 'RAPTOR-001',
2413
- * species: 'Velociraptor',
2414
- * status: 'ACTIVE',
2415
- * stats: {
2416
- * health: 100,
2417
- * age: 5,
2418
- * threatLevel: 8
2419
- * }
2420
- * }, 'dinosaurs').execute();
2574
+ * // Check if dinosaur is ready for feeding
2575
+ * const check = new ConditionCheckBuilder('dinosaurs', { id: 'TREX-001' })
2576
+ * .condition(op =>
2577
+ * op.and([
2578
+ * op.eq('status', 'HUNTING'),
2579
+ * op.gt('stats.hunger', 80),
2580
+ * op.lt('stats.health', 100)
2581
+ * ])
2582
+ * )
2583
+ * .toDynamoCommand();
2421
2584
  *
2422
- * // Create new habitat with conditions
2423
- * const result = await new PutBuilder(executor, {
2424
- * id: 'PADDOCK-C',
2425
- * type: 'CARNIVORE',
2426
- * securityLevel: 'MAXIMUM',
2427
- * capacity: 3,
2428
- * environmentType: 'TROPICAL'
2429
- * }, 'habitats')
2430
- * .condition(op => op.attributeNotExists('id'))
2431
- * .execute();
2585
+ * // Check habitat security status
2586
+ * const securityCheck = new ConditionCheckBuilder('habitats', { id: 'PADDOCK-A' })
2587
+ * .condition(op =>
2588
+ * op.and([
2589
+ * op.eq('securityStatus', 'ACTIVE'),
2590
+ * op.attributeExists('lastInspection'),
2591
+ * op.lt('threatLevel', 5)
2592
+ * ])
2593
+ * )
2594
+ * .toDynamoCommand();
2432
2595
  * ```
2433
- *
2434
- * @typeParam T - The type of item being put into the table
2435
2596
  */
2436
- declare class PutBuilder<T extends Record<string, unknown>> {
2437
- private readonly item;
2438
- private options;
2439
- private readonly executor;
2597
+ declare class ConditionCheckBuilder {
2598
+ private readonly key;
2440
2599
  private readonly tableName;
2441
- constructor(executor: PutExecutor<T>, item: T, tableName: string);
2600
+ private conditionExpression?;
2601
+ constructor(tableName: string, key: PrimaryKeyWithoutExpression);
2442
2602
  /**
2443
- * Adds a condition that must be satisfied for the put operation to succeed.
2603
+ * Adds a condition that must be satisfied for the check to succeed.
2444
2604
  * Use this method when you need to:
2445
- * - Prevent overwriting existing items (optimistic locking)
2446
- * - Ensure items meet certain criteria before replacement
2447
- * - Implement complex business rules for item updates
2605
+ * - Validate complex item states
2606
+ * - Check multiple attributes together
2607
+ * - Ensure safety conditions are met
2448
2608
  *
2449
2609
  * @example
2450
- * ```ts
2451
- * // Ensure item doesn't exist (insert only)
2452
- * builder.condition(op => op.attributeNotExists('id'))
2453
- *
2454
- * // Complex condition with version check
2610
+ * ```typescript
2611
+ * // Check dinosaur health and behavior
2455
2612
  * builder.condition(op =>
2456
2613
  * op.and([
2457
- * op.attributeExists('id'),
2458
- * op.eq('version', currentVersion),
2459
- * op.eq('status', 'ACTIVE')
2614
+ * op.gt('stats.health', 50),
2615
+ * op.not(op.eq('status', 'SEDATED')),
2616
+ * op.lt('aggressionLevel', 8)
2460
2617
  * ])
2461
- * )
2462
- * ```
2463
- *
2464
- * @param condition - Either a Condition object or a callback function that builds the condition
2465
- * @returns The builder instance for method chaining
2466
- */
2467
- /**
2468
- * Adds a condition that must be satisfied for the put operation to succeed.
2469
- * Use this method when you need to:
2470
- * - Prevent duplicate dinosaur entries
2471
- * - Ensure habitat requirements
2472
- * - Validate security protocols
2473
- *
2474
- * @example
2475
- * ```typescript
2476
- * // Ensure unique dinosaur ID
2477
- * builder.condition(op =>
2478
- * op.attributeNotExists('id')
2479
2618
  * );
2480
2619
  *
2481
- * // Verify habitat requirements
2620
+ * // Verify habitat conditions
2482
2621
  * builder.condition(op =>
2483
2622
  * op.and([
2484
- * op.eq('securityStatus', 'READY'),
2485
- * op.attributeExists('lastInspection'),
2486
- * op.gt('securityLevel', 5)
2623
+ * op.eq('powerStatus', 'ONLINE'),
2624
+ * op.between('temperature', 20, 30),
2625
+ * op.attributeExists('lastMaintenance')
2487
2626
  * ])
2488
2627
  * );
2489
2628
  *
2490
- * // Check breeding facility conditions
2629
+ * // Check breeding conditions
2491
2630
  * builder.condition(op =>
2492
2631
  * op.and([
2493
- * op.between('temperature', 25, 30),
2494
- * op.between('humidity', 60, 80),
2495
- * op.eq('quarantineStatus', 'CLEAR')
2632
+ * op.eq('species', 'VELOCIRAPTOR'),
2633
+ * op.gte('age', 3),
2634
+ * op.eq('geneticPurity', 100)
2496
2635
  * ])
2497
2636
  * );
2498
2637
  * ```
@@ -2500,144 +2639,78 @@ declare class PutBuilder<T extends Record<string, unknown>> {
2500
2639
  * @param condition - Either a Condition object or a callback function that builds the condition
2501
2640
  * @returns The builder instance for method chaining
2502
2641
  */
2503
- condition(condition: Condition | ((op: ConditionOperator<T>) => Condition)): PutBuilder<T>;
2642
+ condition<T extends Record<string, unknown>>(condition: Condition | ((op: ConditionOperator<T>) => Condition)): ConditionCheckBuilder;
2504
2643
  /**
2505
- * Sets whether to return the item's previous values (if it existed).
2506
- * Use this method when you need to:
2507
- * - Track dinosaur profile updates
2508
- * - Monitor habitat modifications
2509
- * - Maintain change history
2644
+ * Generates the DynamoDB command parameters for direct execution.
2645
+ * Use this method when you want to:
2646
+ * - Execute the condition check as a standalone operation
2647
+ * - Get the raw DynamoDB command for custom execution
2648
+ * - Inspect the generated command parameters
2510
2649
  *
2511
2650
  * @example
2512
2651
  * ```ts
2513
- * // Get previous dinosaur state
2514
- * const result = await builder
2515
- * .returnValues('ALL_OLD')
2516
- * .execute();
2517
- *
2518
- * if (result) {
2519
- * console.log('Previous profile:', {
2520
- * species: result.species,
2521
- * status: result.status,
2522
- * stats: {
2523
- * health: result.stats.health,
2524
- * threatLevel: result.stats.threatLevel
2525
- * }
2526
- * });
2527
- * }
2652
+ * const command = new ConditionCheckBuilder('myTable', { id: '123' })
2653
+ * .condition(op => op.attributeExists('status'))
2654
+ * .toDynamoCommand();
2655
+ * // Use command with DynamoDB client
2528
2656
  * ```
2529
2657
  *
2530
- * @param returnValues - Use 'ALL_OLD' to return previous values, or 'NONE' (default)
2531
- * @returns The builder instance for method chaining
2532
- */
2533
- returnValues(returnValues: "ALL_OLD" | "NONE"): PutBuilder<T>;
2534
- /**
2535
- * Generate the DynamoDB command parameters
2658
+ * @throws {Error} If no condition has been set
2659
+ * @returns The DynamoDB command parameters
2536
2660
  */
2537
2661
  private toDynamoCommand;
2538
2662
  /**
2539
- * Adds this put operation to a transaction.
2663
+ * Adds this condition check operation to a transaction.
2540
2664
  * Use this method when you need to:
2541
- * - Transfer dinosaurs between habitats
2542
- * - Initialize new breeding programs
2543
- * - Update multiple facility records
2665
+ * - Verify habitat safety before transfers
2666
+ * - Ensure proper feeding conditions
2667
+ * - Validate security protocols
2544
2668
  *
2545
2669
  * @example
2546
2670
  * ```ts
2547
2671
  * const transaction = new TransactionBuilder();
2548
- *
2549
- * // Add dinosaur to new habitat
2550
- * new PutBuilder(executor, {
2551
- * id: 'TREX-002',
2552
- * location: 'PADDOCK-B',
2553
- * status: 'ACTIVE',
2554
- * transferDate: new Date().toISOString()
2555
- * }, 'dinosaurs')
2556
- * .withTransaction(transaction);
2557
- *
2558
- * // Update habitat records
2559
- * new UpdateBuilder(executor, 'habitats', { id: 'PADDOCK-B' })
2560
- * .add('occupants', 1)
2561
- * .set('lastTransfer', new Date().toISOString())
2672
+ * new ConditionCheckBuilder('habitats', { id: 'PADDOCK-B' })
2673
+ * .condition(op => op.and([
2674
+ * op.eq('securityStatus', 'ACTIVE'),
2675
+ * op.lt('currentOccupants', 3),
2676
+ * op.eq('habitatType', 'CARNIVORE')
2677
+ * ]))
2562
2678
  * .withTransaction(transaction);
2563
- *
2564
- * // Execute transfer atomically
2565
- * await transaction.execute();
2679
+ * // Add dinosaur transfer operations
2566
2680
  * ```
2567
2681
  *
2568
2682
  * @param transaction - The transaction builder to add this operation to
2683
+ * @throws {Error} If no condition has been set
2569
2684
  * @returns The builder instance for method chaining
2570
2685
  */
2571
- withTransaction(transaction: TransactionBuilder): PutBuilder<T>;
2572
- /**
2573
- * Executes the put operation against DynamoDB.
2574
- *
2575
- * @example
2576
- * ```ts
2577
- * try {
2578
- * // Put with condition and return old values
2579
- * const result = await new PutBuilder(executor, newItem, 'myTable')
2580
- * .condition(op => op.eq('version', 1))
2581
- * .returnValues('ALL_OLD')
2582
- * .execute();
2583
- *
2584
- * console.log('Put successful, old item:', result);
2585
- * } catch (error) {
2586
- * // Handle condition check failure or other errors
2587
- * console.error('Put failed:', error);
2588
- * }
2589
- * ```
2590
- *
2591
- * @returns A promise that resolves to the operation result (type depends on returnValues setting)
2592
- * @throws Will throw an error if the condition check fails or other DynamoDB errors occur
2593
- */
2594
- execute(): Promise<T>;
2686
+ withTransaction(transaction: TransactionBuilder): ConditionCheckBuilder;
2595
2687
  /**
2596
- * Gets a human-readable representation of the put command
2688
+ * Gets a human-readable representation of the condition check command
2597
2689
  * with all expression placeholders replaced by their actual values.
2598
2690
  * Use this method when you need to:
2599
- * - Debug complex dinosaur transfers
2600
- * - Verify habitat assignments
2601
- * - Log security protocols
2602
- * - Troubleshoot breeding program conditions
2691
+ * - Debug complex condition expressions
2692
+ * - Verify condition parameters
2693
+ * - Log safety checks
2694
+ * - Troubleshoot condition failures
2603
2695
  *
2604
2696
  * @example
2605
2697
  * ```ts
2606
- * const debugInfo = new PutBuilder(executor, {
2607
- * id: 'RAPTOR-003',
2608
- * species: 'Velociraptor',
2609
- * status: 'QUARANTINE',
2610
- * stats: {
2611
- * health: 100,
2612
- * aggressionLevel: 7,
2613
- * age: 2
2614
- * }
2615
- * }, 'dinosaurs')
2616
- * .condition(op =>
2617
- * op.and([
2618
- * op.attributeNotExists('id'),
2619
- * op.eq('quarantineStatus', 'READY'),
2620
- * op.gt('securityLevel', 8)
2621
- * ])
2622
- * )
2698
+ * const debugInfo = new ConditionCheckBuilder('dinosaurs', { id: 'TREX-001' })
2699
+ * .condition(op => op.and([
2700
+ * op.between('stats.health', 50, 100),
2701
+ * op.not(op.eq('status', 'SEDATED')),
2702
+ * op.attributeExists('lastFeedingTime')
2703
+ * op.eq('version', 1)
2704
+ * ]))
2623
2705
  * .debug();
2624
- *
2625
- * console.log('Dinosaur transfer command:', debugInfo);
2706
+ * console.log(debugInfo);
2626
2707
  * ```
2627
2708
  *
2628
- * @returns A readable representation of the put command with resolved expressions
2709
+ * @returns A readable representation of the condition check command with resolved expressions
2629
2710
  */
2630
2711
  debug(): Record<string, unknown>;
2631
2712
  }
2632
2713
 
2633
- type BatchWriteOperation<T extends Record<string, unknown>> = {
2634
- type: "put";
2635
- item: T;
2636
- } | {
2637
- type: "delete";
2638
- key: PrimaryKeyWithoutExpression;
2639
- };
2640
-
2641
2714
  /**
2642
2715
  * Parameters for the DynamoDB get command.
2643
2716
  */
@@ -2847,4 +2920,4 @@ declare class Table<TConfig extends TableConfig = TableConfig> {
2847
2920
  }>;
2848
2921
  }
2849
2922
 
2850
- 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 };
2923
+ export { type ComparisonOperator, type Condition, ConditionCheckBuilder, type ConditionOperator, DeleteBuilder, type DeleteOptions, type EntityConfig, type ExpressionParams, type GSINames, type Index, type KeyConditionOperator, type LogicalOperator, Paginator, type PrimaryKey, type PrimaryKeyWithoutExpression, PutBuilder, type PutOptions, QueryBuilder, type QueryOptions, Table, type TableConfig, TransactionBuilder, type TransactionExecutor, type TransactionOptions, type UpdateAction, UpdateBuilder, type UpdateOptions, and, attributeExists, attributeNotExists, beginsWith, between, contains, createComparisonCondition, eq, gt, gte, lt, lte, ne, not, or };