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:
@@ -30,6 +30,20 @@ async function handleResponse(response: Response) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The body to forward, as fetch init options.
|
||||
*
|
||||
* Passed through as a stream rather than read into memory first: this process should
|
||||
* never hold a whole upload, which for a zipped Calibre library could be many
|
||||
* gigabytes. A request with no body contributes nothing, since `duplex` without a body
|
||||
* is rejected.
|
||||
*/
|
||||
function bodyOf(request: Request) {
|
||||
if (!request.body) return {};
|
||||
|
||||
return { body: request.body, duplex: 'half' } as RequestInit;
|
||||
}
|
||||
|
||||
// Shared function to prepare the request with authentication
|
||||
function prepareRequest(locals: App.Locals, request: Request) {
|
||||
const token = locals.authToken || 'server-default-token';
|
||||
@@ -76,13 +90,14 @@ export const POST: RequestHandler = async ({ params, locals, fetch, request, url
|
||||
const backendUrl = `${BACKEND_API_URL}/${path}${queryString}`;
|
||||
const headers = prepareRequest(locals, request);
|
||||
|
||||
// Get the request body
|
||||
const body = await request.arrayBuffer();
|
||||
|
||||
const response = await fetch(backendUrl, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body
|
||||
// Streamed, not buffered. `arrayBuffer()` held the whole upload in this
|
||||
// process before forwarding a byte of it, which is survivable for one book
|
||||
// and not for a zipped Calibre library. `duplex: 'half'` is required by the
|
||||
// fetch spec whenever the body is a stream.
|
||||
...bodyOf(request)
|
||||
});
|
||||
|
||||
return handleResponse(response);
|
||||
@@ -100,13 +115,10 @@ export const PATCH: RequestHandler = async ({ params, locals, fetch, request, ur
|
||||
const backendUrl = `${BACKEND_API_URL}/${path}${queryString}`;
|
||||
const headers = prepareRequest(locals, request);
|
||||
|
||||
// Get the request body
|
||||
const body = await request.arrayBuffer();
|
||||
|
||||
const response = await fetch(backendUrl, {
|
||||
method: 'PATCH',
|
||||
headers,
|
||||
body
|
||||
...bodyOf(request)
|
||||
});
|
||||
|
||||
return handleResponse(response);
|
||||
|
||||
Reference in New Issue
Block a user