/** * Serial Number Validation Utilities (Backend) * * WellNuo device serial numbers follow formats: * - Production: WELLNUO-XXXX-XXXX (16 chars with hyphens) * - Demo: DEMO-00000 or DEMO-1234-5678 * - Legacy: 8+ alphanumeric characters */ const { SERIAL } = require('../config/constants'); // Demo serial numbers const DEMO_SERIALS = new Set([ 'DEMO-00000', 'DEMO-1234-5678', ]); /** * Validates a serial number and returns detailed result * @param {string|null|undefined} serial - Serial number to validate * @returns {{isValid: boolean, format: string, normalized: string, error?: string}} */ function validateSerial(serial) { // Handle empty input if (!serial || typeof serial !== 'string') { return { isValid: false, format: 'invalid', normalized: '', error: 'Serial number is required', }; } // Normalize: trim and uppercase const normalized = serial.trim().toUpperCase(); if (normalized.length === 0) { return { isValid: false, format: 'invalid', normalized: '', error: 'Serial number is required', }; } // Check for demo serial if (DEMO_SERIALS.has(normalized)) { return { isValid: true, format: 'demo', normalized, }; } // Production format: WELLNUO-XXXX-XXXX // Must be exactly 16 characters with hyphens at positions 7 and 12 if (SERIAL.PRODUCTION_PATTERN.test(normalized)) { return { isValid: true, format: 'production', normalized, }; } // Legacy format: minimum 8 alphanumeric characters (no special characters except hyphens) if (SERIAL.LEGACY_PATTERN.test(normalized)) { return { isValid: true, format: 'legacy', normalized, }; } // Invalid format let error = 'Invalid serial number format'; if (normalized.length < SERIAL.MIN_LENGTH) { error = `Serial number must be at least ${SERIAL.MIN_LENGTH} characters`; } else if (!SERIAL.VALID_CHARS_PATTERN.test(normalized)) { error = 'Serial number can only contain letters, numbers, and hyphens'; } return { isValid: false, format: 'invalid', normalized, error, }; } /** * Quick validation - returns true/false only * @param {string|null|undefined} serial - Serial number to validate * @returns {boolean} */ function isValidSerial(serial) { return validateSerial(serial).isValid; } /** * Check if serial is a demo serial * @param {string|null|undefined} serial - Serial number to check * @returns {boolean} */ function isDemoSerial(serial) { if (!serial) return false; const normalized = serial.trim().toUpperCase(); return DEMO_SERIALS.has(normalized); } /** * Get user-friendly error message for invalid serial * @param {string|null|undefined} serial - Serial number to validate * @returns {string} */ function getSerialErrorMessage(serial) { const result = validateSerial(serial); if (result.isValid) { return ''; } if (result.error) { return result.error; } return 'Invalid serial number format'; } module.exports = { validateSerial, isValidSerial, isDemoSerial, getSerialErrorMessage, };