Suite of AT Protocol TypeScript libraries built on web standards
21
fork

Configure Feed

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

at main 77 lines 2.1 kB view raw
1import { failureError, type ResultFailure } from "../core/result.ts"; 2import { arrayAgg } from "../util/array-agg.ts"; 3import { 4 type Issue, 5 IssueInvalidType, 6 IssueInvalidValue, 7} from "./validation-issue.ts"; 8 9export class ValidationError extends Error { 10 override name = "ValidationError"; 11 12 readonly issues: Issue[]; 13 14 constructor(issues: Issue[], options?: ErrorOptions) { 15 const issuesAgg = aggregateIssues(issues); 16 super(issuesAgg.join(", "), options); 17 this.issues = issuesAgg; 18 } 19 20 static fromFailures( 21 failures: ResultFailure<ValidationError>[], 22 ): ValidationError { 23 if (failures.length === 1) return failures[0].error; 24 const issues = failures.flatMap(extractFailureIssues); 25 return new ValidationError(issues, { 26 cause: failures.map(failureError), 27 }); 28 } 29} 30 31function extractFailureIssues(result: ResultFailure<ValidationError>) { 32 return result.error.issues; 33} 34 35function aggregateIssues(issues: Issue[]): Issue[] { 36 if (issues.length <= 1) return issues; 37 if (issues.length === 2 && issues[0].code !== issues[1].code) return issues; 38 39 return [ 40 ...arrayAgg( 41 issues.filter((issue) => issue instanceof IssueInvalidType), 42 (a, b) => comparePropertyPaths(a.path, b.path), 43 (issues) => 44 new IssueInvalidType( 45 issues[0].path, 46 issues[0].input, 47 Array.from(new Set(issues.flatMap((iss) => iss.expected))), 48 ), 49 ), 50 ...arrayAgg( 51 issues.filter((issue) => issue instanceof IssueInvalidValue), 52 (a, b) => comparePropertyPaths(a.path, b.path), 53 (issues) => 54 new IssueInvalidValue( 55 issues[0].path, 56 issues[0].input, 57 Array.from(new Set(issues.flatMap((iss) => iss.values))), 58 ), 59 ), 60 ...issues.filter( 61 (issue) => 62 !(issue instanceof IssueInvalidType) && 63 !(issue instanceof IssueInvalidValue), 64 ), 65 ]; 66} 67 68function comparePropertyPaths( 69 a: readonly PropertyKey[], 70 b: readonly PropertyKey[], 71) { 72 if (a.length !== b.length) return false; 73 for (let i = 0; i < a.length; i++) { 74 if (a[i] !== b[i]) return false; 75 } 76 return true; 77}