Spaces:
Running
Running
| import { supabaseAdmin } from "../config/supabase"; | |
| import { HttpError } from "../utils/httpError"; | |
| export async function listConversations(userId: string) { | |
| const { data, error } = await supabaseAdmin | |
| .from("conversations") | |
| .select(` | |
| id, | |
| match_id, | |
| created_at, | |
| updated_at, | |
| match:matches(id, status, compatibility_score, profile_a_id, profile_b_id) | |
| `) | |
| .order("updated_at", { ascending: false }); | |
| if (error) { | |
| throw error; | |
| } | |
| const { data: profile, error: profileError } = await supabaseAdmin | |
| .from("profiles") | |
| .select("id") | |
| .eq("user_id", userId) | |
| .maybeSingle(); | |
| if (profileError) { | |
| throw profileError; | |
| } | |
| return (data ?? []).filter((conversation) => { | |
| const match = conversation.match as unknown as { profile_a_id?: string; profile_b_id?: string }; | |
| return match.profile_a_id === profile?.id || match.profile_b_id === profile?.id; | |
| }); | |
| } | |
| export async function listMessages(userId: string, conversationId: string) { | |
| await assertConversationParticipant(userId, conversationId); | |
| const { data, error } = await supabaseAdmin | |
| .from("messages") | |
| .select("*") | |
| .eq("conversation_id", conversationId) | |
| .order("created_at", { ascending: true }); | |
| if (error) { | |
| throw error; | |
| } | |
| return data ?? []; | |
| } | |
| export async function sendMessage(userId: string, conversationId: string, body: string) { | |
| await assertConversationParticipant(userId, conversationId); | |
| const { data, error } = await supabaseAdmin | |
| .from("messages") | |
| .insert({ | |
| conversation_id: conversationId, | |
| sender_user_id: userId, | |
| body | |
| }) | |
| .select("*") | |
| .single(); | |
| if (error) { | |
| throw error; | |
| } | |
| await supabaseAdmin.from("conversations").update({ updated_at: new Date().toISOString() }).eq("id", conversationId); | |
| return data; | |
| } | |
| async function assertConversationParticipant(userId: string, conversationId: string) { | |
| const { data: profile, error: profileError } = await supabaseAdmin | |
| .from("profiles") | |
| .select("id") | |
| .eq("user_id", userId) | |
| .maybeSingle(); | |
| if (profileError) { | |
| throw profileError; | |
| } | |
| if (!profile) { | |
| throw new HttpError(404, "profile_not_found", "Profile not found"); | |
| } | |
| const { data, error } = await supabaseAdmin | |
| .from("conversations") | |
| .select("id, match:matches(profile_a_id, profile_b_id, status)") | |
| .eq("id", conversationId) | |
| .maybeSingle(); | |
| if (error) { | |
| throw error; | |
| } | |
| const match = data?.match as unknown as { profile_a_id?: string; profile_b_id?: string; status?: string } | undefined; | |
| const isParticipant = match?.profile_a_id === profile.id || match?.profile_b_id === profile.id; | |
| if (!data || !match || !isParticipant || !["accepted", "active"].includes(match.status ?? "")) { | |
| throw new HttpError(403, "conversation_forbidden", "Conversation is not available for this user"); | |
| } | |
| } | |