Add works table and ASIN deduping

Add persistent cross-ASIN "works" mapping and client-side deduplication to improve library matching. Introduces a Prisma migration and models (Work, WorkAsin) plus src/lib/services/works.service for persisting dedup groups, seeding ASINs at request time, and sibling lookup. Adds a deduplication utility (deduplicate-audiobooks) that normalizes titles/narrators, compares durations, and returns grouping metadata; API routes (search, author, series) now deduplicate results before enrichment and fire-and-forget persist groups. Adds sibling-ASIN expansion into audiobook matcher and expands getAvailableAsins accordingly. Extracts runtime parsing into a shared parse-runtime util and updates audible scrapers/services to use it. Includes unit tests for dedup logic and works service and updates test Prisma mocks.
This commit is contained in:
kikootwo
2026-03-03 13:31:46 -05:00
parent ff80d995c5
commit 610873af6b
15 changed files with 1446 additions and 32 deletions
@@ -0,0 +1,42 @@
-- CreateTable
CREATE TABLE "works" (
"id" TEXT NOT NULL,
"title" TEXT NOT NULL,
"author" TEXT NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,
CONSTRAINT "works_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "work_asins" (
"id" TEXT NOT NULL,
"work_id" TEXT NOT NULL,
"asin" TEXT NOT NULL,
"narrator" TEXT,
"duration_minutes" INTEGER,
"is_canonical" BOOLEAN NOT NULL DEFAULT false,
"source" TEXT NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "work_asins_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "works_title_idx" ON "works"("title");
-- CreateIndex
CREATE INDEX "works_author_idx" ON "works"("author");
-- CreateIndex
CREATE UNIQUE INDEX "work_asins_asin_key" ON "work_asins"("asin");
-- CreateIndex
CREATE INDEX "work_asins_work_id_idx" ON "work_asins"("work_id");
-- CreateIndex
CREATE INDEX "work_asins_asin_idx" ON "work_asins"("asin");
-- AddForeignKey
ALTER TABLE "work_asins" ADD CONSTRAINT "work_asins_work_id_fkey" FOREIGN KEY ("work_id") REFERENCES "works"("id") ON DELETE CASCADE ON UPDATE CASCADE;