@ftschopp/dynatable-core 1.0.0 → 1.2.0

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 (85) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +528 -2
  3. package/dist/builders/delete/types.d.ts +6 -1
  4. package/dist/builders/delete/types.d.ts.map +1 -1
  5. package/dist/builders/get/types.d.ts +6 -1
  6. package/dist/builders/get/types.d.ts.map +1 -1
  7. package/dist/builders/put/types.d.ts +6 -1
  8. package/dist/builders/put/types.d.ts.map +1 -1
  9. package/dist/builders/query/create-query-builder.d.ts +1 -1
  10. package/dist/builders/query/create-query-builder.d.ts.map +1 -1
  11. package/dist/builders/query/types.d.ts +9 -10
  12. package/dist/builders/query/types.d.ts.map +1 -1
  13. package/dist/builders/transact-write/create-transact-write-builder.d.ts.map +1 -1
  14. package/dist/builders/transact-write/create-transact-write-builder.js +1 -1
  15. package/dist/builders/transact-write/types.d.ts +33 -6
  16. package/dist/builders/transact-write/types.d.ts.map +1 -1
  17. package/dist/builders/update/create-update-builder.d.ts.map +1 -1
  18. package/dist/builders/update/create-update-builder.js +30 -9
  19. package/dist/builders/update/types.d.ts +8 -2
  20. package/dist/builders/update/types.d.ts.map +1 -1
  21. package/dist/core/types.d.ts +96 -11
  22. package/dist/core/types.d.ts.map +1 -1
  23. package/dist/entity/create-entity-api.d.ts +15 -0
  24. package/dist/entity/create-entity-api.d.ts.map +1 -0
  25. package/dist/entity/create-entity-api.js +124 -0
  26. package/dist/entity/index.d.ts +12 -0
  27. package/dist/entity/index.d.ts.map +1 -0
  28. package/dist/entity/index.js +18 -0
  29. package/dist/entity/middleware/factories.d.ts +6 -0
  30. package/dist/entity/middleware/factories.d.ts.map +1 -0
  31. package/dist/entity/middleware/factories.js +15 -0
  32. package/dist/entity/middleware/types.d.ts +8 -0
  33. package/dist/entity/middleware/types.d.ts.map +1 -0
  34. package/dist/entity/middleware/types.js +2 -0
  35. package/dist/entity/middleware/with-middleware.d.ts +8 -0
  36. package/dist/entity/middleware/with-middleware.d.ts.map +1 -0
  37. package/dist/entity/middleware/with-middleware.js +29 -0
  38. package/dist/{entity.d.ts → entity/types.d.ts} +6 -17
  39. package/dist/entity/types.d.ts.map +1 -0
  40. package/dist/entity/types.js +2 -0
  41. package/dist/entity/validation/key-validation.d.ts +7 -0
  42. package/dist/entity/validation/key-validation.d.ts.map +1 -0
  43. package/dist/entity/validation/key-validation.js +25 -0
  44. package/dist/index.d.ts +1 -1
  45. package/dist/index.d.ts.map +1 -1
  46. package/dist/table.d.ts +8 -1
  47. package/dist/table.d.ts.map +1 -1
  48. package/dist/table.js +1 -0
  49. package/dist/utils/model-utils.d.ts +7 -1
  50. package/dist/utils/model-utils.d.ts.map +1 -1
  51. package/dist/utils/model-utils.js +32 -3
  52. package/dist/utils/zod-utils.d.ts +3 -2
  53. package/dist/utils/zod-utils.d.ts.map +1 -1
  54. package/dist/utils/zod-utils.js +33 -11
  55. package/package.json +3 -2
  56. package/src/builders/README.md +68 -1
  57. package/src/builders/delete/types.ts +7 -1
  58. package/src/builders/get/types.ts +7 -1
  59. package/src/builders/put/types.ts +7 -1
  60. package/src/builders/query/create-query-builder.ts +4 -6
  61. package/src/builders/query/types.ts +9 -12
  62. package/src/builders/transact-write/README.md +37 -1
  63. package/src/builders/transact-write/create-transact-write-builder.ts +20 -14
  64. package/src/builders/transact-write/types.ts +44 -6
  65. package/src/builders/update/create-update-builder.test.ts +43 -0
  66. package/src/builders/update/create-update-builder.ts +47 -9
  67. package/src/builders/update/types.ts +9 -2
  68. package/src/core/types.test.ts +137 -0
  69. package/src/core/types.ts +97 -20
  70. package/src/entity/create-entity-api.ts +212 -0
  71. package/src/entity/index.ts +19 -0
  72. package/src/entity/middleware/factories.ts +15 -0
  73. package/src/entity/middleware/types.ts +7 -0
  74. package/src/entity/middleware/with-middleware.ts +37 -0
  75. package/src/entity/types.ts +79 -0
  76. package/src/entity/validation/key-validation.ts +34 -0
  77. package/src/index.ts +1 -0
  78. package/src/table.ts +10 -3
  79. package/src/utils/model-utils.test.ts +131 -1
  80. package/src/utils/model-utils.ts +35 -2
  81. package/src/utils/zod-utils.test.ts +97 -2
  82. package/src/utils/zod-utils.ts +31 -12
  83. package/dist/entity.d.ts.map +0 -1
  84. package/dist/entity.js +0 -161
  85. package/src/entity.ts +0 -337
package/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ # @ftschopp/dynatable-core [1.2.0](https://github.com/ftschopp/dynatable/compare/@ftschopp/dynatable-core@1.1.0...@ftschopp/dynatable-core@1.2.0) (2026-03-20)
2
+
3
+
4
+ ### Features
5
+
6
+ * support nested objects and arrays schema ([c06e43e](https://github.com/ftschopp/dynatable/commit/c06e43e6b425bae09f127d2f767b5c8c62dd1142))
7
+
8
+ # @ftschopp/dynatable-core [1.1.0](https://github.com/ftschopp/dynatable/compare/@ftschopp/dynatable-core@1.0.0...@ftschopp/dynatable-core@1.1.0) (2026-01-20)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * improve types ([efdf362](https://github.com/ftschopp/dynatable/commit/efdf362cefa94f5b6cba653b3a0cc8d017da6966))
14
+
15
+
16
+ ### Features
17
+
18
+ * improve types ([3a87c5c](https://github.com/ftschopp/dynatable/commit/3a87c5c37565f92d8c4a4790396eefa57cd9a5c5))
19
+
1
20
  # @ftschopp/dynatable-core 1.0.0 (2026-01-10)
2
21
 
3
22
 
package/README.md CHANGED
@@ -1,17 +1,543 @@
1
1
  # @ftschopp/dynatable-core
2
2
 
3
- A type-safe, functional programming library for AWS DynamoDB with Single Table Design support.
3
+ A type-safe, functional programming library for AWS DynamoDB with Single Table Design support. Built with TypeScript and designed to make DynamoDB development elegant and productive.
4
+
5
+ ## Features
6
+
7
+ - 🔐 **Type-Safe** - Full TypeScript support with end-to-end type inference
8
+ - 🎯 **Single Table Design** - Built-in support for DynamoDB best practices
9
+ - 🔄 **Functional API** - Chainable, composable operations with immutable builders
10
+ - ⚡️ **Auto-generated IDs** - ULID/UUID generation for unique identifiers
11
+ - 🕒 **Automatic Timestamps** - Auto-manage `createdAt` and `updatedAt`
12
+ - 🔒 **Transactions** - Atomic operations with `TransactWrite` and `TransactGet`
13
+ - 📦 **Batch Operations** - Efficient `BatchGet` and `BatchWrite` operations
14
+ - 🎨 **Query Builder** - Intuitive, type-safe API for complex queries
15
+ - ✅ **Validation** - Built-in Zod schema validation
16
+ - 🧪 **Testable** - Easy to mock and test with AWS SDK client mock support
4
17
 
5
18
  ## Installation
6
19
 
7
20
  ```bash
8
21
  npm install @ftschopp/dynatable-core
22
+ # or
23
+ yarn add @ftschopp/dynatable-core
24
+ # or
25
+ pnpm add @ftschopp/dynatable-core
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```typescript
31
+ import { Table } from '@ftschopp/dynatable-core';
32
+ import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
33
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
34
+
35
+ // Define your schema
36
+ const schema = {
37
+ format: 'dynatable:1.0.0',
38
+ version: '1.0.0',
39
+ indexes: {
40
+ primary: { hash: 'PK', sort: 'SK' },
41
+ },
42
+ models: {
43
+ User: {
44
+ key: {
45
+ PK: { type: String, value: 'USER#${username}' },
46
+ SK: { type: String, value: 'USER#${username}' },
47
+ },
48
+ attributes: {
49
+ username: { type: String, required: true },
50
+ name: { type: String, required: true },
51
+ email: { type: String, required: true },
52
+ },
53
+ },
54
+ },
55
+ params: {
56
+ timestamps: true,
57
+ isoDates: true,
58
+ },
59
+ } as const;
60
+
61
+ // Create DynamoDB client
62
+ const ddbClient = new DynamoDBClient({ region: 'us-east-1' });
63
+ const client = DynamoDBDocumentClient.from(ddbClient);
64
+
65
+ // Create table instance
66
+ const table = new Table({
67
+ name: 'MyTable',
68
+ client,
69
+ schema,
70
+ });
71
+
72
+ // Use it!
73
+ async function example() {
74
+ // Create
75
+ const user = await table.entities.User.put({
76
+ username: 'alice',
77
+ name: 'Alice Smith',
78
+ email: 'alice@example.com',
79
+ }).execute();
80
+
81
+ // Read
82
+ const retrieved = await table.entities.User.get({
83
+ username: 'alice',
84
+ }).execute();
85
+
86
+ // Update
87
+ await table.entities.User.update({ username: 'alice' })
88
+ .set('name', 'Alice Johnson')
89
+ .execute();
90
+
91
+ // Query
92
+ const users = await table.entities.User.query()
93
+ .where((attr, op) => op.eq(attr.username, 'alice'))
94
+ .execute();
95
+
96
+ // Delete
97
+ await table.entities.User.delete({ username: 'alice' }).execute();
98
+ }
99
+ ```
100
+
101
+ ## Core Concepts
102
+
103
+ ### Schema Definition
104
+
105
+ Define your data models with full type inference:
106
+
107
+ ```typescript
108
+ const schema = {
109
+ format: 'dynatable:1.0.0',
110
+ version: '1.0.0',
111
+
112
+ indexes: {
113
+ primary: { hash: 'PK', sort: 'SK' },
114
+ gsi1: { hash: 'GSI1PK', sort: 'GSI1SK' },
115
+ },
116
+
117
+ models: {
118
+ User: {
119
+ key: {
120
+ PK: { type: String, value: 'USER#${username}' },
121
+ SK: { type: String, value: 'USER#${username}' },
122
+ },
123
+ index: {
124
+ GSI1PK: { type: String, value: 'USER' },
125
+ GSI1SK: { type: String, value: 'USER#${username}' },
126
+ },
127
+ attributes: {
128
+ username: { type: String, required: true },
129
+ name: { type: String, required: true },
130
+ email: { type: String },
131
+ userId: { type: String, generate: 'ulid' },
132
+ followerCount: { type: Number, default: 0 },
133
+ // Nested object with typed schema
134
+ address: {
135
+ type: Object,
136
+ schema: {
137
+ street: { type: String },
138
+ city: { type: String, required: true },
139
+ country: { type: String, required: true },
140
+ },
141
+ },
142
+ // Typed array with item schema
143
+ tags: {
144
+ type: Array,
145
+ default: [],
146
+ items: { type: String },
147
+ },
148
+ },
149
+ },
150
+ },
151
+
152
+ params: {
153
+ timestamps: true, // Auto createdAt/updatedAt
154
+ isoDates: true, // Use ISO 8601 dates
155
+ cleanInternalKeys: false, // Hide PK/SK from results
156
+ },
157
+ } as const;
158
+ ```
159
+
160
+ ### Nested Objects and Arrays
161
+
162
+ Attributes support typed nested schemas for full TypeScript inference:
163
+
164
+ ```typescript
165
+ Story: {
166
+ attributes: {
167
+ // Typed array of objects
168
+ frames: {
169
+ type: Array,
170
+ default: [],
171
+ items: {
172
+ type: Object,
173
+ schema: {
174
+ url: { type: String, required: true },
175
+ duration: { type: Number },
176
+ mediaType: { type: String },
177
+ },
178
+ },
179
+ },
180
+ // Nested object with a typed schema
181
+ location: {
182
+ type: Object,
183
+ schema: {
184
+ city: { type: String },
185
+ country: { type: String },
186
+ lat: { type: Number },
187
+ lng: { type: Number },
188
+ },
189
+ },
190
+ },
191
+ }
192
+ ```
193
+
194
+ Use `ArrayItem<T>` to extract item types from array attributes:
195
+
196
+ ```typescript
197
+ import type { InferModelFromSchema, ArrayItem } from '@ftschopp/dynatable-core';
198
+
199
+ type StoryEntity = InferModelFromSchema<typeof schema, 'Story'>;
200
+ type StoryFrame = ArrayItem<StoryEntity['frames']>;
201
+ // → { url: string; duration?: number; mediaType?: string }
202
+ ```
203
+
204
+ ### Type Inference
205
+
206
+ Extract types from your schema:
207
+
208
+ ```typescript
209
+ import type {
210
+ InferModel,
211
+ InferInput,
212
+ InferKeyInput,
213
+ InferModelFromSchema,
214
+ InferInputFromSchema,
215
+ ArrayItem,
216
+ } from '@ftschopp/dynatable-core';
217
+
218
+ // Preferred: infer from the full schema (timestamps included automatically)
219
+ type User = InferModelFromSchema<typeof schema, 'User'>;
220
+ // { username: string; name: string; email?: string; userId: string; followerCount: number; createdAt: string; updatedAt: string }
221
+
222
+ type UserInput = InferInputFromSchema<typeof schema, 'User'>;
223
+ // { username: string; name: string; email?: string; followerCount?: number }
224
+
225
+ // Full model type (deprecated — use InferModelFromSchema)
226
+ type UserLegacy = InferModel<typeof schema.models.User>;
227
+
228
+ // Input type (deprecated — use InferInputFromSchema)
229
+ type UserInputLegacy = InferInput<typeof schema.models.User>;
230
+
231
+ // Key input type (only key template variables)
232
+ type UserKey = InferKeyInput<typeof schema.models.User>;
233
+ // { username: string }
234
+
235
+ // Extract item type from an array attribute
236
+ type StoryEntity = InferModelFromSchema<typeof schema, 'Story'>;
237
+ type StoryFrame = ArrayItem<StoryEntity['frames']>;
238
+ // → { url: string; duration?: number; mediaType?: string }
239
+ ```
240
+
241
+ ### Builder Operations
242
+
243
+ All operations use the immutable builder pattern:
244
+
245
+ ```typescript
246
+ // GET - Retrieve item
247
+ const user = await table.entities.User.get({ username: 'alice' })
248
+ .select(['name', 'email'])
249
+ .consistentRead()
250
+ .execute();
251
+
252
+ // PUT - Insert/replace item
253
+ await table.entities.User.put({
254
+ username: 'alice',
255
+ name: 'Alice',
256
+ email: 'alice@example.com',
257
+ })
258
+ .ifNotExists()
259
+ .returning('ALL_OLD')
260
+ .execute();
261
+
262
+ // UPDATE - Modify attributes
263
+ await table.entities.User.update({ username: 'alice' })
264
+ .set('name', 'Alice Johnson')
265
+ .add('followerCount', 1)
266
+ .remove('email')
267
+ .returning('ALL_NEW')
268
+ .where((attr, op) => op.gt(attr.followerCount, 0))
269
+ .execute();
270
+
271
+ // DELETE - Remove item
272
+ await table.entities.User.delete({ username: 'alice' })
273
+ .returning('ALL_OLD')
274
+ .where((attr, op) => op.exists(attr.email))
275
+ .execute();
276
+
277
+ // QUERY - Query with conditions
278
+ const photos = await table.entities.Photo.query()
279
+ .where((attr, op) =>
280
+ op.and(
281
+ op.eq(attr.username, 'alice'),
282
+ op.gt(attr.likesCount, 10)
283
+ )
284
+ )
285
+ .limit(20)
286
+ .scanIndexForward(false)
287
+ .execute();
288
+
289
+ // SCAN - Full table scan with filter
290
+ const activeUsers = await table.entities.User.scan()
291
+ .where((attr, op) => op.gt(attr.followerCount, 1000))
292
+ .limit(50)
293
+ .execute();
294
+
295
+ // BATCH GET - Retrieve multiple items
296
+ const users = await table.entities.User.batchGet([
297
+ { username: 'alice' },
298
+ { username: 'bob' },
299
+ { username: 'charlie' },
300
+ ]).execute();
301
+
302
+ // BATCH WRITE - Write multiple items
303
+ await table.entities.User.batchWrite([
304
+ { username: 'alice', name: 'Alice', email: 'alice@example.com' },
305
+ { username: 'bob', name: 'Bob', email: 'bob@example.com' },
306
+ ]).execute();
307
+ ```
308
+
309
+ ### Transactions
310
+
311
+ Atomic operations across multiple items:
312
+
313
+ ```typescript
314
+ // TransactWrite - Atomic writes
315
+ await table.transactWrite()
316
+ .addPut(
317
+ table.entities.Like.put({
318
+ photoId: 'photo1',
319
+ likingUsername: 'alice',
320
+ })
321
+ .ifNotExists()
322
+ .dbParams()
323
+ )
324
+ .addUpdate(
325
+ table.entities.Photo.update({ photoId: 'photo1' })
326
+ .add('likesCount', 1)
327
+ .dbParams()
328
+ )
329
+ .execute();
330
+
331
+ // TransactGet - Atomic reads
332
+ const result = await table.transactGet()
333
+ .addGet(table.entities.User.get({ username: 'alice' }).dbParams())
334
+ .addGet(table.entities.Photo.get({ photoId: 'photo1' }).dbParams())
335
+ .execute();
336
+
337
+ const [user, photo] = result.items;
338
+ ```
339
+
340
+ ## Available Operators
341
+
342
+ Build complex conditions with type-safe operators:
343
+
344
+ ### Comparison
345
+ - `eq(attr, value)` - Equals
346
+ - `ne(attr, value)` - Not equals
347
+ - `lt(attr, value)` - Less than
348
+ - `lte(attr, value)` - Less than or equal
349
+ - `gt(attr, value)` - Greater than
350
+ - `gte(attr, value)` - Greater than or equal
351
+ - `between(attr, low, high)` - Between values
352
+
353
+ ### String
354
+ - `beginsWith(attr, prefix)` - Begins with prefix
355
+ - `contains(attr, value)` - Contains value (strings, sets, lists)
356
+
357
+ ### Existence
358
+ - `exists(attr)` - Attribute exists
359
+ - `notExists(attr)` - Attribute doesn't exist
360
+
361
+ ### Advanced
362
+ - `attributeType(attr, type)` - Check attribute type ('S', 'N', 'M', 'L', etc.)
363
+ - `in(attr, values[])` - Value in array
364
+ - `size(attr)` - Get size, returns object with `.eq()`, `.gt()`, etc.
365
+
366
+ ### Logical
367
+ - `and(...conditions)` - Combine with AND
368
+ - `or(...conditions)` - Combine with OR
369
+ - `not(condition)` - Negate condition
370
+
371
+ ### Examples
372
+
373
+ ```typescript
374
+ // Exists check
375
+ await table.entities.User.update({ username: 'alice' })
376
+ .set('email', 'alice@example.com')
377
+ .where((attr, op) => op.notExists(attr.email))
378
+ .execute();
379
+
380
+ // Contains
381
+ const users = await table.entities.User.query()
382
+ .where((attr, op) =>
383
+ op.and(
384
+ op.eq(attr.username, 'alice'),
385
+ op.contains(attr.tags, 'premium')
386
+ )
387
+ )
388
+ .execute();
389
+
390
+ // IN operator
391
+ const activeUsers = await table.entities.User.scan()
392
+ .where((attr, op) => op.in(attr.status, ['active', 'pending']))
393
+ .execute();
394
+
395
+ // Size function
396
+ const posts = await table.entities.Post.query()
397
+ .where((attr, op) =>
398
+ op.and(
399
+ op.eq(attr.userId, 'alice'),
400
+ op.size(attr.tags).gte(3)
401
+ )
402
+ )
403
+ .execute();
404
+
405
+ // Complex nested conditions
406
+ await table.entities.Photo.query()
407
+ .where((attr, op) =>
408
+ op.and(
409
+ op.eq(attr.username, 'alice'),
410
+ op.or(
411
+ op.gt(attr.likesCount, 100),
412
+ op.and(
413
+ op.gt(attr.commentCount, 50),
414
+ op.exists(attr.featured)
415
+ )
416
+ )
417
+ )
418
+ )
419
+ .execute();
420
+ ```
421
+
422
+ ## DynamoDB Logger
423
+
424
+ Debug your DynamoDB operations:
425
+
426
+ ```typescript
427
+ import { createDynamoDBLogger } from '@ftschopp/dynatable-core';
428
+
429
+ const logger = createDynamoDBLogger({
430
+ enabled: true,
431
+ logParams: true,
432
+ logResponse: false,
433
+ });
434
+
435
+ const table = new Table({
436
+ name: 'MyTable',
437
+ client,
438
+ schema,
439
+ logger, // Attach logger
440
+ });
441
+
442
+ // All operations now logged to console
9
443
  ```
10
444
 
445
+ ## Pagination
446
+
447
+ Built-in pagination support:
448
+
449
+ ```typescript
450
+ // Execute with pagination
451
+ const page1 = await table.entities.Post.query()
452
+ .where((attr, op) => op.eq(attr.userId, 'alice'))
453
+ .limit(20)
454
+ .executeWithPagination();
455
+
456
+ // Get next page
457
+ if (page1.lastEvaluatedKey) {
458
+ const page2 = await table.entities.Post.query()
459
+ .where((attr, op) => op.eq(attr.userId, 'alice'))
460
+ .startFrom(page1.lastEvaluatedKey)
461
+ .limit(20)
462
+ .executeWithPagination();
463
+ }
464
+ ```
465
+
466
+ ## API Reference
467
+
468
+ ### Core Exports
469
+
470
+ ```typescript
471
+ export {
472
+ Table, // Main Table class
473
+ type SchemaDefinition, // Schema type
474
+ type ModelDefinition, // Model type
475
+ type AttributeDefinition, // Union of all attribute types
476
+ type ScalarAttributeDefinition, // String/Number/Boolean/Date attribute
477
+ type ObjectAttributeDefinition, // Nested object attribute with schema
478
+ type ArrayAttributeDefinition, // Typed array attribute with items
479
+ type PrimaryKeyDefinition, // PK + SK key definition
480
+ type KeyDefinition, // Single key definition
481
+ type IndexDefinition, // Index (hash + optional sort)
482
+ type IndexesDefinition, // All table indexes
483
+ type SchemaParams, // Global schema params
484
+ type InferModel, // Infer model type (deprecated)
485
+ type InferInput, // Infer input type (deprecated)
486
+ type InferKeyInput, // Infer key type
487
+ type InferModelFromSchema, // Infer from full schema (preferred)
488
+ type InferInputFromSchema, // Infer input from full schema (preferred)
489
+ type TimestampFields, // createdAt/updatedAt fields type
490
+ type ArrayItem, // Extract item type from array attribute
491
+ createDynamoDBLogger, // Logger factory
492
+ type DynamoDBLogger, // Logger type
493
+ type DynamoDBLoggerConfig, // Logger config
494
+ };
495
+ ```
496
+
497
+ ### Builder Types
498
+
499
+ Each builder type is exported for advanced use cases:
500
+
501
+ - `GetBuilder`, `PutBuilder`, `UpdateBuilder`, `DeleteBuilder`
502
+ - `QueryBuilder`, `ScanBuilder`
503
+ - `BatchGetBuilder`, `BatchWriteBuilder`
504
+ - `TransactWriteBuilder`, `TransactGetBuilder`
505
+ - `Condition`, `OpBuilder`, `AttrBuilder`, `SizeRef`
506
+
507
+ ## Requirements
508
+
509
+ - Node.js >= 18
510
+ - TypeScript >= 5.0 (recommended)
511
+ - AWS SDK v3 (`@aws-sdk/client-dynamodb`, `@aws-sdk/lib-dynamodb`)
512
+
513
+ ## Dependencies
514
+
515
+ - `@aws-sdk/client-dynamodb` ^3.965.0
516
+ - `@aws-sdk/lib-dynamodb` ^3.965.0
517
+ - `zod` ^4.3.5 - Runtime validation
518
+ - `ulid` ^3.0.2 - ULID generation
519
+ - `ramda` ^0.32.0 - Functional utilities
520
+
11
521
  ## Documentation
12
522
 
13
- See the [main repository](https://github.com/ftschopp/dynatable) for full documentation and examples.
523
+ For complete documentation, examples, and guides, visit the [main repository](https://github.com/ftschopp/dynatable).
524
+
525
+ ## Testing
526
+
527
+ The library includes comprehensive test coverage with Jest:
528
+
529
+ ```bash
530
+ npm test
531
+ ```
14
532
 
15
533
  ## License
16
534
 
17
535
  MIT
536
+
537
+ ## Contributing
538
+
539
+ Contributions are welcome! Please see the [main repository](https://github.com/ftschopp/dynatable) for contribution guidelines.
540
+
541
+ ## Related Packages
542
+
543
+ - [@ftschopp/dynatable-migrations](https://www.npmjs.com/package/@ftschopp/dynatable-migrations) - Database migration tool for schema evolution
@@ -1,11 +1,16 @@
1
+ import type { DeleteCommandInput } from '@aws-sdk/lib-dynamodb';
1
2
  import { OperationBuilder } from '../shared';
2
3
  /**
3
4
  * Builder interface for DynamoDB DeleteItem operations
4
5
  */
5
- export interface DeleteBuilder<Model> extends OperationBuilder<Model> {
6
+ export interface DeleteBuilder<Model> extends Omit<OperationBuilder<Model>, 'dbParams'> {
6
7
  /**
7
8
  * Configures what values should be returned after the delete operation
8
9
  */
9
10
  returning(mode: 'NONE' | 'ALL_OLD'): DeleteBuilder<Model>;
11
+ /**
12
+ * Converts the builder state to DynamoDB DeleteItem parameters
13
+ */
14
+ dbParams(): DeleteCommandInput;
10
15
  }
11
16
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/delete/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK,CAAE,SAAQ,gBAAgB,CAAC,KAAK,CAAC;IACnE;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;CAC3D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/delete/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,aAAa,CAAC,KAAK,CAAE,SAAQ,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACrF;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IAE1D;;OAEG;IACH,QAAQ,IAAI,kBAAkB,CAAC;CAChC"}
@@ -1,9 +1,10 @@
1
+ import type { GetCommandInput } from '@aws-sdk/lib-dynamodb';
1
2
  import { ExecutableBuilder } from '../shared';
2
3
  /**
3
4
  * Builder for DynamoDB GetItem operations.
4
5
  * Supports projection, consistent read, and inspection of the final parameters.
5
6
  */
6
- export interface GetBuilder<KeyInput, Model> extends ExecutableBuilder<Model | undefined> {
7
+ export interface GetBuilder<KeyInput, Model> extends Omit<ExecutableBuilder<Model | undefined>, 'dbParams'> {
7
8
  /**
8
9
  * Adds a projection expression to only return specific attributes.
9
10
  * Returns a new immutable builder.
@@ -24,5 +25,9 @@ export interface GetBuilder<KeyInput, Model> extends ExecutableBuilder<Model | u
24
25
  * - NONE: No consumed capacity data returned (default)
25
26
  */
26
27
  returnConsumedCapacity(mode: 'INDEXES' | 'TOTAL' | 'NONE'): GetBuilder<KeyInput, Model>;
28
+ /**
29
+ * Converts the builder state to DynamoDB GetItem parameters
30
+ */
31
+ dbParams(): GetCommandInput;
27
32
  }
28
33
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/get/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C;;;GAGG;AACH,MAAM,WAAW,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAE,SAAQ,iBAAiB,CAAC,KAAK,GAAG,SAAS,CAAC;IACvF;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAE5D;;;OAGG;IACH,cAAc,IAAI,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAE9C;;;;;;;;OAQG;IACH,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;CACzF"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/get/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C;;;GAGG;AACH,MAAM,WAAW,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAE,SAAQ,IAAI,CAAC,iBAAiB,CAAC,KAAK,GAAG,SAAS,CAAC,EAAE,UAAU,CAAC;IACzG;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAE5D;;;OAGG;IACH,cAAc,IAAI,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAE9C;;;;;;;;OAQG;IACH,sBAAsB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAExF;;OAEG;IACH,QAAQ,IAAI,eAAe,CAAC;CAC7B"}
@@ -1,8 +1,9 @@
1
+ import type { PutCommandInput } from '@aws-sdk/lib-dynamodb';
1
2
  import { OperationBuilder } from '../shared';
2
3
  /**
3
4
  * Builder interface for DynamoDB PutItem operations
4
5
  */
5
- export interface PutBuilder<Model> extends OperationBuilder<Model> {
6
+ export interface PutBuilder<Model> extends Omit<OperationBuilder<Model>, 'dbParams'> {
6
7
  /**
7
8
  * Adds a condition that the item must not exist (checks pk and sk)
8
9
  */
@@ -13,5 +14,9 @@ export interface PutBuilder<Model> extends OperationBuilder<Model> {
13
14
  * - ALL_OLD: Returns the item as it was before being replaced (if it existed)
14
15
  */
15
16
  returning(mode: 'NONE' | 'ALL_OLD'): PutBuilder<Model>;
17
+ /**
18
+ * Converts the builder state to DynamoDB PutItem parameters
19
+ */
20
+ dbParams(): PutCommandInput;
16
21
  }
17
22
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/put/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,KAAK,CAAE,SAAQ,gBAAgB,CAAC,KAAK,CAAC;IAChE;;OAEG;IACH,WAAW,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAEjC;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;CACxD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/builders/put/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,KAAK,CAAE,SAAQ,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAClF;;OAEG;IACH,WAAW,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAEjC;;;;OAIG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAEvD;;OAEG;IACH,QAAQ,IAAI,eAAe,CAAC;CAC7B"}
@@ -5,5 +5,5 @@ import { DynamoDBLogger } from '../../utils/dynamodb-logger';
5
5
  /**
6
6
  * Creates a QueryBuilder for a table
7
7
  */
8
- export declare function createQueryBuilder<Model, M extends ModelDefinition = any>(tableName: string, client: DynamoDBClient, model?: M, logger?: DynamoDBLogger): QueryBuilder<Model, M>;
8
+ export declare function createQueryBuilder<Model>(tableName: string, client: DynamoDBClient, model?: ModelDefinition, logger?: DynamoDBLogger): QueryBuilder<Model>;
9
9
  //# sourceMappingURL=create-query-builder.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-query-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/query/create-query-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAK1D,OAAO,EAAE,YAAY,EAA8B,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAmT7D;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,CAAC,SAAS,eAAe,GAAG,GAAG,EACvE,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,cAAc,EACtB,KAAK,CAAC,EAAE,CAAC,EACT,MAAM,CAAC,EAAE,cAAc,GACtB,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CA4BxB"}
1
+ {"version":3,"file":"create-query-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/query/create-query-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAK1D,OAAO,EAAE,YAAY,EAA8B,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAiT7D;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EACtC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,cAAc,EACtB,KAAK,CAAC,EAAE,eAAe,EACvB,MAAM,CAAC,EAAE,cAAc,GACtB,YAAY,CAAC,KAAK,CAAC,CA4BrB"}