validog
Version:
Comprehensive dog breed validation, search, and recommendation library with support for 100+ breeds, fuzzy matching, and advanced filtering by size, temperament, origin, and compatibility
220 lines (196 loc) • 6.78 kB
JavaScript
/**
* Validation library for validog
* Centralized validation functions and error handling
*/
const NonEmptyStringError = require('./errors.js');
/**
* Unit aliases mapping for weight conversions.
*/
const UNIT_ALIASES = {
kgs: new Set(['kg', 'kgs', 'kilogram', 'kilograms', 'kilo', 'kilos']),
lbs: new Set(['lb', 'lbs', 'pound', 'pounds'])
};
/**
* Valid compatibility keys
*/
const VALID_COMPATIBILITY_KEYS = ['children', 'otherDogs', 'cats'];
/**
* Validate that a value is a non-empty string.
* @param {*} value - Value to validate.
* @param {string} fieldName - Field name for error message.
* @throws {NonEmptyStringError} If value is not a non-empty string.
*/
const validateNonEmptyString = (value, fieldName) => {
if (typeof value !== 'string' || value.trim() === '') {
throw new NonEmptyStringError(fieldName);
}
};
/**
* Validate that a value is a string.
* @param {*} value - Value to validate.
* @param {string} fieldName - Field name for error message.
* @throws {TypeError} If value is not a string.
*/
const validateString = (value, fieldName) => {
if (typeof value !== 'string') {
throw new TypeError(`${fieldName} must be a string`);
}
};
/**
* Validate that a value is a number.
* @param {*} value - Value to validate.
* @param {string} fieldName - Field name for error message.
* @throws {TypeError} If value is not a number.
*/
const validateNumber = (value, fieldName) => {
if (typeof value !== 'number') {
throw new TypeError(`${fieldName} must be a number`);
}
};
/**
* Validate that a value is a boolean.
* @param {*} value - Value to validate.
* @param {string} fieldName - Field name for error message.
* @throws {TypeError} If value is not a boolean.
*/
const validateBoolean = (value, fieldName) => {
if (typeof value !== 'boolean') {
throw new TypeError(`${fieldName} must be a boolean`);
}
};
/**
* Validate that a value is an object (not null, not array).
* @param {*} value - Value to validate.
* @param {string} fieldName - Field name for error message.
* @throws {TypeError} If value is not an object.
*/
const validateObject = (value, fieldName) => {
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
throw new TypeError(`${fieldName} must be an object`);
}
};
/**
* Validate that a value is an array.
* @param {*} value - Value to validate.
* @param {string} fieldName - Field name for error message.
* @throws {TypeError} If value is not an array.
*/
const validateArray = (value, fieldName) => {
if (!Array.isArray(value)) {
throw new TypeError(`${fieldName} must be an array`);
}
};
/**
* Validate that a value is a positive number.
* @param {*} value - Value to validate.
* @param {string} fieldName - Field name for error message.
* @throws {TypeError} If value is not a positive number.
*/
const validatePositiveNumber = (value, fieldName) => {
validateNumber(value, fieldName);
if (value <= 0) {
throw new TypeError(`${fieldName} must be a positive number`);
}
};
/**
* Validate that a value is a non-negative number.
* @param {*} value - Value to validate.
* @param {string} fieldName - Field name for error message.
* @throws {TypeError} If value is not a non-negative number.
*/
const validateNonNegativeNumber = (value, fieldName) => {
validateNumber(value, fieldName);
if (value < 0) {
throw new TypeError(`${fieldName} must be a non-negative number`);
}
};
/**
* Validate and normalize a weight unit.
* @param {string} [unit='lbs'] - Unit to validate and normalize.
* @returns {string} - Normalized unit ('kgs' or 'lbs').
* @throws {TypeError} If unit is not valid.
*/
const validateUnit = (unit = 'lbs') => {
validateString(unit, 'Unit');
const normalized = unit.toLowerCase().trim();
if (UNIT_ALIASES.kgs.has(normalized)) return 'kgs';
if (UNIT_ALIASES.lbs.has(normalized)) return 'lbs';
throw new TypeError('Unit must be "lbs"/"lb"/"pounds"/"pound" or "kgs"/"kg"/"kilograms"/"kilos"');
};
/**
* Validate that a value is one of allowed options.
* @param {*} value - Value to validate.
* @param {Array} allowedValues - Array of allowed values.
* @param {string} fieldName - Field name for error message.
* @throws {TypeError} If value is not in allowed values.
*/
const validateOneOf = (value, allowedValues, fieldName) => {
validateArray(allowedValues, 'allowedValues');
if (!allowedValues.includes(value)) {
throw new TypeError(`${fieldName} must be one of: ${allowedValues.join(', ')}`);
}
};
/**
* Validate that a value is a valid compatibility key.
* @param {*} value - Value to validate.
* @throws {TypeError} If value is not a valid compatibility key.
*/
const validateCompatibilityKey = (value) => {
if (!VALID_COMPATIBILITY_KEYS.includes(value)) {
throw new TypeError(`Compatibility key must be one of: ${VALID_COMPATIBILITY_KEYS.join(', ')}`);
}
};
/**
* Validate two numbers for weight range (min/max).
* @param {*} min - Minimum value.
* @param {*} max - Maximum value.
* @throws {TypeError} If either value is not a number.
*/
const validateNumberRange = (min, max) => {
validateNumber(min, 'Min weight');
validateNumber(max, 'Max weight');
};
/**
* Validate that a preferences object is valid.
* @param {*} preferences - Object to validate.
* @throws {TypeError} If not a valid preferences object.
*/
const validatePreferences = (preferences) => {
if (typeof preferences !== 'object' || preferences === null || Array.isArray(preferences)) {
throw new TypeError('Preferences must be an object');
}
};
/**
* Validate data structure (array of breeds).
* @param {*} data - Data to validate.
* @throws {Error} If data is not an array.
*/
const validateBreedData = (data) => {
if (!Array.isArray(data)) {
throw new Error('Breed data must be an array');
}
};
module.exports = {
// Constants
UNIT_ALIASES,
VALID_COMPATIBILITY_KEYS,
// String validations
validateNonEmptyString,
validateString,
// Number validations
validateNumber,
validatePositiveNumber,
validateNonNegativeNumber,
// Boolean validations
validateBoolean,
// Object/Array validations
validateObject,
validateArray,
// Domain-specific validations
validateUnit,
validateOneOf,
validateCompatibilityKey,
validateNumberRange,
validatePreferences,
validateBreedData
};