/**
* Link, Backlink, Graph, Merge & Split Routes
*
* Phase 4 HTTP endpoints for interlinking and advanced operations.
*/
import { json, readJson } from '../response.js'
import { UnauthorizedError, ForbiddenError } from '../errors.js'
async function requireAuth (req, server, action, notebook) {
const { authorized, auth, reason } = await server.authManager.authorizeRequest(req, action, notebook)
if (!auth) throw new UnauthorizedError('Authentication required')
if (!authorized) throw new ForbiddenError(reason, action)
return auth
}
export function registerLinkRoutes (router, server) {
const nm = server.noteManager
const lm = server.linkManager
// ==================== LINKS ====================
// Get outgoing links from a note (open read)
router.get('/api/notebooks/:notebook/notes/:id/links', async (req, res) => {
const links = await lm.getLinks(req.params.notebook, req.params.id)
json(res, { links })
})
// Get backlinks (open read)
router.get('/api/notebooks/:notebook/notes/:id/backlinks', async (req, res) => {
const backlinks = await lm.getBacklinks(req.params.notebook, req.params.id)
json(res, { backlinks })
})
// Get link graph (open read)
router.get('/api/graph', async (req, res) => {
const idx = req.url.indexOf('?')
let notebook = null
if (idx >= 0) {
const qs = req.url.substring(idx + 1)
for (const pair of qs.split('&')) {
const [k, v] = pair.split('=')
if (k === 'notebook') notebook = decodeURIComponent(v)
}
}
const graph = await lm.getGraph(notebook)
json(res, graph)
})
// ==================== MERGE ====================
// Merge two notes in the same notebook
router.post('/api/notebooks/:notebook/merge', async (req, res) => {
await requireAuth(req, server, 'write', req.params.notebook)
const body = await readJson(req)
if (!body.noteId1 || !body.noteId2) {
json(res, { error: 'noteId1 and noteId2 are required' }, 400)
return
}
const merged = await nm.mergeNotes(req.params.notebook, body.noteId1, body.noteId2, {
title: body.title
})
json(res, merged)
})
// ==================== SPLIT ====================
// Split a note at heading boundaries
router.post('/api/notebooks/:notebook/notes/:id/split', async (req, res) => {
await requireAuth(req, server, 'write', req.params.notebook)
const body = await readJson(req)
const created = await nm.splitNote(req.params.notebook, req.params.id, {
delimiter: body.delimiter
})
json(res, { split: created.length > 0, parts: created })
})
}
export default registerLinkRoutes