hvp-shared 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -0
- package/dist/constants/mexican-states.d.ts +43 -0
- package/dist/constants/mexican-states.js +46 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +33 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +23 -0
- package/dist/types/api-response.types.d.ts +322 -0
- package/dist/types/api-response.types.js +65 -0
- package/dist/types/company-settings.types.d.ts +51 -0
- package/dist/types/company-settings.types.js +2 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +28 -0
- package/dist/validation/__tests__/address.validation.test.d.ts +1 -0
- package/dist/validation/__tests__/address.validation.test.js +143 -0
- package/dist/validation/__tests__/email.validation.test.d.ts +1 -0
- package/dist/validation/__tests__/email.validation.test.js +102 -0
- package/dist/validation/__tests__/phone.validation.test.d.ts +1 -0
- package/dist/validation/__tests__/phone.validation.test.js +75 -0
- package/dist/validation/__tests__/rfc.validation.test.d.ts +1 -0
- package/dist/validation/__tests__/rfc.validation.test.js +97 -0
- package/dist/validation/address.validation.d.ts +27 -0
- package/dist/validation/address.validation.js +51 -0
- package/dist/validation/email.validation.d.ts +20 -0
- package/dist/validation/email.validation.js +37 -0
- package/dist/validation/index.d.ts +8 -0
- package/dist/validation/index.js +24 -0
- package/dist/validation/phone.validation.d.ts +14 -0
- package/dist/validation/phone.validation.js +33 -0
- package/dist/validation/rfc.validation.d.ts +27 -0
- package/dist/validation/rfc.validation.js +41 -0
- package/package.json +30 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const address_validation_1 = require("../address.validation");
|
|
4
|
+
describe('validateAddress', () => {
|
|
5
|
+
const validAddress = {
|
|
6
|
+
street: 'Calle 10',
|
|
7
|
+
exteriorNumber: '123',
|
|
8
|
+
interiorNumber: 'A',
|
|
9
|
+
neighborhood: 'Centro',
|
|
10
|
+
city: 'Mérida',
|
|
11
|
+
state: 'YUC',
|
|
12
|
+
postalCode: '97000',
|
|
13
|
+
country: 'México'
|
|
14
|
+
};
|
|
15
|
+
describe('valid addresses', () => {
|
|
16
|
+
it('should accept valid complete address', () => {
|
|
17
|
+
const result = (0, address_validation_1.validateAddress)(validAddress);
|
|
18
|
+
expect(result.isValid).toBe(true);
|
|
19
|
+
expect(result.error).toBeUndefined();
|
|
20
|
+
});
|
|
21
|
+
it('should accept address without interior number', () => {
|
|
22
|
+
const { interiorNumber, ...addressWithoutInterior } = validAddress;
|
|
23
|
+
const result = (0, address_validation_1.validateAddress)(addressWithoutInterior);
|
|
24
|
+
expect(result.isValid).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
it('should accept country "Mexico" without accent', () => {
|
|
27
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, country: 'Mexico' });
|
|
28
|
+
expect(result.isValid).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
it('should accept country in uppercase', () => {
|
|
31
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, country: 'MÉXICO' });
|
|
32
|
+
expect(result.isValid).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
it('should accept address with whitespace (trimmed)', () => {
|
|
35
|
+
const result = (0, address_validation_1.validateAddress)({
|
|
36
|
+
...validAddress,
|
|
37
|
+
street: ' Calle 10 ',
|
|
38
|
+
city: ' Mérida '
|
|
39
|
+
});
|
|
40
|
+
expect(result.isValid).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe('required fields', () => {
|
|
44
|
+
it('should reject missing street', () => {
|
|
45
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, street: '' });
|
|
46
|
+
expect(result.isValid).toBe(false);
|
|
47
|
+
expect(result.error).toBe('Calle es requerida');
|
|
48
|
+
});
|
|
49
|
+
it('should reject missing exterior number', () => {
|
|
50
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, exteriorNumber: '' });
|
|
51
|
+
expect(result.isValid).toBe(false);
|
|
52
|
+
expect(result.error).toBe('Número exterior es requerido');
|
|
53
|
+
});
|
|
54
|
+
it('should reject missing neighborhood', () => {
|
|
55
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, neighborhood: '' });
|
|
56
|
+
expect(result.isValid).toBe(false);
|
|
57
|
+
expect(result.error).toBe('Colonia es requerida');
|
|
58
|
+
});
|
|
59
|
+
it('should reject missing city', () => {
|
|
60
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, city: '' });
|
|
61
|
+
expect(result.isValid).toBe(false);
|
|
62
|
+
expect(result.error).toBe('Ciudad es requerida');
|
|
63
|
+
});
|
|
64
|
+
it('should reject missing postal code', () => {
|
|
65
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, postalCode: '' });
|
|
66
|
+
expect(result.isValid).toBe(false);
|
|
67
|
+
expect(result.error).toBe('Código postal es requerido');
|
|
68
|
+
});
|
|
69
|
+
it('should reject missing state', () => {
|
|
70
|
+
const { state, ...addressWithoutState } = validAddress;
|
|
71
|
+
const result = (0, address_validation_1.validateAddress)(addressWithoutState);
|
|
72
|
+
expect(result.isValid).toBe(false);
|
|
73
|
+
expect(result.error).toBe('Estado es requerido');
|
|
74
|
+
});
|
|
75
|
+
it('should reject missing country', () => {
|
|
76
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, country: '' });
|
|
77
|
+
expect(result.isValid).toBe(false);
|
|
78
|
+
expect(result.error).toBe('País es requerido');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe('postal code validation', () => {
|
|
82
|
+
it('should reject postal code with less than 5 digits', () => {
|
|
83
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, postalCode: '9700' });
|
|
84
|
+
expect(result.isValid).toBe(false);
|
|
85
|
+
expect(result.error).toContain('5 dígitos');
|
|
86
|
+
});
|
|
87
|
+
it('should reject postal code with more than 5 digits', () => {
|
|
88
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, postalCode: '970001' });
|
|
89
|
+
expect(result.isValid).toBe(false);
|
|
90
|
+
expect(result.error).toContain('5 dígitos');
|
|
91
|
+
});
|
|
92
|
+
it('should reject postal code with letters', () => {
|
|
93
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, postalCode: '9700A' });
|
|
94
|
+
expect(result.isValid).toBe(false);
|
|
95
|
+
expect(result.error).toContain('5 dígitos');
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
describe('state code validation', () => {
|
|
99
|
+
it('should accept all valid Mexican state codes', () => {
|
|
100
|
+
const validStates = [
|
|
101
|
+
'AGS', 'BC', 'BCS', 'CAMP', 'CHIS', 'CHIH', 'COAH', 'COL', 'CDMX',
|
|
102
|
+
'DGO', 'GTO', 'GRO', 'HGO', 'JAL', 'MEX', 'MICH', 'MOR', 'NAY',
|
|
103
|
+
'NL', 'OAX', 'PUE', 'QRO', 'QROO', 'SLP', 'SIN', 'SON', 'TAB',
|
|
104
|
+
'TAMPS', 'TLAX', 'VER', 'YUC', 'ZAC'
|
|
105
|
+
];
|
|
106
|
+
validStates.forEach(state => {
|
|
107
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, state: state });
|
|
108
|
+
expect(result.isValid).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
it('should reject invalid state code', () => {
|
|
112
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, state: 'INVALID' });
|
|
113
|
+
expect(result.isValid).toBe(false);
|
|
114
|
+
expect(result.error).toBe('Código de estado inválido');
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
describe('country validation', () => {
|
|
118
|
+
it('should reject non-Mexican country', () => {
|
|
119
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, country: 'USA' });
|
|
120
|
+
expect(result.isValid).toBe(false);
|
|
121
|
+
expect(result.error).toContain('México');
|
|
122
|
+
});
|
|
123
|
+
it('should reject other countries', () => {
|
|
124
|
+
const result = (0, address_validation_1.validateAddress)({ ...validAddress, country: 'Canada' });
|
|
125
|
+
expect(result.isValid).toBe(false);
|
|
126
|
+
expect(result.error).toContain('México');
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe('POSTAL_CODE_PATTERN', () => {
|
|
131
|
+
it('should match valid 5-digit postal code', () => {
|
|
132
|
+
expect(address_validation_1.POSTAL_CODE_PATTERN.test('97000')).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
it('should match postal code starting with 0', () => {
|
|
135
|
+
expect(address_validation_1.POSTAL_CODE_PATTERN.test('01000')).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
it('should not match 4-digit code', () => {
|
|
138
|
+
expect(address_validation_1.POSTAL_CODE_PATTERN.test('9700')).toBe(false);
|
|
139
|
+
});
|
|
140
|
+
it('should not match 6-digit code', () => {
|
|
141
|
+
expect(address_validation_1.POSTAL_CODE_PATTERN.test('970001')).toBe(false);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const email_validation_1 = require("../email.validation");
|
|
4
|
+
describe('validateEmail', () => {
|
|
5
|
+
describe('valid emails', () => {
|
|
6
|
+
it('should accept valid email', () => {
|
|
7
|
+
const result = (0, email_validation_1.validateEmail)('test@example.com');
|
|
8
|
+
expect(result.isValid).toBe(true);
|
|
9
|
+
expect(result.error).toBeUndefined();
|
|
10
|
+
});
|
|
11
|
+
it('should accept email with subdomain', () => {
|
|
12
|
+
const result = (0, email_validation_1.validateEmail)('test@mail.example.com');
|
|
13
|
+
expect(result.isValid).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
it('should accept email with numbers', () => {
|
|
16
|
+
const result = (0, email_validation_1.validateEmail)('test123@example.com');
|
|
17
|
+
expect(result.isValid).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
it('should accept email with dots in local part', () => {
|
|
20
|
+
const result = (0, email_validation_1.validateEmail)('test.user@example.com');
|
|
21
|
+
expect(result.isValid).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
it('should accept email with plus sign', () => {
|
|
24
|
+
const result = (0, email_validation_1.validateEmail)('test+tag@example.com');
|
|
25
|
+
expect(result.isValid).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
it('should accept uppercase email (normalized)', () => {
|
|
28
|
+
const result = (0, email_validation_1.validateEmail)('TEST@EXAMPLE.COM');
|
|
29
|
+
expect(result.isValid).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
it('should accept email with whitespace (trimmed)', () => {
|
|
32
|
+
const result = (0, email_validation_1.validateEmail)(' test@example.com ');
|
|
33
|
+
expect(result.isValid).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe('invalid emails', () => {
|
|
37
|
+
it('should reject empty string', () => {
|
|
38
|
+
const result = (0, email_validation_1.validateEmail)('');
|
|
39
|
+
expect(result.isValid).toBe(false);
|
|
40
|
+
expect(result.error).toBe('Email es requerido');
|
|
41
|
+
});
|
|
42
|
+
it('should reject null', () => {
|
|
43
|
+
const result = (0, email_validation_1.validateEmail)(null);
|
|
44
|
+
expect(result.isValid).toBe(false);
|
|
45
|
+
expect(result.error).toBe('Email es requerido');
|
|
46
|
+
});
|
|
47
|
+
it('should reject undefined', () => {
|
|
48
|
+
const result = (0, email_validation_1.validateEmail)(undefined);
|
|
49
|
+
expect(result.isValid).toBe(false);
|
|
50
|
+
expect(result.error).toBe('Email es requerido');
|
|
51
|
+
});
|
|
52
|
+
it('should reject whitespace only', () => {
|
|
53
|
+
const result = (0, email_validation_1.validateEmail)(' ');
|
|
54
|
+
expect(result.isValid).toBe(false);
|
|
55
|
+
expect(result.error).toBe('Email es requerido');
|
|
56
|
+
});
|
|
57
|
+
it('should reject email without @', () => {
|
|
58
|
+
const result = (0, email_validation_1.validateEmail)('testexample.com');
|
|
59
|
+
expect(result.isValid).toBe(false);
|
|
60
|
+
expect(result.error).toBe('Email inválido');
|
|
61
|
+
});
|
|
62
|
+
it('should reject email without domain', () => {
|
|
63
|
+
const result = (0, email_validation_1.validateEmail)('test@');
|
|
64
|
+
expect(result.isValid).toBe(false);
|
|
65
|
+
expect(result.error).toBe('Email inválido');
|
|
66
|
+
});
|
|
67
|
+
it('should reject email without local part', () => {
|
|
68
|
+
const result = (0, email_validation_1.validateEmail)('@example.com');
|
|
69
|
+
expect(result.isValid).toBe(false);
|
|
70
|
+
expect(result.error).toBe('Email inválido');
|
|
71
|
+
});
|
|
72
|
+
it('should reject email without TLD', () => {
|
|
73
|
+
const result = (0, email_validation_1.validateEmail)('test@example');
|
|
74
|
+
expect(result.isValid).toBe(false);
|
|
75
|
+
expect(result.error).toBe('Email inválido');
|
|
76
|
+
});
|
|
77
|
+
it('should reject email with spaces', () => {
|
|
78
|
+
const result = (0, email_validation_1.validateEmail)('test @example.com');
|
|
79
|
+
expect(result.isValid).toBe(false);
|
|
80
|
+
expect(result.error).toBe('Email inválido');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
describe('normalizeEmail', () => {
|
|
85
|
+
it('should convert to lowercase', () => {
|
|
86
|
+
expect((0, email_validation_1.normalizeEmail)('TEST@EXAMPLE.COM')).toBe('test@example.com');
|
|
87
|
+
});
|
|
88
|
+
it('should trim whitespace', () => {
|
|
89
|
+
expect((0, email_validation_1.normalizeEmail)(' test@example.com ')).toBe('test@example.com');
|
|
90
|
+
});
|
|
91
|
+
it('should handle mixed case', () => {
|
|
92
|
+
expect((0, email_validation_1.normalizeEmail)('Test@Example.Com')).toBe('test@example.com');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('EMAIL_PATTERN', () => {
|
|
96
|
+
it('should match valid email', () => {
|
|
97
|
+
expect(email_validation_1.EMAIL_PATTERN.test('test@example.com')).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
it('should not match invalid email', () => {
|
|
100
|
+
expect(email_validation_1.EMAIL_PATTERN.test('invalid')).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const phone_validation_1 = require("../phone.validation");
|
|
4
|
+
describe('validatePhone', () => {
|
|
5
|
+
describe('valid phones', () => {
|
|
6
|
+
it('should accept valid 10-digit phone', () => {
|
|
7
|
+
const result = (0, phone_validation_1.validatePhone)('9991234567');
|
|
8
|
+
expect(result.isValid).toBe(true);
|
|
9
|
+
expect(result.error).toBeUndefined();
|
|
10
|
+
});
|
|
11
|
+
it('should accept phone with whitespace (trimmed)', () => {
|
|
12
|
+
const result = (0, phone_validation_1.validatePhone)(' 9991234567 ');
|
|
13
|
+
expect(result.isValid).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
it('should accept undefined (phone is optional)', () => {
|
|
16
|
+
const result = (0, phone_validation_1.validatePhone)(undefined);
|
|
17
|
+
expect(result.isValid).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
it('should accept null (phone is optional)', () => {
|
|
20
|
+
const result = (0, phone_validation_1.validatePhone)(null);
|
|
21
|
+
expect(result.isValid).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
it('should accept empty string (phone is optional)', () => {
|
|
24
|
+
const result = (0, phone_validation_1.validatePhone)('');
|
|
25
|
+
expect(result.isValid).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
it('should accept whitespace only (phone is optional)', () => {
|
|
28
|
+
const result = (0, phone_validation_1.validatePhone)(' ');
|
|
29
|
+
expect(result.isValid).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe('invalid phones', () => {
|
|
33
|
+
it('should reject phone with less than 10 digits', () => {
|
|
34
|
+
const result = (0, phone_validation_1.validatePhone)('999123456');
|
|
35
|
+
expect(result.isValid).toBe(false);
|
|
36
|
+
expect(result.error).toContain('10 dígitos');
|
|
37
|
+
});
|
|
38
|
+
it('should reject phone with more than 10 digits', () => {
|
|
39
|
+
const result = (0, phone_validation_1.validatePhone)('99912345678');
|
|
40
|
+
expect(result.isValid).toBe(false);
|
|
41
|
+
expect(result.error).toContain('10 dígitos');
|
|
42
|
+
});
|
|
43
|
+
it('should reject phone with letters', () => {
|
|
44
|
+
const result = (0, phone_validation_1.validatePhone)('999123456a');
|
|
45
|
+
expect(result.isValid).toBe(false);
|
|
46
|
+
expect(result.error).toContain('10 dígitos');
|
|
47
|
+
});
|
|
48
|
+
it('should reject phone with special characters', () => {
|
|
49
|
+
const result = (0, phone_validation_1.validatePhone)('999-123-4567');
|
|
50
|
+
expect(result.isValid).toBe(false);
|
|
51
|
+
expect(result.error).toContain('10 dígitos');
|
|
52
|
+
});
|
|
53
|
+
it('should reject phone with spaces inside', () => {
|
|
54
|
+
const result = (0, phone_validation_1.validatePhone)('999 123 4567');
|
|
55
|
+
expect(result.isValid).toBe(false);
|
|
56
|
+
expect(result.error).toContain('10 dígitos');
|
|
57
|
+
});
|
|
58
|
+
it('should reject phone with parentheses', () => {
|
|
59
|
+
const result = (0, phone_validation_1.validatePhone)('(999)1234567');
|
|
60
|
+
expect(result.isValid).toBe(false);
|
|
61
|
+
expect(result.error).toContain('10 dígitos');
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('PHONE_PATTERN', () => {
|
|
66
|
+
it('should match valid 10-digit phone', () => {
|
|
67
|
+
expect(phone_validation_1.PHONE_PATTERN.test('9991234567')).toBe(true);
|
|
68
|
+
});
|
|
69
|
+
it('should not match invalid phone', () => {
|
|
70
|
+
expect(phone_validation_1.PHONE_PATTERN.test('999-123-4567')).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
it('should not match phone with less than 10 digits', () => {
|
|
73
|
+
expect(phone_validation_1.PHONE_PATTERN.test('999123456')).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const rfc_validation_1 = require("../rfc.validation");
|
|
4
|
+
describe('validateRFC', () => {
|
|
5
|
+
describe('valid RFCs', () => {
|
|
6
|
+
it('should accept valid RFC persona moral (12 chars)', () => {
|
|
7
|
+
const result = (0, rfc_validation_1.validateRFC)('HVP850101AB1');
|
|
8
|
+
expect(result.isValid).toBe(true);
|
|
9
|
+
expect(result.error).toBeUndefined();
|
|
10
|
+
});
|
|
11
|
+
it('should accept valid RFC persona física (13 chars)', () => {
|
|
12
|
+
const result = (0, rfc_validation_1.validateRFC)('GARC850101AB1');
|
|
13
|
+
expect(result.isValid).toBe(true);
|
|
14
|
+
expect(result.error).toBeUndefined();
|
|
15
|
+
});
|
|
16
|
+
it('should accept RFC with Ñ', () => {
|
|
17
|
+
const result = (0, rfc_validation_1.validateRFC)('MÑO850101AB1');
|
|
18
|
+
expect(result.isValid).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
it('should accept RFC with &', () => {
|
|
21
|
+
const result = (0, rfc_validation_1.validateRFC)('M&O850101AB1');
|
|
22
|
+
expect(result.isValid).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it('should accept lowercase RFC (normalized)', () => {
|
|
25
|
+
const result = (0, rfc_validation_1.validateRFC)('hvp850101ab1');
|
|
26
|
+
expect(result.isValid).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
it('should accept RFC with whitespace (trimmed)', () => {
|
|
29
|
+
const result = (0, rfc_validation_1.validateRFC)(' HVP850101AB1 ');
|
|
30
|
+
expect(result.isValid).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('invalid RFCs', () => {
|
|
34
|
+
it('should reject empty string', () => {
|
|
35
|
+
const result = (0, rfc_validation_1.validateRFC)('');
|
|
36
|
+
expect(result.isValid).toBe(false);
|
|
37
|
+
expect(result.error).toBe('RFC es requerido');
|
|
38
|
+
});
|
|
39
|
+
it('should reject null', () => {
|
|
40
|
+
const result = (0, rfc_validation_1.validateRFC)(null);
|
|
41
|
+
expect(result.isValid).toBe(false);
|
|
42
|
+
expect(result.error).toBe('RFC es requerido');
|
|
43
|
+
});
|
|
44
|
+
it('should reject undefined', () => {
|
|
45
|
+
const result = (0, rfc_validation_1.validateRFC)(undefined);
|
|
46
|
+
expect(result.isValid).toBe(false);
|
|
47
|
+
expect(result.error).toBe('RFC es requerido');
|
|
48
|
+
});
|
|
49
|
+
it('should reject whitespace only', () => {
|
|
50
|
+
const result = (0, rfc_validation_1.validateRFC)(' ');
|
|
51
|
+
expect(result.isValid).toBe(false);
|
|
52
|
+
expect(result.error).toBe('RFC es requerido');
|
|
53
|
+
});
|
|
54
|
+
it('should reject RFC too short', () => {
|
|
55
|
+
const result = (0, rfc_validation_1.validateRFC)('HVP850101');
|
|
56
|
+
expect(result.isValid).toBe(false);
|
|
57
|
+
expect(result.error).toContain('RFC inválido');
|
|
58
|
+
});
|
|
59
|
+
it('should reject RFC too long', () => {
|
|
60
|
+
const result = (0, rfc_validation_1.validateRFC)('GARC850101AB1X');
|
|
61
|
+
expect(result.isValid).toBe(false);
|
|
62
|
+
expect(result.error).toContain('RFC inválido');
|
|
63
|
+
});
|
|
64
|
+
it('should reject RFC with invalid characters', () => {
|
|
65
|
+
const result = (0, rfc_validation_1.validateRFC)('HVP-850101AB1');
|
|
66
|
+
expect(result.isValid).toBe(false);
|
|
67
|
+
expect(result.error).toContain('RFC inválido');
|
|
68
|
+
});
|
|
69
|
+
it('should reject RFC with wrong format', () => {
|
|
70
|
+
const result = (0, rfc_validation_1.validateRFC)('123456789012');
|
|
71
|
+
expect(result.isValid).toBe(false);
|
|
72
|
+
expect(result.error).toContain('RFC inválido');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('normalizeRFC', () => {
|
|
77
|
+
it('should convert to uppercase', () => {
|
|
78
|
+
expect((0, rfc_validation_1.normalizeRFC)('hvp850101ab1')).toBe('HVP850101AB1');
|
|
79
|
+
});
|
|
80
|
+
it('should trim whitespace', () => {
|
|
81
|
+
expect((0, rfc_validation_1.normalizeRFC)(' HVP850101AB1 ')).toBe('HVP850101AB1');
|
|
82
|
+
});
|
|
83
|
+
it('should handle mixed case', () => {
|
|
84
|
+
expect((0, rfc_validation_1.normalizeRFC)('HvP850101Ab1')).toBe('HVP850101AB1');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
describe('RFC_PATTERN', () => {
|
|
88
|
+
it('should match valid RFC persona moral', () => {
|
|
89
|
+
expect(rfc_validation_1.RFC_PATTERN.test('HVP850101AB1')).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
it('should match valid RFC persona física', () => {
|
|
92
|
+
expect(rfc_validation_1.RFC_PATTERN.test('GARC850101AB1')).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
it('should not match invalid RFC', () => {
|
|
95
|
+
expect(rfc_validation_1.RFC_PATTERN.test('INVALID')).toBe(false);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ValidationResult } from './rfc.validation';
|
|
2
|
+
import { MexicanStateCode } from '../constants/mexican-states';
|
|
3
|
+
/**
|
|
4
|
+
* Props for address validation
|
|
5
|
+
*/
|
|
6
|
+
export interface AddressValidationProps {
|
|
7
|
+
street: string;
|
|
8
|
+
exteriorNumber: string;
|
|
9
|
+
interiorNumber?: string;
|
|
10
|
+
neighborhood: string;
|
|
11
|
+
city: string;
|
|
12
|
+
state: MexicanStateCode;
|
|
13
|
+
zipCode: string;
|
|
14
|
+
country: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Validates address fields
|
|
18
|
+
*
|
|
19
|
+
* @param props - Address properties to validate
|
|
20
|
+
* @returns ValidationResult with isValid flag and optional error message
|
|
21
|
+
*/
|
|
22
|
+
export declare function validateAddress(props: Partial<AddressValidationProps>): ValidationResult;
|
|
23
|
+
/**
|
|
24
|
+
* Regex pattern for postal code validation (5 digits)
|
|
25
|
+
* Can be used directly in form libraries that accept regex
|
|
26
|
+
*/
|
|
27
|
+
export declare const POSTAL_CODE_PATTERN: RegExp;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.POSTAL_CODE_PATTERN = void 0;
|
|
4
|
+
exports.validateAddress = validateAddress;
|
|
5
|
+
const mexican_states_1 = require("../constants/mexican-states");
|
|
6
|
+
/**
|
|
7
|
+
* Validates address fields
|
|
8
|
+
*
|
|
9
|
+
* @param props - Address properties to validate
|
|
10
|
+
* @returns ValidationResult with isValid flag and optional error message
|
|
11
|
+
*/
|
|
12
|
+
function validateAddress(props) {
|
|
13
|
+
if (!props.street?.trim()) {
|
|
14
|
+
return { isValid: false, error: 'Calle es requerida' };
|
|
15
|
+
}
|
|
16
|
+
if (!props.exteriorNumber?.trim()) {
|
|
17
|
+
return { isValid: false, error: 'Número exterior es requerido' };
|
|
18
|
+
}
|
|
19
|
+
if (!props.neighborhood?.trim()) {
|
|
20
|
+
return { isValid: false, error: 'Colonia es requerida' };
|
|
21
|
+
}
|
|
22
|
+
if (!props.city?.trim()) {
|
|
23
|
+
return { isValid: false, error: 'Ciudad es requerida' };
|
|
24
|
+
}
|
|
25
|
+
if (!props.zipCode?.trim()) {
|
|
26
|
+
return { isValid: false, error: 'Código postal es requerido' };
|
|
27
|
+
}
|
|
28
|
+
if (!/^\d{5}$/.test(props.zipCode.trim())) {
|
|
29
|
+
return { isValid: false, error: 'Código postal inválido. Debe tener 5 dígitos' };
|
|
30
|
+
}
|
|
31
|
+
if (!props.state) {
|
|
32
|
+
return { isValid: false, error: 'Estado es requerido' };
|
|
33
|
+
}
|
|
34
|
+
// Check if state is valid
|
|
35
|
+
if (!(props.state in mexican_states_1.MEXICAN_STATES)) {
|
|
36
|
+
return { isValid: false, error: 'Código de estado inválido' };
|
|
37
|
+
}
|
|
38
|
+
if (!props.country?.trim()) {
|
|
39
|
+
return { isValid: false, error: 'País es requerido' };
|
|
40
|
+
}
|
|
41
|
+
const normalizedCountry = props.country.toLowerCase().trim();
|
|
42
|
+
if (normalizedCountry !== 'méxico' && normalizedCountry !== 'mexico') {
|
|
43
|
+
return { isValid: false, error: 'Solo se soporta México como país' };
|
|
44
|
+
}
|
|
45
|
+
return { isValid: true };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Regex pattern for postal code validation (5 digits)
|
|
49
|
+
* Can be used directly in form libraries that accept regex
|
|
50
|
+
*/
|
|
51
|
+
exports.POSTAL_CODE_PATTERN = /^\d{5}$/;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ValidationResult } from './rfc.validation';
|
|
2
|
+
/**
|
|
3
|
+
* Validates email format
|
|
4
|
+
*
|
|
5
|
+
* @param value - Email to validate
|
|
6
|
+
* @returns ValidationResult with isValid flag and optional error message
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateEmail(value: string | null | undefined): ValidationResult;
|
|
9
|
+
/**
|
|
10
|
+
* Normalizes email to lowercase and trimmed
|
|
11
|
+
*
|
|
12
|
+
* @param value - Email to normalize
|
|
13
|
+
* @returns Normalized email
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeEmail(value: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Regex pattern for email validation
|
|
18
|
+
* Can be used directly in form libraries that accept regex
|
|
19
|
+
*/
|
|
20
|
+
export declare const EMAIL_PATTERN: RegExp;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EMAIL_PATTERN = void 0;
|
|
4
|
+
exports.validateEmail = validateEmail;
|
|
5
|
+
exports.normalizeEmail = normalizeEmail;
|
|
6
|
+
/**
|
|
7
|
+
* Validates email format
|
|
8
|
+
*
|
|
9
|
+
* @param value - Email to validate
|
|
10
|
+
* @returns ValidationResult with isValid flag and optional error message
|
|
11
|
+
*/
|
|
12
|
+
function validateEmail(value) {
|
|
13
|
+
if (!value || !value.trim()) {
|
|
14
|
+
return { isValid: false, error: 'Email es requerido' };
|
|
15
|
+
}
|
|
16
|
+
const normalized = value.toLowerCase().trim();
|
|
17
|
+
// Basic email pattern
|
|
18
|
+
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
19
|
+
if (!emailPattern.test(normalized)) {
|
|
20
|
+
return { isValid: false, error: 'Email inválido' };
|
|
21
|
+
}
|
|
22
|
+
return { isValid: true };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Normalizes email to lowercase and trimmed
|
|
26
|
+
*
|
|
27
|
+
* @param value - Email to normalize
|
|
28
|
+
* @returns Normalized email
|
|
29
|
+
*/
|
|
30
|
+
function normalizeEmail(value) {
|
|
31
|
+
return value.toLowerCase().trim();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Regex pattern for email validation
|
|
35
|
+
* Can be used directly in form libraries that accept regex
|
|
36
|
+
*/
|
|
37
|
+
exports.EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Validation Functions
|
|
4
|
+
* Pure, stateless validation logic shared between frontend and backend
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
__exportStar(require("./rfc.validation"), exports);
|
|
22
|
+
__exportStar(require("./email.validation"), exports);
|
|
23
|
+
__exportStar(require("./phone.validation"), exports);
|
|
24
|
+
__exportStar(require("./address.validation"), exports);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ValidationResult } from './rfc.validation';
|
|
2
|
+
/**
|
|
3
|
+
* Validates Mexican phone number format
|
|
4
|
+
* Phone is optional - undefined/null/empty string are valid
|
|
5
|
+
*
|
|
6
|
+
* @param value - Phone to validate
|
|
7
|
+
* @returns ValidationResult with isValid flag and optional error message
|
|
8
|
+
*/
|
|
9
|
+
export declare function validatePhone(value: string | null | undefined): ValidationResult;
|
|
10
|
+
/**
|
|
11
|
+
* Regex pattern for phone validation (10 digits)
|
|
12
|
+
* Can be used directly in form libraries that accept regex
|
|
13
|
+
*/
|
|
14
|
+
export declare const PHONE_PATTERN: RegExp;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PHONE_PATTERN = void 0;
|
|
4
|
+
exports.validatePhone = validatePhone;
|
|
5
|
+
/**
|
|
6
|
+
* Validates Mexican phone number format
|
|
7
|
+
* Phone is optional - undefined/null/empty string are valid
|
|
8
|
+
*
|
|
9
|
+
* @param value - Phone to validate
|
|
10
|
+
* @returns ValidationResult with isValid flag and optional error message
|
|
11
|
+
*/
|
|
12
|
+
function validatePhone(value) {
|
|
13
|
+
// Phone is optional, undefined/null is valid
|
|
14
|
+
if (value === undefined || value === null) {
|
|
15
|
+
return { isValid: true };
|
|
16
|
+
}
|
|
17
|
+
const trimmed = value.trim();
|
|
18
|
+
// Empty string is also valid (optional field)
|
|
19
|
+
if (trimmed === '') {
|
|
20
|
+
return { isValid: true };
|
|
21
|
+
}
|
|
22
|
+
// Mexican phone: 10 digits
|
|
23
|
+
const phonePattern = /^\d{10}$/;
|
|
24
|
+
if (!phonePattern.test(trimmed)) {
|
|
25
|
+
return { isValid: false, error: 'Teléfono inválido. Debe tener 10 dígitos' };
|
|
26
|
+
}
|
|
27
|
+
return { isValid: true };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Regex pattern for phone validation (10 digits)
|
|
31
|
+
* Can be used directly in form libraries that accept regex
|
|
32
|
+
*/
|
|
33
|
+
exports.PHONE_PATTERN = /^\d{10}$/;
|