This commit is contained in:
2025-12-17 14:04:11 +01:00
parent 1ea9c9649f
commit daa4bb6576
238 changed files with 4263 additions and 1752 deletions

View File

@@ -1,8 +1,16 @@
import { Controller, Post, Body, Res, HttpStatus } from '@nestjs/common';
import type { Response } from 'express';
import type { RecordPageViewInput, RecordPageViewOutput, RecordEngagementInput, RecordEngagementOutput } from './dto/AnalyticsDto';
import type { RecordPageViewInputDTO } from './dtos/RecordPageViewInputDTO';
import type { RecordPageViewOutputDTO } from './dtos/RecordPageViewOutputDTO';
import type { RecordEngagementInputDTO } from './dtos/RecordEngagementInputDTO';
import type { RecordEngagementOutputDTO } from './dtos/RecordEngagementOutputDTO';
import { AnalyticsService } from './AnalyticsService';
type RecordPageViewInput = RecordPageViewInputDTO;
type RecordPageViewOutput = RecordPageViewOutputDTO;
type RecordEngagementInput = RecordEngagementInputDTO;
type RecordEngagementOutput = RecordEngagementOutputDTO;
@Controller('analytics')
export class AnalyticsController {
constructor(

View File

@@ -1,9 +1,17 @@
import { Injectable, Inject } from '@nestjs/common';
import { RecordEngagementInput, RecordEngagementOutput, RecordPageViewInput, RecordPageViewOutput } from './dto/AnalyticsDto';
import type { RecordPageViewInputDTO } from './dtos/RecordPageViewInputDTO';
import type { RecordPageViewOutputDTO } from './dtos/RecordPageViewOutputDTO';
import type { RecordEngagementInputDTO } from './dtos/RecordEngagementInputDTO';
import type { RecordEngagementOutputDTO } from './dtos/RecordEngagementOutputDTO';
import type { Logger } from '@core/shared/application';
import { RecordPageViewUseCase } from './use-cases/RecordPageViewUseCase';
import { RecordEngagementUseCase } from './use-cases/RecordEngagementUseCase';
type RecordPageViewInput = RecordPageViewInputDTO;
type RecordPageViewOutput = RecordPageViewOutputDTO;
type RecordEngagementInput = RecordEngagementInputDTO;
type RecordEngagementOutput = RecordEngagementOutputDTO;
const Logger_TOKEN = 'Logger_TOKEN';
const RECORD_PAGE_VIEW_USE_CASE_TOKEN = 'RecordPageViewUseCase_TOKEN';
const RECORD_ENGAGEMENT_USE_CASE_TOKEN = 'RecordEngagementUseCase_TOKEN';

View File

@@ -1,127 +0,0 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsOptional, IsEnum, IsBoolean, IsNumber, IsObject } from 'class-validator';
// From core/analytics/domain/types/PageView.ts
export enum EntityType {
LEAGUE = 'league',
DRIVER = 'driver',
TEAM = 'team',
RACE = 'race',
SPONSOR = 'sponsor',
}
// From core/analytics/domain/types/PageView.ts
export enum VisitorType {
ANONYMOUS = 'anonymous',
DRIVER = 'driver',
SPONSOR = 'sponsor',
}
export class RecordPageViewInput {
@ApiProperty({ enum: EntityType })
@IsEnum(EntityType)
entityType!: EntityType;
@ApiProperty()
@IsString()
entityId!: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
visitorId?: string;
@ApiProperty({ enum: VisitorType })
@IsEnum(VisitorType)
visitorType!: VisitorType;
@ApiProperty()
@IsString()
sessionId!: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
referrer?: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
userAgent?: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
country?: string;
}
export class RecordPageViewOutput {
@ApiProperty()
@IsString()
pageViewId!: string;
}
// From core/analytics/domain/types/EngagementEvent.ts
export enum EngagementAction {
CLICK_SPONSOR_LOGO = 'click_sponsor_logo',
CLICK_SPONSOR_URL = 'click_sponsor_url',
DOWNLOAD_LIVERY_PACK = 'download_livery_pack',
JOIN_LEAGUE = 'join_league',
REGISTER_RACE = 'register_race',
VIEW_STANDINGS = 'view_standings',
VIEW_SCHEDULE = 'view_schedule',
SHARE_SOCIAL = 'share_social',
CONTACT_SPONSOR = 'contact_sponsor',
}
// From core/analytics/domain/types/EngagementEvent.ts
export enum EngagementEntityType {
LEAGUE = 'league',
DRIVER = 'driver',
TEAM = 'team',
RACE = 'race',
SPONSOR = 'sponsor',
SPONSORSHIP = 'sponsorship',
}
export class RecordEngagementInput {
@ApiProperty({ enum: EngagementAction })
@IsEnum(EngagementAction)
action!: EngagementAction;
@ApiProperty({ enum: EngagementEntityType })
@IsEnum(EngagementEntityType)
entityType!: EngagementEntityType;
@ApiProperty()
@IsString()
entityId!: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
actorId?: string;
@ApiProperty({ enum: ['anonymous', 'driver', 'sponsor'] })
@IsEnum(['anonymous', 'driver', 'sponsor'])
actorType!: 'anonymous' | 'driver' | 'sponsor';
@ApiProperty()
@IsString()
sessionId!: string;
@ApiProperty({ required: false, type: Object })
@IsOptional()
@IsObject()
metadata?: Record<string, string | number | boolean>;
}
export class RecordEngagementOutput {
@ApiProperty()
@IsString()
eventId!: string;
@ApiProperty()
@IsNumber()
engagementWeight!: number;
}

View File

@@ -0,0 +1,12 @@
// From core/analytics/domain/types/EngagementEvent.ts
export enum EngagementAction {
CLICK_SPONSOR_LOGO = 'click_sponsor_logo',
CLICK_SPONSOR_URL = 'click_sponsor_url',
DOWNLOAD_LIVERY_PACK = 'download_livery_pack',
JOIN_LEAGUE = 'join_league',
REGISTER_RACE = 'register_race',
VIEW_STANDINGS = 'view_standings',
VIEW_SCHEDULE = 'view_schedule',
SHARE_SOCIAL = 'share_social',
CONTACT_SPONSOR = 'contact_sponsor',
}

View File

@@ -0,0 +1,9 @@
// From core/analytics/domain/types/EngagementEvent.ts
export enum EngagementEntityType {
LEAGUE = 'league',
DRIVER = 'driver',
TEAM = 'team',
RACE = 'race',
SPONSOR = 'sponsor',
SPONSORSHIP = 'sponsorship',
}

View File

@@ -0,0 +1,8 @@
// From core/analytics/domain/types/PageView.ts
export enum EntityType {
LEAGUE = 'league',
DRIVER = 'driver',
TEAM = 'team',
RACE = 'race',
SPONSOR = 'sponsor',
}

View File

@@ -0,0 +1,36 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsOptional, IsEnum, IsObject } from 'class-validator';
import { EngagementAction } from './EngagementAction';
import { EngagementEntityType } from './EngagementEntityType';
export class RecordEngagementInputDTO {
@ApiProperty({ enum: EngagementAction })
@IsEnum(EngagementAction)
action!: EngagementAction;
@ApiProperty({ enum: EngagementEntityType })
@IsEnum(EngagementEntityType)
entityType!: EngagementEntityType;
@ApiProperty()
@IsString()
entityId!: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
actorId?: string;
@ApiProperty({ enum: ['anonymous', 'driver', 'sponsor'] })
@IsEnum(['anonymous', 'driver', 'sponsor'])
actorType!: 'anonymous' | 'driver' | 'sponsor';
@ApiProperty()
@IsString()
sessionId!: string;
@ApiProperty({ required: false, type: Object })
@IsOptional()
@IsObject()
metadata?: Record<string, string | number | boolean>;
}

View File

@@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsNumber } from 'class-validator';
export class RecordEngagementOutputDTO {
@ApiProperty()
@IsString()
eventId!: string;
@ApiProperty()
@IsNumber()
engagementWeight!: number;
}

View File

@@ -0,0 +1,42 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsOptional, IsEnum } from 'class-validator';
import { EntityType } from './EntityType';
import { VisitorType } from './VisitorType';
export class RecordPageViewInputDTO {
@ApiProperty({ enum: EntityType })
@IsEnum(EntityType)
entityType!: EntityType;
@ApiProperty()
@IsString()
entityId!: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
visitorId?: string;
@ApiProperty({ enum: VisitorType })
@IsEnum(VisitorType)
visitorType!: VisitorType;
@ApiProperty()
@IsString()
sessionId!: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
referrer?: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
userAgent?: string;
@ApiProperty({ required: false })
@IsOptional()
@IsString()
country?: string;
}

View File

@@ -0,0 +1,8 @@
import { ApiProperty } from '@nestjs/swagger';
import { IsString } from 'class-validator';
export class RecordPageViewOutputDTO {
@ApiProperty()
@IsString()
pageViewId!: string;
}

View File

@@ -0,0 +1,6 @@
// From core/analytics/domain/types/PageView.ts
export enum VisitorType {
ANONYMOUS = 'anonymous',
DRIVER = 'driver',
SPONSOR = 'sponsor',
}

View File

@@ -1,9 +1,13 @@
import { Injectable, Inject } from '@nestjs/common';
import { RecordEngagementInput, RecordEngagementOutput } from '../dto/AnalyticsDto';
import type { RecordEngagementInputDTO } from '../dtos/RecordEngagementInputDTO';
import type { RecordEngagementOutputDTO } from '../dtos/RecordEngagementOutputDTO';
import type { IEngagementRepository } from '@core/analytics/domain/repositories/IEngagementRepository';
import type { Logger } from '@core/shared/application';
import { EngagementEvent } from '@core/analytics/domain/entities/EngagementEvent';
type RecordEngagementInput = RecordEngagementInputDTO;
type RecordEngagementOutput = RecordEngagementOutputDTO;
const Logger_TOKEN = 'Logger_TOKEN';
const IENGAGEMENT_REPO_TOKEN = 'IEngagementRepository_TOKEN';

View File

@@ -1,9 +1,13 @@
import { Injectable, Inject } from '@nestjs/common';
import { RecordPageViewInput, RecordPageViewOutput } from '../dto/AnalyticsDto';
import type { RecordPageViewInputDTO } from '../dtos/RecordPageViewInputDTO';
import type { RecordPageViewOutputDTO } from '../dtos/RecordPageViewOutputDTO';
import type { IPageViewRepository } from '@core/analytics/application/repositories/IPageViewRepository';
import type { Logger } from '@core/shared/application';
import { PageView } from '@core/analytics/domain/entities/PageView';
type RecordPageViewInput = RecordPageViewInputDTO;
type RecordPageViewOutput = RecordPageViewOutputDTO;
const Logger_TOKEN = 'Logger_TOKEN';
const IPAGE_VIEW_REPO_TOKEN = 'IPageViewRepository_TOKEN';