import { and, eq, inArray, isNull } from "drizzle-orm"; import type { dbClient } from "@kan/db/client"; import { boards, workspaceMembers, workspaces } from "@kan/db/schema"; import { generateUID } from "@kan/shared/utils"; export const create = async ( db: dbClient, workspaceInput: { publicId?: string; name: string; slug: string; createdBy: string; createdByEmail: string; }, ) => { const [workspace] = await db .insert(workspaces) .values({ publicId: workspaceInput.publicId ?? generateUID(), name: workspaceInput.name, slug: workspaceInput.slug, createdBy: workspaceInput.createdBy, }) .returning({ id: workspaces.id, publicId: workspaces.publicId, name: workspaces.name, slug: workspaces.slug, description: workspaces.description, plan: workspaces.plan, }); if (workspace) { await db.insert(workspaceMembers).values({ publicId: generateUID(), userId: workspaceInput.createdBy, email: workspaceInput.createdByEmail, workspaceId: workspace.id, createdBy: workspaceInput.createdBy, role: "admin", status: "active", }); } const newWorkspace = { ...workspace }; delete newWorkspace.id; return newWorkspace; }; export const update = async ( db: dbClient, workspacePublicId: string, workspaceInput: { name?: string; slug?: string; plan?: "free" | "pro" | "enterprise"; description?: string; }, ) => { const [result] = await db .update(workspaces) .set({ name: workspaceInput.name, slug: workspaceInput.slug, plan: workspaceInput.plan, description: workspaceInput.description, }) .where(eq(workspaces.publicId, workspacePublicId)) .returning({ id: workspaces.id, publicId: workspaces.publicId, name: workspaces.name, slug: workspaces.slug, description: workspaces.description, plan: workspaces.plan, }); return result; }; export const getByPublicId = (db: dbClient, workspacePublicId: string) => { return db.query.workspaces.findFirst({ columns: { id: true, publicId: true, name: true, plan: true, }, where: eq(workspaces.publicId, workspacePublicId), }); }; export const getByPublicIdWithMembers = ( db: dbClient, workspacePublicId: string, ) => { return db.query.workspaces.findFirst({ columns: { id: true, publicId: true, }, with: { members: { columns: { publicId: true, email: true, role: true, status: true, }, where: isNull(workspaceMembers.deletedAt), with: { user: { columns: { id: true, name: true, email: true, image: true, }, }, }, }, }, where: and( eq(workspaces.publicId, workspacePublicId), isNull(workspaces.deletedAt), ), }); }; export const getBySlugWithBoards = (db: dbClient, workspaceSlug: string) => { return db.query.workspaces.findFirst({ columns: { id: true, publicId: true, name: true, description: true, slug: true, }, with: { boards: { columns: { publicId: true, slug: true, name: true, }, where: and(isNull(boards.deletedAt), eq(boards.visibility, "public")), }, }, where: and( eq(workspaces.slug, workspaceSlug), isNull(workspaces.deletedAt), ), }); }; export const getAllByUserId = async (db: dbClient, userId: string) => { const result = await db.query.workspaceMembers.findMany({ columns: { role: true, }, with: { workspace: { columns: { publicId: true, name: true, description: true, slug: true, plan: true, deletedAt: true, }, // https://github.com/drizzle-team/drizzle-orm/issues/2903 // where: isNull(workspaces.deletedAt), }, }, where: and( eq(workspaceMembers.userId, userId), eq(workspaceMembers.status, "active"), isNull(workspaceMembers.deletedAt), ), }); return result.filter((member) => !member.workspace.deletedAt); }; export const getMemberByPublicId = (db: dbClient, memberPublicId: string) => { return db.query.workspaceMembers.findFirst({ columns: { id: true, }, where: eq(workspaceMembers.publicId, memberPublicId), }); }; export const getAllMembersByPublicIds = ( db: dbClient, memberPublicIds: string[], ) => { return db.query.workspaceMembers.findMany({ columns: { id: true, }, where: inArray(workspaceMembers.publicId, memberPublicIds), }); }; export const hardDelete = (db: dbClient, workspacePublicId: string) => { return db .delete(workspaces) .where(eq(workspaces.publicId, workspacePublicId)); }; export const isWorkspaceSlugAvailable = async ( db: dbClient, workspaceSlug: string, ) => { const result = await db.query.workspaces.findFirst({ columns: { id: true, }, where: and( eq(workspaces.slug, workspaceSlug), isNull(workspaces.deletedAt), ), }); return result === undefined; }; export const isUserInWorkspace = async ( db: dbClient, userId: string, workspaceId: number, role?: "admin" | "member", ) => { const result = await db.query.workspaceMembers.findFirst({ columns: { id: true, }, where: and( eq(workspaceMembers.userId, userId), eq(workspaceMembers.workspaceId, workspaceId), eq(workspaceMembers.status, "active"), isNull(workspaceMembers.deletedAt), role ? eq(workspaceMembers.role, role) : undefined, ), }); return result?.id !== undefined; };