/opt/canhelp/apps/api/src/lib
NameSizeModeActions
activity.ts13240644editdlrm
apple-client-secret.ts40730644editdlrm
balance.ts35060644editdlrm
daily-limits.ts42820644editdlrm
email.ts527080644editdlrm
fomo.ts113660644editdlrm
google-oauth.ts105260644editdlrm
helper-capability.ts42070644editdlrm
messaging-rules.ts31230644editdlrm
nameUtils.ts7090644editdlrm
notif.ts189290644editdlrm
plan-history.ts10200644editdlrm
push.ts63860644editdlrm
referral.ts61100644editdlrm
telegram.ts62070644editdlrm
turnstile.ts7410644editdlrm
Edit: /opt/canhelp/apps/api/src/lib/activity.ts (1324B)
import { db } from '../db.js' import { activityLogs, users } from '@canhelp/db' import { eq } from 'drizzle-orm' export async function logActivity(opts: { userId?: string | null userEmail?: string | null userName?: string | null event: string details?: Record | null ipAddress?: string | null userAgent?: string | null }): Promise { try { let { userId, userEmail, userName } = opts // Auto-fetch email/name if only userId is provided if (userId && (!userEmail || !userName)) { const [u] = await db .select({ email: users.email, firstName: users.firstName, lastName: users.lastName, name: users.name }) .from(users) .where(eq(users.id, userId)) .limit(1) .catch(() => []) if (u) { userEmail = userEmail ?? u.email userName = userName ?? (`${u.firstName} ${u.lastName}`.trim() || u.name) } } await db.insert(activityLogs).values({ userId: userId ?? null, userEmail: userEmail ?? null, userName: userName ?? null, event: opts.event, details: opts.details ? JSON.stringify(opts.details) : null, ipAddress: opts.ipAddress ?? null, userAgent: opts.userAgent ?? null, }) } catch { // Never throw — logging must not break the main flow } }