@ftschopp/dynatable-core 1.4.2 → 1.4.3

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 (81) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/builders/query/create-query-builder.d.ts.map +1 -1
  3. package/dist/builders/query/create-query-builder.js +19 -2
  4. package/dist/core/types.d.ts +5 -0
  5. package/dist/core/types.d.ts.map +1 -1
  6. package/package.json +11 -2
  7. package/eslint.config.mjs +0 -4
  8. package/jest.config.js +0 -11
  9. package/src/builders/README.md +0 -339
  10. package/src/builders/batch-get/README.md +0 -43
  11. package/src/builders/batch-get/create-batch-get-builder.test.ts +0 -193
  12. package/src/builders/batch-get/create-batch-get-builder.ts +0 -108
  13. package/src/builders/batch-get/index.ts +0 -2
  14. package/src/builders/batch-get/types.ts +0 -28
  15. package/src/builders/batch-write/README.md +0 -204
  16. package/src/builders/batch-write/create-batch-write-builder.test.ts +0 -173
  17. package/src/builders/batch-write/create-batch-write-builder.ts +0 -49
  18. package/src/builders/batch-write/index.ts +0 -2
  19. package/src/builders/batch-write/types.ts +0 -33
  20. package/src/builders/delete/create-delete-builder.test.ts +0 -294
  21. package/src/builders/delete/create-delete-builder.ts +0 -100
  22. package/src/builders/delete/index.ts +0 -2
  23. package/src/builders/delete/types.ts +0 -17
  24. package/src/builders/get/create-get-builder.test.ts +0 -272
  25. package/src/builders/get/create-get-builder.ts +0 -117
  26. package/src/builders/get/index.ts +0 -2
  27. package/src/builders/get/types.ts +0 -39
  28. package/src/builders/index.ts +0 -14
  29. package/src/builders/put/create-put-builder.test.ts +0 -213
  30. package/src/builders/put/create-put-builder.ts +0 -160
  31. package/src/builders/put/index.ts +0 -2
  32. package/src/builders/put/types.ts +0 -24
  33. package/src/builders/query/create-query-builder.test.ts +0 -770
  34. package/src/builders/query/create-query-builder.ts +0 -455
  35. package/src/builders/query/index.ts +0 -2
  36. package/src/builders/query/types.ts +0 -109
  37. package/src/builders/scan/create-scan-builder.test.ts +0 -416
  38. package/src/builders/scan/create-scan-builder.ts +0 -265
  39. package/src/builders/scan/index.ts +0 -2
  40. package/src/builders/scan/types.ts +0 -88
  41. package/src/builders/shared/conditions.ts +0 -58
  42. package/src/builders/shared/index.ts +0 -4
  43. package/src/builders/shared/operators.test.ts +0 -270
  44. package/src/builders/shared/operators.ts +0 -208
  45. package/src/builders/shared/projection.ts +0 -28
  46. package/src/builders/shared/types.ts +0 -101
  47. package/src/builders/transact-get/README.md +0 -167
  48. package/src/builders/transact-get/create-transact-get-builder.test.ts +0 -239
  49. package/src/builders/transact-get/create-transact-get-builder.ts +0 -67
  50. package/src/builders/transact-get/index.ts +0 -2
  51. package/src/builders/transact-get/types.ts +0 -31
  52. package/src/builders/transact-write/README.md +0 -202
  53. package/src/builders/transact-write/create-transact-write-builder.test.ts +0 -288
  54. package/src/builders/transact-write/create-transact-write-builder.ts +0 -124
  55. package/src/builders/transact-write/index.ts +0 -2
  56. package/src/builders/transact-write/types.ts +0 -71
  57. package/src/builders/update/create-update-builder.test.ts +0 -573
  58. package/src/builders/update/create-update-builder.ts +0 -375
  59. package/src/builders/update/index.ts +0 -2
  60. package/src/builders/update/types.ts +0 -63
  61. package/src/core/types.test.ts +0 -641
  62. package/src/core/types.ts +0 -366
  63. package/src/entity/create-entity-api.ts +0 -224
  64. package/src/entity/index.ts +0 -19
  65. package/src/entity/middleware/factories.ts +0 -15
  66. package/src/entity/middleware/types.ts +0 -7
  67. package/src/entity/middleware/with-middleware.ts +0 -37
  68. package/src/entity/types.ts +0 -79
  69. package/src/entity/validation/key-validation.ts +0 -34
  70. package/src/index.ts +0 -23
  71. package/src/table.ts +0 -116
  72. package/src/utils/dynamodb-logger.test.ts +0 -246
  73. package/src/utils/dynamodb-logger.ts +0 -175
  74. package/src/utils/model-utils.test.ts +0 -452
  75. package/src/utils/model-utils.ts +0 -188
  76. package/src/utils/zod-utils.test.ts +0 -363
  77. package/src/utils/zod-utils.ts +0 -56
  78. package/tests/integration/instagram-clone.integration.test.ts +0 -1019
  79. package/tests/integration/pagination-timestamps.integration.test.ts +0 -374
  80. package/tests/integration/transactions.integration.test.ts +0 -528
  81. package/tsconfig.json +0 -12
@@ -1,202 +0,0 @@
1
- # TransactWrite - Atomic Multi-Item Writes
2
-
3
- TransactWrite provides atomic multi-item write operations in DynamoDB. All operations in a transaction either succeed together or fail together.
4
-
5
- ## Features
6
-
7
- - **Functional API**: Immutable builders using pure functions
8
- - **Type-safe**: Full TypeScript support with AWS SDK types
9
- - **Composable**: Chain operations fluently
10
- - **Idempotent**: Support for client request tokens
11
- - **Flexible**: Accepts both entity builder outputs and raw DynamoDB parameters
12
-
13
- ## Usage
14
-
15
- ### Basic Example
16
-
17
- ```typescript
18
- import { createTransactWriteBuilder } from '@repo/core';
19
- import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
20
-
21
- const client = new DynamoDBClient({});
22
-
23
- await createTransactWriteBuilder(client).addPut(putParams).addUpdate(updateParams).execute();
24
- ```
25
-
26
- ### With Table API
27
-
28
- ```typescript
29
- const table = new Table({
30
- name: 'MyTable',
31
- client: new DynamoDBClient({}),
32
- schema: MySchema,
33
- });
34
-
35
- // Like a photo atomically
36
- await table
37
- .transactWrite()
38
- .addPut(
39
- table.entities.Like.put({
40
- photoId: '123',
41
- likingUsername: 'alice',
42
- })
43
- .ifNotExists()
44
- .dbParams()
45
- )
46
- .addUpdate(
47
- table.entities.Photo.update({
48
- username: 'bob',
49
- photoId: '123',
50
- })
51
- .add('likesCount', 1)
52
- .dbParams()
53
- )
54
- .execute();
55
- ```
56
-
57
- ## Real-World Examples
58
-
59
- ### Follow a User
60
-
61
- ```typescript
62
- await table
63
- .transactWrite()
64
- .addPut(
65
- table.entities.Follow.put({
66
- followedUsername: 'alice',
67
- followingUsername: 'bob',
68
- })
69
- .ifNotExists()
70
- .dbParams()
71
- )
72
- .addUpdate(table.entities.User.update({ username: 'alice' }).add('followerCount', 1).dbParams())
73
- .addUpdate(table.entities.User.update({ username: 'bob' }).add('followingCount', 1).dbParams())
74
- .execute();
75
- ```
76
-
77
- ### Comment on Photo
78
-
79
- ```typescript
80
- await table
81
- .transactWrite()
82
- .addPut(
83
- table.entities.Comment.put({
84
- photoId: '123',
85
- commentingUsername: 'charlie',
86
- content: 'Great photo!',
87
- }).dbParams()
88
- )
89
- .addUpdate(
90
- table.entities.Photo.update({
91
- username: 'alice',
92
- photoId: '123',
93
- })
94
- .add('commentCount', 1)
95
- .dbParams()
96
- )
97
- .execute();
98
- ```
99
-
100
- ### Delete with Safety Check
101
-
102
- ```typescript
103
- // Only delete if photo has no engagement
104
- await table
105
- .transactWrite()
106
- .addDelete(
107
- table.entities.Photo.delete({
108
- username: 'alice',
109
- photoId: '123',
110
- })
111
- .where((attr, op) => op.and(op.eq(attr.likesCount, 0), op.eq(attr.commentCount, 0)))
112
- .dbParams()
113
- )
114
- .execute();
115
- ```
116
-
117
- ### Condition Check
118
-
119
- ```typescript
120
- // Create user only if admin exists
121
- await table
122
- .transactWrite()
123
- .addPut(
124
- table.entities.User.put({
125
- username: 'newuser',
126
- name: 'New User',
127
- })
128
- .ifNotExists()
129
- .dbParams()
130
- )
131
- .addConditionCheck({
132
- TableName: 'MyTable',
133
- Key: { pk: 'USER#admin', sk: 'USER#admin' },
134
- ConditionExpression: 'attribute_exists(#pk)',
135
- ExpressionAttributeNames: { '#pk': 'pk' },
136
- })
137
- .execute();
138
- ```
139
-
140
- ## Idempotency
141
-
142
- Use client request tokens for idempotent operations:
143
-
144
- ```typescript
145
- await table.transactWrite().addPut(params).withClientRequestToken('unique-id-12345').execute();
146
- ```
147
-
148
- ## Type Safety
149
-
150
- All operations are fully typed using AWS SDK types:
151
-
152
- ```typescript
153
- import type {
154
- TransactPutParams,
155
- TransactUpdateParams,
156
- TransactDeleteParams,
157
- TransactConditionCheckParams,
158
- } from '@ftschopp/dynatable-core';
159
-
160
- // addPut accepts PutCommandInput from @aws-sdk/lib-dynamodb
161
- const putParams: TransactPutParams = {
162
- TableName: 'MyTable',
163
- Item: { pk: 'USER#123', sk: 'USER#123', name: 'John' },
164
- };
165
-
166
- // TypeScript validates all parameters at compile time
167
- table.transactWrite().addPut(putParams).execute();
168
- ```
169
-
170
- ### Using Entity Builders
171
-
172
- Entity builders automatically provide correctly typed parameters via `.dbParams()`:
173
-
174
- ```typescript
175
- // The entity builder's dbParams() returns PutCommandInput
176
- const params = table.entities.User.put({ username: 'john' }).ifNotExists().dbParams();
177
- // params is typed as PutCommandInput
178
-
179
- // Pass it to the transaction builder
180
- table.transactWrite().addPut(params).execute();
181
- ```
182
-
183
- ## Functional Design
184
-
185
- The builder is immutable - each method returns a new instance:
186
-
187
- ```typescript
188
- const builder1 = table.transactWrite();
189
- const builder2 = builder1.addPut(params1);
190
- const builder3 = builder2.addPut(params2);
191
-
192
- builder1.dbParams().TransactItems.length; // 0
193
- builder2.dbParams().TransactItems.length; // 1
194
- builder3.dbParams().TransactItems.length; // 2
195
- ```
196
-
197
- ## Limitations
198
-
199
- - Maximum **100 items** per transaction
200
- - Maximum **4 MB** total size
201
- - Single table only
202
- - May fail with `TransactionCanceledException` if conditions fail
@@ -1,288 +0,0 @@
1
- import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
2
- import { createTransactWriteBuilder } from './create-transact-write-builder';
3
-
4
- const client = new DynamoDBClient({});
5
-
6
- describe('TransactWrite Builder - Functional API', () => {
7
- test('should create empty transaction', () => {
8
- const params = createTransactWriteBuilder(client).dbParams();
9
-
10
- expect(params).toEqual({
11
- TransactItems: [],
12
- });
13
- });
14
-
15
- test('should add single Put operation', () => {
16
- const putParams = {
17
- TableName: 'InstagramClone',
18
- Item: {
19
- pk: 'USER#alice',
20
- sk: 'USER#alice',
21
- username: 'alice',
22
- name: 'Alice Smith',
23
- followerCount: 0,
24
- followingCount: 0,
25
- },
26
- };
27
-
28
- const params = createTransactWriteBuilder(client).addPut(putParams).dbParams();
29
-
30
- expect(params).toEqual({
31
- TransactItems: [{ Put: putParams }],
32
- });
33
- });
34
-
35
- test('should add single Update operation', () => {
36
- const updateParams = {
37
- TableName: 'InstagramClone',
38
- Key: { pk: 'USER#alice', sk: 'USER#alice' },
39
- UpdateExpression: 'ADD #followerCount :followerCount_0',
40
- ExpressionAttributeNames: { '#followerCount': 'followerCount' },
41
- ExpressionAttributeValues: { ':followerCount_0': 1 },
42
- };
43
-
44
- const params = createTransactWriteBuilder(client).addUpdate(updateParams).dbParams();
45
-
46
- expect(params).toEqual({
47
- TransactItems: [{ Update: updateParams }],
48
- });
49
- });
50
-
51
- test('should add single Delete operation', () => {
52
- const deleteParams = {
53
- TableName: 'InstagramClone',
54
- Key: { pk: 'USER#alice', sk: 'USER#alice' },
55
- };
56
-
57
- const params = createTransactWriteBuilder(client).addDelete(deleteParams).dbParams();
58
-
59
- expect(params).toEqual({
60
- TransactItems: [{ Delete: deleteParams }],
61
- });
62
- });
63
-
64
- test('should add ConditionCheck operation', () => {
65
- const conditionCheckParams = {
66
- TableName: 'InstagramClone',
67
- Key: { pk: 'USER#admin', sk: 'USER#admin' },
68
- ConditionExpression: 'attribute_exists(#username)',
69
- ExpressionAttributeNames: { '#username': 'username' },
70
- };
71
-
72
- const params = createTransactWriteBuilder(client)
73
- .addConditionCheck(conditionCheckParams)
74
- .dbParams();
75
-
76
- expect(params).toEqual({
77
- TransactItems: [{ ConditionCheck: conditionCheckParams }],
78
- });
79
- });
80
-
81
- test('should chain multiple operations - Like a Photo', () => {
82
- // Like a Photo: Create Like + Increment Photo.likesCount
83
- const putLikeParams = {
84
- TableName: 'InstagramClone',
85
- Item: {
86
- pk: 'PL#photo123',
87
- sk: 'LIKE#juanca',
88
- photoId: 'photo123',
89
- likingUsername: 'juanca',
90
- likeId: '01K16ZP43BRX67DG50SHGZ11DS',
91
- },
92
- ConditionExpression: '(attribute_not_exists(#PK)) AND (attribute_not_exists(#SK))',
93
- ExpressionAttributeNames: { '#PK': 'pk', '#SK': 'sk' },
94
- };
95
-
96
- const updatePhotoParams = {
97
- TableName: 'InstagramClone',
98
- Key: { pk: 'UP#alice', sk: 'PHOTO#photo123' },
99
- UpdateExpression: 'ADD #likesCount :likesCount_0',
100
- ExpressionAttributeNames: { '#likesCount': 'likesCount' },
101
- ExpressionAttributeValues: { ':likesCount_0': 1 },
102
- };
103
-
104
- const params = createTransactWriteBuilder(client)
105
- .addPut(putLikeParams)
106
- .addUpdate(updatePhotoParams)
107
- .dbParams();
108
-
109
- expect(params).toEqual({
110
- TransactItems: [{ Put: putLikeParams }, { Update: updatePhotoParams }],
111
- });
112
- expect(params.TransactItems).toHaveLength(2);
113
- });
114
-
115
- test('should chain multiple operations - Follow a User', () => {
116
- // Follow: Create Follow + Update both user counts
117
- const putFollowParams = {
118
- TableName: 'InstagramClone',
119
- Item: {
120
- pk: 'FOLLOW#alice',
121
- sk: 'FOLLOW#bob',
122
- followedUsername: 'alice',
123
- followingUsername: 'bob',
124
- },
125
- ConditionExpression: '(attribute_not_exists(#PK)) AND (attribute_not_exists(#SK))',
126
- ExpressionAttributeNames: { '#PK': 'pk', '#SK': 'sk' },
127
- };
128
-
129
- const updateFollowedParams = {
130
- TableName: 'InstagramClone',
131
- Key: { pk: 'USER#alice', sk: 'USER#alice' },
132
- UpdateExpression: 'ADD #followerCount :followerCount_0',
133
- ExpressionAttributeNames: { '#followerCount': 'followerCount' },
134
- ExpressionAttributeValues: { ':followerCount_0': 1 },
135
- };
136
-
137
- const updateFollowingParams = {
138
- TableName: 'InstagramClone',
139
- Key: { pk: 'USER#bob', sk: 'USER#bob' },
140
- UpdateExpression: 'ADD #followingCount :followingCount_0',
141
- ExpressionAttributeNames: { '#followingCount': 'followingCount' },
142
- ExpressionAttributeValues: { ':followingCount_0': 1 },
143
- };
144
-
145
- const params = createTransactWriteBuilder(client)
146
- .addPut(putFollowParams)
147
- .addUpdate(updateFollowedParams)
148
- .addUpdate(updateFollowingParams)
149
- .dbParams();
150
-
151
- expect(params.TransactItems).toHaveLength(3);
152
- expect(params.TransactItems[0]).toEqual({ Put: putFollowParams });
153
- expect(params.TransactItems[1]).toEqual({ Update: updateFollowedParams });
154
- expect(params.TransactItems[2]).toEqual({ Update: updateFollowingParams });
155
- });
156
-
157
- test('should chain multiple operations - Comment on Photo', () => {
158
- const putCommentParams = {
159
- TableName: 'InstagramClone',
160
- Item: {
161
- pk: 'PC#photo123',
162
- sk: 'COMMENT#comment456',
163
- photoId: 'photo123',
164
- commentId: 'comment456',
165
- commentingUsername: 'bob',
166
- content: 'Great photo!',
167
- },
168
- };
169
-
170
- const updatePhotoParams = {
171
- TableName: 'InstagramClone',
172
- Key: { pk: 'UP#alice', sk: 'PHOTO#photo123' },
173
- UpdateExpression: 'ADD #commentCount :commentCount_0',
174
- ExpressionAttributeNames: { '#commentCount': 'commentCount' },
175
- ExpressionAttributeValues: { ':commentCount_0': 1 },
176
- };
177
-
178
- const params = createTransactWriteBuilder(client)
179
- .addPut(putCommentParams)
180
- .addUpdate(updatePhotoParams)
181
- .dbParams();
182
-
183
- expect(params.TransactItems).toHaveLength(2);
184
- expect(params.TransactItems[0]).toEqual({ Put: putCommentParams });
185
- expect(params.TransactItems[1]).toEqual({ Update: updatePhotoParams });
186
- });
187
-
188
- test('should support client request token for idempotency', () => {
189
- const putParams = {
190
- TableName: 'InstagramClone',
191
- Item: { pk: 'USER#alice', sk: 'USER#alice', username: 'alice' },
192
- };
193
-
194
- const params = createTransactWriteBuilder(client)
195
- .addPut(putParams)
196
- .withClientRequestToken('my-unique-token-123')
197
- .dbParams();
198
-
199
- expect(params).toEqual({
200
- TransactItems: [{ Put: putParams }],
201
- ClientRequestToken: 'my-unique-token-123',
202
- });
203
- });
204
-
205
- test('should preserve immutability - original builder unchanged', () => {
206
- const builder1 = createTransactWriteBuilder(client);
207
- const putParams = {
208
- TableName: 'InstagramClone',
209
- Item: { pk: 'USER#alice', sk: 'USER#alice' },
210
- };
211
-
212
- const builder2 = builder1.addPut(putParams);
213
- const builder3 = builder2.withClientRequestToken('token');
214
-
215
- // Each builder should be independent
216
- expect(builder1.dbParams().TransactItems).toHaveLength(0);
217
- expect(builder2.dbParams().TransactItems).toHaveLength(1);
218
- expect(builder3.dbParams().ClientRequestToken).toBe('token');
219
- expect(builder2.dbParams().ClientRequestToken).toBeUndefined();
220
- });
221
-
222
- test('should handle complex transaction - Delete Photo only if no engagement', () => {
223
- const deletePhotoParams = {
224
- TableName: 'InstagramClone',
225
- Key: { pk: 'UP#alice', sk: 'PHOTO#photo123' },
226
- ConditionExpression: '(#likesCount = :likesCount_0) AND (#commentCount = :commentCount_1)',
227
- ExpressionAttributeNames: {
228
- '#likesCount': 'likesCount',
229
- '#commentCount': 'commentCount',
230
- },
231
- ExpressionAttributeValues: {
232
- ':likesCount_0': 0,
233
- ':commentCount_1': 0,
234
- },
235
- };
236
-
237
- const params = createTransactWriteBuilder(client).addDelete(deletePhotoParams).dbParams();
238
-
239
- expect(params.TransactItems).toHaveLength(1);
240
- expect(params.TransactItems[0]).toEqual({ Delete: deletePhotoParams });
241
- });
242
-
243
- test('should handle max operations (100 items limit)', () => {
244
- let builder = createTransactWriteBuilder(client);
245
-
246
- // Add 100 Put operations (DynamoDB limit)
247
- for (let i = 0; i < 100; i++) {
248
- builder = builder.addPut({
249
- TableName: 'InstagramClone',
250
- Item: { pk: `USER#user${i}`, sk: `USER#user${i}` },
251
- });
252
- }
253
-
254
- const params = builder.dbParams();
255
- expect(params.TransactItems).toHaveLength(100);
256
- });
257
-
258
- test('should mix all operation types', () => {
259
- const params = createTransactWriteBuilder(client)
260
- .addPut({
261
- TableName: 'InstagramClone',
262
- Item: { pk: 'USER#alice', sk: 'USER#alice' },
263
- })
264
- .addUpdate({
265
- TableName: 'InstagramClone',
266
- Key: { pk: 'USER#bob', sk: 'USER#bob' },
267
- UpdateExpression: 'ADD #count :val',
268
- ExpressionAttributeNames: { '#count': 'followerCount' },
269
- ExpressionAttributeValues: { ':val': 1 },
270
- })
271
- .addDelete({
272
- TableName: 'InstagramClone',
273
- Key: { pk: 'PHOTO#old', sk: 'PHOTO#old' },
274
- })
275
- .addConditionCheck({
276
- TableName: 'InstagramClone',
277
- Key: { pk: 'USER#admin', sk: 'USER#admin' },
278
- ConditionExpression: 'attribute_exists(pk)',
279
- })
280
- .dbParams();
281
-
282
- expect(params.TransactItems).toHaveLength(4);
283
- expect(params.TransactItems[0]).toHaveProperty('Put');
284
- expect(params.TransactItems[1]).toHaveProperty('Update');
285
- expect(params.TransactItems[2]).toHaveProperty('Delete');
286
- expect(params.TransactItems[3]).toHaveProperty('ConditionCheck');
287
- });
288
- });
@@ -1,124 +0,0 @@
1
- import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
2
- import { TransactWriteCommand } from '@aws-sdk/lib-dynamodb';
3
- import {
4
- TransactWriteBuilder,
5
- TransactWriteState,
6
- TransactPutParams,
7
- TransactUpdateParams,
8
- TransactDeleteParams,
9
- TransactConditionCheckParams,
10
- } from './types';
11
-
12
- /**
13
- * Creates the initial state for a TransactWrite builder
14
- */
15
- const createInitialState = (client: DynamoDBClient): TransactWriteState => ({
16
- client,
17
- items: [],
18
- });
19
-
20
- /**
21
- * Adds a Put operation to the transaction
22
- */
23
- const addPutItem =
24
- (state: TransactWriteState) =>
25
- (params: TransactPutParams): TransactWriteState => ({
26
- ...state,
27
- items: [...state.items, { Put: params }],
28
- });
29
-
30
- /**
31
- * Adds an Update operation to the transaction
32
- */
33
- const addUpdateItem =
34
- (state: TransactWriteState) =>
35
- (params: TransactUpdateParams): TransactWriteState => ({
36
- ...state,
37
- items: [...state.items, { Update: params }],
38
- });
39
-
40
- /**
41
- * Adds a Delete operation to the transaction
42
- */
43
- const addDeleteItem =
44
- (state: TransactWriteState) =>
45
- (params: TransactDeleteParams): TransactWriteState => ({
46
- ...state,
47
- items: [...state.items, { Delete: params }],
48
- });
49
-
50
- /**
51
- * Adds a ConditionCheck operation to the transaction
52
- */
53
- const addConditionCheckItem =
54
- (state: TransactWriteState) =>
55
- (params: TransactConditionCheckParams): TransactWriteState => ({
56
- ...state,
57
- items: [...state.items, { ConditionCheck: params }],
58
- });
59
-
60
- /**
61
- * Sets the client request token for idempotency
62
- */
63
- const setClientRequestToken =
64
- (state: TransactWriteState) =>
65
- (token: string): TransactWriteState => ({
66
- ...state,
67
- clientRequestToken: token,
68
- });
69
-
70
- /**
71
- * Converts the builder state to DynamoDB parameters
72
- */
73
- const toDbParams = (state: TransactWriteState): ReturnType<TransactWriteBuilder['dbParams']> => {
74
- const params: ReturnType<TransactWriteBuilder['dbParams']> = {
75
- TransactItems: [...state.items],
76
- };
77
-
78
- if (state.clientRequestToken) {
79
- params.ClientRequestToken = state.clientRequestToken;
80
- }
81
-
82
- return params;
83
- };
84
-
85
- /**
86
- * Executes the transaction
87
- */
88
- const execute = async (state: TransactWriteState) => {
89
- const params = toDbParams(state);
90
- const command = new TransactWriteCommand(params);
91
- return await state.client.send(command);
92
- };
93
-
94
- /**
95
- * Creates a builder from the current state
96
- */
97
- const createBuilder = (state: TransactWriteState): TransactWriteBuilder => ({
98
- addPut: (params) => createBuilder(addPutItem(state)(params)),
99
- addUpdate: (params) => createBuilder(addUpdateItem(state)(params)),
100
- addDelete: (params) => createBuilder(addDeleteItem(state)(params)),
101
- addConditionCheck: (params) => createBuilder(addConditionCheckItem(state)(params)),
102
- withClientRequestToken: (token) => createBuilder(setClientRequestToken(state)(token)),
103
- dbParams: () => toDbParams(state),
104
- execute: () => execute(state),
105
- });
106
-
107
- /**
108
- * Creates a new TransactWrite builder
109
- *
110
- * @param client - DynamoDB client instance
111
- * @returns A TransactWriteBuilder
112
- *
113
- * @example
114
- * ```typescript
115
- * const result = await createTransactWriteBuilder(client)
116
- * .addPut(putParams)
117
- * .addUpdate(updateParams)
118
- * .execute();
119
- * ```
120
- */
121
- export const createTransactWriteBuilder = (client: DynamoDBClient): TransactWriteBuilder => {
122
- const initialState = createInitialState(client);
123
- return createBuilder(initialState);
124
- };
@@ -1,2 +0,0 @@
1
- export * from './types';
2
- export * from './create-transact-write-builder';
@@ -1,71 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
3
- import type {
4
- TransactWriteCommandInput,
5
- TransactWriteCommandOutput,
6
- PutCommandInput,
7
- UpdateCommandInput,
8
- DeleteCommandInput,
9
- } from '@aws-sdk/lib-dynamodb';
10
-
11
- // Extract types from AWS SDK's TransactWriteCommandInput
12
- type TransactWriteItems = NonNullable<TransactWriteCommandInput['TransactItems']>;
13
- type StrictTransactPut = NonNullable<TransactWriteItems[number]['Put']>;
14
- type StrictTransactUpdate = NonNullable<TransactWriteItems[number]['Update']>;
15
- type StrictTransactDelete = NonNullable<TransactWriteItems[number]['Delete']>;
16
- type StrictTransactConditionCheck = NonNullable<TransactWriteItems[number]['ConditionCheck']>;
17
-
18
- /**
19
- * Parameters for a Put operation within a transaction
20
- * Accepts both regular PutCommandInput and strict transaction Put params
21
- */
22
- export type TransactPutParams = PutCommandInput | StrictTransactPut;
23
-
24
- /**
25
- * Parameters for an Update operation within a transaction
26
- * Accepts both regular UpdateCommandInput and strict transaction Update params
27
- */
28
- export type TransactUpdateParams = UpdateCommandInput | StrictTransactUpdate;
29
-
30
- /**
31
- * Parameters for a Delete operation within a transaction
32
- * Accepts both regular DeleteCommandInput and strict transaction Delete params
33
- */
34
- export type TransactDeleteParams = DeleteCommandInput | StrictTransactDelete;
35
-
36
- /**
37
- * Parameters for a ConditionCheck operation within a transaction
38
- */
39
- export type TransactConditionCheckParams = StrictTransactConditionCheck;
40
-
41
- /**
42
- * Represents a single item in a TransactWrite operation
43
- * Using any internally to allow flexibility between CommandInput and strict transaction types
44
- */
45
- export type TransactWriteItem =
46
- | { Put: any }
47
- | { Update: any }
48
- | { Delete: any }
49
- | { ConditionCheck: any };
50
-
51
- /**
52
- * State for the TransactWrite builder
53
- */
54
- export type TransactWriteState = {
55
- readonly client: DynamoDBClient;
56
- readonly items: readonly TransactWriteItem[];
57
- readonly clientRequestToken?: string;
58
- };
59
-
60
- /**
61
- * TransactWrite builder interface
62
- */
63
- export type TransactWriteBuilder = {
64
- readonly addPut: (params: TransactPutParams) => TransactWriteBuilder;
65
- readonly addUpdate: (params: TransactUpdateParams) => TransactWriteBuilder;
66
- readonly addDelete: (params: TransactDeleteParams) => TransactWriteBuilder;
67
- readonly addConditionCheck: (params: TransactConditionCheckParams) => TransactWriteBuilder;
68
- readonly withClientRequestToken: (token: string) => TransactWriteBuilder;
69
- readonly dbParams: () => TransactWriteCommandInput;
70
- readonly execute: () => Promise<TransactWriteCommandOutput>;
71
- };