betterddb 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,11 +1,11 @@
1
- import { ZodSchema } from 'zod';
2
- import { DynamoDB } from 'aws-sdk';
1
+ import { z } from 'zod';
3
2
  import { QueryBuilder } from './builders/query-builder';
4
3
  import { ScanBuilder } from './builders/scan-builder';
5
4
  import { UpdateBuilder } from './builders/update-builder';
6
5
  import { CreateBuilder } from './builders/create-builder';
7
6
  import { GetBuilder } from './builders/get-builder';
8
7
  import { DeleteBuilder } from './builders/delete-builder';
8
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
9
9
  export type PrimaryKeyValue = string | number;
10
10
  /**
11
11
  * A key definition can be either a simple key (a property name)
@@ -60,11 +60,11 @@ export interface KeysConfig<T> {
60
60
  * Options for initializing BetterDDB.
61
61
  */
62
62
  export interface BetterDDBOptions<T> {
63
- schema: ZodSchema<T>;
63
+ schema: z.AnyZodObject;
64
64
  tableName: string;
65
65
  entityName: string;
66
66
  keys: KeysConfig<T>;
67
- client: DynamoDB.DocumentClient;
67
+ client: DynamoDBDocumentClient;
68
68
  /**
69
69
  * If true, automatically inject timestamp fields:
70
70
  * - On create, sets both `createdAt` and `updatedAt`
@@ -78,17 +78,17 @@ export interface BetterDDBOptions<T> {
78
78
  * BetterDDB is a definition-based DynamoDB wrapper library.
79
79
  */
80
80
  export declare class BetterDDB<T> {
81
- protected schema: ZodSchema<T>;
81
+ protected schema: z.AnyZodObject;
82
82
  protected tableName: string;
83
83
  protected entityName: string;
84
- protected client: DynamoDB.DocumentClient;
84
+ protected client: DynamoDBDocumentClient;
85
85
  protected keys: KeysConfig<T>;
86
86
  protected autoTimestamps: boolean;
87
87
  constructor(options: BetterDDBOptions<T>);
88
88
  getKeys(): KeysConfig<T>;
89
89
  getTableName(): string;
90
- getClient(): DynamoDB.DocumentClient;
91
- getSchema(): ZodSchema<T>;
90
+ getClient(): DynamoDBDocumentClient;
91
+ getSchema(): z.AnyZodObject;
92
92
  getAutoTimestamps(): boolean;
93
93
  protected getKeyValue(def: KeyDefinition<T>, rawKey: Partial<T>): string;
94
94
  /**
@@ -1,4 +1,4 @@
1
- import { DynamoDB } from 'aws-sdk';
1
+ import { TransactWriteItem } from '@aws-sdk/client-dynamodb';
2
2
  import { BetterDDB } from '../betterddb';
3
3
  export declare class CreateBuilder<T> {
4
4
  private parent;
@@ -6,8 +6,8 @@ export declare class CreateBuilder<T> {
6
6
  private extraTransactItems;
7
7
  constructor(parent: BetterDDB<T>, item: T);
8
8
  execute(): Promise<T>;
9
- transactWrite(ops: DynamoDB.DocumentClient.TransactWriteItemList | DynamoDB.DocumentClient.TransactWriteItem): this;
10
- toTransactPut(): DynamoDB.DocumentClient.TransactWriteItem;
9
+ transactWrite(ops: TransactWriteItem[] | TransactWriteItem): this;
10
+ toTransactPut(): TransactWriteItem;
11
11
  then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
12
12
  catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null): Promise<T | TResult>;
13
13
  finally(onfinally?: (() => void) | null): Promise<T>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CreateBuilder = void 0;
4
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
4
5
  class CreateBuilder {
5
6
  constructor(parent, item) {
6
7
  this.parent = parent;
@@ -13,9 +14,9 @@ class CreateBuilder {
13
14
  const myTransactItem = this.toTransactPut();
14
15
  // Combine with extra transaction items.
15
16
  const allItems = [...this.extraTransactItems, myTransactItem];
16
- await this.parent.getClient().transactWrite({
17
+ await this.parent.getClient().send(new lib_dynamodb_1.TransactWriteCommand({
17
18
  TransactItems: allItems
18
- }).promise();
19
+ }));
19
20
  // After transaction, retrieve the updated item.
20
21
  const result = await this.parent.get(this.item).execute();
21
22
  if (result === null) {
@@ -38,10 +39,10 @@ class CreateBuilder {
38
39
  // Compute and merge index attributes.
39
40
  const indexAttributes = this.parent.buildIndexes(validated);
40
41
  finalItem = { ...finalItem, ...indexAttributes };
41
- await this.parent.getClient().put({
42
+ await this.parent.getClient().send(new lib_dynamodb_1.PutCommand({
42
43
  TableName: this.parent.getTableName(),
43
44
  Item: finalItem
44
- }).promise();
45
+ }));
45
46
  return validated;
46
47
  }
47
48
  }
@@ -1,5 +1,5 @@
1
- import { DynamoDB } from 'aws-sdk';
2
1
  import { BetterDDB } from '../betterddb';
2
+ import { TransactWriteItem } from '@aws-sdk/client-dynamodb';
3
3
  export declare class DeleteBuilder<T> {
4
4
  private parent;
5
5
  private key;
@@ -11,8 +11,8 @@ export declare class DeleteBuilder<T> {
11
11
  */
12
12
  withCondition(expression: string, attributeValues: Record<string, any>): this;
13
13
  execute(): Promise<void>;
14
- transactWrite(ops: DynamoDB.DocumentClient.TransactWriteItemList | DynamoDB.DocumentClient.TransactWriteItem): this;
15
- toTransactDelete(): DynamoDB.DocumentClient.TransactWriteItem;
14
+ transactWrite(ops: TransactWriteItem[] | TransactWriteItem): this;
15
+ toTransactDelete(): TransactWriteItem;
16
16
  then<TResult1 = void, TResult2 = never>(onfulfilled?: ((value: void) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
17
17
  catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null): Promise<void | TResult>;
18
18
  finally(onfinally?: (() => void) | null): Promise<void>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DeleteBuilder = void 0;
4
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
4
5
  class DeleteBuilder {
5
6
  constructor(parent, key) {
6
7
  this.parent = parent;
@@ -26,9 +27,9 @@ class DeleteBuilder {
26
27
  const myTransactItem = this.toTransactDelete();
27
28
  // Combine with extra transaction items.
28
29
  const allItems = [...this.extraTransactItems, myTransactItem];
29
- await this.parent.getClient().transactWrite({
30
+ await this.parent.getClient().send(new lib_dynamodb_1.TransactWriteCommand({
30
31
  TransactItems: allItems
31
- }).promise();
32
+ }));
32
33
  // After transaction, retrieve the updated item.
33
34
  const result = await this.parent.get(this.key).execute();
34
35
  if (result === null) {
@@ -44,7 +45,7 @@ class DeleteBuilder {
44
45
  params.ConditionExpression = this.condition.expression;
45
46
  params.ExpressionAttributeValues = this.condition.attributeValues;
46
47
  }
47
- await this.parent.getClient().delete(params).promise();
48
+ await this.parent.getClient().send(new lib_dynamodb_1.DeleteCommand(params));
48
49
  }
49
50
  }
50
51
  transactWrite(ops) {
@@ -1,5 +1,5 @@
1
- import { DynamoDB } from 'aws-sdk';
2
1
  import { BetterDDB } from '../betterddb';
2
+ import { TransactGetItem } from '@aws-sdk/client-dynamodb';
3
3
  export declare class GetBuilder<T> {
4
4
  private parent;
5
5
  private key;
@@ -12,8 +12,8 @@ export declare class GetBuilder<T> {
12
12
  */
13
13
  withProjection(attributes: (keyof T)[]): this;
14
14
  execute(): Promise<T | null>;
15
- transactGet(ops: DynamoDB.DocumentClient.TransactGetItemList | DynamoDB.DocumentClient.TransactGetItem): this;
16
- toTransactGet(): DynamoDB.DocumentClient.TransactGetItem;
15
+ transactGet(ops: TransactGetItem[] | TransactGetItem): this;
16
+ toTransactGet(): TransactGetItem;
17
17
  then<TResult1 = T | null, TResult2 = never>(onfulfilled?: ((value: T | null) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
18
18
  catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null): Promise<T | null | TResult>;
19
19
  finally(onfinally?: (() => void) | null): Promise<T | null>;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GetBuilder = void 0;
4
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
4
5
  class GetBuilder {
5
6
  constructor(parent, key) {
6
7
  this.parent = parent;
@@ -24,9 +25,9 @@ class GetBuilder {
24
25
  const myTransactItem = this.toTransactGet();
25
26
  // Combine with extra transaction items.
26
27
  const allItems = [...this.extraTransactItems, myTransactItem];
27
- await this.parent.getClient().transactGet({
28
+ await this.parent.getClient().send(new lib_dynamodb_1.TransactGetCommand({
28
29
  TransactItems: allItems
29
- }).promise();
30
+ }));
30
31
  // After transaction, retrieve the updated item.
31
32
  const result = await this.parent.get(this.key).execute();
32
33
  return result;
@@ -40,7 +41,7 @@ class GetBuilder {
40
41
  params.ProjectionExpression = this.projectionExpression;
41
42
  params.ExpressionAttributeNames = this.expressionAttributeNames;
42
43
  }
43
- const result = await this.parent.getClient().get(params).promise();
44
+ const result = await this.parent.getClient().send(new lib_dynamodb_1.GetCommand(params));
44
45
  if (!result.Item)
45
46
  return null;
46
47
  return this.parent.getSchema().parse(result.Item);
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.QueryBuilder = void 0;
4
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
4
5
  class QueryBuilder {
5
6
  constructor(parent, key) {
6
7
  this.parent = parent;
@@ -89,7 +90,7 @@ class QueryBuilder {
89
90
  if (this.filters.length > 0) {
90
91
  params.FilterExpression = this.filters.join(' AND ');
91
92
  }
92
- const result = await this.parent.getClient().query(params).promise();
93
+ const result = await this.parent.getClient().send(new lib_dynamodb_1.QueryCommand(params));
93
94
  return this.parent.getSchema().array().parse(result.Items);
94
95
  }
95
96
  // Thenable implementation.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ScanBuilder = void 0;
4
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
4
5
  class ScanBuilder {
5
6
  constructor(parent) {
6
7
  this.parent = parent;
@@ -59,7 +60,7 @@ class ScanBuilder {
59
60
  if (this.filters.length > 0) {
60
61
  params.FilterExpression = this.filters.join(' AND ');
61
62
  }
62
- const result = await this.parent.getClient().scan(params).promise();
63
+ const result = await this.parent.getClient().send(new lib_dynamodb_1.ScanCommand(params));
63
64
  return this.parent.getSchema().array().parse(result.Items);
64
65
  }
65
66
  // Thenable implementation.
@@ -1,5 +1,5 @@
1
- import { DynamoDB } from 'aws-sdk';
2
1
  import { BetterDDB } from '../betterddb';
2
+ import { TransactWriteItem } from '@aws-sdk/client-dynamodb';
3
3
  export declare class UpdateBuilder<T> {
4
4
  private parent;
5
5
  private key;
@@ -19,7 +19,7 @@ export declare class UpdateBuilder<T> {
19
19
  /**
20
20
  * Specifies additional transaction items to include when executing this update as a transaction.
21
21
  */
22
- transactWrite(ops: DynamoDB.DocumentClient.TransactWriteItemList | DynamoDB.DocumentClient.TransactWriteItem): this;
22
+ transactWrite(ops: TransactWriteItem[] | TransactWriteItem): this;
23
23
  /**
24
24
  * Builds the update expression and associated maps.
25
25
  */
@@ -27,7 +27,7 @@ export declare class UpdateBuilder<T> {
27
27
  /**
28
28
  * Returns a transaction update item that can be included in a transactWrite call.
29
29
  */
30
- toTransactUpdate(): DynamoDB.DocumentClient.TransactWriteItem;
30
+ toTransactUpdate(): TransactWriteItem;
31
31
  /**
32
32
  * Commits the update immediately by calling the parent's update method.
33
33
  */
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UpdateBuilder = void 0;
4
+ const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
4
5
  class UpdateBuilder {
5
6
  // Reference to the parent BetterDDB instance and key.
6
7
  constructor(parent, key, expectedVersion) {
@@ -170,9 +171,9 @@ class UpdateBuilder {
170
171
  const myTransactItem = this.toTransactUpdate();
171
172
  // Combine with extra transaction items.
172
173
  const allItems = [...this.extraTransactItems, myTransactItem];
173
- await this.parent.getClient().transactWrite({
174
+ await this.parent.getClient().send(new lib_dynamodb_1.TransactWriteCommand({
174
175
  TransactItems: allItems
175
- }).promise();
176
+ }));
176
177
  // After transaction, retrieve the updated item.
177
178
  const result = await this.parent.get(this.key).execute();
178
179
  if (result === null) {
@@ -194,7 +195,7 @@ class UpdateBuilder {
194
195
  if (this.condition && this.condition.expression) {
195
196
  params.ConditionExpression = this.condition.expression;
196
197
  }
197
- const result = await this.parent.getClient().update(params).promise();
198
+ const result = await this.parent.getClient().send(new lib_dynamodb_1.UpdateCommand(params));
198
199
  if (!result.Attributes) {
199
200
  throw new Error('No attributes returned after update');
200
201
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "betterddb",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "A definition-based DynamoDB wrapper library that provides a schema-driven and fully typesafe DAL.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -28,7 +28,8 @@
28
28
  "author": "R.R. Wang",
29
29
  "license": "MIT",
30
30
  "dependencies": {
31
- "aws-sdk": "^2.1370.0",
31
+ "@aws-sdk/lib-dynamodb": "^3.744.0",
32
+ "@aws-sdk/client-dynamodb": "^3.744.0",
32
33
  "zod": "^3.21.4"
33
34
  },
34
35
  "devDependencies": {
package/src/betterddb.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { ZodSchema } from 'zod';
2
- import { DynamoDB } from 'aws-sdk';
1
+ import { z, ZodSchema } from 'zod';
3
2
  import { QueryBuilder } from './builders/query-builder';
4
3
  import { ScanBuilder } from './builders/scan-builder';
5
4
  import { UpdateBuilder } from './builders/update-builder';
6
5
  import { CreateBuilder } from './builders/create-builder';
7
6
  import { GetBuilder } from './builders/get-builder';
8
7
  import { DeleteBuilder } from './builders/delete-builder';
8
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
9
9
 
10
10
  export type PrimaryKeyValue = string | number;
11
11
 
@@ -69,11 +69,11 @@ export interface KeysConfig<T> {
69
69
  * Options for initializing BetterDDB.
70
70
  */
71
71
  export interface BetterDDBOptions<T> {
72
- schema: ZodSchema<T>;
72
+ schema: z.AnyZodObject;
73
73
  tableName: string;
74
74
  entityName: string;
75
75
  keys: KeysConfig<T>;
76
- client: DynamoDB.DocumentClient;
76
+ client: DynamoDBDocumentClient;
77
77
  /**
78
78
  * If true, automatically inject timestamp fields:
79
79
  * - On create, sets both `createdAt` and `updatedAt`
@@ -88,10 +88,10 @@ export interface BetterDDBOptions<T> {
88
88
  * BetterDDB is a definition-based DynamoDB wrapper library.
89
89
  */
90
90
  export class BetterDDB<T> {
91
- protected schema: ZodSchema<T>;
91
+ protected schema: z.AnyZodObject;
92
92
  protected tableName: string;
93
93
  protected entityName: string;
94
- protected client: DynamoDB.DocumentClient;
94
+ protected client: DynamoDBDocumentClient;
95
95
  protected keys: KeysConfig<T>;
96
96
  protected autoTimestamps: boolean;
97
97
 
@@ -112,12 +112,12 @@ export class BetterDDB<T> {
112
112
  return this.tableName;
113
113
  }
114
114
 
115
- public getClient(): DynamoDB.DocumentClient {
115
+ public getClient(): DynamoDBDocumentClient {
116
116
  return this.client;
117
117
  }
118
118
 
119
119
 
120
- public getSchema(): ZodSchema<T> {
120
+ public getSchema(): z.AnyZodObject {
121
121
  return this.schema;
122
122
  }
123
123
 
@@ -1,8 +1,10 @@
1
- import { DynamoDB } from 'aws-sdk';
1
+
2
+ import { AttributeValue, Put, TransactWriteItem } from '@aws-sdk/client-dynamodb';
2
3
  import { BetterDDB } from '../betterddb';
4
+ import { PutCommand, TransactWriteCommand } from '@aws-sdk/lib-dynamodb';
3
5
 
4
6
  export class CreateBuilder<T> {
5
- private extraTransactItems: DynamoDB.DocumentClient.TransactWriteItemList = [];
7
+ private extraTransactItems: TransactWriteItem[] = [];
6
8
 
7
9
  constructor(private parent: BetterDDB<T>, private item: T) {}
8
10
 
@@ -12,9 +14,9 @@ export class CreateBuilder<T> {
12
14
  const myTransactItem = this.toTransactPut();
13
15
  // Combine with extra transaction items.
14
16
  const allItems = [...this.extraTransactItems, myTransactItem];
15
- await this.parent.getClient().transactWrite({
17
+ await this.parent.getClient().send(new TransactWriteCommand({
16
18
  TransactItems: allItems
17
- }).promise();
19
+ }));
18
20
  // After transaction, retrieve the updated item.
19
21
  const result = await this.parent.get(this.item).execute();
20
22
  if (result === null) {
@@ -32,23 +34,23 @@ export class CreateBuilder<T> {
32
34
  let finalItem = { ...validated };
33
35
 
34
36
  // Compute and merge primary key.
35
- const computedKeys = this.parent.buildKey(validated);
37
+ const computedKeys = this.parent.buildKey(validated as Partial<T>);
36
38
  finalItem = { ...finalItem, ...computedKeys };
37
39
 
38
40
  // Compute and merge index attributes.
39
- const indexAttributes = this.parent.buildIndexes(validated);
41
+ const indexAttributes = this.parent.buildIndexes(validated as Partial<T>);
40
42
  finalItem = { ...finalItem, ...indexAttributes };
41
43
 
42
- await this.parent.getClient().put({
44
+ await this.parent.getClient().send(new PutCommand({
43
45
  TableName: this.parent.getTableName(),
44
- Item: finalItem as DynamoDB.DocumentClient.PutItemInputAttributeMap
45
- }).promise();
46
+ Item: finalItem
47
+ }));
46
48
 
47
- return validated;
49
+ return validated as T;
48
50
  }
49
51
  }
50
52
 
51
- public transactWrite(ops: DynamoDB.DocumentClient.TransactWriteItemList | DynamoDB.DocumentClient.TransactWriteItem): this {
53
+ public transactWrite(ops: TransactWriteItem[] | TransactWriteItem): this {
52
54
  if (Array.isArray(ops)) {
53
55
  this.extraTransactItems.push(...ops);
54
56
  } else {
@@ -57,10 +59,10 @@ export class CreateBuilder<T> {
57
59
  return this;
58
60
  }
59
61
 
60
- public toTransactPut(): DynamoDB.DocumentClient.TransactWriteItem {
61
- const putItem: DynamoDB.DocumentClient.Put = {
62
+ public toTransactPut(): TransactWriteItem{
63
+ const putItem: Put = {
62
64
  TableName: this.parent.getTableName(),
63
- Item: this.item as DynamoDB.DocumentClient.PutItemInputAttributeMap,
65
+ Item: this.item as Record<string, AttributeValue>,
64
66
  };
65
67
  return { Put: putItem };
66
68
  }
@@ -1,9 +1,9 @@
1
- import { DynamoDB } from 'aws-sdk';
2
1
  import { BetterDDB } from '../betterddb';
3
-
2
+ import { TransactWriteItem, DeleteItemInput } from '@aws-sdk/client-dynamodb';
3
+ import { TransactWriteCommand, DeleteCommand } from '@aws-sdk/lib-dynamodb';
4
4
  export class DeleteBuilder<T> {
5
5
  private condition?: { expression: string; attributeValues: Record<string, any> };
6
- private extraTransactItems: DynamoDB.DocumentClient.TransactWriteItemList = [];
6
+ private extraTransactItems: TransactWriteItem[] = [];
7
7
  constructor(private parent: BetterDDB<T>, private key: Partial<T>) {}
8
8
 
9
9
  /**
@@ -25,16 +25,16 @@ export class DeleteBuilder<T> {
25
25
  const myTransactItem = this.toTransactDelete();
26
26
  // Combine with extra transaction items.
27
27
  const allItems = [...this.extraTransactItems, myTransactItem];
28
- await this.parent.getClient().transactWrite({
28
+ await this.parent.getClient().send(new TransactWriteCommand({
29
29
  TransactItems: allItems
30
- }).promise();
30
+ }));
31
31
  // After transaction, retrieve the updated item.
32
32
  const result = await this.parent.get(this.key).execute();
33
33
  if (result === null) {
34
34
  throw new Error('Item not found after transaction delete');
35
35
  }
36
36
  } else {
37
- const params: DynamoDB.DocumentClient.DeleteItemInput = {
37
+ const params: DeleteItemInput = {
38
38
  TableName: this.parent.getTableName(),
39
39
  Key: this.parent.buildKey(this.key)
40
40
  };
@@ -42,11 +42,11 @@ export class DeleteBuilder<T> {
42
42
  params.ConditionExpression = this.condition.expression;
43
43
  params.ExpressionAttributeValues = this.condition.attributeValues;
44
44
  }
45
- await this.parent.getClient().delete(params).promise();
45
+ await this.parent.getClient().send(new DeleteCommand(params));
46
46
  }
47
47
  }
48
48
 
49
- public transactWrite(ops: DynamoDB.DocumentClient.TransactWriteItemList | DynamoDB.DocumentClient.TransactWriteItem): this {
49
+ public transactWrite(ops: TransactWriteItem[] | TransactWriteItem): this {
50
50
  if (Array.isArray(ops)) {
51
51
  this.extraTransactItems.push(...ops);
52
52
  } else {
@@ -55,8 +55,8 @@ export class DeleteBuilder<T> {
55
55
  return this;
56
56
  }
57
57
 
58
- public toTransactDelete(): DynamoDB.DocumentClient.TransactWriteItem {
59
- const deleteItem: DynamoDB.DocumentClient.Delete = {
58
+ public toTransactDelete(): TransactWriteItem {
59
+ const deleteItem: DeleteItemInput = {
60
60
  TableName: this.parent.getTableName(),
61
61
  Key: this.parent.buildKey(this.key)
62
62
  };
@@ -1,10 +1,10 @@
1
- import { DynamoDB } from 'aws-sdk';
2
1
  import { BetterDDB } from '../betterddb';
3
-
2
+ import { TransactGetCommand, GetCommand } from '@aws-sdk/lib-dynamodb';
3
+ import { GetItemInput, TransactGetItem } from '@aws-sdk/client-dynamodb';
4
4
  export class GetBuilder<T> {
5
5
  private projectionExpression?: string;
6
6
  private expressionAttributeNames: Record<string, string> = {};
7
- private extraTransactItems: DynamoDB.DocumentClient.TransactGetItemList = [];
7
+ private extraTransactItems: TransactGetItem[] = [];
8
8
  constructor(private parent: BetterDDB<T>, private key: Partial<T>) {}
9
9
 
10
10
  /**
@@ -24,14 +24,14 @@ export class GetBuilder<T> {
24
24
  const myTransactItem = this.toTransactGet();
25
25
  // Combine with extra transaction items.
26
26
  const allItems = [...this.extraTransactItems, myTransactItem];
27
- await this.parent.getClient().transactGet({
27
+ await this.parent.getClient().send(new TransactGetCommand({
28
28
  TransactItems: allItems
29
- }).promise();
29
+ }));
30
30
  // After transaction, retrieve the updated item.
31
31
  const result = await this.parent.get(this.key).execute();
32
32
  return result;
33
33
  } else {
34
- const params: DynamoDB.DocumentClient.GetItemInput = {
34
+ const params: GetItemInput = {
35
35
  TableName: this.parent.getTableName(),
36
36
  Key: this.parent.buildKey(this.key)
37
37
  };
@@ -39,13 +39,13 @@ export class GetBuilder<T> {
39
39
  params.ProjectionExpression = this.projectionExpression;
40
40
  params.ExpressionAttributeNames = this.expressionAttributeNames;
41
41
  }
42
- const result = await this.parent.getClient().get(params).promise();
42
+ const result = await this.parent.getClient().send(new GetCommand(params));
43
43
  if (!result.Item) return null;
44
- return this.parent.getSchema().parse(result.Item);
44
+ return this.parent.getSchema().parse(result.Item) as T;
45
45
  }
46
46
  }
47
47
 
48
- public transactGet(ops: DynamoDB.DocumentClient.TransactGetItemList | DynamoDB.DocumentClient.TransactGetItem): this {
48
+ public transactGet(ops: TransactGetItem[] | TransactGetItem): this {
49
49
  if (Array.isArray(ops)) {
50
50
  this.extraTransactItems.push(...ops);
51
51
  } else {
@@ -54,8 +54,8 @@ export class GetBuilder<T> {
54
54
  return this;
55
55
  }
56
56
 
57
- public toTransactGet(): DynamoDB.DocumentClient.TransactGetItem {
58
- const getItem: DynamoDB.DocumentClient.Get = {
57
+ public toTransactGet(): TransactGetItem {
58
+ const getItem: GetItemInput = {
59
59
  TableName: this.parent.getTableName(),
60
60
  Key: this.parent.buildKey(this.key)
61
61
  };
@@ -1,4 +1,4 @@
1
- import { DynamoDB } from 'aws-sdk';
1
+ import { QueryCommand, QueryCommandInput } from '@aws-sdk/lib-dynamodb';
2
2
  import { BetterDDB } from '../betterddb';
3
3
 
4
4
  export class QueryBuilder<T> {
@@ -90,7 +90,7 @@ export class QueryBuilder<T> {
90
90
  }
91
91
 
92
92
  // If any filters were added, set them as FilterExpression.
93
- const params: DynamoDB.DocumentClient.QueryInput = {
93
+ const params: QueryCommandInput = {
94
94
  TableName: this.parent.getTableName(),
95
95
  KeyConditionExpression: keyConditionExpression,
96
96
  ExpressionAttributeNames: this.expressionAttributeNames,
@@ -105,8 +105,8 @@ export class QueryBuilder<T> {
105
105
  params.FilterExpression = this.filters.join(' AND ');
106
106
  }
107
107
 
108
- const result = await this.parent.getClient().query(params).promise();
109
- return this.parent.getSchema().array().parse(result.Items);
108
+ const result = await this.parent.getClient().send(new QueryCommand(params));
109
+ return this.parent.getSchema().array().parse(result.Items) as T[];
110
110
  }
111
111
 
112
112
  // Thenable implementation.
@@ -1,4 +1,4 @@
1
- import { DynamoDB } from 'aws-sdk';
1
+ import { ScanCommand, ScanCommandInput } from '@aws-sdk/lib-dynamodb';
2
2
  import { BetterDDB } from '../betterddb';
3
3
 
4
4
  export class ScanBuilder<T> {
@@ -56,7 +56,7 @@ export class ScanBuilder<T> {
56
56
  * Executes the scan and returns a Promise that resolves with an array of items.
57
57
  */
58
58
  public async execute(): Promise<T[]> {
59
- const params: DynamoDB.DocumentClient.ScanInput = {
59
+ const params: ScanCommandInput = {
60
60
  TableName: this.parent.getTableName(),
61
61
  ExpressionAttributeNames: this.expressionAttributeNames,
62
62
  ExpressionAttributeValues: this.expressionAttributeValues,
@@ -68,8 +68,8 @@ export class ScanBuilder<T> {
68
68
  params.FilterExpression = this.filters.join(' AND ');
69
69
  }
70
70
 
71
- const result = await this.parent.getClient().scan(params).promise();
72
- return this.parent.getSchema().array().parse(result.Items);
71
+ const result = await this.parent.getClient().send(new ScanCommand(params));
72
+ return this.parent.getSchema().array().parse(result.Items) as T[];
73
73
  }
74
74
 
75
75
  // Thenable implementation.
@@ -1,7 +1,8 @@
1
1
 
2
- import { DynamoDB } from 'aws-sdk';
3
- import { BetterDDB } from '../betterddb';
4
2
 
3
+ import { TransactWriteCommand, UpdateCommand } from '@aws-sdk/lib-dynamodb';
4
+ import { BetterDDB } from '../betterddb';
5
+ import { TransactWriteItem, Update, UpdateItemInput } from '@aws-sdk/client-dynamodb';
5
6
  interface UpdateActions<T> {
6
7
  set?: Partial<T>;
7
8
  remove?: (keyof T)[];
@@ -14,7 +15,7 @@ export class UpdateBuilder<T> {
14
15
  private condition?: { expression: string; attributeValues: Record<string, any> };
15
16
  private expectedVersion?: number;
16
17
  // When using transaction mode, we store extra transaction items.
17
- private extraTransactItems: DynamoDB.DocumentClient.TransactWriteItemList = [];
18
+ private extraTransactItems: TransactWriteItem[] = [];
18
19
 
19
20
  // Reference to the parent BetterDDB instance and key.
20
21
  constructor(private parent: BetterDDB<T>, private key: Partial<T>, expectedVersion?: number) {
@@ -59,7 +60,7 @@ export class UpdateBuilder<T> {
59
60
  /**
60
61
  * Specifies additional transaction items to include when executing this update as a transaction.
61
62
  */
62
- public transactWrite(ops: DynamoDB.DocumentClient.TransactWriteItemList | DynamoDB.DocumentClient.TransactWriteItem): this {
63
+ public transactWrite(ops: TransactWriteItem[] | TransactWriteItem): this {
63
64
  if (Array.isArray(ops)) {
64
65
  this.extraTransactItems.push(...ops);
65
66
  } else {
@@ -173,9 +174,9 @@ export class UpdateBuilder<T> {
173
174
  /**
174
175
  * Returns a transaction update item that can be included in a transactWrite call.
175
176
  */
176
- public toTransactUpdate(): DynamoDB.DocumentClient.TransactWriteItem {
177
+ public toTransactUpdate(): TransactWriteItem {
177
178
  const { updateExpression, attributeNames, attributeValues } = this.buildExpression();
178
- const updateItem: DynamoDB.DocumentClient.Update = {
179
+ const updateItem: Update = {
179
180
  TableName: this.parent.getTableName(),
180
181
  Key: this.parent.buildKey(this.key),
181
182
  UpdateExpression: updateExpression,
@@ -197,9 +198,9 @@ export class UpdateBuilder<T> {
197
198
  const myTransactItem = this.toTransactUpdate();
198
199
  // Combine with extra transaction items.
199
200
  const allItems = [...this.extraTransactItems, myTransactItem];
200
- await this.parent.getClient().transactWrite({
201
+ await this.parent.getClient().send(new TransactWriteCommand({
201
202
  TransactItems: allItems
202
- }).promise();
203
+ }));
203
204
  // After transaction, retrieve the updated item.
204
205
  const result = await this.parent.get(this.key).execute();
205
206
  if (result === null) {
@@ -209,7 +210,7 @@ export class UpdateBuilder<T> {
209
210
  } else {
210
211
  // Normal update flow.
211
212
  const { updateExpression, attributeNames, attributeValues } = this.buildExpression();
212
- const params: DynamoDB.DocumentClient.UpdateItemInput = {
213
+ const params: UpdateItemInput = {
213
214
  TableName: this.parent.getTableName(),
214
215
  Key: this.parent.buildKey(this.key),
215
216
  UpdateExpression: updateExpression,
@@ -220,11 +221,11 @@ export class UpdateBuilder<T> {
220
221
  if (this.condition && this.condition.expression) {
221
222
  params.ConditionExpression = this.condition.expression;
222
223
  }
223
- const result = await this.parent.getClient().update(params).promise();
224
+ const result = await this.parent.getClient().send(new UpdateCommand(params));
224
225
  if (!result.Attributes) {
225
226
  throw new Error('No attributes returned after update');
226
227
  }
227
- return this.parent.getSchema().parse(result.Attributes);
228
+ return this.parent.getSchema().parse(result.Attributes) as T;
228
229
  }
229
230
  }
230
231
  }
@@ -1,8 +1,10 @@
1
1
  import { z } from 'zod';
2
2
  import { BetterDDB } from '../src/betterddb';
3
- import { DynamoDB } from 'aws-sdk';
4
3
  import { createTestTable, deleteTestTable } from './utils/table-setup';
5
-
4
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
5
+ import { DynamoDB } from '@aws-sdk/client-dynamodb';
6
+ import { GetCommand } from '@aws-sdk/lib-dynamodb';
7
+ import { KeySchemaElement, AttributeDefinition } from '@aws-sdk/client-dynamodb';
6
8
  const TEST_TABLE = "create-test-table";
7
9
  const ENDPOINT = 'http://localhost:4566';
8
10
  const REGION = 'us-east-1';
@@ -11,12 +13,12 @@ const PRIMARY_KEY = 'id';
11
13
  const PRIMARY_KEY_TYPE = 'S';
12
14
  const SORT_KEY = 'email';
13
15
  const SORT_KEY_TYPE = 'S';
14
- const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }];
15
- const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }];
16
- const client = new DynamoDB.DocumentClient({
16
+ const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }] as KeySchemaElement[];
17
+ const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }] as AttributeDefinition[];
18
+ const client = DynamoDBDocumentClient.from(new DynamoDB({
17
19
  region: REGION,
18
20
  endpoint: ENDPOINT,
19
- });
21
+ }));
20
22
 
21
23
  const UserSchema = z.object({
22
24
  id: z.string(),
@@ -24,15 +26,18 @@ const UserSchema = z.object({
24
26
  email: z.string().email(),
25
27
  createdAt: z.string(),
26
28
  updatedAt: z.string(),
27
- }).passthrough();
29
+ });
28
30
 
29
- const userDdb = new BetterDDB({
31
+ type User = z.infer<typeof UserSchema>;
32
+
33
+ const userDdb = new BetterDDB<User>({
30
34
  schema: UserSchema,
31
35
  tableName: TEST_TABLE,
32
36
  entityName: ENTITY_NAME,
33
37
  keys: {
34
- primary: { name: PRIMARY_KEY, definition: { build: (raw) => raw.id! } },
35
- sort: { name: SORT_KEY, definition: { build: (raw) => raw.email! } },
38
+ primary: { name: "pk", definition: { build: (raw) => `USER#${raw.id}` } },
39
+ sort: { name: "sk", definition: { build: (raw) => `EMAIL#${raw.email}` } },
40
+ gsis: { gsi1: { name: 'gsi1', primary: { name: "gsi1pk", definition: { build: (raw) => "NAME" } }, sort: { name: "gsi1sk", definition: { build: (raw) => `NAME#${raw.name}` } } } },
36
41
  },
37
42
  client,
38
43
  autoTimestamps: true,
@@ -49,11 +54,24 @@ afterAll(async () => {
49
54
  describe('BetterDDB - Create Operation', () => {
50
55
  it('should insert an item using CreateBuilder', async () => {
51
56
  const user = { id: 'user-123', name: 'John Doe', email: 'john@example.com' };
57
+
52
58
  await userDdb.create(user as any).execute();
53
- const createdUser = await userDdb.get({ id: 'user-123', email: 'john@example.com' }).execute();
54
- expect(createdUser).not.toBeNull();
55
- expect(createdUser?.id).toBe('user-123');
56
- expect(createdUser).toHaveProperty('createdAt');
57
- expect(createdUser).toHaveProperty('updatedAt');
59
+
60
+ const result = await client.send(new GetCommand({ TableName: TEST_TABLE, Key: { id: 'user-123', email: 'john@example.com' } }));
61
+
62
+ expect(result).not.toBeNull();
63
+ expect(result.Item).not.toBeNull();
64
+ expect(result.Item?.pk).toBe('USER#user-123');
65
+ expect(result.Item?.sk).toBe('EMAIL#john@example.com');
66
+ expect(result.Item?.gsi1pk).toBe('NAME');
67
+ expect(result.Item?.gsi1sk).toBe('NAME#John Doe');
68
+ expect(result.Item?.id).toBe('user-123');
69
+ expect(result.Item?.createdAt).not.toBeNull();
70
+ expect(result.Item?.updatedAt).not.toBeNull();
71
+ });
72
+
73
+ it('should fails to validate and not insert an item', async () => {
74
+ const user = { id: 'user-123', email: 'john@example.com' };
75
+ await expect(userDdb.create(user as any).execute()).rejects.toThrow();
58
76
  });
59
77
  });
@@ -1,9 +1,10 @@
1
1
  // __tests__/delete.test.ts
2
2
  import { z } from 'zod';
3
3
  import { BetterDDB } from '../src/betterddb';
4
- import { DynamoDB } from 'aws-sdk';
4
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
5
+ import { DynamoDB } from '@aws-sdk/client-dynamodb';
5
6
  import { createTestTable, deleteTestTable } from './utils/table-setup';
6
-
7
+ import { KeySchemaElement, AttributeDefinition } from '@aws-sdk/client-dynamodb';
7
8
  const TEST_TABLE = "delete-test-table";
8
9
  const ENDPOINT = 'http://localhost:4566';
9
10
  const REGION = 'us-east-1';
@@ -12,12 +13,12 @@ const PRIMARY_KEY = 'id';
12
13
  const PRIMARY_KEY_TYPE = 'S';
13
14
  const SORT_KEY = 'email';
14
15
  const SORT_KEY_TYPE = 'S';
15
- const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }];
16
- const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }];
17
- const client = new DynamoDB.DocumentClient({
16
+ const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }] as KeySchemaElement[];
17
+ const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }] as AttributeDefinition[];
18
+ const client = DynamoDBDocumentClient.from(new DynamoDB({
18
19
  region: REGION,
19
20
  endpoint: ENDPOINT,
20
- });
21
+ }));
21
22
 
22
23
  const UserSchema = z.object({
23
24
  id: z.string(),
@@ -25,9 +26,11 @@ const UserSchema = z.object({
25
26
  email: z.string().email(),
26
27
  createdAt: z.string(),
27
28
  updatedAt: z.string(),
28
- }).passthrough();
29
+ });
30
+
31
+ type User = z.infer<typeof UserSchema>;
29
32
 
30
- const userDdb = new BetterDDB({
33
+ const userDdb = new BetterDDB<User>({
31
34
  schema: UserSchema,
32
35
  tableName: TEST_TABLE,
33
36
  entityName: ENTITY_NAME,
package/test/get.test.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  // __tests__/get.test.ts
2
2
  import { z } from 'zod';
3
3
  import { BetterDDB } from '../src/betterddb';
4
- import { DynamoDB } from 'aws-sdk';
5
4
  import { createTestTable, deleteTestTable } from './utils/table-setup';
6
-
5
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
6
+ import { DynamoDB } from '@aws-sdk/client-dynamodb';
7
+ import { KeySchemaElement, AttributeDefinition } from '@aws-sdk/client-dynamodb';
7
8
  const TEST_TABLE = "get-test-table";
8
9
  const ENDPOINT = 'http://localhost:4566';
9
10
  const REGION = 'us-east-1';
@@ -12,12 +13,12 @@ const PRIMARY_KEY = 'id';
12
13
  const PRIMARY_KEY_TYPE = 'S';
13
14
  const SORT_KEY = 'email';
14
15
  const SORT_KEY_TYPE = 'S';
15
- const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }];
16
- const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }];
17
- const client = new DynamoDB.DocumentClient({
16
+ const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }] as KeySchemaElement[];
17
+ const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }] as AttributeDefinition[];
18
+ const client = DynamoDBDocumentClient.from(new DynamoDB({
18
19
  region: REGION,
19
20
  endpoint: ENDPOINT,
20
- });
21
+ }));
21
22
 
22
23
 
23
24
  const UserSchema = z.object({
@@ -26,9 +27,11 @@ const UserSchema = z.object({
26
27
  email: z.string().email(),
27
28
  createdAt: z.string(),
28
29
  updatedAt: z.string(),
29
- }).passthrough();
30
+ });
31
+
32
+ type User = z.infer<typeof UserSchema>;
30
33
 
31
- const userDdb = new BetterDDB({
34
+ const userDdb = new BetterDDB<User>({
32
35
  schema: UserSchema,
33
36
  tableName: TEST_TABLE,
34
37
  entityName: ENTITY_NAME,
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { BetterDDB } from '../src/betterddb';
3
- import { DynamoDB } from 'aws-sdk';
3
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
4
+ import { AttributeDefinition, DynamoDB, KeySchemaElement } from '@aws-sdk/client-dynamodb';
4
5
  import { createTestTable, deleteTestTable } from './utils/table-setup';
5
6
 
6
7
  const TEST_TABLE = "query-test-table";
@@ -11,12 +12,12 @@ const PRIMARY_KEY = 'id';
11
12
  const PRIMARY_KEY_TYPE = 'S';
12
13
  const SORT_KEY = 'email';
13
14
  const SORT_KEY_TYPE = 'S';
14
- const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }];
15
- const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }];
16
- const client = new DynamoDB.DocumentClient({
15
+ const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }] as KeySchemaElement[];
16
+ const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }] as AttributeDefinition[];
17
+ const client = DynamoDBDocumentClient.from(new DynamoDB({
17
18
  region: REGION,
18
19
  endpoint: ENDPOINT,
19
- });
20
+ }));
20
21
 
21
22
  const UserSchema = z.object({
22
23
  id: z.string(),
@@ -24,9 +25,11 @@ const UserSchema = z.object({
24
25
  email: z.string().email(),
25
26
  createdAt: z.string(),
26
27
  updatedAt: z.string(),
27
- }).passthrough();
28
+ });
29
+
30
+ type User = z.infer<typeof UserSchema>;
28
31
 
29
- const userDdb = new BetterDDB({
32
+ const userDdb = new BetterDDB<User>({
30
33
  schema: UserSchema,
31
34
  tableName: TEST_TABLE,
32
35
  entityName: ENTITY_NAME,
package/test/scan.test.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { BetterDDB } from '../src/betterddb';
3
- import { DynamoDB } from 'aws-sdk';
3
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
4
+ import { DynamoDB } from '@aws-sdk/client-dynamodb';
4
5
  import { createTestTable, deleteTestTable } from './utils/table-setup';
5
-
6
+ import { KeySchemaElement, AttributeDefinition } from '@aws-sdk/client-dynamodb';
6
7
  const TEST_TABLE = "scan-test-table";
7
8
  const ENDPOINT = 'http://localhost:4566';
8
9
  const REGION = 'us-east-1';
@@ -11,12 +12,13 @@ const PRIMARY_KEY = 'id';
11
12
  const PRIMARY_KEY_TYPE = 'S';
12
13
  const SORT_KEY = 'email';
13
14
  const SORT_KEY_TYPE = 'S';
14
- const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }];
15
- const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }];
16
- const client = new DynamoDB.DocumentClient({
15
+ const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }] as KeySchemaElement[];
16
+ const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }] as AttributeDefinition[];
17
+ const client = DynamoDBDocumentClient.from(new DynamoDB({
17
18
  region: REGION,
18
19
  endpoint: ENDPOINT,
19
- });
20
+ }));
21
+
20
22
 
21
23
  const UserSchema = z.object({
22
24
  id: z.string(),
@@ -24,9 +26,11 @@ const UserSchema = z.object({
24
26
  email: z.string().email(),
25
27
  createdAt: z.string(),
26
28
  updatedAt: z.string(),
27
- }).passthrough();
29
+ });
30
+
31
+ type User = z.infer<typeof UserSchema>;
28
32
 
29
- const userDdb = new BetterDDB({
33
+ const userDdb = new BetterDDB<User>({
30
34
  schema: UserSchema,
31
35
  tableName: TEST_TABLE,
32
36
  entityName: ENTITY_NAME,
@@ -1,8 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { BetterDDB } from '../src/betterddb';
3
- import { DynamoDB } from 'aws-sdk';
3
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
4
4
  import { createTestTable, deleteTestTable } from './utils/table-setup';
5
-
5
+ import { DynamoDB } from '@aws-sdk/client-dynamodb';
6
+ import { KeySchemaElement, AttributeDefinition } from '@aws-sdk/client-dynamodb';
6
7
  const TEST_TABLE = "update-test-table";
7
8
  const ENDPOINT = 'http://localhost:4566';
8
9
  const REGION = 'us-east-1';
@@ -11,12 +12,12 @@ const PRIMARY_KEY = 'id';
11
12
  const PRIMARY_KEY_TYPE = 'S';
12
13
  const SORT_KEY = 'email';
13
14
  const SORT_KEY_TYPE = 'S';
14
- const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }];
15
- const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }];
16
- const client = new DynamoDB.DocumentClient({
15
+ const KEY_SCHEMA = [{ AttributeName: PRIMARY_KEY, KeyType: 'HASH' }, { AttributeName: SORT_KEY, KeyType: 'RANGE' }] as KeySchemaElement[];
16
+ const ATTRIBUTE_DEFINITIONS = [{ AttributeName: PRIMARY_KEY, AttributeType: PRIMARY_KEY_TYPE }, { AttributeName: SORT_KEY, AttributeType: SORT_KEY_TYPE }] as AttributeDefinition[];
17
+ const client = DynamoDBDocumentClient.from(new DynamoDB({
17
18
  region: REGION,
18
19
  endpoint: ENDPOINT,
19
- });
20
+ }));
20
21
 
21
22
 
22
23
  const UserSchema = z.object({
@@ -26,9 +27,11 @@ const UserSchema = z.object({
26
27
  createdAt: z.string(),
27
28
  updatedAt: z.string(),
28
29
  version: z.number().optional(),
29
- }).passthrough();
30
+ });
31
+
32
+ type User = z.infer<typeof UserSchema>;
30
33
 
31
- const userDdb = new BetterDDB({
34
+ const userDdb = new BetterDDB<User>({
32
35
  schema: UserSchema,
33
36
  tableName: TEST_TABLE,
34
37
  entityName: ENTITY_NAME,
@@ -1,6 +1,6 @@
1
- import { DynamoDB } from 'aws-sdk';
1
+ import { CreateTableCommandInput, DynamoDB } from '@aws-sdk/client-dynamodb';
2
2
 
3
- export const createTestTable = async (tableName: string, keySchema: DynamoDB.CreateTableInput['KeySchema'], attributeDefinitions: DynamoDB.CreateTableInput['AttributeDefinitions']) => {
3
+ export const createTestTable = async (tableName: string, keySchema: CreateTableCommandInput['KeySchema'], attributeDefinitions: CreateTableCommandInput['AttributeDefinitions']) => {
4
4
  const dynamoDB = new DynamoDB({
5
5
  region: 'us-east-1',
6
6
  endpoint: 'http://localhost:4566',
@@ -14,7 +14,7 @@ export const createTestTable = async (tableName: string, keySchema: DynamoDB.Cre
14
14
  KeySchema: keySchema,
15
15
  AttributeDefinitions: attributeDefinitions,
16
16
  BillingMode: 'PAY_PER_REQUEST',
17
- }).promise();
17
+ });
18
18
  } catch (error: any) {
19
19
  if (error.code === 'ResourceInUseException') {
20
20
  console.log('Table already exists, skipping creation.');
@@ -25,14 +25,14 @@ export const createTestTable = async (tableName: string, keySchema: DynamoDB.Cre
25
25
 
26
26
  // Wait for the table to become active.
27
27
  let attempts = 0;
28
- while (attempts < 60) { // wait up to 60 seconds
29
- const { Table } = await dynamoDB.describeTable({ TableName: tableName }).promise();
28
+ while (attempts < 60) { // wait up to 15 seconds
29
+ const { Table } = await dynamoDB.describeTable({ TableName: tableName });
30
30
  if (Table?.TableStatus === 'ACTIVE') {
31
31
  console.log('DynamoDB table is ready.');
32
32
  return;
33
33
  }
34
34
  console.log('Waiting for table to become ACTIVE...');
35
- await new Promise((res) => setTimeout(res, 1000));
35
+ await new Promise((res) => setTimeout(res, 250));
36
36
  attempts++;
37
37
  }
38
38
  throw new Error('Table did not become active in time.');
@@ -44,7 +44,7 @@ export const deleteTestTable = async (tableName: string) => {
44
44
  endpoint: 'http://localhost:4566',
45
45
  });
46
46
  try {
47
- await dynamoDB.deleteTable({ TableName: tableName }).promise();
47
+ await dynamoDB.deleteTable({ TableName: tableName });
48
48
  } catch (error: any) {
49
49
  if (error.code === 'ResourceNotFoundException') {
50
50
  console.log('Table not found during deletion.');