Files
ostandari/server/plugins/s3Storage.js
T
2026-06-19 12:11:18 +03:30

94 lines
1.9 KiB
JavaScript

const {
S3Client,
PutObjectCommand,
DeleteObjectCommand,
} = require("@aws-sdk/client-s3");
const config = {
bucket: process.env.BUCKET_NAME,
region: process.env.BUCKET_REGION || "us-west-2",
endpoint: process.env.PARSPACK_S3_ENDPOINT,
accessKeyId: process.env.BUCKET_ACCESS_KEY,
secretAccessKey: process.env.BUCKET_SECRET_KEY,
publicUrl: process.env.BUCKET_PUBLIC_URL || process.env.PARSPACK_S3_ENDPOINT,
};
let s3Client = null;
const isConfigured = () =>
Boolean(
config.bucket &&
config.endpoint &&
config.accessKeyId &&
config.secretAccessKey
);
const getClient = () => {
if (!isConfigured()) {
throw new Error("S3 storage is not configured");
}
if (!s3Client) {
s3Client = new S3Client({
region: config.region,
endpoint: config.endpoint,
credentials: {
accessKeyId: config.accessKeyId,
secretAccessKey: config.secretAccessKey,
},
forcePathStyle: true,
});
}
return s3Client;
};
const normalizeKey = (key) => key.replace(/^\/+/, "");
const getPublicUrl = (key) => {
const normalizedKey = normalizeKey(key);
const baseUrl = (config.publicUrl || config.endpoint).replace(/\/+$/, "");
return `${baseUrl}/${normalizedKey}`;
};
const uploadBuffer = async (
key,
buffer,
contentType = "application/octet-stream"
) => {
const normalizedKey = normalizeKey(key);
await getClient().send(
new PutObjectCommand({
Bucket: config.bucket,
Key: normalizedKey,
Body: buffer,
ContentType: contentType,
ACL: "public-read",
})
);
return {
key: normalizedKey,
url: getPublicUrl(normalizedKey),
};
};
const deleteObject = async (key) => {
const normalizedKey = normalizeKey(key);
await getClient().send(
new DeleteObjectCommand({
Bucket: config.bucket,
Key: normalizedKey,
})
);
};
module.exports = {
isConfigured,
getPublicUrl,
uploadBuffer,
deleteObject,
};