UNPKG

codalware-auth

Version:

Complete authentication system with enterprise security, attack protection, team workspaces, waitlist, billing, UI components, 2FA, and account recovery - production-ready in 5 minutes. Enhanced CLI with verification, rollback, and App Router scaffolding.

61 lines (58 loc) 3.83 kB
import type { Adapter, User, Session, MagicToken } from './types'; import type { DrizzleClient } from 'drizzle-orm'; import { users, sessions, magic_tokens } from './drizzle-schema'; import { eq } from 'drizzle-orm'; export function createDrizzleNativeAdapter(db: DrizzleClient): Adapter { if (!db) throw new Error('drizzle client required'); return { async createUser({ email, name, metadata }) { const [r] = await db.insert(users).values({ email, name: name ?? null, metadata: metadata ?? null }).returning(); return { id: r.id, email: r.email, name: r.name, metadata: r.metadata, createdAt: r.created_at, updatedAt: r.updated_at } as User; }, async getUserById(id) { const r = await db.select().from(users).where(eq(users.id, id)).limit(1).then(res => res[0]); if (!r) return null; return { id: r.id, email: r.email, name: r.name, metadata: r.metadata, createdAt: r.created_at, updatedAt: r.updated_at } as User; }, async getUserByEmail(email) { const r = await db.select().from(users).where(eq(users.email, email)).limit(1).then(res => res[0]); if (!r) return null; return { id: r.id, email: r.email, name: r.name, metadata: r.metadata, createdAt: r.created_at, updatedAt: r.updated_at } as User; }, async updateUser(id, patch) { const upd = {} as any; if (patch.email !== undefined) upd.email = patch.email; if (patch.name !== undefined) upd.name = patch.name; if (patch.metadata !== undefined) upd.metadata = patch.metadata; const [r] = await db.update(users).set({ ...upd, updated_at: new Date() }).where(eq(users.id, id)).returning(); return { id: r.id, email: r.email, name: r.name, metadata: r.metadata, createdAt: r.created_at, updatedAt: r.updated_at } as User; }, async createSession(session) { const [r] = await db.insert(sessions).values({ user_id: session.userId, handle: session.handle ?? null, expires_at: session.expiresAt, metadata: session.metadata ?? null }).returning(); return { id: r.id, userId: r.user_id, handle: r.handle, createdAt: r.created_at, expiresAt: r.expires_at, metadata: r.metadata } as Session; }, async getSessionById(id) { const r = await db.select().from(sessions).where(eq(sessions.id, id)).limit(1).then(res => res[0]); if (!r) return null; return { id: r.id, userId: r.user_id, handle: r.handle, createdAt: r.created_at, expiresAt: r.expires_at, metadata: r.metadata } as Session; }, async deleteSession(id) { await db.delete(sessions).where(eq(sessions.id, id)); }, async deleteSessionsByUserId(userId) { await db.delete(sessions).where(eq(sessions.user_id, userId)); }, async storeMagicToken({ tokenHash, userId = null, expiresAt, ip = null, userAgent = null }) { const [r] = await db.insert(magic_tokens).values({ token_hash: tokenHash, user_id: userId, expires_at: expiresAt, ip, user_agent: userAgent }).returning(); return { id: r.id, tokenHash: r.token_hash, userId: r.user_id, createdAt: r.created_at, expiresAt: r.expires_at, consumedAt: r.consumed_at, ip: r.ip, userAgent: r.user_agent } as MagicToken; }, async findValidMagicToken(tokenHash) { const r = await db.select().from(magic_tokens).where(eq(magic_tokens.token_hash, tokenHash), eq(magic_tokens.consumed_at, null)).limit(1).then(res => res[0]); if (!r) return null; return { id: r.id, tokenHash: r.token_hash, userId: r.user_id, createdAt: r.created_at, expiresAt: r.expires_at, consumedAt: r.consumed_at, ip: r.ip, userAgent: r.user_agent } as MagicToken; }, async consumeMagicToken(id) { await db.update(magic_tokens).set({ consumed_at: new Date() }).where(eq(magic_tokens.id, id)); }, }; }