1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
import { Widget, WidgetT } from "@/shared/schema";
import { WidgetDAO } from ".";
import { TracingLogger } from "@/consumer/log";
import {
AttributeValue,
DeleteItemCommand,
DynamoDBClient,
GetItemCommand,
PutItemCommand,
} from "@aws-sdk/client-dynamodb";
export class DynamoWidgetDAO implements WidgetDAO {
private table: string;
private ddbClient: DynamoDBClient;
private logger: TracingLogger;
constructor(table: string, ddbClient: DynamoDBClient, logger: TracingLogger) {
this.table = table;
this.ddbClient = ddbClient;
this.logger = logger;
}
public async retrieve(widget: WidgetT) {
const getReq = new GetItemCommand({
TableName: this.table,
Key: {
id: {
S: widget.id,
},
},
});
const response = await this.ddbClient.send(getReq);
if (response.Item) {
this.logger.info(`sucessfully retrieved Widget=(${widget.id})`);
return this.deflate(response.Item);
}
}
public async save(widget: WidgetT) {
const putReq = new PutItemCommand({
TableName: this.table,
Item: this.inflate(widget),
});
await this.ddbClient.send(putReq);
this.logger.info(`sucessfully saved Widget=(${widget.id})`);
return widget;
}
public async delete(widget: WidgetT) {
const deleteReq = new DeleteItemCommand({
TableName: this.table,
Key: {
id: { S: widget.id },
},
});
await this.ddbClient.send(deleteReq);
this.logger.info(`sucessfully deleted Widget=(${widget.id})`);
return widget;
}
private inflate(widget: WidgetT): Record<string, AttributeValue> {
const additionalAttributes =
widget.otherAttributes?.reduce((acc, { name, value }) => {
acc[name] = { S: value };
return acc;
}, {} as Record<string, { S: string }>) ?? {};
if (widget.label) additionalAttributes["label"] = { S: widget.label };
if (widget.description)
additionalAttributes["description"] = { S: widget.description };
return {
id: { S: widget.id },
owner: { S: widget.owner },
...additionalAttributes,
};
}
private deflate(item: Record<string, AttributeValue>): WidgetT {
const respWidget = Object.keys(item).reduce((widge, key: string) => {
const attributeValue = item![key];
if (["id", "owner", "label", "description"].includes(key)) {
widge[key] = attributeValue.S;
return widge;
}
const attribute = { name: key, value: attributeValue.S! };
widge["otherAttributes"] = widge["otherAttributes"]?.concat([
attribute,
]) ?? [attribute];
return widge;
}, {} as Record<string, any>);
return Widget.parse(respWidget);
}
}
|