A social knowledge tool for researchers built on ATProto
at development 4.0 kB view raw
1export type GuardResponse = string; // This remains the type for the error message 2 3import { Result, ok, err } from './Result'; // Import ok and err factories 4 5export interface IGuardArgument { 6 argument: any; 7 argumentName: string; 8} 9 10export type GuardArgumentCollection = IGuardArgument[]; 11 12// Define the specific Result type used by Guard functions 13// Success holds `void` (or `undefined`), Error holds the message string 14type GuardResult = Result<void, GuardResponse>; 15 16export class Guard { 17 // Combine function now expects GuardResult[] and returns GuardResult 18 public static combine(guardResults: GuardResult[]): GuardResult { 19 for (const result of guardResults) { 20 // Use the isErr type guard 21 if (result.isErr()) { 22 // Return the first error encountered 23 return result; // No need to cast, it's already Err<void, GuardResponse> 24 } 25 } 26 // If all results are Ok, return a single Ok 27 return ok(undefined); // Success case carries no value 28 } 29 30 public static greaterThan( 31 minValue: number, 32 actualValue: number, 33 ): GuardResult { 34 return actualValue > minValue 35 ? ok(undefined) // Use ok factory 36 : err(`Number given {${actualValue}} is not greater than {${minValue}}`); // Use err factory 37 } 38 39 public static againstAtLeast(numChars: number, text: string): GuardResult { 40 return text.length >= numChars 41 ? ok(undefined) // Use ok factory 42 : err(`Text is not at least ${numChars} chars.`); // Use err factory 43 } 44 45 public static againstAtMost(numChars: number, text: string): GuardResult { 46 return text.length <= numChars 47 ? ok(undefined) // Use ok factory 48 : err(`Text is greater than ${numChars} chars.`); // Use err factory 49 } 50 51 public static againstNullOrUndefined( 52 argument: any, 53 argumentName: string, 54 ): GuardResult { 55 if (argument === null || argument === undefined) { 56 return err(`${argumentName} is null or undefined`); // Use err factory 57 } else { 58 return ok(undefined); // Use ok factory 59 } 60 } 61 62 public static againstNullOrUndefinedBulk( 63 args: GuardArgumentCollection, 64 ): GuardResult { 65 for (const arg of args) { 66 const result = this.againstNullOrUndefined( 67 arg.argument, 68 arg.argumentName, 69 ); 70 // Use the isErr type guard 71 if (result.isErr()) { 72 return result; // Return the Err result directly 73 } 74 } 75 // If loop completes, all arguments were valid 76 return ok(undefined); // Use ok factory 77 } 78 79 public static isOneOf( 80 value: any, 81 validValues: any[], 82 argumentName: string, 83 ): GuardResult { 84 let isValid = false; 85 for (const validValue of validValues) { 86 if (value === validValue) { 87 isValid = true; 88 } 89 } 90 91 if (isValid) { 92 return ok(undefined); // Use ok factory 93 } else { 94 // Use err factory 95 return err( 96 `${argumentName} isn't oneOf the correct types in ${JSON.stringify( 97 validValues, 98 )}. Got "${value}".`, 99 ); 100 } 101 } 102 103 public static inRange( 104 num: number, 105 min: number, 106 max: number, 107 argumentName: string, 108 ): GuardResult { 109 const isInRange = num >= min && num <= max; 110 if (!isInRange) { 111 // Use err factory 112 return err(`${argumentName} is not within range ${min} to ${max}.`); 113 } else { 114 return ok(undefined); // Use ok factory 115 } 116 } 117 118 public static allInRange( 119 numbers: number[], 120 min: number, 121 max: number, 122 argumentName: string, 123 ): GuardResult { 124 for (const num of numbers) { 125 const numIsInRangeResult = this.inRange(num, min, max, argumentName); 126 // Use isErr type guard 127 if (numIsInRangeResult.isErr()) { 128 // Return the specific error from inRange 129 return err( 130 `${argumentName} is not within the range. Failed value: ${num}`, 131 ); // Or return numIsInRangeResult directly 132 } 133 } 134 // If loop completes, all numbers are in range 135 return ok(undefined); // Use ok factory 136 } 137}