chore: initial project scaffold
Set up Mangalord with a Rust/axum backend, SvelteKit frontend, Postgres, and Docker Compose deployment. Establishes the architecture and TDD patterns the project will extend: - Hexagonal-ish backend layering (domain / repo / storage / api) with a pluggable Storage trait (LocalStorage today, S3 as a future impl). - Initial migration: users, mangas, chapters, bookmarks. - Vertical slice for mangas (list, search, create, get) with #[sqlx::test] integration coverage and storage unit tests. - SvelteKit frontend using Svelte 5 runes, typed API client, Vitest unit tests and Playwright e2e with route mocking. - CLAUDE.md documenting layering, TDD/git/SemVer workflow rules, and extension points (tags, fulltext search, OCR, S3, auth). - Project-scoped .claude/settings.json with permission allowlist for the toolchain (git, cargo, npm/vite, docker, psql, gh, doc fetches). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
36
frontend/src/lib/api/mangas.ts
Normal file
36
frontend/src/lib/api/mangas.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { request, type Manga } from './client';
|
||||
|
||||
export type ListOptions = {
|
||||
search?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
};
|
||||
|
||||
export async function listMangas(opts: ListOptions = {}): Promise<Manga[]> {
|
||||
const params = new URLSearchParams();
|
||||
if (opts.search) params.set('search', opts.search);
|
||||
if (opts.limit != null) params.set('limit', String(opts.limit));
|
||||
if (opts.offset != null) params.set('offset', String(opts.offset));
|
||||
const qs = params.toString();
|
||||
return request<Manga[]>(`/mangas${qs ? `?${qs}` : ''}`);
|
||||
}
|
||||
|
||||
export async function getManga(id: string): Promise<Manga> {
|
||||
return request<Manga>(`/mangas/${encodeURIComponent(id)}`);
|
||||
}
|
||||
|
||||
export type NewManga = {
|
||||
title: string;
|
||||
author?: string | null;
|
||||
description?: string | null;
|
||||
};
|
||||
|
||||
export async function createManga(input: NewManga): Promise<Manga> {
|
||||
return request<Manga>('/mangas', {
|
||||
method: 'POST',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify(input)
|
||||
});
|
||||
}
|
||||
|
||||
export type { Manga };
|
||||
Reference in New Issue
Block a user