feat: import a Calibre library

Reads metadata.db and copies the books into a library — from a zip uploaded on
the library settings page, or from a path with `litestar calibre-import`. The
source is never touched, and re-running only picks up what is new.

Also names the formats mimetypes does not know: a Calibre library is full of
MOBI and AZW3, and a null content type used to fail the book endpoint.
This commit is contained in:
2026-08-17 13:38:44 -04:00
parent 85367daf7e
commit 55e00ba960
34 changed files with 4723 additions and 50 deletions
+5 -2
View File
@@ -167,8 +167,11 @@ Observed in the current tree — don't mistake these for intentional patterns to
`svelte/no-navigation-without-resolve` on plain `href`s, plus ~59 files Prettier would rewrite
(mostly vendored shadcn components). Check the files you touched, not the whole tree.
- `src/routes/api/[...path]/+server.ts` — all four handlers are annotated `RequestHandler` while the
import of that type is commented out at line 4. It also buffers whole responses with
`arrayBuffer()` and forwards no `Range` header, so book downloads are not streamed.
import of that type is commented out at line 4. It also buffers whole **responses** with
`arrayBuffer()` and forwards no `Range` header, so book downloads are not streamed. **Requests**
are streamed — POST and PATCH pass `request.body` through with `duplex: 'half'` (see `bodyOf`),
because a zipped Calibre library upload cannot be held in this process. The response side is
still buffered; see `TODO.md`.
- `src/app.d.ts``App.Locals["user"]` is typed from `lucide-svelte`'s `User` _icon_ component
rather than the `User` interface in `$lib/server/auth`.
- No CSP, which foliate's README asks for because EPUBs can carry scripts. See `TODO.md` for why it