import type { Logger, UseCase } from '@core/shared/application'; import type { IPageViewRepository } from '../repositories/IPageViewRepository'; import { PageView } from '../../domain/entities/PageView'; import type { EntityType, VisitorType } from '../../domain/types/PageView'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; export interface RecordPageViewInput { entityType: EntityType; entityId: string; visitorId?: string; visitorType: VisitorType; sessionId: string; referrer?: string; userAgent?: string; country?: string; } export interface RecordPageViewOutput { pageViewId: string; } export type RecordPageViewErrorCode = 'REPOSITORY_ERROR'; export class RecordPageViewUseCase implements UseCase { constructor( private readonly pageViewRepository: IPageViewRepository, private readonly logger: Logger, ) {} async execute(input: RecordPageViewInput): Promise>> { try { type PageViewCreateProps = Parameters<(typeof PageView)['create']>[0]; const props: PageViewCreateProps = { id: crypto.randomUUID(), entityType: input.entityType, entityId: input.entityId, visitorType: input.visitorType, sessionId: input.sessionId, ...(input.visitorId !== undefined ? { visitorId: input.visitorId } : {}), ...(input.referrer !== undefined ? { referrer: input.referrer } : {}), ...(input.userAgent !== undefined ? { userAgent: input.userAgent } : {}), ...(input.country !== undefined ? { country: input.country } : {}), }; const pageView = PageView.create(props); await this.pageViewRepository.save(pageView); const resultModel: RecordPageViewOutput = { pageViewId: pageView.id, }; this.logger.info('Page view recorded', { pageViewId: pageView.id, entityId: input.entityId, entityType: input.entityType, }); return Result.ok(resultModel); } catch (error) { const err = error as Error; this.logger.error('Failed to record page view', err, { input }); return Result.err({ code: 'REPOSITORY_ERROR', details: { message: err.message ?? 'Failed to record page view' }, }); } } }