import { db, invites, eq, isNull } from "@epicure/db"; import { randomUUID, randomBytes } from "crypto"; export const INVITE_COOKIE = "epicure_invite"; export function generateInviteToken(): string { return randomBytes(24).toString("base64url"); } export async function findValidInvite(token: string, email?: string | null) { const [invite] = await db.select().from(invites).where(eq(invites.token, token)); if (!invite) return null; if (invite.usedAt) return null; if (invite.expiresAt && invite.expiresAt < new Date()) return null; if (invite.email && email && invite.email.toLowerCase() !== email.toLowerCase()) return null; return invite; } export async function consumeInvite(inviteId: string, userId: string): Promise { await db .update(invites) .set({ usedAt: new Date(), usedById: userId }) .where(eq(invites.id, inviteId)); } export async function createInvite(opts: { createdById: string; email?: string | null; role?: "user" | "moderator" | "admin"; tier?: "free" | "pro" | "team"; expiresInDays?: number | null; }) { const [invite] = await db .insert(invites) .values({ id: randomUUID(), token: generateInviteToken(), email: opts.email || null, role: opts.role ?? "user", tier: opts.tier ?? "free", createdById: opts.createdById, expiresAt: opts.expiresInDays ? new Date(Date.now() + opts.expiresInDays * 86400_000) : null, }) .returning(); return invite; } export async function listInvites() { return db.query.invites.findMany({ where: isNull(invites.usedAt), orderBy: (i, { desc }) => [desc(i.createdAt)], }); }