import { prisma } from '@/lib/prisma' const BACKLINK_REGEX = /\[\[([^\]]+)\]\]/g export function parseBacklinks(content: string): string[] { const matches = content.matchAll(BACKLINK_REGEX) const titles = new Set() for (const match of matches) { const title = match[1].trim() if (title) { titles.add(title) } } return Array.from(titles) } export async function syncBacklinks(noteId: string, content: string): Promise { const linkedTitles = parseBacklinks(content) await prisma.backlink.deleteMany({ where: { sourceNoteId: noteId }, }) if (linkedTitles.length === 0) return const targetNotes = await prisma.note.findMany({ where: { title: { in: linkedTitles }, }, select: { id: true, title: true }, }) const titleToId = new Map(targetNotes.map((n) => [n.title.toLowerCase(), n.id])) const backlinksToCreate: { sourceNoteId: string; targetNoteId: string }[] = [] for (const title of linkedTitles) { const targetNoteId = titleToId.get(title.toLowerCase()) if (targetNoteId && targetNoteId !== noteId) { backlinksToCreate.push({ sourceNoteId: noteId, targetNoteId, }) } } if (backlinksToCreate.length > 0) { await prisma.backlink.createMany({ data: backlinksToCreate, }) } } export interface BacklinkWithNote { id: string sourceNoteId: string targetNoteId: string createdAt: string sourceNote: { id: string title: string type: string } } export async function getBacklinksForNote(noteId: string): Promise { const backlinks = await prisma.backlink.findMany({ where: { targetNoteId: noteId }, include: { sourceNote: { select: { id: true, title: true, type: true, }, }, }, orderBy: { createdAt: 'desc' }, }) return backlinks.map((bl) => ({ id: bl.id, sourceNoteId: bl.sourceNoteId, targetNoteId: bl.targetNoteId, createdAt: bl.createdAt.toISOString(), sourceNote: { id: bl.sourceNote.id, title: bl.sourceNote.title, type: bl.sourceNote.type, }, })) } export async function getOutgoingLinksForNote(noteId: string): Promise { const backlinks = await prisma.backlink.findMany({ where: { sourceNoteId: noteId }, include: { targetNote: { select: { id: true, title: true, type: true, }, }, }, orderBy: { createdAt: 'desc' }, }) return backlinks.map((bl) => ({ id: bl.id, sourceNoteId: bl.sourceNoteId, targetNoteId: bl.targetNoteId, createdAt: bl.createdAt.toISOString(), sourceNote: { id: bl.targetNote.id, title: bl.targetNote.title, type: bl.targetNote.type, }, })) }