import type { BusinessEvent } from '../../../foundation/business-events/types.ts'; import type { ProjectionConsumer, ProjectionHandleResult } from '../../../foundation/projections/types.ts'; import { getProjectionDefinition } from '../../../foundation/projections/registry.ts'; import { buildCalendarChangeFromEvent } from './builder.ts'; const definition = getProjectionDefinition('Calendar'); interface CalendarProjectionConsumerOptions { persist?: (change: ReturnType) => Promise; } export function createCalendarProjectionConsumer( options: CalendarProjectionConsumerOptions = {} ): ProjectionConsumer { const persist = options.persist ?? persistCalendarChange; return { consumerName: definition.consumerName, projectionName: definition.projectionName, supportedEventTypes: definition.consumedEventTypes, supportedVersions: definition.supportedVersions, async handle(event: BusinessEvent): Promise { const change = buildCalendarChangeFromEvent(event); if (!change) { return { status: 'skipped', message: 'Calendar event has no schedulable date', sideEffectCount: 0 }; } const sideEffectCount = await persist(change); return { status: 'processed', message: change.action === 'delete' ? 'Calendar projection activity item removed' : 'Calendar projection item persisted', sideEffectCount }; } }; } export const calendarProjectionConsumer = createCalendarProjectionConsumer(); async function persistCalendarChange( change: ReturnType ): Promise { if (!change) return 0; const { deleteCalendarProjectionForActivity, upsertCalendarProjectionItem } = await import( './service.ts' ); if (change.action === 'delete') { await deleteCalendarProjectionForActivity({ organizationId: change.organizationId, activityId: change.activityId }); return 1; } await deleteCalendarProjectionForActivity({ organizationId: change.item.organizationId, activityId: change.item.activityId ?? change.item.entityId }); await upsertCalendarProjectionItem(change.item); return 1; }