import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsIn, IsOptional } from 'class-validator'; export const availabilityValues = [ 'available', 'initial-loading', 'temporarily-unavailable', 'connection-unavailable', ] as const; export const completenessValues = ['complete', 'incomplete'] as const; export const freshnessValues = ['unknown', 'fresh', 'stale'] as const; export const attemptStateValues = [ 'none', 'running', 'succeeded', 'partial', 'failed', ] as const; export class InvestmentReadQueryDto { @ApiPropertyOptional({ enum: ['observe'] }) @IsOptional() @IsIn(['observe']) declare sync?: 'observe'; } export class InvestmentAttemptProblemDto { @ApiProperty({ enum: ['membership', 'portfolio', 'operations', 'events'] }) declare section: 'events' | 'membership' | 'operations' | 'portfolio'; @ApiProperty({ type: String, nullable: true }) declare accountId: null | string; @ApiProperty({ type: String, nullable: true }) declare errorCode: null | string; } export class InvestmentAttemptDto { @ApiProperty({ enum: attemptStateValues }) declare state: (typeof attemptStateValues)[number]; @ApiProperty({ type: String, nullable: true, format: 'date-time' }) declare startedAt: null | string; @ApiProperty({ type: String, nullable: true, format: 'date-time' }) declare finishedAt: null | string; @ApiProperty({ type: InvestmentAttemptProblemDto, isArray: true }) declare problems: InvestmentAttemptProblemDto[]; } export class InvestmentRangeDto { @ApiPropertyOptional() accountId?: string; @ApiProperty({ format: 'date-time' }) declare from: string; @ApiProperty({ format: 'date-time' }) declare to: string; } export class InvestmentCoverageDto { @ApiProperty({ type: InvestmentRangeDto, isArray: true }) declare requested: InvestmentRangeDto[]; @ApiProperty({ type: InvestmentRangeDto, isArray: true }) declare completeRanges: InvestmentRangeDto[]; @ApiProperty({ type: InvestmentRangeDto, isArray: true }) declare missingRanges: InvestmentRangeDto[]; @ApiProperty({ type: String, nullable: true, format: 'date-time' }) declare asOf: null | string; @ApiProperty({ enum: ['known', 'unknown'] }) declare historyBoundary: 'known' | 'unknown'; @ApiProperty({ enum: ['missing', 'loading', 'partial', 'complete', 'failed'], }) declare historyState: 'complete' | 'failed' | 'loading' | 'missing' | 'partial'; } export class InvestmentDependencyDto { @ApiProperty() declare dataRevision: string; @ApiPropertyOptional({ type: String }) unavailableReason?: string; @ApiPropertyOptional({ type: () => InvestmentCoverageDto }) coverage?: InvestmentCoverageDto; @ApiProperty() declare resourceKey: string; @ApiProperty({ enum: availabilityValues }) declare availability: (typeof availabilityValues)[number]; @ApiProperty({ enum: completenessValues }) declare completeness: (typeof completenessValues)[number]; @ApiProperty({ enum: freshnessValues }) declare freshness: (typeof freshnessValues)[number]; @ApiProperty({ type: String, format: 'date-time', nullable: true }) declare lastSuccessfulAt: null | string; @ApiProperty({ type: InvestmentAttemptDto }) declare lastAttempt: InvestmentAttemptDto; // Internal resource-source work remains available to existing source owners. // It is deliberately undecorated and therefore not part of the HTTP schema. declare sync: { errorCode: null | string; id: null | string; state: 'failed' | 'idle' | 'running' }; } export class InvestmentResourceMetaDto extends InvestmentDependencyDto { @ApiPropertyOptional({ type: InvestmentDependencyDto, isArray: true }) declare dependencies?: InvestmentDependencyDto[]; }