Checkpoint: Audit et refactoring : centralisation robuste du suivi lu/non lu, suppression des captures SQL silencieuses, migration d’unicité avec déduplication des lectures existantes, correction du reclassement AAP via classifyAap, nettoyage de cinq composants template non utilisés, nettoyage des lectures lors des purges/fusions RSS et découpage dynamique du frontend. 27 tests Vitest, TypeScript et build de production validés.

This commit is contained in:
Manus
2026-08-17 20:21:45 +00:00
parent 1344d3c060
commit e4a389cc67
18 changed files with 1343 additions and 2348 deletions

View File

@@ -14,7 +14,7 @@
*/
import { XMLParser } from "fast-xml-parser";
import * as crypto from "crypto";
import { getDb } from "./db";
import { getDb, removeArticleReadRecords } from "./db";
import {
rssFeeds,
veilleItems,
@@ -775,6 +775,7 @@ export async function migrateExistingItems(): Promise<MigrationSummary> {
} catch (e: any) {
// Si le nouveau dedupKey existe déjà → cet article est un doublon, le supprimer
if (e?.code === "ER_DUP_ENTRY" || e?.cause?.code === "ER_DUP_ENTRY" || e?.cause?.message?.includes("Duplicate entry")) {
await removeArticleReadRecords("veille", [row.id]);
await db.delete(veilleItems).where(eq(veilleItems.id, row.id));
veilleMerged++;
} else {
@@ -817,6 +818,7 @@ export async function migrateExistingItems(): Promise<MigrationSummary> {
// Supprimer les doublons
for (const dup of duplicates) {
await removeArticleReadRecords("veille", [dup.id]);
await db.delete(veilleItems).where(eq(veilleItems.id, dup.id));
veilleMerged++;
}
@@ -825,6 +827,7 @@ export async function migrateExistingItems(): Promise<MigrationSummary> {
// Si le newDedupKey existe déjà → supprimer tout le groupe
if (e?.code === "ER_DUP_ENTRY" || e?.cause?.code === "ER_DUP_ENTRY" || e?.cause?.message?.includes("Duplicate entry")) {
for (const row of sorted) {
await removeArticleReadRecords("veille", [row.id]);
await db.delete(veilleItems).where(eq(veilleItems.id, row.id));
veilleMerged++;
}
@@ -868,6 +871,7 @@ export async function migrateExistingItems(): Promise<MigrationSummary> {
} catch (e: any) {
// Si le nouveau dedupKey existe déjà → cet article est un doublon, le supprimer
if (e?.code === "ER_DUP_ENTRY" || e?.cause?.code === "ER_DUP_ENTRY" || e?.cause?.message?.includes("Duplicate entry")) {
await removeArticleReadRecords("aap", [row.id]);
await db.delete(aapItems).where(eq(aapItems.id, row.id));
aapMerged++;
} else {
@@ -903,6 +907,7 @@ export async function migrateExistingItems(): Promise<MigrationSummary> {
.where(eq(aapItems.id, primary.id));
for (const dup of duplicates) {
await removeArticleReadRecords("aap", [dup.id]);
await db.delete(aapItems).where(eq(aapItems.id, dup.id));
aapMerged++;
}
@@ -911,6 +916,7 @@ export async function migrateExistingItems(): Promise<MigrationSummary> {
// Si le newDedupKey existe déjà → supprimer tout le groupe
if (e?.code === "ER_DUP_ENTRY" || e?.cause?.code === "ER_DUP_ENTRY" || e?.cause?.message?.includes("Duplicate entry")) {
for (const row of sorted) {
await removeArticleReadRecords("aap", [row.id]);
await db.delete(aapItems).where(eq(aapItems.id, row.id));
aapMerged++;
}