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 { const additionalAttributes = widget.otherAttributes?.reduce((acc, { name, value }) => { acc[name] = { S: value }; return acc; }, {} as Record) ?? {}; 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): 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); return Widget.parse(respWidget); } }