First commit
This commit is contained in:
132
src/lib/api/documents.ts
Normal file
132
src/lib/api/documents.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
||||
import type { Database, Document } from '$lib/supabase/types';
|
||||
|
||||
export interface DocumentWithChildren extends Document {
|
||||
children?: DocumentWithChildren[];
|
||||
}
|
||||
|
||||
export async function fetchDocuments(
|
||||
supabase: SupabaseClient<Database>,
|
||||
orgId: string
|
||||
): Promise<Document[]> {
|
||||
const { data, error } = await supabase
|
||||
.from('documents')
|
||||
.select('*')
|
||||
.eq('org_id', orgId)
|
||||
.order('type', { ascending: false }) // folders first
|
||||
.order('name');
|
||||
|
||||
if (error) throw error;
|
||||
return data ?? [];
|
||||
}
|
||||
|
||||
export async function createDocument(
|
||||
supabase: SupabaseClient<Database>,
|
||||
orgId: string,
|
||||
name: string,
|
||||
type: 'folder' | 'document',
|
||||
parentId: string | null = null,
|
||||
userId: string
|
||||
): Promise<Document> {
|
||||
const { data, error } = await supabase
|
||||
.from('documents')
|
||||
.insert({
|
||||
org_id: orgId,
|
||||
name,
|
||||
type,
|
||||
parent_id: parentId,
|
||||
created_by: userId,
|
||||
content: type === 'document' ? { type: 'doc', content: [] } : null
|
||||
})
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function updateDocument(
|
||||
supabase: SupabaseClient<Database>,
|
||||
id: string,
|
||||
updates: Partial<Pick<Document, 'name' | 'content' | 'parent_id'>>
|
||||
): Promise<Document> {
|
||||
const { data, error } = await supabase
|
||||
.from('documents')
|
||||
.update({ ...updates, updated_at: new Date().toISOString() })
|
||||
.eq('id', id)
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (error) throw error;
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function deleteDocument(
|
||||
supabase: SupabaseClient<Database>,
|
||||
id: string
|
||||
): Promise<void> {
|
||||
const { error } = await supabase.from('documents').delete().eq('id', id);
|
||||
if (error) throw error;
|
||||
}
|
||||
|
||||
export async function moveDocument(
|
||||
supabase: SupabaseClient<Database>,
|
||||
id: string,
|
||||
newParentId: string | null
|
||||
): Promise<void> {
|
||||
const { error } = await supabase
|
||||
.from('documents')
|
||||
.update({ parent_id: newParentId, updated_at: new Date().toISOString() })
|
||||
.eq('id', id);
|
||||
|
||||
if (error) throw error;
|
||||
}
|
||||
|
||||
export function buildDocumentTree(documents: Document[]): DocumentWithChildren[] {
|
||||
const map = new Map<string, DocumentWithChildren>();
|
||||
const roots: DocumentWithChildren[] = [];
|
||||
|
||||
// First pass: create map
|
||||
documents.forEach((doc) => {
|
||||
map.set(doc.id, { ...doc, children: [] });
|
||||
});
|
||||
|
||||
// Second pass: build tree
|
||||
documents.forEach((doc) => {
|
||||
const node = map.get(doc.id)!;
|
||||
if (doc.parent_id && map.has(doc.parent_id)) {
|
||||
map.get(doc.parent_id)!.children!.push(node);
|
||||
} else {
|
||||
roots.push(node);
|
||||
}
|
||||
});
|
||||
|
||||
return roots;
|
||||
}
|
||||
|
||||
export function subscribeToDocuments(
|
||||
supabase: SupabaseClient<Database>,
|
||||
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();
|
||||
}
|
||||
Reference in New Issue
Block a user