UNPKG

@edgestore/server

Version:

Upload files with ease from React/Next.js

108 lines (105 loc) 4.22 kB
import { S3Client, HeadObjectCommand, PutObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { v4 } from 'uuid'; import { g as getEnv } from '../../shared-c6527780.mjs'; import '@edgestore/shared'; import '@panva/hkdf'; import 'cookie'; import 'jose'; function AWSProvider(options) { const { accessKeyId = getEnv('ES_AWS_ACCESS_KEY_ID'), secretAccessKey = getEnv('ES_AWS_SECRET_ACCESS_KEY'), region = getEnv('ES_AWS_REGION'), bucketName = getEnv('ES_AWS_BUCKET_NAME'), endpoint = getEnv('ES_AWS_ENDPOINT'), forcePathStyle = getEnv('ES_AWS_FORCE_PATH_STYLE') === 'true', overwritePath } = options ?? {}; const baseUrl = options?.baseUrl ?? getEnv('EDGE_STORE_BASE_URL') ?? (endpoint ? `${endpoint}/${bucketName}` : `https://${bucketName}.s3.${region}.amazonaws.com`); const credentials = accessKeyId && secretAccessKey ? { accessKeyId, secretAccessKey } : undefined; const s3Client = new S3Client({ region, credentials, endpoint, forcePathStyle }); return { name: 'aws', async init () { return {}; }, getBaseUrl () { return baseUrl; }, async getFile ({ url }) { const path = url.replace(`${baseUrl}/`, ''); const { ContentLength, LastModified } = await s3Client.send(new HeadObjectCommand({ Bucket: bucketName, Key: path })); if (!ContentLength || !LastModified) { throw new Error('File not found'); } return { url, metadata: {}, path: {}, size: ContentLength, uploadedAt: LastModified }; }, async requestUpload (params) { const { bucketName: esBucketName, fileInfo } = params; if (!bucketName) { throw new Error('S3 bucketName is not configured in AWSProviderOptions.'); } // Default S3 key (accessPath) construction logic const pathPrefix = `${esBucketName}${fileInfo.isPublic ? '/_public' : ''}`; const nameId = v4(); const extension = fileInfo.extension ? `.${fileInfo.extension.replace('.', '')}` : ''; const defaultResolvedFileName = fileInfo.fileName ?? `${nameId}${extension}`; const defaultFilePathFromMetadata = fileInfo.path.reduce((acc, item)=>{ return `${acc}/${item.value}`; }, ''); let accessPath = `${pathPrefix}${defaultFilePathFromMetadata}/${defaultResolvedFileName}`; if (overwritePath) { accessPath = await overwritePath({ esBucketName, fileInfo, defaultAccessPath: accessPath }); } const command = new PutObjectCommand({ Bucket: bucketName, Key: accessPath }); const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 60 * 60 }); const finalAccessUrl = `${baseUrl}/${accessPath.startsWith('/') ? accessPath.substring(1) : accessPath}`; return { uploadUrl: signedUrl, accessUrl: finalAccessUrl }; }, async requestUploadParts () { throw new Error('Not implemented'); }, async completeMultipartUpload () { throw new Error('Not implemented'); }, async confirmUpload () { throw new Error('Not implemented'); }, async deleteFile ({ url }) { if (!bucketName) { throw new Error('S3 bucketName is not configured in AWSProviderOptions for deleteFile.'); } const path = url.replace(`${baseUrl}/`, ''); await s3Client.send(new DeleteObjectCommand({ Bucket: bucketName, Key: path })); return { success: true }; } }; } export { AWSProvider };