73
apps/web/src/lib/services/action-events.ts
Executable file
73
apps/web/src/lib/services/action-events.ts
Executable file
@@ -0,0 +1,73 @@
|
||||
import { db, actionEvents } from "../db";
|
||||
import { eq, desc, and, isNull, lt, sql } from "drizzle-orm";
|
||||
|
||||
export interface RecordActionInput {
|
||||
userId: string;
|
||||
actionType: string;
|
||||
entityType: string;
|
||||
entityId: string;
|
||||
summary: string;
|
||||
beforeState: Record<string, unknown>;
|
||||
afterState: Record<string, unknown>;
|
||||
inversePatch?: Record<string, unknown>;
|
||||
metadata?: Record<string, unknown>;
|
||||
undoable?: boolean;
|
||||
}
|
||||
|
||||
export async function recordAction(input: RecordActionInput) {
|
||||
const [event] = await db
|
||||
.insert(actionEvents)
|
||||
.values({
|
||||
userId: input.userId,
|
||||
actionType: input.actionType,
|
||||
entityType: input.entityType,
|
||||
entityId: input.entityId,
|
||||
summary: input.summary,
|
||||
beforeState: input.beforeState,
|
||||
afterState: input.afterState,
|
||||
inversePatch: input.inversePatch,
|
||||
metadata: input.metadata ?? {},
|
||||
undoable: input.undoable ?? true,
|
||||
})
|
||||
.returning();
|
||||
return event;
|
||||
}
|
||||
|
||||
export async function getRecentActions(userId: string, limit = 20) {
|
||||
return db
|
||||
.select()
|
||||
.from(actionEvents)
|
||||
.where(and(eq(actionEvents.userId, userId), isNull(actionEvents.undoneAt)))
|
||||
.orderBy(desc(actionEvents.createdAt))
|
||||
.limit(limit);
|
||||
}
|
||||
|
||||
export async function getActionEvent(userId: string, actionEventId: string) {
|
||||
const [event] = await db
|
||||
.select()
|
||||
.from(actionEvents)
|
||||
.where(
|
||||
and(eq(actionEvents.id, actionEventId), eq(actionEvents.userId, userId))
|
||||
);
|
||||
return event ?? null;
|
||||
}
|
||||
|
||||
export async function markUndone(actionEventId: string) {
|
||||
await db
|
||||
.update(actionEvents)
|
||||
.set({ undoneAt: new Date() })
|
||||
.where(eq(actionEvents.id, actionEventId));
|
||||
}
|
||||
|
||||
export async function pruneOldActions(userId: string, daysOld = 90) {
|
||||
const cutoff = new Date();
|
||||
cutoff.setDate(cutoff.getDate() - daysOld);
|
||||
await db
|
||||
.delete(actionEvents)
|
||||
.where(
|
||||
and(
|
||||
eq(actionEvents.userId, userId),
|
||||
lt(actionEvents.createdAt, cutoff)
|
||||
)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user