import type { SupabaseClient } from '@supabase/supabase-js'; import type { Database, Document } from '$lib/supabase/types'; import { createLogger } from '$lib/utils/logger'; const log = createLogger('api.documents'); export async function fetchDocuments( supabase: SupabaseClient, orgId: string ): Promise { const { data, error } = await supabase .from('documents') .select('*') .eq('org_id', orgId) .order('type', { ascending: false }) // folders first .order('name'); if (error) { log.error('fetchDocuments failed', { error, data: { orgId } }); throw error; } log.debug('fetchDocuments ok', { data: { count: data?.length ?? 0 } }); return data ?? []; } export async function createDocument( supabase: SupabaseClient, orgId: string, name: string, type: 'folder' | 'document' | 'kanban', parentId: string | null = null, userId: string, options?: { id?: string; content?: import('$lib/supabase/types').Json } ): Promise { let content: import('$lib/supabase/types').Json | null = options?.content ?? null; if (!content && type === 'document') { content = { type: 'doc', content: [] }; } const { data, error } = await supabase .from('documents') .insert({ ...(options?.id ? { id: options.id } : {}), org_id: orgId, name, type, parent_id: parentId, created_by: userId, content, }) .select() .single(); if (error) { log.error('createDocument failed', { error, data: { orgId, name, type, parentId } }); throw error; } log.info('createDocument ok', { data: { id: data.id, name, type } }); return data; } export async function updateDocument( supabase: SupabaseClient, id: string, updates: Partial> ): Promise { const { data, error } = await supabase .from('documents') .update({ ...updates, updated_at: new Date().toISOString() }) .eq('id', id) .select() .single(); if (error) { log.error('updateDocument failed', { error, data: { id, updates } }); throw error; } return data; } export async function deleteDocument( supabase: SupabaseClient, id: string ): Promise { const { error } = await supabase.from('documents').delete().eq('id', id); if (error) { log.error('deleteDocument failed', { error, data: { id } }); throw error; } } export async function moveDocument( supabase: SupabaseClient, id: string, newParentId: string | null ): Promise { const { error } = await supabase .from('documents') .update({ parent_id: newParentId, updated_at: new Date().toISOString() }) .eq('id', id); if (error) { log.error('moveDocument failed', { error, data: { id, newParentId } }); throw error; } } export async function copyDocument( supabase: SupabaseClient, doc: Pick, orgId: string, userId: string ): Promise { const { data, error } = await supabase .from('documents') .insert({ org_id: orgId, name: `${doc.name} (copy)`, type: doc.type, parent_id: doc.parent_id, created_by: userId, content: doc.content, }) .select() .single(); if (error) { log.error('copyDocument failed', { error, data: { orgId, name: doc.name } }); throw error; } log.info('copyDocument ok', { data: { id: data.id, name: data.name } }); return data; } export function subscribeToDocuments( supabase: SupabaseClient, orgId: string, onInsert: (doc: Document) => void, onUpdate: (doc: Document) => void, onDelete: (id: string) => void ) { return supabase .channel(`documents:${orgId}`) .on( 'postgres_changes', { event: 'INSERT', schema: 'public', table: 'documents', filter: `org_id=eq.${orgId}` }, (payload) => onInsert(payload.new as Document) ) .on( 'postgres_changes', { event: 'UPDATE', schema: 'public', table: 'documents', filter: `org_id=eq.${orgId}` }, (payload) => onUpdate(payload.new as Document) ) .on( 'postgres_changes', { event: 'DELETE', schema: 'public', table: 'documents', filter: `org_id=eq.${orgId}` }, (payload) => onDelete((payload.old as { id: string }).id) ) .subscribe(); }