feat: auto-create ClientTimelineEntry via Prisma middleware

CalendarEvent and FeedCard now automatically get a ClientTimelineEntry
when created/updated with a contactId. This ensures events created by
the agent (or any other code path) appear in the contact timeline
without needing explicit upsertClientTimelineEntry calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ruslan Bakiev
2026-02-25 09:01:30 +07:00
parent bf7f4ae933
commit 693a96cffd

View File

@@ -11,6 +11,44 @@ export const prisma =
log: ["error", "warn"], log: ["error", "warn"],
}); });
// ---------------------------------------------------------------------------
// Auto-sync ClientTimelineEntry for CalendarEvent, WorkspaceDocument, FeedCard
// ---------------------------------------------------------------------------
const TIMELINE_MODEL_MAP: Record<string, string> = {
CalendarEvent: "CALENDAR_EVENT",
FeedCard: "RECOMMENDATION",
};
prisma.$use(async (params, next) => {
const result = await next(params);
const contentType = params.model ? TIMELINE_MODEL_MAP[params.model] : undefined;
if (!contentType) return result;
if (params.action !== "create" && params.action !== "update" && params.action !== "upsert") return result;
if (!result || typeof result !== "object") return result;
const row = result as Record<string, any>;
const teamId = row.teamId as string | undefined;
const contactId = row.contactId as string | undefined;
const id = row.id as string | undefined;
if (!teamId || !contactId || !id) return result;
const datetime = row.startsAt ?? row.happenedAt ?? row.createdAt ?? new Date();
prisma.clientTimelineEntry
.upsert({
where: {
teamId_contentType_contentId: { teamId, contentType, contentId: id },
},
create: { teamId, contactId, contentType, contentId: id, datetime },
update: { contactId, datetime },
select: { id: true },
})
.catch(() => {});
return result;
});
if (process.env.NODE_ENV !== "production") { if (process.env.NODE_ENV !== "production") {
globalThis.__prisma = prisma; globalThis.__prisma = prisma;
} }