Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/server/next.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { NextConfig } from 'next'

const nextConfig: NextConfig = {
transpilePackages: ['@openthreads/core', '@openthreads/storage-mongodb'],
transpilePackages: ['@openthreads/core', '@openthreads/storage-mongodb', '@xyflow/react'],
// Allow the mongodb package to run in the Node.js runtime (not Edge)
serverExternalPackages: ['mongodb'],
// Ant Design 5 requires the emotion/CSS-in-JS layer; keep it in-bundle.
Expand Down
33 changes: 33 additions & 0 deletions packages/server/src/app/api/routes/test/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* POST /api/routes/test — Test which routes match given criteria
*/

import { NextRequest, NextResponse } from 'next/server';
import { findMatchingRoutes } from '@/lib/db';
import { verifyManagementAuth } from '@/lib/auth';
import type { RouteCriteria } from '@openthreads/core';

export const runtime = 'nodejs';

export async function POST(request: NextRequest): Promise<NextResponse> {
const auth = verifyManagementAuth(request);
if (!auth.valid) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

let body: unknown;
try {
body = await request.json();
} catch {
return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 });
}

try {
const criteria = body as Partial<RouteCriteria>;
const routes = await findMatchingRoutes(criteria);
return NextResponse.json({ matchingRouteIds: routes.map((r) => r.id), routes });
} catch (err) {
console.error('[routes/test] error:', err);
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
}
}
48 changes: 48 additions & 0 deletions packages/server/src/app/api/settings/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* GET /api/settings — Get global settings
* PUT /api/settings — Update global settings
*/

import { NextRequest, NextResponse } from 'next/server';
import { getSettings, updateSettings } from '@/lib/db';
import { verifyManagementAuth } from '@/lib/auth';
import type { AppSettings } from '@/lib/db';

export const runtime = 'nodejs';

export async function GET(request: NextRequest): Promise<NextResponse> {
const auth = verifyManagementAuth(request);
if (!auth.valid) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

try {
const settings = await getSettings();
return NextResponse.json({ settings });
} catch (err) {
console.error('[settings] get error:', err);
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
}
}

export async function PUT(request: NextRequest): Promise<NextResponse> {
const auth = verifyManagementAuth(request);
if (!auth.valid) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

let body: unknown;
try {
body = await request.json();
} catch {
return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 });
}

try {
const settings = await updateSettings(body as Partial<AppSettings>);
return NextResponse.json({ settings });
} catch (err) {
console.error('[settings] update error:', err);
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
}
}
18 changes: 7 additions & 11 deletions packages/server/src/app/api/threads/route.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/**
* GET /api/threads — List threads, filterable by channelId and targetId
* GET /api/threads — List threads, optionally filtered by channelId, targetId, and search
*/

import { NextRequest, NextResponse } from 'next/server';
import { listThreadsByChannel } from '@/lib/db';
import { listThreads } from '@/lib/db';
import { verifyManagementAuth } from '@/lib/auth';

export const runtime = 'nodejs';
Expand All @@ -14,18 +14,14 @@ export async function GET(request: NextRequest): Promise<NextResponse> {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

const channelId = request.nextUrl.searchParams.get('channelId');
const channelId = request.nextUrl.searchParams.get('channelId') ?? undefined;
const targetId = request.nextUrl.searchParams.get('targetId') ?? undefined;

if (!channelId) {
return NextResponse.json(
{ error: 'Missing required query param: channelId' },
{ status: 400 },
);
}
const search = request.nextUrl.searchParams.get('search') ?? undefined;
const limitParam = request.nextUrl.searchParams.get('limit');
const limit = limitParam ? Math.min(parseInt(limitParam, 10), 200) : 100;

try {
const threads = await listThreadsByChannel(channelId, targetId);
const threads = await listThreads({ channelId, targetId, search, limit });
return NextResponse.json({ threads });
} catch (err) {
console.error('[threads] list error:', err);
Expand Down
Loading
Loading