import type { AuditLogEntry, AuditLogPage, AuditLogQuery } from '@admin/actions/audit/types' import { clampPage } from '@admin/actions/audit/clamp-page' import { getAuditLogOrderBy } from '@admin/actions/audit/get-audit-log-order-by' import { normalizePageSize } from '@admin/actions/audit/normalize-page-size' import db from '@admin/db' import { auditLog } from '@admin/db/schema' import { getExclusiveDateUpperBound } from '@admin/utils/date/get-exclusive-date-upper-bound' import { and, eq, gte, ilike, lt, or, sql } from 'drizzle-orm' export async function queryAuditLogs(query: AuditLogQuery = {}): Promise { const page = clampPage(query.page) const pageSize = normalizePageSize(query.pageSize) const offset = pageSize ? page * pageSize : 0 const conditions = [] if (query.category) conditions.push(eq(auditLog.category, query.category)) if (query.action) conditions.push(eq(auditLog.action, query.action)) if (query.targetType) conditions.push(ilike(auditLog.targetType, `%${query.targetType}%`)) if (query.actor) { const actorPattern = `%${query.actor}%` conditions.push( or(ilike(auditLog.actorEmail, actorPattern), ilike(auditLog.actorName, actorPattern)) ) } if (query.createdAtFrom) { conditions.push(gte(auditLog.createdAt, query.createdAtFrom)) } const createdAtExclusiveTo = getExclusiveDateUpperBound(query.createdAtTo) if (createdAtExclusiveTo) { conditions.push(lt(auditLog.createdAt, createdAtExclusiveTo)) } if (query.search) { const searchPattern = `%${query.search}%` conditions.push( or( ilike(auditLog.targetId, searchPattern), ilike(auditLog.targetLabel, searchPattern), ilike(auditLog.actorEmail, searchPattern), ilike(auditLog.actorName, searchPattern), ilike(auditLog.sourceType, searchPattern), ilike(auditLog.ipAddress, searchPattern), ilike(auditLog.userAgent, searchPattern) ) ) } const where = conditions.length > 0 ? and(...conditions) : undefined const orderBy = getAuditLogOrderBy(query) const orderedQuery = db .select() .from(auditLog) .where(where) .orderBy(...orderBy) const [rows, countResult] = await Promise.all([ pageSize ? orderedQuery.limit(pageSize).offset(offset) : orderedQuery, db .select({ count: sql`count(*)` }) .from(auditLog) .where(where) ]) const total = Number(countResult[0]?.count ?? 0) const resolvedPageSize = pageSize ?? total return { auditLogs: rows as AuditLogEntry[], total, page, pageSize: resolvedPageSize, totalPages: pageSize ? Math.max(1, Math.ceil(total / pageSize)) : 1 } }