UNPKG

n4s

Version:

typed schema validation version of enforce

67 lines (59 loc) 1.89 kB
import { greaterThan } from 'vest-utils'; import { RuleInstance } from '../../utils/RuleInstance'; import { RuleRunReturn } from '../../utils/RuleRunReturn'; const REQUIRED_COUNT = 1; /** * Validates that a value passes exactly one of the provided rules. * Exactly one rule must pass - not zero, not two or more. * All rules are evaluated to count passing rules. * * @template T - The value type to validate * @param value - The value to validate * @param rules - One or more RuleInstances where exactly one must pass * @returns RuleRunReturn indicating success or failure * * @example * ```typescript * // Eager API * enforce(5) * .oneOf( * enforce.lessThan(10), * enforce.greaterThan(100) * ); // passes (only first rule passes) * * // Lazy API - accept either type but not both * const stringOrNumberRule = enforce.oneOf( * enforce.isString(), * enforce.isNumber() * ); * * stringOrNumberRule.test('hello'); // true * stringOrNumberRule.test(42); // true * stringOrNumberRule.test(true); // false (no rules pass) * * // More complex example - exclusive validation * const exclusiveRule = enforce.oneOf( * enforce.equals(null), * enforce.isString().longerThan(0) * ); * * exclusiveRule.test(null); // true (exactly one passes) * exclusiveRule.test('hello'); // true (exactly one passes) * exclusiveRule.test(''); // false (neither passes) * ``` */ export function oneOf<T>(value: T, ...rules: any[]): RuleRunReturn<T> { let passingCount = 0; rules.some(rule => { const res = rule.run(value); if (res.pass) { passingCount++; } if (greaterThan(passingCount, REQUIRED_COUNT)) { return RuleRunReturn.Failing(value); } }); return RuleRunReturn.create(passingCount === REQUIRED_COUNT, value); } // Type for oneOf rule instance export type OneOfRuleInstance<T> = RuleInstance<T, [T]>;