website refactor
This commit is contained in:
@@ -17,7 +17,7 @@ const mockRepository = {
|
|||||||
create: vi.fn(),
|
create: vi.fn(),
|
||||||
update: vi.fn(),
|
update: vi.fn(),
|
||||||
delete: vi.fn(),
|
delete: vi.fn(),
|
||||||
} as unknown as IAdminUserRepository;
|
} as unknown as AdminUserRepository;
|
||||||
|
|
||||||
describe('ListUsersUseCase', () => {
|
describe('ListUsersUseCase', () => {
|
||||||
let useCase: ListUsersUseCase;
|
let useCase: ListUsersUseCase;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export type ListUsersApplicationError = ApplicationErrorCode<ListUsersErrorCode,
|
|||||||
*/
|
*/
|
||||||
export class ListUsersUseCase {
|
export class ListUsersUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly adminUserRepository: IAdminUserRepository,
|
private readonly adminUserRepository: AdminUserRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(
|
async execute(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Entity } from '@core/shared/domain/Entity';
|
import { Entity } from '@core/shared/domain/Entity';
|
||||||
import { AdminDomainInvariantError, AdminDomainValidationError } from '../errors/AdminDomainError';
|
import { AdminDomainInvariantError, AdminDomainValidationError } from '../errors/AdminDomainError';
|
||||||
import { Email } from '../value-objects/Email';
|
import { Email } from '../value-objects/Email';
|
||||||
import { UserId } from '../value-objects/UserId';
|
import { UserId } from '../value-objects/UserId';
|
||||||
@@ -17,8 +17,7 @@ export interface AdminUserProps {
|
|||||||
primaryDriverId: string | undefined;
|
primaryDriverId: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AdminUser implements Entity<UserId> {
|
export class AdminUser extends Entity<UserId> {
|
||||||
readonly id: UserId;
|
|
||||||
private _email: Email;
|
private _email: Email;
|
||||||
private _roles: UserRole[];
|
private _roles: UserRole[];
|
||||||
private _status: UserStatus;
|
private _status: UserStatus;
|
||||||
@@ -29,7 +28,8 @@ export class AdminUser implements Entity<UserId> {
|
|||||||
private _primaryDriverId: string | undefined;
|
private _primaryDriverId: string | undefined;
|
||||||
|
|
||||||
private constructor(props: AdminUserProps) {
|
private constructor(props: AdminUserProps) {
|
||||||
this.id = props.id;
|
super(props.id);
|
||||||
|
|
||||||
this._email = props.email;
|
this._email = props.email;
|
||||||
this._roles = props.roles;
|
this._roles = props.roles;
|
||||||
this._status = props.status;
|
this._status = props.status;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { DomainError, CommonDomainErrorKind } from '@core/shared/errors';
|
import type { DomainErrorProps, CommonDomainErrorKind } from '@core/shared/errors/DomainError';
|
||||||
|
|
||||||
export abstract class AdminDomainError extends Error implements DomainError<CommonDomainErrorKind> {
|
export abstract class AdminDomainError extends Error implements DomainErrorProps<CommonDomainErrorKind> {
|
||||||
readonly type = 'domain' as const;
|
readonly type = 'domain' as const;
|
||||||
readonly context = 'admin-domain';
|
readonly context = 'admin-domain';
|
||||||
abstract readonly kind: CommonDomainErrorKind;
|
abstract readonly kind: CommonDomainErrorKind;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ValueObject } from '@core/shared/domain';
|
import { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { AdminDomainValidationError } from '../errors/AdminDomainError';
|
import { AdminDomainValidationError } from '../errors/AdminDomainError';
|
||||||
|
|
||||||
export interface EmailProps {
|
export interface EmailProps {
|
||||||
@@ -40,7 +40,7 @@ export class Email implements ValueObject<EmailProps> {
|
|||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<EmailProps>): boolean {
|
equals(other: ValueObject<EmailProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ValueObject } from '@core/shared/domain';
|
import { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { AdminDomainValidationError } from '../errors/AdminDomainError';
|
import { AdminDomainValidationError } from '../errors/AdminDomainError';
|
||||||
|
|
||||||
export interface UserIdProps {
|
export interface UserIdProps {
|
||||||
@@ -28,7 +28,7 @@ export class UserId implements ValueObject<UserIdProps> {
|
|||||||
return { value: this.value };
|
return { value: this.value };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<UserIdProps>): boolean {
|
equals(other: ValueObject<UserIdProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ValueObject } from '@core/shared/domain';
|
import { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { AdminDomainValidationError } from '../errors/AdminDomainError';
|
import { AdminDomainValidationError } from '../errors/AdminDomainError';
|
||||||
|
|
||||||
export type UserRoleValue = string;
|
export type UserRoleValue = string;
|
||||||
@@ -41,7 +41,7 @@ export class UserRole implements ValueObject<UserRoleProps> {
|
|||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<UserRoleProps>): boolean {
|
equals(other: ValueObject<UserRoleProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ValueObject } from '@core/shared/domain';
|
import { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { AdminDomainValidationError } from '../errors/AdminDomainError';
|
import { AdminDomainValidationError } from '../errors/AdminDomainError';
|
||||||
|
|
||||||
export type UserStatusValue = string;
|
export type UserStatusValue = string;
|
||||||
@@ -41,7 +41,7 @@ export class UserStatus implements ValueObject<UserStatusProps> {
|
|||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<UserStatusProps>): boolean {
|
equals(other: ValueObject<UserStatusProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
import type { PageViewRepository } from '../repositories/PageViewRepository';
|
import type { PageViewRepository } from '../repositories/PageViewRepository';
|
||||||
@@ -20,7 +21,7 @@ export type GetAnalyticsMetricsErrorCode = 'REPOSITORY_ERROR';
|
|||||||
export class GetAnalyticsMetricsUseCase implements UseCase<GetAnalyticsMetricsInput, GetAnalyticsMetricsOutput, GetAnalyticsMetricsErrorCode> {
|
export class GetAnalyticsMetricsUseCase implements UseCase<GetAnalyticsMetricsInput, GetAnalyticsMetricsOutput, GetAnalyticsMetricsErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
private readonly pageViewRepository?: IPageViewRepository,
|
private readonly pageViewRepository?: PageViewRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(
|
async execute(
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ describe('GetEntityAnalyticsQuery', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new GetEntityAnalyticsQuery(
|
useCase = new GetEntityAnalyticsQuery(
|
||||||
pageViewRepository as unknown as IPageViewRepository,
|
pageViewRepository as unknown as PageViewRepository,
|
||||||
engagementRepository as unknown as IEngagementRepository,
|
engagementRepository as unknown as EngagementRepository,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
* Returns metrics formatted for display to sponsors and admins.
|
* Returns metrics formatted for display to sponsors and admins.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AsyncUseCase , Logger } from '@core/shared/application';
|
import type { AsyncUseCase } from '@core/shared/application/AsyncUseCase';
|
||||||
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
import type { PageViewRepository } from '../repositories/PageViewRepository';
|
import type { PageViewRepository } from '../repositories/PageViewRepository';
|
||||||
import type { EngagementRepository } from '@core/analytics/domain/repositories/EngagementRepository';
|
import type { EngagementRepository } from '@core/analytics/domain/repositories/EngagementRepository';
|
||||||
import type { EntityType } from '../../domain/types/PageView';
|
import type { EntityType } from '../../domain/types/PageView';
|
||||||
@@ -48,8 +49,8 @@ export type GetEntityAnalyticsErrorCode = 'REPOSITORY_ERROR';
|
|||||||
export class GetEntityAnalyticsQuery
|
export class GetEntityAnalyticsQuery
|
||||||
implements AsyncUseCase<GetEntityAnalyticsInput, EntityAnalyticsOutput, GetEntityAnalyticsErrorCode> {
|
implements AsyncUseCase<GetEntityAnalyticsInput, EntityAnalyticsOutput, GetEntityAnalyticsErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly pageViewRepository: IPageViewRepository,
|
private readonly pageViewRepository: PageViewRepository,
|
||||||
private readonly engagementRepository: IEngagementRepository,
|
private readonly engagementRepository: EngagementRepository,
|
||||||
private readonly logger: Logger
|
private readonly logger: Logger
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ describe('RecordEngagementUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new RecordEngagementUseCase(
|
useCase = new RecordEngagementUseCase(
|
||||||
engagementRepository as unknown as IEngagementRepository,
|
engagementRepository as unknown as EngagementRepository,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
import { EngagementEvent } from '../../domain/entities/EngagementEvent';
|
import { EngagementEvent } from '../../domain/entities/EngagementEvent';
|
||||||
@@ -24,7 +25,7 @@ export type RecordEngagementErrorCode = 'REPOSITORY_ERROR';
|
|||||||
|
|
||||||
export class RecordEngagementUseCase implements UseCase<RecordEngagementInput, RecordEngagementOutput, RecordEngagementErrorCode> {
|
export class RecordEngagementUseCase implements UseCase<RecordEngagementInput, RecordEngagementOutput, RecordEngagementErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly engagementRepository: IEngagementRepository,
|
private readonly engagementRepository: EngagementRepository,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
import type { PageViewRepository } from '../repositories/PageViewRepository';
|
import type { PageViewRepository } from '../repositories/PageViewRepository';
|
||||||
import { PageView } from '../../domain/entities/PageView';
|
import { PageView } from '../../domain/entities/PageView';
|
||||||
import type { EntityType, VisitorType } from '../../domain/types/PageView';
|
import type { EntityType, VisitorType } from '../../domain/types/PageView';
|
||||||
@@ -24,7 +25,7 @@ export type RecordPageViewErrorCode = 'REPOSITORY_ERROR';
|
|||||||
|
|
||||||
export class RecordPageViewUseCase implements UseCase<RecordPageViewInput, RecordPageViewOutput, RecordPageViewErrorCode> {
|
export class RecordPageViewUseCase implements UseCase<RecordPageViewInput, RecordPageViewOutput, RecordPageViewErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly pageViewRepository: IPageViewRepository,
|
private readonly pageViewRepository: PageViewRepository,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Pre-calculated metrics for sponsor dashboard and entity analytics.
|
* Pre-calculated metrics for sponsor dashboard and entity analytics.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Entity } from '@core/shared/domain/Entity';
|
import { Entity } from '@core/shared/domain/Entity';
|
||||||
import type {
|
import type {
|
||||||
AnalyticsMetrics,
|
AnalyticsMetrics,
|
||||||
AnalyticsSnapshotProps,
|
AnalyticsSnapshotProps,
|
||||||
@@ -15,8 +15,7 @@ import type {
|
|||||||
import { AnalyticsEntityId } from '../value-objects/AnalyticsEntityId';
|
import { AnalyticsEntityId } from '../value-objects/AnalyticsEntityId';
|
||||||
export type { SnapshotEntityType, SnapshotPeriod } from '../types/AnalyticsSnapshot';
|
export type { SnapshotEntityType, SnapshotPeriod } from '../types/AnalyticsSnapshot';
|
||||||
|
|
||||||
export class AnalyticsSnapshot implements Entity<string> {
|
export class AnalyticsSnapshot extends Entity<string> {
|
||||||
readonly id: string;
|
|
||||||
readonly entityType: SnapshotEntityType;
|
readonly entityType: SnapshotEntityType;
|
||||||
readonly period: SnapshotPeriod;
|
readonly period: SnapshotPeriod;
|
||||||
readonly startDate: Date;
|
readonly startDate: Date;
|
||||||
@@ -27,7 +26,7 @@ export class AnalyticsSnapshot implements Entity<string> {
|
|||||||
private readonly entityIdVo: AnalyticsEntityId;
|
private readonly entityIdVo: AnalyticsEntityId;
|
||||||
|
|
||||||
private constructor(props: AnalyticsSnapshotProps) {
|
private constructor(props: AnalyticsSnapshotProps) {
|
||||||
this.id = props.id;
|
super(props.id);
|
||||||
this.entityType = props.entityType;
|
this.entityType = props.entityType;
|
||||||
this.entityIdVo = AnalyticsEntityId.create(props.entityId);
|
this.entityIdVo = AnalyticsEntityId.create(props.entityId);
|
||||||
this.period = props.period;
|
this.period = props.period;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Tracks clicks, downloads, sign-ups, and other engagement actions.
|
* Tracks clicks, downloads, sign-ups, and other engagement actions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Entity } from '@core/shared/domain/Entity';
|
import { Entity } from '@core/shared/domain/Entity';
|
||||||
import type {
|
import type {
|
||||||
EngagementAction,
|
EngagementAction,
|
||||||
EngagementEntityType,
|
EngagementEntityType,
|
||||||
@@ -15,8 +15,7 @@ import { AnalyticsEntityId } from '../value-objects/AnalyticsEntityId';
|
|||||||
|
|
||||||
export type { EngagementAction, EngagementEntityType } from '../types/EngagementEvent';
|
export type { EngagementAction, EngagementEntityType } from '../types/EngagementEvent';
|
||||||
|
|
||||||
export class EngagementEvent implements Entity<string> {
|
export class EngagementEvent extends Entity<string> {
|
||||||
readonly id: string;
|
|
||||||
readonly action: EngagementAction;
|
readonly action: EngagementAction;
|
||||||
readonly entityType: EngagementEntityType;
|
readonly entityType: EngagementEntityType;
|
||||||
readonly actorId: string | undefined;
|
readonly actorId: string | undefined;
|
||||||
@@ -28,7 +27,8 @@ export class EngagementEvent implements Entity<string> {
|
|||||||
private readonly entityIdVo: AnalyticsEntityId;
|
private readonly entityIdVo: AnalyticsEntityId;
|
||||||
|
|
||||||
private constructor(props: EngagementEventProps) {
|
private constructor(props: EngagementEventProps) {
|
||||||
this.id = props.id;
|
super(props.id);
|
||||||
|
|
||||||
this.action = props.action;
|
this.action = props.action;
|
||||||
this.entityType = props.entityType;
|
this.entityType = props.entityType;
|
||||||
this.entityIdVo = AnalyticsEntityId.create(props.entityId);
|
this.entityIdVo = AnalyticsEntityId.create(props.entityId);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Captures visitor interactions with leagues, drivers, teams, races.
|
* Captures visitor interactions with leagues, drivers, teams, races.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Entity } from '@core/shared/domain/Entity';
|
import { Entity } from '@core/shared/domain/Entity';
|
||||||
import type { EntityType, PageViewProps, VisitorType } from '../types/PageView';
|
import type { EntityType, PageViewProps, VisitorType } from '../types/PageView';
|
||||||
import { AnalyticsEntityId } from '../value-objects/AnalyticsEntityId';
|
import { AnalyticsEntityId } from '../value-objects/AnalyticsEntityId';
|
||||||
import { AnalyticsSessionId } from '../value-objects/AnalyticsSessionId';
|
import { AnalyticsSessionId } from '../value-objects/AnalyticsSessionId';
|
||||||
@@ -13,7 +13,7 @@ import { PageViewId } from '../value-objects/PageViewId';
|
|||||||
|
|
||||||
export type { EntityType, VisitorType } from '../types/PageView';
|
export type { EntityType, VisitorType } from '../types/PageView';
|
||||||
|
|
||||||
export class PageView implements Entity<string> {
|
export class PageView extends Entity<string> {
|
||||||
readonly entityType: EntityType;
|
readonly entityType: EntityType;
|
||||||
readonly visitorId: string | undefined;
|
readonly visitorId: string | undefined;
|
||||||
readonly visitorType: VisitorType;
|
readonly visitorType: VisitorType;
|
||||||
@@ -28,6 +28,7 @@ export class PageView implements Entity<string> {
|
|||||||
private readonly sessionIdVo: AnalyticsSessionId;
|
private readonly sessionIdVo: AnalyticsSessionId;
|
||||||
|
|
||||||
private constructor(props: PageViewProps) {
|
private constructor(props: PageViewProps) {
|
||||||
|
super(props.id);
|
||||||
this.idVo = PageViewId.create(props.id);
|
this.idVo = PageViewId.create(props.id);
|
||||||
this.entityType = props.entityType;
|
this.entityType = props.entityType;
|
||||||
this.entityIdVo = AnalyticsEntityId.create(props.entityId);
|
this.entityIdVo = AnalyticsEntityId.create(props.entityId);
|
||||||
@@ -41,10 +42,6 @@ export class PageView implements Entity<string> {
|
|||||||
this.durationMs = props.durationMs;
|
this.durationMs = props.durationMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
get id(): string {
|
|
||||||
return this.idVo.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
get entityId(): string {
|
get entityId(): string {
|
||||||
return this.entityIdVo.value;
|
return this.entityIdVo.value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Repository Interface: IAnalyticsSnapshotRepository
|
* Repository Interface: AnalyticsSnapshotRepository
|
||||||
*
|
*
|
||||||
* Defines persistence operations for AnalyticsSnapshot entities.
|
* Defines persistence operations for AnalyticsSnapshot entities.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
|
|
||||||
export interface AnalyticsEntityIdProps {
|
export interface AnalyticsEntityIdProps {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -31,7 +31,7 @@ export class AnalyticsEntityId implements ValueObject<AnalyticsEntityIdProps> {
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<AnalyticsEntityIdProps>): boolean {
|
equals(other: ValueObject<AnalyticsEntityIdProps>): boolean {
|
||||||
return this.props.value === other.props.value;
|
return this.props.value === other.props.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
|
|
||||||
export interface AnalyticsSessionIdProps {
|
export interface AnalyticsSessionIdProps {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -30,7 +30,7 @@ export class AnalyticsSessionId implements ValueObject<AnalyticsSessionIdProps>
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<AnalyticsSessionIdProps>): boolean {
|
equals(other: ValueObject<AnalyticsSessionIdProps>): boolean {
|
||||||
return this.props.value === other.props.value;
|
return this.props.value === other.props.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
|
|
||||||
export interface PageViewIdProps {
|
export interface PageViewIdProps {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -30,7 +30,7 @@ export class PageViewId implements ValueObject<PageViewIdProps> {
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<PageViewIdProps>): boolean {
|
equals(other: ValueObject<PageViewIdProps>): boolean {
|
||||||
return this.props.value === other.props.value;
|
return this.props.value === other.props.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
* Follows clean architecture and TDD principles.
|
* Follows clean architecture and TDD principles.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
|
|
||||||
// Variant types for system-default references
|
// Variant types for system-default references
|
||||||
export type MediaVariant = 'avatar' | 'logo';
|
export type MediaVariant = 'avatar' | 'logo';
|
||||||
@@ -236,7 +236,7 @@ export class MediaReference implements ValueObject<MediaReferenceProps> {
|
|||||||
/**
|
/**
|
||||||
* Equality comparison
|
* Equality comparison
|
||||||
*/
|
*/
|
||||||
equals(other: IValueObject<MediaReferenceProps>): boolean {
|
equals(other: ValueObject<MediaReferenceProps>): boolean {
|
||||||
if (!(other instanceof MediaReference)) {
|
if (!(other instanceof MediaReference)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Port: IRaceResultsProvider
|
* Port: RaceResultsProvider
|
||||||
*
|
*
|
||||||
* Provider interface for race results data needed for rating calculations.
|
* Provider interface for race results data needed for rating calculations.
|
||||||
* This is an application layer port that bridges racing context to identity context.
|
* This is an application layer port that bridges racing context to identity context.
|
||||||
|
|||||||
@@ -13,15 +13,15 @@ import { UserRatingRepository } from '../../domain/repositories/UserRatingReposi
|
|||||||
import { ExternalGameRatingRepository } from '../../domain/repositories/ExternalGameRatingRepository';
|
import { ExternalGameRatingRepository } from '../../domain/repositories/ExternalGameRatingRepository';
|
||||||
|
|
||||||
describe('GetLeagueEligibilityPreviewQuery', () => {
|
describe('GetLeagueEligibilityPreviewQuery', () => {
|
||||||
let mockUserRatingRepo: IUserRatingRepository;
|
let mockUserRatingRepo: UserRatingRepository;
|
||||||
let mockExternalRatingRepo: IExternalGameRatingRepository;
|
let mockExternalRatingRepo: ExternalGameRatingRepository;
|
||||||
let handler: GetLeagueEligibilityPreviewQueryHandler;
|
let handler: GetLeagueEligibilityPreviewQueryHandler;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockUserRatingRepo = {
|
mockUserRatingRepo = {
|
||||||
findByUserId: vi.fn(),
|
findByUserId: vi.fn(),
|
||||||
save: vi.fn(),
|
save: vi.fn(),
|
||||||
} as unknown as IUserRatingRepository;
|
} as unknown as UserRatingRepository;
|
||||||
|
|
||||||
mockExternalRatingRepo = {
|
mockExternalRatingRepo = {
|
||||||
findByUserId: vi.fn(),
|
findByUserId: vi.fn(),
|
||||||
@@ -32,7 +32,7 @@ describe('GetLeagueEligibilityPreviewQuery', () => {
|
|||||||
delete: vi.fn(),
|
delete: vi.fn(),
|
||||||
exists: vi.fn(),
|
exists: vi.fn(),
|
||||||
findProfilesPaginated: vi.fn(),
|
findProfilesPaginated: vi.fn(),
|
||||||
} as unknown as IExternalGameRatingRepository;
|
} as unknown as ExternalGameRatingRepository;
|
||||||
|
|
||||||
handler = new GetLeagueEligibilityPreviewQueryHandler(
|
handler = new GetLeagueEligibilityPreviewQueryHandler(
|
||||||
mockUserRatingRepo,
|
mockUserRatingRepo,
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ export class GetLeagueEligibilityPreviewQueryHandler {
|
|||||||
private readonly evaluator: EligibilityEvaluator;
|
private readonly evaluator: EligibilityEvaluator;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userRatingRepo: IUserRatingRepository,
|
private readonly userRatingRepo: UserRatingRepository,
|
||||||
private readonly externalRatingRepo: IExternalGameRatingRepository
|
private readonly externalRatingRepo: ExternalGameRatingRepository
|
||||||
) {
|
) {
|
||||||
this.evaluator = new EligibilityEvaluator();
|
this.evaluator = new EligibilityEvaluator();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export interface GetUserRatingLedgerQuery {
|
|||||||
|
|
||||||
export class GetUserRatingLedgerQueryHandler {
|
export class GetUserRatingLedgerQueryHandler {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly ratingEventRepo: IRatingEventRepository
|
private readonly ratingEventRepo: RatingEventRepository
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(query: GetUserRatingLedgerQuery): Promise<PaginatedLedgerResult> {
|
async execute(query: GetUserRatingLedgerQuery): Promise<PaginatedLedgerResult> {
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ export interface GetUserRatingsSummaryQuery {
|
|||||||
|
|
||||||
export class GetUserRatingsSummaryQueryHandler {
|
export class GetUserRatingsSummaryQueryHandler {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userRatingRepo: IUserRatingRepository,
|
private readonly userRatingRepo: UserRatingRepository,
|
||||||
private readonly externalRatingRepo: IExternalGameRatingRepository,
|
private readonly externalRatingRepo: ExternalGameRatingRepository,
|
||||||
private readonly ratingEventRepo: IRatingEventRepository
|
private readonly ratingEventRepo: RatingEventRepository
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(query: GetUserRatingsSummaryQuery): Promise<RatingSummaryDto> {
|
async execute(query: GetUserRatingsSummaryQuery): Promise<RatingSummaryDto> {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class MockRatingEventRepository {
|
|||||||
return Array.from(this.events.values()).filter(e => e.userId === userId);
|
return Array.from(this.events.values()).filter(e => e.userId === userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async findEventsPaginated(userId: string, options?: import('@core/identity/domain/repositories/IRatingEventRepository').PaginatedQueryOptions): Promise<import('@core/identity/domain/repositories/IRatingEventRepository').PaginatedResult<RatingEvent>> {
|
async findEventsPaginated(userId: string, options?: import('@core/identity/domain/repositories/RatingEventRepository').PaginatedQueryOptions): Promise<import('@core/identity/domain/repositories/RatingEventRepository').PaginatedResult<RatingEvent>> {
|
||||||
const allEvents = await this.findByUserId(userId);
|
const allEvents = await this.findByUserId(userId);
|
||||||
|
|
||||||
// Apply filters
|
// Apply filters
|
||||||
@@ -105,7 +105,7 @@ class MockRatingEventRepository {
|
|||||||
const hasMore = offset + limit < total;
|
const hasMore = offset + limit < total;
|
||||||
const nextOffset = hasMore ? offset + limit : undefined;
|
const nextOffset = hasMore ? offset + limit : undefined;
|
||||||
|
|
||||||
const result: import('@core/identity/domain/repositories/IRatingEventRepository').PaginatedResult<RatingEvent> = {
|
const result: import('@core/identity/domain/repositories/RatingEventRepository').PaginatedResult<RatingEvent> = {
|
||||||
items,
|
items,
|
||||||
total,
|
total,
|
||||||
limit,
|
limit,
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { UserRating } from '../../domain/value-objects/UserRating';
|
|||||||
import { RatingEventId } from '../../domain/value-objects/RatingEventId';
|
import { RatingEventId } from '../../domain/value-objects/RatingEventId';
|
||||||
|
|
||||||
describe('AppendRatingEventsUseCase', () => {
|
describe('AppendRatingEventsUseCase', () => {
|
||||||
let mockEventRepo: Partial<IRatingEventRepository>;
|
let mockEventRepo: Partial<RatingEventRepository>;
|
||||||
let mockRatingRepo: Partial<IUserRatingRepository>;
|
let mockRatingRepo: Partial<UserRatingRepository>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockEventRepo = {
|
mockEventRepo = {
|
||||||
@@ -24,16 +24,16 @@ describe('AppendRatingEventsUseCase', () => {
|
|||||||
|
|
||||||
it('should be constructed with repositories', () => {
|
it('should be constructed with repositories', () => {
|
||||||
const useCase = new AppendRatingEventsUseCase(
|
const useCase = new AppendRatingEventsUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
expect(useCase).toBeInstanceOf(AppendRatingEventsUseCase);
|
expect(useCase).toBeInstanceOf(AppendRatingEventsUseCase);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle empty input (no events)', async () => {
|
it('should handle empty input (no events)', async () => {
|
||||||
const useCase = new AppendRatingEventsUseCase(
|
const useCase = new AppendRatingEventsUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const input: AppendRatingEventsInput = {
|
const input: AppendRatingEventsInput = {
|
||||||
@@ -50,8 +50,8 @@ describe('AppendRatingEventsUseCase', () => {
|
|||||||
|
|
||||||
it('should create and save events from direct input', async () => {
|
it('should create and save events from direct input', async () => {
|
||||||
const useCase = new AppendRatingEventsUseCase(
|
const useCase = new AppendRatingEventsUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const input: AppendRatingEventsInput = {
|
const input: AppendRatingEventsInput = {
|
||||||
@@ -79,8 +79,8 @@ describe('AppendRatingEventsUseCase', () => {
|
|||||||
|
|
||||||
it('should create events from race results using factory', async () => {
|
it('should create events from race results using factory', async () => {
|
||||||
const useCase = new AppendRatingEventsUseCase(
|
const useCase = new AppendRatingEventsUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const input: AppendRatingEventsInput = {
|
const input: AppendRatingEventsInput = {
|
||||||
@@ -108,8 +108,8 @@ describe('AppendRatingEventsUseCase', () => {
|
|||||||
|
|
||||||
it('should handle multiple race results', async () => {
|
it('should handle multiple race results', async () => {
|
||||||
const useCase = new AppendRatingEventsUseCase(
|
const useCase = new AppendRatingEventsUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const input: AppendRatingEventsInput = {
|
const input: AppendRatingEventsInput = {
|
||||||
@@ -129,8 +129,8 @@ describe('AppendRatingEventsUseCase', () => {
|
|||||||
|
|
||||||
it('should handle DNF status', async () => {
|
it('should handle DNF status', async () => {
|
||||||
const useCase = new AppendRatingEventsUseCase(
|
const useCase = new AppendRatingEventsUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const input: AppendRatingEventsInput = {
|
const input: AppendRatingEventsInput = {
|
||||||
@@ -159,8 +159,8 @@ describe('AppendRatingEventsUseCase', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const useCase = new AppendRatingEventsUseCase(
|
const useCase = new AppendRatingEventsUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const input: AppendRatingEventsInput = {
|
const input: AppendRatingEventsInput = {
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ export interface AppendRatingEventsOutput {
|
|||||||
*/
|
*/
|
||||||
export class AppendRatingEventsUseCase {
|
export class AppendRatingEventsUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly ratingEventRepository: IRatingEventRepository,
|
private readonly ratingEventRepository: RatingEventRepository,
|
||||||
private readonly userRatingRepository: IUserRatingRepository,
|
private readonly userRatingRepository: UserRatingRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(input: AppendRatingEventsInput): Promise<AppendRatingEventsOutput> {
|
async execute(input: AppendRatingEventsInput): Promise<AppendRatingEventsOutput> {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import { CastAdminVoteInput, CastAdminVoteOutput } from '../dtos/AdminVoteSessio
|
|||||||
*/
|
*/
|
||||||
export class CastAdminVoteUseCase {
|
export class CastAdminVoteUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly adminVoteSessionRepository: IAdminVoteSessionRepository,
|
private readonly adminVoteSessionRepository: AdminVoteSessionRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(input: CastAdminVoteInput): Promise<CastAdminVoteOutput> {
|
async execute(input: CastAdminVoteInput): Promise<CastAdminVoteOutput> {
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ import { CloseAdminVoteSessionInput, CloseAdminVoteSessionOutput } from '../dtos
|
|||||||
*/
|
*/
|
||||||
export class CloseAdminVoteSessionUseCase {
|
export class CloseAdminVoteSessionUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly adminVoteSessionRepository: IAdminVoteSessionRepository,
|
private readonly adminVoteSessionRepository: AdminVoteSessionRepository,
|
||||||
private readonly ratingEventRepository: IRatingEventRepository,
|
private readonly ratingEventRepository: RatingEventRepository,
|
||||||
private readonly userRatingRepository: IUserRatingRepository,
|
private readonly userRatingRepository: UserRatingRepository,
|
||||||
private readonly appendRatingEventsUseCase: any, // Will be typed properly in integration
|
private readonly appendRatingEventsUseCase: any, // Will be typed properly in integration
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ describe('ForgotPasswordUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new ForgotPasswordUseCase(
|
useCase = new ForgotPasswordUseCase(
|
||||||
authRepo as unknown as IAuthRepository,
|
authRepo as unknown as AuthRepository,
|
||||||
magicLinkRepo as unknown as IMagicLinkRepository,
|
magicLinkRepo as unknown as MagicLinkRepository,
|
||||||
notificationPort as unknown as IMagicLinkNotificationPort,
|
notificationPort as unknown as MagicLinkNotificationPort,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { MagicLinkRepository } from '../../domain/repositories/MagicLinkReposito
|
|||||||
import { MagicLinkNotificationPort } from '../../domain/ports/MagicLinkNotificationPort';
|
import { MagicLinkNotificationPort } from '../../domain/ports/MagicLinkNotificationPort';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
import { randomBytes } from 'crypto';
|
import { randomBytes } from 'crypto';
|
||||||
|
|
||||||
export type ForgotPasswordInput = {
|
export type ForgotPasswordInput = {
|
||||||
@@ -29,9 +30,9 @@ export type ForgotPasswordApplicationError = ApplicationErrorCode<ForgotPassword
|
|||||||
*/
|
*/
|
||||||
export class ForgotPasswordUseCase implements UseCase<ForgotPasswordInput, ForgotPasswordResult, ForgotPasswordErrorCode> {
|
export class ForgotPasswordUseCase implements UseCase<ForgotPasswordInput, ForgotPasswordResult, ForgotPasswordErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly authRepo: IAuthRepository,
|
private readonly authRepo: AuthRepository,
|
||||||
private readonly magicLinkRepo: IMagicLinkRepository,
|
private readonly magicLinkRepo: MagicLinkRepository,
|
||||||
private readonly notificationPort: IMagicLinkNotificationPort,
|
private readonly notificationPort: MagicLinkNotificationPort,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ describe('GetCurrentSessionUseCase', () => {
|
|||||||
error: vi.fn(),
|
error: vi.fn(),
|
||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
useCase = new GetCurrentSessionUseCase(
|
useCase = new GetCurrentSessionUseCase(
|
||||||
mockUserRepo as IUserRepository,
|
mockUserRepo as UserRepository,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export type GetCurrentSessionApplicationError = ApplicationErrorCode<
|
|||||||
*/
|
*/
|
||||||
export class GetCurrentSessionUseCase {
|
export class GetCurrentSessionUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userRepo: IUserRepository,
|
private readonly userRepo: UserRepository,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ describe('GetUserUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new GetUserUseCase(
|
useCase = new GetUserUseCase(
|
||||||
userRepo as unknown as IUserRepository,
|
userRepo as unknown as UserRepository,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { User } from '../../domain/entities/User';
|
|||||||
import { UserRepository } from '../../domain/repositories/UserRepository';
|
import { UserRepository } from '../../domain/repositories/UserRepository';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
|
|
||||||
export type GetUserInput = {
|
export type GetUserInput = {
|
||||||
userId: string;
|
userId: string;
|
||||||
@@ -21,7 +22,7 @@ export type GetUserApplicationError = ApplicationErrorCode<
|
|||||||
|
|
||||||
export class GetUserUseCase implements UseCase<GetUserInput, GetUserResult, GetUserErrorCode> {
|
export class GetUserUseCase implements UseCase<GetUserInput, GetUserResult, GetUserErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userRepo: IUserRepository,
|
private readonly userRepo: UserRepository,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ describe('LoginUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new LoginUseCase(
|
useCase = new LoginUseCase(
|
||||||
authRepo as unknown as IAuthRepository,
|
authRepo as unknown as AuthRepository,
|
||||||
passwordService as unknown as IPasswordHashingService,
|
passwordService as unknown as PasswordHashingService,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { AuthRepository } from '../../domain/repositories/AuthRepository';
|
|||||||
import { PasswordHashingService } from '../../domain/services/PasswordHashingService';
|
import { PasswordHashingService } from '../../domain/services/PasswordHashingService';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
|
|
||||||
export type LoginInput = {
|
export type LoginInput = {
|
||||||
email: string;
|
email: string;
|
||||||
@@ -26,8 +27,8 @@ export type LoginApplicationError = ApplicationErrorCode<LoginErrorCode, { messa
|
|||||||
*/
|
*/
|
||||||
export class LoginUseCase implements UseCase<LoginInput, LoginResult, LoginErrorCode> {
|
export class LoginUseCase implements UseCase<LoginInput, LoginResult, LoginErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly authRepo: IAuthRepository,
|
private readonly authRepo: AuthRepository,
|
||||||
private readonly passwordService: IPasswordHashingService,
|
private readonly passwordService: PasswordHashingService,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ describe('LoginWithEmailUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new LoginWithEmailUseCase(
|
useCase = new LoginWithEmailUseCase(
|
||||||
userRepository as unknown as IUserRepository,
|
userRepository as unknown as UserRepository,
|
||||||
sessionPort as unknown as IdentitySessionPort,
|
sessionPort as unknown as IdentitySessionPort,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export type LoginWithEmailApplicationError = ApplicationErrorCode<
|
|||||||
|
|
||||||
export class LoginWithEmailUseCase {
|
export class LoginWithEmailUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userRepository: IUserRepository,
|
private readonly userRepository: UserRepository,
|
||||||
private readonly sessionPort: IdentitySessionPort,
|
private readonly sessionPort: IdentitySessionPort,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { IdentitySessionPort } from '../ports/IdentitySessionPort';
|
import type { IdentitySessionPort } from '../ports/IdentitySessionPort';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
|
|
||||||
export type LogoutInput = {};
|
export type LogoutInput = {};
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { OpenAdminVoteSessionInput, OpenAdminVoteSessionOutput } from '../dtos/A
|
|||||||
*/
|
*/
|
||||||
export class OpenAdminVoteSessionUseCase {
|
export class OpenAdminVoteSessionUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly adminVoteSessionRepository: IAdminVoteSessionRepository,
|
private readonly adminVoteSessionRepository: AdminVoteSessionRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(input: OpenAdminVoteSessionInput): Promise<OpenAdminVoteSessionOutput> {
|
async execute(input: OpenAdminVoteSessionInput): Promise<OpenAdminVoteSessionOutput> {
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { RatingDimensionKey } from '../../domain/value-objects/RatingDimensionKe
|
|||||||
import { RatingDelta } from '../../domain/value-objects/RatingDelta';
|
import { RatingDelta } from '../../domain/value-objects/RatingDelta';
|
||||||
|
|
||||||
describe('RecomputeUserRatingSnapshotUseCase', () => {
|
describe('RecomputeUserRatingSnapshotUseCase', () => {
|
||||||
let mockEventRepo: Partial<IRatingEventRepository>;
|
let mockEventRepo: Partial<RatingEventRepository>;
|
||||||
let mockRatingRepo: Partial<IUserRatingRepository>;
|
let mockRatingRepo: Partial<UserRatingRepository>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockEventRepo = {
|
mockEventRepo = {
|
||||||
@@ -25,16 +25,16 @@ describe('RecomputeUserRatingSnapshotUseCase', () => {
|
|||||||
|
|
||||||
it('should be constructed with repositories', () => {
|
it('should be constructed with repositories', () => {
|
||||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
expect(useCase).toBeInstanceOf(RecomputeUserRatingSnapshotUseCase);
|
expect(useCase).toBeInstanceOf(RecomputeUserRatingSnapshotUseCase);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should compute snapshot from empty event list', async () => {
|
it('should compute snapshot from empty event list', async () => {
|
||||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = await useCase.execute({ userId: 'user-1' });
|
const result = await useCase.execute({ userId: 'user-1' });
|
||||||
@@ -64,8 +64,8 @@ describe('RecomputeUserRatingSnapshotUseCase', () => {
|
|||||||
mockEventRepo.getAllByUserId = vi.fn().mockResolvedValue(events);
|
mockEventRepo.getAllByUserId = vi.fn().mockResolvedValue(events);
|
||||||
|
|
||||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = await useCase.execute({ userId: 'user-1' });
|
const result = await useCase.execute({ userId: 'user-1' });
|
||||||
@@ -78,8 +78,8 @@ describe('RecomputeUserRatingSnapshotUseCase', () => {
|
|||||||
|
|
||||||
it('should return proper DTO format', async () => {
|
it('should return proper DTO format', async () => {
|
||||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = await useCase.execute({ userId: 'user-1' });
|
const result = await useCase.execute({ userId: 'user-1' });
|
||||||
@@ -117,8 +117,8 @@ describe('RecomputeUserRatingSnapshotUseCase', () => {
|
|||||||
mockRatingRepo.save = vi.fn().mockResolvedValue(updated);
|
mockRatingRepo.save = vi.fn().mockResolvedValue(updated);
|
||||||
|
|
||||||
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
const useCase = new RecomputeUserRatingSnapshotUseCase(
|
||||||
mockEventRepo as IRatingEventRepository,
|
mockEventRepo as RatingEventRepository,
|
||||||
mockRatingRepo as IUserRatingRepository,
|
mockRatingRepo as UserRatingRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = await useCase.execute({ userId: 'user-1' });
|
const result = await useCase.execute({ userId: 'user-1' });
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ export interface RecomputeUserRatingSnapshotOutput {
|
|||||||
*/
|
*/
|
||||||
export class RecomputeUserRatingSnapshotUseCase {
|
export class RecomputeUserRatingSnapshotUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly ratingEventRepository: IRatingEventRepository,
|
private readonly ratingEventRepository: RatingEventRepository,
|
||||||
private readonly userRatingRepository: IUserRatingRepository,
|
private readonly userRatingRepository: UserRatingRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(input: RecomputeUserRatingSnapshotInput): Promise<RecomputeUserRatingSnapshotOutput> {
|
async execute(input: RecomputeUserRatingSnapshotInput): Promise<RecomputeUserRatingSnapshotOutput> {
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import { RecordRaceRatingEventsInput, RecordRaceRatingEventsOutput } from '../dt
|
|||||||
*/
|
*/
|
||||||
export class RecordRaceRatingEventsUseCase {
|
export class RecordRaceRatingEventsUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly raceResultsProvider: IRaceResultsProvider,
|
private readonly raceResultsProvider: RaceResultsProvider,
|
||||||
private readonly ratingEventRepository: IRatingEventRepository,
|
private readonly ratingEventRepository: RatingEventRepository,
|
||||||
private readonly userRatingRepository: IUserRatingRepository,
|
private readonly userRatingRepository: UserRatingRepository,
|
||||||
private readonly appendRatingEventsUseCase: AppendRatingEventsUseCase,
|
private readonly appendRatingEventsUseCase: AppendRatingEventsUseCase,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ describe('ResetPasswordUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new ResetPasswordUseCase(
|
useCase = new ResetPasswordUseCase(
|
||||||
authRepo as unknown as IAuthRepository,
|
authRepo as unknown as AuthRepository,
|
||||||
magicLinkRepo as unknown as IMagicLinkRepository,
|
magicLinkRepo as unknown as MagicLinkRepository,
|
||||||
passwordService as unknown as IPasswordHashingService,
|
passwordService as unknown as PasswordHashingService,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import { EmailAddress } from '../../domain/value-objects/EmailAddress';
|
|||||||
import { PasswordHash } from '../../domain/value-objects/PasswordHash';
|
import { PasswordHash } from '../../domain/value-objects/PasswordHash';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
|
|
||||||
export type ResetPasswordInput = {
|
export type ResetPasswordInput = {
|
||||||
token: string;
|
token: string;
|
||||||
@@ -28,9 +29,9 @@ export type ResetPasswordApplicationError = ApplicationErrorCode<ResetPasswordEr
|
|||||||
*/
|
*/
|
||||||
export class ResetPasswordUseCase implements UseCase<ResetPasswordInput, ResetPasswordResult, ResetPasswordErrorCode> {
|
export class ResetPasswordUseCase implements UseCase<ResetPasswordInput, ResetPasswordResult, ResetPasswordErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly authRepo: IAuthRepository,
|
private readonly authRepo: AuthRepository,
|
||||||
private readonly magicLinkRepo: IMagicLinkRepository,
|
private readonly magicLinkRepo: MagicLinkRepository,
|
||||||
private readonly passwordService: IPasswordHashingService,
|
private readonly passwordService: PasswordHashingService,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ describe('SignupSponsorUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new SignupSponsorUseCase(
|
useCase = new SignupSponsorUseCase(
|
||||||
authRepo as unknown as IAuthRepository,
|
authRepo as unknown as AuthRepository,
|
||||||
companyRepo as unknown as ICompanyRepository,
|
companyRepo as unknown as CompanyRepository,
|
||||||
passwordService as unknown as IPasswordHashingService,
|
passwordService as unknown as PasswordHashingService,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import { CompanyRepository } from '../../domain/repositories/CompanyRepository';
|
|||||||
import { PasswordHashingService } from '../../domain/services/PasswordHashingService';
|
import { PasswordHashingService } from '../../domain/services/PasswordHashingService';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
|
|
||||||
export type SignupSponsorInput = {
|
export type SignupSponsorInput = {
|
||||||
email: string;
|
email: string;
|
||||||
@@ -33,9 +34,9 @@ export type SignupSponsorApplicationError = ApplicationErrorCode<SignupSponsorEr
|
|||||||
*/
|
*/
|
||||||
export class SignupSponsorUseCase implements UseCase<SignupSponsorInput, SignupSponsorResult, SignupSponsorErrorCode> {
|
export class SignupSponsorUseCase implements UseCase<SignupSponsorInput, SignupSponsorResult, SignupSponsorErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly authRepo: IAuthRepository,
|
private readonly authRepo: AuthRepository,
|
||||||
private readonly companyRepo: ICompanyRepository,
|
private readonly companyRepo: CompanyRepository,
|
||||||
private readonly passwordService: IPasswordHashingService,
|
private readonly passwordService: PasswordHashingService,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ describe('SignupUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new SignupUseCase(
|
useCase = new SignupUseCase(
|
||||||
authRepo as unknown as IAuthRepository,
|
authRepo as unknown as AuthRepository,
|
||||||
passwordService as unknown as IPasswordHashingService,
|
passwordService as unknown as PasswordHashingService,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ import { PasswordHashingService } from '../../domain/services/PasswordHashingSer
|
|||||||
import { PasswordHash } from '../../domain/value-objects/PasswordHash';
|
import { PasswordHash } from '../../domain/value-objects/PasswordHash';
|
||||||
import { Result } from '@core/shared/domain/Result';
|
import { Result } from '@core/shared/domain/Result';
|
||||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||||
import type { Logger, UseCase } from '@core/shared/application';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
|
import type { UseCase } from '@core/shared/application/UseCase';
|
||||||
|
|
||||||
export type SignupInput = {
|
export type SignupInput = {
|
||||||
email: string;
|
email: string;
|
||||||
@@ -29,8 +30,8 @@ export type SignupApplicationError = ApplicationErrorCode<SignupErrorCode, { mes
|
|||||||
*/
|
*/
|
||||||
export class SignupUseCase implements UseCase<SignupInput, SignupResult, SignupErrorCode> {
|
export class SignupUseCase implements UseCase<SignupInput, SignupResult, SignupErrorCode> {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly authRepo: IAuthRepository,
|
private readonly authRepo: AuthRepository,
|
||||||
private readonly passwordService: IPasswordHashingService,
|
private readonly passwordService: PasswordHashingService,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ describe('SignupWithEmailUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new SignupWithEmailUseCase(
|
useCase = new SignupWithEmailUseCase(
|
||||||
userRepository as unknown as IUserRepository,
|
userRepository as unknown as UserRepository,
|
||||||
sessionPort as unknown as IdentitySessionPort,
|
sessionPort as unknown as IdentitySessionPort,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export type SignupWithEmailApplicationError = ApplicationErrorCode<
|
|||||||
|
|
||||||
export class SignupWithEmailUseCase {
|
export class SignupWithEmailUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userRepository: IUserRepository,
|
private readonly userRepository: UserRepository,
|
||||||
private readonly sessionPort: IdentitySessionPort,
|
private readonly sessionPort: IdentitySessionPort,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|||||||
|
|
||||||
describe('UpsertExternalGameRatingUseCase', () => {
|
describe('UpsertExternalGameRatingUseCase', () => {
|
||||||
let useCase: UpsertExternalGameRatingUseCase;
|
let useCase: UpsertExternalGameRatingUseCase;
|
||||||
let mockRepository: IExternalGameRatingRepository;
|
let mockRepository: ExternalGameRatingRepository;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockRepository = {
|
mockRepository = {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { UpsertExternalGameRatingInput, UpsertExternalGameRatingOutput } from '.
|
|||||||
*/
|
*/
|
||||||
export class UpsertExternalGameRatingUseCase {
|
export class UpsertExternalGameRatingUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly externalGameRatingRepository: IExternalGameRatingRepository
|
private readonly externalGameRatingRepository: ExternalGameRatingRepository
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async execute(input: UpsertExternalGameRatingInput): Promise<UpsertExternalGameRatingOutput> {
|
async execute(input: UpsertExternalGameRatingInput): Promise<UpsertExternalGameRatingOutput> {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { Logger } from '@core/shared/domain/Logger';
|
import type { Logger } from '@core/shared/domain/Logger';
|
||||||
import { describe, expect, it, vi, type Mock } from 'vitest';
|
import { describe, expect, it, vi, type Mock } from 'vitest';
|
||||||
import { CreateAchievementUseCase, type IAchievementRepository } from './CreateAchievementUseCase';
|
import { CreateAchievementUseCase, type AchievementRepository } from './CreateAchievementUseCase';
|
||||||
|
|
||||||
describe('CreateAchievementUseCase', () => {
|
describe('CreateAchievementUseCase', () => {
|
||||||
let achievementRepository: {
|
let achievementRepository: {
|
||||||
@@ -24,7 +24,7 @@ describe('CreateAchievementUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new CreateAchievementUseCase(
|
useCase = new CreateAchievementUseCase(
|
||||||
achievementRepository as unknown as IAchievementRepository,
|
achievementRepository as unknown as AchievementRepository,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export type CreateAchievementApplicationError = ApplicationErrorCode<
|
|||||||
|
|
||||||
export class CreateAchievementUseCase {
|
export class CreateAchievementUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly achievementRepository: IAchievementRepository,
|
private readonly achievementRepository: AchievementRepository,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Achievements are categorized by role (driver, steward, admin) and type.
|
* Achievements are categorized by role (driver, steward, admin) and type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Entity } from '@core/shared/domain/Entity';
|
import { Entity } from '@core/shared/domain/Entity';
|
||||||
|
|
||||||
export type AchievementCategory = 'driver' | 'steward' | 'admin' | 'community';
|
export type AchievementCategory = 'driver' | 'steward' | 'admin' | 'community';
|
||||||
|
|
||||||
@@ -32,8 +32,7 @@ export interface AchievementRequirement {
|
|||||||
operator: '>=' | '>' | '=' | '<' | '<=';
|
operator: '>=' | '>' | '=' | '<' | '<=';
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Achievement implements Entity<string> {
|
export class Achievement extends Entity<string> {
|
||||||
readonly id: string;
|
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
readonly description: string;
|
readonly description: string;
|
||||||
readonly category: AchievementCategory;
|
readonly category: AchievementCategory;
|
||||||
@@ -45,7 +44,8 @@ export class Achievement implements Entity<string> {
|
|||||||
readonly createdAt: Date;
|
readonly createdAt: Date;
|
||||||
|
|
||||||
private constructor(props: AchievementProps) {
|
private constructor(props: AchievementProps) {
|
||||||
this.id = props.id;
|
super(props.id);
|
||||||
|
|
||||||
this.name = props.name;
|
this.name = props.name;
|
||||||
this.description = props.description;
|
this.description = props.description;
|
||||||
this.category = props.category;
|
this.category = props.category;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Entity, IEntity } from '@core/shared/domain/Entity';
|
import { Entity } from '@core/shared/domain/Entity';
|
||||||
import { IdentityDomainInvariantError, IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainInvariantError, IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
|
|
||||||
export interface AdminVote {
|
export interface AdminVote {
|
||||||
@@ -42,8 +42,7 @@ export interface AdminVoteSessionProps {
|
|||||||
*
|
*
|
||||||
* Based on ratings-architecture-concept.md sections 5.2.1 and 7.1.1
|
* Based on ratings-architecture-concept.md sections 5.2.1 and 7.1.1
|
||||||
*/
|
*/
|
||||||
export class AdminVoteSession implements Entity<string> {
|
export class AdminVoteSession extends Entity<string> {
|
||||||
readonly id: string;
|
|
||||||
readonly leagueId: string;
|
readonly leagueId: string;
|
||||||
readonly adminId: string;
|
readonly adminId: string;
|
||||||
readonly startDate: Date;
|
readonly startDate: Date;
|
||||||
@@ -56,7 +55,7 @@ export class AdminVoteSession implements Entity<string> {
|
|||||||
private _updatedAt: Date;
|
private _updatedAt: Date;
|
||||||
|
|
||||||
private constructor(props: AdminVoteSessionProps) {
|
private constructor(props: AdminVoteSessionProps) {
|
||||||
this.id = props.voteSessionId;
|
super(props.voteSessionId);
|
||||||
this.leagueId = props.leagueId;
|
this.leagueId = props.leagueId;
|
||||||
this.adminId = props.adminId;
|
this.adminId = props.adminId;
|
||||||
this.startDate = props.startDate;
|
this.startDate = props.startDate;
|
||||||
@@ -269,7 +268,7 @@ export class AdminVoteSession implements Entity<string> {
|
|||||||
return now >= this.startDate && now <= this.endDate && !this._closed;
|
return now >= this.startDate && now <= this.endDate && !this._closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IEntity<string>): boolean {
|
equals(other: Entity<string>): boolean {
|
||||||
return this.id === other.id;
|
return this.id === other.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Entity, IEntity } from '@core/shared/domain/Entity';
|
import { Entity } from '@core/shared/domain/Entity';
|
||||||
import { IdentityDomainInvariantError, IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainInvariantError, IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
import { RatingDelta } from '../value-objects/RatingDelta';
|
import { RatingDelta } from '../value-objects/RatingDelta';
|
||||||
import { RatingDimensionKey } from '../value-objects/RatingDimensionKey';
|
import { RatingDimensionKey } from '../value-objects/RatingDimensionKey';
|
||||||
@@ -34,8 +34,7 @@ export interface RatingEventProps {
|
|||||||
version: number;
|
version: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RatingEvent implements Entity<RatingEventId> {
|
export class RatingEvent extends Entity<RatingEventId> {
|
||||||
readonly id: RatingEventId;
|
|
||||||
readonly userId: string;
|
readonly userId: string;
|
||||||
readonly dimension: RatingDimensionKey;
|
readonly dimension: RatingDimensionKey;
|
||||||
readonly delta: RatingDelta;
|
readonly delta: RatingDelta;
|
||||||
@@ -48,7 +47,8 @@ export class RatingEvent implements Entity<RatingEventId> {
|
|||||||
readonly version: number;
|
readonly version: number;
|
||||||
|
|
||||||
private constructor(props: RatingEventProps) {
|
private constructor(props: RatingEventProps) {
|
||||||
this.id = props.id;
|
super(props.id);
|
||||||
|
|
||||||
this.userId = props.userId;
|
this.userId = props.userId;
|
||||||
this.dimension = props.dimension;
|
this.dimension = props.dimension;
|
||||||
this.delta = props.delta;
|
this.delta = props.delta;
|
||||||
@@ -118,7 +118,7 @@ export class RatingEvent implements Entity<RatingEventId> {
|
|||||||
return new RatingEvent(props);
|
return new RatingEvent(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IEntity<RatingEventId>): boolean {
|
equals(other: Entity<RatingEventId>): boolean {
|
||||||
return this.id.equals(other.id);
|
return this.id.equals(other.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
* Represents an achievement earned by a specific user.
|
* Represents an achievement earned by a specific user.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Entity } from '@core/shared/domain/Entity';
|
import { Entity } from '@core/shared/domain/Entity';
|
||||||
|
|
||||||
export interface UserAchievementProps {
|
export interface UserAchievementProps {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -15,8 +15,7 @@ export interface UserAchievementProps {
|
|||||||
progress?: number; // For partial progress tracking (0-100)
|
progress?: number; // For partial progress tracking (0-100)
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserAchievement implements Entity<string> {
|
export class UserAchievement extends Entity<string> {
|
||||||
readonly id: string;
|
|
||||||
readonly userId: string;
|
readonly userId: string;
|
||||||
readonly achievementId: string;
|
readonly achievementId: string;
|
||||||
readonly earnedAt: Date;
|
readonly earnedAt: Date;
|
||||||
@@ -24,7 +23,8 @@ export class UserAchievement implements Entity<string> {
|
|||||||
readonly progress: number;
|
readonly progress: number;
|
||||||
|
|
||||||
private constructor(props: UserAchievementProps) {
|
private constructor(props: UserAchievementProps) {
|
||||||
this.id = props.id;
|
super(props.id);
|
||||||
|
|
||||||
this.userId = props.userId;
|
this.userId = props.userId;
|
||||||
this.achievementId = props.achievementId;
|
this.achievementId = props.achievementId;
|
||||||
this.earnedAt = props.earnedAt;
|
this.earnedAt = props.earnedAt;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { DomainError, CommonDomainErrorKind } from '@core/shared/errors';
|
import type { DomainError } from '@core/shared/errors/DomainError';
|
||||||
|
import type { CommonDomainErrorKind } from '@core/shared/errors/DomainError';
|
||||||
|
|
||||||
export abstract class IdentityDomainError extends Error implements DomainError<CommonDomainErrorKind> {
|
export abstract class IdentityDomainError extends Error implements DomainError<CommonDomainErrorKind> {
|
||||||
readonly type = 'domain' as const;
|
readonly type = 'domain' as const;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Repository Interface: IAchievementRepository
|
* Repository Interface: AchievementRepository
|
||||||
*
|
*
|
||||||
* Defines operations for Achievement and UserAchievement entities
|
* Defines operations for Achievement and UserAchievement entities
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { AdminVoteSession } from '../entities/AdminVoteSession';
|
import type { AdminVoteSession } from '../entities/AdminVoteSession';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repository Interface: IAdminVoteSessionRepository
|
* Repository Interface: AdminVoteSessionRepository
|
||||||
*
|
*
|
||||||
* Port for persisting and retrieving admin vote sessions.
|
* Port for persisting and retrieving admin vote sessions.
|
||||||
* Sessions are scoped to leagues and control voting windows.
|
* Sessions are scoped to leagues and control voting windows.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { EmailAddress } from '../value-objects/EmailAddress';
|
|||||||
import { User } from '../entities/User';
|
import { User } from '../entities/User';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Domain Repository: IAuthRepository
|
* Domain Repository: AuthRepository
|
||||||
*
|
*
|
||||||
* Repository interface for authentication operations.
|
* Repository interface for authentication operations.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Company } from '../entities/Company';
|
import { Company } from '../entities/Company';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Domain Repository: ICompanyRepository
|
* Domain Repository: CompanyRepository
|
||||||
*
|
*
|
||||||
* Repository interface for Company entity operations.
|
* Repository interface for Company entity operations.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import { ExternalRating } from '../value-objects/ExternalRating';
|
|||||||
import { ExternalRatingProvenance } from '../value-objects/ExternalRatingProvenance';
|
import { ExternalRatingProvenance } from '../value-objects/ExternalRatingProvenance';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test suite for IExternalGameRatingRepository interface
|
* Test suite for ExternalGameRatingRepository interface
|
||||||
* This tests the contract that all implementations must satisfy
|
* This tests the contract that all implementations must satisfy
|
||||||
*/
|
*/
|
||||||
describe('IExternalGameRatingRepository', () => {
|
describe('ExternalGameRatingRepository', () => {
|
||||||
// Mock implementation for testing
|
// Mock implementation for testing
|
||||||
class MockExternalGameRatingRepository implements ExternalGameRatingRepository {
|
class MockExternalGameRatingRepository implements ExternalGameRatingRepository {
|
||||||
private profiles: Map<string, ExternalGameRatingProfile> = new Map();
|
private profiles: Map<string, ExternalGameRatingProfile> = new Map();
|
||||||
@@ -105,7 +105,7 @@ describe('IExternalGameRatingRepository', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let repository: IExternalGameRatingRepository;
|
let repository: ExternalGameRatingRepository;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
repository = new MockExternalGameRatingRepository();
|
repository = new MockExternalGameRatingRepository();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ExternalGameRatingProfile } from '../entities/ExternalGameRatingProfile';
|
import { ExternalGameRatingProfile } from '../entities/ExternalGameRatingProfile';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Repository Interface: IExternalGameRatingRepository
|
* Repository Interface: ExternalGameRatingRepository
|
||||||
*
|
*
|
||||||
* Port for persisting and retrieving external game rating profiles.
|
* Port for persisting and retrieving external game rating profiles.
|
||||||
* Store/display only, no compute.
|
* Store/display only, no compute.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Unit tests for IRatingEventRepository
|
* Unit tests for RatingEventRepository
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { RatingEvent } from '../entities/RatingEvent';
|
import { RatingEvent } from '../entities/RatingEvent';
|
||||||
@@ -110,7 +110,7 @@ class InMemoryRatingEventRepository implements RatingEventRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('IRatingEventRepository', () => {
|
describe('RatingEventRepository', () => {
|
||||||
let repository: InMemoryRatingEventRepository;
|
let repository: InMemoryRatingEventRepository;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Repository Interface: IRatingEventRepository
|
* Repository Interface: RatingEventRepository
|
||||||
*
|
*
|
||||||
* Port for persisting and retrieving rating events (ledger).
|
* Port for persisting and retrieving rating events (ledger).
|
||||||
* Events are immutable and ordered by occurredAt for deterministic snapshot computation.
|
* Events are immutable and ordered by occurredAt for deterministic snapshot computation.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Repository Interface: ISponsorAccountRepository
|
* Repository Interface: SponsorAccountRepository
|
||||||
*
|
*
|
||||||
* Defines persistence operations for SponsorAccount entities.
|
* Defines persistence operations for SponsorAccount entities.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Unit tests for IUserRatingRepository
|
* Unit tests for UserRatingRepository
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { UserRating } from '../value-objects/UserRating';
|
import { UserRating } from '../value-objects/UserRating';
|
||||||
@@ -19,7 +19,7 @@ class InMemoryUserRatingRepository implements UserRatingRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('IUserRatingRepository', () => {
|
describe('UserRatingRepository', () => {
|
||||||
let repository: InMemoryUserRatingRepository;
|
let repository: InMemoryUserRatingRepository;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Repository Interface: IUserRatingRepository
|
* Repository Interface: UserRatingRepository
|
||||||
*
|
*
|
||||||
* Port for persisting and retrieving UserRating snapshots.
|
* Port for persisting and retrieving UserRating snapshots.
|
||||||
* Snapshots are derived from rating events for fast reads.
|
* Snapshots are derived from rating events for fast reads.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Domain Repository: IUserRepository
|
* Domain Repository: UserRepository
|
||||||
*
|
*
|
||||||
* Repository interface for User entity operations.
|
* Repository interface for User entity operations.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { DomainService } from '@core/shared/domain';
|
import type { DomainService } from '@core/shared/domain/Service';
|
||||||
import type { UserRatingRepository } from '../repositories/UserRatingRepository';
|
import type { UserRatingRepository } from '../repositories/UserRatingRepository';
|
||||||
import type { RatingEventRepository } from '../repositories/RatingEventRepository';
|
import type { RatingEventRepository } from '../repositories/RatingEventRepository';
|
||||||
import { RatingEventFactory } from './RatingEventFactory';
|
import { RatingEventFactory } from './RatingEventFactory';
|
||||||
@@ -21,8 +21,8 @@ export class RatingUpdateService implements DomainService {
|
|||||||
readonly serviceName = 'RatingUpdateService';
|
readonly serviceName = 'RatingUpdateService';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly userRatingRepository: IUserRatingRepository,
|
private readonly userRatingRepository: UserRatingRepository,
|
||||||
private readonly ratingEventRepository: IRatingEventRepository
|
private readonly ratingEventRepository: RatingEventRepository
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,7 +68,7 @@ export class AdminTrustReasonCode implements ValueObject<AdminTrustReasonCodePro
|
|||||||
return { value: this.value };
|
return { value: this.value };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<AdminTrustReasonCodeProps>): boolean {
|
equals(other: ValueObject<AdminTrustReasonCodeProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,7 +80,7 @@ export class DrivingReasonCode implements ValueObject<DrivingReasonCodeProps> {
|
|||||||
return { value: this.value };
|
return { value: this.value };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<DrivingReasonCodeProps>): boolean {
|
equals(other: ValueObject<DrivingReasonCodeProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import type { EmailValidationResult } from '../types/EmailAddress';
|
import type { EmailValidationResult } from '../types/EmailAddress';
|
||||||
import { validateEmail, isDisposableEmail } from '../types/EmailAddress';
|
import { validateEmail, isDisposableEmail } from '../types/EmailAddress';
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ export class EmailAddress implements ValueObject<EmailAddressProps> {
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<EmailAddressProps>): boolean {
|
equals(other: ValueObject<EmailAddressProps>): boolean {
|
||||||
return this.props.value === other.props.value;
|
return this.props.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
import { GameKey } from './GameKey';
|
import { GameKey } from './GameKey';
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ export class ExternalRating implements ValueObject<ExternalRatingProps> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<ExternalRatingProps>): boolean {
|
equals(other: ValueObject<ExternalRatingProps>): boolean {
|
||||||
return (
|
return (
|
||||||
this.gameKey.equals(other.props.gameKey) &&
|
this.gameKey.equals(other.props.gameKey) &&
|
||||||
this.type === other.props.type &&
|
this.type === other.props.type &&
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
|
|
||||||
export interface ExternalRatingProvenanceProps {
|
export interface ExternalRatingProvenanceProps {
|
||||||
@@ -45,7 +45,7 @@ export class ExternalRatingProvenance implements ValueObject<ExternalRatingProve
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<ExternalRatingProvenanceProps>): boolean {
|
equals(other: ValueObject<ExternalRatingProvenanceProps>): boolean {
|
||||||
return (
|
return (
|
||||||
this.source === other.props.source &&
|
this.source === other.props.source &&
|
||||||
this.lastSyncedAt.getTime() === other.props.lastSyncedAt.getTime() &&
|
this.lastSyncedAt.getTime() === other.props.lastSyncedAt.getTime() &&
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
|
|
||||||
export interface GameKeyProps {
|
export interface GameKeyProps {
|
||||||
@@ -33,7 +33,7 @@ export class GameKey implements ValueObject<GameKeyProps> {
|
|||||||
return { value: this.value };
|
return { value: this.value };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<GameKeyProps>): boolean {
|
equals(other: ValueObject<GameKeyProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import bcrypt from 'bcrypt';
|
import bcrypt from 'bcrypt';
|
||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
|
|
||||||
export interface PasswordHashProps {
|
export interface PasswordHashProps {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -35,7 +35,7 @@ export class PasswordHash implements ValueObject<PasswordHashProps> {
|
|||||||
return bcrypt.compare(plain, this.props.value);
|
return bcrypt.compare(plain, this.props.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<PasswordHashProps>): boolean {
|
equals(other: ValueObject<PasswordHashProps>): boolean {
|
||||||
return this.props.value === other.props.value;
|
return this.props.value === other.props.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
|
|
||||||
export interface RatingDeltaProps {
|
export interface RatingDeltaProps {
|
||||||
@@ -30,7 +30,7 @@ export class RatingDelta implements ValueObject<RatingDeltaProps> {
|
|||||||
return { value: this.value };
|
return { value: this.value };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<RatingDeltaProps>): boolean {
|
equals(other: ValueObject<RatingDeltaProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
|
|
||||||
export interface RatingDimensionKeyProps {
|
export interface RatingDimensionKeyProps {
|
||||||
@@ -39,7 +39,7 @@ export class RatingDimensionKey implements ValueObject<RatingDimensionKeyProps>
|
|||||||
return { value: this.value };
|
return { value: this.value };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<RatingDimensionKeyProps>): boolean {
|
equals(other: ValueObject<RatingDimensionKeyProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ export class RatingEventId implements ValueObject<RatingEventIdProps> {
|
|||||||
return { value: this.value };
|
return { value: this.value };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<RatingEventIdProps>): boolean {
|
equals(other: ValueObject<RatingEventIdProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
|
|
||||||
export type RatingReferenceType = 'race' | 'penalty' | 'vote' | 'adminAction';
|
export type RatingReferenceType = 'race' | 'penalty' | 'vote' | 'adminAction';
|
||||||
@@ -38,7 +38,7 @@ export class RatingReference implements ValueObject<RatingReferenceProps> {
|
|||||||
return { type: this.type, id: this.id };
|
return { type: this.type, id: this.id };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<RatingReferenceProps>): boolean {
|
equals(other: ValueObject<RatingReferenceProps>): boolean {
|
||||||
return this.type === other.props.type && this.id === other.props.id;
|
return this.type === other.props.type && this.id === other.props.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
import { IdentityDomainValidationError } from '../errors/IdentityDomainError';
|
||||||
|
|
||||||
export interface RatingValueProps {
|
export interface RatingValueProps {
|
||||||
@@ -30,7 +30,7 @@ export class RatingValue implements ValueObject<RatingValueProps> {
|
|||||||
return { value: this.value };
|
return { value: this.value };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<RatingValueProps>): boolean {
|
equals(other: ValueObject<RatingValueProps>): boolean {
|
||||||
return this.value === other.props.value;
|
return this.value === other.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
|
|
||||||
export interface UserIdProps {
|
export interface UserIdProps {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -31,7 +31,7 @@ export class UserId implements ValueObject<UserIdProps> {
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public equals(other: IValueObject<UserIdProps>): boolean {
|
public equals(other: ValueObject<UserIdProps>): boolean {
|
||||||
return this.props.value === other.props.value;
|
return this.props.value === other.props.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { ValueObject } from '@core/shared/domain';
|
import type { ValueObject } from '@core/shared/domain/ValueObject';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value Object: UserRating
|
* Value Object: UserRating
|
||||||
@@ -111,7 +111,7 @@ export class UserRating implements ValueObject<UserRatingProps> {
|
|||||||
return new UserRating(props);
|
return new UserRating(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: IValueObject<UserRatingProps>): boolean {
|
equals(other: ValueObject<UserRatingProps>): boolean {
|
||||||
return this.props.userId === other.props.userId;
|
return this.props.userId === other.props.userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ describe('DeleteMediaUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new DeleteMediaUseCase(
|
useCase = new DeleteMediaUseCase(
|
||||||
mediaRepo as unknown as IMediaRepository,
|
mediaRepo as unknown as MediaRepository,
|
||||||
mediaStorage as unknown as MediaStoragePort,
|
mediaStorage as unknown as MediaStoragePort,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export type DeleteMediaApplicationError = ApplicationErrorCode<
|
|||||||
|
|
||||||
export class DeleteMediaUseCase {
|
export class DeleteMediaUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly mediaRepo: IMediaRepository,
|
private readonly mediaRepo: MediaRepository,
|
||||||
private readonly mediaStorage: MediaStoragePort,
|
private readonly mediaStorage: MediaStoragePort,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ describe('GetAvatarUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new GetAvatarUseCase(
|
useCase = new GetAvatarUseCase(
|
||||||
avatarRepo as unknown as IAvatarRepository,
|
avatarRepo as unknown as AvatarRepository,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export type GetAvatarApplicationError = ApplicationErrorCode<
|
|||||||
|
|
||||||
export class GetAvatarUseCase {
|
export class GetAvatarUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly avatarRepo: IAvatarRepository,
|
private readonly avatarRepo: AvatarRepository,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ describe('GetMediaUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new GetMediaUseCase(
|
useCase = new GetMediaUseCase(
|
||||||
mediaRepo as unknown as IMediaRepository,
|
mediaRepo as unknown as MediaRepository,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export type GetMediaErrorCode = 'MEDIA_NOT_FOUND' | 'REPOSITORY_ERROR';
|
|||||||
|
|
||||||
export class GetMediaUseCase {
|
export class GetMediaUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly mediaRepo: IMediaRepository,
|
private readonly mediaRepo: MediaRepository,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ describe('RequestAvatarGenerationUseCase', () => {
|
|||||||
} as unknown as Logger;
|
} as unknown as Logger;
|
||||||
|
|
||||||
useCase = new RequestAvatarGenerationUseCase(
|
useCase = new RequestAvatarGenerationUseCase(
|
||||||
avatarRepo as unknown as IAvatarGenerationRepository,
|
avatarRepo as unknown as AvatarGenerationRepository,
|
||||||
faceValidation as unknown as FaceValidationPort,
|
faceValidation as unknown as FaceValidationPort,
|
||||||
avatarGeneration as unknown as AvatarGenerationPort,
|
avatarGeneration as unknown as AvatarGenerationPort,
|
||||||
logger,
|
logger,
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export type RequestAvatarGenerationApplicationError = ApplicationErrorCode<
|
|||||||
|
|
||||||
export class RequestAvatarGenerationUseCase {
|
export class RequestAvatarGenerationUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly avatarRepo: IAvatarGenerationRepository,
|
private readonly avatarRepo: AvatarGenerationRepository,
|
||||||
private readonly faceValidation: FaceValidationPort,
|
private readonly faceValidation: FaceValidationPort,
|
||||||
private readonly avatarGeneration: AvatarGenerationPort,
|
private readonly avatarGeneration: AvatarGenerationPort,
|
||||||
private readonly logger: Logger,
|
private readonly logger: Logger,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user