Files
factorio-signal-exporter/web/app/api/ingest/[combinator]/route.ts
Caesar2011 20ed6ee9fb Initial web
2026-05-17 19:55:53 +02:00

71 lines
2.3 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import pool from '@/lib/db';
import { withAuth } from '@/lib/apiHelpers';
interface CircuitNetwork {
green: Record<string, number>;
red: Record<string, number>;
}
interface IngestBody {
game_tick: number;
circuit_network: CircuitNetwork;
logistic_network: Record<string, number>;
}
export const POST = withAuth(async (req: NextRequest, { params }) => {
const { combinator } = await params;
const mtimeHeader = req.headers.get('x-file-mtime');
const realTime = mtimeHeader ? new Date(parseInt(mtimeHeader, 10)) : new Date();
let body: IngestBody;
try {
body = await req.json();
} catch {
return NextResponse.json({ error: 'Invalid JSON' }, { status: 400 });
}
const { game_tick, circuit_network, logistic_network } = body;
if (typeof game_tick !== 'number') {
return NextResponse.json({ error: 'Missing game_tick' }, { status: 400 });
}
const green = circuit_network?.green ?? {};
const red = circuit_network?.red ?? {};
const logistic = logistic_network ?? {};
const allKeys = new Set([...Object.keys(green), ...Object.keys(red), ...Object.keys(logistic)]);
if (allKeys.size === 0) return NextResponse.json({ ok: true, rows: 0 });
const client = await pool.connect();
try {
await client.query('BEGIN');
const values: unknown[] = [];
const placeholders: string[] = [];
let idx = 1;
for (const key of allKeys) {
placeholders.push(`($${idx++},$${idx++},$${idx++},$${idx++},$${idx++},$${idx++},$${idx++})`);
values.push(realTime, game_tick, combinator, key, green[key] ?? 0, red[key] ?? 0, logistic[key] ?? null);
}
await client.query(
`INSERT INTO signals (real_time, game_tick, combinator, item_key, green, red, logistic)
VALUES ${placeholders.join(', ')}`,
values,
);
await client.query(
`INSERT INTO tick_timing (real_time, game_tick, combinator) VALUES ($1,$2,$3)`,
[realTime, game_tick, combinator],
);
await client.query('COMMIT');
return NextResponse.json({ ok: true, rows: allKeys.size });
} catch (err) {
await client.query('ROLLBACK');
throw err; // re-throw — withAuth handler catches and returns 500
} finally {
client.release();
}
});