85 lines
3.2 KiB
TypeScript
85 lines
3.2 KiB
TypeScript
import { supabase } from '@/integrations/supabase/client';
|
|
|
|
/**
|
|
* Uploads an image file to Supabase Storage.
|
|
* If the file is larger than the configured threshold (VITE_MAX_IMAGE_SIZE),
|
|
* it proxies the upload through the server (VITE_SERVER_IMAGE_API_URL) for resizing.
|
|
* Otherwise, it uploads directly to Supabase Storage.
|
|
*/
|
|
export const uploadImage = async (file: File, userId: string): Promise<{ publicUrl: string, meta?: any }> => {
|
|
if (!userId) throw new Error('User ID is required for upload');
|
|
|
|
console.log('uploading ', import.meta.env);
|
|
const MAX_SIZE = Number(import.meta.env.VITE_MAX_IMAGE_SIZE) || 1572864; // 1.5MB default
|
|
const SERVER_URL = import.meta.env.VITE_SERVER_IMAGE_API_URL;
|
|
|
|
// Use proxy if file is too large and server URL is configured
|
|
if (file.size > MAX_SIZE && SERVER_URL) {
|
|
console.log(`File size (${file.size}) exceeds threshold (${MAX_SIZE}), uploading via proxy...`);
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
|
|
// The server expects multipart/form-data
|
|
const response = await fetch(`${SERVER_URL}/api/images?forward=supabase&original=true`, {
|
|
method: 'POST',
|
|
body: formData,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorText = await response.text();
|
|
console.error('Proxy upload failed:', errorText);
|
|
throw new Error(`Failed to upload image via proxy: ${response.statusText}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
return { publicUrl: data.url, meta: data.meta };
|
|
} else {
|
|
// Direct Supabase upload
|
|
console.log(`File size (${file.size}) within threshold (${MAX_SIZE}), uploading directly...`);
|
|
const fileExt = file.name.split('.').pop();
|
|
// Generate a unique filename using user ID and timestamp/random string
|
|
const fileName = `${userId}/${Date.now()}-${Math.random().toString(36).substring(7)}.${fileExt}`;
|
|
|
|
const { error: uploadError } = await supabase.storage
|
|
.from('pictures')
|
|
.upload(fileName, file);
|
|
|
|
if (uploadError) throw uploadError;
|
|
|
|
const { data: { publicUrl } } = supabase.storage
|
|
.from('pictures')
|
|
.getPublicUrl(fileName);
|
|
|
|
return { publicUrl };
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Creates a picture record in the database.
|
|
*/
|
|
export const createPictureRecord = async (userId: string, file: File, publicUrl: string, meta?: any) => {
|
|
const { data, error } = await supabase
|
|
.from('pictures')
|
|
.insert({
|
|
user_id: userId,
|
|
title: file.name.split('.')[0] || 'Uploaded Image',
|
|
description: null,
|
|
image_url: publicUrl,
|
|
type: 'supabase-image',
|
|
meta: meta || {},
|
|
})
|
|
.select()
|
|
.single();
|
|
|
|
if (error) throw error;
|
|
return data;
|
|
};
|
|
|
|
/**
|
|
* Uploads an image and creates a picture record in one go.
|
|
*/
|
|
export const uploadAndCreatePicture = async (file: File, userId: string) => {
|
|
const { publicUrl, meta } = await uploadImage(file, userId);
|
|
return await createPictureRecord(userId, file, publicUrl, meta);
|
|
};
|