betterddb 0.4.1 → 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.
- package/lib/betterddb.d.ts +101 -36
- package/lib/betterddb.js +72 -12
- package/lib/builders/create-builder.d.ts +9 -10
- package/lib/builders/create-builder.js +5 -4
- package/lib/builders/delete-builder.d.ts +5 -6
- package/lib/builders/delete-builder.js +4 -3
- package/lib/builders/get-builder.d.ts +10 -11
- package/lib/builders/get-builder.js +4 -3
- package/lib/builders/query-builder.d.ts +7 -8
- package/lib/builders/query-builder.js +2 -1
- package/lib/builders/scan-builder.d.ts +7 -8
- package/lib/builders/scan-builder.js +2 -1
- package/lib/builders/update-builder.d.ts +10 -11
- package/lib/builders/update-builder.js +4 -3
- package/package.json +3 -2
- package/src/betterddb.ts +163 -77
- package/src/builders/create-builder.ts +24 -23
- package/src/builders/delete-builder.ts +12 -13
- package/src/builders/get-builder.ts +19 -20
- package/src/builders/query-builder.ts +12 -13
- package/src/builders/scan-builder.ts +12 -13
- package/src/builders/update-builder.ts +25 -25
- package/test/create.test.ts +12 -8
- package/test/delete.test.ts +10 -7
- package/test/get.test.ts +10 -7
- package/test/query.test.ts +9 -6
- package/test/scan.test.ts +11 -7
- package/test/update.test.ts +10 -7
- package/test/utils/table-setup.ts +7 -7
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { QueryCommand, QueryCommandInput } from '@aws-sdk/lib-dynamodb';
|
|
2
2
|
import { BetterDDB } from '../betterddb';
|
|
3
|
-
import { z } from 'zod';
|
|
4
3
|
|
|
5
|
-
export class QueryBuilder<
|
|
4
|
+
export class QueryBuilder<T> {
|
|
6
5
|
private filters: string[] = [];
|
|
7
6
|
private expressionAttributeNames: Record<string, string> = {};
|
|
8
7
|
private expressionAttributeValues: Record<string, any> = {};
|
|
@@ -12,7 +11,7 @@ export class QueryBuilder<S extends z.ZodType<any>> {
|
|
|
12
11
|
private lastKey?: Record<string, any>;
|
|
13
12
|
private ascending: boolean = true;
|
|
14
13
|
|
|
15
|
-
constructor(private parent: BetterDDB<
|
|
14
|
+
constructor(private parent: BetterDDB<T>, private key: Partial<T>) {}
|
|
16
15
|
|
|
17
16
|
public usingIndex(indexName: string): this {
|
|
18
17
|
this.indexName = indexName;
|
|
@@ -30,7 +29,7 @@ export class QueryBuilder<S extends z.ZodType<any>> {
|
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
public where(
|
|
33
|
-
attribute: keyof
|
|
32
|
+
attribute: keyof T,
|
|
34
33
|
operator: 'eq' | 'begins_with' | 'between',
|
|
35
34
|
values: any | [any, any]
|
|
36
35
|
): this {
|
|
@@ -74,7 +73,7 @@ export class QueryBuilder<S extends z.ZodType<any>> {
|
|
|
74
73
|
/**
|
|
75
74
|
* Executes the query and returns a Promise that resolves with an array of items.
|
|
76
75
|
*/
|
|
77
|
-
public async execute(): Promise<
|
|
76
|
+
public async execute(): Promise<T[]> {
|
|
78
77
|
// Build a simple key condition for the partition key.
|
|
79
78
|
const keys = this.parent.getKeys();
|
|
80
79
|
const pkName = keys.primary.name;
|
|
@@ -91,7 +90,7 @@ export class QueryBuilder<S extends z.ZodType<any>> {
|
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
// If any filters were added, set them as FilterExpression.
|
|
94
|
-
const params:
|
|
93
|
+
const params: QueryCommandInput = {
|
|
95
94
|
TableName: this.parent.getTableName(),
|
|
96
95
|
KeyConditionExpression: keyConditionExpression,
|
|
97
96
|
ExpressionAttributeNames: this.expressionAttributeNames,
|
|
@@ -106,23 +105,23 @@ export class QueryBuilder<S extends z.ZodType<any>> {
|
|
|
106
105
|
params.FilterExpression = this.filters.join(' AND ');
|
|
107
106
|
}
|
|
108
107
|
|
|
109
|
-
const result = await this.parent.getClient().
|
|
110
|
-
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[];
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
// Thenable implementation.
|
|
114
|
-
public then<TResult1 =
|
|
115
|
-
onfulfilled?: ((value:
|
|
113
|
+
public then<TResult1 = T[], TResult2 = never>(
|
|
114
|
+
onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | null,
|
|
116
115
|
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
117
116
|
): Promise<TResult1 | TResult2> {
|
|
118
117
|
return this.execute().then(onfulfilled, onrejected);
|
|
119
118
|
}
|
|
120
119
|
public catch<TResult = never>(
|
|
121
120
|
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
|
122
|
-
): Promise<
|
|
121
|
+
): Promise<T[] | TResult> {
|
|
123
122
|
return this.execute().catch(onrejected);
|
|
124
123
|
}
|
|
125
|
-
public finally(onfinally?: (() => void) | null): Promise<
|
|
124
|
+
public finally(onfinally?: (() => void) | null): Promise<T[]> {
|
|
126
125
|
return this.execute().finally(onfinally);
|
|
127
126
|
}
|
|
128
127
|
}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ScanCommand, ScanCommandInput } from '@aws-sdk/lib-dynamodb';
|
|
2
2
|
import { BetterDDB } from '../betterddb';
|
|
3
|
-
import { z } from 'zod';
|
|
4
3
|
|
|
5
|
-
export class ScanBuilder<
|
|
4
|
+
export class ScanBuilder<T> {
|
|
6
5
|
private filters: string[] = [];
|
|
7
6
|
private expressionAttributeNames: Record<string, string> = {};
|
|
8
7
|
private expressionAttributeValues: Record<string, any> = {};
|
|
9
8
|
private limit?: number;
|
|
10
9
|
private lastKey?: Record<string, any>;
|
|
11
10
|
|
|
12
|
-
constructor(private parent: BetterDDB<
|
|
11
|
+
constructor(private parent: BetterDDB<T>) {}
|
|
13
12
|
|
|
14
13
|
public where(
|
|
15
|
-
attribute: keyof
|
|
14
|
+
attribute: keyof T,
|
|
16
15
|
operator: 'eq' | 'begins_with' | 'between',
|
|
17
16
|
values: any | [any, any]
|
|
18
17
|
): this {
|
|
@@ -56,8 +55,8 @@ export class ScanBuilder<S extends z.ZodType<any>> {
|
|
|
56
55
|
/**
|
|
57
56
|
* Executes the scan and returns a Promise that resolves with an array of items.
|
|
58
57
|
*/
|
|
59
|
-
public async execute(): Promise<
|
|
60
|
-
const params:
|
|
58
|
+
public async execute(): Promise<T[]> {
|
|
59
|
+
const params: ScanCommandInput = {
|
|
61
60
|
TableName: this.parent.getTableName(),
|
|
62
61
|
ExpressionAttributeNames: this.expressionAttributeNames,
|
|
63
62
|
ExpressionAttributeValues: this.expressionAttributeValues,
|
|
@@ -69,23 +68,23 @@ export class ScanBuilder<S extends z.ZodType<any>> {
|
|
|
69
68
|
params.FilterExpression = this.filters.join(' AND ');
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
const result = await this.parent.getClient().
|
|
73
|
-
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[];
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
// Thenable implementation.
|
|
77
|
-
public then<TResult1 =
|
|
78
|
-
onfulfilled?: ((value:
|
|
76
|
+
public then<TResult1 = T[], TResult2 = never>(
|
|
77
|
+
onfulfilled?: ((value: T[]) => TResult1 | PromiseLike<TResult1>) | null,
|
|
79
78
|
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|
|
80
79
|
): Promise<TResult1 | TResult2> {
|
|
81
80
|
return this.execute().then(onfulfilled, onrejected);
|
|
82
81
|
}
|
|
83
82
|
public catch<TResult = never>(
|
|
84
83
|
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
|
|
85
|
-
): Promise<
|
|
84
|
+
): Promise<T[] | TResult> {
|
|
86
85
|
return this.execute().catch(onrejected);
|
|
87
86
|
}
|
|
88
|
-
public finally(onfinally?: (() => void) | null): Promise<
|
|
87
|
+
public finally(onfinally?: (() => void) | null): Promise<T[]> {
|
|
89
88
|
return this.execute().finally(onfinally);
|
|
90
89
|
}
|
|
91
90
|
}
|
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
|
|
2
|
-
import { DynamoDB } from 'aws-sdk';
|
|
3
|
-
import { BetterDDB } from '../betterddb';
|
|
4
|
-
import { z } from 'zod';
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
import { TransactWriteCommand, UpdateCommand } from '@aws-sdk/lib-dynamodb';
|
|
4
|
+
import { BetterDDB } from '../betterddb';
|
|
5
|
+
import { TransactWriteItem, Update, UpdateItemInput } from '@aws-sdk/client-dynamodb';
|
|
6
|
+
interface UpdateActions<T> {
|
|
7
|
+
set?: Partial<T>;
|
|
8
|
+
remove?: (keyof T)[];
|
|
9
|
+
add?: Partial<Record<keyof T, number | Set<any>>>;
|
|
10
|
+
delete?: Partial<Record<keyof T, Set<any>>>;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export class UpdateBuilder<
|
|
14
|
-
private actions: UpdateActions<
|
|
13
|
+
export class UpdateBuilder<T> {
|
|
14
|
+
private actions: UpdateActions<T> = {};
|
|
15
15
|
private condition?: { expression: string; attributeValues: Record<string, any> };
|
|
16
16
|
private expectedVersion?: number;
|
|
17
17
|
// When using transaction mode, we store extra transaction items.
|
|
18
|
-
private extraTransactItems:
|
|
18
|
+
private extraTransactItems: TransactWriteItem[] = [];
|
|
19
19
|
|
|
20
20
|
// Reference to the parent BetterDDB instance and key.
|
|
21
|
-
constructor(private parent: BetterDDB<
|
|
21
|
+
constructor(private parent: BetterDDB<T>, private key: Partial<T>, expectedVersion?: number) {
|
|
22
22
|
this.expectedVersion = expectedVersion;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
// Chainable methods:
|
|
26
|
-
public set(attrs: Partial<
|
|
26
|
+
public set(attrs: Partial<T>): this {
|
|
27
27
|
this.actions.set = { ...this.actions.set, ...attrs };
|
|
28
28
|
return this;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
public remove(attrs: (keyof
|
|
31
|
+
public remove(attrs: (keyof T)[]): this {
|
|
32
32
|
this.actions.remove = [...(this.actions.remove || []), ...attrs];
|
|
33
33
|
return this;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
public add(attrs: Partial<Record<keyof
|
|
36
|
+
public add(attrs: Partial<Record<keyof T, number | Set<any>>>): this {
|
|
37
37
|
this.actions.add = { ...this.actions.add, ...attrs };
|
|
38
38
|
return this;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
public delete(attrs: Partial<Record<keyof
|
|
41
|
+
public delete(attrs: Partial<Record<keyof T, Set<any>>>): this {
|
|
42
42
|
this.actions.delete = { ...this.actions.delete, ...attrs };
|
|
43
43
|
return this;
|
|
44
44
|
}
|
|
@@ -60,7 +60,7 @@ export class UpdateBuilder<S extends z.ZodType<any>> {
|
|
|
60
60
|
/**
|
|
61
61
|
* Specifies additional transaction items to include when executing this update as a transaction.
|
|
62
62
|
*/
|
|
63
|
-
public transactWrite(ops:
|
|
63
|
+
public transactWrite(ops: TransactWriteItem[] | TransactWriteItem): this {
|
|
64
64
|
if (Array.isArray(ops)) {
|
|
65
65
|
this.extraTransactItems.push(...ops);
|
|
66
66
|
} else {
|
|
@@ -174,9 +174,9 @@ export class UpdateBuilder<S extends z.ZodType<any>> {
|
|
|
174
174
|
/**
|
|
175
175
|
* Returns a transaction update item that can be included in a transactWrite call.
|
|
176
176
|
*/
|
|
177
|
-
public toTransactUpdate():
|
|
177
|
+
public toTransactUpdate(): TransactWriteItem {
|
|
178
178
|
const { updateExpression, attributeNames, attributeValues } = this.buildExpression();
|
|
179
|
-
const updateItem:
|
|
179
|
+
const updateItem: Update = {
|
|
180
180
|
TableName: this.parent.getTableName(),
|
|
181
181
|
Key: this.parent.buildKey(this.key),
|
|
182
182
|
UpdateExpression: updateExpression,
|
|
@@ -192,15 +192,15 @@ export class UpdateBuilder<S extends z.ZodType<any>> {
|
|
|
192
192
|
/**
|
|
193
193
|
* Commits the update immediately by calling the parent's update method.
|
|
194
194
|
*/
|
|
195
|
-
public async execute(): Promise<
|
|
195
|
+
public async execute(): Promise<T> {
|
|
196
196
|
if (this.extraTransactItems.length > 0) {
|
|
197
197
|
// Build our update transaction item.
|
|
198
198
|
const myTransactItem = this.toTransactUpdate();
|
|
199
199
|
// Combine with extra transaction items.
|
|
200
200
|
const allItems = [...this.extraTransactItems, myTransactItem];
|
|
201
|
-
await this.parent.getClient().
|
|
201
|
+
await this.parent.getClient().send(new TransactWriteCommand({
|
|
202
202
|
TransactItems: allItems
|
|
203
|
-
})
|
|
203
|
+
}));
|
|
204
204
|
// After transaction, retrieve the updated item.
|
|
205
205
|
const result = await this.parent.get(this.key).execute();
|
|
206
206
|
if (result === null) {
|
|
@@ -210,7 +210,7 @@ export class UpdateBuilder<S extends z.ZodType<any>> {
|
|
|
210
210
|
} else {
|
|
211
211
|
// Normal update flow.
|
|
212
212
|
const { updateExpression, attributeNames, attributeValues } = this.buildExpression();
|
|
213
|
-
const params:
|
|
213
|
+
const params: UpdateItemInput = {
|
|
214
214
|
TableName: this.parent.getTableName(),
|
|
215
215
|
Key: this.parent.buildKey(this.key),
|
|
216
216
|
UpdateExpression: updateExpression,
|
|
@@ -221,11 +221,11 @@ export class UpdateBuilder<S extends z.ZodType<any>> {
|
|
|
221
221
|
if (this.condition && this.condition.expression) {
|
|
222
222
|
params.ConditionExpression = this.condition.expression;
|
|
223
223
|
}
|
|
224
|
-
const result = await this.parent.getClient().
|
|
224
|
+
const result = await this.parent.getClient().send(new UpdateCommand(params));
|
|
225
225
|
if (!result.Attributes) {
|
|
226
226
|
throw new Error('No attributes returned after update');
|
|
227
227
|
}
|
|
228
|
-
return this.parent.getSchema().parse(result.Attributes);
|
|
228
|
+
return this.parent.getSchema().parse(result.Attributes) as T;
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
}
|
package/test/create.test.ts
CHANGED
|
@@ -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
|
|
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(),
|
|
@@ -26,7 +28,9 @@ const UserSchema = z.object({
|
|
|
26
28
|
updatedAt: z.string(),
|
|
27
29
|
});
|
|
28
30
|
|
|
29
|
-
|
|
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,
|
|
@@ -53,7 +57,7 @@ describe('BetterDDB - Create Operation', () => {
|
|
|
53
57
|
|
|
54
58
|
await userDdb.create(user as any).execute();
|
|
55
59
|
|
|
56
|
-
const result = await client.
|
|
60
|
+
const result = await client.send(new GetCommand({ TableName: TEST_TABLE, Key: { id: 'user-123', email: 'john@example.com' } }));
|
|
57
61
|
|
|
58
62
|
expect(result).not.toBeNull();
|
|
59
63
|
expect(result.Item).not.toBeNull();
|
package/test/delete.test.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
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(),
|
|
@@ -27,7 +28,9 @@ const UserSchema = z.object({
|
|
|
27
28
|
updatedAt: z.string(),
|
|
28
29
|
});
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
type User = z.infer<typeof UserSchema>;
|
|
32
|
+
|
|
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
|
|
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({
|
|
@@ -28,7 +29,9 @@ const UserSchema = z.object({
|
|
|
28
29
|
updatedAt: z.string(),
|
|
29
30
|
});
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
type User = z.infer<typeof UserSchema>;
|
|
33
|
+
|
|
34
|
+
const userDdb = new BetterDDB<User>({
|
|
32
35
|
schema: UserSchema,
|
|
33
36
|
tableName: TEST_TABLE,
|
|
34
37
|
entityName: ENTITY_NAME,
|
package/test/query.test.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { BetterDDB } from '../src/betterddb';
|
|
3
|
-
import {
|
|
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
|
|
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(),
|
|
@@ -26,7 +27,9 @@ const UserSchema = z.object({
|
|
|
26
27
|
updatedAt: z.string(),
|
|
27
28
|
});
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
type User = z.infer<typeof UserSchema>;
|
|
31
|
+
|
|
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 {
|
|
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
|
|
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(),
|
|
@@ -26,7 +28,9 @@ const UserSchema = z.object({
|
|
|
26
28
|
updatedAt: z.string(),
|
|
27
29
|
});
|
|
28
30
|
|
|
29
|
-
|
|
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,
|
package/test/update.test.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { BetterDDB } from '../src/betterddb';
|
|
3
|
-
import {
|
|
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
|
|
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({
|
|
@@ -28,7 +29,9 @@ const UserSchema = z.object({
|
|
|
28
29
|
version: z.number().optional(),
|
|
29
30
|
});
|
|
30
31
|
|
|
31
|
-
|
|
32
|
+
type User = z.infer<typeof UserSchema>;
|
|
33
|
+
|
|
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:
|
|
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
|
-
})
|
|
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
|
|
29
|
-
const { Table } = await dynamoDB.describeTable({ TableName: tableName })
|
|
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,
|
|
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 })
|
|
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.');
|