Files
bodyshop/server/utils/s3.js
2025-05-15 12:53:41 -07:00

126 lines
3.4 KiB
JavaScript

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 { getSignedUrl } = require("@aws-sdk/s3-request-presigner");
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;
}
};
const getPresignedUrl = async ({ bucketName, key }) => {
const command = new PutObjectCommand({
Bucket: bucketName,
Key: key,
StorageClass: "INTELLIGENT_TIERING"
});
const presignedUrl = await getSignedUrl(s3Client, command, { expiresIn: 360 });
return presignedUrl;
}
return {
uploadFileToS3,
downloadFileFromS3,
listFilesInS3Bucket,
deleteFileFromS3,
copyFileInS3,
fileExistsInS3,
getPresignedUrl,
...s3Client
};
};
module.exports = createS3Client();