const { S3Client, PutObjectCommand, GetObjectCommand, ListObjectsV2Command, DeleteObjectCommand, CopyObjectCommand } = require("@aws-sdk/client-s3"); const { defaultProvider } = require("@aws-sdk/credential-provider-node"); const { InstanceRegion } = require("./instanceMgr"); const { isString, isEmpty } = require("lodash"); const createS3Client = () => { const S3Options = { region: InstanceRegion(), credentials: defaultProvider() }; const isLocal = isString(process.env?.LOCALSTACK_HOSTNAME) && !isEmpty(process.env?.LOCALSTACK_HOSTNAME); if (isLocal) { S3Options.endpoint = `http://${process.env.LOCALSTACK_HOSTNAME}:4566`; S3Options.forcePathStyle = true; // Needed for LocalStack to avoid bucket name as hostname } const s3Client = new S3Client(S3Options); /** * Uploads a file to the specified S3 bucket and key. */ const uploadFileToS3 = async ({ bucketName, key, content, contentType }) => { const params = { Bucket: bucketName, Key: key, Body: content, ContentType: contentType ?? "application/json" }; const command = new PutObjectCommand(params); return await s3Client.send(command); }; /** * Downloads a file from the specified S3 bucket and key. */ const downloadFileFromS3 = async ({ bucketName, key }) => { const params = { Bucket: bucketName, Key: key }; const command = new GetObjectCommand(params); const data = await s3Client.send(command); return data.Body; }; /** * Lists objects in the specified S3 bucket. */ const listFilesInS3Bucket = async (bucketName, prefix = "") => { const params = { Bucket: bucketName, Prefix: prefix }; const command = new ListObjectsV2Command(params); const data = await s3Client.send(command); return data.Contents || []; }; /** * Deletes a file from the specified S3 bucket and key. */ const deleteFileFromS3 = async ({ bucketName, key }) => { const params = { Bucket: bucketName, Key: key }; const command = new DeleteObjectCommand(params); return await s3Client.send(command); }; /** * Copies a file within S3 from a source bucket/key to a destination bucket/key. */ const copyFileInS3 = async ({ sourceBucket, sourceKey, destinationBucket, destinationKey }) => { const params = { CopySource: `/${sourceBucket}/${sourceKey}`, Bucket: destinationBucket, Key: destinationKey }; const command = new CopyObjectCommand(params); return await s3Client.send(command); }; /** * Checks if a file exists in the specified S3 bucket and key. */ const fileExistsInS3 = async ({ bucketName, key }) => { try { await downloadFileFromS3({ bucketName, key }); return true; } catch (error) { if (error.name === "NoSuchKey" || error.name === "NotFound") { return false; } throw error; } }; return { uploadFileToS3, downloadFileFromS3, listFilesInS3Bucket, deleteFileFromS3, copyFileInS3, fileExistsInS3, ...s3Client }; }; module.exports = createS3Client();