UNPKG

fortify-schema

Version:

TypeScript interface-like schema validation system that's easier to use than Zod

149 lines (129 loc) 3.87 kB
import { BaseSchema } from "./BaseSchema"; import { SchemaValidationResult, NumberSchemaOptions } from "../../../types/types"; /** * Number schema with comprehensive validation options */ export class NumberSchema extends BaseSchema<number> { private _min?: number; private _max?: number; private _integer = false; private _positive = false; private _precision?: number; /** * Set minimum value */ min(value: number): this { const cloned = this.clone(); cloned._min = value; return cloned; } /** * Set maximum value */ max(value: number): this { const cloned = this.clone(); cloned._max = value; return cloned; } /** * Require integer values only */ int(): this { const cloned = this.clone(); cloned._integer = true; return cloned; } /** * Require positive values only */ positive(): this { const cloned = this.clone(); cloned._positive = true; return cloned; } /** * Set maximum decimal precision */ precision(digits: number): this { const cloned = this.clone(); cloned._precision = digits; return cloned; } /** * Validate number value */ validate(value: any): SchemaValidationResult<number> { // Handle common validation (undefined/null) const commonResult = this.handleCommonValidation(value); if (commonResult) { return commonResult; } const result: SchemaValidationResult<number> = { success: true, errors: [], warnings: [], data: undefined, }; // Type check and conversion let num: number; if (typeof value === "string") { num = parseFloat(value); if (value.trim() !== "" && !isNaN(num)) { result.warnings.push("String converted to number"); } } else { num = value; } if (typeof num !== "number" || isNaN(num) || !isFinite(num)) { result.success = false; result.errors.push("Expected number"); return result; } result.data = num; // Integer validation if (this._integer && num % 1 !== 0) { result.success = false; result.errors.push("Expected integer"); } // Range validation if (this._min !== undefined && num < this._min) { result.success = false; result.errors.push(`Number must be at least ${this._min}`); } if (this._max !== undefined && num > this._max) { result.success = false; result.errors.push(`Number must be at most ${this._max}`); } // Positive validation if (this._positive && num <= 0) { result.success = false; result.errors.push("Number must be positive"); } // Precision validation if (this._precision !== undefined) { const decimalPlaces = (num.toString().split(".")[1] || "").length; if (decimalPlaces > this._precision) { result.success = false; result.errors.push( `Number must have at most ${this._precision} decimal places` ); } } return result; } /** * Get schema configuration */ getConfig(): NumberSchemaOptions { return { min: this._min, max: this._max, integer: this._integer, positive: this._positive, precision: this._precision, optional: this._optional, nullable: this._nullable, default: this._default, }; } }