'use server'; import 'server-only'; import { createServerClient } from '@/utils/supabase'; import type { Result } from './index'; export type GetStorageProps = { bucket: string; url: string; seconds?: number; transform?: { width?: number; height?: number; quality?: number; format?: 'origin'; resize?: 'cover' | 'contain' | 'fill'; }; download?: boolean | string; }; export type UploadStorageProps = { bucket: string; path: string; file: File; options?: { cacheControl?: string; upsert?: boolean; contentType?: string; }; }; export type ReplaceStorageProps = { bucket: string; prevPath: string; file: File; options?: { cacheControl?: string; upsert?: boolean; contentType?: string; }; }; export type resizeImageProps = { file: File, options?: { maxWidth?: number, maxHeight?: number, quality?: number, } }; export const getSignedUrl = async ({ bucket, url, seconds = 3600, transform = {}, download = false, }: GetStorageProps): Promise> => { try { const supabase = await createServerClient(); const { data, error } = await supabase.storage .from(bucket) .createSignedUrl(url, seconds, { download, transform, }); if (error) throw error; if (!data?.signedUrl) throw new Error('No signed URL returned'); return { success: true, data: data.signedUrl }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error getting signed URL', }; } } export const getPublicUrl = async ({ bucket, url, transform = {}, download = false, }: GetStorageProps): Promise> => { try { const supabase = await createServerClient(); const { data } = supabase.storage .from(bucket) .getPublicUrl(url, { download, transform, }); if (!data?.publicUrl) throw new Error('No public URL returned'); return { success: true, data: data.publicUrl }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error getting public URL', }; } } export const uploadFile = async ({ bucket, path, file, options = {}, }: UploadStorageProps): Promise> => { try { const supabase = await createServerClient(); const { data, error } = await supabase.storage .from(bucket) .upload(path, file, options); if (error) throw error; if (!data?.path) throw new Error('No path returned from upload'); return { success: true, data: data.path }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error uploading file', }; } } export const replaceFile = async ({ bucket, prevPath, file, options = {}, }: ReplaceStorageProps): Promise> => { try { options.upsert = true; const supabase = await createServerClient(); //const deleteFileData = await deleteFile({ //bucket, //path: [...prevPath], //}); const { data, error } = await supabase.storage .from(bucket) //.update(path, file, options); .update(prevPath, file, options); if (error) throw error; if (!data?.path) throw new Error('No path returned from upload'); return { success: true, data: data.path }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error replacing file', }; } }; // Add a helper to delete files export const deleteFile = async ({ bucket, path, }: { bucket: string; path: string[]; }): Promise> => { try { const supabase = await createServerClient(); const { error } = await supabase.storage.from(bucket).remove(path); if (error) throw error; return { success: true, data: null }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error deleting file', }; } } // Add a helper to list files in a bucket export const listFiles = async ({ bucket, path = '', options = {}, }: { bucket: string; path?: string; options?: { limit?: number; offset?: number; sortBy?: { column: string; order: 'asc' | 'desc' }; }; }): Promise>> => { try { const supabase = await createServerClient(); const { data, error } = await supabase.storage .from(bucket) .list(path, options); if (error) throw error; if (!data) throw new Error('No data returned from list operation'); return { success: true, data }; } catch (error) { console.error('Could not list files!', error); return { success: false, error: error instanceof Error ? error.message : 'Unknown error listing files', }; } } export const resizeImage = async ({ file, options = {}, }: resizeImageProps): Promise => { const { maxWidth = 800, maxHeight = 800, quality = 0.8, } = options; return new Promise((resolve) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = (event) => { const img = new Image(); img.src = event.target?.result as string; img.onload = () => { let width = img.width; let height = img.height; if (width > height) { if (width > maxWidth) { height = Math.round((height * maxWidth / width)); width = maxWidth; } } else if (height > maxHeight) { width = Math.round((width * maxHeight / height)); height = maxHeight; } const canvas = document.createElement('canvas'); canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); ctx?.drawImage(img, 0, 0, width, height); canvas.toBlob( (blob) => { if (!blob) return; const resizedFile = new File([blob], file.name, { type: 'imgage/jpeg', lastModified: Date.now(), }); resolve(resizedFile); }, 'image/jpeg', quality ); }; }; }); };