2025-02-20 08:55:25 +01:00
|
|
|
import {
|
|
|
|
|
PutObjectCommand,
|
|
|
|
|
DeleteObjectCommand,
|
|
|
|
|
GetObjectCommand,
|
|
|
|
|
HeadObjectCommand,
|
|
|
|
|
} from '@aws-sdk/client-s3';
|
|
|
|
|
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
|
|
|
|
|
2025-06-11 00:14:17 +02:00
|
|
|
import { FileAttributes } from '@colanode/core';
|
|
|
|
|
import { s3Client } from '@colanode/server/data/storage';
|
|
|
|
|
import { config } from '@colanode/server/lib/config';
|
2025-02-12 21:45:02 +01:00
|
|
|
|
|
|
|
|
export const buildFilePath = (
|
|
|
|
|
workspaceId: string,
|
|
|
|
|
fileId: string,
|
|
|
|
|
fileAttributes: FileAttributes
|
|
|
|
|
) => {
|
|
|
|
|
return `files/${workspaceId}/${fileId}_${fileAttributes.version}${fileAttributes.extension}`;
|
|
|
|
|
};
|
2025-02-20 08:55:25 +01:00
|
|
|
|
|
|
|
|
export const buildUploadUrl = async (
|
|
|
|
|
path: string,
|
|
|
|
|
size: number,
|
|
|
|
|
mimeType: string
|
|
|
|
|
) => {
|
|
|
|
|
const command = new PutObjectCommand({
|
2025-06-11 00:14:17 +02:00
|
|
|
Bucket: config.storage.bucketName,
|
2025-02-20 08:55:25 +01:00
|
|
|
Key: path,
|
|
|
|
|
ContentLength: size,
|
|
|
|
|
ContentType: mimeType,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const expiresIn = 60 * 60 * 4; // 4 hours
|
2025-06-11 00:14:17 +02:00
|
|
|
const presignedUrl = await getSignedUrl(s3Client, command, {
|
2025-02-20 08:55:25 +01:00
|
|
|
expiresIn,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return presignedUrl;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const buildDownloadUrl = async (path: string) => {
|
|
|
|
|
const command = new GetObjectCommand({
|
2025-06-11 00:14:17 +02:00
|
|
|
Bucket: config.storage.bucketName,
|
2025-02-20 08:55:25 +01:00
|
|
|
Key: path,
|
|
|
|
|
});
|
|
|
|
|
|
2025-06-11 00:14:17 +02:00
|
|
|
const presignedUrl = await getSignedUrl(s3Client, command, {
|
2025-02-20 08:55:25 +01:00
|
|
|
expiresIn: 60 * 60 * 4, // 4 hours
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return presignedUrl;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const fetchFileMetadata = async (path: string) => {
|
|
|
|
|
const command = new HeadObjectCommand({
|
2025-06-11 00:14:17 +02:00
|
|
|
Bucket: config.storage.bucketName,
|
2025-02-20 08:55:25 +01:00
|
|
|
Key: path,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
try {
|
2025-06-11 00:14:17 +02:00
|
|
|
const headObject = await s3Client.send(command);
|
2025-02-20 08:55:25 +01:00
|
|
|
return {
|
|
|
|
|
size: headObject.ContentLength,
|
|
|
|
|
mimeType: headObject.ContentType,
|
|
|
|
|
};
|
|
|
|
|
} catch {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const deleteFile = async (path: string) => {
|
|
|
|
|
const command = new DeleteObjectCommand({
|
2025-06-11 00:14:17 +02:00
|
|
|
Bucket: config.storage.bucketName,
|
2025-02-20 08:55:25 +01:00
|
|
|
Key: path,
|
|
|
|
|
});
|
|
|
|
|
|
2025-06-11 00:14:17 +02:00
|
|
|
await s3Client.send(command);
|
2025-02-20 08:55:25 +01:00
|
|
|
};
|