This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

semble / src / modules / user / application / useCases / queries / GetUserStatsUseCase.ts
3.8 kB 134 lines
1import { err, ok, Result } from 'src/shared/core/Result'; 2import { UseCase } from 'src/shared/core/UseCase'; 3import { 4 IUserStatsRepository, 5 UserGrowthStatsDTO, 6 UserEngagementStatsDTO, 7 UserStatType, 8 TimeInterval, 9} from '../../../domain/IUserStatsRepository'; 10 11export interface GetUserStatsQuery { 12 statType: UserStatType; 13 interval?: TimeInterval; 14 limit?: number; 15 includeTimeSeries?: boolean; // For engagement stats 16 // Future parameters can be added here for other stat types 17} 18 19export type GetUserStatsResult = UserGrowthStatsDTO | UserEngagementStatsDTO; // Union type for different stat types 20 21export class ValidationError extends Error { 22 constructor(message: string) { 23 super(message); 24 this.name = 'ValidationError'; 25 } 26} 27 28export class GetUserStatsUseCase 29 implements UseCase<GetUserStatsQuery, Result<GetUserStatsResult>> 30{ 31 constructor(private userStatsRepository: IUserStatsRepository) {} 32 33 async execute(query: GetUserStatsQuery): Promise<Result<GetUserStatsResult>> { 34 try { 35 // Validate query parameters 36 if (!query.statType) { 37 return err(new ValidationError('Stat type is required')); 38 } 39 40 // Route to appropriate repository method based on stat type 41 switch (query.statType) { 42 case 'growth': 43 return await this.handleGrowthStats(query); 44 45 case 'engagement': 46 return await this.handleEngagementStats(query); 47 48 // Future stat types can be added here 49 // case 'activity': 50 // return await this.handleActivityStats(query); 51 52 default: 53 return err( 54 new ValidationError(`Invalid stat type: ${query.statType}`), 55 ); 56 } 57 } catch (error) { 58 return err( 59 new Error( 60 `Failed to retrieve user stats: ${error instanceof Error ? error.message : 'Unknown error'}`, 61 ), 62 ); 63 } 64 } 65 66 private async handleGrowthStats( 67 query: GetUserStatsQuery, 68 ): Promise<Result<UserGrowthStatsDTO>> { 69 // Apply defaults 70 const interval = query.interval || 'day'; 71 const limit = query.limit || 30; 72 73 // Validate parameters 74 if (!['day', 'week', 'month'].includes(interval)) { 75 return err(new ValidationError(`Invalid interval: ${interval}`)); 76 } 77 78 if (limit < 1 || limit > 365) { 79 return err(new ValidationError('Limit must be between 1 and 365')); 80 } 81 82 try { 83 const stats = await this.userStatsRepository.getUserGrowthStats({ 84 interval, 85 limit, 86 }); 87 88 return ok(stats); 89 } catch (error) { 90 return err( 91 new Error( 92 `Failed to retrieve growth stats: ${error instanceof Error ? error.message : 'Unknown error'}`, 93 ), 94 ); 95 } 96 } 97 98 private async handleEngagementStats( 99 query: GetUserStatsQuery, 100 ): Promise<Result<UserEngagementStatsDTO>> { 101 // Apply defaults 102 const interval = query.interval || 'day'; 103 const limit = query.limit || 30; 104 const includeTimeSeries = query.includeTimeSeries || false; 105 106 // Validate parameters 107 if (interval && !['day', 'week', 'month'].includes(interval)) { 108 return err(new ValidationError(`Invalid interval: ${interval}`)); 109 } 110 111 if (limit < 1 || limit > 365) { 112 return err(new ValidationError('Limit must be between 1 and 365')); 113 } 114 115 try { 116 const stats = await this.userStatsRepository.getUserEngagementStats({ 117 interval, 118 limit, 119 includeTimeSeries, 120 }); 121 122 return ok(stats); 123 } catch (error) { 124 return err( 125 new Error( 126 `Failed to retrieve engagement stats: ${error instanceof Error ? error.message : 'Unknown error'}`, 127 ), 128 ); 129 } 130 } 131 132 // Future handler methods can be added here 133 // private async handleActivityStats(query: GetUserStatsQuery): Promise<Result<UserActivityStatsDTO>> { ... } 134}