← back to Norma
app/api/email-analyzer/references/route.ts
186 lines
/**
* GET /api/email-analyzer/references?session_id=xxx — list references for a session
* POST /api/email-analyzer/references — add a reference
* DELETE /api/email-analyzer/references?id=xxx — remove a reference
*/
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
import { requireRole } from '@/lib/require-role';
export async function GET(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
try {
const { searchParams } = new URL(request.url);
const sessionId = searchParams.get('session_id');
if (!sessionId) {
return NextResponse.json({ error: 'session_id is required' }, { status: 400 });
}
const result = await query(
`SELECT * FROM email_analyzer_references
WHERE session_id = $1
ORDER BY sort_order ASC, created_at ASC`,
[sessionId],
);
return NextResponse.json({ references: result.rows });
} catch (err) {
console.error('[email-analyzer/references] GET error:', (err as Error).message);
return NextResponse.json({ error: 'Failed to fetch references' }, { status: 500 });
}
}
export async function POST(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
try {
const body = await request.json();
const {
session_id,
ref_type,
title,
source_url,
source_domain,
content,
key_points,
include_in_rewrite,
sort_order,
} = body;
if (!session_id || typeof session_id !== 'string') {
return NextResponse.json({ error: 'session_id is required' }, { status: 400 });
}
if (!ref_type || !['article', 'link', 'notes'].includes(ref_type)) {
return NextResponse.json(
{ error: 'ref_type must be one of: article, link, notes' },
{ status: 400 },
);
}
if (!content || typeof content !== 'string') {
return NextResponse.json({ error: 'content is required' }, { status: 400 });
}
// Get next sort_order if not provided
let finalSortOrder = sort_order;
if (finalSortOrder == null) {
const maxResult = await query(
`SELECT COALESCE(MAX(sort_order), -1) + 1 AS next_order
FROM email_analyzer_references
WHERE session_id = $1`,
[session_id],
);
finalSortOrder = maxResult.rows[0]?.next_order ?? 0;
}
const result = await query(
`INSERT INTO email_analyzer_references
(session_id, ref_type, title, source_url, source_domain, content, key_points, include_in_rewrite, sort_order)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
RETURNING *`,
[
session_id,
ref_type,
title || null,
source_url || null,
source_domain || null,
content,
JSON.stringify(key_points || []),
include_in_rewrite !== false,
finalSortOrder,
],
);
return NextResponse.json({ reference: result.rows[0] }, { status: 201 });
} catch (err) {
console.error('[email-analyzer/references] POST error:', (err as Error).message);
return NextResponse.json({ error: 'Failed to save reference' }, { status: 500 });
}
}
export async function DELETE(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
try {
const { searchParams } = new URL(request.url);
const id = searchParams.get('id');
if (!id) {
return NextResponse.json({ error: 'id is required' }, { status: 400 });
}
const result = await query(
`DELETE FROM email_analyzer_references WHERE id = $1 RETURNING id`,
[id],
);
if (result.rowCount === 0) {
return NextResponse.json({ error: 'Reference not found' }, { status: 404 });
}
return NextResponse.json({ deleted: true, id });
} catch (err) {
console.error('[email-analyzer/references] DELETE error:', (err as Error).message);
return NextResponse.json({ error: 'Failed to delete reference' }, { status: 500 });
}
}
export async function PATCH(request: NextRequest) {
const auth = requireRole(request, 'admin', 'staff');
if (auth instanceof NextResponse) return auth;
try {
const body = await request.json();
const { id, include_in_rewrite, sort_order } = body;
if (!id) {
return NextResponse.json({ error: 'id is required' }, { status: 400 });
}
const updates: string[] = [];
const values: unknown[] = [];
let paramIdx = 1;
if (include_in_rewrite !== undefined) {
updates.push(`include_in_rewrite = $${paramIdx}`);
values.push(include_in_rewrite);
paramIdx++;
}
if (sort_order !== undefined) {
updates.push(`sort_order = $${paramIdx}`);
values.push(sort_order);
paramIdx++;
}
if (updates.length === 0) {
return NextResponse.json({ error: 'No fields to update' }, { status: 400 });
}
values.push(id);
const result = await query(
`UPDATE email_analyzer_references
SET ${updates.join(', ')}
WHERE id = $${paramIdx}
RETURNING *`,
values,
);
if (result.rowCount === 0) {
return NextResponse.json({ error: 'Reference not found' }, { status: 404 });
}
return NextResponse.json({ reference: result.rows[0] });
} catch (err) {
console.error('[email-analyzer/references] PATCH error:', (err as Error).message);
return NextResponse.json({ error: 'Failed to update reference' }, { status: 500 });
}
}