Files
FlockPal/backend/src/storage/imageStorageConfig.ts
T
2026-05-02 10:24:58 -04:00

84 lines
2.2 KiB
TypeScript

export type ImageStorageProvider = 'database' | 's3';
export type S3ImageStorageConfig = {
provider: 's3';
endpoint: string;
region: string;
bucket: string;
accessKeyId: string;
secretAccessKey: string;
publicBaseUrl: string | null;
keyPrefix: string;
};
const trimOptional = (value: string | undefined) => {
const trimmed = value?.trim();
return trimmed ? trimmed : null;
};
export const getImageStorageProvider = (): ImageStorageProvider =>
process.env.IMAGE_STORAGE_PROVIDER === 's3' ? 's3' : 'database';
export const getS3ImageStorageConfig = (): S3ImageStorageConfig | null => {
if (getImageStorageProvider() !== 's3') {
return null;
}
const endpoint = trimOptional(process.env.S3_ENDPOINT);
const region = trimOptional(process.env.S3_REGION);
const bucket = trimOptional(process.env.S3_BUCKET);
const accessKeyId = trimOptional(process.env.S3_ACCESS_KEY_ID);
const secretAccessKey = trimOptional(process.env.S3_SECRET_ACCESS_KEY);
if (!endpoint || !region || !bucket || !accessKeyId || !secretAccessKey) {
return null;
}
return {
provider: 's3',
endpoint,
region,
bucket,
accessKeyId,
secretAccessKey,
publicBaseUrl: trimOptional(process.env.S3_PUBLIC_BASE_URL),
keyPrefix: trimOptional(process.env.S3_KEY_PREFIX) ?? 'bird-photos',
};
};
export const isS3ImageStorageConfigured = () => getS3ImageStorageConfig() !== null;
export const buildBirdPhotoObjectKey = ({
workspaceId,
birdId,
extension,
now = new Date(),
}: {
workspaceId: number;
birdId: string;
extension: string;
now?: Date;
}) => {
const prefix = trimOptional(process.env.S3_KEY_PREFIX) ?? 'bird-photos';
const safeExtension = extension.replace(/^\./, '').toLowerCase() || 'bin';
const timestamp = now.toISOString().replace(/[:.]/g, '-');
return `${prefix}/workspace-${workspaceId}/${birdId}/${timestamp}.${safeExtension}`;
};
export const getImageExtensionFromContentType = (contentType: string) => {
switch (contentType.toLowerCase()) {
case 'image/jpeg':
case 'image/jpg':
return 'jpg';
case 'image/png':
return 'png';
case 'image/webp':
return 'webp';
case 'image/gif':
return 'gif';
default:
return 'bin';
}
};