All files / src/utils validators.ts

78.78% Statements 26/33
87.5% Branches 14/16
84.61% Functions 11/13
82.75% Lines 24/29

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 1472x                   2x 5x 5x 2x   3x 3x                 2x         5x 5x             6x 6x 3x   3x               5x                 6x               2x 5x                     2x 8x 4x             2x                                                                               2x                     2x              
import { z } from 'zod';
 
/**
 * Validation result type
 */
export type ValidationResult = true | string;
 
/**
 * Validate input using a Zod schema
 */
export function validateWithSchema<T>(schema: z.ZodSchema<T>, data: unknown): ValidationResult {
  try {
    schema.parse(data);
    return true;
  } catch (error) {
    if (error instanceof z.ZodError) {
      return error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');
    }
    return String(error);
  }
}
 
/**
 * Common validation functions
 */
export const validators = {
  /**
   * Validate email format
   */
  email: (value: string): ValidationResult => {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(value) || 'Invalid email format';
  },
 
  /**
   * Validate URL format
   */
  url: (value: string): ValidationResult => {
    try {
      new URL(value);
      return true;
    } catch {
      return 'Invalid URL format';
    }
  },
 
  /**
   * Validate non-empty string
   */
  nonEmptyString: (value: string): ValidationResult => {
    return (
      (typeof value === 'string' && value.trim().length > 0) || 'Value must be a non-empty string'
    );
  },
 
  /**
   * Validate positive number
   */
  positiveNumber: (value: number): ValidationResult => {
    return (typeof value === 'number' && value > 0) || 'Value must be a positive number';
  },
 
  /**
   * Validate array with minimum length
   */
  minArrayLength:
    (minLength: number) =>
    (value: unknown[]): ValidationResult => {
      return (
        (Array.isArray(value) && value.length >= minLength) ||
        `Array must have at least ${minLength} items`
      );
    },
 
  /**
   * Validate object has required properties
   */
  hasProperties:
    (properties: string[]) =>
    (value: Record<string, unknown>): ValidationResult => {
      const missing = properties.filter(prop => !(prop in value));
      return missing.length === 0 || `Missing required properties: ${missing.join(', ')}`;
    },
};
 
/**
 * Common Zod schemas
 */
export const schemas = {
  /**
   * URL schema
   */
  url: z.string().url(),
 
  /**
   * Email schema
   */
  email: z.string().email(),
 
  /**
   * Non-empty string schema
   */
  nonEmptyString: z.string().min(1),
 
  /**
   * Positive number schema
   */
  positiveNumber: z.number().positive(),
 
  /**
   * Port number schema
   */
  port: z.number().int().min(1).max(65535),
 
  /**
   * Timeout schema (in milliseconds)
   */
  timeout: z.number().int().min(1000).max(300000),
 
  /**
   * Retry count schema
   */
  retryCount: z.number().int().min(0).max(10),
};
 
/**
 * Validate input function (for backward compatibility)
 */
export function validateInput(
  input: unknown,
  validator?: (input: unknown) => ValidationResult
): ValidationResult {
  Iif (!validator) return true;
  return validator(input);
}
 
/**
 * Validate output function (for backward compatibility)
 */
export function validateOutput(
  output: unknown,
  validator?: (output: unknown) => ValidationResult
): ValidationResult {
  Iif (!validator) return true;
  return validator(output);
}