import "dotenv/config"; import express from "express"; import cors from "cors"; export function createServer() { const app = express(); // Middleware app.use(cors()); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Example API routes app.get("/api/ping", (_req, res) => { const ping = process.env.PING_MESSAGE ?? "ping"; res.json({ message: ping }); }); // Admin-backed API (service role) try { const { adminSupabase } = await import("./supabase"); app.get("/api/health", async (_req, res) => { try { const { error } = await adminSupabase.from("user_profiles").select("count", { count: "exact", head: true }); if (error) return res.status(500).json({ ok: false, error: error.message }); return res.json({ ok: true }); } catch (e: any) { return res.status(500).json({ ok: false, error: e?.message || String(e) }); } }); app.get("/api/posts", async (req, res) => { const limit = Math.max(1, Math.min(50, Number(req.query.limit) || 10)); try { const { data, error } = await adminSupabase .from("community_posts") .select(`*, user_profiles ( username, full_name, avatar_url )`) .eq("is_published", true) .order("created_at", { ascending: false }) .limit(limit); if (error) return res.status(500).json({ error: error.message }); res.json(data || []); } catch (e: any) { res.status(500).json({ error: e?.message || String(e) }); } }); app.get("/api/user/:id/posts", async (req, res) => { const userId = req.params.id; try { const { data, error } = await adminSupabase .from("community_posts") .select("*") .eq("author_id", userId) .order("created_at", { ascending: false }); if (error) return res.status(500).json({ error: error.message }); res.json(data || []); } catch (e: any) { res.status(500).json({ error: e?.message || String(e) }); } }); app.post("/api/posts", async (req, res) => { const payload = req.body || {}; try { const { data, error } = await adminSupabase .from("community_posts") .insert({ author_id: payload.author_id, title: payload.title, content: payload.content, category: payload.category, tags: payload.tags, is_published: payload.is_published ?? true, }) .select() .single(); if (error) return res.status(500).json({ error: error.message }); res.json(data); } catch (e: any) { res.status(500).json({ error: e?.message || String(e) }); } }); app.post("/api/profile/ensure", async (req, res) => { const { id, profile } = req.body || {}; if (!id) return res.status(400).json({ error: "missing id" }); try { const { data, error } = await adminSupabase .from("user_profiles") .upsert({ id, ...profile }, { onConflict: "id" }) .select() .single(); if (error) return res.status(500).json({ error: error.message }); res.json(data); } catch (e: any) { res.status(500).json({ error: e?.message || String(e) }); } }); app.post("/api/interests", async (req, res) => { const { user_id, interests } = req.body || {}; if (!user_id || !Array.isArray(interests)) return res.status(400).json({ error: "invalid payload" }); try { await adminSupabase.from("user_interests").delete().eq("user_id", user_id); if (interests.length) { const rows = interests.map((interest: string) => ({ user_id, interest })); const { error } = await adminSupabase.from("user_interests").insert(rows); if (error) return res.status(500).json({ error: error.message }); } res.json({ ok: true }); } catch (e: any) { res.status(500).json({ error: e?.message || String(e) }); } }); app.get("/api/applications", async (req, res) => { const owner = String(req.query.owner || ""); if (!owner) return res.status(400).json({ error: "owner required" }); try { const { data, error } = await adminSupabase .from("project_applications") .select(`*, projects!inner(id, title, user_id)`) .eq("projects.user_id", owner) .order("created_at", { ascending: false }) .limit(50); if (error) return res.status(500).json({ error: error.message }); res.json(data || []); } catch (e: any) { res.status(500).json({ error: e?.message || String(e) }); } }); } catch (e) { console.warn("Admin API not initialized:", e); } return app; }