import type { Router } from 'express'; import { supabase, tableMissing } from '../supabase.js'; interface RevenueStreamRecord { amount: number; status: string; metadata: Record | null; } export function registerRiverRoutes(router: Router) { router.get('/river/tools', async (_req, res, next) => { try { const { data, error } = await supabase .from('river_tools') .select('*') .order('created_at', { ascending: false }); if (error && !tableMissing(error)) throw error; res.json({ tools: data ?? [] }); } catch (error) { next(error); } }); router.get('/river/analytics/:toolId', async (req, res, next) => { const { toolId } = req.params; try { const { data, error } = await supabase .from('river_tool_metrics') .select('*') .eq('tool_id', toolId) .order('recorded_at', { ascending: false }) .limit(1) .single(); if (!error && data) { return res.json({ toolId, ...data }); } if (error && !tableMissing(error)) { throw error; } // Fallback to aggregate revenue streams const { data: revenueData, error: revenueError } = await supabase .from('revenue_streams') .select('amount,status,metadata'); if (revenueError && !tableMissing(revenueError)) throw revenueError; const streams = (revenueData ?? []) as RevenueStreamRecord[]; const relevant = streams.filter(stream => { const meta = stream.metadata || {}; return meta.tool_id === toolId || meta.toolId === toolId; }); const revenue = relevant.reduce((sum, stream) => sum + (stream.status === 'confirmed' ? stream.amount : 0), 0); const conversions = relevant.length; res.json({ toolId, revenue, conversions, subscribers: conversions, // placeholder until distinct subscribers tracked mrr: revenue, timestamp: new Date().toISOString(), }); } catch (error) { next(error); } }); }