Node and servers
Paths, batches and a command line — the conveniences that only make sense where there is a file system.
Everything else in Genom runs in a browser too, and pays for it by refusing to know about paths, file systems and worker threads. @genomdev/genom/node is where that knowledge is allowed, and it is deliberately thin.
import { extractFile, extractAll, openFile, hashFile } from '@genomdev/genom/node';
// One file, by path.
const doc = await extractFile('report.docx');
doc.toMarkdown();
// A corpus, with a fixed number in flight. Failures are collected, not thrown:
// ten thousand documents always contain a few nobody can open.
const results = await extractAll(paths, { concurrency: 8 });
for (const { path, document, error } of results) {
if (error) console.warn(path, error.message);
}
// The hash an address will carry, without parsing the file.
const hash = await hashFile('report.docx');When the format is known
Reaching for the umbrella means all four parsers are in the module graph. If a route only ever receives Word documents, ask Word directly — nothing else comes with it.
import { extractDocx } from '@genomdev/docx';
export async function POST(request: Request) {
const doc = await extractDocx(new Uint8Array(await request.arrayBuffer()));
return Response.json({ markdown: doc.toMarkdown() });
}The command line
The fastest way to see what extraction does to your own files, and useful in a pipeline on its own.
npx @genomdev/genom md report.docx
npx @genomdev/genom text *.docx --out corpus.txt
npx @genomdev/genom chunks handbook.docx --max-tokens 512 > chunks.jsonl
npx @genomdev/genom json deck.pptx --images referenceLong documents and the event loop
Parsing is synchronous work on a large buffer. On a server handling requests, put it in a worker thread rather than on the main one — extractAll bounds concurrency but does not move work off the thread it is called on.
Cancellation is supported everywhere through signal, and a cancelled parse stops at the next block boundary rather than at the end.
const controller = new AbortController();
setTimeout(() => controller.abort(), 5_000);
await extractFile('huge.pdf', { signal: controller.signal });