/** * Property On — manuell abgelegte Newsquellen (Runde 10, §2.6). * * Der Dienst nimmt die Datei entgegen, gewinnt einmal ihren Text und legt * beides ab. Die Textextraktion gehört hierher und nicht in die Komponente: * Sie ist fachliche Arbeit, und sie soll für jeden künftigen Weg ins System — * Upload, Mailanhang, Ablageordner — dieselbe sein. */ import { IndexedDbResearchDocumentProvider } from '../provider/IndexedDbResearchDocumentProvider' import type { ResearchDocument } from '../domain/researchDocument' import { RESEARCH_DOCUMENT_MAX_BYTES } from '../domain/researchDocument' import { extractDocumentText, kindOf } from '../lib/documentText' import type { ListResponse, ItemResponse } from './types' import { throwServiceError } from './errors' const provider = IndexedDbResearchDocumentProvider export const researchDocumentService = { async getAll(): Promise> { try { const data = await provider.getAll() return { data, meta: { total: data.length, page: 1, pageSize: data.length, hasMore: false } } } catch (err) { throwServiceError(err) } }, async upload(file: File): Promise> { const kind = kindOf(file.name) if (!kind) { throw new Error('Nur PDF- und Word-Dateien (.pdf, .docx) können abgelegt werden.') } if (file.size > RESEARCH_DOCUMENT_MAX_BYTES) { throw new Error( `Die Datei ist zu gross (${Math.round(file.size / 1024 / 1024)} MB). Höchstens ${RESEARCH_DOCUMENT_MAX_BYTES / 1024 / 1024} MB.`, ) } try { const { text, note } = await extractDocumentText(file, kind) const doc: ResearchDocument = { id: `doc-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`, name: file.name, kind, size: file.size, uploadedAt: new Date().toISOString(), text, ...(note ? { extractionNote: note } : {}), } await provider.add(doc, file) return { data: doc } } catch (err) { throwServiceError(err) } }, async remove(id: string): Promise { try { await provider.remove(id) } catch (err) { throwServiceError(err) } }, }