chore: init monorepo snapshot
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
import type { Database } from "@/types/supabase";
|
||||
|
||||
type TypedClient = SupabaseClient<Database>;
|
||||
|
||||
interface WorkspaceMembershipRow {
|
||||
workspace_id: string;
|
||||
is_default: boolean;
|
||||
workspaces: {
|
||||
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<void> {
|
||||
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 ?? [];
|
||||
const workspaceIds = rows.map((row) => row.workspace_id);
|
||||
|
||||
const memberCountMap: Record<string, number> = {};
|
||||
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}`);
|
||||
}
|
||||
|
||||
(memberCounts ?? []).forEach((item) => {
|
||||
const workspaceId = item.workspace_id as string;
|
||||
memberCountMap[workspaceId] = (memberCountMap[workspaceId] ?? 0) + 1;
|
||||
});
|
||||
}
|
||||
|
||||
const summaries: WorkspaceSummary[] = rows
|
||||
.map((row) => {
|
||||
if (!row.workspaces) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
id: row.workspaces.id,
|
||||
name: row.workspaces.name,
|
||||
type: row.workspaces.type,
|
||||
iconUrl: row.workspaces.icon_url,
|
||||
memberCount: memberCountMap[row.workspaces.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<string> {
|
||||
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 ?? "";
|
||||
}
|
||||
Reference in New Issue
Block a user