nyk
feat(refactor): ready for manual QA after main sync (#274)
b6ecafa unverified
Raw
History Blame Contribute Delete
2.38 kB
import { NextRequest, NextResponse } from 'next/server'
import { config } from '@/lib/config'
import { requireRole } from '@/lib/auth'
import { readLimiter } from '@/lib/rate-limit'
import { buildLinkGraph, extractWikiLinks } from '@/lib/memory-utils'
import { readFile } from 'fs/promises'
import { join, basename, extname } from 'path'
import { logger } from '@/lib/logger'
const MEMORY_PATH = config.memoryDir
export async function GET(request: NextRequest) {
const auth = requireRole(request, 'viewer')
if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status })
const limited = readLimiter(request)
if (limited) return limited
if (!MEMORY_PATH) {
return NextResponse.json({ error: 'Memory directory not configured' }, { status: 500 })
}
const { searchParams } = new URL(request.url)
const filePath = searchParams.get('file')
try {
if (filePath) {
// Return links for a specific file
const fullPath = join(MEMORY_PATH, filePath)
// Basic path traversal check
if (!fullPath.startsWith(MEMORY_PATH)) {
return NextResponse.json({ error: 'Invalid path' }, { status: 400 })
}
const content = await readFile(fullPath, 'utf-8')
const links = extractWikiLinks(content)
// Also find backlinks from the full graph
const graph = await buildLinkGraph(MEMORY_PATH)
const node = graph.nodes[filePath]
const incoming = node?.incoming ?? []
const outgoing = node?.outgoing ?? []
return NextResponse.json({
file: filePath,
wikiLinks: links,
outgoing,
incoming,
})
}
// Return full link graph
const graph = await buildLinkGraph(MEMORY_PATH)
// Serialize for the frontend (strip wikiLinks detail for the full graph)
const nodes = Object.values(graph.nodes).map((n) => ({
path: n.path,
name: n.name,
outgoing: n.outgoing,
incoming: n.incoming,
linkCount: n.outgoing.length + n.incoming.length,
hasSchema: n.schema !== null,
}))
return NextResponse.json({
nodes,
totalFiles: graph.totalFiles,
totalLinks: graph.totalLinks,
orphans: graph.orphans,
})
} catch (err) {
logger.error({ err }, 'Memory links API error')
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}
}