Patterns
Paquete: @tiendana/utils
Colección de expresiones regulares (regex) listas para usar para validación de patrones comunes como emails, contraseñas, dominios y más.
Características
✅ Regex probados y validados
✅ Listos para usar sin configuración
✅ Cubren casos comunes de validación
✅ Sin dependencias externas
Patrones Disponibles
EMAIL
Validación completa de formato de email según RFC 5322.
import { Patterns } from '@tiendana/utils';
Patterns.EMAIL.test('usuario@ejemplo.com'); // true
Patterns.EMAIL.test('user.name+tag@example.co'); // true
Patterns.EMAIL.test('invalido@'); // false
Patterns.EMAIL.test('sin-arroba.com'); // false
Formato:
/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+...@...)+$/
PASSWORD
Contraseña fuerte: mínimo 6 caracteres con al menos una mayúscula, una minúscula y un número.
Patterns.PASSWORD.test('Abc123'); // true
Patterns.PASSWORD.test('Password1'); // true
Patterns.PASSWORD.test('abc123'); // false - falta mayúscula
Patterns.PASSWORD.test('ABC123'); // false - falta minúscula
Patterns.PASSWORD.test('Abcdef'); // false - falta número
Patterns.PASSWORD.test('Abc12'); // false - muy corta
Formato: /^((?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])).{6,}$/
Requisitos:
- ✅ Mínimo 6 caracteres
- ✅ Al menos 1 número
- ✅ Al menos 1 letra minúscula
- ✅ Al menos 1 letra mayúscula
DOMAIN
Validación de nombre de dominio válido (sin protocolo).
Patterns.DOMAIN.test('ejemplo.com'); // true
Patterns.DOMAIN.test('sub.ejemplo.com'); // true
Patterns.DOMAIN.test('mi-sitio.co'); // true
Patterns.DOMAIN.test('invalido'); // false
Patterns.DOMAIN.test('.com'); // false
Patterns.DOMAIN.test('https://ejemplo.com'); // false - no incluir protocolo
Formato: /^([a-zA-Z0-9\_\-\.]{2,63})\.([a-zA-Z0-9]{2,})$/
NUMBER
Extrae números (enteros o decimales, positivos o negativos) de un string.
'El precio es $1,234.56'.match(Patterns.NUMBER);
// ['1', '234.56'] (la coma separa números)
'Temperatura: -15.5°C'.match(Patterns.NUMBER);
// ['-15.5']
'Sin números aquí'.match(Patterns.NUMBER);
// null
Formato: /[-]{0,1}[0-9]*[.]{0,1}[0-9]+/g
Nota: Usa flag g (global) para encontrar todos los números. Con g, RegExp.prototype.test conserva lastIndex entre llamadas; prefiere match o matchAll, o reinicia lastIndex = 0.
IMAGE
Verifica si un MIME type corresponde a una imagen.
Patterns.IMAGE.test('image/png'); // true
Patterns.IMAGE.test('image/jpeg'); // true
Patterns.IMAGE.test('image/svg+xml'); // true
Patterns.IMAGE.test('application/pdf'); // false
Patterns.IMAGE.test('text/html'); // false
Formato: /^image\/([a-zA-Z].*)$/
CC
Patrón orientado a números de cédula colombiana (8, 10 u 11 dígitos, o formato 6-5).
'12345678'.match(Patterns.CC); // ['12345678', '']
'123456-12345'.match(Patterns.CC); // ['123456-12345', '']
Formato: /((\d{8})|(\d{10})|(\d{11})|(\d{6}-\d{5}))?/g
Todo el patrón es opcional (?) y global (g), así que coincide con cualquier texto, incluido el string vacío: Patterns.CC.test('abc') es true y 'abc'.match(Patterns.CC) devuelve cadenas vacías, no null. Para validar una cédula usa una expresión anclada propia (por ejemplo /^(\d{8}|\d{10}|\d{11}|\d{6}-\d{5})$/).
Ejemplos de Uso
Validación de Formulario
import { Patterns } from '@tiendana/utils';
function validateRegistration(data: RegistrationForm) {
const errors: string[] = [];
if (!Patterns.EMAIL.test(data.email)) {
errors.push('Email no válido');
}
if (!Patterns.PASSWORD.test(data.password)) {
errors.push('Contraseña debe tener min 6 caracteres, mayúscula, minúscula y número');
}
if (data.website && !Patterns.DOMAIN.test(data.website)) {
errors.push('Dominio de sitio web no válido');
}
return errors.length > 0 ? errors : null;
}
Verificación de Archivo de Imagen
function isImageFile(file: File): boolean {
return Patterns.IMAGE.test(file.type);
}
// Uso en input de archivo
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (!isImageFile(file)) {
alert('Por favor selecciona una imagen válida');
return;
}
// Procesar imagen...
});
Extracción de Números
function extractNumbers(text: string): number[] {
const matches = text.match(Patterns.NUMBER);
return matches ? matches.map(Number) : [];
}
extractNumbers('Pedido #123: $45.99 - Descuento: 10%');
// [123, 45.99, 10]
Validación de Email en Input
function validateEmailInput(input: HTMLInputElement) {
const isValid = Patterns.EMAIL.test(input.value);
input.classList.toggle('invalid', !isValid);
input.classList.toggle('valid', isValid);
return isValid;
}
Validación de Contraseña con Feedback
function validatePasswordStrength(password: string) {
if (password.length < 6) {
return { valid: false, message: 'Mínimo 6 caracteres' };
}
if (!/[0-9]/.test(password)) {
return { valid: false, message: 'Debe incluir al menos un número' };
}
if (!/[a-z]/.test(password)) {
return { valid: false, message: 'Debe incluir al menos una minúscula' };
}
if (!/[A-Z]/.test(password)) {
return { valid: false, message: 'Debe incluir al menos una mayúscula' };
}
return { valid: true, message: 'Contraseña fuerte' };
}
Definición del Objeto
export const Patterns = {
PASSWORD: /^((?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])).{6,}$/,
DOMAIN: /^([a-zA-Z0-9\_\-\.]{2,63})\.([a-zA-Z0-9]{2,})$/,
EMAIL: /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/,
IMAGE: /^image\/([a-zA-Z].*)$/,
NUMBER: /[-]{0,1}[0-9]*[.]{0,1}[0-9]+/g,
CC: /((\d{8})|(\d{10})|(\d{11})|(\d{6}-\d{5}))?/g,
}
Casos de Uso Comunes
- Validación de formularios: Verificar formato de inputs antes de enviar
- Sanitización de datos: Filtrar contenido válido de APIs externas
- Restricción de archivos: Verificar tipos de archivo en uploads
- Extracción de datos: Parsear números de strings
- Validación en tiempo real: Feedback instantáneo en inputs
Notas Técnicas
- Case sensitivity: EMAIL no tiene la bandera
iy rechaza mayúsculas ('Juan@Example.com'no coincide); DOMAIN sí acepta mayúsculas - Performance: Regex compilados una sola vez, muy eficiente para múltiples validaciones
- Unicode: EMAIL no valida caracteres unicode (IDN), solo ASCII
- Flags: NUMBER y CC usan flag
g(global) para encontrar todas las coincidencias - Browser support: Compatible con todos los navegadores modernos (ES5+)
Ver También
- hasValue - Para verificar valores no vacíos