feat: edit existing manga metadata (0.31.0)

Adds PUT /mangas/:id/cover (multipart) and DELETE /mangas/:id/cover so
covers can be replaced or cleared after creation, and wires a dedicated
/manga/[id]/edit SvelteKit route that combines the existing PATCH with
the new cover endpoints. Cover PUT cleans up the old blob when the
extension changes, swallowing StorageError::NotFound so a manually-gone
file doesn't surface as a 404 to the client. Edit link on the manga
detail page is gated on session.user, matching the auth posture of the
underlying handlers.

Also pins the local-dev port story via loadEnv() in vite.config.ts so
VITE_PORT / BACKEND_URL from a (gitignored) .env keep the dev URL
stable across runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-05-27 20:26:23 +02:00
parent 9ff49166a5
commit fa0a7da311
14 changed files with 1277 additions and 19 deletions

View File

@@ -109,6 +109,31 @@ export async function updateManga(
});
}
/**
* PUT /api/v1/mangas/:id/cover (multipart). Replaces the cover image and
* returns the refreshed detail. As with createManga the browser fills in
* the multipart boundary automatically, so we must NOT set Content-Type.
*/
export async function updateMangaCover(
id: string,
cover: Blob
): Promise<MangaDetail> {
const form = new FormData();
form.append('cover', cover);
return request<MangaDetail>(
`/v1/mangas/${encodeURIComponent(id)}/cover`,
{ method: 'PUT', body: form }
);
}
/** DELETE /api/v1/mangas/:id/cover. Returns the refreshed detail. */
export async function deleteMangaCover(id: string): Promise<MangaDetail> {
return request<MangaDetail>(
`/v1/mangas/${encodeURIComponent(id)}/cover`,
{ method: 'DELETE' }
);
}
export async function attachTag(
mangaId: string,
name: string