Add Hardcover shelf sync & unify book mappings

Introduce Hardcover provider support and consolidate per-provider book mapping tables into a unified BookMapping model. Adds two Prisma migrations (add_hardcover_shelves, unify_book_mappings), new backend services (hardcover-api, shelf-sync-core), and provider-specific sync logic and API routes for hardcover shelves with token/list validation. Frontend: new HardcoverForm component, refactor AddShelfModal to support Hardcover, hook updates, and small UI/accessibility tweaks. Also add documentation for Goodreads and Hardcover sync flows and update tests to cover scheduler/prisma helpers.
This commit is contained in:
kikootwo
2026-03-04 10:11:19 -05:00
parent 6ca2e964e8
commit 338331d006
23 changed files with 1613 additions and 1391 deletions
+36
View File
@@ -0,0 +1,36 @@
/**
* Component: Shelf Helpers
* Documentation: documentation/frontend/components.md
*/
/**
* Parse a JSON string of cover/book data into a typed array.
* Returns an empty array on parse failure (graceful degradation).
*/
export function processBooks(
coverUrls: string | null,
): { coverUrl: string; asin: string | null; title: string; author: string }[] {
if (!coverUrls) return [];
let parsed: unknown;
try {
parsed = JSON.parse(coverUrls);
} catch {
return [];
}
if (!Array.isArray(parsed)) return [];
return parsed.map((item: unknown) => {
if (typeof item === 'string') {
return { coverUrl: item, asin: null, title: '', author: '' };
}
const obj = item as Record<string, unknown>;
return {
coverUrl: (obj.coverUrl as string) || '',
asin: (obj.asin as string) || null,
title: (obj.title as string) || '',
author: (obj.author as string) || '',
};
});
}