mono/packages/ui/src/lib/uploadUtils.ts

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);
};