import { loadAirportsGeoJson } from '@/lib/airports'; import { getGameDb } from '@/lib/db/client'; import * as schema from '@/lib/db/schema'; // Read-only game-state snapshot for client polling (GET /api/state). export interface PlaneState { id: string; model: string; status: 'available' | 'flying'; fuel: number; maxFuel: number; locationIcao: string; locationName: string; contractId: string | null; lat: number; lon: number; } export interface ContractState { id: string; originIcao: string; originName: string; destIcao: string; destName: string; reward: number; cargoType: string; cargoCount: number; deadlineSimTime: number; status: 'open' | 'accepted' | 'completed'; planeId: string | null; createdSimTime: number; } export interface StateSnapshot { account: { cash: number; reputation: number }; simState: { clockMs: number; timeScale: number; paused: boolean }; planes: PlaneState[]; contracts: ContractState[]; } export async function getStateSnapshot(): Promise { const { db } = await getGameDb(); // NOTE: use plain select(), not the relational db.query.* API — in drizzle-orm // 0.45.x the sql-js driver drops the result mapper for relational queries and // returns raw rows keyed by SQL column names (snake_case, no type decoding). const [accountRows, simRows, planeRows, contractRows] = await Promise.all([ db.select().from(schema.account), db.select().from(schema.simState), db.select().from(schema.planes), db.select().from(schema.contracts), ]); const accountRow = accountRows[0]; const simRow = simRows[0]; if (!accountRow || !simRow) throw new Error('game state missing account/sim_state row'); const fc = await loadAirportsGeoJson(); const nameByIcao = new Map(fc.features.map((f) => [f.properties.icao, f.properties.name])); const nameOf = (icao: string) => nameByIcao.get(icao) ?? icao; return { account: { cash: accountRow.cash, reputation: accountRow.reputation }, simState: { clockMs: simRow.clockMs, timeScale: simRow.timeScale, paused: simRow.paused }, planes: planeRows.map((p) => ({ id: p.id, model: p.model, status: p.status, fuel: p.fuel, maxFuel: p.maxFuel, locationIcao: p.locationIcao, locationName: nameOf(p.locationIcao), contractId: p.contractId, lat: p.lat, lon: p.lon, })), contracts: contractRows.map((c) => ({ id: c.id, originIcao: c.originIcao, originName: nameOf(c.originIcao), destIcao: c.destIcao, destName: nameOf(c.destIcao), reward: c.reward, cargoType: c.cargoType, cargoCount: c.cargoCount, deadlineSimTime: c.deadlineSimTime, status: c.status, planeId: c.planeId, createdSimTime: c.createdSimTime, })), }; }