/** * Upload-side ingest path. * * BROWSER SURFACE — not part of the headless ingest core. This is a thin * wrapper over the headless `ingestPdf` that additionally pushes the bytes * into a per-session `PdfByteStore`, which mints a `blob:` URL and stamps it * onto `document.uri` so a viewer adapter can mount the PDF directly. * * 1. Read `file.arrayBuffer()` once into a `Uint8Array`. * 2. Run the existing `ingestPdf(bytes, { filename })` pipeline to produce * `{document, representation}`. * 3. Push the bytes into the per-session `PdfByteStore`. * 4. Hand the engine inputs back to the caller, which wires them via * `engine.documents.register(...)`. * * Keeping URL-minting inside the byte store (rather than at the call site) * means there is exactly one place that creates `blob:` URLs and exactly one * place that revokes them. */ import { ingestPdf, type IngestPdfResult } from "../pdf/ingest"; import type { PdfByteStore } from "./byte-store"; export interface IngestPdfFromFileOptions { /** Override the filename used as the document title. */ readonly title?: string; } export async function ingestPdfFromFile( file: File | Blob, store: PdfByteStore, options: IngestPdfFromFileOptions = {}, ): Promise { const bytes = new Uint8Array(await file.arrayBuffer()); const filename = "name" in file && typeof file.name === "string" ? file.name : undefined; const ingested = await ingestPdf(bytes, { ...(filename !== undefined ? { filename } : {}), ...(options.title !== undefined ? { title: options.title } : {}), }); const record = store.put(ingested.document.id, bytes); const document = { ...ingested.document, uri: record.blobUrl }; return { document, representation: ingested.representation }; }