import { desc, eq, inArray } from "drizzle-orm"; import { recentActivity } from "../db/schema.js"; import type { DatabaseContext } from "./database-context.js"; import { rowsAffected } from "./mutation-result.js"; import { insertReturning } from "./returning.js"; export type RecentActivityRecord = typeof recentActivity.$inferSelect; export type NewRecentActivityRecord = typeof recentActivity.$inferInsert; export class RecentActivityRepository { constructor( private readonly context: DatabaseContext, private readonly onWrite?: () => void | Promise, ) {} async listByUserId( userId: string, limit: number, ): Promise { return this.context.drizzle .select() .from(recentActivity) .where(eq(recentActivity.userId, userId)) .orderBy(desc(recentActivity.timestamp)) .limit(limit); } async create( activity: NewRecentActivityRecord, ): Promise { const rows = await insertReturning(this.context, recentActivity, activity); await this.afterWrite(); return rows[0]; } async trimUserActivity(userId: string, keepCount: number): Promise { const rows = await this.context.drizzle .select({ id: recentActivity.id }) .from(recentActivity) .where(eq(recentActivity.userId, userId)) .orderBy(desc(recentActivity.timestamp)); const idsToDelete = rows .slice(keepCount) .map((row) => row.id) .filter((id) => typeof id === "number"); if (idsToDelete.length === 0) { return 0; } const result = await this.context.drizzle .delete(recentActivity) .where(inArray(recentActivity.id, idsToDelete)); if (rowsAffected(result) > 0) { await this.afterWrite(); } return rowsAffected(result); } async deleteByUserId(userId: string): Promise { const result = await this.context.drizzle .delete(recentActivity) .where(eq(recentActivity.userId, userId)); if (rowsAffected(result) > 0) { await this.afterWrite(); } return rowsAffected(result); } async deleteByHostId(hostId: number): Promise { const result = await this.context.drizzle .delete(recentActivity) .where(eq(recentActivity.hostId, hostId)); if (rowsAffected(result) > 0) { await this.afterWrite(); } return rowsAffected(result); } async deleteByHostIds(hostIds: number[]): Promise { if (hostIds.length === 0) { return 0; } const result = await this.context.drizzle .delete(recentActivity) .where(inArray(recentActivity.hostId, hostIds)); if (rowsAffected(result) > 0) { await this.afterWrite(); } return rowsAffected(result); } private async afterWrite(): Promise { await this.onWrite?.(); } }