fix: case-sensitive label matching broken on PostgreSQL
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 42s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 42s
syncLabels created Labels with original case (e.g. "Projet") but searched with .toLowerCase() (e.g. "projet"). On PostgreSQL (case- sensitive), findMany returned [] → labelRelations disconnected → orphan cleanup deleted ALL notebook labels. Fix: use Prisma mode:'insensitive' for findFirst and findMany, deduplicate case-insensitively while preserving original case. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -107,12 +107,22 @@ async function syncLabels(userId: string, noteLabels: string[] = [], notebookId?
|
|||||||
const nbScope = notebookId ?? null
|
const nbScope = notebookId ?? null
|
||||||
|
|
||||||
if (noteLabels.length > 0) {
|
if (noteLabels.length > 0) {
|
||||||
const trimmedNames = [...new Set(
|
// Deduplicate case-insensitively, keep original case
|
||||||
noteLabels.map(name => name?.trim()).filter((n): n is string => Boolean(n))
|
const seen = new Set<string>()
|
||||||
)]
|
const trimmedNames = noteLabels
|
||||||
|
.map(name => name?.trim())
|
||||||
|
.filter((n): n is string => Boolean(n))
|
||||||
|
.filter(n => {
|
||||||
|
const key = n.toLowerCase()
|
||||||
|
if (seen.has(key)) return false
|
||||||
|
seen.add(key)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
for (const name of trimmedNames) {
|
for (const name of trimmedNames) {
|
||||||
|
// Case-insensitive find on PostgreSQL
|
||||||
const existing = await prisma.label.findFirst({
|
const existing = await prisma.label.findFirst({
|
||||||
where: { userId, name, notebookId: nbScope },
|
where: { userId, name: { equals: name, mode: 'insensitive' }, notebookId: nbScope },
|
||||||
})
|
})
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
await prisma.label.create({
|
await prisma.label.create({
|
||||||
@@ -120,14 +130,16 @@ async function syncLabels(userId: string, noteLabels: string[] = [], notebookId?
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (trimmedNames.length === 0) return []
|
||||||
|
// Search with original case (case-insensitive on PostgreSQL)
|
||||||
|
return prisma.label.findMany({
|
||||||
|
where: { userId, notebookId: nbScope, name: { in: trimmedNames, mode: 'insensitive' } },
|
||||||
|
select: { id: true, name: true },
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noteLabels.length === 0) return []
|
return []
|
||||||
const uniqueNames = [...new Set(noteLabels.map(n => n.trim().toLowerCase()).filter(Boolean))]
|
|
||||||
return prisma.label.findMany({
|
|
||||||
where: { userId, notebookId: nbScope, name: { in: uniqueNames } },
|
|
||||||
select: { id: true, name: true },
|
|
||||||
})
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Fatal error in syncLabels:', error)
|
console.error('Fatal error in syncLabels:', error)
|
||||||
return []
|
return []
|
||||||
|
|||||||
Reference in New Issue
Block a user