refactor(ux): consolidate BMAD skills, update design system, and clean up Prisma generated client
This commit is contained in:
57
keep-notes/lib/image-cleanup.ts
Normal file
57
keep-notes/lib/image-cleanup.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Image Cleanup Utility
|
||||
* Safely deletes orphaned image files from disk.
|
||||
* Checks database references before deleting to avoid breaking shared images.
|
||||
*/
|
||||
|
||||
import { promises as fs } from 'fs'
|
||||
import path from 'path'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
const UPLOADS_DIR = 'public/uploads/notes'
|
||||
|
||||
/**
|
||||
* Delete an image file from disk only if no other note references it.
|
||||
* @param imageUrl - The relative URL path (e.g. "/uploads/notes/abc.jpg")
|
||||
* @param excludeNoteId - Note ID to exclude from reference check (the note being deleted)
|
||||
*/
|
||||
export async function deleteImageFileSafely(imageUrl: string, excludeNoteId?: string): Promise<void> {
|
||||
if (!imageUrl || !imageUrl.startsWith('/uploads/notes/')) return
|
||||
|
||||
try {
|
||||
const notes = await prisma.note.findMany({
|
||||
where: { images: { contains: imageUrl } },
|
||||
select: { id: true },
|
||||
})
|
||||
const otherRefs = notes.filter(n => n.id !== excludeNoteId)
|
||||
if (otherRefs.length > 0) return // File still referenced elsewhere
|
||||
|
||||
const filePath = path.join(process.cwd(), imageUrl)
|
||||
await fs.unlink(filePath)
|
||||
} catch {
|
||||
// File already gone or unreadable -- silently skip
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all image files associated with a note.
|
||||
* Checks that each image is not referenced by any other note before deleting.
|
||||
*/
|
||||
export async function cleanupNoteImages(noteId: string, imageUrls: string[]): Promise<void> {
|
||||
for (const url of imageUrls) {
|
||||
await deleteImageFileSafely(url, noteId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the images JSON field from a note record.
|
||||
*/
|
||||
export function parseImageUrls(imagesJson: string | null): string[] {
|
||||
if (!imagesJson) return []
|
||||
try {
|
||||
const parsed = JSON.parse(imagesJson)
|
||||
return Array.isArray(parsed) ? parsed.filter((u: unknown) => typeof u === 'string') : []
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user