import { WidgetT, Widget } from "@/shared/schema"; import { WidgetDAO } from "."; import { DeleteObjectCommand, GetObjectCommand, NoSuchKey, PutObjectCommand, S3Client, } from "@aws-sdk/client-s3"; import { S3WidgetKeyGenerator } from "./keys"; import { TracingLogger } from "@/consumer/log"; export class S3WidgetDAO implements WidgetDAO { private bucket: string; private s3Client: S3Client; private widgetKeyGenerator: S3WidgetKeyGenerator; private logger: TracingLogger; constructor( bucket: string, s3Client: S3Client, widgetKeyGenerator: S3WidgetKeyGenerator, logger: TracingLogger ) { this.bucket = bucket; this.s3Client = s3Client; this.widgetKeyGenerator = widgetKeyGenerator; this.logger = logger; } public async retrieve(widget: WidgetT) { const key = this.widgetKeyGenerator.fromWidget(widget); this.logger.info( `getting Widget=(${widget.id}) in Bucket=(${this.bucket})` ); const retrievalRequest = new GetObjectCommand({ Bucket: this.bucket, Key: key, }); try { const objectResp = await this.s3Client.send(retrievalRequest); const textRepr = await objectResp.Body?.transformToString(); if (textRepr) { this.logger.info(`retrieved WidgetObject=(${widget.id}) from S3`); return Widget.parse(JSON.parse(textRepr)); } } catch (e: unknown) { if (e instanceof NoSuchKey) { return; } throw e; } } public async save(widget: WidgetT) { const key = this.widgetKeyGenerator.fromWidget(widget); this.logger.info(`saving Widget=(${widget.id}) in Bucket=(${this.bucket})`); const putReq = new PutObjectCommand({ Bucket: this.bucket, Key: key, Body: JSON.stringify(widget, null, 2), }); await this.s3Client.send(putReq); this.logger.info(`successfully saved Widget=(${widget.id}) in S3`); return widget; } public async delete(widget: WidgetT) { const key = this.widgetKeyGenerator.fromWidget(widget); this.logger.info( `deleting Widget=(${widget.id}) in Bucket=(${this.bucket})` ); const deleteReq = new DeleteObjectCommand({ Key: key, Bucket: this.bucket, }); await this.s3Client.send(deleteReq); this.logger.info(`successfully deleted Widget=(${widget.id}) in S3`); return widget; } }