This commit is contained in:
2025-12-16 13:53:23 +01:00
parent 84f05598a6
commit 29dc11deb9
127 changed files with 538 additions and 547 deletions

View File

@@ -7,9 +7,9 @@
import type { AsyncUseCase } from '@core/shared/application';
import type { Logger } from '@core/shared/application';
import type { IPageViewRepository } from '../../domain/repositories/IPageViewRepository';
import type { IEngagementRepository } from '../../domain/repositories/IEngagementRepository';
import type { IAnalyticsSnapshotRepository } from '../../domain/repositories/IAnalyticsSnapshotRepository';
import type { IPageViewRepository } from '../repositories/IPageViewRepository';
import type { IEngagementRepository } from '@core/analytics/domain/repositories/IEngagementRepository';
import type { IAnalyticsSnapshotRepository } from '@core/analytics/domain/repositories/IAnalyticsSnapshotRepository';
import type { EntityType } from '../../domain/types/PageView';
import type { SnapshotPeriod } from '../../domain/types/AnalyticsSnapshot';
@@ -69,7 +69,8 @@ export class GetEntityAnalyticsQuery
);
this.logger.debug(`Total page views for entity ${input.entityId}: ${totalPageViews}`);
} catch (error) {
this.logger.error(`Error counting total page views for entity ${input.entityId}: ${error.message}`);
const err = error instanceof Error ? error : new Error(String(error));
this.logger.error(`Error counting total page views for entity ${input.entityId}: ${err.message}`);
throw error;
}
@@ -82,7 +83,8 @@ export class GetEntityAnalyticsQuery
);
this.logger.debug(`Unique visitors for entity ${input.entityId}: ${uniqueVisitors}`);
} catch (error) {
this.logger.error(`Error counting unique visitors for entity ${input.entityId}: ${error.message}`);
const err = error instanceof Error ? error : new Error(String(error));
this.logger.error(`Error counting unique visitors for entity ${input.entityId}: ${err.message}`);
throw error;
}
@@ -94,7 +96,8 @@ export class GetEntityAnalyticsQuery
);
this.logger.debug(`Sponsor clicks for entity ${input.entityId}: ${sponsorClicks}`);
} catch (error) {
this.logger.error(`Error getting sponsor clicks for entity ${input.entityId}: ${error.message}`);
const err = error instanceof Error ? error : new Error(String(error));
this.logger.error(`Error getting sponsor clicks for entity ${input.entityId}: ${err.message}`);
throw error;
}
@@ -104,7 +107,8 @@ export class GetEntityAnalyticsQuery
engagementScore = await this.calculateEngagementScore(input.entityId, since);
this.logger.debug(`Engagement score for entity ${input.entityId}: ${engagementScore}`);
} catch (error) {
this.logger.error(`Error calculating engagement score for entity ${input.entityId}: ${error.message}`);
const err = error instanceof Error ? error : new Error(String(error));
this.logger.error(`Error calculating engagement score for entity ${input.entityId}: ${err.message}`);
throw error;
}
@@ -130,7 +134,8 @@ export class GetEntityAnalyticsQuery
previousPageViews = fullPreviousPageViews - totalPageViews; // This calculates change, not just previous period's total
this.logger.debug(`Previous period full page views: ${fullPreviousPageViews}, change: ${previousPageViews}`);
} catch (error) {
this.logger.error(`Error counting previous period page views for entity ${input.entityId}: ${error.message}`);
const err = error instanceof Error ? error : new Error(String(error));
this.logger.error(`Error counting previous period page views for entity ${input.entityId}: ${err.message}`);
throw error;
}
@@ -145,7 +150,8 @@ export class GetEntityAnalyticsQuery
this.logger.debug(`Previous period full unique visitors: ${fullPreviousUniqueVisitors}, change: ${previousUniqueVisitors}`);
} catch (error) {
this.logger.error(`Error counting previous period unique visitors for entity ${input.entityId}: ${error.message}`);
const err = error instanceof Error ? error : new Error(String(error));
this.logger.error(`Error counting previous period unique visitors for entity ${input.entityId}: ${err.message}`);
throw error;
}
@@ -218,7 +224,8 @@ export class GetEntityAnalyticsQuery
sponsorClicks = await this.engagementRepository.getSponsorClicksForEntity(entityId, since);
this.logger.debug(`Sponsor clicks for engagement score for entity ${entityId}: ${sponsorClicks}`);
} catch (error) {
this.logger.error(`Error getting sponsor clicks for engagement score for entity ${entityId}: ${error.message}`);
const err = error instanceof Error ? error : new Error(String(error));
this.logger.error(`Error getting sponsor clicks for engagement score for entity ${entityId}: ${err.message}`);
throw error;
}
const score = sponsorClicks * 10; // Weighted score

View File

@@ -8,7 +8,7 @@ import type { AsyncUseCase } from '@core/shared/application';
import type { Logger } from '@core/shared/application';
import { PageView } from '../../domain/entities/PageView';
import type { EntityType, VisitorType } from '../../domain/types/PageView';
import type { IPageViewRepository } from '../../domain/repositories/IPageViewRepository';
import type { IPageViewRepository } from '../repositories/IPageViewRepository';
export interface RecordPageViewInput {
entityType: EntityType;
@@ -57,7 +57,8 @@ export class RecordPageViewUseCase
this.logger.info('Page view recorded successfully', { pageViewId, input });
return { pageViewId };
} catch (error) {
this.logger.error('Error recording page view', error, { input });
const err = error instanceof Error ? error : new Error(String(error));
this.logger.error('Error recording page view', err, { input });
throw error;
}
}

View File

@@ -1,6 +1,6 @@
export interface Logger {
debug(message: string, ...args: any[]): void;
info(message: string, ...args: any[]): void;
warn(message: string, ...args: any[]): void;
error(message: string, ...args: any[]): void;
debug(message: string, ...args: unknown[]): void;
info(message: string, ...args: unknown[]): void;
warn(message: string, ...args: unknown[]): void;
error(message: string, ...args: unknown[]): void;
}

View File

@@ -1,4 +1,4 @@
import { AnalyticsEntityId } from '../../../core/analytics/domain/value-objects/AnalyticsEntityId';
import { AnalyticsEntityId } from '@core/analytics/domain/value-objects/AnalyticsEntityId';
describe('AnalyticsEntityId', () => {
it('creates a valid AnalyticsEntityId from a non-empty string', () => {

View File

@@ -1,4 +1,4 @@
import { AnalyticsSessionId } from '../../../core/analytics/domain/value-objects/AnalyticsSessionId';
import { AnalyticsSessionId } from '@core/analytics/domain/value-objects/AnalyticsSessionId';
describe('AnalyticsSessionId', () => {
it('creates a valid AnalyticsSessionId from a non-empty string', () => {

View File

@@ -1,4 +1,4 @@
import { PageViewId } from '../../../core/analytics/domain/value-objects/PageViewId';
import { PageViewId } from '@core/analytics/domain/value-objects/PageViewId';
describe('PageViewId', () => {
it('creates a valid PageViewId from a non-empty string', () => {

View File

@@ -10,8 +10,8 @@ export * from './domain/entities/PageView';
export * from './domain/entities/EngagementEvent';
export * from './domain/entities/AnalyticsSnapshot';
// Domain repositories
export * from './domain/repositories/IPageViewRepository';
// Application repositories
export * from './application/repositories/IPageViewRepository';
export * from './domain/repositories/IEngagementRepository';
export * from './domain/repositories/IAnalyticsSnapshotRepository';
@@ -20,7 +20,7 @@ export * from './application/use-cases/RecordPageViewUseCase';
export * from './application/use-cases/RecordEngagementUseCase';
export * from './application/use-cases/GetEntityAnalyticsQuery';
// Infrastructure
export * from './infrastructure/repositories/InMemoryPageViewRepository';
export * from './infrastructure/repositories/InMemoryEngagementRepository';
export * from './infrastructure/repositories/InMemoryAnalyticsSnapshotRepository';
// Infrastructure (moved to adapters)
export type { IPageViewRepository } from './application/repositories/IPageViewRepository';
export type { IEngagementRepository } from './domain/repositories/IEngagementRepository';
export type { IAnalyticsSnapshotRepository } from './domain/repositories/IAnalyticsSnapshotRepository';