import type { Kysely } from 'kysely' import type { DB } from '../types/db.types.js' /** * Ensures a login-capable client user exists for a client org, idempotently. * * Finds or creates a `user` row (role `client`) keyed by lower-cased email, * then ensures a `client_member` row links that user to the client as `organiser`. * * Reuse-by-email is intentional: one person who organises for several clients * gets one login with multiple `client_member` rows. * Returns the resolved `userId`. */ export async function provisionClientLogin( kysely: Kysely, { clientId, email, name }: { clientId: string; email: string; name: string | null }, ): Promise { const normalisedEmail = email.toLowerCase() const existing = await kysely .selectFrom('user') .where('email', '=', normalisedEmail) .select('id') .executeTakeFirst() const id = existing?.id ?? crypto.randomUUID() if (!existing) { const now = new Date().toISOString() await kysely .insertInto('user') .values({ id, email: normalisedEmail, name: name ?? normalisedEmail, emailVerified: 0, createdAt: now, updatedAt: now, role: 'client', locale: 'de', } as any) .execute() } await kysely .insertInto('clientMember') .values({ clientId, userId: id, role: 'organiser' }) .onConflict((oc) => oc.columns(['clientId', 'userId']).doNothing()) .execute() return id }