AppView in a box as a Vite plugin thing hatk.dev
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: deduplicate labels per-source on insert, collapse at query time

Keeps insertLabels dedup scoped to (src, uri, val) so multiple labelers
can independently label the same content. Adds GROUP BY uri, val to
queryLabelsForUris to collapse duplicates for display.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

+2 -2
+2 -2
packages/hatk/src/database/db.ts
··· 760 760 ): Promise<void> { 761 761 if (labels.length === 0) return 762 762 for (const label of labels) { 763 - // Skip if an active (non-negated, non-expired, not-superseded-by-negation) label already exists 763 + // Skip if an active (non-negated, non-expired, not-superseded-by-negation) label already exists for this src+uri+val 764 764 const existing = await all( 765 765 `SELECT 1 FROM _labels l1 WHERE l1.src = $1 AND l1.uri = $2 AND l1.val = $3 AND l1.neg = false AND (l1.exp IS NULL OR l1.exp > CURRENT_TIMESTAMP) AND NOT EXISTS (SELECT 1 FROM _labels l2 WHERE l2.uri = l1.uri AND l2.val = l1.val AND l2.neg = true AND l2.id > l1.id) LIMIT 1`, 766 766 [label.src, label.uri, label.val], ··· 786 786 if (uris.length === 0) return new Map() 787 787 const placeholders = uris.map((_, i) => `$${i + 1}`).join(',') 788 788 const rows = await all<{ src: string; uri: string; val: string; neg: boolean; cts: string; exp: string | null }>( 789 - `SELECT src, uri, val, neg, cts, exp FROM _labels l1 WHERE uri IN (${placeholders}) AND (exp IS NULL OR exp > CURRENT_TIMESTAMP) AND neg = false AND NOT EXISTS (SELECT 1 FROM _labels l2 WHERE l2.uri = l1.uri AND l2.val = l1.val AND l2.neg = true AND l2.id > l1.id)`, 789 + `SELECT src, uri, val, neg, cts, exp FROM _labels l1 WHERE uri IN (${placeholders}) AND (exp IS NULL OR exp > CURRENT_TIMESTAMP) AND neg = false AND NOT EXISTS (SELECT 1 FROM _labels l2 WHERE l2.uri = l1.uri AND l2.val = l1.val AND l2.neg = true AND l2.id > l1.id) GROUP BY uri, val`, 790 790 uris, 791 791 ) 792 792 const result = new Map<string, Array<any>>()