feat:add Finds feature with media upload and R2 support
This commit is contained in:
74
src/lib/server/r2.ts
Normal file
74
src/lib/server/r2.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import {
|
||||
S3Client,
|
||||
PutObjectCommand,
|
||||
DeleteObjectCommand,
|
||||
GetObjectCommand
|
||||
} from '@aws-sdk/client-s3';
|
||||
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
||||
import { env } from '$env/dynamic/private';
|
||||
|
||||
// Environment variables with validation
|
||||
const R2_ACCOUNT_ID = env.R2_ACCOUNT_ID;
|
||||
const R2_ACCESS_KEY_ID = env.R2_ACCESS_KEY_ID;
|
||||
const R2_SECRET_ACCESS_KEY = env.R2_SECRET_ACCESS_KEY;
|
||||
const R2_BUCKET_NAME = env.R2_BUCKET_NAME;
|
||||
|
||||
// Validate required environment variables
|
||||
function validateR2Config() {
|
||||
if (!R2_ACCOUNT_ID) throw new Error('R2_ACCOUNT_ID environment variable is required');
|
||||
if (!R2_ACCESS_KEY_ID) throw new Error('R2_ACCESS_KEY_ID environment variable is required');
|
||||
if (!R2_SECRET_ACCESS_KEY)
|
||||
throw new Error('R2_SECRET_ACCESS_KEY environment variable is required');
|
||||
if (!R2_BUCKET_NAME) throw new Error('R2_BUCKET_NAME environment variable is required');
|
||||
}
|
||||
|
||||
export const r2Client = new S3Client({
|
||||
region: 'auto',
|
||||
endpoint: `https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
|
||||
credentials: {
|
||||
accessKeyId: R2_ACCESS_KEY_ID!,
|
||||
secretAccessKey: R2_SECRET_ACCESS_KEY!
|
||||
}
|
||||
});
|
||||
|
||||
export const R2_PUBLIC_URL = `https://pub-${R2_ACCOUNT_ID}.r2.dev`;
|
||||
|
||||
export async function uploadToR2(file: File, path: string, contentType: string): Promise<string> {
|
||||
validateR2Config();
|
||||
|
||||
const buffer = Buffer.from(await file.arrayBuffer());
|
||||
|
||||
await r2Client.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: R2_BUCKET_NAME,
|
||||
Key: path,
|
||||
Body: buffer,
|
||||
ContentType: contentType,
|
||||
CacheControl: 'public, max-age=31536000, immutable'
|
||||
})
|
||||
);
|
||||
|
||||
return `${R2_PUBLIC_URL}/${path}`;
|
||||
}
|
||||
|
||||
export async function deleteFromR2(path: string): Promise<void> {
|
||||
validateR2Config();
|
||||
|
||||
await r2Client.send(
|
||||
new DeleteObjectCommand({
|
||||
Bucket: R2_BUCKET_NAME,
|
||||
Key: path
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export async function getSignedR2Url(path: string, expiresIn = 3600): Promise<string> {
|
||||
validateR2Config();
|
||||
|
||||
const command = new GetObjectCommand({
|
||||
Bucket: R2_BUCKET_NAME,
|
||||
Key: path
|
||||
});
|
||||
|
||||
return await getSignedUrl(r2Client, command, { expiresIn });
|
||||
}
|
||||
Reference in New Issue
Block a user