type TypedClient = { from: (table: string) => any; }; interface WorkspaceMembershipRow { workspace_id: string; is_default: boolean; workspaces: | { id: string; name: string; type: "personal" | "team"; icon_url: string | null; } | Array<{ id: string; name: string; type: "personal" | "team"; icon_url: string | null; }> | null; } export interface WorkspaceSummary { id: string; name: string; type: "personal" | "team"; iconUrl: string | null; memberCount: number; isDefault: boolean; } export async function ensureDefaultWorkspace(client: TypedClient, userId: string, fallbackName: string): Promise { const { data: memberships, error } = await client .from("workspace_members") .select("workspace_id") .eq("user_id", userId) .limit(1); if (error) { throw new Error(`获取工作空间成员信息失败:${error.message}`); } if (memberships && memberships.length > 0) { return; } const workspaceName = fallbackName.trim() ? `${fallbackName.trim()} 的空间` : "我的空间"; const { data: workspace, error: workspaceError } = await client .from("workspaces") .insert({ name: workspaceName, type: "personal", created_by: userId, }) .select("id") .single(); if (workspaceError || !workspace) { throw new Error(`创建默认工作空间失败:${workspaceError?.message ?? "未知错误"}`); } const { error: memberError } = await client.from("workspace_members").insert({ workspace_id: workspace.id, user_id: userId, role: "owner", is_default: true, }); if (memberError) { throw new Error(`创建工作空间成员失败:${memberError.message}`); } } export async function fetchWorkspaceSummaries( client: TypedClient, userId: string, ): Promise<{ workspaces: WorkspaceSummary[]; activeWorkspaceId: string }> { const { data: memberRows, error } = await client .from("workspace_members") .select("workspace_id,is_default,workspaces(id,name,type,icon_url)") .eq("user_id", userId) .order("created_at", { ascending: true }); if (error) { throw new Error(`拉取工作空间列表失败:${error.message}`); } const rows: WorkspaceMembershipRow[] = (memberRows ?? []) as any; const workspaceIds = rows.map((row) => row.workspace_id); const memberCountMap: Record = {}; if (workspaceIds.length > 0) { const { data: memberCounts, error: countError } = await client .from("workspace_members") .select("workspace_id") .in("workspace_id", workspaceIds); if (countError) { throw new Error(`统计成员数失败:${countError.message}`); } const countRows = (memberCounts ?? []) as Array<{ workspace_id: string }>; countRows.forEach((item) => { const workspaceId = item.workspace_id; memberCountMap[workspaceId] = (memberCountMap[workspaceId] ?? 0) + 1; }); } const summaries: WorkspaceSummary[] = rows .map((row) => { const workspace = Array.isArray(row.workspaces) ? row.workspaces[0] : row.workspaces; if (!workspace) { return null; } return { id: workspace.id, name: workspace.name, type: workspace.type, iconUrl: workspace.icon_url, memberCount: memberCountMap[workspace.id] ?? 1, isDefault: row.is_default, } satisfies WorkspaceSummary; }) .filter(Boolean) as WorkspaceSummary[]; const defaultWorkspace = summaries.find((workspace) => workspace.isDefault); const activeWorkspaceId = defaultWorkspace?.id ?? summaries[0]?.id ?? ""; return { workspaces: summaries, activeWorkspaceId, }; } export async function resolveActiveWorkspaceId(client: TypedClient, userId: string): Promise { const { data, error } = await client .from("workspace_members") .select("workspace_id,is_default") .eq("user_id", userId) .order("is_default", { ascending: false }) .order("created_at", { ascending: true }) .limit(1); if (error) { throw new Error(`获取当前工作空间失败:${error.message}`); } return data?.[0]?.workspace_id ?? ""; }