70 lines
2.5 KiB
TypeScript
70 lines
2.5 KiB
TypeScript
// server/supabase/functions/embed-chunks/supabase-knowledge-store.ts
|
|
// KnowledgeIndexStore adapter over the service-role Supabase client.
|
|
|
|
import type { createClient } from '@supabase/supabase-js'
|
|
import { type KnowledgeChunkRow, type KnowledgeIndexStore, KnowledgeStorageError } from './handler.ts'
|
|
|
|
type SupabaseClient = ReturnType<typeof createClient>
|
|
|
|
export function createSupabaseKnowledgeStore(client: SupabaseClient): KnowledgeIndexStore {
|
|
return {
|
|
async documentOwner(documentId) {
|
|
const { data, error } = await client
|
|
.from('knowledge_documents')
|
|
.select('id,user_id')
|
|
.eq('id', documentId)
|
|
.maybeSingle()
|
|
if (error) throw new KnowledgeStorageError()
|
|
const row = data as { user_id?: unknown } | null
|
|
return row && typeof row.user_id === 'string' ? row.user_id : null
|
|
},
|
|
async countChunks(documentId, pendingOnly) {
|
|
let query = client
|
|
.from('knowledge_chunks')
|
|
.select('id', { count: 'exact', head: true })
|
|
.eq('document_id', documentId)
|
|
if (pendingOnly) query = query.is('embedding', null)
|
|
const { count, error } = await query
|
|
if (error) throw new KnowledgeStorageError()
|
|
return count
|
|
},
|
|
async listPendingChunks(documentId, limit) {
|
|
const { data, error } = await client
|
|
.from('knowledge_chunks')
|
|
.select('id,content')
|
|
.eq('document_id', documentId)
|
|
.is('embedding', null)
|
|
.order('chunk_index', { ascending: true })
|
|
.limit(limit)
|
|
if (error) throw new KnowledgeStorageError()
|
|
return (data ?? []) as KnowledgeChunkRow[]
|
|
},
|
|
async saveEmbedding(documentId, chunkId, embedding) {
|
|
const { error } = await client
|
|
.from('knowledge_chunks')
|
|
.update({ embedding })
|
|
.eq('id', chunkId)
|
|
.eq('document_id', documentId)
|
|
return !error
|
|
},
|
|
async clearIndexed(documentId, userId) {
|
|
let query = client
|
|
.from('knowledge_documents')
|
|
.update({ indexed: false, indexed_at: null })
|
|
.eq('id', documentId)
|
|
if (userId !== null) query = query.eq('user_id', userId)
|
|
const { error } = await query
|
|
return !error
|
|
},
|
|
async markIndexed(documentId, userId) {
|
|
const { data, error } = await client
|
|
.from('knowledge_documents')
|
|
.update({ indexed: true, indexed_at: new Date().toISOString() })
|
|
.eq('id', documentId)
|
|
.eq('user_id', userId)
|
|
.select('id')
|
|
.maybeSingle()
|
|
return !error && Boolean(data)
|
|
},
|
|
}
|
|
}
|