mirror of
https://github.com/bretzel-app/crumbs.git
synced 2026-10-12 20:06:57 +02:00
49 lines
1.6 KiB
TypeScript
49 lines
1.6 KiB
TypeScript
import type { Db } from './db/index.js';
|
|
import { noteLinks, notes } from './db/schema.js';
|
|
import { eq, inArray } from 'drizzle-orm';
|
|
import { canAccessNote } from './api-utils.js';
|
|
|
|
/**
|
|
* Sync link rows for a note: removes old associations, inserts the current set.
|
|
* Mirrors syncNoteTags — called right after a note's content is saved.
|
|
*/
|
|
export function syncNoteLinks(db: Db, noteId: string, targetIds: string[]): void {
|
|
db.delete(noteLinks).where(eq(noteLinks.sourceNoteId, noteId)).run();
|
|
|
|
for (const targetId of targetIds) {
|
|
db.insert(noteLinks).values({ sourceNoteId: noteId, targetNoteId: targetId }).run();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find notes that link to the given note, scoped to what the requesting user
|
|
* can access — this both respects normal sharing boundaries and, as a side
|
|
* effect, prevents an unrelated note from appearing in someone's backlinks
|
|
* just because it happens to reference a note ID it was never shared to see.
|
|
*/
|
|
export function fetchBacklinksForNote(
|
|
db: Db,
|
|
noteId: string,
|
|
userId: number
|
|
): { id: string; title: string }[] {
|
|
const linkRows = db
|
|
.select({ sourceNoteId: noteLinks.sourceNoteId })
|
|
.from(noteLinks)
|
|
.where(eq(noteLinks.targetNoteId, noteId))
|
|
.all();
|
|
|
|
if (linkRows.length === 0) return [];
|
|
|
|
const sourceIds = linkRows.map((r) => r.sourceNoteId);
|
|
const accessibleIds = sourceIds.filter((id) => canAccessNote(db, id, userId).canAccess);
|
|
if (accessibleIds.length === 0) return [];
|
|
|
|
const sourceNotes = db
|
|
.select({ id: notes.id, title: notes.title })
|
|
.from(notes)
|
|
.where(inArray(notes.id, accessibleIds))
|
|
.all();
|
|
|
|
return sourceNotes;
|
|
}
|