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.
71 lines (67 loc) • 2.37 kB
text/typescript
import { Adapter, User, Session, MagicToken } from './types';
import crypto from 'crypto';
function id() {
return crypto.randomUUID();
}
export function createMemoryAdapter(): Adapter {
const users = new Map<string, User>();
const sessions = new Map<string, Session>();
const tokens = new Map<string, MagicToken>();
return {
async createUser({ email, name, metadata }) {
const now = new Date();
const u: User = { id: id(), email, name: name ?? null, metadata: metadata ?? null, createdAt: now, updatedAt: now };
users.set(u.id, u);
return u;
},
async getUserById(id) {
return users.get(id) ?? null;
},
async getUserByEmail(email) {
for (const u of Array.from(users.values())) {
if (u.email === email) return u;
}
return null;
},
async updateUser(id, patch) {
const u = users.get(id);
if (!u) throw new Error('user not found');
const nu = { ...u, ...patch, updatedAt: new Date() } as User;
users.set(id, nu);
return nu;
},
async createSession(session) {
const s: Session = { id: id(), userId: session.userId, createdAt: new Date(), expiresAt: session.expiresAt, handle: session.handle ?? null, metadata: session.metadata ?? null };
sessions.set(s.id, s);
return s;
},
async getSessionById(id) {
return sessions.get(id) ?? null;
},
async deleteSession(id) {
sessions.delete(id);
},
async deleteSessionsByUserId(userId) {
for (const [k, s] of Array.from(sessions.entries())) {
if (s.userId === userId) sessions.delete(k);
}
},
async storeMagicToken({ tokenHash, userId = null, expiresAt, ip = null, userAgent = null }) {
const t: MagicToken = { id: id(), tokenHash, userId, createdAt: new Date(), expiresAt, consumedAt: null, ip, userAgent };
tokens.set(t.id, t);
return t;
},
async findValidMagicToken(tokenHash) {
for (const t of Array.from(tokens.values())) {
if (t.tokenHash === tokenHash && !t.consumedAt && t.expiresAt > new Date()) return t;
}
return null;
},
async consumeMagicToken(id) {
const t = tokens.get(id);
if (!t) return;
t.consumedAt = new Date();
tokens.set(id, t);
},
};
}