Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BUCKET_NAME="YOUR_BUCKET_NAME"
AWS_REGION="YOUR_AWS_REGION"
70 changes: 59 additions & 11 deletions amplify/functions/storeImages/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,41 @@ import { env } from '$amplify/env/storeImages'
const s3Client = new S3Client()

const bucketName = env.BUCKET_NAME
// URL base de CloudFront
const cloudFrontDomain = 'https://d1etr7t5j9fzio.cloudfront.net'
const awsRegion = env.AWS_REGION_BUCKET

// Determinar el dominio de CloudFront a usar, si aplica.
// cloudFrontDomainBase contendrá solo el nombre de host (ej: d123.cloudfront.net) si está en producción y configurado.
// De lo contrario, permanecerá vacío, y se usará la URL directa de S3.
let cloudFrontDomainBase = ''
if (
env.APP_ENV === 'production' &&
env.CLOUDFRONT_DOMAIN_NAME &&
env.CLOUDFRONT_DOMAIN_NAME.trim() !== ''
) {
cloudFrontDomainBase = env.CLOUDFRONT_DOMAIN_NAME
}

if (!bucketName) {
console.error(
'Error: BUCKET_NAME is not defined in the environment variables of the storeImages function.'
)
}
// AWS_REGION_BUCKET es necesario si no se usa CloudFront (no producción o CloudFront no configurado)
if (!awsRegion && (!cloudFrontDomainBase || cloudFrontDomainBase.trim() === '')) {
console.warn(
"Warning: AWS_REGION_BUCKET is not defined. S3 URLs may default to 'us-east-2' if CloudFront is not used or not configured."
)
}

// Advertencia específica si es producción pero CLOUDFRONT_DOMAIN_NAME no está configurado
if (
env.APP_ENV === 'production' &&
(!env.CLOUDFRONT_DOMAIN_NAME || env.CLOUDFRONT_DOMAIN_NAME.trim() === '')
) {
console.warn(
'Warning: APP_ENV is "production" but CLOUDFRONT_DOMAIN_NAME is not set. Image URLs will use S3 direct links.'
)
}

export const handler = async (event: any) => {
try {
Expand Down Expand Up @@ -88,12 +121,19 @@ async function listImages(storeId: string, limit: number = 1000, prefix: string
// Generar URLs para cada objeto usando CloudFront
const imagePromises = listResponse.Contents.map(async item => {
if (!item.Key) return null

// Omitir objetos de carpeta
if (item.Key.endsWith('/')) return null

// Construir la URL de CloudFront
const cloudFrontUrl = `${cloudFrontDomain}/${item.Key}`
let imageUrl: string
const s3Key = item.Key

if (cloudFrontDomainBase && cloudFrontDomainBase.trim() !== '') {
// Usar CloudFront para producción
imageUrl = `https://${cloudFrontDomainBase}/${s3Key}`
} else {
// Fallback a la URL de S3 para otros entornos o si CloudFront no está configurado
const regionForS3Url = awsRegion || 'us-east-2'
imageUrl = `https://${bucketName}.s3.${regionForS3Url}.amazonaws.com/${s3Key}`
}

// Extraer el nombre del archivo de la clave
const keyParts = item.Key.split('/')
Expand All @@ -110,7 +150,7 @@ async function listImages(storeId: string, limit: number = 1000, prefix: string

return {
key: item.Key,
url: cloudFrontUrl,
url: imageUrl, // Usar la URL construida dinámicamente
filename,
lastModified: item.LastModified,
size: item.Size,
Expand Down Expand Up @@ -165,13 +205,21 @@ async function uploadImage(

await s3Client.send(putCommand)

// Construir la URL de CloudFront
const cloudFrontUrl = `${cloudFrontDomain}/${key}`
let imageUrl: string
const s3Key = key

if (cloudFrontDomainBase && cloudFrontDomainBase.trim() !== '') {
// Usar CloudFront para producción
imageUrl = `https://${cloudFrontDomainBase}/${s3Key}`
} else {
// Fallback a la URL de S3 para otros entornos o si CloudFront no está configurado
const regionForS3Url = awsRegion || 'us-east-2'
imageUrl = `https://${bucketName}.s3.${regionForS3Url}.amazonaws.com/${s3Key}`
}

// Crear un objeto de imagen para devolver
const image = {
key,
url: cloudFrontUrl,
url: imageUrl, // Usar la URL construida dinámicamente
filename,
lastModified: new Date(),
size: buffer.length,
Expand Down
3 changes: 3 additions & 0 deletions amplify/functions/storeImages/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ export const storeImages = defineFunction({
resourceGroupName: 'storeImages',
environment: {
BUCKET_NAME: secret('BUCKET_NAME'),
AWS_REGION_BUCKET: secret('AWS_REGION_BUCKET'),
CLOUDFRONT_DOMAIN_NAME: secret('CLOUDFRONT_DOMAIN_NAME'),
APP_ENV: secret('APP_ENV'),
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ export function useUpdateProfilePicture() {
}).result

// 2. Construir la URL pública manualmente.
const bucketName = outputs.storage.bucket_name
const region = outputs.storage.aws_region
const publicUrl = `https://${bucketName}.s3.${region}.amazonaws.com/${result.path}`
const bucketName = process.env.NEXT_PUBLIC_S3_URL

if (!bucketName) {
throw new Error('There is no bucket for profile pictures')
}

const publicUrl = `${bucketName}/${result.path}`

// 3. Actualizar el atributo 'picture' del usuario con la URL pública.
await updateUserAttributes({
Expand All @@ -42,7 +46,7 @@ export function useUpdateProfilePicture() {
},
})
} catch (error) {
console.error('Error al actualizar la foto de perfil:', error)
console.error('Error updating profile picture:', error)
} finally {
setIsLoading(false)
}
Expand Down
7 changes: 3 additions & 4 deletions app/store/hooks/useLogoUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ export function useLogoUpload(): UseLogoUploadReturn {
const [error, setError] = useState<string | null>(null)

// Obtener el bucket correcto para logos de tienda
const logoBucket = outputs.storage.bucket_name
const aws_region = outputs.storage.aws_region
const bucketName = process.env.NEXT_PUBLIC_S3_URL

if (!logoBucket) {
if (!bucketName) {
throw new Error('There is no bucket for store logos')
}

Expand Down Expand Up @@ -63,7 +62,7 @@ export function useLogoUpload(): UseLogoUploadReturn {
}).result

// Construir la URL pública correcta usando el nombre del bucket
const publicUrl = `https://${logoBucket}.s3.${aws_region}.amazonaws.com/${key}`
const publicUrl = `${bucketName}/${key}`

setStatus('success')

Expand Down
7 changes: 3 additions & 4 deletions app/store/hooks/useProductImageUpload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@ export function useProductImageUpload() {
const [error, setError] = useState<Error | null>(null)

// Obtener el bucket correcto para imágenes de productos
const productBucket = outputs.storage.bucket_name
const aws_region = outputs.storage.aws_region
const bucketName = process.env.NEXT_PUBLIC_S3_URL

if (!productBucket) {
if (!bucketName) {
throw new Error('There is no bucket for product images')
}

Expand All @@ -46,7 +45,7 @@ export function useProductImageUpload() {
}).result

// Construir la URL pública correcta usando el nombre del bucket
const publicUrl = `https://${productBucket}.s3.${aws_region}.amazonaws.com/${result.path}`
const publicUrl = `${bucketName}/${result.path}`
return {
url: publicUrl,
alt: '',
Expand Down